(CHECK_FRAME, CHECK_LIVE_FRAME): Remove unused argument `i' in macros.
[bpt/emacs.git] / src / xterm.c
index 6d814b3..83da1b5 100644 (file)
@@ -1,5 +1,5 @@
 /* X Communication module for terminals which understand the X protocol.
 /* X Communication module for terminals which understand the X protocol.
-   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.
    Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -76,10 +76,6 @@ Boston, MA 02111-1307, USA.  */
 #include "termhooks.h"
 #include "termopts.h"
 #include "termchar.h"
 #include "termhooks.h"
 #include "termopts.h"
 #include "termchar.h"
-#if 0
-#include "sink.h"
-#include "sinkmask.h"
-#endif /* ! 0 */
 #include "gnu.h"
 #include "disptab.h"
 #include "buffer.h"
 #include "gnu.h"
 #include "disptab.h"
 #include "buffer.h"
@@ -88,6 +84,7 @@ Boston, MA 02111-1307, USA.  */
 #include "intervals.h"
 #include "process.h"
 #include "atimer.h"
 #include "intervals.h"
 #include "process.h"
 #include "atimer.h"
+#include "keymap.h"
 
 #ifdef USE_X_TOOLKIT
 #include <X11/Shell.h>
 
 #ifdef USE_X_TOOLKIT
 #include <X11/Shell.h>
@@ -100,6 +97,11 @@ Boston, MA 02111-1307, USA.  */
 #include <unistd.h>
 #endif
 
 #include <unistd.h>
 #endif
 
+#ifdef USE_LUCID
+extern int xlwmenu_window_p (Widget w, Window window);
+extern void xlwmenu_redisplay P_ ((Widget));
+#endif
+
 #ifdef USE_X_TOOLKIT
 
 extern void free_frame_menubar P_ ((struct frame *));
 #ifdef USE_X_TOOLKIT
 
 extern void free_frame_menubar P_ ((struct frame *));
@@ -117,7 +119,6 @@ extern void _XEditResCheckMessages ();
 #if defined USE_MOTIF
 #include <Xm/Xm.h>             /* for LESSTIF_VERSION */
 #include <Xm/ScrollBar.h>
 #if defined USE_MOTIF
 #include <Xm/Xm.h>             /* for LESSTIF_VERSION */
 #include <Xm/ScrollBar.h>
-#include <Xm/ScrollBarP.h>
 #else /* !USE_MOTIF i.e. use Xaw */
 
 #ifdef HAVE_XAW3D
 #else /* !USE_MOTIF i.e. use Xaw */
 
 #ifdef HAVE_XAW3D
@@ -149,13 +150,6 @@ extern void _XEditResCheckMessages ();
 #endif
 #endif
 
 #endif
 #endif
 
-#ifndef min
-#define min(a,b) ((a) < (b) ? (a) : (b))
-#endif
-#ifndef max
-#define max(a,b) ((a) > (b) ? (a) : (b))
-#endif
-
 #define abs(x) ((x) < 0 ? -(x) : (x))
 
 #define BETWEEN(X, LOWER, UPPER)  ((X) >= (LOWER) && (X) < (UPPER))
 #define abs(x) ((x) < 0 ? -(x) : (x))
 
 #define BETWEEN(X, LOWER, UPPER)  ((X) >= (LOWER) && (X) < (UPPER))
@@ -257,6 +251,10 @@ static int any_help_event_p;
 
 int x_stretch_cursor_p;
 
 
 int x_stretch_cursor_p;
 
+/* Non-zero means make use of UNDERLINE_POSITION font properties.  */
+
+int x_use_underline_position_properties;
+
 /* This is a chain of structures for all the X displays currently in
    use.  */
 
 /* This is a chain of structures for all the X displays currently in
    use.  */
 
@@ -396,17 +394,23 @@ enum draw_glyphs_face
   DRAW_IMAGE_SUNKEN
 };
 
   DRAW_IMAGE_SUNKEN
 };
 
-static const XColor *x_color_cells P_ ((struct frame *, int *));
+static int cursor_in_mouse_face_p P_ ((struct window *));
+static int clear_mouse_face P_ ((struct x_display_info *));
+static int x_alloc_nearest_color_1 P_ ((Display *, Colormap, XColor *));
+static void x_set_window_size_1 P_ ((struct frame *, int, int, int));
+static const XColor *x_color_cells P_ ((Display *, int *));
 static void x_update_window_end P_ ((struct window *, int, int));
 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
 void x_delete_display P_ ((struct x_display_info *));
 static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
                                                unsigned));
 static int fast_find_position P_ ((struct window *, int, int *, int *,
 static void x_update_window_end P_ ((struct window *, int, int));
 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
 void x_delete_display P_ ((struct x_display_info *));
 static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
                                                unsigned));
 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,
 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 note_mouse_highlight P_ ((struct frame *, int, int));
 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
 static void note_mode_line_highlight P_ ((struct window *, int, int));
 static void note_mouse_highlight P_ ((struct frame *, int, int));
 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
@@ -432,8 +436,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 XTframe_up_to_date P_ ((struct frame *));
                                          enum draw_glyphs_face));
 static void x_update_end P_ ((struct frame *));
 static void XTframe_up_to_date P_ ((struct frame *));
-static void XTreassert_line_highlight P_ ((int, int));
-static void x_change_line_highlight P_ ((int, int, int, int));
 static void XTset_terminal_modes P_ ((void));
 static void XTreset_terminal_modes P_ ((void));
 static void XTcursor_to P_ ((int, int, int, int));
 static void XTset_terminal_modes P_ ((void));
 static void XTreset_terminal_modes P_ ((void));
 static void XTcursor_to P_ ((int, int, int, int));
@@ -451,11 +453,11 @@ static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
 static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
                                       XRectangle *));
 static void expose_frame P_ ((struct frame *, int, int, int, int));
 static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
                                       XRectangle *));
 static void expose_frame P_ ((struct frame *, int, int, int, int));
-static void expose_window_tree P_ ((struct window *, XRectangle *));
-static void expose_window P_ ((struct window *, XRectangle *));
+static int expose_window_tree P_ ((struct window *, XRectangle *));
+static int expose_window P_ ((struct window *, XRectangle *));
 static void expose_area P_ ((struct window *, struct glyph_row *,
                             XRectangle *, enum glyph_row_area));
 static void expose_area P_ ((struct window *, struct glyph_row *,
                             XRectangle *, enum glyph_row_area));
-static void expose_line P_ ((struct window *, struct glyph_row *,
+static int expose_line P_ ((struct window *, struct glyph_row *,
                             XRectangle *));
 static void x_update_cursor_in_window_tree P_ ((struct window *, int));
 static void x_update_window_cursor P_ ((struct window *, int));
                             XRectangle *));
 static void x_update_cursor_in_window_tree P_ ((struct window *, int));
 static void x_update_window_cursor P_ ((struct window *, int));
@@ -468,7 +470,7 @@ static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
                               GC, int));
 static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
 static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *));
                               GC, int));
 static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
 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 notice_overwritten_cursor P_ ((struct window *, int, int));
 static void x_flush P_ ((struct frame *f));
 static void x_update_begin P_ ((struct frame *));
 static void x_update_window_begin P_ ((struct window *));
 static void x_flush P_ ((struct frame *f));
 static void x_update_begin P_ ((struct frame *));
 static void x_update_window_begin P_ ((struct window *));
@@ -476,7 +478,11 @@ static void x_draw_vertical_border P_ ((struct window *));
 static void x_after_update_window_line P_ ((struct glyph_row *));
 static INLINE void take_vertical_position_into_account P_ ((struct it *));
 static void x_produce_stretch_glyph P_ ((struct it *));
 static void x_after_update_window_line P_ ((struct glyph_row *));
 static INLINE void take_vertical_position_into_account P_ ((struct it *));
 static void x_produce_stretch_glyph P_ ((struct it *));
-
+static struct scroll_bar *x_window_to_scroll_bar P_ ((Window));
+static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
+                                           enum scroll_bar_part *,
+                                           Lisp_Object *, Lisp_Object *,
+                                           unsigned long *));
 
 /* Flush display of frame F, or of all frames if F is null.  */
 
 
 /* Flush display of frame F, or of all frames if F is null.  */
 
@@ -680,22 +686,12 @@ x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
      struct window *w;
      int cursor_on_p, mouse_face_overwritten_p;
 {
      struct window *w;
      int cursor_on_p, mouse_face_overwritten_p;
 {
+  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
+      
   if (!w->pseudo_window_p)
     {
   if (!w->pseudo_window_p)
     {
-      struct x_display_info *dpyinfo
-       = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
-      
       BLOCK_INPUT;
 
       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,
       if (cursor_on_p)
        x_display_and_set_cursor (w, 1, output_cursor.hpos,
                                  output_cursor.vpos,
@@ -705,6 +701,15 @@ x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
       UNBLOCK_INPUT;
     }
   
       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;
+    }
+      
   updated_window = NULL;
 }
 
   updated_window = NULL;
 }
 
@@ -764,6 +769,8 @@ x_after_update_window_line (desired_row)
      struct glyph_row *desired_row;
 {
   struct window *w = updated_window;
      struct glyph_row *desired_row;
 {
   struct window *w = updated_window;
+  struct frame *f;
+  int width, height;
   
   xassert (w);
   
   
   xassert (w);
   
@@ -771,22 +778,36 @@ x_after_update_window_line (desired_row)
     {
       BLOCK_INPUT;
       x_draw_row_bitmaps (w, desired_row);
     {
       BLOCK_INPUT;
       x_draw_row_bitmaps (w, desired_row);
-
-      /* 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));
-
-         XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                     x, y, width, height, False);
-       }
+      UNBLOCK_INPUT;
+    }
+      
+  /* 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;
+      x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                   0, y, width, height, False);
+      x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                   f->output_data.x->pixel_width - width,
+                   y, width, height, False);
       UNBLOCK_INPUT;
     }
 }
       UNBLOCK_INPUT;
     }
 }
@@ -1011,32 +1032,6 @@ x_draw_row_bitmaps (w, row)
 }
 
 \f
 }
 
 \f
-/***********************************************************************
-                         Line Highlighting
- ***********************************************************************/
-
-/* External interface to control of standout mode.  Not used for X
-   frames.  Aborts when called.  */
-
-static void
-XTreassert_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 X 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 X window is mapped.  And nothing
 
 /* This is called when starting Emacs and when restarting after
    suspend.  When starting Emacs, no X window is mapped.  And nothing
@@ -1504,20 +1499,23 @@ x_produce_image_glyph (it)
   prepare_image_for_display (it->f, img);
 
   it->ascent = it->phys_ascent = image_ascent (img, face);
   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->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)
       
       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)
       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);
     }
 
   take_vertical_position_into_account (it);
@@ -1722,13 +1720,16 @@ x_produce_stretch_glyph (it)
 
   if (face->box != FACE_NO_BOX)
     {
 
   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)
       
       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)
       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);
     }
   
   take_vertical_position_into_account (it);
@@ -1795,8 +1796,7 @@ x_produce_glyphs (it)
         struct glyph because the character code itself tells if or
         not the character is multibyte.  Thus, in the future, we must
         consider eliminating the field `multibyte_p' in the struct
         struct glyph because the character code itself tells if or
         not the character is multibyte.  Thus, in the future, we must
         consider eliminating the field `multibyte_p' in the struct
-        glyph.
-      */
+        glyph.  */
       int saved_multibyte_p = it->multibyte_p;
 
       /* Maybe translate single-byte characters to multibyte, or the
       int saved_multibyte_p = it->multibyte_p;
 
       /* Maybe translate single-byte characters to multibyte, or the
@@ -1817,8 +1817,7 @@ x_produce_glyphs (it)
          else if (!SINGLE_BYTE_CHAR_P (it->c)
                   && !it->multibyte_p)
            {
          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);
            }
              it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
              face = FACE_FROM_ID (it->f, it->face_id);
            }
@@ -1885,9 +1884,14 @@ x_produce_glyphs (it)
            {
              int thick = face->box_line_width;
              
            {
              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)
              if (it->start_of_box_run_p)
                it->pixel_width += thick;
              if (it->end_of_box_run_p)
@@ -1930,11 +1934,11 @@ x_produce_glyphs (it)
          it->ascent = it->phys_ascent = font->ascent + boff;
          it->descent = it->phys_descent = font->descent - boff;
       
          it->ascent = it->phys_ascent = font->ascent + boff;
          it->descent = it->phys_descent = font->descent - 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')
            }
        }
       else if (it->char_to_display == '\t')
@@ -1999,8 +2003,14 @@ x_produce_glyphs (it)
          if (face->box != FACE_NO_BOX)
            {
              int thick = face->box_line_width;
          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->start_of_box_run_p)
                it->pixel_width += thick;
@@ -2266,8 +2276,14 @@ x_produce_glyphs (it)
       if (face->box != FACE_NO_BOX)
        {
          int thick = face->box_line_width;
       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->start_of_box_run_p)
            it->pixel_width += thick;
@@ -2324,7 +2340,8 @@ x_estimate_mode_line_height (f, face_id)
          {
            if (face->font)
              height = FONT_HEIGHT (face->font);
          {
            if (face->font)
              height = FONT_HEIGHT (face->font);
-           height += 2 * face->box_line_width;
+           if (face->box_line_width > 0)
+             height += 2 * face->box_line_width;
          }
       }
   
          }
       }
   
@@ -2453,7 +2470,7 @@ struct glyph_string
 };
 
 
 };
 
 
-#if 0
+#if GLYPH_DEBUG
 
 static void
 x_dump_glyph_string (s)
 
 static void
 x_dump_glyph_string (s)
@@ -2501,7 +2518,7 @@ static void x_init_glyph_string P_ ((struct glyph_string *,
                                        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));
 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 *,
 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 *,
@@ -2661,9 +2678,12 @@ x_set_mouse_face_gc (s)
   int face_id;
   struct face *face;
 
   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_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
   face = FACE_FROM_ID (s->f, face_id);
   face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
   face = FACE_FROM_ID (s->f, face_id);
+  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
   if (s->first_glyph->type == CHAR_GLYPH)
     face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
   else
@@ -2800,20 +2820,6 @@ x_get_glyph_string_clip_rect (s, r)
       r->height = s->row->visible_height;
     }
 
       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->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
-  else
-    r->y = 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->y -= s->f->output_data.x->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.  */
   /* 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.  */
@@ -2822,7 +2828,23 @@ x_get_glyph_string_clip_rect (s, r)
       r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
       r->height = window_text_bottom_y (s->w) - r->y;
     }
       r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
       r->height = window_text_bottom_y (s->w) - r->y;
     }
-      
+  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->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
+      else
+       r->y = 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->y -= s->f->output_data.x->internal_border_width;
+    }
+
   r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);
 }
 
   r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);
 }
 
@@ -3068,25 +3090,27 @@ x_draw_glyph_string_background (s, force_p)
      shouldn't be drawn in the first place.  */
   if (!s->background_filled_p)
     {
      shouldn't be drawn in the first place.  */
   if (!s->background_filled_p)
     {
+      int box_line_width = max (s->face->box_line_width, 0);
+
       if (s->stippled_p)
        {
          /* Fill background with a stipple pattern.  */
          XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
          XFillRectangle (s->display, s->window, s->gc, s->x,
       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->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;
        }
          XSetFillStyle (s->display, s->gc, FillSolid);
          s->background_filled_p = 1;
        }
-      else if (FONT_HEIGHT (s->font) < s->height - 2 * s->face->box_line_width
+      else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
               || s->font_not_found_p
               || s->extends_to_end_of_line_p
               || force_p)
        {
               || s->font_not_found_p
               || s->extends_to_end_of_line_p
               || 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->background_width,
-                                    s->height - 2 * s->face->box_line_width);
+                                    s->height - 2 * box_line_width);
          s->background_filled_p = 1;
        }
     }
          s->background_filled_p = 1;
        }
     }
@@ -3105,7 +3129,7 @@ x_draw_glyph_string_foreground (s)
      of S to the right of that box line.  */
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
      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;
 
   else
     x = s->x;
 
@@ -3175,7 +3199,7 @@ x_draw_composite_glyph_string_foreground (s)
      of S to the right of that box line.  */
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
      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;
 
   else
     x = s->x;
 
@@ -3206,6 +3230,10 @@ x_draw_composite_glyph_string_foreground (s)
 #ifdef USE_X_TOOLKIT
 
 static struct frame *x_frame_of_widget P_ ((Widget));
 #ifdef USE_X_TOOLKIT
 
 static struct frame *x_frame_of_widget P_ ((Widget));
+static Boolean cvt_string_to_pixel P_ ((Display *, XrmValue *, Cardinal *,
+                                       XrmValue *, XrmValue *, XtPointer *));
+static void cvt_pixel_dtor P_ ((XtAppContext, XrmValue *, XtPointer,
+                               XrmValue *, Cardinal *));
 
 
 /* Return the frame on which widget WIDGET is used.. Abort if frame
 
 
 /* Return the frame on which widget WIDGET is used.. Abort if frame
@@ -3279,29 +3307,178 @@ x_alloc_lighter_color_for_widget (widget, display, cmap, pixel, factor, delta)
 }
 
 
 }
 
 
+/* Structure specifying which arguments should be passed by Xt to
+   cvt_string_to_pixel.  We want the widget's screen and colormap.  */
+
+static XtConvertArgRec cvt_string_to_pixel_args[] =
+  {
+    {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.screen),
+     sizeof (Screen *)},
+    {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.colormap),
+     sizeof (Colormap)}
+  };
+
+
+/* The address of this variable is returned by
+   cvt_string_to_pixel.  */
+
+static Pixel cvt_string_to_pixel_value;
+
+
+/* Convert a color name to a pixel color.
+
+   DPY is the display we are working on.
+
+   ARGS is an array of *NARGS XrmValue structures holding additional
+   information about the widget for which the conversion takes place.
+   The contents of this array are determined by the specification
+   in cvt_string_to_pixel_args.
+
+   FROM is a pointer to an XrmValue which points to the color name to
+   convert.  TO is an XrmValue in which to return the pixel color.
+
+   CLOSURE_RET is a pointer to user-data, in which we record if
+   we allocated the color or not.
+
+   Value is True if successful, False otherwise.  */
+
+static Boolean
+cvt_string_to_pixel (dpy, args, nargs, from, to, closure_ret)
+     Display *dpy;
+     XrmValue *args;
+     Cardinal *nargs;
+     XrmValue *from, *to;
+     XtPointer *closure_ret;
+{
+  Screen *screen;
+  Colormap cmap;
+  Pixel pixel;
+  String color_name;
+  XColor color;
+
+  if (*nargs != 2)
+    {
+      XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
+                      "wrongParameters", "cvt_string_to_pixel",
+                      "XtToolkitError",
+                      "Screen and colormap args required", NULL, NULL);
+      return False;
+    }
+
+  screen = *(Screen **) args[0].addr;
+  cmap = *(Colormap *) args[1].addr;
+  color_name = (String) from->addr;
+
+  if (strcmp (color_name, XtDefaultBackground) == 0)
+    {
+      *closure_ret = (XtPointer) False;
+      pixel = WhitePixelOfScreen (screen);
+    }
+  else if (strcmp (color_name, XtDefaultForeground) == 0)
+    {
+      *closure_ret = (XtPointer) False;
+      pixel = BlackPixelOfScreen (screen);
+    }
+  else if (XParseColor (dpy, cmap, color_name, &color)
+          && x_alloc_nearest_color_1 (dpy, cmap, &color))
+    {
+      pixel = color.pixel;
+      *closure_ret = (XtPointer) True;
+    }
+  else
+    {
+      String params[1];
+      Cardinal nparams = 1;
+      
+      params[0] = color_name;
+      XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
+                      "badValue", "cvt_string_to_pixel",
+                      "XtToolkitError", "Invalid color `%s'",
+                      params, &nparams);
+      return False;
+    }
+
+  if (to->addr != NULL)
+    {
+      if (to->size < sizeof (Pixel))
+       {
+         to->size = sizeof (Pixel);
+         return False;
+       }
+      
+      *(Pixel *) to->addr = pixel;
+    }
+  else
+    {
+      cvt_string_to_pixel_value = pixel;
+      to->addr = (XtPointer) &cvt_string_to_pixel_value;
+    }
+  
+  to->size = sizeof (Pixel);
+  return True;
+}
+
+
+/* Free a pixel color which was previously allocated via
+   cvt_string_to_pixel.  This is registered as the destructor
+   for this type of resource via XtSetTypeConverter.
+
+   APP is the application context in which we work.
+
+   TO is a pointer to an XrmValue holding the color to free.
+   CLOSURE is the value we stored in CLOSURE_RET for this color
+   in cvt_string_to_pixel.
+
+   ARGS and NARGS are like for cvt_string_to_pixel.  */
+
+static void
+cvt_pixel_dtor (app, to, closure, args, nargs)
+    XtAppContext app;
+    XrmValuePtr to;
+    XtPointer closure;
+    XrmValuePtr args;
+    Cardinal *nargs;
+{
+  if (*nargs != 2)
+    {
+      XtAppWarningMsg (app, "wrongParameters", "cvt_pixel_dtor",
+                      "XtToolkitError",
+                      "Screen and colormap arguments required",
+                      NULL, NULL);
+    }
+  else if (closure != NULL)
+    {
+      /* We did allocate the pixel, so free it.  */
+      Screen *screen = *(Screen **) args[0].addr;
+      Colormap cmap = *(Colormap *) args[1].addr;
+      x_free_dpy_colors (DisplayOfScreen (screen), screen, cmap,
+                        (Pixel *) to->addr, 1);
+    }
+}
+
+
 #endif /* USE_X_TOOLKIT */
 
 
 /* Value is an array of XColor structures for the contents of the
 #endif /* USE_X_TOOLKIT */
 
 
 /* Value is an array of XColor structures for the contents of the
-   color map of frame F.  Set *NCELLS to the size of the array.
+   color map of display DPY.  Set *NCELLS to the size of the array.
    Note that this probably shouldn't be called for large color maps,
    say a 24-bit TrueColor map.  */
 
 static const XColor *
    Note that this probably shouldn't be called for large color maps,
    say a 24-bit TrueColor map.  */
 
 static const XColor *
