Fix typo in a comment.
[bpt/emacs.git] / src / xterm.c
index 5991d3e..94542bf 100644 (file)
@@ -76,10 +76,6 @@ Boston, MA 02111-1307, USA.  */
 #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"
@@ -88,6 +84,7 @@ Boston, MA 02111-1307, USA.  */
 #include "intervals.h"
 #include "process.h"
 #include "atimer.h"
+#include "keymap.h"
 
 #ifdef USE_X_TOOLKIT
 #include <X11/Shell.h>
@@ -100,6 +97,11 @@ Boston, MA 02111-1307, USA.  */
 #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 *));
@@ -148,13 +150,6 @@ extern void _XEditResCheckMessages ();
 #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))
@@ -410,7 +405,7 @@ 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 *));
@@ -441,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 *));
-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));
@@ -460,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 void expose_window_tree 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_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));
@@ -477,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 *));
-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 *));
@@ -1027,32 +1020,6 @@ x_draw_row_bitmaps (w, row)
 }
 
 \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
@@ -2491,7 +2458,7 @@ struct glyph_string
 };
 
 
-#if 1
+#if GLYPH_DEBUG
 
 static void
 x_dump_glyph_string (s)
@@ -2539,7 +2506,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, 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 *,
@@ -2841,20 +2808,6 @@ x_get_glyph_string_clip_rect (s, r)
       r->height = s->row->visible_height;
     }
 
-  /* Don't use S->y for clipping because it doesn't take partially
-     visible lines into account.  For example, it can be negative for
-     partially visible lines at the top of a window.  */
-  if (!s->row->full_width_p
-      && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
-    r->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.  */
@@ -2863,7 +2816,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;
     }
-      
+  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);
 }
 
@@ -3854,6 +3823,9 @@ x_setup_relief_colors (s)
 
   if (s->face->use_box_color_for_shadows_p)
     color = s->face->box_color;
+  else if (s->first_glyph->type == IMAGE_GLYPH
+          && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
+    color = IMAGE_BACKGROUND (s->img, s->f, 0);
   else
     {
       XGCValues xgcv;
@@ -3890,6 +3862,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;
 {
+  Display *dpy = FRAME_X_DISPLAY (f);
+  Window window = FRAME_X_WINDOW (f);
   int i;
   GC gc;
   
@@ -3897,40 +3871,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;
-  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)
-    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)
-      XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+      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;
-  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)
-    XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
-              left_x + i * left_p + 1, bottom_y - i,
-              right_x + 1 - i * right_p, bottom_y - i);
+    XDrawLine (dpy, window, gc,
+              left_x + i * left_p, bottom_y - i,
+              right_x + 2 - 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);
 
-  XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
+  XSetClipMask (dpy, gc, None);
 }
 
 
