Change defvar_int def and vars to use EMACS_INT instead of just int.
[bpt/emacs.git] / src / w32term.c
index 7ad6eae..07624b9 100644 (file)
@@ -1,5 +1,5 @@
 /* Implementation of GUI terminal on the Microsoft W32 API.
-   Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000
+   Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001
    Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -35,6 +35,7 @@ Boston, MA 02111-1307, USA.  */
 #include "systty.h"
 #include "systime.h"
 #include "atimer.h"
+#include "keymap.h"
 
 #include <ctype.h>
 #include <errno.h>
@@ -56,21 +57,16 @@ Boston, MA 02111-1307, USA.  */
 #include "composite.h"
 #include "coding.h"
 
-#undef min
-#undef max
-#define min(x, y) (((x) < (y)) ? (x) : (y))
-#define max(x, y) (((x) > (y)) ? (x) : (y))
-
 #define abs(x) ((x) < 0 ? -(x) : (x))
 
 #define BETWEEN(X, LOWER, UPPER)  ((X) >= (LOWER) && (X) < (UPPER))
 
 \f
-/* Bitmaps for truncated lines.  */
+/* Fringe bitmaps.  */
 
-enum bitmap_type
+enum fringe_bitmap_type
 {
-  NO_BITMAP,
+  NO_FRINGE_BITMAP,
   LEFT_TRUNCATION_BITMAP,
   RIGHT_TRUNCATION_BITMAP,
   OVERLAY_ARROW_BITMAP,
@@ -88,9 +84,17 @@ enum bitmap_type
    `indicate-empty-lines' is non-nil.  */
 
 #define zv_width 8
-#define zv_height 8
-static unsigned short zv_bits[] = {
-   0x00, 0x00, 0x78, 0x78, 0x78, 0x78, 0x00, 0x00};
+#define zv_height 72
+#define zv_period 3
+static unsigned char zv_bits[] = {
+  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
 static HBITMAP zv_bmp;
 
 /* An arrow like this: `<-'.  */
@@ -166,18 +170,24 @@ static Lisp_Object previous_help_echo;
 
 static int any_help_event_p;
 
+/* Non-zero means autoselect window with the mouse cursor.  */
+
+int x_autoselect_window_p;
+
 /* Non-zero means draw block and hollow cursor as wide as the glyph
    under it.  For example, if a block cursor is over a tab, it will be
    drawn as wide as that tab on the display.  */
 
 int x_stretch_cursor_p;
 
+/* Non-zero means make use of UNDERLINE_POSITION font properties.  */
+
+int x_use_underline_position_properties;
+
 extern unsigned int msh_mousewheel;
 
 extern void free_frame_menubar ();
 
-extern void w32_menu_display_help (HMENU menu, UINT menu_item, UINT flags);
-
 extern int w32_codepage_for_font (char *fontname);
 
 extern glyph_metric *w32_BDF_TextMetric(bdffont *fontp,
@@ -190,6 +200,7 @@ extern Lisp_Object Vwindow_system;
 \f
 /* This is display since w32 does not support multiple ones.  */
 struct w32_display_info one_w32_display_info;
+struct w32_display_info *x_display_list;
 
 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
    one for each element of w32_display_list and in the same order.
@@ -213,6 +224,13 @@ struct frame *pending_autoraise_frame;
 
 struct cursor_pos output_cursor;
 
+/* The handle of the frame that currently owns the system caret.  */
+HWND w32_system_caret_hwnd;
+int w32_system_caret_height;
+int w32_system_caret_x;
+int w32_system_caret_y;
+int w32_use_visible_system_caret;
+
 /* Flag to enable Unicode output in case users wish to use programs
    like Twinbridge on '95 rather than installed system level support
    for Far East languages.  */
@@ -315,7 +333,7 @@ extern int errno;
 
 /* A mask of extra modifier bits to put into every keyboard char.  */
 
-extern int extra_keyboard_modifiers;
+extern EMACS_INT extra_keyboard_modifiers;
 
 /* Enumeration for overriding/changing the face to use for drawing
    glyphs in x_draw_glyphs.  */
@@ -334,19 +352,21 @@ static void x_update_window_end P_ ((struct window *, int, int));
 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
 void w32_delete_display P_ ((struct w32_display_info *));
 static int fast_find_position P_ ((struct window *, int, int *, int *,
-                                  int *, int *));
+                                  int *, int *, Lisp_Object));
+static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
+                                    int *, int *, int *, int *, int));
 static void set_output_cursor P_ ((struct cursor_pos *));
 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
-                                          int *, int *, int *));
+                                          int *, int *, int *, int));
 static void note_mode_line_highlight P_ ((struct window *, int, int));
-static void x_check_font P_ ((struct frame *, XFontStruct *));
 static void note_mouse_highlight P_ ((struct frame *, int, int));
 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
 static void w32_handle_tool_bar_click P_ ((struct frame *,
                                           struct input_event *));
 static void show_mouse_face P_ ((struct w32_display_info *,
                                 enum draw_glyphs_face));
-void clear_mouse_face P_ ((struct w32_display_info *));
+static int cursor_in_mouse_face_p P_ ((struct window *));
+static int clear_mouse_face P_ ((struct w32_display_info *));
 
 void x_lower_frame P_ ((struct frame *));
 void x_scroll_bar_clear P_ ((struct frame *));
@@ -363,8 +383,6 @@ static void x_draw_phys_cursor_glyph P_ ((struct window *,
                                          enum draw_glyphs_face));
 static void x_update_end P_ ((struct frame *));
 static void w32_frame_up_to_date P_ ((struct frame *));
-static void w32_reassert_line_highlight P_ ((int, int));
-static void x_change_line_highlight P_ ((int, int, int, int));
 static void w32_set_terminal_modes P_ ((void));
 static void w32_reset_terminal_modes P_ ((void));
 static void w32_cursor_to P_ ((int, int, int, int));
@@ -374,32 +392,36 @@ static void x_clear_frame P_ ((void));
 static void x_clear_cursor P_ ((struct window *));
 static void frame_highlight P_ ((struct frame *));
 static void frame_unhighlight P_ ((struct frame *));
-static void w32_new_focus_frame P_ ((struct w32_display_info *,
-                                     struct frame *));
+static void x_new_focus_frame P_ ((struct w32_display_info *,
+                                  struct frame *));
 static void w32_frame_rehighlight P_ ((struct frame *));
 static void x_frame_rehighlight P_ ((struct w32_display_info *));
 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
 static void expose_frame P_ ((struct frame *, int, int, int, int));
-static void expose_window_tree P_ ((struct window *, RECT *));
-static void expose_window P_ ((struct window *, RECT *));
+static int expose_window_tree P_ ((struct window *, RECT *));
+static int expose_window P_ ((struct window *, RECT *));
 static void expose_area P_ ((struct window *, struct glyph_row *,
                             RECT *, enum glyph_row_area));
-static void expose_line P_ ((struct window *, struct glyph_row *,
-                            RECT *));
+static int expose_line P_ ((struct window *, struct glyph_row *,
+                           RECT *));
 void x_update_cursor P_ ((struct frame *, int));
 static void x_update_cursor_in_window_tree P_ ((struct window *, int));
 static void x_update_window_cursor P_ ((struct window *, int));
 static void x_erase_phys_cursor P_ ((struct window *));
 void x_display_cursor P_ ((struct window *w, int, int, int, int, int));
 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
-static void w32_draw_bitmap P_ ((struct window *, HDC hdc, struct glyph_row *, 
-                                 enum bitmap_type));
-static int x_phys_cursor_in_rect_p P_ ((struct window *, RECT *));
-static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *));
-static void note_overwritten_text_cursor P_ ((struct window *, int, int));
+static void w32_draw_fringe_bitmap P_ ((struct window *, HDC hdc,
+                                       struct glyph_row *, 
+                                       enum fringe_bitmap_type, int left_p));
 static void w32_clip_to_row P_ ((struct window *, struct glyph_row *,
-                               HDC, int));
+                                 HDC, int));
+static int x_phys_cursor_in_rect_p P_ ((struct window *, RECT *));
+static void x_draw_row_fringe_bitmaps P_ ((struct window *,
+                                          struct glyph_row *));
+static void notice_overwritten_cursor P_ ((struct window *,
+                                          enum glyph_row_area,
+                                          int, int, int, int));
 
 static Lisp_Object Qvendor_specific_keysyms;
 
@@ -510,7 +532,6 @@ w32_fill_rect (f, hdc, pix, lprect)
      RECT * lprect;
 {
   HBRUSH hb;
-  RECT rect;
 
   hb = CreateSolidBrush (pix);
   FillRect (hdc, lprect, hb);
@@ -576,6 +597,10 @@ x_update_window_begin (w)
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
 
+  /* Hide the system caret during an update.  */
+  if (w32_use_visible_system_caret)
+    SendMessage (w32_system_caret_hwnd, WM_EMACS_HIDE_CARET, 0, 0);
+
   updated_window = w;
   set_output_cursor (&w->cursor);
 
@@ -641,8 +666,9 @@ x_draw_vertical_border (w)
       RECT r;
       HDC hdc;
 
-      window_box_edges (w, -1, &r.left, &r.top, &r.right, &r.bottom);
-      r.left = r.right + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f);
+      window_box_edges (w, -1, (int *) &r.left, (int *) &r.top,
+                       (int *) &r.right, (int *) &r.bottom);
+      r.left = r.right + FRAME_X_RIGHT_FRINGE_WIDTH (f);
       r.right = r.left + 1;
       r.bottom -= 1;
 
@@ -671,30 +697,37 @@ x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
      struct window *w;
      int cursor_on_p, mouse_face_overwritten_p;
 {
+  struct w32_display_info *dpyinfo
+    = FRAME_W32_DISPLAY_INFO (XFRAME (w->frame));
+
   if (!w->pseudo_window_p)
     {
-      struct w32_display_info *dpyinfo
-        = FRAME_W32_DISPLAY_INFO (XFRAME (w->frame));
-
       BLOCK_INPUT;
 
-      /* If a row with mouse-face was overwritten, arrange for
-        XTframe_up_to_date to redisplay the mouse highlight.  */
-      if (mouse_face_overwritten_p)
-       {
-         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;
-       }
-
       if (cursor_on_p)
        x_display_and_set_cursor (w, 1, output_cursor.hpos,
                                  output_cursor.vpos,
                                  output_cursor.x, output_cursor.y);
+      
       x_draw_vertical_border (w);
       UNBLOCK_INPUT;
     }
-  
+
+  /* If a row with mouse-face was overwritten, arrange for
+     XTframe_up_to_date to redisplay the mouse highlight.  */
+  if (mouse_face_overwritten_p)
+    {
+      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;
+    }
+
+  /* Unhide the caret.  This won't actually show the cursor, unless it
+     was visible before the corresponding call to HideCaret in
+     x_update_window_begin.  */
+  if (w32_use_visible_system_caret)
+    SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
+
   updated_window = NULL;
 }
 
@@ -741,9 +774,9 @@ w32_frame_up_to_date (f)
 
 
 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
-   arrow bitmaps, or clear the areas where they would be displayed
+   arrow bitmaps, or clear the fringes if no bitmaps are required
    before DESIRED_ROW is made current.  The window being updated is
-   found in updated_window.  This function It is called from
+   found in updated_window.  This function is called from
    update_window_line only if it is known that there are differences
    between bitmaps to be drawn between current row and DESIRED_ROW.  */
 
@@ -752,51 +785,69 @@ x_after_update_window_line (desired_row)
      struct glyph_row *desired_row;
 {
   struct window *w = updated_window;
-  
+  struct frame *f;
+  int width, height;
+
   xassert (w);
   
   if (!desired_row->mode_line_p && !w->pseudo_window_p)
     {
       BLOCK_INPUT;
-      x_draw_row_bitmaps (w, desired_row);
+      x_draw_row_fringe_bitmaps (w, desired_row);
+      UNBLOCK_INPUT;
+    }
 
-      /* When a window has disappeared, make sure that no rest of
-        full-width rows stays visible in the internal border.  */
-      if (windows_or_buffers_changed)
-       {
-         struct frame *f = XFRAME (w->frame);
-         int width = FRAME_INTERNAL_BORDER_WIDTH (f);
-         int height = desired_row->visible_height;
-         int x = (window_box_right (w, -1)
-                   + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f));
-         int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
-          HDC hdc = get_frame_dc (f);
-
-          w32_clear_area (f, hdc, x, y, width, height);
-          release_frame_dc (f, hdc);
-       }
-      
+  /* When a window has disappeared, make sure that no rest of
+     full-width rows stays visible in the internal border.  Could
+     check here if updated_window is the leftmost/rightmost window,
+     but I guess it's not worth doing since vertically split windows
+     are almost never used, internal border is rarely set, and the
+     overhead is very small.  */
+  if (windows_or_buffers_changed
+      && desired_row->full_width_p
+      && (f = XFRAME (w->frame),
+         width = FRAME_INTERNAL_BORDER_WIDTH (f),
+         width != 0)
+      && (height = desired_row->visible_height,
+         height > 0))
+    {
+      int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
+      /* Internal border is drawn below the tool bar.  */
+      if (WINDOWP (f->tool_bar_window)
+         && w == XWINDOW (f->tool_bar_window))
+       y -= width;
+
+      BLOCK_INPUT;
+      {
+       HDC hdc = get_frame_dc (f);
+       w32_clear_area (f, hdc, 0, y, width, height);
+       w32_clear_area (f, hdc, f->output_data.w32->pixel_width - width,
+                       y, width, height);
+       release_frame_dc (f, hdc);
+      }
       UNBLOCK_INPUT;
     }
 }
 
 
-/* Draw the bitmap WHICH in one of the areas to the left or right of
+/* Draw the bitmap WHICH in one of the left or right fringes of
    window W.  ROW is the glyph row for which to display the bitmap; it
    determines the vertical position at which the bitmap has to be
    drawn.  */
 
 static void
-w32_draw_bitmap (w, hdc, row, which)
+w32_draw_fringe_bitmap (w, hdc, row, which, left_p)
      struct window *w;
      HDC hdc;
      struct glyph_row *row;
-     enum bitmap_type which;
+     enum fringe_bitmap_type which;
+     int left_p;
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   Window window = FRAME_W32_WINDOW (f);
   HDC compat_hdc;
   int x, y, wd, h, dy;
+  int b1, b2;
   HBITMAP pixmap;
   HANDLE horig_obj;
   struct face *face;
@@ -804,71 +855,118 @@ w32_draw_bitmap (w, hdc, row, which)
   /* Must clip because of partially visible lines.  */
   w32_clip_to_row (w, row, hdc, 1);
 
+  /* Convert row to frame coordinates.  */
+  y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
+
   switch (which)
     {
+    case NO_FRINGE_BITMAP:
+      wd = 0;
+      h = 0;
+      break;
+
     case LEFT_TRUNCATION_BITMAP:
       wd = left_width;
       h = left_height;
       pixmap = left_bmp;
-      x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
-          - wd
-          - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
       break;
       
     case OVERLAY_ARROW_BITMAP:
       wd = ov_width;
       h = ov_height;
       pixmap = ov_bmp;
-      x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
-          - wd
-          - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
       break;
       
     case RIGHT_TRUNCATION_BITMAP:
       wd = right_width;
       h = right_height;
       pixmap = right_bmp;
-      x = window_box_right (w, -1);
-      x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
       break;
 
     case CONTINUED_LINE_BITMAP:
       wd = continued_width;
       h = continued_height;
       pixmap = continued_bmp;
-      x = window_box_right (w, -1);
-      x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
       break;
       
     case CONTINUATION_LINE_BITMAP:
       wd = continuation_width;
       h = continuation_height;
       pixmap = continuation_bmp;
-      x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
-          - wd
-          - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
       break;
 
     case ZV_LINE_BITMAP:
       wd = zv_width;
-      h = zv_height;
+      h = zv_height - (y % zv_period);
       pixmap = zv_bmp;
-      x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
-          - wd
-          - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
       break;
 
     default:
       abort ();
     }
 
-  /* Convert to frame coordinates.  Set dy to the offset in the row to
-     start drawing the bitmap.  */
-  y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
+  /* Clip bitmap if too high.  */
+  if (h > row->height)
+    h = row->height;
+
+  /* Set dy to the offset in the row to start drawing the bitmap.  */
   dy = (row->height - h) / 2;
 
   /* Draw the bitmap.  */
-  face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
+  face = FACE_FROM_ID (f, FRINGE_FACE_ID);
+  PREPARE_FACE_FOR_DISPLAY (f, face);
+
+  /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
+     the fringe.  */
+  b1 = -1;
+  if (left_p)
+    {
+      if (wd > FRAME_X_LEFT_FRINGE_WIDTH (f))
+       wd = FRAME_X_LEFT_FRINGE_WIDTH (f);
+      x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
+          - wd
+          - (FRAME_X_LEFT_FRINGE_WIDTH (f) - wd) / 2);
+      if (wd < FRAME_X_LEFT_FRINGE_WIDTH (f) || row->height > h)
+       {
+         /* If W has a vertical border to its left, don't draw over it.  */
+         int border = ((XFASTINT (w->left) > 0
+                        && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
+                       ? 1 : 0);
+         b1 = (window_box_left (w, -1)
+               - FRAME_X_LEFT_FRINGE_WIDTH (f)
+               + border);
+         b2 = (FRAME_X_LEFT_FRINGE_WIDTH (f) - border);
+       }
+    }
+  else
+    {
+      if (wd > FRAME_X_RIGHT_FRINGE_WIDTH (f))
+       wd = FRAME_X_RIGHT_FRINGE_WIDTH (f);
+      x = (window_box_right (w, -1)
+          + (FRAME_X_RIGHT_FRINGE_WIDTH (f) - wd) / 2);
+      /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
+        the fringe.  */
+      if (wd < FRAME_X_RIGHT_FRINGE_WIDTH (f) || row->height > h)
+       {
+         b1 = window_box_right (w, -1);
+         b2 = FRAME_X_RIGHT_FRINGE_WIDTH (f);
+       }
+    }
+
+  if (b1 >= 0)
+    {
+      int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
+      
+      w32_fill_area (f, hdc, face->background,
+                     b1,
+                     WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
+                                                      row->y)),
+                     b2,
+                     row->visible_height);
+    }
+
+  if (which == NO_FRINGE_BITMAP)
+    return;
 
   compat_hdc = CreateCompatibleDC (hdc);
   SaveDC (hdc);
@@ -877,7 +975,9 @@ w32_draw_bitmap (w, hdc, row, which)
   SetTextColor (hdc, face->background);
   SetBkColor (hdc, face->foreground);
 
-  BitBlt (hdc, x, y + dy, wd, h, compat_hdc, 0, 0, SRCCOPY);
+  BitBlt (hdc, x, y + dy, wd, h, compat_hdc, 0,
+         (which == ZV_LINE_BITMAP ? (row->y % zv_period) : 0),
+         SRCCOPY);
 
   SelectObject (compat_hdc, horig_obj);
   DeleteDC (compat_hdc);
@@ -885,19 +985,17 @@ w32_draw_bitmap (w, hdc, row, which)
 }
 
 
-/* Draw flags bitmaps for glyph row ROW on window W.  Call this
+/* Draw fringe bitmaps for glyph row ROW on window W.  Call this
    function with input blocked.  */
 
 static void
-x_draw_row_bitmaps (w, row)
+x_draw_row_fringe_bitmaps (w, row)
      struct window *w;
      struct glyph_row *row;
 {
   struct frame *f = XFRAME (w->frame);
-  enum bitmap_type bitmap;
-  struct face *face;
-  int header_line_height = -1;
-  HDC hdc = get_frame_dc (f);
+  enum fringe_bitmap_type bitmap;
+  HDC hdc;
 
   xassert (interrupt_input_blocked);
 
@@ -906,128 +1004,44 @@ x_draw_row_bitmaps (w, row)
   if (row->visible_height <= 0)
     return;
 
-  face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
-  PREPARE_FACE_FOR_DISPLAY (f, face);
-
-  /* Decide which bitmap to draw at the left side.  */
-  if (row->overlay_arrow_p)
-    bitmap = OVERLAY_ARROW_BITMAP;
-  else if (row->truncated_on_left_p)
-    bitmap = LEFT_TRUNCATION_BITMAP;
-  else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
-    bitmap = CONTINUATION_LINE_BITMAP;
-  else if (row->indicate_empty_line_p)
-    bitmap = ZV_LINE_BITMAP;
-  else
-    bitmap = NO_BITMAP;
-
-  /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
-     the flags area.  */
-  if (bitmap == NO_BITMAP
-      || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
-      || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
-    {
-      /* If W has a vertical border to its left, don't draw over it.  */
-      int border = ((XFASTINT (w->left) > 0
-                    && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
-                   ? 1 : 0);
-      int left = window_box_left (w, -1);
-
-      if (header_line_height < 0)
-       header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
-      
-      w32_fill_area (f, hdc, face->background,
-                     left - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) + border,
-                     WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
-                                                      row->y)),
-                     FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - border,
-                     row->visible_height);
-    }
+  hdc = get_frame_dc (f);
 
-  /* Draw the left bitmap.  */
-  if (bitmap != NO_BITMAP)
-    w32_draw_bitmap (w, hdc, row, bitmap);
+  if (FRAME_X_LEFT_FRINGE_WIDTH (f) != 0)
+    {
+      /* Decide which bitmap to draw in the left fringe.  */
+      if (row->overlay_arrow_p)
+       bitmap = OVERLAY_ARROW_BITMAP;
+      else if (row->truncated_on_left_p)
+       bitmap = LEFT_TRUNCATION_BITMAP;
+      else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
+       bitmap = CONTINUATION_LINE_BITMAP;
+      else if (row->indicate_empty_line_p)
+       bitmap = ZV_LINE_BITMAP;
+      else
+       bitmap = NO_FRINGE_BITMAP;
 
-  /* Decide which bitmap to draw at the right side.  */
-  if (row->truncated_on_right_p)
-    bitmap = RIGHT_TRUNCATION_BITMAP;
-  else if (row->continued_p)
-    bitmap = CONTINUED_LINE_BITMAP;
-  else
-    bitmap = NO_BITMAP;
+      w32_draw_fringe_bitmap (w, hdc, row, bitmap, 1);
+    }
 
