]> code.delx.au - gnu-emacs/blobdiff - src/w32term.c
Revision: miles@gnu.org--gnu-2004/emacs--unicode--0--patch-15
[gnu-emacs] / src / w32term.c
index 4098ee548249eefb28373767144028c89918fbd9..95ccafe415bacfd2c9fc99f04ed091332254e0bd 100644 (file)
@@ -24,25 +24,21 @@ Boston, MA 02111-1307, USA.  */
 #include <stdio.h>
 #include <stdlib.h>
 #include "lisp.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include "lisp.h"
-#include "charset.h"
 #include "blockinput.h"
 #include "blockinput.h"
-
-#include "w32heap.h"
 #include "w32term.h"
 #include "w32term.h"
-#include "w32bdf.h"
-#include <shellapi.h>
 
 #include "systty.h"
 #include "systime.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 <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 "frame.h"
 #include "dispextern.h"
 #include "fontset.h"
@@ -53,9 +49,15 @@ Boston, MA 02111-1307, USA.  */
 #include "disptab.h"
 #include "buffer.h"
 #include "window.h"
 #include "disptab.h"
 #include "buffer.h"
 #include "window.h"
+#include "keyboard.h"
 #include "intervals.h"
 #include "intervals.h"
-#include "composite.h"
-#include "coding.h"
+#include "process.h"
+#include "atimer.h"
+#include "keymap.h"
+
+#include "w32heap.h"
+#include "w32bdf.h"
+#include <shellapi.h>
 
 #define abs(x) ((x) < 0 ? -(x) : (x))
 
 
 #define abs(x) ((x) < 0 ? -(x) : (x))
 
@@ -73,6 +75,11 @@ Lisp_Object Vx_toolkit_scroll_bars;
 static int last_mousemove_x = 0;
 static int last_mousemove_y = 0;
 
 static int last_mousemove_x = 0;
 static int last_mousemove_y = 0;
 
+/* Define GET_WHEEL_DELTA_WPARAM macro if system headers don't.  */
+#ifndef GET_WHEEL_DELTA_WPARAM
+#define GET_WHEEL_DELTA_WPARAM(wparam) ((short)HIWORD (wparam))
+#endif
+
 /* Non-zero means that a HELP_EVENT has been generated since Emacs
    start.  */
 
 /* Non-zero means that a HELP_EVENT has been generated since Emacs
    start.  */
 
@@ -106,6 +113,31 @@ struct w32_display_info *x_display_list;
    FONT-LIST-CACHE records previous values returned by x-list-fonts.  */
 Lisp_Object w32_display_name_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 GetFontUnicodeRanges (not available on 95, 98, ME).  */
+DWORD (PASCAL *pfnGetFontUnicodeRanges) (HDC device, GLYPHSET *ranges);
+
 /* 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.
 /* 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.
@@ -172,7 +204,7 @@ int last_scroll_bar_drag_pos;
 static RECT last_mouse_glyph;
 static Lisp_Object last_mouse_press_frame;
 
 static RECT last_mouse_glyph;
 static Lisp_Object last_mouse_press_frame;
 
-Lisp_Object Vw32_num_mouse_buttons;
+int w32_num_mouse_buttons;
 
 Lisp_Object Vw32_swap_mouse_buttons;
 
 
 Lisp_Object Vw32_swap_mouse_buttons;
 
@@ -216,8 +248,6 @@ static int input_signal_count;
 
 extern Lisp_Object Vcommand_line_args, Vsystem_name;
 
 
 extern Lisp_Object Vcommand_line_args, Vsystem_name;
 
-extern Lisp_Object Qface, Qmouse_face;
-
 #ifndef USE_CRT_DLL
 extern int errno;
 #endif
 #ifndef USE_CRT_DLL
 extern int errno;
 #endif
@@ -256,8 +286,7 @@ static void x_frame_rehighlight P_ ((struct w32_display_info *));
 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
                                   enum text_cursor_kinds));
 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
                                   enum text_cursor_kinds));
-static void w32_clip_to_row P_ ((struct window *, struct glyph_row *,
-                                 HDC, int));
+static void w32_clip_to_row P_ ((struct window *, struct glyph_row *, HDC));
 
 static Lisp_Object Qvendor_specific_keysyms;
 
 
 static Lisp_Object Qvendor_specific_keysyms;
 
@@ -296,8 +325,9 @@ record_event (locus, type)
 #endif /* 0 */
 \f
 
 #endif /* 0 */
 \f
 
-void XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
-                XGCValues *xgcv)
+void
+XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
+          XGCValues *xgcv)
 {
   if (mask & GCForeground)
     gc->foreground = xgcv->foreground;
 {
   if (mask & GCForeground)
     gc->foreground = xgcv->foreground;
@@ -318,7 +348,8 @@ XGCValues *XCreateGC (void * ignore, Window window, unsigned long mask,
   return gc;
 }
 
   return gc;
 }
 
-void XGetGCValues (void* ignore, XGCValues *gc,
+void
+XGetGCValues (void* ignore, XGCValues *gc,
                    unsigned long mask, XGCValues *xgcv)
 {
   XChangeGC (ignore, xgcv, mask, gc);
                    unsigned long mask, XGCValues *xgcv)
 {
   XChangeGC (ignore, xgcv, mask, gc);
@@ -494,7 +525,7 @@ w32_draw_vertical_window_border (w, x, y0, y1)
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   RECT r;
   HDC hdc;
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   RECT r;
   HDC hdc;
-  
+
   r.left = x;
   r.right = x + 1;
   r.top = y0;
   r.left = x;
   r.right = x + 1;
   r.top = y0;
@@ -536,6 +567,9 @@ x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
                                output_cursor.x, output_cursor.y);
 
       x_draw_vertical_border (w);
                                output_cursor.x, output_cursor.y);
 
       x_draw_vertical_border (w);
+
+      draw_window_fringes (w);
+
       UNBLOCK_INPUT;
     }
 
       UNBLOCK_INPUT;
     }
 
@@ -620,11 +654,7 @@ x_after_update_window_line (desired_row)
   xassert (w);
 
   if (!desired_row->mode_line_p && !w->pseudo_window_p)
   xassert (w);
 
   if (!desired_row->mode_line_p && !w->pseudo_window_p)
-    {
-      BLOCK_INPUT;
-      draw_row_fringe_bitmaps (w, desired_row);
-      UNBLOCK_INPUT;
-    }
+    desired_row->redraw_fringe_bitmaps_p = 1;
 
   /* When a window has disappeared, make sure that no rest of
      full-width rows stays visible in the internal border.  Could
 
   /* When a window has disappeared, make sure that no rest of
      full-width rows stays visible in the internal border.  Could
@@ -651,7 +681,7 @@ x_after_update_window_line (desired_row)
       {
        HDC hdc = get_frame_dc (f);
        w32_clear_area (f, hdc, 0, y, width, height);
       {
        HDC hdc = get_frame_dc (f);
        w32_clear_area (f, hdc, 0, y, width, height);
-       w32_clear_area (f, hdc, f->output_data.w32->pixel_width - width,
+       w32_clear_area (f, hdc, FRAME_PIXEL_WIDTH (f) - width,
                        y, width, height);
        release_frame_dc (f, hdc);
       }
                        y, width, height);
        release_frame_dc (f, hdc);
       }
@@ -674,34 +704,79 @@ w32_draw_fringe_bitmap (w, row, p)
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   HDC hdc;
   struct face *face = p->face;
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   HDC hdc;
   struct face *face = p->face;
+  int rowY;
 
   hdc = get_frame_dc (f);
 
   /* Must clip because of partially visible lines.  */
 
   hdc = get_frame_dc (f);
 
   /* Must clip because of partially visible lines.  */
-  w32_clip_to_row (w, row, hdc, 1);
+  rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
+  if (p->y < rowY)
+    {
+      /* Adjust position of "bottom aligned" bitmap on partially
+        visible last row.  */
+      int oldY = row->y;
+      int oldVH = row->visible_height;
+      row->visible_height = p->h;
+      row->y -= rowY - p->y;
+      w32_clip_to_row (w, row, hdc);
+      row->y = oldY;
+      row->visible_height = oldVH;
+    }
+  else
+    w32_clip_to_row (w, row, hdc);
 
 
-  if (p->bx >= 0)
+  if (p->bx >= 0 && !p->overlay_p)
     {
       w32_fill_area (f, hdc, face->background,
                     p->bx, p->by, p->nx, p->ny);
     }
 
     {
       w32_fill_area (f, hdc, face->background,
                     p->bx, p->by, p->nx, p->ny);
     }
 
-  if (p->which != NO_FRINGE_BITMAP)
+  if (p->which)
     {
       HBITMAP pixmap = fringe_bmp[p->which];
       HDC compat_hdc;
       HANDLE horig_obj;
 
       compat_hdc = CreateCompatibleDC (hdc);
     {
       HBITMAP pixmap = fringe_bmp[p->which];
       HDC compat_hdc;
       HANDLE horig_obj;
 
       compat_hdc = CreateCompatibleDC (hdc);
+
       SaveDC (hdc);
 
       horig_obj = SelectObject (compat_hdc, pixmap);
       SaveDC (hdc);
 
       horig_obj = SelectObject (compat_hdc, pixmap);
-      SetTextColor (hdc, face->background);
-      SetBkColor (hdc, face->foreground);
 
 
-      BitBlt (hdc, p->x, p->y, p->wd, p->h,
-             compat_hdc, 0, p->dh,
-             SRCCOPY);
+      /* Paint overlays transparently.  */
+      if (p->overlay_p)
+       {
+         HBRUSH h_brush, h_orig_brush;
+
+         SetTextColor (hdc, BLACK_PIX_DEFAULT (f));
+         SetBkColor (hdc, WHITE_PIX_DEFAULT (f));
+         h_brush = CreateSolidBrush (face->foreground);
+         h_orig_brush = SelectObject (hdc, h_brush);
+
+         BitBlt (hdc, p->x, p->y, p->wd, p->h,
+                 compat_hdc, 0, p->dh,
+                 DSTINVERT);
+         BitBlt (hdc, p->x, p->y, p->wd, p->h,
+                 compat_hdc, 0, p->dh,
+                 0x2E064A);
+         BitBlt (hdc, p->x, p->y, p->wd, p->h,
+                 compat_hdc, 0, p->dh,
+                 DSTINVERT);
+
+         SelectObject (hdc, h_orig_brush);
+         DeleteObject (h_brush);
+       }
+      else
+       {
+         SetTextColor (hdc, face->background);
+         SetBkColor (hdc, (p->cursor_p
+                           ? f->output_data.w32->cursor_pixel
+                           : face->foreground));
+
+         BitBlt (hdc, p->x, p->y, p->wd, p->h,
+                 compat_hdc, 0, p->dh,
+                 SRCCOPY);
+       }
 
       SelectObject (compat_hdc, horig_obj);
       DeleteDC (compat_hdc);
 
       SelectObject (compat_hdc, horig_obj);
       DeleteDC (compat_hdc);
@@ -713,6 +788,25 @@ w32_draw_fringe_bitmap (w, row, p)
   release_frame_dc (f, hdc);
 }
 
   release_frame_dc (f, hdc);
 }
 
+static void
+w32_define_fringe_bitmap (which, bits, h, wd)
+     int which;
+     unsigned short *bits;
+     int h, wd;
+{
+  fringe_bmp[which] = CreateBitmap (wd, h, 1, 1, bits);
+}
+
+static void
+w32_destroy_fringe_bitmap (which)
+     int which;
+{
+  if (fringe_bmp[which])
+    DeleteObject (fringe_bmp[which]);
+  fringe_bmp[which] = 0;
+}
+
+
 \f
 /* This is called when starting Emacs and when restarting after
    suspend.  When starting Emacs, no window is mapped.  And nothing
 \f
 /* This is called when starting Emacs and when restarting after
    suspend.  When starting Emacs, no window is mapped.  And nothing
@@ -742,7 +836,8 @@ w32_reset_terminal_modes (void)
 
 static XCharStruct *w32_per_char_metric P_ ((XFontStruct *,
                                              wchar_t *, int));
 
 static XCharStruct *w32_per_char_metric P_ ((XFontStruct *,
                                              wchar_t *, int));
-static int w32_encode_char P_ ((int, wchar_t *, struct font_info *, int *));
+static int w32_encode_char P_ ((int, wchar_t *, struct font_info *,
+                               struct charset *, int *));
 
 
 /* Get metrics of character CHAR2B in FONT.  Value is always non-null.
 
 
 /* Get metrics of character CHAR2B in FONT.  Value is always non-null.
@@ -889,7 +984,17 @@ w32_per_char_metric (font, char2b, font_type)
   BOOL retval;
 
   xassert (font && char2b);
   BOOL retval;
 
   xassert (font && char2b);
-  xassert (font_type != UNKNOWN_FONT);
+
+  /* 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)
 
   /* Handle the common cases quickly.  */
   if (!font->bdf && font->per_char == NULL)
@@ -898,6 +1003,8 @@ w32_per_char_metric (font, char2b, font_type)
   else if (!font->bdf && *char2b < 128)
     return &font->per_char[*char2b];
 
   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)
   pcm = &font->scratch;
 
   if (font_type == BDF_1D_FONT)
