/* Fontset handler.
- Ver.1.0
- Copyright (C) 1995 Free Software Foundation, Inc.
- Copyright (C) 1995 Electrotechnical Laboratory, JAPAN.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1997, 2000 Electrotechnical Laboratory, JAPAN.
+ Licensed to the Free Software Foundation.
+ Copyright (C) 2003
+ National Institute of Advanced Industrial Science and Technology (AIST)
+ Registration Number H13PRO009
This file is part of GNU Emacs.
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+/* #define FONTSET_DEBUG */
+
#include <config.h>
-#if HAVE_ALLOCA_H
-#include <alloca.h>
-#endif /* HAVE_ALLOCA_H */
+
+#ifdef FONTSET_DEBUG
+#include <stdio.h>
+#endif
+
#include "lisp.h"
+#include "blockinput.h"
+#include "buffer.h"
+#include "character.h"
#include "charset.h"
#include "ccl.h"
-#include "fontset.h"
+#include "keyboard.h"
#include "frame.h"
+#include "dispextern.h"
+#include "intervals.h"
+#include "fontset.h"
+#include "window.h"
+#ifdef HAVE_X_WINDOWS
+#include "xterm.h"
+#endif
+#ifdef WINDOWSNT
+#include "w32term.h"
+#endif
+#ifdef MAC_OS
+#include "macterm.h"
+#endif
-Lisp_Object Vglobal_fontset_alist;
-Lisp_Object Vfont_encoding_alist;
-Lisp_Object Vuse_default_ascent;
-Lisp_Object Valternative_fontname_alist;
+#undef xassert
+#ifdef FONTSET_DEBUG
+#define xassert(X) do {if (!(X)) abort ();} while (0)
+#undef INLINE
+#define INLINE
+#else /* not FONTSET_DEBUG */
+#define xassert(X) (void) 0
+#endif /* not FONTSET_DEBUG */
-/* We had better have our own strcasecmp function because some system
- doesn't have it. */
-static char my_strcasetbl[256];
+EXFUN (Fclear_face_cache, 1);
-/* Compare two strings S0 and S1 while ignoring differences in case.
- Return 1 if they differ, else return 0. */
-static int
-my_strcasecmp (s0, s1)
- unsigned char *s0, *s1;
-{
- while (*s0)
- if (my_strcasetbl[*s0++] != my_strcasetbl[*s1++]) return 1;
- return (int) *s1;
-}
+/* FONTSET
+
+ A fontset is a collection of font related information to give
+ similar appearance (style, etc) of characters. A fontset has two
+ roles. One is to use for the frame parameter `font' as if it is an
+ ASCII font. In that case, Emacs uses the font specified for
+ `ascii' script for the frame's default font.
+
+ Another role, the more important one, is to provide information
+ about which font to use for each non-ASCII character.
+
+ There are two kinds of fontsets; base and realized. A base fontset
+ is created by `new-fontset' from Emacs Lisp explicitly. A realized
+ fontset is created implicitly when a face is realized for ASCII
+ characters. A face is also realized for non-ASCII characters based
+ on an ASCII face. All of non-ASCII faces based on the same ASCII
+ face share the same realized fontset.
+
+ A fontset object is implemented by a char-table whose default value
+ and parent are always nil.
+
+ An element of a base fontset is a vector of FONT-DEFs which itself
+ is a vector [ FONT-SPEC ENCODING REPERTORY ].
+
+ FONT-SPEC is:
+ [ FAMILY WEIGHT SLANT SWIDTH ADSTYLE REGISTRY ]
+ or
+ FONT-NAME
+ where FAMILY, WEIGHT, SLANT, SWIDTH, ADSTYLE, REGISTRY, and
+ FONT-NAME are strings.
+
+ Note: Currently WEIGHT through ADSTYLE are ignored.
+
+ ENCODING is a charset ID that can convert characters to glyph codes
+ of the corresponding font.
+
+ REPERTORY is a charset ID, a char-table, or nil. If REPERTORY is a
+ charset ID, the repertory of the charset exactly matches with that
+ of the font. If REPERTORY is a char-table, all characters who have
+ a non-nil value in the table are supported. If REPERTORY is nil,
+ we consult with the font itself to get the repertory.
+
+ ENCODING and REPERTORY are extracted from the variable
+ Vfont_encoding_alist by using a font name generated from FONT-SPEC
+ (if it is a vector) or FONT-NAME as a matching target.
+
+
+ An element of a realized fontset is nil or t, or has this form:
+
+ [CHARSET-ORDERED-LIST-TICK PREFERRED-CHARSET-ID
+ PREFERRED-RFONT-DEF RFONT-DEF0 RFONT-DEF1 ...].
+
+ RFONT-DEFn (i.e. Realized FONT-DEF) has this form:
+
+ [ FACE-ID FONT-INDEX FONT-DEF OPENED-FONT-NAME ]
+
+ RFONT-DEFn is automatically reordered by the current charset
+ priority list.
+
+ The value nil means that we have not yet generated the above vector
+ from the base of the fontset.
+
+ The value t means that no font is available for the corresponding
+ range of characters.
+
+
+ A fontset has 9 extra slots.
+
+ The 1st slot: the ID number of the fontset
+
+ The 2nd slot:
+ base: the name of the fontset
+ realized: nil
+
+ The 3rd slot:
+ base: nil
+ realized: the base fontset
+
+ The 4th slot:
+ base: nil
+ realized: the frame that the fontset belongs to
+
+ The 5th slot:
+ base: the font name for ASCII characters
+ realized: nil
+
+ The 6th slot:
+ base: nil
+ realized: the ID number of a face to use for characters that
+ has no font in a realized fontset.
+
+ The 7th slot:
+ base: nil
+ realized: Alist of font index vs the corresponding repertory
+ char-table.
+
+ The 8th slot:
+ base: nil
+ realized: If the base is not the default fontset, a fontset
+ realized from the default fontset, else nil.
+
+ The 9th slot:
+ base: Same as element value (but for fallback fonts).
+ realized: Likewise.
+
+ All fontsets are recorded in the vector Vfontset_table.
+
+
+ DEFAULT FONTSET
+
+ There's a special base fontset named `default fontset' which
+ defines the default font specifications. When a base fontset
+ doesn't specify a font for a specific character, the corresponding
+ value in the default fontset is used.
+
+ The parent of a realized fontset created for such a face that has
+ no fontset is the default fontset.
+
+
+ These structures are hidden from the other codes than this file.
+ The other codes handle fontsets only by their ID numbers. They
+ usually use the variable name `fontset' for IDs. But, in this
+ file, we always use varialbe name `id' for IDs, and name `fontset'
+ for an actual fontset object, i.e., char-table.
+
+*/
+
+/********** VARIABLES and FUNCTION PROTOTYPES **********/
+
+extern Lisp_Object Qfont;
+static Lisp_Object Qfontset;
+static Lisp_Object Qfontset_info;
+static Lisp_Object Qprepend, Qappend;
+
+/* Vector containing all fontsets. */
+static Lisp_Object Vfontset_table;
+
+/* Next possibly free fontset ID. Usually this keeps the minimum
+ fontset ID not yet used. */
+static int next_fontset_id;
+
+/* The default fontset. This gives default FAMILY and REGISTRY of
+ font for each character. */
+static Lisp_Object Vdefault_fontset;
+
+Lisp_Object Vfont_encoding_alist;
+Lisp_Object Vuse_default_ascent;
+Lisp_Object Vignore_relative_composition;
+Lisp_Object Valternate_fontname_alist;
+Lisp_Object Vfontset_alias_alist;
+Lisp_Object Vvertical_centering_font_regexp;
-/* The following six are window system dependent functions. See
- the comments in src/fontset.h for more detail. */
+/* The following six are declarations of callback functions depending
+ on window system. See the comments in src/fontset.h for more
+ detail. */
/* Return a pointer to struct font_info of font FONT_IDX of frame F. */
-struct font_info *(*get_font_info_func) (/* FRAME_PTR f; int font_idx */);
+struct font_info *(*get_font_info_func) P_ ((FRAME_PTR f, int font_idx));
-/* Return a list of font names which matches PATTERN. See the document of
- `x-list-fonts' for more detail. */
-Lisp_Object (*list_fonts_func) (/* Lisp_Object pattern, face, frame, width */);
+/* Return a list of font names which matches PATTERN. See the documentation
+ of `x-list-fonts' for more details. */
+Lisp_Object (*list_fonts_func) P_ ((struct frame *f,
+ Lisp_Object pattern,
+ int size,
+ int maxnames));
/* Load a font named NAME for frame F and return a pointer to the
information of the loaded font. If loading is failed, return 0. */
-struct font_info *(*load_font_func) (/* FRAME_PTR f; char *name */);
+struct font_info *(*load_font_func) P_ ((FRAME_PTR f, char *name, int));
/* Return a pointer to struct font_info of a font named NAME for frame F. */
-struct font_info *(*query_font_func) (/* FRAME_PTR f; char *name */);
+struct font_info *(*query_font_func) P_ ((FRAME_PTR f, char *name));
/* Additional function for setting fontset or changing fontset
contents of frame F. */
-void (*set_frame_fontset_func) (/* FRAME_PTR f; Lisp_Object arg, oldval */);
+void (*set_frame_fontset_func) P_ ((FRAME_PTR f, Lisp_Object arg,
+ Lisp_Object oldval));
+
+/* To find a CCL program, fs_load_font calls this function.
+ The argument is a pointer to the struct font_info.
+ This function set the member `encoder' of the structure. */
+void (*find_ccl_program_func) P_ ((struct font_info *));
+
+Lisp_Object (*get_font_repertory_func) P_ ((struct frame *,
+ struct font_info *));
/* Check if any window system is used now. */
-void (*check_window_system_func) ();
+void (*check_window_system_func) P_ ((void));
+
+
+/* Prototype declarations for static functions. */
+static Lisp_Object fontset_add P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
+ Lisp_Object));
+static Lisp_Object fontset_font P_ ((Lisp_Object, int, struct face *, int));
+static Lisp_Object make_fontset P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
+static Lisp_Object fontset_pattern_regexp P_ ((Lisp_Object));
+static void accumulate_script_ranges P_ ((Lisp_Object, Lisp_Object,
+ Lisp_Object));
+static Lisp_Object find_font_encoding P_ ((Lisp_Object));
+
+static void set_fontset_font P_ ((Lisp_Object, Lisp_Object));
+
+#ifdef FONTSET_DEBUG
+
+/* Return 1 if ID is a valid fontset id, else return 0. */
+
+static int
+fontset_id_valid_p (id)
+ int id;
+{
+ return (id >= 0 && id < ASIZE (Vfontset_table) - 1);
+}
+
+#endif
+
+
+\f
+/********** MACROS AND FUNCTIONS TO HANDLE FONTSET **********/
+
+/* Return the fontset with ID. No check of ID's validness. */
+#define FONTSET_FROM_ID(id) AREF (Vfontset_table, id)
+
+/* Macros to access special values of FONTSET. */
+#define FONTSET_ID(fontset) XCHAR_TABLE (fontset)->extras[0]
+
+/* Macros to access special values of (base) FONTSET. */
+#define FONTSET_NAME(fontset) XCHAR_TABLE (fontset)->extras[1]
+#define FONTSET_ASCII(fontset) XCHAR_TABLE (fontset)->extras[4]
+
+/* Macros to access special values of (realized) FONTSET. */
+#define FONTSET_BASE(fontset) XCHAR_TABLE (fontset)->extras[2]
+#define FONTSET_FRAME(fontset) XCHAR_TABLE (fontset)->extras[3]
+#define FONTSET_NOFONT_FACE(fontset) XCHAR_TABLE (fontset)->extras[5]
+#define FONTSET_REPERTORY(fontset) XCHAR_TABLE (fontset)->extras[6]
+#define FONTSET_DEFAULT(fontset) XCHAR_TABLE (fontset)->extras[7]
+
+/* For both base and realized fontset. */
+#define FONTSET_FALLBACK(fontset) XCHAR_TABLE (fontset)->extras[8]
+
+#define BASE_FONTSET_P(fontset) (NILP (FONTSET_BASE (fontset)))
+
+
+/* Return the element of FONTSET for the character C. If FONTSET is a
+ base fontset other then the default fontset and FONTSET doesn't
+ contain information for C, return the information in the default
+ fontset. */
+
+#define FONTSET_REF(fontset, c) \
+ (EQ (fontset, Vdefault_fontset) \
+ ? CHAR_TABLE_REF (fontset, c) \
+ : fontset_ref ((fontset), (c)))
+
+static Lisp_Object
+fontset_ref (fontset, c)
+ Lisp_Object fontset;
+ int c;
+{
+ Lisp_Object elt;
+
+ elt = CHAR_TABLE_REF (fontset, c);
+ if (NILP (elt) && ! EQ (fontset, Vdefault_fontset)
+ /* Don't check Vdefault_fontset for a realized fontset. */
+ && NILP (FONTSET_BASE (fontset)))
+ elt = CHAR_TABLE_REF (Vdefault_fontset, c);
+ return elt;
+}
+
+
+/* Return the element of FONTSET for the character C, set FROM and TO
+ to the range of characters around C that have the same value as C.
+ If FONTSET is a base fontset other then the default fontset and
+ FONTSET doesn't contain information for C, return the information
+ in the default fontset. */
+
+#define FONTSET_REF_AND_RANGE(fontset, c, form, to) \
+ (EQ (fontset, Vdefault_fontset) \
+ ? char_table_ref_and_range (fontset, c, &from, &to) \
+ : fontset_ref_and_range (fontset, c, &from, &to))
+
+static Lisp_Object
+fontset_ref_and_range (fontset, c, from, to)
+ Lisp_Object fontset;
+ int c;
+ int *from, *to;
+{
+ Lisp_Object elt;
+
+ elt = char_table_ref_and_range (fontset, c, from, to);
+ if (NILP (elt) && ! EQ (fontset, Vdefault_fontset)
+ /* Don't check Vdefault_fontset for a realized fontset. */
+ && NILP (FONTSET_BASE (fontset)))
+ {
+ int from1, to1;
+
+ elt = char_table_ref_and_range (Vdefault_fontset, c, &from1, &to1);
+ if (*from < from1)
+ *from = from1;
+ if (*to > to1)
+ *to = to1;
+ }
+ return elt;
+}
+
+
+/* Set elements of FONTSET for characters in RANGE to the value ELT.
+ RANGE is a cons (FROM . TO), where FROM and TO are character codes
+ specifying a range. */
+
+#define FONTSET_SET(fontset, range, elt) \
+ Fset_char_table_range ((fontset), (range), (elt))
+
+
+/* Modify the elements of FONTSET for characters in RANGE by replacing
+ with ELT or adding ELT. RANGE is a cons (FROM . TO), where FROM
+ and TO are character codes specifying a range. If ADD is nil,
+ replace with ELT, if ADD is `prepend', prepend ELT, otherwise,
+ append ELT. */
+
+#define FONTSET_ADD(fontset, range, elt, add) \
+ (NILP (add) \
+ ? (NILP (range) \
+ ? (FONTSET_FALLBACK (fontset) = Fmake_vector (make_number (1), (elt))) \
+ : Fset_char_table_range ((fontset), (range), \
+ Fmake_vector (make_number (1), (elt)))) \
+ : fontset_add ((fontset), (range), (elt), (add)))
+
+static Lisp_Object
+fontset_add (fontset, range, elt, add)
+ Lisp_Object fontset, range, elt, add;
+{
+ Lisp_Object args[2];
+ int idx = (EQ (add, Qappend) ? 0 : 1);
+
+ args[1 - idx] = Fmake_vector (make_number (1), elt);
+
+ if (CONSP (range))
+ {
+ int from = XINT (XCAR (range));
+ int to = XINT (XCDR (range));
+ int from1, to1;
+
+ do {
+ args[idx] = char_table_ref_and_range (fontset, from, &from1, &to1);
+ if (to < to1)
+ to1 = to;
+ char_table_set_range (fontset, from, to1,
+ NILP (args[idx]) ? args[1 - idx]
+ : Fvconcat (2, args));
+ from = to1 + 1;
+ } while (from < to);
+ }
+ else
+ {
+ args[idx] = FONTSET_FALLBACK (fontset);
+ FONTSET_FALLBACK (fontset)
+ = NILP (args[idx]) ? args[1 - idx] : Fvconcat (2, args);
+ }
+ return Qnil;
+}
+
-struct fontset_data *
-alloc_fontset_data ()
+/* Update FONTSET_ELEMENT which has this form:
+ [CHARSET-ORDERED-LIST-TICK PREFERRED-CHARSET-ID PREFERRED-RFONT-DEF
+ RFONT-DEF0 RFONT-DEF1 ...].
+ Reorder RFONT-DEFs according to the current order of charset
+ (Vcharset_ordered_list), and update CHARSET-ORDERED-LIST-TICK to
+ the latest value. */
+
+static void
+reorder_font_vector (fontset_element)
+ Lisp_Object fontset_element;
+{
+ Lisp_Object list, *new_vec;
+ Lisp_Object font_def;
+ int size;
+ int *charset_id_table;
+ int i, idx;
+
+ ASET (fontset_element, 0, make_number (charset_ordered_list_tick));
+ size = ASIZE (fontset_element) - 3;
+ if (size <= 1)
+ /* No need to reorder VEC. */
+ return;
+ charset_id_table = (int *) alloca (sizeof (int) * size);
+ new_vec = (Lisp_Object *) alloca (sizeof (Lisp_Object) * size);
+
+ /* At first, extract ENCODING (a chaset ID) from each FONT-DEF.
+ FONT-DEF has this form:
+ [FACE-ID FONT-INDEX [ FONT-SPEC ENCODING REPERTORY ]] */
+ for (i = 0; i < size; i++)
+ {
+ font_def = AREF (fontset_element, i + 3);
+ charset_id_table[i] = XINT (AREF (AREF (font_def, 2), 1));
+ }
+
+ /* Then, store FONT-DEFs in NEW_VEC in the correct order. */
+ for (idx = 0, list = Vcharset_ordered_list;
+ idx < size && CONSP (list); list = XCDR (list))
+ {
+ for (i = 0; i < size; i++)
+ if (charset_id_table[i] == XINT (XCAR (list)))
+ new_vec[idx++] = AREF (fontset_element, i + 3);
+ }
+
+ /* At last, update FONT-DEFs. */
+ for (i = 0; i < size; i++)
+ ASET (fontset_element, i + 3, new_vec[i]);
+}
+
+
+/* Load a font matching the font related attributes in FACE->lface and
+ font pattern in FONT_DEF of FONTSET, and return an index of the
+ font. FONT_DEF has this form:
+ [ FONT-SPEC ENCODING REPERTORY ]
+ If REPERTORY is nil, generate a char-table representing the font
+ repertory by looking into the font itself. */
+
+static int
+load_font_get_repertory (f, face, font_def, fontset)
+ FRAME_PTR f;
+ struct face *face;
+ Lisp_Object font_def;
+ Lisp_Object fontset;
+{
+ char *font_name;
+ struct font_info *font_info;
+ int charset;
+
+ font_name = choose_face_font (f, face->lface, AREF (font_def, 0), NULL);
+ charset = XINT (AREF (font_def, 1));
+ if (! (font_info = fs_load_font (f, font_name, charset)))
+ return -1;
+
+ if (NILP (AREF (font_def, 2))
+ && NILP (Fassq (make_number (font_info->font_idx),
+ FONTSET_REPERTORY (fontset))))
+ {
+ /* We must look into the font to get the correct repertory as a
+ char-table. */
+ Lisp_Object repertory;
+
+ repertory = (*get_font_repertory_func) (f, font_info);
+ FONTSET_REPERTORY (fontset)
+ = Fcons (Fcons (make_number (font_info->font_idx), repertory),
+ FONTSET_REPERTORY (fontset));
+ }
+
+ return font_info->font_idx;
+}
+
+
+/* Return RFONT-DEF (vector) in the realized fontset FONTSET for the
+ character C. If the corresponding font is not yet opened, open it
+ (if FACE is not NULL) or return Qnil (if FACE is NULL).
+ If no proper font is found for C, return Qnil. */
+
+static Lisp_Object
+fontset_font (fontset, c, face, id)
+ Lisp_Object fontset;
+ int c;
+ struct face *face;
+ int id;
+{
+ Lisp_Object base_fontset, elt, vec;
+ int i, from, to;
+ int font_idx;
+ FRAME_PTR f = XFRAME (FONTSET_FRAME (fontset));
+
+ base_fontset = FONTSET_BASE (fontset);
+ vec = CHAR_TABLE_REF (fontset, c);
+ if (EQ (vec, Qt))
+ goto try_fallback;
+
+ if (NILP (vec))
+ {
+ /* We have not yet decided a face for C. */
+ Lisp_Object range;
+
+ if (! face)
+ return Qnil;
+ elt = FONTSET_REF_AND_RANGE (base_fontset, c, from, to);
+ range = Fcons (make_number (from), make_number (to));
+ if (NILP (elt))
+ {
+ /* Record that we have no font for characters of this
+ range. */
+ vec = Qt;
+ FONTSET_SET (fontset, range, vec);
+ goto try_fallback;
+ }
+ /* Build a vector [ -1 -1 nil NEW-ELT0 NEW-ELT1 NEW-ELT2 ... ],
+ where the first -1 is to force reordering of NEW-ELTn,
+ NEW-ETLn is [nil nil AREF (elt, n) nil]. */
+ vec = Fmake_vector (make_number (ASIZE (elt) + 3), make_number (-1));
+ ASET (vec, 2, Qnil);
+ for (i = 0; i < ASIZE (elt); i++)
+ {
+ Lisp_Object tmp;
+
+ tmp = Fmake_vector (make_number (4), Qnil);
+ ASET (tmp, 2, AREF (elt, i));
+ ASET (vec, 3 + i, tmp);
+ }
+ /* Then store it in the fontset. */
+ FONTSET_SET (fontset, range, vec);
+ }
+
+ retry:
+ if (XINT (AREF (vec, 0)) != charset_ordered_list_tick)
+ /* The priority of charsets is changed after we selected a face
+ for C last time. */
+ reorder_font_vector (vec);
+
+ if (id < 0)
+ i = 3;
+ else if (id == XFASTINT (AREF (vec, 1)))
+ i = 2;
+ else
+ {
+ ASET (vec, 1, make_number (id));
+ for (i = 3; i < ASIZE (vec); i++)
+ if (id == XFASTINT (AREF (AREF (AREF (vec, i), 2), 1)))
+ break;
+ if (i < ASIZE (vec))
+ {
+ ASET (vec, 2, AREF (vec, i));
+ i = 2;
+ }
+ else
+ {
+ ASET (vec, 2, Qnil);
+ i = 3;
+ }
+ }
+
+ /* Find the first available font in the vector of RFONT-DEF. */
+ for (; i < ASIZE (vec); i++)
+ {
+ Lisp_Object font_def;
+
+ elt = AREF (vec, i);
+ if (NILP (elt))
+ continue;
+ /* ELT == [ FACE-ID FONT-INDEX FONT-DEF OPENED-FONT-NAME ] */
+ if (INTEGERP (AREF (elt, 1)) && XINT (AREF (elt, 1)) < 0)
+ /* We couldn't open this font last time. */
+ continue;
+
+ if (!face && NILP (AREF (elt, 1)))
+ /* We have not yet opened the font. */
+ return Qnil;
+
+ font_def = AREF (elt, 2);
+ /* FONT_DEF == [ FONT-SPEC ENCODING REPERTORY ] */
+ if (INTEGERP (AREF (font_def, 2)))
+ {
+ /* The repertory is specified by charset ID. */
+ struct charset *charset
+ = CHARSET_FROM_ID (XINT (AREF (font_def, 2)));
+
+ if (! CHAR_CHARSET_P (c, charset))
+ /* This font can't display C. */
+ continue;
+ }
+ else if (CHAR_TABLE_P (AREF (font_def, 2)))
+ {
+ /* The repertory is specified by a char table. */
+ if (NILP (CHAR_TABLE_REF (AREF (font_def, 2), c)))
+ /* This font can't display C. */
+ continue;
+ }
+ else
+ {
+ Lisp_Object slot;
+
+ if (! INTEGERP (AREF (elt, 1)))
+ {
+ /* We have not yet opened a font matching this spec.
+ Open the best matching font now and register the
+ repertory. */
+ struct font_info *font_info;
+
+ font_idx = load_font_get_repertory (f, face, font_def, fontset);
+ ASET (elt, 1, make_number (font_idx));
+ if (font_idx < 0)
+ /* This means that we couldn't find a font matching
+ FONT_DEF. */
+ continue;
+ font_info = (*get_font_info_func) (f, font_idx);
+ ASET (elt, 3, build_string (font_info->full_name));
+ }
+
+ slot = Fassq (AREF (elt, 1), FONTSET_REPERTORY (fontset));
+ xassert (CONSP (slot));
+ if (NILP (CHAR_TABLE_REF (XCDR (slot), c)))
+ /* This font can't display C. */
+ continue;
+ }
+
+ /* Now we have decided to use this font spec to display C. */
+ if (! INTEGERP (AREF (elt, 1)))
+ {
+ /* But not yet opened the best matching font. */
+ struct font_info *font_info;
+
+ font_idx = load_font_get_repertory (f, face, font_def, fontset);
+ ASET (elt, 1, make_number (font_idx));
+ if (font_idx < 0)
+ /* Can't open it. Try the other one. */
+ continue;
+ font_info = (*get_font_info_func) (f, font_idx);
+ ASET (elt, 3, build_string (font_info->full_name));
+ }
+
+ /* Now we have the opened font. */
+ return elt;
+ }
+
+ try_fallback:
+ if (! EQ (vec, FONTSET_FALLBACK (fontset)))
+ {
+ vec = FONTSET_FALLBACK (fontset);
+ if (VECTORP (vec))
+ goto retry;
+ if (EQ (vec, Qt))
+ goto try_default;
+ elt = FONTSET_FALLBACK (base_fontset);
+ if (! NILP (elt))
+ {
+ vec = Fmake_vector (make_number (ASIZE (elt) + 3), make_number (-1));
+ ASET (vec, 2, Qnil);
+ for (i = 0; i < ASIZE (elt); i++)
+ {
+ Lisp_Object tmp;
+
+ tmp = Fmake_vector (make_number (4), Qnil);
+ ASET (tmp, 2, AREF (elt, i));
+ ASET (vec, 3 + i, tmp);
+ }
+ FONTSET_FALLBACK (fontset) = vec;
+ goto retry;
+ }
+ /* Record that this fontset has no fallback fonts. */
+ FONTSET_FALLBACK (fontset) = Qt;
+ }
+
+ /* Try the default fontset. */
+ try_default:
+ if (! EQ (base_fontset, Vdefault_fontset))
+ {
+ if (NILP (FONTSET_DEFAULT (fontset)))
+ FONTSET_DEFAULT (fontset)
+ = make_fontset (FONTSET_FRAME (fontset), Qnil, Vdefault_fontset);
+ return fontset_font (FONTSET_DEFAULT (fontset), c, face, id);
+ }
+ return Qnil;
+}
+
+
+/* Return a newly created fontset with NAME. If BASE is nil, make a
+ base fontset. Otherwise make a realized fontset whose base is
+ BASE. */
+
+static Lisp_Object
+make_fontset (frame, name, base)
+ Lisp_Object frame, name, base;
{
- struct fontset_data *fontset_data
- = (struct fontset_data *) xmalloc (sizeof (struct fontset_data));
+ Lisp_Object fontset;
+ int size = ASIZE (Vfontset_table);
+ int id = next_fontset_id;
+
+ /* Find a free slot in Vfontset_table. Usually, next_fontset_id is
+ the next available fontset ID. So it is expected that this loop
+ terminates quickly. In addition, as the last element of
+ Vfontset_table is always nil, we don't have to check the range of
+ id. */
+ while (!NILP (AREF (Vfontset_table, id))) id++;
+
+ if (id + 1 == size)
+ {
+ /* We must grow Vfontset_table. */
+ Lisp_Object tem;
+ int i;
- bzero (fontset_data, sizeof (struct fontset_data));
+ tem = Fmake_vector (make_number (size + 32), Qnil);
+ for (i = 0; i < size; i++)
+ AREF (tem, i) = AREF (Vfontset_table, i);
+ Vfontset_table = tem;
+ }
+
+ fontset = Fmake_char_table (Qfontset, Qnil);
+
+ FONTSET_ID (fontset) = make_number (id);
+ if (NILP (base))
+ {
+ FONTSET_NAME (fontset) = name;
+ }
+ else
+ {
+ FONTSET_NAME (fontset) = Qnil;
+ FONTSET_FRAME (fontset) = frame;
+ FONTSET_BASE (fontset) = base;
+ }
- return fontset_data;
+ ASET (Vfontset_table, id, fontset);
+ next_fontset_id = id + 1;
+ return fontset;
}
+
+/* Set the ASCII font of the default fontset to FONTNAME if that is
+ not yet set. */
void
-free_fontset_data (fontset_data)
- struct fontset_data *fontset_data;
+set_default_ascii_font (fontname)
+ Lisp_Object fontname;
{
- int i;
+ if (! CONSP (FONTSET_ASCII (Vdefault_fontset)))
+ {
+ int id = fs_query_fontset (fontname, 2);
+
+ if (id >= 0)
+ fontname = XCDR (FONTSET_ASCII (FONTSET_FROM_ID (id)));
+ FONTSET_ASCII (Vdefault_fontset)
+ = Fcons (make_number (0), fontname);
+ }
+}
+
+\f
+/********** INTERFACES TO xfaces.c, xfns.c, and dispextern.h **********/
+
+/* Return the name of the fontset who has ID. */
+
+Lisp_Object
+fontset_name (id)
+ int id;
+{
+ Lisp_Object fontset;
+
+ fontset = FONTSET_FROM_ID (id);
+ return FONTSET_NAME (fontset);
+}
+
+
+/* Return the ASCII font name of the fontset who has ID. */
+
+Lisp_Object
+fontset_ascii (id)
+ int id;
+{
+ Lisp_Object fontset, elt;
+
+ fontset= FONTSET_FROM_ID (id);
+ elt = FONTSET_ASCII (fontset);
+ /* It is assured that ELT is always a string (i.e. fontname
+ pattern). */
+ return elt;
+}
- for (i = 0; i < fontset_data->n_fontsets; i++)
+
+/* Free fontset of FACE defined on frame F. Called from
+ free_realized_face. */
+
+void
+free_face_fontset (f, face)
+ FRAME_PTR f;
+ struct face *face;
+{
+ Lisp_Object fontset;
+
+ fontset = AREF (Vfontset_table, face->fontset);
+ xassert (!NILP (fontset) && ! BASE_FONTSET_P (fontset));
+ xassert (f == XFRAME (FONTSET_FRAME (fontset)));
+ ASET (Vfontset_table, face->fontset, Qnil);
+ if (face->fontset < next_fontset_id)
+ next_fontset_id = face->fontset;
+ if (! NILP (FONTSET_DEFAULT (fontset)))
{
- int j;
+ int id = XINT (FONTSET_ID (FONTSET_DEFAULT (fontset)));
+
+ fontset = AREF (Vfontset_table, id);
+ xassert (!NILP (fontset) && ! BASE_FONTSET_P (fontset));
+ xassert (f == XFRAME (FONTSET_FRAME (fontset)));
+ ASET (Vfontset_table, id, Qnil);
+ if (id < next_fontset_id)
+ next_fontset_id = face->fontset;
+ }
+}
- xfree (fontset_data->fontset_table[i]->name);
- for (j = 0; j <= MAX_CHARSET; j++)
- if (fontset_data->fontset_table[i]->fontname[j])
- xfree (fontset_data->fontset_table[i]->fontname[j]);
- xfree (fontset_data->fontset_table[i]);
+
+/* Return 1 iff FACE is suitable for displaying character C.
+ Otherwise return 0. Called from the macro FACE_SUITABLE_FOR_CHAR_P
+ when C is not an ASCII character. */
+
+int
+face_suitable_for_char_p (face, c)
+ struct face *face;
+ int c;
+{
+ Lisp_Object fontset, rfont_def;
+
+ fontset = FONTSET_FROM_ID (face->fontset);
+ rfont_def = fontset_font (fontset, c, NULL, -1);
+ return (VECTORP (rfont_def)
+ && INTEGERP (AREF (rfont_def, 0))
+ && face->id == XINT (AREF (rfont_def, 0)));
+}
+
+
+/* Return ID of face suitable for displaying character C on frame F.
+ FACE must be reazlied for ASCII characters in advance. Called from
+ the macro FACE_FOR_CHAR. */
+
+int
+face_for_char (f, face, c, pos, object)
+ FRAME_PTR f;
+ struct face *face;
+ int c, pos;
+ Lisp_Object object;
+{
+ Lisp_Object fontset, charset, rfont_def;
+ int face_id;
+ int id;
+
+ if (ASCII_CHAR_P (c))
+ return face->ascii_face->id;
+
+ xassert (fontset_id_valid_p (face->fontset));
+ fontset = FONTSET_FROM_ID (face->fontset);
+ xassert (!BASE_FONTSET_P (fontset));
+ if (pos < 0)
+ id = -1;
+ else
+ {
+ charset = Fget_char_property (make_number (pos), Qcharset, object);
+ if (NILP (charset))
+ id = -1;
+ else if (CHARSETP (charset))
+ id = XINT (CHARSET_SYMBOL_ID (charset));
}
- xfree (fontset_data->fontset_table);
+ rfont_def = fontset_font (fontset, c, face, id);
+ if (VECTORP (rfont_def))
+ {
+ if (NILP (AREF (rfont_def, 0)))
+ {
+ /* We have not yet made a realized face that uses this font. */
+ int font_idx = XINT (AREF (rfont_def, 1));
- xfree (fontset_data);
+ face_id = lookup_non_ascii_face (f, font_idx, face);
+ ASET (rfont_def, 0, make_number (face_id));
+ }
+ return XINT (AREF (rfont_def, 0));
+ }
+
+ if (NILP (FONTSET_NOFONT_FACE (fontset)))
+ {
+ face_id = lookup_non_ascii_face (f, -1, face);
+ FONTSET_NOFONT_FACE (fontset) = make_number (face_id);
+ }
+ return XINT (FONTSET_NOFONT_FACE (fontset));
+}
+
+
+/* Make a realized fontset for ASCII face FACE on frame F from the
+ base fontset BASE_FONTSET_ID. If BASE_FONTSET_ID is -1, use the
+ default fontset as the base. Value is the id of the new fontset.
+ Called from realize_x_face. */
+
+int
+make_fontset_for_ascii_face (f, base_fontset_id, face)
+ FRAME_PTR f;
+ int base_fontset_id;
+ struct face *face;
+{
+ Lisp_Object base_fontset, fontset, frame;
+
+ XSETFRAME (frame, f);
+ if (base_fontset_id >= 0)
+ {
+ base_fontset = FONTSET_FROM_ID (base_fontset_id);
+ if (!BASE_FONTSET_P (base_fontset))
+ base_fontset = FONTSET_BASE (base_fontset);
+ xassert (BASE_FONTSET_P (base_fontset));
+ if (! BASE_FONTSET_P (base_fontset))
+ abort ();
+ }
+ else
+ base_fontset = Vdefault_fontset;
+
+ fontset = make_fontset (frame, Qnil, base_fontset);
+ {
+ Lisp_Object elt, rfont_def;
+
+ elt = FONTSET_REF (base_fontset, 0);
+ xassert (VECTORP (elt) && ASIZE (elt) > 0);
+ rfont_def = Fmake_vector (make_number (4), Qnil);
+ ASET (rfont_def, 0, make_number (face->id));
+ ASET (rfont_def, 1, make_number (face->font_info_id));
+ ASET (rfont_def, 2, AREF (elt, 0));
+ ASET (rfont_def, 3, build_string (face->font_name));
+ elt = Fmake_vector (make_number (4), Qnil);
+ ASET (elt, 0, make_number (charset_ordered_list_tick));
+ ASET (elt, 1, make_number (charset_ascii));
+ ASET (elt, 2, rfont_def);
+ ASET (elt, 3, rfont_def);
+ char_table_set_range (fontset, 0, 127, elt);
+ }
+ return XINT (FONTSET_ID (fontset));
}
-/* Load a font named FONTNAME for displaying CHARSET on frame F.
- All fonts for frame F is stored in a table pointed by FONT_TABLE.
- Return a pointer to the struct font_info of the loaded font.
- If loading fails, return 0;
- If FONTNAME is NULL, the name is taken from the information of FONTSET.
- If FONTSET is given, try to load a font whose size matches that of
- FONTSET, and, the font index is stored in the table for FONTSET. */
+
+#if defined(WINDOWSNT) && defined (_MSC_VER)
+#pragma optimize("", off)
+#endif
+
+/* Load a font named FONTNAME on frame F. Return a pointer to the
+ struct font_info of the loaded font. If loading fails, return
+ NULL. CHARSET is an ID of charset to encode characters for this
+ font. If it is -1, find one from Vfont_encoding_alist. */
struct font_info *
-fs_load_font (f, font_table, charset, fontname, fontset)
+fs_load_font (f, fontname, charset)
FRAME_PTR f;
- struct font_info *font_table;
- int charset, fontset;
char *fontname;
+ int charset;
{
- Lisp_Object font_list;
- Lisp_Object list, elt;
- int font_idx;
- int size = 0;
- struct fontset_info *fontsetp = 0;
struct font_info *fontp;
+ Lisp_Object fullname;
+
+ if (!fontname)
+ /* No way to get fontname. */
+ return NULL;
+
+ fontp = (*load_font_func) (f, fontname, 0);
+ if (! fontp || fontp->charset >= 0)
+ return fontp;
+
+ fontname = fontp->full_name;
+ fullname = build_string (fontp->full_name);
+
+ if (charset < 0)
+ {
+ Lisp_Object charset_symbol;
+
+ charset_symbol = find_font_encoding (fullname);
+ if (CONSP (charset_symbol))
+ charset_symbol = XCAR (charset_symbol);
+ charset = XINT (CHARSET_SYMBOL_ID (charset_symbol));
+ }
+ fontp->charset = charset;
+ fontp->vertical_centering = 0;
+ fontp->font_encoder = NULL;
- if (fontset >= 0 && fontset < FRAME_FONTSET_DATA (f)->n_fontsets)
+ if (charset != charset_ascii)
{
- fontsetp = FRAME_FONTSET_DATA (f)->fontset_table[fontset];
- font_idx = fontsetp->font_indexes[charset];
- if (font_idx >= 0)
- /* We have already loaded a font. */
- return font_table + font_idx;
- else if (font_idx == FONT_NOT_FOUND)
- /* We have already tried loading a font and failed. */
- return 0;
- if (!fontname)
- fontname = fontsetp->fontname[charset];
+ fontp->vertical_centering
+ = (STRINGP (Vvertical_centering_font_regexp)
+ && (fast_string_match_ignore_case
+ (Vvertical_centering_font_regexp, fullname) >= 0));
+
+ if (find_ccl_program_func)
+ (*find_ccl_program_func) (fontp);
}
- if (!fontname)
- /* No way to get fontname. */
- return 0;
+ return fontp;
+}
+
+#if defined(WINDOWSNT) && defined (_MSC_VER)
+#pragma optimize("", on)
+#endif
- /* If a fontset is specified and we have already loaded some fonts
- in the fontset, we need a font of appropriate size to be used
- with the fonts. */
- if (fontsetp && fontsetp->size)
- size = fontsetp->size * CHARSET_WIDTH (charset);
+\f
+/* Return ENCODING or a cons of ENCODING and REPERTORY of the font
+ FONTNAME. ENCODING is a charset symbol that specifies the encoding
+ of the font. REPERTORY is a charset symbol or nil. */
- fontp = (*load_font_func) (f, fontname, size);
- if (!fontp)
+static Lisp_Object
+find_font_encoding (fontname)
+ Lisp_Object fontname;
+{
+ Lisp_Object tail, elt;
+
+ for (tail = Vfont_encoding_alist; CONSP (tail); tail = XCDR (tail))
{
- if (fontsetp)
- fontsetp->font_indexes[charset] = FONT_NOT_FOUND;
- return 0;
+ elt = XCAR (tail);
+ if (CONSP (elt)
+ && STRINGP (XCAR (elt))
+ && fast_string_match_ignore_case (XCAR (elt), fontname) >= 0
+ && (SYMBOLP (XCDR (elt))
+ ? CHARSETP (XCDR (elt))
+ : CONSP (XCDR (elt)) && CHARSETP (XCAR (XCDR (elt)))))
+ return (XCDR (elt));
}
+ /* We don't know the encoding of this font. Let's assume `ascii'. */
+ return Qascii;
+}
- /* Fill in fields (CHARSET, ENCODING, and FONT_ENCODER) which are
- not set by (*load_font_func). */
- fontp->charset = charset;
- if (fontp->encoding[1] >= 0)
+/* Cache data used by fontset_pattern_regexp. The car part is a
+ pattern string containing at least one wild card, the cdr part is
+ the corresponding regular expression. */
+static Lisp_Object Vcached_fontset_data;
+
+#define CACHED_FONTSET_NAME (SDATA (XCAR (Vcached_fontset_data)))
+#define CACHED_FONTSET_REGEX (XCDR (Vcached_fontset_data))
+
+/* If fontset name PATTERN contains any wild card, return regular
+ expression corresponding to PATTERN. */
+
+static Lisp_Object
+fontset_pattern_regexp (pattern)
+ Lisp_Object pattern;
+{
+ if (!index (SDATA (pattern), '*')
+ && !index (SDATA (pattern), '?'))
+ /* PATTERN does not contain any wild cards. */
+ return Qnil;
+
+ if (!CONSP (Vcached_fontset_data)
+ || strcmp (SDATA (pattern), CACHED_FONTSET_NAME))
{
- /* The font itself tells which code points to be used. Use this
- encoding for all other charsets. */
- int i;
+ /* We must at first update the cached data. */
+ unsigned char *regex, *p0, *p1;
+ int ndashes = 0, nstars = 0;
+
+ for (p0 = SDATA (pattern); *p0; p0++)
+ {
+ if (*p0 == '-')
+ ndashes++;
+ else if (*p0 == '*')
+ nstars++;
+ }
+
+ /* If PATTERN is not full XLFD we conert "*" to ".*". Otherwise
+ we convert "*" to "[^-]*" which is much faster in regular
+ expression matching. */
+ if (ndashes < 14)
+ p1 = regex = (unsigned char *) alloca (SBYTES (pattern) + 2 * nstars + 1);
+ else
+ p1 = regex = (unsigned char *) alloca (SBYTES (pattern) + 5 * nstars + 1);
+
+ *p1++ = '^';
+ for (p0 = SDATA (pattern); *p0; p0++)
+ {
+ if (*p0 == '*')
+ {
+ if (ndashes < 14)
+ *p1++ = '.';
+ else
+ *p1++ = '[', *p1++ = '^', *p1++ = '-', *p1++ = ']';
+ *p1++ = '*';
+ }
+ else if (*p0 == '?')
+ *p1++ = '.';
+ else
+ *p1++ = *p0;
+ }
+ *p1++ = '$';
+ *p1++ = 0;
- fontp->encoding[0] = fontp->encoding[1];
- for (i = MIN_CHARSET_OFFICIAL_DIMENSION1; i <= MAX_CHARSET; i++)
- fontp->encoding[i] = fontp->encoding[1];
+ Vcached_fontset_data = Fcons (build_string (SDATA (pattern)),
+ build_string (regex));
}
- else
+
+ return CACHED_FONTSET_REGEX;
+}
+
+/* Return ID of the base fontset named NAME. If there's no such
+ fontset, return -1. NAME_PATTERN specifies how to treat NAME as this:
+ 0: pattern containing '*' and '?' as wildcards
+ 1: regular expression
+ 2: literal fontset name
+*/
+
+int
+fs_query_fontset (name, name_pattern)
+ Lisp_Object name;
+ int name_pattern;
+{
+ Lisp_Object tem;
+ int i;
+
+ name = Fdowncase (name);
+ if (name_pattern != 1)
{
- /* The font itself doesn't tell which code points to be used. */
- int i;
+ tem = Frassoc (name, Vfontset_alias_alist);
+ if (NILP (tem))
+ tem = Fassoc (name, Vfontset_alias_alist);
+ if (CONSP (tem) && STRINGP (XCAR (tem)))
+ name = XCAR (tem);
+ else if (name_pattern == 0)
+ {
+ tem = fontset_pattern_regexp (name);
+ if (STRINGP (tem))
+ {
+ name = tem;
+ name_pattern = 1;
+ }
+ }
+ }
+
+ for (i = 0; i < ASIZE (Vfontset_table); i++)
+ {
+ Lisp_Object fontset, this_name;
+
+ fontset = FONTSET_FROM_ID (i);
+ if (NILP (fontset)
+ || !BASE_FONTSET_P (fontset))
+ continue;
+
+ this_name = FONTSET_NAME (fontset);
+ if (name_pattern == 1
+ ? fast_string_match (name, this_name) >= 0
+ : !strcmp (SDATA (name), SDATA (this_name)))
+ return i;
+ }
+ return -1;
+}
+
- /* At first, set 1 (means 0xA0..0xFF) as the default. */
- fontp->encoding[0] = 1;
- for (i = MIN_CHARSET_OFFICIAL_DIMENSION1; i <= MAX_CHARSET; i++)
- fontp->encoding[i] = 1;
- /* Then override them by a specification in Vfont_encoding_alist. */
- for (list = Vfont_encoding_alist; CONSP (list); list = XCONS (list)->cdr)
+DEFUN ("query-fontset", Fquery_fontset, Squery_fontset, 1, 2, 0,
+ doc: /* Return the name of a fontset that matches PATTERN.
+The value is nil if there is no matching fontset.
+PATTERN can contain `*' or `?' as a wildcard
+just as X font name matching algorithm allows.
+If REGEXPP is non-nil, PATTERN is a regular expression. */)
+ (pattern, regexpp)
+ Lisp_Object pattern, regexpp;
+{
+ Lisp_Object fontset;
+ int id;
+
+ (*check_window_system_func) ();
+
+ CHECK_STRING (pattern);
+
+ if (SCHARS (pattern) == 0)
+ return Qnil;
+
+ id = fs_query_fontset (pattern, !NILP (regexpp));
+ if (id < 0)
+ return Qnil;
+
+ fontset = FONTSET_FROM_ID (id);
+ return FONTSET_NAME (fontset);
+}
+
+/* Return a list of base fontset names matching PATTERN on frame F. */
+
+Lisp_Object
+list_fontsets (f, pattern, size)
+ FRAME_PTR f;
+ Lisp_Object pattern;
+ int size;
+{
+ Lisp_Object frame, regexp, val;
+ int id;
+
+ XSETFRAME (frame, f);
+
+ regexp = fontset_pattern_regexp (pattern);
+ val = Qnil;
+
+ for (id = 0; id < ASIZE (Vfontset_table); id++)
+ {
+ Lisp_Object fontset, name;
+
+ fontset = FONTSET_FROM_ID (id);
+ if (NILP (fontset)
+ || !BASE_FONTSET_P (fontset)
+ || !EQ (frame, FONTSET_FRAME (fontset)))
+ continue;
+ name = FONTSET_NAME (fontset);
+
+ if (STRINGP (regexp)
+ ? (fast_string_match (regexp, name) < 0)
+ : strcmp (SDATA (pattern), SDATA (name)))
+ continue;
+
+ val = Fcons (Fcopy_sequence (FONTSET_NAME (fontset)), val);
+ }
+
+ return val;
+}
+
+
+/* Free all realized fontsets whose base fontset is BASE. */
+
+static void
+free_realized_fontsets (base)
+ Lisp_Object base;
+{
+#if 0
+ int id;
+
+ /* For the moment, this doesn't work because free_realized_face
+ doesn't remove FACE from a cache. Until we find a solution, we
+ suppress this code, and simply use Fclear_face_cache even though
+ that is not efficient. */
+ BLOCK_INPUT;
+ for (id = 0; id < ASIZE (Vfontset_table); id++)
+ {
+ Lisp_Object this = AREF (Vfontset_table, id);
+
+ if (EQ (FONTSET_BASE (this), base))
{
- elt = XCONS (list)->car;
- if (CONSP (elt)
- && STRINGP (XCONS (elt)->car) && CONSP (XCONS (elt)->cdr)
- && (fast_string_match_ignore_case (XCONS (elt)->car, fontname)
- >= 0))
+ Lisp_Object tail;
+
+ for (tail = FONTSET_FACE_ALIST (this); CONSP (tail);
+ tail = XCDR (tail))
{
- Lisp_Object tmp;
+ FRAME_PTR f = XFRAME (FONTSET_FRAME (this));
+ int face_id = XINT (XCDR (XCAR (tail)));
+ struct face *face = FACE_FROM_ID (f, face_id);
+
+ /* Face THIS itself is also freed by the following call. */
+ free_realized_face (f, face);
+ }
+ }
+ }
+ UNBLOCK_INPUT;
+#else /* not 0 */
+ Fclear_face_cache (Qt);
+#endif /* not 0 */
+}
+
+
+/* Check validity of NAME as a fontset name and return the
+ corresponding fontset. If not valid, signal an error.
+ If NAME is t, return Vdefault_fontset. */
+
+static Lisp_Object
+check_fontset_name (name)
+ Lisp_Object name;
+{
+ int id;
+
+ if (EQ (name, Qt))
+ return Vdefault_fontset;
+
+ CHECK_STRING (name);
+ /* First try NAME as literal. */
+ id = fs_query_fontset (name, 2);
+ if (id < 0)
+ /* For backward compatibility, try again NAME as pattern. */
+ id = fs_query_fontset (name, 0);
+ if (id < 0)
+ error ("Fontset `%s' does not exist", SDATA (name));
+ return FONTSET_FROM_ID (id);
+}
+
+static void
+accumulate_script_ranges (arg, range, val)
+ Lisp_Object arg, range, val;
+{
+ if (EQ (XCAR (arg), val))
+ {
+ if (CONSP (range))
+ XSETCDR (arg, Fcons (Fcons (XCAR (range), XCDR (range)), XCDR (arg)));
+ else
+ XSETCDR (arg, Fcons (Fcons (range, range), XCDR (arg)));
+ }
+}
+
+
+/* Return an ASCII font name generated from fontset name NAME and
+ ASCII font specification ASCII_SPEC. NAME is a string conforming
+ to XLFD. ASCII_SPEC is a vector:
+ [FAMILY WEIGHT SLANT SWIDTH ADSTYLE REGISTRY]. */
+
+static INLINE Lisp_Object
+generate_ascii_font_name (name, ascii_spec)
+ Lisp_Object name, ascii_spec;
+{
+ Lisp_Object vec;
+ int i;
+
+ vec = split_font_name_into_vector (name);
+ for (i = FONT_SPEC_FAMILY_INDEX; i <= FONT_SPEC_ADSTYLE_INDEX; i++)
+ if (! NILP (AREF (ascii_spec, i)))
+ ASET (vec, 1 + i, AREF (ascii_spec, i));
+ if (! NILP (AREF (ascii_spec, FONT_SPEC_REGISTRY_INDEX)))
+ ASET (vec, 12, AREF (ascii_spec, FONT_SPEC_REGISTRY_INDEX));
+ return build_font_name_from_vector (vec);
+}
+
+/* Variables referred in set_fontset_font. They are set before
+ map_charset_chars is called in Fset_fontset_font. */
+static Lisp_Object font_def_arg, add_arg;
+static int from_arg, to_arg;
+
+/* Callback function for map_charset_chars in Fset_fontset_font. In
+ FONTSET, set font_def_arg in a fashion specified by add_arg for
+ characters in RANGE while ignoring the range between from_arg and
+ to_arg. */
+
+static void
+set_fontset_font (fontset, range)
+ Lisp_Object fontset, range;
+{
+ if (from_arg < to_arg)
+ {
+ int from = XINT (XCAR (range)), to = XINT (XCDR (range));
+
+ if (from < from_arg)
+ {
+ if (to > to_arg)
+ {
+ Lisp_Object range2;
- for (tmp = XCONS (elt)->cdr; CONSP (tmp); tmp = XCONS (tmp)->cdr)
- if (CONSP (XCONS (tmp)->car)
- && ((i = get_charset_id (XCONS (XCONS (tmp)->car)->car))
- >= 0)
- && INTEGERP (XCONS (XCONS (tmp)->car)->cdr)
- && XFASTINT (XCONS (XCONS (tmp)->car)->cdr) < 4)
- fontp->encoding[i]
- = XFASTINT (XCONS (XCONS (tmp)->car)->cdr);
+ range2 = Fcons (make_number (to_arg), XCDR (range));
+ FONTSET_ADD (fontset, range, font_def_arg, add_arg);
+ to = to_arg;
}
+ if (to > from_arg)
+ range = Fcons (XCAR (range), make_number (from_arg));
}
+ else if (to <= to_arg)
+ return;
+ else
+ {
+ if (from < to_arg)
+ range = Fcons (make_number (to_arg), XCDR (range));
+ }
+ }
+ FONTSET_ADD (fontset, range, font_def_arg, add_arg);
+}
+
+
+DEFUN ("set-fontset-font", Fset_fontset_font, Sset_fontset_font, 3, 5, 0,
+ doc: /*
+Modify fontset NAME to use FONT-SPEC for TARGET characters.
+
+TARGET may be a cons; (FROM . TO), where FROM and TO are characters.
+In that case, use FONT-SPEC for all characters in the range FROM and
+TO (inclusive).
+
+TARGET may be a script name symbol. In that case, use FONT-SPEC for
+all characters that belong to the script.
+
+TARGET may be a charset. In that case, use FONT-SPEC for all
+characters in the charset.
+
+TARGET may be nil. In that case, use FONT-SPEC for any characters for
+that no FONT-SPEC is specified.
+
+FONT-SPEC may one of these:
+ * A cons (FAMILY . REGISTRY), where FAMILY is a font family name and
+ REGISTRY is a font registry name. FAMILY may contains foundry
+ name, and REGISTRY may contains encoding name.
+ * A font name string.
+
+Optional 4th argument FRAME, if non-nil, is a frame. This argument is
+kept for backward compatibility and has no meaning.
+
+Optional 5th argument ADD, if non-nil, specifies how to add FONT-SPEC
+to the font specifications for TARGET previously set. If it is
+`prepend', FONT-SPEC is prepended. If it is `append', FONT-SPEC is
+appended. By default, FONT-SPEC overrides the previous settings. */)
+ (name, target, font_spec, frame, add)
+ Lisp_Object name, target, font_spec, frame, add;
+{
+ Lisp_Object fontset;
+ Lisp_Object font_def, registry, family;
+ Lisp_Object encoding, repertory;
+ Lisp_Object range_list;
+ struct charset *charset = NULL;
+
+ fontset = check_fontset_name (name);
+
+ /* The arg FRAME is kept for backward compatibility. We only check
+ the validity. */
+ if (!NILP (frame))
+ CHECK_LIVE_FRAME (frame);
+
+ if (VECTORP (font_spec))
+ {
+ /* FONT_SPEC should have this form:
+ [ FAMILY WEIGHT SLANT WIDTH ADSTYLE REGISTRY ]
+ This is a feature not yet documented because WEIGHT thru
+ ADSTYLE are ignored for the moment. */
+ int j;
+
+ if (ASIZE (font_spec) != FONT_SPEC_MAX_INDEX)
+ args_out_of_range (make_number (FONT_SPEC_MAX_INDEX),
+ make_number (ASIZE (font_spec)));
+
+ font_spec = Fcopy_sequence (font_spec);
+ for (j = 0; j < FONT_SPEC_MAX_INDEX - 1; j++)
+ if (! NILP (AREF (font_spec, j)))
+ {
+ CHECK_STRING (AREF (font_spec, j));
+ ASET (font_spec, j, Fdowncase (AREF (font_spec, j)));
+ }
+ family = AREF (font_spec, FONT_SPEC_FAMILY_INDEX);
+ /* REGISTRY should not be omitted. */
+ CHECK_STRING (AREF (font_spec, FONT_SPEC_REGISTRY_INDEX));
+ registry = AREF (font_spec, FONT_SPEC_REGISTRY_INDEX);
+ }
+ else if (CONSP (font_spec))
+ {
+ family = XCAR (font_spec);
+ registry = XCDR (font_spec);
+
+ if (! NILP (family))
+ {
+ CHECK_STRING (family);
+ family = Fdowncase (family);
+ }
+ CHECK_STRING (registry);
+ registry = Fdowncase (registry);
+ font_spec = Fmake_vector (make_number (FONT_SPEC_MAX_INDEX), Qnil);
+ ASET (font_spec, FONT_SPEC_FAMILY_INDEX, family);
+ ASET (font_spec, FONT_SPEC_REGISTRY_INDEX, registry);
+ }
+ else
+ {
+ CHECK_STRING (font_spec);
+ font_spec = Fdowncase (font_spec);
}
- fontp->font_encoder = (struct ccl_program *) 0;
- for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCONS (list)->cdr)
+ if (STRINGP (font_spec))
+ encoding = find_font_encoding (font_spec);
+ else
+ encoding = find_font_encoding (concat2 (family, registry));
+ if (SYMBOLP (encoding))
{
- elt = XCONS (list)->car;
- if (CONSP (elt)
- && STRINGP (XCONS (elt)->car) && VECTORP (XCONS (elt)->cdr)
- && fast_string_match_ignore_case (XCONS (elt)->car, fontname) >= 0)
+ CHECK_CHARSET (encoding);
+ encoding = repertory = CHARSET_SYMBOL_ID (encoding);
+ }
+ else
+ {
+ repertory = XCDR (encoding);
+ encoding = XCAR (encoding);
+ CHECK_CHARSET (encoding);
+ encoding = CHARSET_SYMBOL_ID (encoding);
+ if (! NILP (repertory) && SYMBOLP (repertory))
{
- fontp->font_encoder
- = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
- setup_ccl_program (fontp->font_encoder, XCONS (elt)->cdr);
- break;
+ CHECK_CHARSET (repertory);
+ repertory = CHARSET_SYMBOL_ID (repertory);
}
}
+ font_def = Fmake_vector (make_number (3), font_spec);
+ ASET (font_def, 1, encoding);
+ ASET (font_def, 2, repertory);
- if (fontsetp)
+ if (CHARACTERP (target))
+ range_list = Fcons (Fcons (target, target), Qnil);
+ else if (CONSP (target))
{
- fontsetp->font_indexes[charset] = fontp->font_idx;
- if (fontsetp->size == 0)
- fontsetp->size = fontp->size / CHARSET_WIDTH (charset);
+ Lisp_Object from, to;
- if (charset == CHARSET_ASCII
- && fontsetp->size != fontp->size)
+ from = Fcar (target);
+ to = Fcdr (target);
+ CHECK_CHARACTER (from);
+ CHECK_CHARACTER (to);
+ range_list = Fcons (target, Qnil);
+ }
+ else if (SYMBOLP (target) && !NILP (target))
+ {
+ Lisp_Object script_list;
+ Lisp_Object val;
+
+ range_list = Qnil;
+ script_list = XCHAR_TABLE (Vchar_script_table)->extras[0];
+ if (! NILP (Fmemq (target, script_list)))
+ {
+ val = Fcons (target, Qnil);
+ map_char_table (accumulate_script_ranges, Qnil, Vchar_script_table,
+ val);
+ range_list = XCDR (val);
+ }
+ if (CHARSETP (target))
{
- /* When loading ASCII font of the different size from the
- size of FONTSET, we have to update the size of FONTSET.
- Since changing the size of FONTSET may make some fonts
- already loaded inappropriate to be used in FONTSET, we
- must delete the record of such fonts. In that case, we
- also have to calculate the height of FONTSET from the
- remaining fonts. */
- int i;
-
- fontsetp->size = fontp->size;
- fontsetp->height = fontp->height;
- for (i = CHARSET_ASCII + 1; i <= MAX_CHARSET; i++)
+ if (EQ (target, Qascii))
{
- font_idx = fontsetp->font_indexes[i];
- if (font_idx >= 0)
- {
- struct font_info *fontp2 = font_table + font_idx;
-
- if (fontp2->size != fontp->size * CHARSET_WIDTH (i))
- fontsetp->font_indexes[i] = FONT_NOT_OPENED;
- /* The following code should be disabled until Emacs
- supports variable height lines. */
-#if 0
- else if (fontsetp->height < fontp->height)
- fontsetp->height = fontp->height;
-#endif
- }
+ if (VECTORP (font_spec))
+ font_spec = generate_ascii_font_name (FONTSET_NAME (fontset),
+ font_spec);
+ FONTSET_ASCII (fontset) = font_spec;
+ range_list = Fcons (Fcons (make_number (0), make_number (127)),
+ Qnil);
+ }
+ else
+ {
+ CHECK_CHARSET_GET_CHARSET (target, charset);
}
}
- else if (fontsetp->height < fontp->height)
- fontsetp->height = fontp->height;
+ else if (NILP (range_list))
+ error ("Invalid script or charset name: %s",
+ SDATA (SYMBOL_NAME (target)));
}
+ else if (NILP (target))
+ range_list = Fcons (Qnil, Qnil);
+ else
+ error ("Invalid target for setting a font");
- return fontp;
-}
-/* Return ID of the fontset named NAME on frame F. */
+ if (charset)
+ {
+ font_def_arg = font_def;
+ add_arg = add;
+ if (NILP (range_list))
+ from_arg = to_arg = 0;
+ else
+ from_arg = XINT (XCAR (XCAR (range_list))),
+ to_arg = XINT (XCDR (XCAR (range_list)));
-int
-fs_query_fontset (f, name)
- FRAME_PTR f;
- char *name;
-{
- struct fontset_data *fontset_data = FRAME_FONTSET_DATA (f);
- int i;
+ map_charset_chars (set_fontset_font, Qnil, fontset, charset,
+ CHARSET_MIN_CODE (charset),
+ CHARSET_MAX_CODE (charset));
+ }
+ for (; CONSP (range_list); range_list = XCDR (range_list))
+ FONTSET_ADD (fontset, XCAR (range_list), font_def, add);
- for (i = 0; i < fontset_data->n_fontsets; i++)
- if (!my_strcasecmp(name, fontset_data->fontset_table[i]->name))
- return i;
- return -1;
-}
+ /* Free all realized fontsets whose base is FONTSET. This way, the
+ specified character(s) are surely redisplayed by a correct
+ font. */
+ free_realized_fontsets (fontset);
-/* Register a fontset specified by FONTSET_INFO for frame FRAME.
- Return the fontset ID if successfully registered, else return -1.
- FONTSET_INFO is a cons of name of the fontset and FONTLIST, where
- FONTLIST is an alist of charsets vs fontnames. */
+ return Qnil;
+}
-int
-fs_register_fontset (f, fontset_info)
- FRAME_PTR f;
- Lisp_Object fontset_info;
-{
- struct fontset_data *fontset_data = FRAME_FONTSET_DATA (f);
- Lisp_Object name, fontlist;
- int fontset;
- struct fontset_info *fontsetp;
- int i;
- if (!CONSP (fontset_info)
- || !STRINGP (XCONS (fontset_info)->car)
- || !CONSP (XCONS (fontset_info)->cdr))
- /* Invalid data in FONTSET_INFO. */
- return -1;
+DEFUN ("new-fontset", Fnew_fontset, Snew_fontset, 2, 2, 0,
+ doc: /* Create a new fontset NAME from font information in FONTLIST.
- name = XCONS (fontset_info)->car;
- if ((fontset = fs_query_fontset (f, XSTRING (name)->data)) >= 0)
- /* This fontset already exists on frame F. */
- return fontset;
+FONTLIST is an alist of scripts vs the corresponding font specification list.
+Each element of FONTLIST has the form (SCRIPT FONT-SPEC ...), where a
+character of SCRIPT is displayed by a font that matches one of
+FONT-SPEC.
- fontsetp = (struct fontset_info *) xmalloc (sizeof (struct fontset_info));
+SCRIPT is a symbol that appears in the first extra slot of the
+char-table `char-script-table'.
- fontsetp->name = (char *) xmalloc (XSTRING (name)->size + 1);
- bcopy(XSTRING (name)->data, fontsetp->name, XSTRING (name)->size + 1);
+FONT-SPEC is a vector, a cons, or a string. See the documentation of
+`set-fontset-font' for the meaning. */)
+ (name, fontlist)
+ Lisp_Object name, fontlist;
+{
+ Lisp_Object fontset;
+ Lisp_Object val;
+ int id;
- fontsetp->size = fontsetp->height = 0;
+ CHECK_STRING (name);
+ CHECK_LIST (fontlist);
- for (i = 0; i <= MAX_CHARSET; i++)
+ id = fs_query_fontset (name, 0);
+ if (id < 0)
{
- fontsetp->fontname[i] = (char *) 0;
- fontsetp->font_indexes[i] = FONT_NOT_OPENED;
+ name = Fdowncase (name);
+ val = split_font_name_into_vector (name);
+ if (NILP (val) || NILP (AREF (val, 12)) || NILP (AREF (val, 13)))
+ error ("Fontset name must be in XLFD format");
+ if (strcmp (SDATA (AREF (val, 12)), "fontset"))
+ error ("Registry field of fontset name must be \"fontset\"");
+ Vfontset_alias_alist
+ = Fcons (Fcons (name,
+ concat2 (concat2 (AREF (val, 12), build_string ("-")),
+ AREF (val, 13))),
+ Vfontset_alias_alist);
+ ASET (val, 12, build_string ("iso8859-1"));
+ fontset = make_fontset (Qnil, name, Qnil);
+ FONTSET_ASCII (fontset) = build_font_name_from_vector (val);
}
-
- for (fontlist = XCONS (fontset_info)->cdr; CONSP (fontlist);
- fontlist = XCONS (fontlist)->cdr)
+ else
{
- Lisp_Object tem = Fcar (fontlist);
- int charset;
-
- if (CONSP (tem)
- && (charset = get_charset_id (XCONS (tem)->car)) >= 0
- && STRINGP (XCONS (tem)->cdr))
- {
- fontsetp->fontname[charset]
- = (char *) xmalloc (XSTRING (XCONS (tem)->cdr)->size + 1);
- bcopy (XSTRING (XCONS (tem)->cdr)->data,
- fontsetp->fontname[charset],
- XSTRING (XCONS (tem)->cdr)->size + 1);
- }
- else
- /* Broken or invalid data structure. */
- return -1;
+ fontset = FONTSET_FROM_ID (id);;
+ free_realized_fontsets (fontset);
+ Fset_char_table_range (fontset, Qt, Qnil);
}
- /* Do we need to create the table? */
- if (fontset_data->fontset_table_size == 0)
- {
- fontset_data->fontset_table_size = 8;
- fontset_data->fontset_table
- = (struct fontset_info **) xmalloc (fontset_data->fontset_table_size
- * sizeof (struct fontset_info *));
- }
- /* Do we need to grow the table? */
- else if (fontset_data->n_fontsets >= fontset_data->fontset_table_size)
+ for (; ! NILP (fontlist); fontlist = Fcdr (fontlist))
{
- fontset_data->fontset_table_size += 8;
- fontset_data->fontset_table
- = (struct fontset_info **) xrealloc (fontset_data->fontset_table,
- fontset_data->fontset_table_size
- * sizeof (struct fontset_info *));
+ Lisp_Object elt, script;
+
+ elt = Fcar (fontlist);
+ script = Fcar (elt);
+ elt = Fcdr (elt);
+ if (CONSP (elt) && (NILP (XCDR (elt)) || CONSP (XCDR (elt))))
+ for (; CONSP (elt); elt = XCDR (elt))
+ Fset_fontset_font (name, script, XCAR (elt), Qnil, Qappend);
+ else
+ Fset_fontset_font (name, script, elt, Qnil, Qappend);
}
- fontset = fontset_data->n_fontsets++;
- fontset_data->fontset_table[fontset] = fontsetp;
-
- return fontset;
+ return name;
}
-/* Cache data used by fontset_pattern_regexp. The car part is a
- pattern string containing at least one wild card, the cdr part is
- the corresponding regular expression. */
-static Lisp_Object Vcached_fontset_data;
-
-#define CACHED_FONTSET_NAME (XSTRING (XCONS (Vcached_fontset_data)->car)->data)
-#define CACHED_FONTSET_REGEX (XCONS (Vcached_fontset_data)->cdr)
-/* If fontset name PATTERN contains any wild card, return regular
- expression corresponding to PATTERN. */
+/* Alist of automatically created fontsets. Each element is a cons
+ (FONTNAME . FONTSET-ID). */
+static Lisp_Object auto_fontset_alist;
-Lisp_Object
-fontset_pattern_regexp (pattern)
- Lisp_Object pattern;
+int
+new_fontset_from_font_name (Lisp_Object fontname)
{
- int nickname = 0;
-
- if (!index (XSTRING (pattern)->data, '*')
- && !index (XSTRING (pattern)->data, '?'))
- /* PATTERN does not contain any wild cards. */
+ Lisp_Object val;
+ Lisp_Object name;
+ Lisp_Object vec;
+ int id;
+
+ fontname = Fdowncase (fontname);
+ val = Fassoc (fontname, auto_fontset_alist);
+ if (CONSP (val))
+ return XINT (XCDR (val));
+
+ vec = split_font_name_into_vector (fontname);
+ if ( NILP (vec))
+ vec = Fmake_vector (make_number (14), build_string (""));
+ ASET (vec, 12, build_string ("fontset"));
+ if (NILP (auto_fontset_alist))
{
- if (XSTRING (pattern)->size > 8
- && ! bcmp (XSTRING (pattern)->data, "fontset-", 8))
- /* Just a nickname of a fontset is specified. */
- nickname = 1;
- else
- return Qnil;
+ ASET (vec, 13, build_string ("startup"));
+ name = build_font_name_from_vector (vec);
}
-
- if (!CONSP (Vcached_fontset_data)
- || strcmp (XSTRING (pattern)->data, CACHED_FONTSET_NAME))
+ else
{
- /* We must at first update the cached data. */
- char *regex = (char *) alloca (XSTRING (pattern)->size * 2 + 3);
- char *p0, *p1 = regex;
-
- if (nickname)
- {
- /* Just prepend ".*-" to PATTERN. */
- *p1++= '.'; *p1++= '*', *p1++= '-';
- bcopy (XSTRING (pattern)->data, p1, XSTRING (pattern)->size);
- p1 += XSTRING (pattern)->size;
- }
- else
- {
- /* Convert "*" to ".*", "?" to ".". */
- *p1++ = '^';
- for (p0 = XSTRING (pattern)->data; *p0; p0++)
- {
- if (*p0 == '*')
- {
- *p1++ = '.';
- *p1++ = '*';
- }
- else if (*p0 == '?')
- *p1++ == '.';
- else
- *p1++ = *p0;
- }
- }
- *p1++ = '$';
- *p1++ = 0;
+ char temp[20];
+ int len = XINT (Flength (auto_fontset_alist));
- Vcached_fontset_data = Fcons (build_string (XSTRING (pattern)->data),
- build_string (regex));
+ sprintf (temp, "auto%d", len);
+ ASET (vec, 13, build_string (temp));
+ name = build_font_name_from_vector (vec);
}
-
- return CACHED_FONTSET_REGEX;
+ name = Fnew_fontset (name, list2 (list2 (Qascii, fontname),
+ list2 (Fcons (make_number (0),
+ make_number (MAX_CHAR)),
+ fontname)));
+ id = fs_query_fontset (name, 0);
+ auto_fontset_alist
+ = Fcons (Fcons (fontname, make_number (id)), auto_fontset_alist);
+ return id;
}
-DEFUN ("query-fontset", Fquery_fontset, Squery_fontset, 1, 1, 0,
- "Return a fontset name which matches PATTERN, nil if no matching fontset.\n\
-PATTERN can contain `*' or `?' as a wild card\n\
-just like X's font name matching algorithm allows.")
- (pattern)
- Lisp_Object pattern;
+
+DEFUN ("font-info", Ffont_info, Sfont_info, 1, 2, 0,
+ doc: /* Return information about a font named NAME on frame FRAME.
+If FRAME is omitted or nil, use the selected frame.
+The returned value is a vector of OPENED-NAME, FULL-NAME, CHARSET, SIZE,
+ HEIGHT, BASELINE-OFFSET, RELATIVE-COMPOSE, and DEFAULT-ASCENT,
+where
+ OPENED-NAME is the name used for opening the font,
+ FULL-NAME is the full name of the font,
+ SIZE is the maximum bound width of the font,
+ HEIGHT is the height of the font,
+ BASELINE-OFFSET is the upward offset pixels from ASCII baseline,
+ RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling
+ how to compose characters.
+If the named font is not yet loaded, return nil. */)
+ (name, frame)
+ Lisp_Object name, frame;
{
- Lisp_Object regexp, tem;
+ FRAME_PTR f;
+ struct font_info *fontp;
+ Lisp_Object info;
(*check_window_system_func) ();
- CHECK_STRING (pattern, 0);
+ CHECK_STRING (name);
+ name = Fdowncase (name);
+ if (NILP (frame))
+ frame = selected_frame;
+ CHECK_LIVE_FRAME (frame);
+ f = XFRAME (frame);
+
+ if (!query_font_func)
+ error ("Font query function is not supported");
- if (XSTRING (pattern)->size == 0)
+ fontp = (*query_font_func) (f, SDATA (name));
+ if (!fontp)
return Qnil;
- regexp = fontset_pattern_regexp (pattern);
+ info = Fmake_vector (make_number (7), Qnil);
- for (tem = Vglobal_fontset_alist; CONSP (tem); tem = XCONS (tem)->cdr)
- {
- Lisp_Object fontset_name = XCONS (XCONS (tem)->car)->car;
- if (!NILP (regexp))
- {
- if (fast_string_match_ignore_case (regexp,
- XSTRING (fontset_name)->data)
- >= 0)
- return fontset_name;
- }
- else
- {
- if (!my_strcasecmp (XSTRING (pattern)->data,
- XSTRING (fontset_name)->data))
- return fontset_name;
- }
- }
+ XVECTOR (info)->contents[0] = build_string (fontp->name);
+ XVECTOR (info)->contents[1] = build_string (fontp->full_name);
+ XVECTOR (info)->contents[2] = make_number (fontp->size);
+ XVECTOR (info)->contents[3] = make_number (fontp->height);
+ XVECTOR (info)->contents[4] = make_number (fontp->baseline_offset);
+ XVECTOR (info)->contents[5] = make_number (fontp->relative_compose);
+ XVECTOR (info)->contents[6] = make_number (fontp->default_ascent);
- return Qnil;
+ return info;
}
-Lisp_Object Fframe_char_width ();
-/* Return a list of names of available fontsets matching PATTERN on
- frame F. If SIZE is not 0, it is the size (maximum bound width) of
- fontsets to be listed. */
+/* Return a cons (FONT-NAME . GLYPH-CODE).
+ FONT-NAME is the font name for the character at POSITION in the current
+ buffer. This is computed from all the text properties and overlays
+ that apply to POSITION. POSTION may be nil, in which case,
+ FONT-NAME is the font name for display the character CH with the
+ default face.
-Lisp_Object
-list_fontsets (f, pattern, size)
- FRAME_PTR f;
- Lisp_Object pattern;
- int size;
-{
- int i;
- Lisp_Object regexp, val;
+ GLYPH-CODE is the glyph code in the font to use for the character.
- regexp = fontset_pattern_regexp (pattern);
+ If the 2nd optional arg CH is non-nil, it is a character to check
+ the font instead of the character at POSITION.
- val = Qnil;
- for (i = 0; i < FRAME_FONTSET_DATA (f)->n_fontsets; i++)
- {
- struct fontset_info *fontsetp = FRAME_FONTSET_DATA (f)->fontset_table[i];
- int name_matched = 0;
- int size_matched = 0;
+ It returns nil in the following cases:
- if (!NILP (regexp))
- {
- if (fast_string_match_ignore_case (regexp, fontsetp->name) >= 0)
- name_matched = 1;
- }
- else
- {
- if (!my_strcasecmp (XSTRING (pattern)->data, fontsetp->name))
- name_matched = 1;
- }
+ (1) The window system doesn't have a font for the character (thus
+ it is displayed by an empty box).
- if (name_matched)
- {
- if (!size || fontsetp->size == size)
- size_matched = 1;
- else if (fontsetp->size == 0)
- {
- /* No font of this fontset has loaded yet. Try loading
- one with SIZE. */
- int j;
+ (2) The character code is invalid.
- for (j = 0; j <= MAX_CHARSET; j++)
- if (fontsetp->fontname[j])
- {
- if ((*load_font_func) (f, fontsetp->fontname[j], size))
- size_matched = 1;
- break;
- }
- }
+ (3) If POSITION is not nil, and the current buffer is not displayed
+ in any window.
- if (size_matched)
- val = Fcons (build_string (fontsetp->name), val);
- }
- }
+ In addition, the returned font name may not take into account of
+ such redisplay engine hooks as what used in jit-lock-mode if
+ POSITION is currently not visible. */
- return val;
-}
-DEFUN ("new-fontset", Fnew_fontset, Snew_fontset, 2, 2, 0,
- "Create a new fontset NAME which contains fonts in FONTLIST.\n\
-FONTLIST is an alist of charsets vs corresponding font names.")
- (name, fontlist)
- Lisp_Object name, fontlist;
+DEFUN ("internal-char-font", Finternal_char_font, Sinternal_char_font, 1, 2, 0,
+ doc: /* For internal use only. */)
+ (position, ch)
+ Lisp_Object position, ch;
{
- Lisp_Object fullname, fontset_info;
- Lisp_Object tail;
-
- (*check_window_system_func) ();
-
- CHECK_STRING (name, 0);
- CHECK_LIST (fontlist, 1);
+ int pos, pos_byte, dummy;
+ int face_id;
+ int c;
+ struct frame *f;
+ struct face *face;
+ Lisp_Object charset, rfont_def;
+ int id;
+
+ if (NILP (position))
+ {
+ CHECK_CHARACTER (ch);
+ c = XINT (ch);
+ f = XFRAME (selected_frame);
+ face_id = DEFAULT_FACE_ID;
+ pos = -1;
+ }
+ else
+ {
+ Lisp_Object window;
+ struct window *w;
+
+ CHECK_NUMBER_COERCE_MARKER (position);
+ pos = XINT (position);
+ if (pos < BEGV || pos >= ZV)
+ args_out_of_range_3 (position, make_number (BEGV), make_number (ZV));
+ pos_byte = CHAR_TO_BYTE (pos);
+ if (NILP (ch))
+ c = FETCH_CHAR (pos_byte);
+ else
+ {
+ CHECK_NATNUM (ch);
+ c = XINT (ch);
+ }
+ window = Fget_buffer_window (Fcurrent_buffer (), Qnil);
+ if (NILP (window))
+ return Qnil;
+ w = XWINDOW (window);
+ f = XFRAME (w->frame);
+ face_id = face_at_buffer_position (w, pos, -1, -1, &dummy, pos + 100, 0);
+ }
+ if (! CHAR_VALID_P (c, 0))
+ return Qnil;
+ face_id = FACE_FOR_CHAR (f, FACE_FROM_ID (f, face_id), c, pos, Qnil);
+ face = FACE_FROM_ID (f, face_id);
+ charset = Fget_char_property (position, Qcharset, Qnil);
+ if (CHARSETP (charset))
+ id = XINT (CHARSET_SYMBOL_ID (charset));
+ else
+ id = -1;
+ rfont_def = fontset_font (FONTSET_FROM_ID (face->fontset), c, face, id);
+ if (VECTORP (rfont_def) && STRINGP (AREF (rfont_def, 3)))
+ {
+ Lisp_Object font_def;
+ struct font_info *fontp;
+ struct charset *charset;
+ XChar2b char2b;
+ int code;
+
+ font_def = AREF (rfont_def, 2);
+ charset = CHARSET_FROM_ID (XINT (AREF (font_def, 1)));
+ code = ENCODE_CHAR (charset, c);
+ if (code == CHARSET_INVALID_CODE (charset))
+ return (Fcons (AREF (rfont_def, 3), Qnil));
+ STORE_XCHAR2B (&char2b, ((code >> 8) & 0xFF), (code & 0xFF));
+ fontp = (*get_font_info_func) (f, XINT (AREF (rfont_def, 1)));
+ rif->encode_char (c, &char2b, fontp, charset, NULL);
+ code = (XCHAR2B_BYTE1 (&char2b) << 8) | XCHAR2B_BYTE2 (&char2b);
+ return (Fcons (AREF (rfont_def, 3), make_number (code)));
+ }
+ return Qnil;
+}
- fullname = Fquery_fontset (name);
- if (!NILP (fullname))
- error ("Fontset \"%s\" matches the existing fontset \"%s\"",
- XSTRING (name)->data, XSTRING (fullname)->data);
- /* Check the validity of FONTLIST. */
- for (tail = fontlist; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- Lisp_Object tem = XCONS (tail)->car;
- int charset;
+DEFUN ("fontset-info", Ffontset_info, Sfontset_info, 1, 2, 0,
+ doc: /* Return information about a fontset FONTSET on frame FRAME.
+The value is a char-table of which elements has this form.
- if (!CONSP (tem)
- || (charset = get_charset_id (XCONS (tem)->car)) < 0
- || !STRINGP (XCONS (tem)->cdr))
- error ("Elements of fontlist must be a cons of charset and font name");
- }
+ ((FONT-PATTERN OPENED-FONT ...) ...)
- fontset_info = Fcons (name, fontlist);
- Vglobal_fontset_alist = Fcons (fontset_info, Vglobal_fontset_alist);
+FONT-PATTERN is a vector:
- /* Register this fontset for all existing frames. */
- {
- Lisp_Object framelist, frame;
-
- FOR_EACH_FRAME (framelist, frame)
- if (!FRAME_TERMCAP_P (XFRAME (frame)))
- fs_register_fontset (XFRAME (frame), fontset_info);
- }
+ [ FAMILY WEIGHT SLANT SWIDTH ADSTYLE REGISTRY ]
- return Qnil;
-}
+or a string of font name pattern.
-extern Lisp_Object Fframe_parameters ();
-extern Lisp_Object Qfont;
-Lisp_Object Qfontset;
+OPENED-FONT is a name of a font actually opened.
-DEFUN ("set-fontset-font", Fset_fontset_font, Sset_fontset_font, 3, 4, 0,
- "Set FONTNAME for a font of CHARSET in fontset NAME on frame FRAME.\n\
-If FRAME is omitted or nil, all frames are affected.")
- (name, charset_symbol, fontname, frame)
- Lisp_Object name, charset_symbol, fontname, frame;
+The char-table has one extra slot. The value is a char-table
+containing the information about the derived fonts from the default
+fontset. The format is the same as abobe. */)
+ (fontset, frame)
+ Lisp_Object fontset, frame;
{
- int charset;
- Lisp_Object fullname, fontlist;
+ FRAME_PTR f;
+ Lisp_Object *realized[2], fontsets[2], tables[2];
+ Lisp_Object val, elt;
+ int c, i, j, k;
(*check_window_system_func) ();
- CHECK_STRING (name, 0);
- CHECK_SYMBOL (charset_symbol, 1);
- CHECK_STRING (fontname, 2);
- if (!NILP (frame))
- CHECK_LIVE_FRAME (frame, 3);
-
- if ((charset = get_charset_id (charset_symbol)) < 0)
- error ("Invalid charset: %s", XSYMBOL (charset_symbol)->name->data);
-
- fullname = Fquery_fontset (name);
- if (NILP (fullname))
- error ("Fontset \"%s\" does not exist", XSTRING (name)->data);
+ fontset = check_fontset_name (fontset);
- /* If FRAME is not specified, we must, at first, update contents of
- `global-fontset-alist' for a frame created in the future. */
if (NILP (frame))
+ frame = selected_frame;
+ CHECK_LIVE_FRAME (frame);
+ f = XFRAME (frame);
+
+ /* Recode fontsets realized on FRAME from the base fontset FONTSET
+ in the table `realized'. */
+ realized[0] = (Lisp_Object *) alloca (sizeof (Lisp_Object)
+ * ASIZE (Vfontset_table));
+ for (i = j = 0; i < ASIZE (Vfontset_table); i++)
{
- Lisp_Object fontset_info = Fassoc (fullname, Vglobal_fontset_alist);
- Lisp_Object tem = Fassq (charset_symbol, XCONS (fontset_info)->cdr);
+ elt = FONTSET_FROM_ID (i);
+ if (!NILP (elt)
+ && EQ (FONTSET_BASE (elt), fontset)
+ && EQ (FONTSET_FRAME (elt), frame))
+ realized[0][j++] = elt;
+ }
+ realized[0][j] = Qnil;
- if (NILP (tem))
- XCONS (fontset_info)->cdr
- = Fcons (Fcons (charset_symbol, fontname),
- XCONS (fontset_info)->cdr);
- else
- XCONS (tem)->cdr = fontname;
+ realized[1] = (Lisp_Object *) alloca (sizeof (Lisp_Object)
+ * ASIZE (Vfontset_table));
+ for (i = j = 0; ! NILP (realized[0][i]); i++)
+ {
+ elt = FONTSET_DEFAULT (realized[0][i]);
+ if (! NILP (elt))
+ realized[1][j++] = elt;
}
+ realized[1][j] = Qnil;
- /* Then, update information in the specified frame or all existing
- frames. */
- {
- Lisp_Object framelist, tem;
+ tables[0] = Fmake_char_table (Qfontset_info, Qnil);
+ tables[1] = Fmake_char_table (Qnil, Qnil);
+ XCHAR_TABLE (tables[0])->extras[0] = tables[1];
+ fontsets[0] = fontset;
+ fontsets[1] = Vdefault_fontset;
- FOR_EACH_FRAME (framelist, tem)
- if (!FRAME_TERMCAP_P (XFRAME (tem))
- && (NILP (frame) || EQ (frame, tem)))
+ /* Accumulate information of the fontset in TABLE. The format of
+ each element is ((FONT-SPEC OPENED-FONT ...) ...). */
+ for (k = 0; k <= 1; k++)
+ {
+ for (c = 0; c <= MAX_CHAR; )
{
- FRAME_PTR f = XFRAME (tem);
- int fontset = fs_query_fontset (f, XSTRING (fullname)->data);
- struct fontset_info *fontsetp
- = FRAME_FONTSET_DATA (f)->fontset_table[fontset];
-
- if (fontsetp->fontname[charset])
- xfree (fontsetp->fontname[charset]);
- fontsetp->fontname[charset]
- = (char *) xmalloc (XSTRING (fontname)->size + 1);
- bcopy (XSTRING (fontname)->data, fontsetp->fontname[charset],
- XSTRING (fontname)->size + 1);
- fontsetp->font_indexes[charset] = FONT_NOT_OPENED;
-
- if (charset == CHARSET_ASCII)
+ int from, to;
+
+ if (c <= MAX_5_BYTE_CHAR)
+ {
+ val = char_table_ref_and_range (fontsets[k], c, &from, &to);
+ if (to > MAX_5_BYTE_CHAR)
+ to = MAX_5_BYTE_CHAR;
+ }
+ else
+ {
+ val = FONTSET_FALLBACK (fontsets[k]);
+ to = MAX_CHAR;
+ }
+ if (VECTORP (val))
{
- Lisp_Object font_param = Fassq (Qfont, Fframe_parameters (tem));
-
- if (set_frame_fontset_func
- && !NILP (font_param)
- && !strcmp (XSTRING (fullname)->data,
- XSTRING (XCONS (font_param)->cdr)->data))
- /* This fontset is the default fontset on frame TEM.
- We may have to resize this frame because of new
- ASCII font. */
- (*set_frame_fontset_func) (f, fullname, Qnil);
+ Lisp_Object alist;
+
+ /* At first, set ALIST to ((FONT-SPEC) ...). */
+ for (alist = Qnil, i = 0; i < ASIZE (val); i++)
+ alist = Fcons (Fcons (AREF (AREF (val, i), 0), Qnil), alist);
+ alist = Fnreverse (alist);
+
+ /* Then store opend font names to cdr of each elements. */
+ for (i = 0; ! NILP (realized[k][i]); i++)
+ {
+ if (c <= MAX_5_BYTE_CHAR)
+ val = FONTSET_REF (realized[k][i], c);
+ else
+ val = FONTSET_FALLBACK (realized[k][i]);
+ if (! VECTORP (val))
+ continue;
+ /* VAL is [int int ?
+ [FACE-ID FONT-INDEX FONT-DEF FONT-NAME] ...].
+ If a font of an element is already opened,
+ FONT-NAME is the name of a opened font. */
+ for (j = 3; j < ASIZE (val); j++)
+ if (STRINGP (AREF (AREF (val, j), 3)))
+ {
+ Lisp_Object font_idx;
+
+ font_idx = AREF (AREF (val, j), 1);
+ elt = Fassq (AREF (AREF (AREF (val, j), 2), 0), alist);
+ if (CONSP (elt)
+ && NILP (Fmemq (font_idx, XCDR(elt))))
+ nconc2 (elt, Fcons (font_idx, Qnil));
+ }
+ }
+ for (val = alist; CONSP (val); val = XCDR (val))
+ for (elt = XCDR (XCAR (val)); CONSP (elt); elt = XCDR (elt))
+ {
+ struct font_info *font_info
+ = (*get_font_info_func) (f, XINT (XCAR (elt)));
+ XSETCAR (elt, build_string (font_info->full_name));
+ }
+
+ /* Store ALIST in TBL for characters C..TO. */
+ if (c <= MAX_5_BYTE_CHAR)
+ char_table_set_range (tables[k], c, to, alist);
+ else
+ XCHAR_TABLE (tables[k])->defalt = alist;
}
+ c = to + 1;
}
- }
+ }
- return Qnil;
+ return tables[0];
}
-DEFUN ("font-info", Ffont_info, Sfont_info, 1, 2, 0,
- "Return information about a font named NAME on frame FRAME.\n\
-If FRAME is omitted or nil, use the selected frame.\n\
-The returned value is a vector of OPENED-NAME, FULL-NAME, CHARSET, SIZE,\n\
- HEIGHT, BASELINE-OFFSET, RELATIVE-COMPOSE, and DEFAULT-ASCENT,\n\
-where\n\
- OPENED-NAME is the name used for opening the font,\n\
- FULL-NAME is the full name of the font,\n\
- CHARSET is the charset displayed by the font,\n\
- SIZE is the minimum bound width of the font,\n\
- HEIGHT is the height of the font,\n\
- BASELINE-OFFSET is the upward offset pixels from ASCII baseline,\n\
- RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling\n\
- how to compose characters.\n\
-If the named font is not yet loaded, return nil.")
- (name, frame)
- Lisp_Object name, frame;
-{
- FRAME_PTR f;
- struct font_info *fontp;
- Lisp_Object info;
-
- (*check_window_system_func) ();
- CHECK_STRING (name, 0);
- if (NILP (frame))
- f = selected_frame;
- else
- {
- CHECK_LIVE_FRAME (frame, 1);
- f = XFRAME (frame);
- }
+DEFUN ("fontset-font", Ffontset_font, Sfontset_font, 2, 3, 0,
+ doc: /* Return a font name pattern for character CH in fontset NAME.
+If NAME is t, find a pattern in the default fontset.
- if (!query_font_func)
- error ("Font query function is not supported");
+The value has the form (FAMILY . REGISTRY), where FAMILY is a font
+family name and REGISTRY is a font registry name. This is actually
+the first font name pattern for CH in the fontset or in the default
+fontset.
- fontp = (*query_font_func) (f, XSTRING (name)->data);
- if (!fontp)
- return Qnil;
+If the 2nd optional arg ALL is non-nil, return a list of all font name
+patterns. */)
+ (name, ch, all)
+ Lisp_Object name, ch, all;
+{
+ int c;
+ Lisp_Object fontset, elt, list, repertory, val;
+ int i, j;
- info = Fmake_vector (make_number (7), Qnil);
+ fontset = check_fontset_name (name);
- XVECTOR (info)->contents[0] = build_string (fontp->name);
- XVECTOR (info)->contents[1] = build_string (fontp->full_name);
- XVECTOR (info)->contents[2] = CHARSET_SYMBOL (fontp->charset);
- XVECTOR (info)->contents[3] = make_number (fontp->size);
- XVECTOR (info)->contents[4] = make_number (fontp->height);
- XVECTOR (info)->contents[5] = make_number (fontp->baseline_offset);
- XVECTOR (info)->contents[6] = make_number (fontp->relative_compose);
- XVECTOR (info)->contents[7] = make_number (fontp->default_ascent);
+ CHECK_CHARACTER (ch);
+ c = XINT (ch);
+ list = Qnil;
+ while (1)
+ {
+ for (i = 0, elt = FONTSET_REF (fontset, c); i < 2;
+ i++, elt = FONTSET_FALLBACK (fontset))
+ if (VECTORP (elt))
+ for (j = 0; j < ASIZE (elt); j++)
+ {
+ val = AREF (elt, j);
+ repertory = AREF (val, 1);
+ if (INTEGERP (repertory))
+ {
+ struct charset *charset = CHARSET_FROM_ID (XINT (repertory));
- return info;
+ if (! CHAR_CHARSET_P (c, charset))
+ continue;
+ }
+ else if (CHAR_TABLE_P (repertory))
+ {
+ if (NILP (CHAR_TABLE_REF (repertory, c)))
+ continue;
+ }
+ val = AREF (val, 0);
+ val = Fcons (AREF (val, 0), AREF (val, 5));
+ if (NILP (all))
+ return val;
+ list = Fcons (val, list);
+ }
+ if (EQ (fontset, Vdefault_fontset))
+ break;
+ fontset = Vdefault_fontset;
+ }
+ return (Fnreverse (list));
}
-DEFUN ("fontset-info", Ffontset_info, Sfontset_info, 1, 2, 0,
- "Return information about a fontset named NAME on frame FRAME.\n\
-If FRAME is omitted or nil, use the selected frame.\n\
-The returned value is a vector of SIZE, HEIGHT, and FONT-LIST,\n\
-where\n\
- SIZE is the minimum bound width of ASCII font of the fontset,\n\
- HEIGHT is the height of the tallest font in the fontset, and\n\
- FONT-LIST is an alist of the format:\n\
- (CHARSET REQUESTED-FONT-NAME LOADED-FONT-NAME).\n\
-LOADED-FONT-NAME t means the font is not yet loaded, nil means the\n\
-loading failed.")
- (name, frame)
- Lisp_Object name, frame;
+DEFUN ("fontset-list", Ffontset_list, Sfontset_list, 0, 0, 0,
+ doc: /* Return a list of all defined fontset names. */)
+ ()
{
- FRAME_PTR f;
- int fontset;
- struct fontset_info *fontsetp;
- Lisp_Object info, val;
+ Lisp_Object fontset, list;
int i;
-
- (*check_window_system_func) ();
- CHECK_STRING(name, 0);
- if (NILP (frame))
- f = selected_frame;
- else
+ list = Qnil;
+ for (i = 0; i < ASIZE (Vfontset_table); i++)
{
- CHECK_LIVE_FRAME (frame, 1);
- f = XFRAME (frame);
+ fontset = FONTSET_FROM_ID (i);
+ if (!NILP (fontset)
+ && BASE_FONTSET_P (fontset))
+ list = Fcons (FONTSET_NAME (fontset), list);
}
- fontset = fs_query_fontset (f, XSTRING (name)->data);
- if (fontset < 0)
- error ("Fontset \"%s\" does not exist", XSTRING (name)->data);
+ return list;
+}
- info = Fmake_vector (make_number (3), Qnil);
- fontsetp = FRAME_FONTSET_DATA (f)->fontset_table[fontset];
+#ifdef FONTSET_DEBUG
- XVECTOR (info)->contents[0] = make_number (fontsetp->size);
- XVECTOR (info)->contents[1] = make_number (fontsetp->height);
- val = Qnil;
- for (i = 0; i <= MAX_CHARSET; i++)
- if (fontsetp->fontname[i])
- {
- int font_idx = fontsetp->font_indexes[i];
- Lisp_Object loaded;
-
- if (font_idx == FONT_NOT_OPENED)
- loaded = Qt;
- else if (font_idx == FONT_NOT_FOUND)
- loaded = Qnil;
- else
- loaded
- = build_string ((*get_font_info_func) (f, font_idx)->full_name);
- val = Fcons (Fcons (CHARSET_SYMBOL (i),
- Fcons (build_string (fontsetp->fontname[i]),
- Fcons (loaded, Qnil))),
- val);
- }
- XVECTOR (info)->contents[2] = val;
- return info;
+Lisp_Object
+dump_fontset (fontset)
+ Lisp_Object fontset;
+{
+ Lisp_Object vec;
+
+ vec = Fmake_vector (make_number (3), Qnil);
+ ASET (vec, 0, FONTSET_ID (fontset));
+
+ if (BASE_FONTSET_P (fontset))
+ {
+ ASET (vec, 1, FONTSET_NAME (fontset));
+ }
+ else
+ {
+ Lisp_Object frame;
+
+ frame = FONTSET_FRAME (fontset);
+ if (FRAMEP (frame))
+ {
+ FRAME_PTR f = XFRAME (frame);
+
+ if (FRAME_LIVE_P (f))
+ ASET (vec, 1, f->name);
+ else
+ ASET (vec, 1, Qt);
+ }
+ if (!NILP (FONTSET_DEFAULT (fontset)))
+ ASET (vec, 2, FONTSET_ID (FONTSET_DEFAULT (fontset)));
+ }
+ return vec;
}
-syms_of_fontset ()
+DEFUN ("fontset-list-all", Ffontset_list_all, Sfontset_list_all, 0, 0, 0,
+ doc: /* Return a brief summary of all fontsets for debug use. */)
+ ()
{
+ Lisp_Object val;
int i;
- for (i = 0; i < 256; i++)
- my_strcasetbl[i] = (i >= 'A' && i <= 'Z') ? i + 'a' - 'A' : i;
+ for (i = 0, val = Qnil; i < ASIZE (Vfontset_table); i++)
+ if (! NILP (AREF (Vfontset_table, i)))
+ val = Fcons (dump_fontset (AREF (Vfontset_table, i)), val);
+ return (Fnreverse (val));
+}
+#endif /* FONTSET_DEBUG */
+void
+syms_of_fontset ()
+{
if (!load_font_func)
/* Window system initializer should have set proper functions. */
abort ();
- Qfontset = intern ("fontset");
- staticpro (&Qfontset);
+ DEFSYM (Qfontset, "fontset");
+ Fput (Qfontset, Qchar_table_extra_slots, make_number (9));
+ DEFSYM (Qfontset_info, "fontset-info");
+ Fput (Qfontset_info, Qchar_table_extra_slots, make_number (1));
+
+ DEFSYM (Qprepend, "prepend");
+ DEFSYM (Qappend, "append");
Vcached_fontset_data = Qnil;
staticpro (&Vcached_fontset_data);
- DEFVAR_LISP ("global-fontset-alist", &Vglobal_fontset_alist,
- "Internal data for fontset. Not for external use.\n\
-This is an alist associating fontset names with the lists of fonts\n\
- contained in them.\n\
-Newly created frames make their own fontset database from here.");
- Vglobal_fontset_alist = Qnil;
+ Vfontset_table = Fmake_vector (make_number (32), Qnil);
+ staticpro (&Vfontset_table);
+
+ Vdefault_fontset = Fmake_char_table (Qfontset, Qnil);
+ staticpro (&Vdefault_fontset);
+ FONTSET_ID (Vdefault_fontset) = make_number (0);
+ FONTSET_NAME (Vdefault_fontset)
+ = build_string ("-*-*-*-*-*-*-*-*-*-*-*-*-fontset-default");
+ AREF (Vfontset_table, 0) = Vdefault_fontset;
+ next_fontset_id = 1;
+
+ auto_fontset_alist = Qnil;
+ staticpro (&auto_fontset_alist);
DEFVAR_LISP ("font-encoding-alist", &Vfont_encoding_alist,
- "Alist of fontname patterns vs corresponding encoding info.\n\
-Each element looks like (REGEXP . ENCODING-INFO),\n\
- where ENCODING-INFO is an alist of CHARSET vs ENCODING.\n\
-ENCODING is one of the following integer values:\n\
- 0: code points 0x20..0x7F or 0x2020..0x7F7F are used,\n\
- 1: code points 0xA0..0xFF or 0xA0A0..0xFFFF are used,\n\
- 2: code points 0x20A0..0x7FFF are used,\n\
- 3: code points 0xA020..0xFF7F are used.");
+ doc: /*
+Alist of fontname patterns vs the corresponding encoding and repertory info.
+Each element looks like (REGEXP . (ENCODING . REPERTORY)),
+where ENCODING is a charset or a char-table,
+and REPERTORY is a charset, a char-table, or nil.
+
+ENCODING is for converting a character to a glyph code of the font.
+If ENCODING is a charset, encoding a character by the charset gives
+the corresponding glyph code. If ENCODING is a char-table, looking up
+the table by a character gives the corresponding glyph code.
+
+REPERTORY specifies a repertory of characters supported by the font.
+If REPERTORY is a charset, all characters beloging to the charset are
+supported. If REPERTORY is a char-table, all characters who have a
+non-nil value in the table are supported. It REPERTORY is nil, Emacs
+gets the repertory information by an opened font and ENCODING. */);
Vfont_encoding_alist = Qnil;
DEFVAR_LISP ("use-default-ascent", &Vuse_default_ascent,
- "Char table of characters of which ascent values should be ignored.\n\
-If an entry for a character is non-nil, the ascent value of the glyph\n\
-is assumed to be what specified by _MULE_DEFAULT_ASCENT property of a font.");
+ doc: /*
+Char table of characters whose ascent values should be ignored.
+If an entry for a character is non-nil, the ascent value of the glyph
+is assumed to be what specified by _MULE_DEFAULT_ASCENT property of a font.
+
+This affects how a composite character which contains
+such a character is displayed on screen. */);
Vuse_default_ascent = Qnil;
- DEFVAR_LISP ("alternative-fontname-alist", &Valternative_fontname_alist,
- "Alist of fontname vs list of the alternative fontnames.
-When no font can be opened by a fontname, the corresponding
-alternative fontnames are tried.");
- Valternative_fontname_alist = Qnil;
+ DEFVAR_LISP ("ignore-relative-composition", &Vignore_relative_composition,
+ doc: /*
+Char table of characters which is not composed relatively.
+If an entry for a character is non-nil, a composition sequence
+which contains that character is displayed so that
+the glyph of that character is put without considering
+an ascent and descent value of a previous character. */);
+ Vignore_relative_composition = Qnil;
+
+ DEFVAR_LISP ("alternate-fontname-alist", &Valternate_fontname_alist,
+ doc: /* Alist of fontname vs list of the alternate fontnames.
+When a specified font name is not found, the corresponding
+alternate fontnames (if any) are tried instead. */);
+ Valternate_fontname_alist = Qnil;
+
+ DEFVAR_LISP ("fontset-alias-alist", &Vfontset_alias_alist,
+ doc: /* Alist of fontset names vs the aliases. */);
+ Vfontset_alias_alist = Fcons (Fcons (FONTSET_NAME (Vdefault_fontset),
+ build_string ("fontset-default")),
+ Qnil);
+
+ DEFVAR_LISP ("vertical-centering-font-regexp",
+ &Vvertical_centering_font_regexp,
+ doc: /* *Regexp matching font names that require vertical centering on display.
+When a character is displayed with such fonts, the character is displayed
+at the vertical center of lines. */);
+ Vvertical_centering_font_regexp = Qnil;
defsubr (&Squery_fontset);
defsubr (&Snew_fontset);
defsubr (&Sset_fontset_font);
defsubr (&Sfont_info);
+ defsubr (&Sinternal_char_font);
defsubr (&Sfontset_info);
+ defsubr (&Sfontset_font);
+ defsubr (&Sfontset_list);
+#ifdef FONTSET_DEBUG
+ defsubr (&Sfontset_list_all);
+#endif
}
+
+/* arch-tag: ea861585-2f5f-4e5b-9849-d04a9c3a3537
+ (do not change this comment) */