Include keymap.h.
[bpt/emacs.git] / src / xterm.c
index 9158cdd..b977fa6 100644 (file)
@@ -1,5 +1,5 @@
 /* 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.
@@ -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>
@@ -117,7 +114,6 @@ extern void _XEditResCheckMessages ();
 #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
@@ -149,13 +145,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))
@@ -230,9 +219,9 @@ static unsigned char ov_bits[] = {
 extern Lisp_Object Qhelp_echo;
 
 \f
-/* Non-zero means Emacs uses toolkit scroll bars.  */
+/* Non-nil means Emacs uses toolkit scroll bars.  */
 
-int x_toolkit_scroll_bars_p;
+Lisp_Object Vx_toolkit_scroll_bars;
 
 /* If a string, XTread_socket generates an event to display that string.
    (The display is done in read_char.)  */
@@ -257,6 +246,10 @@ static int any_help_event_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.  */
 
@@ -396,17 +389,23 @@ enum draw_glyphs_face
   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 *,
-                                  int *, int *));
+                                  int *, int *, Lisp_Object));
+static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
+                                    int *, int *, int *, int *, int));
 static void set_output_cursor P_ ((struct cursor_pos *));
 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
-                                          int *, int *, int *));
+                                          int *, int *, int *, int));
 static void note_mode_line_highlight P_ ((struct window *, int, int));
 static void note_mouse_highlight P_ ((struct frame *, int, int));
 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
@@ -451,11 +450,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 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_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));
@@ -476,7 +475,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 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.  */
 
@@ -680,22 +683,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 x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
+      
   if (!w->pseudo_window_p)
     {
-      struct x_display_info *dpyinfo
-       = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
-      
       BLOCK_INPUT;
 
-      /* If a row with mouse-face was overwritten, arrange for
-        XTframe_up_to_date to redisplay the mouse highlight.  */
-      if (mouse_face_overwritten_p)
-       {
-         dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
-         dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
-         dpyinfo->mouse_face_window = Qnil;
-       }
-      
       if (cursor_on_p)
        x_display_and_set_cursor (w, 1, output_cursor.hpos,
                                  output_cursor.vpos,
@@ -705,6 +698,15 @@ x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
       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;
 }
 
@@ -769,22 +771,26 @@ x_after_update_window_line (desired_row)
   
   if (!desired_row->mode_line_p && !w->pseudo_window_p)
     {
+      struct frame *f;
+      int width;
+      
       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)
+      if (windows_or_buffers_changed
+         && (f = XFRAME (w->frame),
+             width = FRAME_INTERNAL_BORDER_WIDTH (f),
+             width != 0))
        {
-         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);
+         x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                       x, y, width, height, False);
        }
       
       UNBLOCK_INPUT;
@@ -1139,19 +1145,6 @@ static void x_produce_glyphs P_ ((struct it *));
 static void x_produce_image_glyph P_ ((struct it *it));
 
 
-/* Return a pointer to per-char metric information in FONT of a
-   character pointed by B which is a pointer to an XChar2b.  */
-
-#define PER_CHAR_METRIC(font, b)                                          \
-  ((font)->per_char                                                       \
-   ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2                   \
-      + (((font)->min_byte1 || (font)->max_byte1)                         \
-        ? (((b)->byte1 - (font)->min_byte1)                               \
-           * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
-        : 0))                                                             \
-   : &((font)->max_bounds))
-
-
 /* Get metrics of character CHAR2B in FONT.  Value is null if CHAR2B
    is not contained in the font.  */
 
@@ -1517,20 +1510,23 @@ x_produce_image_glyph (it)
   prepare_image_for_display (it->f, img);
 
   it->ascent = it->phys_ascent = image_ascent (img, face);
-  it->descent = it->phys_descent = img->height + 2 * img->margin - it->ascent;
-  it->pixel_width = img->width + 2 * img->margin;
+  it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
+  it->pixel_width = img->width + 2 * img->hmargin;
 
   it->nglyphs = 1;
   
   if (face->box != FACE_NO_BOX)
     {
-      it->ascent += face->box_line_width;
-      it->descent += face->box_line_width;
+      if (face->box_line_width > 0)
+       {
+         it->ascent += face->box_line_width;
+         it->descent += face->box_line_width;
+       }
       
       if (it->start_of_box_run_p)
-       it->pixel_width += face->box_line_width;
+       it->pixel_width += abs (face->box_line_width);
       if (it->end_of_box_run_p)
-       it->pixel_width += face->box_line_width;
+       it->pixel_width += abs (face->box_line_width);
     }
 
   take_vertical_position_into_account (it);
@@ -1735,13 +1731,16 @@ x_produce_stretch_glyph (it)
 
   if (face->box != FACE_NO_BOX)
     {
-      it->ascent += face->box_line_width;
-      it->descent += face->box_line_width;
+      if (face->box_line_width > 0)
+       {
+         it->ascent += face->box_line_width;
+         it->descent += face->box_line_width;
+       }
       
       if (it->start_of_box_run_p)
-       it->pixel_width += face->box_line_width;
+       it->pixel_width += abs (face->box_line_width);
       if (it->end_of_box_run_p)
-       it->pixel_width += face->box_line_width;
+       it->pixel_width += abs (face->box_line_width);
     }
   
   take_vertical_position_into_account (it);
