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