Revisited my earlier fix for the following entry in etc/PROBLEMS: 'Emacs built on...
[bpt/emacs.git] / src / w32term.c
index 23cde3c..08b076d 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
+#define zv_height 72
+#define zv_period 3
 static unsigned short zv_bits[] = {
-   0x00, 0x00, 0x78, 0x78, 0x78, 0x78, 0x00, 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, 0x00, 0x3c, 0x00};
 static HBITMAP zv_bmp;
 
 /* An arrow like this: `<-'.  */
@@ -145,39 +149,47 @@ static HBITMAP ov_bmp;
 extern Lisp_Object Qhelp_echo;
 
 \f
-/* Non-zero means Emacs uses toolkit scroll bars.  */
+/* Non-nil means Emacs uses toolkit scroll bars.  */
 
-int x_toolkit_scroll_bars_p;
+Lisp_Object Vx_toolkit_scroll_bars;
 
 /* If a string, w32_read_socket generates an event to display that string.
    (The display is done in read_char.)  */
-   
+
 static Lisp_Object help_echo;
 static Lisp_Object help_echo_window;
 static Lisp_Object help_echo_object;
 static int help_echo_pos;
 
-/* Temporary variable for w32_read_socket.  */
+/* Temporary variables for w32_read_socket.  */
 
 static Lisp_Object previous_help_echo;
+static int last_mousemove_x = 0;
+static int last_mousemove_y = 0;
 
 /* Non-zero means that a HELP_EVENT has been generated since Emacs
    start.  */
 
 static int any_help_event_p;
 
+/* Non-zero means autoselect window with the mouse cursor.  */
+
+int mouse_autoselect_window;
+
 /* 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 +202,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 +226,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 +335,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 +354,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 +385,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 +394,39 @@ 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 x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
+                                  enum text_cursor_kinds));
 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 void expose_overlaps P_ ((struct window *, struct glyph_row *,
+                                struct glyph_row *));
+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;
 
@@ -413,7 +440,7 @@ static Lisp_Object Qvendor_specific_keysyms;
 /* This is a function useful for recording debugging information about
    the sequence of occurrences in this file.  */
 
-struct record 
+struct record
 {
   char *locus;
   int type;
@@ -502,7 +529,7 @@ w32_draw_rectangle (HDC hdc, XGCValues *gc, int x, int y,
 }
 
 /* Draw a filled rectangle at the specified position. */
-void 
+void
 w32_fill_rect (f, hdc, pix, lprect)
      FRAME_PTR f;
      HDC hdc;
@@ -510,22 +537,28 @@ w32_fill_rect (f, hdc, pix, lprect)
      RECT * lprect;
 {
   HBRUSH hb;
-  RECT rect;
 
   hb = CreateSolidBrush (pix);
   FillRect (hdc, lprect, hb);
   DeleteObject (hb);
 }
 
-void 
+void
 w32_clear_window (f)
      FRAME_PTR f;
 {
   RECT rect;
   HDC hdc = get_frame_dc (f);
 
-  GetClientRect (FRAME_W32_WINDOW (f), &rect);
-  w32_clear_rect (f, hdc, &rect);
+  /* Under certain conditions, this can be called at startup with
+     a console frame pointer before the GUI frame is created. An HDC
+     of 0 indicates this. */
+  if (hdc)
+    {
+      GetClientRect (FRAME_W32_WINDOW (f), &rect);
+      w32_clear_rect (f, hdc, &rect);
+    }
+
   release_frame_dc (f, hdc);
 }
 
@@ -533,20 +566,28 @@ w32_clear_window (f)
 /***********************************************************************
                    Starting and ending an update
  ***********************************************************************/
-                                                                       
+
 /* Start an update of frame F.  This function is installed as a hook
    for update_begin, i.e. it is called when update_begin is called.
    This function is called prior to calls to x_update_window_begin for
-   each window being updated.  Currently, there is nothing to do here
-   because all interesting stuff is done on a window basis.  */
+   each window being updated.  */
 
 static void
 x_update_begin (f)
      struct frame *f;
 {
-  /* Nothing to do.  We have to do something though, otherwise the
-     function gets optimized away and the hook is no longer valid. */
-  struct frame *cf = f;
+  struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
+
+  if (! FRAME_W32_P (f))
+    return;
+
+  /* Regenerate display palette before drawing if list of requested
+     colors has changed. */
+  if (display_info->regen_palette)
+  {
+    w32_regenerate_palette (f);
+    display_info->regen_palette = FALSE;
+  }
 }
 
 
@@ -561,19 +602,17 @@ 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 && w32_system_caret_hwnd)
+    {
+      SendMessage (w32_system_caret_hwnd, WM_EMACS_HIDE_CARET, 0, 0);
+    }
+
   updated_window = w;
   set_output_cursor (&w->cursor);
 
   BLOCK_INPUT;
 
-  /* Regenerate display palette before drawing if list of requested
-     colors has changed. */
-  if (display_info->regen_palette)
-  {
-    w32_regenerate_palette (f);
-    display_info->regen_palette = FALSE;
-  }
-
   if (f == display_info->mouse_face_mouse_frame)
     {
       /* Don't do highlighting for mouse motion during the update.  */
@@ -590,7 +629,7 @@ x_update_window_begin (w)
         flag set.  So, rows containing mouse-face glyphs are never
         scrolled, and we don't have to switch the mouse highlight off
         here to prevent it from being scrolled.  */
-      
+
       /* Can we tell that this update does not affect the window
         where the mouse highlight is?  If so, no need to turn off.
         Likewise, don't do anything if the frame is garbaged;
@@ -623,7 +662,7 @@ x_draw_vertical_border (w)
      struct window *w;
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
-  
+
   /* Redraw borders between horizontally adjacent windows.  Don't
      do it for frames with vertical scroll bars because either the
      right scroll bar of a window, or the left scroll bar of its
@@ -634,18 +673,19 @@ 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;
 
       hdc = get_frame_dc (f);
-      w32_fill_rect (f, hdc, FRAME_FOREGROUND_PIXEL (f), r);
+      w32_fill_rect (f, hdc, FRAME_FOREGROUND_PIXEL (f), &r);
       release_frame_dc (f, hdc);
     }
 }
 
-   
+
 /* End update of window W (which is equal to updated_window).
 
    Draw vertical borders between horizontally adjacent windows, and
@@ -664,30 +704,39 @@ 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 && w32_system_caret_hwnd)
+    {
+      SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
+    }
+
   updated_window = NULL;
 }
 
@@ -699,6 +748,9 @@ static void
 x_update_end (f)
      struct frame *f;
 {
+  if (! FRAME_W32_P (f))
+    return;
+
   /* Mouse highlight may be displayed again.  */
   FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 0;
 }
@@ -731,9 +783,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.  */
 
@@ -742,158 +794,216 @@ 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;
-  HBRUSH fg_brush, orig_brush;
   HANDLE horig_obj;
   struct face *face;
 
   /* 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);
-  fg_brush = CreateSolidBrush (FRAME_FOREGROUND_PIXEL (f));
-  orig_brush = SelectObject (hdc, fg_brush);
+
   horig_obj = SelectObject (compat_hdc, pixmap);
-  SetTextColor (hdc, FRAME_BACKGROUND_PIXEL (f));
-  SetBkColor (hdc, FRAME_FOREGROUND_PIXEL (f));
-#if 0 /* From w32bdf.c (which is from Meadow).  */
-  BitBlt (hdc, x, y + dy, wd, h, compat_hdc, 0, 0, SRCCOPY);
-#else
-  BitBlt (hdc, x, y + dy, wd, h, compat_hdc, 0, 0, 0xB8074A);
-#endif
+  SetTextColor (hdc, face->background);
+  SetBkColor (hdc, face->foreground);
+
+  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);
-  SelectObject (hdc, orig_brush);
-  DeleteObject (fg_brush);
   DeleteDC (compat_hdc);
   RestoreDC (hdc, -1);
 }
 
 
-/* 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);
 
@@ -902,108 +1012,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;
-{
-  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;
-{
-  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
@@ -1046,7 +1092,7 @@ set_output_cursor (cursor)
 
    HPOS and VPOS are column/row positions in a window glyph matrix.  X
    and Y are window text area relative pixel positions.
-   
+
    If this is done during an update, updated_window will contain the
    window that is being updated and the position is the future output
    cursor position for that window.  If updated_window is null, use
@@ -1134,7 +1180,7 @@ w32_bdf_per_char_metric (font, char2b, dim, pcm)
   char buf[2];
 
   if (dim == 1)
-    buf[0] = (char)char2b;
+    buf[0] = (char)(*char2b);
   else
     {
       buf[0] = BYTE1 (*char2b);
@@ -1150,7 +1196,7 @@ w32_bdf_per_char_metric (font, char2b, dim, pcm)
       pcm->rbearing = bdf_metric->dwidth
                     - (bdf_metric->bbox + bdf_metric->bbw);
       pcm->ascent = bdf_metric->bboy + bdf_metric->bbh;
-      pcm->descent = bdf_metric->bboy;
+      pcm->descent = -bdf_metric->bboy;
 
       return 1;
     }
@@ -1165,9 +1211,6 @@ w32_native_per_char_metric (font, char2b, font_type, pcm)
      enum w32_char_font_type font_type;
      XCharStruct * pcm;
 {
-  /* NTEMACS_TODO: Use GetGlyphOutline where possible (no Unicode
-     version on W9x) */
-
   HDC hdc = GetDC (NULL);
   HFONT old_font;
   BOOL retval = FALSE;
@@ -1189,9 +1232,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);
        }
@@ -1205,6 +1263,11 @@ w32_native_per_char_metric (font, char2b, font_type, pcm)
         though - we can call GetTextExtentPoint32 to get rbearing and
         deduce width based on the font's per-string overhang.  lbearing
         is assumed to be zero.  */
+
+      /* TODO: Some Thai characters (and other composites if Windows
+         supports them) do have lbearing, and report their total width
+         as zero. Need some way of handling them when
+         GetCharABCWidthsW fails. */
       SIZE sz;
 
       if (font_type == UNICODE_FONT)
@@ -1249,10 +1312,10 @@ w32_per_char_metric (font, char2b, font_type)
   xassert (font_type != UNKNOWN_FONT);
 
   /* Handle the common cases quickly.  */
-  if (font->per_char == NULL)
+  if (!font->bdf && font->per_char == NULL)
     /* TODO: determine whether char2b exists in font?  */
     return &font->max_bounds;
-  else if (*char2b < 128)
+  else if (!font->bdf && *char2b < 128)
     return &font->per_char[*char2b];
 
   pcm = &font->scratch;
@@ -1280,7 +1343,16 @@ w32_cache_char_metrics (font)
   if (font->bdf)
     {
       /* TODO: determine whether font is fixed-pitch.  */
-      w32_bdf_per_char_metric (font, &char2b, 1, &font->max_bounds);
+      if (!w32_bdf_per_char_metric (font, &char2b, 1, &font->max_bounds))
+        {
+          /* Use the font width and height as max bounds, as not all BDF
+             fonts contain the letter 'x'. */
+          font->max_bounds.width = FONT_MAX_WIDTH (font);
+          font->max_bounds.lbearing = -font->bdf->llx;
+          font->max_bounds.rbearing = FONT_MAX_WIDTH (font) - font->bdf->urx;
+          font->max_bounds.ascent = FONT_BASE (font);
+          font->max_bounds.descent = FONT_DESCENT (font);
+        }
     }
   else
     {
@@ -1318,6 +1390,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.  */
 
@@ -1372,11 +1454,11 @@ w32_encode_char (c, char2b, font_info, two_byte_p)
       /* Fixed encoding scheme.  See fontset.h for the meaning of the
         encoding numbers.  */
       int enc = font_info->encoding[charset];
-      
+
       if ((enc == 1 || enc == 2)
          && CHARSET_DIMENSION (charset) == 2)
        *char2b = BUILD_WCHAR_T (BYTE1 (*char2b) | 0x80, BYTE2 (*char2b));
-      
+
       if (enc == 1 || enc == 3
           || (enc == 4 && CHARSET_DIMENSION (charset) == 1))
        *char2b = BUILD_WCHAR_T (BYTE1 (*char2b), BYTE2 (*char2b) | 0x80);
@@ -1389,21 +1471,25 @@ 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);
       temp[1] = BYTE2 (*char2b);
       temp[2] = '\0';
-      if (temp[0])
-        MultiByteToWideChar (codepage, 0, temp, 2, char2b, 1);
-      else
-        MultiByteToWideChar (codepage, 0, temp+1, 1, char2b, 1);
+      if (codepage != CP_UNICODE)
+        {
+          if (temp[0])
+            MultiByteToWideChar (codepage, 0, temp, 2, char2b, 1);
+          else
+            MultiByteToWideChar (codepage, 0, temp+1, 1, char2b, 1);
+        }
       unicode_p = 1;
       *two_byte_p = 1;
     }