-x_color_cells (f, ncells)
-     struct frame *f;
+x_color_cells (dpy, ncells)
+     Display *dpy;
      int *ncells;
 {
      int *ncells;
 {
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
 
   if (dpyinfo->color_cells == NULL)
     {
 
   if (dpyinfo->color_cells == NULL)
     {
-      Display *display = FRAME_X_DISPLAY (f);
-      Screen *screen = FRAME_X_SCREEN (f);
+      Screen *screen = dpyinfo->screen;
       int i;
       
       dpyinfo->ncolor_cells
       int i;
       
       dpyinfo->ncolor_cells
-       = XDisplayCells (display, XScreenNumberOfScreen (screen));
+       = XDisplayCells (dpy, XScreenNumberOfScreen (screen));
       dpyinfo->color_cells
        = (XColor *) xmalloc (dpyinfo->ncolor_cells
                              * sizeof *dpyinfo->color_cells);
       dpyinfo->color_cells
        = (XColor *) xmalloc (dpyinfo->ncolor_cells
                              * sizeof *dpyinfo->color_cells);
@@ -3309,7 +3486,7 @@ x_color_cells (f, ncells)
       for (i = 0; i < dpyinfo->ncolor_cells; ++i)
        dpyinfo->color_cells[i].pixel = i;
       
       for (i = 0; i < dpyinfo->ncolor_cells; ++i)
        dpyinfo->color_cells[i].pixel = i;
       
-      XQueryColors (display, FRAME_X_COLORMAP (f),
+      XQueryColors (dpy, dpyinfo->cmap,
                    dpyinfo->color_cells, dpyinfo->ncolor_cells);
     }
 
                    dpyinfo->color_cells, dpyinfo->ncolor_cells);
     }
 
@@ -3357,23 +3534,20 @@ x_query_color (f, color)
 }
      
 
 }
      
 
-/* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
-   CMAP.  If an exact match can't be allocated, try the nearest color
-   available.  Value is non-zero if successful.  Set *COLOR to the
-   color allocated.  */
+/* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP.  If an
+   exact match can't be allocated, try the nearest color available.
+   Value is non-zero if successful.  Set *COLOR to the color
+   allocated.  */
 
 
-int
-x_alloc_nearest_color (f, cmap, color)
-     struct frame *f;
+static int
+x_alloc_nearest_color_1 (dpy, cmap, color)
+     Display *dpy;
      Colormap cmap;
      XColor *color;
 {
      Colormap cmap;
      XColor *color;
 {
-  Display *display = FRAME_X_DISPLAY (f);
-  Screen *screen = FRAME_X_SCREEN (f);
   int rc;
 
   int rc;
 
-  gamma_correct (f, color);
-  rc = XAllocColor (display, cmap, color);
+  rc = XAllocColor (dpy, cmap, color);
   if (rc == 0)
     {
       /* If we got to this point, the colormap is full, so we're going
   if (rc == 0)
     {
       /* If we got to this point, the colormap is full, so we're going
@@ -3383,7 +3557,7 @@ x_alloc_nearest_color (f, cmap, color)
       int nearest, i;
       unsigned long nearest_delta = ~0;
       int ncells;
       int nearest, i;
       unsigned long nearest_delta = ~0;
       int ncells;
-      const XColor *cells = x_color_cells (f, &ncells);
+      const XColor *cells = x_color_cells (dpy, &ncells);
 
       for (nearest = i = 0; i < ncells; ++i)
        {
 
       for (nearest = i = 0; i < ncells; ++i)
        {
@@ -3402,14 +3576,14 @@ x_alloc_nearest_color (f, cmap, color)
       color->red   = cells[nearest].red;
       color->green = cells[nearest].green;
       color->blue  = cells[nearest].blue;
       color->red   = cells[nearest].red;
       color->green = cells[nearest].green;
       color->blue  = cells[nearest].blue;
-      rc = XAllocColor (display, cmap, color);
+      rc = XAllocColor (dpy, cmap, color);
     }
   else
     {
       /* If allocation succeeded, and the allocated pixel color is not
          equal to a cached pixel color recorded earlier, there was a
          change in the colormap, so clear the color cache.  */
     }
   else
     {
       /* If allocation succeeded, and the allocated pixel color is not
          equal to a cached pixel color recorded earlier, there was a
          change in the colormap, so clear the color cache.  */
-      struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+      struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
       XColor *cached_color;
       
       if (dpyinfo->color_cells
       XColor *cached_color;
       
       if (dpyinfo->color_cells
@@ -3433,6 +3607,22 @@ x_alloc_nearest_color (f, cmap, color)
 }
 
 
 }
 
 
+/* Allocate the color COLOR->pixel on frame F, colormap CMAP.  If an
+   exact match can't be allocated, try the nearest color available.
+   Value is non-zero if successful.  Set *COLOR to the color
+   allocated.  */
+
+int
+x_alloc_nearest_color (f, cmap, color)
+     struct frame *f;
+     Colormap cmap;
+     XColor *color;
+{
+  gamma_correct (f, color);
+  return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f), cmap, color);
+}
+
+
 /* Allocate color PIXEL on frame F.  PIXEL must already be allocated.
    It's necessary to do this instead of just using PIXEL directly to
    get color reference counts right.  */
 /* Allocate color PIXEL on frame F.  PIXEL must already be allocated.
    It's necessary to do this instead of just using PIXEL directly to
    get color reference counts right.  */
@@ -3645,6 +3835,9 @@ x_setup_relief_colors (s)
 
   if (s->face->use_box_color_for_shadows_p)
     color = s->face->box_color;
 
   if (s->face->use_box_color_for_shadows_p)
     color = s->face->box_color;
+  else if (s->first_glyph->type == IMAGE_GLYPH
+          && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
+    color = IMAGE_BACKGROUND (s->img, s->f, 0);
   else
     {
       XGCValues xgcv;
   else
     {
       XGCValues xgcv;
@@ -3681,6 +3874,8 @@ x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
      int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
      XRectangle *clip_rect;
 {
      int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
      XRectangle *clip_rect;
 {
+  Display *dpy = FRAME_X_DISPLAY (f);
+  Window window = FRAME_X_WINDOW (f);
   int i;
   GC gc;
   
   int i;
   GC gc;
   
@@ -3688,40 +3883,40 @@ x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
     gc = f->output_data.x->white_relief.gc;
   else
     gc = f->output_data.x->black_relief.gc;
     gc = f->output_data.x->white_relief.gc;
   else
     gc = f->output_data.x->black_relief.gc;
-  XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
+  XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
 
   /* Top.  */
   for (i = 0; i < width; ++i)
 
   /* Top.  */
   for (i = 0; i < width; ++i)
-    XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+    XDrawLine (dpy, window, gc,
               left_x + i * left_p, top_y + i,
               right_x + 1 - i * right_p, top_y + i);
 
   /* Left.  */
   if (left_p)
     for (i = 0; i < width; ++i)
               left_x + i * left_p, top_y + i,
               right_x + 1 - i * right_p, top_y + i);
 
   /* Left.  */
   if (left_p)
     for (i = 0; i < width; ++i)
-      XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
-                left_x + i, top_y + i, left_x + i, bottom_y - i);
+      XDrawLine (dpy, window, gc,
+                left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
 
 
-  XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
+  XSetClipMask (dpy, gc, None);
   if (raised_p)
     gc = f->output_data.x->black_relief.gc;
   else
     gc = f->output_data.x->white_relief.gc;
   if (raised_p)
     gc = f->output_data.x->black_relief.gc;
   else
     gc = f->output_data.x->white_relief.gc;
-  XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
+  XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
   
   /* Bottom.  */
   for (i = 0; i < width; ++i)
   
   /* Bottom.  */
   for (i = 0; i < width; ++i)
-    XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+    XDrawLine (dpy, window, gc,
               left_x + i * left_p, bottom_y - i,
               right_x + 1 - i * right_p, bottom_y - i);
   
   /* Right.  */
   if (right_p)
     for (i = 0; i < width; ++i)
               left_x + i * left_p, bottom_y - i,
               right_x + 1 - i * right_p, bottom_y - i);
   
   /* Right.  */
   if (right_p)
     for (i = 0; i < width; ++i)
-      XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+      XDrawLine (dpy, window, gc,
                 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
 
                 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
 
-  XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
+  XSetClipMask (dpy, gc, None);
 }
 
 
 }
 
 
@@ -3793,12 +3988,12 @@ x_draw_glyph_string_box (s)
                ? s->first_glyph
                : s->first_glyph + s->nchars - 1);
 
                ? 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;
   raised_p = s->face->box == FACE_RAISED_BOX;
   left_x = s->x;
-  right_x = ((s->row->full_width_p
-             ? last_x - 1
-             : min (last_x, s->x + s->background_width) - 1));
+  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;
   bottom_y = top_y + s->height - 1;
 
   top_y = s->y;
   bottom_y = top_y + s->height - 1;
 
@@ -3810,7 +4005,7 @@ x_draw_glyph_string_box (s)
             || (s->hl == DRAW_MOUSE_FACE
                 && (s->next == NULL
                     || s->next->hl != s->hl)));
             || (s->hl == DRAW_MOUSE_FACE
                 && (s->next == NULL
                     || s->next->hl != s->hl)));
-  
+
   x_get_glyph_string_clip_rect (s, &clip_rect);
 
   if (s->face->box == FACE_SIMPLE_BOX)
   x_get_glyph_string_clip_rect (s, &clip_rect);
 
   if (s->face->box == FACE_SIMPLE_BOX)
