home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / unix / fontutil.cpp < prev    next >
C/C++ Source or Header  |  2002-11-09  |  36KB  |  1,217 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        unix/fontutil.cpp
  3. // Purpose:     Font helper functions for X11 (GDK/X)
  4. // Author:      Vadim Zeitlin
  5. // Modified by:
  6. // Created:     05.11.99
  7. // RCS-ID:      $Id: fontutil.cpp,v 1.34.2.3 2002/11/09 15:20:40 RR Exp $
  8. // Copyright:   (c) Vadim Zeitlin
  9. // Licence:     wxWindows license
  10. /////////////////////////////////////////////////////////////////////////////
  11.  
  12. // ============================================================================
  13. // declarations
  14. // ============================================================================
  15.  
  16. // ----------------------------------------------------------------------------
  17. // headers
  18. // ----------------------------------------------------------------------------
  19.  
  20. #ifdef __GNUG__
  21.     #pragma implementation "fontutil.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. #endif // PCH
  33.  
  34. #include "wx/fontutil.h"
  35. #include "wx/fontmap.h"
  36. #include "wx/tokenzr.h"
  37. #include "wx/hash.h"
  38. #include "wx/module.h"
  39.  
  40. #if wxUSE_PANGO
  41.  
  42. #include "pango/pango.h"
  43.  
  44. #ifdef __WXGTK20__
  45. #include "wx/gtk/private.h"
  46. #else
  47. #include "wx/x11/private.h"
  48. #endif
  49.  
  50. // ----------------------------------------------------------------------------
  51. // wxNativeFontInfo
  52. // ----------------------------------------------------------------------------
  53.  
  54. void wxNativeFontInfo::Init()
  55. {
  56.     description = NULL;
  57. }
  58.  
  59. int wxNativeFontInfo::GetPointSize() const
  60. {
  61.     return pango_font_description_get_size( description ) / PANGO_SCALE;
  62. }
  63.  
  64. wxFontStyle wxNativeFontInfo::GetStyle() const
  65. {
  66.     wxFontStyle m_style = wxFONTSTYLE_NORMAL;
  67.  
  68.     switch (pango_font_description_get_style( description ))
  69.     {
  70.         case PANGO_STYLE_NORMAL:
  71.             m_style = wxFONTSTYLE_NORMAL;
  72.             break;
  73.         case PANGO_STYLE_ITALIC:
  74.             m_style = wxFONTSTYLE_ITALIC;
  75.             break;
  76.         case PANGO_STYLE_OBLIQUE:
  77.             m_style = wxFONTSTYLE_SLANT;
  78.             break;
  79.     }
  80.  
  81.     return m_style;
  82. }
  83.  
  84. wxFontWeight wxNativeFontInfo::GetWeight() const
  85. {
  86.     wxFontWeight m_weight = wxFONTWEIGHT_NORMAL;
  87.  
  88.     switch (pango_font_description_get_weight( description ))
  89.     {
  90.         case PANGO_WEIGHT_ULTRALIGHT:
  91.             m_weight = wxFONTWEIGHT_LIGHT;
  92.             break;
  93.         case PANGO_WEIGHT_LIGHT:
  94.             m_weight = wxFONTWEIGHT_LIGHT;
  95.             break;
  96.         case PANGO_WEIGHT_NORMAL:
  97.             m_weight = wxFONTWEIGHT_NORMAL;
  98.             break;
  99.         case PANGO_WEIGHT_BOLD:
  100.             m_weight = wxFONTWEIGHT_BOLD;
  101.             break;
  102.         case PANGO_WEIGHT_ULTRABOLD:
  103.             m_weight = wxFONTWEIGHT_BOLD;
  104.             break;
  105.         case PANGO_WEIGHT_HEAVY:
  106.             m_weight = wxFONTWEIGHT_BOLD;
  107.             break;
  108.     }
  109.  
  110.     return m_weight;
  111. }
  112.  
  113. bool wxNativeFontInfo::GetUnderlined() const
  114. {
  115.     return FALSE;
  116. }
  117.  
  118. wxString wxNativeFontInfo::GetFaceName() const
  119. {
  120.     wxString tmp = wxGTK_CONV_BACK( pango_font_description_get_family( description ) );
  121.  
  122.     return tmp;
  123. }
  124.  
  125. wxFontFamily wxNativeFontInfo::GetFamily() const
  126. {
  127.     return wxFONTFAMILY_SWISS;
  128. }
  129.  
  130. wxFontEncoding wxNativeFontInfo::GetEncoding() const
  131. {
  132.     return wxFONTENCODING_SYSTEM;
  133. }
  134.  
  135. bool wxNativeFontInfo::FromString(const wxString& s)
  136. {
  137.     if (description)
  138.         pango_font_description_free( description );
  139.  
  140.     description = pango_font_description_from_string( wxGTK_CONV( s ) );
  141.  
  142.     return TRUE;
  143. }
  144.  
  145. wxString wxNativeFontInfo::ToString() const
  146. {
  147.     wxString tmp = wxGTK_CONV_BACK( pango_font_description_to_string( description ) );
  148.  
  149.     return tmp;
  150. }
  151.  
  152. bool wxNativeFontInfo::FromUserString(const wxString& s)
  153. {
  154.     return FromString( s );
  155. }
  156.  
  157. wxString wxNativeFontInfo::ToUserString() const
  158. {
  159.     return ToString();
  160. }
  161.  
  162. // ----------------------------------------------------------------------------
  163. // wxNativeEncodingInfo
  164. // ----------------------------------------------------------------------------
  165.  
  166. bool wxNativeEncodingInfo::FromString(const wxString& s)
  167. {
  168.     return FALSE;
  169. }
  170.  
  171. wxString wxNativeEncodingInfo::ToString() const
  172. {
  173.     return wxEmptyString;
  174. }
  175.  
  176. bool wxTestFontEncoding(const wxNativeEncodingInfo& info)
  177. {
  178.     return TRUE;
  179. }
  180.  
  181. bool wxGetNativeFontEncoding(wxFontEncoding encoding,
  182.                              wxNativeEncodingInfo *info)
  183. {
  184.     return FALSE;
  185. }
  186.  
  187. #else // GTK+ 1.x
  188.  
  189. #ifdef __X__
  190.     #ifdef __VMS__
  191.         #pragma message disable nosimpint
  192.     #endif
  193.  
  194.     #include <X11/Xlib.h>
  195.  
  196.     #ifdef __VMS__
  197.         #pragma message enable nosimpint
  198.     #endif
  199.  
  200.     #include "wx/utils.h"       // for wxGetDisplay()
  201. #elif defined(__WXGTK__)
  202.     // we have to declare struct tm to avoid problems with first forward
  203.     // declaring it in C code (glib.h included from gdk.h does it) and then
  204.     // defining it when time.h is included from the headers below - this is
  205.     // known not to work at least with Sun CC 6.01
  206.     #include <time.h>
  207.  
  208.     #include <gdk/gdk.h>
  209. #endif
  210.  
  211.  
  212. // ----------------------------------------------------------------------------
  213. // private data
  214. // ----------------------------------------------------------------------------
  215.  
  216. static wxHashTable *g_fontHash = (wxHashTable*) NULL;
  217.  
  218. // ----------------------------------------------------------------------------
  219. // private functions
  220. // ----------------------------------------------------------------------------
  221.  
  222. // define the functions to create and destroy native fonts for this toolkit
  223. #ifdef __X__
  224.     wxNativeFont wxLoadFont(const wxString& fontSpec)
  225.     {
  226.         return XLoadQueryFont((Display *)wxGetDisplay(), fontSpec);
  227.     }
  228.  
  229.     inline void wxFreeFont(wxNativeFont font)
  230.     {
  231.         XFreeFont((Display *)wxGetDisplay(), (XFontStruct *)font);
  232.     }
  233. #elif defined(__WXGTK__)
  234.     wxNativeFont wxLoadFont(const wxString& fontSpec)
  235.     {
  236.        return gdk_font_load( wxConvertWX2MB(fontSpec) );
  237.     }
  238.  
  239.     inline void wxFreeFont(wxNativeFont font)
  240.     {
  241.         gdk_font_unref(font);
  242.     }
  243. #else
  244.     #error "Unknown GUI toolkit"
  245. #endif
  246.  
  247. static bool wxTestFontSpec(const wxString& fontspec);
  248.  
  249. static wxNativeFont wxLoadQueryFont(int pointSize,
  250.                                     int family,
  251.                                     int style,
  252.                                     int weight,
  253.                                     bool underlined,
  254.                                     const wxString& facename,
  255.                                     const wxString& xregistry,
  256.                                     const wxString& xencoding,
  257.                                     wxString* xFontName);
  258.  
  259. // ============================================================================
  260. // implementation
  261. // ============================================================================
  262.  
  263. // ----------------------------------------------------------------------------
  264. // wxNativeEncodingInfo
  265. // ----------------------------------------------------------------------------
  266.  
  267. // convert to/from the string representation: format is
  268. //      encodingid;registry;encoding[;facename]
  269. bool wxNativeEncodingInfo::FromString(const wxString& s)
  270. {
  271.     // use ";", not "-" because it may be part of encoding name
  272.     wxStringTokenizer tokenizer(s, _T(";"));
  273.  
  274.     wxString encid = tokenizer.GetNextToken();
  275.     long enc;
  276.     if ( !encid.ToLong(&enc) )
  277.         return FALSE;
  278.     encoding = (wxFontEncoding)enc;
  279.  
  280.     xregistry = tokenizer.GetNextToken();
  281.     if ( !xregistry )
  282.         return FALSE;
  283.  
  284.     xencoding = tokenizer.GetNextToken();
  285.     if ( !xencoding )
  286.         return FALSE;
  287.  
  288.     // ok even if empty
  289.     facename = tokenizer.GetNextToken();
  290.  
  291.     return TRUE;
  292. }
  293.  
  294. wxString wxNativeEncodingInfo::ToString() const
  295. {
  296.     wxString s;
  297.     s << (long)encoding << _T(';') << xregistry << _T(';') << xencoding;
  298.     if ( !!facename )
  299.     {
  300.         s << _T(';') << facename;
  301.     }
  302.  
  303.     return s;
  304. }
  305.  
  306. // ----------------------------------------------------------------------------
  307. // wxNativeFontInfo
  308. // ----------------------------------------------------------------------------
  309.  
  310. void wxNativeFontInfo::Init()
  311. {
  312.     m_isDefault = TRUE;
  313. }
  314.  
  315. bool wxNativeFontInfo::FromString(const wxString& s)
  316. {
  317.     wxStringTokenizer tokenizer(s, _T(";"));
  318.  
  319.     // check the version
  320.     wxString token = tokenizer.GetNextToken();
  321.     if ( token != _T('0') )
  322.         return FALSE;
  323.  
  324.     xFontName = tokenizer.GetNextToken();
  325.  
  326.     // this should be the end
  327.     if ( tokenizer.HasMoreTokens() )
  328.         return FALSE;
  329.  
  330.     return FromXFontName(xFontName);
  331. }
  332.  
  333. wxString wxNativeFontInfo::ToString() const
  334. {
  335.     // 0 is the version
  336.     return wxString::Format(_T("%d;%s"), 0, GetXFontName().c_str());
  337. }
  338.  
  339. bool wxNativeFontInfo::FromUserString(const wxString& s)
  340. {
  341.     return FromXFontName(s);
  342. }
  343.  
  344. wxString wxNativeFontInfo::ToUserString() const
  345. {
  346.     return GetXFontName();
  347. }
  348.  
  349. bool wxNativeFontInfo::HasElements() const
  350. {
  351.     // we suppose that the foundry is never empty, so if it is it means that we
  352.     // had never parsed the XLFD
  353.     return !fontElements[0].empty();
  354. }
  355.  
  356. wxString wxNativeFontInfo::GetXFontComponent(wxXLFDField field) const
  357. {
  358.     wxCHECK_MSG( field < wxXLFD_MAX, _T(""), _T("invalid XLFD field") );
  359.  
  360.     if ( !HasElements() )
  361.     {
  362.         // const_cast
  363.         if ( !((wxNativeFontInfo *)this)->FromXFontName(xFontName) )
  364.             return _T("");
  365.     }
  366.  
  367.     return fontElements[field];
  368. }
  369.  
  370. bool wxNativeFontInfo::FromXFontName(const wxString& fontname)
  371. {
  372.     // TODO: we should be able to handle the font aliases here, but how?
  373.     wxStringTokenizer tokenizer(fontname, _T("-"));
  374.  
  375.     // skip the leading, usually empty field (font name registry)
  376.     if ( !tokenizer.HasMoreTokens() )
  377.         return FALSE;
  378.  
  379.     (void)tokenizer.GetNextToken();
  380.  
  381.     for ( size_t n = 0; n < WXSIZEOF(fontElements); n++ )
  382.     {
  383.         if ( !tokenizer.HasMoreTokens() )
  384.         {
  385.             // not enough elements in the XLFD - or maybe an alias
  386.             return FALSE;
  387.         }
  388.  
  389.         fontElements[n] = tokenizer.GetNextToken();
  390.     }
  391.  
  392.     // this should be all
  393.     if ( tokenizer.HasMoreTokens() )
  394.         return FALSE;
  395.  
  396.     // we're initialized now
  397.     m_isDefault = FALSE;
  398.  
  399.     return TRUE;
  400. }
  401.  
  402. wxString wxNativeFontInfo::GetXFontName() const
  403. {
  404.     if ( xFontName.empty() )
  405.     {
  406.         for ( size_t n = 0; n < WXSIZEOF(fontElements); n++ )
  407.         {
  408.             // replace the non specified elements with '*' except for the
  409.             // additional style which is usually just omitted
  410.             wxString elt = fontElements[n];
  411.             if ( elt.empty() && n != wxXLFD_ADDSTYLE )
  412.             {
  413.                 elt = _T('*');
  414.             }
  415.  
  416.             // const_cast
  417.             ((wxNativeFontInfo *)this)->xFontName << _T('-') << elt;
  418.         }
  419.     }
  420.  
  421.     return xFontName;
  422. }
  423.  
  424. void
  425. wxNativeFontInfo::SetXFontComponent(wxXLFDField field, const wxString& value)
  426. {
  427.     wxCHECK_RET( field < wxXLFD_MAX, _T("invalid XLFD field") );
  428.  
  429.     // this class should be initialized with a valid font spec first and only
  430.     // then the fields may be modified!
  431.     wxASSERT_MSG( !IsDefault(), _T("can't modify an uninitialized XLFD") );
  432.  
  433.     if ( !HasElements() )
  434.     {
  435.         // const_cast
  436.         if ( !((wxNativeFontInfo *)this)->FromXFontName(xFontName) )
  437.         {
  438.             wxFAIL_MSG( _T("can't set font element for invalid XLFD") );
  439.  
  440.             return;
  441.         }
  442.     }
  443.  
  444.     fontElements[field] = value;
  445.  
  446.     // invalidate the XFLD, it doesn't correspond to the font elements any more
  447.     xFontName.clear();
  448. }
  449.  
  450. void wxNativeFontInfo::SetXFontName(const wxString& xFontName_)
  451. {
  452.     // invalidate the font elements, GetXFontComponent() will reparse the XLFD
  453.     fontElements[0].clear();
  454.  
  455.     xFontName = xFontName_;
  456.  
  457.     m_isDefault = FALSE;
  458. }
  459.  
  460. int wxNativeFontInfo::GetPointSize() const
  461. {
  462.     const wxString s = GetXFontComponent(wxXLFD_POINTSIZE);
  463.  
  464.     // return -1 to indicate that the size is unknown
  465.     long l;
  466.     return s.ToLong(&l) ? l : -1;
  467. }
  468.  
  469. wxFontStyle wxNativeFontInfo::GetStyle() const
  470. {
  471.     const wxString s = GetXFontComponent(wxXLFD_SLANT);
  472.  
  473.     if ( s.length() != 1 )
  474.     {
  475.         // it is really unknown but we don't have any way to return it from
  476.         // here
  477.         return wxFONTSTYLE_NORMAL;
  478.     }
  479.  
  480.     switch ( s[0] )
  481.     {
  482.         default:
  483.             // again, unknown but consider normal by default
  484.  
  485.         case _T('r'):
  486.             return wxFONTSTYLE_NORMAL;
  487.  
  488.         case _T('i'):
  489.             return wxFONTSTYLE_ITALIC;
  490.  
  491.         case _T('o'):
  492.             return wxFONTSTYLE_SLANT;
  493.     }
  494. }
  495.  
  496. wxFontWeight wxNativeFontInfo::GetWeight() const
  497. {
  498.     const wxString s = GetXFontComponent(wxXLFD_WEIGHT).MakeLower();
  499.     if ( s.find(_T("bold")) != wxString::npos || s == _T("black") )
  500.         return wxFONTWEIGHT_BOLD;
  501.     else if ( s == _T("light") )
  502.         return wxFONTWEIGHT_LIGHT;
  503.  
  504.     return wxFONTWEIGHT_NORMAL;
  505. }
  506.  
  507. bool wxNativeFontInfo::GetUnderlined() const
  508. {
  509.     // X fonts are never underlined
  510.     return FALSE;
  511. }
  512.  
  513. wxString wxNativeFontInfo::GetFaceName() const
  514. {
  515.     // wxWindows facename probably more accurately corresponds to X family
  516.     return GetXFontComponent(wxXLFD_FAMILY);
  517. }
  518.  
  519. wxFontFamily wxNativeFontInfo::GetFamily() const
  520. {
  521.     // and wxWindows family -- to X foundry, but we have to translate it to
  522.     // wxFontFamily somehow...
  523.     wxFAIL_MSG(_T("not implemented")); // GetXFontComponent(wxXLFD_FOUNDRY);
  524.  
  525.     return wxFONTFAMILY_DEFAULT;
  526. }
  527.  
  528. wxFontEncoding wxNativeFontInfo::GetEncoding() const
  529. {
  530.     // we already have the code for this but need to refactor it first
  531.     wxFAIL_MSG( _T("not implemented") );
  532.  
  533.     return wxFONTENCODING_MAX;
  534. }
  535.  
  536. void wxNativeFontInfo::SetPointSize(int pointsize)
  537. {
  538.     SetXFontComponent(wxXLFD_POINTSIZE, wxString::Format(_T("%d"), pointsize));
  539. }
  540.  
  541. void wxNativeFontInfo::SetStyle(wxFontStyle style)
  542. {
  543.     wxString s;
  544.     switch ( style )
  545.     {
  546.         case wxFONTSTYLE_ITALIC:
  547.             s = _T('i');
  548.             break;
  549.  
  550.         case wxFONTSTYLE_SLANT:
  551.             s = _T('o');
  552.             break;
  553.  
  554.         case wxFONTSTYLE_NORMAL:
  555.             s = _T('r');
  556.  
  557.         default:
  558.             wxFAIL_MSG( _T("unknown wxFontStyle in wxNativeFontInfo::SetStyle") );
  559.             return;
  560.     }
  561.  
  562.     SetXFontComponent(wxXLFD_SLANT, s);
  563. }
  564.  
  565. void wxNativeFontInfo::SetWeight(wxFontWeight weight)
  566. {
  567.     wxString s;
  568.     switch ( weight )
  569.     {
  570.         case wxFONTWEIGHT_BOLD:
  571.             s = _T("bold");
  572.             break;
  573.  
  574.         case wxFONTWEIGHT_LIGHT:
  575.             s = _T("light");
  576.             break;
  577.  
  578.         case wxFONTWEIGHT_NORMAL:
  579.             s = _T("medium");
  580.             break;
  581.  
  582.         default:
  583.             wxFAIL_MSG( _T("unknown wxFontWeight in wxNativeFontInfo::SetWeight") );
  584.             return;
  585.     }
  586.  
  587.     SetXFontComponent(wxXLFD_WEIGHT, s);
  588. }
  589.  
  590. void wxNativeFontInfo::SetUnderlined(bool WXUNUSED(underlined))
  591. {
  592.     // can't do this under X
  593. }
  594.  
  595. void wxNativeFontInfo::SetFaceName(wxString facename)
  596. {
  597.     SetXFontComponent(wxXLFD_FAMILY, facename);
  598. }
  599.  
  600. void wxNativeFontInfo::SetFamily(wxFontFamily family)
  601. {
  602.     // wxFontFamily -> X foundry, anyone?
  603.     wxFAIL_MSG( _T("not implemented") );
  604.  
  605.     // SetXFontComponent(wxXLFD_FOUNDRY, ...);
  606. }
  607.  
  608. void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding)
  609. {
  610.     wxNativeEncodingInfo info;
  611.     if ( wxGetNativeFontEncoding(encoding, &info) )
  612.     {
  613.         SetXFontComponent(wxXLFD_ENCODING, info.xencoding);
  614.         SetXFontComponent(wxXLFD_REGISTRY, info.xregistry);
  615.     }
  616. }
  617.  
  618. // ----------------------------------------------------------------------------
  619. // common functions
  620. // ----------------------------------------------------------------------------
  621.  
  622. bool wxGetNativeFontEncoding(wxFontEncoding encoding,
  623.                              wxNativeEncodingInfo *info)
  624. {
  625.     wxCHECK_MSG( info, FALSE, _T("bad pointer in wxGetNativeFontEncoding") );
  626.  
  627.     if ( encoding == wxFONTENCODING_DEFAULT )
  628.     {
  629.         encoding = wxFont::GetDefaultEncoding();
  630.     }
  631.  
  632.     switch ( encoding )
  633.     {
  634.         case wxFONTENCODING_ISO8859_1:
  635.         case wxFONTENCODING_ISO8859_2:
  636.         case wxFONTENCODING_ISO8859_3:
  637.         case wxFONTENCODING_ISO8859_4:
  638.         case wxFONTENCODING_ISO8859_5:
  639.         case wxFONTENCODING_ISO8859_6:
  640.         case wxFONTENCODING_ISO8859_7:
  641.         case wxFONTENCODING_ISO8859_8:
  642.         case wxFONTENCODING_ISO8859_9:
  643.         case wxFONTENCODING_ISO8859_10:
  644.         case wxFONTENCODING_ISO8859_11:
  645.         case wxFONTENCODING_ISO8859_12:
  646.         case wxFONTENCODING_ISO8859_13:
  647.         case wxFONTENCODING_ISO8859_14:
  648.         case wxFONTENCODING_ISO8859_15:
  649.             {
  650.                 int cp = encoding - wxFONTENCODING_ISO8859_1 + 1;
  651.                 info->xregistry = wxT("iso8859");
  652.                 info->xencoding.Printf(wxT("%d"), cp);
  653.             }
  654.             break;
  655.  
  656.         case wxFONTENCODING_UTF8:
  657.             info->xregistry = wxT("iso10646");
  658.             info->xencoding = wxT("*");
  659.             break;
  660.  
  661.         case wxFONTENCODING_GB2312:
  662.             info->xregistry = wxT("GB2312");   // or the otherway round? 
  663.             info->xencoding = wxT("*");
  664.             break;
  665.  
  666.         case wxFONTENCODING_KOI8:
  667.             info->xregistry = wxT("koi8");
  668.  
  669.             // we don't make distinction between koi8-r, koi8-u and koi8-ru (so far)
  670.             info->xencoding = wxT("*");
  671.             break;
  672.  
  673.         case wxFONTENCODING_CP1250:
  674.         case wxFONTENCODING_CP1251:
  675.         case wxFONTENCODING_CP1252:
  676.         case wxFONTENCODING_CP1253:
  677.         case wxFONTENCODING_CP1254:
  678.         case wxFONTENCODING_CP1255:
  679.         case wxFONTENCODING_CP1256:
  680.         case wxFONTENCODING_CP1257:
  681.             {
  682.                 int cp = encoding - wxFONTENCODING_CP1250 + 1250;
  683.                 info->xregistry = wxT("microsoft");
  684.                 info->xencoding.Printf(wxT("cp%d"), cp);
  685.             }
  686.             break;
  687.  
  688.         case wxFONTENCODING_SYSTEM:
  689.             info->xregistry =
  690.             info->xencoding = wxT("*");
  691.             break;
  692.  
  693.         default:
  694.             // don't know how to translate this encoding into X fontspec
  695.             return FALSE;
  696.     }
  697.  
  698.     info->encoding = encoding;
  699.  
  700.     return TRUE;
  701. }
  702.  
  703. bool wxTestFontEncoding(const wxNativeEncodingInfo& info)
  704. {
  705.     wxString fontspec;
  706.     fontspec.Printf(_T("-*-%s-*-*-*-*-*-*-*-*-*-*-%s-%s"),
  707.                     !info.facename ? _T("*") : info.facename.c_str(),
  708.                     info.xregistry.c_str(),
  709.                     info.xencoding.c_str());
  710.  
  711.     return wxTestFontSpec(fontspec);
  712. }
  713.  
  714. // ----------------------------------------------------------------------------
  715. // X-specific functions
  716. // ----------------------------------------------------------------------------
  717.  
  718. wxNativeFont wxLoadQueryNearestFont(int pointSize,
  719.                                     int family,
  720.                                     int style,
  721.                                     int weight,
  722.                                     bool underlined,
  723.                                     const wxString &facename,
  724.                                     wxFontEncoding encoding,
  725.                                     wxString* xFontName)
  726. {
  727.     if ( encoding == wxFONTENCODING_DEFAULT )
  728.     {
  729.         encoding = wxFont::GetDefaultEncoding();
  730.     }
  731.  
  732.     // first determine the encoding - if the font doesn't exist at all in this
  733.     // encoding, it's useless to do all other approximations (i.e. size,
  734.     // family &c don't matter much)
  735.     wxNativeEncodingInfo info;
  736.     if ( encoding == wxFONTENCODING_SYSTEM )
  737.     {
  738.         // This will always work so we don't test to save time
  739.         wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM, &info);
  740.     }
  741.     else
  742.     {
  743.         if ( !wxGetNativeFontEncoding(encoding, &info) ||
  744.              !wxTestFontEncoding(info) )
  745.         {
  746. #if wxUSE_FONTMAP
  747.             if ( !wxFontMapper::Get()->GetAltForEncoding(encoding, &info) )
  748. #endif // wxUSE_FONTMAP
  749.             {
  750.                 // unspported encoding - replace it with the default
  751.                 //
  752.                 // NB: we can't just return 0 from here because wxGTK code doesn't
  753.                 //     check for it (i.e. it supposes that we'll always succeed),
  754.                 //     so it would provoke a crash
  755.                 wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM, &info);
  756.             }
  757.         }
  758.     }
  759.  
  760.     // OK, we have the correct xregistry/xencoding in info structure
  761.     wxNativeFont font = 0;
  762.  
  763.     // if we already have the X font name, try to use it
  764.     if( xFontName && !xFontName->IsEmpty() )
  765.     {
  766.         //
  767.         //  Make sure point size is correct for scale factor.
  768.         //
  769.         wxStringTokenizer tokenizer(*xFontName, _T("-"), wxTOKEN_RET_DELIMS);
  770.         wxString newFontName;
  771.  
  772.         for(int i = 0; i < 8; i++)
  773.           newFontName += tokenizer.NextToken();
  774.  
  775.         (void) tokenizer.NextToken();
  776.  
  777.         newFontName += wxString::Format(wxT("%d-"), pointSize);
  778.  
  779.         while(tokenizer.HasMoreTokens())
  780.           newFontName += tokenizer.GetNextToken();
  781.  
  782.         font = wxLoadFont(newFontName);
  783.  
  784.         if(font)
  785.           *xFontName = newFontName;
  786.     }
  787.  
  788.     // try to load exactly the font requested first
  789.     if( !font )
  790.     {
  791.         font = wxLoadQueryFont( pointSize, family, style, weight,
  792.                                 underlined, facename,
  793.                                 info.xregistry, info.xencoding,
  794.                                 xFontName );
  795.     }
  796.  
  797.     if ( !font )
  798.     {
  799.         // search up and down by stepsize 10
  800.         int max_size = pointSize + 20 * (1 + (pointSize/180));
  801.         int min_size = pointSize - 20 * (1 + (pointSize/180));
  802.  
  803.         int i;
  804.  
  805.         // Search for smaller size (approx.)
  806.         for ( i = pointSize - 10; !font && i >= 10 && i >= min_size; i -= 10 )
  807.         {
  808.             font = wxLoadQueryFont(i, family, style, weight, underlined,
  809.                                    facename, info.xregistry, info.xencoding,
  810.                                    xFontName);
  811.         }
  812.  
  813.         // Search for larger size (approx.)
  814.         for ( i = pointSize + 10; !font && i <= max_size; i += 10 )
  815.         {
  816.             font = wxLoadQueryFont(i, family, style, weight, underlined,
  817.                                    facename, info.xregistry, info.xencoding,
  818.                                    xFontName);
  819.         }
  820.  
  821.         // Try default family
  822.         if ( !font && family != wxDEFAULT )
  823.         {
  824.             font = wxLoadQueryFont(pointSize, wxDEFAULT, style, weight,
  825.                                    underlined, facename,
  826.                                    info.xregistry, info.xencoding,
  827.                                    xFontName );
  828.         }
  829.  
  830.         // ignore size, family, style and weight but try to find font with the
  831.         // given facename and encoding
  832.         if ( !font )
  833.         {
  834.             font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL,
  835.                                    underlined, facename,
  836.                                    info.xregistry, info.xencoding,
  837.                                    xFontName);
  838.  
  839.             // ignore family as well
  840.             if ( !font )
  841.             {
  842.                 font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL,
  843.                                        underlined, wxEmptyString,
  844.                                        info.xregistry, info.xencoding,
  845.                                        xFontName);
  846.  
  847.                 // if it still failed, try to get the font of any size but
  848.                 // with the requested encoding: this can happen if the
  849.                 // encoding is only available in one size which happens to be
  850.                 // different from 120
  851.                 if ( !font )
  852.                 {
  853.                     font = wxLoadQueryFont(-1, wxDEFAULT, wxNORMAL, wxNORMAL,
  854.                                            FALSE, wxEmptyString,
  855.                                            info.xregistry, info.xencoding,
  856.                                            xFontName);
  857.  
  858.                     // this should never happen as we had tested for it in the
  859.                     // very beginning, but if it does, do return something non
  860.                     // NULL or we'd crash in wxFont code
  861.                     if ( !font )
  862.                     {
  863.                         wxFAIL_MSG( _T("this encoding should be available!") );
  864.  
  865.                         font = wxLoadQueryFont(-1,
  866.                                                wxDEFAULT, wxNORMAL, wxNORMAL,
  867.                                                FALSE, wxEmptyString,
  868.                                                _T("*"), _T("*"),
  869.                                                xFontName);
  870.                     }
  871.                 }
  872.             }
  873.         }
  874.     }
  875.  
  876.     return font;
  877. }
  878.  
  879. // ----------------------------------------------------------------------------
  880. // private functions
  881. // ----------------------------------------------------------------------------
  882.  
  883. // returns TRUE if there are any fonts matching this font spec
  884. static bool wxTestFontSpec(const wxString& fontspec)
  885. {
  886.     // some X servers will fail to load this font because there are too many
  887.     // matches so we must test explicitly for this
  888.     if ( fontspec == _T("-*-*-*-*-*-*-*-*-*-*-*-*-*-*") )
  889.     {
  890.         return TRUE;
  891.     }
  892.  
  893.     wxNativeFont test = (wxNativeFont) g_fontHash->Get( fontspec );
  894.     if (test)
  895.     {
  896.         return TRUE;
  897.     }
  898.  
  899.     test = wxLoadFont(fontspec);
  900.     g_fontHash->Put( fontspec, (wxObject*) test );
  901.  
  902.     if ( test )
  903.     {
  904.         wxFreeFont(test);
  905.  
  906.         return TRUE;
  907.     }
  908.     else
  909.     {
  910.         return FALSE;
  911.     }
  912. }
  913.  
  914. static wxNativeFont wxLoadQueryFont(int pointSize,
  915.                                     int family,
  916.                                     int style,
  917.                                     int weight,
  918.                                     bool WXUNUSED(underlined),
  919.                                     const wxString& facename,
  920.                                     const wxString& xregistry,
  921.                                     const wxString& xencoding,
  922.                                     wxString* xFontName)
  923. {
  924.     wxString xfamily;
  925.     switch (family)
  926.     {
  927.         case wxDECORATIVE: xfamily = wxT("lucida"); break;
  928.         case wxROMAN:      xfamily = wxT("times");  break;
  929.         case wxMODERN:     xfamily = wxT("courier"); break;
  930.         case wxSWISS:      xfamily = wxT("helvetica"); break;
  931.         case wxTELETYPE:   xfamily = wxT("lucidatypewriter"); break;
  932.         case wxSCRIPT:     xfamily = wxT("utopia"); break;
  933.         default:           xfamily = wxT("*");
  934.     }
  935. #if wxUSE_NANOX
  936.     int xweight;
  937.     switch (weight)
  938.     {
  939.          case wxBOLD:
  940.              {
  941.                  xweight = MWLF_WEIGHT_BOLD;
  942.                  break;
  943.              }
  944.         case wxLIGHT:
  945.              {
  946.                  xweight = MWLF_WEIGHT_LIGHT;
  947.                  break;
  948.              }
  949.          case wxNORMAL:
  950.              {
  951.                  xweight = MWLF_WEIGHT_NORMAL;
  952.                  break;
  953.              }
  954.  
  955.      default:
  956.              {
  957.                  xweight = MWLF_WEIGHT_DEFAULT;
  958.                  break;
  959.              }
  960.     }
  961.     GR_SCREEN_INFO screenInfo;
  962.     GrGetScreenInfo(& screenInfo);
  963.  
  964.     int yPixelsPerCM = screenInfo.ydpcm;
  965.  
  966.     // A point is 1/72 of an inch.
  967.     // An inch is 2.541 cm.
  968.     // So pixelHeight = (pointSize / 72) (inches) * 2.541 (for cm) * yPixelsPerCM (for pixels)
  969.     // In fact pointSize is 10 * the normal point size so
  970.     // divide by 10.
  971.  
  972.     int pixelHeight = (int) ( (((float)pointSize) / 720.0) * 2.541 * (float) yPixelsPerCM) ;
  973.  
  974.     // An alternative: assume that the screen is 72 dpi.
  975.     //int pixelHeight = (int) (((float)pointSize / 720.0) * 72.0) ;
  976.     //int pixelHeight = (int) ((float)pointSize / 10.0) ;
  977.  
  978.     GR_LOGFONT logFont;
  979.     logFont.lfHeight = pixelHeight;
  980.     logFont.lfWidth = 0;
  981.     logFont.lfEscapement = 0;
  982.     logFont.lfOrientation = 0;
  983.     logFont.lfWeight = xweight;
  984.     logFont.lfItalic = (style == wxNORMAL ? 0 : 1) ;
  985.     logFont.lfUnderline = 0;
  986.     logFont.lfStrikeOut = 0;
  987.     logFont.lfCharSet = MWLF_CHARSET_DEFAULT; // TODO: select appropriate one
  988.     logFont.lfOutPrecision = MWLF_TYPE_DEFAULT;
  989.     logFont.lfClipPrecision = 0; // Not used
  990.     logFont.lfRoman = (family == wxROMAN ? 1 : 0) ;
  991.     logFont.lfSerif = (family == wxSWISS ? 0 : 1) ;
  992.     logFont.lfSansSerif = !logFont.lfSerif ;
  993.     logFont.lfModern = (family == wxMODERN ? 1 : 0) ;
  994.     logFont.lfProportional = (family == wxTELETYPE ? 0 : 1) ;
  995.     logFont.lfOblique = 0;
  996.     logFont.lfSmallCaps = 0;
  997.     logFont.lfPitch = 0; // 0 = default
  998.     strcpy(logFont.lfFaceName, facename.c_str());
  999.  
  1000.     XFontStruct* fontInfo = (XFontStruct*) malloc(sizeof(XFontStruct));
  1001.     fontInfo->fid = GrCreateFont((GR_CHAR*) facename.c_str(), pixelHeight, & logFont);
  1002.     GrGetFontInfo(fontInfo->fid, & fontInfo->info);
  1003.     return (wxNativeFont) fontInfo;
  1004.  
  1005. #else
  1006.     wxString fontSpec;
  1007.     if (!facename.IsEmpty())
  1008.     {
  1009.         fontSpec.Printf(wxT("-*-%s-*-*-normal-*-*-*-*-*-*-*-*-*"),
  1010.                         facename.c_str());
  1011.  
  1012.         if ( wxTestFontSpec(fontSpec) )
  1013.         {
  1014.             xfamily = facename;
  1015.         }
  1016.         //else: no such family, use default one instead
  1017.     }
  1018.  
  1019.     wxString xstyle;
  1020.     switch (style)
  1021.     {
  1022.         case wxSLANT:
  1023.             fontSpec.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"),
  1024.                     xfamily.c_str());
  1025.             if ( wxTestFontSpec(fontSpec) )
  1026.             {
  1027.                 xstyle = wxT("o");
  1028.                 break;
  1029.             }
  1030.             // fall through - try wxITALIC now
  1031.  
  1032.         case wxITALIC:
  1033.             fontSpec.Printf(wxT("-*-%s-*-i-*-*-*-*-*-*-*-*-*-*"),
  1034.                     xfamily.c_str());
  1035.             if ( wxTestFontSpec(fontSpec) )
  1036.             {
  1037.                 xstyle = wxT("i");
  1038.             }
  1039.             else if ( style == wxITALIC ) // and not wxSLANT
  1040.             {
  1041.                 // try wxSLANT
  1042.                 fontSpec.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"),
  1043.                         xfamily.c_str());
  1044.                 if ( wxTestFontSpec(fontSpec) )
  1045.                 {
  1046.                     xstyle = wxT("o");
  1047.                 }
  1048.                 else
  1049.                 {
  1050.                     // no italic, no slant - leave default
  1051.                     xstyle = wxT("*");
  1052.                 }
  1053.             }
  1054.             break;
  1055.  
  1056.         default:
  1057.             wxFAIL_MSG(_T("unknown font style"));
  1058.             // fall back to normal
  1059.  
  1060.         case wxNORMAL:
  1061.             xstyle = wxT("r");
  1062.             break;
  1063.     }
  1064.  
  1065.     wxString xweight;
  1066.     switch (weight)
  1067.     {
  1068.          case wxBOLD:
  1069.              {
  1070.                   fontSpec.Printf(wxT("-*-%s-bold-*-*-*-*-*-*-*-*-*-*-*"),
  1071.                          xfamily.c_str());
  1072.                   if ( wxTestFontSpec(fontSpec) )
  1073.                   {
  1074.                        xweight = wxT("bold");
  1075.                        break;
  1076.                   }
  1077.                   fontSpec.Printf(wxT("-*-%s-heavy-*-*-*-*-*-*-*-*-*-*-*"),
  1078.                          xfamily.c_str());
  1079.                   if ( wxTestFontSpec(fontSpec) )
  1080.                   {
  1081.                        xweight = wxT("heavy");
  1082.                        break;
  1083.                   }
  1084.                   fontSpec.Printf(wxT("-*-%s-extrabold-*-*-*-*-*-*-*-*-*-*-*"),
  1085.                          xfamily.c_str());
  1086.                   if ( wxTestFontSpec(fontSpec) )
  1087.                   {
  1088.                       xweight = wxT("extrabold");
  1089.                       break;
  1090.                   }
  1091.                   fontSpec.Printf(wxT("-*-%s-demibold-*-*-*-*-*-*-*-*-*-*-*"),
  1092.                          xfamily.c_str());
  1093.                   if ( wxTestFontSpec(fontSpec) )
  1094.                   {
  1095.                       xweight = wxT("demibold");
  1096.                       break;
  1097.                   }
  1098.                   fontSpec.Printf(wxT("-*-%s-black-*-*-*-*-*-*-*-*-*-*-*"),
  1099.                          xfamily.c_str());
  1100.                   if ( wxTestFontSpec(fontSpec) )
  1101.                   {
  1102.                       xweight = wxT("black");
  1103.                       break;
  1104.                   }
  1105.                   fontSpec.Printf(wxT("-*-%s-ultrablack-*-*-*-*-*-*-*-*-*-*-*"),
  1106.                          xfamily.c_str());
  1107.                   if ( wxTestFontSpec(fontSpec) )
  1108.                   {
  1109.                       xweight = wxT("ultrablack");
  1110.                       break;
  1111.                   }
  1112.               }
  1113.               break;
  1114.         case wxLIGHT:
  1115.              {
  1116.                   fontSpec.Printf(wxT("-*-%s-light-*-*-*-*-*-*-*-*-*-*-*"),
  1117.                          xfamily.c_str());
  1118.                   if ( wxTestFontSpec(fontSpec) )
  1119.                   {
  1120.                        xweight = wxT("light");
  1121.                        break;
  1122.                   }
  1123.                   fontSpec.Printf(wxT("-*-%s-thin-*-*-*-*-*-*-*-*-*-*-*"),
  1124.                          xfamily.c_str());
  1125.                   if ( wxTestFontSpec(fontSpec) )
  1126.                   {
  1127.                        xweight = wxT("thin");
  1128.                        break;
  1129.                   }
  1130.              }
  1131.              break;
  1132.          case wxNORMAL:
  1133.              {
  1134.                   fontSpec.Printf(wxT("-*-%s-medium-*-*-*-*-*-*-*-*-*-*-*"),
  1135.                          xfamily.c_str());
  1136.                   if ( wxTestFontSpec(fontSpec) )
  1137.                   {
  1138.                        xweight = wxT("medium");
  1139.                        break;
  1140.                   }
  1141.                   fontSpec.Printf(wxT("-*-%s-normal-*-*-*-*-*-*-*-*-*-*-*"),
  1142.                          xfamily.c_str());
  1143.                   if ( wxTestFontSpec(fontSpec) )
  1144.                   {
  1145.                        xweight = wxT("normal");
  1146.                        break;
  1147.                   }
  1148.                   fontSpec.Printf(wxT("-*-%s-regular-*-*-*-*-*-*-*-*-*-*-*"),
  1149.                          xfamily.c_str());
  1150.                   if ( wxTestFontSpec(fontSpec) )
  1151.                   {
  1152.                       xweight = wxT("regular");
  1153.                       break;
  1154.                   }
  1155.                   xweight = wxT("*");
  1156.               }
  1157.               break;
  1158.         default:           xweight = wxT("*"); break;
  1159.     }
  1160.  
  1161.     // if pointSize is -1, don't specify any
  1162.     wxString sizeSpec;
  1163.     if ( pointSize == -1 )
  1164.     {
  1165.         sizeSpec = _T('*');
  1166.     }
  1167.     else
  1168.     {
  1169.         sizeSpec.Printf(_T("%d"), pointSize);
  1170.     }
  1171.  
  1172.     // construct the X font spec from our data
  1173.     fontSpec.Printf(wxT("-*-%s-%s-%s-normal-*-*-%s-*-*-*-*-%s-%s"),
  1174.                     xfamily.c_str(), xweight.c_str(), xstyle.c_str(),
  1175.                     sizeSpec.c_str(), xregistry.c_str(), xencoding.c_str());
  1176.  
  1177.     if( xFontName )
  1178.         *xFontName = fontSpec;
  1179.  
  1180.     return wxLoadFont(fontSpec);
  1181. #endif
  1182.     // wxUSE_NANOX
  1183. }
  1184.  
  1185. // ----------------------------------------------------------------------------
  1186. // wxFontModule
  1187. // ----------------------------------------------------------------------------
  1188.  
  1189. class wxFontModule : public wxModule
  1190. {
  1191. public:
  1192.     bool OnInit();
  1193.     void OnExit();
  1194.  
  1195. private:
  1196.     DECLARE_DYNAMIC_CLASS(wxFontModule)
  1197. };
  1198.  
  1199. IMPLEMENT_DYNAMIC_CLASS(wxFontModule, wxModule)
  1200.  
  1201. bool wxFontModule::OnInit()
  1202. {
  1203.     g_fontHash = new wxHashTable( wxKEY_STRING );
  1204.  
  1205.     return TRUE;
  1206. }
  1207.  
  1208. void wxFontModule::OnExit()
  1209. {
  1210.     delete g_fontHash;
  1211.  
  1212.     g_fontHash = (wxHashTable *)NULL;
  1213. }
  1214.  
  1215. #endif // GTK 2.0/1.x
  1216.  
  1217.