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