]> code.delx.au - gnu-emacs/blobdiff - src/font.c
Merge from emacs-23
[gnu-emacs] / src / font.c
index c08477821edadf5aa665cb594ef1f837c23aba05..667a23e4b56a81f095cfea580ce191128f70a132 100644 (file)
@@ -21,7 +21,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 #include <stdio.h>
-#include <stdlib.h>
 #include <ctype.h>
 #include <setjmp.h>
 
@@ -48,10 +47,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "nsterm.h"
 #endif /* HAVE_NS */
 
-#ifdef HAVE_NS
-extern Lisp_Object Qfontsize;
-#endif
-
 Lisp_Object Qopentype;
 
 /* Important character set strings.  */
@@ -127,13 +122,8 @@ static const struct table_entry width_table[] =
   { 200, { "ultra-expanded", "ultraexpanded", "wide" }}
 };
 
-extern Lisp_Object Qnormal;
-
-/* Symbols representing keys of normal font properties.  */
-extern Lisp_Object QCtype, QCfamily, QCweight, QCslant, QCwidth;
-extern Lisp_Object QCheight, QCsize, QCname;
-
-Lisp_Object QCfoundry, QCadstyle, QCregistry;
+Lisp_Object QCfoundry;
+static Lisp_Object QCadstyle, QCregistry;
 /* Symbols representing keys of font extra info.  */
 Lisp_Object QCspacing, QCdpi, QCscalable, QCotf, QClang, QCscript, QCavgwidth;
 Lisp_Object QCantialias, QCfont_entity, QCfc_unknown_spec;
@@ -174,8 +164,8 @@ static struct font_driver_list *font_driver_list;
 
 /* Creaters of font-related Lisp object.  */
 
-Lisp_Object
-font_make_spec ()
+static Lisp_Object
+font_make_spec (void)
 {
   Lisp_Object font_spec;
   struct font_spec *spec
@@ -187,7 +177,7 @@ font_make_spec ()
 }
 
 Lisp_Object
