(jdb): Add gud-pstar to dump object information.
[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);
5a189ffa
KH
414 font_parse_xlfd (buf, entity);
415 ASET (entity, FONT_TYPE_INDEX, Qx);
416 /* Avoid auto-scaled fonts. */
417 if (XINT (AREF (entity, FONT_DPI_INDEX)) != 0
418 && XINT (AREF (entity, FONT_AVGWIDTH_INDEX)) == 0)
419 continue;
420 /* Avoid not-allowed scalable fonts. */
421 if (NILP (Vscalable_fonts_allowed))
c2f5bfd6 422 {
5a189ffa 423 if (XINT (AREF (entity, FONT_SIZE_INDEX)) == 0)
6c4aeab6 424 continue;
5a189ffa
KH
425 }
426 else if (CONSP (Vscalable_fonts_allowed))
427 {
428 Lisp_Object tail, elt;
429
430 for (tail = Vscalable_fonts_allowed; CONSP (tail);
431 tail = XCDR (tail))
f0c55750 432 {
5a189ffa
KH
433 elt = XCAR (tail);
434 if (STRINGP (elt)
435 && fast_c_string_match_ignore_case (elt, indices[i]) >= 0)
436 break;
f0c55750 437 }
5a189ffa
KH
438 if (! CONSP (tail))
439 continue;
c2f5bfd6 440 }
f0c55750 441
5a189ffa
KH
442 /* Update encoding and repertory if necessary. */
443 if (! EQ (registry, AREF (entity, FONT_REGISTRY_INDEX)))
444 {
445 registry = AREF (entity, FONT_REGISTRY_INDEX);
446 if (font_registry_charsets (registry, &encoding, &repertory) < 0)
447 encoding = NULL;
448 }
449 if (! encoding)
450 /* Unknown REGISTRY, not supported. */
451 continue;
452 if (repertory)
453 {
454 if (NILP (script)
455 || xfont_chars_supported (chars, NULL, encoding, repertory))
456 list = Fcons (entity, list);
457 continue;
458 }
459 if (memcmp (props, &(AREF (entity, FONT_FOUNDRY_INDEX)),
460 sizeof (Lisp_Object) * 7)
461 || ! EQ (AREF (entity, FONT_SPACING_INDEX), props[7]))
462 {
463 memcpy (props, &(AREF (entity, FONT_FOUNDRY_INDEX)),
464 sizeof (Lisp_Object) * 7);
465 props[7] = AREF (entity, FONT_SPACING_INDEX);
466 scripts = xfont_supported_scripts (display, indices[i],
467 xfont_scratch_props, encoding);
468 }
469 if (NILP (script)
470 || ! NILP (Fmemq (script, scripts)))
f0c55750 471 list = Fcons (entity, list);
c2f5bfd6 472 }
019e13ef 473 XFreeFontNames (names);
c2f5bfd6
KH
474 }
475
476 x_uncatch_errors ();
477 UNBLOCK_INPUT;
478
678dca3d 479 FONT_ADD_LOG ("xfont-list", build_string (pattern), list);
6c4aeab6
KH
480 return list;
481}
c2f5bfd6 482
6c4aeab6
KH
483static Lisp_Object
484xfont_list (frame, spec)
485 Lisp_Object frame, spec;
486{
487 FRAME_PTR f = XFRAME (frame);
488 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
5a189ffa 489 Lisp_Object registry, list, val, extra, script;
6c4aeab6 490 int len;
6a705b23
KH
491 /* Large enough to contain the longest XLFD (255 bytes) in UTF-8. */
492 char name[512];
8510724d 493
6c4aeab6 494 extra = AREF (spec, FONT_EXTRA_INDEX);
6c4aeab6 495 if (CONSP (extra))
c2f5bfd6 496 {
6c4aeab6 497 val = assq_no_quit (QCotf, extra);
6c4aeab6 498 if (! NILP (val))
f0c55750
KH
499 return Qnil;
500 val = assq_no_quit (QClang, extra);
6c4aeab6 501 if (! NILP (val))
f0c55750 502 return Qnil;
c2f5bfd6 503 }
398dbf26 504
f0c55750 505 registry = AREF (spec, FONT_REGISTRY_INDEX);
6a705b23
KH
506 len = font_unparse_xlfd (spec, 0, name, 512);
507 if (len < 0 || (len = xfont_encode_coding_xlfd (name)) < 0)
f0c55750 508 return Qnil;
5a189ffa
KH
509
510 val = assq_no_quit (QCscript, extra);
511 script = CDR (val);
512 list = xfont_list_pattern (display, name, registry, script);
f0c55750 513 if (NILP (list) && NILP (registry))
c2f5bfd6 514 {
f0c55750
KH
515 /* Try iso10646-1 */
516 char *r = name + len - 9; /* 9 == strlen (iso8859-1) */
517
518 if (r - name + 10 < 256) /* 10 == strlen (iso10646-1) */
6c4aeab6 519 {
f0c55750 520 strcpy (r, "iso10646-1");
5a189ffa 521 list = xfont_list_pattern (display, name, Qiso10646_1, script);
f0c55750
KH
522 }
523 }
524 if (NILP (list) && ! NILP (registry))
525 {
37470f4d 526 /* Try alternate registries. */
f0c55750 527 Lisp_Object alter;
6c4aeab6 528
f0c55750
KH
529 if ((alter = Fassoc (SYMBOL_NAME (registry),
530 Vface_alternative_font_registry_alist),
531 CONSP (alter)))
532 {
533 /* Pointer to REGISTRY-ENCODING field. */
534 char *r = name + len - SBYTES (SYMBOL_NAME (registry));
535
536 for (alter = XCDR (alter); CONSP (alter); alter = XCDR (alter))
537 if (STRINGP (XCAR (alter))
538 && ((r - name) + SBYTES (XCAR (alter))) < 256)
539 {
540 strcpy (r, (char *) SDATA (XCAR (alter)));
5a189ffa 541 list = xfont_list_pattern (display, name, registry, script);
f0c55750
KH
542 if (! NILP (list))
543 break;
544 }
6c4aeab6 545 }
c2f5bfd6 546 }
37470f4d
KH
547 if (NILP (list))
548 {
549 /* Try alias. */
550 val = assq_no_quit (QCname, AREF (spec, FONT_EXTRA_INDEX));
6a705b23
KH
551 if (CONSP (val) && STRINGP (XCDR (val)) && SBYTES (XCDR (val)) < 512)
552 {
553 bcopy (SDATA (XCDR (val)), name, SBYTES (XCDR (val)) + 1);
554 if (xfont_encode_coding_xlfd (name) < 0)
555 return Qnil;
5a189ffa 556 list = xfont_list_pattern (display, name, registry, script);
6a705b23 557 }
37470f4d 558 }
398dbf26 559
f0c55750 560 return list;
c2f5bfd6
KH
561}
562
6e34c9c1
KH
563static Lisp_Object
564xfont_match (frame, spec)
565 Lisp_Object frame, spec;
566{
567 FRAME_PTR f = XFRAME (frame);
568 Display *display = FRAME_X_DISPLAY_INFO (f)->display;
569 Lisp_Object extra, val, entity;
6a705b23 570 char name[512];
6e34c9c1
KH
571 XFontStruct *xfont;
572 unsigned long value;
573
574 extra = AREF (spec, FONT_EXTRA_INDEX);
575 val = assq_no_quit (QCname, extra);
576 if (! CONSP (val) || ! STRINGP (XCDR (val)))
f0c55750 577 {
6a705b23 578 if (font_unparse_xlfd (spec, 0, name, 512) < 0)
f0c55750 579 return Qnil;
f0c55750 580 }
6a705b23
KH
581 else if (SBYTES (XCDR (val)) < 512)
582 bcopy (SDATA (XCDR (val)), name, SBYTES (XCDR (val)) + 1);
f0c55750 583 else
6a705b23
KH
584 return Qnil;
585 if (xfont_encode_coding_xlfd (name) < 0)
586 return Qnil;
6e34c9c1 587
9c6d1df5 588 BLOCK_INPUT;
6e34c9c1 589 entity = Qnil;
6e34c9c1
KH
590 xfont = XLoadQueryFont (display, name);
591 if (xfont)
592 {
593 if (XGetFontProperty (xfont, XA_FONT, &value))
594 {
595 int len;
6a705b23 596 char *s;
6e34c9c1 597
6a705b23
KH
598 s = (char *) XGetAtomName (display, (Atom) value);
599 len = strlen (s);
6e34c9c1
KH
600
601 /* If DXPC (a Differential X Protocol Compressor)
602 Ver.3.7 is running, XGetAtomName will return null
603 string. We must avoid such a name. */
604 if (len > 0)
605 {
f0c55750 606 entity = font_make_entity ();
6e34c9c1 607 ASET (entity, FONT_TYPE_INDEX, Qx);
6a705b23 608 xfont_decode_coding_xlfd (s, -1, name);
6e34c9c1
KH
609 if (font_parse_xlfd (name, entity) < 0)
610 entity = Qnil;
611 }
6a705b23 612 XFree (s);
6e34c9c1
KH
613 }
614 XFreeFont (display, xfont);
615 }
9c6d1df5 616 UNBLOCK_INPUT;
6e34c9c1 617
678dca3d 618 FONT_ADD_LOG ("xfont-match", spec, entity);
6e34c9c1
KH
619 return entity;
620}
621
c2f5bfd6
KH
622static Lisp_Object
623xfont_list_family (frame)
9df50a31 624 Lisp_Object frame;
c2f5bfd6
KH
625{
626 FRAME_PTR f = XFRAME (frame);
627 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
628 char **names;
629 int num_fonts, i;
630 Lisp_Object list;
631 char *last_family;
632 int last_len;
633
634 BLOCK_INPUT;
635 x_catch_errors (dpyinfo->display);
636 names = XListFonts (dpyinfo->display, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*",
637 0x8000, &num_fonts);
638 if (x_had_errors_p (dpyinfo->display))
639 {
640 /* This error is perhaps due to insufficient memory on X server.
641 Let's just ignore it. */
642 x_clear_errors (dpyinfo->display);
643 num_fonts = 0;
644 }
645
646 list = Qnil;
647 for (i = 0, last_len = 0; i < num_fonts; i++)
648 {
6a705b23 649 char *p0 = names[i], *p1, buf[512];
c2f5bfd6 650 Lisp_Object family;
6a705b23 651 int decoded_len;
c2f5bfd6
KH
652
653 p0++; /* skip the leading '-' */
654 while (*p0 && *p0 != '-') p0++; /* skip foundry */
655 if (! *p0)
656 continue;
657 p1 = ++p0;
658 while (*p1 && *p1 != '-') p1++; /* find the end of family */
659 if (! *p1 || p1 == p0)
660 continue;
661 if (last_len == p1 - p0
662 && bcmp (last_family, p0, last_len) == 0)
663 continue;
664 last_len = p1 - p0;
665 last_family = p0;
6a705b23
KH
666
667 decoded_len = xfont_decode_coding_xlfd (p0, last_len, buf);
668 family = font_intern_prop (p0, decoded_len, 1);
29428bb8 669 if (NILP (assq_no_quit (family, list)))
c2f5bfd6
KH
670 list = Fcons (family, list);
671 }
672
673 XFreeFontNames (names);
674 x_uncatch_errors ();
675 UNBLOCK_INPUT;
676
677 return list;
678}
679
f0c55750
KH
680extern Lisp_Object QCavgwidth;
681
682static Lisp_Object
c2f5bfd6
KH
683xfont_open (f, entity, pixel_size)
684 FRAME_PTR f;
685 Lisp_Object entity;
686 int pixel_size;
687{
688 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
689 Display *display = dpyinfo->display;
6a705b23 690 char name[512];
c2f5bfd6
KH
691 int len;
692 unsigned long value;
693 Lisp_Object registry;
694 struct charset *encoding, *repertory;
f0c55750 695 Lisp_Object font_object, fullname;
c2f5bfd6
KH
696 struct font *font;
697 XFontStruct *xfont;
698
699 /* At first, check if we know how to encode characters for this
700 font. */
701 registry = AREF (entity, FONT_REGISTRY_INDEX);
a9822ae8 702 if (font_registry_charsets (registry, &encoding, &repertory) < 0)
c8e0e16d 703 {
678dca3d 704 FONT_ADD_LOG (" x:unknown registry", registry, Qnil);
c8e0e16d
KH
705 return Qnil;
706 }
c2f5bfd6
KH
707
708 if (XINT (AREF (entity, FONT_SIZE_INDEX)) != 0)
709 pixel_size = XINT (AREF (entity, FONT_SIZE_INDEX));
f0c55750
KH
710 else if (pixel_size == 0)
711 {
712 if (FRAME_FONT (f))
713 pixel_size = FRAME_FONT (f)->pixel_size;
714 else
715 pixel_size = 14;
716 }
6a705b23
KH
717 len = font_unparse_xlfd (entity, pixel_size, name, 512);
718 if (len <= 0 || (len = xfont_encode_coding_xlfd (name)) < 0)
c8e0e16d 719 {
678dca3d 720 FONT_ADD_LOG (" x:unparse failed", entity, Qnil);
c8e0e16d
KH
721 return Qnil;
722 }
c2f5bfd6
KH
723
724 BLOCK_INPUT;
725 x_catch_errors (display);
726 xfont = XLoadQueryFont (display, name);
727 if (x_had_errors_p (display))
728 {
729 /* This error is perhaps due to insufficient memory on X server.
730 Let's just ignore it. */
731 x_clear_errors (display);
732 xfont = NULL;
733 }
2f73901f
KH
734 else if (! xfont)
735 {
736 /* Some version of X lists:
737 -misc-fixed-medium-r-normal--20-*-75-75-c-100-iso8859-1
738 -misc-fixed-medium-r-normal--20-*-100-100-c-100-iso8859-1
739 but can open only:
740 -misc-fixed-medium-r-normal--20-*-100-100-c-100-iso8859-1
741 and
742 -misc-fixed-medium-r-normal--20-*-*-*-c-100-iso8859-1
743 So, we try again with wildcards in RESX and RESY. */
744 Lisp_Object temp;
745
746 temp = Fcopy_font_spec (entity);
747 ASET (temp, FONT_DPI_INDEX, Qnil);
6a705b23
KH
748 len = font_unparse_xlfd (temp, pixel_size, name, 512);
749 if (len <= 0 || (len = xfont_encode_coding_xlfd (name)) < 0)
2f73901f 750 {
678dca3d 751 FONT_ADD_LOG (" x:unparse failed", temp, Qnil);
2f73901f
KH
752 return Qnil;
753 }
754 xfont = XLoadQueryFont (display, name);
755 if (x_had_errors_p (display))
756 {
757 /* This error is perhaps due to insufficient memory on X server.
758 Let's just ignore it. */
759 x_clear_errors (display);
760 xfont = NULL;
761 }
762 }
f0c55750
KH
763 fullname = Qnil;
764 /* Try to get the full name of FONT. */
765 if (xfont && XGetFontProperty (xfont, XA_FONT, &value))
766 {
767 char *p0, *p;
768 int dashes = 0;
769
8510724d 770 p0 = p = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
f0c55750
KH
771 /* Count the number of dashes in the "full name".
772 If it is too few, this isn't really the font's full name,
773 so don't use it.
774 In X11R4, the fonts did not come with their canonical names
775 stored in them. */
776 while (*p)
777 {
778 if (*p == '-')
779 dashes++;
780 p++;
781 }
782
783 if (dashes >= 13)
6a705b23
KH
784 {
785 len = xfont_decode_coding_xlfd (p0, -1, name);
786 fullname = Fdowncase (make_string (name, len));
787 }
f0c55750
KH
788 XFree (p0);
789 }
c2f5bfd6
KH
790 x_uncatch_errors ();
791 UNBLOCK_INPUT;
792
793 if (! xfont)
c8e0e16d 794 {
678dca3d 795 FONT_ADD_LOG (" x:open failed", build_string (name), Qnil);
c8e0e16d
KH
796 return Qnil;
797 }
f0c55750 798
947eecfb
KH
799 font_object = font_make_object (VECSIZE (struct xfont_info),
800 entity, pixel_size);
f0c55750
KH
801 ASET (font_object, FONT_TYPE_INDEX, Qx);
802 if (STRINGP (fullname))
6a705b23
KH
803 {
804 font_parse_xlfd ((char *) SDATA (fullname), font_object);
805 ASET (font_object, FONT_NAME_INDEX, fullname);
806 }
f0c55750 807 else
6a705b23
KH
808 {
809 char buf[512];
810
811 len = xfont_decode_coding_xlfd (name, -1, buf);
812 ASET (font_object, FONT_NAME_INDEX, make_string (buf, len));
813 }
f0c55750
KH
814 ASET (font_object, FONT_FULLNAME_INDEX, fullname);
815 ASET (font_object, FONT_FILE_INDEX, Qnil);
816 ASET (font_object, FONT_FORMAT_INDEX, Qx);
817 font = XFONT_OBJECT (font_object);
818 ((struct xfont_info *) font)->xfont = xfont;
819 ((struct xfont_info *) font)->display = FRAME_X_DISPLAY (f);
c2f5bfd6
KH
820 font->pixel_size = pixel_size;
821 font->driver = &xfont_driver;
c2f5bfd6 822 font->encoding_charset = encoding->id;
1886668d 823 font->repertory_charset = repertory ? repertory->id : -1;
c2f5bfd6
KH
824 font->ascent = xfont->ascent;
825 font->descent = xfont->descent;
f0c55750
KH
826 font->height = font->ascent + font->descent;
827 font->min_width = xfont->min_bounds.width;
c2f5bfd6
KH
828 if (xfont->min_bounds.width == xfont->max_bounds.width)
829 {
830 /* Fixed width font. */
f0c55750 831 font->average_width = font->space_width = xfont->min_bounds.width;
c2f5bfd6
KH
832 }
833 else
834 {
c2f5bfd6 835 XCharStruct *pcm;
f0c55750
KH
836 XChar2b char2b;
837 Lisp_Object val;
c2f5bfd6
KH
838
839 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
840 pcm = xfont_get_pcm (xfont, &char2b);
841 if (pcm)
f0c55750 842 font->space_width = pcm->width;
c2f5bfd6 843 else
f0c55750
KH
844 font->space_width = 0;
845
846 val = Ffont_get (font_object, QCavgwidth);
847 if (INTEGERP (val))
848 font->average_width = XINT (val);
849 if (font->average_width < 0)
850 font->average_width = - font->average_width;
851 if (font->average_width == 0
852 && encoding->ascii_compatible_p)
c2f5bfd6 853 {
f0c55750 854 int width = font->space_width, n = pcm != NULL;
c2f5bfd6 855
f0c55750
KH
856 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
857 if ((pcm = xfont_get_pcm (xfont, &char2b)) != NULL)
858 width += pcm->width, n++;
4f64a164
KH
859 if (n > 0)
860 font->average_width = width / n;
c2f5bfd6 861 }
4f64a164
KH
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
f0c55750
KH
869 BLOCK_INPUT;
870 font->underline_thickness
871 = (XGetFontProperty (xfont, XA_UNDERLINE_THICKNESS, &value)
872 ? (long) value : 0);
873 font->underline_position
874 = (XGetFontProperty (xfont, XA_UNDERLINE_POSITION, &value)
875 ? (long) value : -1);
876 font->baseline_offset
c2f5bfd6
KH
877 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
878 ? (long) value : 0);
f0c55750 879 font->relative_compose
c2f5bfd6
KH
880 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
881 ? (long) value : 0);
f0c55750 882 font->default_ascent
c2f5bfd6
KH
883 = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
884 ? (long) value : 0);
c2f5bfd6
KH
885 UNBLOCK_INPUT;
886
f0c55750
KH
887 if (NILP (fullname))
888 fullname = AREF (font_object, FONT_NAME_INDEX);
634c4da0
KH
889 font->vertical_centering
890 = (STRINGP (Vvertical_centering_font_regexp)
891 && (fast_string_match_ignore_case
892 (Vvertical_centering_font_regexp, fullname) >= 0));
c2f5bfd6 893
f0c55750 894 return font_object;
c2f5bfd6
KH
895}
896
897static void
898xfont_close (f, font)
899 FRAME_PTR f;
900 struct font *font;
901{
902 BLOCK_INPUT;
f0c55750 903 XFreeFont (FRAME_X_DISPLAY (f), ((struct xfont_info *) font)->xfont);
c2f5bfd6 904 UNBLOCK_INPUT;
c2f5bfd6
KH
905}
906
907static int
908xfont_prepare_face (f, face)
909 FRAME_PTR f;
910 struct face *face;
911{
912 BLOCK_INPUT;
f0c55750
KH
913 XSetFont (FRAME_X_DISPLAY (f), face->gc,
914 ((struct xfont_info *) face->font)->xfont->fid);
c2f5bfd6
KH
915 UNBLOCK_INPUT;
916
917 return 0;
918}
919
c2f5bfd6 920static int
bd0af90d
KH
921xfont_has_char (font, c)
922 Lisp_Object font;
c2f5bfd6
KH
923 int c;
924{
bd0af90d 925 Lisp_Object registry = AREF (font, FONT_REGISTRY_INDEX);
d156542d 926 struct charset *encoding;
bd0af90d 927 struct charset *repertory = NULL;
c2f5bfd6 928
bd0af90d
KH
929 if (EQ (registry, Qiso10646_1))
930 {
5a189ffa 931 encoding = CHARSET_FROM_ID (charset_unicode);
bd0af90d
KH
932 /* We use a font of `ja' and `ko' adstyle only for a character
933 in JISX0208 and KSC5601 charsets respectively. */
934 if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
935 && charset_jisx0208 >= 0)
5a189ffa 936 repertory = CHARSET_FROM_ID (charset_jisx0208);
bd0af90d
KH
937 else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
938 && charset_ksc5601 >= 0)
5a189ffa 939 repertory = CHARSET_FROM_ID (charset_ksc5601);
bd0af90d
KH
940 }
941 else if (font_registry_charsets (registry, &encoding, &repertory) < 0)
942 /* Unknown REGISTRY, not usable. */
943 return 0;
d156542d
KH
944 if (ASCII_CHAR_P (c) && encoding->ascii_compatible_p)
945 return 1;
c2f5bfd6
KH
946 if (! repertory)
947 return -1;
948 return (ENCODE_CHAR (repertory, c) != CHARSET_INVALID_CODE (repertory));
949}
950
951static unsigned
952xfont_encode_char (font, c)
953 struct font *font;
954 int c;
955{
f0c55750 956 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
c2f5bfd6
KH
957 struct charset *charset;
958 unsigned code;
959 XChar2b char2b;
960
961 charset = CHARSET_FROM_ID (font->encoding_charset);
962 code = ENCODE_CHAR (charset, c);
963 if (code == CHARSET_INVALID_CODE (charset))
21138cff 964 return FONT_INVALID_CODE;
1886668d 965 if (font->repertory_charset >= 0)
c2f5bfd6 966 {
1886668d 967 charset = CHARSET_FROM_ID (font->repertory_charset);
c2f5bfd6 968 return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset)
21138cff 969 ? code : FONT_INVALID_CODE);
c2f5bfd6 970 }
88649c62
KH
971 char2b.byte1 = code >> 8;
972 char2b.byte2 = code & 0xFF;
f0c55750 973 return (xfont_get_pcm (xfont, &char2b) ? code : FONT_INVALID_CODE);
c2f5bfd6
KH
974}
975
976static int
977xfont_text_extents (font, code, nglyphs, metrics)
978 struct font *font;
979 unsigned *code;
980 int nglyphs;
981 struct font_metrics *metrics;
982{
f0c55750 983 XFontStruct *xfont = ((struct xfont_info *) font)->xfont;
c2f5bfd6 984 int width = 0;
41fa3e2c 985 int i, first, x;
c2f5bfd6
KH
986
987 if (metrics)
988 bzero (metrics, sizeof (struct font_metrics));
41fa3e2c 989 for (i = 0, x = 0, first = 1; i < nglyphs; i++)
c2f5bfd6
KH
990 {
991 XChar2b char2b;
992 static XCharStruct *pcm;
993
994 if (code[i] >= 0x10000)
995 continue;
996 char2b.byte1 = code[i] >> 8, char2b.byte2 = code[i] & 0xFF;
f0c55750 997 pcm = xfont_get_pcm (xfont, &char2b);
c2f5bfd6
KH
998 if (! pcm)
999 continue;
41fa3e2c
KH
1000 if (first)
1001 {
1002 if (metrics)
1003 {
1004 metrics->lbearing = pcm->lbearing;
1005 metrics->rbearing = pcm->rbearing;
1006 metrics->ascent = pcm->ascent;
1007 metrics->descent = pcm->descent;
1008 }
1009 first = 0;
1010 }
1011 else
1012 {
1013 if (metrics)
1014 {
1015 if (metrics->lbearing > width + pcm->lbearing)
1016 metrics->lbearing = width + pcm->lbearing;
1017 if (metrics->rbearing < width + pcm->rbearing)
1018 metrics->rbearing = width + pcm->rbearing;
1019 if (metrics->ascent < pcm->ascent)
1020 metrics->ascent = pcm->ascent;
1021 if (metrics->descent < pcm->descent)
1022 metrics->descent = pcm->descent;
1023 }
1024 }
c2f5bfd6
KH
1025 width += pcm->width;
1026 }
1027 if (metrics)
1028 metrics->width = width;
1029 return width;
1030}
1031
1032static int
1033xfont_draw (s, from, to, x, y, with_background)
1034 struct glyph_string *s;
1035 int from, to, x, y, with_background;
1036{
f0c55750 1037 XFontStruct *xfont = ((struct xfont_info *) s->font)->xfont;
c2f5bfd6 1038 int len = to - from;
6e34c9c1 1039 GC gc = s->gc;
298fd5b1 1040 int i;
6e34c9c1 1041
f0c55750 1042 if (s->gc != s->face->gc)
6e34c9c1 1043 {
d45fefc7 1044 BLOCK_INPUT;
f0c55750 1045 XSetFont (s->display, gc, xfont->fid);
d45fefc7 1046 UNBLOCK_INPUT;
6e34c9c1 1047 }
c2f5bfd6
KH
1048
1049 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
1050 {
1051 char *str;
c2f5bfd6
KH
1052 USE_SAFE_ALLOCA;
1053
1054 SAFE_ALLOCA (str, char *, len);
1055 for (i = 0; i < len ; i++)
1056 str[i] = XCHAR2B_BYTE2 (s->char2b + from + i);
d45fefc7 1057 BLOCK_INPUT;
c2f5bfd6 1058 if (with_background > 0)
298fd5b1
KH
1059 {
1060 if (s->padding_p)
1061 for (i = 0; i < len; i++)
1062 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
1063 gc, x + i, y, str + i, 1);
1064 else
1065 XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
1066 gc, x, y, str, len);
1067 }
c2f5bfd6 1068 else
298fd5b1
KH
1069 {
1070 if (s->padding_p)
1071 for (i = 0; i < len; i++)
1072 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
1073 gc, x + i, y, str + i, 1);
1074 else
1075 XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
1076 gc, x, y, str, len);
1077 }
d45fefc7 1078 UNBLOCK_INPUT;
c2f5bfd6
KH
1079 SAFE_FREE ();
1080 return s->nchars;
1081 }
1082
d45fefc7 1083 BLOCK_INPUT;
c2f5bfd6 1084 if (with_background > 0)
298fd5b1
KH
1085 {
1086 if (s->padding_p)
1087 for (i = 0; i < len; i++)
1088 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
1089 gc, x + i, y, s->char2b + from + i, 1);
1090 else
1091 XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
1092 gc, x, y, s->char2b + from, len);
1093 }
c2f5bfd6 1094 else
298fd5b1
KH
1095 {
1096 if (s->padding_p)
1097 for (i = 0; i < len; i++)
1098 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
1099 gc, x + i, y, s->char2b + from + i, 1);
1100 else
1101 XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
1102 gc, x, y, s->char2b + from, len);
1103 }
d45fefc7 1104 UNBLOCK_INPUT;
c2f5bfd6
KH
1105
1106 return len;
1107}
1108
f0c55750
KH
1109static int
1110xfont_check (f, font)
1111 FRAME_PTR f;
1112 struct font *font;
1113{
1114 struct xfont_info *xfont = (struct xfont_info *) font;
1115
1116 return (FRAME_X_DISPLAY (f) == xfont->display ? 0 : -1);
1117}
1118
c2f5bfd6
KH
1119\f
1120void
1121syms_of_xfont ()
1122{
5a189ffa 1123 staticpro (&xfont_scripts_cache);
46306a17
SM
1124 { /* Here we rely on the fact that syms_of_xfont (via syms_of_font)
1125 is called fairly late, when QCtest and Qequal are known to be set. */
1126 Lisp_Object args[2];
1127 args[0] = QCtest;
1128 args[1] = Qequal;
1129 xfont_scripts_cache = Fmake_hash_table (2, args);
1130 }
5a189ffa 1131 staticpro (&xfont_scratch_props);
46306a17 1132 xfont_scratch_props = Fmake_vector (make_number (8), Qnil);
c2f5bfd6
KH
1133 xfont_driver.type = Qx;
1134 register_font_driver (&xfont_driver, NULL);
1135}
885b7d09
MB
1136
1137/* arch-tag: 23c5f366-a5ee-44b7-a3b7-90d6da7fd749
1138 (do not change this comment) */