mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-03-22 14:39:24 -05:00
gtkfont: refactor parse/unparse of XLFDs.
There were already two places in the code (x11font_enum_fonts and x11_guess_derived_font_name) where we retrieved an XLFD from the X server, sawed it up ad-hoc into its '-'-separated parts and accessed them by numeric index. I'm about to add a third, so before I do, let's turn this into a somewhat principled system where we get to do the decode/encode in just one place and call all the individual fields by names that are actually memorable. No functional change intended by this commit.
This commit is contained in:
parent
22013390c4
commit
d9c68d236b
271
unix/gtkfont.c
271
unix/gtkfont.c
@ -219,6 +219,86 @@ static const struct unifont_vtable x11font_vtable = {
|
|||||||
"server",
|
"server",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define XLFD_STRING_PARTS_LIST(S,I) \
|
||||||
|
S(foundry) \
|
||||||
|
S(family_name) \
|
||||||
|
S(weight_name) \
|
||||||
|
S(slant) \
|
||||||
|
S(setwidth_name) \
|
||||||
|
S(add_style_name) \
|
||||||
|
I(pixel_size) \
|
||||||
|
I(point_size) \
|
||||||
|
I(resolution_x) \
|
||||||
|
I(resolution_y) \
|
||||||
|
S(spacing) \
|
||||||
|
I(average_width) \
|
||||||
|
S(charset_registry) \
|
||||||
|
S(charset_encoding) \
|
||||||
|
/* end of list */
|
||||||
|
|
||||||
|
struct xlfd_decomposed {
|
||||||
|
#define STR_FIELD(f) const char *f;
|
||||||
|
#define INT_FIELD(f) int f;
|
||||||
|
XLFD_STRING_PARTS_LIST(STR_FIELD, INT_FIELD)
|
||||||
|
#undef STR_FIELD
|
||||||
|
#undef INT_FIELD
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct xlfd_decomposed *xlfd_decompose(const char *xlfd)
|
||||||
|
{
|
||||||
|
void *mem;
|
||||||
|
char *p, *components[14];
|
||||||
|
struct xlfd_decomposed *dec;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!xlfd)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
mem = smalloc(sizeof(struct xlfd_decomposed) + strlen(xlfd) + 1);
|
||||||
|
p = ((char *)mem) + sizeof(struct xlfd_decomposed);
|
||||||
|
strcpy(p, xlfd);
|
||||||
|
dec = (struct xlfd_decomposed *)mem;
|
||||||
|
|
||||||
|
for (i = 0; i < 14; i++) {
|
||||||
|
if (*p != '-') {
|
||||||
|
/* Malformed XLFD: not enough '-' */
|
||||||
|
sfree(mem);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
*p++ = '\0';
|
||||||
|
components[i] = p;
|
||||||
|
p += strcspn(p, "-");
|
||||||
|
}
|
||||||
|
if (*p) {
|
||||||
|
/* Malformed XLFD: too many '-' */
|
||||||
|
sfree(mem);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
#define STORE_STR(f) dec->f = components[i++];
|
||||||
|
#define STORE_INT(f) dec->f = atoi(components[i++]);
|
||||||
|
XLFD_STRING_PARTS_LIST(STORE_STR, STORE_INT)
|
||||||
|
#undef STORE_STR
|
||||||
|
#undef STORE_INT
|
||||||
|
|
||||||
|
return dec;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *xlfd_recompose(const struct xlfd_decomposed *dec)
|
||||||
|
{
|
||||||
|
#define FMT_STR(f) "-%s"
|
||||||
|
#define ARG_STR(f) , dec->f
|
||||||
|
#define FMT_INT(f) "-%d"
|
||||||
|
#define ARG_INT(f) , dec->f
|
||||||
|
return dupprintf(XLFD_STRING_PARTS_LIST(FMT_STR, FMT_INT)
|
||||||
|
XLFD_STRING_PARTS_LIST(ARG_STR, ARG_INT));
|
||||||
|
#undef FMT_STR
|
||||||
|
#undef ARG_STR
|
||||||
|
#undef FMT_INT
|
||||||
|
#undef ARG_INT
|
||||||
|
}
|
||||||
|
|
||||||
static char *x11_guess_derived_font_name(XFontStruct *xfs, int bold, int wide)
|
static char *x11_guess_derived_font_name(XFontStruct *xfs, int bold, int wide)
|
||||||
{
|
{
|
||||||
Display *disp = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
|
Display *disp = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
|
||||||
@ -226,48 +306,27 @@ static char *x11_guess_derived_font_name(XFontStruct *xfs, int bold, int wide)
|
|||||||
unsigned long ret;
|
unsigned long ret;
|
||||||
if (XGetFontProperty(xfs, fontprop, &ret)) {
|
if (XGetFontProperty(xfs, fontprop, &ret)) {
|
||||||
char *name = XGetAtomName(disp, (Atom)ret);
|
char *name = XGetAtomName(disp, (Atom)ret);
|
||||||
if (name && name[0] == '-') {
|
struct xlfd_decomposed *xlfd = xlfd_decompose(name);
|
||||||
const char *strings[13];
|
if (!xlfd)
|
||||||
char *dupname, *extrafree = NULL, *ret;
|
return NULL;
|
||||||
char *p, *q;
|
|
||||||
int nstr;
|
|
||||||
|
|
||||||
p = q = dupname = dupstr(name); /* skip initial minus */
|
if (bold)
|
||||||
nstr = 0;
|
xlfd->weight_name = "bold";
|
||||||
|
|
||||||
while (*p && nstr < lenof(strings)) {
|
if (wide) {
|
||||||
if (*p == '-') {
|
/* Width name obviously may have changed. */
|
||||||
*p = '\0';
|
/* Additional style may now become e.g. `ja' or `ko'. */
|
||||||
strings[nstr++] = p+1;
|
xlfd->setwidth_name = xlfd->add_style_name = "*";
|
||||||
}
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nstr < lenof(strings)) {
|
/* Expect to double the average width. */
|
||||||
sfree(dupname);
|
xlfd->average_width *= 2;
|
||||||
return NULL; /* XLFD was malformed */
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (bold)
|
{
|
||||||
strings[2] = "bold";
|
char *ret = xlfd_recompose(xlfd);
|
||||||
|
sfree(xlfd);
|
||||||
if (wide) {
|
return ret;
|
||||||
/* 4 is `wideness', which obviously may have changed. */
|
}
|
||||||
/* 5 is additional style, which may be e.g. `ja' or `ko'. */
|
|
||||||
strings[4] = strings[5] = "*";
|
|
||||||
strings[11] = extrafree = dupprintf("%d", 2*atoi(strings[11]));
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = dupcat("-", strings[ 0], "-", strings[ 1], "-", strings[ 2],
|
|
||||||
"-", strings[ 3], "-", strings[ 4], "-", strings[ 5],
|
|
||||||
"-", strings[ 6], "-", strings[ 7], "-", strings[ 8],
|
|
||||||
"-", strings[ 9], "-", strings[10], "-", strings[11],
|
|
||||||
"-", strings[12], NULL);
|
|
||||||
sfree(extrafree);
|
|
||||||
sfree(dupname);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -921,73 +980,65 @@ static void x11font_enum_fonts(GtkWidget *widget,
|
|||||||
tmpsize = 0;
|
tmpsize = 0;
|
||||||
|
|
||||||
for (i = 0; i < nnames; i++) {
|
for (i = 0; i < nnames; i++) {
|
||||||
if (fontnames[i][0] == '-') {
|
struct xlfd_decomposed *xlfd = xlfd_decompose(fontnames[i]);
|
||||||
|
if (xlfd) {
|
||||||
|
char *p, *font, *style, *stylekey, *charset;
|
||||||
|
int weightkey, slantkey, setwidthkey;
|
||||||
|
int thistmpsize;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Dismember an XLFD and convert it into the format
|
* Convert a dismembered XLFD into the format we'll be
|
||||||
* we'll be using in the font selector.
|
* using in the font selector.
|
||||||
*/
|
*/
|
||||||
char *components[14];
|
|
||||||
char *p, *font, *style, *stylekey, *charset;
|
|
||||||
int j, weightkey, slantkey, setwidthkey;
|
|
||||||
int thistmpsize, fontsize, flags;
|
|
||||||
|
|
||||||
thistmpsize = 4 * strlen(fontnames[i]) + 256;
|
|
||||||
if (tmpsize < thistmpsize) {
|
|
||||||
tmpsize = thistmpsize;
|
|
||||||
tmp = sresize(tmp, tmpsize, char);
|
|
||||||
}
|
|
||||||
strcpy(tmp, fontnames[i]);
|
|
||||||
|
|
||||||
|
thistmpsize = 4 * strlen(fontnames[i]) + 256;
|
||||||
|
if (tmpsize < thistmpsize) {
|
||||||
|
tmpsize = thistmpsize;
|
||||||
|
tmp = sresize(tmp, tmpsize, char);
|
||||||
|
}
|
||||||
p = tmp;
|
p = tmp;
|
||||||
for (j = 0; j < 14; j++) {
|
|
||||||
if (*p)
|
|
||||||
*p++ = '\0';
|
|
||||||
components[j] = p;
|
|
||||||
while (*p && *p != '-')
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
*p++ = '\0';
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Font name is made up of fields 0 and 1, in reverse
|
* Font name is in the form "family (foundry)". (This is
|
||||||
* order with parentheses. (This is what the GTK 1.2 X
|
* what the GTK 1.2 X font selector does, and it seems to
|
||||||
* font selector does, and it seems to come out
|
* come out looking reasonably sensible.)
|
||||||
* looking reasonably sensible.)
|
|
||||||
*/
|
*/
|
||||||
font = p;
|
font = p;
|
||||||
p += 1 + sprintf(p, "%s (%s)", components[1], components[0]);
|
p += 1 + sprintf(p, "%s (%s)", xlfd->family_name, xlfd->foundry);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Charset is made up of fields 12 and 13.
|
* Character set.
|
||||||
*/
|
*/
|
||||||
charset = p;
|
charset = p;
|
||||||
p += 1 + sprintf(p, "%s-%s", components[12], components[13]);
|
p += 1 + sprintf(p, "%s-%s", xlfd->charset_registry,
|
||||||
|
xlfd->charset_encoding);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Style is a mixture of quite a lot of the fields,
|
* Style is a mixture of quite a lot of the fields,
|
||||||
* with some strange formatting.
|
* with some strange formatting.
|
||||||
*/
|
*/
|
||||||
style = p;
|
style = p;
|
||||||
p += sprintf(p, "%s", components[2][0] ? components[2] :
|
p += sprintf(p, "%s", xlfd->weight_name[0] ? xlfd->weight_name :
|
||||||
"regular");
|
"regular");
|
||||||
if (!g_ascii_strcasecmp(components[3], "i"))
|
if (!g_ascii_strcasecmp(xlfd->slant, "i"))
|
||||||
p += sprintf(p, " italic");
|
p += sprintf(p, " italic");
|
||||||
else if (!g_ascii_strcasecmp(components[3], "o"))
|
else if (!g_ascii_strcasecmp(xlfd->slant, "o"))
|
||||||
p += sprintf(p, " oblique");
|
p += sprintf(p, " oblique");
|
||||||
else if (!g_ascii_strcasecmp(components[3], "ri"))
|
else if (!g_ascii_strcasecmp(xlfd->slant, "ri"))
|
||||||
p += sprintf(p, " reverse italic");
|
p += sprintf(p, " reverse italic");
|
||||||
else if (!g_ascii_strcasecmp(components[3], "ro"))
|
else if (!g_ascii_strcasecmp(xlfd->slant, "ro"))
|
||||||
p += sprintf(p, " reverse oblique");
|
p += sprintf(p, " reverse oblique");
|
||||||
else if (!g_ascii_strcasecmp(components[3], "ot"))
|
else if (!g_ascii_strcasecmp(xlfd->slant, "ot"))
|
||||||
p += sprintf(p, " other-slant");
|
p += sprintf(p, " other-slant");
|
||||||
if (components[4][0] && g_ascii_strcasecmp(components[4], "normal"))
|
if (xlfd->setwidth_name[0] &&
|
||||||
p += sprintf(p, " %s", components[4]);
|
g_ascii_strcasecmp(xlfd->setwidth_name, "normal"))
|
||||||
if (!g_ascii_strcasecmp(components[10], "m"))
|
p += sprintf(p, " %s", xlfd->setwidth_name);
|
||||||
|
if (!g_ascii_strcasecmp(xlfd->spacing, "m"))
|
||||||
p += sprintf(p, " [M]");
|
p += sprintf(p, " [M]");
|
||||||
if (!g_ascii_strcasecmp(components[10], "c"))
|
if (!g_ascii_strcasecmp(xlfd->spacing, "c"))
|
||||||
p += sprintf(p, " [C]");
|
p += sprintf(p, " [C]");
|
||||||
if (components[5][0])
|
if (xlfd->add_style_name[0])
|
||||||
p += sprintf(p, " %s", components[5]);
|
p += sprintf(p, " %s", xlfd->add_style_name);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Style key is the same stuff as above, but with a
|
* Style key is the same stuff as above, but with a
|
||||||
@ -996,63 +1047,59 @@ static void x11font_enum_fonts(GtkWidget *widget,
|
|||||||
*/
|
*/
|
||||||
p++;
|
p++;
|
||||||
stylekey = p;
|
stylekey = p;
|
||||||
if (!g_ascii_strcasecmp(components[2], "medium") ||
|
if (!g_ascii_strcasecmp(xlfd->weight_name, "medium") ||
|
||||||
!g_ascii_strcasecmp(components[2], "regular") ||
|
!g_ascii_strcasecmp(xlfd->weight_name, "regular") ||
|
||||||
!g_ascii_strcasecmp(components[2], "normal") ||
|
!g_ascii_strcasecmp(xlfd->weight_name, "normal") ||
|
||||||
!g_ascii_strcasecmp(components[2], "book"))
|
!g_ascii_strcasecmp(xlfd->weight_name, "book"))
|
||||||
weightkey = 0;
|
weightkey = 0;
|
||||||
else if (!g_ascii_strncasecmp(components[2], "demi", 4) ||
|
else if (!g_ascii_strncasecmp(xlfd->weight_name, "demi", 4) ||
|
||||||
!g_ascii_strncasecmp(components[2], "semi", 4))
|
!g_ascii_strncasecmp(xlfd->weight_name, "semi", 4))
|
||||||
weightkey = 1;
|
weightkey = 1;
|
||||||
else
|
else
|
||||||
weightkey = 2;
|
weightkey = 2;
|
||||||
if (!g_ascii_strcasecmp(components[3], "r"))
|
if (!g_ascii_strcasecmp(xlfd->slant, "r"))
|
||||||
slantkey = 0;
|
slantkey = 0;
|
||||||
else if (!g_ascii_strncasecmp(components[3], "r", 1))
|
else if (!g_ascii_strncasecmp(xlfd->slant, "r", 1))
|
||||||
slantkey = 2;
|
slantkey = 2;
|
||||||
else
|
else
|
||||||
slantkey = 1;
|
slantkey = 1;
|
||||||
if (!g_ascii_strcasecmp(components[4], "normal"))
|
if (!g_ascii_strcasecmp(xlfd->setwidth_name, "normal"))
|
||||||
setwidthkey = 0;
|
setwidthkey = 0;
|
||||||
else
|
else
|
||||||
setwidthkey = 1;
|
setwidthkey = 1;
|
||||||
|
|
||||||
p += sprintf(p, "%04d%04d%s%04d%04d%s%04d%04d%s%04d%s%04d%s",
|
p += sprintf(
|
||||||
weightkey,
|
p, "%04d%04d%s%04d%04d%s%04d%04d%s%04d%s%04d%s",
|
||||||
(int)strlen(components[2]), components[2],
|
weightkey, (int)strlen(xlfd->weight_name), xlfd->weight_name,
|
||||||
slantkey,
|
slantkey, (int)strlen(xlfd->slant), xlfd->slant,
|
||||||
(int)strlen(components[3]), components[3],
|
setwidthkey,
|
||||||
setwidthkey,
|
(int)strlen(xlfd->setwidth_name), xlfd->setwidth_name,
|
||||||
(int)strlen(components[4]), components[4],
|
(int)strlen(xlfd->spacing), xlfd->spacing,
|
||||||
(int)strlen(components[10]), components[10],
|
(int)strlen(xlfd->add_style_name), xlfd->add_style_name);
|
||||||
(int)strlen(components[5]), components[5]);
|
|
||||||
|
|
||||||
assert(p - tmp < thistmpsize);
|
assert(p - tmp < thistmpsize);
|
||||||
|
|
||||||
/*
|
|
||||||
* Size is in pixels, for our application, so we
|
|
||||||
* derive it directly from the pixel size field,
|
|
||||||
* number 6.
|
|
||||||
*/
|
|
||||||
fontsize = atoi(components[6]);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flags: we need to know whether this is a monospaced
|
* Flags: we need to know whether this is a monospaced
|
||||||
* font, which we do by examining the spacing field
|
* font, which we do by examining the spacing field
|
||||||
* again.
|
* again.
|
||||||
*/
|
*/
|
||||||
flags = FONTFLAG_SERVERSIDE;
|
flags = FONTFLAG_SERVERSIDE;
|
||||||
if (!strchr("CcMm", components[10][0]))
|
if (!strchr("CcMm", xlfd->spacing[0]))
|
||||||
flags |= FONTFLAG_NONMONOSPACED;
|
flags |= FONTFLAG_NONMONOSPACED;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Not sure why, but sometimes the X server will
|
* Some fonts have a pixel size of zero, meaning they're
|
||||||
* deliver dummy font types in which fontsize comes
|
* treated as scalable. For these purposes, we only want
|
||||||
* out as zero. Filter those out.
|
* fonts whose pixel size we actually know, so filter
|
||||||
|
* those out.
|
||||||
*/
|
*/
|
||||||
if (fontsize)
|
if (xlfd->pixel_size)
|
||||||
callback(callback_ctx, fontnames[i], font, charset,
|
callback(callback_ctx, fontnames[i], font, charset,
|
||||||
style, stylekey, fontsize, flags, &x11font_vtable);
|
style, stylekey, xlfd->pixel_size, flags,
|
||||||
|
&x11font_vtable);
|
||||||
|
|
||||||
|
sfree(xlfd);
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* This isn't an XLFD, so it must be an alias.
|
* This isn't an XLFD, so it must be an alias.
|
||||||
@ -1064,6 +1111,8 @@ static void x11font_enum_fonts(GtkWidget *widget,
|
|||||||
*/
|
*/
|
||||||
callback(callback_ctx, fontnames[i], fontnames[i], NULL,
|
callback(callback_ctx, fontnames[i], fontnames[i], NULL,
|
||||||
NULL, NULL, 0, FONTFLAG_SERVERALIAS, &x11font_vtable);
|
NULL, NULL, 0, FONTFLAG_SERVERALIAS, &x11font_vtable);
|
||||||
|
|
||||||
|
sfree(xlfd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
XFreeFontNames(fontnames);
|
XFreeFontNames(fontnames);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user