(fix_submap_inheritance, get_keyelt, store_in_keymap,
[bpt/emacs.git] / src / w32term.c
index 350e076..053c148 100644 (file)
@@ -1,4 +1,4 @@
-/* Implementation of Win32 GUI terminal
+/* Implementation of GUI terminal on the Microsoft W32 API.
    Copyright (C) 1989, 1993, 1994, 1995 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -14,8 +14,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+along with GNU Emacs; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 /* Added by Kevin Gallo */
 
@@ -23,9 +24,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include <config.h>
 #include <stdio.h>
 #include "lisp.h"
+#include "charset.h"
 #include "blockinput.h"
 
-#include <w32term.h>
+#include "w32term.h"
 
 #include "systty.h"
 #include "systime.h"
@@ -55,19 +57,19 @@ extern Lisp_Object Vwindow_system;
 #define x_top_window_to_frame x_window_to_frame
 
 \f
-/* This is display since win32 does not support multiple ones.  */
-struct win32_display_info one_win32_display_info;
+/* This is display since w32 does not support multiple ones.  */
+struct w32_display_info one_w32_display_info;
 
 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
-   one for each element of win32_display_list and in the same order.
+   one for each element of w32_display_list and in the same order.
    NAME is the name of the frame.
    FONT-LIST-CACHE records previous values returned by x-list-fonts.  */
-Lisp_Object win32_display_name_list;
+Lisp_Object w32_display_name_list;
 
 /* Frame being updated by update_frame.  This is declared in term.c.
    This is set by update_begin and looked at by all the
-   win32 functions.  It is zero while not inside an update.
-   In that case, the win32 functions assume that `selected_frame'
+   w32 functions.  It is zero while not inside an update.
+   In that case, the w32 functions assume that `selected_frame'
    is the frame to apply to.  */
 extern struct frame *updating_frame;
 
@@ -88,33 +90,71 @@ static int highlight;
 static int curs_x;
 static int curs_y;
 
-DWORD dwWinThreadId = 0;
-HANDLE hWinThread = NULL;
+DWORD dwWindowsThreadId = 0;
+HANDLE hWindowsThread = NULL;
 DWORD dwMainThreadId = 0;
 HANDLE hMainThread = NULL;
 
+#ifndef SIF_ALL
+/* These definitions are new with Windows 95. */
+#define SIF_RANGE           0x0001
+#define SIF_PAGE            0x0002
+#define SIF_POS             0x0004
+#define SIF_DISABLENOSCROLL 0x0008
+#define SIF_TRACKPOS        0x0010
+#define SIF_ALL             (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS)
+
+typedef struct tagSCROLLINFO
+{
+    UINT    cbSize;
+    UINT    fMask;
+    int     nMin;
+    int     nMax;
+    UINT    nPage;
+    int     nPos;
+    int     nTrackPos;
+}   SCROLLINFO, FAR *LPSCROLLINFO;
+typedef SCROLLINFO CONST FAR *LPCSCROLLINFO;
+#endif /* SIF_ALL */
+
+/* Dynamic linking to new proportional scroll bar functions. */
+int (PASCAL *pfnSetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi, BOOL fRedraw);
+BOOL (PASCAL *pfnGetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi);
+
+int vertical_scroll_bar_min_handle;
+int vertical_scroll_bar_top_border;
+int vertical_scroll_bar_bottom_border;
+
+int last_scroll_bar_drag_pos;
+
 /* Mouse movement. */
 
 /* Where the mouse was last time we reported a mouse event.  */
 static FRAME_PTR last_mouse_frame;
 static RECT last_mouse_glyph;
 
-Lisp_Object Vwin32_num_mouse_buttons;
+Lisp_Object Vw32_num_mouse_buttons;
 
-Lisp_Object Vwin32_swap_mouse_buttons;
+Lisp_Object Vw32_swap_mouse_buttons;
+
+/* Control whether x_raise_frame also sets input focus.  */
+Lisp_Object Vw32_grab_focus_on_raise;
+
+/* Control whether Caps Lock affects non-ascii characters.  */
+Lisp_Object Vw32_capslock_is_shiftlock;
 
 /* The scroll bar in which the last motion event occurred.
 
    If the last motion event occurred in a scroll bar, we set this
-   so win32_mouse_position can know whether to report a scroll bar motion or
+   so w32_mouse_position can know whether to report a scroll bar motion or
    an ordinary motion.
 
    If the last motion event didn't occur in a scroll bar, we set this
-   to Qnil, to tell win32_mouse_position to return an ordinary motion event.  */
+   to Qnil, to tell w32_mouse_position to return an ordinary motion event.  */
 Lisp_Object last_mouse_scroll_bar;
 int last_mouse_scroll_bar_pos;
 
-/* This is a hack.  We would really prefer that win32_mouse_position would
+/* This is a hack.  We would really prefer that w32_mouse_position would
    return the time associated with the position it returns, but there
    doesn't seem to be any way to wrest the timestamp from the server
    along with the position query.  So, we just keep track of the time
@@ -140,11 +180,11 @@ extern int extra_keyboard_modifiers;
 
 static Lisp_Object Qvendor_specific_keysyms;
 
-void win32_delete_display ();
+void w32_delete_display ();
 
 static void redraw_previous_char ();
 static void redraw_following_char ();
-static unsigned int win32_get_modifiers ();
+static unsigned int w32_get_modifiers ();
 
 static int fast_find_position ();
 static void note_mouse_highlight ();
@@ -152,8 +192,8 @@ static void clear_mouse_face ();
 static void show_mouse_face ();
 static void do_line_dance ();
 
-static int win32_cursor_to ();
-static int win32_clear_end_of_line ();
+static int w32_cursor_to ();
+static int w32_clear_end_of_line ();
 \f
 #if 0
 /* This is a function useful for recording debugging information
@@ -183,16 +223,16 @@ record_event (locus, type)
 
 #endif /* 0 */
 \f
-/* Return the struct win32_display_info.  */
+/* Return the struct w32_display_info.  */
 
-struct win32_display_info *
-win32_display_info_for_display ()
+struct w32_display_info *
+w32_display_info_for_display ()
 {
-  return (&one_win32_display_info);
+  return (&one_w32_display_info);
 }
 
 void 
-win32_fill_rect (f, _hdc, pix, lprect)
+w32_fill_rect (f, _hdc, pix, lprect)
      FRAME_PTR f;
      HDC _hdc;
      COLORREF pix;
@@ -219,13 +259,13 @@ win32_fill_rect (f, _hdc, pix, lprect)
 }
 
 void 
-win32_clear_window (f)
+w32_clear_window (f)
      FRAME_PTR f;
 {
   RECT rect;
 
-  GetClientRect (FRAME_WIN32_WINDOW (f), &rect);
-  win32_clear_rect (f, NULL, &rect);
+  GetClientRect (FRAME_W32_WINDOW (f), &rect);
+  w32_clear_rect (f, NULL, &rect);
 }
 
 \f
