(define-charset): New args :min-code and :max-code.
[bpt/emacs.git] / src / fontset.c
index 0259b3e..34d27ce 100644 (file)
@@ -1,6 +1,9 @@
 /* Fontset handler.
    Copyright (C) 1995, 1997, 2000 Electrotechnical Laboratory, JAPAN.
    Licensed to the Free Software Foundation.
+   Copyright (C) 2001, 2002
+     National Institute of Advanced Industrial Science and Technology (AIST)
+     Registration Number H13PRO009
 
 This file is part of GNU Emacs.
 
@@ -28,8 +31,12 @@ Boston, MA 02111-1307, USA.  */
 #endif
 
 #include "lisp.h"
+#include "blockinput.h"
+#include "buffer.h"
+#include "character.h"
 #include "charset.h"
 #include "ccl.h"
+#include "keyboard.h"
 #include "frame.h"
 #include "dispextern.h"
 #include "fontset.h"
@@ -42,79 +49,76 @@ Boston, MA 02111-1307, USA.  */
 #define INLINE
 #endif
 
+EXFUN (Fclear_face_cache, 1);
 
 /* FONTSET
 
    A fontset is a collection of font related information to give
-   similar appearance (style, size, etc) of characters.  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
+   similar appearance (style, etc) of characters.  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 multibyte characters based on an ASCII
-   face.  All of the multibyte faces based on the same ASCII face
-   share the same realized fontset.
+   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.
-
-   An element of a base fontset is:
-       (INDEX . FONTNAME) or
-       (INDEX . (FOUNDRY . REGISTRY ))
-   FONTNAME is a font name pattern for the corresponding character.
-   FOUNDRY and REGISTRY are respectively foundy and regisry fields of
-   a font name for the corresponding character.  INDEX specifies for
-   which character (or generic character) the element is defined.  It
-   may be different from an index to access this element.  For
-   instance, if a fontset defines some font for all characters of
-   charset `japanese-jisx0208', INDEX is the generic character of this
-   charset.  REGISTRY is the
-
-   An element of a realized fontset is FACE-ID which is a face to use
-   for displaying the correspnding character.
-
-   All single byte charaters (ASCII and 8bit-unibyte) share the same
-   element in a fontset.  The element is stored in `defalt' slot of
-   the fontset.  And this slot is never used as a default value of
-   multibyte characters.  That means that the first 256 elements of a
-   fontset set is always nil (as this is not efficient, we may
-   implement a fontset in a different way in the future).
-
-   To access or set each element, use macros FONTSET_REF and
-   FONTSET_SET respectively for efficiency.
-
-   A fontset has 3 extra slots.
+   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 font specification of the form:
+       [ FAMILY WEIGHT SLANT SWIDTH REGISTRY ] (vector of size 5)
+   or
+       FONT-NAME (strig)
+
+   FAMILY and REGISTRY are strings.
+
+   WEIGHT, SLANT, and SWIDTH must be symbols that set-face-attribute
+   accepts as attribute values for :weight, :slant, :swidth
+   respectively.
+
+
+   A fontset has 7 extra slots.
 
    The 1st slot is an ID number of the fontset.
 
-   The 2nd slot is a name of the fontset.  This is nil for a realized
-   face.
+   The 2nd slot is a name of the fontset in a base fontset, and nil in
+   a realized fontset.
 
-   The 3rd slot is a frame that the fontset belongs to.  This is nil
-   for a default face.
+   The 3rd slot is nil in a base fontset, and a base fontset in a
+   realized fontset.
 
-   A parent of a base fontset is nil.  A parent of a realized fontset
-   is a base fontset.
+   The 4th slot is a frame that the fontset belongs to.  This is nil
+   in a base fontset.
 
-   All fontsets (except for the default fontset described below) are
-   recorded in Vfontset_table.
+   The 5th slot is a cons of 0 and fontname for ASCII characters in a
+   base fontset, and nil in a realized face.
+
+   The 6th slot is an alist of a charset vs. the corresponding font
+   specification.
+
+   The 7th slot is an alist of a font specification vs. the
+   corresponding face ID.  In a base fontset, the face IDs are all
+   nil.
+
+   All fontsets are recorded in Vfontset_table.
 
 
    DEFAULT FONTSET
 
-   There's a special fontset named `default fontset' which defines a
-   default fontname that contains only REGISTRY field for each
-   character.  When a base fontset doesn't specify a font for a
-   specific character, the corresponding value in the default fontset
-   is used.  The format is the same as a base fontset.
+   There's a special 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 format is the same as a base fontset.
 
-   The parent of realized fontsets created for faces that have no
-   fontset is the default fontset.
+   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 variable name `fontset' for IDs.  But, in this file, we
-   always use varialbe name `id' for IDs, and name `fontset' for the
-   actual fontset objects.
+   usually use the variable name `fontset' for IDs.  But, in this
+   file, we always use varialbe name `id' for IDs, and name `fontset'
+   for the actual fontset objects (i.e. char-table objects).
 
 */
 
@@ -126,12 +130,12 @@ Lisp_Object Qfontset;
 /* Vector containing all fontsets.  */
 static Lisp_Object Vfontset_table;
 
-/* Next possibly free fontset ID.  Usually this keeps the mininum
+/* 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 characters.  */
+   font for each character.  */
 static Lisp_Object Vdefault_fontset;
 
 Lisp_Object Vfont_encoding_alist;
@@ -139,8 +143,6 @@ Lisp_Object Vuse_default_ascent;
 Lisp_Object Vignore_relative_composition;
 Lisp_Object Valternate_fontname_alist;
 Lisp_Object Vfontset_alias_alist;
-Lisp_Object Vhighlight_wrong_size_font;
-Lisp_Object Vclip_large_size_font;
 Lisp_Object Vvertical_centering_font_regexp;
 
 /* The following six are declarations of callback functions depending
@@ -150,8 +152,8 @@ Lisp_Object Vvertical_centering_font_regexp;
 /* Return a pointer to struct font_info of font FONT_IDX of frame F.  */
 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.  */
+/* 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,
@@ -171,7 +173,7 @@ void (*set_frame_fontset_func) P_ ((FRAME_PTR f, Lisp_Object arg,
 
 /* 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 memer `encoder' of the structure.  */
