Merge from emacs--rel--22
[bpt/emacs.git] / src / w32font.c
index 52af8f3..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,31 +29,53 @@ Boston, MA 02110-1301, USA.  */
 #include "charset.h"
 #include "fontset.h"
 #include "font.h"
+#include "w32font.h"
 
-/* The actual structure for a w32 font, that can be cast to struct font.  */
-struct w32font_info
-{
-  struct font font;
-  TEXTMETRIC metrics;
-  /* Unicode subset bitfield. See MSDN documentation for FONTSIGNATURE.  */
-  DWORD *subranges;
-};
+/* Cleartype available on Windows XP, cleartype_natural from XP SP1.
+   The latter does not try to fit cleartype smoothed fonts into the
+   same bounding box as the non-antialiased version of the font.
+ */
+#ifndef CLEARTYPE_QUALITY
+#define CLEARTYPE_QUALITY 5
+#endif
+#ifndef CLEARTYPE_NATURAL_QUALITY
+#define CLEARTYPE_NATURAL_QUALITY 6
+#endif
 
 extern struct font_driver w32font_driver;
 
-Lisp_Object Qw32, QCsubranges;
-static Lisp_Object Qmodern, Qswiss, Qroman, Qdecorative, Qscript, Qunknown;
+Lisp_Object Qgdi;
+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  */
+extern Lisp_Object Qnone; /* reuse from w32fns.c  */
+static Lisp_Object Qstandard, Qsubpixel, Qnatural;
+
+/* scripts */
+static Lisp_Object Qlatin, 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;
+
+/* Font spacing symbols - defined in font.c.  */
+extern Lisp_Object Qc, Qp, Qm;
 
 static void fill_in_logfont P_ ((FRAME_PTR f, LOGFONT *logfont,
                                  Lisp_Object font_spec));
 
-static void set_fonts_frame P_ ((Lisp_Object fontlist, Lisp_Object frame));
-
-static int unicode_range_for_char (unsigned c);
+static BYTE w32_antialias_type P_ ((Lisp_Object type));
+static Lisp_Object lispy_antialias_type P_ ((BYTE type));
 
-static void list_all_matching_fonts P_ ((Lisp_Object frame,
-                                         LOGFONT *font_match_pattern,
-                                         Lisp_Object* list));
+static Lisp_Object font_supported_scripts P_ ((FONTSIGNATURE * sig));
 
 /* From old font code in w32fns.c */
 char * w32_to_x_charset P_ ((int charset, char * matching));
@@ -71,14 +93,34 @@ static int CALLBACK add_font_name_to_list P_ ((ENUMLOGFONTEX *,
                                                NEWTEXTMETRICEX *,
                                                DWORD, LPARAM));
 
-/* W32 API functions only available on some versions of Windows  */
-typedef DWORD (*GETGLYPHINDICES) (HDC, wchar_t *, int, LPWORD, DWORD);
-typedef BOOL (*GETTEXTEXTENTPTI) (HDC, LPWORD, int, LPSIZE);
-static GETGLYPHINDICES get_glyph_indices_fn = NULL;
-static GETTEXTEXTENTPTI get_text_extent_pointi_fn = NULL;
+/* struct passed in as LPARAM arg to EnumFontFamiliesEx, for keeping track
+   of what we really want.  */
+struct font_callback_data
+{
+  /* The logfont we are matching against. EnumFontFamiliesEx only matches
+     face name and charset, so we need to manually match everything else
+     in the callback function.  */
+  LOGFONT pattern;
+  /* The original font spec or entity.  */
+  Lisp_Object orig_font_spec;
+  /* The frame the font is being loaded on.  */
+  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));
+
+
 /* 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)
@@ -92,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);
 }
@@ -109,34 +151,7 @@ static Lisp_Object
 w32font_list (frame, font_spec)
      Lisp_Object frame, font_spec;
 {
-  Lisp_Object list = Qnil;
-  LOGFONT font_match_pattern;
-  HDC dc;
-  FRAME_PTR f = XFRAME (frame);
-
-  bzero (&font_match_pattern, sizeof (font_match_pattern));
-  fill_in_logfont (f, &font_match_pattern, font_spec);
-
-
-  if (font_match_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 (frame, &font_match_pattern, &list);
-    }
-  else
-    {
-      dc = get_frame_dc (f);
-
-      EnumFontFamiliesEx (dc, &font_match_pattern,
-                          (FONTENUMPROC) add_font_entity_to_list,
-                          (LPARAM) &list, 0);
-      release_frame_dc (f, dc);
-    }
-
-  set_fonts_frame (list, frame);
-
-  return list;
+  return w32font_list_internal (frame, font_spec, 0);
 }
 
 /* w32 implementation of match for font backend.
@@ -147,27 +162,9 @@ static Lisp_Object
 w32font_match (frame, font_spec)
      Lisp_Object frame, font_spec;
 {
-  Lisp_Object list = Qnil;
-  LOGFONT font_match_pattern;
-  HDC dc;
-  FRAME_PTR f = XFRAME (frame);
-
-  bzero (&font_match_pattern, sizeof (font_match_pattern));
-  fill_in_logfont (f, &font_match_pattern, font_spec);
-
-  dc = get_frame_dc (f);
-
-  EnumFontFamiliesEx (dc, &font_match_pattern,
-                      (FONTENUMPROC) add_one_font_entity_to_list,
-                      (LPARAM) &list, 0);
-  release_frame_dc (f, dc);
-
-  set_fonts_frame (list, frame);
-
-  return NILP (list) ? Qnil : XCAR (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).  */
@@ -201,108 +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 == 0)
-    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;
-
-  font->font.font_idx = 0;
-  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 = Qw32;
-  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;
-
-  /* Truetype fonts will have extra information about the characters
-     covered by the font.  */
-  ((struct w32font_info *)(font))->subranges = NULL;
-  extra = AREF (font_entity, FONT_EXTRA_INDEX);
-  if (CONSP (extra))
-    {
-      val = assq_no_quit (extra, QCsubranges);
-      if (CONSP (val))
-        {
-          val = XCDR (val);
-
-          if (XTYPE (val) == Lisp_Misc && XMISCTYPE (val) == Lisp_Misc_Save_Value)
-            ((struct w32font_info *)(font))->subranges = XSAVE_VALUE (val)->pointer;
-        }
-    }
-
-  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;
@@ -310,13 +222,17 @@ w32font_close (f, font)
   if (font->font.font)
     {
       W32FontStruct *old_w32_font = (W32FontStruct *)font->font.font;
-      DeleteObject (font->font.font);
+      DeleteObject (old_w32_font->hfont);
       xfree (old_w32_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);
 }
 
