]> code.delx.au - gnu-emacs/blobdiff - src/w32font.c
Fmarker_position doc string clarification
[gnu-emacs] / src / w32font.c
index aef62f61a3a3f3f2d0de0268a42803f988358f45..018e6572563df4118f8690cfd0276a0cb4919c9f 100644 (file)
@@ -1,12 +1,12 @@
-/* Font backend for the Microsoft W32 API.
-   Copyright (C) 2007-2011 Free Software Foundation, Inc.
+/* Font backend for the Microsoft Windows API.
+   Copyright (C) 2007-2016 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 GNU Emacs is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+the Free Software Foundation, either version 3 of the License, or (at
+your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,21 +18,19 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 #include <windows.h>
+#include <stdio.h>
 #include <math.h>
 #include <ctype.h>
 #include <commdlg.h>
-#include <setjmp.h>
 
 #include "lisp.h"
 #include "w32term.h"
 #include "frame.h"
-#include "dispextern.h"
-#include "character.h"
-#include "charset.h"
-#include "coding.h"
-#include "fontset.h"
-#include "font.h"
+#include "coding.h"    /* for ENCODE_SYSTEM, DECODE_SYSTEM */
 #include "w32font.h"
+#ifdef WINDOWSNT
+#include "w32.h"
+#endif
 
 /* Cleartype available on Windows XP, cleartype_natural from XP SP1.
    The latter does not try to fit cleartype smoothed fonts into the
@@ -54,56 +52,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #define JOHAB_CHARSET 130
 #endif
 
-extern struct font_driver w32font_driver;
-
-Lisp_Object Qgdi;
-Lisp_Object Quniscribe;
-static Lisp_Object QCformat;
-static Lisp_Object Qmonospace, Qsansserif, Qmono, Qsans, Qsans_serif;
-static Lisp_Object Qserif, Qscript, Qdecorative;
-static Lisp_Object Qraster, Qoutline, Qunknown;
-
-/* antialiasing  */
-extern Lisp_Object QCantialias, QCotf, QClang; /* defined in font.c  */
-extern Lisp_Object Qnone; /* reuse from w32fns.c  */
-static Lisp_Object Qstandard, Qsubpixel, Qnatural;
-
-/* languages */
-static Lisp_Object Qzh;
-
-/* scripts */
-static Lisp_Object Qgreek, Qcoptic, Qcyrillic, Qarmenian, Qhebrew;
-static Lisp_Object Qarabic, Qsyriac, Qnko, Qthaana, Qdevanagari, Qbengali;
-static Lisp_Object Qgurmukhi, Qgujarati, Qoriya, Qtamil, Qtelugu;
-static Lisp_Object Qkannada, Qmalayalam, Qsinhala, Qthai, Qlao;
-static Lisp_Object Qtibetan, Qmyanmar, Qgeorgian, Qhangul, Qethiopic;
-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, 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;
-
-/* W32 charsets: for use in Vw32_charset_info_alist.  */
-static Lisp_Object Qw32_charset_ansi, Qw32_charset_default;
-static Lisp_Object Qw32_charset_symbol, Qw32_charset_shiftjis;
-static Lisp_Object Qw32_charset_hangeul, Qw32_charset_gb2312;
-static Lisp_Object Qw32_charset_chinesebig5, Qw32_charset_oem;
-static Lisp_Object Qw32_charset_easteurope, Qw32_charset_turkish;
-static Lisp_Object Qw32_charset_baltic, Qw32_charset_russian;
-static Lisp_Object Qw32_charset_arabic, Qw32_charset_greek;
-static Lisp_Object Qw32_charset_hebrew, Qw32_charset_vietnamese;
-static Lisp_Object Qw32_charset_thai, Qw32_charset_johab, Qw32_charset_mac;
-
-/* Font spacing symbols - defined in font.c.  */
-extern Lisp_Object Qc, Qp, Qm;
-
-static void fill_in_logfont (FRAME_PTR, LOGFONT *, Lisp_Object);
+static void fill_in_logfont (struct frame *, LOGFONT *, Lisp_Object);
 
 static BYTE w32_antialias_type (Lisp_Object);
 static Lisp_Object lispy_antialias_type (BYTE);
@@ -116,15 +65,15 @@ static void compute_metrics (HDC, struct w32font_info *, unsigned int,
 static Lisp_Object w32_registry (LONG, DWORD);
 
 /* EnumFontFamiliesEx callbacks.  */
-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_font_name_to_list (ENUMLOGFONTEX *,
-                                           NEWTEXTMETRICEX *,
-                                           DWORD, LPARAM);
+static int CALLBACK ALIGN_STACK add_font_entity_to_list (ENUMLOGFONTEX *,
+                                                        NEWTEXTMETRICEX *,
+                                                        DWORD, LPARAM);
+static int CALLBACK ALIGN_STACK add_one_font_entity_to_list (ENUMLOGFONTEX *,
+                                                            NEWTEXTMETRICEX *,
+                                                            DWORD, LPARAM);
+static int CALLBACK ALIGN_STACK 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.  */
@@ -141,13 +90,140 @@ struct font_callback_data
   /* The list to add matches to.  */
   Lisp_Object list;
   /* Whether to match only opentype fonts.  */
-  int opentype_only;
+  bool opentype_only;
 };
 
 /* Handles the problem that EnumFontFamiliesEx will not return all
    style variations if the font name is not specified.  */
 static void list_all_matching_fonts (struct font_callback_data *);
 