+   This function set the member `encoder' of the structure.  */
 void (*find_ccl_program_func) P_ ((struct font_info *));
 
 /* Check if any window system is used now.  */
@@ -179,221 +181,197 @@ void (*check_window_system_func) P_ ((void));
 
 
 /* Prototype declarations for static functions.  */
-static Lisp_Object fontset_ref P_ ((Lisp_Object, int));
-static void fontset_set P_ ((Lisp_Object, int, Lisp_Object));
 static Lisp_Object make_fontset P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
 static int fontset_id_valid_p P_ ((int));
 static Lisp_Object fontset_pattern_regexp P_ ((Lisp_Object));
-static Lisp_Object font_family_registry P_ ((Lisp_Object));
 
 \f
 /********** MACROS AND FUNCTIONS TO HANDLE FONTSET **********/
 
-/* Macros for Lisp vector.  */
-#define AREF(V, IDX)   XVECTOR (V)->contents[IDX]
-#define ASIZE(V)       XVECTOR (V)->size
-
 /* Return the fontset with ID.  No check of ID's validness.  */
 #define FONTSET_FROM_ID(id) AREF (Vfontset_table, id)
 
-/* Macros to access extra, default, and parent slots, of fontset.  */
+/* 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_FRAME(fontset)         XCHAR_TABLE (fontset)->extras[2]
-#define FONTSET_ASCII(fontset)         XCHAR_TABLE (fontset)->defalt
-#define FONTSET_BASE(fontset)          XCHAR_TABLE (fontset)->parent
+#define FONTSET_ASCII(fontset)         XCHAR_TABLE (fontset)->extras[4]
 
-#define BASE_FONTSET_P(fontset)                NILP (FONTSET_BASE(fontset))
+#define BASE_FONTSET_P(fontset)                STRINGP (FONTSET_NAME (fontset))
+
+/* 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_CHARSET_ALIST(fontset) XCHAR_TABLE (fontset)->extras[5]
+#define FONTSET_FACE_ALIST(fontset)    XCHAR_TABLE (fontset)->extras[6]
 
 
 /* Return the element of FONTSET (char-table) at index C (character).  */
 
-#define FONTSET_REF(fontset, c)        fontset_ref (fontset, c)
+#define FONTSET_REF(fontset, c, etl)   ((elt) = fontset_ref ((fontset), (c)))
 
-static INLINE Lisp_Object
+static Lisp_Object
 fontset_ref (fontset, c)
      Lisp_Object fontset;
      int c;
 {
-  int charset, c1, c2;
-  Lisp_Object elt, defalt;
-  int i;
+  Lisp_Object elt;
 
-  if (SINGLE_BYTE_CHAR_P (c))
-    return FONTSET_ASCII (fontset);
-
-  SPLIT_NON_ASCII_CHAR (c, charset, c1, c2);
-  elt = XCHAR_TABLE (fontset)->contents[charset + 128];
-  if (!SUB_CHAR_TABLE_P (elt))
-    return elt;
-  defalt = XCHAR_TABLE (elt)->defalt;
-  if (c1 < 32
-      || (elt = XCHAR_TABLE (elt)->contents[c1],
-         NILP (elt)))
-    return defalt;
-  if (!SUB_CHAR_TABLE_P (elt))
-    return elt;
-  defalt = XCHAR_TABLE (elt)->defalt;
-  if (c2 < 32
-      || (elt = XCHAR_TABLE (elt)->contents[c2],
-         NILP (elt)))
-    return defalt;
+  while (1)
+    {
+      elt = CHAR_TABLE_REF (fontset, c);
+      if (NILP (elt) && ASCII_CHAR_P (c))
+       elt = FONTSET_ASCII (fontset);
+      if (NILP (elt))
+       {
+         Lisp_Object tail;
+         struct charset *charset;
+
+         for (tail = FONTSET_CHARSET_ALIST (fontset);
+              CONSP (tail);  tail = XCDR (tail))
+           {
+             charset = CHARSET_FROM_ID (XCAR (XCAR (tail)));
+             if (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset))
+               {
+                 elt = XCDR (XCAR (tail));
+                 break;
+               }
+           }
+       }
+      if (! NILP (elt) || EQ (fontset, Vdefault_fontset))
+       break;
+      fontset = Vdefault_fontset;
+    }
   return elt;
 }
 
 
-#define FONTSET_REF_VIA_BASE(fontset, c) fontset_ref_via_base (fontset, &c)
-
-static INLINE Lisp_Object
-fontset_ref_via_base (fontset, c)
-     Lisp_Object fontset;
-     int *c;
-{
-  int charset, c1, c2;
-  Lisp_Object elt;
-  int i;
+/* Set the element of FONTSET at index IDX to the value ELT.  IDX may
+   be a character or a charset.  */
 
-  if (SINGLE_BYTE_CHAR_P (*c))
-    return FONTSET_ASCII (fontset);
+#define FONTSET_SET(fontset, c, newelt) fontset_set(fontset, c, newelt)
 
-  elt = FONTSET_REF (FONTSET_BASE (fontset), *c);
-  if (NILP (elt))
-    return Qnil;
+static void
+fontset_set (fontset, idx, elt)
+     Lisp_Object fontset, idx, elt;
+{
+  if (SYMBOLP (idx))
+    {
+      Lisp_Object id, slot, tail;
+      
+      id = make_number (CHARSET_SYMBOL_ID (idx));
+      if (id == charset_ascii)
+       Fset_char_table_range (fontset,
+                              Fcons (make_number (0), make_number (127)),
+                              elt);
+      else
+       {
+         slot = Fassq (id, FONTSET_CHARSET_ALIST (fontset));
+         if (CONSP (slot))
+           XCDR (slot) = elt;
+         else if (CONSP (FONTSET_CHARSET_ALIST (fontset)))
+           {
+             for (tail = FONTSET_CHARSET_ALIST (fontset);
+                  CONSP (XCDR (tail)); tail = XCDR (tail));
+             XCDR (tail) = Fcons (Fcons (id, elt), Qnil);
+           }
+         else
+           FONTSET_CHARSET_ALIST (fontset) = Fcons (Fcons (id, elt), Qnil);
+       }
+    }
+  else
+    {
+      int from = XINT (XCAR (idx));
+      int to = XINT (XCDR (idx));
 
-  *c = XINT (XCAR (elt));
-  SPLIT_NON_ASCII_CHAR (*c, charset, c1, c2);
-  elt = XCHAR_TABLE (fontset)->contents[charset + 128];
-  if (c1 < 32)
-    return (SUB_CHAR_TABLE_P (elt) ? XCHAR_TABLE (elt)->defalt : elt);
-  if (!SUB_CHAR_TABLE_P (elt))
-    return Qnil;
-  elt = XCHAR_TABLE (elt)->contents[c1];
-  if (c2 < 32)
-    return (SUB_CHAR_TABLE_P (elt) ? XCHAR_TABLE (elt)->defalt : elt);
-  if (!SUB_CHAR_TABLE_P (elt))
-    return Qnil;
-  elt = XCHAR_TABLE (elt)->contents[c2];
-  return elt;
+      if (from == to)
+       CHAR_TABLE_SET (fontset, from, elt);
+      else
+       Fset_char_table_range (fontset, idx, elt);
+    }
 }
 
 
-/* Store into the element of FONTSET at index C the value NEWETL.  */
-#define FONTSET_SET(fontset, c, newelt) fontset_set(fontset, c, newelt)
+/* Return a face registerd in the realized fontset FONTSET for the
+   character C.  Return -1 if a face ID is not yet set.  */
 
-static void
-fontset_set (fontset, c, newelt)
+static struct face *
+fontset_face (fontset, c)
      Lisp_Object fontset;
      int c;
-     Lisp_Object newelt;
 {
-  int charset, code[3];
-  Lisp_Object *elt, tmp;
-  int i, j;
+  Lisp_Object base, elt;
+  int id;
+  struct face *face;
 
-  if (SINGLE_BYTE_CHAR_P (c))
-    {
-      FONTSET_ASCII (fontset) = newelt;
-      return;
-    }
+  base = FONTSET_BASE (fontset);
+  FONTSET_REF (base, c, elt);
 
-  SPLIT_NON_ASCII_CHAR (c, charset, code[0], code[1]);
-  code[2] = 0;                 /* anchor */
-  elt = &XCHAR_TABLE (fontset)->contents[charset + 128];
-  for (i = 0; code[i] > 0; i++)
-    {
-      if (!SUB_CHAR_TABLE_P (*elt))
-       *elt = make_sub_char_table (*elt);
-      elt = &XCHAR_TABLE (*elt)->contents[code[i]];
-    }
-  if (SUB_CHAR_TABLE_P (*elt))
-    XCHAR_TABLE (*elt)->defalt = newelt;
-  else
-    *elt = newelt;
+  if (NILP (elt))
+    return NULL;
+
+  elt = Fassoc (elt, FONTSET_FACE_ALIST (fontset));
+  if (! CONSP (elt))
+    return NULL;
+  id = XINT (XCDR (elt));
+  face = FACE_FROM_ID (XFRAME (FONTSET_FRAME (fontset)), id);
+  return face;
 }
 
 
 /* Return a newly created fontset with NAME.  If BASE is nil, make a
-   base fontset.  Otherwise make a realized fontset whose parent is
+   base fontset.  Otherwise make a realized fontset whose base is
    BASE.  */
 
 static Lisp_Object
 make_fontset (frame, name, base)
      Lisp_Object frame, name, base;
 {
-  Lisp_Object fontset, elt, base_elt;
+  Lisp_Object fontset;
   int size = ASIZE (Vfontset_table);
   int id = next_fontset_id;
-  int i, j;
 
   /* 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
-     Vfotnset_table is always nil, we don't have to check the range 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)
     {
       Lisp_Object tem;
-      int i; 
+      int i;
 
-      tem = Fmake_vector (make_number (size + 8), Qnil);
+      tem = Fmake_vector (make_number (size + 32), Qnil);
       for (i = 0; i < size; i++)
        AREF (tem, i) = AREF (Vfontset_table, i);
       Vfontset_table = tem;
     }
 
-  if (NILP (base))
-    fontset = Fcopy_sequence (Vdefault_fontset);
-  else
-    fontset = Fmake_char_table (Qfontset, Qnil);
+  fontset = Fmake_char_table (Qfontset, Qnil);
 
   FONTSET_ID (fontset) = make_number (id);
-  FONTSET_NAME (fontset) = name;
-  FONTSET_FRAME (fontset) = frame;
-  FONTSET_BASE (fontset) = base;
+  if (NILP (base))
+    {
+      FONTSET_NAME (fontset) = name;
+    }
+  else
+    {
+      FONTSET_NAME (fontset) = Qnil;
+      FONTSET_FRAME (fontset) = frame;
+      FONTSET_BASE (fontset) = base;
+    }
 
-  AREF (Vfontset_table, id) = fontset;
+  ASET (Vfontset_table, id, fontset);
   next_fontset_id = id + 1;
   return fontset;
 }
 
 
-/* Return 1 if ID is a valid fontset id, else return 0.  */
-
-static INLINE int
-fontset_id_valid_p (id)
-     int id;
-{
-  return (id >= 0 && id < ASIZE (Vfontset_table) - 1);
-}
-
-
-/* Extract `family' and `registry' string from FONTNAME and set in
-   *FAMILY and *REGISTRY respectively.  Actually, `family' may also
-   contain `foundry', `registry' may also contain `encoding' of
-   FONTNAME.  */
-
-static Lisp_Object
-font_family_registry (fontname)
-     Lisp_Object fontname;
-{
-  Lisp_Object family, registry;
-  char *p = XSTRING (fontname)->data;
-  char *sep[15];
-  int i = 0;
-  
-  while (*p && i < 15) if (*p++ == '-') sep[i++] = p;
-  if (i != 14)
-    return fontname;
-
-  family = make_unibyte_string (sep[0], sep[2] - 1 - sep[0]);
-  registry = make_unibyte_string (sep[12], p - sep[12]);
-  return Fcons (family, registry);
-}
-
 \f
-/********** INTERFACES TO xfaces.c and dispextern.h **********/ 
+/********** INTERFACES TO xfaces.c and dispextern.h **********/
 
 /* Return name of the fontset with ID.  */
 
@@ -402,6 +380,7 @@ fontset_name (id)
      int id;
 {
   Lisp_Object fontset;
+
   fontset = FONTSET_FROM_ID (id);
   return FONTSET_NAME (fontset);
 }
@@ -413,56 +392,47 @@ Lisp_Object
 fontset_ascii (id)
      int id;
 {
-  Lisp_Object fontset, elt;
+  Lisp_Object fontset;
+
   fontset= FONTSET_FROM_ID (id);
-  elt = FONTSET_ASCII (fontset);
-  return XCDR (elt);
+  return FONTSET_ASCII (fontset);
 }
 
 
-/* Free fontset of FACE.  Called from free_realized_face.  */
+/* 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;
 {
-  if (fontset_id_valid_p (face->fontset))
-    {
-      AREF (Vfontset_table, face->fontset) = Qnil;
-      if (face->fontset < next_fontset_id)
-       next_fontset_id = face->fontset;
-    }
+  AREF (Vfontset_table, face->fontset) = Qnil;
+  if (face->fontset < next_fontset_id)
+    next_fontset_id = face->fontset;
 }
 
 
 /* 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 a single byte character..  */
+   when C is not an ASCII character.  */
 
 int
 face_suitable_for_char_p (face, c)
      struct face *face;
      int c;
 {
-  Lisp_Object fontset, elt;
-
-  if (SINGLE_BYTE_CHAR_P (c))
-    return (face == face->ascii_face);
+  Lisp_Object fontset;
 
-  xassert (fontset_id_valid_p (face->fontset));
   fontset = FONTSET_FROM_ID (face->fontset);
-  xassert (!BASE_FONTSET_P (fontset));
-
-  elt = FONTSET_REF_VIA_BASE (fontset, c);
-  return (!NILP (elt) && face->id == XFASTINT (elt));
+  return (face == fontset_face (fontset, c));
 }
 
 
 /* Return ID of face suitable for displaying character C on frame F.
    The selection of face is done based on the fontset of FACE.  FACE
-   should already have been realized for ASCII characters.  Called
-   from the macro FACE_FOR_CHAR when C is not a single byte character.  */
+   must be reazlied for ASCII characters in advance.  Called from the
+   macro FACE_FOR_CHAR when C is not an ASCII character.  */
 
 int
 face_for_char (f, face, c)
@@ -470,25 +440,20 @@ face_for_char (f, face, c)
      struct face *face;
      int c;
 {
-  Lisp_Object fontset, elt;
-  int face_id;
+  Lisp_Object fontset;
+  struct face *new_face;
 
   xassert (fontset_id_valid_p (face->fontset));
   fontset = FONTSET_FROM_ID (face->fontset);
   xassert (!BASE_FONTSET_P (fontset));
 
-  elt = FONTSET_REF_VIA_BASE (fontset, c);
-  if (!NILP (elt))
-    return XINT (elt);
+  new_face = fontset_face (fontset, c);
+  if (new_face)
+    return new_face->id;
 
   /* No face is recorded for C in the fontset of FACE.  Make a new
      realized face for C that has the same fontset.  */
-  face_id = lookup_face (f, face->lface, c, face);
-  
-  /* Record the face ID in FONTSET at the same index as the
-     information in the base fontset.  */
-  FONTSET_SET (fontset, c, make_number (face_id));
-  return face_id;
+  return lookup_face (f, face->lface, c, face);
 }
 
 
@@ -502,7 +467,7 @@ make_fontset_for_ascii_face (f, base_fontset_id)
      FRAME_PTR f;
      int base_fontset_id;
 {
-  Lisp_Object base_fontset, fontset, name, frame;
+  Lisp_Object base_fontset, fontset, frame;
 
   XSETFRAME (frame, f);
   if (base_fontset_id >= 0)
@@ -516,173 +481,97 @@ make_fontset_for_ascii_face (f, base_fontset_id)
     base_fontset = Vdefault_fontset;
 
   fontset = make_fontset (frame, Qnil, base_fontset);
-  return FONTSET_ID (fontset);
+  return XINT (FONTSET_ID (fontset));
 }
 
 
-/* Return the font name pattern for C that is recorded in the fontset
-   with ID.  A font is opened by that pattern to get the fullname.  If
-   the fullname conform to XLFD, extract foundry-family field and
-   registry-encoding field, and return the cons of them.  Otherwise
-   return the fullname.  If ID is -1, or the fontset doesn't contain
-   information about C, get the registry and encoding of C from the
-   default fontset.  Called from choose_face_font.  */
+/* Return FONT-SPEC recorded in the fontset of FACE for character C.
+   If FACE is null, or the fontset doesn't contain information about
+   C, get the font name pattern from the default fontset.  Called from
+   choose_face_font.  */
 
 Lisp_Object
-fontset_font_pattern (f, id, c)
+fontset_font_pattern (f, face, c)
      FRAME_PTR f;
-     int id, c;
+     struct face *face;
+     int c;
 {
-  Lisp_Object fontset, elt;
-  struct font_info *fontp;
-  Lisp_Object family_registry;
-  
-  elt = Qnil;
-  if (fontset_id_valid_p (id))
+  Lisp_Object fontset, base, elt;
+  int id = face ? face->fontset : -1;
+
+  if (id >= 0)
     {
       fontset = FONTSET_FROM_ID (id);
       xassert (!BASE_FONTSET_P (fontset));
-      fontset = FONTSET_BASE (fontset);
-      elt = FONTSET_REF (fontset, c);
+      base = FONTSET_BASE (fontset);
     }
   else
-    elt = FONTSET_REF (Vdefault_fontset, c);
-
-  if (!CONSP (elt))
-    return Qnil;
-  if (CONSP (XCDR (elt)))
-    return XCDR (elt);
-
-  /* The fontset specifies only a font name pattern (not cons of
-     family and registry).  Try to open a font by that pattern and get
-     a registry from the full name of the opened font.  We ignore
-     family name here because it should be wild card in the fontset
-     specification.  */
-  elt = XCDR (elt);
-  xassert (STRINGP (elt));
-  fontp = FS_LOAD_FONT (f, c, XSTRING (elt)->data, -1);
-  if (!fontp)
-    return Qnil;
+    {
+      base = Vdefault_fontset;
+    }
 
-  family_registry = font_family_registry (build_string (fontp->full_name));
-  if (!CONSP (family_registry))
-    return family_registry;
-  XCAR (family_registry) = Qnil;
-  return family_registry;
+  FONTSET_REF (base, c, elt);
+  if (face && ! NILP (elt))
+    {
+      Lisp_Object slot;
+
+      slot = Fassoc (elt, FONTSET_FACE_ALIST (fontset));
+      if (CONSP (slot))
+       XSETCDR (slot, make_number (face->id));
+      FONTSET_FACE_ALIST (fontset)      
+       = Fcons (Fcons (elt, make_number (face->id)),
+                FONTSET_FACE_ALIST (fontset));
+    }
+  return elt;
 }
 
 
-/* Load a font named FONTNAME to display character C on frame F.
-   Return a pointer to the struct font_info of the loaded font.  If
-   loading fails, return NULL.  If FACE is non-zero and a fontset is
-   assigned to it, record FACE->id in the fontset for C.  If FONTNAME
-   is NULL, the name is taken from the fontset of FACE or what
-   specified by ID.  */
+#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.  */
 
 struct font_info *
-fs_load_font (f, c, fontname, id, face)
+fs_load_font (f, fontname)
      FRAME_PTR f;
-     int c;
      char *fontname;
-     int id;
-     struct face *face;
 {
-  Lisp_Object fontset;
-  Lisp_Object list, elt;
-  int font_idx;
-  int size = 0;
+  Lisp_Object tail, elt;
   struct font_info *fontp;
-  int charset = CHAR_CHARSET (c);
-
-  if (face)
-    id = face->fontset;
-  if (id < 0)
-    fontset = Qnil;
-  else
-    fontset = FONTSET_FROM_ID (id);
-
-  if (!NILP (fontset)
-      && !BASE_FONTSET_P (fontset))
-    {
-      elt = FONTSET_REF_VIA_BASE (fontset, c);
-      if (!NILP (elt))
-       {
-         /* A suitable face for C is already recorded, which means
-            that a proper font is already loaded.  */
-         int face_id = XINT (elt);
-
-         xassert (face_id == face->id);
-         face = FACE_FROM_ID (f, face_id);
-         return (*get_font_info_func) (f, face->font_info_id);
-       }
-
-      if (!fontname && charset == CHARSET_ASCII)
-       {
-         elt = FONTSET_ASCII (fontset);
-         fontname = XSTRING (XCDR (elt))->data;
-       }
-    }
 
   if (!fontname)
     /* No way to get fontname.  */
     return 0;
 
-  fontp = (*load_font_func) (f, fontname, size);
+  fontp = (*load_font_func) (f, fontname, 0);
   if (!fontp)
-    return 0;
+    return NULL;
 
+  fontname = fontp->full_name;
   /* Fill in members (charset, vertical_centering, encoding, etc) of
      font_info structure that are not set by (*load_font_func).  */
-  fontp->charset = charset;
-
-  fontp->vertical_centering
-    = (STRINGP (Vvertical_centering_font_regexp)
-       && (fast_c_string_match_ignore_case 
-          (Vvertical_centering_font_regexp, fontp->full_name) >= 0));
-
-  if (fontp->encoding[1] != FONT_ENCODING_NOT_DECIDED)
+  for (tail = Vfont_encoding_alist; CONSP (tail); tail = XCDR (tail))
     {
-      /* The font itself tells which code points to be used.  Use this
-        encoding for all other charsets.  */
-      int i;
-
-      fontp->encoding[0] = fontp->encoding[1];
-      for (i = MIN_CHARSET_OFFICIAL_DIMENSION1; i <= MAX_CHARSET; i++)
-       fontp->encoding[i] = fontp->encoding[1];
-    }
-  else
-    {
-      /* The font itself doesn't have information about encoding.  */
-      int i;
-
-      /* 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 = XCDR (list))
+      elt = XCAR (tail);
+      if (STRINGP (XCAR (elt)) && CHARSETP (XCDR (elt))
+         && fast_c_string_match_ignore_case (XCAR (elt), fontname) >= 0)
        {
-         elt = XCAR (list);
-         if (CONSP (elt)
-             && STRINGP (XCAR (elt)) && CONSP (XCDR (elt))
-             && (fast_c_string_match_ignore_case (XCAR (elt), fontname)
-                 >= 0))
-           {
-             Lisp_Object tmp;
-
-             for (tmp = XCDR (elt); CONSP (tmp); tmp = XCDR (tmp))
-               if (CONSP (XCAR (tmp))
-                   && ((i = get_charset_id (XCAR (XCAR (tmp))))
-                       >= 0)
-                   && INTEGERP (XCDR (XCAR (tmp)))
-                   && XFASTINT (XCDR (XCAR (tmp))) < 4)
-                 fontp->encoding[i]
-                   = XFASTINT (XCDR (XCAR (tmp)));
-           }
+         fontp->charset = CHARSET_SYMBOL_ID (XCDR (elt));
+         break;
        }
     }
+  if (! CONSP (tail))
+    return NULL;
 
-  fontp->font_encoder = (struct ccl_program *) 0;
+  fontp->vertical_centering
+    = (STRINGP (Vvertical_centering_font_regexp)
+       && (fast_c_string_match_ignore_case
+          (Vvertical_centering_font_regexp, fontname) >= 0));
+
+  fontp->font_encoder = NULL;
 
   if (find_ccl_program_func)
     (*find_ccl_program_func) (fontp);
@@ -690,6 +579,10 @@ fs_load_font (f, c, fontname, id, face)
   return fontp;
 }
 
+#if defined(WINDOWSNT) && defined (_MSC_VER)
+#pragma optimize("", on)
+#endif
+
 \f
 /* Cache data used by fontset_pattern_regexp.  The car part is a
    pattern string containing at least one wild card, the cdr part is
@@ -715,7 +608,7 @@ fontset_pattern_regexp (pattern)
       || strcmp (XSTRING (pattern)->data, CACHED_FONTSET_NAME))
     {
       /* We must at first update the cached data.  */
-      char *regex = (char *) alloca (XSTRING (pattern)->size * 2);
+      char *regex = (char *) alloca (XSTRING (pattern)->size * 2 + 3);
       char *p0, *p1 = regex;
 
       /* Convert "*" to ".*", "?" to ".".  */
@@ -750,7 +643,7 @@ fs_query_fontset (name, regexpp)
      Lisp_Object name;
      int regexpp;
 {
-  Lisp_Object fontset, tem;
+  Lisp_Object tem;
   int i;
 
   name = Fdowncase (name);
@@ -791,12 +684,12 @@ fs_query_fontset (name, regexpp)
 
 
 DEFUN ("query-fontset", Fquery_fontset, Squery_fontset, 1, 2, 0,
-  "Return the name of a fontset that matches PATTERN.\n\
-The value is nil if there is no matching fontset.\n\
-PATTERN can contain `*' or `?' as a wildcard\n\
-just as X font name matching algorithm allows.\n\
-If REGEXPP is non-nil, PATTERN is a regular expression.")
-  (pattern, regexpp)
+       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;
@@ -804,7 +697,7 @@ If REGEXPP is non-nil, PATTERN is a regular expression.")
 
   (*check_window_system_func) ();
 