-  /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
-     the flags area.  */
-  if (bitmap == NO_BITMAP
-      || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f)
-      || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
+  if (FRAME_X_RIGHT_FRINGE_WIDTH (f) != 0)
     {
-      int right = window_box_right (w, -1);
-
-      if (header_line_height < 0)
-       header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
+      /* Decide which bitmap to draw in the right fringe.  */
+      if (row->truncated_on_right_p)
+       bitmap = RIGHT_TRUNCATION_BITMAP;
+      else if (row->continued_p)
+       bitmap = CONTINUED_LINE_BITMAP;
+      else if (row->indicate_empty_line_p && FRAME_X_LEFT_FRINGE_WIDTH (f) == 0)
+       bitmap = ZV_LINE_BITMAP;
+      else
+       bitmap = NO_FRINGE_BITMAP;
 
-      w32_fill_area (f, hdc, face->background,
-                     right,
-                     WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
-                                                      row->y)),
-                     FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f),
-                     row->visible_height);
+      w32_draw_fringe_bitmap (w, hdc, row, bitmap, 0);
     }
 
-  /* Draw the right bitmap.  */
-  if (bitmap != NO_BITMAP)
-    w32_draw_bitmap (w, hdc, row, bitmap);
-
   release_frame_dc (f, hdc);
 }
 
 \f
-/***********************************************************************
-                         Line Highlighting
- ***********************************************************************/
-
-/* External interface to control of standout mode. Not used for W32
-   frames. Aborts when called.  */
-
-static void
-w32_reassert_line_highlight (new, vpos)
-     int new, vpos;
-{
-  struct frame *f;
-
-  if (updating_frame)
-    f = updating_frame;
-  else
-    f = SELECTED_FRAME ();
-
-  if (! FRAME_W32_P (f))
-    return;
-
-  abort ();
-}
-
-/* Call this when about to modify line at position VPOS and change
-   whether it is highlighted. Not used for W32 frames.  Aborts when
-   called.  */
-
-static void
-x_change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
-     int new_highlight, vpos, y, first_unused_hpos;
-{
-  struct frame *f;
-
-  if (updating_frame)
-    f = updating_frame;
-  else
-    f = SELECTED_FRAME ();
-
-  if (! FRAME_W32_P (f))
-    return;
-
-  abort ();
-}
-
 /* This is called when starting Emacs and when restarting after
    suspend.  When starting Emacs, no window is mapped.  And nothing
    must be done to Emacs's own window if it is suspended (though that
@@ -1210,9 +1224,24 @@ w32_native_per_char_metric (font, char2b, font_type, pcm)
 
       if (retval)
        {
+#if 0
+         /* Disabled until we can find a way to get the right results
+            on all versions of Windows.  */
+
+         /* Don't trust the ABC widths.  For synthesized fonts they are
+            wrong, and so is the result of GetCharWidth()!  */
+         int real_width;
+         GetCharWidth (hdc, *char2b, *char2b, &real_width);
+#endif
          pcm->width = char_widths.abcA + char_widths.abcB + char_widths.abcC;
+#if 0
+         /* As far as I can tell, this is the best way to determine what
+            ExtTextOut will do with the broken font.  */
+         if (pcm->width != real_width)
+           pcm->width = (pcm->width + real_width) / 2;
+#endif
          pcm->lbearing = char_widths.abcA;
-         pcm->rbearing = pcm->width - char_widths.abcC;
+         pcm->rbearing = char_widths.abcA + char_widths.abcB;
          pcm->ascent = FONT_BASE (font);
          pcm->descent = FONT_DESCENT (font);
        }
@@ -1353,6 +1382,16 @@ int w32_font_is_double_byte (XFontStruct *font)
 }
 
 
+static BOOL 
+w32_use_unicode_for_codepage (codepage)
+     int codepage;
+{
+  /* If the current codepage is supported, use Unicode for output. */
+  return (w32_enable_unicode_output
+          && codepage != CP_8BIT
+          && (codepage == CP_UNICODE || IsValidCodePage (codepage)));
+}
+
 /* Encode CHAR2B using encoding information from FONT_INFO.  CHAR2B is
    the two-byte form of C.  Encoding is returned in *CHAR2B.  */
 
@@ -1424,12 +1463,13 @@ w32_encode_char (c, char2b, font_info, two_byte_p)
           *char2b = BUILD_WCHAR_T (sjis1, sjis2);
         }
     }
-  codepage = w32_codepage_for_font (font_info->name);
+  codepage = font_info->codepage;
 
   /* If charset is not ASCII or Latin-1, may need to move it into
      Unicode space.  */
   if ( font && !font->bdf && w32_use_unicode_for_codepage (codepage)
-       && charset != CHARSET_ASCII && charset != charset_latin_iso8859_1)
+       && charset != CHARSET_ASCII && charset != charset_latin_iso8859_1
+       && charset != CHARSET_8_BIT_CONTROL && charset != CHARSET_8_BIT_GRAPHIC)
     {
       char temp[3];
       temp[0] = BYTE1 (*char2b);
@@ -1694,20 +1734,23 @@ x_produce_image_glyph (it)
   prepare_image_for_display (it->f, img);
 
   it->ascent = it->phys_ascent = image_ascent (img, face);
-  it->descent = it->phys_descent = img->height + 2 * img->margin - it->ascent;
-  it->pixel_width = img->width + 2 * img->margin;
+  it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
+  it->pixel_width = img->width + 2 * img->hmargin;
 
   it->nglyphs = 1;
   
   if (face->box != FACE_NO_BOX)
     {
-      it->ascent += face->box_line_width;
-      it->descent += face->box_line_width;
+      if (face->box_line_width > 0)
+       {
+         it->ascent += face->box_line_width;
+         it->descent += face->box_line_width;
+       }
       
       if (it->start_of_box_run_p)
-       it->pixel_width += face->box_line_width;
+       it->pixel_width += abs (face->box_line_width);
       if (it->end_of_box_run_p)
-       it->pixel_width += face->box_line_width;
+       it->pixel_width += abs (face->box_line_width);
     }
 
   take_vertical_position_into_account (it);
@@ -1801,7 +1844,7 @@ x_append_stretch_glyph (it, object, width, height, ascent)
    4. `:height HEIGHT' specifies that the height of the stretch produced
    should be HEIGHT, measured in canonical character units.
 
-   5. `:relative-height FACTOR' specifies that the height of the the
+   5. `:relative-height FACTOR' specifies that the height of the
    stretch should be FACTOR times the height of the characters having
    the glyph property.
 
@@ -1822,7 +1865,10 @@ x_produce_stretch_glyph (it)
      struct it *it;
 {
   /* (space :width WIDTH :height HEIGHT.  */
-  extern Lisp_Object QCwidth, QCheight, QCascent, Qspace;
+#if GLYPH_DEBUG
+  extern Lisp_Object Qspace;
+#endif
+  extern Lisp_Object QCwidth, QCheight, QCascent;
   extern Lisp_Object QCrelative_width, QCrelative_height;
   extern Lisp_Object QCalign_to;
   Lisp_Object prop, plist;
@@ -1911,13 +1957,16 @@ x_produce_stretch_glyph (it)
 
   if (face->box != FACE_NO_BOX)
     {
-      it->ascent += face->box_line_width;
-      it->descent += face->box_line_width;
+      if (face->box_line_width > 0)
+       {
+         it->ascent += face->box_line_width;
+         it->descent += face->box_line_width;
+       }
       
       if (it->start_of_box_run_p)
-       it->pixel_width += face->box_line_width;
+       it->pixel_width += abs (face->box_line_width);
       if (it->end_of_box_run_p)
-       it->pixel_width += face->box_line_width;
+       it->pixel_width += abs (face->box_line_width);
     }
   
   take_vertical_position_into_account (it);
@@ -2006,8 +2055,7 @@ x_produce_glyphs (it)
          else if (!SINGLE_BYTE_CHAR_P (it->c)
                   && !it->multibyte_p)
            {
-             it->char_to_display = multibyte_char_to_unibyte (it->c, Qnil);
-              it->multibyte_p = 0;
+              it->multibyte_p = 1;
              it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
              face = FACE_FROM_ID (it->f, it->face_id);
            }
@@ -2075,8 +2123,13 @@ x_produce_glyphs (it)
            {
              int thick = face->box_line_width;
              
-             it->ascent += thick;
-             it->descent += thick;
+             if (thick > 0)
+               {
+                 it->ascent += thick;
+                 it->descent += thick;
+               }
+             else
+               thick = -thick;
              
              if (it->start_of_box_run_p)
                it->pixel_width += thick;
@@ -2121,11 +2174,11 @@ x_produce_glyphs (it)
          it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
          it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
       
-         if (face->box != FACE_NO_BOX)
+         if (face->box != FACE_NO_BOX
+             && face->box_line_width > 0)
            {
-             int thick = face->box_line_width;
-             it->ascent += thick;
-             it->descent += thick;
+             it->ascent += face->box_line_width;
+             it->descent += face->box_line_width;
            }
        }
       else if (it->char_to_display == '\t')
@@ -2194,12 +2247,17 @@ x_produce_glyphs (it)
           it->nglyphs = 1;
           it->ascent = FONT_BASE (font) + boff;
           it->descent = FONT_DESCENT (font) - boff;
-
          if (face->box != FACE_NO_BOX)
            {
              int thick = face->box_line_width;
-             it->ascent += thick;
-             it->descent += thick;
+
+             if (thick > 0)
+               {
+                 it->ascent += thick;
+                 it->descent += thick;
+               }
+             else
+               thick = - thick;
          
              if (it->start_of_box_run_p)
                it->pixel_width += thick;
@@ -2480,8 +2538,14 @@ x_produce_glyphs (it)
       if (face->box != FACE_NO_BOX)
        {
          int thick = face->box_line_width;
-         it->ascent += thick;
-         it->descent += thick;
+
+         if (thick > 0)
+           {
+             it->ascent += thick;
+             it->descent += thick;
+           }
+         else
+           thick = - thick;
          
          if (it->start_of_box_run_p)
            it->pixel_width += thick;
@@ -2504,8 +2568,9 @@ x_produce_glyphs (it)
   else if (it->what == IT_STRETCH)
     x_produce_stretch_glyph (it);
 
-  /* Accumulate dimensions.  */
-  xassert (it->ascent >= 0 && it->descent > 0);
+  /* Accumulate dimensions.  Note: can't assume that it->descent > 0
+     because this isn't true for images with `:ascent 100'.  */
+  xassert (it->ascent >= 0 && it->descent >= 0);
   if (it->area == TEXT_AREA)
     it->current_x += it->pixel_width;
 
@@ -2537,27 +2602,15 @@ x_estimate_mode_line_height (f, face_id)
           {
             if (face->font)
               height = FONT_HEIGHT (face->font);
-            height += 2 * face->box_line_width;
+           if (face->box_line_width > 0)
+             height += 2 * face->box_line_width;
           }
-        
       }
   
   return height;
 }
 
 \f
-
-BOOL 
-w32_use_unicode_for_codepage (codepage)
-     int codepage;
-{
-  /* If the current codepage is supported, use Unicode for output. */
-  return (w32_enable_unicode_output
-          && codepage != CP_8BIT
-          && (codepage == CP_UNICODE || IsValidCodePage (codepage)));
-}
-
-\f
 /***********************************************************************
                            Glyph display
  ***********************************************************************/
@@ -2682,7 +2735,8 @@ struct glyph_string
 
 /* Encapsulate the different ways of displaying text under W32.  */
 
-void W32_TEXTOUT (s, x, y,chars,nchars)
+static void
+w32_text_out (s, x, y,chars,nchars)
      struct glyph_string * s;
      int x, y;
      wchar_t * chars;
@@ -2696,11 +2750,11 @@ void W32_TEXTOUT (s, x, y,chars,nchars)
   else if (s->first_glyph->w32_font_type == UNICODE_FONT)
     ExtTextOutW (s->hdc, x, y, 0, NULL, chars, nchars, NULL);
   else
-    ExtTextOut (s->hdc, x, y, 0, NULL, (char *) chars,
-                nchars * charset_dim, NULL);
+    ExtTextOutA (s->hdc, x, y, 0, NULL, (char *) chars,
+                nchars * charset_dim, NULL);
 }
 
-#if 0
+#if GLYPH_DEBUG
 
 static void
 x_dump_glyph_string (s)
@@ -2739,16 +2793,16 @@ static int x_left_overwritten P_ ((struct glyph_string *));
 static int x_left_overwriting P_ ((struct glyph_string *));
 static int x_right_overwritten P_ ((struct glyph_string *));
 static int x_right_overwriting P_ ((struct glyph_string *));
-static int x_fill_glyph_string P_ ((struct glyph_string *, int, int,
-                                    int, int));
+static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
+                                    int));
 static void w32_init_glyph_string P_ ((struct glyph_string *, HDC hdc,
-                                     wchar_t *, struct window *,
-                                     struct glyph_row *,
-                                     enum glyph_row_area, int, 
-                                     enum draw_glyphs_face));
+                                       wchar_t *, struct window *,
+                                       struct glyph_row *,
+                                       enum glyph_row_area, int, 
+                                       enum draw_glyphs_face));
 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
                              enum glyph_row_area, int, int,
-                             enum draw_glyphs_face, int *, int *, int));
+                             enum draw_glyphs_face, int));
 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
@@ -2782,6 +2836,13 @@ static void w32_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
                                 int, int, int, RECT *));
 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
                                        enum glyph_row_area));
+static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
+                                           struct glyph_row *,
+                                           enum glyph_row_area, int, int));
+
+#if GLYPH_DEBUG
+static void x_check_font P_ ((struct frame *, XFontStruct *));
+#endif
 
      
 /* Append the list of glyph strings with head H and tail T to the list
@@ -2900,10 +2961,16 @@ x_set_mouse_face_gc (s)
   int face_id;
   struct face *face;
 
-  /* What face has to be used for the mouse face?  */
+  /* What face has to be used last for the mouse face?  */
   face_id = FRAME_W32_DISPLAY_INFO (s->f)->mouse_face_face_id;
   face = FACE_FROM_ID (s->f, face_id);
-  face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
+  if (face == NULL)
+    face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
+  
+  if (s->first_glyph->type == CHAR_GLYPH)
+    face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
+  else
+    face_id = FACE_FOR_CHAR (s->f, face, 0);
   s->face = FACE_FROM_ID (s->f, face_id);
   PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
 
@@ -3037,20 +3104,6 @@ w32_get_glyph_string_clip_rect (s, r)
       r_height = s->row->visible_height;
     }
 
-  /* Don't use S->y for clipping because it doesn't take partially
-     visible lines into account.  For example, it can be negative for
-     partially visible lines at the top of a window.  */
-  if (!s->row->full_width_p
-      && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
-    r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
-  else
-    r->top = max (0, s->row->y);
-
-  /* If drawing a tool-bar window, draw it over the internal border
-     at the top of the window.  */
-  if (s->w == XWINDOW (s->f->tool_bar_window))
-    r->top -= s->f->output_data.w32->internal_border_width;
-
   /* If S draws overlapping rows, it's sufficient to use the top and
      bottom of the window for clipping because this glyph string
      intentionally draws over other lines.  */
@@ -3059,7 +3112,23 @@ w32_get_glyph_string_clip_rect (s, r)
       r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
       r_height = window_text_bottom_y (s->w) - r->top;
     }
-      
+  else
+    {
+      /* Don't use S->y for clipping because it doesn't take partially
+        visible lines into account.  For example, it can be negative for
+        partially visible lines at the top of a window.  */
+      if (!s->row->full_width_p
+         && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
+       r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
+      else
+       r->top = max (0, s->row->y);
+
+      /* If drawing a tool-bar window, draw it over the internal border
+        at the top of the window.  */
+      if (s->w == XWINDOW (s->f->tool_bar_window))
+       r->top -= s->f->output_data.w32->internal_border_width;
+    }
+
   r->top = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->top);
 
   r->bottom = r->top + r_height;
@@ -3137,8 +3206,6 @@ w32_get_glyph_overhangs (hdc, glyph, f, left, right)
      struct frame *f;
      int *left, *right;
 {
-  int c;
-
   *left = *right = 0;
   
   if (glyph->type == CHAR_GLYPH)
@@ -3330,29 +3397,31 @@ x_draw_glyph_string_background (s, force_p)
      shouldn't be drawn in the first place.  */
   if (!s->background_filled_p)
     {
+      int box_line_width = max (s->face->box_line_width, 0);
+
 #if 0 /* TODO: stipple */
       if (s->stippled_p)
        {
          /* Fill background with a stipple pattern.  */
          XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
          XFillRectangle (s->display, s->window, s->gc, s->x,
-                         s->y + s->face->box_line_width,
+                         s->y + box_line_width,
                          s->background_width,
-                         s->height - 2 * s->face->box_line_width);
+                         s->height - 2 * box_line_width);
          XSetFillStyle (s->display, s->gc, FillSolid);
          s->background_filled_p = 1;
        }
       else
 #endif
-        if (FONT_HEIGHT (s->font) < s->height - 2 * s->face->box_line_width
+        if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
               || s->font_not_found_p
               || s->extends_to_end_of_line_p
                || s->font->bdf
               || force_p)
        {
-         x_clear_glyph_string_rect (s, s->x, s->y + s->face->box_line_width,
+         x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
                                     s->background_width,
-                                    s->height - 2 * s->face->box_line_width);
+                                    s->height - 2 * box_line_width);
          s->background_filled_p = 1;
        }
     }
@@ -3372,7 +3441,7 @@ x_draw_glyph_string_foreground (s)
      of S to the right of that box line.  */
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
-    x = s->x + s->face->box_line_width;
+    x = s->x + abs (s->face->box_line_width);
   else
     x = s->x;
 
@@ -3415,7 +3484,7 @@ x_draw_glyph_string_foreground (s)
           char1b[i] = BYTE2 (s->char2b[i]);
 
       /* Draw text with TextOut and friends. */
-      W32_TEXTOUT (s, x, s->ybase - boff, s->char2b, s->nchars);
+      w32_text_out (s, x, s->ybase - boff, s->char2b, s->nchars);
     }
   if (s->font && s->font->hfont)
     SelectObject (s->hdc, old_font);
@@ -3434,7 +3503,7 @@ x_draw_composite_glyph_string_foreground (s)
      of S to the right of that box line.  */
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
-    x = s->x + s->face->box_line_width;
+    x = s->x + abs (s->face->box_line_width);
   else
     x = s->x;
 
@@ -3462,7 +3531,7 @@ x_draw_composite_glyph_string_foreground (s)
   else
     {
       for (i = 0; i < s->nchars; i++, ++s->gidx)
-          W32_TEXTOUT (s, x + s->cmp->offsets[s->gidx * 2],
+          w32_text_out (s, x + s->cmp->offsets[s->gidx * 2],
                        s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
                        s->char2b + i, 1);
     }
@@ -3610,6 +3679,10 @@ x_setup_relief_colors (s)
 
   if (s->face->use_box_color_for_shadows_p)
     color = s->face->box_color;
+  else if (s->first_glyph->type == IMAGE_GLYPH
+          && s->img->pixmap
+          && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
+    color = IMAGE_BACKGROUND  (s->img, s->f, 0);
   else
     color = s->gc->background;
 
@@ -3653,47 +3726,34 @@ w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
 
   /* Top.  */
   for (i = 0; i < width; ++i)
-    {
-      w32_fill_area (f, hdc, gc.foreground,
-                     left_x + i * left_p, top_y + i,
-                     (right_x + 1 - i * right_p) - (left_x + i * left_p), 1);
-    }
+    w32_fill_area (f, hdc, gc.foreground,
+                  left_x + i * left_p, top_y + i,
+                  (right_x + 1 - i * right_p) - (left_x + i * left_p) + 1, 1);
 
   /* Left.  */
   if (left_p)
     for (i = 0; i < width; ++i)
-      {
-        w32_fill_area (f, hdc, gc.foreground,
-                       left_x + i, top_y + i, 1,
-                       (bottom_y - i) - (top_y + i));
-      }
-
-  w32_set_clip_rectangle (hdc, NULL);
+      w32_fill_area (f, hdc, gc.foreground,
+                    left_x + i, top_y + i, 1,
+                    (bottom_y - i) - (top_y + i) + 2);
 
   if (raised_p)
     gc.foreground = f->output_data.w32->black_relief.gc->foreground;
   else
     gc.foreground = f->output_data.w32->white_relief.gc->foreground;
-
-
-  w32_set_clip_rectangle (hdc, clip_rect);
   
   /* Bottom.  */
   for (i = 0; i < width; ++i)
-    {
-      w32_fill_area (f, hdc, gc.foreground, 
-                     left_x + i * left_p, bottom_y - i,
-                     (right_x + 1 - i * right_p) - left_x + i * left_p, 1);
-    }
+    w32_fill_area (f, hdc, gc.foreground, 
+                  left_x + i * left_p, bottom_y - i,
+                  (right_x - i * right_p) - (left_x + i * left_p) + 2, 1);
 
   /* Right.  */
   if (right_p)
     for (i = 0; i < width; ++i)
-      {
-        w32_fill_area (f, hdc, gc.foreground,
-                       right_x - i, top_y + i + 1, 1,
-                       (bottom_y - i) - (top_y + i + 1));
-      }
+      w32_fill_area (f, hdc, gc.foreground,
+                    right_x - i, top_y + i + 1, 1,
+                    (bottom_y - i) - (top_y + i));
 
   w32_set_clip_rectangle (hdc, NULL);
   
@@ -3758,7 +3818,7 @@ x_draw_glyph_string_box (s)
   if (s->row->full_width_p
       && !s->w->pseudo_window_p)
     {
-      last_x += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s->f);
+      last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f);
       if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
        last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
     }
