Merge from emacs-24; up to 2012-05-05T02:50:20Z!monnier@iro.umontreal.ca
[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. */
c2f5bfd6 49
f57e2426 50static XCharStruct *xfont_get_pcm (XFontStruct *, XChar2b *);
c2f5bfd6
KH
51
52/* Get metrics of character CHAR2B in XFONT. Value is null if CHAR2B
53 is not contained in the font. */
54
55static XCharStruct *
971de7fb 56xfont_get_pcm (XFontStruct *xfont, XChar2b *char2b)
c2f5bfd6
KH
57{
58 /* The result metric information. */
59 XCharStruct *pcm = NULL;
60
4e6a86c6 61 eassert (xfont && char2b);
c2f5bfd6
KH
62
63 if (xfont->per_char != NULL)
64 {
65 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
66 {
67 /* min_char_or_byte2 specifies the linear character index
68 corresponding to the first element of the per_char array,
69 max_char_or_byte2 is the index of the last character. A
70 character with non-zero CHAR2B->byte1 is not in the font.
71 A character with byte2 less than min_char_or_byte2 or
72 greater max_char_or_byte2 is not in the font. */
73 if (char2b->byte1 == 0
74 && char2b->byte2 >= xfont->min_char_or_byte2
75 && char2b->byte2 <= xfont->max_char_or_byte2)
76 pcm = xfont->per_char + char2b->byte2 - xfont->min_char_or_byte2;
77 }
78 else
79 {
80 /* If either min_byte1 or max_byte1 are nonzero, both
81 min_char_or_byte2 and max_char_or_byte2 are less than
82 256, and the 2-byte character index values corresponding
83 to the per_char array element N (counting from 0) are:
84
85 byte1 = N/D + min_byte1
86 byte2 = N\D + min_char_or_byte2
87
88 where:
89
90 D = max_char_or_byte2 - min_char_or_byte2 + 1
91 / = integer division
92 \ = integer modulus */
93 if (char2b->byte1 >= xfont->min_byte1
94 && char2b->byte1 <= xfont->max_byte1
95 && char2b->byte2 >= xfont->min_char_or_byte2
96 && char2b->byte2 <= xfont->max_char_or_byte2)
97 pcm = (xfont->per_char
98 + ((xfont->max_char_or_byte2 - xfont->min_char_or_byte2 + 1)
99 * (char2b->byte1 - xfont->min_byte1))
100 + (char2b->byte2 - xfont->min_char_or_byte2));
101 }
102 }
103 else
104 {
105 /* If the per_char pointer is null, all glyphs between the first
106 and last character indexes inclusive have the same
107 information, as given by both min_bounds and max_bounds. */
108 if (char2b->byte2 >= xfont->min_char_or_byte2
109 && char2b->byte2 <= xfont->max_char_or_byte2)
110 pcm = &xfont->max_bounds;
111 }
112
113 return ((pcm == NULL
114 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
115 ? NULL : pcm);
116}
117
f57e2426
J
118static Lisp_Object xfont_get_cache (FRAME_PTR);
119static Lisp_Object xfont_list (Lisp_Object, Lisp_Object);
120static Lisp_Object xfont_match (Lisp_Object, Lisp_Object);
121static Lisp_Object xfont_list_family (Lisp_Object);
122static Lisp_Object xfont_open (FRAME_PTR, Lisp_Object, int);
123static void xfont_close (FRAME_PTR, struct font *);
124static int xfont_prepare_face (FRAME_PTR, struct face *);
125static int xfont_has_char (Lisp_Object, int);
126static unsigned xfont_encode_char (struct font *, int);
127static int xfont_text_extents (struct font *, unsigned *, int,
128 struct font_metrics *);
129static int xfont_draw (struct glyph_string *, int, int, int, int, int);
130static int xfont_check (FRAME_PTR, struct font *);
c2f5bfd6
KH
131
132struct font_driver xfont_driver =
133 {
bfe3e0a2 134 LISP_INITIALLY_ZERO, /* Qx */
f0c55750 135 0, /* case insensitive */
c2f5bfd6 136 xfont_get_cache,
c2f5bfd6 137 xfont_list,
6e34c9c1 138 xfont_match,
c2f5bfd6
KH
139 xfont_list_family,
140 NULL,
141 xfont_open,
142 xfont_close,
143 xfont_prepare_face,
f0c55750 144 NULL,
c2f5bfd6
KH
145 xfont_has_char,
146 xfont_encode_char,
147 xfont_text_extents,
f0c55750
KH
148 xfont_draw,
149 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
637fa988
JD
150 xfont_check,
151 NULL, /* get_variation_glyphs */
152 NULL, /* filter_properties */
c2f5bfd6
KH
153 };
154
c2f5bfd6 155static Lisp_Object
971de7fb 156xfont_get_cache (FRAME_PTR f)
c2f5bfd6 157{
feb2737b 158 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
c2f5bfd6
KH
159
160 return (dpyinfo->name_list_element);
161}
162
f0c55750
KH
163static int
164compare_font_names (const void *name1, const void *name2)
165{
fd573f31
PE
166 char *const *n1 = name1;
167 char *const *n2 = name2;
168 return xstrcasecmp (*n1, *n2);
f0c55750
KH
169}
170
6a705b23
KH
171/* Decode XLFD as iso-8859-1 into OUTPUT, and return the byte length
172 of the decoding result. LEN is the byte length of XLFD, or -1 if
173 XLFD is NULL terminated. The caller must assure that OUTPUT is at
174 least twice (plus 1) as large as XLFD. */
175
984e7f30 176static ptrdiff_t
6a705b23
KH
177xfont_decode_coding_xlfd (char *xlfd, int len, char *output)
178{
179 char *p0 = xlfd, *p1 = output;
180 int c;
8510724d 181
6a705b23
KH
182 while (*p0)
183 {
184 c = *(unsigned char *) p0++;
efe0234f 185 p1 += CHAR_STRING (c, (unsigned char *) p1);
6a705b23
KH
186 if (--len == 0)
187 break;
188 }
189 *p1 = 0;
190 return (p1 - output);
191}
192
193/* Encode XLFD from UTF-8 to iso-8859-1 destructively, and return the
194 resulting byte length. If XLFD contains unencodable character,
195 return -1. */
196
197static int
198xfont_encode_coding_xlfd (char *xlfd)
199{
200 const unsigned char *p0 = (unsigned char *) xlfd;
201 unsigned char *p1 = (unsigned char *) xlfd;
202 int len = 0;
8510724d 203
6a705b23
KH
204 while (*p0)
205 {
206 int c = STRING_CHAR_ADVANCE (p0);
207
208 if (c >= 0x100)
209 return -1;
210 *p1++ = c;
211 len++;
212 }
213 *p1 = 0;
214 return len;
215}
216
5a189ffa
KH
217/* Check if CHARS (cons or vector) is supported by XFONT whose
218 encoding charset is ENCODING (XFONT is NULL) or by a font whose
219 registry corresponds to ENCODING and REPERTORY.
220 Return 1 if supported, return 0 otherwise. */
221
222static int
223xfont_chars_supported (Lisp_Object chars, XFontStruct *xfont,
224 struct charset *encoding, struct charset *repertory)
225{
226 struct charset *charset = repertory ? repertory : encoding;
227
228 if (CONSP (chars))
229 {
230 for (; CONSP (chars); chars = XCDR (chars))
231 {
232 int c = XINT (XCAR (chars));
233 unsigned code = ENCODE_CHAR (charset, c);
234 XChar2b char2b;
235
236 if (code == CHARSET_INVALID_CODE (charset))
237 break;
238 if (! xfont)
239 continue;
240 if (code >= 0x10000)
241 break;
242 char2b.byte1 = code >> 8;
243 char2b.byte2 = code & 0xFF;
244 if (! xfont_get_pcm (xfont, &char2b))
245 break;
246 }
247 return (NILP (chars));
248 }
249 else if (VECTORP (chars))
250 {
d311d28c 251 ptrdiff_t i;
5a189ffa
KH
252
253 for (i = ASIZE (chars) - 1; i >= 0; i--)
254 {
255 int c = XINT (AREF (chars, i));
256 unsigned code = ENCODE_CHAR (charset, c);
257 XChar2b char2b;
258
259 if (code == CHARSET_INVALID_CODE (charset))
260 continue;
261 if (! xfont)
262 break;
263 if (code >= 0x10000)
264 continue;
265 char2b.byte1 = code >> 8;
266 char2b.byte2 = code & 0xFF;
267 if (xfont_get_pcm (xfont, &char2b))
268 break;
269 }
270 return (i >= 0);
271 }
272 return 0;
273}
274
0b381c7e
JB
275/* A hash table recoding which font supports which scripts. Each key
276 is a vector of characteristic font properties FOUNDRY to WIDTH and
5a189ffa
KH
277 ADDSTYLE, and each value is a list of script symbols.
278
279 We assume that fonts that have the same value in the above
280 properties supports the same set of characters on all displays. */
281
282static Lisp_Object xfont_scripts_cache;
283
0b381c7e 284/* Re-usable vector to store characteristic font properties. */
5a189ffa
KH
285static Lisp_Object xfont_scratch_props;
286
5a189ffa
KH
287/* Return a list of scripts supported by the font of FONTNAME whose
288 characteristic properties are in PROPS and whose encoding charset
289 is ENCODING. A caller must call BLOCK_INPUT in advance. */
92f19280
KH
290
291static Lisp_Object
5a189ffa
KH
292xfont_supported_scripts (Display *display, char *fontname, Lisp_Object props,
293 struct charset *encoding)
294{
295 Lisp_Object scripts;
296
297 /* Two special cases to avoid opening rather big fonts. */
298 if (EQ (AREF (props, 2), Qja))
299 return Fcons (intern ("kana"), Fcons (intern ("han"), Qnil));
300 if (EQ (AREF (props, 2), Qko))
301 return Fcons (intern ("hangul"), Qnil);
302 scripts = Fgethash (props, xfont_scripts_cache, Qt);
303 if (EQ (scripts, Qt))
304 {
305 XFontStruct *xfont;
306 Lisp_Object val;
307
308 scripts = Qnil;
309 xfont = XLoadQueryFont (display, fontname);
310 if (xfont)
311 {
312 if (xfont->per_char)
313 {
314 for (val = Vscript_representative_chars; CONSP (val);
315 val = XCDR (val))
316 if (CONSP (XCAR (val)) && SYMBOLP (XCAR (XCAR (val))))
317 {
318 Lisp_Object script = XCAR (XCAR (val));
319 Lisp_Object chars = XCDR (XCAR (val));
320
321 if (xfont_chars_supported (chars, xfont, encoding, NULL))
322 scripts = Fcons (script, scripts);
323 }
324 }
325 XFreeFont (display, xfont);
326 }
327 if (EQ (AREF (props, 3), Qiso10646_1)
328 && NILP (Fmemq (Qlatin, scripts)))
329 scripts = Fcons (Qlatin, scripts);
330 Fputhash (Fcopy_sequence (props), scripts, xfont_scripts_cache);
331 }
332 return scripts;
333}
334
5a189ffa 335static Lisp_Object
675e2c69 336xfont_list_pattern (Display *display, const char *pattern,
5a189ffa 337 Lisp_Object registry, Lisp_Object script)
c2f5bfd6 338{
6c4aeab6 339 Lisp_Object list = Qnil;
5a189ffa
KH
340 Lisp_Object chars = Qnil;
341 struct charset *encoding, *repertory = NULL;
6c4aeab6
KH
342 int i, limit, num_fonts;
343 char **names;
6a705b23
KH
344 /* Large enough to decode the longest XLFD (255 bytes). */
345 char buf[512];
c2f5bfd6 346
5a189ffa
KH
347 if (! NILP (registry)
348 && font_registry_charsets (registry, &encoding, &repertory) < 0)
349 /* Unknown REGISTRY, not supported. */
350 return Qnil;
351 if (! NILP (script))
352 {
353 chars = assq_no_quit (script, Vscript_representative_chars);
354 if (NILP (chars))
355 /* We can't tell whether or not a font supports SCRIPT. */
356 return Qnil;
357 chars = XCDR (chars);
358 if (repertory)
359 {
360 if (! xfont_chars_supported (chars, NULL, encoding, repertory))
361 return Qnil;
362 script = Qnil;
363 }
364 }
51b59d79 365
c2f5bfd6 366 BLOCK_INPUT;
6c4aeab6 367 x_catch_errors (display);
c2f5bfd6 368
6c4aeab6 369 for (limit = 512; ; limit *= 2)
c2f5bfd6 370 {
6c4aeab6
KH
371 names = XListFonts (display, pattern, limit, &num_fonts);
372 if (x_had_errors_p (display))
c2f5bfd6
KH
373 {
374 /* This error is perhaps due to insufficient memory on X
375 server. Let's just ignore it. */
6c4aeab6
KH
376 x_clear_errors (display);
377 num_fonts = 0;
378 break;
c2f5bfd6 379 }
6c4aeab6
KH
380 if (num_fonts < limit)
381 break;
382 XFreeFontNames (names);
383 }
384
f0c55750 385 if (num_fonts > 0)
6c4aeab6 386 {
f0c55750 387 char **indices = alloca (sizeof (char *) * num_fonts);
46306a17 388 Lisp_Object *props = XVECTOR (xfont_scratch_props)->contents;
5a189ffa 389 Lisp_Object scripts = Qnil;
6c4aeab6 390
46306a17 391 for (i = 0; i < ASIZE (xfont_scratch_props); i++)
086ca913 392 ASET (xfont_scratch_props, i, Qnil);
f0c55750
KH
393 for (i = 0; i < num_fonts; i++)
394 indices[i] = names[i];
395 qsort (indices, num_fonts, sizeof (char *), compare_font_names);
6c4aeab6 396
f0c55750 397 for (i = 0; i < num_fonts; i++)
c2f5bfd6 398 {
984e7f30 399 ptrdiff_t len;
f0c55750 400 Lisp_Object entity;
6c4aeab6 401
05131107 402 if (i > 0 && xstrcasecmp (indices[i - 1], indices[i]) == 0)
6c4aeab6 403 continue;
f0c55750 404 entity = font_make_entity ();
984e7f30
DA
405 len = xfont_decode_coding_xlfd (indices[i], -1, buf);
406 if (font_parse_xlfd (buf, len, entity) < 0)
4fa58085 407 continue;
5a189ffa
KH
408 ASET (entity, FONT_TYPE_INDEX, Qx);
409 /* Avoid auto-scaled fonts. */
4fa58085
KH
410 if (INTEGERP (AREF (entity, FONT_DPI_INDEX))
411 && INTEGERP (AREF (entity, FONT_AVGWIDTH_INDEX))
412 && XINT (AREF (entity, FONT_DPI_INDEX)) != 0
5a189ffa
KH
413 && XINT (AREF (entity, FONT_AVGWIDTH_INDEX)) == 0)
414 continue;
415 /* Avoid not-allowed scalable fonts. */
416 if (NILP (Vscalable_fonts_allowed))
c2f5bfd6 417 {
4fa58085
KH
418 int size = 0;
419
420 if (INTEGERP (AREF (entity, FONT_SIZE_INDEX)))
421 size = XINT (AREF (entity, FONT_SIZE_INDEX));
422 else if (FLOATP (AREF (entity, FONT_SIZE_INDEX)))
423 size = XFLOAT_DATA (AREF (entity, FONT_SIZE_INDEX));
424 if (size == 0)
6c4aeab6 425 continue;
5a189ffa
KH
426 }
427 else if (CONSP (Vscalable_fonts_allowed))
428 {
429 Lisp_Object tail, elt;
430
431 for (tail = Vscalable_fonts_allowed; CONSP (tail);
432 tail = XCDR (tail))
f0c55750 433 {
5a189ffa
KH
434 elt = XCAR (tail);
435 if (STRINGP (elt)
d923b542
DA
436 && fast_c_string_match_ignore_case (elt, indices[i],
437 len) >= 0)
5a189ffa 438 break;
f0c55750 439 }
5a189ffa
KH
440 if (! CONSP (tail))
441 continue;
c2f5bfd6 442 }
f0c55750 443
4fa58085
KH
444 /* Avoid fonts of invalid registry. */
445 if (NILP (AREF (entity, FONT_REGISTRY_INDEX)))
446 continue;
447
5a189ffa
KH
448 /* Update encoding and repertory if necessary. */
449 if (! EQ (registry, AREF (entity, FONT_REGISTRY_INDEX)))
450 {
451 registry = AREF (entity, FONT_REGISTRY_INDEX);
452 if (font_registry_charsets (registry, &encoding, &repertory) < 0)
453 encoding = NULL;
454 }
455 if (! encoding)
456 /* Unknown REGISTRY, not supported. */
457 continue;
458 if (repertory)
459 {
460 if (NILP (script)
461 || xfont_chars_supported (chars, NULL, encoding, repertory))
462 list = Fcons (entity, list);
463 continue;
464 }
4939150c 465 if (memcmp (props, aref_addr (entity, FONT_FOUNDRY_INDEX),
663e2b3f 466 word_size * 7)
5a189ffa
KH
467 || ! EQ (AREF (entity, FONT_SPACING_INDEX), props[7]))
468 {
086ca913
DA
469 vcopy (xfont_scratch_props, 0,
470 aref_addr (entity, FONT_FOUNDRY_INDEX), 7);
471 ASET (xfont_scratch_props, 7, AREF (entity, FONT_SPACING_INDEX));
5a189ffa
KH
472 scripts = xfont_supported_scripts (display, indices[i],
473 xfont_scratch_props, encoding);
474 }
475 if (NILP (script)
476 || ! NILP (Fmemq (script, scripts)))
f0c55750 477 list = Fcons (entity, list);
c2f5bfd6 478 }
019e13ef 479 XFreeFontNames (names);
c2f5bfd6
KH
480 }
481
482 x_uncatch_errors ();
483 UNBLOCK_INPUT;
484
678dca3d 485 FONT_ADD_LOG ("xfont-list", build_string (pattern), list);
6c4aeab6
KH
486 return list;
487}
c2f5bfd6 488
6c4aeab6 489static Lisp_Object
971de7fb 490xfont_list (Lisp_Object frame, Lisp_Object spec)
6c4aeab6
KH
491{
492 FRAME_PTR f = XFRAME (frame);
493 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
5a189ffa 494 Lisp_Object registry, list, val, extra, script;
6c4aeab6 495 int len;
6a705b23
KH
496 /* Large enough to contain the longest XLFD (255 bytes) in UTF-8. */
497 char name[512];
8510724d 498
6c4aeab6 499 extra = AREF (spec, FONT_EXTRA_INDEX);
6c4aeab6 500 if (CONSP (extra))
c2f5bfd6 501 {
6c4aeab6 502 val = assq_no_quit (QCotf, extra);
6c4aeab6 503 if (! NILP (val))
f0c55750
KH
504 return Qnil;
505 val = assq_no_quit (QClang, extra);
6c4aeab6 506 if (! NILP (val))
f0c55750 507 return Qnil;
c2f5bfd6 508 }
398dbf26 509
f0c55750 510 registry = AREF (spec, FONT_REGISTRY_INDEX);
6a705b23
KH
511 len = font_unparse_xlfd (spec, 0, name, 512);
512 if (len < 0 || (len = xfont_encode_coding_xlfd (name)) < 0)
f0c55750 513 return Qnil;
5a189ffa
KH
514
515 val = assq_no_quit (QCscript, extra);
516 script = CDR (val);
517 list = xfont_list_pattern (display, name, registry, script);
f0c55750 518 if (NILP (list) && NILP (registry))
c2f5bfd6 519 {
f0c55750
KH
520 /* Try iso10646-1 */
521 char *r = name + len - 9; /* 9 == strlen (iso8859-1) */
522
523 if (r - name + 10 < 256) /* 10 == strlen (iso10646-1) */
6c4aeab6 524 {
f0c55750 525 strcpy (r, "iso10646-1");
5a189ffa 526 list = xfont_list_pattern (display, name, Qiso10646_1, script);
f0c55750
KH
527 }
528 }
529 if (NILP (list) && ! NILP (registry))
530 {
37470f4d 531 /* Try alternate registries. */
f0c55750 532 Lisp_Object alter;
6c4aeab6 533
f0c55750
KH
534 if ((alter = Fassoc (SYMBOL_NAME (registry),
535 Vface_alternative_font_registry_alist),
536 CONSP (alter)))
537 {
538 /* Pointer to REGISTRY-ENCODING field. */
539 char *r = name + len - SBYTES (SYMBOL_NAME (registry));
540
541 for (alter = XCDR (alter); CONSP (alter); alter = XCDR (alter))
542 if (STRINGP (XCAR (alter))
543 && ((r - name) + SBYTES (XCAR (alter))) < 256)
544 {
51b59d79 545 strcpy (r, SSDATA (XCAR (alter)));
5a189ffa 546 list = xfont_list_pattern (display, name, registry, script);
f0c55750
KH
547 if (! NILP (list))
548 break;
549 }
6c4aeab6 550 }
c2f5bfd6 551 }
37470f4d
KH
552 if (NILP (list))
553 {
554 /* Try alias. */
555 val = assq_no_quit (QCname, AREF (spec, FONT_EXTRA_INDEX));
6a705b23
KH
556 if (CONSP (val) && STRINGP (XCDR (val)) && SBYTES (XCDR (val)) < 512)
557 {
72af86bd 558 memcpy (name, SDATA (XCDR (val)), SBYTES (XCDR (val)) + 1);
6a705b23
KH
559 if (xfont_encode_coding_xlfd (name) < 0)
560 return Qnil;
5a189ffa 561 list = xfont_list_pattern (display, name, registry, script);
6a705b23 562 }
37470f4d 563 }
398dbf26 564
f0c55750 565 return list;
c2f5bfd6
KH
566}
567
6e34c9c1 568static Lisp_Object
971de7fb 569xfont_match (Lisp_Object frame, Lisp_Object spec)
6e34c9c1
KH
570{
571 FRAME_PTR f = XFRAME (frame);
572 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
573 Lisp_Object extra, val, entity;
6a705b23 574 char name[512];
6e34c9c1
KH
575 XFontStruct *xfont;
576 unsigned long value;
577
578 extra = AREF (spec, FONT_EXTRA_INDEX);
579 val = assq_no_quit (QCname, extra);
580 if (! CONSP (val) || ! STRINGP (XCDR (val)))
f0c55750 581 {
6a705b23 582 if (font_unparse_xlfd (spec, 0, name, 512) < 0)
f0c55750 583 return Qnil;
f0c55750 584 }
6a705b23 585 else if (SBYTES (XCDR (val)) < 512)
72af86bd 586 memcpy (name, SDATA (XCDR (val)), SBYTES (XCDR (val)) + 1);
f0c55750 587 else
6a705b23
KH
588 return Qnil;
589 if (xfont_encode_coding_xlfd (name) < 0)
590 return Qnil;
6e34c9c1 591
9c6d1df5 592 BLOCK_INPUT;
6e34c9c1 593 entity = Qnil;
6e34c9c1
KH
594 xfont = XLoadQueryFont (display, name);
595 if (xfont)
596 {
597 if (XGetFontProperty (xfont, XA_FONT, &value))
598 {
6a705b23 599 char *s;
6e34c9c1 600
6a705b23 601 s = (char *) XGetAtomName (display, (Atom) value);
6e34c9c1
KH
602
603 /* If DXPC (a Differential X Protocol Compressor)
604 Ver.3.7 is running, XGetAtomName will return null
605 string. We must avoid such a name. */
7de51af5 606 if (*s)
6e34c9c1 607 {
984e7f30 608 ptrdiff_t len;
f0c55750 609 entity = font_make_entity ();
6e34c9c1 610 ASET (entity, FONT_TYPE_INDEX, Qx);
984e7f30
DA
611 len = xfont_decode_coding_xlfd (s, -1, name);
612 if (font_parse_xlfd (name, len, entity) < 0)
6e34c9c1
KH
613 entity = Qnil;
614 }
6a705b23 615 XFree (s);
6e34c9c1
KH
616 }
617 XFreeFont (display, xfont);
618 }
9c6d1df5 619 UNBLOCK_INPUT;
6e34c9c1 620
678dca3d 621 FONT_ADD_LOG ("xfont-match", spec, entity);
6e34c9c1
KH
622 return entity;
623}
624
c2f5bfd6 625static Lisp_Object
971de7fb 626xfont_list_family (Lisp_Object frame)
c2f5bfd6
KH
627{
628 FRAME_PTR f = XFRAME (frame);
629 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
630 char **names;
631 int num_fonts, i;
632 Lisp_Object list;
e2be39f6 633 char *last_family IF_LINT (= 0);
c2f5bfd6
KH
634 int last_len;
635
636 BLOCK_INPUT;
637 x_catch_errors (dpyinfo->display);
638 names = XListFonts (dpyinfo->display, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*",
639 0x8000, &num_fonts);
640 if (x_had_errors_p (dpyinfo->display))
641 {
642 /* This error is perhaps due to insufficient memory on X server.
643 Let's just ignore it. */
644 x_clear_errors (dpyinfo->display);
645 num_fonts = 0;
646 }
647
648 list = Qnil;
649 for (i = 0, last_len = 0; i < num_fonts; i++)
650 {
6a705b23 651 char *p0 = names[i], *p1, buf[512];
c2f5bfd6 652 Lisp_Object family;
6a705b23 653 int decoded_len;
c2f5bfd6
KH
654
655 p0++; /* skip the leading '-' */
656 while (*p0 && *p0 != '-') p0++; /* skip foundry */
657 if (! *p0)
658 continue;
659 p1 = ++p0;
660 while (*p1 && *p1 != '-') p1++; /* find the end of family */
661 if (! *p1 || p1 == p0)
662 continue;
663 if (last_len == p1 - p0
72af86bd 664 && memcmp (last_family, p0, last_len) == 0)
c2f5bfd6
KH
665 continue;
666 last_len = p1 - p0;
667 last_family = p0;
6a705b23
KH
668
669 decoded_len = xfont_decode_coding_xlfd (p0, last_len, buf);
670 family = font_intern_prop (p0, decoded_len, 1);
29428bb8 671 if (NILP (assq_no_quit (family, list)))
c2f5bfd6
KH
672 list = Fcons (family, list);
673 }
674
675 XFreeFontNames (names);
676 x_uncatch_errors ();
677 UNBLOCK_INPUT;
678
679 return list;
680}
681
f0c55750 682static Lisp_Object
971de7fb 683xfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
c2f5bfd6
KH
684{
685 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
686 Display *display = dpyinfo->display;
6a705b23 687 char name[512];
c2f5bfd6
KH
688 int len;
689 unsigned long value;
690 Lisp_Object registry;
691 struct charset *encoding, *repertory;
f0c55750 692 Lisp_Object font_object, fullname;
c2f5bfd6
KH
693 struct font *font;
694 XFontStruct *xfont;
695
696 /* At first, check if we know how to encode characters for this
697 font. */
698 registry = AREF (entity, FONT_REGISTRY_INDEX);
a9822ae8 699 if (font_registry_charsets (registry, &encoding, &repertory) < 0)
c8e0e16d 700 {
678dca3d 701 FONT_ADD_LOG (" x:unknown registry", registry, Qnil);
c8e0e16d
KH
702 return Qnil;
703 }
c2f5bfd6
KH
704
705 if (XINT (AREF (entity, FONT_SIZE_INDEX)) != 0)
706 pixel_size = XINT (AREF (entity, FONT_SIZE_INDEX));
f0c55750
KH
707 else if (pixel_size == 0)
708 {
709 if (FRAME_FONT (f))
710 pixel_size = FRAME_FONT (f)->pixel_size;
711 else
712 pixel_size = 14;
713 }
6a705b23
KH
714 len = font_unparse_xlfd (entity, pixel_size, name, 512);
715 if (len <= 0 || (len = xfont_encode_coding_xlfd (name)) < 0)
c8e0e16d 716 {
678dca3d 717 FONT_ADD_LOG (" x:unparse failed", entity, Qnil);
c8e0e16d
KH
718 return Qnil;
719 }
c2f5bfd6
KH
720
721 BLOCK_INPUT;
722 x_catch_errors (display);
723 xfont = XLoadQueryFont (display, name);
724 if (x_had_errors_p (display))
725 {
726 /* This error is perhaps due to insufficient memory on X server.
727 Let's just ignore it. */
728 x_clear_errors (display);
729 xfont = NULL;
730 }
2f73901f
KH
731 else if (! xfont)
732 {
733 /* Some version of X lists:
734 -misc-fixed-medium-r-normal--20-*-75-75-c-100-iso8859-1
735 -misc-fixed-medium-r-normal--20-*-100-100-c-100-iso8859-1
736 but can open only:
737 -misc-fixed-medium-r-normal--20-*-100-100-c-100-iso8859-1
738 and
739 -misc-fixed-medium-r-normal--20-*-*-*-c-100-iso8859-1
740 So, we try again with wildcards in RESX and RESY. */
741 Lisp_Object temp;
742
92470028 743 temp = copy_font_spec (entity);
2f73901f 744 ASET (temp, FONT_DPI_INDEX, Qnil);
6a705b23
KH
745 len = font_unparse_xlfd (temp, pixel_size, name, 512);
746 if (len <= 0 || (len = xfont_encode_coding_xlfd (name)) < 0)
2f73901f 747 {
678dca3d 748 FONT_ADD_LOG (" x:unparse failed", temp, Qnil);
2f73901f
KH
749 return Qnil;
750 }
751 xfont = XLoadQueryFont (display, name);
752 if (x_had_errors_p (display))
753 {
754 /* This error is perhaps due to insufficient memory on X server.
755 Let's just ignore it. */
756 x_clear_errors (display);
757 xfont = NULL;
758 }
759 }
f0c55750
KH
760 fullname = Qnil;
761 /* Try to get the full name of FONT. */
762 if (xfont && XGetFontProperty (xfont, XA_FONT, &value))
763 {
764 char *p0, *p;
765 int dashes = 0;
766
8510724d 767 p0 = p = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
f0c55750
KH
768 /* Count the number of dashes in the "full name".
769 If it is too few, this isn't really the font's full name,
770 so don't use it.
771 In X11R4, the fonts did not come with their canonical names
772 stored in them. */
773 while (*p)
774 {
775 if (*p == '-')
776 dashes++;
777 p++;
778 }
779
780 if (dashes >= 13)
6a705b23
KH
781 {
782 len = xfont_decode_coding_xlfd (p0, -1, name);
783 fullname = Fdowncase (make_string (name, len));
784 }
f0c55750
KH
785 XFree (p0);
786 }
c2f5bfd6
KH
787 x_uncatch_errors ();
788 UNBLOCK_INPUT;
789
790 if (! xfont)
c8e0e16d 791 {
678dca3d 792 FONT_ADD_LOG (" x:open failed", build_string (name), Qnil);
c8e0e16d
KH
793 return Qnil;
794 }
f0c55750 795
947eecfb
KH
796 font_object = font_make_object (VECSIZE (struct xfont_info),
797 entity, pixel_size);
f0c55750
KH
798 ASET (font_object, FONT_TYPE_INDEX, Qx);
799 if (STRINGP (fullname))
6a705b23 800 {
984e7f30 801 font_parse_xlfd (SSDATA (fullname), SBYTES (fullname), font_object);
6a705b23
KH
802 ASET (font_object, FONT_NAME_INDEX, fullname);
803 }
f0c55750 804 else
6a705b23
KH
805 {
806 char buf[512];
807
808 len = xfont_decode_coding_xlfd (name, -1, buf);
809 ASET (font_object, FONT_NAME_INDEX, make_string (buf, len));
810 }
f0c55750
KH
811 ASET (font_object, FONT_FULLNAME_INDEX, fullname);
812 ASET (font_object, FONT_FILE_INDEX, Qnil);
813 ASET (font_object, FONT_FORMAT_INDEX, Qx);
814 font = XFONT_OBJECT (font_object);
815 ((struct xfont_info *) font)->xfont = xfont;
816 ((struct xfont_info *) font)->display = FRAME_X_DISPLAY (f);
c2f5bfd6
KH
817 font->pixel_size = pixel_size;
818 font->driver = &xfont_driver;
c2f5bfd6 819 font->encoding_charset = encoding->id;
1886668d 820 font->repertory_charset = repertory ? repertory->id : -1;
c2f5bfd6
KH
821 font->ascent = xfont->ascent;
822 font->descent = xfont->descent;
f0c55750
KH
823 font->height = font->ascent + font->descent;
824 font->min_width = xfont->min_bounds.width;
032a42c8 825 font->max_width = xfont->max_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}