/* xfont.c -- X core font driver.
- Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
+ Copyright (C) 2006-2014 Free Software Foundation, Inc.
Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
National Institute of Advanced Industrial Science and Technology (AIST)
Registration Number H13PRO009
#include <config.h>
#include <stdio.h>
-#include <stdlib.h>
-#include <setjmp.h>
#include <X11/Xlib.h>
#include "lisp.h"
};
/* Prototypes of support functions. */
-extern void x_clear_errors P_ ((Display *));
-static XCharStruct *xfont_get_pcm P_ ((XFontStruct *, XChar2b *));
+static XCharStruct *xfont_get_pcm (XFontStruct *, XChar2b *);
/* Get metrics of character CHAR2B in XFONT. Value is null if CHAR2B
is not contained in the font. */
static XCharStruct *
-xfont_get_pcm (xfont, char2b)
- XFontStruct *xfont;
- XChar2b *char2b;
+xfont_get_pcm (XFontStruct *xfont, XChar2b *char2b)
{
/* The result metric information. */
XCharStruct *pcm = NULL;
- font_assert (xfont && char2b);
+ eassert (xfont && char2b);
if (xfont->per_char != NULL)
{
? NULL : pcm);
}
-static Lisp_Object xfont_get_cache P_ ((FRAME_PTR));
-static Lisp_Object xfont_list P_ ((Lisp_Object, Lisp_Object));
-static Lisp_Object xfont_match P_ ((Lisp_Object, Lisp_Object));
-static Lisp_Object xfont_list_family P_ ((Lisp_Object));
-static Lisp_Object xfont_open P_ ((FRAME_PTR, Lisp_Object, int));
-static void xfont_close P_ ((FRAME_PTR, struct font *));
-static int xfont_prepare_face P_ ((FRAME_PTR, struct face *));
-static int xfont_has_char P_ ((Lisp_Object, int));
-static unsigned xfont_encode_char P_ ((struct font *, int));
-static int xfont_text_extents P_ ((struct font *, unsigned *, int,
- struct font_metrics *));
-static int xfont_draw P_ ((struct glyph_string *, int, int, int, int, int));
-static int xfont_check P_ ((FRAME_PTR, struct font *));
+static Lisp_Object xfont_get_cache (struct frame *);
+static Lisp_Object xfont_list (struct frame *, Lisp_Object);
+static Lisp_Object xfont_match (struct frame *, Lisp_Object);
+static Lisp_Object xfont_list_family (struct frame *);
+static Lisp_Object xfont_open (struct frame *, Lisp_Object, int);
+static void xfont_close (struct font *);
+static int xfont_prepare_face (struct frame *, struct face *);
+static int xfont_has_char (Lisp_Object, int);
+static unsigned xfont_encode_char (struct font *, int);
+static int xfont_text_extents (struct font *, unsigned *, int,
+ struct font_metrics *);
+static int xfont_draw (struct glyph_string *, int, int, int, int, bool);
+static int xfont_check (struct frame *, struct font *);
struct font_driver xfont_driver =
{
- 0, /* Qx */
+ LISP_INITIALLY_ZERO, /* Qx */
0, /* case insensitive */
xfont_get_cache,
xfont_list,
NULL, /* filter_properties */
};
-extern Lisp_Object QCname;
-
static Lisp_Object
-xfont_get_cache (f)
- FRAME_PTR f;
+xfont_get_cache (struct frame *f)
{
- Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+ Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
return (dpyinfo->name_list_element);
}
-extern Lisp_Object Vface_alternative_font_registry_alist;
-
static int
compare_font_names (const void *name1, const void *name2)
{
- return xstrcasecmp (*(const unsigned char **) name1,
- *(const unsigned char **) name2);
+ char *const *n1 = name1;
+ char *const *n2 = name2;
+ return xstrcasecmp (*n1, *n2);
}
/* Decode XLFD as iso-8859-1 into OUTPUT, and return the byte length
XLFD is NULL terminated. The caller must assure that OUTPUT is at
least twice (plus 1) as large as XLFD. */
-static int
+static ptrdiff_t
xfont_decode_coding_xlfd (char *xlfd, int len, char *output)
{
char *p0 = xlfd, *p1 = output;
while (*p0)
{
c = *(unsigned char *) p0++;
- p1 += CHAR_STRING (c, p1);
+ p1 += CHAR_STRING (c, (unsigned char *) p1);
if (--len == 0)
break;
}
/* Check if CHARS (cons or vector) is supported by XFONT whose
encoding charset is ENCODING (XFONT is NULL) or by a font whose
registry corresponds to ENCODING and REPERTORY.
- Return 1 if supported, return 0 otherwise. */
+ Return true if supported. */
-static int
+static bool
xfont_chars_supported (Lisp_Object chars, XFontStruct *xfont,
struct charset *encoding, struct charset *repertory)
{
}
else if (VECTORP (chars))
{
- int i;
+ ptrdiff_t i;
for (i = ASIZE (chars) - 1; i >= 0; i--)
{
return 0;
}
-/* A hash table recoding which font supports which scritps. Each key
- is a vector of characteristic font propertis FOUNDRY to WIDTH and
+/* A hash table recoding which font supports which scripts. Each key
+ is a vector of characteristic font properties FOUNDRY to WIDTH and
ADDSTYLE, and each value is a list of script symbols.
We assume that fonts that have the same value in the above
static Lisp_Object xfont_scripts_cache;
-/* Re-usable vector to store characteristic font properites. */
+/* Re-usable vector to store characteristic font properties. */
static Lisp_Object xfont_scratch_props;
-extern Lisp_Object Qlatin;
-
/* Return a list of scripts supported by the font of FONTNAME whose
characteristic properties are in PROPS and whose encoding charset
is ENCODING. A caller must call BLOCK_INPUT in advance. */
/* Two special cases to avoid opening rather big fonts. */
if (EQ (AREF (props, 2), Qja))
- return Fcons (intern ("kana"), Fcons (intern ("han"), Qnil));
+ return list2 (intern ("kana"), intern ("han"));
if (EQ (AREF (props, 2), Qko))
- return Fcons (intern ("hangul"), Qnil);
+ return list1 (intern ("hangul"));
scripts = Fgethash (props, xfont_scripts_cache, Qt);
if (EQ (scripts, Qt))
{
return scripts;
}
-extern Lisp_Object Vscalable_fonts_allowed;
-
static Lisp_Object
-xfont_list_pattern (Display *display, char *pattern,
+xfont_list_pattern (Display *display, const char *pattern,
Lisp_Object registry, Lisp_Object script)
{
Lisp_Object list = Qnil;
script = Qnil;
}
}
-
- BLOCK_INPUT;
+
+ block_input ();
x_catch_errors (display);
for (limit = 512; ; limit *= 2)
Lisp_Object scripts = Qnil;
for (i = 0; i < ASIZE (xfont_scratch_props); i++)
- props[i] = Qnil;
+ ASET (xfont_scratch_props, i, Qnil);
for (i = 0; i < num_fonts; i++)
indices[i] = names[i];
qsort (indices, num_fonts, sizeof (char *), compare_font_names);
for (i = 0; i < num_fonts; i++)
{
+ ptrdiff_t len;
Lisp_Object entity;
if (i > 0 && xstrcasecmp (indices[i - 1], indices[i]) == 0)
continue;
entity = font_make_entity ();
- xfont_decode_coding_xlfd (indices[i], -1, buf);
- if (font_parse_xlfd (buf, entity) < 0)
+ len = xfont_decode_coding_xlfd (indices[i], -1, buf);
+ if (font_parse_xlfd (buf, len, entity) < 0)
continue;
ASET (entity, FONT_TYPE_INDEX, Qx);
/* Avoid auto-scaled fonts. */
{
elt = XCAR (tail);
if (STRINGP (elt)
- && fast_c_string_match_ignore_case (elt, indices[i]) >= 0)
+ && fast_c_string_match_ignore_case (elt, indices[i],
+ len) >= 0)
break;
}
if (! CONSP (tail))
list = Fcons (entity, list);
continue;
}
- if (memcmp (props, &(AREF (entity, FONT_FOUNDRY_INDEX)),
- sizeof (Lisp_Object) * 7)
+ if (memcmp (props, aref_addr (entity, FONT_FOUNDRY_INDEX),
+ word_size * 7)
|| ! EQ (AREF (entity, FONT_SPACING_INDEX), props[7]))
{
- memcpy (props, &(AREF (entity, FONT_FOUNDRY_INDEX)),
- sizeof (Lisp_Object) * 7);
- props[7] = AREF (entity, FONT_SPACING_INDEX);
+ vcopy (xfont_scratch_props, 0,
+ aref_addr (entity, FONT_FOUNDRY_INDEX), 7);
+ ASET (xfont_scratch_props, 7, AREF (entity, FONT_SPACING_INDEX));
scripts = xfont_supported_scripts (display, indices[i],
xfont_scratch_props, encoding);
}
}
x_uncatch_errors ();
- UNBLOCK_INPUT;
+ unblock_input ();
FONT_ADD_LOG ("xfont-list", build_string (pattern), list);
return list;
}
static Lisp_Object
-xfont_list (frame, spec)
- Lisp_Object frame, spec;
+xfont_list (struct frame *f, Lisp_Object spec)
{
- FRAME_PTR f = XFRAME (frame);
- Display *display = FRAME_X_DISPLAY_INFO (f)->display;
+ Display *display = FRAME_DISPLAY_INFO (f)->display;
Lisp_Object registry, list, val, extra, script;
int len;
/* Large enough to contain the longest XLFD (255 bytes) in UTF-8. */
if (STRINGP (XCAR (alter))
&& ((r - name) + SBYTES (XCAR (alter))) < 256)
{
- strcpy (r, (char *) SDATA (XCAR (alter)));
+ strcpy (r, SSDATA (XCAR (alter)));
list = xfont_list_pattern (display, name, registry, script);
if (! NILP (list))
break;
val = assq_no_quit (QCname, AREF (spec, FONT_EXTRA_INDEX));
if (CONSP (val) && STRINGP (XCDR (val)) && SBYTES (XCDR (val)) < 512)
{
- bcopy (SDATA (XCDR (val)), name, SBYTES (XCDR (val)) + 1);
+ memcpy (name, SDATA (XCDR (val)), SBYTES (XCDR (val)) + 1);
if (xfont_encode_coding_xlfd (name) < 0)
return Qnil;
list = xfont_list_pattern (display, name, registry, script);
}
static Lisp_Object
-xfont_match (frame, spec)
- Lisp_Object frame, spec;
+xfont_match (struct frame *f, Lisp_Object spec)
{
- FRAME_PTR f = XFRAME (frame);
- Display *display = FRAME_X_DISPLAY_INFO (f)->display;
+ Display *display = FRAME_DISPLAY_INFO (f)->display;
Lisp_Object extra, val, entity;
char name[512];
XFontStruct *xfont;
return Qnil;
}
else if (SBYTES (XCDR (val)) < 512)
- bcopy (SDATA (XCDR (val)), name, SBYTES (XCDR (val)) + 1);
+ memcpy (name, SDATA (XCDR (val)), SBYTES (XCDR (val)) + 1);
else
return Qnil;
if (xfont_encode_coding_xlfd (name) < 0)
return Qnil;
- BLOCK_INPUT;
+ block_input ();
entity = Qnil;
xfont = XLoadQueryFont (display, name);
if (xfont)
{
if (XGetFontProperty (xfont, XA_FONT, &value))
{
- int len;
- char *s;
-
- s = (char *) XGetAtomName (display, (Atom) value);
- len = strlen (s);
+ char *s = XGetAtomName (display, (Atom) value);
/* If DXPC (a Differential X Protocol Compressor)
Ver.3.7 is running, XGetAtomName will return null
string. We must avoid such a name. */
- if (len > 0)
+ if (*s)
{
+ ptrdiff_t len;
entity = font_make_entity ();
ASET (entity, FONT_TYPE_INDEX, Qx);
- xfont_decode_coding_xlfd (s, -1, name);
- if (font_parse_xlfd (name, entity) < 0)
+ len = xfont_decode_coding_xlfd (s, -1, name);
+ if (font_parse_xlfd (name, len, entity) < 0)
entity = Qnil;
}
XFree (s);
}
XFreeFont (display, xfont);
}
- UNBLOCK_INPUT;
+ unblock_input ();
FONT_ADD_LOG ("xfont-match", spec, entity);
return entity;
}
static Lisp_Object
-xfont_list_family (frame)
- Lisp_Object frame;
+xfont_list_family (struct frame *f)
{
- FRAME_PTR f = XFRAME (frame);
- Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+ Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
char **names;
int num_fonts, i;
Lisp_Object list;
- char *last_family;
+ char *last_family IF_LINT (= 0);
int last_len;
- BLOCK_INPUT;
+ block_input ();
x_catch_errors (dpyinfo->display);
names = XListFonts (dpyinfo->display, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*",
0x8000, &num_fonts);
if (! *p1 || p1 == p0)
continue;
if (last_len == p1 - p0
- && bcmp (last_family, p0, last_len) == 0)
+ && memcmp (last_family, p0, last_len) == 0)
continue;
last_len = p1 - p0;
last_family = p0;
XFreeFontNames (names);
x_uncatch_errors ();
- UNBLOCK_INPUT;
+ unblock_input ();
return list;
}
-extern Lisp_Object QCavgwidth;
-
static Lisp_Object
-xfont_open (f, entity, pixel_size)
- FRAME_PTR f;
- Lisp_Object entity;
- int pixel_size;
+xfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
{
- Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+ Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
Display *display = dpyinfo->display;
char name[512];
int len;
return Qnil;
}
- BLOCK_INPUT;
+ block_input ();
x_catch_errors (display);
xfont = XLoadQueryFont (display, name);
if (x_had_errors_p (display))
So, we try again with wildcards in RESX and RESY. */
Lisp_Object temp;
- temp = Fcopy_font_spec (entity);
+ temp = copy_font_spec (entity);
ASET (temp, FONT_DPI_INDEX, Qnil);
len = font_unparse_xlfd (temp, pixel_size, name, 512);
if (len <= 0 || (len = xfont_encode_coding_xlfd (name)) < 0)
char *p0, *p;
int dashes = 0;
- p0 = p = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
+ p0 = p = XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
/* Count the number of dashes in the "full name".
If it is too few, this isn't really the font's full name,
so don't use it.
XFree (p0);
}
x_uncatch_errors ();
- UNBLOCK_INPUT;
+ unblock_input ();
if (! xfont)
{
ASET (font_object, FONT_TYPE_INDEX, Qx);
if (STRINGP (fullname))
{
- font_parse_xlfd ((char *) SDATA (fullname), font_object);
+ font_parse_xlfd (SSDATA (fullname), SBYTES (fullname), font_object);
ASET (font_object, FONT_NAME_INDEX, fullname);
}
else
font->descent = xfont->descent;
font->height = font->ascent + font->descent;
font->min_width = xfont->min_bounds.width;
+ font->max_width = xfont->max_bounds.width;
if (xfont->min_bounds.width == xfont->max_bounds.width)
{
/* Fixed width font. */
font->average_width = XINT (val) / 10;
if (font->average_width < 0)
font->average_width = - font->average_width;
- if (font->average_width == 0
- && encoding->ascii_compatible_p)
+ else
{
- int width = font->space_width, n = pcm != NULL;
+ if (font->average_width == 0
+ && encoding->ascii_compatible_p)
+ {
+ int width = font->space_width, n = pcm != NULL;
- for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
- if ((pcm = xfont_get_pcm (xfont, &char2b)) != NULL)
- width += pcm->width, n++;
- if (n > 0)
- font->average_width = width / n;
+ for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
+ if ((pcm = xfont_get_pcm (xfont, &char2b)) != NULL)
+ width += pcm->width, n++;
+ if (n > 0)
+ font->average_width = width / n;
+ }
+ if (font->average_width == 0)
+ /* No easy way other than this to get a reasonable
+ average_width. */
+ font->average_width
+ = (xfont->min_bounds.width + xfont->max_bounds.width) / 2;
}
- if (font->average_width == 0)
- /* No easy way other than this to get a reasonable
- average_width. */
- font->average_width
- = (xfont->min_bounds.width + xfont->max_bounds.width) / 2;
}
- BLOCK_INPUT;
+ block_input ();
font->underline_thickness
= (XGetFontProperty (xfont, XA_UNDERLINE_THICKNESS, &value)
? (long) value : 0);
font->default_ascent
= (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
? (long) value : 0);
- UNBLOCK_INPUT;
+ unblock_input ();
if (NILP (fullname))
fullname = AREF (font_object, FONT_NAME_INDEX);
}
static void
-xfont_close (f, font)
- FRAME_PTR f;
- struct font *font;
+xfont_close (struct font *font)
{
- BLOCK_INPUT;
- XFreeFont (FRAME_X_DISPLAY (f), ((struct xfont_info *) font)->xfont);
- UNBLOCK_INPUT;
+ struct xfont_info *xfi = (struct xfont_info *) font;
+
+ /* This function may be called from GC when X connection is gone
+ (Bug#16093), and an attempt to free font resources on invalid
+ display may lead to X protocol errors or segfaults. */
+ if (xfi->xfont && x_display_info_for_display (xfi->display))
+ {
+ block_input ();
+ XFreeFont (xfi->display, xfi->xfont);
+ unblock_input ();
+ xfi->xfont = NULL;
+ }
}
static int
-xfont_prepare_face (f, face)
- FRAME_PTR f;
- struct face *face;
+xfont_prepare_face (struct frame *f, struct face *face)
{
- BLOCK_INPUT;
+ block_input ();
XSetFont (FRAME_X_DISPLAY (f), face->gc,
((struct xfont_info *) face->font)->xfont->fid);
- UNBLOCK_INPUT;
+ unblock_input ();
return 0;
}
static int
-xfont_has_char (font, c)
- Lisp_Object font;
- int c;
+xfont_has_char (Lisp_Object font, int c)
{
Lisp_Object registry = AREF (font, FONT_REGISTRY_INDEX);
struct charset *encoding;
}
static unsigned
-xfont_encode_char (font, c)
- struct font *font;
- int c;
+xfont_encode_char (struct font *font, int c)
{
XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
struct charset *charset;
}
static int
-xfont_text_extents (font, code, nglyphs, metrics)
- struct font *font;
- unsigned *code;
- int nglyphs;
- struct font_metrics *metrics;
+xfont_text_extents (struct font *font, unsigned int *code, int nglyphs, struct font_metrics *metrics)
{
XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
int width = 0;
- int i, first, x;
+ int i, first;
if (metrics)
- bzero (metrics, sizeof (struct font_metrics));
- for (i = 0, x = 0, first = 1; i < nglyphs; i++)
+ memset (metrics, 0, sizeof (struct font_metrics));
+ for (i = 0, first = 1; i < nglyphs; i++)
{
XChar2b char2b;
static XCharStruct *pcm;
}
static int
-xfont_draw (s, from, to, x, y, with_background)
- struct glyph_string *s;
- int from, to, x, y, with_background;
+xfont_draw (struct glyph_string *s, int from, int to, int x, int y,
+ bool with_background)
{
XFontStruct *xfont = ((struct xfont_info *) s->font)->xfont;
int len = to - from;
if (s->gc != s->face->gc)
{
- BLOCK_INPUT;
+ block_input ();
XSetFont (s->display, gc, xfont->fid);
- UNBLOCK_INPUT;
+ unblock_input ();
}
if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
{
- char *str;
USE_SAFE_ALLOCA;
-
- SAFE_ALLOCA (str, char *, len);
+ char *str = SAFE_ALLOCA (len);
for (i = 0; i < len ; i++)
str[i] = XCHAR2B_BYTE2 (s->char2b + from + i);
- BLOCK_INPUT;
- if (with_background > 0)
+ block_input ();
+ if (with_background)
{
if (s->padding_p)
for (i = 0; i < len; i++)
XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
gc, x, y, str, len);
}
- UNBLOCK_INPUT;
+ unblock_input ();
SAFE_FREE ();
return s->nchars;
}
- BLOCK_INPUT;
- if (with_background > 0)
+ block_input ();
+ if (with_background)
{
if (s->padding_p)
for (i = 0; i < len; i++)
XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
gc, x, y, s->char2b + from, len);
}
- UNBLOCK_INPUT;
+ unblock_input ();
return len;
}
static int
-xfont_check (f, font)
- FRAME_PTR f;
- struct font *font;
+xfont_check (struct frame *f, struct font *font)
{
struct xfont_info *xfont = (struct xfont_info *) font;
\f
void
-syms_of_xfont ()
+syms_of_xfont (void)
{
staticpro (&xfont_scripts_cache);
{ /* Here we rely on the fact that syms_of_xfont (via syms_of_font)
xfont_driver.type = Qx;
register_font_driver (&xfont_driver, NULL);
}
-
-/* arch-tag: 23c5f366-a5ee-44b7-a3b7-90d6da7fd749
- (do not change this comment) */