-font_make_entity ()
+font_make_entity (void)
 {
   Lisp_Object font_entity;
   struct font_entity *entity
@@ -202,10 +192,7 @@ font_make_entity ()
    not nil, copy properties from ENTITY to the font-object.  If
    PIXELSIZE is positive, set the `size' property to PIXELSIZE.  */
 Lisp_Object
-font_make_object (size, entity, pixelsize)
-     int size;
-     Lisp_Object entity;
-     int pixelsize;
+font_make_object (int size, Lisp_Object entity, int pixelsize)
 {
   Lisp_Object font_object;
   struct font *font
@@ -229,10 +216,11 @@ font_make_object (size, entity, pixelsize)
 
 \f
 
-static int font_pixel_size P_ ((FRAME_PTR f, Lisp_Object));
-static Lisp_Object font_open_entity P_ ((FRAME_PTR, Lisp_Object, int));
-static Lisp_Object font_matching_entity P_ ((FRAME_PTR, Lisp_Object *,
-                                            Lisp_Object));
+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 *,
+                                         Lisp_Object);
+static unsigned font_encode_char (Lisp_Object, int);
 
 /* Number of registered font drivers.  */
 static int num_font_drivers;
@@ -245,15 +233,12 @@ static int num_font_drivers;
    STR.  */
 
 Lisp_Object
-font_intern_prop (str, len, force_symbol)
-     char *str;
-     int len;
-     int force_symbol;
+font_intern_prop (const char *str, int len, int force_symbol)
 {
   int i;
   Lisp_Object tem;
   Lisp_Object obarray;
-  int nbytes, nchars;
+  EMACS_INT nbytes, nchars;
 
   if (len == 1 && *str == '*')
     return Qnil;
@@ -290,9 +275,7 @@ font_intern_prop (str, len, force_symbol)
 /* Return a pixel size of font-spec SPEC on frame F.  */
 
 static int
-font_pixel_size (f, spec)
-     FRAME_PTR f;
-     Lisp_Object spec;
+font_pixel_size (FRAME_PTR f, Lisp_Object spec)
 {
 #ifdef HAVE_WINDOW_SYSTEM
   Lisp_Object size = AREF (spec, FONT_SIZE_INDEX);
@@ -327,10 +310,7 @@ font_pixel_size (f, spec)
    VAL is an integer.  */
 
 int
-font_style_to_value (prop, val, noerror)
-     enum font_property_index prop;
-     Lisp_Object val;
-     int noerror;
+font_style_to_value (enum font_property_index prop, Lisp_Object val, int noerror)
 {
   Lisp_Object table = AREF (font_style_table, prop - FONT_WEIGHT_INDEX);
   int len = ASIZE (table);
@@ -395,10 +375,7 @@ font_style_to_value (prop, val, noerror)
 }
 
 Lisp_Object
-font_style_symbolic (font, prop, for_face)
-     Lisp_Object font;
-     enum font_property_index prop;
-     int for_face;
+font_style_symbolic (Lisp_Object font, enum font_property_index prop, int for_face)
 {
   Lisp_Object val = AREF (font, prop);
   Lisp_Object table, elt;
@@ -414,18 +391,12 @@ font_style_symbolic (font, prop, for_face)
   return (for_face ? AREF (elt, 1) : AREF (elt, (i & 0xF) + 1));
 }
 
-extern Lisp_Object Vface_alternative_font_family_alist;
-
-extern Lisp_Object find_font_encoding P_ ((Lisp_Object));
-
-
 /* Return ENCODING or a cons of ENCODING and REPERTORY of the font
    FONTNAME.  ENCODING is a charset symbol that specifies the encoding
    of the font.  REPERTORY is a charset symbol or nil.  */
 
 Lisp_Object
-find_font_encoding (fontname)
-     Lisp_Object fontname;
+find_font_encoding (Lisp_Object fontname)
 {
   Lisp_Object tail, elt;
 
@@ -448,9 +419,7 @@ find_font_encoding (fontname)
    REGISTRY is available, return 0.  Otherwise return -1.  */
 
 int
-font_registry_charsets (registry, encoding, repertory)
-     Lisp_Object registry;
-     struct charset **encoding, **repertory;
+font_registry_charsets (Lisp_Object registry, struct charset **encoding, struct charset **repertory)
 {
   Lisp_Object val;
   int encoding_id, repertory_id;
@@ -508,16 +477,15 @@ font_registry_charsets (registry, encoding, repertory)
 /* Font property value validaters.  See the comment of
    font_property_table for the meaning of the arguments.  */
 
-static Lisp_Object font_prop_validate P_ ((int, Lisp_Object, Lisp_Object));
-static Lisp_Object font_prop_validate_symbol P_ ((Lisp_Object, Lisp_Object));
-static Lisp_Object font_prop_validate_style P_ ((Lisp_Object, Lisp_Object));
-static Lisp_Object font_prop_validate_non_neg P_ ((Lisp_Object, Lisp_Object));
-static Lisp_Object font_prop_validate_spacing P_ ((Lisp_Object, Lisp_Object));
-static int get_font_prop_index P_ ((Lisp_Object));
+static Lisp_Object font_prop_validate (int, Lisp_Object, Lisp_Object);
+static Lisp_Object font_prop_validate_symbol (Lisp_Object, Lisp_Object);
+static Lisp_Object font_prop_validate_style (Lisp_Object, Lisp_Object);
+static Lisp_Object font_prop_validate_non_neg (Lisp_Object, Lisp_Object);
+static Lisp_Object font_prop_validate_spacing (Lisp_Object, Lisp_Object);
+static int get_font_prop_index (Lisp_Object);
 
 static Lisp_Object
-font_prop_validate_symbol (prop, val)
-     Lisp_Object prop, val;
+font_prop_validate_symbol (Lisp_Object prop, Lisp_Object val)
 {
   if (STRINGP (val))
     val = Fintern (val, Qnil);
@@ -530,8 +498,7 @@ font_prop_validate_symbol (prop, val)
 
 
 static Lisp_Object
-font_prop_validate_style (style, val)
-     Lisp_Object style, val;
+font_prop_validate_style (Lisp_Object style, Lisp_Object val)
 {
   enum font_property_index prop = (EQ (style, QCweight) ? FONT_WEIGHT_INDEX
                                   : EQ (style, QCslant) ? FONT_SLANT_INDEX
@@ -565,16 +532,14 @@ font_prop_validate_style (style, val)
 }
 
 static Lisp_Object
-font_prop_validate_non_neg (prop, val)
-     Lisp_Object prop, val;
+font_prop_validate_non_neg (Lisp_Object prop, Lisp_Object val)
 {
   return (NATNUMP (val) || (FLOATP (val) && XFLOAT_DATA (val) >= 0)
          ? val : Qerror);
 }
 
 static Lisp_Object
-font_prop_validate_spacing (prop, val)
-     Lisp_Object prop, val;
+font_prop_validate_spacing (Lisp_Object prop, Lisp_Object val)
 {
   if (NILP (val) || (NATNUMP (val) && XINT (val) <= FONT_SPACING_CHARCELL))
     return val;
@@ -595,8 +560,7 @@ font_prop_validate_spacing (prop, val)
 }
 
 static Lisp_Object
-font_prop_validate_otf (prop, val)
-     Lisp_Object prop, val;
+font_prop_validate_otf (Lisp_Object prop, Lisp_Object val)
 {
   Lisp_Object tail, tmp;
   int i;
@@ -631,14 +595,14 @@ font_prop_validate_otf (prop, val)
 
 /* Structure of known font property keys and validater of the
    values.  */
-struct
+static const struct
 {
   /* Pointer to the key symbol.  */
   Lisp_Object *key;
   /* Function to validate PROP's value VAL, or NULL if any value is
      ok.  The value is VAL or its regularized value if VAL is valid,
      and Qerror if not.  */
-  Lisp_Object (*validater) P_ ((Lisp_Object prop, Lisp_Object val));
+  Lisp_Object (*validater) (Lisp_Object prop, Lisp_Object val);
 } font_property_table[] =
   { { &QCtype, font_prop_validate_symbol },
     { &QCfoundry, font_prop_validate_symbol },
@@ -667,8 +631,7 @@ struct
    already known property.  */
 
 static int
-get_font_prop_index (key)
-     Lisp_Object key;
+get_font_prop_index (Lisp_Object key)
 {
   int i;
 
@@ -683,9 +646,7 @@ get_font_prop_index (key)
    signal an error.  The value is VAL or the regularized one.  */
 
 static Lisp_Object
-font_prop_validate (idx, prop, val)
-     int idx;
-     Lisp_Object prop, val;
+font_prop_validate (int idx, Lisp_Object prop, Lisp_Object val)
 {
   Lisp_Object validated;
 
@@ -710,8 +671,7 @@ font_prop_validate (idx, prop, val)
    keeping the sorting order.  Don't check the validity of VAL.  */
 
 Lisp_Object
-font_put_extra (font, prop, val)
-     Lisp_Object font, prop, val;
+font_put_extra (Lisp_Object font, Lisp_Object prop, Lisp_Object val)
 {
   Lisp_Object extra = AREF (font, FONT_EXTRA_INDEX);
   Lisp_Object slot = (NILP (extra) ? Qnil : assq_no_quit (prop, extra));
@@ -740,9 +700,9 @@ font_put_extra (font, prop, val)
 \f
 /* Font name parser and unparser */
 
-static int parse_matrix P_ ((char *));
-static int font_expand_wildcards P_ ((Lisp_Object *, int));
-static int font_parse_name P_ ((char *, Lisp_Object));
+static int parse_matrix (const char *);
+static int font_expand_wildcards (Lisp_Object *, int);
+static int font_parse_name (char *, Lisp_Object);
 
 /* An enumerator for each field of an XLFD font name.  */
 enum xlfd_field_index
@@ -799,8 +759,7 @@ enum xlfd_field_mask
    -1.  */
 
 static int
-parse_matrix (p)
-     char *p;
+parse_matrix (const char *p)
 {
   double matrix[4];
   char *end;
@@ -822,9 +781,7 @@ parse_matrix (p)
    field position by its contents.  */
 
 static int
-font_expand_wildcards (field, n)
-     Lisp_Object field[XLFD_LAST_INDEX];
-     int n;
+font_expand_wildcards (Lisp_Object *field, int n)
 {
   /* Copy of FIELD.  */
   Lisp_Object tmp[XLFD_LAST_INDEX];
@@ -1009,39 +966,6 @@ font_expand_wildcards (field, n)
 }
 
 
-#ifdef ENABLE_CHECKING
-/* Match a 14-field XLFD pattern against a full XLFD font name.  */
-static int
-font_match_xlfd (char *pattern, char *name)
-{
-  while (*pattern && *name)
-    {
-      if (*pattern == *name)
-       pattern++;
-      else if (*pattern == '*')
-       if (*name == pattern[1])
-         pattern += 2;
-       else
-         ;
-      else
-       return 0;
-      name++;
-    }
-  return 1;
-}
-
-/* Make sure the font object matches the XLFD font name.  */
-static int
-font_check_xlfd_parse (Lisp_Object font, char *name)
-{
-  char name_check[256];
-  font_unparse_xlfd (font, 0, name_check, 255);
-  return font_match_xlfd (name_check, name);
-}
-
-#endif
-
-
 /* Parse NAME (null terminated) as XLFD and store information in FONT
    (font-spec or font-entity).  Size property of FONT is set as
    follows:
@@ -1058,9 +982,7 @@ font_check_xlfd_parse (Lisp_Object font, char *name)
    a fully specified XLFD.  */
 
 int
-font_parse_xlfd (name, font)
-     char *name;
-     Lisp_Object font;
+font_parse_xlfd (char *name, Lisp_Object font)
 {
   int len = strlen (name);
   int i, j, n;
@@ -1242,11 +1164,7 @@ font_parse_xlfd (name, font)
    0, use PIXEL_SIZE instead.  */
 
 int
-font_unparse_xlfd (font, pixel_size, name, nbytes)
-     Lisp_Object font;
-     int pixel_size;
-     char *name;
-     int nbytes;
+font_unparse_xlfd (Lisp_Object font, int pixel_size, char *name, int nbytes)
 {
   char *f[XLFD_REGISTRY_INDEX + 1];
   Lisp_Object val;
@@ -1388,10 +1306,8 @@ font_unparse_xlfd (font, pixel_size, name, nbytes)
 
    This function tries to guess which format it is.  */
 
-int
-font_parse_fcname (name, font)
-     char *name;
-     Lisp_Object font;
+static int
+font_parse_fcname (char *name, Lisp_Object font)
 {
   char *p, *q;
   char *size_beg = NULL, *size_end = NULL;
@@ -1544,7 +1460,7 @@ font_parse_fcname (name, font)
              int size_found = 1;
 
              for (q = p + 1; *q && *q != ' '; q++)
-               if (! isdigit (*q))
+               if (! isdigit (*q) && *q != '.')
                  {
                    size_found = 0;
                    break;
@@ -1648,11 +1564,7 @@ font_parse_fcname (name, font)
    FONT_SIZE_INDEX of FONT is 0, use PIXEL_SIZE instead.  */
 
 int
-font_unparse_fcname (font, pixel_size, name, nbytes)
-     Lisp_Object font;
-     int pixel_size;
-     char *name;
-     int nbytes;
+font_unparse_fcname (Lisp_Object font, int pixel_size, char *name, int nbytes)
 {
   Lisp_Object family, foundry;
   Lisp_Object tail, val;
@@ -1660,7 +1572,7 @@ font_unparse_fcname (font, pixel_size, name, nbytes)
   int i, len = 1;
   char *p;
   Lisp_Object styles[3];
-  char *style_names[3] = { "weight", "slant", "width" };
+  const char *style_names[3] = { "weight", "slant", "width" };
   char work[256];
 
   family = AREF (font, FONT_FAMILY_INDEX);
@@ -1765,104 +1677,14 @@ font_unparse_fcname (font, pixel_size, name, nbytes)
   return (p - name);
 }
 
-/* Store GTK-style font name of FONT (font-spec or font-entity) in
-   NAME (NBYTES length), and return the name length.  F is the frame
-   on which the font is displayed; it is used to calculate the point
-   size.  */
-
-int
-font_unparse_gtkname (font, f, name, nbytes)
-     Lisp_Object font;
-     struct frame *f;
-     char *name;
-     int nbytes;
-{
-  char *p;
-  int len = 1;
-  Lisp_Object family, weight, slant, size;
-  int point_size = -1;
-
-  family = AREF (font, FONT_FAMILY_INDEX);
-  if (! NILP (family))
-    {
-      if (! SYMBOLP (family))
-       return -1;
-      family = SYMBOL_NAME (family);
-      len += SBYTES (family);
-    }
-
-  weight = font_style_symbolic (font, FONT_WEIGHT_INDEX, 0);
-  if (EQ (weight, Qnormal))
-    weight = Qnil;
-  else if (! NILP (weight))
-    {
-      weight = SYMBOL_NAME (weight);
-      len += SBYTES (weight);
-    }
-
-  slant = font_style_symbolic (font, FONT_SLANT_INDEX, 0);
-  if (EQ (slant, Qnormal))
-    slant = Qnil;
-  else if (! NILP (slant))
-    {
-      slant = SYMBOL_NAME (slant);
-      len += SBYTES (slant);
-    }
-
-  size = AREF (font, FONT_SIZE_INDEX);
-  /* Convert pixel size to point size.  */
-  if (INTEGERP (size))
-    {
-      Lisp_Object font_dpi = AREF (font, FONT_DPI_INDEX);
-      int dpi = 75;
-      if (INTEGERP (font_dpi))
-       dpi = XINT (font_dpi);
-      else if (f)
-       dpi = f->resy;
-      point_size = PIXEL_TO_POINT (XINT (size), dpi);
-      len += 11;
-    }
-  else if (FLOATP (size))
-    {
-      point_size = (int) XFLOAT_DATA (size);
-      len += 11;
-    }
-
-  if (len > nbytes)
-    return -1;
-
-  p = name + sprintf (name, "%s", SDATA (family));
-
-  if (! NILP (weight))
-    {
-      char *q = p;
-      p += sprintf (p, " %s", SDATA (weight));
-      q[1] = toupper (q[1]);
-    }
-
-  if (! NILP (slant))
-    {
-      char *q = p;
-      p += sprintf (p, " %s", SDATA (slant));
-      q[1] = toupper (q[1]);
-    }
-
-  if (point_size > 0)
-    p += sprintf (p, " %d", point_size);
-
-  return (p - name);
-}
-
 /* Parse NAME (null terminated) and store information in FONT
    (font-spec or font-entity).  If NAME is successfully parsed, return
    0.  Otherwise return -1.  */
 
 static int
-font_parse_name (name, font)
-     char *name;
-     Lisp_Object font;
+font_parse_name (char *name, Lisp_Object font)
 {
-  if (name[0] == '-' || index (name, '*') || index (name, '?'))
+  if (name[0] == '-' || strchr (name, '*') || strchr (name, '?'))
     return font_parse_xlfd (name, font);
   return font_parse_fcname (name, font);
 }
@@ -1873,8 +1695,7 @@ font_parse_name (name, font)
    part.  */
 
 void
-font_parse_family_registry (family, registry, font_spec)
-     Lisp_Object family, registry, font_spec;
+font_parse_family_registry (Lisp_Object family, Lisp_Object registry, Lisp_Object font_spec)
 {
   int len;
   char *p0, *p1;
@@ -1885,7 +1706,7 @@ font_parse_family_registry (family, registry, font_spec)
       CHECK_STRING (family);
       len = SBYTES (family);
       p0 = (char *) SDATA (family);
-      p1 = index (p0, '-');
+      p1 = strchr (p0, '-');
       if (p1)
        {
          if ((*p0 != '*' && p1 - p0 > 0)
@@ -1904,7 +1725,7 @@ font_parse_family_registry (family, registry, font_spec)
       CHECK_STRING (registry);
       len = SBYTES (registry);
       p0 = (char *) SDATA (registry);
-      p1 = index (p0, '-');
+      p1 = strchr (p0, '-');
       if (! p1)
        {
          if (SDATA (registry)[len - 1] == '*')
@@ -2220,17 +2041,13 @@ font_otf_Anchor (anchor)
 \f
 /* Font sorting */
 
-static unsigned font_score P_ ((Lisp_Object, Lisp_Object *));
-static int font_compare P_ ((const void *, const void *));
-static Lisp_Object font_sort_entities P_ ((Lisp_Object, Lisp_Object,
-                                         Lisp_Object, int));
-
-/* Return a rescaling ratio of FONT_ENTITY.  */
-extern Lisp_Object Vface_font_rescale_alist;
+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 (font_entity)
-     Lisp_Object font_entity;
+font_rescale_ratio (Lisp_Object font_entity)
 {
   Lisp_Object tail, elt;
   Lisp_Object name = Qnil;
@@ -2277,8 +2094,7 @@ static int sort_shift_bits[FONT_SIZE_INDEX + 1];
    SPEC_PROP.  */
 
 static unsigned
-font_score (entity, spec_prop)
-     Lisp_Object entity, *spec_prop;
+font_score (Lisp_Object entity, Lisp_Object *spec_prop)
 {
   unsigned score = 0;
   int i;
@@ -2352,8 +2168,7 @@ struct font_sort_data
 /* The comparison function for qsort.  */
 
 static int
-font_compare (d1, d2)
-     const void *d1, *d2;
+font_compare (const void *d1, const void *d2)
 {
   const struct font_sort_data *data1 = d1;
   const struct font_sort_data *data2 = d2;
@@ -2381,9 +2196,7 @@ font_compare (d1, d2)
    such a case.  */
 
 static Lisp_Object
-font_sort_entities (list, prefer, frame, best_only)
-     Lisp_Object list, prefer, frame;
-     int best_only;
+font_sort_entities (Lisp_Object list, Lisp_Object prefer, Lisp_Object frame, int best_only)
 {
   Lisp_Object prefer_prop[FONT_SPEC_MAX];
   int len, maxlen, i;
@@ -2488,8 +2301,7 @@ font_sort_entities (list, prefer, frame, best_only)
    function with font_sort_order after setting up it.  */
 
 void
-font_update_sort_order (order)
-     int *order;
+font_update_sort_order (int *order)
 {
   int i, shift_bits;
 
@@ -2509,8 +2321,7 @@ font_update_sort_order (order)
 }
 
 static int
-font_check_otf_features (script, langsys, features, table)
-     Lisp_Object script, langsys, features, table;
+font_check_otf_features (Lisp_Object script, Lisp_Object langsys, Lisp_Object features, Lisp_Object table)
 {
   Lisp_Object val;
   int negative;
@@ -2584,8 +2395,7 @@ font_check_otf (Lisp_Object spec, Lisp_Object otf_capability)
    specification SPEC.  */
 
 int
-font_match_p (spec, font)
-     Lisp_Object spec, font;
+font_match_p (Lisp_Object spec, Lisp_Object font)
 {
   Lisp_Object prop[FONT_SPEC_MAX], *props;
   Lisp_Object extra, font_extra;
@@ -2701,16 +2511,14 @@ font_match_p (spec, font)
    is a number frames sharing this cache, and FONT-CACHE-DATA is a
    cons (FONT-SPEC FONT-ENTITY ...).  */
 
-static void font_prepare_cache P_ ((FRAME_PTR, struct font_driver *));
-static void font_finish_cache P_ ((FRAME_PTR, struct font_driver *));
-static Lisp_Object font_get_cache P_ ((FRAME_PTR, struct font_driver *));
-static void font_clear_cache P_ ((FRAME_PTR, Lisp_Object,
-                                 struct font_driver *));
+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,
+                              struct font_driver *);
 
 static void
-font_prepare_cache (f, driver)
-     FRAME_PTR f;
-     struct font_driver *driver;
+font_prepare_cache (FRAME_PTR f, struct font_driver *driver)
 {
   Lisp_Object cache, val;
 
@@ -2732,9 +2540,7 @@ font_prepare_cache (f, driver)
 
 
 static void
-font_finish_cache (f, driver)
-     FRAME_PTR f;
-     struct font_driver *driver;
+font_finish_cache (FRAME_PTR f, struct font_driver *driver)
 {
   Lisp_Object cache, val, tmp;
 
@@ -2755,9 +2561,7 @@ font_finish_cache (f, driver)
 
 
 static Lisp_Object
-font_get_cache (f, driver)
-     FRAME_PTR f;
-     struct font_driver *driver;
+font_get_cache (FRAME_PTR f, struct font_driver *driver)
 {
   Lisp_Object val = driver->get_cache (f);
   Lisp_Object type = driver->type;
@@ -2773,10 +2577,7 @@ font_get_cache (f, driver)
 static int num_fonts;
 
 static void
-font_clear_cache (f, cache, driver)
-     FRAME_PTR f;
-     Lisp_Object cache;
-     struct font_driver *driver;
+font_clear_cache (FRAME_PTR f, Lisp_Object cache, struct font_driver *driver)
 {
   Lisp_Object tail, elt;
   Lisp_Object tail2, entity;
@@ -2827,12 +2628,8 @@ static Lisp_Object scratch_font_spec, scratch_font_prefer;
      (2) doesn't match with any regexps in Vface_ignored_fonts (if non-nil).
 */
 
-extern Lisp_Object Vface_ignored_fonts;
-
 Lisp_Object
-font_delete_unmatched (vec, spec, size)
-     Lisp_Object vec, spec;
-     int size;
+font_delete_unmatched (Lisp_Object vec, Lisp_Object spec, int size)
 {
   Lisp_Object entity, val;
   enum font_property_index prop;
@@ -2905,8 +2702,7 @@ font_delete_unmatched (vec, spec, size)
    same font-driver.  */
 
 Lisp_Object
-font_list_entities (frame, spec)
-     Lisp_Object frame, spec;
+font_list_entities (Lisp_Object frame, Lisp_Object spec)
 {
   FRAME_PTR f = XFRAME (frame);
   struct font_driver_list *driver_list = f->font_driver_list;
@@ -2982,9 +2778,7 @@ font_list_entities (frame, spec)
    font-related attributes.  */
 
 static Lisp_Object
-font_matching_entity (f, attrs, spec)
-     FRAME_PTR f;
-     Lisp_Object *attrs, spec;
+font_matching_entity (FRAME_PTR f, Lisp_Object *attrs, Lisp_Object spec)
 {
   struct font_driver_list *driver_list = f->font_driver_list;
   Lisp_Object ftype, size, entity;
@@ -3032,10 +2826,7 @@ font_matching_entity (f, attrs, spec)
    opened font object.  */
 
 static Lisp_Object
-font_open_entity (f, entity, pixel_size)
-     FRAME_PTR f;
-     Lisp_Object entity;
-     int pixel_size;
+font_open_entity (FRAME_PTR f, Lisp_Object entity, int pixel_size)
 {
   struct font_driver_list *driver_list;
   Lisp_Object objlist, size, val, font_object;
@@ -3078,7 +2869,6 @@ font_open_entity (f, entity, pixel_size)
     return Qnil;
   ASET (entity, FONT_OBJLIST_INDEX,
        Fcons (font_object, AREF (entity, FONT_OBJLIST_INDEX)));
-  ASET (font_object, FONT_OBJLIST_INDEX, Qnil);
   num_fonts++;
 
   font = XFONT_OBJECT (font_object);
@@ -3111,9 +2901,7 @@ font_open_entity (f, entity, pixel_size)
 /* Close FONT_OBJECT that is opened on frame F.  */
 
 void
-font_close_object (f, font_object)
-     FRAME_PTR f;
-     Lisp_Object font_object;
+font_close_object (FRAME_PTR f, Lisp_Object font_object)
 {
   struct font *font = XFONT_OBJECT (font_object);
 
@@ -3134,10 +2922,7 @@ font_close_object (f, font_object)
    FONT is a font-entity and it must be opened to check.  */
 
 int
-font_has_char (f, font, c)
-     FRAME_PTR f;
-     Lisp_Object font;
-     int c;
+font_has_char (FRAME_PTR f, Lisp_Object font, int c)
 {
   struct font *fontp;
 
@@ -3171,10 +2956,8 @@ font_has_char (f, font, c)
 
 /* Return the glyph ID of FONT_OBJECT for character C.  */
 
-unsigned
-font_encode_char (font_object, c)
-     Lisp_Object font_object;
-     int c;
+static unsigned
+font_encode_char (Lisp_Object font_object, int c)
 {
   struct font *font;
 
@@ -3187,8 +2970,7 @@ font_encode_char (font_object, c)
 /* Return the name of FONT_OBJECT.  */
 
 Lisp_Object
-font_get_name (font_object)
-     Lisp_Object font_object;
+font_get_name (Lisp_Object font_object)
 {
   font_assert (FONT_OBJECT_P (font_object));
   return AREF (font_object, FONT_NAME_INDEX);
@@ -3198,8 +2980,7 @@ font_get_name (font_object)
 /* Return the specification of FONT_OBJECT.  */
 
 Lisp_Object
-font_get_spec (font_object)
-     Lisp_Object font_object;
+font_get_spec (Lisp_Object font_object)
 {
   Lisp_Object spec = font_make_spec ();
   int i;
@@ -3216,8 +2997,7 @@ font_get_spec (font_object)
    could not be parsed by font_parse_name, return Qnil.  */
 
 Lisp_Object
-font_spec_from_name (font_name)
-     Lisp_Object font_name;
+font_spec_from_name (Lisp_Object font_name)
 {
   Lisp_Object spec = Ffont_spec (0, NULL);
 
@@ -3231,9 +3011,7 @@ font_spec_from_name (font_name)
 
 
 void
-font_clear_prop (attrs, prop)
-     Lisp_Object *attrs;
-     enum font_property_index prop;
+font_clear_prop (Lisp_Object *attrs, enum font_property_index prop)
 {
   Lisp_Object font = attrs[LFACE_FONT_INDEX];
 
@@ -3283,59 +3061,11 @@ font_clear_prop (attrs, prop)
   attrs[LFACE_FONT_INDEX] = font;
 }
 
-void
-font_update_lface (f, attrs)
-     FRAME_PTR f;
-     Lisp_Object *attrs;
-{
-  Lisp_Object spec;
-
-  spec = attrs[LFACE_FONT_INDEX];
-  if (! FONT_SPEC_P (spec))
-    return;
-
-  if (! NILP (AREF (spec, FONT_FOUNDRY_INDEX)))
-    attrs[LFACE_FOUNDRY_INDEX] = SYMBOL_NAME (AREF (spec, FONT_FOUNDRY_INDEX));
-  if (! NILP (AREF (spec, FONT_FAMILY_INDEX)))
-    attrs[LFACE_FAMILY_INDEX] = SYMBOL_NAME (AREF (spec, FONT_FAMILY_INDEX));
-  if (! NILP (AREF (spec, FONT_WEIGHT_INDEX)))
-    attrs[LFACE_WEIGHT_INDEX] = FONT_WEIGHT_FOR_FACE (spec);
-  if (! NILP (AREF (spec, FONT_SLANT_INDEX)))
-    attrs[LFACE_SLANT_INDEX] = FONT_SLANT_FOR_FACE (spec);
-  if (! NILP (AREF (spec, FONT_WIDTH_INDEX)))
-    attrs[LFACE_SWIDTH_INDEX] = FONT_WIDTH_FOR_FACE (spec);
-  if (! NILP (AREF (spec, FONT_SIZE_INDEX)))
-    {
-      int point;
-
-      if (INTEGERP (AREF (spec, FONT_SIZE_INDEX)))
-       {
-         Lisp_Object val;
-         int dpi = f->resy;
-
-         val = Ffont_get (spec, QCdpi);
-         if (! NILP (val))
-           dpi = XINT (val);
-         point = PIXEL_TO_POINT (XINT (AREF (spec, FONT_SIZE_INDEX)) * 10,
-                                 dpi);
-         attrs[LFACE_HEIGHT_INDEX] = make_number (point);
-       }
-      else if (FLOATP (AREF (spec, FONT_SIZE_INDEX)))
-       {
-         point = XFLOAT_DATA (AREF (spec, FONT_SIZE_INDEX)) * 10;
-         attrs[LFACE_HEIGHT_INDEX] = make_number (point);
-       }
-    }
-}
-
-
 /* Selecte a font from ENTITIES (list of font-entity vectors) that
    supports C and matches best with ATTRS and PIXEL_SIZE.  */
 
 static Lisp_Object
-font_select_entity (frame, entities, attrs, pixel_size, c)
-     Lisp_Object frame, entities, *attrs;
-     int pixel_size, c;
+font_select_entity (Lisp_Object frame, Lisp_Object entities, Lisp_Object *attrs, int pixel_size, int c)
 {
   Lisp_Object font_entity;
   Lisp_Object prefer;
@@ -3380,11 +3110,7 @@ font_select_entity (frame, entities, attrs, pixel_size, c)
    character that the entity must support.  */
 
 Lisp_Object
-font_find_for_lface (f, attrs, spec, c)
-     FRAME_PTR f;
-     Lisp_Object *attrs;
-     Lisp_Object spec;
-     int c;
+font_find_for_lface (FRAME_PTR f, Lisp_Object *attrs, Lisp_Object spec, int c)
 {
   Lisp_Object work;
   Lisp_Object frame, entities, val;
@@ -3534,11 +3260,7 @@ font_find_for_lface (f, attrs, spec, c)
 
 
 Lisp_Object
-font_open_for_lface (f, entity, attrs, spec)
-     FRAME_PTR f;
-     Lisp_Object entity;
-     Lisp_Object *attrs;
-     Lisp_Object spec;
+font_open_for_lface (FRAME_PTR f, Lisp_Object entity, Lisp_Object *attrs, Lisp_Object spec)
 {
   int size;
 
@@ -3581,9 +3303,7 @@ font_open_for_lface (f, entity, attrs, spec)
    font-object.  */
 
 Lisp_Object
-font_load_for_lface (f, attrs, spec)
-     FRAME_PTR f;
-     Lisp_Object *attrs, spec;
+font_load_for_lface (FRAME_PTR f, Lisp_Object *attrs, Lisp_Object spec)
 {
   Lisp_Object entity, name;
 
@@ -3597,7 +3317,7 @@ font_load_for_lface (f, attrs, spec)
       if (NILP (entity))
        return Qnil;
     }
-  /* Don't loose the original name that was put in initially.  We need
+  /* Don't lose the original name that was put in initially.  We need
      it to re-apply the font when font parameters (like hinting or dpi) have
      changed.  */
   entity = font_open_for_lface (f, entity, attrs, spec);
@@ -3613,9 +3333,7 @@ font_load_for_lface (f, attrs, spec)
 /* Make FACE on frame F ready to use the font opened for FACE.  */
 
 void
-font_prepare_for_face (f, face)
-     FRAME_PTR f;
-     struct face *face;
+font_prepare_for_face (FRAME_PTR f, struct face *face)
 {
   if (face->font->driver->prepare_face)
     face->font->driver->prepare_face (f, face);
@@ -3625,9 +3343,7 @@ font_prepare_for_face (f, face)
 /* Make FACE on frame F stop using the font opened for FACE.  */
 
 void
-font_done_for_face (f, face)
-     FRAME_PTR f;
-     struct face *face;
+font_done_for_face (FRAME_PTR f, struct face *face)
 {
   if (face->font->driver->done_face)
     face->font->driver->done_face (f, face);
@@ -3639,9 +3355,7 @@ font_done_for_face (f, face)
    font is found, return Qnil.  */
 
 Lisp_Object
-font_open_by_spec (f, spec)
-     FRAME_PTR f;
-     Lisp_Object spec;
+font_open_by_spec (FRAME_PTR f, Lisp_Object spec)
 {
   Lisp_Object attrs[LFACE_VECTOR_SIZE];
 
@@ -3665,9 +3379,7 @@ font_open_by_spec (f, spec)
    found, return Qnil.  */
 
 Lisp_Object
-font_open_by_name (f, name)
-     FRAME_PTR f;
-     char *name;
+font_open_by_name (FRAME_PTR f, const char *name)
 {
   Lisp_Object args[2];
   Lisp_Object spec, ret;
@@ -3676,7 +3388,7 @@ font_open_by_name (f, name)
   args[1] = make_unibyte_string (name, strlen (name));
   spec = Ffont_spec (2, args);
   ret = font_open_by_spec (f, spec);
-  /* Do not loose name originally put in.  */
+  /* Do not lose name originally put in.  */
   if (!NILP (ret))
     font_put_extra (ret, QCuser_spec, args[1]);
 
@@ -3697,9 +3409,7 @@ font_open_by_name (f, name)
    (e.g. syms_of_xfont).  */
 
 void
-register_font_driver (driver, f)
-     struct font_driver *driver;
-     FRAME_PTR f;
+register_font_driver (struct font_driver *driver, FRAME_PTR f)
 {
   struct font_driver_list *root = f ? f->font_driver_list : font_driver_list;
   struct font_driver_list *prev, *list;
@@ -3727,8 +3437,7 @@ register_font_driver (driver, f)
 }
 
 void
-free_font_driver_list (f)
-     FRAME_PTR f;
+free_font_driver_list (FRAME_PTR f)
 {
   struct font_driver_list *list, *next;
 
@@ -3750,9 +3459,7 @@ free_font_driver_list (f)
    F.  */
 
 Lisp_Object
-font_update_drivers (f, new_drivers)
-     FRAME_PTR f;
-     Lisp_Object new_drivers;
+font_update_drivers (FRAME_PTR f, Lisp_Object new_drivers)
 {
   Lisp_Object active_drivers = Qnil;
   struct font_driver *driver;
@@ -3843,10 +3550,7 @@ font_update_drivers (f, new_drivers)
 }
 
 int
-font_put_frame_data (f, driver, data)
-     FRAME_PTR f;
-     struct font_driver *driver;
-     void *data;
+font_put_frame_data (FRAME_PTR f, struct font_driver *driver, void *data)
 {
   struct font_data_list *list, *prev;
 
@@ -3880,9 +3584,7 @@ font_put_frame_data (f, driver, data)
 
 
 void *
-font_get_frame_data (f, driver)
-     FRAME_PTR f;
-     struct font_driver *driver;
+font_get_frame_data (FRAME_PTR f, struct font_driver *driver)
 {
   struct font_data_list *list;
 
@@ -3901,11 +3603,10 @@ font_get_frame_data (f, driver)
    arrays of strings.  This function is intended for use by the font
    drivers to implement their specific font_filter_properties.  */
 void
-font_filter_properties (font, alist, boolean_properties, non_boolean_properties)
-     Lisp_Object font;
-     Lisp_Object alist;
-     const char *boolean_properties[];
-     const char *non_boolean_properties[];
+font_filter_properties (Lisp_Object font,
+                       Lisp_Object alist,
+                       const char *const boolean_properties[],
+                       const char *const non_boolean_properties[])
 {
   Lisp_Object it;
   int i;
@@ -3953,13 +3654,9 @@ font_filter_properties (font, alist, boolean_properties, non_boolean_properties)
    at index POS.  If C is negative, get C from the current buffer or
    STRING.  */
 
-Lisp_Object
-font_at (c, pos, face, w, string)
-     int c;
-     EMACS_INT pos;
-     struct face *face;
-     struct window *w;
-     Lisp_Object string;
+static Lisp_Object
+font_at (int c, EMACS_INT pos, struct face *face, struct window *w,
+        Lisp_Object string)
 {
   FRAME_PTR f;
   int multibyte;
@@ -4041,13 +3738,9 @@ font_at (c, pos, face, w, string)
    It is assured that the current buffer (or STRING) is multibyte.  */
 
 Lisp_Object
-font_range (pos, limit, w, face, string)
-     EMACS_INT pos, *limit;
-     struct window *w;
-     struct face *face;
-     Lisp_Object string;
+font_range (EMACS_INT pos, EMACS_INT *limit, struct window *w, struct face *face, Lisp_Object string)
 {
-  EMACS_INT pos_byte, ignore, start, start_byte;
+  EMACS_INT pos_byte, ignore;
   int c;
   Lisp_Object font_object = Qnil;
 
@@ -4069,7 +3762,6 @@ font_range (pos, limit, w, face, string)
       pos_byte = string_char_to_byte (string, pos);
     }
 
-  start = pos, start_byte = pos_byte;
   while (pos < *limit)
     {
       Lisp_Object category;
@@ -4078,6 +3770,10 @@ font_range (pos, limit, w, face, string)
        FETCH_CHAR_ADVANCE_NO_CHECK (c, pos, pos_byte);
       else
        FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c, string, pos, pos_byte);
+      category = CHAR_TABLE_REF (Vunicode_category_table, c);
+      if (EQ (category, QCf)
+         || CHAR_VARIATION_SELECTOR_P (c))
+       continue;
       if (NILP (font_object))
        {
          font_object = font_for_char (face, c, pos - 1, string);
@@ -4085,40 +3781,8 @@ font_range (pos, limit, w, face, string)
            return Qnil;
          continue;
        }
-
-      category = CHAR_TABLE_REF (Vunicode_category_table, c);
-      if (! EQ (category, QCf)
-         && ! CHAR_VARIATION_SELECTOR_P (c)
-         && font_encode_char (font_object, c) == FONT_INVALID_CODE)
-       {
-         Lisp_Object f = font_for_char (face, c, pos - 1, string);
-         EMACS_INT i, i_byte;
-
-
-         if (NILP (f))
-           {
-             *limit = pos - 1;
-             return font_object;
-           }
-         i = start, i_byte = start_byte;
-         while (i < pos - 1)
-           {
-
-             if (NILP (string))
-               FETCH_CHAR_ADVANCE_NO_CHECK (c, i, i_byte);
-             else
-               FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c, string, i, i_byte);
-             category = CHAR_TABLE_REF (Vunicode_category_table, c);
-             if (! EQ (category, QCf)
-                 && ! CHAR_VARIATION_SELECTOR_P (c)
-                 && font_encode_char (f, c) == FONT_INVALID_CODE)
-               {
-                 *limit = pos - 1;
-                 return font_object;
-               }
-           }
-         font_object = f;
-       }
+      if (font_encode_char (font_object, c) == FONT_INVALID_CODE)
+       *limit = pos - 1;
     }
   return font_object;
 }
@@ -4133,8 +3797,7 @@ Return nil otherwise.
 Optional 2nd argument EXTRA-TYPE, if non-nil, specifies to check
 which kind of font it is.  It must be one of `font-spec', `font-entity',
 `font-object'.  */)
-     (object, extra_type)
-     Lisp_Object object, extra_type;
+  (Lisp_Object object, Lisp_Object extra_type)
 {
   if (NILP (extra_type))
     return (FONTP (object) ? Qt : Qnil);
@@ -4212,9 +3875,7 @@ be an OpenType font, and whose GPOS table of `thai' script's default
 language system must contain `mark' feature.
 
 usage: (font-spec ARGS...)  */)
-     (nargs, args)
-     int nargs;
-     Lisp_Object *args;
+  (int nargs, Lisp_Object *args)
 {
   Lisp_Object spec = font_make_spec ();
   int i;
@@ -4255,8 +3916,7 @@ usage: (font-spec ARGS...)  */)
 
 DEFUN ("copy-font-spec", Fcopy_font_spec, Scopy_font_spec, 1, 1, 0,
        doc: /* Return a copy of FONT as a font-spec.  */)
-     (font)
-     Lisp_Object font;
+  (Lisp_Object font)
 {
   Lisp_Object new_spec, tail, prev, extra;
   int i;
@@ -4284,8 +3944,7 @@ DEFUN ("merge-font-spec", Fmerge_font_spec, Smerge_font_spec, 2, 2, 0,
        doc: /* Merge font-specs FROM and TO, and return a new font-spec.
 Every specified properties in FROM override the corresponding
 properties in TO.  */)
-     (from, to)
-     Lisp_Object from, to;
+  (Lisp_Object from, Lisp_Object to)
 {
   Lisp_Object extra, tail;
   int i;
@@ -4313,16 +3972,24 @@ properties in TO.  */)
 DEFUN ("font-get", Ffont_get, Sfont_get, 2, 2, 0,
        doc: /* Return the value of FONT's property KEY.
 FONT is a font-spec, a font-entity, or a font-object.
-KEY must be one of these symbols:
+KEY is any symbol, but these are reserved for specific meanings:
   :family, :weight, :slant, :width, :foundry, :adstyle, :registry,
-  :size, :name, :script
+  :size, :name, :script, :otf
 See the documentation of `font-spec' for their meanings.
-If FONT is a font-entity or font-object, the value of :script may be
-a list of scripts that are supported by the font.  */)
-     (font, key)
-     Lisp_Object font, key;
+In addition, if FONT is a font-entity or a font-object, values of
+:script and :otf are different from those of a font-spec as below:
+
+The value of :script may be a list of scripts that are supported by the font.
+
+The value of :otf is a cons (GSUB . GPOS) where GSUB and GPOS are lists
+representing the OpenType features supported by the font by this form:
+  ((SCRIPT (LANGSYS FEATURE ...) ...) ...)
+SCRIPT, LANGSYS, and FEATURE are all symbols representing OpenType
+Layout tags.  */)
+  (Lisp_Object font, Lisp_Object key)
 {
   int idx;
+  Lisp_Object val;
 
   CHECK_FONT (font);
   CHECK_SYMBOL (key);
@@ -4332,7 +3999,20 @@ a list of scripts that are supported by the font.  */)
     return font_style_symbolic (font, idx, 0);
   if (idx >= 0 && idx < FONT_EXTRA_INDEX)
     return AREF (font, idx);
