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