(Qfont_spec, Qfont_entity, Qfont_object): Extern them.
[bpt/emacs.git] / src / fontset.c
index 045e632..48a32ea 100644 (file)
@@ -1,8 +1,8 @@
 /* Fontset handler.
 /* Fontset handler.
-   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
      Free Software Foundation, Inc.
    Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
      Free Software Foundation, Inc.
    Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-     2005, 2006, 2007
+     2005, 2006, 2007, 2008
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H14PRO021
    Copyright (C) 2003, 2006
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H14PRO021
    Copyright (C) 2003, 2006
@@ -57,9 +57,7 @@ Boston, MA 02110-1301, USA.  */
 #endif
 #include "termhooks.h"
 
 #endif
 #include "termhooks.h"
 
-#ifdef USE_FONT_BACKEND
 #include "font.h"
 #include "font.h"
-#endif /* USE_FONT_BACKEND */
 
 #undef xassert
 #ifdef FONTSET_DEBUG
 
 #undef xassert
 #ifdef FONTSET_DEBUG
@@ -96,14 +94,11 @@ EXFUN (Fclear_face_cache, 1);
    An element of a base fontset is a vector of FONT-DEFs which itself
    is a vector [ FONT-SPEC ENCODING REPERTORY ].
 
    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 ]
+   FONT-SPEC is a font-spec created by `font-spec' or
+       ( FAMILY . REGISTRY )
    or
        FONT-NAME
    or
        FONT-NAME
-   where FAMILY, WEIGHT, SLANT, SWIDTH, ADSTYLE, REGISTRY, and
-   FONT-NAME are strings.
-
-   Note: Currently WEIGHT through ADSTYLE are ignored.
+   where FAMILY, REGISTRY, and FONT-NAME are strings.
 
    ENCODING is a charset ID that can convert characters to glyph codes
    of the corresponding font.
 
    ENCODING is a charset ID that can convert characters to glyph codes
    of the corresponding font.
@@ -121,8 +116,8 @@ EXFUN (Fclear_face_cache, 1);
 
    An element of a realized fontset is nil or t, or has this form:
 
 
    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 ...].
+       [CHARSET-ORDERED-LIST-TICK PREFERRED-CHARSET-ID PREFERRED-FAMILY
+        RFONT-DEF0 RFONT-DEF1 ...].
 
    RFONT-DEFn (i.e. Realized FONT-DEF) has this form:
 
 
    RFONT-DEFn (i.e. Realized FONT-DEF) has this form:
 
@@ -219,6 +214,7 @@ static int next_fontset_id;
 static Lisp_Object Vdefault_fontset;
 
 Lisp_Object Vfont_encoding_alist;
 static Lisp_Object Vdefault_fontset;
 
 Lisp_Object Vfont_encoding_alist;
+Lisp_Object Vfont_encoding_charset_alist;
 Lisp_Object Vuse_default_ascent;
 Lisp_Object Vignore_relative_composition;
 Lisp_Object Valternate_fontname_alist;
 Lisp_Object Vuse_default_ascent;
 Lisp_Object Vignore_relative_composition;
 Lisp_Object Valternate_fontname_alist;
@@ -267,6 +263,7 @@ 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));
 /* Prototype declarations for static functions.  */
 static Lisp_Object fontset_add P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
                                    Lisp_Object));
+static void reorder_font_vector P_ ((Lisp_Object, int, 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 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));
@@ -306,6 +303,7 @@ fontset_id_valid_p (id)
 /* 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]
 /* 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_OBJLIST(fontset)       XCHAR_TABLE (fontset)->extras[4]
 #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]
 #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]
@@ -341,43 +339,6 @@ fontset_ref (fontset, c)
   return elt;
 }
 
   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.  */
 /* 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.  */
@@ -435,59 +396,97 @@ fontset_add (fontset, range, elt, add)
 }
 
 
 }
 
 
-/* Update FONTSET_ELEMENT which has this form:
-       [CHARSET-ORDERED-LIST-TICK PREFERRED-CHARSET-ID PREFERRED-RFONT-DEF
+/* Update FONT-GROUP which has this form:
+       [CHARSET-ORDERED-LIST-TICK PREFERRED-CHARSET-ID PREFERRED-FAMILY
         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
         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;
+reorder_font_vector (font_group, charset_id, family)
+     Lisp_Object font_group;
+     int charset_id;
+     Lisp_Object family;
 {
   Lisp_Object list, *new_vec;
 {
   Lisp_Object list, *new_vec;
-  Lisp_Object font_def;
   int size;
   int *charset_id_table;
   int i, idx;
   int size;
   int *charset_id_table;
   int i, idx;
+  Lisp_Object preferred_by_charset, preferred_by_family;
 
 
-  ASET (fontset_element, 0, make_number (charset_ordered_list_tick));
-  size = ASIZE (fontset_element) - 3;
-  if (size <= 1)
-    /* No need to reorder VEC.  */
-    return;
+  size = ASIZE (font_group) - 3;
+  /* Exclude the tailing nil elements from the reordering.  */
+  while (NILP (AREF (font_group, size - 1))) size--;
   charset_id_table = (int *) alloca (sizeof (int) * size);
   new_vec = (Lisp_Object *) alloca (sizeof (Lisp_Object) * size);
 
   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++)
+  /* At first, extract ENCODING (a chaset ID) from RFONT_DEF which
+     has this form:
+       [FACE-ID FONT-INDEX [ FONT-SPEC ENCODING REPERTORY ]]
+     In addtion, if RFONT_DEF is preferred by family or charset, store
+     it from the start of new_vec.  */
+  for (i = 0, idx = 0; i < size; i++)
     {
     {
-      font_def = AREF (fontset_element, i + 3);
-      if (VECTORP (AREF (font_def, 2))
-         && INTEGERP (AREF (AREF (font_def, 2), 1)))
-       charset_id_table[i] = XINT (AREF (AREF (font_def, 2), 1));
-      else
-       charset_id_table[i] = -1;
+      Lisp_Object rfont_def = AREF (font_group, i + 3);
+      Lisp_Object font_spec = AREF (AREF (rfont_def, 2), 0);
+      Lisp_Object this_family = AREF (font_spec, FONT_FAMILY_INDEX);
+      int id = XINT (AREF (AREF (rfont_def, 2), 1));
+      struct charset *charset = CHARSET_FROM_ID (id);
+
+      charset_id_table[i] = -1;
+      if (! NILP (this_family)
+         && (fast_string_match_ignore_case (family, SYMBOL_NAME (this_family))
+             >= 0))
+       {
+         if (idx > 0)
+           memmove (new_vec + 1, new_vec, sizeof (Lisp_Object) * idx);
+         new_vec[0] = rfont_def;
+         idx++;
+         ASET (font_group, i + 3, Qnil);
+       }
+      else if (id == charset_id)
+       {
+         new_vec[idx++] = rfont_def;
+         ASET (font_group, i + 3, Qnil);
+       }
+      else if (! charset->supplementary_p)
+       charset_id_table[i] = id;
     }
 
     }
 
-  /* 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))
+  if (idx == 0
+      && (XINT (AREF (font_group, 0)) == charset_ordered_list_tick))
+    /* No need of reordering.  */
+    return;
+
+  ASET (font_group, 0, make_number (charset_ordered_list_tick));
+  ASET (font_group, 1, make_number (charset_id));
+  ASET (font_group, 2, family);
+
+  /* Then, store the remaining RFONT-DEFs in NEW_VEC in the correct
+     order.  */
+  for (list = Vcharset_ordered_list; idx < size; list = XCDR (list))
     {
     {
+      int id = XINT (XCAR (list));
+      struct charset *charset = CHARSET_FROM_ID (id);
+
+      if (charset->supplementary_p)
+       break;
       for (i = 0; i < size; i++)
       for (i = 0; i < size; i++)
-       if (charset_id_table[i] == XINT (XCAR (list)))
-         new_vec[idx++] = AREF (fontset_element, i + 3);
+       if (charset_id_table[i] == XINT (XCAR (list))
+           && ! NILP (AREF (font_group, i + 3)))
+         {
+           new_vec[idx++] = AREF (font_group, i + 3);
+           ASET (font_group, i + 3, Qnil);
+         }
     }
   for (i = 0; i < size; i++)
     }
   for (i = 0; i < size; i++)
-    if (charset_id_table[i] < 0)
-      new_vec[idx++] = AREF (fontset_element, i + 3);
+    if (! NILP (AREF (font_group, i + 3)))
+      new_vec[idx++] = AREF (font_group, i + 3);
 
 
-  /* At last, update FONT-DEFs.  */
+  /* At last, update elements of FONT-GROUP.  */
   for (i = 0; i < size; i++)
   for (i = 0; i < size; i++)
-    ASET (fontset_element, i + 3, new_vec[i]);
+    ASET (font_group, i + 3, new_vec[i]);
 }
 
 
 }
 
 
@@ -498,6 +497,8 @@ reorder_font_vector (fontset_element)
    If REPERTORY is nil, generate a char-table representing the font
    repertory by looking into the font itself.  */
 
    If REPERTORY is nil, generate a char-table representing the font
    repertory by looking into the font itself.  */
 
+extern Lisp_Object QCname;
+
 static int
 load_font_get_repertory (f, face, font_def, fontset)
      FRAME_PTR f;
 static int
 load_font_get_repertory (f, face, font_def, fontset)
      FRAME_PTR f;
@@ -508,8 +509,14 @@ load_font_get_repertory (f, face, font_def, fontset)
   char *font_name;
   struct font_info *font_info;
   int charset;
   char *font_name;
   struct font_info *font_info;
   int charset;
+  Lisp_Object font_spec, name;
 
 
-  font_name = choose_face_font (f, face->lface, AREF (font_def, 0), NULL);
+  font_spec = AREF (font_def, 0);
+  name = Ffont_get (font_spec, QCname);
+  if (! NILP (name))
+    font_name = choose_face_font (f, face->lface, name, NULL);
+  else
+    font_name = choose_face_font (f, face->lface, font_spec, NULL);
   charset = XINT (AREF (font_def, 1));
   if (! (font_info = fs_load_font (f, font_name, charset)))
     return -1;
   charset = XINT (AREF (font_def, 1));
   if (! (font_info = fs_load_font (f, font_name, charset)))
     return -1;
@@ -535,12 +542,17 @@ static Lisp_Object fontset_find_font P_ ((Lisp_Object, int, struct face *,
                                          int, int));
 
 /* Return RFONT-DEF (vector) in the realized fontset FONTSET for the
                                          int, int));
 
 /* 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.
+   character C.  If no font is found, return Qnil if there's a
+   possibility that the default fontset or the fallback font groups
+   have a proper font, and return Qt if not.
+
+   If a font is found but is not yet opened, open it (if FACE is not
+   NULL) or return Qnil (if FACE is NULL).
+
    ID is a charset-id that must be preferred, or -1 meaning no
    preference.
    ID is a charset-id that must be preferred, or -1 meaning no
    preference.
-   If FALLBACK if nonzero, search only fallback fonts.  */
+
+   If FALLBACK is nonzero, search only fallback fonts.  */
 
 static Lisp_Object
 fontset_find_font (fontset, c, face, id, fallback)
 
 static Lisp_Object
 fontset_find_font (fontset, c, face, id, fallback)
@@ -559,21 +571,31 @@ fontset_find_font (fontset, c, face, id, fallback)
     vec = CHAR_TABLE_REF (fontset, c);
   else
     vec = FONTSET_FALLBACK (fontset);
     vec = CHAR_TABLE_REF (fontset, c);
   else
     vec = FONTSET_FALLBACK (fontset);
+
   if (NILP (vec))
     {
   if (NILP (vec))
     {
-      /* We have not yet decided a font for C.  */
       Lisp_Object range;
 
       Lisp_Object range;
 
+      /* We have not yet decided a font for C.  */
       if (! face)
        return Qnil;
       if (! fallback)
       if (! face)
        return Qnil;
       if (! fallback)
-       elt = FONTSET_REF_AND_RANGE (base_fontset, c, from, to);
+       {
+         elt = char_table_ref_and_range (base_fontset, c, &from, &to);
+         range = Fcons (make_number (from), make_number (to));
+       }
       else
       else
-       elt = FONTSET_FALLBACK (base_fontset);
-      range = Fcons (make_number (from), make_number (to));
+       {
+         elt = FONTSET_FALLBACK (base_fontset);
+       }
       if (NILP (elt))
        {
       if (NILP (elt))
        {
-         /* Qt means we have no font for characters of this range.  */
+         /* This fontset doesn't specify any font for C. */
+         vec = make_number (0);
+       }
+      else if (ASIZE (elt) == 1 && NILP (AREF (elt, 0)))
+       {
+         /* Explicitly specified no font.  */
          vec = Qt;
        }
       else
          vec = Qt;
        }
       else
@@ -581,92 +603,50 @@ fontset_find_font (fontset, c, face, id, 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-ELTn is [nil nil AREF (elt, n) nil].  */
          /* Build a vector [ -1 -1 nil NEW-ELT0 NEW-ELT1 NEW-ELT2 ... ],
             where the first -1 is to force reordering of NEW-ELTn,
             NEW-ELTn is [nil nil AREF (elt, n) nil].  */
-#ifdef USE_FONT_BACKEND
-         if (! fallback
-             && enable_font_backend
-             && EQ (base_fontset, Vdefault_fontset))
-           /* Extra one element is for an automatically added
-              font-def specifying only a script.  */
-           vec = Fmake_vector (make_number (ASIZE (elt) + 4), Qnil);
-         else
-#endif /* not USE_FONT_BACKEND */
-           vec = Fmake_vector (make_number (ASIZE (elt) + 3), Qnil);
+         int size = ASIZE (elt);
+         int j;
+
+         vec = Fmake_vector (make_number (size + 3), Qnil);
          ASET (vec, 0, make_number (-1));
          ASET (vec, 1, make_number (-1));
          ASET (vec, 0, make_number (-1));
          ASET (vec, 1, make_number (-1));
-         for (i = 0; i < ASIZE (elt); i++)
-           {
-             Lisp_Object tmp;
-
-             tmp = Fmake_vector (make_number (5), Qnil);
-             ASET (tmp, 2, AREF (elt, i));
-             ASET (vec, 3 + i, tmp);
-           }
-#ifdef USE_FONT_BACKEND
-         if (! fallback
-             && enable_font_backend
-             && EQ (base_fontset, Vdefault_fontset))
-           {
-             Lisp_Object script, font_spec;
-
-             script = CHAR_TABLE_REF (Vchar_script_table, c);
-             if (NILP (script))
-               script = intern ("latin");
-             font_spec = Ffont_spec (0, NULL);
-             ASET (font_spec, FONT_REGISTRY_INDEX, Qiso10646_1);
-             ASET (font_spec, FONT_EXTRA_INDEX,
-                   Fcons (Fcons (QCscript, script), Qnil));
-             font_def = Fmake_vector (make_number (3), Qnil);
-             ASET (font_def, 0, font_spec);
-             elt = Fmake_vector (make_number (5), Qnil);
-             ASET (elt, 2, font_def);
-             ASET (vec, 3 + i, elt);
-           }
-#endif /* USE_FONT_BACKEND */
-
-         /* Then store it in the fontset.  */
-         if (! fallback)
-           FONTSET_SET (fontset, range, vec);
-         else
-           FONTSET_FALLBACK (fontset) = vec;
-       }
-    }
-  if (EQ (vec, Qt))
-    return Qnil;
-
-  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;
+         for (i = j = 0; i < size; i++)
+           if (! NILP (AREF (elt, i)))
+             {
+               Lisp_Object tmp;
+               tmp = Fmake_vector (make_number (5), Qnil);
+               ASET (tmp, 2, AREF (elt, i));
+               ASET (vec, j + 3, tmp);
+               j++;
+             }
        }
        }
+      /* Then store it in the fontset.  */
+      if (! fallback)
+       FONTSET_SET (fontset, range, vec);
       else
       else
-       {
-         ASET (vec, 2, Qnil);
-         i = 3;
-       }
+       FONTSET_FALLBACK (fontset) = vec;
+
     }
     }
+  if (! VECTORP (vec))
+    return (EQ (vec, Qt) ? Qt : Qnil);
+
+  if (ASIZE (vec) > 4
+      && (XINT (AREF (vec, 0)) != charset_ordered_list_tick
+         || (id >= 0 && XINT (AREF (vec, 1)) != id)
+         || NILP (Fequal (AREF (vec, 2), face->lface[LFACE_FAMILY_INDEX]))))
+    /* We have just created VEC,
+       or the charset priorities were changed,
+       or the preferred charset was changed,
+       or the preferred family was changed.  */
+    reorder_font_vector (vec, id, face->lface[LFACE_FAMILY_INDEX]);
 
   /* Find the first available font in the vector of RFONT-DEF.  */
 
   /* Find the first available font in the vector of RFONT-DEF.  */
-  for (; i < ASIZE (vec); i++)
+  for (i = 3; i < ASIZE (vec); i++)
     {
       elt = AREF (vec, i);
       if (NILP (elt))
     {
       elt = AREF (vec, i);
       if (NILP (elt))
-       continue;
-      /* ELT == [ FACE-ID FONT-INDEX FONT-DEF OPENED-FONT-NAME ] */
+       /* This is the sign of not to try fallback fonts.  */
+       return Qt;
+      /* ELT == [ FACE-ID FONT-INDEX FONT-DEF ... ] */
       if (INTEGERP (AREF (elt, 1)) && XINT (AREF (elt, 1)) < 0)
        /* We couldn't open this font last time.  */
        continue;
       if (INTEGERP (AREF (elt, 1)) && XINT (AREF (elt, 1)) < 0)
        /* We couldn't open this font last time.  */
        continue;
@@ -681,58 +661,52 @@ fontset_find_font (fontset, c, face, id, fallback)
 #ifdef USE_FONT_BACKEND
       if (enable_font_backend)
        {
 #ifdef USE_FONT_BACKEND
       if (enable_font_backend)
        {
-         /* ELT == [ FACE-ID FONT-INDEX FONT-DEF FONT-ENTITY FONT-OBJECT ] */
+         /* ELT == [ FACE-ID FONT-INDEX FONT-DEF FONT-ENTITY ]
+            where FONT-ENTITY turns to a font-object once opened.  */
          Lisp_Object font_entity = AREF (elt, 3);
          Lisp_Object font_entity = AREF (elt, 3);
-         Lisp_Object font_object = AREF (elt, 4);
-         Lisp_Object font_spec = AREF (font_def, 0);
-         int has_char;
+         int has_char = 0;
 
          if (NILP (font_entity))
            {
 
          if (NILP (font_entity))
            {
-             if (! FONT_SPEC_P (font_spec))
-               {
-                 /* FONT_SPEC is FONT-NAME or (FAMILY . REGISTRY).  */
-                 font_spec = Ffont_spec (0, NULL);
-                 if (STRINGP (AREF (font_def, 0)))
-                   font_merge_old_spec (AREF (font_def, 0), Qnil, Qnil,
-                                        font_spec);
-                 else
-                   {
-                     Lisp_Object family = AREF (AREF (font_def, 0), 0);
-                     Lisp_Object registry = AREF (AREF (font_def, 0), 5);;
-
-                     font_merge_old_spec (Qnil, family, registry, font_spec);
-                   }
-                 ASET (font_def, 0, font_spec);
-               }
-             font_entity = font_find_for_lface (f, face->lface, font_spec);
-             ASET (elt, 3, font_entity);
+             font_entity = font_find_for_lface (f, face->lface,
+                                                AREF (font_def, 0), -1);
              if (NILP (font_entity))
                {
                  ASET (elt, 1, make_number (-1));
                  continue;
                }
              if (NILP (font_entity))
                {
                  ASET (elt, 1, make_number (-1));
                  continue;
                }
-             font_object = Qnil;
+             ASET (elt, 3, font_entity);
+           }
+         else if (FONT_ENTITY_P (font_entity))
+           {
+             if (FONT_ENTITY_NOT_LOADABLE (font_entity))
+               continue;
            }
          has_char = font_has_char (f, font_entity, c);
            }
          has_char = font_has_char (f, font_entity, c);
-         if (has_char == 0)
+         if (! has_char)
            continue;
            continue;
-         if (NILP (font_object))
+         if (! FONT_OBJECT_P (font_entity))
            {
            {
-             font_object = font_open_for_lface (f, font_entity,
-                                                face->lface, font_spec);
-             ASET (elt, 4, font_object);
+             Lisp_Object font_object
+               = font_open_for_lface (f, font_entity, face->lface, Qnil);
+
              if (NILP (font_object))
                {
              if (NILP (font_object))
                {
-                 ASET (elt, 1, make_number (-1));
+                 FONT_ENTITY_SET_NOT_LOADABLE (font_entity);
                  continue;
                }
                  continue;
                }
+             FONTSET_OBJLIST (fontset)
+               = Fcons (font_object, FONTSET_OBJLIST (fontset));
+             ASET (elt, 3, font_object);
+             if (has_char < 0)
+               {
+                 has_char = font_has_char (f, font_object, c);
+                 if (! has_char)
+                   continue;
+               }
            }
            }
+         /* Decide to use this font.  */
          ASET (elt, 1, make_number (0));
          ASET (elt, 1, make_number (0));
-         ASET (elt, 4, font_object);
-         if (has_char < 0
-             && font_encode_char (font_object, c) == FONT_INVALID_CODE)
-           continue;
        }
       else
 #endif /* USE_FONT_BACKEND */
        }
       else
 #endif /* USE_FONT_BACKEND */
@@ -796,10 +770,9 @@ fontset_find_font (fontset, c, face, id, fallback)
          font_info = (*get_font_info_func) (f, font_idx);
          ASET (elt, 3, build_string (font_info->full_name));
        }
          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;
     }
       return elt;
     }
+
   return Qnil;
 }
 
   return Qnil;
 }
 
@@ -816,8 +789,10 @@ fontset_font (fontset, c, face, id)
 
   /* Try a font-group for C. */
   rfont_def = fontset_find_font (fontset, c, face, id, 0);
 
   /* Try a font-group for C. */
   rfont_def = fontset_find_font (fontset, c, face, id, 0);
-  if (! NILP (rfont_def))
+  if (VECTORP (rfont_def))
     return rfont_def;
     return rfont_def;
+  if (EQ (rfont_def, Qt))
+    return Qnil;
   base_fontset = FONTSET_BASE (fontset);
   /* Try a font-group for C of the default fontset. */
   if (! EQ (base_fontset, Vdefault_fontset))
   base_fontset = FONTSET_BASE (fontset);
   /* Try a font-group for C of the default fontset. */
   if (! EQ (base_fontset, Vdefault_fontset))
@@ -826,16 +801,24 @@ fontset_font (fontset, c, face, id)
        FONTSET_DEFAULT (fontset)
          = make_fontset (FONTSET_FRAME (fontset), Qnil, Vdefault_fontset);
       rfont_def = fontset_find_font (FONTSET_DEFAULT (fontset), c, face, id, 0);
        FONTSET_DEFAULT (fontset)
          = make_fontset (FONTSET_FRAME (fontset), Qnil, Vdefault_fontset);
       rfont_def = fontset_find_font (FONTSET_DEFAULT (fontset), c, face, id, 0);
+      if (VECTORP (rfont_def))
+       return (rfont_def);
+      if (! NILP (rfont_def))
+       /* Remeber that we have no font for C.  */
+       FONTSET_SET (fontset, make_number (c), Qt);
     }
     }
-  if (! NILP (rfont_def))
-    return rfont_def;
+
   /* Try a fallback font-group. */
   rfont_def = fontset_find_font (fontset, c, face, id, 1);
   /* Try a fallback font-group. */
   rfont_def = fontset_find_font (fontset, c, face, id, 1);
-  if (! NILP (rfont_def))
-    return rfont_def;
-  /* Try a fallback font-group of the default fontset . */
-  if (! EQ (base_fontset, Vdefault_fontset))
+  if (! VECTORP (rfont_def)
+      && ! EQ (base_fontset, Vdefault_fontset))
+    /* Try a fallback font-group of the default fontset . */
     rfont_def = fontset_find_font (FONTSET_DEFAULT (fontset), c, face, id, 1);
     rfont_def = fontset_find_font (FONTSET_DEFAULT (fontset), c, face, id, 1);
+
+  if (! VECTORP (rfont_def))
+    /* Remeber that we have no font for C.  */
+    FONTSET_SET (fontset, make_number (c), Qt);
+
   return rfont_def;
 }
 
   return rfont_def;
 }
 
@@ -932,6 +915,21 @@ fontset_ascii (id)
   return elt;
 }
 
   return elt;
 }
 
+void
+free_realized_fontset (f, fontset)
+     FRAME_PTR f;
+     Lisp_Object fontset;
+{
+  int i;
+  Lisp_Object tail;
+
+  return;
+  for (tail = FONTSET_OBJLIST (fontset); CONSP (tail); tail = XCDR (tail))
+    {
+      xassert (FONT_OBJECT_P (XCAR (tail)));
+      font_close_object (f, XCAR (tail));
+    }
+}
 
 /* Free fontset of FACE defined on frame F.  Called from
    free_realized_face.  */
 
 /* Free fontset of FACE defined on frame F.  Called from
    free_realized_face.  */
@@ -943,9 +941,10 @@ free_face_fontset (f, face)
 {
   Lisp_Object fontset;
 
 {
   Lisp_Object fontset;
 
-  fontset = AREF (Vfontset_table, face->fontset);
+  fontset = FONTSET_FROM_ID (face->fontset);
   xassert (!NILP (fontset) && ! BASE_FONTSET_P (fontset));
   xassert (f == XFRAME (FONTSET_FRAME (fontset)));
   xassert (!NILP (fontset) && ! BASE_FONTSET_P (fontset));
   xassert (f == XFRAME (FONTSET_FRAME (fontset)));
+  free_realized_fontset (f, fontset);
   ASET (Vfontset_table, face->fontset, Qnil);
   if (face->fontset < next_fontset_id)
     next_fontset_id = face->fontset;
   ASET (Vfontset_table, face->fontset, Qnil);
   if (face->fontset < next_fontset_id)
     next_fontset_id = face->fontset;
@@ -956,6 +955,7 @@ free_face_fontset (f, face)
       fontset = AREF (Vfontset_table, id);
       xassert (!NILP (fontset) && ! BASE_FONTSET_P (fontset));
       xassert (f == XFRAME (FONTSET_FRAME (fontset)));
       fontset = AREF (Vfontset_table, id);
       xassert (!NILP (fontset) && ! BASE_FONTSET_P (fontset));
       xassert (f == XFRAME (FONTSET_FRAME (fontset)));
+      free_realized_fontset (f, fontset);
       ASET (Vfontset_table, id, Qnil);
       if (id < next_fontset_id)
        next_fontset_id = face->fontset;
       ASET (Vfontset_table, id, Qnil);
       if (id < next_fontset_id)
        next_fontset_id = face->fontset;
@@ -1011,7 +1011,14 @@ face_for_char (f, face, c, pos, object)
       if (NILP (charset))
        id = -1;
       else if (CHARSETP (charset))
       if (NILP (charset))
        id = -1;
       else if (CHARSETP (charset))
-       id = XINT (CHARSET_SYMBOL_ID (charset));
+       {
+         Lisp_Object val;
+
+         val = assoc_no_quit (charset, Vfont_encoding_charset_alist);
+         if (CONSP (val) && CHARSETP (XCDR (val)))
+           charset = XCDR (val);
+         id = XINT (CHARSET_SYMBOL_ID (charset));
+       }
     }
   rfont_def = fontset_font (fontset, c, face, id);
   if (VECTORP (rfont_def))
     }
   rfont_def = fontset_font (fontset, c, face, id);
   if (VECTORP (rfont_def))
@@ -1020,7 +1027,7 @@ face_for_char (f, face, c, pos, object)
       if (enable_font_backend
          && NILP (AREF (rfont_def, 0)))
        {
       if (enable_font_backend
          && NILP (AREF (rfont_def, 0)))
        {
-         struct font *font = XSAVE_VALUE (AREF (rfont_def, 4))->pointer;
+         struct font *font = XSAVE_VALUE (AREF (rfont_def, 3))->pointer;
 
          face_id = face_for_font (f, font, face);
          ASET (rfont_def, 0, make_number (face_id));
 
          face_id = face_for_font (f, font, face);
          ASET (rfont_def, 0, make_number (face_id));
@@ -1066,7 +1073,6 @@ make_fontset_for_ascii_face (f, base_fontset_id, face)
       base_fontset = FONTSET_FROM_ID (base_fontset_id);
       if (!BASE_FONTSET_P (base_fontset))
        base_fontset = FONTSET_BASE (base_fontset);
       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 ();
     }
       if (! BASE_FONTSET_P (base_fontset))
        abort ();
     }
@@ -1074,41 +1080,6 @@ make_fontset_for_ascii_face (f, base_fontset_id, face)
     base_fontset = Vdefault_fontset;
 
   fontset = make_fontset (frame, Qnil, base_fontset);
     base_fontset = Vdefault_fontset;
 
   fontset = make_fontset (frame, Qnil, base_fontset);
-  {
-    Lisp_Object elt, rfont_def, val;
-
-    elt = FONTSET_REF (base_fontset, 0);
-    xassert (VECTORP (elt) && ASIZE (elt) > 0);
-#ifdef USE_FONT_BACKEND
-    rfont_def = Fmake_vector (make_number (5), Qnil);
-    if (enable_font_backend && face->font_info)
-      {
-       struct font *font = (struct font *) face->font_info;
-
-       ASET (rfont_def, 3, font->entity);
-       ASET (rfont_def, 4, font_find_object (font));
-      }
-    else
-#endif  /* USE_FONT_BACKEND */
-    {
-      rfont_def = Fmake_vector (make_number (4), Qnil);
-      ASET (rfont_def, 3, build_string (face->font_name));
-    }
-    ASET (rfont_def, 1, make_number (face->font_info_id));
-    ASET (rfont_def, 2, AREF (elt, 0));
-    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);
-
-    val = Fcons (Qlatin, Qnil);
-    map_char_table (accumulate_script_ranges, Qnil, Vchar_script_table, val);
-    for (val = XCDR (val); CONSP (val); val = XCDR (val))
-      char_table_set_range (fontset, XINT (XCAR (XCAR (val))),
-                           XINT (XCDR (XCAR (val))), elt);
-    FONTSET_FALLBACK (fontset) = elt;
-  }
   return XINT (FONTSET_ID (fontset));
 }
 
   return XINT (FONTSET_ID (fontset));
 }
 
@@ -1482,24 +1453,26 @@ accumulate_script_ranges (arg, range, val)
 
 
 /* Return an ASCII font name generated from fontset name NAME and
 
 
 /* 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].  */
+   font-spec ASCII_SPEC.  NAME is a string conforming to XLFD.  */
 
 static INLINE Lisp_Object
 generate_ascii_font_name (name, ascii_spec)
      Lisp_Object name, ascii_spec;
 {
 
 static INLINE Lisp_Object
 generate_ascii_font_name (name, ascii_spec)
      Lisp_Object name, ascii_spec;
 {
+  Lisp_Object font_spec = Ffont_spec (0, NULL);
   Lisp_Object vec;
   int i;
   Lisp_Object vec;
   int i;
+  char xlfd[256];
 
 
-  vec = split_font_name_into_vector (name);
-  for (i = FONT_SPEC_FAMILY_INDEX; i <= FONT_SPEC_ADSTYLE_INDEX; i++)
+  if (font_parse_xlfd (SDATA (name), font_spec) < 0)
+    error ("Not an XLFD font name: %s", SDATA (name));
+  for (i = FONT_FOUNDRY_INDEX; i <= FONT_WIDTH_INDEX; i++)
     if (! NILP (AREF (ascii_spec, 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);
+      ASET (font_spec, i, AREF (ascii_spec, i));
+  i = font_unparse_xlfd (font_spec, 0, xlfd, 256);
+  if (i < 0)
+    error ("Not an XLFD font name: %s", SDATA (name));
+  return make_unibyte_string (xlfd, i);
 }
 
 /* Variables referred in set_fontset_font.  They are set before
 }
 
 /* Variables referred in set_fontset_font.  They are set before
@@ -1544,6 +1517,7 @@ set_fontset_font (fontset, range)
   FONTSET_ADD (fontset, range, font_def_arg, add_arg);
 }
 
   FONTSET_ADD (fontset, range, font_def_arg, add_arg);
 }
 
+extern Lisp_Object QCfamily, QCregistry;
 
 DEFUN ("set-fontset-font", Fset_fontset_font, Sset_fontset_font, 3, 5, 0,
        doc: /*
 
 DEFUN ("set-fontset-font", Fset_fontset_font, Sset_fontset_font, 3, 5, 0,
        doc: /*
@@ -1567,6 +1541,7 @@ FONT-SPEC may one of these:
    REGISTRY is a font registry name.  FAMILY may contains foundry
    name, and REGISTRY may contains encoding name.
  * A font name string.
    REGISTRY is a font registry name.  FAMILY may contains foundry
    name, and REGISTRY may contains encoding name.
  * A font name string.
+ * nil, which explicitly specifies that there's no font for TARGET.
 
 Optional 4th argument FRAME, if non-nil, is a frame.  This argument is
 kept for backward compatibility and has no meaning.
 
 Optional 4th argument FRAME, if non-nil, is a frame.  This argument is
 kept for backward compatibility and has no meaning.
@@ -1593,77 +1568,75 @@ appended.  By default, FONT-SPEC overrides the previous settings.  */)
 
   if (VECTORP (font_spec))
     {
 
   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);
+      if (! FONT_SPEC_P (font_spec))
+       Fsignal (Qfont, list2 (build_string ("invalid font-spec"), font_spec));
     }
   else if (CONSP (font_spec))
     {
     }
   else if (CONSP (font_spec))
     {
+      Lisp_Object args[4];
+      int i= 0;
+
       family = XCAR (font_spec);
       registry = XCDR (font_spec);
 
       if (! NILP (family))
        {
          CHECK_STRING (family);
       family = XCAR (font_spec);
       registry = XCDR (font_spec);
 
       if (! NILP (family))
        {
          CHECK_STRING (family);
-         family = Fdowncase (family);
+         args[i++] = QCfamily;
+         args[i++] = family;
        }
       CHECK_STRING (registry);
        }
       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);
+      args[i++] = QCregistry;
+      args[i++] = registry;
+      font_spec = Ffont_spec (i, args);
     }
     }
-  else
+  else if (STRINGP (font_spec))
     {
     {
-      CHECK_STRING (font_spec);
-      font_spec = Fdowncase (font_spec);
-    }
-
-  if (STRINGP (font_spec))
-    encoding = find_font_encoding (font_spec);
-  else
-    encoding = find_font_encoding (concat2 (family, registry));
-  if (NILP (encoding))
-    encoding = Qascii;
+      Lisp_Object args[2];
 
 
-  if (SYMBOLP (encoding))
-    {
-      CHECK_CHARSET (encoding);
-      encoding = repertory = CHARSET_SYMBOL_ID (encoding);
+      args[0] = QCname;
+      args[1] = font_spec;
+      font_spec = Ffont_spec (2, args);
     }
     }
-  else
+  else if (! NILP (font_spec))
+    wrong_type_argument (intern ("font-spec"), font_spec);
+
+  if (! NILP (font_spec))
     {
     {
-      repertory = XCDR (encoding);
-      encoding = XCAR (encoding);
-      CHECK_CHARSET (encoding);
-      encoding = CHARSET_SYMBOL_ID (encoding);
-      if (! NILP (repertory) && SYMBOLP (repertory))
+      family = AREF (font_spec, FONT_FAMILY_INDEX);
+      if (! NILP (family) && SYMBOLP (family))
+       family = SYMBOL_NAME (family);
+      registry = AREF (font_spec, FONT_REGISTRY_INDEX);
+      if (! NILP (registry) && SYMBOLP (registry))
+       registry = SYMBOL_NAME (registry);
+
+      encoding = find_font_encoding (concat2 (family, registry));
+      if (NILP (encoding))
+       encoding = Qascii;
+
+      if (SYMBOLP (encoding))
+       {
+         CHECK_CHARSET (encoding);
+         encoding = repertory = CHARSET_SYMBOL_ID (encoding);
+       }
+      else
        {
        {
-         CHECK_CHARSET (repertory);
-         repertory = CHARSET_SYMBOL_ID (repertory);
+         repertory = XCDR (encoding);
+         encoding = XCAR (encoding);
+         CHECK_CHARSET (encoding);
+         encoding = CHARSET_SYMBOL_ID (encoding);
+         if (! NILP (repertory) && SYMBOLP (repertory))
+           {
+             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);
     }
     }
-  font_def = Fmake_vector (make_number (3), font_spec);
-  ASET (font_def, 1, encoding);
-  ASET (font_def, 2, repertory);
+  else
+    font_def = Qnil;
 
   if (CHARACTERP (target))
     range_list = Fcons (Fcons (target, target), Qnil);
 
   if (CHARACTERP (target))
     range_list = Fcons (Fcons (target, target), Qnil);
@@ -1690,7 +1663,7 @@ appended.  By default, FONT-SPEC overrides the previous settings.  */)
          map_char_table (accumulate_script_ranges, Qnil, Vchar_script_table,
                          val);
          range_list = XCDR (val);
          map_char_table (accumulate_script_ranges, Qnil, Vchar_script_table,
                          val);
          range_list = XCDR (val);
-         if (EQ (target, Qlatin))
+         if (EQ (target, Qlatin) && NILP (FONTSET_ASCII (fontset)))
            {
              if (VECTORP (font_spec))
                val = generate_ascii_font_name (FONTSET_NAME (fontset),
            {
              if (VECTORP (font_spec))
                val = generate_ascii_font_name (FONTSET_NAME (fontset),
@@ -1702,7 +1675,7 @@ appended.  By default, FONT-SPEC overrides the previous settings.  */)
        }
       if (CHARSETP (target))
        {
        }
       if (CHARSETP (target))
        {
-         if (EQ (target, Qascii))
+         if (EQ (target, Qascii) && NILP (FONTSET_ASCII (fontset)))
            {
              if (VECTORP (font_spec))
                font_spec = generate_ascii_font_name (FONTSET_NAME (fontset),
            {
              if (VECTORP (font_spec))
                font_spec = generate_ascii_font_name (FONTSET_NAME (fontset),
@@ -1900,6 +1873,8 @@ new_fontset_from_font (font_object)
   font_spec = Fcons (SYMBOL_NAME (AREF (font_spec, FONT_FAMILY_INDEX)),
                     SYMBOL_NAME (AREF (font_spec, FONT_REGISTRY_INDEX)));
   Fset_fontset_font (name, Qlatin, font_spec, Qnil, Qnil);
   font_spec = Fcons (SYMBOL_NAME (AREF (font_spec, FONT_FAMILY_INDEX)),
                     SYMBOL_NAME (AREF (font_spec, FONT_REGISTRY_INDEX)));
   Fset_fontset_font (name, Qlatin, font_spec, Qnil, Qnil);
+  XSETCDR (font_spec, build_string ("iso10646-1"));
+  Fset_fontset_font (name, Qlatin, font_spec, Qnil, Qappend);
   Fset_fontset_font (name, Qnil, font_spec, Qnil, Qnil);
   return XINT (FONTSET_ID (fontset));
 }
   Fset_fontset_font (name, Qnil, font_spec, Qnil, Qnil);
   return XINT (FONTSET_ID (fontset));
 }
@@ -2011,7 +1986,7 @@ If the named font is not yet loaded, return nil.  */)
   XVECTOR (info)->contents[6] = make_number (fontp->default_ascent);
 
 #ifdef USE_FONT_BACKEND
   XVECTOR (info)->contents[6] = make_number (fontp->default_ascent);
 
 #ifdef USE_FONT_BACKEND
-  if (! NILP (font_object))
+  if (enable_font_backend && ! NILP (font_object))
     font_close_object (f, font_object);
 #endif /* USE_FONT_BACKEND */
   return info;
     font_close_object (f, font_object);
 #endif /* USE_FONT_BACKEND */
   return info;
@@ -2050,7 +2025,7 @@ DEFUN ("internal-char-font", Finternal_char_font, Sinternal_char_font, 1, 2, 0,
      (position, ch)
      Lisp_Object position, ch;
 {
      (position, ch)
      Lisp_Object position, ch;
 {
-  int pos, pos_byte, dummy;
+  EMACS_INT pos, pos_byte, dummy;
   int face_id;
   int c;
   struct frame *f;
   int face_id;
   int c;
   struct frame *f;
@@ -2104,16 +2079,19 @@ DEFUN ("internal-char-font", Finternal_char_font, Sinternal_char_font, 1, 2, 0,
 #ifdef USE_FONT_BACKEND
   if (enable_font_backend)
     {
 #ifdef USE_FONT_BACKEND
   if (enable_font_backend)
     {
-      if (VECTORP (rfont_def) && ! NILP (AREF (rfont_def, 4)))
+      if (VECTORP (rfont_def) && ! NILP (AREF (rfont_def, 3)))
        {
        {
-         Lisp_Object font_object = AREF (rfont_def, 4);
+         Lisp_Object font_object = AREF (rfont_def, 3);
          struct font *font = XSAVE_VALUE (font_object)->pointer;
          unsigned code = font->driver->encode_char (font, c);
          Lisp_Object fontname = font_get_name (font_object);
          struct font *font = XSAVE_VALUE (font_object)->pointer;
          unsigned code = font->driver->encode_char (font, c);
          Lisp_Object fontname = font_get_name (font_object);
+         /* Assignment to EMACS_INT stops GCC whining about limited range
+            of data type.  */
+         EMACS_INT cod = code;
 
          if (code == FONT_INVALID_CODE)
 
          if (code == FONT_INVALID_CODE)
-           return Fcons (fontname, Qnil);
-         if (code <= MOST_POSITIVE_FIXNUM)
+           return Qnil;
+         if (cod <= MOST_POSITIVE_FIXNUM)
            return Fcons (fontname, make_number (code));
          return Fcons (fontname, Fcons (make_number (code >> 16),
                                         make_number (code & 0xFFFF)));
            return Fcons (fontname, make_number (code));
          return Fcons (fontname, Fcons (make_number (code >> 16),
                                         make_number (code & 0xFFFF)));
@@ -2233,7 +2211,12 @@ fontset.  The format is the same as abobe.  */)
 
              /* At first, set ALIST to ((FONT-SPEC) ...).  */
              for (alist = Qnil, i = 0; i < ASIZE (val); i++)
 
              /* 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);
+               {
+                 if (NILP (AREF (val, i)))
+                   alist = Fcons (Qnil, alist);
+                 else
+                   alist = Fcons (Fcons (AREF (AREF (val, i), 0), Qnil), alist);
+               }
              alist = Fnreverse (alist);
 
              /* Then store opend font names to cdr of each elements.  */
              alist = Fnreverse (alist);
 
              /* Then store opend font names to cdr of each elements.  */
@@ -2245,29 +2228,63 @@ fontset.  The format is the same as abobe.  */)
                    val = FONTSET_FALLBACK (realized[k][i]);
                  if (! VECTORP (val))
                    continue;
                    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)))
+#ifdef USE_FONT_BACKEND
+                 /* VAL: [int int ?
+                          [FACE-ID FONT-INDEX FONT-DEF FONT-ENTITY/OBJECT]
+                          ...]  */
+                 if (enable_font_backend)
+                   for (j = 3; j < ASIZE (val); j++)
                      {
                      {
-                       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));
+                       elt = AREF (val, j);
+                       if (INTEGERP (AREF (elt, 1))
+                           && XINT (AREF (elt, 1)) >= 0)
+                         {
+                           Lisp_Object font_object = AREF (elt, 3);
+
+                           if (FONT_OBJECT_P (font_object))
+                             {
+                               struct font *font
+                                 = XSAVE_VALUE (font_object)->pointer;
+                               char *name = font->font.full_name;
+                               int len = strlen (name);
+                               Lisp_Object slot;
+
+                               slot = Fassq (AREF (AREF (elt, 2), 0), alist);
+                               nconc2 (slot,
+                                       Fcons (make_unibyte_string (name, len),
+                                              Qnil));
+                             }
+                         }
                      }
                      }
+                 else
+#endif  /* not USE_FONT_BACKEND */
+                   {
+                     /* 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));
+                         }
+                   }
                }
                }
-             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)
 
              /* Store ALIST in TBL for characters C..TO.  */
              if (c <= MAX_5_BYTE_CHAR)
@@ -2438,7 +2455,7 @@ syms_of_fontset ()
   FONTSET_ID (Vdefault_fontset) = make_number (0);
   FONTSET_NAME (Vdefault_fontset)
     = build_string ("-*-*-*-*-*-*-*-*-*-*-*-*-fontset-default");
   FONTSET_ID (Vdefault_fontset) = make_number (0);
   FONTSET_NAME (Vdefault_fontset)
     = build_string ("-*-*-*-*-*-*-*-*-*-*-*-*-fontset-default");
-  AREF (Vfontset_table, 0) = Vdefault_fontset;
+  ASET (Vfontset_table, 0, Vdefault_fontset);
   next_fontset_id = 1;
 
   auto_fontset_alist = Qnil;
   next_fontset_id = 1;
 
   auto_fontset_alist = Qnil;
@@ -2451,6 +2468,9 @@ 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.
 
 where ENCODING is a charset or a char-table,
 and REPERTORY is a charset, a char-table, or nil.
 
+If ENCDING and REPERTORY are the same, the element can have the form
+\(REGEXP . ENCODING).
+
 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
 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
@@ -2463,6 +2483,17 @@ 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;
 
 gets the repertory information by an opened font and ENCODING.  */);
   Vfont_encoding_alist = Qnil;
 
+  DEFVAR_LISP ("font-encoding-charset-alist", &Vfont_encoding_charset_alist,
+              doc: /*
+Alist of charsets vs the charsets to determine the preferred font encoding.
+Each element looks like (CHARSET . ENCDOING-CHARSET),
+where ENCODING-CHARSET is a charset registered in the variable
+`font-encoding-alist' as ENCODING.
+
+When a text has a property `charset' and the value is CHARSET, a font
+whose encoding corresponds to ENCODING-CHARSET is preferred.  */);
+  Vfont_encoding_charset_alist = Qnil;
+
   DEFVAR_LISP ("use-default-ascent", &Vuse_default_ascent,
               doc: /*
 Char table of characters whose ascent values should be ignored.
   DEFVAR_LISP ("use-default-ascent", &Vuse_default_ascent,
               doc: /*
 Char table of characters whose ascent values should be ignored.