netscape-revival
cmd/xfe/fonts.c
/* -*- Mode: C; tab-width: 8 -*-
fonts.c --- managing fonts for layout.
Copyright © 1995 Netscape Communications Corporation, all rights reserved.
Created: Jamie Zawinski <jwz@netscape.com>, 23-Jun-94.
Re-written: Erik van der Poel <erik@netscape.com>, 15-Oct-95.
*/
/* Currently, we allow the user to select the size of the font used, and
the family/foundry. Within that, the document author specifies
a size from 1-7, a face (normal, bold, italic, bold-italic) and whether
the font is fixed or variable width. Meaning 7*4*2 = 56 possible
fonts (but we load lazily).
*/
#include "mozilla.h"
#include "xfe.h"
#include "fonts.h"
#include <libi18n.h>
#include <nspr/prprf.h>
#include <nspr/prmem.h>
#include <xpgetstr.h>
/* for XP_GetString() */
extern int XFE_OTHER_LANGUAGE;
extern int XFE_USER_DEFINED;
/* for debugging */
/* #define FE_PRINT_FONTS 1 */
#define fe_FONT_PITCH_MONO 0x1
#define fe_FONT_PITCH_PROPORTIONAL 0x2
#define fe_FONT_PITCH_BOTH 0x3
#define fe_TryFont(context, familyName, sizeNum, fontmask, charset, pitch, faceNum, dpy) \
(*fe_CharSetFuncsArray[fe_CharSetInfoArray[charset].info].loadFont) \
(context, familyName, sizeNum, fontmask, charset, pitch, faceNum, dpy)
#define FE_MAYBE_FREE(p) do { if (p) { free(p); (p) = NULL; } } while (0)
#define FE_MALLOC_ZAP(type) ((type *) calloc(1, sizeof(type)))
#define FE_FONT_MASK_TO_PITCH(fontmask) (((fontmask) & LO_FONT_FIXED) ? 1 : 0)
#define FE_FONT_MASK_TOGGLE_PITCH(fontmask) ((fontmask) ^ LO_FONT_FIXED)
#ifdef DEBUG_jwz
extern XP_Bool fe_ignore_font_size_changes_p;
# define FE_NORMALIZE_SIZE(sizeNum) \
do { if (fe_ignore_font_size_changes_p) { (sizeNum) = 3; } \
else { \
(sizeNum) &= 0x7; if ((sizeNum) < 1) { (sizeNum) = 1; } } \
} while (0)
#else /* !DEBUG_jwz */
#define FE_NORMALIZE_SIZE(sizeNum) \
do { (sizeNum) &= 0x7; if ((sizeNum) < 1) { (sizeNum) = 1; } } while (0)
#endif /* !DEBUG_jwz */
#define FE_FONT_MASK_TO_FACE(fontmask) \
((((fontmask) & LO_FONT_BOLD) && \
((fontmask) & LO_FONT_ITALIC)) ? 3 : \
((fontmask) & LO_FONT_ITALIC) ? 2 : \
((fontmask) & LO_FONT_BOLD) ? 1 : 0);
#define FE_FONT_SELECTED_FAMILY(charset, pitch) \
fe_FontFindSelectedFamily(&fe_FontCharSets[charset].pitches[pitch])
typedef struct fe_StringProcessTable
{
unsigned char fontIndex;
unsigned char skip;
unsigned char len;
} fe_StringProcessTable;
typedef struct fe_FontGroupFont
{
unsigned char mask1;
unsigned char mask2;
XFontStruct *xFont;
} fe_FontGroupFont;
typedef struct fe_FontSetListEntry fe_FontSetListEntry;
struct fe_FontSetListEntry
{
fe_FontSetListEntry *next;
char *list;
XFontSet fontSet;
};
typedef int (*fe_XDrawStringFunc)(Display *dpy, Drawable d, GC gc,
int x, int y, char *string, int len);
static fe_Font fe_FixedFont = NULL;
#define FE_DEFAULT_FONT_SIZE_INCREMENT 0.2
static double fe_FontSizeIncrement = FE_DEFAULT_FONT_SIZE_INCREMENT;
static fe_FontFace *fe_FontFaceList = NULL;
static fe_FontSize *fe_FontSizeList = NULL;
static fe_FontSetListEntry *fe_FontSetList = NULL;
fe_FontCharSet fe_FontCharSets[INTL_CHAR_SET_MAX];
unsigned char fe_SortedFontCharSets[INTL_CHAR_SET_MAX];
static fe_Font
fe_LoadNormalFont(MWContext *context, char *familyName, int sizeNum,
int fontmask, int charset, int pitch, int faceNum,
Display *dpy);
static fe_Font
fe_LoadEUCCNFont(MWContext *context, char *familyName, int sizeNum,
int fontmask, int charset, int pitch, int faceNum,
Display *dpy);
static void
fe_EUCCNTextExtents(fe_Font font, char *string, int len, int *direction,
int *fontAscent, int *fontDescent, XCharStruct *overall);
static void
fe_DrawEUCCNString(Display *dpy, Drawable d, fe_Font font, GC gc, int x,
int y, char *string, int len);
static void
fe_DrawEUCCNImageString(Display *dpy, Drawable d, fe_Font font, GC gc, int x,
int y, char *string, int len);
static fe_Font
fe_LoadEUCJPFont(MWContext *context, char *familyName, int sizeNum,
int fontmask, int charset, int pitch, int faceNum,
Display *dpy);
static void
fe_EUCJPTextExtents(fe_Font font, char *string, int len, int *direction,
int *fontAscent, int *fontDescent, XCharStruct *overall);
static void
fe_DrawEUCJPString(Display *dpy, Drawable d, fe_Font font, GC gc, int x,
int y, char *string, int len);
static void
fe_DrawEUCJPImageString(Display *dpy, Drawable d, fe_Font font, GC gc, int x,
int y, char *string, int len);
static fe_Font
fe_LoadEUCKRFont(MWContext *context, char *familyName, int sizeNum,
int fontmask, int charset, int pitch, int faceNum,
Display *dpy);
static void
fe_EUCKRTextExtents(fe_Font font, char *string, int len, int *direction,
int *fontAscent, int *fontDescent, XCharStruct *overall);
static void
fe_DrawEUCKRString(Display *dpy, Drawable d, fe_Font font, GC gc, int x,
int y, char *string, int len);
static void
fe_DrawEUCKRImageString(Display *dpy, Drawable d, fe_Font font, GC gc, int x,
int y, char *string, int len);
static fe_Font
fe_LoadEUCTWFont(MWContext *context, char *familyName, int sizeNum,
int fontmask, int charset, int pitch, int faceNum,
Display *dpy);
static void
fe_EUCTWTextExtents(fe_Font font, char *string, int len, int *direction,
int *fontAscent, int *fontDescent, XCharStruct *overall);
static void
fe_DrawEUCTWString(Display *dpy, Drawable d, fe_Font font, GC gc, int x,
int y, char *string, int len);
static void
fe_DrawEUCTWImageString(Display *dpy, Drawable d, fe_Font font, GC gc, int x,
int y, char *string, int len);
static fe_Font
fe_LoadBIG5Font(MWContext *context, char *familyName, int sizeNum,
int fontmask, int charset, int pitch, int faceNum,
Display *dpy);
static void
fe_BIG5TextExtents(fe_Font font, char *string, int len, int *direction,
int *fontAscent, int *fontDescent, XCharStruct *overall);
static void
fe_DrawBIG5String(Display *dpy, Drawable d, fe_Font font, GC gc, int x,
int y, char *string, int len);
static void
fe_DrawBIG5ImageString(Display *dpy, Drawable d, fe_Font font, GC gc, int x,
int y, char *string, int len);
enum
{
FE_FONT_INFO_X8 = 0,
FE_FONT_INFO_X16,
FE_FONT_INFO_EUCCN,
FE_FONT_INFO_EUCJP,
FE_FONT_INFO_EUCKR,
FE_FONT_INFO_EUCTW,
FE_FONT_INFO_BIG5
};
fe_CharSetFuncs fe_CharSetFuncsArray[] =
{
{
1,
(fe_LoadFontFunc) fe_LoadNormalFont,
(fe_TextExtentsFunc) XTextExtents,
(fe_DrawStringFunc) XDrawString,
(fe_DrawImageStringFunc) XDrawImageString
},
{
1,
(fe_LoadFontFunc) fe_LoadNormalFont,
(fe_TextExtentsFunc) XTextExtents16,
(fe_DrawStringFunc) XDrawString16,
(fe_DrawImageStringFunc) XDrawImageString16
},
{
2,
(fe_LoadFontFunc) fe_LoadEUCCNFont,
(fe_TextExtentsFunc) fe_EUCCNTextExtents,
(fe_DrawStringFunc) fe_DrawEUCCNString,
(fe_DrawImageStringFunc) fe_DrawEUCCNImageString
},
{
4,
(fe_LoadFontFunc) fe_LoadEUCJPFont,
(fe_TextExtentsFunc) fe_EUCJPTextExtents,
(fe_DrawStringFunc) fe_DrawEUCJPString,
(fe_DrawImageStringFunc) fe_DrawEUCJPImageString
},
{
2,
(fe_LoadFontFunc) fe_LoadEUCKRFont,
(fe_TextExtentsFunc) fe_EUCKRTextExtents,
(fe_DrawStringFunc) fe_DrawEUCKRString,
(fe_DrawImageStringFunc) fe_DrawEUCKRImageString
},
{
3,
(fe_LoadFontFunc) fe_LoadEUCTWFont,
(fe_TextExtentsFunc) fe_EUCTWTextExtents,
(fe_DrawStringFunc) fe_DrawEUCTWString,
(fe_DrawImageStringFunc) fe_DrawEUCTWImageString
},
{
2,
(fe_LoadFontFunc) fe_LoadBIG5Font,
(fe_TextExtentsFunc) fe_BIG5TextExtents,
(fe_DrawStringFunc) fe_DrawBIG5String,
(fe_DrawImageStringFunc) fe_DrawBIG5ImageString
},
};
fe_CharSetInfo fe_CharSetInfoArray[] =
{
{ CS_DEFAULT , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_ASCII , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_LATIN1 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_JIS , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_SJIS , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_EUCJP , FE_FONT_TYPE_GROUP , FE_FONT_INFO_EUCJP },
{ CS_MAC_ROMAN , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_BIG5 , FE_FONT_TYPE_GROUP , FE_FONT_INFO_BIG5 },
{ CS_GB_8BIT , FE_FONT_TYPE_GROUP , FE_FONT_INFO_EUCCN },
{ CS_CNS_8BIT , FE_FONT_TYPE_GROUP , FE_FONT_INFO_EUCTW },
{ CS_LATIN2 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_MAC_CE , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_KSC_8BIT , FE_FONT_TYPE_GROUP , FE_FONT_INFO_EUCKR },
{ CS_2022_KR , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_8859_3 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_8859_4 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_8859_5 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_8859_6 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_8859_7 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_8859_8 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_8859_9 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_SYMBOL , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_DINGBATS , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_DECTECH , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_CNS11643_1 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 },
{ CS_CNS11643_2 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 },
{ CS_JISX0208 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 },
{ CS_JISX0201 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_KSC5601 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 },
{ CS_TIS620 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_JISX0212 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 },
{ CS_GB2312 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 },
{ CS_UCS2 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 },
{ CS_UCS4 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 },
{ CS_UTF8 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_UTF7 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_NPC , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_X_BIG5 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 },
{ CS_USRDEF2 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_KOI8_R , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_MAC_CYRILLIC , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_CP_1251 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_MAC_GREEK , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_CP_1253 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_CP_1250 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_CP_1254 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_MAC_TURKISH , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 },
{ CS_GB2312_11 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 },
{ CS_JISX0208_11 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 },
{ CS_KSC5601_11 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 },
{ CS_CNS11643_1110, FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 },
};
static unsigned char *fe_LocaleCharSets = NULL;
static void
fe_GetLocaleCharSets(Display *dpy)
{
char *charset;
int16 charsetID;
char clas[512];
XrmDatabase db;
char *def;
XFontSet fontSet;
int i;
int j;
char *mimeCharSet;
int missCount;
char **missing;
char name[512];
char *p;
char *type;
XrmValue value;
if (fe_LocaleCharSets)
{
return;
}
#if defined(SCO) || defined(UNIXWARE) && (XlibSpecificationRelease == 5)
/*
** XCreateFontSet is very slow in old Xlibs, fixed in X11R6
** If locale == C, just punt
*/
{
char *locale;
locale = setlocale(LC_CTYPE, NULL);
if (*locale == 'C') /* SCO is C_C.C */
{
return;
}
}
#endif
missing = NULL;
missCount = 0;
def = NULL;
fontSet = XCreateFontSet(dpy, "*-iso8859-1", &missing, &missCount,
&def);
if ((!fontSet) || (missCount < 1) || (!missing))
{
goto get_locale_char_sets_fail;
}
fe_LocaleCharSets = malloc(missCount + 2);
if (!fe_LocaleCharSets)
{
goto get_locale_char_sets_fail;
}
j = 0;
fe_LocaleCharSets[j++] = ((unsigned char) (CS_LATIN1 & 0xff));
charset = NULL;
db = XtDatabase(dpy);
for (i = 0; i < missCount; i++)
{
FE_MAYBE_FREE(charset);
if (!missing[i])
{
continue;
}
/*
(void) fprintf(real_stderr, "locale font %d: \"%s\"\n", i + 1,
missing[i]);
*/
charset = strdup(missing[i]);
if (!charset)
{
goto get_locale_char_sets_fail;
}
p = charset;
while (*p)
{
(*p) = XP_TO_LOWER(*p);
p++;
}
(void) PR_snprintf(clas, sizeof(clas),
"%s.DocumentFonts.CharSet.Name", fe_progclass);
(void) PR_snprintf(name, sizeof(name),
"%s.documentFonts.charset.%s", fe_progclass, charset);
if (XrmGetResource(db, name, clas, &type, &value))
{
mimeCharSet = (char *) value.addr;
}
else
{
#if 0 /* jwz */
#ifdef DEBUG
(void) fprintf(real_stderr, "fontset charset %s\n",
charset);
#endif /* DEBUG */
#endif /* 0 -- jwz */
continue;
}
charsetID = INTL_CharSetNameToID(mimeCharSet);
if ((charsetID == CS_UNKNOWN) && strcmp(charset, "x-ignore"))
{
#if 0 /* jwz */
#ifdef DEBUG
(void) fprintf(real_stderr, "fontset internal %s %s\n",
charset, mimeCharSet);
#endif /* DEBUG */
#endif /* 0 -- jwz */
continue;
}
if (!strcmp(charset, "x-ignore"))
{
continue;
}
charsetID &= 0xff;
if (charsetID >= INTL_CHAR_SET_MAX)
{
continue;
}
fe_LocaleCharSets[j++] = (unsigned char) charsetID;
}
FE_MAYBE_FREE(charset);
fe_LocaleCharSets[j] = 0;
XFreeStringList(missing);
XFreeFontSet(dpy, fontSet);
return;
get_locale_char_sets_fail:
if (fontSet)
{
XFreeFontSet(dpy, fontSet);
}
if (missing)
{
XFreeStringList(missing);
}
if (fe_LocaleCharSets)
{
free(fe_LocaleCharSets);
fe_LocaleCharSets = NULL;
}
}
fe_FontFamily *
fe_FontFindSelectedFamily(fe_FontPitch *pitch)
{
fe_FontFamily *family;
int i;
if (!pitch) return(NULL);
if (pitch->selectedFamily) return(pitch->selectedFamily);
family = NULL;
for (i = 0; i < pitch->numberOfFamilies; i++)
{
if (pitch->families[i].selected)
{
family = &pitch->families[i];
break;
}
}
if (!family)
{
family = FE_MALLOC_ZAP(fe_FontFamily);
}
pitch->selectedFamily = family;
return (family);
}
fe_FontFamily *
fe_FontFindFamily(int charsetID, int pitchID, char *familyName)
{
#ifdef DEBUG_jwz
return NULL; /* totally fucking disable <FONT FACE="..."> */
#else /* !DEBUG_jwz */
fe_FontFamily *family;
fe_FontPitch *pitch;
int i;
if (!familyName || !*familyName) return(NULL);
family = NULL;
pitch = &fe_FontCharSets[charsetID].pitches[pitchID];
for (i = 0; i < pitch->numberOfFamilies; i++)
{
if (!strcasecmp(pitch->families[i].family, familyName))
{
family = &pitch->families[i];
break;
}
}
return (family);
#endif /* !DEBUG_jwz */
}
XtPointer
fe_GetFont(MWContext *context, int sizeNum, int fontmask)
{
XmFontListEntry flentry;
XtPointer fontOrFontSet;
XmFontType type;
XmFontList fontList;
fontOrFontSet = fe_GetFontOrFontSet(context, NULL, sizeNum, fontmask,
&type);
if (!fontOrFontSet)
{
return NULL;
}
flentry = XmFontListEntryCreate(XmFONTLIST_DEFAULT_TAG, type,
fontOrFontSet);
if (!flentry)
{
return NULL;
}
fontList = XmFontListAppendEntry(NULL, flentry);
if (!fontList)
{
return NULL;
}
XmFontListEntryFree(&flentry);
return fontList;
}
XtPointer
fe_GetFontOrFontSet(MWContext *context, char *familyName, int sizeNum,
int fontmask, XmFontType *type)
{
unsigned char charset;
int16 cs;
char *def;
Display *dpy;
fe_FontSetListEntry *f;
fe_FontFace *face;
int faceNum;
XtPointer fontOrFontSet;
char *list;
int missCount;
char **missing;
char *newList;
unsigned char *p;
int pitch;
fe_FontSize *size;
fe_FontFamily *family;
def = NULL;
dpy = XtDisplay(CONTEXT_WIDGET(context));
faceNum = FE_FONT_MASK_TO_FACE(fontmask);
list = NULL;
missCount = 0;
missing = NULL;
pitch = FE_FONT_MASK_TO_PITCH(fontmask);
FE_NORMALIZE_SIZE(sizeNum);
if (fe_LocaleCharSets)
{
p = fe_LocaleCharSets;
while (*p)
{
charset = *p++;
family = NULL;
if (familyName && *familyName)
{
family = fe_FontFindFamily(charset, pitch, familyName);
if (!family) return NULL;
}
if (!family)
{
family = FE_FONT_SELECTED_FAMILY(charset,pitch);
if (!family)
{
return NULL;
}
}
if (!family->htmlSizesComputed)
{
fe_ComputeFontSizeTable(family);
}
size = family->htmlSizes[sizeNum-1];
if (!size)
{
continue;
}
face = size->faces[faceNum];
if (!face)
{
continue;
}
if (!face->longXLFDFontName)
{
continue;
}
if (list)
{
newList = PR_smprintf("%s,%s", list,
face->longXLFDFontName);
free(list);
list = newList;
}
else
{
list = strdup(face->longXLFDFontName);
}
if (!list)
{
return NULL;
}
}
f = fe_FontSetList;
while (f)
{
if (!strcmp(f->list, list))
{
break;
}
f = f->next;
}
if (f)
{
free(list);
fontOrFontSet = f->fontSet;
*type = XmFONT_IS_FONTSET;
}
else
{
fontOrFontSet = XCreateFontSet(dpy, list, &missing,
&missCount, &def);
if (fontOrFontSet)
{
/*
(void) fprintf(real_stderr,
"font set \"%s\" succeeded\n", list);
*/
f = XP_NEW_ZAP(fe_FontSetListEntry);
if (!f)
{
return NULL;
}
f->next = fe_FontSetList;
fe_FontSetList = f;
f->list = list;
f->fontSet = fontOrFontSet;
*type = XmFONT_IS_FONTSET;
}
else
{
/*
(void) fprintf(real_stderr,
"font set \"%s\" failed\n", list);
*/
return NULL;
}
}
}
else
{
cs = CS_LATIN1;
fontOrFontSet = fe_LoadFont(context, &cs, familyName,
sizeNum, fontmask);
*type = XmFONT_IS_FONT;
}
return fontOrFontSet;
}
static int
fe_PitchAndFaceToFontMask(int pitch, int face)
{
int fontmask;
if (pitch)
{
fontmask = LO_FONT_FIXED;
}
else
{
fontmask = 0;
}
switch (face)
{
case 1:
fontmask |= LO_FONT_BOLD;
break;
case 2:
fontmask |= LO_FONT_ITALIC;
break;
case 3:
fontmask |= (LO_FONT_BOLD | LO_FONT_ITALIC);
break;
default:
break;
}
return fontmask;
}
static fe_Font
fe_LoadFontGroup(MWContext *context, char *familyName, int sizeNum,
int fontmask, int16 charsetID, int pitch, int faceNum, Display *dpy)
{
fe_FontFace *face;
fe_Font font;
int i;
fe_FontSize *size;
fe_FontFamily *family;
size = FE_MALLOC_ZAP(fe_FontSize);
if (!size)
{
return NULL;
}
for (i = 0; i < 4; i++)
{
face = FE_MALLOC_ZAP(fe_FontFace);
if (!face)
{
return NULL;
}
size->faces[i] = face;
/*
* @@@ ignore familyName for now
* need to modify all the loadFont funcs too
*/
font = (*fe_CharSetFuncsArray[fe_CharSetInfoArray[charsetID].
info].loadFont)(context, NULL, sizeNum,
fe_PitchAndFaceToFontMask(pitch, i), charsetID,
pitch, i, dpy);
if (!font)
{
return NULL;
}
face->font = font;
}
family = FE_FONT_SELECTED_FAMILY(charsetID, pitch);
if (!family)
{
XP_FREE(size);
return NULL;
}
family->htmlSizes[sizeNum-1] = size;
return size->faces[faceNum]->font;
}
fe_Font
fe_LoadFont(MWContext *context, int16 *charset, char *familyName,
int sizeNum, int fontmask)
{
int16 charsetID;
Display *dpy;
fe_FontFace *face;
int faceNum;
fe_Font font;
int pitch;
fe_FontSize *size;
int trySize;
fe_FontFamily *family;
/*
* paranoia, robustness
*/
charsetID = 0;
if (charset)
{
charsetID = *charset;
}
else
{
charset = &charsetID;
}
if (!charsetID)
{
charsetID = INTL_DefaultTextAttributeCharSetID(context);
if (!charsetID)
{
charsetID = CS_LATIN1;
}
*charset = charsetID;
}
charsetID &= 0xff;
if (charsetID >= INTL_CHAR_SET_MAX)
{
charsetID = (CS_LATIN1 & 0xff);
*charset = CS_LATIN1;
}
pitch = FE_FONT_MASK_TO_PITCH(fontmask);
FE_NORMALIZE_SIZE(sizeNum);
faceNum = FE_FONT_MASK_TO_FACE(fontmask);
dpy = XtDisplay(CONTEXT_WIDGET(context));
family = NULL;
if (familyName && *familyName)
{
family = fe_FontFindFamily(charsetID, pitch, familyName);
if ((!family) && (fe_CharSetInfoArray[charsetID].type !=
FE_FONT_TYPE_GROUP))
{
return NULL;
}
}
if (!family)
{
family = FE_FONT_SELECTED_FAMILY(charsetID, pitch);
if (!family)
{
if (*charset == CS_LATIN1)
{
return fe_FixedFont;
}
else
{
*charset = CS_LATIN1;
return fe_LoadFont(context, charset, familyName,
sizeNum, fontmask);
}
}
}
if (!family->htmlSizesComputed)
{
fe_ComputeFontSizeTable(family);
}
size = family->htmlSizes[sizeNum-1];
if (!size)
{
if (fe_CharSetInfoArray[charsetID].type == FE_FONT_TYPE_GROUP)
{
font = fe_LoadFontGroup(context, familyName, sizeNum,
fontmask, charsetID, pitch, faceNum, dpy);
if (font)
{
return font;
}
}
/*
* this charset is not available
* use Latin-1 font to display the bytes
*/
if (*charset == CS_LATIN1)
{
return fe_FixedFont;
}
else
{
*charset = CS_LATIN1;
return fe_LoadFont(context, charset, familyName,
sizeNum, fontmask);
}
}
face = size->faces[faceNum];
if (!face)
{
/*
* this shouldn't happen
* if it does, we will display these bytes in a Latin-1 font
*/
if (*charset == CS_LATIN1)
{
return fe_FixedFont;
}
else
{
*charset = CS_LATIN1;
return fe_LoadFont(context, charset, familyName,
sizeNum, fontmask);
}
}
font = face->font;
if (!font)
{
font = fe_TryFont(context, familyName, sizeNum, fontmask,
charsetID, pitch, faceNum, dpy);
if (!font)
{
for (trySize = sizeNum - 1; trySize > 0; trySize--)
{
font = fe_TryFont(context, familyName,
trySize, fontmask,
charsetID, pitch,
faceNum, dpy);
if (font)
{
return font;
}
}
for (trySize = sizeNum + 1; trySize < 8; trySize++)
{
font = fe_TryFont(context, familyName,
trySize, fontmask,
charsetID, pitch,
faceNum, dpy);
if (font)
{
return font;
}
}
*charset = CS_LATIN1;
font = fe_FixedFont;
face->font = font;
return font;
/* @@@ need to change this */
/*
(void) fprintf(real_stderr, "could not load\n%s\n",
face->longXLFDFontName);
*/
/* XP_GetString(XFE_COULD_NOT_LOAD_FONT) */
/* XP_GetString(XFE_USING_FALLBACK_FONT) */
/* XP_GetString(XFE_NO_FALLBACK_FONT) */
/* FE_Alert(context, msg); */
}
}
return font;
}
fe_Font
fe_LoadFontFromFace(MWContext *context, LO_TextAttr *attr, int16 *charset, char *net_font_face,
int size, int fontmask)
{
fe_Font font = 0;
char *local_net_font_face = NULL;
char *familyname = NULL;
if (attr)
{
font = (fe_Font) attr->FE_Data;
if (font) return(font);
}
if (net_font_face && *net_font_face)
{
local_net_font_face = strdup(net_font_face);
if (!local_net_font_face) return (0);
familyname = strtok(local_net_font_face, ",");
while (familyname)
{
fe_StringTrim(familyname);
font = fe_LoadFont(context, charset, familyname, size, fontmask);
if (!font)
{
/* Try the other pitch */
font = fe_LoadFont(context, charset, familyname, size,
FE_FONT_MASK_TOGGLE_PITCH(fontmask));
}
if (font) break;
familyname = strtok(NULL, ",");
}
XP_FREE(local_net_font_face);
}
/* If we didn't get a font from the face, default to no font_face */
if (!font)
{
font = fe_LoadFont(context, charset, NULL, size, fontmask);
}
if (font)
{
if (attr)
{
attr->FE_Data = (void *) font;
}
}
return(font);
}
XtPointer
fe_GetFontOrFontSetFromFace(MWContext *context, LO_TextAttr *attr, char *net_font_face,
int size, int fontmask, XmFontType *type)
{
XtPointer fontOrFontset = 0;
char *local_net_font_face = NULL;
char *familyname = NULL;
if (attr)
{
fontOrFontset = (fe_Font) attr->FE_Data;
if (fontOrFontset) return(fontOrFontset);
}
if (net_font_face && *net_font_face)
{
local_net_font_face = strdup(net_font_face);
if (!local_net_font_face) return (0);
familyname = strtok(local_net_font_face, ",");
while (familyname)
{
fe_StringTrim(familyname);
fontOrFontset = fe_GetFontOrFontSet(context, familyname, size,
fontmask, type);
if (!fontOrFontset)
{
/* Try the other pitch */
fontOrFontset = fe_GetFontOrFontSet(context, familyname, size,
FE_FONT_MASK_TOGGLE_PITCH(fontmask),
type);
}
if (fontOrFontset) break;
familyname = strtok(NULL, ",");
}
XP_FREE(local_net_font_face);
}
if (!fontOrFontset)
{
fontOrFontset = fe_GetFontOrFontSet(context, NULL, size,
fontmask, type);
}
if (fontOrFontset)
{
if (attr)
{
attr->FE_Data = (void *) fontOrFontset;
}
}
return(fontOrFontset);
}
static void *
fe_ReallocZap(void *p, int oldSize, int newSize)
{
char *end;
char *q;
p = realloc(p, newSize);
if (p)
{
if (newSize > oldSize)
{
end = ((char *) p) + newSize;
for (q = ((char *) p) + oldSize; q < end; q++)
{
*q = 0;
}
}
}
return p;
}
#define FE_REALLOC_ZAP(p, oldSize, newSize, type) \
((type *) fe_ReallocZap((p), (oldSize) * sizeof(type), \
(newSize) * sizeof(type)))
static char *
fe_CapitalizeFontName(char *name)
{
char *p;
char *ret;
ret = strdup(name);
if (!ret)
{
return NULL;
}
p = ret;
while (1)
{
while ((*p) && XP_IS_SPACE(*p))
{
p++;
}
if (!*p)
{
break;
}
*p = XP_TO_UPPER(*p);
while ((*p) && (!XP_IS_SPACE(*p)))
{
p++;
}
if (!*p)
{
break;
}
}
return ret;
}
static void
fe_AddFontSize(fe_FontFamily *family, int faceNum, int pixelSizeNum,
int pointSizeNum, char *pixelSizeFontSpec, char *pointSizeFontSpec)
{
int alloc;
fe_FontFace *face;
int i;
fe_FontSize *newSizes;
fe_FontSize *size;
/*
* first we do the pixel size
*/
size = NULL;
if (family->pixelSizes)
{
for (i = 0; i < family->numberOfPixelSizes; i++)
{
size = &family->pixelSizes[i];
if (size->size == pixelSizeNum)
{
break;
}
else
{
size = NULL;
}
}
}
if (!size)
{
if (family->numberOfPixelSizes >= family->pixelAlloc)
{
alloc = (2 * (family->pixelAlloc + 1));
newSizes = FE_REALLOC_ZAP(family->pixelSizes,
family->pixelAlloc, alloc, fe_FontSize);
if (!newSizes)
{
return;
}
family->pixelSizes = newSizes;
family->pixelAlloc = alloc;
}
size = &family->pixelSizes[family->numberOfPixelSizes++];
size->size = pixelSizeNum;
}
if (!size->faces[faceNum])
{
face = FE_MALLOC_ZAP(fe_FontFace);
if (!face)
{
return;
}
face->longXLFDFontName = strdup(pixelSizeFontSpec);
if (!face->longXLFDFontName)
{
free(face);
return;
}
face->next = fe_FontFaceList;
fe_FontFaceList = face;
size->faces[faceNum] = face;
}
else
{
/* @@@ fix this -- erik */
/*
(void) fprintf(real_stderr, "dup %s\n", pixelSizeFontSpec);
*/
}
/*
* now we do the same for the point size
*/
size = NULL;
if (family->pointSizes)
{
for (i = 0; i < family->numberOfPointSizes; i++)
{
size = &family->pointSizes[i];
if (size->size == pointSizeNum)
{
break;
}
else
{
size = NULL;
}
}
}
if (!size)
{
if (family->numberOfPointSizes >= family->pointAlloc)
{
alloc = (2 * (family->pointAlloc + 1));
newSizes = FE_REALLOC_ZAP(family->pointSizes,
family->pointAlloc, alloc, fe_FontSize);
if (!newSizes)
{
return;
}
family->pointSizes = newSizes;
family->pointAlloc = alloc;
}
size = &family->pointSizes[family->numberOfPointSizes++];
size->size = pointSizeNum;
}
if (!size->faces[faceNum])
{
face = FE_MALLOC_ZAP(fe_FontFace);
if (!face)
{
return;
}
face->longXLFDFontName = strdup(pointSizeFontSpec);
if (!face->longXLFDFontName)
{
free(face);
return;
}
face->next = fe_FontFaceList;
fe_FontFaceList = face;
size->faces[faceNum] = face;
}
else
{
/* @@@ fix this -- erik */
/*
(void) fprintf(real_stderr, "dup %s\n", pointSizeFontSpec);
*/
}
}
static void
fe_AddFontFamily(fe_FontPitch *pitch, char *origFoundry, char *foundry,
char *origFamily, char *familyName, int face, int pixelSize,
int pointSize, char *pixelSizeFontSpec, char *pointSizeFontSpec,
int charsetID, char *origCharset)
{
int alloc;
fe_FontFamily *family;
int i;
char *name;
fe_FontFamily *newFamilies;
if (charsetID == CS_USRDEF2)
{
if (*foundry)
{
name = PR_smprintf("%s (%s, %s)", familyName, foundry,
origCharset);
}
else
{
name = PR_smprintf("%s (%s)", familyName, origCharset);
}
}
else
{
if (*foundry)
{
name = PR_smprintf("%s (%s)", familyName, foundry);
}
else
{
name = strdup(familyName);
}
}
if (!name)
{
return;
}
family = NULL;
if (pitch->families)
{
for (i = 0; i < pitch->numberOfFamilies; i++)
{
family = &pitch->families[i];
if (!strcmp(family->name, name))
{
break;
}
else
{
family = NULL;
}
}
}
if (family)
{
free(name);
}
else
{
if (pitch->numberOfFamilies >= pitch->alloc)
{
alloc = (2 * (pitch->alloc + 1));
newFamilies = FE_REALLOC_ZAP(pitch->families,
pitch->alloc, alloc, fe_FontFamily);
if (!newFamilies)
{
free(name);
return;
}
pitch->families = newFamilies;
pitch->alloc = alloc;
}
family = &pitch->families[pitch->numberOfFamilies++];
family->name = name;
family->family = strdup(origFamily);
family->foundry = strdup(origFoundry);
}
fe_AddFontSize(family, face, pixelSize, pointSize, pixelSizeFontSpec,
pointSizeFontSpec);
}
static void
fe_AddFontCharSet(char *origFoundry, char *foundry, char *origFamily,
char *family, int face, int pixelSize, int pointSize, int pitch,
int charsetID, char *charset, char *charsetlang,
char *pixelSizeFontSpec, char *pointSizeFontSpec, char *origCharset)
{
char mimeName[128];
char *name;
if ((charsetID < 0) || (charsetID >= INTL_CHAR_SET_MAX))
{
return;
}
if (!fe_FontCharSets[charsetID].name)
{
if (charsetID == CS_USRDEF2)
{
name = strdup(XP_GetString(XFE_USER_DEFINED));
}
else
{
name = PR_smprintf("%s (%s)", charsetlang, charset);
}
if (!name)
{
return;
}
fe_FontCharSets[charsetID].name = name;
INTL_CharSetIDToName(charsetID, mimeName);
fe_FontCharSets[charsetID].mimeName = strdup(mimeName);
if (!fe_FontCharSets[charsetID].mimeName)
{
return;
}
}
if (pitch & fe_FONT_PITCH_PROPORTIONAL)
{
fe_AddFontFamily(&fe_FontCharSets[charsetID].pitches[0],
origFoundry, foundry, origFamily, family, face,
pixelSize, pointSize, pixelSizeFontSpec,
pointSizeFontSpec, charsetID, origCharset);
}
if (pitch & fe_FONT_PITCH_MONO)
{
fe_AddFontFamily(&fe_FontCharSets[charsetID].pitches[1],
origFoundry, foundry, origFamily, family, face,
pixelSize, pointSize, pixelSizeFontSpec,
pointSizeFontSpec, charsetID, origCharset);
}
}
static char *
fe_PropOrFixedFont(int i)
{
return i == 0 ? "prop" : "fixed";
}
#define FE_INDEX_TO_FACE(face) (face == 0 ? "normal" : face == 1 ? "bold" : \
face == 2 ? "italic" : "boldItalic")
#ifdef FE_PRINT_FONTS
static void
fe_PrintFamily(fe_FontFamily *family)
{
fe_FontFace *face;
int i;
int j;
fe_FontSize *size;
(void) fprintf(real_stderr, " %s\n", family->name);
for (i = 0; i < family->numberOfPointSizes; i++)
{
size = &family->pointSizes[i];
(void) fprintf(real_stderr, " %d\n", size->size / 10);
for (j = 0; j < 4; j++)
{
(void) fprintf(real_stderr, " %s\n",
FE_INDEX_TO_FACE(j));
face = size->faces[j];
while (face)
{
(void) fprintf(real_stderr, " %s\n",
face->longXLFDFontName);
face = face->next;
}
}
}
}
static void
fe_PrintFonts(void)
{
fe_FontCharSet *charset;
int i;
int j;
int k;
fe_FontPitch *pitch;
for (i = 0; i < INTL_CHAR_SET_MAX; i++)
{
charset = &fe_FontCharSets[i];
if (!charset->name)
{
continue;
}
(void) fprintf(real_stderr, "%s\n", charset->name);
for (j = 0; j < 2; j++)
{
(void) fprintf(real_stderr, " %s\n",
fe_PropOrFixedFont(j));
pitch = &charset->pitches[j];
for (k = 0; k < pitch->numberOfFamilies; k++)
{
fe_PrintFamily(&pitch->families[k]);
}
}
}
}
#endif /* FE_PRINT_FONTS */
static int
fe_CompareFontCharSets(unsigned char *charset1, unsigned char *charset2)
{
char *name1;
char *name2;
name1 = fe_FontCharSets[*charset1].name;
name2 = fe_FontCharSets[*charset2].name;
if (!name1)
{
if (!name2)
{
return 0;
}
return 1;
}
if (!name2)
{
return -1;
}
return strcmp(name1, name2);
}
static int
fe_CompareFontFamilies(fe_FontFamily *family1, fe_FontFamily *family2)
{
return strcmp(family1->name, family2->name);
}
static int
fe_CompareFontSizes(fe_FontSize *size1, fe_FontSize *size2)
{
return size1->size - size2->size;
}
typedef int (*fe_CompFunc)(const void *, const void *);
static void
fe_SortFonts(void)
{
fe_FontCharSet *charset;
fe_FontFamily *family;
int i;
int j;
int k;
fe_FontPitch *pitch;
for (i = 0; i < INTL_CHAR_SET_MAX; i++)
{
fe_SortedFontCharSets[i] = i;
}
qsort(fe_SortedFontCharSets, INTL_CHAR_SET_MAX,
sizeof(*fe_SortedFontCharSets),
(fe_CompFunc) fe_CompareFontCharSets);
for (i = 0; i < INTL_CHAR_SET_MAX; i++)
{
charset = &fe_FontCharSets[i];
if (!charset->name)
{
continue;
}
for (j = 0; j < 2; j++)
{
pitch = &charset->pitches[j];
if (pitch->families)
{
qsort(pitch->families, pitch->numberOfFamilies,
sizeof(fe_FontFamily),
(fe_CompFunc) fe_CompareFontFamilies);
}
for (k = 0; k < pitch->numberOfFamilies; k++)
{
family = &pitch->families[k];
qsort(family->pixelSizes,
family->numberOfPixelSizes,
sizeof(fe_FontSize),
(fe_CompFunc) fe_CompareFontSizes);
qsort(family->pointSizes,
family->numberOfPointSizes,
sizeof(fe_FontSize),
(fe_CompFunc) fe_CompareFontSizes);
}
}
}
}
void
fe_ReadFontCharSet(char *charsetname)
{
fe_FontCharSet *charset;
int16 charsetID;
int i;
charsetID = (INTL_CharSetNameToID(charsetname) & 0xff);
if ((charsetID < 0) || (charsetID >= INTL_CHAR_SET_MAX))
{
charsetID = CS_LATIN1;
}
charsetID &= 0xff;
for (i = 0; i < INTL_CHAR_SET_MAX; i++)
{
fe_FontCharSets[i].selected = 0;
}
charset = &fe_FontCharSets[charsetID];
if (charset->name)
{
charset->selected = 1;
}
else
{
charset = NULL;
for (i = 0; i < INTL_CHAR_SET_MAX; i++)
{
charset = &fe_FontCharSets[i];
if (!charset->name)
{
charset = NULL;
continue;
}
charset->selected = 1;
break;
}
}
if (!charset)
{
/* this should never happen */
(void) fprintf(real_stderr, "no recognized font charsets!\n");
exit(1);
}
}
void
fe_ReadFontSpec(char *spec)
{
fe_FontCharSet *charset;
char *charSetName;
fe_FontFamily *family;
char *familyName;
char *foundry;
int i;
int j;
int k;
int m;
char *p;
fe_FontPitch *pitch;
char *pitchName;
char *s;
char *scaling;
fe_FontSize *size;
char *sizeName;
int sizeNum;
s = strdup(spec);
if (!s)
{
return;
}
p = s;
foundry = p;
p = strchr(p, '-');
if (!p)
{
return;
}
*p++ = 0;
familyName = p;
p = strchr(p, '-');
if (!p)
{
return;
}
*p++ = 0;
sizeName = p;
p = strchr(p, '-');
if (!p)
{
return;
}
*p++ = 0;
(void) sscanf(sizeName, "%d", &sizeNum);
scaling = p;
p = strchr(p, '-');
if (!p)
{
return;
}
*p++ = 0;
pitchName = p;
p = strchr(p, '-');
if (!p)
{
return;
}
*p++ = 0;
charSetName = p;
for (i = 0; i < INTL_CHAR_SET_MAX; i++)
{
charset = &fe_FontCharSets[i];
if ((!charset->name) || strcmp(charset->mimeName, charSetName))
{
continue;
}
j = (*pitchName == 'p' ? 0 : 1);
pitch = &charset->pitches[j];
family = NULL;
for (k = 0; k < pitch->numberOfFamilies; k++)
{
family = &pitch->families[k];
if ((!strcmp(family->foundry, foundry)) &&
(!strcmp(family->family, familyName)))
{
break;
}
else
{
family = NULL;
}
}
if (family)
{
for (k = 0; k < pitch->numberOfFamilies; k++)
{
pitch->families[k].selected = 0;
}
family->selected = 1;
pitch->selectedFamily = family;
family->allowScaling = (((*scaling) == 's') ? 1 : 0);
/*
* sanity check
*/
if (family->pointSizes->size)
{
family->allowScaling = 0;
}
else if (family->numberOfPointSizes == 1)
{
family->allowScaling = 1;
}
size = NULL;
for (m = 0; m < family->numberOfPointSizes; m++)
{
size = &family->pointSizes[m];
if (size->size == sizeNum)
{
break;
}
else
{
size = NULL;
}
}
if (size)
{
for (m = 0; m < family->numberOfPointSizes; m++)
{
family->pointSizes[m].selected = 0;
}
size->selected = 1;
}
else if (family->allowScaling)
{
for (m = 0; m < family->numberOfPointSizes; m++)
{
family->pointSizes[m].selected = 0;
}
family->pointSizes[0].selected = 1;
family->scaledSize = sizeNum;
}
}
break;
}
free(s);
}
static fe_FontSize *
fe_GetScaledFontSize(fe_FontFamily *family, double idealSize)
{
fe_FontFace *face;
int i;
fe_FontSize *ret;
ret = FE_MALLOC_ZAP(fe_FontSize);
if (!ret)
{
return NULL;
}
ret->next = fe_FontSizeList;
fe_FontSizeList = ret;
ret->size = idealSize;
for (i = 0; i < 4; i++)
{
ret->faces[i] = FE_MALLOC_ZAP(fe_FontFace);
face = ret->faces[i];
if (!face)
{
return NULL;
}
face->next = fe_FontFaceList;
fe_FontFaceList = face;
face->longXLFDFontName = PR_smprintf(
family->pointSizes->faces[i]->longXLFDFontName,
ret->size);
if (!face->longXLFDFontName)
{
return NULL;
}
}
return ret;
}
static fe_FontSize *
fe_ComputeFontSize(fe_FontFamily *family, double idealSize)
{
int i;
double minDist;
fe_FontSize *minSize;
fe_FontSize *maxSize;
double newDist;
fe_FontSize *ret;
fe_FontSize *size;
ret = NULL;
if (family->allowScaling)
{
return fe_GetScaledFontSize(family, idealSize);
}
if (family->pointSizes->size == 0)
{
minSize = &family->pointSizes[1];
}
else
{
minSize = family->pointSizes;
}
maxSize = &family->pointSizes[family->numberOfPointSizes - 1];
if ((idealSize < minSize->size) || (idealSize > maxSize->size))
{
if (idealSize > maxSize->size)
{
ret = maxSize;
}
if (idealSize < minSize->size)
{
ret = minSize;
}
}
else
{
minDist = (1E+36);
ret = family->pointSizes;
for (i = 0; i < family->numberOfPointSizes; i++)
{
size = &family->pointSizes[i];
newDist = ((idealSize - size->size) *
(idealSize - size->size));
if (newDist < minDist)
{
minDist = newDist;
ret = size;
}
else
{
break;
}
}
}
return ret;
}
void
fe_FreeFontGroups(void)
{
fe_FontCharSet *charset;
fe_FontFace *face;
int i;
int j;
int k;
int m;
fe_FontPitch *pitch;
fe_FontSize *size;
for (i = 0; i < INTL_CHAR_SET_MAX; i++)
{
charset = &fe_FontCharSets[i];
if (fe_CharSetInfoArray[i].type == FE_FONT_TYPE_GROUP)
{
for (j = 0; j < 2; j++)
{
pitch = &charset->pitches[j];
if (!pitch->selectedFamily)
{
continue;
}
for (k = 0; k < 7; k++)
{
size = pitch->selectedFamily->htmlSizes[k];
if (size)
{
for (m = 0; m < 4; m++)
{
face = size->faces[m];
if (face)
{
free(face);
}
}
free(size);
}
}
free(pitch->selectedFamily);
pitch->selectedFamily = NULL;
}
}
}
}
void
fe_FreeFontSizeTable(fe_FontFamily *family)
{
int k,m;
fe_FontSize *size;
fe_FontFace *face;
if (!family->htmlSizesComputed) return;
family->htmlSizesComputed = 0;
/*
* Only the scaled fonts were allocated new sizes. Hence we free
* only them.
*/
if (!family->allowScaling) return;
for (k = 0; k < 7; k++)
{
size = family->htmlSizes[k];
if (size)
{
for (m = 0; m < 4; m++)
{
face = size->faces[m];
if (face)
{
free(face);
}
}
free(size);
family->htmlSizes[k] = NULL;
}
}
}
void
fe_ComputeFontSizeTable(fe_FontFamily *family)
{
int i;
double idealSize;
int j;
fe_FontSize *size;
int size3;
size = NULL;
/*
* first, find the size selected within the family
*/
for (j = 0; j < family->numberOfPointSizes; j++)
{
size = &family->pointSizes[j];
if (size->selected)
{
break;
}
else
{
size = NULL;
}
}
if ((!family) || (!size))
{
/* this should not happen */
return;
}
fe_FreeFontGroups();
fe_FreeFontSizeTable(family);
/*
* set the default size (3)
*/
size3 = size->size;
if (!size3)
{
size3 = family->scaledSize;
}
if (!size3)
{
size3 = 120;
}
i = 3;
idealSize = size3;
family->htmlSizes[i - 1] = fe_ComputeFontSize(family, idealSize);
/*
* set the higher sizes (4-7)
*/
for (i = 4; i <= 7; i++)
{
idealSize = ((1 + ((i - 3) * fe_FontSizeIncrement)) * size3);
family->htmlSizes[i - 1] = fe_ComputeFontSize(family, idealSize);
}
/*
* set the lower sizes (1-2)
*/
for (i = 1; i <= 2; i++)
{
idealSize = ((1 - ((3 - i) * fe_FontSizeIncrement)) * size3);
if (idealSize < 10)
{
idealSize = 10;
}
family->htmlSizes[i - 1] = fe_ComputeFontSize(family, idealSize);
}
/*
* mark family that htmlSizes has been computed.
*/
family->htmlSizesComputed = 1;
/* @@@ need to implement this in case any of the scaled
* sizes couldn't be malloc'ed -- erik
* fe_CheckFonts();
*/
}
static int
fe_CloneFamily(fe_FontFamily *cloneFamily, fe_FontFamily *origFamily)
{
int i;
cloneFamily->name = strdup(origFamily->name);
cloneFamily->foundry = strdup(origFamily->foundry);
cloneFamily->family = strdup(origFamily->family);
if ((!cloneFamily->name) || (!cloneFamily->foundry) ||
(!cloneFamily->family))
{
return 0;
}
cloneFamily->selected = origFamily->selected;
cloneFamily->allowScaling = origFamily->allowScaling;
cloneFamily->pointAlloc = origFamily->pointAlloc;
cloneFamily->numberOfPointSizes = origFamily->numberOfPointSizes;
cloneFamily->pointSizes = XP_CALLOC(cloneFamily->pointAlloc,
sizeof(fe_FontSize));
if (!cloneFamily->pointSizes)
{
return 0;
}
for (i = 0; i < cloneFamily->numberOfPointSizes; i++)
{
cloneFamily->pointSizes[i] = origFamily->pointSizes[i];
}
if (origFamily->allowScaling)
{
/*
* For scaled families, take care to copy the sizes and faces.
* Setting this will make the sizes get recomputed.
*/
cloneFamily->htmlSizesComputed = 0;
}
else
{
cloneFamily->htmlSizesComputed = origFamily->htmlSizesComputed;
for (i = 0; i < 7; i++)
{
cloneFamily->htmlSizes[i] = origFamily->htmlSizes[i];
}
}
return 1;
}
static int
fe_ClonePitch(fe_FontPitch *clonePitch, fe_FontPitch *origPitch)
{
int i;
clonePitch->alloc = origPitch->alloc;
clonePitch->numberOfFamilies = origPitch->numberOfFamilies;
clonePitch->families = XP_CALLOC(clonePitch->alloc,
sizeof(fe_FontFamily));
if (!clonePitch->families)
{
return 0;
}
for (i = 0; i < clonePitch->numberOfFamilies; i++)
{
if (!fe_CloneFamily(&clonePitch->families[i],
&origPitch->families[i]))
{
return 0;
}
}
clonePitch->selectedFamily = NULL;
return 1;
}
static void
fe_SetDefaultFontSettings(Display *dpy)
{
fe_FontCharSet *charset;
char *charsetname;
char clas[512];
XrmDatabase db;
fe_FontFace **faces;
fe_FontFamily *family;
int i;
int j;
int k;
int m;
char name[512];
fe_FontPitch *pitch;
fe_FontSize *size;
char *spec;
char *type;
XrmValue value;
db = XtDatabase(dpy);
/*
* try to get the default charset from the resources
*/
(void) PR_snprintf(clas, sizeof(clas),
"%s.DocumentFonts.DefaultCharSet", fe_progclass);
(void) PR_snprintf(name, sizeof(name),
"%s.documentFonts.defaultCharSet", fe_progclass);
if (XrmGetResource(db, name, clas, &type, &value))
{
charsetname = (char *) value.addr;
}
else
{
charsetname = "iso-8859-1";
}
fe_ReadFontCharSet(charsetname);
/*
* try to get the default fonts from the resources
*/
for (i = 0; i < INTL_CHAR_SET_MAX; i++)
{
charset = &fe_FontCharSets[i];
if (!charset->name)
{
continue;
}
for (j = 0; j < 2; j++)
{
(void) PR_snprintf(clas, sizeof(clas),
"%s.DocumentFonts.DefaultFont.CharSet.Pitch",
fe_progclass);
(void) PR_snprintf(name, sizeof(name),
"%s.documentFonts.defaultFont.%s.%s",
fe_progclass, charset->mimeName,
fe_PropOrFixedFont(j));
if (XrmGetResource(db, name, clas, &type, &value))
{
spec = PR_smprintf("%s-%s-%s",
(char *) value.addr,
fe_PropOrFixedFont(j),
charset->mimeName);
if (!spec)
{
continue;
}
fe_ReadFontSpec(spec);
free(spec);
}
}
}
/*
* make sure we have families set for each charset/pitch,
* and sizes set for each family
*/
for (i = 0; i < INTL_CHAR_SET_MAX; i++)
{
charset = &fe_FontCharSets[i];
if (!charset->name)
{
continue;
}
for (j = 0; j < 2; j++)
{
pitch = &charset->pitches[j];
for (k = 0; k < pitch->numberOfFamilies; k++)
{
family = &pitch->families[k];
for (m = 0; m < family->numberOfPointSizes; m++)
{
faces = family->pointSizes[m].faces;
if (!faces[0])
{
if (faces[1])
{
faces[0] = faces[1];
}
else if (faces[2])
{
faces[0] = faces[2];
}
else
{
faces[0] = faces[3];
}
}
if (!faces[1])
{
if (faces[3])
{
faces[1] = faces[3];
}
else if (faces[2])
{
faces[1] = faces[2];
}
else
{
faces[1] = faces[0];
}
}
if (!faces[2])
{
if (faces[3])
{
faces[2] = faces[3];
}
else if (faces[1])
{
faces[2] = faces[1];
}
else
{
faces[2] = faces[0];
}
}
if (!faces[3])
{
if (faces[1])
{
faces[3] = faces[1];
}
else if (faces[2])
{
faces[3] = faces[2];
}
else
{
faces[3] = faces[0];
}
}
}
/*
* make sure a size is selected for each family
*/
size = NULL;
for (m = 0; m < family->numberOfPointSizes; m++)
{
size = &family->pointSizes[m];
if (size->selected)
{
break;
}
else
{
size = NULL;
}
}
if ((!size) && family->numberOfPointSizes)
{
size = &family->pointSizes
[(family->numberOfPointSizes+1)/2-1];
size->selected = 1;
}
/*
* determine whether or not we allow scaling
* from the available sizes
*/
if ((family->numberOfPointSizes == 1) &&
(family->pointSizes->size == 0))
{
family->allowScaling = 1;
}
}
/*
* make sure a family is selected for each pitch
*/
family = NULL;
for (k = 0; k < pitch->numberOfFamilies; k++)
{
family = &pitch->families[k];
if (family->selected)
{
break;
}
else
{
family = NULL;
}
}
if ((!family) && pitch->numberOfFamilies)
{
family = &pitch->families[0];
family->selected = 1;
}
/* Force recomputation */
if (family) fe_FreeFontSizeTable(family);
}
/*
* if some charset has fonts in one pitch, but not the
* other, we clone the one that is available, so that
* we always have a pitch available
*/
if (!charset->pitches[0].families)
{
if (!fe_ClonePitch(&charset->pitches[0],
&charset->pitches[1]))
{
/*
* if we can't clone the pitch, we
* disable the whole charset
*/
free(charset->name);
charset->name = NULL;
}
}
else if (!charset->pitches[1].families)
{
if (!fe_ClonePitch(&charset->pitches[1],
&charset->pitches[0]))
{
/*
* if we can't clone the pitch, we
* disable the whole charset
*/
free(charset->name);
charset->name = NULL;
}
}
}
}
static void
fe_ReportFontCharSets(void)
{
fe_FontCharSet *charset;
int16 *charsets;
int i;
int j;
charsets = calloc(INTL_CHAR_SET_MAX, sizeof(*charsets));
if (!charsets)
{
return;
}
j = 0;
for (i = 1; i < INTL_CHAR_SET_MAX; i++)
{
charset = &fe_FontCharSets[i];
if (!charset->name)
{
continue;
}
charsets[j++] = fe_CharSetInfoArray[i].charsetID;
}
INTL_ReportFontCharSets(charsets);
}
static fe_Font
fe_LoadXFont(Display *dpy, char *name)
{
XFontStruct *f;
f = XLoadQueryFont(dpy, name);
if (f)
{
/*
* The width check is from xemacs.
* The ascent check is from Sun's AWT.
*/
if ((!f->max_bounds.width) || (f->ascent < 0))
{
XFreeFont(dpy, f);
f = NULL;
}
}
return (fe_Font) f;
}
void
fe_InitFonts(Display *dpy)
{
#ifdef SOLARIS
char *avgwidth;
int avgWidthNum;
#endif
char *charset;
int16 charsetID;
char *charsetlang;
char clas[512];
int count;
XrmDatabase db;
int face;
char *family;
char *font;
char **fonts;
char *foundry;
int i;
int j;
char name[512];
char *origCharset;
char *origFamily;
char *origFoundry;
char *origWeight;
char *p;
int pitch;
char *pixelSize;
char *pixelSizeFontSpec;
int pixelSizeNum;
char *pointSize;
char *pointSizeFontSpec;
int pointSizeNum;
char *resx;
char *setwidth;
char *spacing;
char *type;
XrmValue value;
char *weight;
char *xResolution;
char *yResolution;
#ifdef SOLARIS
avgwidth = NULL;
#endif
charset = NULL;
charsetlang = NULL;
family = NULL;
font = NULL;
fonts = NULL;
foundry = NULL;
origCharset = NULL;
origFamily = NULL;
origFoundry = NULL;
origWeight = NULL;
p = NULL;
pixelSize = NULL;
pixelSizeFontSpec = NULL;
pointSize = NULL;
pointSizeFontSpec = NULL;
resx = NULL;
setwidth = NULL;
spacing = NULL;
type = NULL;
weight = NULL;
xResolution = NULL;
yResolution = NULL;
/*
* do this first so that we are very likely to have this
* font available if/when we fail to load any other font
*/
fe_FixedFont = fe_LoadXFont(dpy, "fixed");
fe_GetLocaleCharSets(dpy);
#ifdef DEBUG
if (sizeof(fe_CharSetInfoArray) / sizeof(*fe_CharSetInfoArray) !=
INTL_CHAR_SET_MAX)
{
(void) fprintf(real_stderr,
"fe_CharSetInfoArray broken (size)\n");
fe_Exit(1);
}
for (i = 0; i < INTL_CHAR_SET_MAX; i++)
{
if ((fe_CharSetInfoArray[i].charsetID & 0xff) != i)
{
(void) fprintf(real_stderr,
"fe_CharSetInfoArray broken (%d)\n", i);
fe_Exit(1);
}
}
#endif /* DEBUG */
fonts = XListFonts(dpy, "*", INT_MAX, &count);
if (!fonts)
{
return;
}
(void) memset(fe_FontCharSets, 0, sizeof(fe_FontCharSets));
for (i = 0; i < count; i++)
{
FE_MAYBE_FREE(font);
FE_MAYBE_FREE(origCharset);
FE_MAYBE_FREE(origFamily);
FE_MAYBE_FREE(origWeight);
FE_MAYBE_FREE(pixelSizeFontSpec);
FE_MAYBE_FREE(pointSizeFontSpec);
/* ignore the non-XLFD short names */
if ((!fonts[i]) || (fonts[i][0] != '-'))
{
continue;
}
font = strdup(fonts[i]);
if (!font)
{
continue;
}
p = font;
j = 0;
while (1)
{
p = strchr(p, '-');
if (!p)
{
break;
}
p++;
switch (j)
{
case 0:
foundry = p;
break;
case 1:
family = p;
break;
case 2:
weight = p;
break;
case 4:
setwidth = p;
break;
case 6:
pixelSize = p;
break;
case 7:
pointSize = p;
break;
case 8:
resx = p;
break;
case 10:
spacing = p;
break;
#ifdef SOLARIS
case 11:
avgwidth = p;
break;
#endif
case 12:
charset = p;
break;
default:
break;
}
j++;
}
if (j < 14)
{
/* skip non-XLFD names */
continue;
}
/* Skip Applix fonts -- if these are installed, there are
hundreds of them, and they do not have proper XLFD names:
the bold/italic/etc versions of the fonts have different
*families* as well ("axhvr" for Helvetica-normal,
"axhvb" for Helvetica-bold, etc) so all they do is bloat
the menus and make the UI unusable.
*/
if (family &&
strncasecomp(family, "ax", 2) &&
XP_STRLEN(family) == 5)
continue;
db = XtDatabase(dpy);
(void) PR_snprintf(clas, sizeof(clas),
"%s.DocumentFonts.Foundry.Name", fe_progclass);
family[-1] = 0;
(void) PR_snprintf(name, sizeof(name),
"%s.documentFonts.foundry.%s", fe_progclass, foundry);
origFoundry = strdup(foundry);
if (!origFoundry)
{
continue;
}
if (XrmGetResource(db, name, clas, &type, &value))
{
foundry = strdup((char *) value.addr);
}
else
{
foundry = fe_CapitalizeFontName(foundry);
}
if (!foundry)
{
continue;
}
(void) PR_snprintf(clas, sizeof(clas),
"%s.DocumentFonts.Family.Name", fe_progclass);
weight[-1] = 0;
(void) PR_snprintf(name, sizeof(name),
"%s.documentFonts.family.%s", fe_progclass, family);
origFamily = strdup(family);
if (!origFamily)
{
continue;
}
if (XrmGetResource(db, name, clas, &type, &value))
{
family = strdup((char *) value.addr);
}
else
{
family = fe_CapitalizeFontName(family);
}
if (!family)
{
continue;
}
(void) PR_snprintf(clas, sizeof(clas),
"%s.DocumentFonts.Face.Name", fe_progclass);
setwidth[-1] = 0;
(void) PR_snprintf(name, sizeof(name),
"%s.documentFonts.face.%s", fe_progclass, weight);
origWeight = strdup(weight);
if (!origWeight)
{
continue;
}
if (XrmGetResource(db, name, clas, &type, &value))
{
weight = (char *) value.addr;
}
else
{
#if 0 /* jwz */
#ifdef DEBUG
(void) fprintf(real_stderr, "face %s\n", weight);
#endif /* DEBUG */
#endif /* 0 -- jwz */
weight = "";
}
if (!strcmp(weight, "bold"))
{
face = 1;
}
else if (!strcmp(weight, "boldItalic"))
{
face = 3;
}
else if (!strcmp(weight, "italic"))
{
face = 2;
}
else
{
face = 0;
}
pointSize[-1] = 0;
sscanf(pixelSize, "%d", &pixelSizeNum);
if (pixelSizeNum < 0)
{
continue;
}
resx[-1] = 0;
sscanf(pointSize, "%d", &pointSizeNum);
if (pointSizeNum < 0)
{
continue;
}
switch (spacing[0])
{
case 'm':
pitch = fe_FONT_PITCH_MONO;
break;
case 'p':
pitch = fe_FONT_PITCH_PROPORTIONAL;
break;
case 'c':
/* fall through */
default:
pitch = fe_FONT_PITCH_BOTH;
break;
}
#ifdef SOLARIS
charset[-1] = 0;
sscanf(avgwidth, "%d", &avgWidthNum);
if (avgWidthNum < 0)
{
continue;
}
#endif
(void) PR_snprintf(clas, sizeof(clas),
"%s.DocumentFonts.CharSet.Family.Name", fe_progclass);
(void) PR_snprintf(name, sizeof(name),
"%s.documentFonts.charset.%s.%s", fe_progclass,
origFamily, charset);
origCharset = strdup(charset);
if (!origCharset)
{
continue;
}
charsetlang = charset;
if (XrmGetResource(db, name, clas, &type, &value))
{
charset = (char *) value.addr;
}
else
{
/*
* if the user has messed with the app-defaults, we
* might not be able to find our mapping, so check for
* the following at least
*/
if (!strcmp(charset, "iso8859-1"))
{
charset = "iso-8859-1";
}
#if 0 /* jwz */
#ifdef DEBUG
else
{
(void) fprintf(real_stderr, "charset %s %s\n",
origFamily, charsetlang);
}
#endif /* DEBUG */
#endif /* 0 -- jwz */
}
charsetID = (INTL_CharSetNameToID(charset) & 0xff);
#ifdef SOLARIS
if (charsetID == (CS_GB2312 & 0xff))
{
/*
* Simplified Chinese Solaris has broken fonts that
* say GB2312 but are actually ASCII fonts. Skip 'em.
*/
if (avgWidthNum && (avgWidthNum == (pointSizeNum / 2)))
{
continue;
}
}
else
{
avgwidth = "*";
}
#endif /* SOLARIS */
#if 0 /* jwz */
#ifdef DEBUG
if ((charsetID == CS_UNKNOWN) && strcmp(charset, "x-ignore"))
{
(void) fprintf(real_stderr, "internal %s %s %s\n",
origFamily, charsetlang, charset);
}
#endif /* DEBUG */
#endif /* 0 -- jwz */
if (!strcmp(charset, "x-ignore"))
{
charsetID = CS_USRDEF2;
}
if (charsetID >= INTL_CHAR_SET_MAX)
{
charsetID = CS_USRDEF2;
}
if (fe_CharSetInfoArray[charsetID].type == FE_FONT_TYPE_GROUP)
{
continue;
}
(void) PR_snprintf(clas, sizeof(clas),
"%s.DocumentFonts.CharSetLang.Name", fe_progclass);
(void) PR_snprintf(name, sizeof(name),
"%s.documentFonts.charsetlang.%s", fe_progclass,
charset);
if (XrmGetResource(db, name, clas, &type, &value))
{
charsetlang = (char *) value.addr;
}
else
{
#if 0
(void) fprintf(real_stderr, "charsetlang %s\n",
charsetlang);
#endif /* 0 */
charsetlang = XP_GetString(XFE_OTHER_LANGUAGE);
}
(void) PR_snprintf(clas, sizeof(clas),
"%s.DocumentFonts.XResolution.CharSet", fe_progclass);
(void) PR_snprintf(name, sizeof(name),
"%s.documentFonts.xResolution.%s", fe_progclass,
charset);
if (XrmGetResource(db, name, clas, &type, &value))
{
xResolution = (char *) value.addr;
}
else
{
xResolution = "*";
}
(void) PR_snprintf(clas, sizeof(clas),
"%s.DocumentFonts.YResolution.CharSet", fe_progclass);
(void) PR_snprintf(name, sizeof(name),
"%s.documentFonts.yResolution.%s", fe_progclass,
charset);
if (XrmGetResource(db, name, clas, &type, &value))
{
yResolution = (char *) value.addr;
}
else
{
yResolution = "*";
}
#ifdef SOLARIS
if (pixelSizeNum)
{
pixelSizeFontSpec = PR_smprintf(
"-%s-%s-%s-*-*-%d-*-*-*-*-%s-%s", origFoundry,
origFamily, origWeight, pixelSizeNum, avgwidth,
origCharset);
}
else
{
pixelSizeFontSpec = PR_smprintf(
"-%s-%s-%s-*-*-%%d-*-*-*-*-%s-%s", origFoundry,
origFamily, origWeight, avgwidth, origCharset);
}
if (!pixelSizeFontSpec)
{
continue;
}
if (pointSizeNum)
{
pointSizeFontSpec = PR_smprintf(
"-%s-%s-%s-*-*-*-%d-%s-%s-*-%s-%s",
origFoundry, origFamily, origWeight,
pointSizeNum, xResolution, yResolution,
avgwidth, origCharset);
}
else
{
pointSizeFontSpec = PR_smprintf(
"-%s-%s-%s-*-*-*-%%d-%s-%s-*-%s-%s",
origFoundry, origFamily, origWeight,
xResolution, yResolution, avgwidth,
origCharset);
}
if (!pointSizeFontSpec)
{
continue;
}
#else /* SOLARIS */
if (pixelSizeNum)
{
pixelSizeFontSpec = PR_smprintf(
"-%s-%s-%s-*-*-%d-*-*-*-*-*-%s", origFoundry,
origFamily, origWeight, pixelSizeNum,
origCharset);
}
else
{
pixelSizeFontSpec = PR_smprintf(
"-%s-%s-%s-*-*-%%d-*-*-*-*-*-%s", origFoundry,
origFamily, origWeight, origCharset);
}
if (!pixelSizeFontSpec)
{
continue;
}
if (pointSizeNum)
{
pointSizeFontSpec = PR_smprintf(
"-%s-%s-%s-*-*-*-%d-%s-%s-*-*-%s", origFoundry,
origFamily, origWeight, pointSizeNum,
xResolution, yResolution, origCharset);
}
else
{
pointSizeFontSpec = PR_smprintf(
"-%s-%s-%s-*-*-*-%%d-%s-%s-*-*-%s",
origFoundry, origFamily, origWeight,
xResolution, yResolution, origCharset);
}
if (!pointSizeFontSpec)
{
continue;
}
#endif /* SOLARIS */
fe_AddFontCharSet(origFoundry, foundry, origFamily, family,
face, pixelSizeNum, pointSizeNum, pitch, charsetID,
charset, charsetlang, pixelSizeFontSpec,
pointSizeFontSpec, origCharset);
#if 0
(void) fprintf
(
real_stderr,
"\"%s\" \"%s\" \"%s\" %d \"%s%s\" %d \"%s\" \"%s\"\n\"%s\"\n",
foundry,
family,
FE_INDEX_TO_FACE(face),
pointSizeNum,
((pitch & fe_FONT_PITCH_MONO) ? "m" : ""),
((pitch & fe_FONT_PITCH_PROPORTIONAL) ? "p" : ""),
charsetID,
charset,
charsetlang,
pointSizeFontSpec
);
#endif /* 0 */
free(origFoundry);
free(foundry);
free(family);
}
FE_MAYBE_FREE(font);
FE_MAYBE_FREE(origCharset);
FE_MAYBE_FREE(origFamily);
FE_MAYBE_FREE(origWeight);
FE_MAYBE_FREE(pixelSizeFontSpec);
FE_MAYBE_FREE(pointSizeFontSpec);
XFreeFontNames(fonts);
(void) PR_snprintf(clas, sizeof(clas),
"%s.DocumentFonts.SizeIncrement", fe_progclass);
(void) PR_snprintf(name, sizeof(name),
"%s.documentFonts.sizeIncrement", fe_progclass);
if (XrmGetResource(db, name, clas, &type, &value))
{
fe_FontSizeIncrement = (((double) atoi(value.addr)) / 100.0);
if (fe_FontSizeIncrement <= 0)
{
fe_FontSizeIncrement = FE_DEFAULT_FONT_SIZE_INCREMENT;
}
}
fe_SortFonts();
fe_SetDefaultFontSettings(dpy);
fe_ReportFontCharSets();
#ifdef FE_PRINT_FONTS
fe_PrintFonts();
#endif
}
#ifdef DEBUG
void
fe_FreeFonts(void)
{
fe_FontCharSet *charset;
fe_FontFace *face;
fe_FontFamily *family;
int i;
int j;
int k;
fe_FontFace *nextFace;
fe_FontPitch *pitch;
for (i = 0; i < INTL_CHAR_SET_MAX; i++)
{
charset = &fe_FontCharSets[i];
if (!charset->name)
{
continue;
}
for (j = 0; j < 2; j++)
{
pitch = &charset->pitches[j];
for (k = 0; k < pitch->numberOfFamilies; k++)
{
family = &pitch->families[k];
free(family->name);
free(family->foundry);
free(family->family);
free(family->pixelSizes);
free(family->pointSizes);
}
free(pitch->families);
}
free(charset->name);
free(charset->mimeName);
}
(void) memset(fe_FontCharSets, 0, sizeof(fe_FontCharSets));
face = fe_FontFaceList;
while (face)
{
nextFace = face->next;
if (face->longXLFDFontName)
{
free(face->longXLFDFontName);
}
if (face->font)
{
XFreeFont(fe_display, face->font);
}
free(face);
face = nextFace;
}
fe_FontFaceList = NULL;
if (fe_FixedFont)
{
XFreeFont(fe_display, fe_FixedFont);
fe_FixedFont = NULL;
}
}
#endif /* DEBUG */
static void
fe_AddFontSetting(fe_FontSettings **ret, fe_FontCharSet *charset, int i,
fe_FontFamily *family, fe_FontSize *size)
{
fe_FontSettings *set;
char *spec;
spec = PR_smprintf
(
"%s-%s-%d-%s-%s-%s\n",
family->foundry,
family->family,
size->size,
family->allowScaling ? "scale" : "noscale",
fe_PropOrFixedFont(i),
charset->mimeName
);
set = FE_MALLOC_ZAP(fe_FontSettings);
if ((!spec) || (!set))
{
return;
}
set->spec = spec;
set->next = *ret;
*ret = set;
}
fe_FontSettings *
fe_GetFontSettings(void)
{
fe_FontCharSet *charset;
fe_FontFamily *family;
int i;
int j;
int k;
int m;
fe_FontPitch *pitch;
fe_FontSettings *ret;
fe_FontSize *size;
ret = NULL;
for (i = 0; i < INTL_CHAR_SET_MAX; i++)
{
charset = &fe_FontCharSets[i];
if (!charset->name)
{
continue;
}
for (j = 0; j < 2; j++)
{
pitch = &charset->pitches[j];
for (k = 0; k < pitch->numberOfFamilies; k++)
{
family = &pitch->families[k];
if (family->selected)
{
for (m = 0; m < family->numberOfPointSizes;
m++)
{
size = &family->pointSizes[m];
if (size->selected)
{
fe_AddFontSetting
(
&ret,
charset,
j,
family,
size
);
}
}
}
}
}
}
return ret;
}
void
fe_SetFontSettings(fe_FontSettings *set)
{
}
char *
fe_GetFontCharSetSetting(void)
{
fe_FontCharSet *charset;
int i;
for (i = 0; i < INTL_CHAR_SET_MAX; i++)
{
charset = &fe_FontCharSets[i];
if (!charset->name)
{
continue;
}
if (charset->selected)
{
return charset->mimeName;
}
}
return "";
}
void
fe_FreeFontSettings(fe_FontSettings *set)
{
fe_FontSettings *next;
while (set)
{
next = set->next;
free(set->spec);
free(set);
set = next;
}
}
int
fe_GetStrikePosition(int charset, fe_Font font)
{
int ascent;
int descent;
XCharStruct overall;
/*
* strike through the middle of lower case letters
*/
FE_TEXT_EXTENTS(charset, font, "a", 1, &ascent, &descent, &overall);
return -((overall.ascent + 1) / 2);
}
int
fe_GetUnderlinePosition(int charset)
{
/*
* Underline position does not depend on font, otherwise you get
* varying positions within a single line, and this looks bad.
*/
if (fe_CharSetInfoArray[charset & 0xff].type == FE_FONT_TYPE_GROUP)
{
/*
* East Asian fonts have a lower baseline.
* Underline looks better like this.
*/
return 3;
}
return 1;
}
static fe_Font
fe_LoadNormalFont(MWContext *context, char *familyName, int sizeNum,
int fontmask, int charset,
int pitch, int faceNum, Display *dpy)
{
fe_FontFace *face;
fe_Font font;
fe_FontFamily *family = NULL;
if (familyName && *familyName)
{
family = fe_FontFindFamily(charset, pitch, familyName);
}
if (!family)
{
family = FE_FONT_SELECTED_FAMILY(charset,pitch);
if (!family)
{
return NULL;
}
}
if (!family->htmlSizesComputed)
{
fe_ComputeFontSizeTable(family);
}
face = family->htmlSizes[sizeNum-1]->faces[faceNum];
font = face->font;
if (font)
{
return font;
}
font = fe_LoadXFont(dpy, face->longXLFDFontName);
if (font)
{
face->font = font;
return font;
}
return NULL;
}
void
fe_GenericFontExtents(int num, fe_Font font, int *fontAscent, int *fontDescent)
{
int ascent;
int ascentExtra;
int descent;
int descentExtra;
XFontStruct *f;
fe_FontGroupFont *fonts;
int i;
fonts = (fe_FontGroupFont *) font;
ascent = 0;
descent = 0;
for (i = 0; i < num; i++)
{
if (i)
{
/*
* East Asian text looks better with extra space for
* underline.
*/
ascentExtra = 1;
descentExtra = 2;
}
else
{
ascentExtra = 0;
descentExtra = 0;
}
f = fonts[i].xFont;
if (f)
{
if (f->ascent + ascentExtra > ascent)
{
ascent = f->ascent + ascentExtra;
}
if (f->descent + descentExtra > descent)
{
descent = f->descent + descentExtra;
}
}
}
*fontAscent = ascent;
*fontDescent = descent;
}
#define FE_PROCESS_STRING_BUFFER_SIZE 1024
static void
fe_ProcessString(fe_StringProcessTable *table, fe_XDrawStringFunc draw1,
fe_XDrawStringFunc draw2, Display *dpy, Drawable d, fe_Font fontGroup,
GC gc, int x, int y, unsigned char *in, unsigned int inEnd,
int *fontAscent, int *fontDescent, XCharStruct *overall,
unsigned char numberOfFonts)
{
int ascent;
int descent;
int direction;
fe_StringProcessTable *entry;
fe_FontGroupFont *font;
unsigned char fontIndex;
fe_FontGroupFont *fonts;
unsigned int inIndex;
unsigned char len;
unsigned char mask1;
unsigned char mask2;
XCharStruct metrics;
unsigned char nextFontIndex;
unsigned char out1[FE_PROCESS_STRING_BUFFER_SIZE];
XChar2b out2[FE_PROCESS_STRING_BUFFER_SIZE/2];
unsigned int out1Index;
unsigned int out2Index;
XChar2b *p;
unsigned char skip;
XFontStruct *xFont;
if (inEnd > FE_PROCESS_STRING_BUFFER_SIZE)
{
inEnd = FE_PROCESS_STRING_BUFFER_SIZE;
}
fonts = (fe_FontGroupFont *) fontGroup;
inIndex = 0;
out1Index = 0;
out2Index = 0;
if (overall)
{
overall->lbearing = 0;
overall->rbearing = 0;
overall->width = 0;
overall->ascent = 0;
overall->descent = 0;
}
while (inIndex < inEnd)
{
entry = &table[in[inIndex]];
skip = entry->skip;
len = entry->len;
fontIndex = entry->fontIndex;
font = &fonts[fontIndex];
xFont = font->xFont;
if (gc && xFont)
{
XSetFont(dpy, gc, xFont->fid);
}
if (len == 1)
{
while (inIndex < inEnd)
{
inIndex += skip;
if (inIndex >= inEnd)
{
break;
}
out1[out1Index++] = in[inIndex++];
if (inIndex >= inEnd)
{
break;
}
nextFontIndex = table[in[inIndex]].fontIndex;
if (nextFontIndex != fontIndex)
{
break;
}
}
if (out1Index && xFont)
{
XTextExtents(xFont, out1, out1Index,
&direction, &ascent, &descent,
&metrics);
if (draw1)
{
(*draw1)(dpy, d, gc, x, y,
out1, out1Index);
}
x += metrics.width;
if (overall)
{
overall->width += metrics.width;
if (metrics.ascent > overall->ascent)
{
overall->ascent =
metrics.ascent;
}
if (metrics.descent > overall->descent)
{
overall->descent =
metrics.descent;
}
}
}
out1Index = 0;
}
else
{
mask1 = font->mask1;
mask2 = font->mask2;
while (inIndex < inEnd)
{
inIndex += skip;
if ((inIndex + 1) >= inEnd)
{
inIndex++;
break;
}
p = &out2[out2Index++];
p->byte1 = (in[inIndex++] & mask1);
p->byte2 = (in[inIndex++] & mask2);
if (inIndex >= inEnd)
{
break;
}
nextFontIndex = table[in[inIndex]].fontIndex;
if (nextFontIndex != fontIndex)
{
break;
}
}
if (out2Index && xFont)
{
XTextExtents16(xFont, out2, out2Index,
&direction, &ascent, &descent,
&metrics);
if (draw2)
{
(*draw2)(dpy, d, gc, x, y,
(char *) out2, out2Index);
}
x += metrics.width;
if (overall)
{
overall->width += metrics.width;
if (metrics.ascent > overall->ascent)
{
overall->ascent =
metrics.ascent;
}
if (metrics.descent > overall->descent)
{
overall->descent =
metrics.descent;
}
}
}
out2Index = 0;
}
}
if (overall)
{
/* @@@ fix */
overall->rbearing = overall->width;
fe_GenericFontExtents(numberOfFonts, fontGroup, fontAscent,
fontDescent);
}
}
/* fontIndex skip len */
#define EUCCN_LATIN1 { 0, 0, 1 }
#define EUCCN_GB2312 { 1, 0, 2 }
static fe_StringProcessTable EUCCNTable[] =
{
/* 0x00 */ EUCCN_LATIN1,
/* 0x01 */ EUCCN_LATIN1,
/* 0x02 */ EUCCN_LATIN1,
/* 0x03 */ EUCCN_LATIN1,
/* 0x04 */ EUCCN_LATIN1,
/* 0x05 */ EUCCN_LATIN1,
/* 0x06 */ EUCCN_LATIN1,
/* 0x07 */ EUCCN_LATIN1,
/* 0x08 */ EUCCN_LATIN1,
/* 0x09 */ EUCCN_LATIN1,
/* 0x0a */ EUCCN_LATIN1,
/* 0x0b */ EUCCN_LATIN1,
/* 0x0c */ EUCCN_LATIN1,
/* 0x0d */ EUCCN_LATIN1,
/* 0x0e */ EUCCN_LATIN1,
/* 0x0f */ EUCCN_LATIN1,
/* 0x10 */ EUCCN_LATIN1,
/* 0x11 */ EUCCN_LATIN1,
/* 0x12 */ EUCCN_LATIN1,
/* 0x13 */ EUCCN_LATIN1,
/* 0x14 */ EUCCN_LATIN1,
/* 0x15 */ EUCCN_LATIN1,
/* 0x16 */ EUCCN_LATIN1,
/* 0x17 */ EUCCN_LATIN1,
/* 0x18 */ EUCCN_LATIN1,
/* 0x19 */ EUCCN_LATIN1,
/* 0x1a */ EUCCN_LATIN1,
/* 0x1b */ EUCCN_LATIN1,
/* 0x1c */ EUCCN_LATIN1,
/* 0x1d */ EUCCN_LATIN1,
/* 0x1e */ EUCCN_LATIN1,
/* 0x1f */ EUCCN_LATIN1,
/* 0x20 */ EUCCN_LATIN1,
/* 0x21 */ EUCCN_LATIN1,
/* 0x22 */ EUCCN_LATIN1,
/* 0x23 */ EUCCN_LATIN1,
/* 0x24 */ EUCCN_LATIN1,
/* 0x25 */ EUCCN_LATIN1,
/* 0x26 */ EUCCN_LATIN1,
/* 0x27 */ EUCCN_LATIN1,
/* 0x28 */ EUCCN_LATIN1,
/* 0x29 */ EUCCN_LATIN1,
/* 0x2a */ EUCCN_LATIN1,
/* 0x2b */ EUCCN_LATIN1,
/* 0x2c */ EUCCN_LATIN1,
/* 0x2d */ EUCCN_LATIN1,
/* 0x2e */ EUCCN_LATIN1,
/* 0x2f */ EUCCN_LATIN1,
/* 0x30 */ EUCCN_LATIN1,
/* 0x31 */ EUCCN_LATIN1,
/* 0x32 */ EUCCN_LATIN1,
/* 0x33 */ EUCCN_LATIN1,
/* 0x34 */ EUCCN_LATIN1,
/* 0x35 */ EUCCN_LATIN1,
/* 0x36 */ EUCCN_LATIN1,
/* 0x37 */ EUCCN_LATIN1,
/* 0x38 */ EUCCN_LATIN1,
/* 0x39 */ EUCCN_LATIN1,
/* 0x3a */ EUCCN_LATIN1,
/* 0x3b */ EUCCN_LATIN1,
/* 0x3c */ EUCCN_LATIN1,
/* 0x3d */ EUCCN_LATIN1,
/* 0x3e */ EUCCN_LATIN1,
/* 0x3f */ EUCCN_LATIN1,
/* 0x40 */ EUCCN_LATIN1,
/* 0x41 */ EUCCN_LATIN1,
/* 0x42 */ EUCCN_LATIN1,
/* 0x43 */ EUCCN_LATIN1,
/* 0x44 */ EUCCN_LATIN1,
/* 0x45 */ EUCCN_LATIN1,
/* 0x46 */ EUCCN_LATIN1,
/* 0x47 */ EUCCN_LATIN1,
/* 0x48 */ EUCCN_LATIN1,
/* 0x49 */ EUCCN_LATIN1,
/* 0x4a */ EUCCN_LATIN1,
/* 0x4b */ EUCCN_LATIN1,
/* 0x4c */ EUCCN_LATIN1,
/* 0x4d */ EUCCN_LATIN1,
/* 0x4e */ EUCCN_LATIN1,
/* 0x4f */ EUCCN_LATIN1,
/* 0x50 */ EUCCN_LATIN1,
/* 0x51 */ EUCCN_LATIN1,
/* 0x52 */ EUCCN_LATIN1,
/* 0x53 */ EUCCN_LATIN1,
/* 0x54 */ EUCCN_LATIN1,
/* 0x55 */ EUCCN_LATIN1,
/* 0x56 */ EUCCN_LATIN1,
/* 0x57 */ EUCCN_LATIN1,
/* 0x58 */ EUCCN_LATIN1,
/* 0x59 */ EUCCN_LATIN1,
/* 0x5a */ EUCCN_LATIN1,
/* 0x5b */ EUCCN_LATIN1,
/* 0x5c */ EUCCN_LATIN1,
/* 0x5d */ EUCCN_LATIN1,
/* 0x5e */ EUCCN_LATIN1,
/* 0x5f */ EUCCN_LATIN1,
/* 0x60 */ EUCCN_LATIN1,
/* 0x61 */ EUCCN_LATIN1,
/* 0x62 */ EUCCN_LATIN1,
/* 0x63 */ EUCCN_LATIN1,
/* 0x64 */ EUCCN_LATIN1,
/* 0x65 */ EUCCN_LATIN1,
/* 0x66 */ EUCCN_LATIN1,
/* 0x67 */ EUCCN_LATIN1,
/* 0x68 */ EUCCN_LATIN1,
/* 0x69 */ EUCCN_LATIN1,
/* 0x6a */ EUCCN_LATIN1,
/* 0x6b */ EUCCN_LATIN1,
/* 0x6c */ EUCCN_LATIN1,
/* 0x6d */ EUCCN_LATIN1,
/* 0x6e */ EUCCN_LATIN1,
/* 0x6f */ EUCCN_LATIN1,
/* 0x70 */ EUCCN_LATIN1,
/* 0x71 */ EUCCN_LATIN1,
/* 0x72 */ EUCCN_LATIN1,
/* 0x73 */ EUCCN_LATIN1,
/* 0x74 */ EUCCN_LATIN1,
/* 0x75 */ EUCCN_LATIN1,
/* 0x76 */ EUCCN_LATIN1,
/* 0x77 */ EUCCN_LATIN1,
/* 0x78 */ EUCCN_LATIN1,
/* 0x79 */ EUCCN_LATIN1,
/* 0x7a */ EUCCN_LATIN1,
/* 0x7b */ EUCCN_LATIN1,
/* 0x7c */ EUCCN_LATIN1,
/* 0x7d */ EUCCN_LATIN1,
/* 0x7e */ EUCCN_LATIN1,
/* 0x7f */ EUCCN_LATIN1,
/* 0x80 */ EUCCN_LATIN1,
/* 0x81 */ EUCCN_LATIN1,
/* 0x82 */ EUCCN_LATIN1,
/* 0x83 */ EUCCN_LATIN1,
/* 0x84 */ EUCCN_LATIN1,
/* 0x85 */ EUCCN_LATIN1,
/* 0x86 */ EUCCN_LATIN1,
/* 0x87 */ EUCCN_LATIN1,
/* 0x88 */ EUCCN_LATIN1,
/* 0x89 */ EUCCN_LATIN1,
/* 0x8a */ EUCCN_LATIN1,
/* 0x8b */ EUCCN_LATIN1,
/* 0x8c */ EUCCN_LATIN1,
/* 0x8d */ EUCCN_LATIN1,
/* 0x8e */ EUCCN_LATIN1,
/* 0x8f */ EUCCN_LATIN1,
/* 0x90 */ EUCCN_LATIN1,
/* 0x91 */ EUCCN_LATIN1,
/* 0x92 */ EUCCN_LATIN1,
/* 0x93 */ EUCCN_LATIN1,
/* 0x94 */ EUCCN_LATIN1,
/* 0x95 */ EUCCN_LATIN1,
/* 0x96 */ EUCCN_LATIN1,
/* 0x97 */ EUCCN_LATIN1,
/* 0x98 */ EUCCN_LATIN1,
/* 0x99 */ EUCCN_LATIN1,
/* 0x9a */ EUCCN_LATIN1,
/* 0x9b */ EUCCN_LATIN1,
/* 0x9c */ EUCCN_LATIN1,
/* 0x9d */ EUCCN_LATIN1,
/* 0x9e */ EUCCN_LATIN1,
/* 0x9f */ EUCCN_LATIN1,
/* 0xa0 */ EUCCN_LATIN1,
/* 0xa1 */ EUCCN_GB2312,
/* 0xa2 */ EUCCN_GB2312,
/* 0xa3 */ EUCCN_GB2312,
/* 0xa4 */ EUCCN_GB2312,
/* 0xa5 */ EUCCN_GB2312,
/* 0xa6 */ EUCCN_GB2312,
/* 0xa7 */ EUCCN_GB2312,
/* 0xa8 */ EUCCN_GB2312,
/* 0xa9 */ EUCCN_GB2312,
/* 0xaa */ EUCCN_GB2312,
/* 0xab */ EUCCN_GB2312,
/* 0xac */ EUCCN_GB2312,
/* 0xad */ EUCCN_GB2312,
/* 0xae */ EUCCN_GB2312,
/* 0xaf */ EUCCN_GB2312,
/* 0xb0 */ EUCCN_GB2312,
/* 0xb1 */ EUCCN_GB2312,
/* 0xb2 */ EUCCN_GB2312,
/* 0xb3 */ EUCCN_GB2312,
/* 0xb4 */ EUCCN_GB2312,
/* 0xb5 */ EUCCN_GB2312,
/* 0xb6 */ EUCCN_GB2312,
/* 0xb7 */ EUCCN_GB2312,
/* 0xb8 */ EUCCN_GB2312,
/* 0xb9 */ EUCCN_GB2312,
/* 0xba */ EUCCN_GB2312,
/* 0xbb */ EUCCN_GB2312,
/* 0xbc */ EUCCN_GB2312,
/* 0xbd */ EUCCN_GB2312,
/* 0xbe */ EUCCN_GB2312,
/* 0xbf */ EUCCN_GB2312,
/* 0xc0 */ EUCCN_GB2312,
/* 0xc1 */ EUCCN_GB2312,
/* 0xc2 */ EUCCN_GB2312,
/* 0xc3 */ EUCCN_GB2312,
/* 0xc4 */ EUCCN_GB2312,
/* 0xc5 */ EUCCN_GB2312,
/* 0xc6 */ EUCCN_GB2312,
/* 0xc7 */ EUCCN_GB2312,
/* 0xc8 */ EUCCN_GB2312,
/* 0xc9 */ EUCCN_GB2312,
/* 0xca */ EUCCN_GB2312,
/* 0xcb */ EUCCN_GB2312,
/* 0xcc */ EUCCN_GB2312,
/* 0xcd */ EUCCN_GB2312,
/* 0xce */ EUCCN_GB2312,
/* 0xcf */ EUCCN_GB2312,
/* 0xd0 */ EUCCN_GB2312,
/* 0xd1 */ EUCCN_GB2312,
/* 0xd2 */ EUCCN_GB2312,
/* 0xd3 */ EUCCN_GB2312,
/* 0xd4 */ EUCCN_GB2312,
/* 0xd5 */ EUCCN_GB2312,
/* 0xd6 */ EUCCN_GB2312,
/* 0xd7 */ EUCCN_GB2312,
/* 0xd8 */ EUCCN_GB2312,
/* 0xd9 */ EUCCN_GB2312,
/* 0xda */ EUCCN_GB2312,
/* 0xdb */ EUCCN_GB2312,
/* 0xdc */ EUCCN_GB2312,
/* 0xdd */ EUCCN_GB2312,
/* 0xde */ EUCCN_GB2312,
/* 0xdf */ EUCCN_GB2312,
/* 0xe0 */ EUCCN_GB2312,
/* 0xe1 */ EUCCN_GB2312,
/* 0xe2 */ EUCCN_GB2312,
/* 0xe3 */ EUCCN_GB2312,
/* 0xe4 */ EUCCN_GB2312,
/* 0xe5 */ EUCCN_GB2312,
/* 0xe6 */ EUCCN_GB2312,
/* 0xe7 */ EUCCN_GB2312,
/* 0xe8 */ EUCCN_GB2312,
/* 0xe9 */ EUCCN_GB2312,
/* 0xea */ EUCCN_GB2312,
/* 0xeb */ EUCCN_GB2312,
/* 0xec */ EUCCN_GB2312,
/* 0xed */ EUCCN_GB2312,
/* 0xee */ EUCCN_GB2312,
/* 0xef */ EUCCN_GB2312,
/* 0xf0 */ EUCCN_GB2312,
/* 0xf1 */ EUCCN_GB2312,
/* 0xf2 */ EUCCN_GB2312,
/* 0xf3 */ EUCCN_GB2312,
/* 0xf4 */ EUCCN_GB2312,
/* 0xf5 */ EUCCN_GB2312,
/* 0xf6 */ EUCCN_GB2312,
/* 0xf7 */ EUCCN_GB2312,
/* 0xf8 */ EUCCN_GB2312,
/* 0xf9 */ EUCCN_GB2312,
/* 0xfa */ EUCCN_GB2312,
/* 0xfb */ EUCCN_GB2312,
/* 0xfc */ EUCCN_GB2312,
/* 0xfd */ EUCCN_GB2312,
/* 0xfe */ EUCCN_GB2312,
/* 0xff */ EUCCN_LATIN1,
};
static fe_Font
fe_LoadEUCCNFont(MWContext *context, char *familyName, int sizeNum,
int fontmask, int charset, int pitch, int faceNum,
Display *dpy)
{
int16 cs;
int len;
fe_FontGroupFont *ret;
len = (2 * sizeof(fe_FontGroupFont));
ret = calloc(1, len);
if (!ret)
{
return NULL;
}
(void) memset(ret, 0, len);
cs = CS_LATIN1;
ret[0].xFont = (XFontStruct *) fe_LoadFont(context, &cs, familyName,
sizeNum, fontmask);
if (cs != CS_LATIN1)
{
XP_FREE(ret);
return NULL;
}
cs = CS_GB2312;
ret[1].xFont = (XFontStruct *) fe_LoadFont(context, &cs, familyName,
sizeNum, fontmask);
if (cs == CS_GB2312)
{
ret[1].mask1 = 0x7f;
ret[1].mask2 = 0x7f;
}
else
{
cs = CS_GB2312_11;
ret[1].xFont = (XFontStruct *) fe_LoadFont(context, &cs,
familyName, sizeNum, fontmask);
if (cs == CS_GB2312_11)
{
ret[1].mask1 = 0xff;
ret[1].mask2 = 0xff;
}
else
{
XP_FREE(ret);
return NULL;
}
}
return (fe_Font) ret;
}
static void
fe_EUCCNTextExtents(fe_Font font, char *string, int len, int *direction,
int *fontAscent, int *fontDescent, XCharStruct *overall)
{
fe_ProcessString(EUCCNTable, NULL,
NULL,
NULL, None, font, NULL, 0, 0, string, len,
fontAscent, fontDescent, overall,
fe_CharSetFuncsArray[FE_FONT_INFO_EUCCN].numberOfFonts);
}
static void
fe_DrawEUCCNString(Display *dpy, Drawable d, fe_Font font, GC gc, int x,
int y, char *string, int len)
{
fe_ProcessString(EUCCNTable, (fe_XDrawStringFunc) XDrawString,
(fe_XDrawStringFunc) XDrawString16,
dpy, d, font, gc, x, y, string, len,
NULL, NULL, NULL,
0);
}
static void
fe_DrawEUCCNImageString(Display *dpy, Drawable d, fe_Font font, GC gc, int x,
int y, char *string, int len)
{
fe_ProcessString(EUCCNTable, (fe_XDrawStringFunc) XDrawImageString,
(fe_XDrawStringFunc) XDrawImageString16,
dpy, d, font, gc, x, y, string, len,
NULL, NULL, NULL,
0);
}
/* fontIndex skip len */
#define EUCJP_LATIN1 { 0, 0, 1 }
#define EUCJP_JISX0208 { 1, 0, 2 }
#define EUCJP_JISX0201 { 2, 1, 1 }
#define EUCJP_JISX0212 { 3, 1, 2 }
static fe_StringProcessTable EUCJPTable[] =
{
/* 0x00 */ EUCJP_LATIN1,
/* 0x01 */ EUCJP_LATIN1,
/* 0x02 */ EUCJP_LATIN1,
/* 0x03 */ EUCJP_LATIN1,
/* 0x04 */ EUCJP_LATIN1,
/* 0x05 */ EUCJP_LATIN1,
/* 0x06 */ EUCJP_LATIN1,
/* 0x07 */ EUCJP_LATIN1,
/* 0x08 */ EUCJP_LATIN1,
/* 0x09 */ EUCJP_LATIN1,
/* 0x0a */ EUCJP_LATIN1,
/* 0x0b */ EUCJP_LATIN1,
/* 0x0c */ EUCJP_LATIN1,
/* 0x0d */ EUCJP_LATIN1,
/* 0x0e */ EUCJP_LATIN1,
/* 0x0f */ EUCJP_LATIN1,
/* 0x10 */ EUCJP_LATIN1,
/* 0x11 */ EUCJP_LATIN1,
/* 0x12 */ EUCJP_LATIN1,
/* 0x13 */ EUCJP_LATIN1,
/* 0x14 */ EUCJP_LATIN1,
/* 0x15 */ EUCJP_LATIN1,
/* 0x16 */ EUCJP_LATIN1,
/* 0x17 */ EUCJP_LATIN1,
/* 0x18 */ EUCJP_LATIN1,
/* 0x19 */ EUCJP_LATIN1,
/* 0x1a */ EUCJP_LATIN1,
/* 0x1b */ EUCJP_LATIN1,
/* 0x1c */ EUCJP_LATIN1,
/* 0x1d */ EUCJP_LATIN1,
/* 0x1e */ EUCJP_LATIN1,
/* 0x1f */ EUCJP_LATIN1,
/* 0x20 */ EUCJP_LATIN1,
/* 0x21 */ EUCJP_LATIN1,
/* 0x22 */ EUCJP_LATIN1,
/* 0x23 */ EUCJP_LATIN1,
/* 0x24 */ EUCJP_LATIN1,
/* 0x25 */ EUCJP_LATIN1,
/* 0x26 */ EUCJP_LATIN1,
/* 0x27 */ EUCJP_LATIN1,
/* 0x28 */ EUCJP_LATIN1,
/* 0x29 */ EUCJP_LATIN1,
/* 0x2a */ EUCJP_LATIN1,
/* 0x2b */ EUCJP_LATIN1,
/* 0x2c */ EUCJP_LATIN1,
/* 0x2d */ EUCJP_LATIN1,
/* 0x2e */ EUCJP_LATIN1,
/* 0x2f */ EUCJP_LATIN1,
/* 0x30 */ EUCJP_LATIN1,
/* 0x31 */ EUCJP_LATIN1,
/* 0x32 */ EUCJP_LATIN1,
/* 0x33 */ EUCJP_LATIN1,
/* 0x34 */ EUCJP_LATIN1,
/* 0x35 */ EUCJP_LATIN1,
/* 0x36 */ EUCJP_LATIN1,
/* 0x37 */ EUCJP_LATIN1,
/* 0x38 */ EUCJP_LATIN1,
/* 0x39 */ EUCJP_LATIN1,
/* 0x3a */ EUCJP_LATIN1,
/* 0x3b */ EUCJP_LATIN1,
/* 0x3c */ EUCJP_LATIN1,
/* 0x3d */ EUCJP_LATIN1,
/* 0x3e */ EUCJP_LATIN1,
/* 0x3f */ EUCJP_LATIN1,
/* 0x40 */ EUCJP_LATIN1,
/* 0x41 */ EUCJP_LATIN1,
/* 0x42 */ EUCJP_LATIN1,
/* 0x43 */ EUCJP_LATIN1,
/* 0x44 */ EUCJP_LATIN1,
/* 0x45 */ EUCJP_LATIN1,
/* 0x46 */ EUCJP_LATIN1,
/* 0x47 */ EUCJP_LATIN1,
/* 0x48 */ EUCJP_LATIN1,
/* 0x49 */ EUCJP_LATIN1,
/* 0x4a */ EUCJP_LATIN1,
/* 0x4b */ EUCJP_LATIN1,
/* 0x4c */ EUCJP_LATIN1,
/* 0x4d */ EUCJP_LATIN1,
/* 0x4e */ EUCJP_LATIN1,
/* 0x4f */ EUCJP_LATIN1,
/* 0x50 */ EUCJP_LATIN1,
/* 0x51 */ EUCJP_LATIN1,
/* 0x52 */ EUCJP_LATIN1,
/* 0x53 */ EUCJP_LATIN1,
/* 0x54 */ EUCJP_LATIN1,
/* 0x55 */ EUCJP_LATIN1,
/* 0x56 */ EUCJP_LATIN1,
/* 0x57 */ EUCJP_LATIN1,
/* 0x58 */ EUCJP_LATIN1,
/* 0x59 */ EUCJP_LATIN1,
/* 0x5a */ EUCJP_LATIN1,
/* 0x5b */ EUCJP_LATIN1,
/* 0x5c */ EUCJP_LATIN1,
/* 0x5d */ EUCJP_LATIN1,
/* 0x5e */ EUCJP_LATIN1,
/* 0x5f */ EUCJP_LATIN1,
/* 0x60 */ EUCJP_LATIN1,
/* 0x61 */ EUCJP_LATIN1,
/* 0x62 */ EUCJP_LATIN1,
/* 0x63 */ EUCJP_LATIN1,
/* 0x64 */ EUCJP_LATIN1,
/* 0x65 */ EUCJP_LATIN1,
/* 0x66 */ EUCJP_LATIN1,
/* 0x67 */ EUCJP_LATIN1,
/* 0x68 */ EUCJP_LATIN1,
/* 0x69 */ EUCJP_LATIN1,
/* 0x6a */ EUCJP_LATIN1,
/* 0x6b */ EUCJP_LATIN1,
/* 0x6c */ EUCJP_LATIN1,
/* 0x6d */ EUCJP_LATIN1,
/* 0x6e */ EUCJP_LATIN1,
/* 0x6f */ EUCJP_LATIN1,
/* 0x70 */ EUCJP_LATIN1,
/* 0x71 */ EUCJP_LATIN1,
/* 0x72 */ EUCJP_LATIN1,
/* 0x73 */ EUCJP_LATIN1,
/* 0x74 */ EUCJP_LATIN1,
/* 0x75 */ EUCJP_LATIN1,
/* 0x76 */ EUCJP_LATIN1,
/* 0x77 */ EUCJP_LATIN1,
/* 0x78 */ EUCJP_LATIN1,
/* 0x79 */ EUCJP_LATIN1,
/* 0x7a */ EUCJP_LATIN1,
/* 0x7b */ EUCJP_LATIN1,
/* 0x7c */ EUCJP_LATIN1,
/* 0x7d */ EUCJP_LATIN1,
/* 0x7e */ EUCJP_LATIN1,
/* 0x7f */ EUCJP_LATIN1,
/* 0x80 */ EUCJP_LATIN1,
/* 0x81 */ EUCJP_LATIN1,
/* 0x82 */ EUCJP_LATIN1,
/* 0x83 */ EUCJP_LATIN1,
/* 0x84 */ EUCJP_LATIN1,
/* 0x85 */ EUCJP_LATIN1,
/* 0x86 */ EUCJP_LATIN1,
/* 0x87 */ EUCJP_LATIN1,
/* 0x88 */ EUCJP_LATIN1,
/* 0x89 */ EUCJP_LATIN1,
/* 0x8a */ EUCJP_LATIN1,
/* 0x8b */ EUCJP_LATIN1,
/* 0x8c */ EUCJP_LATIN1,
/* 0x8d */ EUCJP_LATIN1,
/* 0x8e */ EUCJP_JISX0201,
/* 0x8f */ EUCJP_JISX0212,
/* 0x90 */ EUCJP_LATIN1,
/* 0x91 */ EUCJP_LATIN1,
/* 0x92 */ EUCJP_LATIN1,
/* 0x93 */ EUCJP_LATIN1,
/* 0x94 */ EUCJP_LATIN1,
/* 0x95 */ EUCJP_LATIN1,
/* 0x96 */ EUCJP_LATIN1,
/* 0x97 */ EUCJP_LATIN1,
/* 0x98 */ EUCJP_LATIN1,
/* 0x99 */ EUCJP_LATIN1,
/* 0x9a */ EUCJP_LATIN1,
/* 0x9b */ EUCJP_LATIN1,
/* 0x9c */ EUCJP_LATIN1,
/* 0x9d */ EUCJP_LATIN1,
/* 0x9e */ EUCJP_LATIN1,
/* 0x9f */ EUCJP_LATIN1,
/* 0xa0 */ EUCJP_LATIN1,
/* 0xa1 */ EUCJP_JISX0208,
/* 0xa2 */ EUCJP_JISX0208,
/* 0xa3 */ EUCJP_JISX0208,
/* 0xa4 */ EUCJP_JISX0208,
/* 0xa5 */ EUCJP_JISX0208,
/* 0xa6 */ EUCJP_JISX0208,
/* 0xa7 */ EUCJP_JISX0208,
/* 0xa8 */ EUCJP_JISX0208,
/* 0xa9 */ EUCJP_JISX0208,
/* 0xaa */ EUCJP_JISX0208,
/* 0xab */ EUCJP_JISX0208,
/* 0xac */ EUCJP_JISX0208,
/* 0xad */ EUCJP_JISX0208,
/* 0xae */ EUCJP_JISX0208,
/* 0xaf */ EUCJP_JISX0208,
/* 0xb0 */ EUCJP_JISX0208,
/* 0xb1 */ EUCJP_JISX0208,
/* 0xb2 */ EUCJP_JISX0208,
/* 0xb3 */ EUCJP_JISX0208,
/* 0xb4 */ EUCJP_JISX0208,
/* 0xb5 */ EUCJP_JISX0208,
/* 0xb6 */ EUCJP_JISX0208,
/* 0xb7 */ EUCJP_JISX0208,
/* 0xb8 */ EUCJP_JISX0208,
/* 0xb9 */ EUCJP_JISX0208,
/* 0xba */ EUCJP_JISX0208,
/* 0xbb */ EUCJP_JISX0208,
/* 0xbc */ EUCJP_JISX0208,
/* 0xbd */ EUCJP_JISX0208,
/* 0xbe */ EUCJP_JISX0208,
/* 0xbf */ EUCJP_JISX0208,
/* 0xc0 */ EUCJP_JISX0208,
/* 0xc1 */ EUCJP_JISX0208,
/* 0xc2 */ EUCJP_JISX0208,
/* 0xc3 */ EUCJP_JISX0208,
/* 0xc4 */ EUCJP_JISX0208,
/* 0xc5 */ EUCJP_JISX0208,
/* 0xc6 */ EUCJP_JISX0208,
/* 0xc7 */ EUCJP_JISX0208,
/* 0xc8 */ EUCJP_JISX0208,
/* 0xc9 */ EUCJP_JISX0208,
/* 0xca */ EUCJP_JISX0208,
/* 0xcb */ EUCJP_JISX0208,
/* 0xcc */ EUCJP_JISX0208,
/* 0xcd */ EUCJP_JISX0208,
/* 0xce */ EUCJP_JISX0208,
/* 0xcf */ EUCJP_JISX0208,
/* 0xd0 */ EUCJP_JISX0208,
/* 0xd1 */ EUCJP_JISX0208,
/* 0xd2 */ EUCJP_JISX0208,
/* 0xd3 */ EUCJP_JISX0208,
/* 0xd4 */ EUCJP_JISX0208,
/* 0xd5 */ EUCJP_JISX0208,
/* 0xd6 */ EUCJP_JISX0208,
/* 0xd7 */ EUCJP_JISX0208,
/* 0xd8 */ EUCJP_JISX0208,
/* 0xd9 */ EUCJP_JISX0208,
/* 0xda */ EUCJP_JISX0208,
/* 0xdb */ EUCJP_JISX0208,
/* 0xdc */ EUCJP_JISX0208,
/* 0xdd */ EUCJP_JISX0208,
/* 0xde */ EUCJP_JISX0208,
/* 0xdf */ EUCJP_JISX0208,
/* 0xe0 */ EUCJP_JISX0208,
/* 0xe1 */ EUCJP_JISX0208,
/* 0xe2 */ EUCJP_JISX0208,
/* 0xe3 */ EUCJP_JISX0208,
/* 0xe4 */ EUCJP_JISX0208,
/* 0xe5 */ EUCJP_JISX0208,
/* 0xe6 */ EUCJP_JISX0208,
/* 0xe7 */ EUCJP_JISX0208,
/* 0xe8 */ EUCJP_JISX0208,
/* 0xe9 */ EUCJP_JISX0208,
/* 0xea */ EUCJP_JISX0208,
/* 0xeb */ EUCJP_JISX0208,
/* 0xec */ EUCJP_JISX0208,
/* 0xed */ EUCJP_JISX0208,
/* 0xee */ EUCJP_JISX0208,
/* 0xef */ EUCJP_JISX0208,
/* 0xf0 */ EUCJP_JISX0208,
/* 0xf1 */ EUCJP_JISX0208,
/* 0xf2 */ EUCJP_JISX0208,
/* 0xf3 */ EUCJP_JISX0208,
/* 0xf4 */ EUCJP_JISX0208,
/* 0xf5 */ EUCJP_JISX0208,
/* 0xf6 */ EUCJP_JISX0208,
/* 0xf7 */ EUCJP_JISX0208,
/* 0xf8 */ EUCJP_JISX0208,
/* 0xf9 */ EUCJP_JISX0208,
/* 0xfa */ EUCJP_JISX0208,
/* 0xfb */ EUCJP_JISX0208,
/* 0xfc */ EUCJP_JISX0208,
/* 0xfd */ EUCJP_JISX0208,
/* 0xfe */ EUCJP_JISX0208,
/* 0xff */ EUCJP_LATIN1,
};
static fe_Font
fe_LoadEUCJPFont(MWContext *context, char *familyName, int sizeNum,
int fontmask, int charset, int pitch, int faceNum,
Display *dpy)
{
int16 cs;
int len;
fe_FontGroupFont *ret;
len = (4 * sizeof(fe_FontGroupFont));
ret = calloc(1, len);
if (!ret)
{
return NULL;
}
(void) memset(ret, 0, len);
cs = CS_LATIN1;
ret[0].xFont = (XFontStruct *) fe_LoadFont(context, &cs, familyName,
sizeNum, fontmask);
if (cs != CS_LATIN1)
{
XP_FREE(ret);
return NULL;
}
cs = CS_JISX0208;
ret[1].xFont = (XFontStruct *) fe_LoadFont(context, &cs, familyName,
sizeNum, fontmask);
if (cs == CS_JISX0208)
{
ret[1].mask1 = 0x7f;
ret[1].mask2 = 0x7f;
}
else
{
cs = CS_JISX0208_11;
ret[1].xFont = (XFontStruct *) fe_LoadFont(context, &cs,
familyName, sizeNum, fontmask);
if (cs == CS_JISX0208_11)
{
ret[1].mask1 = 0xff;
ret[1].mask2 = 0xff;
}
else
{
XP_FREE(ret);
return NULL;
}
}
cs = CS_JISX0201;
ret[2].xFont = (XFontStruct *) fe_LoadFont(context, &cs, familyName,
sizeNum, fontmask);
if (cs != CS_JISX0201)
{
ret[2].xFont = NULL;
}
cs = CS_JISX0212;
ret[3].xFont = (XFontStruct *) fe_LoadFont(context, &cs, familyName,
sizeNum, fontmask);
if (cs == CS_JISX0212)
{
ret[3].mask1 = 0x7f;
ret[3].mask2 = 0x7f;
}
else
{
ret[3].xFont = NULL;
}
return (fe_Font) ret;
}
static void
fe_EUCJPTextExtents(fe_Font font, char *string, int len, int *direction,
int *fontAscent, int *fontDescent, XCharStruct *overall)
{
fe_ProcessString(EUCJPTable, NULL,
NULL,
NULL, None, font, NULL, 0, 0, string, len,
fontAscent, fontDescent, overall,
fe_CharSetFuncsArray[FE_FONT_INFO_EUCJP].numberOfFonts);
}
static void
fe_DrawEUCJPString(Display *dpy, Drawable d, fe_Font font, GC gc, int x,
int y, char *string, int len)
{
fe_ProcessString(EUCJPTable, (fe_XDrawStringFunc) XDrawString,
(fe_XDrawStringFunc) XDrawString16,
dpy, d, font, gc, x, y, string, len,
NULL, NULL, NULL,
0);
}
static void
fe_DrawEUCJPImageString(Display *dpy, Drawable d, fe_Font font, GC gc, int x,
int y, char *string, int len)
{
fe_ProcessString(EUCJPTable, (fe_XDrawStringFunc) XDrawImageString,
(fe_XDrawStringFunc) XDrawImageString16,
dpy, d, font, gc, x, y, string, len,
NULL, NULL, NULL,
0);
}
/* fontIndex skip len */
#define EUCKR_LATIN1 { 0, 0, 1 }
#define EUCKR_KSC5601 { 1, 0, 2 }
static fe_StringProcessTable EUCKRTable[] =
{
/* 0x00 */ EUCKR_LATIN1,
/* 0x01 */ EUCKR_LATIN1,
/* 0x02 */ EUCKR_LATIN1,
/* 0x03 */ EUCKR_LATIN1,
/* 0x04 */ EUCKR_LATIN1,
/* 0x05 */ EUCKR_LATIN1,
/* 0x06 */ EUCKR_LATIN1,
/* 0x07 */ EUCKR_LATIN1,
/* 0x08 */ EUCKR_LATIN1,
/* 0x09 */ EUCKR_LATIN1,
/* 0x0a */ EUCKR_LATIN1,
/* 0x0b */ EUCKR_LATIN1,
/* 0x0c */ EUCKR_LATIN1,
/* 0x0d */ EUCKR_LATIN1,
/* 0x0e */ EUCKR_LATIN1,
/* 0x0f */ EUCKR_LATIN1,
/* 0x10 */ EUCKR_LATIN1,
/* 0x11 */ EUCKR_LATIN1,
/* 0x12 */ EUCKR_LATIN1,
/* 0x13 */ EUCKR_LATIN1,
/* 0x14 */ EUCKR_LATIN1,
/* 0x15 */ EUCKR_LATIN1,
/* 0x16 */ EUCKR_LATIN1,
/* 0x17 */ EUCKR_LATIN1,
/* 0x18 */ EUCKR_LATIN1,
/* 0x19 */ EUCKR_LATIN1,
/* 0x1a */ EUCKR_LATIN1,
/* 0x1b */ EUCKR_LATIN1,
/* 0x1c */ EUCKR_LATIN1,
/* 0x1d */ EUCKR_LATIN1,
/* 0x1e */ EUCKR_LATIN1,
/* 0x1f */ EUCKR_LATIN1,
/* 0x20 */ EUCKR_LATIN1,
/* 0x21 */ EUCKR_LATIN1,
/* 0x22 */ EUCKR_LATIN1,
/* 0x23 */ EUCKR_LATIN1,
/* 0x24 */ EUCKR_LATIN1,
/* 0x25 */ EUCKR_LATIN1,
/* 0x26 */ EUCKR_LATIN1,
/* 0x27 */ EUCKR_LATIN1,
/* 0x28 */ EUCKR_LATIN1,
/* 0x29 */ EUCKR_LATIN1,
/* 0x2a */ EUCKR_LATIN1,
/* 0x2b */ EUCKR_LATIN1,
/* 0x2c */ EUCKR_LATIN1,
/* 0x2d */ EUCKR_LATIN1,
/* 0x2e */ EUCKR_LATIN1,
/* 0x2f */ EUCKR_LATIN1,
/* 0x30 */ EUCKR_LATIN1,
/* 0x31 */ EUCKR_LATIN1,
/* 0x32 */ EUCKR_LATIN1,
/* 0x33 */ EUCKR_LATIN1,
/* 0x34 */ EUCKR_LATIN1,
/* 0x35 */ EUCKR_LATIN1,
/* 0x36 */ EUCKR_LATIN1,
/* 0x37 */ EUCKR_LATIN1,
/* 0x38 */ EUCKR_LATIN1,
/* 0x39 */ EUCKR_LATIN1,
/* 0x3a */ EUCKR_LATIN1,
/* 0x3b */ EUCKR_LATIN1,
/* 0x3c */ EUCKR_LATIN1,
/* 0x3d */ EUCKR_LATIN1,
/* 0x3e */ EUCKR_LATIN1,
/* 0x3f */ EUCKR_LATIN1,
/* 0x40 */ EUCKR_LATIN1,
/* 0x41 */ EUCKR_LATIN1,
/* 0x42 */ EUCKR_LATIN1,
/* 0x43 */ EUCKR_LATIN1,
/* 0x44 */ EUCKR_LATIN1,
/* 0x45 */ EUCKR_LATIN1,
/* 0x46 */ EUCKR_LATIN1,
/* 0x47 */ EUCKR_LATIN1,
/* 0x48 */ EUCKR_LATIN1,
/* 0x49 */ EUCKR_LATIN1,
/* 0x4a */ EUCKR_LATIN1,
/* 0x4b */ EUCKR_LATIN1,
/* 0x4c */ EUCKR_LATIN1,
/* 0x4d */ EUCKR_LATIN1,
/* 0x4e */ EUCKR_LATIN1,
/* 0x4f */ EUCKR_LATIN1,
/* 0x50 */ EUCKR_LATIN1,
/* 0x51 */ EUCKR_LATIN1,
/* 0x52 */ EUCKR_LATIN1,
/* 0x53 */ EUCKR_LATIN1,
/* 0x54 */ EUCKR_LATIN1,
/* 0x55 */ EUCKR_LATIN1,
/* 0x56 */ EUCKR_LATIN1,
/* 0x57 */ EUCKR_LATIN1,
/* 0x58 */ EUCKR_LATIN1,
/* 0x59 */ EUCKR_LATIN1,
/* 0x5a */ EUCKR_LATIN1,
/* 0x5b */ EUCKR_LATIN1,
/* 0x5c */ EUCKR_LATIN1,
/* 0x5d */ EUCKR_LATIN1,
/* 0x5e */ EUCKR_LATIN1,
/* 0x5f */ EUCKR_LATIN1,
/* 0x60 */ EUCKR_LATIN1,
/* 0x61 */ EUCKR_LATIN1,
/* 0x62 */ EUCKR_LATIN1,
/* 0x63 */ EUCKR_LATIN1,
/* 0x64 */ EUCKR_LATIN1,
/* 0x65 */ EUCKR_LATIN1,
/* 0x66 */ EUCKR_LATIN1,
/* 0x67 */ EUCKR_LATIN1,
/* 0x68 */ EUCKR_LATIN1,
/* 0x69 */ EUCKR_LATIN1,
/* 0x6a */ EUCKR_LATIN1,
/* 0x6b */ EUCKR_LATIN1,
/* 0x6c */ EUCKR_LATIN1,
/* 0x6d */ EUCKR_LATIN1,
/* 0x6e */ EUCKR_LATIN1,
/* 0x6f */ EUCKR_LATIN1,
/* 0x70 */ EUCKR_LATIN1,
/* 0x71 */ EUCKR_LATIN1,
/* 0x72 */ EUCKR_LATIN1,
/* 0x73 */ EUCKR_LATIN1,
/* 0x74 */ EUCKR_LATIN1,
/* 0x75 */ EUCKR_LATIN1,
/* 0x76 */ EUCKR_LATIN1,
/* 0x77 */ EUCKR_LATIN1,
/* 0x78 */ EUCKR_LATIN1,
/* 0x79 */ EUCKR_LATIN1,
/* 0x7a */ EUCKR_LATIN1,
/* 0x7b */ EUCKR_LATIN1,
/* 0x7c */ EUCKR_LATIN1,
/* 0x7d */ EUCKR_LATIN1,
/* 0x7e */ EUCKR_LATIN1,
/* 0x7f */ EUCKR_LATIN1,
/* 0x80 */ EUCKR_LATIN1,
/* 0x81 */ EUCKR_LATIN1,
/* 0x82 */ EUCKR_LATIN1,
/* 0x83 */ EUCKR_LATIN1,
/* 0x84 */ EUCKR_LATIN1,
/* 0x85 */ EUCKR_LATIN1,
/* 0x86 */ EUCKR_LATIN1,
/* 0x87 */ EUCKR_LATIN1,
/* 0x88 */ EUCKR_LATIN1,
/* 0x89 */ EUCKR_LATIN1,
/* 0x8a */ EUCKR_LATIN1,
/* 0x8b */ EUCKR_LATIN1,
/* 0x8c */ EUCKR_LATIN1,
/* 0x8d */ EUCKR_LATIN1,
/* 0x8e */ EUCKR_LATIN1,
/* 0x8f */ EUCKR_LATIN1,
/* 0x90 */ EUCKR_LATIN1,
/* 0x91 */ EUCKR_LATIN1,
/* 0x92 */ EUCKR_LATIN1,
/* 0x93 */ EUCKR_LATIN1,
/* 0x94 */ EUCKR_LATIN1,
/* 0x95 */ EUCKR_LATIN1,
/* 0x96 */ EUCKR_LATIN1,
/* 0x97 */ EUCKR_LATIN1,
/* 0x98 */ EUCKR_LATIN1,
/* 0x99 */ EUCKR_LATIN1,
/* 0x9a */ EUCKR_LATIN1,
/* 0x9b */ EUCKR_LATIN1,
/* 0x9c */ EUCKR_LATIN1,
/* 0x9d */ EUCKR_LATIN1,
/* 0x9e */ EUCKR_LATIN1,
/* 0x9f */ EUCKR_LATIN1,
/* 0xa0 */ EUCKR_LATIN1,
/* 0xa1 */ EUCKR_KSC5601,
/* 0xa2 */ EUCKR_KSC5601,
/* 0xa3 */ EUCKR_KSC5601,
/* 0xa4 */ EUCKR_KSC5601,
/* 0xa5 */ EUCKR_KSC5601,
/* 0xa6 */ EUCKR_KSC5601,
/* 0xa7 */ EUCKR_KSC5601,
/* 0xa8 */ EUCKR_KSC5601,
/* 0xa9 */ EUCKR_KSC5601,
/* 0xaa */ EUCKR_KSC5601,
/* 0xab */ EUCKR_KSC5601,
/* 0xac */ EUCKR_KSC5601,
/* 0xad */ EUCKR_KSC5601,
/* 0xae */ EUCKR_KSC5601,
/* 0xaf */ EUCKR_KSC5601,
/* 0xb0 */ EUCKR_KSC5601,
/* 0xb1 */ EUCKR_KSC5601,
/* 0xb2 */ EUCKR_KSC5601,
/* 0xb3 */ EUCKR_KSC5601,
/* 0xb4 */ EUCKR_KSC5601,
/* 0xb5 */ EUCKR_KSC5601,
/* 0xb6 */ EUCKR_KSC5601,
/* 0xb7 */ EUCKR_KSC5601,
/* 0xb8 */ EUCKR_KSC5601,
/* 0xb9 */ EUCKR_KSC5601,
/* 0xba */ EUCKR_KSC5601,
/* 0xbb */ EUCKR_KSC5601,
/* 0xbc */ EUCKR_KSC5601,
/* 0xbd */ EUCKR_KSC5601,
/* 0xbe */ EUCKR_KSC5601,
/* 0xbf */ EUCKR_KSC5601,
/* 0xc0 */ EUCKR_KSC5601,
/* 0xc1 */ EUCKR_KSC5601,
/* 0xc2 */ EUCKR_KSC5601,
/* 0xc3 */ EUCKR_KSC5601,
/* 0xc4 */ EUCKR_KSC5601,
/* 0xc5 */ EUCKR_KSC5601,
/* 0xc6 */ EUCKR_KSC5601,
/* 0xc7 */ EUCKR_KSC5601,
/* 0xc8 */ EUCKR_KSC5601,
/* 0xc9 */ EUCKR_KSC5601,
/* 0xca */ EUCKR_KSC5601,
/* 0xcb */ EUCKR_KSC5601,
/* 0xcc */ EUCKR_KSC5601,
/* 0xcd */ EUCKR_KSC5601,
/* 0xce */ EUCKR_KSC5601,
/* 0xcf */ EUCKR_KSC5601,
/* 0xd0 */ EUCKR_KSC5601,
/* 0xd1 */ EUCKR_KSC5601,
/* 0xd2 */ EUCKR_KSC5601,
/* 0xd3 */ EUCKR_KSC5601,
/* 0xd4 */ EUCKR_KSC5601,
/* 0xd5 */ EUCKR_KSC5601,
/* 0xd6 */ EUCKR_KSC5601,
/* 0xd7 */ EUCKR_KSC5601,
/* 0xd8 */ EUCKR_KSC5601,
/* 0xd9 */ EUCKR_KSC5601,
/* 0xda */ EUCKR_KSC5601,
/* 0xdb */ EUCKR_KSC5601,
/* 0xdc */ EUCKR_KSC5601,
/* 0xdd */ EUCKR_KSC5601,
/* 0xde */ EUCKR_KSC5601,
/* 0xdf */ EUCKR_KSC5601,
/* 0xe0 */ EUCKR_KSC5601,
/* 0xe1 */ EUCKR_KSC5601,
/* 0xe2 */ EUCKR_KSC5601,
/* 0xe3 */ EUCKR_KSC5601,
/* 0xe4 */ EUCKR_KSC5601,
/* 0xe5 */ EUCKR_KSC5601,
/* 0xe6 */ EUCKR_KSC5601,
/* 0xe7 */ EUCKR_KSC5601,
/* 0xe8 */ EUCKR_KSC5601,
/* 0xe9 */ EUCKR_KSC5601,
/* 0xea */ EUCKR_KSC5601,
/* 0xeb */ EUCKR_KSC5601,
/* 0xec */ EUCKR_KSC5601,
/* 0xed */ EUCKR_KSC5601,
/* 0xee */ EUCKR_KSC5601,
/* 0xef */ EUCKR_KSC5601,
/* 0xf0 */ EUCKR_KSC5601,
/* 0xf1 */ EUCKR_KSC5601,
/* 0xf2 */ EUCKR_KSC5601,
/* 0xf3 */ EUCKR_KSC5601,
/* 0xf4 */ EUCKR_KSC5601,
/* 0xf5 */ EUCKR_KSC5601,
/* 0xf6 */ EUCKR_KSC5601,
/* 0xf7 */ EUCKR_KSC5601,
/* 0xf8 */ EUCKR_KSC5601,
/* 0xf9 */ EUCKR_KSC5601,
/* 0xfa */ EUCKR_KSC5601,
/* 0xfb */ EUCKR_KSC5601,
/* 0xfc */ EUCKR_KSC5601,
/* 0xfd */ EUCKR_KSC5601,
/* 0xfe */ EUCKR_KSC5601,
/* 0xff */ EUCKR_LATIN1,
};
static fe_Font
fe_LoadEUCKRFont(MWContext *context, char *familyName, int sizeNum,
int fontmask, int charset, int pitch, int faceNum,
Display *dpy)
{
int16 cs;
int len;
fe_FontGroupFont *ret;
len = (2 * sizeof(fe_FontGroupFont));
ret = calloc(1, len);
if (!ret)
{
return NULL;
}
(void) memset(ret, 0, len);
cs = CS_LATIN1;
ret[0].xFont = (XFontStruct *) fe_LoadFont(context, &cs, familyName,
sizeNum, fontmask);
if (cs != CS_LATIN1)
{
XP_FREE(ret);
return NULL;
}
cs = CS_KSC5601;
ret[1].xFont = (XFontStruct *) fe_LoadFont(context, &cs, familyName,
sizeNum, fontmask);
if (cs == CS_KSC5601)
{
ret[1].mask1 = 0x7f;
ret[1].mask2 = 0x7f;
}
else
{
cs = CS_KSC5601_11;
ret[1].xFont = (XFontStruct *) fe_LoadFont(context, &cs,
familyName, sizeNum, fontmask);
if (cs == CS_KSC5601_11)
{
ret[1].mask1 = 0xff;
ret[1].mask2 = 0xff;
}
else
{
XP_FREE(ret);
return NULL;
}
}
return (fe_Font) ret;
}
static void
fe_EUCKRTextExtents(fe_Font font, char *string, int len, int *direction,
int *fontAscent, int *fontDescent, XCharStruct *overall)
{
fe_ProcessString(EUCKRTable, NULL,
NULL,
NULL, None, font, NULL, 0, 0, string, len,
fontAscent, fontDescent, overall,
fe_CharSetFuncsArray[FE_FONT_INFO_EUCKR].numberOfFonts);
}
static void
fe_DrawEUCKRString(Display *dpy, Drawable d, fe_Font font, GC gc, int x,
int y, char *string, int len)
{
fe_ProcessString(EUCKRTable, (fe_XDrawStringFunc) XDrawString,
(fe_XDrawStringFunc) XDrawString16,
dpy, d, font, gc, x, y, string, len,
NULL, NULL, NULL,
0);
}
static void
fe_DrawEUCKRImageString(Display *dpy, Drawable d, fe_Font font, GC gc, int x,
int y, char *string, int len)
{
fe_ProcessString(EUCKRTable, (fe_XDrawStringFunc) XDrawImageString,
(fe_XDrawStringFunc) XDrawImageString16,
dpy, d, font, gc, x, y, string, len,
NULL, NULL, NULL,
0);
}
/* fontIndex skip len */
#define EUCTW_LATIN1 { 0, 0, 1 }
#define EUCTW_CNS11643_1 { 1, 0, 2 }
#define EUCTW_CNS11643_2 { 2, 2, 2 }
static fe_StringProcessTable EUCTWTable[] =
{
/* 0x00 */ EUCTW_LATIN1,
/* 0x01 */ EUCTW_LATIN1,
/* 0x02 */ EUCTW_LATIN1,
/* 0x03 */ EUCTW_LATIN1,
/* 0x04 */ EUCTW_LATIN1,
/* 0x05 */ EUCTW_LATIN1,
/* 0x06 */ EUCTW_LATIN1,
/* 0x07 */ EUCTW_LATIN1,
/* 0x08 */ EUCTW_LATIN1,
/* 0x09 */ EUCTW_LATIN1,
/* 0x0a */ EUCTW_LATIN1,
/* 0x0b */ EUCTW_LATIN1,
/* 0x0c */ EUCTW_LATIN1,
/* 0x0d */ EUCTW_LATIN1,
/* 0x0e */ EUCTW_LATIN1,
/* 0x0f */ EUCTW_LATIN1,
/* 0x10 */ EUCTW_LATIN1,
/* 0x11 */ EUCTW_LATIN1,
/* 0x12 */ EUCTW_LATIN1,
/* 0x13 */ EUCTW_LATIN1,
/* 0x14 */ EUCTW_LATIN1,
/* 0x15 */ EUCTW_LATIN1,
/* 0x16 */ EUCTW_LATIN1,
/* 0x17 */ EUCTW_LATIN1,
/* 0x18 */ EUCTW_LATIN1,
/* 0x19 */ EUCTW_LATIN1,
/* 0x1a */ EUCTW_LATIN1,
/* 0x1b */ EUCTW_LATIN1,
/* 0x1c */ EUCTW_LATIN1,
/* 0x1d */ EUCTW_LATIN1,
/* 0x1e */ EUCTW_LATIN1,
/* 0x1f */ EUCTW_LATIN1,
/* 0x20 */ EUCTW_LATIN1,
/* 0x21 */ EUCTW_LATIN1,
/* 0x22 */ EUCTW_LATIN1,
/* 0x23 */ EUCTW_LATIN1,
/* 0x24 */ EUCTW_LATIN1,
/* 0x25 */ EUCTW_LATIN1,
/* 0x26 */ EUCTW_LATIN1,
/* 0x27 */ EUCTW_LATIN1,
/* 0x28 */ EUCTW_LATIN1,
/* 0x29 */ EUCTW_LATIN1,
/* 0x2a */ EUCTW_LATIN1,
/* 0x2b */ EUCTW_LATIN1,
/* 0x2c */ EUCTW_LATIN1,
/* 0x2d */ EUCTW_LATIN1,
/* 0x2e */ EUCTW_LATIN1,
/* 0x2f */ EUCTW_LATIN1,
/* 0x30 */ EUCTW_LATIN1,
/* 0x31 */ EUCTW_LATIN1,
/* 0x32 */ EUCTW_LATIN1,
/* 0x33 */ EUCTW_LATIN1,
/* 0x34 */ EUCTW_LATIN1,
/* 0x35 */ EUCTW_LATIN1,
/* 0x36 */ EUCTW_LATIN1,
/* 0x37 */ EUCTW_LATIN1,
/* 0x38 */ EUCTW_LATIN1,
/* 0x39 */ EUCTW_LATIN1,
/* 0x3a */ EUCTW_LATIN1,
/* 0x3b */ EUCTW_LATIN1,
/* 0x3c */ EUCTW_LATIN1,
/* 0x3d */ EUCTW_LATIN1,
/* 0x3e */ EUCTW_LATIN1,
/* 0x3f */ EUCTW_LATIN1,
/* 0x40 */ EUCTW_LATIN1,
/* 0x41 */ EUCTW_LATIN1,
/* 0x42 */ EUCTW_LATIN1,
/* 0x43 */ EUCTW_LATIN1,
/* 0x44 */ EUCTW_LATIN1,
/* 0x45 */ EUCTW_LATIN1,
/* 0x46 */ EUCTW_LATIN1,
/* 0x47 */ EUCTW_LATIN1,
/* 0x48 */ EUCTW_LATIN1,
/* 0x49 */ EUCTW_LATIN1,
/* 0x4a */ EUCTW_LATIN1,
/* 0x4b */ EUCTW_LATIN1,
/* 0x4c */ EUCTW_LATIN1,
/* 0x4d */ EUCTW_LATIN1,
/* 0x4e */ EUCTW_LATIN1,
/* 0x4f */ EUCTW_LATIN1,
/* 0x50 */ EUCTW_LATIN1,
/* 0x51 */ EUCTW_LATIN1,
/* 0x52 */ EUCTW_LATIN1,
/* 0x53 */ EUCTW_LATIN1,
/* 0x54 */ EUCTW_LATIN1,
/* 0x55 */ EUCTW_LATIN1,
/* 0x56 */ EUCTW_LATIN1,
/* 0x57 */ EUCTW_LATIN1,
/* 0x58 */ EUCTW_LATIN1,
/* 0x59 */ EUCTW_LATIN1,
/* 0x5a */ EUCTW_LATIN1,
/* 0x5b */ EUCTW_LATIN1,
/* 0x5c */ EUCTW_LATIN1,
/* 0x5d */ EUCTW_LATIN1,
/* 0x5e */ EUCTW_LATIN1,
/* 0x5f */ EUCTW_LATIN1,
/* 0x60 */ EUCTW_LATIN1,
/* 0x61 */ EUCTW_LATIN1,
/* 0x62 */ EUCTW_LATIN1,
/* 0x63 */ EUCTW_LATIN1,
/* 0x64 */ EUCTW_LATIN1,
/* 0x65 */ EUCTW_LATIN1,
/* 0x66 */ EUCTW_LATIN1,
/* 0x67 */ EUCTW_LATIN1,
/* 0x68 */ EUCTW_LATIN1,
/* 0x69 */ EUCTW_LATIN1,
/* 0x6a */ EUCTW_LATIN1,
/* 0x6b */ EUCTW_LATIN1,
/* 0x6c */ EUCTW_LATIN1,
/* 0x6d */ EUCTW_LATIN1,
/* 0x6e */ EUCTW_LATIN1,
/* 0x6f */ EUCTW_LATIN1,
/* 0x70 */ EUCTW_LATIN1,
/* 0x71 */ EUCTW_LATIN1,
/* 0x72 */ EUCTW_LATIN1,
/* 0x73 */ EUCTW_LATIN1,
/* 0x74 */ EUCTW_LATIN1,
/* 0x75 */ EUCTW_LATIN1,
/* 0x76 */ EUCTW_LATIN1,
/* 0x77 */ EUCTW_LATIN1,
/* 0x78 */ EUCTW_LATIN1,
/* 0x79 */ EUCTW_LATIN1,
/* 0x7a */ EUCTW_LATIN1,
/* 0x7b */ EUCTW_LATIN1,
/* 0x7c */ EUCTW_LATIN1,
/* 0x7d */ EUCTW_LATIN1,
/* 0x7e */ EUCTW_LATIN1,
/* 0x7f */ EUCTW_LATIN1,
/* 0x80 */ EUCTW_LATIN1,
/* 0x81 */ EUCTW_LATIN1,
/* 0x82 */ EUCTW_LATIN1,
/* 0x83 */ EUCTW_LATIN1,
/* 0x84 */ EUCTW_LATIN1,
/* 0x85 */ EUCTW_LATIN1,
/* 0x86 */ EUCTW_LATIN1,
/* 0x87 */ EUCTW_LATIN1,
/* 0x88 */ EUCTW_LATIN1,
/* 0x89 */ EUCTW_LATIN1,
/* 0x8a */ EUCTW_LATIN1,
/* 0x8b */ EUCTW_LATIN1,
/* 0x8c */ EUCTW_LATIN1,
/* 0x8d */ EUCTW_LATIN1,
/* 0x8e */ EUCTW_CNS11643_2,
/* 0x8f */ EUCTW_LATIN1,
/* 0x90 */ EUCTW_LATIN1,
/* 0x91 */ EUCTW_LATIN1,
/* 0x92 */ EUCTW_LATIN1,
/* 0x93 */ EUCTW_LATIN1,
/* 0x94 */ EUCTW_LATIN1,
/* 0x95 */ EUCTW_LATIN1,
/* 0x96 */ EUCTW_LATIN1,
/* 0x97 */ EUCTW_LATIN1,
/* 0x98 */ EUCTW_LATIN1,
/* 0x99 */ EUCTW_LATIN1,
/* 0x9a */ EUCTW_LATIN1,
/* 0x9b */ EUCTW_LATIN1,
/* 0x9c */ EUCTW_LATIN1,
/* 0x9d */ EUCTW_LATIN1,
/* 0x9e */ EUCTW_LATIN1,
/* 0x9f */ EUCTW_LATIN1,
/* 0xa0 */ EUCTW_LATIN1,
/* 0xa1 */ EUCTW_CNS11643_1,
/* 0xa2 */ EUCTW_CNS11643_1,
/* 0xa3 */ EUCTW_CNS11643_1,
/* 0xa4 */ EUCTW_CNS11643_1,
/* 0xa5 */ EUCTW_CNS11643_1,
/* 0xa6 */ EUCTW_CNS11643_1,
/* 0xa7 */ EUCTW_CNS11643_1,
/* 0xa8 */ EUCTW_CNS11643_1,
/* 0xa9 */ EUCTW_CNS11643_1,
/* 0xaa */ EUCTW_CNS11643_1,
/* 0xab */ EUCTW_CNS11643_1,
/* 0xac */ EUCTW_CNS11643_1,
/* 0xad */ EUCTW_CNS11643_1,
/* 0xae */ EUCTW_CNS11643_1,
/* 0xaf */ EUCTW_CNS11643_1,
/* 0xb0 */ EUCTW_CNS11643_1,
/* 0xb1 */ EUCTW_CNS11643_1,
/* 0xb2 */ EUCTW_CNS11643_1,
/* 0xb3 */ EUCTW_CNS11643_1,
/* 0xb4 */ EUCTW_CNS11643_1,
/* 0xb5 */ EUCTW_CNS11643_1,
/* 0xb6 */ EUCTW_CNS11643_1,
/* 0xb7 */ EUCTW_CNS11643_1,
/* 0xb8 */ EUCTW_CNS11643_1,
/* 0xb9 */ EUCTW_CNS11643_1,
/* 0xba */ EUCTW_CNS11643_1,
/* 0xbb */ EUCTW_CNS11643_1,
/* 0xbc */ EUCTW_CNS11643_1,
/* 0xbd */ EUCTW_CNS11643_1,
/* 0xbe */ EUCTW_CNS11643_1,
/* 0xbf */ EUCTW_CNS11643_1,
/* 0xc0 */ EUCTW_CNS11643_1,
/* 0xc1 */ EUCTW_CNS11643_1,
/* 0xc2 */ EUCTW_CNS11643_1,
/* 0xc3 */ EUCTW_CNS11643_1,
/* 0xc4 */ EUCTW_CNS11643_1,
/* 0xc5 */ EUCTW_CNS11643_1,
/* 0xc6 */ EUCTW_CNS11643_1,
/* 0xc7 */ EUCTW_CNS11643_1,
/* 0xc8 */ EUCTW_CNS11643_1,
/* 0xc9 */ EUCTW_CNS11643_1,
/* 0xca */ EUCTW_CNS11643_1,
/* 0xcb */ EUCTW_CNS11643_1,
/* 0xcc */ EUCTW_CNS11643_1,
/* 0xcd */ EUCTW_CNS11643_1,
/* 0xce */ EUCTW_CNS11643_1,
/* 0xcf */ EUCTW_CNS11643_1,
/* 0xd0 */ EUCTW_CNS11643_1,
/* 0xd1 */ EUCTW_CNS11643_1,
/* 0xd2 */ EUCTW_CNS11643_1,
/* 0xd3 */ EUCTW_CNS11643_1,
/* 0xd4 */ EUCTW_CNS11643_1,
/* 0xd5 */ EUCTW_CNS11643_1,
/* 0xd6 */ EUCTW_CNS11643_1,
/* 0xd7 */ EUCTW_CNS11643_1,
/* 0xd8 */ EUCTW_CNS11643_1,
/* 0xd9 */ EUCTW_CNS11643_1,
/* 0xda */ EUCTW_CNS11643_1,
/* 0xdb */ EUCTW_CNS11643_1,
/* 0xdc */ EUCTW_CNS11643_1,
/* 0xdd */ EUCTW_CNS11643_1,
/* 0xde */ EUCTW_CNS11643_1,
/* 0xdf */ EUCTW_CNS11643_1,
/* 0xe0 */ EUCTW_CNS11643_1,
/* 0xe1 */ EUCTW_CNS11643_1,
/* 0xe2 */ EUCTW_CNS11643_1,
/* 0xe3 */ EUCTW_CNS11643_1,
/* 0xe4 */ EUCTW_CNS11643_1,
/* 0xe5 */ EUCTW_CNS11643_1,
/* 0xe6 */ EUCTW_CNS11643_1,
/* 0xe7 */ EUCTW_CNS11643_1,
/* 0xe8 */ EUCTW_CNS11643_1,
/* 0xe9 */ EUCTW_CNS11643_1,
/* 0xea */ EUCTW_CNS11643_1,
/* 0xeb */ EUCTW_CNS11643_1,
/* 0xec */ EUCTW_CNS11643_1,
/* 0xed */ EUCTW_CNS11643_1,
/* 0xee */ EUCTW_CNS11643_1,
/* 0xef */ EUCTW_CNS11643_1,
/* 0xf0 */ EUCTW_CNS11643_1,
/* 0xf1 */ EUCTW_CNS11643_1,
/* 0xf2 */ EUCTW_CNS11643_1,
/* 0xf3 */ EUCTW_CNS11643_1,
/* 0xf4 */ EUCTW_CNS11643_1,
/* 0xf5 */ EUCTW_CNS11643_1,
/* 0xf6 */ EUCTW_CNS11643_1,
/* 0xf7 */ EUCTW_CNS11643_1,
/* 0xf8 */ EUCTW_CNS11643_1,
/* 0xf9 */ EUCTW_CNS11643_1,
/* 0xfa */ EUCTW_CNS11643_1,
/* 0xfb */ EUCTW_CNS11643_1,
/* 0xfc */ EUCTW_CNS11643_1,
/* 0xfd */ EUCTW_CNS11643_1,
/* 0xfe */ EUCTW_CNS11643_1,
/* 0xff */ EUCTW_LATIN1,
};
static fe_Font
fe_LoadEUCTWFont(MWContext *context, char *familyName, int sizeNum,
int fontmask, int charset, int pitch, int faceNum,
Display *dpy)
{
int16 cs;
int len;
fe_FontGroupFont *ret;
len = (3 * sizeof(fe_FontGroupFont));
ret = calloc(1, len);
if (!ret)
{
return NULL;
}
(void) memset(ret, 0, len);
cs = CS_LATIN1;
ret[0].xFont = (XFontStruct *) fe_LoadFont(context, &cs, familyName,
sizeNum, fontmask);
if (cs != CS_LATIN1)
{
XP_FREE(ret);
return NULL;
}
cs = CS_CNS11643_1;
ret[1].xFont = (XFontStruct *) fe_LoadFont(context, &cs, familyName,
sizeNum, fontmask);
if (cs == CS_CNS11643_1)
{
ret[1].mask1 = 0x7f;
ret[1].mask2 = 0x7f;
}
else
{
ret[1].xFont = NULL;
}
cs = CS_CNS11643_2;
ret[2].xFont = (XFontStruct *) fe_LoadFont(context, &cs, familyName,
sizeNum, fontmask);
if (cs == CS_CNS11643_2)
{
ret[2].mask1 = 0x7f;
ret[2].mask2 = 0x7f;
}
else
{
ret[2].xFont = NULL;
}
if ((!ret[1].xFont) || (!ret[2].xFont))
{
cs = CS_CNS11643_1110;
ret[1].xFont = (XFontStruct *) fe_LoadFont(context, &cs,
familyName, sizeNum, fontmask);
if (cs == CS_CNS11643_1110)
{
ret[1].mask1 = 0xff;
ret[1].mask2 = 0xff;
ret[2].xFont = ret[1].xFont;
ret[2].mask1 = 0xff;
ret[2].mask2 = 0x7f;
}
else
{
XP_FREE(ret);
return NULL;
}
}
return (fe_Font) ret;
}
static void
fe_EUCTWTextExtents(fe_Font font, char *string, int len, int *direction,
int *fontAscent, int *fontDescent, XCharStruct *overall)
{
fe_ProcessString(EUCTWTable, NULL,
NULL,
NULL, None, font, NULL, 0, 0, string, len,
fontAscent, fontDescent, overall,
fe_CharSetFuncsArray[FE_FONT_INFO_EUCTW].numberOfFonts);
}
static void
fe_DrawEUCTWString(Display *dpy, Drawable d, fe_Font font, GC gc, int x,
int y, char *string, int len)
{
fe_ProcessString(EUCTWTable, (fe_XDrawStringFunc) XDrawString,
(fe_XDrawStringFunc) XDrawString16,
dpy, d, font, gc, x, y, string, len,
NULL, NULL, NULL,
0);
}
static void
fe_DrawEUCTWImageString(Display *dpy, Drawable d, fe_Font font, GC gc, int x,
int y, char *string, int len)
{
fe_ProcessString(EUCTWTable, (fe_XDrawStringFunc) XDrawImageString,
(fe_XDrawStringFunc) XDrawImageString16,
dpy, d, font, gc, x, y, string, len,
NULL, NULL, NULL,
0);
}
/* fontIndex skip len */
#define BIG5_LATIN1 { 0, 0, 1 }
#define BIG5_BIG5 { 1, 0, 2 }
static fe_StringProcessTable BIG5Table[] =
{
/* 0x00 */ BIG5_LATIN1,
/* 0x01 */ BIG5_LATIN1,
/* 0x02 */ BIG5_LATIN1,
/* 0x03 */ BIG5_LATIN1,
/* 0x04 */ BIG5_LATIN1,
/* 0x05 */ BIG5_LATIN1,
/* 0x06 */ BIG5_LATIN1,
/* 0x07 */ BIG5_LATIN1,
/* 0x08 */ BIG5_LATIN1,
/* 0x09 */ BIG5_LATIN1,
/* 0x0a */ BIG5_LATIN1,
/* 0x0b */ BIG5_LATIN1,
/* 0x0c */ BIG5_LATIN1,
/* 0x0d */ BIG5_LATIN1,
/* 0x0e */ BIG5_LATIN1,
/* 0x0f */ BIG5_LATIN1,
/* 0x10 */ BIG5_LATIN1,
/* 0x11 */ BIG5_LATIN1,
/* 0x12 */ BIG5_LATIN1,
/* 0x13 */ BIG5_LATIN1,
/* 0x14 */ BIG5_LATIN1,
/* 0x15 */ BIG5_LATIN1,
/* 0x16 */ BIG5_LATIN1,
/* 0x17 */ BIG5_LATIN1,
/* 0x18 */ BIG5_LATIN1,
/* 0x19 */ BIG5_LATIN1,
/* 0x1a */ BIG5_LATIN1,
/* 0x1b */ BIG5_LATIN1,
/* 0x1c */ BIG5_LATIN1,
/* 0x1d */ BIG5_LATIN1,
/* 0x1e */ BIG5_LATIN1,
/* 0x1f */ BIG5_LATIN1,
/* 0x20 */ BIG5_LATIN1,
/* 0x21 */ BIG5_LATIN1,
/* 0x22 */ BIG5_LATIN1,
/* 0x23 */ BIG5_LATIN1,
/* 0x24 */ BIG5_LATIN1,
/* 0x25 */ BIG5_LATIN1,
/* 0x26 */ BIG5_LATIN1,
/* 0x27 */ BIG5_LATIN1,
/* 0x28 */ BIG5_LATIN1,
/* 0x29 */ BIG5_LATIN1,
/* 0x2a */ BIG5_LATIN1,
/* 0x2b */ BIG5_LATIN1,
/* 0x2c */ BIG5_LATIN1,
/* 0x2d */ BIG5_LATIN1,
/* 0x2e */ BIG5_LATIN1,
/* 0x2f */ BIG5_LATIN1,
/* 0x30 */ BIG5_LATIN1,
/* 0x31 */ BIG5_LATIN1,
/* 0x32 */ BIG5_LATIN1,
/* 0x33 */ BIG5_LATIN1,
/* 0x34 */ BIG5_LATIN1,
/* 0x35 */ BIG5_LATIN1,
/* 0x36 */ BIG5_LATIN1,
/* 0x37 */ BIG5_LATIN1,
/* 0x38 */ BIG5_LATIN1,
/* 0x39 */ BIG5_LATIN1,
/* 0x3a */ BIG5_LATIN1,
/* 0x3b */ BIG5_LATIN1,
/* 0x3c */ BIG5_LATIN1,
/* 0x3d */ BIG5_LATIN1,
/* 0x3e */ BIG5_LATIN1,
/* 0x3f */ BIG5_LATIN1,
/* 0x40 */ BIG5_LATIN1,
/* 0x41 */ BIG5_LATIN1,
/* 0x42 */ BIG5_LATIN1,
/* 0x43 */ BIG5_LATIN1,
/* 0x44 */ BIG5_LATIN1,
/* 0x45 */ BIG5_LATIN1,
/* 0x46 */ BIG5_LATIN1,
/* 0x47 */ BIG5_LATIN1,
/* 0x48 */ BIG5_LATIN1,
/* 0x49 */ BIG5_LATIN1,
/* 0x4a */ BIG5_LATIN1,
/* 0x4b */ BIG5_LATIN1,
/* 0x4c */ BIG5_LATIN1,
/* 0x4d */ BIG5_LATIN1,
/* 0x4e */ BIG5_LATIN1,
/* 0x4f */ BIG5_LATIN1,
/* 0x50 */ BIG5_LATIN1,
/* 0x51 */ BIG5_LATIN1,
/* 0x52 */ BIG5_LATIN1,
/* 0x53 */ BIG5_LATIN1,
/* 0x54 */ BIG5_LATIN1,
/* 0x55 */ BIG5_LATIN1,
/* 0x56 */ BIG5_LATIN1,
/* 0x57 */ BIG5_LATIN1,
/* 0x58 */ BIG5_LATIN1,
/* 0x59 */ BIG5_LATIN1,
/* 0x5a */ BIG5_LATIN1,
/* 0x5b */ BIG5_LATIN1,
/* 0x5c */ BIG5_LATIN1,
/* 0x5d */ BIG5_LATIN1,
/* 0x5e */ BIG5_LATIN1,
/* 0x5f */ BIG5_LATIN1,
/* 0x60 */ BIG5_LATIN1,
/* 0x61 */ BIG5_LATIN1,
/* 0x62 */ BIG5_LATIN1,
/* 0x63 */ BIG5_LATIN1,
/* 0x64 */ BIG5_LATIN1,
/* 0x65 */ BIG5_LATIN1,
/* 0x66 */ BIG5_LATIN1,
/* 0x67 */ BIG5_LATIN1,
/* 0x68 */ BIG5_LATIN1,
/* 0x69 */ BIG5_LATIN1,
/* 0x6a */ BIG5_LATIN1,
/* 0x6b */ BIG5_LATIN1,
/* 0x6c */ BIG5_LATIN1,
/* 0x6d */ BIG5_LATIN1,
/* 0x6e */ BIG5_LATIN1,
/* 0x6f */ BIG5_LATIN1,
/* 0x70 */ BIG5_LATIN1,
/* 0x71 */ BIG5_LATIN1,
/* 0x72 */ BIG5_LATIN1,
/* 0x73 */ BIG5_LATIN1,
/* 0x74 */ BIG5_LATIN1,
/* 0x75 */ BIG5_LATIN1,
/* 0x76 */ BIG5_LATIN1,
/* 0x77 */ BIG5_LATIN1,
/* 0x78 */ BIG5_LATIN1,
/* 0x79 */ BIG5_LATIN1,
/* 0x7a */ BIG5_LATIN1,
/* 0x7b */ BIG5_LATIN1,
/* 0x7c */ BIG5_LATIN1,
/* 0x7d */ BIG5_LATIN1,
/* 0x7e */ BIG5_LATIN1,
/* 0x7f */ BIG5_LATIN1,
/* 0x80 */ BIG5_LATIN1,
/* 0x81 */ BIG5_LATIN1,
/* 0x82 */ BIG5_LATIN1,
/* 0x83 */ BIG5_LATIN1,
/* 0x84 */ BIG5_LATIN1,
/* 0x85 */ BIG5_LATIN1,
/* 0x86 */ BIG5_LATIN1,
/* 0x87 */ BIG5_LATIN1,
/* 0x88 */ BIG5_LATIN1,
/* 0x89 */ BIG5_LATIN1,
/* 0x8a */ BIG5_LATIN1,
/* 0x8b */ BIG5_LATIN1,
/* 0x8c */ BIG5_LATIN1,
/* 0x8d */ BIG5_LATIN1,
/* 0x8e */ BIG5_LATIN1,
/* 0x8f */ BIG5_LATIN1,
/* 0x90 */ BIG5_LATIN1,
/* 0x91 */ BIG5_LATIN1,
/* 0x92 */ BIG5_LATIN1,
/* 0x93 */ BIG5_LATIN1,
/* 0x94 */ BIG5_LATIN1,
/* 0x95 */ BIG5_LATIN1,
/* 0x96 */ BIG5_LATIN1,
/* 0x97 */ BIG5_LATIN1,
/* 0x98 */ BIG5_LATIN1,
/* 0x99 */ BIG5_LATIN1,
/* 0x9a */ BIG5_LATIN1,
/* 0x9b */ BIG5_LATIN1,
/* 0x9c */ BIG5_LATIN1,
/* 0x9d */ BIG5_LATIN1,
/* 0x9e */ BIG5_LATIN1,
/* 0x9f */ BIG5_LATIN1,
/* 0xa0 */ BIG5_LATIN1,
/* 0xa1 */ BIG5_BIG5,
/* 0xa2 */ BIG5_BIG5,
/* 0xa3 */ BIG5_BIG5,
/* 0xa4 */ BIG5_BIG5,
/* 0xa5 */ BIG5_BIG5,
/* 0xa6 */ BIG5_BIG5,
/* 0xa7 */ BIG5_BIG5,
/* 0xa8 */ BIG5_BIG5,
/* 0xa9 */ BIG5_BIG5,
/* 0xaa */ BIG5_BIG5,
/* 0xab */ BIG5_BIG5,
/* 0xac */ BIG5_BIG5,
/* 0xad */ BIG5_BIG5,
/* 0xae */ BIG5_BIG5,
/* 0xaf */ BIG5_BIG5,
/* 0xb0 */ BIG5_BIG5,
/* 0xb1 */ BIG5_BIG5,
/* 0xb2 */ BIG5_BIG5,
/* 0xb3 */ BIG5_BIG5,
/* 0xb4 */ BIG5_BIG5,
/* 0xb5 */ BIG5_BIG5,
/* 0xb6 */ BIG5_BIG5,
/* 0xb7 */ BIG5_BIG5,
/* 0xb8 */ BIG5_BIG5,
/* 0xb9 */ BIG5_BIG5,
/* 0xba */ BIG5_BIG5,
/* 0xbb */ BIG5_BIG5,
/* 0xbc */ BIG5_BIG5,
/* 0xbd */ BIG5_BIG5,
/* 0xbe */ BIG5_BIG5,
/* 0xbf */ BIG5_BIG5,
/* 0xc0 */ BIG5_BIG5,
/* 0xc1 */ BIG5_BIG5,
/* 0xc2 */ BIG5_BIG5,
/* 0xc3 */ BIG5_BIG5,
/* 0xc4 */ BIG5_BIG5,
/* 0xc5 */ BIG5_BIG5,
/* 0xc6 */ BIG5_BIG5,
/* 0xc7 */ BIG5_BIG5,
/* 0xc8 */ BIG5_BIG5,
/* 0xc9 */ BIG5_BIG5,
/* 0xca */ BIG5_BIG5,
/* 0xcb */ BIG5_BIG5,
/* 0xcc */ BIG5_BIG5,
/* 0xcd */ BIG5_BIG5,
/* 0xce */ BIG5_BIG5,
/* 0xcf */ BIG5_BIG5,
/* 0xd0 */ BIG5_BIG5,
/* 0xd1 */ BIG5_BIG5,
/* 0xd2 */ BIG5_BIG5,
/* 0xd3 */ BIG5_BIG5,
/* 0xd4 */ BIG5_BIG5,
/* 0xd5 */ BIG5_BIG5,
/* 0xd6 */ BIG5_BIG5,
/* 0xd7 */ BIG5_BIG5,
/* 0xd8 */ BIG5_BIG5,
/* 0xd9 */ BIG5_BIG5,
/* 0xda */ BIG5_BIG5,
/* 0xdb */ BIG5_BIG5,
/* 0xdc */ BIG5_BIG5,
/* 0xdd */ BIG5_BIG5,
/* 0xde */ BIG5_BIG5,
/* 0xdf */ BIG5_BIG5,
/* 0xe0 */ BIG5_BIG5,
/* 0xe1 */ BIG5_BIG5,
/* 0xe2 */ BIG5_BIG5,
/* 0xe3 */ BIG5_BIG5,
/* 0xe4 */ BIG5_BIG5,
/* 0xe5 */ BIG5_BIG5,
/* 0xe6 */ BIG5_BIG5,
/* 0xe7 */ BIG5_BIG5,
/* 0xe8 */ BIG5_BIG5,
/* 0xe9 */ BIG5_BIG5,
/* 0xea */ BIG5_BIG5,
/* 0xeb */ BIG5_BIG5,
/* 0xec */ BIG5_BIG5,
/* 0xed */ BIG5_BIG5,
/* 0xee */ BIG5_BIG5,
/* 0xef */ BIG5_BIG5,
/* 0xf0 */ BIG5_BIG5,
/* 0xf1 */ BIG5_BIG5,
/* 0xf2 */ BIG5_BIG5,
/* 0xf3 */ BIG5_BIG5,
/* 0xf4 */ BIG5_BIG5,
/* 0xf5 */ BIG5_BIG5,
/* 0xf6 */ BIG5_BIG5,
/* 0xf7 */ BIG5_BIG5,
/* 0xf8 */ BIG5_BIG5,
/* 0xf9 */ BIG5_BIG5,
/* 0xfa */ BIG5_BIG5,
/* 0xfb */ BIG5_BIG5,
/* 0xfc */ BIG5_BIG5,
/* 0xfd */ BIG5_BIG5,
/* 0xfe */ BIG5_BIG5,
/* 0xff */ BIG5_LATIN1,
};
static fe_Font
fe_LoadBIG5Font(MWContext *context, char *familyName, int sizeNum,
int fontmask, int charset, int pitch, int faceNum,
Display *dpy)
{
int16 cs;
int len;
fe_FontGroupFont *ret;
len = (2 * sizeof(fe_FontGroupFont));
ret = calloc(1, len);
if (!ret)
{
return NULL;
}
(void) memset(ret, 0, len);
cs = CS_LATIN1;
ret[0].xFont = (XFontStruct *) fe_LoadFont(context, &cs, familyName,
sizeNum, fontmask);
if (cs != CS_LATIN1)
{
XP_FREE(ret);
return NULL;
}
cs = CS_X_BIG5;
ret[1].xFont = (XFontStruct *) fe_LoadFont(context, &cs, familyName,
sizeNum, fontmask);
if (cs == CS_X_BIG5)
{
ret[1].mask1 = 0xff;
ret[1].mask2 = 0xff;
}
else
{
XP_FREE(ret);
return NULL;
}
return (fe_Font) ret;
}
static void
fe_BIG5TextExtents(fe_Font font, char *string, int len, int *direction,
int *fontAscent, int *fontDescent, XCharStruct *overall)
{
fe_ProcessString(BIG5Table, NULL,
NULL,
NULL, None, font, NULL, 0, 0, string, len,
fontAscent, fontDescent, overall,
fe_CharSetFuncsArray[FE_FONT_INFO_BIG5].numberOfFonts);
}
static void
fe_DrawBIG5String(Display *dpy, Drawable d, fe_Font font, GC gc, int x,
int y, char *string, int len)
{
fe_ProcessString(BIG5Table, (fe_XDrawStringFunc) XDrawString,
(fe_XDrawStringFunc) XDrawString16,
dpy, d, font, gc, x, y, string, len,
NULL, NULL, NULL,
0);
}
static void
fe_DrawBIG5ImageString(Display *dpy, Drawable d, fe_Font font, GC gc, int x,
int y, char *string, int len)
{
fe_ProcessString(BIG5Table, (fe_XDrawStringFunc) XDrawImageString,
(fe_XDrawStringFunc) XDrawImageString16,
dpy, d, font, gc, x, y, string, len,
NULL, NULL, NULL,
0);
}
/********************************************************************
New Code
********************************************************************/
/*
* these values can be changed to whatever is convenient for Java
*/
enum
{
INTL_FontStyleNormal,
INTL_FontStyleBold,
INTL_FontStyleItalic,
INTL_FontStyleBoldItalic
};
static XFontStruct *
intl_GetFontFace(Display *display, int sizeNum, fe_FontSize *size, int faceNum,
char **fontName)
{
fe_FontFace *face;
int i;
char *name;
XFontStruct *ret;
for (i = 0; i < 2; i++, faceNum = 0)
{
face = size->faces[faceNum];
if (!face)
{
continue;
}
if (face->font)
{
if (fontName)
{
if (size->size)
{
*fontName =
strdup(face->longXLFDFontName);
}
else
{
*fontName = PR_smprintf(
face->longXLFDFontName,
sizeNum);
}
}
return face->font;
}
else
{
if (size->size)
{
name = strdup(face->longXLFDFontName);
}
else
{
name = PR_smprintf(face->longXLFDFontName,
sizeNum);
}
if (!name)
{
return NULL;
}
ret = fe_LoadXFont(display, name);
if (ret)
{
face->font = ret;
if (fontName)
{
*fontName = name;
}
return ret;
}
}
}
return NULL;
}
static XFontStruct *
intl_GetFontSize(Display *display, fe_FontFamily *family, int sizeNum,
int faceNum, char **fontName)
{
int closestSize;
int firstSize;
int i;
double minDist;
double newDist;
XFontStruct *ret;
fe_FontSize *size;
if (!family->pixelSizes)
{
return NULL;
}
if (family->pixelSizes->size)
{
firstSize = 0;
}
else
{
if (family->numberOfPixelSizes == 1)
{
return intl_GetFontFace(display, sizeNum,
family->pixelSizes, faceNum, fontName);
}
firstSize = 1;
}
minDist = (1E+36);
for (i = firstSize; i < family->numberOfPixelSizes; i++)
{
size = &family->pixelSizes[i];
newDist = ((sizeNum - size->size) * (sizeNum - size->size));
if (newDist < minDist)
{
minDist = newDist;
closestSize = i;
}
else
{
break;
}
}
for (i = 0; i < family->numberOfPixelSizes; i++)
{
if (closestSize - i >= firstSize)
{
size = &family->pixelSizes[closestSize - i];
ret = intl_GetFontFace(display, size->size, size,
faceNum, fontName);
if (ret)
{
return ret;
}
}
if (closestSize + i < family->numberOfPixelSizes)
{
size = &family->pixelSizes[closestSize + i];
ret = intl_GetFontFace(display, size->size, size,
faceNum, fontName);
if (ret)
{
return ret;
}
}
}
if (!family->pixelSizes->size)
{
return intl_GetFontFace(display, sizeNum, family->pixelSizes,
faceNum, fontName);
}
return NULL;
}
XFontStruct *
intl_GetFont(Display *display, int16 characterSet, char *familyName,
char *foundry, int sizeNum, int style, char **fontName)
{
fe_FontCharSet *charset;
int faceNum;
fe_FontFamily *family;
int i;
int j;
fe_FontPitch *pitch;
XFontStruct *ret;
/*
* check the charset
*/
characterSet &= 0x00ff;
if ((0 > characterSet) || (characterSet >= INTL_CHAR_SET_MAX))
{
return NULL;
}
if (fe_CharSetInfoArray[characterSet].type == FE_FONT_TYPE_GROUP)
{
return NULL;
}
if (!fe_FontCharSets[characterSet].name)
{
return NULL;
}
/*
* check the family
*/
if (!familyName)
{
familyName = "";
}
/*
* check the foundry
*/
if (!foundry)
{
foundry = "";
}
/*
* check the size
*/
if (sizeNum <= 0)
{
return NULL;
}
/*
* check the style
*/
switch (style)
{
case INTL_FontStyleNormal:
faceNum = 0;
break;
case INTL_FontStyleBold:
faceNum = 1;
break;
case INTL_FontStyleItalic:
faceNum = 2;
break;
case INTL_FontStyleBoldItalic:
faceNum = 3;
break;
default:
return NULL;
}
charset = &fe_FontCharSets[characterSet];
/*
* iterate over the pitches (proportional and fixed)
* and for each pitch, look for the requested family and foundry
*/
for (i = 0; i < 2; i++)
{
pitch = &charset->pitches[i];
for (j = 0; j < pitch->numberOfFamilies; j++)
{
family = &pitch->families[j];
if ((!strcmp(family->family, familyName)) &&
(!strcmp(family->foundry, foundry)))
{
ret = intl_GetFontSize(display, family,
sizeNum, faceNum, fontName);
if (ret)
{
return ret;
}
}
}
}
/*
* couldn't find the requested family/foundry pair
* so try matching just the family
*/
for (i = 0; i < 2; i++)
{
pitch = &charset->pitches[i];
for (j = 0; j < pitch->numberOfFamilies; j++)
{
family = &pitch->families[j];
if (!strcmp(family->family, familyName))
{
ret = intl_GetFontSize(display, family,
sizeNum, faceNum, fontName);
if (ret)
{
return ret;
}
}
}
}
/*
* couldn't find the requested family
* so let's try the one selected in the UI
*/
for (i = 0; i < 2; i++)
{
pitch = &charset->pitches[i];
for (j = 0; j < pitch->numberOfFamilies; j++)
{
family = &pitch->families[j];
if (family->selected)
{
break;
}
else
{
family = NULL;
}
}
if (family)
{
ret = intl_GetFontSize(display, family, sizeNum,
faceNum, fontName);
if (ret)
{
return ret;
}
}
}
/*
* if we couldn't load the selected family
* we try all of the families in turn
*/
for (i = 0; i < 2; i++)
{
pitch = &charset->pitches[i];
for (j = 0; j < pitch->numberOfFamilies; j++)
{
family = &pitch->families[j];
ret = intl_GetFontSize(display, family, sizeNum,
faceNum, fontName);
if (ret)
{
return ret;
}
}
}
return NULL;
}
XFontStruct *
INTL_GetFont(Display *display, int16 characterSet, char *familyName,
char *foundry, int sizeNum, int style)
{
return intl_GetFont(display, characterSet, familyName, foundry,
sizeNum, style, NULL);
}
int16 *
INTL_GetXCharSetIDs(Display *dpy)
{
unsigned char *charset;
int len;
int16 *p;
int16 *ret;
ret = NULL;
if (!fe_LocaleCharSets)
{
fe_GetLocaleCharSets(dpy);
if (!fe_LocaleCharSets)
{
ret = (int16 *) malloc(2 * sizeof(int16));
if (!ret)
{
return NULL;
}
ret[0] = CS_LATIN1;
ret[1] = 0;
return ret;
}
}
len = 0;
charset = fe_LocaleCharSets;
while (*charset)
{
len++;
charset++;
}
ret = (int16 *) malloc((len + 1) * sizeof(int16));
if (!ret)
{
return NULL;
}
p = ret;
charset = fe_LocaleCharSets;
while (*charset)
{
*p++ = fe_CharSetInfoArray[*charset++].charsetID;
}
*p = 0;
return ret;
}
char *
INTL_GetXFontName(Display *display, int16 characterSet, char *familyName,
char *foundry, int sizeNum, int style)
{
char *fontName;
fontName = NULL;
(void) intl_GetFont(display, characterSet, familyName, foundry,
sizeNum, style, &fontName);
return fontName;
}