@@ -325,83 +241,48 @@ 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;
 {
-  Lisp_Object val, extra;
-  DWORD *ranges;
-  int index;
+  Lisp_Object supported_scripts, extra, script;
   DWORD mask;
 
   extra = AREF (entity, FONT_EXTRA_INDEX);
   if (!CONSP (extra))
     return -1;
 
-  val = assq_no_quit (extra, QCsubranges);
-  if (!CONSP (val))
+  supported_scripts = assq_no_quit (QCscript, extra);
+  if (!CONSP (supported_scripts))
     return -1;
 
-  val = XCDR (val);
-  if (XTYPE (val) != Lisp_Misc || XMISCTYPE (val) != Lisp_Misc_Save_Value)
-    return -1;
-
-  ranges = XSAVE_VALUE (val)->pointer;
+  supported_scripts = XCDR (supported_scripts);
 
-  index = unicode_range_for_char (c);
-  mask = 1 << (index % 32);
-  index = index / 32;
+  script = CHAR_TABLE_REF (Vchar_script_table, c);
 
-  if (ranges[index] & mask)
-    return 1;
-  else
-    return 0;
+  return (memq_no_quit (script, supported_scripts)) ? 1 : 0;
 }
 
 /* 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;
 {
-  if (get_glyph_indices_fn)
-    {
-      HFONT old_font;
-      WORD glyph[2];
-      int converted;
-      /* FIXME: Be nice if we had a frame here, rather than getting
-         the desktop's device context to measure against... */
-      HDC dc = GetDC (NULL);
-      wchar_t string[2];
-      string[0] = c;
-      string[1] = 0x0000;
-
-      if (get_glyph_indices_fn)
-        converted = (*get_glyph_indices_fn) (dc, string, 1, glyph,
-                                             GGI_MARK_NONEXISTING_GLYPHS);
-
-      /* Restore state and release DC.  */
-      SelectObject (dc, old_font);
-      ReleaseDC (NULL, dc);
-      if (converted > 0 && glyph[0] != 0xFFFF)
-        return glyph[0];
-      else if (converted != GDI_ERROR)
-        return FONT_INVALID_CODE;
-    }
-  /* On older platforms, or if the above fails, return the unicode
-     code point.  */
+  /* Avoid unneccesary conversion - all the Win32 APIs will take a unicode
+     character.  */
   return c;
 }
 
 /* w32 implementation of text_extents for font backend.
    Perform the size computation of glyphs of FONT and fillin members
    of METRICS.  The glyphs are specified by their glyph codes in
-   CODE (length NGLYPHS).  Apparently medtrics can be NULL, in this
+   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;
@@ -410,45 +291,67 @@ 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;
-
-  /* TODO: Allow some extra room for surrogates. */
   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)
     {
       GLYPHMETRICS gm;
-      int i;
-      UINT format = GGO_METRICS;
-      if (get_text_extent_pointi_fn)
-        format |= GGO_GLYPH_INDEX;
+      MAT2 transform;
+
+      /* Set transform to the identity matrix.  */
+      bzero (&transform, sizeof (transform));
+      transform.eM11.value = 1;
+      transform.eM22.value = 1;
+      metrics->width = 0;
+      metrics->ascent = 0;
+      metrics->descent = 0;
 
       for (i = 0; i < nglyphs; i++)
         {
-          if (GetGlyphOutline (dc, *(code + i), format, &gm, 0, NULL, NULL)
-              != GDI_ERROR)
+          if (GetGlyphOutlineW (dc, *(code + i), GGO_METRICS, &gm, 0,
+                                NULL, &transform) != GDI_ERROR)
             {
-              metrics[i].lbearing = gm.gmptGlyphOrigin.x;
-              metrics[i].rbearing = gm.gmptGlyphOrigin.x + gm.gmBlackBoxX;
-              metrics[i].width = gm.gmCellIncX;
-              metrics[i].ascent = -gm.gmptGlyphOrigin.y;
-              metrics[i].descent = gm.gmBlackBoxY + gm.gmptGlyphOrigin.y;
+              int new_val = metrics->width + gm.gmBlackBoxX
+                + gm.gmptGlyphOrigin.x;
+
+              metrics->rbearing = max (metrics->rbearing, new_val);
+              metrics->width += gm.gmCellIncX;
+              new_val = -gm.gmptGlyphOrigin.y;
+              metrics->ascent = max (metrics->ascent, new_val);
+              new_val = gm.gmBlackBoxY + gm.gmptGlyphOrigin.y;
+              metrics->descent = max (metrics->descent, new_val);
             }
           else
             {
-              metrics[i].lbearing = 0;
-              metrics[i].rbearing = font->font.size
-                + ((struct w32font_info *) font)->metrics.tmOverhang;
-              metrics[i].width = font->font.size;
-              metrics[i].ascent = font->ascent;
-              metrics[i].descent = font->descent;
+              /* Rely on an estimate based on the overall font metrics.  */
+              break;
             }
         }
+
+      /* If we got through everything, return.  */
+      if (i == nglyphs)
+        {
+          /* Restore state and release DC.  */
+          SelectObject (dc, old_font);
+          release_frame_dc (f, dc);
+
+          return metrics->width;
+        }
     }
 
   for (i = 0; i < nglyphs; i++)
@@ -462,16 +365,12 @@ w32font_text_extents (font, code, nglyphs, metrics)
         }
     }
 
-  if (get_text_extent_pointi_fn)
+  if (GetTextExtentPoint32W (dc, wcode, nglyphs, &size))
     {
-      SIZE size;
-      if ((*get_text_extent_pointi_fn) (dc, wcode, nglyphs, &size))
-        {
-          total_width = size.cx;
-        }
+      total_width = size.cx;
     }
 
-  if (total_width == 0)
+  if (!total_width)
     {
       RECT rect;
       rect.top = 0; rect.bottom = font->font.height; rect.left = 0; rect.right = 1;
@@ -479,9 +378,20 @@ w32font_text_extents (font, code, nglyphs, metrics)
                  DT_CALCRECT | DT_NOPREFIX | DT_SINGLELINE);
       total_width = rect.right;
     }
+
+  if (metrics)
+    {
+      metrics->width = total_width;
+      metrics->ascent = font->ascent;
+      metrics->descent = font->descent;
+      metrics->lbearing = 0;
+      metrics->rbearing = total_width
+        + ((struct w32font_info *) font)->metrics.tmOverhang;
+    }
+
   /* Restore state and release DC.  */
   SelectObject (dc, old_font);
-  ReleaseDC (NULL, dc);
+  release_frame_dc (f, dc);
 
   return total_width;
 }