@@ -1808,8 +1807,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
-        glyph.
-      */
+        glyph.  */
       int saved_multibyte_p = it->multibyte_p;
 
       /* Maybe translate single-byte characters to multibyte, or the
@@ -1830,8 +1828,7 @@ x_produce_glyphs (it)
          else if (!SINGLE_BYTE_CHAR_P (it->c)
                   && !it->multibyte_p)
            {
-             it->char_to_display = multibyte_char_to_unibyte (it->c, Qnil);
-             it->multibyte_p = 0;
+             it->multibyte_p = 1;
              it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
              face = FACE_FROM_ID (it->f, it->face_id);
            }
@@ -1898,9 +1895,14 @@ x_produce_glyphs (it)
            {
              int thick = face->box_line_width;
              
-             it->ascent += thick;
-             it->descent += thick;
-             
+             if (thick > 0)
+               {
+                 it->ascent += thick;
+                 it->descent += thick;
+               }
+             else
+               thick = -thick;
+
              if (it->start_of_box_run_p)
                it->pixel_width += thick;
              if (it->end_of_box_run_p)
@@ -1943,11 +1945,11 @@ x_produce_glyphs (it)
          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')
@@ -2012,8 +2014,14 @@ x_produce_glyphs (it)
          if (face->box != FACE_NO_BOX)
            {
              int thick = face->box_line_width;
-             it->ascent += thick;
-             it->descent += thick;
+
+             if (thick > 0)
+               {
+                 it->ascent += thick;
+                 it->descent += thick;
+               }
+             else
+               thick = - thick;
          
              if (it->start_of_box_run_p)
                it->pixel_width += thick;
@@ -2279,8 +2287,14 @@ x_produce_glyphs (it)
       if (face->box != FACE_NO_BOX)
        {
          int thick = face->box_line_width;
-         it->ascent += thick;
-         it->descent += thick;
+
+         if (thick > 0)
+           {
+             it->ascent += thick;
+             it->descent += thick;
+           }
+         else
+           thick = - thick;
          
          if (it->start_of_box_run_p)
            it->pixel_width += thick;
@@ -2337,7 +2351,8 @@ x_estimate_mode_line_height (f, face_id)
          {
            if (face->font)
              height = FONT_HEIGHT (face->font);
-           height += 2 * face->box_line_width;
+           if (face->box_line_width > 0)
+             height += 2 * face->box_line_width;
          }
       }
   
@@ -2466,7 +2481,7 @@ struct glyph_string
 };
 
 
-#if 0
+#if GLYPH_DEBUG
 
 static void
 x_dump_glyph_string (s)
@@ -2674,9 +2689,12 @@ x_set_mouse_face_gc (s)
   int face_id;
   struct face *face;
 
-  /* What face has to be used for the mouse face?  */
+  /* What face has to be used last for the mouse face?  */
   face_id = FRAME_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
@@ -2813,20 +2831,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.  */
@@ -2835,7 +2839,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);
 }
 
@@ -3081,25 +3101,27 @@ x_draw_glyph_string_background (s, force_p)
      shouldn't be drawn in the first place.  */
   if (!s->background_filled_p)
     {
+      int box_line_width = max (s->face->box_line_width, 0);
+
       if (s->stippled_p)
        {
          /* Fill background with a stipple pattern.  */
          XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
          XFillRectangle (s->display, s->window, s->gc, s->x,
-                         s->y + s->face->box_line_width,
+                         s->y + box_line_width,
                          s->background_width,
-                         s->height - 2 * s->face->box_line_width);
+                         s->height - 2 * box_line_width);
          XSetFillStyle (s->display, s->gc, FillSolid);
          s->background_filled_p = 1;
        }
-      else 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)
        {
-         x_clear_glyph_string_rect (s, s->x, s->y + s->face->box_line_width,
+         x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
                                     s->background_width,
-                                    s->height - 2 * s->face->box_line_width);
+                                    s->height - 2 * box_line_width);
          s->background_filled_p = 1;
        }
     }
@@ -3118,7 +3140,7 @@ x_draw_glyph_string_foreground (s)
      of S to the right of that box line.  */
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
-    x = s->x + s->face->box_line_width;
+    x = s->x + abs (s->face->box_line_width);
   else
     x = s->x;
 
@@ -3188,7 +3210,7 @@ x_draw_composite_glyph_string_foreground (s)
      of S to the right of that box line.  */
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
-    x = s->x + s->face->box_line_width;
+    x = s->x + abs (s->face->box_line_width);
   else
     x = s->x;
 
@@ -3219,6 +3241,10 @@ x_draw_composite_glyph_string_foreground (s)
 #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
