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