* s/ms-w32.h (MULTI_KBOARD): Remove.
[bpt/emacs.git] / src / w32term.c
index edde95f..85ac8d9 100644 (file)
@@ -1,14 +1,14 @@
 /* Implementation of GUI terminal on the Microsoft W32 API.
    Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998,
                  1999, 2000, 2001, 2002, 2003, 2004, 2005,
-                 2006, 2007 Free Software Foundation, Inc.
+                 2006, 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
+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, 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
@@ -16,48 +16,48 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include "lisp.h"
-#include "charset.h"
 #include "blockinput.h"
-
-#include "w32heap.h"
 #include "w32term.h"
-#include "w32bdf.h"
-#include <shellapi.h>
 
 #include "systty.h"
 #include "systime.h"
-#include "atimer.h"
-#include "keymap.h"
 
 #include <ctype.h>
 #include <errno.h>
 #include <setjmp.h>
 #include <sys/stat.h>
 
-#include "keyboard.h"
+#include "charset.h"
+#include "character.h"
+#include "coding.h"
+#include "ccl.h"
 #include "frame.h"
 #include "dispextern.h"
 #include "fontset.h"
 #include "termhooks.h"
 #include "termopts.h"
 #include "termchar.h"
-#include "gnu.h"
 #include "disptab.h"
 #include "buffer.h"
 #include "window.h"
+#include "keyboard.h"
 #include "intervals.h"
-#include "composite.h"
-#include "coding.h"
+#include "process.h"
+#include "atimer.h"
+#include "keymap.h"
+
+#include "w32heap.h"
+#include <shellapi.h>
 
+#include "font.h"
+#include "w32font.h"
 \f
 /* Fringe bitmaps.  */
 
@@ -86,8 +86,7 @@ static int any_help_event_p;
 /* Last window where we saw the mouse.  Used by mouse-autoselect-window.  */
 static Lisp_Object last_window;
 
-/* Non-zero means make use of UNDERLINE_POSITION font properties.
-   (Not yet supported, see TODO in x_draw_glyph_string.)  */
+/* Non-zero means make use of UNDERLINE_POSITION font properties.  */
 int x_use_underline_position_properties;
 
 /* Non-zero means to draw the underline at the same place as the descent line.  */
@@ -101,8 +100,6 @@ extern void free_frame_menubar ();
 extern int w32_codepage_for_font (char *fontname);
 extern Cursor w32_load_cursor (LPCTSTR name);
 
-extern glyph_metric *w32_BDF_TextMetric(bdffont *fontp,
-                                       unsigned char *text, int dim);
 extern Lisp_Object Vwindow_system;
 
 #define x_any_window_to_frame x_window_to_frame
@@ -119,6 +116,40 @@ struct w32_display_info *x_display_list;
    FONT-LIST-CACHE records previous values returned by x-list-fonts.  */
 Lisp_Object w32_display_name_list;
 
+
+#ifndef GLYPHSET
+/* Pre Windows 2000, this was not available, but define it here so
+   that Emacs compiled on such a platform will run on newer versions.  */
+
+typedef struct tagWCRANGE
+{
+  WCHAR wcLow;
+  USHORT cGlyphs;
+} WCRANGE;
+
+typedef struct tagGLYPHSET
+{
+  DWORD cbThis;
+  DWORD flAccel;
+  DWORD cGlyphsSupported;
+  DWORD cRanges;
+  WCRANGE ranges[1];
+} GLYPHSET;
+
+#endif
+
+/* Dynamic linking to SetLayeredWindowAttribute (only since 2000).  */
+BOOL (PASCAL *pfnSetLayeredWindowAttributes) (HWND, COLORREF, BYTE, DWORD);
+
+#ifndef LWA_ALPHA
+#define LWA_ALPHA 0x02
+#endif
+/* WS_EX_LAYERED is defined unconditionally by MingW, but only for W2K and
+   later targets by MSVC headers.  */
+#ifndef WS_EX_LAYERED
+#define WS_EX_LAYERED 0x80000
+#endif
+
 /* Frame being updated by update_frame.  This is declared in term.c.
    This is set by update_begin and looked at by all the
    w32 functions.  It is zero while not inside an update.
@@ -136,14 +167,6 @@ int w32_system_caret_x;
 int w32_system_caret_y;
 int w32_use_visible_system_caret;
 
-/* Flag to enable Unicode output in case users wish to use programs
-   like Twinbridge on '95 rather than installed system level support
-   for Far East languages.  */
-int w32_enable_unicode_output;
-
-/* Flag to enable Cleartype hack for font metrics.  */
-static int cleartype_active;
-
 DWORD dwWindowsThreadId = 0;
 HANDLE hWindowsThread = NULL;
 DWORD dwMainThreadId = 0;
@@ -228,8 +251,6 @@ void x_set_window_size P_ ((struct frame *, int, int, int));
 void x_wm_set_window_state P_ ((struct frame *, int));
 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
 static void w32_initialize P_ ((void));
-static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
-int x_compute_min_glyph_bounds P_ ((struct frame *));
 static void x_update_end P_ ((struct frame *));
 static void w32_frame_up_to_date P_ ((struct frame *));
 static void w32_set_terminal_modes P_ ((struct terminal *));
@@ -391,6 +412,53 @@ w32_clear_window (f)
   release_frame_dc (f, hdc);
 }
 
+#define OPAQUE_FRAME 255
+
+void
+x_set_frame_alpha (f)
+     struct frame *f;
+{
+  struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
+  double alpha = 1.0;
+  double alpha_min = 1.0;
+  BYTE opac;
+  LONG ex_style;
+  HWND window = FRAME_W32_WINDOW (f);
+
+  /* Older versions of Windows do not support transparency.  */
+  if (!pfnSetLayeredWindowAttributes)
+    return;
+
+  if (dpyinfo->x_highlight_frame == f)
+    alpha = f->alpha[0];
+  else
+    alpha = f->alpha[1];
+
+  if (FLOATP (Vframe_alpha_lower_limit))
+    alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit);
+  else if (INTEGERP (Vframe_alpha_lower_limit))
+    alpha_min = (XINT (Vframe_alpha_lower_limit)) / 100.0;
+
+  if (alpha < 0.0 || 1.0 < alpha)
+    alpha = 1.0;
+  else if (alpha < alpha_min && alpha_min <= 1.0)
+    alpha = alpha_min;
+
+  opac = alpha * OPAQUE_FRAME;
+
+  ex_style = GetWindowLong (window, GWL_EXSTYLE);
+
+  if (opac == OPAQUE_FRAME)
+    ex_style &= ~WS_EX_LAYERED;
+  else
+    ex_style |= WS_EX_LAYERED;
+
+  SetWindowLong (window, GWL_EXSTYLE, ex_style);
+
+  if (opac != OPAQUE_FRAME)
+    pfnSetLayeredWindowAttributes (window, 0, opac, LWA_ALPHA);
+}
+
 \f
 /***********************************************************************
                    Starting and ending an update
@@ -866,406 +934,6 @@ w32_reset_terminal_modes (struct terminal *term)
 
 /* Function prototypes of this page.  */
 