@@ -233,13 +273,13 @@ win32_clear_window (f)
 
    These hooks are called by update_frame at the beginning and end
    of a frame update.  We record in `updating_frame' the identity
-   of the frame being updated, so that the win32_... functions do not
-   need to take a frame as argument.  Most of the win32_... functions
+   of the frame being updated, so that the w32_... functions do not
+   need to take a frame as argument.  Most of the w32_... functions
    should never be called except during an update, the only exceptions
-   being win32_cursor_to, win32_write_glyphs and win32_reassert_line_highlight.  */
+   being w32_cursor_to, w32_write_glyphs and w32_reassert_line_highlight.  */
 
 static
-win32_update_begin (f)
+w32_update_begin (f)
      struct frame *f;
 {
   if (f == 0)
@@ -252,26 +292,26 @@ win32_update_begin (f)
 
   /* Regenerate display palette before drawing if list of requested
      colors has changed. */
-  if (FRAME_WIN32_DISPLAY_INFO (f)->regen_palette)
+  if (FRAME_W32_DISPLAY_INFO (f)->regen_palette)
   {
-    win32_regenerate_palette (f);
-    FRAME_WIN32_DISPLAY_INFO (f)->regen_palette = FALSE;
+    w32_regenerate_palette (f);
+    FRAME_W32_DISPLAY_INFO (f)->regen_palette = FALSE;
   }
 
-  if (f == FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_mouse_frame)
+  if (f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame)
     {
       /* Don't do highlighting for mouse motion during the update.  */
-      FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_defer = 1;
+      FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 1;
 
       /* If the frame needs to be redrawn,
         simply forget about any prior mouse highlighting.  */
       if (FRAME_GARBAGED_P (f))
-       FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_window = Qnil;
+       FRAME_W32_DISPLAY_INFO (f)->mouse_face_window = Qnil;
 
-      if (!NILP (FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_window))
+      if (!NILP (FRAME_W32_DISPLAY_INFO (f)->mouse_face_window))
        {
          int firstline, lastline, i;
-         struct window *w = XWINDOW (FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_window);
+         struct window *w = XWINDOW (FRAME_W32_DISPLAY_INFO (f)->mouse_face_window);
 
          /* Find the first, and the last+1, lines affected by redisplay.  */
          for (firstline = 0; firstline < f->height; firstline++)
@@ -294,7 +334,7 @@ win32_update_begin (f)
             are all wrong, and we will redisplay that line anyway.  */
          if (! (firstline > (XFASTINT (w->top) + window_internal_height (w))
                 || lastline < XFASTINT (w->top)))
-           clear_mouse_face (FRAME_WIN32_DISPLAY_INFO (f));
+           clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
        }
     }
 
@@ -302,7 +342,7 @@ win32_update_begin (f)
 }
 
 static
-win32_update_end (f)
+w32_update_end (f)
      struct frame *f;
 {
   BLOCK_INPUT;
@@ -310,8 +350,8 @@ win32_update_end (f)
   do_line_dance ();
   x_display_cursor (f, 1);
 
-  if (f == FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_mouse_frame)
-    FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_defer = 0;
+  if (f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame)
+    FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 0;
 
   UNBLOCK_INPUT;
 }
@@ -319,24 +359,26 @@ win32_update_end (f)
 /* This is called after a redisplay on frame F.  */
 
 static
-win32_frame_up_to_date (f)
+w32_frame_up_to_date (f)
      FRAME_PTR f;
 {
-  if (FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_deferred_gc
-      || f == FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_mouse_frame)
+  BLOCK_INPUT;
+  if (FRAME_W32_DISPLAY_INFO (f)->mouse_face_deferred_gc
+      || f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame)
     {
-      note_mouse_highlight (FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_mouse_frame,
-                           FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_mouse_x,
-                           FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_mouse_y);
-      FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_deferred_gc = 0;
+      note_mouse_highlight (FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame,
+                           FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_x,
+                           FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_y);
+      FRAME_W32_DISPLAY_INFO (f)->mouse_face_deferred_gc = 0;
     }
+  UNBLOCK_INPUT;
 }
 \f
 /* External interface to control of standout mode.
    Call this when about to modify line at position VPOS
    and not change whether it is highlighted.  */
 
-win32_reassert_line_highlight (new, vpos)
+w32_reassert_line_highlight (new, vpos)
      int new, vpos;
 {
   highlight = new;
@@ -346,12 +388,12 @@ win32_reassert_line_highlight (new, vpos)
    and change whether it is highlighted.  */
 
 static
-win32_change_line_highlight (new_highlight, vpos, first_unused_hpos)
+w32_change_line_highlight (new_highlight, vpos, first_unused_hpos)
      int new_highlight, vpos, first_unused_hpos;
 {
   highlight = new_highlight;
-  win32_cursor_to (vpos, 0);
-  win32_clear_end_of_line (updating_frame->width);
+  w32_cursor_to (vpos, 0);
+  w32_clear_end_of_line (updating_frame->width);
 }
 
 /* This is used when starting Emacs and when restarting after suspend.
@@ -359,16 +401,16 @@ win32_change_line_highlight (new_highlight, vpos, first_unused_hpos)
    to Emacs's own window if it is suspended (though that rarely happens).  */
 
 static
-win32_set_terminal_modes ()
+w32_set_terminal_modes ()
 {
 }
 
 /* This is called when exiting or suspending Emacs.
-   Exiting will make the Win32 windows go away, and suspending
+   Exiting will make the W32 windows go away, and suspending
    requires no action.  */
 
 static
-win32_reset_terminal_modes ()
+w32_reset_terminal_modes ()
 {
 }
 \f
@@ -377,7 +419,7 @@ win32_reset_terminal_modes ()
    This does not affect the place where the cursor-box is displayed.  */
 
 static int
-win32_cursor_to (row, col)
+w32_cursor_to (row, col)
      register int row, col;
 {
   int orow = row;
@@ -423,7 +465,7 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground)
   register char *cp;            /* Steps through buf[]. */
   register int tlen = GLYPH_TABLE_LENGTH;
   register Lisp_Object *tbase = GLYPH_TABLE_BASE;
-  Window window = FRAME_WIN32_WINDOW (f);
+  Window window = FRAME_W32_WINDOW (f);
   int orig_left = left;
   HDC hdc;
 
@@ -467,7 +509,7 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground)
 
        /* HL = 3 means use a mouse face previously chosen.  */
        if (hl == 3)
-         cf = FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_face_id;
+         cf = FRAME_W32_DISPLAY_INFO (f)->mouse_face_face_id;
 
        /* First look at the face of the text itself.  */
        if (cf != 0)
@@ -509,24 +551,24 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground)
 
            if ((!face->font
                 || face->font == (XFontStruct *) FACE_DEFAULT
-                || face->font == f->output_data.win32->font)
-               && face->background == f->output_data.win32->background_pixel
-               && face->foreground == f->output_data.win32->foreground_pixel)
+                || face->font == f->output_data.w32->font)
+               && face->background == f->output_data.w32->background_pixel
+               && face->foreground == f->output_data.w32->foreground_pixel)
              {
-               bg = f->output_data.win32->cursor_pixel;
+               bg = f->output_data.w32->cursor_pixel;
                fg = face->background;
              }
            /* Cursor on non-default face: must merge.  */
            else
              {
-               bg = f->output_data.win32->cursor_pixel;
+               bg = f->output_data.w32->cursor_pixel;
                fg = face->background;
                /* If the glyph would be invisible,
                   try a different foreground.  */
                if (fg == bg)
                  fg = face->foreground;
                if (fg == bg)
-                 fg = f->output_data.win32->cursor_foreground_pixel;
+                 fg = f->output_data.w32->cursor_foreground_pixel;
                if (fg == bg)
                  fg = face->foreground;
                /* Make sure the cursor is distinct from text in this face.  */
@@ -540,7 +582,7 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground)
          }
 
        if (font == (XFontStruct *) FACE_DEFAULT)
-         font = f->output_data.win32->font;
+         font = f->output_data.w32->font;
 
        SetBkMode (hdc, just_foreground ? TRANSPARENT : OPAQUE);
 
@@ -554,12 +596,12 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground)
        if (!just_foreground)
          {
            /* Clear the rest of the line's height.  */
-           if (f->output_data.win32->line_height != FONT_HEIGHT (font))
-               win32_fill_area (f, hdc, bg,
+           if (f->output_data.w32->line_height != FONT_HEIGHT (font))
+               w32_fill_area (f, hdc, bg,
                                 left,
                                 top + FONT_HEIGHT (font),
                                 FONT_WIDTH (font) * len,
-                                f->output_data.win32->line_height - FONT_HEIGHT (font));
+                                f->output_data.w32->line_height - FONT_HEIGHT (font));
          }
 
        {
@@ -569,7 +611,7 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground)
              underline_position = font->tm.tmDescent - 1;
 
          if (face->underline)
-             win32_fill_area (f, hdc, fg,
+             w32_fill_area (f, hdc, fg,
                               left, (top
                                      + FONT_BASE (font)
                                      + underline_position),
@@ -588,11 +630,11 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground)
    Advance the cursor over the text.
    Output LEN glyphs at START.
 
-   `highlight', set up by win32_reassert_line_highlight or win32_change_line_highlight,
+   `highlight', set up by w32_reassert_line_highlight or w32_change_line_highlight,
    controls the pixel values used for foreground and background.  */
 
 static
-win32_write_glyphs (start, len)
+w32_write_glyphs (start, len)
      register GLYPH *start;
      int len;
 {
@@ -641,7 +683,7 @@ win32_write_glyphs (start, len)
    from FIRST_UNUSED onward is already erased.  */
 
 static
-win32_clear_end_of_line (first_unused)
+w32_clear_end_of_line (first_unused)
      register int first_unused;
 {
   struct frame *f = updating_frame;
@@ -657,6 +699,8 @@ win32_clear_end_of_line (first_unused)
   if (first_unused >= f->width)
     first_unused = f->width;
 
+  first_unused += FRAME_LEFT_SCROLL_BAR_WIDTH (f);
+
   BLOCK_INPUT;
 
   do_line_dance ();
@@ -667,17 +711,17 @@ win32_clear_end_of_line (first_unused)
       && f->phys_cursor_x < first_unused)
     f->phys_cursor_x = -1;
 
-  win32_clear_area (f, NULL,
+  w32_clear_area (f, NULL,
                    CHAR_TO_PIXEL_COL (f, curs_x),
                    CHAR_TO_PIXEL_ROW (f, curs_y),
-                   FONT_WIDTH (f->output_data.win32->font) * (first_unused - curs_x),
-                   f->output_data.win32->line_height);
+                   FONT_WIDTH (f->output_data.w32->font) * (first_unused - curs_x),
+                   f->output_data.w32->line_height);
 
   UNBLOCK_INPUT;
 }
 
 static
-win32_clear_frame ()
+w32_clear_frame ()
 {
   struct frame *f = updating_frame;
 
@@ -690,7 +734,7 @@ win32_clear_frame ()
 
   BLOCK_INPUT;
 
-  win32_clear_window (f);
+  w32_clear_window (f);
 
   /* We have to clear the scroll bars, too.  If we have changed
      colors or something like that, then they should be notified.  */
@@ -701,14 +745,14 @@ win32_clear_frame ()
 \f
 /* Make audible bell.  */
 
-win32_ring_bell ()
+w32_ring_bell ()
 {
   BLOCK_INPUT;
 
   if (visible_bell)
-      FlashWindow (FRAME_WIN32_WINDOW (selected_frame), FALSE);
+      FlashWindow (FRAME_W32_WINDOW (selected_frame), FALSE);
   else
-      nt_ring_bell ();
+      w32_sys_ring_bell ();
 
   UNBLOCK_INPUT;
 
@@ -720,7 +764,7 @@ win32_ring_bell ()
    off the feature of using them.  */
 
 static
-win32_insert_glyphs (start, len)
+w32_insert_glyphs (start, len)
      register char *start;
      register int len;
 {
@@ -728,7 +772,7 @@ win32_insert_glyphs (start, len)
 }
 
 static
-win32_delete_glyphs (n)
+w32_delete_glyphs (n)
      register int n;
 {
   abort ();
@@ -737,10 +781,10 @@ win32_delete_glyphs (n)
 /* Specify how many text lines, from the top of the window,
    should be affected by insert-lines and delete-lines operations.
    This, and those operations, are used only within an update
-   that is bounded by calls to win32_update_begin and win32_update_end.  */
+   that is bounded by calls to w32_update_begin and w32_update_end.  */
 
 static
-win32_set_terminal_window (n)
+w32_set_terminal_window (n)
      register int n;
 {
   if (updating_frame == 0)
@@ -770,7 +814,7 @@ static int line_dance_in_progress;
 
 /* Perform an insert-lines or delete-lines operation,
    inserting N lines or deleting -N lines at vertical position VPOS.  */
-win32_ins_del_lines (vpos, n)
+w32_ins_del_lines (vpos, n)
      int vpos, n;
 {
   register int fence, i;
@@ -833,7 +877,7 @@ do_line_dance ()
     abort ();
 
   ht = f->height;
-  intborder = f->output_data.win32->internal_border_width;
+  intborder = f->output_data.w32->internal_border_width;
 
   x_display_cursor (updating_frame, 0);
 
@@ -847,8 +891,8 @@ do_line_dance ()
        /* Copy [i,j) upward from [i+distance, j+distance) */
        BitBlt (hdc, 
                intborder, CHAR_TO_PIXEL_ROW (f, i+distance),
-               f->width * FONT_WIDTH (f->output_data.win32->font),
-               (j-i) * f->output_data.win32->line_height, 
+               f->width * FONT_WIDTH (f->output_data.w32->font),
+               (j-i) * f->output_data.w32->line_height, 
                hdc,
                intborder, CHAR_TO_PIXEL_ROW (f, i),
                SRCCOPY);
@@ -863,29 +907,29 @@ do_line_dance ()
        /* Copy (j, i] downward from (j+distance, i+distance] */
        BitBlt (hdc,
                intborder, CHAR_TO_PIXEL_ROW (f, j+1+distance),
-               f->width * FONT_WIDTH (f->output_data.win32->font),
-               (i-j) * f->output_data.win32->line_height, 
+               f->width * FONT_WIDTH (f->output_data.w32->font),
+               (i-j) * f->output_data.w32->line_height, 
                hdc,
                intborder, CHAR_TO_PIXEL_ROW (f, j+1),
                SRCCOPY);
        i = j+1;
       }
 
-  release_frame_dc (f, hdc);
-
   for (i = 0; i < ht; ++i)
     if (line_dance[i] == -1)
       {
        for (j = i; j < ht && line_dance[j] == -1; ++j);
        /* Clear [i,j) */
-       win32_clear_area (f, NULL,
+       w32_clear_area (f, hdc,
                          intborder, 
                          CHAR_TO_PIXEL_ROW (f, i),
-                         f->width * FONT_WIDTH (f->output_data.win32->font),
-                         (j-i) * f->output_data.win32->line_height);
+                         f->width * FONT_WIDTH (f->output_data.w32->font),
+                         (j-i) * f->output_data.w32->line_height);
        i = j-1;
       }
   line_dance_in_progress = 0;
+
+  release_frame_dc (f, hdc);
 }
 \f
 /* Support routines for exposure events.  */
@@ -918,8 +962,8 @@ dumprectangle (f, left, top, cols, rows)
      Round down for left and top, up for right and bottom.  */
   top  = PIXEL_TO_CHAR_ROW (f, top);
   left = PIXEL_TO_CHAR_COL (f, left);
-  bottom += (f->output_data.win32->line_height - 1);
-  right += (FONT_WIDTH (f->output_data.win32->font) - 1);
+  bottom += (f->output_data.w32->line_height - 1);
+  right += (FONT_WIDTH (f->output_data.w32->font) - 1);
   bottom = PIXEL_TO_CHAR_ROW (f, bottom);
   right = PIXEL_TO_CHAR_COL (f, right);
 
@@ -986,7 +1030,7 @@ frame_unhighlight (f)
   x_display_cursor (f, 1);
 }
 
-static void win32_frame_rehighlight ();
+static void w32_frame_rehighlight ();
 static void x_frame_rehighlight ();
 
 /* The focus has changed.  Update the frames as necessary to reflect
@@ -997,23 +1041,23 @@ static void x_frame_rehighlight ();
 
 void
 x_new_focus_frame (dpyinfo, frame)
-     struct win32_display_info *dpyinfo;
+     struct w32_display_info *dpyinfo;
      struct frame *frame;
 {
-  struct frame *old_focus = dpyinfo->win32_focus_frame;
+  struct frame *old_focus = dpyinfo->w32_focus_frame;
   int events_enqueued = 0;
 
-  if (frame != dpyinfo->win32_focus_frame)
+  if (frame != dpyinfo->w32_focus_frame)
     {
       /* Set this before calling other routines, so that they see
-        the correct value of win32_focus_frame.  */
-      dpyinfo->win32_focus_frame = frame;
+        the correct value of w32_focus_frame.  */
+      dpyinfo->w32_focus_frame = frame;
 
       if (old_focus && old_focus->auto_lower)
        x_lower_frame (old_focus);
 
-      if (dpyinfo->win32_focus_frame && dpyinfo->win32_focus_frame->auto_raise)
-       pending_autoraise_frame = dpyinfo->win32_focus_frame;
+      if (dpyinfo->w32_focus_frame && dpyinfo->w32_focus_frame->auto_raise)
+       pending_autoraise_frame = dpyinfo->w32_focus_frame;
       else
        pending_autoraise_frame = 0;
     }
@@ -1025,9 +1069,9 @@ x_new_focus_frame (dpyinfo, frame)
 
 void
 x_mouse_leave (dpyinfo)
-     struct win32_display_info *dpyinfo;
+     struct w32_display_info *dpyinfo;
 {
-  x_new_focus_frame (dpyinfo, dpyinfo->win32_focus_event_frame);
+  x_new_focus_frame (dpyinfo, dpyinfo->w32_focus_event_frame);
 }
 
 /* The focus has changed, or we have redirected a frame's focus to
@@ -1038,39 +1082,39 @@ x_mouse_leave (dpyinfo)
    frame is being highlighted or unhighlighted; we only use it to find
    the appropriate display info.  */
 static void
-win32_frame_rehighlight (frame)
+w32_frame_rehighlight (frame)
      struct frame *frame;
 {
-  x_frame_rehighlight (FRAME_WIN32_DISPLAY_INFO (frame));
+  x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame));
 }
 
 static void
 x_frame_rehighlight (dpyinfo)
-     struct win32_display_info *dpyinfo;
+     struct w32_display_info *dpyinfo;
 {
-  struct frame *old_highlight = dpyinfo->win32_highlight_frame;
+  struct frame *old_highlight = dpyinfo->w32_highlight_frame;
 
-  if (dpyinfo->win32_focus_frame)
+  if (dpyinfo->w32_focus_frame)
     {
-      dpyinfo->win32_highlight_frame
-       = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->win32_focus_frame)))
-          ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->win32_focus_frame))
-          : dpyinfo->win32_focus_frame);
-      if (! FRAME_LIVE_P (dpyinfo->win32_highlight_frame))
+      dpyinfo->w32_highlight_frame
+       = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame)))
+          ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame))
+          : dpyinfo->w32_focus_frame);
+      if (! FRAME_LIVE_P (dpyinfo->w32_highlight_frame))
        {
-         FRAME_FOCUS_FRAME (dpyinfo->win32_focus_frame) = Qnil;
-         dpyinfo->win32_highlight_frame = dpyinfo->win32_focus_frame;
+         FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame) = Qnil;
+         dpyinfo->w32_highlight_frame = dpyinfo->w32_focus_frame;
        }
     }
   else
-    dpyinfo->win32_highlight_frame = 0;
+    dpyinfo->w32_highlight_frame = 0;
 
-  if (dpyinfo->win32_highlight_frame != old_highlight)
+  if (dpyinfo->w32_highlight_frame != old_highlight)
     {
       if (old_highlight)
        frame_unhighlight (old_highlight);
-      if (dpyinfo->win32_highlight_frame)
-       frame_highlight (dpyinfo->win32_highlight_frame);
+      if (dpyinfo->w32_highlight_frame)
+       frame_highlight (dpyinfo->w32_highlight_frame);
     }
 }
 \f
@@ -1118,9 +1162,9 @@ pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
   /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
      even for negative values.  */
   if (pix_x < 0)
-    pix_x -= FONT_WIDTH ((f)->output_data.win32->font) - 1;
+    pix_x -= FONT_WIDTH ((f)->output_data.w32->font) - 1;
   if (pix_y < 0)
-    pix_y -= (f)->output_data.win32->line_height - 1;
+    pix_y -= (f)->output_data.w32->line_height - 1;
 
   pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
   pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
@@ -1129,8 +1173,8 @@ pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
     {
       bounds->left = CHAR_TO_PIXEL_COL (f, pix_x);
       bounds->top = CHAR_TO_PIXEL_ROW (f, pix_y);
-      bounds->right  = bounds->left + FONT_WIDTH  (f->output_data.win32->font) - 1;
-      bounds->bottom = bounds->top + f->output_data.win32->line_height - 1;
+      bounds->right  = bounds->left + FONT_WIDTH  (f->output_data.w32->font) - 1;
+      bounds->bottom = bounds->top + f->output_data.w32->line_height - 1;
     }
 
   if (!noclip)
@@ -1188,28 +1232,28 @@ parse_button (message, pbutton, pup)
       up = 1;
       break;
     case WM_MBUTTONDOWN:
-      if (NILP (Vwin32_swap_mouse_buttons))
+      if (NILP (Vw32_swap_mouse_buttons))
        button = 1;
       else
        button = 2;
       up = 0;
       break;
     case WM_MBUTTONUP:
-      if (NILP (Vwin32_swap_mouse_buttons))
+      if (NILP (Vw32_swap_mouse_buttons))
        button = 1;
       else
        button = 2;
       up = 1;
       break;
     case WM_RBUTTONDOWN:
-      if (NILP (Vwin32_swap_mouse_buttons))
+      if (NILP (Vw32_swap_mouse_buttons))
        button = 2;
       else
        button = 1;
       up = 0;
       break;
     case WM_RBUTTONUP:
-      if (NILP (Vwin32_swap_mouse_buttons))
+      if (NILP (Vw32_swap_mouse_buttons))
        button = 2;
       else
        button = 1;
@@ -1234,7 +1278,7 @@ parse_button (message, pbutton, pup)
 static void
 construct_mouse_click (result, msg, f)
      struct input_event *result;
-     Win32Msg *msg;
+     W32Msg *msg;
      struct frame *f;
 {
   int button;
@@ -1261,6 +1305,25 @@ construct_mouse_click (result, msg, f)
   }
 }
 
+static void
+construct_mouse_wheel (result, msg, f)
+     struct input_event *result;
+     W32Msg *msg;
+     struct frame *f;
+{
+  POINT p;
+  result->kind = mouse_wheel;
+  result->code = (short) HIWORD (msg->msg.wParam);
+  result->timestamp = msg->msg.time;
+  result->modifiers = msg->dwModifiers;
+  p.x = LOWORD (msg->msg.lParam);
+  p.y = HIWORD (msg->msg.lParam);
+  ScreenToClient(msg->msg.hwnd, &p);
+  XSETINT (result->x, p.x);
+  XSETINT (result->y, p.y);
+  XSETFRAME (result->frame_or_window, f);
+}
+
 \f
 /* Function to report a mouse movement to the mainstream Emacs code.
    The input handler calls this.
@@ -1277,7 +1340,7 @@ note_mouse_movement (frame, msg)
 {
   last_mouse_movement_time = msg->time;
 
-  if (msg->hwnd != FRAME_WIN32_WINDOW (frame))
+  if (msg->hwnd != FRAME_W32_WINDOW (frame))
     {
       frame->mouse_moved = 1;
       last_mouse_scroll_bar = Qnil;
@@ -1319,37 +1382,38 @@ note_mouse_highlight (f, x, y)
   if (disable_mouse_highlight)
     return;
 
-  FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_mouse_x = x;
-  FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_mouse_y = y;
-  FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_mouse_frame = f;
+  FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_x = x;
+  FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_y = y;
+  FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame = f;
 
-  if (FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_defer)
+  if (FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer)
     return;
 
   if (gc_in_progress)
     {
-      FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_deferred_gc = 1;
+      FRAME_W32_DISPLAY_INFO (f)->mouse_face_deferred_gc = 1;
       return;
     }
 
   /* Find out which glyph the mouse is on.  */
   pixel_to_glyph_coords (f, x, y, &column, &row,
-                        &new_glyph, FRAME_WIN32_DISPLAY_INFO (f)->grabbed);
+                        &new_glyph, FRAME_W32_DISPLAY_INFO (f)->grabbed);
 
   /* Which window is that in?  */
   window = window_from_coordinates (f, column, row, &portion);
   w = XWINDOW (window);
 
   /* If we were displaying active text in another window, clear that.  */
-  if (! EQ (window, FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_window))
-    clear_mouse_face (FRAME_WIN32_DISPLAY_INFO (f));
+  if (! EQ (window, FRAME_W32_DISPLAY_INFO (f)->mouse_face_window))
+    clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
 
   /* Are we in a window whose display is up to date?
      And verify the buffer's text has not changed.  */
   if (WINDOWP (window) && portion == 0 && row >= 0 && column >= 0
       && row < FRAME_HEIGHT (f) && column < FRAME_WIDTH (f)
       && EQ (w->window_end_valid, w->buffer)
-      && w->last_modified == BUF_MODIFF (XBUFFER (w->buffer)))
+      && w->last_modified == BUF_MODIFF (XBUFFER (w->buffer))
+      && w->last_overlay_modified == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer)))
     {
       int *ptr = FRAME_CURRENT_GLYPHS (f)->charstarts[row];
       int i, pos;
@@ -1361,15 +1425,15 @@ note_mouse_highlight (f, x, y)
       pos = ptr[i];
       /* Is it outside the displayed active region (if any)?  */
       if (pos <= 0)
-       clear_mouse_face (FRAME_WIN32_DISPLAY_INFO (f));
-      else if (! (EQ (window, FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_window)
-                 && row >= FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_row
-                 && row <= FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_row
-                 && (row > FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_row
-                     || column >= FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_col)
-                 && (row < FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_row
-                     || column < FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_col
-                     || FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_past_end)))
+       clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
+      else if (! (EQ (window, FRAME_W32_DISPLAY_INFO (f)->mouse_face_window)
+                 && row >= FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row
+                 && row <= FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row
+                 && (row > FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row
+                     || column >= FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col)
+                 && (row < FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row
+                     || column < FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col
+                     || FRAME_W32_DISPLAY_INFO (f)->mouse_face_past_end)))
        {
          Lisp_Object mouse_face, overlay, position;
          Lisp_Object *overlay_vec;
@@ -1391,7 +1455,7 @@ note_mouse_highlight (f, x, y)
          ZV = Z;
 
          /* Yes.  Clear the display of the old active region, if any.  */
-         clear_mouse_face (FRAME_WIN32_DISPLAY_INFO (f));
+         clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
 
          /* Is this char mouse-active?  */
          XSETINT (position, pos);
@@ -1433,19 +1497,19 @@ note_mouse_highlight (f, x, y)
              after = Foverlay_end (overlay);
              /* Record this as the current active region.  */
              fast_find_position (window, before,
-                                 &FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_col,
-                                 &FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_row);
-             FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_past_end
+                                 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col,
+                                 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row);
+             FRAME_W32_DISPLAY_INFO (f)->mouse_face_past_end
                = !fast_find_position (window, after,
-                                      &FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_col,
-                                      &FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_row);
-             FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_window = window;
-             FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_face_id
+                                      &FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col,
+                                      &FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row);
+             FRAME_W32_DISPLAY_INFO (f)->mouse_face_window = window;
+             FRAME_W32_DISPLAY_INFO (f)->mouse_face_face_id
                = compute_char_face (f, w, pos, 0, 0,
                                     &ignore, pos + 1, 1);
 
              /* Display it as active.  */
-             show_mouse_face (FRAME_WIN32_DISPLAY_INFO (f), 1);
+             show_mouse_face (FRAME_W32_DISPLAY_INFO (f), 1);
            }
          /* Handle the text property case.  */
          else if (! NILP (mouse_face))
@@ -1467,19 +1531,19 @@ note_mouse_highlight (f, x, y)
                                                w->buffer, end);
              /* Record this as the current active region.  */
              fast_find_position (window, before,
-                                 &FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_col,
-                                 &FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_row);
-             FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_past_end
+                                 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col,
+                                 &FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row);
+             FRAME_W32_DISPLAY_INFO (f)->mouse_face_past_end
                = !fast_find_position (window, after,
-                                      &FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_col,
-                                      &FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_row);
-             FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_window = window;
-             FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_face_id
+                                      &FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col,
+                                      &FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row);
+             FRAME_W32_DISPLAY_INFO (f)->mouse_face_window = window;
+             FRAME_W32_DISPLAY_INFO (f)->mouse_face_face_id
                = compute_char_face (f, w, pos, 0, 0,
                                     &ignore, pos + 1, 1);
 
              /* Display it as active.  */
-             show_mouse_face (FRAME_WIN32_DISPLAY_INFO (f), 1);
+             show_mouse_face (FRAME_W32_DISPLAY_INFO (f), 1);
            }
          BEGV = obegv;
          ZV = ozv;
@@ -1507,7 +1571,7 @@ fast_find_position (window, pos, columnp, rowp)
   FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
   int i;
   int row = 0;
-  int left = w->left;
+  int left = WINDOW_LEFT_MARGIN (w);
   int top = w->top;
   int height = XFASTINT (w->height) - ! MINI_WINDOW_P (w);
   int width = window_internal_width (w);
@@ -1570,7 +1634,7 @@ fast_find_position (window, pos, columnp, rowp)
 
 static void
 show_mouse_face (dpyinfo, hl)
-     struct win32_display_info *dpyinfo;
+     struct w32_display_info *dpyinfo;
      int hl;
 {
   struct window *w = XWINDOW (dpyinfo->mouse_face_window);
@@ -1587,22 +1651,22 @@ show_mouse_face (dpyinfo, hl)
   curs_x = f->phys_cursor_x;
   curs_y = f->phys_cursor_y;
 
-  for (i = FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_row;
-       i <= FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_row; i++)
+  for (i = FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row;
+       i <= FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row; i++)
     {
-      int column = (i == FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_row
-                   ? FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_col
-                   : w->left);
-      int endcolumn = (i == FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_row
-                      ? FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_col
-                      : w->left + width);
+      int column = (i == FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row
+                   ? FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col
+                   : WINDOW_LEFT_MARGIN (w));
+      int endcolumn = (i == FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row
+                      ? FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col
+                      : WINDOW_LEFT_MARGIN (w) + width);
       endcolumn = min (endcolumn, FRAME_CURRENT_GLYPHS (f)->used[i]);
 
       /* If the cursor's in the text we are about to rewrite,
         turn the cursor off.  */
       if (i == curs_y
-         && curs_x >= FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_col - 1
-         && curs_x <= FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_col)
+         && curs_x >= column - 1
+         && curs_x <= endcolumn)
        {
          x_display_cursor (f, 0);
          cursor_off = 1;
@@ -1626,9 +1690,9 @@ show_mouse_face (dpyinfo, hl)
 
   /* Change the mouse cursor according to the value of HL.  */
   if (hl > 0)
-    SetCursor (f->output_data.win32->cross_cursor);
+    SetCursor (f->output_data.w32->cross_cursor);
   else
-    SetCursor (f->output_data.win32->text_cursor);
+    SetCursor (f->output_data.w32->text_cursor);
 }
 
 /* Clear out the mouse-highlighted active region.
@@ -1636,7 +1700,7 @@ show_mouse_face (dpyinfo, hl)
 
 static void
 clear_mouse_face (dpyinfo)
-     struct win32_display_info *dpyinfo;
+     struct w32_display_info *dpyinfo;
 {
   if (! NILP (dpyinfo->mouse_face_window))
     show_mouse_face (dpyinfo, 0);
@@ -1672,7 +1736,7 @@ static void x_scroll_bar_report_motion ();
    again. */
 
 static void
-win32_mouse_position (fp, insist, bar_window, part, x, y, time)
+w32_mouse_position (fp, insist, bar_window, part, x, y, time)
      FRAME_PTR *fp;
      int insist;
      Lisp_Object *bar_window;
@@ -1684,7 +1748,8 @@ win32_mouse_position (fp, insist, bar_window, part, x, y, time)
 
   BLOCK_INPUT;
 
-  if (! NILP (last_mouse_scroll_bar))
+  if (! NILP (last_mouse_scroll_bar) && insist == 0)
+    /* This is never called at the moment.  */
     x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
   else
     {
@@ -1703,7 +1768,7 @@ win32_mouse_position (fp, insist, bar_window, part, x, y, time)
       /* Now we have a position on the root; find the innermost window
         containing the pointer.  */
       {
-       if (FRAME_WIN32_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
+       if (FRAME_W32_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
            && FRAME_LIVE_P (last_mouse_frame))
          {
            f1 = last_mouse_frame;
@@ -1711,7 +1776,7 @@ win32_mouse_position (fp, insist, bar_window, part, x, y, time)
        else
          {
            /* Is win one of our frames?  */
-           f1 = x_window_to_frame (FRAME_WIN32_DISPLAY_INFO (*fp), WindowFromPoint(pt));
+           f1 = x_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp), WindowFromPoint(pt));
          }
 
        /* If not, is it one of our scroll bars?  */
@@ -1725,20 +1790,20 @@ win32_mouse_position (fp, insist, bar_window, part, x, y, time)
              }
          }
 
-       if (f1 == 0 && insist)
+       if (f1 == 0 && insist > 0)
          f1 = selected_frame;
 
        if (f1)
          {
            int ignore1, ignore2;
 
-           ScreenToClient (FRAME_WIN32_WINDOW (f1), &pt);
+           ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
 
            /* Ok, we found a frame.  Store all the values.  */
 
            pixel_to_glyph_coords (f1, pt.x, pt.y, &ignore1, &ignore2,
                                   &last_mouse_glyph,
-                                  FRAME_WIN32_DISPLAY_INFO (f1)->grabbed
+                                  FRAME_W32_DISPLAY_INFO (f1)->grabbed
                                   || insist);
 
            *bar_window = Qnil;
@@ -1786,7 +1851,7 @@ x_window_to_scroll_bar (window_id)
                               condemned = Qnil,
                               ! GC_NILP (bar));
           bar = XSCROLL_BAR (bar)->next)
-       if (SCROLL_BAR_WIN32_WINDOW (XSCROLL_BAR (bar)) == window_id)
+       if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id)
          return XSCROLL_BAR (bar);
     }
 
@@ -1798,34 +1863,31 @@ my_create_scrollbar (f, bar)
      struct frame * f;
      struct scroll_bar * bar;
 {
-  MSG msg;
-  
-  PostThreadMessage (dwWinThreadId, WM_EMACS_CREATESCROLLBAR, (WPARAM) f, 
-                    (LPARAM) bar);
-  GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
-  
-  return ((HWND) msg.wParam);
+  return (HWND) SendMessage (FRAME_W32_WINDOW (f),
+                            WM_EMACS_CREATESCROLLBAR, (WPARAM) f, 
+                            (LPARAM) bar);
 }
 
 //#define ATTACH_THREADS
 
-void
-my_show_window (HWND hwnd, int how)
+BOOL
+my_show_window (FRAME_PTR f, HWND hwnd, int how)
 {
 #ifndef ATTACH_THREADS
-  SendMessage (hwnd, WM_EMACS_SHOWWINDOW, (WPARAM) how, 0);
+  return SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SHOWWINDOW,
+                     (WPARAM) hwnd, (LPARAM) how);
 #else
-  ShowWindow (hwnd , how);
+  return ShowWindow (hwnd, how);
 #endif
 }
 
 void
 my_set_window_pos (HWND hwnd, HWND hwndAfter,
-                  int x, int y, int cx, int cy, int flags)
+                  int x, int y, int cx, int cy, UINT flags)
 {
 #ifndef ATTACH_THREADS
-  Win32WindowPos pos;
-  pos.hwndAfter = hwndAfter;
+  WINDOWPOS pos;
+  pos.hwndInsertAfter = hwndAfter;
   pos.x = x;
   pos.y = y;
   pos.cx = cx;
@@ -1837,12 +1899,21 @@ my_set_window_pos (HWND hwnd, HWND hwndAfter,
 #endif
 }
 
+BOOL
+my_set_focus (f, hwnd)
+     struct frame * f;
+     HWND hwnd;
+{
+  SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SETFOCUS, 
+              (WPARAM) hwnd, 0);
+}
+
 void
 my_destroy_window (f, hwnd)
      struct frame * f;
      HWND hwnd;
 {
-  SendMessage (FRAME_WIN32_WINDOW (f), WM_EMACS_DESTROYWINDOW, 
+  SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_DESTROYWINDOW, 
               (WPARAM) hwnd, 0);
 }
 
@@ -1873,10 +1944,27 @@ x_scroll_bar_create (window, top, left, width, height)
 
   hwnd = my_create_scrollbar (f, bar);
 
-  SetScrollRange (hwnd, SB_CTL, 0, height, FALSE);
-  SetScrollPos (hwnd, SB_CTL, 0, TRUE);
+  if (pfnSetScrollInfo)
+    {
+      SCROLLINFO si;
+
+      si.cbSize = sizeof (si);
+      si.fMask = SIF_ALL;
+      si.nMin = 0;
+      si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (height)
+       + VERTICAL_SCROLL_BAR_MIN_HANDLE;
+      si.nPage = si.nMax;
+      si.nPos = 0;
+
+      pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE);
+    }
+  else
+    {
+      SetScrollRange (hwnd, SB_CTL, 0, VERTICAL_SCROLL_BAR_TOP_RANGE (height), FALSE);
+      SetScrollPos (hwnd, SB_CTL, 0, FALSE);
+    }
 
-  SET_SCROLL_BAR_WIN32_WINDOW (bar, hwnd);
+  SET_SCROLL_BAR_W32_WINDOW (bar, hwnd);
 
   /* Add bar to its frame's list of scroll bars.  */
   bar->next = FRAME_SCROLL_BARS (f);
@@ -1908,7 +1996,7 @@ x_scroll_bar_set_handle (bar, start, end, rebuild)
      int rebuild;
 {
   int dragging = ! NILP (bar->dragging);
-  Window w = SCROLL_BAR_WIN32_WINDOW (bar);
+  Window w = SCROLL_BAR_W32_WINDOW (bar);
   FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
 
   /* If the display is already accurate, do nothing.  */
@@ -1919,11 +2007,48 @@ x_scroll_bar_set_handle (bar, start, end, rebuild)
 
   BLOCK_INPUT;
 
+  {
+    int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
+
+    /* Make sure the values are reasonable, and try to preserve
+       the distance between start and end.  */
+    {
+      int length = end - start;
+
+      if (start < 0)
+       start = 0;
+      else if (start > top_range)
+       start = top_range;
+      end = start + length;
+
+      if (end < start)
+       end = start;
+      else if (end > top_range && ! dragging)
+       end = top_range;
+    }
+  }
+
   /* Store the adjusted setting in the scroll bar.  */
   XSETINT (bar->start, start);
   XSETINT (bar->end, end);
 
-  SetScrollPos (w, SB_CTL, start, TRUE);
+  /* If being dragged, let scroll bar update itself.  */
+  if (!dragging)
+    {
+      if (pfnSetScrollInfo)
+       {
+         SCROLLINFO si;
+
+         si.cbSize = sizeof (si);
+         si.fMask = SIF_PAGE | SIF_POS;
+         si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE;
+         si.nPos = start;
+
+         pfnSetScrollInfo (w, SB_CTL, &si, TRUE);
+       }
+      else
+       SetScrollPos (w, SB_CTL, start, TRUE);
+    }
 
   UNBLOCK_INPUT;
 }
@@ -1935,15 +2060,43 @@ x_scroll_bar_move (bar, top, left, width, height)
      struct scroll_bar *bar;
      int top, left, width, height;
 {
-  Window w = SCROLL_BAR_WIN32_WINDOW (bar);
+  Window w = SCROLL_BAR_W32_WINDOW (bar);
   FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
 
+  /* If already correctly positioned, do nothing.  */
+  if ( XINT (bar->left) == left
+       && XINT (bar->top) == top
+       && XINT (bar->width) ==  width
+       && XINT (bar->height) == height )
+    {
+      /* Redraw after clear_frame. */
+      if (!my_show_window (f, w, SW_NORMAL))
+       InvalidateRect (w, NULL, FALSE);
+      return;
+    }
+
   BLOCK_INPUT;
 
+  /* Make sure scroll bar is "visible" before moving, to ensure the
+     area of the parent window now exposed will be refreshed.  */
+  my_show_window (f, w, SW_HIDE);
   MoveWindow (w, left, top, width, height, TRUE);
-  SetScrollRange (w, SB_CTL, 0, height, FALSE);
-  InvalidateRect (w, NULL, FALSE);
-  my_show_window (w, SW_NORMAL);
+  if (pfnSetScrollInfo)
+    {
+      SCROLLINFO si;
+
+      si.cbSize = sizeof (si);
+      si.fMask = SIF_RANGE;
+      si.nMin = 0;
+      si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (height)
+       + VERTICAL_SCROLL_BAR_MIN_HANDLE;
+
+      pfnSetScrollInfo (w, SB_CTL, &si, FALSE);
+    }
+  else
+    SetScrollRange (w, SB_CTL, 0, VERTICAL_SCROLL_BAR_TOP_RANGE (height), FALSE);
+  my_show_window (f, w, SW_NORMAL);
+//  InvalidateRect (w, NULL, FALSE);
 
   XSETINT (bar->left, left);
   XSETINT (bar->top, top);
@@ -1964,7 +2117,7 @@ x_scroll_bar_remove (bar)
   BLOCK_INPUT;
 
   /* Destroy the window.  */
-  my_destroy_window (f, SCROLL_BAR_WIN32_WINDOW (bar));
+  my_destroy_window (f, SCROLL_BAR_W32_WINDOW (bar));
 
   /* Disassociate this scroll bar from its window.  */
   XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
@@ -1977,7 +2130,7 @@ x_scroll_bar_remove (bar)
    characters, starting at POSITION.  If WINDOW has no scroll bar,
    create one.  */
 static void
-win32_set_vertical_scroll_bar (window, portion, whole, position)
+w32_set_vertical_scroll_bar (window, portion, whole, position)
      struct window *window;
      int portion, whole, position;
 {
@@ -1992,7 +2145,7 @@ win32_set_vertical_scroll_bar (window, portion, whole, position)
   int pixel_width
     = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
        ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
-       : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.win32->font)));
+       : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font)));
   int pixel_height = VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f, height);
 
   struct scroll_bar *bar;
@@ -2009,22 +2162,20 @@ win32_set_vertical_scroll_bar (window, portion, whole, position)
       x_scroll_bar_move (bar, pixel_top, pixel_left, pixel_width, pixel_height);
     }
 
-  /* Set the scroll bar's current state, unless we're currently being
-     dragged.  */
-  if (NILP (bar->dragging))
-    {
-      int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height);
+  /* Set the scroll bar's current state.  */
+  {
+    int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height);
 
-      if (whole == 0)
-       x_scroll_bar_set_handle (bar, 0, top_range, 0);
-      else
-       {
-         int start = (int) (((double) position * top_range) / whole);
-         int end = (int) (((double) (position + portion) * top_range) / whole);
+    if (whole == 0)
+      x_scroll_bar_set_handle (bar, 0, top_range, 0);
+    else
+      {
+       int start = (int) (((double) position * top_range) / whole);
+       int end = (int) (((double) (position + portion) * top_range) / whole);
 
-         x_scroll_bar_set_handle (bar, start, end, 0);
-       }
-    }
+       x_scroll_bar_set_handle (bar, start, end, 0);
+      }
+  }
 
   XSETVECTOR (window->vertical_scroll_bar, bar);
 }
@@ -2042,7 +2193,7 @@ win32_set_vertical_scroll_bar (window, portion, whole, position)
    to `*judge_scroll_bars_hook'.  A scroll bar may be spared if
    `*redeem_scroll_bar_hook' is applied to its window before the judgement.  */
 static void
-win32_condemn_scroll_bars (frame)
+w32_condemn_scroll_bars (frame)
      FRAME_PTR frame;
 {
   /* The condemned list should be empty at this point; if it's not,
@@ -2059,7 +2210,7 @@ win32_condemn_scroll_bars (frame)
 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
    Note that WINDOW isn't necessarily condemned at all.  */
 static void
-win32_redeem_scroll_bar (window)
+w32_redeem_scroll_bar (window)
      struct window *window;
 {
   struct scroll_bar *bar;
@@ -2106,7 +2257,7 @@ win32_redeem_scroll_bar (window)
 /* Remove all scroll bars on FRAME that haven't been saved since the
    last call to `*condemn_scroll_bars_hook'.  */
 static void