@@ -1450,7 +1536,7 @@ x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
   else
     {
       int c1, c2, charset;
-      
+
       /* Split characters into bytes.  If c2 is -1 afterwards, C is
         really a one-byte character so that byte1 is zero.  */
       SPLIT_CHAR (c, charset, c1, c2);
@@ -1458,7 +1544,7 @@ x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
        *char2b = BUILD_WCHAR_T (c1, c2);
       else
        *char2b = BUILD_WCHAR_T (0, c1);
-  
+
       /* Maybe encode the character in *CHAR2B.  */
       if (face->font != NULL)
        {
@@ -1472,7 +1558,7 @@ x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
   /* Make sure X resources of the face are allocated.  */
   xassert (face != NULL);
   PREPARE_FACE_FOR_DISPLAY (f, face);
-  
+
   return face;
 }
 
@@ -1514,7 +1600,7 @@ x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
   else
     {
       int c1, c2, charset;
-      
+
       /* Split characters into bytes.  If c2 is -1 afterwards, C is
         really a one-byte character so that byte1 is zero.  */
       SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
@@ -1543,7 +1629,7 @@ x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
 }
 
 
-/* Store one glyph for IT->char_to_display in IT->glyph_row.  
+/* Store one glyph for IT->char_to_display in IT->glyph_row.
    Called from x_produce_glyphs when IT->glyph_row is non-null.  */
 
 static INLINE void
@@ -1552,10 +1638,10 @@ x_append_glyph (it)
 {
   struct glyph *glyph;
   enum glyph_row_area area = it->area;
-  
+
   xassert (it->glyph_row);
   xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
-  
+
   glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
   if (glyph < it->glyph_row->glyphs[area + 1])
     {
@@ -1578,7 +1664,7 @@ x_append_glyph (it)
     }
 }
 
-/* Store one glyph for the composition IT->cmp_id in IT->glyph_row.  
+/* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
    Called from x_produce_glyphs when IT->glyph_row is non-null.  */
 
 static INLINE void
@@ -1587,9 +1673,9 @@ x_append_composite_glyph (it)
 {
   struct glyph *glyph;
   enum glyph_row_area area = it->area;
-  
+
   xassert (it->glyph_row);
-  
+
   glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
   if (glyph < it->glyph_row->glyphs[area + 1])
     {
@@ -1656,29 +1742,32 @@ 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);
-  
+
   if (it->glyph_row)
     {
       struct glyph *glyph;
       enum glyph_row_area area = it->area;
-      
+
       glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
       if (glyph < it->glyph_row->glyphs[area + 1])
        {
@@ -1703,10 +1792,10 @@ x_produce_image_glyph (it)
 
 
 /* Append a stretch glyph to IT->glyph_row.  OBJECT is the source
-   of the glyph, WIDTH and HEIGHT are the width and height of the 
-   stretch.  ASCENT is the percentage/100 of HEIGHT to use for the 
+   of the glyph, WIDTH and HEIGHT are the width and height of the
+   stretch.  ASCENT is the percentage/100 of HEIGHT to use for the
    ascent of the glyph (0 <= ASCENT <= 1).  */
-  
+
 static void
 x_append_stretch_glyph (it, object, width, height, ascent)
      struct it *it;
@@ -1718,7 +1807,7 @@ x_append_stretch_glyph (it, object, width, height, ascent)
   enum glyph_row_area area = it->area;
 
   xassert (ascent >= 0 && ascent <= 1);
-  
+
   glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
   if (glyph < it->glyph_row->glyphs[area + 1])
     {
@@ -1748,7 +1837,7 @@ x_append_stretch_glyph (it, object, width, height, ascent)
    being recognized:
 
    1. `:width WIDTH' specifies that the space should be WIDTH *
-   canonical char width wide.  WIDTH may be an integer or floating 
+   canonical char width wide.  WIDTH may be an integer or floating
    point number.
 
    2. `:relative-width FACTOR' specifies that the width of the stretch
@@ -1758,12 +1847,12 @@ x_append_stretch_glyph (it, object, width, height, ascent)
    3. `:align-to HPOS' specifies that the space should be wide enough
    to reach HPOS, a value in canonical character units.
 
-   Exactly one of the above pairs must be present.  
+   Exactly one of the above pairs must be present.
 
    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.
 
@@ -1784,7 +1873,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;
@@ -1793,7 +1885,7 @@ x_produce_stretch_glyph (it)
   XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
 
   PREPARE_FACE_FOR_DISPLAY (it->f, face);
-  
+
   /* List should start with `space'.  */
   xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
   plist = XCDR (it->object);
@@ -1811,7 +1903,7 @@ x_produce_stretch_glyph (it)
         property.  */
       struct it it2;
       unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
-      
+
       it2 = *it;
       if (it->multibyte_p)
        {
@@ -1833,7 +1925,7 @@ x_produce_stretch_glyph (it)
   else
     /* Nothing specified -> width defaults to canonical char width.  */
     width = CANON_X_UNIT (it->f);
-  
+
   /* Compute height.  */
   if (prop = Fplist_get (plist, QCheight),
       NUMVAL (prop) > 0)
@@ -1844,7 +1936,7 @@ x_produce_stretch_glyph (it)
   else
     height = FONT_HEIGHT (font);
 
-  /* Compute percentage of height used for ascent.  If 
+  /* Compute percentage of height used for ascent.  If
      `:ascent ASCENT' is present and valid, use that.  Otherwise,
      derive the ascent from the font in use.  */
   if (prop = Fplist_get (plist, QCascent),
@@ -1873,15 +1965,18 @@ 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);
 }
 
@@ -1914,9 +2009,10 @@ x_produce_stretch_glyph (it)
 */
 
 #define VCENTER_BASELINE_OFFSET(FONT, F)                       \
- (FONT_DESCENT (FONT)                                          \
-  + (FRAME_LINE_HEIGHT ((F)) + 1 - FONT_HEIGHT ((FONT))) / 2   \
-  - (FONT_DESCENT (FRAME_FONT (F)) - FRAME_BASELINE_OFFSET (F)))
+  (FONT_DESCENT (FONT)                                         \
+   + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT))           \
+      + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2  \
+   - (FONT_DESCENT (FRAME_FONT (F)) - FRAME_BASELINE_OFFSET (F)))
 
 /* Produce glyphs/get display metrics for the display element IT is
    loaded with.  See the description of struct display_iterator in
@@ -1967,13 +2063,12 @@ 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);
            }
         }
-      
+
       /* Get font to use.  Encode IT->char_to_display.  */
       x_get_char_face_and_encoding (it->f, it->char_to_display,
                                     it->face_id, &char2b,
@@ -2022,7 +2117,7 @@ x_produce_glyphs (it)
               it->phys_descent = FONT_DESCENT (font) - boff;
               it->pixel_width = FONT_WIDTH (font);
             }
-          
+
          /* If this is a space inside a region of text with
             `space-width' property, change its width.  */
          stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
@@ -2035,10 +2130,15 @@ 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;
              if (it->end_of_box_run_p)
@@ -2051,7 +2151,7 @@ x_produce_glyphs (it)
            it->ascent += 2;
 
          take_vertical_position_into_account (it);
-  
+
          /* If we have to actually produce glyphs, do it.  */
          if (it->glyph_row)
            {
@@ -2061,7 +2161,7 @@ x_produce_glyphs (it)
                     into a stretch glyph.  */
                  double ascent = (double) FONT_BASE (font)
                                 / FONT_HEIGHT (font);
-                 x_append_stretch_glyph (it, it->object, it->pixel_width, 
+                 x_append_stretch_glyph (it, it->object, it->pixel_width,
                                          it->ascent + it->descent, ascent);
                }
              else
@@ -2081,12 +2181,12 @@ x_produce_glyphs (it)
          it->nglyphs = 0;
          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')
@@ -2094,7 +2194,7 @@ x_produce_glyphs (it)
          int tab_width = it->tab_width * CANON_X_UNIT (it->f);
          int x = it->current_x + it->continuation_lines_width;
          int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
-      
+
          /* If the distance from the current position to the next tab
             stop is less than a canonical character width, use the
             tab stop after that.  */
@@ -2105,15 +2205,15 @@ x_produce_glyphs (it)
          it->nglyphs = 1;
          it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
          it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
-         
+
          if (it->glyph_row)
            {
              double ascent = (double) it->ascent / (it->ascent + it->descent);
-             x_append_stretch_glyph (it, it->object, it->pixel_width, 
+             x_append_stretch_glyph (it, it->object, it->pixel_width,
                                      it->ascent + it->descent, ascent);
            }
        }
-      else 
+      else
        {
          /* A multi-byte character.
              If we found a font, this font should give us the right
@@ -2155,26 +2255,31 @@ 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;
              if (it->end_of_box_run_p)
                it->pixel_width += thick;
            }
-  
+
          /* If face has an overline, add the height of the overline
             (1 pixel) and a 1 pixel margin to the character height.  */
          if (face->overline_p)
            it->ascent += 2;
 
          take_vertical_position_into_account (it);
-  
+
          if (it->glyph_row)
            x_append_glyph (it);
        }
@@ -2182,19 +2287,302 @@ x_produce_glyphs (it)
     }
   else if (it->what == IT_COMPOSITION)
     {
-      /* NTEMACS_TODO: Composite glyphs.  */
-    }
-  else if (it->what == IT_IMAGE)
-    x_produce_image_glyph (it);
-  else if (it->what == IT_STRETCH)
-    x_produce_stretch_glyph (it);
+      /* Note: A composition is represented as one glyph in the
+        glyph matrix.  There are no padding glyphs.  */
+      wchar_t char2b;
+      XFontStruct *font;
+      struct face *face = FACE_FROM_ID (it->f, it->face_id);
+      XCharStruct *pcm;
+      int font_not_found_p;
+      struct font_info *font_info;
+      int boff;                        /* baseline offset */
+      struct composition *cmp = composition_table[it->cmp_id];
 
-  /* Accumulate dimensions.  */
-  xassert (it->ascent >= 0 && it->descent > 0);
-  if (it->area == TEXT_AREA)
-    it->current_x += it->pixel_width;
+      /* Maybe translate single-byte characters to multibyte.  */
+      it->char_to_display = it->c;
+      if (unibyte_display_via_language_environment
+         && SINGLE_BYTE_CHAR_P (it->c)
+         && (it->c >= 0240
+             || (it->c >= 0200
+                 && !NILP (Vnonascii_translation_table))))
+       {
+         it->char_to_display = unibyte_char_to_multibyte (it->c);
+       }
 
-  it->descent += it->extra_line_spacing;
+      /* Get face and font to use.  Encode IT->char_to_display.  */
+      it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
+      face = FACE_FROM_ID (it->f, it->face_id);
+      x_get_char_face_and_encoding (it->f, it->char_to_display,
+                                   it->face_id, &char2b, it->multibyte_p);
+      font = face->font;
+
+      /* When no suitable font found, use the default font.  */
+      font_not_found_p = font == NULL;
+      if (font_not_found_p)
+       {
+         font = FRAME_FONT (it->f);
+         boff = it->f->output_data.w32->baseline_offset;
+         font_info = NULL;
+       }
+      else
+       {
+         font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
+         boff = font_info->baseline_offset;
+         if (font_info->vertical_centering)
+           boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
+       }
+
+      /* There are no padding glyphs, so there is only one glyph to
+        produce for the composition.  Important is that pixel_width,
+        ascent and descent are the values of what is drawn by
+        draw_glyphs (i.e. the values of the overall glyphs composed).  */
+      it->nglyphs = 1;
+
+      /* If we have not yet calculated pixel size data of glyphs of
+        the composition for the current face font, calculate them
+        now.  Theoretically, we have to check all fonts for the
+        glyphs, but that requires much time and memory space.  So,
+        here we check only the font of the first glyph.  This leads
+        to incorrect display very rarely, and C-l (recenter) can
+        correct the display anyway.  */
+      if (cmp->font != (void *) font)
+       {
+         /* Ascent and descent of the font of the first character of
+            this composition (adjusted by baseline offset).  Ascent
+            and descent of overall glyphs should not be less than
+            them respectively.  */
+         int font_ascent = FONT_BASE (font) + boff;
+         int font_descent = FONT_DESCENT (font) - boff;
+         /* Bounding box of the overall glyphs.  */
+         int leftmost, rightmost, lowest, highest;
+         int i, width, ascent, descent;
+          enum w32_char_font_type font_type;
+
+         cmp->font = (void *) font;
+
+          if (font->bdf && CHARSET_DIMENSION (CHAR_CHARSET (it->c)) == 1)
+            font_type = BDF_1D_FONT;
+          else if (font->bdf)
+            font_type = BDF_2D_FONT;
+          else
+            font_type = UNICODE_FONT;
+
+         /* Initialize the bounding box.  */
+         if (font_info
+              && (pcm = w32_per_char_metric (font, &char2b, font_type)))
+           {
+             width = pcm->width;
+             ascent = pcm->ascent;
+             descent = pcm->descent;
+           }
+         else
+           {
+             width = FONT_WIDTH (font);
+             ascent = FONT_BASE (font);
+             descent = FONT_DESCENT (font);
+           }
+
+         rightmost = width;
+         lowest = - descent + boff;
+         highest = ascent + boff;
+         leftmost = 0;
+
+         if (font_info
+             && font_info->default_ascent
+             && CHAR_TABLE_P (Vuse_default_ascent)
+             && !NILP (Faref (Vuse_default_ascent,
+                              make_number (it->char_to_display))))
+           highest = font_info->default_ascent + boff;
+
+         /* Draw the first glyph at the normal position.  It may be
+            shifted to right later if some other glyphs are drawn at
+            the left.  */
+         cmp->offsets[0] = 0;
+         cmp->offsets[1] = boff;
+
+         /* Set cmp->offsets for the remaining glyphs.  */
+         for (i = 1; i < cmp->glyph_len; i++)
+           {
+             int left, right, btm, top;
+             int ch = COMPOSITION_GLYPH (cmp, i);
+             int face_id = FACE_FOR_CHAR (it->f, face, ch);
+
+             face = FACE_FROM_ID (it->f, face_id);
+             x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
+                                           it->multibyte_p);
+             font = face->font;
+             if (font == NULL)
+               {
+                 font = FRAME_FONT (it->f);
+                 boff = it->f->output_data.w32->baseline_offset;
+                 font_info = NULL;
+               }
+             else
+               {
+                 font_info
+                   = FONT_INFO_FROM_ID (it->f, face->font_info_id);
+                 boff = font_info->baseline_offset;
+                 if (font_info->vertical_centering)
+                   boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
+               }
+
+              if (font->bdf && CHARSET_DIMENSION (CHAR_CHARSET (ch)) == 1)
+                font_type = BDF_1D_FONT;
+              else if (font->bdf)
+                font_type = BDF_2D_FONT;
+              else
+                font_type = UNICODE_FONT;
+
+             if (font_info
+                  && (pcm = w32_per_char_metric (font, &char2b, font_type)))
+               {
+                 width = pcm->width;
+                 ascent = pcm->ascent;
+                 descent = pcm->descent;
+               }
+             else
+               {
+                 width = FONT_WIDTH (font);
+                 ascent = 1;
+                 descent = 0;
+               }
+
+             if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
+               {
+                 /* Relative composition with or without
+                    alternate chars.  */
+                 left = (leftmost + rightmost - width) / 2;
+                 btm = - descent + boff;
+                 if (font_info && font_info->relative_compose
+                     && (! CHAR_TABLE_P (Vignore_relative_composition)
+                         || NILP (Faref (Vignore_relative_composition,
+                                         make_number (ch)))))
+                   {
+
+                     if (- descent >= font_info->relative_compose)
+                       /* One extra pixel between two glyphs.  */
+                       btm = highest + 1;
+                     else if (ascent <= 0)
+                       /* One extra pixel between two glyphs.  */
+                       btm = lowest - 1 - ascent - descent;
+                   }
+               }
+             else
+               {
+                 /* A composition rule is specified by an integer
+                    value that encodes global and new reference
+                    points (GREF and NREF).  GREF and NREF are
+                    specified by numbers as below:
+
+                       0---1---2 -- ascent
+                       |       |
+                       |       |
+                       |       |
+                       9--10--11 -- center
+                       |       |
+                    ---3---4---5--- baseline
+                       |       |
+                       6---7---8 -- descent
+                 */
+                 int rule = COMPOSITION_RULE (cmp, i);
+                 int gref, nref, grefx, grefy, nrefx, nrefy;
+
+                 COMPOSITION_DECODE_RULE (rule, gref, nref);
+                 grefx = gref % 3, nrefx = nref % 3;
+                 grefy = gref / 3, nrefy = nref / 3;
+
+                 left = (leftmost
+                         + grefx * (rightmost - leftmost) / 2
+                         - nrefx * width / 2);
+                 btm = ((grefy == 0 ? highest
+                         : grefy == 1 ? 0
+                         : grefy == 2 ? lowest
+                         : (highest + lowest) / 2)
+                        - (nrefy == 0 ? ascent + descent
+                           : nrefy == 1 ? descent - boff
+                           : nrefy == 2 ? 0
+                           : (ascent + descent) / 2));
+               }
+
+             cmp->offsets[i * 2] = left;
+             cmp->offsets[i * 2 + 1] = btm + descent;
+
+             /* Update the bounding box of the overall glyphs. */
+             right = left + width;
+             top = btm + descent + ascent;
+             if (left < leftmost)
+               leftmost = left;
+             if (right > rightmost)
+               rightmost = right;
+             if (top > highest)
+               highest = top;
+             if (btm < lowest)
+               lowest = btm;
+           }
+
+         /* If there are glyphs whose x-offsets are negative,
+            shift all glyphs to the right and make all x-offsets
+            non-negative.  */
+         if (leftmost < 0)
+           {
+             for (i = 0; i < cmp->glyph_len; i++)
+               cmp->offsets[i * 2] -= leftmost;
+             rightmost -= leftmost;
+           }
+
+         cmp->pixel_width = rightmost;
+         cmp->ascent = highest;
+         cmp->descent = - lowest;
+         if (cmp->ascent < font_ascent)
+           cmp->ascent = font_ascent;
+         if (cmp->descent < font_descent)
+           cmp->descent = font_descent;
+       }
+
+      it->pixel_width = cmp->pixel_width;
+      it->ascent = it->phys_ascent = cmp->ascent;
+      it->descent = it->phys_descent = cmp->descent;
+
+      if (face->box != FACE_NO_BOX)
+       {
+         int thick = face->box_line_width;
+
+         if (thick > 0)
+           {
+             it->ascent += thick;
+             it->descent += thick;
+           }
+         else
+           thick = - thick;
+
+         if (it->start_of_box_run_p)
+           it->pixel_width += thick;
+         if (it->end_of_box_run_p)
+           it->pixel_width += thick;
+       }
+
+      /* If face has an overline, add the height of the overline
+        (1 pixel) and a 1 pixel margin to the character height.  */
+      if (face->overline_p)
+       it->ascent += 2;
+
+      take_vertical_position_into_account (it);
+
+      if (it->glyph_row)
+       x_append_composite_glyph (it);
+    }
+  else if (it->what == IT_IMAGE)
+    x_produce_image_glyph (it);
+  else if (it->what == IT_STRETCH)
+    x_produce_stretch_glyph (it);
+
+  /* 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;
+
+  it->descent += it->extra_line_spacing;
 
   it->max_ascent = max (it->max_ascent, it->ascent);
   it->max_descent = max (it->max_descent, it->descent);
@@ -2211,7 +2599,7 @@ x_estimate_mode_line_height (f, face_id)
      struct frame *f;
      enum face_id face_id;
 {
-  int height = 1;
+  int height = FONT_HEIGHT (FRAME_FONT (f));
 
   /* This function is called so early when Emacs starts that the face
      cache and mode line face are not yet initialized.  */
@@ -2219,21 +2607,15 @@ x_estimate_mode_line_height (f, face_id)
       {
        struct face *face = FACE_FROM_ID (f, face_id);
        if (face)
-         height = FONT_HEIGHT (face->font) + 2 * face->box_line_width;
+          {
+            if (face->font)
+              height = FONT_HEIGHT (face->font);
+           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_DEFAULT && IsValidCodePage (codepage));
+  return height;
 }
 
 \f
@@ -2361,7 +2743,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;
@@ -2370,15 +2753,16 @@ void W32_TEXTOUT (s, x, y,chars,nchars)
   int charset_dim = w32_font_is_double_byte (s->gc->font) ? 2 : 1;
   if (s->gc->font->bdf)
     w32_BDF_TextOut (s->gc->font->bdf, s->hdc,
-                     x, y, (char *) chars, charset_dim, nchars, 0);
+                     x, y, (char *) chars, charset_dim,
+                     nchars * charset_dim, 0);
   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)
