Convert DEFUNs to standard C.
[bpt/emacs.git] / src / w32font.c
index 77e949a..d1375d5 100644 (file)
@@ -1,5 +1,5 @@
 /* Font backend for the Microsoft W32 API.
-   Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+   Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -21,6 +21,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <math.h>
 #include <ctype.h>
 #include <commdlg.h>
+#include <setjmp.h>
 
 #include "lisp.h"
 #include "w32term.h"
@@ -28,6 +29,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "dispextern.h"
 #include "character.h"
 #include "charset.h"
+#include "coding.h"
 #include "fontset.h"
 #include "font.h"
 #include "w32font.h"
@@ -67,7 +69,7 @@ extern Lisp_Object Qnone; /* reuse from w32fns.c  */
 static Lisp_Object Qstandard, Qsubpixel, Qnatural;
 
 /* languages */
-static Lisp_Object Qja, Qko, Qzh;
+static Lisp_Object Qzh;
 
 /* scripts */
 static Lisp_Object Qlatin, Qgreek, Qcoptic, Qcyrillic, Qarmenian, Qhebrew;
@@ -79,15 +81,13 @@ static Lisp_Object Qcherokee, Qcanadian_aboriginal, Qogham, Qrunic;
 static Lisp_Object Qkhmer, Qmongolian, Qsymbol, Qbraille, Qhan;
 static Lisp_Object Qideographic_description, Qcjk_misc, Qkana, Qbopomofo;
 static Lisp_Object Qkanbun, Qyi, Qbyzantine_musical_symbol;
-static Lisp_Object Qmusical_symbol, Qmathematical;
+static Lisp_Object Qmusical_symbol, Qmathematical, Qcham, Qphonetic;
 /* Not defined in characters.el, but referenced in fontset.el.  */
 static Lisp_Object Qbalinese, Qbuginese, Qbuhid, Qcuneiform, Qcypriot;
 static Lisp_Object Qdeseret, Qglagolitic, Qgothic, Qhanunoo, Qkharoshthi;
 static Lisp_Object Qlimbu, Qlinear_b, Qold_italic, Qold_persian, Qosmanya;
 static Lisp_Object Qphags_pa, Qphoenician, Qshavian, Qsyloti_nagri;
 static Lisp_Object Qtagalog, Qtagbanwa, Qtai_le, Qtifinagh, Qugaritic;
-/* Only defined here, but useful for distinguishing IPA capable fonts.  */
-static Lisp_Object Qphonetic;
 
 /* W32 charsets: for use in Vw32_charset_info_alist.  */
 static Lisp_Object Qw32_charset_ansi, Qw32_charset_default;
@@ -106,29 +106,28 @@ static Lisp_Object Vw32_charset_info_alist;
 /* Font spacing symbols - defined in font.c.  */
 extern Lisp_Object Qc, Qp, Qm;
 
-static void fill_in_logfont P_ ((FRAME_PTR, LOGFONT *, Lisp_Object));
+static void fill_in_logfont (FRAME_PTR, LOGFONT *, Lisp_Object);
 
-static BYTE w32_antialias_type P_ ((Lisp_Object));
-static Lisp_Object lispy_antialias_type P_ ((BYTE));
+static BYTE w32_antialias_type (Lisp_Object);
+static Lisp_Object lispy_antialias_type (BYTE);
 
-static Lisp_Object font_supported_scripts P_ ((FONTSIGNATURE *));
-static int w32font_full_name P_ ((LOGFONT *, Lisp_Object, int, char *, int));
-static void compute_metrics P_ ((HDC, struct w32font_info *, unsigned int,
-                                struct w32_metric_cache *));
-static void clear_cached_metrics P_ ((struct w32font_info *));
+static Lisp_Object font_supported_scripts (FONTSIGNATURE *);
+static int w32font_full_name (LOGFONT *, Lisp_Object, int, char *, int);
+static void compute_metrics (HDC, struct w32font_info *, unsigned int,
+                             struct w32_metric_cache *);
 
-static Lisp_Object w32_registry P_ ((LONG, DWORD));
+static Lisp_Object w32_registry (LONG, DWORD);
 
 /* EnumFontFamiliesEx callbacks.  */
-static int CALLBACK add_font_entity_to_list P_ ((ENUMLOGFONTEX *,
+static int CALLBACK add_font_entity_to_list (ENUMLOGFONTEX *,
+                                             NEWTEXTMETRICEX *,
+                                             DWORD, LPARAM);
+static int CALLBACK add_one_font_entity_to_list (ENUMLOGFONTEX *,
                                                  NEWTEXTMETRICEX *,
-                                                 DWORD, LPARAM));
-static int CALLBACK add_one_font_entity_to_list P_ ((ENUMLOGFONTEX *,
-                                                     NEWTEXTMETRICEX *,
-                                                     DWORD, LPARAM));
-static int CALLBACK add_font_name_to_list P_ ((ENUMLOGFONTEX *,
-                                               NEWTEXTMETRICEX *,
-                                               DWORD, LPARAM));
+                                                 DWORD, LPARAM);
+static int CALLBACK add_font_name_to_list (ENUMLOGFONTEX *,
+                                           NEWTEXTMETRICEX *,
+                                           DWORD, LPARAM);
 
 /* struct passed in as LPARAM arg to EnumFontFamiliesEx, for keeping track
    of what we really want.  */
@@ -150,24 +149,41 @@ struct font_callback_data
 
 /* Handles the problem that EnumFontFamiliesEx will not return all
    style variations if the font name is not specified.  */
-static void list_all_matching_fonts P_ ((struct font_callback_data *));
+static void list_all_matching_fonts (struct font_callback_data *);
 
 
 static int
-memq_no_quit (elt, list)
-     Lisp_Object elt, list;
+memq_no_quit (Lisp_Object elt, Lisp_Object list)
 {
   while (CONSP (list) && ! EQ (XCAR (list), elt))
     list = XCDR (list);
   return (CONSP (list));
 }
 
+Lisp_Object
+intern_font_name (char * string)
+{
+  Lisp_Object obarray, tem, str;
+  int len;
+
+  str = DECODE_SYSTEM (build_string (string));
+  len = SCHARS (str);
+
+  /* The following code is copied from the function intern (in lread.c).  */
+  obarray = Vobarray;
+  if (!VECTORP (obarray) || XVECTOR (obarray)->size == 0)
+    obarray = check_obarray (obarray);
+  tem = oblookup (obarray, SDATA (str), len, len);
+  if (SYMBOLP (tem))
+    return tem;
+  return Fintern (str, obarray);
+}
+
 /* w32 implementation of get_cache for font backend.
    Return a cache of font-entities on FRAME.  The cache must be a
    cons whose cdr part is the actual cache area.  */
 Lisp_Object