-  CHECK_STRING (pattern, 0);
+  CHECK_STRING (pattern);
 
   if (XSTRING (pattern)->size == 0)
     return Qnil;
@@ -817,9 +710,7 @@ If REGEXPP is non-nil, PATTERN is a regular expression.")
   return FONTSET_NAME (fontset);
 }
 
-/* Return a list of base fontset names matching PATTERN on frame F.
-   If SIZE is not 0, it is the size (maximum bound width) of fontsets
-   to be listed. */
+/* Return a list of base fontset names matching PATTERN on frame F.  */
 
 Lisp_Object
 list_fontsets (f, pattern, size)
@@ -827,7 +718,7 @@ list_fontsets (f, pattern, size)
      Lisp_Object pattern;
      int size;
 {
-  Lisp_Object frame, regexp, val, tail;
+  Lisp_Object frame, regexp, val;
   int id;
 
   XSETFRAME (frame, f);
@@ -852,109 +743,51 @@ list_fontsets (f, pattern, size)
          : strcmp (XSTRING (pattern)->data, name))
        continue;
 
-      if (size)
-       {
-         struct font_info *fontp;
-         fontp = FS_LOAD_FONT (f, 0, NULL, id);
-         if (!fontp || size != fontp->size)
-           continue;
-       }
       val = Fcons (Fcopy_sequence (FONTSET_NAME (fontset)), val);
     }
 
   return val;
 }
 