+#ifdef WINDOWSNT
+
+static BOOL g_b_init_get_outline_metrics_w;
+static BOOL g_b_init_get_text_metrics_w;
+static BOOL g_b_init_get_glyph_outline_w;
+static BOOL g_b_init_get_glyph_outline_w;
+static BOOL g_b_init_get_char_width_32_w;
+
+typedef UINT (WINAPI * GetOutlineTextMetricsW_Proc) (
+   HDC hdc,
+   UINT cbData,
+   LPOUTLINETEXTMETRICW lpotmw);
+typedef BOOL (WINAPI * GetTextMetricsW_Proc) (
+   HDC hdc,
+   LPTEXTMETRICW lptmw);
+typedef DWORD (WINAPI * GetGlyphOutlineW_Proc) (
+   HDC hdc,
+   UINT uChar,
+   UINT uFormat,
+   LPGLYPHMETRICS lpgm,
+   DWORD cbBuffer,
+   LPVOID lpvBuffer,
+   const MAT2 *lpmat2);
+typedef BOOL (WINAPI * GetCharWidth32W_Proc) (
+   HDC hdc,
+   UINT uFirstChar,
+   UINT uLastChar,
+   LPINT lpBuffer);
+
+/* Several "wide" functions we use to support the font backends are
+   unavailable on Windows 9X, unless UNICOWS.DLL is installed (their
+   versions in the default libraries are non-functional stubs).  On NT
+   and later systems, these functions are in GDI32.DLL.  The following
+   helper function attempts to load UNICOWS.DLL on Windows 9X, and
+   refuses to let Emacs start up if that library is not found.  On NT
+   and later versions, it simply loads GDI32.DLL, which should always
+   be available.  */
+static HMODULE
+w32_load_unicows_or_gdi32 (void)
+{
+  return maybe_load_unicows_dll ();
+}
+
+/* The following 3 functions call the problematic "wide" APIs via
+   function pointers, to avoid linking against the non-standard
+   libunicows on W9X.  */
+static UINT WINAPI
+get_outline_metrics_w(HDC hdc, UINT cbData, LPOUTLINETEXTMETRICW lpotmw)
+{
+  static GetOutlineTextMetricsW_Proc s_pfn_Get_Outline_Text_MetricsW = NULL;
+  HMODULE hm_unicows = NULL;
+  if (g_b_init_get_outline_metrics_w == 0)
+    {
+      g_b_init_get_outline_metrics_w = 1;
+      hm_unicows = w32_load_unicows_or_gdi32 ();
+      if (hm_unicows)
+       s_pfn_Get_Outline_Text_MetricsW = (GetOutlineTextMetricsW_Proc)
+         GetProcAddress (hm_unicows, "GetOutlineTextMetricsW");
+    }
+  eassert (s_pfn_Get_Outline_Text_MetricsW != NULL);
+  return s_pfn_Get_Outline_Text_MetricsW (hdc, cbData, lpotmw);
+}
+
+static BOOL WINAPI
+get_text_metrics_w(HDC hdc, LPTEXTMETRICW lptmw)
+{
+  static GetTextMetricsW_Proc s_pfn_Get_Text_MetricsW = NULL;
+  HMODULE hm_unicows = NULL;
+  if (g_b_init_get_text_metrics_w == 0)
+    {
+      g_b_init_get_text_metrics_w = 1;
+      hm_unicows = w32_load_unicows_or_gdi32 ();
+      if (hm_unicows)
+       s_pfn_Get_Text_MetricsW = (GetTextMetricsW_Proc)
+         GetProcAddress (hm_unicows, "GetTextMetricsW");
+    }
+  eassert (s_pfn_Get_Text_MetricsW != NULL);
+  return s_pfn_Get_Text_MetricsW (hdc, lptmw);
+}
+
+static DWORD WINAPI
+get_glyph_outline_w (HDC hdc, UINT uChar, UINT uFormat, LPGLYPHMETRICS lpgm,
+                    DWORD cbBuffer, LPVOID lpvBuffer, const MAT2 *lpmat2)
+{
+  static GetGlyphOutlineW_Proc s_pfn_Get_Glyph_OutlineW = NULL;
+  HMODULE hm_unicows = NULL;
+  if (g_b_init_get_glyph_outline_w == 0)
+    {
+      g_b_init_get_glyph_outline_w = 1;
+      hm_unicows = w32_load_unicows_or_gdi32 ();
+      if (hm_unicows)
+       s_pfn_Get_Glyph_OutlineW = (GetGlyphOutlineW_Proc)
+         GetProcAddress (hm_unicows, "GetGlyphOutlineW");
+    }
+  eassert (s_pfn_Get_Glyph_OutlineW != NULL);
+  return s_pfn_Get_Glyph_OutlineW (hdc, uChar, uFormat, lpgm, cbBuffer,
+                                  lpvBuffer, lpmat2);
+}
+
+static DWORD WINAPI
+get_char_width_32_w (HDC hdc, UINT uFirstChar, UINT uLastChar, LPINT lpBuffer)
+{
+  static GetCharWidth32W_Proc s_pfn_Get_Char_Width_32W = NULL;
+  HMODULE hm_unicows = NULL;
+  if (g_b_init_get_char_width_32_w == 0)
+    {
+      g_b_init_get_char_width_32_w = 1;
+      hm_unicows = w32_load_unicows_or_gdi32 ();
+      if (hm_unicows)
+       s_pfn_Get_Char_Width_32W = (GetCharWidth32W_Proc)
+         GetProcAddress (hm_unicows, "GetCharWidth32W");
+    }
+  eassert (s_pfn_Get_Char_Width_32W != NULL);
+  return s_pfn_Get_Char_Width_32W (hdc, uFirstChar, uLastChar, lpBuffer);
+}
+
+#else  /* Cygwin */
+
+/* Cygwin doesn't support Windows 9X, and links against GDI32.DLL, so
+   it can just call these functions directly.  */
+#define get_outline_metrics_w(h,d,o)   GetOutlineTextMetricsW(h,d,o)
+#define get_text_metrics_w(h,t)        GetTextMetricsW(h,t)
+#define get_glyph_outline_w(h,uc,f,gm,b,v,m) \
+                                       GetGlyphOutlineW(h,uc,f,gm,b,v,m)
+#define get_char_width_32_w(h,fc,lc,b) GetCharWidth32W(h,fc,lc,b)
+
+#endif /* Cygwin */
 
 static int
 memq_no_quit (Lisp_Object elt, Lisp_Object list)
@@ -160,29 +236,21 @@ memq_no_quit (Lisp_Object elt, Lisp_Object 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);
+  Lisp_Object str = DECODE_SYSTEM (build_string (string));
+  ptrdiff_t len = SCHARS (str);
+  Lisp_Object obarray = check_obarray (Vobarray);
+  Lisp_Object tem = oblookup (obarray, SSDATA (str), len, len);
+  /* This code is similar to intern function from lread.c.  */
+  return SYMBOLP (tem) ? tem : intern_driver (str, obarray, tem);
 }
 
 /* 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 (FRAME_PTR f)
+w32font_get_cache (struct frame *f)
 {
-  struct w32_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
 
   return (dpyinfo->name_list_element);
 }
@@ -192,21 +260,21 @@ w32font_get_cache (FRAME_PTR f)
    is a vector of font-entities.  This is the sole API that
    allocates font-entities.  */
 static Lisp_Object
-w32font_list (Lisp_Object frame, Lisp_Object font_spec)
+w32font_list (struct frame *f, Lisp_Object font_spec)
 {
-  Lisp_Object fonts = w32font_list_internal (frame, font_spec, 0);
+  Lisp_Object fonts = w32font_list_internal (f, font_spec, 0);
   FONT_ADD_LOG ("w32font-list", font_spec, fonts);
   return fonts;
 }
 
 /* w32 implementation of match for font backend.
    Return a font entity most closely matching with FONT_SPEC on
-   FRAME.  The closeness is detemined by the font backend, thus
+   FRAME.  The closeness is determined by the font backend, thus
    `face-font-selection-order' is ignored here.  */
 static Lisp_Object
-w32font_match (Lisp_Object frame, Lisp_Object font_spec)
+w32font_match (struct frame *f, Lisp_Object font_spec)
 {
-  Lisp_Object entity = w32font_match_internal (frame, font_spec, 0);
+  Lisp_Object entity = w32font_match_internal (f, font_spec, 0);
   FONT_ADD_LOG ("w32font-match", font_spec, entity);
   return entity;
 }
@@ -215,12 +283,11 @@ w32font_match (Lisp_Object frame, Lisp_Object font_spec)
    List available families.  The value is a list of family names
    (symbols).  */
 static Lisp_Object