@@ -2417,16 +2801,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 *,
@@ -2460,8 +2844,15 @@ 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
    with head *HEAD and tail *TAIL.  Set *HEAD and *TAIL to the result.  */
 
@@ -2570,18 +2961,24 @@ x_set_cursor_gc (s)
 
 
 /* Set up S->gc of glyph string S for drawing text in mouse face.  */
-   
+
 static void
 x_set_mouse_face_gc (s)
      struct glyph_string *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);
 
@@ -2594,20 +2991,20 @@ x_set_mouse_face_gc (s)
         but font FONT.  */
       XGCValues xgcv;
       unsigned long mask;
-      
+
       xgcv.background = s->face->background;
       xgcv.foreground = s->face->foreground;
       IF_DEBUG (x_check_font (s->f, s->font));
       xgcv.font = s->font;
       mask = GCForeground | GCBackground | GCFont;
-      
+
       if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
        XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
                   mask, &xgcv);
       else
        FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
          = XCreateGC (NULL, s->window, mask, &xgcv);
-      
+
       s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
     }
 
@@ -2622,7 +3019,7 @@ x_set_mouse_face_gc (s)
 static INLINE void
 x_set_mode_line_face_gc (s)
      struct glyph_string *s;
-{     
+{
   s->gc = s->face->gc;
 }
 
@@ -2636,7 +3033,7 @@ x_set_glyph_string_gc (s)
      struct glyph_string *s;
 {
   PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
-  
+
   if (s->hl == DRAW_NORMAL_TEXT)
     {
       s->gc = s->face->gc;
@@ -2687,7 +3084,7 @@ w32_get_glyph_string_clip_rect (s, r)
     {
       /* Draw full-width.  X coordinates are relative to S->w->left.  */
       int canon_x = CANON_X_UNIT (s->f);
-      
+
       r->left = WINDOW_LEFT_MARGIN (s->w) * canon_x;
       r_width = XFASTINT (s->w->width) * canon_x;
 
@@ -2697,7 +3094,7 @@ w32_get_glyph_string_clip_rect (s, r)
          if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
            r->left -= width;
        }
-      
+
       r->left += FRAME_INTERNAL_BORDER_WIDTH (s->f);
 
       /* Unless displaying a mode or menu bar line, which are always
@@ -2715,20 +3112,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.  */
@@ -2737,9 +3120,37 @@ 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);
 
+  /* If drawing the cursor, don't let glyph draw outside its
+     advertised boundaries. Cleartype does this under some circumstances.  */
+  if (s->hl == DRAW_CURSOR)
+    {
+      if (s->x > r->left)
+       {
+         r_width -= s->x - r->left;
+         r->left = s->x;
+       }
+      r_width = min (r_width, s->first_glyph->pixel_width);
+    }
+
   r->bottom = r->top + r_height;
   r->right = r->left + r_width;
 }
@@ -2765,7 +3176,7 @@ static INLINE void
 x_compute_glyph_string_overhangs (s)
      struct glyph_string *s;
 {
-  /* NTEMACS_TODO: Windows does not appear to have a method for
+  /* TODO: Windows does not appear to have a method for
      getting this info without getting the ABC widths for each
      individual character and working it out manually. */
 }
@@ -2774,7 +3185,7 @@ x_compute_glyph_string_overhangs (s)
 /* Compute overhangs and x-positions for glyph string S and its
    predecessors, or successors.  X is the starting x-position for S.
    BACKWARD_P non-zero means process predecessors.  */
-   
+
 static void
 x_compute_overhangs_and_x (s, x, backward_p)
      struct glyph_string *s;
@@ -2815,10 +3226,8 @@ 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)
     {
       XFontStruct *font;
@@ -2864,7 +3273,7 @@ x_left_overwritten (s)
      struct glyph_string *s;
 {
   int k;
-    
+
   if (s->left_overhang)
     {
       int x = 0, i;
@@ -2926,7 +3335,7 @@ x_right_overwritten (s)
       struct glyph *glyphs = s->row->glyphs[s->area];
       int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
       int end = s->row->used[s->area];
-      
+
       for (i = first; i < end && s->right_overhang > x; ++i)
        x += glyphs[i].pixel_width;
 
@@ -3008,29 +3417,31 @@ x_draw_glyph_string_background (s, force_p)
      shouldn't be drawn in the first place.  */
   if (!s->background_filled_p)
     {
-#if 0 /* NTEMACS_TODO: stipple */
+      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;
        }
     }
@@ -3044,12 +3455,13 @@ x_draw_glyph_string_foreground (s)
      struct glyph_string *s;
 {
   int i, x;
+  HFONT old_font;
 
   /* If first glyph of S has a left box line, start drawing the text
      of S to the right of that box line.  */
   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;
 
@@ -3063,7 +3475,7 @@ x_draw_glyph_string_foreground (s)
   SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
 
   if (s->font && s->font->hfont)
-    SelectObject (s->hdc, s->font->hfont);
+    old_font = SelectObject (s->hdc, s->font->hfont);
 
   /* Draw characters of S as rectangles if S's font could not be
      loaded. */
@@ -3092,8 +3504,10 @@ 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);
 }
 
 /* Draw the foreground of composite glyph string S.  */
@@ -3103,12 +3517,13 @@ x_draw_composite_glyph_string_foreground (s)
      struct glyph_string *s;
 {
   int i, x;
+  HFONT old_font;
 
   /* If first glyph of S has a left box line, start drawing the text
      of S to the right of that box line.  */
   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;
 
@@ -3122,6 +3537,9 @@ x_draw_composite_glyph_string_foreground (s)
   SetBkMode (s->hdc, TRANSPARENT);
   SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
 
+  if (s->font && s->font->hfont)
+    old_font = SelectObject (s->hdc, s->font->hfont);
+
   /* Draw a rectangle for the composition if the font for the very
      first character of the composition could not be loaded.  */
   if (s->font_not_found_p)
@@ -3133,12 +3551,29 @@ 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],
-                     s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
-                     s->char2b + i, 1);
+          w32_text_out (s, x + s->cmp->offsets[s->gidx * 2],
+                       s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
+                       s->char2b + i, 1);
     }
+  if (s->font && s->font->hfont)
+    SelectObject (s->hdc, old_font);
 }
 
+
+/* Brightness beyond which a color won't have its highlight brightness
+   boosted.
+
+   Nominally, highlight colors for `3d' faces are calculated by
+   brightening an object's color by a constant scale factor, but this
+   doesn't yield good results for dark colors, so for colors who's
+   brightness is less than this value (on a scale of 0-255) have to
+   use an additional additive factor.
+
+   The value here is set so that the default menu-bar/mode-line color
+   (grey75) will not have its highlights changed at all.  */
+#define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
+
+
 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
    or DELTA.  Try a color with RGB values multiplied by FACTOR first.
    If this produces the same color as COLOR, try a color where all RGB
@@ -3154,19 +3589,49 @@ w32_alloc_lighter_color (f, color, factor, delta)
      int delta;
 {
   COLORREF new;
+  long bright;
+
+  /* On Windows, RGB values are 0-255, not 0-65535, so scale delta. */
+  delta /= 256;
 
   /* Change RGB values by specified FACTOR.  Avoid overflow!  */
   xassert (factor >= 0);
   new = PALETTERGB (min (0xff, factor * GetRValue (*color)),
                     min (0xff, factor * GetGValue (*color)),
                     min (0xff, factor * GetBValue (*color)));
+
+  /* Calculate brightness of COLOR.  */
+  bright = (2 * GetRValue (*color) + 3 * GetGValue (*color)
+            + GetBValue (*color)) / 6;
+
+  /* We only boost colors that are darker than
+     HIGHLIGHT_COLOR_DARK_BOOST_LIMIT.  */
+  if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
+    /* Make an additive adjustment to NEW, because it's dark enough so
+       that scaling by FACTOR alone isn't enough.  */
+    {
+      /* How far below the limit this color is (0 - 1, 1 being darker).  */
+      double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
+      /* The additive adjustment.  */
+      int min_delta = delta * dimness * factor / 2;
+
+      if (factor < 1)
+        new = PALETTERGB (max (0, min (0xff, min_delta - GetRValue (*color))),
+                          max (0, min (0xff, min_delta - GetGValue (*color))),
+                          max (0, min (0xff, min_delta - GetBValue (*color))));
+      else
+        new = PALETTERGB (max (0, min (0xff, min_delta + GetRValue (*color))),
+                          max (0, min (0xff, min_delta + GetGValue (*color))),
+                          max (0, min (0xff, min_delta + GetBValue (*color))));
+    }
+
   if (new == *color)
     new = PALETTERGB (max (0, min (0xff, delta + GetRValue (*color))),
                       max (0, min (0xff, delta + GetGValue (*color))),
                       max (0, min (0xff, delta + GetBValue (*color))));
 
-  /* NTEMACS_TODO: Map to palette and retry with delta if same? */
-  /* NTEMACS_TODO: Free colors (if using palette)? */
+  /* TODO: Map to palette and retry with delta if same? */
+  /* TODO: Free colors (if using palette)? */
 
   if (new == *color)
     return 0;
@@ -3183,7 +3648,7 @@ w32_alloc_lighter_color (f, color, factor, delta)
    DELTA lighter or darker than the relief's background which is found
    in S->f->output_data.x->relief_background.  If such a color cannot
    be allocated, use DEFAULT_PIXEL, instead.  */
-   
+
 static void
 w32_setup_relief_color (f, relief, factor, delta, default_pixel)
      struct frame *f;
@@ -3199,7 +3664,7 @@ w32_setup_relief_color (f, relief, factor, delta, default_pixel)
   COLORREF background = di->relief_background;
   struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
 
-  /* NTEMACS_TODO: Free colors (if using palette)? */
+  /* TODO: Free colors (if using palette)? */
 
   /* Allocate new color.  */
   xgcv.foreground = default_pixel;
@@ -3209,10 +3674,10 @@ w32_setup_relief_color (f, relief, factor, delta, default_pixel)
       relief->allocated_p = 1;
       xgcv.foreground = relief->pixel = pixel;
     }