-DEFUN ("new-fontset", Fnew_fontset, Snew_fontset, 2, 2, 0,
-  "Create a new fontset NAME that contains font information in FONTLIST.\n\
-FONTLIST is an alist of charsets vs corresponding font name patterns.")
-  (name, fontlist)
-     Lisp_Object name, fontlist;
-{
-  Lisp_Object fontset, elements, ascii_font;
-  Lisp_Object tem, tail, elt;
-
-  (*check_window_system_func) ();
-
-  CHECK_STRING (name, 0);
-  CHECK_LIST (fontlist, 1);
-
-  name = Fdowncase (name);
-  tem = Fquery_fontset (name, Qnil);
-  if (!NILP (tem))
-    error ("Fontset `%s' matches the existing fontset `%s'",
-          XSTRING (name)->data, XSTRING (tem)->data);
-
-  /* Check the validity of FONTLIST while creating a template for
-     fontset elements.  */
-  elements = ascii_font = Qnil;
-  for (tail = fontlist; CONSP (tail); tail = XCDR (tail))
-    {
-      Lisp_Object family, registry;
-      int c, charset;
-
-      tem = XCAR (tail);
-      if (!CONSP (tem)
-         || (charset = get_charset_id (XCAR (tem))) < 0
-         || !STRINGP (XCDR (tem)))
-       error ("Elements of fontlist must be a cons of charset and font name");
-
-      tem = Fdowncase (XCDR (tem));
-      if (charset == CHARSET_ASCII)
-       ascii_font = tem;
-      else
-       {
-         c = MAKE_CHAR (charset, 0, 0);
-         elements = Fcons (Fcons (make_number (c), tem), elements);
-       }
-    }
-
-  if (NILP (ascii_font))
-    error ("No ASCII font in the fontlist");
-
-  fontset = make_fontset (Qnil, name, Qnil);
-  FONTSET_ASCII (fontset) = Fcons (make_number (0), ascii_font);
-  for (; CONSP (elements); elements = XCDR (elements))
-    {
-      elt = XCAR (elements);
-      tem = Fcons (XCAR (elt), font_family_registry (XCDR (elt)));
-      FONTSET_SET (fontset, XINT (XCAR (elt)), tem);
-    }
-
-  return Qnil;
-}
-
 