-  return Fcdr (Fassq (key, AREF (font, FONT_EXTRA_INDEX)));
+  val = Fassq (key, AREF (font, FONT_EXTRA_INDEX));
+  if (NILP (val) && EQ (key, QCotf) && FONT_OBJECT_P (font))
+    {
+      struct font *fontp = XFONT_OBJECT (font);
+
+      if (fontp->driver->otf_capability)
+       val = fontp->driver->otf_capability (fontp);
+      else
+       val = Fcons (Qnil, Qnil);
+      font_put_extra (font, QCotf, val);
+    }
+  else
+    val = Fcdr (val);
+  return val;
 }
 
 #ifdef HAVE_WINDOW_SYSTEM
@@ -4350,8 +4030,7 @@ may be omitted from the list if they are not specified by FONT.
 
 The optional argument FRAME specifies the frame that the face attributes
 are to be displayed on.  If omitted, the selected frame is used.  */)
-     (font, frame)
-     Lisp_Object font, frame;
+  (Lisp_Object font, Lisp_Object frame)
 {
   struct frame *f;
   Lisp_Object plist[10];
@@ -4424,18 +4103,36 @@ are to be displayed on.  If omitted, the selected frame is used.  */)
 #endif
 
 DEFUN ("font-put", Ffont_put, Sfont_put, 3, 3, 0,
-       doc: /* Set one property of FONT-SPEC: give property PROP value VAL.  */)
-     (font_spec, prop, val)
-     Lisp_Object font_spec, prop, val;
+       doc: /* Set one property of FONT: give property KEY value VAL.
+FONT is a font-spec, a font-entity, or a font-object.
+
+If FONT is a font-spec, KEY can be any symbol.  But if KEY is the one
+accepted by the function `font-spec' (which see), VAL must be what
+allowed in `font-spec'.
+
+If FONT is a font-entity or a font-object, KEY must not be the one
+accepted by `font-spec'.  */)
+  (Lisp_Object font, Lisp_Object prop, Lisp_Object val)
 {
   int idx;
 
-  CHECK_FONT_SPEC (font_spec);
   idx = get_font_prop_index (prop);
   if (idx >= 0 && idx < FONT_EXTRA_INDEX)
-    ASET (font_spec, idx, font_prop_validate (idx, Qnil, val));
+    {
+      CHECK_FONT_SPEC (font);
+      ASET (font, idx, font_prop_validate (idx, Qnil, val));
+    }
   else
-    font_put_extra (font_spec, prop, font_prop_validate (0, prop, val));
+    {
+      if (EQ (prop, QCname)
+         || EQ (prop, QCscript)
+         || EQ (prop, QClang)
+         || EQ (prop, QCotf))
+       CHECK_FONT_SPEC (font);
+      else
+       CHECK_FONT (font);
+      font_put_extra (font, prop, font_prop_validate (0, prop, val));
+    }
   return val;
 }
 
