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