@@ -3768,10 +3828,10 @@ x_draw_glyph_string_box (s)
                ? s->first_glyph
                : s->first_glyph + s->nchars - 1);
 
-  width = s->face->box_line_width;
+  width = abs (s->face->box_line_width);
   raised_p = s->face->box == FACE_RAISED_BOX;
   left_x = s->x;
-  right_x = ((s->row->full_width_p
+  right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
              ? last_x - 1
              : min (last_x, s->x + s->background_width) - 1));
   top_y = s->y;
@@ -3813,17 +3873,14 @@ x_draw_image_foreground (s)
      right of that line.  */
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
-    x = s->x + s->face->box_line_width;
+    x = s->x + abs (s->face->box_line_width);
   else
     x = s->x;
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
-  if (s->img->margin)
-    {
-      x += s->img->margin;
-      y += s->img->margin;
-    }
+  x += s->img->hmargin;
+  y += s->img->vmargin;
 
   SaveDC (s->hdc);
 
@@ -3918,22 +3975,19 @@ x_draw_image_relief (s)
      right of that line.  */
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
-    x = s->x + s->face->box_line_width;
+    x = s->x + abs (s->face->box_line_width);
   else
     x = s->x;
   
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
-  if (s->img->margin)
-    {
-      x += s->img->margin;
-      y += s->img->margin;
-    }
+  x += s->img->hmargin;
+  y += s->img->vmargin;
   
   if (s->hl == DRAW_IMAGE_SUNKEN
       || s->hl == DRAW_IMAGE_RAISED)
     {
-      thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
+      thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
       raised_p = s->hl == DRAW_IMAGE_RAISED;
     }
   else
@@ -3969,17 +4023,14 @@ w32_draw_image_foreground_1 (s, pixmap)
      right of that line.  */
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
-    x = s->face->box_line_width;
+    x = abs (s->face->box_line_width);
   else
     x = 0;
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
-  if (s->img->margin)
-    {
-      x += s->img->margin;
-      y += s->img->margin;
-    }
+  x += s->img->hmargin;
+  y += s->img->vmargin;
 
   if (s->img->pixmap)
     {
@@ -4078,7 +4129,7 @@ x_draw_glyph_string_bg_rect (s, x, y, w, h)
             |   s->face->box
             |
             |     +-------------------------
-            |     |  s->img->margin
+            |     |  s->img->vmargin
             |     |
             |     |       +-------------------
             |     |       |  the image
@@ -4090,37 +4141,38 @@ x_draw_image_glyph_string (s)
      struct glyph_string *s;
 {
   int x, y;
-  int box_line_width = s->face->box_line_width;
-  int margin = s->img->margin;
+  int box_line_hwidth = abs (s->face->box_line_width);
+  int box_line_vwidth = max (s->face->box_line_width, 0);
   int height;
   HBITMAP pixmap = 0;
 
-  height = s->height - 2 * box_line_width;
+  height = s->height - 2 * box_line_vwidth;
 
   /* Fill background with face under the image.  Do it only if row is
      taller than image or if image has a clip mask to reduce
      flickering.  */
   s->stippled_p = s->face->stipple != 0;
   if (height > s->img->height
-      || margin
+      || s->img->hmargin
+      || s->img->vmargin
 #if 0 /* TODO: image mask */
       || s->img->mask
 #endif
       || s->img->pixmap == 0
       || s->width != s->background_width)
     {
-      if (box_line_width && s->first_glyph->left_box_line_p)
-       x = s->x + box_line_width;
+      if (box_line_hwidth && s->first_glyph->left_box_line_p)
+       x = s->x + box_line_hwidth;
       else
        x = s->x;
       
-      y = s->y + box_line_width;
+      y = s->y + box_line_vwidth;
 #if 0 /* TODO: image mask */
       if (s->img->mask)
        {
-         /* Create a pixmap as large as the glyph string Fill it with
-            the background color.  Copy the image to it, using its
-            mask.  Copy the temporary pixmap to the display.  */
+         /* Create a pixmap as large as the glyph string.  Fill it
+            with the background color.  Copy the image to it, using
+            its mask.  Copy the temporary pixmap to the display.  */
          Screen *screen = FRAME_X_SCREEN (s->f);
          int depth = DefaultDepthOfScreen (screen);
 
@@ -4228,6 +4280,16 @@ x_draw_stretch_glyph_string (s)
          int w = s->background_width - width, h = s->height;
          RECT r;
           HDC hdc = s->hdc;
+
+         if (s->row->mouse_face_p
+             && cursor_in_mouse_face_p (s->w))
+           {
+             x_set_mouse_face_gc (s);
+             gc = s->gc;
+           }
+         else
+           gc = s->face->gc;
+  
          w32_get_glyph_string_clip_rect (s, &r);
          w32_set_clip_rectangle (hdc, &r);
 
@@ -4246,7 +4308,7 @@ x_draw_stretch_glyph_string (s)
             }
         }
     }
-  else
+  else if (!s->background_filled_p)
     x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
                                 s->height);
   
@@ -4260,6 +4322,8 @@ static void
 x_draw_glyph_string (s)
      struct glyph_string *s;
 {
+  int relief_drawn_p = 0;
+
   /* If S draws into the background of its successor, draw the
      background of the successor first so that S can draw into it.
      This makes S->next use XDrawString instead of XDrawImageString.  */
@@ -4273,7 +4337,23 @@ x_draw_glyph_string (s)
 
   /* Set up S->gc, set clipping and draw S.  */
   x_set_glyph_string_gc (s);
-  x_set_glyph_string_clipping (s);
+
+  /* Draw relief (if any) in advance for char/composition so that the
+     glyph string can be drawn over it.  */
+  if (!s->for_overlaps_p
+      && s->face->box != FACE_NO_BOX
+      && (s->first_glyph->type == CHAR_GLYPH
+         || s->first_glyph->type == COMPOSITE_GLYPH))
+
+    {
+      x_set_glyph_string_clipping (s);
+      x_draw_glyph_string_background (s, 1);
+      x_draw_glyph_string_box (s);
+      x_set_glyph_string_clipping (s);
+      relief_drawn_p = 1;
+    }
+  else
+    x_set_glyph_string_clipping (s);
 
   switch (s->first_glyph->type)
     {
@@ -4314,6 +4394,8 @@ x_draw_glyph_string (s)
           unsigned long h = 1;
           unsigned long dy = s->height - h;
 
+         /* TODO: Use font information for positioning and thickness
+            of underline.  See OUTLINETEXTMETRIC, and xterm.c.  */
           if (s->face->underline_defaulted_p)
             {
               w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
@@ -4363,7 +4445,7 @@ x_draw_glyph_string (s)
         }
 
       /* Draw relief.  */
-      if (s->face->box != FACE_NO_BOX)
+      if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
         x_draw_glyph_string_box (s);
     }
 
@@ -4376,11 +4458,12 @@ static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
                                              struct face **, int));
 
 
-/* Load glyph string S with a composition components specified by S->cmp.
+/* Fill glyph string S with composition components specified by S->cmp.
+   
    FACES is an array of faces for all components of this composition.
    S->gidx is the index of the first component for S.
    OVERLAPS_P non-zero means S should draw the foreground only, and
-   use its lines physical height for clipping.
+   use its physical height for clipping.
 
    Value is the index of a component not in S.  */
 
@@ -4434,11 +4517,12 @@ x_fill_composite_glyph_string (s, faces, overlaps_p)
 }
 
 
-/* Load glyph string S with a sequence of characters.
+/* Fill glyph string S from a sequence of character glyphs.
+   
    FACE_ID is the face id of the string.  START is the index of the
    first glyph to consider, END is the index of the last + 1.
    OVERLAPS_P non-zero means S should draw the foreground only, and
-   use its lines physical height for clipping.
+   use its physical height for clipping.
 
    Value is the index of the first glyph not in S.  */
 
@@ -4561,7 +4645,7 @@ x_fill_stretch_glyph_string (s, row, area, start, end)
   /* Adjust base line for subscript/superscript text.  */
   s->ybase += voffset;
 
-  xassert (s->face && s->face->gc);
+  xassert (s->face);
   return glyph - s->row->glyphs[s->area];
 }
 
@@ -4621,10 +4705,15 @@ x_set_glyph_string_background_width (s, start, last_x)
   struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
   
   if (start == s->row->used[s->area]
-      && s->hl == DRAW_NORMAL_TEXT
-      && ((s->area == TEXT_AREA && s->row->fill_line_p)
-         || s->face->background != default_face->background
-         || s->face->stipple != default_face->stipple))
+      && s->area == TEXT_AREA
+      && ((s->hl == DRAW_NORMAL_TEXT
+          && (s->row->fill_line_p
+              || s->face->background != default_face->background
+              || s->face->stipple != default_face->stipple
+              || s->row->mouse_face_p))
+         || s->hl == DRAW_MOUSE_FACE
+         || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
+             && s->row->fill_line_p)))
     s->extends_to_end_of_line_p = 1;
   
   /* If S extends its face to the end of the line, set its
@@ -4826,27 +4915,19 @@ x_set_glyph_string_background_width (s, start, last_x)
    DRAW_IMAGE_SUNKEN   draw an image with a sunken relief around it
    DRAW_IMAGE_RAISED   draw an image with a raised relief around it
 
-   If REAL_START is non-null, return in *REAL_START the real starting
-   position for display.  This can be different from START in case
-   overlapping glyphs must be displayed.  If REAL_END is non-null,
-   return in *REAL_END the real end position for display.  This can be
-   different from END in case overlapping glyphs must be displayed.
-
    If OVERLAPS_P is non-zero, draw only the foreground of characters
    and clip to the physical height of ROW.
 
    Value is the x-position reached, relative to AREA of W.  */
      
 static int
-x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
-               overlaps_p)
+x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
      struct window *w;
      int x;
      struct glyph_row *row;
      enum glyph_row_area area;
      int start, end;
      enum draw_glyphs_face hl;
-     int *real_start, *real_end;
      int overlaps_p;
 {
   struct glyph_string *head, *tail;
@@ -4861,19 +4942,13 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
   start = max (0, start);
   start = min (end, start);
 
-  if (real_start)
-    *real_start = start;
-  if (real_end)
-    *real_end = end;
-
   /* Translate X to frame coordinates.  Set last_x to the right
      end of the drawing area.  */
   if (row->full_width_p)
     {
       /* X is relative to the left edge of W, without scroll bars
-        or flag areas.  */
+        or fringes.  */
       struct frame *f = XFRAME (WINDOW_FRAME (w));
-      /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
       int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
 
       x += window_left_x;
@@ -4936,8 +5011,6 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
                               DRAW_NORMAL_TEXT, dummy_x, last_x,
                                overlaps_p);
          start = i;
-         if (real_start)
-           *real_start = start;
          x_compute_overhangs_and_x (t, head->x, 1);
          x_prepend_glyph_string_lists (&head, &tail, h, t);
        }
@@ -4957,8 +5030,6 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
                                overlaps_p);
          for (s = h; s; s = s->next)
            s->background_filled_p = 1;
-         if (real_start)
-           *real_start = i;
          x_compute_overhangs_and_x (t, head->x, 1);
          x_prepend_glyph_string_lists (&head, &tail, h, t);
        }
@@ -4975,8 +5046,6 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
                                overlaps_p);
          x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
          x_append_glyph_string_lists (&head, &tail, h, t);
-         if (real_end)
-           *real_end = i;
        }
 
       /* Append glyph strings for glyphs following the last glyph
@@ -4994,8 +5063,6 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
            s->background_filled_p = 1;
          x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
          x_append_glyph_string_lists (&head, &tail, h, t);
-         if (real_end)
-           *real_end = i;
        }
     }
 
@@ -5003,6 +5070,30 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
   for (s = head; s; s = s->next)
     x_draw_glyph_string (s);
 
+  if (area == TEXT_AREA
+      && !row->full_width_p
+      /* When drawing overlapping rows, only the glyph strings'
+        foreground is drawn, which doesn't erase a cursor
+        completely. */
+      && !overlaps_p)
+    {
+      int x0 = head ? head->x : x;
+      int x1 = tail ? tail->x + tail->background_width : x;
+      
+      x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0);
+      x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1);
+      
+      if (!row->full_width_p && XFASTINT (w->left_margin_width) != 0)
+       {
+         int left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
+         x0 -= left_area_width;
+         x1 -= left_area_width;
+       }
+
+      notice_overwritten_cursor (w, area, x0, x1,
+                                row->y, MATRIX_ROW_BOTTOM_Y (row));
+    }
+
   /* Value is the x-position up to which drawn, relative to AREA of W.
      This doesn't include parts drawn because of overhangs.  */
   x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
@@ -5055,9 +5146,7 @@ x_fix_overlapping_area (w, row, area)
                 && row->glyphs[area][i].overlaps_vertically_p);
 
          x_draw_glyphs (w, start_x, row, area, start, i,
-                        (row->inverse_p
-                         ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
-                        NULL, NULL, 1);
+                        DRAW_NORMAL_TEXT, 1);
        }
       else
        {
@@ -5081,7 +5170,7 @@ x_write_glyphs (start, len)
      struct glyph *start;
      int len;
 {
-  int x, hpos, real_start, real_end;
+  int x, hpos;
 
   xassert (updated_window && updated_row);
   BLOCK_INPUT;
@@ -5092,13 +5181,7 @@ x_write_glyphs (start, len)
   x = x_draw_glyphs (updated_window, output_cursor.x,
                     updated_row, updated_area,
                     hpos, hpos + len,
-                    (updated_row->inverse_p
-                     ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
-                    &real_start, &real_end, 0);
-
-  /* If we drew over the cursor, note that it is not visible any more.  */
-  note_overwritten_text_cursor (updated_window, real_start,
-                               real_end - real_start);
+                    DRAW_NORMAL_TEXT, 0);
 
   UNBLOCK_INPUT;
   
@@ -5120,7 +5203,7 @@ x_insert_glyphs (start, len)
   int line_height, shift_by_width, shifted_region_width;
   struct glyph_row *row;
   struct glyph *glyph;
-  int frame_x, frame_y, hpos, real_start, real_end;
+  int frame_x, frame_y, hpos;
   HDC hdc;
 
   xassert (updated_window && updated_row);
@@ -5144,7 +5227,7 @@ x_insert_glyphs (start, len)
                          - shift_by_width);
 
   /* Shift right.  */
-  frame_x = WINDOW_TO_FRAME_PIXEL_X (w, output_cursor.x);
+  frame_x = window_box_left (w, updated_area) + output_cursor.x;
   frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
   BitBlt (hdc, frame_x + shift_by_width, frame_y,
           shifted_region_width, line_height,
@@ -5153,9 +5236,8 @@ x_insert_glyphs (start, len)
   /* Write the glyphs.  */
   hpos = start - row->glyphs[updated_area];
   x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
-                DRAW_NORMAL_TEXT, &real_start, &real_end, 0);
-  note_overwritten_text_cursor (w, real_start, real_end - real_start);
-  
+                DRAW_NORMAL_TEXT, 0);
+
   /* Advance the output cursor.  */
   output_cursor.hpos += len;
   output_cursor.x += shift_by_width;
@@ -5229,10 +5311,13 @@ x_clear_end_of_line (to_x)
   
   /* Notice if the cursor will be cleared by this operation.  */
   if (!updated_row->full_width_p)
-    note_overwritten_text_cursor (w, output_cursor.hpos, -1);
+    notice_overwritten_cursor (w, updated_area,
+                              output_cursor.x, -1,
+                              updated_row->y,
+                              MATRIX_ROW_BOTTOM_Y (updated_row));
 
   from_x = output_cursor.x;
-     
+
   /* Translate to frame coordinates.  */
   if (updated_row->full_width_p)
     {
@@ -5308,12 +5393,9 @@ w32_ring_bell (void)
 
   f = SELECTED_FRAME ();
 
-  if (! FRAME_W32_P (f))
-    return;
-
   BLOCK_INPUT;
 
-  if (visible_bell)
+  if (FRAME_W32_P (f) && visible_bell)
     {
       int i;
       HWND hwnd = FRAME_W32_WINDOW (SELECTED_FRAME ());
@@ -5380,14 +5462,15 @@ x_scroll_run (w, run)
 {
   struct frame *f = XFRAME (w->frame);
   int x, y, width, height, from_y, to_y, bottom_y;
-  HDC hdc = get_frame_dc (f);
+  HWND hwnd = FRAME_W32_WINDOW (f);
+  HRGN expect_dirty;
 
   /* Get frame-relative bounding box of the text display area of W,
-     without mode lines.  Include in this box the flags areas to the
-     left and right of W.  */
+     without mode lines.  Include in this box the left and right
+     fringes of W.  */
   window_box (w, -1, &x, &y, &width, &height);
-  width += FRAME_X_FLAGS_AREA_WIDTH (f);
-  x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
+  width += FRAME_X_FRINGE_WIDTH (f);
+  x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
 
   from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
   to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
@@ -5401,6 +5484,7 @@ x_scroll_run (w, run)
        height = bottom_y - from_y;
       else
        height = run->height;
+      expect_dirty = CreateRectRgn (x, y + height, x + width, bottom_y);
     }
   else
     {
@@ -5410,6 +5494,7 @@ x_scroll_run (w, run)
        height = bottom_y - to_y;
       else
        height = run->height;
+      expect_dirty = CreateRectRgn (x, y, x + width, to_y);
     }
 
   BLOCK_INPUT;
@@ -5418,10 +5503,32 @@ x_scroll_run (w, run)
   updated_window = w;
   x_clear_cursor (w);
 
-  BitBlt (hdc, x, to_y, width, height, hdc, x, from_y, SRCCOPY);
-  
+  {
+    RECT from;
+    RECT to;
+    HRGN dirty = CreateRectRgn (0, 0, 0, 0);
+    HRGN combined = CreateRectRgn (0, 0, 0, 0);
+
+    from.left = to.left = x;
+    from.right = to.right = x + width;
+    from.top = from_y;
+    from.bottom = from_y + height;
+    to.top = y;
+    to.bottom = bottom_y;
+
+    ScrollWindowEx (hwnd, 0, to_y - from_y, &from, &to, dirty,
+                   NULL, SW_INVALIDATE);
+
+    /* Combine this with what we expect to be dirty. This covers the
+       case where not all of the region we expect is actually dirty.  */
+    CombineRgn (combined, dirty, expect_dirty, RGN_OR);
+
+    /* If the dirty region is not what we expected, redraw the entire frame.  */
+    if (!EqualRgn (combined, expect_dirty))
+      SET_FRAME_GARBAGED (f);
+  }
+
   UNBLOCK_INPUT;
-  release_frame_dc (f, hdc);
 }
 
 
@@ -5441,6 +5548,7 @@ expose_frame (f, x, y, w, h)
      int x, y, w, h;
 {
   RECT r;
+  int mouse_face_overwritten_p = 0;
 
   TRACE ((stderr, "expose_frame "));
 
@@ -5476,23 +5584,35 @@ expose_frame (f, x, y, w, h)
     }
 
   TRACE ((stderr, "(%d, %d, %d, %d)\n", r.left, r.top, r.right, r.bottom));
-  expose_window_tree (XWINDOW (f->root_window), &r);
+  mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
 
   if (WINDOWP (f->tool_bar_window))
+    mouse_face_overwritten_p
+      |= expose_window (XWINDOW (f->tool_bar_window), &r);
+
+  /* Some window managers support a focus-follows-mouse style with
+     delayed raising of frames.  Imagine a partially obscured frame,
+     and moving the mouse into partially obscured mouse-face on that
+     frame.  The visible part of the mouse-face will be highlighted,
+     then the WM raises the obscured frame.  With at least one WM, KDE
+     2.1, Emacs is not getting any event for the raising of the frame
+     (even tried with SubstructureRedirectMask), only Expose events.
+     These expose events will draw text normally, i.e. not
+     highlighted.  Which means we must redo the highlight here.
+     Subsume it under ``we love X''.  --gerd 2001-08-15  */
+  /* Included in Windows version because Windows most likely does not
+     do the right thing if any third party tool offers
+     focus-follows-mouse with delayed raise.  --jason 2001-10-12  */
+  if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
     {
-      struct window *w = XWINDOW (f->tool_bar_window);
-      RECT window_rect;
-      RECT intersection_rect;
-      int window_x, window_y, window_width, window_height;
-
-      window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
-      window_rect.left = window_x;
-      window_rect.top = window_y;
-      window_rect.right = window_x + window_width;
-      window_rect.bottom = window_y + window_height;
-
-      if (IntersectRect (&intersection_rect, &r, &window_rect))
-       expose_window (w, &intersection_rect);
+      struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
+      if (f == dpyinfo->mouse_face_mouse_frame)
+       {
+         int x = dpyinfo->mouse_face_mouse_x;
+         int y = dpyinfo->mouse_face_mouse_y;
+         clear_mouse_face (dpyinfo);
+         note_mouse_highlight (f, x, y);
+       }
     }
 }
 
@@ -5500,45 +5620,29 @@ expose_frame (f, x, y, w, h)
 /* Redraw (parts) of all windows in the window tree rooted at W that
    intersect R.  R contains frame pixel coordinates.  */
 