@@ -4087,8 +4061,6 @@ x_draw_image_foreground (s)
        }
       else
        {
-         unsigned long mask = GCClipXOrigin | GCClipYOrigin | GCFunction;
-         XGCValues xgcv;
          XRectangle clip_rect, image_rect, r;
 
          x_get_glyph_string_clip_rect (s, &clip_rect);
@@ -4446,7 +4418,6 @@ x_draw_glyph_string (s)
 
   /* Set up S->gc, set clipping and draw S.  */
   x_set_glyph_string_gc (s);
-  x_set_glyph_string_clipping (s);
 
   /* Draw relief (if any) in advance for char/composition so that the
      glyph string can be drawn over it.  */
@@ -4456,10 +4427,14 @@ x_draw_glyph_string (s)
          || 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)
     {
@@ -4773,7 +4748,9 @@ x_fill_stretch_glyph_string (s, row, area, start, end)
   /* Adjust base line for subscript/superscript text.  */
   s->ybase += voffset;
 
-  xassert (s->face && s->face->gc);
+  /* 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];
 }
 
@@ -4832,12 +4809,14 @@ x_set_glyph_string_background_width (s, start, last_x)
   struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
   
   if (start == s->row->used[s->area]
-      && s->hl == DRAW_NORMAL_TEXT
       && s->area == TEXT_AREA
-      && (s->row->fill_line_p
-         || s->face->background != default_face->background
-         || s->face->stipple != default_face->stipple))
-    s->extends_to_end_of_line_p = 1;
+      && ((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->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
@@ -5040,27 +5019,19 @@ x_set_glyph_string_background_width (s, start, last_x)
    DRAW_IMAGE_SUNKEN   draw an image with a sunken relief around it
    DRAW_IMAGE_RAISED   draw an image with a raised relief around it
 
-   If REAL_START is non-null, return in *REAL_START the real starting
-   position for display.  This can be different from START in case
-   overlapping glyphs must be displayed.  If REAL_END is non-null,
-   return in *REAL_END the real end position for display.  This can be
-   different from END in case overlapping glyphs must be displayed.
-
    If OVERLAPS_P is non-zero, draw only the foreground of characters
    and clip to the physical height of ROW.
 
    Value is the x-position reached, relative to AREA of W.  */
      
 static int
-x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
-              overlaps_p)
+x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
      struct window *w;
      int x;
      struct glyph_row *row;
      enum glyph_row_area area;
      int start, end;
      enum draw_glyphs_face hl;
-     int *real_start, *real_end;
      int overlaps_p;
 {
   struct glyph_string *head, *tail;
@@ -5073,10 +5044,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);
-  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.  */
@@ -5148,8 +5115,6 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
                               DRAW_NORMAL_TEXT, dummy_x, last_x,
                               overlaps_p);
          start = i;
-         if (real_start)
-           *real_start = start;
          x_compute_overhangs_and_x (t, head->x, 1);
          x_prepend_glyph_string_lists (&head, &tail, h, t);
        }
@@ -5169,8 +5134,6 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
                               overlaps_p);
          for (s = h; s; s = s->next)
            s->background_filled_p = 1;
-         if (real_start)
-           *real_start = i;
          x_compute_overhangs_and_x (t, head->x, 1);
          x_prepend_glyph_string_lists (&head, &tail, h, t);
        }
@@ -5187,8 +5150,6 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
                               overlaps_p);
          x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
          x_append_glyph_string_lists (&head, &tail, h, t);
-         if (real_end)
-           *real_end = i;
        }
 
       /* Append glyph strings for glyphs following the last glyph
@@ -5206,8 +5167,6 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
            s->background_filled_p = 1;
          x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
          x_append_glyph_string_lists (&head, &tail, h, t);
-         if (real_end)
-           *real_end = i;
        }
     }
 
@@ -5215,12 +5174,30 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
   for (s = head; s; s = s->next)
     x_draw_glyph_string (s);
 
+  if (area == TEXT_AREA && !row->full_width_p)
+    {
+      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)
     {
-      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);
@@ -5265,9 +5242,7 @@ x_fix_overlapping_area (w, row, area)
                 && row->glyphs[area][i].overlaps_vertically_p);
 
          x_draw_glyphs (w, start_x, row, area, start, i,
-                        (row->inverse_p
-                         ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
-                        NULL, NULL, 1);
+                        DRAW_NORMAL_TEXT, 1);
        }
       else
        {
@@ -5291,7 +5266,7 @@ x_write_glyphs (start, len)
      struct glyph *start;
      int len;
 {
-  int x, hpos, real_start, real_end;
+  int x, hpos;
 
   xassert (updated_window && updated_row);
   BLOCK_INPUT;
@@ -5302,13 +5277,7 @@ x_write_glyphs (start, len)
   x = x_draw_glyphs (updated_window, output_cursor.x,
                     updated_row, updated_area,
                     hpos, hpos + len,
-                    (updated_row->inverse_p
-                     ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
-                    &real_start, &real_end, 0);
-
-  /* If we drew over the cursor, note that it is not visible any more.  */
-  note_overwritten_text_cursor (updated_window, real_start,
-                               real_end - real_start);
+                    DRAW_NORMAL_TEXT, 0);
 
   UNBLOCK_INPUT;
   
