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