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