@@ -491,24 +401,66 @@ 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;
 {
-  /* TODO: Do we need to specify ETO_GLYPH_INDEX or is char2b always utf-16?  */
   UINT options = 0;
+  HRGN orig_clip;
+
+  /* Save clip region for later restoration.  */
+  GetClipRgn(s->hdc, orig_clip);
+
+  if (s->num_clips > 0)
+    {
+      HRGN new_clip = CreateRectRgnIndirect (s->clip);
+
+      if (s->num_clips > 1)
+        {
+          HRGN clip2 = CreateRectRgnIndirect (s->clip + 1);
 
+          CombineRgn (new_clip, new_clip, clip2, RGN_OR);
+          DeleteObject (clip2);
+        }
+
+      SelectClipRgn (s->hdc, new_clip);
+      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)
     {
-      options = ETO_OPAQUE;
-      SetBkColor (s->hdc, s->gc->background);
+      HBRUSH brush;
+      RECT rect;
+      struct font *font = (struct font *) s->face->font_info;
+
+      brush = CreateSolidBrush (s->gc->background);
+      rect.left = x;
+      rect.top = y - font->ascent;
+      rect.right = x + s->width;
+      rect.bottom = y + font->descent;
+      FillRect (s->hdc, &rect, brush);
+      DeleteObject (brush);
     }
-  else
-    SetBkMode (s->hdc, TRANSPARENT);
 
   ExtTextOutW (s->hdc, x, y, options, NULL, s->char2b + from, to - from, NULL);
+
+  /* Restore clip region.  */
+  if (s->num_clips > 0)
+    {
+      SelectClipRgn (s->hdc, orig_clip);
+    }
 }
 
 /* w32 implementation of free_entity for font backend.
@@ -535,7 +487,7 @@ w32font_done_face (FRAME_PTR f, struct face *face);  */
 /* w32 implementation of get_bitmap for font backend.
    Optional.
    Store bitmap data for glyph-code CODE of FONT in BITMAP.  It is
-   intended that this method is callled from the other font-driver
+   intended that this method is called from the other font-driver
    for actual drawing.
 static int
 w32font_get_bitmap (struct font *font, unsigned code,
@@ -599,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
@@ -609,8 +742,14 @@ add_font_name_to_list (logical_font, physical_font, font_type, list_object)
      LPARAM list_object;
 {
   Lisp_Object* list = (Lisp_Object *) list_object;
-  Lisp_Object family = intern_downcase (logical_font->elfLogFont.lfFaceName,
-                                        strlen (logical_font->elfLogFont.lfFaceName));
+  Lisp_Object family;
+
+  /* Skip vertical fonts (intended only for printing)  */
+  if (logical_font->elfLogFont.lfFaceName[0] == '@')
+    return 1;
+
+  family = intern_downcase (logical_font->elfLogFont.lfFaceName,
+                            strlen (logical_font->elfLogFont.lfFaceName));
   if (! memq_no_quit (family, *list))
     *list = Fcons (family, *list);
 
@@ -619,46 +758,73 @@ add_font_name_to_list (logical_font, physical_font, font_type, list_object)
 
 /* Convert an enumerated Windows font to an Emacs font entity.  */
 static Lisp_Object
-w32_enumfont_pattern_entity (logical_font, physical_font, font_type)
+w32_enumfont_pattern_entity (frame, logical_font, physical_font,
+                             font_type, requested_font)
+     Lisp_Object frame;
      ENUMLOGFONTEX *logical_font;
      NEWTEXTMETRICEX *physical_font;
      DWORD font_type;
+     LOGFONT *requested_font;
 {
   Lisp_Object entity, tem;
   LOGFONT *lf = (LOGFONT*) logical_font;
   BYTE generic_type;
 
-  entity = Fmake_vector (make_number (FONT_ENTITY_MAX), null_string);
+  entity = Fmake_vector (make_number (FONT_ENTITY_MAX), Qnil);
 
-  ASET (entity, FONT_TYPE_INDEX, Qw32);
+  ASET (entity, FONT_TYPE_INDEX, Qgdi);
+  ASET (entity, FONT_FRAME_INDEX, frame);
   ASET (entity, FONT_REGISTRY_INDEX, w32_registry (lf->lfCharSet));
   ASET (entity, FONT_OBJLIST_INDEX, Qnil);
 
   /* Foundry is difficult to get in readable form on Windows.
-     But Emacs crashes if it is not set, so set it to the generic type.  */
+     But Emacs crashes if it is not set, so set it to something more
+     generic.  Thes values make xflds compatible with Emacs 22. */
+  if (lf->lfOutPrecision == OUT_STRING_PRECIS)
+    tem = Qraster;
+  else if (lf->lfOutPrecision == OUT_STROKE_PRECIS)
+    tem = Qoutline;
+  else
+    tem = Qunknown;
+
+  ASET (entity, FONT_FOUNDRY_INDEX, tem);
+
+  /* Save the generic family in the extra info, as it is likely to be
+     useful to users looking for a close match.  */
   generic_type = physical_font->ntmTm.tmPitchAndFamily & 0xF0;
   if (generic_type == FF_DECORATIVE)
     tem = Qdecorative;
   else if (generic_type == FF_MODERN)
-    tem = Qmodern;
+    tem = Qmono;
   else if (generic_type == FF_ROMAN)
-    tem = Qroman;
+    tem = Qserif;
   else if (generic_type == FF_SCRIPT)
     tem = Qscript;
   else if (generic_type == FF_SWISS)
-    tem = Qswiss;
+    tem = Qsans;
   else
-    tem = Qunknown;
+    tem = null_string;
 
-  ASET (entity, FONT_FOUNDRY_INDEX, tem);
+  ASET (entity, FONT_ADSTYLE_INDEX, tem);
+
+  if (physical_font->ntmTm.tmPitchAndFamily & 0x01)
+    font_put_extra (entity, QCspacing, make_number (FONT_SPACING_PROPORTIONAL));
+  else
+    font_put_extra (entity, QCspacing, make_number (FONT_SPACING_MONO));
 
+  if (requested_font->lfQuality != DEFAULT_QUALITY)
+    {
+      font_put_extra (entity, QCantialias,
+                      lispy_antialias_type (requested_font->lfQuality));
+    }
   ASET (entity, FONT_FAMILY_INDEX,
         intern_downcase (lf->lfFaceName, strlen (lf->lfFaceName)));
 
   ASET (entity, FONT_WEIGHT_INDEX, make_number (lf->lfWeight));
   ASET (entity, FONT_SLANT_INDEX, make_number (lf->lfItalic ? 200 : 100));
-  ASET (entity, FONT_WIDTH_INDEX,
-        make_number (physical_font->ntmTm.tmAveCharWidth));
+  /* TODO: PANOSE struct has this info, but need to call GetOutlineTextMetrics
+     to get it.  */
+  ASET (entity, FONT_WIDTH_INDEX, make_number (100));
 
   if (font_type & RASTER_FONTTYPE)
     ASET (entity, FONT_SIZE_INDEX, make_number (physical_font->ntmTm.tmHeight));
@@ -669,43 +835,259 @@ w32_enumfont_pattern_entity (logical_font, physical_font, font_type)
      of getting this information easily.  */
   if (font_type & TRUETYPE_FONTTYPE)
     {
-      DWORD *subranges = xmalloc(16);
-      memcpy (subranges, physical_font->ntmFontSig.fsUsb, 16);
-      font_put_extra (entity, QCsubranges, make_save_value (subranges, 0));
+      font_put_extra (entity, QCscript,
+                      font_supported_scripts (&physical_font->ntmFontSig));
     }
+
   return entity;
 }
 