-win32_judge_scroll_bars (f)
+w32_judge_scroll_bars (f)
      FRAME_PTR f;
 {
   Lisp_Object bar, next;
@@ -2140,13 +2291,13 @@ win32_judge_scroll_bars (f)
 static int
 x_scroll_bar_handle_click (bar, msg, emacs_event)
      struct scroll_bar *bar;
-     Win32Msg *msg;
+     W32Msg *msg;
      struct input_event *emacs_event;
 {
   if (! GC_WINDOWP (bar->window))
     abort ();
 
-  emacs_event->kind = win32_scroll_bar_click;
+  emacs_event->kind = w32_scroll_bar_click;
   emacs_event->code = 0;
   /* not really meaningful to distinguish up/down */
   emacs_event->modifiers = msg->dwModifiers;
@@ -2154,19 +2305,27 @@ x_scroll_bar_handle_click (bar, msg, emacs_event)
   emacs_event->timestamp = msg->msg.time;
 
   {
-    int internal_height
-      = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
-    int top_range
-      = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
-    int y = GetScrollPos ((HWND) msg->msg.lParam, SB_CTL);
+    int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
+    int y;
+    int dragging = !NILP (bar->dragging);
+
+    if (pfnGetScrollInfo)
+      {
+       SCROLLINFO si;
+
+       si.cbSize = sizeof (si);
+       si.fMask = SIF_POS;
+
+       pfnGetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
+       y = si.nPos;
+      }
+    else
+      y = GetScrollPos ((HWND) msg->msg.lParam, SB_CTL);
+
+    bar->dragging = Qnil;
 
     switch (LOWORD (msg->msg.wParam))
       {
-      case SB_THUMBTRACK:
-       emacs_event->part = scroll_bar_handle;
-       if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)) <= 0xffff)
-           y = HIWORD (msg->msg.wParam);
-       break;
       case SB_LINEDOWN:
        emacs_event->part = scroll_bar_down_arrow;
        break;
@@ -2187,12 +2346,76 @@ x_scroll_bar_handle_click (bar, msg, emacs_event)
        emacs_event->part = scroll_bar_handle;
        y = top_range;
        break;
+      case SB_THUMBTRACK:
       case SB_THUMBPOSITION:
+       if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)) <= 0xffff)
+           y = HIWORD (msg->msg.wParam);
+       bar->dragging = Qt;
        emacs_event->part = scroll_bar_handle;
