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