Merge from emacs--devo--0
[bpt/emacs.git] / src / fontset.c
index c92e05c..47a682c 100644 (file)
@@ -13,7 +13,7 @@ This file is part of GNU Emacs.
 
 GNU Emacs is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -465,7 +465,8 @@ reorder_font_vector (fontset_element)
   for (i = 0; i < size; i++)
     {
       font_def = AREF (fontset_element, i + 3);
-      if (! NILP (AREF (font_def, 2)))
+      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;
@@ -529,94 +530,108 @@ load_font_get_repertory (f, face, font_def, fontset)
   return font_info->font_idx;
 }
 
+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
    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.  */
+   If no proper font is found for C, return Qnil.
+   ID is a charset-id that must be preferred, or -1 meaning no
+   preference.
+   If FALLBACK if nonzero, search only fallback fonts.  */
 
 static Lisp_Object
-fontset_font (fontset, c, face, id)
+fontset_find_font (fontset, c, face, id, fallback)
      Lisp_Object fontset;
      int c;
      struct face *face;
-     int id;
+     int id, fallback;
 {
-  Lisp_Object base_fontset, elt, vec;
+  Lisp_Object base_fontset, elt, vec, font_def;
   int i, from, to;
   int font_idx;
   FRAME_PTR f = XFRAME (FONTSET_FRAME (fontset));
 
   base_fontset = FONTSET_BASE (fontset);
-  vec = CHAR_TABLE_REF (fontset, c);
-  if (EQ (vec, Qt))
-    goto try_fallback;
-
+  if (! fallback)
+    vec = CHAR_TABLE_REF (fontset, c);
+  else
+    vec = FONTSET_FALLBACK (fontset);
   if (NILP (vec))
     {
-      /* We have not yet decided a face for C.  */
+      /* We have not yet decided a font for C.  */
       Lisp_Object range;
 
       if (! face)
        return Qnil;
-      elt = FONTSET_REF_AND_RANGE (base_fontset, c, from, to);
+      if (! fallback)
+       elt = FONTSET_REF_AND_RANGE (base_fontset, c, from, to);
+      else
+       elt = FONTSET_FALLBACK (base_fontset);
       range = Fcons (make_number (from), make_number (to));
       if (NILP (elt))
        {
-         /* Record that we have no font for characters of this
-            range.  */
+         /* Qt means we have no font for characters of this range.  */
          vec = Qt;
-         FONTSET_SET (fontset, range, vec);
-         goto try_fallback;
        }
-      /* Build a vector [ -1 -1 nil NEW-ELT0 NEW-ELT1 NEW-ELT2 ... ],
-        where the first -1 is to force reordering of NEW-ELTn,
-        NEW-ETLn is [nil nil AREF (elt, n) nil].  */
-#ifdef USE_FONT_BACKEND
-      if (enable_font_backend
-         && EQ (base_fontset, Vdefault_fontset))
-       vec = Fmake_vector (make_number (ASIZE (elt) + 4), make_number (-1));
       else
-#endif /* not USE_FONT_BACKEND */
-      vec = Fmake_vector (make_number (ASIZE (elt) + 3), make_number (-1));
-      ASET (vec, 2, Qnil);
-      for (i = 0; i < ASIZE (elt); i++)
        {
-         Lisp_Object tmp;
-
+         /* 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 (enable_font_backend)
-           tmp = Fmake_vector (make_number (5), Qnil);
+         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 /* USE_FONT_BACKEND */
-         tmp = Fmake_vector (make_number (4), Qnil);
-         ASET (tmp, 2, AREF (elt, i));
-         ASET (vec, 3 + i, tmp);
-       }
+#endif /* not USE_FONT_BACKEND */
+           vec = Fmake_vector (make_number (ASIZE (elt) + 3), Qnil);
+         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 (enable_font_backend
-         && EQ (base_fontset, Vdefault_fontset))
-       {
-         Lisp_Object script, font_spec, tmp;
-
-         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));
-         tmp = Fmake_vector (make_number (5), Qnil);
-         ASET (tmp, 3, font_spec);
-         ASET (vec, 3 + i, tmp);
-       }
+         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.  */
-      FONTSET_SET (fontset, range, vec);
+         /* Then store it in the fontset.  */
+         if (! fallback)
+           FONTSET_SET (fontset, range, vec);
+         else
+           FONTSET_FALLBACK (fontset) = vec;
+       }
     }
+  if (EQ (vec, Qt))
+    return Qnil;
 
- retry:
   if (XINT (AREF (vec, 0)) != charset_ordered_list_tick)
     /* The priority of charsets is changed after we selected a face
        for C last time.  */