@@ -3838,17 +4033,14 @@ x_draw_image_foreground (s)
      right of that line.  */
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
      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.  */
   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->img->pixmap)
     {
 
   if (s->img->pixmap)
     {
@@ -3881,8 +4073,6 @@ x_draw_image_foreground (s)
        }
       else
        {
        }
       else
        {
-         unsigned long mask = GCClipXOrigin | GCClipYOrigin | GCFunction;
-         XGCValues xgcv;
          XRectangle clip_rect, image_rect, r;
 
          x_get_glyph_string_clip_rect (s, &clip_rect);
          XRectangle clip_rect, image_rect, r;
 
          x_get_glyph_string_clip_rect (s, &clip_rect);
@@ -3927,17 +4117,14 @@ x_draw_image_relief (s)
      right of that line.  */
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
      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.  */
   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)
   
   if (s->hl == DRAW_IMAGE_SUNKEN
       || s->hl == DRAW_IMAGE_RAISED)
@@ -3976,17 +4163,14 @@ x_draw_image_foreground_1 (s, pixmap)
      right of that line.  */
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
      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.  */
   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 (s->img->pixmap)
     {
@@ -4073,29 +4257,30 @@ x_draw_image_glyph_string (s)
      struct glyph_string *s;
 {
   int x, y;
      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;
   Pixmap pixmap = None;
 
   int height;
   Pixmap pixmap = None;
 
-  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
 
   /* Fill background with face under the image.  Do it only if row is
      taller than image or if image has a clip mask to reduce
      flickering.  */
   s->stippled_p = s->face->stipple != 0;
   if (height > s->img->height
-      || margin
+      || s->img->hmargin
+      || s->img->vmargin
       || s->img->mask
       || s->img->pixmap == 0
       || s->width != s->background_width)
     {
       || s->img->mask
       || 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;
       
       else
        x = s->x;
       
-      y = s->y + box_line_width;
+      y = s->y + box_line_vwidth;
       
       if (s->img->mask)
        {
       
       if (s->img->mask)
        {
@@ -4182,14 +4367,23 @@ x_draw_stretch_glyph_string (s)
       /* Clear rest using the GC of the original non-cursor face.  */
       if (width < s->background_width)
        {
       /* Clear rest using the GC of the original non-cursor face.  */
       if (width < s->background_width)
        {
-         GC gc = s->face->gc;
          int x = s->x + width, y = s->y;
          int w = s->background_width - width, h = s->height;
          XRectangle r;
          int x = s->x + width, y = s->y;
          int w = s->background_width - width, h = s->height;
          XRectangle r;
+         GC gc;
 
 
+         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;
+  
          x_get_glyph_string_clip_rect (s, &r);
          XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
          x_get_glyph_string_clip_rect (s, &r);
          XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
-
+         
          if (s->face->stipple)
            {
              /* Fill background with a stipple pattern.  */
          if (s->face->stipple)
            {
              /* Fill background with a stipple pattern.  */
@@ -4207,7 +4401,7 @@ x_draw_stretch_glyph_string (s)
            }
        }
     }
            }
        }
     }
-  else
+  else if (!s->background_filled_p)
     x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
                                 s->height);
   
     x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
                                 s->height);
   
@@ -4221,6 +4415,8 @@ static void
 x_draw_glyph_string (s)
      struct glyph_string *s;
 {
 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.  */
   /* 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.  */
@@ -4234,7 +4430,23 @@ x_draw_glyph_string (s)
 
   /* Set up S->gc, set clipping and draw S.  */
   x_set_glyph_string_gc (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)
     {
 
   switch (s->first_glyph->type)
     {
@@ -4286,12 +4498,13 @@ x_draw_glyph_string (s)
             ROUND ((maximum descent) / 2), with
             ROUND(x) = floor (x + 0.5)  */
          
             ROUND ((maximum descent) / 2), with
             ROUND(x) = floor (x + 0.5)  */
          
-         if (XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
+         if (x_use_underline_position_properties
+             && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
            y = s->ybase + (long) tem;
          else if (s->face->font)
            y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
          else
            y = s->ybase + (long) tem;
          else if (s->face->font)
            y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
          else
-           y = s->height - h;
+           y = s->y + s->height - h;
       
          if (s->face->underline_defaulted_p)
            XFillRectangle (s->display, s->window, s->gc,
       
          if (s->face->underline_defaulted_p)
            XFillRectangle (s->display, s->window, s->gc,
@@ -4346,8 +4559,8 @@ x_draw_glyph_string (s)
            }
        }
   
            }
        }
   
-      /* Draw relief.  */
-      if (s->face->box != FACE_NO_BOX)
+      /* Draw relief if not yet drawn.  */
+      if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
        x_draw_glyph_string_box (s);
     }
   
        x_draw_glyph_string_box (s);
     }
   
@@ -4547,7 +4760,9 @@ x_fill_stretch_glyph_string (s, row, area, start, end)
   /* Adjust base line for subscript/superscript text.  */
   s->ybase += voffset;
 
   /* Adjust base line for subscript/superscript text.  */
   s->ybase += voffset;
 
-  xassert (s->face && s->face->gc);
+  /* The case that face->gc == 0 is handled when drawing the glyph
+     string by calling PREPARE_FACE_FOR_DISPLAY.  */
+  xassert (s->face);
   return glyph - s->row->glyphs[s->area];
 }
 
   return glyph - s->row->glyphs[s->area];
 }
 
@@ -4606,11 +4821,16 @@ x_set_glyph_string_background_width (s, start, last_x)
   struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
   
   if (start == s->row->used[s->area]
   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->extends_to_end_of_line_p = 1;
+      && 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
   
   /* 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
@@ -4813,27 +5033,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
 
    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
    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;
      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;
      int overlaps_p;
 {
   struct glyph_string *head, *tail;
@@ -4846,10 +5058,6 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
   end = min (end, row->used[area]);
   start = max (0, start);
   start = min (end, start);
   end = min (end, row->used[area]);
   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.  */
 
   /* Translate X to frame coordinates.  Set last_x to the right
      end of the drawing area.  */
@@ -4875,7 +5083,7 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
        }
 
       x += FRAME_INTERNAL_BORDER_WIDTH (f);
        }
 
       x += FRAME_INTERNAL_BORDER_WIDTH (f);
-      last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
+      last_x += FRAME_INTERNAL_BORDER_WIDTH (f);
     }
   else
     {
     }
   else
     {
@@ -4921,8 +5129,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;
                               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);
        }
          x_compute_overhangs_and_x (t, head->x, 1);
          x_prepend_glyph_string_lists (&head, &tail, h, t);
        }
@@ -4942,8 +5148,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;
                               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);
        }
          x_compute_overhangs_and_x (t, head->x, 1);
          x_prepend_glyph_string_lists (&head, &tail, h, t);
        }
@@ -4960,8 +5164,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);
                               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
        }
 
       /* Append glyph strings for glyphs following the last glyph
@@ -4979,8 +5181,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);
            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;
        }
     }
 
        }
     }
 
@@ -4988,12 +5188,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);
 
   for (s = head; s; s = s->next)
     x_draw_glyph_string (s);
 
+  if (area == TEXT_AREA && !row->full_width_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, x0, x1);
+    }
+
   /* 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);
   if (!row->full_width_p)
     {
   /* 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);
   if (!row->full_width_p)
     {
-      if (area > LEFT_MARGIN_AREA)
+      if (area > LEFT_MARGIN_AREA && XFASTINT (w->left_margin_width) != 0)
        x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
       if (area > TEXT_AREA)
        x_reached -= window_box_width (w, TEXT_AREA);
        x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
       if (area > TEXT_AREA)
        x_reached -= window_box_width (w, TEXT_AREA);
@@ -5038,9 +5256,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->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
        {
        }
       else
        {
@@ -5064,7 +5280,7 @@ x_write_glyphs (start, len)
      struct glyph *start;
      int len;
 {
      struct glyph *start;
      int len;
 {
-  int x, hpos, real_start, real_end;
+  int x, hpos;
 
   xassert (updated_window && updated_row);
   BLOCK_INPUT;
 
   xassert (updated_window && updated_row);
   BLOCK_INPUT;
@@ -5075,13 +5291,7 @@ x_write_glyphs (start, len)
   x = x_draw_glyphs (updated_window, output_cursor.x,
                     updated_row, updated_area,
                     hpos, hpos + len,
   x = x_draw_glyphs (updated_window, output_cursor.x,
                     updated_row, updated_area,
                     hpos, hpos + len,
-                    (updated_row->inverse_p
-                     ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
-                    &real_start, &real_end, 0);
-
-  /* If we drew over the cursor, note that it is not visible any more.  */
-  note_overwritten_text_cursor (updated_window, real_start,
-                               real_end - real_start);
+                    DRAW_NORMAL_TEXT, 0);
 
   UNBLOCK_INPUT;
   
 
   UNBLOCK_INPUT;
   
@@ -5103,7 +5313,7 @@ x_insert_glyphs (start, len)
   int line_height, shift_by_width, shifted_region_width;
   struct glyph_row *row;
   struct glyph *glyph;
   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;
 
   xassert (updated_window && updated_row);
   BLOCK_INPUT;
 
   xassert (updated_window && updated_row);
   BLOCK_INPUT;
@@ -5125,7 +5335,7 @@ x_insert_glyphs (start, len)
                          - shift_by_width);
 
   /* Shift right.  */
                          - 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);
   XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
             f->output_data.x->normal_gc,
   frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
   XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
             f->output_data.x->normal_gc,
@@ -5136,8 +5346,7 @@ 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,
   /* 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;
   
   /* Advance the output cursor.  */
   output_cursor.hpos += len;
@@ -5157,6 +5366,22 @@ x_delete_glyphs (n)
 }
 
 
 }
 
 
+/* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
+   If they are <= 0, this is probably an error.  */
+
+void
+x_clear_area (dpy, window, x, y, width, height, exposures)
+     Display *dpy;
+     Window window;
+     int x, y;
+     int width, height;
+     int exposures;
+{
+  xassert (width > 0 && height > 0);
+  XClearArea (dpy, window, x, y, width, height, exposures);
+}
+
+
 /* Erase the current text line from the nominal cursor position
    (inclusive) to pixel column TO_X (exclusive).  The idea is that
    everything from TO_X onward is already erased.
 /* Erase the current text line from the nominal cursor position
    (inclusive) to pixel column TO_X (exclusive).  The idea is that
    everything from TO_X onward is already erased.
@@ -5200,7 +5425,7 @@ x_clear_end_of_line (to_x)
   
   /* Notice if the cursor will be cleared by this operation.  */
   if (!updated_row->full_width_p)
   
   /* 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, output_cursor.x, -1);
 
   from_x = output_cursor.x;
      
 
   from_x = output_cursor.x;
      
@@ -5224,9 +5449,9 @@ x_clear_end_of_line (to_x)
   if (to_x > from_x && to_y > from_y)
     {
       BLOCK_INPUT;
   if (to_x > from_x && to_y > from_y)
     {
       BLOCK_INPUT;
-      XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                 from_x, from_y, to_x - from_x, to_y - from_y,
-                 False);
+      x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                   from_x, from_y, to_x - from_x, to_y - from_y,
+                   False);
       UNBLOCK_INPUT;
     }
 }
       UNBLOCK_INPUT;
     }
 }
@@ -5390,18 +5615,23 @@ XTflash (f)
        wakeup.tv_sec += (wakeup.tv_usec / 1000000);
        wakeup.tv_usec %= 1000000;
 
        wakeup.tv_sec += (wakeup.tv_usec / 1000000);
        wakeup.tv_usec %= 1000000;
 
-       /* Keep waiting until past the time wakeup.  */
-       while (1)
+       /* Keep waiting until past the time wakeup or any input gets
+          available.  */
+       while (! detect_input_pending ())
          {
          {
+           struct timeval current;
            struct timeval timeout;
 
            struct timeval timeout;
 
-           EMACS_GET_TIME (timeout);
+           EMACS_GET_TIME (current);
 
 
-           /* In effect, timeout = wakeup - timeout.
-              Break if result would be negative.  */
-           if (timeval_subtract (&timeout, wakeup, timeout))
+           /* Break if result would be negative.  */
+           if (timeval_subtract (&current, wakeup, current))
              break;
 
              break;
 
+           /* How long `select' should wait.  */
+           timeout.tv_sec = 0;
+           timeout.tv_usec = 10000;
+
            /* Try to wait that long--but we might wake up sooner.  */
            select (0, NULL, NULL, NULL, &timeout);
          }
            /* Try to wait that long--but we might wake up sooner.  */
            select (0, NULL, NULL, NULL, &timeout);
          }
@@ -5564,6 +5794,7 @@ expose_frame (f, x, y, w, h)
      int x, y, w, h;
 {
   XRectangle r;
      int x, y, w, h;
 {
   XRectangle r;
+  int mouse_face_overwritten_p = 0;
 
   TRACE ((stderr, "expose_frame "));
 
 
   TRACE ((stderr, "expose_frame "));
 
@@ -5599,90 +5830,69 @@ expose_frame (f, x, y, w, h)
     }
 
   TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
     }
 
   TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
-  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))
 
   if (WINDOWP (f->tool_bar_window))
-    {
-      struct window *w = XWINDOW (f->tool_bar_window);
-      XRectangle window_rect;
-      XRectangle 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.x = window_x;
-      window_rect.y = window_y;
-      window_rect.width = window_width;
-      window_rect.height = window_height;
-
-      if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
-       expose_window (w, &intersection_rect);
-    }
+    mouse_face_overwritten_p
+      |= expose_window (XWINDOW (f->tool_bar_window), &r);
 
 #ifndef USE_X_TOOLKIT
   if (WINDOWP (f->menu_bar_window))
 
 #ifndef USE_X_TOOLKIT
   if (WINDOWP (f->menu_bar_window))
-    {
-      struct window *w = XWINDOW (f->menu_bar_window);
-      XRectangle window_rect;
-      XRectangle 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.x = window_x;
-      window_rect.y = window_y;
-      window_rect.width = window_width;
-      window_rect.height = window_height;
+    mouse_face_overwritten_p
+      |= expose_window (XWINDOW (f->menu_bar_window), &r);
+#endif /* not USE_X_TOOLKIT */
 
 
-      if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
-       expose_window (w, &intersection_rect);
+  /* 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  */
+  if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
+    {
+      struct x_display_info *dpyinfo = FRAME_X_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);
+       }
     }
     }
-#endif /* not USE_X_TOOLKIT */
 }
 
 
 /* Redraw (parts) of all windows in the window tree rooted at W that
 }
 
 
 /* Redraw (parts) of all windows in the window tree rooted at W that
-   intersect R.  R contains frame pixel coordinates.  */
+   intersect R.  R contains frame pixel coordinates.  Value is
+   non-zero if the exposure overwrites mouse-face.  */
 
 
-static void
+static int
 expose_window_tree (w, r)
      struct window *w;
      XRectangle *r;
 {
 expose_window_tree (w, r)
      struct window *w;
      XRectangle *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))
     {
       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))
       else if (!NILP (w->vchild))
-       expose_window_tree (XWINDOW (w->vchild), r);
+       mouse_face_overwritten_p
+         |= expose_window_tree (XWINDOW (w->vchild), r);
       else
       else
-       {
-         XRectangle window_rect;
-         XRectangle 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.x
-           = (window_x
-              - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
-              - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
-         window_rect.y = window_y;
-         window_rect.width
-           = (window_width
-              + FRAME_X_FLAGS_AREA_WIDTH (f)
-              + FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
-         window_rect.height
-           = window_height + CURRENT_MODE_LINE_HEIGHT (w);
-
-         if (x_intersect_rectangles (r, &window_rect, &intersection_rect))
-           expose_window (w, &intersection_rect);
-       }
-
-      w = NILP (w->next) ? 0 : XWINDOW (w->next);
+       mouse_face_overwritten_p |= expose_window (w, r);
+      
+      w = NILP (w->next) ? NULL : XWINDOW (w->next);
     }
     }
+
+  return mouse_face_overwritten_p;
 }
 
 
 }
 
 
@@ -5703,10 +5913,8 @@ expose_area (w, row, r, area)
 
   if (area == TEXT_AREA && row->fill_line_p)
     /* If row extends face to end of line write the whole line.  */
 
   if (area == TEXT_AREA && row->fill_line_p)
     /* If row extends face to end of line write the whole line.  */