-XCharStruct *w32_per_char_metric P_ ((XFontStruct *, wchar_t *, int));
-static int w32_encode_char P_ ((int, wchar_t *, struct font_info *, int *));
-
-
-/* Get metrics of character CHAR2B in FONT.  Value is always non-null.
-   If CHAR2B is not contained in FONT, the font's default character
-   metric is returned. */
-
-static int
-w32_bdf_per_char_metric (font, char2b, dim, pcm)
-     XFontStruct *font;
-     wchar_t *char2b;
-     int dim;
-     XCharStruct * pcm;
-{
-  glyph_metric * bdf_metric;
-  char buf[2];
-
-  if (dim == 1)
-    buf[0] = (char)(*char2b);
-  else
-    {
-      buf[0] = XCHAR2B_BYTE1 (char2b);
-      buf[1] = XCHAR2B_BYTE2 (char2b);
-    }
-
-  bdf_metric = w32_BDF_TextMetric (font->bdf, buf, dim);
-
-  if (bdf_metric)
-    {
-      pcm->width = bdf_metric->dwidth;
-      pcm->lbearing = bdf_metric->bbox;
-      pcm->rbearing = bdf_metric->dwidth
-                    - (bdf_metric->bbox + bdf_metric->bbw);
-      pcm->ascent = bdf_metric->bboy + bdf_metric->bbh;
-      pcm->descent = -bdf_metric->bboy;
-
-      return 1;
-    }
-  return 0;
-}
-
-
-static int
-w32_native_per_char_metric (font, char2b, font_type, pcm)
-     XFontStruct *font;
-     wchar_t *char2b;
-     enum w32_char_font_type font_type;
-     XCharStruct * pcm;
-{
-  HDC hdc = GetDC (NULL);
-  HFONT old_font;
-  BOOL retval = FALSE;
-
-  xassert (font && char2b);
-  xassert (font->hfont);
-  xassert (font_type == UNICODE_FONT || font_type == ANSI_FONT);
-
-  old_font = SelectObject (hdc, font->hfont);
-
-  if ((font->tm.tmPitchAndFamily & TMPF_TRUETYPE) != 0)
-    {
-      ABC char_widths;
-
-      if (font_type == UNICODE_FONT)
-       retval = GetCharABCWidthsW (hdc, *char2b, *char2b, &char_widths);
-      else
-       retval = GetCharABCWidthsA (hdc, *char2b, *char2b, &char_widths);
-
-      if (retval)
-       {
-#if 0
-         /* Disabled until we can find a way to get the right results
-            on all versions of Windows.  */
-
-         /* Don't trust the ABC widths.  For synthesized fonts they are
-            wrong, and so is the result of GetCharWidth()!  */
-         int real_width;
-         GetCharWidth (hdc, *char2b, *char2b, &real_width);
-#endif
-         if (cleartype_active)
-           {
-             /* Cleartype antialiasing causes characters to overhang
-                by a pixel on each side compared with what GetCharABCWidths
-                reports.  */
-             char_widths.abcA -= 1;
-             char_widths.abcC -= 1;
-             char_widths.abcB += 2;
-           }
-
-         pcm->width = char_widths.abcA + char_widths.abcB + char_widths.abcC;
-#if 0
-         /* As far as I can tell, this is the best way to determine what
-            ExtTextOut will do with the broken font.  */
-         if (pcm->width != real_width)
-           pcm->width = (pcm->width + real_width) / 2;
-#endif
-         pcm->lbearing = char_widths.abcA;
-         pcm->rbearing = char_widths.abcA + char_widths.abcB;
-         pcm->ascent = FONT_BASE (font);
-         pcm->descent = FONT_DESCENT (font);
-       }
-    }
-
-  if (!retval)
-    {
-      /* Either font is not a True-type font, or GetCharABCWidthsW
-        failed (it is not supported on Windows 9x for instance), so we
-        can't determine the full info we would like.  All is not lost
-        though - we can call GetTextExtentPoint32 to get rbearing and
-        deduce width based on the font's per-string overhang.  lbearing
-        is assumed to be zero.  */
-
-      /* TODO: Some Thai characters (and other composites if Windows
-         supports them) do have lbearing, and report their total width
-         as zero. Need some way of handling them when
-         GetCharABCWidthsW fails. */
-      SIZE sz;
-
-      if (font_type == UNICODE_FONT)
-       retval = GetTextExtentPoint32W (hdc, char2b, 1, &sz);
-      else
-       retval = GetTextExtentPoint32A (hdc, (char*)char2b, 1, &sz);
-
-      if (retval)
-       {
-         pcm->width = sz.cx - font->tm.tmOverhang;
-         pcm->rbearing = sz.cx;
-         pcm->lbearing = 0;
-         pcm->ascent = FONT_BASE (font);
-         pcm->descent = FONT_DESCENT (font);
-       }
-    }
-
-
-  if (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0)
-    {
-      retval = FALSE;
-    }
-
-  SelectObject (hdc, old_font);
-  ReleaseDC (NULL, hdc);
-
-  return retval;
-}
-
-
-XCharStruct *
-w32_per_char_metric (font, char2b, font_type)
-     XFontStruct *font;
-     wchar_t *char2b;
-     int /* enum w32_char_font_type */ font_type;
-{
-  /* The result metric information.  */
-  XCharStruct *pcm;
-  BOOL retval;
-
-  xassert (font && char2b);
-
-  /* TODO: This function is currently called through the RIF, and in
-     some cases font_type is UNKNOWN_FONT. We currently allow the
-     cached metrics to be used, which seems to work, but in cases
-     where font_type is UNKNOWN_FONT, we probably haven't encoded
-     char2b appropriately. All callers need checking to see what they
-     are passing.  This is most likely to affect variable width fonts
-     outside the Latin-1 range, particularly in languages like Thai
-     that rely on rbearing and lbearing to provide composition. I
-     don't think that is working currently anyway, but we don't seem
-     to have anyone testing such languages on Windows.  */
-
-  /* Handle the common cases quickly.  */
-  if (!font->bdf && font->per_char == NULL)
-    /* TODO: determine whether char2b exists in font?  */
-    return &font->max_bounds;
-  else if (!font->bdf && *char2b < 128)
-    return &font->per_char[*char2b];
-
-  xassert (font_type != UNKNOWN_FONT);
-
-  pcm = &font->scratch;
-
-  if (font_type == BDF_1D_FONT)
-    retval = w32_bdf_per_char_metric (font, char2b, 1, pcm);
-  else if (font_type == BDF_2D_FONT)
-    retval = w32_bdf_per_char_metric (font, char2b, 2, pcm);
-  else
-    retval = w32_native_per_char_metric (font, char2b, font_type, pcm);
-
-  if (retval)
-    return pcm;
-
-  return NULL;
-}
-
-void
-w32_cache_char_metrics (font)
-     XFontStruct *font;
-{
-  wchar_t char2b = L'x';
-
-  /* Cache char metrics for the common cases.  */
-  if (font->bdf)
-    {
-      /* TODO: determine whether font is fixed-pitch.  */
-      if (!w32_bdf_per_char_metric (font, &char2b, 1, &font->max_bounds))
-        {
-          /* Use the font width and height as max bounds, as not all BDF
-             fonts contain the letter 'x'. */
-          font->max_bounds.width = FONT_MAX_WIDTH (font);
-          font->max_bounds.lbearing = -font->bdf->llx;
-          font->max_bounds.rbearing = FONT_MAX_WIDTH (font) - font->bdf->urx;
-          font->max_bounds.ascent = FONT_BASE (font);
-          font->max_bounds.descent = FONT_DESCENT (font);
-        }
-    }
-  else
-    {
-      if (((font->tm.tmPitchAndFamily & TMPF_FIXED_PITCH) != 0)
-          /* Some fonts (eg DBCS fonts) are marked as fixed width even
-             though they contain characters of different widths. */
-          || (font->tm.tmMaxCharWidth != font->tm.tmAveCharWidth))
-       {
-         /* Font is not fixed pitch, so cache per_char info for the
-             ASCII characters.  It would be much more work, and probably
-             not worth it, to cache other chars, since we may change
-             between using Unicode and ANSI text drawing functions at
-             run-time.  */
-         int i;
-
-         font->per_char = xmalloc (128 * sizeof(XCharStruct));
-         for (i = 0; i < 128; i++)
-           {
-             char2b = i;
-             w32_native_per_char_metric (font, &char2b, ANSI_FONT,
-                                         &font->per_char[i]);
-           }
-       }
-      else
-       w32_native_per_char_metric (font, &char2b, ANSI_FONT,
-                                   &font->max_bounds);
-    }
-}
-
-
-/* Determine if a font is double byte. */
-static int
-w32_font_is_double_byte (XFontStruct *font)
-{
-  return font->double_byte_p;
-}
-
-
-static BOOL
-w32_use_unicode_for_codepage (codepage)
-     int codepage;
-{
-  /* If the current codepage is supported, use Unicode for output. */
-  return (w32_enable_unicode_output
-          && codepage != CP_8BIT
-          && (codepage == CP_UNICODE || IsValidCodePage (codepage)));
-}
-
-/* Encode CHAR2B using encoding information from FONT_INFO.  CHAR2B is
-   the two-byte form of C.  Encoding is returned in *CHAR2B.  */
-
-static int /* enum w32_char_font_type */
-w32_encode_char (c, char2b, font_info, two_byte_p)
-     int c;
-     wchar_t *char2b;
-     struct font_info *font_info;
-     int * two_byte_p;
-{
-  int charset = CHAR_CHARSET (c);
-  int codepage;
-  int unicode_p = 0;
-  int internal_two_byte_p = 0;
-
-  XFontStruct *font = font_info->font;
-
-  internal_two_byte_p = w32_font_is_double_byte (font);
-
-  /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
-     This may be either a program in a special encoder language or a
-     fixed encoding.  */
-  if (font_info->font_encoder)
-    {
-      /* It's a program.  */
-      struct ccl_program *ccl = font_info->font_encoder;
-
-      if (CHARSET_DIMENSION (charset) == 1)
-       {
-         ccl->reg[0] = charset;
-         ccl->reg[1] = XCHAR2B_BYTE2 (char2b);
-         ccl->reg[2] = -1;
-       }
-      else
-       {
-         ccl->reg[0] = charset;
-         ccl->reg[1] = XCHAR2B_BYTE1 (char2b);
-         ccl->reg[2] = XCHAR2B_BYTE2 (char2b);
-       }
-
-      ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
-
-      /* We assume that MSBs are appropriately set/reset by CCL
-        program.  */
-      if (!internal_two_byte_p)        /* 1-byte font */
-       STORE_XCHAR2B (char2b, 0, ccl->reg[1]);
-      else
-       STORE_XCHAR2B (char2b, ccl->reg[1], ccl->reg[2]);
-    }
-  else if (font_info->encoding[charset])
-    {
-      /* Fixed encoding scheme.  See fontset.h for the meaning of the
-        encoding numbers.  */
-      int enc = font_info->encoding[charset];
-
-      if ((enc == 1 || enc == 2)
-         && CHARSET_DIMENSION (charset) == 2)
-       STORE_XCHAR2B (char2b, XCHAR2B_BYTE1 (char2b) | 0x80, XCHAR2B_BYTE2 (char2b));
-
-      if (enc == 1 || enc == 3
-          || (enc == 4 && CHARSET_DIMENSION (charset) == 1))
-       STORE_XCHAR2B (char2b, XCHAR2B_BYTE1 (char2b), XCHAR2B_BYTE2 (char2b) | 0x80);
-      else if (enc == 4)
-        {
-          int sjis1, sjis2;
-
-          ENCODE_SJIS (XCHAR2B_BYTE1 (char2b), XCHAR2B_BYTE2 (char2b),
-                       sjis1, sjis2);
-          STORE_XCHAR2B (char2b, sjis1, sjis2);
-        }
-    }
-  codepage = font_info->codepage;
-
-  /* If charset is not ASCII or Latin-1, may need to move it into
-     Unicode space.  */
-  if ( font && !font->bdf && w32_use_unicode_for_codepage (codepage)
-       && charset != CHARSET_ASCII && charset != charset_latin_iso8859_1
-       && charset != CHARSET_8_BIT_CONTROL && charset != CHARSET_8_BIT_GRAPHIC)
-    {
-      char temp[3];
-      temp[0] = XCHAR2B_BYTE1 (char2b);
-      temp[1] = XCHAR2B_BYTE2 (char2b);
-      temp[2] = '\0';
-      if (codepage != CP_UNICODE)
-        {
-          if (temp[0])
-            MultiByteToWideChar (codepage, 0, temp, 2, char2b, 1);
-          else
-            MultiByteToWideChar (codepage, 0, temp+1, 1, char2b, 1);
-        }
-      unicode_p = 1;
-      internal_two_byte_p = 1;
-    }
-
-  if (two_byte_p)
-    *two_byte_p = internal_two_byte_p;
-
-  if (!font)
-    return UNKNOWN_FONT;
-  else if (font->bdf && CHARSET_DIMENSION (charset) == 1)
-    return BDF_1D_FONT;
-  else if (font->bdf)
-    return BDF_2D_FONT;
-  else if (unicode_p)
-    return UNICODE_FONT;
-  else
-    return ANSI_FONT;
-}
-
-
-\f
-/***********************************************************************
-                           Glyph display
- ***********************************************************************/
-
-
-/* Encapsulate the different ways of displaying text under W32.  */
-
-static void
-w32_text_out (s, x, y,chars,nchars)
-     struct glyph_string * s;
-     int x, y;
-     wchar_t * chars;
-     int nchars;
-{
-  int charset_dim = w32_font_is_double_byte (s->font) ? 2 : 1;
-  if (s->font->bdf)
-    w32_BDF_TextOut (s->font->bdf, s->hdc,
-                     x, y, (char *) chars, charset_dim,
-                     nchars * charset_dim, 0);
-  else if (s->first_glyph->font_type == UNICODE_FONT)
-    ExtTextOutW (s->hdc, x, y, 0, NULL, chars, nchars, NULL);
-  else
-    ExtTextOutA (s->hdc, x, y, 0, NULL, (char *) chars,
-                nchars * charset_dim, NULL);
-}
-
-
 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