+
+       /* "Silently" update current position.  */
+       if (pfnSetScrollInfo)
+         {
+           SCROLLINFO si;
+
+           si.cbSize = sizeof (si);
+           si.fMask = SIF_POS;
+
+#if 0
+           /* Shrink handle if necessary to allow full range for position.  */
+           {
+             int start = XINT (bar->start);
+             int end = XINT (bar->end);
+             int len = end - start;
+
+             /* If new end is nearly hitting bottom, we must shrink
+                handle.  How much we shrink it depends on the relative
+                sizes of len and top_range.  */
+             if (y + len > top_range - 2)
+               {
+                 len -= min (top_range / 10, (len / 3) + 2);
+                 if (len < 0)
+                   len = 0;
+               }
+             si.nPage = len + VERTICAL_SCROLL_BAR_MIN_HANDLE;
+             si.fMask |= SIF_PAGE;
+           }
+#endif
+           si.nPos = y;
+           /* Remember apparent position (we actually lag behind the real
+              position, so don't set that directly.  */
+           last_scroll_bar_drag_pos = y;
+
+           pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE);
+         }
+       else
+         SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, FALSE);
        break;
       case SB_ENDSCROLL:
+       /* If this is the end of a drag sequence, then reset the scroll
+          handle size to normal and do a final redraw.  Otherwise do
+          nothing.  */
+       if (dragging)
+         {
+           if (pfnSetScrollInfo)
+             {
+               SCROLLINFO si;
+               int start = XINT (bar->start);
+               int end = XINT (bar->end);
+
+               si.cbSize = sizeof (si);
+               si.fMask = SIF_PAGE | SIF_POS;
+               si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE;
+               si.nPos = last_scroll_bar_drag_pos;
+
+               pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE);
+             }
+           else
+             SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, TRUE);
+         }
+       /* fall through */
       default:
-       SetScrollPos (SCROLL_BAR_WIN32_WINDOW (bar), SB_CTL, y, TRUE);
+       emacs_event->kind = no_event;
        return FALSE;
       }
 
@@ -2214,16 +2437,29 @@ x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
      unsigned long *time;
 {
   struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
-  Window w = SCROLL_BAR_WIN32_WINDOW (bar);
+  Window w = SCROLL_BAR_W32_WINDOW (bar);
   FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
   int pos;
+  int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
 
   BLOCK_INPUT;
 
   *fp = f;
   *bar_window = bar->window;
 
-  pos = GetScrollPos (w, SB_CTL);
+  if (pfnGetScrollInfo)
+    {
+      SCROLLINFO si;
+
+      si.cbSize = sizeof (si);
+      si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
+
+      pfnGetScrollInfo (w, SB_CTL, &si);
+      pos = si.nPos;
+      top_range = si.nMax - si.nPage + 1;
+    }
+  else
+    pos = GetScrollPos (w, SB_CTL);
 
   switch (LOWORD (last_mouse_scroll_bar_pos))
   {
@@ -2243,7 +2479,7 @@ x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
   }
 
   XSETINT(*x, pos);
-  XSETINT(*y, VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)));
+  XSETINT(*y, top_range);
 
   f->mouse_moved = 0;
   last_mouse_scroll_bar = Qnil;
@@ -2266,15 +2502,20 @@ x_scroll_bar_clear (f)
   for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
        bar = XSCROLL_BAR (bar)->next)
     {
-      HWND window = SCROLL_BAR_WIN32_WINDOW (XSCROLL_BAR (bar));
+      HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
       HDC hdc = GetDC (window);
       RECT rect;
 
-      my_show_window (window, SW_HIDE);
+      /* Hide scroll bar until ready to repaint.  x_scroll_bar_move
+         arranges to refresh the scroll bar if hidden.  */
+      my_show_window (f, window, SW_HIDE);
+
       GetClientRect (window, &rect);
       select_palette (f, hdc);
-      win32_clear_rect (f, hdc, &rect);
+      w32_clear_rect (f, hdc, &rect);
       deselect_palette (f, hdc);
+
+      ReleaseDC (window, hdc);
     }
 }
 
@@ -2287,13 +2528,13 @@ show_scroll_bars (f, how)
   for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
        bar = XSCROLL_BAR (bar)->next)
     {
-      HWND window = SCROLL_BAR_WIN32_WINDOW (XSCROLL_BAR (bar));
-      my_show_window (window, how);
+      HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
+      my_show_window (f, window, how);
     }
 }
 
 \f
-/* The main Win32 event-reading loop - w32_read_socket.  */
+/* The main W32 event-reading loop - w32_read_socket.  */
 
 /* Timestamp of enter window event.  This is only used by w32_read_socket,
    but we have to put it out here, since static variables within functions
@@ -2305,14 +2546,14 @@ static Time enter_timestamp;
 int temp_index;
 short temp_buffer[100];
 
-extern int key_event (KEY_EVENT_RECORD *, struct input_event *);
+extern int key_event (KEY_EVENT_RECORD *, struct input_event *, int *isdead);
 
-/* Map a Win32 WM_CHAR message into a KEY_EVENT_RECORD so that
+/* Map a W32 WM_CHAR message into a KEY_EVENT_RECORD so that
    we can use the same routines to handle input in both console
    and window modes.  */
 
 static void