+
+/* Convert generic families to the family portion of lfPitchAndFamily.  */
+BYTE
+w32_generic_family (Lisp_Object name)
+{
+  /* Generic families.  */
+  if (EQ (name, Qmonospace) || EQ (name, Qmono))
+    return FF_MODERN;
+  else if (EQ (name, Qsans) || EQ (name, Qsans_serif) || EQ (name, Qsansserif))
+    return FF_SWISS;
+  else if (EQ (name, Qserif))
+    return FF_ROMAN;
+  else if (EQ (name, Qdecorative))
+    return FF_DECORATIVE;
+  else if (EQ (name, Qscript))
+    return FF_SCRIPT;
+  else
+    return FF_DONTCARE;
+}
+
+static int
+logfonts_match (font, pattern)
+     LOGFONT *font, *pattern;
+{
+  /* Only check height for raster fonts.  */
+  if (pattern->lfHeight && font->lfOutPrecision == OUT_STRING_PRECIS
+      && font->lfHeight != pattern->lfHeight)
+    return 0;
+
+  /* Have some flexibility with weights.  */
+  if (pattern->lfWeight
+      && ((font->lfWeight < (pattern->lfWeight - 150))
+          || font->lfWeight > (pattern->lfWeight + 150)))
+      return 0;
+
+  /* Charset and face should be OK.  Italic has to be checked
+     against the original spec, in case we don't have any preference.  */
+  return 1;
+}
+
+static int
+font_matches_spec (type, font, spec)
+     DWORD type;
+     NEWTEXTMETRICEX *font;
+     Lisp_Object spec;
+{
+  Lisp_Object extra, val;
+
+  /* Check italic. Can't check logfonts, since it is a boolean field,
+     so there is no difference between "non-italic" and "don't care".  */
+  val = AREF (spec, FONT_SLANT_INDEX);
+  if (INTEGERP (val))
+    {
+      int slant = XINT (val);
+      if ((slant > 150 && !font->ntmTm.tmItalic)
+          || (slant <= 150 && font->ntmTm.tmItalic))
+        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))
+    {
+      Lisp_Object extra_entry;
+      extra_entry = XCAR (extra);
+      if (CONSP (extra_entry))
+        {
+          Lisp_Object key = XCAR (extra_entry);
+          val = XCDR (extra_entry);
+          if (EQ (key, QCspacing))
+            {
+              int proportional;
+              if (INTEGERP (val))
+                {
+                  int spacing = XINT (val);
+                  proportional = (spacing < FONT_SPACING_MONO);
+                }
+              else if (EQ (val, Qp))
+                proportional = 1;
+              else if (EQ (val, Qc) || EQ (val, Qm))
+                proportional = 0;
+              else
+                return 0; /* Bad font spec.  */
+
+              if ((proportional && !(font->ntmTm.tmPitchAndFamily & 0x01))
+                  || (!proportional && (font->ntmTm.tmPitchAndFamily & 0x01)))
+                return 0;
+            }
+          else if (EQ (key, QCscript) && SYMBOLP (val))
+            {
+              /* 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.  */
+              if (type & TRUETYPE_FONTTYPE)
+                {
+                  Lisp_Object support
+                    = font_supported_scripts (&font->ntmFontSig);
+                  if (! memq_no_quit (val, support))
+                    return 0;
+                }
+              else
+                {
+                  /* Return specific matches, but play it safe. Fonts
+                     that cover more than their charset would suggest
+                     are likely to be truetype or opentype fonts,
+                     covered above.  */
+                  if (EQ (val, Qlatin))
+                    {
+                      /* Although every charset but symbol, thai and
+                         arabic contains the basic ASCII set of latin
+                         characters, Emacs expects much more.  */
+                      if (font->ntmTm.tmCharSet != ANSI_CHARSET)
+                        return 0;
+                    }
+                  else if (EQ (val, Qsymbol))
+                    {
+                      if (font->ntmTm.tmCharSet != SYMBOL_CHARSET)
+                        return 0;
+                    }
+                  else if (EQ (val, Qcyrillic))
+                    {
+                      if (font->ntmTm.tmCharSet != RUSSIAN_CHARSET)
+                        return 0;
+                    }
+                  else if (EQ (val, Qgreek))
+                    {
+                      if (font->ntmTm.tmCharSet != GREEK_CHARSET)
+                        return 0;
+                    }
+                  else if (EQ (val, Qarabic))
+                    {
+                      if (font->ntmTm.tmCharSet != ARABIC_CHARSET)
+                        return 0;
+                    }
+                  else if (EQ (val, Qhebrew))
+                    {
+                      if (font->ntmTm.tmCharSet != HEBREW_CHARSET)
+                        return 0;
+                    }
+                  else if (EQ (val, Qthai))
+                    {
+                      if (font->ntmTm.tmCharSet != THAI_CHARSET)
+                        return 0;
+                    }
+                  else if (EQ (val, Qkana))
+                    {
+                      if (font->ntmTm.tmCharSet != SHIFTJIS_CHARSET)
+                        return 0;
+                    }
+                  else if (EQ (val, Qbopomofo))
+                    {
+                      if (font->ntmTm.tmCharSet != CHINESEBIG5_CHARSET)
+                        return 0;
+                    }
+                  else if (EQ (val, Qhangul))
+                    {
+                      if (font->ntmTm.tmCharSet != HANGUL_CHARSET
+                          && font->ntmTm.tmCharSet != JOHAB_CHARSET)
+                        return 0;
+                    }
+                  else if (EQ (val, Qhan))
+                    {
+                      if (font->ntmTm.tmCharSet != CHINESEBIG5_CHARSET
+                          && font->ntmTm.tmCharSet != GB2312_CHARSET
+                          && font->ntmTm.tmCharSet != HANGUL_CHARSET
+                          && font->ntmTm.tmCharSet != JOHAB_CHARSET
+                          && font->ntmTm.tmCharSet != SHIFTJIS_CHARSET)
+                        return 0;
+                    }
+                  else
+                    /* Other scripts unlikely to be handled.  */
+                    return 0;
+                }
+            }
+        }
+    }
+  return 1;
+}
+
 /* Callback function for EnumFontFamiliesEx.
- * Adds the name of a font to a Lisp list (passed in as the lParam arg).  */
+ * 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, list_object)
+add_font_entity_to_list (logical_font, physical_font, font_type, lParam)
      ENUMLOGFONTEX *logical_font;
      NEWTEXTMETRICEX *physical_font;
      DWORD font_type;
-     LPARAM list_object;
+     LPARAM lParam;
 {
-  Lisp_Object *list = (Lisp_Object *) list_object;
-  Lisp_Object entity = w32_enumfont_pattern_entity (logical_font,
-                                                    physical_font, font_type);
-  if (!NILP (entity))
-    *list = Fcons (entity, *list);
-
+  struct font_callback_data *match_data
+    = (struct font_callback_data *) lParam;
+
+  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 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,
+                                       physical_font, font_type,
+                                       &match_data->pattern);
+      if (!NILP (entity))
+        match_data->list = Fcons (entity, match_data->list);
+    }
   return 1;
 }
 
 /* Callback function for EnumFontFamiliesEx.
- * Adds the name of a font to a Lisp list (passed in as the lParam arg),
- * then terminate the search.  */
+ * Terminates the search once we have a match. */
 static int CALLBACK
-add_one_font_entity_to_list (logical_font, physical_font, font_type, list)
+add_one_font_entity_to_list (logical_font, physical_font, font_type, lParam)
      ENUMLOGFONTEX *logical_font;
      NEWTEXTMETRICEX *physical_font;
      DWORD font_type;
-     LPARAM list;
+     LPARAM lParam;
 {
-  add_font_entity_to_list (logical_font, physical_font, font_type, list);
-  return 0;
+  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);
 }
 
 /* Convert a Lisp font registry (symbol) to a windows charset.  */