-w32font_get_cache (f)
-     FRAME_PTR f;
+w32font_get_cache (FRAME_PTR f)
 {
   struct w32_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
 
@@ -179,11 +195,10 @@ w32font_get_cache (f)
    is a vector of font-entities.  This is the sole API that
    allocates font-entities.  */
 static Lisp_Object
-w32font_list (frame, font_spec)
-     Lisp_Object frame, font_spec;
+w32font_list (Lisp_Object frame, Lisp_Object font_spec)
 {
   Lisp_Object fonts = w32font_list_internal (frame, font_spec, 0);
-  font_add_log ("w32font-list", font_spec, fonts);
+  FONT_ADD_LOG ("w32font-list", font_spec, fonts);
   return fonts;
 }
 
@@ -192,11 +207,10 @@ w32font_list (frame, font_spec)
    FRAME.  The closeness is detemined by the font backend, thus
    `face-font-selection-order' is ignored here.  */
 static Lisp_Object
-w32font_match (frame, font_spec)
-     Lisp_Object frame, font_spec;
+w32font_match (Lisp_Object frame, Lisp_Object font_spec)
 {
   Lisp_Object entity = w32font_match_internal (frame, font_spec, 0);
-  font_add_log ("w32font-match", font_spec, entity);
+  FONT_ADD_LOG ("w32font-match", font_spec, entity);
   return entity;
 }
 
@@ -204,15 +218,14 @@ w32font_match (frame, font_spec)
    List available families.  The value is a list of family names
    (symbols).  */
 static Lisp_Object
-w32font_list_family (frame)
-     Lisp_Object frame;
+w32font_list_family (Lisp_Object frame)
 {
   Lisp_Object list = Qnil;
   LOGFONT font_match_pattern;
   HDC dc;
   FRAME_PTR f = XFRAME (frame);
 
-  bzero (&font_match_pattern, sizeof (font_match_pattern));
+  memset (&font_match_pattern, 0, sizeof (font_match_pattern));
   font_match_pattern.lfCharSet = DEFAULT_CHARSET;
 
   dc = get_frame_dc (f);
@@ -229,15 +242,14 @@ w32font_list_family (frame)
    Open a font specified by FONT_ENTITY on frame F.
    If the font is scalable, open it with PIXEL_SIZE.  */
 static Lisp_Object
-w32font_open (f, font_entity, pixel_size)
-     FRAME_PTR f;
-     Lisp_Object font_entity;
-     int pixel_size;
+w32font_open (FRAME_PTR f, Lisp_Object font_entity, int pixel_size)
 {
-  Lisp_Object font_object;
+  Lisp_Object font_object
+    = font_make_object (VECSIZE (struct w32font_info),
+                        font_entity, pixel_size);
+  struct w32font_info *w32_font
+    = (struct w32font_info *) XFONT_OBJECT (font_object);
 
-  font_object = font_make_object (VECSIZE (struct w32font_info),
-                                 font_entity, pixel_size);
   ASET (font_object, FONT_TYPE_INDEX, Qgdi);
 
   if (!w32font_open_internal (f, font_entity, pixel_size, font_object))
@@ -245,15 +257,16 @@ w32font_open (f, font_entity, pixel_size)
       return Qnil;
     }
 
+  /* GDI backend does not use glyph indices.  */
+  w32_font->glyph_idx = 0;
+
   return font_object;
 }
 
 /* w32 implementation of close for font_backend.
    Close FONT on frame F.  */
 void
-w32font_close (f, font)
-     FRAME_PTR f;
-     struct font *font;
+w32font_close (FRAME_PTR f, struct font *font)
 {
   int i;
   struct w32font_info *w32_font = (struct w32font_info *) font;
@@ -266,8 +279,7 @@ w32font_close (f, font)
     {
       for (i = 0; i < w32_font->n_cache_blocks; i++)
         {
-          if (w32_font->cached_metrics[i])
-            xfree (w32_font->cached_metrics[i]);
+          xfree (w32_font->cached_metrics[i]);
         }
       xfree (w32_font->cached_metrics);
       w32_font->cached_metrics = NULL;
@@ -280,10 +292,14 @@ w32font_close (f, font)
    return 1.  If not, return 0.  If a font must be opened to check
    it, return -1.  */
 int
-w32font_has_char (entity, c)
-     Lisp_Object entity;
-     int c;
+w32font_has_char (Lisp_Object entity, int c)
 {
+  /* We can't be certain about which characters a font will support until
+     we open it.  Checking the scripts that the font supports turns out
+     to not be reliable.  */
+  return -1;
+
+#if 0
   Lisp_Object supported_scripts, extra, script;
   DWORD mask;
 
@@ -292,6 +308,8 @@ w32font_has_char (entity, c)
     return -1;
 
   supported_scripts = assq_no_quit (QCscript, extra);
+  /* If font doesn't claim to support any scripts, then we can't be certain
+     until we open it.  */
   if (!CONSP (supported_scripts))
     return -1;
 
@@ -299,82 +317,39 @@ w32font_has_char (entity, c)
 
   script = CHAR_TABLE_REF (Vchar_script_table, c);
 
-  return (memq_no_quit (script, supported_scripts)) ? -1 : 0;
+  /* If we don't know what script the character is from, then we can't be
+     certain until we open it.  Also if the font claims support for the script
+     the character is from, it may only have partial coverage, so we still
+     can't be certain until we open the font.  */
+  if (NILP (script) || memq_no_quit (script, supported_scripts))
+    return -1;
+
+  /* Font reports what scripts it supports, and none of them are the script
+     the character is from. But we still can't be certain, as some fonts
+     will contain some/most/all of the characters in that script without
+     claiming support for it.  */
+  return -1;
+#endif
 }
 
 /* w32 implementation of encode_char for font backend.
    Return a glyph code of FONT for characer C (Unicode code point).
-   If FONT doesn't have such a glyph, return FONT_INVALID_CODE.  */
+   If FONT doesn't have such a glyph, return FONT_INVALID_CODE.
+
+   For speed, the gdi backend uses unicode (Emacs calls encode_char
+   far too often for it to be efficient). But we still need to detect
+   which characters are not supported by the font.
+  */
 static unsigned
-w32font_encode_char (font, c)
-     struct font *font;
-     int c;
+w32font_encode_char (struct font *font, int c)
 {
-  struct frame *f;
-  HDC dc;
-  HFONT old_font;
-  DWORD retval;
-  GCP_RESULTSW result;
-  wchar_t in[2];
-  wchar_t out[2];
-  int len;
-  struct w32font_info *w32_font = (struct w32font_info *) font;
-
-  /* If glyph indexing is not working for this font, just return the
-     unicode code-point.  */
-  if (!w32_font->glyph_idx)
-    return c;
-
-  if (c > 0xFFFF)
-    {
-      /* TODO: Encode as surrogate pair and lookup the glyph.  */
-      return FONT_INVALID_CODE;
-    }
-  else
-    {
-      in[0] = (wchar_t) c;
-      len = 1;
-    }
-
-  bzero (&result, sizeof (result));
-  result.lStructSize = sizeof (result);
-  result.lpGlyphs = out;
-  result.nGlyphs = 2;
-
-  f = XFRAME (selected_frame);
-
-  dc = get_frame_dc (f);
-  old_font = SelectObject (dc, w32_font->hfont);
-
-  /* GetCharacterPlacement is used here rather than GetGlyphIndices because
-     it is supported on Windows NT 4 and 9x/ME.  But it cannot reliably report
-     missing glyphs, see below for workaround.  */
-  retval = GetCharacterPlacementW (dc, in, len, 0, &result, 0);
+  struct w32font_info * w32_font = (struct w32font_info *)font;
 
-  SelectObject (dc, old_font);
-  release_frame_dc (f, dc);
-
-  if (retval)
-    {
-      if (result.nGlyphs != 1 || !result.lpGlyphs[0]
-          /* GetCharacterPlacementW seems to return 3, which seems to be
-             the space glyph in most/all truetype fonts, instead of 0
-             for unsupported glyphs.  */
-          || (result.lpGlyphs[0] == 3 && !iswspace (in[0])))
-        return FONT_INVALID_CODE;
-      return result.lpGlyphs[0];
-    }
+  if (c < w32_font->metrics.tmFirstChar
+      || c > w32_font->metrics.tmLastChar)
+    return FONT_INVALID_CODE;
   else
-    {
-      int i;
-      /* Mark this font as not supporting glyph indices. This can happen
-         on Windows9x, and maybe with non-Truetype fonts on NT etc.  */
-      w32_font->glyph_idx = 0;
-      /* Clear metrics cache.  */
-      clear_cached_metrics (w32_font);
-
-      return c;
-    }
+    return c;
 }
 
 /* w32 implementation of text_extents for font backend.
@@ -383,25 +358,22 @@ w32font_encode_char (font, c)
    CODE (length NGLYPHS).  Apparently metrics can be NULL, in this
    case just return the overall width.  */
 int
-w32font_text_extents (font, code, nglyphs, metrics)
-     struct font *font;
-     unsigned *code;
-     int nglyphs;
-     struct font_metrics *metrics;
+w32font_text_extents (struct font *font, unsigned *code,
+                     int nglyphs, struct font_metrics *metrics)
 {
   int i;
   HFONT old_font = NULL;
   HDC dc = NULL;
   struct frame * f;
   int total_width = 0;
-  WORD *wcode = NULL;
+  WORD *wcode;
   SIZE size;
 
   struct w32font_info *w32_font = (struct w32font_info *) font;
 
   if (metrics)
     {
-      bzero (metrics, sizeof (struct font_metrics));
+      memset (metrics, 0, sizeof (struct font_metrics));
       metrics->ascent = font->ascent;
       metrics->descent = font->descent;
 
@@ -416,24 +388,24 @@ w32font_text_extents (font, code, nglyphs, metrics)
              if (!w32_font->cached_metrics)
                w32_font->cached_metrics
                  = xmalloc ((block + 1)
-                            * sizeof (struct w32_cached_metric *));
+                            * sizeof (struct w32_metric_cache *));
              else
                w32_font->cached_metrics
                  = xrealloc (w32_font->cached_metrics,
                              (block + 1)
-                             * sizeof (struct w32_cached_metric *));
-             bzero (w32_font->cached_metrics + w32_font->n_cache_blocks,
-                    ((block + 1 - w32_font->n_cache_blocks)
-                     * sizeof (struct w32_cached_metric *)));
+                             * sizeof (struct w32_metric_cache *));
+             memset (w32_font->cached_metrics + w32_font->n_cache_blocks, 0,
+                     ((block + 1 - w32_font->n_cache_blocks)
+                      * sizeof (struct w32_metric_cache *)));
              w32_font->n_cache_blocks = block + 1;
            }
 
          if (!w32_font->cached_metrics[block])
            {
              w32_font->cached_metrics[block]
-               = xmalloc (CACHE_BLOCKSIZE * sizeof (struct font_metrics));
-             bzero (w32_font->cached_metrics[block],
-                    CACHE_BLOCKSIZE * sizeof (struct font_metrics));
+               = xmalloc (CACHE_BLOCKSIZE * sizeof (struct w32_metric_cache));
+             memset (w32_font->cached_metrics[block], 0,
+                     CACHE_BLOCKSIZE * sizeof (struct w32_metric_cache));
            }
 
          char_metric = w32_font->cached_metrics[block] + pos_in_block;
@@ -484,19 +456,27 @@ w32font_text_extents (font, code, nglyphs, metrics)
   /* For non-truetype fonts, GetGlyphOutlineW is not supported, so
      fallback on other methods that will at least give some of the metric
      information.  */
-  if (!wcode) {
-    wcode = alloca (nglyphs * sizeof (WORD));
-    for (i = 0; i < nglyphs; i++)
-      {
-       if (code[i] < 0x10000)
-         wcode[i] = code[i];
-       else
-         {
-           /* TODO: Convert to surrogate, reallocating array if needed */
-           wcode[i] = 0xffff;
-         }
-      }
-  }
+
+  /* Make array big enough to hold surrogates.  */
+  wcode = alloca (nglyphs * sizeof (WORD) * 2);
+  for (i = 0; i < nglyphs; i++)
+    {
+      if (code[i] < 0x10000)
+        wcode[i] = code[i];
+      else
+        {
+          DWORD surrogate = code[i] - 0x10000;
+
+          /* High surrogate: U+D800 - U+DBFF.  */
+          wcode[i++] = 0xD800 + ((surrogate >> 10) & 0x03FF);
+          /* Low surrogate: U+DC00 - U+DFFF.  */
+          wcode[i] = 0xDC00 + (surrogate & 0x03FF);
+          /* An extra glyph. wcode is already double the size of code to
+             cope with this.  */
+          nglyphs++;
+        }
+    }
+
   if (dc == NULL)
     {
       /* TODO: Frames can come and go, and their fonts outlive
@@ -554,23 +534,27 @@ w32font_text_extents (font, code, nglyphs, metrics)
 */
 
 int
-w32font_draw (s, from, to, x, y, with_background)
-     struct glyph_string *s;
-     int from, to, x, y, with_background;
+w32font_draw (struct glyph_string *s, int from, int to,
+             int x, int y, int with_background)
 {
   UINT options;
-  HRGN orig_clip;
+  HRGN orig_clip = NULL;
   struct w32font_info *w32font = (struct w32font_info *) s->font;
 
   options = w32font->glyph_idx;
 
-  /* Save clip region for later restoration.  */
-  GetClipRgn(s->hdc, orig_clip);
-
   if (s->num_clips > 0)
     {
       HRGN new_clip = CreateRectRgnIndirect (s->clip);
 
+      /* Save clip region for later restoration.  */
+      orig_clip = CreateRectRgn (0, 0, 0, 0);
+      if (!GetClipRgn (s->hdc, orig_clip))
+       {
+         DeleteObject (orig_clip);
+         orig_clip = NULL;
+       }
+
       if (s->num_clips > 1)
         {
           HRGN clip2 = CreateRectRgnIndirect (s->clip + 1);
@@ -614,9 +598,10 @@ w32font_draw (s, from, to, x, y, with_background)
 
   /* Restore clip region.  */
   if (s->num_clips > 0)
-    {
-      SelectClipRgn (s->hdc, orig_clip);
-    }
+    SelectClipRgn (s->hdc, orig_clip);
+
+  if (orig_clip)
+    DeleteObject (orig_clip);
 }
 
 /* w32 implementation of free_entity for font backend.
@@ -711,9 +696,7 @@ w32font_otf_drive (struct font *font, Lisp_Object features,
    Additional parameter opentype_only restricts the returned fonts to
    opentype fonts, which can be used with the Uniscribe backend.  */
 Lisp_Object
-w32font_list_internal (frame, font_spec, opentype_only)
-     Lisp_Object frame, font_spec;
-     int opentype_only;
+w32font_list_internal (Lisp_Object frame, Lisp_Object font_spec, int opentype_only)
 {
   struct font_callback_data match_data;
   HDC dc;
@@ -723,9 +706,22 @@ w32font_list_internal (frame, font_spec, opentype_only)
   match_data.list = Qnil;
   match_data.frame = frame;
 
-  bzero (&match_data.pattern, sizeof (LOGFONT));
+  memset (&match_data.pattern, 0, sizeof (LOGFONT));
   fill_in_logfont (f, &match_data.pattern, font_spec);
 
+  /* If the charset is unrecognized, then we won't find a font, so don't
+     waste time looking for one.  */
+  if (match_data.pattern.lfCharSet == DEFAULT_CHARSET)
+    {
+      Lisp_Object spec_charset = AREF (font_spec, FONT_REGISTRY_INDEX);
+      if (!NILP (spec_charset)
+         && !EQ (spec_charset, Qiso10646_1)
+         && !EQ (spec_charset, Qunicode_bmp)
+         && !EQ (spec_charset, Qunicode_sip)
+         && !EQ (spec_charset, Qunknown))
+       return Qnil;
+    }
+
   match_data.opentype_only = opentype_only;
   if (opentype_only)
     match_data.pattern.lfOutPrecision = OUT_OUTLINE_PRECIS;
@@ -746,16 +742,14 @@ w32font_list_internal (frame, font_spec, opentype_only)
       release_frame_dc (f, dc);
     }
 
-  return NILP (match_data.list) ? Qnil : match_data.list;
+  return match_data.list;
 }
 
 /* Internal implementation of w32font_match.
    Additional parameter opentype_only restricts the returned fonts to
    opentype fonts, which can be used with the Uniscribe backend.  */
 Lisp_Object
-w32font_match_internal (frame, font_spec, opentype_only)
-     Lisp_Object frame, font_spec;
-     int opentype_only;
+w32font_match_internal (Lisp_Object frame, Lisp_Object font_spec, int opentype_only)
 {
   struct font_callback_data match_data;
   HDC dc;
@@ -765,7 +759,7 @@ w32font_match_internal (frame, font_spec, opentype_only)
   match_data.frame = frame;
   match_data.list = Qnil;
 
-  bzero (&match_data.pattern, sizeof (LOGFONT));
+  memset (&match_data.pattern, 0, sizeof (LOGFONT));
   fill_in_logfont (f, &match_data.pattern, font_spec);
 
   match_data.opentype_only = opentype_only;
@@ -783,11 +777,8 @@ w32font_match_internal (frame, font_spec, opentype_only)
 }
 
 int
-w32font_open_internal (f, font_entity, pixel_size, font_object)
-     FRAME_PTR f;
-     Lisp_Object font_entity;
-     int pixel_size;
-     Lisp_Object font_object;
+w32font_open_internal (FRAME_PTR f, Lisp_Object font_entity,
+                      int pixel_size, Lisp_Object font_object)
 {
   int len, size, i;
   LOGFONT logfont;
@@ -796,7 +787,7 @@ w32font_open_internal (f, font_entity, pixel_size, font_object)
   Lisp_Object val, extra;
   struct w32font_info *w32_font;
   struct font * font;
-  OUTLINETEXTMETRIC* metrics = NULL;
+  OUTLINETEXTMETRICW* metrics = NULL;
 
   w32_font = (struct w32font_info *) XFONT_OBJECT (font_object);
   font = (struct font *) w32_font;
@@ -804,7 +795,7 @@ w32font_open_internal (f, font_entity, pixel_size, font_object)
   if (!font)
     return 0;
 
-  bzero (&logfont, sizeof (logfont));
+  memset (&logfont, 0, sizeof (logfont));
   fill_in_logfont (f, &logfont, font_entity);
 
   /* Prefer truetype fonts, to avoid known problems with type1 fonts, and
@@ -828,25 +819,19 @@ w32font_open_internal (f, font_entity, pixel_size, font_object)
   old_font = SelectObject (dc, hfont);
 
   /* Try getting the outline metrics (only works for truetype fonts).  */
-  len = GetOutlineTextMetrics (dc, 0, NULL);
+  len = GetOutlineTextMetricsW (dc, 0, NULL);
   if (len)
     {
-      metrics = (OUTLINETEXTMETRIC *) alloca (len);
-      if (GetOutlineTextMetrics (dc, len, metrics))
-        bcopy (&metrics->otmTextMetrics, &w32_font->metrics,
-               sizeof (TEXTMETRIC));
+      metrics = (OUTLINETEXTMETRICW *) alloca (len);
+      if (GetOutlineTextMetricsW (dc, len, metrics))
+        memcpy (&w32_font->metrics, &metrics->otmTextMetrics,
+               sizeof (TEXTMETRICW));
       else
         metrics = NULL;
-
-      /* If it supports outline metrics, it should support Glyph Indices.  */
-      w32_font->glyph_idx = ETO_GLYPH_INDEX;
     }
 
   if (!metrics)
-    {
-      GetTextMetrics (dc, &w32_font->metrics);
-      w32_font->glyph_idx = 0;
-    }
+    GetTextMetricsW (dc, &w32_font->metrics);
 
   w32_font->cached_metrics = NULL;
   w32_font->n_cache_blocks = 0;
@@ -871,15 +856,19 @@ w32font_open_internal (f, font_entity, pixel_size, font_object)
       }
     if (name)
       font->props[FONT_FULLNAME_INDEX]
-        = make_unibyte_string (name, strlen (name));
+        = DECODE_SYSTEM (build_string (name));
     else
-      font->props[FONT_FULLNAME_INDEX] =
-        make_unibyte_string (logfont.lfFaceName, len);
+      font->props[FONT_FULLNAME_INDEX]
+       = DECODE_SYSTEM (build_string (logfont.lfFaceName));
   }
 
   font->max_width = w32_font->metrics.tmMaxCharWidth;
+  /* Parts of Emacs display assume that height = ascent + descent...
+     so height is defined later, after ascent and descent.
   font->height = w32_font->metrics.tmHeight
     + w32_font->metrics.tmExternalLeading;
+  */
+
   font->space_width = font->average_width = w32_font->metrics.tmAveCharWidth;
 
   font->vertical_centering = 0;
@@ -911,6 +900,7 @@ w32font_open_internal (f, font_entity, pixel_size, font_object)
   font->min_width = font->space_width;
   font->ascent = w32_font->metrics.tmAscent;
   font->descent = w32_font->metrics.tmDescent;
+  font->height = font->ascent + font->descent;
 
   if (metrics)
     {
@@ -935,11 +925,9 @@ w32font_open_internal (f, font_entity, pixel_size, font_object)
 /* Callback function for EnumFontFamiliesEx.
  * Adds the name of a font to a Lisp list (passed in as the lParam arg).  */
 static int CALLBACK
-add_font_name_to_list (logical_font, physical_font, font_type, list_object)
-     ENUMLOGFONTEX *logical_font;
-     NEWTEXTMETRICEX *physical_font;
-     DWORD font_type;
-     LPARAM list_object;
+add_font_name_to_list (ENUMLOGFONTEX *logical_font,
+                      NEWTEXTMETRICEX *physical_font,
+                      DWORD font_type, LPARAM list_object)
 {
   Lisp_Object* list = (Lisp_Object *) list_object;
   Lisp_Object family;
@@ -948,27 +936,24 @@ add_font_name_to_list (logical_font, physical_font, font_type, list_object)
   if (logical_font->elfLogFont.lfFaceName[0] == '@')
     return 1;
 
-  family = font_intern_prop (logical_font->elfLogFont.lfFaceName,
-                            strlen (logical_font->elfLogFont.lfFaceName), 1);
+  family = intern_font_name (logical_font->elfLogFont.lfFaceName);
   if (! memq_no_quit (family, *list))
     *list = Fcons (family, *list);
 
   return 1;
 }
 
-static int w32_decode_weight P_ ((int));
-static int w32_encode_weight P_ ((int));
+static int w32_decode_weight (int);
+static int w32_encode_weight (int);
 
 /* Convert an enumerated Windows font to an Emacs font entity.  */
 static Lisp_Object
-w32_enumfont_pattern_entity (frame, logical_font, physical_font,
-                             font_type, requested_font, backend)
-     Lisp_Object frame;
-     ENUMLOGFONTEX *logical_font;
-     NEWTEXTMETRICEX *physical_font;
-     DWORD font_type;
-     LOGFONT *requested_font;
-     Lisp_Object backend;
+w32_enumfont_pattern_entity (Lisp_Object frame,
+                            ENUMLOGFONTEX *logical_font,
+                            NEWTEXTMETRICEX *physical_font,
+                            DWORD font_type,
+                            LOGFONT *requested_font,
+                            Lisp_Object backend)
 {
   Lisp_Object entity, tem;
   LOGFONT *lf = (LOGFONT*) logical_font;
@@ -1022,7 +1007,7 @@ w32_enumfont_pattern_entity (frame, logical_font, physical_font,
                       lispy_antialias_type (requested_font->lfQuality));
     }
   ASET (entity, FONT_FAMILY_INDEX,
-        font_intern_prop (lf->lfFaceName, strlen (lf->lfFaceName), 1));
+       intern_font_name (lf->lfFaceName));
 
   FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
                  make_number (w32_decode_weight (lf->lfWeight)));
@@ -1092,8 +1077,7 @@ w32_generic_family (Lisp_Object name)
 }
 
 static int
-logfonts_match (font, pattern)
-     LOGFONT *font, *pattern;
+logfonts_match (LOGFONT *font, LOGFONT *pattern)
 {
   /* Only check height for raster fonts.  */
   if (pattern->lfHeight && font->lfOutPrecision == OUT_STRING_PRECIS
@@ -1117,12 +1101,9 @@ logfonts_match (font, pattern)
 #define CSB_CHINESE ((1 << 18) | (1 << 20))
 
 static int
-font_matches_spec (type, font, spec, backend, logfont)
-     DWORD type;
-     NEWTEXTMETRICEX *font;
-     Lisp_Object spec;
-     Lisp_Object backend;
-     LOGFONT *logfont;
+font_matches_spec (DWORD type, NEWTEXTMETRICEX *font,
+                  Lisp_Object spec, Lisp_Object backend,
+                  LOGFONT *logfont)
 {
   Lisp_Object extra, val;
 
@@ -1307,9 +1288,7 @@ font_matches_spec (type, font, spec, backend, logfont)
 }
 
 static int
-w32font_coverage_ok (coverage, charset)
-     FONTSIGNATURE * coverage;
-     BYTE charset;
+w32font_coverage_ok (FONTSIGNATURE * coverage, BYTE charset)
 {
   DWORD subrange1 = coverage->fsUsb[1];
 
@@ -1333,96 +1312,157 @@ w32font_coverage_ok (coverage, charset)
   return 1;
 }
 
+
+static int
+check_face_name (LOGFONT *font, char *full_name)
+{
+  char full_iname[LF_FULLFACESIZE+1];
+
+  /* Just check for names known to cause problems, since the full name
+     can contain expanded abbreviations, prefixed foundry, postfixed
+     style, the latter of which sometimes differs from the style indicated
+     in the shorter name (eg Lt becomes Light or even Extra Light)  */
+
+  /* Helvetica is mapped to Arial in Windows, but if a Type-1 Helvetica is
+     installed, we run into problems with the Uniscribe backend which tries
+     to avoid non-truetype fonts, and ends up mixing the Type-1 Helvetica
+     with Arial's characteristics, since that attempt to use Truetype works
+     some places, but not others.  */
+  if (!xstrcasecmp (font->lfFaceName, "helvetica"))
+    {
+      strncpy (full_iname, full_name, LF_FULLFACESIZE);
+      full_iname[LF_FULLFACESIZE] = 0;
+      _strlwr (full_iname);
+      return strstr ("helvetica", full_iname) != NULL;
+    }
+  /* Same for Helv.  */
+  if (!xstrcasecmp (font->lfFaceName, "helv"))
+    {
+      strncpy (full_iname, full_name, LF_FULLFACESIZE);
+      full_iname[LF_FULLFACESIZE] = 0;
+      _strlwr (full_iname);
+      return strstr ("helv", full_iname) != NULL;
+    }
+
+  /* Since Times is mapped to Times New Roman, a substring
+     match is not sufficient to filter out the bogus match.  */
+  else if (!xstrcasecmp (font->lfFaceName, "times"))
+    return xstrcasecmp (full_name, "times") == 0;
+
+  return 1;
+}
+
+
 /* Callback function for EnumFontFamiliesEx.
  * Checks if a font matches everything we are trying to check agaist,
  * and if so, adds it to a list. Both the data we are checking against
  * and the list to which the fonts are added are passed in via the
  * lparam argument, in the form of a font_callback_data struct. */
 static int CALLBACK
-add_font_entity_to_list (logical_font, physical_font, font_type, lParam)
-     ENUMLOGFONTEX *logical_font;
-     NEWTEXTMETRICEX *physical_font;
-     DWORD font_type;
-     LPARAM lParam;
+add_font_entity_to_list (ENUMLOGFONTEX *logical_font,
+                        NEWTEXTMETRICEX *physical_font,
+                        DWORD font_type, LPARAM lParam)
 {
   struct font_callback_data *match_data
     = (struct font_callback_data *) lParam;
   Lisp_Object backend = match_data->opentype_only ? Quniscribe : Qgdi;
+  Lisp_Object entity;
+
+  int is_unicode = physical_font->ntmFontSig.fsUsb[3]
+    || physical_font->ntmFontSig.fsUsb[2]
+    || physical_font->ntmFontSig.fsUsb[1]
+    || physical_font->ntmFontSig.fsUsb[0] & 0x3fffffff;
+
+  /* Skip non matching fonts.  */
+
+  /* For uniscribe backend, consider only truetype or opentype fonts
+     that have some unicode coverage.  */
+  if (match_data->opentype_only
+      && ((!physical_font->ntmTm.ntmFlags & NTMFLAGS_OPENTYPE
+          && !(font_type & TRUETYPE_FONTTYPE))
+         || !is_unicode))
+    return 1;
+
+  /* Ensure a match.  */
+  if (!logfonts_match (&logical_font->elfLogFont, &match_data->pattern)
+      || !font_matches_spec (font_type, physical_font,
+                            match_data->orig_font_spec, backend,
+                            &logical_font->elfLogFont)
+      || !w32font_coverage_ok (&physical_font->ntmFontSig,
+                              match_data->pattern.lfCharSet))
+    return 1;
 
-  if ((!match_data->opentype_only
-       || (((physical_font->ntmTm.ntmFlags & NTMFLAGS_OPENTYPE)
-            || (font_type & TRUETYPE_FONTTYPE))
-           /* For the uniscribe backend, only consider fonts that claim
-              to cover at least some part of Unicode.  */
-           && (physical_font->ntmFontSig.fsUsb[3]
-               || physical_font->ntmFontSig.fsUsb[2]
-               || physical_font->ntmFontSig.fsUsb[1]
-               || (physical_font->ntmFontSig.fsUsb[0] & 0x3fffffff))))
-      && logfonts_match (&logical_font->elfLogFont, &match_data->pattern)
-      && font_matches_spec (font_type, physical_font,
-                            match_data->orig_font_spec, backend,
-                           &logical_font->elfLogFont)
-      && w32font_coverage_ok (&physical_font->ntmFontSig,
-                              match_data->pattern.lfCharSet)
-      /* Avoid substitutions involving raster fonts (eg Helv -> MS Sans Serif)
-         We limit this to raster fonts, because the test can catch some
-         genuine fonts (eg the full name of DejaVu Sans Mono Light is actually
-         DejaVu Sans Mono ExtraLight). Helvetica -> Arial substitution will
-         therefore get through this test.  Since full names can be prefixed
-         by a foundry, we accept raster fonts if the font name is found
-         anywhere within the full name.  */
-      && (logical_font->elfLogFont.lfOutPrecision != OUT_STRING_PRECIS
-          || strstr (logical_font->elfFullName,
-                     logical_font->elfLogFont.lfFaceName)))
+  /* Avoid substitutions involving raster fonts (eg Helv -> MS Sans Serif)
+     We limit this to raster fonts, because the test can catch some
+     genuine fonts (eg the full name of DejaVu Sans Mono Light is actually
+     DejaVu Sans Mono ExtraLight). Helvetica -> Arial substitution will
+     therefore get through this test.  Since full names can be prefixed
+     by a foundry, we accept raster fonts if the font name is found
+     anywhere within the full name.  */
+  if ((logical_font->elfLogFont.lfOutPrecision == OUT_STRING_PRECIS
+       && !strstr (logical_font->elfFullName,
+                  logical_font->elfLogFont.lfFaceName))
+      /* Check for well known substitutions that mess things up in the
+        presence of Type-1 fonts of the same name.  */
+      || (!check_face_name (&logical_font->elfLogFont,
+                           logical_font->elfFullName)))
+    return 1;
+
+  /* Make a font entity for the font.  */
+  entity = w32_enumfont_pattern_entity (match_data->frame, logical_font,
+                                       physical_font, font_type,
+                                       &match_data->pattern,
+                                       backend);
+
+  if (!NILP (entity))
     {
-      Lisp_Object entity
-        = w32_enumfont_pattern_entity (match_data->frame, logical_font,
-                                       physical_font, font_type,
-                                       &match_data->pattern,
-                                       backend);
-      if (!NILP (entity))
-        {
-          Lisp_Object spec_charset = AREF (match_data->orig_font_spec,
-                                           FONT_REGISTRY_INDEX);
-
-          /* If registry was specified as iso10646-1, only report
-             ANSI and DEFAULT charsets, as most unicode fonts will
-             contain one of those plus others.  */
-          if ((EQ (spec_charset, Qiso10646_1)
-               || EQ (spec_charset, Qunicode_bmp)
-               || EQ (spec_charset, Qunicode_sip))
-              && logical_font->elfLogFont.lfCharSet != DEFAULT_CHARSET
-              && logical_font->elfLogFont.lfCharSet != ANSI_CHARSET)
-            return 1;
-          /* If registry was specified, but did not map to a windows
-             charset, only report fonts that have unknown charsets.
-             This will still report fonts that don't match, but at
-             least it eliminates known definite mismatches.  */
-          else if (!NILP (spec_charset)
-                   && !EQ (spec_charset, Qiso10646_1)
-                   && !EQ (spec_charset, Qunicode_bmp)
-                   && !EQ (spec_charset, Qunicode_sip)
-                   && match_data->pattern.lfCharSet == DEFAULT_CHARSET
-                   && logical_font->elfLogFont.lfCharSet != DEFAULT_CHARSET)
-            return 1;
-
-          /* If registry was specified, ensure it is reported as the same.  */
-          if (!NILP (spec_charset))
-            ASET (entity, FONT_REGISTRY_INDEX, spec_charset);
-
-          match_data->list = Fcons (entity, match_data->list);
-
-          /* If no registry specified, duplicate iso8859-1 truetype fonts
-             as iso10646-1.  */
-          if (NILP (spec_charset)
-              && font_type == TRUETYPE_FONTTYPE
-              && logical_font->elfLogFont.lfCharSet == ANSI_CHARSET)
-            {
-              Lisp_Object tem = Fcopy_font_spec (entity);
-              ASET (tem, FONT_REGISTRY_INDEX, Qiso10646_1);
-              match_data->list = Fcons (tem, match_data->list);
-            }
-        }
+      Lisp_Object spec_charset = AREF (match_data->orig_font_spec,
+                                      FONT_REGISTRY_INDEX);
+
+      /* iso10646-1 fonts must contain unicode mapping tables.  */
+      if (EQ (spec_charset, Qiso10646_1))
+       {
+         if (!is_unicode)
+           return 1;
+       }
+      /* unicode-bmp fonts must contain characters from the BMP.  */
+      else if (EQ (spec_charset, Qunicode_bmp))
+       {
+         if (!physical_font->ntmFontSig.fsUsb[3]
+             && !(physical_font->ntmFontSig.fsUsb[2] & 0xFFFFFF9E)
+             && !(physical_font->ntmFontSig.fsUsb[1] & 0xE81FFFFF)
+             && !(physical_font->ntmFontSig.fsUsb[0] & 0x007F001F))
+           return 1;
+       }
+      /* unicode-sip fonts must contain characters in unicode plane 2.
+        so look for bit 57 (surrogates) in the Unicode subranges, plus
+        the bits for CJK ranges that include those characters.  */
+      else if (EQ (spec_charset, Qunicode_sip))
+       {
+         if (!physical_font->ntmFontSig.fsUsb[1] & 0x02000000
+             || !physical_font->ntmFontSig.fsUsb[1] & 0x28000000)
+           return 1;
+       }
+
+      /* This font matches.  */
+
+      /* If registry was specified, ensure it is reported as the same.  */
+      if (!NILP (spec_charset))
+       ASET (entity, FONT_REGISTRY_INDEX, spec_charset);
+
+      /* Otherwise if using the uniscribe backend, report ANSI and DEFAULT
+        fonts as unicode and skip other charsets.  */
+      else if (match_data->opentype_only)
+       {
+         if (logical_font->elfLogFont.lfCharSet == ANSI_CHARSET
+             || logical_font->elfLogFont.lfCharSet == DEFAULT_CHARSET)
+           ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1);
+         else
+           return 1;
+       }
+
+      /* Add this font to the list.  */
+      match_data->list = Fcons (entity, match_data->list);
     }
   return 1;
 }
@@ -1430,24 +1470,21 @@ add_font_entity_to_list (logical_font, physical_font, font_type, lParam)
 /* Callback function for EnumFontFamiliesEx.
  * Terminates the search once we have a match. */
 static int CALLBACK
-add_one_font_entity_to_list (logical_font, physical_font, font_type, lParam)
-     ENUMLOGFONTEX *logical_font;
-     NEWTEXTMETRICEX *physical_font;
-     DWORD font_type;
-     LPARAM lParam;
+add_one_font_entity_to_list (ENUMLOGFONTEX *logical_font,
+                            NEWTEXTMETRICEX *physical_font,
+                            DWORD font_type, LPARAM lParam)
 {
   struct font_callback_data *match_data
     = (struct font_callback_data *) lParam;
   add_font_entity_to_list (logical_font, physical_font, font_type, lParam);
 
   /* If we have a font in the list, terminate the search.  */
-  return !NILP (match_data->list);
+  return NILP (match_data->list);
 }
 
 /* Old function to convert from x to w32 charset, from w32fns.c.  */
 static LONG
-x_to_w32_charset (lpcs)
-    char * lpcs;
+x_to_w32_charset (char * lpcs)
 {
   Lisp_Object this_entry, w32_charset;
   char *charset;
@@ -1529,8 +1566,7 @@ x_to_w32_charset (lpcs)
 
 /* Convert a Lisp font registry (symbol) to a windows charset.  */
 static LONG
-registry_to_w32_charset (charset)
-     Lisp_Object charset;
+registry_to_w32_charset (Lisp_Object charset)
 {
   if (EQ (charset, Qiso10646_1) || EQ (charset, Qunicode_bmp)
       || EQ (charset, Qunicode_sip))
@@ -1545,9 +1581,7 @@ registry_to_w32_charset (charset)
 
 /* Old function to convert from w32 to x charset, from w32fns.c.  */
 static char *
-w32_to_x_charset (fncharset, matching)
-    int fncharset;
-    char *matching;
+w32_to_x_charset (int fncharset, char *matching)
 {
   static char buf[32];
   Lisp_Object charset_type;
@@ -1741,9 +1775,7 @@ w32_to_x_charset (fncharset, matching)
 }
 
 static Lisp_Object
-w32_registry (w32_charset, font_type)
-     LONG w32_charset;
-     DWORD font_type;
+w32_registry (LONG w32_charset, DWORD font_type)
 {
   char *charset;
 
@@ -1753,12 +1785,11 @@ w32_registry (w32_charset, font_type)
     return font_type == TRUETYPE_FONTTYPE ? Qiso10646_1 : Qunknown;
 
   charset = w32_to_x_charset (w32_charset, NULL);
-  return font_intern_prop (charset, strlen(charset), 1);
+  return font_intern_prop (charset, strlen (charset), 1);
 }
 
 static int
-w32_decode_weight (fnweight)
-     int fnweight;
+w32_decode_weight (int fnweight)
 {
   if (fnweight >= FW_HEAVY)      return 210;
   if (fnweight >= FW_EXTRABOLD)  return 205;
@@ -1772,8 +1803,7 @@ w32_decode_weight (fnweight)
 }
 
 static int
-w32_encode_weight (n)
-     int n;
+w32_encode_weight (int n)
 {
   if (n >= 210) return FW_HEAVY;
   if (n >= 205) return FW_EXTRABOLD;
@@ -1789,8 +1819,7 @@ w32_encode_weight (n)
 /* Convert a Windows font weight into one of the weights supported
    by fontconfig (see font.c:font_parse_fcname).  */
 static Lisp_Object
-w32_to_fc_weight (n)
-     int n;
+w32_to_fc_weight (int n)
 {
   if (n >= FW_EXTRABOLD) return intern ("black");
   if (n >= FW_BOLD) return intern ("bold");
@@ -1801,10 +1830,7 @@ w32_to_fc_weight (n)
 
 /* Fill in all the available details of LOGFONT from FONT_SPEC.  */
 static void
-fill_in_logfont (f, logfont, font_spec)
-     FRAME_PTR f;
-     LOGFONT *logfont;
-     Lisp_Object font_spec;
+fill_in_logfont (FRAME_PTR f, LOGFONT *logfont, Lisp_Object font_spec)
 {
   Lisp_Object tmp, extra;
   int dpi = FRAME_W32_DISPLAY_INFO (f)->resy;
@@ -1873,7 +1899,8 @@ fill_in_logfont (f, logfont, font_spec)
         /* Font families are interned, but allow for strings also in case of
            user input.  */
       else if (SYMBOLP (tmp))
-        strncpy (logfont->lfFaceName, SDATA (SYMBOL_NAME (tmp)), LF_FACESIZE);
+        strncpy (logfont->lfFaceName,
+                SDATA (ENCODE_SYSTEM (SYMBOL_NAME (tmp))), LF_FACESIZE);
     }
 
   tmp = AREF (font_spec, FONT_ADSTYLE_INDEX);
@@ -1938,8 +1965,6 @@ fill_in_logfont (f, logfont, font_spec)
                 logfont->lfCharSet = ARABIC_CHARSET;
               else if (EQ (val, Qthai))
                 logfont->lfCharSet = THAI_CHARSET;
-              else if (EQ (val, Qsymbol))
-                logfont->lfCharSet = SYMBOL_CHARSET;
             }
           else if (EQ (key, QCantialias) && SYMBOLP (val))
             {
@@ -1950,8 +1975,7 @@ fill_in_logfont (f, logfont, font_spec)
 }
 
 static void
-list_all_matching_fonts (match_data)
-     struct font_callback_data *match_data;
+list_all_matching_fonts (struct font_callback_data *match_data)
 {
   HDC dc;
   Lisp_Object families = w32font_list_family (match_data->frame);
@@ -1961,15 +1985,17 @@ list_all_matching_fonts (match_data)
 
   while (!NILP (families))
     {
-      /* TODO: Use the Unicode versions of the W32 APIs, so we can
-         handle non-ASCII font names.  */
+      /* Only fonts from the current locale are given localized names
+        on Windows, so we can keep backwards compatibility with
+        Windows 9x/ME by using non-Unicode font enumeration without
+        sacrificing internationalization here.  */
       char *name;
       Lisp_Object family = CAR (families);
       families = CDR (families);
       if (NILP (family))
         continue;
       else if (SYMBOLP (family))
-        name = SDATA (SYMBOL_NAME (family));
+        name = SDATA (ENCODE_SYSTEM (SYMBOL_NAME (family)));
       else
        continue;
 
@@ -1985,8 +2011,7 @@ list_all_matching_fonts (match_data)
 }
 
 static Lisp_Object
-lispy_antialias_type (type)
-     BYTE type;
+lispy_antialias_type (BYTE type)
 {
   Lisp_Object lispy;
 
@@ -2013,8 +2038,7 @@ lispy_antialias_type (type)
 
 /* Convert antialiasing symbols to lfQuality  */
 static BYTE
-w32_antialias_type (type)
-     Lisp_Object type;
+w32_antialias_type (Lisp_Object type)
 {
   if (EQ (type, Qnone))
     return NONANTIALIASED_QUALITY;
@@ -2058,6 +2082,7 @@ font_supported_scripts (FONTSIGNATURE * sig)
   SUBRANGE (9, Qcyrillic);
   SUBRANGE (10, Qarmenian);
   SUBRANGE (11, Qhebrew);
+  /* 12: Vai.  */
   SUBRANGE (13, Qarabic);
   SUBRANGE (14, Qnko);
   SUBRANGE (15, Qdevanagari);
@@ -2137,13 +2162,18 @@ font_supported_scripts (FONTSIGNATURE * sig)
   SUBRANGE (108, Qkharoshthi);
   /* 109: Tai Xuan Jing.  */
   SUBRANGE (110, Qcuneiform);
-  /* 111: Counting Rods.  */
+  /* 111: Counting Rods, 112: Sundanese, 113: Lepcha, 114: Ol Chiki.  */
+  /* 115: Saurashtra, 116: Kayah Li, 117: Rejang.  */
+  SUBRANGE (118, Qcham);
+  /* 119: Ancient symbols, 120: Phaistos Disc.  */
+  /* 121: Carian, Lycian, Lydian, 122: Dominos, Mah Jong tiles.  */
+  /* 123-127: Reserved.  */
 
   /* There isn't really a main symbol range, so include symbol if any
      relevant range is set.  */
   MASK_ANY (0x8000000, 0x0000FFFF, 0, 0, Qsymbol);
 
-  /* Missing: Tai Viet (U+AA80) and Cham (U+AA00) .  */
+  /* Missing: Tai Viet (U+AA80-U+AADF).  */
 #undef SUBRANGE
 #undef MASK_ANY
 
@@ -2154,12 +2184,8 @@ font_supported_scripts (FONTSIGNATURE * sig)
    The full name is in fcname format, with weight, slant and antialiasing
    specified if they are not "normal".  */
 static int
-w32font_full_name (font, font_obj, pixel_size, name, nbytes)
-  LOGFONT * font;
-  Lisp_Object font_obj;
-  int pixel_size;
-  char *name;
-  int nbytes;
+w32font_full_name (LOGFONT * font, Lisp_Object font_obj,
+                  int pixel_size, char *name, int nbytes)
 {
   int len, height, outline;
   char *p;
@@ -2230,11 +2256,8 @@ w32font_full_name (font, font_obj, pixel_size, name, nbytes)
    is written.  If the buffer is not large enough to contain the name,
    the function returns -1, otherwise it returns the number of bytes
    written to FCNAME.  */
-static int logfont_to_fcname(font, pointsize, fcname, size)
-     LOGFONT* font;
-     int pointsize;
-     char *fcname;
-     int size;
+static int
+logfont_to_fcname (LOGFONT* font, int pointsize, char *fcname, int size)
 {
   int len, height;
   char *p = fcname;
@@ -2273,11 +2296,8 @@ static int logfont_to_fcname(font, pointsize, fcname, size)
 }
 
 static void
-compute_metrics (dc, w32_font, code, metrics)
-     HDC dc;
-     struct w32font_info *w32_font;
-     unsigned int code;
-     struct w32_metric_cache *metrics;
+compute_metrics (HDC dc, struct w32font_info *w32_font, unsigned int code,
+                struct w32_metric_cache *metrics)
 {
   GLYPHMETRICS gm;
   MAT2 transform;
@@ -2286,7 +2306,7 @@ compute_metrics (dc, w32_font, code, metrics)
   if (w32_font->glyph_idx)
     options |= GGO_GLYPH_INDEX;
 
-  bzero (&transform, sizeof (transform));
+  memset (&transform, 0, sizeof (transform));
   transform.eM11.value = 1;
   transform.eM22.value = 1;
 
@@ -2298,40 +2318,18 @@ compute_metrics (dc, w32_font, code, metrics)
       metrics->width = gm.gmCellIncX;
       metrics->status = W32METRIC_SUCCESS;
     }
-  else if (w32_font->glyph_idx)
-    {
-      /* Can't use glyph indexes after all.
-        Avoid it in future, and clear any metrics that were based on
-        glyph indexes.  */
-      w32_font->glyph_idx = 0;
-      clear_cached_metrics (w32_font);
-    }
   else
     metrics->status = W32METRIC_FAIL;
 }
 
-static void
-clear_cached_metrics (w32_font)
-     struct w32font_info *w32_font;
-{
-  int i;
-  for (i = 0; i < w32_font->n_cache_blocks; i++)
-    {
-      if (w32_font->cached_metrics[i])
-        bzero (w32_font->cached_metrics[i],
-               CACHE_BLOCKSIZE * sizeof (struct font_metrics));
-    }
-}
-
 DEFUN ("x-select-font", Fx_select_font, Sx_select_font, 0, 2, 0,
        doc: /* Read a font name using a W32 font selection dialog.
 Return fontconfig style font string corresponding to the selection.
 
 If FRAME is omitted or nil, it defaults to the selected frame.
-If INCLUDE-PROPORTIONAL is non-nil, include proportional fonts
+If EXCLUDE-PROPORTIONAL is non-nil, exclude proportional fonts
 in the font selection dialog. */)
-  (frame, include_proportional)
-     Lisp_Object frame, include_proportional;
+  (Lisp_Object frame, Lisp_Object exclude_proportional)
 {
   FRAME_PTR f = check_x_frame (frame);
   CHOOSEFONT cf;
@@ -2341,16 +2339,16 @@ in the font selection dialog. */)
   HANDLE oldobj;
   char buf[100];
 
-  bzero (&cf, sizeof (cf));
-  bzero (&lf, sizeof (lf));
+  memset (&cf, 0, sizeof (cf));
+  memset (&lf, 0, sizeof (lf));
 
   cf.lStructSize = sizeof (cf);
   cf.hwndOwner = FRAME_W32_WINDOW (f);
   cf.Flags = CF_FORCEFONTEXIST | CF_SCREENFONTS | CF_NOVERTFONTS;
 
-  /* Unless include_proportional is non-nil, limit the selection to
+  /* If exclude_proportional is non-nil, limit the selection to
      monospaced fonts.  */
-  if (NILP (include_proportional))
+  if (!NILP (exclude_proportional))
     cf.Flags |= CF_FIXEDPITCHONLY;
 
   cf.lpLogFont = &lf;
@@ -2377,7 +2375,7 @@ in the font selection dialog. */)
       || logfont_to_fcname (&lf, cf.iPointSize, buf, 100) < 0)
     return Qnil;
 
-  return build_string (buf);
+  return DECODE_SYSTEM (build_string (buf));
 }
 
 struct font_driver w32font_driver =
@@ -2406,14 +2404,17 @@ struct font_driver w32font_driver =
     NULL, /* otf_drive */
     NULL, /* start_for_frame */
     NULL, /* end_for_frame */
-    NULL  /* shape */
+    NULL, /* shape */
+    NULL, /* check */
+    NULL, /* get_variation_glyphs */
+    NULL, /* filter_properties */
   };
 
 
 /* Initialize state that does not change between invocations. This is only
    called when Emacs is dumped.  */
 void
-syms_of_w32font ()
+syms_of_w32font (void)
 {
   DEFSYM (Qgdi, "gdi");
   DEFSYM (Quniscribe, "uniscribe");
@@ -2441,8 +2442,6 @@ syms_of_w32font ()
   DEFSYM (Qnatural, "natural");
 
   /* Languages  */
-  DEFSYM (Qja, "ja");
-  DEFSYM (Qko, "ko");
   DEFSYM (Qzh, "zh");
 
   /* Scripts  */
@@ -2491,6 +2490,7 @@ syms_of_w32font ()
   DEFSYM (Qbyzantine_musical_symbol, "byzantine-musical-symbol");
   DEFSYM (Qmusical_symbol, "musical-symbol");
   DEFSYM (Qmathematical, "mathematical");
+  DEFSYM (Qcham, "cham");
   DEFSYM (Qphonetic, "phonetic");
   DEFSYM (Qbalinese, "balinese");
   DEFSYM (Qbuginese, "buginese");