home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / xfe / fonts.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  208.0 KB  |  8,568 lines

  1. /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18. /* 
  19.    fonts.c --- managing fonts for layout.
  20.    Created:    Jamie Zawinski     <jwz@netscape.com>, 23-Jun-94.
  21.    Re-written: Erik van der Poel <erik@netscape.com>, 15-Oct-95.
  22.  */
  23.  
  24.  
  25. /* Currently, we allow the user to select the size of the font used, and
  26.    the family/foundry.  Within that, the document author specifies
  27.    a size from 1-7, a face (normal, bold, italic, bold-italic) and whether
  28.    the font is fixed or variable width.  Meaning 7*4*2 = 56 possible
  29.    fonts (but we load lazily).
  30.  */
  31.  
  32.  
  33. #include "mozilla.h"
  34. #include "xfe.h"
  35. #include "fonts.h"
  36. #include "libi18n.h"
  37. #include "prprf.h"
  38. #include "prmem.h"
  39. #include <xpgetstr.h>
  40. #include "xupfonts.h"
  41. #ifndef NO_WEB_FONTS
  42. #include "nf.h"
  43. #include "Mnfrc.h"     /* before Mnffbc to stop warnings about nfrc */
  44. #include "Mnffmi.h"    /* before Mnffbc to stop warnings about nffmi */
  45. #include "Mnff.h"      /* before Mnfdoer to stop warnings about nff */
  46. #include "Mnfdoer.h"   /* before Mnffbc to stop warnings about nfdoer */
  47. #include "Mnfrf.h"     /* before Mnffbc to stop warnings about nfrf */
  48. #include "Mnffp.h"
  49. #include "Mnffbc.h"    /* font consumer interface definitions */
  50. #include "Mnffbu.h"    /* font utility interface definitions */
  51. #include "Mnffbp.h"    /* font producer interface definitions */
  52. #endif
  53.  
  54. #include "xp_qsort.h"
  55.  
  56. /* for XP_GetString() */
  57. extern int XFE_OTHER_LANGUAGE;
  58. extern int XFE_USER_DEFINED;
  59.  
  60.  
  61. /* for debugging */
  62. /* #define FE_PRINT_FONTS 1 */
  63.  
  64. #ifndef NO_WEB_FONTS
  65. /* This is defined in mozilla.c */
  66. extern void fe_GetProgramDirectory(char *path, int len);
  67. #endif /* NO_WEB_FONTS */
  68.  
  69. #define fe_FONT_PITCH_MONO        0x1
  70. #define fe_FONT_PITCH_PROPORTIONAL    0x2
  71. #define fe_FONT_PITCH_BOTH        0x3
  72.  
  73.  
  74. #define fe_TryFont(context, familyName, points, sizeNum, fontmask, charset, pitch, faceNum, dpy) \
  75.     (*fe_CharSetFuncsArray[fe_CharSetInfoArray[charset].info].loadFont) \
  76. (context, familyName, points, sizeNum, fontmask, charset, pitch, faceNum, dpy)
  77.  
  78.  
  79. #define FE_MAYBE_FREE(p) do { if (p) { free(p); (p) = NULL; } } while (0)
  80.  
  81.  
  82. #define FE_MALLOC_ZAP(type) ((type *) calloc(1, sizeof(type)))
  83.  
  84.  
  85. #define FE_FONT_MASK_TO_PITCH(fontmask) (((fontmask) & LO_FONT_FIXED) ? 1 : 0)
  86.  
  87. #define FE_FONT_MASK_TOGGLE_PITCH(fontmask) ((fontmask) ^ LO_FONT_FIXED)
  88.  
  89. #define FE_NORMALIZE_SIZE(sizeNum) \
  90.     do { (sizeNum) &= 0x7; if ((sizeNum) < 1) { (sizeNum) = 1; } } while (0)
  91.  
  92. #define FE_OPPOSITE_PITCH(p) ((p)==0 ? 1 : 0)
  93. #define FE_OPPOSITE_WEIGHT_FACE(f) ((f)^1)
  94. #define FE_OPPOSITE_SLANT_FACE(f) ((f)^2)
  95.  
  96. #define FE_FONT_MASK_TO_FACE(fontmask) \
  97.     ((((fontmask) & LO_FONT_BOLD) && \
  98.       ((fontmask) & LO_FONT_ITALIC)) ? 3 : \
  99.       ((fontmask) & LO_FONT_ITALIC) ? 2 : \
  100.       ((fontmask) & LO_FONT_BOLD) ? 1 : 0);
  101.  
  102. #define FE_FONT_SELECTED_FAMILY(charset, pitch) \
  103.     fe_FontFindSelectedFamily(&fe_FontCharSets[charset].pitches[pitch])
  104.  
  105. typedef struct fe_StringProcessTable
  106. {
  107.     unsigned char    fontIndex;
  108.     unsigned char    skip;
  109.     unsigned char    len;
  110. } fe_StringProcessTable;
  111.  
  112.  
  113. typedef struct fe_FontGroupFont
  114. {
  115.     unsigned char    mask1;
  116.  
  117.     unsigned char    mask2;
  118.  
  119.     XFontStruct    *xFont;
  120.  
  121. } fe_FontGroupFont;
  122.  
  123.  
  124. typedef struct fe_FontSetListEntry fe_FontSetListEntry;
  125.  
  126. struct fe_FontSetListEntry
  127. {
  128.     fe_FontSetListEntry    *next;
  129.     char            *list;
  130.     XFontSet        fontSet;
  131. };
  132.  
  133.  
  134. typedef int (*fe_XDrawStringFunc)(Display *dpy, Drawable d, GC gc,
  135.     int x, int y, char *string, int len);
  136.  
  137.  
  138. static fe_Font fe_FixedFont = NULL;
  139.  
  140. #define FE_DEFAULT_FONT_SIZE_INCREMENT    0.2
  141. static double fe_FontSizeIncrement = FE_DEFAULT_FONT_SIZE_INCREMENT;
  142.  
  143. /* Allowing an arbitrarily large point sizes enables a condition
  144.  * where viewing a web page which requests fonts in large point sizes
  145.  * could cause the X server to run out of memory and crash.
  146.  * Choose a reasonable maximum point size and normalize requests.
  147.  */
  148. #define FE_DEFAULT_FONT_MAXIMUM_POINTS 200
  149. static int fe_FontMaximumPoints = FE_DEFAULT_FONT_MAXIMUM_POINTS;
  150.  
  151. static fe_FontFace *fe_FontFaceList = NULL;
  152. static fe_FontSize *fe_FontSizeList = NULL;
  153.  
  154. static fe_FontSetListEntry *fe_FontSetList = NULL;
  155.  
  156. #ifndef NO_WEB_FONTS
  157. static struct nffbc * fe_FontBroker  = NULL;
  158.        struct nffbu * fe_FontUtility = NULL;
  159. #endif
  160.  
  161. fe_FontCharSet fe_FontCharSets[INTL_CHAR_SET_MAX];
  162.  
  163. unsigned char fe_SortedFontCharSets[INTL_CHAR_SET_MAX];
  164.  
  165. typedef struct GenericFontFamily {
  166.     char * class_name;
  167.     char * generic_name;
  168.     char * family_name;
  169. } GenericFontFamily;
  170.  
  171. static GenericFontFamily fe_generics[] = {
  172.     {"Serif",        "serif",      "times"},
  173.     {"Sans-Serif",    "sans-serif", "helvetica"},
  174.     {"Cursive",        "cursive",    "itc zapf chancery"},
  175.     {"Fantasy",        "fantasy",    "new century schoolbook"},
  176.     {"Monospace",    "monospace",  "courier"}
  177. };
  178.  
  179. #define fe_GenericFamilyCount (sizeof(fe_generics) / sizeof(GenericFontFamily))
  180.  
  181. static XP_Bool fe_AreNormalFontsAvail(int16 win_csid);
  182.  
  183. static fe_Font
  184. fe_LoadNormalFont(MWContext *context, char *familyName, 
  185.                   int points, int sizeNum,
  186.           int fontmask, int charset, int pitch, int faceNum,
  187.           Display *dpy);
  188.  
  189. static fe_Font
  190. fe_LoadFont(MWContext *context, int16 *charset, char *familyName,
  191.             int points, int size, int fontmask);
  192.  
  193. static fe_Font
  194. fe_LoadFontWithoutSubstitution(MWContext *context, int16 *charset, char *familyName,
  195.                                int points, int sizeNum, int fontmask);
  196.  
  197. static fe_Font WrapPlatformFont(fe_Font platform_font,
  198.                                 unsigned char font_type);
  199. #ifndef NO_WEB_FONTS
  200. static fe_Font fe_LoadRenderableFont(MWContext *context, LO_TextAttr *attr,
  201.                                      int16 *charset, char *family);
  202.  
  203. static double fe_ConvertHTMLSizeToPointSize(LO_TextAttr *attr, int16 charset);
  204. #endif
  205.  
  206. static fe_FontSize *
  207. fe_FindFontPointSize(fe_FontFamily *family, double decipoints,
  208.                      XP_Bool search_for_fit, XP_Bool scale_to_fit);
  209.  
  210. static char * fe_FindGenericFamily(int charsetID, char *familyName);
  211.  
  212. static XP_Bool fe_AreEUCCNFontsAvail(int16 /* win_csid */);
  213.  
  214. static fe_Font
  215. fe_LoadEUCCNFont(MWContext *context, char *familyName, int points,
  216.                  int sizeNum, int fontmask, int charset, int pitch,
  217.                  int faceNum, Display *dpy);
  218. static void
  219. fe_EUCCNTextExtents(fe_Font font, char *string, int len, int *direction,
  220.     int *fontAscent, int *fontDescent, XCharStruct *overall);
  221. static void
  222. fe_DrawEUCCNString(Display *dpy, Drawable d, fe_Font font, GC gc, int x,
  223.     int y, char *string, int len);
  224. static void
  225. fe_DrawEUCCNImageString(Display *dpy, Drawable d, fe_Font font, GC gc, GC gc2,
  226.     int x, int y, char *string, int len);
  227.  
  228. static XP_Bool fe_AreEUCJPFontsAvail(int16 /* win_csid */);
  229.  
  230. static fe_Font
  231. fe_LoadEUCJPFont(MWContext *context, char *familyName, int points,
  232.                  int sizeNum, int fontmask, int charset, int pitch,
  233.                  int faceNum, Display *dpy);
  234. static void
  235. fe_EUCJPTextExtents(fe_Font font, char *string, int len, int *direction,
  236.     int *fontAscent, int *fontDescent, XCharStruct *overall);
  237. static void
  238. fe_DrawEUCJPString(Display *dpy, Drawable d, fe_Font font, GC gc, int x,
  239.     int y, char *string, int len);
  240. static void
  241. fe_DrawEUCJPImageString(Display *dpy, Drawable d, fe_Font font, GC gc, GC gc2,
  242.     int x, int y, char *string, int len);
  243.  
  244. static XP_Bool fe_AreEUCKRFontsAvail(int16 /* win_csid */);
  245.  
  246. static fe_Font
  247. fe_LoadEUCKRFont(MWContext *context, char *familyName, int points,
  248.                  int sizeNum, int fontmask, int charset, int pitch,
  249.                  int faceNum, Display *dpy);
  250. static void
  251. fe_EUCKRTextExtents(fe_Font font, char *string, int len, int *direction,
  252.     int *fontAscent, int *fontDescent, XCharStruct *overall);
  253. static void
  254. fe_DrawEUCKRString(Display *dpy, Drawable d, fe_Font font, GC gc, int x,
  255.     int y, char *string, int len);
  256. static void
  257. fe_DrawEUCKRImageString(Display *dpy, Drawable d, fe_Font font, GC gc, GC gc2,
  258.     int x, int y, char *string, int len);
  259.  
  260. static XP_Bool fe_AreEUCTWFontsAvail(int16 /* win_csid */);
  261.  
  262. static fe_Font
  263. fe_LoadEUCTWFont(MWContext *context, char *familyName, int points,
  264.                  int sizeNum, int fontmask, int charset, int pitch,
  265.                  int faceNum, Display *dpy);
  266. static void
  267. fe_EUCTWTextExtents(fe_Font font, char *string, int len, int *direction,
  268.     int *fontAscent, int *fontDescent, XCharStruct *overall);
  269. static void
  270. fe_DrawEUCTWString(Display *dpy, Drawable d, fe_Font font, GC gc, int x,
  271.     int y, char *string, int len);
  272. static void
  273. fe_DrawEUCTWImageString(Display *dpy, Drawable d, fe_Font font, GC gc, GC gc2,
  274.     int x, int y, char *string, int len);
  275.  
  276. static XP_Bool fe_AreBIG5FontsAvail(int16 /* win_csid */);
  277.  
  278. static fe_Font
  279. fe_LoadBIG5Font(MWContext *context, char *familyName, int points,
  280.                 int sizeNum, int fontmask, int charset, int pitch,
  281.                 int faceNum, Display *dpy);
  282. static void
  283. fe_BIG5TextExtents(fe_Font font, char *string, int len, int *direction,
  284.     int *fontAscent, int *fontDescent, XCharStruct *overall);
  285. static void
  286. fe_DrawBIG5String(Display *dpy, Drawable d, fe_Font font, GC gc, int x,
  287.     int y, char *string, int len);
  288. static void
  289. fe_DrawBIG5ImageString(Display *dpy, Drawable d, fe_Font font, GC gc, GC gc2,
  290.     int x, int y, char *string, int len);
  291.  
  292. /* Unicode support */
  293. static XP_Bool fe_AreUnicodeFontsAvail(int16 /* win_csid */);
  294. static void
  295. fe_DrawUTF8StringImage(Display *dpy, Drawable d, fe_Font font, GC gc, GC gc2,
  296.     int x, int y, char *string, int len);
  297. static XFontStruct *
  298. fe_UnicodeInitXfont(fe_UnicodePseudoFont *ufont, uint16 encoding);
  299. static int16 *INTL_GetXCharSetIDs(Display *dpy);
  300.  
  301. enum
  302. {
  303.     FE_FONT_INFO_X8 = 0,
  304.     FE_FONT_INFO_X16,
  305.     FE_FONT_INFO_EUCCN,
  306.     FE_FONT_INFO_EUCJP,
  307.     FE_FONT_INFO_EUCKR,
  308.     FE_FONT_INFO_EUCTW,
  309.     FE_FONT_INFO_BIG5,
  310.     FE_FONT_INFO_UNICODE
  311. };
  312.  
  313.  
  314. fe_CharSetFuncs fe_CharSetFuncsArray[] =
  315. {
  316.     {
  317.                         1,
  318.         (fe_AreFontsAvailFunc)    fe_AreNormalFontsAvail,
  319.         (fe_LoadFontFunc)        fe_LoadNormalFont,
  320.         (fe_TextExtentsFunc)        XTextExtents,
  321.         (fe_DrawStringFunc)        XDrawString,
  322.         (fe_DrawImageStringFunc)    XDrawImageString
  323.     },
  324.     {
  325.                         1,
  326.         (fe_AreFontsAvailFunc)    fe_AreNormalFontsAvail,
  327.         (fe_LoadFontFunc)        fe_LoadNormalFont,
  328.         (fe_TextExtentsFunc)        XTextExtents16,
  329.         (fe_DrawStringFunc)        XDrawString16,
  330.         (fe_DrawImageStringFunc)    XDrawImageString16
  331.     },
  332.     {
  333.                         2,
  334.         (fe_AreFontsAvailFunc)        fe_AreEUCCNFontsAvail,
  335.         (fe_LoadFontFunc)        fe_LoadEUCCNFont,
  336.         (fe_TextExtentsFunc)        fe_EUCCNTextExtents,
  337.         (fe_DrawStringFunc)        fe_DrawEUCCNString,
  338.         (fe_DrawImageStringFunc)    fe_DrawEUCCNImageString
  339.     },
  340.     {
  341.                         4,
  342.         (fe_AreFontsAvailFunc)        fe_AreEUCJPFontsAvail,
  343.         (fe_LoadFontFunc)        fe_LoadEUCJPFont,
  344.         (fe_TextExtentsFunc)        fe_EUCJPTextExtents,
  345.         (fe_DrawStringFunc)        fe_DrawEUCJPString,
  346.         (fe_DrawImageStringFunc)    fe_DrawEUCJPImageString
  347.     },
  348.     {
  349.                         2,
  350.         (fe_AreFontsAvailFunc)        fe_AreEUCKRFontsAvail,
  351.         (fe_LoadFontFunc)        fe_LoadEUCKRFont,
  352.         (fe_TextExtentsFunc)        fe_EUCKRTextExtents,
  353.         (fe_DrawStringFunc)        fe_DrawEUCKRString,
  354.         (fe_DrawImageStringFunc)    fe_DrawEUCKRImageString
  355.     },
  356.     {
  357.                         3,
  358.         (fe_AreFontsAvailFunc)        fe_AreEUCTWFontsAvail,
  359.         (fe_LoadFontFunc)        fe_LoadEUCTWFont,
  360.         (fe_TextExtentsFunc)        fe_EUCTWTextExtents,
  361.         (fe_DrawStringFunc)        fe_DrawEUCTWString,
  362.         (fe_DrawImageStringFunc)    fe_DrawEUCTWImageString
  363.     },
  364.     {
  365.                         2,
  366.         (fe_AreFontsAvailFunc)        fe_AreBIG5FontsAvail,
  367.         (fe_LoadFontFunc)        fe_LoadBIG5Font,
  368.         (fe_TextExtentsFunc)        fe_BIG5TextExtents,
  369.         (fe_DrawStringFunc)        fe_DrawBIG5String,
  370.         (fe_DrawImageStringFunc)    fe_DrawBIG5ImageString
  371.     },
  372.     {
  373.                         4,
  374.         (fe_AreFontsAvailFunc)        fe_AreUnicodeFontsAvail,
  375.         (fe_LoadFontFunc)        fe_LoadUnicodeFont,
  376.         (fe_TextExtentsFunc)        fe_UTF8TextExtents,
  377.         (fe_DrawStringFunc)        fe_DrawUTF8String,
  378.         (fe_DrawImageStringFunc)    fe_DrawUTF8StringImage
  379.     },
  380. };
  381.  
  382.  
  383. fe_CharSetInfo fe_CharSetInfoArray[] =
  384. {
  385.     { CS_DEFAULT      , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  386.     { CS_ASCII        , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  387.     { CS_LATIN1       , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  388.     { CS_JIS          , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  389.     { CS_SJIS         , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  390.     { CS_EUCJP        , FE_FONT_TYPE_GROUP , FE_FONT_INFO_EUCJP    },
  391.     { CS_MAC_ROMAN    , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  392.     { CS_BIG5         , FE_FONT_TYPE_GROUP , FE_FONT_INFO_BIG5     },
  393.     { CS_GB_8BIT      , FE_FONT_TYPE_GROUP , FE_FONT_INFO_EUCCN    },
  394.     { CS_CNS_8BIT     , FE_FONT_TYPE_GROUP , FE_FONT_INFO_EUCTW    },
  395.     { CS_LATIN2       , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  396.     { CS_MAC_CE       , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  397.     { CS_KSC_8BIT     , FE_FONT_TYPE_GROUP , FE_FONT_INFO_EUCKR    },
  398.     { CS_2022_KR      , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  399.     { CS_8859_3       , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  400.     { CS_8859_4       , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  401.     { CS_8859_5       , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  402.     { CS_8859_6       , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  403.     { CS_8859_7       , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  404.     { CS_8859_8       , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  405.     { CS_8859_9       , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  406.     { CS_SYMBOL       , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  407.     { CS_DINGBATS     , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  408.     { CS_DECTECH      , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  409.     { CS_CNS11643_1   , FE_FONT_TYPE_X16   , FE_FONT_INFO_X16      },
  410.     { CS_CNS11643_2   , FE_FONT_TYPE_X16   , FE_FONT_INFO_X16      },
  411.     { CS_JISX0208     , FE_FONT_TYPE_X16   , FE_FONT_INFO_X16      },
  412.     { CS_JISX0201     , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  413.     { CS_KSC5601      , FE_FONT_TYPE_X16   , FE_FONT_INFO_X16      },
  414.     { CS_TIS620       , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  415.     { CS_JISX0212     , FE_FONT_TYPE_X16   , FE_FONT_INFO_X16      },
  416.     { CS_GB2312       , FE_FONT_TYPE_X16   , FE_FONT_INFO_X16      },
  417.     { CS_UCS2         , FE_FONT_TYPE_X16   , FE_FONT_INFO_X16      },
  418.     { CS_UCS4         , FE_FONT_TYPE_X16   , FE_FONT_INFO_X16      },
  419.     { CS_UTF8         , FE_FONT_TYPE_GROUP , FE_FONT_INFO_UNICODE  },
  420.     { CS_UTF7         , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  421.     { CS_NPC          , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  422.     { CS_X_BIG5       , FE_FONT_TYPE_X16   , FE_FONT_INFO_X16      },
  423.     { CS_USRDEF2      , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  424.     { CS_KOI8_R       , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  425.     { CS_MAC_CYRILLIC , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  426.     { CS_CP_1251      , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  427.     { CS_MAC_GREEK    , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  428.     { CS_CP_1253      , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  429.     { CS_CP_1250      , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  430.     { CS_CP_1254      , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  431.     { CS_MAC_TURKISH  , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  432.     { CS_GB2312_11    , FE_FONT_TYPE_X16   , FE_FONT_INFO_X16      },
  433.     { CS_JISX0208_11  , FE_FONT_TYPE_X16   , FE_FONT_INFO_X16      },
  434.     { CS_KSC5601_11   , FE_FONT_TYPE_X16   , FE_FONT_INFO_X16      },
  435.     { CS_CNS11643_1110, FE_FONT_TYPE_X16   , FE_FONT_INFO_X16      },
  436.     { CS_UCS2_SWAP    , FE_FONT_TYPE_X16   , FE_FONT_INFO_X16      },
  437.     { CS_IMAP4_UTF7   , FE_FONT_TYPE_X8    , FE_FONT_INFO_X8       },
  438. };
  439.  
  440. static unsigned char *fe_LocaleCharSets = NULL;
  441. static int32 smallestFontFoundSize = 12;
  442.  
  443. XP_Bool
  444. fe_IsCharSetSupported(int16 doc_csid)
  445. {
  446. /* need to deal with webfonts */
  447. #if 1
  448.     return TRUE;
  449. #else
  450.     int16 win_csid;
  451.  
  452.     win_csid = INTL_DocToWinCharSetID(doc_csid);
  453.     return(fe_AreFontsAvail(win_csid));
  454. #endif
  455. }
  456.  
  457. XP_Bool
  458. fe_AreFontsAvail(int16 win_csid)
  459. {
  460.     int result;
  461.  
  462.     result = (*fe_CharSetFuncsArray[fe_CharSetInfoArray[(win_csid) & 0xff].info
  463.                                         ].areFontsAvail)(win_csid);
  464.     return result;
  465. }
  466.  
  467. static void
  468. fe_GetLocaleCharSets(Display *dpy)
  469. {
  470.     char        *charset;
  471.     int16        charsetID;
  472.     char        clas[512];
  473.     XrmDatabase    db;
  474.     char        *def;
  475.     XFontSet    fontSet;
  476.     int        i;
  477.     int        j;
  478.     char        *mimeCharSet;
  479.     int        missCount;
  480.     char        **missing;
  481.     char        name[512];
  482.     char        *p;
  483.     char        *type;
  484.     XrmValue    value;
  485.  
  486.     if (fe_LocaleCharSets)
  487.     {
  488.         return;
  489.     }
  490.  
  491. #if defined(SCO) || defined(UNIXWARE) && (XlibSpecificationRelease == 5)
  492.     /*
  493.     ** XCreateFontSet is very slow in old Xlibs, fixed in X11R6
  494.     ** If locale == C, just punt
  495.     */
  496.     {
  497.         char *locale;
  498.         locale = setlocale(LC_CTYPE, NULL);
  499.         if (*locale == 'C') /* SCO is C_C.C */
  500.         {
  501.             return;
  502.         }
  503.     }
  504. #endif
  505.  
  506.     missing = NULL;
  507.     missCount = 0;
  508.     def = NULL;
  509.     fontSet = XCreateFontSet(dpy, "*-iso8859-1", &missing, &missCount,
  510.         &def);
  511.     if ((!fontSet) || (missCount < 1) || (!missing))
  512.     {
  513.         goto get_locale_char_sets_fail;
  514.     }
  515.  
  516.     fe_LocaleCharSets = malloc(missCount + 2);
  517.     if (!fe_LocaleCharSets)
  518.     {
  519.         goto get_locale_char_sets_fail;
  520.     }
  521.     j = 0;
  522.     fe_LocaleCharSets[j++] = ((unsigned char) (CS_LATIN1 & 0xff));
  523.  
  524.     charset = NULL;
  525.  
  526.     db = XtDatabase(dpy);
  527.  
  528.     for (i = 0; i < missCount; i++)
  529.     {
  530.         FE_MAYBE_FREE(charset);
  531.         if (!missing[i])
  532.         {
  533.             continue;
  534.         }
  535.         /*
  536.         (void) fprintf(real_stderr, "locale font %d: \"%s\"\n", i + 1,
  537.             missing[i]);
  538.         */
  539.         charset = strdup(missing[i]);
  540.         if (!charset)
  541.         {
  542.             goto get_locale_char_sets_fail;
  543.         }
  544.         p = charset;
  545.         while (*p)
  546.         {
  547.             (*p) = XP_TO_LOWER(*p);
  548.             p++;
  549.         }
  550.         (void) PR_snprintf(clas, sizeof(clas),
  551.             "%s.DocumentFonts.CharSet.Name", fe_progclass);
  552.         (void) PR_snprintf(name, sizeof(name),
  553.             "%s.documentFonts.charset.%s", fe_progclass, charset);
  554.         if (XrmGetResource(db, name, clas, &type, &value))
  555.         {
  556.             mimeCharSet = (char *) value.addr;
  557.         }
  558.         else
  559.         {
  560. #ifdef DEBUG
  561.             (void) fprintf(real_stderr, "fontset charset %s\n",
  562.                 charset);
  563. #endif /* DEBUG */
  564.             continue;
  565.         }
  566.         charsetID = INTL_CharSetNameToID(mimeCharSet);
  567.         if ((charsetID == CS_UNKNOWN) && strcmp(charset, "x-ignore"))
  568.         {
  569. #ifdef DEBUG
  570.             (void) fprintf(real_stderr, "fontset internal %s %s\n",
  571.                 charset, mimeCharSet);
  572. #endif /* DEBUG */
  573.             continue;
  574.         }
  575.         if (!strcmp(charset, "x-ignore"))
  576.         {
  577.             continue;
  578.         }
  579.         charsetID &= 0xff;
  580.         if (charsetID >= INTL_CHAR_SET_MAX)
  581.         {
  582.             continue;
  583.         }
  584.         fe_LocaleCharSets[j++] = (unsigned char) charsetID;
  585.     }
  586.  
  587.     FE_MAYBE_FREE(charset);
  588.  
  589.     fe_LocaleCharSets[j] = 0;
  590.  
  591.     XFreeStringList(missing);
  592.     XFreeFontSet(dpy, fontSet);
  593.  
  594.     return;
  595.  
  596. get_locale_char_sets_fail:
  597.  
  598.     if (fontSet)
  599.     {
  600.         XFreeFontSet(dpy, fontSet);
  601.     }
  602.     if (missing)
  603.     {
  604.         XFreeStringList(missing);
  605.     }
  606.     if (fe_LocaleCharSets)
  607.     {
  608.         free(fe_LocaleCharSets);
  609.         fe_LocaleCharSets = NULL;
  610.     }
  611. }
  612.  
  613. fe_FontFamily *
  614. fe_FontFindSelectedFamily(fe_FontPitch *pitch)
  615. {
  616.     fe_FontFamily        *family;
  617.     int            i;
  618.  
  619.     if (!pitch) return(NULL);
  620.  
  621.     if (pitch->selectedFamily) return(pitch->selectedFamily);
  622.  
  623.     family = NULL;
  624.     for (i = 0; i < pitch->numberOfFamilies; i++)
  625.     {
  626.         if (pitch->families[i].selected)
  627.         {
  628.             family = &pitch->families[i];
  629.             break;
  630.         }
  631.     }
  632.     if (!family)
  633.     {
  634.         family = FE_MALLOC_ZAP(fe_FontFamily);
  635.     }
  636.     
  637.     pitch->selectedFamily = family;
  638.     return (family);
  639. }
  640.  
  641. static fe_FontFamily *
  642. fe_GetFontFamily(uint16 charset, int pitch)
  643. {
  644.     fe_FontFamily *family;
  645.     family = FE_FONT_SELECTED_FAMILY((charset&0xFF), pitch);
  646.     if (family == NULL) {
  647.         return NULL;
  648.     }
  649.     if (!family->htmlSizesComputed) {
  650.         fe_ComputeFontSizeTable(family);
  651.     }
  652.     return family;
  653. }
  654.  
  655. fe_FontFamily *
  656. fe_FontFindFamily(int charsetID, int pitchID, char *familyName)
  657. {
  658.     fe_FontFamily        *family;
  659.     fe_FontPitch        *pitch;
  660.     int            i;
  661.         char *                  genericFamily;
  662.  
  663.     if (!familyName || !*familyName) return(NULL);
  664.  
  665.     family = NULL;
  666.     pitch = &fe_FontCharSets[charsetID&0xFF].pitches[pitchID];
  667.     for (i = 0; i < pitch->numberOfFamilies; i++)
  668.     {
  669.         if (!XP_STRCASECMP(pitch->families[i].family, familyName))
  670.         {
  671.             family = &pitch->families[i];
  672.             if (!family->htmlSizesComputed) {
  673.                 fe_ComputeFontSizeTable(family);
  674.             }
  675.             break;
  676.         }
  677.     }
  678.  
  679.         if (family)
  680.             return family;
  681.  
  682.         genericFamily = fe_FindGenericFamily(charsetID, familyName);
  683.         if (!genericFamily)
  684.             return family;
  685.  
  686.     for (i = 0; i < pitch->numberOfFamilies; i++) {
  687.             if (!XP_STRCASECMP(pitch->families[i].family, genericFamily)) {
  688.                 family = &pitch->families[i];
  689.                 if (!family->htmlSizesComputed) {
  690.                     fe_ComputeFontSizeTable(family);
  691.                 }
  692.                 break;
  693.             }
  694.     }
  695.     return (family);
  696. }
  697.  
  698. static char * fe_FindGenericFamily(int charsetID, char *familyName)
  699. {
  700.     char * genericFamily;
  701.     int i;
  702.  
  703.     /* This is the "default font displayer's" mapping of the
  704.      * generic font names, as described by CSS1, into common X fonts.
  705.      */
  706.  
  707.     if (!familyName || !*familyName) return(NULL);
  708.  
  709.     /* Generic font names are mapped only for the Latin-1 charset */
  710.     if (CS_LATIN1 != charsetID) return NULL;
  711.  
  712.     genericFamily = NULL;
  713.     for (i = 0; i < fe_GenericFamilyCount; i++) {
  714.         if (!XP_STRCASECMP(fe_generics[i].generic_name, familyName)) {
  715.             genericFamily = fe_generics[i].family_name;
  716.             break;
  717.         }
  718.     }
  719.     return genericFamily;
  720. }
  721.  
  722.  
  723. XtPointer
  724. fe_GetFont(MWContext *context, int sizeNum, int fontmask)
  725. {
  726.         XmFontListEntry flentry;
  727.         XtPointer       fontOrFontSet;
  728.         XmFontType      type;
  729.     XmFontList      fontList;
  730.  
  731.         fontOrFontSet = fe_GetFontOrFontSet(context, NULL, sizeNum, fontmask,
  732.                 &type);
  733.         if (!fontOrFontSet)
  734.         {
  735.                 return NULL;
  736.         }
  737.         flentry = XmFontListEntryCreate(XmFONTLIST_DEFAULT_TAG, type,
  738.                 fontOrFontSet);
  739.         if (!flentry)
  740.         {
  741.                 return NULL;
  742.         }
  743.         fontList = XmFontListAppendEntry(NULL, flentry);
  744.         if (!fontList)
  745.         {
  746.                 return NULL;
  747.         }
  748.         XmFontListEntryFree(&flentry);
  749.     return fontList;
  750. }
  751.  
  752.  
  753. XtPointer
  754. fe_GetFontOrFontSet(MWContext *context, char *familyName, int sizeNum,
  755.     int fontmask, XmFontType *type)
  756. {
  757.     unsigned char        charset;
  758.     int16            cs;
  759.     char            *def;
  760.     Display            *dpy;
  761.     fe_FontSetListEntry    *f;
  762.     fe_FontFace        *face;
  763.     int            faceNum;
  764.     XtPointer        fontOrFontSet;
  765.     char            *list;
  766.     int            missCount;
  767.     char            **missing;
  768.     char            *newList;
  769.     unsigned char        *p;
  770.     int            pitch;
  771.     fe_FontSize        *size;
  772.     fe_FontFamily        *family;
  773.  
  774.     def = NULL;
  775.     dpy = XtDisplay(CONTEXT_WIDGET(context));
  776.     faceNum = FE_FONT_MASK_TO_FACE(fontmask);
  777.     list = NULL;
  778.     missCount = 0;
  779.     missing = NULL;
  780.     pitch = FE_FONT_MASK_TO_PITCH(fontmask);
  781.     FE_NORMALIZE_SIZE(sizeNum);
  782.  
  783.     if (fe_LocaleCharSets)
  784.     {
  785.         p = fe_LocaleCharSets;
  786.         while (*p)
  787.         {
  788.             charset = *p++;
  789.             family = NULL;
  790.             if (familyName && *familyName)
  791.             {
  792.                 family = fe_FontFindFamily(charset, pitch, familyName);
  793.                 if (!family) return NULL;
  794.             }
  795.             if (!family)
  796.             {
  797.                 family = fe_GetFontFamily(charset, pitch);
  798.                 if (!family)
  799.                 {
  800.                     return NULL;
  801.                 }
  802.             }
  803.             size = family->htmlSizes[sizeNum-1];
  804.             if (!size)
  805.             {
  806.                 continue;
  807.             }
  808.             face = size->faces[faceNum];
  809.             if (!face)
  810.             {
  811.                 continue;
  812.             }
  813.             if (!face->longXLFDFontName)
  814.             {
  815.                 continue;
  816.             }
  817.             if (list)
  818.             {
  819.                 newList = PR_smprintf("%s,%s", list,
  820.                     face->longXLFDFontName);
  821.                 free(list);
  822.                 list = newList;
  823.             }
  824.             else
  825.             {
  826.                 list = strdup(face->longXLFDFontName);
  827.             }
  828.             if (!list)
  829.             {
  830.                 return NULL;
  831.             }
  832.         }
  833.         f = fe_FontSetList;
  834.         while (f)
  835.         {
  836.             if (!strcmp(f->list, list))
  837.             {
  838.                 break;
  839.             }
  840.             f = f->next;
  841.         }
  842.         if (f)
  843.         {
  844.             free(list);
  845.             fontOrFontSet = f->fontSet;
  846.             *type = XmFONT_IS_FONTSET;
  847.         }
  848.         else
  849.         {
  850.             fontOrFontSet = XCreateFontSet(dpy, list, &missing,
  851.                 &missCount, &def);
  852.             if (fontOrFontSet)
  853.             {
  854.                 /*
  855.                 (void) fprintf(real_stderr,
  856.                     "font set \"%s\" succeeded\n", list);
  857.                 */
  858.                 f = XP_NEW_ZAP(fe_FontSetListEntry);
  859.                 if (!f)
  860.                 {
  861.                     return NULL;
  862.                 }
  863.                 f->next = fe_FontSetList;
  864.                 fe_FontSetList = f;
  865.                 f->list = list;
  866.                 f->fontSet = fontOrFontSet;
  867.                 *type = XmFONT_IS_FONTSET;
  868.             }
  869.             else
  870.             {
  871.                 /*
  872.                 (void) fprintf(real_stderr,
  873.                     "font set \"%s\" failed\n", list);
  874.                 */
  875.                 return NULL;
  876.             }
  877.         }
  878.     }
  879.     else
  880.     {
  881.         cs = CS_LATIN1;
  882.         fontOrFontSet = fe_LoadFont(context, &cs, familyName,
  883.                         0 /* no pointsize */,
  884.                                             sizeNum, fontmask);
  885.         *type = XmFONT_IS_FONT;
  886.     }
  887.  
  888.     return fontOrFontSet;
  889. }
  890.  
  891.  
  892. static int
  893. fe_PitchAndFaceToFontMask(int pitch, int face)
  894. {
  895.     int    fontmask;
  896.  
  897.     if (pitch)
  898.     {
  899.         fontmask = LO_FONT_FIXED;
  900.     }
  901.     else
  902.     {
  903.         fontmask = 0;
  904.     }
  905.  
  906.     switch (face)
  907.     {
  908.     case 1:
  909.         fontmask |= LO_FONT_BOLD;
  910.         break;
  911.     case 2:
  912.         fontmask |= LO_FONT_ITALIC;
  913.         break;
  914.     case 3:
  915.         fontmask |= (LO_FONT_BOLD | LO_FONT_ITALIC);
  916.         break;
  917.     default:
  918.         break;
  919.     }
  920.  
  921.     return fontmask;
  922. }
  923.  
  924.  
  925. static fe_Font
  926. fe_LoadFontGroup(MWContext *context, char *familyName,
  927.                  int points, int sizeNum,
  928.     int fontmask, int16 charsetID, int pitch, int faceNum, Display *dpy)
  929. {
  930.     fe_FontFace    *face;
  931.     fe_Font        font;
  932.     int        i;
  933.     fe_FontSize    *size;
  934.     fe_FontFamily    *family;
  935.  
  936.     size = FE_MALLOC_ZAP(fe_FontSize);
  937.     if (!size)
  938.     {
  939.         return NULL;
  940.     }
  941.  
  942.     for (i = 0; i < 4; i++)
  943.     {
  944.         face = FE_MALLOC_ZAP(fe_FontFace);
  945.         if (!face)
  946.         {
  947.             return NULL;
  948.         }
  949.         size->faces[i] = face;
  950.  
  951.         /*
  952.          * @@@ ignore familyName for now
  953.          * need to modify all the loadFont funcs too
  954.          */
  955.         font = (*fe_CharSetFuncsArray[fe_CharSetInfoArray[charsetID].
  956.             info].loadFont)(context, NULL, points, sizeNum,
  957.             fe_PitchAndFaceToFontMask(pitch, i), charsetID,
  958.             pitch, i, dpy);
  959.  
  960.         if (!font)
  961.         {
  962.             return NULL;
  963.         }
  964.         face->font = font;
  965.     }
  966.  
  967.     family = FE_FONT_SELECTED_FAMILY(charsetID, pitch);
  968.     if (!family)
  969.     {
  970.         XP_FREE(size);
  971.         return NULL;
  972.     }
  973.  
  974.         /* XXX what is going on here for pointsizes?  -converse */
  975.  
  976.         if (!points) {
  977.             family->htmlSizes[sizeNum-1] = size;
  978.         }
  979.         return size->faces[faceNum]->font;
  980. }
  981.  
  982.  
  983. static fe_Font
  984. fe_LoadFont(MWContext *context, int16 *charset, char *familyName,
  985.         int points, int sizeNum, int fontmask)
  986. {
  987.     int16        charsetID;
  988.     Display        *dpy;
  989.     fe_FontFace    *face;
  990.     int        faceNum;
  991.     fe_Font        font;
  992.     int        pitch;
  993.     fe_FontSize    *size;
  994.     int        trySize;
  995.     fe_FontFamily    *family;
  996.         double          decipoints;
  997.  
  998.     /*
  999.      * paranoia, robustness
  1000.      */
  1001.  
  1002.     charsetID = 0;
  1003.     if (charset)
  1004.     {
  1005.         charsetID = *charset;
  1006.     }
  1007.     else
  1008.     {
  1009.         charset = &charsetID;
  1010.     }
  1011.  
  1012.     if (!charsetID)
  1013.     {
  1014.         charsetID = INTL_DefaultTextAttributeCharSetID(context);
  1015.         if (!charsetID)
  1016.         {
  1017.             charsetID = CS_LATIN1;
  1018.         }
  1019.         *charset = charsetID;
  1020.     }
  1021.     charsetID &= 0xff;
  1022.     if (charsetID >= INTL_CHAR_SET_MAX)
  1023.     {
  1024.         charsetID = (CS_LATIN1 & 0xff);
  1025.         *charset = CS_LATIN1;
  1026.     }
  1027.  
  1028.     pitch = FE_FONT_MASK_TO_PITCH(fontmask);
  1029.  
  1030.     faceNum = FE_FONT_MASK_TO_FACE(fontmask);
  1031.  
  1032.     dpy = XtDisplay(CONTEXT_WIDGET(context));
  1033.  
  1034.     family = NULL;
  1035.     if (familyName && *familyName)
  1036.     {
  1037.         family = fe_FontFindFamily(charsetID, pitch, familyName);
  1038.         if ((!family) && (fe_CharSetInfoArray[charsetID].type !=
  1039.             FE_FONT_TYPE_GROUP))
  1040.         {
  1041.             return NULL;
  1042.         }
  1043.     }
  1044.     if (!family)
  1045.     {
  1046.         /* We blew the font lookup, falling back to default. */
  1047.         family = fe_GetFontFamily(*charset, pitch);
  1048.  
  1049.         /* Invalidate the point size, I can't read it. */
  1050.         points = 0;
  1051.  
  1052.         if (!family)
  1053.         {
  1054.             if (*charset == CS_LATIN1)
  1055.             {
  1056.                 return fe_FixedFont;
  1057.             }
  1058.             else
  1059.             {
  1060.                 *charset = CS_LATIN1;
  1061.                 return fe_LoadFont(context, charset,
  1062.                                                    familyName, points,
  1063.                                                    sizeNum, fontmask);
  1064.             }
  1065.         }
  1066.     }
  1067.         if (! points)
  1068.             size = family->htmlSizes[sizeNum-1];
  1069.         else {
  1070.             decipoints = (double) (points * 10);
  1071.             size = fe_FindFontPointSize(family, decipoints, False, True);
  1072.         }
  1073.     if (!size)
  1074.     {
  1075.         if (fe_CharSetInfoArray[charsetID].type == FE_FONT_TYPE_GROUP)
  1076.         {
  1077.             font = fe_LoadFontGroup(context, familyName, points,
  1078.                                                 sizeNum, fontmask, charsetID,
  1079.                                                 pitch, faceNum, dpy);
  1080.             if (font)
  1081.             {
  1082.                 return font;
  1083.             }
  1084.         }
  1085.  
  1086.         /*
  1087.          * this charset is not available
  1088.          * use Latin-1 font to display the bytes
  1089.          */
  1090.         if (*charset == CS_LATIN1)
  1091.         {
  1092.             return fe_FixedFont;
  1093.         }
  1094.         else
  1095.         {
  1096.             *charset = CS_LATIN1;
  1097.             return fe_LoadFont(context, charset, familyName,
  1098.                        points, sizeNum, fontmask);
  1099.         }
  1100.     }
  1101.  
  1102.     face = size->faces[faceNum];
  1103.     if (!face)
  1104.     {
  1105.         /*
  1106.          * this shouldn't happen
  1107.          * if it does, we will display these bytes in a Latin-1 font
  1108.          */
  1109.         if (*charset == CS_LATIN1)
  1110.         {
  1111.             return fe_FixedFont;
  1112.         }
  1113.         else
  1114.         {
  1115.             *charset = CS_LATIN1;
  1116.             return fe_LoadFont(context, charset, familyName,
  1117.                        points, sizeNum, fontmask);
  1118.         }
  1119.     }
  1120.  
  1121.     font = face->font;
  1122.     if (!font)
  1123.     {
  1124.         font = fe_TryFont(context, familyName, points, sizeNum,
  1125.                                   fontmask, charsetID, pitch, faceNum, dpy);
  1126.         if (font)
  1127.         {
  1128.                     face->font = font;
  1129.         }
  1130.         else
  1131.         {
  1132.             for (trySize = sizeNum - 1; trySize > 0; trySize--)
  1133.             {
  1134.                 font = fe_TryFont(context, familyName,
  1135.                           points, trySize, fontmask,
  1136.                           charsetID, pitch,
  1137.                           faceNum, dpy);
  1138.                 if (font)
  1139.                 {
  1140.                     return font;
  1141.                 }
  1142.             }
  1143.  
  1144.             for (trySize = sizeNum + 1; trySize < 8; trySize++)
  1145.             {
  1146.                 font = fe_TryFont(context, familyName,
  1147.                           points, trySize, fontmask,
  1148.                           charsetID, pitch,
  1149.                           faceNum, dpy);
  1150.                 if (font)
  1151.                 {
  1152.                     return font;
  1153.                 }
  1154.             }
  1155.  
  1156.             *charset = CS_LATIN1;
  1157.             font = fe_FixedFont;
  1158.             face->font = font;
  1159.             return font;
  1160.  
  1161.             /* @@@ need to change this */
  1162.             /*
  1163.             (void) fprintf(real_stderr, "could not load\n%s\n",
  1164.                 face->longXLFDFontName);
  1165.             */
  1166.             /* XP_GetString(XFE_COULD_NOT_LOAD_FONT) */
  1167.             /* XP_GetString(XFE_USING_FALLBACK_FONT) */
  1168.             /* XP_GetString(XFE_NO_FALLBACK_FONT) */
  1169.             /* FE_Alert(context, msg); */
  1170.         }
  1171.     }
  1172.  
  1173.     return font;
  1174. }
  1175.  
  1176. static fe_Font
  1177. fe_LoadFontWithoutSubstitution(MWContext *context, int16 *charset, char *familyName,
  1178.                                int points, int sizeNum, int fontmask)
  1179. {
  1180.     int16        charsetID;
  1181.     Display        *dpy;
  1182.     fe_FontFace    *face;
  1183.     int        faceNum;
  1184.     fe_Font        font;
  1185.     int        pitch;
  1186.     fe_FontSize    *size;
  1187.     int        trySize;
  1188.     fe_FontFamily    *family;
  1189.         double          decipoints;
  1190.  
  1191.     /*
  1192.      * paranoia, robustness
  1193.      */
  1194.  
  1195.     charsetID = 0;
  1196.     if (charset)
  1197.     {
  1198.         charsetID = *charset;
  1199.     }
  1200.     else
  1201.     {
  1202.         charset = &charsetID;
  1203.     }
  1204.  
  1205.     if (!charsetID)
  1206.     {
  1207.         charsetID = INTL_DefaultTextAttributeCharSetID(context);
  1208.         if (!charsetID)
  1209.         {
  1210.             charsetID = CS_LATIN1;
  1211.         }
  1212.         *charset = charsetID;
  1213.     }
  1214.     charsetID &= 0xff;
  1215.     if (charsetID >= INTL_CHAR_SET_MAX)
  1216.     {
  1217.         charsetID = (CS_LATIN1 & 0xff);
  1218.         *charset = CS_LATIN1;
  1219.     }
  1220.  
  1221.     pitch = FE_FONT_MASK_TO_PITCH(fontmask);
  1222.  
  1223.     faceNum = FE_FONT_MASK_TO_FACE(fontmask);
  1224.  
  1225.     dpy = XtDisplay(CONTEXT_WIDGET(context));
  1226.  
  1227.     family = NULL;
  1228.     if (familyName && *familyName)
  1229.     {
  1230.         family = fe_FontFindFamily(charsetID, pitch, familyName);
  1231.         if (!family)
  1232.         {
  1233.             return NULL;
  1234.         }
  1235.     }
  1236.         else
  1237.         {
  1238.             return NULL;
  1239.         }
  1240.         if (! points)
  1241.             size = family->htmlSizes[sizeNum-1];
  1242.         else {
  1243.             decipoints = (double) (points * 10);
  1244.             size = fe_FindFontPointSize(family, decipoints, False, True);
  1245.         }
  1246.     if (!size)
  1247.     {
  1248.             return NULL;
  1249.         }
  1250.     face = size->faces[faceNum];
  1251.     if (!face)
  1252.     {
  1253.             return NULL;
  1254.     }
  1255.     font = face->font;
  1256.     if (!font)
  1257.     {
  1258.         font = fe_TryFont(context, familyName, points, sizeNum,
  1259.                                   fontmask, charsetID, pitch, faceNum, dpy);
  1260.         if (font)
  1261.         {
  1262.                     face->font = font;
  1263.         }
  1264.         else if (points == 0)
  1265.         {
  1266.             for (trySize = sizeNum - 1; trySize > 0; trySize--)
  1267.             {
  1268.                 font = fe_TryFont(context, familyName,
  1269.                           points, trySize, fontmask,
  1270.                           charsetID, pitch,
  1271.                           faceNum, dpy);
  1272.                 if (font)
  1273.                 {
  1274.                     return font;
  1275.                 }
  1276.             }
  1277.  
  1278.             for (trySize = sizeNum + 1; trySize < 8; trySize++)
  1279.             {
  1280.                 font = fe_TryFont(context, familyName,
  1281.                           points, trySize, fontmask,
  1282.                           charsetID, pitch,
  1283.                           faceNum, dpy);
  1284.                 if (font)
  1285.                 {
  1286.                     return font;
  1287.                 }
  1288.             }
  1289.         }
  1290.     }
  1291.     return font;
  1292. }
  1293.  
  1294.  
  1295. static char * NameFromList(char * namelist)
  1296. {
  1297.     static char * list;
  1298.     static int next;
  1299.     static int len;
  1300.  
  1301.     int start;
  1302.     int end;
  1303.     char final = '\0';
  1304.  
  1305.     if (namelist) {
  1306.         list = namelist;
  1307.         len = strlen(namelist);
  1308.         next = 0;
  1309.     }
  1310.     
  1311.     start = next;
  1312.         
  1313.     if (! list || list[start] == '\0')
  1314.         return (char *) NULL;
  1315.         
  1316.     /* skip over leading whitespace and commas to find the start of the name */
  1317.     while (list[start] != '\0' && (list[start] == ',' || isspace(list[start])))
  1318.         start++;
  1319.         
  1320.     /* find the end of the name */
  1321.     next = start;
  1322.     while(list[next] != '\0' && list[next] != ',') {
  1323.         if (list[next] == '"' || list[next] == '\'') {
  1324.             final = list[next];
  1325.                         
  1326.             /* find the matching quote */
  1327.             next++;
  1328.             while (list[next] != '\0' && list[next] != final)
  1329.                 next++;
  1330.  
  1331.             /* if list[next] is null, there was no matching quote, so bail */
  1332.             if (list[next] == '\0')
  1333.                 break;
  1334.         }
  1335.         next++;
  1336.     }
  1337.     end = next - 1;
  1338.  
  1339.     if (list[next] != '\0' && next < len)
  1340.         next++;
  1341.  
  1342.     /* strip off trailing whitespace */        
  1343.     while (end >= start && isspace(list[end]))
  1344.         end--;
  1345.         
  1346.     /* if it's quoted, strip off the quotes */
  1347.     if ((list[start] == '"' || list[start] == '\'') && list[end] == list[start]) {
  1348.         start++;
  1349.         end--;
  1350.     }
  1351.  
  1352.     end++;
  1353.     list[end] = '\0';
  1354.     return &(list[start]);
  1355. }
  1356.  
  1357. fe_Font
  1358. fe_LoadFontFromFace(MWContext *context, LO_TextAttr *attr, int16 *charset, char *net_font_face,
  1359.            int size, int fontmask)
  1360. {
  1361.     fe_Font font = 0;
  1362.     char *local_net_font_face = NULL;
  1363.     char *familyname = NULL;
  1364.         char *last_familyname = NULL;
  1365.         unsigned char font_type = 0;
  1366.         int16 charsetID;
  1367.         int16 saved_charset;
  1368.         int points = 0;
  1369.  
  1370.     if (attr)
  1371.     {
  1372.         font = (fe_Font) attr->FE_Data;
  1373.         if (font) return(font);
  1374.  
  1375.                 points = (int) attr->point_size;
  1376.                 if (points < 1)
  1377.                     points = 0;
  1378.                 if (points > fe_FontMaximumPoints)
  1379.                     points = fe_FontMaximumPoints;
  1380.  
  1381.                 if (attr->font_weight > 0) {
  1382.                     if (attr->font_weight <= 500)
  1383.                         fontmask &= ~LO_FONT_BOLD;
  1384.                     else 
  1385.                         fontmask |= LO_FONT_BOLD;
  1386.                 }
  1387.     }
  1388.  
  1389.         charsetID = 0;
  1390.     if (charset)
  1391.     {
  1392.         charsetID = *charset;
  1393.     }
  1394.     else
  1395.     {
  1396.         charset = &charsetID;
  1397.     }
  1398.  
  1399.     if (!charsetID)
  1400.     {
  1401.         charsetID = INTL_DefaultTextAttributeCharSetID(context);
  1402.         if (!charsetID)
  1403.         {
  1404.             charsetID = CS_LATIN1;
  1405.         }
  1406.         *charset = charsetID;
  1407.     }
  1408.     charsetID &= 0xff;
  1409.     if (charsetID >= INTL_CHAR_SET_MAX)
  1410.     {
  1411.         charsetID = (CS_LATIN1 & 0xff);
  1412.         *charset = CS_LATIN1;
  1413.     }
  1414.         saved_charset = *charset;
  1415.  
  1416.     FE_NORMALIZE_SIZE(size);
  1417.  
  1418.     if (net_font_face && *net_font_face)
  1419.     {
  1420.         local_net_font_face = strdup(net_font_face);
  1421.         if (!local_net_font_face) return (0);
  1422.         familyname = NameFromList(local_net_font_face);
  1423.         while (familyname)
  1424.         {
  1425. #if !defined(NO_WEB_FONTS) && !defined(NO_BROKERED_WEB_FONTS)
  1426.  
  1427.                     /* Prefer fonts from the broker. */
  1428.                     font = fe_LoadRenderableFont(context, attr, charset,
  1429.                                                  familyname);
  1430.                     if (font)
  1431.                         font_type = FE_FONT_TYPE_RENDERABLE;
  1432. #endif
  1433.                     if (! font) {
  1434.  
  1435.                         /* First, determine whether any font is available
  1436.                          * in this charset; if not, the charset will be 
  1437.                          * reassigned to CS_LATIN1.
  1438.                          */
  1439.                         (void) fe_LoadFont(context, charset, NULL, 0, 3, 0);
  1440.  
  1441.                         font = fe_LoadFontWithoutSubstitution(context, charset,
  1442.                                     familyname, points, size, fontmask);
  1443.                         if (!font)
  1444.                             /* Try the other pitch */
  1445.                             font = fe_LoadFontWithoutSubstitution(context,
  1446.                                         charset, familyname, points, size,
  1447.                                         FE_FONT_MASK_TOGGLE_PITCH(fontmask));
  1448.                     }
  1449.  
  1450.                     if (font) break;
  1451.                     last_familyname = familyname;
  1452.                     familyname = NameFromList((char *) NULL);
  1453.         }
  1454.                 if (!font && last_familyname) {
  1455.                     font = fe_LoadFont(context, charset, last_familyname,
  1456.                                        points, size, fontmask);
  1457.                     if (!font)
  1458.             {
  1459.                             /* Try the other pitch */
  1460.                             font = fe_LoadFont(context, charset,
  1461.                                                familyname, points, size,
  1462.                                                FE_FONT_MASK_TOGGLE_PITCH(fontmask));
  1463.             }
  1464.                 }
  1465.                 XP_FREE(local_net_font_face);
  1466.     }
  1467.  
  1468.     /* If we didn't get a font from the face, default to no font_face */
  1469.     if (!font)
  1470.     {
  1471.             font =  fe_LoadFont(context, charset, NULL, points, size,
  1472.                                 fontmask);
  1473.     }
  1474.     if (font)
  1475.     {
  1476.                 fe_Font platform_font = font;
  1477.                 if (FE_FONT_TYPE_RENDERABLE != font_type)
  1478.                     font_type = fe_CharSetInfoArray[(*charset) & 0xff].type;
  1479.                 font = WrapPlatformFont(platform_font, font_type);
  1480.         if (attr)
  1481.         {
  1482.             attr->FE_Data = (void *) font;
  1483.         }
  1484.     }
  1485.         /* Preserve the document charset.  Web fonts may be used to
  1486.          * render glyphs in character sets which are not represented
  1487.          * in the platform-specific font catalog.  
  1488.          */
  1489.         *charset = saved_charset;
  1490.     return(font);
  1491. }
  1492.  
  1493.  
  1494. static fe_Font WrapPlatformFont(fe_Font platform_font, unsigned char font_type)
  1495. {
  1496.     fe_FontWrap *fw;
  1497.  
  1498.     fw = XP_NEW(fe_FontWrap);
  1499.     if (!fw) return NULL;
  1500.  
  1501.     fw->platform_font = platform_font;
  1502.     fw->distinguisher = font_type;
  1503.  
  1504.     return (fe_Font) fw;
  1505. }
  1506.  
  1507. /* Delete the wrapper but do not free the font. */
  1508. void fe_DoneWithFont(fe_Font font)
  1509. {
  1510.     XP_DELETE(font);
  1511. }
  1512.  
  1513. static void FreePlatformFont(Display *dpy, XFontStruct *xfs, LO_TextAttr *attr)
  1514. {
  1515.     XFontProp *prop;
  1516.     int n;
  1517.     fe_FontSize *size = 0;
  1518.     fe_FontSize **prev = 0;
  1519.     fe_FontFace *face = 0;
  1520.     fe_FontFamily *family;
  1521.     XP_Bool in_use;
  1522.     XP_Bool found;
  1523.     char * familyName;
  1524.     int pitch;
  1525.     Atom atom;
  1526.  
  1527.     /* Do not free fonts which fulfill requests for HTML sizes */
  1528.     if (attr->point_size < 1)
  1529.         return;
  1530.  
  1531.     /* Take the family name from the FAMILY_NAME property of the font */
  1532.     familyName = NULL;
  1533.     for (n = xfs->n_properties, prop=xfs->properties; --n >= 0; prop++) {
  1534.         if (XA_FAMILY_NAME == prop->name) {
  1535.             atom = prop->card32;
  1536.             familyName = XGetAtomName(dpy, atom);
  1537.             break;
  1538.         }
  1539.     }
  1540.     if (! familyName)
  1541.         return;
  1542.  
  1543.     /* Use the font family name, the requested charset and the 
  1544.      * requested pitch to find the family record.
  1545.      */
  1546.     pitch = FE_FONT_MASK_TO_PITCH(attr->fontmask);
  1547.     family = fe_FontFindFamily(attr->charset, pitch, familyName);
  1548.     if (! family) {
  1549.         pitch = FE_OPPOSITE_PITCH(pitch);
  1550.         family = fe_FontFindFamily(attr->charset, pitch, familyName);
  1551.     }
  1552.     if (! family && CS_LATIN1 != attr->charset) {
  1553.         pitch = FE_FONT_MASK_TO_PITCH(attr->fontmask);
  1554.         family = fe_FontFindFamily(CS_LATIN1, pitch, familyName);
  1555.         if (! family) {
  1556.             pitch = FE_OPPOSITE_PITCH(pitch);
  1557.             family = fe_FontFindFamily(CS_LATIN1, pitch, familyName);
  1558.         }
  1559.     }        
  1560.     XFree(familyName);
  1561.  
  1562.     /* Search through the family pool for a match on this xfs */
  1563.     found = False;
  1564.     if (family) {
  1565.         prev = &(family->pool);
  1566.         for (size = family->pool; size; prev = &(size->next), 
  1567.                  size = size->next) {
  1568.             for (n=0; n <= 3; n++) {
  1569.                 face = size->faces[n];
  1570.                 if (face && face->font == xfs) {
  1571.                     found = True;
  1572.                     break;
  1573.                 }
  1574.             }
  1575.             if (found)
  1576.                 break;
  1577.         }
  1578.     }
  1579.  
  1580.     /* Free the font and set the font field to NULL */
  1581.     if (found && size) {
  1582.         XFreeFont(dpy, xfs);
  1583.         face->font = NULL;
  1584.  
  1585.         /* If all the faces are not loaded, free the faces
  1586.          * and free the size record which points to them.
  1587.          */
  1588.         in_use = False;
  1589.         for (n=0; n < 4; n++) {
  1590.             if (size->faces[n]->font != NULL)
  1591.                 in_use = True;
  1592.         }
  1593.         if ((! in_use) && prev) {
  1594.             *prev = size->next;
  1595.             for (n=0; n < 4; n++) {
  1596.                 face = size->faces[n];
  1597.                 if (face->longXLFDFontName)
  1598.                     free(face->longXLFDFontName);
  1599.                 free(face);
  1600.             }
  1601.             free(size);
  1602.         }
  1603.     }
  1604. }
  1605.  
  1606. void FE_ReleaseTextAttrFeData(MWContext *context, LO_TextAttr *attr)
  1607. {
  1608.     fe_FontWrap *fw;
  1609.     struct nfrf *rf;
  1610.     XFontStruct *xfs;
  1611.     Display *dpy;
  1612.  
  1613.     if (!context || !attr)
  1614.         return;
  1615.  
  1616.     fw = (fe_FontWrap *) attr->FE_Data;
  1617.     if (! fw) return;
  1618.  
  1619.     switch (fw->distinguisher) {
  1620.     case FE_FONT_TYPE_X8:
  1621.     case FE_FONT_TYPE_X16:
  1622.         dpy = XtDisplay(CONTEXT_WIDGET(context));
  1623.         xfs = (XFontStruct *) fw->platform_font;
  1624.         FreePlatformFont(dpy, xfs, attr);
  1625.         break;
  1626.  
  1627.     case FE_FONT_TYPE_GROUP:
  1628.     default:
  1629.         break;
  1630.  
  1631.     case FE_FONT_TYPE_RENDERABLE:
  1632.         rf = (struct nfrf *) fw->platform_font;
  1633.         nfrf_release(rf, NULL);
  1634.         break;
  1635.     }
  1636.  
  1637.     XP_DELETE(fw);
  1638.     attr->FE_Data = NULL;
  1639. }
  1640.  
  1641. #ifndef NO_WEB_FONTS
  1642. static fe_Font fe_LoadRenderableFont(MWContext *context, LO_TextAttr *attr,
  1643.                                      int16 *charset, char *family)
  1644.  
  1645. {
  1646.     int weight;
  1647.     int escapement;
  1648.     int style;
  1649.     int underline;
  1650.     int strikeout;
  1651.     int charsetID;
  1652.     struct nfrc *  rc;
  1653.     struct nffmi * fmi;
  1654.     struct nff *   unsized_font = NULL;
  1655.     struct nfrf *  renderable_font = NULL;
  1656.     void *         rcbuf[4];
  1657.     double pointsize;
  1658.     char mime_name[128];
  1659.  
  1660.     if (!context || !attr || !charset)
  1661.         return (fe_Font) NULL;
  1662.     
  1663.     /* Create a rendering context */
  1664.  
  1665.     rcbuf[0] = XtDisplay(CONTEXT_WIDGET(context));
  1666.     rcbuf[1] = rcbuf[2] = NULL;
  1667.     rc = nffbu_CreateRenderingContext(fe_FontUtility, NF_RC_DIRECT, 0,
  1668.                                       rcbuf, 3, NULL);
  1669.     if (!rc)
  1670.         return (fe_Font) NULL;
  1671.  
  1672.     /* Create a font match information object */
  1673.  
  1674.     charsetID = *charset;
  1675.     if (charsetID < 0 || (charsetID & 0xff) >= INTL_CHAR_SET_MAX)
  1676.         return (fe_Font) NULL;
  1677.     INTL_CharSetIDToName(charsetID, mime_name);
  1678.     weight = attr->font_weight;
  1679.     if (0 == weight)
  1680.         weight = (LO_FONT_BOLD & attr->attrmask) ? 700 : 400;
  1681.     style = (LO_FONT_ITALIC & attr->attrmask)
  1682.         ? nfStyleItalic : nfStyleNormal;
  1683.     underline = (LO_ATTR_UNDERLINE & attr->attrmask) 
  1684.         ? nfUnderlineYes : nfUnderlineNo;
  1685.     strikeout = (LO_ATTR_STRIKEOUT & attr->attrmask)
  1686.         ? nfStrikeOutYes : nfStrikeOutNo;
  1687.     escapement = (LO_FONT_FIXED & attr->attrmask)
  1688.         ? nfSpacingMonospaced : nfSpacingProportional;
  1689.     fmi = nffbu_CreateFontMatchInfo(fe_FontUtility,
  1690.                                     family, NULL, mime_name, weight,
  1691.                                     escapement, style, underline, strikeout,
  1692.                                     nfResolutionDontCare,
  1693.                                     nfResolutionDontCare,
  1694.                                     NULL /* exception */);
  1695.  
  1696.     /* Create the font, cleanup, and return the font */
  1697.  
  1698.     if (fmi) {
  1699.         /* Find the url that is loading this font */
  1700.         History_entry *he = SHIST_GetCurrent(&context->hist);
  1701.         const char *accessing_url_str = NULL;
  1702.         if (he)
  1703.         {
  1704.              accessing_url_str = he->address;
  1705.         }
  1706.  
  1707.         unsized_font = nffbc_LookupFont(fe_FontBroker, rc, fmi,
  1708.                     accessing_url_str, NULL);
  1709.         if (!unsized_font) {
  1710.             nffbu_LookupFailed(fe_FontUtility, context, rc, fmi, NULL);
  1711.         }
  1712.         nffmi_release(fmi, NULL);
  1713.  
  1714.         if (unsized_font) {
  1715.  
  1716.             pointsize = attr->point_size;
  1717.             if (pointsize <= 0)
  1718.                 pointsize = fe_ConvertHTMLSizeToPointSize(attr, charsetID);
  1719.  
  1720.             renderable_font = nff_GetRenderableFont(unsized_font, rc,
  1721.                                                     pointsize, NULL);
  1722.             nff_release(unsized_font, NULL);
  1723.         }
  1724.     }
  1725.     nfrc_release(rc, NULL);
  1726.     return ((fe_Font) renderable_font);
  1727. }
  1728.  
  1729.  
  1730. int fe_WebfontsNeedReload(MWContext *context)
  1731. {
  1732.     int ret = 0;
  1733.     if (fe_FontUtility)
  1734.     {
  1735.         ret = nffbu_WebfontsNeedReload(fe_FontUtility, context, NULL);
  1736.     }
  1737.     return (ret);
  1738. }
  1739.  
  1740. void fe_ShutdownWebfonts(void)
  1741. {
  1742.     char buf[MAXPATHLEN];
  1743.     char *home = NULL;
  1744.  
  1745.     /* Load Catalog */
  1746.     if (home = getenv("HOME"))
  1747.     {
  1748.         /* Form "$HOME/.netscape/dynfonts/fonts.cat" into buf */
  1749.         strncpy(buf, home, sizeof(buf)-1);
  1750.         strncat(buf, "/.netscape/dynfonts/fonts.cat",
  1751.                 sizeof(buf)-1 - strlen(buf));
  1752.         buf[sizeof(buf)-1] = '\0';
  1753.         nffbu_SaveCatalog(fe_FontUtility, buf, NULL);
  1754.     }
  1755. }
  1756.  
  1757.  
  1758. static double fe_ConvertHTMLSizeToPointSize(LO_TextAttr *attr, int16 charset)
  1759. {
  1760.     int j;
  1761.     int size3;
  1762.     double decipoints = 0.0;
  1763.     fe_FontFamily *family;
  1764.     fe_FontSize *size;
  1765.     int pitch;
  1766.     double pointsize;
  1767.  
  1768.     /* Translate HTML sizes 1-7 to pointsize */
  1769.  
  1770.     /* Take the default size of the default family for
  1771.      * this charset to be the pointsize of HTML size 3,
  1772.      * if it is given; otherwise, use 12 points.
  1773.      */
  1774.     size3 = 0;
  1775.     size = NULL;
  1776.     pitch = FE_FONT_MASK_TO_PITCH(attr->attrmask);
  1777.     family = FE_FONT_SELECTED_FAMILY(charset, pitch);
  1778.     if (family && family->name) {
  1779.         for (j = 0; j < family->numberOfPointSizes; j++) {
  1780.             size = &family->pointSizes[j];
  1781.             if (size->selected) {
  1782.                 break;
  1783.             } else {
  1784.                 size = NULL;
  1785.             }
  1786.         }
  1787.         if (size)
  1788.             size3 = size->size;
  1789.         if (!size3)
  1790.             size3 = family->scaledSize;
  1791.     }
  1792.     if (!size3)
  1793.         size3 = 120;
  1794.  
  1795.     /* Sizing logic from fe_ComputeFontSizeTable */
  1796.     if (attr->size < 3) {
  1797.         decipoints = ((1 - ((3 - attr->size)
  1798.                             * fe_FontSizeIncrement)) * size3);
  1799.         if (decipoints < 10)
  1800.             decipoints = 10;
  1801.     } else if (attr->size == 3) {
  1802.         decipoints = size3;
  1803.     } else if (attr->size > 3) {
  1804.         decipoints = ((1 + ((attr->size - 3)
  1805.                             * fe_FontSizeIncrement)) * size3);
  1806.     }
  1807.  
  1808.     pointsize = decipoints / 10;
  1809.     return pointsize;
  1810. }
  1811.  
  1812. #endif /* ifndef NO_WEB_FONTS */
  1813.  
  1814.  
  1815. XtPointer
  1816. fe_GetFontOrFontSetFromFace(MWContext *context, LO_TextAttr *attr, char *net_font_face,
  1817.                 int size, int fontmask, XmFontType *type)
  1818. {
  1819.     XtPointer fontOrFontset = 0;
  1820.     char *local_net_font_face = NULL;
  1821.     char *familyname = NULL;
  1822.  
  1823.     if (attr)
  1824.     {
  1825.         fontOrFontset = (fe_Font) attr->FE_Data;
  1826.         if (fontOrFontset) return(fontOrFontset);
  1827.     }
  1828.     
  1829.     if (net_font_face && *net_font_face)
  1830.     {
  1831.         local_net_font_face = strdup(net_font_face);
  1832.         if (!local_net_font_face) return (0);
  1833.         familyname = NameFromList(local_net_font_face);
  1834.         while (familyname)
  1835.         {
  1836.             fontOrFontset = fe_GetFontOrFontSet(context, familyname, size,
  1837.                                 fontmask, type);
  1838.             if (!fontOrFontset)
  1839.             {
  1840.                 /* Try the other pitch */
  1841.                 fontOrFontset = fe_GetFontOrFontSet(context, familyname, size,
  1842.                                     FE_FONT_MASK_TOGGLE_PITCH(fontmask),
  1843.                                     type);
  1844.             }
  1845.             if (fontOrFontset) break;
  1846.             familyname = NameFromList((char *) NULL);
  1847.         }
  1848.         XP_FREE(local_net_font_face);
  1849.     }
  1850.     
  1851.     if (!fontOrFontset)
  1852.     {
  1853.         fontOrFontset = fe_GetFontOrFontSet(context, NULL, size,
  1854.                             fontmask, type);
  1855.     }
  1856.     if (fontOrFontset)
  1857.     {
  1858.         if (attr)
  1859.         {
  1860.             attr->FE_Data = (void *) fontOrFontset;
  1861.         }
  1862.     }
  1863.     return(fontOrFontset);
  1864. }
  1865.  
  1866.  
  1867. static void *
  1868. fe_ReallocZap(void *p, int oldSize, int newSize)
  1869. {
  1870.     char    *end;
  1871.     char    *q;
  1872.  
  1873.     p = realloc(p, newSize);
  1874.     if (p)
  1875.     {
  1876.         if (newSize > oldSize)
  1877.         {
  1878.             end = ((char *) p) + newSize;
  1879.             for (q = ((char *) p) + oldSize; q < end; q++)
  1880.             {
  1881.                 *q = 0;
  1882.             }
  1883.         }
  1884.     }
  1885.  
  1886.     return p;
  1887. }
  1888.  
  1889.  
  1890. #define FE_REALLOC_ZAP(p, oldSize, newSize, type) \
  1891.   ((type *) fe_ReallocZap((p), (oldSize) * sizeof(type), \
  1892.     (newSize) * sizeof(type)))
  1893.  
  1894.  
  1895. static char *
  1896. fe_CapitalizeFontName(char *name)
  1897. {
  1898.     char    *p;
  1899.     char    *ret;
  1900.  
  1901.     ret = strdup(name);
  1902.     if (!ret)
  1903.     {
  1904.         return NULL;
  1905.     }
  1906.  
  1907.     p = ret;
  1908.     while (1)
  1909.     {
  1910.         while ((*p) && XP_IS_SPACE(*p))
  1911.         {
  1912.             p++;
  1913.         }
  1914.         if (!*p)
  1915.         {
  1916.             break;
  1917.         }
  1918.         *p = XP_TO_UPPER(*p);
  1919.         while ((*p) && (!XP_IS_SPACE(*p)))
  1920.         {
  1921.             p++;
  1922.         }
  1923.         if (!*p)
  1924.         {
  1925.             break;
  1926.         }
  1927.     }
  1928.  
  1929.     return ret;
  1930. }
  1931.  
  1932.  
  1933. static void
  1934. fe_AddFontSize(fe_FontFamily *family, int faceNum, int pixelSizeNum,
  1935.     int pointSizeNum, char *pixelSizeFontSpec, char *pointSizeFontSpec)
  1936. {
  1937.     int        alloc;
  1938.     fe_FontFace    *face;
  1939.     int        i;
  1940.     fe_FontSize    *newSizes;
  1941.     fe_FontSize    *size;
  1942.  
  1943.     /*
  1944.      * first we do the pixel size
  1945.      */
  1946.  
  1947.     size = NULL;
  1948.  
  1949.     if (family->pixelSizes)
  1950.     {
  1951.         for (i = 0; i < family->numberOfPixelSizes; i++)
  1952.         {
  1953.             size = &family->pixelSizes[i];
  1954.             if (size->size == pixelSizeNum)
  1955.             {
  1956.                 break;
  1957.             }
  1958.             else
  1959.             {
  1960.                 size = NULL;
  1961.             }
  1962.         }
  1963.     }
  1964.  
  1965.     if (!size)
  1966.     {
  1967.         if (family->numberOfPixelSizes >= family->pixelAlloc)
  1968.         {
  1969.             alloc = (2 * (family->pixelAlloc + 1));
  1970.             newSizes = FE_REALLOC_ZAP(family->pixelSizes,
  1971.                 family->pixelAlloc, alloc, fe_FontSize);
  1972.             if (!newSizes)
  1973.             {
  1974.                 return;
  1975.             }
  1976.             family->pixelSizes = newSizes;
  1977.             family->pixelAlloc = alloc;
  1978.         }
  1979.         size = &family->pixelSizes[family->numberOfPixelSizes++];
  1980.         size->size = pixelSizeNum;
  1981.     }
  1982.  
  1983.     if (!size->faces[faceNum])
  1984.     {
  1985.         face = FE_MALLOC_ZAP(fe_FontFace);
  1986.         if (!face)
  1987.         {
  1988.             return;
  1989.         }
  1990.         face->longXLFDFontName = strdup(pixelSizeFontSpec);
  1991.         if (!face->longXLFDFontName)
  1992.         {
  1993.             free(face);
  1994.             return;
  1995.         }
  1996.         face->next = fe_FontFaceList;
  1997.         fe_FontFaceList = face;
  1998.         size->faces[faceNum] = face;
  1999.     }
  2000.     else
  2001.     {
  2002.         /* @@@ fix this -- erik */
  2003.         /*
  2004.         (void) fprintf(real_stderr, "dup %s\n", pixelSizeFontSpec);
  2005.         */
  2006.     }
  2007.  
  2008.     /*
  2009.      * now we do the same for the point size
  2010.      */
  2011.  
  2012.     size = NULL;
  2013.  
  2014.     if (family->pointSizes)
  2015.     {
  2016.         for (i = 0; i < family->numberOfPointSizes; i++)
  2017.         {
  2018.             size = &family->pointSizes[i];
  2019.             if (size->size == pointSizeNum)
  2020.             {
  2021.                 break;
  2022.             }
  2023.             else
  2024.             {
  2025.                 size = NULL;
  2026.             }
  2027.         }
  2028.     }
  2029.  
  2030.     if (!size)
  2031.     {
  2032.         if (family->numberOfPointSizes >= family->pointAlloc)
  2033.         {
  2034.             alloc = (2 * (family->pointAlloc + 1));
  2035.             newSizes = FE_REALLOC_ZAP(family->pointSizes,
  2036.                 family->pointAlloc, alloc, fe_FontSize);
  2037.             if (!newSizes)
  2038.             {
  2039.                 return;
  2040.             }
  2041.             family->pointSizes = newSizes;
  2042.             family->pointAlloc = alloc;
  2043.         }
  2044.         size = &family->pointSizes[family->numberOfPointSizes++];
  2045.         size->size = pointSizeNum;
  2046.     }
  2047.  
  2048.     if (!size->faces[faceNum])
  2049.     {
  2050.         face = FE_MALLOC_ZAP(fe_FontFace);
  2051.         if (!face)
  2052.         {
  2053.             return;
  2054.         }
  2055.         face->longXLFDFontName = strdup(pointSizeFontSpec);
  2056.         if (!face->longXLFDFontName)
  2057.         {
  2058.             free(face);
  2059.             return;
  2060.         }
  2061.         face->next = fe_FontFaceList;
  2062.         fe_FontFaceList = face;
  2063.         size->faces[faceNum] = face;
  2064.     }
  2065.     else
  2066.     {
  2067.         /* @@@ fix this -- erik */
  2068.         /*
  2069.         (void) fprintf(real_stderr, "dup %s\n", pointSizeFontSpec);
  2070.         */
  2071.     }
  2072. }
  2073.  
  2074.  
  2075. static void
  2076. fe_AddFontFamily(fe_FontPitch *pitch, char *origFoundry, char *foundry,
  2077.     char *origFamily, char *familyName, int face, int pixelSize,
  2078.     int pointSize, char *pixelSizeFontSpec, char *pointSizeFontSpec,
  2079.     int charsetID, char *origCharset)
  2080. {
  2081.     int        alloc;
  2082.     fe_FontFamily    *family;
  2083.     int        i;
  2084.     char        *name;
  2085.     fe_FontFamily    *newFamilies;
  2086.  
  2087.     if (charsetID == CS_USRDEF2)
  2088.     {
  2089.         if (*foundry)
  2090.         {
  2091.             name = PR_smprintf("%s (%s, %s)", familyName, foundry,
  2092.                 origCharset);
  2093.         }
  2094.         else
  2095.         {
  2096.             name = PR_smprintf("%s (%s)", familyName, origCharset);
  2097.         }
  2098.     }
  2099.     else
  2100.     {
  2101.         if (*foundry)
  2102.         {
  2103.             name = PR_smprintf("%s (%s)", familyName, foundry);
  2104.         }
  2105.         else
  2106.         {
  2107.             name = strdup(familyName);
  2108.         }
  2109.     }
  2110.     if (!name)
  2111.     {
  2112.         return;
  2113.     }
  2114.  
  2115.     family = NULL;
  2116.  
  2117.     if (pitch->families)
  2118.     {
  2119.         for (i = 0; i < pitch->numberOfFamilies; i++)
  2120.         {
  2121.             family = &pitch->families[i];
  2122.             if (!strcmp(family->name, name))
  2123.             {
  2124.                 break;
  2125.             }
  2126.             else
  2127.             {
  2128.                 family = NULL;
  2129.             }
  2130.         }
  2131.     }
  2132.  
  2133.     if (family)
  2134.     {
  2135.         free(name);
  2136.     }
  2137.     else
  2138.     {
  2139.         if (pitch->numberOfFamilies >= pitch->alloc)
  2140.         {
  2141.             alloc = (2 * (pitch->alloc + 1));
  2142.             newFamilies = FE_REALLOC_ZAP(pitch->families,
  2143.                 pitch->alloc, alloc, fe_FontFamily);
  2144.             if (!newFamilies)
  2145.             {
  2146.                 free(name);
  2147.                 return;
  2148.             }
  2149.             pitch->families = newFamilies;
  2150.             pitch->alloc = alloc;
  2151.         }
  2152.         family = &pitch->families[pitch->numberOfFamilies++];
  2153.         family->name = name;
  2154.         family->family = strdup(origFamily);
  2155.         family->foundry = strdup(origFoundry);
  2156.     }
  2157.  
  2158.     fe_AddFontSize(family, face, pixelSize, pointSize, pixelSizeFontSpec,
  2159.         pointSizeFontSpec);
  2160. }
  2161.  
  2162.  
  2163. static void
  2164. fe_AddFontCharSet(char *origFoundry, char *foundry, char *origFamily,
  2165.     char *family, int face, int pixelSize, int pointSize, int pitch,
  2166.     int charsetID, char *charset, char *charsetlang,
  2167.     char *pixelSizeFontSpec, char *pointSizeFontSpec, char *origCharset)
  2168. {
  2169.     char    mimeName[128];
  2170.     char    *name;
  2171.  
  2172.     if ((charsetID < 0) || (charsetID >= INTL_CHAR_SET_MAX))
  2173.     {
  2174.         return;
  2175.     }
  2176.  
  2177.     if (!fe_FontCharSets[charsetID].name)
  2178.     {
  2179.         if (charsetID == CS_USRDEF2)
  2180.         {
  2181.             name = strdup(XP_GetString(XFE_USER_DEFINED));
  2182.         }
  2183.         else
  2184.         {
  2185.             name = PR_smprintf("%s (%s)", charsetlang, charset);
  2186.         }
  2187.         if (!name)
  2188.         {
  2189.             return;
  2190.         }
  2191.         fe_FontCharSets[charsetID].name = name;
  2192.  
  2193.         INTL_CharSetIDToName(charsetID, mimeName);
  2194.         fe_FontCharSets[charsetID].mimeName = strdup(mimeName);
  2195.         if (!fe_FontCharSets[charsetID].mimeName)
  2196.         {
  2197.             return;
  2198.         }
  2199.     }
  2200.  
  2201.     if (pitch & fe_FONT_PITCH_PROPORTIONAL)
  2202.     {
  2203.         fe_AddFontFamily(&fe_FontCharSets[charsetID].pitches[0],
  2204.             origFoundry, foundry, origFamily, family, face,
  2205.             pixelSize, pointSize, pixelSizeFontSpec,
  2206.             pointSizeFontSpec, charsetID, origCharset);
  2207.     }
  2208.  
  2209.     if (pitch & fe_FONT_PITCH_MONO)
  2210.     {
  2211.         fe_AddFontFamily(&fe_FontCharSets[charsetID].pitches[1],
  2212.             origFoundry, foundry, origFamily, family, face,
  2213.             pixelSize, pointSize, pixelSizeFontSpec,
  2214.             pointSizeFontSpec, charsetID, origCharset);
  2215.     }
  2216. }
  2217.  
  2218.  
  2219. static char *
  2220. fe_PropOrFixedFont(int i)
  2221. {
  2222.     return i == 0 ? "prop" : "fixed";
  2223. }
  2224.  
  2225.  
  2226. #define FE_INDEX_TO_FACE(face) (face == 0 ? "normal" : face == 1 ? "bold" : \
  2227.     face == 2 ? "italic" : "boldItalic")
  2228.  
  2229.  
  2230. #ifdef FE_PRINT_FONTS
  2231. static void
  2232. fe_PrintFamily(fe_FontFamily *family)
  2233. {
  2234.     fe_FontFace    *face;
  2235.     int        i;
  2236.     int        j;
  2237.     fe_FontSize    *size;
  2238.  
  2239.         (void) fprintf(real_stderr, "    %s\n", family->name);
  2240.     for (i = 0; i < family->numberOfPointSizes; i++)
  2241.     {
  2242.         size = &family->pointSizes[i];
  2243.         (void) fprintf(real_stderr, "      %d\n", size->size / 10);
  2244.         for (j = 0; j < 4; j++)
  2245.         {
  2246.             (void) fprintf(real_stderr, "        %s\n",
  2247.                 FE_INDEX_TO_FACE(j));
  2248.             face = size->faces[j];
  2249.             (void) fprintf(real_stderr, "          %s\n",
  2250.                     face->longXLFDFontName);
  2251.         }
  2252.     }
  2253. }
  2254.  
  2255.  
  2256. static void
  2257. fe_PrintFonts(void)
  2258. {
  2259.     fe_FontCharSet    *charset;
  2260.     int        i;
  2261.     int        j;
  2262.     int        k;
  2263.     fe_FontPitch    *pitch;
  2264.  
  2265.     for (i = 0; i < INTL_CHAR_SET_MAX; i++)
  2266.     {
  2267.         charset = &fe_FontCharSets[i];
  2268.         if (!charset->name)
  2269.         {
  2270.             continue;
  2271.         }
  2272.         (void) fprintf(real_stderr, "%s\n", charset->name);
  2273.         for (j = 0; j < 2; j++)
  2274.         {
  2275.             (void) fprintf(real_stderr, "  %s\n",
  2276.                 fe_PropOrFixedFont(j));
  2277.             pitch = &charset->pitches[j];
  2278.             for (k = 0; k < pitch->numberOfFamilies; k++)
  2279.             {
  2280.                 fe_PrintFamily(&pitch->families[k]);
  2281.             }
  2282.         }
  2283.     }
  2284. }
  2285. #endif /* FE_PRINT_FONTS */
  2286.  
  2287.  
  2288. static int
  2289. fe_CompareFontCharSets(unsigned char *charset1, unsigned char *charset2)
  2290. {
  2291.     char    *name1;
  2292.     char    *name2;
  2293.  
  2294.     name1 = fe_FontCharSets[*charset1].name;
  2295.     name2 = fe_FontCharSets[*charset2].name;
  2296.  
  2297.     if (!name1)
  2298.     {
  2299.         if (!name2)
  2300.         {
  2301.             return 0;
  2302.         }
  2303.  
  2304.         return 1;
  2305.     }
  2306.  
  2307.     if (!name2)
  2308.     {
  2309.         return -1;
  2310.     }
  2311.  
  2312.     return strcmp(name1, name2);
  2313. }
  2314.  
  2315.  
  2316. static int
  2317. fe_CompareFontFamilies(fe_FontFamily *family1, fe_FontFamily *family2)
  2318. {
  2319.     return strcmp(family1->name, family2->name);
  2320. }
  2321.  
  2322.  
  2323. static int
  2324. fe_CompareFontSizes(fe_FontSize *size1, fe_FontSize *size2)
  2325. {
  2326.     return size1->size - size2->size;
  2327. }
  2328.  
  2329.  
  2330. typedef int (*fe_CompFunc)(const void *, const void *);
  2331.  
  2332.  
  2333. static void
  2334. fe_SortFonts(void)
  2335. {
  2336.     fe_FontCharSet    *charset;
  2337.     fe_FontFamily    *family;
  2338.     int        i;
  2339.     int        j;
  2340.     int        k;
  2341.     fe_FontPitch    *pitch;
  2342.  
  2343.  
  2344.     for (i = 0; i < INTL_CHAR_SET_MAX; i++)
  2345.     {
  2346.         fe_SortedFontCharSets[i] = i;
  2347.     }
  2348.     XP_QSORT(fe_SortedFontCharSets, INTL_CHAR_SET_MAX,
  2349.              sizeof(*fe_SortedFontCharSets),
  2350.              (fe_CompFunc) fe_CompareFontCharSets);
  2351.  
  2352.  
  2353.     for (i = 0; i < INTL_CHAR_SET_MAX; i++)
  2354.     {
  2355.         charset = &fe_FontCharSets[i];
  2356.         if (!charset->name)
  2357.         {
  2358.             continue;
  2359.         }
  2360.         for (j = 0; j < 2; j++)
  2361.         {
  2362.             pitch = &charset->pitches[j];
  2363.             if (pitch->families)
  2364.             {
  2365.                 XP_QSORT(pitch->families, pitch->numberOfFamilies,
  2366.                          sizeof(fe_FontFamily),
  2367.                          (fe_CompFunc) fe_CompareFontFamilies);
  2368.             }
  2369.             for (k = 0; k < pitch->numberOfFamilies; k++)
  2370.             {
  2371.                 family = &pitch->families[k];
  2372.                 XP_QSORT(family->pixelSizes,
  2373.                          family->numberOfPixelSizes,
  2374.                          sizeof(fe_FontSize),
  2375.                          (fe_CompFunc) fe_CompareFontSizes);
  2376.                 XP_QSORT(family->pointSizes,
  2377.                          family->numberOfPointSizes,
  2378.                          sizeof(fe_FontSize),
  2379.                          (fe_CompFunc) fe_CompareFontSizes);
  2380.             }
  2381.         }
  2382.     }
  2383. }
  2384.  
  2385.  
  2386. void
  2387. fe_ReadFontCharSet(char *charsetname)
  2388. {
  2389.     fe_FontCharSet    *charset;
  2390.     int16        charsetID;
  2391.     int        i;
  2392.  
  2393.     charsetID = (INTL_CharSetNameToID(charsetname) & 0xff);
  2394.     if ((charsetID < 0) || (charsetID >= INTL_CHAR_SET_MAX))
  2395.     {
  2396.         charsetID = CS_LATIN1;
  2397.     }
  2398.     charsetID &= 0xff;
  2399.  
  2400.     for (i = 0; i < INTL_CHAR_SET_MAX; i++)
  2401.     {
  2402.         fe_FontCharSets[i].selected = 0;
  2403.     }
  2404.  
  2405.     charset = &fe_FontCharSets[charsetID];
  2406.     if (charset->name)
  2407.     {
  2408.         charset->selected = 1;
  2409.     }
  2410.     else
  2411.     {
  2412.         charset = NULL;
  2413.         for (i = 0; i < INTL_CHAR_SET_MAX; i++)
  2414.         {
  2415.             charset = &fe_FontCharSets[i];
  2416.             if (!charset->name)
  2417.             {
  2418.                 charset = NULL;
  2419.                 continue;
  2420.             }
  2421.             charset->selected = 1;
  2422.             break;
  2423.         }
  2424.     }
  2425.     if (!charset)
  2426.     {
  2427.         /* this should never happen */
  2428.         (void) fprintf(real_stderr, "no recognized font charsets!\n");
  2429.         exit(1);
  2430.     }
  2431. }
  2432.  
  2433.  
  2434. void
  2435. fe_ReadFontSpec(char *spec)
  2436. {
  2437.     fe_FontCharSet    *charset;
  2438.     char        *charSetName;
  2439.     fe_FontFamily    *family;
  2440.     char        *familyName;
  2441.     char        *foundry;
  2442.     int        i;
  2443.     int        j;
  2444.     int        k;
  2445.     int        m;
  2446.     char        *p;
  2447.     fe_FontPitch    *pitch;
  2448.     char        *pitchName;
  2449.     char        *s;
  2450.     char        *scaling;
  2451.     fe_FontSize    *size;
  2452.     char        *sizeName;
  2453.     int        sizeNum;
  2454.  
  2455.     s = strdup(spec);
  2456.     if (!s)
  2457.     {
  2458.         return;
  2459.     }
  2460.  
  2461.     p = s;
  2462.  
  2463.     foundry = p;
  2464.     p = strchr(p, '-');
  2465.     if (!p)
  2466.     {
  2467.         return;
  2468.     }
  2469.     *p++ = 0;
  2470.  
  2471.     familyName = p;
  2472.     p = strchr(p, '-');
  2473.     if (!p)
  2474.     {
  2475.         return;
  2476.     }
  2477.     *p++ = 0;
  2478.  
  2479.     sizeName = p;
  2480.     p = strchr(p, '-');
  2481.     if (!p)
  2482.     {
  2483.         return;
  2484.     }
  2485.     *p++ = 0;
  2486.     (void) sscanf(sizeName, "%d", &sizeNum);
  2487.  
  2488.     scaling = p;
  2489.     p = strchr(p, '-');
  2490.     if (!p)
  2491.     {
  2492.         return;
  2493.     }
  2494.     *p++ = 0;
  2495.  
  2496.     pitchName = p;
  2497.     p = strchr(p, '-');
  2498.     if (!p)
  2499.     {
  2500.         return;
  2501.     }
  2502.     *p++ = 0;
  2503.  
  2504.     charSetName = p;
  2505.  
  2506.  
  2507.     for (i = 0; i < INTL_CHAR_SET_MAX; i++)
  2508.     {
  2509.         charset = &fe_FontCharSets[i];
  2510.         if ((!charset->name) || strcmp(charset->mimeName, charSetName))
  2511.         {
  2512.             continue;
  2513.         }
  2514.  
  2515.         j = (*pitchName == 'p' ? 0 : 1);
  2516.         pitch = &charset->pitches[j];
  2517.  
  2518.         family = NULL;
  2519.         for (k = 0; k < pitch->numberOfFamilies; k++)
  2520.         {
  2521.             family = &pitch->families[k];
  2522.  
  2523.             if ((!strcmp(family->foundry, foundry)) &&
  2524.                 (!strcmp(family->family, familyName)))
  2525.             {
  2526.                 break;
  2527.             }
  2528.             else
  2529.             {
  2530.                 family = NULL;
  2531.             }
  2532.         }
  2533.         if (family)
  2534.         {
  2535.             for (k = 0; k < pitch->numberOfFamilies; k++)
  2536.             {
  2537.                 pitch->families[k].selected = 0;
  2538.             }
  2539.             family->selected = 1;
  2540.             pitch->selectedFamily = family;
  2541.  
  2542.             family->allowScaling = (((*scaling) == 's') ? 1 : 0);
  2543.  
  2544.             /*
  2545.              * sanity check
  2546.              */
  2547.             if (family->pointSizes->size)
  2548.             {
  2549.                 family->allowScaling = 0;
  2550.             }
  2551.             else if (family->numberOfPointSizes == 1)
  2552.             {
  2553.                 family->allowScaling = 1;
  2554.             }
  2555.  
  2556.             size = NULL;
  2557.             for (m = 0; m < family->numberOfPointSizes; m++)
  2558.             {
  2559.                 size = &family->pointSizes[m];
  2560.                 if (size->size == sizeNum)
  2561.                 {
  2562.                     break;
  2563.                 }
  2564.                 else
  2565.                 {
  2566.                     size = NULL;
  2567.                 }
  2568.             }
  2569.             if (size)
  2570.             {
  2571.                 for (m = 0; m < family->numberOfPointSizes; m++)
  2572.                 {
  2573.                     family->pointSizes[m].selected = 0;
  2574.                 }
  2575.                 size->selected = 1;
  2576.             }
  2577.             else if (family->allowScaling)
  2578.             {
  2579.                 for (m = 0; m < family->numberOfPointSizes; m++)
  2580.                 {
  2581.                     family->pointSizes[m].selected = 0;
  2582.                 }
  2583.                 family->pointSizes[0].selected = 1;
  2584.                 family->scaledSize = sizeNum;
  2585.             }
  2586.         }
  2587.  
  2588.         break;
  2589.     }
  2590.  
  2591.     free(s);
  2592. }
  2593.  
  2594.  
  2595. static fe_FontSize *
  2596. fe_GetScaledFontSize(fe_FontFamily *family, double idealSize, XP_Bool make_global)
  2597. {
  2598.     fe_FontFace    *face;
  2599.     int        i;
  2600.     fe_FontSize    *ret;
  2601.  
  2602.     ret = FE_MALLOC_ZAP(fe_FontSize);
  2603.     if (!ret)
  2604.     {
  2605.         return NULL;
  2606.     }
  2607.         if (make_global) {
  2608.             ret->next = fe_FontSizeList;
  2609.             fe_FontSizeList = ret;
  2610.         }
  2611.  
  2612.     ret->size = idealSize;
  2613.  
  2614.     for (i = 0; i < 4; i++)
  2615.     {
  2616.         ret->faces[i] = FE_MALLOC_ZAP(fe_FontFace);
  2617.         face = ret->faces[i];
  2618.         if (!face)
  2619.         {
  2620.             return NULL;
  2621.         }
  2622.                 if (make_global) {
  2623.                     face->next = fe_FontFaceList;
  2624.                     fe_FontFaceList = face;
  2625.                 }
  2626.         face->longXLFDFontName = PR_smprintf(
  2627.             family->pointSizes->faces[i]->longXLFDFontName,
  2628.             ret->size);
  2629.         if (!face->longXLFDFontName)
  2630.         {
  2631.             return NULL;
  2632.         }
  2633.     }
  2634.  
  2635.     return ret;
  2636. }
  2637.  
  2638.  
  2639. static fe_FontSize *
  2640. fe_FindFontPointSize(fe_FontFamily *family, double idealSize,
  2641.                      XP_Bool search_for_fit, XP_Bool scale_to_fit)
  2642. {
  2643.     int        i;
  2644.     double        minDist;
  2645.     fe_FontSize    *minSize;
  2646.     fe_FontSize    *maxSize;
  2647.     double        newDist;
  2648.     fe_FontSize    *ret;
  2649.     fe_FontSize    *size;
  2650.  
  2651.     ret = NULL;
  2652.  
  2653.         if (! family->pointSizes)
  2654.             return NULL;
  2655.  
  2656.     if (family->pointSizes->size == 0)
  2657.     {
  2658.         minSize = &family->pointSizes[1];
  2659.     }
  2660.     else
  2661.     {
  2662.         minSize = family->pointSizes;
  2663.     }
  2664.     maxSize = &family->pointSizes[family->numberOfPointSizes - 1];
  2665.  
  2666.     if ((idealSize < minSize->size) || (idealSize > maxSize->size))
  2667.     {
  2668.         if (idealSize > maxSize->size)
  2669.         {
  2670.             ret = maxSize;
  2671.         }
  2672.         if (idealSize < minSize->size)
  2673.         {
  2674.             ret = minSize;
  2675.         }
  2676.     }
  2677.     else
  2678.     {
  2679.                 minDist = (1E+36);
  2680.         ret = family->pointSizes;
  2681.         for (i = 0; i < family->numberOfPointSizes; i++)
  2682.         {
  2683.             size = &family->pointSizes[i];
  2684.             newDist = ((idealSize - size->size) *
  2685.                    (idealSize - size->size));
  2686.             if (newDist < minDist)
  2687.             {
  2688.                 minDist = newDist;
  2689.                 ret = size;
  2690.             }
  2691.             else
  2692.             {
  2693.                 break;
  2694.             }
  2695.         }
  2696.     }
  2697.  
  2698.         if (search_for_fit) {
  2699.  
  2700.             minDist =  (ret)
  2701.                 ? ((idealSize - ret->size) * (idealSize - ret->size))
  2702.                 : (1E+36);
  2703.  
  2704.             for (size = family->pool; size; size = size->next) {
  2705.                 newDist = ((idealSize - size->size) *
  2706.                            (idealSize - size->size));
  2707.                 if (newDist < minDist) {
  2708.                     minDist = newDist;
  2709.                     ret = size;
  2710.                 }
  2711.             }
  2712.         }
  2713.  
  2714.         if (scale_to_fit) {
  2715.  
  2716.             /* We have deliberately first searched through the array
  2717.              * of HTML point sizes for a match within 1/2 point of the
  2718.              * requested point size because we prefer hand-tuned bitmaps
  2719.              * to scaled outlines, all other things being equal.
  2720.              */
  2721.  
  2722.             minDist =  (ret)
  2723.                 ? ((idealSize - ret->size) * (idealSize - ret->size))
  2724.                 : (1E+36);
  2725.  
  2726.             if (0 == family->pointSizes->size && minDist > 0.25) {
  2727.  
  2728.                 size = fe_GetScaledFontSize(family, idealSize, False);
  2729.                 if (size) {
  2730.  
  2731.                     /* mark to be freed when the context expires */
  2732.                     size->in_pool = 1;
  2733.  
  2734.                     /* hang off of the family */
  2735.                     size->next = family->pool;
  2736.                     family->pool = size;
  2737.  
  2738.                     ret = size;
  2739.                 }
  2740.             }
  2741.         }
  2742.  
  2743.     return ret;
  2744. }
  2745.  
  2746.  
  2747. static fe_FontSize *
  2748. fe_ComputeFontSize(fe_FontFamily *family, double idealSize)
  2749. {
  2750.     if (family->allowScaling)
  2751.         return fe_GetScaledFontSize(family, idealSize, True);
  2752.  
  2753.     /* Pass False for scale_to_fit: fe_ComputeFontSize
  2754.      * is used only to compute the table of HTML sizes.  
  2755.      * In integrating the range of sizes allowed by CSS-1, we want
  2756.      * no perturbation of font sizes as they are instantiated through
  2757.      * HTML size requests.  Therefore, offer to scale outline fonts
  2758.      * in the construction of the HTML size table only when the
  2759.      * allowScaling flag is set for that particular family, as was
  2760.      * the case prior to CSS-1.
  2761.      */
  2762.  
  2763.     return fe_FindFontPointSize(family, idealSize, False, False);
  2764. }
  2765.  
  2766.  
  2767. void
  2768. fe_FreeFontGroups(void)
  2769. {
  2770. #if 0
  2771.     fe_FontCharSet    *charset;
  2772.     fe_FontFace    *face;
  2773.     int        i;
  2774.     int        j;
  2775.     int        k;
  2776.     int        m;
  2777.     fe_FontPitch    *pitch;
  2778.     fe_FontSize    *size;
  2779.  
  2780.     for (i = 0; i < INTL_CHAR_SET_MAX; i++)
  2781.     {
  2782.         charset = &fe_FontCharSets[i];
  2783.         if (fe_CharSetInfoArray[i].type == FE_FONT_TYPE_GROUP)
  2784.         {
  2785.             for (j = 0; j < 2; j++)
  2786.             {
  2787.                 pitch = &charset->pitches[j];
  2788.                 if (!pitch->selectedFamily)
  2789.                 {
  2790.                     continue;
  2791.                 }
  2792.                 for (k = 0; k < 7; k++)
  2793.                 {
  2794.                     size = pitch->selectedFamily->htmlSizes[k];
  2795.                     if (size)
  2796.                     {
  2797.                         for (m = 0; m < 4; m++)
  2798.                         {
  2799.                             face = size->faces[m];
  2800.                             if (face)
  2801.                             {
  2802.                                 free(face);
  2803.                             }
  2804.                         }
  2805.                         free(size);
  2806.                     }
  2807.                 }
  2808.                 free(pitch->selectedFamily);
  2809.                 pitch->selectedFamily = NULL;
  2810.             }
  2811.         }
  2812.     }
  2813. #endif
  2814. }
  2815.  
  2816. void
  2817. fe_FreeUnicodeFonts(void)
  2818. {
  2819.     fe_FontCharSet *charset;
  2820.     fe_FontFace *face;
  2821.     int i_pitch, i_htmlsize, i_face, i_encodings;
  2822.     fe_FontPitch *pitch;
  2823.     fe_FontSize *size;
  2824.     fe_UnicodePseudoFont *ufont;
  2825.  
  2826.     charset = &fe_FontCharSets[CS_UTF8&0xFF];
  2827.     for (i_pitch = 0; i_pitch < 2; i_pitch++) {
  2828.         pitch = &charset->pitches[i_pitch];
  2829.         if (!pitch->selectedFamily)
  2830.            continue;
  2831.         for (i_htmlsize = 0; i_htmlsize < 7; i_htmlsize++) {
  2832.             size = pitch->selectedFamily->htmlSizes[i_htmlsize];
  2833.             if (!size)
  2834.                 continue;
  2835.             for (i_face = 0; i_face < 4; i_face++) {
  2836.                 face = size->faces[i_face];
  2837.                 if (!face)
  2838.                     continue;
  2839.                 if (!face->font)
  2840.                     continue;
  2841.                 ufont = (fe_UnicodePseudoFont *)face->font;
  2842.                 if (ufont->tag != UNICODE_PSEUDO_FONT_TAG) {
  2843.                     continue;
  2844.                 }
  2845.                 for (i_encodings=0; i_encodings<INTL_CHAR_SET_MAX; 
  2846.                                                         i_encodings++) {
  2847.                     if (ufont->xfont_scaled[i_encodings]) {
  2848.                         XFreeFont(ufont->dpy, ufont->xFonts[i_encodings]);
  2849.                         XP_FREE(ufont->xfont_name[i_encodings]);
  2850.                     }
  2851.                     ufont->xfont_inited[i_encodings] = FALSE;
  2852.                     ufont->xfont_scaled[i_encodings] = FALSE;
  2853.                     ufont->xfont_name[i_encodings] = NULL;
  2854.                     ufont->larger_fonts_avail[i_encodings] = FALSE;
  2855.                     if (ufont->xmfontlist) 
  2856.                         XmFontListFree(ufont->xmfontlist);
  2857.                     ufont->xmfontlist = NULL;
  2858.                     if (ufont->xm_fontset) 
  2859.                         XmFontListFree(ufont->xm_fontset);
  2860.                     ufont->xm_fontset = NULL;
  2861.                     if (ufont->xfontset) 
  2862.                         XFreeFontSet(ufont->dpy, ufont->xfontset);
  2863.                     ufont->xfontset = NULL;
  2864.                 }
  2865.             }
  2866.         }
  2867.     }
  2868. }
  2869.  
  2870. void
  2871. fe_FreeFontSizeTable(fe_FontFamily *family)
  2872. {
  2873.     int        k,m;
  2874.     fe_FontSize    *size;
  2875.     fe_FontFace    *face;
  2876.  
  2877.     if (!family->htmlSizesComputed) return;
  2878.  
  2879.     family->htmlSizesComputed = 0;
  2880.  
  2881.     /*
  2882.      * Only the scaled fonts were allocated new sizes. Hence we free
  2883.      * only them.
  2884.      */
  2885.     if (!family->allowScaling) return;
  2886.  
  2887.     for (k = 0; k < 7; k++)
  2888.     {
  2889.         size = family->htmlSizes[k];
  2890.         if (size)
  2891.         {
  2892.             for (m = 0; m < 4; m++)
  2893.             {
  2894.                 face = size->faces[m];
  2895.                 if (face)
  2896.                 {
  2897.                     free(face);
  2898.                 }
  2899.             }
  2900.             free(size);
  2901.             family->htmlSizes[k] = NULL;
  2902.         }
  2903.     }
  2904. }
  2905.  
  2906. void
  2907. fe_ComputeFontSizeTable(fe_FontFamily *family)
  2908. {
  2909.     int        i;
  2910.     double        idealSize;
  2911.     int        j;
  2912.     fe_FontSize    *size;
  2913.     int        size3;
  2914.  
  2915.     size = NULL;
  2916.  
  2917.     /*
  2918.      * first, find the size selected within the family
  2919.      */
  2920.     for (j = 0; j < family->numberOfPointSizes; j++)
  2921.     {
  2922.         size = &family->pointSizes[j];
  2923.         if (size->selected)
  2924.         {
  2925.             break;
  2926.         }
  2927.         else
  2928.         {
  2929.             size = NULL;
  2930.         }
  2931.     }
  2932.  
  2933.     if ((!family) || (!size))
  2934.     {
  2935.         /* this should not happen */
  2936.         return;
  2937.     }
  2938.  
  2939.     fe_FreeFontGroups();
  2940.     fe_FreeFontSizeTable(family);
  2941.  
  2942.     /*
  2943.      * set the default size (3)
  2944.      */
  2945.     size3 = size->size;
  2946.     if (!size3)
  2947.     {
  2948.         size3 = family->scaledSize;
  2949.     }
  2950.     if (!size3)
  2951.     {
  2952.         size3 = 120;
  2953.     }
  2954.  
  2955.     i = 3;
  2956.     idealSize = size3;
  2957.     family->htmlSizes[i - 1] = fe_ComputeFontSize(family, idealSize);
  2958.  
  2959.     /*
  2960.      * set the higher sizes (4-7)
  2961.      */
  2962.     for (i = 4; i <= 7; i++)
  2963.     {
  2964.         idealSize = ((1 + ((i - 3) * fe_FontSizeIncrement)) * size3);
  2965.         family->htmlSizes[i - 1] = fe_ComputeFontSize(family, idealSize);
  2966.     }
  2967.  
  2968.     /*
  2969.      * set the lower sizes (1-2)
  2970.      */
  2971.     for (i = 1; i <= 2; i++)
  2972.     {
  2973.         idealSize = ((1 - ((3 - i) * fe_FontSizeIncrement)) * size3);
  2974.         if (idealSize < 10)
  2975.         {
  2976.             idealSize = 10;
  2977.         }
  2978.         family->htmlSizes[i - 1] = fe_ComputeFontSize(family, idealSize);
  2979.     }
  2980.  
  2981.     /*
  2982.      * mark family that htmlSizes has been computed.
  2983.      */
  2984.     family->htmlSizesComputed = 1;
  2985.  
  2986.     /* @@@ need to implement this in case any of the scaled
  2987.      * sizes couldn't be malloc'ed -- erik
  2988.      * fe_CheckFonts();
  2989.      */
  2990. }
  2991.  
  2992.  
  2993. static int
  2994. fe_CloneFamily(fe_FontFamily *cloneFamily, fe_FontFamily *origFamily)
  2995. {
  2996.     int    i;
  2997.  
  2998.     cloneFamily->name = strdup(origFamily->name);
  2999.     cloneFamily->foundry = strdup(origFamily->foundry);
  3000.     cloneFamily->family = strdup(origFamily->family);
  3001.     if ((!cloneFamily->name) || (!cloneFamily->foundry) ||
  3002.         (!cloneFamily->family))
  3003.     {
  3004.         return 0;
  3005.     }
  3006.  
  3007.     cloneFamily->selected = origFamily->selected;
  3008.     cloneFamily->allowScaling = origFamily->allowScaling;
  3009.  
  3010.     cloneFamily->pointAlloc = origFamily->pointAlloc;
  3011.     cloneFamily->numberOfPointSizes = origFamily->numberOfPointSizes;
  3012.  
  3013.     cloneFamily->pointSizes = XP_CALLOC(cloneFamily->pointAlloc,
  3014.         sizeof(fe_FontSize));
  3015.     if (!cloneFamily->pointSizes)
  3016.     {
  3017.         return 0;
  3018.     }
  3019.  
  3020.     for (i = 0; i < cloneFamily->numberOfPointSizes; i++)
  3021.     {
  3022.         cloneFamily->pointSizes[i] = origFamily->pointSizes[i];
  3023.     }
  3024.  
  3025.     if (origFamily->allowScaling)
  3026.     {
  3027.         /*
  3028.          * For scaled families, take care to copy the sizes and faces.
  3029.          * Setting this will make the sizes get recomputed.
  3030.          */
  3031.         cloneFamily->htmlSizesComputed = 0;
  3032.     }
  3033.     else 
  3034.     {
  3035.         cloneFamily->htmlSizesComputed = origFamily->htmlSizesComputed;
  3036.         for (i = 0; i < 7; i++)
  3037.         {
  3038.             cloneFamily->htmlSizes[i] = origFamily->htmlSizes[i];
  3039.         }
  3040.     }
  3041.     return 1;
  3042. }
  3043.  
  3044.  
  3045. static int
  3046. fe_ClonePitch(fe_FontPitch *clonePitch, fe_FontPitch *origPitch)
  3047. {
  3048.     int    i;
  3049.  
  3050.     clonePitch->alloc = origPitch->alloc;
  3051.     clonePitch->numberOfFamilies = origPitch->numberOfFamilies;
  3052.  
  3053.     clonePitch->families = XP_CALLOC(clonePitch->alloc,
  3054.         sizeof(fe_FontFamily));
  3055.     if (!clonePitch->families)
  3056.     {
  3057.         return 0;
  3058.     }
  3059.  
  3060.     for (i = 0; i < clonePitch->numberOfFamilies; i++)
  3061.     {
  3062.         if (!fe_CloneFamily(&clonePitch->families[i],
  3063.             &origPitch->families[i]))
  3064.         {
  3065.             return 0;
  3066.         }
  3067.     }
  3068.  
  3069.     clonePitch->selectedFamily = NULL;
  3070.  
  3071.     return 1;
  3072. }
  3073.  
  3074.  
  3075. static void
  3076. fe_SetDefaultFontSettings(Display *dpy)
  3077. {
  3078.     fe_FontCharSet    *charset;
  3079.     char        *charsetname;
  3080.     char        clas[512];
  3081.     XrmDatabase    db;
  3082.     fe_FontFace    **faces;
  3083.     fe_FontFamily    *family;
  3084.     int        i;
  3085.     int        j;
  3086.     int        k;
  3087.     int        m;
  3088.     char        name[512];
  3089.     fe_FontPitch    *pitch;
  3090.     fe_FontSize    *size;
  3091.     char        *spec;
  3092.     char        *type;
  3093.     XrmValue    value;
  3094.  
  3095.  
  3096.     db = XtDatabase(dpy);
  3097.  
  3098.  
  3099.     /*
  3100.      * try to get the default charset from the resources
  3101.      */
  3102.     (void) PR_snprintf(clas, sizeof(clas),
  3103.         "%s.DocumentFonts.DefaultCharSet", fe_progclass);
  3104.     (void) PR_snprintf(name, sizeof(name),
  3105.         "%s.documentFonts.defaultCharSet", fe_progclass);
  3106.     if (XrmGetResource(db, name, clas, &type, &value))
  3107.     {
  3108.         charsetname = (char *) value.addr;
  3109.     }
  3110.     else
  3111.     {
  3112.         charsetname = "iso-8859-1";
  3113.     }
  3114.     fe_ReadFontCharSet(charsetname);
  3115.  
  3116.  
  3117.     /*
  3118.      * try to get the default fonts from the resources
  3119.      */
  3120.     for (i = 0; i < INTL_CHAR_SET_MAX; i++)
  3121.     {
  3122.         charset = &fe_FontCharSets[i];
  3123.         if (!charset->name)
  3124.         {
  3125.             continue;
  3126.         }
  3127.         for (j = 0; j < 2; j++)
  3128.         {
  3129.             (void) PR_snprintf(clas, sizeof(clas),
  3130.                 "%s.DocumentFonts.DefaultFont.CharSet.Pitch",
  3131.                 fe_progclass);
  3132.             (void) PR_snprintf(name, sizeof(name),
  3133.                 "%s.documentFonts.defaultFont.%s.%s",
  3134.                 fe_progclass, charset->mimeName,
  3135.                 fe_PropOrFixedFont(j));
  3136.             if (XrmGetResource(db, name, clas, &type, &value))
  3137.             {
  3138.                 spec = PR_smprintf("%s-%s-%s",
  3139.                     (char *) value.addr,
  3140.                     fe_PropOrFixedFont(j),
  3141.                     charset->mimeName);
  3142.                 if (!spec)
  3143.                 {
  3144.                     continue;
  3145.                 }
  3146.                 fe_ReadFontSpec(spec);
  3147.                 free(spec);
  3148.             }
  3149.         }
  3150.     }
  3151.  
  3152.  
  3153.     /*
  3154.      * make sure we have families set for each charset/pitch,
  3155.      * and sizes set for each family
  3156.      */
  3157.     for (i = 0; i < INTL_CHAR_SET_MAX; i++)
  3158.     {
  3159.         charset = &fe_FontCharSets[i];
  3160.         if (!charset->name)
  3161.         {
  3162.             continue;
  3163.         }
  3164.         for (j = 0; j < 2; j++)
  3165.         {
  3166.             pitch = &charset->pitches[j];
  3167.             for (k = 0; k < pitch->numberOfFamilies; k++)
  3168.             {
  3169.                 family = &pitch->families[k];
  3170.                 for (m = 0; m < family->numberOfPointSizes; m++)
  3171.                 {
  3172.                     faces = family->pointSizes[m].faces;
  3173.                     if (!faces[0])
  3174.                     {
  3175.                         if (faces[1])
  3176.                         {
  3177.                             faces[0] = faces[1];
  3178.                         }
  3179.                         else if (faces[2])
  3180.                         {
  3181.                             faces[0] = faces[2];
  3182.                         }
  3183.                         else
  3184.                         {
  3185.                             faces[0] = faces[3];
  3186.                         }
  3187.                     }
  3188.                     if (!faces[1])
  3189.                     {
  3190.                         if (faces[3])
  3191.                         {
  3192.                             faces[1] = faces[3];
  3193.                         }
  3194.                         else if (faces[2])
  3195.                         {
  3196.                             faces[1] = faces[2];
  3197.                         }
  3198.                         else
  3199.                         {
  3200.                             faces[1] = faces[0];
  3201.                         }
  3202.                     }
  3203.                     if (!faces[2])
  3204.                     {
  3205.                         if (faces[3])
  3206.                         {
  3207.                             faces[2] = faces[3];
  3208.                         }
  3209.                         else if (faces[1])
  3210.                         {
  3211.                             faces[2] = faces[1];
  3212.                         }
  3213.                         else
  3214.                         {
  3215.                             faces[2] = faces[0];
  3216.                         }
  3217.                     }
  3218.                     if (!faces[3])
  3219.                     {
  3220.                         if (faces[1])
  3221.                         {
  3222.                             faces[3] = faces[1];
  3223.                         }
  3224.                         else if (faces[2])
  3225.                         {
  3226.                             faces[3] = faces[2];
  3227.                         }
  3228.                         else
  3229.                         {
  3230.                             faces[3] = faces[0];
  3231.                         }
  3232.                     }
  3233.                 }
  3234.  
  3235.                 /*
  3236.                  * make sure a size is selected for each family
  3237.                  */
  3238.                 size = NULL;
  3239.                 for (m = 0; m < family->numberOfPointSizes; m++)
  3240.                 {
  3241.                     size = &family->pointSizes[m];
  3242.                     if (size->selected)
  3243.                     {
  3244.                         break;
  3245.                     }
  3246.                     else
  3247.                     {
  3248.                         size = NULL;
  3249.                     }
  3250.                 }
  3251.                 if ((!size) && family->numberOfPointSizes)
  3252.                 {
  3253.                     size = &family->pointSizes
  3254.                         [(family->numberOfPointSizes+1)/2-1];
  3255.                     size->selected = 1;
  3256.                 }
  3257.  
  3258.                 /*
  3259.                  * determine whether or not we allow scaling
  3260.                  * from the available sizes
  3261.                  */
  3262.                 if ((family->numberOfPointSizes == 1) &&
  3263.                     (family->pointSizes->size == 0))
  3264.                 {
  3265.                     family->allowScaling = 1;
  3266.                 }
  3267.             }
  3268.  
  3269.             /*
  3270.              * make sure a family is selected for each pitch
  3271.              */
  3272.             family = NULL;
  3273.             for (k = 0; k < pitch->numberOfFamilies; k++)
  3274.             {
  3275.                 family = &pitch->families[k];
  3276.                 if (family->selected)
  3277.                 {
  3278.                     break;
  3279.                 }
  3280.                 else
  3281.                 {
  3282.                     family = NULL;
  3283.                 }
  3284.             }
  3285.             if ((!family) && pitch->numberOfFamilies)
  3286.             {
  3287.                 family = &pitch->families[0];
  3288.                 family->selected = 1;
  3289.             }
  3290.             /* Force recomputation */
  3291.             if (family) fe_FreeFontSizeTable(family);
  3292.         }
  3293.  
  3294.         /*
  3295.          * if some charset has fonts in one pitch, but not the
  3296.          * other, we clone the one that is available, so that
  3297.          * we always have a pitch available
  3298.          */
  3299.         if (!charset->pitches[0].families)
  3300.         {
  3301.             if (!fe_ClonePitch(&charset->pitches[0],
  3302.                 &charset->pitches[1]))
  3303.             {
  3304.                 /*
  3305.                  * if we can't clone the pitch, we
  3306.                  * disable the whole charset
  3307.                  */
  3308.                 free(charset->name);
  3309.                 charset->name = NULL;
  3310.             }
  3311.         }
  3312.         else if (!charset->pitches[1].families)
  3313.         {
  3314.             if (!fe_ClonePitch(&charset->pitches[1],
  3315.                 &charset->pitches[0]))
  3316.             {
  3317.                 /*
  3318.                  * if we can't clone the pitch, we
  3319.                  * disable the whole charset
  3320.                  */
  3321.                 free(charset->name);
  3322.                 charset->name = NULL;
  3323.             }
  3324.         }
  3325.     }
  3326. }
  3327.  
  3328.  
  3329. static void
  3330. fe_ReportFontCharSets(void)
  3331. {
  3332.     fe_FontCharSet    *charset;
  3333.     int16        *charsets;
  3334.     int        i;
  3335.     int        j;
  3336.  
  3337.     charsets = calloc(INTL_CHAR_SET_MAX, sizeof(*charsets));
  3338.     if (!charsets)
  3339.     {
  3340.         return;
  3341.     }
  3342.  
  3343.     j = 0;
  3344.     for (i = 1; i < INTL_CHAR_SET_MAX; i++)
  3345.     {
  3346.         charset = &fe_FontCharSets[i];
  3347.         if (!charset->name)
  3348.         {
  3349.             continue;
  3350.         }
  3351.         charsets[j++] = fe_CharSetInfoArray[i].charsetID;
  3352.     }
  3353.  
  3354.     INTL_ReportFontCharSets(charsets);
  3355. }
  3356.  
  3357.  
  3358. static fe_Font
  3359. fe_LoadXFont(Display *dpy, char *name)
  3360. {
  3361.     XFontStruct    *f;
  3362.  
  3363.     f = XLoadQueryFont(dpy, name);
  3364.  
  3365.     if (f)
  3366.     {
  3367.         /*
  3368.          * The width check is from xemacs.
  3369.          * The ascent check is from Sun's AWT.
  3370.          */
  3371.         if ((!f->max_bounds.width) || (f->ascent < 0))
  3372.         {
  3373.             XFreeFont(dpy, f);
  3374.             f = NULL;
  3375.         }
  3376.     }
  3377.  
  3378.     return (fe_Font) f;
  3379. }
  3380.  
  3381. static float default_UnicodePseudoFontSizes[] = {
  3382.     0.0, 
  3383.     8.0,   9.0, 10.0, 11.0, 12.0, 14.0, 
  3384.     16.0, 18.0, 20.0, 22.0, 24.0, 28.0, 
  3385.     32.0, 36.0,
  3386.     48.0, 60.0, 72.0,
  3387. };
  3388.  
  3389. static float* UnicodePseudoFontSizes = default_UnicodePseudoFontSizes;
  3390. static int num_UnicodePseudoFontSizes = 
  3391.             sizeof(default_UnicodePseudoFontSizes)/sizeof(float*);
  3392.  
  3393. static char *
  3394. fe_generatePixelSizeFontSpec(
  3395.         int  pixelSizeNum,
  3396.         char *origFoundry,
  3397.         char *origFamily,
  3398.         char *origWeight,
  3399.         char *avgwidth,
  3400.         char *origCharset)
  3401. {
  3402.     char *pixelSizeFontSpec;
  3403.  
  3404.     /*
  3405.      * Note:
  3406.      * origWeight has 2 values
  3407.      * origCharset has 2 values
  3408.      */
  3409. #ifdef SOLARIS
  3410.         if (pixelSizeNum)
  3411.         {
  3412.             pixelSizeFontSpec = PR_smprintf(
  3413.                 "-%s-%s-%s-*-*-%d-*-*-*-*-%s-%s", origFoundry,
  3414.                 origFamily, origWeight, pixelSizeNum, avgwidth,
  3415.                 origCharset);
  3416.         }
  3417.         else
  3418.         {
  3419.             pixelSizeFontSpec = PR_smprintf(
  3420.                 "-%s-%s-%s-*-*-%%d-*-*-*-*-%s-%s", origFoundry,
  3421.                 origFamily, origWeight, avgwidth, origCharset);
  3422.         }
  3423. #else /* SOLARIS */
  3424.         if (pixelSizeNum)
  3425.         {
  3426.             pixelSizeFontSpec = PR_smprintf(
  3427.                 "-%s-%s-%s-*-*-%d-*-*-*-*-*-%s", origFoundry,
  3428.                 origFamily, origWeight, pixelSizeNum,
  3429.                 origCharset);
  3430.         }
  3431.         else
  3432.         {
  3433.             pixelSizeFontSpec = PR_smprintf(
  3434.                 "-%s-%s-%s-*-*-%%d-*-*-*-*-*-%s", origFoundry,
  3435.                 origFamily, origWeight, origCharset);
  3436.         }
  3437. #endif /* SOLARIS */
  3438.     return pixelSizeFontSpec;
  3439.  
  3440. }
  3441.  
  3442. static char *
  3443. fe_generatePointSizeFontSpec(
  3444.         int  pointSizeNum,
  3445.         char *origFoundry,
  3446.         char *origFamily,
  3447.         char *origWeight,
  3448.         char *xResolution,
  3449.         char *yResolution,
  3450.         char *avgwidth,
  3451.         char *origCharset)
  3452. {
  3453.     char *pointSizeFontSpec;
  3454.  
  3455.     /*
  3456.      * Note:
  3457.      * origWeight has 2 values
  3458.      * origCharset has 2 values
  3459.      */
  3460. #ifdef SOLARIS
  3461.         if (pointSizeNum)
  3462.         {
  3463.             pointSizeFontSpec = PR_smprintf(
  3464.                 "-%s-%s-%s-*-*-*-%d-%s-%s-*-%s-%s",
  3465.                 origFoundry, origFamily, origWeight,
  3466.                 pointSizeNum, xResolution, yResolution,
  3467.                 avgwidth, origCharset);
  3468.         }
  3469.         else
  3470.         {
  3471.             pointSizeFontSpec = PR_smprintf(
  3472.                 "-%s-%s-%s-*-*-*-%%d-%s-%s-*-%s-%s",
  3473.                 origFoundry, origFamily, origWeight,
  3474.                 xResolution, yResolution, avgwidth,
  3475.                 origCharset);
  3476.         }
  3477. #else /* SOLARIS */
  3478.         if (pointSizeNum)
  3479.         {
  3480.             pointSizeFontSpec = PR_smprintf(
  3481.                 "-%s-%s-%s-*-*-*-%d-%s-%s-*-*-%s", origFoundry,
  3482.                 origFamily, origWeight, pointSizeNum,
  3483.                 xResolution, yResolution, origCharset);
  3484.         }
  3485.         else
  3486.         {
  3487.             pointSizeFontSpec = PR_smprintf(
  3488.                 "-%s-%s-%s-*-*-*-%%d-%s-%s-*-*-%s",
  3489.                 origFoundry, origFamily, origWeight,
  3490.                 xResolution, yResolution, origCharset);
  3491.         }
  3492. #endif /* SOLARIS */
  3493.     return pointSizeFontSpec;
  3494.  
  3495. }
  3496.  
  3497. /*
  3498.  * fe_loadUnicodePseudoFonts
  3499.  *
  3500.  * At this time, Sept. 1996, Unicode fonts are not
  3501.  * available for Unix. To display (size) a Unicode string
  3502.  * we convert the Unicode string to a series substrings each
  3503.  * of which is converted in a locally displayable encoding.
  3504.  * We then display (size) each substring using a standard
  3505.  * X font from a this Unicode Pseudo font.
  3506.  *
  3507.  * A Unicode Pseudo font is therefore an array of X fonts
  3508.  * each of the given size/pitch/weight for this font with one
  3509.  * one X font per encoding.
  3510.  *
  3511.  * In loading these Unicode Pseudo fonts we pretend to
  3512.  * to have these Unicode fonts available and fill in the master 
  3513.  * font table. Actually checking for a X font for each
  3514.  * for each size/pitch/weight/encoding would require loading 
  3515.  * a huge number of fonts.
  3516.  *
  3517.  *    11 sizes * 2 pitches * 2 weights * 35 encodings = 1540 fonts
  3518.  *
  3519.  * Because of the large number of fonts and the fact that asian 
  3520.  * fonts are large (1M per font) and the fact we might ask for 
  3521.  * scaling this loading time could be in the order of 
  3522.  * several minutes.  During this font loading time the X server 
  3523.  * appears to freeze and this is quite distressing to the user.
  3524.  *
  3525.  * HENCE BECAUSE OF THE UNACCEPTABLE LOADING DELAYS 
  3526.  * WE JUST ASSUME THE UNICODE FONTS ARE AVAILABLE.
  3527.  *
  3528.  * Even when we begin using a Unicode Pseudo font we only
  3529.  * load the X fonts for the encodings that have actually been 
  3530.  * seen.  Just loading X fonts for all the encodings for a given
  3531.  * size/pitch/weight requires a large number of X fonts.
  3532.  * 
  3533.  *    11 sizes * 2 pitches * 2 weights = 44 X fonts
  3534.  *
  3535.  */
  3536. static void
  3537. fe_loadUnicodePseudoFonts(Display *dpy, char *my_origFamily, int my_pitch)
  3538. {
  3539.     int i, j;
  3540.     char *my_origFoundry = "nsPseudoFont";
  3541.     char *my_foundry = my_origFoundry;
  3542.     char *my_family = my_origFamily;
  3543.     int   my_face;
  3544.     int   my_pointSizeNum;
  3545.     int   my_pixelSizeNum;
  3546.     int16 my_charsetID = CS_UTF8 & 0xFF;
  3547.     char *my_origCharset = "unicode-2-0";
  3548.     char *my_charset = my_origCharset;
  3549.     char *my_charsetlang = "unicode-2-0";
  3550.     char *my_pixelSizeFontSpec = NULL; 
  3551.     char *my_pointSizeFontSpec = NULL;
  3552.     char *my_origWeight;
  3553.     char *my_avgwidth = "*";
  3554.     char *my_xResolution = "*";
  3555.     char *my_yResolution = "*";
  3556.     char name[512], clas[512];
  3557.     char *type;
  3558.     XrmValue value;
  3559.     XrmDatabase    db = XtDatabase(dpy);
  3560.  
  3561.     /* Family name */
  3562.     (void) PR_snprintf(name, sizeof(name),
  3563.              "%s.documentFonts.family.%s", fe_progclass, my_origFamily);
  3564.     (void) PR_snprintf(clas, sizeof(clas),
  3565.                 "%s.DocumentFonts.Family.Name", fe_progclass);
  3566.     if (XrmGetResource(db, name, clas, &type, &value))
  3567.         my_family = (char *) value.addr;
  3568.  
  3569.     /* Foundry name */
  3570.     (void) PR_snprintf(name, sizeof(name),
  3571.              "%s.documentFonts.foundry.%s", fe_progclass, my_origFoundry);
  3572.     (void) PR_snprintf(clas, sizeof(clas),
  3573.                 "%s.DocumentFonts.Foundry.Name", fe_progclass);
  3574.     if (XrmGetResource(db, name, clas, &type, &value))
  3575.         my_foundry = (char *) value.addr;
  3576.  
  3577.     /* CharsetLang name */
  3578.     (void) PR_snprintf(name, sizeof(name),
  3579.              "%s.documentFonts.charsetlang.%s", fe_progclass, my_charsetlang);
  3580.     (void) PR_snprintf(clas, sizeof(clas),
  3581.                 "%s.DocumentFonts.CharSetLang.Name", fe_progclass);
  3582.     if (XrmGetResource(db, name, clas, &type, &value))
  3583.         my_charsetlang = (char *) value.addr;
  3584.  
  3585.     /*
  3586.      * Create the Pseudo font sizes
  3587.      */
  3588.  
  3589.     for (i=0; i<num_UnicodePseudoFontSizes; i++) {
  3590.         /* one of these is not quite right */
  3591.         my_pixelSizeNum = (int)(UnicodePseudoFontSizes[i] * 10);
  3592.         my_pointSizeNum = (int)(UnicodePseudoFontSizes[i] * 10);
  3593.         /*
  3594.          * for each size create a plain/bold/italic/boldItalic version
  3595.          * (0=plain, 1=bold, 2=italic, 3=boldItalic)
  3596.          */
  3597.         for (j=0; j<4; j++) {
  3598.             my_face = j;
  3599.             switch(j) {
  3600.                 default:
  3601.                 case 0:
  3602.                     my_origWeight = "medium-r";
  3603.                     break;
  3604.                 case 1:
  3605.                     my_origWeight = "bold-r";
  3606.                     break;
  3607.                 case 2:
  3608.                     my_origWeight = "medium-i";
  3609.                     break;
  3610.                 case 3:
  3611.                     my_origWeight = "bold-i";
  3612.                     break;
  3613.             };
  3614.  
  3615.             /*
  3616.              * Proportional/Monospaced
  3617.              */
  3618.             my_pixelSizeFontSpec = fe_generatePixelSizeFontSpec(
  3619.                                             my_pixelSizeNum,
  3620.                                             my_origFoundry,
  3621.                                             my_origFamily,
  3622.                                             my_origWeight,
  3623.                                             my_avgwidth,
  3624.                                             my_origCharset);
  3625.             if (!my_pixelSizeFontSpec)
  3626.                 continue;
  3627.             my_pointSizeFontSpec = fe_generatePointSizeFontSpec(
  3628.                                         my_pointSizeNum,
  3629.                                         my_origFoundry,
  3630.                                         my_origFamily,
  3631.                                         my_origWeight,
  3632.                                         my_xResolution,
  3633.                                         my_yResolution,
  3634.                                         my_avgwidth,
  3635.                                         my_origCharset);
  3636.             if (!my_pointSizeFontSpec)
  3637.                 continue;
  3638.  
  3639.             fe_AddFontCharSet(
  3640.                     my_origFoundry, 
  3641.                     my_foundry,
  3642.                     my_origFamily,
  3643.                     my_family,
  3644.                     my_face,
  3645.                     my_pixelSizeNum,
  3646.                     my_pointSizeNum,
  3647.                     my_pitch,
  3648.                     my_charsetID,
  3649.                     my_charset,
  3650.                     my_charsetlang,
  3651.                     my_pixelSizeFontSpec,
  3652.                     my_pointSizeFontSpec,
  3653.                     my_origCharset);
  3654.             FE_MAYBE_FREE(my_pixelSizeFontSpec);
  3655.             FE_MAYBE_FREE(my_pointSizeFontSpec);
  3656.         }
  3657.     }
  3658. }
  3659.  
  3660. #ifndef NO_WEB_FONTS
  3661.  
  3662. #define WF_FONT_DISPLAYER_PATH_1 "~/.netscape/dynfonts"
  3663. #define WF_FONT_DISPLAYER_PATH_4 "/usr/local/lib/netscape/dynfonts"
  3664.  
  3665. /* This static is outside of fe_InitializeWebfonts() 'cause HPUX has a
  3666.  * bug that causes it to become a loaded error with
  3667.  *    ld: Invalid loader fixup for symbol
  3668.  */
  3669. static char *dynfonts_str = "/dynfonts";
  3670. static char *dynfonts_str_no_slash = "dynfonts";
  3671.  
  3672. static void
  3673. fe_InitializeWebfonts(void)
  3674. {
  3675.     struct nffbp *fbp;
  3676.     char buf[MAXPATHLEN];
  3677.     char *mozilla_home = NULL;
  3678.     char *home = NULL;
  3679.  
  3680.     /* Initialize and obtain the font broker and font utility provider. */
  3681.     fe_FontBroker = NF_FontBrokerInitialize();
  3682.     fe_FontUtility = (struct nffbu *)
  3683.         nffbc_getInterface(fe_FontBroker, &nffbu_ID, NULL);
  3684.  
  3685.     /* Load Catalog */
  3686.     if (home = getenv("HOME"))
  3687.     {
  3688.         /* Form "$HOME/.netscape/dynfonts/fonts.cat" into buf */
  3689.         strncpy(buf, home, sizeof(buf)-1);
  3690.         strncat(buf, "/.netscape/dynfonts/fonts.cat",
  3691.                 sizeof(buf)-1 - strlen(buf));
  3692.         buf[sizeof(buf)-1] = '\0';
  3693.         nffbu_LoadCatalog(fe_FontUtility, buf, NULL);
  3694.     }
  3695.  
  3696.     /* Load all font displayers */
  3697.     fbp = (struct nffbp *)
  3698.         nffbc_getInterface(fe_FontBroker, &nffbp_ID, NULL);
  3699.  
  3700.     /* Scan for font displayers. Here is the order and list of places
  3701.      * where we look for font displayers.
  3702.      *    ~/.netscape/dynfonts
  3703.      *    $MOZILLA_HOME/dynfonts
  3704.      *    <program directory>/dynfonts
  3705.      *    /usr/local/lib/netscape/dynfonts
  3706.      *
  3707.      * According to our webfont implementation, if a font displayer with
  3708.      * the same name exists in more than one directory, then the
  3709.      * first one takes priority.
  3710.      */
  3711.     nffbp_ScanForFontDisplayers(fbp, WF_FONT_DISPLAYER_PATH_1, NULL);
  3712.  
  3713.     /* WF_FONT_DISPLAYER_PATH_2 */
  3714.     if (mozilla_home = getenv("MOZILLA_HOME"))
  3715.     {
  3716.         /* Form "$MOZILLA_HOME/dynfonts" into buf */
  3717.         strncpy(buf, mozilla_home, sizeof(buf)-1);
  3718.         strncat(buf, dynfonts_str, sizeof(buf)-1 - strlen(buf));
  3719.         buf[sizeof(buf)-1] = '\0';
  3720.         nffbp_ScanForFontDisplayers(fbp, buf, NULL);
  3721.     }
  3722.  
  3723.     /* WF_FONT_DISPLAYER_PATH_3 */
  3724.     /* Form "<program-dir>/dynfonts" into buf */
  3725.     buf[0] = '\0';
  3726.     fe_GetProgramDirectory(buf, sizeof(buf)-1);
  3727.     if (buf[0])
  3728.     {
  3729.         strncat(buf, dynfonts_str_no_slash, sizeof(buf)-1 - strlen(buf));
  3730.         buf[sizeof(buf)-1] = '\0';
  3731.         nffbp_ScanForFontDisplayers(fbp, buf, NULL);
  3732.     }
  3733.  
  3734.     /* WF_FONT_DISPLAYER_PATH_4 */
  3735.     nffbp_ScanForFontDisplayers(fbp, WF_FONT_DISPLAYER_PATH_4, NULL);
  3736. }
  3737. #endif
  3738.  
  3739. void
  3740. fe_InitFonts(Display *dpy)
  3741. {
  3742.     char        *avgwidth = NULL;
  3743. #ifdef SOLARIS
  3744.     int        avgWidthNum;
  3745. #endif
  3746.     char        *charset;
  3747.     int16        charsetID;
  3748.     char        *charsetlang;
  3749.     char        clas[512];
  3750.     int        count;
  3751.     XrmDatabase    db;
  3752.     int        face;
  3753.     char        *family;
  3754.     char        *font;
  3755.     char        **fonts;
  3756.     char        *foundry;
  3757.     int        i;
  3758.     int        j;
  3759.     char        name[512];
  3760.     char        *origCharset;
  3761.     char        *origFamily;
  3762.     char        *origFoundry;
  3763.     char        *origWeight; /* note: has weight and slant */
  3764.     char        *p;
  3765.     int        pitch;
  3766.     char        *pixelSize;
  3767.     char        *pixelSizeFontSpec;
  3768.     int        pixelSizeNum;
  3769.     char        *pointSize;
  3770.     char        *pointSizeFontSpec;
  3771.     int        pointSizeNum;
  3772.     char        *resx;
  3773.     char        *setwidth;
  3774.     char        *spacing;
  3775.     char        *type;
  3776.     XrmValue    value;
  3777.     char        *weight;
  3778.     char        *xResolution;
  3779.     char        *yResolution;
  3780.  
  3781. #ifdef SOLARIS
  3782.     avgwidth = NULL;
  3783. #endif
  3784.     charset = NULL;
  3785.     charsetlang = NULL;
  3786.     family = NULL;
  3787.     font = NULL;
  3788.     fonts = NULL;
  3789.     foundry = NULL;
  3790.     origCharset = NULL;
  3791.     origFamily = NULL;
  3792.     origFoundry = NULL;
  3793.     origWeight = NULL;
  3794.     p = NULL;
  3795.     pixelSize = NULL;
  3796.     pixelSizeFontSpec = NULL;
  3797.     pointSize = NULL;
  3798.     pointSizeFontSpec = NULL;
  3799.     resx = NULL;
  3800.     setwidth = NULL;
  3801.     spacing = NULL;
  3802.     type = NULL;
  3803.     weight = NULL;
  3804.     xResolution = NULL;
  3805.     yResolution = NULL;
  3806.  
  3807. #ifndef NO_WEB_FONTS
  3808.     /* Initialize font library */
  3809.     fe_InitializeWebfonts();
  3810. #endif
  3811.     /*
  3812.      * do this first so that we are very likely to have this
  3813.      * font available if/when we fail to load any other font
  3814.      */
  3815.     fe_FixedFont = fe_LoadXFont(dpy, "fixed");
  3816.  
  3817.     fe_GetLocaleCharSets(dpy);
  3818.  
  3819. #ifdef DEBUG
  3820.     if (sizeof(fe_CharSetInfoArray) / sizeof(*fe_CharSetInfoArray) !=
  3821.         INTL_CHAR_SET_MAX)
  3822.     {
  3823.         (void) fprintf(real_stderr,
  3824.             "fe_CharSetInfoArray broken (size)\n");
  3825. #if 0 
  3826.         /* to fix 93446
  3827.          */
  3828.         fe_Exit(1);
  3829. #endif
  3830.     }
  3831.     for (i = 0; i < INTL_CHAR_SET_MAX; i++)
  3832.     {
  3833.         if ((fe_CharSetInfoArray[i].charsetID & 0xff) != i)
  3834.         {
  3835.             (void) fprintf(real_stderr,
  3836.                 "fe_CharSetInfoArray broken (%d)\n", i);
  3837. #if 0 
  3838.             /* to fix 93446
  3839.              */
  3840.             fe_Exit(1);
  3841. #endif
  3842.         }
  3843.     }
  3844. #endif /* DEBUG */
  3845.  
  3846.     fonts = XListFonts(dpy, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*", INT_MAX,
  3847.                            &count);
  3848.     if (!fonts)
  3849.     {
  3850.         return;
  3851.     }
  3852.  
  3853.     (void) memset(fe_FontCharSets, 0, sizeof(fe_FontCharSets));
  3854.  
  3855.         db = XtDatabase(dpy);
  3856.  
  3857.     for (i = 0; i < count; i++)
  3858.     {
  3859.         FE_MAYBE_FREE(font);
  3860.         FE_MAYBE_FREE(origCharset);
  3861.         FE_MAYBE_FREE(origFamily);
  3862.         FE_MAYBE_FREE(origWeight);
  3863.         FE_MAYBE_FREE(pixelSizeFontSpec);
  3864.         FE_MAYBE_FREE(pointSizeFontSpec);
  3865.  
  3866.         /* ignore the non-XLFD short names */
  3867.         if ((!fonts[i]) || (fonts[i][0] != '-'))
  3868.         {
  3869.             continue;
  3870.         }
  3871.  
  3872.         font = strdup(fonts[i]);
  3873.         if (!font)
  3874.         {
  3875.             continue;
  3876.         }
  3877.  
  3878.         p = font;
  3879.         j = 0;
  3880.         while (1)
  3881.         {
  3882.             p = strchr(p, '-');
  3883.             if (!p)
  3884.             {
  3885.                 break;
  3886.             }
  3887.             p++;
  3888.             switch (j)
  3889.             {
  3890.             case 0:
  3891.                 foundry = p;
  3892.                 break;
  3893.             case 1:
  3894.                 family = p;
  3895.                 break;
  3896.             case 2:
  3897.                 weight = p;
  3898.                 break;
  3899.             case 4:
  3900.                 setwidth = p;
  3901.                 break;
  3902.             case 6:
  3903.                 pixelSize = p;
  3904.                 break;
  3905.             case 7:
  3906.                 pointSize = p;
  3907.                 break;
  3908.             case 8:
  3909.                 resx = p;
  3910.                 break;
  3911.             case 10:
  3912.                 spacing = p;
  3913.                 break;
  3914. #ifdef SOLARIS
  3915.             case 11:
  3916.                 avgwidth = p;
  3917.                 break;
  3918. #endif
  3919.             case 12:
  3920.                 charset = p;
  3921.                 break;
  3922.             default:
  3923.                 break;
  3924.             }
  3925.             j++;
  3926.         }
  3927.  
  3928.         if (j < 14)
  3929.         {
  3930.             /* skip non-XLFD names */
  3931.             continue;
  3932.         }
  3933.  
  3934.                 /* Skip Applix fonts -- if these are installed, there are
  3935.                    hundreds of them, and they do not have proper XLFD names:
  3936.                    the bold/italic/etc versions of the fonts have different
  3937.                    *families* as well ("axhvr" for Helvetica-normal,
  3938.                    "axhvb" for Helvetica-bold, etc) so all they do is bloat
  3939.                    the menus and make the UI unusable.
  3940.                  */
  3941.                 if (family &&
  3942.                     strncasecomp(family, "ax", 2) &&
  3943.                     XP_STRLEN(family) == 5)
  3944.                     continue;
  3945.  
  3946.         (void) PR_snprintf(clas, sizeof(clas),
  3947.             "%s.DocumentFonts.Foundry.Name", fe_progclass);
  3948.         family[-1] = 0;
  3949.         (void) PR_snprintf(name, sizeof(name),
  3950.             "%s.documentFonts.foundry.%s", fe_progclass, foundry);
  3951.         origFoundry = strdup(foundry);
  3952.         if (!origFoundry)
  3953.         {
  3954.             continue;
  3955.         }
  3956.         if (XrmGetResource(db, name, clas, &type, &value))
  3957.         {
  3958.             foundry = strdup((char *) value.addr);
  3959.         }
  3960.         else
  3961.         {
  3962.             foundry = fe_CapitalizeFontName(foundry);
  3963.         }
  3964.         if (!foundry)
  3965.         {
  3966.             continue;
  3967.         }
  3968.  
  3969.         (void) PR_snprintf(clas, sizeof(clas),
  3970.             "%s.DocumentFonts.Family.Name", fe_progclass);
  3971.         weight[-1] = 0;
  3972.         (void) PR_snprintf(name, sizeof(name),
  3973.             "%s.documentFonts.family.%s", fe_progclass, family);
  3974.         origFamily = strdup(family);
  3975.         if (!origFamily)
  3976.         {
  3977.             continue;
  3978.         }
  3979.         if (XrmGetResource(db, name, clas, &type, &value))
  3980.         {
  3981.             family = strdup((char *) value.addr);
  3982.         }
  3983.         else
  3984.         {
  3985.             family = fe_CapitalizeFontName(family);
  3986.         }
  3987.         if (!family)
  3988.         {
  3989.             continue;
  3990.         }
  3991.  
  3992.         (void) PR_snprintf(clas, sizeof(clas),
  3993.             "%s.DocumentFonts.Face.Name", fe_progclass);
  3994.         setwidth[-1] = 0;
  3995.         (void) PR_snprintf(name, sizeof(name),
  3996.             "%s.documentFonts.face.%s", fe_progclass, weight);
  3997.         origWeight = strdup(weight);
  3998.         if (!origWeight)
  3999.         {
  4000.             continue;
  4001.         }
  4002.         if (XrmGetResource(db, name, clas, &type, &value))
  4003.         {
  4004.             weight = (char *) value.addr;
  4005.         }
  4006.         else
  4007.         {
  4008. #ifdef DEBUG_xxx
  4009.             (void) fprintf(real_stderr, "face %s\n", weight);
  4010. #endif /* DEBUG_xxx */
  4011.             weight = "";
  4012.         }
  4013.         if (!strcmp(weight, "bold"))
  4014.         {
  4015.             face = 1;
  4016.         }
  4017.         else if (!strcmp(weight, "boldItalic"))
  4018.         {
  4019.             face = 3;
  4020.         }
  4021.         else if (!strcmp(weight, "italic"))
  4022.         {
  4023.             face = 2;
  4024.         }
  4025.         else
  4026.         {
  4027.             face = 0;
  4028.         }
  4029.  
  4030.         pointSize[-1] = 0;
  4031.         sscanf(pixelSize, "%d", &pixelSizeNum);
  4032.         if (pixelSizeNum < 0)
  4033.         {
  4034.             continue;
  4035.         }
  4036.  
  4037.         resx[-1] = 0;
  4038.         sscanf(pointSize, "%d", &pointSizeNum);
  4039.         if (pointSizeNum < 0)
  4040.         {
  4041.             continue;
  4042.         }
  4043.  
  4044.         switch (spacing[0])
  4045.         {
  4046.         case 'm':
  4047.             pitch = fe_FONT_PITCH_MONO;
  4048.             break;
  4049.         case 'p':
  4050.             pitch = fe_FONT_PITCH_PROPORTIONAL;
  4051.             break;
  4052.         case 'c':
  4053.             /* fall through */
  4054.         default:
  4055.             pitch = fe_FONT_PITCH_BOTH;
  4056.             break;
  4057.         }
  4058.  
  4059. #ifdef SOLARIS
  4060.         charset[-1] = 0;
  4061.         sscanf(avgwidth, "%d", &avgWidthNum);
  4062.         if (avgWidthNum < 0)
  4063.         {
  4064.             continue;
  4065.         }
  4066. #endif
  4067.  
  4068.         (void) PR_snprintf(clas, sizeof(clas),
  4069.             "%s.DocumentFonts.CharSet.Family.Name", fe_progclass);
  4070.         (void) PR_snprintf(name, sizeof(name),
  4071.             "%s.documentFonts.charset.%s.%s", fe_progclass,
  4072.             origFamily, charset);
  4073.         origCharset = strdup(charset);
  4074.         if (!origCharset)
  4075.         {
  4076.             continue;
  4077.         }
  4078.         charsetlang = charset;
  4079.         if (XrmGetResource(db, name, clas, &type, &value))
  4080.         {
  4081.             charset = (char *) value.addr;
  4082.         }
  4083.         else
  4084.         {
  4085.             /*
  4086.              * if the user has messed with the app-defaults, we
  4087.              * might not be able to find our mapping, so check for
  4088.              * the following at least
  4089.              */
  4090.             if (!strcmp(charset, "iso8859-1"))
  4091.             {
  4092.                 charset = "iso-8859-1";
  4093.             }
  4094. #ifdef DEBUG
  4095.             else
  4096.             {
  4097.                 (void) fprintf(real_stderr, "charset %s %s\n",
  4098.                     origFamily, charsetlang);
  4099.             }
  4100. #endif /* DEBUG */
  4101.         }
  4102.         charsetID = (INTL_CharSetNameToID(charset) & 0xff);
  4103.  
  4104. #ifdef SOLARIS
  4105.         if (charsetID == (CS_GB2312 & 0xff))
  4106.         {
  4107.             /*
  4108.              * Simplified Chinese Solaris has broken fonts that
  4109.              * say GB2312 but are actually ASCII fonts. Skip 'em.
  4110.              */
  4111.             if (avgWidthNum && (avgWidthNum == (pointSizeNum / 2)))
  4112.             {
  4113.                 continue;
  4114.             }
  4115.         }
  4116.         else
  4117.         {
  4118.             avgwidth = "*";
  4119.         }
  4120. #endif /* SOLARIS */
  4121.  
  4122. #ifdef DEBUG
  4123.         if ((charsetID == CS_UNKNOWN) && strcmp(charset, "x-ignore"))
  4124.         {
  4125.             (void) fprintf(real_stderr, "internal %s %s %s\n",
  4126.                 origFamily, charsetlang, charset);
  4127.         }
  4128. #endif /* DEBUG */
  4129.         if (!strcmp(charset, "x-ignore"))
  4130.         {
  4131.             charsetID = CS_USRDEF2;
  4132.         }
  4133.         if (charsetID >= INTL_CHAR_SET_MAX)
  4134.         {
  4135.             charsetID = CS_USRDEF2;
  4136.         }
  4137.         if (fe_CharSetInfoArray[charsetID].type == FE_FONT_TYPE_GROUP)
  4138.         {
  4139.             continue;
  4140.         }
  4141.         (void) PR_snprintf(clas, sizeof(clas),
  4142.             "%s.DocumentFonts.CharSetLang.Name", fe_progclass);
  4143.         (void) PR_snprintf(name, sizeof(name),
  4144.             "%s.documentFonts.charsetlang.%s", fe_progclass,
  4145.             charset);
  4146.         if (XrmGetResource(db, name, clas, &type, &value))
  4147.         {
  4148.             charsetlang = (char *) value.addr;
  4149.         }
  4150.         else
  4151.         {
  4152. #if 0
  4153.             (void) fprintf(real_stderr, "charsetlang %s\n",
  4154.                 charsetlang);
  4155. #endif /* 0 */
  4156.             charsetlang = XP_GetString(XFE_OTHER_LANGUAGE);
  4157.         }
  4158.  
  4159.         (void) PR_snprintf(clas, sizeof(clas),
  4160.             "%s.DocumentFonts.XResolution.CharSet", fe_progclass);
  4161.         (void) PR_snprintf(name, sizeof(name),
  4162.             "%s.documentFonts.xResolution.%s", fe_progclass,
  4163.             charset);
  4164.         if (XrmGetResource(db, name, clas, &type, &value))
  4165.         {
  4166.             xResolution = (char *) value.addr;
  4167.         }
  4168.         else
  4169.         {
  4170.             xResolution = "*";
  4171.         }
  4172.  
  4173.         (void) PR_snprintf(clas, sizeof(clas),
  4174.             "%s.DocumentFonts.YResolution.CharSet", fe_progclass);
  4175.         (void) PR_snprintf(name, sizeof(name),
  4176.             "%s.documentFonts.yResolution.%s", fe_progclass,
  4177.             charset);
  4178.         if (XrmGetResource(db, name, clas, &type, &value))
  4179.         {
  4180.             yResolution = (char *) value.addr;
  4181.         }
  4182.         else
  4183.         {
  4184.             yResolution = "*";
  4185.         }
  4186.  
  4187.         pixelSizeFontSpec = fe_generatePixelSizeFontSpec(
  4188.                                 pixelSizeNum,
  4189.                                 origFoundry,
  4190.                                 origFamily,
  4191.                                 origWeight,
  4192.                                 avgwidth,
  4193.                                 origCharset);
  4194.         if (!pixelSizeFontSpec)
  4195.         {
  4196.             continue;
  4197.         }
  4198.  
  4199.         pointSizeFontSpec = fe_generatePointSizeFontSpec(
  4200.                                 pointSizeNum,
  4201.                                 origFoundry,
  4202.                                 origFamily,
  4203.                                 origWeight,
  4204.                                 xResolution,
  4205.                                 yResolution,
  4206.                                 avgwidth,
  4207.                                 origCharset);
  4208.         if (!pointSizeFontSpec)
  4209.         {
  4210.             continue;
  4211.         }
  4212.  
  4213.         fe_AddFontCharSet(origFoundry, foundry, origFamily, family,
  4214.             face, pixelSizeNum, pointSizeNum, pitch, charsetID,
  4215.             charset, charsetlang, pixelSizeFontSpec,
  4216.             pointSizeFontSpec, origCharset);
  4217.  
  4218. #if 0
  4219. (void) fprintf
  4220. (
  4221.     real_stderr,
  4222.     "\"%s\" \"%s\" \"%s\" %d \"%s%s\" %d \"%s\" \"%s\"\n\"%s\"\n",
  4223.     foundry,
  4224.     family,
  4225.     FE_INDEX_TO_FACE(face),
  4226.     pointSizeNum,
  4227.     ((pitch & fe_FONT_PITCH_MONO) ? "m" : ""),
  4228.     ((pitch & fe_FONT_PITCH_PROPORTIONAL) ? "p" : ""),
  4229.     charsetID,
  4230.     charset,
  4231.     charsetlang,
  4232.     pointSizeFontSpec
  4233. );
  4234. #endif /* 0 */
  4235.  
  4236.         free(origFoundry);
  4237.         free(foundry);
  4238.         free(family);
  4239.     }
  4240.  
  4241.     FE_MAYBE_FREE(font);
  4242.     FE_MAYBE_FREE(origCharset);
  4243.     FE_MAYBE_FREE(origFamily);
  4244.     FE_MAYBE_FREE(origWeight);
  4245.     FE_MAYBE_FREE(pixelSizeFontSpec);
  4246.     FE_MAYBE_FREE(pointSizeFontSpec);
  4247.  
  4248.     XFreeFontNames(fonts);
  4249.  
  4250.     (void) PR_snprintf(clas, sizeof(clas),
  4251.         "%s.DocumentFonts.SizeIncrement", fe_progclass);
  4252.     (void) PR_snprintf(name, sizeof(name),
  4253.         "%s.documentFonts.sizeIncrement", fe_progclass);
  4254.     if (XrmGetResource(db, name, clas, &type, &value))
  4255.     {
  4256.         fe_FontSizeIncrement = (((double) atoi(value.addr)) / 100.0);
  4257.         if (fe_FontSizeIncrement <= 0)
  4258.         {
  4259.             fe_FontSizeIncrement = FE_DEFAULT_FONT_SIZE_INCREMENT;
  4260.         }
  4261.     }
  4262.  
  4263.     (void) PR_snprintf(clas, sizeof(clas),
  4264.                            "%s.DocumentFonts.MaximumPoints", fe_progclass);
  4265.     (void) PR_snprintf(name, sizeof(name),
  4266.                            "%s.documentFonts.maximumPoints", fe_progclass);
  4267.     if (XrmGetResource(db, name, clas, &type, &value))
  4268.     {
  4269.             fe_FontMaximumPoints = atoi(value.addr);
  4270.             if (fe_FontMaximumPoints <= 0)
  4271.                 fe_FontMaximumPoints = FE_DEFAULT_FONT_MAXIMUM_POINTS;
  4272.     }
  4273.  
  4274.         for (i=0; i < fe_GenericFamilyCount; i++) {
  4275.             (void) PR_snprintf(clas, sizeof(clas),
  4276.                                "%s.DocumentFonts.Generic.%s",
  4277.                                fe_progclass, fe_generics[i].class_name);
  4278.             (void) PR_snprintf(name, sizeof(name),
  4279.                                "%s.documentFonts.generic.%s",
  4280.                                fe_progclass, fe_generics[i].generic_name);
  4281.             if (XrmGetResource(db, name, clas, &type, &value))
  4282.                 fe_generics[i].family_name = strdup(value.addr);
  4283.         }
  4284.  
  4285.     fe_loadUnicodePseudoFonts(dpy, "helvetica", fe_FONT_PITCH_PROPORTIONAL);
  4286.     fe_loadUnicodePseudoFonts(dpy, "times",     fe_FONT_PITCH_PROPORTIONAL);
  4287.     fe_loadUnicodePseudoFonts(dpy, "courier",   fe_FONT_PITCH_MONO);
  4288.     fe_loadUnicodePseudoFonts(dpy, "fixed",     fe_FONT_PITCH_MONO);
  4289.  
  4290.     fe_SortFonts();
  4291.  
  4292.     fe_SetDefaultFontSettings(dpy);
  4293.  
  4294.     fe_ReportFontCharSets();
  4295.  
  4296. #ifdef FE_PRINT_FONTS
  4297.     fe_PrintFonts();
  4298. #endif
  4299. }
  4300.  
  4301.  
  4302. #ifdef DEBUG
  4303. void
  4304. fe_FreeFonts(void)
  4305. {
  4306.     fe_FontCharSet    *charset;
  4307.     fe_FontFace    *face;
  4308.     fe_FontFamily    *family;
  4309.     int        i;
  4310.     int        j;
  4311.     int        k;
  4312.     fe_FontFace    *nextFace;
  4313.     fe_FontPitch    *pitch;
  4314.  
  4315.     for (i = 0; i < INTL_CHAR_SET_MAX; i++)
  4316.     {
  4317.         charset = &fe_FontCharSets[i];
  4318.         if (!charset->name)
  4319.         {
  4320.             continue;
  4321.         }
  4322.         for (j = 0; j < 2; j++)
  4323.         {
  4324.             pitch = &charset->pitches[j];
  4325.             for (k = 0; k < pitch->numberOfFamilies; k++)
  4326.             {
  4327.                 family = &pitch->families[k];
  4328.                 free(family->name);
  4329.                 free(family->foundry);
  4330.                 free(family->family);
  4331.                 free(family->pixelSizes);
  4332.                 free(family->pointSizes);
  4333.             }
  4334.             free(pitch->families);
  4335.         }
  4336.         free(charset->name);
  4337.         free(charset->mimeName);
  4338.     }
  4339.  
  4340.     (void) memset(fe_FontCharSets, 0, sizeof(fe_FontCharSets));
  4341.  
  4342.     face = fe_FontFaceList;
  4343.     while (face)
  4344.     {
  4345.         nextFace = face->next;
  4346.         if (face->longXLFDFontName)
  4347.         {
  4348.             free(face->longXLFDFontName);
  4349.         }
  4350.         if (face->font)
  4351.         {
  4352.             XFreeFont(fe_display, face->font);
  4353.         }
  4354.         face->loaded = FALSE;
  4355.         free(face);
  4356.         face = nextFace;
  4357.     }
  4358.     fe_FontFaceList = NULL;
  4359.  
  4360.     if (fe_FixedFont)
  4361.     {
  4362.         XFreeFont(fe_display, fe_FixedFont);
  4363.         fe_FixedFont = NULL;
  4364.     }
  4365. }
  4366. #endif /* DEBUG */
  4367.  
  4368.  
  4369. static void
  4370. fe_AddFontSetting(fe_FontSettings **ret, fe_FontCharSet *charset, int i,
  4371.     fe_FontFamily *family, fe_FontSize *size)
  4372. {
  4373.     fe_FontSettings    *set;
  4374.     char        *spec;
  4375.  
  4376.     spec = PR_smprintf
  4377.     (
  4378.         "%s-%s-%d-%s-%s-%s\n",
  4379.         family->foundry,
  4380.         family->family,
  4381.         size->size,
  4382.         family->allowScaling ? "scale" : "noscale",
  4383.         fe_PropOrFixedFont(i),
  4384.         charset->mimeName
  4385.     );
  4386.  
  4387.     set = FE_MALLOC_ZAP(fe_FontSettings);
  4388.  
  4389.     if ((!spec) || (!set))
  4390.     {
  4391.         return;
  4392.     }
  4393.  
  4394.     set->spec = spec;
  4395.     set->next = *ret;
  4396.     *ret = set;
  4397. }
  4398.  
  4399.  
  4400. fe_FontSettings *
  4401. fe_GetFontSettings(void)
  4402. {
  4403.     fe_FontCharSet    *charset;
  4404.     fe_FontFamily    *family;
  4405.     int        i;
  4406.     int        j;
  4407.     int        k;
  4408.     int        m;
  4409.     fe_FontPitch    *pitch;
  4410.     fe_FontSettings    *ret;
  4411.     fe_FontSize    *size;
  4412.  
  4413.     ret = NULL;
  4414.  
  4415.     for (i = 0; i < INTL_CHAR_SET_MAX; i++)
  4416.     {
  4417.         charset = &fe_FontCharSets[i];
  4418.         if (!charset->name)
  4419.         {
  4420.             continue;
  4421.         }
  4422.         for (j = 0; j < 2; j++)
  4423.         {
  4424.             pitch = &charset->pitches[j];
  4425.             for (k = 0; k < pitch->numberOfFamilies; k++)
  4426.             {
  4427.                 family = &pitch->families[k];
  4428.                 if (family->selected)
  4429.                 {
  4430.                     for (m = 0; m < family->numberOfPointSizes;
  4431.                         m++)
  4432.                     {
  4433.                         size = &family->pointSizes[m];
  4434.                         if (size->selected)
  4435.                         {
  4436.                             fe_AddFontSetting
  4437.                             (
  4438.                                 &ret,
  4439.                                 charset,
  4440.                                 j,
  4441.                                 family,
  4442.                                 size
  4443.                             );
  4444.                         }
  4445.                     }
  4446.                 }
  4447.             }
  4448.         }
  4449.     }
  4450.  
  4451.     return ret;
  4452. }
  4453.  
  4454.  
  4455. void
  4456. fe_SetFontSettings(fe_FontSettings *set)
  4457. {
  4458. }
  4459.  
  4460.  
  4461. char *
  4462. fe_GetFontCharSetSetting(void)
  4463. {
  4464.     fe_FontCharSet    *charset;
  4465.     int        i;
  4466.  
  4467.     for (i = 0; i < INTL_CHAR_SET_MAX; i++)
  4468.     {
  4469.         charset = &fe_FontCharSets[i];
  4470.         if (!charset->name)
  4471.         {
  4472.             continue;
  4473.         }
  4474.         if (charset->selected)
  4475.         {
  4476.             return charset->mimeName;
  4477.         }
  4478.     }
  4479.  
  4480.     return "";
  4481. }
  4482.  
  4483.  
  4484. void
  4485. fe_FreeFontSettings(fe_FontSettings *set)
  4486. {
  4487.     fe_FontSettings    *next;
  4488.  
  4489.     while (set)
  4490.     {
  4491.         next = set->next;
  4492.         free(set->spec);
  4493.         free(set);
  4494.         set = next;
  4495.     }
  4496. }
  4497.  
  4498.  
  4499. int
  4500. fe_GetStrikePosition(int charset, fe_Font font)
  4501. {
  4502.     int        ascent;
  4503.     int        descent;
  4504.     XCharStruct    overall;
  4505.  
  4506.     /*
  4507.      * strike through the middle of lower case letters
  4508.      */
  4509.     FE_TEXT_EXTENTS(charset, font, "a", 1, &ascent, &descent, &overall);
  4510.  
  4511.     return -((overall.ascent + 1) / 2);
  4512. }
  4513.  
  4514.  
  4515. int
  4516. fe_GetUnderlinePosition(int charset)
  4517. {
  4518.     /*
  4519.      * Underline position does not depend on font, otherwise you get
  4520.      * varying positions within a single line, and this looks bad.
  4521.      */
  4522.  
  4523.     if ((fe_CharSetInfoArray[charset & 0xff].type == FE_FONT_TYPE_GROUP)
  4524.         || ((charset&0xFF) == (CS_UTF8&0xFF)))
  4525.     {
  4526.         /*
  4527.          * East Asian fonts have a lower baseline.
  4528.          * Underline looks better like this.
  4529.          */
  4530.         return 3;
  4531.     }
  4532.  
  4533.     return 1;
  4534. }
  4535.  
  4536.  
  4537. static XP_Bool
  4538. fe_AreNormalFontsAvail(int16 win_csid)
  4539. {
  4540.     if (fe_FontCharSets[win_csid & 0xff].name != NULL)
  4541.         return TRUE;
  4542.     else
  4543.         return FALSE;
  4544. }
  4545.  
  4546. static fe_Font
  4547. fe_LoadNormalFont(MWContext *context, char *familyName, 
  4548.                   int points, int sizeNum,
  4549.           int fontmask, int charset,
  4550.           int pitch, int faceNum, Display *dpy)
  4551. {
  4552.     fe_FontFace    *face;
  4553.     fe_Font        font;
  4554.     fe_FontFamily    *family = NULL;
  4555.         fe_FontSize     *size;
  4556.         double          decipoints;
  4557.  
  4558.     if (familyName && *familyName)
  4559.     {
  4560.         family = fe_FontFindFamily(charset, pitch, familyName);
  4561.     }
  4562.     if (!family)
  4563.     {
  4564.         family = fe_GetFontFamily(charset, pitch);
  4565.         if (!family)
  4566.         {
  4567.             return NULL;
  4568.         }
  4569.     }
  4570.         if (! points)
  4571.             size = family->htmlSizes[sizeNum-1];
  4572.         else {
  4573.             decipoints = (double) (points * 10);
  4574.             size = fe_FindFontPointSize(family, decipoints, True, False);
  4575.         }
  4576.         if (!size)
  4577.             return NULL;
  4578.         face = size->faces[faceNum];
  4579.         if (!face)
  4580.             return NULL;
  4581.  
  4582.     font = face->font;
  4583.     if (font)
  4584.     {
  4585.         return font;
  4586.     }
  4587.  
  4588.     else {
  4589.         font = fe_LoadXFont(dpy, face->longXLFDFontName);
  4590.     }
  4591.     if (font)
  4592.     {
  4593.         face->font = font;
  4594.         return font;
  4595.     }
  4596.  
  4597.     return NULL;
  4598. }
  4599.  
  4600.  
  4601. void
  4602. fe_GenericFontExtents(int charset, fe_Font font, 
  4603.                         int *fontAscent, int *fontDescent)
  4604. {
  4605.     int            ascent;
  4606.     int            ascentExtra;
  4607.     int            descent;
  4608.     int            descentExtra;
  4609.     XFontStruct        *f;
  4610.     fe_FontGroupFont    *fonts;
  4611.     int            i;
  4612.     int            num;
  4613.     fe_CharSetInfo  *info = &fe_CharSetInfoArray[(charset) & 0xff];
  4614.  
  4615.     /*
  4616.      * Handle Unicode Pseudo Fonts
  4617.      */
  4618.     if (info->info == FE_FONT_INFO_UNICODE) {
  4619.         fe_UnicodePseudoFont *ufont = (fe_UnicodePseudoFont *)font;
  4620.         if (ufont->tag != UNICODE_PSEUDO_FONT_TAG) {
  4621. #ifdef DEBUG_bstell
  4622.             printf("bad ufont %s %d\n", __FILE__, __LINE__);
  4623. #endif
  4624.             *(fontAscent) = 12;
  4625.             *(fontDescent) = 3;
  4626.         }
  4627.                     
  4628.         (void)fe_UnicodeInitXfont(font, CS_LATIN1);
  4629.         *(fontAscent) = ufont->ascent;
  4630.         *(fontDescent) = ufont->descent;
  4631.         return;
  4632.     }
  4633.  
  4634.     /*
  4635.      * Handle EUC Fonts
  4636.      */
  4637.     fonts = (fe_FontGroupFont *) font;
  4638.  
  4639.     ascent = 0;
  4640.     descent = 0;
  4641.  
  4642.     num = fe_CharSetFuncsArray[info->info].numberOfFonts;
  4643.     for (i = 0; i < num; i++)
  4644.     {
  4645.         if (i)
  4646.         {
  4647.             /*
  4648.              * East Asian text looks better with extra space for
  4649.              * underline.
  4650.              */
  4651.             ascentExtra = 1;
  4652.             descentExtra = 2;
  4653.         }
  4654.         else
  4655.         {
  4656.             ascentExtra = 0;
  4657.             descentExtra = 0;
  4658.         }
  4659.         f = fonts[i].xFont;
  4660.         if (f)
  4661.         {
  4662.             if (f->ascent + ascentExtra > ascent)
  4663.             {
  4664.                 ascent = f->ascent + ascentExtra;
  4665.             }
  4666.             if (f->descent + descentExtra > descent)
  4667.             {
  4668.                 descent = f->descent + descentExtra;
  4669.             }
  4670.         }
  4671.     }
  4672.  
  4673.     *fontAscent = ascent;
  4674.     *fontDescent = descent;
  4675. }
  4676.  
  4677.  
  4678. #define FE_PROCESS_STRING_BUFFER_SIZE    1024
  4679.  
  4680.  
  4681. static void
  4682. fe_ProcessEUCString(int charset, fe_StringProcessTable *table, 
  4683.     fe_XDrawStringFunc draw1, 
  4684.     fe_XDrawStringFunc draw2, 
  4685.     Display *dpy, Drawable d, fe_Font fontGroup,
  4686.     GC gc, int x, int y, unsigned char *in, unsigned int inEnd,
  4687.     int *fontAscent, int *fontDescent, XCharStruct *overall,
  4688.     unsigned char numberOfFonts)
  4689. {
  4690.     int            ascent;
  4691.     int            descent;
  4692.     int            direction;
  4693.     fe_StringProcessTable    *entry;
  4694.     fe_FontGroupFont    *font;
  4695.     unsigned char        fontIndex;
  4696.     fe_FontGroupFont    *fonts;
  4697.     unsigned int        inIndex;
  4698.     unsigned char        len;
  4699.     unsigned char        mask1;
  4700.     unsigned char        mask2;
  4701.     XCharStruct        metrics;
  4702.     unsigned char        nextFontIndex;
  4703.     unsigned char        out1[FE_PROCESS_STRING_BUFFER_SIZE];
  4704.     XChar2b            out2[FE_PROCESS_STRING_BUFFER_SIZE/2];
  4705.     unsigned int        out1Index;
  4706.     unsigned int        out2Index;
  4707.     XChar2b            *p;
  4708.     unsigned char        skip;
  4709.     XFontStruct        *xFont;
  4710.  
  4711.     if (inEnd > FE_PROCESS_STRING_BUFFER_SIZE)
  4712.     {
  4713.         inEnd = FE_PROCESS_STRING_BUFFER_SIZE;
  4714.     }
  4715.  
  4716.     fonts = (fe_FontGroupFont *) fontGroup;
  4717.  
  4718.     inIndex = 0;
  4719.  
  4720.     out1Index = 0;
  4721.  
  4722.     out2Index = 0;
  4723.  
  4724.     if (overall)
  4725.     {
  4726.         overall->lbearing = 0;
  4727.         overall->rbearing = 0;
  4728.         overall->width = 0;
  4729.         overall->ascent = 0;
  4730.         overall->descent = 0;
  4731.     }
  4732.  
  4733.     while (inIndex < inEnd)
  4734.     {
  4735.         entry = &table[in[inIndex]];
  4736.         skip = entry->skip;
  4737.         len = entry->len;
  4738.         fontIndex = entry->fontIndex;
  4739.         font = &fonts[fontIndex];
  4740.         xFont = font->xFont;
  4741.         if (gc && xFont)
  4742.         {
  4743.             XSetFont(dpy, gc, xFont->fid);
  4744.         }
  4745.         if (len == 1)
  4746.         {
  4747.             while (inIndex < inEnd)
  4748.             {
  4749.                 inIndex += skip;
  4750.                 if (inIndex >= inEnd)
  4751.                 {
  4752.                     break;
  4753.                 }
  4754.                 out1[out1Index++] = in[inIndex++];
  4755.                 if (inIndex >= inEnd)
  4756.                 {
  4757.                     break;
  4758.                 }
  4759.                 nextFontIndex = table[in[inIndex]].fontIndex;
  4760.                 if (nextFontIndex != fontIndex)
  4761.                 {
  4762.                     break;
  4763.                 }
  4764.             }
  4765.             if (out1Index && xFont)
  4766.             {
  4767.                 XTextExtents(xFont, out1, out1Index,
  4768.                     &direction, &ascent, &descent,
  4769.                     &metrics);
  4770.                 if (draw1)
  4771.                 {
  4772.                     (*draw1)(dpy, d, gc, x, y,
  4773.                         out1, out1Index);
  4774.                 }
  4775.                 x += metrics.width;
  4776.                 if (overall)
  4777.                 {
  4778.                     overall->width += metrics.width;
  4779.                     if (metrics.ascent > overall->ascent)
  4780.                     {
  4781.                         overall->ascent =
  4782.                             metrics.ascent;
  4783.                     }
  4784.                     if (metrics.descent > overall->descent)
  4785.                     {
  4786.                         overall->descent =
  4787.                             metrics.descent;
  4788.                     }
  4789.                 }
  4790.             }
  4791.             out1Index = 0;
  4792.         }
  4793.         else
  4794.         {
  4795.             mask1 = font->mask1;
  4796.             mask2 = font->mask2;
  4797.             while (inIndex < inEnd)
  4798.             {
  4799.                 inIndex += skip;
  4800.                 if ((inIndex + 1) >= inEnd)
  4801.                 {
  4802.                     inIndex++;
  4803.                     break;
  4804.                 }
  4805.                 p = &out2[out2Index++];
  4806.                 p->byte1 = (in[inIndex++] & mask1);
  4807.                 p->byte2 = (in[inIndex++] & mask2);
  4808.                 if (inIndex >= inEnd)
  4809.                 {
  4810.                     break;
  4811.                 }
  4812.                 nextFontIndex = table[in[inIndex]].fontIndex;
  4813.                 if (nextFontIndex != fontIndex)
  4814.                 {
  4815.                     break;
  4816.                 }
  4817.             }
  4818.             if (out2Index && xFont)
  4819.             {
  4820.                 XTextExtents16(xFont, out2, out2Index,
  4821.                     &direction, &ascent, &descent,
  4822.                     &metrics);
  4823.                 if (draw2)
  4824.                 {
  4825.                     (*draw2)(dpy, d, gc, x, y,
  4826.                         (char *) out2, out2Index);
  4827.                 }
  4828.                 x += metrics.width;
  4829.                 if (overall)
  4830.                 {
  4831.                     overall->width += metrics.width;
  4832.                     if (metrics.ascent > overall->ascent)
  4833.                     {
  4834.                         overall->ascent =
  4835.                             metrics.ascent;
  4836.                     }
  4837.                     if (metrics.descent > overall->descent)
  4838.                     {
  4839.                         overall->descent =
  4840.                             metrics.descent;
  4841.                     }
  4842.                 }
  4843.             }
  4844.             out2Index = 0;
  4845.         }
  4846.     }
  4847.  
  4848.     if (overall)
  4849.     {
  4850.         /* @@@ fix */
  4851.         overall->rbearing = overall->width;
  4852.  
  4853.         fe_GenericFontExtents(charset, fontGroup, fontAscent,
  4854.             fontDescent);
  4855.     }
  4856. }
  4857.  
  4858.  
  4859.             /*    fontIndex    skip    len    */
  4860. #define EUCCN_LATIN1    {    0,        0,    1    }
  4861. #define EUCCN_GB2312    {    1,        0,    2    }
  4862.  
  4863. static fe_StringProcessTable EUCCNTable[] =
  4864. {
  4865.     /* 0x00 */    EUCCN_LATIN1,
  4866.     /* 0x01 */    EUCCN_LATIN1,
  4867.     /* 0x02 */    EUCCN_LATIN1,
  4868.     /* 0x03 */    EUCCN_LATIN1,
  4869.     /* 0x04 */    EUCCN_LATIN1,
  4870.     /* 0x05 */    EUCCN_LATIN1,
  4871.     /* 0x06 */    EUCCN_LATIN1,
  4872.     /* 0x07 */    EUCCN_LATIN1,
  4873.     /* 0x08 */    EUCCN_LATIN1,
  4874.     /* 0x09 */    EUCCN_LATIN1,
  4875.     /* 0x0a */    EUCCN_LATIN1,
  4876.     /* 0x0b */    EUCCN_LATIN1,
  4877.     /* 0x0c */    EUCCN_LATIN1,
  4878.     /* 0x0d */    EUCCN_LATIN1,
  4879.     /* 0x0e */    EUCCN_LATIN1,
  4880.     /* 0x0f */    EUCCN_LATIN1,
  4881.     /* 0x10 */    EUCCN_LATIN1,
  4882.     /* 0x11 */    EUCCN_LATIN1,
  4883.     /* 0x12 */    EUCCN_LATIN1,
  4884.     /* 0x13 */    EUCCN_LATIN1,
  4885.     /* 0x14 */    EUCCN_LATIN1,
  4886.     /* 0x15 */    EUCCN_LATIN1,
  4887.     /* 0x16 */    EUCCN_LATIN1,
  4888.     /* 0x17 */    EUCCN_LATIN1,
  4889.     /* 0x18 */    EUCCN_LATIN1,
  4890.     /* 0x19 */    EUCCN_LATIN1,
  4891.     /* 0x1a */    EUCCN_LATIN1,
  4892.     /* 0x1b */    EUCCN_LATIN1,
  4893.     /* 0x1c */    EUCCN_LATIN1,
  4894.     /* 0x1d */    EUCCN_LATIN1,
  4895.     /* 0x1e */    EUCCN_LATIN1,
  4896.     /* 0x1f */    EUCCN_LATIN1,
  4897.     /* 0x20 */    EUCCN_LATIN1,
  4898.     /* 0x21 */    EUCCN_LATIN1,
  4899.     /* 0x22 */    EUCCN_LATIN1,
  4900.     /* 0x23 */    EUCCN_LATIN1,
  4901.     /* 0x24 */    EUCCN_LATIN1,
  4902.     /* 0x25 */    EUCCN_LATIN1,
  4903.     /* 0x26 */    EUCCN_LATIN1,
  4904.     /* 0x27 */    EUCCN_LATIN1,
  4905.     /* 0x28 */    EUCCN_LATIN1,
  4906.     /* 0x29 */    EUCCN_LATIN1,
  4907.     /* 0x2a */    EUCCN_LATIN1,
  4908.     /* 0x2b */    EUCCN_LATIN1,
  4909.     /* 0x2c */    EUCCN_LATIN1,
  4910.     /* 0x2d */    EUCCN_LATIN1,
  4911.     /* 0x2e */    EUCCN_LATIN1,
  4912.     /* 0x2f */    EUCCN_LATIN1,
  4913.     /* 0x30 */    EUCCN_LATIN1,
  4914.     /* 0x31 */    EUCCN_LATIN1,
  4915.     /* 0x32 */    EUCCN_LATIN1,
  4916.     /* 0x33 */    EUCCN_LATIN1,
  4917.     /* 0x34 */    EUCCN_LATIN1,
  4918.     /* 0x35 */    EUCCN_LATIN1,
  4919.     /* 0x36 */    EUCCN_LATIN1,
  4920.     /* 0x37 */    EUCCN_LATIN1,
  4921.     /* 0x38 */    EUCCN_LATIN1,
  4922.     /* 0x39 */    EUCCN_LATIN1,
  4923.     /* 0x3a */    EUCCN_LATIN1,
  4924.     /* 0x3b */    EUCCN_LATIN1,
  4925.     /* 0x3c */    EUCCN_LATIN1,
  4926.     /* 0x3d */    EUCCN_LATIN1,
  4927.     /* 0x3e */    EUCCN_LATIN1,
  4928.     /* 0x3f */    EUCCN_LATIN1,
  4929.     /* 0x40 */    EUCCN_LATIN1,
  4930.     /* 0x41 */    EUCCN_LATIN1,
  4931.     /* 0x42 */    EUCCN_LATIN1,
  4932.     /* 0x43 */    EUCCN_LATIN1,
  4933.     /* 0x44 */    EUCCN_LATIN1,
  4934.     /* 0x45 */    EUCCN_LATIN1,
  4935.     /* 0x46 */    EUCCN_LATIN1,
  4936.     /* 0x47 */    EUCCN_LATIN1,
  4937.     /* 0x48 */    EUCCN_LATIN1,
  4938.     /* 0x49 */    EUCCN_LATIN1,
  4939.     /* 0x4a */    EUCCN_LATIN1,
  4940.     /* 0x4b */    EUCCN_LATIN1,
  4941.     /* 0x4c */    EUCCN_LATIN1,
  4942.     /* 0x4d */    EUCCN_LATIN1,
  4943.     /* 0x4e */    EUCCN_LATIN1,
  4944.     /* 0x4f */    EUCCN_LATIN1,
  4945.     /* 0x50 */    EUCCN_LATIN1,
  4946.     /* 0x51 */    EUCCN_LATIN1,
  4947.     /* 0x52 */    EUCCN_LATIN1,
  4948.     /* 0x53 */    EUCCN_LATIN1,
  4949.     /* 0x54 */    EUCCN_LATIN1,
  4950.     /* 0x55 */    EUCCN_LATIN1,
  4951.     /* 0x56 */    EUCCN_LATIN1,
  4952.     /* 0x57 */    EUCCN_LATIN1,
  4953.     /* 0x58 */    EUCCN_LATIN1,
  4954.     /* 0x59 */    EUCCN_LATIN1,
  4955.     /* 0x5a */    EUCCN_LATIN1,
  4956.     /* 0x5b */    EUCCN_LATIN1,
  4957.     /* 0x5c */    EUCCN_LATIN1,
  4958.     /* 0x5d */    EUCCN_LATIN1,
  4959.     /* 0x5e */    EUCCN_LATIN1,
  4960.     /* 0x5f */    EUCCN_LATIN1,
  4961.     /* 0x60 */    EUCCN_LATIN1,
  4962.     /* 0x61 */    EUCCN_LATIN1,
  4963.     /* 0x62 */    EUCCN_LATIN1,
  4964.     /* 0x63 */    EUCCN_LATIN1,
  4965.     /* 0x64 */    EUCCN_LATIN1,
  4966.     /* 0x65 */    EUCCN_LATIN1,
  4967.     /* 0x66 */    EUCCN_LATIN1,
  4968.     /* 0x67 */    EUCCN_LATIN1,
  4969.     /* 0x68 */    EUCCN_LATIN1,
  4970.     /* 0x69 */    EUCCN_LATIN1,
  4971.     /* 0x6a */    EUCCN_LATIN1,
  4972.     /* 0x6b */    EUCCN_LATIN1,
  4973.     /* 0x6c */    EUCCN_LATIN1,
  4974.     /* 0x6d */    EUCCN_LATIN1,
  4975.     /* 0x6e */    EUCCN_LATIN1,
  4976.     /* 0x6f */    EUCCN_LATIN1,
  4977.     /* 0x70 */    EUCCN_LATIN1,
  4978.     /* 0x71 */    EUCCN_LATIN1,
  4979.     /* 0x72 */    EUCCN_LATIN1,
  4980.     /* 0x73 */    EUCCN_LATIN1,
  4981.     /* 0x74 */    EUCCN_LATIN1,
  4982.     /* 0x75 */    EUCCN_LATIN1,
  4983.     /* 0x76 */    EUCCN_LATIN1,
  4984.     /* 0x77 */    EUCCN_LATIN1,
  4985.     /* 0x78 */    EUCCN_LATIN1,
  4986.     /* 0x79 */    EUCCN_LATIN1,
  4987.     /* 0x7a */    EUCCN_LATIN1,
  4988.     /* 0x7b */    EUCCN_LATIN1,
  4989.     /* 0x7c */    EUCCN_LATIN1,
  4990.     /* 0x7d */    EUCCN_LATIN1,
  4991.     /* 0x7e */    EUCCN_LATIN1,
  4992.     /* 0x7f */    EUCCN_LATIN1,
  4993.     /* 0x80 */    EUCCN_LATIN1,
  4994.     /* 0x81 */    EUCCN_LATIN1,
  4995.     /* 0x82 */    EUCCN_LATIN1,
  4996.     /* 0x83 */    EUCCN_LATIN1,
  4997.     /* 0x84 */    EUCCN_LATIN1,
  4998.     /* 0x85 */    EUCCN_LATIN1,
  4999.     /* 0x86 */    EUCCN_LATIN1,
  5000.     /* 0x87 */    EUCCN_LATIN1,
  5001.     /* 0x88 */    EUCCN_LATIN1,
  5002.     /* 0x89 */    EUCCN_LATIN1,
  5003.     /* 0x8a */    EUCCN_LATIN1,
  5004.     /* 0x8b */    EUCCN_LATIN1,
  5005.     /* 0x8c */    EUCCN_LATIN1,
  5006.     /* 0x8d */    EUCCN_LATIN1,
  5007.     /* 0x8e */    EUCCN_LATIN1,
  5008.     /* 0x8f */    EUCCN_LATIN1,
  5009.     /* 0x90 */    EUCCN_LATIN1,
  5010.     /* 0x91 */    EUCCN_LATIN1,
  5011.     /* 0x92 */    EUCCN_LATIN1,
  5012.     /* 0x93 */    EUCCN_LATIN1,
  5013.     /* 0x94 */    EUCCN_LATIN1,
  5014.     /* 0x95 */    EUCCN_LATIN1,
  5015.     /* 0x96 */    EUCCN_LATIN1,
  5016.     /* 0x97 */    EUCCN_LATIN1,
  5017.     /* 0x98 */    EUCCN_LATIN1,
  5018.     /* 0x99 */    EUCCN_LATIN1,
  5019.     /* 0x9a */    EUCCN_LATIN1,
  5020.     /* 0x9b */    EUCCN_LATIN1,
  5021.     /* 0x9c */    EUCCN_LATIN1,
  5022.     /* 0x9d */    EUCCN_LATIN1,
  5023.     /* 0x9e */    EUCCN_LATIN1,
  5024.     /* 0x9f */    EUCCN_LATIN1,
  5025.     /* 0xa0 */    EUCCN_LATIN1,
  5026.     /* 0xa1 */    EUCCN_GB2312,
  5027.     /* 0xa2 */    EUCCN_GB2312,
  5028.     /* 0xa3 */    EUCCN_GB2312,
  5029.     /* 0xa4 */    EUCCN_GB2312,
  5030.     /* 0xa5 */    EUCCN_GB2312,
  5031.     /* 0xa6 */    EUCCN_GB2312,
  5032.     /* 0xa7 */    EUCCN_GB2312,
  5033.     /* 0xa8 */    EUCCN_GB2312,
  5034.     /* 0xa9 */    EUCCN_GB2312,
  5035.     /* 0xaa */    EUCCN_GB2312,
  5036.     /* 0xab */    EUCCN_GB2312,
  5037.     /* 0xac */    EUCCN_GB2312,
  5038.     /* 0xad */    EUCCN_GB2312,
  5039.     /* 0xae */    EUCCN_GB2312,
  5040.     /* 0xaf */    EUCCN_GB2312,
  5041.     /* 0xb0 */    EUCCN_GB2312,
  5042.     /* 0xb1 */    EUCCN_GB2312,
  5043.     /* 0xb2 */    EUCCN_GB2312,
  5044.     /* 0xb3 */    EUCCN_GB2312,
  5045.     /* 0xb4 */    EUCCN_GB2312,
  5046.     /* 0xb5 */    EUCCN_GB2312,
  5047.     /* 0xb6 */    EUCCN_GB2312,
  5048.     /* 0xb7 */    EUCCN_GB2312,
  5049.     /* 0xb8 */    EUCCN_GB2312,
  5050.     /* 0xb9 */    EUCCN_GB2312,
  5051.     /* 0xba */    EUCCN_GB2312,
  5052.     /* 0xbb */    EUCCN_GB2312,
  5053.     /* 0xbc */    EUCCN_GB2312,
  5054.     /* 0xbd */    EUCCN_GB2312,
  5055.     /* 0xbe */    EUCCN_GB2312,
  5056.     /* 0xbf */    EUCCN_GB2312,
  5057.     /* 0xc0 */    EUCCN_GB2312,
  5058.     /* 0xc1 */    EUCCN_GB2312,
  5059.     /* 0xc2 */    EUCCN_GB2312,
  5060.     /* 0xc3 */    EUCCN_GB2312,
  5061.     /* 0xc4 */    EUCCN_GB2312,
  5062.     /* 0xc5 */    EUCCN_GB2312,
  5063.     /* 0xc6 */    EUCCN_GB2312,
  5064.     /* 0xc7 */    EUCCN_GB2312,
  5065.     /* 0xc8 */    EUCCN_GB2312,
  5066.     /* 0xc9 */    EUCCN_GB2312,
  5067.     /* 0xca */    EUCCN_GB2312,
  5068.     /* 0xcb */    EUCCN_GB2312,
  5069.     /* 0xcc */    EUCCN_GB2312,
  5070.     /* 0xcd */    EUCCN_GB2312,
  5071.     /* 0xce */    EUCCN_GB2312,
  5072.     /* 0xcf */    EUCCN_GB2312,
  5073.     /* 0xd0 */    EUCCN_GB2312,
  5074.     /* 0xd1 */    EUCCN_GB2312,
  5075.     /* 0xd2 */    EUCCN_GB2312,
  5076.     /* 0xd3 */    EUCCN_GB2312,
  5077.     /* 0xd4 */    EUCCN_GB2312,
  5078.     /* 0xd5 */    EUCCN_GB2312,
  5079.     /* 0xd6 */    EUCCN_GB2312,
  5080.     /* 0xd7 */    EUCCN_GB2312,
  5081.     /* 0xd8 */    EUCCN_GB2312,
  5082.     /* 0xd9 */    EUCCN_GB2312,
  5083.     /* 0xda */    EUCCN_GB2312,
  5084.     /* 0xdb */    EUCCN_GB2312,
  5085.     /* 0xdc */    EUCCN_GB2312,
  5086.     /* 0xdd */    EUCCN_GB2312,
  5087.     /* 0xde */    EUCCN_GB2312,
  5088.     /* 0xdf */    EUCCN_GB2312,
  5089.     /* 0xe0 */    EUCCN_GB2312,
  5090.     /* 0xe1 */    EUCCN_GB2312,
  5091.     /* 0xe2 */    EUCCN_GB2312,
  5092.     /* 0xe3 */    EUCCN_GB2312,
  5093.     /* 0xe4 */    EUCCN_GB2312,
  5094.     /* 0xe5 */    EUCCN_GB2312,
  5095.     /* 0xe6 */    EUCCN_GB2312,
  5096.     /* 0xe7 */    EUCCN_GB2312,
  5097.     /* 0xe8 */    EUCCN_GB2312,
  5098.     /* 0xe9 */    EUCCN_GB2312,
  5099.     /* 0xea */    EUCCN_GB2312,
  5100.     /* 0xeb */    EUCCN_GB2312,
  5101.     /* 0xec */    EUCCN_GB2312,
  5102.     /* 0xed */    EUCCN_GB2312,
  5103.     /* 0xee */    EUCCN_GB2312,
  5104.     /* 0xef */    EUCCN_GB2312,
  5105.     /* 0xf0 */    EUCCN_GB2312,
  5106.     /* 0xf1 */    EUCCN_GB2312,
  5107.     /* 0xf2 */    EUCCN_GB2312,
  5108.     /* 0xf3 */    EUCCN_GB2312,
  5109.     /* 0xf4 */    EUCCN_GB2312,
  5110.     /* 0xf5 */    EUCCN_GB2312,
  5111.     /* 0xf6 */    EUCCN_GB2312,
  5112.     /* 0xf7 */    EUCCN_GB2312,
  5113.     /* 0xf8 */    EUCCN_GB2312,
  5114.     /* 0xf9 */    EUCCN_GB2312,
  5115.     /* 0xfa */    EUCCN_GB2312,
  5116.     /* 0xfb */    EUCCN_GB2312,
  5117.     /* 0xfc */    EUCCN_GB2312,
  5118.     /* 0xfd */    EUCCN_GB2312,
  5119.     /* 0xfe */    EUCCN_GB2312,
  5120.     /* 0xff */    EUCCN_LATIN1,
  5121. };
  5122.  
  5123.  
  5124. static XP_Bool
  5125. fe_AreEUCCNFontsAvail(int16 win_csid)
  5126. {
  5127.     /* this needs to match the code in fe_LoadEUCCNFont */
  5128.     if ((fe_FontCharSets[CS_GB2312 & 0xff].name == NULL)
  5129.         && (fe_FontCharSets[CS_GB2312_11 & 0xff].name == NULL))
  5130.         return FALSE;
  5131.     else
  5132.         return TRUE;
  5133. }
  5134.  
  5135. static fe_Font
  5136. fe_LoadEUCCNFont(MWContext *context, char *familyName, int points,
  5137.                  int sizeNum, int fontmask, int charset, int pitch,
  5138.                  int faceNum, Display *dpy)
  5139. {
  5140.     int16            cs;
  5141.     int            len;
  5142.     fe_FontGroupFont    *ret;
  5143.  
  5144.     len = (2 * sizeof(fe_FontGroupFont));
  5145.     ret = calloc(1, len);
  5146.     if (!ret)
  5147.     {
  5148.         return NULL;
  5149.     }
  5150.     (void) memset(ret, 0, len);
  5151.  
  5152.     /* this needs to match the code in fe_AreEUCCNFontsAvail */
  5153.     cs = CS_LATIN1;
  5154.     ret[0].xFont = (XFontStruct *)
  5155.             fe_LoadFont(context, &cs, familyName, points, sizeNum, fontmask);
  5156.     if (cs != CS_LATIN1)
  5157.     {
  5158.         XP_FREE(ret);
  5159.         return NULL;
  5160.     }
  5161.  
  5162.     cs = CS_GB2312;
  5163.     ret[1].xFont = (XFontStruct *)
  5164.             fe_LoadFont(context, &cs, familyName, points, sizeNum, fontmask);
  5165.     if (cs == CS_GB2312)
  5166.     {
  5167.         ret[1].mask1 = 0x7f;
  5168.         ret[1].mask2 = 0x7f;
  5169.     }
  5170.     else
  5171.     {
  5172.         cs = CS_GB2312_11;
  5173.         ret[1].xFont = (XFontStruct *)
  5174.                     fe_LoadFont(context, &cs, familyName, points, sizeNum,
  5175.                                 fontmask);
  5176.         if (cs == CS_GB2312_11)
  5177.         {
  5178.             ret[1].mask1 = 0xff;
  5179.             ret[1].mask2 = 0xff;
  5180.         }
  5181.         else
  5182.         {
  5183.             XP_FREE(ret);
  5184.             return NULL;
  5185.         }
  5186.     }
  5187.  
  5188.     return (fe_Font) ret;
  5189. }
  5190.  
  5191.  
  5192. static void
  5193. fe_EUCCNTextExtents(fe_Font font, char *string, int len, int *direction,
  5194.     int *fontAscent, int *fontDescent, XCharStruct *overall)
  5195. {
  5196.     fe_ProcessEUCString(CS_GB_8BIT, EUCCNTable, 
  5197.         NULL, 
  5198.         NULL,
  5199.         NULL, None, font, NULL, 0, 0, string, len,
  5200.         fontAscent, fontDescent, overall,
  5201.         fe_CharSetFuncsArray[FE_FONT_INFO_EUCCN].numberOfFonts);
  5202. }
  5203.  
  5204.  
  5205. static void
  5206. fe_DrawEUCCNString(Display *dpy, Drawable d, fe_Font font, GC gc, int x,
  5207.     int y, char *string, int len)
  5208. {
  5209.     fe_ProcessEUCString(CS_GB_8BIT, EUCCNTable, 
  5210.         (fe_XDrawStringFunc) XDrawString, 
  5211.         (fe_XDrawStringFunc) XDrawString16,
  5212.         dpy, d, font, gc, x, y, string, len,
  5213.         NULL, NULL, NULL,
  5214.         0);
  5215. }
  5216.  
  5217.  
  5218. static void
  5219. fe_DrawEUCCNImageString(Display *dpy, Drawable d, fe_Font font, GC gc, GC gc2,
  5220.     int x, int y, char *string, int len)
  5221. {
  5222.     fe_ProcessEUCString(CS_GB_8BIT, EUCCNTable, 
  5223.         (fe_XDrawStringFunc) XDrawImageString,
  5224.         (fe_XDrawStringFunc) XDrawImageString16,
  5225.         dpy, d, font, gc, x, y, string, len,
  5226.         NULL, NULL, NULL,
  5227.         0);
  5228. }
  5229.  
  5230.  
  5231.             /*    fontIndex    skip    len    */
  5232. #define EUCJP_LATIN1    {    0,        0,    1    }
  5233. #define EUCJP_JISX0208    {    1,        0,    2    }
  5234. #define EUCJP_JISX0201    {    2,        1,    1    }
  5235. #define EUCJP_JISX0212    {    3,        1,    2    }
  5236.  
  5237. static fe_StringProcessTable EUCJPTable[] =
  5238. {
  5239.     /* 0x00 */    EUCJP_LATIN1,
  5240.     /* 0x01 */    EUCJP_LATIN1,
  5241.     /* 0x02 */    EUCJP_LATIN1,
  5242.     /* 0x03 */    EUCJP_LATIN1,
  5243.     /* 0x04 */    EUCJP_LATIN1,
  5244.     /* 0x05 */    EUCJP_LATIN1,
  5245.     /* 0x06 */    EUCJP_LATIN1,
  5246.     /* 0x07 */    EUCJP_LATIN1,
  5247.     /* 0x08 */    EUCJP_LATIN1,
  5248.     /* 0x09 */    EUCJP_LATIN1,
  5249.     /* 0x0a */    EUCJP_LATIN1,
  5250.     /* 0x0b */    EUCJP_LATIN1,
  5251.     /* 0x0c */    EUCJP_LATIN1,
  5252.     /* 0x0d */    EUCJP_LATIN1,
  5253.     /* 0x0e */    EUCJP_LATIN1,
  5254.     /* 0x0f */    EUCJP_LATIN1,
  5255.     /* 0x10 */    EUCJP_LATIN1,
  5256.     /* 0x11 */    EUCJP_LATIN1,
  5257.     /* 0x12 */    EUCJP_LATIN1,
  5258.     /* 0x13 */    EUCJP_LATIN1,
  5259.     /* 0x14 */    EUCJP_LATIN1,
  5260.     /* 0x15 */    EUCJP_LATIN1,
  5261.     /* 0x16 */    EUCJP_LATIN1,
  5262.     /* 0x17 */    EUCJP_LATIN1,
  5263.     /* 0x18 */    EUCJP_LATIN1,
  5264.     /* 0x19 */    EUCJP_LATIN1,
  5265.     /* 0x1a */    EUCJP_LATIN1,
  5266.     /* 0x1b */    EUCJP_LATIN1,
  5267.     /* 0x1c */    EUCJP_LATIN1,
  5268.     /* 0x1d */    EUCJP_LATIN1,
  5269.     /* 0x1e */    EUCJP_LATIN1,
  5270.     /* 0x1f */    EUCJP_LATIN1,
  5271.     /* 0x20 */    EUCJP_LATIN1,
  5272.     /* 0x21 */    EUCJP_LATIN1,
  5273.     /* 0x22 */    EUCJP_LATIN1,
  5274.     /* 0x23 */    EUCJP_LATIN1,
  5275.     /* 0x24 */    EUCJP_LATIN1,
  5276.     /* 0x25 */    EUCJP_LATIN1,
  5277.     /* 0x26 */    EUCJP_LATIN1,
  5278.     /* 0x27 */    EUCJP_LATIN1,
  5279.     /* 0x28 */    EUCJP_LATIN1,
  5280.     /* 0x29 */    EUCJP_LATIN1,
  5281.     /* 0x2a */    EUCJP_LATIN1,
  5282.     /* 0x2b */    EUCJP_LATIN1,
  5283.     /* 0x2c */    EUCJP_LATIN1,
  5284.     /* 0x2d */    EUCJP_LATIN1,
  5285.     /* 0x2e */    EUCJP_LATIN1,
  5286.     /* 0x2f */    EUCJP_LATIN1,
  5287.     /* 0x30 */    EUCJP_LATIN1,
  5288.     /* 0x31 */    EUCJP_LATIN1,
  5289.     /* 0x32 */    EUCJP_LATIN1,
  5290.     /* 0x33 */    EUCJP_LATIN1,
  5291.     /* 0x34 */    EUCJP_LATIN1,
  5292.     /* 0x35 */    EUCJP_LATIN1,
  5293.     /* 0x36 */    EUCJP_LATIN1,
  5294.     /* 0x37 */    EUCJP_LATIN1,
  5295.     /* 0x38 */    EUCJP_LATIN1,
  5296.     /* 0x39 */    EUCJP_LATIN1,
  5297.     /* 0x3a */    EUCJP_LATIN1,
  5298.     /* 0x3b */    EUCJP_LATIN1,
  5299.     /* 0x3c */    EUCJP_LATIN1,
  5300.     /* 0x3d */    EUCJP_LATIN1,
  5301.     /* 0x3e */    EUCJP_LATIN1,
  5302.     /* 0x3f */    EUCJP_LATIN1,
  5303.     /* 0x40 */    EUCJP_LATIN1,
  5304.     /* 0x41 */    EUCJP_LATIN1,
  5305.     /* 0x42 */    EUCJP_LATIN1,
  5306.     /* 0x43 */    EUCJP_LATIN1,
  5307.     /* 0x44 */    EUCJP_LATIN1,
  5308.     /* 0x45 */    EUCJP_LATIN1,
  5309.     /* 0x46 */    EUCJP_LATIN1,
  5310.     /* 0x47 */    EUCJP_LATIN1,
  5311.     /* 0x48 */    EUCJP_LATIN1,
  5312.     /* 0x49 */    EUCJP_LATIN1,
  5313.     /* 0x4a */    EUCJP_LATIN1,
  5314.     /* 0x4b */    EUCJP_LATIN1,
  5315.     /* 0x4c */    EUCJP_LATIN1,
  5316.     /* 0x4d */    EUCJP_LATIN1,
  5317.     /* 0x4e */    EUCJP_LATIN1,
  5318.     /* 0x4f */    EUCJP_LATIN1,
  5319.     /* 0x50 */    EUCJP_LATIN1,
  5320.     /* 0x51 */    EUCJP_LATIN1,
  5321.     /* 0x52 */    EUCJP_LATIN1,
  5322.     /* 0x53 */    EUCJP_LATIN1,
  5323.     /* 0x54 */    EUCJP_LATIN1,
  5324.     /* 0x55 */    EUCJP_LATIN1,
  5325.     /* 0x56 */    EUCJP_LATIN1,
  5326.     /* 0x57 */    EUCJP_LATIN1,
  5327.     /* 0x58 */    EUCJP_LATIN1,
  5328.     /* 0x59 */    EUCJP_LATIN1,
  5329.     /* 0x5a */    EUCJP_LATIN1,
  5330.     /* 0x5b */    EUCJP_LATIN1,
  5331.     /* 0x5c */    EUCJP_LATIN1,
  5332.     /* 0x5d */    EUCJP_LATIN1,
  5333.     /* 0x5e */    EUCJP_LATIN1,
  5334.     /* 0x5f */    EUCJP_LATIN1,
  5335.     /* 0x60 */    EUCJP_LATIN1,
  5336.     /* 0x61 */    EUCJP_LATIN1,
  5337.     /* 0x62 */    EUCJP_LATIN1,
  5338.     /* 0x63 */    EUCJP_LATIN1,
  5339.     /* 0x64 */    EUCJP_LATIN1,
  5340.     /* 0x65 */    EUCJP_LATIN1,
  5341.     /* 0x66 */    EUCJP_LATIN1,
  5342.     /* 0x67 */    EUCJP_LATIN1,
  5343.     /* 0x68 */    EUCJP_LATIN1,
  5344.     /* 0x69 */    EUCJP_LATIN1,
  5345.     /* 0x6a */    EUCJP_LATIN1,
  5346.     /* 0x6b */    EUCJP_LATIN1,
  5347.     /* 0x6c */    EUCJP_LATIN1,
  5348.     /* 0x6d */    EUCJP_LATIN1,
  5349.     /* 0x6e */    EUCJP_LATIN1,
  5350.     /* 0x6f */    EUCJP_LATIN1,
  5351.     /* 0x70 */    EUCJP_LATIN1,
  5352.     /* 0x71 */    EUCJP_LATIN1,
  5353.     /* 0x72 */    EUCJP_LATIN1,
  5354.     /* 0x73 */    EUCJP_LATIN1,
  5355.     /* 0x74 */    EUCJP_LATIN1,
  5356.     /* 0x75 */    EUCJP_LATIN1,
  5357.     /* 0x76 */    EUCJP_LATIN1,
  5358.     /* 0x77 */    EUCJP_LATIN1,
  5359.     /* 0x78 */    EUCJP_LATIN1,
  5360.     /* 0x79 */    EUCJP_LATIN1,
  5361.     /* 0x7a */    EUCJP_LATIN1,
  5362.     /* 0x7b */    EUCJP_LATIN1,
  5363.     /* 0x7c */    EUCJP_LATIN1,
  5364.     /* 0x7d */    EUCJP_LATIN1,
  5365.     /* 0x7e */    EUCJP_LATIN1,
  5366.     /* 0x7f */    EUCJP_LATIN1,
  5367.     /* 0x80 */    EUCJP_LATIN1,
  5368.     /* 0x81 */    EUCJP_LATIN1,
  5369.     /* 0x82 */    EUCJP_LATIN1,
  5370.     /* 0x83 */    EUCJP_LATIN1,
  5371.     /* 0x84 */    EUCJP_LATIN1,
  5372.     /* 0x85 */    EUCJP_LATIN1,
  5373.     /* 0x86 */    EUCJP_LATIN1,
  5374.     /* 0x87 */    EUCJP_LATIN1,
  5375.     /* 0x88 */    EUCJP_LATIN1,
  5376.     /* 0x89 */    EUCJP_LATIN1,
  5377.     /* 0x8a */    EUCJP_LATIN1,
  5378.     /* 0x8b */    EUCJP_LATIN1,
  5379.     /* 0x8c */    EUCJP_LATIN1,
  5380.     /* 0x8d */    EUCJP_LATIN1,
  5381.     /* 0x8e */    EUCJP_JISX0201,
  5382.     /* 0x8f */    EUCJP_JISX0212,
  5383.     /* 0x90 */    EUCJP_LATIN1,
  5384.     /* 0x91 */    EUCJP_LATIN1,
  5385.     /* 0x92 */    EUCJP_LATIN1,
  5386.     /* 0x93 */    EUCJP_LATIN1,
  5387.     /* 0x94 */    EUCJP_LATIN1,
  5388.     /* 0x95 */    EUCJP_LATIN1,
  5389.     /* 0x96 */    EUCJP_LATIN1,
  5390.     /* 0x97 */    EUCJP_LATIN1,
  5391.     /* 0x98 */    EUCJP_LATIN1,
  5392.     /* 0x99 */    EUCJP_LATIN1,
  5393.     /* 0x9a */    EUCJP_LATIN1,
  5394.     /* 0x9b */    EUCJP_LATIN1,
  5395.     /* 0x9c */    EUCJP_LATIN1,
  5396.     /* 0x9d */    EUCJP_LATIN1,
  5397.     /* 0x9e */    EUCJP_LATIN1,
  5398.     /* 0x9f */    EUCJP_LATIN1,
  5399.     /* 0xa0 */    EUCJP_LATIN1,
  5400.     /* 0xa1 */    EUCJP_JISX0208,
  5401.     /* 0xa2 */    EUCJP_JISX0208,
  5402.     /* 0xa3 */    EUCJP_JISX0208,
  5403.     /* 0xa4 */    EUCJP_JISX0208,
  5404.     /* 0xa5 */    EUCJP_JISX0208,
  5405.     /* 0xa6 */    EUCJP_JISX0208,
  5406.     /* 0xa7 */    EUCJP_JISX0208,
  5407.     /* 0xa8 */    EUCJP_JISX0208,
  5408.     /* 0xa9 */    EUCJP_JISX0208,
  5409.     /* 0xaa */    EUCJP_JISX0208,
  5410.     /* 0xab */    EUCJP_JISX0208,
  5411.     /* 0xac */    EUCJP_JISX0208,
  5412.     /* 0xad */    EUCJP_JISX0208,
  5413.     /* 0xae */    EUCJP_JISX0208,
  5414.     /* 0xaf */    EUCJP_JISX0208,
  5415.     /* 0xb0 */    EUCJP_JISX0208,
  5416.     /* 0xb1 */    EUCJP_JISX0208,
  5417.     /* 0xb2 */    EUCJP_JISX0208,
  5418.     /* 0xb3 */    EUCJP_JISX0208,
  5419.     /* 0xb4 */    EUCJP_JISX0208,
  5420.     /* 0xb5 */    EUCJP_JISX0208,
  5421.     /* 0xb6 */    EUCJP_JISX0208,
  5422.     /* 0xb7 */    EUCJP_JISX0208,
  5423.     /* 0xb8 */    EUCJP_JISX0208,
  5424.     /* 0xb9 */    EUCJP_JISX0208,
  5425.     /* 0xba */    EUCJP_JISX0208,
  5426.     /* 0xbb */    EUCJP_JISX0208,
  5427.     /* 0xbc */    EUCJP_JISX0208,
  5428.     /* 0xbd */    EUCJP_JISX0208,
  5429.     /* 0xbe */    EUCJP_JISX0208,
  5430.     /* 0xbf */    EUCJP_JISX0208,
  5431.     /* 0xc0 */    EUCJP_JISX0208,
  5432.     /* 0xc1 */    EUCJP_JISX0208,
  5433.     /* 0xc2 */    EUCJP_JISX0208,
  5434.     /* 0xc3 */    EUCJP_JISX0208,
  5435.     /* 0xc4 */    EUCJP_JISX0208,
  5436.     /* 0xc5 */    EUCJP_JISX0208,
  5437.     /* 0xc6 */    EUCJP_JISX0208,
  5438.     /* 0xc7 */    EUCJP_JISX0208,
  5439.     /* 0xc8 */    EUCJP_JISX0208,
  5440.     /* 0xc9 */    EUCJP_JISX0208,
  5441.     /* 0xca */    EUCJP_JISX0208,
  5442.     /* 0xcb */    EUCJP_JISX0208,
  5443.     /* 0xcc */    EUCJP_JISX0208,
  5444.     /* 0xcd */    EUCJP_JISX0208,
  5445.     /* 0xce */    EUCJP_JISX0208,
  5446.     /* 0xcf */    EUCJP_JISX0208,
  5447.     /* 0xd0 */    EUCJP_JISX0208,
  5448.     /* 0xd1 */    EUCJP_JISX0208,
  5449.     /* 0xd2 */    EUCJP_JISX0208,
  5450.     /* 0xd3 */    EUCJP_JISX0208,
  5451.     /* 0xd4 */    EUCJP_JISX0208,
  5452.     /* 0xd5 */    EUCJP_JISX0208,
  5453.     /* 0xd6 */    EUCJP_JISX0208,
  5454.     /* 0xd7 */    EUCJP_JISX0208,
  5455.     /* 0xd8 */    EUCJP_JISX0208,
  5456.     /* 0xd9 */    EUCJP_JISX0208,
  5457.     /* 0xda */    EUCJP_JISX0208,
  5458.     /* 0xdb */    EUCJP_JISX0208,
  5459.     /* 0xdc */    EUCJP_JISX0208,
  5460.     /* 0xdd */    EUCJP_JISX0208,
  5461.     /* 0xde */    EUCJP_JISX0208,
  5462.     /* 0xdf */    EUCJP_JISX0208,
  5463.     /* 0xe0 */    EUCJP_JISX0208,
  5464.     /* 0xe1 */    EUCJP_JISX0208,
  5465.     /* 0xe2 */    EUCJP_JISX0208,
  5466.     /* 0xe3 */    EUCJP_JISX0208,
  5467.     /* 0xe4 */    EUCJP_JISX0208,
  5468.     /* 0xe5 */    EUCJP_JISX0208,
  5469.     /* 0xe6 */    EUCJP_JISX0208,
  5470.     /* 0xe7 */    EUCJP_JISX0208,
  5471.     /* 0xe8 */    EUCJP_JISX0208,
  5472.     /* 0xe9 */    EUCJP_JISX0208,
  5473.     /* 0xea */    EUCJP_JISX0208,
  5474.     /* 0xeb */    EUCJP_JISX0208,
  5475.     /* 0xec */    EUCJP_JISX0208,
  5476.     /* 0xed */    EUCJP_JISX0208,
  5477.     /* 0xee */    EUCJP_JISX0208,
  5478.     /* 0xef */    EUCJP_JISX0208,
  5479.     /* 0xf0 */    EUCJP_JISX0208,
  5480.     /* 0xf1 */    EUCJP_JISX0208,
  5481.     /* 0xf2 */    EUCJP_JISX0208,
  5482.     /* 0xf3 */    EUCJP_JISX0208,
  5483.     /* 0xf4 */    EUCJP_JISX0208,
  5484.     /* 0xf5 */    EUCJP_JISX0208,
  5485.     /* 0xf6 */    EUCJP_JISX0208,
  5486.     /* 0xf7 */    EUCJP_JISX0208,
  5487.     /* 0xf8 */    EUCJP_JISX0208,
  5488.     /* 0xf9 */    EUCJP_JISX0208,
  5489.     /* 0xfa */    EUCJP_JISX0208,
  5490.     /* 0xfb */    EUCJP_JISX0208,
  5491.     /* 0xfc */    EUCJP_JISX0208,
  5492.     /* 0xfd */    EUCJP_JISX0208,
  5493.     /* 0xfe */    EUCJP_JISX0208,
  5494.     /* 0xff */    EUCJP_LATIN1,
  5495. };
  5496.  
  5497.  
  5498. static XP_Bool
  5499. fe_AreEUCJPFontsAvail(int16 win_csid)
  5500. {
  5501.     /* this needs to match the code in fe_LoadEUCJPFont */
  5502.     if ((fe_FontCharSets[CS_JISX0208 & 0xff].name == NULL)
  5503.         && (fe_FontCharSets[CS_JISX0208_11 & 0xff].name == NULL))
  5504.         return FALSE;
  5505.     else
  5506.         return TRUE;
  5507. }
  5508.  
  5509. static fe_Font
  5510. fe_LoadEUCJPFont(MWContext *context, char *familyName, int points,
  5511.                  int sizeNum, int fontmask, int charset, int pitch,
  5512.                  int faceNum, Display *dpy)
  5513. {
  5514.     int16            cs;
  5515.     int            len;
  5516.     fe_FontGroupFont    *ret;
  5517.  
  5518.     len = (4 * sizeof(fe_FontGroupFont));
  5519.     ret = calloc(1, len);
  5520.     if (!ret)
  5521.     {
  5522.         return NULL;
  5523.     }
  5524.     (void) memset(ret, 0, len);
  5525.  
  5526.     /* this needs to match the code in fe_AreEUCJPFontsAvail */
  5527.     cs = CS_LATIN1;
  5528.     ret[0].xFont = (XFontStruct *)
  5529.             fe_LoadFont(context, &cs, familyName, points, sizeNum, fontmask);
  5530.     if (cs != CS_LATIN1)
  5531.     {
  5532.         XP_FREE(ret);
  5533.         return NULL;
  5534.     }
  5535.  
  5536.     cs = CS_JISX0208;
  5537.     ret[1].xFont = (XFontStruct *)
  5538.             fe_LoadFont(context, &cs, familyName, points, sizeNum, fontmask);
  5539.     if (cs == CS_JISX0208)
  5540.     {
  5541.         ret[1].mask1 = 0x7f;
  5542.         ret[1].mask2 = 0x7f;
  5543.     }
  5544.     else
  5545.     {
  5546.         cs = CS_JISX0208_11;
  5547.         ret[1].xFont = (XFontStruct *)
  5548.                     fe_LoadFont(context, &cs, familyName, points, sizeNum,
  5549.                                 fontmask);
  5550.         if (cs == CS_JISX0208_11)
  5551.         {
  5552.             ret[1].mask1 = 0xff;
  5553.             ret[1].mask2 = 0xff;
  5554.         }
  5555.         else
  5556.         {
  5557.             XP_FREE(ret);
  5558.             return NULL;
  5559.         }
  5560.     }
  5561.  
  5562.     cs = CS_JISX0201;
  5563.     ret[2].xFont = (XFontStruct *)
  5564.             fe_LoadFont(context, &cs, familyName, points, sizeNum, fontmask);
  5565.     if (cs != CS_JISX0201)
  5566.     {
  5567.         ret[2].xFont = NULL;
  5568.     }
  5569.  
  5570.     cs = CS_JISX0212;
  5571.     ret[3].xFont = (XFontStruct *)
  5572.             fe_LoadFont(context, &cs, familyName, points, sizeNum, fontmask);
  5573.     if (cs == CS_JISX0212)
  5574.     {
  5575.         ret[3].mask1 = 0x7f;
  5576.         ret[3].mask2 = 0x7f;
  5577.     }
  5578.     else
  5579.     {
  5580.         ret[3].xFont = NULL;
  5581.     }
  5582.  
  5583.     return (fe_Font) ret;
  5584. }
  5585.  
  5586.  
  5587. static void
  5588. fe_EUCJPTextExtents(fe_Font font, char *string, int len, int *direction,
  5589.     int *fontAscent, int *fontDescent, XCharStruct *overall)
  5590. {
  5591.     fe_ProcessEUCString(CS_EUCJP, EUCJPTable, 
  5592.         NULL, 
  5593.         NULL,
  5594.         NULL, None, font, NULL, 0, 0, string, len,
  5595.         fontAscent, fontDescent, overall,
  5596.         fe_CharSetFuncsArray[FE_FONT_INFO_EUCJP].numberOfFonts);
  5597. }
  5598.  
  5599.  
  5600. static void
  5601. fe_DrawEUCJPString(Display *dpy, Drawable d, fe_Font font, GC gc, int x,
  5602.     int y, char *string, int len)
  5603. {
  5604.     fe_ProcessEUCString(CS_EUCJP, EUCJPTable, 
  5605.         (fe_XDrawStringFunc) XDrawString, 
  5606.         (fe_XDrawStringFunc) XDrawString16,
  5607.         dpy, d, font, gc, x, y, string, len,
  5608.         NULL, NULL, NULL,
  5609.         0);
  5610. }
  5611.  
  5612.  
  5613. static void
  5614. fe_DrawEUCJPImageString(Display *dpy, Drawable d, fe_Font font, GC gc, GC gc2,
  5615.     int x, int y, char *string, int len)
  5616. {
  5617.     fe_ProcessEUCString(CS_EUCJP, EUCJPTable, 
  5618.         (fe_XDrawStringFunc) XDrawImageString,
  5619.         (fe_XDrawStringFunc) XDrawImageString16,
  5620.         dpy, d, font, gc, x, y, string, len,
  5621.         NULL, NULL, NULL,
  5622.         0);
  5623. }
  5624.  
  5625.  
  5626.             /*    fontIndex    skip    len    */
  5627. #define EUCKR_LATIN1    {    0,        0,    1    }
  5628. #define EUCKR_KSC5601    {    1,        0,    2    }
  5629.  
  5630. static fe_StringProcessTable EUCKRTable[] =
  5631. {
  5632.     /* 0x00 */    EUCKR_LATIN1,
  5633.     /* 0x01 */    EUCKR_LATIN1,
  5634.     /* 0x02 */    EUCKR_LATIN1,
  5635.     /* 0x03 */    EUCKR_LATIN1,
  5636.     /* 0x04 */    EUCKR_LATIN1,
  5637.     /* 0x05 */    EUCKR_LATIN1,
  5638.     /* 0x06 */    EUCKR_LATIN1,
  5639.     /* 0x07 */    EUCKR_LATIN1,
  5640.     /* 0x08 */    EUCKR_LATIN1,
  5641.     /* 0x09 */    EUCKR_LATIN1,
  5642.     /* 0x0a */    EUCKR_LATIN1,
  5643.     /* 0x0b */    EUCKR_LATIN1,
  5644.     /* 0x0c */    EUCKR_LATIN1,
  5645.     /* 0x0d */    EUCKR_LATIN1,
  5646.     /* 0x0e */    EUCKR_LATIN1,
  5647.     /* 0x0f */    EUCKR_LATIN1,
  5648.     /* 0x10 */    EUCKR_LATIN1,
  5649.     /* 0x11 */    EUCKR_LATIN1,
  5650.     /* 0x12 */    EUCKR_LATIN1,
  5651.     /* 0x13 */    EUCKR_LATIN1,
  5652.     /* 0x14 */    EUCKR_LATIN1,
  5653.     /* 0x15 */    EUCKR_LATIN1,
  5654.     /* 0x16 */    EUCKR_LATIN1,
  5655.     /* 0x17 */    EUCKR_LATIN1,
  5656.     /* 0x18 */    EUCKR_LATIN1,
  5657.     /* 0x19 */    EUCKR_LATIN1,
  5658.     /* 0x1a */    EUCKR_LATIN1,
  5659.     /* 0x1b */    EUCKR_LATIN1,
  5660.     /* 0x1c */    EUCKR_LATIN1,
  5661.     /* 0x1d */    EUCKR_LATIN1,
  5662.     /* 0x1e */    EUCKR_LATIN1,
  5663.     /* 0x1f */    EUCKR_LATIN1,
  5664.     /* 0x20 */    EUCKR_LATIN1,
  5665.     /* 0x21 */    EUCKR_LATIN1,
  5666.     /* 0x22 */    EUCKR_LATIN1,
  5667.     /* 0x23 */    EUCKR_LATIN1,
  5668.     /* 0x24 */    EUCKR_LATIN1,
  5669.     /* 0x25 */    EUCKR_LATIN1,
  5670.     /* 0x26 */    EUCKR_LATIN1,
  5671.     /* 0x27 */    EUCKR_LATIN1,
  5672.     /* 0x28 */    EUCKR_LATIN1,
  5673.     /* 0x29 */    EUCKR_LATIN1,
  5674.     /* 0x2a */    EUCKR_LATIN1,
  5675.     /* 0x2b */    EUCKR_LATIN1,
  5676.     /* 0x2c */    EUCKR_LATIN1,
  5677.     /* 0x2d */    EUCKR_LATIN1,
  5678.     /* 0x2e */    EUCKR_LATIN1,
  5679.     /* 0x2f */    EUCKR_LATIN1,
  5680.     /* 0x30 */    EUCKR_LATIN1,
  5681.     /* 0x31 */    EUCKR_LATIN1,
  5682.     /* 0x32 */    EUCKR_LATIN1,
  5683.     /* 0x33 */    EUCKR_LATIN1,
  5684.     /* 0x34 */    EUCKR_LATIN1,
  5685.     /* 0x35 */    EUCKR_LATIN1,
  5686.     /* 0x36 */    EUCKR_LATIN1,
  5687.     /* 0x37 */    EUCKR_LATIN1,
  5688.     /* 0x38 */    EUCKR_LATIN1,
  5689.     /* 0x39 */    EUCKR_LATIN1,
  5690.     /* 0x3a */    EUCKR_LATIN1,
  5691.     /* 0x3b */    EUCKR_LATIN1,
  5692.     /* 0x3c */    EUCKR_LATIN1,
  5693.     /* 0x3d */    EUCKR_LATIN1,
  5694.     /* 0x3e */    EUCKR_LATIN1,
  5695.     /* 0x3f */    EUCKR_LATIN1,
  5696.     /* 0x40 */    EUCKR_LATIN1,
  5697.     /* 0x41 */    EUCKR_LATIN1,
  5698.     /* 0x42 */    EUCKR_LATIN1,
  5699.     /* 0x43 */    EUCKR_LATIN1,
  5700.     /* 0x44 */    EUCKR_LATIN1,
  5701.     /* 0x45 */    EUCKR_LATIN1,
  5702.     /* 0x46 */    EUCKR_LATIN1,
  5703.     /* 0x47 */    EUCKR_LATIN1,
  5704.     /* 0x48 */    EUCKR_LATIN1,
  5705.     /* 0x49 */    EUCKR_LATIN1,
  5706.     /* 0x4a */    EUCKR_LATIN1,
  5707.     /* 0x4b */    EUCKR_LATIN1,
  5708.     /* 0x4c */    EUCKR_LATIN1,
  5709.     /* 0x4d */    EUCKR_LATIN1,
  5710.     /* 0x4e */    EUCKR_LATIN1,
  5711.     /* 0x4f */    EUCKR_LATIN1,
  5712.     /* 0x50 */    EUCKR_LATIN1,
  5713.     /* 0x51 */    EUCKR_LATIN1,
  5714.     /* 0x52 */    EUCKR_LATIN1,
  5715.     /* 0x53 */    EUCKR_LATIN1,
  5716.     /* 0x54 */    EUCKR_LATIN1,
  5717.     /* 0x55 */    EUCKR_LATIN1,
  5718.     /* 0x56 */    EUCKR_LATIN1,
  5719.     /* 0x57 */    EUCKR_LATIN1,
  5720.     /* 0x58 */    EUCKR_LATIN1,
  5721.     /* 0x59 */    EUCKR_LATIN1,
  5722.     /* 0x5a */    EUCKR_LATIN1,
  5723.     /* 0x5b */    EUCKR_LATIN1,
  5724.     /* 0x5c */    EUCKR_LATIN1,
  5725.     /* 0x5d */    EUCKR_LATIN1,
  5726.     /* 0x5e */    EUCKR_LATIN1,
  5727.     /* 0x5f */    EUCKR_LATIN1,
  5728.     /* 0x60 */    EUCKR_LATIN1,
  5729.     /* 0x61 */    EUCKR_LATIN1,
  5730.     /* 0x62 */    EUCKR_LATIN1,
  5731.     /* 0x63 */    EUCKR_LATIN1,
  5732.     /* 0x64 */    EUCKR_LATIN1,
  5733.     /* 0x65 */    EUCKR_LATIN1,
  5734.     /* 0x66 */    EUCKR_LATIN1,
  5735.     /* 0x67 */    EUCKR_LATIN1,
  5736.     /* 0x68 */    EUCKR_LATIN1,
  5737.     /* 0x69 */    EUCKR_LATIN1,
  5738.     /* 0x6a */    EUCKR_LATIN1,
  5739.     /* 0x6b */    EUCKR_LATIN1,
  5740.     /* 0x6c */    EUCKR_LATIN1,
  5741.     /* 0x6d */    EUCKR_LATIN1,
  5742.     /* 0x6e */    EUCKR_LATIN1,
  5743.     /* 0x6f */    EUCKR_LATIN1,
  5744.     /* 0x70 */    EUCKR_LATIN1,
  5745.     /* 0x71 */    EUCKR_LATIN1,
  5746.     /* 0x72 */    EUCKR_LATIN1,
  5747.     /* 0x73 */    EUCKR_LATIN1,
  5748.     /* 0x74 */    EUCKR_LATIN1,
  5749.     /* 0x75 */    EUCKR_LATIN1,
  5750.     /* 0x76 */    EUCKR_LATIN1,
  5751.     /* 0x77 */    EUCKR_LATIN1,
  5752.     /* 0x78 */    EUCKR_LATIN1,
  5753.     /* 0x79 */    EUCKR_LATIN1,
  5754.     /* 0x7a */    EUCKR_LATIN1,
  5755.     /* 0x7b */    EUCKR_LATIN1,
  5756.     /* 0x7c */    EUCKR_LATIN1,
  5757.     /* 0x7d */    EUCKR_LATIN1,
  5758.     /* 0x7e */    EUCKR_LATIN1,
  5759.     /* 0x7f */    EUCKR_LATIN1,
  5760.     /* 0x80 */    EUCKR_LATIN1,
  5761.     /* 0x81 */    EUCKR_LATIN1,
  5762.     /* 0x82 */    EUCKR_LATIN1,
  5763.     /* 0x83 */    EUCKR_LATIN1,
  5764.     /* 0x84 */    EUCKR_LATIN1,
  5765.     /* 0x85 */    EUCKR_LATIN1,
  5766.     /* 0x86 */    EUCKR_LATIN1,
  5767.     /* 0x87 */    EUCKR_LATIN1,
  5768.     /* 0x88 */    EUCKR_LATIN1,
  5769.     /* 0x89 */    EUCKR_LATIN1,
  5770.     /* 0x8a */    EUCKR_LATIN1,
  5771.     /* 0x8b */    EUCKR_LATIN1,
  5772.     /* 0x8c */    EUCKR_LATIN1,
  5773.     /* 0x8d */    EUCKR_LATIN1,
  5774.     /* 0x8e */    EUCKR_LATIN1,
  5775.     /* 0x8f */    EUCKR_LATIN1,
  5776.     /* 0x90 */    EUCKR_LATIN1,
  5777.     /* 0x91 */    EUCKR_LATIN1,
  5778.     /* 0x92 */    EUCKR_LATIN1,
  5779.     /* 0x93 */    EUCKR_LATIN1,
  5780.     /* 0x94 */    EUCKR_LATIN1,
  5781.     /* 0x95 */    EUCKR_LATIN1,
  5782.     /* 0x96 */    EUCKR_LATIN1,
  5783.     /* 0x97 */    EUCKR_LATIN1,
  5784.     /* 0x98 */    EUCKR_LATIN1,
  5785.     /* 0x99 */    EUCKR_LATIN1,
  5786.     /* 0x9a */    EUCKR_LATIN1,
  5787.     /* 0x9b */    EUCKR_LATIN1,
  5788.     /* 0x9c */    EUCKR_LATIN1,
  5789.     /* 0x9d */    EUCKR_LATIN1,
  5790.     /* 0x9e */    EUCKR_LATIN1,
  5791.     /* 0x9f */    EUCKR_LATIN1,
  5792.     /* 0xa0 */    EUCKR_LATIN1,
  5793.     /* 0xa1 */    EUCKR_KSC5601,
  5794.     /* 0xa2 */    EUCKR_KSC5601,
  5795.     /* 0xa3 */    EUCKR_KSC5601,
  5796.     /* 0xa4 */    EUCKR_KSC5601,
  5797.     /* 0xa5 */    EUCKR_KSC5601,
  5798.     /* 0xa6 */    EUCKR_KSC5601,
  5799.     /* 0xa7 */    EUCKR_KSC5601,
  5800.     /* 0xa8 */    EUCKR_KSC5601,
  5801.     /* 0xa9 */    EUCKR_KSC5601,
  5802.     /* 0xaa */    EUCKR_KSC5601,
  5803.     /* 0xab */    EUCKR_KSC5601,
  5804.     /* 0xac */    EUCKR_KSC5601,
  5805.     /* 0xad */    EUCKR_KSC5601,
  5806.     /* 0xae */    EUCKR_KSC5601,
  5807.     /* 0xaf */    EUCKR_KSC5601,
  5808.     /* 0xb0 */    EUCKR_KSC5601,
  5809.     /* 0xb1 */    EUCKR_KSC5601,
  5810.     /* 0xb2 */    EUCKR_KSC5601,
  5811.     /* 0xb3 */    EUCKR_KSC5601,
  5812.     /* 0xb4 */    EUCKR_KSC5601,
  5813.     /* 0xb5 */    EUCKR_KSC5601,
  5814.     /* 0xb6 */    EUCKR_KSC5601,
  5815.     /* 0xb7 */    EUCKR_KSC5601,
  5816.     /* 0xb8 */    EUCKR_KSC5601,
  5817.     /* 0xb9 */    EUCKR_KSC5601,
  5818.     /* 0xba */    EUCKR_KSC5601,
  5819.     /* 0xbb */    EUCKR_KSC5601,
  5820.     /* 0xbc */    EUCKR_KSC5601,
  5821.     /* 0xbd */    EUCKR_KSC5601,
  5822.     /* 0xbe */    EUCKR_KSC5601,
  5823.     /* 0xbf */    EUCKR_KSC5601,
  5824.     /* 0xc0 */    EUCKR_KSC5601,
  5825.     /* 0xc1 */    EUCKR_KSC5601,
  5826.     /* 0xc2 */    EUCKR_KSC5601,
  5827.     /* 0xc3 */    EUCKR_KSC5601,
  5828.     /* 0xc4 */    EUCKR_KSC5601,
  5829.     /* 0xc5 */    EUCKR_KSC5601,
  5830.     /* 0xc6 */    EUCKR_KSC5601,
  5831.     /* 0xc7 */    EUCKR_KSC5601,
  5832.     /* 0xc8 */    EUCKR_KSC5601,
  5833.     /* 0xc9 */    EUCKR_KSC5601,
  5834.     /* 0xca */    EUCKR_KSC5601,
  5835.     /* 0xcb */    EUCKR_KSC5601,
  5836.     /* 0xcc */    EUCKR_KSC5601,
  5837.     /* 0xcd */    EUCKR_KSC5601,
  5838.     /* 0xce */    EUCKR_KSC5601,
  5839.     /* 0xcf */    EUCKR_KSC5601,
  5840.     /* 0xd0 */    EUCKR_KSC5601,
  5841.     /* 0xd1 */    EUCKR_KSC5601,
  5842.     /* 0xd2 */    EUCKR_KSC5601,
  5843.     /* 0xd3 */    EUCKR_KSC5601,
  5844.     /* 0xd4 */    EUCKR_KSC5601,
  5845.     /* 0xd5 */    EUCKR_KSC5601,
  5846.     /* 0xd6 */    EUCKR_KSC5601,
  5847.     /* 0xd7 */    EUCKR_KSC5601,
  5848.     /* 0xd8 */    EUCKR_KSC5601,
  5849.     /* 0xd9 */    EUCKR_KSC5601,
  5850.     /* 0xda */    EUCKR_KSC5601,
  5851.     /* 0xdb */    EUCKR_KSC5601,
  5852.     /* 0xdc */    EUCKR_KSC5601,
  5853.     /* 0xdd */    EUCKR_KSC5601,
  5854.     /* 0xde */    EUCKR_KSC5601,
  5855.     /* 0xdf */    EUCKR_KSC5601,
  5856.     /* 0xe0 */    EUCKR_KSC5601,
  5857.     /* 0xe1 */    EUCKR_KSC5601,
  5858.     /* 0xe2 */    EUCKR_KSC5601,
  5859.     /* 0xe3 */    EUCKR_KSC5601,
  5860.     /* 0xe4 */    EUCKR_KSC5601,
  5861.     /* 0xe5 */    EUCKR_KSC5601,
  5862.     /* 0xe6 */    EUCKR_KSC5601,
  5863.     /* 0xe7 */    EUCKR_KSC5601,
  5864.     /* 0xe8 */    EUCKR_KSC5601,
  5865.     /* 0xe9 */    EUCKR_KSC5601,
  5866.     /* 0xea */    EUCKR_KSC5601,
  5867.     /* 0xeb */    EUCKR_KSC5601,
  5868.     /* 0xec */    EUCKR_KSC5601,
  5869.     /* 0xed */    EUCKR_KSC5601,
  5870.     /* 0xee */    EUCKR_KSC5601,
  5871.     /* 0xef */    EUCKR_KSC5601,
  5872.     /* 0xf0 */    EUCKR_KSC5601,
  5873.     /* 0xf1 */    EUCKR_KSC5601,
  5874.     /* 0xf2 */    EUCKR_KSC5601,
  5875.     /* 0xf3 */    EUCKR_KSC5601,
  5876.     /* 0xf4 */    EUCKR_KSC5601,
  5877.     /* 0xf5 */    EUCKR_KSC5601,
  5878.     /* 0xf6 */    EUCKR_KSC5601,
  5879.     /* 0xf7 */    EUCKR_KSC5601,
  5880.     /* 0xf8 */    EUCKR_KSC5601,
  5881.     /* 0xf9 */    EUCKR_KSC5601,
  5882.     /* 0xfa */    EUCKR_KSC5601,
  5883.     /* 0xfb */    EUCKR_KSC5601,
  5884.     /* 0xfc */    EUCKR_KSC5601,
  5885.     /* 0xfd */    EUCKR_KSC5601,
  5886.     /* 0xfe */    EUCKR_KSC5601,
  5887.     /* 0xff */    EUCKR_LATIN1,
  5888. };
  5889.  
  5890.  
  5891. static XP_Bool
  5892. fe_AreEUCKRFontsAvail(int16 win_csid)
  5893. {
  5894.     /* this needs to match the code in fe_LoadEUCKRFont */
  5895.     if ((fe_FontCharSets[CS_KSC5601 & 0xff].name == NULL)
  5896.         && (fe_FontCharSets[CS_KSC5601_11 & 0xff].name == NULL))
  5897.         return FALSE;
  5898.     else
  5899.         return TRUE;
  5900. }
  5901.  
  5902. static fe_Font
  5903. fe_LoadEUCKRFont(MWContext *context, char *familyName, int points,
  5904.                  int sizeNum, int fontmask, int charset, int pitch,
  5905.                  int faceNum, Display *dpy)
  5906. {
  5907.     int16            cs;
  5908.     int            len;
  5909.     fe_FontGroupFont    *ret;
  5910.  
  5911.     len = (2 * sizeof(fe_FontGroupFont));
  5912.     ret = calloc(1, len);
  5913.     if (!ret)
  5914.     {
  5915.         return NULL;
  5916.     }
  5917.     (void) memset(ret, 0, len);
  5918.  
  5919.     cs = CS_LATIN1;
  5920.     ret[0].xFont = (XFontStruct *)
  5921.             fe_LoadFont(context, &cs, familyName, points, sizeNum, fontmask);
  5922.     if (cs != CS_LATIN1)
  5923.     {
  5924.         XP_FREE(ret);
  5925.         return NULL;
  5926.     }
  5927.  
  5928.     /* this needs to match the code in fe_AreEUCKRFontsAvail */
  5929.     cs = CS_KSC5601;
  5930.     ret[1].xFont = (XFontStruct *)
  5931.             fe_LoadFont(context, &cs, familyName, points, sizeNum, fontmask);
  5932.     if (cs == CS_KSC5601)
  5933.     {
  5934.         ret[1].mask1 = 0x7f;
  5935.         ret[1].mask2 = 0x7f;
  5936.     }
  5937.     else
  5938.     {
  5939.         cs = CS_KSC5601_11;
  5940.         ret[1].xFont = (XFontStruct *)
  5941.                     fe_LoadFont(context, &cs, familyName, points, sizeNum,
  5942.                                 fontmask);
  5943.         if (cs == CS_KSC5601_11)
  5944.         {
  5945.             ret[1].mask1 = 0xff;
  5946.             ret[1].mask2 = 0xff;
  5947.         }
  5948.         else
  5949.         {
  5950.             XP_FREE(ret);
  5951.             return NULL;
  5952.         }
  5953.     }
  5954.  
  5955.     return (fe_Font) ret;
  5956. }
  5957.  
  5958.  
  5959. static void
  5960. fe_EUCKRTextExtents(fe_Font font, char *string, int len, int *direction,
  5961.     int *fontAscent, int *fontDescent, XCharStruct *overall)
  5962. {
  5963.     fe_ProcessEUCString(CS_KSC_8BIT, EUCKRTable, 
  5964.         NULL, 
  5965.         NULL,
  5966.         NULL, None, font, NULL, 0, 0, string, len,
  5967.         fontAscent, fontDescent, overall,
  5968.         fe_CharSetFuncsArray[FE_FONT_INFO_EUCKR].numberOfFonts);
  5969. }
  5970.  
  5971.  
  5972. static void
  5973. fe_DrawEUCKRString(Display *dpy, Drawable d, fe_Font font, GC gc, int x,
  5974.     int y, char *string, int len)
  5975. {
  5976.     fe_ProcessEUCString(CS_KSC_8BIT, EUCKRTable, 
  5977.         (fe_XDrawStringFunc) XDrawString, 
  5978.         (fe_XDrawStringFunc) XDrawString16,
  5979.         dpy, d, font, gc, x, y, string, len,
  5980.         NULL, NULL, NULL,
  5981.         0);
  5982. }
  5983.  
  5984.  
  5985. static void
  5986. fe_DrawEUCKRImageString(Display *dpy, Drawable d, fe_Font font, GC gc, GC gc2,
  5987.     int x, int y, char *string, int len)
  5988. {
  5989.     fe_ProcessEUCString(CS_KSC_8BIT, EUCKRTable, 
  5990.         (fe_XDrawStringFunc) XDrawImageString,
  5991.         (fe_XDrawStringFunc) XDrawImageString16,
  5992.         dpy, d, font, gc, x, y, string, len,
  5993.         NULL, NULL, NULL,
  5994.         0);
  5995. }
  5996.  
  5997.  
  5998.                 /*    fontIndex    skip    len    */
  5999. #define EUCTW_LATIN1        {    0,        0,    1    }
  6000. #define EUCTW_CNS11643_1    {    1,        0,    2    }
  6001. #define EUCTW_CNS11643_2    {    2,        2,    2    }
  6002.  
  6003. static fe_StringProcessTable EUCTWTable[] =
  6004. {
  6005.     /* 0x00 */    EUCTW_LATIN1,
  6006.     /* 0x01 */    EUCTW_LATIN1,
  6007.     /* 0x02 */    EUCTW_LATIN1,
  6008.     /* 0x03 */    EUCTW_LATIN1,
  6009.     /* 0x04 */    EUCTW_LATIN1,
  6010.     /* 0x05 */    EUCTW_LATIN1,
  6011.     /* 0x06 */    EUCTW_LATIN1,
  6012.     /* 0x07 */    EUCTW_LATIN1,
  6013.     /* 0x08 */    EUCTW_LATIN1,
  6014.     /* 0x09 */    EUCTW_LATIN1,
  6015.     /* 0x0a */    EUCTW_LATIN1,
  6016.     /* 0x0b */    EUCTW_LATIN1,
  6017.     /* 0x0c */    EUCTW_LATIN1,
  6018.     /* 0x0d */    EUCTW_LATIN1,
  6019.     /* 0x0e */    EUCTW_LATIN1,
  6020.     /* 0x0f */    EUCTW_LATIN1,
  6021.     /* 0x10 */    EUCTW_LATIN1,
  6022.     /* 0x11 */    EUCTW_LATIN1,
  6023.     /* 0x12 */    EUCTW_LATIN1,
  6024.     /* 0x13 */    EUCTW_LATIN1,
  6025.     /* 0x14 */    EUCTW_LATIN1,
  6026.     /* 0x15 */    EUCTW_LATIN1,
  6027.     /* 0x16 */    EUCTW_LATIN1,
  6028.     /* 0x17 */    EUCTW_LATIN1,
  6029.     /* 0x18 */    EUCTW_LATIN1,
  6030.     /* 0x19 */    EUCTW_LATIN1,
  6031.     /* 0x1a */    EUCTW_LATIN1,
  6032.     /* 0x1b */    EUCTW_LATIN1,
  6033.     /* 0x1c */    EUCTW_LATIN1,
  6034.     /* 0x1d */    EUCTW_LATIN1,
  6035.     /* 0x1e */    EUCTW_LATIN1,
  6036.     /* 0x1f */    EUCTW_LATIN1,
  6037.     /* 0x20 */    EUCTW_LATIN1,
  6038.     /* 0x21 */    EUCTW_LATIN1,
  6039.     /* 0x22 */    EUCTW_LATIN1,
  6040.     /* 0x23 */    EUCTW_LATIN1,
  6041.     /* 0x24 */    EUCTW_LATIN1,
  6042.     /* 0x25 */    EUCTW_LATIN1,
  6043.     /* 0x26 */    EUCTW_LATIN1,
  6044.     /* 0x27 */    EUCTW_LATIN1,
  6045.     /* 0x28 */    EUCTW_LATIN1,
  6046.     /* 0x29 */    EUCTW_LATIN1,
  6047.     /* 0x2a */    EUCTW_LATIN1,
  6048.     /* 0x2b */    EUCTW_LATIN1,
  6049.     /* 0x2c */    EUCTW_LATIN1,
  6050.     /* 0x2d */    EUCTW_LATIN1,
  6051.     /* 0x2e */    EUCTW_LATIN1,
  6052.     /* 0x2f */    EUCTW_LATIN1,
  6053.     /* 0x30 */    EUCTW_LATIN1,
  6054.     /* 0x31 */    EUCTW_LATIN1,
  6055.     /* 0x32 */    EUCTW_LATIN1,
  6056.     /* 0x33 */    EUCTW_LATIN1,
  6057.     /* 0x34 */    EUCTW_LATIN1,
  6058.     /* 0x35 */    EUCTW_LATIN1,
  6059.     /* 0x36 */    EUCTW_LATIN1,
  6060.     /* 0x37 */    EUCTW_LATIN1,
  6061.     /* 0x38 */    EUCTW_LATIN1,
  6062.     /* 0x39 */    EUCTW_LATIN1,
  6063.     /* 0x3a */    EUCTW_LATIN1,
  6064.     /* 0x3b */    EUCTW_LATIN1,
  6065.     /* 0x3c */    EUCTW_LATIN1,
  6066.     /* 0x3d */    EUCTW_LATIN1,
  6067.     /* 0x3e */    EUCTW_LATIN1,
  6068.     /* 0x3f */    EUCTW_LATIN1,
  6069.     /* 0x40 */    EUCTW_LATIN1,
  6070.     /* 0x41 */    EUCTW_LATIN1,
  6071.     /* 0x42 */    EUCTW_LATIN1,
  6072.     /* 0x43 */    EUCTW_LATIN1,
  6073.     /* 0x44 */    EUCTW_LATIN1,
  6074.     /* 0x45 */    EUCTW_LATIN1,
  6075.     /* 0x46 */    EUCTW_LATIN1,
  6076.     /* 0x47 */    EUCTW_LATIN1,
  6077.     /* 0x48 */    EUCTW_LATIN1,
  6078.     /* 0x49 */    EUCTW_LATIN1,
  6079.     /* 0x4a */    EUCTW_LATIN1,
  6080.     /* 0x4b */    EUCTW_LATIN1,
  6081.     /* 0x4c */    EUCTW_LATIN1,
  6082.     /* 0x4d */    EUCTW_LATIN1,
  6083.     /* 0x4e */    EUCTW_LATIN1,
  6084.     /* 0x4f */    EUCTW_LATIN1,
  6085.     /* 0x50 */    EUCTW_LATIN1,
  6086.     /* 0x51 */    EUCTW_LATIN1,
  6087.     /* 0x52 */    EUCTW_LATIN1,
  6088.     /* 0x53 */    EUCTW_LATIN1,
  6089.     /* 0x54 */    EUCTW_LATIN1,
  6090.     /* 0x55 */    EUCTW_LATIN1,
  6091.     /* 0x56 */    EUCTW_LATIN1,
  6092.     /* 0x57 */    EUCTW_LATIN1,
  6093.     /* 0x58 */    EUCTW_LATIN1,
  6094.     /* 0x59 */    EUCTW_LATIN1,
  6095.     /* 0x5a */    EUCTW_LATIN1,
  6096.     /* 0x5b */    EUCTW_LATIN1,
  6097.     /* 0x5c */    EUCTW_LATIN1,
  6098.     /* 0x5d */    EUCTW_LATIN1,
  6099.     /* 0x5e */    EUCTW_LATIN1,
  6100.     /* 0x5f */    EUCTW_LATIN1,
  6101.     /* 0x60 */    EUCTW_LATIN1,
  6102.     /* 0x61 */    EUCTW_LATIN1,
  6103.     /* 0x62 */    EUCTW_LATIN1,
  6104.     /* 0x63 */    EUCTW_LATIN1,
  6105.     /* 0x64 */    EUCTW_LATIN1,
  6106.     /* 0x65 */    EUCTW_LATIN1,
  6107.     /* 0x66 */    EUCTW_LATIN1,
  6108.     /* 0x67 */    EUCTW_LATIN1,
  6109.     /* 0x68 */    EUCTW_LATIN1,
  6110.     /* 0x69 */    EUCTW_LATIN1,
  6111.     /* 0x6a */    EUCTW_LATIN1,
  6112.     /* 0x6b */    EUCTW_LATIN1,
  6113.     /* 0x6c */    EUCTW_LATIN1,
  6114.     /* 0x6d */    EUCTW_LATIN1,
  6115.     /* 0x6e */    EUCTW_LATIN1,
  6116.     /* 0x6f */    EUCTW_LATIN1,
  6117.     /* 0x70 */    EUCTW_LATIN1,
  6118.     /* 0x71 */    EUCTW_LATIN1,
  6119.     /* 0x72 */    EUCTW_LATIN1,
  6120.     /* 0x73 */    EUCTW_LATIN1,
  6121.     /* 0x74 */    EUCTW_LATIN1,
  6122.     /* 0x75 */    EUCTW_LATIN1,
  6123.     /* 0x76 */    EUCTW_LATIN1,
  6124.     /* 0x77 */    EUCTW_LATIN1,
  6125.     /* 0x78 */    EUCTW_LATIN1,
  6126.     /* 0x79 */    EUCTW_LATIN1,
  6127.     /* 0x7a */    EUCTW_LATIN1,
  6128.     /* 0x7b */    EUCTW_LATIN1,
  6129.     /* 0x7c */    EUCTW_LATIN1,
  6130.     /* 0x7d */    EUCTW_LATIN1,
  6131.     /* 0x7e */    EUCTW_LATIN1,
  6132.     /* 0x7f */    EUCTW_LATIN1,
  6133.     /* 0x80 */    EUCTW_LATIN1,
  6134.     /* 0x81 */    EUCTW_LATIN1,
  6135.     /* 0x82 */    EUCTW_LATIN1,
  6136.     /* 0x83 */    EUCTW_LATIN1,
  6137.     /* 0x84 */    EUCTW_LATIN1,
  6138.     /* 0x85 */    EUCTW_LATIN1,
  6139.     /* 0x86 */    EUCTW_LATIN1,
  6140.     /* 0x87 */    EUCTW_LATIN1,
  6141.     /* 0x88 */    EUCTW_LATIN1,
  6142.     /* 0x89 */    EUCTW_LATIN1,
  6143.     /* 0x8a */    EUCTW_LATIN1,
  6144.     /* 0x8b */    EUCTW_LATIN1,
  6145.     /* 0x8c */    EUCTW_LATIN1,
  6146.     /* 0x8d */    EUCTW_LATIN1,
  6147.     /* 0x8e */    EUCTW_CNS11643_2,
  6148.     /* 0x8f */    EUCTW_LATIN1,
  6149.     /* 0x90 */    EUCTW_LATIN1,
  6150.     /* 0x91 */    EUCTW_LATIN1,
  6151.     /* 0x92 */    EUCTW_LATIN1,
  6152.     /* 0x93 */    EUCTW_LATIN1,
  6153.     /* 0x94 */    EUCTW_LATIN1,
  6154.     /* 0x95 */    EUCTW_LATIN1,
  6155.     /* 0x96 */    EUCTW_LATIN1,
  6156.     /* 0x97 */    EUCTW_LATIN1,
  6157.     /* 0x98 */    EUCTW_LATIN1,
  6158.     /* 0x99 */    EUCTW_LATIN1,
  6159.     /* 0x9a */    EUCTW_LATIN1,
  6160.     /* 0x9b */    EUCTW_LATIN1,
  6161.     /* 0x9c */    EUCTW_LATIN1,
  6162.     /* 0x9d */    EUCTW_LATIN1,
  6163.     /* 0x9e */    EUCTW_LATIN1,
  6164.     /* 0x9f */    EUCTW_LATIN1,
  6165.     /* 0xa0 */    EUCTW_LATIN1,
  6166.     /* 0xa1 */    EUCTW_CNS11643_1,
  6167.     /* 0xa2 */    EUCTW_CNS11643_1,
  6168.     /* 0xa3 */    EUCTW_CNS11643_1,
  6169.     /* 0xa4 */    EUCTW_CNS11643_1,
  6170.     /* 0xa5 */    EUCTW_CNS11643_1,
  6171.     /* 0xa6 */    EUCTW_CNS11643_1,
  6172.     /* 0xa7 */    EUCTW_CNS11643_1,
  6173.     /* 0xa8 */    EUCTW_CNS11643_1,
  6174.     /* 0xa9 */    EUCTW_CNS11643_1,
  6175.     /* 0xaa */    EUCTW_CNS11643_1,
  6176.     /* 0xab */    EUCTW_CNS11643_1,
  6177.     /* 0xac */    EUCTW_CNS11643_1,
  6178.     /* 0xad */    EUCTW_CNS11643_1,
  6179.     /* 0xae */    EUCTW_CNS11643_1,
  6180.     /* 0xaf */    EUCTW_CNS11643_1,
  6181.     /* 0xb0 */    EUCTW_CNS11643_1,
  6182.     /* 0xb1 */    EUCTW_CNS11643_1,
  6183.     /* 0xb2 */    EUCTW_CNS11643_1,
  6184.     /* 0xb3 */    EUCTW_CNS11643_1,
  6185.     /* 0xb4 */    EUCTW_CNS11643_1,
  6186.     /* 0xb5 */    EUCTW_CNS11643_1,
  6187.     /* 0xb6 */    EUCTW_CNS11643_1,
  6188.     /* 0xb7 */    EUCTW_CNS11643_1,
  6189.     /* 0xb8 */    EUCTW_CNS11643_1,
  6190.     /* 0xb9 */    EUCTW_CNS11643_1,
  6191.     /* 0xba */    EUCTW_CNS11643_1,
  6192.     /* 0xbb */    EUCTW_CNS11643_1,
  6193.     /* 0xbc */    EUCTW_CNS11643_1,
  6194.     /* 0xbd */    EUCTW_CNS11643_1,
  6195.     /* 0xbe */    EUCTW_CNS11643_1,
  6196.     /* 0xbf */    EUCTW_CNS11643_1,
  6197.     /* 0xc0 */    EUCTW_CNS11643_1,
  6198.     /* 0xc1 */    EUCTW_CNS11643_1,
  6199.     /* 0xc2 */    EUCTW_CNS11643_1,
  6200.     /* 0xc3 */    EUCTW_CNS11643_1,
  6201.     /* 0xc4 */    EUCTW_CNS11643_1,
  6202.     /* 0xc5 */    EUCTW_CNS11643_1,
  6203.     /* 0xc6 */    EUCTW_CNS11643_1,
  6204.     /* 0xc7 */    EUCTW_CNS11643_1,
  6205.     /* 0xc8 */    EUCTW_CNS11643_1,
  6206.     /* 0xc9 */    EUCTW_CNS11643_1,
  6207.     /* 0xca */    EUCTW_CNS11643_1,
  6208.     /* 0xcb */    EUCTW_CNS11643_1,
  6209.     /* 0xcc */    EUCTW_CNS11643_1,
  6210.     /* 0xcd */    EUCTW_CNS11643_1,
  6211.     /* 0xce */    EUCTW_CNS11643_1,
  6212.     /* 0xcf */    EUCTW_CNS11643_1,
  6213.     /* 0xd0 */    EUCTW_CNS11643_1,
  6214.     /* 0xd1 */    EUCTW_CNS11643_1,
  6215.     /* 0xd2 */    EUCTW_CNS11643_1,
  6216.     /* 0xd3 */    EUCTW_CNS11643_1,
  6217.     /* 0xd4 */    EUCTW_CNS11643_1,
  6218.     /* 0xd5 */    EUCTW_CNS11643_1,
  6219.     /* 0xd6 */    EUCTW_CNS11643_1,
  6220.     /* 0xd7 */    EUCTW_CNS11643_1,
  6221.     /* 0xd8 */    EUCTW_CNS11643_1,
  6222.     /* 0xd9 */    EUCTW_CNS11643_1,
  6223.     /* 0xda */    EUCTW_CNS11643_1,
  6224.     /* 0xdb */    EUCTW_CNS11643_1,
  6225.     /* 0xdc */    EUCTW_CNS11643_1,
  6226.     /* 0xdd */    EUCTW_CNS11643_1,
  6227.     /* 0xde */    EUCTW_CNS11643_1,
  6228.     /* 0xdf */    EUCTW_CNS11643_1,
  6229.     /* 0xe0 */    EUCTW_CNS11643_1,
  6230.     /* 0xe1 */    EUCTW_CNS11643_1,
  6231.     /* 0xe2 */    EUCTW_CNS11643_1,
  6232.     /* 0xe3 */    EUCTW_CNS11643_1,
  6233.     /* 0xe4 */    EUCTW_CNS11643_1,
  6234.     /* 0xe5 */    EUCTW_CNS11643_1,
  6235.     /* 0xe6 */    EUCTW_CNS11643_1,
  6236.     /* 0xe7 */    EUCTW_CNS11643_1,
  6237.     /* 0xe8 */    EUCTW_CNS11643_1,
  6238.     /* 0xe9 */    EUCTW_CNS11643_1,
  6239.     /* 0xea */    EUCTW_CNS11643_1,
  6240.     /* 0xeb */    EUCTW_CNS11643_1,
  6241.     /* 0xec */    EUCTW_CNS11643_1,
  6242.     /* 0xed */    EUCTW_CNS11643_1,
  6243.     /* 0xee */    EUCTW_CNS11643_1,
  6244.     /* 0xef */    EUCTW_CNS11643_1,
  6245.     /* 0xf0 */    EUCTW_CNS11643_1,
  6246.     /* 0xf1 */    EUCTW_CNS11643_1,
  6247.     /* 0xf2 */    EUCTW_CNS11643_1,
  6248.     /* 0xf3 */    EUCTW_CNS11643_1,
  6249.     /* 0xf4 */    EUCTW_CNS11643_1,
  6250.     /* 0xf5 */    EUCTW_CNS11643_1,
  6251.     /* 0xf6 */    EUCTW_CNS11643_1,
  6252.     /* 0xf7 */    EUCTW_CNS11643_1,
  6253.     /* 0xf8 */    EUCTW_CNS11643_1,
  6254.     /* 0xf9 */    EUCTW_CNS11643_1,
  6255.     /* 0xfa */    EUCTW_CNS11643_1,
  6256.     /* 0xfb */    EUCTW_CNS11643_1,
  6257.     /* 0xfc */    EUCTW_CNS11643_1,
  6258.     /* 0xfd */    EUCTW_CNS11643_1,
  6259.     /* 0xfe */    EUCTW_CNS11643_1,
  6260.     /* 0xff */    EUCTW_LATIN1,
  6261. };
  6262.  
  6263.  
  6264. static XP_Bool
  6265. fe_AreEUCTWFontsAvail(int16 win_csid)
  6266. {
  6267.     /* this needs to match the code in fe_LoadEUCTWFont */
  6268.     if (((fe_FontCharSets[CS_CNS11643_1 & 0xff].name == NULL)
  6269.         || (fe_FontCharSets[CS_CNS11643_2 & 0xff].name == NULL))
  6270.         && (fe_FontCharSets[CS_CNS11643_1110 & 0xff].name == NULL))
  6271.         return FALSE;
  6272.     else
  6273.         return TRUE;
  6274. }
  6275.  
  6276. static fe_Font
  6277. fe_LoadEUCTWFont(MWContext *context, char *familyName, int points,
  6278.                  int sizeNum, int fontmask, int charset, int pitch,
  6279.                  int faceNum, Display *dpy)
  6280. {
  6281.     int16            cs;
  6282.     int            len;
  6283.     fe_FontGroupFont    *ret;
  6284.  
  6285.     len = (3 * sizeof(fe_FontGroupFont));
  6286.     ret = calloc(1, len);
  6287.     if (!ret)
  6288.     {
  6289.         return NULL;
  6290.     }
  6291.     (void) memset(ret, 0, len);
  6292.  
  6293.     cs = CS_LATIN1;
  6294.     ret[0].xFont = (XFontStruct *)
  6295.             fe_LoadFont(context, &cs, familyName, points, sizeNum, fontmask);
  6296.     if (cs != CS_LATIN1)
  6297.     {
  6298.         XP_FREE(ret);
  6299.         return NULL;
  6300.     }
  6301.  
  6302.     /* this needs to match the code in fe_AreEUCTWFontsAvail */
  6303.     cs = CS_CNS11643_1;
  6304.     ret[1].xFont = (XFontStruct *)
  6305.             fe_LoadFont(context, &cs, familyName, points, sizeNum, fontmask);
  6306.     if (cs == CS_CNS11643_1)
  6307.     {
  6308.         ret[1].mask1 = 0x7f;
  6309.         ret[1].mask2 = 0x7f;
  6310.     }
  6311.     else
  6312.     {
  6313.         ret[1].xFont = NULL;
  6314.     }
  6315.  
  6316.     cs = CS_CNS11643_2;
  6317.     ret[2].xFont = (XFontStruct *)
  6318.             fe_LoadFont(context, &cs, familyName, points, sizeNum, fontmask);
  6319.     if (cs == CS_CNS11643_2)
  6320.     {
  6321.         ret[2].mask1 = 0x7f;
  6322.         ret[2].mask2 = 0x7f;
  6323.     }
  6324.     else
  6325.     {
  6326.         ret[2].xFont = NULL;
  6327.     }
  6328.  
  6329.     if ((!ret[1].xFont) || (!ret[2].xFont))
  6330.     {
  6331.         cs = CS_CNS11643_1110;
  6332.         ret[1].xFont = (XFontStruct *)
  6333.                     fe_LoadFont(context, &cs, familyName, points, sizeNum,
  6334.                                 fontmask);
  6335.         if (cs == CS_CNS11643_1110)
  6336.         {
  6337.             ret[1].mask1 = 0xff;
  6338.             ret[1].mask2 = 0xff;
  6339.  
  6340.             ret[2].xFont = ret[1].xFont;
  6341.             ret[2].mask1 = 0xff;
  6342.             ret[2].mask2 = 0x7f;
  6343.         }
  6344.         else
  6345.         {
  6346.             XP_FREE(ret);
  6347.             return NULL;
  6348.         }
  6349.     }
  6350.  
  6351.     return (fe_Font) ret;
  6352. }
  6353.  
  6354.  
  6355. static void
  6356. fe_EUCTWTextExtents(fe_Font font, char *string, int len, int *direction,
  6357.     int *fontAscent, int *fontDescent, XCharStruct *overall)
  6358. {
  6359.     fe_ProcessEUCString(CS_CNS_8BIT, EUCTWTable, 
  6360.         NULL, 
  6361.         NULL,
  6362.         NULL, None, font, NULL, 0, 0, string, len,
  6363.         fontAscent, fontDescent, overall,
  6364.         fe_CharSetFuncsArray[FE_FONT_INFO_EUCTW].numberOfFonts);
  6365. }
  6366.  
  6367.  
  6368. static void
  6369. fe_DrawEUCTWString(Display *dpy, Drawable d, fe_Font font, GC gc, int x,
  6370.     int y, char *string, int len)
  6371. {
  6372.     fe_ProcessEUCString(CS_CNS_8BIT, EUCTWTable, 
  6373.         (fe_XDrawStringFunc) XDrawString,
  6374.         (fe_XDrawStringFunc) XDrawString16,
  6375.         dpy, d, font, gc, x, y, string, len,
  6376.         NULL, NULL, NULL,
  6377.         0);
  6378. }
  6379.  
  6380.  
  6381. static void
  6382. fe_DrawEUCTWImageString(Display *dpy, Drawable d, fe_Font font, GC gc, GC gc2,
  6383.     int x, int y, char *string, int len)
  6384. {
  6385.     fe_ProcessEUCString(CS_CNS_8BIT, EUCTWTable, 
  6386.         (fe_XDrawStringFunc) XDrawImageString,
  6387.         (fe_XDrawStringFunc) XDrawImageString16,
  6388.         dpy, d, font, gc, x, y, string, len,
  6389.         NULL, NULL, NULL,
  6390.         0);
  6391. }
  6392.  
  6393.  
  6394.                 /*    fontIndex    skip    len    */
  6395. #define BIG5_LATIN1        {    0,        0,    1    }
  6396. #define BIG5_BIG5        {    1,        0,    2    }
  6397.  
  6398. static fe_StringProcessTable BIG5Table[] =
  6399. {
  6400.     /* 0x00 */    BIG5_LATIN1,
  6401.     /* 0x01 */    BIG5_LATIN1,
  6402.     /* 0x02 */    BIG5_LATIN1,
  6403.     /* 0x03 */    BIG5_LATIN1,
  6404.     /* 0x04 */    BIG5_LATIN1,
  6405.     /* 0x05 */    BIG5_LATIN1,
  6406.     /* 0x06 */    BIG5_LATIN1,
  6407.     /* 0x07 */    BIG5_LATIN1,
  6408.     /* 0x08 */    BIG5_LATIN1,
  6409.     /* 0x09 */    BIG5_LATIN1,
  6410.     /* 0x0a */    BIG5_LATIN1,
  6411.     /* 0x0b */    BIG5_LATIN1,
  6412.     /* 0x0c */    BIG5_LATIN1,
  6413.     /* 0x0d */    BIG5_LATIN1,
  6414.     /* 0x0e */    BIG5_LATIN1,
  6415.     /* 0x0f */    BIG5_LATIN1,
  6416.     /* 0x10 */    BIG5_LATIN1,
  6417.     /* 0x11 */    BIG5_LATIN1,
  6418.     /* 0x12 */    BIG5_LATIN1,
  6419.     /* 0x13 */    BIG5_LATIN1,
  6420.     /* 0x14 */    BIG5_LATIN1,
  6421.     /* 0x15 */    BIG5_LATIN1,
  6422.     /* 0x16 */    BIG5_LATIN1,
  6423.     /* 0x17 */    BIG5_LATIN1,
  6424.     /* 0x18 */    BIG5_LATIN1,
  6425.     /* 0x19 */    BIG5_LATIN1,
  6426.     /* 0x1a */    BIG5_LATIN1,
  6427.     /* 0x1b */    BIG5_LATIN1,
  6428.     /* 0x1c */    BIG5_LATIN1,
  6429.     /* 0x1d */    BIG5_LATIN1,
  6430.     /* 0x1e */    BIG5_LATIN1,
  6431.     /* 0x1f */    BIG5_LATIN1,
  6432.     /* 0x20 */    BIG5_LATIN1,
  6433.     /* 0x21 */    BIG5_LATIN1,
  6434.     /* 0x22 */    BIG5_LATIN1,
  6435.     /* 0x23 */    BIG5_LATIN1,
  6436.     /* 0x24 */    BIG5_LATIN1,
  6437.     /* 0x25 */    BIG5_LATIN1,
  6438.     /* 0x26 */    BIG5_LATIN1,
  6439.     /* 0x27 */    BIG5_LATIN1,
  6440.     /* 0x28 */    BIG5_LATIN1,
  6441.     /* 0x29 */    BIG5_LATIN1,
  6442.     /* 0x2a */    BIG5_LATIN1,
  6443.     /* 0x2b */    BIG5_LATIN1,
  6444.     /* 0x2c */    BIG5_LATIN1,
  6445.     /* 0x2d */    BIG5_LATIN1,
  6446.     /* 0x2e */    BIG5_LATIN1,
  6447.     /* 0x2f */    BIG5_LATIN1,
  6448.     /* 0x30 */    BIG5_LATIN1,
  6449.     /* 0x31 */    BIG5_LATIN1,
  6450.     /* 0x32 */    BIG5_LATIN1,
  6451.     /* 0x33 */    BIG5_LATIN1,
  6452.     /* 0x34 */    BIG5_LATIN1,
  6453.     /* 0x35 */    BIG5_LATIN1,
  6454.     /* 0x36 */    BIG5_LATIN1,
  6455.     /* 0x37 */    BIG5_LATIN1,
  6456.     /* 0x38 */    BIG5_LATIN1,
  6457.     /* 0x39 */    BIG5_LATIN1,
  6458.     /* 0x3a */    BIG5_LATIN1,
  6459.     /* 0x3b */    BIG5_LATIN1,
  6460.     /* 0x3c */    BIG5_LATIN1,
  6461.     /* 0x3d */    BIG5_LATIN1,
  6462.     /* 0x3e */    BIG5_LATIN1,
  6463.     /* 0x3f */    BIG5_LATIN1,
  6464.     /* 0x40 */    BIG5_LATIN1,
  6465.     /* 0x41 */    BIG5_LATIN1,
  6466.     /* 0x42 */    BIG5_LATIN1,
  6467.     /* 0x43 */    BIG5_LATIN1,
  6468.     /* 0x44 */    BIG5_LATIN1,
  6469.     /* 0x45 */    BIG5_LATIN1,
  6470.     /* 0x46 */    BIG5_LATIN1,
  6471.     /* 0x47 */    BIG5_LATIN1,
  6472.     /* 0x48 */    BIG5_LATIN1,
  6473.     /* 0x49 */    BIG5_LATIN1,
  6474.     /* 0x4a */    BIG5_LATIN1,
  6475.     /* 0x4b */    BIG5_LATIN1,
  6476.     /* 0x4c */    BIG5_LATIN1,
  6477.     /* 0x4d */    BIG5_LATIN1,
  6478.     /* 0x4e */    BIG5_LATIN1,
  6479.     /* 0x4f */    BIG5_LATIN1,
  6480.     /* 0x50 */    BIG5_LATIN1,
  6481.     /* 0x51 */    BIG5_LATIN1,
  6482.     /* 0x52 */    BIG5_LATIN1,
  6483.     /* 0x53 */    BIG5_LATIN1,
  6484.     /* 0x54 */    BIG5_LATIN1,
  6485.     /* 0x55 */    BIG5_LATIN1,
  6486.     /* 0x56 */    BIG5_LATIN1,
  6487.     /* 0x57 */    BIG5_LATIN1,
  6488.     /* 0x58 */    BIG5_LATIN1,
  6489.     /* 0x59 */    BIG5_LATIN1,
  6490.     /* 0x5a */    BIG5_LATIN1,
  6491.     /* 0x5b */    BIG5_LATIN1,
  6492.     /* 0x5c */    BIG5_LATIN1,
  6493.     /* 0x5d */    BIG5_LATIN1,
  6494.     /* 0x5e */    BIG5_LATIN1,
  6495.     /* 0x5f */    BIG5_LATIN1,
  6496.     /* 0x60 */    BIG5_LATIN1,
  6497.     /* 0x61 */    BIG5_LATIN1,
  6498.     /* 0x62 */    BIG5_LATIN1,
  6499.     /* 0x63 */    BIG5_LATIN1,
  6500.     /* 0x64 */    BIG5_LATIN1,
  6501.     /* 0x65 */    BIG5_LATIN1,
  6502.     /* 0x66 */    BIG5_LATIN1,
  6503.     /* 0x67 */    BIG5_LATIN1,
  6504.     /* 0x68 */    BIG5_LATIN1,
  6505.     /* 0x69 */    BIG5_LATIN1,
  6506.     /* 0x6a */    BIG5_LATIN1,
  6507.     /* 0x6b */    BIG5_LATIN1,
  6508.     /* 0x6c */    BIG5_LATIN1,
  6509.     /* 0x6d */    BIG5_LATIN1,
  6510.     /* 0x6e */    BIG5_LATIN1,
  6511.     /* 0x6f */    BIG5_LATIN1,
  6512.     /* 0x70 */    BIG5_LATIN1,
  6513.     /* 0x71 */    BIG5_LATIN1,
  6514.     /* 0x72 */    BIG5_LATIN1,
  6515.     /* 0x73 */    BIG5_LATIN1,
  6516.     /* 0x74 */    BIG5_LATIN1,
  6517.     /* 0x75 */    BIG5_LATIN1,
  6518.     /* 0x76 */    BIG5_LATIN1,
  6519.     /* 0x77 */    BIG5_LATIN1,
  6520.     /* 0x78 */    BIG5_LATIN1,
  6521.     /* 0x79 */    BIG5_LATIN1,
  6522.     /* 0x7a */    BIG5_LATIN1,
  6523.     /* 0x7b */    BIG5_LATIN1,
  6524.     /* 0x7c */    BIG5_LATIN1,
  6525.     /* 0x7d */    BIG5_LATIN1,
  6526.     /* 0x7e */    BIG5_LATIN1,
  6527.     /* 0x7f */    BIG5_LATIN1,
  6528.     /* 0x80 */    BIG5_LATIN1,
  6529.     /* 0x81 */    BIG5_LATIN1,
  6530.     /* 0x82 */    BIG5_LATIN1,
  6531.     /* 0x83 */    BIG5_LATIN1,
  6532.     /* 0x84 */    BIG5_LATIN1,
  6533.     /* 0x85 */    BIG5_LATIN1,
  6534.     /* 0x86 */    BIG5_LATIN1,
  6535.     /* 0x87 */    BIG5_LATIN1,
  6536.     /* 0x88 */    BIG5_LATIN1,
  6537.     /* 0x89 */    BIG5_LATIN1,
  6538.     /* 0x8a */    BIG5_LATIN1,
  6539.     /* 0x8b */    BIG5_LATIN1,
  6540.     /* 0x8c */    BIG5_LATIN1,
  6541.     /* 0x8d */    BIG5_LATIN1,
  6542.     /* 0x8e */    BIG5_LATIN1,
  6543.     /* 0x8f */    BIG5_LATIN1,
  6544.     /* 0x90 */    BIG5_LATIN1,
  6545.     /* 0x91 */    BIG5_LATIN1,
  6546.     /* 0x92 */    BIG5_LATIN1,
  6547.     /* 0x93 */    BIG5_LATIN1,
  6548.     /* 0x94 */    BIG5_LATIN1,
  6549.     /* 0x95 */    BIG5_LATIN1,
  6550.     /* 0x96 */    BIG5_LATIN1,
  6551.     /* 0x97 */    BIG5_LATIN1,
  6552.     /* 0x98 */    BIG5_LATIN1,
  6553.     /* 0x99 */    BIG5_LATIN1,
  6554.     /* 0x9a */    BIG5_LATIN1,
  6555.     /* 0x9b */    BIG5_LATIN1,
  6556.     /* 0x9c */    BIG5_LATIN1,
  6557.     /* 0x9d */    BIG5_LATIN1,
  6558.     /* 0x9e */    BIG5_LATIN1,
  6559.     /* 0x9f */    BIG5_LATIN1,
  6560.     /* 0xa0 */    BIG5_LATIN1,
  6561.     /* 0xa1 */    BIG5_BIG5,
  6562.     /* 0xa2 */    BIG5_BIG5,
  6563.     /* 0xa3 */    BIG5_BIG5,
  6564.     /* 0xa4 */    BIG5_BIG5,
  6565.     /* 0xa5 */    BIG5_BIG5,
  6566.     /* 0xa6 */    BIG5_BIG5,
  6567.     /* 0xa7 */    BIG5_BIG5,
  6568.     /* 0xa8 */    BIG5_BIG5,
  6569.     /* 0xa9 */    BIG5_BIG5,
  6570.     /* 0xaa */    BIG5_BIG5,
  6571.     /* 0xab */    BIG5_BIG5,
  6572.     /* 0xac */    BIG5_BIG5,
  6573.     /* 0xad */    BIG5_BIG5,
  6574.     /* 0xae */    BIG5_BIG5,
  6575.     /* 0xaf */    BIG5_BIG5,
  6576.     /* 0xb0 */    BIG5_BIG5,
  6577.     /* 0xb1 */    BIG5_BIG5,
  6578.     /* 0xb2 */    BIG5_BIG5,
  6579.     /* 0xb3 */    BIG5_BIG5,
  6580.     /* 0xb4 */    BIG5_BIG5,
  6581.     /* 0xb5 */    BIG5_BIG5,
  6582.     /* 0xb6 */    BIG5_BIG5,
  6583.     /* 0xb7 */    BIG5_BIG5,
  6584.     /* 0xb8 */    BIG5_BIG5,
  6585.     /* 0xb9 */    BIG5_BIG5,
  6586.     /* 0xba */    BIG5_BIG5,
  6587.     /* 0xbb */    BIG5_BIG5,
  6588.     /* 0xbc */    BIG5_BIG5,
  6589.     /* 0xbd */    BIG5_BIG5,
  6590.     /* 0xbe */    BIG5_BIG5,
  6591.     /* 0xbf */    BIG5_BIG5,
  6592.     /* 0xc0 */    BIG5_BIG5,
  6593.     /* 0xc1 */    BIG5_BIG5,
  6594.     /* 0xc2 */    BIG5_BIG5,
  6595.     /* 0xc3 */    BIG5_BIG5,
  6596.     /* 0xc4 */    BIG5_BIG5,
  6597.     /* 0xc5 */    BIG5_BIG5,
  6598.     /* 0xc6 */    BIG5_BIG5,
  6599.     /* 0xc7 */    BIG5_BIG5,
  6600.     /* 0xc8 */    BIG5_BIG5,
  6601.     /* 0xc9 */    BIG5_BIG5,
  6602.     /* 0xca */    BIG5_BIG5,
  6603.     /* 0xcb */    BIG5_BIG5,
  6604.     /* 0xcc */    BIG5_BIG5,
  6605.     /* 0xcd */    BIG5_BIG5,
  6606.     /* 0xce */    BIG5_BIG5,
  6607.     /* 0xcf */    BIG5_BIG5,
  6608.     /* 0xd0 */    BIG5_BIG5,
  6609.     /* 0xd1 */    BIG5_BIG5,
  6610.     /* 0xd2 */    BIG5_BIG5,
  6611.     /* 0xd3 */    BIG5_BIG5,
  6612.     /* 0xd4 */    BIG5_BIG5,
  6613.     /* 0xd5 */    BIG5_BIG5,
  6614.     /* 0xd6 */    BIG5_BIG5,
  6615.     /* 0xd7 */    BIG5_BIG5,
  6616.     /* 0xd8 */    BIG5_BIG5,
  6617.     /* 0xd9 */    BIG5_BIG5,
  6618.     /* 0xda */    BIG5_BIG5,
  6619.     /* 0xdb */    BIG5_BIG5,
  6620.     /* 0xdc */    BIG5_BIG5,
  6621.     /* 0xdd */    BIG5_BIG5,
  6622.     /* 0xde */    BIG5_BIG5,
  6623.     /* 0xdf */    BIG5_BIG5,
  6624.     /* 0xe0 */    BIG5_BIG5,
  6625.     /* 0xe1 */    BIG5_BIG5,
  6626.     /* 0xe2 */    BIG5_BIG5,
  6627.     /* 0xe3 */    BIG5_BIG5,
  6628.     /* 0xe4 */    BIG5_BIG5,
  6629.     /* 0xe5 */    BIG5_BIG5,
  6630.     /* 0xe6 */    BIG5_BIG5,
  6631.     /* 0xe7 */    BIG5_BIG5,
  6632.     /* 0xe8 */    BIG5_BIG5,
  6633.     /* 0xe9 */    BIG5_BIG5,
  6634.     /* 0xea */    BIG5_BIG5,
  6635.     /* 0xeb */    BIG5_BIG5,
  6636.     /* 0xec */    BIG5_BIG5,
  6637.     /* 0xed */    BIG5_BIG5,
  6638.     /* 0xee */    BIG5_BIG5,
  6639.     /* 0xef */    BIG5_BIG5,
  6640.     /* 0xf0 */    BIG5_BIG5,
  6641.     /* 0xf1 */    BIG5_BIG5,
  6642.     /* 0xf2 */    BIG5_BIG5,
  6643.     /* 0xf3 */    BIG5_BIG5,
  6644.     /* 0xf4 */    BIG5_BIG5,
  6645.     /* 0xf5 */    BIG5_BIG5,
  6646.     /* 0xf6 */    BIG5_BIG5,
  6647.     /* 0xf7 */    BIG5_BIG5,
  6648.     /* 0xf8 */    BIG5_BIG5,
  6649.     /* 0xf9 */    BIG5_BIG5,
  6650.     /* 0xfa */    BIG5_BIG5,
  6651.     /* 0xfb */    BIG5_BIG5,
  6652.     /* 0xfc */    BIG5_BIG5,
  6653.     /* 0xfd */    BIG5_BIG5,
  6654.     /* 0xfe */    BIG5_BIG5,
  6655.     /* 0xff */    BIG5_LATIN1,
  6656. };
  6657.  
  6658.  
  6659. static XP_Bool
  6660. fe_AreBIG5FontsAvail(int16 win_csid)
  6661. {
  6662.     /* this needs to match the code in fe_LoadBIG5Font */
  6663.     if (fe_FontCharSets[CS_X_BIG5 & 0xff].name == NULL)
  6664.         return FALSE;
  6665.     else
  6666.         return TRUE;
  6667. }
  6668.  
  6669. static fe_Font
  6670. fe_LoadBIG5Font(MWContext *context, char *familyName, int points,
  6671.                 int sizeNum, int fontmask, int charset, int pitch,
  6672.                 int faceNum, Display *dpy)
  6673. {
  6674.     int16            cs;
  6675.     int            len;
  6676.     fe_FontGroupFont    *ret;
  6677.  
  6678.     len = (2 * sizeof(fe_FontGroupFont));
  6679.     ret = calloc(1, len);
  6680.     if (!ret)
  6681.     {
  6682.         return NULL;
  6683.     }
  6684.     (void) memset(ret, 0, len);
  6685.  
  6686.     cs = CS_LATIN1;
  6687.     ret[0].xFont = (XFontStruct *)
  6688.             fe_LoadFont(context, &cs, familyName, points, sizeNum, fontmask);
  6689.     if (cs != CS_LATIN1)
  6690.     {
  6691.         XP_FREE(ret);
  6692.         return NULL;
  6693.     }
  6694.  
  6695.     /* this needs to match the code in fe_AreBIG5FontsAvail */
  6696.     cs = CS_X_BIG5;
  6697.     ret[1].xFont = (XFontStruct *)
  6698.             fe_LoadFont(context, &cs, familyName, points, sizeNum, fontmask);
  6699.     if (cs == CS_X_BIG5)
  6700.     {
  6701.         ret[1].mask1 = 0xff;
  6702.         ret[1].mask2 = 0xff;
  6703.     }
  6704.     else
  6705.     {
  6706.         XP_FREE(ret);
  6707.         return NULL;
  6708.     }
  6709.  
  6710.     return (fe_Font) ret;
  6711. }
  6712.  
  6713.  
  6714. static void
  6715. fe_BIG5TextExtents(fe_Font font, char *string, int len, int *direction,
  6716.     int *fontAscent, int *fontDescent, XCharStruct *overall)
  6717. {
  6718.     fe_ProcessEUCString(CS_BIG5, BIG5Table, 
  6719.         NULL,
  6720.         NULL,
  6721.         NULL, None, font, NULL, 0, 0, string, len,
  6722.         fontAscent, fontDescent, overall,
  6723.         fe_CharSetFuncsArray[FE_FONT_INFO_BIG5].numberOfFonts);
  6724. }
  6725.  
  6726.  
  6727. static void
  6728. fe_DrawBIG5String(Display *dpy, Drawable d, fe_Font font, GC gc, int x,
  6729.     int y, char *string, int len)
  6730. {
  6731.     fe_ProcessEUCString(CS_BIG5, BIG5Table, 
  6732.         (fe_XDrawStringFunc) XDrawString,
  6733.         (fe_XDrawStringFunc) XDrawString16,
  6734.         dpy, d, font, gc, x, y, string, len,
  6735.         NULL, NULL, NULL,
  6736.         0);
  6737. }
  6738.  
  6739.  
  6740. static void
  6741. fe_DrawBIG5ImageString(Display *dpy, Drawable d, fe_Font font, GC gc, GC gc2,
  6742.     int x, int y, char *string, int len)
  6743. {
  6744.     fe_ProcessEUCString(CS_BIG5, BIG5Table, 
  6745.         (fe_XDrawStringFunc) XDrawImageString,
  6746.         (fe_XDrawStringFunc) XDrawImageString16,
  6747.         dpy, d, font, gc, x, y, string, len,
  6748.         NULL, NULL, NULL,
  6749.         0);
  6750. }
  6751.  
  6752. int 
  6753. fe_UnicodePointToPixelSize(Display *dpy, int pointSize)
  6754. {
  6755.     int pixelSize;
  6756.     static double pointToPixelFactor;
  6757.     static XP_Bool inited = FALSE;
  6758.     char name[512], class[512];
  6759.     char *type;
  6760.     XrmValue value;
  6761.  
  6762.     if (!inited) {
  6763.         inited = TRUE;
  6764.         pointToPixelFactor = ((WidthOfScreen(DefaultScreenOfDisplay(dpy)) /
  6765.                 (WidthMMOfScreen(DefaultScreenOfDisplay(dpy)) / 25.4)) /
  6766.                 72.27) / 10;
  6767.  
  6768.         /*
  6769.          * Get the users resource setting
  6770.          */
  6771.         (void) PR_snprintf(name, sizeof(name), "%s.unicodeFont.screenDpi", 
  6772.                         fe_progclass);
  6773.         (void) PR_snprintf(class, sizeof(class),"%s.UnicodeFont.ScreenDpi",
  6774.                         fe_progclass);
  6775.         if (XrmGetResource(XtDatabase(dpy), name, class, &type, &value)){
  6776.             float userScreenDpi;
  6777.             if (sscanf((char *)value.addr, "%e", &userScreenDpi)) {
  6778.                 pointToPixelFactor = (userScreenDpi/72.27) / 10;
  6779.             }
  6780.         }
  6781.     }
  6782.     pointSize += 4; /* round up */
  6783.     pixelSize = (int)(pointSize * pointToPixelFactor);
  6784.     return pixelSize;
  6785. }
  6786.  
  6787. static XP_Bool
  6788. fe_AreUnicodeFontsAvail(int16 win_csid)
  6789. {
  6790.     /*
  6791.      * since we build unicode fonts from other fonts
  6792.      * there is not a good way to tell what will be
  6793.      * avail so just assume we can do it
  6794.      */
  6795.     return TRUE;
  6796. }
  6797.  
  6798. /*
  6799.  * fe_LoadUnicodeFont - load (create) a Unicode Pseudo Font
  6800.  *
  6801.  * see fe_loadUnicodePseudoFonts() for information on Unicode Pseudo Fonts
  6802.  *
  6803.  */
  6804. fe_Font
  6805. fe_LoadUnicodeFont(void *not_used, char *familyName,
  6806.                    int points, int sizeNum,
  6807.          int fontmask, int charset, int pitch, int faceNum,
  6808.          Display *dpy)
  6809. {
  6810.     fe_UnicodePseudoFont *ufont;
  6811.     fe_FontFamily *unicodeFamily = NULL;
  6812.     fe_FontSize *unicodeSize;
  6813.     int pixelSize;
  6814.  
  6815.     /*
  6816.      * If the familyName is specified then find it
  6817.      * else use the selected family
  6818.      */
  6819.     if (familyName) {
  6820.         unicodeFamily = fe_FontFindFamily(CS_UTF8, pitch, familyName);
  6821.     }
  6822.     /*
  6823.      * If the familyName is not specified or that family not found
  6824.      * then use the selected family
  6825.      */
  6826.     if (!unicodeFamily) {
  6827.         unicodeFamily = fe_GetFontFamily(CS_UTF8, pitch);
  6828.         familyName = unicodeFamily->family;
  6829.     }
  6830.     unicodeSize = unicodeFamily->htmlSizes[sizeNum-1];
  6831.     pixelSize = fe_UnicodePointToPixelSize(dpy, unicodeSize->size);
  6832.     ufont = fe_LoadUnicodeFontByPixelSize(not_used, familyName, 
  6833.                     pixelSize, fontmask, charset, pitch, faceNum, dpy);
  6834.  
  6835.     return ufont;
  6836. }
  6837.  
  6838. /*
  6839.  * fe_LoadUnicodeFontByPixelSize - load (create) a Unicode Pseudo Font
  6840.  *
  6841.  * see fe_loadUnicodePseudoFonts() for information on Unicode Pseudo Fonts
  6842.  *
  6843.  */
  6844. fe_Font
  6845. fe_LoadUnicodeFontByPixelSize(void *not_used, char *familyName, int pixelSize,
  6846.          int fontmask, int charset, int pitch, int faceNum,
  6847.          Display *dpy)
  6848. {
  6849.     fe_UnicodePseudoFont *ufont;
  6850.  
  6851.     ufont = (fe_UnicodePseudoFont*)calloc(1, sizeof(fe_UnicodePseudoFont));
  6852.     if (!ufont) {
  6853.         return NULL;
  6854.     }
  6855.     ufont->tag = UNICODE_PSEUDO_FONT_TAG;
  6856.     ufont->family = strdup(familyName);
  6857.     ufont->dpy = dpy;
  6858.     ufont->pixelSize = pixelSize;
  6859.     ufont->fontmask = fontmask;
  6860.     ufont->pitch = pitch;
  6861.     ufont->faceNum = faceNum;
  6862.     ufont->ascent = 0;
  6863.     ufont->descent = 0;
  6864.  
  6865.     return ufont;
  6866. }
  6867.  
  6868. void
  6869. fe_freeUnicodePseudoFont(fe_Font font)
  6870. {
  6871.     fe_UnicodePseudoFont *ufont = (fe_UnicodePseudoFont *)font;
  6872.     int i_encodings;
  6873.  
  6874.     if (ufont->tag != UNICODE_PSEUDO_FONT_TAG) {
  6875. #ifdef DEBUG_bstell
  6876.         printf("bad ufont %s %d\n", __FILE__, __LINE__);
  6877. #endif
  6878.         return;
  6879.     }
  6880.  
  6881.     if (ufont->family)
  6882.         free(ufont->family);
  6883.     /*
  6884.      * Free any scaled fonts
  6885.      */
  6886.     for (i_encodings=0; i_encodings<INTL_CHAR_SET_MAX; i_encodings++) {
  6887.         if (ufont->xfont_scaled[i_encodings]) {
  6888.             XFreeFont(ufont->dpy, ufont->xFonts[i_encodings]);
  6889.             XP_FREE(ufont->xfont_name[i_encodings]);
  6890.         }
  6891.     }
  6892.     if (ufont->xmfontlist)
  6893.         XmFontListFree(ufont->xmfontlist);
  6894.     if (ufont->xm_fontset)
  6895.         XmFontListFree(ufont->xm_fontset);
  6896.     if (ufont->xfontset) 
  6897.         XFreeFontSet(ufont->dpy, ufont->xfontset);
  6898.     free(ufont);
  6899. }
  6900.  
  6901. static char *
  6902. fe_UnicodeEquivFontName(fe_UnicodePseudoFont *ufont, uint16 charsetID)
  6903. {
  6904.     XrmDatabase db;
  6905.     char name[512], class[512];
  6906.     char *csid_name, *type;
  6907.     XrmValue value;
  6908.  
  6909.     charsetID &= 0xFF;
  6910.  
  6911.     if (ufont->fontFamily[charsetID&0xFF])
  6912.         return (ufont->fontFamily[charsetID]);
  6913.  
  6914.     db = XtDatabase(ufont->dpy);
  6915.  
  6916.     csid_name = INTL_CsidToCharsetNamePt(charsetID);
  6917.     (void) PR_snprintf(name, sizeof(name), "%s.unicodeFont.%s.%s", 
  6918.                         fe_progclass, ufont->family, csid_name);
  6919.     (void) PR_snprintf(class, sizeof(class), "%s.UnicodeFont.%s.%s", 
  6920.                         fe_progclass, ufont->family, "Name");
  6921.     if (XrmGetResource(db, name, class, &type, &value))
  6922.         ufont->fontFamily[charsetID] = strdup(value.addr);
  6923.     else
  6924.         ufont->fontFamily[charsetID] = strdup(ufont->family);
  6925.     return (ufont->fontFamily[charsetID]);
  6926. }
  6927.  
  6928. /*
  6929.  * Rate the  Quality of the font match
  6930.  *
  6931.  * a return range 0.0 to 1.0
  6932.  * 1.0 means perfect match
  6933.  * lower numbers mean poorer match
  6934.  */
  6935. static int
  6936. fe_UnicodeFontQ(fe_UnicodePseudoFont *ufont, 
  6937.                 int32 target_height, int32 actual_height,
  6938.                 XP_Bool family_match, XP_Bool weight_match, XP_Bool slant_match,
  6939.                 int target_pitch, XP_Bool pitch_match
  6940.                 )
  6941. {
  6942.     float q = 1.0;
  6943.  
  6944.     /*
  6945.      * Look at size match
  6946.      */
  6947.     if (actual_height <= target_height)
  6948.         q *= (float)actual_height / (float)target_height;
  6949.     else
  6950.         q *= (float)target_height / (float)actual_height;
  6951.  
  6952.     /*
  6953.      * Look at family match (correct font family)
  6954.      */
  6955.     if (!family_match)
  6956.         q *= 0.8;
  6957. #ifdef DEBUG_bstell
  6958.     else
  6959.         q *= 1.0;
  6960. #endif
  6961.  
  6962.     /*
  6963.      * Look at weight match (regular vs bold)
  6964.      */
  6965.     if (!weight_match)
  6966.         q *= 0.75;
  6967.  
  6968.     /*
  6969.      * Look at slant match (regular vs italic)
  6970.      */
  6971.     if (!slant_match)
  6972.         q *= 0.5;
  6973.  
  6974.     /*
  6975.      * Look at pitch match (monospaced vs proportional)
  6976.      *
  6977.      * Pitch doesn't mean much to most users but:
  6978.      *    many (older) applications assume a monospaced font 
  6979.      *    and won't work correctly with a proportional font 
  6980.      * Hence if the target font is monospaced
  6981.      *    we strongly want the pitch to be right
  6982.      */
  6983.     if (!pitch_match) {
  6984.         if (target_pitch == 0) /* proportional */
  6985.             q *= 0.8;
  6986.         else /* MONO */
  6987.             q *= 0.0;
  6988.     }
  6989.  
  6990.     return (int)(q * 100);
  6991. }
  6992.  
  6993. #define IS_ORIG_PITCH(pitch) ((pitch)==0)
  6994. #define IS_ORIG_WEIGHT_FACE(face)   (((face)&1)==0)
  6995. #define IS_ORIG_SLANT_FACE(face)  (((face)&2)==0)
  6996.  
  6997. /*
  6998.  * fe_UnicodeFindFontInRange
  6999.  *
  7000.  * find the font for this encoding with the UnicodePseudoFont's 
  7001.  *   specified font name / slant / weight
  7002.  *   no scaling
  7003.  *   size range = minPixelSize to maxPixelSize
  7004.  *   either pitch
  7005.  */
  7006. static XFontStruct *
  7007. fe_UnicodeFindFontInRange(fe_UnicodePseudoFont *ufont, uint16 charsetID,
  7008.                     int32 maxPixelSize, int32 minPixelSize, XP_Bool any_weight,
  7009.                     char **name)
  7010. {
  7011.     int pitch, i_pitch, i_pnt;
  7012.     fe_FontSize *size;
  7013.     fe_FontFamily *fontFamily;
  7014.     char *family;
  7015.     int bestFoundQ = 0;
  7016.     int thisFontQ;
  7017.     int bestFoundFaceNum;
  7018.     fe_FontSize *bestFoundSize = NULL;
  7019.  
  7020.     /*
  7021.      * Get the equivalent font name for this encoding
  7022.      */
  7023.     family = fe_UnicodeEquivFontName(ufont, charsetID);
  7024.  
  7025.     /*
  7026.      * Find the font
  7027.      */
  7028.     for (i_pitch=0; i_pitch<2; i_pitch++) {
  7029.         if (IS_ORIG_PITCH(i_pitch))
  7030.             pitch = ufont->pitch;
  7031.         else
  7032.             pitch = FE_OPPOSITE_PITCH(ufont->pitch);
  7033.         fontFamily = fe_FontFindFamily(charsetID, pitch, family);
  7034.         if (fontFamily == NULL)
  7035.             continue;
  7036.         /* scan pixel sizes for largest size that is not too big */
  7037.         for (i_pnt=fontFamily->numberOfPixelSizes-1; i_pnt>=0; i_pnt--) {
  7038.             size = &fontFamily->pixelSizes[i_pnt];
  7039.             /* stop when sizes are too small */
  7040.             if (size->size<minPixelSize)
  7041.                 break;
  7042.             if (size->size>=maxPixelSize) 
  7043.                 ufont->larger_fonts_avail[charsetID] = TRUE;
  7044.             if ((size->size>=minPixelSize) && (size->size<=maxPixelSize)) {
  7045.                 int i_face, faceNum;
  7046.                 for (i_face=0; i_face<2; i_face++) {
  7047.                     if (IS_ORIG_WEIGHT_FACE(i_face))
  7048.                         faceNum = ufont->faceNum;
  7049.                     else {
  7050.                         if (!any_weight)
  7051.                             continue;
  7052.                         faceNum = FE_OPPOSITE_WEIGHT_FACE(ufont->faceNum);
  7053.                     }
  7054.                     /* load font if necessary */
  7055.                     if (!size->faces[faceNum]) 
  7056.                            continue;
  7057.                     thisFontQ = fe_UnicodeFontQ(ufont, 
  7058.                                         maxPixelSize, size->size,
  7059.                                         /* family_match */
  7060.                                         TRUE,
  7061.                                         IS_ORIG_WEIGHT_FACE(i_face),
  7062.                                         TRUE,
  7063.                                         ufont->pitch, IS_ORIG_PITCH(i_pitch));
  7064.                     if (thisFontQ > bestFoundQ) {
  7065.                         bestFoundQ = thisFontQ;
  7066.                         bestFoundSize = size;
  7067.                         bestFoundFaceNum = faceNum;
  7068.                     }
  7069.                 }
  7070.             }
  7071.         }
  7072.     }
  7073.     if (bestFoundSize != NULL) {
  7074.         if (!bestFoundSize->faces[bestFoundFaceNum]->loaded) {
  7075.             bestFoundSize->faces[bestFoundFaceNum]->loaded = TRUE;
  7076.             bestFoundSize->faces[bestFoundFaceNum]->font = 
  7077.                 fe_LoadXFont(ufont->dpy,
  7078.                       bestFoundSize->faces[bestFoundFaceNum]->longXLFDFontName);
  7079.         }
  7080.         if (bestFoundSize->faces[bestFoundFaceNum]->font) {
  7081.             *name = bestFoundSize->faces[bestFoundFaceNum]->longXLFDFontName;
  7082.             return bestFoundSize->faces[bestFoundFaceNum]->font;
  7083.         }
  7084.     }
  7085.     *name = "";
  7086.     return NULL;
  7087. }
  7088.  
  7089.  
  7090. /*
  7091.  * fe_UnicodeFindFontSloppy
  7092.  *
  7093.  * find the font for this encoding with the UnicodePseudoFont's 
  7094.  *   ANY FAMILY
  7095.  */
  7096. static XFontStruct *
  7097. fe_UnicodeFindFontSloppy(fe_UnicodePseudoFont *ufont, uint16 charsetID,
  7098.                           int32 maxPixelSize, int32 minPixelSize,
  7099.                           XP_Bool allow_scaling, 
  7100.               XP_Bool any_weight, XP_Bool any_slant,
  7101.               char **name)
  7102. {
  7103.     int i_family, i_pitch, i_pnt, i_face;
  7104.     fe_FontPitch *fontPitch;
  7105.     fe_FontSize *size = NULL;
  7106.     fe_FontFamily *fontFamily = NULL;
  7107.     fe_FontCharSet    *fontCharset;
  7108.     XFontStruct *scaled_font;
  7109.     fe_FontSize *bestFoundSize = NULL;
  7110.     fe_FontFamily *bestFontFamily = NULL;
  7111.     int bestFoundQ = 0;
  7112.     int thisFontQ;
  7113.     int bestFoundFaceNum = 0;
  7114.     fe_FontFamily *targetFontFamily;
  7115.     char *targetFamily;
  7116.  
  7117.     if (minPixelSize < 1)
  7118.         minPixelSize = 1;
  7119.  
  7120.     fontCharset = &fe_FontCharSets[charsetID];
  7121.     /*
  7122.      * Get the equivalent font name for this encoding
  7123.      */
  7124.     targetFamily = fe_UnicodeEquivFontName(ufont, charsetID);
  7125.  
  7126.     /*
  7127.      * Find the font
  7128.      */
  7129.     for (i_pitch=0; i_pitch<2; i_pitch++) {
  7130.         if IS_ORIG_PITCH(i_pitch) {
  7131.             fontPitch = &fontCharset->pitches[ufont->pitch];
  7132.             targetFontFamily = fe_FontFindFamily(charsetID, 
  7133.                                         ufont->pitch, targetFamily);
  7134.         }
  7135.         else {
  7136.             fontPitch = &fontCharset->pitches[FE_OPPOSITE_PITCH(ufont->pitch)];
  7137.             targetFontFamily = fe_FontFindFamily(charsetID, 
  7138.                                 FE_OPPOSITE_PITCH(ufont->pitch), targetFamily);
  7139.         }
  7140.         for (i_family = 0; i_family < fontPitch->numberOfFamilies; i_family++) {
  7141.             fontFamily = &fontPitch->families[i_family];
  7142.             for (i_pnt=fontFamily->numberOfPixelSizes-1; i_pnt>=0; i_pnt--) {
  7143.                 size = &fontFamily->pixelSizes[i_pnt];
  7144.                 if ((charsetID==CS_LATIN1) 
  7145.                     && (size->size) && (size->size < smallestFontFoundSize))
  7146.                     smallestFontFoundSize = size->size;
  7147.                 /* skip sizes that are too small */
  7148.                 if ((size->size) && (size->size<minPixelSize))
  7149.                     continue;
  7150.                 if (size->size>=maxPixelSize) 
  7151.                     ufont->larger_fonts_avail[charsetID] = TRUE;
  7152.                 if (((size->size>=minPixelSize) && (size->size<=maxPixelSize))
  7153.                     || (allow_scaling && (size->size == 0))) {
  7154.                     int32 target_size;
  7155.                     for (i_face=0; i_face<4; i_face++) {
  7156.                         int faceNum = ufont->faceNum;
  7157.                         if (!IS_ORIG_WEIGHT_FACE(i_face)) {
  7158.                             if (!any_weight)
  7159.                                 continue;
  7160.                             faceNum = FE_OPPOSITE_WEIGHT_FACE(faceNum);
  7161.                         }
  7162.                         if (!IS_ORIG_SLANT_FACE(i_face)) {
  7163.                             if (!any_slant)
  7164.                                 continue;
  7165.                             faceNum = FE_OPPOSITE_SLANT_FACE(faceNum);
  7166.                         }
  7167.                         if (!size->faces[faceNum])
  7168.                             continue;
  7169.                         if (size->size) /* not scaled */
  7170.                             target_size = size->size;
  7171.                         else
  7172.                             target_size = maxPixelSize;
  7173.                         thisFontQ = fe_UnicodeFontQ(ufont, 
  7174.                                         maxPixelSize, target_size,
  7175.                                         /* family_match */
  7176.                                         (targetFontFamily==fontFamily),
  7177.                                         IS_ORIG_WEIGHT_FACE(i_face),
  7178.                                         IS_ORIG_SLANT_FACE(i_face),
  7179.                                         ufont->pitch, IS_ORIG_PITCH(i_pitch));
  7180.                         if (thisFontQ > bestFoundQ) {
  7181.                             bestFoundQ = thisFontQ;
  7182.                             bestFoundSize = size;
  7183.                             bestFoundFaceNum = faceNum;
  7184.                             bestFontFamily = fontFamily;
  7185.                         }
  7186.                     }
  7187.                 }
  7188.             }
  7189.         }
  7190.     }
  7191.     if (bestFoundSize != NULL) {
  7192.         /* load font if necessary */
  7193.         if (bestFoundSize->size) {
  7194.             if (!bestFoundSize->faces[bestFoundFaceNum]->loaded) {
  7195.                 bestFoundSize->faces[bestFoundFaceNum]->loaded = TRUE;
  7196.                 bestFoundSize->faces[bestFoundFaceNum]->font = 
  7197.                             fe_LoadXFont(ufont->dpy, 
  7198.                     bestFoundSize->faces[bestFoundFaceNum]->longXLFDFontName);
  7199.             }
  7200.             if (bestFoundSize->faces[bestFoundFaceNum]->font)
  7201.                 *name = bestFoundSize->faces[bestFoundFaceNum]->longXLFDFontName;
  7202.                 return bestFoundSize->faces[bestFoundFaceNum]->font;
  7203.             }
  7204.         else if (allow_scaling) {
  7205.             *name = PR_smprintf(bestFontFamily->pixelSizes->faces[
  7206.                       bestFoundFaceNum]->longXLFDFontName, maxPixelSize);
  7207.             scaled_font = fe_LoadXFont(ufont->dpy, *name);
  7208.             if (scaled_font)
  7209.                 return scaled_font;
  7210.             else
  7211.                 XP_FREE(*name);
  7212.         }
  7213.     }
  7214.  
  7215.     *name = "";
  7216.     return NULL;
  7217. }
  7218.  
  7219. /*
  7220.  * fe_UnicodeFindFontScaled
  7221.  *
  7222.  * find the font for this encoding with the UnicodePseudoFont's 
  7223.  *   specified font name / slant / weight
  7224.  *   scaled font
  7225.  *   either pitch
  7226.  */
  7227. static XFontStruct *
  7228. fe_UnicodeFindFontScaled(fe_UnicodePseudoFont *ufont, uint16 charsetID,
  7229.                         int32 maxPixelSize, char **name)
  7230. {
  7231.     int pitch, i_pitch, i_face;
  7232.     char *family;
  7233.     fe_FontFamily *fontFamily;
  7234.     XFontStruct *scaled_font;
  7235.     fe_FontFamily *bestFontFamily = NULL;
  7236.     int bestFoundQ = 0;
  7237.     int thisFontQ;
  7238.     int bestFoundFaceNum = 0;
  7239.  
  7240.     /*
  7241.      * Get the equivalent font name for this encoding
  7242.      */
  7243.     family = fe_UnicodeEquivFontName(ufont, charsetID);
  7244.     for (i_pitch=0; i_pitch<2; i_pitch++) {
  7245.         if (IS_ORIG_PITCH(i_pitch))
  7246.             pitch = ufont->pitch;
  7247.         else
  7248.             pitch = FE_OPPOSITE_PITCH(ufont->pitch);
  7249.         fontFamily = fe_FontFindFamily(charsetID, pitch, family);
  7250.         if (fontFamily == NULL)
  7251.             continue;
  7252.         if (fontFamily->pixelSizes->size == 0)  {
  7253.             int faceNum;
  7254.             for (i_face=0; i_face<2; i_face++) {
  7255.                 if (IS_ORIG_WEIGHT_FACE(i_face))
  7256.                     faceNum = ufont->faceNum;
  7257.                 else
  7258.                     faceNum = FE_OPPOSITE_WEIGHT_FACE(ufont->faceNum);
  7259.                 if (!fontFamily->pixelSizes->faces[faceNum])
  7260.                     continue;
  7261.                 thisFontQ = fe_UnicodeFontQ(ufont, 
  7262.                                         maxPixelSize, maxPixelSize,
  7263.                                         TRUE, /* family_match */
  7264.                                         IS_ORIG_WEIGHT_FACE(i_face),
  7265.                                         TRUE, /* slant_match */
  7266.                                         ufont->pitch, IS_ORIG_PITCH(i_pitch));
  7267.                 if (thisFontQ > bestFoundQ) {
  7268.                     bestFoundQ = thisFontQ;
  7269.                     bestFoundFaceNum = faceNum;
  7270.                     bestFontFamily = fontFamily;
  7271.                 }
  7272.             }
  7273.         }
  7274.     }
  7275.     if (bestFontFamily != NULL) {
  7276.         *name = PR_smprintf(bestFontFamily->pixelSizes->faces[
  7277.                               bestFoundFaceNum]->longXLFDFontName,
  7278.                               maxPixelSize);
  7279.         scaled_font = fe_LoadXFont(ufont->dpy, *name);
  7280.         if (scaled_font)
  7281.             return scaled_font;
  7282.         else
  7283.             XP_FREE(*name);
  7284.     }
  7285.     *name = "";
  7286.     return NULL;
  7287. }
  7288.  
  7289. static XP_Bool
  7290. fe_UnicodeCheckAllowScaling(fe_UnicodePseudoFont *ufont)
  7291. {
  7292.     XP_Bool allow_scaling;
  7293.     fe_FontFamily *unicodeFamily;
  7294.     char *server_vendor;
  7295.     static XP_Bool inited_server_info = FALSE;
  7296.     static XP_Bool is_hp_server = FALSE;
  7297.     static XP_Bool allow_hp_scaling = FALSE;
  7298.     char name[512], class[512];
  7299.     char *type;
  7300.     XrmValue value;
  7301.  
  7302.     /*
  7303.      * When displaying on a HP system do not scale.
  7304.      *
  7305.      * HP scaling causes the X server to "freeze"
  7306.      * which makes the system unusable.
  7307.      * Mouse delays of 20+ seconds make it very 
  7308.      * difficult to even exit the application.
  7309.      */
  7310.     if (!inited_server_info) {
  7311.         inited_server_info = TRUE;
  7312.         server_vendor = ServerVendor(ufont->dpy);
  7313.         if (strstr(server_vendor, "Hewlett-Packard")) {
  7314.             is_hp_server = TRUE;
  7315.         }
  7316.         /*
  7317.          * Get the users resource setting
  7318.          */
  7319.         (void) PR_snprintf(name, sizeof(name), "%s.unicodeFont.allowHPScaling", 
  7320.                         fe_progclass);
  7321.         (void) PR_snprintf(class, sizeof(class),"%s.UnicodeFont.AllowHPScaling",
  7322.                         fe_progclass);
  7323.         if (XrmGetResource(XtDatabase(ufont->dpy), name, class, &type, &value)){
  7324.             char *string = (char *)value.addr;
  7325.             if ((string[0]=='y') || (string[0]=='Y')
  7326.                 || (string[0]=='t') || (string[0]=='T')
  7327.                 || (string[0]=='1'))
  7328.                 allow_hp_scaling = TRUE;
  7329.             else
  7330.                 allow_hp_scaling = FALSE;
  7331.         }
  7332.     }
  7333.     if ((is_hp_server) && (!allow_hp_scaling))
  7334.         return FALSE;
  7335.  
  7336.     unicodeFamily = fe_GetFontFamily(CS_UTF8, ufont->pitch);
  7337.     allow_scaling = unicodeFamily->allowScaling;
  7338.     return allow_scaling;
  7339. }
  7340.  
  7341. static XFontStruct *
  7342. fe_UnicodeFindFont(fe_UnicodePseudoFont *ufont, uint16 encoding, 
  7343.                                                        XP_Bool *is_scaled,
  7344.                                                        char **name)
  7345. {
  7346.     uint16 charsetID;
  7347.     fe_FontCharSet    *fontCharset;
  7348.     int loop_timeout;
  7349.     int32 maxPixelSize;
  7350.     XFontStruct *ret_font, *scaled_font = NULL;
  7351.     XP_Bool allow_scaling;
  7352.  
  7353.     /* printf("encoding = %d (%d), pixelSize = %d, pitch = %d, faceNum = %d\n",
  7354.                 encoding, encoding&0xFF, ufont->pixelSize, 
  7355.                 ufont->pitch, ufont->faceNum); */
  7356.     /*
  7357.      * Init return value
  7358.      */
  7359.     *is_scaled = FALSE;
  7360.  
  7361.     /*
  7362.      * Check the encoding
  7363.      */
  7364.     charsetID = encoding & 0xFF;
  7365.     fontCharset = &fe_FontCharSets[charsetID];
  7366.     if (!fontCharset->name) {
  7367.         return NULL;
  7368.     }
  7369.  
  7370.     maxPixelSize = ufont->pixelSize;
  7371.     allow_scaling = fe_UnicodeCheckAllowScaling(ufont);
  7372.  
  7373.     /*
  7374.      * Get the best font for this size and encoding
  7375.      *
  7376.      * We loop looking for a font that will fit
  7377.      *  The reason for the loop is that after we load the font it is
  7378.      *  possible that the ascent or descent is too large.
  7379.      *  If this happens we reduce the size by that amount and try again.
  7380.      *
  7381.      * The loop count is large because:
  7382.      *  If we can only find a bestfit that is small
  7383.      *  and this bestfit is still larger than the desired size
  7384.      *  then we end up running thru the loop while maxPixelSize is reduced
  7385.      *  to the pixel that bestfit is small enough.
  7386.      *  This tends to not be efficient since the bestfit font
  7387.      *  is only loaded once.
  7388.      */
  7389. #define LOOP_TIMEOUT 100
  7390.     scaled_font = NULL;
  7391.     for (loop_timeout=0; loop_timeout<LOOP_TIMEOUT; loop_timeout++) {
  7392.         if (scaled_font != NULL) {
  7393.             XFreeFont(ufont->dpy, scaled_font);
  7394.             XP_FREE(*name);
  7395.             *name = "";
  7396.             scaled_font = NULL;
  7397.         }
  7398.  
  7399.         /*
  7400.          * Exact Fit (non scaled)
  7401.          * try to find:
  7402.          * the family with this size range: 100% - 95%
  7403.          * no scaling
  7404.          * correct pitch/weight/slant
  7405.          * then try the other pitch
  7406.          */
  7407.         ret_font = fe_UnicodeFindFontInRange(ufont, charsetID, 
  7408.                                         maxPixelSize, 0.95*maxPixelSize, FALSE,
  7409.                                         name);
  7410.         if (ret_font) {
  7411.             loop_timeout += LOOP_TIMEOUT/10 - 1;
  7412.             goto UnicodeFindFont_foundOne;
  7413.         }
  7414.  
  7415.         /*
  7416.          * Exact Fit (scaled)
  7417.          * try to find:
  7418.          * the family with the SCALED SIZE
  7419.          * (X bitmap scaled fonts typically look bad)
  7420.          * correct slant
  7421.          * ANY PITCH / ANY WEIGHT
  7422.          */
  7423.         if (allow_scaling) {
  7424.             scaled_font = fe_UnicodeFindFontScaled(ufont, charsetID, 
  7425.                                                 maxPixelSize, name);
  7426.             if (scaled_font) {
  7427.                 loop_timeout += LOOP_TIMEOUT/5 - 1;
  7428.                 ret_font = scaled_font;
  7429.                 goto UnicodeFindFont_foundOne;
  7430.             }
  7431.         }
  7432.     
  7433.         /*
  7434.          * Close Fit (non scaled)
  7435.          * try to find:
  7436.          * the family with this size range: 100% - 75%
  7437.          * no scaling
  7438.          * correct slant
  7439.          * ANY_WEIGHT / ANY PITCH
  7440.          */
  7441.         ret_font = fe_UnicodeFindFontInRange(ufont, charsetID, 
  7442.                                         maxPixelSize, 0.75*maxPixelSize, TRUE,
  7443.                                         name);
  7444.         if (ret_font) {
  7445.             loop_timeout += LOOP_TIMEOUT/10 - 1;
  7446.             goto UnicodeFindFont_foundOne;
  7447.         }
  7448.  
  7449.         /*
  7450.          * Okay Fit (any family)
  7451.          * try to find:
  7452.          * size range: 100% - 75%
  7453.          * correct slant
  7454.          * ANY FAMILY / ANY WEIGHT / ANY PITCH
  7455.          */
  7456.         ret_font = fe_UnicodeFindFontSloppy(ufont, charsetID, 
  7457.                          maxPixelSize, 0.75*maxPixelSize, 
  7458.                          allow_scaling, TRUE, FALSE,
  7459.                          name);
  7460.         if (ret_font) {
  7461.             loop_timeout += LOOP_TIMEOUT/10 - 1;
  7462.             goto UnicodeFindFont_foundOne;
  7463.         }
  7464.     
  7465.         /*
  7466.          * Loose Fit (non scaled)
  7467.          * try to find:
  7468.          * size range: 100% - 50%
  7469.          * ANY FAMILY / ANY WEIGHT / ANY PITCH / ANY SLANT
  7470.          */
  7471.         ret_font = fe_UnicodeFindFontSloppy(ufont, charsetID, 
  7472.                                 maxPixelSize, 0.50*maxPixelSize, 
  7473.                                 allow_scaling, TRUE, TRUE,
  7474.                                 name);
  7475.         if (ret_font) {
  7476.             loop_timeout += LOOP_TIMEOUT/10 - 1;
  7477.             goto UnicodeFindFont_foundOne;
  7478.         }
  7479.     
  7480.         /*
  7481.          * Any fit
  7482.          * try to find:
  7483.          * ANY SIZE / ANY FAMILY / ANY WEIGHT / ANY PITCH / ANY SLANT
  7484.          */
  7485.         ret_font = fe_UnicodeFindFontSloppy(ufont, charsetID, 
  7486.                                 maxPixelSize, 0.0*maxPixelSize,
  7487.                                 allow_scaling, TRUE, TRUE,
  7488.                                 name);
  7489.         if (ret_font) {
  7490.             loop_timeout += LOOP_TIMEOUT/10 - 1;
  7491.             goto UnicodeFindFont_foundOne;
  7492.         }
  7493.  
  7494.         /* 
  7495.          * HUM ..., 
  7496.          * must not be a font small enough
  7497.          * in desperation we give them a real small font.
  7498.          */
  7499.         ret_font = fe_UnicodeFindFontSloppy(ufont, CS_LATIN1, 
  7500.                                 smallestFontFoundSize, 0.0*maxPixelSize,
  7501.                                 allow_scaling, TRUE, TRUE,
  7502.                                 name);
  7503.         if (ret_font) {
  7504.             loop_timeout += LOOP_TIMEOUT/10 - 1;
  7505.             goto UnicodeFindFont_foundOne;
  7506.         }
  7507.     
  7508.         /*
  7509.          * Gave up trying to find a font that will fit
  7510.          */
  7511.         goto UnicodeFindFont_failed;
  7512.  
  7513.  
  7514. UnicodeFindFont_foundOne:
  7515.         /*
  7516.          * if encoding is CS_LATIN1 use the font
  7517.          * else check that the font will fit
  7518.          */
  7519.         if ((encoding==CS_LATIN1) && (ufont->ascent==0) && (ufont->descent==0)){
  7520.             if ((ufont->pixelSize/10) > (ret_font->ascent+ret_font->descent))
  7521.                 ret_font->ascent = (ufont->pixelSize/10) - ret_font->descent;
  7522.             ufont->ascent  = ret_font->ascent;
  7523.             ufont->descent = ret_font->descent;
  7524.         }
  7525.         else {
  7526.             if (ret_font->ascent > ufont->ascent) {
  7527.                 /* printf("ascent too big (%d), reduce by %d\n",
  7528.                         ufont->pixelSize, ret_font->ascent - ufont->ascent); */
  7529.                 maxPixelSize -= (ret_font->ascent - ufont->ascent) * 10;
  7530.                 if (maxPixelSize > 20) /* continue unless something wrong */
  7531.                     continue;
  7532.             }
  7533.             if (ret_font->descent > ufont->descent) {
  7534.                 /* printf("descent too big (%d), reduce by %d\n",
  7535.                                     ret_font->descent - ufont->descent); */
  7536.                 maxPixelSize -= (ret_font->descent - ufont->descent) * 10;
  7537.                 if (maxPixelSize > 20) /* continue unless something wrong */
  7538.                     continue;
  7539.             }
  7540.         }
  7541.         if (scaled_font != NULL)
  7542.             *is_scaled = TRUE;
  7543.         return ret_font;
  7544.     }
  7545. UnicodeFindFont_failed:
  7546.     /*
  7547.      * did not find any fit
  7548.      */
  7549.     if (encoding == CS_LATIN1) {
  7550.         /* if we got here something is wrong with fonts */
  7551.         XFontStruct *xfont = (XFontStruct *)fe_FixedFont;
  7552.         ufont->ascent = xfont->ascent;
  7553.         ufont->descent = xfont->descent;
  7554.         return fe_FixedFont;
  7555.     }
  7556.     return NULL;
  7557. }
  7558.  
  7559. static XFontStruct *
  7560. fe_UnicodeInitXfont(fe_UnicodePseudoFont *ufont, uint16 encoding)
  7561. {
  7562.     XmFontListEntry flentry;
  7563.     uint16 charset = encoding&0xFF;
  7564.  
  7565.     if (ufont->tag != UNICODE_PSEUDO_FONT_TAG) {
  7566. #ifdef DEBUG_bstell
  7567.         printf("bad ufont %s %d\n", __FILE__, __LINE__);
  7568. #endif
  7569.                 return fe_FixedFont; /* fallback */
  7570.     }
  7571.  
  7572.    /*
  7573.     * Time to load the font
  7574.     */
  7575.     ufont->xfont_inited[charset] = TRUE;
  7576.     ufont->xFonts[charset] = fe_UnicodeFindFont(ufont, encoding, 
  7577.                                     &ufont->xfont_scaled[charset],
  7578.                                     &ufont->xfont_name[charset]);
  7579.     /*
  7580.      * Add this font to the XmFontList
  7581.      */
  7582.     if (ufont->xFonts[charset]) {
  7583.         flentry = XmFontListEntryCreate(INTL_CsidToCharsetNamePt(encoding), 
  7584.                                        XmFONT_IS_FONT, ufont->xFonts[charset]);
  7585.         ufont->xmfontlist = XmFontListAppendEntry(ufont->xmfontlist, flentry);
  7586.         XmFontListEntryFree(&flentry);
  7587.     }
  7588.     return ufont->xFonts[charset];
  7589. }
  7590.  
  7591. XFontStruct *
  7592. fe_UnicodeGetXfont(fe_UnicodePseudoFont *ufont, uint16 encoding)
  7593. {
  7594.     uint16 charset = encoding&0xFF;
  7595.  
  7596.     if (ufont->tag != UNICODE_PSEUDO_FONT_TAG) {
  7597. #ifdef DEBUG_bstell
  7598.         printf("bad ufont %s %d\n", __FILE__, __LINE__);
  7599. #endif
  7600.                 return fe_FixedFont; /* fallback */
  7601.     }
  7602.  
  7603.     /*
  7604.      * If the xfont is already there return it
  7605.      */
  7606.     if (ufont->xfont_inited[charset])
  7607.         return ufont->xFonts[charset];
  7608.  
  7609.     /*
  7610.      * Make sure CS_LATIN1 loaded so the
  7611.      * ascender/descender info is set
  7612.      */
  7613.     if (encoding != CS_LATIN1) {
  7614.         if (ufont->xfont_inited[CS_LATIN1] == FALSE)
  7615.                         fe_UnicodeInitXfont(ufont, CS_LATIN1);
  7616.     }
  7617.  
  7618.     /*
  7619.      * Load the font
  7620.      */
  7621.     fe_UnicodeInitXfont(ufont, encoding);
  7622.     return ufont->xFonts[charset];
  7623. }
  7624.  
  7625. XmFontList 
  7626. XUPF_GetXmFontList(fe_Font font)
  7627. {
  7628.     fe_UnicodePseudoFont *ufont = (fe_UnicodePseudoFont *)font;
  7629.  
  7630.     if ((ufont==NULL) || (ufont->tag != UNICODE_PSEUDO_FONT_TAG)) {
  7631.         return NULL;
  7632.     }
  7633.     return ufont->xmfontlist;
  7634. }
  7635.  
  7636. /*
  7637.  * create a XmFontList with one XFontSet for XmText widgets
  7638.  * since they can only handle a single locale.
  7639.  */
  7640. XmFontList 
  7641. XUPF_GetXmFontSet(fe_Font font)
  7642. {
  7643.     fe_UnicodePseudoFont *ufont = (fe_UnicodePseudoFont *)font;
  7644.     int16 *csidList;
  7645.     int i;
  7646.     char *fontNameList = NULL;
  7647.     char **missingCharSets;
  7648.     int missingCharSetCount;
  7649.     char *missingCharString;
  7650.     XmFontListEntry flentry;
  7651.  
  7652.  
  7653.     /* check for bad inputs */
  7654.     if ((ufont==NULL) || (ufont->tag != UNICODE_PSEUDO_FONT_TAG)) {
  7655.         return NULL;
  7656.     }
  7657.  
  7658.     /* if it has already been created just use it */
  7659.     if (ufont->xm_fontset)
  7660.         return ufont->xm_fontset;
  7661.  
  7662.    /*
  7663.     * get the list of charset we need
  7664.     */
  7665.     csidList = INTL_GetXCharSetIDs(ufont->dpy);
  7666.     if (csidList == NULL)
  7667.         return NULL;
  7668.  
  7669.    /*
  7670.     * build the list of fontSet names
  7671.     */
  7672.     for( i=0; csidList[i] != 0; i++ ) {
  7673.         char *fontName;
  7674.         char *newFontNameList;
  7675.         (void)fe_UnicodeGetXfont(ufont, csidList[i]);
  7676.         fontName = ufont->xfont_name[csidList[i]&0xff];
  7677.  
  7678.         if ((fontName==NULL) || (strlen(fontName)==0)) {
  7679.             continue;
  7680.         }
  7681.  
  7682.         if (fontNameList == NULL)
  7683.             newFontNameList = strdup(fontName);
  7684.         else
  7685.             newFontNameList = PR_smprintf("%s,\n%s", fontNameList, fontName);
  7686.  
  7687.         if (!newFontNameList) {
  7688.             continue;
  7689.         }
  7690.         if (fontNameList != NULL)
  7691.             free(fontNameList);
  7692.         fontNameList = newFontNameList;
  7693.     }
  7694.     free(csidList);
  7695.  
  7696.    /*
  7697.     * create the XFontSet
  7698.     */
  7699.     ufont->xfontset = XCreateFontSet(ufont->dpy, fontNameList, &missingCharSets,
  7700.                           &missingCharSetCount, &missingCharString);
  7701.  
  7702.     flentry = XmFontListEntryCreate(XmFONTLIST_DEFAULT_TAG, XmFONT_IS_FONTSET,
  7703.                                         ufont->xfontset);
  7704.     ufont->xm_fontset = XmFontListAppendEntry(NULL, flentry);
  7705.     XmFontListEntryFree(&flentry);
  7706.     return ufont->xm_fontset;
  7707.  
  7708. }
  7709.  
  7710. int
  7711. XUPF_JavaPointToPixelSize(Display *dpy, int pointSize)
  7712. {
  7713.     static XP_Bool inited = FALSE;
  7714.     static XP_Bool use_point_sizing;
  7715.     static double pointToPixelFactor = (72.27/72.27)/10;
  7716.     char name[512], class[512];
  7717.     char *type;
  7718.     XrmValue value;
  7719.  
  7720.     if (!inited) {
  7721.         inited = TRUE;
  7722.         /*
  7723.          * Get the users resource setting
  7724.          */
  7725.         (void) PR_snprintf(name, sizeof(name), "%s.javaFont.usePointSizing", 
  7726.                         fe_progclass);
  7727.         (void) PR_snprintf(class, sizeof(class),"%s.JavaFont.UsePointSizing",
  7728.                         fe_progclass);
  7729.         if (XrmGetResource(XtDatabase(dpy), name, class, &type, &value)){
  7730.             char *string = (char *)value.addr;
  7731.             if ((string[0]=='y') || (string[0]=='Y')
  7732.                 || (string[0]=='t') || (string[0]=='T')
  7733.                 || (string[0]=='1'))
  7734.                 use_point_sizing = TRUE;
  7735.             else
  7736.                 use_point_sizing = FALSE;
  7737.         }
  7738.         (void) PR_snprintf(name, sizeof(name), "%s.javaFont.screenDpi", 
  7739.                         fe_progclass);
  7740.         (void) PR_snprintf(class, sizeof(class),"%s.JavaFont.ScreenDpi",
  7741.                         fe_progclass);
  7742.         if (XrmGetResource(XtDatabase(dpy), name, class, &type, &value)){
  7743.             float userScreenDpi;
  7744.             if (sscanf((char *)value.addr, "%e", &userScreenDpi)) {
  7745.                 pointToPixelFactor = (userScreenDpi/72.27)/10;
  7746.             }
  7747.         }
  7748.     }
  7749.     if (use_point_sizing)
  7750.         return (fe_UnicodePointToPixelSize(dpy, pointSize));
  7751.     else {
  7752.         pointSize += 4; /* round up */
  7753.         return (int)(pointSize * pointToPixelFactor);
  7754.     }
  7755. }
  7756.  
  7757. void
  7758. fe_UnicodeConvertToPlaceHolder(fe_UnicodePseudoFont *ufont, 
  7759.                         int16 *encoding, XFontStruct **xfont,
  7760.                         unsigned char *segment, int seg_data_len)
  7761. {
  7762.     /* unsigned char c; */
  7763.     int i;
  7764.  
  7765.     /*
  7766.      * Handle errors
  7767.      */
  7768. #if 0
  7769.     if (*encoding == -1) /* not utf8 */
  7770.         c = '?';
  7771.     else if (!*xfont) /* only bigger fonts available */
  7772.         c = '?';
  7773.     else /* no font at all for this encoding */
  7774.         c = '?';
  7775. #endif /* 0 */
  7776.     for (i=0; i< seg_data_len; i++) {
  7777.         segment[i] = ((unsigned char) '?') /* c */;
  7778.     }
  7779.     *encoding = CS_LATIN1;
  7780.     *xfont = fe_UnicodeGetXfont(ufont, CS_LATIN1);
  7781. }
  7782.  
  7783. /*
  7784.  * fe_UTF8TextExtents - Get the Text Extents for a UTF8 Unicode string
  7785.  *
  7786.  * Parse the string into locally displayable encoded segments
  7787.  * and sum up the extents for the segments
  7788.  *
  7789.  * If there are errors dummy up some space for those characters
  7790.  * so we can display something.
  7791.  * hopefully the user will see the garbage and try a different encoding
  7792.  */
  7793. void
  7794. fe_UTF8TextExtents(fe_Font font, char *string, int len, int *direction,
  7795.     int *fontAscent, int *fontDescent, XCharStruct *overall)
  7796. {
  7797.     fe_UnicodePseudoFont *ufont = (fe_UnicodePseudoFont *)font;
  7798.     unsigned char segment[X11STRING_LIMIT*6];
  7799.     int16 encoding;
  7800.     int parsed_cnt = 0;
  7801.     int this_parsed_cnt, seg_data_len;
  7802.     int ascent, descent, this_direction;
  7803.     Dimension width;
  7804.     XFontStruct *xfont;
  7805.     XCharStruct this_overall;
  7806.  
  7807.  
  7808.     if ((ufont==NULL) || (ufont->tag != UNICODE_PSEUDO_FONT_TAG)) {
  7809.         /* something is wrong. I will just return a guess */
  7810.         overall->ascent = *fontAscent = 14;
  7811.         overall->descent = *fontDescent = 3;
  7812.         overall->lbearing = 0;
  7813.         overall->rbearing = 0;
  7814.         overall->width = len*9;
  7815.         return;
  7816.     }
  7817.  
  7818.     /*
  7819.      * initialize the values
  7820.      */
  7821.     *fontAscent = 0;
  7822.     *fontDescent = 0;
  7823.     overall->lbearing = 0;
  7824.     overall->rbearing = 0;
  7825.     overall->width = 0;
  7826.     overall->ascent = 0;
  7827.     overall->descent = 0;
  7828.  
  7829.     /*
  7830.      * Break up the unicode string into locally sizeable encoded segments
  7831.      */
  7832.     ascent = 0;
  7833.     descent = 0;
  7834.     width = 0;
  7835.     while (1) {
  7836.         /* get a single encoding string */
  7837.         this_parsed_cnt = utf8_to_local_encoding(string+parsed_cnt, 
  7838.                                         len-parsed_cnt, 
  7839.                                         segment, sizeof(segment),
  7840.                                         &seg_data_len, &encoding);
  7841.         if (this_parsed_cnt < 1) /* no more input data */
  7842.             break;
  7843.  
  7844.         /*
  7845.          * Get the font for this segment
  7846.          */
  7847.         if (encoding >= 0)
  7848.             xfont = fe_UnicodeGetXfont(ufont, encoding);
  7849.         else
  7850.             xfont = NULL;
  7851.  
  7852.         /*
  7853.          * Handle errors
  7854.          */
  7855.         if ((encoding < 0) || (!xfont)) {
  7856.             fe_UnicodeConvertToPlaceHolder(ufont, &encoding, &xfont,
  7857.                             segment, seg_data_len);
  7858.         }
  7859.  
  7860.         /*
  7861.          * Get the size metrics for this segment
  7862.          */
  7863.         if (IS_16BIT_ENCODING(encoding)) {
  7864.             XTextExtents16(xfont, (XChar2b*)segment, seg_data_len/2,
  7865.                 &this_direction, &ascent, &descent, &this_overall);
  7866.         }
  7867.         else {
  7868.             XTextExtents(xfont, segment, seg_data_len,
  7869.                 &this_direction, &ascent, &descent, &this_overall);
  7870.         }
  7871.  
  7872.         /*
  7873.          * sum up the width so far
  7874.          * height (ascent/descent) comes from the theoritical size
  7875.          */
  7876.         parsed_cnt += this_parsed_cnt;
  7877.         *direction = this_direction; /* which segment should I use ? */
  7878.         if ((this_overall.lbearing+overall->width) < overall->lbearing)
  7879.             overall->lbearing = this_overall.lbearing + overall->width;
  7880.         overall->width += this_overall.width;
  7881.         overall->rbearing += this_overall.rbearing;
  7882.     }
  7883.  
  7884.     /*
  7885.      * Set the height from the theoritical size
  7886.      */
  7887.     *fontAscent  = ufont->ascent;
  7888.     *fontDescent = ufont->descent + 1;
  7889.     overall->ascent = ufont->ascent;
  7890.     overall->descent = ufont->descent + 1;
  7891. }
  7892.  
  7893.  
  7894. static void
  7895. fe_DisplayUTF8String(XP_Bool imageString, Display *dpy, Drawable d, 
  7896.               fe_Font font, GC gc, GC gc2, int x, int y, char *string, int len)
  7897. {
  7898.     fe_UnicodePseudoFont *ufont = (fe_UnicodePseudoFont *)font;
  7899.     unsigned char segment[X11STRING_LIMIT*6];
  7900.     int parsed_cnt = 0;
  7901.     int16 encoding, charset;
  7902.     int this_parsed_cnt, seg_data_len;
  7903.     int ascent, descent, this_direction;
  7904.     XCharStruct this_overall;
  7905.     XFontStruct *xfont;
  7906.  
  7907.     if ((ufont==NULL) || (ufont->tag != UNICODE_PSEUDO_FONT_TAG)) {
  7908.         return;
  7909.     }
  7910.     if (!gc) {
  7911.         return;
  7912.     }
  7913.     while (1) {
  7914.         /*
  7915.          * get a single encoding string
  7916.          */
  7917.         this_parsed_cnt = utf8_to_local_encoding(string+parsed_cnt, 
  7918.                                         len-parsed_cnt, 
  7919.                                         segment, sizeof(segment),
  7920.                                         &seg_data_len, &encoding);
  7921.         if (this_parsed_cnt < 1)
  7922.             break;
  7923.  
  7924.         parsed_cnt += this_parsed_cnt;
  7925.  
  7926.         /*
  7927.          * Set the font for this encoding
  7928.          */
  7929.         if (encoding>0)
  7930.             xfont = fe_UnicodeGetXfont(ufont, encoding);
  7931.         else
  7932.             xfont = NULL;
  7933.  
  7934.         /*
  7935.          * Handle errors
  7936.          */
  7937.         if ((encoding < 0) || (!xfont)) {
  7938.             fe_UnicodeConvertToPlaceHolder(ufont, &encoding, &xfont,
  7939.                             segment, seg_data_len);
  7940.         }
  7941.  
  7942.         if (IS_16BIT_ENCODING(encoding))
  7943.             seg_data_len /= 2;
  7944.         XSetFont(dpy, gc, xfont->fid);
  7945.         charset = encoding &0xFF;
  7946.         if (IS_16BIT_ENCODING(encoding)) {
  7947.             /* get the real base line / descent */
  7948.             XTextExtents16(ufont->xFonts[charset], (XChar2b*)segment, 
  7949.                 seg_data_len, &this_direction, &ascent, &descent,
  7950.                 &this_overall);
  7951.             if (imageString)
  7952.                 XFillRectangle(dpy, d, gc2, x, y-ufont->ascent, 
  7953.                         this_overall.width, ufont->ascent+ufont->descent);
  7954.             XDrawString16(dpy, d, gc, x, y, (XChar2b*)segment,seg_data_len);
  7955.         }
  7956.         else {
  7957.             XTextExtents(ufont->xFonts[charset], segment, seg_data_len,
  7958.                         &this_direction, &ascent, &descent, &this_overall);
  7959.             if (imageString)
  7960.                 XFillRectangle(dpy, d, gc2, x, y-ufont->ascent, 
  7961.                         this_overall.width, ufont->ascent+ufont->descent);
  7962.             XDrawString(dpy, d, gc, x, y, segment, seg_data_len);
  7963.         }
  7964.         x += this_overall.width;
  7965.     }
  7966. }
  7967.  
  7968.  
  7969. void
  7970. fe_DrawUTF8String(Display *dpy, Drawable d, fe_Font font, GC gc, int x,
  7971.     int y, char *string, int len)
  7972. {
  7973.     fe_DisplayUTF8String(FALSE, dpy, d, font, gc, NULL, x, y, string, len);
  7974. }
  7975.  
  7976. static void
  7977. fe_DrawUTF8StringImage(Display *dpy, Drawable d, fe_Font font, GC gc, GC gc2,
  7978.     int x, int y, char *string, int len)
  7979. {
  7980.     fe_DisplayUTF8String(TRUE, dpy, d, font, gc, gc2, x, y, string, len);
  7981. }
  7982.  
  7983. int
  7984. fe_DrawUCS2String(Display *dpy, Drawable d, fe_Font font, GC gc, int x,
  7985.     int y, uint16 *string, int len)
  7986. {
  7987.     unsigned char *utf8p;
  7988.     int fontAscent, fontDescent, direction; 
  7989.     XCharStruct overall;
  7990.  
  7991.    /*
  7992.     * Convert from UCS2 to UTF8
  7993.     */
  7994.     utf8p = INTL_UCS2ToUTF8(string, len);
  7995.     if (utf8p == NULL) {
  7996.         return -1;
  7997.     }
  7998.     fe_DisplayUTF8String(FALSE, dpy, d, font, gc, NULL, x, y, 
  7999.                         utf8p, strlen(utf8p));
  8000.     fe_UTF8TextExtents(font, utf8p, strlen(utf8p), &direction,
  8001.                             &fontAscent, &fontDescent, &overall);
  8002.     free(utf8p);
  8003.     return overall.width;
  8004. }
  8005.  
  8006. void
  8007. fe_UCS2TextExtents(fe_Font font, uint16 *string, int len, int *direction, 
  8008.                 int *fontAscent, int *fontDescent, XCharStruct *overall)
  8009. {
  8010.     unsigned char *utf8p;
  8011.  
  8012.    /*
  8013.     * Convert from UCS2 to UTF8
  8014.     */
  8015.     utf8p = INTL_UCS2ToUTF8(string, len);
  8016.     if (utf8p == NULL) {
  8017.     *direction = 0;
  8018.     *fontAscent = 0;
  8019.     *fontDescent = 0;
  8020.         overall->width = 0;
  8021.         return;
  8022.     }
  8023.     fe_UTF8TextExtents(font, utf8p, strlen(utf8p), direction,
  8024.                             fontAscent, fontDescent, overall);
  8025.     free(utf8p);
  8026. }
  8027.  
  8028.  
  8029. XmString
  8030. XUPF_UCS2ToXmString(uint16 *uniChars, int32 length, fe_Font font, 
  8031.                         XmFontList *fontList)
  8032. {
  8033.     fe_UnicodePseudoFont *ufont = (fe_UnicodePseudoFont *)font;
  8034.     unsigned char *utf8p;
  8035.     XmString xmstring;
  8036.  
  8037.     if ((ufont==NULL) || (ufont->tag != UNICODE_PSEUDO_FONT_TAG)) {
  8038.         /* something is wrong. */
  8039.         return NULL;
  8040.     }
  8041.    /*
  8042.     * Convert from UCS2 to UTF8
  8043.     */
  8044.     if (length) {
  8045.         utf8p = INTL_UCS2ToUTF8(uniChars, length);
  8046.         if (utf8p == NULL) {
  8047.             return NULL;
  8048.         }
  8049.     }
  8050.     else
  8051.         utf8p = XP_STRDUP("");
  8052.     xmstring = fe_utf8_to_XmString(ufont, utf8p, strlen(utf8p), fontList);
  8053.     free(utf8p);
  8054.     return xmstring;
  8055. }
  8056.  
  8057. fe_Font
  8058. XUPF_LoadDefaultFont(Display *dpy)
  8059. {
  8060.     fe_UnicodePseudoFont *ufont;
  8061.  
  8062.     ufont = fe_LoadUnicodeFont(NULL, "helvetica", 0, 4, 0, CS_LATIN1,
  8063.                                    0, 0, dpy);
  8064.     return ufont;
  8065. }
  8066.  
  8067. /*
  8068.  * fe_utf8_to_XmString - Convert a utf8 string to a XmString
  8069.  *
  8070.  * Parse the utf8 string into locally displayable encoded segments
  8071.  * and add each segment onto a XmString
  8072.  *
  8073.  * If there are errors display something.
  8074.  * hopefully the user will see the garbage and try a different encoding
  8075.  */
  8076. XmString
  8077. fe_utf8_to_XmString(fe_Font font, char *string, int len, XmFontList *fontList)
  8078. {
  8079.     fe_UnicodePseudoFont *ufont = (fe_UnicodePseudoFont *)font;
  8080.     unsigned char segment[X11STRING_LIMIT*6];
  8081.     int16 encoding;
  8082.     char *encoding_name;
  8083.     int parsed_cnt = 0;
  8084.     int this_parsed_cnt, seg_data_len;
  8085.     XmString xm_string = NULL;
  8086.     XmString this_xm_seg, old_xm_string;
  8087.     XFontStruct *xfont;
  8088.  
  8089.  
  8090.     if ((ufont==NULL) || (ufont->tag != UNICODE_PSEUDO_FONT_TAG)) {
  8091.         /* something is wrong. I will just return a guess */
  8092.         return NULL;
  8093.     }
  8094.  
  8095.     /*
  8096.      * Break up the unicode string into locally sizeable encoded segments
  8097.      */
  8098.     while (1) {
  8099.         /* get a single encoding string */
  8100.         this_parsed_cnt = utf8_to_local_encoding(string+parsed_cnt, 
  8101.                                         len-parsed_cnt, 
  8102.                                         segment, sizeof(segment),
  8103.                                         &seg_data_len, &encoding);
  8104.         if (this_parsed_cnt < 1) /* no more input data */
  8105.             break;
  8106.  
  8107.         parsed_cnt += this_parsed_cnt;
  8108.  
  8109.         /*
  8110.          * Get update the XmFontList
  8111.          */
  8112.         if (encoding >= 0)
  8113.             xfont = fe_UnicodeGetXfont(ufont, encoding);
  8114.         else
  8115.             xfont = NULL;
  8116.  
  8117.         /*
  8118.          * Handle errors
  8119.          */
  8120.         if ((encoding < 0) || (!xfont)) {
  8121.             fe_UnicodeConvertToPlaceHolder(ufont, &encoding, &xfont,
  8122.                             segment, seg_data_len);
  8123.         }
  8124.  
  8125.         /*
  8126.         * Add this component to the XmString
  8127.         */
  8128.         encoding_name = INTL_CsidToCharsetNamePt(encoding);
  8129.         this_xm_seg = XmStringCreateLtoR(segment, encoding_name);
  8130.         if (xm_string) {
  8131.             old_xm_string = xm_string;
  8132.             xm_string = XmStringConcat(old_xm_string, this_xm_seg);
  8133.             XmStringFree(old_xm_string);
  8134.             XmStringFree(this_xm_seg);
  8135.         }
  8136.         else
  8137.             xm_string = this_xm_seg;
  8138.     }
  8139.  
  8140.     /*
  8141.      * handle empty string
  8142.      */
  8143.     if (xm_string==NULL) {
  8144.         (void)fe_UnicodeGetXfont(ufont, CS_LATIN1);
  8145.         xm_string = XmStringCreateSimple("");
  8146.     }
  8147.  
  8148.     *fontList = ufont->xmfontlist;
  8149.     return xm_string;
  8150. }
  8151.  
  8152. /********************************************************************
  8153.   New Code
  8154.  ********************************************************************/
  8155. /*
  8156.  * these values can be changed to whatever is convenient for Java
  8157.  */
  8158. enum
  8159. {
  8160.     INTL_FontStyleNormal,
  8161.     INTL_FontStyleBold,
  8162.     INTL_FontStyleItalic,
  8163.     INTL_FontStyleBoldItalic
  8164. };
  8165.  
  8166.  
  8167. static XFontStruct *
  8168. intl_GetFontFace(Display *display, int sizeNum, fe_FontSize *size, int faceNum,
  8169.     char **fontName)
  8170. {
  8171.     fe_FontFace    *face;
  8172.     int        i;
  8173.     char        *name;
  8174.     XFontStruct    *ret;
  8175.  
  8176.     for (i = 0; i < 2; i++, faceNum = 0)
  8177.     {
  8178.         face = size->faces[faceNum];
  8179.         if (!face)
  8180.         {
  8181.             continue;
  8182.         }
  8183.         if (face->font)
  8184.         {
  8185.             if (fontName)
  8186.             {
  8187.                 if (size->size)
  8188.                 {
  8189.                     *fontName =
  8190.                         strdup(face->longXLFDFontName);
  8191.                 }
  8192.                 else
  8193.                 {
  8194.                     *fontName = PR_smprintf(
  8195.                         face->longXLFDFontName,
  8196.                         sizeNum);
  8197.                 }
  8198.             }
  8199.             return face->font;
  8200.         }
  8201.         else
  8202.         {
  8203.             if (size->size)
  8204.             {
  8205.                 name = strdup(face->longXLFDFontName);
  8206.             }
  8207.             else
  8208.             {
  8209.                 name = PR_smprintf(face->longXLFDFontName,
  8210.                     sizeNum);
  8211.             }
  8212.             if (!name)
  8213.             {
  8214.                 return NULL;
  8215.             }
  8216.             ret = fe_LoadXFont(display, name);
  8217.             if (ret)
  8218.             {
  8219.                 face->font = ret;
  8220.                 if (fontName)
  8221.                 {
  8222.                     *fontName = name;
  8223.                 }
  8224.                 return ret;
  8225.             }
  8226.         }
  8227.     }
  8228.  
  8229.     return NULL;
  8230. }
  8231.  
  8232.  
  8233. static XFontStruct *
  8234. intl_GetFontSize(Display *display, fe_FontFamily *family, int sizeNum,
  8235.     int faceNum, char **fontName)
  8236. {
  8237.     int        closestSize = 0;
  8238.     int        firstSize;
  8239.     int        i;
  8240.     double        minDist;
  8241.     double        newDist;
  8242.     XFontStruct    *ret;
  8243.     fe_FontSize    *size;
  8244.  
  8245.     if (!family->pixelSizes)
  8246.     {
  8247.         return NULL;
  8248.     }
  8249.  
  8250.     if (family->pixelSizes->size)
  8251.     {
  8252.         firstSize = 0;
  8253.     }
  8254.     else
  8255.     {
  8256.         if (family->numberOfPixelSizes == 1)
  8257.         {
  8258.             return intl_GetFontFace(display, sizeNum,
  8259.                 family->pixelSizes, faceNum, fontName);
  8260.         }
  8261.         firstSize = 1;
  8262.     }
  8263.  
  8264.     minDist = (1E+36);
  8265.     for (i = firstSize; i < family->numberOfPixelSizes; i++)
  8266.     {
  8267.         size = &family->pixelSizes[i];
  8268.         newDist = ((sizeNum - size->size) * (sizeNum - size->size));
  8269.         if (newDist < minDist)
  8270.         {
  8271.             minDist = newDist;
  8272.             closestSize = i;
  8273.         }
  8274.         else
  8275.         {
  8276.             break;
  8277.         }
  8278.     }
  8279.  
  8280.     for (i = 0; i < family->numberOfPixelSizes; i++)
  8281.     {
  8282.         if (closestSize - i >= firstSize)
  8283.         {
  8284.             size = &family->pixelSizes[closestSize - i];
  8285.             ret = intl_GetFontFace(display, size->size, size,
  8286.                 faceNum, fontName);
  8287.             if (ret)
  8288.             {
  8289.                 return ret;
  8290.             }
  8291.         }
  8292.         if (closestSize + i < family->numberOfPixelSizes)
  8293.         {
  8294.             size = &family->pixelSizes[closestSize + i];
  8295.             ret = intl_GetFontFace(display, size->size, size,
  8296.                 faceNum, fontName);
  8297.             if (ret)
  8298.             {
  8299.                 return ret;
  8300.             }
  8301.         }
  8302.     }
  8303.  
  8304.     if (!family->pixelSizes->size)
  8305.     {
  8306.         return intl_GetFontFace(display, sizeNum, family->pixelSizes,
  8307.             faceNum, fontName);
  8308.     }
  8309.  
  8310.     return NULL;
  8311. }
  8312.  
  8313.  
  8314. XFontStruct *
  8315. intl_GetFont(Display *display, int16 characterSet, char *familyName,
  8316.     char *foundry, int sizeNum, int style, char **fontName)
  8317. {
  8318.     fe_FontCharSet    *charset;
  8319.     int        faceNum;
  8320.     fe_FontFamily    *family = NULL;
  8321.     int        i;
  8322.     int        j;
  8323.     fe_FontPitch    *pitch;
  8324.     XFontStruct    *ret;
  8325.  
  8326.  
  8327.     /*
  8328.      * check the charset
  8329.      */
  8330.         characterSet &= 0x00ff;
  8331.     if ((0 > characterSet) || (characterSet >= INTL_CHAR_SET_MAX))
  8332.     {
  8333.         return NULL;
  8334.     }
  8335.     if (fe_CharSetInfoArray[characterSet].type == FE_FONT_TYPE_GROUP)
  8336.     {
  8337.         return NULL;
  8338.     }
  8339.     if (!fe_FontCharSets[characterSet].name)
  8340.     {
  8341.         return NULL;
  8342.     }
  8343.  
  8344.  
  8345.     /*
  8346.      * check the family
  8347.      */
  8348.     if (!familyName)
  8349.     {
  8350.         familyName = "";
  8351.     }
  8352.  
  8353.  
  8354.     /*
  8355.      * check the foundry
  8356.      */
  8357.     if (!foundry)
  8358.     {
  8359.         foundry = "";
  8360.     }
  8361.  
  8362.  
  8363.     /*
  8364.      * check the size
  8365.      */
  8366.     if (sizeNum <= 0)
  8367.     {
  8368.         return NULL;
  8369.     }
  8370.  
  8371.  
  8372.     /*
  8373.      * check the style
  8374.      */
  8375.     switch (style)
  8376.     {
  8377.     case INTL_FontStyleNormal:
  8378.         faceNum = 0;
  8379.         break;
  8380.     case INTL_FontStyleBold:
  8381.         faceNum = 1;
  8382.         break;
  8383.     case INTL_FontStyleItalic:
  8384.         faceNum = 2;
  8385.         break;
  8386.     case INTL_FontStyleBoldItalic:
  8387.         faceNum = 3;
  8388.         break;
  8389.     default:
  8390.         return NULL;
  8391.     }
  8392.  
  8393.  
  8394.     charset = &fe_FontCharSets[characterSet];
  8395.  
  8396.     /*
  8397.      * iterate over the pitches (proportional and fixed)
  8398.      * and for each pitch, look for the requested family and foundry
  8399.      */
  8400.     for (i = 0; i < 2; i++)
  8401.     {
  8402.         pitch = &charset->pitches[i];
  8403.         for (j = 0; j < pitch->numberOfFamilies; j++)
  8404.         {
  8405.             family = &pitch->families[j];
  8406.             if ((!strcmp(family->family, familyName)) &&
  8407.                 (!strcmp(family->foundry, foundry)))
  8408.             {
  8409.                 ret = intl_GetFontSize(display, family,
  8410.                     sizeNum, faceNum, fontName);
  8411.                 if (ret)
  8412.                 {
  8413.                     return ret;
  8414.                 }
  8415.             }
  8416.         }
  8417.     }
  8418.  
  8419.     /*
  8420.      * couldn't find the requested family/foundry pair
  8421.      * so try matching just the family
  8422.      */
  8423.     for (i = 0; i < 2; i++)
  8424.     {
  8425.         pitch = &charset->pitches[i];
  8426.         for (j = 0; j < pitch->numberOfFamilies; j++)
  8427.         {
  8428.             family = &pitch->families[j];
  8429.             if (!strcmp(family->family, familyName))
  8430.             {
  8431.                 ret = intl_GetFontSize(display, family,
  8432.                     sizeNum, faceNum, fontName);
  8433.                 if (ret)
  8434.                 {
  8435.                     return ret;
  8436.                 }
  8437.             }
  8438.         }
  8439.     }
  8440.  
  8441.     /*
  8442.      * couldn't find the requested family
  8443.      * so let's try the one selected in the UI
  8444.      */
  8445.     for (i = 0; i < 2; i++)
  8446.     {
  8447.         pitch = &charset->pitches[i];
  8448.         for (j = 0; j < pitch->numberOfFamilies; j++)
  8449.         {
  8450.             family = &pitch->families[j];
  8451.             if (family->selected)
  8452.             {
  8453.                 break;
  8454.             }
  8455.             else
  8456.             {
  8457.                 family = NULL;
  8458.             }
  8459.         }
  8460.         if (family)
  8461.         {
  8462.             ret = intl_GetFontSize(display, family, sizeNum,
  8463.                 faceNum, fontName);
  8464.             if (ret)
  8465.             {
  8466.                 return ret;
  8467.             }
  8468.         }
  8469.     }
  8470.  
  8471.     /*
  8472.      * if we couldn't load the selected family
  8473.      * we try all of the families in turn
  8474.      */
  8475.     for (i = 0; i < 2; i++)
  8476.     {
  8477.         pitch = &charset->pitches[i];
  8478.         for (j = 0; j < pitch->numberOfFamilies; j++)
  8479.         {
  8480.             family = &pitch->families[j];
  8481.             ret = intl_GetFontSize(display, family, sizeNum,
  8482.                 faceNum, fontName);
  8483.             if (ret)
  8484.             {
  8485.                 return ret;
  8486.             }
  8487.         }
  8488.     }
  8489.  
  8490.     return NULL;
  8491. }
  8492.  
  8493.  
  8494. XFontStruct *
  8495. INTL_GetFont(Display *display, int16 characterSet, char *familyName,
  8496.     char *foundry, int sizeNum, int style)
  8497. {
  8498.     return intl_GetFont(display, characterSet, familyName, foundry,
  8499.         sizeNum, style, NULL);
  8500. }
  8501.  
  8502.  
  8503. static int16 *
  8504. INTL_GetXCharSetIDs(Display *dpy)
  8505. {
  8506.     unsigned char    *charset;
  8507.     int        len;
  8508.     int16        *p;
  8509.     int16        *ret;
  8510.  
  8511.     ret = NULL;
  8512.  
  8513.     if (!fe_LocaleCharSets)
  8514.     {
  8515.         fe_GetLocaleCharSets(dpy);
  8516.         if (!fe_LocaleCharSets)
  8517.         {
  8518.             ret = (int16 *) malloc(2 * sizeof(int16));
  8519.             if (!ret)
  8520.             {
  8521.                 return NULL;
  8522.             }
  8523.             ret[0] = CS_LATIN1;
  8524.             ret[1] = 0;
  8525.             return ret;
  8526.         }
  8527.     }
  8528.  
  8529.     len = 0;
  8530.     charset = fe_LocaleCharSets;
  8531.     while (*charset)
  8532.     {
  8533.         len++;
  8534.         charset++;
  8535.     }
  8536.  
  8537.     ret = (int16 *) malloc((len + 1) * sizeof(int16));
  8538.     if (!ret)
  8539.     {
  8540.         return NULL;
  8541.     }
  8542.  
  8543.     p = ret;
  8544.     charset = fe_LocaleCharSets;
  8545.     while (*charset)
  8546.     {
  8547.         *p++ = fe_CharSetInfoArray[*charset++].charsetID;
  8548.     }
  8549.     *p = 0;
  8550.  
  8551.     return ret;
  8552. }
  8553.  
  8554.  
  8555. char *
  8556. INTL_GetXFontName(Display *display, int16 characterSet, char *familyName,
  8557.     char *foundry, int sizeNum, int style)
  8558. {
  8559.     char    *fontName;
  8560.  
  8561.     fontName = NULL;
  8562.  
  8563.     (void) intl_GetFont(display, characterSet, familyName, foundry,
  8564.         sizeNum, style, &fontName);
  8565.  
  8566.     return fontName;
  8567. }
  8568.