FromString should not fail on wxMac if facename empty.
[wxWidgets.git] / src / common / fontcmn.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: common/fontcmn.cpp
3 // Purpose: implementation of wxFontBase methods
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 20.09.99
7 // RCS-ID: $Id$
8 // Copyright: (c) wxWindows team
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "fontbase.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #ifndef WX_PRECOMP
32 #include "wx/font.h"
33 #include "wx/intl.h"
34 #endif // WX_PRECOMP
35
36 #include "wx/gdicmn.h"
37 #include "wx/fontutil.h" // for wxNativeFontInfo
38 #include "wx/fontmap.h"
39
40 #include "wx/tokenzr.h"
41
42 // ============================================================================
43 // implementation
44 // ============================================================================
45
46 // ----------------------------------------------------------------------------
47 // wxFontBase
48 // ----------------------------------------------------------------------------
49
50 wxFontEncoding wxFontBase::ms_encodingDefault = wxFONTENCODING_SYSTEM;
51
52 /* static */
53 void wxFontBase::SetDefaultEncoding(wxFontEncoding encoding)
54 {
55 // GetDefaultEncoding() should return something != wxFONTENCODING_DEFAULT
56 // and, besides, using this value here doesn't make any sense
57 wxCHECK_RET( encoding != wxFONTENCODING_DEFAULT,
58 _T("can't set default encoding to wxFONTENCODING_DEFAULT") );
59
60 ms_encodingDefault = encoding;
61 }
62
63 wxFontBase::~wxFontBase()
64 {
65 // this destructor is required for Darwin
66 }
67
68 /* static */
69 wxFont *wxFontBase::New(int size,
70 int family,
71 int style,
72 int weight,
73 bool underlined,
74 const wxString& face,
75 wxFontEncoding encoding)
76 {
77 return new wxFont(size, family, style, weight, underlined, face, encoding);
78 }
79
80 /* static */
81 wxFont *wxFontBase::New(int pointSize,
82 wxFontFamily family,
83 int flags,
84 const wxString& face,
85 wxFontEncoding encoding)
86 {
87 return New
88 (
89 pointSize,
90 family,
91 flags & wxFONTFLAG_ITALIC
92 ? wxFONTSTYLE_ITALIC
93 : flags & wxFONTFLAG_SLANT
94 ? wxFONTSTYLE_SLANT
95 : wxFONTSTYLE_NORMAL,
96 flags & wxFONTFLAG_LIGHT
97 ? wxFONTWEIGHT_LIGHT
98 : flags & wxFONTFLAG_BOLD
99 ? wxFONTWEIGHT_BOLD
100 : wxFONTWEIGHT_NORMAL,
101 (flags & wxFONTFLAG_UNDERLINED) != 0,
102 face,
103 encoding
104 );
105 }
106
107 /* static */
108 wxFont *wxFontBase::New(const wxNativeFontInfo& info)
109 {
110 return new wxFont(info);
111 }
112
113 /* static */
114 wxFont *wxFontBase::New(const wxString& strNativeFontDesc)
115 {
116 wxNativeFontInfo fontInfo;
117 if ( !fontInfo.FromString(strNativeFontDesc) )
118 return new wxFont(*wxNORMAL_FONT);
119
120 return New(fontInfo);
121 }
122
123 bool wxFontBase::IsFixedWidth() const
124 {
125 return GetFamily() == wxFONTFAMILY_TELETYPE;
126 }
127
128 wxNativeFontInfo *wxFontBase::GetNativeFontInfo() const
129 {
130 #ifdef wxNO_NATIVE_FONTINFO
131 wxNativeFontInfo *fontInfo = new wxNativeFontInfo();
132
133 fontInfo->SetPointSize(GetPointSize());
134 fontInfo->SetFamily((wxFontFamily)GetFamily());
135 fontInfo->SetStyle((wxFontStyle)GetStyle());
136 fontInfo->SetWeight((wxFontWeight)GetWeight());
137 fontInfo->SetUnderlined(GetUnderlined());
138 fontInfo->SetFaceName(GetFaceName());
139 fontInfo->SetEncoding(GetEncoding());
140
141 return fontInfo;
142 #else
143 return (wxNativeFontInfo *)NULL;
144 #endif
145 }
146
147 void wxFontBase::SetNativeFontInfo(const wxNativeFontInfo& info)
148 {
149 #ifdef wxNO_NATIVE_FONTINFO
150 SetPointSize(info.pointSize);
151 SetFamily(info.family);
152 SetStyle(info.style);
153 SetWeight(info.weight);
154 SetUnderlined(info.underlined);
155 SetFaceName(info.faceName);
156 SetEncoding(info.encoding);
157 #else
158 (void)info;
159 #endif
160 }
161
162 wxString wxFontBase::GetNativeFontInfoDesc() const
163 {
164 wxString fontDesc;
165 wxNativeFontInfo *fontInfo = GetNativeFontInfo();
166 if ( fontInfo )
167 {
168 fontDesc = fontInfo->ToString();
169 delete fontInfo;
170 }
171
172 return fontDesc;
173 }
174
175 wxString wxFontBase::GetNativeFontInfoUserDesc() const
176 {
177 wxString fontDesc;
178 wxNativeFontInfo *fontInfo = GetNativeFontInfo();
179 if ( fontInfo )
180 {
181 fontDesc = fontInfo->ToUserString();
182 delete fontInfo;
183 }
184
185 return fontDesc;
186 }
187
188 void wxFontBase::SetNativeFontInfo(const wxString& info)
189 {
190 wxNativeFontInfo fontInfo;
191 if ( !info.empty() && fontInfo.FromString(info) )
192 {
193 SetNativeFontInfo(fontInfo);
194 }
195 }
196
197 void wxFontBase::SetNativeFontInfoUserDesc(const wxString& info)
198 {
199 wxNativeFontInfo fontInfo;
200 if ( !info.empty() && fontInfo.FromUserString(info) )
201 {
202 SetNativeFontInfo(fontInfo);
203 }
204 }
205
206 wxFont& wxFont::operator=(const wxFont& font)
207 {
208 if ( this != &font )
209 Ref(font);
210
211 return (wxFont &)*this;
212 }
213
214 bool wxFontBase::operator==(const wxFont& font) const
215 {
216 // either it is the same font, i.e. they share the same common data or they
217 // have different ref datas but still describe the same font
218 return GetFontData() == font.GetFontData() ||
219 (
220 Ok() == font.Ok() &&
221 GetPointSize() == font.GetPointSize() &&
222 GetFamily() == font.GetFamily() &&
223 GetStyle() == font.GetStyle() &&
224 GetWeight() == font.GetWeight() &&
225 GetUnderlined() == font.GetUnderlined() &&
226 GetFaceName() == font.GetFaceName() &&
227 GetEncoding() == font.GetEncoding()
228 );
229 }
230
231 bool wxFontBase::operator!=(const wxFont& font) const
232 {
233 return !(*this == font);
234 }
235
236 wxString wxFontBase::GetFamilyString() const
237 {
238 wxCHECK_MSG( Ok(), wxT("wxDEFAULT"), wxT("invalid font") );
239
240 switch ( GetFamily() )
241 {
242 case wxDECORATIVE: return wxT("wxDECORATIVE");
243 case wxROMAN: return wxT("wxROMAN");
244 case wxSCRIPT: return wxT("wxSCRIPT");
245 case wxSWISS: return wxT("wxSWISS");
246 case wxMODERN: return wxT("wxMODERN");
247 case wxTELETYPE: return wxT("wxTELETYPE");
248 default: return wxT("wxDEFAULT");
249 }
250 }
251
252 wxString wxFontBase::GetStyleString() const
253 {
254 wxCHECK_MSG( Ok(), wxT("wxDEFAULT"), wxT("invalid font") );
255
256 switch ( GetStyle() )
257 {
258 case wxNORMAL: return wxT("wxNORMAL");
259 case wxSLANT: return wxT("wxSLANT");
260 case wxITALIC: return wxT("wxITALIC");
261 default: return wxT("wxDEFAULT");
262 }
263 }
264
265 wxString wxFontBase::GetWeightString() const
266 {
267 wxCHECK_MSG( Ok(), wxT("wxDEFAULT"), wxT("invalid font") );
268
269 switch ( GetWeight() )
270 {
271 case wxNORMAL: return wxT("wxNORMAL");
272 case wxBOLD: return wxT("wxBOLD");
273 case wxLIGHT: return wxT("wxLIGHT");
274 default: return wxT("wxDEFAULT");
275 }
276 }
277
278 // ----------------------------------------------------------------------------
279 // wxNativeFontInfo
280 // ----------------------------------------------------------------------------
281
282 #ifdef wxNO_NATIVE_FONTINFO
283
284 // These are the generic forms of FromString()/ToString.
285 //
286 // convert to/from the string representation: format is
287 // version;pointsize;family;style;weight;underlined;facename;encoding
288
289 bool wxNativeFontInfo::FromString(const wxString& s)
290 {
291 long l;
292
293 wxStringTokenizer tokenizer(s, _T(";"));
294
295 wxString token = tokenizer.GetNextToken();
296 //
297 // Ignore the version for now
298 //
299
300 token = tokenizer.GetNextToken();
301 if ( !token.ToLong(&l) )
302 return FALSE;
303 pointSize = (int)l;
304
305 token = tokenizer.GetNextToken();
306 if ( !token.ToLong(&l) )
307 return FALSE;
308 family = (wxFontFamily)l;
309
310 token = tokenizer.GetNextToken();
311 if ( !token.ToLong(&l) )
312 return FALSE;
313 style = (wxFontStyle)l;
314
315 token = tokenizer.GetNextToken();
316 if ( !token.ToLong(&l) )
317 return FALSE;
318 weight = (wxFontWeight)l;
319
320 token = tokenizer.GetNextToken();
321 if ( !token.ToLong(&l) )
322 return FALSE;
323 underlined = l != 0;
324
325 faceName = tokenizer.GetNextToken();
326
327 #ifndef __WXMAC__
328 if( !faceName )
329 return FALSE;
330 #endif
331
332 token = tokenizer.GetNextToken();
333 if ( !token.ToLong(&l) )
334 return FALSE;
335 encoding = (wxFontEncoding)l;
336
337 return TRUE;
338 }
339
340 wxString wxNativeFontInfo::ToString() const
341 {
342 wxString s;
343
344 s.Printf(_T("%d;%d;%d;%d;%d;%d;%s;%d"),
345 0, // version
346 pointSize,
347 family,
348 (int)style,
349 (int)weight,
350 underlined,
351 faceName.GetData(),
352 (int)encoding);
353
354 return s;
355 }
356
357 void wxNativeFontInfo::Init()
358 {
359 pointSize = wxNORMAL_FONT->GetPointSize();
360 family = wxFONTFAMILY_DEFAULT;
361 style = wxFONTSTYLE_NORMAL;
362 weight = wxFONTWEIGHT_NORMAL;
363 underlined = FALSE;
364 faceName.clear();
365 encoding = wxFONTENCODING_DEFAULT;
366 }
367
368 int wxNativeFontInfo::GetPointSize() const
369 {
370 return pointSize;
371 }
372
373 wxFontStyle wxNativeFontInfo::GetStyle() const
374 {
375 return style;
376 }
377
378 wxFontWeight wxNativeFontInfo::GetWeight() const
379 {
380 return weight;
381 }
382
383 bool wxNativeFontInfo::GetUnderlined() const
384 {
385 return underlined;
386 }
387
388 wxString wxNativeFontInfo::GetFaceName() const
389 {
390 return faceName;
391 }
392
393 wxFontFamily wxNativeFontInfo::GetFamily() const
394 {
395 return family;
396 }
397
398 wxFontEncoding wxNativeFontInfo::GetEncoding() const
399 {
400 return encoding;
401 }
402
403 void wxNativeFontInfo::SetPointSize(int pointsize)
404 {
405 pointSize = pointsize;
406 }
407
408 void wxNativeFontInfo::SetStyle(wxFontStyle style_)
409 {
410 style = style_;
411 }
412
413 void wxNativeFontInfo::SetWeight(wxFontWeight weight_)
414 {
415 weight = weight_;
416 }
417
418 void wxNativeFontInfo::SetUnderlined(bool underlined_)
419 {
420 underlined = underlined_;
421 }
422
423 void wxNativeFontInfo::SetFaceName(wxString facename_)
424 {
425 faceName = facename_;
426 }
427
428 void wxNativeFontInfo::SetFamily(wxFontFamily family_)
429 {
430 family = family_;
431 }
432
433 void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding_)
434 {
435 encoding = encoding_;
436 }
437
438 #endif // generic wxNativeFontInfo implementation
439
440 // conversion to/from user-readable string: this is used in the generic
441 // versions and under MSW as well because there is no standard font description
442 // format there anyhow (but there is a well-defined standard for X11 fonts used
443 // by wxGTK and wxMotif)
444
445 #if defined(wxNO_NATIVE_FONTINFO) || defined(__WXMSW__) || defined (__WXPM__)
446
447 wxString wxNativeFontInfo::ToUserString() const
448 {
449 wxString desc;
450
451 // first put the adjectives, if any - this is English-centric, of course,
452 // but what else can we do?
453 if ( GetUnderlined() )
454 {
455 desc << _("underlined ");
456 }
457
458 switch ( GetWeight() )
459 {
460 default:
461 wxFAIL_MSG( _T("unknown font weight") );
462 // fall through
463
464 case wxFONTWEIGHT_NORMAL:
465 break;
466
467 case wxFONTWEIGHT_LIGHT:
468 desc << _("light ");
469 break;
470
471 case wxFONTWEIGHT_BOLD:
472 desc << _("bold ");
473 break;
474 }
475
476 switch ( GetStyle() )
477 {
478 default:
479 wxFAIL_MSG( _T("unknown font style") );
480 // fall through
481
482 case wxFONTSTYLE_NORMAL:
483 break;
484
485 // we don't distinguish between the two for now anyhow...
486 case wxFONTSTYLE_ITALIC:
487 case wxFONTSTYLE_SLANT:
488 desc << _("italic");
489 break;
490 }
491
492 wxString face = GetFaceName();
493 if ( !face.empty() )
494 {
495 desc << _T(' ') << face;
496 }
497
498 int size = GetPointSize();
499 if ( size != wxNORMAL_FONT->GetPointSize() )
500 {
501 desc << _T(' ') << size;
502 }
503
504 #if wxUSE_FONTMAP
505 wxFontEncoding enc = GetEncoding();
506 if ( enc != wxFONTENCODING_DEFAULT && enc != wxFONTENCODING_SYSTEM )
507 {
508 desc << _T(' ') << wxFontMapper::Get()->GetEncodingName(enc);
509 }
510 #endif // wxUSE_FONTMAP
511
512 return desc;
513 }
514
515 bool wxNativeFontInfo::FromUserString(const wxString& s)
516 {
517 // reset to the default state
518 Init();
519
520 // parse a more or less free form string
521 //
522 // TODO: we should handle at least the quoted facenames
523 wxStringTokenizer tokenizer(s, _T(";, "), wxTOKEN_STRTOK);
524
525 wxString face;
526 unsigned long size;
527
528 #if wxUSE_FONTMAP
529 wxFontEncoding encoding;
530 #endif // wxUSE_FONTMAP
531
532 while ( tokenizer.HasMoreTokens() )
533 {
534 wxString token = tokenizer.GetNextToken();
535
536 // normalize it
537 token.Trim(TRUE).Trim(FALSE).MakeLower();
538
539 // look for the known tokens
540 if ( token == _T("underlined") || token == _("underlined") )
541 {
542 SetUnderlined(TRUE);
543 }
544 else if ( token == _T("light") || token == _("light") )
545 {
546 SetWeight(wxFONTWEIGHT_LIGHT);
547 }
548 else if ( token == _T("bold") || token == _("bold") )
549 {
550 SetWeight(wxFONTWEIGHT_BOLD);
551 }
552 else if ( token == _T("italic") || token == _("italic") )
553 {
554 SetStyle(wxFONTSTYLE_ITALIC);
555 }
556 else if ( token.ToULong(&size) )
557 {
558 SetPointSize(size);
559 }
560 #if wxUSE_FONTMAP
561 else if ( (encoding = wxFontMapper::Get()->CharsetToEncoding(token, FALSE))
562 != wxFONTENCODING_DEFAULT )
563 {
564 SetEncoding(encoding);
565 }
566 #endif // wxUSE_FONTMAP
567 else // assume it is the face name
568 {
569 if ( !face.empty() )
570 {
571 face += _T(' ');
572 }
573
574 face += token;
575
576 // skip the code which resets face below
577 continue;
578 }
579
580 // if we had had the facename, we shouldn't continue appending tokens
581 // to it (i.e. "foo bold bar" shouldn't result in the facename "foo
582 // bar")
583 if ( !face.empty() )
584 {
585 SetFaceName(face);
586 face.clear();
587 }
588 }
589
590 // we might not have flushed it inside the loop
591 if ( !face.empty() )
592 {
593 SetFaceName(face);
594 }
595
596 return TRUE;
597 }
598
599 #endif // generic or wxMSW or wxOS2
600