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