@@ -1293,10 +961,6 @@ static void w32_draw_relief_rect P_ ((struct frame *, int, int, int, int,
 static void w32_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
                                 int, int, int, RECT *));
 
-#if GLYPH_DEBUG
-static void x_check_font P_ ((struct frame *, XFontStruct *));
-#endif
-
 
 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
    face.  */
@@ -1367,9 +1031,9 @@ x_set_mouse_face_gc (s)
     face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
 
   if (s->first_glyph->type == CHAR_GLYPH)
-    face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
+    face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch, -1, Qnil);
   else
-    face_id = FACE_FOR_CHAR (s->f, face, 0);
+    face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil);
   s->face = FACE_FROM_ID (s->f, face_id);
   PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
 
@@ -1469,38 +1133,75 @@ static INLINE void
 x_set_glyph_string_clipping (s)
      struct glyph_string *s;
 {
-  RECT r;
-  get_glyph_string_clip_rect (s, &r);
-  w32_set_clip_rectangle (s->hdc, &r);
-}
+  RECT *r = s->clip;
+  int n = get_glyph_string_clip_rects (s, r, 2);
 
+  if (n == 1)
+    w32_set_clip_rectangle (s->hdc, r);
+  else if (n > 1)
+    {
+      HRGN full_clip, clip1, clip2;
+      clip1 = CreateRectRgnIndirect (r);
+      clip2 = CreateRectRgnIndirect (r + 1);
+      if (CombineRgn (full_clip, clip1, clip2, RGN_OR) != ERROR)
+        {
+          SelectClipRgn (s->hdc, full_clip);
+        }
+      DeleteObject (clip1);
+      DeleteObject (clip2);
+      DeleteObject (full_clip);
+    }
+    s->num_clips = n;
+}
 
-/* RIF:
-   Compute left and right overhang of glyph string S.  If S is a glyph
-   string for a composition, assume overhangs don't exist.  */
+/* Set SRC's clipping for output of glyph string DST.  This is called
+   when we are drawing DST's left_overhang or right_overhang only in
+   the area of SRC.  */
 
 static void
-w32_compute_glyph_string_overhangs (s)
-     struct glyph_string *s;
+x_set_glyph_string_clipping_exactly (src, dst)
+     struct glyph_string *src, *dst;
 {
-  /* TODO: Windows does not appear to have a method for
-     getting this info without getting the ABC widths for each
-     individual character and working it out manually. */
+  RECT r;
+
+  r.left = src->x;
+  r.right = r.left + src->width;
+  r.top = src->y;
+  r.bottom = r.top + src->height;
+  dst->clip[0] = r;
+  dst->num_clips = 1;
+  w32_set_clip_rectangle (dst->hdc, &r);
 }
 
