(Fencode_char, Fsplit_char): Doc fixes.
[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 ... ]
387 Reorder RFONT-DEFs according to the current langauge, and update
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 }
581f7ac7
KH
611 font_object = font_open_for_lface (f, font_entity, face->lface, Qnil);
612 if (NILP (font_object))
d67f7f1a 613 {
581f7ac7
KH
614 /* Record that the font is unsable. */
615 RFONT_DEF_SET_FACE (elt, -1);
616 continue;
8aa07a8d 617 }
581f7ac7 618 RFONT_DEF_SET_OBJECT (elt, font_object);
8aa07a8d 619 }
eb152aa9 620
581f7ac7
KH
621 if (font_has_char (f, font_object, c))
622 return elt;
1d5d7200 623
581f7ac7
KH
624#if 0
625 /* The following code makes Emacs to find a font for C by fairly
626 exhausitive search. But, that takes long time especially for
627 X font backend. */
628
629 /* Try to find the different font maching with the current spec
630 and support C. */
631 font_def = RFONT_DEF_FONT_DEF (elt);
632 for (i++; i < ASIZE (vec); i++)
57e13af9 633 {
581f7ac7
KH
634 if (! EQ (RFONT_DEF_FONT_DEF (AREF (vec, i)), font_def))
635 break;
636 if (font_has_char (f, RFONT_DEF_OBJECT (AREF (vec, i)), c))
637 return AREF (vec, i);
57e13af9 638 }
581f7ac7
KH
639 /* Find an font-entity that support C. */
640 font_entity = font_find_for_lface (f, face->lface,
641 FONT_DEF_SPEC (font_def), c);
642 if (! NILP (font_entity))
1d5d7200 643 {
581f7ac7
KH
644 Lisp_Object rfont_def, new_vec;
645 int j;
1d5d7200 646
581f7ac7
KH
647 font_object = font_open_for_lface (f, font_entity, face->lface,
648 Qnil);
649 RFONT_DEF_NEW (rfont_def, font_def);
650 RFONT_DEF_SET_OBJECT (rfont_def, font_object);
651 RFONT_DEF_SET_SCORE (rfont_def, RFONT_DEF_SCORE (elt));
652 new_vec = Fmake_vector (make_number (ASIZE (vec) + 1), Qnil);
653 for (j = 0; j < i; j++)
654 ASET (new_vec, j, AREF (vec, j));
655 ASET (new_vec, j, rfont_def);
656 for (j++; j < ASIZE (new_vec); j++)
657 ASET (new_vec, j, AREF (vec, j - 1));
658 vec = new_vec;
659 return rfont_def;
1d5d7200 660 }
581f7ac7
KH
661 i--;
662#endif /* 0 */
0d407d77 663 }
d67f7f1a 664
581f7ac7 665 FONTSET_SET (fontset, make_number (c), make_number (0));
eaa0402c 666 return Qnil;
1c82b4b3 667}
0d407d77 668
cc7b6145 669
1c82b4b3
KH
670static Lisp_Object
671fontset_font (fontset, c, face, id)
672 Lisp_Object fontset;
673 int c;
674 struct face *face;
675 int id;
676{
677 Lisp_Object rfont_def;
678 Lisp_Object base_fontset;
cc7b6145 679
1c82b4b3
KH
680 /* Try a font-group for C. */
681 rfont_def = fontset_find_font (fontset, c, face, id, 0);
eaa0402c
KH
682 if (VECTORP (rfont_def))
683 return rfont_def;
684 if (EQ (rfont_def, Qt))
685 return Qnil;
1c82b4b3
KH
686 /* Try a fallback font-group. */
687 rfont_def = fontset_find_font (fontset, c, face, id, 1);
dbf46ba6
KH
688 if (VECTORP (rfont_def))
689 return rfont_def;
690 if (EQ (rfont_def, Qt))
691 return Qnil;
d67f7f1a 692
dbf46ba6
KH
693 base_fontset = FONTSET_BASE (fontset);
694 if (EQ (base_fontset, Vdefault_fontset))
695 return Qnil;
696
697 /* Try a font-group for C of the default fontset. */
698 if (NILP (FONTSET_DEFAULT (fontset)))
699 FONTSET_DEFAULT (fontset)
700 = make_fontset (FONTSET_FRAME (fontset), Qnil, Vdefault_fontset);
701 rfont_def = fontset_find_font (FONTSET_DEFAULT (fontset), c, face, id, 0);
702 if (VECTORP (rfont_def))
703 return rfont_def;
704 /* Try a fallback font-group of the default fontset . */
705 rfont_def = fontset_find_font (FONTSET_DEFAULT (fontset), c, face, id, 1);
d67f7f1a
KH
706 if (! VECTORP (rfont_def))
707 /* Remeber that we have no font for C. */
708 FONTSET_SET (fontset, make_number (c), Qt);
709
1c82b4b3 710 return rfont_def;
0d407d77
KH
711}
712
0d407d77 713/* Return a newly created fontset with NAME. If BASE is nil, make a
06f76f0d 714 base fontset. Otherwise make a realized fontset whose base is
0d407d77
KH
715 BASE. */
716
717static Lisp_Object
718make_fontset (frame, name, base)
719 Lisp_Object frame, name, base;
4ed46869 720{
1337ac77 721 Lisp_Object fontset;
0d407d77
KH
722 int size = ASIZE (Vfontset_table);
723 int id = next_fontset_id;
0d407d77
KH
724
725 /* Find a free slot in Vfontset_table. Usually, next_fontset_id is
726 the next available fontset ID. So it is expected that this loop
727 terminates quickly. In addition, as the last element of
fc8865fc 728 Vfontset_table is always nil, we don't have to check the range of
0d407d77
KH
729 id. */
730 while (!NILP (AREF (Vfontset_table, id))) id++;
731
732 if (id + 1 == size)
63655c83 733 Vfontset_table = larger_vector (Vfontset_table, size + 32, Qnil);
4ed46869 734
11d9bd93 735 fontset = Fmake_char_table (Qfontset, Qnil);
0d407d77
KH
736
737 FONTSET_ID (fontset) = make_number (id);
06f76f0d
KH
738 if (NILP (base))
739 {
740 FONTSET_NAME (fontset) = name;
741 }
742 else
743 {
744 FONTSET_NAME (fontset) = Qnil;
745 FONTSET_FRAME (fontset) = frame;
746 FONTSET_BASE (fontset) = base;
747 }
0d407d77 748
06f76f0d 749 ASET (Vfontset_table, id, fontset);
0d407d77
KH
750 next_fontset_id = id + 1;
751 return fontset;
4ed46869
KH
752}
753
0d407d77 754
2cdd4f88
MB
755/* Set the ASCII font of the default fontset to FONTNAME if that is
756 not yet set. */
757void
758set_default_ascii_font (fontname)
0d407d77
KH
759 Lisp_Object fontname;
760{
d7fb7b91 761 if (! STRINGP (FONTSET_ASCII (Vdefault_fontset)))
2cdd4f88
MB
762 {
763 int id = fs_query_fontset (fontname, 2);
764
765 if (id >= 0)
d7fb7b91
KH
766 fontname = FONTSET_ASCII (FONTSET_FROM_ID (id));
767 FONTSET_ASCII (Vdefault_fontset)= fontname;
2cdd4f88 768 }
0d407d77
KH
769}
770
771\f
1d5d7200 772/********** INTERFACES TO xfaces.c, xfns.c, and dispextern.h **********/
0d407d77 773
1d5d7200 774/* Return the name of the fontset who has ID. */
0d407d77
KH
775
776Lisp_Object
777fontset_name (id)
778 int id;
779{
780 Lisp_Object fontset;
06f76f0d 781
0d407d77
KH
782 fontset = FONTSET_FROM_ID (id);
783 return FONTSET_NAME (fontset);
784}
785
786
1d5d7200 787/* Return the ASCII font name of the fontset who has ID. */
0d407d77
KH
788
789Lisp_Object
790fontset_ascii (id)
791 int id;
792{
793 Lisp_Object fontset, elt;
06f76f0d 794
0d407d77
KH
795 fontset= FONTSET_FROM_ID (id);
796 elt = FONTSET_ASCII (fontset);
8aa07a8d
KH
797 if (CONSP (elt))
798 elt = XCAR (elt);
1d5d7200 799 return elt;
0d407d77
KH
800}
801
9459b1e9
KH
802void
803free_realized_fontset (f, fontset)
804 FRAME_PTR f;
805 Lisp_Object fontset;
806{
9459b1e9
KH
807 Lisp_Object tail;
808
809 return;
810 for (tail = FONTSET_OBJLIST (fontset); CONSP (tail); tail = XCDR (tail))
811 {
812 xassert (FONT_OBJECT_P (XCAR (tail)));
813 font_close_object (f, XCAR (tail));
814 }
815}
0d407d77 816
06f76f0d
KH
817/* Free fontset of FACE defined on frame F. Called from
818 free_realized_face. */
0d407d77 819
4ed46869 820void
0d407d77
KH
821free_face_fontset (f, face)
822 FRAME_PTR f;
823 struct face *face;
4ed46869 824{
452a78e0
KH
825 Lisp_Object fontset;
826
ff7a2223 827 fontset = FONTSET_FROM_ID (face->fontset);
581f7ac7
KH
828 if (NILP (fontset))
829 return;
830 xassert (! BASE_FONTSET_P (fontset));
452a78e0 831 xassert (f == XFRAME (FONTSET_FRAME (fontset)));
9459b1e9 832 free_realized_fontset (f, fontset);
1d5d7200 833 ASET (Vfontset_table, face->fontset, Qnil);
06f76f0d
KH
834 if (face->fontset < next_fontset_id)
835 next_fontset_id = face->fontset;
eb36588a 836 if (! NILP (FONTSET_DEFAULT (fontset)))
452a78e0 837 {
e1a14cdc 838 int id = XINT (FONTSET_ID (FONTSET_DEFAULT (fontset)));
eb152aa9 839
452a78e0
KH
840 fontset = AREF (Vfontset_table, id);
841 xassert (!NILP (fontset) && ! BASE_FONTSET_P (fontset));
842 xassert (f == XFRAME (FONTSET_FRAME (fontset)));
9459b1e9 843 free_realized_fontset (f, fontset);
452a78e0
KH
844 ASET (Vfontset_table, id, Qnil);
845 if (id < next_fontset_id)
846 next_fontset_id = face->fontset;
847 }
581f7ac7 848 face->fontset = -1;
0d407d77 849}
18998710 850
0d407d77 851
e0f24100 852/* Return 1 if FACE is suitable for displaying character C.
0d407d77 853 Otherwise return 0. Called from the macro FACE_SUITABLE_FOR_CHAR_P
06f76f0d 854 when C is not an ASCII character. */
0d407d77
KH
855
856int
857face_suitable_for_char_p (face, c)
858 struct face *face;
859 int c;
860{
7e1a1cd9 861 Lisp_Object fontset, rfont_def;
0d407d77 862
0d407d77 863 fontset = FONTSET_FROM_ID (face->fontset);
7e1a1cd9
KH
864 rfont_def = fontset_font (fontset, c, NULL, -1);
865 return (VECTORP (rfont_def)
581f7ac7
KH
866 && INTEGERP (RFONT_DEF_FACE (rfont_def))
867 && face->id == XINT (RFONT_DEF_FACE (rfont_def)));
0d407d77
KH
868}
869
870
871/* Return ID of face suitable for displaying character C on frame F.
1d5d7200
KH
872 FACE must be reazlied for ASCII characters in advance. Called from
873 the macro FACE_FOR_CHAR. */
0d407d77
KH
874
875int
6bad8007 876face_for_char (f, face, c, pos, object)
0d407d77
KH
877 FRAME_PTR f;
878 struct face *face;
6bad8007
KH
879 int c, pos;
880 Lisp_Object object;
0d407d77 881{
581f7ac7 882 Lisp_Object fontset, rfont_def;
7e1a1cd9 883 int face_id;
6bad8007 884 int id;
1d5d7200
KH
885
886 if (ASCII_CHAR_P (c))
887 return face->ascii_face->id;
0d407d77
KH
888
889 xassert (fontset_id_valid_p (face->fontset));
890 fontset = FONTSET_FROM_ID (face->fontset);
891 xassert (!BASE_FONTSET_P (fontset));
6bad8007
KH
892 if (pos < 0)
893 id = -1;
894 else
895 {
581f7ac7
KH
896 Lisp_Object charset;
897
6bad8007
KH
898 charset = Fget_char_property (make_number (pos), Qcharset, object);
899 if (NILP (charset))
900 id = -1;
901 else if (CHARSETP (charset))
28e2436a
KH
902 {
903 Lisp_Object val;
904
905 val = assoc_no_quit (charset, Vfont_encoding_charset_alist);
906 if (CONSP (val) && CHARSETP (XCDR (val)))
907 charset = XCDR (val);
908 id = XINT (CHARSET_SYMBOL_ID (charset));
909 }
6bad8007 910 }
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
940/* Make a realized fontset for ASCII face FACE on frame F from the
941 base fontset BASE_FONTSET_ID. If BASE_FONTSET_ID is -1, use the
942 default fontset as the base. Value is the id of the new fontset.
943 Called from realize_x_face. */
944
945int
1d5d7200 946make_fontset_for_ascii_face (f, base_fontset_id, face)
0d407d77
KH
947 FRAME_PTR f;
948 int base_fontset_id;
1d5d7200 949 struct face *face;
0d407d77 950{
1337ac77 951 Lisp_Object base_fontset, fontset, frame;
0d407d77
KH
952
953 XSETFRAME (frame, f);
954 if (base_fontset_id >= 0)
955 {
956 base_fontset = FONTSET_FROM_ID (base_fontset_id);
957 if (!BASE_FONTSET_P (base_fontset))
958 base_fontset = FONTSET_BASE (base_fontset);
1d5d7200
KH
959 if (! BASE_FONTSET_P (base_fontset))
960 abort ();
4ed46869 961 }
0d407d77
KH
962 else
963 base_fontset = Vdefault_fontset;
964
965 fontset = make_fontset (frame, Qnil, base_fontset);
f3231837 966 return XINT (FONTSET_ID (fontset));
0d407d77
KH
967}
968
0d407d77 969\f
1d5d7200 970
4ed46869
KH
971/* Cache data used by fontset_pattern_regexp. The car part is a
972 pattern string containing at least one wild card, the cdr part is
973 the corresponding regular expression. */
974static Lisp_Object Vcached_fontset_data;
975
dbf46ba6 976#define CACHED_FONTSET_NAME ((char *) SDATA (XCAR (Vcached_fontset_data)))
7539e11f 977#define CACHED_FONTSET_REGEX (XCDR (Vcached_fontset_data))
4ed46869
KH
978
979/* If fontset name PATTERN contains any wild card, return regular
980 expression corresponding to PATTERN. */
981
0d407d77 982static Lisp_Object
4ed46869
KH
983fontset_pattern_regexp (pattern)
984 Lisp_Object pattern;
985{
dbf46ba6
KH
986 if (!index ((char *) SDATA (pattern), '*')
987 && !index ((char *) SDATA (pattern), '?'))
4ed46869 988 /* PATTERN does not contain any wild cards. */
1c283e35 989 return Qnil;
4ed46869
KH
990
991 if (!CONSP (Vcached_fontset_data)
dbf46ba6 992 || strcmp ((char *) SDATA (pattern), CACHED_FONTSET_NAME))
4ed46869
KH
993 {
994 /* We must at first update the cached data. */
6cc06608 995 unsigned char *regex, *p0, *p1;
fc1062f5 996 int ndashes = 0, nstars = 0;
6cc06608 997
fc1062f5
KH
998 for (p0 = SDATA (pattern); *p0; p0++)
999 {
1000 if (*p0 == '-')
1001 ndashes++;
a653f812 1002 else if (*p0 == '*')
fc1062f5
KH
1003 nstars++;
1004 }
1005
1006 /* If PATTERN is not full XLFD we conert "*" to ".*". Otherwise
1007 we convert "*" to "[^-]*" which is much faster in regular
1008 expression matching. */
1009 if (ndashes < 14)
6cc06608 1010 p1 = regex = (unsigned char *) alloca (SBYTES (pattern) + 2 * nstars + 1);
fc1062f5 1011 else
6cc06608 1012 p1 = regex = (unsigned char *) alloca (SBYTES (pattern) + 5 * nstars + 1);
4ed46869 1013
1c283e35 1014 *p1++ = '^';
6cc06608 1015 for (p0 = SDATA (pattern); *p0; p0++)
4ed46869 1016 {
a653f812 1017 if (*p0 == '*')
4ed46869 1018 {
fc1062f5
KH
1019 if (ndashes < 14)
1020 *p1++ = '.';
1021 else
1022 *p1++ = '[', *p1++ = '^', *p1++ = '-', *p1++ = ']';
1c283e35 1023 *p1++ = '*';
4ed46869 1024 }
1c283e35 1025 else if (*p0 == '?')
d96d677d 1026 *p1++ = '.';
1c283e35
KH
1027 else
1028 *p1++ = *p0;
4ed46869
KH
1029 }
1030 *p1++ = '$';
1031 *p1++ = 0;
1032
dbf46ba6
KH
1033 Vcached_fontset_data = Fcons (build_string ((char *) SDATA (pattern)),
1034 build_string ((char *) regex));
4ed46869
KH
1035 }
1036
1037 return CACHED_FONTSET_REGEX;
1038}
1039
0d407d77 1040/* Return ID of the base fontset named NAME. If there's no such
a653f812
KH
1041 fontset, return -1. NAME_PATTERN specifies how to treat NAME as this:
1042 0: pattern containing '*' and '?' as wildcards
1043 1: regular expression
1044 2: literal fontset name
1045*/
0d407d77
KH
1046
1047int
a653f812 1048fs_query_fontset (name, name_pattern)
0d407d77 1049 Lisp_Object name;
a653f812 1050 int name_pattern;
0d407d77 1051{
1337ac77 1052 Lisp_Object tem;
0d407d77
KH
1053 int i;
1054
1055 name = Fdowncase (name);
a653f812 1056 if (name_pattern != 1)
0d407d77
KH
1057 {
1058 tem = Frassoc (name, Vfontset_alias_alist);
6bad8007
KH
1059 if (NILP (tem))
1060 tem = Fassoc (name, Vfontset_alias_alist);
0d407d77
KH
1061 if (CONSP (tem) && STRINGP (XCAR (tem)))
1062 name = XCAR (tem);
a653f812 1063 else if (name_pattern == 0)
0d407d77
KH
1064 {
1065 tem = fontset_pattern_regexp (name);
1066 if (STRINGP (tem))
1067 {
1068 name = tem;
a653f812 1069 name_pattern = 1;
0d407d77
KH
1070 }
1071 }
1072 }
1073
1074 for (i = 0; i < ASIZE (Vfontset_table); i++)
1075 {
6e1b0d8c 1076 Lisp_Object fontset, this_name;
0d407d77
KH
1077
1078 fontset = FONTSET_FROM_ID (i);
1079 if (NILP (fontset)
1080 || !BASE_FONTSET_P (fontset))
1081 continue;
1082
6e1b0d8c 1083 this_name = FONTSET_NAME (fontset);
a653f812 1084 if (name_pattern == 1
581f7ac7 1085 ? fast_string_match_ignore_case (name, this_name) >= 0
05131107 1086 : !xstrcasecmp (SDATA (name), SDATA (this_name)))
0d407d77
KH
1087 return i;
1088 }
1089 return -1;
1090}
1091
1092
727fb790 1093DEFUN ("query-fontset", Fquery_fontset, Squery_fontset, 1, 2, 0,
335c5470
PJ
1094 doc: /* Return the name of a fontset that matches PATTERN.
1095The value is nil if there is no matching fontset.
1096PATTERN can contain `*' or `?' as a wildcard
1097just as X font name matching algorithm allows.
1098If REGEXPP is non-nil, PATTERN is a regular expression. */)
1099 (pattern, regexpp)
727fb790 1100 Lisp_Object pattern, regexpp;
4ed46869 1101{
0d407d77
KH
1102 Lisp_Object fontset;
1103 int id;
4ed46869
KH
1104
1105 (*check_window_system_func) ();
1106
b7826503 1107 CHECK_STRING (pattern);
4ed46869 1108
d5db4077 1109 if (SCHARS (pattern) == 0)
4ed46869
KH
1110 return Qnil;
1111
0d407d77
KH
1112 id = fs_query_fontset (pattern, !NILP (regexpp));
1113 if (id < 0)
1114 return Qnil;
4ed46869 1115
0d407d77
KH
1116 fontset = FONTSET_FROM_ID (id);
1117 return FONTSET_NAME (fontset);
4ed46869
KH
1118}
1119
06f76f0d 1120/* Return a list of base fontset names matching PATTERN on frame F. */
4ed46869
KH
1121
1122Lisp_Object
1123list_fontsets (f, pattern, size)
1124 FRAME_PTR f;
1125 Lisp_Object pattern;
1126 int size;
1127{
1337ac77 1128 Lisp_Object frame, regexp, val;
0d407d77 1129 int id;
4ed46869 1130
0d407d77 1131 XSETFRAME (frame, f);
4ed46869 1132
0d407d77 1133 regexp = fontset_pattern_regexp (pattern);
4ed46869 1134 val = Qnil;
4ed46869 1135
0d407d77
KH
1136 for (id = 0; id < ASIZE (Vfontset_table); id++)
1137 {
6e1b0d8c 1138 Lisp_Object fontset, name;
0d407d77
KH
1139
1140 fontset = FONTSET_FROM_ID (id);
1141 if (NILP (fontset)
1142 || !BASE_FONTSET_P (fontset)
1143 || !EQ (frame, FONTSET_FRAME (fontset)))
1144 continue;
6e1b0d8c 1145 name = FONTSET_NAME (fontset);
0d407d77 1146
1d5d7200 1147 if (STRINGP (regexp)
6e1b0d8c 1148 ? (fast_string_match (regexp, name) < 0)
dbf46ba6 1149 : strcmp ((char *) SDATA (pattern), (char *) SDATA (name)))
0d407d77
KH
1150 continue;
1151
0d407d77 1152 val = Fcons (Fcopy_sequence (FONTSET_NAME (fontset)), val);
4ed46869
KH
1153 }
1154
1155 return val;
1156}
1157
4ed46869 1158
8f924df7 1159/* Free all realized fontsets whose base fontset is BASE. */
4ed46869 1160
06f76f0d
KH
1161static void
1162free_realized_fontsets (base)
1163 Lisp_Object base;
1164{
1165 int id;
4ed46869 1166
2f034212 1167#if 0
27e20b2f
KH
1168 /* For the moment, this doesn't work because free_realized_face
1169 doesn't remove FACE from a cache. Until we find a solution, we
1170 suppress this code, and simply use Fclear_face_cache even though
1171 that is not efficient. */
06f76f0d
KH
1172 BLOCK_INPUT;
1173 for (id = 0; id < ASIZE (Vfontset_table); id++)
4ed46869 1174 {
06f76f0d 1175 Lisp_Object this = AREF (Vfontset_table, id);
0d407d77 1176
06f76f0d 1177 if (EQ (FONTSET_BASE (this), base))
0d407d77 1178 {
06f76f0d 1179 Lisp_Object tail;
4ed46869 1180
06f76f0d
KH
1181 for (tail = FONTSET_FACE_ALIST (this); CONSP (tail);
1182 tail = XCDR (tail))
1183 {
1184 FRAME_PTR f = XFRAME (FONTSET_FRAME (this));
1185 int face_id = XINT (XCDR (XCAR (tail)));
1186 struct face *face = FACE_FROM_ID (f, face_id);
4ed46869 1187
06f76f0d
KH
1188 /* Face THIS itself is also freed by the following call. */
1189 free_realized_face (f, face);
1190 }
1191 }
0d407d77 1192 }
06f76f0d 1193 UNBLOCK_INPUT;
27e20b2f 1194#else /* not 0 */
2f034212
KH
1195 /* But, we don't have to call Fclear_face_cache if no fontset has
1196 been realized from BASE. */
1197 for (id = 0; id < ASIZE (Vfontset_table); id++)
1198 {
1199 Lisp_Object this = AREF (Vfontset_table, id);
1200
985773c9 1201 if (CHAR_TABLE_P (this) && EQ (FONTSET_BASE (this), base))
2f034212
KH
1202 {
1203 Fclear_face_cache (Qt);
1204 break;
1205 }
1206 }
27e20b2f 1207#endif /* not 0 */
0d407d77 1208}
4ed46869 1209
4ed46869 1210
0d407d77
KH
1211/* Check validity of NAME as a fontset name and return the
1212 corresponding fontset. If not valid, signal an error.
1213 If NAME is t, return Vdefault_fontset. */
1214
1215static Lisp_Object
1216check_fontset_name (name)
1217 Lisp_Object name;
1218{
1219 int id;
1220
1221 if (EQ (name, Qt))
1222 return Vdefault_fontset;
4ed46869 1223
b7826503 1224 CHECK_STRING (name);
a653f812
KH
1225 /* First try NAME as literal. */
1226 id = fs_query_fontset (name, 2);
1227 if (id < 0)
1228 /* For backward compatibility, try again NAME as pattern. */
1229 id = fs_query_fontset (name, 0);
0d407d77 1230 if (id < 0)
d5db4077 1231 error ("Fontset `%s' does not exist", SDATA (name));
0d407d77
KH
1232 return FONTSET_FROM_ID (id);
1233}
4ed46869 1234
1d5d7200
KH
1235static void
1236accumulate_script_ranges (arg, range, val)
1237 Lisp_Object arg, range, val;
1238{
1239 if (EQ (XCAR (arg), val))
1240 {
1241 if (CONSP (range))
1242 XSETCDR (arg, Fcons (Fcons (XCAR (range), XCDR (range)), XCDR (arg)));
1243 else
1244 XSETCDR (arg, Fcons (Fcons (range, range), XCDR (arg)));
1245 }
1246}
1247
1248
d6aaac9e 1249/* Return an ASCII font name generated from fontset name NAME and
7ff614ed 1250 font-spec ASCII_SPEC. NAME is a string conforming to XLFD. */
d6aaac9e
KH
1251
1252static INLINE Lisp_Object
1253generate_ascii_font_name (name, ascii_spec)
1254 Lisp_Object name, ascii_spec;
1255{
7ff614ed 1256 Lisp_Object font_spec = Ffont_spec (0, NULL);
d6aaac9e 1257 int i;
7ff614ed 1258 char xlfd[256];
d6aaac9e 1259
dbf46ba6 1260 if (font_parse_xlfd ((char *) SDATA (name), font_spec) < 0)
7ff614ed 1261 error ("Not an XLFD font name: %s", SDATA (name));
581f7ac7 1262 for (i = FONT_FOUNDRY_INDEX; i < FONT_EXTRA_INDEX; i++)
d6aaac9e 1263 if (! NILP (AREF (ascii_spec, i)))
7ff614ed
KH
1264 ASET (font_spec, i, AREF (ascii_spec, i));
1265 i = font_unparse_xlfd (font_spec, 0, xlfd, 256);
1266 if (i < 0)
1267 error ("Not an XLFD font name: %s", SDATA (name));
1268 return make_unibyte_string (xlfd, i);
d6aaac9e
KH
1269}
1270
fb78e2ed
KH
1271/* Variables referred in set_fontset_font. They are set before
1272 map_charset_chars is called in Fset_fontset_font. */
1273static Lisp_Object font_def_arg, add_arg;
1274static int from_arg, to_arg;
1275
1276/* Callback function for map_charset_chars in Fset_fontset_font. In
1277 FONTSET, set font_def_arg in a fashion specified by add_arg for
1278 characters in RANGE while ignoring the range between from_arg and
1279 to_arg. */
1280
2449d4d0 1281static void
fb78e2ed
KH
1282set_fontset_font (fontset, range)
1283 Lisp_Object fontset, range;
2449d4d0 1284{
fb78e2ed
KH
1285 if (from_arg < to_arg)
1286 {
1287 int from = XINT (XCAR (range)), to = XINT (XCDR (range));
2449d4d0 1288
fb78e2ed
KH
1289 if (from < from_arg)
1290 {
1291 if (to > to_arg)
1292 {
1293 Lisp_Object range2;
1294
1295 range2 = Fcons (make_number (to_arg), XCDR (range));
1296 FONTSET_ADD (fontset, range, font_def_arg, add_arg);
1297 to = to_arg;
1298 }
1299 if (to > from_arg)
1300 range = Fcons (XCAR (range), make_number (from_arg));
1301 }
1302 else if (to <= to_arg)
1303 return;
1304 else
1305 {
1306 if (from < to_arg)
1307 range = Fcons (make_number (to_arg), XCDR (range));
1308 }
1309 }
1310 FONTSET_ADD (fontset, range, font_def_arg, add_arg);
2449d4d0
KH
1311}
1312
8b67c40a 1313extern Lisp_Object QCfamily, QCregistry;
d6aaac9e 1314
1d5d7200 1315DEFUN ("set-fontset-font", Fset_fontset_font, Sset_fontset_font, 3, 5, 0,
8f924df7 1316 doc: /*
eb36588a 1317Modify fontset NAME to use FONT-SPEC for TARGET characters.
335c5470 1318
eb36588a
KH
1319TARGET may be a cons; (FROM . TO), where FROM and TO are characters.
1320In that case, use FONT-SPEC for all characters in the range FROM and
1321TO (inclusive).
06f76f0d 1322
eb36588a
KH
1323TARGET may be a script name symbol. In that case, use FONT-SPEC for
1324all characters that belong to the script.
06f76f0d 1325
eb36588a 1326TARGET may be a charset. In that case, use FONT-SPEC for all
95318a38 1327characters in the charset.
1d5d7200 1328
eb36588a
KH
1329TARGET may be nil. In that case, use FONT-SPEC for any characters for
1330that no FONT-SPEC is specified.
1331
0fdf26e6 1332FONT-SPEC may one of these:
581f7ac7 1333 * A font-spec object made by the function `font-spec' (which see).
3dcd48dd 1334 * A cons (FAMILY . REGISTRY), where FAMILY is a font family name and
581f7ac7
KH
1335 REGISTRY is a font registry name. FAMILY may contain foundry
1336 name, and REGISTRY may contain encoding name.
00c4da0f 1337 * A font name string.
eaa0402c 1338 * nil, which explicitly specifies that there's no font for TARGET.
1d5d7200
KH
1339
1340Optional 4th argument FRAME, if non-nil, is a frame. This argument is
1341kept for backward compatibility and has no meaning.
1342
1343Optional 5th argument ADD, if non-nil, specifies how to add FONT-SPEC
eb36588a 1344to the font specifications for TARGET previously set. If it is
1d5d7200
KH
1345`prepend', FONT-SPEC is prepended. If it is `append', FONT-SPEC is
1346appended. By default, FONT-SPEC overrides the previous settings. */)
eb36588a
KH
1347 (name, target, font_spec, frame, add)
1348 Lisp_Object name, target, font_spec, frame, add;
0d407d77 1349{
06f76f0d 1350 Lisp_Object fontset;
9683749a 1351 Lisp_Object font_def, registry, family;
1d5d7200 1352 Lisp_Object range_list;
fb78e2ed 1353 struct charset *charset = NULL;
0d407d77
KH
1354
1355 fontset = check_fontset_name (name);
1356
1d5d7200
KH
1357 /* The arg FRAME is kept for backward compatibility. We only check
1358 the validity. */
1359 if (!NILP (frame))
1360 CHECK_LIVE_FRAME (frame);
1361
581f7ac7 1362 if (CONSP (font_spec))
0d407d77 1363 {
581f7ac7 1364 Lisp_Object spec = Ffont_spec (0, NULL);
1d5d7200 1365
581f7ac7
KH
1366 font_parse_family_registry (XCAR (font_spec), XCDR (font_spec), spec);
1367 font_spec = spec;
0890801b 1368 }
d67f7f1a 1369 else if (STRINGP (font_spec))
4ed46869 1370 {
ea0162a6 1371 Lisp_Object args[2];
581f7ac7 1372 extern Lisp_Object QCname;
ea0162a6 1373
ea0162a6
KH
1374 args[0] = QCname;
1375 args[1] = font_spec;
1376 font_spec = Ffont_spec (2, args);
0d407d77 1377 }
581f7ac7
KH
1378 else if (! NILP (font_spec) && ! FONT_SPEC_P (font_spec))
1379 Fsignal (Qfont, list2 (build_string ("Invalid font-spec"), font_spec));
1d5d7200 1380
d67f7f1a 1381 if (! NILP (font_spec))
57e13af9 1382 {
581f7ac7
KH
1383 Lisp_Object encoding, repertory;
1384
d67f7f1a 1385 family = AREF (font_spec, FONT_FAMILY_INDEX);
581f7ac7 1386 if (! NILP (family) )
d67f7f1a
KH
1387 family = SYMBOL_NAME (family);
1388 registry = AREF (font_spec, FONT_REGISTRY_INDEX);
581f7ac7
KH
1389 if (! NILP (registry))
1390 registry = Fdowncase (SYMBOL_NAME (registry));
1391 encoding = find_font_encoding (concat3 (family, build_string ("-"),
1392 registry));
d67f7f1a
KH
1393 if (NILP (encoding))
1394 encoding = Qascii;
1395
1396 if (SYMBOLP (encoding))
1397 {
1398 CHECK_CHARSET (encoding);
1399 encoding = repertory = CHARSET_SYMBOL_ID (encoding);
1400 }
1401 else
57e13af9 1402 {
d67f7f1a
KH
1403 repertory = XCDR (encoding);
1404 encoding = XCAR (encoding);
1405 CHECK_CHARSET (encoding);
1406 encoding = CHARSET_SYMBOL_ID (encoding);
1407 if (! NILP (repertory) && SYMBOLP (repertory))
1408 {
1409 CHECK_CHARSET (repertory);
1410 repertory = CHARSET_SYMBOL_ID (repertory);
1411 }
57e13af9 1412 }
581f7ac7 1413 FONT_DEF_NEW (font_def, font_spec, encoding, repertory);
0d407d77 1414 }
d67f7f1a
KH
1415 else
1416 font_def = Qnil;
4ed46869 1417
eb36588a
KH
1418 if (CHARACTERP (target))
1419 range_list = Fcons (Fcons (target, target), Qnil);
1420 else if (CONSP (target))
0d407d77 1421 {
06f76f0d
KH
1422 Lisp_Object from, to;
1423
eb36588a
KH
1424 from = Fcar (target);
1425 to = Fcdr (target);
06f76f0d
KH
1426 CHECK_CHARACTER (from);
1427 CHECK_CHARACTER (to);
eb36588a 1428 range_list = Fcons (target, Qnil);
4ed46869 1429 }
eb36588a 1430 else if (SYMBOLP (target) && !NILP (target))
8a9be3ac 1431 {
1d5d7200
KH
1432 Lisp_Object script_list;
1433 Lisp_Object val;
0d407d77 1434
1d5d7200
KH
1435 range_list = Qnil;
1436 script_list = XCHAR_TABLE (Vchar_script_table)->extras[0];
eb36588a 1437 if (! NILP (Fmemq (target, script_list)))
afe93d01 1438 {
eb36588a 1439 val = Fcons (target, Qnil);
1d5d7200 1440 map_char_table (accumulate_script_ranges, Qnil, Vchar_script_table,
8f924df7
KH
1441 val);
1442 range_list = XCDR (val);
432cfa54 1443 if (EQ (target, Qlatin) && NILP (FONTSET_ASCII (fontset)))
c3fb88cc
KH
1444 {
1445 if (VECTORP (font_spec))
1446 val = generate_ascii_font_name (FONTSET_NAME (fontset),
1447 font_spec);
1448 else
1449 val = font_spec;
1450 FONTSET_ASCII (fontset) = val;
1451 }
afe93d01 1452 }
fb78e2ed 1453 if (CHARSETP (target))
afe93d01 1454 {
432cfa54 1455 if (EQ (target, Qascii) && NILP (FONTSET_ASCII (fontset)))
862aa7f9 1456 {
d6aaac9e 1457 if (VECTORP (font_spec))
862aa7f9
KH
1458 font_spec = generate_ascii_font_name (FONTSET_NAME (fontset),
1459 font_spec);
1460 FONTSET_ASCII (fontset) = font_spec;
2449d4d0
KH
1461 range_list = Fcons (Fcons (make_number (0), make_number (127)),
1462 Qnil);
1463 }
1464 else
1465 {
fb78e2ed 1466 CHECK_CHARSET_GET_CHARSET (target, charset);
862aa7f9 1467 }
afe93d01 1468 }
fb78e2ed 1469 else if (NILP (range_list))
1d5d7200 1470 error ("Invalid script or charset name: %s",
eb36588a 1471 SDATA (SYMBOL_NAME (target)));
8a9be3ac 1472 }
eb36588a
KH
1473 else if (NILP (target))
1474 range_list = Fcons (Qnil, Qnil);
1475 else
1476 error ("Invalid target for setting a font");
0d407d77 1477
fb78e2ed
KH
1478
1479 if (charset)
1480 {
1481 font_def_arg = font_def;
1482 add_arg = add;
1483 if (NILP (range_list))
1484 from_arg = to_arg = 0;
1485 else
1486 from_arg = XINT (XCAR (XCAR (range_list))),
1487 to_arg = XINT (XCDR (XCAR (range_list)));
1488
1489 map_charset_chars (set_fontset_font, Qnil, fontset, charset,
1490 CHARSET_MIN_CODE (charset),
1491 CHARSET_MAX_CODE (charset));
1492 }
1d5d7200
KH
1493 for (; CONSP (range_list); range_list = XCDR (range_list))
1494 FONTSET_ADD (fontset, XCAR (range_list), font_def, add);
4ed46869 1495
06f76f0d
KH
1496 /* Free all realized fontsets whose base is FONTSET. This way, the
1497 specified character(s) are surely redisplayed by a correct
1498 font. */
1499 free_realized_fontsets (fontset);
4ed46869 1500
4ed46869
KH
1501 return Qnil;
1502}
1503
06f76f0d
KH
1504
1505DEFUN ("new-fontset", Fnew_fontset, Snew_fontset, 2, 2, 0,
1506 doc: /* Create a new fontset NAME from font information in FONTLIST.
1507
1d5d7200 1508FONTLIST is an alist of scripts vs the corresponding font specification list.
d6aaac9e
KH
1509Each element of FONTLIST has the form (SCRIPT FONT-SPEC ...), where a
1510character of SCRIPT is displayed by a font that matches one of
1511FONT-SPEC.
06f76f0d 1512
d6aaac9e
KH
1513SCRIPT is a symbol that appears in the first extra slot of the
1514char-table `char-script-table'.
06f76f0d 1515
1d5d7200
KH
1516FONT-SPEC is a vector, a cons, or a string. See the documentation of
1517`set-fontset-font' for the meaning. */)
06f76f0d
KH
1518 (name, fontlist)
1519 Lisp_Object name, fontlist;
1520{
1d5d7200 1521 Lisp_Object fontset;
1d5d7200 1522 int id;
06f76f0d
KH
1523
1524 CHECK_STRING (name);
1525 CHECK_LIST (fontlist);
1526
581f7ac7 1527 name = Fdowncase (name);
1d5d7200
KH
1528 id = fs_query_fontset (name, 0);
1529 if (id < 0)
0d407d77 1530 {
581f7ac7
KH
1531 Lisp_Object font_spec = Ffont_spec (0, NULL);
1532 Lisp_Object short_name;
5f2d79e0 1533 char xlfd[256];
581f7ac7
KH
1534 int len;
1535
dbf46ba6 1536 if (font_parse_xlfd ((char *) SDATA (name), font_spec) < 0)
d6aaac9e 1537 error ("Fontset name must be in XLFD format");
581f7ac7 1538 short_name = AREF (font_spec, FONT_REGISTRY_INDEX);
dbf46ba6 1539 if (strncmp ((char *) SDATA (SYMBOL_NAME (short_name)), "fontset-", 8)
581f7ac7
KH
1540 || SBYTES (SYMBOL_NAME (short_name)) < 9)
1541 error ("Registry field of fontset name must be \"fontset-*\"");
1542 Vfontset_alias_alist = Fcons (Fcons (name, SYMBOL_NAME (short_name)),
1543 Vfontset_alias_alist);
1544 ASET (font_spec, FONT_REGISTRY_INDEX, Qiso8859_1);
d6aaac9e 1545 fontset = make_fontset (Qnil, name, Qnil);
5f2d79e0
KH
1546 len = font_unparse_xlfd (font_spec, 0, xlfd, 256);
1547 if (len < 0)
1548 error ("Invalid fontset name (perhaps too long): %s", SDATA (name));
581f7ac7 1549 FONTSET_ASCII (fontset) = make_unibyte_string (xlfd, len);
d6aaac9e 1550 }
1d5d7200
KH
1551 else
1552 {
1553 fontset = FONTSET_FROM_ID (id);;
1554 free_realized_fontsets (fontset);
1555 Fset_char_table_range (fontset, Qt, Qnil);
0d407d77 1556 }
4ed46869 1557
1d5d7200
KH
1558 for (; ! NILP (fontlist); fontlist = Fcdr (fontlist))
1559 {
1560 Lisp_Object elt, script;
1561
1562 elt = Fcar (fontlist);
1563 script = Fcar (elt);
cc36ddbf
KH
1564 elt = Fcdr (elt);
1565 if (CONSP (elt) && (NILP (XCDR (elt)) || CONSP (XCDR (elt))))
1566 for (; CONSP (elt); elt = XCDR (elt))
1567 Fset_fontset_font (name, script, XCAR (elt), Qnil, Qappend);
1568 else
1569 Fset_fontset_font (name, script, elt, Qnil, Qappend);
1d5d7200 1570 }
06f76f0d
KH
1571 return name;
1572}
1573
1574
452a78e0 1575/* Alist of automatically created fontsets. Each element is a cons
581f7ac7 1576 (FONT-SPEC . FONTSET-ID). */
452a78e0 1577static Lisp_Object auto_fontset_alist;
d6aaac9e
KH
1578
1579int
581f7ac7 1580fontset_from_font (font_object)
8aa07a8d
KH
1581 Lisp_Object font_object;
1582{
03ef560c 1583 Lisp_Object font_name = font_get_name (font_object);
581f7ac7
KH
1584 Lisp_Object font_spec = Fcopy_font_spec (font_object);
1585 Lisp_Object fontset_spec, alias, name, fontset;
1586 Lisp_Object val;
1587 int i;
8aa07a8d 1588
581f7ac7
KH
1589 val = assoc_no_quit (font_spec, auto_fontset_alist);
1590 if (CONSP (val))
1591 return XINT (FONTSET_ID (XCDR (val)));
03ef560c 1592 if (NILP (auto_fontset_alist))
581f7ac7 1593 alias = intern ("fontset-startup");
03ef560c
KH
1594 else
1595 {
1596 char temp[32];
1597 int len = XINT (Flength (auto_fontset_alist));
8aa07a8d 1598
03ef560c 1599 sprintf (temp, "fontset-auto%d", len);
581f7ac7 1600 alias = intern (temp);
03ef560c 1601 }
581f7ac7
KH
1602 fontset_spec = Fcopy_font_spec (font_spec);
1603 ASET (fontset_spec, FONT_REGISTRY_INDEX, alias);
7ae2e7f0 1604 name = Ffont_xlfd_name (fontset_spec, Qnil);
03ef560c 1605 if (NILP (name))
581f7ac7 1606 abort ();
03ef560c 1607 fontset = make_fontset (Qnil, name, Qnil);
581f7ac7
KH
1608 Vfontset_alias_alist = Fcons (Fcons (name, SYMBOL_NAME (alias)),
1609 Vfontset_alias_alist);
1610 alias = Fdowncase (AREF (font_object, FONT_NAME_INDEX));
1611 Vfontset_alias_alist = Fcons (Fcons (name, alias), Vfontset_alias_alist);
1612 auto_fontset_alist = Fcons (Fcons (font_spec, fontset), auto_fontset_alist);
03ef560c 1613 FONTSET_ASCII (fontset) = font_name;
581f7ac7
KH
1614 ASET (font_spec, FONT_FOUNDRY_INDEX, Qnil);
1615 ASET (font_spec, FONT_ADSTYLE_INDEX, Qnil);
1616 for (i = FONT_WEIGHT_INDEX; i < FONT_EXTRA_INDEX; i++)
1617 ASET (font_spec, i, Qnil);
1c82b4b3 1618 Fset_fontset_font (name, Qlatin, font_spec, Qnil, Qnil);
581f7ac7
KH
1619 font_spec = Fcopy_font_spec (font_spec);
1620 ASET (font_spec, FONT_REGISTRY_INDEX, Qiso10646_1);
1c82b4b3 1621 Fset_fontset_font (name, Qnil, font_spec, Qnil, Qnil);
03ef560c 1622 return XINT (FONTSET_ID (fontset));
8aa07a8d
KH
1623}
1624
4ed46869 1625DEFUN ("font-info", Ffont_info, Sfont_info, 1, 2, 0,
335c5470
PJ
1626 doc: /* Return information about a font named NAME on frame FRAME.
1627If FRAME is omitted or nil, use the selected frame.
1628The returned value is a vector of OPENED-NAME, FULL-NAME, CHARSET, SIZE,
1629 HEIGHT, BASELINE-OFFSET, RELATIVE-COMPOSE, and DEFAULT-ASCENT,
1630where
1631 OPENED-NAME is the name used for opening the font,
1632 FULL-NAME is the full name of the font,
1633 SIZE is the maximum bound width of the font,
1634 HEIGHT is the height of the font,
1635 BASELINE-OFFSET is the upward offset pixels from ASCII baseline,
1636 RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling
1637 how to compose characters.
1638If the named font is not yet loaded, return nil. */)
1639 (name, frame)
4ed46869
KH
1640 Lisp_Object name, frame;
1641{
1642 FRAME_PTR f;
581f7ac7 1643 struct font *font;
4ed46869 1644 Lisp_Object info;
8aa07a8d 1645 Lisp_Object font_object;
4ed46869
KH
1646
1647 (*check_window_system_func) ();
1648
b7826503 1649 CHECK_STRING (name);
0d407d77 1650 name = Fdowncase (name);
4ed46869 1651 if (NILP (frame))
18f39d0e 1652 frame = selected_frame;
b7826503 1653 CHECK_LIVE_FRAME (frame);
18f39d0e 1654 f = XFRAME (frame);
4ed46869 1655
dbf46ba6 1656 font_object = font_open_by_name (f, (char *) SDATA (name));
581f7ac7 1657 if (NILP (font_object))
4ed46869 1658 return Qnil;
581f7ac7 1659 font = XFONT_OBJECT (font_object);
4ed46869 1660
0d407d77 1661 info = Fmake_vector (make_number (7), Qnil);
581f7ac7
KH
1662 XVECTOR (info)->contents[0] = AREF (font_object, FONT_NAME_INDEX);
1663 XVECTOR (info)->contents[1] = AREF (font_object, FONT_NAME_INDEX);
1664 XVECTOR (info)->contents[2] = make_number (font->pixel_size);
1665 XVECTOR (info)->contents[3] = make_number (font->height);
1666 XVECTOR (info)->contents[4] = make_number (font->baseline_offset);
1667 XVECTOR (info)->contents[5] = make_number (font->relative_compose);
1668 XVECTOR (info)->contents[6] = make_number (font->default_ascent);
1669
1670 font_close_object (f, font_object);
4ed46869
KH
1671 return info;
1672}
1673
1ff005e1 1674
92c15c34
KH
1675/* Return a cons (FONT-NAME . GLYPH-CODE).
1676 FONT-NAME is the font name for the character at POSITION in the current
1ff005e1 1677 buffer. This is computed from all the text properties and overlays
cf14fd6e
KH
1678 that apply to POSITION. POSTION may be nil, in which case,
1679 FONT-NAME is the font name for display the character CH with the
1680 default face.
1681
92c15c34
KH
1682 GLYPH-CODE is the glyph code in the font to use for the character.
1683
1684 If the 2nd optional arg CH is non-nil, it is a character to check
1685 the font instead of the character at POSITION.
1686
1687 It returns nil in the following cases:
1ff005e1
KH
1688
1689 (1) The window system doesn't have a font for the character (thus
1690 it is displayed by an empty box).
1691
1692 (2) The character code is invalid.
1693
cf14fd6e
KH
1694 (3) If POSITION is not nil, and the current buffer is not displayed
1695 in any window.
1ff005e1
KH
1696
1697 In addition, the returned font name may not take into account of
1698 such redisplay engine hooks as what used in jit-lock-mode if
1699 POSITION is currently not visible. */
1700
1701
92c15c34 1702DEFUN ("internal-char-font", Finternal_char_font, Sinternal_char_font, 1, 2, 0,
335c5470 1703 doc: /* For internal use only. */)
92c15c34
KH
1704 (position, ch)
1705 Lisp_Object position, ch;
1ff005e1 1706{
0f8b27ea 1707 EMACS_INT pos, pos_byte, dummy;
1ff005e1
KH
1708 int face_id;
1709 int c;
1ff005e1
KH
1710 struct frame *f;
1711 struct face *face;
f0be8ea0 1712 int cs_id;
1ff005e1 1713
cf14fd6e 1714 if (NILP (position))
92c15c34
KH
1715 {
1716 CHECK_CHARACTER (ch);
1717 c = XINT (ch);
cf14fd6e
KH
1718 f = XFRAME (selected_frame);
1719 face_id = DEFAULT_FACE_ID;
327719ee 1720 pos = -1;
f0be8ea0 1721 cs_id = -1;
cf14fd6e
KH
1722 }
1723 else
1724 {
2f80c0a2 1725 Lisp_Object window, charset;
cf14fd6e
KH
1726 struct window *w;
1727
1728 CHECK_NUMBER_COERCE_MARKER (position);
1729 pos = XINT (position);
1730 if (pos < BEGV || pos >= ZV)
1731 args_out_of_range_3 (position, make_number (BEGV), make_number (ZV));
1732 pos_byte = CHAR_TO_BYTE (pos);
1733 if (NILP (ch))
1734 c = FETCH_CHAR (pos_byte);
1735 else
1736 {
1737 CHECK_NATNUM (ch);
1738 c = XINT (ch);
1739 }
1740 window = Fget_buffer_window (Fcurrent_buffer (), Qnil);
1741 if (NILP (window))
1742 return Qnil;
1743 w = XWINDOW (window);
1744 f = XFRAME (w->frame);
1745 face_id = face_at_buffer_position (w, pos, -1, -1, &dummy, pos + 100, 0);
2f80c0a2
KH
1746 charset = Fget_char_property (position, Qcharset, Qnil);
1747 if (CHARSETP (charset))
f0be8ea0 1748 cs_id = XINT (CHARSET_SYMBOL_ID (charset));
2f80c0a2 1749 else
f0be8ea0 1750 cs_id = -1;
92c15c34 1751 }
1ff005e1 1752 if (! CHAR_VALID_P (c, 0))
1ff005e1 1753 return Qnil;
327719ee 1754 face_id = FACE_FOR_CHAR (f, FACE_FROM_ID (f, face_id), c, pos, Qnil);
1ff005e1 1755 face = FACE_FROM_ID (f, face_id);
581f7ac7 1756 if (face->font)
8aa07a8d 1757 {
581f7ac7
KH
1758 struct font *font = face->font;
1759 unsigned code = font->driver->encode_char (font, c);
1760 Lisp_Object fontname = font->props[FONT_NAME_INDEX];
1761 /* Assignment to EMACS_INT stops GCC whining about limited range
1762 of data type. */
1763 EMACS_INT cod = code;
1764
1765 if (code == FONT_INVALID_CODE)
1766 return Qnil;
1767 if (cod <= MOST_POSITIVE_FIXNUM)
1768 return Fcons (fontname, make_number (code));
1769 return Fcons (fontname, Fcons (make_number (code >> 16),
1770 make_number (code & 0xFFFF)));
92c15c34
KH
1771 }
1772 return Qnil;
1ff005e1
KH
1773}
1774
1775
1d5d7200
KH
1776DEFUN ("fontset-info", Ffontset_info, Sfontset_info, 1, 2, 0,
1777 doc: /* Return information about a fontset FONTSET on frame FRAME.
eb152aa9 1778The value is a char-table whose elements have this form:
e2b45cf9 1779
1d5d7200 1780 ((FONT-PATTERN OPENED-FONT ...) ...)
1ff005e1 1781
1d5d7200 1782FONT-PATTERN is a vector:
1ff005e1 1783
1d5d7200 1784 [ FAMILY WEIGHT SLANT SWIDTH ADSTYLE REGISTRY ]
1ff005e1 1785
1d5d7200 1786or a string of font name pattern.
1ff005e1 1787
d6aaac9e 1788OPENED-FONT is a name of a font actually opened.
1ff005e1 1789
d6aaac9e
KH
1790The char-table has one extra slot. The value is a char-table
1791containing the information about the derived fonts from the default
eb152aa9 1792fontset. The format is the same as above. */)
1d5d7200
KH
1793 (fontset, frame)
1794 Lisp_Object fontset, frame;
4ed46869
KH
1795{
1796 FRAME_PTR f;
cc7b6145
KH
1797 Lisp_Object *realized[2], fontsets[2], tables[2];
1798 Lisp_Object val, elt;
1799 int c, i, j, k;
fc8865fc 1800
4ed46869
KH
1801 (*check_window_system_func) ();
1802
1d5d7200 1803 fontset = check_fontset_name (fontset);
0d407d77 1804
4ed46869 1805 if (NILP (frame))
18f39d0e 1806 frame = selected_frame;
b7826503 1807 CHECK_LIVE_FRAME (frame);
18f39d0e 1808 f = XFRAME (frame);
4ed46869 1809
1d5d7200
KH
1810 /* Recode fontsets realized on FRAME from the base fontset FONTSET
1811 in the table `realized'. */
cc7b6145
KH
1812 realized[0] = (Lisp_Object *) alloca (sizeof (Lisp_Object)
1813 * ASIZE (Vfontset_table));
1814 for (i = j = 0; i < ASIZE (Vfontset_table); i++)
0d407d77 1815 {
1ff005e1
KH
1816 elt = FONTSET_FROM_ID (i);
1817 if (!NILP (elt)
1d5d7200
KH
1818 && EQ (FONTSET_BASE (elt), fontset)
1819 && EQ (FONTSET_FRAME (elt), frame))
cc7b6145 1820 realized[0][j++] = elt;
0d407d77 1821 }
cc7b6145 1822 realized[0][j] = Qnil;
4ed46869 1823
cc7b6145
KH
1824 realized[1] = (Lisp_Object *) alloca (sizeof (Lisp_Object)
1825 * ASIZE (Vfontset_table));
1826 for (i = j = 0; ! NILP (realized[0][i]); i++)
1827 {
1828 elt = FONTSET_DEFAULT (realized[0][i]);
1829 if (! NILP (elt))
1830 realized[1][j++] = elt;
1831 }
1832 realized[1][j] = Qnil;
1833
1834 tables[0] = Fmake_char_table (Qfontset_info, Qnil);
1835 tables[1] = Fmake_char_table (Qnil, Qnil);
1836 XCHAR_TABLE (tables[0])->extras[0] = tables[1];
1837 fontsets[0] = fontset;
1838 fontsets[1] = Vdefault_fontset;
e2b45cf9 1839
1d5d7200
KH
1840 /* Accumulate information of the fontset in TABLE. The format of
1841 each element is ((FONT-SPEC OPENED-FONT ...) ...). */
cc7b6145 1842 for (k = 0; k <= 1; k++)
0d407d77 1843 {
cc7b6145 1844 for (c = 0; c <= MAX_CHAR; )
d6aaac9e
KH
1845 {
1846 int from, to;
0d407d77 1847
cc7b6145
KH
1848 if (c <= MAX_5_BYTE_CHAR)
1849 {
1850 val = char_table_ref_and_range (fontsets[k], c, &from, &to);
1851 if (to > MAX_5_BYTE_CHAR)
1852 to = MAX_5_BYTE_CHAR;
1853 }
1854 else
1855 {
1856 val = FONTSET_FALLBACK (fontsets[k]);
1857 to = MAX_CHAR;
1858 }
d6aaac9e 1859 if (VECTORP (val))
0d407d77 1860 {
d6aaac9e
KH
1861 Lisp_Object alist;
1862
1863 /* At first, set ALIST to ((FONT-SPEC) ...). */
1864 for (alist = Qnil, i = 0; i < ASIZE (val); i++)
581f7ac7
KH
1865 if (! NILP (AREF (val, i)))
1866 alist = Fcons (Fcons (FONT_DEF_SPEC (AREF (val, i)), Qnil),
1867 alist);
d6aaac9e
KH
1868 alist = Fnreverse (alist);
1869
1870 /* Then store opend font names to cdr of each elements. */
cc7b6145 1871 for (i = 0; ! NILP (realized[k][i]); i++)
1ff005e1 1872 {
cc7b6145
KH
1873 if (c <= MAX_5_BYTE_CHAR)
1874 val = FONTSET_REF (realized[k][i], c);
1875 else
1876 val = FONTSET_FALLBACK (realized[k][i]);
1877 if (! VECTORP (val))
d6aaac9e 1878 continue;
581f7ac7
KH
1879 /* VAL: [int ? [FACE-ID FONT-DEF FONT-OBJECT int] ... ] */
1880 for (j = 2; j < ASIZE (val); j++)
3d4448a8 1881 {
581f7ac7
KH
1882 elt = AREF (val, j);
1883 if (FONT_OBJECT_P (RFONT_DEF_OBJECT (elt)))
1884 {
1885 Lisp_Object font_object = RFONT_DEF_OBJECT (elt);
1886 Lisp_Object slot, name;
1887
1888 slot = Fassq (RFONT_DEF_SPEC (elt), alist);
1889 name = AREF (font_object, FONT_NAME_INDEX);
1890 if (NILP (Fmember (name, XCDR (slot))))
1891 nconc2 (slot, Fcons (name, Qnil));
1892 }
3d4448a8 1893 }
1ff005e1 1894 }
d6aaac9e
KH
1895
1896 /* Store ALIST in TBL for characters C..TO. */
cc7b6145
KH
1897 if (c <= MAX_5_BYTE_CHAR)
1898 char_table_set_range (tables[k], c, to, alist);
1899 else
1900 XCHAR_TABLE (tables[k])->defalt = alist;
581f7ac7
KH
1901
1902 /* At last, change each elements to font names. */
1903 for (; CONSP (alist); alist = XCDR (alist))
1904 {
1905 elt = XCAR (alist);
7ae2e7f0 1906 XSETCAR (elt, Ffont_xlfd_name (XCAR (elt), Qnil));
581f7ac7 1907 }
0d407d77 1908 }
d6aaac9e 1909 c = to + 1;
0d407d77
KH
1910 }
1911 }
a921395d 1912
cc7b6145 1913 return tables[0];
4ed46869
KH
1914}
1915
1d5d7200 1916
0fdf26e6 1917DEFUN ("fontset-font", Ffontset_font, Sfontset_font, 2, 3, 0,
335c5470 1918 doc: /* Return a font name pattern for character CH in fontset NAME.
0fdf26e6
KH
1919If NAME is t, find a pattern in the default fontset.
1920
1921The value has the form (FAMILY . REGISTRY), where FAMILY is a font
1922family name and REGISTRY is a font registry name. This is actually
1923the first font name pattern for CH in the fontset or in the default
1924fontset.
1925
1926If the 2nd optional arg ALL is non-nil, return a list of all font name
1927patterns. */)
1928 (name, ch, all)
1929 Lisp_Object name, ch, all;
0d407d77 1930{
1337ac77 1931 int c;
0fdf26e6
KH
1932 Lisp_Object fontset, elt, list, repertory, val;
1933 int i, j;
0d407d77
KH
1934
1935 fontset = check_fontset_name (name);
1936
06f76f0d 1937 CHECK_CHARACTER (ch);
0d407d77 1938 c = XINT (ch);
0fdf26e6
KH
1939 list = Qnil;
1940 while (1)
1941 {
1942 for (i = 0, elt = FONTSET_REF (fontset, c); i < 2;
1943 i++, elt = FONTSET_FALLBACK (fontset))
1944 if (VECTORP (elt))
1945 for (j = 0; j < ASIZE (elt); j++)
1946 {
1947 val = AREF (elt, j);
1948 repertory = AREF (val, 1);
1949 if (INTEGERP (repertory))
1950 {
1951 struct charset *charset = CHARSET_FROM_ID (XINT (repertory));
1952
1953 if (! CHAR_CHARSET_P (c, charset))
1954 continue;
1955 }
1956 else if (CHAR_TABLE_P (repertory))
1957 {
1958 if (NILP (CHAR_TABLE_REF (repertory, c)))
1959 continue;
1960 }
1961 val = AREF (val, 0);
1962 val = Fcons (AREF (val, 0), AREF (val, 5));
1963 if (NILP (all))
1964 return val;
1965 list = Fcons (val, list);
1966 }
1967 if (EQ (fontset, Vdefault_fontset))
1968 break;
1969 fontset = Vdefault_fontset;
1970 }
1971 return (Fnreverse (list));
0d407d77 1972}
0d407d77
KH
1973
1974DEFUN ("fontset-list", Ffontset_list, Sfontset_list, 0, 0, 0,
335c5470
PJ
1975 doc: /* Return a list of all defined fontset names. */)
1976 ()
0d407d77
KH
1977{
1978 Lisp_Object fontset, list;
1979 int i;
1980
1981 list = Qnil;
1982 for (i = 0; i < ASIZE (Vfontset_table); i++)
1983 {
1984 fontset = FONTSET_FROM_ID (i);
1985 if (!NILP (fontset)
1986 && BASE_FONTSET_P (fontset))
1987 list = Fcons (FONTSET_NAME (fontset), list);
1988 }
1ff005e1 1989
0d407d77
KH
1990 return list;
1991}
1992
452a78e0
KH
1993
1994#ifdef FONTSET_DEBUG
1995
1996Lisp_Object
1997dump_fontset (fontset)
1998 Lisp_Object fontset;
1999{
2000 Lisp_Object vec;
2001
2002 vec = Fmake_vector (make_number (3), Qnil);
2003 ASET (vec, 0, FONTSET_ID (fontset));
2004
2005 if (BASE_FONTSET_P (fontset))
2006 {
2007 ASET (vec, 1, FONTSET_NAME (fontset));
2008 }
2009 else
2010 {
2011 Lisp_Object frame;
2012
2013 frame = FONTSET_FRAME (fontset);
2014 if (FRAMEP (frame))
2015 {
2016 FRAME_PTR f = XFRAME (frame);
2017
2018 if (FRAME_LIVE_P (f))
1c82b4b3
KH
2019 ASET (vec, 1,
2020 Fcons (FONTSET_NAME (FONTSET_BASE (fontset)), f->name));
452a78e0 2021 else
1c82b4b3
KH
2022 ASET (vec, 1,
2023 Fcons (FONTSET_NAME (FONTSET_BASE (fontset)), Qnil));
452a78e0 2024 }
eb36588a
KH
2025 if (!NILP (FONTSET_DEFAULT (fontset)))
2026 ASET (vec, 2, FONTSET_ID (FONTSET_DEFAULT (fontset)));
452a78e0
KH
2027 }
2028 return vec;
2029}
2030
2031DEFUN ("fontset-list-all", Ffontset_list_all, Sfontset_list_all, 0, 0, 0,
2032 doc: /* Return a brief summary of all fontsets for debug use. */)
2033 ()
2034{
2035 Lisp_Object val;
2036 int i;
2037
2038 for (i = 0, val = Qnil; i < ASIZE (Vfontset_table); i++)
2039 if (! NILP (AREF (Vfontset_table, i)))
2040 val = Fcons (dump_fontset (AREF (Vfontset_table, i)), val);
2041 return (Fnreverse (val));
2042}
2043#endif /* FONTSET_DEBUG */
2044
dfcf069d 2045void
4ed46869
KH
2046syms_of_fontset ()
2047{
1d5d7200 2048 DEFSYM (Qfontset, "fontset");
eb36588a 2049 Fput (Qfontset, Qchar_table_extra_slots, make_number (9));
d6aaac9e
KH
2050 DEFSYM (Qfontset_info, "fontset-info");
2051 Fput (Qfontset_info, Qchar_table_extra_slots, make_number (1));
4ed46869 2052
1d5d7200
KH
2053 DEFSYM (Qprepend, "prepend");
2054 DEFSYM (Qappend, "append");
c3fb88cc 2055 DEFSYM (Qlatin, "latin");
4ed46869
KH
2056
2057 Vcached_fontset_data = Qnil;
2058 staticpro (&Vcached_fontset_data);
2059
0d407d77
KH
2060 Vfontset_table = Fmake_vector (make_number (32), Qnil);
2061 staticpro (&Vfontset_table);
0d407d77
KH
2062
2063 Vdefault_fontset = Fmake_char_table (Qfontset, Qnil);
2064 staticpro (&Vdefault_fontset);
1ff005e1
KH
2065 FONTSET_ID (Vdefault_fontset) = make_number (0);
2066 FONTSET_NAME (Vdefault_fontset)
2067 = build_string ("-*-*-*-*-*-*-*-*-*-*-*-*-fontset-default");
ff7a2223 2068 ASET (Vfontset_table, 0, Vdefault_fontset);
1ff005e1 2069 next_fontset_id = 1;
4ed46869 2070
452a78e0
KH
2071 auto_fontset_alist = Qnil;
2072 staticpro (&auto_fontset_alist);
2073
28e2436a
KH
2074 DEFVAR_LISP ("font-encoding-charset-alist", &Vfont_encoding_charset_alist,
2075 doc: /*
2076Alist of charsets vs the charsets to determine the preferred font encoding.
eb152aa9 2077Each element looks like (CHARSET . ENCODING-CHARSET),
28e2436a
KH
2078where ENCODING-CHARSET is a charset registered in the variable
2079`font-encoding-alist' as ENCODING.
2080
2081When a text has a property `charset' and the value is CHARSET, a font
2082whose encoding corresponds to ENCODING-CHARSET is preferred. */);
2083 Vfont_encoding_charset_alist = Qnil;
2084
6a7e6d80 2085 DEFVAR_LISP ("use-default-ascent", &Vuse_default_ascent,
1d5d7200
KH
2086 doc: /*
2087Char table of characters whose ascent values should be ignored.
335c5470 2088If an entry for a character is non-nil, the ascent value of the glyph
eb152aa9 2089is assumed to be specified by _MULE_DEFAULT_ASCENT property of a font.
335c5470
PJ
2090
2091This affects how a composite character which contains
2092such a character is displayed on screen. */);
2aeafb78
KH
2093 Vuse_default_ascent = Qnil;
2094
2095 DEFVAR_LISP ("ignore-relative-composition", &Vignore_relative_composition,
1d5d7200 2096 doc: /*
eb152aa9 2097Char table of characters which are not composed relatively.
335c5470
PJ
2098If an entry for a character is non-nil, a composition sequence
2099which contains that character is displayed so that
2100the glyph of that character is put without considering
2101an ascent and descent value of a previous character. */);
810abb87 2102 Vignore_relative_composition = Qnil;
6a7e6d80 2103
01d4b817 2104 DEFVAR_LISP ("alternate-fontname-alist", &Valternate_fontname_alist,
335c5470
PJ
2105 doc: /* Alist of fontname vs list of the alternate fontnames.
2106When a specified font name is not found, the corresponding
2107alternate fontnames (if any) are tried instead. */);
01d4b817 2108 Valternate_fontname_alist = Qnil;
8c83e4f9 2109
1c283e35 2110 DEFVAR_LISP ("fontset-alias-alist", &Vfontset_alias_alist,
335c5470 2111 doc: /* Alist of fontset names vs the aliases. */);
1ff005e1
KH
2112 Vfontset_alias_alist = Fcons (Fcons (FONTSET_NAME (Vdefault_fontset),
2113 build_string ("fontset-default")),
2114 Qnil);
1c283e35 2115
810abb87
KH
2116 DEFVAR_LISP ("vertical-centering-font-regexp",
2117 &Vvertical_centering_font_regexp,
335c5470
PJ
2118 doc: /* *Regexp matching font names that require vertical centering on display.
2119When a character is displayed with such fonts, the character is displayed
fc8865fc 2120at the vertical center of lines. */);
810abb87
KH
2121 Vvertical_centering_font_regexp = Qnil;
2122
21ff5ed6
KH
2123 DEFVAR_LISP ("otf-script-alist", &Votf_script_alist,
2124 doc: /* Alist of OpenType script tags vs the corresponding script names. */);
2125 Votf_script_alist = Qnil;
2126
4ed46869
KH
2127 defsubr (&Squery_fontset);
2128 defsubr (&Snew_fontset);
2129 defsubr (&Sset_fontset_font);
2130 defsubr (&Sfont_info);
1ff005e1 2131 defsubr (&Sinternal_char_font);
4ed46869 2132 defsubr (&Sfontset_info);
0d407d77
KH
2133 defsubr (&Sfontset_font);
2134 defsubr (&Sfontset_list);
452a78e0
KH
2135#ifdef FONTSET_DEBUG
2136 defsubr (&Sfontset_list_all);
2137#endif
e3400864 2138}
92c15c34
KH
2139
2140/* arch-tag: ea861585-2f5f-4e5b-9849-d04a9c3a3537
2141 (do not change this comment) */