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