@@ -731,7 +1113,7 @@ w32_registry (w32_charset)
      LONG w32_charset;
 {
   if (w32_charset == ANSI_CHARSET)
-    return Qiso8859_1;
+    return Qiso10646_1;
   else
     {
       char * charset = w32_to_x_charset (w32_charset, NULL);
@@ -739,24 +1121,6 @@ w32_registry (w32_charset)
     }
 }
 
-static void
-set_fonts_frame (fontlist, frame)
-     Lisp_Object fontlist;
-     Lisp_Object frame;
-{
-  if (VECTORP (fontlist))
-    ASET (fontlist, FONT_FRAME_INDEX, frame);
-  else
-    {
-      for ( ; CONSP (fontlist); fontlist = XCDR (fontlist))
-        {
-          Lisp_Object entity = XCAR (fontlist);
-          if (VECTORP (entity))
-            ASET (entity, FONT_FRAME_INDEX, frame);
-        }
-    }
-}
-
 /* Fill in all the available details of LOGFONT from FONT_SPEC.  */
 static void
 fill_in_logfont (f, logfont, font_spec)
@@ -764,23 +1128,30 @@ fill_in_logfont (f, logfont, font_spec)
      LOGFONT *logfont;
      Lisp_Object font_spec;
 {
-  Lisp_Object val, tmp, extra;
+  Lisp_Object tmp, extra;
   int dpi = FRAME_W32_DISPLAY_INFO (f)->resy;
 
-  /* TODO: Allow user to override dpi settings.  */
+  extra = AREF (font_spec, FONT_EXTRA_INDEX);
+  /* Allow user to override dpi settings.  */
+  if (CONSP (extra))
+    {
+      tmp = assq_no_quit (QCdpi, extra);
+      if (CONSP (tmp) && INTEGERP (XCDR (tmp)))
+        {
+          dpi = XINT (XCDR (tmp));
+        }
+      else if (CONSP (tmp) && FLOATP (XCDR (tmp)))
+        {
+          dpi = (int) (XFLOAT_DATA (XCDR (tmp)) + 0.5);
+        }
+    }
 
   /* Height  */
   tmp = AREF (font_spec, FONT_SIZE_INDEX);
   if (INTEGERP (tmp))
     logfont->lfHeight = -1 * XINT (tmp);
   else if (FLOATP (tmp))
-    logfont->lfHeight = (int) (-1.0 *  dpi * XFLOAT_DATA (tmp) / 72.0);
-
-  /* Width  TODO: makes fonts look distorted.
-  tmp = AREF (font_spec, FONT_WIDTH_INDEX);
-  if (INTEGERP (tmp))
-    logfont->lfWidth = XINT (tmp);
- */
+    logfont->lfHeight = (int) (-1.0 *  dpi * XFLOAT_DATA (tmp) / 72.27 + 0.5);
 
   /* Escapement  */
 
@@ -806,330 +1177,275 @@ fill_in_logfont (f, logfont, font_spec)
   /* Charset  */
   tmp = AREF (font_spec, FONT_REGISTRY_INDEX);
   if (! NILP (tmp))
-    {
-      if (STRINGP (tmp))
-        logfont->lfCharSet = x_to_w32_charset (SDATA (tmp));
-      else
-        logfont->lfCharSet = registry_to_w32_charset (tmp);
-    }
+    logfont->lfCharSet = registry_to_w32_charset (tmp);
 
   /* Out Precision  */
+
   /* Clip Precision  */
-  /* Quality  TODO: Allow different quality to be specified, so user
-     can enable/disable anti-aliasing for individual fonts.  */
+
+  /* Quality */
   logfont->lfQuality = DEFAULT_QUALITY;
 
-  /* Pitch and Family  */
-  /* Facename  TODO: handle generic names  */
+  /* Generic Family and Face Name  */
+  logfont->lfPitchAndFamily = FF_DONTCARE | DEFAULT_PITCH;
+
   tmp = AREF (font_spec, FONT_FAMILY_INDEX);
-  /* Font families are interned  */
-  if (SYMBOLP (tmp))
-    strncpy (logfont->lfFaceName, SDATA (SYMBOL_NAME (tmp)), LF_FACESIZE);
-  else if (STRINGP (tmp))
-    strncpy (logfont->lfFaceName, SDATA (tmp), LF_FACESIZE);
+  if (! NILP (tmp))
+    {
+      logfont->lfPitchAndFamily = w32_generic_family (tmp) | DEFAULT_PITCH;
+      if ((logfont->lfPitchAndFamily & 0xF0) != FF_DONTCARE)
+        ; /* Font name was generic, don't fill in font name.  */
+        /* 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);
+      else if (STRINGP (tmp))
+        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))
+    {
+      tmp = XCAR (extra);
+      if (CONSP (tmp))
+        {
+          Lisp_Object key, val;
+          key = XCAR (tmp), val = XCDR (tmp);
+          if (EQ (key, QCspacing))
+            {
+              /* Set pitch based on the spacing property.  */
+              if (INTEGERP (val))
+                {
+                  int spacing = XINT (val);
+                  if (spacing < FONT_SPACING_MONO)
+                    logfont->lfPitchAndFamily
+                      = logfont->lfPitchAndFamily & 0xF0 | VARIABLE_PITCH;
+                  else
+                    logfont->lfPitchAndFamily
+                      = logfont->lfPitchAndFamily & 0xF0 | FIXED_PITCH;
+                }
+              else if (EQ (val, Qp))
+                logfont->lfPitchAndFamily
+                  = logfont->lfPitchAndFamily & 0xF0 | VARIABLE_PITCH;
+              else if (EQ (val, Qc) || EQ (val, Qm))
+                logfont->lfPitchAndFamily
+                  = logfont->lfPitchAndFamily & 0xF0 | FIXED_PITCH;
+            }
+          /* 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,
+             cjk-misc match multiple lfCharSet values, so we can't pre-filter
+             them.  */
+          else if (EQ (key, QCscript)
+                   && logfont->lfCharSet == DEFAULT_CHARSET
+                   && SYMBOLP (val))
+            {
+              if (EQ (val, Qgreek))
+                logfont->lfCharSet = GREEK_CHARSET;
+              else if (EQ (val, Qhangul))
+                logfont->lfCharSet = HANGUL_CHARSET;
+              else if (EQ (val, Qkana) || EQ (val, Qkanbun))
+                logfont->lfCharSet = SHIFTJIS_CHARSET;
+              else if (EQ (val, Qbopomofo))
+                logfont->lfCharSet = CHINESEBIG5_CHARSET;
+              /* GB 18030 supports tibetan, yi, mongolian,
+                 fonts that support it should show up if we ask for
+                 GB2312 fonts. */
+              else if (EQ (val, Qtibetan) || EQ (val, Qyi)
+                       || EQ (val, Qmongolian))
+                logfont->lfCharSet = GB2312_CHARSET;
+              else if (EQ (val, Qhebrew))
+                logfont->lfCharSet = HEBREW_CHARSET;
+              else if (EQ (val, Qarabic))
+                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))
+            {
+              logfont->lfQuality = w32_antialias_type (val);
+            }
+        }
+    }
 }
 
 static void