@@ -3292,29 +3318,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
-   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 *
-x_color_cells (f, ncells)
-     struct frame *f;
+x_color_cells (dpy, ncells)
+     Display *dpy;
      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)
     {
-      Display *display = FRAME_X_DISPLAY (f);
-      Screen *screen = FRAME_X_SCREEN (f);
+      Screen *screen = dpyinfo->screen;
       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);
@@ -3322,7 +3497,7 @@ x_color_cells (f, ncells)
       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);
     }
 
@@ -3370,23 +3545,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;
 {
-  Display *display = FRAME_X_DISPLAY (f);
-  Screen *screen = FRAME_X_SCREEN (f);
   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
@@ -3396,7 +3568,7 @@ x_alloc_nearest_color (f, cmap, color)
       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)
        {
@@ -3415,14 +3587,14 @@ x_alloc_nearest_color (f, cmap, color)
       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.  */
-      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
@@ -3446,6 +3618,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.  */
@@ -3694,6 +3882,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;
   
@@ -3701,40 +3891,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,
-                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;
-  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,
+    XDrawLine (dpy, window, gc,
               left_x + i * left_p, bottom_y - i,
-              right_x + 1 - i * right_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);
 }
 
 
@@ -3806,12 +3996,12 @@ x_draw_glyph_string_box (s)
                ? s->first_glyph
                : s->first_glyph + s->nchars - 1);
 
-  width = s->face->box_line_width;
+  width = abs (s->face->box_line_width);
   raised_p = s->face->box == FACE_RAISED_BOX;
   left_x = s->x;
-  right_x = ((s->row->full_width_p
-             ? 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;
 
@@ -3851,17 +4041,14 @@ x_draw_image_foreground (s)
      right of that line.  */
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
-    x = s->x + s->face->box_line_width;
+    x = s->x + abs (s->face->box_line_width);
   else
     x = s->x;
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
-  if (s->img->margin)
-    {
-      x += s->img->margin;
-      y += s->img->margin;
-    }
+  x += s->img->hmargin;
+  y += s->img->vmargin;
 
   if (s->img->pixmap)
     {
@@ -3940,17 +4127,14 @@ x_draw_image_relief (s)
      right of that line.  */
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
-    x = s->x + s->face->box_line_width;
+    x = s->x + abs (s->face->box_line_width);
   else
     x = s->x;
   
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
-  if (s->img->margin)
-    {
-      x += s->img->margin;
-      y += s->img->margin;
-    }
+  x += s->img->hmargin;
+  y += s->img->vmargin;
   
   if (s->hl == DRAW_IMAGE_SUNKEN
       || s->hl == DRAW_IMAGE_RAISED)
@@ -3989,17 +4173,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)
-    x = s->face->box_line_width;
+    x = abs (s->face->box_line_width);
   else
     x = 0;
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
-  if (s->img->margin)
-    {
-      x += s->img->margin;
-      y += s->img->margin;
-    }
+  x += s->img->hmargin;
+  y += s->img->vmargin;
 
   if (s->img->pixmap)
     {
@@ -4086,29 +4267,30 @@ x_draw_image_glyph_string (s)
      struct glyph_string *s;
 {
   int x, y;
-  int box_line_width = s->face->box_line_width;
-  int margin = s->img->margin;
+  int box_line_hwidth = abs (s->face->box_line_width);
+  int box_line_vwidth = max (s->face->box_line_width, 0);
   int height;
   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
-      || margin
+      || s->img->hmargin
+      || s->img->vmargin
       || 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;
       
-      y = s->y + box_line_width;
+      y = s->y + box_line_vwidth;
       
       if (s->img->mask)
        {
@@ -4195,14 +4377,23 @@ x_draw_stretch_glyph_string (s)
       /* 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;
+         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);
-
+         
          if (s->face->stipple)
            {
              /* Fill background with a stipple pattern.  */
@@ -4220,7 +4411,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);
   
@@ -4234,6 +4425,8 @@ static void
 x_draw_glyph_string (s)
      struct glyph_string *s;
 {
+  int relief_drawn_p = 0;
+
   /* If S draws into the background of its successor, draw the
      background of the successor first so that S can draw into it.
      This makes S->next use XDrawString instead of XDrawImageString.  */
@@ -4249,6 +4442,19 @@ x_draw_glyph_string (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_draw_glyph_string_background (s, 1);
+      x_draw_glyph_string_box (s);
+      relief_drawn_p = 1;
+    }
+
   switch (s->first_glyph->type)
     {
     case IMAGE_GLYPH:
@@ -4299,12 +4505,13 @@ x_draw_glyph_string (s)
             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->height - h;
+           y = s->y + s->height - h;
       
          if (s->face->underline_defaulted_p)
            XFillRectangle (s->display, s->window, s->gc,
@@ -4359,8 +4566,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);
     }
   
@@ -4560,7 +4767,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];
 }
 
@@ -4619,11 +4828,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->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->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
@@ -4888,7 +5100,7 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
        }
 
       x += FRAME_INTERNAL_BORDER_WIDTH (f);
-      last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
+      last_x += FRAME_INTERNAL_BORDER_WIDTH (f);
     }
   else
     {
@@ -5138,7 +5350,7 @@ x_insert_glyphs (start, len)
                          - shift_by_width);
 
   /* Shift right.  */
-  frame_x = WINDOW_TO_FRAME_PIXEL_X (w, output_cursor.x);
+  frame_x = window_box_left (w, updated_area) + output_cursor.x;
   frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
   XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
             f->output_data.x->normal_gc,
@@ -5170,6 +5382,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.
@@ -5237,9 +5465,9 @@ x_clear_end_of_line (to_x)
   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;
     }
 }