-  
+
   if (relief->gc == 0)
     {
-#if 0 /* NTEMACS_TODO: stipple */
+#if 0 /* TODO: stipple */
       xgcv.stipple = dpyinfo->gray;
       mask |= GCStipple;
 #endif
@@ -3234,6 +3699,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;
 
@@ -3269,57 +3738,45 @@ w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
   HDC hdc = get_frame_dc (f);
 
   if (raised_p)
-    gc.foreground = PALETTERGB (255, 255, 255);
+    gc.foreground = f->output_data.w32->white_relief.gc->foreground;
   else
-    gc.foreground = PALETTERGB (0, 0, 0);
+    gc.foreground = f->output_data.w32->black_relief.gc->foreground;
 
   w32_set_clip_rectangle (hdc, clip_rect);
 
   /* Top.  */
   for (i = 0; i < width; ++i)
-    {
-      w32_fill_area (f, hdc, gc.foreground,
-                     left_x + i * left_p, top_y + i,
-                     (right_x + 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 - left_x - i * (left_p + right_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 - top_y - 2 * i + 1);
 
   if (raised_p)
-    gc.foreground = PALETTERGB (0, 0, 0);
+    gc.foreground = f->output_data.w32->black_relief.gc->foreground;
   else
-    gc.foreground = PALETTERGB (255, 255, 255);
+    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 - left_x - i * (left_p + right_p) + 1, 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 - top_y - 2 * i - 1);
 
   w32_set_clip_rectangle (hdc, NULL);
-  
+
   release_frame_dc (f, hdc);
 }
 
@@ -3339,7 +3796,7 @@ w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
      RECT *clip_rect;
 {
   w32_set_clip_rectangle (s->hdc, clip_rect);
-  
+
   /* Top.  */
   w32_fill_area (s->f, s->hdc, s->face->box_color,
                  left_x, top_y, right_x - left_x + 1, width);
@@ -3350,11 +3807,11 @@ w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
       w32_fill_area (s->f, s->hdc, s->face->box_color,
                      left_x, top_y, width, bottom_y - top_y + 1);
     }
-  
+
   /* Bottom.  */
   w32_fill_area (s->f, s->hdc, s->face->box_color,
                  left_x, bottom_y - width + 1, right_x - left_x + 1, width);
-  
+
   /* Right.  */
   if (right_p)
     {
@@ -3381,20 +3838,20 @@ 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);
     }
-  
+
   /* The glyph that may have a right box line.  */
   last_glyph = (s->cmp || s->img
                ? 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;
@@ -3408,7 +3865,7 @@ x_draw_glyph_string_box (s)
             || (s->hl == DRAW_MOUSE_FACE
                 && (s->next == NULL
                     || s->next->hl != s->hl)));
-  
+
   w32_get_glyph_string_clip_rect (s, &clip_rect);
 
   if (s->face->box == FACE_SIMPLE_BOX)
@@ -3436,72 +3893,52 @@ 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);
 
   if (s->img->pixmap)
     {
-#if 0 /* NTEMACS_TODO: image mask */
+      HDC compat_hdc = CreateCompatibleDC (s->hdc);
+      HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
+      HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
+      HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
+      SetBkColor (compat_hdc, RGB (255, 255, 255));
+      SetTextColor (s->hdc, RGB (0, 0, 0));
+      x_set_glyph_string_clipping (s);
+
       if (s->img->mask)
        {
-         /* We can't set both a clip mask and use XSetClipRectangles
-            because the latter also sets a clip mask.  We also can't
-            trust on the shape extension to be available
-            (XShapeCombineRegion).  So, compute the rectangle to draw
-            manually.  */
-         unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
-                               | GCFunction);
-         XGCValues xgcv;
-         XRectangle clip_rect, image_rect, r;
-
-         xgcv.clip_mask = s->img->mask;
-         xgcv.clip_x_origin = x;
-         xgcv.clip_y_origin = y;
-         xgcv.function = GXcopy;
-         XChangeGC (s->display, s->gc, mask, &xgcv);
-         
-         w32_get_glyph_string_clip_rect (s, &clip_rect);
-         image_rect.x = x;
-         image_rect.y = y;
-         image_rect.width = s->img->width;
-         image_rect.height = s->img->height;
-         if (IntersectRect (&r, &clip_rect, &image_rect))
-           XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
-                      r.x - x, r.y - y, r.width, r.height, r.x, r.y);
+         HDC mask_dc = CreateCompatibleDC (s->hdc);
+         HGDIOBJ mask_orig_obj = SelectObject (mask_dc, s->img->mask);
+
+         SetTextColor (s->hdc, RGB (255, 255, 255));
+         SetBkColor (s->hdc, RGB (0, 0, 0));
+
+         BitBlt (s->hdc, x, y, s->img->width, s->img->height,
+                 compat_hdc, 0, 0, SRCINVERT);
+         BitBlt (s->hdc, x, y, s->img->width, s->img->height,
+                 mask_dc, 0, 0, SRCAND);
+         BitBlt (s->hdc, x, y, s->img->width, s->img->height,
+                 compat_hdc, 0, 0, SRCINVERT);
+
+         SelectObject (mask_dc, mask_orig_obj);
+         DeleteDC (mask_dc);
        }
       else
-#endif
        {
-          HDC compat_hdc = CreateCompatibleDC (s->hdc);
-          HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
-          HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
-          HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
-          x_set_glyph_string_clipping (s);
-
-          SetTextColor (s->hdc, s->gc->foreground);
-          SetBkColor (s->hdc, s->gc->background);
-#if 0 /* From w32bdf.c (which is from Meadow).  */
+         SetTextColor (s->hdc, s->gc->foreground);
+         SetBkColor (s->hdc, s->gc->background);
+
           BitBlt (s->hdc, x, y, s->img->width, s->img->height,
                   compat_hdc, 0, 0, SRCCOPY);
-#else
-          BitBlt (s->hdc, x, y, s->img->width, s->img->height,
-                  compat_hdc, 0, 0, 0xB8074A);
-#endif
-          SelectObject (s->hdc, orig_brush);
-          DeleteObject (fg_brush);
-         SelectObject (compat_hdc, orig_obj);
-          DeleteDC (compat_hdc);
 
          /* When the image has a mask, we can expect that at
             least part of a mouse highlight or a block cursor will
@@ -3510,10 +3947,19 @@ x_draw_image_foreground (s)
             the image.  I believe it's looking better if we do
             nothing here for mouse-face.  */
          if (s->hl == DRAW_CURSOR)
-            w32_draw_rectangle (s->hdc, s->gc, x, y, s->img->width - 1,
-                                s->img->height - 1);
-          w32_set_clip_rectangle (s->hdc, NULL);
+           {
+             int r = s->img->relief;
+             if (r < 0) r = -r;
+             w32_draw_rectangle (s->hdc, s->gc, x - r, y - r ,
+                                 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
+           }
        }
+
+      w32_set_clip_rectangle (s->hdc, NULL);
+      SelectObject (s->hdc, orig_brush);
+      DeleteObject (fg_brush);
+      SelectObject (compat_hdc, orig_obj);
+      DeleteDC (compat_hdc);
     }
   else
     w32_draw_rectangle (s->hdc, s->gc, x, y, s->img->width -1,
@@ -3534,27 +3980,24 @@ x_draw_image_relief (s)
   RECT r;
   int x;
   int y = s->ybase - image_ascent (s->img, s->face);
+
   /* If first glyph of S has a left box line, start drawing it to the
      right of that line.  */
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
-    x = s->x + 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
@@ -3562,12 +4005,12 @@ x_draw_image_relief (s)
       thick = abs (s->img->relief);
       raised_p = s->img->relief > 0;
     }
-  
+
   x0 = x - thick;
   y0 = y - thick;
   x1 = x + s->img->width + thick - 1;
   y1 = y + s->img->height + thick - 1;
-  
+
   x_setup_relief_colors (s);
   w32_get_glyph_string_clip_rect (s, &r);
   w32_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
@@ -3590,63 +4033,46 @@ 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)
     {
-#if 0 /* NTEMACS_TODO: image mask */
+      HDC compat_hdc = CreateCompatibleDC (hdc);
+      HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
+      HBRUSH orig_brush = SelectObject (hdc, fg_brush);
+      HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
+
       if (s->img->mask)
        {
-         /* We can't set both a clip mask and use XSetClipRectangles
-            because the latter also sets a clip mask.  We also can't
-            trust on the shape extension to be available
-            (XShapeCombineRegion).  So, compute the rectangle to draw
-            manually.  */
-         unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
-                               | GCFunction);
-         XGCValues xgcv;
-
-         xgcv.clip_mask = s->img->mask;
-         xgcv.clip_x_origin = x;
-         xgcv.clip_y_origin = y;
-         xgcv.function = GXcopy;
-         XChangeGC (s->display, s->gc, mask, &xgcv);
-
-         XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
-                    0, 0, s->img->width, s->img->height, x, y);
-         XSetClipMask (s->display, s->gc, None);
+         HDC mask_dc = CreateCompatibleDC (hdc);
+         HGDIOBJ mask_orig_obj = SelectObject (mask_dc, s->img->mask);
+
+         SetTextColor (hdc, RGB (0, 0, 0));
+         SetBkColor (hdc, RGB (255, 255, 255));
+         BitBlt (hdc, x, y, s->img->width, s->img->height,
+                 compat_hdc, 0, 0, SRCINVERT);
+         BitBlt (hdc, x, y, s->img->width, s->img->height,
+                 mask_dc, 0, 0, SRCAND);
+         BitBlt (hdc, x, y, s->img->width, s->img->height,
+                 compat_hdc, 0, 0, SRCINVERT);
+
+         SelectObject (mask_dc, mask_orig_obj);
+         DeleteDC (mask_dc);
        }
       else
-#endif
        {
-          HDC compat_hdc = CreateCompatibleDC (hdc);
-          HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
-          HBRUSH orig_brush = SelectObject (hdc, fg_brush);
-          HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
-
-          SetTextColor (hdc, s->gc->foreground);
-          SetBkColor (hdc, s->gc->background);
-#if 0 /* From w32bdf.c (which is from Meadow).  */
+         SetTextColor (hdc, s->gc->foreground);
+         SetBkColor (hdc, s->gc->background);
+
           BitBlt (hdc, x, y, s->img->width, s->img->height,
                   compat_hdc, 0, 0, SRCCOPY);
-#else
-          BitBlt (hdc, x, y, s->img->width, s->img->height,
-                  compat_hdc, 0, 0, 0xB8074A);
-#endif
-          SelectObject (hdc, orig_brush);
-          DeleteObject (fg_brush);
-         SelectObject (compat_hdc, orig_obj);
-          DeleteDC (compat_hdc);
 
          /* When the image has a mask, we can expect that at
             least part of a mouse highlight or a block cursor will
@@ -3655,9 +4081,18 @@ w32_draw_image_foreground_1 (s, pixmap)
             the image.  I believe it's looking better if we do
             nothing here for mouse-face.  */
          if (s->hl == DRAW_CURSOR)
-            w32_draw_rectangle (hdc, s->gc, x, y, s->img->width - 1,
-                                s->img->height - 1);
+           {
+             int r = s->img->relief;
+             if (r < 0) r = -r;
+             w32_draw_rectangle (hdc, s->gc, x - r, y - r ,
+                                 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
+           }
        }
+
+      SelectObject (hdc, orig_brush);
+      DeleteObject (fg_brush);
+      SelectObject (compat_hdc, orig_obj);
+      DeleteDC (compat_hdc);
     }
   else
     w32_draw_rectangle (hdc, s->gc, x, y, s->img->width - 1,
@@ -3676,7 +4111,7 @@ x_draw_glyph_string_bg_rect (s, x, y, w, h)
      struct glyph_string *s;
      int x, y, w, h;
 {
-#if 0 /* NTEMACS_TODO: stipple */
+#if 0 /* TODO: stipple */
   if (s->stippled_p)
     {
       /* Fill background with a stipple pattern.  */
@@ -3690,14 +4125,14 @@ x_draw_glyph_string_bg_rect (s, x, y, w, h)
 }
 
 
-/* Draw image glyph string S.  
+/* Draw image glyph string S.
 
             s->y
    s->x      +-------------------------
             |   s->face->box
             |
             |     +-------------------------
-            |     |  s->img->margin
+            |     |  s->img->vmargin
             |     |
             |     |       +-------------------
             |     |       |  the image
@@ -3709,37 +4144,36 @@ 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
-#if 0 /* NTEMACS_TODO: image mask */
+      || s->img->hmargin
+      || s->img->vmargin
       || 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;
-#if 0 /* NTEMACS_TODO: image mask */
+
+      y = s->y + box_line_vwidth;
+#if 0 /* TODO: figure out if we need to do this on Windows.  */
       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);
 
@@ -3747,7 +4181,7 @@ x_draw_image_glyph_string (s)
          pixmap = XCreatePixmap (s->display, s->window,
                                  s->background_width,
                                  s->height, depth);
-         
+
          /* Don't clip in the following because we're working on the
             pixmap.  */
          XSetClipMask (s->display, s->gc, None);
@@ -3775,7 +4209,7 @@ x_draw_image_glyph_string (s)
       else
 #endif
        x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
-      
+
       s->background_filled_p = 1;
     }
 
@@ -3792,13 +4226,9 @@ x_draw_image_glyph_string (s)
 
         SetTextColor (s->hdc, s->gc->foreground);
         SetBkColor (s->hdc, s->gc->background);
-#if 0 /* From w32bdf.c (which is from Meadow).  */
         BitBlt (s->hdc, s->x, s->y, s->background_width, s->height,
                 compat_hdc, 0, 0, SRCCOPY);
-#else
-        BitBlt (s->hdc, s->x, s->y, s->background_width, s->height,
-                compat_hdc, 0, 0, 0xB8074A);
-#endif
+
         SelectObject (s->hdc, orig_brush);
         DeleteObject (fg_brush);
         SelectObject (compat_hdc, orig_obj);
@@ -3845,10 +4275,20 @@ 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);
 
-#if 0 /* NTEMACS_TODO: stipple */
+#if 0 /* TODO: stipple */
          if (s->face->stipple)
            {
              /* Fill background with a stipple pattern.  */
@@ -3863,10 +4303,10 @@ 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);
-  
+
   s->background_filled_p = 1;
 }
 
@@ -3877,6 +4317,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.  */
@@ -3890,7 +4332,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)
     {
@@ -3931,6 +4389,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,
@@ -3980,7 +4440,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);
     }
 
@@ -3993,11 +4453,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.  */
 
@@ -4041,7 +4502,7 @@ x_fill_composite_glyph_string (s, faces, overlaps_p)
 
   /* Adjust base line for subscript/superscript text.  */
   s->ybase += s->first_glyph->voffset;
-  
+
   xassert (s->face && s->face->gc);
 
   /* This glyph string must always be drawn with 16-bit functions.  */
@@ -4051,11 +4512,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.  */
 
@@ -4101,7 +4563,7 @@ x_fill_glyph_string (s, face_id, start, end, overlaps_p)
 
   s->font = s->face->font;
   s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
-  
+
   /* If the specified font could not be loaded, use the frame's font,
      but record the fact that we couldn't load it in
      S->font_not_found_p so that we can draw rectangles for the
@@ -4114,7 +4576,7 @@ x_fill_glyph_string (s, face_id, start, end, overlaps_p)
 
   /* Adjust base line for subscript/superscript text.  */
   s->ybase += voffset;
-  
+
   xassert (s->face && s->face->gc);
   return glyph - s->row->glyphs[s->area];
 }
@@ -4132,7 +4594,7 @@ x_fill_image_glyph_string (s)
   s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
   s->font = s->face->font;
   s->width = s->first_glyph->pixel_width;
-  
+
   /* Adjust base line for subscript/superscript text.  */
   s->ybase += s->first_glyph->voffset;
 }
@@ -4155,9 +4617,9 @@ x_fill_stretch_glyph_string (s, row, area, start, end)
 {
   struct glyph *glyph, *last;
   int voffset, face_id;
-  
+
   xassert (s->first_glyph->type == STRETCH_GLYPH);
-  
+
   glyph = s->row->glyphs[s->area] + start;
   last = s->row->glyphs[s->area] + end;
   face_id = glyph->face_id;
@@ -4174,11 +4636,11 @@ x_fill_stretch_glyph_string (s, row, area, start, end)
        && glyph->face_id == face_id);
        ++glyph)
     s->width += glyph->pixel_width;
-  
+
   /* 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];
 }
 
@@ -4190,7 +4652,7 @@ x_fill_stretch_glyph_string (s, row, area, start, end)
    and area within the row from which S is constructed.  START is the
    index of the first glyph structure covered by S.  HL is a
    face-override for drawing S.  */
-   
+
 static void
 w32_init_glyph_string (s, hdc, char2b, w, row, area, start, hl)
      struct glyph_string *s;
@@ -4218,7 +4680,7 @@ w32_init_glyph_string (s, hdc, char2b, w, row, area, start, hl)
   /* Display the internal border below the tool-bar window.  */
   if (s->w == XWINDOW (s->f->tool_bar_window))
     s->y -= s->f->output_data.w32->internal_border_width;
-  
+
   s->ybase = s->y + row->ascent;
 }
 
@@ -4236,14 +4698,19 @@ x_set_glyph_string_background_width (s, start, last_x)
   /* If the face of this glyph string has to be drawn to the end of
      the drawing area, set S->extends_to_end_of_line_p.  */
   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
      background_width to the distance to the right edge of the drawing
      area.  */
