wxMotif::wxFont supports encodings too (and shares 99% of font code with wxGTK)
[wxWidgets.git] / src / motif / font.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: 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 #include "wx/defs.h"
25 #include "wx/string.h"
26 #include "wx/font.h"
27 #include "wx/gdicmn.h"
28 #include "wx/utils.h"
29
30 #include <Xm/Xm.h>
31
32 #if !USE_SHARED_LIBRARIES
33 IMPLEMENT_DYNAMIC_CLASS(wxFont, wxGDIObject)
34 #endif
35
36 // ----------------------------------------------------------------------------
37 // private classes
38 // ----------------------------------------------------------------------------
39
40 // For every wxFont, there must be a font for each display and scale requested.
41 // So these objects are stored in wxFontRefData::m_fonts
42 class wxXFont: public wxObject
43 {
44 public:
45 wxXFont();
46 ~wxXFont();
47
48 WXFontStructPtr m_fontStruct; // XFontStruct
49 WXFontList m_fontList; // Motif XmFontList
50 WXDisplay* m_display; // XDisplay
51 int m_scale; // Scale * 100
52 };
53
54 class wxFontRefData: public wxGDIRefData
55 {
56 friend class wxFont;
57
58 public:
59 wxFontRefData(int size = wxDEFAULT,
60 int family = wxDEFAULT,
61 int style = wxDEFAULT,
62 int weight = wxDEFAULT,
63 bool underlined = FALSE,
64 const wxString& faceName = wxEmptyString,
65 wxFontEncoding encoding = wxFONTENCODING_DEFAULT)
66 {
67 Init(size, family, style, weight, underlined, faceName, encoding);
68 }
69
70 wxFontRefData(const wxFontRefData& data)
71 {
72 Init(data.m_pointSize, data.m_family, data.m_style, data.m_weight,
73 data.m_underlined, data.m_faceName, data.m_encoding);
74 }
75
76 ~wxFontRefData();
77
78 protected:
79 // common part of all ctors
80 void Init(int size,
81 int family,
82 int style,
83 int weight,
84 bool underlined,
85 const wxString& faceName,
86 wxFontEncoding encoding);
87
88 // font attributes
89 int m_pointSize;
90 int m_family;
91 int m_style;
92 int m_weight;
93 bool m_underlined;
94 wxString m_faceName;
95 wxFontEncoding m_encoding;
96
97 // A list of wxXFonts
98 wxList m_fonts;
99 };
100
101 // ============================================================================
102 // implementation
103 // ============================================================================
104
105 // ----------------------------------------------------------------------------
106 // wxXFont
107 // ----------------------------------------------------------------------------
108
109 wxXFont::wxXFont()
110 {
111 m_fontStruct = (WXFontStructPtr) 0;
112 m_fontList = (WXFontList) 0;
113 m_display = (WXDisplay*) 0;
114 m_scale = 100;
115 }
116
117 wxXFont::~wxXFont()
118 {
119 XmFontList fontList = (XmFontList) m_fontList;
120
121 XmFontListFree (fontList);
122
123 // TODO: why does freeing the font produce a segv???
124 // Note that XFreeFont wasn't called in wxWin 1.68 either.
125 // XFontStruct* fontStruct = (XFontStruct*) m_fontStruct;
126 // XFreeFont((Display*) m_display, fontStruct);
127 }
128
129 // ----------------------------------------------------------------------------
130 // wxFontRefData
131 // ----------------------------------------------------------------------------
132
133 void wxFontRefData::Init(int pointSize,
134 int family,
135 int style,
136 int weight,
137 bool underlined,
138 const wxString& faceName,
139 wxFontEncoding encoding)
140 {
141 if (family == wxDEFAULT)
142 m_family = wxSWISS;
143 else
144 m_family = family;
145
146 m_faceName = faceName;
147
148 if (style == wxDEFAULT)
149 m_style = wxNORMAL;
150 else
151 m_style = style;
152
153 if (weight == wxDEFAULT)
154 m_weight = wxNORMAL;
155 else
156 m_weight = weight;
157
158 if (pointSize == wxDEFAULT)
159 m_pointSize = 12;
160 else
161 m_pointSize = pointSize;
162
163 m_underlined = underlined;
164 m_encoding = encoding;
165 }
166
167 wxFontRefData::~wxFontRefData()
168 {
169 wxNode* node = m_fonts.First();
170 while (node)
171 {
172 wxXFont* f = (wxXFont*) node->Data();
173 delete f;
174 node = node->Next();
175 }
176 m_fonts.Clear();
177 }
178
179 // ----------------------------------------------------------------------------
180 // wxFont
181 // ----------------------------------------------------------------------------
182
183 void wxFont::Init()
184 {
185 if ( wxTheFontList )
186 wxTheFontList->Append(this);
187 }
188
189 bool wxFont::Create(int pointSize,
190 int family,
191 int style,
192 int weight,
193 bool underlined,
194 const wxString& faceName,
195 wxFontEncoding encoding)
196 {
197 UnRef();
198 m_refData = new wxFontRefData(pointSize, family, style, weight,
199 underlined, faceName, encoding);
200
201 RealizeResource();
202
203 return TRUE;
204 }
205
206 wxFont::~wxFont()
207 {
208 if ( wxTheFontList )
209 wxTheFontList->DeleteObject(this);
210 }
211
212 // ----------------------------------------------------------------------------
213 // change the font attributes
214 // ----------------------------------------------------------------------------
215
216 void wxFont::Unshare()
217 {
218 // Don't change shared data
219 if (!m_refData)
220 {
221 m_refData = new wxFontRefData();
222 }
223 else
224 {
225 wxFontRefData* ref = new wxFontRefData(*(wxFontRefData*)m_refData);
226 UnRef();
227 m_refData = ref;
228 }
229 }
230
231 void wxFont::SetPointSize(int pointSize)
232 {
233 Unshare();
234
235 M_FONTDATA->m_pointSize = pointSize;
236
237 RealizeResource();
238 }
239
240 void wxFont::SetFamily(int family)
241 {
242 Unshare();
243
244 M_FONTDATA->m_family = family;
245
246 RealizeResource();
247 }
248
249 void wxFont::SetStyle(int style)
250 {
251 Unshare();
252
253 M_FONTDATA->m_style = style;
254
255 RealizeResource();
256 }
257
258 void wxFont::SetWeight(int weight)
259 {
260 Unshare();
261
262 M_FONTDATA->m_weight = weight;
263
264 RealizeResource();
265 }
266
267 void wxFont::SetFaceName(const wxString& faceName)
268 {
269 Unshare();
270
271 M_FONTDATA->m_faceName = faceName;
272
273 RealizeResource();
274 }
275
276 void wxFont::SetUnderlined(bool underlined)
277 {
278 Unshare();
279
280 M_FONTDATA->m_underlined = underlined;
281
282 RealizeResource();
283 }
284
285 void wxFont::SetEncoding(wxFontEncoding encoding)
286 {
287 Unshare();
288
289 M_FONTDATA->m_encoding = encoding;
290
291 RealizeResource();
292 }
293
294 // ----------------------------------------------------------------------------
295 // query font attributes
296 // ----------------------------------------------------------------------------
297
298 int wxFont::GetPointSize() const
299 {
300 return M_FONTDATA->m_pointSize;
301 }
302
303 int wxFont::GetFamily() const
304 {
305 return M_FONTDATA->m_family;
306 }
307
308 int wxFont::GetStyle() const
309 {
310 return M_FONTDATA->m_style;
311 }
312
313 int wxFont::GetWeight() const
314 {
315 return M_FONTDATA->m_weight;
316 }
317
318 bool wxFont::GetUnderlined() const
319 {
320 return M_FONTDATA->m_underlined;
321 }
322
323 wxString wxFont::GetFaceName() const
324 {
325 wxString str;
326 if ( M_FONTDATA )
327 str = M_FONTDATA->m_faceName ;
328 return str;
329 }
330
331 wxFontEncoding wxFont::GetEncoding() const
332 {
333 return M_FONTDATA->m_encoding;
334 }
335
336 // ----------------------------------------------------------------------------
337 // real implementation
338 // ----------------------------------------------------------------------------
339
340 // Find an existing, or create a new, XFontStruct
341 // based on this wxFont and the given scale. Append the
342 // font to list in the private data for future reference.
343 wxXFont* wxFont::GetInternalFont(double scale, WXDisplay* display) const
344 {
345 if ( !Ok() )
346 return (wxXFont *)NULL;
347
348 long intScale = long(scale * 100.0 + 0.5); // key for wxXFont
349 int pointSize = (M_FONTDATA->m_pointSize * 10 * intScale) / 100;
350
351 // search existing fonts first
352 wxNode* node = M_FONTDATA->m_fonts.First();
353 while (node)
354 {
355 wxXFont* f = (wxXFont*) node->Data();
356 if ((!display || (f->m_display == display)) && (f->m_scale == intScale))
357 return f;
358 node = node->Next();
359 }
360
361 // not found, create a new one
362 XFontStruct *font = wxLoadQueryNearestFont(pointSize,
363 M_FONTDATA->m_family,
364 M_FONTDATA->m_style,
365 M_FONTDATA->m_weight,
366 M_FONTDATA->m_underlined,
367 _T(""),
368 M_FONTDATA->m_encoding);
369
370 if ( !font )
371 {
372 wxFAIL_MSG( _T("Could not allocate even a default font -- something is wrong.") );
373
374 return (wxXFont*) NULL;
375 }
376
377 wxXFont* f = new wxXFont;
378 f->m_fontStruct = (WXFontStructPtr)font;
379 f->m_display = ( display ? display : wxGetDisplay() );
380 f->m_scale = intScale;
381 f->m_fontList = XmFontListCreate ((XFontStruct*) font, XmSTRING_DEFAULT_CHARSET);
382 M_FONTDATA->m_fonts.Append(f);
383
384 return f;
385 }
386
387 WXFontStructPtr wxFont::GetFontStruct(double scale, WXDisplay* display) const
388 {
389 wxXFont* f = GetInternalFont(scale, display);
390
391 return (f ? f->m_fontStruct : (WXFontStructPtr) 0);
392 }
393
394 WXFontList wxFont::GetFontList(double scale, WXDisplay* display) const
395 {
396 wxXFont* f = GetInternalFont(scale, display);
397
398 return (f ? f->m_fontList : (WXFontList) 0);
399 }