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