@@ -984,13 +1091,13 @@ w32_use_unicode_for_codepage (codepage)
    the two-byte form of C.  Encoding is returned in *CHAR2B.  */
 
 static int /* enum w32_char_font_type */
    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)
+w32_encode_char (c, char2b, font_info, charset, two_byte_p)
      int c;
      wchar_t *char2b;
      struct font_info *font_info;
      int c;
      wchar_t *char2b;
      struct font_info *font_info;
+     struct charset *charset;
      int * two_byte_p;
 {
      int * two_byte_p;
 {
-  int charset = CHAR_CHARSET (c);
   int codepage;
   int unicode_p = 0;
   int internal_two_byte_p = 0;
   int codepage;
   int unicode_p = 0;
   int internal_two_byte_p = 0;
@@ -998,29 +1105,39 @@ w32_encode_char (c, char2b, font_info, two_byte_p)
   XFontStruct *font = font_info->font;
 
   internal_two_byte_p = w32_font_is_double_byte (font);
   XFontStruct *font = font_info->font;
 
   internal_two_byte_p = w32_font_is_double_byte (font);
+  codepage = font_info->codepage;
+
+  /* If font can output unicode, use the original unicode character.  */
+  if ( font && !font->bdf && w32_use_unicode_for_codepage (codepage)
+       && c >= 0x100)
+    {
+      *char2b = c;
+      unicode_p = 1;
+      internal_two_byte_p = 1;
+    }
 
   /* 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.  */
 
   /* 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)
+  else if (font_info->font_encoder)
     {
       /* It's a program.  */
       struct ccl_program *ccl = font_info->font_encoder;
 
       if (CHARSET_DIMENSION (charset) == 1)
        {
     {
       /* It's a program.  */
       struct ccl_program *ccl = font_info->font_encoder;
 
       if (CHARSET_DIMENSION (charset) == 1)
        {
-         ccl->reg[0] = charset;
+         ccl->reg[0] = CHARSET_ID (charset);
          ccl->reg[1] = XCHAR2B_BYTE2 (char2b);
          ccl->reg[2] = -1;
        }
       else
        {
          ccl->reg[1] = XCHAR2B_BYTE2 (char2b);
          ccl->reg[2] = -1;
        }
       else
        {
-         ccl->reg[0] = charset;
+         ccl->reg[0] = CHARSET_ID (charset);
          ccl->reg[1] = XCHAR2B_BYTE1 (char2b);
          ccl->reg[2] = XCHAR2B_BYTE2 (char2b);
        }
 
          ccl->reg[1] = XCHAR2B_BYTE1 (char2b);
          ccl->reg[2] = XCHAR2B_BYTE2 (char2b);
        }
 
-      ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
+      ccl_driver (ccl, NULL, NULL, 0, 0, Qnil);
 
       /* We assume that MSBs are appropriately set/reset by CCL
         program.  */
 
       /* We assume that MSBs are appropriately set/reset by CCL
         program.  */
@@ -1029,50 +1146,26 @@ w32_encode_char (c, char2b, font_info, two_byte_p)
       else
        STORE_XCHAR2B (char2b, ccl->reg[1], ccl->reg[2]);
     }
       else
        STORE_XCHAR2B (char2b, ccl->reg[1], ccl->reg[2]);
     }
-  else if (font_info->encoding[charset])
+  else if (font_info->encoding_type)
     {
       /* Fixed encoding scheme.  See fontset.h for the meaning of the
         encoding numbers.  */
     {
       /* Fixed encoding scheme.  See fontset.h for the meaning of the
         encoding numbers.  */
-      int enc = font_info->encoding[charset];
+      unsigned char enc = font_info->encoding_type;
 
       if ((enc == 1 || enc == 2)
          && CHARSET_DIMENSION (charset) == 2)
        STORE_XCHAR2B (char2b, XCHAR2B_BYTE1 (char2b) | 0x80, XCHAR2B_BYTE2 (char2b));
 
 
       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))
+      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)
         {
        STORE_XCHAR2B (char2b, XCHAR2B_BYTE1 (char2b), XCHAR2B_BYTE2 (char2b) | 0x80);
       else if (enc == 4)
         {
-          int sjis1, sjis2;
+          int code = (int) (*char2b);
 
 
-          ENCODE_SJIS (XCHAR2B_BYTE1 (char2b), XCHAR2B_BYTE2 (char2b),
-                       sjis1, sjis2);
-          STORE_XCHAR2B (char2b, sjis1, sjis2);
+         JIS_TO_SJIS (code);
+          STORE_XCHAR2B (char2b, (code >> 8), (code & 0xFF));
         }
     }
         }
     }
-  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 (two_byte_p)
     *two_byte_p = internal_two_byte_p;
@@ -1090,6 +1183,143 @@ w32_encode_char (c, char2b, font_info, two_byte_p)
 }
 
 
 }
 
 
+/* Return a char-table whose elements are t if the font FONT_INFO
+   contains a glyph for the corresponding character, and nil if not.
+
+   Fixme: For the moment, this function works only for fonts whose
+   glyph encoding is the same as Unicode (e.g. ISO10646-1 fonts).  */
+
+Lisp_Object
+x_get_font_repertory (f, font_info)
+     FRAME_PTR f;
+     struct font_info *font_info;
+{
+  XFontStruct *font = (XFontStruct *) font_info->font;
+  Lisp_Object table;
+  int min_byte1, max_byte1, min_byte2, max_byte2;
+
+  table = Fmake_char_table (Qnil, Qnil);
+
+  if (!font->bdf && pfnGetFontUnicodeRanges)
+    {
+      GLYPHSET *glyphset;
+      DWORD glyphset_size;
+      HDC display = get_frame_dc (f);
+      HFONT prev_font;
+      int i;
+
+      prev_font = SelectObject (display, font->hfont);
+
+      /* First call GetFontUnicodeRanges to find out how big a structure
+        we need.  */
+      glyphset_size = pfnGetFontUnicodeRanges (display, NULL);
+      if (glyphset_size)
+       {
+         glyphset = (GLYPHSET *) alloca (glyphset_size);
+         glyphset->cbThis = glyphset_size;
+
+         /* Now call it again to get the ranges.  */
+         glyphset_size = pfnGetFontUnicodeRanges (display, glyphset);
+
+         if (glyphset_size)
+           {
+             /* Store the ranges in TABLE.  */
+             for (i = 0; i < glyphset->cRanges; i++)
+               {
+                 int from = glyphset->ranges[i].wcLow;
+                 int to = from + glyphset->ranges[i].cGlyphs - 1;
+                 char_table_set_range (table, from, to, Qt);
+               }
+           }
+       }
+
+      SelectObject (display, prev_font);
+      release_frame_dc (f, display);
+
+      /* If we got the information we wanted above, then return it.  */
+      if (glyphset_size)
+       return table;
+    }
+
+#if 0 /* TODO: Convert to work on Windows so BDF and older platforms work.  */
+  /* When GetFontUnicodeRanges is not available or does not work,
+     work it out manually.  */
+  min_byte1 = font->min_byte1;
+  max_byte1 = font->max_byte1;
+  min_byte2 = font->min_char_or_byte2;
+  max_byte2 = font->max_char_or_byte2;
+  if (min_byte1 == 0 && max_byte1 == 0)
+    {
+      if (! font->per_char || font->all_chars_exist == True)
+       char_table_set_range (table, min_byte2, max_byte2, Qt);
+      else
+       {
+         XCharStruct *pcm = font->per_char;
+         int from = -1;
+         int i;
+
+         for (i = min_byte2; i <= max_byte2; i++, pcm++)
+           {
+             if (pcm->width == 0 && pcm->rbearing == pcm->lbearing)
+               {
+                 if (from >= 0)
+                   {
+                     char_table_set_range (table, from, i - 1, Qt);
+                     from = -1;
+                   }
+               }
+             else if (from < 0)
+               from = i;
+           }
+         if (from >= 0)
+           char_table_set_range (table, from, i - 1, Qt);
+       }
+    }
+  else
+    {
+      if (! font->per_char || font->all_chars_exist == True)
+       {
+         int i;
+
+         for (i = min_byte1; i <= max_byte1; i++)
+           char_table_set_range (table,
+                                 (i << 8) | min_byte2, (i << 8) | max_byte2,
+                                 Qt);
+       }
+      else
+       {
+         XCharStruct *pcm = font->per_char;
+         int i;
+
+         for (i = min_byte1; i <= max_byte1; i++)
+           {
+             int from = -1;
+             int j;
+
+             for (j = min_byte2; j <= max_byte2; j++, pcm++)
+               {
+                 if (pcm->width == 0 && pcm->rbearing == pcm->lbearing)
+                   {
+                     if (from >= 0)
+                       {
+                         char_table_set_range (table, (i << 8) | from,
+                                               (i << 8) | (j - 1), Qt);
+                         from = -1;
+                       }
+                   }
+                 else if (from < 0)
+                   from = j;
+               }
+             if (from >= 0)
+               char_table_set_range (table, (i << 8) | from,
+                                     (i << 8) | (j - 1), Qt);
+           }
+       }
+    }
+#endif
+  return table;
+}
+
 \f
 /***********************************************************************
                            Glyph display
 \f
 /***********************************************************************
                            Glyph display
@@ -1105,9 +1335,9 @@ w32_text_out (s, x, y,chars,nchars)
      wchar_t * chars;
      int nchars;
 {
      wchar_t * chars;
      int nchars;
 {
-  int charset_dim = w32_font_is_double_byte (s->gc->font) ? 2 : 1;
-  if (s->gc->font->bdf)
-    w32_BDF_TextOut (s->gc->font->bdf, s->hdc,
+  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)
                      x, y, (char *) chars, charset_dim,
                      nchars * charset_dim, 0);
   else if (s->first_glyph->font_type == UNICODE_FONT)
@@ -1141,7 +1371,8 @@ static void w32_draw_image_foreground_1 P_ ((struct glyph_string *, HBITMAP));
 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
                                           int, int, int));
 static void w32_draw_relief_rect P_ ((struct frame *, int, int, int, int,
 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
                                           int, int, int));
 static void w32_draw_relief_rect P_ ((struct frame *, int, int, int, int,
-                                   int, int, int, int, RECT *));
+                                     int, int, int, int, int, int,
+                                     RECT *));
 static void w32_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
                                 int, int, int, RECT *));
 
 static void w32_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
                                 int, int, int, RECT *));
 
@@ -1219,9 +1450,9 @@ x_set_mouse_face_gc (s)
     face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
 
   if (s->first_glyph->type == CHAR_GLYPH)
     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
   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);
 
   s->face = FACE_FROM_ID (s->f, face_id);
   PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
 
@@ -1722,9 +1953,10 @@ x_setup_relief_colors (s)
 
 static void
 w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
 
 static void
 w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
-                      raised_p, left_p, right_p, clip_rect)
+                      raised_p, top_p, bot_p, left_p, right_p, clip_rect)
      struct frame *f;
      struct frame *f;
-     int left_x, top_y, right_x, bottom_y, width, left_p, right_p, raised_p;
+     int left_x, top_y, right_x, bottom_y, width;
+     int top_p, bot_p, left_p, right_p, raised_p;
      RECT *clip_rect;
 {
   int i;
      RECT *clip_rect;
 {
   int i;
@@ -1739,10 +1971,11 @@ w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
   w32_set_clip_rectangle (hdc, clip_rect);
 
   /* Top.  */
   w32_set_clip_rectangle (hdc, clip_rect);
 
   /* Top.  */
-  for (i = 0; i < width; ++i)
-    w32_fill_area (f, hdc, gc.foreground,
-                  left_x + i * left_p, top_y + i,
-                  right_x - left_x - i * (left_p + right_p ) + 1, 1);
+  if (top_p)
+    for (i = 0; i < width; ++i)
+      w32_fill_area (f, hdc, gc.foreground,
+                    left_x + i * left_p, top_y + i,
+                    right_x - left_x - i * (left_p + right_p ) + 1, 1);
 
   /* Left.  */
   if (left_p)
 
   /* Left.  */
   if (left_p)
@@ -1757,10 +1990,11 @@ w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
     gc.foreground = f->output_data.w32->white_relief.gc->foreground;
 
   /* Bottom.  */
     gc.foreground = f->output_data.w32->white_relief.gc->foreground;
 
   /* Bottom.  */
-  for (i = 0; i < width; ++i)
-    w32_fill_area (f, hdc, gc.foreground,
-                  left_x + i * left_p, bottom_y - i,
-                  right_x - left_x - i * (left_p + right_p) + 1, 1);
+  if (bot_p)
+    for (i = 0; i < width; ++i)
+      w32_fill_area (f, hdc, gc.foreground,
+                    left_x + i * left_p, bottom_y - i,
+                    right_x - left_x - i * (left_p + right_p) + 1, 1);
 
   /* Right.  */
   if (right_p)
 
   /* Right.  */
   if (right_p)
@@ -1832,9 +2066,10 @@ x_draw_glyph_string_box (s)
   if (s->row->full_width_p
       && !s->w->pseudo_window_p)
     {
   if (s->row->full_width_p
       && !s->w->pseudo_window_p)
     {
-      last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f);
-      if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
-       last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
+      last_x += WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (s->w);
+      if (s->area != RIGHT_MARGIN_AREA
+         || WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (s->w))
+       last_x += WINDOW_RIGHT_FRINGE_WIDTH (s->w);
     }
 
   /* The glyph that may have a right box line.  */
     }
 
   /* The glyph that may have a right box line.  */