-w32font_list_family (Lisp_Object frame)
+w32font_list_family (struct frame *f)
 {
   Lisp_Object list = Qnil;
   LOGFONT font_match_pattern;
   HDC dc;
-  FRAME_PTR f = XFRAME (frame);
 
   memset (&font_match_pattern, 0, sizeof (font_match_pattern));
   font_match_pattern.lfCharSet = DEFAULT_CHARSET;
@@ -239,7 +306,7 @@ w32font_list_family (Lisp_Object 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 (FRAME_PTR f, Lisp_Object font_entity, int pixel_size)
+w32font_open (struct frame *f, Lisp_Object font_entity, int pixel_size)
 {
   Lisp_Object font_object
     = font_make_object (VECSIZE (struct w32font_info),
@@ -260,26 +327,28 @@ w32font_open (FRAME_PTR f, Lisp_Object font_entity, int pixel_size)
   return font_object;
 }
 
-/* w32 implementation of close for font_backend.
-   Close FONT on frame F.  */
+/* w32 implementation of close for font_backend.  */
 void
-w32font_close (FRAME_PTR f, struct font *font)
+w32font_close (struct font *font)
 {
-  int i;
   struct w32font_info *w32_font = (struct w32font_info *) font;
 
-  /* Delete the GDI font object.  */
-  DeleteObject (w32_font->hfont);
-
-  /* Free all the cached metrics.  */
-  if (w32_font->cached_metrics)
+  if (w32_font->hfont)
     {
-      for (i = 0; i < w32_font->n_cache_blocks; i++)
-        {
-          xfree (w32_font->cached_metrics[i]);
-        }
-      xfree (w32_font->cached_metrics);
-      w32_font->cached_metrics = NULL;
+      /* Delete the GDI font object.  */
+      DeleteObject (w32_font->hfont);
+      w32_font->hfont = NULL;
+
+      /* Free all the cached metrics.  */
+      if (w32_font->cached_metrics)
+       {
+         int i;
+
+         for (i = 0; i < w32_font->n_cache_blocks; i++)
+             xfree (w32_font->cached_metrics[i]);
+         xfree (w32_font->cached_metrics);
+         w32_font->cached_metrics = NULL;
+       }
     }
 }
 
@@ -333,7 +402,7 @@ w32font_has_char (Lisp_Object entity, int c)
    Return a glyph code of FONT for character C (Unicode code point).
    If FONT doesn't have such a glyph, return FONT_INVALID_CODE.
 
-   For speed, the gdi backend uses unicode (Emacs calls encode_char
+   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.
   */
@@ -354,7 +423,7 @@ w32font_encode_char (struct font *font, int c)
    of METRICS.  The glyphs are specified by their glyph codes in
    CODE (length NGLYPHS).  Apparently metrics can be NULL, in this
    case just return the overall width.  */
-int
+void
 w32font_text_extents (struct font *font, unsigned *code,
                      int nglyphs, struct font_metrics *metrics)
 {
@@ -365,89 +434,95 @@ w32font_text_extents (struct font *font, unsigned *code,
   int total_width = 0;
   WORD *wcode;
   SIZE size;
+  bool first;
 
   struct w32font_info *w32_font = (struct w32font_info *) font;
 
-  if (metrics)
-    {
-      memset (metrics, 0, sizeof (struct font_metrics));
-      metrics->ascent = font->ascent;
-      metrics->descent = font->descent;
+  memset (metrics, 0, sizeof (struct font_metrics));
 
-      for (i = 0; i < nglyphs; i++)
-        {
-         struct w32_metric_cache *char_metric;
-         int block = *(code + i) / CACHE_BLOCKSIZE;
-         int pos_in_block = *(code + i) % CACHE_BLOCKSIZE;
+  for (i = 0, first = true; i < nglyphs; i++)
+    {
+      struct w32_metric_cache *char_metric;
+      int block = *(code + i) / CACHE_BLOCKSIZE;
+      int pos_in_block = *(code + i) % CACHE_BLOCKSIZE;
 
-         if (block >= w32_font->n_cache_blocks)
-           {
-             if (!w32_font->cached_metrics)
-               w32_font->cached_metrics
-                 = xmalloc ((block + 1)
-                            * sizeof (struct w32_metric_cache *));
-             else
-               w32_font->cached_metrics
-                 = xrealloc (w32_font->cached_metrics,
-                             (block + 1)
-                             * 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 (block >= w32_font->n_cache_blocks)
+       {
+         if (!w32_font->cached_metrics)
+           w32_font->cached_metrics
+             = xmalloc ((block + 1)
+                        * sizeof (struct w32_metric_cache *));
+         else
+           w32_font->cached_metrics
+             = xrealloc (w32_font->cached_metrics,
+                         (block + 1)
+                         * 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 w32_metric_cache));
-             memset (w32_font->cached_metrics[block], 0,
-                     CACHE_BLOCKSIZE * sizeof (struct w32_metric_cache));
-           }
+      if (!w32_font->cached_metrics[block])
+       {
+         w32_font->cached_metrics[block]
+           = xzalloc (CACHE_BLOCKSIZE * sizeof (struct w32_metric_cache));
+       }
 
-         char_metric = w32_font->cached_metrics[block] + pos_in_block;
+      char_metric = w32_font->cached_metrics[block] + pos_in_block;
 
-         if (char_metric->status == W32METRIC_NO_ATTEMPT)
+      if (char_metric->status == W32METRIC_NO_ATTEMPT)
+       {
+         if (dc == NULL)
            {
-             if (dc == NULL)
-               {
-                 /* TODO: Frames can come and go, and their fonts
-                    outlive them. So we can't cache the frame in the
-                    font structure.  Use selected_frame until the API
-                    is updated to pass in a frame.  */
-                 f = XFRAME (selected_frame);
-
-                  dc = get_frame_dc (f);
-                  old_font = SelectObject (dc, w32_font->hfont);
-               }
-             compute_metrics (dc, w32_font, *(code + i), char_metric);
+             /* TODO: Frames can come and go, and their fonts
+                outlive them. So we can't cache the frame in the
+                font structure.  Use selected_frame until the API
+                is updated to pass in a frame.  */
+             f = XFRAME (selected_frame);
+
+             dc = get_frame_dc (f);
+             old_font = SelectObject (dc, w32_font->hfont);
            }
+         compute_metrics (dc, w32_font, *(code + i), char_metric);
+       }
 
-         if (char_metric->status == W32METRIC_SUCCESS)
+      if (char_metric->status == W32METRIC_SUCCESS)
+       {
+         if (first)
            {
-             metrics->lbearing = min (metrics->lbearing,
-                                      metrics->width + char_metric->lbearing);
-             metrics->rbearing = max (metrics->rbearing,
-                                      metrics->width + char_metric->rbearing);
-             metrics->width += char_metric->width;
+             metrics->lbearing = char_metric->lbearing;
+             metrics->rbearing = char_metric->rbearing;
+             metrics->width    = 0;
+             metrics->ascent   = char_metric->ascent;
+             metrics->descent  = char_metric->descent;
+             first = false;
            }
-         else
-           /* If we couldn't get metrics for a char,
-              use alternative method.  */
-           break;
+         if (metrics->lbearing > char_metric->lbearing)
+           metrics->lbearing = char_metric->lbearing;
+         if (metrics->rbearing < char_metric->rbearing)
+           metrics->rbearing = char_metric->rbearing;
+         metrics->width += char_metric->width;
+         if (metrics->ascent < char_metric->ascent)
+           metrics->ascent = char_metric->ascent;
+         if (metrics->descent < char_metric->descent)
+           metrics->descent = char_metric->descent;
        }
-      /* If we got through everything, return.  */
-      if (i == nglyphs)
-        {
-          if (dc != NULL)
-            {
-              /* Restore state and release DC.  */
-              SelectObject (dc, old_font);
-              release_frame_dc (f, dc);
-            }
-
-          return metrics->width;
-        }
+      else
+       /* If we couldn't get metrics for a char,
+          use alternative method.  */
+       break;
+    }
+  /* If we got through everything, return.  */
+  if (i == nglyphs)
+    {
+      if (dc != NULL)
+       {
+         /* Restore state and release DC.  */
+         SelectObject (dc, old_font);
+         release_frame_dc (f, dc);
+       }
+      return;
     }
 
   /* For non-truetype fonts, GetGlyphOutlineW is not supported, so
@@ -491,7 +566,7 @@ w32font_text_extents (struct font *font, unsigned *code,
       total_width = size.cx;
     }
 
-  /* On 95/98/ME, only some unicode functions are available, so fallback
+  /* On 95/98/ME, only some Unicode functions are available, so fallback
      on doing a dummy draw to find the total width.  */
   if (!total_width)
     {
@@ -503,26 +578,23 @@ w32font_text_extents (struct font *font, unsigned *code,
     }
 
   /* Give our best estimate of the metrics, based on what we know.  */
-  if (metrics)
-    {
-      metrics->width = total_width - w32_font->metrics.tmOverhang;
-      metrics->lbearing = 0;
-      metrics->rbearing = total_width;
-    }
+  metrics->width = total_width - w32_font->metrics.tmOverhang;
+  metrics->lbearing = 0;
+  metrics->rbearing = total_width;
+  metrics->ascent = font->ascent;
+  metrics->descent = font->descent;
 
   /* Restore state and release DC.  */
   SelectObject (dc, old_font);
   release_frame_dc (f, dc);
-
-  return total_width;
 }
 
 /* w32 implementation of draw for font backend.
    Optional.
    Draw glyphs between FROM and TO of S->char2b at (X Y) pixel
-   position of frame F with S->FACE and S->GC.  If WITH_BACKGROUND
-   is nonzero, fill the background in advance.  It is assured that
-   WITH_BACKGROUND is zero when (FROM > 0 || TO < S->nchars).
+   position of frame F with S->FACE and S->GC.  If WITH_BACKGROUND,
+   fill the background in advance.  It is assured that WITH_BACKGROUND
+   is false when (FROM > 0 || TO < S->nchars).
 
    TODO: Currently this assumes that the colors and fonts are already
    set in the DC. This seems to be true now, but maybe only due to
@@ -532,10 +604,11 @@ w32font_text_extents (struct font *font, unsigned *code,
 
 int
 w32font_draw (struct glyph_string *s, int from, int to,
-             int x, int y, int with_background)
+             int x, int y, bool with_background)
 {
   UINT options;
   HRGN orig_clip = NULL;
+  int len = to - from;
   struct w32font_info *w32font = (struct w32font_info *) s->font;
 
   options = w32font->glyph_idx;
@@ -572,26 +645,45 @@ w32font_draw (struct glyph_string *s, int from, int to,
       HBRUSH brush;
       RECT rect;
       struct font *font = s->font;
-
+      int ascent = font->ascent, descent = font->descent;
+
+      /* Font's global ascent and descent values might be
+        preposterously large for some fonts.  We fix here the case
+        when those fonts are used for display of glyphless
+        characters, because drawing background with font dimensions
+        in those cases makes the display illegible.  There's only one
+        more call to the draw method with with_background set to
+        true, and that's in x_draw_glyph_string_foreground, when
+        drawing the cursor, where we have no such heuristics
+        available.  FIXME.  */
+      if (s->first_glyph->type == GLYPHLESS_GLYPH
+         && (s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE
+             || s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM))
+       {
+         ascent =
+           s->first_glyph->slice.glyphless.lower_yoff
+           - s->first_glyph->slice.glyphless.upper_yoff;
+         descent = 0;
+       }
       brush = CreateSolidBrush (s->gc->background);
       rect.left = x;
-      rect.top = y - font->ascent;
+      rect.top = y - ascent;
       rect.right = x + s->width;
-      rect.bottom = y + font->descent;
+      rect.bottom = y + descent;
       FillRect (s->hdc, &rect, brush);
       DeleteObject (brush);
     }
 
   if (s->padding_p)
     {
-      int len = to - from, i;
+      int i;
 
       for (i = 0; i < len; i++)
        ExtTextOutW (s->hdc, x + i, y, options, NULL,
                     s->char2b + from + i, 1, NULL);
     }
   else
-    ExtTextOutW (s->hdc, x, y, options, NULL, s->char2b + from, to - from, NULL);
+    ExtTextOutW (s->hdc, x, y, options, NULL, s->char2b + from, len, NULL);
 
   /* Restore clip region.  */
   if (s->num_clips > 0)
@@ -599,6 +691,8 @@ w32font_draw (struct glyph_string *s, int from, int to,
 
   if (orig_clip)
     DeleteObject (orig_clip);
+
+  return len;
 }
 
 /* w32 implementation of free_entity for font backend.
@@ -614,13 +708,13 @@ w32font_free_entity (Lisp_Object entity);
    storing some data in FACE->extra.  If successful, return 0.
    Otherwise, return -1.
 static int
-w32font_prepare_face (FRAME_PTR f, struct face *face);
+w32font_prepare_face (struct frame *f, struct face *face);
   */
 /* w32 implementation of done_face for font backend.
    Optional.
    Done FACE for displaying characters by FACE->font on frame F.
 static void
-w32font_done_face (FRAME_PTR f, struct face *face);  */
+w32font_done_face (struct frame *f, struct face *face);  */
 
 /* w32 implementation of get_bitmap for font backend.
    Optional.
@@ -637,24 +731,11 @@ w32font_get_bitmap (struct font *font, unsigned code,
 static void
 w32font_free_bitmap (struct font *font, struct font_bitmap *bitmap);
   */
-/* w32 implementation of get_outline for font backend.
-   Optional.
-   Return an outline data for glyph-code CODE of FONT.  The format
-   of the outline data depends on the font-driver.
-static void *
-w32font_get_outline (struct font *font, unsigned code);
-  */
-/* w32 implementation of free_outline for font backend.
-   Optional.
-   Free OUTLINE (that is obtained by the above method).
-static void
-w32font_free_outline (struct font *font, void *outline);
-  */
 /* w32 implementation of anchor_point for font backend.
    Optional.
    Get coordinates of the INDEXth anchor point of the glyph whose
    code is CODE.  Store the coordinates in *X and *Y.  Return 0 if
-   the operations was successfull.  Otherwise return -1.
+   the operations was successful.  Otherwise return -1.
 static int
 w32font_anchor_point (struct font *font, unsigned code,
                                  int index, int *x, int *y);
@@ -686,22 +767,22 @@ static int
 w32font_otf_drive (struct font *font, Lisp_Object features,
                    Lisp_Object gstring_in, int from, int to,
                    Lisp_Object gstring_out, int idx,
-                   int alternate_subst);
+                   bool alternate_subst);
   */
 
 /* Internal implementation of w32font_list.
    Additional parameter opentype_only restricts the returned fonts to
    opentype fonts, which can be used with the Uniscribe backend.  */
 Lisp_Object
-w32font_list_internal (Lisp_Object frame, Lisp_Object font_spec, int opentype_only)
+w32font_list_internal (struct frame *f, Lisp_Object font_spec,
+                      bool opentype_only)
 {
   struct font_callback_data match_data;
   HDC dc;
-  FRAME_PTR f = XFRAME (frame);
 
   match_data.orig_font_spec = font_spec;
   match_data.list = Qnil;
-  match_data.frame = frame;
+  XSETFRAME (match_data.frame, f);
 
   memset (&match_data.pattern, 0, sizeof (LOGFONT));
   fill_in_logfont (f, &match_data.pattern, font_spec);
@@ -715,7 +796,8 @@ w32font_list_internal (Lisp_Object frame, Lisp_Object font_spec, int opentype_on
          && !EQ (spec_charset, Qiso10646_1)
          && !EQ (spec_charset, Qunicode_bmp)
          && !EQ (spec_charset, Qunicode_sip)
-         && !EQ (spec_charset, Qunknown))
+         && !EQ (spec_charset, Qunknown)
+         && !EQ (spec_charset, Qascii_0))
        return Qnil;
     }
 
@@ -746,14 +828,14 @@ w32font_list_internal (Lisp_Object frame, Lisp_Object font_spec, int opentype_on
    Additional parameter opentype_only restricts the returned fonts to
    opentype fonts, which can be used with the Uniscribe backend.  */
 Lisp_Object
-w32font_match_internal (Lisp_Object frame, Lisp_Object font_spec, int opentype_only)
+w32font_match_internal (struct frame *f, Lisp_Object font_spec,
+                       bool opentype_only)
 {
   struct font_callback_data match_data;
   HDC dc;
-  FRAME_PTR f = XFRAME (frame);
 
   match_data.orig_font_spec = font_spec;
-  match_data.frame = frame;
+  XSETFRAME (match_data.frame, f);
   match_data.list = Qnil;
 
   memset (&match_data.pattern, 0, sizeof (LOGFONT));
@@ -774,14 +856,14 @@ w32font_match_internal (Lisp_Object frame, Lisp_Object font_spec, int opentype_o
 }
 
 int
-w32font_open_internal (FRAME_PTR f, Lisp_Object font_entity,
+w32font_open_internal (struct frame *f, Lisp_Object font_entity,
                       int pixel_size, Lisp_Object font_object)
 {
-  int len, size, i;
+  int len, size;
   LOGFONT logfont;
   HDC dc;
   HFONT hfont, old_font;
-  Lisp_Object val, extra;
+  Lisp_Object val;
   struct w32font_info *w32_font;
   struct font * font;
   OUTLINETEXTMETRICW* metrics = NULL;
@@ -816,11 +898,11 @@ w32font_open_internal (FRAME_PTR f, Lisp_Object font_entity,
   old_font = SelectObject (dc, hfont);
 
   /* Try getting the outline metrics (only works for truetype fonts).  */
-  len = GetOutlineTextMetricsW (dc, 0, NULL);
+  len = get_outline_metrics_w (dc, 0, NULL);
   if (len)
     {
       metrics = (OUTLINETEXTMETRICW *) alloca (len);
-      if (GetOutlineTextMetricsW (dc, len, metrics))
+      if (get_outline_metrics_w (dc, len, metrics))
         memcpy (&w32_font->metrics, &metrics->otmTextMetrics,
                sizeof (TEXTMETRICW));
       else
@@ -828,7 +910,7 @@ w32font_open_internal (FRAME_PTR f, Lisp_Object font_entity,
     }
 
   if (!metrics)
-    GetTextMetricsW (dc, &w32_font->metrics);
+    get_text_metrics_w (dc, &w32_font->metrics);
 
   w32_font->cached_metrics = NULL;
   w32_font->n_cache_blocks = 0;
@@ -869,28 +951,11 @@ w32font_open_internal (FRAME_PTR f, Lisp_Object font_entity,
   font->space_width = font->average_width = w32_font->metrics.tmAveCharWidth;
 
   font->vertical_centering = 0;
-  font->encoding_type = 0;
   font->baseline_offset = 0;
   font->relative_compose = 0;
   font->default_ascent = w32_font->metrics.tmAscent;
-  font->font_encoder = NULL;
   font->pixel_size = size;
   font->driver = &w32font_driver;
-  /* Use format cached during list, as the information we have access to
-     here is incomplete.  */
-  extra = AREF (font_entity, FONT_EXTRA_INDEX);
-  if (CONSP (extra))
-    {
-      val = assq_no_quit (QCformat, extra);
-      if (CONSP (val))
-        font->props[FONT_FORMAT_INDEX] = XCDR (val);
-      else
-        font->props[FONT_FORMAT_INDEX] = Qunknown;
-    }
-  else
-    font->props[FONT_FORMAT_INDEX] = Qunknown;
-
-  font->props[FONT_FILE_INDEX] = Qnil;
   font->encoding_charset = -1;
   font->repertory_charset = -1;
   /* TODO: do we really want the minimum width here, which could be negative? */
@@ -921,7 +986,7 @@ w32font_open_internal (FRAME_PTR f, Lisp_Object font_entity,
 
 /* Callback function for EnumFontFamiliesEx.
  * Adds the name of a font to a Lisp list (passed in as the lParam arg).  */
-static int CALLBACK
+static int CALLBACK ALIGN_STACK
 add_font_name_to_list (ENUMLOGFONTEX *logical_font,
                       NEWTEXTMETRICEX *physical_font,
                       DWORD font_type, LPARAM list_object)
@@ -1021,7 +1086,7 @@ w32_enumfont_pattern_entity (Lisp_Object frame,
   else
     ASET (entity, FONT_SIZE_INDEX, make_number (0));
 
-  /* Cache unicode codepoints covered by this font, as there is no other way
+  /* Cache Unicode codepoints covered by this font, as there is no other way
      of getting this information easily.  */
   if (font_type & TRUETYPE_FONTTYPE)
     {
@@ -1036,11 +1101,11 @@ w32_enumfont_pattern_entity (Lisp_Object frame,
      truetype so that this information is not any worse than we could
      have obtained later.  */
   if (EQ (backend, Quniscribe) && (full_type & NTMFLAGS_OPENTYPE))
-    tem = intern ("opentype");
+    tem = Qopentype;
   else if (font_type & TRUETYPE_FONTTYPE)
     tem = intern ("truetype");
   else if (full_type & NTM_PS_OPENTYPE)
-    tem = intern ("postscript");
+    tem = Qpostscript;
   else if (full_type & NTM_TYPE1)
     tem = intern ("type1");
   else if (font_type & RASTER_FONTTYPE)
@@ -1152,14 +1217,23 @@ font_matches_spec (DWORD type, NEWTEXTMETRICEX *font,
             {
               /* Only truetype fonts will have information about what
                  scripts they support.  This probably means the user
-                 will have to force Emacs to use raster, postscript
-                 or atm fonts for non-ASCII text.  */
+                 will have to force Emacs to use raster, PostScript
+                 or ATM fonts for non-ASCII text.  */
               if (type & TRUETYPE_FONTTYPE)
                 {
                   Lisp_Object support
                     = font_supported_scripts (&font->ntmFontSig);
                   if (! memq_no_quit (val, support))
                     return 0;
+
+                 /* Avoid using non-Japanese fonts for Japanese, even
+                    if they claim they are capable, due to known
+                    breakage in Vista and Windows 7 fonts
+                    (bug#6029).  */
+                 if (EQ (val, Qkana)
+                     && (font->ntmTm.tmCharSet != SHIFTJIS_CHARSET
+                         || !(font->ntmFontSig.fsCsb[0] & CSB_JAPANESE)))
+                   return 0;
                 }
               else
                 {
@@ -1263,7 +1337,7 @@ font_matches_spec (DWORD type, NEWTEXTMETRICEX *font,
                    currently appear in fontset.el, so it isn't worth
                    creating a mapping table of codepages/scripts to languages
                    or opening the font to see if there are any language tags
-                   in it that the W32 API does not expose. Fontset
+                   in it that the Windows API does not expose. Fontset
                   spec should have a fallback, as some backends do
                   not recognize language at all.  */
                return 0;
@@ -1309,6 +1383,9 @@ w32font_coverage_ok (FONTSIGNATURE * coverage, BYTE charset)
   return 1;
 }
 
+#ifndef WINDOWSNT
+#define _strlwr strlwr
+#endif /* !WINDOWSNT */
 
 static int
 check_face_name (LOGFONT *font, char *full_name)
@@ -1323,7 +1400,7 @@ check_face_name (LOGFONT *font, char *full_name)
   /* 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
+     with Arial's characteristics, since that attempt to use TrueType works
      some places, but not others.  */
   if (!xstrcasecmp (font->lfFaceName, "helvetica"))
     {
@@ -1351,11 +1428,11 @@ check_face_name (LOGFONT *font, char *full_name)
 
 
 /* Callback function for EnumFontFamiliesEx.
- * Checks if a font matches everything we are trying to check agaist,
+ * Checks if a font matches everything we are trying to check against,
  * 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
+static int CALLBACK ALIGN_STACK
 add_font_entity_to_list (ENUMLOGFONTEX *logical_font,
                         NEWTEXTMETRICEX *physical_font,
                         DWORD font_type, LPARAM lParam)
@@ -1373,9 +1450,9 @@ add_font_entity_to_list (ENUMLOGFONTEX *logical_font,
   /* Skip non matching fonts.  */
 
   /* For uniscribe backend, consider only truetype or opentype fonts
-     that have some unicode coverage.  */
+     that have some Unicode coverage.  */
   if (match_data->opentype_only
-      && ((!physical_font->ntmTm.ntmFlags & NTMFLAGS_OPENTYPE
+      && ((!(physical_font->ntmTm.ntmFlags & NTMFLAGS_OPENTYPE)
           && !(font_type & TRUETYPE_FONTTYPE))
          || !is_unicode))
     return 1;
@@ -1397,12 +1474,12 @@ add_font_entity_to_list (ENUMLOGFONTEX *logical_font,
      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,
+       && !strstr ((char *)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)))
+                           (char *)logical_font->elfFullName)))
     return 1;
 
   /* Make a font entity for the font.  */
@@ -1416,7 +1493,7 @@ add_font_entity_to_list (ENUMLOGFONTEX *logical_font,
       Lisp_Object spec_charset = AREF (match_data->orig_font_spec,
                                       FONT_REGISTRY_INDEX);
 
-      /* iso10646-1 fonts must contain unicode mapping tables.  */
+      /* iso10646-1 fonts must contain Unicode mapping tables.  */
       if (EQ (spec_charset, Qiso10646_1))
        {
          if (!is_unicode)
@@ -1431,13 +1508,13 @@ add_font_entity_to_list (ENUMLOGFONTEX *logical_font,
              && !(physical_font->ntmFontSig.fsUsb[0] & 0x007F001F))
            return 1;
        }
-      /* unicode-sip fonts must contain characters in unicode plane 2.
+      /* 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)
+         if (!(physical_font->ntmFontSig.fsUsb[1] & 0x02000000)
+             || !(physical_font->ntmFontSig.fsUsb[1] & 0x28000000))
            return 1;
        }
 
@@ -1445,10 +1522,18 @@ add_font_entity_to_list (ENUMLOGFONTEX *logical_font,
 
       /* If registry was specified, ensure it is reported as the same.  */
       if (!NILP (spec_charset))
-       ASET (entity, FONT_REGISTRY_INDEX, spec_charset);
-
+       {
+         /* Avoid using non-Japanese fonts for Japanese, even if they
+            claim they are capable, due to known breakage in Vista
+            and Windows 7 fonts (bug#6029).  */
+         if (logical_font->elfLogFont.lfCharSet == SHIFTJIS_CHARSET
+             && !(physical_font->ntmFontSig.fsCsb[0] & CSB_JAPANESE))
+           return 1;
+         else
+           ASET (entity, FONT_REGISTRY_INDEX, spec_charset);
+       }
       /* Otherwise if using the uniscribe backend, report ANSI and DEFAULT
-        fonts as unicode and skip other charsets.  */
+        fonts as Unicode and skip other charsets.  */
       else if (match_data->opentype_only)
        {
          if (logical_font->elfLogFont.lfCharSet == ANSI_CHARSET
@@ -1466,7 +1551,7 @@ add_font_entity_to_list (ENUMLOGFONTEX *logical_font,
 
 /* Callback function for EnumFontFamiliesEx.
  * Terminates the search once we have a match. */
-static int CALLBACK
+static int CALLBACK ALIGN_STACK
 add_one_font_entity_to_list (ENUMLOGFONTEX *logical_font,
                             NEWTEXTMETRICEX *physical_font,
                             DWORD font_type, LPARAM lParam)
@@ -1491,7 +1576,7 @@ x_to_w32_charset (char * lpcs)
   if (strncmp (lpcs, "*-#", 3) == 0)
     return atoi (lpcs + 3);
 
-  /* All Windows fonts qualify as unicode.  */
+  /* All Windows fonts qualify as Unicode.  */
   if (!strncmp (lpcs, "iso10646", 8))
     return DEFAULT_CHARSET;
 
@@ -1571,7 +1656,7 @@ registry_to_w32_charset (Lisp_Object charset)
   else if (EQ (charset, Qiso8859_1))
     return ANSI_CHARSET;
   else if (SYMBOLP (charset))
-    return x_to_w32_charset (SDATA (SYMBOL_NAME (charset)));
+    return x_to_w32_charset (SSDATA (SYMBOL_NAME (charset)));
   else
     return DEFAULT_CHARSET;
 }
@@ -1693,7 +1778,7 @@ w32_to_x_charset (int fncharset, char *matching)
             || !SYMBOLP (XCAR (XCDR (this_entry))))
           continue;
 
-        x_charset = SDATA (XCAR (this_entry));
+        x_charset = SSDATA (XCAR (this_entry));
         w32_charset = XCAR (XCDR (this_entry));
         codepage = XCDR (XCDR (this_entry));
 
@@ -1776,7 +1861,7 @@ w32_registry (LONG w32_charset, DWORD font_type)
 {
   char *charset;
 
-  /* If charset is defaulted, charset is unicode or unknown, depending on
+  /* If charset is defaulted, charset is Unicode or unknown, depending on
      font type.  */
   if (w32_charset == DEFAULT_CHARSET)
     return font_type == TRUETYPE_FONTTYPE ? Qiso10646_1 : Qunknown;
@@ -1819,18 +1904,18 @@ static Lisp_Object
 w32_to_fc_weight (int n)
 {
   if (n >= FW_EXTRABOLD) return intern ("black");
-  if (n >= FW_BOLD)      return intern ("bold");
+  if (n >= FW_BOLD)      return Qbold;
   if (n >= FW_SEMIBOLD)  return intern ("demibold");
   if (n >= FW_NORMAL)    return intern ("medium");
-  return intern ("light");
+  return Qlight;
 }
 
 /* Fill in all the available details of LOGFONT from FONT_SPEC.  */
 static void
-fill_in_logfont (FRAME_PTR f, LOGFONT *logfont, Lisp_Object font_spec)
+fill_in_logfont (struct frame *f, LOGFONT *logfont, Lisp_Object font_spec)
 {
   Lisp_Object tmp, extra;
-  int dpi = FRAME_W32_DISPLAY_INFO (f)->resy;
+  int dpi = FRAME_RES_Y (f);
 
   tmp = AREF (font_spec, FONT_DPI_INDEX);
   if (INTEGERP (tmp))
@@ -1896,8 +1981,11 @@ fill_in_logfont (FRAME_PTR f, LOGFONT *logfont, Lisp_Object font_spec)
         /* Font families are interned, but allow for strings also in case of
            user input.  */
       else if (SYMBOLP (tmp))
-        strncpy (logfont->lfFaceName,
-                SDATA (ENCODE_SYSTEM (SYMBOL_NAME (tmp))), LF_FACESIZE);
+       {
+         strncpy (logfont->lfFaceName,
+                  SSDATA (ENCODE_SYSTEM (SYMBOL_NAME (tmp))), LF_FACESIZE);
+         logfont->lfFaceName[LF_FACESIZE-1] = '\0';
+       }
     }
 
   tmp = AREF (font_spec, FONT_ADSTYLE_INDEX);
@@ -1916,10 +2004,10 @@ fill_in_logfont (FRAME_PTR f, LOGFONT *logfont, Lisp_Object font_spec)
       int spacing = XINT (tmp);
       if (spacing < FONT_SPACING_MONO)
        logfont->lfPitchAndFamily
-         = logfont->lfPitchAndFamily & 0xF0 | VARIABLE_PITCH;
+         = (logfont->lfPitchAndFamily & 0xF0) | VARIABLE_PITCH;
       else
        logfont->lfPitchAndFamily
-         = logfont->lfPitchAndFamily & 0xF0 | FIXED_PITCH;
+         = (logfont->lfPitchAndFamily & 0xF0) | FIXED_PITCH;
     }
 
   /* Process EXTRA info.  */
@@ -1931,7 +2019,7 @@ fill_in_logfont (FRAME_PTR f, LOGFONT *logfont, Lisp_Object font_spec)
         {
           Lisp_Object key, val;
           key = XCAR (tmp), val = XCDR (tmp);
-          /* Only use QCscript if charset is not provided, or is unicode
+          /* Only use QCscript if charset is not provided, or is Unicode
              and a single script is specified.  This is rather crude,
              and is only used to narrow down the fonts returned where
              there is a definite match.  Some scripts, such as latin, han,
@@ -1974,7 +2062,7 @@ static void
 list_all_matching_fonts (struct font_callback_data *match_data)
 {
   HDC dc;
-  Lisp_Object families = w32font_list_family (match_data->frame);
+  Lisp_Object families = w32font_list_family (XFRAME (match_data->frame));
   struct frame *f = XFRAME (match_data->frame);
 
   dc = get_frame_dc (f);
@@ -1991,7 +2079,7 @@ list_all_matching_fonts (struct font_callback_data *match_data)
       if (NILP (family))
         continue;
       else if (SYMBOLP (family))
-        name = SDATA (ENCODE_SYSTEM (SYMBOL_NAME (family)));
+        name = SSDATA (ENCODE_SYSTEM (SYMBOL_NAME (family)));
       else
        continue;
 
@@ -2068,17 +2156,31 @@ font_supported_scripts (FONTSIGNATURE * sig)
     supported = Fcons ((sym), supported)
 
   SUBRANGE (0, Qlatin);
-  /* The following count as latin too, ASCII should be present in these fonts,
-     so don't need to mark them separately.  */
   /* 1: Latin-1 supplement, 2: Latin Extended A, 3: Latin Extended B.  */
+  /* Most fonts that support Latin will have good coverage of the
+     Extended blocks, so in practice marking them below is not really
+     needed, or useful: if a font claims support for, say, Latin
+     Extended-B, but does not contain glyphs for some of the
+     characters in the range, the user will have to augment her
+     fontset to display those few characters.  But we mark these
+     subranges here anyway, for the marginal use cases where they
+     might make a difference.  */
+  SUBRANGE (1, Qlatin);
+  SUBRANGE (2, Qlatin);
+  SUBRANGE (3, Qlatin);
   SUBRANGE (4, Qphonetic);
-  /* 5: Spacing and tone modifiers, 6: Combining Diacriticals.  */
+  /* 5: Spacing and tone modifiers, 6: Combining Diacritical Marks.  */
   SUBRANGE (7, Qgreek);
   SUBRANGE (8, Qcoptic);
   SUBRANGE (9, Qcyrillic);
   SUBRANGE (10, Qarmenian);
   SUBRANGE (11, Qhebrew);
-  /* 12: Vai.  */
+  /* Bit 12 is rather useless if the user has Hebrew fonts installed,
+     because apparently at some point in the past bit 12 was "Hebrew
+     Extended", and many Hebrew fonts still have this bit set.  The
+     only workaround is to customize fontsets to use fonts like Ebrima
+     or Quivira.  */
+  SUBRANGE (12, Qvai);
   SUBRANGE (13, Qarabic);
   SUBRANGE (14, Qnko);
   SUBRANGE (15, Qdevanagari);
@@ -2094,8 +2196,11 @@ font_supported_scripts (FONTSIGNATURE * sig)
   SUBRANGE (25, Qlao);
   SUBRANGE (26, Qgeorgian);
   SUBRANGE (27, Qbalinese);
-  /* 28: Hangul Jamo.  */
-  /* 29: Latin Extended, 30: Greek Extended, 31: Punctuation.  */
+  /* 28: Hangul Jamo -- covered by the default fontset.  */
+  /* 29: Latin Extended, 30: Greek Extended -- covered above.  */
+  /* 31: Supplemental Punctuation -- most probably be masked by
+     Courier New, so fontset customization is needed.  */
+  SUBRANGE (31, Qsymbol);
   /* 32-47: Symbols (defined below).  */
   SUBRANGE (48, Qcjk_misc);
   /* Match either 49: katakana or 50: hiragana for kana.  */
@@ -2110,6 +2215,9 @@ font_supported_scripts (FONTSIGNATURE * sig)
   SUBRANGE (59, Qhan); /* There are others, but this is the main one.  */
   SUBRANGE (59, Qideographic_description); /* Windows lumps this in.  */
   SUBRANGE (59, Qkanbun); /* And this.  */
+  /* These are covered well either by the default Courier New or by
+     CJK fonts that are set up specially in the default fontset.  So
+     marking them here wouldn't be useful.  */
   /* 60: Private use, 61: CJK strokes and compatibility.  */
   /* 62: Alphabetic Presentation, 63: Arabic Presentation A.  */
   /* 64: Combining half marks, 65: Vertical and CJK compatibility.  */
@@ -2138,31 +2246,54 @@ font_supported_scripts (FONTSIGNATURE * sig)
   SUBRANGE (87, Qdeseret);
   SUBRANGE (88, Qbyzantine_musical_symbol);
   SUBRANGE (88, Qmusical_symbol); /* Windows doesn't distinguish these.  */
-  SUBRANGE (89, Qmathematical);
+  SUBRANGE (89, Qmathematical_bold); /* See fontset.el:setup-default-fontset.  */
+  SUBRANGE (89, Qmathematical_italic);
+  SUBRANGE (89, Qmathematical_bold_italic);
+  SUBRANGE (89, Qmathematical_script);
+  SUBRANGE (89, Qmathematical_bold_script);
+  SUBRANGE (89, Qmathematical_fraktur);
+  SUBRANGE (89, Qmathematical_double_struck);
+  SUBRANGE (89, Qmathematical_bold_fraktur);
+  SUBRANGE (89, Qmathematical_sans_serif);
+  SUBRANGE (89, Qmathematical_sans_serif_bold);
+  SUBRANGE (89, Qmathematical_sans_serif_italic);
+  SUBRANGE (89, Qmathematical_sans_serif_bold_italic);
+  SUBRANGE (89, Qmathematical_monospace);
   /* 90: Private use, 91: Variation selectors, 92: Tags.  */
   SUBRANGE (93, Qlimbu);
   SUBRANGE (94, Qtai_le);
-  /* 95: New Tai Le */
-  SUBRANGE (90, Qbuginese);
+  SUBRANGE (95, Qtai_le);
+  SUBRANGE (96, Qbuginese);
   SUBRANGE (97, Qglagolitic);
   SUBRANGE (98, Qtifinagh);
   /* 99: Yijing Hexagrams.  */
+  SUBRANGE (99, Qhan);
   SUBRANGE (100, Qsyloti_nagri);
   SUBRANGE (101, Qlinear_b);
-  /* 102: Ancient Greek Numbers.  */
+  SUBRANGE (102, Qancient_greek_number);
   SUBRANGE (103, Qugaritic);
   SUBRANGE (104, Qold_persian);
   SUBRANGE (105, Qshavian);
   SUBRANGE (106, Qosmanya);
   SUBRANGE (107, Qcypriot);
   SUBRANGE (108, Qkharoshthi);
-  /* 109: Tai Xuan Jing.  */
+  SUBRANGE (109, Qtai_xuan_jing_symbol);
   SUBRANGE (110, Qcuneiform);
-  /* 111: Counting Rods, 112: Sundanese, 113: Lepcha, 114: Ol Chiki.  */
-  /* 115: Saurashtra, 116: Kayah Li, 117: Rejang.  */
+  SUBRANGE (111, Qcounting_rod_numeral);
+  SUBRANGE (112, Qsundanese);
+  SUBRANGE (113, Qlepcha);
+  SUBRANGE (114, Qol_chiki);
+  SUBRANGE (115, Qsaurashtra);
+  SUBRANGE (116, Qkayah_li);
+  SUBRANGE (117, Qrejang);
   SUBRANGE (118, Qcham);
-  /* 119: Ancient symbols, 120: Phaistos Disc.  */
-  /* 121: Carian, Lycian, Lydian, 122: Dominos, Mah Jong tiles.  */
+  SUBRANGE (119, Qancient_symbol);
+  SUBRANGE (120, Qphaistos_disc);
+  SUBRANGE (121, Qlycian);
+  SUBRANGE (121, Qcarian);
+  SUBRANGE (121, Qlydian);
+  SUBRANGE (122, Qdomino_tile);
+  SUBRANGE (122, Qmahjong_tile);
   /* 123-127: Reserved.  */
 
   /* There isn't really a main symbol range, so include symbol if any
@@ -2298,6 +2429,7 @@ compute_metrics (HDC dc, struct w32font_info *w32_font, unsigned int code,
   GLYPHMETRICS gm;
   MAT2 transform;
   unsigned int options = GGO_METRICS;
+  INT width;
 
   if (w32_font->glyph_idx)
     options |= GGO_GLYPH_INDEX;
@@ -2306,12 +2438,23 @@ compute_metrics (HDC dc, struct w32font_info *w32_font, unsigned int code,
   transform.eM11.value = 1;
   transform.eM22.value = 1;
 
-  if (GetGlyphOutlineW (dc, code, options, &gm, 0, NULL, &transform)
+  if (get_glyph_outline_w (dc, code, options, &gm, 0, NULL, &transform)
       != GDI_ERROR)
     {
       metrics->lbearing = gm.gmptGlyphOrigin.x;
       metrics->rbearing = gm.gmptGlyphOrigin.x + gm.gmBlackBoxX;
       metrics->width = gm.gmCellIncX;
+      metrics->ascent = gm.gmptGlyphOrigin.y;
+      metrics->descent = gm.gmBlackBoxY - gm.gmptGlyphOrigin.y;
+      metrics->status = W32METRIC_SUCCESS;
+    }
+  else if (get_char_width_32_w (dc, code, code, &width) != 0)
+    {
+      metrics->lbearing = 0;
+      metrics->rbearing = width;
+      metrics->width = width;
+      metrics->ascent = w32_font->font.ascent;
+      metrics->descent = w32_font->font.descent;
       metrics->status = W32METRIC_SUCCESS;
     }
   else
@@ -2327,7 +2470,7 @@ If EXCLUDE-PROPORTIONAL is non-nil, exclude proportional fonts
 in the font selection dialog. */)
   (Lisp_Object frame, Lisp_Object exclude_proportional)
 {
-  FRAME_PTR f = check_x_frame (frame);
+  struct frame *f = decode_window_system_frame (frame);
   CHOOSEFONT cf;
   LOGFONT lf;
   TEXTMETRIC tm;
@@ -2393,8 +2536,8 @@ w32font_filter_properties (Lisp_Object font, Lisp_Object alist)
 
 struct font_driver w32font_driver =
   {
-    0, /* Qgdi */
-    0, /* case insensitive */
+    LISP_INITIALLY_ZERO, /* Qgdi */
+    false, /* case insensitive */
     w32font_get_cache,
     w32font_list,
     w32font_match,
@@ -2410,8 +2553,6 @@ struct font_driver w32font_driver =
     w32font_draw,
     NULL, /* get_bitmap */
     NULL, /* free_bitmap */
-    NULL, /* get_outline */
-    NULL, /* free_outline */
     NULL, /* anchor_point */
     NULL, /* otf_capability */
     NULL, /* otf_drive */
@@ -2421,6 +2562,7 @@ struct font_driver w32font_driver =
     NULL, /* check */
     NULL, /* get_variation_glyphs */
     w32font_filter_properties,
+    NULL, /* cached_font_ok */
   };
 
 
@@ -2464,6 +2606,7 @@ syms_of_w32font (void)
   DEFSYM (Qcyrillic, "cyrillic");
   DEFSYM (Qarmenian, "armenian");
   DEFSYM (Qhebrew, "hebrew");
+  DEFSYM (Qvai, "vai");
   DEFSYM (Qarabic, "arabic");
   DEFSYM (Qsyriac, "syriac");
   DEFSYM (Qnko, "nko");
@@ -2491,7 +2634,6 @@ syms_of_w32font (void)
   DEFSYM (Qrunic, "runic");
   DEFSYM (Qkhmer, "khmer");
   DEFSYM (Qmongolian, "mongolian");
-  DEFSYM (Qsymbol, "symbol");
   DEFSYM (Qbraille, "braille");
   DEFSYM (Qhan, "han");
   DEFSYM (Qideographic_description, "ideographic-description");
@@ -2502,7 +2644,19 @@ syms_of_w32font (void)
   DEFSYM (Qyi, "yi");
   DEFSYM (Qbyzantine_musical_symbol, "byzantine-musical-symbol");
   DEFSYM (Qmusical_symbol, "musical-symbol");
-  DEFSYM (Qmathematical, "mathematical");
+  DEFSYM (Qmathematical_bold, "mathematical-bold");
+  DEFSYM (Qmathematical_italic, "mathematical-italic");
+  DEFSYM (Qmathematical_bold_italic, "mathematical-bold-italic");
+  DEFSYM (Qmathematical_script, "mathematical-script");
+  DEFSYM (Qmathematical_bold_script, "mathematical-bold-script");
+  DEFSYM (Qmathematical_fraktur, "mathematical-fraktur");
+  DEFSYM (Qmathematical_double_struck, "mathematical-double-struck");
+  DEFSYM (Qmathematical_bold_fraktur, "mathematical-bold-fraktur");
+  DEFSYM (Qmathematical_sans_serif, "mathematical-sans-serif");
+  DEFSYM (Qmathematical_sans_serif_bold, "mathematical-sans-serif-bold");
+  DEFSYM (Qmathematical_sans_serif_italic, "mathematical-sans-serif-italic");
+  DEFSYM (Qmathematical_sans_serif_bold_italic, "mathematical-sans-serif-bold-italic");
+  DEFSYM (Qmathematical_monospace, "mathematical-monospace");
   DEFSYM (Qcham, "cham");
   DEFSYM (Qphonetic, "phonetic");
   DEFSYM (Qbalinese, "balinese");
@@ -2529,6 +2683,22 @@ syms_of_w32font (void)
   DEFSYM (Qtai_le, "tai_le");
   DEFSYM (Qtifinagh, "tifinagh");
   DEFSYM (Qugaritic, "ugaritic");
+  DEFSYM (Qlycian, "lycian");
+  DEFSYM (Qcarian, "carian");
+  DEFSYM (Qlydian, "lydian");
+  DEFSYM (Qdomino_tile, "domino-tile");
+  DEFSYM (Qmahjong_tile, "mahjong-tile");
+  DEFSYM (Qtai_xuan_jing_symbol, "tai-xuan-jing-symbol");
+  DEFSYM (Qcounting_rod_numeral, "counting-rod-numeral");
+  DEFSYM (Qancient_symbol, "ancient-symbol");
+  DEFSYM (Qphaistos_disc, "phaistos-disc");
+  DEFSYM (Qancient_greek_number, "ancient-greek-number");
+  DEFSYM (Qsundanese, "sundanese");
+  DEFSYM (Qlepcha, "lepcha");
+  DEFSYM (Qol_chiki, "ol-chiki");
+  DEFSYM (Qsaurashtra, "saurashtra");
+  DEFSYM (Qkayah_li, "kayah-li");
+  DEFSYM (Qrejang, "rejang");
 
   /* W32 font encodings.  */
   DEFVAR_LISP ("w32-charset-info-alist",
@@ -2581,3 +2751,13 @@ versions of Windows) characters.  */);
   register_font_driver (&w32font_driver, NULL);
 }
 
+void
+globals_of_w32font (void)
+{
+#ifdef WINDOWSNT
+  g_b_init_get_outline_metrics_w = 0;
+  g_b_init_get_text_metrics_w = 0;
+  g_b_init_get_glyph_outline_w = 0;
+  g_b_init_get_char_width_32_w = 0;
+#endif
+}