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