@@ -4322,7 +4789,7 @@ x_set_glyph_string_background_width (s, start, last_x)
                                           OVERLAPS_P);                    \
        }                                                                  \
      while (0)
-     
+
 
 /* Add a glyph string for a composite sequence to the list of strings
    between HEAD and TAIL.  START is the index of the first glyph in
@@ -4443,27 +4910,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;
@@ -4478,19 +4937,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;
@@ -4543,7 +4996,7 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
       /* Prepend glyph strings for glyphs in front of the first glyph
         string that are overwritten because of the first glyph
         string's left overhang.  The background of all strings
-        prepended must be drawn because the first glyph string 
+        prepended must be drawn because the first glyph string
         draws over it.  */
       i = x_left_overwritten (head);
       if (i >= 0)
@@ -4553,8 +5006,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);
        }
@@ -4574,8 +5025,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);
        }
@@ -4592,8 +5041,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
@@ -4611,8 +5058,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;
        }
     }
 
@@ -4620,6 +5065,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);
@@ -4646,9 +5115,9 @@ x_fix_overlapping_area (w, row, area)
      enum glyph_row_area area;
 {
   int i, x;
-  
+
   BLOCK_INPUT;
-  
+
   if (area == LEFT_MARGIN_AREA)
     x = 0;
   else if (area == TEXT_AREA)
@@ -4672,9 +5141,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
        {
@@ -4682,7 +5149,7 @@ x_fix_overlapping_area (w, row, area)
          ++i;
        }
     }
-  
+
   UNBLOCK_INPUT;
 }
 
@@ -4698,27 +5165,21 @@ 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;
-  
+
   /* Write glyphs.  */
 
   hpos = start - updated_row->glyphs[updated_area];
   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;
-  
+
   /* Advance the output cursor.  */
   output_cursor.hpos += len;
   output_cursor.x = x;
@@ -4737,7 +5198,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);
@@ -4761,7 +5222,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,
@@ -4770,9 +5231,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;
@@ -4789,6 +5249,16 @@ static void
 x_delete_glyphs (n)
      register int n;
 {
+  struct frame *f;
+
+  if (updating_frame)
+    f = updating_frame;
+  else
+    f = SELECTED_FRAME ();
+
+  if (! FRAME_W32_P (f))
+    return;
+
   abort ();
 }
 
@@ -4808,10 +5278,10 @@ x_clear_end_of_line (to_x)
   struct window *w = updated_window;
   int max_x, min_y, max_y;
   int from_x, from_y, to_y;
-  
+
   xassert (updated_window && updated_row);
   f = XFRAME (w->frame);
-  
+
   if (updated_row->full_width_p)
     {
       max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
@@ -4833,13 +5303,16 @@ x_clear_end_of_line (to_x)
     to_x = min (to_x, max_x);
 
   to_y = min (max_y, output_cursor.y + updated_row->height);
-  
+
   /* 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)
     {
@@ -4851,11 +5324,11 @@ x_clear_end_of_line (to_x)
       from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
       to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
     }
-  
+
   min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
   from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
   to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
-  
+
   /* Prevent inadvertently clearing to end of the X window.  */
   if (to_x > from_x && to_y > from_y)
     {
@@ -4883,6 +5356,9 @@ x_clear_frame ()
   else
     f = SELECTED_FRAME ();
 
+  if (! FRAME_W32_P (f))
+    return;
+
   /* Clearing the frame will erase any cursor, so mark them all as no
      longer visible.  */
   mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
@@ -4908,14 +5384,18 @@ x_clear_frame ()
 static void
 w32_ring_bell (void)
 {
+  struct frame *f;
+
+  f = SELECTED_FRAME ();
+
   BLOCK_INPUT;
 
-  if (visible_bell)
+  if (FRAME_W32_P (f) && visible_bell)
     {
       int i;
       HWND hwnd = FRAME_W32_WINDOW (SELECTED_FRAME ());
 
-      for (i = 0; i < 5; i++) 
+      for (i = 0; i < 5; i++)
        {
          FlashWindow (hwnd, TRUE);
          Sleep (10);
@@ -4954,6 +5434,16 @@ static void
 x_ins_del_lines (vpos, n)
      int vpos, n;
 {
+  struct frame *f;
+
+  if (updating_frame)
+    f = updating_frame;
+  else
+    f = SELECTED_FRAME ();
+
+  if (! FRAME_W32_P (f))
+    return;
+
   abort ();
 }
 
@@ -4967,14 +5457,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);
@@ -4988,6 +5479,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
     {
@@ -4997,18 +5489,41 @@ 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;
-  
+
   /* Cursor off.  Will be switched on again in x_update_window_end.  */
   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);
 }
 
 
@@ -5016,7 +5531,7 @@ x_scroll_run (w, run)
 /***********************************************************************
                           Exposure Events
  ***********************************************************************/
-                                                                       
+
 /* Redisplay an exposed area of frame F.  X and Y are the upper-left
    corner of the exposed rectangle.  W and H are width and height of
    the exposed area.  All are pixel values.  W or H zero means redraw
@@ -5028,6 +5543,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 "));
 
@@ -5063,23 +5579,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);
+       }
     }
 }
 
@@ -5087,45 +5615,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;
 }
 
 
@@ -5139,31 +5651,30 @@ expose_area (w, row, r, area)
      RECT *r;
      enum glyph_row_area area;
 {
-  int x;
   struct glyph *first = row->glyphs[area];
   struct glyph *end = row->glyphs[area] + row->used[area];
   struct glyph *last;
-  int first_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));
+  int first_x, start_x, x;
 
   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
+        AREA.  The first glyph of the text area can be partially visible.
+        The first glyphs of other areas cannot.  */
+      if (area == LEFT_MARGIN_AREA)
+       start_x = 0;
+      else if (area == TEXT_AREA)
+       start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
+      else
+       start_x = (window_box_width (w, LEFT_MARGIN_AREA)
+                  + window_box_width (w, TEXT_AREA));
+      x = start_x;
+
       /* Find the first glyph that must be redrawn.  */
       while (first < end
              && x + first->pixel_width < r->left)
@@ -5171,7 +5682,7 @@ expose_area (w, row, r, area)
           x += first->pixel_width;
           ++first;
         }
-  
+
       /* Find the last one.  */
       last = first;
       first_x = x;
@@ -5181,33 +5692,32 @@ expose_area (w, row, r, area)
           x += last->pixel_width;
           ++last;
         }
-      
+
       /* Repaint.  */
       if (last > first)
-        x_draw_glyphs (w, first_x, row, 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;
      RECT *r;
 {
   xassert (row->enabled_p);
-  
+
   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])
@@ -5216,8 +5726,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;
 }
 
 
@@ -5245,82 +5757,156 @@ 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 those parts of glyphs rows during expose event handling that
+   overlap other rows.  Redrawing of an exposed line writes over parts
+   of lines overlapping that exposed line; this function fixes that.
+
+   W is the window being exposed.  FIRST_OVERLAPPING_ROW is the first
+   row in W's current matrix that is exposed and overlaps other rows.
+   LAST_OVERLAPPING_ROW is the last such row.  */
 
 static void
-expose_window (w, r)
+expose_overlaps (w, first_overlapping_row, last_overlapping_row)
      struct window *w;
-     RECT *r;
+     struct glyph_row *first_overlapping_row;
+     struct glyph_row *last_overlapping_row;
 {
   struct glyph_row *row;
-  int y;
-  int yb = window_text_bottom_y (w);
-  int cursor_cleared_p;
+
+  for (row = first_overlapping_row; row <= last_overlapping_row; ++row)
+    if (row->overlapping_p)
+      {
+       xassert (row->enabled_p && !row->mode_line_p);
+
+       if (row->used[LEFT_MARGIN_AREA])
+         x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA);
+
+       if (row->used[TEXT_AREA])
+         x_fix_overlapping_area (w, row, TEXT_AREA);
+
+       if (row->used[RIGHT_MARGIN_AREA])
+         x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA);
+      }
+}
+
+
+/* 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 int
+expose_window (w, fr)
+     struct window *w;
+     RECT *fr;
+{
+  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)
-    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);
+    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;
+      struct glyph_row *first_overlapping_row, *last_overlapping_row;
 
-  /* 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;
+
+      /* Update lines intersecting rectangle R.  */
+      first_overlapping_row = last_overlapping_row = NULL;
+      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 (row->overlapping_p)
+               {
+                 if (first_overlapping_row == NULL)
+                   first_overlapping_row = row;
+                 last_overlapping_row = row;
+               }
+
+             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)
+       {
+         /* Fix the display of overlapping rows.  */
+         if (first_overlapping_row)
+           expose_overlaps (w, first_overlapping_row, last_overlapping_row);
+
+         /* 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
@@ -5390,6 +5976,8 @@ static void
 w32_frame_rehighlight (frame)
      struct frame *frame;
 {
+  if (! FRAME_W32_P (frame))
+    return;
   x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame));
 }
 
@@ -5397,29 +5985,29 @@ static void
 x_frame_rehighlight (dpyinfo)
      struct w32_display_info *dpyinfo;
 {
-  struct frame *old_highlight = dpyinfo->w32_highlight_frame;
+  struct frame *old_highlight = dpyinfo->x_highlight_frame;
 
   if (dpyinfo->w32_focus_frame)
     {
-      dpyinfo->w32_highlight_frame
+      dpyinfo->x_highlight_frame
        = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame)))
           ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame))
           : dpyinfo->w32_focus_frame);
-      if (! FRAME_LIVE_P (dpyinfo->w32_highlight_frame))
+      if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
        {
          FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame) = Qnil;
-         dpyinfo->w32_highlight_frame = dpyinfo->w32_focus_frame;
+         dpyinfo->x_highlight_frame = dpyinfo->w32_focus_frame;
        }
     }
   else
-    dpyinfo->w32_highlight_frame = 0;
+    dpyinfo->x_highlight_frame = 0;
 
-  if (dpyinfo->w32_highlight_frame != old_highlight)
+  if (dpyinfo->x_highlight_frame != old_highlight)
     {
       if (old_highlight)
        frame_unhighlight (old_highlight);
-      if (dpyinfo->w32_highlight_frame)
-       frame_highlight (dpyinfo->w32_highlight_frame);
+      if (dpyinfo->x_highlight_frame)
+       frame_highlight (dpyinfo->x_highlight_frame);
     }
 }
 \f
@@ -5545,15 +6133,19 @@ glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
   return success_p;
 }
 
-BOOL 
-parse_button (message, pbutton, pup)
+/* 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, xbutton, pbutton, pup)
      int message;
+     int xbutton;
      int * pbutton;
      int * pup;
 {
   int button = 0;
   int up = 0;
-  
+
   switch (message)
     {
     case WM_LBUTTONDOWN:
@@ -5592,13 +6184,21 @@ 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);
     }
-  
+
   if (pup) *pup = up;
   if (pbutton) *pbutton = button;
-  
+
   return (TRUE);
 }
 
@@ -5617,11 +6217,12 @@ 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
+  /* Make the event type NO_EVENT; we'll change that when we decide
      otherwise.  */
-  result->kind = mouse_click;
+  result->kind = MOUSE_CLICK_EVENT;
   result->code = button;
   result->timestamp = msg->msg.time;
   result->modifiers = (msg->dwModifiers
@@ -5643,7 +6244,7 @@ construct_mouse_wheel (result, msg, f)
      struct frame *f;
 {
   POINT p;
-  result->kind = mouse_wheel;
+  result->kind = MOUSE_WHEEL_EVENT;
   result->code = (short) HIWORD (msg->msg.wParam);
   result->timestamp = msg->msg.time;
   result->modifiers = msg->dwModifiers;
@@ -5671,7 +6272,7 @@ construct_drag_n_drop (result, msg, f)
   char *name;
   int i, len;
 
-  result->kind = drag_n_drop;
+  result->kind = DRAG_N_DROP_EVENT;
   result->code = 0;
   result->timestamp = msg->msg.time;
   result->modifiers = msg->dwModifiers;
@@ -5698,7 +6299,7 @@ construct_drag_n_drop (result, msg, f)
        continue;
       name = alloca (len + 1);
       DragQueryFile (hdrop, i, name, len + 1);
-      files = Fcons (build_string (name), files);
+      files = Fcons (DECODE_FILE (build_string (name)), files);
     }
 
   DragFinish (hdrop);
@@ -5721,15 +6322,42 @@ 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 0 /* Calling Lisp asynchronously is not safe.  */
+  if (mouse_autoselect_window)
+    {
+      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.  Minibuffer 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;
+    }
+#endif
+
   if (msg->hwnd != FRAME_W32_WINDOW (frame))
     {
       frame->mouse_moved = 1;
@@ -5738,23 +6366,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
@@ -5769,10 +6396,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;
@@ -5830,10 +6458,10 @@ 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;
        }
-      
+
       x0 += glyph->pixel_width;
       ++glyph;
     }
@@ -5870,10 +6498,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
@@ -5896,12 +6524,13 @@ note_mode_line_highlight (w, x, mode_line_p)
       struct glyph *glyph, *end;
       Lisp_Object help, map;
       int x0;
-      
+
       /* Find the glyph under X.  */
       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)
        {
@@ -5911,9 +6540,9 @@ note_mode_line_highlight (w, x, mode_line_p)
 
       if (glyph < end
          && STRINGP (glyph->object)
-         && XSTRING (glyph->object)->intervals
+         && STRING_INTERVALS (glyph->object)
          && glyph->charpos >= 0
-         && glyph->charpos < XSTRING (glyph->object)->size)
+         && glyph->charpos < SCHARS (glyph->object))
        {
          /* If we're on a string with `help-echo' text property,
             arrange for the help to be displayed.  This is done by
@@ -5931,12 +6560,18 @@ note_mode_line_highlight (w, x, mode_line_p)
          /* Change the mouse pointer according to what is under X/Y.  */
          map = Fget_text_property (make_number (glyph->charpos),
                                    Qlocal_map, glyph->object);
-         if (!NILP (Fkeymapp (map)))
+         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;
+           }
        }
     }
-
-#if 0 /* NTEMACS_TODO: mouse cursor */
+#if 0 /* TODO: mouse cursor */
   XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
 #endif
 }
@@ -5956,12 +6591,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;
 
@@ -5989,6 +6625,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);
@@ -6001,32 +6640,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 /* NTEMACS_TODO: mouse cursor */
+#if 0 /* TODO: mouse 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
@@ -6034,197 +6679,336 @@ 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];
+           }
+
+         /* 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,
+                                          !dpyinfo->mouse_face_hidden);
+
+             /* 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,
+                                            !dpyinfo->mouse_face_hidden);
+
+             /* 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 (SCHARS (object) - 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,
+                                              !dpyinfo->mouse_face_hidden);
+
+                 /* Display it as active.  */
+                 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
+                 /* TODO: mouse cursor changes.  */
+               }
+           }
+       }
+
+    check_help_echo:
 