+/* RIF:
+   Compute left and right overhang of glyph string S.  */
 
 static void
-w32_get_glyph_overhangs (glyph, f, left, right)
-     struct glyph *glyph;
-     struct frame *f;
-     int *left, *right;
+w32_compute_glyph_string_overhangs (s)
+     struct glyph_string *s;
 {
-  HDC hdc = get_frame_dc (f);
-  /* Convert to unicode! */
-  x_get_glyph_overhangs (glyph, f, left, right);
-  release_frame_dc (f, hdc);
-}
+  if (s->cmp == NULL
+      && s->first_glyph->type == CHAR_GLYPH
+      && !s->font_not_found_p)
+    {
+      unsigned *code = alloca (sizeof (unsigned) * s->nchars);
+      struct font *font = s->font;
+      struct font_metrics metrics;
+      int i;
 
+      for (i = 0; i < s->nchars; i++)
+       code[i] = s->char2b[i];
+      font->driver->text_extents (font, code, s->nchars, &metrics);
+      s->right_overhang = (metrics.rbearing > metrics.width
+                          ? metrics.rbearing - metrics.width : 0);
+      s->left_overhang = metrics.lbearing < 0 ? -metrics.lbearing : 0;
+    }
+  else if (s->cmp)
+    {
+      s->right_overhang = s->cmp->rbearing - s->cmp->pixel_width;
+      s->left_overhang = -s->cmp->lbearing;
+    }
+}
 
 /* Fill rectangle X, Y, W, H with background color of glyph string S.  */
 
@@ -1564,7 +1265,6 @@ x_draw_glyph_string_background (s, force_p)
         if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
               || s->font_not_found_p
               || s->extends_to_end_of_line_p
-               || s->font->bdf
               || force_p)
        {
          x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
@@ -1583,7 +1283,6 @@ x_draw_glyph_string_foreground (s)
      struct glyph_string *s;
 {
   int i, x;
-  HFONT old_font;
 
   /* If first glyph of S has a left box line, start drawing the text
      of S to the right of that box line.  */
@@ -1593,18 +1292,10 @@ x_draw_glyph_string_foreground (s)
   else
     x = s->x;
 
-  if (s->for_overlaps || (s->background_filled_p && s->hl != DRAW_CURSOR))
-    SetBkMode (s->hdc, TRANSPARENT);
-  else
-    SetBkMode (s->hdc, OPAQUE);
-
   SetTextColor (s->hdc, s->gc->foreground);
   SetBkColor (s->hdc, s->gc->background);
   SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
 
-  if (s->font && s->font->hfont)
-    old_font = SelectObject (s->hdc, s->font->hfont);
-
   /* Draw characters of S as rectangles if S's font could not be
      loaded. */
   if (s->font_not_found_p)
@@ -1620,32 +1311,27 @@ x_draw_glyph_string_foreground (s)
     }
   else
     {
-      char *char1b = (char *) s->char2b;
-      int boff = s->font_info->baseline_offset;
-
-      if (s->font_info->vertical_centering)
-       boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
+      struct font *font = s->font;
+      int boff = font->baseline_offset;
+      int y;
+      HFONT old_font;
 
-      /* If we can use 8-bit functions, condense S->char2b.  */
-      if (!s->two_byte_p)
-        for (i = 0; i < s->nchars; ++i)
-          char1b[i] = XCHAR2B_BYTE2 (&s->char2b[i]);
+      old_font = SelectObject (s->hdc, FONT_HANDLE (font));
 
-      /* Draw text with TextOut and friends. */
-      w32_text_out (s, x, s->ybase - boff, s->char2b, s->nchars);
+      if (font->vertical_centering)
+       boff = VCENTER_BASELINE_OFFSET (font, s->f) - boff;
 
+      y = s->ybase - boff;
+      if (s->for_overlaps
+         || (s->background_filled_p && s->hl != DRAW_CURSOR))
+       font->driver->draw (s, 0, s->nchars, x, y, 0);
+      else
+       font->driver->draw (s, 0, s->nchars, x, y, 1);
       if (s->face->overstrike)
-       {
-         /* For overstriking (to simulate bold-face), draw the
-            characters again shifted to the right by one pixel.  */
-         int old_BkMode = SetBkMode (s->hdc, TRANSPARENT);
-         w32_text_out (s, x + 1, s->ybase - boff, s->char2b, s->nchars);
-         if (old_BkMode && old_BkMode != TRANSPARENT)
-           SetBkMode (s->hdc, old_BkMode);
-       }
+       font->driver->draw (s, 0, s->nchars, x + 1, y, 0);
+
+      SelectObject (s->hdc, old_font);
     }
-  if (s->font && s->font->hfont)
-    SelectObject (s->hdc, old_font);
 }
 
 /* Draw the foreground of composite glyph string S.  */
@@ -1654,12 +1340,11 @@ static void
 x_draw_composite_glyph_string_foreground (s)
      struct glyph_string *s;
 {
-  int i, x;
-  HFONT old_font;
+  int i, j, x;
 
   /* If first glyph of S has a left box line, start drawing the text
      of S to the right of that box line.  */
-  if (s->face->box != FACE_NO_BOX
+  if (s->face && s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
     x = s->x + eabs (s->face->box_line_width);
   else
@@ -1672,12 +1357,8 @@ x_draw_composite_glyph_string_foreground (s)
 
   SetTextColor (s->hdc, s->gc->foreground);
   SetBkColor (s->hdc, s->gc->background);
-  SetBkMode (s->hdc, TRANSPARENT);
   SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
 
-  if (s->font && s->font->hfont)
-    old_font = SelectObject (s->hdc, s->font->hfont);
-
   /* Draw a rectangle for the composition if the font for the very
      first character of the composition could not be loaded.  */
   if (s->font_not_found_p)
@@ -1688,20 +1369,63 @@ x_draw_composite_glyph_string_foreground (s)
     }
   else
     {
-      for (i = 0; i < s->nchars; i++, ++s->gidx)
+      struct font *font = s->font;
+      int y = s->ybase;
+      int width = 0;
+      HFONT old_font;
+
+      old_font = SelectObject (s->hdc, FONT_HANDLE (font));
+
+      if (s->cmp->method == COMPOSITION_WITH_GLYPH_STRING)
        {
-         w32_text_out (s, x + s->cmp->offsets[s->gidx * 2],
-                       s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
-                       s->char2b + i, 1);
-         if (s->face->overstrike)
-           w32_text_out (s, x + s->cmp->offsets[s->gidx * 2] + 1,
-                         s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
-                         s->char2b + i, 1);
+         Lisp_Object gstring = AREF (XHASH_TABLE (composition_hash_table)
+                                     ->key_and_value,
+                                     s->cmp->hash_index * 2);
+         int from;
+
+         for (i = from = 0; i < s->nchars; i++)
+           {
+             Lisp_Object g = LGSTRING_GLYPH (gstring, i);
+             Lisp_Object adjustment = LGLYPH_ADJUSTMENT (g);
+             int xoff, yoff, wadjust;
+
+             if (! VECTORP (adjustment))
+               {
+                 width += LGLYPH_WIDTH (g);
+                 continue;
+               }
+             if (from < i)
+               {
+                 font->driver->draw (s, from, i, x, y, 0);
+                 x += width;
+               }
+             xoff = XINT (AREF (adjustment, 0));
+             yoff = XINT (AREF (adjustment, 1));
+             wadjust = XINT (AREF (adjustment, 2));
+
+             font->driver->draw (s, i, i + 1, x + xoff, y + yoff, 0);
+             x += wadjust;
+             from = i + 1;
+             width = 0;
+           }
+         if (from < i)
+           font->driver->draw (s, from, i, x, y, 0);
        }
-    }
+      else
+       {
+         for (i = 0, j = s->gidx; i < s->nchars; i++, j++)
+           if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
+             {
+               int xx = x + s->cmp->offsets[j * 2];
+               int yy = y - s->cmp->offsets[j * 2 + 1];
 
-  if (s->font && s->font->hfont)
-    SelectObject (s->hdc, old_font);
+               font->driver->draw (s, j, j + 1, xx, yy, 0);
+               if (s->face->overstrike)
+                 font->driver->draw (s, j, j + 1, xx + 1, yy, 0);
+             }
+       }
+      SelectObject (s->hdc, old_font);
+    }
 }
 
 
