(struct it): Increase size of ctl_chars to 16.
[bpt/emacs.git] / src / xterm.c
index a20acf0..be86909 100644 (file)
@@ -117,7 +117,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
@@ -257,6 +256,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,8 +399,11 @@ enum draw_glyphs_face
   DRAW_IMAGE_SUNKEN
 };
 
+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_ ((struct frame *, 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 *));
@@ -405,9 +411,11 @@ 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 *));
+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));
@@ -453,7 +461,7 @@ 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 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 *,
@@ -477,7 +485,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.  */
 
@@ -681,22 +693,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,
@@ -706,6 +708,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;
 }
 
@@ -1806,8 +1817,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
@@ -1828,8 +1838,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);
            }
@@ -2482,7 +2491,7 @@ struct glyph_string
 };
 
 
-#if 0
+#if 1
 
 static void
 x_dump_glyph_string (s)
@@ -3240,6 +3249,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
@@ -3313,29 +3326,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);
@@ -3343,7 +3505,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);
     }
 
@@ -3391,23 +3553,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
@@ -3417,7 +3576,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)
        {
@@ -3436,14 +3595,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
@@ -3467,6 +3626,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.  */
@@ -3734,7 +3909,7 @@ x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
   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);
+                left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
 
   XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
   if (raised_p)
@@ -3746,7 +3921,7 @@ x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
   /* Bottom.  */
   for (i = 0; i < width; ++i)
     XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
-              left_x + i * left_p, bottom_y - i,
+              left_x + i * left_p + 1, bottom_y - i,
               right_x + 1 - i * right_p, bottom_y - i);
   
   /* Right.  */
@@ -3830,9 +4005,9 @@ x_draw_glyph_string_box (s)
   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;
 
@@ -4208,14 +4383,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.  */
@@ -4233,7 +4417,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);
   
@@ -4247,6 +4431,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.  */
@@ -4262,6 +4448,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:
@@ -4312,12 +4511,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,
@@ -4372,8 +4572,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);
     }
   
@@ -4573,7 +4773,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];
 }
 
@@ -4633,7 +4835,8 @@ x_set_glyph_string_background_width (s, start, last_x)
   
   if (start == s->row->used[s->area]
       && s->hl == DRAW_NORMAL_TEXT
-      && ((s->area == TEXT_AREA && s->row->fill_line_p)
+      && 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;
@@ -4901,7 +5104,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
     {
@@ -5151,7 +5354,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,
@@ -5432,18 +5635,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);
          }
@@ -5644,41 +5852,11 @@ expose_frame (f, x, y, w, h)
   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);
-    }
+    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;
-
-      if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
-       expose_window (w, &intersection_rect);
-    }
+    expose_window (XWINDOW (f->menu_bar_window), &r);
 #endif /* not USE_X_TOOLKIT */
 }
 
@@ -5697,33 +5875,9 @@ expose_window_tree (w, r)
        expose_window_tree (XWINDOW (w->hchild), r);
       else if (!NILP (w->vchild))
        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);
+      else if (expose_window (w, r) == 0)
+       break;
+      w = NILP (w->next) ? NULL : XWINDOW (w->next);
     }
 }
 
@@ -5844,80 +5998,100 @@ 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.  */
 
-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;
 
   /* If window is not yet fully initialized, do nothing.  This can
      happen when toolkit scroll bars are used and a window is split.
      Reconfiguring the scroll bar will generate an expose for a newly
      created window.  */
-  if (w->current_matrix == NULL || w == updated_window)
-    return;
-
-  TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
-         r->x, r->y, r->width, r->height));
-
-  /* Convert to window coordinates.  */
-  r->x = FRAME_TO_WINDOW_PIXEL_X (w, r->x);
-  r->y = FRAME_TO_WINDOW_PIXEL_Y (w, r->y);
+  if (w->current_matrix == NULL)
+    return 1;
 
-  /* 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))
+           expose_line (w, row, &r);
+
+         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)
+       expose_line (w, row, &r);
+
+      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 1;
 }
 
 
@@ -6436,10 +6610,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;
@@ -6497,7 +6672,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;
        }
       
@@ -6629,6 +6804,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
@@ -6676,231 +6853,323 @@ 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);
+             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);
+             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);
+             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;
+
+             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);
+                                   &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;
+           }
+       }
 
-               /* Display it as active.  */
-               show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
-             }
-         }
+    check_help_echo:
 
-       /* Look for a `help-echo' property.  */
-       {
-         Lisp_Object help, overlay;
+      /* 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);
-           }
+       /* 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
-           {
-             /* Try text properties.  */
-             if ((STRINGP (glyph->object)
-                  && glyph->charpos >= 0
-                  && glyph->charpos < XSTRING (glyph->object)->size)
-                 || (BUFFERP (glyph->object)
-                     && glyph->charpos >= BEGV
-                     && glyph->charpos < ZV))
-               help = Fget_text_property (make_number (glyph->charpos),
-                                          Qhelp_echo, glyph->object);
+       if (!NILP (help))
+         {
+           help_echo = help;
+           help_echo_window = window;
+           help_echo_object = 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_text_property (make_number (pos),
+                                                  Qhelp_echo, w->buffer);
+                       if (!NILP (help))
+                         {
+                           charpos = pos;
+                           object = w->buffer;
+                         }
+                     }
+                 }
+             }
+           else if (BUFFERP (object)
+                    && charpos >= BEGV
+                    && charpos < ZV)
+             help = Fget_text_property (make_number (charpos), Qhelp_echo,
+                                        object);
            
