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