]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/font.cpp
//... => /* ... */
[wxWidgets.git] / src / gtk / font.cpp
CommitLineData
c801d85f
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: font.cpp
3// Purpose:
4// Author: Robert Roebling
a81258be 5// Id: $Id$
c801d85f 6// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem
8bbe427f 7// Licence: wxWindows licence
c801d85f
KB
8/////////////////////////////////////////////////////////////////////////////
9
10#ifdef __GNUG__
11#pragma implementation "font.h"
12#endif
13
14#include "wx/font.h"
15#include "wx/utils.h"
5705323e 16#include "wx/log.h"
4cb122de 17#include "wx/gdicmn.h"
8636aed8 18#include "wx/tokenzr.h"
c801d85f
KB
19#include <strings.h>
20
83624f79
RR
21#include "gdk/gdk.h"
22
c801d85f
KB
23//-----------------------------------------------------------------------------
24// local data
25//-----------------------------------------------------------------------------
26
36b3b54a 27/*
a3622daa 28extern wxFontNameDirectory *wxTheFontNameDirectory;
36b3b54a 29*/
c801d85f
KB
30
31//-----------------------------------------------------------------------------
32// wxFont
33//-----------------------------------------------------------------------------
34
35class wxFontRefData: public wxObjectRefData
36{
8bbe427f
VZ
37public:
38
39 wxFontRefData();
358fc25c 40 wxFontRefData( const wxFontRefData& data );
8bbe427f
VZ
41 ~wxFontRefData();
42
358fc25c
RR
43 wxList m_scaled_xfonts;
44 int m_pointSize;
45 int m_family, m_style, m_weight;
46 bool m_underlined;
358fc25c 47 wxString m_faceName;
8bbe427f 48
358fc25c
RR
49 bool m_byXFontName;
50 GdkFont *m_font;
8bbe427f 51
c801d85f
KB
52 friend wxFont;
53};
54
8bbe427f
VZ
55wxFontRefData::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;
8bbe427f
VZ
63 m_font = (GdkFont *) NULL;
64}
65
358fc25c
RR
66wxFontRefData::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;
358fc25c
RR
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
8bbe427f
VZ
79wxFontRefData::~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 }
8bbe427f 89 if (m_font) gdk_font_unref( m_font );
ff7b1510 90}
c801d85f
KB
91
92//-----------------------------------------------------------------------------
93
94#define M_FONTDATA ((wxFontRefData *)m_refData)
95
96IMPLEMENT_DYNAMIC_CLASS(wxFont, wxGDIObject)
97
8bbe427f 98wxFont::wxFont()
c801d85f 99{
8bbe427f 100 if (wxTheFontList) wxTheFontList->Append( this );
ff7b1510 101}
c801d85f 102
8636aed8 103wxFont::wxFont( GdkFont *font, char *xFontName )
c801d85f 104{
8bbe427f
VZ
105 if (!xFontName) return;
106
107 m_refData = new wxFontRefData();
108
8636aed8
RR
109// M_FONTDATA->m_byXFontName = TRUE;
110 M_FONTDATA->m_font = font;
284b4c88 111
8636aed8 112 wxString tmp;
284b4c88 113
8636aed8
RR
114 wxString fontname( xFontName );
115 wxStringTokenizer tn( fontname, _T("-") );
284b4c88 116
8636aed8 117 tn.GetNextToken(); // foundry
284b4c88 118
8636aed8
RR
119 M_FONTDATA->m_faceName = tn.GetNextToken(); // courier
120
121 tmp = tn.GetNextToken().MakeUpper();
122 if (tmp == _T("BOLD")) M_FONTDATA->m_weight = wxBOLD;
284b4c88 123
8636aed8
RR
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;
284b4c88 127
8636aed8
RR
128 tn.GetNextToken(); // set width
129 tn.GetNextToken(); // ?
130 tn.GetNextToken(); // pixel size
284b4c88 131
8636aed8
RR
132 tmp = tn.GetNextToken(); // pointsize
133 int num = wxStrtol (tmp.c_str(), (wxChar **) NULL, 10);
134 M_FONTDATA->m_pointSize = num / 10;
284b4c88 135
8636aed8
RR
136 tn.GetNextToken(); // x-res
137 tn.GetNextToken(); // y-res
284b4c88 138
8636aed8
RR
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;
ff7b1510 146}
c801d85f 147
8fc613f1 148wxFont::wxFont( int pointSize, int family, int style, int weight, bool underlined, const wxString& face )
8bbe427f
VZ
149{
150 m_refData = new wxFontRefData();
151
284b4c88 152 if (family == wxDEFAULT)
36b3b54a 153 M_FONTDATA->m_family = wxSWISS;
8bbe427f 154 else
36b3b54a 155 M_FONTDATA->m_family = family;
284b4c88 156
36b3b54a 157 if (!face.IsEmpty()) M_FONTDATA->m_faceName = face;
8bbe427f 158
284b4c88 159 if (style == wxDEFAULT)
36b3b54a
RR
160 M_FONTDATA->m_style = wxNORMAL;
161 else
162 M_FONTDATA->m_style = style;
284b4c88
VZ
163
164 if (weight == wxDEFAULT)
36b3b54a
RR
165 M_FONTDATA->m_weight = wxNORMAL;
166 else
167 M_FONTDATA->m_weight = weight;
284b4c88
VZ
168
169 if (pointSize == wxDEFAULT)
36b3b54a
RR
170 M_FONTDATA->m_pointSize = 12;
171 else
172 M_FONTDATA->m_pointSize = pointSize;
284b4c88 173
358fc25c 174 M_FONTDATA->m_underlined = underlined;
8bbe427f
VZ
175
176 if (wxTheFontList) wxTheFontList->Append( this );
284b4c88 177
ff7b1510 178}
c801d85f 179
8bbe427f
VZ
180wxFont::wxFont( const wxFont& font )
181{
182 Ref( font );
183
184 if (wxTheFontList) wxTheFontList->Append( this );
ff7b1510 185}
c801d85f 186
8bbe427f 187wxFont::~wxFont()
c801d85f 188{
8bbe427f 189 if (wxTheFontList) wxTheFontList->DeleteObject( this );
ff7b1510 190}
c801d85f 191
8bbe427f
VZ
192wxFont& wxFont::operator = ( const wxFont& font )
193{
194 if (*this == font) return (*this);
195 Ref( font );
196 return *this;
ff7b1510 197}
c801d85f 198
f03fc89f 199bool wxFont::operator == ( const wxFont& font ) const
8bbe427f
VZ
200{
201 return m_refData == font.m_refData;
ff7b1510 202}
c801d85f 203
f03fc89f 204bool wxFont::operator != ( const wxFont& font ) const
8bbe427f
VZ
205{
206 return m_refData != font.m_refData;
ff7b1510 207}
c801d85f 208
d84eb083 209bool wxFont::Ok() const
c801d85f 210{
8bbe427f 211 return (m_refData != NULL);
ff7b1510 212}
c801d85f 213
8bbe427f 214int wxFont::GetPointSize() const
c801d85f 215{
ed9b9841 216 wxCHECK_MSG( Ok(), 0, _T("invalid font") );
8bbe427f
VZ
217
218 return M_FONTDATA->m_pointSize;
ff7b1510 219}
c801d85f 220
8bbe427f 221wxString wxFont::GetFaceName() const
c801d85f 222{
ed9b9841 223 wxCHECK_MSG( Ok(), _T(""), _T("invalid font") );
8bbe427f 224
36b3b54a 225 return M_FONTDATA->m_faceName;
ff7b1510 226}
c801d85f 227
8bbe427f 228int wxFont::GetFamily() const
c801d85f 229{
ed9b9841 230 wxCHECK_MSG( Ok(), 0, _T("invalid font") );
8bbe427f
VZ
231
232 return M_FONTDATA->m_family;
ff7b1510 233}
c801d85f 234
8bbe427f 235wxString wxFont::GetFamilyString() const
c801d85f 236{
ed9b9841 237 wxCHECK_MSG( Ok(), _T("wxDEFAULT"), _T("invalid font") );
8bbe427f
VZ
238
239 switch (M_FONTDATA->m_family)
240 {
ed9b9841
OK
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");
8bbe427f
VZ
248 }
249
e55ad60e 250 return "wxDEFAULT";
ff7b1510 251}
c801d85f 252
8bbe427f 253int wxFont::GetStyle() const
c801d85f 254{
ed9b9841 255 wxCHECK_MSG( Ok(), 0, _T("invalid font") );
d84eb083 256
8bbe427f 257 return M_FONTDATA->m_style;
ff7b1510 258}
c801d85f 259
8bbe427f 260wxString wxFont::GetStyleString() const
c801d85f 261{
ed9b9841 262 wxCHECK_MSG( Ok(), _T("wxDEFAULT"), _T("invalid font") );
8bbe427f
VZ
263
264 switch (M_FONTDATA->m_style)
265 {
ed9b9841
OK
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"));
8bbe427f 270 }
d84eb083 271
ed9b9841 272 return wxString(_T("wxDEFAULT"));
ff7b1510 273}
c801d85f 274
8bbe427f 275int wxFont::GetWeight() const
c801d85f 276{
ed9b9841 277 wxCHECK_MSG( Ok(), 0, _T("invalid font") );
8bbe427f
VZ
278
279 return M_FONTDATA->m_weight;
280}
281
282wxString wxFont::GetWeightString() const
283{
ed9b9841 284 wxCHECK_MSG( Ok(), _T("wxDEFAULT"), _T("invalid font") );
8bbe427f
VZ
285
286 switch (M_FONTDATA->m_weight)
287 {
ed9b9841
OK
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"));
8bbe427f
VZ
292 }
293
ed9b9841 294 return wxString(_T("wxDEFAULT"));
8bbe427f
VZ
295}
296
297bool wxFont::GetUnderlined() const
298{
ed9b9841 299 wxCHECK_MSG( Ok(), FALSE, _T("invalid font") );
8bbe427f
VZ
300
301 return M_FONTDATA->m_underlined;
ff7b1510 302}
c801d85f 303
358fc25c
RR
304void wxFont::Unshare()
305{
306 if (!m_refData)
307 {
284b4c88 308 m_refData = new wxFontRefData();
358fc25c
RR
309 }
310 else
311 {
284b4c88
VZ
312 wxFontRefData* ref = new wxFontRefData(*(wxFontRefData*)m_refData);
313 UnRef();
314 m_refData = ref;
358fc25c
RR
315 }
316}
317
318void wxFont::SetPointSize(int pointSize)
319{
320 Unshare();
321
322 M_FONTDATA->m_pointSize = pointSize;
323}
324
325void wxFont::SetFamily(int family)
326{
327 Unshare();
328
329 M_FONTDATA->m_family = family;
330}
331
332void wxFont::SetStyle(int style)
333{
334 Unshare();
335
336 M_FONTDATA->m_style = style;
337}
338
339void wxFont::SetWeight(int weight)
340{
341 Unshare();
342
343 M_FONTDATA->m_weight = weight;
344}
345
346void wxFont::SetFaceName(const wxString& faceName)
347{
348 Unshare();
349
350 M_FONTDATA->m_faceName = faceName;
351}
352
353void wxFont::SetUnderlined(bool underlined)
354{
355 Unshare();
356
357 M_FONTDATA->m_underlined = underlined;
358}
359
c801d85f
KB
360//-----------------------------------------------------------------------------
361// get internal representation of font
362//-----------------------------------------------------------------------------
363
284b4c88 364static GdkFont *wxLoadQueryNearestFont( int point_size, int family, int style, int weight,
36b3b54a 365 bool underlined, const wxString &facename );
c801d85f 366
36b3b54a 367GdkFont *wxFont::GetInternalFont( float scale ) const
c801d85f 368{
8bbe427f
VZ
369 if (!Ok())
370 {
ed9b9841 371 wxFAIL_MSG( _T("invalid font") );
8bbe427f
VZ
372 return (GdkFont*) NULL;
373 }
374
36b3b54a 375 /* short cut if the special X font constructor has been used */
8bbe427f
VZ
376 if (M_FONTDATA->m_byXFontName) return M_FONTDATA->m_font;
377
36b3b54a 378 long int_scale = long(scale * 100.0 + 0.5); /* key for fontlist */
8bbe427f
VZ
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 {
36b3b54a 389/*
8bbe427f
VZ
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
36b3b54a 400*/
8bbe427f 401 {
36b3b54a
RR
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 );
8bbe427f
VZ
404 }
405 M_FONTDATA->m_scaled_xfonts.Append( int_scale, (wxObject*)font );
406 }
284b4c88 407
8bbe427f 408 if (!font)
36b3b54a 409 {
ed9b9841 410 wxLogError(_T("could not load any font"));
36b3b54a 411 }
284b4c88 412
8bbe427f 413 return font;
ff7b1510 414}
c801d85f
KB
415
416//-----------------------------------------------------------------------------
417// local utilities to find a X font
418//-----------------------------------------------------------------------------
419
284b4c88
VZ
420static GdkFont*wxLoadQueryFont( int pointSize, int family, int style, int weight,
421 bool WXUNUSED(underlined), const wxString &facename )
c801d85f 422{
ed9b9841
OK
423 wxChar *xfamily = (wxChar*) NULL;
424 wxChar *xstyle = (wxChar*) NULL;
425 wxChar *xweight = (wxChar*) NULL;
284b4c88 426
36b3b54a
RR
427 switch (family)
428 {
ed9b9841
OK
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;
284b4c88
VZ
433 case wxTELETYPE: xfamily = _T("lucidatypewriter"); break;
434 case wxSCRIPT: xfamily = _T("utopia"); break;
ed9b9841 435 default: xfamily = _T("*");
36b3b54a 436 }
284b4c88 437
36b3b54a
RR
438 if (!facename.IsEmpty())
439 {
ed9b9841 440 wxSprintf( wxBuffer, _T("-*-%s-*-*-normal-*-*-*-*-*-*-*-*-*"), facename.c_str() );
dcf924a3 441 GdkFont *test = gdk_font_load( wxConvCurrent->cWX2MB(wxBuffer) );
36b3b54a 442 if (test)
284b4c88
VZ
443 {
444 gdk_font_unref( test );
445 xfamily = WXSTRINGCAST facename;
446 }
36b3b54a 447 }
284b4c88 448
36b3b54a
RR
449 switch (style)
450 {
ed9b9841
OK
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;
36b3b54a
RR
455 }
456 switch (weight)
457 {
ed9b9841 458 case wxBOLD: xweight = _T("bold"); break;
36b3b54a 459 case wxLIGHT:
ed9b9841
OK
460 case wxNORMAL: xweight = _T("medium"); break;
461 default: xweight = _T("*"); break;
36b3b54a 462 }
284b4c88 463
ed9b9841 464 wxSprintf( wxBuffer, _T("-*-%s-%s-%s-normal-*-*-%d-*-*-*-*-*-*"),
36b3b54a 465 xfamily, xweight, xstyle, pointSize);
284b4c88 466
dcf924a3 467 return gdk_font_load( wxConvCurrent->cWX2MB(wxBuffer) );
c801d85f
KB
468}
469
284b4c88
VZ
470static GdkFont *wxLoadQueryNearestFont( int point_size, int family, int style, int weight,
471 bool underlined, const wxString &facename )
c801d85f 472{
36b3b54a 473 GdkFont *font = wxLoadQueryFont( point_size, family, style, weight, underlined, facename );
c801d85f 474
284b4c88 475 if (!font)
36b3b54a
RR
476 {
477 /* search up and down by stepsize 10 */
8bbe427f
VZ
478 int max_size = point_size + 20 * (1 + (point_size/180));
479 int min_size = point_size - 20 * (1 + (point_size/180));
36b3b54a 480
8fc613f1
RR
481 int i;
482
36b3b54a 483 /* Search for smaller size (approx.) */
8fc613f1 484 for (i=point_size-10; !font && i >= 10 && i >= min_size; i -= 10)
36b3b54a
RR
485 font = wxLoadQueryFont(i, family, style, weight, underlined, facename );
486
487 /* Search for larger size (approx.) */
8fc613f1 488 for (i=point_size+10; !font && i <= max_size; i += 10)
36b3b54a
RR
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 */
8bbe427f 496 if (!font)
36b3b54a 497 font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL, underlined, facename );
c801d85f 498 }
284b4c88 499
c801d85f
KB
500 return font;
501}
502
36b3b54a
RR
503/*
504
c801d85f
KB
505//-----------------------------------------------------------------------------
506// face names and index functions
507//-----------------------------------------------------------------------------
508
509static 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",
8bbe427f 528
c801d85f
KB
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",
8bbe427f 551
c801d85f
KB
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
b1c71cd0 585 "ScreenDefaultBase", "*-times",
284b4c88 586
c801d85f
KB
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]}"
8bbe427f 595 "-normal-*-*-%d-*-*-*-*-*-*",
c801d85f
KB
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}",
c67daf87 611 (char *) NULL
c801d85f
KB
612};
613
614enum {wxWEIGHT_NORMAL, wxWEIGHT_BOLD, wxWEIGHT_LIGHT, wxNUM_WEIGHTS};
615enum {wxSTYLE_NORMAL, wxSTYLE_ITALIC, wxSTYLE_SLANT, wxNUM_STYLES};
616
617static int WCoordinate(int w)
618{
284b4c88 619 switch (w)
5705323e 620 {
8bbe427f
VZ
621 case wxBOLD: return wxWEIGHT_BOLD;
622 case wxLIGHT: return wxWEIGHT_LIGHT;
623 case wxNORMAL:
624 default: return wxWEIGHT_NORMAL;
c801d85f 625 }
ff7b1510 626};
c801d85f
KB
627
628static int SCoordinate(int s)
629{
284b4c88 630 switch (s)
5705323e 631 {
8bbe427f
VZ
632 case wxITALIC: return wxSTYLE_ITALIC;
633 case wxSLANT: return wxSTYLE_SLANT;
634 case wxNORMAL:
635 default: return wxSTYLE_NORMAL;
c801d85f 636 }
ff7b1510 637};
c801d85f
KB
638
639//-----------------------------------------------------------------------------
640// wxSuffixMap
641//-----------------------------------------------------------------------------
642
284b4c88 643class wxSuffixMap
5705323e 644{
c801d85f 645public:
8bbe427f 646 ~wxSuffixMap();
c801d85f
KB
647
648 inline char *GetName(int weight, int style)
649 {
8bbe427f 650 return ( map [WCoordinate(weight)] [SCoordinate(style)] );
c801d85f
KB
651 }
652
653 char *map[wxNUM_WEIGHTS][wxNUM_STYLES];
654 void Initialize(const char *, const char *);
655};
656
c801d85f
KB
657static 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;
8bbe427f 663
c67daf87
UR
664 *v = (char *) NULL;
665 internal = (char *) NULL;
c801d85f 666
284b4c88 667 for (i = 0; i < k; i++)
5705323e 668 {
8bbe427f 669 strcpy(resource, prefix);
284b4c88
VZ
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
8bbe427f
VZ
678 if (!(i & (1 << j)))
679 strcat(resource, names[j]);
680 else
681 strcat(resource, "_");
682 }
5705323e 683
284b4c88
VZ
684 // we previously search the Xt-resources here
685
686 if (!internal)
687 {
8bbe427f 688 defaults = font_defaults;
284b4c88
VZ
689 while (*defaults)
690 {
691 if (!strcmp(*defaults, resource))
692 {
8bbe427f
VZ
693 internal = defaults[1];
694 break;
695 }
696 defaults += 2;
697 }
698 }
c801d85f 699 }
284b4c88 700
c801d85f 701 if (internal)
5705323e 702 {
b1c71cd0 703 if ((strcmp(internal,"-${ScreenDefaultBase}${ScreenStdSuffix}") == 0) &&
284b4c88
VZ
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 {
5705323e 718 *v = copystring(internal);
284b4c88 719 }
5705323e 720 }
c801d85f
KB
721}
722
8bbe427f 723wxSuffixMap::~wxSuffixMap()
c801d85f
KB
724{
725 int k, j;
726
727 for (k = 0; k < wxNUM_WEIGHTS; ++k)
8bbe427f 728 for (j = 0; j < wxNUM_STYLES; ++j)
284b4c88
VZ
729 if (map[k][j])
730 {
8bbe427f
VZ
731 delete[] map[k][j];
732 map[k][j] = (char *) NULL;
733 }
c801d85f
KB
734}
735
736void 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
284b4c88 743 for (k = 0; k < wxNUM_WEIGHTS; k++)
5705323e 744 {
284b4c88
VZ
745 switch (k)
746 {
8bbe427f
VZ
747 case wxWEIGHT_NORMAL: weight = "Medium"; break;
748 case wxWEIGHT_LIGHT: weight = "Light"; break;
749 case wxWEIGHT_BOLD:
5705323e 750 default: weight = "Bold";
8bbe427f 751 }
284b4c88
VZ
752 for (j = 0; j < wxNUM_STYLES; j++)
753 {
754 switch (j)
755 {
8bbe427f
VZ
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);
284b4c88
VZ
766
767 // Expand macros in the found string:
8bbe427f
VZ
768found:
769 int len, closer = 0, startpos = 0;
770
771 len = (v ? strlen(v) : 0);
284b4c88
VZ
772 for (i = 0; i < len; i++)
773 {
774 if (v[i] == '$' && ((v[i+1] == '[') || (v[i+1] == '{')))
775 {
8bbe427f
VZ
776 startpos = i;
777 closer = (v[i+1] == '[') ? ']' : '}';
778 ++i;
284b4c88
VZ
779 }
780 else if (v[i] == closer)
781 {
8bbe427f
VZ
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
284b4c88
VZ
789 if (closer == '}')
790 {
8bbe427f
VZ
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++)
284b4c88
VZ
803 if (name[i] == ',')
804 {
8bbe427f
VZ
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
284b4c88
VZ
813 if (!r)
814 {
8bbe427f
VZ
815 for (i = 0; i < len; i++)
816 if (!name[i])
817 name[i] = ',';
818 r = "";
5705323e 819 wxLogError( "Bad resource name in font lookup." );
8bbe427f
VZ
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 = "";
5705323e 829 wxLogError( "Bad font macro name." );
8bbe427f
VZ
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 }
284b4c88 846 // We have a final value:
8bbe427f
VZ
847 map[k][j] = v;
848 }
c801d85f
KB
849 }
850}
851
852//-----------------------------------------------------------------------------
853// wxFontNameItem
854//-----------------------------------------------------------------------------
855
284b4c88 856class wxFontNameItem : public wxObject
358fc25c 857{
8bbe427f 858 DECLARE_DYNAMIC_CLASS(wxFontNameItem)
c801d85f 859public:
8bbe427f
VZ
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;}
ea57084d 870#if defined(__WXDEBUG__)
8bbe427f 871 void Dump(ostream& str);
c801d85f
KB
872#endif
873
8bbe427f
VZ
874 int id;
875 int family;
876 char *name;
877 wxSuffixMap screen, printing, afm;
878 bool isroman;
c801d85f
KB
879};
880
881IMPLEMENT_ABSTRACT_CLASS(wxFontNameItem, wxObject)
882
883wxFontNameItem::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
8bbe427f 894wxFontNameItem::~wxFontNameItem()
c801d85f
KB
895{
896 if (name)
8bbe427f 897 delete[] name;
c67daf87 898 name = (char *) NULL;
c801d85f
KB
899}
900
ea57084d 901#if defined(__WXDEBUG__)
c801d85f
KB
902void wxFontNameItem::Dump(ostream& str)
903{
904 str << "wxFontNameItem(" << name << ")";
905}
906#endif
907
908//-----------------------------------------------------------------------------
909// wxFontDirectory
910//-----------------------------------------------------------------------------
911
912IMPLEMENT_DYNAMIC_CLASS(wxFontNameDirectory, wxObject)
913
8bbe427f 914wxFontNameDirectory::wxFontNameDirectory()
c801d85f
KB
915{
916 table = new wxHashTable(wxKEY_INTEGER, 20);
917 nextFontId = -1;
c801d85f
KB
918}
919
920wxFontNameDirectory::~wxFontNameDirectory()
921{
922 // Cleanup wxFontNameItems allocated
923 table->BeginFind();
924 wxNode *node = table->Next();
284b4c88 925 while (node)
358fc25c 926 {
8bbe427f
VZ
927 wxFontNameItem *item = (wxFontNameItem*)node->Data();
928 delete item;
929 node = table->Next();
c801d85f
KB
930 }
931 delete table;
932}
933
8bbe427f 934int wxFontNameDirectory::GetNewFontId()
c801d85f
KB
935{
936 return (nextFontId--);
937}
938
939void 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
950void wxFontNameDirectory::Initialize(int fontid, int family, const char *resname)
951{
952 char *fam, resource[256];
8bbe427f 953
c801d85f 954 sprintf(resource, "Family%s", resname);
c67daf87 955 SearchResource((const char *)resource, (const char **) NULL, 0, (char **)&fam);
284b4c88
VZ
956
957 if (fam)
358fc25c 958 {
8bbe427f
VZ
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
c801d85f
KB
967 }
968 table->Put(fontid, new wxFontNameItem(resname, fontid, family));
969}
970
971int wxFontNameDirectory::FindOrCreateFontId(const char *name, int family)
972{
973 int id;
284b4c88 974
c801d85f
KB
975 // font exists -> return id
976 if ( (id = GetFontId(name)) ) return id;
284b4c88 977
c801d85f
KB
978 // create new font
979 Initialize(id=GetNewFontId(), family, name);
980 return id;
981}
982
983char *wxFontNameDirectory::GetScreenName(int fontid, int weight, int style)
984{
985 wxFontNameItem *item = (wxFontNameItem*)table->Get(fontid); // find font
986 if (item)
8bbe427f 987 return item->GetScreenName(weight, style);
284b4c88 988
c801d85f 989 // font does not exist
c67daf87 990 return (char *) NULL;
c801d85f
KB
991}
992
993char *wxFontNameDirectory::GetPostScriptName(int fontid, int weight, int style)
994{
995 wxFontNameItem *item = (wxFontNameItem*)table->Get(fontid); // find font
996 if (item)
8bbe427f 997 return item->GetPostScriptName(weight, style);
284b4c88 998
c801d85f 999 // font does not exist
c67daf87 1000 return (char *) NULL;
c801d85f
KB
1001}
1002
1003char *wxFontNameDirectory::GetAFMName(int fontid, int weight, int style)
1004{
1005 wxFontNameItem *item = (wxFontNameItem *)table->Get(fontid); // find font
1006 if (item)
8bbe427f 1007 return item->GetAFMName(weight, style);
c801d85f 1008 // font does not exist
c67daf87 1009 return (char *) NULL;
c801d85f
KB
1010}
1011
1012char *wxFontNameDirectory::GetFontName(int fontid)
1013{
1014 wxFontNameItem *item = (wxFontNameItem *)table->Get(fontid); // find font
1015 if (item)
8bbe427f 1016 return item->GetName();
284b4c88 1017
c801d85f 1018 // font does not exist
c67daf87 1019 return (char *) NULL;
c801d85f
KB
1020}
1021
1022int wxFontNameDirectory::GetFontId(const char *name)
1023{
1024 wxNode *node;
1025
1026 table->BeginFind();
1027
284b4c88 1028 while ( (node = table->Next()) )
358fc25c 1029 {
8bbe427f
VZ
1030 wxFontNameItem *item = (wxFontNameItem*)node->Data();
1031 if (!strcmp(name, item->name))
1032 return item->id;
c801d85f 1033 }
284b4c88 1034
c801d85f
KB
1035 // font does not exist
1036 return 0;
1037}
1038
1039int wxFontNameDirectory::GetFamily(int fontid)
1040{
1041 wxFontNameItem *item = (wxFontNameItem *)table->Get(fontid);
8bbe427f 1042
c801d85f 1043 if (item)
8bbe427f 1044 return item->family;
284b4c88 1045
c801d85f
KB
1046 // font does not exist
1047 return wxDEFAULT;
1048}
36b3b54a
RR
1049
1050*/