-    x_draw_glyphs (w, 0, row, area,
-                  0, row->used[area],
-                  row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
-                  NULL, NULL, 0);
+    x_draw_glyphs (w, 0, row, area, 0, row->used[area],
+                  DRAW_NORMAL_TEXT, 0);
   else
     {
       /* Set START_X to the window-relative start position for drawing glyphs of
   else
     {
       /* Set START_X to the window-relative start position for drawing glyphs of
@@ -5744,16 +5952,16 @@ expose_area (w, row, r, area)
        x_draw_glyphs (w, first_x - start_x, row, area,
                       first - row->glyphs[area],
                       last - row->glyphs[area],
        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
     }
 }
       
 
 /* 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;
 expose_line (w, row, r)
      struct window *w;
      struct glyph_row *row;
@@ -5763,8 +5971,7 @@ expose_line (w, row, r)
   
   if (row->mode_line_p || w->pseudo_window_p)
     x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
   
   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])
   else
     {
       if (row->used[LEFT_MARGIN_AREA])
@@ -5775,6 +5982,8 @@ expose_line (w, row, r)
        expose_area (w, row, r, RIGHT_MARGIN_AREA);
       x_draw_row_bitmaps (w, row);
     }
        expose_area (w, row, r, RIGHT_MARGIN_AREA);
       x_draw_row_bitmaps (w, row);
     }
+
+  return row->mouse_face_p;
 }
 
 
 }
 
 
@@ -5802,80 +6011,108 @@ x_phys_cursor_in_rect_p (w, r)
 }
 
 
 }
 
 
-/* Redraw a rectangle of window W.  R is a rectangle in window
-   relative coordinates.  Call this function with input blocked.  */
+/* Redraw the part of window W intersection rectangle FR.  Pixel
+   coordinates in FR are frame-relative.  Call this function with
+   input blocked.  Value is non-zero if the exposure overwrites
+   mouse-face.  */
 
 
-static void
-expose_window (w, r)
+static int
+expose_window (w, fr)
      struct window *w;
      struct window *w;
-     XRectangle *r;
+     XRectangle *fr;
 {
 {
-  struct glyph_row *row;
-  int y;
-  int yb = window_text_bottom_y (w);
-  int cursor_cleared_p;
+  struct frame *f = XFRAME (w->frame);
+  XRectangle 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 window is not yet fully initialized, do nothing.  This can
      happen when toolkit scroll bars are used and a window is split.
      Reconfiguring the scroll bar will generate an expose for a newly
      created window.  */
-  if (w->current_matrix == NULL || w == updated_window)
-    return;
-
-  TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
-         r->x, r->y, r->width, r->height));
-
-  /* Convert to window coordinates.  */
-  r->x = FRAME_TO_WINDOW_PIXEL_X (w, r->x);
-  r->y = FRAME_TO_WINDOW_PIXEL_Y (w, r->y);
+  if (w->current_matrix == NULL)
+    return 0;
 
 
-  /* Turn off the cursor.  */
-  if (!w->pseudo_window_p
-      && x_phys_cursor_in_rect_p (w, r))
+  /* When we're currently updating the window, display and current
+     matrix usually don't agree.  Arrange for a thorough display
+     later.  */
+  if (w == updated_window)
     {
     {
-      x_clear_cursor (w);
-      cursor_cleared_p = 1;
+      SET_FRAME_GARBAGED (f);
+      return 0;
     }
     }
-  else
-    cursor_cleared_p = 0;
 
 
-  /* Find the first row intersecting the rectangle R.  */
-  row = w->current_matrix->rows;
-  y = 0;
-  while (row->enabled_p
-        && y < yb
-        && y + row->height < r->y)
-    {
-      y += row->height;
-      ++row;
-    }
-       
-  /* Display the text in the rectangle, one text line at a time.  */
-  while (row->enabled_p
-        && y < yb
-        && y < r->y + r->height)
+  /* Frame-relative pixel rectangle of W.  */
+  wr.x = XFASTINT (w->left) * CANON_X_UNIT (f);
+  wr.y = XFASTINT (w->top) * CANON_Y_UNIT (f);
+  wr.width = XFASTINT (w->width) * CANON_X_UNIT (f);
+  wr.height = XFASTINT (w->height) * CANON_Y_UNIT (f);
+
+  if (x_intersect_rectangles (fr, &wr, &r))
     {
     {
-      expose_line (w, row, r);
-      y += row->height;
-      ++row;
-    }
+      int yb = window_text_bottom_y (w);
+      struct glyph_row *row;
+      int cursor_cleared_p;
+  
+      TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
+             r.x, r.y, r.width, r.height));
 
 
-  /* 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->y + r->height)
-    expose_line (w, row, r);
+      /* Convert to window coordinates.  */
+      r.x = FRAME_TO_WINDOW_PIXEL_X (w, r.x);
+      r.y = FRAME_TO_WINDOW_PIXEL_Y (w, r.y);
 
 
-  if (!w->pseudo_window_p)
-    {
-      /* Draw border between windows.  */
-      x_draw_vertical_border (w);
+      /* Turn off the cursor.  */
+      if (!w->pseudo_window_p
+         && x_phys_cursor_in_rect_p (w, &r))
+       {
+         x_clear_cursor (w);
+         cursor_cleared_p = 1;
+       }
+      else
+       cursor_cleared_p = 0;
+
+      /* Find the first row intersecting the rectangle R.  */
+      for (row = w->current_matrix->rows;
+          row->enabled_p;
+          ++row)
+       {
+         int y0 = row->y;
+         int y1 = MATRIX_ROW_BOTTOM_Y (row);
+         
+         if ((y0 >= r.y && y0 < r.y + r.height)
+             || (y1 > r.y && y1 < r.y + r.height)
+             || (r.y >= y0 && r.y < y1)
+             || (r.y + r.height > y0 && r.y + r.height < y1))
+           {
+             if (expose_line (w, row, &r))
+               mouse_face_overwritten_p = 1;
+           }
+             
+         if (y1 >= yb)
+           break;
+       }
+
+      /* Display the mode line if there is one.  */
+      if (WINDOW_WANTS_MODELINE_P (w)
+         && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
+             row->enabled_p)
+         && row->y < r.y + r.height)
+       {
+         if (expose_line (w, row, &r))
+           mouse_face_overwritten_p = 1;
+       }
+
+      if (!w->pseudo_window_p)
+       {
+         /* Draw border between windows.  */
+         x_draw_vertical_border (w);
       
       
-      /* Turn the cursor on again.  */
-      if (cursor_cleared_p)
-       x_update_window_cursor (w, 1);
+         /* Turn the cursor on again.  */
+         if (cursor_cleared_p)
+           x_update_window_cursor (w, 1);
+       }
     }
     }
+
+  return mouse_face_overwritten_p;
 }
 
 
 }
 
 
@@ -6394,10 +6631,11 @@ note_mouse_movement (frame, event)
    date.  */
 
 static struct glyph *
    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;
      struct window *w;
      int x, y;
      int *hpos, *vpos, *area;
+     int buffer_only_p;
 {
   struct glyph *glyph, *end;
   struct glyph_row *row = NULL;
 {
   struct glyph *glyph, *end;
   struct glyph_row *row = NULL;
@@ -6455,7 +6693,7 @@ x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
        {
          if (w->pseudo_window_p)
            break;
        {
          if (w->pseudo_window_p)
            break;
-         else if (BUFFERP (glyph->object))
+         else if (!buffer_only_p || BUFFERP (glyph->object))
            break;
        }
       
            break;
        }
       
@@ -6587,6 +6825,8 @@ note_mouse_highlight (f, x, y)
   int portion;
   Lisp_Object window;
   struct window *w;
   int portion;
   Lisp_Object window;
   struct window *w;
+  Cursor cursor = None;
+  struct buffer *b;
 
   /* When a menu is active, don't highlight because this looks odd.  */
 #ifdef USE_X_TOOLKIT
 
   /* When a menu is active, don't highlight because this looks odd.  */
 #ifdef USE_X_TOOLKIT
@@ -6634,231 +6874,372 @@ note_mouse_highlight (f, x, y)
       return;
     }
 
       return;
     }
 
+  /* Mouse is on the mode or header line?  */
   if (portion == 1 || portion == 3)
     {
   if (portion == 1 || portion == 3)
     {
-      /* Mouse is on the mode or top line.  */
       note_mode_line_highlight (w, x, portion == 1);
       return;
     }
       note_mode_line_highlight (w, x, portion == 1);
       return;
     }
-  else if (portion == 2)
-    XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                  f->output_data.x->horizontal_drag_cursor);
+  
+  if (portion == 2)
+    cursor = f->output_data.x->horizontal_drag_cursor;
   else
   else
-    XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                  f->output_data.x->text_cursor);
+    cursor = f->output_data.x->text_cursor;
 
   /* Are we in a window whose display is up to date?
      And verify the buffer's text has not changed.  */
 
   /* 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)
   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;
     {
       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.  */
 
       /* 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
          || area != TEXT_AREA
          || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
        {
 
       /* Clear mouse face if X/Y not over text.  */
       if (glyph == NULL
          || area != TEXT_AREA
          || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
        {
-         clear_mouse_face (dpyinfo);
-         return;
+         if (clear_mouse_face (dpyinfo))
+           cursor = None;
+         goto set_cursor;
        }
 
       pos = glyph->charpos;
        }
 
       pos = glyph->charpos;
-      xassert (w->pseudo_window_p || BUFFERP (glyph->object));
-
-      /* Check for mouse-face and help-echo.  */
-      {
-       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)
-         {
-           len = noverlays;
-           overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
-           noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
-         }
+      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);
-
-       /* 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)))
-         {
-           /* Clear the display of the old active region, if any.  */
-           clear_mouse_face (dpyinfo);
+         /* 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));
+
+      if (same_region)
+       cursor = None;
+
+      /* 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 only 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;
 
 
-           /* 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;
-                 }
-             }
+         /* Clear the display of the old active region, if any.  */
+         if (clear_mouse_face (dpyinfo))
+           cursor = None;
 
 
-           /* If no overlay applies, get a text property.  */
-           if (NILP (overlay))
-             mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
+         /* 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);
-               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;
+         /* Handle the overlay case.  */
+         if (!NILP (overlay))
+           {
+             /* Find the range of text around this char that
+                should be active.  */
+             Lisp_Object before, after;
+             int ignore;
+
+             before = Foverlay_start (overlay);
+             after = Foverlay_end (overlay);
+             /* Record this as the current active region.  */
+             fast_find_position (w, XFASTINT (before),
+                                 &dpyinfo->mouse_face_beg_col,
+                                 &dpyinfo->mouse_face_beg_row,
+                                 &dpyinfo->mouse_face_beg_x,
+                                 &dpyinfo->mouse_face_beg_y, Qnil);
+                      
+             dpyinfo->mouse_face_past_end
+               = !fast_find_position (w, XFASTINT (after),
+                                      &dpyinfo->mouse_face_end_col,
+                                      &dpyinfo->mouse_face_end_row,
+                                      &dpyinfo->mouse_face_end_x,
+                                      &dpyinfo->mouse_face_end_y, Qnil);
+             dpyinfo->mouse_face_window = window;
+             dpyinfo->mouse_face_face_id
+               = face_at_buffer_position (w, pos, 0, 0,
+                                          &ignore, pos + 1, 1);
+
+             /* Display it as active.  */
+             show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
+             cursor = None;
+           }
+         /* Handle the text property case.  */
+         else if (!NILP (mouse_face) && BUFFERP (object))
+           {
+             /* Find the range of text around this char that
+                should be active.  */
+             Lisp_Object before, after, beginning, end;
+             int ignore;
+
+             beginning = Fmarker_position (w->start);
+             end = make_number (BUF_Z (XBUFFER (object))
+                                - XFASTINT (w->window_end_pos));
+             before
+               = Fprevious_single_property_change (make_number (pos + 1),
+                                                   Qmouse_face,
+                                                   object, beginning);
+             after
+               = Fnext_single_property_change (position, Qmouse_face,
+                                               object, end);
+               
+             /* Record this as the current active region.  */
+             fast_find_position (w, XFASTINT (before),
+                                 &dpyinfo->mouse_face_beg_col,
+                                 &dpyinfo->mouse_face_beg_row,
+                                 &dpyinfo->mouse_face_beg_x,
+                                 &dpyinfo->mouse_face_beg_y, Qnil);
+             dpyinfo->mouse_face_past_end
+               = !fast_find_position (w, XFASTINT (after),
+                                      &dpyinfo->mouse_face_end_col,
+                                      &dpyinfo->mouse_face_end_row,
+                                      &dpyinfo->mouse_face_end_x,
+                                      &dpyinfo->mouse_face_end_y, Qnil);
+             dpyinfo->mouse_face_window = window;
+
+             if (BUFFERP (object))
                dpyinfo->mouse_face_face_id
                  = face_at_buffer_position (w, pos, 0, 0,
                                             &ignore, pos + 1, 1);
 
                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),
+             /* Display it as active.  */
+             show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
+             cursor = None;
+           }
+         else if (!NILP (mouse_face) && STRINGP (object))
+           {
+             Lisp_Object b, e;
+             int ignore;
+               
+             b = Fprevious_single_property_change (make_number (pos + 1),
+                                                   Qmouse_face,
+                                                   object, Qnil);
+             e = Fnext_single_property_change (position, Qmouse_face,
+                                               object, Qnil);
+             if (NILP (b))
+               b = make_number (0);
+             if (NILP (e))
+               e = make_number (XSTRING (object)->size - 1);
+             fast_find_string_pos (w, XINT (b), object,
                                    &dpyinfo->mouse_face_beg_col,
                                    &dpyinfo->mouse_face_beg_row,
                                    &dpyinfo->mouse_face_beg_x,
                                    &dpyinfo->mouse_face_beg_col,
                                    &dpyinfo->mouse_face_beg_row,
                                    &dpyinfo->mouse_face_beg_x,
-                                   &dpyinfo->mouse_face_beg_y);
-               dpyinfo->mouse_face_past_end
-                 = !fast_find_position (w, XFASTINT (after),
-                                        &dpyinfo->mouse_face_end_col,
-                                        &dpyinfo->mouse_face_end_row,
-                                        &dpyinfo->mouse_face_end_x,
-                                        &dpyinfo->mouse_face_end_y);
-               dpyinfo->mouse_face_window = window;
-               dpyinfo->mouse_face_face_id
-                 = face_at_buffer_position (w, pos, 0, 0,
-                                            &ignore, pos + 1, 1);
-
-               /* Display it as active.  */
-               show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
-             }
-         }
-
-       /* Look for a `help-echo' property.  */
-       {
-         Lisp_Object help, overlay;
-
-         /* Check overlays first.  */
-         help = overlay = Qnil;
-         for (i = noverlays - 1; i >= 0 && NILP (help); --i)
-           {
-             overlay = overlay_vec[i];
-             help = Foverlay_get (overlay, Qhelp_echo);
-           }
-
-         if (!NILP (help))
-           {
-             help_echo = help;
-             help_echo_window = window;
-             help_echo_object = overlay;
-             help_echo_pos = pos;
+                                   &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);
+             cursor = None;
            }
            }
-         else
+         else if (STRINGP (object) && NILP (mouse_face))
            {
            {
-             /* 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))
+             /* 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))
                {
                {
-                 help_echo = help;
-                 help_echo_window = window;
-                 help_echo_object = glyph->object;
-                 help_echo_pos = glyph->charpos;
+                 Lisp_Object before = Foverlay_start (overlay);
+                 Lisp_Object after = Foverlay_end (overlay);
+                 Lisp_Object ignore;
+
+                 /* Note that we might not be able to find position
+                    BEFORE in the glyph matrix if the overlay is
+                    entirely covered by a `display' property.  In
+                    this case, we overshoot.  So let's stop in
+                    the glyph matrix before glyphs for OBJECT.  */
+                 fast_find_position (w, XFASTINT (before),
+                                     &dpyinfo->mouse_face_beg_col,
+                                     &dpyinfo->mouse_face_beg_row,
+                                     &dpyinfo->mouse_face_beg_x,
+                                     &dpyinfo->mouse_face_beg_y,
+                                     object);
+                      
+                 dpyinfo->mouse_face_past_end
+                   = !fast_find_position (w, XFASTINT (after),
+                                          &dpyinfo->mouse_face_end_col,
+                                          &dpyinfo->mouse_face_end_row,
+                                          &dpyinfo->mouse_face_end_x,
+                                          &dpyinfo->mouse_face_end_y,
+                                          Qnil);
+                 dpyinfo->mouse_face_window = window;
+                 dpyinfo->mouse_face_face_id
+                   = face_at_buffer_position (w, pos, 0, 0,
+                                              &ignore, pos + 1, 1);
+
+                 /* Display it as active.  */
+                 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
+                 cursor = None;
                }
            }
        }
                }
            }
        }