-             if (!NILP (help))
-               {
-                 help_echo = help;
-                 help_echo_window = window;
-                 help_echo_object = glyph->object;
-                 help_echo_pos = glyph->charpos;
-               }
-           }
-       }
-         
-       BEGV = obegv;
-       ZV = ozv;
-       current_buffer = obuf;
+           if (!NILP (help))
+             {
+               help_echo = help;
+               help_echo_window = window;
+               help_echo_object = object;
+               help_echo_pos = charpos;
+             }
+         }
       }
+         
+      BEGV = obegv;
+      ZV = ozv;
+      current_buffer = obuf;
     }
+
+ set_cursor:
+  
+  if (cursor != None)
+    XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
 }
 
 static void
@@ -6950,7 +7219,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;
 
@@ -7054,7 +7323,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
@@ -7073,7 +7342,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);
@@ -7148,11 +7416,13 @@ fast_find_position (w, pos, hpos, vpos, x, y)
   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])
@@ -7227,6 +7497,88 @@ fast_find_position (w, pos, hpos, vpos, x, y)
 }
 
 
+/* 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.  */
 
@@ -7297,7 +7649,7 @@ show_mouse_face (dpyinfo, draw)
 
       if (end_hpos > start_hpos)
        {
-         row->mouse_face_p = draw == DRAW_MOUSE_FACE;
+         row->mouse_face_p = draw == DRAW_MOUSE_FACE || DRAW_IMAGE_RAISED;
          x_draw_glyphs (w, start_x, row, TEXT_AREA, 
                         start_hpos, end_hpos, draw, NULL, NULL, 0);
        }
@@ -7326,24 +7678,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 0 /* This prevents redrawing tool bar items when changing from one
-        to another while a tooltip is open, so don't do it.  */
-  if (!NILP (tip_frame))
-    return;
-#endif
+  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;
 }
 
 
@@ -7384,23 +7738,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.
@@ -7572,32 +7974,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;
@@ -7677,6 +8079,33 @@ x_window_to_scroll_bar (window_id)
 }
 
 
+#if defined USE_X_TOOLKIT && 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_X_TOOLKIT && USE_LUCID */
+
 \f
 /************************************************************************
                         Toolkit scroll bars
@@ -7929,10 +8358,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.
@@ -8074,14 +8503,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;
@@ -8223,8 +8644,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
@@ -8239,18 +8658,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)
@@ -8270,10 +8677,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 */
   {
@@ -8419,15 +8822,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 */
@@ -8523,7 +8926,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,
@@ -8627,8 +9029,9 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
   if (NILP (w->vertical_scroll_bar))
     {
       BLOCK_INPUT;
-      x_clear_area (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);
     }
@@ -8654,8 +9057,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.  */
-      x_clear_area (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)
@@ -8663,16 +9067,14 @@ 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.  */
          x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                        left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
                        height, False);
@@ -8681,6 +9083,19 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
                        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)
@@ -9584,7 +9999,8 @@ XTread_socket (sd, bufp, numchars, expected)
                               &event);
              else
                {
-                 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
+                 XSelectionRequestEvent *eventp
+                   = (XSelectionRequestEvent *) &event;
 
                  if (numchars == 0)
                    abort ();
@@ -9606,12 +10022,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);
@@ -9644,12 +10064,26 @@ XTread_socket (sd, bufp, numchars, expected)
                }
              else
                {
+#ifndef USE_TOOLKIT_SCROLL_BARS
+                 struct scroll_bar *bar;
+#endif
+#if defined USE_X_TOOLKIT && 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_X_TOOLKIT && 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);
@@ -9761,10 +10195,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))
@@ -10045,43 +10479,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.
-                  On the other hand, Motif seems to not have this
-                  problem.
-
-                  (gerd, LessTif 0.92).  */
-               
-               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)
@@ -10097,7 +10497,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;
              }
@@ -10134,8 +10534,6 @@ XTread_socket (sd, bufp, numchars, expected)
              f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
              if (f)
                {
-                 int from_menu_bar_p = 0;
-                 
                  if (f == dpyinfo->mouse_face_mouse_frame)
                    {
                      /* If we move outside the frame, then we're
@@ -10160,21 +10558,7 @@ XTread_socket (sd, bufp, numchars, expected)
                      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
                    {
@@ -10816,7 +11200,7 @@ x_erase_phys_cursor (w)
       if (cursor_glyph == NULL)
        goto mark_cursor_off;
 
-      x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
+      x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
       
       x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                    x,
@@ -10842,6 +11226,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.  */
@@ -11624,7 +12037,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
     }
@@ -11995,7 +12408,7 @@ x_set_window_size (f, change_gravity, cols, rows)
 
 #ifdef USE_X_TOOLKIT
   
-  if (f->output_data.x->widget != None)
+  if (f->output_data.x->widget != NULL)
     {
       /* The x and y position of the widget is clobbered by the
         call to XtSetValues within EmacsFrameSetCharSize.
@@ -12525,7 +12938,10 @@ x_free_frame_resources (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 */
 
@@ -13026,8 +13442,13 @@ 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.  */
@@ -13079,7 +13500,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
@@ -13724,6 +14147,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;
@@ -14041,7 +14465,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
@@ -14109,6 +14543,14 @@ 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-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\