@@ -647,8 +662,6 @@ fontset_font (fontset, c, face, id)
   /* Find the first available font in the vector of RFONT-DEF.  */
   for (; i < ASIZE (vec); i++)
     {
-      Lisp_Object font_def;
-
       elt = AREF (vec, i);
       if (NILP (elt))
        continue;
@@ -670,44 +683,49 @@ fontset_font (fontset, c, face, id)
          /* ELT == [ FACE-ID FONT-INDEX FONT-DEF FONT-ENTITY FONT-OBJECT ] */
          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;
 
-         if (NILP (font_entity) && ! NILP (AREF (font_def, 0)))
+         if (NILP (font_entity))
            {
-             Lisp_Object tmp = AREF (font_def, 0);
-             Lisp_Object spec = Ffont_spec (0, NULL);
-
-             if (STRINGP (tmp))
-               font_merge_old_spec (tmp, Qnil, Qnil, spec);
-             else
+             if (! FONT_SPEC_P (font_spec))
                {
-                 Lisp_Object family = AREF (tmp, 0);
-                 Lisp_Object registry = AREF (tmp, 5);;
+                 /* 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, spec);
+                     font_merge_old_spec (Qnil, family, registry, font_spec);
+                   }
+                 ASET (font_def, 0, font_spec);
                }
-             font_entity = font_find_for_lface (f, face->lface, spec);
-             ASET (elt, 3, font_entity);
-           }
-         else if (FONT_SPEC_P (font_entity))
-           {
-             font_entity = font_find_for_lface (f, face->lface, font_entity);
+             font_entity = font_find_for_lface (f, face->lface, font_spec);
              ASET (elt, 3, font_entity);
-           }
-         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;
            }
          has_char = font_has_char (f, font_entity, c);
          if (has_char == 0)
            continue;
-         if (NILP (font_object))
-           font_object = font_open_for_lface (f, face->lface, font_entity);
          if (NILP (font_object))
            {
-             ASET (elt, 1, make_number (-1));
-             continue;
+             font_object = font_open_for_lface (f, font_entity,
+                                                face->lface, font_spec);
+             ASET (elt, 4, font_object);
+             if (NILP (font_object))
+               {
+                 ASET (elt, 1, make_number (-1));
+                 continue;
+               }
            }
          ASET (elt, 1, make_number (0));
          ASET (elt, 4, font_object);
@@ -781,53 +799,45 @@ fontset_font (fontset, c, face, id)
       /* Now we have the opened font.  */
       return elt;
     }
+  return Qnil;
+}
 
- try_fallback:
-  if (! EQ (vec, FONTSET_FALLBACK (fontset)))
-    {
-      vec = FONTSET_FALLBACK (fontset);
-      if (VECTORP (vec))
-       goto retry;
-      if (EQ (vec, Qt))
-       goto try_default;
-      elt = FONTSET_FALLBACK (base_fontset);
-      if (! NILP (elt))
-       {
-         vec = Fmake_vector (make_number (ASIZE (elt) + 3), make_number (-1));
-         ASET (vec, 2, Qnil);
-         for (i = 0; i < ASIZE (elt); i++)
-           {
-             Lisp_Object tmp;
 
-#ifdef USE_FONT_BACKEND
-             if (enable_font_backend)
-               tmp = Fmake_vector (make_number (5), Qnil);
-             else
-#endif /* USE_FONT_BACKEND */
-             tmp = Fmake_vector (make_number (4), Qnil);
-             ASET (tmp, 2, AREF (elt, i));
-             ASET (vec, 3 + i, tmp);
-           }
-         FONTSET_FALLBACK (fontset) = vec;       
-         goto retry;
-       }
-      /* Record that this fontset has no fallback fonts.  */
-      FONTSET_FALLBACK (fontset) = Qt;
-    }
+static Lisp_Object
+fontset_font (fontset, c, face, id)
+     Lisp_Object fontset;
+     int c;
+     struct face *face;
+     int id;
+{
+  Lisp_Object rfont_def;
+  Lisp_Object base_fontset;
 
-  /* Try the default fontset.  */
- try_default:
+  /* Try a font-group for C. */
+  rfont_def = fontset_find_font (fontset, c, face, id, 0);
+  if (! NILP (rfont_def))
+    return rfont_def;
+  base_fontset = FONTSET_BASE (fontset);
+  /* Try a font-group for C of the default fontset. */
   if (! EQ (base_fontset, Vdefault_fontset))
     {
       if (NILP (FONTSET_DEFAULT (fontset)))
        FONTSET_DEFAULT (fontset)
          = make_fontset (FONTSET_FRAME (fontset), Qnil, Vdefault_fontset);
-      return fontset_font (FONTSET_DEFAULT (fontset), c, face, id);
+      rfont_def = fontset_find_font (FONTSET_DEFAULT (fontset), c, face, id, 0);
     }
-  return Qnil;
+  if (! NILP (rfont_def))
+    return rfont_def;
+  /* 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))
+    rfont_def = fontset_find_font (FONTSET_DEFAULT (fontset), c, face, id, 1);
+  return rfont_def;
 }
 
-
 /* Return a newly created fontset with NAME.  If BASE is nil, make a
    base fontset.  Otherwise make a realized fontset whose base is
    BASE.  */
@@ -961,7 +971,7 @@ free_face_fontset (f, face)
 }
 
 
-/* Return 1 iff FACE is suitable for displaying character C.
+/* Return 1 if FACE is suitable for displaying character C.
    Otherwise return 0.  Called from the macro FACE_SUITABLE_FOR_CHAR_P
    when C is not an ASCII character.  */
 
@@ -1073,7 +1083,7 @@ make_fontset_for_ascii_face (f, base_fontset_id, face)
 
   fontset = make_fontset (frame, Qnil, base_fontset);
   {
-    Lisp_Object elt, rfont_def;
+    Lisp_Object elt, rfont_def, val;
 
     elt = FONTSET_REF (base_fontset, 0);
     xassert (VECTORP (elt) && ASIZE (elt) > 0);
@@ -1092,7 +1102,6 @@ make_fontset_for_ascii_face (f, base_fontset_id, face)
       rfont_def = Fmake_vector (make_number (4), Qnil);
       ASET (rfont_def, 3, build_string (face->font_name));
     }
-    ASET (rfont_def, 0, make_number (face->id));
     ASET (rfont_def, 1, make_number (face->font_info_id));
     ASET (rfont_def, 2, AREF (elt, 0));
     elt = Fmake_vector (make_number (4), Qnil);
@@ -1100,7 +1109,13 @@ make_fontset_for_ascii_face (f, base_fontset_id, face)
     ASET (elt, 1, make_number (charset_ascii));
     ASET (elt, 2, rfont_def);
     ASET (elt, 3, rfont_def);
-    char_table_set_range (fontset, 0, 127, elt);
+
+    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));
 }
