1/////////////////////////////////////////////////////////////////////////////
2// Name:        src/os2/font.cpp
3// Purpose:     wxFont class
4// Author:      David Webster
5// Modified by:
6// Created:     10/06/99
7// RCS-ID:      $Id: font.cpp 43545 2006-11-20 16:21:08Z VS $
8// Copyright:   (c) David Webster
9// Licence:     wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15// ============================================================================
16// declarations
17// ============================================================================
18
19// ----------------------------------------------------------------------------
20// headers
21// ----------------------------------------------------------------------------
22
23#include "wx/font.h"
24
25#ifndef WX_PRECOMP
26    #include <stdio.h>
27    #include "wx/list.h"
28    #include "wx/utils.h"
29    #include "wx/app.h"
30    #include "wx/log.h"
31#endif // WX_PRECOMP
32
33#include "wx/os2/private.h"
34
35#include "wx/fontutil.h"
36#include "wx/fontmap.h"
37#include "wx/encinfo.h"
38
39#include "wx/tokenzr.h"
40
41#include <malloc.h>
42
43IMPLEMENT_DYNAMIC_CLASS(wxFont, wxGDIObject)
44
45// ----------------------------------------------------------------------------
46// wxFontRefData - the internal description of the font
47// ----------------------------------------------------------------------------
48
49class WXDLLEXPORT wxFontRefData: public wxGDIRefData
50{
51public:
52    wxFontRefData()
53    {
54        Init(-1, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false,
55             wxEmptyString, wxFONTENCODING_DEFAULT);
56    }
57
58    wxFontRefData( int             nSize
59                  ,int             nFamily
60                  ,int             nStyle
61                  ,int             nWeight
62                  ,bool            bUnderlined
63                  ,const wxString& sFaceName
64                  ,wxFontEncoding  vEncoding
65                 )
66    {
67        Init( nSize
68             ,nFamily
69             ,nStyle
70             ,nWeight
71             ,bUnderlined
72             ,sFaceName
73             ,vEncoding
74            );
75    }
76
77    wxFontRefData( const wxNativeFontInfo& rInfo
78                  ,WXHFONT                 hFont = 0
79                  ,WXHANDLE                hPS   = 0
80                 )
81    {
82        Init( rInfo
83             ,hFont
84             ,hPS
85            );
86    }
87
88    wxFontRefData(const wxFontRefData& rData)
89    {
90        Init( rData.m_nPointSize
91             ,rData.m_nFamily
92             ,rData.m_nStyle
93             ,rData.m_nWeight
94             ,rData.m_bUnderlined
95             ,rData.m_sFaceName
96             ,rData.m_vEncoding
97            );
98        m_nFontId = rData.m_nFontId;
99    }
100
101    virtual ~wxFontRefData();
102
103    //
104    // Operations
105    //
106    bool Alloc(wxFont* pFont);
107    void Free(void);
108
109    //
110    // All wxFont accessors
111    //
112    inline int GetPointSize(void) const
113    {
114        //
115        // We don't use the actual native font point size since it is
116        // the chosen physical font, which is usually only and approximation
117        // of the desired outline font.  The actual displayable point size
118        // is the one stored in the refData
119        //
120        return m_nPointSize;
121    }
122
123    inline int GetFamily(void) const
124    {
125        return m_nFamily;
126    }
127
128    inline int GetStyle(void) const
129    {
130        return m_bNativeFontInfoOk ? m_vNativeFontInfo.GetStyle()
131                                   : m_nStyle;
132    }
133
134    inline int GetWeight(void) const
135    {
136        return m_bNativeFontInfoOk ? m_vNativeFontInfo.GetWeight()
137                                   : m_nWeight;
138    }
139
140    inline bool GetUnderlined(void) const
141    {
142        return m_bNativeFontInfoOk ? m_vNativeFontInfo.GetUnderlined()
143                                   : m_bUnderlined;
144    }
145
146    inline wxString GetFaceName(void) const
147    {
148        wxString                    sFaceName;
149
150        if (m_bNativeFontInfoOk)
151            sFaceName = m_vNativeFontInfo.GetFaceName();
152        else
153            sFaceName = m_sFaceName;
154
155        return sFaceName;
156    }
157
158    inline wxFontEncoding GetEncoding(void) const
159    {
160        return m_bNativeFontInfoOk ? m_vNativeFontInfo.GetEncoding()
161                                   : m_vEncoding;
162    }
163
164    inline WXHFONT      GetHFONT(void) const { return m_hFont; }
165    inline HPS          GetPS(void) const { return m_hPS; }
166    inline PFONTMETRICS GetFM(void) const { return m_pFM; }
167    inline int          GetNumFonts(void) const { return m_nNumFonts; }
168
169    // ... and setters
170    inline void SetPointSize(int nPointSize)
171    {
172        if (m_bNativeFontInfoOk)
173            m_vNativeFontInfo.SetPointSize(nPointSize);
174        else
175            m_nPointSize = nPointSize;
176    }
177
178    inline void SetFamily(int nFamily)
179    {
180        m_nFamily = nFamily;
181    }
182
183    inline void SetStyle(int nStyle)
184    {
185        if (m_bNativeFontInfoOk)
186            m_vNativeFontInfo.SetStyle((wxFontStyle)nStyle);
187        else
188            m_nStyle = nStyle;
189    }
190
191    inline void SetWeight(int nWeight)
192    {
193        if (m_bNativeFontInfoOk)
194            m_vNativeFontInfo.SetWeight((wxFontWeight)nWeight);
195        else
196            m_nWeight = nWeight;
197    }
198
199    inline bool SetFaceName(const wxString& sFaceName)
200    {
201        if (m_bNativeFontInfoOk)
202            return m_vNativeFontInfo.SetFaceName(sFaceName);
203        else
204            m_sFaceName = sFaceName;
205        return true;
206    }
207
208    inline void SetUnderlined(bool bUnderlined)
209    {
210        if (m_bNativeFontInfoOk)
211            m_vNativeFontInfo.SetUnderlined(bUnderlined);
212        else
213            m_bUnderlined = bUnderlined;
214    }
215
216    inline void SetEncoding(wxFontEncoding vEncoding)
217    {
218        if (m_bNativeFontInfoOk)
219            m_vNativeFontInfo.SetEncoding(vEncoding);
220        else
221            m_vEncoding = vEncoding;
222    }
223
224    inline void SetPS(HPS hPS)
225    {
226        m_hPS = hPS;
227    }
228
229    inline void SetFM(PFONTMETRICS pFM)
230    {
231        m_pFM = pFM;
232    }
233
234    inline void SetNumFonts(int nNumFonts)
235    {
236        m_nNumFonts = nNumFonts;
237    }
238
239    //
240    // Native font info tests
241    //
242    bool HasNativeFontInfo() const { return m_bNativeFontInfoOk; }
243
244    const wxNativeFontInfo& GetNativeFontInfo() const
245        { return m_vNativeFontInfo; }
246
247protected:
248    //
249    // Common part of all ctors
250    //
251    void Init( int             nSize
252              ,int             nFamily
253              ,int             nStyle
254              ,int             nWeight
255              ,bool            bUnderlined
256              ,const wxString& rsFaceName
257              ,wxFontEncoding  vEncoding
258             );
259
260    void Init( const wxNativeFontInfo& rInfo
261              ,WXHFONT                 hFont = 0
262              ,WXHANDLE                hPS   = 0
263             );
264    //
265    // If true, the pointer to the actual font is temporary and SHOULD NOT BE
266    // DELETED by destructor
267    //
268    bool                            m_bTemporary;
269    int                             m_nFontId;
270
271    //
272    // Font characterstics
273    //
274    int                             m_nPointSize;
275    int                             m_nFamily;
276    int                             m_nStyle;
277    int                             m_nWeight;
278    bool                            m_bUnderlined;
279    wxString                        m_sFaceName;
280    wxFontEncoding                  m_vEncoding;
281    WXHFONT                         m_hFont;
282
283    //
284    // Native font info
285    //
286    wxNativeFontInfo                m_vNativeFontInfo;
287    bool                            m_bNativeFontInfoOk;
288
289    //
290    // Some PM specific stuff
291    //
292    PFONTMETRICS                    m_pFM;         // array of FONTMETRICS structs
293    int                             m_nNumFonts;   // number of fonts in array
294    HPS                             m_hPS;         // PS handle this font belongs to
295    FATTRS                          m_vFattrs;     // Current fattrs struct
296    FACENAMEDESC                    m_vFname;      // Current facename struct
297    bool                            m_bInternalPS; // Internally generated PS?
298}; // end of CLASS wxFontRefData
299
300#define M_FONTDATA ((wxFontRefData*)m_refData)
301
302// ============================================================================
303// implementation
304// ============================================================================
305
306// ----------------------------------------------------------------------------
307// wxFontRefData
308// ----------------------------------------------------------------------------
309
310void wxFontRefData::Init(
311  int                               nPointSize
312, int                               nFamily
313, int                               nStyle
314, int                               nWeight
315, bool                              bUnderlined
316, const wxString&                   rsFaceName
317, wxFontEncoding                    vEncoding
318)
319{
320    m_nStyle      = nStyle;
321    m_nPointSize  = nPointSize;
322    m_nFamily     = nFamily;
323    m_nStyle      = nStyle;
324    m_nWeight     = nWeight;
325    m_bUnderlined = bUnderlined;
326    m_sFaceName   = rsFaceName;
327    m_vEncoding   = vEncoding;
328    m_hFont       = 0;
329
330    m_bNativeFontInfoOk = false;
331
332    m_nFontId     = 0;
333    m_bTemporary  = false;
334    m_pFM         = (PFONTMETRICS)NULL;
335    m_hPS         = NULLHANDLE;
336    m_nNumFonts   = 0;
337} // end of wxFontRefData::Init
338
339void wxFontRefData::Init(
340  const wxNativeFontInfo&           rInfo
341, WXHFONT                           hFont //this is the FontId -- functions as the hFont for OS/2
342, WXHANDLE                          hPS   // Presentation Space we are using
343)
344{
345    //
346    // hFont may be zero, or it be passed in case we really want to
347    // use the exact font created in the underlying system
348    // (for example where we can't guarantee conversion from HFONT
349    // to LOGFONT back to HFONT)
350    //
351    m_hFont = hFont;
352    m_nFontId = (int)hFont;
353
354    m_bNativeFontInfoOk = true;
355    m_vNativeFontInfo = rInfo;
356
357    if (hPS == NULLHANDLE)
358    {
359        m_hPS = ::WinGetPS(HWND_DESKTOP);
360        m_bInternalPS = true;
361    }
362    else
363        m_hPS = (HPS)hPS;
364
365    m_nFontId     = 0;
366    m_bTemporary  = false;
367    m_pFM         = (PFONTMETRICS)NULL;
368    m_nNumFonts   = 0;
369} // end of wxFontRefData::Init
370
371wxFontRefData::~wxFontRefData()
372{
373    Free();
374}
375
376bool wxFontRefData::Alloc( wxFont* pFont )
377{
378    wxString                        sFaceName;
379    long                            flId = m_hFont;
380    long                            lRc;
381    ERRORID                         vError;
382    wxString                        sError;
383
384    if (!m_bNativeFontInfoOk)
385    {
386        wxFillLogFont( &m_vNativeFontInfo.fa
387                      ,&m_vNativeFontInfo.fn
388                      ,&m_hPS
389                      ,&m_bInternalPS
390                      ,&flId
391                      ,sFaceName
392                      ,pFont
393                     );
394        m_bNativeFontInfoOk = true;
395    }
396    else
397    {
398        if (flId == 0L)
399            flId = 1L;
400        else
401            flId++;
402        if (flId > 254)
403            flId = 1L;
404    }
405    if((lRc = ::GpiCreateLogFont( m_hPS
406                                 ,NULL
407                                 ,flId
408                                 ,&m_vNativeFontInfo.fa
409                                )) != GPI_ERROR)
410    {
411       m_hFont = (WXHFONT)flId;
412       m_nFontId = flId;
413    }
414    if (!m_hFont)
415    {
416        vError = ::WinGetLastError(vHabmain);
417        sError = wxPMErrorToStr(vError);
418        wxLogLastError(wxT("CreateFont"));
419    }
420
421    ::GpiSetCharSet(m_hPS, flId); // sets font for presentation space
422    ::GpiQueryFontMetrics(m_hPS, sizeof(FONTMETRICS), &m_vNativeFontInfo.fm);
423
424    //
425    // Set refData members with the results
426    //
427    memcpy(&m_vFattrs, &m_vNativeFontInfo.fa, sizeof(m_vFattrs));
428    memcpy(&m_vFname, &m_vNativeFontInfo.fn, sizeof(m_vFname));
429    //
430    // Going to leave the point size alone.  Mostly we use outline fonts
431    // that can be set to any point size inside of Presentation Parameters,
432    // regardless of whether or not the actual font is registered in the system.
433    // The GpiCreateLogFont will do enough by selecting the right family,
434    // and face name.
435    //
436    if (strcmp(m_vNativeFontInfo.fm.szFamilyname, "Times New Roman") == 0)
437        m_nFamily = wxROMAN;
438    else if (strcmp(m_vNativeFontInfo.fm.szFamilyname, "Times New Roman MT 30") == 0)
439        m_nFamily = wxROMAN;
440    else if (strcmp(m_vNativeFontInfo.fm.szFamilyname, "@Times New Roman MT 30") == 0)
441        m_nFamily = wxROMAN;
442    else if (strcmp(m_vNativeFontInfo.fm.szFamilyname, "Tms Rmn") == 0)
443        m_nFamily = wxROMAN;
444    else if (strcmp(m_vNativeFontInfo.fm.szFamilyname, "WarpSans") == 0)
445        m_nFamily = wxDECORATIVE;
446    else if (strcmp(m_vNativeFontInfo.fm.szFamilyname, "Helvetica") == 0)
447        m_nFamily = wxSWISS;
448    else if (strcmp(m_vNativeFontInfo.fm.szFamilyname, "Helv") == 0)
449        m_nFamily = wxSWISS;
450    else if (strcmp(m_vNativeFontInfo.fm.szFamilyname, "Script") == 0)
451        m_nFamily = wxSCRIPT;
452    else if (strcmp(m_vNativeFontInfo.fm.szFamilyname, "Courier New") == 0)
453        m_nFamily = wxTELETYPE;
454    else if (strcmp(m_vNativeFontInfo.fm.szFamilyname, "Courier") == 0)
455        m_nFamily = wxTELETYPE;
456    else if (strcmp(m_vNativeFontInfo.fm.szFamilyname, "System Monospaced") == 0)
457        m_nFamily = wxTELETYPE;
458    else if (strcmp(m_vNativeFontInfo.fm.szFamilyname, "System VIO") == 0)
459        m_nFamily = wxMODERN;
460    else if (strcmp(m_vNativeFontInfo.fm.szFamilyname, "System Proportional") == 0)
461        m_nFamily = wxMODERN;
462    else if (strcmp(m_vNativeFontInfo.fm.szFamilyname, "Arial") == 0)
463        m_nFamily = wxSWISS;
464    else if (strcmp(m_vNativeFontInfo.fm.szFamilyname, "Swiss") == 0)
465        m_nFamily = wxSWISS;
466    else
467        m_nFamily = wxSWISS;
468
469    if (m_vNativeFontInfo.fa.fsSelection & FATTR_SEL_ITALIC)
470        m_nStyle = wxFONTSTYLE_ITALIC;
471    else
472        m_nStyle = wxFONTSTYLE_NORMAL;
473    switch(m_vNativeFontInfo.fn.usWeightClass)
474    {
475        case FWEIGHT_DONT_CARE:
476            m_nWeight = wxFONTWEIGHT_NORMAL;
477            break;
478
479        case FWEIGHT_NORMAL:
480            m_nWeight = wxFONTWEIGHT_NORMAL;
481            break;
482
483        case FWEIGHT_LIGHT:
484            m_nWeight = wxFONTWEIGHT_LIGHT;
485            break;
486
487        case FWEIGHT_BOLD:
488            m_nWeight = wxFONTWEIGHT_BOLD;
489            break;
490
491        case FWEIGHT_ULTRA_BOLD:
492            m_nWeight = wxFONTWEIGHT_MAX;
493            break;
494
495        default:
496            m_nWeight = wxFONTWEIGHT_NORMAL;
497    }
498    m_bUnderlined = ((m_vNativeFontInfo.fa.fsSelection & FATTR_SEL_UNDERSCORE) != 0);
499    m_sFaceName = (wxChar*)m_vNativeFontInfo.fa.szFacename;
500    m_vEncoding = wxGetFontEncFromCharSet(m_vNativeFontInfo.fa.usCodePage);
501
502    //
503    // We don't actuall keep the font around if using a temporary PS
504    //
505    if (m_bInternalPS)
506    {
507        if(m_hFont)
508            ::GpiDeleteSetId( m_hPS
509                             ,flId
510                            );
511
512        ::WinReleasePS(m_hPS);
513    }
514    else
515        //
516        // Select the font into the Presentation space
517        //
518        ::GpiSetCharSet(m_hPS, flId); // sets font for presentation space
519    return true;
520} // end of wxFontRefData::Alloc
521
522void wxFontRefData::Free()
523{
524    if (m_pFM)
525        delete [] m_pFM;
526    m_pFM = (PFONTMETRICS)NULL;
527
528    if ( m_hFont )
529    {
530        ::GpiDeleteSetId(m_hPS, 1L); /* delete the logical font          */
531        m_nFontId = 0;
532        m_hFont   = 0;
533    }
534    if (m_bInternalPS)
535        ::WinReleasePS(m_hPS);
536    m_hPS = NULLHANDLE;
537} // end of wxFontRefData::Free
538
539// ----------------------------------------------------------------------------
540// wxNativeFontInfo
541// ----------------------------------------------------------------------------
542
543void wxNativeFontInfo::Init()
544{
545    memset(&fa, '\0', sizeof(FATTRS));
546} // end of wxNativeFontInfo::Init
547
548int wxNativeFontInfo::GetPointSize() const
549{
550    return fm.lEmHeight;
551} // end of wxNativeFontInfo::GetPointSize
552
553wxFontStyle wxNativeFontInfo::GetStyle() const
554{
555    return fa.fsSelection & FATTR_SEL_ITALIC ? wxFONTSTYLE_ITALIC : wxFONTSTYLE_NORMAL;
556} // end of wxNativeFontInfo::GetStyle
557
558wxFontWeight wxNativeFontInfo::GetWeight() const
559{
560    switch(fn.usWeightClass)
561    {
562        case FWEIGHT_DONT_CARE:
563            return wxFONTWEIGHT_NORMAL;
564
565        case FWEIGHT_NORMAL:
566            return wxFONTWEIGHT_NORMAL;
567
568        case FWEIGHT_LIGHT:
569            return wxFONTWEIGHT_LIGHT;
570
571        case FWEIGHT_BOLD:
572            return wxFONTWEIGHT_BOLD;
573
574        case FWEIGHT_ULTRA_BOLD:
575            return wxFONTWEIGHT_MAX;
576    }
577    return wxFONTWEIGHT_NORMAL;
578} // end of wxNativeFontInfo::GetWeight
579
580bool wxNativeFontInfo::GetUnderlined() const
581{
582    return ((fa.fsSelection & FATTR_SEL_UNDERSCORE) != 0);
583} // end of wxNativeFontInfo::GetUnderlined
584
585wxString wxNativeFontInfo::GetFaceName() const
586{
587    return (wxChar*)fm.szFacename;
588} // end of wxNativeFontInfo::GetFaceName
589
590wxFontFamily wxNativeFontInfo::GetFamily() const
591{
592    int                             nFamily;
593
594    //
595    // Extract family from facename
596    //
597    if (strcmp(fm.szFamilyname, "Times New Roman") == 0)
598        nFamily = wxROMAN;
599    else if (strcmp(fm.szFamilyname, "Times New Roman MT 30") == 0)
600        nFamily = wxROMAN;
601    else if (strcmp(fm.szFamilyname, "@Times New Roman MT 30") == 0)
602        nFamily = wxROMAN;
603    else if (strcmp(fm.szFamilyname, "Tms Rmn") == 0)
604        nFamily = wxROMAN;
605    else if (strcmp(fm.szFamilyname, "WarpSans") == 0)
606        nFamily = wxDECORATIVE;
607    else if (strcmp(fm.szFamilyname, "Helvetica") == 0)
608        nFamily = wxSWISS;
609    else if (strcmp(fm.szFamilyname, "Helv") == 0)
610        nFamily = wxSWISS;
611    else if (strcmp(fm.szFamilyname, "Script") == 0)
612        nFamily = wxSCRIPT;
613    else if (strcmp(fm.szFamilyname, "Courier New") == 0)
614        nFamily = wxTELETYPE;
615    else if (strcmp(fm.szFamilyname, "Courier") == 0)
616        nFamily = wxTELETYPE;
617    else if (strcmp(fm.szFamilyname, "System Monospaced") == 0)
618        nFamily = wxTELETYPE;
619    else if (strcmp(fm.szFamilyname, "System VIO") == 0)
620        nFamily = wxMODERN;
621    else if (strcmp(fm.szFamilyname, "System Proportional") == 0)
622        nFamily = wxMODERN;
623    else if (strcmp(fm.szFamilyname, "Arial") == 0)
624        nFamily = wxSWISS;
625    else if (strcmp(fm.szFamilyname, "Swiss") == 0)
626        nFamily = wxSWISS;
627    else
628        nFamily = wxSWISS;
629    return (wxFontFamily)nFamily;
630} // end of wxNativeFontInfo::GetFamily
631
632wxFontEncoding wxNativeFontInfo::GetEncoding() const
633{
634    return wxGetFontEncFromCharSet(fa.usCodePage);
635} // end of wxNativeFontInfo::GetEncoding
636
637void wxNativeFontInfo::SetPointSize(
638  int                               nPointsize
639)
640{
641    fm.lEmHeight = (LONG)nPointsize;
642} // end of wxNativeFontInfo::SetPointSize
643
644void wxNativeFontInfo::SetStyle(
645  wxFontStyle                       eStyle
646)
647{
648    switch (eStyle)
649    {
650        default:
651            wxFAIL_MSG( _T("unknown font style") );
652            // fall through
653
654        case wxFONTSTYLE_NORMAL:
655            break;
656
657        case wxFONTSTYLE_ITALIC:
658        case wxFONTSTYLE_SLANT:
659            fa.fsSelection |= FATTR_SEL_ITALIC;
660            break;
661    }
662} // end of wxNativeFontInfo::SetStyle
663
664void wxNativeFontInfo::SetWeight(
665  wxFontWeight                      eWeight
666)
667{
668    switch (eWeight)
669    {
670        default:
671            wxFAIL_MSG( _T("unknown font weight") );
672            // fall through
673
674        case wxFONTWEIGHT_NORMAL:
675            fn.usWeightClass = FWEIGHT_NORMAL;
676            break;
677
678        case wxFONTWEIGHT_LIGHT:
679            fn.usWeightClass = FWEIGHT_LIGHT;
680            break;
681
682        case wxFONTWEIGHT_BOLD:
683            fn.usWeightClass = FWEIGHT_BOLD;
684            break;
685    }
686} // end of wxNativeFontInfo::SetWeight
687
688void wxNativeFontInfo::SetUnderlined(
689  bool                              bUnderlined
690)
691{
692    if(bUnderlined)
693        fa.fsSelection |= FATTR_SEL_UNDERSCORE;
694} // end of wxNativeFontInfo::SetUnderlined
695
696bool wxNativeFontInfo::SetFaceName(
697  const wxString&                   sFacename
698)
699{
700    wxStrncpy((wxChar*)fa.szFacename, sFacename, WXSIZEOF(fa.szFacename));
701    return true;
702} // end of wxNativeFontInfo::SetFaceName
703
704void wxNativeFontInfo::SetFamily(
705  wxFontFamily                      eFamily
706)
707{
708    wxString                        sFacename;
709
710    switch (eFamily)
711    {
712        case wxSCRIPT:
713            sFacename = wxT("Tms Rmn");
714            break;
715
716        case wxDECORATIVE:
717            sFacename = wxT("WarpSans");
718            break;
719
720        case wxROMAN:
721            sFacename = wxT("Tms Rmn");
722            break;
723
724        case wxTELETYPE:
725            sFacename = wxT("Courier") ;
726            break;
727
728        case wxMODERN:
729            sFacename = wxT("System VIO") ;
730            break;
731
732        case wxSWISS:
733            sFacename = wxT("Helv") ;
734            break;
735
736        case wxDEFAULT:
737        default:
738            sFacename = wxT("System VIO") ;
739    }
740
741    if (!wxStrlen((wxChar*)fa.szFacename) )
742    {
743        SetFaceName(sFacename);
744    }
745} // end of wxNativeFontInfo::SetFamily
746
747void wxNativeFontInfo::SetEncoding( wxFontEncoding eEncoding )
748{
749    wxNativeEncodingInfo            vInfo;
750
751    if ( !wxGetNativeFontEncoding( eEncoding
752                                  ,&vInfo
753                                 ))
754    {
755        if (wxFontMapper::Get()->GetAltForEncoding( eEncoding
756                                               ,&vInfo
757                                              ))
758        {
759            if (!vInfo.facename.empty())
760            {
761                //
762                // If we have this encoding only in some particular facename, use
763                // the facename - it is better to show the correct characters in a
764                // wrong facename than unreadable text in a correct one
765                //
766                SetFaceName(vInfo.facename);
767            }
768        }
769        else
770        {
771            // unsupported encoding, replace with the default
772            vInfo.charset = 850;
773        }
774    }
775    fa.usCodePage = (USHORT)vInfo.charset;
776} // end of wxNativeFontInfo::SetFaceName
777
778bool wxNativeFontInfo::FromString( const wxString& rsStr )
779{
780    long                            lVal;
781
782    wxStringTokenizer               vTokenizer(rsStr, _T(";"));
783
784    //
785    // First the version
786    //
787    wxString                        sToken = vTokenizer.GetNextToken();
788
789    if (sToken != _T('0'))
790        return false;
791
792    sToken = vTokenizer.GetNextToken();
793    if (!sToken.ToLong(&lVal))
794        return false;
795    fm.lEmHeight = lVal;
796
797    sToken = vTokenizer.GetNextToken();
798    if (!sToken.ToLong(&lVal))
799        return false;
800    fa.lAveCharWidth = lVal;
801
802    sToken = vTokenizer.GetNextToken();
803    if (!sToken.ToLong(&lVal))
804        return false;
805    fa.fsSelection = (USHORT)lVal;
806
807    sToken = vTokenizer.GetNextToken();
808    if (!sToken.ToLong(&lVal))
809        return false;
810    fa.fsType = (USHORT)lVal;
811
812    sToken = vTokenizer.GetNextToken();
813    if (!sToken.ToLong(&lVal))
814        return false;
815    fa.fsFontUse = (USHORT)lVal;
816
817    sToken = vTokenizer.GetNextToken();
818    if (!sToken.ToLong(&lVal))
819        return false;
820    fa.idRegistry = (USHORT)lVal;
821
822    sToken = vTokenizer.GetNextToken();
823    if (!sToken.ToLong(&lVal))
824        return false;
825    fa.usCodePage = (USHORT)lVal;
826
827    sToken = vTokenizer.GetNextToken();
828    if (!sToken.ToLong(&lVal))
829        return false;
830    fa.lMatch = lVal;
831
832    sToken = vTokenizer.GetNextToken();
833    if (!sToken.ToLong(&lVal))
834        return false;
835    fn.usWeightClass = (USHORT)lVal;
836
837    sToken = vTokenizer.GetNextToken();
838    if(!sToken)
839        return false;
840    wxStrcpy((wxChar*)fa.szFacename, sToken.c_str());
841    return true;
842} // end of wxNativeFontInfo::FromString
843
844wxString wxNativeFontInfo::ToString() const
845{
846    wxString sStr;
847
848    sStr.Printf(_T("%d;%ld;%ld;%ld;%d;%d;%d;%d;%d;%ld;%d;%s"),
849                0, // version, in case we want to change the format later
850                fm.lEmHeight,
851                fa.lAveCharWidth,
852                fa.lMaxBaselineExt,
853                fa.fsSelection,
854                fa.fsType,
855                fa.fsFontUse,
856                fa.idRegistry,
857                fa.usCodePage,
858                fa.lMatch,
859                fn.usWeightClass,
860                fa.szFacename);
861    return sStr;
862} // end of wxNativeFontInfo::ToString
863
864// ----------------------------------------------------------------------------
865// wxFont
866// ----------------------------------------------------------------------------
867
868bool wxFont::Create( const wxNativeFontInfo& rInfo,
869                     WXHFONT hFont )
870{
871    UnRef();
872    m_refData = new wxFontRefData( rInfo
873                                  ,hFont
874                                 );
875    RealizeResource();
876    return true;
877} // end of wxFont::Create
878
879wxFont::wxFont(
880  const wxString&                   rsFontdesc
881)
882{
883    wxNativeFontInfo                vInfo;
884
885    if (vInfo.FromString(rsFontdesc))
886        (void)Create(vInfo);
887} // end of wxFont::wxFont
888
889// ----------------------------------------------------------------------------
890// Constructor for a font. Note that the real construction is done
891// in wxDC::SetFont, when information is available about scaling etc.
892// ----------------------------------------------------------------------------
893bool wxFont::Create( int             nPointSize,
894                     int             nFamily,
895                     int             nStyle,
896                     int             nWeight,
897                     bool            bUnderlined,
898                     const wxString& rsFaceName,
899                     wxFontEncoding  vEncoding )
900{
901    UnRef();
902
903    //
904    // wxDEFAULT is a valid value for the font size too so we must treat it
905    // specially here (otherwise the size would be 70 == wxDEFAULT value)
906    //
907    if (nPointSize == wxDEFAULT)
908    {
909        nPointSize = wxNORMAL_FONT->GetPointSize();
910    }
911    m_refData = new wxFontRefData( nPointSize
912                                  ,nFamily
913                                  ,nStyle
914                                  ,nWeight
915                                  ,bUnderlined
916                                  ,rsFaceName
917                                  ,vEncoding
918                                 );
919    RealizeResource();
920    return true;
921} // end of wxFont::Create
922
923wxFont::~wxFont()
924{
925} // end of wxFont::~wxFont
926
927// ----------------------------------------------------------------------------
928// real implementation
929// Boris' Kovalenko comments:
930//   Because OS/2 fonts are associated with PS we can not create the font
931//   here, but we may check that font definition is true
932// ----------------------------------------------------------------------------
933
934bool wxFont::RealizeResource()
935{
936    if ( GetResourceHandle() )
937    {
938        return true;
939    }
940    return M_FONTDATA->Alloc(this);
941} // end of wxFont::RealizeResource
942
943bool wxFont::FreeResource( bool WXUNUSED(bForce) )
944{
945    if (GetResourceHandle())
946    {
947        M_FONTDATA->Free();
948        return true;
949    }
950    return false;
951} // end of wxFont::FreeResource
952
953WXHANDLE wxFont::GetResourceHandle() const
954{
955    return GetHFONT();
956} // end of wxFont::GetResourceHandle
957
958WXHFONT wxFont::GetHFONT() const
959{
960    return M_FONTDATA ? M_FONTDATA->GetHFONT() : 0;
961} // end of wxFont::GetHFONT
962
963bool wxFont::IsFree() const
964{
965    return M_FONTDATA && (M_FONTDATA->GetHFONT() == 0);
966} // end of wxFont::IsFree
967
968void wxFont::Unshare()
969{
970    // Don't change shared data
971    if ( !m_refData )
972    {
973        m_refData = new wxFontRefData();
974    }
975    else
976    {
977        wxFontRefData* ref = new wxFontRefData(*M_FONTDATA);
978        UnRef();
979        m_refData = ref;
980    }
981} // end of wxFont::Unshare
982
983// ----------------------------------------------------------------------------
984// change font attribute: we recreate font when doing it
985// ----------------------------------------------------------------------------
986
987void wxFont::SetPointSize(
988  int                               nPointSize
989)
990{
991    Unshare();
992
993    M_FONTDATA->SetPointSize(nPointSize);
994
995    RealizeResource();
996} // end of wxFont::SetPointSize
997
998void wxFont::SetFamily(
999  int                               nFamily
1000)
1001{
1002    Unshare();
1003
1004    M_FONTDATA->SetFamily(nFamily);
1005
1006    RealizeResource();
1007} // end of wxFont::SetFamily
1008
1009void wxFont::SetStyle(
1010  int                               nStyle
1011)
1012{
1013    Unshare();
1014
1015    M_FONTDATA->SetStyle(nStyle);
1016
1017    RealizeResource();
1018} // end of wxFont::SetStyle
1019
1020void wxFont::SetWeight(
1021  int                               nWeight
1022)
1023{
1024    Unshare();
1025
1026    M_FONTDATA->SetWeight(nWeight);
1027
1028    RealizeResource();
1029} // end of wxFont::SetWeight
1030
1031bool wxFont::SetFaceName(
1032  const wxString&                   rsFaceName
1033)
1034{
1035    Unshare();
1036
1037    bool refdataok = M_FONTDATA->SetFaceName(rsFaceName);
1038
1039    RealizeResource();
1040
1041    return refdataok && wxFontBase::SetFaceName(rsFaceName);
1042} // end of wxFont::SetFaceName
1043
1044void wxFont::SetUnderlined(
1045  bool                              bUnderlined
1046)
1047{
1048    Unshare();
1049
1050    M_FONTDATA->SetUnderlined(bUnderlined);
1051
1052    RealizeResource();
1053} // end of wxFont::SetUnderlined
1054
1055void wxFont::SetEncoding(
1056  wxFontEncoding                    vEncoding
1057)
1058{
1059    Unshare();
1060
1061    M_FONTDATA->SetEncoding(vEncoding);
1062
1063    RealizeResource();
1064} // end of wxFont::SetEncoding
1065
1066void wxFont::DoSetNativeFontInfo(
1067  const wxNativeFontInfo&           rInfo
1068)
1069{
1070    Unshare();
1071
1072    FreeResource();
1073
1074    *M_FONTDATA = wxFontRefData(rInfo);
1075
1076    RealizeResource();
1077}
1078
1079// ----------------------------------------------------------------------------
1080// accessors
1081// ----------------------------------------------------------------------------
1082
1083int wxFont::GetPointSize() const
1084{
1085    wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
1086
1087    return M_FONTDATA->GetPointSize();
1088} // end of wxFont::GetPointSize
1089
1090int wxFont::GetFamily() const
1091{
1092    wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
1093
1094    return M_FONTDATA->GetFamily();
1095} // end of wxFont::GetFamily
1096
1097int wxFont::GetStyle() const
1098{
1099    wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
1100
1101    return M_FONTDATA->GetStyle();
1102} // end of wxFont::GetStyle
1103
1104int wxFont::GetWeight() const
1105{
1106    wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
1107
1108    return M_FONTDATA->GetWeight();
1109}
1110
1111bool wxFont::GetUnderlined() const
1112{
1113    wxCHECK_MSG( Ok(), false, wxT("invalid font") );
1114
1115    return M_FONTDATA->GetUnderlined();
1116} // end of wxFont::GetUnderlined
1117
1118wxString wxFont::GetFaceName() const
1119{
1120    wxCHECK_MSG( Ok(), wxEmptyString, wxT("invalid font") );
1121
1122    return M_FONTDATA->GetFaceName();
1123} // end of wxFont::GetFaceName
1124
1125wxFontEncoding wxFont::GetEncoding() const
1126{
1127    wxCHECK_MSG( Ok(), wxFONTENCODING_DEFAULT, wxT("invalid font") );
1128
1129    return M_FONTDATA->GetEncoding();
1130} // end of wxFont::GetEncoding
1131
1132const wxNativeFontInfo* wxFont::GetNativeFontInfo() const
1133{
1134    return M_FONTDATA->HasNativeFontInfo() ? &(M_FONTDATA->GetNativeFontInfo())
1135                                           : NULL;
1136} // end of wxFont::GetNativeFontInfo
1137
1138//
1139// Internal use only method to set the FONTMETRICS array
1140//
1141void wxFont::SetFM( PFONTMETRICS pFM, int nNumFonts )
1142{
1143    M_FONTDATA->SetFM(pFM);
1144    M_FONTDATA->SetNumFonts(nNumFonts);
1145} // end of wxFont::SetFM
1146
1147
1148void wxFont::SetPS( HPS hPS )
1149{
1150    Unshare();
1151
1152    M_FONTDATA->SetPS(hPS);
1153
1154    RealizeResource();
1155} // end of wxFont::SetPS
1156