@@ -2410,7 +2134,6 @@ x_draw_stretch_glyph_string (s)
      struct glyph_string *s;
 {
   xassert (s->first_glyph->type == STRETCH_GLYPH);
-  s->stippled_p = s->face->stipple != 0;
 
   if (s->hl == DRAW_CURSOR
       && !x_stretch_cursor_p)
@@ -2500,10 +2223,17 @@ x_draw_glyph_string (s)
      This makes S->next use XDrawString instead of XDrawImageString.  */
   if (s->next && s->right_overhang && !s->for_overlaps)
     {
-      xassert (s->next->img == NULL);
-      x_set_glyph_string_gc (s->next);
-      x_set_glyph_string_clipping (s->next);
-      x_draw_glyph_string_background (s->next, 1);
+      int width;
+      struct glyph_string *next;
+      for (width = 0, next = s->next; next;
+           width += next->width, next = next->next)
+        if (next->first_glyph->type != IMAGE_GLYPH)
+          {
+            x_set_glyph_string_gc (next);
+            x_set_glyph_string_clipping (next);
+            x_draw_glyph_string_background (next, 1);
+            next->num_clips = 0;
+          }
     }
 
   /* Set up S->gc, set clipping and draw S.  */
@@ -2523,6 +2253,14 @@ x_draw_glyph_string (s)
       x_set_glyph_string_clipping (s);
       relief_drawn_p = 1;
     }
+  else if (!s->clip_head /* draw_glyphs didn't specify a clip mask.  */
+           && !s->clip_tail
+           && ((s->prev && s->prev->hl != s->hl && s->left_overhang)
+               || (s->next && s->next->hl != s->hl && s->right_overhang)))
+    /* We must clip just this glyph.  left_overhang part has already
+       drawn when s->prev was drawn, and right_overhang part will be
+       drawn later when s->next is drawn. */
+    x_set_glyph_string_clipping_exactly (s, s);
   else
     x_set_glyph_string_clipping (s);
 
@@ -2559,44 +2297,74 @@ x_draw_glyph_string (s)
   if (!s->for_overlaps)
     {
       /* Draw underline.  */
-      if (s->face->underline_p
-          && (s->font->bdf || !s->font->tm.tmUnderlined))
+      if (s->face->underline_p)
         {
-          unsigned long h = 1;
-          unsigned long dy = 0;
+          unsigned long thickness, position;
+          int y;
 
-          if (x_underline_at_descent_line)
-            dy = s->height - h;
+          if (s->prev && s->prev->face->underline_p)
+            {
+              /* We use the same underline style as the previous one.  */
+              thickness = s->prev->underline_thickness;
+              position = s->prev->underline_position;
+            }
           else
             {
-              /* TODO: Use font information for positioning and thickness of
-                 underline.  See OUTLINETEXTMETRIC, and xterm.c.  Note: If
-                 you make this work, don't forget to change the doc string of
-                 x-use-underline-position-properties below.  */
-              dy = s->height - h;
+              /* Get the underline thickness.  Default is 1 pixel.  */
+              if (s->font && s->font->underline_thickness > 0)
+                thickness = s->font->underline_thickness;
+              else
+                thickness = 1;
+              if (x_underline_at_descent_line)
+                position = (s->height - thickness) - (s->ybase - s->y);
+              else
+                {
+                /* Get the underline position.  This is the recommended
+                   vertical offset in pixels from the baseline to the top of
+                   the underline.  This is a signed value according to the
+                   specs, and its default is
+
+                   ROUND ((maximum_descent) / 2), with
+                   ROUND (x) = floor (x + 0.5)  */
+
+                if (x_use_underline_position_properties
+                    && s->font && s->font->underline_position >= 0)
+                  position = s->font->underline_position;
+                else if (s->font)
+                  position = (s->font->descent + 1) / 2;
+                }
+             position = max (position, underline_minimum_offset);
             }
+         /* Check the sanity of thickness and position.  We should
+            avoid drawing underline out of the current line area.  */
+         if (s->y + s->height <= s->ybase + position)
+           position = (s->height - 1) - (s->ybase - s->y);
+         if (s->y + s->height < s->ybase + position + thickness)
+           thickness = (s->y + s->height) - (s->ybase + position);
+         s->underline_thickness = thickness;
+         s->underline_position =position;
+          y = s->ybase + position;
           if (s->face->underline_defaulted_p)
             {
               w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
-                             s->y + dy, s->background_width, 1);
+                             y, s->background_width, 1);
             }
           else
             {
               w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
-                             s->y + dy, s->background_width, 1);
+                             y, s->background_width, 1);
             }
         }
-
       /* Draw overline.  */
       if (s->face->overline_p)
         {
           unsigned long dy = 0, h = 1;
 
           if (s->face->overline_color_defaulted_p)
-           {
-             w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
-                         s->y + dy, s->background_width, h);
-           }
+            {
+              w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
+                             s->y + dy, s->background_width, h);
+            }
           else
             {
               w32_fill_area (s->f, s->hdc, s->face->overline_color, s->x,
@@ -2606,7 +2374,7 @@ x_draw_glyph_string (s)
 
       /* Draw strike-through.  */
       if (s->face->strike_through_p
-          && (s->font->bdf || !s->font->tm.tmStruckOut))
+          && !FONT_TEXTMETRIC(s->font).tmStruckOut)
         {
           unsigned long h = 1;
           unsigned long dy = (s->height - h) / 2;
@@ -2623,13 +2391,64 @@ x_draw_glyph_string (s)
             }
         }
 
-      /* Draw relief.  */
+      /* Draw relief if not yet drawn.  */
       if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
         x_draw_glyph_string_box (s);
+
+      if (s->prev)
+        {
+          struct glyph_string *prev;
+
+          for (prev = s->prev; prev; prev = prev->prev)
+            if (prev->hl != s->hl
+                && prev->x + prev->width + prev->right_overhang > s->x)
+              {
+                /* As prev was drawn while clipped to its own area, we
+                   must draw the right_overhang part using s->hl now.  */
+               enum draw_glyphs_face save = prev->hl;
+
+               prev->hl = s->hl;
+               x_set_glyph_string_gc (prev);
+               x_set_glyph_string_clipping_exactly (s, prev);
+               if (prev->first_glyph->type == CHAR_GLYPH)
+                 x_draw_glyph_string_foreground (prev);
+               else
+                 x_draw_composite_glyph_string_foreground (prev);
+                w32_set_clip_rectangle (prev->hdc, NULL);
+               prev->hl = save;
+               prev->num_clips = 0;
+             }
+       }
+
+      if (s->next)
+       {
+         struct glyph_string *next;
+
+         for (next = s->next; next; next = next->next)
+           if (next->hl != s->hl
+               && next->x - next->left_overhang < s->x + s->width)
+             {
+               /* As next will be drawn while clipped to its own area,
+                  we must draw the left_overhang part using s->hl now.  */
+               enum draw_glyphs_face save = next->hl;
+
+               next->hl = s->hl;
+               x_set_glyph_string_gc (next);
+               x_set_glyph_string_clipping_exactly (s, next);
+               if (next->first_glyph->type == CHAR_GLYPH)
+                 x_draw_glyph_string_foreground (next);
+               else
+                 x_draw_composite_glyph_string_foreground (next);
+                w32_set_clip_rectangle (next->hdc, NULL);
+               next->hl = save;
+               next->num_clips = 0;
+             }
+       }
     }
 
   /* Reset clipping.  */
   w32_set_clip_rectangle (s->hdc, NULL);
+  s->num_clips = 0;
 }
 
 
@@ -2843,6 +2662,7 @@ frame_highlight (f)
      struct frame *f;
 {
   x_update_cursor (f, 1);
+  x_set_frame_alpha (f);
 }
 
 static void
