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