-list_all_matching_fonts (frame, font_match_pattern, list)
-     Lisp_Object frame;
-     LOGFONT *font_match_pattern;
-     Lisp_Object* list;
+list_all_matching_fonts (match_data)
+     struct font_callback_data *match_data;
 {
   HDC dc;
-  Lisp_Object families = w32font_list_family (frame);
-  struct frame *f = XFRAME (frame);
+  Lisp_Object families = w32font_list_family (match_data->frame);
+  struct frame *f = XFRAME (match_data->frame);
 
   dc = get_frame_dc (f);
 
   while (!NILP (families))
     {
+      /* TODO: Use the Unicode versions of the W32 APIs, so we can
+         handle non-ASCII font names.  */
+      char *name;
       Lisp_Object family = CAR (families);
       families = CDR (families);
-      if (STRINGP (family))
-        {
-          /* TODO: Use the Unicode versions of the W32 APIs, so we can
-             handle non-ASCII font names.  */
-          char * name = SDATA (family);
-          strncpy (font_match_pattern->lfFaceName, name, LF_FACESIZE);
-          font_match_pattern->lfFaceName[LF_FACESIZE - 1] = '\0';
-
-          EnumFontFamiliesEx (dc, font_match_pattern,
-                              (FONTENUMPROC) add_font_entity_to_list,
-                              (LPARAM)&list, 0);
-        }
+      if (NILP (family))
+        continue;
+      else if (STRINGP (family))
+        name = SDATA (family);
+      else
+        name = SDATA (SYMBOL_NAME (family)); 
+
+      strncpy (match_data->pattern.lfFaceName, name, LF_FACESIZE);
+      match_data->pattern.lfFaceName[LF_FACESIZE - 1] = '\0';
+
+      EnumFontFamiliesEx (dc, &match_data->pattern,
+                          (FONTENUMPROC) add_font_entity_to_list,
+                          (LPARAM) match_data, 0);
     }
 
   release_frame_dc (f, dc);
 }
 