-/* Clear all elements of FONTSET for multibyte characters.  */
+/* Free all realized fontsets whose base fontset is BASE.  */ 
 
 static void
-clear_fontset_elements (fontset)
-     Lisp_Object fontset;
+free_realized_fontsets (base)
+     Lisp_Object base;
 {
-  int i;
-
-  for (i = CHAR_TABLE_SINGLE_BYTE_SLOTS; i < CHAR_TABLE_ORDINARY_SLOTS; i++)
-    XCHAR_TABLE (fontset)->contents[i] = Qnil;
-}
-
+#if 0
+  int id;
 
-/* Return 1 iff REGISTRY is a valid string as the font registry and
-   encoding.  It is valid if it doesn't start with `-' and the number
-   of `-' in the string is at most 1.  */
+  /* 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);
 
-static int
-check_registry_encoding (registry)
-     Lisp_Object registry;
-{
-  unsigned char *str = XSTRING (registry)->data;
-  unsigned char *p = str;
-  int i;
+      if (EQ (FONTSET_BASE (this), base))
+       {
+         Lisp_Object tail;
 
-  if (!*p || *p++ == '-')
-    return 0;
-  for (i = 0; *p; p++)
-    if (*p == '-') i++;
-  return (i < 2);
+         for (tail = FONTSET_FACE_ALIST (this); CONSP (tail);
+              tail = XCDR (tail))
+           {
+             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 */
 }
 
 
@@ -971,7 +804,7 @@ check_fontset_name (name)
   if (EQ (name, Qt))
     return Vdefault_fontset;
 
-  CHECK_STRING (name, 0);
+  CHECK_STRING (name);
   id = fs_query_fontset (name, 0);
   if (id < 0)
     error ("Fontset `%s' does not exist", XSTRING (name)->data);