@@ -5403,18 +5631,23 @@ XTflash (f)
        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;
 
-           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;
 
+           /* 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);
          }
@@ -5577,6 +5810,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 "));
 
@@ -5612,90 +5846,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))
-    {
-      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))
-    {
-      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
-   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);
+       mouse_face_overwritten_p
+         |= expose_window_tree (XWINDOW (w->vchild), r);
       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;
 }
 
 
@@ -5764,9 +5977,10 @@ expose_area (w, row, r, area)
       
 
 /* 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;
@@ -5788,6 +6002,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;
 }
 
 
@@ -5815,80 +6031,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;
-     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 (w->current_matrix == NULL)
-    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);
+    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;
 }
 
 
@@ -6407,10 +6651,11 @@ note_mouse_movement (frame, event)
    date.  */
 
 static struct glyph *
-x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
+x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
      struct window *w;
      int x, y;
      int *hpos, *vpos, *area;
+     int buffer_only_p;
 {
   struct glyph *glyph, *end;
   struct glyph_row *row = NULL;
@@ -6468,7 +6713,7 @@ x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
        {
          if (w->pseudo_window_p)
            break;
-         else if (BUFFERP (glyph->object))
+         else if (!buffer_only_p || BUFFERP (glyph->object))
            break;
        }
       
@@ -6600,6 +6845,8 @@ note_mouse_highlight (f, x, y)
   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
@@ -6647,231 +6894,372 @@ note_mouse_highlight (f, x, y)
       return;
     }
 
+  /* Mouse is on the mode or header line?  */
   if (portion == 1 || portion == 3)
     {
-      /* Mouse is on the mode or top line.  */
       note_mode_line_highlight (w, x, portion == 1);
       return;
     }
-  else if (portion == 2)
-    XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                  f->output_data.x->horizontal_drag_cursor);
+  
+  if (portion == 2)
+    cursor = f->output_data.x->horizontal_drag_cursor;
   else
-    XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                  f->output_data.x->text_cursor);
+    cursor = f->output_data.x->text_cursor;
 
   /* Are we in a window whose display is up to date?
      And verify the buffer's text has not changed.  */
+  b = XBUFFER (w->buffer);
   if (/* Within text portion of the window.  */
       portion == 0
       && EQ (w->window_end_valid, w->buffer)
-      && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
-      && (XFASTINT (w->last_overlay_modified)
-         == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
+      && XFASTINT (w->last_modified) == BUF_MODIFF (b)
+      && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
     {
       int hpos, vpos, pos, i, area;
       struct glyph *glyph;
+      Lisp_Object object;
+      Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
+      Lisp_Object *overlay_vec = NULL;
+      int len, noverlays;
+      struct buffer *obuf;
+      int obegv, ozv, same_region;
 
       /* Find the glyph under X/Y.  */
-      glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area);
+      glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
 
       /* Clear mouse face if X/Y not over text.  */
       if (glyph == NULL
          || 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;
-      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);
 
-               /* 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_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
@@ -6921,7 +7309,7 @@ x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
   int area;
 
   /* Find the glyph under X/Y.  */
-  *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area);
+  *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
   if (*glyph == NULL)
     return -1;
 
@@ -7025,7 +7413,7 @@ note_tool_bar_highlight (f, x, y)
   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
@@ -7044,7 +7432,6 @@ note_tool_bar_highlight (f, x, y)
       return;
     }
   else if (rc == 0)
-    /* On same tool-bar item as before.  */
     goto set_help_echo;
 
   clear_mouse_face (dpyinfo);
@@ -7102,28 +7489,101 @@ note_tool_bar_highlight (f, x, y)
 
 
 \f
-/* Find the glyph matrix position of buffer position POS in window W.
-   *HPOS, *VPOS, *X, and *Y are set to the positions found.  W's
-   current glyphs must be up to date.  If POS is above window start
-   return (0, 0, 0, 0).  If POS is after end of W, return end of
-   last line in W.  */
+/* Find the glyph matrix position of buffer position CHARPOS in window
+   *W.  HPOS, *VPOS, *X, and *Y are set to the positions found.  W's
+   current glyphs must be up to date.  If CHARPOS is above window
+   start return (0, 0, 0, 0).  If CHARPOS is after end of W, return end
+   of last line in W.  In the row containing CHARPOS, stop before glyphs
+   having STOP as object.  */
+
+#if 0 /* This is a version of fast_find_position that's more correct
+        in the presence of hscrolling, for example.  I didn't install
+        it right away because the problem fixed is minor, it failed
+        in 20.x as well, and I think it's too risky to install 
+        so near the release of 21.1.  2001-09-25 gerd.  */
 
 static int