-      /* Check for mouse-face and 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;
+           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;
 
-         /* Check overlays first.  */
-         help = Qnil;
-         for (i = noverlays - 1; i >= 0 && NILP (help); --i)
-            {
-              overlay = overlay_vec[i];
-              help = Foverlay_get (overlay, Qhelp_echo); 
-            }
+           /* Try text properties.  */
+           if (STRINGP (object)
+               && charpos >= 0
+               && charpos < SCHARS (object))
+             {
+               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 = 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);
-           
-              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
@@ -6256,7 +7040,7 @@ static int last_tool_bar_item;
    Return in *GLYPH a pointer to the glyph of the tool-bar item in
    the current matrix of the tool-bar window of F, or NULL if not
    on a tool-bar item.  Return in *PROP_IDX the index of the tool-bar
-   item in F->current_tool_bar_items.  Value is
+   item in F->tool_bar_items.  Value is
 
    -1  if X/Y is not on a tool-bar item
    0   if X/Y is on the same item that was highlighted before.
@@ -6274,12 +7058,12 @@ 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;
 
   /* Get the start of this tool-bar item's properties in
-     f->current_tool_bar_items.  */
+     f->tool_bar_items.  */
   if (!tool_bar_item_info (f, *glyph, prop_idx))
     return -1;
 
@@ -6293,7 +7077,7 @@ x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
          || *hpos < dpyinfo->mouse_face_end_col
          || dpyinfo->mouse_face_past_end))
     return 0;
-  
+
   return 1;
 }
 
@@ -6314,19 +7098,18 @@ w32_handle_tool_bar_click (f, button_event)
   Lisp_Object enabled_p;
   int x = XFASTINT (button_event->x);
   int y = XFASTINT (button_event->y);
-  
+
   /* If not on the highlighted tool-bar item, return.  */
   frame_to_window_pixel_xy (w, &x, &y);
   if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
     return;
 
   /* If item is disabled, do nothing.  */
-  enabled_p = (XVECTOR (f->current_tool_bar_items)
-              ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
+  enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
   if (NILP (enabled_p))
     return;
-  
-  if (button_event->kind == mouse_click)
+
+  if (button_event->modifiers & down_modifier)
     {
       /* Show item in pressed state.  */
       show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
@@ -6342,8 +7125,7 @@ w32_handle_tool_bar_click (f, button_event)
       show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
       dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
 
-      key = (XVECTOR (f->current_tool_bar_items)
-            ->contents[prop_idx + TOOL_BAR_ITEM_KEY]);
+      key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
 
       XSETFRAME (frame, f);
       event.kind = TOOL_BAR_EVENT;
@@ -6354,7 +7136,8 @@ w32_handle_tool_bar_click (f, button_event)
       event.kind = TOOL_BAR_EVENT;
       event.frame_or_window = frame;
       event.arg = key;
-      event.modifiers = button_event->modifiers;
+      /* The keyboard buffer doesn't like the up modifier being set.  */
+      event.modifiers = button_event->modifiers & ~up_modifier;
       kbd_buffer_store_event (&event);
       last_tool_bar_item = -1;
     }
@@ -6402,7 +7185,7 @@ note_tool_bar_highlight (f, x, y)
     goto set_help_echo;
 
   clear_mouse_face (dpyinfo);
-  
+
   /* Mouse is down, but on different tool-bar item?  */
   mouse_down_p = (dpyinfo->grabbed
                  && f == last_mouse_frame
@@ -6413,10 +7196,9 @@ note_tool_bar_highlight (f, x, y)
 
   dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
   draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
-  
+
   /* If tool-bar item is not enabled, don't highlight it.  */
-  enabled_p = (XVECTOR (f->current_tool_bar_items)
-              ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
+  enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
   if (!NILP (enabled_p))
     {
       /* Compute the x-position of the glyph.  In front and past the
@@ -6424,76 +7206,147 @@ note_tool_bar_highlight (f, x, y)
       row = MATRIX_ROW (w->current_matrix, vpos);
       for (i = x = 0; i < hpos; ++i)
        x += row->glyphs[TEXT_AREA][i].pixel_width;
-      
+
       /* Record this as the current active region.  */
       dpyinfo->mouse_face_beg_col = hpos;
       dpyinfo->mouse_face_beg_row = vpos;
       dpyinfo->mouse_face_beg_x = x;
       dpyinfo->mouse_face_beg_y = row->y;
       dpyinfo->mouse_face_past_end = 0;
-      
+
       dpyinfo->mouse_face_end_col = hpos + 1;
       dpyinfo->mouse_face_end_row = vpos;
       dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
       dpyinfo->mouse_face_end_y = row->y;
       dpyinfo->mouse_face_window = window;
       dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
-      
+
       /* Display it as active.  */
       show_mouse_face (dpyinfo, draw);
       dpyinfo->mouse_face_image_state = draw;
     }
-      
+
  set_help_echo:
-  
+
   /* Set help_echo to a help string.to display for this tool-bar item.
      w32_read_socket does the rest.  */
   help_echo_object = help_echo_window = Qnil;
   help_echo_pos = -1;
-  help_echo = (XVECTOR (f->current_tool_bar_items)
-              ->contents[prop_idx + TOOL_BAR_ITEM_HELP]);
+  help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
   if (NILP (help_echo))
-    help_echo = (XVECTOR (f->current_tool_bar_items)
-                ->contents[prop_idx + TOOL_BAR_ITEM_CAPTION]);
+    help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
 }
 
 
 \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, pos, hpos, vpos, x, y)
+fast_find_position (w, charpos, hpos, vpos, x, y, stop)
      struct window *w;
-     int pos;
+     int charpos;
      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;
-  int current_x;
+  struct glyph_row *row, *first;
+  struct glyph *glyph, *end;
+  int i, past_end = 0;
 
-  while (row->y < yb)
+  first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+  row = row_containing_pos (w, charpos, first, NULL, 0);
+  if (row == NULL)
     {
-      if (row->used[TEXT_AREA])
-       line_start_position = row->glyphs[TEXT_AREA]->charpos;
+      if (charpos < MATRIX_ROW_START_CHARPOS (first))
+       {
+         *x = *y = *hpos = *vpos = 0;
+         return 0;
+       }
       else
-       line_start_position = 0;
-
-      if (line_start_position > pos)
-       break;
-      /* If the position sought is the end of the buffer,
-        don't include the blank lines at the bottom of the window.  */
-      else if (line_start_position == pos
-               && pos == BUF_ZV (XBUFFER (w->buffer)))
+       {
+         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, 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, *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])
+       line_start_position = row->glyphs[TEXT_AREA]->charpos;
+      else
+       line_start_position = 0;
+
+      if (line_start_position > pos)
+       break;
+      /* If the position sought is the end of the buffer,
+        don't include the blank lines at the bottom of the window.  */
+      else if (line_start_position == pos
+               && pos == BUF_ZV (XBUFFER (w->buffer)))
        {
          maybe_next_line_p = 1;
          break;
@@ -6517,22 +7370,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;
     }
 
@@ -6554,6 +7411,90 @@ fast_find_position (w, pos, hpos, vpos, x, y)
   return 0;
 }
 
+#endif /* not 0 */
+
+
+/* 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.
+
+   RIGHT_P non-zero means return the position of the right edge of the
+   glyph, RIGHT_P zero means return the left edge position.
+
+   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.
+
+   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;
+
+  for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+       r->enabled_p && r->y < yb;
+       ++r)
+    {
+      struct glyph *g = r->glyphs[TEXT_AREA];
+      struct glyph *e = g + r->used[TEXT_AREA];
+      int gx;
+
+      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;
+             }
+         }
+    }
+
+ found:
+
+  if (best_glyph)
+    {
+      *x = best_x;
+      *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
+
+      if (right_p)
+       {
+         *x += best_glyph->pixel_width;
+         ++*hpos;
+       }
+
+      *y = best_row->y;
+      *vpos = best_row - w->current_matrix->rows;
+    }
+
+  return best_glyph != NULL;
+}
+
 
 /* Display the active region described by mouse_face_*
    in its mouse-face if HL > 0, in its normal face if HL = 0.  */
@@ -6565,82 +7506,62 @@ show_mouse_face (dpyinfo, 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;
-
-  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;
 
-  /* 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;
-
-  set_output_cursor (&w->phys_cursor);
-
-  /* Note that mouse_face_beg_row etc. are window relative.  */
-  for (i = dpyinfo->mouse_face_beg_row;
-       i <= dpyinfo->mouse_face_end_row;
-       i++)
+  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 start_hpos, end_hpos, start_x;
-      struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
+      int phys_cursor_on_p = w->phys_cursor_on_p;
+      struct glyph_row *row, *first, *last;
 
-      /* Don't do anything if row doesn't have valid contents.  */
-      if (!row->enabled_p)
-       continue;
+      first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
+      last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
 
-      /* For all but the first row, the highlight starts at column 0.  */
-      if (i == dpyinfo->mouse_face_beg_row)
+      for (row = first; row <= last && row->enabled_p; ++row)
        {
-         start_hpos = dpyinfo->mouse_face_beg_col;
-         start_x = dpyinfo->mouse_face_beg_x;
-       }
-      else
-       {
-         start_hpos = 0;
-         start_x = 0;
-       }
+         int start_hpos, end_hpos, start_x;
 
-      if (i == dpyinfo->mouse_face_end_row)
-       end_hpos = dpyinfo->mouse_face_end_col;
-      else
-       end_hpos = row->used[TEXT_AREA];
+         /* 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 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)
-       {
-         x_update_window_cursor (w, 0);
-         cursor_off_p = 1;
-       }
+         if (row == last)
+           end_hpos = dpyinfo->mouse_face_end_col;
+         else
+           end_hpos = row->used[TEXT_AREA];
 
-      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);
-        }
-    }
+         if (end_hpos > start_hpos)
+           {
+             x_draw_glyphs (w, start_x, row, TEXT_AREA,
+                            start_hpos, end_hpos, draw, 0);
 
-  /* 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);
+             row->mouse_face_p
+               = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
+           }
+       }
 
-  output_cursor = saved_cursor;
+      /* 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);
+    }
 
- set_x_cursor:
-#if 0 /* NTEMACS_TODO: mouse cursor */
+#if 0 /* TODO: mouse cursor */
   /* Change the mouse cursor.  */
   if (draw == DRAW_NORMAL_TEXT)
     XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
@@ -6652,25 +7573,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 (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;
 }
 
 
@@ -6715,6 +7639,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.
@@ -6762,7 +7787,7 @@ w32_mouse_position (fp, insist, bar_window, part, x, y, time)
        XFRAME (frame)->mouse_moved = 0;
 
       last_mouse_scroll_bar = Qnil;
-      
+
       GetCursorPos (&pt);
 
       /* Now we have a position on the root; find the innermost window
@@ -6778,7 +7803,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));
          }
 
@@ -6818,24 +7843,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;
@@ -6903,7 +7911,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;
 
@@ -6956,18 +7964,18 @@ w32_set_scroll_bar_thumb (bar, portion, position, whole)
 /************************************************************************
                         Scroll bars, general
  ************************************************************************/
-                                                                        
-HWND 
+
+HWND
 my_create_scrollbar (f, bar)
      struct frame * f;
      struct scroll_bar * bar;
 {
   return (HWND) SendMessage (FRAME_W32_WINDOW (f),
-                            WM_EMACS_CREATESCROLLBAR, (WPARAM) f, 
+                            WM_EMACS_CREATESCROLLBAR, (WPARAM) f,
                             (LPARAM) bar);
 }
 
-//#define ATTACH_THREADS
+/*#define ATTACH_THREADS*/
 
 BOOL
 my_show_window (FRAME_PTR f, HWND hwnd, int how)
@@ -7003,7 +8011,7 @@ my_set_focus (f, hwnd)
      struct frame * f;
      HWND hwnd;
 {
-  SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SETFOCUS, 
+  SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SETFOCUS,
               (WPARAM) hwnd, 0);
 }
 
@@ -7019,7 +8027,7 @@ my_destroy_window (f, hwnd)
      struct frame * f;
      HWND hwnd;
 {
-  SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_DESTROYWINDOW, 
+  SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_DESTROYWINDOW,
               (WPARAM) hwnd, 0);
 }
 
@@ -7146,7 +8154,7 @@ w32_set_vertical_scroll_bar (w, portion, whole, position)
 
   /* Compute the left edge of the scroll bar.  */
   if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
-    sb_left = left + width - sb_width - (width - sb_width) / 2; 
+    sb_left = left + width - sb_width - (width - sb_width) / 2;
   else
     sb_left = left + (width - sb_width) / 2;
 
@@ -7155,16 +8163,19 @@ 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);
     }
   else
     {
-      /* It may just need to be moved and resized.  */      
+      /* It may just need to be moved and resized.  */
       HWND hwnd;
 
       bar = XSCROLL_BAR (w->vertical_scroll_bar);
@@ -7184,22 +8195,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;
@@ -7216,7 +8229,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);
@@ -7263,13 +8276,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))
@@ -7278,36 +8294,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
@@ -7340,13 +8353,13 @@ w32_judge_scroll_bars (f)
 }
 
 /* Handle a mouse click on the scroll bar BAR.  If *EMACS_EVENT's kind
-   is set to something other than no_event, it is enqueued.
+   is set to something other than NO_EVENT, it is enqueued.
 
    This may be called from a signal handler, so we have to ignore GC
    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;
@@ -7354,7 +8367,7 @@ x_scroll_bar_handle_click (bar, msg, emacs_event)
   if (! GC_WINDOWP (bar->window))
     abort ();
 
-  emacs_event->kind = w32_scroll_bar_click;
+  emacs_event->kind = W32_SCROLL_BAR_CLICK_EVENT;
   emacs_event->code = 0;
   /* not really meaningful to distinguish up/down */
   emacs_event->modifiers = msg->dwModifiers;
@@ -7384,7 +8397,7 @@ x_scroll_bar_handle_click (bar, msg, emacs_event)
 
 
     last_mouse_scroll_bar_pos = msg->msg.wParam;
+
     switch (LOWORD (msg->msg.wParam))
       {
       case SB_LINEDOWN:
@@ -7454,7 +8467,7 @@ x_scroll_bar_handle_click (bar, msg, emacs_event)
          }
        /* fall through */
       default:
-       emacs_event->kind = no_event;
+       emacs_event->kind = NO_EVENT;
        return FALSE;
       }
 
@@ -7565,29 +8578,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.  */
 
