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