Include coding.h and termhooks.h.
[bpt/emacs.git] / src / xfont.c
CommitLineData
c2f5bfd6 1/* xfont.c -- X core font driver.
76b6f707
GM
2 Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008, 2009
c2f5bfd6
KH
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H13PRO009
6
7This file is part of GNU Emacs.
8
9ec0b715 9GNU Emacs is free software: you can redistribute it and/or modify
c2f5bfd6 10it under the terms of the GNU General Public License as published by
9ec0b715
GM
11the Free Software Foundation, either version 3 of the License, or
12(at your option) any later version.
c2f5bfd6
KH
13
14GNU Emacs is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
9ec0b715 20along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
c2f5bfd6
KH
21
22#include <config.h>
23#include <stdio.h>
f0c55750 24#include <stdlib.h>
c2f5bfd6
KH
25#include <X11/Xlib.h>
26
27#include "lisp.h"
28#include "dispextern.h"
29#include "xterm.h"
30#include "frame.h"
31#include "blockinput.h"
32#include "character.h"
33#include "charset.h"
34#include "fontset.h"
35#include "font.h"
f0c55750 36#include "ccl.h"
c2f5bfd6
KH
37
38\f
39/* X core font driver. */
40
f0c55750
KH
41struct xfont_info
42{
43 struct font font;
44 Display *display;
45 XFontStruct *xfont;
46};
47
c2f5bfd6
KH
48/* Prototypes of support functions. */
49extern void x_clear_errors P_ ((Display *));
50
c2f5bfd6 51static XCharStruct *xfont_get_pcm P_ ((XFontStruct *, XChar2b *));
f0c55750 52static void xfont_find_ccl_program P_ ((struct font *));
c2f5bfd6
KH
53
54/* Get metrics of character CHAR2B in XFONT. Value is null if CHAR2B
55 is not contained in the font. */
56
57static XCharStruct *
58xfont_get_pcm (xfont, char2b)
59 XFontStruct *xfont;
60 XChar2b *char2b;
61{
62 /* The result metric information. */
63 XCharStruct *pcm = NULL;
64
960d80b9 65 font_assert (xfont && char2b);
c2f5bfd6
KH
66
67 if (xfont->per_char != NULL)
68 {
69 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
70 {
71 /* min_char_or_byte2 specifies the linear character index
72 corresponding to the first element of the per_char array,
73 max_char_or_byte2 is the index of the last character. A
74 character with non-zero CHAR2B->byte1 is not in the font.
75 A character with byte2 less than min_char_or_byte2 or
76 greater max_char_or_byte2 is not in the font. */
77 if (char2b->byte1 == 0
78 && char2b->byte2 >= xfont->min_char_or_byte2
79 && char2b->byte2 <= xfont->max_char_or_byte2)
80 pcm = xfont->per_char + char2b->byte2 - xfont->min_char_or_byte2;
81 }
82 else
83 {
84 /* If either min_byte1 or max_byte1 are nonzero, both
85 min_char_or_byte2 and max_char_or_byte2 are less than
86 256, and the 2-byte character index values corresponding
87 to the per_char array element N (counting from 0) are:
88
89 byte1 = N/D + min_byte1
90 byte2 = N\D + min_char_or_byte2
91
92 where:
93
94 D = max_char_or_byte2 - min_char_or_byte2 + 1
95 / = integer division
96 \ = integer modulus */
97 if (char2b->byte1 >= xfont->min_byte1
98 && char2b->byte1 <= xfont->max_byte1
99 && char2b->byte2 >= xfont->min_char_or_byte2
100 && char2b->byte2 <= xfont->max_char_or_byte2)
101 pcm = (xfont->per_char
102 + ((xfont->max_char_or_byte2 - xfont->min_char_or_byte2 + 1)
103 * (char2b->byte1 - xfont->min_byte1))
104 + (char2b->byte2 - xfont->min_char_or_byte2));
105 }
106 }
107 else
108 {
109 /* If the per_char pointer is null, all glyphs between the first
110 and last character indexes inclusive have the same
111 information, as given by both min_bounds and max_bounds. */
112 if (char2b->byte2 >= xfont->min_char_or_byte2
113 && char2b->byte2 <= xfont->max_char_or_byte2)
114 pcm = &xfont->max_bounds;
115 }
116
117 return ((pcm == NULL
118 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
119 ? NULL : pcm);
120}
121
f0c55750
KH
122/* Find a CCL program for a font specified by FONTP, and set the member
123 `encoder' of the structure. */
124
125static void
126xfont_find_ccl_program (font)
127 struct font *font;
128{
129 Lisp_Object list, elt;
130
131 elt = Qnil;
132 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
133 {
134 elt = XCAR (list);
135 if (CONSP (elt)
136 && STRINGP (XCAR (elt))
137 && ((fast_string_match_ignore_case (XCAR (elt),
138 font->props[FONT_NAME_INDEX])
139 >= 0)
140 || (fast_string_match_ignore_case (XCAR (elt),
141 font->props[FONT_FULLNAME_INDEX])
142 >= 0)))
143 break;
144 }
145
146 if (! NILP (list))
147 {
148 struct ccl_program *ccl
149 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
150
151 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
152 xfree (ccl);
153 else
154 font->font_encoder = ccl;
155 }
156}
157
feb2737b 158static Lisp_Object xfont_get_cache P_ ((FRAME_PTR));
c2f5bfd6 159static Lisp_Object xfont_list P_ ((Lisp_Object, Lisp_Object));
6e34c9c1 160static Lisp_Object xfont_match P_ ((Lisp_Object, Lisp_Object));
c2f5bfd6 161static Lisp_Object xfont_list_family P_ ((Lisp_Object));
f0c55750 162static Lisp_Object xfont_open P_ ((FRAME_PTR, Lisp_Object, int));
c2f5bfd6
KH
163static void xfont_close P_ ((FRAME_PTR, struct font *));
164static int xfont_prepare_face P_ ((FRAME_PTR, struct face *));
c2f5bfd6
KH
165static int xfont_has_char P_ ((Lisp_Object, int));
166static unsigned xfont_encode_char P_ ((struct font *, int));
167static int xfont_text_extents P_ ((struct font *, unsigned *, int,
168 struct font_metrics *));
169static int xfont_draw P_ ((struct glyph_string *, int, int, int, int, int));
f0c55750 170static int xfont_check P_ ((FRAME_PTR, struct font *));
c2f5bfd6
KH
171
172struct font_driver xfont_driver =
173 {
575abfb7 174 0, /* Qx */
f0c55750 175 0, /* case insensitive */
c2f5bfd6 176 xfont_get_cache,
c2f5bfd6 177 xfont_list,
6e34c9c1 178 xfont_match,
c2f5bfd6
KH
179 xfont_list_family,
180 NULL,
181 xfont_open,
182 xfont_close,
183 xfont_prepare_face,
f0c55750 184 NULL,
c2f5bfd6
KH
185 xfont_has_char,
186 xfont_encode_char,
187 xfont_text_extents,
f0c55750
KH
188 xfont_draw,
189 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
190 xfont_check
c2f5bfd6
KH
191 };
192
193extern Lisp_Object QCname;
194
195static Lisp_Object
feb2737b
KH
196xfont_get_cache (f)
197 FRAME_PTR f;
c2f5bfd6 198{
feb2737b 199 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
c2f5bfd6
KH
200
201 return (dpyinfo->name_list_element);
202}
203
c2f5bfd6
KH
204extern Lisp_Object Vface_alternative_font_registry_alist;
205
f0c55750
KH
206static int
207compare_font_names (const void *name1, const void *name2)
208{
7740d2c7
KH
209 return xstrcasecmp (*(const unsigned char **) name1,
210 *(const unsigned char **) name2);
f0c55750
KH
211}
212
6a705b23
KH
213/* Decode XLFD as iso-8859-1 into OUTPUT, and return the byte length
214 of the decoding result. LEN is the byte length of XLFD, or -1 if
215 XLFD is NULL terminated. The caller must assure that OUTPUT is at
216 least twice (plus 1) as large as XLFD. */
217
218static int
219xfont_decode_coding_xlfd (char *xlfd, int len, char *output)
220{
221 char *p0 = xlfd, *p1 = output;
222 int c;
223
224 while (*p0)
225 {
226 c = *(unsigned char *) p0++;
227 p1 += CHAR_STRING (c, p1);
228 if (--len == 0)
229 break;
230 }
231 *p1 = 0;
232 return (p1 - output);
233}
234
235/* Encode XLFD from UTF-8 to iso-8859-1 destructively, and return the
236 resulting byte length. If XLFD contains unencodable character,
237 return -1. */
238
239static int
240xfont_encode_coding_xlfd (char *xlfd)
241{
242 const unsigned char *p0 = (unsigned char *) xlfd;
243 unsigned char *p1 = (unsigned char *) xlfd;
244 int len = 0;
245
246 while (*p0)
247 {
248 int c = STRING_CHAR_ADVANCE (p0);
249
250 if (c >= 0x100)
251 return -1;
252 *p1++ = c;
253 len++;
254 }
255 *p1 = 0;
256 return len;
257}
258
f0c55750
KH
259static Lisp_Object xfont_list_pattern P_ ((Lisp_Object, Display *, char *));
260
c2f5bfd6 261static Lisp_Object
6c4aeab6
KH
262xfont_list_pattern (frame, display, pattern)
263 Lisp_Object frame;
264 Display *display;
265 char *pattern;
c2f5bfd6 266{
6c4aeab6
KH
267 Lisp_Object list = Qnil;
268 int i, limit, num_fonts;
269 char **names;
6a705b23
KH
270 /* Large enough to decode the longest XLFD (255 bytes). */
271 char buf[512];
c2f5bfd6
KH
272
273 BLOCK_INPUT;
6c4aeab6 274 x_catch_errors (display);
c2f5bfd6 275
6c4aeab6 276 for (limit = 512; ; limit *= 2)
c2f5bfd6 277 {
6c4aeab6
KH
278 names = XListFonts (display, pattern, limit, &num_fonts);
279 if (x_had_errors_p (display))
c2f5bfd6
KH
280 {
281 /* This error is perhaps due to insufficient memory on X
282 server. Let's just ignore it. */
6c4aeab6
KH
283 x_clear_errors (display);
284 num_fonts = 0;
285 break;
c2f5bfd6 286 }
6c4aeab6
KH
287 if (num_fonts < limit)
288 break;
289 XFreeFontNames (names);
290 }
291
f0c55750 292 if (num_fonts > 0)
6c4aeab6 293 {
f0c55750 294 char **indices = alloca (sizeof (char *) * num_fonts);
6c4aeab6 295
f0c55750
KH
296 for (i = 0; i < num_fonts; i++)
297 indices[i] = names[i];
298 qsort (indices, num_fonts, sizeof (char *), compare_font_names);
6c4aeab6 299
f0c55750 300 for (i = 0; i < num_fonts; i++)
c2f5bfd6 301 {
f0c55750
KH
302 Lisp_Object entity;
303 int result;
6a705b23 304 char *p;
6c4aeab6 305
05131107 306 if (i > 0 && xstrcasecmp (indices[i - 1], indices[i]) == 0)
6c4aeab6 307 continue;
6c4aeab6 308
f0c55750
KH
309 entity = font_make_entity ();
310 ASET (entity, FONT_TYPE_INDEX, Qx);
6a705b23
KH
311 xfont_decode_coding_xlfd (indices[i], -1, buf);
312 result = font_parse_xlfd (buf, entity);
f0c55750 313 if (result < 0)
c2f5bfd6 314 {
f0c55750
KH
315 /* This may be an alias name. Try to get the full XLFD name
316 from XA_FONT property of the font. */
317 XFontStruct *font = XLoadQueryFont (display, indices[i]);
318 unsigned long value;
319
320 if (! font)
6c4aeab6 321 continue;
f0c55750
KH
322 if (XGetFontProperty (font, XA_FONT, &value))
323 {
324 char *name = (char *) XGetAtomName (display, (Atom) value);
325 int len = strlen (name);
326
327 /* If DXPC (a Differential X Protocol Compressor)
328 Ver.3.7 is running, XGetAtomName will return null
329 string. We must avoid such a name. */
330 if (len > 0)
6a705b23
KH
331 {
332 xfont_decode_coding_xlfd (indices[i], -1, buf);
333 result = font_parse_xlfd (buf, entity);
334 }
f0c55750
KH
335 XFree (name);
336 }
337 XFreeFont (display, font);
c2f5bfd6 338 }
f0c55750
KH
339
340 if (result == 0
341 /* Avoid auto-scaled fonts. */
342 && (XINT (AREF (entity, FONT_DPI_INDEX)) == 0
343 || XINT (AREF (entity, FONT_AVGWIDTH_INDEX)) > 0))
344 list = Fcons (entity, list);
c2f5bfd6 345 }
019e13ef 346 XFreeFontNames (names);
c2f5bfd6
KH
347 }
348
349 x_uncatch_errors ();
350 UNBLOCK_INPUT;
351
960d80b9 352 font_add_log ("xfont-list", build_string (pattern), list);
6c4aeab6
KH
353 return list;
354}
c2f5bfd6 355
6c4aeab6
KH
356static Lisp_Object
357xfont_list (frame, spec)
358 Lisp_Object frame, spec;
359{
360 FRAME_PTR f = XFRAME (frame);
361 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
960d80b9 362 Lisp_Object registry, list, val, extra;
6c4aeab6 363 int len;
6a705b23
KH
364 /* Large enough to contain the longest XLFD (255 bytes) in UTF-8. */
365 char name[512];
6c4aeab6
KH
366
367 extra = AREF (spec, FONT_EXTRA_INDEX);
6c4aeab6 368 if (CONSP (extra))
c2f5bfd6 369 {
6c4aeab6
KH
370 val = assq_no_quit (QCotf, extra);
371 if (! NILP (val))
f0c55750 372 return Qnil;
6c4aeab6
KH
373 val = assq_no_quit (QCscript, extra);
374 if (! NILP (val))
f0c55750
KH
375 return Qnil;
376 val = assq_no_quit (QClang, extra);
6c4aeab6 377 if (! NILP (val))
f0c55750 378 return Qnil;
c2f5bfd6 379 }
6c4aeab6 380
f0c55750 381 registry = AREF (spec, FONT_REGISTRY_INDEX);
6a705b23
KH
382 len = font_unparse_xlfd (spec, 0, name, 512);
383 if (len < 0 || (len = xfont_encode_coding_xlfd (name)) < 0)
f0c55750 384 return Qnil;
6a705b23 385 ASET (spec, FONT_REGISTRY_INDEX, registry);
f0c55750
KH
386 list = xfont_list_pattern (frame, display, name);
387 if (NILP (list) && NILP (registry))
c2f5bfd6 388 {
f0c55750
KH
389 /* Try iso10646-1 */
390 char *r = name + len - 9; /* 9 == strlen (iso8859-1) */
391
392 if (r - name + 10 < 256) /* 10 == strlen (iso10646-1) */
6c4aeab6 393 {
f0c55750
KH
394 strcpy (r, "iso10646-1");
395 list = xfont_list_pattern (frame, display, name);
396 }
397 }
398 if (NILP (list) && ! NILP (registry))
399 {
37470f4d 400 /* Try alternate registries. */
f0c55750 401 Lisp_Object alter;
6c4aeab6 402
f0c55750
KH
403 if ((alter = Fassoc (SYMBOL_NAME (registry),
404 Vface_alternative_font_registry_alist),
405 CONSP (alter)))
406 {
407 /* Pointer to REGISTRY-ENCODING field. */
408 char *r = name + len - SBYTES (SYMBOL_NAME (registry));
409
410 for (alter = XCDR (alter); CONSP (alter); alter = XCDR (alter))
411 if (STRINGP (XCAR (alter))
412 && ((r - name) + SBYTES (XCAR (alter))) < 256)
413 {
414 strcpy (r, (char *) SDATA (XCAR (alter)));
415 list = xfont_list_pattern (frame, display, name);
416 if (! NILP (list))
417 break;
418 }
6c4aeab6 419 }
c2f5bfd6 420 }
37470f4d
KH
421 if (NILP (list))
422 {
423 /* Try alias. */
424 val = assq_no_quit (QCname, AREF (spec, FONT_EXTRA_INDEX));
6a705b23
KH
425 if (CONSP (val) && STRINGP (XCDR (val)) && SBYTES (XCDR (val)) < 512)
426 {
427 bcopy (SDATA (XCDR (val)), name, SBYTES (XCDR (val)) + 1);
428 if (xfont_encode_coding_xlfd (name) < 0)
429 return Qnil;
430 list = xfont_list_pattern (frame, display, name);
431 }
37470f4d 432 }
c2f5bfd6 433
f0c55750 434 return list;
c2f5bfd6
KH
435}
436
6e34c9c1
KH
437static Lisp_Object
438xfont_match (frame, spec)
439 Lisp_Object frame, spec;
440{
441 FRAME_PTR f = XFRAME (frame);
442 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
443 Lisp_Object extra, val, entity;
6a705b23 444 char name[512];
6e34c9c1
KH
445 XFontStruct *xfont;
446 unsigned long value;
447
448 extra = AREF (spec, FONT_EXTRA_INDEX);
449 val = assq_no_quit (QCname, extra);
450 if (! CONSP (val) || ! STRINGP (XCDR (val)))
f0c55750 451 {
6a705b23 452 if (font_unparse_xlfd (spec, 0, name, 512) < 0)
f0c55750 453 return Qnil;
f0c55750 454 }
6a705b23
KH
455 else if (SBYTES (XCDR (val)) < 512)
456 bcopy (SDATA (XCDR (val)), name, SBYTES (XCDR (val)) + 1);
f0c55750 457 else
6a705b23
KH
458 return Qnil;
459 if (xfont_encode_coding_xlfd (name) < 0)
460 return Qnil;
6e34c9c1 461
9c6d1df5 462 BLOCK_INPUT;
6e34c9c1 463 entity = Qnil;
6e34c9c1
KH
464 xfont = XLoadQueryFont (display, name);
465 if (xfont)
466 {
467 if (XGetFontProperty (xfont, XA_FONT, &value))
468 {
469 int len;
6a705b23 470 char *s;
6e34c9c1 471
6a705b23
KH
472 s = (char *) XGetAtomName (display, (Atom) value);
473 len = strlen (s);
6e34c9c1
KH
474
475 /* If DXPC (a Differential X Protocol Compressor)
476 Ver.3.7 is running, XGetAtomName will return null
477 string. We must avoid such a name. */
478 if (len > 0)
479 {
f0c55750 480 entity = font_make_entity ();
6e34c9c1 481 ASET (entity, FONT_TYPE_INDEX, Qx);
6a705b23 482 xfont_decode_coding_xlfd (s, -1, name);
6e34c9c1
KH
483 if (font_parse_xlfd (name, entity) < 0)
484 entity = Qnil;
485 }
6a705b23 486 XFree (s);
6e34c9c1
KH
487 }
488 XFreeFont (display, xfont);
489 }
9c6d1df5 490 UNBLOCK_INPUT;
6e34c9c1 491
960d80b9 492 font_add_log ("xfont-match", spec, entity);
6e34c9c1
KH
493 return entity;
494}
495
c2f5bfd6
KH
496static Lisp_Object
497xfont_list_family (frame)
9df50a31 498 Lisp_Object frame;
c2f5bfd6
KH
499{
500 FRAME_PTR f = XFRAME (frame);
501 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
502 char **names;
503 int num_fonts, i;
504 Lisp_Object list;
505 char *last_family;
506 int last_len;
507
508 BLOCK_INPUT;
509 x_catch_errors (dpyinfo->display);
510 names = XListFonts (dpyinfo->display, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*",
511 0x8000, &num_fonts);
512 if (x_had_errors_p (dpyinfo->display))
513 {
514 /* This error is perhaps due to insufficient memory on X server.
515 Let's just ignore it. */
516 x_clear_errors (dpyinfo->display);
517 num_fonts = 0;
518 }
519
520 list = Qnil;
521 for (i = 0, last_len = 0; i < num_fonts; i++)
522 {
6a705b23 523 char *p0 = names[i], *p1, buf[512];
c2f5bfd6 524 Lisp_Object family;
6a705b23 525 int decoded_len;
c2f5bfd6
KH
526
527 p0++; /* skip the leading '-' */
528 while (*p0 && *p0 != '-') p0++; /* skip foundry */
529 if (! *p0)
530 continue;
531 p1 = ++p0;
532 while (*p1 && *p1 != '-') p1++; /* find the end of family */
533 if (! *p1 || p1 == p0)
534 continue;
535 if (last_len == p1 - p0
536 && bcmp (last_family, p0, last_len) == 0)
537 continue;
538 last_len = p1 - p0;
539 last_family = p0;
6a705b23
KH
540
541 decoded_len = xfont_decode_coding_xlfd (p0, last_len, buf);
542 family = font_intern_prop (p0, decoded_len, 1);
29428bb8 543 if (NILP (assq_no_quit (family, list)))
c2f5bfd6
KH
544 list = Fcons (family, list);
545 }
546
547 XFreeFontNames (names);
548 x_uncatch_errors ();
549 UNBLOCK_INPUT;
550
551 return list;
552}
553
f0c55750
KH
554extern Lisp_Object QCavgwidth;
555
556static Lisp_Object
c2f5bfd6
KH
557xfont_open (f, entity, pixel_size)
558 FRAME_PTR f;
559 Lisp_Object entity;
560 int pixel_size;
561{
562 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
563 Display *display = dpyinfo->display;
6a705b23 564 char name[512];
c2f5bfd6
KH
565 int len;
566 unsigned long value;
567 Lisp_Object registry;
568 struct charset *encoding, *repertory;
f0c55750 569 Lisp_Object font_object, fullname;
c2f5bfd6
KH
570 struct font *font;
571 XFontStruct *xfont;
f0c55750 572 int i;
c2f5bfd6
KH
573
574 /* At first, check if we know how to encode characters for this
575 font. */
576 registry = AREF (entity, FONT_REGISTRY_INDEX);
a9822ae8 577 if (font_registry_charsets (registry, &encoding, &repertory) < 0)
c8e0e16d
KH
578 {
579 font_add_log (" x:unknown registry", registry, Qnil);
580 return Qnil;
581 }
c2f5bfd6
KH
582
583 if (XINT (AREF (entity, FONT_SIZE_INDEX)) != 0)
584 pixel_size = XINT (AREF (entity, FONT_SIZE_INDEX));
f0c55750
KH
585 else if (pixel_size == 0)
586 {
587 if (FRAME_FONT (f))
588 pixel_size = FRAME_FONT (f)->pixel_size;
589 else
590 pixel_size = 14;
591 }
6a705b23
KH
592 len = font_unparse_xlfd (entity, pixel_size, name, 512);
593 if (len <= 0 || (len = xfont_encode_coding_xlfd (name)) < 0)
c8e0e16d
KH
594 {
595 font_add_log (" x:unparse failed", entity, Qnil);
596 return Qnil;
597 }
c2f5bfd6
KH
598
599 BLOCK_INPUT;
600 x_catch_errors (display);
601 xfont = XLoadQueryFont (display, name);
602 if (x_had_errors_p (display))
603 {
604 /* This error is perhaps due to insufficient memory on X server.
605 Let's just ignore it. */
606 x_clear_errors (display);
607 xfont = NULL;
608 }
2f73901f
KH
609 else if (! xfont)
610 {
611 /* Some version of X lists:
612 -misc-fixed-medium-r-normal--20-*-75-75-c-100-iso8859-1
613 -misc-fixed-medium-r-normal--20-*-100-100-c-100-iso8859-1
614 but can open only:
615 -misc-fixed-medium-r-normal--20-*-100-100-c-100-iso8859-1
616 and
617 -misc-fixed-medium-r-normal--20-*-*-*-c-100-iso8859-1
618 So, we try again with wildcards in RESX and RESY. */
619 Lisp_Object temp;
620
621 temp = Fcopy_font_spec (entity);
622 ASET (temp, FONT_DPI_INDEX, Qnil);
6a705b23
KH
623 len = font_unparse_xlfd (temp, pixel_size, name, 512);
624 if (len <= 0 || (len = xfont_encode_coding_xlfd (name)) < 0)
2f73901f
KH
625 {
626 font_add_log (" x:unparse failed", temp, Qnil);
627 return Qnil;
628 }
629 xfont = XLoadQueryFont (display, name);
630 if (x_had_errors_p (display))
631 {
632 /* This error is perhaps due to insufficient memory on X server.
633 Let's just ignore it. */
634 x_clear_errors (display);
635 xfont = NULL;
636 }
637 }
f0c55750
KH
638 fullname = Qnil;
639 /* Try to get the full name of FONT. */
640 if (xfont && XGetFontProperty (xfont, XA_FONT, &value))
641 {
642 char *p0, *p;
643 int dashes = 0;
644
645 p0 = p = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);;
646 /* Count the number of dashes in the "full name".
647 If it is too few, this isn't really the font's full name,
648 so don't use it.
649 In X11R4, the fonts did not come with their canonical names
650 stored in them. */
651 while (*p)
652 {
653 if (*p == '-')
654 dashes++;
655 p++;
656 }
657
658 if (dashes >= 13)
6a705b23
KH
659 {
660 len = xfont_decode_coding_xlfd (p0, -1, name);
661 fullname = Fdowncase (make_string (name, len));
662 }
f0c55750
KH
663 XFree (p0);
664 }
c2f5bfd6
KH
665 x_uncatch_errors ();
666 UNBLOCK_INPUT;
667
668 if (! xfont)
c8e0e16d
KH
669 {
670 font_add_log (" x:open failed", build_string (name), Qnil);
671 return Qnil;
672 }
f0c55750 673
947eecfb
KH
674 font_object = font_make_object (VECSIZE (struct xfont_info),
675 entity, pixel_size);
f0c55750
KH
676 ASET (font_object, FONT_TYPE_INDEX, Qx);
677 if (STRINGP (fullname))
6a705b23
KH
678 {
679 font_parse_xlfd ((char *) SDATA (fullname), font_object);
680 ASET (font_object, FONT_NAME_INDEX, fullname);
681 }
f0c55750 682 else
6a705b23
KH
683 {
684 char buf[512];
685
686 len = xfont_decode_coding_xlfd (name, -1, buf);
687 ASET (font_object, FONT_NAME_INDEX, make_string (buf, len));
688 }
f0c55750
KH
689 ASET (font_object, FONT_FULLNAME_INDEX, fullname);
690 ASET (font_object, FONT_FILE_INDEX, Qnil);
691 ASET (font_object, FONT_FORMAT_INDEX, Qx);
692 font = XFONT_OBJECT (font_object);
693 ((struct xfont_info *) font)->xfont = xfont;
694 ((struct xfont_info *) font)->display = FRAME_X_DISPLAY (f);
c2f5bfd6
KH
695 font->pixel_size = pixel_size;
696 font->driver = &xfont_driver;
c2f5bfd6 697 font->encoding_charset = encoding->id;
1886668d 698 font->repertory_charset = repertory ? repertory->id : -1;
c2f5bfd6
KH
699 font->ascent = xfont->ascent;
700 font->descent = xfont->descent;
f0c55750
KH
701 font->height = font->ascent + font->descent;
702 font->min_width = xfont->min_bounds.width;
c2f5bfd6
KH
703 if (xfont->min_bounds.width == xfont->max_bounds.width)
704 {
705 /* Fixed width font. */
f0c55750 706 font->average_width = font->space_width = xfont->min_bounds.width;
c2f5bfd6
KH
707 }
708 else
709 {
c2f5bfd6 710 XCharStruct *pcm;
f0c55750
KH
711 XChar2b char2b;
712 Lisp_Object val;
c2f5bfd6
KH
713
714 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
715 pcm = xfont_get_pcm (xfont, &char2b);
716 if (pcm)
f0c55750 717 font->space_width = pcm->width;
c2f5bfd6 718 else
f0c55750
KH
719 font->space_width = 0;
720
721 val = Ffont_get (font_object, QCavgwidth);
722 if (INTEGERP (val))
723 font->average_width = XINT (val);
724 if (font->average_width < 0)
725 font->average_width = - font->average_width;
726 if (font->average_width == 0
727 && encoding->ascii_compatible_p)
c2f5bfd6 728 {
f0c55750 729 int width = font->space_width, n = pcm != NULL;
c2f5bfd6 730
f0c55750
KH
731 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
732 if ((pcm = xfont_get_pcm (xfont, &char2b)) != NULL)
733 width += pcm->width, n++;
4f64a164
KH
734 if (n > 0)
735 font->average_width = width / n;
c2f5bfd6 736 }
4f64a164
KH
737 if (font->average_width == 0)
738 /* No easy way other than this to get a reasonable
739 average_width. */
740 font->average_width
741 = (xfont->min_bounds.width + xfont->max_bounds.width) / 2;
c2f5bfd6 742 }
c2f5bfd6 743
f0c55750
KH
744 BLOCK_INPUT;
745 font->underline_thickness
746 = (XGetFontProperty (xfont, XA_UNDERLINE_THICKNESS, &value)
747 ? (long) value : 0);
748 font->underline_position
749 = (XGetFontProperty (xfont, XA_UNDERLINE_POSITION, &value)
750 ? (long) value : -1);
751 font->baseline_offset
c2f5bfd6
KH
752 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
753 ? (long) value : 0);
f0c55750 754 font->relative_compose
c2f5bfd6
KH
755 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
756 ? (long) value : 0);
f0c55750 757 font->default_ascent
c2f5bfd6
KH
758 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
759 ? (long) value : 0);
c2f5bfd6
KH
760 UNBLOCK_INPUT;
761
f0c55750
KH
762 if (NILP (fullname))
763 fullname = AREF (font_object, FONT_NAME_INDEX);
634c4da0
KH
764 font->vertical_centering
765 = (STRINGP (Vvertical_centering_font_regexp)
766 && (fast_string_match_ignore_case
767 (Vvertical_centering_font_regexp, fullname) >= 0));
c2f5bfd6 768
f0c55750 769 return font_object;
c2f5bfd6
KH
770}
771
772static void
773xfont_close (f, font)
774 FRAME_PTR f;
775 struct font *font;
776{
777 BLOCK_INPUT;
f0c55750 778 XFreeFont (FRAME_X_DISPLAY (f), ((struct xfont_info *) font)->xfont);
c2f5bfd6 779 UNBLOCK_INPUT;
c2f5bfd6
KH
780}
781
782static int
783xfont_prepare_face (f, face)
784 FRAME_PTR f;
785 struct face *face;
786{
787 BLOCK_INPUT;
f0c55750
KH
788 XSetFont (FRAME_X_DISPLAY (f), face->gc,
789 ((struct xfont_info *) face->font)->xfont->fid);
c2f5bfd6
KH
790 UNBLOCK_INPUT;
791
792 return 0;
793}
794
c2f5bfd6
KH
795static int
796xfont_has_char (entity, c)
797 Lisp_Object entity;
798 int c;
799{
800 Lisp_Object registry = AREF (entity, FONT_REGISTRY_INDEX);
801 struct charset *repertory;
802
a9822ae8 803 if (font_registry_charsets (registry, NULL, &repertory) < 0)
c2f5bfd6
KH
804 return -1;
805 if (! repertory)
806 return -1;
807 return (ENCODE_CHAR (repertory, c) != CHARSET_INVALID_CODE (repertory));
808}
809
810static unsigned
811xfont_encode_char (font, c)
812 struct font *font;
813 int c;
814{
f0c55750 815 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
c2f5bfd6
KH
816 struct charset *charset;
817 unsigned code;
818 XChar2b char2b;
819
820 charset = CHARSET_FROM_ID (font->encoding_charset);
821 code = ENCODE_CHAR (charset, c);
822 if (code == CHARSET_INVALID_CODE (charset))
21138cff 823 return FONT_INVALID_CODE;
1886668d 824 if (font->repertory_charset >= 0)
c2f5bfd6 825 {
1886668d 826 charset = CHARSET_FROM_ID (font->repertory_charset);
c2f5bfd6 827 return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset)
21138cff 828 ? code : FONT_INVALID_CODE);
c2f5bfd6 829 }
88649c62
KH
830 char2b.byte1 = code >> 8;
831 char2b.byte2 = code & 0xFF;
f0c55750 832 return (xfont_get_pcm (xfont, &char2b) ? code : FONT_INVALID_CODE);
c2f5bfd6
KH
833}
834
835static int
836xfont_text_extents (font, code, nglyphs, metrics)
837 struct font *font;
838 unsigned *code;
839 int nglyphs;
840 struct font_metrics *metrics;
841{
f0c55750 842 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
c2f5bfd6 843 int width = 0;
41fa3e2c 844 int i, first, x;
c2f5bfd6
KH
845
846 if (metrics)
847 bzero (metrics, sizeof (struct font_metrics));
41fa3e2c 848 for (i = 0, x = 0, first = 1; i < nglyphs; i++)
c2f5bfd6
KH
849 {
850 XChar2b char2b;
851 static XCharStruct *pcm;
852
853 if (code[i] >= 0x10000)
854 continue;
855 char2b.byte1 = code[i] >> 8, char2b.byte2 = code[i] & 0xFF;
f0c55750 856 pcm = xfont_get_pcm (xfont, &char2b);
c2f5bfd6
KH
857 if (! pcm)
858 continue;
41fa3e2c
KH
859 if (first)
860 {
861 if (metrics)
862 {
863 metrics->lbearing = pcm->lbearing;
864 metrics->rbearing = pcm->rbearing;
865 metrics->ascent = pcm->ascent;
866 metrics->descent = pcm->descent;
867 }
868 first = 0;
869 }
870 else
871 {
872 if (metrics)
873 {
874 if (metrics->lbearing > width + pcm->lbearing)
875 metrics->lbearing = width + pcm->lbearing;
876 if (metrics->rbearing < width + pcm->rbearing)
877 metrics->rbearing = width + pcm->rbearing;
878 if (metrics->ascent < pcm->ascent)
879 metrics->ascent = pcm->ascent;
880 if (metrics->descent < pcm->descent)
881 metrics->descent = pcm->descent;
882 }
883 }
c2f5bfd6
KH
884 width += pcm->width;
885 }
886 if (metrics)
887 metrics->width = width;
888 return width;
889}
890
891static int
892xfont_draw (s, from, to, x, y, with_background)
893 struct glyph_string *s;
894 int from, to, x, y, with_background;
895{
f0c55750 896 XFontStruct *xfont = ((struct xfont_info *) s->font)->xfont;
c2f5bfd6 897 int len = to - from;
6e34c9c1 898 GC gc = s->gc;
298fd5b1 899 int i;
6e34c9c1 900
f0c55750 901 if (s->gc != s->face->gc)
6e34c9c1 902 {
d45fefc7 903 BLOCK_INPUT;
f0c55750 904 XSetFont (s->display, gc, xfont->fid);
d45fefc7 905 UNBLOCK_INPUT;
6e34c9c1 906 }
c2f5bfd6
KH
907
908 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
909 {
910 char *str;
c2f5bfd6
KH
911 USE_SAFE_ALLOCA;
912
913 SAFE_ALLOCA (str, char *, len);
914 for (i = 0; i < len ; i++)
915 str[i] = XCHAR2B_BYTE2 (s->char2b + from + i);
d45fefc7 916 BLOCK_INPUT;
c2f5bfd6 917 if (with_background > 0)
298fd5b1
KH
918 {
919 if (s->padding_p)
920 for (i = 0; i < len; i++)
921 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
922 gc, x + i, y, str + i, 1);
923 else
924 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
925 gc, x, y, str, len);
926 }
c2f5bfd6 927 else
298fd5b1
KH
928 {
929 if (s->padding_p)
930 for (i = 0; i < len; i++)
931 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
932 gc, x + i, y, str + i, 1);
933 else
934 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
935 gc, x, y, str, len);
936 }
d45fefc7 937 UNBLOCK_INPUT;
c2f5bfd6
KH
938 SAFE_FREE ();
939 return s->nchars;
940 }
941
d45fefc7 942 BLOCK_INPUT;
c2f5bfd6 943 if (with_background > 0)
298fd5b1
KH
944 {
945 if (s->padding_p)
946 for (i = 0; i < len; i++)
947 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
948 gc, x + i, y, s->char2b + from + i, 1);
949 else
950 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
951 gc, x, y, s->char2b + from, len);
952 }
c2f5bfd6 953 else
298fd5b1
KH
954 {
955 if (s->padding_p)
956 for (i = 0; i < len; i++)
957 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
958 gc, x + i, y, s->char2b + from + i, 1);
959 else
960 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
961 gc, x, y, s->char2b + from, len);
962 }
d45fefc7 963 UNBLOCK_INPUT;
c2f5bfd6
KH
964
965 return len;
966}
967
f0c55750
KH
968static int
969xfont_check (f, font)
970 FRAME_PTR f;
971 struct font *font;
972{
973 struct xfont_info *xfont = (struct xfont_info *) font;
974
975 return (FRAME_X_DISPLAY (f) == xfont->display ? 0 : -1);
976}
977
c2f5bfd6
KH
978\f
979void
980syms_of_xfont ()
981{
c2f5bfd6
KH
982 xfont_driver.type = Qx;
983 register_font_driver (&xfont_driver, NULL);
984}
885b7d09
MB
985
986/* arch-tag: 23c5f366-a5ee-44b7-a3b7-90d6da7fd749
987 (do not change this comment) */