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