-fast_find_position (w, 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);
+  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;
+     Lisp_Object stop;
 {
   int i;
   int lastcol;
   int maybe_next_line_p = 0;
   int line_start_position;
   int yb = window_text_bottom_y (w);
-  struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
-  struct glyph_row *best_row = row;
-  int row_vpos = 0, best_row_vpos = 0;
+  struct glyph_row *row, *best_row;
+  int row_vpos, best_row_vpos;
   int current_x;
 
+  row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+  row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
+
   while (row->y < yb)
     {
       if (row->used[TEXT_AREA])
@@ -7160,22 +7620,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;
     }
 
@@ -7197,6 +7661,90 @@ 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
+   coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
+
+   RIGHT_P non-zero means return the position of the right edge of the
+   glyph, RIGHT_P zero means return the left edge position.
+
+   If no glyph for POS exists in the matrix, return the position of
+   the glyph with the next smaller position that is in the matrix, if
+   RIGHT_P is zero.  If RIGHT_P is non-zero, and no glyph for POS
+   exists in the matrix, return the position of the glyph with the
+   next larger position in OBJECT.
+
+   Value is non-zero if a glyph was found.  */
+
+static int
+fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
+     struct window *w;
+     int pos;
+     Lisp_Object object;
+     int *hpos, *vpos, *x, *y;
+     int right_p;
+{
+  int yb = window_text_bottom_y (w);
+  struct glyph_row *r;
+  struct glyph *best_glyph = NULL;
+  struct glyph_row *best_row = NULL;
+  int best_x = 0;
+
+  for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+       r->enabled_p && r->y < yb;
+       ++r)
+    {
+      struct glyph *g = r->glyphs[TEXT_AREA];
+      struct glyph *e = g + r->used[TEXT_AREA];
+      int gx;
+
+      for (gx = r->x; g < e; gx += g->pixel_width, ++g)
+       if (EQ (g->object, object))
+         {
+           if (g->charpos == pos)
+             {
+               best_glyph = g;
+               best_x = gx;
+               best_row = r;
+               goto found;
+             }
+           else if (best_glyph == NULL
+                    || ((abs (g->charpos - pos)
+                        < abs (best_glyph->charpos - pos))
+                        && (right_p
+                            ? g->charpos < pos
+                            : g->charpos > pos)))
+             {
+               best_glyph = g;
+               best_x = gx;
+               best_row = r;
+             }
+         }
+    }
+
+ found:
+
+  if (best_glyph)
+    {
+      *x = best_x;
+      *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
+
+      if (right_p)
+       {
+         *x += best_glyph->pixel_width;
+         ++*hpos;
+       }
+      
+      *y = best_row->y;
+      *vpos = best_row - w->current_matrix->rows;
+    }
+
+  return best_glyph != NULL;
+}
+
 
 /* Display the active region described by mouse_face_*
    in its mouse-face if HL > 0, in its normal face if HL = 0.  */
@@ -7268,9 +7816,9 @@ show_mouse_face (dpyinfo, draw)
 
       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);
+         row->mouse_face_p = draw == DRAW_MOUSE_FACE || DRAW_IMAGE_RAISED;
        }
     }
 
@@ -7297,21 +7845,26 @@ show_mouse_face (dpyinfo, draw)
 }
 
 /* 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;
 {
-  if (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_overlay = Qnil;
+  return cleared;
 }
 
 
@@ -7352,23 +7905,71 @@ cancel_mouse_face (f)
       dpyinfo->mouse_face_window = Qnil;
     }
 }
+
 \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;
+      int area;
+
+      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.
-   *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.
 
-   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.
 
-   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.
@@ -7540,32 +8141,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.  */
 
-#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;
@@ -7645,6 +8246,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
@@ -7850,7 +8478,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)
@@ -7897,10 +8524,10 @@ xm_scroll_callback (widget, client_data, call_data)
        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.
@@ -8042,14 +8669,6 @@ x_create_toolkit_scroll_bar (f, bar)
   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;
@@ -8110,7 +8729,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)
@@ -8125,7 +8743,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);
 
@@ -8191,9 +8863,6 @@ x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
 #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
@@ -8207,18 +8876,6 @@ x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
     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)
@@ -8238,10 +8895,6 @@ x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
                              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 */
   {
@@ -8348,9 +9001,9 @@ 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.  */
-    XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-               left, top, width,
-               window_box_height (w), False);
+    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.  */
@@ -8387,15 +9040,15 @@ x_scroll_bar_create (w, top, left, width, height)
 
   /* 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 */