@@ -1390,9 +1405,9 @@ static void
 free_realized_fontsets (base)
      Lisp_Object base;
 {
-#if 0
   int id;
 
+#if 0
   /* 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
@@ -1420,7 +1435,18 @@ free_realized_fontsets (base)
     }
   UNBLOCK_INPUT;
 #else  /* not 0 */
-  Fclear_face_cache (Qt);
+  /* But, we don't have to call Fclear_face_cache if no fontset has
+     been realized from BASE.  */
+  for (id = 0; id < ASIZE (Vfontset_table); id++)
+    {
+      Lisp_Object this = AREF (Vfontset_table, id);
+
+      if (EQ (FONTSET_BASE (this), base))
+       {
+         Fclear_face_cache (Qt);
+         break;
+       }
+    }
 #endif /* not 0 */
 }
 
@@ -1851,7 +1877,7 @@ new_fontset_from_font (font_object)
 {
   Lisp_Object font_name = font_get_name (font_object);
   Lisp_Object font_spec = font_get_spec (font_object);
-  Lisp_Object short_name, name, fontset;
+  Lisp_Object fontset_spec, short_name, name, fontset;
 
   if (NILP (auto_fontset_alist))
     short_name = build_string ("fontset-startup");
@@ -1863,21 +1889,26 @@ new_fontset_from_font (font_object)
       sprintf (temp, "fontset-auto%d", len);
       short_name = build_string (temp);
     }
-  ASET (font_spec, FONT_REGISTRY_INDEX, short_name);
-  name = Ffont_xlfd_name (font_spec);
+  fontset_spec = Fcopy_sequence (font_spec);
+  ASET (fontset_spec, FONT_REGISTRY_INDEX, short_name);
+  name = Ffont_xlfd_name (fontset_spec);
   if (NILP (name))
     {
       int i;
 
       for (i = 0; i < FONT_SIZE_INDEX; i++)
        if ((i != FONT_FAMILY_INDEX) && (i != FONT_REGISTRY_INDEX))
-         ASET (font_spec, i, Qnil);
-      name = Ffont_xlfd_name (font_spec);
+         ASET (fontset_spec, i, Qnil);
+      name = Ffont_xlfd_name (fontset_spec);
       if (NILP (name))
        abort ();
     }
   fontset = make_fontset (Qnil, name, Qnil);
   FONTSET_ASCII (fontset) = font_name;
+  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);
+  Fset_fontset_font (name, Qnil, font_spec, Qnil, Qnil);
   return XINT (FONTSET_ID (fontset));
 }
 
@@ -2362,9 +2393,11 @@ dump_fontset (fontset)
          FRAME_PTR f = XFRAME (frame);
 
          if (FRAME_LIVE_P (f))
-           ASET (vec, 1, f->name);
+           ASET (vec, 1,
+                 Fcons (FONTSET_NAME (FONTSET_BASE (fontset)), f->name));
          else
-           ASET (vec, 1, Qt);
+           ASET (vec, 1,
+                 Fcons (FONTSET_NAME (FONTSET_BASE (fontset)), Qnil));
        }
       if (!NILP (FONTSET_DEFAULT (fontset)))
        ASET (vec, 2, FONTSET_ID (FONTSET_DEFAULT (fontset)));