-static void
+static int
 expose_window_tree (w, r)
      struct window *w;
      RECT *r;
 {
-  while (w)
+  struct frame *f = XFRAME (w->frame);
+  int mouse_face_overwritten_p = 0;
+
+  while (w && !FRAME_GARBAGED_P (f))
     {
       if (!NILP (w->hchild))
-       expose_window_tree (XWINDOW (w->hchild), r);
+       mouse_face_overwritten_p
+         |= expose_window_tree (XWINDOW (w->hchild), r);
       else if (!NILP (w->vchild))
-       expose_window_tree (XWINDOW (w->vchild), r);
+       mouse_face_overwritten_p
+         |= expose_window_tree (XWINDOW (w->vchild), r);
       else
-       {
-         RECT window_rect;
-         RECT intersection_rect;
-         struct frame *f = XFRAME (w->frame);
-         int window_x, window_y, window_width, window_height;
-
-         /* Frame-relative pixel rectangle of W.  */
-         window_box (w, -1, &window_x, &window_y, &window_width,
-                     &window_height);
-         window_rect.left
-           = (window_x
-              - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
-              - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_Y_UNIT (f));
-         window_rect.top = window_y;
-         window_rect.right = window_rect.left
-           + (window_width
-              + FRAME_X_FLAGS_AREA_WIDTH (f)
-              + FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
-         window_rect.bottom = window_rect.top
-           + window_height + CURRENT_MODE_LINE_HEIGHT (w);
-
-         if (IntersectRect (&intersection_rect, r, &window_rect))
-           expose_window (w, &intersection_rect);
-       }
+       mouse_face_overwritten_p |= expose_window (w, r);
 
-      w = NILP (w->next) ? 0 : XWINDOW (w->next);
+      w = NILP (w->next) ? NULL : XWINDOW (w->next);
     }
+
+  return mouse_face_overwritten_p;
 }
 
 
@@ -5557,23 +5661,11 @@ expose_area (w, row, r, area)
   struct glyph *last;
   int first_x, start_x, x;
 
-  /* Set x to the window-relative start position for drawing glyphs of
-     AREA.  The first glyph of the text area can be partially visible.
-     The first glyphs of other areas cannot.  */
-  if (area == LEFT_MARGIN_AREA)
-    x = 0;
-  else if (area == TEXT_AREA)
-    x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
-  else
-    x = (window_box_width (w, LEFT_MARGIN_AREA)
-        + window_box_width (w, TEXT_AREA));
-
   if (area == TEXT_AREA && row->fill_line_p)
     /* If row extends face to end of line write the whole line.  */
-    x_draw_glyphs (w, x, row, area,
+    x_draw_glyphs (w, 0, row, area,
                   0, row->used[area],
-                  row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
-                  NULL, NULL, 0);
+                  DRAW_NORMAL_TEXT, 0);
   else
     {
       /* Set START_X to the window-relative start position for drawing glyphs of
@@ -5611,16 +5703,16 @@ expose_area (w, row, r, area)
         x_draw_glyphs (w, first_x - start_x, row, area,
                        first - row->glyphs[area],
                        last - row->glyphs[area],
-                       row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
-                       NULL, NULL, 0);
+                       DRAW_NORMAL_TEXT, 0);
     }
 }
 
 
 /* Redraw the parts of the glyph row ROW on window W intersecting
-   rectangle R.  R is in window-relative coordinates.  */
+   rectangle R.  R is in window-relative coordinates.  Value is
+   non-zero if mouse face was overwritten.  */
 
-static void
+static int
 expose_line (w, row, r)
      struct window *w;
      struct glyph_row *row;
@@ -5630,8 +5722,7 @@ expose_line (w, row, r)
   
   if (row->mode_line_p || w->pseudo_window_p)
     x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
-                  row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
-                  NULL, NULL, 0);
+                  DRAW_NORMAL_TEXT, 0);
   else
     {
       if (row->used[LEFT_MARGIN_AREA])
@@ -5640,8 +5731,10 @@ expose_line (w, row, r)
        expose_area (w, row, r, TEXT_AREA);
       if (row->used[RIGHT_MARGIN_AREA])
        expose_area (w, row, r, RIGHT_MARGIN_AREA);
-      x_draw_row_bitmaps (w, row);
+      x_draw_row_fringe_bitmaps (w, row);
     }
+
+  return row->mouse_face_p;
 }
 
 
@@ -5669,82 +5762,110 @@ x_phys_cursor_in_rect_p (w, r)
 }
 
 
-/* Redraw a rectangle of window W.  R is a rectangle in window
-   relative coordinates.  Call this function with input blocked.  */
+/* Redraw the part of window W intersection rectagle FR.  Pixel
+   coordinates in FR are frame relative.  Call this function with
+   input blocked.  Value is non-zero if the exposure overwrites
+   mouse-face.  */
 
-static void
-expose_window (w, r)
+static int
+expose_window (w, fr)
      struct window *w;
-     RECT *r;
+     RECT *fr;
 {
-  struct glyph_row *row;
-  int y;
-  int yb = window_text_bottom_y (w);
-  int cursor_cleared_p;
+  struct frame *f = XFRAME (w->frame);
+  RECT wr, r;
+  int mouse_face_overwritten_p = 0;
 
   /* If window is not yet fully initialized, do nothing.  This can
      happen when toolkit scroll bars are used and a window is split.
      Reconfiguring the scroll bar will generate an expose for a newly
      created window.  */
-  if (w->current_matrix == NULL || w == updated_window)
-    return;
-
-  TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
-         r->left, r->top, r->right, r->bottom));
-
-  /* Convert to window coordinates.  */
-  r->left = FRAME_TO_WINDOW_PIXEL_X (w, r->left);
-  r->top = FRAME_TO_WINDOW_PIXEL_Y (w, r->top);
-  r->right = FRAME_TO_WINDOW_PIXEL_X (w, r->right);
-  r->bottom = FRAME_TO_WINDOW_PIXEL_Y (w, r->bottom);
+  if (w->current_matrix == NULL)
+    return 0;
 
-  /* Turn off the cursor.  */
-  if (!w->pseudo_window_p
-      && x_phys_cursor_in_rect_p (w, r))
+  /* When we're currently updating the window, display and current
+     matrix usually don't agree.  Arrange for a thorough display
+     later.  */
+  if (w == updated_window)
     {
-      x_clear_cursor (w);
-      cursor_cleared_p = 1;
+      SET_FRAME_GARBAGED (f);
+      return 0;
     }
-  else
-    cursor_cleared_p = 0;
 
-  /* Find the first row intersecting the rectangle R.  */
-  row = w->current_matrix->rows;
-  y = 0;
-  while (row->enabled_p
-        && y < yb
-        && y + row->height < r->top)
-    {
-      y += row->height;
-      ++row;
-    }
-       
-  /* Display the text in the rectangle, one text line at a time.  */
-  while (row->enabled_p
-        && y < yb
-        && y < r->bottom)
+  /* Frame-relative pixel rectangle of W.  */
+  wr.left = XFASTINT (w->left) * CANON_X_UNIT (f);
+  wr.top = XFASTINT (w->top) * CANON_Y_UNIT (f);
+  wr.right = wr.left + XFASTINT (w->width) * CANON_X_UNIT (f);
+  wr.bottom = wr.top + XFASTINT (w->height) * CANON_Y_UNIT (f);
+
+  if (IntersectRect(&r, fr, &wr))
     {
-      expose_line (w, row, r);
-      y += row->height;
-      ++row;
-    }
+      int yb = window_text_bottom_y (w);
+      struct glyph_row *row;
+      int cursor_cleared_p;
 
-  /* Display the mode line if there is one.  */
-  if (WINDOW_WANTS_MODELINE_P (w)
-      && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
-         row->enabled_p)
-      && row->y < r->bottom)
-    expose_line (w, row, r);
+      TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
+             r.left, r.top, r.right, r.bottom));
 
-  if (!w->pseudo_window_p)
-    {
-      /* Draw border between windows.  */
-      x_draw_vertical_border (w);
-      
-      /* Turn the cursor on again.  */
-      if (cursor_cleared_p)
-       x_update_window_cursor (w, 1);
+      /* Convert to window coordinates.  */
+      r.left = FRAME_TO_WINDOW_PIXEL_X (w, r.left);
+      r.right = FRAME_TO_WINDOW_PIXEL_X (w, r.right);
+      r.top = FRAME_TO_WINDOW_PIXEL_Y (w, r.top);
+      r.bottom = FRAME_TO_WINDOW_PIXEL_Y (w, r.bottom);
+
+      /* Turn off the cursor.  */
+      if (!w->pseudo_window_p
+         && x_phys_cursor_in_rect_p (w, &r))
+       {
+         x_clear_cursor (w);
+         cursor_cleared_p = 1;
+       }
+      else
+       cursor_cleared_p = 0;
+
+      /* Find the first row intersecting the rectangle R.  */
+      for (row = w->current_matrix->rows;
+          row->enabled_p;
+          ++row)
+       {
+         int y0 = row->y;
+         int y1 = MATRIX_ROW_BOTTOM_Y (row);
+
+         if ((y0 >= r.top && y0 < r.bottom)
+             || (y1 > r.top && y1 < r.bottom)
+             || (r.top >= y0 && r.top < y1)
+             || (r.bottom > y0 && r.bottom < y1))
+           {
+             if (expose_line (w, row, &r))
+               mouse_face_overwritten_p = 1;
+           }
+
+         if (y1 >= yb)
+           break;
+       }
+
+      /* Display the mode line if there is one.  */
+      if (WINDOW_WANTS_MODELINE_P (w)
+         && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
+             row->enabled_p)
+         && row->y < r.bottom)
+       {
+         if (expose_line (w, row, &r))
+           mouse_face_overwritten_p = 1;
+       }
+
+      if (!w->pseudo_window_p)
+       {
+         /* Draw border between windows.  */
+         x_draw_vertical_border (w);
+
+         /* Turn the cursor on again.  */
+         if (cursor_cleared_p)
+           x_update_window_cursor (w, 1);
+       }
     }
+
+  return mouse_face_overwritten_p;
 }
 
 \f
@@ -5816,7 +5937,6 @@ w32_frame_rehighlight (frame)
 {
   if (! FRAME_W32_P (frame))
     return;
-
   x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame));
 }
 
@@ -5972,9 +6092,13 @@ glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
   return success_p;
 }
 
+/* Parse a button MESSAGE. The button index is returned in PBUTTON, and
+   the state in PUP. XBUTTON provides extra information for extended mouse
+   button messages. Returns FALSE if unable to parse the message.  */
 BOOL 
-parse_button (message, pbutton, pup)
+parse_button (message, xbutton, pbutton, pup)
      int message;
+     int xbutton;
      int * pbutton;
      int * pup;
 {
@@ -6019,6 +6143,14 @@ parse_button (message, pbutton, pup)
        button = 1;
       up = 1;
       break;
+    case WM_XBUTTONDOWN:
+      button = xbutton + 2;
+      up = 0;
+      break;
+    case WM_XBUTTONUP:
+      button = xbutton + 2;
+      up = 1;
+      break;
     default:
       return (FALSE);
     }
@@ -6044,7 +6176,8 @@ construct_mouse_click (result, msg, f)
   int button;
   int up;
 
-  parse_button (msg->msg.message, &button, &up);
+  parse_button (msg->msg.message, HIWORD (msg->msg.wParam),
+               &button, &up);
 
   /* Make the event type no_event; we'll change that when we decide
      otherwise.  */
@@ -6148,15 +6281,40 @@ construct_drag_n_drop (result, msg, f)
 static MSG last_mouse_motion_event;
 static Lisp_Object last_mouse_motion_frame;
 
+static void remember_mouse_glyph P_ ((struct frame *, int, int));
+
 static void
 note_mouse_movement (frame, msg)
      FRAME_PTR frame;
      MSG *msg;
 {
+  int mouse_x = LOWORD (msg->lParam);
+  int mouse_y = HIWORD (msg->lParam);
+
   last_mouse_movement_time = msg->time;
   memcpy (&last_mouse_motion_event, msg, sizeof (last_mouse_motion_event));
   XSETFRAME (last_mouse_motion_frame, frame);
 
+  if (x_autoselect_window_p)
+    {
+      int area;
+      Lisp_Object window;
+      static Lisp_Object last_window;
+
+      window = window_from_coordinates (frame, mouse_x, mouse_y, &area, 0);
+
+      /* Window will be selected only when it is not selected now and
+        last mouse movement event was not in it.  Minubuffer window
+        will be selected iff it is active.  */
+      if (!EQ (window, last_window)
+         && !EQ (window, selected_window)
+         && (!MINI_WINDOW_P (XWINDOW (window))
+             || (EQ (window, minibuf_window) && minibuf_level > 0)))
+       Fselect_window (window);
+
+      last_window=window;
+    }
+
   if (msg->hwnd != FRAME_W32_WINDOW (frame))
     {
       frame->mouse_moved = 1;
@@ -6165,23 +6323,22 @@ note_mouse_movement (frame, msg)
     }
 
   /* Has the mouse moved off the glyph it was on at the last sighting?  */
-  else if (LOWORD (msg->lParam) < last_mouse_glyph.left
-          || LOWORD (msg->lParam) > last_mouse_glyph.right
-          || HIWORD (msg->lParam) < last_mouse_glyph.top
-          || HIWORD (msg->lParam) > last_mouse_glyph.bottom)
+  else if (mouse_x < last_mouse_glyph.left
+          || mouse_x > last_mouse_glyph.right
+          || mouse_y < last_mouse_glyph.top
+          || mouse_y > last_mouse_glyph.bottom)
     {
       frame->mouse_moved = 1;
       last_mouse_scroll_bar = Qnil;
-
-      note_mouse_highlight (frame, LOWORD (msg->lParam), HIWORD (msg->lParam));
+      note_mouse_highlight (frame, mouse_x, mouse_y);
+      /* Remember the mouse position here, as w32_mouse_position only
+        gets called when mouse tracking is enabled but we also need
+        to keep track of the mouse for help_echo and highlighting at
+        other times.  */
+      remember_mouse_glyph (frame, mouse_x, mouse_y);
     }
 }
 
-/* This is used for debugging, to turn off note_mouse_highlight.  */
-
-int disable_mouse_highlight;
-
-
 \f
 /************************************************************************
                              Mouse Face
@@ -6196,10 +6353,11 @@ int disable_mouse_highlight;
    date.  */
 
 static struct glyph *
-x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
+x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
      struct window *w;
      int x, y;
      int *hpos, *vpos, *area;
+     int buffer_only_p;
 {
   struct glyph *glyph, *end;
   struct glyph_row *row = NULL;
@@ -6257,7 +6415,7 @@ x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
        {
          if (w->pseudo_window_p)
            break;
-         else if (BUFFERP (glyph->object))
+         else if (!buffer_only_p || BUFFERP (glyph->object))
            break;
        }
       
@@ -6297,10 +6455,10 @@ frame_to_window_pixel_xy (w, x, y)
 }
 
 
-/* Take proper action when mouse has moved to the mode or top line of
+/* Take proper action when mouse has moved to the mode or header line of
    window W, x-position X.  MODE_LINE_P non-zero means mouse is on the
    mode line.  X is relative to the start of the text display area of
-   W, so the width of bitmap areas and scroll bars must be subtracted
+   W, so the width of fringes and scroll bars must be subtracted
    to get a position relative to the start of the mode line.  */
 
 static void
@@ -6328,7 +6486,8 @@ note_mode_line_highlight (w, x, mode_line_p)
       glyph = row->glyphs[TEXT_AREA];
       end = glyph + row->used[TEXT_AREA];
       x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
-             + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
+             + FRAME_X_LEFT_FRINGE_WIDTH (f));
+      
       while (glyph < end
             && x >= x0 + glyph->pixel_width)
        {
@@ -6360,6 +6519,13 @@ note_mode_line_highlight (w, x, mode_line_p)
                                    Qlocal_map, glyph->object);
          if (KEYMAPP (map))
            cursor = f->output_data.w32->nontext_cursor;
+         else
+           {
+             map = Fget_text_property (make_number (glyph->charpos),
+                                       Qkeymap, glyph->object);
+             if (KEYMAPP (map))
+               cursor = f->output_data.w32->nontext_cursor;
+           }
        }
     }
 
@@ -6383,12 +6549,13 @@ note_mouse_highlight (f, x, y)
   int portion;
   Lisp_Object window;
   struct window *w;
+  struct buffer *b;
 
   /* When a menu is active, don't highlight because this looks odd. */
   if (popup_activated ())
     return;
 
-  if (disable_mouse_highlight
+  if (NILP (Vmouse_highlight)
       || !f->glyphs_initialized_p)
     return;
 
@@ -6416,6 +6583,9 @@ note_mouse_highlight (f, x, y)
   if (!WINDOWP (window))
     return;
 
+  /* Reset help_echo. It will get recomputed below.  */
+  help_echo = Qnil;
+
   /* Convert to window-relative pixel coordinates.  */
   w = XWINDOW (window);
   frame_to_window_pixel_xy (w, &x, &y);
@@ -6428,35 +6598,38 @@ note_mouse_highlight (f, x, y)
       return;
     }
 
+  /* Mouse is on the mode or header line?  */
   if (portion == 1 || portion == 3)
     {
-      /* Mouse is on the mode or top line.  */
       note_mode_line_highlight (w, x, portion == 1);
       return;
     }
 #if 0 /* TODO: mouse cursor */
-  else if (portion == 2)
-    XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                  f->output_data.x->horizontal_drag_cursor);
+  if (portion == 2)
+    cursor = f->output_data.x->horizontal_drag_cursor;
   else
-    XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                  f->output_data.x->text_cursor);
+    cursor = f->output_data.x->text_cursor;
 #endif
-
   /* Are we in a window whose display is up to date?
      And verify the buffer's text has not changed.  */
