* alloc.c: Do not define struct catchtag.
[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>
d7306fe6 25#include <setjmp.h>
c2f5bfd6
KH
26#include <X11/Xlib.h>
27
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"
f0c55750 37#include "ccl.h"
c2f5bfd6
KH
38
39\f
40/* X core font driver. */
41
f0c55750
KH
42struct xfont_info
43{
44 struct font font;
45 Display *display;
46 XFontStruct *xfont;
47};
48
c2f5bfd6
KH
49/* Prototypes of support functions. */
50extern void x_clear_errors P_ ((Display *));
51
c2f5bfd6 52static XCharStruct *xfont_get_pcm P_ ((XFontStruct *, XChar2b *));
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
feb2737b 122static Lisp_Object xfont_get_cache P_ ((FRAME_PTR));
c2f5bfd6 123static Lisp_Object xfont_list P_ ((Lisp_Object, Lisp_Object));
6e34c9c1 124static Lisp_Object xfont_match P_ ((Lisp_Object, Lisp_Object));
c2f5bfd6 125static Lisp_Object xfont_list_family P_ ((Lisp_Object));
f0c55750 126static Lisp_Object xfont_open P_ ((FRAME_PTR, Lisp_Object, int));
c2f5bfd6
KH
127static void xfont_close P_ ((FRAME_PTR, struct font *));
128static int xfont_prepare_face P_ ((FRAME_PTR, struct face *));
c2f5bfd6
KH
129static int xfont_has_char P_ ((Lisp_Object, int));
130static unsigned xfont_encode_char P_ ((struct font *, int));
131static int xfont_text_extents P_ ((struct font *, unsigned *, int,
132 struct font_metrics *));
133static int xfont_draw P_ ((struct glyph_string *, int, int, int, int, int));
f0c55750 134static int xfont_check P_ ((FRAME_PTR, struct font *));
c2f5bfd6
KH
135
136struct font_driver xfont_driver =
137 {
575abfb7 138 0, /* Qx */
f0c55750 139 0, /* case insensitive */
c2f5bfd6 140 xfont_get_cache,
c2f5bfd6 141 xfont_list,
6e34c9c1 142 xfont_match,
c2f5bfd6
KH
143 xfont_list_family,
144 NULL,
145 xfont_open,
146 xfont_close,
147 xfont_prepare_face,
f0c55750 148 NULL,
c2f5bfd6
KH
149 xfont_has_char,
150 xfont_encode_char,
151 xfont_text_extents,
f0c55750
KH
152 xfont_draw,
153 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
154 xfont_check
c2f5bfd6
KH
155 };
156
157extern Lisp_Object QCname;
158
159static Lisp_Object
feb2737b
KH
160xfont_get_cache (f)
161 FRAME_PTR f;
c2f5bfd6 162{
feb2737b 163 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
c2f5bfd6
KH
164
165 return (dpyinfo->name_list_element);
166}
167
c2f5bfd6
KH
168extern Lisp_Object Vface_alternative_font_registry_alist;
169
f0c55750
KH
170static int
171compare_font_names (const void *name1, const void *name2)
172{
7740d2c7
KH
173 return xstrcasecmp (*(const unsigned char **) name1,
174 *(const unsigned char **) name2);
f0c55750
KH
175}
176
6a705b23
KH
177/* Decode XLFD as iso-8859-1 into OUTPUT, and return the byte length
178 of the decoding result. LEN is the byte length of XLFD, or -1 if
179 XLFD is NULL terminated. The caller must assure that OUTPUT is at
180 least twice (plus 1) as large as XLFD. */
181
182static int
183xfont_decode_coding_xlfd (char *xlfd, int len, char *output)
184{
185 char *p0 = xlfd, *p1 = output;
186 int c;
8510724d 187
6a705b23
KH
188 while (*p0)
189 {
190 c = *(unsigned char *) p0++;
191 p1 += CHAR_STRING (c, p1);
192 if (--len == 0)
193 break;
194 }
195 *p1 = 0;
196 return (p1 - output);
197}
198
199/* Encode XLFD from UTF-8 to iso-8859-1 destructively, and return the
200 resulting byte length. If XLFD contains unencodable character,
201 return -1. */
202
203static int
204xfont_encode_coding_xlfd (char *xlfd)
205{
206 const unsigned char *p0 = (unsigned char *) xlfd;
207 unsigned char *p1 = (unsigned char *) xlfd;
208 int len = 0;
8510724d 209
6a705b23
KH
210 while (*p0)
211 {
212 int c = STRING_CHAR_ADVANCE (p0);
213
214 if (c >= 0x100)
215 return -1;
216 *p1++ = c;
217 len++;
218 }
219 *p1 = 0;
220 return len;
221}
222
5a189ffa
KH
223/* Check if CHARS (cons or vector) is supported by XFONT whose
224 encoding charset is ENCODING (XFONT is NULL) or by a font whose
225 registry corresponds to ENCODING and REPERTORY.
226 Return 1 if supported, return 0 otherwise. */
227
228static int
229xfont_chars_supported (Lisp_Object chars, XFontStruct *xfont,
230 struct charset *encoding, struct charset *repertory)
231{
232 struct charset *charset = repertory ? repertory : encoding;
233
234 if (CONSP (chars))
235 {
236 for (; CONSP (chars); chars = XCDR (chars))
237 {
238 int c = XINT (XCAR (chars));
239 unsigned code = ENCODE_CHAR (charset, c);
240 XChar2b char2b;
241
242 if (code == CHARSET_INVALID_CODE (charset))
243 break;
244 if (! xfont)
245 continue;
246 if (code >= 0x10000)
247 break;
248 char2b.byte1 = code >> 8;
249 char2b.byte2 = code & 0xFF;
250 if (! xfont_get_pcm (xfont, &char2b))
251 break;
252 }
253 return (NILP (chars));
254 }
255 else if (VECTORP (chars))
256 {
257 int i;
258
259 for (i = ASIZE (chars) - 1; i >= 0; i--)
260 {
261 int c = XINT (AREF (chars, i));
262 unsigned code = ENCODE_CHAR (charset, c);
263 XChar2b char2b;
264
265 if (code == CHARSET_INVALID_CODE (charset))
266 continue;
267 if (! xfont)
268 break;
269 if (code >= 0x10000)
270 continue;
271 char2b.byte1 = code >> 8;
272 char2b.byte2 = code & 0xFF;
273 if (xfont_get_pcm (xfont, &char2b))
274 break;
275 }
276 return (i >= 0);
277 }
278 return 0;
279}
280
281/* A hash table recoding which font supports which scritps. Each key
282 is a vector of characteristic font propertis FOUNDRY to WIDTH and
283 ADDSTYLE, and each value is a list of script symbols.
284
285 We assume that fonts that have the same value in the above
286 properties supports the same set of characters on all displays. */
287
288static Lisp_Object xfont_scripts_cache;
289
290/* Re-usable vector to store characteristic font properites. */
291static Lisp_Object xfont_scratch_props;
292
293extern Lisp_Object Qlatin;
294
295/* Return a list of scripts supported by the font of FONTNAME whose
296 characteristic properties are in PROPS and whose encoding charset
297 is ENCODING. A caller must call BLOCK_INPUT in advance. */
92f19280
KH
298
299static Lisp_Object
5a189ffa
KH
300xfont_supported_scripts (Display *display, char *fontname, Lisp_Object props,
301 struct charset *encoding)
302{
303 Lisp_Object scripts;
304
305 /* Two special cases to avoid opening rather big fonts. */
306 if (EQ (AREF (props, 2), Qja))
307 return Fcons (intern ("kana"), Fcons (intern ("han"), Qnil));
308 if (EQ (AREF (props, 2), Qko))
309 return Fcons (intern ("hangul"), Qnil);
310 scripts = Fgethash (props, xfont_scripts_cache, Qt);
311 if (EQ (scripts, Qt))
312 {
313 XFontStruct *xfont;
314 Lisp_Object val;
315
316 scripts = Qnil;
317 xfont = XLoadQueryFont (display, fontname);
318 if (xfont)
319 {
320 if (xfont->per_char)
321 {
322 for (val = Vscript_representative_chars; CONSP (val);
323 val = XCDR (val))
324 if (CONSP (XCAR (val)) && SYMBOLP (XCAR (XCAR (val))))
325 {
326 Lisp_Object script = XCAR (XCAR (val));
327 Lisp_Object chars = XCDR (XCAR (val));
328
329 if (xfont_chars_supported (chars, xfont, encoding, NULL))
330 scripts = Fcons (script, scripts);
331 }
332 }
333 XFreeFont (display, xfont);
334 }
335 if (EQ (AREF (props, 3), Qiso10646_1)
336 && NILP (Fmemq (Qlatin, scripts)))
337 scripts = Fcons (Qlatin, scripts);
338 Fputhash (Fcopy_sequence (props), scripts, xfont_scripts_cache);
339 }
340 return scripts;
341}
342
343extern Lisp_Object Vscalable_fonts_allowed;
344
345static Lisp_Object
346xfont_list_pattern (Display *display, char *pattern,
347 Lisp_Object registry, Lisp_Object script)
c2f5bfd6 348{
6c4aeab6 349 Lisp_Object list = Qnil;
5a189ffa
KH
350 Lisp_Object chars = Qnil;
351 struct charset *encoding, *repertory = NULL;
6c4aeab6
KH
352 int i, limit, num_fonts;
353 char **names;
6a705b23
KH
354 /* Large enough to decode the longest XLFD (255 bytes). */
355 char buf[512];
c2f5bfd6 356
5a189ffa
KH
357 if (! NILP (registry)
358 && font_registry_charsets (registry, &encoding, &repertory) < 0)
359 /* Unknown REGISTRY, not supported. */
360 return Qnil;
361 if (! NILP (script))
362 {
363 chars = assq_no_quit (script, Vscript_representative_chars);
364 if (NILP (chars))
365 /* We can't tell whether or not a font supports SCRIPT. */
366 return Qnil;
367 chars = XCDR (chars);
368 if (repertory)
369 {
370 if (! xfont_chars_supported (chars, NULL, encoding, repertory))
371 return Qnil;
372 script = Qnil;
373 }
374 }
5a189ffa 375
c2f5bfd6 376 BLOCK_INPUT;
6c4aeab6 377 x_catch_errors (display);
c2f5bfd6 378
6c4aeab6 379 for (limit = 512; ; limit *= 2)
c2f5bfd6 380 {
6c4aeab6
KH
381 names = XListFonts (display, pattern, limit, &num_fonts);
382 if (x_had_errors_p (display))
c2f5bfd6
KH
383 {
384 /* This error is perhaps due to insufficient memory on X
385 server. Let's just ignore it. */
6c4aeab6
KH
386 x_clear_errors (display);
387 num_fonts = 0;
388 break;
c2f5bfd6 389 }
6c4aeab6
KH
390 if (num_fonts < limit)
391 break;
392 XFreeFontNames (names);
393 }
394
f0c55750 395 if (num_fonts > 0)
6c4aeab6 396 {
f0c55750 397 char **indices = alloca (sizeof (char *) * num_fonts);
46306a17 398 Lisp_Object *props = XVECTOR (xfont_scratch_props)->contents;
5a189ffa 399 Lisp_Object scripts = Qnil;
6c4aeab6 400
46306a17
SM
401 for (i = 0; i < ASIZE (xfont_scratch_props); i++)
402 props[i] = Qnil;
f0c55750
KH
403 for (i = 0; i < num_fonts; i++)
404 indices[i] = names[i];
405 qsort (indices, num_fonts, sizeof (char *), compare_font_names);
6c4aeab6 406
f0c55750 407 for (i = 0; i < num_fonts; i++)
c2f5bfd6 408 {
f0c55750 409 Lisp_Object entity;
6c4aeab6 410
05131107 411 if (i > 0 && xstrcasecmp (indices[i - 1], indices[i]) == 0)
6c4aeab6 412 continue;
f0c55750 413 entity = font_make_entity ();
6a705b23 414 xfont_decode_coding_xlfd (indices[i], -1, buf);
4fa58085
KH
415 if (font_parse_xlfd (buf, entity) < 0)
416 continue;
5a189ffa
KH
417 ASET (entity, FONT_TYPE_INDEX, Qx);
418 /* Avoid auto-scaled fonts. */
4fa58085
KH
419 if (INTEGERP (AREF (entity, FONT_DPI_INDEX))
420 && INTEGERP (AREF (entity, FONT_AVGWIDTH_INDEX))
421 && XINT (AREF (entity, FONT_DPI_INDEX)) != 0
5a189ffa
KH
422 && XINT (AREF (entity, FONT_AVGWIDTH_INDEX)) == 0)
423 continue;
424 /* Avoid not-allowed scalable fonts. */
425 if (NILP (Vscalable_fonts_allowed))
c2f5bfd6 426 {
4fa58085
KH
427 int size = 0;
428
429 if (INTEGERP (AREF (entity, FONT_SIZE_INDEX)))
430 size = XINT (AREF (entity, FONT_SIZE_INDEX));
431 else if (FLOATP (AREF (entity, FONT_SIZE_INDEX)))
432 size = XFLOAT_DATA (AREF (entity, FONT_SIZE_INDEX));
433 if (size == 0)
6c4aeab6 434 continue;
5a189ffa
KH
435 }
436 else if (CONSP (Vscalable_fonts_allowed))
437 {
438 Lisp_Object tail, elt;
439
440 for (tail = Vscalable_fonts_allowed; CONSP (tail);
441 tail = XCDR (tail))
f0c55750 442 {
5a189ffa
KH
443 elt = XCAR (tail);
444 if (STRINGP (elt)
445 && fast_c_string_match_ignore_case (elt, indices[i]) >= 0)
446 break;
f0c55750 447 }
5a189ffa
KH
448 if (! CONSP (tail))
449 continue;
c2f5bfd6 450 }
f0c55750 451
4fa58085
KH
452 /* Avoid fonts of invalid registry. */
453 if (NILP (AREF (entity, FONT_REGISTRY_INDEX)))
454 continue;
455
5a189ffa
KH
456 /* Update encoding and repertory if necessary. */
457 if (! EQ (registry, AREF (entity, FONT_REGISTRY_INDEX)))
458 {
459 registry = AREF (entity, FONT_REGISTRY_INDEX);
460 if (font_registry_charsets (registry, &encoding, &repertory) < 0)
461 encoding = NULL;
462 }
463 if (! encoding)
464 /* Unknown REGISTRY, not supported. */
465 continue;
466 if (repertory)
467 {
468 if (NILP (script)
469 || xfont_chars_supported (chars, NULL, encoding, repertory))
470 list = Fcons (entity, list);
471 continue;
472 }
473 if (memcmp (props, &(AREF (entity, FONT_FOUNDRY_INDEX)),
474 sizeof (Lisp_Object) * 7)
475 || ! EQ (AREF (entity, FONT_SPACING_INDEX), props[7]))
476 {
477 memcpy (props, &(AREF (entity, FONT_FOUNDRY_INDEX)),
478 sizeof (Lisp_Object) * 7);
479 props[7] = AREF (entity, FONT_SPACING_INDEX);
480 scripts = xfont_supported_scripts (display, indices[i],
481 xfont_scratch_props, encoding);
482 }
483 if (NILP (script)
484 || ! NILP (Fmemq (script, scripts)))
f0c55750 485 list = Fcons (entity, list);
c2f5bfd6 486 }
019e13ef 487 XFreeFontNames (names);
c2f5bfd6
KH
488 }
489
490 x_uncatch_errors ();
491 UNBLOCK_INPUT;
492
678dca3d 493 FONT_ADD_LOG ("xfont-list", build_string (pattern), list);
6c4aeab6
KH
494 return list;
495}
c2f5bfd6 496
6c4aeab6
KH
497static Lisp_Object
498xfont_list (frame, spec)
499 Lisp_Object frame, spec;
500{
501 FRAME_PTR f = XFRAME (frame);
502 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
5a189ffa 503 Lisp_Object registry, list, val, extra, script;
6c4aeab6 504 int len;
6a705b23
KH
505 /* Large enough to contain the longest XLFD (255 bytes) in UTF-8. */
506 char name[512];
8510724d 507
6c4aeab6 508 extra = AREF (spec, FONT_EXTRA_INDEX);
6c4aeab6 509 if (CONSP (extra))
c2f5bfd6 510 {
6c4aeab6 511 val = assq_no_quit (QCotf, extra);
6c4aeab6 512 if (! NILP (val))
f0c55750
KH
513 return Qnil;
514 val = assq_no_quit (QClang, extra);
6c4aeab6 515 if (! NILP (val))
f0c55750 516 return Qnil;
c2f5bfd6 517 }
398dbf26 518
f0c55750 519 registry = AREF (spec, FONT_REGISTRY_INDEX);
6a705b23
KH
520 len = font_unparse_xlfd (spec, 0, name, 512);
521 if (len < 0 || (len = xfont_encode_coding_xlfd (name)) < 0)
f0c55750 522 return Qnil;
5a189ffa
KH
523
524 val = assq_no_quit (QCscript, extra);
525 script = CDR (val);
526 list = xfont_list_pattern (display, name, registry, script);
f0c55750 527 if (NILP (list) && NILP (registry))
c2f5bfd6 528 {
f0c55750
KH
529 /* Try iso10646-1 */
530 char *r = name + len - 9; /* 9 == strlen (iso8859-1) */
531
532 if (r - name + 10 < 256) /* 10 == strlen (iso10646-1) */
6c4aeab6 533 {
f0c55750 534 strcpy (r, "iso10646-1");
5a189ffa 535 list = xfont_list_pattern (display, name, Qiso10646_1, script);
f0c55750
KH
536 }
537 }
538 if (NILP (list) && ! NILP (registry))
539 {
37470f4d 540 /* Try alternate registries. */
f0c55750 541 Lisp_Object alter;
6c4aeab6 542
f0c55750
KH
543 if ((alter = Fassoc (SYMBOL_NAME (registry),
544 Vface_alternative_font_registry_alist),
545 CONSP (alter)))
546 {
547 /* Pointer to REGISTRY-ENCODING field. */
548 char *r = name + len - SBYTES (SYMBOL_NAME (registry));
549
550 for (alter = XCDR (alter); CONSP (alter); alter = XCDR (alter))
551 if (STRINGP (XCAR (alter))
552 && ((r - name) + SBYTES (XCAR (alter))) < 256)
553 {
554 strcpy (r, (char *) SDATA (XCAR (alter)));
5a189ffa 555 list = xfont_list_pattern (display, name, registry, script);
f0c55750
KH
556 if (! NILP (list))
557 break;
558 }
6c4aeab6 559 }
c2f5bfd6 560 }
37470f4d
KH
561 if (NILP (list))
562 {
563 /* Try alias. */
564 val = assq_no_quit (QCname, AREF (spec, FONT_EXTRA_INDEX));
6a705b23
KH
565 if (CONSP (val) && STRINGP (XCDR (val)) && SBYTES (XCDR (val)) < 512)
566 {
567 bcopy (SDATA (XCDR (val)), name, SBYTES (XCDR (val)) + 1);
568 if (xfont_encode_coding_xlfd (name) < 0)
569 return Qnil;
5a189ffa 570 list = xfont_list_pattern (display, name, registry, script);
6a705b23 571 }
37470f4d 572 }
398dbf26 573
f0c55750 574 return list;
c2f5bfd6
KH
575}
576
6e34c9c1
KH
577static Lisp_Object
578xfont_match (frame, spec)
579 Lisp_Object frame, spec;
580{
581 FRAME_PTR f = XFRAME (frame);
582 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
583 Lisp_Object extra, val, entity;
6a705b23 584 char name[512];
6e34c9c1
KH
585 XFontStruct *xfont;
586 unsigned long value;
587
588 extra = AREF (spec, FONT_EXTRA_INDEX);
589 val = assq_no_quit (QCname, extra);
590 if (! CONSP (val) || ! STRINGP (XCDR (val)))
f0c55750 591 {
6a705b23 592 if (font_unparse_xlfd (spec, 0, name, 512) < 0)
f0c55750 593 return Qnil;
f0c55750 594 }
6a705b23
KH
595 else if (SBYTES (XCDR (val)) < 512)
596 bcopy (SDATA (XCDR (val)), name, SBYTES (XCDR (val)) + 1);
f0c55750 597 else
6a705b23
KH
598 return Qnil;
599 if (xfont_encode_coding_xlfd (name) < 0)
600 return Qnil;
6e34c9c1 601
9c6d1df5 602 BLOCK_INPUT;
6e34c9c1 603 entity = Qnil;
6e34c9c1
KH
604 xfont = XLoadQueryFont (display, name);
605 if (xfont)
606 {
607 if (XGetFontProperty (xfont, XA_FONT, &value))
608 {
609 int len;
6a705b23 610 char *s;
6e34c9c1 611
6a705b23
KH
612 s = (char *) XGetAtomName (display, (Atom) value);
613 len = strlen (s);
6e34c9c1
KH
614
615 /* If DXPC (a Differential X Protocol Compressor)
616 Ver.3.7 is running, XGetAtomName will return null
617 string. We must avoid such a name. */
618 if (len > 0)
619 {
f0c55750 620 entity = font_make_entity ();
6e34c9c1 621 ASET (entity, FONT_TYPE_INDEX, Qx);
6a705b23 622 xfont_decode_coding_xlfd (s, -1, name);
6e34c9c1
KH
623 if (font_parse_xlfd (name, entity) < 0)
624 entity = Qnil;
625 }
6a705b23 626 XFree (s);
6e34c9c1
KH
627 }
628 XFreeFont (display, xfont);
629 }
9c6d1df5 630 UNBLOCK_INPUT;
6e34c9c1 631
678dca3d 632 FONT_ADD_LOG ("xfont-match", spec, entity);
6e34c9c1
KH
633 return entity;
634}
635
c2f5bfd6
KH
636static Lisp_Object
637xfont_list_family (frame)
9df50a31 638 Lisp_Object frame;
c2f5bfd6
KH
639{
640 FRAME_PTR f = XFRAME (frame);
641 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
642 char **names;
643 int num_fonts, i;
644 Lisp_Object list;
645 char *last_family;
646 int last_len;
647
648 BLOCK_INPUT;
649 x_catch_errors (dpyinfo->display);
650 names = XListFonts (dpyinfo->display, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*",
651 0x8000, &num_fonts);
652 if (x_had_errors_p (dpyinfo->display))
653 {
654 /* This error is perhaps due to insufficient memory on X server.
655 Let's just ignore it. */
656 x_clear_errors (dpyinfo->display);
657 num_fonts = 0;
658 }
659
660 list = Qnil;
661 for (i = 0, last_len = 0; i < num_fonts; i++)
662 {
6a705b23 663 char *p0 = names[i], *p1, buf[512];
c2f5bfd6 664 Lisp_Object family;
6a705b23 665 int decoded_len;
c2f5bfd6
KH
666
667 p0++; /* skip the leading '-' */
668 while (*p0 && *p0 != '-') p0++; /* skip foundry */
669 if (! *p0)
670 continue;
671 p1 = ++p0;
672 while (*p1 && *p1 != '-') p1++; /* find the end of family */
673 if (! *p1 || p1 == p0)
674 continue;
675 if (last_len == p1 - p0
676 && bcmp (last_family, p0, last_len) == 0)
677 continue;
678 last_len = p1 - p0;
679 last_family = p0;
6a705b23
KH
680
681 decoded_len = xfont_decode_coding_xlfd (p0, last_len, buf);
682 family = font_intern_prop (p0, decoded_len, 1);
29428bb8 683 if (NILP (assq_no_quit (family, list)))
c2f5bfd6
KH
684 list = Fcons (family, list);
685 }
686
687 XFreeFontNames (names);
688 x_uncatch_errors ();
689 UNBLOCK_INPUT;
690
691 return list;
692}
693
f0c55750
KH
694extern Lisp_Object QCavgwidth;
695
696static Lisp_Object
c2f5bfd6
KH
697xfont_open (f, entity, pixel_size)
698 FRAME_PTR f;
699 Lisp_Object entity;
700 int pixel_size;
701{
702 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
703 Display *display = dpyinfo->display;
6a705b23 704 char name[512];
c2f5bfd6
KH
705 int len;
706 unsigned long value;
707 Lisp_Object registry;
708 struct charset *encoding, *repertory;
f0c55750 709 Lisp_Object font_object, fullname;
c2f5bfd6
KH
710 struct font *font;
711 XFontStruct *xfont;
712
713 /* At first, check if we know how to encode characters for this
714 font. */
715 registry = AREF (entity, FONT_REGISTRY_INDEX);
a9822ae8 716 if (font_registry_charsets (registry, &encoding, &repertory) < 0)
c8e0e16d 717 {
678dca3d 718 FONT_ADD_LOG (" x:unknown registry", registry, Qnil);
c8e0e16d
KH
719 return Qnil;
720 }
c2f5bfd6
KH
721
722 if (XINT (AREF (entity, FONT_SIZE_INDEX)) != 0)
723 pixel_size = XINT (AREF (entity, FONT_SIZE_INDEX));
f0c55750
KH
724 else if (pixel_size == 0)
725 {
726 if (FRAME_FONT (f))
727 pixel_size = FRAME_FONT (f)->pixel_size;
728 else
729 pixel_size = 14;
730 }
6a705b23
KH
731 len = font_unparse_xlfd (entity, pixel_size, name, 512);
732 if (len <= 0 || (len = xfont_encode_coding_xlfd (name)) < 0)
c8e0e16d 733 {
678dca3d 734 FONT_ADD_LOG (" x:unparse failed", entity, Qnil);
c8e0e16d
KH
735 return Qnil;
736 }
c2f5bfd6
KH
737
738 BLOCK_INPUT;
739 x_catch_errors (display);
740 xfont = XLoadQueryFont (display, name);
741 if (x_had_errors_p (display))
742 {
743 /* This error is perhaps due to insufficient memory on X server.
744 Let's just ignore it. */
745 x_clear_errors (display);
746 xfont = NULL;
747 }
2f73901f
KH
748 else if (! xfont)
749 {
750 /* Some version of X lists:
751 -misc-fixed-medium-r-normal--20-*-75-75-c-100-iso8859-1
752 -misc-fixed-medium-r-normal--20-*-100-100-c-100-iso8859-1
753 but can open only:
754 -misc-fixed-medium-r-normal--20-*-100-100-c-100-iso8859-1
755 and
756 -misc-fixed-medium-r-normal--20-*-*-*-c-100-iso8859-1
757 So, we try again with wildcards in RESX and RESY. */
758 Lisp_Object temp;
759
760 temp = Fcopy_font_spec (entity);
761 ASET (temp, FONT_DPI_INDEX, Qnil);
6a705b23
KH
762 len = font_unparse_xlfd (temp, pixel_size, name, 512);
763 if (len <= 0 || (len = xfont_encode_coding_xlfd (name)) < 0)
2f73901f 764 {
678dca3d 765 FONT_ADD_LOG (" x:unparse failed", temp, Qnil);
2f73901f
KH
766 return Qnil;
767 }
768 xfont = XLoadQueryFont (display, name);
769 if (x_had_errors_p (display))
770 {
771 /* This error is perhaps due to insufficient memory on X server.
772 Let's just ignore it. */
773 x_clear_errors (display);
774 xfont = NULL;
775 }
776 }
f0c55750
KH
777 fullname = Qnil;
778 /* Try to get the full name of FONT. */
779 if (xfont && XGetFontProperty (xfont, XA_FONT, &value))
780 {
781 char *p0, *p;
782 int dashes = 0;
783
8510724d 784 p0 = p = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
f0c55750
KH
785 /* Count the number of dashes in the "full name".
786 If it is too few, this isn't really the font's full name,
787 so don't use it.
788 In X11R4, the fonts did not come with their canonical names
789 stored in them. */
790 while (*p)
791 {
792 if (*p == '-')
793 dashes++;
794 p++;
795 }
796
797 if (dashes >= 13)
6a705b23
KH
798 {
799 len = xfont_decode_coding_xlfd (p0, -1, name);
800 fullname = Fdowncase (make_string (name, len));
801 }
f0c55750
KH
802 XFree (p0);
803 }
c2f5bfd6
KH
804 x_uncatch_errors ();
805 UNBLOCK_INPUT;
806
807 if (! xfont)
c8e0e16d 808 {
678dca3d 809 FONT_ADD_LOG (" x:open failed", build_string (name), Qnil);
c8e0e16d
KH
810 return Qnil;
811 }
f0c55750 812
947eecfb
KH
813 font_object = font_make_object (VECSIZE (struct xfont_info),
814 entity, pixel_size);
f0c55750
KH
815 ASET (font_object, FONT_TYPE_INDEX, Qx);
816 if (STRINGP (fullname))
6a705b23
KH
817 {
818 font_parse_xlfd ((char *) SDATA (fullname), font_object);
819 ASET (font_object, FONT_NAME_INDEX, fullname);
820 }
f0c55750 821 else
6a705b23
KH
822 {
823 char buf[512];
824
825 len = xfont_decode_coding_xlfd (name, -1, buf);
826 ASET (font_object, FONT_NAME_INDEX, make_string (buf, len));
827 }
f0c55750
KH
828 ASET (font_object, FONT_FULLNAME_INDEX, fullname);
829 ASET (font_object, FONT_FILE_INDEX, Qnil);
830 ASET (font_object, FONT_FORMAT_INDEX, Qx);
831 font = XFONT_OBJECT (font_object);
832 ((struct xfont_info *) font)->xfont = xfont;
833 ((struct xfont_info *) font)->display = FRAME_X_DISPLAY (f);
c2f5bfd6
KH
834 font->pixel_size = pixel_size;
835 font->driver = &xfont_driver;
c2f5bfd6 836 font->encoding_charset = encoding->id;
1886668d 837 font->repertory_charset = repertory ? repertory->id : -1;
c2f5bfd6
KH
838 font->ascent = xfont->ascent;
839 font->descent = xfont->descent;
f0c55750
KH
840 font->height = font->ascent + font->descent;
841 font->min_width = xfont->min_bounds.width;
c2f5bfd6
KH
842 if (xfont->min_bounds.width == xfont->max_bounds.width)
843 {
844 /* Fixed width font. */
f0c55750 845 font->average_width = font->space_width = xfont->min_bounds.width;
c2f5bfd6
KH
846 }
847 else
848 {
c2f5bfd6 849 XCharStruct *pcm;
f0c55750
KH
850 XChar2b char2b;
851 Lisp_Object val;
c2f5bfd6
KH
852
853 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
854 pcm = xfont_get_pcm (xfont, &char2b);
855 if (pcm)
f0c55750 856 font->space_width = pcm->width;
c2f5bfd6 857 else
f0c55750
KH
858 font->space_width = 0;
859
860 val = Ffont_get (font_object, QCavgwidth);
861 if (INTEGERP (val))
862 font->average_width = XINT (val);
863 if (font->average_width < 0)
864 font->average_width = - font->average_width;
865 if (font->average_width == 0
866 && encoding->ascii_compatible_p)
c2f5bfd6 867 {
f0c55750 868 int width = font->space_width, n = pcm != NULL;
c2f5bfd6 869
f0c55750
KH
870 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
871 if ((pcm = xfont_get_pcm (xfont, &char2b)) != NULL)
872 width += pcm->width, n++;
4f64a164
KH
873 if (n > 0)
874 font->average_width = width / n;
c2f5bfd6 875 }
4f64a164
KH
876 if (font->average_width == 0)
877 /* No easy way other than this to get a reasonable
878 average_width. */
879 font->average_width
880 = (xfont->min_bounds.width + xfont->max_bounds.width) / 2;
c2f5bfd6 881 }
c2f5bfd6 882
f0c55750
KH
883 BLOCK_INPUT;
884 font->underline_thickness
885 = (XGetFontProperty (xfont, XA_UNDERLINE_THICKNESS, &value)
886 ? (long) value : 0);
887 font->underline_position
888 = (XGetFontProperty (xfont, XA_UNDERLINE_POSITION, &value)
889 ? (long) value : -1);
890 font->baseline_offset
c2f5bfd6
KH
891 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
892 ? (long) value : 0);
f0c55750 893 font->relative_compose
c2f5bfd6
KH
894 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
895 ? (long) value : 0);
f0c55750 896 font->default_ascent
c2f5bfd6
KH
897 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
898 ? (long) value : 0);
c2f5bfd6
KH
899 UNBLOCK_INPUT;
900
f0c55750
KH
901 if (NILP (fullname))
902 fullname = AREF (font_object, FONT_NAME_INDEX);
634c4da0
KH
903 font->vertical_centering
904 = (STRINGP (Vvertical_centering_font_regexp)
905 && (fast_string_match_ignore_case
906 (Vvertical_centering_font_regexp, fullname) >= 0));
c2f5bfd6 907
f0c55750 908 return font_object;
c2f5bfd6
KH
909}
910
911static void
912xfont_close (f, font)
913 FRAME_PTR f;
914 struct font *font;
915{
916 BLOCK_INPUT;
f0c55750 917 XFreeFont (FRAME_X_DISPLAY (f), ((struct xfont_info *) font)->xfont);
c2f5bfd6 918 UNBLOCK_INPUT;
c2f5bfd6
KH
919}
920
921static int
922xfont_prepare_face (f, face)
923 FRAME_PTR f;
924 struct face *face;
925{
926 BLOCK_INPUT;
f0c55750
KH
927 XSetFont (FRAME_X_DISPLAY (f), face->gc,
928 ((struct xfont_info *) face->font)->xfont->fid);
c2f5bfd6
KH
929 UNBLOCK_INPUT;
930
931 return 0;
932}
933
c2f5bfd6 934static int
bd0af90d
KH
935xfont_has_char (font, c)
936 Lisp_Object font;
c2f5bfd6
KH
937 int c;
938{
bd0af90d 939 Lisp_Object registry = AREF (font, FONT_REGISTRY_INDEX);
d156542d 940 struct charset *encoding;
bd0af90d 941 struct charset *repertory = NULL;
c2f5bfd6 942
bd0af90d
KH
943 if (EQ (registry, Qiso10646_1))
944 {
5a189ffa 945 encoding = CHARSET_FROM_ID (charset_unicode);
bd0af90d
KH
946 /* We use a font of `ja' and `ko' adstyle only for a character
947 in JISX0208 and KSC5601 charsets respectively. */
948 if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
949 && charset_jisx0208 >= 0)
5a189ffa 950 repertory = CHARSET_FROM_ID (charset_jisx0208);
bd0af90d
KH
951 else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
952 && charset_ksc5601 >= 0)
5a189ffa 953 repertory = CHARSET_FROM_ID (charset_ksc5601);
bd0af90d
KH
954 }
955 else if (font_registry_charsets (registry, &encoding, &repertory) < 0)
956 /* Unknown REGISTRY, not usable. */
957 return 0;
d156542d
KH
958 if (ASCII_CHAR_P (c) && encoding->ascii_compatible_p)
959 return 1;
c2f5bfd6
KH
960 if (! repertory)
961 return -1;
962 return (ENCODE_CHAR (repertory, c) != CHARSET_INVALID_CODE (repertory));
963}
964
965static unsigned
966xfont_encode_char (font, c)
967 struct font *font;
968 int c;
969{
f0c55750 970 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
c2f5bfd6
KH
971 struct charset *charset;
972 unsigned code;
973 XChar2b char2b;
974
975 charset = CHARSET_FROM_ID (font->encoding_charset);
976 code = ENCODE_CHAR (charset, c);
977 if (code == CHARSET_INVALID_CODE (charset))
21138cff 978 return FONT_INVALID_CODE;
1886668d 979 if (font->repertory_charset >= 0)
c2f5bfd6 980 {
1886668d 981 charset = CHARSET_FROM_ID (font->repertory_charset);
c2f5bfd6 982 return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset)
21138cff 983 ? code : FONT_INVALID_CODE);
c2f5bfd6 984 }
88649c62
KH
985 char2b.byte1 = code >> 8;
986 char2b.byte2 = code & 0xFF;
f0c55750 987 return (xfont_get_pcm (xfont, &char2b) ? code : FONT_INVALID_CODE);
c2f5bfd6
KH
988}
989
990static int
991xfont_text_extents (font, code, nglyphs, metrics)
992 struct font *font;
993 unsigned *code;
994 int nglyphs;
995 struct font_metrics *metrics;
996{
f0c55750 997 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
c2f5bfd6 998 int width = 0;
41fa3e2c 999 int i, first, x;
c2f5bfd6
KH
1000
1001 if (metrics)
1002 bzero (metrics, sizeof (struct font_metrics));
41fa3e2c 1003 for (i = 0, x = 0, first = 1; i < nglyphs; i++)
c2f5bfd6
KH
1004 {
1005 XChar2b char2b;
1006 static XCharStruct *pcm;
1007
1008 if (code[i] >= 0x10000)
1009 continue;
1010 char2b.byte1 = code[i] >> 8, char2b.byte2 = code[i] & 0xFF;
f0c55750 1011 pcm = xfont_get_pcm (xfont, &char2b);
c2f5bfd6
KH
1012 if (! pcm)
1013 continue;
41fa3e2c
KH
1014 if (first)
1015 {
1016 if (metrics)
1017 {
1018 metrics->lbearing = pcm->lbearing;
1019 metrics->rbearing = pcm->rbearing;
1020 metrics->ascent = pcm->ascent;
1021 metrics->descent = pcm->descent;
1022 }
1023 first = 0;
1024 }
1025 else
1026 {
1027 if (metrics)
1028 {
1029 if (metrics->lbearing > width + pcm->lbearing)
1030 metrics->lbearing = width + pcm->lbearing;
1031 if (metrics->rbearing < width + pcm->rbearing)
1032 metrics->rbearing = width + pcm->rbearing;
1033 if (metrics->ascent < pcm->ascent)
1034 metrics->ascent = pcm->ascent;
1035 if (metrics->descent < pcm->descent)
1036 metrics->descent = pcm->descent;
1037 }
1038 }
c2f5bfd6
KH
1039 width += pcm->width;
1040 }
1041 if (metrics)
1042 metrics->width = width;
1043 return width;
1044}
1045
1046static int
1047xfont_draw (s, from, to, x, y, with_background)
1048 struct glyph_string *s;
1049 int from, to, x, y, with_background;
1050{
f0c55750 1051 XFontStruct *xfont = ((struct xfont_info *) s->font)->xfont;
c2f5bfd6 1052 int len = to - from;
6e34c9c1 1053 GC gc = s->gc;
298fd5b1 1054 int i;
6e34c9c1 1055
f0c55750 1056 if (s->gc != s->face->gc)
6e34c9c1 1057 {
d45fefc7 1058 BLOCK_INPUT;
f0c55750 1059 XSetFont (s->display, gc, xfont->fid);
d45fefc7 1060 UNBLOCK_INPUT;
6e34c9c1 1061 }
c2f5bfd6
KH
1062
1063 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
1064 {
1065 char *str;
c2f5bfd6
KH
1066 USE_SAFE_ALLOCA;
1067
1068 SAFE_ALLOCA (str, char *, len);
1069 for (i = 0; i < len ; i++)
1070 str[i] = XCHAR2B_BYTE2 (s->char2b + from + i);
d45fefc7 1071 BLOCK_INPUT;
c2f5bfd6 1072 if (with_background > 0)
298fd5b1
KH
1073 {
1074 if (s->padding_p)
1075 for (i = 0; i < len; i++)
1076 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
1077 gc, x + i, y, str + i, 1);
1078 else
1079 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
1080 gc, x, y, str, len);
1081 }
c2f5bfd6 1082 else
298fd5b1
KH
1083 {
1084 if (s->padding_p)
1085 for (i = 0; i < len; i++)
1086 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
1087 gc, x + i, y, str + i, 1);
1088 else
1089 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
1090 gc, x, y, str, len);
1091 }
d45fefc7 1092 UNBLOCK_INPUT;
c2f5bfd6
KH
1093 SAFE_FREE ();
1094 return s->nchars;
1095 }
1096
d45fefc7 1097 BLOCK_INPUT;
c2f5bfd6 1098 if (with_background > 0)
298fd5b1
KH
1099 {
1100 if (s->padding_p)
1101 for (i = 0; i < len; i++)
1102 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
1103 gc, x + i, y, s->char2b + from + i, 1);
1104 else
1105 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
1106 gc, x, y, s->char2b + from, len);
1107 }
c2f5bfd6 1108 else
298fd5b1
KH
1109 {
1110 if (s->padding_p)
1111 for (i = 0; i < len; i++)
1112 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
1113 gc, x + i, y, s->char2b + from + i, 1);
1114 else
1115 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
1116 gc, x, y, s->char2b + from, len);
1117 }
d45fefc7 1118 UNBLOCK_INPUT;
c2f5bfd6
KH
1119
1120 return len;
1121}
1122
f0c55750
KH
1123static int
1124xfont_check (f, font)
1125 FRAME_PTR f;
1126 struct font *font;
1127{
1128 struct xfont_info *xfont = (struct xfont_info *) font;
1129
1130 return (FRAME_X_DISPLAY (f) == xfont->display ? 0 : -1);
1131}
1132
c2f5bfd6
KH
1133\f
1134void
1135syms_of_xfont ()
1136{
5a189ffa 1137 staticpro (&xfont_scripts_cache);
46306a17
SM
1138 { /* Here we rely on the fact that syms_of_xfont (via syms_of_font)
1139 is called fairly late, when QCtest and Qequal are known to be set. */
1140 Lisp_Object args[2];
1141 args[0] = QCtest;
1142 args[1] = Qequal;
1143 xfont_scripts_cache = Fmake_hash_table (2, args);
1144 }
5a189ffa 1145 staticpro (&xfont_scratch_props);
46306a17 1146 xfont_scratch_props = Fmake_vector (make_number (8), Qnil);
c2f5bfd6
KH
1147 xfont_driver.type = Qx;
1148 register_font_driver (&xfont_driver, NULL);
1149}
885b7d09
MB
1150
1151/* arch-tag: 23c5f366-a5ee-44b7-a3b7-90d6da7fd749
1152 (do not change this comment) */