remove Lisp_Free struct type
[bpt/emacs.git] / src / font.c
index 231df2e..251d43b 100644 (file)
@@ -1,6 +1,6 @@
 /* font.c -- "Font" primitives.
 
-Copyright (C) 2006-2013 Free Software Foundation, Inc.
+Copyright (C) 2006-2014 Free Software Foundation, Inc.
 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
   National Institute of Advanced Industrial Science and Technology (AIST)
   Registration Number H13PRO009
@@ -148,7 +148,27 @@ static Lisp_Object font_charset_alist;
    here.  */
 static struct font_driver_list *font_driver_list;
 
-\f
+#ifdef ENABLE_CHECKING
+
+/* Used to catch bogus pointers in font objects.  */
+
+bool
+valid_font_driver (struct font_driver *drv)
+{
+  Lisp_Object tail, frame;
+  struct font_driver_list *fdl;
+
+  for (fdl = font_driver_list; fdl; fdl = fdl->next)
+    if (fdl->driver == drv)
+      return true;
+  FOR_EACH_FRAME (tail, frame)
+    for (fdl = XFRAME (frame)->font_driver_list; fdl; fdl = fdl->next)
+      if (fdl->driver == drv)
+       return true;
+  return false;
+}
+
+#endif /* ENABLE_CHECKING */
 
 /* Creators of font-related Lisp object.  */
 
@@ -187,6 +207,9 @@ font_make_object (int size, Lisp_Object entity, int pixelsize)
     = (struct font *) allocate_pseudovector (size, FONT_OBJECT_MAX, PVEC_FONT);
   int i;
 
+  /* GC can happen before the driver is set up,
+     so avoid dangling pointer here (Bug#17771).  */
+  font->driver = NULL;
   XSETFONT (font_object, font);
 
   if (! NILP (entity))
@@ -204,9 +227,9 @@ font_make_object (int size, Lisp_Object entity, int pixelsize)
 
 \f
 
-static int font_pixel_size (FRAME_PTR f, Lisp_Object);
-static Lisp_Object font_open_entity (FRAME_PTR, Lisp_Object, int);
-static Lisp_Object font_matching_entity (FRAME_PTR, Lisp_Object *,
+static int font_pixel_size (struct frame *f, Lisp_Object);
+static Lisp_Object font_open_entity (struct frame *, Lisp_Object, int);
+static Lisp_Object font_matching_entity (struct frame *, Lisp_Object *,
                                          Lisp_Object);
 static unsigned font_encode_char (Lisp_Object, int);
 
@@ -259,17 +282,15 @@ font_intern_prop (const char *str, ptrdiff_t len, bool force_symbol)
 
   if (SYMBOLP (tem))
     return tem;
-  if (len == nchars || len != nbytes)
-    tem = make_unibyte_string (str, len);
-  else
-    tem = make_multibyte_string (str, nchars, len);
+  tem = make_specified_string (str, nchars, len,
+                              len != nchars && len == nbytes);
   return Fintern (tem, obarray);
 }
 
 /* Return a pixel size of font-spec SPEC on frame F.  */
 
 static int
-font_pixel_size (FRAME_PTR f, Lisp_Object spec)
+font_pixel_size (struct frame *f, Lisp_Object spec)
 {
 #ifdef HAVE_WINDOW_SYSTEM
   Lisp_Object size = AREF (spec, FONT_SIZE_INDEX);
@@ -472,7 +493,7 @@ font_registry_charsets (Lisp_Object registry, struct charset **encoding, struct
        goto invalid_entry;
       val = Fcons (make_number (encoding_id), make_number (repertory_id));
       font_charset_alist
-       = nconc2 (font_charset_alist, Fcons (Fcons (registry, val), Qnil));
+       = nconc2 (font_charset_alist, list1 (Fcons (registry, val)));
     }
 
   if (encoding)
@@ -483,7 +504,7 @@ font_registry_charsets (Lisp_Object registry, struct charset **encoding, struct
 
  invalid_entry:
   font_charset_alist
-    = nconc2 (font_charset_alist, Fcons (Fcons (registry, Qnil), Qnil));
+    = nconc2 (font_charset_alist, list1 (Fcons (registry, Qnil)));
   return -1;
 }
 
@@ -642,10 +663,6 @@ static const struct
     { &QCotf, font_prop_validate_otf }
   };
 
-/* Size (number of elements) of the above table.  */
-#define FONT_PROPERTY_TABLE_SIZE \
-  ((sizeof font_property_table) / (sizeof *font_property_table))
-
 /* Return an index number of font property KEY or -1 if KEY is not an
    already known property.  */
 
