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