Added some tentative wxMotif clipboard code; did some file formatting
[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 #ifdef __GNUG__
13 #pragma implementation "font.h"
14 #endif
15
16 #include "wx/defs.h"
17 #include "wx/string.h"
18 #include "wx/font.h"
19 #include "wx/gdicmn.h"
20 #include "wx/utils.h"
21
22 #include <Xm/Xm.h>
23
24 #if !USE_SHARED_LIBRARIES
25 IMPLEMENT_DYNAMIC_CLASS(wxFont, wxGDIObject)
26 #endif
27
28 wxXFont::wxXFont()
29 {
30 m_fontStruct = (WXFontStructPtr) 0;
31 m_fontList = (WXFontList) 0;
32 m_display = (WXDisplay*) 0;
33 m_scale = 100;
34 }
35
36 wxXFont::~wxXFont()
37 {
38 XFontStruct* fontStruct = (XFontStruct*) m_fontStruct;
39 XmFontList fontList = (XmFontList) m_fontList;
40
41 XmFontListFree (fontList);
42
43 // TODO: why does freeing the font produce a segv???
44 // Note that XFreeFont wasn't called in wxWin 1.68 either.
45 // XFreeFont((Display*) m_display, fontStruct);
46 }
47
48 wxFontRefData::wxFontRefData()
49 {
50 m_style = 0;
51 m_pointSize = 0;
52 m_family = 0;
53 m_style = 0;
54 m_weight = 0;
55 m_underlined = 0;
56 m_faceName = "";
57 }
58
59 wxFontRefData::wxFontRefData(const wxFontRefData& data)
60 {
61 m_style = data.m_style;
62 m_pointSize = data.m_pointSize;
63 m_family = data.m_family;
64 m_style = data.m_style;
65 m_weight = data.m_weight;
66 m_underlined = data.m_underlined;
67 m_faceName = data.m_faceName;
68
69 // Don't have to copy actual fonts, because they'll be created
70 // on demand.
71 }
72
73 wxFontRefData::~wxFontRefData()
74 {
75 wxNode* node = m_fonts.First();
76 while (node)
77 {
78 wxXFont* f = (wxXFont*) node->Data();
79 delete f;
80 node = node->Next();
81 }
82 m_fonts.Clear();
83 }
84
85 wxFont::wxFont()
86 {
87 if ( wxTheFontList )
88 wxTheFontList->Append(this);
89 }
90
91 wxFont::wxFont(int pointSize, int family, int style, int weight, bool underlined, const wxString& faceName)
92 {
93 Create(pointSize, family, style, weight, underlined, faceName);
94
95 if ( wxTheFontList )
96 wxTheFontList->Append(this);
97 }
98
99 bool wxFont::Create(int pointSize, int family, int style, int weight, bool underlined, const wxString& faceName)
100 {
101 UnRef();
102 m_refData = new wxFontRefData;
103
104 M_FONTDATA->m_family = family;
105 M_FONTDATA->m_style = style;
106 M_FONTDATA->m_weight = weight;
107 M_FONTDATA->m_pointSize = pointSize;
108 M_FONTDATA->m_underlined = underlined;
109 M_FONTDATA->m_faceName = faceName;
110
111 RealizeResource();
112
113 return TRUE;
114 }
115
116 wxFont::~wxFont()
117 {
118 if (wxTheFontList)
119 wxTheFontList->DeleteObject(this);
120 }
121
122 bool wxFont::RealizeResource()
123 {
124 // TODO: create the font (if there is a native font object)
125 return FALSE;
126 }
127
128 void wxFont::Unshare()
129 {
130 // Don't change shared data
131 if (!m_refData)
132 {
133 m_refData = new wxFontRefData();
134 }
135 else
136 {
137 wxFontRefData* ref = new wxFontRefData(*(wxFontRefData*)m_refData);
138 UnRef();
139 m_refData = ref;
140 }
141 }
142
143 void wxFont::SetPointSize(int pointSize)
144 {
145 Unshare();
146
147 M_FONTDATA->m_pointSize = pointSize;
148
149 RealizeResource();
150 }
151
152 void wxFont::SetFamily(int family)
153 {
154 Unshare();
155
156 M_FONTDATA->m_family = family;
157
158 RealizeResource();
159 }
160
161 void wxFont::SetStyle(int style)
162 {
163 Unshare();
164
165 M_FONTDATA->m_style = style;
166
167 RealizeResource();
168 }
169
170 void wxFont::SetWeight(int weight)
171 {
172 Unshare();
173
174 M_FONTDATA->m_weight = weight;
175
176 RealizeResource();
177 }
178
179 void wxFont::SetFaceName(const wxString& faceName)
180 {
181 Unshare();
182
183 M_FONTDATA->m_faceName = faceName;
184
185 RealizeResource();
186 }
187
188 void wxFont::SetUnderlined(bool underlined)
189 {
190 Unshare();
191
192 M_FONTDATA->m_underlined = underlined;
193
194 RealizeResource();
195 }
196
197 wxString wxFont::GetFamilyString() const
198 {
199 wxString fam("");
200 switch (GetFamily())
201 {
202 case wxDECORATIVE:
203 fam = "wxDECORATIVE";
204 break;
205 case wxROMAN:
206 fam = "wxROMAN";
207 break;
208 case wxSCRIPT:
209 fam = "wxSCRIPT";
210 break;
211 case wxSWISS:
212 fam = "wxSWISS";
213 break;
214 case wxMODERN:
215 fam = "wxMODERN";
216 break;
217 case wxTELETYPE:
218 fam = "wxTELETYPE";
219 break;
220 default:
221 fam = "wxDEFAULT";
222 break;
223 }
224 return fam;
225 }
226
227 /* New font system */
228 wxString wxFont::GetFaceName() const
229 {
230 wxString str("");
231 if (M_FONTDATA)
232 str = M_FONTDATA->m_faceName ;
233 return str;
234 }
235
236 wxString wxFont::GetStyleString() const
237 {
238 wxString styl("");
239 switch (GetStyle())
240 {
241 case wxITALIC:
242 styl = "wxITALIC";
243 break;
244 case wxSLANT:
245 styl = "wxSLANT";
246 break;
247 default:
248 styl = "wxNORMAL";
249 break;
250 }
251 return styl;
252 }
253
254 wxString wxFont::GetWeightString() const
255 {
256 wxString w("");
257 switch (GetWeight())
258 {
259 case wxBOLD:
260 w = "wxBOLD";
261 break;
262 case wxLIGHT:
263 w = "wxLIGHT";
264 break;
265 default:
266 w = "wxNORMAL";
267 break;
268 }
269 return w;
270 }
271
272 // Find an existing, or create a new, XFontStruct
273 // based on this wxFont and the given scale. Append the
274 // font to list in the private data for future reference.
275 wxXFont* wxFont::GetInternalFont(double scale, WXDisplay* display) const
276 {
277 if (!Ok())
278 return (wxXFont*) NULL;
279
280 long intScale = long(scale * 100.0 + 0.5); // key for wxXFont
281 int pointSize = (M_FONTDATA->m_pointSize * 10 * intScale) / 100;
282
283 wxNode* node = M_FONTDATA->m_fonts.First();
284 while (node)
285 {
286 wxXFont* f = (wxXFont*) node->Data();
287 if ((!display || (f->m_display == display)) && (f->m_scale == intScale))
288 return f;
289 node = node->Next();
290 }
291
292 WXFontStructPtr font = LoadQueryFont(pointSize, M_FONTDATA->m_family,
293 M_FONTDATA->m_style, M_FONTDATA->m_weight, M_FONTDATA->m_underlined);
294
295 if (!font)
296 {
297 // search up and down by stepsize 10
298 int max_size = pointSize + 20 * (1 + (pointSize/180));
299 int min_size = pointSize - 20 * (1 + (pointSize/180));
300 int i;
301
302 // Search for smaller size (approx.)
303 for (i=pointSize-10; !font && i >= 10 && i >= min_size; i -= 10)
304 font = LoadQueryFont(i, M_FONTDATA->m_family, M_FONTDATA->m_style, M_FONTDATA->m_weight, M_FONTDATA->m_underlined);
305 // Search for larger size (approx.)
306 for (i=pointSize+10; !font && i <= max_size; i += 10)
307 font = LoadQueryFont(i, M_FONTDATA->m_family, M_FONTDATA->m_style, M_FONTDATA->m_weight, M_FONTDATA->m_underlined);
308 // Try default family
309 if (!font && M_FONTDATA->m_family != wxDEFAULT)
310 font = LoadQueryFont(pointSize, wxDEFAULT, M_FONTDATA->m_style,
311 M_FONTDATA->m_weight, M_FONTDATA->m_underlined);
312 // Bogus font
313 if (!font)
314 font = LoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL,
315 M_FONTDATA->m_underlined);
316 wxASSERT_MSG( (font != (XFontStruct*) NULL), "Could not allocate even a default font -- something is wrong." );
317 }
318 if (font)
319 {
320 wxXFont* f = new wxXFont;
321 f->m_fontStruct = font;
322 f->m_display = ( display ? display : wxGetDisplay() );
323 f->m_scale = intScale;
324 f->m_fontList = XmFontListCreate ((XFontStruct*) font, XmSTRING_DEFAULT_CHARSET);
325 M_FONTDATA->m_fonts.Append(f);
326 return f;
327 }
328 return (wxXFont*) NULL;
329 }
330
331 WXFontStructPtr wxFont::LoadQueryFont(int pointSize, int family, int style,
332 int weight, bool underlined) const
333 {
334 char *xfamily;
335 char *xstyle;
336 char *xweight;
337 switch (family)
338 {
339 case wxDECORATIVE: xfamily = "lucida";
340 break;
341 case wxROMAN: xfamily = "times";
342 break;
343 case wxMODERN: xfamily = "courier";
344 break;
345 case wxSWISS: xfamily = "lucida";
346 break;
347 case wxDEFAULT:
348 default: xfamily = "*";
349 }
350 switch (style)
351 {
352 case wxITALIC: xstyle = "i";
353 break;
354 case wxSLANT: xstyle = "o";
355 break;
356 case wxNORMAL: xstyle = "r";
357 break;
358 default: xstyle = "*";
359 break;
360 }
361 switch (weight)
362 {
363 case wxBOLD: xweight = "bold";
364 break;
365 case wxLIGHT:
366 case wxNORMAL: xweight = "medium";
367 break;
368 default: xweight = "*";
369 break;
370 }
371
372 sprintf(wxBuffer, "-*-%s-%s-%s-normal-*-*-%d-*-*-*-*-*-*",
373 xfamily, xweight, xstyle, pointSize);
374
375 Display *dpy = (Display*) wxGetDisplay();
376 XFontStruct* font = XLoadQueryFont(dpy, wxBuffer);
377
378 return (WXFontStructPtr) font;
379 }