Mercurial > emacs
diff src/xfont.c @ 90400:80fff33f74f5
New file.
author | Kenichi Handa <handa@m17n.org> |
---|---|
date | Tue, 06 Jun 2006 03:47:13 +0000 |
parents | |
children | 5976e428d68e |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xfont.c Tue Jun 06 03:47:13 2006 +0000 @@ -0,0 +1,868 @@ +/* xfont.c -- X core font driver. + Copyright (C) 2006 Free Software Foundation, Inc. + Copyright (C) 2006 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H13PRO009 + +This file is part of GNU Emacs. + +GNU Emacs is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Emacs is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Emacs; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. */ + +#include <config.h> +#include <stdio.h> +#include <X11/Xlib.h> + +#include "lisp.h" +#include "dispextern.h" +#include "xterm.h" +#include "frame.h" +#include "blockinput.h" +#include "character.h" +#include "charset.h" +#include "fontset.h" +#include "font.h" + + +/* X core font driver. */ + +Lisp_Object Qx; + +/* Alist of font registry symbol and the corresponding charsets + information. The information is retrieved from + Vfont_encoding_alist on demand. + + Eash element has the form: + (REGISTRY . (ENCODING-CHARSET-ID . REPERTORY-CHARSET-ID)) + or + (REGISTRY . nil) + + In the former form, ENCODING-CHARSET-ID is an ID of a charset that + encodes a character code to a glyph code of a font, and + REPERTORY-CHARSET-ID is an ID of a charset that tells if a + character is supported by a font. + + The latter form means that the information for REGISTRY couldn't be + retrieved. */ +static Lisp_Object x_font_charset_alist; + +/* Prototypes of support functions. */ +extern void x_clear_errors P_ ((Display *)); + +static char *xfont_query_font P_ ((Display *, char *, Lisp_Object)); +static XCharStruct *xfont_get_pcm P_ ((XFontStruct *, XChar2b *)); +static int xfont_registry_charsets P_ ((Lisp_Object, struct charset **, + struct charset **)); + +static char * +xfont_query_font (display, name, spec) + Display *display; + char *name; + Lisp_Object spec; +{ + XFontStruct *font; + + BLOCK_INPUT; + x_catch_errors (display); + font = XLoadQueryFont (display, name); + name = NULL; + if (x_had_errors_p (display)) + { + /* This error is perhaps due to insufficient memory on X + server. Let's just ignore it. */ + x_clear_errors (display); + } + else if (font) + { + unsigned long value; + + if (XGetFontProperty (font, XA_FONT, &value)) + { + char *n = (char *) XGetAtomName (display, (Atom) value); + + if (font_parse_xlfd (n, spec, 0) >= 0) + name = n; + else + XFree (n); + } + XFreeFont (display, font); + } + x_uncatch_errors (); + UNBLOCK_INPUT; + + return name; +} + + +/* 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; +{ + /* The result metric information. */ + XCharStruct *pcm = NULL; + + xassert (xfont && char2b); + + if (xfont->per_char != NULL) + { + if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0) + { + /* min_char_or_byte2 specifies the linear character index + corresponding to the first element of the per_char array, + max_char_or_byte2 is the index of the last character. A + character with non-zero CHAR2B->byte1 is not in the font. + A character with byte2 less than min_char_or_byte2 or + greater max_char_or_byte2 is not in the font. */ + if (char2b->byte1 == 0 + && char2b->byte2 >= xfont->min_char_or_byte2 + && char2b->byte2 <= xfont->max_char_or_byte2) + pcm = xfont->per_char + char2b->byte2 - xfont->min_char_or_byte2; + } + else + { + /* If either min_byte1 or max_byte1 are nonzero, both + min_char_or_byte2 and max_char_or_byte2 are less than + 256, and the 2-byte character index values corresponding + to the per_char array element N (counting from 0) are: + + byte1 = N/D + min_byte1 + byte2 = N\D + min_char_or_byte2 + + where: + + D = max_char_or_byte2 - min_char_or_byte2 + 1 + / = integer division + \ = integer modulus */ + if (char2b->byte1 >= xfont->min_byte1 + && char2b->byte1 <= xfont->max_byte1 + && char2b->byte2 >= xfont->min_char_or_byte2 + && char2b->byte2 <= xfont->max_char_or_byte2) + pcm = (xfont->per_char + + ((xfont->max_char_or_byte2 - xfont->min_char_or_byte2 + 1) + * (char2b->byte1 - xfont->min_byte1)) + + (char2b->byte2 - xfont->min_char_or_byte2)); + } + } + else + { + /* If the per_char pointer is null, all glyphs between the first + and last character indexes inclusive have the same + information, as given by both min_bounds and max_bounds. */ + if (char2b->byte2 >= xfont->min_char_or_byte2 + && char2b->byte2 <= xfont->max_char_or_byte2) + pcm = &xfont->max_bounds; + } + + return ((pcm == NULL + || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0)) + ? NULL : pcm); +} + +extern Lisp_Object find_font_encoding P_ ((Lisp_Object)); + +/* Return encoding charset and repertory charset for REGISTRY in + ENCODING and REPERTORY correspondingly. If correct information for + REGISTRY is available, return 0. Otherwise return -1. */ + +static int +xfont_registry_charsets (registry, encoding, repertory) + Lisp_Object registry; + struct charset **encoding, **repertory; +{ + Lisp_Object val; + int encoding_id, repertory_id; + + val = assq_no_quit (registry, x_font_charset_alist); + if (! NILP (val)) + { + val = XCDR (val); + if (NILP (val)) + return -1; + encoding_id = XINT (XCAR (val)); + repertory_id = XINT (XCDR (val)); + } + else + { + val = find_font_encoding (SYMBOL_NAME (registry)); + if (SYMBOLP (val) && CHARSETP (val)) + { + encoding_id = repertory_id = XINT (CHARSET_SYMBOL_ID (val)); + } + else if (CONSP (val)) + { + if (! CHARSETP (XCAR (val))) + goto invalid_entry; + encoding_id = XINT (CHARSET_SYMBOL_ID (XCAR (val))); + if (NILP (XCDR (val))) + repertory_id = -1; + else + { + if (! CHARSETP (XCDR (val))) + goto invalid_entry; + repertory_id = XINT (CHARSET_SYMBOL_ID (XCDR (val))); + } + } + else + goto invalid_entry; + val = Fcons (make_number (encoding_id), make_number (repertory_id)); + x_font_charset_alist + = nconc2 (x_font_charset_alist, Fcons (Fcons (registry, val), Qnil)); + } + + if (encoding) + *encoding = CHARSET_FROM_ID (encoding_id); + if (repertory) + *repertory = repertory_id >= 0 ? CHARSET_FROM_ID (repertory_id) : NULL; + return 0; + + invalid_entry: + x_font_charset_alist + = nconc2 (x_font_charset_alist, Fcons (Fcons (registry, Qnil), Qnil)); + return -1; +} + +static Lisp_Object xfont_get_cache P_ ((Lisp_Object)); +static int xfont_parse_name P_ ((FRAME_PTR, char *, Lisp_Object)); +static Lisp_Object xfont_list P_ ((Lisp_Object, Lisp_Object)); +static Lisp_Object xfont_list_family P_ ((Lisp_Object)); +static struct font *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 *)); +#if 0 +static void xfont_done_face P_ ((FRAME_PTR, struct face *)); +#endif +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)); + +struct font_driver xfont_driver = + { + (Lisp_Object) NULL, /* Qx */ + xfont_get_cache, + xfont_parse_name, + xfont_list, + xfont_list_family, + NULL, + xfont_open, + xfont_close, + xfont_prepare_face, + NULL /*xfont_done_face*/, + xfont_has_char, + xfont_encode_char, + xfont_text_extents, + xfont_draw, + }; + +extern Lisp_Object QCname; + +static Lisp_Object +xfont_get_cache (frame) + Lisp_Object frame; +{ + Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (frame)); + + return (dpyinfo->name_list_element); +} + +static int +xfont_parse_name (f, name, spec) + FRAME_PTR f; + char *name; + Lisp_Object spec; +{ + if (font_parse_xlfd (name, spec, 0) >= 0) + return 0; + name = xfont_query_font (FRAME_X_DISPLAY (f), name, spec); + if (name) + { + XFree (name); + return 0; + } + return -1; +} + +extern Lisp_Object Vface_alternative_font_registry_alist; + +static Lisp_Object +xfont_list (frame, spec) + Lisp_Object frame, spec; +{ + FRAME_PTR f = XFRAME (frame); + Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + Lisp_Object *vec, val, extra, font_name, entity; + char name[256], **names; + int i, idx, limit, num_fonts; + int error_occurred = 0; + USE_SAFE_ALLOCA; + + extra = AREF (spec, FONT_EXTRA_INDEX); + font_name = Qnil; + if (CONSP (extra)) + { + val = Fassq (QCotf, extra); + if (! NILP (val)) + return null_vector; + val = Fassq (QCname, extra); + if (CONSP (val)) + font_name = XCDR (val); + } + + if (! STRINGP (font_name) + && font_unparse_xlfd (spec, 0, name, 256) < 0) + return null_vector; + + BLOCK_INPUT; + x_catch_errors (dpyinfo->display); + + if (STRINGP (font_name)) + { + XFontStruct *font = XLoadQueryFont (dpyinfo->display, + (char *) SDATA (font_name)); + unsigned long value; + + num_fonts = 0; + if (x_had_errors_p (dpyinfo->display)) + { + /* This error is perhaps due to insufficient memory on X + server. Let's just ignore it. */ + font = NULL; + error_occurred = 1; + x_clear_errors (dpyinfo->display); + } + if (font) + { + if (XGetFontProperty (font, XA_FONT, &value)) + { + char *n = (char *) XGetAtomName (dpyinfo->display, (Atom) value); + int len = strlen (n); + char *tmp; + + /* 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) + { + num_fonts = 1; + names = (char **) alloca (sizeof (char *)); + /* Some systems only allow alloca assigned to a + simple var. */ + tmp = (char *) alloca (len + 1); names[0] = tmp; + bcopy (n, names[0], len + 1); + } + XFree (n); + } + XFreeFont (dpyinfo->display, font); + } + } + else + { + Lisp_Object registry = AREF (spec, FONT_REGISTRY_INDEX); + Lisp_Object alter = Qnil; + char *r = NULL; + + if (! NILP (registry)) + alter = Fassoc_string (SYMBOL_NAME (registry), + Vface_alternative_font_registry_alist); + while (1) + { + for (limit = 512, num_fonts = 0; ; limit *= 2) + { + names = XListFonts (dpyinfo->display, name, limit, &num_fonts); + if (x_had_errors_p (dpyinfo->display)) + { + /* This error is perhaps due to insufficient memory + on X server. Let's just ignore it. */ + x_clear_errors (dpyinfo->display); + error_occurred = 1; + num_fonts = 0; + break; + } + if (num_fonts < limit) + break; + XFreeFontNames (names); + } + if (num_fonts > 0 + || NILP (alter)) + break; + + /* Setup for trying alternatives. */ + if (! r + && ! (r = strstr (name, (char *) SDATA (SYMBOL_NAME (registry))))) + abort (); + while (1) + { + registry = Qnil; + alter = XCDR (alter); + if (NILP (alter)) + break; + registry = XCAR (alter); + if ((r - name) + SBYTES (registry) < 255) + break; + } + if (NILP (registry)) + break; + bcopy (SDATA (registry), r, SBYTES (registry)); + } + } + + x_uncatch_errors (); + UNBLOCK_INPUT; + + if (error_occurred) + return Qnil; + if (num_fonts == 0) + return null_vector; + + entity = Fmake_vector (make_number (FONT_ENTITY_MAX), Qnil); + ASET (entity, FONT_TYPE_INDEX, Qx); + ASET (entity, FONT_FRAME_INDEX, frame); + + SAFE_ALLOCA_LISP (vec, num_fonts); + for (i = idx = 0; i < num_fonts; i++) + { + if (font_parse_xlfd (names[i], entity, 0) > 0) + vec[idx++] = Fcopy_sequence (entity); + } + if (! STRINGP (font_name)) + { + BLOCK_INPUT; + XFreeFontNames (names); + UNBLOCK_INPUT; + } + val = Fvector (idx, vec); + SAFE_FREE (); + + return val; +} + +static int +memq_no_quit (elt, list) + Lisp_Object elt, list; +{ + while (CONSP (list) && ! EQ (XCAR (list), elt)) + list = XCDR (list); + return (CONSP (list)); +} + +static Lisp_Object +xfont_list_family (frame) +{ + FRAME_PTR f = XFRAME (frame); + Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + char **names; + int num_fonts, i; + Lisp_Object list; + char *last_family; + int last_len; + + BLOCK_INPUT; + x_catch_errors (dpyinfo->display); + names = XListFonts (dpyinfo->display, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*", + 0x8000, &num_fonts); + if (x_had_errors_p (dpyinfo->display)) + { + /* This error is perhaps due to insufficient memory on X server. + Let's just ignore it. */ + x_clear_errors (dpyinfo->display); + num_fonts = 0; + } + + list = Qnil; + for (i = 0, last_len = 0; i < num_fonts; i++) + { + char *p0 = names[i], *p1; + Lisp_Object family; + + p0++; /* skip the leading '-' */ + while (*p0 && *p0 != '-') p0++; /* skip foundry */ + if (! *p0) + continue; + p1 = ++p0; + while (*p1 && *p1 != '-') p1++; /* find the end of family */ + if (! *p1 || p1 == p0) + continue; + if (last_len == p1 - p0 + && bcmp (last_family, p0, last_len) == 0) + continue; + last_len = p1 - p0; + last_family = p0; + family = intern_downcase (p0, last_len); + if (! memq_no_quit (family, list)) + list = Fcons (family, list); + } + + XFreeFontNames (names); + x_uncatch_errors (); + UNBLOCK_INPUT; + + return list; +} + +static struct font * +xfont_open (f, entity, pixel_size) + FRAME_PTR f; + Lisp_Object entity; + int pixel_size; +{ + Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + Display *display = dpyinfo->display; + char name[256]; + int len; + unsigned long value; + Lisp_Object registry; + struct charset *encoding, *repertory; + struct font *font; + XFontStruct *xfont; + + /* At first, check if we know how to encode characters for this + font. */ + registry = AREF (entity, FONT_REGISTRY_INDEX); + if (xfont_registry_charsets (registry, &encoding, &repertory) < 0) + return NULL; + + if (XINT (AREF (entity, FONT_SIZE_INDEX)) != 0) + pixel_size = XINT (AREF (entity, FONT_SIZE_INDEX)); + len = font_unparse_xlfd (entity, pixel_size, name, 256); + if (len <= 0) + return NULL; + + BLOCK_INPUT; + x_catch_errors (display); + xfont = XLoadQueryFont (display, name); + if (x_had_errors_p (display)) + { + /* This error is perhaps due to insufficient memory on X server. + Let's just ignore it. */ + x_clear_errors (display); + xfont = NULL; + } + x_uncatch_errors (); + UNBLOCK_INPUT; + + if (! xfont) + return NULL; + font = malloc (sizeof (struct font)); + font->font.font = xfont; + font->entity = entity; + font->pixel_size = pixel_size; + font->driver = &xfont_driver; + font->font.name = malloc (len + 1); + if (! font->font.name) + { + XFreeFont (display, xfont); + free (font); + return NULL; + } + bcopy (name, font->font.name, len + 1); + font->font.charset = encoding->id; + font->encoding_charset = encoding->id; + font->repertory_charet = repertory ? repertory->id : -1; + font->ascent = xfont->ascent; + font->descent = xfont->descent; + + if (xfont->min_bounds.width == xfont->max_bounds.width) + { + /* Fixed width font. */ + font->font.average_width = font->font.space_width + = xfont->min_bounds.width; + } + else + { + XChar2b char2b; + XCharStruct *pcm; + + char2b.byte1 = 0x00, char2b.byte2 = 0x20; + pcm = xfont_get_pcm (xfont, &char2b); + if (pcm) + font->font.space_width = pcm->width; + else + font->font.space_width = xfont->max_bounds.width; + + font->font.average_width + = (XGetFontProperty (xfont, dpyinfo->Xatom_AVERAGE_WIDTH, &value) + ? (long) value / 10 : 0); + if (font->font.average_width < 0) + font->font.average_width = - font->font.average_width; + if (font->font.average_width == 0) + { + if (pcm) + { + int width = pcm->width; + for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++) + if ((pcm = xfont_get_pcm (xfont, &char2b)) != NULL) + width += pcm->width; + font->font.average_width = width / 95; + } + else + font->font.average_width = xfont->max_bounds.width; + } + } + font->min_width = xfont->min_bounds.width; + if (font->min_width <= 0) + font->min_width = font->font.space_width; + + BLOCK_INPUT; + /* Try to get the full name of FONT. Put it in FULL_NAME. */ + if (XGetFontProperty (xfont, XA_FONT, &value)) + { + char *full_name = NULL, *p0, *p; + int dashes = 0; + + p0 = p = (char *) 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. + In X11R4, the fonts did not come with their canonical names + stored in them. */ + while (*p) + { + if (*p == '-') + dashes++; + p++; + } + + if (dashes >= 13) + { + full_name = (char *) malloc (p - p0 + 1); + if (full_name) + bcopy (p0, full_name, p - p0 + 1); + } + XFree (p0); + + if (full_name) + font->font.full_name = full_name; + else + font->font.full_name = font->font.name; + } + font->file_name = NULL; + + font->font.size = xfont->max_bounds.width; + font->font.height = xfont->ascent + xfont->descent; + font->font.baseline_offset + = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value) + ? (long) value : 0); + font->font.relative_compose + = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value) + ? (long) value : 0); + font->font.default_ascent + = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value) + ? (long) value : 0); + font->font.vertical_centering + = (STRINGP (Vvertical_centering_font_regexp) + && (fast_c_string_match_ignore_case + (Vvertical_centering_font_regexp, font->font.full_name) >= 0)); + + UNBLOCK_INPUT; + + dpyinfo->n_fonts++; + + /* Set global flag fonts_changed_p to non-zero if the font loaded + has a character with a smaller width than any other character + before, or if the font loaded has a smaller height than any other + font loaded before. If this happens, it will make a glyph matrix + reallocation necessary. */ + if (dpyinfo->n_fonts == 1) + { + dpyinfo->smallest_font_height = font->font.height; + dpyinfo->smallest_char_width = font->min_width; + fonts_changed_p = 1; + } + else + { + if (dpyinfo->smallest_font_height > font->font.height) + dpyinfo->smallest_font_height = font->font.height, fonts_changed_p |= 1; + if (dpyinfo->smallest_char_width > font->min_width) + dpyinfo->smallest_char_width = font->min_width, fonts_changed_p |= 1; + } + + return font; +} + +static void +xfont_close (f, font) + FRAME_PTR f; + struct font *font; +{ + BLOCK_INPUT; + XFreeFont (FRAME_X_DISPLAY (f), font->font.font); + UNBLOCK_INPUT; + + if (font->font.name != font->font.full_name) + free (font->font.full_name); + free (font->font.name); + free (font); + FRAME_X_DISPLAY_INFO (f)->n_fonts--; +} + +static int +xfont_prepare_face (f, face) + FRAME_PTR f; + struct face *face; +{ + BLOCK_INPUT; + XSetFont (FRAME_X_DISPLAY (f), face->gc, face->font->fid); + UNBLOCK_INPUT; + + return 0; +} + +#if 0 +static void +xfont_done_face (f, face) + FRAME_PTR f; + struct face *face; +{ + if (face->extra) + { + BLOCK_INPUT; + XFreeGC (FRAME_X_DISPLAY (f), (GC) face->extra); + UNBLOCK_INPUT; + face->extra = NULL; + } +} +#endif /* 0 */ + +static int +xfont_has_char (entity, c) + Lisp_Object entity; + int c; +{ + Lisp_Object registry = AREF (entity, FONT_REGISTRY_INDEX); + struct charset *repertory; + + if (xfont_registry_charsets (registry, NULL, &repertory) < 0) + return -1; + if (! repertory) + return -1; + return (ENCODE_CHAR (repertory, c) != CHARSET_INVALID_CODE (repertory)); +} + +static unsigned +xfont_encode_char (font, c) + struct font *font; + int c; +{ + struct charset *charset; + unsigned code; + XChar2b char2b; + + charset = CHARSET_FROM_ID (font->encoding_charset); + code = ENCODE_CHAR (charset, c); + if (code == CHARSET_INVALID_CODE (charset)) + return 0xFFFFFFFF; + if (font->repertory_charet >= 0) + { + charset = CHARSET_FROM_ID (font->repertory_charet); + return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset) + ? code : 0xFFFFFFFF); + } + char2b.byte1 = code >> 16; + char2b.byte2 = code & 0xFFFF; + return (xfont_get_pcm (font->font.font, &char2b) ? code : 0xFFFFFFFF); +} + +static int +xfont_text_extents (font, code, nglyphs, metrics) + struct font *font; + unsigned *code; + int nglyphs; + struct font_metrics *metrics; +{ + int width = 0; + int i, x; + + if (metrics) + bzero (metrics, sizeof (struct font_metrics)); + for (i = 0, x = 0; i < nglyphs; i++) + { + XChar2b char2b; + static XCharStruct *pcm; + + if (code[i] >= 0x10000) + continue; + char2b.byte1 = code[i] >> 8, char2b.byte2 = code[i] & 0xFF; + pcm = xfont_get_pcm (font->font.font, &char2b); + if (! pcm) + continue; + if (metrics->lbearing > width + pcm->lbearing) + metrics->lbearing = width + pcm->lbearing; + if (metrics->rbearing < width + pcm->rbearing) + metrics->rbearing = width + pcm->rbearing; + if (metrics->ascent < pcm->ascent) + metrics->ascent = pcm->ascent; + if (metrics->descent < pcm->descent) + metrics->descent = pcm->descent; + width += pcm->width; + } + if (metrics) + metrics->width = width; + return width; +} + +static int +xfont_draw (s, from, to, x, y, with_background) + struct glyph_string *s; + int from, to, x, y, with_background; +{ + XFontStruct *xfont = s->face->font; + int len = to - from; + + if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0) + { + char *str; + int i; + USE_SAFE_ALLOCA; + + SAFE_ALLOCA (str, char *, len); + for (i = 0; i < len ; i++) + str[i] = XCHAR2B_BYTE2 (s->char2b + from + i); + if (with_background > 0) + XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f), + s->gc, x, y, str, len); + else + XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f), + s->gc, x, y, str, len); + SAFE_FREE (); + return s->nchars; + } + + if (with_background > 0) + XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f), + s->gc, x, y, s->char2b + from, len); + else + XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f), + s->gc, x, y, s->char2b + from, len); + + return len; +} + + + +void +syms_of_xfont () +{ + staticpro (&x_font_charset_alist); + x_font_charset_alist = Qnil; + + DEFSYM (Qx, "x"); + xfont_driver.type = Qx; + register_font_driver (&xfont_driver, NULL); +}