2 Copyright (C) 1995, 1997, 2000 Electrotechnical Laboratory, JAPAN.
3 Licensed to the Free Software Foundation.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* #define FONTSET_DEBUG */
35 #include "dispextern.h"
41 #define xassert(X) do {if (!(X)) abort ();} while (0)
49 A fontset is a collection of font related information to give
50 similar appearance (style, size, etc) of characters. There are two
51 kinds of fontsets; base and realized. A base fontset is created by
52 new-fontset from Emacs Lisp explicitly. A realized fontset is
53 created implicitly when a face is realized for ASCII characters. A
54 face is also realized for multibyte characters based on an ASCII
55 face. All of the multibyte faces based on the same ASCII face
56 share the same realized fontset.
58 A fontset object is implemented by a char-table.
60 An element of a base fontset is:
62 (INDEX . (FOUNDRY . REGISTRY ))
63 FONTNAME is a font name pattern for the corresponding character.
64 FOUNDRY and REGISTRY are respectively foundy and regisry fields of
65 a font name for the corresponding character. INDEX specifies for
66 which character (or generic character) the element is defined. It
67 may be different from an index to access this element. For
68 instance, if a fontset defines some font for all characters of
69 charset `japanese-jisx0208', INDEX is the generic character of this
70 charset. REGISTRY is the
72 An element of a realized fontset is FACE-ID which is a face to use
73 for displaying the correspnding character.
75 All single byte charaters (ASCII and 8bit-unibyte) share the same
76 element in a fontset. The element is stored in the first element
79 To access or set each element, use macros FONTSET_REF and
80 FONTSET_SET respectively for efficiency.
82 A fontset has 3 extra slots.
84 The 1st slot is an ID number of the fontset.
86 The 2nd slot is a name of the fontset. This is nil for a realized
89 The 3rd slot is a frame that the fontset belongs to. This is nil
92 A parent of a base fontset is nil. A parent of a realized fontset
95 All fontsets (except for the default fontset described below) are
96 recorded in Vfontset_table.
101 There's a special fontset named `default fontset' which defines a
102 default fontname that contains only REGISTRY field for each
103 character. When a base fontset doesn't specify a font for a
104 specific character, the corresponding value in the default fontset
105 is used. The format is the same as a base fontset.
107 The parent of realized fontsets created for faces that have no
108 fontset is the default fontset.
111 These structures are hidden from the other codes than this file.
112 The other codes handle fontsets only by their ID numbers. They
113 usually use variable name `fontset' for IDs. But, in this file, we
114 always use varialbe name `id' for IDs, and name `fontset' for the
115 actual fontset objects.
119 /********** VARIABLES and FUNCTION PROTOTYPES **********/
121 extern Lisp_Object Qfont
;
122 Lisp_Object Qfontset
;
124 /* Vector containing all fontsets. */
125 static Lisp_Object Vfontset_table
;
127 /* Next possibly free fontset ID. Usually this keeps the mininum
128 fontset ID not yet used. */
129 static int next_fontset_id
;
131 /* The default fontset. This gives default FAMILY and REGISTRY of
132 font for each characters. */
133 static Lisp_Object Vdefault_fontset
;
135 Lisp_Object Vfont_encoding_alist
;
136 Lisp_Object Vuse_default_ascent
;
137 Lisp_Object Vignore_relative_composition
;
138 Lisp_Object Valternate_fontname_alist
;
139 Lisp_Object Vfontset_alias_alist
;
140 Lisp_Object Vhighlight_wrong_size_font
;
141 Lisp_Object Vclip_large_size_font
;
142 Lisp_Object Vvertical_centering_font_regexp
;
144 /* The following six are declarations of callback functions depending
145 on window system. See the comments in src/fontset.h for more
148 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
149 struct font_info
*(*get_font_info_func
) P_ ((FRAME_PTR f
, int font_idx
));
151 /* Return a list of font names which matches PATTERN. See the document of
152 `x-list-fonts' for more detail. */
153 Lisp_Object (*list_fonts_func
) P_ ((struct frame
*f
,
158 /* Load a font named NAME for frame F and return a pointer to the
159 information of the loaded font. If loading is failed, return 0. */
160 struct font_info
*(*load_font_func
) P_ ((FRAME_PTR f
, char *name
, int));
162 /* Return a pointer to struct font_info of a font named NAME for frame F. */
163 struct font_info
*(*query_font_func
) P_ ((FRAME_PTR f
, char *name
));
165 /* Additional function for setting fontset or changing fontset
166 contents of frame F. */
167 void (*set_frame_fontset_func
) P_ ((FRAME_PTR f
, Lisp_Object arg
,
168 Lisp_Object oldval
));
170 /* To find a CCL program, fs_load_font calls this function.
171 The argument is a pointer to the struct font_info.
172 This function set the memer `encoder' of the structure. */
173 void (*find_ccl_program_func
) P_ ((struct font_info
*));
175 /* Check if any window system is used now. */
176 void (*check_window_system_func
) P_ ((void));
179 /* Prototype declarations for static functions. */
180 static Lisp_Object fontset_ref
P_ ((Lisp_Object
, int));
181 static void fontset_set
P_ ((Lisp_Object
, int, Lisp_Object
));
182 static Lisp_Object make_fontset
P_ ((Lisp_Object
, Lisp_Object
, Lisp_Object
));
183 static int fontset_id_valid_p
P_ ((int));
184 static Lisp_Object fontset_pattern_regexp
P_ ((Lisp_Object
));
185 static Lisp_Object font_family_registry
P_ ((Lisp_Object
));
188 /********** MACROS AND FUNCTIONS TO HANDLE FONTSET **********/
190 /* Macros for Lisp vector. */
191 #define AREF(V, IDX) XVECTOR (V)->contents[IDX]
192 #define ASIZE(V) XVECTOR (V)->size
194 /* Return the fontset with ID. No check of ID's validness. */
195 #define FONTSET_FROM_ID(id) AREF (Vfontset_table, id)
197 /* Macros to access extra, default, and parent slots, of fontset. */
198 #define FONTSET_ID(fontset) XCHAR_TABLE (fontset)->extras[0]
199 #define FONTSET_NAME(fontset) XCHAR_TABLE (fontset)->extras[1]
200 #define FONTSET_FRAME(fontset) XCHAR_TABLE (fontset)->extras[2]
201 #define FONTSET_ASCII(fontset) XCHAR_TABLE (fontset)->contents[0]
202 #define FONTSET_BASE(fontset) XCHAR_TABLE (fontset)->parent
204 #define BASE_FONTSET_P(fontset) NILP (FONTSET_BASE(fontset))
207 /* Return the element of FONTSET (char-table) at index C (character). */
209 #define FONTSET_REF(fontset, c) fontset_ref (fontset, c)
211 static INLINE Lisp_Object
212 fontset_ref (fontset
, c
)
217 Lisp_Object elt
, defalt
;
220 if (SINGLE_BYTE_CHAR_P (c
))
221 return FONTSET_ASCII (fontset
);
223 SPLIT_CHAR (c
, charset
, c1
, c2
);
224 elt
= XCHAR_TABLE (fontset
)->contents
[charset
+ 128];
225 if (!SUB_CHAR_TABLE_P (elt
))
227 defalt
= XCHAR_TABLE (elt
)->defalt
;
229 || (elt
= XCHAR_TABLE (elt
)->contents
[c1
],
232 if (!SUB_CHAR_TABLE_P (elt
))
234 defalt
= XCHAR_TABLE (elt
)->defalt
;
236 || (elt
= XCHAR_TABLE (elt
)->contents
[c2
],
243 #define FONTSET_REF_VIA_BASE(fontset, c) fontset_ref_via_base (fontset, &c)
245 static INLINE Lisp_Object
246 fontset_ref_via_base (fontset
, c
)
253 if (SINGLE_BYTE_CHAR_P (*c
))
254 return FONTSET_ASCII (fontset
);
256 elt
= FONTSET_REF (FONTSET_BASE (fontset
), *c
);
257 if (NILP (elt
) && ! EQ (fontset
, Vdefault_fontset
))
258 elt
= FONTSET_REF (Vdefault_fontset
, *c
);
262 *c
= XINT (XCAR (elt
));
263 SPLIT_CHAR (*c
, charset
, c1
, c2
);
264 elt
= XCHAR_TABLE (fontset
)->contents
[charset
+ 128];
266 return (SUB_CHAR_TABLE_P (elt
) ? XCHAR_TABLE (elt
)->defalt
: elt
);
267 if (!SUB_CHAR_TABLE_P (elt
))
269 elt
= XCHAR_TABLE (elt
)->contents
[c1
];
271 return (SUB_CHAR_TABLE_P (elt
) ? XCHAR_TABLE (elt
)->defalt
: elt
);
272 if (!SUB_CHAR_TABLE_P (elt
))
274 elt
= XCHAR_TABLE (elt
)->contents
[c2
];
279 /* Store into the element of FONTSET at index C the value NEWETL. */
280 #define FONTSET_SET(fontset, c, newelt) fontset_set(fontset, c, newelt)
283 fontset_set (fontset
, c
, newelt
)
288 int charset
, code
[3];
289 Lisp_Object
*elt
, tmp
;
292 if (SINGLE_BYTE_CHAR_P (c
))
294 FONTSET_ASCII (fontset
) = newelt
;
298 SPLIT_CHAR (c
, charset
, code
[0], code
[1]);
299 code
[2] = 0; /* anchor */
300 elt
= &XCHAR_TABLE (fontset
)->contents
[charset
+ 128];
301 for (i
= 0; code
[i
] > 0; i
++)
303 if (!SUB_CHAR_TABLE_P (*elt
))
304 *elt
= make_sub_char_table (*elt
);
305 elt
= &XCHAR_TABLE (*elt
)->contents
[code
[i
]];
307 if (SUB_CHAR_TABLE_P (*elt
))
308 XCHAR_TABLE (*elt
)->defalt
= newelt
;
314 /* Return a newly created fontset with NAME. If BASE is nil, make a
315 base fontset. Otherwise make a realized fontset whose parent is
319 make_fontset (frame
, name
, base
)
320 Lisp_Object frame
, name
, base
;
322 Lisp_Object fontset
, elt
, base_elt
;
323 int size
= ASIZE (Vfontset_table
);
324 int id
= next_fontset_id
;
327 /* Find a free slot in Vfontset_table. Usually, next_fontset_id is
328 the next available fontset ID. So it is expected that this loop
329 terminates quickly. In addition, as the last element of
330 Vfotnset_table is always nil, we don't have to check the range of
332 while (!NILP (AREF (Vfontset_table
, id
))) id
++;
339 tem
= Fmake_vector (make_number (size
+ 8), Qnil
);
340 for (i
= 0; i
< size
; i
++)
341 AREF (tem
, i
) = AREF (Vfontset_table
, i
);
342 Vfontset_table
= tem
;
345 fontset
= Fmake_char_table (Qfontset
, Qnil
);
347 FONTSET_ID (fontset
) = make_number (id
);
348 FONTSET_NAME (fontset
) = name
;
349 FONTSET_FRAME (fontset
) = frame
;
350 FONTSET_BASE (fontset
) = base
;
352 AREF (Vfontset_table
, id
) = fontset
;
353 next_fontset_id
= id
+ 1;
358 /* Return 1 if ID is a valid fontset id, else return 0. */
361 fontset_id_valid_p (id
)
364 return (id
>= 0 && id
< ASIZE (Vfontset_table
) - 1);
368 /* Extract `family' and `registry' string from FONTNAME and set in
369 *FAMILY and *REGISTRY respectively. Actually, `family' may also
370 contain `foundry', `registry' may also contain `encoding' of
374 font_family_registry (fontname
)
375 Lisp_Object fontname
;
377 Lisp_Object family
, registry
;
378 char *p
= XSTRING (fontname
)->data
;
382 while (*p
&& i
< 15) if (*p
++ == '-') sep
[i
++] = p
;
386 family
= make_unibyte_string (sep
[0], sep
[2] - 1 - sep
[0]);
387 registry
= make_unibyte_string (sep
[12], p
- sep
[12]);
388 return Fcons (family
, registry
);
392 /********** INTERFACES TO xfaces.c and dispextern.h **********/
394 /* Return name of the fontset with ID. */
401 fontset
= FONTSET_FROM_ID (id
);
402 return FONTSET_NAME (fontset
);
406 /* Return ASCII font name of the fontset with ID. */
412 Lisp_Object fontset
, elt
;
413 fontset
= FONTSET_FROM_ID (id
);
414 elt
= FONTSET_ASCII (fontset
);
419 /* Free fontset of FACE. Called from free_realized_face. */
422 free_face_fontset (f
, face
)
426 if (fontset_id_valid_p (face
->fontset
))
428 AREF (Vfontset_table
, face
->fontset
) = Qnil
;
429 if (face
->fontset
< next_fontset_id
)
430 next_fontset_id
= face
->fontset
;
435 /* Return 1 iff FACE is suitable for displaying character C.
436 Otherwise return 0. Called from the macro FACE_SUITABLE_FOR_CHAR_P
437 when C is not a single byte character.. */
440 face_suitable_for_char_p (face
, c
)
444 Lisp_Object fontset
, elt
;
446 if (SINGLE_BYTE_CHAR_P (c
))
447 return (face
== face
->ascii_face
);
449 xassert (fontset_id_valid_p (face
->fontset
));
450 fontset
= FONTSET_FROM_ID (face
->fontset
);
451 xassert (!BASE_FONTSET_P (fontset
));
453 elt
= FONTSET_REF_VIA_BASE (fontset
, c
);
454 return (!NILP (elt
) && face
->id
== XFASTINT (elt
));
458 /* Return ID of face suitable for displaying character C on frame F.
459 The selection of face is done based on the fontset of FACE. FACE
460 should already have been realized for ASCII characters. Called
461 from the macro FACE_FOR_CHAR when C is not a single byte character. */
464 face_for_char (f
, face
, c
)
469 Lisp_Object fontset
, elt
;
472 xassert (fontset_id_valid_p (face
->fontset
));
473 fontset
= FONTSET_FROM_ID (face
->fontset
);
474 xassert (!BASE_FONTSET_P (fontset
));
476 elt
= FONTSET_REF_VIA_BASE (fontset
, c
);
480 /* No face is recorded for C in the fontset of FACE. Make a new
481 realized face for C that has the same fontset. */
482 face_id
= lookup_face (f
, face
->lface
, c
, face
);
484 /* Record the face ID in FONTSET at the same index as the
485 information in the base fontset. */
486 FONTSET_SET (fontset
, c
, make_number (face_id
));
491 /* Make a realized fontset for ASCII face FACE on frame F from the
492 base fontset BASE_FONTSET_ID. If BASE_FONTSET_ID is -1, use the
493 default fontset as the base. Value is the id of the new fontset.
494 Called from realize_x_face. */
497 make_fontset_for_ascii_face (f
, base_fontset_id
)
501 Lisp_Object base_fontset
, fontset
, name
, frame
;
503 XSETFRAME (frame
, f
);
504 if (base_fontset_id
>= 0)
506 base_fontset
= FONTSET_FROM_ID (base_fontset_id
);
507 if (!BASE_FONTSET_P (base_fontset
))
508 base_fontset
= FONTSET_BASE (base_fontset
);
509 xassert (BASE_FONTSET_P (base_fontset
));
512 base_fontset
= Vdefault_fontset
;
514 fontset
= make_fontset (frame
, Qnil
, base_fontset
);
515 return XINT (FONTSET_ID (fontset
));
519 /* Return the font name pattern for C that is recorded in the fontset
520 with ID. A font is opened by that pattern to get the fullname. If
521 the fullname conform to XLFD, extract foundry-family field and
522 registry-encoding field, and return the cons of them. Otherwise
523 return the fullname. If ID is -1, or the fontset doesn't contain
524 information about C, get the registry and encoding of C from the
525 default fontset. Called from choose_face_font. */
528 fontset_font_pattern (f
, id
, c
)
532 Lisp_Object fontset
, elt
;
533 struct font_info
*fontp
;
534 Lisp_Object family_registry
;
537 if (fontset_id_valid_p (id
))
539 fontset
= FONTSET_FROM_ID (id
);
540 xassert (!BASE_FONTSET_P (fontset
));
541 fontset
= FONTSET_BASE (fontset
);
542 elt
= FONTSET_REF (fontset
, c
);
545 elt
= FONTSET_REF (Vdefault_fontset
, c
);
549 if (CONSP (XCDR (elt
)))
552 /* The fontset specifies only a font name pattern (not cons of
553 family and registry). Try to open a font by that pattern and get
554 a registry from the full name of the opened font. We ignore
555 family name here because it should be wild card in the fontset
558 xassert (STRINGP (elt
));
559 fontp
= FS_LOAD_FONT (f
, c
, XSTRING (elt
)->data
, -1);
563 family_registry
= font_family_registry (build_string (fontp
->full_name
));
564 if (!CONSP (family_registry
))
565 return family_registry
;
566 XCAR (family_registry
) = Qnil
;
567 return family_registry
;
571 /* Load a font named FONTNAME to display character C on frame F.
572 Return a pointer to the struct font_info of the loaded font. If
573 loading fails, return NULL. If FACE is non-zero and a fontset is
574 assigned to it, record FACE->id in the fontset for C. If FONTNAME
575 is NULL, the name is taken from the fontset of FACE or what
579 fs_load_font (f
, c
, fontname
, id
, face
)
587 Lisp_Object list
, elt
;
590 struct font_info
*fontp
;
591 int charset
= CHAR_CHARSET (c
);
598 fontset
= FONTSET_FROM_ID (id
);
601 && !BASE_FONTSET_P (fontset
))
603 elt
= FONTSET_REF_VIA_BASE (fontset
, c
);
606 /* A suitable face for C is already recorded, which means
607 that a proper font is already loaded. */
608 int face_id
= XINT (elt
);
610 xassert (face_id
== face
->id
);
611 face
= FACE_FROM_ID (f
, face_id
);
612 return (*get_font_info_func
) (f
, face
->font_info_id
);
615 if (!fontname
&& charset
== CHARSET_ASCII
)
617 elt
= FONTSET_ASCII (fontset
);
618 fontname
= XSTRING (XCDR (elt
))->data
;
623 /* No way to get fontname. */
626 fontp
= (*load_font_func
) (f
, fontname
, size
);
630 /* Fill in members (charset, vertical_centering, encoding, etc) of
631 font_info structure that are not set by (*load_font_func). */
632 fontp
->charset
= charset
;
634 fontp
->vertical_centering
635 = (STRINGP (Vvertical_centering_font_regexp
)
636 && (fast_c_string_match_ignore_case
637 (Vvertical_centering_font_regexp
, fontp
->full_name
) >= 0));
639 if (fontp
->encoding
[1] != FONT_ENCODING_NOT_DECIDED
)
641 /* The font itself tells which code points to be used. Use this
642 encoding for all other charsets. */
645 fontp
->encoding
[0] = fontp
->encoding
[1];
646 for (i
= MIN_CHARSET_OFFICIAL_DIMENSION1
; i
<= MAX_CHARSET
; i
++)
647 fontp
->encoding
[i
] = fontp
->encoding
[1];
651 /* The font itself doesn't have information about encoding. */
654 fontname
= fontp
->full_name
;
655 /* By default, encoding of ASCII chars is 0 (i.e. 0x00..0x7F),
656 others is 1 (i.e. 0x80..0xFF). */
657 fontp
->encoding
[0] = 0;
658 for (i
= MIN_CHARSET_OFFICIAL_DIMENSION1
; i
<= MAX_CHARSET
; i
++)
659 fontp
->encoding
[i
] = 1;
660 /* Then override them by a specification in Vfont_encoding_alist. */
661 for (list
= Vfont_encoding_alist
; CONSP (list
); list
= XCDR (list
))
665 && STRINGP (XCAR (elt
)) && CONSP (XCDR (elt
))
666 && (fast_c_string_match_ignore_case (XCAR (elt
), fontname
)
671 for (tmp
= XCDR (elt
); CONSP (tmp
); tmp
= XCDR (tmp
))
672 if (CONSP (XCAR (tmp
))
673 && ((i
= get_charset_id (XCAR (XCAR (tmp
))))
675 && INTEGERP (XCDR (XCAR (tmp
)))
676 && XFASTINT (XCDR (XCAR (tmp
))) < 4)
678 = XFASTINT (XCDR (XCAR (tmp
)));
683 fontp
->font_encoder
= (struct ccl_program
*) 0;
685 if (find_ccl_program_func
)
686 (*find_ccl_program_func
) (fontp
);
688 /* If we loaded a font for a face that has fontset, record the face
689 ID in the fontset for C. */
692 && !BASE_FONTSET_P (fontset
))
693 FONTSET_SET (fontset
, c
, make_number (face
->id
));
698 /* Cache data used by fontset_pattern_regexp. The car part is a
699 pattern string containing at least one wild card, the cdr part is
700 the corresponding regular expression. */
701 static Lisp_Object Vcached_fontset_data
;
703 #define CACHED_FONTSET_NAME (XSTRING (XCAR (Vcached_fontset_data))->data)
704 #define CACHED_FONTSET_REGEX (XCDR (Vcached_fontset_data))
706 /* If fontset name PATTERN contains any wild card, return regular
707 expression corresponding to PATTERN. */
710 fontset_pattern_regexp (pattern
)
713 if (!index (XSTRING (pattern
)->data
, '*')
714 && !index (XSTRING (pattern
)->data
, '?'))
715 /* PATTERN does not contain any wild cards. */
718 if (!CONSP (Vcached_fontset_data
)
719 || strcmp (XSTRING (pattern
)->data
, CACHED_FONTSET_NAME
))
721 /* We must at first update the cached data. */
722 char *regex
= (char *) alloca (XSTRING (pattern
)->size
* 2);
723 char *p0
, *p1
= regex
;
725 /* Convert "*" to ".*", "?" to ".". */
727 for (p0
= (char *) XSTRING (pattern
)->data
; *p0
; p0
++)
742 Vcached_fontset_data
= Fcons (build_string (XSTRING (pattern
)->data
),
743 build_string (regex
));
746 return CACHED_FONTSET_REGEX
;
749 /* Return ID of the base fontset named NAME. If there's no such
750 fontset, return -1. */
753 fs_query_fontset (name
, regexpp
)
757 Lisp_Object fontset
, tem
;
760 name
= Fdowncase (name
);
763 tem
= Frassoc (name
, Vfontset_alias_alist
);
764 if (CONSP (tem
) && STRINGP (XCAR (tem
)))
768 tem
= fontset_pattern_regexp (name
);
777 for (i
= 0; i
< ASIZE (Vfontset_table
); i
++)
780 unsigned char *this_name
;
782 fontset
= FONTSET_FROM_ID (i
);
784 || !BASE_FONTSET_P (fontset
))
787 this_name
= XSTRING (FONTSET_NAME (fontset
))->data
;
789 ? fast_c_string_match_ignore_case (name
, this_name
) >= 0
790 : !strcmp (XSTRING (name
)->data
, this_name
))
797 DEFUN ("query-fontset", Fquery_fontset
, Squery_fontset
, 1, 2, 0,
798 "Return the name of a fontset that matches PATTERN.\n\
799 The value is nil if there is no matching fontset.\n\
800 PATTERN can contain `*' or `?' as a wildcard\n\
801 just as X font name matching algorithm allows.\n\
802 If REGEXPP is non-nil, PATTERN is a regular expression.")
804 Lisp_Object pattern
, regexpp
;
809 (*check_window_system_func
) ();
811 CHECK_STRING (pattern
, 0);
813 if (XSTRING (pattern
)->size
== 0)
816 id
= fs_query_fontset (pattern
, !NILP (regexpp
));
820 fontset
= FONTSET_FROM_ID (id
);
821 return FONTSET_NAME (fontset
);
824 /* Return a list of base fontset names matching PATTERN on frame F.
825 If SIZE is not 0, it is the size (maximum bound width) of fontsets
829 list_fontsets (f
, pattern
, size
)
834 Lisp_Object frame
, regexp
, val
, tail
;
837 XSETFRAME (frame
, f
);
839 regexp
= fontset_pattern_regexp (pattern
);
842 for (id
= 0; id
< ASIZE (Vfontset_table
); id
++)
847 fontset
= FONTSET_FROM_ID (id
);
849 || !BASE_FONTSET_P (fontset
)
850 || !EQ (frame
, FONTSET_FRAME (fontset
)))
852 name
= XSTRING (FONTSET_NAME (fontset
))->data
;
855 ? (fast_c_string_match_ignore_case (regexp
, name
) < 0)
856 : strcmp (XSTRING (pattern
)->data
, name
))
861 struct font_info
*fontp
;
862 fontp
= FS_LOAD_FONT (f
, 0, NULL
, id
);
863 if (!fontp
|| size
!= fontp
->size
)
866 val
= Fcons (Fcopy_sequence (FONTSET_NAME (fontset
)), val
);
872 DEFUN ("new-fontset", Fnew_fontset
, Snew_fontset
, 2, 2, 0,
873 "Create a new fontset NAME that contains font information in FONTLIST.\n\
874 FONTLIST is an alist of charsets vs corresponding font name patterns.")
876 Lisp_Object name
, fontlist
;
878 Lisp_Object fontset
, elements
, ascii_font
;
879 Lisp_Object tem
, tail
, elt
;
881 (*check_window_system_func
) ();
883 CHECK_STRING (name
, 0);
884 CHECK_LIST (fontlist
, 1);
886 name
= Fdowncase (name
);
887 tem
= Fquery_fontset (name
, Qnil
);
889 error ("Fontset `%s' matches the existing fontset `%s'",
890 XSTRING (name
)->data
, XSTRING (tem
)->data
);
892 /* Check the validity of FONTLIST while creating a template for
894 elements
= ascii_font
= Qnil
;
895 for (tail
= fontlist
; CONSP (tail
); tail
= XCDR (tail
))
897 Lisp_Object family
, registry
;
902 || (charset
= get_charset_id (XCAR (tem
))) < 0
903 || !STRINGP (XCDR (tem
)))
904 error ("Elements of fontlist must be a cons of charset and font name");
906 tem
= Fdowncase (XCDR (tem
));
907 if (charset
== CHARSET_ASCII
)
911 c
= MAKE_CHAR (charset
, 0, 0);
912 elements
= Fcons (Fcons (make_number (c
), tem
), elements
);
916 if (NILP (ascii_font
))
917 error ("No ASCII font in the fontlist");
919 fontset
= make_fontset (Qnil
, name
, Qnil
);
920 FONTSET_ASCII (fontset
) = Fcons (make_number (0), ascii_font
);
921 for (; CONSP (elements
); elements
= XCDR (elements
))
923 elt
= XCAR (elements
);
924 tem
= Fcons (XCAR (elt
), font_family_registry (XCDR (elt
)));
925 FONTSET_SET (fontset
, XINT (XCAR (elt
)), tem
);
932 /* Clear all elements of FONTSET for multibyte characters. */
935 clear_fontset_elements (fontset
)
940 for (i
= CHAR_TABLE_SINGLE_BYTE_SLOTS
; i
< CHAR_TABLE_ORDINARY_SLOTS
; i
++)
941 XCHAR_TABLE (fontset
)->contents
[i
] = Qnil
;
945 /* Check validity of NAME as a fontset name and return the
946 corresponding fontset. If not valid, signal an error.
947 If NAME is t, return Vdefault_fontset. */
950 check_fontset_name (name
)
956 return Vdefault_fontset
;
958 CHECK_STRING (name
, 0);
959 id
= fs_query_fontset (name
, 0);
961 error ("Fontset `%s' does not exist", XSTRING (name
)->data
);
962 return FONTSET_FROM_ID (id
);
965 DEFUN ("set-fontset-font", Fset_fontset_font
, Sset_fontset_font
, 3, 4, 0,
966 "Modify fontset NAME to use FONTNAME for CHARACTER.\n\
968 CHARACTER may be a cons; (FROM . TO), where FROM and TO are\n\
969 non-generic characters. In that case, use FONTNAME\n\
970 for all characters in the range FROM and TO (inclusive).\n\
971 CHARACTER may be a charset. In that case, use FONTNAME\n\
972 for all character in the charsets.\n\
974 FONTNAME may be a cons; (FAMILY . REGISTRY), where FAMILY is a family\n\
975 name of a font, REGSITRY is a registry name of a font.")
976 (name
, character
, fontname
, frame
)
977 Lisp_Object name
, character
, fontname
, frame
;
979 Lisp_Object fontset
, elt
;
980 Lisp_Object realized
;
983 Lisp_Object family
, registry
;
985 fontset
= check_fontset_name (name
);
987 if (CONSP (character
))
989 /* CH should be (FROM . TO) where FROM and TO are non-generic
991 CHECK_NUMBER (XCAR (character
), 1);
992 CHECK_NUMBER (XCDR (character
), 1);
993 from
= XINT (XCAR (character
));
994 to
= XINT (XCDR (character
));
995 if (!char_valid_p (from
, 0) || !char_valid_p (to
, 0))
996 error ("Character range should be by non-generic characters.");
998 && (SINGLE_BYTE_CHAR_P (from
) || SINGLE_BYTE_CHAR_P (to
)))
999 error ("Can't change font for a single byte character");
1001 else if (SYMBOLP (character
))
1003 elt
= Fget (character
, Qcharset
);
1004 if (!VECTORP (elt
) || ASIZE (elt
) < 1 || !NATNUMP (AREF (elt
, 0)))
1005 error ("Invalid charset: %s", (XSYMBOL (character
)->name
)->data
);
1006 from
= MAKE_CHAR (XINT (AREF (elt
, 0)), 0, 0);
1011 CHECK_NUMBER (character
, 1);
1012 from
= XINT (character
);
1015 if (!char_valid_p (from
, 1))
1016 invalid_character (from
);
1017 if (SINGLE_BYTE_CHAR_P (from
))
1018 error ("Can't change font for a single byte character");
1021 if (!char_valid_p (to
, 1))
1022 invalid_character (to
);
1023 if (SINGLE_BYTE_CHAR_P (to
))
1024 error ("Can't change font for a single byte character");
1027 if (STRINGP (fontname
))
1029 fontname
= Fdowncase (fontname
);
1030 elt
= Fcons (make_number (from
), font_family_registry (fontname
));
1034 CHECK_CONS (fontname
, 2);
1035 family
= XCAR (fontname
);
1036 registry
= XCDR (fontname
);
1038 CHECK_STRING (family
, 2);
1039 if (!NILP (registry
))
1040 CHECK_STRING (registry
, 2);
1041 elt
= Fcons (make_number (from
), Fcons (family
, registry
));
1044 /* The arg FRAME is kept for backward compatibility. We only check
1047 CHECK_LIVE_FRAME (frame
, 3);
1049 for (; from
<= to
; from
++)
1050 FONTSET_SET (fontset
, from
, elt
);
1051 Foptimize_char_table (fontset
);
1053 /* If there's a realized fontset REALIZED whose parent is FONTSET,
1054 clear all the elements of REALIZED and free all multibyte faces
1055 whose fontset is REALIZED. This way, the specified character(s)
1056 are surely redisplayed by a correct font. */
1057 for (id
= 0; id
< ASIZE (Vfontset_table
); id
++)
1059 realized
= AREF (Vfontset_table
, id
);
1060 if (!NILP (realized
)
1061 && !BASE_FONTSET_P (realized
)
1062 && EQ (FONTSET_BASE (realized
), fontset
))
1064 FRAME_PTR f
= XFRAME (FONTSET_FRAME (realized
));
1065 clear_fontset_elements (realized
);
1066 free_realized_multibyte_face (f
, id
);
1073 DEFUN ("font-info", Ffont_info
, Sfont_info
, 1, 2, 0,
1074 "Return information about a font named NAME on frame FRAME.\n\
1075 If FRAME is omitted or nil, use the selected frame.\n\
1076 The returned value is a vector of OPENED-NAME, FULL-NAME, CHARSET, SIZE,\n\
1077 HEIGHT, BASELINE-OFFSET, RELATIVE-COMPOSE, and DEFAULT-ASCENT,\n\
1079 OPENED-NAME is the name used for opening the font,\n\
1080 FULL-NAME is the full name of the font,\n\
1081 SIZE is the maximum bound width of the font,\n\
1082 HEIGHT is the height of the font,\n\
1083 BASELINE-OFFSET is the upward offset pixels from ASCII baseline,\n\
1084 RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling\n\
1085 how to compose characters.\n\
1086 If the named font is not yet loaded, return nil.")
1088 Lisp_Object name
, frame
;
1091 struct font_info
*fontp
;
1094 (*check_window_system_func
) ();
1096 CHECK_STRING (name
, 0);
1097 name
= Fdowncase (name
);
1099 frame
= selected_frame
;
1100 CHECK_LIVE_FRAME (frame
, 1);
1103 if (!query_font_func
)
1104 error ("Font query function is not supported");
1106 fontp
= (*query_font_func
) (f
, XSTRING (name
)->data
);
1110 info
= Fmake_vector (make_number (7), Qnil
);
1112 XVECTOR (info
)->contents
[0] = build_string (fontp
->name
);
1113 XVECTOR (info
)->contents
[1] = build_string (fontp
->full_name
);
1114 XVECTOR (info
)->contents
[2] = make_number (fontp
->size
);
1115 XVECTOR (info
)->contents
[3] = make_number (fontp
->height
);
1116 XVECTOR (info
)->contents
[4] = make_number (fontp
->baseline_offset
);
1117 XVECTOR (info
)->contents
[5] = make_number (fontp
->relative_compose
);
1118 XVECTOR (info
)->contents
[6] = make_number (fontp
->default_ascent
);
1124 /* Return the font name for the character at POSITION in the current
1125 buffer. This is computed from all the text properties and overlays
1126 that apply to POSITION. It returns nil in the following cases:
1128 (1) The window system doesn't have a font for the character (thus
1129 it is displayed by an empty box).
1131 (2) The character code is invalid.
1133 (3) The current buffer is not displayed in any window.
1135 In addition, the returned font name may not take into account of
1136 such redisplay engine hooks as what used in jit-lock-mode if
1137 POSITION is currently not visible. */
1140 DEFUN ("internal-char-font", Finternal_char_font
, Sinternal_char_font
, 1, 1, 0,
1141 "For internal use only.")
1143 Lisp_Object position
;
1145 int pos
, pos_byte
, dummy
;
1153 CHECK_NUMBER_COERCE_MARKER (position
, 0);
1154 pos
= XINT (position
);
1155 if (pos
< BEGV
|| pos
>= ZV
)
1156 args_out_of_range_3 (position
, make_number (BEGV
), make_number (ZV
));
1157 pos_byte
= CHAR_TO_BYTE (pos
);
1158 c
= FETCH_CHAR (pos_byte
);
1159 if (! CHAR_VALID_P (c
, 0))
1161 window
= Fget_buffer_window (Fcurrent_buffer (), Qt
);
1164 w
= XWINDOW (window
);
1165 f
= XFRAME (w
->frame
);
1166 face_id
= face_at_buffer_position (w
, pos
, -1, -1, &dummy
, pos
+ 100, 0);
1167 face_id
= FACE_FOR_CHAR (f
, FACE_FROM_ID (f
, face_id
), c
);
1168 face
= FACE_FROM_ID (f
, face_id
);
1169 return (face
->font
&& face
->font_name
1170 ? build_string (face
->font_name
)
1175 /* Called from Ffontset_info via map_char_table on each leaf of
1176 fontset. ARG is a list (LAST FONT-INFO ...), where LAST is `(last
1177 ARG)' and FONT-INFOs have this form:
1178 (CHAR FONT-SPEC) or ((FROM . TO) FONT-SPEC)
1179 The current leaf is indexed by CHARACTER and has value ELT. This
1180 function add the information of the current leaf to ARG by
1181 appending a new element or modifying the last element.. */
1184 accumulate_font_info (arg
, character
, elt
)
1185 Lisp_Object arg
, character
, elt
;
1187 Lisp_Object last
, last_char
, last_elt
, tmp
;
1189 if (!CONSP (elt
) && !SINGLE_BYTE_CHAR_P (XINT (character
)))
1190 elt
= FONTSET_REF (Vdefault_fontset
, XINT (character
));
1194 last_char
= XCAR (XCAR (last
));
1195 last_elt
= XCAR (XCDR (XCAR (last
)));
1197 if (!NILP (Fequal (elt
, last_elt
)))
1199 int this_charset
= CHAR_CHARSET (XINT (character
));
1201 if (CONSP (last_char
)) /* LAST_CHAR == (FROM . TO) */
1203 if (this_charset
== CHAR_CHARSET (XINT (XCAR (last_char
))))
1205 XCDR (last_char
) = character
;
1209 else if (XINT (last_char
) == XINT (character
))
1211 else if (this_charset
== CHAR_CHARSET (XINT (last_char
)))
1213 XCAR (XCAR (last
)) = Fcons (last_char
, character
);
1217 XCDR (last
) = Fcons (Fcons (character
, Fcons (elt
, Qnil
)), Qnil
);
1218 XCAR (arg
) = XCDR (last
);
1222 DEFUN ("fontset-info", Ffontset_info
, Sfontset_info
, 1, 2, 0,
1223 "Return information about a fontset named NAME on frame FRAME.\n\
1224 The value is a list:\n\
1225 \(FONTSET-NAME (CHARSET-OR-RANGE FONT-SPEC OPENED ...) ...),\n\
1227 FONTSET-NAME is a full name of the fontset.\n\
1228 CHARSET-OR-RANGE is a charset, a character (may be a generic character)\n\
1229 or a cons of two characters specifying the range of characters.\n\
1230 FONT-SPEC is a fontname pattern string or a cons (FAMILY . REGISTRY),\n\
1231 where FAMILY is a `FAMILY' field of a XLFD font name,\n\
1232 REGISTRY is a `CHARSET_REGISTRY' field of a XLDF font name.\n\
1233 FAMILY may contain a `FOUNDARY' field at the head.\n\
1234 REGISTRY may contain a `CHARSET_ENCODING' field at the tail.\n\
1235 OPENEDs are names of fonts actually opened.\n\
1236 If FRAME is omitted, it defaults to the currently selected frame.")
1238 Lisp_Object name
, frame
;
1240 Lisp_Object fontset
;
1242 Lisp_Object indices
[3];
1243 Lisp_Object val
, tail
, elt
;
1244 Lisp_Object
*realized
;
1248 (*check_window_system_func
) ();
1250 fontset
= check_fontset_name (name
);
1253 frame
= selected_frame
;
1254 CHECK_LIVE_FRAME (frame
, 1);
1257 /* Recode realized fontsets whose base is FONTSET in the table
1259 realized
= (Lisp_Object
*) alloca (sizeof (Lisp_Object
)
1260 * ASIZE (Vfontset_table
));
1261 for (i
= 0; i
< ASIZE (Vfontset_table
); i
++)
1263 elt
= FONTSET_FROM_ID (i
);
1265 && EQ (FONTSET_BASE (elt
), fontset
))
1266 realized
[n_realized
++] = elt
;
1269 /* Accumulate information of the fontset in VAL. The format is
1270 (LAST FONT-INFO FONT-INFO ...), where FONT-INFO is (CHAR-OR-RANGE
1271 FONT-SPEC). See the comment for accumulate_font_info for the
1273 val
= Fcons (Fcons (make_number (0),
1274 Fcons (XCDR (FONTSET_ASCII (fontset
)), Qnil
)),
1276 val
= Fcons (val
, val
);
1277 map_char_table (accumulate_font_info
, Qnil
, fontset
, val
, 0, indices
);
1280 /* For each FONT-INFO, if CHAR_OR_RANGE (car part) is a generic
1281 character for a charset, replace it with the charset symbol. If
1282 fonts are opened for FONT-SPEC, append the names of the fonts to
1284 for (tail
= val
; CONSP (tail
); tail
= XCDR (tail
))
1288 if (INTEGERP (XCAR (elt
)))
1290 int charset
, c1
, c2
;
1291 c
= XINT (XCAR (elt
));
1292 SPLIT_CHAR (c
, charset
, c1
, c2
);
1294 XCAR (elt
) = CHARSET_SYMBOL (charset
);
1297 c
= XINT (XCAR (XCAR (elt
)));
1298 for (i
= 0; i
< n_realized
; i
++)
1300 Lisp_Object face_id
, font
;
1303 face_id
= FONTSET_REF_VIA_BASE (realized
[i
], c
);
1304 if (INTEGERP (face_id
))
1306 face
= FACE_FROM_ID (f
, XINT (face_id
));
1307 if (face
->font
&& face
->font_name
)
1309 font
= build_string (face
->font_name
);
1310 if (NILP (Fmember (font
, XCDR (XCDR (elt
)))))
1311 XCDR (XCDR (elt
)) = Fcons (font
, XCDR (XCDR (elt
)));
1316 return Fcons (FONTSET_NAME (fontset
), val
);
1319 DEFUN ("fontset-font", Ffontset_font
, Sfontset_font
, 2, 2, 0,
1320 "Return a font name pattern for character CH in fontset NAME.\n\
1321 If NAME is t, find a font name pattern in the default fontset.")
1323 Lisp_Object name
, ch
;
1326 Lisp_Object fontset
, elt
;
1328 fontset
= check_fontset_name (name
);
1330 CHECK_NUMBER (ch
, 1);
1332 if (!char_valid_p (c
, 1))
1333 invalid_character (c
);
1335 elt
= FONTSET_REF (fontset
, c
);
1343 DEFUN ("fontset-list", Ffontset_list
, Sfontset_list
, 0, 0, 0,
1344 "Return a list of all defined fontset names.")
1347 Lisp_Object fontset
, list
;
1351 for (i
= 0; i
< ASIZE (Vfontset_table
); i
++)
1353 fontset
= FONTSET_FROM_ID (i
);
1355 && BASE_FONTSET_P (fontset
))
1356 list
= Fcons (FONTSET_NAME (fontset
), list
);
1367 if (!load_font_func
)
1368 /* Window system initializer should have set proper functions. */
1371 Qfontset
= intern ("fontset");
1372 staticpro (&Qfontset
);
1373 Fput (Qfontset
, Qchar_table_extra_slots
, make_number (3));
1375 Vcached_fontset_data
= Qnil
;
1376 staticpro (&Vcached_fontset_data
);
1378 Vfontset_table
= Fmake_vector (make_number (32), Qnil
);
1379 staticpro (&Vfontset_table
);
1381 Vdefault_fontset
= Fmake_char_table (Qfontset
, Qnil
);
1382 staticpro (&Vdefault_fontset
);
1383 FONTSET_ID (Vdefault_fontset
) = make_number (0);
1384 FONTSET_NAME (Vdefault_fontset
)
1385 = build_string ("-*-*-*-*-*-*-*-*-*-*-*-*-fontset-default");
1386 FONTSET_ASCII (Vdefault_fontset
)
1387 = Fcons (make_number (0),
1388 build_string ("-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1"));
1389 AREF (Vfontset_table
, 0) = Vdefault_fontset
;
1390 next_fontset_id
= 1;
1392 DEFVAR_LISP ("font-encoding-alist", &Vfont_encoding_alist
,
1393 "Alist of fontname patterns vs corresponding encoding info.\n\
1394 Each element looks like (REGEXP . ENCODING-INFO),\n\
1395 where ENCODING-INFO is an alist of CHARSET vs ENCODING.\n\
1396 ENCODING is one of the following integer values:\n\
1397 0: code points 0x20..0x7F or 0x2020..0x7F7F are used,\n\
1398 1: code points 0xA0..0xFF or 0xA0A0..0xFFFF are used,\n\
1399 2: code points 0x20A0..0x7FFF are used,\n\
1400 3: code points 0xA020..0xFF7F are used.");
1401 Vfont_encoding_alist
= Qnil
;
1403 DEFVAR_LISP ("use-default-ascent", &Vuse_default_ascent
,
1404 "Char table of characters whose ascent values should be ignored.\n\
1405 If an entry for a character is non-nil, the ascent value of the glyph\n\
1406 is assumed to be what specified by _MULE_DEFAULT_ASCENT property of a font.\n\
1408 This affects how a composite character which contains\n\
1409 such a character is displayed on screen.");
1410 Vuse_default_ascent
= Qnil
;
1412 DEFVAR_LISP ("ignore-relative-composition", &Vignore_relative_composition
,
1413 "Char table of characters which is not composed relatively.\n\
1414 If an entry for a character is non-nil, a composition sequence\n\
1415 which contains that character is displayed so that\n\
1416 the glyph of that character is put without considering\n\
1417 an ascent and descent value of a previous character.");
1418 Vignore_relative_composition
= Qnil
;
1420 DEFVAR_LISP ("alternate-fontname-alist", &Valternate_fontname_alist
,
1421 "Alist of fontname vs list of the alternate fontnames.\n\
1422 When a specified font name is not found, the corresponding\n\
1423 alternate fontnames (if any) are tried instead.");
1424 Valternate_fontname_alist
= Qnil
;
1426 DEFVAR_LISP ("fontset-alias-alist", &Vfontset_alias_alist
,
1427 "Alist of fontset names vs the aliases.");
1428 Vfontset_alias_alist
= Fcons (Fcons (FONTSET_NAME (Vdefault_fontset
),
1429 build_string ("fontset-default")),
1432 DEFVAR_LISP ("highlight-wrong-size-font", &Vhighlight_wrong_size_font
,
1433 "*Non-nil means highlight characters shown in wrong size fonts somehow.\n\
1434 The way to highlight them depends on window system on which Emacs runs.\n\
1435 On X11, a rectangle is shown around each such character.");
1436 Vhighlight_wrong_size_font
= Qnil
;
1438 DEFVAR_LISP ("clip-large-size-font", &Vclip_large_size_font
,
1439 "*Non-nil means characters shown in overlarge fonts are clipped.\n\
1440 The height of clipping area is the same as that of an ASCII character.\n\
1441 The width of the area is the same as that of an ASCII character,\n\
1442 or twice as wide, depending on the character set's column-width.\n\
1444 If the only font you have for a specific character set is too large,\n\
1445 and clipping these characters makes them hard to read,\n\
1446 you can set this variable to nil to display the characters without clipping.\n\
1447 The drawback is that you will get some garbage left on your screen.");
1448 Vclip_large_size_font
= Qt
;
1450 DEFVAR_LISP ("vertical-centering-font-regexp",
1451 &Vvertical_centering_font_regexp
,
1452 "*Regexp matching font names that require vertical centering on display.\n\
1453 When a character is displayed with such fonts, the character is displayed\n\
1454 at the vertival center of lines.");
1455 Vvertical_centering_font_regexp
= Qnil
;
1457 defsubr (&Squery_fontset
);
1458 defsubr (&Snew_fontset
);
1459 defsubr (&Sset_fontset_font
);
1460 defsubr (&Sfont_info
);
1461 defsubr (&Sinternal_char_font
);
1462 defsubr (&Sfontset_info
);
1463 defsubr (&Sfontset_font
);
1464 defsubr (&Sfontset_list
);