* font.c [HAVE_M17N_FLT]: Include <m17n-flt.h>.
[bpt/emacs.git] / src / fontset.c
CommitLineData
4ed46869 1/* Fontset handler.
429ab54e
GM
2 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007
3 Free Software Foundation, Inc.
7976eda0 4 Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
7cdc02a6 5 2005, 2006, 2007
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
41882805 11
369314dc
KH
12This file is part of GNU Emacs.
13
14GNU Emacs is free software; you can redistribute it and/or modify
15it under the terms of the GNU General Public License as published by
1427aa65 16the Free Software Foundation; either version 3, or (at your option)
369314dc 17any 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
KH
24You should have received a copy of the GNU General Public License
25along with GNU Emacs; see the file COPYING. If not, write to
4fc5845f
LK
26the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
27Boston, MA 02110-1301, USA. */
4ed46869 28
0d407d77
KH
29/* #define FONTSET_DEBUG */
30
4ed46869 31#include <config.h>
0d407d77
KH
32
33#ifdef FONTSET_DEBUG
34#include <stdio.h>
35#endif
36
4ed46869 37#include "lisp.h"
06f76f0d 38#include "blockinput.h"
1ff005e1 39#include "buffer.h"
06f76f0d 40#include "character.h"
4ed46869
KH
41#include "charset.h"
42#include "ccl.h"
2538fae4 43#include "keyboard.h"
4ed46869 44#include "frame.h"
0d407d77 45#include "dispextern.h"
e1a14cdc 46#include "intervals.h"
3541bb8f 47#include "fontset.h"
0d407d77 48#include "window.h"
92c15c34
KH
49#ifdef HAVE_X_WINDOWS
50#include "xterm.h"
51#endif
52#ifdef WINDOWSNT
53#include "w32term.h"
54#endif
55#ifdef MAC_OS
56#include "macterm.h"
57#endif
fa971ac3 58#include "termhooks.h"
0d407d77 59
8aa07a8d
KH
60#ifdef USE_FONT_BACKEND
61#include "font.h"
62#endif /* USE_FONT_BACKEND */
63
0d407d77 64#undef xassert
8f924df7 65#ifdef FONTSET_DEBUG
0d407d77
KH
66#define xassert(X) do {if (!(X)) abort ();} while (0)
67#undef INLINE
68#define INLINE
8f924df7
KH
69#else /* not FONTSET_DEBUG */
70#define xassert(X) (void) 0
71#endif /* not FONTSET_DEBUG */
0d407d77 72
a980c932 73EXFUN (Fclear_face_cache, 1);
0d407d77
KH
74
75/* FONTSET
76
77 A fontset is a collection of font related information to give
1d5d7200
KH
78 similar appearance (style, etc) of characters. A fontset has two
79 roles. One is to use for the frame parameter `font' as if it is an
80 ASCII font. In that case, Emacs uses the font specified for
81 `ascii' script for the frame's default font.
82
83 Another role, the more important one, is to provide information
84 about which font to use for each non-ASCII character.
85
86 There are two kinds of fontsets; base and realized. A base fontset
87 is created by `new-fontset' from Emacs Lisp explicitly. A realized
88 fontset is created implicitly when a face is realized for ASCII
89 characters. A face is also realized for non-ASCII characters based
90 on an ASCII face. All of non-ASCII faces based on the same ASCII
91 face share the same realized fontset.
8f924df7 92
06f76f0d
KH
93 A fontset object is implemented by a char-table whose default value
94 and parent are always nil.
fc8865fc 95
1d5d7200
KH
96 An element of a base fontset is a vector of FONT-DEFs which itself
97 is a vector [ FONT-SPEC ENCODING REPERTORY ].
98
99 FONT-SPEC is:
100 [ FAMILY WEIGHT SLANT SWIDTH ADSTYLE REGISTRY ]
06f76f0d 101 or
1d5d7200
KH
102 FONT-NAME
103 where FAMILY, WEIGHT, SLANT, SWIDTH, ADSTYLE, REGISTRY, and
104 FONT-NAME are strings.
105
7e1a1cd9
KH
106 Note: Currently WEIGHT through ADSTYLE are ignored.
107
57e13af9
KH
108 ENCODING is a charset ID that can convert characters to glyph codes
109 of the corresponding font.
1d5d7200 110
57e13af9
KH
111 REPERTORY is a charset ID, a char-table, or nil. If REPERTORY is a
112 charset ID, the repertory of the charset exactly matches with that
113 of the font. If REPERTORY is a char-table, all characters who have
114 a non-nil value in the table are supported. If REPERTORY is nil,
115 we consult with the font itself to get the repertory.
1d5d7200
KH
116
117 ENCODING and REPERTORY are extracted from the variable
57e13af9 118 Vfont_encoding_alist by using a font name generated from FONT-SPEC
7e1a1cd9 119 (if it is a vector) or FONT-NAME as a matching target.
1d5d7200
KH
120
121
122 An element of a realized fontset is nil or t, or has this form:
fc8865fc 123
7e1a1cd9
KH
124 [CHARSET-ORDERED-LIST-TICK PREFERRED-CHARSET-ID
125 PREFERRED-RFONT-DEF RFONT-DEF0 RFONT-DEF1 ...].
0d407d77 126
7e1a1cd9 127 RFONT-DEFn (i.e. Realized FONT-DEF) has this form:
0d407d77 128
7e1a1cd9 129 [ FACE-ID FONT-INDEX FONT-DEF OPENED-FONT-NAME ]
0d407d77 130
7e1a1cd9 131 RFONT-DEFn is automatically reordered by the current charset
1d5d7200 132 priority list.
0d407d77 133
7e1a1cd9
KH
134 The value nil means that we have not yet generated the above vector
135 from the base of the fontset.
0d407d77 136
1d5d7200
KH
137 The value t means that no font is available for the corresponding
138 range of characters.
0d407d77 139
0d407d77 140
eb36588a 141 A fontset has 9 extra slots.
0d407d77 142
1d5d7200 143 The 1st slot: the ID number of the fontset
0d407d77 144
1d5d7200
KH
145 The 2nd slot:
146 base: the name of the fontset
147 realized: nil
0d407d77 148
1d5d7200 149 The 3rd slot:
d6aaac9e 150 base: nil
1d5d7200 151 realized: the base fontset
06f76f0d 152
1d5d7200
KH
153 The 4th slot:
154 base: nil
155 realized: the frame that the fontset belongs to
0d407d77 156
1d5d7200
KH
157 The 5th slot:
158 base: the font name for ASCII characters
159 realized: nil
0d407d77 160
1d5d7200
KH
161 The 6th slot:
162 base: nil
163 realized: the ID number of a face to use for characters that
164 has no font in a realized fontset.
0d407d77 165
1d5d7200
KH
166 The 7th slot:
167 base: nil
168 realized: Alist of font index vs the corresponding repertory
169 char-table.
170
d6aaac9e
KH
171 The 8th slot:
172 base: nil
173 realized: If the base is not the default fontset, a fontset
174 realized from the default fontset, else nil.
1d5d7200 175
eb36588a 176 The 9th slot:
cc7b6145
KH
177 base: Same as element value (but for fallback fonts).
178 realized: Likewise.
eb36588a 179
1d5d7200 180 All fontsets are recorded in the vector Vfontset_table.
0d407d77
KH
181
182
183 DEFAULT FONTSET
184
1d5d7200
KH
185 There's a special base fontset named `default fontset' which
186 defines the default font specifications. When a base fontset
187 doesn't specify a font for a specific character, the corresponding
188 value in the default fontset is used.
0d407d77 189
afe93d01
KH
190 The parent of a realized fontset created for such a face that has
191 no fontset is the default fontset.
0d407d77
KH
192
193
194 These structures are hidden from the other codes than this file.
195 The other codes handle fontsets only by their ID numbers. They
06f76f0d
KH
196 usually use the variable name `fontset' for IDs. But, in this
197 file, we always use varialbe name `id' for IDs, and name `fontset'
1d5d7200 198 for an actual fontset object, i.e., char-table.
0d407d77
KH
199
200*/
201
202/********** VARIABLES and FUNCTION PROTOTYPES **********/
203
204extern Lisp_Object Qfont;
d6aaac9e
KH
205static Lisp_Object Qfontset;
206static Lisp_Object Qfontset_info;
1d5d7200 207static Lisp_Object Qprepend, Qappend;
c3fb88cc 208static Lisp_Object Qlatin;
0d407d77
KH
209
210/* Vector containing all fontsets. */
211static Lisp_Object Vfontset_table;
212
fc8865fc 213/* Next possibly free fontset ID. Usually this keeps the minimum
0d407d77
KH
214 fontset ID not yet used. */
215static int next_fontset_id;
216
217/* The default fontset. This gives default FAMILY and REGISTRY of
06f76f0d 218 font for each character. */
0d407d77 219static Lisp_Object Vdefault_fontset;
4ed46869 220
4ed46869 221Lisp_Object Vfont_encoding_alist;
6a7e6d80 222Lisp_Object Vuse_default_ascent;
2aeafb78 223Lisp_Object Vignore_relative_composition;
01d4b817 224Lisp_Object Valternate_fontname_alist;
1c283e35 225Lisp_Object Vfontset_alias_alist;
810abb87 226Lisp_Object Vvertical_centering_font_regexp;
21ff5ed6 227Lisp_Object Votf_script_alist;
4ed46869 228
0d407d77
KH
229/* The following six are declarations of callback functions depending
230 on window system. See the comments in src/fontset.h for more
231 detail. */
4ed46869
KH
232
233/* Return a pointer to struct font_info of font FONT_IDX of frame F. */
5771dcf4 234struct font_info *(*get_font_info_func) P_ ((FRAME_PTR f, int font_idx));
4ed46869 235
fc8865fc
PJ
236/* Return a list of font names which matches PATTERN. See the documentation
237 of `x-list-fonts' for more details. */
3541bb8f
KH
238Lisp_Object (*list_fonts_func) P_ ((struct frame *f,
239 Lisp_Object pattern,
240 int size,
241 int maxnames));
4ed46869
KH
242
243/* Load a font named NAME for frame F and return a pointer to the
244 information of the loaded font. If loading is failed, return 0. */
5771dcf4 245struct font_info *(*load_font_func) P_ ((FRAME_PTR f, char *name, int));
4ed46869
KH
246
247/* Return a pointer to struct font_info of a font named NAME for frame F. */
5771dcf4 248struct font_info *(*query_font_func) P_ ((FRAME_PTR f, char *name));
4ed46869
KH
249
250/* Additional function for setting fontset or changing fontset
251 contents of frame F. */
5771dcf4
AS
252void (*set_frame_fontset_func) P_ ((FRAME_PTR f, Lisp_Object arg,
253 Lisp_Object oldval));
4ed46869 254
727fb790
KH
255/* To find a CCL program, fs_load_font calls this function.
256 The argument is a pointer to the struct font_info.
fc8865fc 257 This function set the member `encoder' of the structure. */
727fb790
KH
258void (*find_ccl_program_func) P_ ((struct font_info *));
259
1d5d7200
KH
260Lisp_Object (*get_font_repertory_func) P_ ((struct frame *,
261 struct font_info *));
262
4ed46869 263/* Check if any window system is used now. */
5771dcf4 264void (*check_window_system_func) P_ ((void));
4ed46869 265
0d407d77
KH
266
267/* Prototype declarations for static functions. */
b11a4ed7
DL
268static Lisp_Object fontset_add P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
269 Lisp_Object));
7e1a1cd9 270static Lisp_Object fontset_font P_ ((Lisp_Object, int, struct face *, int));
0d407d77 271static Lisp_Object make_fontset P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
0d407d77 272static Lisp_Object fontset_pattern_regexp P_ ((Lisp_Object));
1d5d7200
KH
273static void accumulate_script_ranges P_ ((Lisp_Object, Lisp_Object,
274 Lisp_Object));
8aa07a8d 275Lisp_Object find_font_encoding P_ ((Lisp_Object));
0d407d77 276
2449d4d0
KH
277static void set_fontset_font P_ ((Lisp_Object, Lisp_Object));
278
556383ac
KH
279#ifdef FONTSET_DEBUG
280
281/* Return 1 if ID is a valid fontset id, else return 0. */
282
283static int
284fontset_id_valid_p (id)
285 int id;
286{
287 return (id >= 0 && id < ASIZE (Vfontset_table) - 1);
288}
289
290#endif
291
0d407d77
KH
292
293\f
294/********** MACROS AND FUNCTIONS TO HANDLE FONTSET **********/
295
0d407d77
KH
296/* Return the fontset with ID. No check of ID's validness. */
297#define FONTSET_FROM_ID(id) AREF (Vfontset_table, id)
298
afe93d01 299/* Macros to access special values of FONTSET. */
0d407d77 300#define FONTSET_ID(fontset) XCHAR_TABLE (fontset)->extras[0]
06f76f0d
KH
301
302/* Macros to access special values of (base) FONTSET. */
0d407d77 303#define FONTSET_NAME(fontset) XCHAR_TABLE (fontset)->extras[1]
06f76f0d
KH
304#define FONTSET_ASCII(fontset) XCHAR_TABLE (fontset)->extras[4]
305
06f76f0d
KH
306/* Macros to access special values of (realized) FONTSET. */
307#define FONTSET_BASE(fontset) XCHAR_TABLE (fontset)->extras[2]
308#define FONTSET_FRAME(fontset) XCHAR_TABLE (fontset)->extras[3]
1d5d7200
KH
309#define FONTSET_NOFONT_FACE(fontset) XCHAR_TABLE (fontset)->extras[5]
310#define FONTSET_REPERTORY(fontset) XCHAR_TABLE (fontset)->extras[6]
eb36588a
KH
311#define FONTSET_DEFAULT(fontset) XCHAR_TABLE (fontset)->extras[7]
312
cc7b6145 313/* For both base and realized fontset. */
eb36588a 314#define FONTSET_FALLBACK(fontset) XCHAR_TABLE (fontset)->extras[8]
0d407d77 315
e3400864 316#define BASE_FONTSET_P(fontset) (NILP (FONTSET_BASE (fontset)))
0d407d77
KH
317
318
1d5d7200
KH
319/* Return the element of FONTSET for the character C. If FONTSET is a
320 base fontset other then the default fontset and FONTSET doesn't
321 contain information for C, return the information in the default
322 fontset. */
0d407d77 323
1d5d7200
KH
324#define FONTSET_REF(fontset, c) \
325 (EQ (fontset, Vdefault_fontset) \
326 ? CHAR_TABLE_REF (fontset, c) \
327 : fontset_ref ((fontset), (c)))
0d407d77 328
afe93d01 329static Lisp_Object
0d407d77
KH
330fontset_ref (fontset, c)
331 Lisp_Object fontset;
332 int c;
333{
06f76f0d
KH
334 Lisp_Object elt;
335
1d5d7200
KH
336 elt = CHAR_TABLE_REF (fontset, c);
337 if (NILP (elt) && ! EQ (fontset, Vdefault_fontset)
338 /* Don't check Vdefault_fontset for a realized fontset. */
339 && NILP (FONTSET_BASE (fontset)))
340 elt = CHAR_TABLE_REF (Vdefault_fontset, c);
0d407d77
KH
341 return elt;
342}
343
344
1d5d7200
KH
345/* Return the element of FONTSET for the character C, set FROM and TO
346 to the range of characters around C that have the same value as C.
347 If FONTSET is a base fontset other then the default fontset and
348 FONTSET doesn't contain information for C, return the information
349 in the default fontset. */
350
351#define FONTSET_REF_AND_RANGE(fontset, c, form, to) \
352 (EQ (fontset, Vdefault_fontset) \
353 ? char_table_ref_and_range (fontset, c, &from, &to) \
354 : fontset_ref_and_range (fontset, c, &from, &to))
0d407d77 355
afe93d01 356static Lisp_Object
1d5d7200 357fontset_ref_and_range (fontset, c, from, to)
0d407d77 358 Lisp_Object fontset;
1d5d7200
KH
359 int c;
360 int *from, *to;
0d407d77 361{
0d407d77 362 Lisp_Object elt;
0d407d77 363
1d5d7200
KH
364 elt = char_table_ref_and_range (fontset, c, from, to);
365 if (NILP (elt) && ! EQ (fontset, Vdefault_fontset)
366 /* Don't check Vdefault_fontset for a realized fontset. */
367 && NILP (FONTSET_BASE (fontset)))
06f76f0d 368 {
1d5d7200 369 int from1, to1;
0d407d77 370
1d5d7200
KH
371 elt = char_table_ref_and_range (Vdefault_fontset, c, &from1, &to1);
372 if (*from < from1)
373 *from = from1;
374 if (*to > to1)
375 *to = to1;
06f76f0d 376 }
0d407d77
KH
377 return elt;
378}
379
380
1d5d7200
KH
381/* Set elements of FONTSET for characters in RANGE to the value ELT.
382 RANGE is a cons (FROM . TO), where FROM and TO are character codes
383 specifying a range. */
384
385#define FONTSET_SET(fontset, range, elt) \
386 Fset_char_table_range ((fontset), (range), (elt))
387
0d407d77 388
1d5d7200 389/* Modify the elements of FONTSET for characters in RANGE by replacing
6bad8007 390 with ELT or adding ELT. RANGE is a cons (FROM . TO), where FROM
1d5d7200
KH
391 and TO are character codes specifying a range. If ADD is nil,
392 replace with ELT, if ADD is `prepend', prepend ELT, otherwise,
393 append ELT. */
394
cc7b6145
KH
395#define FONTSET_ADD(fontset, range, elt, add) \
396 (NILP (add) \
397 ? (NILP (range) \
398 ? (FONTSET_FALLBACK (fontset) = Fmake_vector (make_number (1), (elt))) \
399 : Fset_char_table_range ((fontset), (range), \
400 Fmake_vector (make_number (1), (elt)))) \
1d5d7200 401 : fontset_add ((fontset), (range), (elt), (add)))
0d407d77 402
b11a4ed7 403static Lisp_Object
1d5d7200 404fontset_add (fontset, range, elt, add)
00c4da0f 405 Lisp_Object fontset, range, elt, add;
06f76f0d 406{
eb36588a
KH
407 Lisp_Object args[2];
408 int idx = (EQ (add, Qappend) ? 0 : 1);
409
410 args[1 - idx] = Fmake_vector (make_number (1), elt);
411
412 if (CONSP (range))
413 {
414 int from = XINT (XCAR (range));
415 int to = XINT (XCDR (range));
416 int from1, to1;
417
418 do {
419 args[idx] = char_table_ref_and_range (fontset, from, &from1, &to1);
420 if (to < to1)
421 to1 = to;
422 char_table_set_range (fontset, from, to1,
423 NILP (args[idx]) ? args[1 - idx]
424 : Fvconcat (2, args));
425 from = to1 + 1;
426 } while (from < to);
427 }
428 else
429 {
430 args[idx] = FONTSET_FALLBACK (fontset);
431 FONTSET_FALLBACK (fontset)
432 = NILP (args[idx]) ? args[1 - idx] : Fvconcat (2, args);
433 }
b11a4ed7 434 return Qnil;
1d5d7200
KH
435}
436
437
438/* Update FONTSET_ELEMENT which has this form:
7e1a1cd9
KH
439 [CHARSET-ORDERED-LIST-TICK PREFERRED-CHARSET-ID PREFERRED-RFONT-DEF
440 RFONT-DEF0 RFONT-DEF1 ...].
441 Reorder RFONT-DEFs according to the current order of charset
442 (Vcharset_ordered_list), and update CHARSET-ORDERED-LIST-TICK to
1d5d7200 443 the latest value. */
0d407d77
KH
444
445static void
1d5d7200
KH
446reorder_font_vector (fontset_element)
447 Lisp_Object fontset_element;
448{
0fdf26e6 449 Lisp_Object list, *new_vec;
6bad8007 450 Lisp_Object font_def;
1d5d7200
KH
451 int size;
452 int *charset_id_table;
453 int i, idx;
454
6bad8007
KH
455 ASET (fontset_element, 0, make_number (charset_ordered_list_tick));
456 size = ASIZE (fontset_element) - 3;
457 if (size <= 1)
7e1a1cd9 458 /* No need to reorder VEC. */
1d5d7200
KH
459 return;
460 charset_id_table = (int *) alloca (sizeof (int) * size);
461 new_vec = (Lisp_Object *) alloca (sizeof (Lisp_Object) * size);
6bad8007
KH
462
463 /* At first, extract ENCODING (a chaset ID) from each FONT-DEF.
464 FONT-DEF has this form:
465 [FACE-ID FONT-INDEX [ FONT-SPEC ENCODING REPERTORY ]] */
1d5d7200 466 for (i = 0; i < size; i++)
6bad8007
KH
467 {
468 font_def = AREF (fontset_element, i + 3);
ae54cb3c
KH
469 if (VECTORP (AREF (font_def, 2))
470 && INTEGERP (AREF (AREF (font_def, 2), 1)))
02dacbbc
KH
471 charset_id_table[i] = XINT (AREF (AREF (font_def, 2), 1));
472 else
473 charset_id_table[i] = -1;
6bad8007 474 }
1d5d7200 475
6bad8007
KH
476 /* Then, store FONT-DEFs in NEW_VEC in the correct order. */
477 for (idx = 0, list = Vcharset_ordered_list;
478 idx < size && CONSP (list); list = XCDR (list))
06f76f0d 479 {
1d5d7200
KH
480 for (i = 0; i < size; i++)
481 if (charset_id_table[i] == XINT (XCAR (list)))
6bad8007 482 new_vec[idx++] = AREF (fontset_element, i + 3);
06f76f0d 483 }
02dacbbc
KH
484 for (i = 0; i < size; i++)
485 if (charset_id_table[i] < 0)
486 new_vec[idx++] = AREF (fontset_element, i + 3);
0d407d77 487
6bad8007 488 /* At last, update FONT-DEFs. */
1d5d7200 489 for (i = 0; i < size; i++)
6bad8007 490 ASET (fontset_element, i + 3, new_vec[i]);
1d5d7200
KH
491}
492
493
494/* Load a font matching the font related attributes in FACE->lface and
495 font pattern in FONT_DEF of FONTSET, and return an index of the
496 font. FONT_DEF has this form:
497 [ FONT-SPEC ENCODING REPERTORY ]
498 If REPERTORY is nil, generate a char-table representing the font
499 repertory by looking into the font itself. */
500
501static int
502load_font_get_repertory (f, face, font_def, fontset)
503 FRAME_PTR f;
504 struct face *face;
505 Lisp_Object font_def;
506 Lisp_Object fontset;
507{
508 char *font_name;
509 struct font_info *font_info;
f7a9f116 510 int charset;
1d5d7200 511
8f924df7 512 font_name = choose_face_font (f, face->lface, AREF (font_def, 0), NULL);
fb78e2ed 513 charset = XINT (AREF (font_def, 1));
f7a9f116 514 if (! (font_info = fs_load_font (f, font_name, charset)))
1d5d7200
KH
515 return -1;
516
517 if (NILP (AREF (font_def, 2))
518 && NILP (Fassq (make_number (font_info->font_idx),
519 FONTSET_REPERTORY (fontset))))
520 {
521 /* We must look into the font to get the correct repertory as a
522 char-table. */
523 Lisp_Object repertory;
524
525 repertory = (*get_font_repertory_func) (f, font_info);
526 FONTSET_REPERTORY (fontset)
527 = Fcons (Fcons (make_number (font_info->font_idx), repertory),
8f924df7 528 FONTSET_REPERTORY (fontset));
06f76f0d 529 }
1d5d7200
KH
530
531 return font_info->font_idx;
0d407d77
KH
532}
533
1c82b4b3
KH
534static Lisp_Object fontset_find_font P_ ((Lisp_Object, int, struct face *,
535 int, int));
0d407d77 536
7e1a1cd9
KH
537/* Return RFONT-DEF (vector) in the realized fontset FONTSET for the
538 character C. If the corresponding font is not yet opened, open it
539 (if FACE is not NULL) or return Qnil (if FACE is NULL).
1c82b4b3
KH
540 If no proper font is found for C, return Qnil.
541 ID is a charset-id that must be preferred, or -1 meaning no
542 preference.
543 If FALLBACK if nonzero, search only fallback fonts. */
0d407d77 544
7e1a1cd9 545static Lisp_Object
1c82b4b3 546fontset_find_font (fontset, c, face, id, fallback)
0d407d77
KH
547 Lisp_Object fontset;
548 int c;
1d5d7200 549 struct face *face;
1c82b4b3 550 int id, fallback;
0d407d77 551{
ae54cb3c 552 Lisp_Object base_fontset, elt, vec, font_def;
1d5d7200
KH
553 int i, from, to;
554 int font_idx;
555 FRAME_PTR f = XFRAME (FONTSET_FRAME (fontset));
0d407d77 556
d6aaac9e 557 base_fontset = FONTSET_BASE (fontset);
1c82b4b3
KH
558 if (! fallback)
559 vec = CHAR_TABLE_REF (fontset, c);
560 else
561 vec = FONTSET_FALLBACK (fontset);
cc7b6145 562 if (NILP (vec))
1d5d7200 563 {
1c82b4b3 564 /* We have not yet decided a font for C. */
d6aaac9e 565 Lisp_Object range;
1d5d7200
KH
566
567 if (! face)
7e1a1cd9 568 return Qnil;
1c82b4b3
KH
569 if (! fallback)
570 elt = FONTSET_REF_AND_RANGE (base_fontset, c, from, to);
571 else
572 elt = FONTSET_FALLBACK (base_fontset);
1d5d7200
KH
573 range = Fcons (make_number (from), make_number (to));
574 if (NILP (elt))
575 {
1c82b4b3 576 /* Qt means we have no font for characters of this range. */
cc7b6145 577 vec = Qt;
1d5d7200 578 }
02dacbbc 579 else
1d5d7200 580 {
1c82b4b3
KH
581 /* Build a vector [ -1 -1 nil NEW-ELT0 NEW-ELT1 NEW-ELT2 ... ],
582 where the first -1 is to force reordering of NEW-ELTn,
583 NEW-ELTn is [nil nil AREF (elt, n) nil]. */
8aa07a8d 584#ifdef USE_FONT_BACKEND
1c82b4b3
KH
585 if (! fallback
586 && enable_font_backend
587 && EQ (base_fontset, Vdefault_fontset))
4582742d
KH
588 /* Extra one element is for an automatically added
589 font-def specifying only a script. */
1c82b4b3 590 vec = Fmake_vector (make_number (ASIZE (elt) + 4), Qnil);
8aa07a8d 591 else
1c82b4b3
KH
592#endif /* not USE_FONT_BACKEND */
593 vec = Fmake_vector (make_number (ASIZE (elt) + 3), Qnil);
594 ASET (vec, 0, make_number (-1));
595 ASET (vec, 1, make_number (-1));
596 for (i = 0; i < ASIZE (elt); i++)
597 {
598 Lisp_Object tmp;
599
600 tmp = Fmake_vector (make_number (5), Qnil);
601 ASET (tmp, 2, AREF (elt, i));
602 ASET (vec, 3 + i, tmp);
603 }
02dacbbc 604#ifdef USE_FONT_BACKEND
1c82b4b3
KH
605 if (! fallback
606 && enable_font_backend
607 && EQ (base_fontset, Vdefault_fontset))
608 {
ae54cb3c 609 Lisp_Object script, font_spec;
1c82b4b3
KH
610
611 script = CHAR_TABLE_REF (Vchar_script_table, c);
612 if (NILP (script))
613 script = intern ("latin");
614 font_spec = Ffont_spec (0, NULL);
615 ASET (font_spec, FONT_REGISTRY_INDEX, Qiso10646_1);
616 ASET (font_spec, FONT_EXTRA_INDEX,
617 Fcons (Fcons (QCscript, script), Qnil));
ae54cb3c
KH
618 font_def = Fmake_vector (make_number (3), Qnil);
619 ASET (font_def, 0, font_spec);
620 elt = Fmake_vector (make_number (5), Qnil);
621 ASET (elt, 2, font_def);
622 ASET (vec, 3 + i, elt);
1c82b4b3 623 }
02dacbbc
KH
624#endif /* USE_FONT_BACKEND */
625
1c82b4b3
KH
626 /* Then store it in the fontset. */
627 if (! fallback)
628 FONTSET_SET (fontset, range, vec);
629 else
630 FONTSET_FALLBACK (fontset) = vec;
631 }
1d5d7200 632 }
1c82b4b3
KH
633 if (EQ (vec, Qt))
634 return Qnil;
0d407d77 635
6bad8007 636 if (XINT (AREF (vec, 0)) != charset_ordered_list_tick)
1d5d7200
KH
637 /* The priority of charsets is changed after we selected a face
638 for C last time. */
6bad8007
KH
639 reorder_font_vector (vec);
640
641 if (id < 0)
642 i = 3;
643 else if (id == XFASTINT (AREF (vec, 1)))
644 i = 2;
645 else
646 {
647 ASET (vec, 1, make_number (id));
648 for (i = 3; i < ASIZE (vec); i++)
649 if (id == XFASTINT (AREF (AREF (AREF (vec, i), 2), 1)))
650 break;
651 if (i < ASIZE (vec))
652 {
653 ASET (vec, 2, AREF (vec, i));
654 i = 2;
655 }
656 else
657 {
658 ASET (vec, 2, Qnil);
659 i = 3;
660 }
661 }
1d5d7200 662
7e1a1cd9 663 /* Find the first available font in the vector of RFONT-DEF. */
6bad8007 664 for (; i < ASIZE (vec); i++)
0d407d77 665 {
1d5d7200 666 elt = AREF (vec, i);
6bad8007
KH
667 if (NILP (elt))
668 continue;
7e1a1cd9 669 /* ELT == [ FACE-ID FONT-INDEX FONT-DEF OPENED-FONT-NAME ] */
1d5d7200
KH
670 if (INTEGERP (AREF (elt, 1)) && XINT (AREF (elt, 1)) < 0)
671 /* We couldn't open this font last time. */
672 continue;
673
7e1a1cd9
KH
674 if (!face && NILP (AREF (elt, 1)))
675 /* We have not yet opened the font. */
676 return Qnil;
1d5d7200 677
7e1a1cd9
KH
678 font_def = AREF (elt, 2);
679 /* FONT_DEF == [ FONT-SPEC ENCODING REPERTORY ] */
8aa07a8d
KH
680
681#ifdef USE_FONT_BACKEND
682 if (enable_font_backend)
683 {
684 /* ELT == [ FACE-ID FONT-INDEX FONT-DEF FONT-ENTITY FONT-OBJECT ] */
685 Lisp_Object font_entity = AREF (elt, 3);
686 Lisp_Object font_object = AREF (elt, 4);
4582742d 687 Lisp_Object font_spec = AREF (font_def, 0);
8aa07a8d
KH
688 int has_char;
689
4582742d 690 if (NILP (font_entity))
8aa07a8d 691 {
4582742d 692 if (! FONT_SPEC_P (font_spec))
8aa07a8d 693 {
4582742d
KH
694 /* FONT_SPEC is FONT-NAME or (FAMILY . REGISTRY). */
695 font_spec = Ffont_spec (0, NULL);
696 if (STRINGP (AREF (font_def, 0)))
697 font_merge_old_spec (AREF (font_def, 0), Qnil, Qnil,
698 font_spec);
699 else
700 {
701 Lisp_Object family = AREF (AREF (font_def, 0), 0);
702 Lisp_Object registry = AREF (AREF (font_def, 0), 5);;
703
704 font_merge_old_spec (Qnil, family, registry, font_spec);
705 }
706 ASET (font_def, 0, font_spec);
8aa07a8d 707 }
4582742d 708 font_entity = font_find_for_lface (f, face->lface, font_spec);
8aa07a8d 709 ASET (elt, 3, font_entity);
4582742d
KH
710 if (NILP (font_entity))
711 {
712 ASET (elt, 1, make_number (-1));
713 continue;
714 }
715 font_object = Qnil;
8aa07a8d
KH
716 }
717 has_char = font_has_char (f, font_entity, c);
718 if (has_char == 0)
719 continue;
8aa07a8d
KH
720 if (NILP (font_object))
721 {
4582742d
KH
722 font_object = font_open_for_lface (f, font_entity,
723 face->lface, font_spec);
724 ASET (elt, 4, font_object);
725 if (NILP (font_object))
726 {
727 ASET (elt, 1, make_number (-1));
728 continue;
729 }
8aa07a8d
KH
730 }
731 ASET (elt, 1, make_number (0));
732 ASET (elt, 4, font_object);
733 if (has_char < 0
734 && font_encode_char (font_object, c) == FONT_INVALID_CODE)
735 continue;
736 }
737 else
738#endif /* USE_FONT_BACKEND */
739
1d5d7200
KH
740 if (INTEGERP (AREF (font_def, 2)))
741 {
742 /* The repertory is specified by charset ID. */
743 struct charset *charset
744 = CHARSET_FROM_ID (XINT (AREF (font_def, 2)));
745
746 if (! CHAR_CHARSET_P (c, charset))
d6aaac9e 747 /* This font can't display C. */
1d5d7200
KH
748 continue;
749 }
57e13af9
KH
750 else if (CHAR_TABLE_P (AREF (font_def, 2)))
751 {
752 /* The repertory is specified by a char table. */
753 if (NILP (CHAR_TABLE_REF (AREF (font_def, 2), c)))
754 /* This font can't display C. */
755 continue;
756 }
1d5d7200
KH
757 else
758 {
759 Lisp_Object slot;
760
761 if (! INTEGERP (AREF (elt, 1)))
762 {
763 /* We have not yet opened a font matching this spec.
764 Open the best matching font now and register the
765 repertory. */
7e1a1cd9
KH
766 struct font_info *font_info;
767
1d5d7200
KH
768 font_idx = load_font_get_repertory (f, face, font_def, fontset);
769 ASET (elt, 1, make_number (font_idx));
770 if (font_idx < 0)
771 /* This means that we couldn't find a font matching
772 FONT_DEF. */
773 continue;
7e1a1cd9
KH
774 font_info = (*get_font_info_func) (f, font_idx);
775 ASET (elt, 3, build_string (font_info->full_name));
1d5d7200
KH
776 }
777
778 slot = Fassq (AREF (elt, 1), FONTSET_REPERTORY (fontset));
7e1a1cd9 779 xassert (CONSP (slot));
1d5d7200 780 if (NILP (CHAR_TABLE_REF (XCDR (slot), c)))
7e1a1cd9 781 /* This font can't display C. */
1d5d7200
KH
782 continue;
783 }
784
785 /* Now we have decided to use this font spec to display C. */
7e1a1cd9 786 if (! INTEGERP (AREF (elt, 1)))
1d5d7200
KH
787 {
788 /* But not yet opened the best matching font. */
7e1a1cd9
KH
789 struct font_info *font_info;
790
1d5d7200
KH
791 font_idx = load_font_get_repertory (f, face, font_def, fontset);
792 ASET (elt, 1, make_number (font_idx));
793 if (font_idx < 0)
7e1a1cd9 794 /* Can't open it. Try the other one. */
1d5d7200 795 continue;
7e1a1cd9
KH
796 font_info = (*get_font_info_func) (f, font_idx);
797 ASET (elt, 3, build_string (font_info->full_name));
1d5d7200
KH
798 }
799
800 /* Now we have the opened font. */
7e1a1cd9 801 return elt;
0d407d77 802 }
1c82b4b3
KH
803 return Qnil;
804}
0d407d77 805
cc7b6145 806
1c82b4b3
KH
807static Lisp_Object
808fontset_font (fontset, c, face, id)
809 Lisp_Object fontset;
810 int c;
811 struct face *face;
812 int id;
813{
814 Lisp_Object rfont_def;
815 Lisp_Object base_fontset;
cc7b6145 816
1c82b4b3
KH
817 /* Try a font-group for C. */
818 rfont_def = fontset_find_font (fontset, c, face, id, 0);
819 if (! NILP (rfont_def))
820 return rfont_def;
821 base_fontset = FONTSET_BASE (fontset);
822 /* Try a font-group for C of the default fontset. */
d6aaac9e 823 if (! EQ (base_fontset, Vdefault_fontset))
452a78e0 824 {
eb36588a
KH
825 if (NILP (FONTSET_DEFAULT (fontset)))
826 FONTSET_DEFAULT (fontset)
452a78e0 827 = make_fontset (FONTSET_FRAME (fontset), Qnil, Vdefault_fontset);
1c82b4b3 828 rfont_def = fontset_find_font (FONTSET_DEFAULT (fontset), c, face, id, 0);
0d407d77 829 }
1c82b4b3
KH
830 if (! NILP (rfont_def))
831 return rfont_def;
832 /* Try a fallback font-group. */
833 rfont_def = fontset_find_font (fontset, c, face, id, 1);
834 if (! NILP (rfont_def))
835 return rfont_def;
836 /* Try a fallback font-group of the default fontset . */
837 if (! EQ (base_fontset, Vdefault_fontset))
838 rfont_def = fontset_find_font (FONTSET_DEFAULT (fontset), c, face, id, 1);
839 return rfont_def;
0d407d77
KH
840}
841
0d407d77 842/* Return a newly created fontset with NAME. If BASE is nil, make a
06f76f0d 843 base fontset. Otherwise make a realized fontset whose base is
0d407d77
KH
844 BASE. */
845
846static Lisp_Object
847make_fontset (frame, name, base)
848 Lisp_Object frame, name, base;
4ed46869 849{
1337ac77 850 Lisp_Object fontset;
0d407d77
KH
851 int size = ASIZE (Vfontset_table);
852 int id = next_fontset_id;
0d407d77
KH
853
854 /* Find a free slot in Vfontset_table. Usually, next_fontset_id is
855 the next available fontset ID. So it is expected that this loop
856 terminates quickly. In addition, as the last element of
fc8865fc 857 Vfontset_table is always nil, we don't have to check the range of
0d407d77
KH
858 id. */
859 while (!NILP (AREF (Vfontset_table, id))) id++;
860
861 if (id + 1 == size)
63655c83 862 Vfontset_table = larger_vector (Vfontset_table, size + 32, Qnil);
4ed46869 863
11d9bd93 864 fontset = Fmake_char_table (Qfontset, Qnil);
0d407d77
KH
865
866 FONTSET_ID (fontset) = make_number (id);
06f76f0d
KH
867 if (NILP (base))
868 {
869 FONTSET_NAME (fontset) = name;
870 }
871 else
872 {
873 FONTSET_NAME (fontset) = Qnil;
874 FONTSET_FRAME (fontset) = frame;
875 FONTSET_BASE (fontset) = base;
876 }
0d407d77 877
06f76f0d 878 ASET (Vfontset_table, id, fontset);
0d407d77
KH
879 next_fontset_id = id + 1;
880 return fontset;
4ed46869
KH
881}
882
0d407d77 883
2cdd4f88
MB
884/* Set the ASCII font of the default fontset to FONTNAME if that is
885 not yet set. */
886void
887set_default_ascii_font (fontname)
0d407d77
KH
888 Lisp_Object fontname;
889{
d7fb7b91 890 if (! STRINGP (FONTSET_ASCII (Vdefault_fontset)))
2cdd4f88
MB
891 {
892 int id = fs_query_fontset (fontname, 2);
893
894 if (id >= 0)
d7fb7b91
KH
895 fontname = FONTSET_ASCII (FONTSET_FROM_ID (id));
896 FONTSET_ASCII (Vdefault_fontset)= fontname;
2cdd4f88 897 }
0d407d77
KH
898}
899
900\f
1d5d7200 901/********** INTERFACES TO xfaces.c, xfns.c, and dispextern.h **********/
0d407d77 902
1d5d7200 903/* Return the name of the fontset who has ID. */
0d407d77
KH
904
905Lisp_Object
906fontset_name (id)
907 int id;
908{
909 Lisp_Object fontset;
06f76f0d 910
0d407d77
KH
911 fontset = FONTSET_FROM_ID (id);
912 return FONTSET_NAME (fontset);
913}
914
915
1d5d7200 916/* Return the ASCII font name of the fontset who has ID. */
0d407d77
KH
917
918Lisp_Object
919fontset_ascii (id)
920 int id;
921{
922 Lisp_Object fontset, elt;
06f76f0d 923
0d407d77
KH
924 fontset= FONTSET_FROM_ID (id);
925 elt = FONTSET_ASCII (fontset);
8aa07a8d
KH
926#ifdef USE_FONT_BACKEND
927 if (CONSP (elt))
928 elt = XCAR (elt);
929#endif /* USE_FONT_BACKEND */
1d5d7200
KH
930 /* It is assured that ELT is always a string (i.e. fontname
931 pattern). */
932 return elt;
0d407d77
KH
933}
934
935
06f76f0d
KH
936/* Free fontset of FACE defined on frame F. Called from
937 free_realized_face. */
0d407d77 938
4ed46869 939void
0d407d77
KH
940free_face_fontset (f, face)
941 FRAME_PTR f;
942 struct face *face;
4ed46869 943{
452a78e0
KH
944 Lisp_Object fontset;
945
946 fontset = AREF (Vfontset_table, face->fontset);
947 xassert (!NILP (fontset) && ! BASE_FONTSET_P (fontset));
948 xassert (f == XFRAME (FONTSET_FRAME (fontset)));
1d5d7200 949 ASET (Vfontset_table, face->fontset, Qnil);
06f76f0d
KH
950 if (face->fontset < next_fontset_id)
951 next_fontset_id = face->fontset;
eb36588a 952 if (! NILP (FONTSET_DEFAULT (fontset)))
452a78e0 953 {
e1a14cdc 954 int id = XINT (FONTSET_ID (FONTSET_DEFAULT (fontset)));
452a78e0
KH
955
956 fontset = AREF (Vfontset_table, id);
957 xassert (!NILP (fontset) && ! BASE_FONTSET_P (fontset));
958 xassert (f == XFRAME (FONTSET_FRAME (fontset)));
959 ASET (Vfontset_table, id, Qnil);
960 if (id < next_fontset_id)
961 next_fontset_id = face->fontset;
962 }
0d407d77 963}
18998710 964
0d407d77 965
e0f24100 966/* Return 1 if FACE is suitable for displaying character C.
0d407d77 967 Otherwise return 0. Called from the macro FACE_SUITABLE_FOR_CHAR_P
06f76f0d 968 when C is not an ASCII character. */
0d407d77
KH
969
970int
971face_suitable_for_char_p (face, c)
972 struct face *face;
973 int c;
974{
7e1a1cd9 975 Lisp_Object fontset, rfont_def;
0d407d77 976
0d407d77 977 fontset = FONTSET_FROM_ID (face->fontset);
7e1a1cd9
KH
978 rfont_def = fontset_font (fontset, c, NULL, -1);
979 return (VECTORP (rfont_def)
980 && INTEGERP (AREF (rfont_def, 0))
981 && face->id == XINT (AREF (rfont_def, 0)));
0d407d77
KH
982}
983
984
985/* Return ID of face suitable for displaying character C on frame F.
1d5d7200
KH
986 FACE must be reazlied for ASCII characters in advance. Called from
987 the macro FACE_FOR_CHAR. */
0d407d77
KH
988
989int
6bad8007 990face_for_char (f, face, c, pos, object)
0d407d77
KH
991 FRAME_PTR f;
992 struct face *face;
6bad8007
KH
993 int c, pos;
994 Lisp_Object object;
0d407d77 995{
7e1a1cd9
KH
996 Lisp_Object fontset, charset, rfont_def;
997 int face_id;
6bad8007 998 int id;
1d5d7200
KH
999
1000 if (ASCII_CHAR_P (c))
1001 return face->ascii_face->id;
0d407d77
KH
1002
1003 xassert (fontset_id_valid_p (face->fontset));
1004 fontset = FONTSET_FROM_ID (face->fontset);
1005 xassert (!BASE_FONTSET_P (fontset));
6bad8007
KH
1006 if (pos < 0)
1007 id = -1;
1008 else
1009 {
1010 charset = Fget_char_property (make_number (pos), Qcharset, object);
1011 if (NILP (charset))
1012 id = -1;
1013 else if (CHARSETP (charset))
1014 id = XINT (CHARSET_SYMBOL_ID (charset));
1015 }
7e1a1cd9
KH
1016 rfont_def = fontset_font (fontset, c, face, id);
1017 if (VECTORP (rfont_def))
1018 {
8aa07a8d
KH
1019#ifdef USE_FONT_BACKEND
1020 if (enable_font_backend
1021 && NILP (AREF (rfont_def, 0)))
1022 {
1023 struct font *font = XSAVE_VALUE (AREF (rfont_def, 4))->pointer;
1024
1025 face_id = face_for_font (f, font, face);
1026 ASET (rfont_def, 0, make_number (face_id));
1027 }
1028 else
1029#endif /* USE_FONT_BACKEND */
7e1a1cd9
KH
1030 if (NILP (AREF (rfont_def, 0)))
1031 {
1032 /* We have not yet made a realized face that uses this font. */
1033 int font_idx = XINT (AREF (rfont_def, 1));
1034
1035 face_id = lookup_non_ascii_face (f, font_idx, face);
1036 ASET (rfont_def, 0, make_number (face_id));
1037 }
1038 return XINT (AREF (rfont_def, 0));
1039 }
1040
1041 if (NILP (FONTSET_NOFONT_FACE (fontset)))
1042 {
1043 face_id = lookup_non_ascii_face (f, -1, face);
1044 FONTSET_NOFONT_FACE (fontset) = make_number (face_id);
1045 }
1046 return XINT (FONTSET_NOFONT_FACE (fontset));
0d407d77
KH
1047}
1048
1049
1050/* Make a realized fontset for ASCII face FACE on frame F from the
1051 base fontset BASE_FONTSET_ID. If BASE_FONTSET_ID is -1, use the
1052 default fontset as the base. Value is the id of the new fontset.
1053 Called from realize_x_face. */
1054
1055int
1d5d7200 1056make_fontset_for_ascii_face (f, base_fontset_id, face)
0d407d77
KH
1057 FRAME_PTR f;
1058 int base_fontset_id;
1d5d7200 1059 struct face *face;
0d407d77 1060{
1337ac77 1061 Lisp_Object base_fontset, fontset, frame;
0d407d77
KH
1062
1063 XSETFRAME (frame, f);
1064 if (base_fontset_id >= 0)
1065 {
1066 base_fontset = FONTSET_FROM_ID (base_fontset_id);
1067 if (!BASE_FONTSET_P (base_fontset))
1068 base_fontset = FONTSET_BASE (base_fontset);
1069 xassert (BASE_FONTSET_P (base_fontset));
1d5d7200
KH
1070 if (! BASE_FONTSET_P (base_fontset))
1071 abort ();
4ed46869 1072 }
0d407d77
KH
1073 else
1074 base_fontset = Vdefault_fontset;
1075
1076 fontset = make_fontset (frame, Qnil, base_fontset);
1d5d7200 1077 {
1c82b4b3 1078 Lisp_Object elt, rfont_def, val;
1d5d7200
KH
1079
1080 elt = FONTSET_REF (base_fontset, 0);
7e1a1cd9 1081 xassert (VECTORP (elt) && ASIZE (elt) > 0);
8aa07a8d
KH
1082#ifdef USE_FONT_BACKEND
1083 rfont_def = Fmake_vector (make_number (5), Qnil);
1084 if (enable_font_backend && face->font_info)
1085 {
1086 struct font *font = (struct font *) face->font_info;
1087
1088 ASET (rfont_def, 3, font->entity);
1089 ASET (rfont_def, 4, font_find_object (font));
1090 }
ce4aada8
KH
1091 else
1092#endif /* USE_FONT_BACKEND */
8aa07a8d
KH
1093 {
1094 rfont_def = Fmake_vector (make_number (4), Qnil);
1095 ASET (rfont_def, 3, build_string (face->font_name));
1096 }
7e1a1cd9
KH
1097 ASET (rfont_def, 1, make_number (face->font_info_id));
1098 ASET (rfont_def, 2, AREF (elt, 0));
7e1a1cd9 1099 elt = Fmake_vector (make_number (4), Qnil);
6bad8007 1100 ASET (elt, 0, make_number (charset_ordered_list_tick));
7e1a1cd9
KH
1101 ASET (elt, 1, make_number (charset_ascii));
1102 ASET (elt, 2, rfont_def);
1103 ASET (elt, 3, rfont_def);
1c82b4b3
KH
1104
1105 val = Fcons (Qlatin, Qnil);
1106 map_char_table (accumulate_script_ranges, Qnil, Vchar_script_table, val);
1107 for (val = XCDR (val); CONSP (val); val = XCDR (val))
1108 char_table_set_range (fontset, XINT (XCAR (XCAR (val))),
1109 XINT (XCDR (XCAR (val))), elt);
1110 FONTSET_FALLBACK (fontset) = elt;
1d5d7200 1111 }
f3231837 1112 return XINT (FONTSET_ID (fontset));
0d407d77
KH
1113}
1114
1115
97f4db8c
AI
1116#if defined(WINDOWSNT) && defined (_MSC_VER)
1117#pragma optimize("", off)
1118#endif
1119
06f76f0d
KH
1120/* Load a font named FONTNAME on frame F. Return a pointer to the
1121 struct font_info of the loaded font. If loading fails, return
6ab1fb6a
KH
1122 NULL. CHARSET is an ID of charset to encode characters for this
1123 font. If it is -1, find one from Vfont_encoding_alist. */
4ed46869
KH
1124
1125struct font_info *
6ab1fb6a 1126fs_load_font (f, fontname, charset)
4ed46869 1127 FRAME_PTR f;
4ed46869 1128 char *fontname;
6ab1fb6a 1129 int charset;
4ed46869 1130{
4ed46869 1131 struct font_info *fontp;
71c54d6f 1132 Lisp_Object fullname;
4ed46869 1133
0d407d77
KH
1134 if (!fontname)
1135 /* No way to get fontname. */
1d5d7200 1136 return NULL;
4ed46869 1137
06f76f0d 1138 fontp = (*load_font_func) (f, fontname, 0);
6ab1fb6a
KH
1139 if (! fontp || fontp->charset >= 0)
1140 return fontp;
4ed46869 1141
48728c92 1142 fontname = fontp->full_name;
71c54d6f 1143 fullname = build_string (fontp->full_name);
4ed46869 1144
6ab1fb6a 1145 if (charset < 0)
4ed46869 1146 {
6ab1fb6a 1147 Lisp_Object charset_symbol;
4ed46869 1148
71c54d6f 1149 charset_symbol = find_font_encoding (fullname);
6ab1fb6a
KH
1150 if (CONSP (charset_symbol))
1151 charset_symbol = XCAR (charset_symbol);
8aa07a8d
KH
1152 if (NILP (charset_symbol))
1153 charset_symbol = Qascii;
6ab1fb6a 1154 charset = XINT (CHARSET_SYMBOL_ID (charset_symbol));
4ed46869 1155 }
6ab1fb6a 1156 fontp->charset = charset;
1d5d7200 1157 fontp->vertical_centering = 0;
06f76f0d 1158 fontp->font_encoder = NULL;
727fb790 1159
6ab1fb6a 1160 if (charset != charset_ascii)
4ed46869 1161 {
1d5d7200
KH
1162 fontp->vertical_centering
1163 = (STRINGP (Vvertical_centering_font_regexp)
71c54d6f
KH
1164 && (fast_string_match_ignore_case
1165 (Vvertical_centering_font_regexp, fullname) >= 0));
4ed46869 1166
1d5d7200
KH
1167 if (find_ccl_program_func)
1168 (*find_ccl_program_func) (fontp);
4ed46869
KH
1169 }
1170
4ed46869
KH
1171 return fontp;
1172}
1173
97f4db8c
AI
1174#if defined(WINDOWSNT) && defined (_MSC_VER)
1175#pragma optimize("", on)
1176#endif
1177
0d407d77 1178\f
6ab1fb6a
KH
1179/* Return ENCODING or a cons of ENCODING and REPERTORY of the font
1180 FONTNAME. ENCODING is a charset symbol that specifies the encoding
1181 of the font. REPERTORY is a charset symbol or nil. */
1d5d7200
KH
1182
1183
8aa07a8d 1184Lisp_Object
1d5d7200 1185find_font_encoding (fontname)
71c54d6f 1186 Lisp_Object fontname;
1d5d7200
KH
1187{
1188 Lisp_Object tail, elt;
1189
1190 for (tail = Vfont_encoding_alist; CONSP (tail); tail = XCDR (tail))
1191 {
1192 elt = XCAR (tail);
1193 if (CONSP (elt)
1194 && STRINGP (XCAR (elt))
71c54d6f 1195 && fast_string_match_ignore_case (XCAR (elt), fontname) >= 0
1d5d7200
KH
1196 && (SYMBOLP (XCDR (elt))
1197 ? CHARSETP (XCDR (elt))
1198 : CONSP (XCDR (elt)) && CHARSETP (XCAR (XCDR (elt)))))
1199 return (XCDR (elt));
1200 }
fb78e2ed
KH
1201 /* We don't know the encoding of this font. Let's assume `ascii'. */
1202 return Qascii;
1d5d7200
KH
1203}
1204
1205
4ed46869
KH
1206/* Cache data used by fontset_pattern_regexp. The car part is a
1207 pattern string containing at least one wild card, the cdr part is
1208 the corresponding regular expression. */
1209static Lisp_Object Vcached_fontset_data;
1210
d5db4077 1211#define CACHED_FONTSET_NAME (SDATA (XCAR (Vcached_fontset_data)))
7539e11f 1212#define CACHED_FONTSET_REGEX (XCDR (Vcached_fontset_data))
4ed46869
KH
1213
1214/* If fontset name PATTERN contains any wild card, return regular
1215 expression corresponding to PATTERN. */
1216
0d407d77 1217static Lisp_Object
4ed46869
KH
1218fontset_pattern_regexp (pattern)
1219 Lisp_Object pattern;
1220{
d5db4077
KR
1221 if (!index (SDATA (pattern), '*')
1222 && !index (SDATA (pattern), '?'))
4ed46869 1223 /* PATTERN does not contain any wild cards. */
1c283e35 1224 return Qnil;
4ed46869
KH
1225
1226 if (!CONSP (Vcached_fontset_data)
d5db4077 1227 || strcmp (SDATA (pattern), CACHED_FONTSET_NAME))
4ed46869
KH
1228 {
1229 /* We must at first update the cached data. */
6cc06608 1230 unsigned char *regex, *p0, *p1;
fc1062f5 1231 int ndashes = 0, nstars = 0;
6cc06608 1232
fc1062f5
KH
1233 for (p0 = SDATA (pattern); *p0; p0++)
1234 {
1235 if (*p0 == '-')
1236 ndashes++;
a653f812 1237 else if (*p0 == '*')
fc1062f5
KH
1238 nstars++;
1239 }
1240
1241 /* If PATTERN is not full XLFD we conert "*" to ".*". Otherwise
1242 we convert "*" to "[^-]*" which is much faster in regular
1243 expression matching. */
1244 if (ndashes < 14)
6cc06608 1245 p1 = regex = (unsigned char *) alloca (SBYTES (pattern) + 2 * nstars + 1);
fc1062f5 1246 else
6cc06608 1247 p1 = regex = (unsigned char *) alloca (SBYTES (pattern) + 5 * nstars + 1);
4ed46869 1248
1c283e35 1249 *p1++ = '^';
6cc06608 1250 for (p0 = SDATA (pattern); *p0; p0++)
4ed46869 1251 {
a653f812 1252 if (*p0 == '*')
4ed46869 1253 {
fc1062f5
KH
1254 if (ndashes < 14)
1255 *p1++ = '.';
1256 else
1257 *p1++ = '[', *p1++ = '^', *p1++ = '-', *p1++ = ']';
1c283e35 1258 *p1++ = '*';
4ed46869 1259 }
1c283e35 1260 else if (*p0 == '?')
d96d677d 1261 *p1++ = '.';
1c283e35
KH
1262 else
1263 *p1++ = *p0;
4ed46869
KH
1264 }
1265 *p1++ = '$';
1266 *p1++ = 0;
1267
d5db4077 1268 Vcached_fontset_data = Fcons (build_string (SDATA (pattern)),
4ed46869
KH
1269 build_string (regex));
1270 }
1271
1272 return CACHED_FONTSET_REGEX;
1273}
1274
0d407d77 1275/* Return ID of the base fontset named NAME. If there's no such
a653f812
KH
1276 fontset, return -1. NAME_PATTERN specifies how to treat NAME as this:
1277 0: pattern containing '*' and '?' as wildcards
1278 1: regular expression
1279 2: literal fontset name
1280*/
0d407d77
KH
1281
1282int
a653f812 1283fs_query_fontset (name, name_pattern)
0d407d77 1284 Lisp_Object name;
a653f812 1285 int name_pattern;
0d407d77 1286{
1337ac77 1287 Lisp_Object tem;
0d407d77
KH
1288 int i;
1289
1290 name = Fdowncase (name);
a653f812 1291 if (name_pattern != 1)
0d407d77
KH
1292 {
1293 tem = Frassoc (name, Vfontset_alias_alist);
6bad8007
KH
1294 if (NILP (tem))
1295 tem = Fassoc (name, Vfontset_alias_alist);
0d407d77
KH
1296 if (CONSP (tem) && STRINGP (XCAR (tem)))
1297 name = XCAR (tem);
a653f812 1298 else if (name_pattern == 0)
0d407d77
KH
1299 {
1300 tem = fontset_pattern_regexp (name);
1301 if (STRINGP (tem))
1302 {
1303 name = tem;
a653f812 1304 name_pattern = 1;
0d407d77
KH
1305 }
1306 }
1307 }
1308
1309 for (i = 0; i < ASIZE (Vfontset_table); i++)
1310 {
6e1b0d8c 1311 Lisp_Object fontset, this_name;
0d407d77
KH
1312
1313 fontset = FONTSET_FROM_ID (i);
1314 if (NILP (fontset)
1315 || !BASE_FONTSET_P (fontset))
1316 continue;
1317
6e1b0d8c 1318 this_name = FONTSET_NAME (fontset);
a653f812 1319 if (name_pattern == 1
6e1b0d8c
KH
1320 ? fast_string_match (name, this_name) >= 0
1321 : !strcmp (SDATA (name), SDATA (this_name)))
0d407d77
KH
1322 return i;
1323 }
1324 return -1;
1325}
1326
1327
727fb790 1328DEFUN ("query-fontset", Fquery_fontset, Squery_fontset, 1, 2, 0,
335c5470
PJ
1329 doc: /* Return the name of a fontset that matches PATTERN.
1330The value is nil if there is no matching fontset.
1331PATTERN can contain `*' or `?' as a wildcard
1332just as X font name matching algorithm allows.
1333If REGEXPP is non-nil, PATTERN is a regular expression. */)
1334 (pattern, regexpp)
727fb790 1335 Lisp_Object pattern, regexpp;
4ed46869 1336{
0d407d77
KH
1337 Lisp_Object fontset;
1338 int id;
4ed46869
KH
1339
1340 (*check_window_system_func) ();
1341
b7826503 1342 CHECK_STRING (pattern);
4ed46869 1343
d5db4077 1344 if (SCHARS (pattern) == 0)
4ed46869
KH
1345 return Qnil;
1346
0d407d77
KH
1347 id = fs_query_fontset (pattern, !NILP (regexpp));
1348 if (id < 0)
1349 return Qnil;
4ed46869 1350
0d407d77
KH
1351 fontset = FONTSET_FROM_ID (id);
1352 return FONTSET_NAME (fontset);
4ed46869
KH
1353}
1354
06f76f0d 1355/* Return a list of base fontset names matching PATTERN on frame F. */
4ed46869
KH
1356
1357Lisp_Object
1358list_fontsets (f, pattern, size)
1359 FRAME_PTR f;
1360 Lisp_Object pattern;
1361 int size;
1362{
1337ac77 1363 Lisp_Object frame, regexp, val;
0d407d77 1364 int id;
4ed46869 1365
0d407d77 1366 XSETFRAME (frame, f);
4ed46869 1367
0d407d77 1368 regexp = fontset_pattern_regexp (pattern);
4ed46869 1369 val = Qnil;
4ed46869 1370
0d407d77
KH
1371 for (id = 0; id < ASIZE (Vfontset_table); id++)
1372 {
6e1b0d8c 1373 Lisp_Object fontset, name;
0d407d77
KH
1374
1375 fontset = FONTSET_FROM_ID (id);
1376 if (NILP (fontset)
1377 || !BASE_FONTSET_P (fontset)
1378 || !EQ (frame, FONTSET_FRAME (fontset)))
1379 continue;
6e1b0d8c 1380 name = FONTSET_NAME (fontset);
0d407d77 1381
1d5d7200 1382 if (STRINGP (regexp)
6e1b0d8c
KH
1383 ? (fast_string_match (regexp, name) < 0)
1384 : strcmp (SDATA (pattern), SDATA (name)))
0d407d77
KH
1385 continue;
1386
0d407d77 1387 val = Fcons (Fcopy_sequence (FONTSET_NAME (fontset)), val);
4ed46869
KH
1388 }
1389
1390 return val;
1391}
1392
4ed46869 1393
8f924df7 1394/* Free all realized fontsets whose base fontset is BASE. */
4ed46869 1395
06f76f0d
KH
1396static void
1397free_realized_fontsets (base)
1398 Lisp_Object base;
1399{
1400 int id;
4ed46869 1401
2f034212 1402#if 0
27e20b2f
KH
1403 /* For the moment, this doesn't work because free_realized_face
1404 doesn't remove FACE from a cache. Until we find a solution, we
1405 suppress this code, and simply use Fclear_face_cache even though
1406 that is not efficient. */
06f76f0d
KH
1407 BLOCK_INPUT;
1408 for (id = 0; id < ASIZE (Vfontset_table); id++)
4ed46869 1409 {
06f76f0d 1410 Lisp_Object this = AREF (Vfontset_table, id);
0d407d77 1411
06f76f0d 1412 if (EQ (FONTSET_BASE (this), base))
0d407d77 1413 {
06f76f0d 1414 Lisp_Object tail;
4ed46869 1415
06f76f0d
KH
1416 for (tail = FONTSET_FACE_ALIST (this); CONSP (tail);
1417 tail = XCDR (tail))
1418 {
1419 FRAME_PTR f = XFRAME (FONTSET_FRAME (this));
1420 int face_id = XINT (XCDR (XCAR (tail)));
1421 struct face *face = FACE_FROM_ID (f, face_id);
4ed46869 1422
06f76f0d
KH
1423 /* Face THIS itself is also freed by the following call. */
1424 free_realized_face (f, face);
1425 }
1426 }
0d407d77 1427 }
06f76f0d 1428 UNBLOCK_INPUT;
27e20b2f 1429#else /* not 0 */
2f034212
KH
1430 /* But, we don't have to call Fclear_face_cache if no fontset has
1431 been realized from BASE. */
1432 for (id = 0; id < ASIZE (Vfontset_table); id++)
1433 {
1434 Lisp_Object this = AREF (Vfontset_table, id);
1435
985773c9 1436 if (CHAR_TABLE_P (this) && EQ (FONTSET_BASE (this), base))
2f034212
KH
1437 {
1438 Fclear_face_cache (Qt);
1439 break;
1440 }
1441 }
27e20b2f 1442#endif /* not 0 */
0d407d77 1443}
4ed46869 1444
4ed46869 1445
0d407d77
KH
1446/* Check validity of NAME as a fontset name and return the
1447 corresponding fontset. If not valid, signal an error.
1448 If NAME is t, return Vdefault_fontset. */
1449
1450static Lisp_Object
1451check_fontset_name (name)
1452 Lisp_Object name;
1453{
1454 int id;
1455
1456 if (EQ (name, Qt))
1457 return Vdefault_fontset;
4ed46869 1458
b7826503 1459 CHECK_STRING (name);
a653f812
KH
1460 /* First try NAME as literal. */
1461 id = fs_query_fontset (name, 2);
1462 if (id < 0)
1463 /* For backward compatibility, try again NAME as pattern. */
1464 id = fs_query_fontset (name, 0);
0d407d77 1465 if (id < 0)
d5db4077 1466 error ("Fontset `%s' does not exist", SDATA (name));
0d407d77
KH
1467 return FONTSET_FROM_ID (id);
1468}
4ed46869 1469
1d5d7200
KH
1470static void
1471accumulate_script_ranges (arg, range, val)
1472 Lisp_Object arg, range, val;
1473{
1474 if (EQ (XCAR (arg), val))
1475 {
1476 if (CONSP (range))
1477 XSETCDR (arg, Fcons (Fcons (XCAR (range), XCDR (range)), XCDR (arg)));
1478 else
1479 XSETCDR (arg, Fcons (Fcons (range, range), XCDR (arg)));
1480 }
1481}
1482
1483
d6aaac9e
KH
1484/* Return an ASCII font name generated from fontset name NAME and
1485 ASCII font specification ASCII_SPEC. NAME is a string conforming
1486 to XLFD. ASCII_SPEC is a vector:
1487 [FAMILY WEIGHT SLANT SWIDTH ADSTYLE REGISTRY]. */
1488
1489static INLINE Lisp_Object
1490generate_ascii_font_name (name, ascii_spec)
1491 Lisp_Object name, ascii_spec;
1492{
1493 Lisp_Object vec;
1494 int i;
1495
1496 vec = split_font_name_into_vector (name);
1497 for (i = FONT_SPEC_FAMILY_INDEX; i <= FONT_SPEC_ADSTYLE_INDEX; i++)
1498 if (! NILP (AREF (ascii_spec, i)))
1499 ASET (vec, 1 + i, AREF (ascii_spec, i));
1500 if (! NILP (AREF (ascii_spec, FONT_SPEC_REGISTRY_INDEX)))
1501 ASET (vec, 12, AREF (ascii_spec, FONT_SPEC_REGISTRY_INDEX));
1502 return build_font_name_from_vector (vec);
1503}
1504
fb78e2ed
KH
1505/* Variables referred in set_fontset_font. They are set before
1506 map_charset_chars is called in Fset_fontset_font. */
1507static Lisp_Object font_def_arg, add_arg;
1508static int from_arg, to_arg;
1509
1510/* Callback function for map_charset_chars in Fset_fontset_font. In
1511 FONTSET, set font_def_arg in a fashion specified by add_arg for
1512 characters in RANGE while ignoring the range between from_arg and
1513 to_arg. */
1514
2449d4d0 1515static void
fb78e2ed
KH
1516set_fontset_font (fontset, range)
1517 Lisp_Object fontset, range;
2449d4d0 1518{
fb78e2ed
KH
1519 if (from_arg < to_arg)
1520 {
1521 int from = XINT (XCAR (range)), to = XINT (XCDR (range));
2449d4d0 1522
fb78e2ed
KH
1523 if (from < from_arg)
1524 {
1525 if (to > to_arg)
1526 {
1527 Lisp_Object range2;
1528
1529 range2 = Fcons (make_number (to_arg), XCDR (range));
1530 FONTSET_ADD (fontset, range, font_def_arg, add_arg);
1531 to = to_arg;
1532 }
1533 if (to > from_arg)
1534 range = Fcons (XCAR (range), make_number (from_arg));
1535 }
1536 else if (to <= to_arg)
1537 return;
1538 else
1539 {
1540 if (from < to_arg)
1541 range = Fcons (make_number (to_arg), XCDR (range));
1542 }
1543 }
1544 FONTSET_ADD (fontset, range, font_def_arg, add_arg);
2449d4d0
KH
1545}
1546
d6aaac9e 1547
1d5d7200 1548DEFUN ("set-fontset-font", Fset_fontset_font, Sset_fontset_font, 3, 5, 0,
8f924df7 1549 doc: /*
eb36588a 1550Modify fontset NAME to use FONT-SPEC for TARGET characters.
335c5470 1551
eb36588a
KH
1552TARGET may be a cons; (FROM . TO), where FROM and TO are characters.
1553In that case, use FONT-SPEC for all characters in the range FROM and
1554TO (inclusive).
06f76f0d 1555
eb36588a
KH
1556TARGET may be a script name symbol. In that case, use FONT-SPEC for
1557all characters that belong to the script.
06f76f0d 1558
eb36588a 1559TARGET may be a charset. In that case, use FONT-SPEC for all
95318a38 1560characters in the charset.
1d5d7200 1561
eb36588a
KH
1562TARGET may be nil. In that case, use FONT-SPEC for any characters for
1563that no FONT-SPEC is specified.
1564
0fdf26e6 1565FONT-SPEC may one of these:
3dcd48dd 1566 * A cons (FAMILY . REGISTRY), where FAMILY is a font family name and
0fdf26e6
KH
1567 REGISTRY is a font registry name. FAMILY may contains foundry
1568 name, and REGISTRY may contains encoding name.
00c4da0f 1569 * A font name string.
1d5d7200
KH
1570
1571Optional 4th argument FRAME, if non-nil, is a frame. This argument is
1572kept for backward compatibility and has no meaning.
1573
1574Optional 5th argument ADD, if non-nil, specifies how to add FONT-SPEC
eb36588a 1575to the font specifications for TARGET previously set. If it is
1d5d7200
KH
1576`prepend', FONT-SPEC is prepended. If it is `append', FONT-SPEC is
1577appended. By default, FONT-SPEC overrides the previous settings. */)
eb36588a
KH
1578 (name, target, font_spec, frame, add)
1579 Lisp_Object name, target, font_spec, frame, add;
0d407d77 1580{
06f76f0d 1581 Lisp_Object fontset;
9683749a 1582 Lisp_Object font_def, registry, family;
00c4da0f 1583 Lisp_Object encoding, repertory;
1d5d7200 1584 Lisp_Object range_list;
fb78e2ed 1585 struct charset *charset = NULL;
0d407d77
KH
1586
1587 fontset = check_fontset_name (name);
1588
1d5d7200
KH
1589 /* The arg FRAME is kept for backward compatibility. We only check
1590 the validity. */
1591 if (!NILP (frame))
1592 CHECK_LIVE_FRAME (frame);
1593
06f76f0d 1594 if (VECTORP (font_spec))
0d407d77 1595 {
0fdf26e6
KH
1596 /* FONT_SPEC should have this form:
1597 [ FAMILY WEIGHT SLANT WIDTH ADSTYLE REGISTRY ]
1598 This is a feature not yet documented because WEIGHT thru
1599 ADSTYLE are ignored for the moment. */
1d5d7200
KH
1600 int j;
1601
d6aaac9e
KH
1602 if (ASIZE (font_spec) != FONT_SPEC_MAX_INDEX)
1603 args_out_of_range (make_number (FONT_SPEC_MAX_INDEX),
1d5d7200 1604 make_number (ASIZE (font_spec)));
06f76f0d
KH
1605
1606 font_spec = Fcopy_sequence (font_spec);
d6aaac9e 1607 for (j = 0; j < FONT_SPEC_MAX_INDEX - 1; j++)
1d5d7200
KH
1608 if (! NILP (AREF (font_spec, j)))
1609 {
1610 CHECK_STRING (AREF (font_spec, j));
1611 ASET (font_spec, j, Fdowncase (AREF (font_spec, j)));
1612 }
d19b3ee7 1613 family = AREF (font_spec, FONT_SPEC_FAMILY_INDEX);
1d5d7200 1614 /* REGISTRY should not be omitted. */
d6aaac9e 1615 CHECK_STRING (AREF (font_spec, FONT_SPEC_REGISTRY_INDEX));
d19b3ee7 1616 registry = AREF (font_spec, FONT_SPEC_REGISTRY_INDEX);
0d407d77 1617 }
06f76f0d 1618 else if (CONSP (font_spec))
0890801b 1619 {
06f76f0d
KH
1620 family = XCAR (font_spec);
1621 registry = XCDR (font_spec);
1d5d7200
KH
1622
1623 if (! NILP (family))
06f76f0d
KH
1624 {
1625 CHECK_STRING (family);
1d5d7200 1626 family = Fdowncase (family);
06f76f0d
KH
1627 }
1628 CHECK_STRING (registry);
1d5d7200 1629 registry = Fdowncase (registry);
d6aaac9e
KH
1630 font_spec = Fmake_vector (make_number (FONT_SPEC_MAX_INDEX), Qnil);
1631 ASET (font_spec, FONT_SPEC_FAMILY_INDEX, family);
1632 ASET (font_spec, FONT_SPEC_REGISTRY_INDEX, registry);
0890801b 1633 }
0d407d77 1634 else
4ed46869 1635 {
1d5d7200
KH
1636 CHECK_STRING (font_spec);
1637 font_spec = Fdowncase (font_spec);
0d407d77 1638 }
1d5d7200
KH
1639
1640 if (STRINGP (font_spec))
71c54d6f 1641 encoding = find_font_encoding (font_spec);
0d407d77 1642 else
9683749a 1643 encoding = find_font_encoding (concat2 (family, registry));
8aa07a8d
KH
1644 if (NILP (encoding))
1645 encoding = Qascii;
1646
1d5d7200 1647 if (SYMBOLP (encoding))
57e13af9
KH
1648 {
1649 CHECK_CHARSET (encoding);
1650 encoding = repertory = CHARSET_SYMBOL_ID (encoding);
1651 }
1d5d7200 1652 else
0d407d77 1653 {
1d5d7200 1654 repertory = XCDR (encoding);
57e13af9
KH
1655 encoding = XCAR (encoding);
1656 CHECK_CHARSET (encoding);
1657 encoding = CHARSET_SYMBOL_ID (encoding);
1658 if (! NILP (repertory) && SYMBOLP (repertory))
1659 {
1660 CHECK_CHARSET (repertory);
1661 repertory = CHARSET_SYMBOL_ID (repertory);
1662 }
0d407d77 1663 }
1d5d7200
KH
1664 font_def = Fmake_vector (make_number (3), font_spec);
1665 ASET (font_def, 1, encoding);
1666 ASET (font_def, 2, repertory);
4ed46869 1667
eb36588a
KH
1668 if (CHARACTERP (target))
1669 range_list = Fcons (Fcons (target, target), Qnil);
1670 else if (CONSP (target))
0d407d77 1671 {
06f76f0d
KH
1672 Lisp_Object from, to;
1673
eb36588a
KH
1674 from = Fcar (target);
1675 to = Fcdr (target);
06f76f0d
KH
1676 CHECK_CHARACTER (from);
1677 CHECK_CHARACTER (to);
eb36588a 1678 range_list = Fcons (target, Qnil);
4ed46869 1679 }
eb36588a 1680 else if (SYMBOLP (target) && !NILP (target))
8a9be3ac 1681 {
1d5d7200
KH
1682 Lisp_Object script_list;
1683 Lisp_Object val;
0d407d77 1684
1d5d7200
KH
1685 range_list = Qnil;
1686 script_list = XCHAR_TABLE (Vchar_script_table)->extras[0];
eb36588a 1687 if (! NILP (Fmemq (target, script_list)))
afe93d01 1688 {
eb36588a 1689 val = Fcons (target, Qnil);
1d5d7200 1690 map_char_table (accumulate_script_ranges, Qnil, Vchar_script_table,
8f924df7
KH
1691 val);
1692 range_list = XCDR (val);
c3fb88cc
KH
1693 if (EQ (target, Qlatin))
1694 {
1695 if (VECTORP (font_spec))
1696 val = generate_ascii_font_name (FONTSET_NAME (fontset),
1697 font_spec);
1698 else
1699 val = font_spec;
1700 FONTSET_ASCII (fontset) = val;
1701 }
afe93d01 1702 }
fb78e2ed 1703 if (CHARSETP (target))
afe93d01 1704 {
eb36588a 1705 if (EQ (target, Qascii))
862aa7f9 1706 {
d6aaac9e 1707 if (VECTORP (font_spec))
862aa7f9
KH
1708 font_spec = generate_ascii_font_name (FONTSET_NAME (fontset),
1709 font_spec);
1710 FONTSET_ASCII (fontset) = font_spec;
2449d4d0
KH
1711 range_list = Fcons (Fcons (make_number (0), make_number (127)),
1712 Qnil);
1713 }
1714 else
1715 {
fb78e2ed 1716 CHECK_CHARSET_GET_CHARSET (target, charset);
862aa7f9 1717 }
afe93d01 1718 }
fb78e2ed 1719 else if (NILP (range_list))
1d5d7200 1720 error ("Invalid script or charset name: %s",
eb36588a 1721 SDATA (SYMBOL_NAME (target)));
8a9be3ac 1722 }
eb36588a
KH
1723 else if (NILP (target))
1724 range_list = Fcons (Qnil, Qnil);
1725 else
1726 error ("Invalid target for setting a font");
0d407d77 1727
fb78e2ed
KH
1728
1729 if (charset)
1730 {
1731 font_def_arg = font_def;
1732 add_arg = add;
1733 if (NILP (range_list))
1734 from_arg = to_arg = 0;
1735 else
1736 from_arg = XINT (XCAR (XCAR (range_list))),
1737 to_arg = XINT (XCDR (XCAR (range_list)));
1738
1739 map_charset_chars (set_fontset_font, Qnil, fontset, charset,
1740 CHARSET_MIN_CODE (charset),
1741 CHARSET_MAX_CODE (charset));
1742 }
1d5d7200
KH
1743 for (; CONSP (range_list); range_list = XCDR (range_list))
1744 FONTSET_ADD (fontset, XCAR (range_list), font_def, add);
4ed46869 1745
06f76f0d
KH
1746 /* Free all realized fontsets whose base is FONTSET. This way, the
1747 specified character(s) are surely redisplayed by a correct
1748 font. */
1749 free_realized_fontsets (fontset);
4ed46869 1750
4ed46869
KH
1751 return Qnil;
1752}
1753
06f76f0d
KH
1754
1755DEFUN ("new-fontset", Fnew_fontset, Snew_fontset, 2, 2, 0,
1756 doc: /* Create a new fontset NAME from font information in FONTLIST.
1757
1d5d7200 1758FONTLIST is an alist of scripts vs the corresponding font specification list.
d6aaac9e
KH
1759Each element of FONTLIST has the form (SCRIPT FONT-SPEC ...), where a
1760character of SCRIPT is displayed by a font that matches one of
1761FONT-SPEC.
06f76f0d 1762
d6aaac9e
KH
1763SCRIPT is a symbol that appears in the first extra slot of the
1764char-table `char-script-table'.
06f76f0d 1765
1d5d7200
KH
1766FONT-SPEC is a vector, a cons, or a string. See the documentation of
1767`set-fontset-font' for the meaning. */)
06f76f0d
KH
1768 (name, fontlist)
1769 Lisp_Object name, fontlist;
1770{
1d5d7200
KH
1771 Lisp_Object fontset;
1772 Lisp_Object val;
1773 int id;
06f76f0d
KH
1774
1775 CHECK_STRING (name);
1776 CHECK_LIST (fontlist);
1777
1d5d7200
KH
1778 id = fs_query_fontset (name, 0);
1779 if (id < 0)
0d407d77 1780 {
d6aaac9e
KH
1781 name = Fdowncase (name);
1782 val = split_font_name_into_vector (name);
df1e3c95 1783 if (NILP (val) || NILP (AREF (val, 12)) || NILP (AREF (val, 13)))
d6aaac9e 1784 error ("Fontset name must be in XLFD format");
8f924df7 1785 if (strcmp (SDATA (AREF (val, 12)), "fontset"))
d6aaac9e
KH
1786 error ("Registry field of fontset name must be \"fontset\"");
1787 Vfontset_alias_alist
1788 = Fcons (Fcons (name,
1789 concat2 (concat2 (AREF (val, 12), build_string ("-")),
1790 AREF (val, 13))),
1791 Vfontset_alias_alist);
1792 ASET (val, 12, build_string ("iso8859-1"));
1793 fontset = make_fontset (Qnil, name, Qnil);
1794 FONTSET_ASCII (fontset) = build_font_name_from_vector (val);
1795 }
1d5d7200
KH
1796 else
1797 {
1798 fontset = FONTSET_FROM_ID (id);;
1799 free_realized_fontsets (fontset);
1800 Fset_char_table_range (fontset, Qt, Qnil);
0d407d77 1801 }
4ed46869 1802
1d5d7200
KH
1803 for (; ! NILP (fontlist); fontlist = Fcdr (fontlist))
1804 {
1805 Lisp_Object elt, script;
1806
1807 elt = Fcar (fontlist);
1808 script = Fcar (elt);
cc36ddbf
KH
1809 elt = Fcdr (elt);
1810 if (CONSP (elt) && (NILP (XCDR (elt)) || CONSP (XCDR (elt))))
1811 for (; CONSP (elt); elt = XCDR (elt))
1812 Fset_fontset_font (name, script, XCAR (elt), Qnil, Qappend);
1813 else
1814 Fset_fontset_font (name, script, elt, Qnil, Qappend);
1d5d7200 1815 }
06f76f0d
KH
1816 return name;
1817}
1818
1819
452a78e0
KH
1820/* Alist of automatically created fontsets. Each element is a cons
1821 (FONTNAME . FONTSET-ID). */
1822static Lisp_Object auto_fontset_alist;
d6aaac9e
KH
1823
1824int
1825new_fontset_from_font_name (Lisp_Object fontname)
1826{
452a78e0 1827 Lisp_Object val;
d6aaac9e
KH
1828 Lisp_Object name;
1829 Lisp_Object vec;
452a78e0 1830 int id;
d6aaac9e
KH
1831
1832 fontname = Fdowncase (fontname);
452a78e0
KH
1833 val = Fassoc (fontname, auto_fontset_alist);
1834 if (CONSP (val))
1835 return XINT (XCDR (val));
1836
d6aaac9e
KH
1837 vec = split_font_name_into_vector (fontname);
1838 if ( NILP (vec))
1839 vec = Fmake_vector (make_number (14), build_string (""));
1840 ASET (vec, 12, build_string ("fontset"));
452a78e0 1841 if (NILP (auto_fontset_alist))
d6aaac9e
KH
1842 {
1843 ASET (vec, 13, build_string ("startup"));
1844 name = build_font_name_from_vector (vec);
d6aaac9e
KH
1845 }
1846 else
1847 {
1848 char temp[20];
e1a14cdc 1849 int len = XINT (Flength (auto_fontset_alist));
d6aaac9e 1850
452a78e0
KH
1851 sprintf (temp, "auto%d", len);
1852 ASET (vec, 13, build_string (temp));
1853 name = build_font_name_from_vector (vec);
d6aaac9e 1854 }
fb78e2ed
KH
1855 name = Fnew_fontset (name, list2 (list2 (Qascii, fontname),
1856 list2 (Fcons (make_number (0),
2ec7fd70 1857 make_number (MAX_CHAR)),
fb78e2ed 1858 fontname)));
452a78e0
KH
1859 id = fs_query_fontset (name, 0);
1860 auto_fontset_alist
1861 = Fcons (Fcons (fontname, make_number (id)), auto_fontset_alist);
1862 return id;
4ed46869
KH
1863}
1864
8aa07a8d
KH
1865#ifdef USE_FONT_BACKEND
1866int
03ef560c 1867new_fontset_from_font (font_object)
8aa07a8d
KH
1868 Lisp_Object font_object;
1869{
03ef560c
KH
1870 Lisp_Object font_name = font_get_name (font_object);
1871 Lisp_Object font_spec = font_get_spec (font_object);
1c82b4b3 1872 Lisp_Object fontset_spec, short_name, name, fontset;
8aa07a8d 1873
03ef560c
KH
1874 if (NILP (auto_fontset_alist))
1875 short_name = build_string ("fontset-startup");
1876 else
1877 {
1878 char temp[32];
1879 int len = XINT (Flength (auto_fontset_alist));
8aa07a8d 1880
03ef560c
KH
1881 sprintf (temp, "fontset-auto%d", len);
1882 short_name = build_string (temp);
1883 }
1c82b4b3
KH
1884 fontset_spec = Fcopy_sequence (font_spec);
1885 ASET (fontset_spec, FONT_REGISTRY_INDEX, short_name);
1886 name = Ffont_xlfd_name (fontset_spec);
03ef560c
KH
1887 if (NILP (name))
1888 {
1889 int i;
1890
1891 for (i = 0; i < FONT_SIZE_INDEX; i++)
1892 if ((i != FONT_FAMILY_INDEX) && (i != FONT_REGISTRY_INDEX))
1c82b4b3
KH
1893 ASET (fontset_spec, i, Qnil);
1894 name = Ffont_xlfd_name (fontset_spec);
03ef560c
KH
1895 if (NILP (name))
1896 abort ();
1897 }
1898 fontset = make_fontset (Qnil, name, Qnil);
1899 FONTSET_ASCII (fontset) = font_name;
1c82b4b3
KH
1900 font_spec = Fcons (SYMBOL_NAME (AREF (font_spec, FONT_FAMILY_INDEX)),
1901 SYMBOL_NAME (AREF (font_spec, FONT_REGISTRY_INDEX)));
1902 Fset_fontset_font (name, Qlatin, font_spec, Qnil, Qnil);
1903 Fset_fontset_font (name, Qnil, font_spec, Qnil, Qnil);
03ef560c 1904 return XINT (FONTSET_ID (fontset));
8aa07a8d
KH
1905}
1906
1907struct font *
1908fontset_ascii_font (f, id)
1909 FRAME_PTR f;
1910 int id;
1911{
1912 Lisp_Object fontset = FONTSET_FROM_ID (id);
1913 Lisp_Object ascii_slot = FONTSET_ASCII (fontset);
1914 Lisp_Object val, font_object;
1915
1916 if (CONSP (ascii_slot))
1917 {
1918 Lisp_Object ascii_font_name = XCAR (ascii_slot);
1919
1920 font_object = Qnil;
1921 for (val = XCDR (ascii_slot); ! NILP (val); val = XCDR (val))
1922 {
1923 Lisp_Object frame = font_get_frame (XCAR (val));
1924
1925 if (NILP (frame) || XFRAME (frame) == f)
1926 {
1927 font_object = XCAR (val);
1928 if (XSAVE_VALUE (font_object)->integer == 0)
1929 {
1930 font_object = font_open_by_name (f, SDATA (ascii_font_name));
1931 XSETCAR (val, font_object);
1932 }
1933 break;
1934 }
1935 }
1936 if (NILP (font_object))
1937 {
1938 font_object = font_open_by_name (f, SDATA (ascii_font_name));
1939 XSETCDR (ascii_slot, Fcons (font_object, XCDR (ascii_slot)));
1940 }
1941 }
1942 else
1943 {
1944 font_object = font_open_by_name (f, SDATA (ascii_slot));
1945 FONTSET_ASCII (fontset) = Fcons (ascii_slot, Fcons (font_object, Qnil));
1946 }
02dacbbc
KH
1947 if (NILP (font_object))
1948 return NULL;
8aa07a8d
KH
1949 return XSAVE_VALUE (font_object)->pointer;
1950}
1951
1952#endif /* USE_FONT_BACKEND */
d6aaac9e 1953
4ed46869 1954DEFUN ("font-info", Ffont_info, Sfont_info, 1, 2, 0,
335c5470
PJ
1955 doc: /* Return information about a font named NAME on frame FRAME.
1956If FRAME is omitted or nil, use the selected frame.
1957The returned value is a vector of OPENED-NAME, FULL-NAME, CHARSET, SIZE,
1958 HEIGHT, BASELINE-OFFSET, RELATIVE-COMPOSE, and DEFAULT-ASCENT,
1959where
1960 OPENED-NAME is the name used for opening the font,
1961 FULL-NAME is the full name of the font,
1962 SIZE is the maximum bound width of the font,
1963 HEIGHT is the height of the font,
1964 BASELINE-OFFSET is the upward offset pixels from ASCII baseline,
1965 RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling
1966 how to compose characters.
1967If the named font is not yet loaded, return nil. */)
1968 (name, frame)
4ed46869
KH
1969 Lisp_Object name, frame;
1970{
1971 FRAME_PTR f;
1972 struct font_info *fontp;
1973 Lisp_Object info;
8aa07a8d 1974 Lisp_Object font_object;
4ed46869
KH
1975
1976 (*check_window_system_func) ();
1977
b7826503 1978 CHECK_STRING (name);
0d407d77 1979 name = Fdowncase (name);
4ed46869 1980 if (NILP (frame))
18f39d0e 1981 frame = selected_frame;
b7826503 1982 CHECK_LIVE_FRAME (frame);
18f39d0e 1983 f = XFRAME (frame);
4ed46869
KH
1984
1985 if (!query_font_func)
1986 error ("Font query function is not supported");
1987
8aa07a8d
KH
1988#ifdef USE_FONT_BACKEND
1989 if (enable_font_backend)
1990 {
1991 font_object = font_open_by_name (f, SDATA (name));
1992 if (NILP (font_object))
1993 fontp = NULL;
1994 else
1995 fontp = (struct font_info *) XSAVE_VALUE (font_object)->pointer;
1996 }
1997 else
1998#endif /* USE_FONT_BACKEND */
d5db4077 1999 fontp = (*query_font_func) (f, SDATA (name));
4ed46869
KH
2000 if (!fontp)
2001 return Qnil;
2002
0d407d77 2003 info = Fmake_vector (make_number (7), Qnil);
4ed46869
KH
2004
2005 XVECTOR (info)->contents[0] = build_string (fontp->name);
2006 XVECTOR (info)->contents[1] = build_string (fontp->full_name);
0d407d77
KH
2007 XVECTOR (info)->contents[2] = make_number (fontp->size);
2008 XVECTOR (info)->contents[3] = make_number (fontp->height);
2009 XVECTOR (info)->contents[4] = make_number (fontp->baseline_offset);
2010 XVECTOR (info)->contents[5] = make_number (fontp->relative_compose);
2011 XVECTOR (info)->contents[6] = make_number (fontp->default_ascent);
4ed46869 2012
8aa07a8d
KH
2013#ifdef USE_FONT_BACKEND
2014 if (! NILP (font_object))
2015 font_close_object (f, font_object);
2016#endif /* USE_FONT_BACKEND */
4ed46869
KH
2017 return info;
2018}
2019
1ff005e1 2020
92c15c34
KH
2021/* Return a cons (FONT-NAME . GLYPH-CODE).
2022 FONT-NAME is the font name for the character at POSITION in the current
1ff005e1 2023 buffer. This is computed from all the text properties and overlays
cf14fd6e
KH
2024 that apply to POSITION. POSTION may be nil, in which case,
2025 FONT-NAME is the font name for display the character CH with the
2026 default face.
2027
92c15c34
KH
2028 GLYPH-CODE is the glyph code in the font to use for the character.
2029
2030 If the 2nd optional arg CH is non-nil, it is a character to check
2031 the font instead of the character at POSITION.
2032
2033 It returns nil in the following cases:
1ff005e1
KH
2034
2035 (1) The window system doesn't have a font for the character (thus
2036 it is displayed by an empty box).
2037
2038 (2) The character code is invalid.
2039
cf14fd6e
KH
2040 (3) If POSITION is not nil, and the current buffer is not displayed
2041 in any window.
1ff005e1
KH
2042
2043 In addition, the returned font name may not take into account of
2044 such redisplay engine hooks as what used in jit-lock-mode if
2045 POSITION is currently not visible. */
2046
2047
92c15c34 2048DEFUN ("internal-char-font", Finternal_char_font, Sinternal_char_font, 1, 2, 0,
335c5470 2049 doc: /* For internal use only. */)
92c15c34
KH
2050 (position, ch)
2051 Lisp_Object position, ch;
1ff005e1
KH
2052{
2053 int pos, pos_byte, dummy;
2054 int face_id;
2055 int c;
1ff005e1
KH
2056 struct frame *f;
2057 struct face *face;
7e1a1cd9 2058 Lisp_Object charset, rfont_def;
f0be8ea0 2059 int cs_id;
1ff005e1 2060
cf14fd6e 2061 if (NILP (position))
92c15c34
KH
2062 {
2063 CHECK_CHARACTER (ch);
2064 c = XINT (ch);
cf14fd6e
KH
2065 f = XFRAME (selected_frame);
2066 face_id = DEFAULT_FACE_ID;
327719ee 2067 pos = -1;
f0be8ea0 2068 cs_id = -1;
cf14fd6e
KH
2069 }
2070 else
2071 {
2f80c0a2 2072 Lisp_Object window, charset;
cf14fd6e
KH
2073 struct window *w;
2074
2075 CHECK_NUMBER_COERCE_MARKER (position);
2076 pos = XINT (position);
2077 if (pos < BEGV || pos >= ZV)
2078 args_out_of_range_3 (position, make_number (BEGV), make_number (ZV));
2079 pos_byte = CHAR_TO_BYTE (pos);
2080 if (NILP (ch))
2081 c = FETCH_CHAR (pos_byte);
2082 else
2083 {
2084 CHECK_NATNUM (ch);
2085 c = XINT (ch);
2086 }
2087 window = Fget_buffer_window (Fcurrent_buffer (), Qnil);
2088 if (NILP (window))
2089 return Qnil;
2090 w = XWINDOW (window);
2091 f = XFRAME (w->frame);
2092 face_id = face_at_buffer_position (w, pos, -1, -1, &dummy, pos + 100, 0);
2f80c0a2
KH
2093 charset = Fget_char_property (position, Qcharset, Qnil);
2094 if (CHARSETP (charset))
f0be8ea0 2095 cs_id = XINT (CHARSET_SYMBOL_ID (charset));
2f80c0a2 2096 else
f0be8ea0 2097 cs_id = -1;
92c15c34 2098 }
1ff005e1 2099 if (! CHAR_VALID_P (c, 0))
1ff005e1 2100 return Qnil;
327719ee 2101 face_id = FACE_FOR_CHAR (f, FACE_FROM_ID (f, face_id), c, pos, Qnil);
1ff005e1 2102 face = FACE_FROM_ID (f, face_id);
f0be8ea0 2103 rfont_def = fontset_font (FONTSET_FROM_ID (face->fontset), c, face, cs_id);
8aa07a8d
KH
2104#ifdef USE_FONT_BACKEND
2105 if (enable_font_backend)
2106 {
8aa07a8d
KH
2107 if (VECTORP (rfont_def) && ! NILP (AREF (rfont_def, 4)))
2108 {
2109 Lisp_Object font_object = AREF (rfont_def, 4);
2110 struct font *font = XSAVE_VALUE (font_object)->pointer;
2111 unsigned code = font->driver->encode_char (font, c);
a49d705d 2112 Lisp_Object fontname = font_get_name (font_object);
8aa07a8d
KH
2113
2114 if (code == FONT_INVALID_CODE)
2115 return Fcons (fontname, Qnil);
2116 if (code <= MOST_POSITIVE_FIXNUM)
2117 return Fcons (fontname, make_number (code));
2118 return Fcons (fontname, Fcons (make_number (code >> 16),
2119 make_number (code & 0xFFFF)));
2120 }
2121 return Qnil;
2122 }
2123#endif /* USE_FONT_BACKEND */
92c15c34
KH
2124 if (VECTORP (rfont_def) && STRINGP (AREF (rfont_def, 3)))
2125 {
2126 Lisp_Object font_def;
2127 struct font_info *fontp;
2128 struct charset *charset;
2129 XChar2b char2b;
2130 int code;
2131
2132 font_def = AREF (rfont_def, 2);
2133 charset = CHARSET_FROM_ID (XINT (AREF (font_def, 1)));
2134 code = ENCODE_CHAR (charset, c);
2135 if (code == CHARSET_INVALID_CODE (charset))
2136 return (Fcons (AREF (rfont_def, 3), Qnil));
2137 STORE_XCHAR2B (&char2b, ((code >> 8) & 0xFF), (code & 0xFF));
2138 fontp = (*get_font_info_func) (f, XINT (AREF (rfont_def, 1)));
c73bd236 2139 FRAME_RIF (f)->encode_char (c, &char2b, fontp, charset, NULL);
92c15c34
KH
2140 code = (XCHAR2B_BYTE1 (&char2b) << 8) | XCHAR2B_BYTE2 (&char2b);
2141 return (Fcons (AREF (rfont_def, 3), make_number (code)));
2142 }
2143 return Qnil;
1ff005e1
KH
2144}
2145
2146
1d5d7200
KH
2147DEFUN ("fontset-info", Ffontset_info, Sfontset_info, 1, 2, 0,
2148 doc: /* Return information about a fontset FONTSET on frame FRAME.
2149The value is a char-table of which elements has this form.
e2b45cf9 2150
1d5d7200 2151 ((FONT-PATTERN OPENED-FONT ...) ...)
1ff005e1 2152
1d5d7200 2153FONT-PATTERN is a vector:
1ff005e1 2154
1d5d7200 2155 [ FAMILY WEIGHT SLANT SWIDTH ADSTYLE REGISTRY ]
1ff005e1 2156
1d5d7200 2157or a string of font name pattern.
1ff005e1 2158
d6aaac9e 2159OPENED-FONT is a name of a font actually opened.
1ff005e1 2160
d6aaac9e
KH
2161The char-table has one extra slot. The value is a char-table
2162containing the information about the derived fonts from the default
2163fontset. The format is the same as abobe. */)
1d5d7200
KH
2164 (fontset, frame)
2165 Lisp_Object fontset, frame;
4ed46869
KH
2166{
2167 FRAME_PTR f;
cc7b6145
KH
2168 Lisp_Object *realized[2], fontsets[2], tables[2];
2169 Lisp_Object val, elt;
2170 int c, i, j, k;
fc8865fc 2171
4ed46869
KH
2172 (*check_window_system_func) ();
2173
1d5d7200 2174 fontset = check_fontset_name (fontset);
0d407d77 2175
4ed46869 2176 if (NILP (frame))
18f39d0e 2177 frame = selected_frame;
b7826503 2178 CHECK_LIVE_FRAME (frame);
18f39d0e 2179 f = XFRAME (frame);
4ed46869 2180
1d5d7200
KH
2181 /* Recode fontsets realized on FRAME from the base fontset FONTSET
2182 in the table `realized'. */
cc7b6145
KH
2183 realized[0] = (Lisp_Object *) alloca (sizeof (Lisp_Object)
2184 * ASIZE (Vfontset_table));
2185 for (i = j = 0; i < ASIZE (Vfontset_table); i++)
0d407d77 2186 {
1ff005e1
KH
2187 elt = FONTSET_FROM_ID (i);
2188 if (!NILP (elt)
1d5d7200
KH
2189 && EQ (FONTSET_BASE (elt), fontset)
2190 && EQ (FONTSET_FRAME (elt), frame))
cc7b6145 2191 realized[0][j++] = elt;
0d407d77 2192 }
cc7b6145 2193 realized[0][j] = Qnil;
4ed46869 2194
cc7b6145
KH
2195 realized[1] = (Lisp_Object *) alloca (sizeof (Lisp_Object)
2196 * ASIZE (Vfontset_table));
2197 for (i = j = 0; ! NILP (realized[0][i]); i++)
2198 {
2199 elt = FONTSET_DEFAULT (realized[0][i]);
2200 if (! NILP (elt))
2201 realized[1][j++] = elt;
2202 }
2203 realized[1][j] = Qnil;
2204
2205 tables[0] = Fmake_char_table (Qfontset_info, Qnil);
2206 tables[1] = Fmake_char_table (Qnil, Qnil);
2207 XCHAR_TABLE (tables[0])->extras[0] = tables[1];
2208 fontsets[0] = fontset;
2209 fontsets[1] = Vdefault_fontset;
e2b45cf9 2210
1d5d7200
KH
2211 /* Accumulate information of the fontset in TABLE. The format of
2212 each element is ((FONT-SPEC OPENED-FONT ...) ...). */
cc7b6145 2213 for (k = 0; k <= 1; k++)
0d407d77 2214 {
cc7b6145 2215 for (c = 0; c <= MAX_CHAR; )
d6aaac9e
KH
2216 {
2217 int from, to;
0d407d77 2218
cc7b6145
KH
2219 if (c <= MAX_5_BYTE_CHAR)
2220 {
2221 val = char_table_ref_and_range (fontsets[k], c, &from, &to);
2222 if (to > MAX_5_BYTE_CHAR)
2223 to = MAX_5_BYTE_CHAR;
2224 }
2225 else
2226 {
2227 val = FONTSET_FALLBACK (fontsets[k]);
2228 to = MAX_CHAR;
2229 }
d6aaac9e 2230 if (VECTORP (val))
0d407d77 2231 {
d6aaac9e
KH
2232 Lisp_Object alist;
2233
2234 /* At first, set ALIST to ((FONT-SPEC) ...). */
2235 for (alist = Qnil, i = 0; i < ASIZE (val); i++)
2236 alist = Fcons (Fcons (AREF (AREF (val, i), 0), Qnil), alist);
2237 alist = Fnreverse (alist);
2238
2239 /* Then store opend font names to cdr of each elements. */
cc7b6145 2240 for (i = 0; ! NILP (realized[k][i]); i++)
1ff005e1 2241 {
cc7b6145
KH
2242 if (c <= MAX_5_BYTE_CHAR)
2243 val = FONTSET_REF (realized[k][i], c);
2244 else
2245 val = FONTSET_FALLBACK (realized[k][i]);
2246 if (! VECTORP (val))
d6aaac9e 2247 continue;
7e1a1cd9
KH
2248 /* VAL is [int int ?
2249 [FACE-ID FONT-INDEX FONT-DEF FONT-NAME] ...].
d6aaac9e 2250 If a font of an element is already opened,
7e1a1cd9 2251 FONT-NAME is the name of a opened font. */
6bad8007 2252 for (j = 3; j < ASIZE (val); j++)
7e1a1cd9 2253 if (STRINGP (AREF (AREF (val, j), 3)))
d6aaac9e
KH
2254 {
2255 Lisp_Object font_idx;
2256
2257 font_idx = AREF (AREF (val, j), 1);
2258 elt = Fassq (AREF (AREF (AREF (val, j), 2), 0), alist);
2259 if (CONSP (elt)
2260 && NILP (Fmemq (font_idx, XCDR(elt))))
2261 nconc2 (elt, Fcons (font_idx, Qnil));
2262 }
1ff005e1 2263 }
d6aaac9e
KH
2264 for (val = alist; CONSP (val); val = XCDR (val))
2265 for (elt = XCDR (XCAR (val)); CONSP (elt); elt = XCDR (elt))
1d5d7200 2266 {
d6aaac9e
KH
2267 struct font_info *font_info
2268 = (*get_font_info_func) (f, XINT (XCAR (elt)));
2269 XSETCAR (elt, build_string (font_info->full_name));
1d5d7200 2270 }
d6aaac9e
KH
2271
2272 /* Store ALIST in TBL for characters C..TO. */
cc7b6145
KH
2273 if (c <= MAX_5_BYTE_CHAR)
2274 char_table_set_range (tables[k], c, to, alist);
2275 else
2276 XCHAR_TABLE (tables[k])->defalt = alist;
0d407d77 2277 }
d6aaac9e 2278 c = to + 1;
0d407d77
KH
2279 }
2280 }
a921395d 2281
cc7b6145 2282 return tables[0];
4ed46869
KH
2283}
2284
1d5d7200 2285
0fdf26e6 2286DEFUN ("fontset-font", Ffontset_font, Sfontset_font, 2, 3, 0,
335c5470 2287 doc: /* Return a font name pattern for character CH in fontset NAME.
0fdf26e6
KH
2288If NAME is t, find a pattern in the default fontset.
2289
2290The value has the form (FAMILY . REGISTRY), where FAMILY is a font
2291family name and REGISTRY is a font registry name. This is actually
2292the first font name pattern for CH in the fontset or in the default
2293fontset.
2294
2295If the 2nd optional arg ALL is non-nil, return a list of all font name
2296patterns. */)
2297 (name, ch, all)
2298 Lisp_Object name, ch, all;
0d407d77 2299{
1337ac77 2300 int c;
0fdf26e6
KH
2301 Lisp_Object fontset, elt, list, repertory, val;
2302 int i, j;
0d407d77
KH
2303
2304 fontset = check_fontset_name (name);
2305
06f76f0d 2306 CHECK_CHARACTER (ch);
0d407d77 2307 c = XINT (ch);
0fdf26e6
KH
2308 list = Qnil;
2309 while (1)
2310 {
2311 for (i = 0, elt = FONTSET_REF (fontset, c); i < 2;
2312 i++, elt = FONTSET_FALLBACK (fontset))
2313 if (VECTORP (elt))
2314 for (j = 0; j < ASIZE (elt); j++)
2315 {
2316 val = AREF (elt, j);
2317 repertory = AREF (val, 1);
2318 if (INTEGERP (repertory))
2319 {
2320 struct charset *charset = CHARSET_FROM_ID (XINT (repertory));
2321
2322 if (! CHAR_CHARSET_P (c, charset))
2323 continue;
2324 }
2325 else if (CHAR_TABLE_P (repertory))
2326 {
2327 if (NILP (CHAR_TABLE_REF (repertory, c)))
2328 continue;
2329 }
2330 val = AREF (val, 0);
2331 val = Fcons (AREF (val, 0), AREF (val, 5));
2332 if (NILP (all))
2333 return val;
2334 list = Fcons (val, list);
2335 }
2336 if (EQ (fontset, Vdefault_fontset))
2337 break;
2338 fontset = Vdefault_fontset;
2339 }
2340 return (Fnreverse (list));
0d407d77 2341}
0d407d77
KH
2342
2343DEFUN ("fontset-list", Ffontset_list, Sfontset_list, 0, 0, 0,
335c5470
PJ
2344 doc: /* Return a list of all defined fontset names. */)
2345 ()
0d407d77
KH
2346{
2347 Lisp_Object fontset, list;
2348 int i;
2349
2350 list = Qnil;
2351 for (i = 0; i < ASIZE (Vfontset_table); i++)
2352 {
2353 fontset = FONTSET_FROM_ID (i);
2354 if (!NILP (fontset)
2355 && BASE_FONTSET_P (fontset))
2356 list = Fcons (FONTSET_NAME (fontset), list);
2357 }
1ff005e1 2358
0d407d77
KH
2359 return list;
2360}
2361
452a78e0
KH
2362
2363#ifdef FONTSET_DEBUG
2364
2365Lisp_Object
2366dump_fontset (fontset)
2367 Lisp_Object fontset;
2368{
2369 Lisp_Object vec;
2370
2371 vec = Fmake_vector (make_number (3), Qnil);
2372 ASET (vec, 0, FONTSET_ID (fontset));
2373
2374 if (BASE_FONTSET_P (fontset))
2375 {
2376 ASET (vec, 1, FONTSET_NAME (fontset));
2377 }
2378 else
2379 {
2380 Lisp_Object frame;
2381
2382 frame = FONTSET_FRAME (fontset);
2383 if (FRAMEP (frame))
2384 {
2385 FRAME_PTR f = XFRAME (frame);
2386
2387 if (FRAME_LIVE_P (f))
1c82b4b3
KH
2388 ASET (vec, 1,
2389 Fcons (FONTSET_NAME (FONTSET_BASE (fontset)), f->name));
452a78e0 2390 else
1c82b4b3
KH
2391 ASET (vec, 1,
2392 Fcons (FONTSET_NAME (FONTSET_BASE (fontset)), Qnil));
452a78e0 2393 }
eb36588a
KH
2394 if (!NILP (FONTSET_DEFAULT (fontset)))
2395 ASET (vec, 2, FONTSET_ID (FONTSET_DEFAULT (fontset)));
452a78e0
KH
2396 }
2397 return vec;
2398}
2399
2400DEFUN ("fontset-list-all", Ffontset_list_all, Sfontset_list_all, 0, 0, 0,
2401 doc: /* Return a brief summary of all fontsets for debug use. */)
2402 ()
2403{
2404 Lisp_Object val;
2405 int i;
2406
2407 for (i = 0, val = Qnil; i < ASIZE (Vfontset_table); i++)
2408 if (! NILP (AREF (Vfontset_table, i)))
2409 val = Fcons (dump_fontset (AREF (Vfontset_table, i)), val);
2410 return (Fnreverse (val));
2411}
2412#endif /* FONTSET_DEBUG */
2413
dfcf069d 2414void
4ed46869
KH
2415syms_of_fontset ()
2416{
4ed46869
KH
2417 if (!load_font_func)
2418 /* Window system initializer should have set proper functions. */
2419 abort ();
2420
1d5d7200 2421 DEFSYM (Qfontset, "fontset");
eb36588a 2422 Fput (Qfontset, Qchar_table_extra_slots, make_number (9));
d6aaac9e
KH
2423 DEFSYM (Qfontset_info, "fontset-info");
2424 Fput (Qfontset_info, Qchar_table_extra_slots, make_number (1));
4ed46869 2425
1d5d7200
KH
2426 DEFSYM (Qprepend, "prepend");
2427 DEFSYM (Qappend, "append");
c3fb88cc 2428 DEFSYM (Qlatin, "latin");
4ed46869
KH
2429
2430 Vcached_fontset_data = Qnil;
2431 staticpro (&Vcached_fontset_data);
2432
0d407d77
KH
2433 Vfontset_table = Fmake_vector (make_number (32), Qnil);
2434 staticpro (&Vfontset_table);
0d407d77
KH
2435
2436 Vdefault_fontset = Fmake_char_table (Qfontset, Qnil);
2437 staticpro (&Vdefault_fontset);
1ff005e1
KH
2438 FONTSET_ID (Vdefault_fontset) = make_number (0);
2439 FONTSET_NAME (Vdefault_fontset)
2440 = build_string ("-*-*-*-*-*-*-*-*-*-*-*-*-fontset-default");
1ff005e1
KH
2441 AREF (Vfontset_table, 0) = Vdefault_fontset;
2442 next_fontset_id = 1;
4ed46869 2443
452a78e0
KH
2444 auto_fontset_alist = Qnil;
2445 staticpro (&auto_fontset_alist);
2446
4ed46869 2447 DEFVAR_LISP ("font-encoding-alist", &Vfont_encoding_alist,
1d5d7200
KH
2448 doc: /*
2449Alist of fontname patterns vs the corresponding encoding and repertory info.
2450Each element looks like (REGEXP . (ENCODING . REPERTORY)),
2451where ENCODING is a charset or a char-table,
8f924df7 2452and REPERTORY is a charset, a char-table, or nil.
1d5d7200
KH
2453
2454ENCODING is for converting a character to a glyph code of the font.
2455If ENCODING is a charset, encoding a character by the charset gives
2456the corresponding glyph code. If ENCODING is a char-table, looking up
2457the table by a character gives the corresponding glyph code.
2458
2459REPERTORY specifies a repertory of characters supported by the font.
2460If REPERTORY is a charset, all characters beloging to the charset are
2461supported. If REPERTORY is a char-table, all characters who have a
2462non-nil value in the table are supported. It REPERTORY is nil, Emacs
2463gets the repertory information by an opened font and ENCODING. */);
4ed46869
KH
2464 Vfont_encoding_alist = Qnil;
2465
6a7e6d80 2466 DEFVAR_LISP ("use-default-ascent", &Vuse_default_ascent,
1d5d7200
KH
2467 doc: /*
2468Char table of characters whose ascent values should be ignored.
335c5470
PJ
2469If an entry for a character is non-nil, the ascent value of the glyph
2470is assumed to be what specified by _MULE_DEFAULT_ASCENT property of a font.
2471
2472This affects how a composite character which contains
2473such a character is displayed on screen. */);
2aeafb78
KH
2474 Vuse_default_ascent = Qnil;
2475
2476 DEFVAR_LISP ("ignore-relative-composition", &Vignore_relative_composition,
1d5d7200
KH
2477 doc: /*
2478Char table of characters which is not composed relatively.
335c5470
PJ
2479If an entry for a character is non-nil, a composition sequence
2480which contains that character is displayed so that
2481the glyph of that character is put without considering
2482an ascent and descent value of a previous character. */);
810abb87 2483 Vignore_relative_composition = Qnil;
6a7e6d80 2484
01d4b817 2485 DEFVAR_LISP ("alternate-fontname-alist", &Valternate_fontname_alist,
335c5470
PJ
2486 doc: /* Alist of fontname vs list of the alternate fontnames.
2487When a specified font name is not found, the corresponding
2488alternate fontnames (if any) are tried instead. */);
01d4b817 2489 Valternate_fontname_alist = Qnil;
8c83e4f9 2490
1c283e35 2491 DEFVAR_LISP ("fontset-alias-alist", &Vfontset_alias_alist,
335c5470 2492 doc: /* Alist of fontset names vs the aliases. */);
1ff005e1
KH
2493 Vfontset_alias_alist = Fcons (Fcons (FONTSET_NAME (Vdefault_fontset),
2494 build_string ("fontset-default")),
2495 Qnil);
1c283e35 2496
810abb87
KH
2497 DEFVAR_LISP ("vertical-centering-font-regexp",
2498 &Vvertical_centering_font_regexp,
335c5470
PJ
2499 doc: /* *Regexp matching font names that require vertical centering on display.
2500When a character is displayed with such fonts, the character is displayed
fc8865fc 2501at the vertical center of lines. */);
810abb87
KH
2502 Vvertical_centering_font_regexp = Qnil;
2503
21ff5ed6
KH
2504 DEFVAR_LISP ("otf-script-alist", &Votf_script_alist,
2505 doc: /* Alist of OpenType script tags vs the corresponding script names. */);
2506 Votf_script_alist = Qnil;
2507
4ed46869
KH
2508 defsubr (&Squery_fontset);
2509 defsubr (&Snew_fontset);
2510 defsubr (&Sset_fontset_font);
2511 defsubr (&Sfont_info);
1ff005e1 2512 defsubr (&Sinternal_char_font);
4ed46869 2513 defsubr (&Sfontset_info);
0d407d77
KH
2514 defsubr (&Sfontset_font);
2515 defsubr (&Sfontset_list);
452a78e0
KH
2516#ifdef FONTSET_DEBUG
2517 defsubr (&Sfontset_list_all);
2518#endif
e3400864 2519}
92c15c34
KH
2520
2521/* arch-tag: ea861585-2f5f-4e5b-9849-d04a9c3a3537
2522 (do not change this comment) */