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