+  b = XBUFFER (w->buffer);
   if (/* Within text portion of the window.  */
       portion == 0
       && EQ (w->window_end_valid, w->buffer)
-      && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
-      && (XFASTINT (w->last_overlay_modified)
-         == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
+      && XFASTINT (w->last_modified) == BUF_MODIFF (b)
+      && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
     {
       int hpos, vpos, pos, i, area;
       struct glyph *glyph;
+      Lisp_Object object;
+      Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
+      Lisp_Object *overlay_vec = NULL;
+      int len, noverlays;
+      struct buffer *obuf;
+      int obegv, ozv, same_region;
 
       /* Find the glyph under X/Y.  */
-      glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area);
+      glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
 
       /* Clear mouse face if X/Y not over text.  */
       if (glyph == NULL
@@ -6464,197 +6637,333 @@ note_mouse_highlight (f, x, y)
          || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
        {
          clear_mouse_face (dpyinfo);
-         return;
+         /* TODO: mouse cursor */
+         goto set_cursor;
        }
 
       pos = glyph->charpos;
-      xassert (w->pseudo_window_p || BUFFERP (glyph->object));
+      object = glyph->object;
+      if (!STRINGP (object) && !BUFFERP (object))
+       goto set_cursor;
+
+      /* If we get an out-of-range value, return now; avoid an error.  */
+      if (BUFFERP (object) && pos > BUF_Z (b))
+       goto set_cursor;
+
+      /* Make the window's buffer temporarily current for
+        overlays_at and compute_char_face.  */
+      obuf = current_buffer;
+      current_buffer = b;
+      obegv = BEGV;
+      ozv = ZV;
+      BEGV = BEG;
+      ZV = Z;
+
+      /* Is this char mouse-active or does it have help-echo?  */
+      position = make_number (pos);
+
+      if (BUFFERP (object))
+       {
+         /* Put all the overlays we want in a vector in overlay_vec.
+            Store the length in len.  If there are more than 10, make
+            enough space for all, and try again.  */
+         len = 10;
+         overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
+         noverlays =  overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
+         if (noverlays > len)
+           {
+             len = noverlays;
+             overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
+             noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
+           }
+
+         /* Sort overlays into increasing priority order.  */
+         noverlays = sort_overlays (overlay_vec, noverlays, w);
+       }
+      else
+       noverlays = 0;
+
+      same_region = (EQ (window, dpyinfo->mouse_face_window)
+                    && vpos >= dpyinfo->mouse_face_beg_row
+                    && vpos <= dpyinfo->mouse_face_end_row
+                    && (vpos > dpyinfo->mouse_face_beg_row
+                        || hpos >= dpyinfo->mouse_face_beg_col)
+                    && (vpos < dpyinfo->mouse_face_end_row
+                        || hpos < dpyinfo->mouse_face_end_col
+                        || dpyinfo->mouse_face_past_end));
+
+      /* TODO: if (same_region)
+        mouse cursor */
+
+      /* Check mouse-face highlighting.  */
+      if (! same_region
+         /* If there exists an overlay with mouse-face overlapping
+            the one we are currently highlighting, we have to
+            check if we enter the overlapping overlay, and then
+            highlight that.  */
+         || (OVERLAYP (dpyinfo->mouse_face_overlay)
+             && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
+       {
+         /* Find the highest priority overlay that has a mouse-face
+            property.  */
+         overlay = Qnil;
+         for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
+           {
+             mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
+             if (!NILP (mouse_face))
+               overlay = overlay_vec[i];
+           }
 
-      /* Check for mouse-face and help-echo.  */
+         /* If we're actually highlighting the same overlay as
+            before, there's no need to do that again.  */
+         if (!NILP (overlay)
+             && EQ (overlay, dpyinfo->mouse_face_overlay))
+           goto check_help_echo;
+
+         dpyinfo->mouse_face_overlay = overlay;
+
+         /* Clear the display of the old active region, if any.  */
+         clear_mouse_face (dpyinfo);
+         /* TODO: mouse cursor changes.  */
+
+         /* If no overlay applies, get a text property.  */
+         if (NILP (overlay))
+           mouse_face = Fget_text_property (position, Qmouse_face, object);
+
+         /* Handle the overlay case.  */
+         if (!NILP (overlay))
+           {
+             /* Find the range of text around this char that
+                should be active.  */
+             Lisp_Object before, after;
+             int ignore;
+
+             before = Foverlay_start (overlay);
+             after = Foverlay_end (overlay);
+             /* Record this as the current active region.  */
+             fast_find_position (w, XFASTINT (before),
+                                 &dpyinfo->mouse_face_beg_col,
+                                 &dpyinfo->mouse_face_beg_row,
+                                 &dpyinfo->mouse_face_beg_x,
+                                 &dpyinfo->mouse_face_beg_y, Qnil);
+
+             dpyinfo->mouse_face_past_end
+               = !fast_find_position (w, XFASTINT (after),
+                                      &dpyinfo->mouse_face_end_col,
+                                      &dpyinfo->mouse_face_end_row,
+                                      &dpyinfo->mouse_face_end_x,
+                                      &dpyinfo->mouse_face_end_y, Qnil);
+             dpyinfo->mouse_face_window = window;
+
+             dpyinfo->mouse_face_face_id
+               = face_at_buffer_position (w, pos, 0, 0,
+                                          &ignore, pos + 1, 1);
+
+             /* Display it as active.  */
+             show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
+             /* TODO: mouse cursor changes.  */
+           }
+         /* Handle the text property case.  */
+         else if (! NILP (mouse_face) && BUFFERP (object))
+           {
+             /* Find the range of text around this char that
+                should be active.  */
+             Lisp_Object before, after, beginning, end;
+             int ignore;
+
+             beginning = Fmarker_position (w->start);
+             end = make_number (BUF_Z (XBUFFER (object))
+                                - XFASTINT (w->window_end_pos));
+             before
+               = Fprevious_single_property_change (make_number (pos + 1),
+                                                   Qmouse_face,
+                                                   object, beginning);
+             after
+               = Fnext_single_property_change (position, Qmouse_face,
+                                               object, end);
+
+             /* Record this as the current active region.  */
+             fast_find_position (w, XFASTINT (before),
+                                 &dpyinfo->mouse_face_beg_col,
+                                 &dpyinfo->mouse_face_beg_row,
+                                 &dpyinfo->mouse_face_beg_x,
+                                 &dpyinfo->mouse_face_beg_y, Qnil);
+             dpyinfo->mouse_face_past_end
+               = !fast_find_position (w, XFASTINT (after),
+                                      &dpyinfo->mouse_face_end_col,
+                                      &dpyinfo->mouse_face_end_row,
+                                      &dpyinfo->mouse_face_end_x,
+                                      &dpyinfo->mouse_face_end_y, Qnil);
+             dpyinfo->mouse_face_window = window;
+
+             if (BUFFERP (object))
+               dpyinfo->mouse_face_face_id
+                 = face_at_buffer_position (w, pos, 0, 0,
+                                            &ignore, pos + 1, 1);
+
+             /* Display it as active.  */
+             show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
+             /* TODO: mouse cursor changes.  */
+           }
+         else if (!NILP (mouse_face) && STRINGP (object))
+           {
+             Lisp_Object b, e;
+             int ignore;
+
+             b = Fprevious_single_property_change (make_number (pos + 1),
+                                                   Qmouse_face,
+                                                   object, Qnil);
+             e = Fnext_single_property_change (position, Qmouse_face,
+                                               object, Qnil);
+             if (NILP (b))
+               b = make_number (0);
+             if (NILP (e))
+               e = make_number (XSTRING (object)->size - 1);
+             fast_find_string_pos (w, XINT (b), object,
+                                   &dpyinfo->mouse_face_beg_col,
+                                   &dpyinfo->mouse_face_beg_row,
+                                   &dpyinfo->mouse_face_beg_x,
+                                   &dpyinfo->mouse_face_beg_y, 0);
+             fast_find_string_pos (w, XINT (e), object,
+                                   &dpyinfo->mouse_face_end_col,
+                                   &dpyinfo->mouse_face_end_row,
+                                   &dpyinfo->mouse_face_end_x,
+                                   &dpyinfo->mouse_face_end_y, 1);
+             dpyinfo->mouse_face_past_end = 0;
+             dpyinfo->mouse_face_window = window;
+             dpyinfo->mouse_face_face_id
+               = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
+                                          glyph->face_id, 1);
+             show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
+             /* TODO: mouse cursor changes.  */
+           }
+         else if (STRINGP (object) && NILP (mouse_face))
+           {
+             /* A string which doesn't have mouse-face, but
+                the text ``under'' it might have.  */
+             struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
+             int start = MATRIX_ROW_START_CHARPOS (r);
+             
+             pos = string_buffer_position (w, object, start);
+             if (pos > 0)
+               mouse_face = get_char_property_and_overlay (make_number (pos),
+                                                           Qmouse_face,
+                                                           w->buffer,
+                                                           &overlay);
+             if (!NILP (mouse_face) && !NILP (overlay))
+               {
+                 Lisp_Object before = Foverlay_start (overlay);
+                 Lisp_Object after = Foverlay_end (overlay);
+                 int ignore;
+
+                 /* Note that we might not be able to find position
+                    BEFORE in the glyph matrix if the overlay is
+                    entirely covered by a `display' property.  In
+                    this case, we overshoot.  So let's stop in
+                    the glyph matrix before glyphs for OBJECT.  */
+                 fast_find_position (w, XFASTINT (before),
+                                     &dpyinfo->mouse_face_beg_col,
+                                     &dpyinfo->mouse_face_beg_row,
+                                     &dpyinfo->mouse_face_beg_x,
+                                     &dpyinfo->mouse_face_beg_y,
+                                     object);
+                      
+                 dpyinfo->mouse_face_past_end
+                   = !fast_find_position (w, XFASTINT (after),
+                                          &dpyinfo->mouse_face_end_col,
+                                          &dpyinfo->mouse_face_end_row,
+                                          &dpyinfo->mouse_face_end_x,
+                                          &dpyinfo->mouse_face_end_y,
+                                          Qnil);
+                 dpyinfo->mouse_face_window = window;
+                 dpyinfo->mouse_face_face_id
+                   = face_at_buffer_position (w, pos, 0, 0,
+                                              &ignore, pos + 1, 1);
+
+                 /* Display it as active.  */
+                 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
+                 /* TODO: mouse cursor changes.  */
+               }
+           }
+       }
+
+    check_help_echo:
+
+      /* Look for a `help-echo' property.  */
       {
-        Lisp_Object mouse_face, overlay, position;
-        Lisp_Object *overlay_vec;
-        int len, noverlays;
-        struct buffer *obuf;
-        int obegv, ozv;
-
-        /* If we get an out-of-range value, return now; avoid an error.  */
-        if (pos > BUF_Z (XBUFFER (w->buffer)))
-          return;
-
-        /* Make the window's buffer temporarily current for
-           overlays_at and compute_char_face.  */
-        obuf = current_buffer;
-        current_buffer = XBUFFER (w->buffer);
-        obegv = BEGV;
-        ozv = ZV;
-        BEGV = BEG;
-        ZV = Z;
-
-        /* Is this char mouse-active or does it have help-echo?  */
-        XSETINT (position, pos);
-
-       /* Put all the overlays we want in a vector in overlay_vec.
-          Store the length in len.  If there are more than 10, make
-          enough space for all, and try again.  */
-        len = 10;
-        overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
-        noverlays =  overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
-       if (noverlays > len)
+       Lisp_Object help, overlay;
+
+       /* Check overlays first.  */
+       help = overlay = Qnil;
+       for (i = noverlays - 1; i >= 0 && NILP (help); --i)
          {
-           len = noverlays;
-           overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
-           noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
+           overlay = overlay_vec[i];
+           help = Foverlay_get (overlay, Qhelp_echo); 
          }
 
-       /* Sort overlays into increasing priority order.  */
-        noverlays = sort_overlays (overlay_vec, noverlays, w);
-
-       /* Check mouse-face highlighting.  */
-       if (! (EQ (window, dpyinfo->mouse_face_window)
-              && vpos >= dpyinfo->mouse_face_beg_row
-              && vpos <= dpyinfo->mouse_face_end_row
-              && (vpos > dpyinfo->mouse_face_beg_row
-                  || hpos >= dpyinfo->mouse_face_beg_col)
-              && (vpos < dpyinfo->mouse_face_end_row
-                  || hpos < dpyinfo->mouse_face_end_col
-                  || dpyinfo->mouse_face_past_end)))
+       if (!NILP (help))
          {
-           /* Clear the display of the old active region, if any.  */
-           clear_mouse_face (dpyinfo);
-
-            /* Find the highest priority overlay that has a mouse-face prop.  */
-            overlay = Qnil;
-            for (i = noverlays - 1; i >= 0; --i)
-              {
-                mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
-                if (!NILP (mouse_face))
-                  {
-                    overlay = overlay_vec[i];
-                    break;
-                  }
-              }
-
-            /* If no overlay applies, get a text property.  */
-            if (NILP (overlay))
-              mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
-
-            /* Handle the overlay case.  */
-            if (! NILP (overlay))
-              {
-                /* Find the range of text around this char that
-                   should be active.  */
-                Lisp_Object before, after;
-                int ignore;
-
-                before = Foverlay_start (overlay);
-                after = Foverlay_end (overlay);
-                /* Record this as the current active region.  */
-                fast_find_position (w, XFASTINT (before),
-                                    &dpyinfo->mouse_face_beg_col,
-                                    &dpyinfo->mouse_face_beg_row,
-                                   &dpyinfo->mouse_face_beg_x,
-                                   &dpyinfo->mouse_face_beg_y);
-                dpyinfo->mouse_face_past_end
-                  = !fast_find_position (w, XFASTINT (after),
-                                         &dpyinfo->mouse_face_end_col,
-                                         &dpyinfo->mouse_face_end_row,
-                                         &dpyinfo->mouse_face_end_x,
-                                         &dpyinfo->mouse_face_end_y);
-                dpyinfo->mouse_face_window = window;
-                dpyinfo->mouse_face_face_id
-                  = face_at_buffer_position (w, pos, 0, 0,
-                                             &ignore, pos + 1, 1);
-
-                /* Display it as active.  */
-                show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
-              }
-            /* Handle the text property case.  */
-            else if (! NILP (mouse_face))
-              {
-                /* Find the range of text around this char that
-                   should be active.  */
-                Lisp_Object before, after, beginning, end;
-                int ignore;
-
-                beginning = Fmarker_position (w->start);
-                XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
-                               - XFASTINT (w->window_end_pos)));
-                before
-                  = Fprevious_single_property_change (make_number (pos + 1),
-                                                      Qmouse_face,
-                                                      w->buffer, beginning);
-                after
-                  = Fnext_single_property_change (position, Qmouse_face,
-                                                  w->buffer, end);
-                /* Record this as the current active region.  */
-                fast_find_position (w, XFASTINT (before),
-                                    &dpyinfo->mouse_face_beg_col,
-                                    &dpyinfo->mouse_face_beg_row,
-                                    &dpyinfo->mouse_face_beg_x,
-                                    &dpyinfo->mouse_face_beg_y);
-                dpyinfo->mouse_face_past_end
-                  = !fast_find_position (w, XFASTINT (after),
-                                         &dpyinfo->mouse_face_end_col,
-                                         &dpyinfo->mouse_face_end_row,
-                                        &dpyinfo->mouse_face_end_x,
-                                        &dpyinfo->mouse_face_end_y);
-                dpyinfo->mouse_face_window = window;
-                dpyinfo->mouse_face_face_id
-                  = face_at_buffer_position (w, pos, 0, 0,
-                                             &ignore, pos + 1, 1);
-
-                /* Display it as active.  */
-                show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
-              }
-          }
-
-        /* Look for a `help-echo' property.  */
-        {
-          Lisp_Object help, overlay;
-
-         /* Check overlays first.  */
-         help = Qnil;
-         for (i = noverlays - 1; i >= 0 && NILP (help); --i)
-            {
-              overlay = overlay_vec[i];
-              help = Foverlay_get (overlay, Qhelp_echo); 
-            }
+           help_echo = help;
+           help_echo_window = window;
+           help_echo_object = overlay;
+           help_echo_pos = pos;
+         }
+       else
+         {
+           Lisp_Object object = glyph->object;
+           int charpos = glyph->charpos;
 
-          if (!NILP (help))
-            {
-              help_echo = help;
-              help_echo_window = window;
-              help_echo_object = overlay;
-              help_echo_pos = pos;
-            }
-          else
-            {
-              /* Try text properties.  */
-              if ((STRINGP (glyph->object)
-                  && glyph->charpos >= 0
-                  && glyph->charpos < XSTRING (glyph->object)->size)
-                 || (BUFFERP (glyph->object)
-                     && glyph->charpos >= BEGV
-                     && glyph->charpos < ZV))
-                help = Fget_text_property (make_number (glyph->charpos),
-                                           Qhelp_echo, glyph->object);
+           /* Try text properties.  */
+           if (STRINGP (object)
+               && charpos >= 0
+               && charpos < XSTRING (object)->size)
+             {
+               help = Fget_text_property (make_number (charpos),
+                                          Qhelp_echo, object);
+               if (NILP (help))
+                 {
+                   /* If the string itself doesn't specify a help-echo,
+                      see if the buffer text ``under'' it does.  */
+                   struct glyph_row *r
+                     = MATRIX_ROW (w->current_matrix, vpos);
+                   int start = MATRIX_ROW_START_CHARPOS (r);
+                   int pos = string_buffer_position (w, object, start);
+                   if (pos > 0)
+                     {
+                       help = Fget_char_property (make_number (pos),
+                                                  Qhelp_echo, w->buffer);
+                       if (!NILP (help))
+                         {
+                           charpos = pos;
+                           object = w->buffer;
+                         }
+                     }
+                 }
+             }
+           else if (BUFFERP (object)
+                    && charpos >= BEGV
+                    && charpos < ZV)
+             help = Fget_text_property (make_number (charpos), Qhelp_echo,
+                                        object);
            
-              if (!NILP (help))
-                {
-                  help_echo = help;
-                  help_echo_window = window;
-                  help_echo_object = glyph->object;
-                  help_echo_pos = glyph->charpos;
-                }
-            }
-        }
-        
-        BEGV = obegv;
-        ZV = ozv;
-        current_buffer = obuf;
+           if (!NILP (help))
+             {
+               help_echo = help;
+               help_echo_window = window;
+               help_echo_object = object;
+               help_echo_pos = charpos;
+             }
+         }
       }
+
+      BEGV = obegv;
+      ZV = ozv;
+      current_buffer = obuf;
     }
+
+ set_cursor:
+  /* TODO: mouse cursor changes. */
+  ;
 }
 
 static void
@@ -6704,7 +7013,7 @@ x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
   int area;
 
   /* Find the glyph under X/Y.  */
-  *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area);
+  *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
   if (*glyph == NULL)
     return -1;
 
@@ -6884,28 +7193,101 @@ note_tool_bar_highlight (f, x, y)
 
 
 \f
-/* Find the glyph matrix position of buffer position POS in window W.
-   *HPOS, *VPOS, *X, and *Y are set to the positions found.  W's
-   current glyphs must be up to date.  If POS is above window start
-   return (0, 0, 0, 0).  If POS is after end of W, return end of
-   last line in W.  */
+/* Find the glyph matrix position of buffer position CHARPOS in window
+   *W.  HPOS, *VPOS, *X, and *Y are set to the positions found.  W's
+   current glyphs must be up to date.  If CHARPOS is above window
+   start return (0, 0, 0, 0).  If CHARPOS is after end of W, return end
+   of last line in W.  In the row containing CHARPOS, stop before glyphs
+   having STOP as object.  */
+
+#if 0 /* This is a version of fast_find_position that's more correct
+        in the presence of hscrolling, for example.  I didn't install
+        it right away because the problem fixed is minor, it failed
+        in 20.x as well, and I think it's too risky to install 
+        so near the release of 21.1.  2001-09-25 gerd.  */
+
+static int
+fast_find_position (w, charpos, hpos, vpos, x, y, stop)
+     struct window *w;
+     int charpos;
+     int *hpos, *vpos, *x, *y;
+     Lisp_Object stop;
+{
+  struct glyph_row *row, *first;
+  struct glyph *glyph, *end;
+  int i, past_end = 0;
+
+  first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+  row = row_containing_pos (w, charpos, first, NULL, 0);
+  if (row == NULL)
+    {
+      if (charpos < MATRIX_ROW_START_CHARPOS (first))
+       {
+         *x = *y = *hpos = *vpos = 0;
+         return 0;
+       }
+      else
+       {
+         row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
+         past_end = 1;
+       }
+    }
+
+  *x = row->x;
+  *y = row->y;
+  *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
+  
+  glyph = row->glyphs[TEXT_AREA];
+  end = glyph + row->used[TEXT_AREA];
+  
+  /* Skip over glyphs not having an object at the start of the row.
+     These are special glyphs like truncation marks on terminal
+     frames.  */
+  if (row->displays_text_p)
+    while (glyph < end
+          && INTEGERP (glyph->object)
+          && !EQ (stop, glyph->object)
+          && glyph->charpos < 0)
+      {
+       *x += glyph->pixel_width;
+       ++glyph;
+      }
+
+  while (glyph < end
+        && !INTEGERP (glyph->object)
+        && !EQ (stop, glyph->object)
+        && (!BUFFERP (glyph->object)
+            || glyph->charpos < charpos))
+    {
+      *x += glyph->pixel_width;
+      ++glyph;
+    }
+
+  *hpos = glyph - row->glyphs[TEXT_AREA];
+  return past_end;
+}
+
+#else /* not 0 */
 
 static int
-fast_find_position (w, pos, hpos, vpos, x, y)
+fast_find_position (w, pos, hpos, vpos, x, y, stop)
      struct window *w;
      int pos;
      int *hpos, *vpos, *x, *y;
+     Lisp_Object stop;
 {
   int i;
   int lastcol;
   int maybe_next_line_p = 0;
   int line_start_position;
   int yb = window_text_bottom_y (w);
-  struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
-  struct glyph_row *best_row = row;
-  int row_vpos = 0, best_row_vpos = 0;
+  struct glyph_row *row, *best_row;
+  int row_vpos, best_row_vpos;
   int current_x;
 
+  row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+  row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
+
   while (row->y < yb)
     {
       if (row->used[TEXT_AREA])
@@ -6942,22 +7324,26 @@ fast_find_position (w, pos, hpos, vpos, x, y)
   for (i = 0; i < best_row->used[TEXT_AREA]; i++)
     {
       struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
-      int charpos;
+      int charpos = glyph->charpos;
 
-      charpos = glyph->charpos;
-      if (charpos == pos)
+      if (BUFFERP (glyph->object))
        {
-         *hpos = i;
-         *vpos = best_row_vpos;
-         *x = current_x;
-         *y = best_row->y;
-         return 1;
+         if (charpos == pos)
+           {
+             *hpos = i;
+             *vpos = best_row_vpos;
+             *x = current_x;
+             *y = best_row->y;
+             return 1;
+           }
+         else if (charpos > pos)
+           break;
        }
-      else if (charpos > pos)
+      else if (EQ (glyph->object, stop))
        break;
-      else if (charpos > 0)
-       lastcol = i;
 
+      if (charpos > 0)
+       lastcol = i;
       current_x += glyph->pixel_width;
     }
 
@@ -6979,92 +7365,156 @@ fast_find_position (w, pos, hpos, vpos, x, y)
   return 0;
 }
 
+#endif /* not 0 */
 
-/* Display the active region described by mouse_face_*
-   in its mouse-face if HL > 0, in its normal face if HL = 0.  */
 
-static void
-show_mouse_face (dpyinfo, draw)
-     struct w32_display_info *dpyinfo;
-     enum draw_glyphs_face draw;
-{
-  struct window *w = XWINDOW (dpyinfo->mouse_face_window);
-  struct frame *f = XFRAME (WINDOW_FRAME (w));
-  int i;
-  int cursor_off_p = 0;
-  struct cursor_pos saved_cursor;
+/* Find the position of the glyph for position POS in OBJECT in
+   window W's current matrix, and return in *X/*Y the pixel
+   coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
 
-  saved_cursor = output_cursor;
-  
-  /* If window is in the process of being destroyed, don't bother
-     to do anything.  */
-  if (w->current_matrix == NULL)
-    goto set_x_cursor;
+   RIGHT_P non-zero means return the position of the right edge of the
+   glyph, RIGHT_P zero means return the left edge position.
 
-  /* Recognize when we are called to operate on rows that don't exist
-     anymore.  This can happen when a window is split.  */
-  if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
-    goto set_x_cursor;
+   If no glyph for POS exists in the matrix, return the position of
+   the glyph with the next smaller position that is in the matrix, if
+   RIGHT_P is zero.  If RIGHT_P is non-zero, and no glyph for POS
+   exists in the matrix, return the position of the glyph with the
+   next larger position in OBJECT.
 
-  set_output_cursor (&w->phys_cursor);
+   Value is non-zero if a glyph was found.  */
+
+static int
+fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
+     struct window *w;
+     int pos;
+     Lisp_Object object;
+     int *hpos, *vpos, *x, *y;
+     int right_p;
+{
+  int yb = window_text_bottom_y (w);
+  struct glyph_row *r;
+  struct glyph *best_glyph = NULL;
+  struct glyph_row *best_row = NULL;
+  int best_x = 0;
 
-  /* Note that mouse_face_beg_row etc. are window relative.  */
-  for (i = dpyinfo->mouse_face_beg_row;
-       i <= dpyinfo->mouse_face_end_row;
-       i++)
+  for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+       r->enabled_p && r->y < yb;
+       ++r)
     {
-      int start_hpos, end_hpos, start_x;
-      struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
+      struct glyph *g = r->glyphs[TEXT_AREA];
+      struct glyph *e = g + r->used[TEXT_AREA];
+      int gx;
 
-      /* Don't do anything if row doesn't have valid contents.  */
-      if (!row->enabled_p)
-       continue;
+      for (gx = r->x; g < e; gx += g->pixel_width, ++g)
+       if (EQ (g->object, object))
+         {
+           if (g->charpos == pos)
+             {
+               best_glyph = g;
+               best_x = gx;
+               best_row = r;
+               goto found;
+             }
+           else if (best_glyph == NULL
+                    || ((abs (g->charpos - pos)
+                        < abs (best_glyph->charpos - pos))
+                        && (right_p
+                            ? g->charpos < pos
+                            : g->charpos > pos)))
+             {
+               best_glyph = g;
+               best_x = gx;
+               best_row = r;
+             }
+         }
+    }
 
-      /* For all but the first row, the highlight starts at column 0.  */
-      if (i == dpyinfo->mouse_face_beg_row)
-       {
-         start_hpos = dpyinfo->mouse_face_beg_col;
-         start_x = dpyinfo->mouse_face_beg_x;
-       }
-      else
-       {
-         start_hpos = 0;
-         start_x = 0;
-       }
+ found:
 
-      if (i == dpyinfo->mouse_face_end_row)
-       end_hpos = dpyinfo->mouse_face_end_col;
-      else
-       end_hpos = row->used[TEXT_AREA];
+  if (best_glyph)
+    {
+      *x = best_x;
+      *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
 
-      /* If the cursor's in the text we are about to rewrite, turn the
-        cursor off.  */
-      if (!w->pseudo_window_p
-         && i == output_cursor.vpos
-         && output_cursor.hpos >= start_hpos - 1
-         && output_cursor.hpos <= end_hpos)
+      if (right_p)
        {
-         x_update_window_cursor (w, 0);
-         cursor_off_p = 1;
+         *x += best_glyph->pixel_width;
+         ++*hpos;
        }
-
-      if (end_hpos > start_hpos)
-        {
-          row->mouse_face_p = draw == DRAW_MOUSE_FACE;
-          x_draw_glyphs (w, start_x, row, TEXT_AREA,
-                         start_hpos, end_hpos, draw, NULL, NULL, 0);
-        }
+      
+      *y = best_row->y;
+      *vpos = best_row - w->current_matrix->rows;
     }
 
-  /* If we turned the cursor off, turn it back on.  */
-  if (cursor_off_p)
-    x_display_cursor (w, 1,
-                     output_cursor.hpos, output_cursor.vpos,
-                     output_cursor.x, output_cursor.y);
+  return best_glyph != NULL;
+}
 
-  output_cursor = saved_cursor;
 
- set_x_cursor:
+/* Display the active region described by mouse_face_*
+   in its mouse-face if HL > 0, in its normal face if HL = 0.  */
+
+static void
+show_mouse_face (dpyinfo, draw)
+     struct w32_display_info *dpyinfo;
+     enum draw_glyphs_face draw;
+{
+  struct window *w = XWINDOW (dpyinfo->mouse_face_window);
+  struct frame *f = XFRAME (WINDOW_FRAME (w));
+  
+  if (/* If window is in the process of being destroyed, don't bother
+        to do anything.  */
+      w->current_matrix != NULL
+      /* Don't update mouse highlight if hidden */
+      && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden)
+      /* Recognize when we are called to operate on rows that don't exist
+        anymore.  This can happen when a window is split.  */
+      && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
+    {
+      int phys_cursor_on_p = w->phys_cursor_on_p;
+      struct glyph_row *row, *first, *last;
+
+      first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
+      last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
+      
+      for (row = first; row <= last && row->enabled_p; ++row)
+       {
+         int start_hpos, end_hpos, start_x;
+
+         /* For all but the first row, the highlight starts at column 0.  */
+         if (row == first)
+           {
+             start_hpos = dpyinfo->mouse_face_beg_col;
+             start_x = dpyinfo->mouse_face_beg_x;
+           }
+         else
+           {
+             start_hpos = 0;
+             start_x = 0;
+           }
+
+         if (row == last)
+           end_hpos = dpyinfo->mouse_face_end_col;
+         else
+           end_hpos = row->used[TEXT_AREA];
+
+         if (end_hpos > start_hpos)
+           {
+             x_draw_glyphs (w, start_x, row, TEXT_AREA, 
+                            start_hpos, end_hpos, draw, 0);
+
+             row->mouse_face_p
+               = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
+           }
+       }
+
+      /* When we've written over the cursor, arrange for it to
+        be displayed again.  */
+      if (phys_cursor_on_p && !w->phys_cursor_on_p)
+       x_display_cursor (w, 1,
+                         w->phys_cursor.hpos, w->phys_cursor.vpos,
+                         w->phys_cursor.x, w->phys_cursor.y);
+    }
+
 #if 0 /* TODO: mouse cursor */
   /* Change the mouse cursor.  */
   if (draw == DRAW_NORMAL_TEXT)
@@ -7077,25 +7527,28 @@ show_mouse_face (dpyinfo, draw)
     XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                   f->output_data.x->nontext_cursor);
 #endif
-  ;
 }
 
 /* Clear out the mouse-highlighted active region.
    Redraw it un-highlighted first.  */
 