@@ -2850,6 +2670,7 @@ frame_unhighlight (f)
      struct frame *f;
 {
   x_update_cursor (f, 1);
+  x_set_frame_alpha (f);
 }
 
 /* The focus has changed.  Update the frames as necessary to reflect
@@ -2905,9 +2726,9 @@ x_focus_changed (type, state, dpyinfo, frame, bufp)
 
           /* Don't stop displaying the initial startup message
              for a switch-frame event we don't need.  */
-          if (GC_NILP (Vterminal_frame)
-              && GC_CONSP (Vframe_list)
-              && !GC_NILP (XCDR (Vframe_list)))
+          if (NILP (Vterminal_frame)
+              && CONSP (Vframe_list)
+              && !NILP (XCDR (Vframe_list)))
             {
               bufp->kind = FOCUS_IN_EVENT;
               XSETFRAME (bufp->frame_or_window, frame);
@@ -2993,7 +2814,7 @@ x_frame_rehighlight (dpyinfo)
   if (dpyinfo->w32_focus_frame)
     {
       dpyinfo->x_highlight_frame
-       = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame)))
+       = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame)))
           ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame))
           : dpyinfo->w32_focus_frame);
       if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
@@ -3252,6 +3073,9 @@ note_mouse_movement (frame, msg)
   memcpy (&last_mouse_motion_event, msg, sizeof (last_mouse_motion_event));
   XSETFRAME (last_mouse_motion_frame, frame);
 
+  if (!FRAME_X_OUTPUT (frame))
+    return 0;
+
   if (msg->hwnd != FRAME_W32_WINDOW (frame))
     {
       frame->mouse_moved = 1;
@@ -3459,15 +3283,13 @@ x_window_to_scroll_bar (window_id)
 {
   Lisp_Object tail;
 
-  for (tail = Vframe_list;
-       XGCTYPE (tail) == Lisp_Cons;
-       tail = XCDR (tail))
+  for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
     {
       Lisp_Object frame, bar, condemned;
 
       frame = XCAR (tail);
       /* All elements of Vframe_list should be frames.  */
-      if (! GC_FRAMEP (frame))
+      if (! FRAMEP (frame))
        abort ();
 
       /* Scan this frame's scroll bar list for a scroll bar with the
@@ -3476,9 +3298,9 @@ x_window_to_scroll_bar (window_id)
       for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
           /* This trick allows us to search both the ordinary and
              condemned scroll bar lists with one loop.  */
-          ! GC_NILP (bar) || (bar = condemned,
+          ! NILP (bar) || (bar = condemned,
                               condemned = Qnil,
-                              ! GC_NILP (bar));
+                              ! NILP (bar));
           bar = XSCROLL_BAR (bar)->next)
        if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id)
          return XSCROLL_BAR (bar);
@@ -3968,10 +3790,10 @@ w32_scroll_bar_handle_click (bar, msg, emacs_event)
      W32Msg *msg;
      struct input_event *emacs_event;
 {
-  if (! GC_WINDOWP (bar->window))
+  if (! WINDOWP (bar->window))
     abort ();
 
-  emacs_event->kind = W32_SCROLL_BAR_CLICK_EVENT;
+  emacs_event->kind = SCROLL_BAR_CLICK_EVENT;
   emacs_event->code = 0;
   /* not really meaningful to distinguish up/down */
   emacs_event->modifiers = msg->dwModifiers;
@@ -4171,6 +3993,8 @@ x_scroll_bar_clear (f)
 static int temp_index;
 static short temp_buffer[100];
 
+/* Temporarily store lead byte of DBCS input sequences.  */
+static char dbcs_lead = 0;
 
 /* Read events coming from the W32 shell.
    This routine is called by the SIGIO handler.
@@ -4314,6 +4138,7 @@ w32_read_socket (sd, expected, hold_quit)
            }
          break;
 
+        case WM_UNICHAR:
        case WM_SYSCHAR:
        case WM_CHAR:
          f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
@@ -4330,8 +4155,84 @@ w32_read_socket (sd, expected, hold_quit)
              if (temp_index == sizeof temp_buffer / sizeof (short))
                temp_index = 0;
              temp_buffer[temp_index++] = msg.msg.wParam;
-             inev.kind = ASCII_KEYSTROKE_EVENT;
-             inev.code = msg.msg.wParam;
+
+             inev.modifiers = msg.dwModifiers;
+             XSETFRAME (inev.frame_or_window, f);
+             inev.timestamp = msg.msg.time;
+
+              if (msg.msg.message == WM_UNICHAR)
+                {
+                  inev.code = msg.msg.wParam;
+                }
+              else if (msg.msg.wParam < 256)
+                {
+                  wchar_t code;
+                  char dbcs[2];
+                  dbcs[0] = 0;
+                  dbcs[1] = (char) msg.msg.wParam;
+
+                  if (dbcs_lead)
+                    {
+                      dbcs[0] = dbcs_lead;
+                      dbcs_lead = 0;
+                      if (!MultiByteToWideChar (CP_ACP, 0, dbcs, 2, &code, 1))
+                        {
+                          /* Garbage */
+                          DebPrint (("Invalid DBCS sequence: %d %d\n",
+                                     dbcs[0], dbcs[1]));
+                          inev.kind = NO_EVENT;
+                          break;
+                        }
+                    }
+                  else if (IsDBCSLeadByteEx (CP_ACP, (BYTE) msg.msg.wParam))
+                    {
+                      dbcs_lead = (char) msg.msg.wParam;
+                      inev.kind = NO_EVENT;
+                      break;
+                    }
+                  else
+                    {
+                      if (!MultiByteToWideChar (CP_ACP, 0, &dbcs[1], 1,
+                                                &code, 1))
+                        {
+                          /* What to do with garbage? */
+                          DebPrint (("Invalid character: %d\n", dbcs[1]));
+                          inev.kind = NO_EVENT;
+                          break;
+                        }
+                    }
+                  inev.code = code;
+                }
+              else
+                {
+                  /* Windows shouldn't generate WM_CHAR events above 0xFF
+                     in non-Unicode message handlers.  */
+                  DebPrint (("Non-byte WM_CHAR: %d\n", msg.msg.wParam));
+                  inev.kind = NO_EVENT;
+                  break;
+                }
+              inev.kind = inev.code < 128 ? ASCII_KEYSTROKE_EVENT
+                                          : MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+           }
+         break;
+
+        case WM_APPCOMMAND:
+         f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
+
+         if (f && !f->iconified)
+           {
+             if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
+                 && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
+               {
+                 clear_mouse_face (dpyinfo);
+                 dpyinfo->mouse_face_hidden = 1;
+               }
+
+             if (temp_index == sizeof temp_buffer / sizeof (short))
+               temp_index = 0;
+             temp_buffer[temp_index++] = msg.msg.wParam;
+             inev.kind = MULTIMEDIA_KEY_EVENT;
+             inev.code = GET_APPCOMMAND_LPARAM(msg.msg.lParam);
              inev.modifiers = msg.dwModifiers;
              XSETFRAME (inev.frame_or_window, f);
              inev.timestamp = msg.msg.time;
@@ -5293,29 +5194,29 @@ x_io_error_quitter (display)
 \f
 /* Changing the font of the frame.  */
 
-/* Give frame F the font named FONTNAME as its default font, and
-   return the full name of that font.  FONTNAME may be a wildcard
-   pattern; in that case, we choose some font that fits the pattern.
-   The return value shows which font we chose.  */
-
 Lisp_Object
-x_new_font (f, fontname)
+x_new_font (f, font_object, fontset)
      struct frame *f;
-     register char *fontname;
+     Lisp_Object font_object;
+     int fontset;
 {
-  struct font_info *fontp
-    = FS_LOAD_FONT (f, 0, fontname, -1);
+  struct font *font = XFONT_OBJECT (font_object);
 
-  if (!fontp)
-    return Qnil;
+  if (fontset < 0)
+    fontset = fontset_from_font (font_object);
+  FRAME_FONTSET (f) = fontset;
+  if (FRAME_FONT (f) == font)
+    /* This font is already set in frame F.  There's nothing more to
+       do.  */
+    return fontset_name (fontset);
 
-  FRAME_FONT (f) = (XFontStruct *) (fontp->font);
-  FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
-  FRAME_FONTSET (f) = -1;
+  BLOCK_INPUT;
 
-  FRAME_COLUMN_WIDTH (f) = fontp->average_width;
-  FRAME_SPACE_WIDTH (f) = fontp->space_width;
-  FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
+  FRAME_FONT (f) = font;
+  FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
+  FRAME_COLUMN_WIDTH (f) = font->average_width;
+  FRAME_SPACE_WIDTH (f) = font->space_width;
+  FRAME_LINE_HEIGHT (f) = font->height;
 
   compute_fringe_widths (f, 1);
 
@@ -5324,7 +5225,7 @@ x_new_font (f, fontname)
     {
       int wid = FRAME_COLUMN_WIDTH (f);
       FRAME_CONFIG_SCROLL_BAR_COLS (f)
-       = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
+       = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid - 1) / wid;
     }
   else
     {
@@ -5333,46 +5234,24 @@ x_new_font (f, fontname)
     }
 
   /* Now make the frame display the given font.  */
-  if (FRAME_W32_WINDOW (f) != 0)
+  if (FRAME_X_WINDOW (f) != 0)
     {
+      /* Don't change the size of a tip frame; there's no point in
+        doing it because it's done in Fx_show_tip, and it leads to
+        problems because the tip frame has no widget.  */
       if (NILP (tip_frame) || XFRAME (tip_frame) != f)
-        x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
+       x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
     }
 
-  return build_string (fontp->full_name);
-}
-\f
-/* Give frame F the fontset named FONTSETNAME as its default font, and
-   return the full name of that fontset.  FONTSETNAME may be a wildcard
-   pattern; in that case, we choose some fontset that fits the pattern.
-   The return value shows which fontset we chose.  */
-
-Lisp_Object
-x_new_fontset (f, fontsetname)
-     struct frame *f;
-     char *fontsetname;
-{
-  int fontset = fs_query_fontset (build_string (fontsetname), 0);
-  Lisp_Object result;
-
-  if (fontset < 0)
-    return Qnil;
-
-  if (FRAME_FONTSET (f) == fontset)
-    /* This fontset is already set in frame F.  There's nothing more
-       to do.  */
-    return fontset_name (fontset);
-
-  result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
-
-  if (!STRINGP (result))
-    /* Can't load ASCII font.  */
-    return Qnil;
+#ifdef HAVE_X_I18N
+  if (FRAME_XIC (f)
+      && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
+    xic_set_xfontset (f, SDATA (fontset_ascii (fontset)));
+#endif
 
-  /* Since x_new_font doesn't update any fontset information, do it now.  */
-  FRAME_FONTSET(f) = fontset;
+  UNBLOCK_INPUT;
 
-  return build_string (fontsetname);
+  return fontset_name (fontset);
 }
 
 \f
@@ -5570,7 +5449,7 @@ x_set_window_size (f, change_gravity, cols, rows)
      resize will happen asynchronously. But on Windows, the menu bar
      automatically wraps when the frame is too narrow to contain it,
      and that causes any calculations made here to come out wrong. The
-     end is some nasty buggy behaviour, including the potential loss
+     end is some nasty buggy behavior, including the potential loss
      of the minibuffer.
 
      Disabling this code is either not sufficient to fix the problems
@@ -5693,9 +5572,9 @@ x_raise_frame (f)
   BLOCK_INPUT;
 
   /* Strictly speaking, raise-frame should only change the frame's Z
-     order, leaving input focus unchanged.  This is reasonable behaviour
+     order, leaving input focus unchanged.  This is reasonable behavior
      on X where the usual policy is point-to-focus.  However, this
-     behaviour would be very odd on Windows where the usual policy is
+     behavior would be very odd on Windows where the usual policy is
      click-to-focus.
 
      On X, if the mouse happens to be over the raised frame, it gets
@@ -5820,8 +5699,15 @@ x_make_frame_visible (f)
 
       f->output_data.w32->asked_for_visible = 1;
 
-/*      my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW);  */
-      my_show_window (f, FRAME_W32_WINDOW (f), SW_SHOWNORMAL);
+      /* The first of these seems to give more expected behavior, but
+         was added as a commented out line in Sept 1997, with the
+         second version remaining uncommented. There may have been
+         some problem with it that led to it not being enabled,
+         so the old version remains commented out below in case we
+         decide we need to go back to it [23.0.60 2008-06-09].  */
+      my_show_window (f, FRAME_W32_WINDOW (f),
+                      f->async_iconified ? SW_RESTORE : SW_SHOW);
+      /* my_show_window (f, FRAME_W32_WINDOW (f), SW_SHOWNORMAL);  */
     }
 
   /* Synchronize to ensure Emacs knows the frame is visible
@@ -5930,6 +5816,12 @@ x_free_frame_resources (f)
 
   BLOCK_INPUT;
 
+  /* We must free faces before destroying windows because some
+     font-driver (e.g. xft) access a window while finishing a
+     face.  */
+  if (FRAME_FACE_CACHE (f))
+    free_frame_faces (f);
+
   if (FRAME_W32_WINDOW (f))
     my_destroy_window (f, FRAME_W32_WINDOW (f));
 