@@ -1869,7 +2104,7 @@ x_draw_glyph_string_box (s)
     {
       x_setup_relief_colors (s);
       w32_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
     {
       x_setup_relief_colors (s);
       w32_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
-                            width, raised_p, left_p, right_p, &clip_rect);
+                            width, raised_p, 1, 1, left_p, right_p, &clip_rect);
     }
 }
 
     }
 }
 
@@ -1880,21 +2115,22 @@ static void
 x_draw_image_foreground (s)
      struct glyph_string *s;
 {
 x_draw_image_foreground (s)
      struct glyph_string *s;
 {
-  int x;
-  int y = s->ybase - image_ascent (s->img, s->face);
+  int x = s->x;
+  int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
 
   /* If first glyph of S has a left box line, start drawing it to the
      right of that line.  */
   if (s->face->box != FACE_NO_BOX
 
   /* If first glyph of S has a left box line, start drawing it to the
      right of that line.  */
   if (s->face->box != FACE_NO_BOX
-      && s->first_glyph->left_box_line_p)
-    x = s->x + abs (s->face->box_line_width);
-  else
-    x = s->x;
+      && s->first_glyph->left_box_line_p
+      && s->slice.x == 0)
+    x += abs (s->face->box_line_width);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
-  x += s->img->hmargin;
-  y += s->img->vmargin;
+  if (s->slice.x == 0)
+    x += s->img->hmargin;
+  if (s->slice.y == 0)
+    y += s->img->vmargin;
 
   SaveDC (s->hdc);
 
 
   SaveDC (s->hdc);
 
@@ -1916,12 +2152,12 @@ x_draw_image_foreground (s)
          SetTextColor (s->hdc, RGB (255, 255, 255));
          SetBkColor (s->hdc, RGB (0, 0, 0));
 
          SetTextColor (s->hdc, RGB (255, 255, 255));
          SetBkColor (s->hdc, RGB (0, 0, 0));
 
-         BitBlt (s->hdc, x, y, s->img->width, s->img->height,
-                 compat_hdc, 0, 0, SRCINVERT);
-         BitBlt (s->hdc, x, y, s->img->width, s->img->height,
-                 mask_dc, 0, 0, SRCAND);
-         BitBlt (s->hdc, x, y, s->img->width, s->img->height,
-                 compat_hdc, 0, 0, SRCINVERT);
+         BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
+                 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
+         BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
+                 mask_dc, s->slice.x, s->slice.y, SRCAND);
+         BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
+                 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
 
          SelectObject (mask_dc, mask_orig_obj);
          DeleteDC (mask_dc);
 
          SelectObject (mask_dc, mask_orig_obj);
          DeleteDC (mask_dc);
@@ -1931,8 +2167,8 @@ x_draw_image_foreground (s)
          SetTextColor (s->hdc, s->gc->foreground);
          SetBkColor (s->hdc, s->gc->background);
 
          SetTextColor (s->hdc, s->gc->foreground);
          SetBkColor (s->hdc, s->gc->background);
 
-          BitBlt (s->hdc, x, y, s->img->width, s->img->height,
-                  compat_hdc, 0, 0, SRCCOPY);
+          BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
+                  compat_hdc, s->slice.x, s->slice.y, SRCCOPY);
 
          /* When the image has a mask, we can expect that at
             least part of a mouse highlight or a block cursor will
 
          /* When the image has a mask, we can expect that at
             least part of a mouse highlight or a block cursor will
@@ -1945,7 +2181,8 @@ x_draw_image_foreground (s)
              int r = s->img->relief;
              if (r < 0) r = -r;
              w32_draw_rectangle (s->hdc, s->gc, x - r, y - r ,
              int r = s->img->relief;
              if (r < 0) r = -r;
              w32_draw_rectangle (s->hdc, s->gc, x - r, y - r ,
-                                 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
+                                 s->slice.width + r*2 - 1,
+                                 s->slice.height + r*2 - 1);
            }
        }
 
            }
        }
 
@@ -1956,8 +2193,8 @@ x_draw_image_foreground (s)
       DeleteDC (compat_hdc);
     }
   else
       DeleteDC (compat_hdc);
     }
   else
-    w32_draw_rectangle (s->hdc, s->gc, x, y, s->img->width -1,
-                        s->img->height - 1);
+    w32_draw_rectangle (s->hdc, s->gc, x, y,
+                       s->slice.width - 1, s->slice.height - 1);
 
   RestoreDC (s->hdc ,-1);
 }
 
   RestoreDC (s->hdc ,-1);
 }
@@ -1972,21 +2209,22 @@ x_draw_image_relief (s)
 {
   int x0, y0, x1, y1, thick, raised_p;
   RECT r;
 {
   int x0, y0, x1, y1, thick, raised_p;
   RECT r;
-  int x;
-  int y = s->ybase - image_ascent (s->img, s->face);
+  int x = s->x;
+  int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
 
   /* If first glyph of S has a left box line, start drawing it to the
      right of that line.  */
   if (s->face->box != FACE_NO_BOX
 
   /* If first glyph of S has a left box line, start drawing it to the
      right of that line.  */
   if (s->face->box != FACE_NO_BOX
-      && s->first_glyph->left_box_line_p)
-    x = s->x + abs (s->face->box_line_width);
-  else
-    x = s->x;
+      && s->first_glyph->left_box_line_p
+      && s->slice.x == 0)
+    x += abs (s->face->box_line_width);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
-  x += s->img->hmargin;
-  y += s->img->vmargin;
+  if (s->slice.x == 0)
+    x += s->img->hmargin;
+  if (s->slice.y == 0)
+    y += s->img->vmargin;
 
   if (s->hl == DRAW_IMAGE_SUNKEN
       || s->hl == DRAW_IMAGE_RAISED)
 
   if (s->hl == DRAW_IMAGE_SUNKEN
       || s->hl == DRAW_IMAGE_RAISED)
@@ -2002,12 +2240,17 @@ x_draw_image_relief (s)
 
   x0 = x - thick;
   y0 = y - thick;
 
   x0 = x - thick;
   y0 = y - thick;
-  x1 = x + s->img->width + thick - 1;
-  y1 = y + s->img->height + thick - 1;
+  x1 = x + s->slice.width + thick - 1;
+  y1 = y + s->slice.height + thick - 1;
 
   x_setup_relief_colors (s);
   get_glyph_string_clip_rect (s, &r);
 
   x_setup_relief_colors (s);
   get_glyph_string_clip_rect (s, &r);
-  w32_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
+  w32_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
+                       s->slice.y == 0,
+                       s->slice.y + s->slice.height == s->img->height,
+                       s->slice.x == 0,
+                       s->slice.x + s->slice.width == s->img->width,
+                       &r);
 }
 
 
 }
 
 