@@ -4446,8 +4143,7 @@ Optional 3rd argument NUM, if non-nil, limits the number of returned fonts.
 Optional 4th argument PREFER, if non-nil, is a font-spec to
 control the order of the returned list.  Fonts are sorted by
 how close they are to PREFER.  */)
-     (font_spec, frame, num, prefer)
-     Lisp_Object font_spec, frame, num, prefer;
+  (Lisp_Object font_spec, Lisp_Object frame, Lisp_Object num, Lisp_Object prefer)
 {
   Lisp_Object vec, list;
   int n = 0;
@@ -4496,8 +4192,7 @@ how close they are to PREFER.  */)
 DEFUN ("font-family-list", Ffont_family_list, Sfont_family_list, 0, 1, 0,
        doc: /* List available font families on the current frame.
 Optional argument FRAME, if non-nil, specifies the target frame.  */)
-     (frame)
-     Lisp_Object frame;
+  (Lisp_Object frame)
 {
   FRAME_PTR f;
   struct font_driver_list *driver_list;
@@ -4526,8 +4221,7 @@ Optional argument FRAME, if non-nil, specifies the target frame.  */)
 DEFUN ("find-font", Ffind_font, Sfind_font, 1, 2, 0,
        doc: /* Return a font-entity matching with FONT-SPEC on the current frame.
 Optional 2nd argument FRAME, if non-nil, specifies the target frame.  */)
