(calendar-location-name, calendar-latitude)
[emacs.git] / src / xfont.c
blobf13f3e5e36caef5627f15a65a9baa6bc0ab1c93d
1 /* xfont.c -- X core font driver.
2 Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H13PRO009
7 This file is part of GNU Emacs.
9 GNU Emacs is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
12 any later version.
14 GNU Emacs is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GNU Emacs; see the file COPYING. If not, write to
21 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 Boston, MA 02110-1301, USA. */
24 #include <config.h>
25 #include <stdio.h>
26 #include <X11/Xlib.h>
28 #include "lisp.h"
29 #include "dispextern.h"
30 #include "xterm.h"
31 #include "frame.h"
32 #include "blockinput.h"
33 #include "character.h"
34 #include "charset.h"
35 #include "fontset.h"
36 #include "font.h"
39 /* X core font driver. */
41 /* Prototypes of support functions. */
42 extern void x_clear_errors P_ ((Display *));
44 static char *xfont_query_font P_ ((Display *, char *, Lisp_Object));
45 static XCharStruct *xfont_get_pcm P_ ((XFontStruct *, XChar2b *));
46 static int xfont_registry_charsets P_ ((Lisp_Object, struct charset **,
47 struct charset **));
49 static char *
50 xfont_query_font (display, name, spec)
51 Display *display;
52 char *name;
53 Lisp_Object spec;
55 XFontStruct *font;
57 BLOCK_INPUT;
58 x_catch_errors (display);
59 font = XLoadQueryFont (display, name);
60 name = NULL;
61 if (x_had_errors_p (display))
63 /* This error is perhaps due to insufficient memory on X
64 server. Let's just ignore it. */
65 x_clear_errors (display);
67 else if (font)
69 unsigned long value;
71 if (XGetFontProperty (font, XA_FONT, &value))
73 char *n = (char *) XGetAtomName (display, (Atom) value);
75 if (font_parse_xlfd (n, spec) >= 0)
76 name = n;
77 else
78 XFree (n);
80 XFreeFont (display, font);
82 x_uncatch_errors ();
83 UNBLOCK_INPUT;
85 return name;
89 /* Get metrics of character CHAR2B in XFONT. Value is null if CHAR2B
90 is not contained in the font. */
92 static XCharStruct *
93 xfont_get_pcm (xfont, char2b)
94 XFontStruct *xfont;
95 XChar2b *char2b;
97 /* The result metric information. */
98 XCharStruct *pcm = NULL;
100 xassert (xfont && char2b);
102 if (xfont->per_char != NULL)
104 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
106 /* min_char_or_byte2 specifies the linear character index
107 corresponding to the first element of the per_char array,
108 max_char_or_byte2 is the index of the last character. A
109 character with non-zero CHAR2B->byte1 is not in the font.
110 A character with byte2 less than min_char_or_byte2 or
111 greater max_char_or_byte2 is not in the font. */
112 if (char2b->byte1 == 0
113 && char2b->byte2 >= xfont->min_char_or_byte2
114 && char2b->byte2 <= xfont->max_char_or_byte2)
115 pcm = xfont->per_char + char2b->byte2 - xfont->min_char_or_byte2;
117 else
119 /* If either min_byte1 or max_byte1 are nonzero, both
120 min_char_or_byte2 and max_char_or_byte2 are less than
121 256, and the 2-byte character index values corresponding
122 to the per_char array element N (counting from 0) are:
124 byte1 = N/D + min_byte1
125 byte2 = N\D + min_char_or_byte2
127 where:
129 D = max_char_or_byte2 - min_char_or_byte2 + 1
130 / = integer division
131 \ = integer modulus */
132 if (char2b->byte1 >= xfont->min_byte1
133 && char2b->byte1 <= xfont->max_byte1
134 && char2b->byte2 >= xfont->min_char_or_byte2
135 && char2b->byte2 <= xfont->max_char_or_byte2)
136 pcm = (xfont->per_char
137 + ((xfont->max_char_or_byte2 - xfont->min_char_or_byte2 + 1)
138 * (char2b->byte1 - xfont->min_byte1))
139 + (char2b->byte2 - xfont->min_char_or_byte2));
142 else
144 /* If the per_char pointer is null, all glyphs between the first
145 and last character indexes inclusive have the same
146 information, as given by both min_bounds and max_bounds. */
147 if (char2b->byte2 >= xfont->min_char_or_byte2
148 && char2b->byte2 <= xfont->max_char_or_byte2)
149 pcm = &xfont->max_bounds;
152 return ((pcm == NULL
153 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
154 ? NULL : pcm);
157 static Lisp_Object xfont_get_cache P_ ((FRAME_PTR));
158 static Lisp_Object xfont_list P_ ((Lisp_Object, Lisp_Object));
159 static Lisp_Object xfont_match P_ ((Lisp_Object, Lisp_Object));
160 static Lisp_Object xfont_list_family P_ ((Lisp_Object));
161 static struct font *xfont_open P_ ((FRAME_PTR, Lisp_Object, int));
162 static void xfont_close P_ ((FRAME_PTR, struct font *));
163 static int xfont_prepare_face P_ ((FRAME_PTR, struct face *));
164 #if 0
165 static void xfont_done_face P_ ((FRAME_PTR, struct face *));
166 #endif
167 static int xfont_has_char P_ ((Lisp_Object, int));
168 static unsigned xfont_encode_char P_ ((struct font *, int));
169 static int xfont_text_extents P_ ((struct font *, unsigned *, int,
170 struct font_metrics *));
171 static int xfont_draw P_ ((struct glyph_string *, int, int, int, int, int));
173 struct font_driver xfont_driver =
175 0, /* Qx */
176 xfont_get_cache,
177 xfont_list,
178 xfont_match,
179 xfont_list_family,
180 NULL,
181 xfont_open,
182 xfont_close,
183 xfont_prepare_face,
184 NULL /*xfont_done_face*/,
185 xfont_has_char,
186 xfont_encode_char,
187 xfont_text_extents,
188 xfont_draw
191 extern Lisp_Object QCname;
193 static Lisp_Object
194 xfont_get_cache (f)
195 FRAME_PTR f;
197 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
199 return (dpyinfo->name_list_element);
202 extern Lisp_Object Vface_alternative_font_registry_alist;
204 static Lisp_Object
205 xfont_list_pattern (frame, display, pattern)
206 Lisp_Object frame;
207 Display *display;
208 char *pattern;
210 Lisp_Object list = Qnil;
211 int i, limit, num_fonts;
212 char **names;
214 BLOCK_INPUT;
215 x_catch_errors (display);
217 for (limit = 512; ; limit *= 2)
219 names = XListFonts (display, pattern, limit, &num_fonts);
220 if (x_had_errors_p (display))
222 /* This error is perhaps due to insufficient memory on X
223 server. Let's just ignore it. */
224 x_clear_errors (display);
225 num_fonts = 0;
226 break;
228 if (num_fonts < limit)
229 break;
230 XFreeFontNames (names);
233 for (i = 0; i < num_fonts; i++)
235 Lisp_Object entity = Fmake_vector (make_number (FONT_ENTITY_MAX), Qnil);
236 int result;
238 ASET (entity, FONT_TYPE_INDEX, Qx);
239 ASET (entity, FONT_FRAME_INDEX, frame);
241 result = font_parse_xlfd (names[i], entity);
242 if (result < 0)
244 /* This may be an alias name. Try to get the full XLFD name
245 from XA_FONT property of the font. */
246 XFontStruct *font = XLoadQueryFont (display, names[i]);
247 unsigned long value;
249 if (! font)
250 continue;
251 if (XGetFontProperty (font, XA_FONT, &value))
253 char *name = (char *) XGetAtomName (display, (Atom) value);
254 int len = strlen (name);
256 /* If DXPC (a Differential X Protocol Compressor)
257 Ver.3.7 is running, XGetAtomName will return null
258 string. We must avoid such a name. */
259 if (len > 0)
260 result = font_parse_xlfd (name, entity);
261 XFree (name);
263 XFreeFont (display, font);
266 if (result == 0)
268 Lisp_Object val = AREF (entity, FONT_EXTRA_INDEX);
269 char *p = (char *) SDATA (SYMBOL_NAME (val));
271 /* P == "RESX-RESY-SPACING-AVGWIDTH. We rejust this font if
272 it's an autoscaled one (i.e. RESX > 0 && AVGWIDTH == 0). */
273 if (atoi (p) > 0)
275 p += SBYTES (SYMBOL_NAME (val));
276 while (p[-1] != '-') p--;
277 if (atoi (p) == 0)
278 continue;
280 list = Fcons (entity, list);
284 x_uncatch_errors ();
285 UNBLOCK_INPUT;
287 return list;
290 static Lisp_Object
291 xfont_list (frame, spec)
292 Lisp_Object frame, spec;
294 FRAME_PTR f = XFRAME (frame);
295 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
296 Lisp_Object list, val, extra, font_name;
297 int len;
298 char name[256];
300 extra = AREF (spec, FONT_EXTRA_INDEX);
301 font_name = Qnil;
302 if (CONSP (extra))
304 val = assq_no_quit (QCotf, extra);
305 if (! NILP (val))
306 return null_vector;
307 val = assq_no_quit (QCscript, extra);
308 if (! NILP (val))
309 return null_vector;
310 val = assq_no_quit (QClanguage, extra);
311 if (! NILP (val))
312 return null_vector;
313 val = assq_no_quit (QCname, extra);
314 if (CONSP (val))
315 font_name = XCDR (val);
318 if (STRINGP (font_name)
319 && ! strchr ((char *) SDATA (font_name), ':'))
320 list = xfont_list_pattern (frame, display, (char *) SDATA (font_name));
321 else if ((len = font_unparse_xlfd (spec, 0, name, 256)) < 0)
322 return null_vector;
323 else
325 list = xfont_list_pattern (frame, display, name);
326 if (NILP (list))
328 Lisp_Object registry = AREF (spec, FONT_REGISTRY_INDEX);
329 Lisp_Object alter;
331 if (! NILP (registry)
332 && (alter = Fassoc (SYMBOL_NAME (registry),
333 Vface_alternative_font_registry_alist),
334 CONSP (alter)))
336 /* Pointer to REGISTRY-ENCODING field. */
337 char *r = name + len - SBYTES (SYMBOL_NAME (registry));
339 for (alter = XCDR (alter); CONSP (alter); alter = XCDR (alter))
340 if (STRINGP (XCAR (alter))
341 && ((r - name) + SBYTES (XCAR (alter))) < 255)
343 strcpy (r, (char *) SDATA (XCAR (alter)));
344 list = xfont_list_pattern (frame, display, name);
345 if (! NILP (list))
346 break;
352 return (NILP (list) ? null_vector : Fvconcat (1, &list));
355 static Lisp_Object
356 xfont_match (frame, spec)
357 Lisp_Object frame, spec;
359 FRAME_PTR f = XFRAME (frame);
360 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
361 Lisp_Object extra, val, entity;
362 char *name;
363 XFontStruct *xfont;
364 unsigned long value;
366 extra = AREF (spec, FONT_EXTRA_INDEX);
367 val = assq_no_quit (QCname, extra);
368 if (! CONSP (val) || ! STRINGP (XCDR (val)))
369 return Qnil;
371 BLOCK_INPUT;
372 entity = Qnil;
373 name = (char *) SDATA (XCDR (val));
374 xfont = XLoadQueryFont (display, name);
375 if (xfont)
377 if (XGetFontProperty (xfont, XA_FONT, &value))
379 int len;
381 name = (char *) XGetAtomName (display, (Atom) value);
382 len = strlen (name);
384 /* If DXPC (a Differential X Protocol Compressor)
385 Ver.3.7 is running, XGetAtomName will return null
386 string. We must avoid such a name. */
387 if (len > 0)
389 entity = Fmake_vector (make_number (FONT_ENTITY_MAX), Qnil);
390 ASET (entity, FONT_TYPE_INDEX, Qx);
391 ASET (entity, FONT_FRAME_INDEX, frame);
392 if (font_parse_xlfd (name, entity) < 0)
393 entity = Qnil;
395 XFree (name);
397 XFreeFont (display, xfont);
399 UNBLOCK_INPUT;
401 return entity;
404 static int
405 memq_no_quit (elt, list)
406 Lisp_Object elt, list;
408 while (CONSP (list) && ! EQ (XCAR (list), elt))
409 list = XCDR (list);
410 return (CONSP (list));
413 static Lisp_Object
414 xfont_list_family (frame)
415 Lisp_Object frame;
417 FRAME_PTR f = XFRAME (frame);
418 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
419 char **names;
420 int num_fonts, i;
421 Lisp_Object list;
422 char *last_family;
423 int last_len;
425 BLOCK_INPUT;
426 x_catch_errors (dpyinfo->display);
427 names = XListFonts (dpyinfo->display, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*",
428 0x8000, &num_fonts);
429 if (x_had_errors_p (dpyinfo->display))
431 /* This error is perhaps due to insufficient memory on X server.
432 Let's just ignore it. */
433 x_clear_errors (dpyinfo->display);
434 num_fonts = 0;
437 list = Qnil;
438 for (i = 0, last_len = 0; i < num_fonts; i++)
440 char *p0 = names[i], *p1;
441 Lisp_Object family;
443 p0++; /* skip the leading '-' */
444 while (*p0 && *p0 != '-') p0++; /* skip foundry */
445 if (! *p0)
446 continue;
447 p1 = ++p0;
448 while (*p1 && *p1 != '-') p1++; /* find the end of family */
449 if (! *p1 || p1 == p0)
450 continue;
451 if (last_len == p1 - p0
452 && bcmp (last_family, p0, last_len) == 0)
453 continue;
454 last_len = p1 - p0;
455 last_family = p0;
456 family = intern_downcase (p0, last_len);
457 if (! memq_no_quit (family, list))
458 list = Fcons (family, list);
461 XFreeFontNames (names);
462 x_uncatch_errors ();
463 UNBLOCK_INPUT;
465 return list;
468 static struct font *
469 xfont_open (f, entity, pixel_size)
470 FRAME_PTR f;
471 Lisp_Object entity;
472 int pixel_size;
474 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
475 Display *display = dpyinfo->display;
476 char name[256];
477 int len;
478 unsigned long value;
479 Lisp_Object registry;
480 struct charset *encoding, *repertory;
481 struct font *font;
482 XFontStruct *xfont;
484 /* At first, check if we know how to encode characters for this
485 font. */
486 registry = AREF (entity, FONT_REGISTRY_INDEX);
487 if (font_registry_charsets (registry, &encoding, &repertory) < 0)
488 return NULL;
490 if (XINT (AREF (entity, FONT_SIZE_INDEX)) != 0)
491 pixel_size = XINT (AREF (entity, FONT_SIZE_INDEX));
492 len = font_unparse_xlfd (entity, pixel_size, name, 256);
493 if (len <= 0)
494 return NULL;
496 BLOCK_INPUT;
497 x_catch_errors (display);
498 xfont = XLoadQueryFont (display, name);
499 if (x_had_errors_p (display))
501 /* This error is perhaps due to insufficient memory on X server.
502 Let's just ignore it. */
503 x_clear_errors (display);
504 xfont = NULL;
506 x_uncatch_errors ();
507 UNBLOCK_INPUT;
509 if (! xfont)
510 return NULL;
511 font = malloc (sizeof (struct font));
512 font->format = Qx;
513 font->font.font = xfont;
514 font->entity = entity;
515 font->pixel_size = pixel_size;
516 font->driver = &xfont_driver;
517 font->font.name = malloc (len + 1);
518 if (! font->font.name)
520 XFreeFont (display, xfont);
521 free (font);
522 return NULL;
524 bcopy (name, font->font.name, len + 1);
525 font->font.charset = encoding->id;
526 font->encoding_charset = encoding->id;
527 font->repertory_charset = repertory ? repertory->id : -1;
528 font->ascent = xfont->ascent;
529 font->descent = xfont->descent;
531 if (xfont->min_bounds.width == xfont->max_bounds.width)
533 /* Fixed width font. */
534 font->font.average_width = font->font.space_width
535 = xfont->min_bounds.width;
537 else
539 XChar2b char2b;
540 XCharStruct *pcm;
542 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
543 pcm = xfont_get_pcm (xfont, &char2b);
544 if (pcm)
545 font->font.space_width = pcm->width;
546 else
547 font->font.space_width = xfont->max_bounds.width;
549 font->font.average_width
550 = (XGetFontProperty (xfont, dpyinfo->Xatom_AVERAGE_WIDTH, &value)
551 ? (long) value / 10 : 0);
552 if (font->font.average_width < 0)
553 font->font.average_width = - font->font.average_width;
554 if (font->font.average_width == 0)
556 if (pcm)
558 int width = pcm->width;
559 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
560 if ((pcm = xfont_get_pcm (xfont, &char2b)) != NULL)
561 width += pcm->width;
562 font->font.average_width = width / 95;
564 else
565 font->font.average_width = xfont->max_bounds.width;
568 font->min_width = xfont->min_bounds.width;
569 if (font->min_width <= 0)
570 font->min_width = font->font.space_width;
572 BLOCK_INPUT;
573 /* Try to get the full name of FONT. Put it in FULL_NAME. */
574 if (XGetFontProperty (xfont, XA_FONT, &value))
576 char *full_name = NULL, *p0, *p;
577 int dashes = 0;
579 p0 = p = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);;
580 /* Count the number of dashes in the "full name".
581 If it is too few, this isn't really the font's full name,
582 so don't use it.
583 In X11R4, the fonts did not come with their canonical names
584 stored in them. */
585 while (*p)
587 if (*p == '-')
588 dashes++;
589 p++;
592 if (dashes >= 13)
594 full_name = (char *) malloc (p - p0 + 1);
595 if (full_name)
596 bcopy (p0, full_name, p - p0 + 1);
598 XFree (p0);
600 if (full_name)
601 font->font.full_name = full_name;
602 else
603 font->font.full_name = font->font.name;
605 font->file_name = NULL;
607 font->font.size = xfont->max_bounds.width;
608 font->font.height = xfont->ascent + xfont->descent;
609 font->font.baseline_offset
610 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
611 ? (long) value : 0);
612 font->font.relative_compose
613 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
614 ? (long) value : 0);
615 font->font.default_ascent
616 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
617 ? (long) value : 0);
618 font->font.vertical_centering
619 = (STRINGP (Vvertical_centering_font_regexp)
620 && (fast_c_string_match_ignore_case
621 (Vvertical_centering_font_regexp, font->font.full_name) >= 0));
623 UNBLOCK_INPUT;
625 dpyinfo->n_fonts++;
627 /* Set global flag fonts_changed_p to non-zero if the font loaded
628 has a character with a smaller width than any other character
629 before, or if the font loaded has a smaller height than any other
630 font loaded before. If this happens, it will make a glyph matrix
631 reallocation necessary. */
632 if (dpyinfo->n_fonts == 1)
634 dpyinfo->smallest_font_height = font->font.height;
635 dpyinfo->smallest_char_width = font->min_width;
636 fonts_changed_p = 1;
638 else
640 if (dpyinfo->smallest_font_height > font->font.height)
641 dpyinfo->smallest_font_height = font->font.height, fonts_changed_p |= 1;
642 if (dpyinfo->smallest_char_width > font->min_width)
643 dpyinfo->smallest_char_width = font->min_width, fonts_changed_p |= 1;
646 return font;
649 static void
650 xfont_close (f, font)
651 FRAME_PTR f;
652 struct font *font;
654 BLOCK_INPUT;
655 XFreeFont (FRAME_X_DISPLAY (f), font->font.font);
656 UNBLOCK_INPUT;
658 if (font->font.name != font->font.full_name)
659 free (font->font.full_name);
660 free (font->font.name);
661 free (font);
662 FRAME_X_DISPLAY_INFO (f)->n_fonts--;
665 static int
666 xfont_prepare_face (f, face)
667 FRAME_PTR f;
668 struct face *face;
670 BLOCK_INPUT;
671 XSetFont (FRAME_X_DISPLAY (f), face->gc, face->font->fid);
672 UNBLOCK_INPUT;
674 return 0;
677 #if 0
678 static void
679 xfont_done_face (f, face)
680 FRAME_PTR f;
681 struct face *face;
683 if (face->extra)
685 BLOCK_INPUT;
686 XFreeGC (FRAME_X_DISPLAY (f), (GC) face->extra);
687 UNBLOCK_INPUT;
688 face->extra = NULL;
691 #endif /* 0 */
693 static int
694 xfont_has_char (entity, c)
695 Lisp_Object entity;
696 int c;
698 Lisp_Object registry = AREF (entity, FONT_REGISTRY_INDEX);
699 struct charset *repertory;
701 if (font_registry_charsets (registry, NULL, &repertory) < 0)
702 return -1;
703 if (! repertory)
704 return -1;
705 return (ENCODE_CHAR (repertory, c) != CHARSET_INVALID_CODE (repertory));
708 static unsigned
709 xfont_encode_char (font, c)
710 struct font *font;
711 int c;
713 struct charset *charset;
714 unsigned code;
715 XChar2b char2b;
717 charset = CHARSET_FROM_ID (font->encoding_charset);
718 code = ENCODE_CHAR (charset, c);
719 if (code == CHARSET_INVALID_CODE (charset))
720 return FONT_INVALID_CODE;
721 if (font->repertory_charset >= 0)
723 charset = CHARSET_FROM_ID (font->repertory_charset);
724 return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset)
725 ? code : FONT_INVALID_CODE);
727 char2b.byte1 = code >> 8;
728 char2b.byte2 = code & 0xFF;
729 return (xfont_get_pcm (font->font.font, &char2b) ? code : FONT_INVALID_CODE);
732 static int
733 xfont_text_extents (font, code, nglyphs, metrics)
734 struct font *font;
735 unsigned *code;
736 int nglyphs;
737 struct font_metrics *metrics;
739 int width = 0;
740 int i, x;
742 if (metrics)
743 bzero (metrics, sizeof (struct font_metrics));
744 for (i = 0, x = 0; i < nglyphs; i++)
746 XChar2b char2b;
747 static XCharStruct *pcm;
749 if (code[i] >= 0x10000)
750 continue;
751 char2b.byte1 = code[i] >> 8, char2b.byte2 = code[i] & 0xFF;
752 pcm = xfont_get_pcm (font->font.font, &char2b);
753 if (! pcm)
754 continue;
755 if (metrics->lbearing > width + pcm->lbearing)
756 metrics->lbearing = width + pcm->lbearing;
757 if (metrics->rbearing < width + pcm->rbearing)
758 metrics->rbearing = width + pcm->rbearing;
759 if (metrics->ascent < pcm->ascent)
760 metrics->ascent = pcm->ascent;
761 if (metrics->descent < pcm->descent)
762 metrics->descent = pcm->descent;
763 width += pcm->width;
765 if (metrics)
766 metrics->width = width;
767 return width;
770 static int
771 xfont_draw (s, from, to, x, y, with_background)
772 struct glyph_string *s;
773 int from, to, x, y, with_background;
775 XFontStruct *xfont = s->face->font;
776 int len = to - from;
777 GC gc = s->gc;
778 int i;
780 if (gc != s->face->gc)
782 XGCValues xgcv;
783 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (s->f);
785 BLOCK_INPUT;
786 XGetGCValues (s->display, gc, GCFont, &xgcv);
787 if (xgcv.font != xfont->fid)
788 XSetFont (s->display, gc, xfont->fid);
789 UNBLOCK_INPUT;
792 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
794 char *str;
795 USE_SAFE_ALLOCA;
797 SAFE_ALLOCA (str, char *, len);
798 for (i = 0; i < len ; i++)
799 str[i] = XCHAR2B_BYTE2 (s->char2b + from + i);
800 BLOCK_INPUT;
801 if (with_background > 0)
803 if (s->padding_p)
804 for (i = 0; i < len; i++)
805 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
806 gc, x + i, y, str + i, 1);
807 else
808 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
809 gc, x, y, str, len);
811 else
813 if (s->padding_p)
814 for (i = 0; i < len; i++)
815 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
816 gc, x + i, y, str + i, 1);
817 else
818 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
819 gc, x, y, str, len);
821 UNBLOCK_INPUT;
822 SAFE_FREE ();
823 return s->nchars;
826 BLOCK_INPUT;
827 if (with_background > 0)
829 if (s->padding_p)
830 for (i = 0; i < len; i++)
831 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
832 gc, x + i, y, s->char2b + from + i, 1);
833 else
834 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
835 gc, x, y, s->char2b + from, len);
837 else
839 if (s->padding_p)
840 for (i = 0; i < len; i++)
841 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
842 gc, x + i, y, s->char2b + from + i, 1);
843 else
844 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
845 gc, x, y, s->char2b + from, len);
847 UNBLOCK_INPUT;
849 return len;
853 void
854 syms_of_xfont ()
856 xfont_driver.type = Qx;
857 register_font_driver (&xfont_driver, NULL);
860 /* arch-tag: 23c5f366-a5ee-44b7-a3b7-90d6da7fd749
861 (do not change this comment) */