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