Generalize run-time debugging checks.
[bpt/emacs.git] / src / fontset.c
CommitLineData
4ed46869 1/* Fontset handler.
95df8112 2
acaf905b 3Copyright (C) 2001-2012 Free Software Foundation, Inc.
95df8112
GM
4Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
5 2005, 2006, 2007, 2008, 2009, 2010, 2011
6 National Institute of Advanced Industrial Science and Technology (AIST)
7 Registration Number H14PRO021
8Copyright (C) 2003, 2006
9 National Institute of Advanced Industrial Science and Technology (AIST)
10 Registration Number H13PRO009
eb152aa9 11
369314dc
KH
12This file is part of GNU Emacs.
13
9ec0b715 14GNU Emacs is free software: you can redistribute it and/or modify
369314dc 15it under the terms of the GNU General Public License as published by
9ec0b715
GM
16the Free Software Foundation, either version 3 of the License, or
17(at your option) any later version.
4ed46869 18
369314dc
KH
19GNU Emacs is distributed in the hope that it will be useful,
20but WITHOUT ANY WARRANTY; without even the implied warranty of
21MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22GNU General Public License for more details.
4ed46869 23
369314dc 24You should have received a copy of the GNU General Public License
9ec0b715 25along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
4ed46869
KH
26
27#include <config.h>
0d407d77 28#include <stdio.h>
d7306fe6 29#include <setjmp.h>
0d407d77 30
4ed46869 31#include "lisp.h"
06f76f0d 32#include "blockinput.h"
06f76f0d 33#include "character.h"
e5560ff7 34#include "buffer.h"
4ed46869
KH
35#include "charset.h"
36#include "ccl.h"
2538fae4 37#include "keyboard.h"
4ed46869 38#include "frame.h"
0d407d77 39#include "dispextern.h"
e1a14cdc 40#include "intervals.h"
3541bb8f 41#include "fontset.h"
0d407d77 42#include "window.h"
92c15c34
KH
43#ifdef HAVE_X_WINDOWS
44#include "xterm.h"
45#endif
46#ifdef WINDOWSNT
47#include "w32term.h"
48#endif
edfda783
AR
49#ifdef HAVE_NS
50#include "nsterm.h"
51#endif
fa971ac3 52#include "termhooks.h"
0d407d77 53
8aa07a8d 54#include "font.h"
8aa07a8d 55
0d407d77
KH
56/* FONTSET
57
58 A fontset is a collection of font related information to give
1d5d7200
KH
59 similar appearance (style, etc) of characters. A fontset has two
60 roles. One is to use for the frame parameter `font' as if it is an
61 ASCII font. In that case, Emacs uses the font specified for
62 `ascii' script for the frame's default font.
63
64 Another role, the more important one, is to provide information
65 about which font to use for each non-ASCII character.
66
67 There are two kinds of fontsets; base and realized. A base fontset
68 is created by `new-fontset' from Emacs Lisp explicitly. A realized
69 fontset is created implicitly when a face is realized for ASCII
70 characters. A face is also realized for non-ASCII characters based
71 on an ASCII face. All of non-ASCII faces based on the same ASCII
72 face share the same realized fontset.
8f924df7 73
06f76f0d
KH
74 A fontset object is implemented by a char-table whose default value
75 and parent are always nil.
fc8865fc 76
1d5d7200
KH
77 An element of a base fontset is a vector of FONT-DEFs which itself
78 is a vector [ FONT-SPEC ENCODING REPERTORY ].
79
f088b054
KH
80 An element of a realized fontset is nil, t, 0, or a vector of this
81 form:
7e1a1cd9 82
581f7ac7
KH
83 [ CHARSET-ORDERED-LIST-TICK PREFERRED-RFONT-DEF
84 RFONT-DEF0 RFONT-DEF1 ... ]
0d407d77 85
7e1a1cd9 86 RFONT-DEFn (i.e. Realized FONT-DEF) has this form:
0d407d77 87
581f7ac7 88 [ FACE-ID FONT-DEF FONT-OBJECT SORTING-SCORE ]
0d407d77 89
581f7ac7 90 RFONT-DEFn are automatically reordered by the current charset
1d5d7200 91 priority list.
0d407d77 92
7e1a1cd9
KH
93 The value nil means that we have not yet generated the above vector
94 from the base of the fontset.
0d407d77 95
1d5d7200
KH
96 The value t means that no font is available for the corresponding
97 range of characters.
0d407d77 98
f088b054
KH
99 The value 0 means that no font is available for the corresponding
100 range of characters in this fontset, but may be available in the
101 default fontset.
102
0d407d77 103
eb36588a 104 A fontset has 9 extra slots.
0d407d77 105
1d5d7200 106 The 1st slot: the ID number of the fontset
0d407d77 107
1d5d7200
KH
108 The 2nd slot:
109 base: the name of the fontset
110 realized: nil
0d407d77 111
1d5d7200 112 The 3rd slot:
d6aaac9e 113 base: nil
1d5d7200 114 realized: the base fontset
06f76f0d 115
1d5d7200
KH
116 The 4th slot:
117 base: nil
118 realized: the frame that the fontset belongs to
0d407d77 119
1d5d7200
KH
120 The 5th slot:
121 base: the font name for ASCII characters
122 realized: nil
0d407d77 123
1d5d7200
KH
124 The 6th slot:
125 base: nil
126 realized: the ID number of a face to use for characters that
127 has no font in a realized fontset.
0d407d77 128
1d5d7200
KH
129 The 7th slot:
130 base: nil
131 realized: Alist of font index vs the corresponding repertory
132 char-table.
eb152aa9 133
d6aaac9e
KH
134 The 8th slot:
135 base: nil
136 realized: If the base is not the default fontset, a fontset
137 realized from the default fontset, else nil.
1d5d7200 138
eb36588a 139 The 9th slot:
cc7b6145
KH
140 base: Same as element value (but for fallback fonts).
141 realized: Likewise.
eb36588a 142
1d5d7200 143 All fontsets are recorded in the vector Vfontset_table.
0d407d77
KH
144
145
146 DEFAULT FONTSET
147
1d5d7200
KH
148 There's a special base fontset named `default fontset' which
149 defines the default font specifications. When a base fontset
150 doesn't specify a font for a specific character, the corresponding
151 value in the default fontset is used.
0d407d77 152
afe93d01
KH
153 The parent of a realized fontset created for such a face that has
154 no fontset is the default fontset.
0d407d77
KH
155
156
157 These structures are hidden from the other codes than this file.
158 The other codes handle fontsets only by their ID numbers. They
06f76f0d 159 usually use the variable name `fontset' for IDs. But, in this
c80e3b4a 160 file, we always use variable name `id' for IDs, and name `fontset'
1d5d7200 161 for an actual fontset object, i.e., char-table.
0d407d77
KH
162
163*/
164
165/********** VARIABLES and FUNCTION PROTOTYPES **********/
166
d6aaac9e
KH
167static Lisp_Object Qfontset;
168static Lisp_Object Qfontset_info;
1d5d7200 169static Lisp_Object Qprepend, Qappend;
ef6e0694 170Lisp_Object Qlatin;
0d407d77
KH
171
172/* Vector containing all fontsets. */
173static Lisp_Object Vfontset_table;
174
fc8865fc 175/* Next possibly free fontset ID. Usually this keeps the minimum
0d407d77
KH
176 fontset ID not yet used. */
177static int next_fontset_id;
178
179/* The default fontset. This gives default FAMILY and REGISTRY of
06f76f0d 180 font for each character. */
0d407d77 181static Lisp_Object Vdefault_fontset;
4ed46869 182
4ed46869 183/* Check if any window system is used now. */
f57e2426 184void (*check_window_system_func) (void);
4ed46869 185
0d407d77
KH
186
187/* Prototype declarations for static functions. */
f57e2426
J
188static Lisp_Object fontset_add (Lisp_Object, Lisp_Object, Lisp_Object,
189 Lisp_Object);
190static Lisp_Object fontset_find_font (Lisp_Object, int, struct face *,
191 int, int);
192static void reorder_font_vector (Lisp_Object, struct font *);
193static Lisp_Object fontset_font (Lisp_Object, int, struct face *, int);
194static Lisp_Object make_fontset (Lisp_Object, Lisp_Object, Lisp_Object);
195static Lisp_Object fontset_pattern_regexp (Lisp_Object);
196static void accumulate_script_ranges (Lisp_Object, Lisp_Object,
197 Lisp_Object);
f57e2426 198static void set_fontset_font (Lisp_Object, Lisp_Object);
2449d4d0 199
a54e2c05 200#ifdef ENABLE_CHECKING
556383ac
KH
201
202/* Return 1 if ID is a valid fontset id, else return 0. */
203
204static int
ef1b0ba7 205fontset_id_valid_p (int id)
556383ac
KH
206{
207 return (id >= 0 && id < ASIZE (Vfontset_table) - 1);
208}
209
210#endif
211
0d407d77
KH
212
213\f
214/********** MACROS AND FUNCTIONS TO HANDLE FONTSET **********/
215
0d407d77
KH
216/* Return the fontset with ID. No check of ID's validness. */
217#define FONTSET_FROM_ID(id) AREF (Vfontset_table, id)
218
afe93d01 219/* Macros to access special values of FONTSET. */
0d407d77 220#define FONTSET_ID(fontset) XCHAR_TABLE (fontset)->extras[0]
06f76f0d
KH
221
222/* Macros to access special values of (base) FONTSET. */
0d407d77 223#define FONTSET_NAME(fontset) XCHAR_TABLE (fontset)->extras[1]
06f76f0d 224#define FONTSET_ASCII(fontset) XCHAR_TABLE (fontset)->extras[4]
a9a06e0b 225/* #define FONTSET_SPEC(fontset) XCHAR_TABLE (fontset)->extras[5] */
06f76f0d 226
06f76f0d
KH
227/* Macros to access special values of (realized) FONTSET. */
228#define FONTSET_BASE(fontset) XCHAR_TABLE (fontset)->extras[2]
229#define FONTSET_FRAME(fontset) XCHAR_TABLE (fontset)->extras[3]
239f9db9 230/* #define FONTSET_OBJLIST(fontset) XCHAR_TABLE (fontset)->extras[4] */
1d5d7200 231#define FONTSET_NOFONT_FACE(fontset) XCHAR_TABLE (fontset)->extras[5]
a9a06e0b 232/* #define FONTSET_REPERTORY(fontset) XCHAR_TABLE (fontset)->extras[6] */
eb36588a
KH
233#define FONTSET_DEFAULT(fontset) XCHAR_TABLE (fontset)->extras[7]
234
cc7b6145 235/* For both base and realized fontset. */
eb36588a 236#define FONTSET_FALLBACK(fontset) XCHAR_TABLE (fontset)->extras[8]
0d407d77 237
e3400864 238#define BASE_FONTSET_P(fontset) (NILP (FONTSET_BASE (fontset)))
0d407d77
KH
239
240
581f7ac7
KH
241/* Macros for FONT-DEF and RFONT-DEF of fontset. */
242#define FONT_DEF_NEW(font_def, font_spec, encoding, repertory) \
243 do { \
244 (font_def) = Fmake_vector (make_number (3), (font_spec)); \
245 ASET ((font_def), 1, encoding); \
246 ASET ((font_def), 2, repertory); \
247 } while (0)
248
249#define FONT_DEF_SPEC(font_def) AREF (font_def, 0)
250#define FONT_DEF_ENCODING(font_def) AREF (font_def, 1)
251#define FONT_DEF_REPERTORY(font_def) AREF (font_def, 2)
252
253#define RFONT_DEF_FACE(rfont_def) AREF (rfont_def, 0)
254#define RFONT_DEF_SET_FACE(rfont_def, face_id) \
255 ASET ((rfont_def), 0, make_number (face_id))
256#define RFONT_DEF_FONT_DEF(rfont_def) AREF (rfont_def, 1)
257#define RFONT_DEF_SPEC(rfont_def) FONT_DEF_SPEC (AREF (rfont_def, 1))
581f7ac7
KH
258#define RFONT_DEF_OBJECT(rfont_def) AREF (rfont_def, 2)
259#define RFONT_DEF_SET_OBJECT(rfont_def, object) \
260 ASET ((rfont_def), 2, (object))
9dfdbc0a
KH
261/* Score of RFONT_DEF is an integer value; the lowest 8 bits represent
262 the order of listing by font backends, the higher bits represents
263 the order given by charset priority list. The smaller value is
264 preferable. */
581f7ac7
KH
265#define RFONT_DEF_SCORE(rfont_def) XINT (AREF (rfont_def, 3))
266#define RFONT_DEF_SET_SCORE(rfont_def, score) \
267 ASET ((rfont_def), 3, make_number (score))
268#define RFONT_DEF_NEW(rfont_def, font_def) \
269 do { \
270 (rfont_def) = Fmake_vector (make_number (4), Qnil); \
271 ASET ((rfont_def), 1, (font_def)); \
272 RFONT_DEF_SET_SCORE ((rfont_def), 0); \
273 } while (0)
274
275
1d5d7200
KH
276/* Return the element of FONTSET for the character C. If FONTSET is a
277 base fontset other then the default fontset and FONTSET doesn't
278 contain information for C, return the information in the default
279 fontset. */
0d407d77 280
1d5d7200
KH
281#define FONTSET_REF(fontset, c) \
282 (EQ (fontset, Vdefault_fontset) \
283 ? CHAR_TABLE_REF (fontset, c) \
284 : fontset_ref ((fontset), (c)))
0d407d77 285
afe93d01 286static Lisp_Object
971de7fb 287fontset_ref (Lisp_Object fontset, int c)
0d407d77 288{
06f76f0d
KH
289 Lisp_Object elt;
290
1d5d7200
KH
291 elt = CHAR_TABLE_REF (fontset, c);
292 if (NILP (elt) && ! EQ (fontset, Vdefault_fontset)
293 /* Don't check Vdefault_fontset for a realized fontset. */
294 && NILP (FONTSET_BASE (fontset)))
295 elt = CHAR_TABLE_REF (Vdefault_fontset, c);
0d407d77
KH
296 return elt;
297}
298
1d5d7200
KH
299/* Set elements of FONTSET for characters in RANGE to the value ELT.
300 RANGE is a cons (FROM . TO), where FROM and TO are character codes
301 specifying a range. */
302
303#define FONTSET_SET(fontset, range, elt) \
304 Fset_char_table_range ((fontset), (range), (elt))
305
0d407d77 306
1d5d7200 307/* Modify the elements of FONTSET for characters in RANGE by replacing
6bad8007 308 with ELT or adding ELT. RANGE is a cons (FROM . TO), where FROM
1d5d7200
KH
309 and TO are character codes specifying a range. If ADD is nil,
310 replace with ELT, if ADD is `prepend', prepend ELT, otherwise,
311 append ELT. */
312
cc7b6145
KH
313#define FONTSET_ADD(fontset, range, elt, add) \
314 (NILP (add) \
315 ? (NILP (range) \
316 ? (FONTSET_FALLBACK (fontset) = Fmake_vector (make_number (1), (elt))) \
317 : Fset_char_table_range ((fontset), (range), \
318 Fmake_vector (make_number (1), (elt)))) \
1d5d7200 319 : fontset_add ((fontset), (range), (elt), (add)))
0d407d77 320
b11a4ed7 321static Lisp_Object
971de7fb 322fontset_add (Lisp_Object fontset, Lisp_Object range, Lisp_Object elt, Lisp_Object add)
06f76f0d 323{
eb36588a
KH
324 Lisp_Object args[2];
325 int idx = (EQ (add, Qappend) ? 0 : 1);
326
327 args[1 - idx] = Fmake_vector (make_number (1), elt);
328
329 if (CONSP (range))
330 {
331 int from = XINT (XCAR (range));
332 int to = XINT (XCDR (range));
333 int from1, to1;
334
335 do {
5b30be1a 336 from1 = from, to1 = to;
eb36588a 337 args[idx] = char_table_ref_and_range (fontset, from, &from1, &to1);
eb36588a
KH
338 char_table_set_range (fontset, from, to1,
339 NILP (args[idx]) ? args[1 - idx]
340 : Fvconcat (2, args));
341 from = to1 + 1;
342 } while (from < to);
343 }
344 else
345 {
346 args[idx] = FONTSET_FALLBACK (fontset);
347 FONTSET_FALLBACK (fontset)
348 = NILP (args[idx]) ? args[1 - idx] : Fvconcat (2, args);
349 }
b11a4ed7 350 return Qnil;
1d5d7200
KH
351}
352
581f7ac7 353static int
971de7fb 354fontset_compare_rfontdef (const void *val1, const void *val2)
581f7ac7 355{
41ad6003
KH
356 return (RFONT_DEF_SCORE (*(Lisp_Object *) val1)
357 - RFONT_DEF_SCORE (*(Lisp_Object *) val2));
581f7ac7 358}
1d5d7200 359
ea0162a6 360/* Update FONT-GROUP which has this form:
581f7ac7
KH
361 [ CHARSET-ORDERED-LIST-TICK PREFERRED-RFONT-DEF
362 RFONT-DEF0 RFONT-DEF1 ... ]
20746fe4 363 Reorder RFONT-DEFs according to the current language, and update
581f7ac7
KH
364 CHARSET-ORDERED-LIST-TICK.
365
366 If PREFERRED_FAMILY is not nil, that family has the higher priority
367 if the encoding charsets or languages in font-specs are the same. */
368
0d407d77 369static void
971de7fb 370reorder_font_vector (Lisp_Object font_group, struct font *font)
1d5d7200 371{
41ad6003 372 Lisp_Object vec, font_object;
1d5d7200 373 int size;
581f7ac7
KH
374 int i;
375 int score_changed = 0;
1d5d7200 376
41ad6003
KH
377 if (font)
378 XSETFONT (font_object, font);
379 else
380 font_object = Qnil;
381
382 vec = XCDR (font_group);
383 size = ASIZE (vec);
384 /* Exclude the tailing nil element from the reordering. */
385 if (NILP (AREF (vec, size - 1)))
386 size--;
581f7ac7
KH
387
388 for (i = 0; i < size; i++)
6bad8007 389 {
41ad6003 390 Lisp_Object rfont_def = AREF (vec, i);
581f7ac7
KH
391 Lisp_Object font_def = RFONT_DEF_FONT_DEF (rfont_def);
392 Lisp_Object font_spec = FONT_DEF_SPEC (font_def);
41ad6003 393 int score = RFONT_DEF_SCORE (rfont_def) & 0xFF;
9dfdbc0a 394 Lisp_Object otf_spec = Ffont_get (font_spec, QCotf);
581f7ac7 395
9dfdbc0a
KH
396 if (! NILP (otf_spec))
397 /* A font-spec with :otf is preferable regardless of encoding
398 and language.. */
399 ;
400 else if (! font_match_p (font_spec, font_object))
eb152aa9 401 {
cd872f08 402 Lisp_Object encoding = FONT_DEF_ENCODING (font_def);
581f7ac7 403
cd872f08 404 if (! NILP (encoding))
41ad6003
KH
405 {
406 Lisp_Object tail;
581f7ac7 407
41ad6003
KH
408 for (tail = Vcharset_ordered_list;
409 ! EQ (tail, Vcharset_non_preferred_head) && CONSP (tail);
d311d28c 410 tail = XCDR (tail))
cd872f08 411 if (EQ (encoding, XCAR (tail)))
41ad6003 412 break;
2972b14b 413 else if (score <= min (INT_MAX, MOST_POSITIVE_FIXNUM) - 0x100)
d311d28c 414 score += 0x100;
41ad6003
KH
415 }
416 else
417 {
418 Lisp_Object lang = Ffont_get (font_spec, QClang);
419
420 if (! NILP (lang)
421 && ! EQ (lang, Vcurrent_iso639_language)
422 && (! CONSP (Vcurrent_iso639_language)
423 || NILP (Fmemq (lang, Vcurrent_iso639_language))))
424 score |= 0x100;
425 }
ea0162a6 426 }
581f7ac7 427 if (RFONT_DEF_SCORE (rfont_def) != score)
ea0162a6 428 {
581f7ac7
KH
429 RFONT_DEF_SET_SCORE (rfont_def, score);
430 score_changed = 1;
ea0162a6 431 }
6bad8007 432 }
1d5d7200 433
581f7ac7 434 if (score_changed)
41ad6003 435 qsort (XVECTOR (vec)->contents, size, sizeof (Lisp_Object),
581f7ac7 436 fontset_compare_rfontdef);
41ad6003
KH
437 XSETCAR (font_group, make_number (charset_ordered_list_tick));
438}
439
f084f942
KH
440/* Return a font-group (actually a cons (-1 . FONT-GROUP-VECTOR)) for
441 character C in FONTSET. If C is -1, return a fallback font-group.
442 If C is not -1, the value may be Qt (FONTSET doesn't have a font
ea180610 443 for C even in the fallback group), or 0 (a font for C may be found
f084f942
KH
444 only in the fallback group). */
445
41ad6003 446static Lisp_Object
3cba9369 447fontset_get_font_group (Lisp_Object fontset, int c)
41ad6003
KH
448{
449 Lisp_Object font_group;
450 Lisp_Object base_fontset;
5b30be1a 451 int from = 0, to = MAX_CHAR, i;
28e2436a 452
a54e2c05 453 eassert (! BASE_FONTSET_P (fontset));
41ad6003
KH
454 if (c >= 0)
455 font_group = CHAR_TABLE_REF (fontset, c);
456 else
457 font_group = FONTSET_FALLBACK (fontset);
458 if (! NILP (font_group))
459 return font_group;
460 base_fontset = FONTSET_BASE (fontset);
ea180610
AS
461 if (NILP (base_fontset))
462 font_group = Qnil;
463 else if (c >= 0)
41ad6003
KH
464 font_group = char_table_ref_and_range (base_fontset, c, &from, &to);
465 else
466 font_group = FONTSET_FALLBACK (base_fontset);
467 if (NILP (font_group))
f088b054 468 {
f084f942 469 font_group = make_number (0);
f088b054 470 if (c >= 0)
f084f942
KH
471 char_table_set_range (fontset, from, to, font_group);
472 return font_group;
f088b054 473 }
ea180610
AS
474 if (!VECTORP (font_group))
475 return font_group;
41ad6003
KH
476 font_group = Fcopy_sequence (font_group);
477 for (i = 0; i < ASIZE (font_group); i++)
478 if (! NILP (AREF (font_group, i)))
479 {
480 Lisp_Object rfont_def;
481
482 RFONT_DEF_NEW (rfont_def, AREF (font_group, i));
483 /* Remember the original order. */
484 RFONT_DEF_SET_SCORE (rfont_def, i);
485 ASET (font_group, i, rfont_def);
486 }
487 font_group = Fcons (make_number (-1), font_group);
488 if (c >= 0)
489 char_table_set_range (fontset, from, to, font_group);
490 else
491 FONTSET_FALLBACK (fontset) = font_group;
492 return font_group;
0d407d77
KH
493}
494
7e1a1cd9 495/* Return RFONT-DEF (vector) in the realized fontset FONTSET for the
d67f7f1a
KH
496 character C. If no font is found, return Qnil if there's a
497 possibility that the default fontset or the fallback font groups
498 have a proper font, and return Qt if not.
499
500 If a font is found but is not yet opened, open it (if FACE is not
501 NULL) or return Qnil (if FACE is NULL).
502
1c82b4b3
KH
503 ID is a charset-id that must be preferred, or -1 meaning no
504 preference.
d67f7f1a 505
ea0162a6 506 If FALLBACK is nonzero, search only fallback fonts. */
0d407d77 507
7e1a1cd9 508static Lisp_Object
971de7fb 509fontset_find_font (Lisp_Object fontset, int c, struct face *face, int id, int fallback)
0d407d77 510{
162f5458 511 Lisp_Object vec, font_group;
374bf7e4 512 int i, charset_matched = 0, found_index;
2a1ef5be
KH
513 FRAME_PTR f = (FRAMEP (FONTSET_FRAME (fontset))
514 ? XFRAME (FONTSET_FRAME (fontset)) : XFRAME (selected_frame));
a71ccf3a 515 Lisp_Object rfont_def;
0d407d77 516
41ad6003
KH
517 font_group = fontset_get_font_group (fontset, fallback ? -1 : c);
518 if (! CONSP (font_group))
bf86d09c 519 return font_group;
41ad6003
KH
520 vec = XCDR (font_group);
521 if (ASIZE (vec) == 0)
522 return Qnil;
eaa0402c 523
41ad6003 524 if (ASIZE (vec) > 1)
1d5d7200 525 {
41ad6003
KH
526 if (XINT (XCAR (font_group)) != charset_ordered_list_tick)
527 /* We have just created the font-group,
528 or the charset priorities were changed. */
529 reorder_font_vector (font_group, face->ascii_face->font);
530 if (id >= 0)
531 /* Find a spec matching with the charset ID to try at
532 first. */
533 for (i = 0; i < ASIZE (vec); i++)
534 {
0ff75233
KH
535 Lisp_Object repertory;
536
a71ccf3a 537 rfont_def = AREF (vec, i);
0ff75233
KH
538 if (NILP (rfont_def))
539 break;
540 repertory = FONT_DEF_REPERTORY (RFONT_DEF_FONT_DEF (rfont_def));
41ad6003
KH
541
542 if (XINT (repertory) == id)
eaa0402c 543 {
41ad6003 544 charset_matched = i;
581f7ac7 545 break;
41ad6003
KH
546 }
547 }
581f7ac7 548 }
1d5d7200 549
7e1a1cd9 550 /* Find the first available font in the vector of RFONT-DEF. */
41ad6003 551 for (i = 0; i < ASIZE (vec); i++)
0d407d77 552 {
a71ccf3a 553 Lisp_Object font_def;
dbf46ba6 554 Lisp_Object font_entity, font_object;
581f7ac7 555
635c75b1 556 found_index = i;
374bf7e4 557 if (i == 0)
41ad6003 558 {
374bf7e4
KH
559 if (charset_matched > 0)
560 {
635c75b1
KH
561 /* Try the element matching with the charset ID at first. */
562 found_index = charset_matched;
563 /* Make this negative so that we don't come here in the
564 next loop. */
374bf7e4 565 charset_matched = - charset_matched;
635c75b1 566 /* We must try the first element in the next loop. */
374bf7e4
KH
567 i--;
568 }
41ad6003 569 }
635c75b1 570 else if (i == - charset_matched)
374bf7e4
KH
571 {
572 /* We have already tried this element and the followings
635c75b1
KH
573 that have the same font specifications in the first
574 iteration. So, skip them all. */
374bf7e4
KH
575 rfont_def = AREF (vec, i);
576 font_def = RFONT_DEF_FONT_DEF (rfont_def);
577 for (; i + 1 < ASIZE (vec); i++)
578 {
579 rfont_def = AREF (vec, i + 1);
580 if (NILP (rfont_def))
581 break;
582 if (! EQ (RFONT_DEF_FONT_DEF (rfont_def), font_def))
583 break;
584 }
585 continue;
586 }
41ad6003 587
374bf7e4 588 rfont_def = AREF (vec, found_index);
162f5458 589 if (NILP (rfont_def))
374bf7e4 590 {
635c75b1 591 if (i < 0)
374bf7e4
KH
592 continue;
593 /* This is a sign of not to try the other fonts. */
594 return Qt;
595 }
162f5458
KH
596 if (INTEGERP (RFONT_DEF_FACE (rfont_def))
597 && XINT (RFONT_DEF_FACE (rfont_def)) < 0)
1d5d7200
KH
598 /* We couldn't open this font last time. */
599 continue;
600
162f5458 601 font_object = RFONT_DEF_OBJECT (rfont_def);
581f7ac7 602 if (NILP (font_object))
8aa07a8d 603 {
162f5458 604 font_def = RFONT_DEF_FONT_DEF (rfont_def);
d67f7f1a 605
581f7ac7
KH
606 if (! face)
607 /* We have not yet opened the font. */
608 return Qnil;
162f5458
KH
609 /* Find a font best-matching with the spec without checking
610 the support of the character C. That checking is costly,
611 and even without the checking, the found font supports C
612 in high possibility. */
581f7ac7
KH
613 font_entity = font_find_for_lface (f, face->lface,
614 FONT_DEF_SPEC (font_def), -1);
d67f7f1a 615 if (NILP (font_entity))
8b67c40a 616 {
581f7ac7 617 /* Record that no font matches the spec. */
162f5458 618 RFONT_DEF_SET_FACE (rfont_def, -1);
581f7ac7 619 continue;
d67f7f1a 620 }
ca2b2cde
KH
621 font_object = font_open_for_lface (f, font_entity, face->lface,
622 FONT_DEF_SPEC (font_def));
581f7ac7 623 if (NILP (font_object))
d67f7f1a 624 {
162f5458
KH
625 /* Something strange happened, perhaps because of a
626 Font-backend problem. Too avoid crashing, record
ee7683eb 627 that this spec is unusable. It may be better to find
162f5458
KH
628 another font of the same spec, but currently we don't
629 have such an API. */
630 RFONT_DEF_SET_FACE (rfont_def, -1);
581f7ac7 631 continue;
8aa07a8d 632 }
162f5458 633 RFONT_DEF_SET_OBJECT (rfont_def, font_object);
8aa07a8d 634 }
eb152aa9 635
581f7ac7 636 if (font_has_char (f, font_object, c))
a71ccf3a 637 goto found;
581f7ac7 638
333f9019 639 /* Find a font already opened, matching with the current spec,
162f5458
KH
640 and supporting C. */
641 font_def = RFONT_DEF_FONT_DEF (rfont_def);
374bf7e4 642 for (; found_index + 1 < ASIZE (vec); found_index++)
57e13af9 643 {
374bf7e4 644 rfont_def = AREF (vec, found_index + 1);
7d72bb82 645 if (NILP (rfont_def))
374bf7e4 646 break;
162f5458 647 if (! EQ (RFONT_DEF_FONT_DEF (rfont_def), font_def))
581f7ac7 648 break;
374bf7e4 649 font_object = RFONT_DEF_OBJECT (rfont_def);
69a8e484 650 if (! NILP (font_object) && font_has_char (f, font_object, c))
374bf7e4
KH
651 {
652 found_index++;
653 goto found;
654 }
57e13af9 655 }
162f5458
KH
656
657 /* Find a font-entity with the current spec and supporting C. */
581f7ac7
KH
658 font_entity = font_find_for_lface (f, face->lface,
659 FONT_DEF_SPEC (font_def), c);
660 if (! NILP (font_entity))
1d5d7200 661 {
162f5458
KH
662 /* We found a font. Open it and insert a new element for
663 that font in VEC. */
664 Lisp_Object new_vec;
581f7ac7 665 int j;
1d5d7200 666
581f7ac7
KH
667 font_object = font_open_for_lface (f, font_entity, face->lface,
668 Qnil);
162f5458
KH
669 if (NILP (font_object))
670 continue;
581f7ac7
KH
671 RFONT_DEF_NEW (rfont_def, font_def);
672 RFONT_DEF_SET_OBJECT (rfont_def, font_object);
162f5458 673 RFONT_DEF_SET_SCORE (rfont_def, RFONT_DEF_SCORE (rfont_def));
581f7ac7 674 new_vec = Fmake_vector (make_number (ASIZE (vec) + 1), Qnil);
374bf7e4
KH
675 found_index++;
676 for (j = 0; j < found_index; j++)
581f7ac7
KH
677 ASET (new_vec, j, AREF (vec, j));
678 ASET (new_vec, j, rfont_def);
679 for (j++; j < ASIZE (new_vec); j++)
680 ASET (new_vec, j, AREF (vec, j - 1));
162f5458 681 XSETCDR (font_group, new_vec);
a71ccf3a
KH
682 vec = new_vec;
683 goto found;
1d5d7200 684 }
374bf7e4
KH
685 if (i >= 0)
686 i = found_index;
0d407d77 687 }
d67f7f1a 688
581f7ac7 689 FONTSET_SET (fontset, make_number (c), make_number (0));
eaa0402c 690 return Qnil;
a71ccf3a
KH
691
692 found:
693 if (fallback && found_index > 0)
694 {
695 /* The order of fonts in the fallback font-group is not that
696 important, and it is better to move the found font to the
697 first of the group so that the next try will find it
698 quickly. */
699 for (i = found_index; i > 0; i--)
700 ASET (vec, i, AREF (vec, i - 1));
701 ASET (vec, 0, rfont_def);
702 }
703 return rfont_def;
1c82b4b3 704}
0d407d77 705
cc7b6145 706
1c82b4b3 707static Lisp_Object
971de7fb 708fontset_font (Lisp_Object fontset, int c, struct face *face, int id)
1c82b4b3 709{
cc6e5db1 710 Lisp_Object rfont_def, default_rfont_def IF_LINT (= Qnil);
1c82b4b3 711 Lisp_Object base_fontset;
cc7b6145 712
41ad6003 713 /* Try a font-group of FONTSET. */
b23bf85a 714 FONT_DEFERRED_LOG ("current fontset: font for", make_number (c), Qnil);
1c82b4b3 715 rfont_def = fontset_find_font (fontset, c, face, id, 0);
eaa0402c
KH
716 if (VECTORP (rfont_def))
717 return rfont_def;
f084f942
KH
718 if (NILP (rfont_def))
719 FONTSET_SET (fontset, make_number (c), make_number (0));
41ad6003
KH
720
721 /* Try a font-group of the default fontset. */
722 base_fontset = FONTSET_BASE (fontset);
723 if (! EQ (base_fontset, Vdefault_fontset))
724 {
725 if (NILP (FONTSET_DEFAULT (fontset)))
726 FONTSET_DEFAULT (fontset)
727 = make_fontset (FONTSET_FRAME (fontset), Qnil, Vdefault_fontset);
b23bf85a 728 FONT_DEFERRED_LOG ("default fontset: font for", make_number (c), Qnil);
f084f942
KH
729 default_rfont_def
730 = fontset_find_font (FONTSET_DEFAULT (fontset), c, face, id, 0);
731 if (VECTORP (default_rfont_def))
732 return default_rfont_def;
733 if (NILP (default_rfont_def))
734 FONTSET_SET (FONTSET_DEFAULT (fontset), make_number (c),
735 make_number (0));
41ad6003
KH
736 }
737
738 /* Try a fallback font-group of FONTSET. */
f084f942
KH
739 if (! EQ (rfont_def, Qt))
740 {
741 FONT_DEFERRED_LOG ("current fallback: font for", make_number (c), Qnil);
742 rfont_def = fontset_find_font (fontset, c, face, id, 1);
743 if (VECTORP (rfont_def))
744 return rfont_def;
745 /* Remember that FONTSET has no font for C. */
746 FONTSET_SET (fontset, make_number (c), Qt);
747 }
d67f7f1a 748
f084f942
KH
749 /* Try a fallback font-group of the default fontset. */
750 if (! EQ (base_fontset, Vdefault_fontset)
751 && ! EQ (default_rfont_def, Qt))
41ad6003 752 {
b23bf85a 753 FONT_DEFERRED_LOG ("default fallback: font for", make_number (c), Qnil);
41ad6003
KH
754 rfont_def = fontset_find_font (FONTSET_DEFAULT (fontset), c, face, id, 1);
755 if (VECTORP (rfont_def))
756 return rfont_def;
f084f942
KH
757 /* Remember that the default fontset has no font for C. */
758 FONTSET_SET (FONTSET_DEFAULT (fontset), make_number (c), Qt);
41ad6003
KH
759 }
760
41ad6003 761 return Qnil;
0d407d77
KH
762}
763
0d407d77 764/* Return a newly created fontset with NAME. If BASE is nil, make a
06f76f0d 765 base fontset. Otherwise make a realized fontset whose base is
0d407d77
KH
766 BASE. */
767
768static Lisp_Object
971de7fb 769make_fontset (Lisp_Object frame, Lisp_Object name, Lisp_Object base)
4ed46869 770{
1337ac77 771 Lisp_Object fontset;
0d407d77
KH
772 int size = ASIZE (Vfontset_table);
773 int id = next_fontset_id;
0d407d77
KH
774
775 /* Find a free slot in Vfontset_table. Usually, next_fontset_id is
776 the next available fontset ID. So it is expected that this loop
777 terminates quickly. In addition, as the last element of
fc8865fc 778 Vfontset_table is always nil, we don't have to check the range of
0d407d77
KH
779 id. */
780 while (!NILP (AREF (Vfontset_table, id))) id++;
781
782 if (id + 1 == size)
d311d28c 783 Vfontset_table = larger_vector (Vfontset_table, 1, -1);
4ed46869 784
11d9bd93 785 fontset = Fmake_char_table (Qfontset, Qnil);
0d407d77
KH
786
787 FONTSET_ID (fontset) = make_number (id);
06f76f0d
KH
788 if (NILP (base))
789 {
790 FONTSET_NAME (fontset) = name;
791 }
792 else
793 {
794 FONTSET_NAME (fontset) = Qnil;
795 FONTSET_FRAME (fontset) = frame;
796 FONTSET_BASE (fontset) = base;
797 }
0d407d77 798
06f76f0d 799 ASET (Vfontset_table, id, fontset);
0d407d77
KH
800 next_fontset_id = id + 1;
801 return fontset;
4ed46869
KH
802}
803
0d407d77 804\f
1d5d7200 805/********** INTERFACES TO xfaces.c, xfns.c, and dispextern.h **********/
0d407d77 806
1d5d7200 807/* Return the name of the fontset who has ID. */
0d407d77
KH
808
809Lisp_Object
971de7fb 810fontset_name (int id)
0d407d77
KH
811{
812 Lisp_Object fontset;
06f76f0d 813
0d407d77
KH
814 fontset = FONTSET_FROM_ID (id);
815 return FONTSET_NAME (fontset);
816}
817
818
1d5d7200 819/* Return the ASCII font name of the fontset who has ID. */
0d407d77
KH
820
821Lisp_Object
971de7fb 822fontset_ascii (int id)
0d407d77
KH
823{
824 Lisp_Object fontset, elt;
06f76f0d 825
0d407d77
KH
826 fontset= FONTSET_FROM_ID (id);
827 elt = FONTSET_ASCII (fontset);
8aa07a8d
KH
828 if (CONSP (elt))
829 elt = XCAR (elt);
1d5d7200 830 return elt;
0d407d77
KH
831}
832
a5c0af81 833static void
971de7fb 834free_realized_fontset (FRAME_PTR f, Lisp_Object fontset)
9459b1e9 835{
239f9db9 836#if 0
9459b1e9
KH
837 Lisp_Object tail;
838
97be3ce3
PE
839 if (0)
840 for (tail = FONTSET_OBJLIST (fontset); CONSP (tail); tail = XCDR (tail))
841 {
a54e2c05 842 eassert (FONT_OBJECT_P (XCAR (tail)));
97be3ce3
PE
843 font_close_object (f, XCAR (tail));
844 }
239f9db9 845#endif
9459b1e9 846}
0d407d77 847
06f76f0d
KH
848/* Free fontset of FACE defined on frame F. Called from
849 free_realized_face. */
0d407d77 850
4ed46869 851void
971de7fb 852free_face_fontset (FRAME_PTR f, struct face *face)
4ed46869 853{
452a78e0
KH
854 Lisp_Object fontset;
855
ff7a2223 856 fontset = FONTSET_FROM_ID (face->fontset);
581f7ac7
KH
857 if (NILP (fontset))
858 return;
a54e2c05
DA
859 eassert (! BASE_FONTSET_P (fontset));
860 eassert (f == XFRAME (FONTSET_FRAME (fontset)));
9459b1e9 861 free_realized_fontset (f, fontset);
1d5d7200 862 ASET (Vfontset_table, face->fontset, Qnil);
06f76f0d
KH
863 if (face->fontset < next_fontset_id)
864 next_fontset_id = face->fontset;
eb36588a 865 if (! NILP (FONTSET_DEFAULT (fontset)))
452a78e0 866 {
e1a14cdc 867 int id = XINT (FONTSET_ID (FONTSET_DEFAULT (fontset)));
eb152aa9 868
452a78e0 869 fontset = AREF (Vfontset_table, id);
a54e2c05
DA
870 eassert (!NILP (fontset) && ! BASE_FONTSET_P (fontset));
871 eassert (f == XFRAME (FONTSET_FRAME (fontset)));
9459b1e9 872 free_realized_fontset (f, fontset);
452a78e0
KH
873 ASET (Vfontset_table, id, Qnil);
874 if (id < next_fontset_id)
875 next_fontset_id = face->fontset;
876 }
581f7ac7 877 face->fontset = -1;
0d407d77 878}
18998710 879
0d407d77 880
239f9db9 881#if 0
e0f24100 882/* Return 1 if FACE is suitable for displaying character C.
0d407d77 883 Otherwise return 0. Called from the macro FACE_SUITABLE_FOR_CHAR_P
06f76f0d 884 when C is not an ASCII character. */
0d407d77
KH
885
886int
971de7fb 887face_suitable_for_char_p (struct face *face, int c)
0d407d77 888{
7e1a1cd9 889 Lisp_Object fontset, rfont_def;
0d407d77 890
0d407d77 891 fontset = FONTSET_FROM_ID (face->fontset);
7e1a1cd9
KH
892 rfont_def = fontset_font (fontset, c, NULL, -1);
893 return (VECTORP (rfont_def)
581f7ac7
KH
894 && INTEGERP (RFONT_DEF_FACE (rfont_def))
895 && face->id == XINT (RFONT_DEF_FACE (rfont_def)));
0d407d77 896}
239f9db9 897#endif
0d407d77
KH
898
899
900/* Return ID of face suitable for displaying character C on frame F.
40ba43b4 901 FACE must be realized for ASCII characters in advance. Called from
1d5d7200 902 the macro FACE_FOR_CHAR. */
0d407d77
KH
903
904int
971de7fb 905face_for_char (FRAME_PTR f, struct face *face, int c, int pos, Lisp_Object object)
0d407d77 906{
303d5190 907 Lisp_Object fontset, rfont_def, charset;
7e1a1cd9 908 int face_id;
6bad8007 909 int id;
1d5d7200 910
ea217c11
KH
911 /* If face->fontset is negative (that happens when no font is found
912 for face), just return face->ascii_face because we can't do
913 anything. Perhaps, we should fix the callers to assure
914 that face->fontset is always valid. */
915 if (ASCII_CHAR_P (c) || face->fontset < 0)
1d5d7200 916 return face->ascii_face->id;
0d407d77 917
a54e2c05 918 eassert (fontset_id_valid_p (face->fontset));
0d407d77 919 fontset = FONTSET_FROM_ID (face->fontset);
a54e2c05 920 eassert (!BASE_FONTSET_P (fontset));
41ad6003 921
6bad8007 922 if (pos < 0)
303d5190
KH
923 {
924 id = -1;
925 charset = Qnil;
926 }
6bad8007
KH
927 else
928 {
929 charset = Fget_char_property (make_number (pos), Qcharset, object);
b1bde622 930 if (CHARSETP (charset))
28e2436a
KH
931 {
932 Lisp_Object val;
933
a124bbb6 934 val = assq_no_quit (charset, Vfont_encoding_charset_alist);
28e2436a
KH
935 if (CONSP (val) && CHARSETP (XCDR (val)))
936 charset = XCDR (val);
937 id = XINT (CHARSET_SYMBOL_ID (charset));
938 }
b1bde622
KH
939 else
940 id = -1;
6bad8007 941 }
b59e66b3 942
7e1a1cd9
KH
943 rfont_def = fontset_font (fontset, c, face, id);
944 if (VECTORP (rfont_def))
945 {
581f7ac7
KH
946 if (INTEGERP (RFONT_DEF_FACE (rfont_def)))
947 face_id = XINT (RFONT_DEF_FACE (rfont_def));
8aa07a8d 948 else
7e1a1cd9 949 {
581f7ac7 950 Lisp_Object font_object;
7e1a1cd9 951
581f7ac7
KH
952 font_object = RFONT_DEF_OBJECT (rfont_def);
953 face_id = face_for_font (f, font_object, face);
954 RFONT_DEF_SET_FACE (rfont_def, face_id);
7e1a1cd9 955 }
7e1a1cd9 956 }
581f7ac7 957 else
7e1a1cd9 958 {
581f7ac7
KH
959 if (INTEGERP (FONTSET_NOFONT_FACE (fontset)))
960 face_id = XINT (FONTSET_NOFONT_FACE (fontset));
961 else
962 {
963 face_id = face_for_font (f, Qnil, face);
964 FONTSET_NOFONT_FACE (fontset) = make_number (face_id);
965 }
7e1a1cd9 966 }
a54e2c05 967 eassert (face_id >= 0);
581f7ac7 968 return face_id;
0d407d77
KH
969}
970
971
514cf218 972Lisp_Object
971de7fb 973font_for_char (struct face *face, int c, int pos, Lisp_Object object)
514cf218
KH
974{
975 Lisp_Object fontset, rfont_def, charset;
514cf218
KH
976 int id;
977
978 if (ASCII_CHAR_P (c))
979 {
980 Lisp_Object font_object;
981
982 XSETFONT (font_object, face->ascii_face->font);
983 return font_object;
984 }
985
a54e2c05 986 eassert (fontset_id_valid_p (face->fontset));
514cf218 987 fontset = FONTSET_FROM_ID (face->fontset);
a54e2c05 988 eassert (!BASE_FONTSET_P (fontset));
514cf218
KH
989 if (pos < 0)
990 {
991 id = -1;
992 charset = Qnil;
993 }
994 else
995 {
996 charset = Fget_char_property (make_number (pos), Qcharset, object);
b1bde622 997 if (CHARSETP (charset))
514cf218
KH
998 {
999 Lisp_Object val;
1000
9fe78804 1001 val = assq_no_quit (charset, Vfont_encoding_charset_alist);
514cf218
KH
1002 if (CONSP (val) && CHARSETP (XCDR (val)))
1003 charset = XCDR (val);
1004 id = XINT (CHARSET_SYMBOL_ID (charset));
1005 }
b1bde622
KH
1006 else
1007 id = -1;
514cf218
KH
1008 }
1009
514cf218
KH
1010 rfont_def = fontset_font (fontset, c, face, id);
1011 return (VECTORP (rfont_def)
1012 ? RFONT_DEF_OBJECT (rfont_def)
1013 : Qnil);
1014}
1015
1016
0d407d77
KH
1017/* Make a realized fontset for ASCII face FACE on frame F from the
1018 base fontset BASE_FONTSET_ID. If BASE_FONTSET_ID is -1, use the
1019 default fontset as the base. Value is the id of the new fontset.
1020 Called from realize_x_face. */
1021
1022int
971de7fb 1023make_fontset_for_ascii_face (FRAME_PTR f, int base_fontset_id, struct face *face)
0d407d77 1024{
1337ac77 1025 Lisp_Object base_fontset, fontset, frame;
0d407d77
KH
1026
1027 XSETFRAME (frame, f);
1028 if (base_fontset_id >= 0)
1029 {
1030 base_fontset = FONTSET_FROM_ID (base_fontset_id);
1031 if (!BASE_FONTSET_P (base_fontset))
1032 base_fontset = FONTSET_BASE (base_fontset);
1d5d7200
KH
1033 if (! BASE_FONTSET_P (base_fontset))
1034 abort ();
4ed46869 1035 }
0d407d77
KH
1036 else
1037 base_fontset = Vdefault_fontset;
1038
1039 fontset = make_fontset (frame, Qnil, base_fontset);
f3231837 1040 return XINT (FONTSET_ID (fontset));
0d407d77
KH
1041}
1042
0d407d77 1043\f
1d5d7200 1044
4ed46869
KH
1045/* Cache data used by fontset_pattern_regexp. The car part is a
1046 pattern string containing at least one wild card, the cdr part is
1047 the corresponding regular expression. */
1048static Lisp_Object Vcached_fontset_data;
1049
51b59d79 1050#define CACHED_FONTSET_NAME SSDATA (XCAR (Vcached_fontset_data))
7539e11f 1051#define CACHED_FONTSET_REGEX (XCDR (Vcached_fontset_data))
4ed46869
KH
1052
1053/* If fontset name PATTERN contains any wild card, return regular
1054 expression corresponding to PATTERN. */
1055
0d407d77 1056static Lisp_Object
971de7fb 1057fontset_pattern_regexp (Lisp_Object pattern)
4ed46869 1058{
51b59d79
PE
1059 if (!strchr (SSDATA (pattern), '*')
1060 && !strchr (SSDATA (pattern), '?'))
4ed46869 1061 /* PATTERN does not contain any wild cards. */
1c283e35 1062 return Qnil;
4ed46869
KH
1063
1064 if (!CONSP (Vcached_fontset_data)
51b59d79 1065 || strcmp (SSDATA (pattern), CACHED_FONTSET_NAME))
4ed46869
KH
1066 {
1067 /* We must at first update the cached data. */
6cc06608 1068 unsigned char *regex, *p0, *p1;
821bc4db 1069 int ndashes = 0, nstars = 0, nescs = 0;
6cc06608 1070
fc1062f5
KH
1071 for (p0 = SDATA (pattern); *p0; p0++)
1072 {
1073 if (*p0 == '-')
1074 ndashes++;
a653f812 1075 else if (*p0 == '*')
fc1062f5 1076 nstars++;
821bc4db
KH
1077 else if (*p0 == '['
1078 || *p0 == '.' || *p0 == '\\'
8510724d 1079 || *p0 == '+' || *p0 == '^'
821bc4db
KH
1080 || *p0 == '$')
1081 nescs++;
fc1062f5
KH
1082 }
1083
da6062e6 1084 /* If PATTERN is not full XLFD we convert "*" to ".*". Otherwise
fc1062f5
KH
1085 we convert "*" to "[^-]*" which is much faster in regular
1086 expression matching. */
1087 if (ndashes < 14)
821bc4db 1088 p1 = regex = (unsigned char *) alloca (SBYTES (pattern) + 2 * nstars + 2 * nescs + 1);
fc1062f5 1089 else
821bc4db 1090 p1 = regex = (unsigned char *) alloca (SBYTES (pattern) + 5 * nstars + 2 * nescs + 1);
4ed46869 1091
1c283e35 1092 *p1++ = '^';
6cc06608 1093 for (p0 = SDATA (pattern); *p0; p0++)
4ed46869 1094 {
a653f812 1095 if (*p0 == '*')
4ed46869 1096 {
fc1062f5
KH
1097 if (ndashes < 14)
1098 *p1++ = '.';
1099 else
1100 *p1++ = '[', *p1++ = '^', *p1++ = '-', *p1++ = ']';
1c283e35 1101 *p1++ = '*';
4ed46869 1102 }
1c283e35 1103 else if (*p0 == '?')
d96d677d 1104 *p1++ = '.';
821bc4db
KH
1105 else if (*p0 == '['
1106 || *p0 == '.' || *p0 == '\\'
8510724d 1107 || *p0 == '+' || *p0 == '^'
821bc4db
KH
1108 || *p0 == '$')
1109 *p1++ = '\\', *p1++ = *p0;
1c283e35
KH
1110 else
1111 *p1++ = *p0;
4ed46869
KH
1112 }
1113 *p1++ = '$';
1114 *p1++ = 0;
1115
51b59d79 1116 Vcached_fontset_data = Fcons (build_string (SSDATA (pattern)),
dbf46ba6 1117 build_string ((char *) regex));
4ed46869
KH
1118 }
1119
1120 return CACHED_FONTSET_REGEX;
1121}
1122
0d407d77 1123/* Return ID of the base fontset named NAME. If there's no such
a653f812
KH
1124 fontset, return -1. NAME_PATTERN specifies how to treat NAME as this:
1125 0: pattern containing '*' and '?' as wildcards
1126 1: regular expression
1127 2: literal fontset name
1128*/
0d407d77
KH
1129
1130int
971de7fb 1131fs_query_fontset (Lisp_Object name, int name_pattern)
0d407d77 1132{
1337ac77 1133 Lisp_Object tem;
0d407d77
KH
1134 int i;
1135
1136 name = Fdowncase (name);
a653f812 1137 if (name_pattern != 1)
0d407d77
KH
1138 {
1139 tem = Frassoc (name, Vfontset_alias_alist);
6bad8007
KH
1140 if (NILP (tem))
1141 tem = Fassoc (name, Vfontset_alias_alist);
0d407d77
KH
1142 if (CONSP (tem) && STRINGP (XCAR (tem)))
1143 name = XCAR (tem);
a653f812 1144 else if (name_pattern == 0)
0d407d77
KH
1145 {
1146 tem = fontset_pattern_regexp (name);
1147 if (STRINGP (tem))
1148 {
1149 name = tem;
a653f812 1150 name_pattern = 1;
0d407d77
KH
1151 }
1152 }
1153 }
1154
1155 for (i = 0; i < ASIZE (Vfontset_table); i++)
1156 {
6e1b0d8c 1157 Lisp_Object fontset, this_name;
0d407d77
KH
1158
1159 fontset = FONTSET_FROM_ID (i);
1160 if (NILP (fontset)
1161 || !BASE_FONTSET_P (fontset))
1162 continue;
1163
6e1b0d8c 1164 this_name = FONTSET_NAME (fontset);
a653f812 1165 if (name_pattern == 1
581f7ac7 1166 ? fast_string_match_ignore_case (name, this_name) >= 0
25a48bd0 1167 : !xstrcasecmp (SSDATA (name), SSDATA (this_name)))
0d407d77
KH
1168 return i;
1169 }
1170 return -1;
1171}
1172
1173
a7ca3326 1174DEFUN ("query-fontset", Fquery_fontset, Squery_fontset, 1, 2, 0,
335c5470
PJ
1175 doc: /* Return the name of a fontset that matches PATTERN.
1176The value is nil if there is no matching fontset.
1177PATTERN can contain `*' or `?' as a wildcard
1178just as X font name matching algorithm allows.
1179If REGEXPP is non-nil, PATTERN is a regular expression. */)
5842a27b 1180 (Lisp_Object pattern, Lisp_Object regexpp)
4ed46869 1181{
0d407d77
KH
1182 Lisp_Object fontset;
1183 int id;
4ed46869
KH
1184
1185 (*check_window_system_func) ();
1186
b7826503 1187 CHECK_STRING (pattern);
4ed46869 1188
d5db4077 1189 if (SCHARS (pattern) == 0)
4ed46869
KH
1190 return Qnil;
1191
0d407d77
KH
1192 id = fs_query_fontset (pattern, !NILP (regexpp));
1193 if (id < 0)
1194 return Qnil;
4ed46869 1195
0d407d77
KH
1196 fontset = FONTSET_FROM_ID (id);
1197 return FONTSET_NAME (fontset);
4ed46869
KH
1198}
1199
06f76f0d 1200/* Return a list of base fontset names matching PATTERN on frame F. */
4ed46869
KH
1201
1202Lisp_Object
971de7fb 1203list_fontsets (FRAME_PTR f, Lisp_Object pattern, int size)
4ed46869 1204{
1337ac77 1205 Lisp_Object frame, regexp, val;
0d407d77 1206 int id;
4ed46869 1207
0d407d77 1208 XSETFRAME (frame, f);
4ed46869 1209
0d407d77 1210 regexp = fontset_pattern_regexp (pattern);
4ed46869 1211 val = Qnil;
4ed46869 1212
0d407d77
KH
1213 for (id = 0; id < ASIZE (Vfontset_table); id++)
1214 {
6e1b0d8c 1215 Lisp_Object fontset, name;
0d407d77
KH
1216
1217 fontset = FONTSET_FROM_ID (id);
1218 if (NILP (fontset)
1219 || !BASE_FONTSET_P (fontset)
1220 || !EQ (frame, FONTSET_FRAME (fontset)))
1221 continue;
6e1b0d8c 1222 name = FONTSET_NAME (fontset);
0d407d77 1223
1d5d7200 1224 if (STRINGP (regexp)
6e1b0d8c 1225 ? (fast_string_match (regexp, name) < 0)
51b59d79 1226 : strcmp (SSDATA (pattern), SSDATA (name)))
0d407d77
KH
1227 continue;
1228
0d407d77 1229 val = Fcons (Fcopy_sequence (FONTSET_NAME (fontset)), val);
4ed46869
KH
1230 }
1231
1232 return val;
1233}
1234
4ed46869 1235
8f924df7 1236/* Free all realized fontsets whose base fontset is BASE. */
4ed46869 1237
06f76f0d 1238static void
971de7fb 1239free_realized_fontsets (Lisp_Object base)
06f76f0d
KH
1240{
1241 int id;
4ed46869 1242
2f034212 1243#if 0
27e20b2f
KH
1244 /* For the moment, this doesn't work because free_realized_face
1245 doesn't remove FACE from a cache. Until we find a solution, we
1246 suppress this code, and simply use Fclear_face_cache even though
1247 that is not efficient. */
06f76f0d
KH
1248 BLOCK_INPUT;
1249 for (id = 0; id < ASIZE (Vfontset_table); id++)
4ed46869 1250 {
06f76f0d 1251 Lisp_Object this = AREF (Vfontset_table, id);
0d407d77 1252
06f76f0d 1253 if (EQ (FONTSET_BASE (this), base))
0d407d77 1254 {
06f76f0d 1255 Lisp_Object tail;
4ed46869 1256
06f76f0d
KH
1257 for (tail = FONTSET_FACE_ALIST (this); CONSP (tail);
1258 tail = XCDR (tail))
1259 {
1260 FRAME_PTR f = XFRAME (FONTSET_FRAME (this));
1261 int face_id = XINT (XCDR (XCAR (tail)));
1262 struct face *face = FACE_FROM_ID (f, face_id);
4ed46869 1263
06f76f0d
KH
1264 /* Face THIS itself is also freed by the following call. */
1265 free_realized_face (f, face);
1266 }
1267 }
0d407d77 1268 }
06f76f0d 1269 UNBLOCK_INPUT;
27e20b2f 1270#else /* not 0 */
2f034212
KH
1271 /* But, we don't have to call Fclear_face_cache if no fontset has
1272 been realized from BASE. */
1273 for (id = 0; id < ASIZE (Vfontset_table); id++)
1274 {
1275 Lisp_Object this = AREF (Vfontset_table, id);
1276
985773c9 1277 if (CHAR_TABLE_P (this) && EQ (FONTSET_BASE (this), base))
2f034212
KH
1278 {
1279 Fclear_face_cache (Qt);
1280 break;
1281 }
1282 }
27e20b2f 1283#endif /* not 0 */
0d407d77 1284}
4ed46869 1285
4ed46869 1286
0d407d77
KH
1287/* Check validity of NAME as a fontset name and return the
1288 corresponding fontset. If not valid, signal an error.
a3d16f39
KH
1289
1290 If NAME is t, return Vdefault_fontset. If NAME is nil, return the
1291 fontset of *FRAME.
1292
1293 Set *FRAME to the actual frame. */
0d407d77
KH
1294
1295static Lisp_Object
971de7fb 1296check_fontset_name (Lisp_Object name, Lisp_Object *frame)
0d407d77
KH
1297{
1298 int id;
1299
a3d16f39
KH
1300 if (NILP (*frame))
1301 *frame = selected_frame;
1302 CHECK_LIVE_FRAME (*frame);
1303
0d407d77
KH
1304 if (EQ (name, Qt))
1305 return Vdefault_fontset;
a3d16f39
KH
1306 if (NILP (name))
1307 {
1308 id = FRAME_FONTSET (XFRAME (*frame));
1309 }
1310 else
1311 {
1312 CHECK_STRING (name);
1313 /* First try NAME as literal. */
1314 id = fs_query_fontset (name, 2);
1315 if (id < 0)
1316 /* For backward compatibility, try again NAME as pattern. */
1317 id = fs_query_fontset (name, 0);
1318 if (id < 0)
1319 error ("Fontset `%s' does not exist", SDATA (name));
1320 }
0d407d77
KH
1321 return FONTSET_FROM_ID (id);
1322}
4ed46869 1323
1d5d7200 1324static void
971de7fb 1325accumulate_script_ranges (Lisp_Object arg, Lisp_Object range, Lisp_Object val)
1d5d7200
KH
1326{
1327 if (EQ (XCAR (arg), val))
1328 {
1329 if (CONSP (range))
1330 XSETCDR (arg, Fcons (Fcons (XCAR (range), XCDR (range)), XCDR (arg)));
1331 else
1332 XSETCDR (arg, Fcons (Fcons (range, range), XCDR (arg)));
1333 }
1334}
1335
1336
a3d16f39
KH
1337/* Callback function for map_charset_chars in Fset_fontset_font.
1338 ARG is a vector [ FONTSET FONT_DEF ADD ASCII SCRIPT_RANGE_LIST ].
fb78e2ed 1339
a3d16f39
KH
1340 In FONTSET, set FONT_DEF in a fashion specified by ADD for
1341 characters in RANGE and ranges in SCRIPT_RANGE_LIST before RANGE.
e1dbe924 1342 The consumed ranges are popped up from SCRIPT_RANGE_LIST, and the
a3d16f39
KH
1343 new SCRIPT_RANGE_LIST is stored in ARG.
1344
1345 If ASCII is nil, don't set FONT_DEF for ASCII characters. It is
1346 assured that SCRIPT_RANGE_LIST doesn't contain ASCII in that
1347 case. */
fb78e2ed 1348
2449d4d0 1349static void
971de7fb 1350set_fontset_font (Lisp_Object arg, Lisp_Object range)
2449d4d0 1351{
a3d16f39
KH
1352 Lisp_Object fontset, font_def, add, ascii, script_range_list;
1353 int from = XINT (XCAR (range)), to = XINT (XCDR (range));
2449d4d0 1354
a3d16f39
KH
1355 fontset = AREF (arg, 0);
1356 font_def = AREF (arg, 1);
1357 add = AREF (arg, 2);
1358 ascii = AREF (arg, 3);
1359 script_range_list = AREF (arg, 4);
fb78e2ed 1360
a3d16f39
KH
1361 if (NILP (ascii) && from < 0x80)
1362 {
1363 if (to < 0x80)
fb78e2ed 1364 return;
a3d16f39
KH
1365 from = 0x80;
1366 range = Fcons (make_number (0x80), XCDR (range));
1367 }
1368
1369#define SCRIPT_FROM XINT (XCAR (XCAR (script_range_list)))
1370#define SCRIPT_TO XINT (XCDR (XCAR (script_range_list)))
1371#define POP_SCRIPT_RANGE() script_range_list = XCDR (script_range_list)
1372
1373 for (; CONSP (script_range_list) && SCRIPT_TO < from; POP_SCRIPT_RANGE ())
1374 FONTSET_ADD (fontset, XCAR (script_range_list), font_def, add);
1375 if (CONSP (script_range_list))
1376 {
1377 if (SCRIPT_FROM < from)
1378 range = Fcons (make_number (SCRIPT_FROM), XCDR (range));
1379 while (CONSP (script_range_list) && SCRIPT_TO <= to)
1380 POP_SCRIPT_RANGE ();
1381 if (CONSP (script_range_list) && SCRIPT_FROM <= to)
1382 XSETCAR (XCAR (script_range_list), make_number (to + 1));
fb78e2ed 1383 }
a3d16f39
KH
1384
1385 FONTSET_ADD (fontset, range, font_def, add);
1386 ASET (arg, 4, script_range_list);
2449d4d0
KH
1387}
1388
f57e2426 1389static void update_auto_fontset_alist (Lisp_Object, Lisp_Object);
d6490542 1390
d6aaac9e 1391
1d5d7200 1392DEFUN ("set-fontset-font", Fset_fontset_font, Sset_fontset_font, 3, 5, 0,
8f924df7 1393 doc: /*
eb36588a 1394Modify fontset NAME to use FONT-SPEC for TARGET characters.
335c5470 1395
a3d16f39
KH
1396NAME is a fontset name string, nil for the fontset of FRAME, or t for
1397the default fontset.
1398
eb36588a
KH
1399TARGET may be a cons; (FROM . TO), where FROM and TO are characters.
1400In that case, use FONT-SPEC for all characters in the range FROM and
1401TO (inclusive).
06f76f0d 1402
eb36588a
KH
1403TARGET may be a script name symbol. In that case, use FONT-SPEC for
1404all characters that belong to the script.
06f76f0d 1405
eb36588a 1406TARGET may be a charset. In that case, use FONT-SPEC for all
95318a38 1407characters in the charset.
1d5d7200 1408
eb36588a
KH
1409TARGET may be nil. In that case, use FONT-SPEC for any characters for
1410that no FONT-SPEC is specified.
1411
0fdf26e6 1412FONT-SPEC may one of these:
581f7ac7 1413 * A font-spec object made by the function `font-spec' (which see).
3dcd48dd 1414 * A cons (FAMILY . REGISTRY), where FAMILY is a font family name and
581f7ac7
KH
1415 REGISTRY is a font registry name. FAMILY may contain foundry
1416 name, and REGISTRY may contain encoding name.
00c4da0f 1417 * A font name string.
eaa0402c 1418 * nil, which explicitly specifies that there's no font for TARGET.
1d5d7200 1419
a3d16f39
KH
1420Optional 4th argument FRAME is a frame or nil for the selected frame
1421that is concerned in the case that NAME is nil.
1d5d7200
KH
1422
1423Optional 5th argument ADD, if non-nil, specifies how to add FONT-SPEC
eb36588a 1424to the font specifications for TARGET previously set. If it is
1d5d7200
KH
1425`prepend', FONT-SPEC is prepended. If it is `append', FONT-SPEC is
1426appended. By default, FONT-SPEC overrides the previous settings. */)
5842a27b 1427 (Lisp_Object name, Lisp_Object target, Lisp_Object font_spec, Lisp_Object frame, Lisp_Object add)
0d407d77 1428{
06f76f0d 1429 Lisp_Object fontset;
9683749a 1430 Lisp_Object font_def, registry, family;
1d5d7200 1431 Lisp_Object range_list;
fb78e2ed 1432 struct charset *charset = NULL;
d6490542
KH
1433 Lisp_Object fontname;
1434 int ascii_changed = 0;
0d407d77 1435
a3d16f39 1436 fontset = check_fontset_name (name, &frame);
1d5d7200 1437
d6490542 1438 fontname = Qnil;
581f7ac7 1439 if (CONSP (font_spec))
0d407d77 1440 {
581f7ac7 1441 Lisp_Object spec = Ffont_spec (0, NULL);
1d5d7200 1442
581f7ac7
KH
1443 font_parse_family_registry (XCAR (font_spec), XCDR (font_spec), spec);
1444 font_spec = spec;
d6490542 1445 fontname = Ffont_xlfd_name (font_spec, Qnil);
0890801b 1446 }
d67f7f1a 1447 else if (STRINGP (font_spec))
4ed46869 1448 {
ea0162a6
KH
1449 Lisp_Object args[2];
1450
d6490542 1451 fontname = font_spec;
ea0162a6
KH
1452 args[0] = QCname;
1453 args[1] = font_spec;
1454 font_spec = Ffont_spec (2, args);
0d407d77 1455 }
d6490542
KH
1456 else if (FONT_SPEC_P (font_spec))
1457 fontname = Ffont_xlfd_name (font_spec, Qnil);
1458 else if (! NILP (font_spec))
581f7ac7 1459 Fsignal (Qfont, list2 (build_string ("Invalid font-spec"), font_spec));
1d5d7200 1460
d67f7f1a 1461 if (! NILP (font_spec))
57e13af9 1462 {
581f7ac7
KH
1463 Lisp_Object encoding, repertory;
1464
d67f7f1a 1465 family = AREF (font_spec, FONT_FAMILY_INDEX);
581f7ac7 1466 if (! NILP (family) )
d67f7f1a
KH
1467 family = SYMBOL_NAME (family);
1468 registry = AREF (font_spec, FONT_REGISTRY_INDEX);
581f7ac7
KH
1469 if (! NILP (registry))
1470 registry = Fdowncase (SYMBOL_NAME (registry));
1471 encoding = find_font_encoding (concat3 (family, build_string ("-"),
1472 registry));
d67f7f1a
KH
1473 if (NILP (encoding))
1474 encoding = Qascii;
1475
1476 if (SYMBOLP (encoding))
1477 {
1478 CHECK_CHARSET (encoding);
1479 encoding = repertory = CHARSET_SYMBOL_ID (encoding);
1480 }
1481 else
57e13af9 1482 {
d67f7f1a
KH
1483 repertory = XCDR (encoding);
1484 encoding = XCAR (encoding);
1485 CHECK_CHARSET (encoding);
1486 encoding = CHARSET_SYMBOL_ID (encoding);
1487 if (! NILP (repertory) && SYMBOLP (repertory))
1488 {
1489 CHECK_CHARSET (repertory);
1490 repertory = CHARSET_SYMBOL_ID (repertory);
1491 }
57e13af9 1492 }
581f7ac7 1493 FONT_DEF_NEW (font_def, font_spec, encoding, repertory);
0d407d77 1494 }
d67f7f1a
KH
1495 else
1496 font_def = Qnil;
4ed46869 1497
eb36588a 1498 if (CHARACTERP (target))
d6490542
KH
1499 {
1500 if (XFASTINT (target) < 0x80)
d7a39b51 1501 error ("Can't set a font for partial ASCII range");
d6490542
KH
1502 range_list = Fcons (Fcons (target, target), Qnil);
1503 }
eb36588a 1504 else if (CONSP (target))
0d407d77 1505 {
06f76f0d
KH
1506 Lisp_Object from, to;
1507
eb36588a
KH
1508 from = Fcar (target);
1509 to = Fcdr (target);
06f76f0d
KH
1510 CHECK_CHARACTER (from);
1511 CHECK_CHARACTER (to);
d6490542
KH
1512 if (XFASTINT (from) < 0x80)
1513 {
1514 if (XFASTINT (from) != 0 || XFASTINT (to) < 0x7F)
d7a39b51 1515 error ("Can't set a font for partial ASCII range");
d6490542
KH
1516 ascii_changed = 1;
1517 }
eb36588a 1518 range_list = Fcons (target, Qnil);
4ed46869 1519 }
eb36588a 1520 else if (SYMBOLP (target) && !NILP (target))
8a9be3ac 1521 {
1d5d7200
KH
1522 Lisp_Object script_list;
1523 Lisp_Object val;
0d407d77 1524
1d5d7200
KH
1525 range_list = Qnil;
1526 script_list = XCHAR_TABLE (Vchar_script_table)->extras[0];
eb36588a 1527 if (! NILP (Fmemq (target, script_list)))
afe93d01 1528 {
d6490542
KH
1529 if (EQ (target, Qlatin))
1530 ascii_changed = 1;
eb36588a 1531 val = Fcons (target, Qnil);
1d5d7200 1532 map_char_table (accumulate_script_ranges, Qnil, Vchar_script_table,
8f924df7 1533 val);
a3d16f39 1534 range_list = Fnreverse (XCDR (val));
afe93d01 1535 }
fb78e2ed 1536 if (CHARSETP (target))
afe93d01 1537 {
d6490542
KH
1538 CHECK_CHARSET_GET_CHARSET (target, charset);
1539 if (charset->ascii_compatible_p)
1540 ascii_changed = 1;
afe93d01 1541 }
fb78e2ed 1542 else if (NILP (range_list))
1d5d7200 1543 error ("Invalid script or charset name: %s",
eb36588a 1544 SDATA (SYMBOL_NAME (target)));
8a9be3ac 1545 }
eb36588a
KH
1546 else if (NILP (target))
1547 range_list = Fcons (Qnil, Qnil);
1548 else
1549 error ("Invalid target for setting a font");
0d407d77 1550
a3d16f39
KH
1551 if (ascii_changed)
1552 {
1553 Lisp_Object val;
1554
1555 if (NILP (font_spec))
1556 error ("Can't set ASCII font to nil");
1557 val = CHAR_TABLE_REF (fontset, 0);
1558 if (! NILP (val) && EQ (add, Qappend))
1559 /* We are going to change just an additional font for ASCII. */
1560 ascii_changed = 0;
1561 }
fb78e2ed
KH
1562
1563 if (charset)
1564 {
a3d16f39
KH
1565 Lisp_Object arg;
1566
1567 arg = Fmake_vector (make_number (5), Qnil);
1568 ASET (arg, 0, fontset);
1569 ASET (arg, 1, font_def);
1570 ASET (arg, 2, add);
1571 ASET (arg, 3, ascii_changed ? Qt : Qnil);
1572 ASET (arg, 4, range_list);
fb78e2ed 1573
a3d16f39 1574 map_charset_chars (set_fontset_font, Qnil, arg, charset,
fb78e2ed
KH
1575 CHARSET_MIN_CODE (charset),
1576 CHARSET_MAX_CODE (charset));
a3d16f39 1577 range_list = AREF (arg, 4);
fb78e2ed 1578 }
1d5d7200
KH
1579 for (; CONSP (range_list); range_list = XCDR (range_list))
1580 FONTSET_ADD (fontset, XCAR (range_list), font_def, add);
4ed46869 1581
d6490542
KH
1582 if (ascii_changed)
1583 {
7519b8cd 1584 Lisp_Object tail, fr, alist;
d6490542
KH
1585 int fontset_id = XINT (FONTSET_ID (fontset));
1586
d6490542
KH
1587 FONTSET_ASCII (fontset) = fontname;
1588 name = FONTSET_NAME (fontset);
7519b8cd 1589 FOR_EACH_FRAME (tail, fr)
d6490542 1590 {
7519b8cd 1591 FRAME_PTR f = XFRAME (fr);
d6490542 1592 Lisp_Object font_object;
0875632e 1593 struct face *face;
d6490542 1594
0875632e 1595 if (FRAME_INITIAL_P (f) || FRAME_TERMCAP_P (f))
d6490542
KH
1596 continue;
1597 if (fontset_id != FRAME_FONTSET (f))
1598 continue;
0875632e
KH
1599 face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
1600 if (face)
1601 font_object = font_load_for_lface (f, face->lface, font_spec);
1602 else
1603 font_object = font_open_by_spec (f, font_spec);
d6490542
KH
1604 if (! NILP (font_object))
1605 {
1606 update_auto_fontset_alist (font_object, fontset);
0875632e 1607 alist = Fcons (Fcons (Qfont, Fcons (name, font_object)), Qnil);
7519b8cd 1608 Fmodify_frame_parameters (fr, alist);
d6490542
KH
1609 }
1610 }
1611 }
1612
0875632e
KH
1613 /* Free all realized fontsets whose base is FONTSET. This way, the
1614 specified character(s) are surely redisplayed by a correct
1615 font. */
1616 free_realized_fontsets (fontset);
1617
4ed46869
KH
1618 return Qnil;
1619}
1620
06f76f0d
KH
1621
1622DEFUN ("new-fontset", Fnew_fontset, Snew_fontset, 2, 2, 0,
1623 doc: /* Create a new fontset NAME from font information in FONTLIST.
1624
1d5d7200 1625FONTLIST is an alist of scripts vs the corresponding font specification list.
d6aaac9e
KH
1626Each element of FONTLIST has the form (SCRIPT FONT-SPEC ...), where a
1627character of SCRIPT is displayed by a font that matches one of
1628FONT-SPEC.
06f76f0d 1629
d6aaac9e
KH
1630SCRIPT is a symbol that appears in the first extra slot of the
1631char-table `char-script-table'.
06f76f0d 1632
1d5d7200
KH
1633FONT-SPEC is a vector, a cons, or a string. See the documentation of
1634`set-fontset-font' for the meaning. */)
5842a27b 1635 (Lisp_Object name, Lisp_Object fontlist)
06f76f0d 1636{
1d5d7200 1637 Lisp_Object fontset;
1d5d7200 1638 int id;
06f76f0d
KH
1639
1640 CHECK_STRING (name);
1641 CHECK_LIST (fontlist);
1642
581f7ac7 1643 name = Fdowncase (name);
1d5d7200
KH
1644 id = fs_query_fontset (name, 0);
1645 if (id < 0)
0d407d77 1646 {
581f7ac7
KH
1647 Lisp_Object font_spec = Ffont_spec (0, NULL);
1648 Lisp_Object short_name;
5f2d79e0 1649 char xlfd[256];
581f7ac7
KH
1650 int len;
1651
51b59d79 1652 if (font_parse_xlfd (SSDATA (name), font_spec) < 0)
d6aaac9e 1653 error ("Fontset name must be in XLFD format");
581f7ac7 1654 short_name = AREF (font_spec, FONT_REGISTRY_INDEX);
51b59d79 1655 if (strncmp (SSDATA (SYMBOL_NAME (short_name)), "fontset-", 8)
581f7ac7
KH
1656 || SBYTES (SYMBOL_NAME (short_name)) < 9)
1657 error ("Registry field of fontset name must be \"fontset-*\"");
1658 Vfontset_alias_alist = Fcons (Fcons (name, SYMBOL_NAME (short_name)),
1659 Vfontset_alias_alist);
1660 ASET (font_spec, FONT_REGISTRY_INDEX, Qiso8859_1);
d6aaac9e 1661 fontset = make_fontset (Qnil, name, Qnil);
5f2d79e0
KH
1662 len = font_unparse_xlfd (font_spec, 0, xlfd, 256);
1663 if (len < 0)
1664 error ("Invalid fontset name (perhaps too long): %s", SDATA (name));
581f7ac7 1665 FONTSET_ASCII (fontset) = make_unibyte_string (xlfd, len);
d6aaac9e 1666 }
1d5d7200
KH
1667 else
1668 {
8510724d 1669 fontset = FONTSET_FROM_ID (id);
1d5d7200
KH
1670 free_realized_fontsets (fontset);
1671 Fset_char_table_range (fontset, Qt, Qnil);
0d407d77 1672 }
4ed46869 1673
1d5d7200
KH
1674 for (; ! NILP (fontlist); fontlist = Fcdr (fontlist))
1675 {
1676 Lisp_Object elt, script;
1677
1678 elt = Fcar (fontlist);
1679 script = Fcar (elt);
cc36ddbf
KH
1680 elt = Fcdr (elt);
1681 if (CONSP (elt) && (NILP (XCDR (elt)) || CONSP (XCDR (elt))))
1682 for (; CONSP (elt); elt = XCDR (elt))
1683 Fset_fontset_font (name, script, XCAR (elt), Qnil, Qappend);
1684 else
1685 Fset_fontset_font (name, script, elt, Qnil, Qappend);
1d5d7200 1686 }
06f76f0d
KH
1687 return name;
1688}
1689
1690
452a78e0 1691/* Alist of automatically created fontsets. Each element is a cons
581f7ac7 1692 (FONT-SPEC . FONTSET-ID). */
452a78e0 1693static Lisp_Object auto_fontset_alist;
d6aaac9e 1694
d6490542 1695/* Number of automatically created fontsets. */
d311d28c 1696static ptrdiff_t num_auto_fontsets;
d6490542 1697
0b381c7e 1698/* Return a fontset synthesized from FONT-OBJECT. This is called from
d8d2f142
KH
1699 x_new_font when FONT-OBJECT is used for the default ASCII font of a
1700 frame, and the returned fontset is used for the default fontset of
1701 that frame. The fontset specifies a font of the same registry as
1702 FONT-OBJECT for all characters in the repertory of the registry
1703 (see Vfont_encoding_alist). If the repertory is not known, the
1704 fontset specifies the font for all Latin characters assuming that a
1705 user intends to use FONT-OBJECT for Latin characters. */
d6490542 1706
d6aaac9e 1707int
971de7fb 1708fontset_from_font (Lisp_Object font_object)
8aa07a8d 1709{
03ef560c 1710 Lisp_Object font_name = font_get_name (font_object);
92470028 1711 Lisp_Object font_spec = copy_font_spec (font_object);
d6490542 1712 Lisp_Object registry = AREF (font_spec, FONT_REGISTRY_INDEX);
581f7ac7
KH
1713 Lisp_Object fontset_spec, alias, name, fontset;
1714 Lisp_Object val;
8aa07a8d 1715
581f7ac7
KH
1716 val = assoc_no_quit (font_spec, auto_fontset_alist);
1717 if (CONSP (val))
1718 return XINT (FONTSET_ID (XCDR (val)));
d6490542 1719 if (num_auto_fontsets++ == 0)
581f7ac7 1720 alias = intern ("fontset-startup");
03ef560c
KH
1721 else
1722 {
d311d28c 1723 char temp[sizeof "fontset-auto" + INT_STRLEN_BOUND (ptrdiff_t)];
8aa07a8d 1724
d311d28c 1725 sprintf (temp, "fontset-auto%"pD"d", num_auto_fontsets - 1);
581f7ac7 1726 alias = intern (temp);
03ef560c 1727 }
92470028 1728 fontset_spec = copy_font_spec (font_spec);
581f7ac7 1729 ASET (fontset_spec, FONT_REGISTRY_INDEX, alias);
7ae2e7f0 1730 name = Ffont_xlfd_name (fontset_spec, Qnil);
03ef560c 1731 if (NILP (name))
581f7ac7 1732 abort ();
03ef560c 1733 fontset = make_fontset (Qnil, name, Qnil);
581f7ac7
KH
1734 Vfontset_alias_alist = Fcons (Fcons (name, SYMBOL_NAME (alias)),
1735 Vfontset_alias_alist);
1736 alias = Fdowncase (AREF (font_object, FONT_NAME_INDEX));
1737 Vfontset_alias_alist = Fcons (Fcons (name, alias), Vfontset_alias_alist);
1738 auto_fontset_alist = Fcons (Fcons (font_spec, fontset), auto_fontset_alist);
d8d2f142
KH
1739 font_spec = Ffont_spec (0, NULL);
1740 ASET (font_spec, FONT_REGISTRY_INDEX, registry);
1741 {
1742 Lisp_Object target = find_font_encoding (SYMBOL_NAME (registry));
1743
1744 if (CONSP (target))
1745 target = XCDR (target);
1746 if (! CHARSETP (target))
1747 target = Qlatin;
1748 Fset_fontset_font (name, target, font_spec, Qnil, Qnil);
1749 Fset_fontset_font (name, Qnil, font_spec, Qnil, Qnil);
1750 }
1751
d6490542 1752 FONTSET_ASCII (fontset) = font_name;
edfda783 1753
03ef560c 1754 return XINT (FONTSET_ID (fontset));
8aa07a8d
KH
1755}
1756
d6490542
KH
1757
1758/* Update auto_fontset_alist for FONTSET. When an ASCII font of
1759 FONTSET is changed, we delete an entry of FONTSET if any from
1760 auto_fontset_alist so that FONTSET is not re-used by
1761 fontset_from_font. */
1762
1763static void
971de7fb 1764update_auto_fontset_alist (Lisp_Object font_object, Lisp_Object fontset)
d6490542
KH
1765{
1766 Lisp_Object prev, tail;
1767
1768 for (prev = Qnil, tail = auto_fontset_alist; CONSP (tail);
1769 prev = tail, tail = XCDR (tail))
1770 if (EQ (fontset, XCDR (XCAR (tail))))
1771 {
1772 if (NILP (prev))
1773 auto_fontset_alist = XCDR (tail);
1774 else
1775 XSETCDR (prev, XCDR (tail));
1776 break;
1777 }
1778}
1779
1780
fe44f009
KH
1781/* Return a cons (FONT-OBJECT . GLYPH-CODE).
1782 FONT-OBJECT is the font for the character at POSITION in the current
1ff005e1 1783 buffer. This is computed from all the text properties and overlays
09e80d9f 1784 that apply to POSITION. POSITION may be nil, in which case,
fe44f009 1785 FONT-SPEC is the font for displaying the character CH with the
cf14fd6e
KH
1786 default face.
1787
92c15c34
KH
1788 GLYPH-CODE is the glyph code in the font to use for the character.
1789
1790 If the 2nd optional arg CH is non-nil, it is a character to check
1791 the font instead of the character at POSITION.
1792
1793 It returns nil in the following cases:
1ff005e1
KH
1794
1795 (1) The window system doesn't have a font for the character (thus
1796 it is displayed by an empty box).
1797
1798 (2) The character code is invalid.
1799
cf14fd6e
KH
1800 (3) If POSITION is not nil, and the current buffer is not displayed
1801 in any window.
1ff005e1
KH
1802
1803 In addition, the returned font name may not take into account of
1804 such redisplay engine hooks as what used in jit-lock-mode if
1805 POSITION is currently not visible. */
1806
1807
92c15c34 1808DEFUN ("internal-char-font", Finternal_char_font, Sinternal_char_font, 1, 2, 0,
335c5470 1809 doc: /* For internal use only. */)
5842a27b 1810 (Lisp_Object position, Lisp_Object ch)
1ff005e1 1811{
d311d28c 1812 ptrdiff_t pos, pos_byte, dummy;
1ff005e1
KH
1813 int face_id;
1814 int c;
1ff005e1
KH
1815 struct frame *f;
1816 struct face *face;
1817
cf14fd6e 1818 if (NILP (position))
92c15c34
KH
1819 {
1820 CHECK_CHARACTER (ch);
1821 c = XINT (ch);
cf14fd6e 1822 f = XFRAME (selected_frame);
f2cec7a9 1823 face_id = lookup_basic_face (f, DEFAULT_FACE_ID);
327719ee 1824 pos = -1;
cf14fd6e
KH
1825 }
1826 else
1827 {
f0397f5a 1828 Lisp_Object window;
cf14fd6e
KH
1829 struct window *w;
1830
1831 CHECK_NUMBER_COERCE_MARKER (position);
d311d28c 1832 if (! (BEGV <= XINT (position) && XINT (position) < ZV))
cf14fd6e 1833 args_out_of_range_3 (position, make_number (BEGV), make_number (ZV));
d311d28c 1834 pos = XINT (position);
cf14fd6e
KH
1835 pos_byte = CHAR_TO_BYTE (pos);
1836 if (NILP (ch))
1837 c = FETCH_CHAR (pos_byte);
1838 else
1839 {
1840 CHECK_NATNUM (ch);
1841 c = XINT (ch);
1842 }
1843 window = Fget_buffer_window (Fcurrent_buffer (), Qnil);
1844 if (NILP (window))
1845 return Qnil;
1846 w = XWINDOW (window);
1847 f = XFRAME (w->frame);
6970f632
CY
1848 face_id = face_at_buffer_position (w, pos, -1, -1, &dummy,
1849 pos + 100, 0, -1);
92c15c34 1850 }
2638320e 1851 if (! CHAR_VALID_P (c))
1ff005e1 1852 return Qnil;
327719ee 1853 face_id = FACE_FOR_CHAR (f, FACE_FROM_ID (f, face_id), c, pos, Qnil);
1ff005e1 1854 face = FACE_FROM_ID (f, face_id);
581f7ac7 1855 if (face->font)
8aa07a8d 1856 {
fe44f009
KH
1857 unsigned code = face->font->driver->encode_char (face->font, c);
1858 Lisp_Object font_object;
581f7ac7
KH
1859
1860 if (code == FONT_INVALID_CODE)
1861 return Qnil;
fe44f009 1862 XSETFONT (font_object, face->font);
be44ca6c 1863 return Fcons (font_object, INTEGER_TO_CONS (code));
92c15c34
KH
1864 }
1865 return Qnil;
1ff005e1
KH
1866}
1867
1868
1d5d7200
KH
1869DEFUN ("fontset-info", Ffontset_info, Sfontset_info, 1, 2, 0,
1870 doc: /* Return information about a fontset FONTSET on frame FRAME.
e2b45cf9 1871
a3d16f39
KH
1872FONTSET is a fontset name string, nil for the fontset of FRAME, or t
1873for the default fontset. FRAME nil means the selected frame.
1ff005e1 1874
a3d16f39 1875The value is a char-table whose elements have this form:
1ff005e1 1876
a3d16f39 1877 ((FONT OPENED-FONT ...) ...)
1ff005e1 1878
a3d16f39 1879FONT is a name of font specified for a range of characters.
1ff005e1 1880
d6aaac9e 1881OPENED-FONT is a name of a font actually opened.
1ff005e1 1882
a3d16f39
KH
1883The char-table has one extra slot. If FONTSET is not the default
1884fontset, the value the extra slot is a char-table containing the
1885information about the derived fonts from the default fontset. The
1886format is the same as above. */)
5842a27b 1887 (Lisp_Object fontset, Lisp_Object frame)
4ed46869 1888{
cc7b6145
KH
1889 Lisp_Object *realized[2], fontsets[2], tables[2];
1890 Lisp_Object val, elt;
1891 int c, i, j, k;
fc8865fc 1892
4ed46869
KH
1893 (*check_window_system_func) ();
1894
a3d16f39 1895 fontset = check_fontset_name (fontset, &frame);
4ed46869 1896
1d5d7200
KH
1897 /* Recode fontsets realized on FRAME from the base fontset FONTSET
1898 in the table `realized'. */
cc7b6145
KH
1899 realized[0] = (Lisp_Object *) alloca (sizeof (Lisp_Object)
1900 * ASIZE (Vfontset_table));
1901 for (i = j = 0; i < ASIZE (Vfontset_table); i++)
0d407d77 1902 {
1ff005e1
KH
1903 elt = FONTSET_FROM_ID (i);
1904 if (!NILP (elt)
1d5d7200
KH
1905 && EQ (FONTSET_BASE (elt), fontset)
1906 && EQ (FONTSET_FRAME (elt), frame))
cc7b6145 1907 realized[0][j++] = elt;
0d407d77 1908 }
cc7b6145 1909 realized[0][j] = Qnil;
4ed46869 1910
cc7b6145
KH
1911 realized[1] = (Lisp_Object *) alloca (sizeof (Lisp_Object)
1912 * ASIZE (Vfontset_table));
1913 for (i = j = 0; ! NILP (realized[0][i]); i++)
1914 {
1915 elt = FONTSET_DEFAULT (realized[0][i]);
1916 if (! NILP (elt))
1917 realized[1][j++] = elt;
1918 }
1919 realized[1][j] = Qnil;
1920
1921 tables[0] = Fmake_char_table (Qfontset_info, Qnil);
cc7b6145 1922 fontsets[0] = fontset;
348db3dd 1923 if (!EQ (fontset, Vdefault_fontset))
a3d16f39
KH
1924 {
1925 tables[1] = Fmake_char_table (Qnil, Qnil);
1926 XCHAR_TABLE (tables[0])->extras[0] = tables[1];
1927 fontsets[1] = Vdefault_fontset;
1928 }
e2b45cf9 1929
1d5d7200
KH
1930 /* Accumulate information of the fontset in TABLE. The format of
1931 each element is ((FONT-SPEC OPENED-FONT ...) ...). */
cc7b6145 1932 for (k = 0; k <= 1; k++)
0d407d77 1933 {
cc7b6145 1934 for (c = 0; c <= MAX_CHAR; )
d6aaac9e 1935 {
5b30be1a 1936 int from = c, to = MAX_5_BYTE_CHAR;
0d407d77 1937
cc7b6145
KH
1938 if (c <= MAX_5_BYTE_CHAR)
1939 {
1940 val = char_table_ref_and_range (fontsets[k], c, &from, &to);
cc7b6145
KH
1941 }
1942 else
1943 {
1944 val = FONTSET_FALLBACK (fontsets[k]);
1945 to = MAX_CHAR;
1946 }
d6aaac9e 1947 if (VECTORP (val))
0d407d77 1948 {
d6aaac9e
KH
1949 Lisp_Object alist;
1950
1951 /* At first, set ALIST to ((FONT-SPEC) ...). */
1952 for (alist = Qnil, i = 0; i < ASIZE (val); i++)
581f7ac7
KH
1953 if (! NILP (AREF (val, i)))
1954 alist = Fcons (Fcons (FONT_DEF_SPEC (AREF (val, i)), Qnil),
1955 alist);
d6aaac9e
KH
1956 alist = Fnreverse (alist);
1957
660100f3 1958 /* Then store opened font names to cdr of each elements. */
cc7b6145 1959 for (i = 0; ! NILP (realized[k][i]); i++)
1ff005e1 1960 {
cc7b6145
KH
1961 if (c <= MAX_5_BYTE_CHAR)
1962 val = FONTSET_REF (realized[k][i], c);
1963 else
1964 val = FONTSET_FALLBACK (realized[k][i]);
a3d16f39 1965 if (! CONSP (val) || ! VECTORP (XCDR (val)))
d6aaac9e 1966 continue;
a3d16f39
KH
1967 /* VAL: (int . [[FACE-ID FONT-DEF FONT-OBJECT int] ... ]) */
1968 val = XCDR (val);
1969 for (j = 0; j < ASIZE (val); j++)
3d4448a8 1970 {
581f7ac7
KH
1971 elt = AREF (val, j);
1972 if (FONT_OBJECT_P (RFONT_DEF_OBJECT (elt)))
1973 {
1974 Lisp_Object font_object = RFONT_DEF_OBJECT (elt);
1975 Lisp_Object slot, name;
1976
1977 slot = Fassq (RFONT_DEF_SPEC (elt), alist);
1978 name = AREF (font_object, FONT_NAME_INDEX);
1979 if (NILP (Fmember (name, XCDR (slot))))
1980 nconc2 (slot, Fcons (name, Qnil));
1981 }
3d4448a8 1982 }
1ff005e1 1983 }
d6aaac9e
KH
1984
1985 /* Store ALIST in TBL for characters C..TO. */
cc7b6145
KH
1986 if (c <= MAX_5_BYTE_CHAR)
1987 char_table_set_range (tables[k], c, to, alist);
1988 else
1989 XCHAR_TABLE (tables[k])->defalt = alist;
581f7ac7
KH
1990
1991 /* At last, change each elements to font names. */
1992 for (; CONSP (alist); alist = XCDR (alist))
1993 {
1994 elt = XCAR (alist);
7ae2e7f0 1995 XSETCAR (elt, Ffont_xlfd_name (XCAR (elt), Qnil));
581f7ac7 1996 }
0d407d77 1997 }
d6aaac9e 1998 c = to + 1;
0d407d77 1999 }
348db3dd 2000 if (EQ (fontset, Vdefault_fontset))
a3d16f39 2001 break;
0d407d77 2002 }
a921395d 2003
cc7b6145 2004 return tables[0];
4ed46869
KH
2005}
2006
1d5d7200 2007
0fdf26e6 2008DEFUN ("fontset-font", Ffontset_font, Sfontset_font, 2, 3, 0,
335c5470 2009 doc: /* Return a font name pattern for character CH in fontset NAME.
0fdf26e6 2010If NAME is t, find a pattern in the default fontset.
5fc05db0 2011If NAME is nil, find a pattern in the fontset of the selected frame.
0fdf26e6
KH
2012
2013The value has the form (FAMILY . REGISTRY), where FAMILY is a font
2014family name and REGISTRY is a font registry name. This is actually
2015the first font name pattern for CH in the fontset or in the default
2016fontset.
2017
2018If the 2nd optional arg ALL is non-nil, return a list of all font name
2019patterns. */)
5842a27b 2020 (Lisp_Object name, Lisp_Object ch, Lisp_Object all)
0d407d77 2021{
1337ac77 2022 int c;
0fdf26e6
KH
2023 Lisp_Object fontset, elt, list, repertory, val;
2024 int i, j;
a3d16f39 2025 Lisp_Object frame;
0d407d77 2026
a3d16f39
KH
2027 frame = Qnil;
2028 fontset = check_fontset_name (name, &frame);
0d407d77 2029
06f76f0d 2030 CHECK_CHARACTER (ch);
0d407d77 2031 c = XINT (ch);
0fdf26e6
KH
2032 list = Qnil;
2033 while (1)
2034 {
2035 for (i = 0, elt = FONTSET_REF (fontset, c); i < 2;
2036 i++, elt = FONTSET_FALLBACK (fontset))
2037 if (VECTORP (elt))
2038 for (j = 0; j < ASIZE (elt); j++)
2039 {
a124bbb6
KH
2040 Lisp_Object family, registry;
2041
0fdf26e6 2042 val = AREF (elt, j);
5fc05db0 2043 if (NILP (val))
563a866e 2044 return Qnil;
0fdf26e6
KH
2045 repertory = AREF (val, 1);
2046 if (INTEGERP (repertory))
2047 {
2048 struct charset *charset = CHARSET_FROM_ID (XINT (repertory));
2049
2050 if (! CHAR_CHARSET_P (c, charset))
2051 continue;
2052 }
2053 else if (CHAR_TABLE_P (repertory))
2054 {
2055 if (NILP (CHAR_TABLE_REF (repertory, c)))
2056 continue;
2057 }
2058 val = AREF (val, 0);
a124bbb6
KH
2059 /* VAL is a FONT-SPEC */
2060 family = AREF (val, FONT_FAMILY_INDEX);
2061 if (! NILP (family))
2062 family = SYMBOL_NAME (family);
2063 registry = AREF (val, FONT_REGISTRY_INDEX);
2064 if (! NILP (registry))
2065 registry = SYMBOL_NAME (registry);
2066 val = Fcons (family, registry);
0fdf26e6
KH
2067 if (NILP (all))
2068 return val;
2069 list = Fcons (val, list);
2070 }
2071 if (EQ (fontset, Vdefault_fontset))
2072 break;
2073 fontset = Vdefault_fontset;
2074 }
2075 return (Fnreverse (list));
0d407d77 2076}
0d407d77
KH
2077
2078DEFUN ("fontset-list", Ffontset_list, Sfontset_list, 0, 0, 0,
335c5470 2079 doc: /* Return a list of all defined fontset names. */)
5842a27b 2080 (void)
0d407d77
KH
2081{
2082 Lisp_Object fontset, list;
2083 int i;
2084
2085 list = Qnil;
2086 for (i = 0; i < ASIZE (Vfontset_table); i++)
2087 {
2088 fontset = FONTSET_FROM_ID (i);
2089 if (!NILP (fontset)
2090 && BASE_FONTSET_P (fontset))
2091 list = Fcons (FONTSET_NAME (fontset), list);
2092 }
1ff005e1 2093
0d407d77
KH
2094 return list;
2095}
2096
452a78e0 2097
a54e2c05 2098#ifdef ENABLE_CHECKING
452a78e0 2099
8a10d76c
PE
2100Lisp_Object dump_fontset (Lisp_Object) EXTERNALLY_VISIBLE;
2101
452a78e0 2102Lisp_Object
ef1b0ba7 2103dump_fontset (Lisp_Object fontset)
452a78e0
KH
2104{
2105 Lisp_Object vec;
2106
2107 vec = Fmake_vector (make_number (3), Qnil);
2108 ASET (vec, 0, FONTSET_ID (fontset));
2109
2110 if (BASE_FONTSET_P (fontset))
2111 {
2112 ASET (vec, 1, FONTSET_NAME (fontset));
2113 }
2114 else
2115 {
2116 Lisp_Object frame;
2117
2118 frame = FONTSET_FRAME (fontset);
2119 if (FRAMEP (frame))
2120 {
2121 FRAME_PTR f = XFRAME (frame);
2122
2123 if (FRAME_LIVE_P (f))
1c82b4b3
KH
2124 ASET (vec, 1,
2125 Fcons (FONTSET_NAME (FONTSET_BASE (fontset)), f->name));
452a78e0 2126 else
1c82b4b3
KH
2127 ASET (vec, 1,
2128 Fcons (FONTSET_NAME (FONTSET_BASE (fontset)), Qnil));
452a78e0 2129 }
eb36588a
KH
2130 if (!NILP (FONTSET_DEFAULT (fontset)))
2131 ASET (vec, 2, FONTSET_ID (FONTSET_DEFAULT (fontset)));
452a78e0
KH
2132 }
2133 return vec;
2134}
2135
a7ca3326 2136DEFUN ("fontset-list-all", Ffontset_list_all, Sfontset_list_all, 0, 0, 0,
452a78e0 2137 doc: /* Return a brief summary of all fontsets for debug use. */)
5842a27b 2138 (void)
452a78e0
KH
2139{
2140 Lisp_Object val;
2141 int i;
2142
2143 for (i = 0, val = Qnil; i < ASIZE (Vfontset_table); i++)
2144 if (! NILP (AREF (Vfontset_table, i)))
2145 val = Fcons (dump_fontset (AREF (Vfontset_table, i)), val);
2146 return (Fnreverse (val));
2147}
a54e2c05 2148#endif /* ENABLE_CHECKING */
452a78e0 2149
dfcf069d 2150void
971de7fb 2151syms_of_fontset (void)
4ed46869 2152{
1d5d7200 2153 DEFSYM (Qfontset, "fontset");
eb36588a 2154 Fput (Qfontset, Qchar_table_extra_slots, make_number (9));
d6aaac9e
KH
2155 DEFSYM (Qfontset_info, "fontset-info");
2156 Fput (Qfontset_info, Qchar_table_extra_slots, make_number (1));
4ed46869 2157
1d5d7200
KH
2158 DEFSYM (Qprepend, "prepend");
2159 DEFSYM (Qappend, "append");
c3fb88cc 2160 DEFSYM (Qlatin, "latin");
4ed46869
KH
2161
2162 Vcached_fontset_data = Qnil;
2163 staticpro (&Vcached_fontset_data);
2164
0d407d77
KH
2165 Vfontset_table = Fmake_vector (make_number (32), Qnil);
2166 staticpro (&Vfontset_table);
0d407d77
KH
2167
2168 Vdefault_fontset = Fmake_char_table (Qfontset, Qnil);
2169 staticpro (&Vdefault_fontset);
1ff005e1
KH
2170 FONTSET_ID (Vdefault_fontset) = make_number (0);
2171 FONTSET_NAME (Vdefault_fontset)
d67b4f80 2172 = make_pure_c_string ("-*-*-*-*-*-*-*-*-*-*-*-*-fontset-default");
ff7a2223 2173 ASET (Vfontset_table, 0, Vdefault_fontset);
1ff005e1 2174 next_fontset_id = 1;
4ed46869 2175
452a78e0
KH
2176 auto_fontset_alist = Qnil;
2177 staticpro (&auto_fontset_alist);
2178
29208e82 2179 DEFVAR_LISP ("font-encoding-charset-alist", Vfont_encoding_charset_alist,
28e2436a
KH
2180 doc: /*
2181Alist of charsets vs the charsets to determine the preferred font encoding.
eb152aa9 2182Each element looks like (CHARSET . ENCODING-CHARSET),
28e2436a
KH
2183where ENCODING-CHARSET is a charset registered in the variable
2184`font-encoding-alist' as ENCODING.
2185
2186When a text has a property `charset' and the value is CHARSET, a font
2187whose encoding corresponds to ENCODING-CHARSET is preferred. */);
2188 Vfont_encoding_charset_alist = Qnil;
2189
29208e82 2190 DEFVAR_LISP ("use-default-ascent", Vuse_default_ascent,
1d5d7200
KH
2191 doc: /*
2192Char table of characters whose ascent values should be ignored.
335c5470 2193If an entry for a character is non-nil, the ascent value of the glyph
eb152aa9 2194is assumed to be specified by _MULE_DEFAULT_ASCENT property of a font.
335c5470
PJ
2195
2196This affects how a composite character which contains
2197such a character is displayed on screen. */);
2aeafb78
KH
2198 Vuse_default_ascent = Qnil;
2199
29208e82 2200 DEFVAR_LISP ("ignore-relative-composition", Vignore_relative_composition,
1d5d7200 2201 doc: /*
eb152aa9 2202Char table of characters which are not composed relatively.
335c5470
PJ
2203If an entry for a character is non-nil, a composition sequence
2204which contains that character is displayed so that
2205the glyph of that character is put without considering
2206an ascent and descent value of a previous character. */);
810abb87 2207 Vignore_relative_composition = Qnil;
6a7e6d80 2208
29208e82 2209 DEFVAR_LISP ("alternate-fontname-alist", Valternate_fontname_alist,
335c5470
PJ
2210 doc: /* Alist of fontname vs list of the alternate fontnames.
2211When a specified font name is not found, the corresponding
2212alternate fontnames (if any) are tried instead. */);
01d4b817 2213 Valternate_fontname_alist = Qnil;
8c83e4f9 2214
29208e82 2215 DEFVAR_LISP ("fontset-alias-alist", Vfontset_alias_alist,
335c5470 2216 doc: /* Alist of fontset names vs the aliases. */);
1ff005e1 2217 Vfontset_alias_alist = Fcons (Fcons (FONTSET_NAME (Vdefault_fontset),
d67b4f80 2218 make_pure_c_string ("fontset-default")),
1ff005e1 2219 Qnil);
1c283e35 2220
810abb87 2221 DEFVAR_LISP ("vertical-centering-font-regexp",
29208e82 2222 Vvertical_centering_font_regexp,
fb7ada5f 2223 doc: /* Regexp matching font names that require vertical centering on display.
335c5470 2224When a character is displayed with such fonts, the character is displayed
fc8865fc 2225at the vertical center of lines. */);
810abb87
KH
2226 Vvertical_centering_font_regexp = Qnil;
2227
29208e82 2228 DEFVAR_LISP ("otf-script-alist", Votf_script_alist,
21ff5ed6
KH
2229 doc: /* Alist of OpenType script tags vs the corresponding script names. */);
2230 Votf_script_alist = Qnil;
2231
4ed46869
KH
2232 defsubr (&Squery_fontset);
2233 defsubr (&Snew_fontset);
2234 defsubr (&Sset_fontset_font);
1ff005e1 2235 defsubr (&Sinternal_char_font);
4ed46869 2236 defsubr (&Sfontset_info);
0d407d77
KH
2237 defsubr (&Sfontset_font);
2238 defsubr (&Sfontset_list);
a54e2c05 2239#ifdef ENABLE_CHECKING
452a78e0
KH
2240 defsubr (&Sfontset_list_all);
2241#endif
e3400864 2242}