-convert_to_key_event (Win32Msg *msgp, KEY_EVENT_RECORD *eventp)
+convert_to_key_event (W32Msg *msgp, KEY_EVENT_RECORD *eventp)
 {
   eventp->bKeyDown = TRUE;
   eventp->wRepeatCount = 1;
@@ -2329,14 +2570,14 @@ is_dead_key (int wparam)
 {
   unsigned int code = MapVirtualKey (wparam, 2);
 
-  /* Win95 returns 0x8000, NT returns 0x80000000.  */
+  /* Windows 95 returns 0x8000, NT returns 0x80000000.  */
   if ((code & 0x8000) || (code & 0x80000000))
     return 1;
   else
     return 0;
 }
 
-/* Read events coming from the Win32 shell.
+/* Read events coming from the W32 shell.
    This routine is called by the SIGIO handler.
    We return as soon as there are no more events to be read.
 
@@ -2345,35 +2586,30 @@ is_dead_key (int wparam)
    We return the number of characters stored into the buffer,
    thus pretending to be `read'.
 
-   WAITP is nonzero if we should block until input arrives.
    EXPECTED is nonzero if the caller knows input is available.  
 
    Some of these messages are reposted back to the message queue since the
-   system calls the winproc directly in a context where we cannot return the
-   data nor can we guarantee the state we are in.  So if we dispatch  them
+   system calls the windows proc directly in a context where we cannot return 
+   the data nor can we guarantee the state we are in.  So if we dispatch  them
    we will get into an infinite loop.  To prevent this from ever happening we
    will set a variable to indicate we are in the read_socket call and indicate
-   which message we are processing since the winproc gets called recursively with different
-   messages by the system.
+   which message we are processing since the windows proc gets called 
+   recursively with different messages by the system.
 */
 
 int
-w32_read_socket (sd, bufp, numchars, waitp, expected)
+w32_read_socket (sd, bufp, numchars, expected)
      register int sd;
      register struct input_event *bufp;
      register int numchars;
-     int waitp;
      int expected;
 {
   int count = 0;
-  int nbytes = 0;
-  int items_pending;            /* How many items are in the X queue. */
-  Win32Msg msg;
+  int check_visibility = 0;
+  W32Msg msg;
   struct frame *f;
-  int event_found = 0;
-  int prefix;
   Lisp_Object part;
-  struct win32_display_info *dpyinfo = &one_win32_display_info;
+  struct w32_display_info *dpyinfo = &one_w32_display_info;
 
   if (interrupt_input_blocked)
     {
@@ -2394,44 +2630,49 @@ w32_read_socket (sd, bufp, numchars, waitp, expected)
     {
       switch (msg.msg.message)
        {
-       case WM_ERASEBKGND:
-         f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
-         if (f)
-           {
-             win32_clear_rect (f, NULL, &msg.rect);
-           }
-         break;
        case WM_PAINT:
-         {
            f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
 
            if (f) 
              {
-               if (f->async_visible == 0)
+             if (f->async_visible != 1)
                  {
+                 /* Definitely not obscured, so mark as visible.  */
                    f->async_visible = 1;
                    f->async_iconified = 0;
                    SET_FRAME_GARBAGED (f);
+                 DebPrint (("frame %04x (%s) reexposed\n", f,
+                            XSTRING (f->name)->data));
+
+                   /* WM_PAINT serves as MapNotify as well, so report
+                       visibility changes properly.  */
+                   if (f->iconified)
+                     {
+                       bufp->kind = deiconify_event;
+                       XSETFRAME (bufp->frame_or_window, f);
+                       bufp++;
+                       count++;
+                       numchars--;
+                     }
+                   else if (! NILP(Vframe_list)
+                            && ! NILP (XCONS (Vframe_list)->cdr))
+                     /* Force a redisplay sooner or later to update the
+                        frame titles in case this is the second frame.  */
+                     record_asynch_buffer_change ();
                  }
                else
                  {
+                   /* Erase background again for safety.  */
+                   w32_clear_rect (f, NULL, &msg.rect);
                    dumprectangle (f,
                                   msg.rect.left,
                                   msg.rect.top,
-                                  msg.rect.right-msg.rect.left+1,
-                                  msg.rect.bottom-msg.rect.top+1);
-                     
+                                  msg.rect.right - msg.rect.left,
+                                  msg.rect.bottom - msg.rect.top);
                  }
              }
-         }
-         
-         break;
-       case WM_PALETTECHANGED:
-         f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
-         if (f)
-           /* Realize palette - will force update if needed. */
-           release_frame_dc (f, get_frame_dc (f));
          break;
+
        case WM_KEYDOWN:
        case WM_SYSKEYDOWN:
          f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
@@ -2443,7 +2684,8 @@ w32_read_socket (sd, bufp, numchars, waitp, expected)
              temp_buffer[temp_index++] = msg.msg.wParam;
              bufp->kind = non_ascii_keystroke;
              bufp->code = msg.msg.wParam;
-             bufp->modifiers = win32_kbd_mods_to_emacs (msg.dwModifiers);
+             bufp->modifiers = w32_kbd_mods_to_emacs (msg.dwModifiers,
+                                                         msg.msg.wParam);
              XSETFRAME (bufp->frame_or_window, f);
              bufp->timestamp = msg.msg.time;
              bufp++;
@@ -2451,6 +2693,7 @@ w32_read_socket (sd, bufp, numchars, waitp, expected)
              count++;
            }
          break;
+
        case WM_SYSCHAR:
        case WM_CHAR:
          f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
@@ -2460,13 +2703,14 @@ w32_read_socket (sd, bufp, numchars, waitp, expected)
              if (numchars > 1) 
                {
                  int add;
+                 int isdead = 0;
                  KEY_EVENT_RECORD key, *keyp = &key;
 
                  if (temp_index == sizeof temp_buffer / sizeof (short))
                    temp_index = 0;
                  
                  convert_to_key_event (&msg, keyp);
-                 add = key_event (keyp, bufp);
+                 add = key_event (keyp, bufp, &isdead);
                  XSETFRAME (bufp->frame_or_window, f);
                  if (add == -1)
                    {
@@ -2480,12 +2724,7 @@ w32_read_socket (sd, bufp, numchars, waitp, expected)
                      add = 1;
                    }
 
-                 /* Throw dead keys away.  However, be sure not to
-                    throw away the dead key if it was produced using
-                    AltGr and there is a valid AltGr scan code for
-                    this key.  */
-                 if (is_dead_key (msg.msg.wParam) 
-                     && !((VkKeyScan (bufp->code) & 0xff00) == 0x600))
+                 if (isdead)
                    break;
 
                  bufp += add;
@@ -2498,6 +2737,7 @@ w32_read_socket (sd, bufp, numchars, waitp, expected)
                }
            }
          break;
+
        case WM_MOUSEMOVE:
          if (dpyinfo->grabbed && last_mouse_frame
              && FRAME_LIVE_P (last_mouse_frame))
@@ -2508,9 +2748,10 @@ w32_read_socket (sd, bufp, numchars, waitp, expected)
          if (f)
            note_mouse_movement (f, &msg.msg);
          else
-           clear_mouse_face (FRAME_WIN32_DISPLAY_INFO (f));
+           clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
          
          break;
+
        case WM_LBUTTONDOWN:
        case WM_LBUTTONUP:
        case WM_MBUTTONDOWN:
@@ -2529,7 +2770,7 @@ w32_read_socket (sd, bufp, numchars, waitp, expected)
            
            if (f)
              {
-               if ((!dpyinfo->win32_focus_frame || f == dpyinfo->win32_focus_frame) 
+               if ((!dpyinfo->w32_focus_frame || f == dpyinfo->w32_focus_frame) 
                    && (numchars >= 1))
                  {
                    construct_mouse_click (bufp, &msg, f);
@@ -2550,12 +2791,34 @@ w32_read_socket (sd, bufp, numchars, waitp, expected)
                dpyinfo->grabbed |= (1 << button);
                last_mouse_frame = f;
              }
+           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);
+
+          if (f)
+            {
+              if ((!dpyinfo->w32_focus_frame 
+                   || f == dpyinfo->w32_focus_frame)
+                  && (numchars >= 1))
+                {
+                  construct_mouse_wheel (bufp, &msg, f);
+                  bufp++;
+                  count++;
+                  numchars--;
+                }
+            }
          break;
+
        case WM_VSCROLL:
          {
-           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)
              {
@@ -2566,19 +2829,48 @@ w32_read_socket (sd, bufp, numchars, waitp, expected)
                    numchars--;
                  }
              }
+           break;
          }
          
+       case WM_WINDOWPOSCHANGED:
+       case WM_ACTIVATE:
+       case WM_ACTIVATEAPP:
+         check_visibility = 1;
          break;
+
        case WM_MOVE:
          f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
          
          if (f && !f->async_iconified)
            {
-             f->output_data.win32->left_pos = LOWORD (msg.msg.lParam);
-             f->output_data.win32->top_pos = HIWORD (msg.msg.lParam);
+             int x, y;
+
+             x_real_positions (f, &x, &y);
+             f->output_data.w32->left_pos = x;
+             f->output_data.w32->top_pos = y;
            }
-         
+
+         check_visibility = 1;
          break;
+
+       case WM_SHOWWINDOW:
+         /* If window has been obscured or exposed by another window
+            being maximised or minimised/restored, then recheck
+            visibility of all frames.  Direct changes to our own
+            windows get handled by WM_SIZE.  */
+#if 0
+         if (msg.msg.lParam != 0)
+           check_visibility = 1;
+         else
+           {
+             f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
+             f->async_visible = msg.msg.wParam;
+           }
+#endif
+
+         check_visibility = 1;
+         break;
+
        case WM_SIZE:
          f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
          
@@ -2592,70 +2884,41 @@ w32_read_socket (sd, bufp, numchars, waitp, expected)
              
              GetClientRect(msg.msg.hwnd, &rect);
              
-             height = rect.bottom - rect.top + 1;
-             width = rect.right - rect.left + 1;
+             height = rect.bottom - rect.top;
+             width = rect.right - rect.left;
              
              rows = PIXEL_TO_CHAR_HEIGHT (f, height);
              columns = PIXEL_TO_CHAR_WIDTH (f, width);
              
+             /* TODO: Clip size to the screen dimensions.  */
+             
              /* Even if the number of character rows and columns has
                 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.win32->pixel_width
-                 || height != f->output_data.win32->pixel_height)
+                 || width != f->output_data.w32->pixel_width
+                 || height != f->output_data.w32->pixel_height)
                {
                  /* I had set this to 0, 0 - I am not sure why?? */
                  
                  change_frame_size (f, rows, columns, 0, 1);
                  SET_FRAME_GARBAGED (f);
                  
-                 f->output_data.win32->pixel_width = width;
-                 f->output_data.win32->pixel_height = height;
-                 f->output_data.win32->win_gravity = NorthWestGravity;
+                 f->output_data.w32->pixel_width = width;
+                 f->output_data.w32->pixel_height = height;
+                 f->output_data.w32->win_gravity = NorthWestGravity;
                }
            }
-         
-         break;
-       case WM_SETFOCUS:
-       case WM_KILLFOCUS:
-         f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
-         
-         if (msg.msg.message == WM_SETFOCUS)
-           {
-             x_new_focus_frame (dpyinfo, f);
-           }
-         else if (f == dpyinfo->win32_focus_frame)
-           x_new_focus_frame (dpyinfo, 0);
-         
-         break;
-       case WM_SYSCOMMAND:
-         switch (msg.msg.wParam & 0xfff0)  /* Lower 4 bits used by Windows. */
+
+         /* Inform lisp of whether frame has been iconified etc. */
+         if (f)
            {
-           case SC_CLOSE:
-             f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
-             
-             if (f)
+             switch (msg.msg.wParam)
                {
-                 if (numchars == 0)
-                   abort ();
-                 
-                 bufp->kind = delete_window_event;
-                 XSETFRAME (bufp->frame_or_window, f);
-                 bufp++;
-                 count++;
-                 numchars--;
-               }
-             
-             break;
-           case SC_MINIMIZE:
-             f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
-             
-             if (f)
-               {
-                 f->async_visible = 1;
+               case SIZE_MINIMIZED:
+                 f->async_visible = 0;
                  f->async_iconified = 1;
                  
                  bufp->kind = iconify_event;
@@ -2663,15 +2926,10 @@ w32_read_socket (sd, bufp, numchars, waitp, expected)
                  bufp++;
                  count++;
                  numchars--;
-               }
-             
-             break;
-           case SC_MAXIMIZE:
-           case SC_RESTORE:
-             f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
-             
-             if (f)
-               {
+                 break;
+
+               case SIZE_MAXIMIZED:
+               case SIZE_RESTORED:
                  f->async_visible = 1;
                  f->async_iconified = 0;
                  
@@ -2692,12 +2950,29 @@ w32_read_socket (sd, bufp, numchars, waitp, expected)
                       to update the frame titles
                       in case this is the second frame.  */
                    record_asynch_buffer_change ();
+                 break;
                }
-             
-             break;
            }
+
+         check_visibility = 1;
+         break;
+
+       case WM_SETFOCUS:
+       case WM_KILLFOCUS:
+         f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
          
+         if (msg.msg.message == WM_SETFOCUS)
+           {
+             x_new_focus_frame (dpyinfo, f);
+           }
+         else if (f == dpyinfo->w32_focus_frame)
+           {
+             x_new_focus_frame (dpyinfo, 0);
+           }
+
+         check_visibility = 1;
          break;
+
        case WM_CLOSE:
          f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
          
@@ -2712,11 +2987,28 @@ w32_read_socket (sd, bufp, numchars, waitp, expected)
              count++;
              numchars--;
            }
+         break;
+
+       case WM_INITMENU:
+         f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
+         
+         if (f)
+           {
+             if (numchars == 0)
+               abort ();
          
+             bufp->kind = menu_bar_activate_event;
+             XSETFRAME (bufp->frame_or_window, f);
+             bufp++;
+             count++;
+             numchars--;
+           }
          break;
+
        case WM_COMMAND:
          f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
          
+#if 1
          if (f)
            {
              if (msg.msg.lParam == 0) 
@@ -2753,6 +3045,24 @@ w32_read_socket (sd, bufp, numchars, waitp, expected)
                  /* Came from popup menu */
                }
            }
+#endif
+
+         check_visibility = 1;
+         break;
+
+       case WM_DISPLAYCHANGE:
+         f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
+
+         if (f) 
+           {
+             dpyinfo->width = (short) LOWORD (msg.msg.lParam);
+             dpyinfo->height = (short) HIWORD (msg.msg.lParam);
+             dpyinfo->n_cbits = msg.msg.wParam;
+             DebPrint (("display change: %d %d\n", dpyinfo->width,
+                        dpyinfo->height));
+           }
+         
+         check_visibility = 1;
          break;
        }
     }
@@ -2766,6 +3076,62 @@ w32_read_socket (sd, bufp, numchars, waitp, expected)
       pending_autoraise_frame = 0;
     }
 
+  /* Check which frames are still visisble, if we have enqueued any user
+     events or been notified of events that may affect visibility.  We
+     do this here because there doesn't seem to be any direct
+     notification from Windows that the visibility of a window has
+     changed (at least, not in all cases).  */
+  if (count > 0 || check_visibility)
+    {
+      Lisp_Object tail, frame;
+
+      FOR_EACH_FRAME (tail, frame)
+       {
+         FRAME_PTR f = XFRAME (frame);
+         /* 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 = get_frame_dc (f);
+             GetClipBox (hdc, &clipbox);
+             release_frame_dc (f, hdc);
+
+             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 %04x (%s) obscured\n", f,
+                                XSTRING (f->name)->data));
+                   }
+               }
+             else
+               {
+                 /* Frame is not obscured, so mark it as such.  */
+                 f->async_visible = 1;
+
+                 if (FRAME_OBSCURED_P (f))
+                   {
+                     SET_FRAME_GARBAGED (f);
+                     DebPrint (("frame %04x (%s) reexposed\n", f,
+                                XSTRING (f->name)->data));
+
+                     /* Force a redisplay sooner or later.  */
+                     record_asynch_buffer_change ();
+                   }
+               }
+           }
+       }
+    }
+
   UNBLOCK_INPUT;
   return count;
 }