-         
-       BEGV = obegv;
-       ZV = ozv;
-       current_buffer = obuf;
+
+    check_help_echo:
+
+      /* Look for a `help-echo' property.  */
+      {
+       Lisp_Object help, overlay;
+
+       /* Check overlays first.  */
+       help = overlay = Qnil;
+       for (i = noverlays - 1; i >= 0 && NILP (help); --i)
+         {
+           overlay = overlay_vec[i];
+           help = Foverlay_get (overlay, Qhelp_echo);
+         }
+
+       if (!NILP (help))
+         {
+           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;
+             
+           /* Try text properties.  */
+           if (STRINGP (object)
+               && charpos >= 0
+               && charpos < XSTRING (object)->size)
+             {
+               help = Fget_text_property (make_number (charpos),
+                                          Qhelp_echo, object);
+               if (NILP (help))
+                 {
+                   /* If the string itself doesn't specify a help-echo,
+                      see if the buffer text ``under'' it does.  */
+                   struct glyph_row *r
+                     = MATRIX_ROW (w->current_matrix, vpos);
+                   int start = MATRIX_ROW_START_CHARPOS (r);
+                   int pos = string_buffer_position (w, object, start);
+                   if (pos > 0)
+                     {
+                       help = Fget_char_property (make_number (pos),
+                                                  Qhelp_echo, w->buffer);
+                       if (!NILP (help))
+                         {
+                           charpos = pos;
+                           object = w->buffer;
+                         }
+                     }
+                 }
+             }
+           else if (BUFFERP (object)
+                    && charpos >= BEGV
+                    && charpos < ZV)
+             help = Fget_text_property (make_number (charpos), Qhelp_echo,
+                                        object);
+           
+           if (!NILP (help))
+             {
+               help_echo = help;
+               help_echo_window = window;
+               help_echo_object = object;
+               help_echo_pos = charpos;
+             }
+         }
       }
       }
+         
+      BEGV = obegv;
+      ZV = ozv;
+      current_buffer = obuf;
     }
     }
+
+ set_cursor:
+  
+  if (cursor != None)
+    XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
 }
 
 static void
 }
 
 static void
@@ -6908,7 +7289,7 @@ x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
   int area;
 
   /* Find the glyph under X/Y.  */
   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;
 
   if (*glyph == NULL)
     return -1;
 
@@ -7012,7 +7393,7 @@ note_tool_bar_highlight (f, x, y)
   int i;
   Lisp_Object enabled_p;
   int prop_idx;
   int i;
   Lisp_Object enabled_p;
   int prop_idx;
-  enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
+  enum draw_glyphs_face draw;
   int mouse_down_p, rc;
 
   /* Function note_mouse_highlight is called with negative x(y
   int mouse_down_p, rc;
 
   /* Function note_mouse_highlight is called with negative x(y
@@ -7031,7 +7412,6 @@ note_tool_bar_highlight (f, x, y)
       return;
     }
   else if (rc == 0)
       return;
     }
   else if (rc == 0)
-    /* On same tool-bar item as before.  */
     goto set_help_echo;
 
   clear_mouse_face (dpyinfo);
     goto set_help_echo;
 
   clear_mouse_face (dpyinfo);
@@ -7089,28 +7469,101 @@ note_tool_bar_highlight (f, x, y)
 
 
 \f
 
 
 \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
 
 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 charpos;
+     int *hpos, *vpos, *x, *y;
+     Lisp_Object stop;
+{
+  struct glyph_row *row, *first;
+  struct glyph *glyph, *end;
+  int i, past_end = 0;
+
+  first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+  row = row_containing_pos (w, charpos, first, NULL, 0);
+  if (row == NULL)
+    {
+      if (charpos < MATRIX_ROW_START_CHARPOS (first))
+       {
+         *x = *y = *hpos = *vpos = 0;
+         return 0;
+       }
+      else
+       {
+         row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
+         past_end = 1;
+       }
+    }
+
+  *x = row->x;
+  *y = row->y;
+  *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
+  
+  glyph = row->glyphs[TEXT_AREA];
+  end = glyph + row->used[TEXT_AREA];
+  
+  /* Skip over glyphs not having an object at the start of the row.
+     These are special glyphs like truncation marks on terminal
+     frames.  */
+  if (row->displays_text_p)
+    while (glyph < end
+          && INTEGERP (glyph->object)
+          && !EQ (stop, glyph->object)
+          && glyph->charpos < 0)
+      {
+       *x += glyph->pixel_width;
+       ++glyph;
+      }
+
+  while (glyph < end
+        && !INTEGERP (glyph->object)
+        && !EQ (stop, glyph->object)
+        && (!BUFFERP (glyph->object)
+            || glyph->charpos < charpos))
+    {
+      *x += glyph->pixel_width;
+      ++glyph;
+    }
+
+  *hpos = glyph - row->glyphs[TEXT_AREA];
+  return past_end;
+}
+
+#else /* not 0 */
+
+static int
+fast_find_position (w, pos, hpos, vpos, x, y, stop)
      struct window *w;
      int pos;
      int *hpos, *vpos, *x, *y;
      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);
 {
   int i;
   int lastcol;
   int maybe_next_line_p = 0;
   int line_start_position;
   int yb = window_text_bottom_y (w);
-  struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
-  struct glyph_row *best_row = row;
-  int row_vpos = 0, best_row_vpos = 0;
+  struct glyph_row *row, *best_row;
+  int row_vpos, best_row_vpos;
   int current_x;
 
   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])
   while (row->y < yb)
     {
       if (row->used[TEXT_AREA])
@@ -7147,22 +7600,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;
   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;
        break;
-      else if (charpos > 0)
-       lastcol = i;
 
 
+      if (charpos > 0)
+       lastcol = i;
       current_x += glyph->pixel_width;
     }
 
       current_x += glyph->pixel_width;
     }
 
@@ -7177,11 +7634,95 @@ fast_find_position (w, pos, hpos, vpos, x, y)
       current_x = best_row->x;
     }
 
       current_x = best_row->x;
     }
 
-  *vpos = best_row_vpos;
-  *hpos = lastcol + 1;
-  *x = current_x;
-  *y = best_row->y;
-  return 0;
+  *vpos = best_row_vpos;
+  *hpos = lastcol + 1;
+  *x = current_x;
+  *y = best_row->y;
+  return 0;
+}
+
+#endif /* not 0 */
+
+
+/* Find the position of the 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;
 }
 
 
 }
 
 
@@ -7195,82 +7736,58 @@ show_mouse_face (dpyinfo, draw)
 {
   struct window *w = XWINDOW (dpyinfo->mouse_face_window);
   struct frame *f = XFRAME (WINDOW_FRAME (w));
 {
   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
+      /* 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);
-
-      /* Don't do anything if row doesn't have valid contents.  */
-      if (!row->enabled_p)
-       continue;
+      int phys_cursor_on_p = w->phys_cursor_on_p;
+      struct glyph_row *row, *first, *last;
 
 
-      /* For all but the first row, the highlight starts at column 0.  */
-      if (i == dpyinfo->mouse_face_beg_row)
-       {
-         start_hpos = dpyinfo->mouse_face_beg_col;
-         start_x = dpyinfo->mouse_face_beg_x;
-       }
-      else
+      first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
+      last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
+      
+      for (row = first; row <= last && row->enabled_p; ++row)
        {
        {
-         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_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:
-  
   /* Change the mouse cursor.  */
   if (draw == DRAW_NORMAL_TEXT)
     XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
   /* Change the mouse cursor.  */
   if (draw == DRAW_NORMAL_TEXT)
     XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
@@ -7284,21 +7801,26 @@ show_mouse_face (dpyinfo, draw)
 }
 
 /* Clear out the mouse-highlighted active region.
 }
 
 /* Clear out the mouse-highlighted active region.
-   Redraw it un-highlighted first.  */
+   Redraw it un-highlighted first.  Value is non-zero if mouse
+   face was actually drawn unhighlighted.  */
 
 
-void
+static int
 clear_mouse_face (dpyinfo)
      struct x_display_info *dpyinfo;
 {
 clear_mouse_face (dpyinfo)
      struct x_display_info *dpyinfo;
 {
-  if (!NILP (tip_frame))
-    return;
+  int cleared = 0;
   
   
-  if (! NILP (dpyinfo->mouse_face_window))
-    show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
+  if (!NILP (dpyinfo->mouse_face_window))
+    {
+      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_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;
 }
 
 
 }
 
 
@@ -7339,23 +7861,70 @@ cancel_mouse_face (f)
       dpyinfo->mouse_face_window = Qnil;
     }
 }
       dpyinfo->mouse_face_window = Qnil;
     }
 }
+
 \f
 \f
-static struct scroll_bar *x_window_to_scroll_bar ();
-static void x_scroll_bar_report_motion ();
+static int glyph_rect P_ ((struct frame *f, int, int, XRectangle *));
+
+
+/* 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;
+     XRectangle *rect;
+{
+  Lisp_Object window;
+  int part, found = 0;
+
+  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 (; !found && r < end && r->enabled_p; ++r)
+       if (r->y >= y)
+         {
+           struct glyph *g = r->glyphs[TEXT_AREA];
+           struct glyph *end = g + r->used[TEXT_AREA];
+           int gx;
+             
+           for (gx = r->x; !found && g < end; gx += g->pixel_width, ++g)
+             if (gx >= x)
+               {
+                 rect->width = g->pixel_width;
+                 rect->height = r->height;
+                 rect->x = WINDOW_TO_FRAME_PIXEL_X (w, gx);
+                 rect->y = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
+                 found = 1;
+               }
+         }
+    }
+
+  return found;
+}
+
 
 /* Return the current position of the mouse.
 
 /* Return the current position of the mouse.
-   *fp should be a frame which indicates which display to ask about.
+   *FP should be a frame which indicates which display to ask about.
 
 
-   If the mouse movement started in a scroll bar, set *fp, *bar_window,
-   and *part to the frame, window, and scroll bar part that the mouse
-   is over.  Set *x and *y to the portion and whole of the mouse's
+   If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
+   and *PART to the frame, window, and scroll bar part that the mouse
+   is over.  Set *X and *Y to the portion and whole of the mouse's
    position on the scroll bar.
 
    position on the scroll bar.
 
-   If the mouse movement started elsewhere, set *fp to the frame the
-   mouse is on, *bar_window to nil, and *x and *y to the character cell
+   If the mouse movement started elsewhere, set *FP to the frame the
+   mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
    the mouse is over.
 
    the mouse is over.
 
-   Set *time to the server time-stamp for the time at which the mouse
+   Set *TIME to the server time-stamp for the time at which the mouse
    was at this position.
 
    Don't store anything if we don't have a valid set of values to report.
    was at this position.
 
    Don't store anything if we don't have a valid set of values to report.
@@ -7527,32 +8096,32 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
               on it, i.e. into the same rectangles that matrices on
               the frame are divided into.  */
 
               on it, i.e. into the same rectangles that matrices on
               the frame are divided into.  */
 
-#if OLD_REDISPLAY_CODE
-           int ignore1, ignore2;
-           pixel_to_glyph_coords (f1, win_x, win_y, &ignore1, &ignore2,
-                                  &last_mouse_glyph,
-                                  FRAME_X_DISPLAY_INFO (f1)->grabbed
-                                  || insist);
-#else
-           {
-             int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
-             int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
-             int x = win_x;
-             int y = win_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;
+           int width, height, gx, gy;
+           XRectangle rect;
+           
+           if (glyph_rect (f1, win_x, win_y, &rect))
+             last_mouse_glyph = rect;
+           else
+             {
+               width = FRAME_SMALLEST_CHAR_WIDTH (f1);
+               height = FRAME_SMALLEST_FONT_HEIGHT (f1);
+               gx = win_x;
+               gy = win_y;
              
              
-             last_mouse_glyph.width  = width;
-             last_mouse_glyph.height = height;
-             last_mouse_glyph.x = (x + width - 1) / width * width;
-             last_mouse_glyph.y = (y + height - 1) / height * height;
-           }
-#endif
+               /* 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;
+               gx = (gx + width - 1) / width * width;
+               gy = (gy + height - 1) / height * height;
+           
+               last_mouse_glyph.width  = width;
+               last_mouse_glyph.height = height;
+               last_mouse_glyph.x = gx;
+               last_mouse_glyph.y = gy;
+             }
 
            *bar_window = Qnil;
            *part = 0;
 
            *bar_window = Qnil;
            *part = 0;
@@ -7632,6 +8201,33 @@ x_window_to_scroll_bar (window_id)
 }
 
 
 }
 
 
+#if defined USE_LUCID
+
+/* Return the Lucid menu bar WINDOW is part of.  Return null
+   if WINDOW is not part of a menu bar.  */
+
+static Widget
+x_window_to_menu_bar (window)
+     Window window;
+{
+  Lisp_Object tail;
+  
+  for (tail = Vframe_list;
+       XGCTYPE (tail) == Lisp_Cons;
+       tail = XCDR (tail))
+    {
+      Lisp_Object frame = XCAR (tail);
+      Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
+      
+      if (menu_bar && xlwmenu_window_p (menu_bar, window))
+       return menu_bar;
+    }
+
+  return NULL;
+}
+
+#endif /* USE_LUCID */
+
 \f
 /************************************************************************
                         Toolkit scroll bars
 \f
 /************************************************************************
                         Toolkit scroll bars
@@ -7837,7 +8433,6 @@ xm_scroll_callback (widget, client_data, call_data)
 {
   struct scroll_bar *bar = (struct scroll_bar *) client_data;
   XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
 {
   struct scroll_bar *bar = (struct scroll_bar *) client_data;
   XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
-  double percent;
   int part = -1, whole = 0, portion = 0;
 
   switch (cs->reason)
   int part = -1, whole = 0, portion = 0;
 
   switch (cs->reason)
@@ -7884,10 +8479,10 @@ xm_scroll_callback (widget, client_data, call_data)
        UNBLOCK_INPUT;
 
        /* At the max position of the scroll bar, do a line-wise
        UNBLOCK_INPUT;
 
        /* At the max position of the scroll bar, do a line-wise
-          movement.  Without doing anything, the LessTif scroll bar
-          calls us with the same cs->value again and again.  If we
-          want to make sure that we can reach the end of the buffer,
-          we have to do something.
+          movement.  Without doing anything, we would be called with
+          the same cs->value again and again.  If we want to make
+          sure that we can reach the end of the buffer, we have to do
+          something.
 
           Implementation note: setting bar->dragging always to
           cs->value gives a smoother movement at the max position.
 
           Implementation note: setting bar->dragging always to
           cs->value gives a smoother movement at the max position.
@@ -8029,14 +8624,6 @@ x_create_toolkit_scroll_bar (f, bar)
   BLOCK_INPUT;
 
 #ifdef USE_MOTIF
   BLOCK_INPUT;
 
 #ifdef USE_MOTIF
-  /* LessTif 0.85, problems:
-
-     1. When the mouse if over the scroll bar, the scroll bar will
-     get keyboard events.  I didn't find a way to turn this off.
-
-     2. Do we have to explicitly set the cursor to get an arrow
-     cursor (see below)?  */
-  
   /* Set resources.  Create the widget.  */
   XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
   XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
   /* Set resources.  Create the widget.  */
   XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
   XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
@@ -8097,7 +8684,6 @@ x_create_toolkit_scroll_bar (f, bar)
   XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
   /* For smoother scrolling with Xaw3d   -sm */
   /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
   XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
   /* For smoother scrolling with Xaw3d   -sm */
   /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
-  /* XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac; */
   
   pixel = f->output_data.x->scroll_bar_foreground_pixel;
   if (pixel != -1)
   
   pixel = f->output_data.x->scroll_bar_foreground_pixel;
   if (pixel != -1)
@@ -8112,7 +8698,61 @@ x_create_toolkit_scroll_bar (f, bar)
       XtSetArg (av[ac], XtNbackground, pixel);
       ++ac;
     }
       XtSetArg (av[ac], XtNbackground, pixel);
       ++ac;
     }
