implemented native font stuff for wxMotif
[wxWidgets.git] / src / motif / font.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/motif/font.cpp
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
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "font.h"
22 #endif
23
24 #ifdef __VMS
25 #pragma message disable nosimpint
26 #include "wx/vms_x_fix.h"
27 #endif
28 #include <Xm/Xm.h>
29 #ifdef __VMS
30 #pragma message enable nosimpint
31 #endif
32
33 #include "wx/defs.h"
34 #include "wx/string.h"
35 #include "wx/font.h"
36 #include "wx/gdicmn.h"
37 #include "wx/utils.h" // for wxGetDisplay()
38 #include "wx/fontutil.h" // for wxNativeFontInfo
39 #include "wx/tokenzr.h"
40 #include "wx/settings.h"
41
42 IMPLEMENT_DYNAMIC_CLASS(wxFont, wxGDIObject)
43
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
50 class wxXFont : public wxObject
51 {
52 public:
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
62 class wxFontRefData: public wxGDIRefData
63 {
64 friend class wxFont;
65
66 public:
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
86 protected:
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
105 wxNativeFontInfo m_nativeFontInfo;
106
107 // A list of wxXFonts
108 wxList m_fonts;
109 };
110
111 // ============================================================================
112 // implementation
113 // ============================================================================
114
115 // ----------------------------------------------------------------------------
116 // wxXFont
117 // ----------------------------------------------------------------------------
118
119 wxXFont::wxXFont()
120 {
121 m_fontStruct = (WXFontStructPtr) 0;
122 m_fontList = (WXFontList) 0;
123 m_display = (WXDisplay*) 0;
124 m_scale = 100;
125 }
126
127 wxXFont::~wxXFont()
128 {
129 XmFontList fontList = (XmFontList) m_fontList;
130
131 XmFontListFree (fontList);
132
133 // TODO: why does freeing the font produce a segv???
134 // Note that XFreeFont wasn't called in wxWin 1.68 either.
135 // XFontStruct* fontStruct = (XFontStruct*) m_fontStruct;
136 // XFreeFont((Display*) m_display, fontStruct);
137 }
138
139 // ----------------------------------------------------------------------------
140 // wxFontRefData
141 // ----------------------------------------------------------------------------
142
143 void wxFontRefData::Init(int pointSize,
144 int family,
145 int style,
146 int weight,
147 bool underlined,
148 const wxString& faceName,
149 wxFontEncoding encoding)
150 {
151 if (family == wxDEFAULT)
152 m_family = wxSWISS;
153 else
154 m_family = family;
155
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;
175 }
176
177 wxFontRefData::~wxFontRefData()
178 {
179 wxNode* node = m_fonts.First();
180 while (node)
181 {
182 wxXFont* f = (wxXFont*) node->Data();
183 delete f;
184 node = node->Next();
185 }
186 m_fonts.Clear();
187 }
188
189 // ----------------------------------------------------------------------------
190 // wxFont
191 // ----------------------------------------------------------------------------
192
193 wxFont::wxFont(const wxNativeFontInfo& info)
194 {
195 Init();
196
197 (void)Create(info.xFontName);
198 }
199
200 void wxFont::Init()
201 {
202 }
203
204 bool wxFont::Create(int pointSize,
205 int family,
206 int style,
207 int weight,
208 bool underlined,
209 const wxString& faceName,
210 wxFontEncoding encoding)
211 {
212 UnRef();
213 m_refData = new wxFontRefData(pointSize, family, style, weight,
214 underlined, faceName, encoding);
215
216 RealizeResource();
217
218 return TRUE;
219 }
220
221 bool wxFont::Create(const wxString& fontname, wxFontEncoding enc)
222 {
223 if( !fontname )
224 {
225 *this = wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT);
226 return TRUE;
227 }
228
229 m_refData = new wxFontRefData();
230
231 M_FONTDATA->m_nativeFontInfo.xFontName = fontname; // X font name
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
324 wxFont::~wxFont()
325 {
326 }
327
328 // ----------------------------------------------------------------------------
329 // change the font attributes
330 // ----------------------------------------------------------------------------
331
332 void wxFont::Unshare()
333 {
334 // Don't change shared data
335 if (!m_refData)
336 {
337 m_refData = new wxFontRefData();
338 }
339 else
340 {
341 wxFontRefData* ref = new wxFontRefData(*(wxFontRefData*)m_refData);
342 UnRef();
343 m_refData = ref;
344 }
345 }
346
347 void wxFont::SetPointSize(int pointSize)
348 {
349 Unshare();
350
351 M_FONTDATA->m_pointSize = pointSize;
352 M_FONTDATA->m_nativeFontInfo.xFontName.Clear(); // invalid now
353
354 RealizeResource();
355 }
356
357 void wxFont::SetFamily(int family)
358 {
359 Unshare();
360
361 M_FONTDATA->m_family = family;
362 M_FONTDATA->m_nativeFontInfo.xFontName.Clear(); // invalid now
363
364 RealizeResource();
365 }
366
367 void wxFont::SetStyle(int style)
368 {
369 Unshare();
370
371 M_FONTDATA->m_style = style;
372 M_FONTDATA->m_nativeFontInfo.xFontName.Clear(); // invalid now
373
374 RealizeResource();
375 }
376
377 void wxFont::SetWeight(int weight)
378 {
379 Unshare();
380
381 M_FONTDATA->m_weight = weight;
382 M_FONTDATA->m_nativeFontInfo.xFontName.Clear(); // invalid now
383
384 RealizeResource();
385 }
386
387 void wxFont::SetFaceName(const wxString& faceName)
388 {
389 Unshare();
390
391 M_FONTDATA->m_faceName = faceName;
392 M_FONTDATA->m_nativeFontInfo.xFontName.Clear(); // invalid now
393
394 RealizeResource();
395 }
396
397 void wxFont::SetUnderlined(bool underlined)
398 {
399 Unshare();
400
401 M_FONTDATA->m_underlined = underlined;
402
403 RealizeResource();
404 }
405
406 void wxFont::SetEncoding(wxFontEncoding encoding)
407 {
408 Unshare();
409
410 M_FONTDATA->m_encoding = encoding;
411 M_FONTDATA->m_nativeFontInfo.xFontName.Clear(); // invalid now
412
413 RealizeResource();
414 }
415
416 void wxFont::SetNativeFontInfo(const wxNativeFontInfo& info)
417 {
418 Unshare();
419
420 M_FONTDATA->m_nativeFontInfo = info;
421 }
422
423 // ----------------------------------------------------------------------------
424 // query font attributes
425 // ----------------------------------------------------------------------------
426
427 int wxFont::GetPointSize() const
428 {
429 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
430
431 return M_FONTDATA->m_pointSize;
432 }
433
434 wxString wxFont::GetFaceName() const
435 {
436 wxCHECK_MSG( Ok(), wxT(""), wxT("invalid font") );
437
438 return M_FONTDATA->m_faceName ;
439 }
440
441 int wxFont::GetFamily() const
442 {
443 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
444
445 return M_FONTDATA->m_family;
446 }
447
448 int wxFont::GetStyle() const
449 {
450 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
451
452 return M_FONTDATA->m_style;
453 }
454
455 int wxFont::GetWeight() const
456 {
457 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
458
459 return M_FONTDATA->m_weight;
460 }
461
462 bool wxFont::GetUnderlined() const
463 {
464 wxCHECK_MSG( Ok(), FALSE, wxT("invalid font") );
465
466 return M_FONTDATA->m_underlined;
467 }
468
469 wxFontEncoding wxFont::GetEncoding() const
470 {
471 wxCHECK_MSG( Ok(), wxFONTENCODING_DEFAULT, wxT("invalid font") );
472
473 return M_FONTDATA->m_encoding;
474 }
475
476 wxNativeFontInfo *wxFont::GetNativeFontInfo() const
477 {
478 wxCHECK_MSG( Ok(), (wxNativeFontInfo *)NULL, wxT("invalid font") );
479
480 if(M_FONTDATA->m_nativeFontInfo.xFontName.IsEmpty())
481 GetInternalFont();
482
483 return new wxNativeFontInfo(M_FONTDATA->m_nativeFontInfo);
484 }
485
486 // ----------------------------------------------------------------------------
487 // real implementation
488 // ----------------------------------------------------------------------------
489
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.
493 wxXFont* wxFont::GetInternalFont(double scale, WXDisplay* display) const
494 {
495 if ( !Ok() )
496 return (wxXFont *)NULL;
497
498 long intScale = long(scale * 100.0 + 0.5); // key for wxXFont
499 int pointSize = (M_FONTDATA->m_pointSize * 10 * intScale) / 100;
500
501 // search existing fonts first
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 }
510
511 // not found, create a new one
512 XFontStruct *font = (XFontStruct *)
513 wxLoadQueryNearestFont(pointSize,
514 M_FONTDATA->m_family,
515 M_FONTDATA->m_style,
516 M_FONTDATA->m_weight,
517 M_FONTDATA->m_underlined,
518 wxT(""),
519 M_FONTDATA->m_encoding);
520
521 if ( !font )
522 {
523 wxFAIL_MSG( wxT("Could not allocate even a default font -- something is wrong.") );
524
525 return (wxXFont*) NULL;
526 }
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;
536 }
537
538 WXFontStructPtr wxFont::GetFontStruct(double scale, WXDisplay* display) const
539 {
540 wxXFont* f = GetInternalFont(scale, display);
541
542 return (f ? f->m_fontStruct : (WXFontStructPtr) 0);
543 }
544
545 WXFontList wxFont::GetFontList(double scale, WXDisplay* display) const
546 {
547 wxXFont* f = GetInternalFont(scale, display);
548
549 return (f ? f->m_fontList : (WXFontList) 0);
550 }
551