@@ -7604,14 +8597,14 @@ static short temp_buffer[100];
    We return the number of characters stored into the buffer,
    thus pretending to be `read'.
 
-   EXPECTED is nonzero if the caller knows input is available.  
+   EXPECTED is nonzero if the caller knows input is available.
 
    Some of these messages are reposted back to the message queue since the
-   system calls the windows proc directly in a context where we cannot return 
+   system calls the windows proc directly in a context where we cannot return
    the data nor can we guarantee the state we are in.  So if we dispatch  them
    we will get into an infinite loop.  To prevent this from ever happening we
    will set a variable to indicate we are in the read_socket call and indicate
-   which message we are processing since the windows proc gets called 
+   which message we are processing since the windows proc gets called
    recursively with different messages by the system.
 */
 
@@ -7643,65 +8636,65 @@ w32_read_socket (sd, bufp, numchars, expected)
   if (numchars <= 0)
     abort ();                   /* Don't think this happens. */
 
-  /* NTEMACS_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,
+                            SDATA (f->name)));
+               }
+             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,
+                            SDATA (f->name)));
+
+                 /* 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:
@@ -7712,8 +8705,8 @@ w32_read_socket (sd, bufp, numchars, expected)
            {
              if (numchars == 0)
                abort ();
-         
-             bufp->kind = language_change_event;
+
+             bufp->kind = LANGUAGE_CHANGE_EVENT;
              XSETFRAME (bufp->frame_or_window, f);
              bufp->arg = Qnil;
              bufp->code = msg.msg.wParam;
@@ -7727,13 +8720,19 @@ w32_read_socket (sd, bufp, numchars, expected)
        case WM_KEYDOWN:
        case WM_SYSKEYDOWN:
          f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
-         
+
          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;
-             bufp->kind = non_ascii_keystroke;
+             bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
              bufp->code = msg.msg.wParam;
              bufp->modifiers = msg.dwModifiers;
              XSETFRAME (bufp->frame_or_window, f);
@@ -7748,13 +8747,19 @@ w32_read_socket (sd, bufp, numchars, expected)
        case WM_SYSCHAR:
        case WM_CHAR:
          f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
-         
+
          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;
-             bufp->kind = ascii_keystroke;
+             bufp->kind = ASCII_KEYSTROKE_EVENT;
              bufp->code = msg.msg.wParam;
              bufp->modifiers = msg.dwModifiers;
              XSETFRAME (bufp->frame_or_window, f);
@@ -7767,33 +8772,53 @@ w32_read_socket (sd, bufp, numchars, expected)
          break;
 
        case WM_MOUSEMOVE:
+         /* Ignore non-movement.  */
+         {
+           int x = LOWORD (msg.msg.lParam);
+           int y = HIWORD (msg.msg.lParam);
+           if (x == last_mousemove_x && y == last_mousemove_y)
+             break;
+           last_mousemove_x = x;
+           last_mousemove_y = y;
+         }
+
           previous_help_echo = help_echo;
-          help_echo = help_echo_object = help_echo_window = Qnil;
-          help_echo_pos = -1;
 
          if (dpyinfo->grabbed && last_mouse_frame
              && FRAME_LIVE_P (last_mouse_frame))
            f = last_mouse_frame;
          else
            f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
-         
+
+         if (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 ||
+             (!NILP (help_echo) && !STRINGP (help_echo) && f->mouse_moved))
             {
               Lisp_Object frame;
               int n;
 
+             if (help_echo == Qnil)
+               {
+                 help_echo_object = help_echo_window = Qnil;
+                 help_echo_pos = -1;
+               }
+
               if (f)
                 XSETFRAME (frame, f);
               else
@@ -7813,6 +8838,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.  */
@@ -7821,18 +8848,18 @@ w32_read_socket (sd, bufp, numchars, expected)
            int button;
            int up;
 
-            emacs_event.kind = no_event;
-           
+            emacs_event.kind = NO_EVENT;
+
            if (dpyinfo->grabbed && last_mouse_frame
                && FRAME_LIVE_P (last_mouse_frame))
              f = last_mouse_frame;
            else
              f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
-           
+
            if (f)
              {
                 construct_mouse_click (&emacs_event, &msg, f);
-                
+
                 /* Is this in the tool-bar?  */
                 if (WINDOWP (f->tool_bar_window)
                     && XFASTINT (XWINDOW (f->tool_bar_window)->height))
@@ -7840,11 +8867,12 @@ w32_read_socket (sd, bufp, numchars, expected)
                     Lisp_Object window;
                     int p, x, y;
 
+                   x = XFASTINT (emacs_event.x);
+                   y = XFASTINT (emacs_event.y);
+
                     /* Set x and y.  */
-                    window = window_from_coordinates (f,
-                                                      emacs_event.x,
-                                                      emacs_event.y,
-                                                      &p, 1);
+                    window = window_from_coordinates (f, x, y, &p, 1);
+
                     if (EQ (window, f->tool_bar_window))
                       {
                         w32_handle_tool_bar_click (f, &emacs_event);
@@ -7863,9 +8891,10 @@ w32_read_socket (sd, bufp, numchars, expected)
                       numchars--;
                     }
              }
-           
-           parse_button (msg.msg.message, &button, &up);
-           
+
+           parse_button (msg.msg.message, HIWORD (msg.msg.wParam),
+                         &button, &up);
+
            if (up)
              {
                dpyinfo->grabbed &= ~ (1 << button);
@@ -7886,7 +8915,7 @@ w32_read_socket (sd, bufp, numchars, expected)
              }
            break;
          }
-         
+
       case WM_MOUSEWHEEL:
           if (dpyinfo->grabbed && last_mouse_frame
               && FRAME_LIVE_P (last_mouse_frame))
@@ -7896,7 +8925,7 @@ w32_read_socket (sd, bufp, numchars, expected)
 
           if (f)
             {
-              if ((!dpyinfo->w32_focus_frame 
+              if ((!dpyinfo->w32_focus_frame
                    || f == dpyinfo->w32_focus_frame)
                   && (numchars >= 1))
                 {
@@ -7908,16 +8937,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);
 
@@ -7934,10 +8953,10 @@ w32_read_socket (sd, bufp, numchars, expected)
          {
            struct scroll_bar *bar =
              x_window_to_scroll_bar ((HWND)msg.msg.lParam);
-             
+
            if (bar && numchars >= 1)
              {
-               if (x_scroll_bar_handle_click (bar, &msg, bufp))
+               if (w32_scroll_bar_handle_click (bar, &msg, bufp))
                  {
                    bufp++;
                    count++;
@@ -7946,16 +8965,30 @@ w32_read_socket (sd, bufp, numchars, expected)
              }
            break;
          }
-         
+
        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;
 
        case WM_MOVE:
          f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
-         
+
          if (f && !f->async_iconified)
            {
              int x, y;
@@ -7969,6 +9002,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
@@ -7988,7 +9030,7 @@ w32_read_socket (sd, bufp, numchars, expected)
 
        case WM_SIZE:
          f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
-         
+
          /* Inform lisp of whether frame has been iconified etc. */
          if (f)
            {
@@ -7997,8 +9039,8 @@ w32_read_socket (sd, bufp, numchars, expected)
                case SIZE_MINIMIZED:
                  f->async_visible = 0;
                  f->async_iconified = 1;
-                 
-                 bufp->kind = iconify_event;
+
+                 bufp->kind = ICONIFY_EVENT;
                  XSETFRAME (bufp->frame_or_window, f);
                  bufp->arg = Qnil;
                  bufp++;
@@ -8010,11 +9052,11 @@ w32_read_socket (sd, bufp, numchars, expected)
                case SIZE_RESTORED:
                  f->async_visible = 1;
                  f->async_iconified = 0;
-                 
+
                  /* wait_reading_process_input will notice this and update
                     the frame's display structures.  */
                  SET_FRAME_GARBAGED (f);
-                 
+
                  if (f->iconified)
                    {
                       int x, y;
@@ -8028,7 +9070,7 @@ w32_read_socket (sd, bufp, numchars, expected)
                       f->output_data.w32->left_pos = x;
                       f->output_data.w32->top_pos = y;
 
-                     bufp->kind = deiconify_event;
+                     bufp->kind = DEICONIFY_EVENT;
                      XSETFRAME (bufp->frame_or_window, f);
                      bufp->arg = Qnil;
                      bufp++;
@@ -8052,21 +9094,21 @@ w32_read_socket (sd, bufp, numchars, expected)
              int columns;
              int width;
              int height;
-             
+
              GetClientRect (msg.msg.hwnd, &rect);
-             
+
              height = rect.bottom - rect.top;
              width = rect.right - rect.left;
-             
+
              rows = PIXEL_TO_CHAR_HEIGHT (f, height);
              columns = PIXEL_TO_CHAR_WIDTH (f, width);
-             
+
              /* TODO: Clip size to the screen dimensions.  */
-             
+
              /* Even if the number of character rows and columns has
                 not changed, the font size may have changed, so we need
                 to check the pixel dimensions as well.  */
-             
+
              if (columns != f->width
                  || rows != f->height
                  || width != f->output_data.w32->pixel_width
@@ -8084,11 +9126,41 @@ 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);
 
           dpyinfo->w32_focus_event_frame = f;
-          
+
           if (f)
             x_new_focus_frame (dpyinfo, f);
 
@@ -8098,13 +9170,11 @@ w32_read_socket (sd, bufp, numchars, expected)
          break;
 
        case WM_KILLFOCUS:
-          /* NTEMACS_TODO: some of this belongs in MOUSE_LEAVE */
+          /* TODO: some of this belongs in MOUSE_LEAVE */
          f = x_top_window_to_frame (dpyinfo, msg.msg.hwnd);
 
           if (f)
             {
-              Lisp_Object frame;
-
               if (f == dpyinfo->w32_focus_event_frame)
                 dpyinfo->w32_focus_event_frame = 0;
 
@@ -8125,11 +9195,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;
                 }
             }
@@ -8140,13 +9212,13 @@ w32_read_socket (sd, bufp, numchars, expected)
 
        case WM_CLOSE:
          f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
-         
+
          if (f)
            {
              if (numchars == 0)
                abort ();
-             
-             bufp->kind = delete_window_event;
+
+             bufp->kind = DELETE_WINDOW_EVENT;
              XSETFRAME (bufp->frame_or_window, f);
              bufp->arg = Qnil;
              bufp++;
@@ -8157,13 +9229,13 @@ w32_read_socket (sd, bufp, numchars, expected)
 
        case WM_INITMENU:
          f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
-         
+
          if (f)
            {
              if (numchars == 0)
                abort ();
-         
-             bufp->kind = menu_bar_activate_event;
+
+             bufp->kind = MENU_BAR_ACTIVATE_EVENT;
              XSETFRAME (bufp->frame_or_window, f);
              bufp->arg = Qnil;
              bufp++;
@@ -8188,7 +9260,7 @@ w32_read_socket (sd, bufp, numchars, expected)
        case WM_DISPLAYCHANGE:
          f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
 
-         if (f) 
+         if (f)
            {
              dpyinfo->width = (short) LOWORD (msg.msg.lParam);
              dpyinfo->height = (short) HIWORD (msg.msg.lParam);
@@ -8196,7 +9268,7 @@ w32_read_socket (sd, bufp, numchars, expected)
              DebPrint (("display change: %d %d\n", dpyinfo->width,
                         dpyinfo->height));
            }
-         
+
          check_visibility = 1;
          break;
 
@@ -8204,15 +9276,15 @@ w32_read_socket (sd, bufp, numchars, expected)
          /* Check for messages registered at runtime. */
          if (msg.msg.message == msh_mousewheel)
            {
-             if (dpyinfo->grabbed && last_mouse_frame 
+             if (dpyinfo->grabbed && last_mouse_frame
                  && FRAME_LIVE_P (last_mouse_frame))
                f = last_mouse_frame;
              else
                f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
-          
+
              if (f)
                {
-                 if ((!dpyinfo->w32_focus_frame 
+                 if ((!dpyinfo->w32_focus_frame
                       || f == dpyinfo->w32_focus_frame)
                      && (numchars >= 1))
                    {
@@ -8248,15 +9320,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)
@@ -8269,8 +9356,8 @@ w32_read_socket (sd, bufp, numchars, expected)
 
                  if (!FRAME_OBSCURED_P (f))
                    {
-                     DebPrint (("frame %04x (%s) obscured\n", f,
-                                XSTRING (f->name)->data));
+                     DebPrint (("frame %p (%s) obscured\n", f,
+                                SDATA (f->name)));
                    }
                }
              else
@@ -8281,8 +9368,8 @@ w32_read_socket (sd, bufp, numchars, expected)
                  if (FRAME_OBSCURED_P (f))
                    {
                      SET_FRAME_GARBAGED (f);
-                     DebPrint (("frame %04x (%s) reexposed\n", f,
-                                XSTRING (f->name)->data));
+                     DebPrint (("obscured frame %p (%s) found to be visible\n", f,
+                                SDATA (f->name)));
 
                      /* Force a redisplay sooner or later.  */
                      record_asynch_buffer_change ();
@@ -8303,21 +9390,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;
 }
 
@@ -8354,8 +9444,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);
@@ -8370,7 +9460,7 @@ x_draw_hollow_cursor (w, row)
      struct glyph_row *row;
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
-  HDC hdc = get_frame_dc (f);
+  HDC hdc;
   RECT rect;
   int wd;
   struct glyph *cursor_glyph;
@@ -8381,7 +9471,7 @@ x_draw_hollow_cursor (w, row)
   rect.left = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
   rect.top = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
               + row->ascent - w->phys_cursor_ascent);
-  rect.bottom = rect.top + row->height - 1;
+  rect.bottom = rect.top + row->height;
 
   /* Get the glyph the cursor is on.  If we can't tell because
      the current matrix is invalid or such, give up.  */
@@ -8393,13 +9483,13 @@ x_draw_hollow_cursor (w, row)
      glyph, and `x-stretch-block-cursor' is nil, don't draw a
      rectangle as wide as the glyph, but use a canonical character
      width instead.  */
-  wd = cursor_glyph->pixel_width - 1;
+  wd = cursor_glyph->pixel_width;
   if (cursor_glyph->type == STRETCH_GLYPH
       && !x_stretch_cursor_p)
     wd = min (CANON_X_UNIT (f), wd);
 
   rect.right = rect.left + wd;
-
+  hdc = get_frame_dc (f);
   FrameRect (hdc, &rect, hb);
   DeleteObject (hb);
 
@@ -8415,50 +9505,68 @@ x_draw_hollow_cursor (w, row)
    --gerd.  */
 
 static void
-x_draw_bar_cursor (w, row, width)
+x_draw_bar_cursor (w, row, width, kind)
      struct window *w;
      struct glyph_row *row;
      int width;
