]> git.saurik.com Git - wxWidgets.git/blame - src/motif/font.cpp
use GetFont() instead of (possibly not initialized) m_font in GetCharWidth/Height()
[wxWidgets.git] / src / motif / font.cpp
CommitLineData
4bb6408c 1/////////////////////////////////////////////////////////////////////////////
7ecb8b06 2// Name: src/motif/font.cpp
4bb6408c
JS
3// Purpose: wxFont class
4// Author: Julian Smart
5// Modified by:
6// Created: 17/09/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
dfe1eee3 9// Licence: wxWindows licence
4bb6408c
JS
10/////////////////////////////////////////////////////////////////////////////
11
93ccaed8
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
14f355c2 20#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
93ccaed8 21 #pragma implementation "font.h"
4bb6408c
JS
22#endif
23
11334a9e
VZ
24#include "wx/defs.h"
25
338dd992
JJ
26#ifdef __VMS
27#pragma message disable nosimpint
4dff3400 28#include "wx/vms_x_fix.h"
338dd992 29#endif
79e4b627 30#include <Xm/Xm.h>
338dd992
JJ
31#ifdef __VMS
32#pragma message enable nosimpint
33#endif
79e4b627 34
4bb6408c
JS
35#include "wx/string.h"
36#include "wx/font.h"
37#include "wx/gdicmn.h"
79e4b627 38#include "wx/utils.h" // for wxGetDisplay()
98c9fc2d 39#include "wx/fontutil.h" // for wxNativeFontInfo
563f868d
GD
40#include "wx/tokenzr.h"
41#include "wx/settings.h"
da494b40 42#include "wx/motif/private.h"
4bb6408c 43
98c9fc2d 44IMPLEMENT_DYNAMIC_CLASS(wxFont, wxGDIObject)
4bb6408c 45
93ccaed8
VZ
46// ----------------------------------------------------------------------------
47// private classes
48// ----------------------------------------------------------------------------
49
50// For every wxFont, there must be a font for each display and scale requested.
51// So these objects are stored in wxFontRefData::m_fonts
79e4b627 52class wxXFont : public wxObject
93ccaed8
VZ
53{
54public:
55 wxXFont();
56 ~wxXFont();
57
58 WXFontStructPtr m_fontStruct; // XFontStruct
59 WXFontList m_fontList; // Motif XmFontList
da494b40
MB
60#if wxCHECK_MOTIF_VERSION( 2, 0 )
61 WXRenderTable m_renderTable; // Motif XmRenderTable
62#endif
93ccaed8
VZ
63 WXDisplay* m_display; // XDisplay
64 int m_scale; // Scale * 100
65};
66
67class wxFontRefData: public wxGDIRefData
68{
69friend class wxFont;
70
71public:
72 wxFontRefData(int size = wxDEFAULT,
73 int family = wxDEFAULT,
74 int style = wxDEFAULT,
75 int weight = wxDEFAULT,
76 bool underlined = FALSE,
77 const wxString& faceName = wxEmptyString,
78 wxFontEncoding encoding = wxFONTENCODING_DEFAULT)
79 {
80 Init(size, family, style, weight, underlined, faceName, encoding);
81 }
82
83 wxFontRefData(const wxFontRefData& data)
84 {
85 Init(data.m_pointSize, data.m_family, data.m_style, data.m_weight,
86 data.m_underlined, data.m_faceName, data.m_encoding);
87 }
88
89 ~wxFontRefData();
90
91protected:
92 // common part of all ctors
93 void Init(int size,
94 int family,
95 int style,
96 int weight,
97 bool underlined,
98 const wxString& faceName,
99 wxFontEncoding encoding);
100
101 // font attributes
102 int m_pointSize;
103 int m_family;
104 int m_style;
105 int m_weight;
106 bool m_underlined;
107 wxString m_faceName;
108 wxFontEncoding m_encoding;
109
563f868d 110 wxNativeFontInfo m_nativeFontInfo;
9045ad9d 111
93ccaed8
VZ
112 // A list of wxXFonts
113 wxList m_fonts;
114};
115
116// ============================================================================
117// implementation
118// ============================================================================
119
120// ----------------------------------------------------------------------------
121// wxXFont
122// ----------------------------------------------------------------------------
123
f97c9854
JS
124wxXFont::wxXFont()
125{
126 m_fontStruct = (WXFontStructPtr) 0;
127 m_fontList = (WXFontList) 0;
da494b40
MB
128#if wxCHECK_MOTIF_VERSION( 2, 0 )
129 m_renderTable = (WXRenderTable) 0;
130#endif
f97c9854
JS
131 m_display = (WXDisplay*) 0;
132 m_scale = 100;
133}
134
135wxXFont::~wxXFont()
136{
f97c9854 137 XmFontList fontList = (XmFontList) m_fontList;
f97c9854 138 XmFontListFree (fontList);
dfe1eee3 139
24f9edfd 140#if wxCHECK_MOTIF_VERSION( 2, 0 ) && !wxCHECK_LESSTIF()
da494b40
MB
141 XmRenderTable renderTable = (XmRenderTable) m_renderTable;
142 XmRenderTableFree (renderTable);
143#endif
144
2d120f83 145 // TODO: why does freeing the font produce a segv???
f97c9854 146 // Note that XFreeFont wasn't called in wxWin 1.68 either.
dfe1eee3 147 // XFontStruct* fontStruct = (XFontStruct*) m_fontStruct;
2d120f83 148 // XFreeFont((Display*) m_display, fontStruct);
f97c9854
JS
149}
150
93ccaed8
VZ
151// ----------------------------------------------------------------------------
152// wxFontRefData
153// ----------------------------------------------------------------------------
154
155void wxFontRefData::Init(int pointSize,
156 int family,
157 int style,
158 int weight,
159 bool underlined,
160 const wxString& faceName,
161 wxFontEncoding encoding)
4bb6408c 162{
93ccaed8
VZ
163 if (family == wxDEFAULT)
164 m_family = wxSWISS;
165 else
166 m_family = family;
4bb6408c 167
93ccaed8
VZ
168 m_faceName = faceName;
169
170 if (style == wxDEFAULT)
171 m_style = wxNORMAL;
172 else
173 m_style = style;
174
175 if (weight == wxDEFAULT)
176 m_weight = wxNORMAL;
177 else
178 m_weight = weight;
179
180 if (pointSize == wxDEFAULT)
181 m_pointSize = 12;
182 else
183 m_pointSize = pointSize;
184
185 m_underlined = underlined;
186 m_encoding = encoding;
4bb6408c
JS
187}
188
189wxFontRefData::~wxFontRefData()
190{
ac32ba44 191 wxList::compatibility_iterator node = m_fonts.GetFirst();
dfc54541
JS
192 while (node)
193 {
fd304d98 194 wxXFont* f = (wxXFont*) node->GetData();
f97c9854 195 delete f;
fd304d98 196 node = node->GetNext();
dfc54541 197 }
f97c9854 198 m_fonts.Clear();
4bb6408c
JS
199}
200
93ccaed8
VZ
201// ----------------------------------------------------------------------------
202// wxFont
203// ----------------------------------------------------------------------------
4bb6408c 204
ef4e8ebd 205wxFont::wxFont(const wxNativeFontInfo& info)
98c9fc2d
VZ
206{
207 Init();
208
42f30fa2 209 (void)Create(info.GetXFontName());
98c9fc2d
VZ
210}
211
93ccaed8 212void wxFont::Init()
4bb6408c 213{
4bb6408c
JS
214}
215
93ccaed8
VZ
216bool wxFont::Create(int pointSize,
217 int family,
218 int style,
219 int weight,
220 bool underlined,
221 const wxString& faceName,
222 wxFontEncoding encoding)
4bb6408c
JS
223{
224 UnRef();
93ccaed8
VZ
225 m_refData = new wxFontRefData(pointSize, family, style, weight,
226 underlined, faceName, encoding);
dfe1eee3 227
4bb6408c 228 RealizeResource();
dfe1eee3 229
4bb6408c
JS
230 return TRUE;
231}
232
563f868d
GD
233bool wxFont::Create(const wxString& fontname, wxFontEncoding enc)
234{
235 if( !fontname )
236 {
a756f210 237 *this = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT);
563f868d
GD
238 return TRUE;
239 }
240
241 m_refData = new wxFontRefData();
242
42f30fa2 243 M_FONTDATA->m_nativeFontInfo.SetXFontName(fontname); // X font name
563f868d
GD
244
245 wxString tmp;
246
247 wxStringTokenizer tn( fontname, wxT("-") );
248
249 tn.GetNextToken(); // skip initial empty token
250 tn.GetNextToken(); // foundry
251
252
253 M_FONTDATA->m_faceName = tn.GetNextToken(); // family
254
255 tmp = tn.GetNextToken().MakeUpper(); // weight
256 if (tmp == wxT("BOLD")) M_FONTDATA->m_weight = wxBOLD;
257 if (tmp == wxT("BLACK")) M_FONTDATA->m_weight = wxBOLD;
258 if (tmp == wxT("EXTRABOLD")) M_FONTDATA->m_weight = wxBOLD;
259 if (tmp == wxT("DEMIBOLD")) M_FONTDATA->m_weight = wxBOLD;
260 if (tmp == wxT("ULTRABOLD")) M_FONTDATA->m_weight = wxBOLD;
261
262 if (tmp == wxT("LIGHT")) M_FONTDATA->m_weight = wxLIGHT;
263 if (tmp == wxT("THIN")) M_FONTDATA->m_weight = wxLIGHT;
264
265 tmp = tn.GetNextToken().MakeUpper(); // slant
266 if (tmp == wxT("I")) M_FONTDATA->m_style = wxITALIC;
267 if (tmp == wxT("O")) M_FONTDATA->m_style = wxITALIC;
268
269 tn.GetNextToken(); // set width
270 tn.GetNextToken(); // add. style
271 tn.GetNextToken(); // pixel size
272
273 tmp = tn.GetNextToken(); // pointsize
274 if (tmp != wxT("*"))
275 {
276 long num = wxStrtol (tmp.c_str(), (wxChar **) NULL, 10);
277 M_FONTDATA->m_pointSize = (int)(num / 10);
278 }
279
280 tn.GetNextToken(); // x-res
281 tn.GetNextToken(); // y-res
282
283 tmp = tn.GetNextToken().MakeUpper(); // spacing
284
285 if (tmp == wxT("M"))
286 M_FONTDATA->m_family = wxMODERN;
287 else if (M_FONTDATA->m_faceName == wxT("TIMES"))
288 M_FONTDATA->m_family = wxROMAN;
289 else if (M_FONTDATA->m_faceName == wxT("HELVETICA"))
290 M_FONTDATA->m_family = wxSWISS;
291 else if (M_FONTDATA->m_faceName == wxT("LUCIDATYPEWRITER"))
292 M_FONTDATA->m_family = wxTELETYPE;
293 else if (M_FONTDATA->m_faceName == wxT("LUCIDA"))
294 M_FONTDATA->m_family = wxDECORATIVE;
295 else if (M_FONTDATA->m_faceName == wxT("UTOPIA"))
296 M_FONTDATA->m_family = wxSCRIPT;
297
298 tn.GetNextToken(); // avg width
299
300 // deal with font encoding
301 M_FONTDATA->m_encoding = enc;
302 if ( M_FONTDATA->m_encoding == wxFONTENCODING_SYSTEM )
303 {
304 wxString registry = tn.GetNextToken().MakeUpper(),
305 encoding = tn.GetNextToken().MakeUpper();
306
307 if ( registry == _T("ISO8859") )
308 {
309 int cp;
310 if ( wxSscanf(encoding, wxT("%d"), &cp) == 1 )
311 {
312 M_FONTDATA->m_encoding =
313 (wxFontEncoding)(wxFONTENCODING_ISO8859_1 + cp - 1);
314 }
315 }
316 else if ( registry == _T("MICROSOFT") )
317 {
318 int cp;
319 if ( wxSscanf(encoding, wxT("cp125%d"), &cp) == 1 )
320 {
321 M_FONTDATA->m_encoding =
322 (wxFontEncoding)(wxFONTENCODING_CP1250 + cp);
323 }
324 }
325 else if ( registry == _T("KOI8") )
326 {
327 M_FONTDATA->m_encoding = wxFONTENCODING_KOI8;
328 }
329 //else: unknown encoding - may be give a warning here?
330 else
331 return FALSE;
332 }
9045ad9d 333 return TRUE;
563f868d
GD
334}
335
4bb6408c
JS
336wxFont::~wxFont()
337{
4bb6408c
JS
338}
339
93ccaed8
VZ
340// ----------------------------------------------------------------------------
341// change the font attributes
342// ----------------------------------------------------------------------------
4bb6408c
JS
343
344void wxFont::Unshare()
345{
2d120f83
JS
346 // Don't change shared data
347 if (!m_refData)
4bb6408c 348 {
2d120f83
JS
349 m_refData = new wxFontRefData();
350 }
4bb6408c
JS
351 else
352 {
2d120f83
JS
353 wxFontRefData* ref = new wxFontRefData(*(wxFontRefData*)m_refData);
354 UnRef();
355 m_refData = ref;
356 }
4bb6408c
JS
357}
358
359void wxFont::SetPointSize(int pointSize)
360{
361 Unshare();
dfe1eee3 362
4bb6408c 363 M_FONTDATA->m_pointSize = pointSize;
42f30fa2 364 M_FONTDATA->m_nativeFontInfo.GetXFontName().Clear(); // invalid now
9045ad9d 365
4bb6408c
JS
366 RealizeResource();
367}
368
369void wxFont::SetFamily(int family)
370{
371 Unshare();
dfe1eee3 372
4bb6408c 373 M_FONTDATA->m_family = family;
42f30fa2 374 M_FONTDATA->m_nativeFontInfo.GetXFontName().Clear(); // invalid now
9045ad9d 375
4bb6408c
JS
376 RealizeResource();
377}
378
379void wxFont::SetStyle(int style)
380{
381 Unshare();
dfe1eee3 382
4bb6408c 383 M_FONTDATA->m_style = style;
42f30fa2 384 M_FONTDATA->m_nativeFontInfo.GetXFontName().Clear(); // invalid now
9045ad9d 385
4bb6408c
JS
386 RealizeResource();
387}
388
389void wxFont::SetWeight(int weight)
390{
391 Unshare();
dfe1eee3 392
4bb6408c 393 M_FONTDATA->m_weight = weight;
42f30fa2 394 M_FONTDATA->m_nativeFontInfo.GetXFontName().Clear(); // invalid now
9045ad9d 395
4bb6408c
JS
396 RealizeResource();
397}
398
399void wxFont::SetFaceName(const wxString& faceName)
400{
401 Unshare();
dfe1eee3 402
4bb6408c 403 M_FONTDATA->m_faceName = faceName;
42f30fa2 404 M_FONTDATA->m_nativeFontInfo.GetXFontName().Clear(); // invalid now
9045ad9d 405
4bb6408c
JS
406 RealizeResource();
407}
408
409void wxFont::SetUnderlined(bool underlined)
410{
411 Unshare();
dfe1eee3 412
4bb6408c 413 M_FONTDATA->m_underlined = underlined;
9045ad9d 414
4bb6408c
JS
415 RealizeResource();
416}
417
93ccaed8 418void wxFont::SetEncoding(wxFontEncoding encoding)
4bb6408c 419{
93ccaed8
VZ
420 Unshare();
421
422 M_FONTDATA->m_encoding = encoding;
42f30fa2 423 M_FONTDATA->m_nativeFontInfo.GetXFontName().Clear(); // invalid now
9045ad9d 424
93ccaed8
VZ
425 RealizeResource();
426}
427
9045ad9d 428void wxFont::DoSetNativeFontInfo(const wxNativeFontInfo& info)
563f868d
GD
429{
430 Unshare();
431
432 M_FONTDATA->m_nativeFontInfo = info;
433}
434
93ccaed8
VZ
435// ----------------------------------------------------------------------------
436// query font attributes
437// ----------------------------------------------------------------------------
438
439int wxFont::GetPointSize() const
440{
563f868d 441 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
9045ad9d 442
93ccaed8
VZ
443 return M_FONTDATA->m_pointSize;
444}
445
563f868d
GD
446wxString wxFont::GetFaceName() const
447{
448 wxCHECK_MSG( Ok(), wxT(""), wxT("invalid font") );
449
450 return M_FONTDATA->m_faceName ;
451}
452
93ccaed8
VZ
453int wxFont::GetFamily() const
454{
563f868d
GD
455 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
456
93ccaed8
VZ
457 return M_FONTDATA->m_family;
458}
459
460int wxFont::GetStyle() const
461{
563f868d
GD
462 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
463
93ccaed8
VZ
464 return M_FONTDATA->m_style;
465}
466
467int wxFont::GetWeight() const
468{
563f868d
GD
469 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
470
93ccaed8
VZ
471 return M_FONTDATA->m_weight;
472}
473
474bool wxFont::GetUnderlined() const
475{
563f868d
GD
476 wxCHECK_MSG( Ok(), FALSE, wxT("invalid font") );
477
93ccaed8 478 return M_FONTDATA->m_underlined;
4bb6408c
JS
479}
480
563f868d 481wxFontEncoding wxFont::GetEncoding() const
4bb6408c 482{
563f868d
GD
483 wxCHECK_MSG( Ok(), wxFONTENCODING_DEFAULT, wxT("invalid font") );
484
485 return M_FONTDATA->m_encoding;
4bb6408c
JS
486}
487
3bf5a59b 488const wxNativeFontInfo *wxFont::GetNativeFontInfo() const
4bb6408c 489{
563f868d
GD
490 wxCHECK_MSG( Ok(), (wxNativeFontInfo *)NULL, wxT("invalid font") );
491
42f30fa2 492 if(M_FONTDATA->m_nativeFontInfo.GetXFontName().IsEmpty())
563f868d
GD
493 GetInternalFont();
494
3bf5a59b 495 return &(M_FONTDATA->m_nativeFontInfo);
4bb6408c
JS
496}
497
93ccaed8
VZ
498// ----------------------------------------------------------------------------
499// real implementation
500// ----------------------------------------------------------------------------
4bb6408c 501
dfc54541
JS
502// Find an existing, or create a new, XFontStruct
503// based on this wxFont and the given scale. Append the
504// font to list in the private data for future reference.
f97c9854 505wxXFont* wxFont::GetInternalFont(double scale, WXDisplay* display) const
dfc54541 506{
93ccaed8
VZ
507 if ( !Ok() )
508 return (wxXFont *)NULL;
dfe1eee3 509
2d120f83
JS
510 long intScale = long(scale * 100.0 + 0.5); // key for wxXFont
511 int pointSize = (M_FONTDATA->m_pointSize * 10 * intScale) / 100;
dfe1eee3 512
93ccaed8 513 // search existing fonts first
ac32ba44 514 wxList::compatibility_iterator node = M_FONTDATA->m_fonts.GetFirst();
2d120f83
JS
515 while (node)
516 {
fd304d98 517 wxXFont* f = (wxXFont*) node->GetData();
2d120f83
JS
518 if ((!display || (f->m_display == display)) && (f->m_scale == intScale))
519 return f;
fd304d98 520 node = node->GetNext();
2d120f83 521 }
dfe1eee3 522
93ccaed8 523 // not found, create a new one
0d083705
VZ
524 XFontStruct *font = (XFontStruct *)
525 wxLoadQueryNearestFont(pointSize,
93ccaed8
VZ
526 M_FONTDATA->m_family,
527 M_FONTDATA->m_style,
528 M_FONTDATA->m_weight,
529 M_FONTDATA->m_underlined,
223d09f6 530 wxT(""),
93ccaed8 531 M_FONTDATA->m_encoding);
dfe1eee3 532
93ccaed8 533 if ( !font )
2d120f83 534 {
223d09f6 535 wxFAIL_MSG( wxT("Could not allocate even a default font -- something is wrong.") );
93ccaed8
VZ
536
537 return (wxXFont*) NULL;
2d120f83 538 }
93ccaed8
VZ
539
540 wxXFont* f = new wxXFont;
541 f->m_fontStruct = (WXFontStructPtr)font;
542 f->m_display = ( display ? display : wxGetDisplay() );
543 f->m_scale = intScale;
544 f->m_fontList = XmFontListCreate ((XFontStruct*) font, XmSTRING_DEFAULT_CHARSET);
545 M_FONTDATA->m_fonts.Append(f);
546
da494b40
MB
547#if wxCHECK_MOTIF_VERSION( 2, 0 ) && !wxCHECK_LESSTIF()
548 XmRendition rendition;
549 XmRenderTable renderTable;
550 Arg args[5];
551 int count = 0;
552
553 XtSetArg( args[count], XmNfont, font ); ++count;
554 XtSetArg( args[count], XmNunderlineType,
555 GetUnderlined() ? XmSINGLE_LINE : XmNO_LINE ); ++count;
556 rendition = XmRenditionCreate( XmGetXmDisplay( (Display*)f->m_display ),
557 (XmStringTag)"",
558 args, count );
559 renderTable = XmRenderTableAddRenditions( NULL, &rendition, 1,
560 XmMERGE_REPLACE );
561
562 f->m_renderTable = (WXRenderTable)renderTable;
563#endif
564
93ccaed8 565 return f;
dfc54541
JS
566}
567
93ccaed8 568WXFontStructPtr wxFont::GetFontStruct(double scale, WXDisplay* display) const
dfc54541 569{
93ccaed8 570 wxXFont* f = GetInternalFont(scale, display);
dfe1eee3 571
93ccaed8
VZ
572 return (f ? f->m_fontStruct : (WXFontStructPtr) 0);
573}
dfe1eee3 574
93ccaed8
VZ
575WXFontList wxFont::GetFontList(double scale, WXDisplay* display) const
576{
577 wxXFont* f = GetInternalFont(scale, display);
dfe1eee3 578
93ccaed8 579 return (f ? f->m_fontList : (WXFontList) 0);
dfc54541 580}
7ecb8b06 581
da494b40
MB
582#if wxCHECK_MOTIF_VERSION( 2, 0 )
583
584WXRenderTable wxFont::GetRenderTable(WXDisplay* display) const
585{
586 wxXFont* f = GetInternalFont(1.0, display);
587
588 return (f ? f->m_renderTable : (WXFontList) 0);
589}
590
591#endif
592
593WXFontType wxFont::GetFontType(WXDisplay* display) const
594{
595#if wxCHECK_MOTIF_VERSION( 2, 0 ) && !wxCHECK_LESSTIF()
596 return Ok() ? GetRenderTable(display) : NULL;
597#else
598 return Ok() ? GetFontList(1.0, display) : NULL;
599#endif
600}
601
602/*static*/ WXString wxFont::GetFontTag()
603{
604#if wxCHECK_MOTIF_VERSION( 2, 0 ) && !wxCHECK_LESSTIF()
605 return (WXString)XmNrenderTable;
606#else
607 return (WXString)XmNfontList;
608#endif
609}