]> code.delx.au - gnu-emacs/blobdiff - src/xterm.c
(custom-set-variables): Set options with :require
[gnu-emacs] / src / xterm.c
index 53ee5c490f9f86bfb06a82d8685587fd9db4fd98..f69d3ef0718b9fc6bb9cb93c2bd66397d82cdc7f 100644 (file)
@@ -256,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.  */
 
@@ -395,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 *));
@@ -454,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 *,
@@ -1810,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
@@ -1832,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);
            }
@@ -2836,20 +2841,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.  */
@@ -2858,7 +2849,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);
 }
 
@@ -3244,6 +3251,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
@@ -3317,29 +3328,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);
@@ -3347,7 +3507,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);
     }
 
@@ -3395,23 +3555,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
@@ -3421,7 +3578,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)
        {
@@ -3440,14 +3597,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
@@ -3471,6 +3628,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.  */
@@ -3738,7 +3911,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)
@@ -3750,7 +3923,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.  */
@@ -4212,14 +4385,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.  */
@@ -4237,7 +4419,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);
   
@@ -4331,7 +4513,8 @@ 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;
@@ -4592,7 +4775,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];
 }
 
@@ -4921,7 +5106,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
     {
@@ -5692,8 +5877,8 @@ 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
-       expose_window (w, r);
+      else if (expose_window (w, r) == 0)
+       break;
       w = NILP (w->next) ? NULL : XWINDOW (w->next);
     }
 }
@@ -5819,88 +6004,96 @@ x_phys_cursor_in_rect_p (w, r)
    coordinates in FR are frame-relative.  Call this function with
    input blocked.  */
 
-static void
+static int
 expose_window (w, fr)
      struct window *w;
      XRectangle *fr;
 {
   struct frame *f = XFRAME (w->frame);
-  struct glyph_row *row;
-  int y, yb, cursor_cleared_p;
   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;
+  if (w->current_matrix == NULL)
+    return 1;
+
+  /* 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)
+    {
+      SET_FRAME_GARBAGED (f);
+      return 0;
+    }
 
-    /* Frame-relative pixel rectangle of W.  */
+  /* 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))
-    return;
-
-  yb = window_text_bottom_y (w);
+  if (x_intersect_rectangles (fr, &wr, &r))
+    {
+      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));
+      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);
+      /* Convert to window coordinates.  */
+      r.x = FRAME_TO_WINDOW_PIXEL_X (w, r.x);
+      r.y = FRAME_TO_WINDOW_PIXEL_Y (w, r.y);
 
-  /* 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;
+      /* 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.  */
-  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)
-    {
-      expose_line (w, row, &r);
-      y += row->height;
-      ++row;
-    }
+      /* 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);
 
-  /* 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 (y1 >= yb)
+           break;
+       }
 
-  if (!w->pseudo_window_p)
-    {
-      /* Draw border between windows.  */
-      x_draw_vertical_border (w);
+      /* 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;
 }
 
 
@@ -6613,6 +6806,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
@@ -6660,31 +6855,35 @@ 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, 0);
@@ -6694,270 +6893,285 @@ note_mouse_highlight (f, x, y)
          || 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;
       object = glyph->object;
       if (!STRINGP (object) && !BUFFERP (object))
-       return;
+       goto set_cursor;
 
-      {
-       Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
-       Lisp_Object *overlay_vec = NULL;
-       int len, noverlays;
-       struct buffer *obuf;
-       int obegv, ozv;
-
-       /* If we get an out-of-range value, return now; avoid an error.  */
-       if (BUFFERP (object) && 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?  */
-       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);
-             }
+      /* If we get an out-of-range value, return now; avoid an error.  */
+      if (BUFFERP (object) && pos > BUF_Z (b))
+       goto set_cursor;
 
-           /* Sort overlays into increasing priority order.  */
-           noverlays = sort_overlays (overlay_vec, noverlays, w);
-         }
-       else
-         noverlays = 0;
-
-       /* Check mouse-face highlighting.  */
-       if (! (EQ (window, dpyinfo->mouse_face_window)
-              && vpos >= dpyinfo->mouse_face_beg_row
-              && vpos <= dpyinfo->mouse_face_end_row
-              && (vpos > dpyinfo->mouse_face_beg_row
-                  || hpos >= dpyinfo->mouse_face_beg_col)
-              && (vpos < dpyinfo->mouse_face_end_row
-                  || hpos < dpyinfo->mouse_face_end_col
-                  || dpyinfo->mouse_face_past_end))
-           /* If 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)))
-         
-         {
-           /* Clear the display of the old active region, if any.  */
-           clear_mouse_face (dpyinfo);
+      /* 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;
 
-           /* 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];
-             }
-           dpyinfo->mouse_face_overlay = overlay;
+      /* Is this char mouse-active or does it have help-echo?  */
+      position = make_number (pos);
+
+      if (BUFFERP (object))
+       {
+         /* Put all the overlays we want in a vector in overlay_vec.
+            Store the length in len.  If there are more than 10, make
+            enough space for all, and try again.  */
+         len = 10;
+         overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
+         noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
+         if (noverlays > len)
+           {
+             len = noverlays;
+             overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
+             noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
+           }
+
+         /* Sort overlays into increasing priority order.  */
+         noverlays = sort_overlays (overlay_vec, noverlays, w);
+       }
+      else
+       noverlays = 0;
+
+      same_region = (EQ (window, dpyinfo->mouse_face_window)
+                    && vpos >= dpyinfo->mouse_face_beg_row
+                    && vpos <= dpyinfo->mouse_face_end_row
+                    && (vpos > dpyinfo->mouse_face_beg_row
+                        || hpos >= dpyinfo->mouse_face_beg_col)
+                    && (vpos < dpyinfo->mouse_face_end_row
+                        || hpos < dpyinfo->mouse_face_end_col
+                        || dpyinfo->mouse_face_past_end));
+
+      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;
            
-           /* If no overlay applies, get a text property.  */
-           if (NILP (overlay))
-             mouse_face = Fget_text_property (position, Qmouse_face, object);
+         dpyinfo->mouse_face_overlay = overlay;
 
-           /* 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;
+         /* 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, 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;
+             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) && 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);
+             /* 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;
                
-               /* Record this as the current active region.  */
-               fast_find_position (w, XFASTINT (before),
+             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;
-
-               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);
-             }
-           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, 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);
-             }
-         }
+                                   &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;
+           }
+       }
 
-       /* Look for a `help-echo' property.  */
-       {
-         Lisp_Object help, overlay;
+    check_help_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);
-           }
+      /* Look for a `help-echo' property.  */
+      {
+       Lisp_Object help, overlay;
 
-         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;
+       /* 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_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);
+           /* 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 = object;
-                 help_echo_pos = 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
@@ -7466,24 +7680,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;
 }
 
 
@@ -7865,6 +8081,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
@@ -9758,7 +10001,8 @@ XTread_socket (sd, bufp, numchars, expected)
                               &event);
              else
                {
-                 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
+                 XSelectionRequestEvent *eventp
+                   = (XSelectionRequestEvent *) &event;
 
                  if (numchars == 0)
                    abort ();
@@ -9780,12 +10024,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);
@@ -9818,12 +10066,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);
@@ -10940,7 +11202,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,
@@ -10966,6 +11228,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.  */
@@ -11748,7 +12039,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
     }
@@ -12649,7 +12940,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 */
 
@@ -13150,8 +13444,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.  */
@@ -13203,7 +13502,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
@@ -14166,7 +14467,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
@@ -14234,6 +14545,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\