@@ -979,113 +812,160 @@ check_fontset_name (name)
 }
 
 DEFUN ("set-fontset-font", Fset_fontset_font, Sset_fontset_font, 3, 4, 0,
-  "Modify fontset NAME to use FONTNAME for character CHAR.\n\
-\n\
-CHAR may be a cons; (FROM . TO), where FROM and TO are\n\
-non-generic characters.  In that case, use FONTNAME\n\
-for all characters in the range FROM and TO (inclusive).\n\
-\n\
-If NAME is t, an entry in the default fontset is modified.\n\
-In that case, FONTNAME should be a registry and encoding name\n\
-of a font for CHAR.")
-  (name, ch, fontname, frame)
-     Lisp_Object name, ch, fontname, frame;
+       doc: /* Modify fontset NAME to use FONT-SPEC for characters of CHARSETS.
+
+CHARSET 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).
+
+FONT-SPEC is be a vector; [ FAMILY WEIGHT SLANT WIDTH ADSTYLE REGISTRY ]
+
+FONT-SPEC may be a cons; (FAMILY . REGISTRY), where FAMILY is a family
+name of a font, REGSITRY is a registry name of a font.
+
+FONT-SPEC may be a font name string.  */)
+     (name, charset, font_spec, frame)
+     Lisp_Object name, charset, font_spec, frame;
 {
-  Lisp_Object fontset, elt;
-  Lisp_Object realized;
-  int from, to;
-  int id;
+  Lisp_Object fontset;
+  Lisp_Object family, registry;
 
   fontset = check_fontset_name (name);
 
-  if (CONSP (ch))
+  if (VECTORP (font_spec))
     {
-      /* CH should be (FROM . TO) where FROM and TO are non-generic
-        characters.  */
-      CHECK_NUMBER (XCAR (ch), 1);
-      CHECK_NUMBER (XCDR (ch), 1);
-      from = XINT (XCAR (ch));
-      to = XINT (XCDR (ch));
-      if (!char_valid_p (from, 0) || !char_valid_p (to, 0))
-       error ("Character range should be by non-generic characters.");
-      if (!NILP (name)
-         && (SINGLE_BYTE_CHAR_P (from) || SINGLE_BYTE_CHAR_P (to)))
-       error ("Can't change font for a single byte character");
-    }
-  else
-    {
-      CHECK_NUMBER (ch, 1);
-      from = XINT (ch);
-      to = from;
+      int i;
+      Lisp_Object val;
+
+      font_spec = Fcopy_sequence (font_spec);
+      for (i = 0; i < 5; i++)
+       {
+         val = Faref (font_spec, make_number (i));
+         if (! NILP (val))
+           {
+             CHECK_STRING (val);
+             ASET (font_spec, i, Fdowncase (val));
+           }
+       }
+      val = Faref (font_spec, make_number (5));
+      CHECK_STRING (val);
+      ASET (font_spec, 5, Fdowncase (val));
     }
-  if (!char_valid_p (from, 1))
-    invalid_character (from);
-  if (SINGLE_BYTE_CHAR_P (from))
-    error ("Can't change font for a single byte character");
-  if (from < to)
+  else if (STRINGP (font_spec))
+    font_spec = Fdowncase (font_spec);
+  else if (CONSP (font_spec))
     {
-      if (!char_valid_p (to, 1))
-       invalid_character (to);
-      if (SINGLE_BYTE_CHAR_P (to))
-       error ("Can't change font for a single byte character");
+      CHECK_CONS (font_spec);
+      family = XCAR (font_spec);
+      registry = XCDR (font_spec);
+      font_spec = Fmake_vector (make_number (6), Qnil);
+      if (!NILP (family))
+       {
+         CHECK_STRING (family);
+         ASET (font_spec, 0, Fdowncase (family));
+       }
+      CHECK_STRING (registry);
+      ASET (font_spec, 5, Fdowncase (registry));
     }
 
-  CHECK_STRING (fontname, 2);
-  fontname = Fdowncase (fontname);
-  if (fontset == Vdefault_fontset)
+  if (SYMBOLP (charset))
     {
-      if (!check_registry_encoding (fontname))
-       error ("Invalid registry and encoding name: %s",
-              XSTRING (fontname)->data);
-      elt = Fcons (make_number (from), Fcons (Qnil, fontname));
+      CHECK_CHARSET (charset);
     }
   else
-    elt = Fcons (make_number (from), font_family_registry (fontname));
+    {
+      Lisp_Object from, to;
+
+      /* CHARSET should be (FROM . TO).  */
+      from = Fcar (charset);
+      to = Fcdr (charset);
+      CHECK_CHARACTER (from);
+      CHECK_CHARACTER (to);
+    }
 
   /* The arg FRAME is kept for backward compatibility.  We only check
      the validity.  */
   if (!NILP (frame))
-    CHECK_LIVE_FRAME (frame, 3);
+    CHECK_LIVE_FRAME (frame);
 
-  for (; from <= to; from++)
-    FONTSET_SET (fontset, from, elt);
-  Foptimize_char_table (fontset);
+  FONTSET_SET (fontset, charset, font_spec);
 
-  /* If there's a realized fontset REALIZED whose parent is FONTSET,
-     clear all the elements of REALIZED and free all multibyte faces
-     whose fontset is REALIZED.  This way, the specified character(s)
-     are surely redisplayed by a correct font.  */
-  for (id = 0; id < ASIZE (Vfontset_table); id++)
-    {
-      realized = AREF (Vfontset_table, id);
-      if (!NILP (realized)
-         && !BASE_FONTSET_P (realized)
-         && EQ (FONTSET_BASE (realized), fontset))
-       {
-         FRAME_PTR f = XFRAME (FONTSET_FRAME (realized));
-         clear_fontset_elements (realized);
-         free_realized_multibyte_face (f, id);
-       }
-    }
+  /* 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);
 
   return Qnil;
 }
 
+
+DEFUN ("new-fontset", Fnew_fontset, Snew_fontset, 2, 2, 0,
+       doc: /* Create a new fontset NAME from font information in FONTLIST.
+
+FONTLIST is an alist of charsets vs corresponding font specifications.
+Each element of FONTLIST has the form (CHARSET . FONT-SPEC), where
+a character of CHARSET is displayed by a font that matches FONT-SPEC.
+
+FONT-SPEC is a vector [ FAMILY WEIGHT SLANT WIDTH ADSTYLE REGISTRY ], where
+FAMILY is a string specifying the font family,
+WEIGHT is a string specifying the weight of the font,
+SLANT is a string specifying the slant of the font,
+WIDTH is a string specifying the width of the font,
+ADSTYLE is a string specifying the adstyle of the font,
+REGISTRY is a string specifying the charset-registry of the font.
+
+See also the documentation of `set-face-attribute' for the detail of
+these vector elements.
+
+FONT-SPEC may be a font name (string).  */)
+  (name, fontlist)
+     Lisp_Object name, fontlist;
+{
+  Lisp_Object fontset, ascii_font;
+  Lisp_Object tem, tail;
+
+  CHECK_STRING (name);
+  CHECK_LIST (fontlist);
+
+  name = Fdowncase (name);
+  tem = Fquery_fontset (name, Qnil);
+  if (! NILP (tem))
+    free_realized_fontsets (tem);
+
+  fontset = make_fontset (Qnil, name, Qnil);
+
+  /* Check the validity of FONTLIST.  */
+  ascii_font = Fcdr (Fassq (Qascii, fontlist));
+  if (NILP (ascii_font))
+    error ("No ascii font specified");
+  if (! STRINGP (ascii_font))
+    ascii_font = generate_ascii_font (name, ascii_font);
+
+  fontlist = Fcopy_sequence (fontlist);
+  for (tail = fontlist; ! NILP (tail); tail = Fcdr (tail))
+    Fset_fontset_font (name, Fcar (Fcar (tail)), Fcdr (Fcar (tail)), Qnil);
+
+  FONTSET_ASCII (fontset) = ascii_font;
+
+  return name;
+}
+
+
 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\
-  SIZE is the maximum 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)
+       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;
 {
   FRAME_PTR f;
@@ -1094,11 +974,11 @@ If the named font is not yet loaded, return nil.")
 
   (*check_window_system_func) ();
 
-  CHECK_STRING (name, 0);
+  CHECK_STRING (name);
   name = Fdowncase (name);
   if (NILP (frame))
     frame = selected_frame;
-  CHECK_LIVE_FRAME (frame, 1);
+  CHECK_LIVE_FRAME (frame);
   f = XFRAME (frame);
 
   if (!query_font_func)
@@ -1121,134 +1001,241 @@ If the named font is not yet loaded, return nil.")
   return info;
 }
 