@@ -8477,13 +9130,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)
-      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)
@@ -8492,7 +9144,6 @@ x_scroll_bar_set_handle (bar, start, end, rebuild)
 
     /* 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,
@@ -8506,13 +9157,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)
-      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);
 
   }
 
@@ -8597,8 +9247,9 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
   if (NILP (w->vertical_scroll_bar))
     {
       BLOCK_INPUT;
-      XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                 left, top, width, height, False);
+      if (width && height)
+       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);
     }
@@ -8624,8 +9275,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.  */
-      XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                 left, top, width, height, False);
+      if (width && height)
+       x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                     left, top, width, height, False);
 
       /* Move/size the scroll bar widget.  */
       if (mask)
@@ -8633,24 +9285,35 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
                           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 */
   
+      /* Clear areas not covered by the scroll bar because of
+        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)
+         x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                       left + area_width -  rest, 0,
+                       rest, max (height, 1), False);
+      }
       
       /* Move/size the scroll bar window.  */
       if (mask)
@@ -9060,7 +9723,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)
-      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 */
 }
@@ -9553,7 +10217,8 @@ XTread_socket (sd, bufp, numchars, expected)
                               &event);
              else
                {
-                 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
+                 XSelectionRequestEvent *eventp
+                   = (XSelectionRequestEvent *) &event;
 
                  if (numchars == 0)
                    abort ();
@@ -9575,12 +10240,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);
@@ -9613,12 +10282,26 @@ XTread_socket (sd, bufp, numchars, expected)
                }
              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 */
-                 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);
@@ -9730,10 +10413,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
-             /* I couldn't find a way to prevent LessTif scroll bars
-                from consuming key events.  */
              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))
@@ -9888,7 +10571,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
@@ -9919,7 +10603,6 @@ XTread_socket (sd, bufp, numchars, expected)
                        {
                          register int i;
                          register int c;
-                         unsigned char *p, *pend;
                          int nchars, len;
 
                          for (i = 0; i < nbytes; i++)
@@ -10015,41 +10698,9 @@ XTread_socket (sd, bufp, numchars, expected)
 
            case EnterNotify:
              {
-               int from_menu_bar_p = 0;
-               
                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)
@@ -10065,7 +10716,7 @@ XTread_socket (sd, bufp, numchars, expected)
              
                /* 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;
              }
@@ -10102,9 +10753,6 @@ XTread_socket (sd, bufp, numchars, expected)
              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
@@ -10123,26 +10771,13 @@ XTread_socket (sd, bufp, numchars, expected)
                      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;
                    }
 
-#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
                    {
@@ -10784,15 +11419,15 @@ 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);
       
-      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.  */
@@ -10810,6 +11445,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.  */
@@ -10872,8 +11536,8 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
     }
   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;
          
@@ -11033,16 +11697,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
@@ -11263,27 +11917,77 @@ x_connection_signal (signalnum)       /* If we don't have an argument, */
   signal (signalnum, x_connection_signal);
 #endif /* USG */
 }
+
 \f
-/* 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 DISPLAY.  */
+/* Handle the loss of connection to display DPY.  ERROR_MESSAGE is
+   the text of an error message that lead to the connection loss.  */
 
 static SIGTYPE
