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