-void
+static int
 clear_mouse_face (dpyinfo)
      struct w32_display_info *dpyinfo;
 {
-  if (!NILP (tip_frame))
-    return;
+  int cleared = 0;
 
   if (! NILP (dpyinfo->mouse_face_window))
-    show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
+    {
+      show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
+      cleared = 1;
+    }
 
   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;
+  dpyinfo->mouse_face_overlay = Qnil;
+  return cleared;
 }
 
 
@@ -7140,6 +7593,107 @@ cancel_mouse_face (f)
 \f
 static struct scroll_bar *x_window_to_scroll_bar ();
 static void x_scroll_bar_report_motion ();
+static void x_check_fullscreen P_ ((struct frame *));
+static void x_check_fullscreen_move P_ ((struct frame *));
+static int glyph_rect P_ ((struct frame *f, int, int, RECT *));
+
+
+/* Try to determine frame pixel position and size of the glyph under
+   frame pixel coordinates X/Y on frame F .  Return the position and
+   size in *RECT.  Value is non-zero if we could compute these
+   values.  */
+
+static int
+glyph_rect (f, x, y, rect)
+     struct frame *f;
+     int x, y;
+     RECT *rect;
+{
+  Lisp_Object window;
+  int part;
+
+  window = window_from_coordinates (f, x, y, &part, 0);
+  if (!NILP (window))
+    {
+      struct window *w = XWINDOW (window);
+      struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+      struct glyph_row *end = r + w->current_matrix->nrows - 1;
+
+      frame_to_window_pixel_xy (w, &x, &y);
+
+      for (; r < end && r->enabled_p; ++r)
+       if (r->y <= y && r->y + r->height > y)
+         {
+           /* Found the row at y.  */
+           struct glyph *g = r->glyphs[TEXT_AREA];
+           struct glyph *end = g + r->used[TEXT_AREA];
+           int gx;
+
+           rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
+           rect->bottom = rect->top + r->height;
+
+           if (x < r->x)
+             {
+               /* x is to the left of the first glyph in the row.  */
+               rect->left = XINT (w->left);
+               rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
+               return 1;
+             }
+
+           for (gx = r->x; g < end; gx += g->pixel_width, ++g)
+             if (gx <= x && gx + g->pixel_width > x)
+               {
+                 /* x is on a glyph.  */
+                 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
+                 rect->right = rect->left + g->pixel_width;
+                 return 1;
+               }
+
+           /* x is to the right of the last glyph in the row.  */
+           rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
+           rect->right = XINT (w->left) + XINT (w->width);
+           return 1;
+         }
+    }
+
+  /* The y is not on any row.  */
+  return 0;
+}
+
+/* Record the position of the mouse in last_mouse_glyph.  */
+static void
+remember_mouse_glyph (f1, gx, gy)
+     struct frame * f1;
+     int gx, gy;
+{
+  if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
+    {
+      int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
+      int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
+
+      /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
+        round down even for negative values.  */
+      if (gx < 0)
+       gx -= width - 1;
+      if (gy < 0)
+       gy -= height - 1;
+#if 0
+      /* This was the original code from XTmouse_position, but it seems
+        to give the position of the glyph diagonally next to the one
+        the mouse is over.  */
+      gx = (gx + width - 1) / width * width;
+      gy = (gy + height - 1) / height * height;
+#else
+      gx = gx / width * width;
+      gy = gy / height * height;
+#endif
+
+      last_mouse_glyph.left = gx;
+      last_mouse_glyph.top = gy;
+      last_mouse_glyph.right  = gx + width;
+      last_mouse_glyph.bottom = gy + height;
+    }
+}
 
 /* Return the current position of the mouse.
    *fp should be a frame which indicates which display to ask about.
@@ -7203,7 +7757,7 @@ w32_mouse_position (fp, insist, bar_window, part, x, y, time)
        else
          {
            /* Is window under mouse one of our frames?  */
-           f1 = x_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp),
+           f1 = x_any_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp),
                                     WindowFromPoint (pt));
          }
 
@@ -7243,24 +7797,7 @@ w32_mouse_position (fp, insist, bar_window, part, x, y, time)
                                   || insist);
 #else
            ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
-           {
-             int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
-             int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
-             int x = pt.x;
-             int y = pt.y;
-             
-             /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
-                round down even for negative values.  */
-             if (x < 0)
-               x -= width - 1;
-             if (y < 0)
-               y -= height - 1;
-             
-             last_mouse_glyph.left = (x + width - 1) / width * width;
-             last_mouse_glyph.top = (y + height - 1) / height * height;
-             last_mouse_glyph.right  = last_mouse_glyph.left + width;
-             last_mouse_glyph.bottom = last_mouse_glyph.top + height;
-           }
+           remember_mouse_glyph (f1, pt.x, pt.y);
 #endif
 
            *bar_window = Qnil;
@@ -7328,7 +7865,7 @@ w32_set_scroll_bar_thumb (bar, portion, position, whole)
      int portion, position, whole;
 {
   Window w = SCROLL_BAR_W32_WINDOW (bar);
-  int range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
+  double range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
   int sb_page, sb_pos;
   BOOL draggingp = !NILP (bar->dragging) ? TRUE : FALSE;
 
@@ -7392,7 +7929,7 @@ my_create_scrollbar (f, bar)
                             (LPARAM) bar);
 }
 
-//#define ATTACH_THREADS
+/*#define ATTACH_THREADS*/
 
 BOOL
 my_show_window (FRAME_PTR f, HWND hwnd, int how)
@@ -7580,9 +8117,12 @@ w32_set_vertical_scroll_bar (w, portion, whole, position)
     {
       HDC hdc;
       BLOCK_INPUT;
-      hdc = get_frame_dc (f);
-      w32_clear_area (f, hdc, left, top, width, height);
-      release_frame_dc (f, hdc);
+      if (width > 0 && height > 0)
+       {
+         hdc = get_frame_dc (f);
+         w32_clear_area (f, hdc, left, top, width, height);
+         release_frame_dc (f, hdc);
+       }
       UNBLOCK_INPUT;
 
       bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
@@ -7609,22 +8149,24 @@ w32_set_vertical_scroll_bar (w, portion, whole, position)
         {
           HDC hdc;
           BLOCK_INPUT;
-
-          hdc = get_frame_dc (f);
-          /* Since Windows scroll bars are smaller than the space reserved
-             for them on the frame, we have to clear "under" them.  */
-          w32_clear_area (f, hdc,
-                          left,
-                          top,
-                          width,
-                          height);
-          release_frame_dc (f, hdc);
-
+         if (width && height)
+           {
+             hdc = get_frame_dc (f);
+             /* Since Windows scroll bars are smaller than the space reserved
+                for them on the frame, we have to clear "under" them.  */
+             w32_clear_area (f, hdc,
+                             left,
+                             top,
+                             width,
+                             height);
+             release_frame_dc (f, hdc);
+           }
           /* 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, hwnd, SW_HIDE);
-          MoveWindow (hwnd, sb_left, top,
-                      sb_width, height, TRUE);
+          MoveWindow (hwnd, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
+                     top, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
+                     max (height, 1), TRUE);
           if (pfnSetScrollInfo)
             {
               SCROLLINFO si;
@@ -7641,7 +8183,7 @@ w32_set_vertical_scroll_bar (w, portion, whole, position)
             SetScrollRange (hwnd, SB_CTL, 0,
                             VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE);
           my_show_window (f, hwnd, SW_NORMAL);
-          //  InvalidateRect (w, NULL, FALSE);
+          /* InvalidateRect (w, NULL, FALSE);  */
 
           /* Remember new settings.  */
           XSETINT (bar->left, sb_left);
@@ -7688,13 +8230,16 @@ w32_condemn_scroll_bars (frame)
     }
 }
 
+
 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
    Note that WINDOW isn't necessarily condemned at all.  */
+
 static void
 w32_redeem_scroll_bar (window)
      struct window *window;
 {
   struct scroll_bar *bar;
+  struct frame *f;
 
   /* We can't redeem this window's scroll bar if it doesn't have one.  */
   if (NILP (window->vertical_scroll_bar))
@@ -7703,36 +8248,33 @@ w32_redeem_scroll_bar (window)
   bar = XSCROLL_BAR (window->vertical_scroll_bar);
 
   /* Unlink it from the condemned list.  */
-  {
-    FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
-
-    if (NILP (bar->prev))
-      {
-       /* If the prev pointer is nil, it must be the first in one of
-           the lists.  */
-       if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
-         /* It's not condemned.  Everything's fine.  */
-         return;
-       else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
-                    window->vertical_scroll_bar))
-         FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
-       else
-         /* If its prev pointer is nil, it must be at the front of
-             one or the other!  */
-         abort ();
-      }
-    else
-      XSCROLL_BAR (bar->prev)->next = bar->next;
+  f = XFRAME (WINDOW_FRAME (window));
+  if (NILP (bar->prev))
+    {
+      /* If the prev pointer is nil, it must be the first in one of
+         the lists.  */
+      if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
+        /* It's not condemned.  Everything's fine.  */
+        return;
+      else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
+                   window->vertical_scroll_bar))
+        FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
+      else
+        /* If its prev pointer is nil, it must be at the front of
+           one or the other!  */
+        abort ();
+    }
+  else
+    XSCROLL_BAR (bar->prev)->next = bar->next;
 
-    if (! NILP (bar->next))
-      XSCROLL_BAR (bar->next)->prev = bar->prev;
+  if (! NILP (bar->next))
+    XSCROLL_BAR (bar->next)->prev = bar->prev;
 
-    bar->next = FRAME_SCROLL_BARS (f);
-    bar->prev = Qnil;
-    XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
-    if (! NILP (bar->next))
-      XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
-  }
+  bar->next = FRAME_SCROLL_BARS (f);
+  bar->prev = Qnil;
+  XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
+  if (! NILP (bar->next))
+    XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
 }
 
 /* Remove all scroll bars on FRAME that haven't been saved since the
@@ -7771,7 +8313,7 @@ w32_judge_scroll_bars (f)
    mark bits.  */
 
 static int
-x_scroll_bar_handle_click (bar, msg, emacs_event)
+w32_scroll_bar_handle_click (bar, msg, emacs_event)
      struct scroll_bar *bar;
      W32Msg *msg;
      struct input_event *emacs_event;
@@ -7990,29 +8532,9 @@ x_scroll_bar_clear (f)
       }
 }
 
-show_scroll_bars (f, how)
-     FRAME_PTR f;
-     int how;
-{
-  Lisp_Object bar;
-
-  for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
-       bar = XSCROLL_BAR (bar)->next)
-    {
-      HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
-      my_show_window (f, window, how);
-    }
-}
-
 \f
 /* The main W32 event-reading loop - w32_read_socket.  */
 
-/* Time stamp 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
-   sometimes don't work.  */
-
-static Time enter_timestamp;
-
 /* Record the last 100 characters stored
    to help debug the loss-of-chars-during-GC problem.  */
 
@@ -8068,65 +8590,65 @@ w32_read_socket (sd, bufp, numchars, expected)
   if (numchars <= 0)
     abort ();                   /* Don't think this happens. */
 
-  /* TODO: tooltips, tool-bars, ghostscript integration, mouse
+  /* TODO: tool-bars, ghostscript integration, mouse
      cursors. */
   while (get_next_msg (&msg, FALSE))
     {
       switch (msg.msg.message)
        {
        case WM_PAINT:
-           f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
+         f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
 
-           if (f) 
-             {
-               if (msg.rect.right == msg.rect.left ||
-                   msg.rect.bottom == msg.rect.top)
-                 {
-                   /* We may get paint messages even though the client
-                      area is clipped - these are not expose events. */
-                   DebPrint (("clipped frame %04x (%s) got WM_PAINT\n", f,
-                              XSTRING (f->name)->data));
-                 }
-               else 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->arg = Qnil;
-                       bufp++;
-                       count++;
-                       numchars--;
-                     }
-                   else if (! NILP (Vframe_list)
-                            && ! NILP (XCDR (Vframe_list)))
-                     /* Force a redisplay sooner or later to update the
-                        frame titles in case this is the second frame.  */
-                     record_asynch_buffer_change ();
-                 }
-               else
-                 {
-                    HDC hdc = get_frame_dc (f);
-
-                   /* Erase background again for safety.  */
-                   w32_clear_rect (f, hdc, &msg.rect);
-                    release_frame_dc (f, hdc);
-                   expose_frame (f,
-                                  msg.rect.left,
-                                  msg.rect.top,
-                                  msg.rect.right - msg.rect.left,
-                                  msg.rect.bottom - msg.rect.top);
-                 }
-             }
+         if (f) 
+           {
+             if (msg.rect.right == msg.rect.left ||
+                 msg.rect.bottom == msg.rect.top)
+               {
+                 /* We may get paint messages even though the client
+                    area is clipped - these are not expose events. */
+                 DebPrint (("clipped frame %p (%s) got WM_PAINT - ignored\n", f,
+                            XSTRING (f->name)->data));
+               }
+             else 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 %p (%s) reexposed by WM_PAINT\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->arg = Qnil;
+                     bufp++;
+                     count++;
+                     numchars--;
+                   }
+                 else if (! NILP (Vframe_list)
+                          && ! NILP (XCDR (Vframe_list)))
+                   /* Force a redisplay sooner or later to update the
+                      frame titles in case this is the second frame.  */
+                   record_asynch_buffer_change ();
+               }
+             else
+               {
+                 HDC hdc = get_frame_dc (f);
+
+                 /* Erase background again for safety.  */
+                 w32_clear_rect (f, hdc, &msg.rect);
+                 release_frame_dc (f, hdc);
+                 expose_frame (f,
+                               msg.rect.left,
+                               msg.rect.top,
+                               msg.rect.right - msg.rect.left,
+                               msg.rect.bottom - msg.rect.top);
+               }
+           }
          break;
 
        case WM_INPUTLANGCHANGE:
@@ -8155,6 +8677,12 @@ w32_read_socket (sd, bufp, numchars, expected)
          
          if (f && !f->iconified)
            {
+             if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
+               {
+                 dpyinfo->mouse_face_hidden = 1;
+                 clear_mouse_face (dpyinfo);
+               }
+
              if (temp_index == sizeof temp_buffer / sizeof (short))
                temp_index = 0;
              temp_buffer[temp_index++] = msg.msg.wParam;
@@ -8176,6 +8704,12 @@ w32_read_socket (sd, bufp, numchars, expected)
          
          if (f && !f->iconified)
            {
+             if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
+               {
+                 dpyinfo->mouse_face_hidden = 1;
+                 clear_mouse_face (dpyinfo);
+               }
+
              if (temp_index == sizeof temp_buffer / sizeof (short))
                temp_index = 0;
              temp_buffer[temp_index++] = msg.msg.wParam;
@@ -8193,7 +8727,7 @@ w32_read_socket (sd, bufp, numchars, expected)
 
        case WM_MOUSEMOVE:
           previous_help_echo = help_echo;
-          help_echo = help_echo_object = help_echo_window = Qnil;
+          help_echo_object = help_echo_window = Qnil;
           help_echo_pos = -1;
 
          if (dpyinfo->grabbed && last_mouse_frame
@@ -8202,19 +8736,24 @@ w32_read_socket (sd, bufp, numchars, expected)
          else
            f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
          
+         if (dpyinfo->mouse_face_hidden)
+           {
+             dpyinfo->mouse_face_hidden = 0;
+             clear_mouse_face (dpyinfo);
+           }
+
          if (f)
            note_mouse_movement (f, &msg.msg);
          else
             {
               /* If we move outside the frame, then we're
                  certainly no longer on any text in the frame.  */
-              clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
+              clear_mouse_face (dpyinfo);
             }
 
           /* If the contents of the global variable help_echo
              has changed, generate a HELP_EVENT.  */
-          if (!NILP (help_echo)
-              || !NILP (previous_help_echo))
+          if (help_echo != previous_help_echo)
             {
               Lisp_Object frame;
               int n;
@@ -8238,6 +8777,8 @@ w32_read_socket (sd, bufp, numchars, expected)
        case WM_MBUTTONUP:
        case WM_RBUTTONDOWN:
        case WM_RBUTTONUP:
+       case WM_XBUTTONDOWN:
+       case WM_XBUTTONUP:
          {
             /* If we decide we want to generate an event to be seen
                by the rest of Emacs, we put it here.  */
@@ -8263,7 +8804,7 @@ w32_read_socket (sd, bufp, numchars, expected)
                     && XFASTINT (XWINDOW (f->tool_bar_window)->height))
                   {
                     Lisp_Object window;
-                    int p, x, y;
+                    int p;
 
                     /* Set x and y.  */
                     window = window_from_coordinates (f,
@@ -8289,8 +8830,9 @@ w32_read_socket (sd, bufp, numchars, expected)
                     }
              }
            
-           parse_button (msg.msg.message, &button, &up);
-           
+           parse_button (msg.msg.message, HIWORD (msg.msg.wParam),
+                         &button, &up);
+
            if (up)
              {
                dpyinfo->grabbed &= ~ (1 << button);
@@ -8333,16 +8875,6 @@ w32_read_socket (sd, bufp, numchars, expected)
             }
          break;
 
-        case WM_MENUSELECT:
-          {
-            HMENU menu = (HMENU) msg.msg.lParam;
-            UINT menu_item = (UINT) LOWORD (msg.msg.wParam);
-            UINT flags = (UINT) HIWORD (msg.msg.wParam);
-
-            w32_menu_display_help (menu, menu_item, flags);
-          }
-          break;
-
        case WM_DROPFILES:
          f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
 
@@ -8362,7 +8894,7 @@ w32_read_socket (sd, bufp, numchars, expected)
              
            if (bar && numchars >= 1)
              {
-               if (x_scroll_bar_handle_click (bar, &msg, bufp))
+               if (w32_scroll_bar_handle_click (bar, &msg, bufp))
                  {
                    bufp++;
                    count++;
@@ -8373,8 +8905,22 @@ w32_read_socket (sd, bufp, numchars, expected)
          }
          
        case WM_WINDOWPOSCHANGED:
+         f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
+         if (f)
+           {
+             x_check_fullscreen_move(f);
+             if (f->output_data.w32->want_fullscreen & FULLSCREEN_WAIT)
+               f->output_data.w32->want_fullscreen &=
+                 ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
+           }
+         check_visibility = 1;
+         break;
+
        case WM_ACTIVATE:
        case WM_ACTIVATEAPP:
+         f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
+         if (f)
+           x_check_fullscreen (f);
          check_visibility = 1;
          break;
 
@@ -8394,6 +8940,15 @@ w32_read_socket (sd, bufp, numchars, expected)
          break;
 
        case WM_SHOWWINDOW:
+         /* wParam non-zero means Window is about to be shown, 0 means
+            about to be hidden.  */
+         /* Redo the mouse-highlight after the tooltip has gone.  */
+         if (!msg.msg.wParam && msg.msg.hwnd == tip_window)
+           {
+             tip_window = NULL;
+             redo_mouse_highlight ();
+           }
+
          /* 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
@@ -8509,6 +9064,36 @@ w32_read_socket (sd, bufp, numchars, expected)
          check_visibility = 1;
          break;
 
+       case WM_MOUSELEAVE:
+         f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd);
+         if (f)
+           {
+             if (f == dpyinfo->mouse_face_mouse_frame)
+               {
+                 /* If we move outside the frame, then we're
+                    certainly no longer on any text in the frame.  */
+                 clear_mouse_face (dpyinfo);
+                 dpyinfo->mouse_face_mouse_frame = 0;
+               }
+
+             /* Generate a nil HELP_EVENT to cancel a help-echo.
+                Do it only if there's something to cancel.
+                Otherwise, the startup message is cleared when
+                the mouse leaves the frame.  */
+             if (any_help_event_p)
+               {
+                 Lisp_Object frame;
+                 int n;
+
+                 XSETFRAME (frame, f);
+                 help_echo = Qnil;
+                 n = gen_help_event (bufp, numchars,
+                                     Qnil, frame, Qnil, Qnil, 0);
+                 bufp += n, count += n, numchars -= n;
+               }
+           }
+         break;
+             
        case WM_SETFOCUS:
          f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd);
 
@@ -8528,8 +9113,6 @@ w32_read_socket (sd, bufp, numchars, expected)
 
           if (f)
             {
-              Lisp_Object frame;
-
               if (f == dpyinfo->w32_focus_event_frame)
                 dpyinfo->w32_focus_event_frame = 0;
 
@@ -8550,11 +9133,13 @@ w32_read_socket (sd, bufp, numchars, expected)
                  the mouse leaves the frame.  */
               if (any_help_event_p)
                 {
+                  Lisp_Object frame;
                   int n;
 
                   XSETFRAME (frame, f);
-                  n = gen_help_event (bufp, numchars, Qnil, frame,
-                                     Qnil, Qnil, 0);
+                  help_echo = Qnil;
+                  n = gen_help_event (bufp, numchars,
+                                      Qnil, frame, Qnil, Qnil, 0);
                   bufp += n, count += n, numchars -=n;
                 }
             }
@@ -8673,15 +9258,30 @@ w32_read_socket (sd, bufp, numchars, expected)
       FOR_EACH_FRAME (tail, frame)
        {
          FRAME_PTR f = XFRAME (frame);
+         /* The tooltip has been drawn already.  Avoid the
+            SET_FRAME_GARBAGED below.  */
+         if (EQ (frame, tip_frame))
+           continue;
+
          /* Check "visible" frames and mark each as obscured or not.
             Note that async_visible is nonzero for unobscured and
             obscured frames, but zero for hidden and iconified frames.  */
          if (FRAME_W32_P (f) && f->async_visible)
            {
              RECT clipbox;
-             HDC  hdc = get_frame_dc (f);
+             HDC  hdc;
+
+             enter_crit ();
+             /* Query clipping rectangle for the entire window area
+                 (GetWindowDC), not just the client portion (GetDC).
+                 Otherwise, the scrollbars and menubar aren't counted as
+                 part of the visible area of the frame, and we may think
+                 the frame is obscured when really a scrollbar is still
+                 visible and gets WM_PAINT messages above.  */
+             hdc = GetWindowDC (FRAME_W32_WINDOW (f));
              GetClipBox (hdc, &clipbox);
-             release_frame_dc (f, hdc);
+             ReleaseDC (FRAME_W32_WINDOW (f), hdc);
+             leave_crit ();
 
              if (clipbox.right == clipbox.left
                  || clipbox.bottom == clipbox.top)
@@ -8694,7 +9294,7 @@ w32_read_socket (sd, bufp, numchars, expected)
 
                  if (!FRAME_OBSCURED_P (f))
                    {
-                     DebPrint (("frame %04x (%s) obscured\n", f,
+                     DebPrint (("frame %p (%s) obscured\n", f,
                                 XSTRING (f->name)->data));
                    }
                }
@@ -8706,7 +9306,7 @@ w32_read_socket (sd, bufp, numchars, expected)
                  if (FRAME_OBSCURED_P (f))
                    {
                      SET_FRAME_GARBAGED (f);
-                     DebPrint (("frame %04x (%s) reexposed\n", f,
+                     DebPrint (("obscured frame %p (%s) found to be visible\n", f,
                                 XSTRING (f->name)->data));
 
                      /* Force a redisplay sooner or later.  */
@@ -8728,21 +9328,24 @@ w32_read_socket (sd, bufp, numchars, expected)
                             Text Cursor
  ***********************************************************************/
 
-/* Note if the text cursor of window W has been overwritten by a
-   drawing operation that outputs N glyphs starting at HPOS in the
-   line given by output_cursor.vpos.  N < 0 means all the rest of the
-   line after HPOS has been written.  */
+/* Notice if the text cursor of window W has been overwritten by a
+   drawing operation that outputs glyphs starting at START_X and
+   ending at END_X in the line given by output_cursor.vpos.
+   Coordinates are area-relative.  END_X < 0 means all the rest
+   of the line after START_X has been written.  */
 
 static void
-note_overwritten_text_cursor (w, hpos, n)
+notice_overwritten_cursor (w, area, x0, x1, y0, y1)
      struct window *w;
-     int hpos, n;
-{
-  if (updated_area == TEXT_AREA
-      && output_cursor.vpos == w->phys_cursor.vpos
-      && hpos <= w->phys_cursor.hpos
-      && (n < 0
-         || hpos + n > w->phys_cursor.hpos))
+     enum glyph_row_area area;
+     int x0, x1, y0, y1;
+{
+  if (area == TEXT_AREA
+      && w->phys_cursor_on_p
+      && y0 <= w->phys_cursor.y
+      && y1 >= w->phys_cursor.y + w->phys_cursor_height
+      && x0 <= w->phys_cursor.x
+      && (x1 < 0 || x1 > w->phys_cursor.x))
     w->phys_cursor_on_p = 0;
 }
 
@@ -8779,8 +9382,8 @@ w32_clip_to_row (w, row, hdc, whole_line_p)
      the rectangle to the left and increase its width.  */
   if (whole_line_p)
     {
-      clip_rect.left -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
-      clip_rect.right += FRAME_X_FLAGS_AREA_WIDTH (f);
+      clip_rect.left -= FRAME_X_LEFT_FRINGE_WIDTH (f);
+      clip_rect.right += FRAME_X_FRINGE_WIDTH (f);
     }
 
   w32_set_clip_rectangle (hdc, &clip_rect);
@@ -8845,45 +9448,51 @@ x_draw_bar_cursor (w, row, width)
      struct glyph_row *row;
      int width;
 {
-  /* If cursor hpos is out of bounds, don't draw garbage.  This can
-     happen in mini-buffer windows when switching between echo area
-     glyphs and mini-buffer.  */
-  if (w->phys_cursor.hpos < row->used[TEXT_AREA])
-    {
-      struct frame *f = XFRAME (w->frame);
-      struct glyph *cursor_glyph;
-      int x;
-      HDC hdc;
+  struct frame *f = XFRAME (w->frame);
+  struct glyph *cursor_glyph;
+  int x;
+  HDC hdc;
 
-      cursor_glyph = get_phys_cursor_glyph (w);
-      if (cursor_glyph == NULL)
-       return;
+  /* If cursor is out of bounds, don't draw garbage.  This can happen
+     in mini-buffer windows when switching between echo area glyphs
+     and mini-buffer.  */
+  cursor_glyph = get_phys_cursor_glyph (w);
+  if (cursor_glyph == NULL)
+    return;
 
-      /* If on an image, draw like a normal cursor.  That's usually better
-         visible than drawing a bar, esp. if the image is large so that
-         the bar might not be in the window.  */
-      if (cursor_glyph->type == IMAGE_GLYPH)
-        {
-          struct glyph_row *row;
-          row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
-          x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
-        }
-      else
-        {
+  /* If on an image, draw like a normal cursor.  That's usually better
+     visible than drawing a bar, esp. if the image is large so that
+     the bar might not be in the window.  */
+  if (cursor_glyph->type == IMAGE_GLYPH)
+    {
+      struct glyph_row *row;
+      row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
+      x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
+    }
+  else
+    {
+      COLORREF cursor_color = f->output_data.w32->cursor_pixel;
+      struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
 
-          x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
+      if (width < 0)
+        width = f->output_data.w32->cursor_width;
 
-          if (width < 0)
-            width = f->output_data.w32->cursor_width;
+      /* If the glyph's background equals the color we normally draw
+        the bar cursor in, the bar cursor in its normal color is
+        invisible.  Use the glyph's foreground color instead in this
+        case, on the assumption that the glyph's colors are chosen so
+        that the glyph is legible.  */
+      if (face->background == cursor_color)
+       cursor_color = face->foreground;
 
-          hdc = get_frame_dc (f);
-          w32_fill_area (f, hdc, f->output_data.w32->cursor_pixel,
-                         x,
-                         WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
-                         min (cursor_glyph->pixel_width, width),
-                         row->height);
-          release_frame_dc (f, hdc);
-        }
+      x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
+      hdc = get_frame_dc (f);
+      w32_clip_to_row (w, row, hdc, 0);
+      w32_fill_area (f, hdc, cursor_color, x,
+                     WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
+                     min (cursor_glyph->pixel_width, width),
+                     row->height);
+      release_frame_dc (f, hdc);
     }
 }
 
@@ -8915,9 +9524,11 @@ x_draw_phys_cursor_glyph (w, row, hl)
      glyphs and mini-buffer.  */
   if (w->phys_cursor.hpos < row->used[TEXT_AREA])
     {
+      int on_p = w->phys_cursor_on_p;
       x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
                      w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
-                     hl, 0, 0, 0);
+                     hl, 0);
+      w->phys_cursor_on_p = on_p;
 
       /* When we erase the cursor, and ROW is overlapped by other
         rows, make sure that these overlapping parts of other rows
@@ -8968,6 +9579,12 @@ x_erase_phys_cursor (w)
   if (!cursor_row->enabled_p)
     goto mark_cursor_off;
   
+  /* If row is completely invisible, don't attempt to delete a cursor which
+     isn't there.  This may happen if cursor is at top of window, and
+     we switch to a buffer with a header line in that window.  */
+  if (cursor_row->visible_height <= 0)
+    goto mark_cursor_off;
+  
   /* This can happen when the new row is shorter than the old one.
      In this case, either x_draw_glyphs or clear_end_of_line
      should have cleared the cursor.  Note that we wouldn't be
@@ -8978,7 +9595,8 @@ x_erase_phys_cursor (w)
         
   /* If the cursor is in the mouse face area, redisplay that when
      we clear the cursor.  */
-  if (w == XWINDOW (dpyinfo->mouse_face_window)
+  if (! NILP (dpyinfo->mouse_face_window)
+      && w == XWINDOW (dpyinfo->mouse_face_window)
       && (vpos > dpyinfo->mouse_face_beg_row
          || (vpos == dpyinfo->mouse_face_beg_row
              && hpos >= dpyinfo->mouse_face_beg_col))
@@ -9016,8 +9634,6 @@ x_erase_phys_cursor (w)
   /* Erase the cursor by redrawing the character underneath it.  */
   if (mouse_face_here_p)
     hl = DRAW_MOUSE_FACE;
-  else if (cursor_row->inverse_p)
-    hl = DRAW_INVERSE_VIDEO;
   else
     hl = DRAW_NORMAL_TEXT;
   x_draw_phys_cursor_glyph (w, cursor_row, hl);
@@ -9028,6 +9644,36 @@ x_erase_phys_cursor (w)
 }
 
 
+/* Non-zero if physical cursor of window W is within mouse face.  */
+
+static int
+cursor_in_mouse_face_p (w)
+     struct window *w;
+{
+  struct w32_display_info *dpyinfo
+    = FRAME_W32_DISPLAY_INFO (XFRAME (w->frame));
+  int in_mouse_face = 0;
+  
+  if (WINDOWP (dpyinfo->mouse_face_window)
+      && XWINDOW (dpyinfo->mouse_face_window) == w)
+    {
+      int hpos = w->phys_cursor.hpos;
+      int vpos = w->phys_cursor.vpos;
+
+      if (vpos >= dpyinfo->mouse_face_beg_row
+         && vpos <= dpyinfo->mouse_face_end_row
+         && (vpos > dpyinfo->mouse_face_beg_row
+             || hpos >= dpyinfo->mouse_face_beg_col)
+         && (vpos < dpyinfo->mouse_face_end_row
+             || hpos < dpyinfo->mouse_face_end_col
+             || dpyinfo->mouse_face_past_end))
+       in_mouse_face = 1;
+    }
+
+  return in_mouse_face;
+}
+
+
 /* Display or clear cursor of window W.  If ON is zero, clear the
    cursor.  If it is non-zero, display the cursor.  If ON is nonzero,
    where to put the cursor is specified by HPOS, VPOS, X and Y.  */
@@ -9043,6 +9689,8 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
   struct glyph_matrix *current_glyphs;
   struct glyph_row *glyph_row;
   struct glyph *glyph;
+  int cursor_non_selected;
+  int active_cursor = 1;
 
   /* This is pointless on invisible frames, and dangerous on garbaged
      windows and frames; in the latter case, the frame or window may
@@ -9078,6 +9726,9 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
      the cursor type given by the frame parameter.  If explicitly
      marked off, draw no cursor.  In all other cases, we want a hollow
      box cursor.  */
+  cursor_non_selected 
+    = !NILP (Fbuffer_local_value (Qcursor_in_non_selected_windows,
+                                 w->buffer));
   new_cursor_width = -1;
   if (cursor_in_echo_area
       && FRAME_HAS_MINIBUF_P (f)
@@ -9086,24 +9737,28 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
       if (w == XWINDOW (echo_area_window))
        new_cursor_type = FRAME_DESIRED_CURSOR (f);
       else
-       new_cursor_type = HOLLOW_BOX_CURSOR;
+       {
+         if (cursor_non_selected)
+           new_cursor_type = HOLLOW_BOX_CURSOR;
+         else
+           new_cursor_type = NO_CURSOR;
+         active_cursor = 0;
+       }
     }
   else
     {
-      if (w != XWINDOW (selected_window)
-          || f != FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame)
+      if (f != FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame
+          || w != XWINDOW (f->selected_window))
         {
-         extern int cursor_in_non_selected_windows;
+         active_cursor = 0;
 
           if (MINI_WINDOW_P (w) 
-              || !cursor_in_non_selected_windows
+              || !cursor_non_selected
               || NILP (XBUFFER (w->buffer)->cursor_type))
             new_cursor_type = NO_CURSOR;
           else
             new_cursor_type = HOLLOW_BOX_CURSOR;
         }
-      else if (w->cursor_off_p)
-        new_cursor_type = NO_CURSOR;
       else
         {
          struct buffer *b = XBUFFER (w->buffer);
@@ -9113,6 +9768,15 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
          else
            new_cursor_type = x_specified_cursor_type (b->cursor_type, 
                                                       &new_cursor_width);
+         if (w->cursor_off_p)
+           {
+             if (new_cursor_type == FILLED_BOX_CURSOR)
+               new_cursor_type = HOLLOW_BOX_CURSOR;
+             else if (new_cursor_type == BAR_CURSOR && new_cursor_width > 1)
+               new_cursor_width = 1;
+             else
+               new_cursor_type = NO_CURSOR;
+           }
        }
     }
 
@@ -9123,7 +9787,9 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
       && (!on
          || w->phys_cursor.x != x
          || w->phys_cursor.y != y
-         || new_cursor_type != w->phys_cursor_type))
+         || new_cursor_type != w->phys_cursor_type
+         || (new_cursor_type == BAR_CURSOR
+             && new_cursor_width != w->phys_cursor_width)))
     x_erase_phys_cursor (w);
 
   /* If the cursor is now invisible and we want it to be visible,
@@ -9139,16 +9805,57 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
       w->phys_cursor.y = glyph_row->y;
       w->phys_cursor.hpos = hpos;
       w->phys_cursor.vpos = vpos;
-      w->phys_cursor_type = new_cursor_type;
-      w->phys_cursor_on_p = 1;
 
-      switch (new_cursor_type)
+      /* If the user wants to use the system caret, make sure our own
+        cursor remains invisible.  */
+      if (w32_use_visible_system_caret)
        {
-       case HOLLOW_BOX_CURSOR:
-         x_draw_hollow_cursor (w, glyph_row);
-         break;
+         if (w->phys_cursor_type != NO_CURSOR)
+           x_erase_phys_cursor (w);
 
-       case FILLED_BOX_CURSOR:
+         new_cursor_type = w->phys_cursor_type = NO_CURSOR;
+         w->phys_cursor_width = -1;
+       }
+      else
+       {
+         w->phys_cursor_type = new_cursor_type;
+         w->phys_cursor_width = new_cursor_width;
+       }
+
+      w->phys_cursor_on_p = 1;
+
+      /* If this is the active cursor, we need to track it with the
+        system caret, so third party software like screen magnifiers
+        and speech synthesizers can follow the cursor.  */
+      if (active_cursor)
+       {
+         HWND hwnd = FRAME_W32_WINDOW (f);
+
+         w32_system_caret_x
+           = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
+         w32_system_caret_y
+           = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
+              + glyph_row->ascent - w->phys_cursor_ascent);
+
+         /* If the size of the active cursor changed, destroy the old
+            system caret.  */
+         if (w32_system_caret_hwnd
+             && (w32_system_caret_height != w->phys_cursor_height))
+           PostMessage (hwnd, WM_EMACS_DESTROY_CARET, 0, 0);
+
+         w32_system_caret_height = w->phys_cursor_height;
+
+         /* Move the system caret.  */
+         PostMessage (hwnd, WM_EMACS_TRACK_CARET, 0, 0);
+       }
+
+      switch (new_cursor_type)
+       {
+       case HOLLOW_BOX_CURSOR:
+         x_draw_hollow_cursor (w, glyph_row);
+         break;
+
+       case FILLED_BOX_CURSOR:
          x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
          break;
 
@@ -9247,8 +9954,6 @@ x_bitmap_icon (f, icon)
      struct frame *f;
      Lisp_Object icon;
 {
-  int mask, bitmap_id;
-  Window icon_window;
   HANDLE hicon;
 
   if (FRAME_W32_WINDOW (f) == 0)
@@ -9293,6 +9998,30 @@ x_bitmap_icon (f, icon)
 }
 
 \f
+/************************************************************************
+                         Handling X errors
+ ************************************************************************/
+
+/* Display Error Handling functions not used on W32. Listing them here
+   helps diff stay in step when comparing w32term.c with xterm.c.
+
+x_error_catcher (display, error)
+x_catch_errors (dpy)
+x_catch_errors_unwind (old_val)
+x_check_errors (dpy, format)
+x_had_errors_p (dpy)
+x_clear_errors (dpy)
+x_uncatch_errors (dpy, count)
+x_trace_wire ()
+x_connection_signal (signalnum)
+x_connection_closed (dpy, error_message)
+x_error_quitter (display, error)
+x_error_handler (display, error)
+x_io_error_quitter (display)
+
+ */
+
+\f
 /* Changing the font of the frame.  */
 
 /* Give frame F the font named FONTNAME as its default font, and
@@ -9331,7 +10060,8 @@ x_new_font (f, fontname)
   if (FRAME_W32_WINDOW (f) != 0)
     {
       frame_update_line_height (f);
-      x_set_window_size (f, 0, f->width, f->height);
+      if (NILP (tip_frame) || XFRAME (tip_frame) != f)
+        x_set_window_size (f, 0, f->width, f->height);
     }
   else
     /* If we are setting a new frame's font for the first time,
@@ -9353,7 +10083,6 @@ x_new_fontset (f, fontsetname)
 {
   int fontset = fs_query_fontset (build_string (fontsetname), 0);
   Lisp_Object result;
-  char *fontname;
 
   if (fontset < 0)
     return Qnil;
@@ -9375,92 +10104,104 @@ x_new_fontset (f, fontsetname)
   return build_string (fontsetname);
 }
 
+/* Compute actual fringe widths */
 
-#if GLYPH_DEBUG
-
-/* Check that FONT is valid on frame F.  It is if it can be found in F's
-   font table.  */
-
-static void
-x_check_font (f, font)
+void
+x_compute_fringe_widths (f, redraw)
      struct frame *f;
-     XFontStruct *font;
-{
-  int i;
-  struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
-
-  xassert (font != NULL);
-
-  for (i = 0; i < dpyinfo->n_fonts; i++)
-    if (dpyinfo->font_table[i].name 
-       && font == dpyinfo->font_table[i].font)
-      break;
-
-  xassert (i < dpyinfo->n_fonts);
-}
-
-#endif /* GLYPH_DEBUG != 0 */
-
-/* Set *W to the minimum width, *H to the minimum font height of FONT.
-   Note: There are (broken) X fonts out there with invalid XFontStruct
-   min_bounds contents.  For example, handa@etl.go.jp reports that
-   "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
-   have font->min_bounds.width == 0.  */
+     int redraw;
+{
+  int o_left = f->output_data.w32->left_fringe_width;
+  int o_right = f->output_data.w32->right_fringe_width;
+  int o_cols = f->output_data.w32->fringe_cols;
+
+  Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
+  Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
+  int left_fringe_width, right_fringe_width;
+
+  if (!NILP (left_fringe))
+    left_fringe = Fcdr (left_fringe);
+  if (!NILP (right_fringe))
+    right_fringe = Fcdr (right_fringe);
+
+  left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
+                      XINT (left_fringe));
+  right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
+                       XINT (right_fringe));
+
+  if (left_fringe_width || right_fringe_width)
+    {
+      int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
+      int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
+      int conf_wid = left_wid + right_wid;
+      int font_wid = FONT_WIDTH (f->output_data.w32->font);
+      int cols = (left_wid + right_wid + font_wid-1) / font_wid;
+      int real_wid = cols * font_wid;
+      if (left_wid && right_wid)
+       {
+         if (left_fringe_width < 0)
+           {
+             /* Left fringe width is fixed, adjust right fringe if necessary */
+             f->output_data.w32->left_fringe_width = left_wid;
+             f->output_data.w32->right_fringe_width = real_wid - left_wid;
+           }
+         else if (right_fringe_width < 0)
+           {
+             /* Right fringe width is fixed, adjust left fringe if necessary */
+             f->output_data.w32->left_fringe_width = real_wid - right_wid;
+             f->output_data.w32->right_fringe_width = right_wid;
+           }
+         else
+           {
+             /* Adjust both fringes with an equal amount.
+                Note that we are doing integer arithmetic here, so don't
+                lose a pixel if the total width is an odd number.  */
+             int fill = real_wid - conf_wid;
+             f->output_data.w32->left_fringe_width = left_wid + fill/2;
+             f->output_data.w32->right_fringe_width = right_wid + fill - fill/2;
+           }
+       }
+      else if (left_fringe_width)
+       {
+         f->output_data.w32->left_fringe_width = real_wid;
+         f->output_data.w32->right_fringe_width = 0;
+       }
+      else
+       {
+         f->output_data.w32->left_fringe_width = 0;
+         f->output_data.w32->right_fringe_width = real_wid;
+       }
+      f->output_data.w32->fringe_cols = cols;
+      f->output_data.w32->fringes_extra = real_wid;
+    }
+  else
+    {
+      f->output_data.w32->left_fringe_width = 0;
+      f->output_data.w32->right_fringe_width = 0;
+      f->output_data.w32->fringe_cols = 0;
+      f->output_data.w32->fringes_extra = 0;
+    }
 
-static INLINE void
-x_font_min_bounds (font, w, h)
-     XFontStruct *font;
-     int *w, *h;
-{
-  /*
-   * TODO: Windows does not appear to offer min bound, only
-   * average and maximum width, and maximum height.
-   */
-  *h = FONT_HEIGHT (font);
-  *w = FONT_WIDTH (font);
+  if (redraw && FRAME_VISIBLE_P (f))
+    if (o_left != f->output_data.w32->left_fringe_width ||
+       o_right != f->output_data.w32->right_fringe_width ||
+       o_cols != f->output_data.w32->fringe_cols)
+      redraw_frame (f);
 }
+\f
+/***********************************************************************
+       TODO: W32 Input Methods
+ ***********************************************************************/
+/* Listing missing functions from xterm.c helps diff stay in step.
 
+xim_destroy_callback (xim, client_data, call_data)
+xim_open_dpy (dpyinfo, resource_name)
+struct xim_inst_t
+xim_instantiate_callback (display, client_data, call_data)
+xim_initialize (dpyinfo, resource_name)
+xim_close_dpy (dpyinfo)
 
-/* Compute the smallest character width and smallest font height over
-   all fonts available on frame F.  Set the members smallest_char_width
-   and smallest_font_height in F's x_display_info structure to
-   the values computed.  Value is non-zero if smallest_font_height or
-   smallest_char_width become smaller than they were before.  */
-
-int
-x_compute_min_glyph_bounds (f)
-     struct frame *f;
-{
-  int i;
-  struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
-  XFontStruct *font;
-  int old_width = dpyinfo->smallest_char_width;
-  int old_height = dpyinfo->smallest_font_height;
-  
-  dpyinfo->smallest_font_height = 100000;
-  dpyinfo->smallest_char_width = 100000;
-  
-  for (i = 0; i < dpyinfo->n_fonts; ++i)
-    if (dpyinfo->font_table[i].name)
-      {
-       struct font_info *fontp = dpyinfo->font_table + i;
-       int w, h;
-       
-       font = (XFontStruct *) fontp->font;
-       xassert (font != (XFontStruct *) ~0);
-       x_font_min_bounds (font, &w, &h);
-       
-       dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
-       dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
-      }
-
-  xassert (dpyinfo->smallest_char_width > 0
-          && dpyinfo->smallest_font_height > 0);
-
-  return (dpyinfo->n_fonts == 1
-         || dpyinfo->smallest_char_width < old_width
-         || dpyinfo->smallest_font_height < old_height);
-}
+ */
 
 \f
 /* Calculate the absolute position in frame F
@@ -9470,14 +10211,14 @@ void
 x_calc_absolute_position (f)
      struct frame *f;
 {
-  Window child;
   POINT pt;
   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.  */
+     the inner window, with respect to the outer window.
+     But do this only if we will need the results.  */
   if (f->output_data.w32->parent_desc != FRAME_W32_DISPLAY_INFO (f)->root_window)
     {
       BLOCK_INPUT;
@@ -9560,10 +10301,120 @@ x_set_offset (f, xoff, yoff, change_gravity)
   UNBLOCK_INPUT;
 }
 
+
+/* Check if we need to resize the frame due to a fullscreen request.
+   If so needed, resize the frame. */
+static void
+x_check_fullscreen (f)
+     struct frame *f;
+{
+  if (f->output_data.w32->want_fullscreen & FULLSCREEN_BOTH)
+    {
+      int width, height, ign;
+                      
+      x_real_positions (f, &f->output_data.w32->left_pos,
+                        &f->output_data.w32->top_pos);
+
+      x_fullscreen_adjust (f, &width, &height, &ign, &ign);
+                  
+      /* We do not need to move the window, it shall be taken care of
+         when setting WM manager hints.
+         If the frame is visible already, the position is checked by
+         x_check_fullscreen_move. */
+      if (f->width != width || f->height != height)
+        {
+          change_frame_size (f, height, width, 0, 1, 0);
+          SET_FRAME_GARBAGED (f);
+          cancel_mouse_face (f);
+
+          /* Wait for the change of frame size to occur */
+          f->output_data.w32->want_fullscreen |= FULLSCREEN_WAIT;
+        }
+    }
+}
+
+/* If frame parameters are set after the frame is mapped, we need to move
+   the window.  This is done in xfns.c.
+   Some window managers moves the window to the right position, some
+   moves the outer window manager window to the specified position.
+   Here we check that we are in the right spot.  If not, make a second
+   move, assuming we are dealing with the second kind of window manager. */
+static void
+x_check_fullscreen_move (f)
+     struct frame *f;
+{
+  if (f->output_data.w32->want_fullscreen & FULLSCREEN_MOVE_WAIT)
+  {
+    int expect_top = f->output_data.w32->top_pos;
+    int expect_left = f->output_data.w32->left_pos;
+
+    if (f->output_data.w32->want_fullscreen & FULLSCREEN_HEIGHT)
+      expect_top = 0;
+    if (f->output_data.w32->want_fullscreen & FULLSCREEN_WIDTH)
+      expect_left = 0;
+    
+    if (expect_top != f->output_data.w32->top_pos
+        || expect_left != f->output_data.w32->left_pos)
+      x_set_offset (f, expect_left, expect_top, 1);
+
+    /* Just do this once */
+    f->output_data.w32->want_fullscreen &= ~FULLSCREEN_MOVE_WAIT;
+  }
+}
+
+
+/* Calculate fullscreen size.  Return in *TOP_POS and *LEFT_POS the
+   wanted positions of the WM window (not emacs window).
+   Return in *WIDTH and *HEIGHT the wanted width and height of Emacs
+   window (FRAME_X_WINDOW).
+ */
+void
+x_fullscreen_adjust (f, width, height, top_pos, left_pos)
+     struct frame *f;
+     int *width;
+     int *height;
+     int *top_pos;
+     int *left_pos;
+{
+  int newwidth = f->width, newheight = f->height;
+
+  *top_pos = f->output_data.w32->top_pos;
+  *left_pos = f->output_data.w32->left_pos;
+  
+  if (f->output_data.w32->want_fullscreen & FULLSCREEN_HEIGHT)
+    {
+      int ph;
+      
+      ph = FRAME_X_DISPLAY_INFO (f)->height;
+      newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);
+      ph = CHAR_TO_PIXEL_HEIGHT (f, newheight)
+        - f->output_data.w32->y_pixels_diff;
+      newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);
+      *top_pos = 0;
+    }
+
+  if (f->output_data.w32->want_fullscreen & FULLSCREEN_WIDTH)
+    {
+      int pw;
+      
+      pw = FRAME_X_DISPLAY_INFO (f)->width;
+      newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);
+      pw = CHAR_TO_PIXEL_WIDTH (f, newwidth)
+        - f->output_data.w32->x_pixels_diff;
+      newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);
+      *left_pos = 0;
+    }
+
+  *width = newwidth;
+  *height = newheight;
+}
+
+
 /* Call this to change the size of frame F's x-window.
    If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
    for this size change and subsequent size changes.
    Otherwise we leave the window gravity unchanged.  */
+
 void
 x_set_window_size (f, change_gravity, cols, rows)
      struct frame *f;
@@ -9579,8 +10430,9 @@ x_set_window_size (f, change_gravity, cols, rows)
     = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
        ? 0
        : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font)));