-     (font_spec, frame)
-     Lisp_Object font_spec, frame;
+  (Lisp_Object font_spec, Lisp_Object frame)
 {
   Lisp_Object val = Flist_fonts (font_spec, frame, make_number (1), Qnil);
 
@@ -4542,8 +4236,7 @@ FONT is a font-spec, font-entity, or font-object.
 If the name is too long for XLFD (maximum 255 chars), return nil.
 If the 2nd optional arg FOLD-WILDCARDS is non-nil,
 the consecutive wildcards are folded to one.  */)
-     (font, fold_wildcards)
-     Lisp_Object font, fold_wildcards;
+  (Lisp_Object font, Lisp_Object fold_wildcards)
 {
   char name[256];
   int pixel_size = 0;
@@ -4583,7 +4276,7 @@ the consecutive wildcards are folded to one.  */)
 
 DEFUN ("clear-font-cache", Fclear_font_cache, Sclear_font_cache, 0, 0, 0,
        doc: /* Clear font cache.  */)
-     ()
+  (void)
 {
   Lisp_Object list, frame;
 
@@ -4617,8 +4310,7 @@ DEFUN ("clear-font-cache", Fclear_font_cache, Sclear_font_cache, 0, 0, 0,
 
 \f
 void
-font_fill_lglyph_metrics (glyph, font_object)
-     Lisp_Object glyph, font_object;
+font_fill_lglyph_metrics (Lisp_Object glyph, Lisp_Object font_object)
 {
   struct font *font = XFONT_OBJECT (font_object);
   unsigned code;
@@ -4645,8 +4337,7 @@ header of the glyph-string.
 
 If the shaping was successful, the value is GSTRING itself or a newly
 created glyph-string.  Otherwise, the value is nil.  */)
-     (gstring)
-     Lisp_Object gstring;
+  (Lisp_Object gstring)
 {
   struct font *font;
   Lisp_Object font_object, n, glyph;
@@ -4674,6 +4365,8 @@ created glyph-string.  Otherwise, the value is nil.  */)
     }
   if (i == 3 || XINT (n) == 0)
     return Qnil;
+  if (XINT (n) < LGSTRING_GLYPH_LEN (gstring))
+    LGSTRING_SET_GLYPH (gstring, XINT (n), Qnil);
 
   glyph = LGSTRING_GLYPH (gstring, 0);
   from = LGLYPH_FROM (glyph);
@@ -4723,8 +4416,7 @@ where
   VARIATION-SELECTOR is a character code of variation selection
     (#xFE00..#xFE0F or #xE0100..#xE01EF)
   GLYPH-ID is a glyph code of the corresponding variation glyph.  */)
-     (font_object, character)
-     Lisp_Object font_object, character;
+  (Lisp_Object font_object, Lisp_Object character)
 {
   unsigned variations[256];
   struct font *font;
@@ -4792,8 +4484,7 @@ produced in GSTRING-OUT, and the value is nil.
 
 See the documentation of `font-make-gstring' for the format of
 glyph-string.  */)
-     (otf_features, gstring_in, from, to, gstring_out, index)
-     Lisp_Object otf_features, gstring_in, from, to, gstring_out, index;
+  (Lisp_Object otf_features, Lisp_Object gstring_in, Lisp_Object from, Lisp_Object to, Lisp_Object gstring_out, Lisp_Object index)
 {
   Lisp_Object font_object = LGSTRING_FONT (gstring_in);
   Lisp_Object val;
@@ -4843,8 +4534,7 @@ The value is a list of cons cells of the format (GLYPH-ID . CHARACTER),
 where GLYPH-ID is a glyph index of the font, and CHARACTER is a
 character code corresponding to the glyph or nil if there's no
 corresponding character.  */)
-     (font_object, character, otf_features)
-     Lisp_Object font_object, character, otf_features;
+  (Lisp_Object font_object, Lisp_Object character, Lisp_Object otf_features)
 {
   struct font *font;
   Lisp_Object gstring_in, gstring_out, g;
@@ -4885,10 +4575,7 @@ corresponding character.  */)
 
 DEFUN ("open-font", Fopen_font, Sopen_font, 1, 3, 0,
        doc: /* Open FONT-ENTITY.  */)
-     (font_entity, size, frame)
-     Lisp_Object font_entity;
-     Lisp_Object size;
-     Lisp_Object frame;
+  (Lisp_Object font_entity, Lisp_Object size, Lisp_Object frame)
 {
   int isize;
 
@@ -4914,8 +4601,7 @@ DEFUN ("open-font", Fopen_font, Sopen_font, 1, 3, 0,
 
 DEFUN ("close-font", Fclose_font, Sclose_font, 1, 2, 0,
        doc: /* Close FONT-OBJECT.  */)
-     (font_object, frame)
-     Lisp_Object font_object, frame;
+  (Lisp_Object font_object, Lisp_Object frame)
 {
   CHECK_FONT_OBJECT (font_object);
   if (NILP (frame))
@@ -4966,8 +4652,7 @@ representing the default langsys.
 FEATURE is a symbol representing OpenType feature tag.
 
 If the font is not OpenType font, CAPABILITY is nil.  */)
-     (font_object)
-     Lisp_Object font_object;
+  (Lisp_Object font_object)
 {
   struct font *font;
   Lisp_Object val;
@@ -4988,25 +4673,99 @@ If the font is not OpenType font, CAPABILITY is nil.  */)
   return val;
 }
 
-DEFUN ("get-font-glyphs", Fget_font_glyphs, Sget_font_glyphs, 2, 2, 0,
-       doc: /* Return a vector of glyphs of FONT-OBJECT for drawing STRING.
-Each element is a vector [GLYPH-CODE LBEARING RBEARING WIDTH ASCENT DESCENT].  */)
-     (font_object, string)
-     Lisp_Object font_object, string;
+DEFUN ("font-get-glyphs", Ffont_get_glyphs, Sfont_get_glyphs, 3, 4, 0,
+       doc:
+       /* Return a vector of FONT-OBJECT's glyphs for the specified characters.
+FROM and TO are positions (integers or markers) specifying a region
+of the current buffer.
+If the optional fourth arg OBJECT is not nil, it is a string or a
+vector containing the target characters.
+
+Each element is a vector containing information of a glyph in this format:
+  [FROM-IDX TO-IDX C CODE WIDTH LBEARING RBEARING ASCENT DESCENT ADJUSTMENT]
+where
+  FROM is an index numbers of a character the glyph corresponds to.
+  TO is the same as FROM.
+  C is the character of the glyph.
+  CODE is the glyph-code of C in FONT-OBJECT.
+  WIDTH thru DESCENT are the metrics (in pixels) of the glyph.
+  ADJUSTMENT is always nil.
+If FONT-OBJECT doesn't have a glyph for a character,
+the corresponding element is nil.  */)
+  (Lisp_Object font_object, Lisp_Object from, Lisp_Object to,
+   Lisp_Object object)
 {
   struct font *font;
-  int i, len;
-  Lisp_Object vec;
+  int i, len, c;
+  Lisp_Object *chars, vec;
+  USE_SAFE_ALLOCA;
 
   CHECK_FONT_GET_OBJECT (font_object, font);
-  CHECK_STRING (string);
-  len = SCHARS (string);
+  if (NILP (object))
+    {
+      EMACS_INT charpos, bytepos;
+
+      validate_region (&from, &to);
+      if (EQ (from, to))
+       return Qnil;
+      len = XFASTINT (to) - XFASTINT (from);
+      SAFE_ALLOCA_LISP (chars, len);
+      charpos = XFASTINT (from);
+      bytepos = CHAR_TO_BYTE (charpos);
+      for (i = 0; charpos < XFASTINT (to); i++)
+       {
+         FETCH_CHAR_ADVANCE (c, charpos, bytepos);
+         chars[i] = make_number (c);
+       }
+    }
+  else if (STRINGP (object))
+    {
+      const unsigned char *p;
+
+      CHECK_NUMBER (from);
+      CHECK_NUMBER (to);
+      if (XINT (from) < 0 || XINT (from) > XINT (to)
+         || XINT (to) > SCHARS (object))
+       args_out_of_range_3 (object, from, to);
+      if (EQ (from, to))
+       return Qnil;
+      len = XFASTINT (to) - XFASTINT (from);
+      SAFE_ALLOCA_LISP (chars, len);
+      p = SDATA (object);
+      if (STRING_MULTIBYTE (object))
+       for (i = 0; i < len; i++)
+         {
+           c = STRING_CHAR_ADVANCE (p);
+           chars[i] = make_number (c);
+         }
+      else
+       for (i = 0; i < len; i++)
+         chars[i] = make_number (p[i]);
+    }
+  else
+    {
+      CHECK_VECTOR (object);
+      CHECK_NUMBER (from);
+      CHECK_NUMBER (to);
+      if (XINT (from) < 0 || XINT (from) > XINT (to)
+         || XINT (to) > ASIZE (object))
+       args_out_of_range_3 (object, from, to);
+      if (EQ (from, to))
+       return Qnil;
+      len = XFASTINT (to) - XFASTINT (from);
+      for (i = 0; i < len; i++)
+       {
+         Lisp_Object elt = AREF (object, XFASTINT (from) + i);
+         CHECK_CHARACTER (elt);
+       }
+      chars = &(AREF (object, XFASTINT (from)));
+    }
+
   vec = Fmake_vector (make_number (len), Qnil);
   for (i = 0; i < len; i++)
     {
-      Lisp_Object ch = Faref (string, make_number (i));
-      Lisp_Object val;
-      int c = XINT (ch);
+      Lisp_Object g;
+      int c = XFASTINT (chars[i]);
       unsigned code;
       EMACS_INT cod;
       struct font_metrics metrics;
@@ -5014,28 +4773,28 @@ Each element is a vector [GLYPH-CODE LBEARING RBEARING WIDTH ASCENT DESCENT].  *
       cod = code = font->driver->encode_char (font, c);
       if (code == FONT_INVALID_CODE)
        continue;
-      val = Fmake_vector (make_number (6), Qnil);
-      if (cod <= MOST_POSITIVE_FIXNUM)
-       ASET (val, 0, make_number (code));
-      else
-       ASET (val, 0, Fcons (make_number (code >> 16),
-                            make_number (code & 0xFFFF)));
+      g = Fmake_vector (make_number (LGLYPH_SIZE), Qnil);
+      LGLYPH_SET_FROM (g, i);
+      LGLYPH_SET_TO (g, i);
+      LGLYPH_SET_CHAR (g, c);
+      LGLYPH_SET_CODE (g, code);
       font->driver->text_extents (font, &code, 1, &metrics);
-      ASET (val, 1, make_number (metrics.lbearing));
-      ASET (val, 2, make_number (metrics.rbearing));
-      ASET (val, 3, make_number (metrics.width));
-      ASET (val, 4, make_number (metrics.ascent));
-      ASET (val, 5, make_number (metrics.descent));
-      ASET (vec, i, val);
-    }
+      LGLYPH_SET_WIDTH (g, metrics.width);
+      LGLYPH_SET_LBEARING (g, metrics.lbearing);
+      LGLYPH_SET_RBEARING (g, metrics.rbearing);
+      LGLYPH_SET_ASCENT (g, metrics.ascent);
+      LGLYPH_SET_DESCENT (g, metrics.descent);
+      ASET (vec, i, g);
+    }
+  if (! VECTORP (object))
+    SAFE_FREE ();
   return vec;
 }
 
 DEFUN ("font-match-p", Ffont_match_p, Sfont_match_p, 2, 2, 0,
        doc: /* Return t if and only if font-spec SPEC matches with FONT.
 FONT is a font-spec, font-entity, or font-object. */)
-     (spec, font)
-     Lisp_Object spec, font;
+  (Lisp_Object spec, Lisp_Object font)
 {
   CHECK_FONT_SPEC (spec);
   CHECK_FONT (font);
@@ -5047,8 +4806,7 @@ DEFUN ("font-at", Ffont_at, Sfont_at, 1, 3, 0,
        doc: /* Return a font-object for displaying a character at POSITION.
 Optional second arg WINDOW, if non-nil, is a window displaying
 the current buffer.  It defaults to the currently selected window.  */)
-     (position, window, string)
-     Lisp_Object position, window, string;
+  (Lisp_Object position, Lisp_Object window, Lisp_Object string)
 {
   struct window *w;
   EMACS_INT pos;
@@ -5081,8 +4839,7 @@ DEFUN ("draw-string", Fdraw_string, Sdraw_string, 2, 2, 0,
        doc: /*  Draw STRING by FONT-OBJECT on the top left corner of the current frame.
 The value is a number of glyphs drawn.
 Type C-l to recover what previously shown.  */)
-     (font_object, string)
-     Lisp_Object font_object, string;
+  (Lisp_Object font_object, Lisp_Object string)
 {
   Lisp_Object frame = selected_frame;
   FRAME_PTR f = XFRAME (frame);
@@ -5136,8 +4893,7 @@ where
   RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling
     how to compose characters.
 If the named font is not yet loaded, return nil.  */)
-     (name, frame)
-     Lisp_Object name, frame;
+  (Lisp_Object name, Lisp_Object frame)
 {
   FRAME_PTR f;
   struct font *font;
@@ -5200,9 +4956,7 @@ If the named font is not yet loaded, return nil.  */)
   build_style_table ((TBL), sizeof TBL / sizeof (struct table_entry))
 
 static Lisp_Object
-build_style_table (entry, nelement)
-     struct table_entry *entry;
-     int nelement;
+build_style_table (const struct table_entry *entry, int nelement)
 {
   int i, j;
   Lisp_Object table, elt;
@@ -5232,9 +4986,7 @@ static Lisp_Object Vfont_log_deferred;
    opening), ARG is the argument for the action, and RESULT is the
    result of the action.  */
 void
-font_add_log (action, arg, result)
-     char *action;
-     Lisp_Object arg, result;
+font_add_log (const char *action, Lisp_Object arg, Lisp_Object result)
 {
   Lisp_Object tail, val;
   int i;
@@ -5320,9 +5072,7 @@ font_add_log (action, arg, result)
    as font_add_log.  */
 
 void
-font_deferred_log (action, arg, result)
-     char *action;
-     Lisp_Object arg, result;
+font_deferred_log (const char *action, Lisp_Object arg, Lisp_Object result)
 {
   if (EQ (Vfont_log, Qt))
     return;
@@ -5331,17 +5081,8 @@ font_deferred_log (action, arg, result)
   ASET (Vfont_log_deferred, 2, result);
 }
 
-extern void syms_of_ftfont P_ (());
-extern void syms_of_xfont P_ (());
-extern void syms_of_xftfont P_ (());
-extern void syms_of_ftxfont P_ (());
-extern void syms_of_bdffont P_ (());
-extern void syms_of_w32font P_ (());
-extern void syms_of_atmfont P_ (());
-extern void syms_of_nsfont P_ (());
-
 void
-syms_of_font ()
+syms_of_font (void)
 {
   sort_shift_bits[FONT_TYPE_INDEX] = 0;
   sort_shift_bits[FONT_SLANT_INDEX] = 2;
@@ -5429,7 +5170,7 @@ syms_of_font ()
   defsubr (&Sopen_font);
   defsubr (&Sclose_font);
   defsubr (&Squery_font);
-  defsubr (&Sget_font_glyphs);
+  defsubr (&Sfont_get_glyphs);
   defsubr (&Sfont_match_p);
   defsubr (&Sfont_at);
 #if 0
@@ -5462,22 +5203,30 @@ non-nil value in the table are supported.  If REPERTORY is nil, Emacs
 gets the repertory information by an opened font and ENCODING.  */);
   Vfont_encoding_alist = Qnil;
 
+  /* FIXME: These 3 vars are not quite what they appear: setq on them
+     won't have any effect other than disconnect them from the style
+     table used by the font display code.  So we make them read-only,
+     to avoid this confusing situation.  */
+
   DEFVAR_LISP_NOPRO ("font-weight-table", &Vfont_weight_table,
               doc: /*  Vector of valid font weight values.
 Each element has the form:
     [NUMERIC-VALUE SYMBOLIC-NAME ALIAS-NAME ...]
 NUMERIC-VALUE is an integer, and SYMBOLIC-NAME and ALIAS-NAME are symbols. */);
   Vfont_weight_table = BUILD_STYLE_TABLE (weight_table);
+  XSYMBOL (intern_c_string ("font-weight-table"))->constant = 1;
 
   DEFVAR_LISP_NOPRO ("font-slant-table", &Vfont_slant_table,
               doc: /*  Vector of font slant symbols vs the corresponding numeric values.
 See `font-weight-table' for the format of the vector. */);
   Vfont_slant_table = BUILD_STYLE_TABLE (slant_table);
+  XSYMBOL (intern_c_string ("font-slant-table"))->constant = 1;
 
   DEFVAR_LISP_NOPRO ("font-width-table", &Vfont_width_table,
               doc: /*  Alist of font width symbols vs the corresponding numeric values.
 See `font-weight-table' for the format of the vector. */);
   Vfont_width_table = BUILD_STYLE_TABLE (width_table);
+  XSYMBOL (intern_c_string ("font-width-table"))->constant = 1;
 
   staticpro (&font_style_table);
   font_style_table = Fmake_vector (make_number (3), Qnil);
@@ -5520,10 +5269,8 @@ EMACS_FONT_LOG is set.  Otherwise, it is set to t.  */);
 }
 
 void
-init_font ()
+init_font (void)
 {
   Vfont_log = egetenv ("EMACS_FONT_LOG") ? Qnil : Qt;
 }
 
-/* arch-tag: 74c9475d-5976-4c93-a327-942ae3072846
-   (do not change this comment) */