1///////////////////////////////////////////////////////////////////////////////
2// Name:        src/msw/fontenum.cpp
3// Purpose:     wxFontEnumerator class for Windows
4// Author:      Julian Smart
5// Modified by: Vadim Zeitlin to add support for font encodings
6// Created:     04/01/98
7// RCS-ID:      $Id: fontenum.cpp 47549 2007-07-18 15:03:10Z VS $
8// Copyright:   (c) Julian Smart
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#if wxUSE_FONTMAP
28
29#ifndef WX_PRECOMP
30    #include "wx/gdicmn.h"
31    #include "wx/font.h"
32    #include "wx/encinfo.h"
33    #include "wx/dynarray.h"
34#endif
35
36#include "wx/msw/private.h"
37
38#include "wx/fontutil.h"
39#include "wx/fontenum.h"
40#include "wx/fontmap.h"
41
42// ----------------------------------------------------------------------------
43// private classes
44// ----------------------------------------------------------------------------
45
46// the helper class which calls ::EnumFontFamilies() and whose OnFont() is
47// called from the callback passed to this function and, in its turn, calls the
48// appropariate wxFontEnumerator method
49class wxFontEnumeratorHelper
50{
51public:
52    wxFontEnumeratorHelper(wxFontEnumerator *fontEnum);
53
54    // control what exactly are we enumerating
55        // we enumerate fonts with given enocding
56    bool SetEncoding(wxFontEncoding encoding);
57        // we enumerate fixed-width fonts
58    void SetFixedOnly(bool fixedOnly) { m_fixedOnly = fixedOnly; }
59        // we enumerate the encodings available in this family
60    void SetFamily(const wxString& family);
61
62    // call to start enumeration
63    void DoEnumerate();
64
65    // called by our font enumeration proc
66    bool OnFont(const LPLOGFONT lf, const LPTEXTMETRIC tm) const;
67
68private:
69    // the object we forward calls to OnFont() to
70    wxFontEnumerator *m_fontEnum;
71
72    // if != -1, enum only fonts which have this encoding
73    int m_charset;
74
75    // if not empty, enum only the fonts with this facename
76    wxString m_facename;
77
78    // if not empty, enum only the fonts in this family
79    wxString m_family;
80
81    // if true, enum only fixed fonts
82    bool m_fixedOnly;
83
84    // if true, we enumerate the encodings, not fonts
85    bool m_enumEncodings;
86
87    // the list of charsets we already found while enumerating charsets
88    wxArrayInt m_charsets;
89
90    // the list of facenames we already found while enumerating facenames
91    wxArrayString m_facenames;
92
93    DECLARE_NO_COPY_CLASS(wxFontEnumeratorHelper)
94};
95
96// ----------------------------------------------------------------------------
97// private functions
98// ----------------------------------------------------------------------------
99
100#ifndef __WXMICROWIN__
101int CALLBACK wxFontEnumeratorProc(LPLOGFONT lplf, LPTEXTMETRIC lptm,
102                                  DWORD dwStyle, LONG lParam);
103#endif
104
105// ============================================================================
106// implementation
107// ============================================================================
108
109// ----------------------------------------------------------------------------
110// wxFontEnumeratorHelper
111// ----------------------------------------------------------------------------
112
113wxFontEnumeratorHelper::wxFontEnumeratorHelper(wxFontEnumerator *fontEnum)
114{
115    m_fontEnum = fontEnum;
116    m_charset = DEFAULT_CHARSET;
117    m_fixedOnly = false;
118    m_enumEncodings = false;
119}
120
121void wxFontEnumeratorHelper::SetFamily(const wxString& family)
122{
123    m_enumEncodings = true;
124    m_family = family;
125}
126
127bool wxFontEnumeratorHelper::SetEncoding(wxFontEncoding encoding)
128{
129    if ( encoding != wxFONTENCODING_SYSTEM )
130    {
131        wxNativeEncodingInfo info;
132        if ( !wxGetNativeFontEncoding(encoding, &info) )
133        {
134#if wxUSE_FONTMAP
135            if ( !wxFontMapper::Get()->GetAltForEncoding(encoding, &info) )
136#endif // wxUSE_FONTMAP
137            {
138                // no such encodings at all
139                return false;
140            }
141        }
142
143        m_charset = info.charset;
144        m_facename = info.facename;
145    }
146
147    return true;
148}
149
150#if defined(__GNUWIN32__) && !defined(__CYGWIN10__) && !wxCHECK_W32API_VERSION( 1, 1 ) && !wxUSE_NORLANDER_HEADERS
151    #define wxFONTENUMPROC int(*)(ENUMLOGFONTEX *, NEWTEXTMETRICEX*, int, LPARAM)
152#else
153    #define wxFONTENUMPROC FONTENUMPROC
154#endif
155
156void wxFontEnumeratorHelper::DoEnumerate()
157{
158#ifndef __WXMICROWIN__
159    HDC hDC = ::GetDC(NULL);
160
161#ifdef __WXWINCE__
162    ::EnumFontFamilies(hDC,
163                       m_facename.empty() ? NULL : m_facename.c_str(),
164                       (wxFONTENUMPROC)wxFontEnumeratorProc,
165                       (LPARAM)this) ;
166#else // __WIN32__
167    LOGFONT lf;
168    lf.lfCharSet = (BYTE)m_charset;
169    wxStrncpy(lf.lfFaceName, m_facename, WXSIZEOF(lf.lfFaceName));
170    lf.lfPitchAndFamily = 0;
171    ::EnumFontFamiliesEx(hDC, &lf, (wxFONTENUMPROC)wxFontEnumeratorProc,
172                         (LPARAM)this, 0 /* reserved */) ;
173#endif // Win32/CE
174
175    ::ReleaseDC(NULL, hDC);
176#endif
177}
178
179bool wxFontEnumeratorHelper::OnFont(const LPLOGFONT lf,
180                                    const LPTEXTMETRIC tm) const
181{
182    if ( m_enumEncodings )
183    {
184        // is this a new charset?
185        int cs = lf->lfCharSet;
186        if ( m_charsets.Index(cs) == wxNOT_FOUND )
187        {
188            wxConstCast(this, wxFontEnumeratorHelper)->m_charsets.Add(cs);
189
190            wxFontEncoding enc = wxGetFontEncFromCharSet(cs);
191            return m_fontEnum->OnFontEncoding(lf->lfFaceName,
192                                              wxFontMapper::GetEncodingName(enc));
193        }
194        else
195        {
196            // continue enumeration
197            return true;
198        }
199    }
200
201    if ( m_fixedOnly )
202    {
203        // check that it's a fixed pitch font (there is *no* error here, the
204        // flag name is misleading!)
205        if ( tm->tmPitchAndFamily & TMPF_FIXED_PITCH )
206        {
207            // not a fixed pitch font
208            return true;
209        }
210    }
211
212    if ( m_charset != DEFAULT_CHARSET )
213    {
214        // check that we have the right encoding
215        if ( lf->lfCharSet != m_charset )
216        {
217            return true;
218        }
219    }
220    else // enumerating fonts in all charsets
221    {
222        // we can get the same facename twice or more in this case because it
223        // may exist in several charsets but we only want to return one copy of
224        // it (note that this can't happen for m_charset != DEFAULT_CHARSET)
225        if ( m_facenames.Index(lf->lfFaceName) != wxNOT_FOUND )
226        {
227            // continue enumeration
228            return true;
229        }
230
231        wxConstCast(this, wxFontEnumeratorHelper)->
232            m_facenames.Add(lf->lfFaceName);
233    }
234
235    return m_fontEnum->OnFacename(lf->lfFaceName);
236}
237
238// ----------------------------------------------------------------------------
239// wxFontEnumerator
240// ----------------------------------------------------------------------------
241
242bool wxFontEnumerator::EnumerateFacenames(wxFontEncoding encoding,
243                                          bool fixedWidthOnly)
244{
245    wxFontEnumeratorHelper fe(this);
246    if ( fe.SetEncoding(encoding) )
247    {
248        fe.SetFixedOnly(fixedWidthOnly);
249
250        fe.DoEnumerate();
251    }
252    // else: no such fonts, unknown encoding
253
254    return true;
255}
256
257bool wxFontEnumerator::EnumerateEncodings(const wxString& family)
258{
259    wxFontEnumeratorHelper fe(this);
260    fe.SetFamily(family);
261    fe.DoEnumerate();
262
263    return true;
264}
265
266// ----------------------------------------------------------------------------
267// Windows callbacks
268// ----------------------------------------------------------------------------
269
270#ifndef __WXMICROWIN__
271int CALLBACK wxFontEnumeratorProc(LPLOGFONT lplf, LPTEXTMETRIC lptm,
272                                  DWORD WXUNUSED(dwStyle), LONG lParam)
273{
274
275    // we used to process TrueType fonts only, but there doesn't seem to be any
276    // reasons to restrict ourselves to them here
277#if 0
278    // Get rid of any fonts that we don't want...
279    if ( dwStyle != TRUETYPE_FONTTYPE )
280    {
281        // continue enumeration
282        return TRUE;
283    }
284#endif // 0
285
286    wxFontEnumeratorHelper *fontEnum = (wxFontEnumeratorHelper *)lParam;
287
288    return fontEnum->OnFont(lplf, lptm);
289}
290#endif
291
292#endif // wxUSE_FONTMAP
293