Merge from emacs--devo--0
[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)
862 {
1d5d7200 863 /* We must grow Vfontset_table. */
0d407d77 864 Lisp_Object tem;
fc8865fc 865 int i;
4ed46869 866
06f76f0d 867 tem = Fmake_vector (make_number (size + 32), Qnil);
0d407d77
KH
868 for (i = 0; i < size; i++)
869 AREF (tem, i) = AREF (Vfontset_table, i);
870 Vfontset_table = tem;
871 }
4ed46869 872
11d9bd93 873 fontset = Fmake_char_table (Qfontset, Qnil);
0d407d77
KH
874
875 FONTSET_ID (fontset) = make_number (id);
06f76f0d
KH
876 if (NILP (base))
877 {
878 FONTSET_NAME (fontset) = name;
879 }
880 else
881 {
882 FONTSET_NAME (fontset) = Qnil;
883 FONTSET_FRAME (fontset) = frame;
884 FONTSET_BASE (fontset) = base;
885 }
0d407d77 886
06f76f0d 887 ASET (Vfontset_table, id, fontset);
0d407d77
KH
888 next_fontset_id = id + 1;
889 return fontset;
4ed46869
KH
890}
891
0d407d77 892
2cdd4f88
MB
893/* Set the ASCII font of the default fontset to FONTNAME if that is
894 not yet set. */
895void
896set_default_ascii_font (fontname)
0d407d77
KH
897 Lisp_Object fontname;
898{
d7fb7b91 899 if (! STRINGP (FONTSET_ASCII (Vdefault_fontset)))
2cdd4f88
MB
900 {
901 int id = fs_query_fontset (fontname, 2);
902
903 if (id >= 0)
d7fb7b91
KH
904 fontname = FONTSET_ASCII (FONTSET_FROM_ID (id));
905 FONTSET_ASCII (Vdefault_fontset)= fontname;
2cdd4f88 906 }
0d407d77
KH
907}
908
909\f
1d5d7200 910/********** INTERFACES TO xfaces.c, xfns.c, and dispextern.h **********/
0d407d77 911
1d5d7200 912/* Return the name of the fontset who has ID. */
0d407d77
KH
913
914Lisp_Object
915fontset_name (id)
916 int id;
917{
918 Lisp_Object fontset;
06f76f0d 919
0d407d77
KH
920 fontset = FONTSET_FROM_ID (id);
921 return FONTSET_NAME (fontset);
922}
923
924
1d5d7200 925/* Return the ASCII font name of the fontset who has ID. */
0d407d77
KH
926
927Lisp_Object
928fontset_ascii (id)
929 int id;
930{
931 Lisp_Object fontset, elt;
06f76f0d 932
0d407d77
KH
933 fontset= FONTSET_FROM_ID (id);
934 elt = FONTSET_ASCII (fontset);
8aa07a8d
KH
935#ifdef USE_FONT_BACKEND
936 if (CONSP (elt))
937 elt = XCAR (elt);
938#endif /* USE_FONT_BACKEND */
1d5d7200
KH
939 /* It is assured that ELT is always a string (i.e. fontname
940 pattern). */
941 return elt;
0d407d77
KH
942}
943
944
06f76f0d
KH
945/* Free fontset of FACE defined on frame F. Called from
946 free_realized_face. */
0d407d77 947
4ed46869 948void
0d407d77
KH
949free_face_fontset (f, face)
950 FRAME_PTR f;
951 struct face *face;
4ed46869 952{
452a78e0
KH
953 Lisp_Object fontset;
954
955 fontset = AREF (Vfontset_table, face->fontset);
956 xassert (!NILP (fontset) && ! BASE_FONTSET_P (fontset));
957 xassert (f == XFRAME (FONTSET_FRAME (fontset)));
1d5d7200 958 ASET (Vfontset_table, face->fontset, Qnil);
06f76f0d
KH
959 if (face->fontset < next_fontset_id)
960 next_fontset_id = face->fontset;
eb36588a 961 if (! NILP (FONTSET_DEFAULT (fontset)))
452a78e0 962 {
e1a14cdc 963 int id = XINT (FONTSET_ID (FONTSET_DEFAULT (fontset)));
452a78e0
KH
964
965 fontset = AREF (Vfontset_table, id);
966 xassert (!NILP (fontset) && ! BASE_FONTSET_P (fontset));
967 xassert (f == XFRAME (FONTSET_FRAME (fontset)));
968 ASET (Vfontset_table, id, Qnil);
969 if (id < next_fontset_id)
970 next_fontset_id = face->fontset;
971 }
0d407d77 972}
18998710 973
0d407d77 974
e0f24100 975/* Return 1 if FACE is suitable for displaying character C.
0d407d77 976 Otherwise return 0. Called from the macro FACE_SUITABLE_FOR_CHAR_P
06f76f0d 977 when C is not an ASCII character. */
0d407d77
KH
978
979int
980face_suitable_for_char_p (face, c)
981 struct face *face;
982 int c;
983{
7e1a1cd9 984 Lisp_Object fontset, rfont_def;
0d407d77 985
0d407d77 986 fontset = FONTSET_FROM_ID (face->fontset);
7e1a1cd9
KH
987 rfont_def = fontset_font (fontset, c, NULL, -1);
988 return (VECTORP (rfont_def)
989 && INTEGERP (AREF (rfont_def, 0))
990 && face->id == XINT (AREF (rfont_def, 0)));
0d407d77
KH
991}
992
993
994/* Return ID of face suitable for displaying character C on frame F.
1d5d7200
KH
995 FACE must be reazlied for ASCII characters in advance. Called from
996 the macro FACE_FOR_CHAR. */
0d407d77
KH
997
998int
6bad8007 999face_for_char (f, face, c, pos, object)
0d407d77
KH
1000 FRAME_PTR f;
1001 struct face *face;
6bad8007
KH
1002 int c, pos;
1003 Lisp_Object object;
0d407d77 1004{
7e1a1cd9
KH
1005 Lisp_Object fontset, charset, rfont_def;
1006 int face_id;
6bad8007 1007 int id;
1d5d7200
KH
1008
1009 if (ASCII_CHAR_P (c))
1010 return face->ascii_face->id;
0d407d77
KH
1011
1012 xassert (fontset_id_valid_p (face->fontset));
1013 fontset = FONTSET_FROM_ID (face->fontset);
1014 xassert (!BASE_FONTSET_P (fontset));
6bad8007
KH
1015 if (pos < 0)
1016 id = -1;
1017 else
1018 {
1019 charset = Fget_char_property (make_number (pos), Qcharset, object);
1020 if (NILP (charset))
1021 id = -1;
1022 else if (CHARSETP (charset))
1023 id = XINT (CHARSET_SYMBOL_ID (charset));
1024 }
7e1a1cd9
KH
1025 rfont_def = fontset_font (fontset, c, face, id);
1026 if (VECTORP (rfont_def))
1027 {
8aa07a8d
KH
1028#ifdef USE_FONT_BACKEND
1029 if (enable_font_backend
1030 && NILP (AREF (rfont_def, 0)))
1031 {
1032 struct font *font = XSAVE_VALUE (AREF (rfont_def, 4))->pointer;
1033
1034 face_id = face_for_font (f, font, face);
1035 ASET (rfont_def, 0, make_number (face_id));
1036 }
1037 else
1038#endif /* USE_FONT_BACKEND */
7e1a1cd9
KH
1039 if (NILP (AREF (rfont_def, 0)))
1040 {
1041 /* We have not yet made a realized face that uses this font. */
1042 int font_idx = XINT (AREF (rfont_def, 1));
1043
1044 face_id = lookup_non_ascii_face (f, font_idx, face);
1045 ASET (rfont_def, 0, make_number (face_id));
1046 }
1047 return XINT (AREF (rfont_def, 0));
1048 }
1049
1050 if (NILP (FONTSET_NOFONT_FACE (fontset)))
1051 {
1052 face_id = lookup_non_ascii_face (f, -1, face);
1053 FONTSET_NOFONT_FACE (fontset) = make_number (face_id);
1054 }
1055 return XINT (FONTSET_NOFONT_FACE (fontset));
0d407d77
KH
1056}
1057
1058
1059/* Make a realized fontset for ASCII face FACE on frame F from the
1060 base fontset BASE_FONTSET_ID. If BASE_FONTSET_ID is -1, use the
1061 default fontset as the base. Value is the id of the new fontset.
1062 Called from realize_x_face. */
1063
1064int
1d5d7200 1065make_fontset_for_ascii_face (f, base_fontset_id, face)
0d407d77
KH
1066 FRAME_PTR f;
1067 int base_fontset_id;
1d5d7200 1068 struct face *face;
0d407d77 1069{
1337ac77 1070 Lisp_Object base_fontset, fontset, frame;
0d407d77
KH
1071
1072 XSETFRAME (frame, f);
1073 if (base_fontset_id >= 0)
1074 {
1075 base_fontset = FONTSET_FROM_ID (base_fontset_id);
1076 if (!BASE_FONTSET_P (base_fontset))
1077 base_fontset = FONTSET_BASE (base_fontset);
1078 xassert (BASE_FONTSET_P (base_fontset));
1d5d7200
KH
1079 if (! BASE_FONTSET_P (base_fontset))
1080 abort ();
4ed46869 1081 }
0d407d77
KH
1082 else
1083 base_fontset = Vdefault_fontset;
1084
1085 fontset = make_fontset (frame, Qnil, base_fontset);
1d5d7200 1086 {
1c82b4b3 1087 Lisp_Object elt, rfont_def, val;
1d5d7200
KH
1088
1089 elt = FONTSET_REF (base_fontset, 0);
7e1a1cd9 1090 xassert (VECTORP (elt) && ASIZE (elt) > 0);
8aa07a8d
KH
1091#ifdef USE_FONT_BACKEND
1092 rfont_def = Fmake_vector (make_number (5), Qnil);
1093 if (enable_font_backend && face->font_info)
1094 {
1095 struct font *font = (struct font *) face->font_info;
1096
1097 ASET (rfont_def, 3, font->entity);
1098 ASET (rfont_def, 4, font_find_object (font));
1099 }
ce4aada8
KH
1100 else
1101#endif /* USE_FONT_BACKEND */
8aa07a8d
KH
1102 {
1103 rfont_def = Fmake_vector (make_number (4), Qnil);
1104 ASET (rfont_def, 3, build_string (face->font_name));
1105 }
7e1a1cd9
KH
1106 ASET (rfont_def, 1, make_number (face->font_info_id));
1107 ASET (rfont_def, 2, AREF (elt, 0));
7e1a1cd9 1108 elt = Fmake_vector (make_number (4), Qnil);
6bad8007 1109 ASET (elt, 0, make_number (charset_ordered_list_tick));
7e1a1cd9
KH
1110 ASET (elt, 1, make_number (charset_ascii));
1111 ASET (elt, 2, rfont_def);
1112 ASET (elt, 3, rfont_def);
1c82b4b3
KH
1113
1114 val = Fcons (Qlatin, Qnil);
1115 map_char_table (accumulate_script_ranges, Qnil, Vchar_script_table, val);
1116 for (val = XCDR (val); CONSP (val); val = XCDR (val))
1117 char_table_set_range (fontset, XINT (XCAR (XCAR (val))),
1118 XINT (XCDR (XCAR (val))), elt);
1119 FONTSET_FALLBACK (fontset) = elt;
1d5d7200 1120 }
f3231837 1121 return XINT (FONTSET_ID (fontset));
0d407d77
KH
1122}
1123
1124
97f4db8c
AI
1125#if defined(WINDOWSNT) && defined (_MSC_VER)
1126#pragma optimize("", off)
1127#endif
1128
06f76f0d
KH
1129/* Load a font named FONTNAME on frame F. Return a pointer to the
1130 struct font_info of the loaded font. If loading fails, return
6ab1fb6a
KH
1131 NULL. CHARSET is an ID of charset to encode characters for this
1132 font. If it is -1, find one from Vfont_encoding_alist. */
4ed46869
KH
1133
1134struct font_info *
6ab1fb6a 1135fs_load_font (f, fontname, charset)
4ed46869 1136 FRAME_PTR f;
4ed46869 1137 char *fontname;
6ab1fb6a 1138 int charset;
4ed46869 1139{
4ed46869 1140 struct font_info *fontp;
71c54d6f 1141 Lisp_Object fullname;
4ed46869 1142
0d407d77
KH
1143 if (!fontname)
1144 /* No way to get fontname. */
1d5d7200 1145 return NULL;
4ed46869 1146
06f76f0d 1147 fontp = (*load_font_func) (f, fontname, 0);
6ab1fb6a
KH
1148 if (! fontp || fontp->charset >= 0)
1149 return fontp;
4ed46869 1150
48728c92 1151 fontname = fontp->full_name;
71c54d6f 1152 fullname = build_string (fontp->full_name);
4ed46869 1153
6ab1fb6a 1154 if (charset < 0)
4ed46869 1155 {
6ab1fb6a 1156 Lisp_Object charset_symbol;
4ed46869 1157
71c54d6f 1158 charset_symbol = find_font_encoding (fullname);
6ab1fb6a
KH
1159 if (CONSP (charset_symbol))
1160 charset_symbol = XCAR (charset_symbol);
8aa07a8d
KH
1161 if (NILP (charset_symbol))
1162 charset_symbol = Qascii;
6ab1fb6a 1163 charset = XINT (CHARSET_SYMBOL_ID (charset_symbol));
4ed46869 1164 }
6ab1fb6a 1165 fontp->charset = charset;
1d5d7200 1166 fontp->vertical_centering = 0;
06f76f0d 1167 fontp->font_encoder = NULL;
727fb790 1168
6ab1fb6a 1169 if (charset != charset_ascii)
4ed46869 1170 {
1d5d7200
KH
1171 fontp->vertical_centering
1172 = (STRINGP (Vvertical_centering_font_regexp)
71c54d6f
KH
1173 && (fast_string_match_ignore_case
1174 (Vvertical_centering_font_regexp, fullname) >= 0));
4ed46869 1175
1d5d7200
KH
1176 if (find_ccl_program_func)
1177 (*find_ccl_program_func) (fontp);
4ed46869
KH
1178 }
1179
4ed46869
KH
1180 return fontp;
1181}
1182
97f4db8c
AI
1183#if defined(WINDOWSNT) && defined (_MSC_VER)
1184#pragma optimize("", on)
1185#endif
1186
0d407d77 1187\f
6ab1fb6a
KH
1188/* Return ENCODING or a cons of ENCODING and REPERTORY of the font
1189 FONTNAME. ENCODING is a charset symbol that specifies the encoding
1190 of the font. REPERTORY is a charset symbol or nil. */
1d5d7200
KH
1191
1192
8aa07a8d 1193Lisp_Object
1d5d7200 1194find_font_encoding (fontname)
71c54d6f 1195 Lisp_Object fontname;
1d5d7200
KH
1196{
1197 Lisp_Object tail, elt;
1198
1199 for (tail = Vfont_encoding_alist; CONSP (tail); tail = XCDR (tail))
1200 {
1201 elt = XCAR (tail);
1202 if (CONSP (elt)
1203 && STRINGP (XCAR (elt))
71c54d6f 1204 && fast_string_match_ignore_case (XCAR (elt), fontname) >= 0
1d5d7200
KH
1205 && (SYMBOLP (XCDR (elt))
1206 ? CHARSETP (XCDR (elt))
1207 : CONSP (XCDR (elt)) && CHARSETP (XCAR (XCDR (elt)))))
1208 return (XCDR (elt));
1209 }
fb78e2ed
KH
1210 /* We don't know the encoding of this font. Let's assume `ascii'. */
1211 return Qascii;
1d5d7200
KH
1212}
1213
1214
4ed46869
KH
1215/* Cache data used by fontset_pattern_regexp. The car part is a
1216 pattern string containing at least one wild card, the cdr part is
1217 the corresponding regular expression. */
1218static Lisp_Object Vcached_fontset_data;
1219
d5db4077 1220#define CACHED_FONTSET_NAME (SDATA (XCAR (Vcached_fontset_data)))
7539e11f 1221#define CACHED_FONTSET_REGEX (XCDR (Vcached_fontset_data))
4ed46869
KH
1222
1223/* If fontset name PATTERN contains any wild card, return regular
1224 expression corresponding to PATTERN. */
1225
0d407d77 1226static Lisp_Object
4ed46869
KH
1227fontset_pattern_regexp (pattern)
1228 Lisp_Object pattern;
1229{
d5db4077
KR
1230 if (!index (SDATA (pattern), '*')
1231 && !index (SDATA (pattern), '?'))
4ed46869 1232 /* PATTERN does not contain any wild cards. */
1c283e35 1233 return Qnil;
4ed46869
KH
1234
1235 if (!CONSP (Vcached_fontset_data)
d5db4077 1236 || strcmp (SDATA (pattern), CACHED_FONTSET_NAME))
4ed46869
KH
1237 {
1238 /* We must at first update the cached data. */
6cc06608 1239 unsigned char *regex, *p0, *p1;
fc1062f5 1240 int ndashes = 0, nstars = 0;
6cc06608 1241
fc1062f5
KH
1242 for (p0 = SDATA (pattern); *p0; p0++)
1243 {
1244 if (*p0 == '-')
1245 ndashes++;
a653f812 1246 else if (*p0 == '*')
fc1062f5
KH
1247 nstars++;
1248 }
1249
1250 /* If PATTERN is not full XLFD we conert "*" to ".*". Otherwise
1251 we convert "*" to "[^-]*" which is much faster in regular
1252 expression matching. */
1253 if (ndashes < 14)
6cc06608 1254 p1 = regex = (unsigned char *) alloca (SBYTES (pattern) + 2 * nstars + 1);
fc1062f5 1255 else
6cc06608 1256 p1 = regex = (unsigned char *) alloca (SBYTES (pattern) + 5 * nstars + 1);
4ed46869 1257
1c283e35 1258 *p1++ = '^';
6cc06608 1259 for (p0 = SDATA (pattern); *p0; p0++)
4ed46869 1260 {
a653f812 1261 if (*p0 == '*')
4ed46869 1262 {
fc1062f5
KH
1263 if (ndashes < 14)
1264 *p1++ = '.';
1265 else
1266 *p1++ = '[', *p1++ = '^', *p1++ = '-', *p1++ = ']';
1c283e35 1267 *p1++ = '*';
4ed46869 1268 }
1c283e35 1269 else if (*p0 == '?')
d96d677d 1270 *p1++ = '.';
1c283e35
KH
1271 else
1272 *p1++ = *p0;
4ed46869
KH
1273 }
1274 *p1++ = '$';
1275 *p1++ = 0;
1276
d5db4077 1277 Vcached_fontset_data = Fcons (build_string (SDATA (pattern)),
4ed46869
KH
1278 build_string (regex));
1279 }
1280
1281 return CACHED_FONTSET_REGEX;
1282}
1283
0d407d77 1284/* Return ID of the base fontset named NAME. If there's no such
a653f812
KH
1285 fontset, return -1. NAME_PATTERN specifies how to treat NAME as this:
1286 0: pattern containing '*' and '?' as wildcards
1287 1: regular expression
1288 2: literal fontset name
1289*/
0d407d77
KH
1290
1291int
a653f812 1292fs_query_fontset (name, name_pattern)
0d407d77 1293 Lisp_Object name;
a653f812 1294 int name_pattern;
0d407d77 1295{
1337ac77 1296 Lisp_Object tem;
0d407d77
KH
1297 int i;
1298
1299 name = Fdowncase (name);
a653f812 1300 if (name_pattern != 1)
0d407d77
KH
1301 {
1302 tem = Frassoc (name, Vfontset_alias_alist);
6bad8007
KH
1303 if (NILP (tem))
1304 tem = Fassoc (name, Vfontset_alias_alist);
0d407d77
KH
1305 if (CONSP (tem) && STRINGP (XCAR (tem)))
1306 name = XCAR (tem);
a653f812 1307 else if (name_pattern == 0)
0d407d77
KH
1308 {
1309 tem = fontset_pattern_regexp (name);
1310 if (STRINGP (tem))
1311 {
1312 name = tem;
a653f812 1313 name_pattern = 1;
0d407d77
KH
1314 }
1315 }
1316 }
1317
1318 for (i = 0; i < ASIZE (Vfontset_table); i++)
1319 {
6e1b0d8c 1320 Lisp_Object fontset, this_name;
0d407d77
KH
1321
1322 fontset = FONTSET_FROM_ID (i);
1323 if (NILP (fontset)
1324 || !BASE_FONTSET_P (fontset))
1325 continue;
1326
6e1b0d8c 1327 this_name = FONTSET_NAME (fontset);
a653f812 1328 if (name_pattern == 1
6e1b0d8c
KH
1329 ? fast_string_match (name, this_name) >= 0
1330 : !strcmp (SDATA (name), SDATA (this_name)))
0d407d77
KH
1331 return i;
1332 }
1333 return -1;
1334}
1335
1336
727fb790 1337DEFUN ("query-fontset", Fquery_fontset, Squery_fontset, 1, 2, 0,
335c5470
PJ
1338 doc: /* Return the name of a fontset that matches PATTERN.
1339The value is nil if there is no matching fontset.
1340PATTERN can contain `*' or `?' as a wildcard
1341just as X font name matching algorithm allows.
1342If REGEXPP is non-nil, PATTERN is a regular expression. */)
1343 (pattern, regexpp)
727fb790 1344 Lisp_Object pattern, regexpp;
4ed46869 1345{
0d407d77
KH
1346 Lisp_Object fontset;
1347 int id;
4ed46869
KH
1348
1349 (*check_window_system_func) ();
1350
b7826503 1351 CHECK_STRING (pattern);
4ed46869 1352
d5db4077 1353 if (SCHARS (pattern) == 0)
4ed46869
KH
1354 return Qnil;
1355
0d407d77
KH
1356 id = fs_query_fontset (pattern, !NILP (regexpp));
1357 if (id < 0)
1358 return Qnil;
4ed46869 1359
0d407d77
KH
1360 fontset = FONTSET_FROM_ID (id);
1361 return FONTSET_NAME (fontset);
4ed46869
KH
1362}
1363
06f76f0d 1364/* Return a list of base fontset names matching PATTERN on frame F. */
4ed46869
KH
1365
1366Lisp_Object
1367list_fontsets (f, pattern, size)
1368 FRAME_PTR f;
1369 Lisp_Object pattern;
1370 int size;
1371{
1337ac77 1372 Lisp_Object frame, regexp, val;
0d407d77 1373 int id;
4ed46869 1374
0d407d77 1375 XSETFRAME (frame, f);
4ed46869 1376
0d407d77 1377 regexp = fontset_pattern_regexp (pattern);
4ed46869 1378 val = Qnil;
4ed46869 1379
0d407d77
KH
1380 for (id = 0; id < ASIZE (Vfontset_table); id++)
1381 {
6e1b0d8c 1382 Lisp_Object fontset, name;
0d407d77
KH
1383
1384 fontset = FONTSET_FROM_ID (id);
1385 if (NILP (fontset)
1386 || !BASE_FONTSET_P (fontset)
1387 || !EQ (frame, FONTSET_FRAME (fontset)))
1388 continue;
6e1b0d8c 1389 name = FONTSET_NAME (fontset);
0d407d77 1390
1d5d7200 1391 if (STRINGP (regexp)
6e1b0d8c
KH
1392 ? (fast_string_match (regexp, name) < 0)
1393 : strcmp (SDATA (pattern), SDATA (name)))
0d407d77
KH
1394 continue;
1395
0d407d77 1396 val = Fcons (Fcopy_sequence (FONTSET_NAME (fontset)), val);
4ed46869
KH
1397 }
1398
1399 return val;
1400}
1401
4ed46869 1402
8f924df7 1403/* Free all realized fontsets whose base fontset is BASE. */
4ed46869 1404
06f76f0d
KH
1405static void
1406free_realized_fontsets (base)
1407 Lisp_Object base;
1408{
1409 int id;
4ed46869 1410
2f034212 1411#if 0
27e20b2f
KH
1412 /* For the moment, this doesn't work because free_realized_face
1413 doesn't remove FACE from a cache. Until we find a solution, we
1414 suppress this code, and simply use Fclear_face_cache even though
1415 that is not efficient. */
06f76f0d
KH
1416 BLOCK_INPUT;
1417 for (id = 0; id < ASIZE (Vfontset_table); id++)
4ed46869 1418 {
06f76f0d 1419 Lisp_Object this = AREF (Vfontset_table, id);
0d407d77 1420
06f76f0d 1421 if (EQ (FONTSET_BASE (this), base))
0d407d77 1422 {
06f76f0d 1423 Lisp_Object tail;
4ed46869 1424
06f76f0d
KH
1425 for (tail = FONTSET_FACE_ALIST (this); CONSP (tail);
1426 tail = XCDR (tail))
1427 {
1428 FRAME_PTR f = XFRAME (FONTSET_FRAME (this));
1429 int face_id = XINT (XCDR (XCAR (tail)));
1430 struct face *face = FACE_FROM_ID (f, face_id);
4ed46869 1431
06f76f0d
KH
1432 /* Face THIS itself is also freed by the following call. */
1433 free_realized_face (f, face);
1434 }
1435 }
0d407d77 1436 }
06f76f0d 1437 UNBLOCK_INPUT;
27e20b2f 1438#else /* not 0 */
2f034212
KH
1439 /* But, we don't have to call Fclear_face_cache if no fontset has
1440 been realized from BASE. */
1441 for (id = 0; id < ASIZE (Vfontset_table); id++)
1442 {
1443 Lisp_Object this = AREF (Vfontset_table, id);
1444
1445 if (EQ (FONTSET_BASE (this), base))
1446 {
1447 Fclear_face_cache (Qt);
1448 break;
1449 }
1450 }
27e20b2f 1451#endif /* not 0 */
0d407d77 1452}
4ed46869 1453
4ed46869 1454
0d407d77
KH
1455/* Check validity of NAME as a fontset name and return the
1456 corresponding fontset. If not valid, signal an error.
1457 If NAME is t, return Vdefault_fontset. */
1458
1459static Lisp_Object
1460check_fontset_name (name)
1461 Lisp_Object name;
1462{
1463 int id;
1464
1465 if (EQ (name, Qt))
1466 return Vdefault_fontset;
4ed46869 1467
b7826503 1468 CHECK_STRING (name);
a653f812
KH
1469 /* First try NAME as literal. */
1470 id = fs_query_fontset (name, 2);
1471 if (id < 0)
1472 /* For backward compatibility, try again NAME as pattern. */
1473 id = fs_query_fontset (name, 0);
0d407d77 1474 if (id < 0)
d5db4077 1475 error ("Fontset `%s' does not exist", SDATA (name));
0d407d77
KH
1476 return FONTSET_FROM_ID (id);
1477}
4ed46869 1478
1d5d7200
KH
1479static void
1480accumulate_script_ranges (arg, range, val)
1481 Lisp_Object arg, range, val;
1482{
1483 if (EQ (XCAR (arg), val))
1484 {
1485 if (CONSP (range))
1486 XSETCDR (arg, Fcons (Fcons (XCAR (range), XCDR (range)), XCDR (arg)));
1487 else
1488 XSETCDR (arg, Fcons (Fcons (range, range), XCDR (arg)));
1489 }
1490}
1491
1492
d6aaac9e
KH
1493/* Return an ASCII font name generated from fontset name NAME and
1494 ASCII font specification ASCII_SPEC. NAME is a string conforming
1495 to XLFD. ASCII_SPEC is a vector:
1496 [FAMILY WEIGHT SLANT SWIDTH ADSTYLE REGISTRY]. */
1497
1498static INLINE Lisp_Object
1499generate_ascii_font_name (name, ascii_spec)
1500 Lisp_Object name, ascii_spec;
1501{
1502 Lisp_Object vec;
1503 int i;
1504
1505 vec = split_font_name_into_vector (name);
1506 for (i = FONT_SPEC_FAMILY_INDEX; i <= FONT_SPEC_ADSTYLE_INDEX; i++)
1507 if (! NILP (AREF (ascii_spec, i)))
1508 ASET (vec, 1 + i, AREF (ascii_spec, i));
1509 if (! NILP (AREF (ascii_spec, FONT_SPEC_REGISTRY_INDEX)))
1510 ASET (vec, 12, AREF (ascii_spec, FONT_SPEC_REGISTRY_INDEX));
1511 return build_font_name_from_vector (vec);
1512}
1513
fb78e2ed
KH
1514/* Variables referred in set_fontset_font. They are set before
1515 map_charset_chars is called in Fset_fontset_font. */
1516static Lisp_Object font_def_arg, add_arg;
1517static int from_arg, to_arg;
1518
1519/* Callback function for map_charset_chars in Fset_fontset_font. In
1520 FONTSET, set font_def_arg in a fashion specified by add_arg for
1521 characters in RANGE while ignoring the range between from_arg and
1522 to_arg. */
1523
2449d4d0 1524static void
fb78e2ed
KH
1525set_fontset_font (fontset, range)
1526 Lisp_Object fontset, range;
2449d4d0 1527{
fb78e2ed
KH
1528 if (from_arg < to_arg)
1529 {
1530 int from = XINT (XCAR (range)), to = XINT (XCDR (range));
2449d4d0 1531
fb78e2ed
KH
1532 if (from < from_arg)
1533 {
1534 if (to > to_arg)
1535 {
1536 Lisp_Object range2;
1537
1538 range2 = Fcons (make_number (to_arg), XCDR (range));
1539 FONTSET_ADD (fontset, range, font_def_arg, add_arg);
1540 to = to_arg;
1541 }
1542 if (to > from_arg)
1543 range = Fcons (XCAR (range), make_number (from_arg));
1544 }
1545 else if (to <= to_arg)
1546 return;
1547 else
1548 {
1549 if (from < to_arg)
1550 range = Fcons (make_number (to_arg), XCDR (range));
1551 }
1552 }
1553 FONTSET_ADD (fontset, range, font_def_arg, add_arg);
2449d4d0
KH
1554}
1555
d6aaac9e 1556
1d5d7200 1557DEFUN ("set-fontset-font", Fset_fontset_font, Sset_fontset_font, 3, 5, 0,
8f924df7 1558 doc: /*
eb36588a 1559Modify fontset NAME to use FONT-SPEC for TARGET characters.
335c5470 1560
eb36588a
KH
1561TARGET may be a cons; (FROM . TO), where FROM and TO are characters.
1562In that case, use FONT-SPEC for all characters in the range FROM and
1563TO (inclusive).
06f76f0d 1564
eb36588a
KH
1565TARGET may be a script name symbol. In that case, use FONT-SPEC for
1566all characters that belong to the script.
06f76f0d 1567
eb36588a 1568TARGET may be a charset. In that case, use FONT-SPEC for all
95318a38 1569characters in the charset.
1d5d7200 1570
eb36588a
KH
1571TARGET may be nil. In that case, use FONT-SPEC for any characters for
1572that no FONT-SPEC is specified.
1573
0fdf26e6 1574FONT-SPEC may one of these:
3dcd48dd 1575 * A cons (FAMILY . REGISTRY), where FAMILY is a font family name and
0fdf26e6
KH
1576 REGISTRY is a font registry name. FAMILY may contains foundry
1577 name, and REGISTRY may contains encoding name.
00c4da0f 1578 * A font name string.
1d5d7200
KH
1579
1580Optional 4th argument FRAME, if non-nil, is a frame. This argument is
1581kept for backward compatibility and has no meaning.
1582
1583Optional 5th argument ADD, if non-nil, specifies how to add FONT-SPEC
eb36588a 1584to the font specifications for TARGET previously set. If it is
1d5d7200
KH
1585`prepend', FONT-SPEC is prepended. If it is `append', FONT-SPEC is
1586appended. By default, FONT-SPEC overrides the previous settings. */)
eb36588a
KH
1587 (name, target, font_spec, frame, add)
1588 Lisp_Object name, target, font_spec, frame, add;
0d407d77 1589{
06f76f0d 1590 Lisp_Object fontset;
9683749a 1591 Lisp_Object font_def, registry, family;
00c4da0f 1592 Lisp_Object encoding, repertory;
1d5d7200 1593 Lisp_Object range_list;
fb78e2ed 1594 struct charset *charset = NULL;
0d407d77
KH
1595
1596 fontset = check_fontset_name (name);
1597
1d5d7200
KH
1598 /* The arg FRAME is kept for backward compatibility. We only check
1599 the validity. */
1600 if (!NILP (frame))
1601 CHECK_LIVE_FRAME (frame);
1602
06f76f0d 1603 if (VECTORP (font_spec))
0d407d77 1604 {
0fdf26e6
KH
1605 /* FONT_SPEC should have this form:
1606 [ FAMILY WEIGHT SLANT WIDTH ADSTYLE REGISTRY ]
1607 This is a feature not yet documented because WEIGHT thru
1608 ADSTYLE are ignored for the moment. */
1d5d7200
KH
1609 int j;
1610
d6aaac9e
KH
1611 if (ASIZE (font_spec) != FONT_SPEC_MAX_INDEX)
1612 args_out_of_range (make_number (FONT_SPEC_MAX_INDEX),
1d5d7200 1613 make_number (ASIZE (font_spec)));
06f76f0d
KH
1614
1615 font_spec = Fcopy_sequence (font_spec);
d6aaac9e 1616 for (j = 0; j < FONT_SPEC_MAX_INDEX - 1; j++)
1d5d7200
KH
1617 if (! NILP (AREF (font_spec, j)))
1618 {
1619 CHECK_STRING (AREF (font_spec, j));
1620 ASET (font_spec, j, Fdowncase (AREF (font_spec, j)));
1621 }
d19b3ee7 1622 family = AREF (font_spec, FONT_SPEC_FAMILY_INDEX);
1d5d7200 1623 /* REGISTRY should not be omitted. */
d6aaac9e 1624 CHECK_STRING (AREF (font_spec, FONT_SPEC_REGISTRY_INDEX));
d19b3ee7 1625 registry = AREF (font_spec, FONT_SPEC_REGISTRY_INDEX);
0d407d77 1626 }
06f76f0d 1627 else if (CONSP (font_spec))
0890801b 1628 {
06f76f0d
KH
1629 family = XCAR (font_spec);
1630 registry = XCDR (font_spec);
1d5d7200
KH
1631
1632 if (! NILP (family))
06f76f0d
KH
1633 {
1634 CHECK_STRING (family);
1d5d7200 1635 family = Fdowncase (family);
06f76f0d
KH
1636 }
1637 CHECK_STRING (registry);
1d5d7200 1638 registry = Fdowncase (registry);
d6aaac9e
KH
1639 font_spec = Fmake_vector (make_number (FONT_SPEC_MAX_INDEX), Qnil);
1640 ASET (font_spec, FONT_SPEC_FAMILY_INDEX, family);
1641 ASET (font_spec, FONT_SPEC_REGISTRY_INDEX, registry);
0890801b 1642 }
0d407d77 1643 else
4ed46869 1644 {
1d5d7200
KH
1645 CHECK_STRING (font_spec);
1646 font_spec = Fdowncase (font_spec);
0d407d77 1647 }
1d5d7200
KH
1648
1649 if (STRINGP (font_spec))
71c54d6f 1650 encoding = find_font_encoding (font_spec);
0d407d77 1651 else
9683749a 1652 encoding = find_font_encoding (concat2 (family, registry));
8aa07a8d
KH
1653 if (NILP (encoding))
1654 encoding = Qascii;
1655
1d5d7200 1656 if (SYMBOLP (encoding))
57e13af9
KH
1657 {
1658 CHECK_CHARSET (encoding);
1659 encoding = repertory = CHARSET_SYMBOL_ID (encoding);
1660 }
1d5d7200 1661 else
0d407d77 1662 {
1d5d7200 1663 repertory = XCDR (encoding);
57e13af9
KH
1664 encoding = XCAR (encoding);
1665 CHECK_CHARSET (encoding);
1666 encoding = CHARSET_SYMBOL_ID (encoding);
1667 if (! NILP (repertory) && SYMBOLP (repertory))
1668 {
1669 CHECK_CHARSET (repertory);
1670 repertory = CHARSET_SYMBOL_ID (repertory);
1671 }
0d407d77 1672 }
1d5d7200
KH
1673 font_def = Fmake_vector (make_number (3), font_spec);
1674 ASET (font_def, 1, encoding);
1675 ASET (font_def, 2, repertory);
4ed46869 1676
eb36588a
KH
1677 if (CHARACTERP (target))
1678 range_list = Fcons (Fcons (target, target), Qnil);
1679 else if (CONSP (target))
0d407d77 1680 {
06f76f0d
KH
1681 Lisp_Object from, to;
1682
eb36588a
KH
1683 from = Fcar (target);
1684 to = Fcdr (target);
06f76f0d
KH
1685 CHECK_CHARACTER (from);
1686 CHECK_CHARACTER (to);
eb36588a 1687 range_list = Fcons (target, Qnil);
4ed46869 1688 }
eb36588a 1689 else if (SYMBOLP (target) && !NILP (target))
8a9be3ac 1690 {
1d5d7200
KH
1691 Lisp_Object script_list;
1692 Lisp_Object val;
0d407d77 1693
1d5d7200
KH
1694 range_list = Qnil;
1695 script_list = XCHAR_TABLE (Vchar_script_table)->extras[0];
eb36588a 1696 if (! NILP (Fmemq (target, script_list)))
afe93d01 1697 {
eb36588a 1698 val = Fcons (target, Qnil);
1d5d7200 1699 map_char_table (accumulate_script_ranges, Qnil, Vchar_script_table,
8f924df7
KH
1700 val);
1701 range_list = XCDR (val);
c3fb88cc
KH
1702 if (EQ (target, Qlatin))
1703 {
1704 if (VECTORP (font_spec))
1705 val = generate_ascii_font_name (FONTSET_NAME (fontset),
1706 font_spec);
1707 else
1708 val = font_spec;
1709 FONTSET_ASCII (fontset) = val;
1710 }
afe93d01 1711 }
fb78e2ed 1712 if (CHARSETP (target))
afe93d01 1713 {
eb36588a 1714 if (EQ (target, Qascii))
862aa7f9 1715 {
d6aaac9e 1716 if (VECTORP (font_spec))
862aa7f9
KH
1717 font_spec = generate_ascii_font_name (FONTSET_NAME (fontset),
1718 font_spec);
1719 FONTSET_ASCII (fontset) = font_spec;
2449d4d0
KH
1720 range_list = Fcons (Fcons (make_number (0), make_number (127)),
1721 Qnil);
1722 }
1723 else
1724 {
fb78e2ed 1725 CHECK_CHARSET_GET_CHARSET (target, charset);
862aa7f9 1726 }
afe93d01 1727 }
fb78e2ed 1728 else if (NILP (range_list))
1d5d7200 1729 error ("Invalid script or charset name: %s",
eb36588a 1730 SDATA (SYMBOL_NAME (target)));
8a9be3ac 1731 }
eb36588a
KH
1732 else if (NILP (target))
1733 range_list = Fcons (Qnil, Qnil);
1734 else
1735 error ("Invalid target for setting a font");
0d407d77 1736
fb78e2ed
KH
1737
1738 if (charset)
1739 {
1740 font_def_arg = font_def;
1741 add_arg = add;
1742 if (NILP (range_list))
1743 from_arg = to_arg = 0;
1744 else
1745 from_arg = XINT (XCAR (XCAR (range_list))),
1746 to_arg = XINT (XCDR (XCAR (range_list)));
1747
1748 map_charset_chars (set_fontset_font, Qnil, fontset, charset,
1749 CHARSET_MIN_CODE (charset),
1750 CHARSET_MAX_CODE (charset));
1751 }
1d5d7200
KH
1752 for (; CONSP (range_list); range_list = XCDR (range_list))
1753 FONTSET_ADD (fontset, XCAR (range_list), font_def, add);
4ed46869 1754
06f76f0d
KH
1755 /* Free all realized fontsets whose base is FONTSET. This way, the
1756 specified character(s) are surely redisplayed by a correct
1757 font. */
1758 free_realized_fontsets (fontset);
4ed46869 1759
4ed46869
KH
1760 return Qnil;
1761}
1762
06f76f0d
KH
1763
1764DEFUN ("new-fontset", Fnew_fontset, Snew_fontset, 2, 2, 0,
1765 doc: /* Create a new fontset NAME from font information in FONTLIST.
1766
1d5d7200 1767FONTLIST is an alist of scripts vs the corresponding font specification list.
d6aaac9e
KH
1768Each element of FONTLIST has the form (SCRIPT FONT-SPEC ...), where a
1769character of SCRIPT is displayed by a font that matches one of
1770FONT-SPEC.
06f76f0d 1771
d6aaac9e
KH
1772SCRIPT is a symbol that appears in the first extra slot of the
1773char-table `char-script-table'.
06f76f0d 1774
1d5d7200
KH
1775FONT-SPEC is a vector, a cons, or a string. See the documentation of
1776`set-fontset-font' for the meaning. */)
06f76f0d
KH
1777 (name, fontlist)
1778 Lisp_Object name, fontlist;
1779{
1d5d7200
KH
1780 Lisp_Object fontset;
1781 Lisp_Object val;
1782 int id;
06f76f0d
KH
1783
1784 CHECK_STRING (name);
1785 CHECK_LIST (fontlist);
1786
1d5d7200
KH
1787 id = fs_query_fontset (name, 0);
1788 if (id < 0)
0d407d77 1789 {
d6aaac9e
KH
1790 name = Fdowncase (name);
1791 val = split_font_name_into_vector (name);
df1e3c95 1792 if (NILP (val) || NILP (AREF (val, 12)) || NILP (AREF (val, 13)))
d6aaac9e 1793 error ("Fontset name must be in XLFD format");
8f924df7 1794 if (strcmp (SDATA (AREF (val, 12)), "fontset"))
d6aaac9e
KH
1795 error ("Registry field of fontset name must be \"fontset\"");
1796 Vfontset_alias_alist
1797 = Fcons (Fcons (name,
1798 concat2 (concat2 (AREF (val, 12), build_string ("-")),
1799 AREF (val, 13))),
1800 Vfontset_alias_alist);
1801 ASET (val, 12, build_string ("iso8859-1"));
1802 fontset = make_fontset (Qnil, name, Qnil);
1803 FONTSET_ASCII (fontset) = build_font_name_from_vector (val);
1804 }
1d5d7200
KH
1805 else
1806 {
1807 fontset = FONTSET_FROM_ID (id);;
1808 free_realized_fontsets (fontset);
1809 Fset_char_table_range (fontset, Qt, Qnil);
0d407d77 1810 }
4ed46869 1811
1d5d7200
KH
1812 for (; ! NILP (fontlist); fontlist = Fcdr (fontlist))
1813 {
1814 Lisp_Object elt, script;
1815
1816 elt = Fcar (fontlist);
1817 script = Fcar (elt);
cc36ddbf
KH
1818 elt = Fcdr (elt);
1819 if (CONSP (elt) && (NILP (XCDR (elt)) || CONSP (XCDR (elt))))
1820 for (; CONSP (elt); elt = XCDR (elt))
1821 Fset_fontset_font (name, script, XCAR (elt), Qnil, Qappend);
1822 else
1823 Fset_fontset_font (name, script, elt, Qnil, Qappend);
1d5d7200 1824 }
06f76f0d
KH
1825 return name;
1826}
1827
1828
452a78e0
KH
1829/* Alist of automatically created fontsets. Each element is a cons
1830 (FONTNAME . FONTSET-ID). */
1831static Lisp_Object auto_fontset_alist;
d6aaac9e
KH
1832
1833int
1834new_fontset_from_font_name (Lisp_Object fontname)
1835{
452a78e0 1836 Lisp_Object val;
d6aaac9e
KH
1837 Lisp_Object name;
1838 Lisp_Object vec;
452a78e0 1839 int id;
d6aaac9e
KH
1840
1841 fontname = Fdowncase (fontname);
452a78e0
KH
1842 val = Fassoc (fontname, auto_fontset_alist);
1843 if (CONSP (val))
1844 return XINT (XCDR (val));
1845
d6aaac9e
KH
1846 vec = split_font_name_into_vector (fontname);
1847 if ( NILP (vec))
1848 vec = Fmake_vector (make_number (14), build_string (""));
1849 ASET (vec, 12, build_string ("fontset"));
452a78e0 1850 if (NILP (auto_fontset_alist))
d6aaac9e
KH
1851 {
1852 ASET (vec, 13, build_string ("startup"));
1853 name = build_font_name_from_vector (vec);
d6aaac9e
KH
1854 }
1855 else
1856 {
1857 char temp[20];
e1a14cdc 1858 int len = XINT (Flength (auto_fontset_alist));
d6aaac9e 1859
452a78e0
KH
1860 sprintf (temp, "auto%d", len);
1861 ASET (vec, 13, build_string (temp));
1862 name = build_font_name_from_vector (vec);
d6aaac9e 1863 }
fb78e2ed
KH
1864 name = Fnew_fontset (name, list2 (list2 (Qascii, fontname),
1865 list2 (Fcons (make_number (0),
2ec7fd70 1866 make_number (MAX_CHAR)),
fb78e2ed 1867 fontname)));
452a78e0
KH
1868 id = fs_query_fontset (name, 0);
1869 auto_fontset_alist
1870 = Fcons (Fcons (fontname, make_number (id)), auto_fontset_alist);
1871 return id;
4ed46869
KH
1872}
1873
8aa07a8d
KH
1874#ifdef USE_FONT_BACKEND
1875int
03ef560c 1876new_fontset_from_font (font_object)
8aa07a8d
KH
1877 Lisp_Object font_object;
1878{
03ef560c
KH
1879 Lisp_Object font_name = font_get_name (font_object);
1880 Lisp_Object font_spec = font_get_spec (font_object);
1c82b4b3 1881 Lisp_Object fontset_spec, short_name, name, fontset;
8aa07a8d 1882
03ef560c
KH
1883 if (NILP (auto_fontset_alist))
1884 short_name = build_string ("fontset-startup");
1885 else
1886 {
1887 char temp[32];
1888 int len = XINT (Flength (auto_fontset_alist));
8aa07a8d 1889
03ef560c
KH
1890 sprintf (temp, "fontset-auto%d", len);
1891 short_name = build_string (temp);
1892 }
1c82b4b3
KH
1893 fontset_spec = Fcopy_sequence (font_spec);
1894 ASET (fontset_spec, FONT_REGISTRY_INDEX, short_name);
1895 name = Ffont_xlfd_name (fontset_spec);
03ef560c
KH
1896 if (NILP (name))
1897 {
1898 int i;
1899
1900 for (i = 0; i < FONT_SIZE_INDEX; i++)
1901 if ((i != FONT_FAMILY_INDEX) && (i != FONT_REGISTRY_INDEX))
1c82b4b3
KH
1902 ASET (fontset_spec, i, Qnil);
1903 name = Ffont_xlfd_name (fontset_spec);
03ef560c
KH
1904 if (NILP (name))
1905 abort ();
1906 }
1907 fontset = make_fontset (Qnil, name, Qnil);
1908 FONTSET_ASCII (fontset) = font_name;
1c82b4b3
KH
1909 font_spec = Fcons (SYMBOL_NAME (AREF (font_spec, FONT_FAMILY_INDEX)),
1910 SYMBOL_NAME (AREF (font_spec, FONT_REGISTRY_INDEX)));
1911 Fset_fontset_font (name, Qlatin, font_spec, Qnil, Qnil);
1912 Fset_fontset_font (name, Qnil, font_spec, Qnil, Qnil);
03ef560c 1913 return XINT (FONTSET_ID (fontset));
8aa07a8d
KH
1914}
1915
1916struct font *
1917fontset_ascii_font (f, id)
1918 FRAME_PTR f;
1919 int id;
1920{
1921 Lisp_Object fontset = FONTSET_FROM_ID (id);
1922 Lisp_Object ascii_slot = FONTSET_ASCII (fontset);
1923 Lisp_Object val, font_object;
1924
1925 if (CONSP (ascii_slot))
1926 {
1927 Lisp_Object ascii_font_name = XCAR (ascii_slot);
1928
1929 font_object = Qnil;
1930 for (val = XCDR (ascii_slot); ! NILP (val); val = XCDR (val))
1931 {
1932 Lisp_Object frame = font_get_frame (XCAR (val));
1933
1934 if (NILP (frame) || XFRAME (frame) == f)
1935 {
1936 font_object = XCAR (val);
1937 if (XSAVE_VALUE (font_object)->integer == 0)
1938 {
1939 font_object = font_open_by_name (f, SDATA (ascii_font_name));
1940 XSETCAR (val, font_object);
1941 }
1942 break;
1943 }
1944 }
1945 if (NILP (font_object))
1946 {
1947 font_object = font_open_by_name (f, SDATA (ascii_font_name));
1948 XSETCDR (ascii_slot, Fcons (font_object, XCDR (ascii_slot)));
1949 }
1950 }
1951 else
1952 {
1953 font_object = font_open_by_name (f, SDATA (ascii_slot));
1954 FONTSET_ASCII (fontset) = Fcons (ascii_slot, Fcons (font_object, Qnil));
1955 }
02dacbbc
KH
1956 if (NILP (font_object))
1957 return NULL;
8aa07a8d
KH
1958 return XSAVE_VALUE (font_object)->pointer;
1959}
1960
1961#endif /* USE_FONT_BACKEND */
d6aaac9e 1962
4ed46869 1963DEFUN ("font-info", Ffont_info, Sfont_info, 1, 2, 0,
335c5470
PJ
1964 doc: /* Return information about a font named NAME on frame FRAME.
1965If FRAME is omitted or nil, use the selected frame.
1966The returned value is a vector of OPENED-NAME, FULL-NAME, CHARSET, SIZE,
1967 HEIGHT, BASELINE-OFFSET, RELATIVE-COMPOSE, and DEFAULT-ASCENT,
1968where
1969 OPENED-NAME is the name used for opening the font,
1970 FULL-NAME is the full name of the font,
1971 SIZE is the maximum bound width of the font,
1972 HEIGHT is the height of the font,
1973 BASELINE-OFFSET is the upward offset pixels from ASCII baseline,
1974 RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling
1975 how to compose characters.
1976If the named font is not yet loaded, return nil. */)
1977 (name, frame)
4ed46869
KH
1978 Lisp_Object name, frame;
1979{
1980 FRAME_PTR f;
1981 struct font_info *fontp;
1982 Lisp_Object info;
8aa07a8d 1983 Lisp_Object font_object;
4ed46869
KH
1984
1985 (*check_window_system_func) ();
1986
b7826503 1987 CHECK_STRING (name);
0d407d77 1988 name = Fdowncase (name);
4ed46869 1989 if (NILP (frame))
18f39d0e 1990 frame = selected_frame;
b7826503 1991 CHECK_LIVE_FRAME (frame);
18f39d0e 1992 f = XFRAME (frame);
4ed46869
KH
1993
1994 if (!query_font_func)
1995 error ("Font query function is not supported");
1996
8aa07a8d
KH
1997#ifdef USE_FONT_BACKEND
1998 if (enable_font_backend)
1999 {
2000 font_object = font_open_by_name (f, SDATA (name));
2001 if (NILP (font_object))
2002 fontp = NULL;
2003 else
2004 fontp = (struct font_info *) XSAVE_VALUE (font_object)->pointer;
2005 }
2006 else
2007#endif /* USE_FONT_BACKEND */
d5db4077 2008 fontp = (*query_font_func) (f, SDATA (name));
4ed46869
KH
2009 if (!fontp)
2010 return Qnil;
2011
0d407d77 2012 info = Fmake_vector (make_number (7), Qnil);
4ed46869
KH
2013
2014 XVECTOR (info)->contents[0] = build_string (fontp->name);
2015 XVECTOR (info)->contents[1] = build_string (fontp->full_name);
0d407d77
KH
2016 XVECTOR (info)->contents[2] = make_number (fontp->size);
2017 XVECTOR (info)->contents[3] = make_number (fontp->height);
2018 XVECTOR (info)->contents[4] = make_number (fontp->baseline_offset);
2019 XVECTOR (info)->contents[5] = make_number (fontp->relative_compose);
2020 XVECTOR (info)->contents[6] = make_number (fontp->default_ascent);
4ed46869 2021
8aa07a8d
KH
2022#ifdef USE_FONT_BACKEND
2023 if (! NILP (font_object))
2024 font_close_object (f, font_object);
2025#endif /* USE_FONT_BACKEND */
4ed46869
KH
2026 return info;
2027}
2028
1ff005e1 2029
92c15c34
KH
2030/* Return a cons (FONT-NAME . GLYPH-CODE).
2031 FONT-NAME is the font name for the character at POSITION in the current
1ff005e1 2032 buffer. This is computed from all the text properties and overlays
cf14fd6e
KH
2033 that apply to POSITION. POSTION may be nil, in which case,
2034 FONT-NAME is the font name for display the character CH with the
2035 default face.
2036
92c15c34
KH
2037 GLYPH-CODE is the glyph code in the font to use for the character.
2038
2039 If the 2nd optional arg CH is non-nil, it is a character to check
2040 the font instead of the character at POSITION.
2041
2042 It returns nil in the following cases:
1ff005e1
KH
2043
2044 (1) The window system doesn't have a font for the character (thus
2045 it is displayed by an empty box).
2046
2047 (2) The character code is invalid.
2048
cf14fd6e
KH
2049 (3) If POSITION is not nil, and the current buffer is not displayed
2050 in any window.
1ff005e1
KH
2051
2052 In addition, the returned font name may not take into account of
2053 such redisplay engine hooks as what used in jit-lock-mode if
2054 POSITION is currently not visible. */
2055
2056
92c15c34 2057DEFUN ("internal-char-font", Finternal_char_font, Sinternal_char_font, 1, 2, 0,
335c5470 2058 doc: /* For internal use only. */)
92c15c34
KH
2059 (position, ch)
2060 Lisp_Object position, ch;
1ff005e1
KH
2061{
2062 int pos, pos_byte, dummy;
2063 int face_id;
2064 int c;
1ff005e1
KH
2065 struct frame *f;
2066 struct face *face;
7e1a1cd9 2067 Lisp_Object charset, rfont_def;
f0be8ea0 2068 int cs_id;
1ff005e1 2069
cf14fd6e 2070 if (NILP (position))
92c15c34
KH
2071 {
2072 CHECK_CHARACTER (ch);
2073 c = XINT (ch);
cf14fd6e
KH
2074 f = XFRAME (selected_frame);
2075 face_id = DEFAULT_FACE_ID;
327719ee 2076 pos = -1;
f0be8ea0 2077 cs_id = -1;
cf14fd6e
KH
2078 }
2079 else
2080 {
2f80c0a2 2081 Lisp_Object window, charset;
cf14fd6e
KH
2082 struct window *w;
2083
2084 CHECK_NUMBER_COERCE_MARKER (position);
2085 pos = XINT (position);
2086 if (pos < BEGV || pos >= ZV)
2087 args_out_of_range_3 (position, make_number (BEGV), make_number (ZV));
2088 pos_byte = CHAR_TO_BYTE (pos);
2089 if (NILP (ch))
2090 c = FETCH_CHAR (pos_byte);
2091 else
2092 {
2093 CHECK_NATNUM (ch);
2094 c = XINT (ch);
2095 }
2096 window = Fget_buffer_window (Fcurrent_buffer (), Qnil);
2097 if (NILP (window))
2098 return Qnil;
2099 w = XWINDOW (window);
2100 f = XFRAME (w->frame);
2101 face_id = face_at_buffer_position (w, pos, -1, -1, &dummy, pos + 100, 0);
2f80c0a2
KH
2102 charset = Fget_char_property (position, Qcharset, Qnil);
2103 if (CHARSETP (charset))
f0be8ea0 2104 cs_id = XINT (CHARSET_SYMBOL_ID (charset));
2f80c0a2 2105 else
f0be8ea0 2106 cs_id = -1;
92c15c34 2107 }
1ff005e1 2108 if (! CHAR_VALID_P (c, 0))
1ff005e1 2109 return Qnil;
327719ee 2110 face_id = FACE_FOR_CHAR (f, FACE_FROM_ID (f, face_id), c, pos, Qnil);
1ff005e1 2111 face = FACE_FROM_ID (f, face_id);
f0be8ea0 2112 rfont_def = fontset_font (FONTSET_FROM_ID (face->fontset), c, face, cs_id);
8aa07a8d
KH
2113#ifdef USE_FONT_BACKEND
2114 if (enable_font_backend)
2115 {
8aa07a8d
KH
2116 if (VECTORP (rfont_def) && ! NILP (AREF (rfont_def, 4)))
2117 {
2118 Lisp_Object font_object = AREF (rfont_def, 4);
2119 struct font *font = XSAVE_VALUE (font_object)->pointer;
2120 unsigned code = font->driver->encode_char (font, c);
a49d705d 2121 Lisp_Object fontname = font_get_name (font_object);
8aa07a8d
KH
2122
2123 if (code == FONT_INVALID_CODE)
2124 return Fcons (fontname, Qnil);
2125 if (code <= MOST_POSITIVE_FIXNUM)
2126 return Fcons (fontname, make_number (code));
2127 return Fcons (fontname, Fcons (make_number (code >> 16),
2128 make_number (code & 0xFFFF)));
2129 }
2130 return Qnil;
2131 }
2132#endif /* USE_FONT_BACKEND */
92c15c34
KH
2133 if (VECTORP (rfont_def) && STRINGP (AREF (rfont_def, 3)))
2134 {
2135 Lisp_Object font_def;
2136 struct font_info *fontp;
2137 struct charset *charset;
2138 XChar2b char2b;
2139 int code;
2140
2141 font_def = AREF (rfont_def, 2);
2142 charset = CHARSET_FROM_ID (XINT (AREF (font_def, 1)));
2143 code = ENCODE_CHAR (charset, c);
2144 if (code == CHARSET_INVALID_CODE (charset))
2145 return (Fcons (AREF (rfont_def, 3), Qnil));
2146 STORE_XCHAR2B (&char2b, ((code >> 8) & 0xFF), (code & 0xFF));
2147 fontp = (*get_font_info_func) (f, XINT (AREF (rfont_def, 1)));
c73bd236 2148 FRAME_RIF (f)->encode_char (c, &char2b, fontp, charset, NULL);
92c15c34
KH
2149 code = (XCHAR2B_BYTE1 (&char2b) << 8) | XCHAR2B_BYTE2 (&char2b);
2150 return (Fcons (AREF (rfont_def, 3), make_number (code)));
2151 }
2152 return Qnil;
1ff005e1
KH
2153}
2154
2155
1d5d7200
KH
2156DEFUN ("fontset-info", Ffontset_info, Sfontset_info, 1, 2, 0,
2157 doc: /* Return information about a fontset FONTSET on frame FRAME.
2158The value is a char-table of which elements has this form.
e2b45cf9 2159
1d5d7200 2160 ((FONT-PATTERN OPENED-FONT ...) ...)
1ff005e1 2161
1d5d7200 2162FONT-PATTERN is a vector:
1ff005e1 2163
1d5d7200 2164 [ FAMILY WEIGHT SLANT SWIDTH ADSTYLE REGISTRY ]
1ff005e1 2165
1d5d7200 2166or a string of font name pattern.
1ff005e1 2167
d6aaac9e 2168OPENED-FONT is a name of a font actually opened.
1ff005e1 2169
d6aaac9e
KH
2170The char-table has one extra slot. The value is a char-table
2171containing the information about the derived fonts from the default
2172fontset. The format is the same as abobe. */)
1d5d7200
KH
2173 (fontset, frame)
2174 Lisp_Object fontset, frame;
4ed46869
KH
2175{
2176 FRAME_PTR f;
cc7b6145
KH
2177 Lisp_Object *realized[2], fontsets[2], tables[2];
2178 Lisp_Object val, elt;
2179 int c, i, j, k;
fc8865fc 2180
4ed46869
KH
2181 (*check_window_system_func) ();
2182
1d5d7200 2183 fontset = check_fontset_name (fontset);
0d407d77 2184
4ed46869 2185 if (NILP (frame))
18f39d0e 2186 frame = selected_frame;
b7826503 2187 CHECK_LIVE_FRAME (frame);
18f39d0e 2188 f = XFRAME (frame);
4ed46869 2189
1d5d7200
KH
2190 /* Recode fontsets realized on FRAME from the base fontset FONTSET
2191 in the table `realized'. */
cc7b6145
KH
2192 realized[0] = (Lisp_Object *) alloca (sizeof (Lisp_Object)
2193 * ASIZE (Vfontset_table));
2194 for (i = j = 0; i < ASIZE (Vfontset_table); i++)
0d407d77 2195 {
1ff005e1
KH
2196 elt = FONTSET_FROM_ID (i);
2197 if (!NILP (elt)
1d5d7200
KH
2198 && EQ (FONTSET_BASE (elt), fontset)
2199 && EQ (FONTSET_FRAME (elt), frame))
cc7b6145 2200 realized[0][j++] = elt;
0d407d77 2201 }
cc7b6145 2202 realized[0][j] = Qnil;
4ed46869 2203
cc7b6145
KH
2204 realized[1] = (Lisp_Object *) alloca (sizeof (Lisp_Object)
2205 * ASIZE (Vfontset_table));
2206 for (i = j = 0; ! NILP (realized[0][i]); i++)
2207 {
2208 elt = FONTSET_DEFAULT (realized[0][i]);
2209 if (! NILP (elt))
2210 realized[1][j++] = elt;
2211 }
2212 realized[1][j] = Qnil;
2213
2214 tables[0] = Fmake_char_table (Qfontset_info, Qnil);
2215 tables[1] = Fmake_char_table (Qnil, Qnil);
2216 XCHAR_TABLE (tables[0])->extras[0] = tables[1];
2217 fontsets[0] = fontset;
2218 fontsets[1] = Vdefault_fontset;
e2b45cf9 2219
1d5d7200
KH
2220 /* Accumulate information of the fontset in TABLE. The format of
2221 each element is ((FONT-SPEC OPENED-FONT ...) ...). */
cc7b6145 2222 for (k = 0; k <= 1; k++)
0d407d77 2223 {
cc7b6145 2224 for (c = 0; c <= MAX_CHAR; )
d6aaac9e
KH
2225 {
2226 int from, to;
0d407d77 2227
cc7b6145
KH
2228 if (c <= MAX_5_BYTE_CHAR)
2229 {
2230 val = char_table_ref_and_range (fontsets[k], c, &from, &to);
2231 if (to > MAX_5_BYTE_CHAR)
2232 to = MAX_5_BYTE_CHAR;
2233 }
2234 else
2235 {
2236 val = FONTSET_FALLBACK (fontsets[k]);
2237 to = MAX_CHAR;
2238 }
d6aaac9e 2239 if (VECTORP (val))
0d407d77 2240 {
d6aaac9e
KH
2241 Lisp_Object alist;
2242
2243 /* At first, set ALIST to ((FONT-SPEC) ...). */
2244 for (alist = Qnil, i = 0; i < ASIZE (val); i++)
2245 alist = Fcons (Fcons (AREF (AREF (val, i), 0), Qnil), alist);
2246 alist = Fnreverse (alist);
2247
2248 /* Then store opend font names to cdr of each elements. */
cc7b6145 2249 for (i = 0; ! NILP (realized[k][i]); i++)
1ff005e1 2250 {
cc7b6145
KH
2251 if (c <= MAX_5_BYTE_CHAR)
2252 val = FONTSET_REF (realized[k][i], c);
2253 else
2254 val = FONTSET_FALLBACK (realized[k][i]);
2255 if (! VECTORP (val))
d6aaac9e 2256 continue;
7e1a1cd9
KH
2257 /* VAL is [int int ?
2258 [FACE-ID FONT-INDEX FONT-DEF FONT-NAME] ...].
d6aaac9e 2259 If a font of an element is already opened,
7e1a1cd9 2260 FONT-NAME is the name of a opened font. */
6bad8007 2261 for (j = 3; j < ASIZE (val); j++)
7e1a1cd9 2262 if (STRINGP (AREF (AREF (val, j), 3)))
d6aaac9e
KH
2263 {
2264 Lisp_Object font_idx;
2265
2266 font_idx = AREF (AREF (val, j), 1);
2267 elt = Fassq (AREF (AREF (AREF (val, j), 2), 0), alist);
2268 if (CONSP (elt)
2269 && NILP (Fmemq (font_idx, XCDR(elt))))
2270 nconc2 (elt, Fcons (font_idx, Qnil));
2271 }
1ff005e1 2272 }
d6aaac9e
KH
2273 for (val = alist; CONSP (val); val = XCDR (val))
2274 for (elt = XCDR (XCAR (val)); CONSP (elt); elt = XCDR (elt))
1d5d7200 2275 {
d6aaac9e
KH
2276 struct font_info *font_info
2277 = (*get_font_info_func) (f, XINT (XCAR (elt)));
2278 XSETCAR (elt, build_string (font_info->full_name));
1d5d7200 2279 }
d6aaac9e
KH
2280
2281 /* Store ALIST in TBL for characters C..TO. */
cc7b6145
KH
2282 if (c <= MAX_5_BYTE_CHAR)
2283 char_table_set_range (tables[k], c, to, alist);
2284 else
2285 XCHAR_TABLE (tables[k])->defalt = alist;
0d407d77 2286 }
d6aaac9e 2287 c = to + 1;
0d407d77
KH
2288 }
2289 }
a921395d 2290
cc7b6145 2291 return tables[0];
4ed46869
KH
2292}
2293
1d5d7200 2294
0fdf26e6 2295DEFUN ("fontset-font", Ffontset_font, Sfontset_font, 2, 3, 0,
335c5470 2296 doc: /* Return a font name pattern for character CH in fontset NAME.
0fdf26e6
KH
2297If NAME is t, find a pattern in the default fontset.
2298
2299The value has the form (FAMILY . REGISTRY), where FAMILY is a font
2300family name and REGISTRY is a font registry name. This is actually
2301the first font name pattern for CH in the fontset or in the default
2302fontset.
2303
2304If the 2nd optional arg ALL is non-nil, return a list of all font name
2305patterns. */)
2306 (name, ch, all)
2307 Lisp_Object name, ch, all;
0d407d77 2308{
1337ac77 2309 int c;
0fdf26e6
KH
2310 Lisp_Object fontset, elt, list, repertory, val;
2311 int i, j;
0d407d77
KH
2312
2313 fontset = check_fontset_name (name);
2314
06f76f0d 2315 CHECK_CHARACTER (ch);
0d407d77 2316 c = XINT (ch);
0fdf26e6
KH
2317 list = Qnil;
2318 while (1)
2319 {
2320 for (i = 0, elt = FONTSET_REF (fontset, c); i < 2;
2321 i++, elt = FONTSET_FALLBACK (fontset))
2322 if (VECTORP (elt))
2323 for (j = 0; j < ASIZE (elt); j++)
2324 {
2325 val = AREF (elt, j);
2326 repertory = AREF (val, 1);
2327 if (INTEGERP (repertory))
2328 {
2329 struct charset *charset = CHARSET_FROM_ID (XINT (repertory));
2330
2331 if (! CHAR_CHARSET_P (c, charset))
2332 continue;
2333 }
2334 else if (CHAR_TABLE_P (repertory))
2335 {
2336 if (NILP (CHAR_TABLE_REF (repertory, c)))
2337 continue;
2338 }
2339 val = AREF (val, 0);
2340 val = Fcons (AREF (val, 0), AREF (val, 5));
2341 if (NILP (all))
2342 return val;
2343 list = Fcons (val, list);
2344 }
2345 if (EQ (fontset, Vdefault_fontset))
2346 break;
2347 fontset = Vdefault_fontset;
2348 }
2349 return (Fnreverse (list));
0d407d77 2350}
0d407d77
KH
2351
2352DEFUN ("fontset-list", Ffontset_list, Sfontset_list, 0, 0, 0,
335c5470
PJ
2353 doc: /* Return a list of all defined fontset names. */)
2354 ()
0d407d77
KH
2355{
2356 Lisp_Object fontset, list;
2357 int i;
2358
2359 list = Qnil;
2360 for (i = 0; i < ASIZE (Vfontset_table); i++)
2361 {
2362 fontset = FONTSET_FROM_ID (i);
2363 if (!NILP (fontset)
2364 && BASE_FONTSET_P (fontset))
2365 list = Fcons (FONTSET_NAME (fontset), list);
2366 }
1ff005e1 2367
0d407d77
KH
2368 return list;
2369}
2370
452a78e0
KH
2371
2372#ifdef FONTSET_DEBUG
2373
2374Lisp_Object
2375dump_fontset (fontset)
2376 Lisp_Object fontset;
2377{
2378 Lisp_Object vec;
2379
2380 vec = Fmake_vector (make_number (3), Qnil);
2381 ASET (vec, 0, FONTSET_ID (fontset));
2382
2383 if (BASE_FONTSET_P (fontset))
2384 {
2385 ASET (vec, 1, FONTSET_NAME (fontset));
2386 }
2387 else
2388 {
2389 Lisp_Object frame;
2390
2391 frame = FONTSET_FRAME (fontset);
2392 if (FRAMEP (frame))
2393 {
2394 FRAME_PTR f = XFRAME (frame);
2395
2396 if (FRAME_LIVE_P (f))
1c82b4b3
KH
2397 ASET (vec, 1,
2398 Fcons (FONTSET_NAME (FONTSET_BASE (fontset)), f->name));
452a78e0 2399 else
1c82b4b3
KH
2400 ASET (vec, 1,
2401 Fcons (FONTSET_NAME (FONTSET_BASE (fontset)), Qnil));
452a78e0 2402 }
eb36588a
KH
2403 if (!NILP (FONTSET_DEFAULT (fontset)))
2404 ASET (vec, 2, FONTSET_ID (FONTSET_DEFAULT (fontset)));
452a78e0
KH
2405 }
2406 return vec;
2407}
2408
2409DEFUN ("fontset-list-all", Ffontset_list_all, Sfontset_list_all, 0, 0, 0,
2410 doc: /* Return a brief summary of all fontsets for debug use. */)
2411 ()
2412{
2413 Lisp_Object val;
2414 int i;
2415
2416 for (i = 0, val = Qnil; i < ASIZE (Vfontset_table); i++)
2417 if (! NILP (AREF (Vfontset_table, i)))
2418 val = Fcons (dump_fontset (AREF (Vfontset_table, i)), val);
2419 return (Fnreverse (val));
2420}
2421#endif /* FONTSET_DEBUG */
2422
dfcf069d 2423void
4ed46869
KH
2424syms_of_fontset ()
2425{
4ed46869
KH
2426 if (!load_font_func)
2427 /* Window system initializer should have set proper functions. */
2428 abort ();
2429
1d5d7200 2430 DEFSYM (Qfontset, "fontset");
eb36588a 2431 Fput (Qfontset, Qchar_table_extra_slots, make_number (9));
d6aaac9e
KH
2432 DEFSYM (Qfontset_info, "fontset-info");
2433 Fput (Qfontset_info, Qchar_table_extra_slots, make_number (1));
4ed46869 2434
1d5d7200
KH
2435 DEFSYM (Qprepend, "prepend");
2436 DEFSYM (Qappend, "append");
c3fb88cc 2437 DEFSYM (Qlatin, "latin");
4ed46869
KH
2438
2439 Vcached_fontset_data = Qnil;
2440 staticpro (&Vcached_fontset_data);
2441
0d407d77
KH
2442 Vfontset_table = Fmake_vector (make_number (32), Qnil);
2443 staticpro (&Vfontset_table);
0d407d77
KH
2444
2445 Vdefault_fontset = Fmake_char_table (Qfontset, Qnil);
2446 staticpro (&Vdefault_fontset);
1ff005e1
KH
2447 FONTSET_ID (Vdefault_fontset) = make_number (0);
2448 FONTSET_NAME (Vdefault_fontset)
2449 = build_string ("-*-*-*-*-*-*-*-*-*-*-*-*-fontset-default");
1ff005e1
KH
2450 AREF (Vfontset_table, 0) = Vdefault_fontset;
2451 next_fontset_id = 1;
4ed46869 2452
452a78e0
KH
2453 auto_fontset_alist = Qnil;
2454 staticpro (&auto_fontset_alist);
2455
4ed46869 2456 DEFVAR_LISP ("font-encoding-alist", &Vfont_encoding_alist,
1d5d7200
KH
2457 doc: /*
2458Alist of fontname patterns vs the corresponding encoding and repertory info.
2459Each element looks like (REGEXP . (ENCODING . REPERTORY)),
2460where ENCODING is a charset or a char-table,
8f924df7 2461and REPERTORY is a charset, a char-table, or nil.
1d5d7200
KH
2462
2463ENCODING is for converting a character to a glyph code of the font.
2464If ENCODING is a charset, encoding a character by the charset gives
2465the corresponding glyph code. If ENCODING is a char-table, looking up
2466the table by a character gives the corresponding glyph code.
2467
2468REPERTORY specifies a repertory of characters supported by the font.
2469If REPERTORY is a charset, all characters beloging to the charset are
2470supported. If REPERTORY is a char-table, all characters who have a
2471non-nil value in the table are supported. It REPERTORY is nil, Emacs
2472gets the repertory information by an opened font and ENCODING. */);
4ed46869
KH
2473 Vfont_encoding_alist = Qnil;
2474
6a7e6d80 2475 DEFVAR_LISP ("use-default-ascent", &Vuse_default_ascent,
1d5d7200
KH
2476 doc: /*
2477Char table of characters whose ascent values should be ignored.
335c5470
PJ
2478If an entry for a character is non-nil, the ascent value of the glyph
2479is assumed to be what specified by _MULE_DEFAULT_ASCENT property of a font.
2480
2481This affects how a composite character which contains
2482such a character is displayed on screen. */);
2aeafb78
KH
2483 Vuse_default_ascent = Qnil;
2484
2485 DEFVAR_LISP ("ignore-relative-composition", &Vignore_relative_composition,
1d5d7200
KH
2486 doc: /*
2487Char table of characters which is not composed relatively.
335c5470
PJ
2488If an entry for a character is non-nil, a composition sequence
2489which contains that character is displayed so that
2490the glyph of that character is put without considering
2491an ascent and descent value of a previous character. */);
810abb87 2492 Vignore_relative_composition = Qnil;
6a7e6d80 2493
01d4b817 2494 DEFVAR_LISP ("alternate-fontname-alist", &Valternate_fontname_alist,
335c5470
PJ
2495 doc: /* Alist of fontname vs list of the alternate fontnames.
2496When a specified font name is not found, the corresponding
2497alternate fontnames (if any) are tried instead. */);
01d4b817 2498 Valternate_fontname_alist = Qnil;
8c83e4f9 2499
1c283e35 2500 DEFVAR_LISP ("fontset-alias-alist", &Vfontset_alias_alist,
335c5470 2501 doc: /* Alist of fontset names vs the aliases. */);
1ff005e1
KH
2502 Vfontset_alias_alist = Fcons (Fcons (FONTSET_NAME (Vdefault_fontset),
2503 build_string ("fontset-default")),
2504 Qnil);
1c283e35 2505
810abb87
KH
2506 DEFVAR_LISP ("vertical-centering-font-regexp",
2507 &Vvertical_centering_font_regexp,
335c5470
PJ
2508 doc: /* *Regexp matching font names that require vertical centering on display.
2509When a character is displayed with such fonts, the character is displayed
fc8865fc 2510at the vertical center of lines. */);
810abb87
KH
2511 Vvertical_centering_font_regexp = Qnil;
2512
21ff5ed6
KH
2513 DEFVAR_LISP ("otf-script-alist", &Votf_script_alist,
2514 doc: /* Alist of OpenType script tags vs the corresponding script names. */);
2515 Votf_script_alist = Qnil;
2516
4ed46869
KH
2517 defsubr (&Squery_fontset);
2518 defsubr (&Snew_fontset);
2519 defsubr (&Sset_fontset_font);
2520 defsubr (&Sfont_info);
1ff005e1 2521 defsubr (&Sinternal_char_font);
4ed46869 2522 defsubr (&Sfontset_info);
0d407d77
KH
2523 defsubr (&Sfontset_font);
2524 defsubr (&Sfontset_list);
452a78e0
KH
2525#ifdef FONTSET_DEBUG
2526 defsubr (&Sfontset_list_all);
2527#endif
e3400864 2528}
92c15c34
KH
2529
2530/* arch-tag: ea861585-2f5f-4e5b-9849-d04a9c3a3537
2531 (do not change this comment) */