@@ -5330,7 +5299,7 @@ x_insert_glyphs (start, len)
   int line_height, shift_by_width, shifted_region_width;
   struct glyph_row *row;
   struct glyph *glyph;
-  int frame_x, frame_y, hpos, real_start, real_end;
+  int frame_x, frame_y, hpos;
 
   xassert (updated_window && updated_row);
   BLOCK_INPUT;
@@ -5363,8 +5332,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,
-                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;
@@ -5443,7 +5411,7 @@ x_clear_end_of_line (to_x)
   
   /* Notice if the cursor will be cleared by this operation.  */
   if (!updated_row->full_width_p)
-    note_overwritten_text_cursor (w, output_cursor.hpos, -1);
+    notice_overwritten_cursor (w, output_cursor.x, -1);
 
   from_x = output_cursor.x;
      
@@ -5812,6 +5780,7 @@ expose_frame (f, x, y, w, h)
      int x, y, w, h;
 {
   XRectangle r;
+  int mouse_face_overwritten_p = 0;
 
   TRACE ((stderr, "expose_frame "));
 
@@ -5847,36 +5816,69 @@ expose_frame (f, x, y, w, h)
     }
 
   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))
-    expose_window (XWINDOW (f->tool_bar_window), &r);
+    mouse_face_overwritten_p
+      |= expose_window (XWINDOW (f->tool_bar_window), &r);
 
 #ifndef USE_X_TOOLKIT
   if (WINDOWP (f->menu_bar_window))
-    expose_window (XWINDOW (f->menu_bar_window), &r);
+    mouse_face_overwritten_p
+      |= expose_window (XWINDOW (f->menu_bar_window), &r);
 #endif /* not USE_X_TOOLKIT */
+
+  /* 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);
+       }
+    }
 }
 
 
 /* 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;
 {
-  while (w)
+  struct frame *f = XFRAME (w->frame);
+  int mouse_face_overwritten_p = 0;
+  
+  while (w && !FRAME_GARBAGED_P (f))
     {
       if (!NILP (w->hchild))
-       expose_window_tree (XWINDOW (w->hchild), r);
+       mouse_face_overwritten_p
+         |= expose_window_tree (XWINDOW (w->hchild), r);
       else if (!NILP (w->vchild))
-       expose_window_tree (XWINDOW (w->vchild), r);
-      else if (expose_window (w, r) == 0)
-       break;
+       mouse_face_overwritten_p
+         |= expose_window_tree (XWINDOW (w->vchild), r);
+      else
+       mouse_face_overwritten_p |= expose_window (w, r);
+      
       w = NILP (w->next) ? NULL : XWINDOW (w->next);
     }
+
+  return mouse_face_overwritten_p;
 }
 
 
@@ -5897,10 +5899,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.  */
-    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
@@ -5938,16 +5938,16 @@ expose_area (w, row, r, area)
        x_draw_glyphs (w, first_x - start_x, row, area,
                       first - row->glyphs[area],
                       last - row->glyphs[area],
-                      row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
-                      NULL, NULL, 0);
+                      DRAW_NORMAL_TEXT, 0);
     }
 }
       
 
 /* Redraw the parts of the glyph row ROW on window W intersecting
-   rectangle R.  R is in window-relative coordinates.  */
+   rectangle R.  R is in window-relative coordinates.  Value is
+   non-zero if mouse-face was overwritten.  */
 
-static void
+static int
 expose_line (w, row, r)
      struct window *w;
      struct glyph_row *row;
@@ -5957,8 +5957,7 @@ expose_line (w, row, r)
   
   if (row->mode_line_p || w->pseudo_window_p)
     x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
-                  row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
-                  NULL, NULL, 0);
+                  DRAW_NORMAL_TEXT, 0);
   else
     {
       if (row->used[LEFT_MARGIN_AREA])
@@ -5969,6 +5968,8 @@ expose_line (w, row, r)
        expose_area (w, row, r, RIGHT_MARGIN_AREA);
       x_draw_row_bitmaps (w, row);
     }