+     enum text_cursor_kinds kind;
 {
-  /* 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 = FRAME_CURSOR_WIDTH (f);
+      width = min (cursor_glyph->pixel_width, 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);
+
+      if (kind == BAR_CURSOR)
+       {
+         w32_fill_area (f, hdc, cursor_color, x,
+                        WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
+                        width, row->height);
+       }
+      else
+       {
+         w32_fill_area (f, hdc, cursor_color, x,
+                        WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
+                                                 row->height - width),
+                        cursor_glyph->pixel_width, width);
+       }
+      release_frame_dc (f, hdc);
     }
 }
 
@@ -8490,9 +9598,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
@@ -8531,7 +9641,7 @@ x_erase_phys_cursor (w)
      screen.  */
   if (w->phys_cursor_type == NO_CURSOR)
     goto mark_cursor_off;
-          
+
   /* VPOS >= active_glyphs->nrows means that window has been resized.
      Don't bother to erase the cursor.  */
   if (vpos >= active_glyphs->nrows)
@@ -8542,7 +9652,13 @@ x_erase_phys_cursor (w)
   cursor_row = MATRIX_ROW (active_glyphs, vpos);
   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
@@ -8550,10 +9666,11 @@ x_erase_phys_cursor (w)
      cursor glyph at hand.  */
   if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
     goto mark_cursor_off;
-        
+
   /* 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))
@@ -8587,12 +9704,10 @@ x_erase_phys_cursor (w)
                       cursor_row->visible_height);
       release_frame_dc (f, hdc);
     }
-  
+
   /* 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);
@@ -8603,6 +9718,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.  */
@@ -8615,6 +9760,7 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
   struct frame *f = XFRAME (w->frame);
   int new_cursor_type;
   int new_cursor_width;
+  int active_cursor;
   struct glyph_matrix *current_glyphs;
   struct glyph_row *glyph_row;
   struct glyph *glyph;
@@ -8636,8 +9782,8 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
   current_glyphs = w->current_matrix;
   glyph_row = MATRIX_ROW (current_glyphs, vpos);
   glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
-  
-  /* If cursor row is not enabled, we don't really know where to 
+
+  /* If cursor row is not enabled, we don't really know where to
      display the cursor.  */
   if (!glyph_row->enabled_p)
     {
@@ -8647,49 +9793,8 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
 
   xassert (interrupt_input_blocked);
 
-  /* Set new_cursor_type to the cursor we want to be displayed.  In a
-     mini-buffer window, we want the cursor only to appear if we are
-     reading input from this window.  For the selected window, we want
-     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.  */
-  new_cursor_width = -1;
-  if (cursor_in_echo_area
-      && FRAME_HAS_MINIBUF_P (f)
-      && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
-    {
-      if (w == XWINDOW (echo_area_window))
-       new_cursor_type = FRAME_DESIRED_CURSOR (f);
-      else
-       new_cursor_type = HOLLOW_BOX_CURSOR;
-    }
-  else
-    {
-      if (w != XWINDOW (selected_window)
-          || f != FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame)
-        {
-         extern int cursor_in_non_selected_windows;
-
-          if (MINI_WINDOW_P (w) 
-              || !cursor_in_non_selected_windows
-              || 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);
-
-         if (EQ (b->cursor_type, Qt))
-            new_cursor_type = FRAME_DESIRED_CURSOR (f);
-         else
-           new_cursor_type = x_specified_cursor_type (b->cursor_type, 
-                                                      &new_cursor_width);
-       }
-    }
+  /* Set new_cursor_type to the cursor we want to be displayed.  */
+  new_cursor_type = get_window_cursor_type (w, &new_cursor_width, &active_cursor);
 
   /* If cursor is currently being shown and we don't want it to be or
      it is in the wrong place, or the cursor type is not what we want,
@@ -8698,25 +9803,71 @@ 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_type == HBAR_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,
-     display it.  */
-  if (on && !w->phys_cursor_on_p)
+  /* Don't check phys_cursor_on_p here because that flag is only set
+     to zero in some cases where we know that the cursor has been
+     completely erased, to avoid the extra work of erasing the cursor
+     twice.  In other words, phys_cursor_on_p can be 1 and the cursor
+     still not be visible, or it has only been partly erased.  */
+  if (on)
     {
       w->phys_cursor_ascent = glyph_row->ascent;
       w->phys_cursor_height = glyph_row->height;
-      
+
       /* Set phys_cursor_.* before x_draw_.* is called because some
         of them may need the information.  */
       w->phys_cursor.x = x;
       w->phys_cursor.y = glyph_row->y;
       w->phys_cursor.hpos = hpos;
       w->phys_cursor.vpos = vpos;
-      w->phys_cursor_type = 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)
+       {
+         if (w->phys_cursor_type != NO_CURSOR)
+           x_erase_phys_cursor (w);
+
+         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:
@@ -8728,7 +9879,11 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
          break;
 
        case BAR_CURSOR:
-         x_draw_bar_cursor (w, glyph_row, new_cursor_width);
+         x_draw_bar_cursor (w, glyph_row, new_cursor_width, BAR_CURSOR);
+         break;
+
+       case HBAR_CURSOR:
+         x_draw_bar_cursor (w, glyph_row, new_cursor_width, HBAR_CURSOR);
          break;
 
        case NO_CURSOR:
@@ -8822,8 +9977,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)
@@ -8832,7 +9985,7 @@ x_bitmap_icon (f, icon)
   if (NILP (icon))
     hicon = LoadIcon (hinst, EMACS_CLASS);
   else if (STRINGP (icon))
-    hicon = LoadImage (NULL, (LPCTSTR) XSTRING (icon)->data, IMAGE_ICON, 0, 0,
+    hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
                       LR_DEFAULTSIZE | LR_LOADFROMFILE);
   else if (SYMBOLP (icon))
     {
@@ -8868,6 +10021,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
@@ -8906,7 +10083,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,
@@ -8928,7 +10106,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;
@@ -8938,7 +10115,7 @@ x_new_fontset (f, fontsetname)
        to do.  */
     return fontset_name (fontset);
 
-  result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
+  result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
 
   if (!STRINGP (result))
     /* Can't load ASCII font.  */
@@ -8950,92 +10127,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;
-{
-  /*
-   * NTEMACS_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
@@ -9045,14 +10234,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;
@@ -9065,7 +10254,7 @@ x_calc_absolute_position (f)
   {
       RECT rt;
       rt.left = rt.right = rt.top = rt.bottom = 0;
-      
+
       BLOCK_INPUT;
       AdjustWindowRect(&rt, f->output_data.w32->dwStyle,
                       FRAME_EXTERNAL_MENU_BAR (f));
@@ -9135,10 +10324,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;
@@ -9146,45 +10445,46 @@ x_set_window_size (f, change_gravity, cols, rows)
      int cols, rows;
 {
   int pixelwidth, pixelheight;
-  
+
   BLOCK_INPUT;
-  
+
   check_frame_size (f, &rows, &cols);
   f->output_data.w32->vertical_scroll_bar_extra
     = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
        ? 0
        : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font)));
-  f->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);
-  
+
   f->output_data.w32->win_gravity = NorthWestGravity;
   x_wm_set_size_hint (f, (long) 0, 0);
-  
+
   {
     RECT rect;
 
     rect.left = rect.top = 0;
     rect.right = pixelwidth;
     rect.bottom = pixelheight;
-      
+
     AdjustWindowRect(&rect, f->output_data.w32->dwStyle,
                     FRAME_EXTERNAL_MENU_BAR (f));
-      
+
     my_set_window_pos (FRAME_W32_WINDOW (f),
-                      NULL, 
+                      NULL,
                       0, 0,
                       rect.right - rect.left,
                       rect.bottom - rect.top,
                       SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
   }
-  
+
   /* Now, strictly speaking, we can't be sure that this is accurate,
      but the window manager will get around to dealing with the size
      change request eventually, and we'll hear how it went when the
      ConfigureNotify event gets here.
-     
+
      We could just not bother storing any of this information here,
      and let the ConfigureNotify event set everything up, but that
      might be kind of confusing to the Lisp code, since size changes
@@ -9207,7 +10507,7 @@ x_set_window_size (f, change_gravity, cols, rows)
   mark_window_cursors_off (XWINDOW (f->root_window));
 
   /* Clear out any recollection of where the mouse highlighting was,
-     since it might be in a place that's outside the new frame size. 
+     since it might be in a place that's outside the new frame size.
      Actually checking whether it is outside is a pain in the neck,
      so don't try--just let the highlighting be done afresh with new size.  */
   cancel_mouse_face (f);
@@ -9363,6 +10663,9 @@ w32_frame_raise_lower (f, raise_flag)
      FRAME_PTR f;
      int raise_flag;
 {
+  if (! FRAME_W32_P (f))
+    return;
+
   if (raise_flag)
     x_raise_frame (f);
   else
@@ -9402,7 +10705,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);
     }
 
@@ -9425,7 +10728,7 @@ x_make_frame_visible (f)
         input_signal_count < count && !FRAME_VISIBLE_P (f);)
       {
        /* Force processing of queued events.  */
-        /* NTEMACS_TODO: x_sync equivalent?  */
+        /* TODO: x_sync equivalent?  */
 
        /* Machines that do polling rather than SIGIO have been observed
           to go into a busy-wait here.  So we'll fake an alarm signal
@@ -9454,13 +10757,13 @@ x_make_frame_invisible (f)
      struct frame *f;
 {
   /* Don't keep the highlight on an invisible frame.  */
-  if (FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame == f)
-    FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame = 0;
-  
+  if (FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame == f)
+    FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame = 0;
+
   BLOCK_INPUT;
-  
+
   my_show_window (f, FRAME_W32_WINDOW (f), SW_HIDE);
-  
+
   /* We can't distinguish this from iconification
      just by the event that we get from the server.
      So we can't win using the usual strategy of letting
@@ -9470,7 +10773,7 @@ x_make_frame_invisible (f)
   FRAME_ICONIFIED_P (f) = 0;
   f->async_visible = 0;
   f->async_iconified = 0;
-  
+
   UNBLOCK_INPUT;
 }
 
@@ -9480,12 +10783,11 @@ void
 x_iconify_frame (f)
      struct frame *f;
 {
-  int result;
   Lisp_Object type;
 
   /* Don't keep the highlight on an invisible frame.  */
-  if (FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame == f)
-    FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame = 0;
+  if (FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame == f)
+    FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame = 0;
 
   if (f->async_iconified)
     return;
@@ -9501,30 +10803,46 @@ x_iconify_frame (f)
 
   UNBLOCK_INPUT;
 }
+
 \f
-/* Destroy the window of frame F.  */
+/* Free X resources of frame F.  */
 
-x_destroy_window (f)
+void
+x_free_frame_resources (f)
      struct frame *f;
 {
   struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
 
   BLOCK_INPUT;
 
-  my_destroy_window (f, FRAME_W32_WINDOW (f));
+  if (FRAME_W32_WINDOW (f))
+    my_destroy_window (f, FRAME_W32_WINDOW (f));
+
   free_frame_menubar (f);
-  free_frame_faces (f);
+
+  unload_color (f, f->output_data.x->foreground_pixel);
+  unload_color (f, f->output_data.x->background_pixel);
+  unload_color (f, f->output_data.w32->cursor_pixel);
+  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);
 
   xfree (f->output_data.w32);
-  f->output_data.w32 = 0;
+  f->output_data.w32 = NULL;
+
   if (f == dpyinfo->w32_focus_frame)
     dpyinfo->w32_focus_frame = 0;
   if (f == dpyinfo->w32_focus_event_frame)
     dpyinfo->w32_focus_event_frame = 0;
-  if (f == dpyinfo->w32_highlight_frame)
-    dpyinfo->w32_highlight_frame = 0;
-
-  dpyinfo->reference_count--;
+  if (f == dpyinfo->x_highlight_frame)
+    dpyinfo->x_highlight_frame = 0;
 
   if (f == dpyinfo->mouse_face_mouse_frame)
     {
@@ -9533,10 +10851,26 @@ x_destroy_window (f)
       dpyinfo->mouse_face_end_row
        = dpyinfo->mouse_face_end_col = -1;
       dpyinfo->mouse_face_window = Qnil;
+      dpyinfo->mouse_face_deferred_gc = 0;
+      dpyinfo->mouse_face_mouse_frame = 0;
     }
 
   UNBLOCK_INPUT;
 }
+
+
+/* Destroy the window of frame F.  */
+
+x_destroy_window (f)
+     struct frame *f;
+{
+  struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
+
+  x_free_frame_resources (f);
+
+  dpyinfo->reference_count--;
+}
+
 \f
 /* Setting window manager hints.  */
 
@@ -9579,7 +10913,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
@@ -9599,13 +11039,13 @@ w32_initialize_display_info (display_name)
   w32_display_name_list = Fcons (Fcons (display_name, Qnil),
                                  w32_display_name_list);
   dpyinfo->name_list_element = XCAR (w32_display_name_list);
-  
+
   dpyinfo->w32_id_name
-    = (char *) xmalloc (XSTRING (Vinvocation_name)->size
-                       + XSTRING (Vsystem_name)->size
+    = (char *) xmalloc (SCHARS (Vinvocation_name)
+                       + SCHARS (Vsystem_name)
                        + 2);
   sprintf (dpyinfo->w32_id_name, "%s@%s",
-          XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
+          SDATA (Vinvocation_name), SDATA (Vsystem_name));
 
   /* Default Console mode values - overridden when running in GUI mode
      with values obtained from system metrics.  */
@@ -9623,8 +11063,9 @@ 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;
-
-  /* NTEMACS_TODO: dpyinfo->gray */
+  dpyinfo->mouse_face_overlay = Qnil;
+  dpyinfo->mouse_face_hidden = 0;
+  /* TODO: dpyinfo->gray */
 
 }
 
@@ -9636,15 +11077,15 @@ w32_term_init (display_name, xrm_option, resource_name)
 {
   struct w32_display_info *dpyinfo;
   HDC hdc;
-  
+
   BLOCK_INPUT;
-  
+
   if (!w32_initialized)
     {
       w32_initialize ();
       w32_initialized = 1;
     }
-  
+
   {
     int argc = 0;
     char *argv[3];
@@ -9657,11 +11098,15 @@ w32_term_init (display_name, xrm_option, resource_name)
        argv[argc++] = xrm_option;
       }
   }
-  
+
   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 ());
 
   dpyinfo->height = GetDeviceCaps (hdc, VERTRES);
@@ -9679,7 +11124,7 @@ w32_term_init (display_name, xrm_option, resource_name)
 
   /* initialise palette with white and black */
   {
-    COLORREF color;
+    XColor color;
     w32_defined_color (0, "white", &color, 1);
     w32_defined_color (0, "black", &color, 1);
   }
@@ -9735,7 +11180,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);
@@ -9802,18 +11247,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;
@@ -9824,13 +11265,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;
 
@@ -9843,7 +11289,7 @@ w32_initialize ()
   init_crit ();
 
   dwMainThreadId = GetCurrentThreadId ();
-  DuplicateHandle (GetCurrentProcess (), GetCurrentThread (), 
+  DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
                   GetCurrentProcess (), &hMainThread, 0, TRUE, DUPLICATE_SAME_ACCESS);
 
   /* Wait for thread to start */
@@ -9853,13 +11299,13 @@ w32_initialize ()
 
     PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
 
-    hWindowsThread = CreateThread (NULL, 0, 
-                              (LPTHREAD_START_ROUTINE) w32_msg_worker, 
+    hWindowsThread = CreateThread (NULL, 0,
+                              (LPTHREAD_START_ROUTINE) w32_msg_worker,
                               0, 0, &dwWindowsThreadId);
 
     GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
   }
-  
+
   /* It is desirable that mainThread should have the same notion of
      focus window and active window as windowsThread.  Unfortunately, the
      following call to AttachThreadInput, which should do precisely what
@@ -9901,8 +11347,6 @@ w32_initialize ()
 void
 syms_of_w32term ()
 {
-  Lisp_Object codepage;
-
   staticpro (&w32_display_name_list);
   w32_display_name_list = Qnil;
 
@@ -9914,43 +11358,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;
@@ -9963,15 +11407,46 @@ affect on NT machines.");
   staticpro (&previous_help_echo);
   help_echo_pos = -1;
 
+  DEFVAR_BOOL ("mouse-autoselect-window", &mouse_autoselect_window,
+    doc: /* *Non-nil means autoselect window with mouse pointer.  */);
+  mouse_autoselect_window = 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;
 
-  DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p,
-    "If not nil, Emacs uses toolkit scroll bars.");
-  x_toolkit_scroll_bars_p = 1;
+  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;
+
+  DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
+              doc: /* If not nil, Emacs uses toolkit scroll bars.  */);
+  Vx_toolkit_scroll_bars = Qt;
 
   staticpro (&last_mouse_motion_frame);
   last_mouse_motion_frame = Qnil;