-static int
-unicode_range_for_char (c)
-     unsigned c;
+static Lisp_Object
+lispy_antialias_type (type)
+     BYTE type;
+{
+  Lisp_Object lispy;
+
+  switch (type)
+    {
+    case NONANTIALIASED_QUALITY:
+      lispy = Qnone;
+      break;
+    case ANTIALIASED_QUALITY:
+      lispy = Qstandard;
+      break;
+    case CLEARTYPE_QUALITY:
+      lispy = Qsubpixel;
+      break;
+    case CLEARTYPE_NATURAL_QUALITY:
+      lispy = Qnatural;
+      break;
+    default:
+      lispy = Qnil;
+      break;
+    }
+  return lispy;
+}
+
+/* Convert antialiasing symbols to lfQuality  */
+static BYTE
+w32_antialias_type (type)
+     Lisp_Object type;
+{
+  if (EQ (type, Qnone))
+    return NONANTIALIASED_QUALITY;
+  else if (EQ (type, Qstandard))
+    return ANTIALIASED_QUALITY;
+  else if (EQ (type, Qsubpixel))
+    return CLEARTYPE_QUALITY;
+  else if (EQ (type, Qnatural))
+    return CLEARTYPE_NATURAL_QUALITY;
+  else
+    return DEFAULT_QUALITY;
+}
+
+/* Return a list of all the scripts that the font supports.  */
+static Lisp_Object
+font_supported_scripts (FONTSIGNATURE * sig)
 {
-  /* Is there really no Windows API function for this?!!! */
-  if (c < 0x80)
-    return 0;              // Basic Latin
-  else if (c < 0x100)
-    return 1;              // Latin-1 supplement
-  else if (c < 0x180)
-    return 2;              // Latin Extended-A
-  else if (c < 0x250)
-    return 3;              // Latin Extended-B
-  else if (c < 0x2B0)
-    return 4;              // IPA Extensions
-  else if (c < 0x300)
-    return 5;              // Spacing modifiers
-  else if (c < 0x370)
-    return 6;              // Combining diacritical marks
-  else if (c < 0x400)
-    return 7;              // Greek and Coptic
-  else if (c < 0x530)
-    return 9;              // Cyrillic, Cyrillic supplementary
-  else if (c < 0x590)
-    return 10;             // Armenian
-  else if (c < 0x600)
-    return 11;             // Hebrew
-  else if (c < 0x700)
-    return 13;             // Arabic
-  else if (c < 0x750)
-    return 71;             // Syriac
-  else if (c < 0x780)
-    return 13;             // Arabic supplement
-  else if (c < 0x7c0)
-    return 72;             // Thaana
-  else if (c < 0x800)
-    return 14;             // N'Ko
-  else if (c < 0x900)
-    return -1;             // Unsupported range
-  else if (c < 0x980)
-    return 15;             // Devanagari
-  else if (c < 0xA00)
-    return 16;             // Bengali
-  else if (c < 0xA80)
-    return 17;             // Gurmukhi
-  else if (c < 0xB00)
-    return 18;             // Gujarati
-  else if (c < 0xB80)
-    return 19;             // Oriya
-  else if (c < 0xC00)
-    return 20;             // Tamil
-  else if (c < 0xC80)
-    return 21;             // Telugu
-  else if (c < 0xD00)
-    return 22;             // Kannada
-  else if (c < 0xD80)
-    return 23;             // Malayalam
-  else if (c < 0xE00)
-    return 73;             // Sinhala
-  else if (c < 0xE80)
-    return 24;             // Thai
-  else if (c < 0xF00)
-    return 25;             // Lao
-  else if (c < 0x1000)
-    return 70;             // Tibetan
-  else if (c < 0x10A0)
-    return 74;             // Myanmar
-  else if (c < 0x1100)
-    return 26;             // Georgian
-  else if (c < 0x1200)
-    return 28;             // Hangul Jamo
-  else if (c < 0x13A0)
-    return 75;             // Ethiopic, Ethiopic Supplement
-  else if (c < 0x1400)
-    return 76;             // Cherokee
-  else if (c < 0x1680)
-    return 77;             // Unified Canadian Aboriginal Syllabics
-  else if (c < 0x16A0)
-    return 78;             // Ogham
-  else if (c < 0x1700)
-    return 79;             // Runic
-  else if (c < 0x1780)
-    return 84;             // Tagalog, Hanunoo, Buhid, Tagbanwa
-  else if (c < 0x1800)
-    return 80;             // Khmer
-  else if (c < 0x18B0)
-    return 81;             // Mongolian
-  else if (c < 0x1900)
-    return -1;             // Unsupported range
-  else if (c < 0x1950)
-    return 93;             // Limbu
-  else if (c < 0x1980)
-    return 94;             // Tai Le
-  else if (c < 0x19E0)
-    return 95;             // New Tai Le
-  else if (c < 0x1A00)
-    return 80;             // Khmer Symbols
-  else if (c < 0x1A20)
-    return 96;             // Buginese
-  else if (c < 0x1B00)
-    return -1;             // Unsupported range
-  else if (c < 0x1B80)
-    return 27;             // Balinese
-  else if (c < 0x1D00)
-    return -1;             // Unsupported range
-  else if (c < 0x1DC0)
-    return 4;              // Phonetic extensions + supplement
-  else if (c < 0x1E00)
-    return 6;              // Combining diacritical marks supplement
-  else if (c < 0x1F00)
-    return 29;             // Latin Extended additional
-  else if (c < 0x2000)
-    return 30;             // Greek Extended
-  else if (c < 0x2070)
-    return 31;             // General Punctuation
-  else if (c < 0x20A0)
-    return 32;             // Subscripts and Superscripts
-  else if (c < 0x20D0)
-    return 33;             // Currency symbols
-  else if (c < 0x2100)
-    return 34;             // Combining marks for diacriticals
-  else if (c < 0x2150)
-    return 35;             // Letterlike symbols
-  else if (c < 0x2190)
-    return 36;             // Number forms
-  else if (c < 0x2200)
-    return 37;             // Arrows
-  else if (c < 0x2300)
-    return 38;             // Mathematical operators
-  else if (c < 0x2400)
-    return 39;             // Miscellaneous technical
-  else if (c < 0x2440)
-    return 40;             // Control pictures
-  else if (c < 0x2460)
-    return 41;             // Optical character recognition
-  else if (c < 0x2500)
-    return 42;             // Enclosed alphanumerics
-  else if (c < 0x2580)
-    return 43;             // Box drawing
-  else if (c < 0x25A0)
-    return 44;             // Block elements
-  else if (c < 0x2600)
-    return 45;             // Geometric shapes
-  else if (c < 0x2700)
-    return 46;             // Miscellaneous symbols
-  else if (c < 0x27C0)
-    return 47;             // Dingbats
-  else if (c < 0x27F0)
-    return 38;             // Misc Math symbols-A
-  else if (c < 0x2800)
-    return 37;             // Supplemental arrows-A
-  else if (c < 0x2900)
-    return 82;             // Braille patterns
-  else if (c < 0x2980)
-    return 37;             // Supplemental arrows-B
-  else if (c < 0x2B00)
-    return 38;             // Misc Math symbols-B, Supplemental Math operators
-  else if (c < 0x2C00)
-    return 37;             // Misc Symbols and Arrows
-  else if (c < 0x2C60)
-    return 97;             // Galgolitic
-  else if (c < 0x2C80)
-    return 29;             // Latin Extended-C
-  else if (c < 0x2D00)
-    return 8;              // Coptic
-  else if (c < 0x2D30)
-    return 26;             // Georgian supplement
-  else if (c < 0x2D80)
-    return 98;             // Tifinagh
-  else if (c < 0x2DE0)
-    return 75;             // Ethiopic extended
-  else if (c < 0x2E00)
-    return -1;             // Unsupported range
-  else if (c < 0x2E80)
-    return 31;             // Supplemental punctuation
-  else if (c < 0x2FE0)
-    return 59;             // CJK radicals supplement, Kangxi radicals
-  else if (c < 0x2FF0)
-    return -1;             // Unsupported range
-  else if (c < 0x3000)
-    return 59;             // Ideographic description characters
-  else if (c < 0x3040)
-    return 48;             // CJK symbols and punctuation
-  else if (c < 0x30A0)
-    return 49;             // Hiragana
-  else if (c < 0x3100)
-    return 50;             // Katakana
-  else if (c < 0x3130)
-    return 51;             // Bopomofo
-  else if (c < 0x3190)
-    return 52;             // Hangul compatibility Jamo
-  else if (c < 0x31A0)
-    return 59;             // Kanbun
-  else if (c < 0x31C0)
-    return 51;             // Bopomofo extended
-  else if (c < 0x31F0)
-    return 61;             // CJK strokes
-  else if (c < 0x3200)
-    return 50;             // Katakana phonetic extensions
-  else if (c < 0x3300)
-    return 54;             // CJK enclosed letters and months
-  else if (c < 0x3400)
-    return 55;             // CJK compatibility
-  else if (c < 0x4DC0)
-    return 59;             // CJK unified ideographs extension-A
-  else if (c < 0x4E00)
-    return 99;             // Yijing Hexagram Symbols
-  else if (c < 0xA000)
-    return 59;             // CJK unified ideographs
-  else if (c < 0xA4D0)
-    return 83;             // Yi syllables, Yi radicals
-  else if (c < 0xA700)
-    return -1;             // Unsupported range
-  else if (c < 0xA720)
-    return 5;              // Modifier tone letters
-  else if (c < 0xA800)
-    return 29;             // Latin Extended-D
-  else if (c < 0xA830)
-    return 100;            // Syloti Nagri
-  else if (c < 0xA840)
-    return -1;             // Unsupported range
-  else if (c < 0xA880)
-    return 53;             // Phags-pa
-  else if (c < 0xAC00)
-    return -1;             // Unsupported range
-  else if (c < 0xD7A4)
-    return 56;             // Hangul syllables
-  else if (c < 0xD800)
-    return -1;             // Unsupported range
-  else if (c < 0xE000)
-    return 57;             // Surrogates
-  else if (c < 0xF900)
-    return 60;             // Private use (plane 0)
-  else if (c < 0xFB00)
-    return 61;             // CJK Compatibility ideographs
-  else if (c < 0xFB50)
-    return 62;             // Alphabetic Presentation Forms
-  else if (c < 0xFE00)
-    return 63;             // Arabic Presentation Forms-A
-  else if (c < 0xFE10)
-    return 91;             // Variation selectors
-  else if (c < 0xFE20)
-    return 65;             // Vertical forms
-  else if (c < 0xFE30)
-    return 64;             // Combining half marks
-  else if (c < 0xFE50)
-    return 65;             // CJK compatibility forms
-  else if (c < 0xFE70)
-    return 66;             // Small form variants
-  else if (c < 0xFEFF)
-    return 67;             // Arabic Presentation Forms-B
-  else if (c == 0xFEFF)
-    return -1;             // Unsupported range
-  else if (c < 0xFFF0)
-    return 68;             // Halfwidth and fullwidth forms
-  else if (c <= 0xFFFF)
-    return 69;             // Specials
-
-  // If int is 64 bit, it could represent characters from 10000 up, but 
-  // any font that handles them should have the surrogate bit set (57).
-  return 57;
+  DWORD * subranges = sig->fsUsb;
+  Lisp_Object supported = Qnil;
+
+  /* Match a single subrange. SYM is set if bit N is set in subranges.  */
+#define SUBRANGE(n,sym) \
+  if (subranges[(n) / 32] & (1 << ((n) % 32))) \
+    supported = Fcons ((sym), supported)
+
+  /* Match multiple subranges. SYM is set if any MASK bit is set in
+     subranges[0 - 3].  */
+#define MASK_ANY(mask0,mask1,mask2,mask3,sym)      \
+  if ((subranges[0] & (mask0)) || (subranges[1] & (mask1))     \
+      || (subranges[2] & (mask2)) || (subranges[3] & (mask3))) \
+    supported = Fcons ((sym), supported)
+
+  SUBRANGE (0, Qlatin); /* There are many others... */
+
+  SUBRANGE (7, Qgreek);
+  SUBRANGE (8, Qcoptic);
+  SUBRANGE (9, Qcyrillic);
+  SUBRANGE (10, Qarmenian);
+  SUBRANGE (11, Qhebrew);
+  SUBRANGE (13, Qarabic);
+  SUBRANGE (14, Qnko);
+  SUBRANGE (15, Qdevanagari);
+  SUBRANGE (16, Qbengali);
+  SUBRANGE (17, Qgurmukhi);
+  SUBRANGE (18, Qgujarati);
+  SUBRANGE (19, Qoriya);
+  SUBRANGE (20, Qtamil);
+  SUBRANGE (21, Qtelugu);
+  SUBRANGE (22, Qkannada);
+  SUBRANGE (23, Qmalayalam);
+  SUBRANGE (24, Qthai);
+  SUBRANGE (25, Qlao);
+  SUBRANGE (26, Qgeorgian);
+
+  SUBRANGE (48, Qcjk_misc);
+  SUBRANGE (51, Qbopomofo);
+  SUBRANGE (54, Qkanbun); /* Is this right?  */
+  SUBRANGE (56, Qhangul);
+
+  SUBRANGE (59, Qhan); /* There are others, but this is the main one.  */
+  SUBRANGE (59, Qideographic_description); /* Windows lumps this in  */
+
+  SUBRANGE (70, Qtibetan);
+  SUBRANGE (71, Qsyriac);
+  SUBRANGE (72, Qthaana);
+  SUBRANGE (73, Qsinhala);
+  SUBRANGE (74, Qmyanmar);
+  SUBRANGE (75, Qethiopic);
+  SUBRANGE (76, Qcherokee);
+  SUBRANGE (77, Qcanadian_aboriginal);
+  SUBRANGE (78, Qogham);
+  SUBRANGE (79, Qrunic);
+  SUBRANGE (80, Qkhmer);
+  SUBRANGE (81, Qmongolian);
+  SUBRANGE (82, Qbraille);
+  SUBRANGE (83, Qyi);
+
+  SUBRANGE (88, Qbyzantine_musical_symbol);
+  SUBRANGE (88, Qmusical_symbol); /* Windows doesn't distinguish these.  */
+
+  SUBRANGE (89, Qmathematical);
+
+  /* Match either katakana or hiragana for kana.  */
+  MASK_ANY (0, 0x00060000, 0, 0, Qkana);
+
+  /* There isn't really a main symbol range, so include symbol if any
+     relevant range is set.  */
+  MASK_ANY (0x8000000, 0x0000FFFF, 0, 0, Qsymbol);
+
+#undef SUBRANGE
+#undef MASK_ANY
+
+  return supported;
 }
 
 
 struct font_driver w32font_driver =
   {
-    0, /* Qw32 */
+    0, /* Qgdi */
     w32font_get_cache,
     w32font_list,
     w32font_match,
@@ -1149,36 +1465,91 @@ 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 */
   };
 
