Merge from emacs--rel--22
[bpt/emacs.git] / src / w32font.c
index e8e9b4c..e2973db 100644 (file)
@@ -1,11 +1,11 @@
 /* Font backend for the Microsoft W32 API.
-   Copyright (C) 2007 Free Software Foundation, Inc.
+   Copyright (C) 2007, 2008 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 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -29,6 +29,7 @@ Boston, MA 02110-1301, USA.  */
 #include "charset.h"
 #include "fontset.h"
 #include "font.h"
+#include "w32font.h"
 
 /* Cleartype available on Windows XP, cleartype_natural from XP SP1.
    The latter does not try to fit cleartype smoothed fonts into the
@@ -41,19 +42,12 @@ Boston, MA 02110-1301, USA.  */
 #define CLEARTYPE_NATURAL_QUALITY 6
 #endif
 
-/* The actual structure for a w32 font, that can be cast to struct font.  */
-struct w32font_info
-{
-  struct font font;
-  TEXTMETRIC metrics;
-};
-
 extern struct font_driver w32font_driver;
 
 Lisp_Object Qgdi;
-extern Lisp_Object QCfamily; /* reuse from xfaces.c  */
-static Lisp_Object Qmonospace, Qsans_serif, Qserif, Qmono, Qsans, Qsans__serif;
-static Lisp_Object Qscript, Qdecorative, Qraster, Qoutline, Qunknown;
+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; /* defined in font.c  */
@@ -113,16 +107,20 @@ struct font_callback_data
   Lisp_Object frame;
   /* The list to add matches to.  */
   Lisp_Object list;
+  /* Whether to match only opentype fonts.  */
+  int 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 P_ ((struct font_callback_data *match_data));
+static void list_all_matching_fonts P_ ((struct font_callback_data *match));
 
 
 /* MingW headers only define this when _WIN32_WINNT >= 0x0500, but we
    target older versions.  */
+#ifndef GGI_MARK_NONEXISTING_GLYPHS
 #define GGI_MARK_NONEXISTING_GLYPHS 1
+#endif
 
 static int
 memq_no_quit (elt, list)
@@ -136,11 +134,11 @@ memq_no_quit (elt, list)
 /* 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.  */
-static Lisp_Object
-w32font_get_cache (frame)
-     Lisp_Object frame;
+Lisp_Object
+w32font_get_cache (f)
+     FRAME_PTR f;
 {
-  struct w32_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (frame));
+  struct w32_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
 
   return (dpyinfo->name_list_element);
 }
@@ -153,33 +151,7 @@ static Lisp_Object
 w32font_list (frame, font_spec)
      Lisp_Object frame, font_spec;
 {
-  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;
-  bzero (&match_data.pattern, sizeof (LOGFONT));
-  fill_in_logfont (f, &match_data.pattern, font_spec);
-
-  if (match_data.pattern.lfFaceName[0] == '\0')
-    {
-      /* EnumFontFamiliesEx does not take other fields into account if
-         font name is blank, so need to use two passes.  */
-      list_all_matching_fonts (&match_data);
-    }
-  else
-    {
-      dc = get_frame_dc (f);
-
-      EnumFontFamiliesEx (dc, &match_data.pattern,
-                          (FONTENUMPROC) add_font_entity_to_list,
-                          (LPARAM) &match_data, 0);
-      release_frame_dc (f, dc);
-    }
-
-  return NILP (match_data.list) ? null_vector : Fvconcat (1, &match_data.list);
+  return w32font_list_internal (frame, font_spec, 0);
 }
 
 /* w32 implementation of match for font backend.
@@ -190,27 +162,9 @@ static Lisp_Object
 w32font_match (frame, font_spec)
      Lisp_Object frame, font_spec;
 {
-  struct font_callback_data match_data;
-  HDC dc;
-  FRAME_PTR f = XFRAME (frame);
-
-  match_data.orig_font_spec = font_spec;
-  match_data.frame = frame;
-  match_data.list = Qnil;
-  bzero (&match_data.pattern, sizeof (LOGFONT));
-  fill_in_logfont (f, &match_data.pattern, font_spec);
-
-  dc = get_frame_dc (f);
-
-  EnumFontFamiliesEx (dc, &match_data.pattern,
-                      (FONTENUMPROC) add_one_font_entity_to_list,
-                      (LPARAM) &match_data, 0);
-  release_frame_dc (f, dc);
-
-  return NILP (match_data.list) ? Qnil : XCAR (match_data.list);
+  return w32font_match_internal (frame, font_spec, 0);
 }
 
-
 /* w32 implementation of list_family for font backend.
    List available families.  The value is a list of family names
    (symbols).  */
