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