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