@@ -244,91 +198,23 @@ w32font_open (f, font_entity, pixel_size)
      Lisp_Object font_entity;
      int pixel_size;
 {
-  int len, size;
-  LOGFONT logfont;
-  HDC dc;
-  HFONT hfont, old_font;
-  Lisp_Object val, extra;
-  /* For backwards compatibility.  */
-  W32FontStruct *compat_w32_font;
-
   struct w32font_info *w32_font = xmalloc (sizeof (struct w32font_info));
 
-  struct font * font = (struct font *) w32_font;
-  if (!font)
+  if (w32_font == NULL)
     return NULL;
 
-  bzero (&logfont, sizeof (logfont));
-  fill_in_logfont (f, &logfont, font_entity);
-
-  size = XINT (AREF (font_entity, FONT_SIZE_INDEX));
-  if (!size)
-    size = pixel_size;
-
-  logfont.lfHeight = -size;
-  hfont = CreateFontIndirect (&logfont);
-
-  if (hfont == NULL)
+  if (!w32font_open_internal (f, font_entity, pixel_size, w32_font))
     {
       xfree (w32_font);
       return NULL;
     }
 
-  /* Get the metrics for this font.  */
-  dc = get_frame_dc (f);
-  old_font = SelectObject (dc, hfont);
-
-  GetTextMetrics (dc, &w32_font->metrics);
-
-  SelectObject (dc, old_font);
-  release_frame_dc (f, dc);
-  /* W32FontStruct - we should get rid of this, and use the w32font_info
-     struct for any W32 specific fields. font->font.font can then be hfont.  */
-  font->font.font = xmalloc (sizeof (W32FontStruct));
-  compat_w32_font = (W32FontStruct *) font->font.font;
-  bzero (compat_w32_font, sizeof (W32FontStruct));
-  compat_w32_font->font_type = UNICODE_FONT;
-  /* Duplicate the text metrics.  */
-  bcopy (&w32_font->metrics,  &compat_w32_font->tm, sizeof (TEXTMETRIC));
-  compat_w32_font->hfont = hfont;
-
-  len = strlen (logfont.lfFaceName);
-  font->font.name = (char *) xmalloc (len + 1);
-  bcopy (logfont.lfFaceName, font->font.name, len);
-  font->font.name[len] = '\0';
-  font->font.full_name = font->font.name;
-  font->font.charset = 0;
-  font->font.codepage = 0;
-  font->font.size = w32_font->metrics.tmMaxCharWidth;
-  font->font.height = w32_font->metrics.tmHeight
-    + w32_font->metrics.tmExternalLeading;
-  font->font.space_width = font->font.average_width
-    = w32_font->metrics.tmAveCharWidth;
-
-  font->font.vertical_centering = 0;
-  font->font.encoding_type = 0;
-  font->font.baseline_offset = 0;
-  font->font.relative_compose = 0;
-  font->font.default_ascent = w32_font->metrics.tmAscent;
-  font->font.font_encoder = NULL;
-  font->entity = font_entity;
-  font->pixel_size = size;
-  font->driver = &w32font_driver;
-  font->format = Qgdi;
-  font->file_name = NULL;
-  font->encoding_charset = -1;
-  font->repertory_charset = -1;
-  font->min_width = 0;
-  font->ascent = w32_font->metrics.tmAscent;
-  font->descent = w32_font->metrics.tmDescent;
-  font->scalable = w32_font->metrics.tmPitchAndFamily & TMPF_VECTOR;
-
-  return font;
+  return (struct font *) w32_font;
 }
 
 /* w32 implementation of close for font_backend.
    Close FONT on frame F.  */
-static void
+void
 w32font_close (f, font)
      FRAME_PTR f;
      struct font *font;