-  
+
+  /* Top/bottom shadow colors.  */
+
+  /* Allocate them, if necessary.  */
+  if (f->output_data.x->scroll_bar_top_shadow_pixel == -1)
+    {
+      pixel = f->output_data.x->scroll_bar_background_pixel;
+      if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
+                                 &pixel, 1.2, 0x8000))
+       pixel = -1;
+      f->output_data.x->scroll_bar_top_shadow_pixel = pixel;
+    }
+  if (f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
+    {
+      pixel = f->output_data.x->scroll_bar_background_pixel;
+      if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
+                                 &pixel, 0.6, 0x4000))
+       pixel = -1;
+      f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
+    }
+
+  /* Tell the toolkit about them.  */
+  if (f->output_data.x->scroll_bar_top_shadow_pixel == -1
+      || f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
+    /* We tried to allocate a color for the top/bottom shadow, and
+       failed, so tell Xaw3d to use dithering instead.   */
+    {
+      XtSetArg (av[ac], XtNbeNiceToColormap, True);
+      ++ac;
+    }
+  else
+    /* Tell what colors Xaw3d should use for the top/bottom shadow, to
+       be more consistent with other emacs 3d colors, and since Xaw3d is
+       not good at dealing with allocation failure.  */
+    {
+      /* This tells Xaw3d to use real colors instead of dithering for
+        the shadows.  */
+      XtSetArg (av[ac], XtNbeNiceToColormap, False);
+      ++ac;
+
+      /* Specify the colors.  */
+      pixel = f->output_data.x->scroll_bar_top_shadow_pixel;
+      if (pixel != -1)
+       {
+         XtSetArg (av[ac], "topShadowPixel", pixel);
+         ++ac;
+       }
+      pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel;
+      if (pixel != -1)
+       {
+         XtSetArg (av[ac], "bottomShadowPixel", pixel);
+         ++ac;
+       }
+    }
+
   widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
                           f->output_data.x->edit_widget, av, ac);
 
   widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
                           f->output_data.x->edit_widget, av, ac);
 
@@ -8178,9 +8818,6 @@ x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
 #ifdef USE_MOTIF
   {
     int size, value;
 #ifdef USE_MOTIF
   {
     int size, value;
-    Boolean arrow1_selected, arrow2_selected;
-    unsigned char flags;
-    XmScrollBarWidget sb;
 
     /* Slider size.  Must be in the range [1 .. MAX - MIN] where MAX
        is the scroll bar's maximum and MIN is the scroll bar's minimum
 
     /* Slider size.  Must be in the range [1 .. MAX - MIN] where MAX
        is the scroll bar's maximum and MIN is the scroll bar's minimum
@@ -8194,18 +8831,6 @@ x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
     value = min (value, XM_SB_MAX - size);
     value = max (value, XM_SB_MIN);
 
     value = min (value, XM_SB_MAX - size);
     value = max (value, XM_SB_MIN);
 
-    /* LessTif: Calling XmScrollBarSetValues after an increment or
-       decrement turns off auto-repeat LessTif-internally.  This can
-       be seen in ScrollBar.c which resets Arrow1Selected and
-       Arrow2Selected.  It also sets internal flags so that LessTif
-       believes the mouse is in the slider.  We either have to change
-       our code, or work around that by accessing private data. */
-
-    sb = (XmScrollBarWidget) widget;
-    arrow1_selected = sb->scrollBar.arrow1_selected;
-    arrow2_selected = sb->scrollBar.arrow2_selected;
-    flags = sb->scrollBar.flags;
-    
     if (NILP (bar->dragging))
       XmScrollBarSetValues (widget, value, size, 0, 0, False);
     else if (last_scroll_bar_part == scroll_bar_down_arrow)
     if (NILP (bar->dragging))
       XmScrollBarSetValues (widget, value, size, 0, 0, False);
     else if (last_scroll_bar_part == scroll_bar_down_arrow)
@@ -8225,10 +8850,6 @@ x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
                              min (size, XM_SB_RANGE - old_value),
                              0, 0, False);
       }
                              min (size, XM_SB_RANGE - old_value),
                              0, 0, False);
       }
-    
-    sb->scrollBar.arrow1_selected = arrow1_selected;
-    sb->scrollBar.arrow2_selected = arrow2_selected;
-    sb->scrollBar.flags = flags;
   }
 #else /* !USE_MOTIF i.e. use Xaw */
   {
   }
 #else /* !USE_MOTIF i.e. use Xaw */
   {
@@ -8335,9 +8956,10 @@ x_scroll_bar_create (w, top, left, width, height)
     /* Clear the area of W that will serve as a scroll bar.  This is
        for the case that a window has been split horizontally.  In
        this case, no clear_frame is generated to reduce flickering.  */
     /* Clear the area of W that will serve as a scroll bar.  This is
        for the case that a window has been split horizontally.  In
        this case, no clear_frame is generated to reduce flickering.  */
-    XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-               left, top, width,
-               window_box_height (w), False);
+    if (width > 0 && height > 0)
+      x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                   left, top, width,
+                   window_box_height (w), False);
 
     window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                            /* Position and size of scroll bar.  */
 
     window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                            /* Position and size of scroll bar.  */
@@ -8374,15 +8996,15 @@ x_scroll_bar_create (w, top, left, width, height)
 
   /* Map the window/widget.  */
 #ifdef USE_TOOLKIT_SCROLL_BARS
 
   /* Map the window/widget.  */
 #ifdef USE_TOOLKIT_SCROLL_BARS
- {
-   Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
-   XtConfigureWidget (scroll_bar,
-                    left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
-                    top,
-                    width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
-                    height, 0);
-   XtMapWidget (scroll_bar);
- }
 {
+    Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
+    XtConfigureWidget (scroll_bar,
+                      left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
+                      top,
+                      width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
+                      max (height, 1), 0);
+    XtMapWidget (scroll_bar);
   }
 #else /* not USE_TOOLKIT_SCROLL_BARS */
   XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
 #endif /* not USE_TOOLKIT_SCROLL_BARS */
 #else /* not USE_TOOLKIT_SCROLL_BARS */
   XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
 #endif /* not USE_TOOLKIT_SCROLL_BARS */
@@ -8464,13 +9086,12 @@ x_scroll_bar_set_handle (bar, start, end, rebuild)
     /* Draw the empty space above the handle.  Note that we can't clear
        zero-height areas; that means "clear to end of window."  */
     if (0 < start)
     /* Draw the empty space above the handle.  Note that we can't clear
        zero-height areas; that means "clear to end of window."  */
     if (0 < start)
-      XClearArea (FRAME_X_DISPLAY (f), w,
-
-                 /* x, y, width, height, and exposures.  */
-                 VERTICAL_SCROLL_BAR_LEFT_BORDER,
-                 VERTICAL_SCROLL_BAR_TOP_BORDER,
-                 inside_width, start,
-                 False);
+      x_clear_area (FRAME_X_DISPLAY (f), w,
+                   /* x, y, width, height, and exposures.  */
+                   VERTICAL_SCROLL_BAR_LEFT_BORDER,
+                   VERTICAL_SCROLL_BAR_TOP_BORDER,
+                   inside_width, start,
+                   False);
 
     /* Change to proper foreground color if one is specified.  */
     if (f->output_data.x->scroll_bar_foreground_pixel != -1)
 
     /* Change to proper foreground color if one is specified.  */
     if (f->output_data.x->scroll_bar_foreground_pixel != -1)
@@ -8479,7 +9100,6 @@ x_scroll_bar_set_handle (bar, start, end, rebuild)
 
     /* Draw the handle itself.  */
     XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
 
     /* Draw the handle itself.  */
     XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
-
                    /* x, y, width, height */
                    VERTICAL_SCROLL_BAR_LEFT_BORDER,
                    VERTICAL_SCROLL_BAR_TOP_BORDER + start,
                    /* x, y, width, height */
                    VERTICAL_SCROLL_BAR_LEFT_BORDER,
                    VERTICAL_SCROLL_BAR_TOP_BORDER + start,
@@ -8493,13 +9113,12 @@ x_scroll_bar_set_handle (bar, start, end, rebuild)
     /* Draw the empty space below the handle.  Note that we can't
        clear zero-height areas; that means "clear to end of window." */
     if (end < inside_height)
     /* Draw the empty space below the handle.  Note that we can't
        clear zero-height areas; that means "clear to end of window." */
     if (end < inside_height)
-      XClearArea (FRAME_X_DISPLAY (f), w,
-
-                 /* x, y, width, height, and exposures.  */
-                 VERTICAL_SCROLL_BAR_LEFT_BORDER,
-                 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
-                 inside_width, inside_height - end,
-                 False);
+      x_clear_area (FRAME_X_DISPLAY (f), w,
+                   /* x, y, width, height, and exposures.  */
+                   VERTICAL_SCROLL_BAR_LEFT_BORDER,
+                   VERTICAL_SCROLL_BAR_TOP_BORDER + end,
+                   inside_width, inside_height - end,
+                   False);
 
   }
 
 
   }
 
@@ -8583,10 +9202,14 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
   /* Does the scroll bar exist yet?  */
   if (NILP (w->vertical_scroll_bar))
     {
   /* Does the scroll bar exist yet?  */
   if (NILP (w->vertical_scroll_bar))
     {
-      BLOCK_INPUT;
-      XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                 left, top, width, height, False);
-      UNBLOCK_INPUT;
+      if (width > 0 && height > 0)
+       {
+         BLOCK_INPUT;
+         x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                       left, top, width, height, False);
+         UNBLOCK_INPUT;
+       }
+      
       bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
     }
   else
       bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
     }
   else
@@ -8611,8 +9234,9 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
 
       /* Since toolkit scroll bars are smaller than the space reserved
         for them on the frame, we have to clear "under" them.  */
 
       /* Since toolkit scroll bars are smaller than the space reserved
         for them on the frame, we have to clear "under" them.  */
-      XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                 left, top, width, height, False);
+      if (width > 0 && height > 0)
+       x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                     left, top, width, height, False);
 
       /* Move/size the scroll bar widget.  */
       if (mask)
 
       /* Move/size the scroll bar widget.  */
       if (mask)
@@ -8620,24 +9244,41 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
                           sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
                           top,
                           sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
                           sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
                           top,
                           sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
-                          height, 0);
+                          max (height, 1), 0);
 
 #else /* not USE_TOOLKIT_SCROLL_BARS */
   
 
 #else /* not USE_TOOLKIT_SCROLL_BARS */
   
+      /* Clear areas not covered by the scroll bar because of
+        VERTICAL_SCROLL_BAR_WIDTH_TRIM.  */
       if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
        {
       if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
        {
-         /* Clear areas not covered by the scroll bar.  This makes sure a
-            previous mode line display is cleared after C-x 2 C-x 1, for
-            example.  Non-toolkit scroll bars are as wide as the area
-            reserved for scroll bars - trim at both sides.  */
-         XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                     left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
-                     height, False);
-         XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                     left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
-                     top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
-                     height, False);
+         x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                       left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
+                       height, False);
+         x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                       left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
+                       top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
+                       height, False);
        }
        }
+
+      /* Clear areas not covered by the scroll bar because it's not as
+        wide as the area reserved for it .  This makes sure a
+        previous mode line display is cleared after C-x 2 C-x 1, for
+        example.  */
+      {
+       int area_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
+       int rest = area_width - sb_width;
+       if (rest > 0 && height > 0)
+         {
+           if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
+             x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                           left + area_width -  rest, top,
+                           rest, height, False);
+           else
+             x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                           left, top, rest, height, False);
+         }
+      }
       
       /* Move/size the scroll bar window.  */
       if (mask)
       
       /* Move/size the scroll bar window.  */
       if (mask)
@@ -9047,7 +9688,8 @@ x_scroll_bar_clear (f)
   if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
     for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
         bar = XSCROLL_BAR (bar)->next)
   if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
     for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
         bar = XSCROLL_BAR (bar)->next)
-      XClearArea (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
+      XClearArea (FRAME_X_DISPLAY (f),
+                 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
                  0, 0, 0, 0, True);
 #endif /* not USE_TOOLKIT_SCROLL_BARS */
 }
                  0, 0, 0, 0, True);
 #endif /* not USE_TOOLKIT_SCROLL_BARS */
 }