@@ -2785,12 +3151,12 @@ x_draw_box (f)
   
   hdc = get_frame_dc (f);
   
-  hb = CreateSolidBrush (f->output_data.win32->cursor_pixel);
+  hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
   
   rect.left = CHAR_TO_PIXEL_COL (f, curs_x);
   rect.top  = CHAR_TO_PIXEL_ROW (f, curs_y);
-  rect.right = rect.left + FONT_WIDTH (f->output_data.win32->font);
-  rect.bottom = rect.top + f->output_data.win32->line_height;
+  rect.right = rect.left + FONT_WIDTH (f->output_data.w32->font);
+  rect.bottom = rect.top + f->output_data.w32->line_height;
 
   FrameRect (hdc, &rect, hb);
   DeleteObject (hb);
@@ -2848,20 +3214,12 @@ x_display_bar_cursor (f, on)
   if (! on && f->phys_cursor_x < 0)
     return;
 
-  /* If we're not updating, then we want to use the current frame's
-     cursor position, not our local idea of where the cursor ought to be.  */
-  if (f != updating_frame)
-    {
-      curs_x = FRAME_CURSOR_X (f);
-      curs_y = FRAME_CURSOR_Y (f);
-    }
-
   /* If there is anything wrong with the current cursor state, remove it.  */
   if (f->phys_cursor_x >= 0
       && (!on
          || f->phys_cursor_x != curs_x
          || f->phys_cursor_y != curs_y
-         || f->output_data.win32->current_cursor != bar_cursor))
+         || f->output_data.w32->current_cursor != bar_cursor))
     {
       /* Erase the cursor by redrawing the character underneath it.  */
       x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
@@ -2873,23 +3231,23 @@ x_display_bar_cursor (f, on)
   /* If we now need a cursor in the new place or in the new form, do it so.  */
   if (on
       && (f->phys_cursor_x < 0
-         || (f->output_data.win32->current_cursor != bar_cursor)))
+         || (f->output_data.w32->current_cursor != bar_cursor)))
     {
       f->phys_cursor_glyph
        = ((current_glyphs->enable[curs_y]
            && curs_x < current_glyphs->used[curs_y])
           ? current_glyphs->glyphs[curs_y][curs_x]
           : SPACEGLYPH);
-      win32_fill_area (f, NULL, f->output_data.win32->cursor_pixel,
+      w32_fill_area (f, NULL, f->output_data.w32->cursor_pixel,
                       CHAR_TO_PIXEL_COL (f, curs_x),
                       CHAR_TO_PIXEL_ROW (f, curs_y),
-                      max (f->output_data.win32->cursor_width, 1),
-                      f->output_data.win32->line_height);
+                      max (f->output_data.w32->cursor_width, 1),
+                      f->output_data.w32->line_height);
 
       f->phys_cursor_x = curs_x;
       f->phys_cursor_y = curs_y;
 
-      f->output_data.win32->current_cursor = bar_cursor;
+      f->output_data.w32->current_cursor = bar_cursor;
     }
 }
 
@@ -2915,14 +3273,6 @@ x_display_box_cursor (f, on)
   if (!on && f->phys_cursor_x < 0)
     return;
 
-  /* If we're not updating, then we want to use the current frame's
-     cursor position, not our local idea of where the cursor ought to be.  */
-  if (f != updating_frame)
-    {
-      curs_x = FRAME_CURSOR_X (f);
-      curs_y = FRAME_CURSOR_Y (f);
-    }
-
   /* If cursor is currently being shown and we don't want it to be
      or it is in the wrong place,
      or we want a hollow box and it's not so, (pout!)
@@ -2931,23 +3281,21 @@ x_display_box_cursor (f, on)
       && (!on
          || f->phys_cursor_x != curs_x
          || f->phys_cursor_y != curs_y
-         || (f->output_data.win32->current_cursor != hollow_box_cursor
-             && (f != FRAME_WIN32_DISPLAY_INFO (f)->win32_highlight_frame))))
+         || (f->output_data.w32->current_cursor != hollow_box_cursor
+             && (f != FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame))))
     {
       int mouse_face_here = 0;
       struct frame_glyphs *active_glyphs = FRAME_CURRENT_GLYPHS (f);
 
       /* If the cursor is in the mouse face area, redisplay that when
         we clear the cursor.  */
-      if (f == FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_mouse_frame
-         &&
-         (f->phys_cursor_y > FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_row
-          || (f->phys_cursor_y == FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_row
-              && f->phys_cursor_x >= FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_beg_col))
-         &&
-         (f->phys_cursor_y < FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_row
-          || (f->phys_cursor_y == FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_row
-              && f->phys_cursor_x < FRAME_WIN32_DISPLAY_INFO (f)->mouse_face_end_col))
+      if (f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame
+         && (f->phys_cursor_y > FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row
+             || (f->phys_cursor_y == FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row
+                 && f->phys_cursor_x >= FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col))
+         && (f->phys_cursor_y < FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row
+             || (f->phys_cursor_y == FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row
+                 && f->phys_cursor_x < FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col))
          /* Don't redraw the cursor's spot in mouse face
             if it is at the end of a line (on a newline).
             The cursor appears there, but mouse highlighting does not.  */
@@ -2956,12 +3304,12 @@ x_display_box_cursor (f, on)
 
       /* If the font is not as tall as a whole line,
         we must explicitly clear the line's whole height.  */
-      if (FONT_HEIGHT (f->output_data.win32->font) != f->output_data.win32->line_height)
-       win32_clear_area (f, NULL,
+      if (FONT_HEIGHT (f->output_data.w32->font) != f->output_data.w32->line_height)
+       w32_clear_area (f, NULL,
                          CHAR_TO_PIXEL_COL (f, f->phys_cursor_x),
                          CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y),
-                         FONT_WIDTH (f->output_data.win32->font),
-                         f->output_data.win32->line_height);
+                         FONT_WIDTH (f->output_data.w32->font),
+                         f->output_data.w32->line_height);
       /* Erase the cursor by redrawing the character underneath it.  */
       x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
                           f->phys_cursor_glyph,
@@ -2976,24 +3324,24 @@ x_display_box_cursor (f, on)
      write it in the right place.  */
   if (on
       && (f->phys_cursor_x < 0
-         || (f->output_data.win32->current_cursor != filled_box_cursor
-             && f == FRAME_WIN32_DISPLAY_INFO (f)->win32_highlight_frame)))
+         || (f->output_data.w32->current_cursor != filled_box_cursor
+             && f == FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame)))
     {
       f->phys_cursor_glyph
        = ((current_glyphs->enable[curs_y]
            && curs_x < current_glyphs->used[curs_y])
           ? current_glyphs->glyphs[curs_y][curs_x]
           : SPACEGLYPH);
-      if (f != FRAME_WIN32_DISPLAY_INFO (f)->win32_highlight_frame)
+      if (f != FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame)
        {
          x_draw_box (f);
-         f->output_data.win32->current_cursor = hollow_box_cursor;
+         f->output_data.w32->current_cursor = hollow_box_cursor;
        }
       else
        {
          x_draw_single_glyph (f, curs_y, curs_x,
                               f->phys_cursor_glyph, 2);
-         f->output_data.win32->current_cursor = filled_box_cursor;
+         f->output_data.w32->current_cursor = filled_box_cursor;
        }
 
       f->phys_cursor_x = curs_x;
@@ -3001,12 +3349,26 @@ x_display_box_cursor (f, on)
     }
 }
 
+/* Display the cursor on frame F, or clear it, according to ON.
+   Use the position specified by curs_x and curs_y
+   if we are doing an update of frame F now.
+   Otherwise use the position in the FRAME_CURSOR_X and FRAME_CURSOR_Y fields
+   of F.  */
+
 x_display_cursor (f, on)
      struct frame *f;
      int on;
 {
   BLOCK_INPUT;
 
+  /* If we're not updating, then we want to use the current frame's
+     cursor position, not our local idea of where the cursor ought to be.  */
+  if (f != updating_frame)
+    {
+      curs_x = FRAME_CURSOR_X (f);
+      curs_y = FRAME_CURSOR_Y (f);
+    }
+
   if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
     x_display_box_cursor (f, on);
   else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
@@ -3039,8 +3401,8 @@ x_new_font (f, fontname)
   {
       LOGFONT lf;
 
-      if (!x_to_win32_font(fontname, &lf)
-         || !win32_to_x_font(&lf, new_font_name, 100))
+      if (!x_to_w32_font(fontname, &lf)
+         || !w32_to_x_font(&lf, new_font_name, 100))
       {
          return Qnil;
       }
@@ -3052,25 +3414,25 @@ x_new_font (f, fontname)
   {
       int i;
 
-      for (i = 0; i < FRAME_WIN32_DISPLAY_INFO (f)->n_fonts; i++)
-         if (!strcmp (FRAME_WIN32_DISPLAY_INFO (f)->font_table[i].name, new_font_name))
+      for (i = 0; i < FRAME_W32_DISPLAY_INFO (f)->n_fonts; i++)
+         if (!strcmp (FRAME_W32_DISPLAY_INFO (f)->font_table[i].name, new_font_name))
          {
              already_loaded = i;
-             fontname = FRAME_WIN32_DISPLAY_INFO (f)->font_table[i].name;
+             fontname = FRAME_W32_DISPLAY_INFO (f)->font_table[i].name;
              break;
          }
   }
 
   /* If we have, just return it from the table.  */
   if (already_loaded >= 0)
-    f->output_data.win32->font = FRAME_WIN32_DISPLAY_INFO (f)->font_table[already_loaded].font;
+    f->output_data.w32->font = FRAME_W32_DISPLAY_INFO (f)->font_table[already_loaded].font;
   /* Otherwise, load the font and add it to the table.  */
   else
     {
       XFontStruct *font;
       int n_fonts;
 
-      font = win32_load_font(FRAME_WIN32_DISPLAY_INFO (f), fontname);
+      font = w32_load_font(FRAME_W32_DISPLAY_INFO (f), fontname);
 
       if (! font)
        {
@@ -3078,42 +3440,42 @@ x_new_font (f, fontname)
        }
 
       /* Do we need to create the table?  */
-      if (FRAME_WIN32_DISPLAY_INFO (f)->font_table_size == 0)
+      if (FRAME_W32_DISPLAY_INFO (f)->font_table_size == 0)
        {
-         FRAME_WIN32_DISPLAY_INFO (f)->font_table_size = 16;
-         FRAME_WIN32_DISPLAY_INFO (f)->font_table
-           = (struct font_info *) xmalloc (FRAME_WIN32_DISPLAY_INFO (f)->font_table_size
+         FRAME_W32_DISPLAY_INFO (f)->font_table_size = 16;
+         FRAME_W32_DISPLAY_INFO (f)->font_table
+           = (struct font_info *) xmalloc (FRAME_W32_DISPLAY_INFO (f)->font_table_size
                                            * sizeof (struct font_info));
        }
       /* Do we need to grow the table?  */
-      else if (FRAME_WIN32_DISPLAY_INFO (f)->n_fonts
-              >= FRAME_WIN32_DISPLAY_INFO (f)->font_table_size)
+      else if (FRAME_W32_DISPLAY_INFO (f)->n_fonts
+              >= FRAME_W32_DISPLAY_INFO (f)->font_table_size)
        {
-         FRAME_WIN32_DISPLAY_INFO (f)->font_table_size *= 2;
-         FRAME_WIN32_DISPLAY_INFO (f)->font_table
-           = (struct font_info *) xrealloc (FRAME_WIN32_DISPLAY_INFO (f)->font_table,
-                                            (FRAME_WIN32_DISPLAY_INFO (f)->font_table_size
+         FRAME_W32_DISPLAY_INFO (f)->font_table_size *= 2;
+         FRAME_W32_DISPLAY_INFO (f)->font_table
+           = (struct font_info *) xrealloc (FRAME_W32_DISPLAY_INFO (f)->font_table,
+                                            (FRAME_W32_DISPLAY_INFO (f)->font_table_size
                                              * sizeof (struct font_info)));
        }
 
-      n_fonts = FRAME_WIN32_DISPLAY_INFO (f)->n_fonts;
-      FRAME_WIN32_DISPLAY_INFO (f)->font_table[n_fonts].name = (char *) xmalloc (strlen (fontname) + 1);
-      bcopy (fontname, FRAME_WIN32_DISPLAY_INFO (f)->font_table[n_fonts].name, strlen (fontname) + 1);
-      f->output_data.win32->font = FRAME_WIN32_DISPLAY_INFO (f)->font_table[n_fonts].font = font;
-      FRAME_WIN32_DISPLAY_INFO (f)->n_fonts++;
+      n_fonts = FRAME_W32_DISPLAY_INFO (f)->n_fonts;
+      FRAME_W32_DISPLAY_INFO (f)->font_table[n_fonts].name = (char *) xmalloc (strlen (fontname) + 1);
+      bcopy (fontname, FRAME_W32_DISPLAY_INFO (f)->font_table[n_fonts].name, strlen (fontname) + 1);
+      f->output_data.w32->font = FRAME_W32_DISPLAY_INFO (f)->font_table[n_fonts].font = font;
+      FRAME_W32_DISPLAY_INFO (f)->n_fonts++;
     }
 
   /* Compute the scroll bar width in character columns.  */
   if (f->scroll_bar_pixel_width > 0)
     {
-      int wid = FONT_WIDTH (f->output_data.win32->font);
+      int wid = FONT_WIDTH (f->output_data.w32->font);
       f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
     }
   else
     f->scroll_bar_cols = 2;
 
   /* Now make the frame display the given font.  */
-  if (FRAME_WIN32_WINDOW (f) != 0)
+  if (FRAME_W32_WINDOW (f) != 0)
     {
       frame_update_line_height (f);
       x_set_window_size (f, 0, f->width, f->height);
@@ -3121,7 +3483,7 @@ x_new_font (f, fontname)
   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.win32->line_height = FONT_HEIGHT (f->output_data.win32->font);
+    f->output_data.w32->line_height = FONT_HEIGHT (f->output_data.w32->font);
 
   {
     Lisp_Object lispy_name;
@@ -3132,22 +3494,25 @@ x_new_font (f, fontname)
   }
 }
 \f
+/* Calculate the absolute position in frame F
+   from its current recorded position values and gravity.  */
+
 x_calc_absolute_position (f)
      struct frame *f;
 {
   Window win, child;
   POINT pt;
-  int flags = f->output_data.win32->size_hint_flags;
+  int flags = f->output_data.w32->size_hint_flags;
 
   pt.x = pt.y = 0;
 
   /* Find the position of the outside upper-left corner of
      the inner window, with respect to the outer window.  */
-  if (f->output_data.win32->parent_desc != FRAME_WIN32_DISPLAY_INFO (f)->root_window)
+  if (f->output_data.w32->parent_desc != FRAME_W32_DISPLAY_INFO (f)->root_window)
     {
       BLOCK_INPUT;
-      MapWindowPoints (FRAME_WIN32_WINDOW (f),
-                      f->output_data.win32->parent_desc,
+      MapWindowPoints (FRAME_W32_WINDOW (f),
+                      f->output_data.w32->parent_desc,
                       &pt, 1);
       UNBLOCK_INPUT;
     }
@@ -3157,7 +3522,7 @@ x_calc_absolute_position (f)
       rt.left = rt.right = rt.top = rt.bottom = 0;
       
       BLOCK_INPUT;
-      AdjustWindowRect(&rt, f->output_data.win32->dwStyle,
+      AdjustWindowRect(&rt, f->output_data.w32->dwStyle,
                       FRAME_EXTERNAL_MENU_BAR (f));
       UNBLOCK_INPUT;
 
@@ -3168,20 +3533,20 @@ x_calc_absolute_position (f)
   /* Treat negative positions as relative to the leftmost bottommost
      position that fits on the screen.  */
   if (flags & XNegative)
-    f->output_data.win32->left_pos = (FRAME_WIN32_DISPLAY_INFO (f)->width
-                             - 2 * f->output_data.win32->border_width - pt.x
+    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.win32->left_pos);
+                             + f->output_data.w32->left_pos);
 
   if (flags & YNegative)
-    f->output_data.win32->top_pos = (FRAME_WIN32_DISPLAY_INFO (f)->height
-                            - 2 * f->output_data.win32->border_width - pt.y
+    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.win32->top_pos);
+                            + f->output_data.w32->top_pos);
   /* The left_pos and top_pos
      are now relative to the top and left screen edges,
      so the flags should correspond.  */
-  f->output_data.win32->size_hint_flags &= ~ (XNegative | YNegative);
+  f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
 }
 
 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
@@ -3199,14 +3564,14 @@ x_set_offset (f, xoff, yoff, change_gravity)
 
   if (change_gravity > 0)
     {
-      f->output_data.win32->top_pos = yoff;
-      f->output_data.win32->left_pos = xoff;
-      f->output_data.win32->size_hint_flags &= ~ (XNegative | YNegative);
+      f->output_data.w32->top_pos = yoff;
+      f->output_data.w32->left_pos = xoff;
+      f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
       if (xoff < 0)
-       f->output_data.win32->size_hint_flags |= XNegative;
+       f->output_data.w32->size_hint_flags |= XNegative;
       if (yoff < 0)
-       f->output_data.win32->size_hint_flags |= YNegative;
-      f->output_data.win32->win_gravity = NorthWestGravity;
+       f->output_data.w32->size_hint_flags |= YNegative;
+      f->output_data.w32->win_gravity = NorthWestGravity;
     }
   x_calc_absolute_position (f);
 
@@ -3215,19 +3580,22 @@ x_set_offset (f, xoff, yoff, change_gravity)
 
   /* It is a mystery why we need to add the border_width here
      when the frame is already visible, but experiment says we do.  */
-  modified_left = f->output_data.win32->left_pos;
-  modified_top = f->output_data.win32->top_pos;
+  modified_left = f->output_data.w32->left_pos;
+  modified_top = f->output_data.w32->top_pos;
+#ifndef HAVE_NTGUI
+  /* Do not add in border widths under W32.  */
   if (change_gravity != 0)
     {
-      modified_left += f->output_data.win32->border_width;
-      modified_top += f->output_data.win32->border_width;
+      modified_left += f->output_data.w32->border_width;
+      modified_top += f->output_data.w32->border_width;
     }
+#endif
 
-  my_set_window_pos (FRAME_WIN32_WINDOW (f),
+  my_set_window_pos (FRAME_W32_WINDOW (f),
                     NULL,
                     modified_left, modified_top,
                     0,0,
-                    SWP_NOZORDER | SWP_NOSIZE);
+                    SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
   UNBLOCK_INPUT;
 }
 
@@ -3242,20 +3610,22 @@ x_set_window_size (f, change_gravity, cols, rows)
      int cols, rows;
 {
   int pixelwidth, pixelheight;
+  Lisp_Object window;
+  struct w32_display_info *dpyinfo = &one_w32_display_info;
   
   BLOCK_INPUT;
   
   check_frame_size (f, &rows, &cols);
-  f->output_data.win32->vertical_scroll_bar_extra
+  f->output_data.w32->vertical_scroll_bar_extra
     = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
        ? 0
        : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
        ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
-       : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.win32->font)));
+       : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font)));
   pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
   pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
   