@@ -341,8 +227,12 @@ w32font_close (f, font)
       font->font.font = 0;
     }
 
+  if (font->font.full_name && font->font.full_name != font->font.name)
+    xfree (font->font.full_name);
+
   if (font->font.name)
     xfree (font->font.name);
+
   xfree (font);
 }
 
@@ -351,7 +241,7 @@ w32font_close (f, font)
    If FONT_ENTITY has a glyph for character C (Unicode code point),
    return 1.  If not, return 0.  If a font must be opened to check
    it, return -1.  */
-static int
+int
 w32font_has_char (entity, c)
      Lisp_Object entity;
      int c;
@@ -377,7 +267,7 @@ w32font_has_char (entity, c)
 /* 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.  */
-static unsigned
+unsigned
 w32font_encode_char (font, c)
      struct font *font;
      int c;
@@ -392,7 +282,7 @@ w32font_encode_char (font, 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.  */
-static int
+int
 w32font_text_extents (font, code, nglyphs, metrics)
      struct font *font;
      unsigned *code;
@@ -401,13 +291,21 @@ w32font_text_extents (font, code, nglyphs, metrics)
 {
   int i;
   HFONT old_font;
-  /* FIXME: Be nice if we had a frame here, rather than getting the desktop's
-     device context to measure against... */
-  HDC dc = GetDC (NULL);
+  HDC dc;
+  struct frame * f;
   int total_width = 0;
   WORD *wcode = alloca(nglyphs * sizeof (WORD));
   SIZE size;
 
+#if 0
+  /* Frames can come and go, and their fonts outlive them. This is
+     particularly troublesome with tooltip frames, and causes crashes.  */
+  f = ((struct w32font_info *)font)->owning_frame;
+#else
+  f = XFRAME (selected_frame);
+#endif
+
+  dc = get_frame_dc (f);
   old_font = SelectObject (dc, ((W32FontStruct *)(font->font.font))->hfont);
 
   if (metrics)
@@ -450,7 +348,7 @@ w32font_text_extents (font, code, nglyphs, metrics)
         {
           /* Restore state and release DC.  */
           SelectObject (dc, old_font);
-          ReleaseDC (NULL, dc);
+          release_frame_dc (f, dc);
 
           return metrics->width;
         }
@@ -493,7 +391,7 @@ w32font_text_extents (font, code, nglyphs, metrics)
 
   /* Restore state and release DC.  */
   SelectObject (dc, old_font);
-  ReleaseDC (NULL, dc);
+  release_frame_dc (f, dc);
 
   return total_width;
 }
@@ -503,8 +401,15 @@ w32font_text_extents (font, code, nglyphs, metrics)
    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).  */
-static int
+   WITH_BACKGROUND is zero 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
+   the old font code setting it up. It may be safer to resolve faces
+   and fonts in here and set them explicitly
+*/
+
+int
 w32font_draw (s, from, to, x, y, with_background)
      struct glyph_string *s;
      int from, to, x, y, with_background;
@@ -531,25 +436,23 @@ w32font_draw (s, from, to, x, y, with_background)
       DeleteObject (new_clip);
     }
 
+  /* Using OPAQUE background mode can clear more background than expected
+     when Cleartype is used.  Draw the background manually to avoid this.  */
+  SetBkMode (s->hdc, TRANSPARENT);
   if (with_background)
     {
-      SetBkColor (s->hdc, s->gc->background);
-      SetBkMode (s->hdc, OPAQUE);
-#if 0
       HBRUSH brush;
       RECT rect;
+      struct font *font = (struct font *) s->face->font_info;
 
       brush = CreateSolidBrush (s->gc->background);
       rect.left = x;
-      rect.top = y - ((struct font *) (s->font_info->font))->ascent;
+      rect.top = y - font->ascent;
       rect.right = x + s->width;
-      rect.bottom = y + ((struct font *) (s->font_info->font))->descent;
+      rect.bottom = y + font->descent;
       FillRect (s->hdc, &rect, brush);
       DeleteObject (brush);
-#endif
     }
-  else
-    SetBkMode (s->hdc, TRANSPARENT);
 
   ExtTextOutW (s->hdc, x, y, options, NULL, s->char2b + from, to - from, NULL);
 