-  f->output_data.w32->flags_areas_extra
-    = FRAME_FLAGS_AREA_WIDTH (f);
+
+  x_compute_fringe_widths (f, 0);
+
   pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
   pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
   
@@ -9830,7 +10682,7 @@ x_make_frame_visible (f)
 
       f->output_data.w32->asked_for_visible = 1;
 
-//      my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW);
+/*      my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW);  */
       my_show_window (f, FRAME_W32_WINDOW (f), SW_SHOWNORMAL);
     }
 
@@ -9908,7 +10760,6 @@ void
 x_iconify_frame (f)
      struct frame *f;
 {
-  int result;
   Lisp_Object type;
 
   /* Don't keep the highlight on an invisible frame.  */
@@ -9929,6 +10780,7 @@ x_iconify_frame (f)
 
   UNBLOCK_INPUT;
 }
+
 \f
 /* Free X resources of frame F.  */
 
@@ -9951,7 +10803,11 @@ x_free_frame_resources (f)
   unload_color (f, f->output_data.w32->cursor_foreground_pixel);
   unload_color (f, f->output_data.w32->border_pixel);
   unload_color (f, f->output_data.w32->mouse_pixel);
-      
+  if (f->output_data.w32->white_relief.allocated_p)
+    unload_color (f, f->output_data.w32->white_relief.pixel);
+  if (f->output_data.w32->black_relief.allocated_p)
+    unload_color (f, f->output_data.w32->black_relief.pixel);
+
   if (FRAME_FACE_CACHE (f))
     free_frame_faces (f);
       
@@ -9991,6 +10847,7 @@ x_destroy_window (f)
 
   dpyinfo->reference_count--;
 }
+
 \f
 /* Setting window manager hints.  */
 
@@ -10033,7 +10890,113 @@ x_wm_set_icon_position (f, icon_x, icon_y)
 #endif
 }
 
+\f
+/***********************************************************************
+                               Fonts
+ ***********************************************************************/
+
+/* The following functions are listed here to help diff stay in step
+   with xterm.c.  See w32fns.c for definitions.
+
+x_get_font_info (f, font_idx)
+x_list_fonts (f, pattern, size, maxnames)
+
+ */
+
+#if GLYPH_DEBUG
 
+/* Check that FONT is valid on frame F.  It is if it can be found in F's
+   font table.  */
+
+static void
+x_check_font (f, font)
+     struct frame *f;
+     XFontStruct *font;
+{
+  int i;
+  struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
+
+  xassert (font != NULL);
+
+  for (i = 0; i < dpyinfo->n_fonts; i++)
+    if (dpyinfo->font_table[i].name 
+       && font == dpyinfo->font_table[i].font)
+      break;
+
+  xassert (i < dpyinfo->n_fonts);
+}
+
+#endif /* GLYPH_DEBUG != 0 */
+
+/* Set *W to the minimum width, *H to the minimum font height of FONT.
+   Note: There are (broken) X fonts out there with invalid XFontStruct
+   min_bounds contents.  For example, handa@etl.go.jp reports that
+   "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
+   have font->min_bounds.width == 0.  */
+
+static INLINE void
+x_font_min_bounds (font, w, h)
+     XFontStruct *font;
+     int *w, *h;
+{
+  /*
+   * TODO: Windows does not appear to offer min bound, only
+   * average and maximum width, and maximum height.
+   */
+  *h = FONT_HEIGHT (font);
+  *w = FONT_WIDTH (font);
+}
+
+
+/* Compute the smallest character width and smallest font height over
+   all fonts available on frame F.  Set the members smallest_char_width
+   and smallest_font_height in F's x_display_info structure to
+   the values computed.  Value is non-zero if smallest_font_height or
+   smallest_char_width become smaller than they were before.  */
+
+int
+x_compute_min_glyph_bounds (f)
+     struct frame *f;
+{
+  int i;
+  struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
+  XFontStruct *font;
+  int old_width = dpyinfo->smallest_char_width;
+  int old_height = dpyinfo->smallest_font_height;
+  
+  dpyinfo->smallest_font_height = 100000;
+  dpyinfo->smallest_char_width = 100000;
+  
+  for (i = 0; i < dpyinfo->n_fonts; ++i)
+    if (dpyinfo->font_table[i].name)
+      {
+       struct font_info *fontp = dpyinfo->font_table + i;
+       int w, h;
+       
+       font = (XFontStruct *) fontp->font;
+       xassert (font != (XFontStruct *) ~0);
+       x_font_min_bounds (font, &w, &h);
+       
+       dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
+       dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
+      }
+
+  xassert (dpyinfo->smallest_char_width > 0
+          && dpyinfo->smallest_font_height > 0);
+
+  return (dpyinfo->n_fonts == 1
+         || dpyinfo->smallest_char_width < old_width
+         || dpyinfo->smallest_font_height < old_height);
+}
+
+/* The following functions are listed here to help diff stay in step
+   with xterm.c.  See w32fns.c for definitions.
+
+x_load_font (f, fontname, size)
+x_query_font (f, fontname)
+x_find_ccl_program (fontp)
+
+*/
 \f
 /***********************************************************************
                            Initialization
@@ -10077,7 +11040,8 @@ w32_initialize_display_info (display_name)
   dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
   dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
   dpyinfo->mouse_face_window = Qnil;
-
+  dpyinfo->mouse_face_overlay = Qnil;
+  dpyinfo->mouse_face_hidden = 0;
   /* TODO: dpyinfo->gray */
 
 }
@@ -10115,6 +11079,10 @@ w32_term_init (display_name, xrm_option, resource_name)
   w32_initialize_display_info (display_name);
 
   dpyinfo = &one_w32_display_info;
+
+  /* Put this display on the chain.  */
+  dpyinfo->next = x_display_list;
+  x_display_list = dpyinfo;
   
   hdc = GetDC (GetDesktopWindow ());
 
@@ -10189,7 +11157,7 @@ x_delete_display (dpyinfo)
        {
          if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
            {
-             XCDR (tail) = XCDR (XCDR (tail));
+             XSETCDR (tail, XCDR (XCDR (tail)));
              break;
            }
          tail = XCDR (tail);
@@ -10256,18 +11224,14 @@ w32_initialize ()
   /* MSVC does not type K&R functions with no arguments correctly, and
      so we must explicitly cast them.  */
   clear_frame_hook = (void (*)(void)) x_clear_frame;
-  ins_del_lines_hook = x_ins_del_lines;
-  change_line_highlight_hook = x_change_line_highlight;
-  delete_glyphs_hook = x_delete_glyphs;
   ring_bell_hook = (void (*)(void)) w32_ring_bell;
-  reset_terminal_modes_hook = (void (*)(void)) w32_reset_terminal_modes;
-  set_terminal_modes_hook = (void (*)(void)) w32_set_terminal_modes;
   update_begin_hook = x_update_begin;
   update_end_hook = x_update_end;
-  set_terminal_window_hook = w32_set_terminal_window;
+
   read_socket_hook = w32_read_socket;
+
   frame_up_to_date_hook = w32_frame_up_to_date;
-  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;
@@ -10278,13 +11242,18 @@ w32_initialize ()
   estimate_mode_line_height_hook = x_estimate_mode_line_height;
 
   scroll_region_ok = 1;         /* we'll scroll partial frames */
-  char_ins_del_ok = 0;          /* just as fast to write the line */
+  char_ins_del_ok = 1;
   line_ins_del_ok = 1;          /* we'll just blt 'em */
   fast_clear_end_of_line = 1;   /* X does this well */
   memory_below_frame = 0;       /* we don't remember what scrolls
                                   off the bottom */
   baud_rate = 19200;
 
+  w32_system_caret_hwnd = NULL;
+  w32_system_caret_height = 0;
+  w32_system_caret_x = 0;
+  w32_system_caret_y = 0;
+
   last_tool_bar_item = -1;
   any_help_event_p = 0;
 
@@ -10366,43 +11335,43 @@ syms_of_w32term ()
 
   DEFVAR_INT ("w32-num-mouse-buttons",
              &Vw32_num_mouse_buttons,
-             "Number of physical mouse buttons.");
+             doc: /* Number of physical mouse buttons.  */);
   Vw32_num_mouse_buttons = Qnil;
 
   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.");
+              doc: /* Swap the mapping of middle and right mouse buttons.
+When nil, middle button is mouse-2 and right button is mouse-3.  */);
   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.");
+              doc: /* Raised frame grabs input focus.
+When t, `raise-frame' grabs input focus as well.  This fits well
+with the normal Windows click-to-focus policy, but might not be
+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.");
+              doc: /* Apply CapsLock state to non character input keys.
+When nil, CapsLock only affects normal character input keys.  */);
   Vw32_capslock_is_shiftlock = Qnil;
 
   DEFVAR_LISP ("w32-recognize-altgr",
               &Vw32_recognize_altgr,
-              "Recognize right-alt and left-ctrl as AltGr.\n\
-When nil, the right-alt and left-ctrl key combination is\n\
-interpreted normally."); 
+              doc: /* Recognize right-alt and left-ctrl as AltGr.
+When nil, the right-alt and left-ctrl key combination is
+interpreted normally.  */); 
   Vw32_recognize_altgr = Qt;
 
   DEFVAR_BOOL ("w32-enable-unicode-output",
                &w32_enable_unicode_output,
-               "Enable the use of Unicode for text output if non-nil.\n\
-Unicode output may prevent some third party applications for displaying\n\
-Far-East Languages on Windows 95/98 from working properly.\n\
-NT uses Unicode internally anyway, so this flag will probably have no\n\
-affect on NT machines.");
+               doc: /* Enable the use of Unicode for text output if non-nil.
+Unicode output may prevent some third party applications for displaying
+Far-East Languages on Windows 95/98 from working properly.
+NT uses Unicode internally anyway, so this flag will probably have no
+affect on NT machines.  */);
   w32_enable_unicode_output = 1;
 
   help_echo = Qnil;
@@ -10415,14 +11384,47 @@ affect on NT machines.");
   staticpro (&previous_help_echo);
   help_echo_pos = -1;
 
+  DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p,
+    doc: /* *Non-nil means autoselect window with mouse pointer.  */);
+  x_autoselect_window_p = 0;
+
+  DEFVAR_BOOL ("w32-use-visible-system-caret",
+              &w32_use_visible_system_caret,
+              doc: /* Flag to make the system caret visible.
+When this is non-nil, Emacs will indicate the position of point by
+using the system caret instead of drawing its own cursor.  Some screen
+reader software does not track the system cursor properly when it is
+invisible, and gets confused by Emacs drawing its own cursor, so this
+variable is initialized to t when Emacs detects that screen reader 
+software is running as it starts up.
+
+When this variable is set, other variables affecting the appearance of
+the cursor have no effect.  */);
+
+  /* Initialize w32_use_visible_system_caret based on whether a screen
+     reader is in use.  */
+  if (!SystemParametersInfo (SPI_GETSCREENREADER, 0,
+                            &w32_use_visible_system_caret, 0))
+    w32_use_visible_system_caret = 0;
+
   DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
-    "*Non-nil means draw block cursor as wide as the glyph under it.\n\
-For example, if a block cursor is over a tab, it will be drawn as\n\
-wide as that tab on the display.");
+              doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
+For example, if a block cursor is over a tab, it will be drawn as
+wide as that tab on the display.  */);
   x_stretch_cursor_p = 0;
 
+#if 0 /* TODO: Setting underline position from font properties.  */
+  DEFVAR_BOOL ("x-use-underline-position-properties",
+              &x_use_underline_position_properties,
+              doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
+nil means ignore them.  If you encounter fonts with bogus
+UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
+to 4.1, set this to nil.  */);
+  x_use_underline_position_properties = 1;
+#endif
+
   DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
-    "If not nil, Emacs uses toolkit scroll bars.");
+              doc: /* If not nil, Emacs uses toolkit scroll bars.  */);
   Vx_toolkit_scroll_bars = Qt;
 
   staticpro (&last_mouse_motion_frame);