-  f->output_data.win32->win_gravity = NorthWestGravity;
+  f->output_data.w32->win_gravity = NorthWestGravity;
   x_wm_set_size_hint (f, (long) 0, 0);
   
   {
@@ -3265,17 +3635,15 @@ x_set_window_size (f, change_gravity, cols, rows)
     rect.right = pixelwidth;
     rect.bottom = pixelheight;
       
-    AdjustWindowRect(&rect, f->output_data.win32->dwStyle,
+    AdjustWindowRect(&rect, f->output_data.w32->dwStyle,
                     FRAME_EXTERNAL_MENU_BAR (f));
       
-    /* All windows have an extra pixel */
-
-    my_set_window_pos (FRAME_WIN32_WINDOW (f),
+    my_set_window_pos (FRAME_W32_WINDOW (f),
                       NULL, 
                       0, 0,
-                      rect.right - rect.left + 1,
-                      rect.bottom - rect.top + 1,
-                      SWP_NOZORDER | SWP_NOMOVE);
+                      rect.right - rect.left,
+                      rect.bottom - rect.top,
+                      SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
   }
   
   /* Now, strictly speaking, we can't be sure that this is accurate,
@@ -3292,6 +3660,12 @@ x_set_window_size (f, change_gravity, cols, rows)
   PIXEL_WIDTH (f) = pixelwidth;
   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
+     for, then the event won't cause the screen to become garbaged, so
+     we have to make sure to do it here.  */
+  SET_FRAME_GARBAGED (f);
+
   /* If cursor was outside the new size, mark it as off.  */
   if (f->phys_cursor_y >= rows
       || f->phys_cursor_x >= cols)
@@ -3300,11 +3674,17 @@ x_set_window_size (f, change_gravity, cols, rows)
       f->phys_cursor_y = -1;
     }
 
-  /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
-     receive in the ConfigureNotify event; if we get what we asked
-     for, then the event won't cause the screen to become garbaged, so
-     we have to make sure to do it here.  */
-  SET_FRAME_GARBAGED (f);
+  /* Clear out any recollection of where the mouse highlighting was,
+     since it might be in a place that's outside the new frame size. 
+     Actually checking whether it is outside is a pain in the neck,
+     so don't try--just let the highlighting be done afresh with new size.  */
+  window = dpyinfo->mouse_face_window;
+  if (! NILP (window) && XFRAME (window) == f)
+    {
+      dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
+      dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
+      dpyinfo->mouse_face_window = Qnil;
+    }
   
   UNBLOCK_INPUT;
 }
@@ -3312,40 +3692,42 @@ x_set_window_size (f, change_gravity, cols, rows)
 /* Mouse warping.  */
 
 void
-x_set_mouse_position (f, x, y)
+x_set_mouse_pixel_position (f, pix_x, pix_y)
      struct frame *f;
-     int 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.win32->font) / 2;
-  pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.win32->line_height / 2;
-
-  if (pix_x < 0) pix_x = 0;
-  if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
-
-  if (pix_y < 0) pix_y = 0;
-  if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
+  RECT rect;
+  POINT pt;
 
   BLOCK_INPUT;
 
-  SetCursorPos (pix_x, pix_y);
+  GetClientRect (FRAME_W32_WINDOW (f), &rect);
+  pt.x = rect.left + pix_x;
+  pt.y = rect.top + pix_y;
+  ClientToScreen (FRAME_W32_WINDOW (f), &pt);
+
+  SetCursorPos (pt.x, pt.y);
 
   UNBLOCK_INPUT;
 }
 
-/* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F.  */
-
 void
-x_set_mouse_pixel_position (f, pix_x, pix_y)
+x_set_mouse_position (f, x, y)
      struct frame *f;