+
+  return row->mouse_face_p;
 }
 
 
@@ -5998,7 +5999,8 @@ x_phys_cursor_in_rect_p (w, r)
 
 /* Redraw the part of window W intersection rectangle FR.  Pixel
    coordinates in FR are frame-relative.  Call this function with
-   input blocked.  */
+   input blocked.  Value is non-zero if the exposure overwrites
+   mouse-face.  */
 
 static int
 expose_window (w, fr)
@@ -6007,13 +6009,14 @@ expose_window (w, fr)
 {
   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 (w->current_matrix == NULL)
-    return 1;
+    return 0;
 
   /* When we're currently updating the window, display and current
      matrix usually don't agree.  Arrange for a thorough display
@@ -6065,8 +6068,11 @@ expose_window (w, fr)
              || (y1 > r.y && y1 < r.y + r.height)
              || (r.y >= y0 && r.y < y1)
              || (r.y + r.height > y0 && r.y + r.height < y1))
-           expose_line (w, row, &r);
-
+           {
+             if (expose_line (w, row, &r))
+               mouse_face_overwritten_p = 1;
+           }
+             
          if (y1 >= yb)
            break;
        }
@@ -6076,7 +6082,10 @@ expose_window (w, fr)
          && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
              row->enabled_p)
          && row->y < r.y + r.height)
-       expose_line (w, row, &r);
+       {
+         if (expose_line (w, row, &r))
+           mouse_face_overwritten_p = 1;
+       }
 
       if (!w->pseudo_window_p)
        {
@@ -6088,8 +6097,8 @@ expose_window (w, fr)
            x_update_window_cursor (w, 1);
        }
     }
-  
-  return 1;
+
+  return mouse_face_overwritten_p;
 }
 
 
@@ -6998,13 +7007,14 @@ note_mouse_highlight (f, x, y)
                                  &dpyinfo->mouse_face_beg_col,
                                  &dpyinfo->mouse_face_beg_row,
                                  &dpyinfo->mouse_face_beg_x,
-                                 &dpyinfo->mouse_face_beg_y);
+                                 &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);
+                                      &dpyinfo->mouse_face_end_y, Qnil);
              dpyinfo->mouse_face_window = window;
              dpyinfo->mouse_face_face_id
                = face_at_buffer_position (w, pos, 0, 0,
@@ -7038,13 +7048,13 @@ note_mouse_highlight (f, x, y)
                                  &dpyinfo->mouse_face_beg_col,
                                  &dpyinfo->mouse_face_beg_row,
                                  &dpyinfo->mouse_face_beg_x,
-                                 &dpyinfo->mouse_face_beg_y);
+                                 &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);
+                                      &dpyinfo->mouse_face_end_y, Qnil);
              dpyinfo->mouse_face_window = window;
 
              if (BUFFERP (object))
@@ -7088,6 +7098,54 @@ note_mouse_highlight (f, x, y)
              show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
              cursor = None;
            }
+         else if (STRINGP (object) && NILP (mouse_face))
+           {
+             /* A string which doesn't have mouse-face, but
+                the text ``under'' it might have.  */
+             struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
+             int start = MATRIX_ROW_START_CHARPOS (r);
+             
+             pos = string_buffer_position (w, object, start);
+             if (pos > 0)
+               mouse_face = get_char_property_and_overlay (make_number (pos),
+                                                           Qmouse_face,
+                                                           w->buffer,
+                                                           &overlay);
+             if (!NILP (mouse_face) && !NILP (overlay))
+               {
+                 Lisp_Object before = Foverlay_start (overlay);
+                 Lisp_Object after = Foverlay_end (overlay);
+                 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;
+               }
+           }
        }
 
     check_help_echo:
@@ -7133,7 +7191,7 @@ note_mouse_highlight (f, x, y)
                    int pos = string_buffer_position (w, object, start);
                    if (pos > 0)
                      {
-                       help = Fget_text_property (make_number (pos),
+                       help = Fget_char_property (make_number (pos),
                                                   Qhelp_echo, w->buffer);
                        if (!NILP (help))
                          {
@@ -7397,17 +7455,88 @@ note_tool_bar_highlight (f, x, y)
 
 
 \f
-/* Find the glyph matrix position of buffer position POS in window W.
-   *HPOS, *VPOS, *X, and *Y are set to the positions found.  W's
-   current glyphs must be up to date.  If POS is above window start
-   return (0, 0, 0, 0).  If POS is after end of W, return end of
-   last line in W.  */
+/* Find the glyph matrix position of buffer position CHARPOS in window
+   *W.  HPOS, *VPOS, *X, and *Y are set to the positions found.  W's
+   current glyphs must be up to date.  If CHARPOS is above window
+   start return (0, 0, 0, 0).  If CHARPOS is after end of W, return end
+   of last line in W.  In the row containing CHARPOS, stop before glyphs
+   having STOP as object.  */
+
+#if 0 /* This is a version of fast_find_position that's more correct
+        in the presence of hscrolling, for example.  I didn't install
+        it right away because the problem fixed is minor, it failed
+        in 20.x as well, and I think it's too risky to install 
+        so near the release of 21.1.  2001-09-25 gerd.  */
+
+static int
+fast_find_position (w, charpos, hpos, vpos, x, y, stop)
+     struct window *w;
+     int charpos;
+     int *hpos, *vpos, *x, *y;
+     Lisp_Object stop;
+{
+  struct glyph_row *row, *first;
+  struct glyph *glyph, *end;
+  int i, past_end = 0;
+
+  first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+  row = row_containing_pos (w, charpos, first, NULL, 0);
+  if (row == NULL)
+    {
+      if (charpos < MATRIX_ROW_START_CHARPOS (first))
+       {
+         *x = *y = *hpos = *vpos = 0;
+         return 0;
+       }
+      else
+       {
+         row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
+         past_end = 1;
+       }
+    }
+
+  *x = row->x;
+  *y = row->y;
+  *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
+  
+  glyph = row->glyphs[TEXT_AREA];
+  end = glyph + row->used[TEXT_AREA];
+  
+  /* Skip over glyphs not having an object at the start of the row.
+     These are special glyphs like truncation marks on terminal
+     frames.  */
+  if (row->displays_text_p)
+    while (glyph < end
+          && INTEGERP (glyph->object)
+          && !EQ (stop, glyph->object)
+          && glyph->charpos < 0)
+      {
+       *x += glyph->pixel_width;
+       ++glyph;
+      }
+
+  while (glyph < end
+        && !INTEGERP (glyph->object)
+        && !EQ (stop, glyph->object)
+        && (!BUFFERP (glyph->object)
+            || glyph->charpos < charpos))
+    {
+      *x += glyph->pixel_width;
+      ++glyph;
+    }
+
+  *hpos = glyph - row->glyphs[TEXT_AREA];
+  return past_end;
+}
+
+#else /* not 0 */
 
 static int
-fast_find_position (w, pos, hpos, vpos, x, y)
+fast_find_position (w, pos, hpos, vpos, x, y, stop)
      struct window *w;
      int pos;
      int *hpos, *vpos, *x, *y;
+     Lisp_Object stop;
 {
   int i;
   int lastcol;
@@ -7457,22 +7586,26 @@ fast_find_position (w, pos, hpos, vpos, x, y)
   for (i = 0; i < best_row->used[TEXT_AREA]; i++)
     {
       struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
-      int charpos;
+      int charpos = glyph->charpos;
 
-      charpos = glyph->charpos;
-      if (charpos == pos)
+      if (BUFFERP (glyph->object))
        {
-         *hpos = i;
-         *vpos = best_row_vpos;
-         *x = current_x;
-         *y = best_row->y;
-         return 1;
+         if (charpos == pos)
+           {
+             *hpos = i;
+             *vpos = best_row_vpos;
+             *x = current_x;
+             *y = best_row->y;
+             return 1;
+           }
+         else if (charpos > pos)
+           break;
        }
-      else if (charpos > pos)
+      else if (EQ (glyph->object, stop))
        break;
-      else if (charpos > 0)
-       lastcol = i;
 
+      if (charpos > 0)
+       lastcol = i;
       current_x += glyph->pixel_width;
     }
 
@@ -7494,6 +7627,8 @@ fast_find_position (w, pos, hpos, vpos, x, 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
@@ -7587,82 +7722,58 @@ show_mouse_face (dpyinfo, draw)
 {
   struct window *w = XWINDOW (dpyinfo->mouse_face_window);
   struct frame *f = XFRAME (WINDOW_FRAME (w));
-  int i;
-  int cursor_off_p = 0;
-  struct cursor_pos saved_cursor;
-
-  saved_cursor = output_cursor;
-  
-  /* If window is in the process of being destroyed, don't bother
-     to do anything.  */
-  if (w->current_matrix == NULL)
-    goto set_x_cursor;
 
-  /* Recognize when we are called to operate on rows that don't exist
-     anymore.  This can happen when a window is split.  */
-  if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
-    goto set_x_cursor;
-
-  set_output_cursor (&w->phys_cursor);
-
-  /* Note that mouse_face_beg_row etc. are window relative.  */
-  for (i = dpyinfo->mouse_face_beg_row;
-       i <= dpyinfo->mouse_face_end_row;
-       i++)
+  if (/* If window is in the process of being destroyed, don't bother
+        to do anything.  */
+      w->current_matrix != NULL
+      /* Recognize when we are called to operate on rows that don't exist
+        anymore.  This can happen when a window is split.  */
+      && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
     {
-      int start_hpos, end_hpos, start_x;
-      struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
+      int phys_cursor_on_p = w->phys_cursor_on_p;
+      struct glyph_row *row, *first, *last;
 
-      /* Don't do anything if row doesn't have valid contents.  */
-      if (!row->enabled_p)
-       continue;
-
-      /* 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 || DRAW_IMAGE_RAISED;
-         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),
@@ -7761,7 +7872,6 @@ glyph_rect (f, x, y, rect)
       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;
-      int area;
 
       frame_to_window_pixel_xy (w, &x, &y);
       
@@ -8077,7 +8187,7 @@ x_window_to_scroll_bar (window_id)
 }
 
 
-#if defined USE_X_TOOLKIT && defined USE_LUCID
+#if defined USE_LUCID
 
 /* Return the Lucid menu bar WINDOW is part of.  Return null
    if WINDOW is not part of a menu bar.  */
@@ -8102,7 +8212,7 @@ x_window_to_menu_bar (window)
   return NULL;
 }
 
-#endif /* USE_X_TOOLKIT && USE_LUCID */
+#endif /* USE_LUCID */
 
 \f
 /************************************************************************
@@ -8309,7 +8419,6 @@ xm_scroll_callback (widget, client_data, 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)
@@ -8561,7 +8670,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], XtNbeNiceToColormap, True); ++ac; */
   
   pixel = f->output_data.x->scroll_bar_foreground_pixel;
   if (pixel != -1)
@@ -8576,7 +8684,61 @@ x_create_toolkit_scroll_bar (f, bar)
       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);
 
@@ -8642,7 +8804,6 @@ x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
 #ifdef USE_MOTIF
   {
     int size, value;
-    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
@@ -9026,11 +9187,14 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
   /* Does the scroll bar exist yet?  */
   if (NILP (w->vertical_scroll_bar))
     {
-      BLOCK_INPUT;
       if (width && height)
-       x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                     left, top, width, height, False);
-      UNBLOCK_INPUT;
+       {
+         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
@@ -9089,10 +9253,16 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
       {
        int area_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
        int rest = area_width - sb_width;
-       if (rest > 0)
-         x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                       left + area_width -  rest, 0,
-                       rest, max (height, 1), False);
+       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.  */
@@ -9997,7 +10167,8 @@ XTread_socket (sd, bufp, numchars, expected)
                               &event);
              else
                {
-                 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
+                 XSelectionRequestEvent *eventp
+                   = (XSelectionRequestEvent *) &event;
 
                  if (numchars == 0)
                    abort ();
@@ -10019,12 +10190,16 @@ XTread_socket (sd, bufp, numchars, expected)
              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;
-#endif /* not USE_X_TOOLKIT */
+#endif
+#endif
              x_handle_property_notify (&event.xproperty);
-             break;
+             goto OTHER;
 
            case ReparentNotify:
              f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
@@ -10060,7 +10235,7 @@ XTread_socket (sd, bufp, numchars, expected)
 #ifndef USE_TOOLKIT_SCROLL_BARS
                  struct scroll_bar *bar;
 #endif
-#if defined USE_X_TOOLKIT && defined USE_LUCID
+#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.  */
@@ -10070,8 +10245,8 @@ XTread_socket (sd, bufp, numchars, expected)
                    if (widget)
                      xlwmenu_redisplay (widget);
                  }
-#endif /* USE_X_TOOLKIT && USE_LUCID */
-                 
+#endif /* USE_LUCID */
+
 #ifdef USE_TOOLKIT_SCROLL_BARS
                  /* Dispatch event to the widget.  */
                  goto OTHER;
@@ -10089,8 +10264,8 @@ XTread_socket (sd, bufp, numchars, expected)
              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)
                {
@@ -10107,7 +10282,7 @@ XTread_socket (sd, bufp, numchars, expected)
 
            case NoExpose:              /* This occurs when an XCopyArea's
                                           source area was completely
-                                          available */
+                                          available */
              break;
 
            case UnmapNotify:
@@ -10120,7 +10295,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
-                                      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
@@ -10346,7 +10521,8 @@ XTread_socket (sd, bufp, numchars, expected)
                           || 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
@@ -10895,21 +11071,22 @@ XTread_socket (sd, bufp, numchars, expected)
                             Text Cursor
  ***********************************************************************/
 
-/* Note if the text cursor of window W has been overwritten by a
-   drawing operation that outputs N glyphs starting at HPOS in the
-   line given by output_cursor.vpos.  N < 0 means all the rest of the
-   line after HPOS has been written.  */
+/* Notice if the text cursor of window W has been overwritten by a
+   drawing operation that outputs 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 means all the rest
+   of the line after START_X has been written.  */
 
 static void
-note_overwritten_text_cursor (w, hpos, n)
+notice_overwritten_cursor (w, start_x, end_x)
      struct window *w;
-     int hpos, n;
+     int start_x, end_x;
 {
   if (updated_area == TEXT_AREA
+      && w->phys_cursor_on_p
       && 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;
 }
 
@@ -11106,9 +11283,12 @@ x_draw_phys_cursor_glyph (w, row, hl)
      glyphs and mini-buffer.  */
   if (w->phys_cursor.hpos < row->used[TEXT_AREA])
     {
+      int on_p = w->phys_cursor_on_p;
+      
       x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
                     w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
-                    hl, 0, 0, 0);
+                    hl, 0);
+      w->phys_cursor_on_p = on_p;
 
       /* When we erase the cursor, and ROW is overlapped by other
         rows, make sure that these overlapping parts of other rows
@@ -11193,7 +11373,7 @@ x_erase_phys_cursor (w)
       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);
       
       x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                    x,
@@ -11207,8 +11387,6 @@ x_erase_phys_cursor (w)
   /* Erase the cursor by redrawing the character underneath it.  */
   if (mouse_face_here_p)
     hl = DRAW_MOUSE_FACE;
-  else if (cursor_row->inverse_p)
-    hl = DRAW_INVERSE_VIDEO;
   else
     hl = DRAW_NORMAL_TEXT;
   x_draw_phys_cursor_glyph (w, cursor_row, hl);
@@ -11471,16 +11649,6 @@ x_update_window_cursor (w, on)
 \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
@@ -11707,6 +11875,21 @@ x_connection_signal (signalnum)        /* If we don't have an argument, */
                          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.  */
 
@@ -11718,10 +11901,9 @@ x_connection_closed (dpy, error_message)
   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
@@ -11749,7 +11931,12 @@ x_connection_closed (dpy, error_message)
   /* 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)
-    XtCloseDisplay (dpy);
+    {
+      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.  */
@@ -11790,7 +11977,7 @@ x_connection_closed (dpy, error_message)
   
   if (x_display_list == 0)
     {
-      fprintf (stderr, "%s\n", msg);
+      fprintf (stderr, "%s\n", error_msg);
       shut_down_emacs (0, 0, Qnil);
       exit (70);
     }
@@ -11803,7 +11990,7 @@ x_connection_closed (dpy, error_message)
   TOTALLY_UNBLOCK_INPUT;
 
   clear_waiting_for_input ();
-  error ("%s", msg);
+  error ("%s", error_msg);
 }
 
 
@@ -12949,6 +13136,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);
+#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)
@@ -13445,8 +13639,8 @@ x_list_fonts (f, pattern, size, maxnames)
        }
 
       /* Now store the result in the cache.  */
-      XCDR (dpyinfo->name_list_element)
-        = Fcons (Fcons (key, list), XCDR (dpyinfo->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.  */
@@ -13489,10 +13683,10 @@ x_list_fonts (f, pattern, size, maxnames)
 
              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);
                  UNBLOCK_INPUT;
@@ -13501,7 +13695,7 @@ x_list_fonts (f, pattern, size, maxnames)
                /* 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));
@@ -13767,22 +13961,22 @@ x_load_font (f, fontname, size)
        Lisp_Object key = Fcons (Fcons (lispy_name, make_number (256)),
                                 Qnil);
 
-       XCDR (dpyinfo->name_list_element)
-         = Fcons (Fcons (key,
-                         Fcons (Fcons (lispy_full_name,
-                                       make_number (fontp->size)),
-                                Qnil)),
-                  XCDR (dpyinfo->name_list_element));
+       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)
          {
            key = Fcons (Fcons (lispy_full_name, make_number (256)),
                         Qnil);
-           XCDR (dpyinfo->name_list_element)
-             = Fcons (Fcons (key,
-                             Fcons (Fcons (lispy_full_name,
-                                           make_number (fontp->size)),
-                                    Qnil)),
-                      XCDR (dpyinfo->name_list_element));
+           XSETCDR (dpyinfo->name_list_element,
+                    Fcons (Fcons (key,
+                                  Fcons (Fcons (lispy_full_name,
+                                                make_number (fontp->size)),
+                                         Qnil)),
+                           XCDR (dpyinfo->name_list_element)));
          }
       }
 
@@ -14353,7 +14547,7 @@ x_delete_display (dpyinfo)
        {
          if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
            {
-             XCDR (tail) = XCDR (XCDR (tail));
+             XSETCDR (tail, XCDR (XCDR (tail)));
              break;
            }
          tail = XCDR (tail);
@@ -14421,7 +14615,6 @@ x_initialize ()
 
   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;
@@ -14431,7 +14624,6 @@ x_initialize ()
   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;
@@ -14531,23 +14723,23 @@ syms_of_xterm ()
   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;
 
   DEFVAR_BOOL ("x-use-underline-position-properties",
               &x_use_underline_position_properties,
-     "*Non-nil means make use of UNDERLINE_POSITION font properties.\n\
-Nil means ignore them.  If you encounter fonts with bogus\n\
-UNDERLINE_POSITION font properties, for example 7x13 on XFree prior\n\
-to 4.1, set this to nil.");
+     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,
-    "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");
@@ -14564,4 +14756,4 @@ Otherwise, value is a symbol describing the X toolkit.");
   last_mouse_motion_frame = Qnil;
 }
 
-#endif /* not HAVE_X_WINDOWS */
+#endif /* HAVE_X_WINDOWS */