@@ -648,6 +551,187 @@ w32font_otf_drive (struct font *font, Lisp_Object features,
                    int 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 (frame, font_spec, opentype_only)
+     Lisp_Object frame, font_spec;
+     int 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;
+
+  bzero (&match_data.pattern, sizeof (LOGFONT));
+  fill_in_logfont (f, &match_data.pattern, font_spec);
+
+  match_data.opentype_only = opentype_only;
+  if (opentype_only)
+    match_data.pattern.lfOutPrecision = OUT_OUTLINE_PRECIS;
+
+  if (match_data.pattern.lfFaceName[0] == '\0')
+    {
+      /* EnumFontFamiliesEx does not take other fields into account if
+         font name is blank, so need to use two passes.  */
+      list_all_matching_fonts (&match_data);
+    }
+  else
+    {
+      dc = get_frame_dc (f);
+
+      EnumFontFamiliesEx (dc, &match_data.pattern,
+                          (FONTENUMPROC) add_font_entity_to_list,
+                          (LPARAM) &match_data, 0);
+      release_frame_dc (f, dc);
+    }
+
+  return NILP (match_data.list) ? null_vector : Fvconcat (1, &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;
+{
+  struct font_callback_data match_data;
+  HDC dc;
+  FRAME_PTR f = XFRAME (frame);
+
+  match_data.orig_font_spec = font_spec;
+  match_data.frame = frame;
+  match_data.list = Qnil;
+
+  bzero (&match_data.pattern, sizeof (LOGFONT));
+  fill_in_logfont (f, &match_data.pattern, font_spec);
+
+  match_data.opentype_only = opentype_only;
+  if (opentype_only)
+    match_data.pattern.lfOutPrecision = OUT_OUTLINE_PRECIS;
+
+  dc = get_frame_dc (f);
+
+  EnumFontFamiliesEx (dc, &match_data.pattern,
+                      (FONTENUMPROC) add_one_font_entity_to_list,
+                      (LPARAM) &match_data, 0);
+  release_frame_dc (f, dc);
+
+  return NILP (match_data.list) ? Qnil : XCAR (match_data.list);
+}
+
+int
+w32font_open_internal (f, font_entity, pixel_size, w32_font)
+     FRAME_PTR f;
+     Lisp_Object font_entity;
+     int pixel_size;
+     struct w32font_info *w32_font;
+{
+  int len, size;
+  LOGFONT logfont;
+  HDC dc;
+  HFONT hfont, old_font;
+  Lisp_Object val, extra;
+  /* For backwards compatibility.  */
+  W32FontStruct *compat_w32_font;
+
+  struct font * font = (struct font *) w32_font;
+  if (!font)
+    return 0;
+
+  bzero (&logfont, sizeof (logfont));
+  fill_in_logfont (f, &logfont, font_entity);
+
+  size = XINT (AREF (font_entity, FONT_SIZE_INDEX));
+  if (!size)
+    size = pixel_size;
+
+  logfont.lfHeight = -size;
+  hfont = CreateFontIndirect (&logfont);
+
+  if (hfont == NULL)
+    return 0;
+
+  w32_font->owning_frame = f;
+
+  /* Get the metrics for this font.  */
+  dc = get_frame_dc (f);
+  old_font = SelectObject (dc, hfont);
+
+  GetTextMetrics (dc, &w32_font->metrics);
+
+  SelectObject (dc, old_font);
+  release_frame_dc (f, dc);
+  /* W32FontStruct - we should get rid of this, and use the w32font_info
+     struct for any W32 specific fields. font->font.font can then be hfont.  */
+  font->font.font = xmalloc (sizeof (W32FontStruct));
+  compat_w32_font = (W32FontStruct *) font->font.font;
+  bzero (compat_w32_font, sizeof (W32FontStruct));
+  compat_w32_font->font_type = UNICODE_FONT;
+  /* Duplicate the text metrics.  */
+  bcopy (&w32_font->metrics,  &compat_w32_font->tm, sizeof (TEXTMETRIC));
+  compat_w32_font->hfont = hfont;
+
+  len = strlen (logfont.lfFaceName);
+  font->font.name = (char *) xmalloc (len + 1);
+  bcopy (logfont.lfFaceName, font->font.name, len);
+  font->font.name[len] = '\0';
+
+  {
+    char *name;
+
+    /* We don't know how much space we need for the full name, so start with
+       96 bytes and go up in steps of 32.  */
+    len = 96;
+    name = malloc (len);
+    while (name && font_unparse_fcname (font_entity, pixel_size, name, len) < 0)
+      {
+        char *new = realloc (name, len += 32);
+
+        if (! new)
+          free (name);
+        name = new;
+      }
+    if (name)
+      font->font.full_name = name;
+    else
+      font->font.full_name = font->font.name;
+  }
+  font->font.charset = 0;
+  font->font.codepage = 0;
+  font->font.size = w32_font->metrics.tmMaxCharWidth;
+  font->font.height = w32_font->metrics.tmHeight
+    + w32_font->metrics.tmExternalLeading;
+  font->font.space_width = font->font.average_width
+    = w32_font->metrics.tmAveCharWidth;
+
+  font->font.vertical_centering = 0;
+  font->font.encoding_type = 0;
+  font->font.baseline_offset = 0;
+  font->font.relative_compose = 0;
+  font->font.default_ascent = w32_font->metrics.tmAscent;
+  font->font.font_encoder = NULL;
+  font->entity = font_entity;
+  font->pixel_size = size;
+  font->driver = &w32font_driver;
+  font->format = Qgdi;
+  font->file_name = NULL;
+  font->encoding_charset = -1;
+  font->repertory_charset = -1;
+  font->min_width = 0;
+  font->ascent = w32_font->metrics.tmAscent;
+  font->descent = w32_font->metrics.tmDescent;
+  font->scalable = w32_font->metrics.tmPitchAndFamily & TMPF_VECTOR;
+
+  return 1;
+}
+
 /* Callback function for EnumFontFamiliesEx.
  * Adds the name of a font to a Lisp list (passed in as the lParam arg).  */
 static int CALLBACK
@@ -711,18 +795,17 @@ w32_enumfont_pattern_entity (frame, logical_font, physical_font,
   if (generic_type == FF_DECORATIVE)
     tem = Qdecorative;
   else if (generic_type == FF_MODERN)
-    tem = Qmonospace;
+    tem = Qmono;
   else if (generic_type == FF_ROMAN)
     tem = Qserif;
   else if (generic_type == FF_SCRIPT)
     tem = Qscript;
   else if (generic_type == FF_SWISS)
-    tem = Qsans_serif;
+    tem = Qsans;
   else
-    tem = Qnil;
-    
-  if (! NILP (tem))
-    font_put_extra (entity, QCfamily, tem);
+    tem = null_string;
+
+  ASET (entity, FONT_ADSTYLE_INDEX, tem);
 
   if (physical_font->ntmTm.tmPitchAndFamily & 0x01)
     font_put_extra (entity, QCspacing, make_number (FONT_SPACING_PROPORTIONAL));
@@ -767,8 +850,7 @@ w32_generic_family (Lisp_Object name)
   /* Generic families.  */
   if (EQ (name, Qmonospace) || EQ (name, Qmono))
     return FF_MODERN;
-  else if (EQ (name, Qsans_serif) || EQ (name, Qsans__serif)
-           || EQ (name, Qsans))
+  else if (EQ (name, Qsans) || EQ (name, Qsans_serif) || EQ (name, Qsansserif))
     return FF_SWISS;
   else if (EQ (name, Qserif))
     return FF_ROMAN;
@@ -819,6 +901,16 @@ font_matches_spec (type, font, spec)
         return 0;
     }
 
+  /* Check adstyle against generic family.  */
+  val = AREF (spec, FONT_ADSTYLE_INDEX);
+  if (!NILP (val))
+    {
+      BYTE family = w32_generic_family (val);
+      if (family != FF_DONTCARE
+          && family != (font->ntmTm.tmPitchAndFamily & 0xF0))
+        return 0;
+    }
+
   /* Check extra parameters.  */
   for (extra = AREF (spec, FONT_EXTRA_INDEX);
        CONSP (extra); extra = XCDR (extra))
@@ -829,22 +921,7 @@ font_matches_spec (type, font, spec)
         {
           Lisp_Object key = XCAR (extra_entry);
           val = XCDR (extra_entry);
-          if (EQ (key, QCfamily))
-            {
-              /* Generic family. Most useful when there is no font name
-                 specified. eg, if a script does not exist in the default
-                 font, we could look for a font with the same generic family
-                 that does support the script. Full PANOSE support would
-                 be better, but we need to open the font to get that.  */
-              BYTE w32_family = w32_generic_family (val);
-
-              /* Reject if FF_DONTCARE is returned, as it means the
-                 font spec is bad.  */
-              if (w32_family == FF_DONTCARE
-                  || w32_family != (font->ntmTm.tmPitchAndFamily & 0xF0))
-                return 0;
-            }
-          else if (EQ (key, QCspacing))
+          if (EQ (key, QCspacing))
             {
               int proportional;
               if (INTEGERP (val))
@@ -970,13 +1047,21 @@ add_font_entity_to_list (logical_font, physical_font, font_type, lParam)
   struct font_callback_data *match_data
     = (struct font_callback_data *) lParam;
 
-  if (logfonts_match (&logical_font->elfLogFont, &match_data->pattern)
+  if ((!match_data->opentype_only
+       || (physical_font->ntmTm.ntmFlags & NTMFLAGS_OPENTYPE))
+      && logfonts_match (&logical_font->elfLogFont, &match_data->pattern)
       && font_matches_spec (font_type, physical_font,
                             match_data->orig_font_spec)
-      /* Avoid Windows substitution so we can control substitution with
-         alternate-fontname-alist.  */
-      && !strnicmp (&logical_font->elfFullName,
-                    &match_data->pattern.lfFaceName, LF_FACESIZE))
+      /* 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)))
     {
       Lisp_Object entity
         = w32_enumfont_pattern_entity (match_data->frame, logical_font,
@@ -1118,6 +1203,15 @@ fill_in_logfont (f, logfont, font_spec)
         strncpy (logfont->lfFaceName, SDATA (tmp), LF_FACESIZE);
     }
 
+  tmp = AREF (font_spec, FONT_ADSTYLE_INDEX);
+  if (!NILP (tmp))
+    {
+      /* Override generic family.  */
+      BYTE family = w32_generic_family (tmp);
+      if (family != FF_DONTCARE)
+        logfont->lfPitchAndFamily = family | DEFAULT_PITCH;
+    }
+
   /* Process EXTRA info.  */
   for ( ; CONSP (extra); extra = XCDR (extra))
     {
@@ -1126,15 +1220,7 @@ fill_in_logfont (f, logfont, font_spec)
         {
           Lisp_Object key, val;
           key = XCAR (tmp), val = XCDR (tmp);
-          if (EQ (key, QCfamily))
-            {
-              /* Override generic family.  */
-              BYTE family = w32_generic_family (val);
-              if (family != FF_DONTCARE)
-                logfont->lfPitchAndFamily
-                  = logfont->lfPitchAndFamily & 0x0F | family;
-            }
-          else if (EQ (key, QCspacing))
+          if (EQ (key, QCspacing))
             {
               /* Set pitch based on the spacing property.  */
               if (INTEGERP (val))
@@ -1379,7 +1465,10 @@ struct font_driver w32font_driver =
     NULL, /* free_outline */
     NULL, /* anchor_point */
     NULL, /* otf_capability */
-    NULL /* otf_drive */
+    NULL, /* otf_drive */
+    NULL, /* start_for_frame */
+    NULL, /* end_for_frame */
+    NULL  /* shape */
   };
 
 
@@ -1393,11 +1482,11 @@ syms_of_w32font ()
   /* Generic font families.  */
   DEFSYM (Qmonospace, "monospace");
   DEFSYM (Qserif, "serif");
-  DEFSYM (Qsans_serif, "sans-serif");
+  DEFSYM (Qsansserif, "sansserif");
   DEFSYM (Qscript, "script");
   DEFSYM (Qdecorative, "decorative");
   /* Aliases.  */
-  DEFSYM (Qsans__serif, "sans_serif");
+  DEFSYM (Qsans_serif, "sans_serif");
   DEFSYM (Qsans, "sans");
   DEFSYM (Qmono, "mono");