-/* Initialize the font subsystem for the environment on which
-   Emacs is running.   */
-void
-w32font_initialize ()
-{
-  /* Load functions that might not exist on older versions of Windows.  */
-  HANDLE gdi = LoadLibrary ("gdi32.dll");
-
-  get_glyph_indices_fn
-    = (GETGLYPHINDICES) GetProcAddress (gdi, "GetGlyphIndicesW");
-  get_text_extent_pointi_fn
-    = (GETTEXTEXTENTPTI) GetProcAddress (gdi, "GetTextExtentPoint32W");
-}
 
 /* Initialize state that does not change between invocations. This is only
    called when Emacs is dumped.  */
 void
 syms_of_w32font ()
 {
-  DEFSYM (Qw32, "w32");
-  DEFSYM (Qdecorative, "decorative");
-  DEFSYM (Qmodern, "modern");
-  DEFSYM (Qroman, "roman");
+  DEFSYM (Qgdi, "gdi");
+
+  /* Generic font families.  */
+  DEFSYM (Qmonospace, "monospace");
+  DEFSYM (Qserif, "serif");
+  DEFSYM (Qsansserif, "sansserif");
   DEFSYM (Qscript, "script");
-  DEFSYM (Qswiss, "swiss");
+  DEFSYM (Qdecorative, "decorative");
+  /* Aliases.  */
+  DEFSYM (Qsans_serif, "sans_serif");
+  DEFSYM (Qsans, "sans");
+  DEFSYM (Qmono, "mono");
+
+  /* Fake foundries.  */
+  DEFSYM (Qraster, "raster");
+  DEFSYM (Qoutline, "outline");
   DEFSYM (Qunknown, "unknown");
-  DEFSYM (QCsubranges, ":subranges");
-  w32font_driver.type = Qw32;
+
+  /* Antialiasing.  */
+  DEFSYM (Qstandard, "standard");
+  DEFSYM (Qsubpixel, "subpixel");
+  DEFSYM (Qnatural, "natural");
+
+  /* Scripts  */
+  DEFSYM (Qlatin, "latin");
+  DEFSYM (Qgreek, "greek");
+  DEFSYM (Qcoptic, "coptic");
+  DEFSYM (Qcyrillic, "cyrillic");
+  DEFSYM (Qarmenian, "armenian");
+  DEFSYM (Qhebrew, "hebrew");
+  DEFSYM (Qarabic, "arabic");
+  DEFSYM (Qsyriac, "syriac");
+  DEFSYM (Qnko, "nko");
+  DEFSYM (Qthaana, "thaana");
+  DEFSYM (Qdevanagari, "devanagari");
+  DEFSYM (Qbengali, "bengali");
+  DEFSYM (Qgurmukhi, "gurmukhi");
+  DEFSYM (Qgujarati, "gujarati");
+  DEFSYM (Qoriya, "oriya");
+  DEFSYM (Qtamil, "tamil");
+  DEFSYM (Qtelugu, "telugu");
+  DEFSYM (Qkannada, "kannada");
+  DEFSYM (Qmalayalam, "malayalam");
+  DEFSYM (Qsinhala, "sinhala");
+  DEFSYM (Qthai, "thai");
+  DEFSYM (Qlao, "lao");
+  DEFSYM (Qtibetan, "tibetan");
+  DEFSYM (Qmyanmar, "myanmar");
+  DEFSYM (Qgeorgian, "georgian");
+  DEFSYM (Qhangul, "hangul");
+  DEFSYM (Qethiopic, "ethiopic");
+  DEFSYM (Qcherokee, "cherokee");
+  DEFSYM (Qcanadian_aboriginal, "canadian-aboriginal");
+  DEFSYM (Qogham, "ogham");
+  DEFSYM (Qrunic, "runic");
+  DEFSYM (Qkhmer, "khmer");
+  DEFSYM (Qmongolian, "mongolian");
+  DEFSYM (Qsymbol, "symbol");
+  DEFSYM (Qbraille, "braille");
+  DEFSYM (Qhan, "han");
+  DEFSYM (Qideographic_description, "ideographic-description");
+  DEFSYM (Qcjk_misc, "cjk-misc");
+  DEFSYM (Qkana, "kana");
+  DEFSYM (Qbopomofo, "bopomofo");
+  DEFSYM (Qkanbun, "kanbun");
+  DEFSYM (Qyi, "yi");
+  DEFSYM (Qbyzantine_musical_symbol, "byzantine-musical-symbol");
+  DEFSYM (Qmusical_symbol, "musical-symbol");
+  DEFSYM (Qmathematical, "mathematical");
+
+  w32font_driver.type = Qgdi;
   register_font_driver (&w32font_driver, NULL);
 }
+
+/* arch-tag: 65b8a3cd-46aa-4c0d-a1f3-99e75b9c07ee
+   (do not change this comment) */