@@ -654,7 +671,7 @@ get_font_prop_index (Lisp_Object key)
 {
   int i;
 
-  for (i = 0; i < FONT_PROPERTY_TABLE_SIZE; i++)
+  for (i = 0; i < ARRAYELTS (font_property_table); i++)
     if (EQ (key, *font_property_table[i].key))
       return i;
   return -1;
@@ -1453,7 +1470,7 @@ font_parse_fcname (char *name, ptrdiff_t len, Lisp_Object font)
                  else
                     {
                       extra_props = nconc2 (extra_props,
-                                            Fcons (Fcons (key, val), Qnil));
+                                            list1 (Fcons (key, val)));
                     }
                }
              p = q;
@@ -1861,7 +1878,7 @@ otf_open (Lisp_Object file)
   else
     {
       otf = STRINGP (file) ? OTF_open (SSDATA (file)) : NULL;
-      val = make_save_pointer (otf);
+      val = make_save_ptr (otf);
       otf_list = Fcons (Fcons (file, val), otf_list);
     }
   return otf;
@@ -2037,11 +2054,6 @@ font_otf_Anchor (OTF_Anchor *anchor)
 \f
 /* Font sorting.  */
 
-static unsigned font_score (Lisp_Object, Lisp_Object *);
-static int font_compare (const void *, const void *);
-static Lisp_Object font_sort_entities (Lisp_Object, Lisp_Object,
-                                       Lisp_Object, int);
-
 static double
 font_rescale_ratio (Lisp_Object font_entity)
 {
@@ -2186,14 +2198,14 @@ font_compare (const void *d1, const void *d2)
    such a case.  */
 
 static Lisp_Object
-font_sort_entities (Lisp_Object list, Lisp_Object prefer, Lisp_Object frame, int best_only)
+font_sort_entities (Lisp_Object list, Lisp_Object prefer,
+                   struct frame *f, int best_only)
 {
   Lisp_Object prefer_prop[FONT_SPEC_MAX];
   int len, maxlen, i;
   struct font_sort_data *data;
   unsigned best_score;
   Lisp_Object best_entity;
-  struct frame *f = XFRAME (frame);
   Lisp_Object tail, vec IF_LINT (= Qnil);
   USE_SAFE_ALLOCA;
 
@@ -2201,7 +2213,7 @@ font_sort_entities (Lisp_Object list, Lisp_Object prefer, Lisp_Object frame, int
     prefer_prop[i] = AREF (prefer, i);
   if (FLOATP (prefer_prop[FONT_SIZE_INDEX]))
     prefer_prop[FONT_SIZE_INDEX]
-      = make_number (font_pixel_size (XFRAME (frame), prefer));
+      = make_number (font_pixel_size (f, prefer));
 
   if (NILP (XCDR (list)))
     {
@@ -2500,16 +2512,16 @@ font_match_p (Lisp_Object spec, Lisp_Object font)
 
    where DRIVER-TYPE is a symbol such as `x', `xft', etc., NUM-FRAMES
    is a number frames sharing this cache, and FONT-CACHE-DATA is a
-   cons (FONT-SPEC FONT-ENTITY ...).  */
+   cons (FONT-SPEC . [FONT-ENTITY ...]).  */
 
-static void font_prepare_cache (FRAME_PTR, struct font_driver *);
-static void font_finish_cache (FRAME_PTR, struct font_driver *);
-static Lisp_Object font_get_cache (FRAME_PTR, struct font_driver *);
-static void font_clear_cache (FRAME_PTR, Lisp_Object,
+static void font_prepare_cache (struct frame *, struct font_driver *);
+static void font_finish_cache (struct frame *, struct font_driver *);
+static Lisp_Object font_get_cache (struct frame *, struct font_driver *);
+static void font_clear_cache (struct frame *, Lisp_Object,
                               struct font_driver *);
 
 static void
-font_prepare_cache (FRAME_PTR f, struct font_driver *driver)
+font_prepare_cache (struct frame *f, struct font_driver *driver)
 {
   Lisp_Object cache, val;
 
@@ -2519,7 +2531,7 @@ font_prepare_cache (FRAME_PTR f, struct font_driver *driver)
     val = XCDR (val);
   if (NILP (val))
     {
-      val = Fcons (driver->type, Fcons (make_number (1), Qnil));
+      val = list2 (driver->type, make_number (1));
       XSETCDR (cache, Fcons (val, XCDR (cache)));
     }
   else
@@ -2531,7 +2543,7 @@ font_prepare_cache (FRAME_PTR f, struct font_driver *driver)
 
 
 static void
-font_finish_cache (FRAME_PTR f, struct font_driver *driver)
+font_finish_cache (struct frame *f, struct font_driver *driver)
 {
   Lisp_Object cache, val, tmp;
 
@@ -2552,7 +2564,7 @@ font_finish_cache (FRAME_PTR f, struct font_driver *driver)
 
 
 static Lisp_Object
-font_get_cache (FRAME_PTR f, struct font_driver *driver)
+font_get_cache (struct frame *f, struct font_driver *driver)
 {
   Lisp_Object val = driver->get_cache (f);
   Lisp_Object type = driver->type;
@@ -2567,21 +2579,24 @@ font_get_cache (FRAME_PTR f, struct font_driver *driver)
 
 
 static void
-font_clear_cache (FRAME_PTR f, Lisp_Object cache, struct font_driver *driver)
+font_clear_cache (struct frame *f, Lisp_Object cache, struct font_driver *driver)
 {
   Lisp_Object tail, elt;
-  Lisp_Object tail2, entity;
+  Lisp_Object entity;
+  ptrdiff_t i;
 
   /* CACHE = (DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...) */
   for (tail = XCDR (XCDR (cache)); CONSP (tail); tail = XCDR (tail))
     {
       elt = XCAR (tail);
-      /* elt should have the form (FONT-SPEC FONT-ENTITY ...) */
+      /* elt should have the form (FONT-SPEC . [FONT-ENTITY ...]) */
       if (CONSP (elt) && FONT_SPEC_P (XCAR (elt)))
        {
-         for (tail2 = XCDR (elt); CONSP (tail2); tail2 = XCDR (tail2))
+         elt = XCDR (elt);
+         eassert (VECTORP (elt));
+         for (i = 0; i < ASIZE (elt); i++)
            {
-             entity = XCAR (tail2);
+             entity = AREF (elt, i);
 
              if (FONT_ENTITY_P (entity)
                  && EQ (driver->type, AREF (entity, FONT_TYPE_INDEX)))
@@ -2596,7 +2611,7 @@ font_clear_cache (FRAME_PTR f, Lisp_Object cache, struct font_driver *driver)
                      if (! NILP (AREF (val, FONT_TYPE_INDEX)))
                        {
                          eassert (font && driver == font->driver);
-                         driver->close (f, font);
+                         driver->close (font);
                        }
                    }
                  if (driver->free_entity)
@@ -2692,9 +2707,8 @@ font_delete_unmatched (Lisp_Object vec, Lisp_Object spec, int size)
    same font-driver.  */
 
 Lisp_Object
-font_list_entities (Lisp_Object frame, Lisp_Object spec)
+font_list_entities (struct frame *f, Lisp_Object spec)
 {
-  FRAME_PTR f = XFRAME (frame);
   struct font_driver_list *driver_list = f->font_driver_list;
   Lisp_Object ftype, val;
   Lisp_Object list = Qnil;
@@ -2724,7 +2738,7 @@ font_list_entities (Lisp_Object frame, Lisp_Object spec)
   ASET (scratch_font_spec, FONT_SPACING_INDEX, AREF (spec, FONT_SPACING_INDEX));
   ASET (scratch_font_spec, FONT_EXTRA_INDEX, AREF (spec, FONT_EXTRA_INDEX));
 
-  for (i = 0; driver_list; driver_list = driver_list->next)
+  for (; driver_list; driver_list = driver_list->next)
     if (driver_list->on
        && (NILP (ftype) || EQ (driver_list->driver->type, ftype)))
       {
@@ -2736,22 +2750,21 @@ font_list_entities (Lisp_Object frame, Lisp_Object spec)
          val = XCDR (val);
        else
          {
-           Lisp_Object copy;
+           val = driver_list->driver->list (f, scratch_font_spec);
+           if (!NILP (val))
+             {
+               Lisp_Object copy = copy_font_spec (scratch_font_spec);
 
-           val = driver_list->driver->list (frame, scratch_font_spec);
-           if (NILP (val))
-             val = zero_vector;
-           else
-             val = Fvconcat (1, &val);
-           copy = copy_font_spec (scratch_font_spec);
-           ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type);
-           XSETCDR (cache, Fcons (Fcons (copy, val), XCDR (cache)));
+               val = Fvconcat (1, &val);
+               ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type);
+               XSETCDR (cache, Fcons (Fcons (copy, val), XCDR (cache)));
+             }
          }
-       if (ASIZE (val) > 0
+       if (VECTORP (val) && ASIZE (val) > 0
            && (need_filtering
                || ! NILP (Vface_ignored_fonts)))
          val = font_delete_unmatched (val, need_filtering ? spec : Qnil, size);
-       if (ASIZE (val) > 0)
+       if (VECTORP (val) && ASIZE (val) > 0)
          list = Fcons (val, list);
       }
 
@@ -2766,14 +2779,12 @@ font_list_entities (Lisp_Object frame, Lisp_Object spec)
    font-related attributes.  */
 
 static Lisp_Object
-font_matching_entity (FRAME_PTR f, Lisp_Object *attrs, Lisp_Object spec)
+font_matching_entity (struct frame *f, Lisp_Object *attrs, Lisp_Object spec)
 {
   struct font_driver_list *driver_list = f->font_driver_list;
   Lisp_Object ftype, size, entity;
-  Lisp_Object frame;
   Lisp_Object work = copy_font_spec (spec);
 
-  XSETFRAME (frame, f);
   ftype = AREF (spec, FONT_TYPE_INDEX);
   size = AREF (spec, FONT_SIZE_INDEX);
 
@@ -2789,18 +2800,22 @@ font_matching_entity (FRAME_PTR f, Lisp_Object *attrs, Lisp_Object spec)
        && (NILP (ftype) || EQ (driver_list->driver->type, ftype)))
       {
        Lisp_Object cache = font_get_cache (f, driver_list->driver);
-       Lisp_Object copy;
 
        ASET (work, FONT_TYPE_INDEX, driver_list->driver->type);
        entity = assoc_no_quit (work, XCDR (cache));
        if (CONSP (entity))
-         entity = XCDR (entity);
+         entity = AREF (XCDR (entity), 0);
        else
          {
-           entity = driver_list->driver->match (frame, work);
-           copy = copy_font_spec (work);
-           ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type);
-           XSETCDR (cache, Fcons (Fcons (copy, entity), XCDR (cache)));
+           entity = driver_list->driver->match (f, work);
+           if (!NILP (entity))
+             {
+               Lisp_Object copy = copy_font_spec (work);
+               Lisp_Object match = Fvector (1, &entity);
+
+               ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type);
+               XSETCDR (cache, Fcons (Fcons (copy, match), XCDR (cache)));
+             }
          }
        if (! NILP (entity))
          break;
@@ -2814,7 +2829,7 @@ font_matching_entity (FRAME_PTR f, Lisp_Object *attrs, Lisp_Object spec)
    opened font object.  */
 
 static Lisp_Object
-font_open_entity (FRAME_PTR f, Lisp_Object entity, int pixel_size)
+font_open_entity (struct frame *f, Lisp_Object entity, int pixel_size)
 {
   struct font_driver_list *driver_list;
   Lisp_Object objlist, size, val, font_object;
@@ -2869,19 +2884,19 @@ font_open_entity (FRAME_PTR f, Lisp_Object entity, int pixel_size)
               : 1);
   height = (font->height ? font->height : 1);
 #ifdef HAVE_WINDOW_SYSTEM
-  FRAME_X_DISPLAY_INFO (f)->n_fonts++;
-  if (FRAME_X_DISPLAY_INFO (f)->n_fonts == 1)
+  FRAME_DISPLAY_INFO (f)->n_fonts++;
+  if (FRAME_DISPLAY_INFO (f)->n_fonts == 1)
     {
       FRAME_SMALLEST_CHAR_WIDTH (f) = min_width;
       FRAME_SMALLEST_FONT_HEIGHT (f) = height;
-      fonts_changed_p = 1;
+      f->fonts_changed = 1;
     }
   else
     {
       if (FRAME_SMALLEST_CHAR_WIDTH (f) > min_width)
-       FRAME_SMALLEST_CHAR_WIDTH (f) = min_width, fonts_changed_p = 1;
+       FRAME_SMALLEST_CHAR_WIDTH (f) = min_width, f->fonts_changed = 1;
       if (FRAME_SMALLEST_FONT_HEIGHT (f) > height)
-       FRAME_SMALLEST_FONT_HEIGHT (f) = height, fonts_changed_p = 1;
+       FRAME_SMALLEST_FONT_HEIGHT (f) = height, f->fonts_changed = 1;
     }
 #endif
 
@@ -2892,7 +2907,7 @@ font_open_entity (FRAME_PTR f, Lisp_Object entity, int pixel_size)
 /* Close FONT_OBJECT that is opened on frame F.  */
 
 static void
-font_close_object (FRAME_PTR f, Lisp_Object font_object)
+font_close_object (struct frame *f, Lisp_Object font_object)
 {
   struct font *font = XFONT_OBJECT (font_object);
 
@@ -2900,10 +2915,10 @@ font_close_object (FRAME_PTR f, Lisp_Object font_object)
     /* Already closed.  */
     return;
   FONT_ADD_LOG ("close", font_object, Qnil);
-  font->driver->close (f, font);
+  font->driver->close (font);
 #ifdef HAVE_WINDOW_SYSTEM
-  eassert (FRAME_X_DISPLAY_INFO (f)->n_fonts);
-  FRAME_X_DISPLAY_INFO (f)->n_fonts--;
+  eassert (FRAME_DISPLAY_INFO (f)->n_fonts);
+  FRAME_DISPLAY_INFO (f)->n_fonts--;
 #endif
 }
 
@@ -2912,7 +2927,7 @@ font_close_object (FRAME_PTR f, Lisp_Object font_object)
    FONT is a font-entity and it must be opened to check.  */
 
 int
-font_has_char (FRAME_PTR f, Lisp_Object font, int c)
+font_has_char (struct frame *f, Lisp_Object font, int c)
 {
   struct font *fontp;
 
@@ -3039,12 +3054,12 @@ font_clear_prop (Lisp_Object *attrs, enum font_property_index prop)
    supports C and is the best match for ATTRS and PIXEL_SIZE.  */
 
 static Lisp_Object
-font_select_entity (Lisp_Object frame, Lisp_Object entities, Lisp_Object *attrs, int pixel_size, int c)
+font_select_entity (struct frame *f, Lisp_Object entities,
+                   Lisp_Object *attrs, int pixel_size, int c)
 {
   Lisp_Object font_entity;
   Lisp_Object prefer;
   int i;
-  FRAME_PTR f = XFRAME (frame);
 
   if (NILP (XCDR (entities))
       && ASIZE (XCAR (entities)) == 1)
@@ -3075,7 +3090,7 @@ font_select_entity (Lisp_Object frame, Lisp_Object entities, Lisp_Object *attrs,
     FONT_SET_STYLE (prefer, FONT_WIDTH_INDEX, attrs[LFACE_SWIDTH_INDEX]);
   ASET (prefer, FONT_SIZE_INDEX, make_number (pixel_size));
 
-  return font_sort_entities (entities, prefer, frame, c);
+  return font_sort_entities (entities, prefer, f, c);
 }
 
 /* Return a font-entity that satisfies SPEC and is the best match for
@@ -3083,10 +3098,10 @@ font_select_entity (Lisp_Object frame, Lisp_Object entities, Lisp_Object *attrs,
    character that the entity must support.  */
 
 Lisp_Object
-font_find_for_lface (FRAME_PTR f, Lisp_Object *attrs, Lisp_Object spec, int c)
+font_find_for_lface (struct frame *f, Lisp_Object *attrs, Lisp_Object spec, int c)
 {
   Lisp_Object work;
-  Lisp_Object frame, entities, val;
+  Lisp_Object entities, val;
   Lisp_Object foundry[3], *family, registry[3], adstyle[3];
   int pixel_size;
   int i, j, k, l;
@@ -3118,7 +3133,6 @@ font_find_for_lface (FRAME_PTR f, Lisp_Object *attrs, Lisp_Object spec, int c)
 
   work = copy_font_spec (spec);
   ASET (work, FONT_TYPE_INDEX, AREF (spec, FONT_TYPE_INDEX));
-  XSETFRAME (frame, f);
   pixel_size = font_pixel_size (f, spec);
   if (pixel_size == 0 && INTEGERP (attrs[LFACE_HEIGHT_INDEX]))
     {
@@ -3212,13 +3226,16 @@ font_find_for_lface (FRAME_PTR f, Lisp_Object *attrs, Lisp_Object spec, int c)
              for (l = 0; SYMBOLP (adstyle[l]); l++)
                {
                  ASET (work, FONT_ADSTYLE_INDEX, adstyle[l]);
-                 entities = font_list_entities (frame, work);
+                 entities = font_list_entities (f, work);
                  if (! NILP (entities))
                    {
-                     val = font_select_entity (frame, entities,
+                     val = font_select_entity (f, entities,
                                                attrs, pixel_size, c);
                      if (! NILP (val))
-                        return val;
+                       {
+                         SAFE_FREE ();
+                         return val;
+                       }
                    }
                }
            }
@@ -3231,7 +3248,7 @@ font_find_for_lface (FRAME_PTR f, Lisp_Object *attrs, Lisp_Object spec, int c)
 
 
 Lisp_Object
-font_open_for_lface (FRAME_PTR f, Lisp_Object entity, Lisp_Object *attrs, Lisp_Object spec)
+font_open_for_lface (struct frame *f, Lisp_Object entity, Lisp_Object *attrs, Lisp_Object spec)
 {
   int size;
 
@@ -3278,7 +3295,7 @@ font_open_for_lface (FRAME_PTR f, Lisp_Object entity, Lisp_Object *attrs, Lisp_O
    font-object.  */
 
 Lisp_Object
-font_load_for_lface (FRAME_PTR f, Lisp_Object *attrs, Lisp_Object spec)
+font_load_for_lface (struct frame *f, Lisp_Object *attrs, Lisp_Object spec)
 {
   Lisp_Object entity, name;
 
@@ -3307,7 +3324,7 @@ font_load_for_lface (FRAME_PTR f, Lisp_Object *attrs, Lisp_Object spec)
 /* Make FACE on frame F ready to use the font opened for FACE.  */
 
 void
-font_prepare_for_face (FRAME_PTR f, struct face *face)
+font_prepare_for_face (struct frame *f, struct face *face)
 {
   if (face->font->driver->prepare_face)
     face->font->driver->prepare_face (f, face);
@@ -3317,11 +3334,10 @@ font_prepare_for_face (FRAME_PTR f, struct face *face)
 /* Make FACE on frame F stop using the font opened for FACE.  */
 
 void
-font_done_for_face (FRAME_PTR f, struct face *face)
+font_done_for_face (struct frame *f, struct face *face)
 {
   if (face->font->driver->done_face)
     face->font->driver->done_face (f, face);
-  face->extra = NULL;
 }
 
 
@@ -3329,7 +3345,7 @@ font_done_for_face (FRAME_PTR f, struct face *face)
    font is found, return Qnil.  */
 
 Lisp_Object
-font_open_by_spec (FRAME_PTR f, Lisp_Object spec)
+font_open_by_spec (struct frame *f, Lisp_Object spec)
 {
   Lisp_Object attrs[LFACE_VECTOR_SIZE];
 
@@ -3353,7 +3369,7 @@ font_open_by_spec (FRAME_PTR f, Lisp_Object spec)
    found, return Qnil.  */
 
 Lisp_Object
-font_open_by_name (FRAME_PTR f, Lisp_Object name)
+font_open_by_name (struct frame *f, Lisp_Object name)
 {
   Lisp_Object args[2];
   Lisp_Object spec, ret;
@@ -3383,14 +3399,16 @@ font_open_by_name (FRAME_PTR f, Lisp_Object name)
    (e.g. syms_of_xfont).  */
 
 void
-register_font_driver (struct font_driver *driver, FRAME_PTR f)
+register_font_driver (struct font_driver *driver, struct frame *f)
 {
   struct font_driver_list *root = f ? f->font_driver_list : font_driver_list;
   struct font_driver_list *prev, *list;
 
+#ifdef HAVE_WINDOW_SYSTEM
   if (f && ! driver->draw)
     error ("Unusable font driver for a frame: %s",
           SDATA (SYMBOL_NAME (driver->type)));
+#endif /* HAVE_WINDOW_SYSTEM */
 
   for (prev = NULL, list = root; list; prev = list, list = list->next)
     if (EQ (list->driver->type, driver->type))
@@ -3411,7 +3429,7 @@ register_font_driver (struct font_driver *driver, FRAME_PTR f)
 }
 
 void
-free_font_driver_list (FRAME_PTR f)
+free_font_driver_list (struct frame *f)
 {
   struct font_driver_list *list, *next;
 
@@ -3433,7 +3451,7 @@ free_font_driver_list (FRAME_PTR f)
    F.  */
 
 Lisp_Object
-font_update_drivers (FRAME_PTR f, Lisp_Object new_drivers)
+font_update_drivers (struct frame *f, Lisp_Object new_drivers)
 {
   Lisp_Object active_drivers = Qnil;
   struct font_driver_list *list;
@@ -3517,13 +3535,12 @@ font_update_drivers (FRAME_PTR f, Lisp_Object new_drivers)
 
   for (list = f->font_driver_list; list; list = list->next)
     if (list->on)
-      active_drivers = nconc2 (active_drivers,
-                              Fcons (list->driver->type, Qnil));
+      active_drivers = nconc2 (active_drivers, list1 (list->driver->type));
   return active_drivers;
 }
 
 int
-font_put_frame_data (FRAME_PTR f, struct font_driver *driver, void *data)
+font_put_frame_data (struct frame *f, struct font_driver *driver, void *data)
 {
   struct font_data_list *list, *prev;
 
@@ -3557,7 +3574,7 @@ font_put_frame_data (FRAME_PTR f, struct font_driver *driver, void *data)
 
 
 void *
-font_get_frame_data (FRAME_PTR f, struct font_driver *driver)
+font_get_frame_data (struct frame *f, struct font_driver *driver)
 {
   struct font_data_list *list;
 
@@ -3631,7 +3648,7 @@ static Lisp_Object
 font_at (int c, ptrdiff_t pos, struct face *face, struct window *w,
         Lisp_Object string)
 {
-  FRAME_PTR f;
+  struct frame *f;
   bool multibyte;
   Lisp_Object font_object;
 
@@ -3677,10 +3694,10 @@ font_at (int c, ptrdiff_t pos, struct face *face, struct window *w,
       ptrdiff_t endptr;
 
       if (STRINGP (string))
-       face_id = face_at_string_position (w, string, pos, 0, -1, -1, &endptr,
+       face_id = face_at_string_position (w, string, pos, 0, &endptr,
                                           DEFAULT_FACE_ID, 0);
       else
-       face_id = face_at_buffer_position (w, pos, -1, -1, &endptr,
+       face_id = face_at_buffer_position (w, pos, &endptr,
                                           pos + 100, 0, -1);
       face = FACE_FROM_ID (f, face_id);
     }
@@ -3724,7 +3741,7 @@ font_range (ptrdiff_t pos, ptrdiff_t pos_byte, ptrdiff_t *limit,
        {
          int face_id;
 
-         face_id = face_at_buffer_position (w, pos, 0, 0, &ignore,
+         face_id = face_at_buffer_position (w, pos, &ignore,
                                             *limit, 0, -1);
          face = FACE_FROM_ID (XFRAME (w->frame), face_id);
        }
@@ -4111,12 +4128,10 @@ control the order of the returned list.  Fonts are sorted by
 how close they are to PREFER.  */)
   (Lisp_Object font_spec, Lisp_Object frame, Lisp_Object num, Lisp_Object prefer)
 {
+  struct frame *f = decode_live_frame (frame);
   Lisp_Object vec, list;
   EMACS_INT n = 0;
 
-  if (NILP (frame))
-    frame = selected_frame;
-  CHECK_LIVE_FRAME (frame);
   CHECK_FONT_SPEC (font_spec);
   if (! NILP (num))
     {
@@ -4128,15 +4143,15 @@ how close they are to PREFER.  */)
   if (! NILP (prefer))
     CHECK_FONT_SPEC (prefer);
 
-  list = font_list_entities (frame, font_spec);
+  list = font_list_entities (f, font_spec);
   if (NILP (list))
     return Qnil;
   if (NILP (XCDR (list))
       && ASIZE (XCAR (list)) == 1)
-    return Fcons (AREF (XCAR (list), 0), Qnil);
+    return list1 (AREF (XCAR (list), 0));
 
   if (! NILP (prefer))
-    vec = font_sort_entities (list, prefer, frame, 0);
+    vec = font_sort_entities (list, prefer, f, 0);
   else
     vec = font_vconcat_entity_vectors (list);
   if (n == 0 || n >= ASIZE (vec))
@@ -4164,13 +4179,11 @@ If FRAME is omitted or nil, the selected frame is used.  */)
   struct font_driver_list *driver_list;
   Lisp_Object list = Qnil;
 
-  XSETFRAME (frame, f);
-
   for (driver_list = f->font_driver_list; driver_list;
        driver_list = driver_list->next)
     if (driver_list->driver->list_family)
       {
-       Lisp_Object val = driver_list->driver->list_family (frame);
+       Lisp_Object val = driver_list->driver->list_family (f);
        Lisp_Object tail = list;
 
        for (; CONSP (val); val = XCDR (val))
@@ -4240,36 +4253,38 @@ the consecutive wildcards are folded into one.  */)
   return make_string (name, namelen);
 }
 
+void
+clear_font_cache (struct frame *f)
+{
+  struct font_driver_list *driver_list = f->font_driver_list;
+
+  for (; driver_list; driver_list = driver_list->next)
+    if (driver_list->on)
+      {
+       Lisp_Object val, tmp, cache = driver_list->driver->get_cache (f);
+
+       val = XCDR (cache);
+       while (! NILP (val)
+              && ! EQ (XCAR (XCAR (val)), driver_list->driver->type))
+         val = XCDR (val);
+       eassert (! NILP (val));
+       tmp = XCDR (XCAR (val));
+       if (XINT (XCAR (tmp)) == 0)
+         {
+           font_clear_cache (f, XCAR (val), driver_list->driver);
+           XSETCDR (cache, XCDR (val));
+         }
+      }
+}
+
 DEFUN ("clear-font-cache", Fclear_font_cache, Sclear_font_cache, 0, 0, 0,
-       doc: /* Clear font cache.  */)
+       doc: /* Clear font cache of each frame.  */)
   (void)
 {
   Lisp_Object list, frame;
 
   FOR_EACH_FRAME (list, frame)
-    {
-      FRAME_PTR f = XFRAME (frame);
-      struct font_driver_list *driver_list = f->font_driver_list;
-
-      for (; driver_list; driver_list = driver_list->next)
-       if (driver_list->on)
-         {
-           Lisp_Object cache = driver_list->driver->get_cache (f);
-           Lisp_Object val, tmp;
-
-           val = XCDR (cache);
-           while (! NILP (val)
-                  && ! EQ (XCAR (XCAR (val)), driver_list->driver->type))
-             val = XCDR (val);
-           eassert (! NILP (val));
-           tmp = XCDR (XCAR (val));
-           if (XINT (XCAR (tmp)) == 0)
-             {
-               font_clear_cache (f, XCAR (val), driver_list->driver);
-               XSETCDR (cache, XCDR (val));
-             }
-         }
-    }
+    clear_font_cache (XFRAME (frame));
 
   return Qnil;
 }
@@ -4416,7 +4431,7 @@ where
   LANGSYS is a symbol specifying a langsys tag of OpenType,
   GSUB and GPOS, if non-nil, are lists of symbols specifying feature tags.
 
-If LANGYS is nil, the default langsys is selected.
+If LANGSYS is nil, the default langsys is selected.
 
 The features are applied in the order they appear in the list.  The
 symbol `*' means to apply all available features not present in this
@@ -4772,7 +4787,7 @@ character at index specified by POSITION.  */)
   if (NILP (string))
     {
       if (XBUFFER (w->contents) != current_buffer)
-       error ("Specified window is not displaying the current buffer.");
+       error ("Specified window is not displaying the current buffer");
       CHECK_NUMBER_COERCE_MARKER (position);
       if (! (BEGV <= XINT (position) && XINT (position) < ZV))
        args_out_of_range_3 (position, make_number (BEGV), make_number (ZV));
@@ -4796,7 +4811,7 @@ Type C-l to recover what previously shown.  */)
   (Lisp_Object font_object, Lisp_Object string)
 {
   Lisp_Object frame = selected_frame;
-  FRAME_PTR f = XFRAME (frame);
+  struct frame *f = XFRAME (frame);
   struct font *font;
   struct face *face;
   int i, len, width;
@@ -4829,6 +4844,21 @@ Type C-l to recover what previously shown.  */)
 }
 #endif
 
+DEFUN ("frame-font-cache", Fframe_font_cache, Sframe_font_cache, 0, 1, 0,
+       doc: /* Return FRAME's font cache.  Mainly used for debugging.
+If FRAME is omitted or nil, use the selected frame.  */)
+  (Lisp_Object frame)
+{
+#ifdef HAVE_WINDOW_SYSTEM
+  struct frame *f = decode_live_frame (frame);
+
+  if (FRAME_WINDOW_P (f))
+    return FRAME_DISPLAY_INFO (f)->name_list_element;
+  else
+#endif
+    return Qnil;
+}
+
 #endif /* FONT_DEBUG */
 
 #ifdef HAVE_WINDOW_SYSTEM
@@ -4901,8 +4931,7 @@ If the named font is not yet loaded, return nil.  */)
 #endif
 
 \f
-#define BUILD_STYLE_TABLE(TBL) \
-  build_style_table ((TBL), sizeof TBL / sizeof (struct table_entry))
+#define BUILD_STYLE_TABLE(TBL) build_style_table (TBL, ARRAYELTS (TBL))
 
 static Lisp_Object
 build_style_table (const struct table_entry *entry, int nelement)
@@ -5121,6 +5150,7 @@ syms_of_font (void)
 #if 0
   defsubr (&Sdraw_string);
 #endif
+  defsubr (&Sframe_font_cache);
 #endif /* FONT_DEBUG */
 #ifdef HAVE_WINDOW_SYSTEM
   defsubr (&Sfont_info);
@@ -5207,9 +5237,6 @@ EMACS_FONT_LOG is set.  Otherwise, it is set to t.  */);
 #ifdef HAVE_NTGUI
   syms_of_w32font ();
 #endif /* HAVE_NTGUI */
-#ifdef HAVE_NS
-  syms_of_nsfont ();
-#endif /* HAVE_NS */
 #endif /* HAVE_WINDOW_SYSTEM */
 }