@@ -6029,113 +5921,6 @@ x_wm_set_icon_position (f, icon_x, icon_y)
 }
 
 \f
-/***********************************************************************
-                               Fonts
- ***********************************************************************/
-
-/* The following functions are listed here to help diff stay in step
-   with xterm.c.  See w32fns.c for definitions.
-
-x_get_font_info (f, font_idx)
-x_list_fonts (f, pattern, size, maxnames)
-
- */
-
-#if GLYPH_DEBUG
-
-/* Check that FONT is valid on frame F.  It is if it can be found in F's
-   font table.  */
-
-static void
-x_check_font (f, font)
-     struct frame *f;
-     XFontStruct *font;
-{
-  int i;
-  struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
-
-  xassert (font != NULL);
-
-  for (i = 0; i < dpyinfo->n_fonts; i++)
-    if (dpyinfo->font_table[i].name
-       && font == dpyinfo->font_table[i].font)
-      break;
-
-  xassert (i < dpyinfo->n_fonts);
-}
-
-#endif /* GLYPH_DEBUG != 0 */
-
-/* Set *W to the minimum width, *H to the minimum font height of FONT.
-   Note: There are (broken) X fonts out there with invalid XFontStruct
-   min_bounds contents.  For example, handa@etl.go.jp reports that
-   "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
-   have font->min_bounds.width == 0.  */
-
-static INLINE void
-x_font_min_bounds (font, w, h)
-     XFontStruct *font;
-     int *w, *h;
-{
-  /*
-   * TODO: Windows does not appear to offer min bound, only
-   * average and maximum width, and maximum height.
-   */
-  *h = FONT_HEIGHT (font);
-  *w = FONT_WIDTH (font);
-}
-
-
-/* Compute the smallest character width and smallest font height over
-   all fonts available on frame F.  Set the members smallest_char_width
-   and smallest_font_height in F's x_display_info structure to
-   the values computed.  Value is non-zero if smallest_font_height or
-   smallest_char_width become smaller than they were before.  */
-
-int
-x_compute_min_glyph_bounds (f)
-     struct frame *f;
-{
-  int i;
-  struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
-  XFontStruct *font;
-  int old_width = dpyinfo->smallest_char_width;
-  int old_height = dpyinfo->smallest_font_height;
-
-  dpyinfo->smallest_font_height = 100000;
-  dpyinfo->smallest_char_width = 100000;
-
-  for (i = 0; i < dpyinfo->n_fonts; ++i)
-    if (dpyinfo->font_table[i].name)
-      {
-       struct font_info *fontp = dpyinfo->font_table + i;
-       int w, h;
-
-       font = (XFontStruct *) fontp->font;
-       xassert (font != (XFontStruct *) ~0);
-       x_font_min_bounds (font, &w, &h);
-
-       dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
-       dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
-      }
-
-  xassert (dpyinfo->smallest_char_width > 0
-          && dpyinfo->smallest_font_height > 0);
-
-  return (dpyinfo->n_fonts == 1
-         || dpyinfo->smallest_char_width < old_width
-         || dpyinfo->smallest_font_height < old_height);
-}
-
-/* The following functions are listed here to help diff stay in step
-   with xterm.c.  See w32fns.c for definitions.
-
-x_load_font (f, fontname, size)
-x_query_font (f, fontname)
-x_find_ccl_program (fontp)
-
-*/
-\f
 /***********************************************************************
                            Initialization
  ***********************************************************************/