-     int pix_x, pix_y;
+     int x, y;
 {
-  BLOCK_INPUT;
+  int pix_x, pix_y;
 
-  SetCursorPos (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;
 
-  UNBLOCK_INPUT;
+  if (pix_x < 0) pix_x = 0;
+  if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
+
+  if (pix_y < 0) pix_y = 0;
+  if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
+
+  x_set_mouse_pixel_position (f, pix_x, pix_y);
 }
 \f
 /* focus shifting, raising and lowering.  */
@@ -3353,6 +3735,18 @@ x_set_mouse_pixel_position (f, pix_x, pix_y)
 x_focus_on_frame (f)
      struct frame *f;
 {
+  struct w32_display_info *dpyinfo = &one_w32_display_info;
+
+  /* Give input focus to frame.  */
+  BLOCK_INPUT;
+#if 0
+  /* Try not to change its Z-order if possible.  */
+  if (x_window_to_frame (dpyinfo, GetForegroundWindow ()))
+    my_set_focus (f, FRAME_W32_WINDOW (f));
+  else
+#endif
+    SetForegroundWindow (FRAME_W32_WINDOW (f));
+  UNBLOCK_INPUT;
 }
 
 x_unfocus_frame (f)
@@ -3365,15 +3759,59 @@ x_unfocus_frame (f)
 x_raise_frame (f)
      struct frame *f;
 {
-//  if (f->async_visible)
+  BLOCK_INPUT;
+
+  /* Strictly speaking, raise-frame should only change the frame's Z
+     order, leaving input focus unchanged.  This is reasonable behaviour
+     on X where the usual policy is point-to-focus.  However, this
+     behaviour would be very odd on Windows where the usual policy is
+     click-to-focus.
+
+     On X, if the mouse happens to be over the raised frame, it gets
+     input focus anyway (so the window with focus will never be
+     completely obscured) - if not, then just moving the mouse over it
+     is sufficient to give it focus.  On Windows, the user must actually
+     click on the frame (preferrably the title bar so as not to move
+     point), which is more awkward.  Also, no other Windows program
+     raises a window to the top but leaves another window (possibly now
+     completely obscured) with input focus.
+
+     Because there is a system setting on Windows that allows the user
+     to choose the point to focus policy, we make the strict semantics
+     optional, but by default we grab focus when raising.  */
+
+  if (NILP (Vw32_grab_focus_on_raise))
     {
-      BLOCK_INPUT;
-      my_set_window_pos (FRAME_WIN32_WINDOW (f),
-                        HWND_TOP,
-                        0, 0, 0, 0,
-                        SWP_NOSIZE | SWP_NOMOVE);
-      UNBLOCK_INPUT;
+      /* The obvious call to my_set_window_pos doesn't work if Emacs is
+        not already the foreground application: the frame is raised
+        above all other frames belonging to us, but not above the
+        current top window.  To achieve that, we have to resort to this
+        more cumbersome method.  */
+
+      HDWP handle = BeginDeferWindowPos (2);
+      if (handle)
+       {
+         DeferWindowPos (handle,
+                         FRAME_W32_WINDOW (f),
+                         HWND_TOP,
+                         0, 0, 0, 0,
+                         SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
+
+         DeferWindowPos (handle,
+                         GetForegroundWindow (),
+                         FRAME_W32_WINDOW (f),
+                         0, 0, 0, 0,
+                         SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
+
+         EndDeferWindowPos (handle);
+       }
     }
+  else
+    {
+      SetForegroundWindow (FRAME_W32_WINDOW (f));
+    }
+
+  UNBLOCK_INPUT;
 }
 
 /* Lower frame F.  */
@@ -3381,19 +3819,16 @@ x_raise_frame (f)
 x_lower_frame (f)
      struct frame *f;
 {
-//  if (f->async_visible)
-    {
-      BLOCK_INPUT;
-      my_set_window_pos (FRAME_WIN32_WINDOW (f),
-                        HWND_BOTTOM,
-                        0, 0, 0, 0,
-                        SWP_NOSIZE | SWP_NOMOVE);
-      UNBLOCK_INPUT;
-    }
+  BLOCK_INPUT;
+  my_set_window_pos (FRAME_W32_WINDOW (f),
+                    HWND_BOTTOM,
+                    0, 0, 0, 0,
+                    SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
+  UNBLOCK_INPUT;
 }
 
 static void
-win32_frame_raise_lower (f, raise)
+w32_frame_raise_lower (f, raise)
      FRAME_PTR f;
      int raise;
 {
@@ -3424,15 +3859,13 @@ x_make_frame_visible (f)
         if we get to x_make_frame_visible a second time
         before the window gets really visible.  */
       if (! FRAME_ICONIFIED_P (f)
-         && ! f->output_data.win32->asked_for_visible)
-      {
-       x_set_offset (f, f->output_data.win32->left_pos, f->output_data.win32->top_pos, 0);
-//     SetForegroundWindow (FRAME_WIN32_WINDOW (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);
 
-      f->output_data.win32->asked_for_visible = 1;
+      f->output_data.w32->asked_for_visible = 1;
 
-      my_show_window (FRAME_WIN32_WINDOW (f), SW_SHOWNORMAL);
+//      my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW);
+      my_show_window (f, FRAME_W32_WINDOW (f), SW_SHOWNORMAL);
     }
 
   /* Synchronize to ensure Emacs knows the frame is visible
@@ -3490,12 +3923,12 @@ x_make_frame_invisible (f)
   Window window;
   
   /* Don't keep the highlight on an invisible frame.  */
-  if (FRAME_WIN32_DISPLAY_INFO (f)->win32_highlight_frame == f)
-    FRAME_WIN32_DISPLAY_INFO (f)->win32_highlight_frame = 0;
+  if (FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame == f)
+    FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame = 0;
   
   BLOCK_INPUT;
   
-  my_show_window (FRAME_WIN32_WINDOW (f), SW_HIDE);
+  my_show_window (f, FRAME_W32_WINDOW (f), SW_HIDE);
   
   /* We can't distinguish this from iconification
      just by the event that we get from the server.
@@ -3519,17 +3952,16 @@ x_iconify_frame (f)
   int result;
 
   /* Don't keep the highlight on an invisible frame.  */
-  if (FRAME_WIN32_DISPLAY_INFO (f)->win32_highlight_frame == f)
-    FRAME_WIN32_DISPLAY_INFO (f)->win32_highlight_frame = 0;
+  if (FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame == f)
+    FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame = 0;
 
   if (f->async_iconified)
     return;
 
   BLOCK_INPUT;
 
-  my_show_window (FRAME_WIN32_WINDOW (f), SW_SHOWMINIMIZED);
-  /* The frame doesn't seem to be lowered automatically. */
-  x_lower_frame (f);
+  /* Simulate the user minimizing the frame.  */
+  PostMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, SC_MINIMIZE, 0);
 
   f->async_iconified = 1;
 
@@ -3541,22 +3973,22 @@ x_iconify_frame (f)
 x_destroy_window (f)
      struct frame *f;
 {
-  struct win32_display_info *dpyinfo = FRAME_WIN32_DISPLAY_INFO (f);
+  struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
 
   BLOCK_INPUT;
 
-  my_destroy_window (f, FRAME_WIN32_WINDOW (f));
+  my_destroy_window (f, FRAME_W32_WINDOW (f));
   free_frame_menubar (f);
   free_frame_faces (f);
 
-  xfree (f->output_data.win32);
-  f->output_data.win32 = 0;
-  if (f == dpyinfo->win32_focus_frame)
-    dpyinfo->win32_focus_frame = 0;
-  if (f == dpyinfo->win32_focus_event_frame)
-    dpyinfo->win32_focus_event_frame = 0;
-  if (f == dpyinfo->win32_highlight_frame)
-    dpyinfo->win32_highlight_frame = 0;
+  xfree (f->output_data.w32);
+  f->output_data.w32 = 0;
+  if (f == dpyinfo->w32_focus_frame)
+    dpyinfo->w32_focus_frame = 0;
+  if (f == dpyinfo->w32_focus_event_frame)
+    dpyinfo->w32_focus_event_frame = 0;
+  if (f == dpyinfo->w32_highlight_frame)
+    dpyinfo->w32_highlight_frame = 0;
 
   dpyinfo->reference_count--;
 
@@ -3585,14 +4017,16 @@ x_wm_set_size_hint (f, flags, user_position)
      long flags;
      int user_position;
 {
-  Window window = FRAME_WIN32_WINDOW (f);
+  Window window = FRAME_W32_WINDOW (f);
 
   flexlines = f->height;
 
   enter_crit ();
 
-  SetWindowLong (window, WND_X_UNITS_INDEX, FONT_WIDTH (f->output_data.win32->font));
-  SetWindowLong (window, WND_Y_UNITS_INDEX, f->output_data.win32->line_height);
+  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);
 
   leave_crit ();
 }
@@ -3603,7 +4037,7 @@ x_wm_set_icon_position (f, icon_x, icon_y)
      int icon_x, icon_y;
 {
 #if 0
-  Window window = FRAME_WIN32_WINDOW (f);
+  Window window = FRAME_W32_WINDOW (f);
 
   f->display.x->wm_hints.flags |= IconPositionHint;
   f->display.x->wm_hints.icon_x = icon_x;
@@ -3635,25 +4069,25 @@ static XrmOptionDescRec emacs_options[] = {
 };
 #endif /* USE_X_TOOLKIT */
 
-static int win32_initialized = 0;
+static int w32_initialized = 0;
 
-struct win32_display_info *
-win32_term_init (display_name, xrm_option, resource_name)
+struct w32_display_info *
+w32_term_init (display_name, xrm_option, resource_name)
      Lisp_Object display_name;
      char *xrm_option;
      char *resource_name;
 {
   Lisp_Object frame;
   char *defaultvalue;
-  struct win32_display_info *dpyinfo;
+  struct w32_display_info *dpyinfo;
   HDC hdc;
   
   BLOCK_INPUT;
   
-  if (!win32_initialized)
+  if (!w32_initialized)
     {
-      win32_initialize ();
-      win32_initialized = 1;
+      w32_initialize ();
+      w32_initialized = 1;
     }
   
   {
@@ -3669,21 +4103,21 @@ win32_term_init (display_name, xrm_option, resource_name)
       }
   }
   
-  dpyinfo = &one_win32_display_info;
+  dpyinfo = &one_w32_display_info;
   
   /* Put this display on the chain.  */
   dpyinfo->next = NULL;
   
-  /* Put it on win32_display_name_list as well, to keep them parallel.  */ 
-  win32_display_name_list = Fcons (Fcons (display_name, Qnil),
-                                  win32_display_name_list);
-  dpyinfo->name_list_element = XCONS (win32_display_name_list)->car;
+  /* Put it on w32_display_name_list as well, to keep them parallel.  */ 
+  w32_display_name_list = Fcons (Fcons (display_name, Qnil),
+                                  w32_display_name_list);
+  dpyinfo->name_list_element = XCONS (w32_display_name_list)->car;
   
-  dpyinfo->win32_id_name
+  dpyinfo->w32_id_name
     = (char *) xmalloc (XSTRING (Vinvocation_name)->size
                        + XSTRING (Vsystem_name)->size
                        + 2);
-  sprintf (dpyinfo->win32_id_name, "%s@%s",
+  sprintf (dpyinfo->w32_id_name, "%s@%s",
           XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
 
 #if 0
@@ -3719,16 +4153,16 @@ win32_term_init (display_name, xrm_option, resource_name)
   dpyinfo->mouse_face_window = Qnil;
   dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
   dpyinfo->mouse_face_defer = 0;
-  dpyinfo->win32_focus_frame = 0;
-  dpyinfo->win32_focus_event_frame = 0;
-  dpyinfo->win32_highlight_frame = 0;
+  dpyinfo->w32_focus_frame = 0;
+  dpyinfo->w32_focus_event_frame = 0;
+  dpyinfo->w32_highlight_frame = 0;
   
   ReleaseDC (GetDesktopWindow (), hdc);
 
   /* Determine if there is a middle mouse button, to allow parse_button
      to decide whether right mouse events should be mouse-2 or
      mouse-3. */
-  XSETINT (Vwin32_num_mouse_buttons, GetSystemMetrics (SM_CMOUSEBUTTONS));
+  XSETINT (Vw32_num_mouse_buttons, GetSystemMetrics (SM_CMOUSEBUTTONS));
 
   /* initialise palette with white and black */
   {
@@ -3762,18 +4196,18 @@ win32_term_init (display_name, xrm_option, resource_name)
 
 void
 x_delete_display (dpyinfo)
-     struct win32_display_info *dpyinfo;
+     struct w32_display_info *dpyinfo;
 {
-  /* Discard this display from win32_display_name_list and win32_display_list.
+  /* Discard this display from w32_display_name_list and w32_display_list.
      We can't use Fdelq because that can quit.  */
-  if (! NILP (win32_display_name_list)
-      && EQ (XCONS (win32_display_name_list)->car, dpyinfo->name_list_element))
-    win32_display_name_list = XCONS (win32_display_name_list)->cdr;
+  if (! NILP (w32_display_name_list)
+      && EQ (XCONS (w32_display_name_list)->car, dpyinfo->name_list_element))
+    w32_display_name_list = XCONS (w32_display_name_list)->cdr;
   else
     {
       Lisp_Object tail;
 
-      tail = win32_display_name_list;
+      tail = w32_display_name_list;
       while (CONSP (tail) && CONSP (XCONS (tail)->cdr))
        {
          if (EQ (XCONS (XCONS (tail)->cdr)->car,
@@ -3788,12 +4222,12 @@ x_delete_display (dpyinfo)
 
   /* free palette table */
   {
-    struct win32_palette_entry * plist;
+    struct w32_palette_entry * plist;
 
     plist = dpyinfo->color_list;
     while (plist)
     {
-      struct win32_palette_entry * pentry = plist;
+      struct w32_palette_entry * pentry = plist;
       plist = plist->next;
       xfree(pentry);
     }
@@ -3802,39 +4236,39 @@ x_delete_display (dpyinfo)
       DeleteObject(dpyinfo->palette);
   }
   xfree (dpyinfo->font_table);
-  xfree (dpyinfo->win32_id_name);
+  xfree (dpyinfo->w32_id_name);
 }
 \f
-/* Set up use of Win32.  */
-
-DWORD win_msg_worker ();
-
-win32_initialize ()
-{
-  clear_frame_hook = win32_clear_frame;
-  clear_end_of_line_hook = win32_clear_end_of_line;
-  ins_del_lines_hook = win32_ins_del_lines;
-  change_line_highlight_hook = win32_change_line_highlight;
-  insert_glyphs_hook = win32_insert_glyphs;
-  write_glyphs_hook = win32_write_glyphs;
-  delete_glyphs_hook = win32_delete_glyphs;
-  ring_bell_hook = win32_ring_bell;
-  reset_terminal_modes_hook = win32_reset_terminal_modes;
-  set_terminal_modes_hook = win32_set_terminal_modes;
-  update_begin_hook = win32_update_begin;
-  update_end_hook = win32_update_end;
-  set_terminal_window_hook = win32_set_terminal_window;
+/* Set up use of W32.  */
+
+DWORD w32_msg_worker ();
+
+w32_initialize ()
+{
+  clear_frame_hook = w32_clear_frame;
+  clear_end_of_line_hook = w32_clear_end_of_line;
+  ins_del_lines_hook = w32_ins_del_lines;
+  change_line_highlight_hook = w32_change_line_highlight;
+  insert_glyphs_hook = w32_insert_glyphs;
+  write_glyphs_hook = w32_write_glyphs;
+  delete_glyphs_hook = w32_delete_glyphs;
+  ring_bell_hook = w32_ring_bell;
+  reset_terminal_modes_hook = w32_reset_terminal_modes;
+  set_terminal_modes_hook = w32_set_terminal_modes;
+  update_begin_hook = w32_update_begin;
+  update_end_hook = w32_update_end;
+  set_terminal_window_hook = w32_set_terminal_window;
   read_socket_hook = w32_read_socket;
-  frame_up_to_date_hook = win32_frame_up_to_date;
-  cursor_to_hook = win32_cursor_to;
-  reassert_line_highlight_hook = win32_reassert_line_highlight;
-  mouse_position_hook = win32_mouse_position;
-  frame_rehighlight_hook = win32_frame_rehighlight;
-  frame_raise_lower_hook = win32_frame_raise_lower;
-  set_vertical_scroll_bar_hook = win32_set_vertical_scroll_bar;
-  condemn_scroll_bars_hook = win32_condemn_scroll_bars;
-  redeem_scroll_bar_hook = win32_redeem_scroll_bar;
-  judge_scroll_bars_hook = win32_judge_scroll_bars;
+  frame_up_to_date_hook = w32_frame_up_to_date;
+  cursor_to_hook = w32_cursor_to;
+  reassert_line_highlight_hook = w32_reassert_line_highlight;
+  mouse_position_hook = w32_mouse_position;
+  frame_rehighlight_hook = w32_frame_rehighlight;
+  frame_raise_lower_hook = w32_frame_raise_lower;
+  set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar;
+  condemn_scroll_bars_hook = w32_condemn_scroll_bars;
+  redeem_scroll_bar_hook = w32_redeem_scroll_bar;
+  judge_scroll_bars_hook = w32_judge_scroll_bars;
 
   scroll_region_ok = 1;         /* we'll scroll partial frames */
   char_ins_del_ok = 0;          /* just as fast to write the line */
@@ -3844,8 +4278,9 @@ win32_initialize ()
                                   off the bottom */
   baud_rate = 19200;
 
-  /* Try to use interrupt input; if we can't, then start polling.  */
-  Fset_input_mode (Qt, Qnil, Qt, Qnil);
+  /* Initialize input mode: interrupt_input off, no flow control, allow
+     8 bit character input, standard quit char.  */
+  Fset_input_mode (Qnil, Qnil, make_number (2), Qnil);
 
   /* Create the window thread - it will terminate itself or when the app terminates */
 
@@ -3862,31 +4297,56 @@ win32_initialize ()
 
     PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
 
-    hWinThread = CreateThread (NULL, 0, 
-                              (LPTHREAD_START_ROUTINE) win_msg_worker, 
-                              0, 0, &dwWinThreadId);
+    hWindowsThread = CreateThread (NULL, 0, 
+                              (LPTHREAD_START_ROUTINE) w32_msg_worker, 
+                              0, 0, &dwWindowsThreadId);
 
     GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
   }
   
   /* It is desirable that mainThread should have the same notion of
-     focus window and active window as winThread.  Unfortunately, the
+     focus window and active window as windowsThread.  Unfortunately, the
      following call to AttachThreadInput, which should do precisely what
      we need, causes major problems when Emacs is linked as a console
      program.  Unfortunately, we have good reasons for doing that, so
-     instead we need to send messages to winThread to make some API
+     instead we need to send messages to windowsThread to make some API
      calls for us (ones that affect, or depend on, the active/focus
      window state.  */
 #ifdef ATTACH_THREADS
-  AttachThreadInput (dwMainThreadId, dwWinThreadId, TRUE);
+  AttachThreadInput (dwMainThreadId, dwWindowsThreadId, TRUE);
 #endif
+
+  /* Dynamically link to optional system components. */
+  {
+    HANDLE user_lib = LoadLibrary ("user32.dll");
+
+#define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn)
+
+    /* New proportional scroll bar functions. */
+    LOAD_PROC( SetScrollInfo );
+    LOAD_PROC( GetScrollInfo );
+
+#undef LOAD_PROC
+
+    FreeLibrary (user_lib);
+
+    /* If using proportional scroll bars, ensure handle is at least 5 pixels;
+       otherwise use the fixed height.  */
+    vertical_scroll_bar_min_handle = (pfnSetScrollInfo != NULL) ? 5 :
+      GetSystemMetrics (SM_CYVTHUMB);
+
+    /* For either kind of scroll bar, take account of the arrows; these
+       effectively form the border of the main scroll bar range.  */
+    vertical_scroll_bar_top_border = vertical_scroll_bar_bottom_border
+      = GetSystemMetrics (SM_CYVSCROLL);
+  }
 }
 
 void
-syms_of_win32term ()
+syms_of_w32term ()
 {
-  staticpro (&win32_display_name_list);
-  win32_display_name_list = Qnil;
+  staticpro (&w32_display_name_list);
+  w32_display_name_list = Qnil;
 
   staticpro (&last_mouse_scroll_bar);
   last_mouse_scroll_bar = Qnil;
@@ -3894,14 +4354,28 @@ syms_of_win32term ()
   staticpro (&Qvendor_specific_keysyms);
   Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
 
-  DEFVAR_INT ("win32-num-mouse-buttons",
-             &Vwin32_num_mouse_buttons,
+  DEFVAR_INT ("w32-num-mouse-buttons",
+             &Vw32_num_mouse_buttons,
              "Number of physical mouse buttons.");
-  Vwin32_num_mouse_buttons = Qnil;
+  Vw32_num_mouse_buttons = Qnil;
 
-  DEFVAR_LISP ("win32-swap-mouse-buttons",
-             &Vwin32_swap_mouse_buttons,
+  DEFVAR_LISP ("w32-swap-mouse-buttons",
+             &Vw32_swap_mouse_buttons,
              "Swap the mapping of middle and right mouse buttons.\n\
 When nil, middle button is mouse-2 and right button is mouse-3.");
-  Vwin32_swap_mouse_buttons = Qnil;
+  Vw32_swap_mouse_buttons = Qnil;
+
+  DEFVAR_LISP ("w32-grab-focus-on-raise",
+              &Vw32_grab_focus_on_raise,
+              "Raised frame grabs input focus.\n\
+When t, `raise-frame' grabs input focus as well.  This fits well\n\
+with the normal Windows click-to-focus policy, but might not be\n\
+desirable when using a point-to-focus policy.");
+  Vw32_grab_focus_on_raise = Qt;
+
+  DEFVAR_LISP ("w32-capslock-is-shiftlock",
+              &Vw32_capslock_is_shiftlock,
+              "Apply CapsLock state to non character input keys.\n\
+When nil, CapsLock only affects normal character input keys.");
+  Vw32_capslock_is_shiftlock = Qnil;
 }