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