*** empty log message ***
[bpt/emacs.git] / 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
464 font_name = choose_face_font (f, face->lface, AREF (font_def, 0), NULL);
465 if (! (font_info = fs_load_font (f, font_name, XINT (AREF (font_def, 1)))))
466 return -1;
467
468 if (NILP (AREF (font_def, 2))
469 && NILP (Fassq (make_number (font_info->font_idx),
470 FONTSET_REPERTORY (fontset))))
471 {
472 /* We must look into the font to get the correct repertory as a
473 char-table. */
474 Lisp_Object repertory;
475
476 repertory = (*get_font_repertory_func) (f, font_info);
477 FONTSET_REPERTORY (fontset)
478 = Fcons (Fcons (make_number (font_info->font_idx), repertory),
479 FONTSET_REPERTORY (fontset));
480 }
481
482 return font_info->font_idx;
483 }
484
485
486 /* Return a face ID registerd in the realized fontset FONTSET for the
487 character C. If FACE is NULL, return -1 if a face is not yet
488 set. Otherwise, realize a proper face from FACE and return it. */
489
490 static int
491 fontset_face (fontset, c, face)
492 Lisp_Object fontset;
493 int c;
494 struct face *face;
495 {
496 Lisp_Object base_fontset, elt, vec;
497 int i, from, to;
498 int font_idx;
499 FRAME_PTR f = XFRAME (FONTSET_FRAME (fontset));
500
501 base_fontset = FONTSET_BASE (fontset);
502 elt = CHAR_TABLE_REF (fontset, c);
503
504 if (EQ (elt, Qt))
505 goto try_default;
506
507 if (NILP (elt))
508 {
509 /* We have not yet decided a face for C. */
510 Lisp_Object range;
511
512 if (! face)
513 return -1;
514 elt = FONTSET_REF_AND_RANGE (base_fontset, c, from, to);
515 range = Fcons (make_number (from), make_number (to));
516 if (NILP (elt))
517 {
518 /* Record that we have no font for characters of this
519 range. */
520 FONTSET_SET (fontset, range, Qt);
521 goto try_default;
522 }
523 elt = Fcopy_sequence (elt);
524 /* Now ELT is a vector of FONT-DEFs. We at first change it to
525 FONT-VECTOR, a vector of [ nil nil FONT-DEF ]. */
526 for (i = 0; i < ASIZE (elt); i++)
527 {
528 Lisp_Object tmp;
529
530 tmp = Fmake_vector (make_number (3), Qnil);
531 ASET (tmp, 2, AREF (elt, i));
532 ASET (elt, i, tmp);
533 }
534 /* Then store (-1 . FONT-VECTOR) in the fontset. -1 is to force
535 reordering of FONT-VECTOR. */
536 elt = Fcons (make_number (-1), elt);
537 FONTSET_SET (fontset, range, elt);
538 }
539
540 if (XINT (XCAR (elt)) != charset_ordered_list_tick)
541 /* The priority of charsets is changed after we selected a face
542 for C last time. */
543 reorder_font_vector (elt);
544
545 vec = XCDR (elt);
546 /* Find the first available font in the font vector VEC. */
547 for (i = 0; i < ASIZE (vec); i++)
548 {
549 Lisp_Object font_def;
550
551 elt = AREF (vec, i);
552 /* ELT == [ FACE-ID FONT-INDEX [ FONT-SPEC ENCODING REPERTORY ] ] */
553 font_def = AREF (elt, 2);
554 if (INTEGERP (AREF (elt, 1)) && XINT (AREF (elt, 1)) < 0)
555 /* We couldn't open this font last time. */
556 continue;
557
558 if (!face && (NILP (AREF (elt, 1)) || NILP (AREF (elt, 0))))
559 /* We have not yet opened the font, or we have not yet made a
560 realized face for the font. */
561 return -1;
562
563 if (INTEGERP (AREF (font_def, 2)))
564 {
565 /* The repertory is specified by charset ID. */
566 struct charset *charset
567 = CHARSET_FROM_ID (XINT (AREF (font_def, 2)));
568
569 if (! CHAR_CHARSET_P (c, charset))
570 /* This font can't display C. */
571 continue;
572 }
573 else
574 {
575 Lisp_Object slot;
576
577 if (! INTEGERP (AREF (elt, 1)))
578 {
579 /* We have not yet opened a font matching this spec.
580 Open the best matching font now and register the
581 repertory. */
582 font_idx = load_font_get_repertory (f, face, font_def, fontset);
583 ASET (elt, 1, make_number (font_idx));
584 if (font_idx < 0)
585 /* This means that we couldn't find a font matching
586 FONT_DEF. */
587 continue;
588 }
589
590 slot = Fassq (AREF (elt, 1), FONTSET_REPERTORY (fontset));
591 if (! CONSP (slot))
592 abort ();
593 if (NILP (CHAR_TABLE_REF (XCDR (slot), c)))
594 /* This fond can't display C. */
595 continue;
596 }
597
598 /* Now we have decided to use this font spec to display C. */
599 if (INTEGERP (AREF (elt, 1)))
600 font_idx = XINT (AREF (elt, 1));
601 else
602 {
603 /* But not yet opened the best matching font. */
604 font_idx = load_font_get_repertory (f, face, font_def, fontset);
605 ASET (elt, 1, make_number (font_idx));
606 if (font_idx < 0)
607 continue;
608 }
609
610 /* Now we have the opened font. */
611 if (NILP (AREF (elt, 0)))
612 {
613 /* But not yet made a realized face that uses this font. */
614 int face_id = lookup_non_ascii_face (f, font_idx, face);
615
616 ASET (elt, 0, make_number (face_id));
617 }
618
619 /* Ok, this face can display C. */
620 return XINT (AREF (elt, 0));
621 }
622
623 try_default:
624 if (! EQ (base_fontset, Vdefault_fontset))
625 return fontset_face (FONTSET_FALLBACK (fontset), c, face);
626
627 /* We have tried all the fonts for C, but none of them can be opened
628 nor can display C. */
629 if (NILP (FONTSET_NOFONT_FACE (fontset)))
630 {
631 int face_id;
632
633 if (! face)
634 return -1;
635 face_id = lookup_non_ascii_face (f, -1, face);
636 FONTSET_NOFONT_FACE (fontset) = make_number (face_id);
637 }
638 return XINT (FONTSET_NOFONT_FACE (fontset));
639 }
640
641
642 /* Return a newly created fontset with NAME. If BASE is nil, make a
643 base fontset. Otherwise make a realized fontset whose base is
644 BASE. */
645
646 static Lisp_Object
647 make_fontset (frame, name, base)
648 Lisp_Object frame, name, base;
649 {
650 Lisp_Object fontset;
651 int size = ASIZE (Vfontset_table);
652 int id = next_fontset_id;
653
654 /* Find a free slot in Vfontset_table. Usually, next_fontset_id is
655 the next available fontset ID. So it is expected that this loop
656 terminates quickly. In addition, as the last element of
657 Vfontset_table is always nil, we don't have to check the range of
658 id. */
659 while (!NILP (AREF (Vfontset_table, id))) id++;
660
661 if (id + 1 == size)
662 {
663 /* We must grow Vfontset_table. */
664 Lisp_Object tem;
665 int i;
666
667 tem = Fmake_vector (make_number (size + 32), Qnil);
668 for (i = 0; i < size; i++)
669 AREF (tem, i) = AREF (Vfontset_table, i);
670 Vfontset_table = tem;
671 }
672
673 fontset = Fmake_char_table (Qfontset, Qnil);
674
675 FONTSET_ID (fontset) = make_number (id);
676 if (NILP (base))
677 {
678 FONTSET_NAME (fontset) = name;
679 }
680 else
681 {
682 FONTSET_NAME (fontset) = Qnil;
683 FONTSET_FRAME (fontset) = frame;
684 FONTSET_BASE (fontset) = base;
685 }
686
687 ASET (Vfontset_table, id, fontset);
688 next_fontset_id = id + 1;
689 if (! NILP (base) && ! EQ (base, Vdefault_fontset))
690 FONTSET_FALLBACK (fontset) = make_fontset (frame, Qnil, Vdefault_fontset);
691 return fontset;
692 }
693
694
695 \f
696 /********** INTERFACES TO xfaces.c, xfns.c, and dispextern.h **********/
697
698 /* Return the name of the fontset who has ID. */
699
700 Lisp_Object
701 fontset_name (id)
702 int id;
703 {
704 Lisp_Object fontset;
705
706 fontset = FONTSET_FROM_ID (id);
707 return FONTSET_NAME (fontset);
708 }
709
710
711 /* Return the ASCII font name of the fontset who has ID. */
712
713 Lisp_Object
714 fontset_ascii (id)
715 int id;
716 {
717 Lisp_Object fontset, elt;
718
719 fontset= FONTSET_FROM_ID (id);
720 elt = FONTSET_ASCII (fontset);
721 /* It is assured that ELT is always a string (i.e. fontname
722 pattern). */
723 return elt;
724 }
725
726
727 /* Free fontset of FACE defined on frame F. Called from
728 free_realized_face. */
729
730 void
731 free_face_fontset (f, face)
732 FRAME_PTR f;
733 struct face *face;
734 {
735 ASET (Vfontset_table, face->fontset, Qnil);
736 if (face->fontset < next_fontset_id)
737 next_fontset_id = face->fontset;
738 }
739
740
741 /* Return 1 iff FACE is suitable for displaying character C.
742 Otherwise return 0. Called from the macro FACE_SUITABLE_FOR_CHAR_P
743 when C is not an ASCII character. */
744
745 int
746 face_suitable_for_char_p (face, c)
747 struct face *face;
748 int c;
749 {
750 Lisp_Object fontset;
751
752 fontset = FONTSET_FROM_ID (face->fontset);
753 return (face->id == fontset_face (fontset, c, NULL));
754 }
755
756
757 /* Return ID of face suitable for displaying character C on frame F.
758 FACE must be reazlied for ASCII characters in advance. Called from
759 the macro FACE_FOR_CHAR. */
760
761 int
762 face_for_char (f, face, c)
763 FRAME_PTR f;
764 struct face *face;
765 int c;
766 {
767 Lisp_Object fontset;
768
769 if (ASCII_CHAR_P (c))
770 return face->ascii_face->id;
771
772 xassert (fontset_id_valid_p (face->fontset));
773 fontset = FONTSET_FROM_ID (face->fontset);
774 xassert (!BASE_FONTSET_P (fontset));
775 return fontset_face (fontset, c, face);
776 }
777
778
779 /* Make a realized fontset for ASCII face FACE on frame F from the
780 base fontset BASE_FONTSET_ID. If BASE_FONTSET_ID is -1, use the
781 default fontset as the base. Value is the id of the new fontset.
782 Called from realize_x_face. */
783
784 int
785 make_fontset_for_ascii_face (f, base_fontset_id, face)
786 FRAME_PTR f;
787 int base_fontset_id;
788 struct face *face;
789 {
790 Lisp_Object base_fontset, fontset, frame;
791
792 XSETFRAME (frame, f);
793 if (base_fontset_id >= 0)
794 {
795 base_fontset = FONTSET_FROM_ID (base_fontset_id);
796 if (!BASE_FONTSET_P (base_fontset))
797 base_fontset = FONTSET_BASE (base_fontset);
798 xassert (BASE_FONTSET_P (base_fontset));
799 if (! BASE_FONTSET_P (base_fontset))
800 abort ();
801 }
802 else
803 base_fontset = Vdefault_fontset;
804
805 fontset = make_fontset (frame, Qnil, base_fontset);
806 {
807 Lisp_Object elt;
808
809 elt = FONTSET_REF (base_fontset, 0);
810 elt = Fmake_vector (make_number (3), AREF (elt, 0));
811 ASET (elt, 0, make_number (face->id));
812 ASET (elt, 1, make_number (face->font_info_id));
813 elt = Fcons (make_number (charset_ordered_list_tick),
814 Fmake_vector (make_number (1), elt));
815 char_table_set_range (fontset, 0, 127, elt);
816 }
817 return XINT (FONTSET_ID (fontset));
818 }
819
820
821 #if defined(WINDOWSNT) && defined (_MSC_VER)
822 #pragma optimize("", off)
823 #endif
824
825 /* Load a font named FONTNAME on frame F. Return a pointer to the
826 struct font_info of the loaded font. If loading fails, return
827 NULL. CHARSET is an ID of charset to encode characters for this
828 font. If it is -1, find one from Vfont_encoding_alist. */
829
830 struct font_info *
831 fs_load_font (f, fontname, charset)
832 FRAME_PTR f;
833 char *fontname;
834 int charset;
835 {
836 struct font_info *fontp;
837
838 if (!fontname)
839 /* No way to get fontname. */
840 return NULL;
841
842 fontp = (*load_font_func) (f, fontname, 0);
843 if (! fontp || fontp->charset >= 0)
844 return fontp;
845
846 fontname = fontp->full_name;
847
848 if (charset < 0)
849 {
850 Lisp_Object charset_symbol;
851
852 charset_symbol = find_font_encoding (fontname);
853 if (CONSP (charset_symbol))
854 charset_symbol = XCAR (charset_symbol);
855 charset = XINT (CHARSET_SYMBOL_ID (charset_symbol));
856 }
857 fontp->charset = charset;
858 fontp->vertical_centering = 0;
859 fontp->font_encoder = NULL;
860
861 if (charset != charset_ascii)
862 {
863 fontp->vertical_centering
864 = (STRINGP (Vvertical_centering_font_regexp)
865 && (fast_c_string_match_ignore_case
866 (Vvertical_centering_font_regexp, fontname) >= 0));
867
868 if (find_ccl_program_func)
869 (*find_ccl_program_func) (fontp);
870 }
871
872 return fontp;
873 }
874
875 #if defined(WINDOWSNT) && defined (_MSC_VER)
876 #pragma optimize("", on)
877 #endif
878
879 \f
880 /* Return ENCODING or a cons of ENCODING and REPERTORY of the font
881 FONTNAME. ENCODING is a charset symbol that specifies the encoding
882 of the font. REPERTORY is a charset symbol or nil. */
883
884
885 static Lisp_Object
886 find_font_encoding (fontname)
887 char *fontname;
888 {
889 Lisp_Object tail, elt;
890
891 for (tail = Vfont_encoding_alist; CONSP (tail); tail = XCDR (tail))
892 {
893 elt = XCAR (tail);
894 if (CONSP (elt)
895 && STRINGP (XCAR (elt))
896 && fast_c_string_match_ignore_case (XCAR (elt), fontname) >= 0
897 && (SYMBOLP (XCDR (elt))
898 ? CHARSETP (XCDR (elt))
899 : CONSP (XCDR (elt)) && CHARSETP (XCAR (XCDR (elt)))))
900 return (XCDR (elt));
901 }
902 /* We don't know the encoding of this font. Let's assume Unicode
903 encoding. */
904 return Qunicode;
905 }
906
907
908 /* Cache data used by fontset_pattern_regexp. The car part is a
909 pattern string containing at least one wild card, the cdr part is
910 the corresponding regular expression. */
911 static Lisp_Object Vcached_fontset_data;
912
913 #define CACHED_FONTSET_NAME (SDATA (XCAR (Vcached_fontset_data)))
914 #define CACHED_FONTSET_REGEX (XCDR (Vcached_fontset_data))
915
916 /* If fontset name PATTERN contains any wild card, return regular
917 expression corresponding to PATTERN. */
918
919 static Lisp_Object
920 fontset_pattern_regexp (pattern)
921 Lisp_Object pattern;
922 {
923 if (!index (SDATA (pattern), '*')
924 && !index (SDATA (pattern), '?'))
925 /* PATTERN does not contain any wild cards. */
926 return Qnil;
927
928 if (!CONSP (Vcached_fontset_data)
929 || strcmp (SDATA (pattern), CACHED_FONTSET_NAME))
930 {
931 /* We must at first update the cached data. */
932 char *regex = (char *) alloca (SCHARS (pattern) * 2 + 3);
933 char *p0, *p1 = regex;
934
935 /* Convert "*" to ".*", "?" to ".". */
936 *p1++ = '^';
937 for (p0 = (char *) SDATA (pattern); *p0; p0++)
938 {
939 if (*p0 == '*')
940 {
941 *p1++ = '.';
942 *p1++ = '*';
943 }
944 else if (*p0 == '?')
945 *p1++ = '.';
946 else
947 *p1++ = *p0;
948 }
949 *p1++ = '$';
950 *p1++ = 0;
951
952 Vcached_fontset_data = Fcons (build_string (SDATA (pattern)),
953 build_string (regex));
954 }
955
956 return CACHED_FONTSET_REGEX;
957 }
958
959 /* Return ID of the base fontset named NAME. If there's no such
960 fontset, return -1. */
961
962 int
963 fs_query_fontset (name, regexpp)
964 Lisp_Object name;
965 int regexpp;
966 {
967 Lisp_Object tem;
968 int i;
969
970 name = Fdowncase (name);
971 if (!regexpp)
972 {
973 tem = Frassoc (name, Vfontset_alias_alist);
974 if (CONSP (tem) && STRINGP (XCAR (tem)))
975 name = XCAR (tem);
976 else
977 {
978 tem = fontset_pattern_regexp (name);
979 if (STRINGP (tem))
980 {
981 name = tem;
982 regexpp = 1;
983 }
984 }
985 }
986
987 for (i = 0; i < ASIZE (Vfontset_table); i++)
988 {
989 Lisp_Object fontset;
990 unsigned char *this_name;
991
992 fontset = FONTSET_FROM_ID (i);
993 if (NILP (fontset)
994 || !BASE_FONTSET_P (fontset))
995 continue;
996
997 this_name = SDATA (FONTSET_NAME (fontset));
998 if (regexpp
999 ? fast_c_string_match_ignore_case (name, this_name) >= 0
1000 : !strcmp (SDATA (name), this_name))
1001 return i;
1002 }
1003 return -1;
1004 }
1005
1006
1007 DEFUN ("query-fontset", Fquery_fontset, Squery_fontset, 1, 2, 0,
1008 doc: /* Return the name of a fontset that matches PATTERN.
1009 The value is nil if there is no matching fontset.
1010 PATTERN can contain `*' or `?' as a wildcard
1011 just as X font name matching algorithm allows.
1012 If REGEXPP is non-nil, PATTERN is a regular expression. */)
1013 (pattern, regexpp)
1014 Lisp_Object pattern, regexpp;
1015 {
1016 Lisp_Object fontset;
1017 int id;
1018
1019 (*check_window_system_func) ();
1020
1021 CHECK_STRING (pattern);
1022
1023 if (SCHARS (pattern) == 0)
1024 return Qnil;
1025
1026 id = fs_query_fontset (pattern, !NILP (regexpp));
1027 if (id < 0)
1028 return Qnil;
1029
1030 fontset = FONTSET_FROM_ID (id);
1031 return FONTSET_NAME (fontset);
1032 }
1033
1034 /* Return a list of base fontset names matching PATTERN on frame F. */
1035
1036 Lisp_Object
1037 list_fontsets (f, pattern, size)
1038 FRAME_PTR f;
1039 Lisp_Object pattern;
1040 int size;
1041 {
1042 Lisp_Object frame, regexp, val;
1043 int id;
1044
1045 XSETFRAME (frame, f);
1046
1047 regexp = fontset_pattern_regexp (pattern);
1048 val = Qnil;
1049
1050 for (id = 0; id < ASIZE (Vfontset_table); id++)
1051 {
1052 Lisp_Object fontset;
1053 unsigned char *name;
1054
1055 fontset = FONTSET_FROM_ID (id);
1056 if (NILP (fontset)
1057 || !BASE_FONTSET_P (fontset)
1058 || !EQ (frame, FONTSET_FRAME (fontset)))
1059 continue;
1060 name = SDATA (FONTSET_NAME (fontset));
1061
1062 if (STRINGP (regexp)
1063 ? (fast_c_string_match_ignore_case (regexp, name) < 0)
1064 : strcmp (SDATA (pattern), name))
1065 continue;
1066
1067 val = Fcons (Fcopy_sequence (FONTSET_NAME (fontset)), val);
1068 }
1069
1070 return val;
1071 }
1072
1073
1074 /* Free all realized fontsets whose base fontset is BASE. */
1075
1076 static void
1077 free_realized_fontsets (base)
1078 Lisp_Object base;
1079 {
1080 #if 0
1081 int id;
1082
1083 /* For the moment, this doesn't work because free_realized_face
1084 doesn't remove FACE from a cache. Until we find a solution, we
1085 suppress this code, and simply use Fclear_face_cache even though
1086 that is not efficient. */
1087 BLOCK_INPUT;
1088 for (id = 0; id < ASIZE (Vfontset_table); id++)
1089 {
1090 Lisp_Object this = AREF (Vfontset_table, id);
1091
1092 if (EQ (FONTSET_BASE (this), base))
1093 {
1094 Lisp_Object tail;
1095
1096 for (tail = FONTSET_FACE_ALIST (this); CONSP (tail);
1097 tail = XCDR (tail))
1098 {
1099 FRAME_PTR f = XFRAME (FONTSET_FRAME (this));
1100 int face_id = XINT (XCDR (XCAR (tail)));
1101 struct face *face = FACE_FROM_ID (f, face_id);
1102
1103 /* Face THIS itself is also freed by the following call. */
1104 free_realized_face (f, face);
1105 }
1106 }
1107 }
1108 UNBLOCK_INPUT;
1109 #else /* not 0 */
1110 Fclear_face_cache (Qt);
1111 #endif /* not 0 */
1112 }
1113
1114
1115 /* Check validity of NAME as a fontset name and return the
1116 corresponding fontset. If not valid, signal an error.
1117 If NAME is t, return Vdefault_fontset. */
1118
1119 static Lisp_Object
1120 check_fontset_name (name)
1121 Lisp_Object name;
1122 {
1123 int id;
1124
1125 if (EQ (name, Qt))
1126 return Vdefault_fontset;
1127
1128 CHECK_STRING (name);
1129 id = fs_query_fontset (name, 0);
1130 if (id < 0)
1131 error ("Fontset `%s' does not exist", SDATA (name));
1132 return FONTSET_FROM_ID (id);
1133 }
1134
1135 static void
1136 accumulate_script_ranges (arg, range, val)
1137 Lisp_Object arg, range, val;
1138 {
1139 if (EQ (XCAR (arg), val))
1140 {
1141 if (CONSP (range))
1142 XSETCDR (arg, Fcons (Fcons (XCAR (range), XCDR (range)), XCDR (arg)));
1143 else
1144 XSETCDR (arg, Fcons (Fcons (range, range), XCDR (arg)));
1145 }
1146 }
1147
1148
1149 /* Return an ASCII font name generated from fontset name NAME and
1150 ASCII font specification ASCII_SPEC. NAME is a string conforming
1151 to XLFD. ASCII_SPEC is a vector:
1152 [FAMILY WEIGHT SLANT SWIDTH ADSTYLE REGISTRY]. */
1153
1154 static INLINE Lisp_Object
1155 generate_ascii_font_name (name, ascii_spec)
1156 Lisp_Object name, ascii_spec;
1157 {
1158 Lisp_Object vec;
1159 int i;
1160
1161 vec = split_font_name_into_vector (name);
1162 for (i = FONT_SPEC_FAMILY_INDEX; i <= FONT_SPEC_ADSTYLE_INDEX; i++)
1163 if (! NILP (AREF (ascii_spec, i)))
1164 ASET (vec, 1 + i, AREF (ascii_spec, i));
1165 if (! NILP (AREF (ascii_spec, FONT_SPEC_REGISTRY_INDEX)))
1166 ASET (vec, 12, AREF (ascii_spec, FONT_SPEC_REGISTRY_INDEX));
1167 return build_font_name_from_vector (vec);
1168 }
1169
1170
1171 DEFUN ("set-fontset-font", Fset_fontset_font, Sset_fontset_font, 3, 5, 0,
1172 doc: /*
1173 Modify fontset NAME to use FONT-SPEC for CHARACTER.
1174
1175 CHARACTER may be a cons; (FROM . TO), where FROM and TO are
1176 characters. In that case, use FONT-SPEC for all characters in the
1177 range FROM and TO (inclusive).
1178
1179 CHARACTER may be a script name symbol. In that case, use FONT-SPEC
1180 for all characters that belong to the script.
1181
1182 CHARACTER may be a charset which has a :code-offset attribute and the
1183 attribute value is greater than the maximum Unicode character
1184 \(#x10FFFF). In that case, use FONT-SPEC for all characters in the
1185 charset.
1186
1187 FONT-SPEC may be:
1188 * A vector [ FAMILY WEIGHT SLANT WIDTH ADSTYLE REGISTRY ].
1189 See the documentation of `set-face-attribute' for the detail of
1190 these vector elements;
1191 * A cons (FAMILY . REGISTRY), where FAMILY is a font family name and
1192 REGISTRY is a font registry name;
1193 * A font name string.
1194
1195 Optional 4th argument FRAME, if non-nil, is a frame. This argument is
1196 kept for backward compatibility and has no meaning.
1197
1198 Optional 5th argument ADD, if non-nil, specifies how to add FONT-SPEC
1199 to the font specifications for RANGE previously set. If it is
1200 `prepend', FONT-SPEC is prepended. If it is `append', FONT-SPEC is
1201 appended. By default, FONT-SPEC overrides the previous settings. */)
1202 (name, character, font_spec, frame, add)
1203 Lisp_Object name, character, font_spec, frame, add;
1204 {
1205 Lisp_Object fontset;
1206 Lisp_Object font_def, registry;
1207 Lisp_Object encoding, repertory;
1208 Lisp_Object range_list;
1209
1210 fontset = check_fontset_name (name);
1211
1212 /* The arg FRAME is kept for backward compatibility. We only check
1213 the validity. */
1214 if (!NILP (frame))
1215 CHECK_LIVE_FRAME (frame);
1216
1217 if (VECTORP (font_spec))
1218 {
1219 int j;
1220
1221 if (ASIZE (font_spec) != FONT_SPEC_MAX_INDEX)
1222 args_out_of_range (make_number (FONT_SPEC_MAX_INDEX),
1223 make_number (ASIZE (font_spec)));
1224
1225 font_spec = Fcopy_sequence (font_spec);
1226 for (j = 0; j < FONT_SPEC_MAX_INDEX - 1; j++)
1227 if (! NILP (AREF (font_spec, j)))
1228 {
1229 CHECK_STRING (AREF (font_spec, j));
1230 ASET (font_spec, j, Fdowncase (AREF (font_spec, j)));
1231 }
1232 /* REGISTRY should not be omitted. */
1233 CHECK_STRING (AREF (font_spec, FONT_SPEC_REGISTRY_INDEX));
1234 registry = Fdowncase (AREF (font_spec, FONT_SPEC_REGISTRY_INDEX));
1235 ASET (font_spec, FONT_SPEC_REGISTRY_INDEX, registry);
1236
1237 }
1238 else if (CONSP (font_spec))
1239 {
1240 Lisp_Object family;
1241
1242 family = XCAR (font_spec);
1243 registry = XCDR (font_spec);
1244
1245 if (! NILP (family))
1246 {
1247 CHECK_STRING (family);
1248 family = Fdowncase (family);
1249 }
1250 CHECK_STRING (registry);
1251 registry = Fdowncase (registry);
1252 font_spec = Fmake_vector (make_number (FONT_SPEC_MAX_INDEX), Qnil);
1253 ASET (font_spec, FONT_SPEC_FAMILY_INDEX, family);
1254 ASET (font_spec, FONT_SPEC_REGISTRY_INDEX, registry);
1255 }
1256 else
1257 {
1258 CHECK_STRING (font_spec);
1259 font_spec = Fdowncase (font_spec);
1260 registry = split_font_name_into_vector (font_spec);
1261 if (NILP (registry))
1262 error ("No XLFD: %s", SDATA (font_spec));
1263 if (NILP (AREF (registry, 12))
1264 || NILP (AREF (registry, 13)))
1265 error ("Registry must be specified");
1266 registry = concat2 (concat2 (AREF (registry, 12), build_string ("-")),
1267 AREF (registry, 13));
1268 }
1269
1270 if (STRINGP (font_spec))
1271 encoding = find_font_encoding ((char *) SDATA (font_spec));
1272 else
1273 encoding = find_font_encoding ((char *) SDATA (registry));
1274 if (SYMBOLP (encoding))
1275 encoding = repertory = CHARSET_SYMBOL_ID (encoding);
1276 else
1277 {
1278 repertory = XCDR (encoding);
1279 encoding = CHARSET_SYMBOL_ID (XCAR (encoding));
1280 }
1281 font_def = Fmake_vector (make_number (3), font_spec);
1282 ASET (font_def, 1, encoding);
1283 ASET (font_def, 2, repertory);
1284
1285 if (CHARACTERP (character))
1286 range_list = Fcons (Fcons (character, character), Qnil);
1287 else if (CONSP (character))
1288 {
1289 Lisp_Object from, to;
1290
1291 from = Fcar (character);
1292 to = Fcdr (character);
1293 CHECK_CHARACTER (from);
1294 CHECK_CHARACTER (to);
1295 range_list = Fcons (character, Qnil);
1296 }
1297 else
1298 {
1299 Lisp_Object script_list;
1300 Lisp_Object val;
1301
1302 CHECK_SYMBOL (character);
1303 range_list = Qnil;
1304 script_list = XCHAR_TABLE (Vchar_script_table)->extras[0];
1305 if (! NILP (Fmemq (character, script_list)))
1306 {
1307 val = Fcons (character, Qnil);
1308 map_char_table (accumulate_script_ranges, Qnil, Vchar_script_table,
1309 val);
1310 range_list = XCDR (val);
1311 }
1312 else if (CHARSETP (character))
1313 {
1314 struct charset *charset;
1315
1316 CHECK_CHARSET_GET_CHARSET (character, charset);
1317 if (CHARSET_METHOD (charset) == CHARSET_METHOD_OFFSET)
1318 range_list
1319 = Fcons (Fcons (make_number (CHARSET_MIN_CHAR (charset)),
1320 make_number (CHARSET_MAX_CHAR (charset))),
1321 range_list);
1322 if (EQ (character, Qascii))
1323 {
1324 if (VECTORP (font_spec))
1325 font_spec = generate_ascii_font_name (FONTSET_NAME (fontset),
1326 font_spec);
1327 FONTSET_ASCII (fontset) = font_spec;
1328 }
1329 }
1330
1331 if (NILP (range_list))
1332 error ("Invalid script or charset name: %s",
1333 SDATA (SYMBOL_NAME (character)));
1334 }
1335
1336 for (; CONSP (range_list); range_list = XCDR (range_list))
1337 FONTSET_ADD (fontset, XCAR (range_list), font_def, add);
1338
1339 /* Free all realized fontsets whose base is FONTSET. This way, the
1340 specified character(s) are surely redisplayed by a correct
1341 font. */
1342 free_realized_fontsets (fontset);
1343
1344 return Qnil;
1345 }
1346
1347
1348 DEFUN ("new-fontset", Fnew_fontset, Snew_fontset, 2, 2, 0,
1349 doc: /* Create a new fontset NAME from font information in FONTLIST.
1350
1351 FONTLIST is an alist of scripts vs the corresponding font specification list.
1352 Each element of FONTLIST has the form (SCRIPT FONT-SPEC ...), where a
1353 character of SCRIPT is displayed by a font that matches one of
1354 FONT-SPEC.
1355
1356 SCRIPT is a symbol that appears in the first extra slot of the
1357 char-table `char-script-table'.
1358
1359 FONT-SPEC is a vector, a cons, or a string. See the documentation of
1360 `set-fontset-font' for the meaning. */)
1361 (name, fontlist)
1362 Lisp_Object name, fontlist;
1363 {
1364 Lisp_Object fontset;
1365 Lisp_Object val;
1366 int id;
1367
1368 CHECK_STRING (name);
1369 CHECK_LIST (fontlist);
1370
1371 id = fs_query_fontset (name, 0);
1372 if (id < 0)
1373 {
1374 name = Fdowncase (name);
1375 val = split_font_name_into_vector (name);
1376 if (NILP (val))
1377 error ("Fontset name must be in XLFD format");
1378 if (strcmp (SDATA (AREF (val, 12)), "fontset"))
1379 error ("Registry field of fontset name must be \"fontset\"");
1380 Vfontset_alias_alist
1381 = Fcons (Fcons (name,
1382 concat2 (concat2 (AREF (val, 12), build_string ("-")),
1383 AREF (val, 13))),
1384 Vfontset_alias_alist);
1385 ASET (val, 12, build_string ("iso8859-1"));
1386 fontset = make_fontset (Qnil, name, Qnil);
1387 FONTSET_ASCII (fontset) = build_font_name_from_vector (val);
1388 }
1389 else
1390 {
1391 fontset = FONTSET_FROM_ID (id);;
1392 free_realized_fontsets (fontset);
1393 Fset_char_table_range (fontset, Qt, Qnil);
1394 }
1395
1396 for (; ! NILP (fontlist); fontlist = Fcdr (fontlist))
1397 {
1398 Lisp_Object elt, script;
1399
1400 elt = Fcar (fontlist);
1401 script = Fcar (elt);
1402 for (elt = Fcdr (elt); ! NILP (elt); elt = Fcdr (elt))
1403 Fset_fontset_font (name, script, Fcar (elt), Qnil, Qappend);
1404 }
1405 return name;
1406 }
1407
1408
1409 /* Number of fontsets created from a fontname automatically. */
1410 static int n_auto_fontsets;
1411
1412 int
1413 new_fontset_from_font_name (Lisp_Object fontname)
1414 {
1415 Lisp_Object name;
1416 Lisp_Object vec;
1417
1418 fontname = Fdowncase (fontname);
1419 vec = split_font_name_into_vector (fontname);
1420 if ( NILP (vec))
1421 vec = Fmake_vector (make_number (14), build_string (""));
1422 ASET (vec, 12, build_string ("fontset"));
1423 if (n_auto_fontsets == 0)
1424 {
1425 ASET (vec, 13, build_string ("startup"));
1426 name = build_font_name_from_vector (vec);
1427 n_auto_fontsets++;
1428 }
1429 else
1430 {
1431 char temp[20];
1432
1433 do {
1434 sprintf (temp, "auto%d", n_auto_fontsets);
1435 ASET (vec, 13, build_string (temp));
1436 name = build_font_name_from_vector (vec);
1437 n_auto_fontsets++;
1438 } while (fs_query_fontset (name, 0) >= 0);
1439 }
1440 name = Fnew_fontset (name,
1441 Fcons (Fcons (Qascii, Fcons (fontname, Qnil)), Qnil));
1442 Vfontset_alias_alist = Fcons (Fcons (name, fontname), Vfontset_alias_alist);
1443 return fs_query_fontset (name, 0);
1444 }
1445
1446
1447 DEFUN ("font-info", Ffont_info, Sfont_info, 1, 2, 0,
1448 doc: /* Return information about a font named NAME on frame FRAME.
1449 If FRAME is omitted or nil, use the selected frame.
1450 The returned value is a vector of OPENED-NAME, FULL-NAME, CHARSET, SIZE,
1451 HEIGHT, BASELINE-OFFSET, RELATIVE-COMPOSE, and DEFAULT-ASCENT,
1452 where
1453 OPENED-NAME is the name used for opening the font,
1454 FULL-NAME is the full name of the font,
1455 SIZE is the maximum bound width of the font,
1456 HEIGHT is the height of the font,
1457 BASELINE-OFFSET is the upward offset pixels from ASCII baseline,
1458 RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling
1459 how to compose characters.
1460 If the named font is not yet loaded, return nil. */)
1461 (name, frame)
1462 Lisp_Object name, frame;
1463 {
1464 FRAME_PTR f;
1465 struct font_info *fontp;
1466 Lisp_Object info;
1467
1468 (*check_window_system_func) ();
1469
1470 CHECK_STRING (name);
1471 name = Fdowncase (name);
1472 if (NILP (frame))
1473 frame = selected_frame;
1474 CHECK_LIVE_FRAME (frame);
1475 f = XFRAME (frame);
1476
1477 if (!query_font_func)
1478 error ("Font query function is not supported");
1479
1480 fontp = (*query_font_func) (f, SDATA (name));
1481 if (!fontp)
1482 return Qnil;
1483
1484 info = Fmake_vector (make_number (7), Qnil);
1485
1486 XVECTOR (info)->contents[0] = build_string (fontp->name);
1487 XVECTOR (info)->contents[1] = build_string (fontp->full_name);
1488 XVECTOR (info)->contents[2] = make_number (fontp->size);
1489 XVECTOR (info)->contents[3] = make_number (fontp->height);
1490 XVECTOR (info)->contents[4] = make_number (fontp->baseline_offset);
1491 XVECTOR (info)->contents[5] = make_number (fontp->relative_compose);
1492 XVECTOR (info)->contents[6] = make_number (fontp->default_ascent);
1493
1494 return info;
1495 }
1496
1497
1498 /* Return the font name for the character at POSITION in the current
1499 buffer. This is computed from all the text properties and overlays
1500 that apply to POSITION. It returns nil in the following cases:
1501
1502 (1) The window system doesn't have a font for the character (thus
1503 it is displayed by an empty box).
1504
1505 (2) The character code is invalid.
1506
1507 (3) The current buffer is not displayed in any window.
1508
1509 In addition, the returned font name may not take into account of
1510 such redisplay engine hooks as what used in jit-lock-mode if
1511 POSITION is currently not visible. */
1512
1513
1514 DEFUN ("internal-char-font", Finternal_char_font, Sinternal_char_font, 1, 1, 0,
1515 doc: /* For internal use only. */)
1516 (position)
1517 Lisp_Object position;
1518 {
1519 int pos, pos_byte, dummy;
1520 int face_id;
1521 int c;
1522 Lisp_Object window;
1523 struct window *w;
1524 struct frame *f;
1525 struct face *face;
1526
1527 CHECK_NUMBER_COERCE_MARKER (position);
1528 pos = XINT (position);
1529 if (pos < BEGV || pos >= ZV)
1530 args_out_of_range_3 (position, make_number (BEGV), make_number (ZV));
1531 pos_byte = CHAR_TO_BYTE (pos);
1532 c = FETCH_CHAR (pos_byte);
1533 window = Fget_buffer_window (Fcurrent_buffer (), Qnil);
1534 if (NILP (window))
1535 return Qnil;
1536 w = XWINDOW (window);
1537 f = XFRAME (w->frame);
1538 face_id = face_at_buffer_position (w, pos, -1, -1, &dummy, pos + 100, 0);
1539 face_id = FACE_FOR_CHAR (f, FACE_FROM_ID (f, face_id), c);
1540 face = FACE_FROM_ID (f, face_id);
1541 return (face->font && face->font_name
1542 ? build_string (face->font_name)
1543 : Qnil);
1544 }
1545
1546
1547 DEFUN ("fontset-info", Ffontset_info, Sfontset_info, 1, 2, 0,
1548 doc: /* Return information about a fontset FONTSET on frame FRAME.
1549 The value is a char-table of which elements has this form.
1550
1551 ((FONT-PATTERN OPENED-FONT ...) ...)
1552
1553 FONT-PATTERN is a vector:
1554
1555 [ FAMILY WEIGHT SLANT SWIDTH ADSTYLE REGISTRY ]
1556
1557 or a string of font name pattern.
1558
1559 OPENED-FONT is a name of a font actually opened.
1560
1561 The char-table has one extra slot. The value is a char-table
1562 containing the information about the derived fonts from the default
1563 fontset. The format is the same as abobe. */)
1564 (fontset, frame)
1565 Lisp_Object fontset, frame;
1566 {
1567 FRAME_PTR f;
1568 Lisp_Object table, val, elt;
1569 Lisp_Object *realized;
1570 int n_realized = 0;
1571 int fallback;
1572 int c, i, j;
1573
1574 (*check_window_system_func) ();
1575
1576 fontset = check_fontset_name (fontset);
1577
1578 if (NILP (frame))
1579 frame = selected_frame;
1580 CHECK_LIVE_FRAME (frame);
1581 f = XFRAME (frame);
1582
1583 /* Recode fontsets realized on FRAME from the base fontset FONTSET
1584 in the table `realized'. */
1585 realized = (Lisp_Object *) alloca (sizeof (Lisp_Object)
1586 * ASIZE (Vfontset_table));
1587 for (i = 0; i < ASIZE (Vfontset_table); i++)
1588 {
1589 elt = FONTSET_FROM_ID (i);
1590 if (!NILP (elt)
1591 && EQ (FONTSET_BASE (elt), fontset)
1592 && EQ (FONTSET_FRAME (elt), frame))
1593 realized[n_realized++] = elt;
1594 }
1595
1596
1597 table = Fmake_char_table (Qfontset_info, Qnil);
1598 XCHAR_TABLE (table)->extras[0] = Fmake_char_table (Qnil, Qnil);
1599 /* Accumulate information of the fontset in TABLE. The format of
1600 each element is ((FONT-SPEC OPENED-FONT ...) ...). */
1601 for (fallback = 0; fallback <= 1; fallback++)
1602 {
1603 Lisp_Object this_fontset, this_table;
1604
1605 if (! fallback)
1606 {
1607 this_fontset = fontset;
1608 this_table = table;
1609 }
1610 else
1611 {
1612 this_fontset = Vdefault_fontset;
1613 this_table = XCHAR_TABLE (table)->extras[0];
1614 #if 0
1615 for (i = 0; i < n_realized; i++)
1616 realized[i] = FONTSET_FALLBACK (realized[i]);
1617 #endif
1618 }
1619 for (c = 0; c <= MAX_5_BYTE_CHAR; )
1620 {
1621 int from, to;
1622
1623 val = char_table_ref_and_range (this_fontset, c, &from, &to);
1624 if (VECTORP (val))
1625 {
1626 Lisp_Object alist;
1627
1628 /* At first, set ALIST to ((FONT-SPEC) ...). */
1629 for (alist = Qnil, i = 0; i < ASIZE (val); i++)
1630 alist = Fcons (Fcons (AREF (AREF (val, i), 0), Qnil), alist);
1631 alist = Fnreverse (alist);
1632
1633 /* Then store opend font names to cdr of each elements. */
1634 for (i = 0; i < n_realized; i++)
1635 {
1636 if (NILP (realized[i]))
1637 continue;
1638 val = FONTSET_REF (realized[i], c);
1639 if (NILP (val))
1640 continue;
1641 val = XCDR (val);
1642 /* Now VAL is [[FACE-ID FONT-INDEX FONT-DEF] ...].
1643 If a font of an element is already opened,
1644 FONT-INDEX of the element is integer. */
1645 for (j = 0; j < ASIZE (val); j++)
1646 if (INTEGERP (AREF (AREF (val, j), 0)))
1647 {
1648 Lisp_Object font_idx;
1649
1650 font_idx = AREF (AREF (val, j), 1);
1651 elt = Fassq (AREF (AREF (AREF (val, j), 2), 0), alist);
1652 if (CONSP (elt)
1653 && NILP (Fmemq (font_idx, XCDR(elt))))
1654 nconc2 (elt, Fcons (font_idx, Qnil));
1655 }
1656 }
1657 for (val = alist; CONSP (val); val = XCDR (val))
1658 for (elt = XCDR (XCAR (val)); CONSP (elt); elt = XCDR (elt))
1659 {
1660 struct font_info *font_info
1661 = (*get_font_info_func) (f, XINT (XCAR (elt)));
1662 XSETCAR (elt, build_string (font_info->full_name));
1663 }
1664
1665 /* Store ALIST in TBL for characters C..TO. */
1666 char_table_set_range (this_table, c, to, alist);
1667 }
1668 c = to + 1;
1669 }
1670 }
1671
1672 return table;
1673 }
1674
1675
1676 DEFUN ("fontset-font", Ffontset_font, Sfontset_font, 2, 2, 0,
1677 doc: /* Return a font name pattern for character CH in fontset NAME.
1678 If NAME is t, find a font name pattern in the default fontset. */)
1679 (name, ch)
1680 Lisp_Object name, ch;
1681 {
1682 int c;
1683 Lisp_Object fontset, elt;
1684
1685 fontset = check_fontset_name (name);
1686
1687 CHECK_CHARACTER (ch);
1688 c = XINT (ch);
1689 elt = FONTSET_REF (fontset, c);
1690 return Fcopy_sequence (elt);
1691 }
1692
1693 DEFUN ("fontset-list", Ffontset_list, Sfontset_list, 0, 0, 0,
1694 doc: /* Return a list of all defined fontset names. */)
1695 ()
1696 {
1697 Lisp_Object fontset, list;
1698 int i;
1699
1700 list = Qnil;
1701 for (i = 0; i < ASIZE (Vfontset_table); i++)
1702 {
1703 fontset = FONTSET_FROM_ID (i);
1704 if (!NILP (fontset)
1705 && BASE_FONTSET_P (fontset))
1706 list = Fcons (FONTSET_NAME (fontset), list);
1707 }
1708
1709 return list;
1710 }
1711
1712 void
1713 syms_of_fontset ()
1714 {
1715 if (!load_font_func)
1716 /* Window system initializer should have set proper functions. */
1717 abort ();
1718
1719 DEFSYM (Qfontset, "fontset");
1720 Fput (Qfontset, Qchar_table_extra_slots, make_number (8));
1721 DEFSYM (Qfontset_info, "fontset-info");
1722 Fput (Qfontset_info, Qchar_table_extra_slots, make_number (1));
1723
1724 DEFSYM (Qprepend, "prepend");
1725 DEFSYM (Qappend, "append");
1726
1727 Vcached_fontset_data = Qnil;
1728 staticpro (&Vcached_fontset_data);
1729
1730 Vfontset_table = Fmake_vector (make_number (32), Qnil);
1731 staticpro (&Vfontset_table);
1732
1733 Vdefault_fontset = Fmake_char_table (Qfontset, Qnil);
1734 staticpro (&Vdefault_fontset);
1735 FONTSET_ID (Vdefault_fontset) = make_number (0);
1736 FONTSET_NAME (Vdefault_fontset)
1737 = build_string ("-*-*-*-*-*-*-*-*-*-*-*-*-fontset-default");
1738 {
1739 Lisp_Object default_ascii_font;
1740
1741 #if defined (macintosh)
1742 default_ascii_font
1743 = build_string ("-apple-monaco-medium-r-*--*-120-*-*-*-*-mac-roman");
1744 #elif defined (WINDOWSNT)
1745 default_ascii_font
1746 = build_string ("-*-courier new-normal-r-*-*-*-100-*-*-*-*-iso8859-1");
1747 #else
1748 default_ascii_font
1749 = build_string ("-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
1750 #endif
1751 FONTSET_ASCII (Vdefault_fontset) = default_ascii_font;
1752 }
1753 AREF (Vfontset_table, 0) = Vdefault_fontset;
1754 next_fontset_id = 1;
1755
1756 DEFVAR_LISP ("font-encoding-alist", &Vfont_encoding_alist,
1757 doc: /*
1758 Alist of fontname patterns vs the corresponding encoding and repertory info.
1759 Each element looks like (REGEXP . (ENCODING . REPERTORY)),
1760 where ENCODING is a charset or a char-table,
1761 and REPERTORY is a charset, a char-table, or nil.
1762
1763 ENCODING is for converting a character to a glyph code of the font.
1764 If ENCODING is a charset, encoding a character by the charset gives
1765 the corresponding glyph code. If ENCODING is a char-table, looking up
1766 the table by a character gives the corresponding glyph code.
1767
1768 REPERTORY specifies a repertory of characters supported by the font.
1769 If REPERTORY is a charset, all characters beloging to the charset are
1770 supported. If REPERTORY is a char-table, all characters who have a
1771 non-nil value in the table are supported. It REPERTORY is nil, Emacs
1772 gets the repertory information by an opened font and ENCODING. */);
1773 Vfont_encoding_alist = Qnil;
1774
1775 DEFVAR_LISP ("use-default-ascent", &Vuse_default_ascent,
1776 doc: /*
1777 Char table of characters whose ascent values should be ignored.
1778 If an entry for a character is non-nil, the ascent value of the glyph
1779 is assumed to be what specified by _MULE_DEFAULT_ASCENT property of a font.
1780
1781 This affects how a composite character which contains
1782 such a character is displayed on screen. */);
1783 Vuse_default_ascent = Qnil;
1784
1785 DEFVAR_LISP ("ignore-relative-composition", &Vignore_relative_composition,
1786 doc: /*
1787 Char table of characters which is not composed relatively.
1788 If an entry for a character is non-nil, a composition sequence
1789 which contains that character is displayed so that
1790 the glyph of that character is put without considering
1791 an ascent and descent value of a previous character. */);
1792 Vignore_relative_composition = Qnil;
1793
1794 DEFVAR_LISP ("alternate-fontname-alist", &Valternate_fontname_alist,
1795 doc: /* Alist of fontname vs list of the alternate fontnames.
1796 When a specified font name is not found, the corresponding
1797 alternate fontnames (if any) are tried instead. */);
1798 Valternate_fontname_alist = Qnil;
1799
1800 DEFVAR_LISP ("fontset-alias-alist", &Vfontset_alias_alist,
1801 doc: /* Alist of fontset names vs the aliases. */);
1802 Vfontset_alias_alist = Fcons (Fcons (FONTSET_NAME (Vdefault_fontset),
1803 build_string ("fontset-default")),
1804 Qnil);
1805
1806 DEFVAR_LISP ("vertical-centering-font-regexp",
1807 &Vvertical_centering_font_regexp,
1808 doc: /* *Regexp matching font names that require vertical centering on display.
1809 When a character is displayed with such fonts, the character is displayed
1810 at the vertical center of lines. */);
1811 Vvertical_centering_font_regexp = Qnil;
1812
1813 defsubr (&Squery_fontset);
1814 defsubr (&Snew_fontset);
1815 defsubr (&Sset_fontset_font);
1816 defsubr (&Sfont_info);
1817 defsubr (&Sinternal_char_font);
1818 defsubr (&Sfontset_info);
1819 defsubr (&Sfontset_font);
1820 defsubr (&Sfontset_list);
1821 }
1822
1823 Lisp_Object
1824 dump_fontset (fontset)
1825 Lisp_Object fontset;
1826 {
1827 Lisp_Object val;
1828
1829 if (NILP (FONTSET_FALLBACK (fontset)))
1830 val = Fcons (Fcons (intern ("fallback-id"), Qnil), Qnil);
1831 else
1832 val = Fcons (Fcons (intern ("fallback-id"),
1833 FONTSET_ID (FONTSET_FALLBACK (fontset))),
1834 Qnil);
1835 if (NILP (FONTSET_BASE (fontset)))
1836 val = Fcons (Fcons (intern ("base"), Qnil), val);
1837 else
1838 val = Fcons (Fcons (intern ("base"),
1839 FONTSET_NAME (FONTSET_BASE (fontset))),
1840 val);
1841 val = Fcons (Fcons (intern ("name"), FONTSET_NAME (fontset)), val);
1842 val = Fcons (Fcons (intern ("id"), FONTSET_ID (fontset)), val);
1843 return val;
1844 }