+
+/* Return 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.  It returns nil in the following cases:
+
+   (1) The window system doesn't have a font for the character (thus
+   it is displayed by an empty box).
+
+   (2) The character code is invalid.
+
+   (3) The current buffer is not displayed in any window.
+
+   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.  */
+
+
+DEFUN ("internal-char-font", Finternal_char_font, Sinternal_char_font, 1, 1, 0,
+       doc: /* For internal use only.  */)
+     (position)
+     Lisp_Object position;
+{
+  int pos, pos_byte, dummy;
+  int face_id;
+  int c;
+  Lisp_Object window;
+  struct window *w;
+  struct frame *f;
+  struct face *face;
+
+  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);
+  c = FETCH_CHAR (pos_byte);
+  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);
+  face_id = FACE_FOR_CHAR (f, FACE_FROM_ID (f, face_id), c);
+  face = FACE_FROM_ID (f, face_id);
+  return (face->font && face->font_name
+         ? build_string (face->font_name)
+         : Qnil);
+}
+
+
+#if 0                          /* unused */
+/* Called from Ffontset_info via map_char_table on each leaf of
+   fontset.  ARG is a list (LAST FONT-INFO ...), where LAST is `(last
+   ARG)' and FONT-INFOs have this form:
+       (CHAR FONT-SPEC) or ((FROM . TO) FONT-SPEC)
+   The current leaf is indexed by CHARACTER and has value ELT.  This
+   function add the information of the current leaf to ARG by
+   appending a new element or modifying the last element..  */
+
+static void
+accumulate_font_info (arg, character, elt)
+     Lisp_Object arg, character, elt;
+{
+  Lisp_Object last, last_char, last_elt;
+
+  if (!CONSP (elt) && !SINGLE_BYTE_CHAR_P (XINT (character)))
+    FONTSET_REF (Vdefault_fontset, XINT (character), elt);
+  if (!CONSP (elt))
+    return;
+  last = XCAR (arg);
+  last_char = XCAR (XCAR (last));
+  last_elt = XCAR (XCDR (XCAR (last)));
+  elt = XCDR (elt);
+  if (!NILP (Fequal (elt, last_elt)))
+    {
+      struct charset *this_charset = CHAR_CHARSET (XINT (character));
+
+      if (CONSP (last_char))   /* LAST_CHAR == (FROM . TO)  */
+       {
+         if (this_charset == CHAR_CHARSET (XINT (XCAR (last_char))))
+           {
+             XSETCDR (last_char, character);
+             return;
+           }
+       }
+      else if (XINT (last_char) == XINT (character))
+       return;
+      else if (this_charset == CHAR_CHARSET (XINT (last_char)))
+       {
+         XSETCAR (XCAR (last), Fcons (last_char, character));
+         return;
+       }
+    }
+  XSETCDR (last, Fcons (Fcons (character, Fcons (elt, Qnil)), Qnil));
+  XSETCAR (arg, XCDR (last));
+}
+#endif /* 0 */
+
 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 maximum bound width of ASCII font of the fontset,\n\
-  HEIGHT is the height of the ASCII 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)
+       doc: /* Return information about a fontset named NAME on frame FRAME.
+The value is a vector:
+  [ SIZE HEIGHT ((CHARSET-OR-RANGE FONT-SPEC OPENED ...) ...) ],
+where,
+  SIZE is the maximum bound width of ASCII font in the fontset,
+  HEIGHT is the maximum bound height of ASCII font in the fontset,
+  CHARSET-OR-RANGE is a charset or a cons of two characters specifying
+    the range of characters.
+  FONT-SPEC is a fontname pattern string or a vector
+    [ FAMILY WEIGHT SLANT WIDTH ADSTYLE REGISTRY ].
+    See the documentation of `new-fontset' for the meanings those elements.
+  OPENEDs are names of fonts actually opened.
+If the ASCII font is not yet opened, SIZE and HEIGHT are 0.
+If FRAME is omitted, it defaults to the currently selected frame.  */)
+     (name, frame)
      Lisp_Object name, frame;
 {
+  Lisp_Object fontset;
   FRAME_PTR f;
-  Lisp_Object fontset, realized;
-  Lisp_Object info, val, loaded, requested;
+  Lisp_Object val, tail, elt;
+  Lisp_Object *realized;
+  struct font_info *fontp = NULL;
+  int n_realized = 0;
   int i;
-  
+
   (*check_window_system_func) ();
 
   fontset = check_fontset_name (name);
 
   if (NILP (frame))
     frame = selected_frame;
-  CHECK_LIVE_FRAME (frame, 1);
+  CHECK_LIVE_FRAME (frame);
   f = XFRAME (frame);
 
-  info = Fmake_vector (make_number (3), Qnil);
-
+  /* Recode realized fontsets whose base is FONTSET in the table
+     `realized'.  */
+  realized = (Lisp_Object *) alloca (sizeof (Lisp_Object)
+                                    * ASIZE (Vfontset_table));
   for (i = 0; i < ASIZE (Vfontset_table); i++)
     {
-      realized = FONTSET_FROM_ID (i);
-      if (!NILP (realized)
-         && EQ (FONTSET_FRAME (realized), frame)
-         && EQ (FONTSET_BASE (realized), fontset)
-         && INTEGERP (FONTSET_ASCII (realized)))
-       break;
+      elt = FONTSET_FROM_ID (i);
+      if (!NILP (elt)
+         && EQ (FONTSET_BASE (elt), fontset))
+       realized[n_realized++] = elt;
     }
 
-  if (NILP (realized))
-    return Qnil;
+  /* Accumulate information of the fontset in VAL.  The format is
+     (LAST FONT-INFO FONT-INFO ...), where FONT-INFO is (CHAR-OR-RANGE
+     FONT-SPEC).  See the comment for accumulate_font_info for the
+     detail.  */
+  val = Fcons (Fcons (Qascii, Fcons (FONTSET_ASCII (fontset), Qnil)), Qnil);
+  val = Fcons (val, val);
+  for (i = 128; i <= MAX_CHAR; )
+    {
+      Lisp_Object elt;
+      int from, to;
 
-  XVECTOR (info)->contents[0] = Qnil;
-  XVECTOR (info)->contents[1] = Qnil;
-  loaded = Qnil;
+      elt = char_table_ref_and_range (fontset, i, &from, &to);
+      if (! NILP (elt))
+       {
+         elt = Fcons (Fcons (make_number (from), make_number (to)),
+                      Fcons (elt, Qnil));
+         XSETCDR (XCAR (val), Fcons (elt, Qnil));
+         XSETCAR (val, XCDR (XCAR (val)));
+       }
+      i = to + 1;
+    }
 
-  val = Fcons (Fcons (CHARSET_SYMBOL (CHARSET_ASCII),
-                     Fcons (FONTSET_ASCII (fontset),
-                            Fcons (loaded, Qnil))),
-              Qnil);
-  for (i = MIN_CHARSET_OFFICIAL_DIMENSION1; i <= MAX_CHARSET; i++)
+  for (tail = FONTSET_CHARSET_ALIST (fontset);
+       CONSP (tail); tail = XCDR (tail))
     {
-      Lisp_Object elt;
-      elt = XCHAR_TABLE (fontset)->contents[i + 128];
+      elt = XCAR (tail);
+      elt = Fcons ((INTEGERP (XCAR (elt))
+                   ? CHARSET_NAME (CHARSET_FROM_ID (XCAR (elt)))
+                   : XCAR (elt)),
+                  Fcons (XCDR (elt), Qnil));
+      XSETCDR (XCAR (val), Fcons (elt, Qnil));
+      XSETCAR (val, XCDR (XCAR (val)));
+    }
+
+  val = XCDR (val);
 
-      if (VECTORP (elt))
+  /* If fonts are opened for FONT-SPEC, append the names of the fonts to
+     FONT-SPEC.  */
+  for (tail = val; CONSP (tail); tail = XCDR (tail))
+    {
+      elt = XCAR (tail);
+      for (i = 0; i < n_realized; i++)
        {
-         int face_id;
-         struct face *face;
+         Lisp_Object face_list, fontname;
 
-         if (INTEGERP (AREF (elt, 2))
-             && (face_id = XINT (AREF (elt, 2)),
-                 face = FACE_FROM_ID (f, face_id)))
+         for (face_list = FONTSET_FACE_ALIST (realized[i]);
+              CONSP (face_list); face_list = XCDR (face_list))
            {
-             struct font_info *fontp;
-             fontp = (*get_font_info_func) (f, face->font_info_id);
-             requested = build_string (fontp->name);
-             loaded = (fontp->full_name
-                       ? build_string (fontp->full_name)
-                       : Qnil);
+             int face_id = XINT (XCDR (XCAR (face_list)));
+             struct face *face = FACE_FROM_ID (f, face_id);
+
+             if (face->font && face->font_name)
+               {
+                 fontname = build_string (face->font_name);
+                 if (NILP (Fmember (fontname, XCDR (XCDR (elt)))))
+                   XSETCDR (XCDR (elt), Fcons (fontname, XCDR (XCDR (elt))));
+               }
            }
-         else
-           {
-             char *str;
-             int family_len = 0, registry_len = 0;
-
-             if (STRINGP (AREF (elt, 0)))
-               family_len = STRING_BYTES (XSTRING (AREF (elt, 0)));
-             if (STRINGP (AREF (elt, 1)))
-               registry_len = STRING_BYTES (XSTRING (AREF (elt, 1)));
-             str = (char *) alloca (1 + family_len + 3 + registry_len + 1);
-             str[0] = '-';
-             str[1] = 0;
-             if (family_len)
-               strcat (str, XSTRING (AREF (elt, 0))->data);
-             strcat (str, "-*-");
-             if (registry_len)
-               strcat (str, XSTRING (AREF (elt, 1))->data);
-             requested = build_string (str);
-             loaded = Qnil;
-           }
-         val = Fcons (Fcons (CHARSET_SYMBOL (i),
-                             Fcons (requested, Fcons (loaded, Qnil))),
-                      val);
        }
     }
-  XVECTOR (info)->contents[2] = val;
-  return info;
+
+  elt = XCDR (XCDR (XCAR (val)));
+  if (CONSP (elt))
+    fontp = (*query_font_func) (f, XSTRING (XCAR (elt))->data);
+  val = Fmake_vector (make_number (3), val);
+  AREF (val, 0) = fontp ? make_number (fontp->size) : make_number (0);
+  AREF (val, 1) = fontp ? make_number (fontp->height) : make_number (0);
+  return val;
 }
 
 DEFUN ("fontset-font", Ffontset_font, Sfontset_font, 2, 2, 0,
-  "Return a font name pattern for character CH in fontset NAME.\n\
-If NAME is t, find a font name pattern in the default fontset.")
-  (name, ch)
+       doc: /* Return a font name pattern for character CH in fontset NAME.
+If NAME is t, find a font name pattern in the default fontset.  */)
+     (name, ch)
      Lisp_Object name, ch;
 {
-  int c, id;
+  int c;
   Lisp_Object fontset, elt;
 
   fontset = check_fontset_name (name);
 
-  CHECK_NUMBER (ch, 1);
+  CHECK_CHARACTER (ch);
   c = XINT (ch);
-  if (!char_valid_p (c, 1))
-    invalid_character (c);
-
-  elt = FONTSET_REF (fontset, c);
-  if (CONSP (elt))
-    elt = XCDR (elt);
-
+  FONTSET_REF (fontset, c, elt);
   return elt;
 }