-x_connection_closed (display, error_message)
-     Display *display;
+x_connection_closed (dpy, error_message)
+     Display *dpy;
      char *error_message;
 {
-  struct x_display_info *dpyinfo = x_display_info_for_display (display);
+  struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
   Lisp_Object frame, tail;
+  int count;
+  
+  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
+     below.  Otherwise, we might end up with printing ``can't find per
+     display information'' in the recursive call instead of printing
+     the original message here.  */
+  count = x_catch_errors (dpy);
+  
+  /* We have to close the display to inform Xt that it doesn't
+     exist anymore.  If we don't, Xt will continue to wait for
+     events from the display.  As a consequence, a sequence of
 
-  /* Indicate that this display is dead.  */
+     M-x make-frame-on-display RET :1 RET
+     ...kill the new frame, so that we get an IO error...
+     M-x make-frame-on-display RET :1 RET
+
+     will indefinitely wait in Xt for events for display `:1', opened
+     in the first class to make-frame-on-display.
 
-#if 0 /* Closing the display caused a bus error on OpenWindows.  */
+     Closing the display is reported to lead to a bus error on
+     OpenWindows in certain situations.  I suspect that is a bug
+     in OpenWindows.  I don't know how to cicumvent it here.  */
+  
 #ifdef USE_X_TOOLKIT
-  XtCloseDisplay (display);
-#endif
+  /* 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.  */
   if (dpyinfo)
     dpyinfo->display = 0;
 
@@ -11317,9 +12021,11 @@ x_connection_closed (display, error_message)
   if (dpyinfo)
     x_delete_display (dpyinfo);
 
+  x_uncatch_errors (dpy, count);
+  
   if (x_display_list == 0)
     {
-      fprintf (stderr, "%s\n", error_message);
+      fprintf (stderr, "%s\n", error_msg);
       shut_down_emacs (0, 0, Qnil);
       exit (70);
     }
@@ -11332,10 +12038,10 @@ x_connection_closed (display, error_message)
   TOTALLY_UNBLOCK_INPUT;
 
   clear_waiting_for_input ();
-  handling_signal = 0;
-  error ("%s", error_message);
+  error ("%s", error_msg);
 }
 
+
 /* This is the usual handler for X protocol errors.
    It kills all frames on the display that we got the error for.
    If that was the only one, it prints an error message and kills Emacs.  */
@@ -11356,6 +12062,7 @@ x_error_quitter (display, error)
   x_connection_closed (display, buf1);
 }
 
+
 /* This is the first-level handler for X protocol errors.
    It calls x_error_quitter or x_error_catcher.  */
 
@@ -11431,7 +12138,12 @@ x_new_font (f, fontname)
                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,
@@ -11553,7 +12265,7 @@ xim_open_dpy (dpyinfo, resource_name)
 #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
     }
@@ -11671,11 +12383,13 @@ xim_close_dpy (dpyinfo)
 {
 #ifdef USE_XIM
 #ifdef HAVE_X11R6_XIM
-  XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
-                                   NULL, EMACS_CLASS,
-                                   xim_instantiate_callback, NULL);
+  if (dpyinfo->display)
+    XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
+                                     NULL, EMACS_CLASS,
+                                     xim_instantiate_callback, NULL);
 #endif /* not HAVE_X11R6_XIM */
-  XCloseIM (dpyinfo->xim);
+  if (dpyinfo->display)
+    XCloseIM (dpyinfo->xim);
   dpyinfo->xim = NULL;
   XFree (dpyinfo->xim_styles);
 #endif /* USE_XIM */
@@ -11847,37 +12561,19 @@ x_set_offset (f, xoff, yoff, change_gravity)
   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;
 {
-#ifndef USE_X_TOOLKIT
   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
@@ -11922,7 +12618,43 @@ x_set_window_size (f, change_gravity, cols, rows)
   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.  */
@@ -12405,11 +13137,12 @@ x_iconify_frame (f)
   UNBLOCK_INPUT;
 #endif /* not USE_X_TOOLKIT */
 }
+
 \f
-/* Destroy the X window of frame F.  */
+/* Free X resources of frame F.  */
 
 void
-x_destroy_window (f)
+x_free_frame_resources (f)
      struct frame *f;
 {
   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
@@ -12418,18 +13151,25 @@ x_destroy_window (f)
 
   /* If a display connection is dead, don't try sending more
      commands to the X server.  */
-  if (dpyinfo->display != 0)
+  if (dpyinfo->display)
     {
-      if (f->output_data.x->icon_desc != 0)
+      if (f->output_data.x->icon_desc)
        XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
+      
 #ifdef HAVE_X_I18N
       if (FRAME_XIC (f))
        free_frame_xic (f);
 #endif
-      XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
+      
+      if (FRAME_X_WINDOW (f))
+       XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
+      
 #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 */
 
@@ -12439,16 +13179,27 @@ x_destroy_window (f)
       unload_color (f, f->output_data.x->cursor_foreground_pixel);
       unload_color (f, f->output_data.x->border_pixel);
       unload_color (f, f->output_data.x->mouse_pixel);
+      
       if (f->output_data.x->scroll_bar_background_pixel != -1)
        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)
        unload_color (f, f->output_data.x->black_relief.pixel);
+
+      if (FRAME_FACE_CACHE (f))
+       free_frame_faces (f);
       
-      free_frame_faces (f);
+      x_free_gcs (f);
       XFlush (FRAME_X_DISPLAY (f));
     }
 
@@ -12456,7 +13207,8 @@ x_destroy_window (f)
     xfree (f->output_data.x->saved_menu_event);
 
   xfree (f->output_data.x);
-  f->output_data.x = 0;
+  f->output_data.x = NULL;
+  
   if (f == dpyinfo->x_focus_frame)
     dpyinfo->x_focus_frame = 0;
   if (f == dpyinfo->x_focus_event_frame)
@@ -12464,8 +13216,6 @@ x_destroy_window (f)
   if (f == dpyinfo->x_highlight_frame)
     dpyinfo->x_highlight_frame = 0;
 
-  dpyinfo->reference_count--;
-
   if (f == dpyinfo->mouse_face_mouse_frame)
     {
       dpyinfo->mouse_face_beg_row
@@ -12479,6 +13229,24 @@ x_destroy_window (f)
 
   UNBLOCK_INPUT;
 }
+
+
+/* Destroy the X window of frame F.  */
+
+void
+x_destroy_window (f)
+     struct frame *f;
+{
+  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+
+  /* If a display connection is dead, don't try sending more
+     commands to the X server.  */
+  if (dpyinfo->display != 0)
+    x_free_frame_resources (f);
+
+  dpyinfo->reference_count--;
+}
+
 \f
 /* Setting window manager hints.  */
 
@@ -12735,24 +13503,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)
-     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;
-  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 allow_scalable_fonts_p = 0;
+
+  if (size < 0)
+    {
+      allow_scalable_fonts_p = 1;
+      size = 0;
+    }
 
   patterns = Fassoc (pattern, Valternate_fontname_alist);
   if (NILP (patterns))
@@ -12770,11 +13552,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 . 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.  */
@@ -12861,10 +13644,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
-               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++ == '-')
                  {
@@ -12874,7 +13657,9 @@ x_list_fonts (f, pattern, size, maxnames)
                    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)))
@@ -12892,15 +13677,18 @@ x_list_fonts (f, pattern, size, maxnames)
                    }
                }
            }
+         
          if (!try_XLoadQueryFont)
-           XFreeFontNames (names);
+           {
+             BLOCK_INPUT;
+             XFreeFontNames (names);
+             UNBLOCK_INPUT;
+           }
        }
 
       /* 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));
+      XCDR (dpyinfo->name_list_element)
+        = Fcons (Fcons (key, list), XCDR (dpyinfo->name_list_element));
 
     label_cached:
       if (NILP (list)) continue; /* Try the remaining alternatives.  */
@@ -12924,7 +13712,7 @@ x_list_fonts (f, pattern, size, maxnames)
          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;
@@ -12947,7 +13735,9 @@ x_list_fonts (f, pattern, size, maxnames)
                    = (thisinfo->min_bounds.width == 0
                       ? make_number (0)
                       : make_number (thisinfo->max_bounds.width));
+                 BLOCK_INPUT;
                  XFreeFont (dpy, thisinfo);
+                 UNBLOCK_INPUT;
                }
              else
                /* For unknown reason, the previous call of XListFont had
@@ -13208,13 +13998,6 @@ x_load_font (f, fontname, size)
 
     fontp->size = font->max_bounds.width;
     fontp->height = FONT_HEIGHT (font);
-    {
-      /* For some font, ascent and descent in max_bounds field is
-        larger than the above value.  */
-      int max_height = font->max_bounds.ascent + font->max_bounds.descent;
-      if (max_height > fontp->height)
-       fontp->height = max_height;
-    }
 
     if (NILP (font_names))
       {
@@ -13223,20 +14006,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);
+       Lisp_Object key = Fcons (Fcons (lispy_name, make_number (256)),
+                                Qnil);
 
        XCDR (dpyinfo->name_list_element)
-         = Fcons (Fcons (Fcons (lispy_name, make_number (256)),
+         = Fcons (Fcons (key,
                          Fcons (Fcons (lispy_full_name,
                                        make_number (fontp->size)),
                                 Qnil)),
                   XCDR (dpyinfo->name_list_element));
        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);
+           XCDR (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
@@ -13593,6 +14382,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_overlay = Qnil;
   dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
   dpyinfo->mouse_face_defer = 0;
   dpyinfo->x_focus_frame = 0;
@@ -13703,7 +14493,7 @@ x_term_init (display_name, xrm_option, resource_name)
 
   {
     extern int gray_bitmap_width, gray_bitmap_height;
-    extern unsigned char *gray_bitmap_bits;
+    extern char *gray_bitmap_bits;
     dpyinfo->gray
       = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
                                     gray_bitmap_bits,
@@ -13894,7 +14684,7 @@ x_initialize ()
   estimate_mode_line_height_hook = x_estimate_mode_line_height;
 
   scroll_region_ok = 1;                /* we'll scroll partial frames */
-  char_ins_del_ok = 0;         /* just as fast to write the line */
+  char_ins_del_ok = 1;
   line_ins_del_ok = 1;         /* we'll just blt 'em */
   fast_clear_end_of_line = 1;  /* X does this well */
   memory_below_frame = 0;      /* we don't remember what scrolls
@@ -13910,7 +14700,17 @@ x_initialize ()
 
 #ifdef USE_X_TOOLKIT
   XtToolkitInitialize ();
+
   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
@@ -13978,16 +14778,32 @@ For example, if a block cursor is over a tab, it will be drawn as\n\
 wide as that tab on the display.");
   x_stretch_cursor_p = 0;
 
-  DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p,
-    "If not nil, Emacs uses toolkit scroll bars.");
+  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.");
+  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.");
 #ifdef USE_TOOLKIT_SCROLL_BARS
-  x_toolkit_scroll_bars_p = 1;
+#ifdef USE_MOTIF
+  Vx_toolkit_scroll_bars = intern ("motif");
+#elif defined HAVE_XAW3D
+  Vx_toolkit_scroll_bars = intern ("xaw3d");
+#else
+  Vx_toolkit_scroll_bars = intern ("xaw");
+#endif
 #else
-  x_toolkit_scroll_bars_p = 0;
+  Vx_toolkit_scroll_bars = Qnil;
 #endif
 
   staticpro (&last_mouse_motion_frame);
   last_mouse_motion_frame = Qnil;
 }
 
-#endif /* not HAVE_X_WINDOWS */
+#endif /* HAVE_X_WINDOWS */