@@ -9540,7 +10182,8 @@ XTread_socket (sd, bufp, numchars, expected)
                               &event);
              else
                {
                               &event);
              else
                {
-                 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
+                 XSelectionRequestEvent *eventp
+                   = (XSelectionRequestEvent *) &event;
 
                  if (numchars == 0)
                    abort ();
 
                  if (numchars == 0)
                    abort ();
@@ -9562,12 +10205,16 @@ XTread_socket (sd, bufp, numchars, expected)
              break;
 
            case PropertyNotify:
              break;
 
            case PropertyNotify:
-#ifdef USE_X_TOOLKIT
+#if 0 /* This is plain wrong.  In the case that we are waiting for a
+        PropertyNotify used as an ACK in incremental selection
+        transfer, the property will be on the receiver's window.  */
+#if defined USE_X_TOOLKIT
              if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
                goto OTHER;
              if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
                goto OTHER;
-#endif /* not USE_X_TOOLKIT */
+#endif
+#endif
              x_handle_property_notify (&event.xproperty);
              x_handle_property_notify (&event.xproperty);
-             break;
+             goto OTHER;
 
            case ReparentNotify:
              f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
 
            case ReparentNotify:
              f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
@@ -9600,12 +10247,26 @@ XTread_socket (sd, bufp, numchars, expected)
                }
              else
                {
                }
              else
                {
+#ifndef USE_TOOLKIT_SCROLL_BARS
+                 struct scroll_bar *bar;
+#endif
+#if defined USE_LUCID
+                 /* Submenus of the Lucid menu bar aren't widgets
+                    themselves, so there's no way to dispatch events
+                    to them.  Recognize this case separately.  */
+                 {
+                   Widget widget
+                     = x_window_to_menu_bar (event.xexpose.window);
+                   if (widget)
+                     xlwmenu_redisplay (widget);
+                 }
+#endif /* USE_LUCID */
+
 #ifdef USE_TOOLKIT_SCROLL_BARS
                  /* Dispatch event to the widget.  */
                  goto OTHER;
 #else /* not USE_TOOLKIT_SCROLL_BARS */
 #ifdef USE_TOOLKIT_SCROLL_BARS
                  /* Dispatch event to the widget.  */
                  goto OTHER;
 #else /* not USE_TOOLKIT_SCROLL_BARS */
-                 struct scroll_bar *bar
-                   = x_window_to_scroll_bar (event.xexpose.window);
+                 bar = x_window_to_scroll_bar (event.xexpose.window);
 
                  if (bar)
                    x_scroll_bar_expose (bar, &event);
 
                  if (bar)
                    x_scroll_bar_expose (bar, &event);
@@ -9618,8 +10279,8 @@ XTread_socket (sd, bufp, numchars, expected)
              break;
 
            case GraphicsExpose:        /* This occurs when an XCopyArea's
              break;
 
            case GraphicsExpose:        /* This occurs when an XCopyArea's
-                                     source area was obscured or not
-                                     available.*/
+                                          source area was obscured or not
+                                          available.  */
              f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
              if (f)
                {
              f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
              if (f)
                {
@@ -9636,7 +10297,7 @@ XTread_socket (sd, bufp, numchars, expected)
 
            case NoExpose:              /* This occurs when an XCopyArea's
                                           source area was completely
 
            case NoExpose:              /* This occurs when an XCopyArea's
                                           source area was completely
-                                          available */
+                                          available */
              break;
 
            case UnmapNotify:
              break;
 
            case UnmapNotify:
@@ -9649,7 +10310,7 @@ XTread_socket (sd, bufp, numchars, expected)
              
              f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
              if (f)            /* F may no longer exist if
              
              f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
              if (f)            /* F may no longer exist if
-                                      the frame was deleted.  */
+                                  the frame was deleted.  */
                {
                  /* While a frame is unmapped, display generation is
                     disabled; you don't want to spend time updating a
                {
                  /* While a frame is unmapped, display generation is
                     disabled; you don't want to spend time updating a
@@ -9717,10 +10378,10 @@ XTread_socket (sd, bufp, numchars, expected)
              f = x_any_window_to_frame (dpyinfo, event.xkey.window);
 
 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
              f = x_any_window_to_frame (dpyinfo, event.xkey.window);
 
 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
-             /* I couldn't find a way to prevent LessTif scroll bars
-                from consuming key events.  */
              if (f == 0)
                {
              if (f == 0)
                {
+                 /* Scroll bars consume key events, but we want
+                    the keys to go to the scroll bar's frame.  */
                  Widget widget = XtWindowToWidget (dpyinfo->display,
                                                    event.xkey.window);
                  if (widget && XmIsScrollBar (widget))
                  Widget widget = XtWindowToWidget (dpyinfo->display,
                                                    event.xkey.window);
                  if (widget && XmIsScrollBar (widget))
@@ -9875,7 +10536,8 @@ XTread_socket (sd, bufp, numchars, expected)
                           || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
                           || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
                           /* Any "vendor-specific" key is ok.  */
                           || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
                           || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
                           /* Any "vendor-specific" key is ok.  */
-                          || (orig_keysym & (1 << 28)))
+                          || (orig_keysym & (1 << 28))
+                          || (keysym != NoSymbol && nbytes == 0))
                          && ! (IsModifierKey (orig_keysym)
 #ifndef HAVE_X11R5
 #ifdef XK_Mode_switch
                          && ! (IsModifierKey (orig_keysym)
 #ifndef HAVE_X11R5
 #ifdef XK_Mode_switch
@@ -9906,7 +10568,6 @@ XTread_socket (sd, bufp, numchars, expected)
                        {
                          register int i;
                          register int c;
                        {
                          register int i;
                          register int c;
-                         unsigned char *p, *pend;
                          int nchars, len;
 
                          for (i = 0; i < nbytes; i++)
                          int nchars, len;
 
                          for (i = 0; i < nbytes; i++)
@@ -9947,8 +10608,12 @@ XTread_socket (sd, bufp, numchars, expected)
                             character events.  */
                          for (i = 0; i < nbytes; i += len)
                            {
                             character events.  */
                          for (i = 0; i < nbytes; i += len)
                            {
-                             c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
-                                                         nbytes - i, len);
+                             if (nchars == nbytes)
+                               c = copy_bufptr[i], len = 1;
+                             else
+                               c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
+                                                           nbytes - i, len);
+                             
                              bufp->kind = (SINGLE_BYTE_CHAR_P (c)
                                            ? ascii_keystroke
                                            : multibyte_char_keystroke);
                              bufp->kind = (SINGLE_BYTE_CHAR_P (c)
                                            ? ascii_keystroke
                                            : multibyte_char_keystroke);
@@ -10002,41 +10667,9 @@ XTread_socket (sd, bufp, numchars, expected)
 
            case EnterNotify:
              {
 
            case EnterNotify:
              {
-               int from_menu_bar_p = 0;
-               
                f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
 
                f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
 
-#ifdef LESSTIF_VERSION
-               /* When clicking outside of a menu bar popup to close
-                  it, we get a FocusIn/ EnterNotify sequence of
-                  events.  The flag event.xcrossing.focus is not set
-                  in the EnterNotify event of that sequence because
-                  the focus is in the menu bar,
-                  event.xcrossing.window is the frame's X window.
-                  Unconditionally setting the focus frame to null in
-                  this case is not the right thing, because no event
-                  follows that could set the focus frame to the right
-                  value.
-
-                  This could be a LessTif bug, but I wasn't able to
-                  reproduce the behavior in a simple test program.
-
-                  (gerd, LessTif 0.88.1).  */
-               
-               if (!event.xcrossing.focus
-                   && f
-                   && f->output_data.x->menubar_widget)
-                 {
-                   Window focus;
-                   int revert;
-                   
-                   XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
-                   if (focus == XtWindow (f->output_data.x->menubar_widget))
-                     from_menu_bar_p = 1;
-                 }
-#endif /* LESSTIF_VERSION */
-
-               if (event.xcrossing.focus || from_menu_bar_p)
+               if (event.xcrossing.focus)
                  {
                    /* Avoid nasty pop/raise loops.  */
                    if (f && (!(f->auto_raise)
                  {
                    /* Avoid nasty pop/raise loops.  */
                    if (f && (!(f->auto_raise)
@@ -10052,7 +10685,7 @@ XTread_socket (sd, bufp, numchars, expected)
              
                /* EnterNotify counts as mouse movement,
                   so update things that depend on mouse position.  */
              
                /* EnterNotify counts as mouse movement,
                   so update things that depend on mouse position.  */
-               if (f && !f->output_data.x->busy_p)
+               if (f && !f->output_data.x->hourglass_p)
                  note_mouse_movement (f, &event.xmotion);
                goto OTHER;
              }
                  note_mouse_movement (f, &event.xmotion);
                goto OTHER;
              }
@@ -10089,9 +10722,6 @@ XTread_socket (sd, bufp, numchars, expected)
              f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
              if (f)
                {
              f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
              if (f)
                {
-                 Lisp_Object frame;
-                 int from_menu_bar_p = 0;
-                 
                  if (f == dpyinfo->mouse_face_mouse_frame)
                    {
                      /* If we move outside the frame, then we're
                  if (f == dpyinfo->mouse_face_mouse_frame)
                    {
                      /* If we move outside the frame, then we're
@@ -10110,26 +10740,13 @@ XTread_socket (sd, bufp, numchars, expected)
                      int n;
 
                      XSETFRAME (frame, f);
                      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;
                    }
 
                      n = gen_help_event (bufp, numchars,
                                          Qnil, frame, Qnil, Qnil, 0);
                      bufp += n, count += n, numchars -= n;
                    }
 
-#ifdef LESSTIF_VERSION
-                 /* Please see the comment at the start of the
-                     EnterNotify case.  */
-                 if (!event.xcrossing.focus
-                     && f->output_data.x->menubar_widget)
-                   {
-                     Window focus;
-                     int revert;
-                     XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
-                     if (focus == XtWindow (f->output_data.x->menubar_widget))
-                       from_menu_bar_p = 1;
-                   }
-#endif /* LESSTIF_VERSION */
-               
-                 if (event.xcrossing.focus || from_menu_bar_p)
+                 if (event.xcrossing.focus)
                    x_mouse_leave (dpyinfo);
                  else
                    {
                    x_mouse_leave (dpyinfo);
                  else
                    {
@@ -10473,21 +11090,22 @@ XTread_socket (sd, bufp, numchars, expected)
                             Text Cursor
  ***********************************************************************/
 
                             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 N 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
 
 static void
-note_overwritten_text_cursor (w, hpos, n)
+notice_overwritten_cursor (w, start_x, end_x)
      struct window *w;
      struct window *w;
-     int hpos, n;
+     int start_x, end_x;
 {
   if (updated_area == TEXT_AREA
 {
   if (updated_area == TEXT_AREA
+      && w->phys_cursor_on_p
       && output_cursor.vpos == w->phys_cursor.vpos
       && output_cursor.vpos == w->phys_cursor.vpos
-      && hpos <= w->phys_cursor.hpos
-      && (n < 0
-         || hpos + n > w->phys_cursor.hpos))
+      && start_x <= w->phys_cursor.x
+      && end_x > w->phys_cursor.x)
     w->phys_cursor_on_p = 0;
 }
 
     w->phys_cursor_on_p = 0;
 }
 
@@ -10684,9 +11302,12 @@ x_draw_phys_cursor_glyph (w, row, hl)
      glyphs and mini-buffer.  */
   if (w->phys_cursor.hpos < row->used[TEXT_AREA])
     {
      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,
       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
 
       /* When we erase the cursor, and ROW is overlapped by other
         rows, make sure that these overlapping parts of other rows
@@ -10771,22 +11392,20 @@ x_erase_phys_cursor (w)
       if (cursor_glyph == NULL)
        goto mark_cursor_off;
 
       if (cursor_glyph == NULL)
        goto mark_cursor_off;
 
-      x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
+      x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
       
       
-      XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                 x,
-                 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
-                                                  cursor_row->y)),
-                 cursor_glyph->pixel_width,
-                 cursor_row->visible_height,
-                 False);
+      x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                   x,
+                   WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
+                                                    cursor_row->y)),
+                   cursor_glyph->pixel_width,
+                   cursor_row->visible_height,
+                   False);
     }
   
   /* Erase the cursor by redrawing the character underneath it.  */
   if (mouse_face_here_p)
     hl = DRAW_MOUSE_FACE;
     }
   
   /* 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);
   else
     hl = DRAW_NORMAL_TEXT;
   x_draw_phys_cursor_glyph (w, cursor_row, hl);
@@ -10797,6 +11416,35 @@ 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 x_display_info *dpyinfo = FRAME_X_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.  */
 /* 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.  */
@@ -10854,13 +11502,15 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
     {
       if (w == XWINDOW (echo_area_window))
        new_cursor_type = FRAME_DESIRED_CURSOR (f);
     {
       if (w == XWINDOW (echo_area_window))
        new_cursor_type = FRAME_DESIRED_CURSOR (f);
-      else
+      else if (cursor_in_non_selected_windows)
        new_cursor_type = HOLLOW_BOX_CURSOR;
        new_cursor_type = HOLLOW_BOX_CURSOR;
+      else
+       new_cursor_type = NO_CURSOR;
     }
   else
     {
     }
   else
     {
-      if (w != XWINDOW (selected_window)
-         || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
+      if (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame
+         || w != XWINDOW (f->selected_window))
        {
          extern int cursor_in_non_selected_windows;
          
        {
          extern int cursor_in_non_selected_windows;
          
@@ -11020,16 +11670,6 @@ x_update_window_cursor (w, on)
 \f
 /* Icons.  */
 
 \f
 /* Icons.  */
 
-/* Refresh bitmap kitchen sink icon for frame F
-   when we get an expose event for it.  */
-
-void
-refreshicon (f)
-     struct frame *f;
-{
-  /* Normally, the window manager handles this function.  */
-}
-
 /* Make the x-window of frame F use the gnu icon bitmap.  */
 
 int
 /* Make the x-window of frame F use the gnu icon bitmap.  */
 
 int
@@ -11256,6 +11896,21 @@ x_connection_signal (signalnum)        /* If we don't have an argument, */
                          Handling X errors
  ************************************************************************/
 
                          Handling X errors
  ************************************************************************/
 
+/* Error message passed to x_connection_closed.  */
+
+static char *error_msg;
+
+/* Function installed as fatal_error_signal_hook in
+   x_connection_closed.  Print the X error message, and exit normally,
+   instead of dumping core when XtCloseDisplay fails.  */
+
+static void
+x_fatal_error_signal ()
+{
+  fprintf (stderr, "%s\n", error_msg);
+  exit (70);
+}
+
 /* Handle the loss of connection to display DPY.  ERROR_MESSAGE is
    the text of an error message that lead to the connection loss.  */
 
 /* Handle the loss of connection to display DPY.  ERROR_MESSAGE is
    the text of an error message that lead to the connection loss.  */
 
@@ -11267,10 +11922,9 @@ x_connection_closed (dpy, error_message)
   struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
   Lisp_Object frame, tail;
   int count;
   struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
   Lisp_Object frame, tail;
   int count;
-  char *msg;
   
   
-  msg = (char *) alloca (strlen (error_message) + 1);
-  strcpy (msg, error_message);
+  error_msg = (char *) alloca (strlen (error_message) + 1);
+  strcpy (error_msg, error_message);
   handling_signal = 0;
   
   /* Prevent being called recursively because of an error condition
   handling_signal = 0;
   
   /* Prevent being called recursively because of an error condition
@@ -11295,7 +11949,15 @@ x_connection_closed (dpy, error_message)
      in OpenWindows.  I don't know how to cicumvent it here.  */
   
 #ifdef USE_X_TOOLKIT
      in OpenWindows.  I don't know how to cicumvent it here.  */
   
 #ifdef USE_X_TOOLKIT
-  XtCloseDisplay (dpy);
+  /* If DPYINFO is null, this means we didn't open the display
+     in the first place, so don't try to close it.  */
+  if (dpyinfo)
+    {
+      extern void (*fatal_error_signal_hook) P_ ((void));
+      fatal_error_signal_hook = x_fatal_error_signal;
+      XtCloseDisplay (dpy);
+      fatal_error_signal_hook = NULL;
+    }
 #endif
 
   /* Indicate that this display is dead.  */
 #endif
 
   /* Indicate that this display is dead.  */
@@ -11336,7 +11998,7 @@ x_connection_closed (dpy, error_message)
   
   if (x_display_list == 0)
     {
   
   if (x_display_list == 0)
     {
-      fprintf (stderr, "%s\n", msg);
+      fprintf (stderr, "%s\n", error_msg);
       shut_down_emacs (0, 0, Qnil);
       exit (70);
     }
       shut_down_emacs (0, 0, Qnil);
       exit (70);
     }
@@ -11349,7 +12011,7 @@ x_connection_closed (dpy, error_message)
   TOTALLY_UNBLOCK_INPUT;
 
   clear_waiting_for_input ();
   TOTALLY_UNBLOCK_INPUT;
 
   clear_waiting_for_input ();
-  error ("%s", msg);
+  error ("%s", error_msg);
 }
 
 
 }
 
 
@@ -11449,7 +12111,12 @@ x_new_font (f, fontname)
                f->output_data.x->font->fid);
 
       frame_update_line_height (f);
                f->output_data.x->font->fid);
 
       frame_update_line_height (f);
-      x_set_window_size (f, 0, f->width, f->height);
+
+      /* Don't change the size of a tip frame; there's no point in
+        doing it because it's done in Fx_show_tip, and it leads to
+        problems because the tip frame has no widget.  */
+      if (NILP (tip_frame) || XFRAME (tip_frame) != f)
+       x_set_window_size (f, 0, f->width, f->height);
     }
   else
     /* If we are setting a new frame's font for the first time,
     }
   else
     /* If we are setting a new frame's font for the first time,
@@ -11571,7 +12238,7 @@ xim_open_dpy (dpyinfo, resource_name)
 #ifdef HAVE_X11R6
       destroy.callback = xim_destroy_callback;
       destroy.client_data = (XPointer)dpyinfo;
 #ifdef HAVE_X11R6
       destroy.callback = xim_destroy_callback;
       destroy.client_data = (XPointer)dpyinfo;
-      /* This isn't prptotyped in OSF 5.0.  */
+      /* This isn't prototyped in OSF 5.0.  */
       XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
 #endif
     }
       XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
 #endif
     }
@@ -11867,37 +12534,19 @@ x_set_offset (f, xoff, yoff, change_gravity)
   UNBLOCK_INPUT;
 }
 
   UNBLOCK_INPUT;
 }
 
-/* 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)
+/* Change the size of frame F's X window to COLS/ROWS in the case F
+   doesn't have a widget.  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.  */
+
+static void
+x_set_window_size_1 (f, change_gravity, cols, rows)
      struct frame *f;
      int change_gravity;
      int cols, rows;
 {
      struct frame *f;
      int change_gravity;
      int cols, rows;
 {
-#ifndef USE_X_TOOLKIT
   int pixelwidth, pixelheight;
   int pixelwidth, pixelheight;
-#endif
-
-  BLOCK_INPUT;
-
-#ifdef USE_X_TOOLKIT
-  {
-    /* The x and y position of the widget is clobbered by the
-       call to XtSetValues within EmacsFrameSetCharSize.
-       This is a real kludge, but I don't understand Xt so I can't
-       figure out a correct fix.  Can anyone else tell me? -- rms.  */
-    int xpos = f->output_data.x->widget->core.x;
-    int ypos = f->output_data.x->widget->core.y;
-    EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
-    f->output_data.x->widget->core.x = xpos;
-    f->output_data.x->widget->core.y = ypos;
-  }
-
-#else /* not USE_X_TOOLKIT */
 
   check_frame_size (f, &rows, &cols);
   f->output_data.x->vertical_scroll_bar_extra
 
   check_frame_size (f, &rows, &cols);
   f->output_data.x->vertical_scroll_bar_extra
@@ -11942,7 +12591,43 @@ x_set_window_size (f, change_gravity, cols, rows)
   SET_FRAME_GARBAGED (f);
 
   XFlush (FRAME_X_DISPLAY (f));
   SET_FRAME_GARBAGED (f);
 
   XFlush (FRAME_X_DISPLAY (f));
+}
 
 
+
+/* 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;
+     int change_gravity;
+     int cols, rows;
+{
+  BLOCK_INPUT;
+
+#ifdef USE_X_TOOLKIT
+  
+  if (f->output_data.x->widget != NULL)
+    {
+      /* The x and y position of the widget is clobbered by the
+        call to XtSetValues within EmacsFrameSetCharSize.
+        This is a real kludge, but I don't understand Xt so I can't
+        figure out a correct fix.  Can anyone else tell me? -- rms.  */
+      int xpos = f->output_data.x->widget->core.x;
+      int ypos = f->output_data.x->widget->core.y;
+      EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
+      f->output_data.x->widget->core.x = xpos;
+      f->output_data.x->widget->core.y = ypos;
+    }
+  else
+    x_set_window_size_1 (f, change_gravity, cols, rows);
+  
+#else /* not USE_X_TOOLKIT */
+  
+  x_set_window_size_1 (f, change_gravity, cols, rows);
+  
 #endif /* not USE_X_TOOLKIT */
 
   /* If cursor was outside the new size, mark it as off.  */
 #endif /* not USE_X_TOOLKIT */
 
   /* If cursor was outside the new size, mark it as off.  */
@@ -12454,7 +13139,10 @@ x_free_frame_resources (f)
       
 #ifdef USE_X_TOOLKIT
       if (f->output_data.x->widget)
       
 #ifdef USE_X_TOOLKIT
       if (f->output_data.x->widget)
-       XtDestroyWidget (f->output_data.x->widget);
+       {
+         XtDestroyWidget (f->output_data.x->widget);
+         f->output_data.x->widget = NULL;
+       }
       free_frame_menubar (f);
 #endif /* USE_X_TOOLKIT */
 
       free_frame_menubar (f);
 #endif /* USE_X_TOOLKIT */
 
@@ -12469,6 +13157,13 @@ x_free_frame_resources (f)
        unload_color (f, f->output_data.x->scroll_bar_background_pixel);
       if (f->output_data.x->scroll_bar_foreground_pixel != -1)
        unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
        unload_color (f, f->output_data.x->scroll_bar_background_pixel);
       if (f->output_data.x->scroll_bar_foreground_pixel != -1)
        unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
+#ifdef USE_TOOLKIT_SCROLL_BARS
+      /* Scrollbar shadow colors.  */
+      if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
+       unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
+      if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
+       unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
+#endif /* USE_TOOLKIT_SCROLL_BARS */
       if (f->output_data.x->white_relief.allocated_p)
        unload_color (f, f->output_data.x->white_relief.pixel);
       if (f->output_data.x->black_relief.allocated_p)
       if (f->output_data.x->white_relief.allocated_p)
        unload_color (f, f->output_data.x->white_relief.pixel);
       if (f->output_data.x->black_relief.allocated_p)
@@ -12781,24 +13476,38 @@ x_get_font_info (f, font_idx)
 }
 
 
 }
 
 
-/* Return a list of names of available fonts matching PATTERN on frame
-   F.  If SIZE is not 0, it is the size (maximum bound width) of fonts
-   to be listed.  Frame F NULL means we have not yet created any
-   frame on X, and consult the first display in x_display_list.
-   MAXNAMES sets a limit on how many fonts to match.  */
+/* Return a list of names of available fonts matching PATTERN on frame F.
+
+   If SIZE is > 0, it is the size (maximum bounds width) of fonts
+   to be listed.
+
+   SIZE < 0 means include scalable fonts.
+
+   Frame F null means we have not yet created any frame on X, and
+   consult the first display in x_display_list.  MAXNAMES sets a limit
+   on how many fonts to match.  */
 
 Lisp_Object
 x_list_fonts (f, pattern, size, maxnames)
 
 Lisp_Object
 x_list_fonts (f, pattern, size, maxnames)
-     FRAME_PTR f;
+     struct frame *f;
      Lisp_Object pattern;
      int size;
      int maxnames;
 {
   Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
   Lisp_Object tem, second_best;
      Lisp_Object pattern;
      int size;
      int maxnames;
 {
   Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
   Lisp_Object tem, second_best;
-  Display *dpy = f != NULL ? FRAME_X_DISPLAY (f) : x_display_list->display;
+  struct x_display_info *dpyinfo
+    = f ? FRAME_X_DISPLAY_INFO (f) : x_display_list;
+  Display *dpy = dpyinfo->display;
   int try_XLoadQueryFont = 0;
   int count;
   int try_XLoadQueryFont = 0;
   int count;
+  int allow_scalable_fonts_p = 0;
+
+  if (size < 0)
+    {
+      allow_scalable_fonts_p = 1;
+      size = 0;
+    }
 
   patterns = Fassoc (pattern, Valternate_fontname_alist);
   if (NILP (patterns))
 
   patterns = Fassoc (pattern, Valternate_fontname_alist);
   if (NILP (patterns))
@@ -12816,11 +13525,12 @@ x_list_fonts (f, pattern, size, maxnames)
       pattern = XCAR (patterns);
       /* See if we cached the result for this particular query.
          The cache is an alist of the form:
       pattern = XCAR (patterns);
       /* See if we cached the result for this particular query.
          The cache is an alist of the form:
-          (((PATTERN . MAXNAMES) (FONTNAME . WIDTH) ...) ...)
-      */
-      if (f && (tem = XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element),
-               key = Fcons (pattern, make_number (maxnames)),
-               !NILP (list = Fassoc (key, tem))))
+        ((((PATTERN . MAXNAMES) . SCALABLE) (FONTNAME . WIDTH) ...) ...)  */
+      tem = XCDR (dpyinfo->name_list_element);
+      key = Fcons (Fcons (pattern, make_number (maxnames)),
+                  allow_scalable_fonts_p ? Qt : Qnil);
+      list = Fassoc (key, tem);
+      if (!NILP (list))
        {
          list = Fcdr_safe (list);
          /* We have a cashed list.  Don't have to get the list again.  */
        {
          list = Fcdr_safe (list);
          /* We have a cashed list.  Don't have to get the list again.  */
@@ -12907,10 +13617,10 @@ x_list_fonts (f, pattern, size, maxnames)
              int average_width = -1, dashes = 0;
              
              /* Count the number of dashes in NAMES[I].  If there are
              int average_width = -1, dashes = 0;
              
              /* Count the number of dashes in NAMES[I].  If there are
-               14 dashes, and the field value following 12th dash
-               (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
-               is usually too ugly to be used for editing.  Let's
-               ignore it.  */
+                14 dashes, and the field value following 12th dash
+                (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
+                is usually too ugly to be used for editing.  Let's
+                ignore it.  */
              while (*p)
                if (*p++ == '-')
                  {
              while (*p)
                if (*p++ == '-')
                  {
@@ -12920,7 +13630,9 @@ x_list_fonts (f, pattern, size, maxnames)
                    else if (dashes == 12) /* AVERAGE_WIDTH field */
                      average_width = atoi (p);
                  }
                    else if (dashes == 12) /* AVERAGE_WIDTH field */
                      average_width = atoi (p);
                  }
-             if (dashes < 14 || average_width != 0)
+             
+             if (allow_scalable_fonts_p
+                 || dashes < 14 || average_width != 0)
                {
                  tem = build_string (names[i]);
                  if (NILP (Fassoc (tem, list)))
                {
                  tem = build_string (names[i]);
                  if (NILP (Fassoc (tem, list)))
@@ -12938,15 +13650,18 @@ x_list_fonts (f, pattern, size, maxnames)
                    }
                }
            }
                    }
                }
            }
+         
          if (!try_XLoadQueryFont)
          if (!try_XLoadQueryFont)
-           XFreeFontNames (names);
+           {
+             BLOCK_INPUT;
+             XFreeFontNames (names);
+             UNBLOCK_INPUT;
+           }
        }
 
       /* Now store the result in the cache.  */
        }
 
       /* Now store the result in the cache.  */
-      if (f != NULL)
-       XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element)
-         = Fcons (Fcons (key, list),
-                  XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
+      XSETCDR (dpyinfo->name_list_element,
+              Fcons (Fcons (key, list), XCDR (dpyinfo->name_list_element)));
 
     label_cached:
       if (NILP (list)) continue; /* Try the remaining alternatives.  */
 
     label_cached:
       if (NILP (list)) continue; /* Try the remaining alternatives.  */
@@ -12970,7 +13685,7 @@ x_list_fonts (f, pattern, size, maxnames)
          if (!INTEGERP (XCDR (tem)))
            {
              /* Since we have not yet known the size of this font, we
          if (!INTEGERP (XCDR (tem)))
            {
              /* Since we have not yet known the size of this font, we
-               must try slow function call XLoadQueryFont.  */
+                must try slow function call XLoadQueryFont.  */
              XFontStruct *thisinfo;
 
              BLOCK_INPUT;
              XFontStruct *thisinfo;
 
              BLOCK_INPUT;
@@ -12989,17 +13704,19 @@ x_list_fonts (f, pattern, size, maxnames)
 
              if (thisinfo)
                {
 
              if (thisinfo)
                {
-                 XCDR (tem)
-                   = (thisinfo->min_bounds.width == 0
-                      ? make_number (0)
-                      : make_number (thisinfo->max_bounds.width));
+                 XSETCDR (tem,
+                          (thisinfo->min_bounds.width == 0
+                           ? make_number (0)
+                           : make_number (thisinfo->max_bounds.width)));
+                 BLOCK_INPUT;
                  XFreeFont (dpy, thisinfo);
                  XFreeFont (dpy, thisinfo);
+                 UNBLOCK_INPUT;
                }
              else
                /* For unknown reason, the previous call of XListFont had
                  returned a font which can't be opened.  Record the size
                  as 0 not to try to open it again.  */
                }
              else
                /* For unknown reason, the previous call of XListFont had
                  returned a font which can't be opened.  Record the size
                  as 0 not to try to open it again.  */
-               XCDR (tem) = make_number (0);
+               XSETCDR (tem, make_number (0));
            }
 
          found_size = XINT (XCDR (tem));
            }
 
          found_size = XINT (XCDR (tem));
@@ -13262,20 +13979,26 @@ x_load_font (f, fontname, size)
           the cache for x_list_fonts.  */
        Lisp_Object lispy_name = build_string (fontname);
        Lisp_Object lispy_full_name = build_string (fontp->full_name);
           the cache for x_list_fonts.  */
        Lisp_Object lispy_name = build_string (fontname);
        Lisp_Object lispy_full_name = build_string (fontp->full_name);
-
-       XCDR (dpyinfo->name_list_element)
-         = Fcons (Fcons (Fcons (lispy_name, make_number (256)),
-                         Fcons (Fcons (lispy_full_name,
-                                       make_number (fontp->size)),
-                                Qnil)),
-                  XCDR (dpyinfo->name_list_element));
+       Lisp_Object key = Fcons (Fcons (lispy_name, make_number (256)),
+                                Qnil);
+
+       XSETCDR (dpyinfo->name_list_element,
+                Fcons (Fcons (key,
+                              Fcons (Fcons (lispy_full_name,
+                                            make_number (fontp->size)),
+                                     Qnil)),
+                       XCDR (dpyinfo->name_list_element)));
        if (full_name)
        if (full_name)
-         XCDR (dpyinfo->name_list_element)
-           = Fcons (Fcons (Fcons (lispy_full_name, make_number (256)),
-                           Fcons (Fcons (lispy_full_name,
-                                         make_number (fontp->size)),
-                                  Qnil)),
-                    XCDR (dpyinfo->name_list_element));
+         {
+           key = Fcons (Fcons (lispy_full_name, make_number (256)),
+                        Qnil);
+           XSETCDR (dpyinfo->name_list_element,
+                    Fcons (Fcons (key,
+                                  Fcons (Fcons (lispy_full_name,
+                                                make_number (fontp->size)),
+                                         Qnil)),
+                           XCDR (dpyinfo->name_list_element)));
+         }
       }
 
     /* The slot `encoding' specifies how to map a character
       }
 
     /* The slot `encoding' specifies how to map a character
@@ -13632,6 +14355,7 @@ x_term_init (display_name, xrm_option, resource_name)
   dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
   dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
   dpyinfo->mouse_face_window = Qnil;
   dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
   dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
   dpyinfo->mouse_face_window = Qnil;
+  dpyinfo->mouse_face_overlay = Qnil;
   dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
   dpyinfo->mouse_face_defer = 0;
   dpyinfo->x_focus_frame = 0;
   dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
   dpyinfo->mouse_face_defer = 0;
   dpyinfo->x_focus_frame = 0;
@@ -13844,7 +14568,7 @@ x_delete_display (dpyinfo)
        {
          if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
            {
        {
          if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
            {
-             XCDR (tail) = XCDR (XCDR (tail));
+             XSETCDR (tail, XCDR (XCDR (tail)));
              break;
            }
          tail = XCDR (tail);
              break;
            }
          tail = XCDR (tail);
@@ -13912,7 +14636,6 @@ x_initialize ()
 
   clear_frame_hook = x_clear_frame;
   ins_del_lines_hook = x_ins_del_lines;
 
   clear_frame_hook = 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 = XTring_bell;
   reset_terminal_modes_hook = XTreset_terminal_modes;
   delete_glyphs_hook = x_delete_glyphs;
   ring_bell_hook = XTring_bell;
   reset_terminal_modes_hook = XTreset_terminal_modes;
@@ -13922,7 +14645,6 @@ x_initialize ()
   set_terminal_window_hook = XTset_terminal_window;
   read_socket_hook = XTread_socket;
   frame_up_to_date_hook = XTframe_up_to_date;
   set_terminal_window_hook = XTset_terminal_window;
   read_socket_hook = XTread_socket;
   frame_up_to_date_hook = XTframe_up_to_date;
-  reassert_line_highlight_hook = XTreassert_line_highlight;
   mouse_position_hook = XTmouse_position;
   frame_rehighlight_hook = XTframe_rehighlight;
   frame_raise_lower_hook = XTframe_raise_lower;
   mouse_position_hook = XTmouse_position;
   frame_rehighlight_hook = XTframe_rehighlight;
   frame_raise_lower_hook = XTframe_raise_lower;
@@ -13933,7 +14655,7 @@ x_initialize ()
   estimate_mode_line_height_hook = x_estimate_mode_line_height;
 
   scroll_region_ok = 1;                /* we'll scroll partial frames */
   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
   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
@@ -13949,7 +14671,17 @@ x_initialize ()
 
 #ifdef USE_X_TOOLKIT
   XtToolkitInitialize ();
 
 #ifdef USE_X_TOOLKIT
   XtToolkitInitialize ();
+
   Xt_app_con = XtCreateApplicationContext ();
   Xt_app_con = XtCreateApplicationContext ();
+  
+  /* Register a converter from strings to pixels, which uses
+     Emacs' color allocation infrastructure.  */
+  XtAppSetTypeConverter (Xt_app_con,
+                        XtRString, XtRPixel, cvt_string_to_pixel,
+                        cvt_string_to_pixel_args,
+                        XtNumber (cvt_string_to_pixel_args),
+                        XtCacheByDisplay, cvt_pixel_dtor);
+
   XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
 
   /* Install an asynchronous timer that processes Xt timeout events
   XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
 
   /* Install an asynchronous timer that processes Xt timeout events
@@ -14012,15 +14744,23 @@ syms_of_xterm ()
   help_echo_pos = -1;
 
   DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
   help_echo_pos = -1;
 
   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;
 
   x_stretch_cursor_p = 0;
 
+  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,
   DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
-    "What X toolkit scroll bars Emacs uses.\n\
-A value of nil means Emacs doesn't use X toolkit scroll bars.\n\
-Otherwise, value is a symbol describing the X toolkit.");
+    doc: /* What X toolkit scroll bars Emacs uses.
+A value of nil means Emacs doesn't use X toolkit scroll bars.
+Otherwise, value is a symbol describing the X toolkit.  */);
 #ifdef USE_TOOLKIT_SCROLL_BARS
 #ifdef USE_MOTIF
   Vx_toolkit_scroll_bars = intern ("motif");
 #ifdef USE_TOOLKIT_SCROLL_BARS
 #ifdef USE_MOTIF
   Vx_toolkit_scroll_bars = intern ("motif");
@@ -14037,4 +14777,4 @@ Otherwise, value is a symbol describing the X toolkit.");
   last_mouse_motion_frame = Qnil;
 }
 
   last_mouse_motion_frame = Qnil;
 }
 
-#endif /* not HAVE_X_WINDOWS */
+#endif /* HAVE_X_WINDOWS */