@@ -6263,14 +6048,12 @@ static struct redisplay_interface w32_redisplay_interface =
   x_flush,
   0,  /* flush_display_optional */
   x_clear_window_mouse_face,
-  w32_get_glyph_overhangs,
+  x_get_glyph_overhangs,
   x_fix_overlapping_area,
   w32_draw_fringe_bitmap,
   w32_define_fringe_bitmap,
   w32_destroy_fringe_bitmap,
-  w32_per_char_metric,
-  w32_encode_char,
-  NULL, /* w32_compute_glyph_string_overhangs */
+  w32_compute_glyph_string_overhangs,
   x_draw_glyph_string,
   w32_define_frame_cursor,
   w32_clear_frame_area,
@@ -6325,7 +6108,6 @@ w32_create_terminal (struct w32_display_info *dpyinfo)
   terminal->memory_below_frame = 0;   /* We don't remember what scrolls
                                         off the bottom. */
 
-#ifdef MULTI_KBOARD
   /* We don't yet support separate terminals on W32, so don't try to share
      keyboards between virtual terminals that are on the same physical
      terminal like X does.  */
@@ -6340,7 +6122,6 @@ w32_create_terminal (struct w32_display_info *dpyinfo)
   if (current_kboard == initial_kboard)
     current_kboard = terminal->kboard;
   terminal->kboard->reference_count++;
-#endif
 
   return terminal;
 }
@@ -6357,12 +6138,6 @@ x_delete_terminal (struct terminal *terminal)
     return;
 
   BLOCK_INPUT;
-  /* Free the fonts in the font table.  */
-  for (i = 0; i < dpyinfo->n_fonts; i++)
-    if (dpyinfo->font_table[i].name)
-      {
-        DeleteObject (((XFontStruct*)(dpyinfo->font_table[i].font))->hfont);
-      }
 
   x_delete_display (dpyinfo);
   UNBLOCK_INPUT;
@@ -6412,7 +6187,7 @@ w32_term_init (display_name, xrm_option, resource_name)
   dpyinfo->resx = GetDeviceCaps (hdc, LOGPIXELSX);
   dpyinfo->resy = GetDeviceCaps (hdc, LOGPIXELSY);
   dpyinfo->has_palette = GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE;
-  dpyinfo->image_cache = make_image_cache ();
+  dpyinfo->terminal->image_cache = make_image_cache ();
   dpyinfo->height_in = dpyinfo->height / dpyinfo->resx;
   dpyinfo->width_in = dpyinfo->width / dpyinfo->resy;
   ReleaseDC (GetDesktopWindow (), hdc);
@@ -6436,16 +6211,9 @@ w32_term_init (display_name, xrm_option, resource_name)
      the bitmaps.  */
   w32_init_fringe (terminal->rif);
 
-#ifndef F_SETOWN_BUG
 #ifdef F_SETOWN
-#ifdef F_SETOWN_SOCK_NEG
-  /* stdin is a socket here */
-  fcntl (connection, F_SETOWN, -getpid ());
-#else /* ! defined (F_SETOWN_SOCK_NEG) */
   fcntl (connection, F_SETOWN, getpid ());
-#endif /* ! defined (F_SETOWN_SOCK_NEG) */
 #endif /* ! defined (F_SETOWN) */
-#endif /* F_SETOWN_BUG */
 
 #ifdef SIGIO
   if (interrupt_input)
@@ -6498,7 +6266,6 @@ x_delete_display (dpyinfo)
     if (dpyinfo->palette)
       DeleteObject(dpyinfo->palette);
   }
-  xfree (dpyinfo->font_table);
   xfree (dpyinfo->w32_id_name);
 
   w32_reset_fringes ();
@@ -6560,46 +6327,30 @@ w32_initialize ()
      program.  Unfortunately, we have good reasons for doing that, so
      instead we need to send messages to windowsThread to make some API
      calls for us (ones that affect, or depend on, the active/focus
-     window state.  */
+     window state.)  */
 #ifdef ATTACH_THREADS
   AttachThreadInput (dwMainThreadId, dwWindowsThreadId, TRUE);
 #endif
 
-  /* Load system settings.  */
+  /* Dynamically link to optional system components.  */
   {
-    UINT smoothing_type;
-    BOOL smoothing_enabled;
+    HANDLE user_lib = LoadLibrary ("user32.dll");
+
+#define LOAD_PROC(lib, fn) pfn##fn = (void *) GetProcAddress (lib, #fn)
+
+    LOAD_PROC (user_lib, SetLayeredWindowAttributes);
 
-    /* If using proportional scroll bars, ensure handle is at least 5 pixels;
-       otherwise use the fixed height.  */
+#undef LOAD_PROC
+
+    FreeLibrary (user_lib);
+
+    /* Ensure scrollbar handle is at least 5 pixels.  */
     vertical_scroll_bar_min_handle = 5;
 
     /* For either kind of scroll bar, take account of the arrows; these
        effectively form the border of the main scroll bar range.  */
     vertical_scroll_bar_top_border = vertical_scroll_bar_bottom_border
       = GetSystemMetrics (SM_CYVSCROLL);
-
-    /* Constants that are not always defined by the system headers
-       since they only exist on certain versions of Windows.  */
-#ifndef SPI_GETFONTSMOOTHING
-#define SPI_GETFONTSMOOTHING 0x4A
-#endif
-#ifndef SPI_GETFONTSMOOTHINGTYPE
-#define SPI_GETFONTSMOOTHINGTYPE 0x0200A
-#endif
-#ifndef FE_FONTSMOOTHINGCLEARTYPE
-#define FE_FONTSMOOTHINGCLEARTYPE 0x2
-#endif
-
-    /* Determine if Cleartype is in use.  Used to enable a hack in
-       the char metric calculations which adds extra pixels to
-       compensate for the "sub-pixels" that are not counted by the
-       system APIs. */
-    cleartype_active =
-      SystemParametersInfo (SPI_GETFONTSMOOTHING, 0, &smoothing_enabled, 0)
-      && smoothing_enabled
-      && SystemParametersInfo (SPI_GETFONTSMOOTHINGTYPE, 0, &smoothing_type, 0)
-      && smoothing_type == FE_FONTSMOOTHINGCLEARTYPE;
   }
 }
 
@@ -6612,8 +6363,7 @@ syms_of_w32term ()
   staticpro (&last_mouse_scroll_bar);
   last_mouse_scroll_bar = Qnil;
 
-  staticpro (&Qvendor_specific_keysyms);
-  Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
+  DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms");
 
   DEFVAR_INT ("w32-num-mouse-buttons",
              &w32_num_mouse_buttons,
@@ -6647,15 +6397,6 @@ When nil, the right-alt and left-ctrl key combination is
 interpreted normally.  */);
   Vw32_recognize_altgr = Qt;
 
-  DEFVAR_BOOL ("w32-enable-unicode-output",
-               &w32_enable_unicode_output,
-               doc: /* Enable the use of Unicode for text output if non-nil.
-Unicode output may prevent some third party applications for displaying
-Far-East Languages on Windows 95/98 from working properly.
-NT uses Unicode internally anyway, so this flag will probably have no
-effect on NT machines.  */);
-  w32_enable_unicode_output = 1;
-
   DEFVAR_BOOL ("w32-use-visible-system-caret",
               &w32_use_visible_system_caret,
               doc: /* Flag to make the system caret visible.