@@ -2020,21 +2263,22 @@ w32_draw_image_foreground_1 (s, pixmap)
 {
   HDC hdc = CreateCompatibleDC (s->hdc);
   HGDIOBJ orig_hdc_obj = SelectObject (hdc, pixmap);
 {
   HDC hdc = CreateCompatibleDC (s->hdc);
   HGDIOBJ orig_hdc_obj = SelectObject (hdc, pixmap);
-  int x;
-  int y = s->ybase - s->y - image_ascent (s->img, s->face);
+  int x = 0;
+  int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
 
   /* If first glyph of S has a left box line, start drawing it to the
      right of that line.  */
   if (s->face->box != FACE_NO_BOX
 
   /* If first glyph of S has a left box line, start drawing it to the
      right of that line.  */
   if (s->face->box != FACE_NO_BOX
-      && s->first_glyph->left_box_line_p)
-    x = abs (s->face->box_line_width);
-  else
-    x = 0;
+      && s->first_glyph->left_box_line_p
+      && s->slice.x == 0)
+    x += abs (s->face->box_line_width);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
-  x += s->img->hmargin;
-  y += s->img->vmargin;
+  if (s->slice.x == 0)
+    x += s->img->hmargin;
+  if (s->slice.y == 0)
+    y += s->img->vmargin;
 
   if (s->img->pixmap)
     {
 
   if (s->img->pixmap)
     {
@@ -2050,12 +2294,12 @@ w32_draw_image_foreground_1 (s, pixmap)
 
          SetTextColor (hdc, RGB (0, 0, 0));
          SetBkColor (hdc, RGB (255, 255, 255));
 
          SetTextColor (hdc, RGB (0, 0, 0));
          SetBkColor (hdc, RGB (255, 255, 255));
-         BitBlt (hdc, x, y, s->img->width, s->img->height,
-                 compat_hdc, 0, 0, SRCINVERT);
-         BitBlt (hdc, x, y, s->img->width, s->img->height,
-                 mask_dc, 0, 0, SRCAND);
-         BitBlt (hdc, x, y, s->img->width, s->img->height,
-                 compat_hdc, 0, 0, SRCINVERT);
+         BitBlt (hdc, x, y, s->slice.width, s->slice.height,
+                 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
+         BitBlt (hdc, x, y, s->slice.width, s->slice.height,
+                 mask_dc, s->slice.x, s->slice.y, SRCAND);
+         BitBlt (hdc, x, y, s->slice.width, s->slice.height,
+                 compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
 
          SelectObject (mask_dc, mask_orig_obj);
          DeleteDC (mask_dc);
 
          SelectObject (mask_dc, mask_orig_obj);
          DeleteDC (mask_dc);
@@ -2065,8 +2309,8 @@ w32_draw_image_foreground_1 (s, pixmap)
          SetTextColor (hdc, s->gc->foreground);
          SetBkColor (hdc, s->gc->background);
 
          SetTextColor (hdc, s->gc->foreground);
          SetBkColor (hdc, s->gc->background);
 
-          BitBlt (hdc, x, y, s->img->width, s->img->height,
-                  compat_hdc, 0, 0, SRCCOPY);
+          BitBlt (hdc, x, y, s->slice.width, s->slice.height,
+                  compat_hdc, s->slice.x, s->slice.y, SRCCOPY);
 
          /* When the image has a mask, we can expect that at
             least part of a mouse highlight or a block cursor will
 
          /* When the image has a mask, we can expect that at
             least part of a mouse highlight or a block cursor will
@@ -2078,8 +2322,9 @@ w32_draw_image_foreground_1 (s, pixmap)
            {
              int r = s->img->relief;
              if (r < 0) r = -r;
            {
              int r = s->img->relief;
              if (r < 0) r = -r;
-             w32_draw_rectangle (hdc, s->gc, x - r, y - r ,
-                                 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
+             w32_draw_rectangle (hdc, s->gc, x - r, y - r,
+                                 s->slice.width + r*2 - 1,
+                                 s->slice.height + r*2 - 1);
            }
        }
 
            }
        }
 
@@ -2089,8 +2334,8 @@ w32_draw_image_foreground_1 (s, pixmap)
       DeleteDC (compat_hdc);
     }
   else
       DeleteDC (compat_hdc);
     }
   else
-    w32_draw_rectangle (hdc, s->gc, x, y, s->img->width - 1,
-                        s->img->height - 1);
+    w32_draw_rectangle (hdc, s->gc, x, y,
+                       s->slice.width - 1, s->slice.height - 1);
 
   SelectObject (hdc, orig_hdc_obj);
   DeleteDC (hdc);
 
   SelectObject (hdc, orig_hdc_obj);
   DeleteDC (hdc);
@@ -2149,19 +2394,22 @@ x_draw_image_glyph_string (s)
      taller than image or if image has a clip mask to reduce
      flickering.  */
   s->stippled_p = s->face->stipple != 0;
      taller than image or if image has a clip mask to reduce
      flickering.  */
   s->stippled_p = s->face->stipple != 0;
-  if (height > s->img->height
+  if (height > s->slice.height
       || s->img->hmargin
       || s->img->vmargin
       || s->img->mask
       || s->img->pixmap == 0
       || s->width != s->background_width)
     {
       || s->img->hmargin
       || s->img->vmargin
       || s->img->mask
       || s->img->pixmap == 0
       || s->width != s->background_width)
     {
-      if (box_line_hwidth && s->first_glyph->left_box_line_p)
-       x = s->x + box_line_hwidth;
-      else
-       x = s->x;
+      x = s->x;
+      if (s->first_glyph->left_box_line_p
+         && s->slice.x == 0)
+       x += box_line_hwidth;
+
+      y = s->y;
+      if (s->slice.y == 0)
+       y += box_line_vwidth;
 
 
-      y = s->y + box_line_vwidth;
 #if 0 /* TODO: figure out if we need to do this on Windows.  */
       if (s->img->mask)
        {
 #if 0 /* TODO: figure out if we need to do this on Windows.  */
       if (s->img->mask)
        {
@@ -2256,7 +2504,7 @@ x_draw_stretch_glyph_string (s)
     {
       /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
         as wide as the stretch glyph.  */
     {
       /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
         as wide as the stretch glyph.  */
-      int width = min (CANON_X_UNIT (s->f), s->background_width);
+      int width = min (FRAME_COLUMN_WIDTH (s->f), s->background_width);
 
       /* Draw cursor.  */
       x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
 
       /* Draw cursor.  */
       x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
@@ -2601,8 +2849,6 @@ x_scroll_run (w, run)
      without mode lines.  Include in this box the left and right
      fringes of W.  */
   window_box (w, -1, &x, &y, &width, &height);
      without mode lines.  Include in this box the left and right
      fringes of W.  */
   window_box (w, -1, &x, &y, &width, &height);
-  width += FRAME_X_FRINGE_WIDTH (f);
-  x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
 
   from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
   to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
 
   from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
   to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
@@ -2911,10 +3157,22 @@ construct_mouse_wheel (result, msg, f)
      struct frame *f;
 {
   POINT p;
      struct frame *f;
 {
   POINT p;
-  result->kind = MOUSE_WHEEL_EVENT;
-  result->code = (short) HIWORD (msg->msg.wParam);
+  int delta;
+
+  result->kind = WHEEL_EVENT;
+  result->code = 0;
   result->timestamp = msg->msg.time;
   result->timestamp = msg->msg.time;
-  result->modifiers = msg->dwModifiers;
+
+  /* A WHEEL_DELTA positive value indicates that the wheel was rotated
+     forward, away from the user (up); a negative value indicates that
+     the wheel was rotated backward, toward the user (down).  */
+  delta = GET_WHEEL_DELTA_WPARAM (msg->msg.wParam);
+
+  /* The up and down modifiers indicate if the wheel was rotated up or
+     down based on WHEEL_DELTA value.  */
+  result->modifiers = (msg->dwModifiers
+                       | ((delta < 0 ) ? down_modifier : up_modifier));
+
   p.x = LOWORD (msg->msg.lParam);
   p.y = HIWORD (msg->msg.lParam);
   ScreenToClient (msg->msg.hwnd, &p);
   p.x = LOWORD (msg->msg.lParam);
   p.y = HIWORD (msg->msg.lParam);
   ScreenToClient (msg->msg.hwnd, &p);
@@ -3035,7 +3293,6 @@ note_mouse_movement (frame, msg)
 static struct scroll_bar *x_window_to_scroll_bar ();
 static void x_scroll_bar_report_motion ();
 static void x_check_fullscreen P_ ((struct frame *));
 static struct scroll_bar *x_window_to_scroll_bar ();
 static void x_scroll_bar_report_motion ();
 static void x_check_fullscreen P_ ((struct frame *));
-static void x_check_fullscreen_move P_ ((struct frame *));
 static int glyph_rect P_ ((struct frame *f, int, int, RECT *));
 
 
 static int glyph_rect P_ ((struct frame *f, int, int, RECT *));
 
 
@@ -3070,15 +3327,14 @@ glyph_rect (f, x, y, rect)
 {
   Lisp_Object window;
 
 {
   Lisp_Object window;
 
-  window = window_from_coordinates (f, x, y, 0, 0);
+  window = window_from_coordinates (f, x, y, 0, &x, &y, 0);
+
   if (!NILP (window))
     {
       struct window *w = XWINDOW (window);
       struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
       struct glyph_row *end = r + w->current_matrix->nrows - 1;
 
   if (!NILP (window))
     {
       struct window *w = XWINDOW (window);
       struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
       struct glyph_row *end = r + w->current_matrix->nrows - 1;
 
-      frame_to_window_pixel_xy (w, &x, &y);
-
       for (; r < end && r->enabled_p; ++r)
        if (r->y <= y && r->y + r->height > y)
          {
       for (; r < end && r->enabled_p; ++r)
        if (r->y <= y && r->y + r->height > y)
          {
@@ -3093,7 +3349,10 @@ glyph_rect (f, x, y, rect)
            if (x < r->x)
              {
                /* x is to the left of the first glyph in the row.  */
            if (x < r->x)
              {
                /* x is to the left of the first glyph in the row.  */
-               rect->left = XINT (w->left);
+               /* Shouldn't this be a pixel value?
+                  WINDOW_LEFT_EDGE_X (w) seems to be the right value.
+                  ++KFS */
+               rect->left = WINDOW_LEFT_EDGE_COL (w);
                rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
                return 1;
              }
                rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
                return 1;
              }
@@ -3109,7 +3368,10 @@ glyph_rect (f, x, y, rect)
 
            /* x is to the right of the last glyph in the row.  */
            rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
 
            /* x is to the right of the last glyph in the row.  */
            rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
-           rect->right = XINT (w->left) + XINT (w->width);
+           /* Shouldn't this be a pixel value?
+              WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
+              ++KFS */
+           rect->right = WINDOW_RIGHT_EDGE_COL (w);
            return 1;
          }
     }
            return 1;
          }
     }
@@ -3129,7 +3391,7 @@ remember_mouse_glyph (f1, gx, gy)
       int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
       int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
 
       int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
       int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
 
-      /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
+      /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
         round down even for negative values.  */
       if (gx < 0)
        gx -= width - 1;
         round down even for negative values.  */
       if (gx < 0)
        gx -= width - 1;
@@ -3570,31 +3832,26 @@ w32_set_vertical_scroll_bar (w, portion, whole, position)
   struct frame *f = XFRAME (w->frame);
   struct scroll_bar *bar;
   int top, height, left, sb_left, width, sb_width;
   struct frame *f = XFRAME (w->frame);
   struct scroll_bar *bar;
   int top, height, left, sb_left, width, sb_width;
-  int window_x, window_y, window_width, window_height;
+  int window_y, window_height;
 
   /* Get window dimensions.  */
 
   /* Get window dimensions.  */
-  window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
+  window_box (w, -1, 0, &window_y, 0, &window_height);
   top  = window_y;
   top  = window_y;
-  width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
+  width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
   height = window_height;
 
   /* Compute the left edge of the scroll bar area.  */
   height = window_height;
 
   /* Compute the left edge of the scroll bar area.  */
-  if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
-    left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
-  else
-    left = XFASTINT (w->left);
-  left *= CANON_X_UNIT (f);
-  left += FRAME_INTERNAL_BORDER_WIDTH (f);
+  left = WINDOW_SCROLL_BAR_AREA_X (w);
 
   /* Compute the width of the scroll bar which might be less than
      the width of the area reserved for the scroll bar.  */
 
   /* Compute the width of the scroll bar which might be less than
      the width of the area reserved for the scroll bar.  */
-  if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
-    sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
+  if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
+    sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
   else
     sb_width = width;
 
   /* Compute the left edge of the scroll bar.  */
   else
     sb_width = width;
 
   /* Compute the left edge of the scroll bar.  */
-  if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
+  if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
     sb_left = left + width - sb_width - (width - sb_width) / 2;
   else
     sb_left = left + (width - sb_width) / 2;
     sb_left = left + width - sb_width - (width - sb_width) / 2;
   else
     sb_left = left + (width - sb_width) / 2;
@@ -4033,8 +4290,6 @@ static short temp_buffer[100];
    This routine is called by the SIGIO handler.
    We return as soon as there are no more events to be read.
 
    This routine is called by the SIGIO handler.
    We return as soon as there are no more events to be read.
 
-   Events representing keys are stored in buffer BUFP,
-   which can hold up to NUMCHARS characters.
    We return the number of characters stored into the buffer,
    thus pretending to be `read'.
 
    We return the number of characters stored into the buffer,
    thus pretending to be `read'.
 
@@ -4050,11 +4305,10 @@ static short temp_buffer[100];
 */
 
 int
 */
 
 int
-w32_read_socket (sd, bufp, numchars, expected)
+w32_read_socket (sd, expected, hold_quit)
      register int sd;
      register int sd;
-     /* register */ struct input_event *bufp;
-     /* register */ int numchars;
      int expected;
      int expected;
+     struct input_event *hold_quit;
 {
   int count = 0;
   int check_visibility = 0;
 {
   int count = 0;
   int check_visibility = 0;
@@ -4074,13 +4328,16 @@ w32_read_socket (sd, bufp, numchars, expected)
   /* So people can tell when we have read the available input.  */
   input_signal_count++;
 
   /* So people can tell when we have read the available input.  */
   input_signal_count++;
 
-  if (numchars <= 0)
-    abort ();                   /* Don't think this happens. */
-
-  /* TODO: tool-bars, ghostscript integration, mouse
-     cursors. */
+  /* TODO: ghostscript integration. */
   while (get_next_msg (&msg, FALSE))
     {
   while (get_next_msg (&msg, FALSE))
     {
+      struct input_event inev;
+      int do_help = 0;
+
+      EVENT_INIT (inev);
+      inev.kind = NO_EVENT;
+      inev.arg = Qnil;
+
       switch (msg.msg.message)
        {
        case WM_PAINT:
       switch (msg.msg.message)
        {
        case WM_PAINT:
@@ -4109,12 +4366,8 @@ w32_read_socket (sd, bufp, numchars, expected)
                     visibility changes properly.  */
                  if (f->iconified)
                    {
                     visibility changes properly.  */
                  if (f->iconified)
                    {
-                     bufp->kind = DEICONIFY_EVENT;
-                     XSETFRAME (bufp->frame_or_window, f);
-                     bufp->arg = Qnil;
-                     bufp++;
-                     count++;
-                     numchars--;
+                     inev.kind = DEICONIFY_EVENT;
+                     XSETFRAME (inev.frame_or_window, f);
                    }
                  else if (! NILP (Vframe_list)
                           && ! NILP (XCDR (Vframe_list)))
                    }
                  else if (! NILP (Vframe_list)
                           && ! NILP (XCDR (Vframe_list)))
@@ -4144,17 +4397,10 @@ w32_read_socket (sd, bufp, numchars, expected)
 
          if (f)
            {
 
          if (f)
            {
-             if (numchars == 0)
-               abort ();
-
-             bufp->kind = LANGUAGE_CHANGE_EVENT;
-             XSETFRAME (bufp->frame_or_window, f);
-             bufp->arg = Qnil;
-             bufp->code = msg.msg.wParam;
-             bufp->modifiers = msg.msg.lParam & 0xffff;
-             bufp++;
-             count++;
-             numchars--;
+             inev.kind = LANGUAGE_CHANGE_EVENT;
+             XSETFRAME (inev.frame_or_window, f);
+             inev.code = msg.msg.wParam;
+             inev.modifiers = msg.msg.lParam & 0xffff;
            }
          break;
 
            }
          break;
 
@@ -4166,22 +4412,18 @@ w32_read_socket (sd, bufp, numchars, expected)
            {
              if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
                {
            {
              if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
                {
-                 dpyinfo->mouse_face_hidden = 1;
                  clear_mouse_face (dpyinfo);
                  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;
                }
 
              if (temp_index == sizeof temp_buffer / sizeof (short))
                temp_index = 0;
              temp_buffer[temp_index++] = msg.msg.wParam;
-             bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
-             bufp->code = msg.msg.wParam;
-             bufp->modifiers = msg.dwModifiers;
-             XSETFRAME (bufp->frame_or_window, f);
-             bufp->arg = Qnil;
-             bufp->timestamp = msg.msg.time;
-             bufp++;
-             numchars--;
-             count++;
+             inev.kind = NON_ASCII_KEYSTROKE_EVENT;
+             inev.code = msg.msg.wParam;
+             inev.modifiers = msg.dwModifiers;
+             XSETFRAME (inev.frame_or_window, f);
+             inev.timestamp = msg.msg.time;
            }
          break;
 
            }
          break;
 
@@ -4193,22 +4435,18 @@ w32_read_socket (sd, bufp, numchars, expected)
            {
              if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
                {
            {
              if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
                {
-                 dpyinfo->mouse_face_hidden = 1;
                  clear_mouse_face (dpyinfo);
                  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;
                }
 
              if (temp_index == sizeof temp_buffer / sizeof (short))
                temp_index = 0;
              temp_buffer[temp_index++] = msg.msg.wParam;
-             bufp->kind = ASCII_KEYSTROKE_EVENT;
-             bufp->code = msg.msg.wParam;
-             bufp->modifiers = msg.dwModifiers;
-             XSETFRAME (bufp->frame_or_window, f);
-             bufp->arg = Qnil;
-             bufp->timestamp = msg.msg.time;
-             bufp++;
-             numchars--;
-             count++;
+             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;
            }
          break;
 
            }
          break;
 
@@ -4246,7 +4484,7 @@ w32_read_socket (sd, bufp, numchars, expected)
                  int x = LOWORD (msg.msg.lParam);
                  int y = HIWORD (msg.msg.lParam);
 
                  int x = LOWORD (msg.msg.lParam);
                  int y = HIWORD (msg.msg.lParam);
 
-                 window = window_from_coordinates (f, x, y, 0, 0);
+                 window = window_from_coordinates (f, x, y, 0, 0, 0, 0);
 
                  /* Window will be selected only when it is not
                     selected now and last mouse movement event was
 
                  /* Window will be selected only when it is not
                     selected now and last mouse movement event was
@@ -4254,13 +4492,10 @@ w32_read_socket (sd, bufp, numchars, expected)
                     iff it is active.  */
                  if (WINDOWP(window)
                      && !EQ (window, last_window)
                     iff it is active.  */
                  if (WINDOWP(window)
                      && !EQ (window, last_window)
-                     && !EQ (window, selected_window)
-                     && numchars > 0)
+                     && !EQ (window, selected_window))
                    {
                    {
-                     bufp->kind = SELECT_WINDOW_EVENT;
-                     bufp->frame_or_window = window;
-                     bufp->arg = Qnil;
-                     ++bufp, ++count, --numchars;
+                     inev.kind = SELECT_WINDOW_EVENT;
+                     inev.frame_or_window = window;
                    }
 
                  last_window=window;
                    }
 
                  last_window=window;
@@ -4276,29 +4511,16 @@ w32_read_socket (sd, bufp, numchars, expected)
 
           /* If the contents of the global variable help_echo_string
              has changed, generate a HELP_EVENT.  */
 
           /* If the contents of the global variable help_echo_string
              has changed, generate a HELP_EVENT.  */
+#if 0 /* The below is an invalid comparison when USE_LISP_UNION_TYPE.
+        But it was originally changed to this to fix a bug, so I have
+        not removed it completely in case the bug is still there.  */
           if (help_echo_string != previous_help_echo_string ||
              (!NILP (help_echo_string) && !STRINGP (help_echo_string) && f->mouse_moved))
           if (help_echo_string != previous_help_echo_string ||
              (!NILP (help_echo_string) && !STRINGP (help_echo_string) && f->mouse_moved))
-            {
-              Lisp_Object frame;
-              int n;
-
-             if (help_echo_string == Qnil)
-               {
-                 help_echo_object = help_echo_window = Qnil;
-                 help_echo_pos = -1;
-               }
-
-              if (f)
-                XSETFRAME (frame, f);
-              else
-                frame = Qnil;
-
-              any_help_event_p = 1;
-              n = gen_help_event (bufp, numchars, help_echo_string, frame,
-                                 help_echo_window, help_echo_object,
-                                 help_echo_pos);
-              bufp += n, count += n, numchars -= n;
-            }
+#else /* This is what xterm.c does.  */
+           if (!NILP (help_echo_string)
+               || !NILP (previous_help_echo_string))
+           do_help = 1;
+#endif
           break;
 
        case WM_LBUTTONDOWN:
           break;
 
        case WM_LBUTTONDOWN:
@@ -4312,13 +4534,10 @@ w32_read_socket (sd, bufp, numchars, expected)
          {
             /* If we decide we want to generate an event to be seen
                by the rest of Emacs, we put it here.  */
          {
             /* If we decide we want to generate an event to be seen
                by the rest of Emacs, we put it here.  */
-            struct input_event emacs_event;
             int tool_bar_p = 0;
            int button;
            int up;
 
             int tool_bar_p = 0;
            int button;
            int up;
 
-            emacs_event.kind = NO_EVENT;
-
            if (dpyinfo->grabbed && last_mouse_frame
                && FRAME_LIVE_P (last_mouse_frame))
              f = last_mouse_frame;
            if (dpyinfo->grabbed && last_mouse_frame
                && FRAME_LIVE_P (last_mouse_frame))
              f = last_mouse_frame;
@@ -4327,35 +4546,29 @@ w32_read_socket (sd, bufp, numchars, expected)
 
            if (f)
              {
 
            if (f)
              {
-                construct_mouse_click (&emacs_event, &msg, f);
+                construct_mouse_click (&inev, &msg, f);
 
                 /* Is this in the tool-bar?  */
                 if (WINDOWP (f->tool_bar_window)
 
                 /* Is this in the tool-bar?  */
                 if (WINDOWP (f->tool_bar_window)
-                    && XFASTINT (XWINDOW (f->tool_bar_window)->height))
+                    && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
                   {
                     Lisp_Object window;
                   {
                     Lisp_Object window;
-                   int x = XFASTINT (emacs_event.x);
-                   int y = XFASTINT (emacs_event.y);
+                   int x = XFASTINT (inev.x);
+                   int y = XFASTINT (inev.y);
 
 
-                    window = window_from_coordinates (f, x, y, 0, 1);
+                    window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
 
                     if (EQ (window, f->tool_bar_window))
                       {
 
                     if (EQ (window, f->tool_bar_window))
                       {
-                        w32_handle_tool_bar_click (f, &emacs_event);
+                        w32_handle_tool_bar_click (f, &inev);
                         tool_bar_p = 1;
                       }
                   }
 
                         tool_bar_p = 1;
                       }
                   }
 
-                if (!tool_bar_p)
-                  if (!dpyinfo->w32_focus_frame
-                      || f == dpyinfo->w32_focus_frame
-                      && (numchars >= 1))
-                    {
-                      construct_mouse_click (bufp, &msg, f);
-                      bufp++;
-                      count++;
-                      numchars--;
-                    }
+                if (tool_bar_p
+                   || (dpyinfo->w32_focus_frame
+                       && f != dpyinfo->w32_focus_frame))
+                 inev.kind = NO_EVENT;
              }
 
            parse_button (msg.msg.message, HIWORD (msg.msg.wParam),
              }
 
            parse_button (msg.msg.message, HIWORD (msg.msg.wParam),
@@ -4382,37 +4595,39 @@ w32_read_socket (sd, bufp, numchars, expected)
            break;
          }
 
            break;
          }
 
-      case WM_MOUSEWHEEL:
-          if (dpyinfo->grabbed && last_mouse_frame
-              && FRAME_LIVE_P (last_mouse_frame))
-            f = last_mouse_frame;
-          else
-            f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
+       case WM_MOUSEWHEEL:
+         {
+           if (dpyinfo->grabbed && last_mouse_frame
+               && FRAME_LIVE_P (last_mouse_frame))
+             f = last_mouse_frame;
+           else
+             f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
 
 
-          if (f)
-            {
-              if ((!dpyinfo->w32_focus_frame
-                   || f == dpyinfo->w32_focus_frame)
-                  && (numchars >= 1))
-                {
-                  construct_mouse_wheel (bufp, &msg, f);
-                  bufp++;
-                  count++;
-                  numchars--;
-                }
-            }
+           if (f)
+             {
+
+               if (!dpyinfo->w32_focus_frame
+                   || f == dpyinfo->w32_focus_frame)
+                 {
+                   /* Emit an Emacs wheel-up/down event.  */
+                   construct_mouse_wheel (&inev, &msg, f);
+                 }
+               /* Ignore any mouse motion that happened before this
+                  event; any subsequent mouse-movement Emacs events
+                  should reflect only motion after the
+                  ButtonPress.  */
+               f->mouse_moved = 0;
+             }
+           last_mouse_frame = f;
+           last_tool_bar_item = -1;
+         }
          break;
 
        case WM_DROPFILES:
          f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
 
          if (f)
          break;
 
        case WM_DROPFILES:
          f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
 
          if (f)
-           {
-             construct_drag_n_drop (bufp, &msg, f);
-             bufp++;
-             count++;
-             numchars--;
-           }
+           construct_drag_n_drop (&inev, &msg, f);
          break;
 
        case WM_VSCROLL:
          break;
 
        case WM_VSCROLL:
@@ -4420,15 +4635,8 @@ w32_read_socket (sd, bufp, numchars, expected)
            struct scroll_bar *bar =
              x_window_to_scroll_bar ((HWND)msg.msg.lParam);
 
            struct scroll_bar *bar =
              x_window_to_scroll_bar ((HWND)msg.msg.lParam);
 
-           if (bar && numchars >= 1)
-             {
-               if (w32_scroll_bar_handle_click (bar, &msg, bufp))
-                 {
-                   bufp++;
-                   count++;
-                   numchars--;
-                 }
-             }
+           if (bar)
+             w32_scroll_bar_handle_click (bar, &msg, &inev);
            break;
          }
 
            break;
          }
 
@@ -4436,10 +4644,8 @@ w32_read_socket (sd, bufp, numchars, expected)
          f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
          if (f)
            {
          f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
          if (f)
            {
-             x_check_fullscreen_move(f);
-             if (f->output_data.w32->want_fullscreen & FULLSCREEN_WAIT)
-               f->output_data.w32->want_fullscreen &=
-                 ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
+             if (f->want_fullscreen & FULLSCREEN_WAIT)
+               f->want_fullscreen &= ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
            }
          check_visibility = 1;
          break;
            }
          check_visibility = 1;
          break;
@@ -4460,8 +4666,8 @@ w32_read_socket (sd, bufp, numchars, expected)
              int x, y;
 
              x_real_positions (f, &x, &y);
              int x, y;
 
              x_real_positions (f, &x, &y);
-             f->output_data.w32->left_pos = x;
-             f->output_data.w32->top_pos = y;
+             f->left_pos = x;
+             f->top_pos = y;
            }
 
          check_visibility = 1;
            }
 
          check_visibility = 1;
@@ -4506,12 +4712,8 @@ w32_read_socket (sd, bufp, numchars, expected)
                  f->async_visible = 0;
                  f->async_iconified = 1;
 
                  f->async_visible = 0;
                  f->async_iconified = 1;
 
-                 bufp->kind = ICONIFY_EVENT;
-                 XSETFRAME (bufp->frame_or_window, f);
-                 bufp->arg = Qnil;
-                 bufp++;
-                 count++;
-                 numchars--;
+                 inev.kind = ICONIFY_EVENT;
+                 XSETFRAME (inev.frame_or_window, f);
                  break;
 
                case SIZE_MAXIMIZED:
                  break;
 
                case SIZE_MAXIMIZED:
@@ -4533,15 +4735,11 @@ w32_read_socket (sd, bufp, numchars, expected)
                          when the Window is iconified, with 3000,3000
                          as the co-ords. */
                       x_real_positions (f, &x, &y);
                          when the Window is iconified, with 3000,3000
                          as the co-ords. */
                       x_real_positions (f, &x, &y);
-                      f->output_data.w32->left_pos = x;
-                      f->output_data.w32->top_pos = y;
-
-                     bufp->kind = DEICONIFY_EVENT;
-                     XSETFRAME (bufp->frame_or_window, f);
-                     bufp->arg = Qnil;
-                     bufp++;
-                     count++;
-                     numchars--;
+                      f->left_pos = x;
+                      f->top_pos = y;
+
+                     inev.kind = DEICONIFY_EVENT;
+                     XSETFRAME (inev.frame_or_window, f);
                    }
                  else if (! NILP (Vframe_list)
                           && ! NILP (XCDR (Vframe_list)))
                    }
                  else if (! NILP (Vframe_list)
                           && ! NILP (XCDR (Vframe_list)))
@@ -4566,8 +4764,8 @@ w32_read_socket (sd, bufp, numchars, expected)
              height = rect.bottom - rect.top;
              width = rect.right - rect.left;
 
              height = rect.bottom - rect.top;
              width = rect.right - rect.left;
 
-             rows = PIXEL_TO_CHAR_HEIGHT (f, height);
-             columns = PIXEL_TO_CHAR_WIDTH (f, width);
+             rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
+             columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
 
              /* TODO: Clip size to the screen dimensions.  */
 
 
              /* TODO: Clip size to the screen dimensions.  */
 
@@ -4575,17 +4773,17 @@ w32_read_socket (sd, bufp, numchars, expected)
                 not changed, the font size may have changed, so we need
                 to check the pixel dimensions as well.  */
 
                 not changed, the font size may have changed, so we need
                 to check the pixel dimensions as well.  */
 
-             if (columns != f->width
-                 || rows != f->height
-                 || width != f->output_data.w32->pixel_width
-                 || height != f->output_data.w32->pixel_height)
+             if (columns != FRAME_COLS (f)
+                 || rows != FRAME_LINES (f)
+                 || width != FRAME_PIXEL_WIDTH (f)
+                 || height != FRAME_PIXEL_HEIGHT (f))
                {
                  change_frame_size (f, rows, columns, 0, 1, 0);
                  SET_FRAME_GARBAGED (f);
                  cancel_mouse_face (f);
                {
                  change_frame_size (f, rows, columns, 0, 1, 0);
                  SET_FRAME_GARBAGED (f);
                  cancel_mouse_face (f);
-                 f->output_data.w32->pixel_width = width;
-                 f->output_data.w32->pixel_height = height;
-                 f->output_data.w32->win_gravity = NorthWestGravity;
+                 FRAME_PIXEL_WIDTH (f) = width;
+                 FRAME_PIXEL_HEIGHT (f) = height;
+                 f->win_gravity = NorthWestGravity;
                }
            }
 
                }
            }
 
@@ -4609,28 +4807,19 @@ w32_read_socket (sd, bufp, numchars, expected)
                 Otherwise, the startup message is cleared when
                 the mouse leaves the frame.  */
              if (any_help_event_p)
                 Otherwise, the startup message is cleared when
                 the mouse leaves the frame.  */
              if (any_help_event_p)
-               {
-                 Lisp_Object frame;
-                 int n;
-
-                 XSETFRAME (frame, f);
-                 help_echo_string = Qnil;
-                 n = gen_help_event (bufp, numchars,
-                                     Qnil, frame, Qnil, Qnil, 0);
-                 bufp += n, count += n, numchars -= n;
-               }
+               do_help = -1;
            }
          break;
 
        case WM_SETFOCUS:
          /* TODO: Port this change:
             2002-06-28  Jan D.  <jan.h.d@swipnet.se>
            }
          break;
 
        case WM_SETFOCUS:
          /* TODO: Port this change:
             2002-06-28  Jan D.  <jan.h.d@swipnet.se>
-          * xterm.h (struct x_output): Add focus_state.
-          * xterm.c (x_focus_changed): New function.
+            * xterm.h (struct x_output): Add focus_state.
+            * xterm.c (x_focus_changed): New function.
             (x_detect_focus_change): New function.
             (XTread_socket): Call x_detect_focus_change for FocusIn/FocusOut
             EnterNotify and LeaveNotify to track X focus changes.
             (x_detect_focus_change): New function.
             (XTread_socket): Call x_detect_focus_change for FocusIn/FocusOut
             EnterNotify and LeaveNotify to track X focus changes.
-          */
+         */
          f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd);
 
           dpyinfo->w32_focus_event_frame = f;
          f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd);
 
           dpyinfo->w32_focus_event_frame = f;
@@ -4668,16 +4857,7 @@ w32_read_socket (sd, bufp, numchars, expected)
                  Otherwise, the startup message is cleared when
                  the mouse leaves the frame.  */
               if (any_help_event_p)
                  Otherwise, the startup message is cleared when
                  the mouse leaves the frame.  */
               if (any_help_event_p)
-                {
-                  Lisp_Object frame;
-                  int n;
-
-                  XSETFRAME (frame, f);
-                  help_echo_string = Qnil;
-                  n = gen_help_event (bufp, numchars,
-                                      Qnil, frame, Qnil, Qnil, 0);
-                  bufp += n, count += n, numchars -=n;
-                }
+               do_help = -1;
             }
 
          dpyinfo->grabbed = 0;
             }
 
          dpyinfo->grabbed = 0;
@@ -4689,15 +4869,8 @@ w32_read_socket (sd, bufp, numchars, expected)
 
          if (f)
            {
 
          if (f)
            {
-             if (numchars == 0)
-               abort ();
-
-             bufp->kind = DELETE_WINDOW_EVENT;
-             XSETFRAME (bufp->frame_or_window, f);
-             bufp->arg = Qnil;
-             bufp++;
-             count++;
-             numchars--;
+             inev.kind = DELETE_WINDOW_EVENT;
+             XSETFRAME (inev.frame_or_window, f);
            }
          break;
 
            }
          break;
 
@@ -4706,15 +4879,8 @@ w32_read_socket (sd, bufp, numchars, expected)
 
          if (f)
            {
 
          if (f)
            {
-             if (numchars == 0)
-               abort ();
-
-             bufp->kind = MENU_BAR_ACTIVATE_EVENT;
-             XSETFRAME (bufp->frame_or_window, f);
-             bufp->arg = Qnil;
-             bufp++;
-             count++;
-             numchars--;
+             inev.kind = MENU_BAR_ACTIVATE_EVENT;
+             XSETFRAME (inev.frame_or_window, f);
            }
          break;
 
            }
          break;
 
@@ -4747,29 +4913,50 @@ w32_read_socket (sd, bufp, numchars, expected)
          break;
 
        default:
          break;
 
        default:
-         /* Check for messages registered at runtime. */
+         /* Check for messages registered at runtime.  */
          if (msg.msg.message == msh_mousewheel)
            {
          if (msg.msg.message == msh_mousewheel)
            {
-             if (dpyinfo->grabbed && last_mouse_frame
-                 && FRAME_LIVE_P (last_mouse_frame))
-               f = last_mouse_frame;
-             else
-               f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
+             /* Forward MSH_MOUSEWHEEL as WM_MOUSEWHEEL.  */
+             msg.msg.message = WM_MOUSEWHEEL;
+             prepend_msg (&msg);
+           }
+         break;
+       }
 
 
-             if (f)
+      if (inev.kind != NO_EVENT)
+       {
+         kbd_buffer_store_event_hold (&inev, hold_quit);
+         count++;
+       }
+
+      if (do_help
+         && !(hold_quit && hold_quit->kind != NO_EVENT))
+       {
+         Lisp_Object frame;
+
+         if (f)
+           XSETFRAME (frame, f);
+         else
+           frame = Qnil;
+
+         if (do_help > 0)
+           {
+             if (NILP (help_echo_string))
                {
                {
-                 if ((!dpyinfo->w32_focus_frame
-                      || f == dpyinfo->w32_focus_frame)
-                     && (numchars >= 1))
-                   {
-                     construct_mouse_wheel (bufp, &msg, f);
-                     bufp++;
-                     count++;
-                     numchars--;
-                   }
+                 help_echo_object = help_echo_window = Qnil;
+                 help_echo_pos = -1;
                }
                }
+
+             any_help_event_p = 1;
+             gen_help_event (help_echo_string, frame, help_echo_window,
+                             help_echo_object, help_echo_pos);
            }
            }
-         break;
+         else
+           {
+             help_echo_string = Qnil;
+             gen_help_event (Qnil, frame, Qnil, Qnil, 0);
+           }
+         count++;
        }
     }
 
        }
     }
 
@@ -4792,65 +4979,65 @@ w32_read_socket (sd, bufp, numchars, expected)
       Lisp_Object tail, frame;
 
       FOR_EACH_FRAME (tail, frame)
       Lisp_Object tail, frame;
 
       FOR_EACH_FRAME (tail, frame)
-       {
-         FRAME_PTR f = XFRAME (frame);
-         /* The tooltip has been drawn already.  Avoid the
-            SET_FRAME_GARBAGED below.  */
-         if (EQ (frame, tip_frame))
-           continue;
-
-         /* Check "visible" frames and mark each as obscured or not.
-            Note that async_visible is nonzero for unobscured and
-            obscured frames, but zero for hidden and iconified frames.  */
-         if (FRAME_W32_P (f) && f->async_visible)
-           {
-             RECT clipbox;
-             HDC  hdc;
-
-             enter_crit ();
-             /* Query clipping rectangle for the entire window area
-                 (GetWindowDC), not just the client portion (GetDC).
-                 Otherwise, the scrollbars and menubar aren't counted as
-                 part of the visible area of the frame, and we may think
-                 the frame is obscured when really a scrollbar is still
-                 visible and gets WM_PAINT messages above.  */
-             hdc = GetWindowDC (FRAME_W32_WINDOW (f));
-             GetClipBox (hdc, &clipbox);
-             ReleaseDC (FRAME_W32_WINDOW (f), hdc);
-             leave_crit ();
-
-             if (clipbox.right == clipbox.left
-                 || clipbox.bottom == clipbox.top)
-               {
-                 /* Frame has become completely obscured so mark as
-                    such (we do this by setting async_visible to 2 so
-                    that FRAME_VISIBLE_P is still true, but redisplay
-                    will skip it).  */
-                 f->async_visible = 2;
+      {
+       FRAME_PTR f = XFRAME (frame);
+       /* The tooltip has been drawn already.  Avoid the
+          SET_FRAME_GARBAGED below.  */
+       if (EQ (frame, tip_frame))
+         continue;
+
+       /* Check "visible" frames and mark each as obscured or not.
+          Note that async_visible is nonzero for unobscured and
+          obscured frames, but zero for hidden and iconified frames.  */
+       if (FRAME_W32_P (f) && f->async_visible)
+         {
+           RECT clipbox;
+           HDC  hdc;
+
+           enter_crit ();
+           /* Query clipping rectangle for the entire window area
+              (GetWindowDC), not just the client portion (GetDC).
+              Otherwise, the scrollbars and menubar aren't counted as
+              part of the visible area of the frame, and we may think
+              the frame is obscured when really a scrollbar is still
+              visible and gets WM_PAINT messages above.  */
+           hdc = GetWindowDC (FRAME_W32_WINDOW (f));
+           GetClipBox (hdc, &clipbox);
+           ReleaseDC (FRAME_W32_WINDOW (f), hdc);
+           leave_crit ();
+
+           if (clipbox.right == clipbox.left
+               || clipbox.bottom == clipbox.top)
+             {
+               /* Frame has become completely obscured so mark as
+                  such (we do this by setting async_visible to 2 so
+                  that FRAME_VISIBLE_P is still true, but redisplay
+                  will skip it).  */
+               f->async_visible = 2;
 
 
-                 if (!FRAME_OBSCURED_P (f))
-                   {
-                     DebPrint (("frame %p (%s) obscured\n", f,
-                                SDATA (f->name)));
-                   }
-               }
-             else
-               {
-                 /* Frame is not obscured, so mark it as such.  */
-                 f->async_visible = 1;
+               if (!FRAME_OBSCURED_P (f))
+                 {
+                   DebPrint (("frame %p (%s) obscured\n", f,
+                              SDATA (f->name)));
+                 }
+             }
+           else
+             {
+               /* Frame is not obscured, so mark it as such.  */
+               f->async_visible = 1;
 
 
-                 if (FRAME_OBSCURED_P (f))
-                   {
-                     SET_FRAME_GARBAGED (f);
-                     DebPrint (("obscured frame %p (%s) found to be visible\n", f,
-                                SDATA (f->name)));
+               if (FRAME_OBSCURED_P (f))
+                 {
+                   SET_FRAME_GARBAGED (f);
+                   DebPrint (("obscured frame %p (%s) found to be visible\n", f,
+                              SDATA (f->name)));
 
 
-                     /* Force a redisplay sooner or later.  */
-                     record_asynch_buffer_change ();
-                   }
-               }
-           }
-       }
+                   /* Force a redisplay sooner or later.  */
+                   record_asynch_buffer_change ();
+                 }
+             }
+         }
+      }
     }
 
   UNBLOCK_INPUT;
     }
 
   UNBLOCK_INPUT;
@@ -4866,25 +5053,22 @@ w32_read_socket (sd, bufp, numchars, expected)
 
 /* Set clipping for output in glyph row ROW.  W is the window in which
    we operate.  GC is the graphics context to set clipping in.
 
 /* Set clipping for output in glyph row ROW.  W is the window in which
    we operate.  GC is the graphics context to set clipping in.
-   WHOLE_LINE_P non-zero means include the areas used for truncation
-   mark display and alike in the clipping rectangle.
 
    ROW may be a text row or, e.g., a mode line.  Text rows must be
    clipped to the interior of the window dedicated to text display,
    mode lines must be clipped to the whole window.  */
 
 static void
 
    ROW may be a text row or, e.g., a mode line.  Text rows must be
    clipped to the interior of the window dedicated to text display,
    mode lines must be clipped to the whole window.  */
 
 static void
-w32_clip_to_row (w, row, hdc, whole_line_p)
+w32_clip_to_row (w, row, hdc)
      struct window *w;
      struct glyph_row *row;
      HDC hdc;
      struct window *w;
      struct glyph_row *row;
      HDC hdc;
-     int whole_line_p;
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   RECT clip_rect;
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   RECT clip_rect;
-  int window_x, window_y, window_width, window_height;
+  int window_y, window_width;
 
 
-  window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
+  window_box (w, -1, 0, &window_y, &window_width, 0);
 
   clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
   clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
 
   clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
   clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
@@ -4892,14 +5076,6 @@ w32_clip_to_row (w, row, hdc, whole_line_p)
   clip_rect.right = clip_rect.left + window_width;
   clip_rect.bottom = clip_rect.top + row->visible_height;
 
   clip_rect.right = clip_rect.left + window_width;
   clip_rect.bottom = clip_rect.top + row->visible_height;
 
-  /* If clipping to the whole line, including trunc marks, extend
-     the rectangle to the left and increase its width.  */
-  if (whole_line_p)
-    {
-      clip_rect.left -= FRAME_X_LEFT_FRINGE_WIDTH (f);
-      clip_rect.right += FRAME_X_FRINGE_WIDTH (f);
-    }
-
   w32_set_clip_rectangle (hdc, &clip_rect);
 }
 
   w32_set_clip_rectangle (hdc, &clip_rect);
 }
 
@@ -4914,37 +5090,47 @@ x_draw_hollow_cursor (w, row)
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   HDC hdc;
   RECT rect;
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   HDC hdc;
   RECT rect;
-  int wd;
+  int wd, h;
   struct glyph *cursor_glyph;
   HBRUSH hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
 
   struct glyph *cursor_glyph;
   HBRUSH hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
 
+  /* Get the glyph the cursor is on.  If we can't tell because
+     the current matrix is invalid or such, give up.  */
+  cursor_glyph = get_phys_cursor_glyph (w);
+  if (cursor_glyph == NULL)
+    return;
+
   /* Compute frame-relative coordinates from window-relative
      coordinates.  */
   rect.left = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
   rect.top = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
               + row->ascent - w->phys_cursor_ascent);
   /* Compute frame-relative coordinates from window-relative
      coordinates.  */
   rect.left = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
   rect.top = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
               + row->ascent - w->phys_cursor_ascent);
-  rect.bottom = rect.top + row->height;
 
 
-  /* Get the glyph the cursor is on.  If we can't tell because
-     the current matrix is invalid or such, give up.  */
-  cursor_glyph = get_phys_cursor_glyph (w);
-  if (cursor_glyph == NULL)
-    return;
+  /* Compute the proper height and ascent of the rectangle, based
+     on the actual glyph.  Using the full height of the row looks
+     bad when there are tall images on that row.  */
+  h = max (min (FRAME_LINE_HEIGHT (f), row->height),
+          cursor_glyph->ascent + cursor_glyph->descent);
+  if (h < row->height)
+    rect.top += row->ascent /* - w->phys_cursor_ascent */ + cursor_glyph->descent - h;
+  h--;
+
+  rect.bottom = rect.top + h;
 
   /* Compute the width of the rectangle to draw.  If on a stretch
      glyph, and `x-stretch-block-cursor' is nil, don't draw a
      rectangle as wide as the glyph, but use a canonical character
      width instead.  */
 
   /* Compute the width of the rectangle to draw.  If on a stretch
      glyph, and `x-stretch-block-cursor' is nil, don't draw a
      rectangle as wide as the glyph, but use a canonical character
      width instead.  */
-  wd = cursor_glyph->pixel_width;
+  wd = cursor_glyph->pixel_width; /* TODO: Why off by one compared with X? */
   if (cursor_glyph->type == STRETCH_GLYPH
       && !x_stretch_cursor_p)
   if (cursor_glyph->type == STRETCH_GLYPH
       && !x_stretch_cursor_p)
-    wd = min (CANON_X_UNIT (f), wd);
+    wd = min (FRAME_COLUMN_WIDTH (f), wd);
   w->phys_cursor_width = wd;
 
   rect.right = rect.left + wd;
   hdc = get_frame_dc (f);
   /* Set clipping, draw the rectangle, and reset clipping again.  */
   w->phys_cursor_width = wd;
 
   rect.right = rect.left + wd;
   hdc = get_frame_dc (f);
   /* Set clipping, draw the rectangle, and reset clipping again.  */
-  w32_clip_to_row (w, row, hdc, 0);
+  w32_clip_to_row (w, row, hdc);
   FrameRect (hdc, &rect, hb);
   DeleteObject (hb);
   w32_set_clip_rectangle (hdc, NULL);
   FrameRect (hdc, &rect, hb);
   DeleteObject (hb);
   w32_set_clip_rectangle (hdc, NULL);
@@ -5010,7 +5196,7 @@ x_draw_bar_cursor (w, row, width, kind)
 
 
       hdc = get_frame_dc (f);
 
 
       hdc = get_frame_dc (f);
-      w32_clip_to_row (w, row, hdc, 0);
+      w32_clip_to_row (w, row, hdc);
 
       if (kind == BAR_CURSOR)
        {
 
       if (kind == BAR_CURSOR)
        {
@@ -5073,6 +5259,9 @@ w32_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, act
         cursor remains invisible.  */
       if (w32_use_visible_system_caret)
        {
         cursor remains invisible.  */
       if (w32_use_visible_system_caret)
        {
+         /* Call to erase_phys_cursor here seems to use the
+            wrong values of w->phys_cursor, as they have been
+            overwritten before this function was called. */
          if (w->phys_cursor_type != NO_CURSOR)
            erase_phys_cursor (w);
 
          if (w->phys_cursor_type != NO_CURSOR)
            erase_phys_cursor (w);
 
@@ -5112,6 +5301,14 @@ w32_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, act
          PostMessage (hwnd, WM_EMACS_TRACK_CARET, 0, 0);
        }
 
          PostMessage (hwnd, WM_EMACS_TRACK_CARET, 0, 0);
        }
 
+      if (glyph_row->exact_window_width_line_p
+         && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
+       {
+         glyph_row->cursor_in_fringe_p = 1;
+         draw_fringe_bitmap (w, glyph_row, 0);
+         return;
+       }
+
       switch (cursor_type)
        {
        case HOLLOW_BOX_CURSOR:
       switch (cursor_type)
        {
        case HOLLOW_BOX_CURSOR:
@@ -5230,73 +5427,91 @@ x_new_font (f, fontname)
      register char *fontname;
 {
   struct font_info *fontp
      register char *fontname;
 {
   struct font_info *fontp
-    = FS_LOAD_FONT (f, 0, fontname, -1);
+    = FS_LOAD_FONT (f, fontname);
 
   if (!fontp)
     return Qnil;
 
 
   if (!fontp)
     return Qnil;
 
+  if (FRAME_FONT (f) == (XFontStruct *) (fontp->font))
+    /* This font is already set in frame F.  There's nothing more to
+       do.  */
+    return build_string (fontp->full_name);
+
   FRAME_FONT (f) = (XFontStruct *) (fontp->font);
   FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
   FRAME_FONTSET (f) = -1;
 
   FRAME_FONT (f) = (XFontStruct *) (fontp->font);
   FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
   FRAME_FONTSET (f) = -1;
 
+  FRAME_COLUMN_WIDTH (f) = FONT_WIDTH (FRAME_FONT (f));
+  FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
+
+  compute_fringe_widths (f, 1);
+
   /* Compute the scroll bar width in character columns.  */
   /* Compute the scroll bar width in character columns.  */
-  if (f->scroll_bar_pixel_width > 0)
+  if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
     {
     {
-      int wid = FONT_WIDTH (FRAME_FONT (f));
-      f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
+      int wid = FRAME_COLUMN_WIDTH (f);
+      FRAME_CONFIG_SCROLL_BAR_COLS (f)
+       = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
     }
   else
     {
     }
   else
     {
-      int wid = FONT_WIDTH (FRAME_FONT (f));
-      f->scroll_bar_cols = (14 + wid - 1) / wid;
+      int wid = FRAME_COLUMN_WIDTH (f);
+      FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
     }
 
   /* Now make the frame display the given font.  */
   if (FRAME_W32_WINDOW (f) != 0)
     {
     }
 
   /* Now make the frame display the given font.  */
   if (FRAME_W32_WINDOW (f) != 0)
     {
-      frame_update_line_height (f);
       if (NILP (tip_frame) || XFRAME (tip_frame) != f)
       if (NILP (tip_frame) || XFRAME (tip_frame) != f)
-        x_set_window_size (f, 0, f->width, f->height);
+        x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
     }
     }
-  else
-    /* If we are setting a new frame's font for the first time,
-       there are no faces yet, so this font's height is the line height.  */
-    f->output_data.w32->line_height = FONT_HEIGHT (FRAME_FONT (f));
 
   return build_string (fontp->full_name);
 }
 \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.  */
+/* Give frame F the fontset named FONTSETNAME as its default fontset,
+   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.  FONTSETNAME may be a font name for ASCII characters;
+   in that case, we create a fontset from that font name.
+
+   The return value shows which fontset we chose.
+   If FONTSETNAME specifies the default fontset, return Qt.
+   If an ASCII font in the specified fontset can't be loaded, return
+   Qnil.  */
 
 Lisp_Object
 x_new_fontset (f, fontsetname)
      struct frame *f;
 
 Lisp_Object
 x_new_fontset (f, fontsetname)
      struct frame *f;
-     char *fontsetname;
+     Lisp_Object fontsetname;
 {
 {
-  int fontset = fs_query_fontset (build_string (fontsetname), 0);
+  int fontset = fs_query_fontset (fontsetname, 0);
   Lisp_Object result;
 
   Lisp_Object result;
 
-  if (fontset < 0)
-    return Qnil;
-
-  if (FRAME_FONTSET (f) == fontset)
+  if (fontset > 0 && FRAME_FONTSET(f) == fontset)
     /* This fontset is already set in frame F.  There's nothing more
        to do.  */
     return fontset_name (fontset);
     /* This fontset is already set in frame F.  There's nothing more
        to do.  */
     return fontset_name (fontset);
+  else if (fontset == 0)
+    /* The default fontset can't be the default font.   */
+    return Qt;
 
 
-  result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
+  if (fontset > 0)
+    result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
+  else
+    result = x_new_font (f, SDATA (fontsetname));
 
   if (!STRINGP (result))
     /* Can't load ASCII font.  */
     return Qnil;
 
 
   if (!STRINGP (result))
     /* Can't load ASCII font.  */
     return Qnil;
 
+  if (fontset < 0)
+    fontset = new_fontset_from_font_name (result);
+
   /* Since x_new_font doesn't update any fontset information, do it now.  */
   FRAME_FONTSET(f) = fontset;
 
   /* Since x_new_font doesn't update any fontset information, do it now.  */
   FRAME_FONTSET(f) = fontset;
 
-  return build_string (fontsetname);
+  return fontset_name (fontset);
 }
 
 \f
 }
 
 \f
@@ -5323,7 +5538,7 @@ x_calc_absolute_position (f)
      struct frame *f;
 {
   POINT pt;
      struct frame *f;
 {
   POINT pt;
-  int flags = f->output_data.w32->size_hint_flags;
+  int flags = f->size_hint_flags;
 
   pt.x = pt.y = 0;
 
 
   pt.x = pt.y = 0;
 
@@ -5355,20 +5570,20 @@ x_calc_absolute_position (f)
   /* Treat negative positions as relative to the leftmost bottommost
      position that fits on the screen.  */
   if (flags & XNegative)
   /* Treat negative positions as relative to the leftmost bottommost
      position that fits on the screen.  */
   if (flags & XNegative)
-    f->output_data.w32->left_pos = (FRAME_W32_DISPLAY_INFO (f)->width
-                             - 2 * f->output_data.w32->border_width - pt.x
-                             - PIXEL_WIDTH (f)
-                             + f->output_data.w32->left_pos);
+    f->left_pos = (FRAME_W32_DISPLAY_INFO (f)->width
+                  - 2 * f->border_width - pt.x
+                  - FRAME_PIXEL_WIDTH (f)
+                  + f->left_pos);
 
   if (flags & YNegative)
 
   if (flags & YNegative)
-    f->output_data.w32->top_pos = (FRAME_W32_DISPLAY_INFO (f)->height
-                            - 2 * f->output_data.w32->border_width - pt.y
-                            - PIXEL_HEIGHT (f)
-                            + f->output_data.w32->top_pos);
+    f->top_pos = (FRAME_W32_DISPLAY_INFO (f)->height
+                 - 2 * f->border_width - pt.y
+                 - FRAME_PIXEL_HEIGHT (f)
+                 + f->top_pos);
   /* The left_pos and top_pos
      are now relative to the top and left screen edges,
      so the flags should correspond.  */
   /* The left_pos and top_pos
      are now relative to the top and left screen edges,
      so the flags should correspond.  */
-  f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
+  f->size_hint_flags &= ~ (XNegative | YNegative);
 }
 
 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
 }
 
 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
@@ -5387,22 +5602,22 @@ x_set_offset (f, xoff, yoff, change_gravity)
 
   if (change_gravity > 0)
     {
 
   if (change_gravity > 0)
     {
-      f->output_data.w32->top_pos = yoff;
-      f->output_data.w32->left_pos = xoff;
-      f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
+      f->top_pos = yoff;
+      f->left_pos = xoff;
+      f->size_hint_flags &= ~ (XNegative | YNegative);
       if (xoff < 0)
       if (xoff < 0)
-       f->output_data.w32->size_hint_flags |= XNegative;
+       f->size_hint_flags |= XNegative;
       if (yoff < 0)
       if (yoff < 0)
-       f->output_data.w32->size_hint_flags |= YNegative;
-      f->output_data.w32->win_gravity = NorthWestGravity;
+       f->size_hint_flags |= YNegative;
+      f->win_gravity = NorthWestGravity;
     }
   x_calc_absolute_position (f);
 
   BLOCK_INPUT;
   x_wm_set_size_hint (f, (long) 0, 0);
 
     }
   x_calc_absolute_position (f);
 
   BLOCK_INPUT;
   x_wm_set_size_hint (f, (long) 0, 0);
 
-  modified_left = f->output_data.w32->left_pos;
-  modified_top = f->output_data.w32->top_pos;
+  modified_left = f->left_pos;
+  modified_top = f->top_pos;
 
   my_set_window_pos (FRAME_W32_WINDOW (f),
                     NULL,
 
   my_set_window_pos (FRAME_W32_WINDOW (f),
                     NULL,
@@ -5419,108 +5634,28 @@ static void
 x_check_fullscreen (f)
      struct frame *f;
 {
 x_check_fullscreen (f)
      struct frame *f;
 {
-  if (f->output_data.w32->want_fullscreen & FULLSCREEN_BOTH)
+  if (f->want_fullscreen & FULLSCREEN_BOTH)
     {
       int width, height, ign;
 
     {
       int width, height, ign;
 
-      x_real_positions (f, &f->output_data.w32->left_pos,
-                        &f->output_data.w32->top_pos);
+      x_real_positions (f, &f->left_pos, &f->top_pos);
 
       x_fullscreen_adjust (f, &width, &height, &ign, &ign);
 
       /* We do not need to move the window, it shall be taken care of
 
       x_fullscreen_adjust (f, &width, &height, &ign, &ign);
 
       /* We do not need to move the window, it shall be taken care of
-         when setting WM manager hints.
-         If the frame is visible already, the position is checked by
-         x_check_fullscreen_move. */
-      if (f->width != width || f->height != height)
+         when setting WM manager hints.  */
+      if (FRAME_COLS (f) != width || FRAME_LINES (f) != height)
         {
           change_frame_size (f, height, width, 0, 1, 0);
           SET_FRAME_GARBAGED (f);
           cancel_mouse_face (f);
 
           /* Wait for the change of frame size to occur */
         {
           change_frame_size (f, height, width, 0, 1, 0);
           SET_FRAME_GARBAGED (f);
           cancel_mouse_face (f);
 
           /* Wait for the change of frame size to occur */
-          f->output_data.w32->want_fullscreen |= FULLSCREEN_WAIT;
+          f->want_fullscreen |= FULLSCREEN_WAIT;
         }
     }
 }
 
         }
     }
 }
 
-/* If frame parameters are set after the frame is mapped, we need to move
-   the window.  This is done in xfns.c.
-   Some window managers moves the window to the right position, some
-   moves the outer window manager window to the specified position.
-   Here we check that we are in the right spot.  If not, make a second
-   move, assuming we are dealing with the second kind of window manager. */
-static void
-x_check_fullscreen_move (f)
-     struct frame *f;
-{
-  if (f->output_data.w32->want_fullscreen & FULLSCREEN_MOVE_WAIT)
-  {
-    int expect_top = f->output_data.w32->top_pos;
-    int expect_left = f->output_data.w32->left_pos;
-
-    if (f->output_data.w32->want_fullscreen & FULLSCREEN_HEIGHT)
-      expect_top = 0;
-    if (f->output_data.w32->want_fullscreen & FULLSCREEN_WIDTH)
-      expect_left = 0;
-
-    if (expect_top != f->output_data.w32->top_pos
-        || expect_left != f->output_data.w32->left_pos)
-      x_set_offset (f, expect_left, expect_top, 1);
-
-    /* Just do this once */
-    f->output_data.w32->want_fullscreen &= ~FULLSCREEN_MOVE_WAIT;
-  }
-}
-
-
-/* Calculate fullscreen size.  Return in *TOP_POS and *LEFT_POS the
-   wanted positions of the WM window (not emacs window).
-   Return in *WIDTH and *HEIGHT the wanted width and height of Emacs
-   window (FRAME_X_WINDOW).
- */
-void
-x_fullscreen_adjust (f, width, height, top_pos, left_pos)
-     struct frame *f;
-     int *width;
-     int *height;
-     int *top_pos;
-     int *left_pos;
-{
-  int newwidth = f->width, newheight = f->height;
-
-  *top_pos = f->output_data.w32->top_pos;
-  *left_pos = f->output_data.w32->left_pos;
-
-  if (f->output_data.w32->want_fullscreen & FULLSCREEN_HEIGHT)
-    {
-      int ph;
-
-      ph = FRAME_X_DISPLAY_INFO (f)->height;
-      newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);
-      ph = CHAR_TO_PIXEL_HEIGHT (f, newheight)
-        - f->output_data.w32->y_pixels_diff;
-      newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);
-      *top_pos = 0;
-    }
-
-  if (f->output_data.w32->want_fullscreen & FULLSCREEN_WIDTH)
-    {
-      int pw;
-
-      pw = FRAME_X_DISPLAY_INFO (f)->width;
-      newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);
-      pw = CHAR_TO_PIXEL_WIDTH (f, newwidth)
-        - f->output_data.w32->x_pixels_diff;
-      newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);
-      *left_pos = 0;
-    }
-
-  *width = newwidth;
-  *height = newheight;
-}
-
-
 /* Call this to change the size of frame F's x-window.
    If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
    for this size change and subsequent size changes.
 /* Call this to change the size of frame F's x-window.
    If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
    for this size change and subsequent size changes.
@@ -5537,17 +5672,15 @@ x_set_window_size (f, change_gravity, cols, rows)
   BLOCK_INPUT;
 
   check_frame_size (f, &rows, &cols);
   BLOCK_INPUT;
 
   check_frame_size (f, &rows, &cols);
-  f->output_data.w32->vertical_scroll_bar_extra
-    = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
-       ? 0
-       : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font)));
+  f->scroll_bar_actual_width
+    = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
 
   compute_fringe_widths (f, 0);
 
 
   compute_fringe_widths (f, 0);
 
-  pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
-  pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
+  pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
+  pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
 
 
-  f->output_data.w32->win_gravity = NorthWestGravity;
+  f->win_gravity = NorthWestGravity;
   x_wm_set_size_hint (f, (long) 0, 0);
 
   {
   x_wm_set_size_hint (f, (long) 0, 0);
 
   {
@@ -5582,8 +5715,8 @@ x_set_window_size (f, change_gravity, cols, rows)
      We pass 1 for DELAY since we can't run Lisp code inside of
      a BLOCK_INPUT.  */
   change_frame_size (f, rows, cols, 0, 1, 0);
      We pass 1 for DELAY since we can't run Lisp code inside of
      a BLOCK_INPUT.  */
   change_frame_size (f, rows, cols, 0, 1, 0);
-  PIXEL_WIDTH (f) = pixelwidth;
-  PIXEL_HEIGHT (f) = pixelheight;
+  FRAME_PIXEL_WIDTH (f) = pixelwidth;
+  FRAME_PIXEL_HEIGHT (f) = pixelheight;
 
   /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
      receive in the ConfigureNotify event; if we get what we asked
 
   /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
      receive in the ConfigureNotify event; if we get what we asked
@@ -5614,14 +5747,14 @@ x_set_mouse_position (f, x, y)
 {
   int pix_x, pix_y;
 
 {
   int pix_x, pix_y;
 
-  pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH  (f->output_data.w32->font) / 2;
-  pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.w32->line_height / 2;
+  pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
+  pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
 
   if (pix_x < 0) pix_x = 0;
 
   if (pix_x < 0) pix_x = 0;
-  if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
+  if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
 
   if (pix_y < 0) pix_y = 0;
 
   if (pix_y < 0) pix_y = 0;
-  if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
+  if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
 
   x_set_mouse_pixel_position (f, pix_x, pix_y);
 }
 
   x_set_mouse_pixel_position (f, pix_x, pix_y);
 }
@@ -5789,7 +5922,7 @@ x_make_frame_visible (f)
         before the window gets really visible.  */
       if (! FRAME_ICONIFIED_P (f)
          && ! f->output_data.w32->asked_for_visible)
         before the window gets really visible.  */
       if (! FRAME_ICONIFIED_P (f)
          && ! f->output_data.w32->asked_for_visible)
-       x_set_offset (f, f->output_data.w32->left_pos, f->output_data.w32->top_pos, 0);
+       x_set_offset (f, f->left_pos, f->top_pos, 0);
 
       f->output_data.w32->asked_for_visible = 1;
 
 
       f->output_data.w32->asked_for_visible = 1;
 
@@ -5977,15 +6110,16 @@ x_wm_set_size_hint (f, flags, user_position)
 
   enter_crit ();
 
 
   enter_crit ();
 
-  SetWindowLong (window, WND_FONTWIDTH_INDEX, FONT_WIDTH (f->output_data.w32->font));
-  SetWindowLong (window, WND_LINEHEIGHT_INDEX, f->output_data.w32->line_height);
-  SetWindowLong (window, WND_BORDER_INDEX, f->output_data.w32->internal_border_width);
-  SetWindowLong (window, WND_SCROLLBAR_INDEX, f->output_data.w32->vertical_scroll_bar_extra);
+  SetWindowLong (window, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f));
+  SetWindowLong (window, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f));
+  SetWindowLong (window, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f));
+  SetWindowLong (window, WND_SCROLLBAR_INDEX, f->scroll_bar_actual_width);
 
   leave_crit ();
 }
 
 /* Window manager things */
 
   leave_crit ();
 }
 
 /* Window manager things */
+void
 x_wm_set_icon_position (f, icon_x, icon_y)
      struct frame *f;
      int icon_x, icon_y;
 x_wm_set_icon_position (f, icon_x, icon_y)
      struct frame *f;
      int icon_x, icon_y;
@@ -6270,32 +6404,7 @@ w32_term_init (display_name, xrm_option, resource_name)
      horizontally reflected compared to how they appear on X, so we
      need to bitswap and convert to unsigned shorts before creating
      the bitmaps.  */
      horizontally reflected compared to how they appear on X, so we
      need to bitswap and convert to unsigned shorts before creating
      the bitmaps.  */
-  {
-    int i, j;
-
-    for (i = NO_FRINGE_BITMAP + 1; i < MAX_FRINGE_BITMAPS; i++)
-      {
-       int h = fringe_bitmaps[i].height;
-       int wd = fringe_bitmaps[i].width;
-       unsigned short *w32bits
-         = (unsigned short *)alloca (h * sizeof (unsigned short));
-       unsigned short *wb = w32bits;
-       unsigned char *bits = fringe_bitmaps[i].bits;
-       for (j = 0; j < h; j++)
-         {
-           static unsigned char swap_nibble[16] 
-             = { 0x0, 0x8, 0x4, 0xc,    /* 0000 1000 0100 1100 */
-                 0x2, 0xa, 0x6, 0xe,    /* 0010 1010 0110 1110 */
-                 0x1, 0x9, 0x5, 0xd,    /* 0001 1001 0101 1101 */
-                 0x3, 0xb, 0x7, 0xf };  /* 0011 1011 0111 1111 */
-                 
-           unsigned char b = *bits++;
-           *wb++ = (unsigned short)((swap_nibble[b & 0xf]<<4)
-                                    | (swap_nibble[(b>>4) & 0xf]));
-         }
-       fringe_bmp[i] = CreateBitmap (wd, h, 1, 1, w32bits);
-      }
-  }
+  w32_init_fringe ();
 
 #ifndef F_SETOWN_BUG
 #ifdef F_SETOWN
 
 #ifndef F_SETOWN_BUG
 #ifdef F_SETOWN
@@ -6363,13 +6472,7 @@ x_delete_display (dpyinfo)
   xfree (dpyinfo->font_table);
   xfree (dpyinfo->w32_id_name);
 
   xfree (dpyinfo->font_table);
   xfree (dpyinfo->w32_id_name);
 
-  /* Destroy row bitmaps.  */
-  {
-    int i;
-
-    for (i = NO_FRINGE_BITMAP + 1; i < MAX_FRINGE_BITMAPS; i++)
-      DeleteObject (fringe_bmp[i]);
-  }
+  w32_reset_fringes ();
 }
 \f
 /* Set up use of W32.  */
 }
 \f
 /* Set up use of W32.  */
@@ -6380,8 +6483,11 @@ void
 x_flush (struct frame * f)
 { /* Nothing to do */ }
 
 x_flush (struct frame * f)
 { /* Nothing to do */ }
 
+extern frame_parm_handler w32_frame_parm_handlers[];
+
 static struct redisplay_interface w32_redisplay_interface =
 {
 static struct redisplay_interface w32_redisplay_interface =
 {
+  w32_frame_parm_handlers,
   x_produce_glyphs,
   x_write_glyphs,
   x_insert_glyphs,
   x_produce_glyphs,
   x_write_glyphs,
   x_insert_glyphs,
@@ -6397,6 +6503,8 @@ static struct redisplay_interface w32_redisplay_interface =
   w32_get_glyph_overhangs,
   x_fix_overlapping_area,
   w32_draw_fringe_bitmap,
   w32_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_per_char_metric,
   w32_encode_char,
   NULL, /* w32_compute_glyph_string_overhangs */
@@ -6489,16 +6597,19 @@ w32_initialize ()
   /* Dynamically link to optional system components. */
   {
     HANDLE user_lib = LoadLibrary ("user32.dll");
   /* Dynamically link to optional system components. */
   {
     HANDLE user_lib = LoadLibrary ("user32.dll");
+    HANDLE gdi_lib = LoadLibrary ("gdi32.dll");
 
 
-#define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn)
+#define LOAD_PROC(lib, fn) pfn##fn = (void *) GetProcAddress (lib, #fn)
 
     /* New proportional scroll bar functions. */
 
     /* New proportional scroll bar functions. */
-    LOAD_PROC (SetScrollInfo);
-    LOAD_PROC (GetScrollInfo);
-
+    LOAD_PROC (user_lib, SetScrollInfo);
+    LOAD_PROC (user_lib, GetScrollInfo);
+    LOAD_PROC (gdi_lib, GetFontUnicodeRanges);
+    
 #undef LOAD_PROC
 
     FreeLibrary (user_lib);
 #undef LOAD_PROC
 
     FreeLibrary (user_lib);
+    FreeLibrary (gdi_lib);
 
     /* If using proportional scroll bars, ensure handle is at least 5 pixels;
        otherwise use the fixed height.  */
 
     /* If using proportional scroll bars, ensure handle is at least 5 pixels;
        otherwise use the fixed height.  */
@@ -6525,9 +6636,9 @@ syms_of_w32term ()
   Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
 
   DEFVAR_INT ("w32-num-mouse-buttons",
   Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
 
   DEFVAR_INT ("w32-num-mouse-buttons",
-             &Vw32_num_mouse_buttons,
+             &w32_num_mouse_buttons,
              doc: /* Number of physical mouse buttons.  */);
              doc: /* Number of physical mouse buttons.  */);
-  Vw32_num_mouse_buttons = Qnil;
+  w32_num_mouse_buttons = 2;
 
   DEFVAR_LISP ("w32-swap-mouse-buttons",
              &Vw32_swap_mouse_buttons,
 
   DEFVAR_LISP ("w32-swap-mouse-buttons",
              &Vw32_swap_mouse_buttons,
@@ -6591,3 +6702,6 @@ the cursor have no effect.  */);
   staticpro (&last_mouse_motion_frame);
   last_mouse_motion_frame = Qnil;
 }
   staticpro (&last_mouse_motion_frame);
   last_mouse_motion_frame = Qnil;
 }
+
+/* arch-tag: 5fa70624-ab86-499c-8a85-473958ee4646
+   (do not change this comment) */