-  
 
 DEFUN ("fontset-list", Ffontset_list, Sfontset_list, 0, 0, 0,
-  "Return a list of all defined fontset names.")
-  ()
+       doc: /* Return a list of all defined fontset names.  */)
+     ()
 {
   Lisp_Object fontset, list;
   int i;
@@ -1261,101 +1248,97 @@ DEFUN ("fontset-list", Ffontset_list, Sfontset_list, 0, 0, 0,
          && BASE_FONTSET_P (fontset))
        list = Fcons (FONTSET_NAME (fontset), list);
     }
+
   return list;
 }
 
 void
 syms_of_fontset ()
 {
-  int i;
-
   if (!load_font_func)
     /* Window system initializer should have set proper functions.  */
     abort ();
 
   Qfontset = intern ("fontset");
   staticpro (&Qfontset);
-  Fput (Qfontset, Qchar_table_extra_slots, make_number (3));
+  Fput (Qfontset, Qchar_table_extra_slots, make_number (7));
 
   Vcached_fontset_data = Qnil;
   staticpro (&Vcached_fontset_data);
 
   Vfontset_table = Fmake_vector (make_number (32), Qnil);
   staticpro (&Vfontset_table);
-  next_fontset_id = 0;
 
   Vdefault_fontset = Fmake_char_table (Qfontset, Qnil);
   staticpro (&Vdefault_fontset);
-  FONTSET_ASCII (Vdefault_fontset)
-    = Fcons (make_number (0), Fcons (Qnil, build_string ("iso8859-1")));
+  FONTSET_ID (Vdefault_fontset) = make_number (0);
+  FONTSET_NAME (Vdefault_fontset)
+    = build_string ("-*-*-*-*-*-*-*-*-*-*-*-*-fontset-default");
+  {
+    Lisp_Object default_ascii_font;
+
+#if defined (macintosh)
+    default_ascii_font
+      = build_string ("-apple-monaco-medium-r-*--*-120-*-*-*-*-mac-roman");
+#elif defined (WINDOWSNT)
+    default_ascii_font
+      = build_string ("-*-courier new-normal-r-*-*-*-100-*-*-*-*-iso8859-1");
+#else
+    default_ascii_font
+      = build_string ("-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
+#endif
+    FONTSET_ASCII (Vdefault_fontset) = default_ascii_font;
+  }
+  AREF (Vfontset_table, 0) = Vdefault_fontset;
+  next_fontset_id = 1;
 
   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 corresponding encoding info.
+Each element looks like (REGEXP . CHARSET), where CHARSET is an
+Emacs charset symbol.  */);
   Vfont_encoding_alist = Qnil;
 
   DEFVAR_LISP ("use-default-ascent", &Vuse_default_ascent,
-     "Char table of characters whose 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.\n\
-\n\
-This affects how a composite character which contains\n\
-such a character is displayed on screen.");
+              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 ("ignore-relative-composition", &Vignore_relative_composition,
-     "Char table of characters which is not composed relatively.\n\
-If an entry for a character is non-nil, a composition sequence\n\
-which contains that character is displayed so that\n\
-the glyph of that character is put without considering\n\
-an ascent and descent value of a previous character.");
+              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,
-     "Alist of fontname vs list of the alternate fontnames.\n\
-When a specified font name is not found, the corresponding\n\
-alternate fontnames (if any) are tried instead.");
+              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,
-     "Alist of fontset names vs the aliases.");
-  Vfontset_alias_alist = Qnil;
-
-  DEFVAR_LISP ("highlight-wrong-size-font", &Vhighlight_wrong_size_font,
-     "*Non-nil means highlight characters shown in wrong size fonts somehow.\n\
-The way to highlight them depends on window system on which Emacs runs.\n\
-On X11, a rectangle is shown around each such character.");
-  Vhighlight_wrong_size_font = Qnil;
-
-  DEFVAR_LISP ("clip-large-size-font", &Vclip_large_size_font,
-     "*Non-nil means characters shown in overlarge fonts are clipped.\n\
-The height of clipping area is the same as that of an ASCII character.\n\
-The width of the area is the same as that of an ASCII character,\n\
-or twice as wide, depending on the character set's column-width.\n\
-\n\
-If the only font you have for a specific character set is too large,\n\
-and clipping these characters makes them hard to read,\n\
-you can set this variable to nil to display the characters without clipping.\n\
-The drawback is that you will get some garbage left on your screen.");
-  Vclip_large_size_font = Qt;
+              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,
-    "*Regexp matching font names that require vertical centering on display.\n\
-When a character is displayed with such fonts, the character is displayed\n\
-at the vertival center of lines.");
+              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);