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