(describe_map): Shorten string to indicate shadowed binding.
[bpt/emacs.git] / src / xterm.c
index 2c6cb44..92b245f 100644 (file)
@@ -1,6 +1,6 @@
 /* X Communication module for terminals which understand the X protocol.
 /* X Communication module for terminals which understand the X protocol.
-   Copyright (C) 1989, 93, 94, 95, 96, 97, 98, 1999, 2000, 01, 02, 2003
-   Free Software Foundation, Inc.
+   Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+                 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 
 This file is part of GNU Emacs.
 
@@ -16,8 +16,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 /* New display code by Gerd Moellmann <gerd@gnu.org>.  */
 /* Xt features made by Fred Pierresteguy.  */
 
 /* New display code by Gerd Moellmann <gerd@gnu.org>.  */
 /* Xt features made by Fred Pierresteguy.  */
@@ -130,9 +130,7 @@ extern void _XEditResCheckMessages ();
 #ifdef HAVE_XAW3D
 #include <X11/Xaw3d/Simple.h>
 #include <X11/Xaw3d/Scrollbar.h>
 #ifdef HAVE_XAW3D
 #include <X11/Xaw3d/Simple.h>
 #include <X11/Xaw3d/Scrollbar.h>
-#define ARROW_SCROLLBAR
-#define XAW_ARROW_SCROLLBARS
-#include <X11/Xaw3d/ScrollbarP.h>
+#include <X11/Xaw3d/ThreeD.h>
 #else /* !HAVE_XAW3D */
 #include <X11/Xaw/Simple.h>
 #include <X11/Xaw/Scrollbar.h>
 #else /* !HAVE_XAW3D */
 #include <X11/Xaw/Simple.h>
 #include <X11/Xaw/Scrollbar.h>
@@ -217,6 +215,17 @@ static String Xt_default_resources[] = {0};
 
 static int toolkit_scroll_bar_interaction;
 
 
 static int toolkit_scroll_bar_interaction;
 
+/* Non-zero means to not move point as a result of clicking on a
+   frame to focus it (when focus-follows-mouse is nil).  */
+
+int x_mouse_click_focus_ignore_position;
+
+/* Non-zero timeout value means ignore next mouse click if it arrives
+   before that timeout elapses (i.e. as part of the same sequence of
+   events resulting from clicking on a frame to select it).  */
+
+static unsigned long ignore_next_mouse_click_timeout;
+
 /* Mouse movement.
 
    Formerly, we used PointerMotionHintMask (in standard_event_mask)
 /* Mouse movement.
 
    Formerly, we used PointerMotionHintMask (in standard_event_mask)
@@ -240,6 +249,7 @@ static int toolkit_scroll_bar_interaction;
 /* Where the mouse was last time we reported a mouse event.  */
 
 static XRectangle last_mouse_glyph;
 /* Where the mouse was last time we reported a mouse event.  */
 
 static XRectangle last_mouse_glyph;
+static FRAME_PTR last_mouse_glyph_frame;
 static Lisp_Object last_mouse_press_frame;
 
 /* The scroll bar in which the last X motion event occurred.
 static Lisp_Object last_mouse_press_frame;
 
 /* The scroll bar in which the last X motion event occurred.
@@ -312,11 +322,10 @@ static void x_set_window_size_1 P_ ((struct frame *, int, int, int));
 static const XColor *x_color_cells P_ ((Display *, int *));
 static void x_update_window_end P_ ((struct window *, int, int));
 void x_delete_display P_ ((struct x_display_info *));
 static const XColor *x_color_cells P_ ((Display *, int *));
 static void x_update_window_end P_ ((struct window *, int, int));
 void x_delete_display P_ ((struct x_display_info *));
-static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
-                                               unsigned));
+
 static int x_io_error_quitter P_ ((Display *));
 static int x_io_error_quitter P_ ((Display *));
-int x_catch_errors P_ ((Display *));
-void x_uncatch_errors P_ ((Display *, int));
+void x_catch_errors P_ ((Display *));
+void x_uncatch_errors P_ ((void));
 void x_lower_frame P_ ((struct frame *));
 void x_scroll_bar_clear P_ ((struct frame *));
 int x_had_errors_p P_ ((Display *));
 void x_lower_frame P_ ((struct frame *));
 void x_scroll_bar_clear P_ ((struct frame *));
 int x_had_errors_p P_ ((Display *));
@@ -336,23 +345,17 @@ static void x_clear_frame P_ ((void));
 static void frame_highlight P_ ((struct frame *));
 static void frame_unhighlight P_ ((struct frame *));
 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
 static void frame_highlight P_ ((struct frame *));
 static void frame_unhighlight P_ ((struct frame *));
 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
-static int  x_focus_changed P_ ((int,
-                                 int,
-                                 struct x_display_info *,
-                                 struct frame *,
-                                 struct input_event *,
-                                 int));
-static int  x_detect_focus_change P_ ((struct x_display_info *,
-                                       XEvent *,
-                                       struct input_event *,
-                                       int));
+static void  x_focus_changed P_ ((int, int, struct x_display_info *,
+                                 struct frame *, struct input_event *));
+static void x_detect_focus_change P_ ((struct x_display_info *,
+                                       XEvent *, struct input_event *));
 static void XTframe_rehighlight P_ ((struct frame *));
 static void x_frame_rehighlight P_ ((struct x_display_info *));
 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
                                   enum text_cursor_kinds));
 
 static void XTframe_rehighlight P_ ((struct frame *));
 static void x_frame_rehighlight P_ ((struct x_display_info *));
 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
                                   enum text_cursor_kinds));
 
-static void x_clip_to_row P_ ((struct window *, struct glyph_row *, GC));
+static void x_clip_to_row P_ ((struct window *, struct glyph_row *, int, GC));
 static void x_flush P_ ((struct frame *f));
 static void x_update_begin P_ ((struct frame *));
 static void x_update_window_begin P_ ((struct window *));
 static void x_flush P_ ((struct frame *f));
 static void x_update_begin P_ ((struct frame *));
 static void x_update_window_begin P_ ((struct window *));
@@ -364,11 +367,8 @@ static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
                                            unsigned long *));
 static void x_check_fullscreen P_ ((struct frame *));
 static void x_check_expected_move P_ ((struct frame *));
                                            unsigned long *));
 static void x_check_fullscreen P_ ((struct frame *));
 static void x_check_expected_move P_ ((struct frame *));
-static int handle_one_xevent P_ ((struct x_display_info *,
-                                  XEvent *,
-                                  struct input_event **,
-                                  int *,
-                                  int *));
+static int handle_one_xevent P_ ((struct x_display_info *, XEvent *,
+                                 int *, struct input_event *));
 
 
 /* Flush display of frame F, or of all frames if F is null.  */
 
 
 /* Flush display of frame F, or of all frames if F is null.  */
@@ -535,6 +535,12 @@ x_draw_vertical_window_border (w, x, y0, y1)
      int x, y0, y1;
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
      int x, y0, y1;
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
+  struct face *face;
+
+  face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
+  if (face)
+    XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
+                   face->foreground);
 
   XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
             f->output_data.x->normal_gc, x, y0, x, y1);
 
   XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
             f->output_data.x->normal_gc, x, y0, x, y1);
@@ -569,7 +575,9 @@ x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
                                output_cursor.vpos,
                                output_cursor.x, output_cursor.y);
 
                                output_cursor.vpos,
                                output_cursor.x, output_cursor.y);
 
-      x_draw_vertical_border (w);
+      if (draw_window_fringes (w, 1))
+       x_draw_vertical_border (w);
+
       UNBLOCK_INPUT;
     }
 
       UNBLOCK_INPUT;
     }
 
@@ -649,11 +657,7 @@ x_after_update_window_line (desired_row)
   xassert (w);
 
   if (!desired_row->mode_line_p && !w->pseudo_window_p)
   xassert (w);
 
   if (!desired_row->mode_line_p && !w->pseudo_window_p)
-    {
-      BLOCK_INPUT;
-      draw_row_fringe_bitmaps (w, desired_row);
-      UNBLOCK_INPUT;
-    }
+    desired_row->redraw_fringe_bitmaps_p = 1;
 
   /* When a window has disappeared, make sure that no rest of
      full-width rows stays visible in the internal border.  Could
 
   /* When a window has disappeared, make sure that no rest of
      full-width rows stays visible in the internal border.  Could
@@ -697,11 +701,26 @@ x_draw_fringe_bitmap (w, row, p)
   Window window = FRAME_X_WINDOW (f);
   GC gc = f->output_data.x->normal_gc;
   struct face *face = p->face;
   Window window = FRAME_X_WINDOW (f);
   GC gc = f->output_data.x->normal_gc;
   struct face *face = p->face;
+  int rowY;
 
   /* Must clip because of partially visible lines.  */
 
   /* Must clip because of partially visible lines.  */
-  x_clip_to_row (w, row, gc);
+  rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
+  if (p->y < rowY)
+    {
+      /* Adjust position of "bottom aligned" bitmap on partially
+        visible last row.  */
+      int oldY = row->y;
+      int oldVH = row->visible_height;
+      row->visible_height = p->h;
+      row->y -= rowY - p->y;
+      x_clip_to_row (w, row, -1, gc);
+      row->y = oldY;
+      row->visible_height = oldVH;
+    }
+  else
+    x_clip_to_row (w, row, -1, gc);
 
 
-  if (p->bx >= 0)
+  if (p->bx >= 0 && !p->overlay_p)
     {
       /* In case the same realized face is used for fringes and
         for something displayed in the text (e.g. face `region' on
     {
       /* In case the same realized face is used for fringes and
         for something displayed in the text (e.g. face `region' on
@@ -719,20 +738,49 @@ x_draw_fringe_bitmap (w, row, p)
        XSetForeground (display, face->gc, face->foreground);
     }
 
        XSetForeground (display, face->gc, face->foreground);
     }
 
-  if (p->which != NO_FRINGE_BITMAP)
+  if (p->which)
     {
     {
-      unsigned char *bits = fringe_bitmaps[p->which].bits + p->dh;
-      Pixmap pixmap;
+      unsigned char *bits;
+      Pixmap pixmap, clipmask = (Pixmap) 0;
       int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
       int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
+      XGCValues gcv;
+
+      if (p->wd > 8)
+       bits = (unsigned char *)(p->bits + p->dh);
+      else
+       bits = (unsigned char *)p->bits + p->dh;
 
       /* Draw the bitmap.  I believe these small pixmaps can be cached
         by the server.  */
       pixmap = XCreatePixmapFromBitmapData (display, window, bits, p->wd, p->h,
 
       /* Draw the bitmap.  I believe these small pixmaps can be cached
         by the server.  */
       pixmap = XCreatePixmapFromBitmapData (display, window, bits, p->wd, p->h,
-                                           face->foreground,
+                                           (p->cursor_p
+                                            ? (p->overlay_p ? face->background
+                                               : f->output_data.x->cursor_pixel)
+                                            : face->foreground),
                                            face->background, depth);
                                            face->background, depth);
+
+      if (p->overlay_p)
+       {
+         clipmask = XCreatePixmapFromBitmapData (display,
+                                                 FRAME_X_DISPLAY_INFO (f)->root_window,
+                                                 bits, p->wd, p->h,
+                                                 1, 0, 1);
+         gcv.clip_mask = clipmask;
+         gcv.clip_x_origin = p->x;
+         gcv.clip_y_origin = p->y;
+         XChangeGC (display, gc, GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv);
+       }
+
       XCopyArea (display, pixmap, window, gc, 0, 0,
                 p->wd, p->h, p->x, p->y);
       XFreePixmap (display, pixmap);
       XCopyArea (display, pixmap, window, gc, 0, 0,
                 p->wd, p->h, p->x, p->y);
       XFreePixmap (display, pixmap);
+
+      if (p->overlay_p)
+       {
+         gcv.clip_mask = (Pixmap) 0;
+         XChangeGC (display, gc, GCClipMask, &gcv);
+         XFreePixmap (display, clipmask);
+       }
     }
 
   XSetClipMask (display, gc, None);
     }
 
   XSetClipMask (display, gc, None);
@@ -862,6 +910,7 @@ x_encode_char (c, char2b, font_info, two_byte_p)
       /* It's a program.  */
       struct ccl_program *ccl = font_info->font_encoder;
 
       /* It's a program.  */
       struct ccl_program *ccl = font_info->font_encoder;
 
+      check_ccl_update (ccl);
       if (CHARSET_DIMENSION (charset) == 1)
        {
          ccl->reg[0] = charset;
       if (CHARSET_DIMENSION (charset) == 1)
        {
          ccl->reg[0] = charset;
@@ -936,7 +985,8 @@ static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
                                           int, int, int));
 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
                                           int, int, int));
 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
-                                   int, int, int, int, XRectangle *));
+                                   int, int, int, int, int, int,
+                                   XRectangle *));
 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
                                 int, int, int, XRectangle *));
 
 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
                                 int, int, int, XRectangle *));
 
@@ -1249,7 +1299,7 @@ x_draw_glyph_string_foreground (s)
         XDrawImageString is usually faster than XDrawString.)  Always
         use XDrawImageString when drawing the cursor so that there is
         no chance that characters under a box cursor are invisible.  */
         XDrawImageString is usually faster than XDrawString.)  Always
         use XDrawImageString when drawing the cursor so that there is
         no chance that characters under a box cursor are invisible.  */
-      if (s->for_overlaps_p
+      if (s->for_overlaps
          || (s->background_filled_p && s->hl != DRAW_CURSOR))
        {
          /* Draw characters with 16-bit or 8-bit functions.  */
          || (s->background_filled_p && s->hl != DRAW_CURSOR))
        {
          /* Draw characters with 16-bit or 8-bit functions.  */
@@ -1974,9 +2024,10 @@ x_setup_relief_colors (s)
 
 static void
 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
 
 static void
 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
-                   raised_p, left_p, right_p, clip_rect)
+                   raised_p, top_p, bot_p, left_p, right_p, clip_rect)
      struct frame *f;
      struct frame *f;
-     int left_x, top_y, right_x, bottom_y, width, left_p, right_p, raised_p;
+     int left_x, top_y, right_x, bottom_y, width;
+     int top_p, bot_p, left_p, right_p, raised_p;
      XRectangle *clip_rect;
 {
   Display *dpy = FRAME_X_DISPLAY (f);
      XRectangle *clip_rect;
 {
   Display *dpy = FRAME_X_DISPLAY (f);
@@ -1991,10 +2042,11 @@ x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
   XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
 
   /* Top.  */
   XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
 
   /* Top.  */
-  for (i = 0; i < width; ++i)
-    XDrawLine (dpy, window, gc,
-              left_x + i * left_p, top_y + i,
-              right_x + 1 - i * right_p, top_y + i);
+  if (top_p)
+    for (i = 0; i < width; ++i)
+      XDrawLine (dpy, window, gc,
+                left_x + i * left_p, top_y + i,
+                right_x + 1 - i * right_p, top_y + i);
 
   /* Left.  */
   if (left_p)
 
   /* Left.  */
   if (left_p)
@@ -2010,10 +2062,11 @@ x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
   XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
 
   /* Bottom.  */
   XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
 
   /* Bottom.  */
-  for (i = 0; i < width; ++i)
-    XDrawLine (dpy, window, gc,
-              left_x + i * left_p, bottom_y - i,
-              right_x + 1 - i * right_p, bottom_y - i);
+  if (bot_p)
+    for (i = 0; i < width; ++i)
+      XDrawLine (dpy, window, gc,
+                left_x + i * left_p, bottom_y - i,
+                right_x + 1 - i * right_p, bottom_y - i);
 
   /* Right.  */
   if (right_p)
 
   /* Right.  */
   if (right_p)
@@ -2079,15 +2132,9 @@ x_draw_glyph_string_box (s)
   struct glyph *last_glyph;
   XRectangle clip_rect;
 
   struct glyph *last_glyph;
   XRectangle clip_rect;
 
-  last_x = window_box_right (s->w, s->area);
-  if (s->row->full_width_p
-      && !s->w->pseudo_window_p)
-    {
-      last_x += WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (s->w);
-      if (s->area != RIGHT_MARGIN_AREA
-         || WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (s->w))
-       last_x += WINDOW_RIGHT_FRINGE_WIDTH (s->w);
-    }
+  last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
+           ? WINDOW_RIGHT_EDGE_X (s->w)
+           : window_box_right (s->w, s->area));
 
   /* The glyph that may have a right box line.  */
   last_glyph = (s->cmp || s->img
 
   /* The glyph that may have a right box line.  */
   last_glyph = (s->cmp || s->img
@@ -2121,7 +2168,7 @@ x_draw_glyph_string_box (s)
     {
       x_setup_relief_colors (s);
       x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
     {
       x_setup_relief_colors (s);
       x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
-                         width, raised_p, left_p, right_p, &clip_rect);
+                         width, raised_p, 1, 1, left_p, right_p, &clip_rect);
     }
 }
 
     }
 }
 
@@ -2132,21 +2179,22 @@ static void
 x_draw_image_foreground (s)
      struct glyph_string *s;
 {
 x_draw_image_foreground (s)
      struct glyph_string *s;
 {
-  int x;
-  int y = s->ybase - image_ascent (s->img, s->face);
+  int x = s->x;
+  int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
 
   /* If first glyph of S has a left box line, start drawing it to the
      right of that line.  */
   if (s->face->box != FACE_NO_BOX
 
   /* If first glyph of S has a left box line, start drawing it to the
      right of that line.  */
   if (s->face->box != FACE_NO_BOX
-      && s->first_glyph->left_box_line_p)
-    x = s->x + abs (s->face->box_line_width);
-  else
-    x = s->x;
+      && s->first_glyph->left_box_line_p
+      && s->slice.x == 0)
+    x += abs (s->face->box_line_width);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
-  x += s->img->hmargin;
-  y += s->img->vmargin;
+  if (s->slice.x == 0)
+    x += s->img->hmargin;
+  if (s->slice.y == 0)
+    y += s->img->vmargin;
 
   if (s->img->pixmap)
     {
 
   if (s->img->pixmap)
     {
@@ -2171,11 +2219,12 @@ x_draw_image_foreground (s)
          get_glyph_string_clip_rect (s, &clip_rect);
          image_rect.x = x;
          image_rect.y = y;
          get_glyph_string_clip_rect (s, &clip_rect);
          image_rect.x = x;
          image_rect.y = y;
-         image_rect.width = s->img->width;
-         image_rect.height = s->img->height;
+         image_rect.width = s->slice.width;
+         image_rect.height = s->slice.height;
          if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
            XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
          if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
            XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
-                      r.x - x, r.y - y, r.width, r.height, r.x, r.y);
+                      s->slice.x + r.x - x, s->slice.y + r.y - y,
+                      r.width, r.height, r.x, r.y);
        }
       else
        {
        }
       else
        {
@@ -2184,11 +2233,12 @@ x_draw_image_foreground (s)
          get_glyph_string_clip_rect (s, &clip_rect);
          image_rect.x = x;
          image_rect.y = y;
          get_glyph_string_clip_rect (s, &clip_rect);
          image_rect.x = x;
          image_rect.y = y;
-         image_rect.width = s->img->width;
-         image_rect.height = s->img->height;
+         image_rect.width = s->slice.width;
+         image_rect.height = s->slice.height;
          if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
            XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
          if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
            XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
-                      r.x - x, r.y - y, r.width, r.height, r.x, r.y);
+                      s->slice.x + r.x - x, s->slice.y + r.y - y,
+                      r.width, r.height, r.x, r.y);
 
          /* When the image has a mask, we can expect that at
             least part of a mouse highlight or a block cursor will
 
          /* When the image has a mask, we can expect that at
             least part of a mouse highlight or a block cursor will
@@ -2200,15 +2250,17 @@ x_draw_image_foreground (s)
            {
              int r = s->img->relief;
              if (r < 0) r = -r;
            {
              int r = s->img->relief;
              if (r < 0) r = -r;
-             XDrawRectangle (s->display, s->window, s->gc, x - r, y - r,
-                             s->img->width + r*2 - 1, s->img->height + r*2 - 1);
+             XDrawRectangle (s->display, s->window, s->gc,
+                             x - r, y - r,
+                             s->slice.width + r*2 - 1,
+                             s->slice.height + r*2 - 1);
            }
        }
     }
   else
     /* Draw a rectangle if image could not be loaded.  */
     XDrawRectangle (s->display, s->window, s->gc, x, y,
            }
        }
     }
   else
     /* Draw a rectangle if image could not be loaded.  */
     XDrawRectangle (s->display, s->window, s->gc, x, y,
-                   s->img->width - 1, s->img->height - 1);
+                   s->slice.width - 1, s->slice.height - 1);
 }
 
 
 }
 
 
@@ -2220,21 +2272,22 @@ x_draw_image_relief (s)
 {
   int x0, y0, x1, y1, thick, raised_p;
   XRectangle r;
 {
   int x0, y0, x1, y1, thick, raised_p;
   XRectangle r;
-  int x;
-  int y = s->ybase - image_ascent (s->img, s->face);
+  int x = s->x;
+  int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
 
   /* If first glyph of S has a left box line, start drawing it to the
      right of that line.  */
   if (s->face->box != FACE_NO_BOX
 
   /* If first glyph of S has a left box line, start drawing it to the
      right of that line.  */
   if (s->face->box != FACE_NO_BOX
-      && s->first_glyph->left_box_line_p)
-    x = s->x + abs (s->face->box_line_width);
-  else
-    x = s->x;
+      && s->first_glyph->left_box_line_p
+      && s->slice.x == 0)
+    x += abs (s->face->box_line_width);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
-  x += s->img->hmargin;
-  y += s->img->vmargin;
+  if (s->slice.x == 0)
+    x += s->img->hmargin;
+  if (s->slice.y == 0)
+    y += s->img->vmargin;
 
   if (s->hl == DRAW_IMAGE_SUNKEN
       || s->hl == DRAW_IMAGE_RAISED)
 
   if (s->hl == DRAW_IMAGE_SUNKEN
       || s->hl == DRAW_IMAGE_RAISED)
@@ -2250,12 +2303,17 @@ x_draw_image_relief (s)
 
   x0 = x - thick;
   y0 = y - thick;
 
   x0 = x - thick;
   y0 = y - thick;
-  x1 = x + s->img->width + thick - 1;
-  y1 = y + s->img->height + thick - 1;
+  x1 = x + s->slice.width + thick - 1;
+  y1 = y + s->slice.height + thick - 1;
 
   x_setup_relief_colors (s);
   get_glyph_string_clip_rect (s, &r);
 
   x_setup_relief_colors (s);
   get_glyph_string_clip_rect (s, &r);
-  x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
+  x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
+                     s->slice.y == 0,
+                     s->slice.y + s->slice.height == s->img->height,
+                     s->slice.x == 0,
+                     s->slice.x + s->slice.width == s->img->width,
+                     &r);
 }
 
 
 }
 
 
@@ -2266,21 +2324,22 @@ x_draw_image_foreground_1 (s, pixmap)
      struct glyph_string *s;
      Pixmap pixmap;
 {
      struct glyph_string *s;
      Pixmap pixmap;
 {
-  int x;
-  int y = s->ybase - s->y - image_ascent (s->img, s->face);
+  int x = 0;
+  int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
 
   /* If first glyph of S has a left box line, start drawing it to the
      right of that line.  */
   if (s->face->box != FACE_NO_BOX
 
   /* If first glyph of S has a left box line, start drawing it to the
      right of that line.  */
   if (s->face->box != FACE_NO_BOX
-      && s->first_glyph->left_box_line_p)
-    x = abs (s->face->box_line_width);
-  else
-    x = 0;
+      && s->first_glyph->left_box_line_p
+      && s->slice.x == 0)
+    x += abs (s->face->box_line_width);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
-  x += s->img->hmargin;
-  y += s->img->vmargin;
+  if (s->slice.x == 0)
+    x += s->img->hmargin;
+  if (s->slice.y == 0)
+    y += s->img->vmargin;
 
   if (s->img->pixmap)
     {
 
   if (s->img->pixmap)
     {
@@ -2296,19 +2355,21 @@ x_draw_image_foreground_1 (s, pixmap)
          XGCValues xgcv;
 
          xgcv.clip_mask = s->img->mask;
          XGCValues xgcv;
 
          xgcv.clip_mask = s->img->mask;
-         xgcv.clip_x_origin = x;
-         xgcv.clip_y_origin = y;
+         xgcv.clip_x_origin = x - s->slice.x;
+         xgcv.clip_y_origin = y - s->slice.y;
          xgcv.function = GXcopy;
          XChangeGC (s->display, s->gc, mask, &xgcv);
 
          XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
          xgcv.function = GXcopy;
          XChangeGC (s->display, s->gc, mask, &xgcv);
 
          XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
-                    0, 0, s->img->width, s->img->height, x, y);
+                    s->slice.x, s->slice.y,
+                    s->slice.width, s->slice.height, x, y);
          XSetClipMask (s->display, s->gc, None);
        }
       else
        {
          XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
          XSetClipMask (s->display, s->gc, None);
        }
       else
        {
          XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
-                    0, 0, s->img->width, s->img->height, x, y);
+                    s->slice.x, s->slice.y,
+                    s->slice.width, s->slice.height, x, y);
 
          /* When the image has a mask, we can expect that at
             least part of a mouse highlight or a block cursor will
 
          /* When the image has a mask, we can expect that at
             least part of a mouse highlight or a block cursor will
@@ -2321,14 +2382,15 @@ x_draw_image_foreground_1 (s, pixmap)
              int r = s->img->relief;
              if (r < 0) r = -r;
              XDrawRectangle (s->display, s->window, s->gc, x - r, y - r,
              int r = s->img->relief;
              if (r < 0) r = -r;
              XDrawRectangle (s->display, s->window, s->gc, x - r, y - r,
-                             s->img->width + r*2 - 1, s->img->height + r*2 - 1);
+                             s->slice.width + r*2 - 1,
+                             s->slice.height + r*2 - 1);
            }
        }
     }
   else
     /* Draw a rectangle if image could not be loaded.  */
     XDrawRectangle (s->display, pixmap, s->gc, x, y,
            }
        }
     }
   else
     /* Draw a rectangle if image could not be loaded.  */
     XDrawRectangle (s->display, pixmap, s->gc, x, y,
-                   s->img->width - 1, s->img->height - 1);
+                   s->slice.width - 1, s->slice.height - 1);
 }
 
 
 }
 
 
@@ -2370,33 +2432,28 @@ static void
 x_draw_image_glyph_string (s)
      struct glyph_string *s;
 {
 x_draw_image_glyph_string (s)
      struct glyph_string *s;
 {
-  int x, y;
   int box_line_hwidth = abs (s->face->box_line_width);
   int box_line_vwidth = max (s->face->box_line_width, 0);
   int height;
   Pixmap pixmap = None;
 
   int box_line_hwidth = abs (s->face->box_line_width);
   int box_line_vwidth = max (s->face->box_line_width, 0);
   int height;
   Pixmap pixmap = None;
 
-  height = s->height - 2 * box_line_vwidth;
-
+  height = s->height;
+  if (s->slice.y == 0)
+    height -= box_line_vwidth;
+  if (s->slice.y + s->slice.height >= s->img->height)
+    height -= box_line_vwidth;
 
   /* Fill background with face under the image.  Do it only if row is
      taller than image or if image has a clip mask to reduce
      flickering.  */
   s->stippled_p = s->face->stipple != 0;
 
   /* Fill background with face under the image.  Do it only if row is
      taller than image or if image has a clip mask to reduce
      flickering.  */
   s->stippled_p = s->face->stipple != 0;
-  if (height > s->img->height
+  if (height > s->slice.height
       || s->img->hmargin
       || s->img->vmargin
       || s->img->mask
       || s->img->pixmap == 0
       || s->width != s->background_width)
     {
       || s->img->hmargin
       || s->img->vmargin
       || s->img->mask
       || s->img->pixmap == 0
       || s->width != s->background_width)
     {
-      if (box_line_hwidth && s->first_glyph->left_box_line_p)
-       x = s->x + box_line_hwidth;
-      else
-       x = s->x;
-
-      y = s->y + box_line_vwidth;
-
       if (s->img->mask)
        {
          /* Create a pixmap as large as the glyph string.  Fill it
       if (s->img->mask)
        {
          /* Create a pixmap as large as the glyph string.  Fill it
@@ -2435,7 +2492,19 @@ x_draw_image_glyph_string (s)
            }
        }
       else
            }
        }
       else
-       x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
+       {
+         int x = s->x;
+         int y = s->y;
+
+         if (s->first_glyph->left_box_line_p
+             && s->slice.x == 0)
+           x += box_line_hwidth;
+
+         if (s->slice.y == 0)
+           y += box_line_vwidth;
+
+         x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
+       }
 
       s->background_filled_p = 1;
     }
 
       s->background_filled_p = 1;
     }
@@ -2535,7 +2604,7 @@ x_draw_glyph_string (s)
   /* If S draws into the background of its successor, draw the
      background of the successor first so that S can draw into it.
      This makes S->next use XDrawString instead of XDrawImageString.  */
   /* If S draws into the background of its successor, draw the
      background of the successor first so that S can draw into it.
      This makes S->next use XDrawString instead of XDrawImageString.  */
-  if (s->next && s->right_overhang && !s->for_overlaps_p)
+  if (s->next && s->right_overhang && !s->for_overlaps)
     {
       xassert (s->next->img == NULL);
       x_set_glyph_string_gc (s->next);
     {
       xassert (s->next->img == NULL);
       x_set_glyph_string_gc (s->next);
@@ -2548,7 +2617,7 @@ x_draw_glyph_string (s)
 
   /* Draw relief (if any) in advance for char/composition so that the
      glyph string can be drawn over it.  */
 
   /* Draw relief (if any) in advance for char/composition so that the
      glyph string can be drawn over it.  */
-  if (!s->for_overlaps_p
+  if (!s->for_overlaps
       && s->face->box != FACE_NO_BOX
       && (s->first_glyph->type == CHAR_GLYPH
          || s->first_glyph->type == COMPOSITE_GLYPH))
       && s->face->box != FACE_NO_BOX
       && (s->first_glyph->type == CHAR_GLYPH
          || s->first_glyph->type == COMPOSITE_GLYPH))
@@ -2574,7 +2643,7 @@ x_draw_glyph_string (s)
       break;
 
     case CHAR_GLYPH:
       break;
 
     case CHAR_GLYPH:
-      if (s->for_overlaps_p)
+      if (s->for_overlaps)
        s->background_filled_p = 1;
       else
        x_draw_glyph_string_background (s, 0);
        s->background_filled_p = 1;
       else
        x_draw_glyph_string_background (s, 0);
@@ -2582,7 +2651,7 @@ x_draw_glyph_string (s)
       break;
 
     case COMPOSITE_GLYPH:
       break;
 
     case COMPOSITE_GLYPH:
-      if (s->for_overlaps_p || s->gidx > 0)
+      if (s->for_overlaps || s->gidx > 0)
        s->background_filled_p = 1;
       else
        x_draw_glyph_string_background (s, 1);
        s->background_filled_p = 1;
       else
        x_draw_glyph_string_background (s, 1);
@@ -2593,7 +2662,7 @@ x_draw_glyph_string (s)
       abort ();
     }
 
       abort ();
     }
 
-  if (!s->for_overlaps_p)
+  if (!s->for_overlaps)
     {
       /* Draw underline.  */
       if (s->face->underline_p)
     {
       /* Draw underline.  */
       if (s->face->underline_p)
@@ -2753,10 +2822,6 @@ x_clear_frame ()
 
   XFlush (FRAME_X_DISPLAY (f));
 
 
   XFlush (FRAME_X_DISPLAY (f));
 
-#ifdef USE_GTK
-  xg_frame_cleared (f);
-#endif
-
   UNBLOCK_INPUT;
 }
 
   UNBLOCK_INPUT;
 }
 
@@ -3124,20 +3189,16 @@ x_new_focus_frame (dpyinfo, frame)
 
 /* Handle FocusIn and FocusOut state changes for FRAME.
    If FRAME has focus and there exists more than one frame, puts
 
 /* Handle FocusIn and FocusOut state changes for FRAME.
    If FRAME has focus and there exists more than one frame, puts
-   a FOCUS_IN_EVENT into BUFP.
-   Returns number of events inserted into BUFP. */
+   a FOCUS_IN_EVENT into *BUFP.  */
 
 
-static int
-x_focus_changed (type, state, dpyinfo, frame, bufp, numchars)
+static void
+x_focus_changed (type, state, dpyinfo, frame, bufp)
      int type;
      int state;
      struct x_display_info *dpyinfo;
      struct frame *frame;
      struct input_event *bufp;
      int type;
      int state;
      struct x_display_info *dpyinfo;
      struct frame *frame;
      struct input_event *bufp;
-     int numchars;
 {
 {
-  int nr_events = 0;
-
   if (type == FocusIn)
     {
       if (dpyinfo->x_focus_event_frame != frame)
   if (type == FocusIn)
     {
       if (dpyinfo->x_focus_event_frame != frame)
@@ -3147,17 +3208,12 @@ x_focus_changed (type, state, dpyinfo, frame, bufp, numchars)
 
           /* Don't stop displaying the initial startup message
              for a switch-frame event we don't need.  */
 
           /* Don't stop displaying the initial startup message
              for a switch-frame event we don't need.  */
-          if (numchars > 0
-              && GC_NILP (Vterminal_frame)
+          if (GC_NILP (Vterminal_frame)
               && GC_CONSP (Vframe_list)
               && !GC_NILP (XCDR (Vframe_list)))
             {
               bufp->kind = FOCUS_IN_EVENT;
               XSETFRAME (bufp->frame_or_window, frame);
               && GC_CONSP (Vframe_list)
               && !GC_NILP (XCDR (Vframe_list)))
             {
               bufp->kind = FOCUS_IN_EVENT;
               XSETFRAME (bufp->frame_or_window, frame);
-              bufp->arg = Qnil;
-              ++bufp;
-              numchars--;
-              ++nr_events;
             }
         }
 
             }
         }
 
@@ -3183,27 +3239,24 @@ x_focus_changed (type, state, dpyinfo, frame, bufp, numchars)
         XUnsetICFocus (FRAME_XIC (frame));
 #endif
     }
         XUnsetICFocus (FRAME_XIC (frame));
 #endif
     }
-
-  return nr_events;
 }
 
 /* The focus may have changed.  Figure out if it is a real focus change,
    by checking both FocusIn/Out and Enter/LeaveNotify events.
 
 }
 
 /* The focus may have changed.  Figure out if it is a real focus change,
    by checking both FocusIn/Out and Enter/LeaveNotify events.
 
-   Returns number of events inserted into BUFP. */
+   Returns FOCUS_IN_EVENT event in *BUFP. */
 
 
-static int
-x_detect_focus_change (dpyinfo, event, bufp, numchars)
+static void
+x_detect_focus_change (dpyinfo, event, bufp)
      struct x_display_info *dpyinfo;
      XEvent *event;
      struct input_event *bufp;
      struct x_display_info *dpyinfo;
      XEvent *event;
      struct input_event *bufp;
-     int numchars;
 {
   struct frame *frame;
 {
   struct frame *frame;
-  int nr_events = 0;
 
   frame = x_any_window_to_frame (dpyinfo, event->xany.window);
 
   frame = x_any_window_to_frame (dpyinfo, event->xany.window);
-  if (! frame) return nr_events;
+  if (! frame)
+    return;
 
   switch (event->type)
     {
 
   switch (event->type)
     {
@@ -3217,29 +3270,20 @@ x_detect_focus_change (dpyinfo, event, bufp, numchars)
         if (event->xcrossing.detail != NotifyInferior
             && event->xcrossing.focus
             && ! (focus_state & FOCUS_EXPLICIT))
         if (event->xcrossing.detail != NotifyInferior
             && event->xcrossing.focus
             && ! (focus_state & FOCUS_EXPLICIT))
-          nr_events = x_focus_changed ((event->type == EnterNotify
-                                        ? FocusIn : FocusOut),
-                                       FOCUS_IMPLICIT,
-                                       dpyinfo,
-                                       frame,
-                                       bufp,
-                                       numchars);
+          x_focus_changed ((event->type == EnterNotify ? FocusIn : FocusOut),
+                          FOCUS_IMPLICIT,
+                          dpyinfo, frame, bufp);
       }
       break;
 
     case FocusIn:
     case FocusOut:
       }
       break;
 
     case FocusIn:
     case FocusOut:
-      nr_events = x_focus_changed (event->type,
-                                   (event->xfocus.detail == NotifyPointer
-                                    ? FOCUS_IMPLICIT : FOCUS_EXPLICIT),
-                                   dpyinfo,
-                                   frame,
-                                   bufp,
-                                   numchars);
+      x_focus_changed (event->type,
+                      (event->xfocus.detail == NotifyPointer ?
+                       FOCUS_IMPLICIT : FOCUS_EXPLICIT),
+                      dpyinfo, frame, bufp);
       break;
     }
       break;
     }
-
-  return nr_events;
 }
 
 
 }
 
 
@@ -3333,12 +3377,14 @@ x_find_modifier_meanings (dpyinfo)
      Alt keysyms are on.  */
   {
     int row, col;      /* The row and column in the modifier table.  */
      Alt keysyms are on.  */
   {
     int row, col;      /* The row and column in the modifier table.  */
+    int found_alt_or_meta;
 
     for (row = 3; row < 8; row++)
 
     for (row = 3; row < 8; row++)
+    {
+      found_alt_or_meta = 0;
       for (col = 0; col < mods->max_keypermod; col++)
        {
       for (col = 0; col < mods->max_keypermod; col++)
        {
-         KeyCode code
-           = mods->modifiermap[(row * mods->max_keypermod) + col];
+         KeyCode code = mods->modifiermap[(row * mods->max_keypermod) + col];
 
          /* Zeroes are used for filler.  Skip them.  */
          if (code == 0)
 
          /* Zeroes are used for filler.  Skip them.  */
          if (code == 0)
@@ -3356,33 +3402,44 @@ x_find_modifier_meanings (dpyinfo)
                  {
                  case XK_Meta_L:
                  case XK_Meta_R:
                  {
                  case XK_Meta_L:
                  case XK_Meta_R:
+                   found_alt_or_meta = 1;
                    dpyinfo->meta_mod_mask |= (1 << row);
                    break;
 
                  case XK_Alt_L:
                  case XK_Alt_R:
                    dpyinfo->meta_mod_mask |= (1 << row);
                    break;
 
                  case XK_Alt_L:
                  case XK_Alt_R:
+                   found_alt_or_meta = 1;
                    dpyinfo->alt_mod_mask |= (1 << row);
                    break;
 
                  case XK_Hyper_L:
                  case XK_Hyper_R:
                    dpyinfo->alt_mod_mask |= (1 << row);
                    break;
 
                  case XK_Hyper_L:
                  case XK_Hyper_R:
-                   dpyinfo->hyper_mod_mask |= (1 << row);
+                   if (!found_alt_or_meta)
+                     dpyinfo->hyper_mod_mask |= (1 << row);
+                   code_col = syms_per_code;
+                   col = mods->max_keypermod;
                    break;
 
                  case XK_Super_L:
                  case XK_Super_R:
                    break;
 
                  case XK_Super_L:
                  case XK_Super_R:
-                   dpyinfo->super_mod_mask |= (1 << row);
+                   if (!found_alt_or_meta)
+                     dpyinfo->super_mod_mask |= (1 << row);
+                   code_col = syms_per_code;
+                   col = mods->max_keypermod;
                    break;
 
                  case XK_Shift_Lock:
                    /* Ignore this if it's not on the lock modifier.  */
                    break;
 
                  case XK_Shift_Lock:
                    /* Ignore this if it's not on the lock modifier.  */
-                   if ((1 << row) == LockMask)
+                   if (!found_alt_or_meta && ((1 << row) == LockMask))
                      dpyinfo->shift_lock_mask = LockMask;
                      dpyinfo->shift_lock_mask = LockMask;
+                   code_col = syms_per_code;
+                   col = mods->max_keypermod;
                    break;
                  }
              }
          }
        }
                    break;
                  }
              }
          }
        }
+    }
   }
 
   /* If we couldn't find any meta keys, accept any alt keys as meta keys.  */
   }
 
   /* If we couldn't find any meta keys, accept any alt keys as meta keys.  */
@@ -3406,7 +3463,7 @@ x_find_modifier_meanings (dpyinfo)
 /* Convert between the modifier bits X uses and the modifier bits
    Emacs uses.  */
 
 /* Convert between the modifier bits X uses and the modifier bits
    Emacs uses.  */
 
-static unsigned int
+unsigned int
 x_x_to_emacs_modifiers (dpyinfo, state)
      struct x_display_info *dpyinfo;
      unsigned int state;
 x_x_to_emacs_modifiers (dpyinfo, state)
      struct x_display_info *dpyinfo;
      unsigned int state;
@@ -3525,7 +3582,7 @@ construct_mouse_click (result, event, f)
 static XMotionEvent last_mouse_motion_event;
 static Lisp_Object last_mouse_motion_frame;
 
 static XMotionEvent last_mouse_motion_event;
 static Lisp_Object last_mouse_motion_frame;
 
-static void
+static int
 note_mouse_movement (frame, event)
      FRAME_PTR frame;
      XMotionEvent *event;
 note_mouse_movement (frame, event)
      FRAME_PTR frame;
      XMotionEvent *event;
@@ -3534,23 +3591,36 @@ note_mouse_movement (frame, event)
   last_mouse_motion_event = *event;
   XSETFRAME (last_mouse_motion_frame, frame);
 
   last_mouse_motion_event = *event;
   XSETFRAME (last_mouse_motion_frame, frame);
 
+  if (!FRAME_X_OUTPUT (frame))
+    return 0;
+
   if (event->window != FRAME_X_WINDOW (frame))
     {
       frame->mouse_moved = 1;
       last_mouse_scroll_bar = Qnil;
       note_mouse_highlight (frame, -1, -1);
   if (event->window != FRAME_X_WINDOW (frame))
     {
       frame->mouse_moved = 1;
       last_mouse_scroll_bar = Qnil;
       note_mouse_highlight (frame, -1, -1);
+      last_mouse_glyph_frame = 0;
+      return 1;
     }
 
     }
 
+
   /* Has the mouse moved off the glyph it was on at the last sighting?  */
   /* Has the mouse moved off the glyph it was on at the last sighting?  */
-  else if (event->x < last_mouse_glyph.x
-          || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
-          || event->y < last_mouse_glyph.y
-          || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
+  if (frame != last_mouse_glyph_frame
+      || event->x < last_mouse_glyph.x
+      || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
+      || event->y < last_mouse_glyph.y
+      || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
     {
       frame->mouse_moved = 1;
       last_mouse_scroll_bar = Qnil;
       note_mouse_highlight (frame, event->x, event->y);
     {
       frame->mouse_moved = 1;
       last_mouse_scroll_bar = Qnil;
       note_mouse_highlight (frame, event->x, event->y);
+      /* Remember which glyph we're now on.  */
+      remember_mouse_glyph (frame, event->x, event->y, &last_mouse_glyph);
+      last_mouse_glyph_frame = frame;
+      return 1;
     }
     }
+
+  return 0;
 }
 
 \f
 }
 
 \f
@@ -3569,52 +3639,6 @@ redo_mouse_highlight ()
 }
 
 
 }
 
 
-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 found = 0;
-
-  window = window_from_coordinates (f, x, y, 0, &x, &y, 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;
-
-      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.
 
 /* Return the current position of the mouse.
    *FP should be a frame which indicates which display to ask about.
@@ -3695,7 +3719,6 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
        Window win, child;
        int win_x, win_y;
        int parent_x = 0, parent_y = 0;
        Window win, child;
        int win_x, win_y;
        int parent_x = 0, parent_y = 0;
-       int count;
 
        win = root;
 
 
        win = root;
 
@@ -3703,7 +3726,7 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
           structure is changing at the same time this function
           is running.  So at least we must not crash from them.  */
 
           structure is changing at the same time this function
           is running.  So at least we must not crash from them.  */
 
-       count = x_catch_errors (FRAME_X_DISPLAY (*fp));
+       x_catch_errors (FRAME_X_DISPLAY (*fp));
 
        if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
            && FRAME_LIVE_P (last_mouse_frame))
 
        if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
            && FRAME_LIVE_P (last_mouse_frame))
@@ -3772,7 +3795,7 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
        if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
          f1 = 0;
 
        if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
          f1 = 0;
 
-       x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
+       x_uncatch_errors ();
 
        /* If not, is it one of our scroll bars?  */
        if (! f1)
 
        /* If not, is it one of our scroll bars?  */
        if (! f1)
@@ -3802,32 +3825,8 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
               on it, i.e. into the same rectangles that matrices on
               the frame are divided into.  */
 
               on it, i.e. into the same rectangles that matrices on
               the frame are divided into.  */
 
-           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;
-
-               /* Arrange for the division in FRAME_PIXEL_X_TO_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;
-             }
+           remember_mouse_glyph (f1, win_x, win_y, &last_mouse_glyph);
+           last_mouse_glyph_frame = f1;
 
            *bar_window = Qnil;
            *part = 0;
 
            *bar_window = Qnil;
            *part = 0;
@@ -3862,9 +3861,9 @@ x_window_to_scroll_bar (display, window_id)
 {
   Lisp_Object tail;
 
 {
   Lisp_Object tail;
 
-#ifdef USE_GTK
+#if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
   window_id = (Window) xg_get_scroll_id_for_window (display, window_id);
   window_id = (Window) xg_get_scroll_id_for_window (display, window_id);
-#endif /* USE_GTK */
+#endif /* USE_GTK  && USE_TOOLKIT_SCROLL_BARS */
 
   for (tail = Vframe_list;
        XGCTYPE (tail) == Lisp_Cons;
 
   for (tail = Vframe_list;
        XGCTYPE (tail) == Lisp_Cons;
@@ -3963,8 +3962,6 @@ static Boolean xaw3d_arrow_scroll;
 
 static Boolean xaw3d_pick_top;
 
 
 static Boolean xaw3d_pick_top;
 
-extern void set_vertical_scroll_bar P_ ((struct window *));
-
 /* Action hook installed via XtAppAddActionHook when toolkit scroll
    bars are used..  The hook is responsible for detecting when
    the user ends an interaction with the scroll bar, and generates
 /* Action hook installed via XtAppAddActionHook when toolkit scroll
    bars are used..  The hook is responsible for detecting when
    the user ends an interaction with the scroll bar, and generates
@@ -4221,8 +4218,6 @@ xg_scroll_callback (widget, data)
   int part = -1, whole = 0, portion = 0;
   GtkAdjustment *adj = GTK_ADJUSTMENT (gtk_range_get_adjustment (widget));
 
   int part = -1, whole = 0, portion = 0;
   GtkAdjustment *adj = GTK_ADJUSTMENT (gtk_range_get_adjustment (widget));
 
-  if (xg_ignore_gtk_scrollbar) return;
-
   position = gtk_adjustment_get_value (adj);
 
   p = g_object_get_data (G_OBJECT (widget), XG_LAST_SB_DATA);
   position = gtk_adjustment_get_value (adj);
 
   p = g_object_get_data (G_OBJECT (widget), XG_LAST_SB_DATA);
@@ -4236,6 +4231,8 @@ xg_scroll_callback (widget, data)
   previous = *p;
   *p = position;
 
   previous = *p;
   *p = position;
 
+  if (xg_ignore_gtk_scrollbar) return;
+
   diff = (int) (position - previous);
 
   if (diff == (int) adj->step_increment)
   diff = (int) (position - previous);
 
   if (diff == (int) adj->step_increment)
@@ -4491,6 +4488,7 @@ x_create_toolkit_scroll_bar (f, bar)
       f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
     }
 
       f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
     }
 
+#ifdef XtNbeNiceToColormap
   /* Tell the toolkit about them.  */
   if (f->output_data.x->scroll_bar_top_shadow_pixel == -1
       || f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
   /* Tell the toolkit about them.  */
   if (f->output_data.x->scroll_bar_top_shadow_pixel == -1
       || f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
@@ -4514,16 +4512,17 @@ x_create_toolkit_scroll_bar (f, bar)
       pixel = f->output_data.x->scroll_bar_top_shadow_pixel;
       if (pixel != -1)
        {
       pixel = f->output_data.x->scroll_bar_top_shadow_pixel;
       if (pixel != -1)
        {
-         XtSetArg (av[ac], "topShadowPixel", pixel);
+         XtSetArg (av[ac], XtNtopShadowPixel, pixel);
          ++ac;
        }
       pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel;
       if (pixel != -1)
        {
          ++ac;
        }
       pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel;
       if (pixel != -1)
        {
-         XtSetArg (av[ac], "bottomShadowPixel", pixel);
+         XtSetArg (av[ac], XtNbottomShadowPixel, pixel);
          ++ac;
        }
     }
          ++ac;
        }
     }
+#endif
 
   widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
                           f->output_data.x->edit_widget, av, ac);
 
   widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
                           f->output_data.x->edit_widget, av, ac);
@@ -4532,11 +4531,14 @@ x_create_toolkit_scroll_bar (f, bar)
     char *initial = "";
     char *val = initial;
     XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
     char *initial = "";
     char *val = initial;
     XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
+#ifdef XtNarrowScrollbars
+                  XtNarrowScrollbars, (XtPointer) &xaw3d_arrow_scroll,
+#endif
                   XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
                   XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
-    if (val == initial)
+    if (xaw3d_arrow_scroll || val == initial)
       {        /* ARROW_SCROLL */
        xaw3d_arrow_scroll = True;
       {        /* ARROW_SCROLL */
        xaw3d_arrow_scroll = True;
-       /* Isn't that just a personal preference ?   -sm */
+       /* Isn't that just a personal preference ?   --Stef */
        XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
       }
   }
        XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
       }
   }
@@ -4669,30 +4671,11 @@ x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
          XawScrollbarSetThumb (widget, top, shown);
        else
          {
          XawScrollbarSetThumb (widget, top, shown);
        else
          {
-#ifdef HAVE_XAW3D
-           ScrollbarWidget sb = (ScrollbarWidget) widget;
-           int scroll_mode = 0;
-
-           /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR.  */
-           if (xaw3d_arrow_scroll)
-             {
-               /* Xaw3d stupidly ignores resize requests while dragging
-                  so we have to make it believe it's not in dragging mode.  */
-               scroll_mode = sb->scrollbar.scroll_mode;
-               if (scroll_mode == 2)
-                 sb->scrollbar.scroll_mode = 0;
-             }
-#endif
            /* Try to make the scrolling a tad smoother.  */
            if (!xaw3d_pick_top)
              shown = min (shown, old_shown);
 
            XawScrollbarSetThumb (widget, top, shown);
            /* Try to make the scrolling a tad smoother.  */
            if (!xaw3d_pick_top)
              shown = min (shown, old_shown);
 
            XawScrollbarSetThumb (widget, top, shown);
-
-#ifdef HAVE_XAW3D
-           if (xaw3d_arrow_scroll && scroll_mode == 2)
-             sb->scrollbar.scroll_mode = scroll_mode;
-#endif
          }
       }
   }
          }
       }
   }
@@ -4795,9 +4778,7 @@ x_scroll_bar_create (w, top, left, width, height)
                              top,
                              left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
                              width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
                              top,
                              left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
                              width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
-                             max (height, 1),
-                             left,
-                             width);
+                             max (height, 1));
     xg_show_scroll_bar (SCROLL_BAR_X_WINDOW (bar));
 #else /* not USE_GTK */
     Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
     xg_show_scroll_bar (SCROLL_BAR_X_WINDOW (bar));
 #else /* not USE_GTK */
     Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
@@ -4992,9 +4973,15 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
   /* Compute the left edge of the scroll bar.  */
 #ifdef USE_TOOLKIT_SCROLL_BARS
   if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
   /* Compute the left edge of the scroll bar.  */
 #ifdef USE_TOOLKIT_SCROLL_BARS
   if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
-    sb_left = left + width - sb_width - (width - sb_width) / 2;
+    sb_left = (left +
+              (WINDOW_RIGHTMOST_P (w)
+               ? width - sb_width - (width - sb_width) / 2
+               : 0));
   else
   else
-    sb_left = left + (width - sb_width) / 2;
+    sb_left = (left +
+              (WINDOW_LEFTMOST_P (w)
+               ? (width - sb_width) / 2
+               : width - sb_width));
 #else
   if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
     sb_left = left + width - sb_width;
 #else
   if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
     sb_left = left + width - sb_width;
@@ -5035,32 +5022,29 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
 
 #ifdef USE_TOOLKIT_SCROLL_BARS
 
 
 #ifdef USE_TOOLKIT_SCROLL_BARS
 
-#ifdef USE_GTK
-      if (mask)
-        xg_update_scrollbar_pos (f,
-                                 SCROLL_BAR_X_WINDOW (bar),
-                                 top,
-                                 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
-                                 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
-                                 max (height, 1),
-                                 left,
-                                 width);
-#else /* not USE_GTK */
-
-      /* Since toolkit scroll bars are smaller than the space reserved
-         for them on the frame, we have to clear "under" them.  */
-      if (width > 0 && height > 0)
-        x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                          left, top, width, height, False);
       /* Move/size the scroll bar widget.  */
       if (mask)
       /* Move/size the scroll bar widget.  */
       if (mask)
+       {
+         /* Since toolkit scroll bars are smaller than the space reserved
+            for them on the frame, we have to clear "under" them.  */
+         if (width > 0 && height > 0)
+           x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                          left, top, width, height, False);
+#ifdef USE_GTK
+          xg_update_scrollbar_pos (f,
+                                   SCROLL_BAR_X_WINDOW (bar),
+                                   top,
+                                   sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
+                                   sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM *2,
+                                   max (height, 1));
+#else /* not USE_GTK */
           XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
                              sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
                              top,
                              sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
                              max (height, 1), 0);
           XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
                              sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
                              top,
                              sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
                              max (height, 1), 0);
-
 #endif /* not USE_GTK */
 #endif /* not USE_GTK */
+       }
 #else /* not USE_TOOLKIT_SCROLL_BARS */
 
       /* Clear areas not covered by the scroll bar because of
 #else /* not USE_TOOLKIT_SCROLL_BARS */
 
       /* Clear areas not covered by the scroll bar because of
@@ -5512,73 +5496,6 @@ x_scroll_bar_clear (f)
 }
 
 \f
 }
 
 \f
-/* Define a queue to save up SelectionRequest events for later handling.  */
-
-struct selection_event_queue
-  {
-    XEvent event;
-    struct selection_event_queue *next;
-  };
-
-static struct selection_event_queue *queue;
-
-/* Nonzero means queue up certain events--don't process them yet.  */
-
-static int x_queue_selection_requests;
-
-/* Queue up an X event *EVENT, to be processed later.  */
-
-static void
-x_queue_event (f, event)
-     FRAME_PTR f;
-     XEvent *event;
-{
-  struct selection_event_queue *queue_tmp
-    = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
-
-  if (queue_tmp != NULL)
-    {
-      queue_tmp->event = *event;
-      queue_tmp->next = queue;
-      queue = queue_tmp;
-    }
-}
-
-/* Take all the queued events and put them back
-   so that they get processed afresh.  */
-
-static void
-x_unqueue_events (display)
-     Display *display;
-{
-  while (queue != NULL)
-    {
-      struct selection_event_queue *queue_tmp = queue;
-      XPutBackEvent (display, &queue_tmp->event);
-      queue = queue_tmp->next;
-      xfree ((char *)queue_tmp);
-    }
-}
-
-/* Start queuing SelectionRequest events.  */
-
-void
-x_start_queuing_selection_requests (display)
-     Display *display;
-{
-  x_queue_selection_requests++;
-}
-
-/* Stop queuing SelectionRequest events.  */
-
-void
-x_stop_queuing_selection_requests (display)
-     Display *display;
-{
-  x_queue_selection_requests--;
-  x_unqueue_events (display);
-}
-\f
 /* The main X event-reading loop - XTread_socket.  */
 
 #if 0
 /* The main X event-reading loop - XTread_socket.  */
 
 #if 0
@@ -5605,6 +5522,11 @@ static XComposeStatus compose_status;
 static int temp_index;
 static short temp_buffer[100];
 
 static int temp_index;
 static short temp_buffer[100];
 
+#define STORE_KEYSYM_FOR_DEBUG(keysym)                         \
+  if (temp_index == sizeof temp_buffer / sizeof (short))       \
+    temp_index = 0;                                            \
+  temp_buffer[temp_index++] = (keysym)
+
 /* Set this to nonzero to fake an "X I/O error"
    on a particular display.  */
 
 /* Set this to nonzero to fake an "X I/O error"
    on a particular display.  */
 
@@ -5624,15 +5546,8 @@ static struct x_display_info *next_noop_dpyinfo;
            f->output_data.x->saved_menu_event                          \
             = (XEvent *) xmalloc (sizeof (XEvent));                    \
          bcopy (&event, f->output_data.x->saved_menu_event, size);     \
            f->output_data.x->saved_menu_event                          \
             = (XEvent *) xmalloc (sizeof (XEvent));                    \
          bcopy (&event, f->output_data.x->saved_menu_event, size);     \
-         if (numchars >= 1)                                            \
-           {                                                           \
-             bufp->kind = MENU_BAR_ACTIVATE_EVENT;                     \
-             XSETFRAME (bufp->frame_or_window, f);                     \
-             bufp->arg = Qnil;                                         \
-             bufp++;                                                   \
-             count++;                                                  \
-             numchars--;                                               \
-           }                                                           \
+        inev.ie.kind = MENU_BAR_ACTIVATE_EVENT;                        \
+        XSETFRAME (inev.ie.frame_or_window, f);                        \
        }                                                               \
      while (0)
 
        }                                                               \
      while (0)
 
@@ -5674,14 +5589,13 @@ x_filter_event (dpyinfo, event)
 #endif
 
 #ifdef USE_GTK
 #endif
 
 #ifdef USE_GTK
-static struct input_event **current_bufp;
-static int *current_numcharsp;
 static int current_count;
 static int current_finish;
 static int current_count;
 static int current_finish;
+static struct input_event *current_hold_quit;
 
 /* This is the filter function invoked by the GTK event loop.
    It is invoked before the XEvent is translated to a GdkEvent,
 
 /* This is the filter function invoked by the GTK event loop.
    It is invoked before the XEvent is translated to a GdkEvent,
-   so we have a chanse to act on the event before GTK. */
+   so we have a chance to act on the event before GTK. */
 static GdkFilterReturn
 event_handler_gdk (gxev, ev, data)
      GdkXEvent *gxev;
 static GdkFilterReturn
 event_handler_gdk (gxev, ev, data)
      GdkXEvent *gxev;
@@ -5690,7 +5604,7 @@ event_handler_gdk (gxev, ev, data)
 {
   XEvent *xev = (XEvent *) gxev;
 
 {
   XEvent *xev = (XEvent *) gxev;
 
-  if (current_numcharsp)
+  if (current_count >= 0)
     {
       struct x_display_info *dpyinfo;
 
     {
       struct x_display_info *dpyinfo;
 
@@ -5708,11 +5622,11 @@ event_handler_gdk (gxev, ev, data)
       if (! dpyinfo)
         current_finish = X_EVENT_NORMAL;
       else
       if (! dpyinfo)
         current_finish = X_EVENT_NORMAL;
       else
-        current_count += handle_one_xevent (dpyinfo,
-                                            xev,
-                                            current_bufp,
-                                            current_numcharsp,
-                                            &current_finish);
+       {
+         current_count +=
+           handle_one_xevent (dpyinfo, xev, &current_finish,
+                              current_hold_quit);
+       }
     }
   else
     current_finish = x_dispatch_event (xev, xev->xany.display);
     }
   else
     current_finish = x_dispatch_event (xev, xev->xany.display);
@@ -5731,28 +5645,32 @@ event_handler_gdk (gxev, ev, data)
    *FINISH is zero if caller should continue reading events.
    *FINISH is X_EVENT_DROP if event should not be passed to the toolkit.
 
    *FINISH is zero if caller should continue reading events.
    *FINISH is X_EVENT_DROP if event should not be passed to the toolkit.
 
-   Events representing keys are stored in buffer *BUFP_R,
-   which can hold up to *NUMCHARSP characters.
    We return the number of characters stored into the buffer. */
 
 static int
    We return the number of characters stored into the buffer. */
 
 static int
-handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
+handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
      struct x_display_info *dpyinfo;
      XEvent *eventp;
      struct x_display_info *dpyinfo;
      XEvent *eventp;
-     /* register */ struct input_event **bufp_r;
-     /* register */ int *numcharsp;
      int *finish;
      int *finish;
+     struct input_event *hold_quit;
 {
 {
+  union {
+    struct input_event ie;
+    struct selection_input_event sie;
+  } inev;
   int count = 0;
   int count = 0;
+  int do_help = 0;
   int nbytes = 0;
   struct frame *f;
   struct coding_system coding;
   int nbytes = 0;
   struct frame *f;
   struct coding_system coding;
-  struct input_event *bufp = *bufp_r;
-  int numchars = *numcharsp;
   XEvent event = *eventp;
 
   *finish = X_EVENT_NORMAL;
 
   XEvent event = *eventp;
 
   *finish = X_EVENT_NORMAL;
 
+  EVENT_INIT (inev.ie);
+  inev.ie.kind = NO_EVENT;
+  inev.ie.arg = Qnil;
+
   switch (event.type)
     {
     case ClientMessage:
   switch (event.type)
     {
     case ClientMessage:
@@ -5794,7 +5712,7 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
                     Display *d = event.xclient.display;
                     /* Catch and ignore errors, in case window has been
                        iconified by a window manager such as GWM.  */
                     Display *d = event.xclient.display;
                     /* Catch and ignore errors, in case window has been
                        iconified by a window manager such as GWM.  */
-                    int count = x_catch_errors (d);
+                    x_catch_errors (d);
                     XSetInputFocus (d, event.xclient.window,
                                     /* The ICCCM says this is
                                        the only valid choice.  */
                     XSetInputFocus (d, event.xclient.window,
                                     /* The ICCCM says this is
                                        the only valid choice.  */
@@ -5803,12 +5721,14 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
                     /* This is needed to detect the error
                        if there is an error.  */
                     XSync (d, False);
                     /* This is needed to detect the error
                        if there is an error.  */
                     XSync (d, False);
-                    x_uncatch_errors (d, count);
+                    x_uncatch_errors ();
                   }
                 /* Not certain about handling scroll bars here */
 #endif /* 0 */
                   }
                 /* Not certain about handling scroll bars here */
 #endif /* 0 */
+               goto done;
               }
               }
-            else if (event.xclient.data.l[0]
+
+            if (event.xclient.data.l[0]
                      == dpyinfo->Xatom_wm_save_yourself)
               {
                 /* Save state modify the WM_COMMAND property to
                      == dpyinfo->Xatom_wm_save_yourself)
               {
                 /* Save state modify the WM_COMMAND property to
@@ -5819,11 +5739,9 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
                 /* If we have a session manager, don't set this.
                    KDE will then start two Emacsen, one for the
                    session manager and one for this. */
                 /* If we have a session manager, don't set this.
                    KDE will then start two Emacsen, one for the
                    session manager and one for this. */
-                if (numchars > 0
 #ifdef HAVE_X_SM
 #ifdef HAVE_X_SM
-                    && ! x_session_have_connection ()
+                if (! x_session_have_connection ())
 #endif
 #endif
-                    )
                   {
                     f = x_top_window_to_frame (dpyinfo,
                                                event.xclient.window);
                   {
                     f = x_top_window_to_frame (dpyinfo,
                                                event.xclient.window);
@@ -5838,41 +5756,36 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
                                    event.xclient.window,
                                    0, 0);
                   }
                                    event.xclient.window,
                                    0, 0);
                   }
+               goto done;
               }
               }
-            else if (event.xclient.data.l[0]
-                     == dpyinfo->Xatom_wm_delete_window)
+
+            if (event.xclient.data.l[0]
+               == dpyinfo->Xatom_wm_delete_window)
               {
               {
-                struct frame *f
-                  = x_any_window_to_frame (dpyinfo,
+                f = x_any_window_to_frame (dpyinfo,
                                            event.xclient.window);
                                            event.xclient.window);
+                if (!f)
+                 goto OTHER; /* May be a dialog that is to be removed  */
 
 
-                if (f)
-                  {
-                    if (numchars == 0)
-                      abort ();
-
-                    bufp->kind = DELETE_WINDOW_EVENT;
-                    XSETFRAME (bufp->frame_or_window, f);
-                    bufp->arg = Qnil;
-                    bufp++;
-
-                    count += 1;
-                    numchars -= 1;
-                  }
-                else
-                  goto OTHER; /* May be a dialog that is to be removed  */
+               inev.ie.kind = DELETE_WINDOW_EVENT;
+               XSETFRAME (inev.ie.frame_or_window, f);
+               goto done;
               }
               }
+
+           goto done;
           }
           }
-        else if (event.xclient.message_type
+
+        if (event.xclient.message_type
                  == dpyinfo->Xatom_wm_configure_denied)
           {
                  == dpyinfo->Xatom_wm_configure_denied)
           {
+           goto done;
           }
           }
-        else if (event.xclient.message_type
-                 == dpyinfo->Xatom_wm_window_moved)
+
+        if (event.xclient.message_type
+           == dpyinfo->Xatom_wm_window_moved)
           {
             int new_x, new_y;
           {
             int new_x, new_y;
-            struct frame *f
-              = x_window_to_frame (dpyinfo, event.xclient.window);
+           f = x_window_to_frame (dpyinfo, event.xclient.window);
 
             new_x = event.xclient.data.s[0];
             new_y = event.xclient.data.s[1];
 
             new_x = event.xclient.data.s[0];
             new_y = event.xclient.data.s[1];
@@ -5882,45 +5795,55 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
                 f->left_pos = new_x;
                 f->top_pos = new_y;
               }
                 f->left_pos = new_x;
                 f->top_pos = new_y;
               }
+           goto done;
           }
           }
+
 #ifdef HACK_EDITRES
 #ifdef HACK_EDITRES
-        else if (event.xclient.message_type
-                 == dpyinfo->Xatom_editres)
+        if (event.xclient.message_type
+           == dpyinfo->Xatom_editres)
           {
           {
-            struct frame *f
-              = x_any_window_to_frame (dpyinfo, event.xclient.window);
+           f = x_any_window_to_frame (dpyinfo, event.xclient.window);
             _XEditResCheckMessages (f->output_data.x->widget, NULL,
                                     &event, NULL);
             _XEditResCheckMessages (f->output_data.x->widget, NULL,
                                     &event, NULL);
+           goto done;
           }
 #endif /* HACK_EDITRES */
           }
 #endif /* HACK_EDITRES */
-        else if ((event.xclient.message_type
-                  == dpyinfo->Xatom_DONE)
-                 || (event.xclient.message_type
-                     == dpyinfo->Xatom_PAGE))
+
+        if ((event.xclient.message_type
+            == dpyinfo->Xatom_DONE)
+           || (event.xclient.message_type
+               == dpyinfo->Xatom_PAGE))
           {
             /* Ghostview job completed.  Kill it.  We could
                reply with "Next" if we received "Page", but we
                currently never do because we are interested in
                images, only, which should have 1 page.  */
             Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
           {
             /* Ghostview job completed.  Kill it.  We could
                reply with "Next" if we received "Page", but we
                currently never do because we are interested in
                images, only, which should have 1 page.  */
             Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
-            struct frame *f
-              = x_window_to_frame (dpyinfo, event.xclient.window);
+           f = x_window_to_frame (dpyinfo, event.xclient.window);
             x_kill_gs_process (pixmap, f);
             expose_frame (f, 0, 0, 0, 0);
             x_kill_gs_process (pixmap, f);
             expose_frame (f, 0, 0, 0, 0);
+           goto done;
           }
           }
+
 #ifdef USE_TOOLKIT_SCROLL_BARS
         /* Scroll bar callbacks send a ClientMessage from which
            we construct an input_event.  */
 #ifdef USE_TOOLKIT_SCROLL_BARS
         /* Scroll bar callbacks send a ClientMessage from which
            we construct an input_event.  */
-        else if (event.xclient.message_type
-                 == dpyinfo->Xatom_Scrollbar)
+        if (event.xclient.message_type
+           == dpyinfo->Xatom_Scrollbar)
           {
           {
-            x_scroll_bar_to_input_event (&event, bufp);
-            ++bufp, ++count, --numchars;
-            goto out;
+            x_scroll_bar_to_input_event (&event, &inev.ie);
+           *finish = X_EVENT_GOTO_OUT;
+            goto done;
           }
 #endif /* USE_TOOLKIT_SCROLL_BARS */
           }
 #endif /* USE_TOOLKIT_SCROLL_BARS */
-        else
-          goto OTHER;
+
+       f = x_any_window_to_frame (dpyinfo, event.xclient.window);
+
+       if (!f)
+         goto OTHER;
+
+       if (x_handle_dnd_message (f, &event.xclient, dpyinfo, &inev.ie))
+         *finish = X_EVENT_DROP;
       }
       break;
 
       }
       break;
 
@@ -5940,19 +5863,11 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
       {
         XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
 
       {
         XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
 
-        if (numchars == 0)
-          abort ();
-
-        bufp->kind = SELECTION_CLEAR_EVENT;
-        SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
-        SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
-        SELECTION_EVENT_TIME (bufp) = eventp->time;
-        bufp->frame_or_window = Qnil;
-        bufp->arg = Qnil;
-        bufp++;
-
-        count += 1;
-        numchars -= 1;
+        inev.ie.kind = SELECTION_CLEAR_EVENT;
+        SELECTION_EVENT_DISPLAY (&inev.sie) = eventp->display;
+        SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
+        SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
+        inev.ie.frame_or_window = Qnil;
       }
       break;
 
       }
       break;
 
@@ -5961,31 +5876,19 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
       if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
         goto OTHER;
 #endif /* USE_X_TOOLKIT */
       if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
         goto OTHER;
 #endif /* USE_X_TOOLKIT */
-      if (x_queue_selection_requests)
-        x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
-                       &event);
-      else
-        {
+      {
           XSelectionRequestEvent *eventp
             = (XSelectionRequestEvent *) &event;
 
           XSelectionRequestEvent *eventp
             = (XSelectionRequestEvent *) &event;
 
-          if (numchars == 0)
-            abort ();
-
-          bufp->kind = SELECTION_REQUEST_EVENT;
-          SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
-          SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
-          SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
-          SELECTION_EVENT_TARGET (bufp) = eventp->target;
-          SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
-          SELECTION_EVENT_TIME (bufp) = eventp->time;
-          bufp->frame_or_window = Qnil;
-          bufp->arg = Qnil;
-          bufp++;
-
-          count += 1;
-          numchars -= 1;
-        }
+          inev.ie.kind = SELECTION_REQUEST_EVENT;
+          SELECTION_EVENT_DISPLAY (&inev.sie) = eventp->display;
+          SELECTION_EVENT_REQUESTOR (&inev.sie) = eventp->requestor;
+          SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
+          SELECTION_EVENT_TARGET (&inev.sie) = eventp->target;
+          SELECTION_EVENT_PROPERTY (&inev.sie) = eventp->property;
+          SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
+          inev.ie.frame_or_window = Qnil;
+      }
       break;
 
     case PropertyNotify:
       break;
 
     case PropertyNotify:
@@ -6014,7 +5917,6 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
           FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_UNKNOWN;
         }
       goto OTHER;
           FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_UNKNOWN;
         }
       goto OTHER;
-      break;
 
     case Expose:
       f = x_window_to_frame (dpyinfo, event.xexpose.window);
 
     case Expose:
       f = x_window_to_frame (dpyinfo, event.xexpose.window);
@@ -6022,6 +5924,14 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
         {
           x_check_fullscreen (f);
 
         {
           x_check_fullscreen (f);
 
+#ifdef USE_GTK
+          /* This seems to be needed for GTK 2.6.  */
+          x_clear_area (event.xexpose.display,
+                        event.xexpose.window,
+                        event.xexpose.x, event.xexpose.y,
+                        event.xexpose.width, event.xexpose.height,
+                        FALSE);
+#endif
           if (f->async_visible == 0)
             {
               f->async_visible = 1;
           if (f->async_visible == 0)
             {
               f->async_visible = 1;
@@ -6116,12 +6026,8 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
             {
               f->async_iconified = 1;
 
             {
               f->async_iconified = 1;
 
-              bufp->kind = ICONIFY_EVENT;
-              XSETFRAME (bufp->frame_or_window, f);
-              bufp->arg = Qnil;
-              bufp++;
-              count++;
-              numchars--;
+              inev.ie.kind = ICONIFY_EVENT;
+              XSETFRAME (inev.ie.frame_or_window, f);
             }
         }
       goto OTHER;
             }
         }
       goto OTHER;
@@ -6138,7 +6044,7 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
       f = x_top_window_to_frame (dpyinfo, event.xmap.window);
       if (f)
         {
       f = x_top_window_to_frame (dpyinfo, event.xmap.window);
       if (f)
         {
-          /* wait_reading_process_input will notice this and update
+          /* wait_reading_process_output will notice this and update
              the frame's display structures.
              If we where iconified, we should not set garbaged,
              because that stops redrawing on Expose events.  This looks
              the frame's display structures.
              If we where iconified, we should not set garbaged,
              because that stops redrawing on Expose events.  This looks
@@ -6153,12 +6059,8 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
 
           if (f->iconified)
             {
 
           if (f->iconified)
             {
-              bufp->kind = DEICONIFY_EVENT;
-              XSETFRAME (bufp->frame_or_window, f);
-              bufp->arg = Qnil;
-              bufp++;
-              count++;
-              numchars--;
+              inev.ie.kind = DEICONIFY_EVENT;
+              XSETFRAME (inev.ie.frame_or_window, f);
             }
           else if (! NILP (Vframe_list)
                    && ! NILP (XCDR (Vframe_list)))
             }
           else if (! NILP (Vframe_list)
                    && ! NILP (XCDR (Vframe_list)))
@@ -6171,6 +6073,8 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
 
     case KeyPress:
 
 
     case KeyPress:
 
+      ignore_next_mouse_click_timeout = 0;
+
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
       /* Dispatch KeyPress events when in menu.  */
       if (popup_activated ())
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
       /* Dispatch KeyPress events when in menu.  */
       if (popup_activated ())
@@ -6181,8 +6085,8 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
 
       if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
         {
 
       if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
         {
-          dpyinfo->mouse_face_hidden = 1;
           clear_mouse_face (dpyinfo);
           clear_mouse_face (dpyinfo);
+          dpyinfo->mouse_face_hidden = 1;
         }
 
 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
         }
 
 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
@@ -6219,6 +6123,15 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
           int copy_bufsiz = sizeof (copy_buffer);
           int modifiers;
           Lisp_Object coding_system = Qlatin_1;
           int copy_bufsiz = sizeof (copy_buffer);
           int modifiers;
           Lisp_Object coding_system = Qlatin_1;
+         Lisp_Object c;
+
+#ifdef USE_GTK
+          /* Don't pass keys to GTK.  A Tab will shift focus to the
+             tool bar in GTK 2.4.  Keys will still go to menus and
+             dialogs because in that case popup_activated is TRUE
+             (see above).  */
+          *finish = X_EVENT_DROP;
+#endif
 
           event.xkey.state
             |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
 
           event.xkey.state
             |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
@@ -6256,7 +6169,7 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
               if (status_return == XBufferOverflow)
                 {
                   copy_bufsiz = nbytes + 1;
               if (status_return == XBufferOverflow)
                 {
                   copy_bufsiz = nbytes + 1;
-                  copy_bufptr = (char *) alloca (copy_bufsiz);
+                  copy_bufptr = (unsigned char *) alloca (copy_bufsiz);
                   nbytes = XmbLookupString (FRAME_XIC (f),
                                             &event.xkey, copy_bufptr,
                                             copy_bufsiz, &keysym,
                   nbytes = XmbLookupString (FRAME_XIC (f),
                                             &event.xkey, copy_bufptr,
                                             copy_bufsiz, &keysym,
@@ -6274,7 +6187,7 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
                   if (status_return == XBufferOverflow)
                     {
                       copy_bufsiz = nbytes + 1;
                   if (status_return == XBufferOverflow)
                     {
                       copy_bufsiz = nbytes + 1;
-                      copy_bufptr = (char *) alloca (copy_bufsiz);
+                      copy_bufptr = (unsigned char *) alloca (copy_bufsiz);
                       nbytes = Xutf8LookupString (FRAME_XIC (f),
                                                   &event.xkey,
                                                   copy_bufptr,
                       nbytes = Xutf8LookupString (FRAME_XIC (f),
                                                   &event.xkey,
                                                   copy_bufptr,
@@ -6310,51 +6223,78 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
           if (compose_status.chars_matched > 0 && nbytes == 0)
             break;
 
           if (compose_status.chars_matched > 0 && nbytes == 0)
             break;
 
+          bzero (&compose_status, sizeof (compose_status));
           orig_keysym = keysym;
 
           orig_keysym = keysym;
 
-          if (numchars > 1)
-            {
-              Lisp_Object c;
+         /* Common for all keysym input events.  */
+         XSETFRAME (inev.ie.frame_or_window, f);
+         inev.ie.modifiers
+           = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), modifiers);
+         inev.ie.timestamp = event.xkey.time;
 
 
-              /* First deal with keysyms which have defined
-                 translations to characters.  */
-              if (keysym >= 32 && keysym < 128)
-                /* Avoid explicitly decoding each ASCII character.  */
-                {
-                  bufp->kind = ASCII_KEYSTROKE_EVENT;
-                  bufp->code = keysym;
-                  XSETFRAME (bufp->frame_or_window, f);
-                  bufp->arg = Qnil;
-                  bufp->modifiers
-                    = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
-                                              modifiers);
-                  bufp->timestamp = event.xkey.time;
-                  bufp++;
-                  count++;
-                  numchars--;
-                }
-              /* Now non-ASCII.  */
-              else if (HASH_TABLE_P (Vx_keysym_table)
-                       && (NATNUMP (c = Fgethash (make_number (keysym),
-                                                  Vx_keysym_table,
-                                                  Qnil))))
-                {
-                  bufp->kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
-                                ? ASCII_KEYSTROKE_EVENT
-                                : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
-                  bufp->code = XFASTINT (c);
-                  XSETFRAME (bufp->frame_or_window, f);
-                  bufp->arg = Qnil;
-                  bufp->modifiers
-                    = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
-                                              modifiers);
-                  bufp->timestamp = event.xkey.time;
-                  bufp++;
-                  count++;
-                  numchars--;
-                }
-              /* Random non-modifier sorts of keysyms.  */
-              else if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
+         /* First deal with keysyms which have defined
+            translations to characters.  */
+         if (keysym >= 32 && keysym < 128)
+           /* Avoid explicitly decoding each ASCII character.  */
+           {
+             inev.ie.kind = ASCII_KEYSTROKE_EVENT;
+             inev.ie.code = keysym;
+             goto done_keysym;
+           }
+
+         /* Keysyms directly mapped to supported Unicode characters.  */
+         if ((keysym >= 0x01000000 && keysym <= 0x010033ff)
+             || (keysym >= 0x0100e000 && keysym <= 0x0100ffff))
+           {
+             int code = keysym & 0xFFFF, charset_id, c1, c2;
+
+             if (code < 0x80)
+               {
+                 inev.ie.kind = ASCII_KEYSTROKE_EVENT;
+                 inev.ie.code = code;
+               }
+             else if (code < 0x100)
+               {
+                 if (code < 0xA0)
+                   charset_id = CHARSET_8_BIT_CONTROL;
+                 else
+                   charset_id = charset_latin_iso8859_1;
+                 inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+                 inev.ie.code = MAKE_CHAR (charset_id, code, 0);
+               }
+             else
+               {
+                 if (code < 0x2500)
+                   charset_id = charset_mule_unicode_0100_24ff,
+                     code -= 0x100;
+                 else if (code < 0xE000)
+                   charset_id = charset_mule_unicode_2500_33ff,
+                     code -= 0x2500;
+                 else
+                   charset_id = charset_mule_unicode_e000_ffff,
+                     code -= 0xE000;
+                 c1 = (code / 96) + 32, c2 = (code % 96) + 32;
+                 inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+                 inev.ie.code = MAKE_CHAR (charset_id, c1, c2);
+               }
+             goto done_keysym;
+           }
+
+         /* Now non-ASCII.  */
+         if (HASH_TABLE_P (Vx_keysym_table)
+             && (NATNUMP (c = Fgethash (make_number (keysym),
+                                        Vx_keysym_table,
+                                        Qnil))))
+           {
+             inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
+                             ? ASCII_KEYSTROKE_EVENT
+                             : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
+             inev.ie.code = XFASTINT (c);
+             goto done_keysym;
+           }
+
+         /* Random non-modifier sorts of keysyms.  */
+         if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
                         || keysym == XK_Delete
 #ifdef XK_ISO_Left_Tab
                         || (keysym >= XK_ISO_Left_Tab
                         || keysym == XK_Delete
 #ifdef XK_ISO_Left_Tab
                         || (keysym >= XK_ISO_Left_Tab
@@ -6435,104 +6375,80 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
                                  <= XK_ISO_Last_Group_Lock)
 #endif
                              ))
                                  <= XK_ISO_Last_Group_Lock)
 #endif
                              ))
-                {
-                  if (temp_index == sizeof temp_buffer / sizeof (short))
-                    temp_index = 0;
-                  temp_buffer[temp_index++] = keysym;
-                  /* make_lispy_event will convert this to a symbolic
-                     key.  */
-                  bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
-                  bufp->code = keysym;
-                  XSETFRAME (bufp->frame_or_window, f);
-                  bufp->arg = Qnil;
-                  bufp->modifiers
-                    = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
-                                              modifiers);
-                  bufp->timestamp = event.xkey.time;
-                  bufp++;
-                  count++;
-                  numchars--;
-                }
-              else if (numchars > nbytes)
-                {      /* Raw bytes, not keysym.  */
-                  register int i;
-                  register int c;
-                  int nchars, len;
-
-                  /* The input should be decoded with `coding_system'
-                     which depends on which X*LookupString function
-                     we used just above and the locale.  */
-                  setup_coding_system (coding_system, &coding);
-                  coding.src_multibyte = 0;
-                  coding.dst_multibyte = 1;
-                  /* The input is converted to events, thus we can't
-                     handle composition.  Anyway, there's no XIM that
-                     gives us composition information.  */
-                  coding.composing = COMPOSITION_DISABLED;
-
-                  for (i = 0; i < nbytes; i++)
-                    {
-                      if (temp_index == (sizeof temp_buffer
-                                         / sizeof (short)))
-                        temp_index = 0;
-                      temp_buffer[temp_index++] = copy_bufptr[i];
-                    }
+           {
+             STORE_KEYSYM_FOR_DEBUG (keysym);
+             /* make_lispy_event will convert this to a symbolic
+                key.  */
+             inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
+             inev.ie.code = keysym;
+             goto done_keysym;
+           }
 
 
-                  {
-                    /* Decode the input data.  */
-                    int require;
-                    unsigned char *p;
-
-                    require = decoding_buffer_size (&coding, nbytes);
-                    p = (unsigned char *) alloca (require);
-                    coding.mode |= CODING_MODE_LAST_BLOCK;
-                    /* We explicitly disable composition
-                       handling because key data should
-                       not contain any composition
-                       sequence.  */
-                    coding.composing = COMPOSITION_DISABLED;
-                    decode_coding (&coding, copy_bufptr, p,
-                                   nbytes, require);
-                    nbytes = coding.produced;
-                    nchars = coding.produced_char;
-                    copy_bufptr = p;
-                  }
+         {     /* Raw bytes, not keysym.  */
+           register int i;
+           register int c;
+           int nchars, len;
+
+           /* The input should be decoded with `coding_system'
+              which depends on which X*LookupString function
+              we used just above and the locale.  */
+           setup_coding_system (coding_system, &coding);
+           coding.src_multibyte = 0;
+           coding.dst_multibyte = 1;
+           /* The input is converted to events, thus we can't
+              handle composition.  Anyway, there's no XIM that
+              gives us composition information.  */
+           coding.composing = COMPOSITION_DISABLED;
+
+           for (i = 0; i < nbytes; i++)
+             {
+               STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]);
+             }
 
 
-                  /* Convert the input data to a sequence of
-                     character events.  */
-                  for (i = 0; i < nbytes; i += len)
-                    {
-                      if (nchars == nbytes)
-                        c = copy_bufptr[i], len = 1;
-                      else
-                        c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
-                                                    nbytes - i, len);
-
-                      bufp->kind = (SINGLE_BYTE_CHAR_P (c)
-                                    ? ASCII_KEYSTROKE_EVENT
-                                    : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
-                      bufp->code = c;
-                      XSETFRAME (bufp->frame_or_window, f);
-                      bufp->arg = Qnil;
-                      bufp->modifiers
-                        = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
-                                                  modifiers);
-                      bufp->timestamp = event.xkey.time;
-                      bufp++;
-                    }
+           {
+             /* Decode the input data.  */
+             int require;
+             unsigned char *p;
+
+             require = decoding_buffer_size (&coding, nbytes);
+             p = (unsigned char *) alloca (require);
+             coding.mode |= CODING_MODE_LAST_BLOCK;
+             /* We explicitly disable composition handling because
+                key data should not contain any composition sequence.  */
+             coding.composing = COMPOSITION_DISABLED;
+             decode_coding (&coding, copy_bufptr, p, nbytes, require);
+             nbytes = coding.produced;
+             nchars = coding.produced_char;
+             copy_bufptr = p;
+           }
 
 
-                  count += nchars;
-                  numchars -= nchars;
+           /* Convert the input data to a sequence of
+              character events.  */
+           for (i = 0; i < nbytes; i += len)
+             {
+               if (nchars == nbytes)
+                 c = copy_bufptr[i], len = 1;
+               else
+                 c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
+                                             nbytes - i, len);
+               inev.ie.kind = (SINGLE_BYTE_CHAR_P (c)
+                             ? ASCII_KEYSTROKE_EVENT
+                             : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
+               inev.ie.code = c;
+               kbd_buffer_store_event_hold (&inev.ie, hold_quit);
+             }
 
 
-                  if (keysym == NoSymbol)
-                    break;
-                }
-              else
-                abort ();
-            }
-          else
-            abort ();
+           /* Previous code updated count by nchars rather than nbytes,
+              but that seems bogus to me.  ++kfs  */
+           count += nbytes;
+
+           inev.ie.kind = NO_EVENT;  /* Already stored above.  */
+
+           if (keysym == NoSymbol)
+             break;
+         }
         }
         }
+    done_keysym:
 #ifdef HAVE_X_I18N
       /* Don't dispatch this event since XtDispatchEvent calls
          XFilterEvent, and two calls in a row may freeze the
 #ifdef HAVE_X_I18N
       /* Don't dispatch this event since XtDispatchEvent calls
          XFilterEvent, and two calls in a row may freeze the
@@ -6553,63 +6469,47 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
 #endif
 
     case EnterNotify:
 #endif
 
     case EnterNotify:
-      {
-        int n;
+      x_detect_focus_change (dpyinfo, &event, &inev.ie);
 
 
-        n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
-        if (n > 0)
-          {
-            bufp += n, count += n, numchars -= n;
-          }
+      f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
 
 
-        f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
+      if (f && x_mouse_click_focus_ignore_position)
+       ignore_next_mouse_click_timeout = event.xmotion.time + 200;
 
 #if 0
 
 #if 0
-        if (event.xcrossing.focus)
-          {
-            /* Avoid nasty pop/raise loops.  */
-            if (f && (!(f->auto_raise)
-                      || !(f->auto_lower)
-                      || (event.xcrossing.time - enter_timestamp) > 500))
-              {
-                x_new_focus_frame (dpyinfo, f);
-                enter_timestamp = event.xcrossing.time;
-              }
-          }
-        else if (f == dpyinfo->x_focus_frame)
-          x_new_focus_frame (dpyinfo, 0);
+      if (event.xcrossing.focus)
+       {
+         /* Avoid nasty pop/raise loops.  */
+         if (f && (!(f->auto_raise)
+                   || !(f->auto_lower)
+                   || (event.xcrossing.time - enter_timestamp) > 500))
+           {
+             x_new_focus_frame (dpyinfo, f);
+             enter_timestamp = event.xcrossing.time;
+           }
+       }
+      else if (f == dpyinfo->x_focus_frame)
+       x_new_focus_frame (dpyinfo, 0);
 #endif
 
 #endif
 
-        /* EnterNotify counts as mouse movement,
-           so update things that depend on mouse position.  */
-        if (f && !f->output_data.x->hourglass_p)
-          note_mouse_movement (f, &event.xmotion);
-        goto OTHER;
-      }
+      /* EnterNotify counts as mouse movement,
+        so update things that depend on mouse position.  */
+      if (f && !f->output_data.x->hourglass_p)
+       note_mouse_movement (f, &event.xmotion);
+#ifdef USE_GTK
+      /* We may get an EnterNotify on the buttons in the toolbar.  In that
+         case we moved out of any highlighted area and need to note this.  */
+      if (!f && last_mouse_glyph_frame)
+        note_mouse_movement (last_mouse_glyph_frame, &event);
+#endif
+      goto OTHER;
 
     case FocusIn:
 
     case FocusIn:
-      {
-        int n;
-
-        n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
-        if (n > 0)
-          {
-            bufp += n, count += n, numchars -= n;
-          }
-      }
-
+      x_detect_focus_change (dpyinfo, &event, &inev.ie);
       goto OTHER;
 
     case LeaveNotify:
       goto OTHER;
 
     case LeaveNotify:
-      {
-        int n;
-
-        n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
-        if (n > 0)
-          {
-            bufp += n, count += n, numchars -= n;
-          }
-      }
+      x_detect_focus_change (dpyinfo, &event, &inev.ie);
 
       f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
       if (f)
 
       f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
       if (f)
@@ -6627,38 +6527,23 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
              Otherwise, the startup message is cleared when
              the mouse leaves the frame.  */
           if (any_help_event_p)
              Otherwise, the startup message is cleared when
              the mouse leaves the frame.  */
           if (any_help_event_p)
-            {
-              Lisp_Object frame;
-              int n;
-
-              XSETFRAME (frame, f);
-              help_echo_string = Qnil;
-              n = gen_help_event (bufp, numchars,
-                                  Qnil, frame, Qnil, Qnil, 0);
-              bufp += n, count += n, numchars -= n;
-            }
-
+           do_help = -1;
         }
         }
+#ifdef USE_GTK
+      /* See comment in EnterNotify above */
+      else if (last_mouse_glyph_frame)
+        note_mouse_movement (last_mouse_glyph_frame, &event);
+#endif
       goto OTHER;
 
     case FocusOut:
       goto OTHER;
 
     case FocusOut:
-      {
-        int n;
-
-        n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
-        if (n > 0)
-          {
-            bufp += n, count += n, numchars -= n;
-          }
-      }
-
+      x_detect_focus_change (dpyinfo, &event, &inev.ie);
       goto OTHER;
 
     case MotionNotify:
       {
         previous_help_echo_string = help_echo_string;
       goto OTHER;
 
     case MotionNotify:
       {
         previous_help_echo_string = help_echo_string;
-        help_echo_string = help_echo_object = help_echo_window = Qnil;
-        help_echo_pos = -1;
+        help_echo_string = Qnil;
 
         if (dpyinfo->grabbed && last_mouse_frame
             && FRAME_LIVE_P (last_mouse_frame))
 
         if (dpyinfo->grabbed && last_mouse_frame
             && FRAME_LIVE_P (last_mouse_frame))
@@ -6689,18 +6574,16 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
                    will be selected iff it is active.  */
                 if (WINDOWP (window)
                     && !EQ (window, last_window)
                    will be selected iff it is active.  */
                 if (WINDOWP (window)
                     && !EQ (window, last_window)
-                    && !EQ (window, selected_window)
-                    && numchars > 0)
+                    && !EQ (window, selected_window))
                   {
                   {
-                    bufp->kind = SELECT_WINDOW_EVENT;
-                    bufp->frame_or_window = window;
-                    bufp->arg = Qnil;
-                    ++bufp, ++count, --numchars;
+                    inev.ie.kind = SELECT_WINDOW_EVENT;
+                    inev.ie.frame_or_window = window;
                   }
 
                 last_window=window;
               }
                   }
 
                 last_window=window;
               }
-            note_mouse_movement (f, &event.xmotion);
+            if (!note_mouse_movement (f, &event.xmotion))
+             help_echo_string = previous_help_echo_string;
           }
         else
           {
           }
         else
           {
@@ -6722,22 +6605,7 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
            has changed, generate a HELP_EVENT.  */
         if (!NILP (help_echo_string)
             || !NILP (previous_help_echo_string))
            has changed, generate a HELP_EVENT.  */
         if (!NILP (help_echo_string)
             || !NILP (previous_help_echo_string))
-          {
-            Lisp_Object frame;
-            int n;
-
-            if (f)
-              XSETFRAME (frame, f);
-            else
-              frame = Qnil;
-
-            any_help_event_p = 1;
-            n = gen_help_event (bufp, numchars, help_echo_string, frame,
-                                help_echo_window, help_echo_object,
-                                help_echo_pos);
-            bufp += n, count += n, numchars -= n;
-          }
-
+         do_help = 1;
         goto OTHER;
       }
 
         goto OTHER;
       }
 
@@ -6821,11 +6689,10 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
       {
         /* If we decide we want to generate an event to be seen
            by the rest of Emacs, we put it here.  */
       {
         /* If we decide we want to generate an event to be seen
            by the rest of Emacs, we put it here.  */
-        struct input_event emacs_event;
         int tool_bar_p = 0;
 
         int tool_bar_p = 0;
 
-        emacs_event.kind = NO_EVENT;
         bzero (&compose_status, sizeof (compose_status));
         bzero (&compose_status, sizeof (compose_status));
+       last_mouse_glyph_frame = 0;
 
         if (dpyinfo->grabbed
             && last_mouse_frame
 
         if (dpyinfo->grabbed
             && last_mouse_frame
@@ -6864,7 +6731,21 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
                   if (! popup_activated ())
 #endif
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
                   if (! popup_activated ())
 #endif
-                    construct_mouse_click (&emacs_event, &event, f);
+                   {
+                     if (ignore_next_mouse_click_timeout)
+                       {
+                         if (event.type == ButtonPress
+                             && (int)(event.xbutton.time - ignore_next_mouse_click_timeout) > 0)
+                           {
+                             ignore_next_mouse_click_timeout = 0;
+                             construct_mouse_click (&inev.ie, &event.xbutton, f);
+                           }
+                         if (event.type == ButtonRelease)
+                           ignore_next_mouse_click_timeout = 0;
+                       }
+                     else
+                       construct_mouse_click (&inev.ie, &event.xbutton, f);
+                   }
                 }
           }
         else
                 }
           }
         else
@@ -6878,12 +6759,12 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
                scroll bars.  */
             if (bar && event.xbutton.state & ControlMask)
               {
                scroll bars.  */
             if (bar && event.xbutton.state & ControlMask)
               {
-                x_scroll_bar_handle_click (bar, &event, &emacs_event);
+                x_scroll_bar_handle_click (bar, &event, &inev.ie);
                 *finish = X_EVENT_DROP;
               }
 #else /* not USE_TOOLKIT_SCROLL_BARS */
             if (bar)
                 *finish = X_EVENT_DROP;
               }
 #else /* not USE_TOOLKIT_SCROLL_BARS */
             if (bar)
-              x_scroll_bar_handle_click (bar, &event, &emacs_event);
+              x_scroll_bar_handle_click (bar, &event, &inev.ie);
 #endif /* not USE_TOOLKIT_SCROLL_BARS */
           }
 
 #endif /* not USE_TOOLKIT_SCROLL_BARS */
           }
 
@@ -6891,12 +6772,6 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
           {
             dpyinfo->grabbed |= (1 << event.xbutton.button);
             last_mouse_frame = f;
           {
             dpyinfo->grabbed |= (1 << event.xbutton.button);
             last_mouse_frame = f;
-            /* Ignore any mouse motion that happened
-               before this event; any subsequent mouse-movement
-               Emacs events should reflect only motion after
-               the ButtonPress.  */
-            if (f != 0)
-              f->mouse_moved = 0;
 
             if (!tool_bar_p)
               last_tool_bar_item = -1;
 
             if (!tool_bar_p)
               last_tool_bar_item = -1;
@@ -6904,13 +6779,11 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
         else
           dpyinfo->grabbed &= ~(1 << event.xbutton.button);
 
         else
           dpyinfo->grabbed &= ~(1 << event.xbutton.button);
 
-        if (numchars >= 1 && emacs_event.kind != NO_EVENT)
-          {
-            bcopy (&emacs_event, bufp, sizeof (struct input_event));
-            bufp++;
-            count++;
-            numchars--;
-          }
+       /* Ignore any mouse motion that happened before this event;
+          any subsequent mouse-movement Emacs events should reflect
+          only motion after the ButtonPress/Release.  */
+       if (f != 0)
+         f->mouse_moved = 0;
 
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
         f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
 
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
         f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
@@ -6998,16 +6871,38 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
     break;
     }
 
     break;
     }
 
-  goto ret;
+ done:
+  if (inev.ie.kind != NO_EVENT)
+    {
+      kbd_buffer_store_event_hold (&inev.ie, hold_quit);
+      count++;
+    }
 
 
- out:
-  *finish = X_EVENT_GOTO_OUT;
+  if (do_help
+      && !(hold_quit && hold_quit->kind != NO_EVENT))
+    {
+      Lisp_Object frame;
 
 
- ret:
-  *bufp_r = bufp;
-  *numcharsp = numchars;
-  *eventp = event;
+      if (f)
+       XSETFRAME (frame, f);
+      else
+       frame = Qnil;
+
+      if (do_help > 0)
+       {
+         any_help_event_p = 1;
+         gen_help_event (help_echo_string, frame, help_echo_window,
+                         help_echo_object, help_echo_pos);
+       }
+      else
+       {
+         help_echo_string = Qnil;
+         gen_help_event (Qnil, frame, Qnil, Qnil, 0);
+       }
+      count++;
+    }
 
 
+  *eventp = event;
   return count;
 }
 
   return count;
 }
 
@@ -7023,28 +6918,12 @@ x_dispatch_event (event, display)
      Display *display;
 {
   struct x_display_info *dpyinfo;
      Display *display;
 {
   struct x_display_info *dpyinfo;
-  struct input_event bufp[10];
-  struct input_event *bufpp;
-  int numchars = 10;
   int finish = X_EVENT_NORMAL;
 
   int finish = X_EVENT_NORMAL;
 
-  for (bufpp = bufp; bufpp != bufp + 10; bufpp++)
-    EVENT_INIT (*bufpp);
-  bufpp = bufp;
-
   dpyinfo = x_display_info_for_display (display);
 
   if (dpyinfo)
   dpyinfo = x_display_info_for_display (display);
 
   if (dpyinfo)
-    {
-      int i, events;
-      events = handle_one_xevent (dpyinfo,
-                                  event,
-                                  &bufpp,
-                                  &numchars,
-                                  &finish);
-      for (i = 0; i < events; ++i)
-        kbd_buffer_store_event (&bufp[i]);
-    }
+    handle_one_xevent (dpyinfo, event, &finish, 0);
 
   return finish;
 }
 
   return finish;
 }
@@ -7054,19 +6933,16 @@ x_dispatch_event (event, display)
    This routine is called by the SIGIO handler.
    We return as soon as there are no more events to be read.
 
    This routine is called by the SIGIO handler.
    We return as soon as there are no more events to be read.
 
-   Events representing keys are stored in buffer BUFP,
-   which can hold up to NUMCHARS characters.
    We return the number of characters stored into the buffer,
    thus pretending to be `read'.
 
    EXPECTED is nonzero if the caller knows input is available.  */
 
 static int
    We return the number of characters stored into the buffer,
    thus pretending to be `read'.
 
    EXPECTED is nonzero if the caller knows input is available.  */
 
 static int
-XTread_socket (sd, bufp, numchars, expected)
+XTread_socket (sd, expected, hold_quit)
      register int sd;
      register int sd;
-     /* register */ struct input_event *bufp;
-     /* register */ int numchars;
      int expected;
      int expected;
+     struct input_event *hold_quit;
 {
   int count = 0;
   XEvent event;
 {
   int count = 0;
   XEvent event;
@@ -7085,9 +6961,6 @@ XTread_socket (sd, bufp, numchars, expected)
   /* So people can tell when we have read the available input.  */
   input_signal_count++;
 
   /* So people can tell when we have read the available input.  */
   input_signal_count++;
 
-  if (numchars <= 0)
-    abort ();                  /* Don't think this happens.  */
-
   ++handling_signal;
 
   /* Find the display we are supposed to read input for.
   ++handling_signal;
 
   /* Find the display we are supposed to read input for.
@@ -7129,9 +7002,18 @@ XTread_socket (sd, bufp, numchars, expected)
        }
 
 #ifdef HAVE_X_SM
        }
 
 #ifdef HAVE_X_SM
-      BLOCK_INPUT;
-      count += x_session_check_input (bufp, &numchars);
-      UNBLOCK_INPUT;
+      {
+       struct input_event inev;
+       BLOCK_INPUT;
+       /* We don't need to EVENT_INIT (inev) here, as
+          x_session_check_input copies an entire input_event.  */
+       if (x_session_check_input (&inev))
+         {
+           kbd_buffer_store_event_hold (&inev, hold_quit);
+           count++;
+         }
+       UNBLOCK_INPUT;
+      }
 #endif
 
 #ifndef USE_GTK
 #endif
 
 #ifndef USE_GTK
@@ -7148,11 +7030,7 @@ XTread_socket (sd, bufp, numchars, expected)
 #endif
          event_found = 1;
 
 #endif
          event_found = 1;
 
-          count += handle_one_xevent (dpyinfo,
-                                      &event,
-                                      &bufp,
-                                      &numchars,
-                                      &finish);
+          count += handle_one_xevent (dpyinfo, &event, &finish, hold_quit);
 
           if (finish == X_EVENT_GOTO_OUT)
             goto out;
 
           if (finish == X_EVENT_GOTO_OUT)
             goto out;
@@ -7173,14 +7051,13 @@ XTread_socket (sd, bufp, numchars, expected)
   while (gtk_events_pending ())
     {
       current_count = count;
   while (gtk_events_pending ())
     {
       current_count = count;
-      current_numcharsp = &numchars;
-      current_bufp = &bufp;
+      current_hold_quit = hold_quit;
 
       gtk_main_iteration ();
 
       count = current_count;
 
       gtk_main_iteration ();
 
       count = current_count;
-      current_bufp = 0;
-      current_numcharsp = 0;
+      current_count = -1;
+      current_hold_quit = 0;
 
       if (current_finish == X_EVENT_GOTO_OUT)
         break;
 
       if (current_finish == X_EVENT_GOTO_OUT)
         break;
@@ -7220,8 +7097,9 @@ XTread_socket (sd, bufp, numchars, expected)
       pending_autoraise_frame = 0;
     }
 
       pending_autoraise_frame = 0;
     }
 
-  UNBLOCK_INPUT;
   --handling_signal;
   --handling_signal;
+  UNBLOCK_INPUT;
+
   return count;
 }
 
   return count;
 }
 
@@ -7240,19 +7118,20 @@ XTread_socket (sd, bufp, numchars, expected)
    mode lines must be clipped to the whole window.  */
 
 static void
    mode lines must be clipped to the whole window.  */
 
 static void
-x_clip_to_row (w, row, gc)
+x_clip_to_row (w, row, area, gc)
      struct window *w;
      struct glyph_row *row;
      struct window *w;
      struct glyph_row *row;
+     int area;
      GC gc;
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   XRectangle clip_rect;
      GC gc;
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   XRectangle clip_rect;
-  int window_y, window_width;
+  int window_x, window_y, window_width;
 
 
-  window_box (w, -1, 0, &window_y, &window_width, 0);
+  window_box (w, area, &window_x, &window_y, &window_width, 0);
 
 
-  clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
-  clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
+  clip_rect.x = window_x;
+  clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y));
   clip_rect.y = max (clip_rect.y, window_y);
   clip_rect.width = window_width;
   clip_rect.height = row->visible_height;
   clip_rect.y = max (clip_rect.y, window_y);
   clip_rect.width = window_width;
   clip_rect.height = row->visible_height;
@@ -7282,28 +7161,10 @@ x_draw_hollow_cursor (w, row)
   if (cursor_glyph == NULL)
     return;
 
   if (cursor_glyph == NULL)
     return;
 
-  /* Compute the width of the rectangle to draw.  If on a stretch
-     glyph, and `x-stretch-block-cursor' is nil, don't draw a
-     rectangle as wide as the glyph, but use a canonical character
-     width instead.  */
-  wd = cursor_glyph->pixel_width - 1;
-  if (cursor_glyph->type == STRETCH_GLYPH
-      && !x_stretch_cursor_p)
-    wd = min (FRAME_COLUMN_WIDTH (f), wd);
-  w->phys_cursor_width = wd;
-
-  /* Compute frame-relative coordinates from window-relative
-     coordinates.  */
+  /* Compute frame-relative coordinates for phys cursor.  */
   x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
   x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
-  y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y);
-
-  /* Compute the proper height and ascent of the rectangle, based
-     on the actual glyph.  Using the full height of the row looks
-     bad when there are tall images on that row.  */
-  h = max (FRAME_LINE_HEIGHT (f), cursor_glyph->ascent + cursor_glyph->descent);
-  if (h < row->height)
-    y += row->ascent /* - w->phys_cursor_ascent */ + cursor_glyph->descent - h;
-  h--;
+  y = get_phys_cursor_geometry (w, row, cursor_glyph, &h);
+  wd = w->phys_cursor_width;
 
   /* The foreground of cursor_gc is typically the same as the normal
      background color, which can cause the cursor box to be invisible.  */
 
   /* The foreground of cursor_gc is typically the same as the normal
      background color, which can cause the cursor box to be invisible.  */
@@ -7316,8 +7177,8 @@ x_draw_hollow_cursor (w, row)
   gc = dpyinfo->scratch_cursor_gc;
 
   /* Set clipping, draw the rectangle, and reset clipping again.  */
   gc = dpyinfo->scratch_cursor_gc;
 
   /* Set clipping, draw the rectangle, and reset clipping again.  */
-  x_clip_to_row (w, row, gc);
-  XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
+  x_clip_to_row (w, row, TEXT_AREA, gc);
+  XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h - 1);
   XSetClipMask (dpy, gc, None);
 }
 
   XSetClipMask (dpy, gc, None);
 }
 
@@ -7388,7 +7249,7 @@ x_draw_bar_cursor (w, row, width, kind)
       width = min (cursor_glyph->pixel_width, width);
 
       w->phys_cursor_width = width;
       width = min (cursor_glyph->pixel_width, width);
 
       w->phys_cursor_width = width;
-      x_clip_to_row (w, row, gc);
+      x_clip_to_row (w, row, TEXT_AREA, gc);
 
       if (kind == BAR_CURSOR)
          XFillRectangle (dpy, window, gc,
 
       if (kind == BAR_CURSOR)
          XFillRectangle (dpy, window, gc,
@@ -7448,6 +7309,13 @@ x_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, activ
       w->phys_cursor_type = cursor_type;
       w->phys_cursor_on_p = 1;
 
       w->phys_cursor_type = cursor_type;
       w->phys_cursor_on_p = 1;
 
+      if (glyph_row->exact_window_width_line_p
+         && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
+       {
+         glyph_row->cursor_in_fringe_p = 1;
+         draw_fringe_bitmap (w, glyph_row, 0);
+       }
+      else
       switch (cursor_type)
        {
        case HOLLOW_BOX_CURSOR:
       switch (cursor_type)
        {
        case HOLLOW_BOX_CURSOR:
@@ -7523,10 +7391,30 @@ x_bitmap_icon (f, file)
       /* Create the GNU bitmap and mask if necessary.  */
       if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
        {
       /* Create the GNU bitmap and mask if necessary.  */
       if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
        {
-         FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
-           = x_create_bitmap_from_data (f, gnu_bits,
-                                        gnu_width, gnu_height);
-         x_create_bitmap_mask (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
+         int rc = -1;
+
+#if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
+#ifdef USE_GTK
+         if (xg_set_icon_from_xpm_data (f, gnu_xpm_bits))
+           return 0;
+#else
+         rc = x_create_bitmap_from_xpm_data (f, gnu_xpm_bits);
+         if (rc != -1)
+           FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id = rc;
+#endif /* USE_GTK */
+#endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
+
+         /* If all else fails, use the (black and white) xbm image. */
+         if (rc == -1)
+           {
+             rc = x_create_bitmap_from_data (f, gnu_xbm_bits,
+                                             gnu_xbm_width, gnu_xbm_height);
+             if (rc == -1)
+               return 1;
+
+             FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id = rc;
+             x_create_bitmap_mask (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
+           }
        }
 
       /* The first time we create the GNU bitmap and mask,
        }
 
       /* The first time we create the GNU bitmap and mask,
@@ -7580,9 +7468,18 @@ x_text_icon (f, icon_name)
 #define X_ERROR_MESSAGE_SIZE 200
 
 /* If non-nil, this should be a string.
 #define X_ERROR_MESSAGE_SIZE 200
 
 /* If non-nil, this should be a string.
-   It means catch X errors  and store the error message in this string.  */
+   It means catch X errors  and store the error message in this string.
 
 
-static Lisp_Object x_error_message_string;
+   The reason we use a stack is that x_catch_error/x_uncatch_error can
+   be called from a signal handler.
+*/
+
+struct x_error_message_stack {
+  char string[X_ERROR_MESSAGE_SIZE];
+  Display *dpy;
+  struct x_error_message_stack *prev;
+};
+static struct x_error_message_stack *x_error_message;
 
 /* An X error handler which stores the error message in
    x_error_message_string.  This is called from x_error_handler if
 
 /* An X error handler which stores the error message in
    x_error_message_string.  This is called from x_error_handler if
@@ -7594,7 +7491,7 @@ x_error_catcher (display, error)
      XErrorEvent *error;
 {
   XGetErrorText (display, error->error_code,
      XErrorEvent *error;
 {
   XGetErrorText (display, error->error_code,
-                SDATA (x_error_message_string),
+                x_error_message->string,
                 X_ERROR_MESSAGE_SIZE);
 }
 
                 X_ERROR_MESSAGE_SIZE);
 }
 
@@ -7612,41 +7509,42 @@ x_error_catcher (display, error)
    Calling x_uncatch_errors resumes the normal error handling.  */
 
 void x_check_errors ();
    Calling x_uncatch_errors resumes the normal error handling.  */
 
 void x_check_errors ();
-static Lisp_Object x_catch_errors_unwind ();
 
 
-int
+void
 x_catch_errors (dpy)
      Display *dpy;
 {
 x_catch_errors (dpy)
      Display *dpy;
 {
-  int count = SPECPDL_INDEX ();
+  struct x_error_message_stack *data = xmalloc (sizeof (*data));
 
   /* Make sure any errors from previous requests have been dealt with.  */
   XSync (dpy, False);
 
 
   /* Make sure any errors from previous requests have been dealt with.  */
   XSync (dpy, False);
 
-  record_unwind_protect (x_catch_errors_unwind,
-                        Fcons (make_save_value (dpy, 0),
-                               x_error_message_string));
-
-  x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
-  SSET (x_error_message_string, 0, 0);
-
-  return count;
+  data->dpy = dpy;
+  data->string[0] = 0;
+  data->prev = x_error_message;
+  x_error_message = data;
 }
 
 }
 
-/* Unbind the binding that we made to check for X errors.  */
+/* Undo the last x_catch_errors call.
+   DPY should be the display that was passed to x_catch_errors.  */
 
 
-static Lisp_Object
-x_catch_errors_unwind (old_val)
-     Lisp_Object old_val;
+void
+x_uncatch_errors ()
 {
 {
-  Lisp_Object first;
+  struct x_error_message_stack *tmp;
 
 
-  first = XCAR (old_val);
-
-  XSync (XSAVE_VALUE (first)->pointer, False);
+  /* The display may have been closed before this function is called.
+     Check if it is still open before calling XSync.  */
+  if (x_display_info_for_display (x_error_message->dpy) != 0)
+    {
+      BLOCK_INPUT;
+      XSync (x_error_message->dpy, False);
+      UNBLOCK_INPUT;
+    }
 
 
-  x_error_message_string = XCDR (old_val);
-  return Qnil;
+  tmp = x_error_message;
+  x_error_message = x_error_message->prev;
+  xfree (tmp);
 }
 
 /* If any X protocol errors have arrived since the last call to
 }
 
 /* If any X protocol errors have arrived since the last call to
@@ -7661,8 +7559,13 @@ x_check_errors (dpy, format)
   /* Make sure to catch any errors incurred so far.  */
   XSync (dpy, False);
 
   /* Make sure to catch any errors incurred so far.  */
   XSync (dpy, False);
 
-  if (SREF (x_error_message_string, 0))
-    error (format, SDATA (x_error_message_string));
+  if (x_error_message->string[0])
+    {
+      char string[X_ERROR_MESSAGE_SIZE];
+      bcopy (x_error_message->string, string, X_ERROR_MESSAGE_SIZE);
+      x_uncatch_errors ();
+      error (format, string);
+    }
 }
 
 /* Nonzero if we had any X protocol errors
 }
 
 /* Nonzero if we had any X protocol errors
@@ -7675,7 +7578,7 @@ x_had_errors_p (dpy)
   /* Make sure to catch any errors incurred so far.  */
   XSync (dpy, False);
 
   /* Make sure to catch any errors incurred so far.  */
   XSync (dpy, False);
 
-  return SREF (x_error_message_string, 0) != 0;
+  return x_error_message->string[0] != 0;
 }
 
 /* Forget about any errors we have had, since we did x_catch_errors on DPY.  */
 }
 
 /* Forget about any errors we have had, since we did x_catch_errors on DPY.  */
@@ -7684,20 +7587,24 @@ void
 x_clear_errors (dpy)
      Display *dpy;
 {
 x_clear_errors (dpy)
      Display *dpy;
 {
-  SSET (x_error_message_string, 0, 0);
+  x_error_message->string[0] = 0;
 }
 
 }
 
-/* Stop catching X protocol errors and let them make Emacs die.
-   DPY should be the display that was passed to x_catch_errors.
-   COUNT should be the value that was returned by
-   the corresponding call to x_catch_errors.  */
+/* Close off all unclosed x_catch_errors calls.  */
 
 void
 
 void
-x_uncatch_errors (dpy, count)
-     Display *dpy;
-     int count;
+x_fully_uncatch_errors ()
+{
+  while (x_error_message)
+    x_uncatch_errors ();
+}
+
+/* Nonzero if x_catch_errors has been done and not yet canceled.  */
+
+int
+x_catching_errors ()
 {
 {
-  unbind_to (count, Qnil);
+  return x_error_message != 0;
 }
 
 #if 0
 }
 
 #if 0
@@ -7756,7 +7663,6 @@ x_connection_closed (dpy, error_message)
 {
   struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
   Lisp_Object frame, tail;
 {
   struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
   Lisp_Object frame, tail;
-  int count;
 
   error_msg = (char *) alloca (strlen (error_message) + 1);
   strcpy (error_msg, error_message);
 
   error_msg = (char *) alloca (strlen (error_message) + 1);
   strcpy (error_msg, error_message);
@@ -7766,7 +7672,7 @@ x_connection_closed (dpy, error_message)
      below.  Otherwise, we might end up with printing ``can't find per
      display information'' in the recursive call instead of printing
      the original message here.  */
      below.  Otherwise, we might end up with printing ``can't find per
      display information'' in the recursive call instead of printing
      the original message here.  */
-  count = x_catch_errors (dpy);
+  x_catch_errors (dpy);
 
   /* We have to close the display to inform Xt that it doesn't
      exist anymore.  If we don't, Xt will continue to wait for
 
   /* We have to close the display to inform Xt that it doesn't
      exist anymore.  If we don't, Xt will continue to wait for
@@ -7834,7 +7740,7 @@ x_connection_closed (dpy, error_message)
   if (dpyinfo)
     x_delete_display (dpyinfo);
 
   if (dpyinfo)
     x_delete_display (dpyinfo);
 
-  x_uncatch_errors (dpy, count);
+  x_uncatch_errors ();
 
   if (x_display_list == 0)
     {
 
   if (x_display_list == 0)
     {
@@ -7854,12 +7760,47 @@ x_connection_closed (dpy, error_message)
   error ("%s", error_msg);
 }
 
   error ("%s", error_msg);
 }
 
+/* We specifically use it before defining it, so that gcc doesn't inline it,
+   otherwise gdb doesn't know how to properly put a breakpoint on it.  */
+static void x_error_quitter (Display *display, XErrorEvent *error);
+
+/* This is the first-level handler for X protocol errors.
+   It calls x_error_quitter or x_error_catcher.  */
+
+static int
+x_error_handler (display, error)
+     Display *display;
+     XErrorEvent *error;
+{
+  if (x_error_message)
+    x_error_catcher (display, error);
+  else
+    x_error_quitter (display, error);
+  return 0;
+}
 
 /* This is the usual handler for X protocol errors.
    It kills all frames on the display that we got the error for.
    If that was the only one, it prints an error message and kills Emacs.  */
 
 
 /* This is the usual handler for X protocol errors.
    It kills all frames on the display that we got the error for.
    If that was the only one, it prints an error message and kills Emacs.  */
 
-static void
+/* .gdbinit puts a breakpoint here, so make sure it is not inlined.  */
+
+#if __GNUC__ >= 3  /* On GCC 3.0 we might get a warning.  */
+#define NO_INLINE __attribute__((noinline))
+#else
+#define NO_INLINE
+#endif
+
+/* Some versions of GNU/Linux define noinline in their headers.  */
+
+#ifdef noinline
+#undef noinline
+#endif
+
+/* On older GCC versions, just putting x_error_quitter
+   after x_error_handler prevents inlining into the former.  */
+
+static void NO_INLINE
 x_error_quitter (display, error)
      Display *display;
      XErrorEvent *error;
 x_error_quitter (display, error)
      Display *display;
      XErrorEvent *error;
@@ -7876,21 +7817,6 @@ x_error_quitter (display, error)
 }
 
 
 }
 
 
-/* This is the first-level handler for X protocol errors.
-   It calls x_error_quitter or x_error_catcher.  */
-
-static int
-x_error_handler (display, error)
-     Display *display;
-     XErrorEvent *error;
-{
-  if (! NILP (x_error_message_string))
-    x_error_catcher (display, error);
-  else
-    x_error_quitter (display, error);
-  return 0;
-}
-
 /* This is the handler for X IO errors, always.
    It kills all frames on the display that we lost touch with.
    If that was the only one, it prints an error message and kills Emacs.  */
 /* This is the handler for X IO errors, always.
    It kills all frames on the display that we lost touch with.
    If that was the only one, it prints an error message and kills Emacs.  */
@@ -7928,7 +7854,8 @@ x_new_font (f, fontname)
   FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
   FRAME_FONTSET (f) = -1;
 
   FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
   FRAME_FONTSET (f) = -1;
 
-  FRAME_COLUMN_WIDTH (f) = FONT_WIDTH (FRAME_FONT (f));
+  FRAME_COLUMN_WIDTH (f) = fontp->average_width;
+  FRAME_SPACE_WIDTH (f) = fontp->space_width;
   FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
 
   compute_fringe_widths (f, 1);
   FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
 
   compute_fringe_widths (f, 1);
@@ -8036,11 +7963,7 @@ xim_destroy_callback (xim, client_data, call_data)
       if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
        {
          FRAME_XIC (f) = NULL;
       if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
        {
          FRAME_XIC (f) = NULL;
-         if (FRAME_XIC_FONTSET (f))
-           {
-             XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
-             FRAME_XIC_FONTSET (f) = NULL;
-           }
+          xic_free_xfontset (f);
        }
     }
 
        }
     }
 
@@ -8233,70 +8156,18 @@ void
 x_calc_absolute_position (f)
      struct frame *f;
 {
 x_calc_absolute_position (f)
      struct frame *f;
 {
-  Window child;
-  int win_x = 0, win_y = 0;
   int flags = f->size_hint_flags;
   int flags = f->size_hint_flags;
-  int this_window;
 
   /* We have nothing to do if the current position
      is already for the top-left corner.  */
   if (! ((flags & XNegative) || (flags & YNegative)))
     return;
 
 
   /* We have nothing to do if the current position
      is already for the top-left corner.  */
   if (! ((flags & XNegative) || (flags & YNegative)))
     return;
 
-  this_window = FRAME_OUTER_WINDOW (f);
-
-  /* Find the position of the outside upper-left corner of
-     the inner window, with respect to the outer window.
-     But do this only if we will need the results.  */
-  if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
-    {
-      int count;
-
-      BLOCK_INPUT;
-      count = x_catch_errors (FRAME_X_DISPLAY (f));
-      while (1)
-       {
-         x_clear_errors (FRAME_X_DISPLAY (f));
-         XTranslateCoordinates (FRAME_X_DISPLAY (f),
-
-                                /* From-window, to-window.  */
-                                this_window,
-                                f->output_data.x->parent_desc,
-
-                                /* From-position, to-position.  */
-                                0, 0, &win_x, &win_y,
-
-                                /* Child of win.  */
-                                &child);
-         if (x_had_errors_p (FRAME_X_DISPLAY (f)))
-           {
-             Window newroot, newparent = 0xdeadbeef;
-             Window *newchildren;
-             unsigned int nchildren;
-
-             if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
-                               &newparent, &newchildren, &nchildren))
-               break;
-
-             XFree ((char *) newchildren);
-
-             f->output_data.x->parent_desc = newparent;
-           }
-         else
-           break;
-       }
-
-      x_uncatch_errors (FRAME_X_DISPLAY (f), count);
-      UNBLOCK_INPUT;
-    }
-
   /* Treat negative positions as relative to the leftmost bottommost
      position that fits on the screen.  */
   if (flags & XNegative)
     f->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
   /* Treat negative positions as relative to the leftmost bottommost
      position that fits on the screen.  */
   if (flags & XNegative)
     f->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
-                  - 2 * f->border_width - win_x
-                  - FRAME_PIXEL_WIDTH (f)
-                  + f->left_pos);
+                   - FRAME_PIXEL_WIDTH (f) + f->left_pos);
 
   {
     int height = FRAME_PIXEL_HEIGHT (f);
 
   {
     int height = FRAME_PIXEL_HEIGHT (f);
@@ -8318,11 +8189,7 @@ x_calc_absolute_position (f)
 #endif
 
   if (flags & YNegative)
 #endif
 
   if (flags & YNegative)
-    f->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
-                 - 2 * f->border_width
-                 - win_y
-                 - height
-                 + f->top_pos);
+    f->top_pos = (FRAME_X_DISPLAY_INFO (f)->height - height + f->top_pos);
   }
 
   /* The left_pos and top_pos
   }
 
   /* The left_pos and top_pos
@@ -8357,24 +8224,13 @@ x_set_offset (f, xoff, yoff, change_gravity)
       f->win_gravity = NorthWestGravity;
     }
   x_calc_absolute_position (f);
       f->win_gravity = NorthWestGravity;
     }
   x_calc_absolute_position (f);
+
   BLOCK_INPUT;
   x_wm_set_size_hint (f, (long) 0, 0);
 
   modified_left = f->left_pos;
   modified_top = f->top_pos;
 
   BLOCK_INPUT;
   x_wm_set_size_hint (f, (long) 0, 0);
 
   modified_left = f->left_pos;
   modified_top = f->top_pos;
 
-#if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
-        this seems to be unnecessary and incorrect.  rms, 4/17/97.  */
-  /* It is a mystery why we need to add the border_width here
-     when the frame is already visible, but experiment says we do.  */
-  if (change_gravity != 0)
-    {
-      modified_left += f->border_width;
-      modified_top += f->border_width;
-    }
-#endif
-
   if (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A)
     {
       /* Some WMs (twm, wmaker at least) has an offset that is smaller
   if (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A)
     {
       /* Some WMs (twm, wmaker at least) has an offset that is smaller
@@ -8449,7 +8305,9 @@ x_check_expected_move (f)
         FRAME_X_OUTPUT (f)->move_offset_left = expect_left - f->left_pos;
         FRAME_X_OUTPUT (f)->move_offset_top = expect_top - f->top_pos;
 
         FRAME_X_OUTPUT (f)->move_offset_left = expect_left - f->left_pos;
         FRAME_X_OUTPUT (f)->move_offset_top = expect_top - f->top_pos;
 
-        x_set_offset (f, expect_left, expect_top, 1);
+        f->left_pos = expect_left;
+        f->top_pos = expect_top;
+        x_set_offset (f, expect_left, expect_top, 0);
       }
     else if (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN)
       FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_B;
       }
     else if (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN)
       FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_B;
@@ -9409,7 +9267,14 @@ x_wm_set_icon_pixmap (f, pixmap_id)
 #endif
     }
 
 #endif
     }
 
-#ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state.  */
+
+#ifdef USE_GTK
+  {
+    xg_set_frame_icon (f, icon_pixmap, icon_mask);
+    return;
+  }
+
+#elif defined (USE_X_TOOLKIT) /* same as in x_wm_set_window_state.  */
 
   {
     Arg al[1];
 
   {
     Arg al[1];
@@ -9419,12 +9284,12 @@ x_wm_set_icon_pixmap (f, pixmap_id)
     XtSetValues (f->output_data.x->widget, al, 1);
   }
 
     XtSetValues (f->output_data.x->widget, al, 1);
   }
 
-#else /* not USE_X_TOOLKIT */
+#else /* not USE_X_TOOLKIT && not USE_GTK */
 
   f->output_data.x->wm_hints.flags |= (IconPixmapHint | IconMaskHint);
   XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
 
 
   f->output_data.x->wm_hints.flags |= (IconPixmapHint | IconMaskHint);
   XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
 
-#endif /* not USE_X_TOOLKIT */
+#endif /* not USE_X_TOOLKIT && not USE_GTK */
 }
 
 void
 }
 
 void
@@ -9481,7 +9346,6 @@ x_list_fonts (f, pattern, size, maxnames)
     = f ? FRAME_X_DISPLAY_INFO (f) : x_display_list;
   Display *dpy = dpyinfo->display;
   int try_XLoadQueryFont = 0;
     = f ? FRAME_X_DISPLAY_INFO (f) : x_display_list;
   Display *dpy = dpyinfo->display;
   int try_XLoadQueryFont = 0;
-  int count;
   int allow_auto_scaled_font = 0;
 
   if (size < 0)
   int allow_auto_scaled_font = 0;
 
   if (size < 0)
@@ -9521,7 +9385,7 @@ x_list_fonts (f, pattern, size, maxnames)
       /* At first, put PATTERN in the cache.  */
 
       BLOCK_INPUT;
       /* At first, put PATTERN in the cache.  */
 
       BLOCK_INPUT;
-      count = x_catch_errors (dpy);
+      x_catch_errors (dpy);
 
       if (try_XLoadQueryFont)
        {
 
       if (try_XLoadQueryFont)
        {
@@ -9602,7 +9466,7 @@ x_list_fonts (f, pattern, size, maxnames)
            }
        }
 
            }
        }
 
-      x_uncatch_errors (dpy, count);
+      x_uncatch_errors ();
       UNBLOCK_INPUT;
 
       if (names)
       UNBLOCK_INPUT;
 
       if (names)
@@ -9693,7 +9557,7 @@ x_list_fonts (f, pattern, size, maxnames)
              XFontStruct *thisinfo;
 
              BLOCK_INPUT;
              XFontStruct *thisinfo;
 
              BLOCK_INPUT;
-             count = x_catch_errors (dpy);
+             x_catch_errors (dpy);
              thisinfo = XLoadQueryFont (dpy,
                                         SDATA (XCAR (tem)));
              if (x_had_errors_p (dpy))
              thisinfo = XLoadQueryFont (dpy,
                                         SDATA (XCAR (tem)));
              if (x_had_errors_p (dpy))
@@ -9703,7 +9567,7 @@ x_list_fonts (f, pattern, size, maxnames)
                  thisinfo = NULL;
                  x_clear_errors (dpy);
                }
                  thisinfo = NULL;
                  x_clear_errors (dpy);
                }
-             x_uncatch_errors (dpy, count);
+             x_uncatch_errors ();
              UNBLOCK_INPUT;
 
              if (thisinfo)
              UNBLOCK_INPUT;
 
              if (thisinfo)
@@ -9859,7 +9723,6 @@ x_load_font (f, fontname, size)
 {
   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
   Lisp_Object font_names;
 {
   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
   Lisp_Object font_names;
-  int count;
 
   /* Get a list of all the fonts that match this name.  Once we
      have a list of matching fonts, we compare them against the fonts
 
   /* Get a list of all the fonts that match this name.  Once we
      have a list of matching fonts, we compare them against the fonts
@@ -9898,7 +9761,7 @@ x_load_font (f, fontname, size)
       fontname = (char *) SDATA (XCAR (font_names));
 
     BLOCK_INPUT;
       fontname = (char *) SDATA (XCAR (font_names));
 
     BLOCK_INPUT;
-    count = x_catch_errors (FRAME_X_DISPLAY (f));
+    x_catch_errors (FRAME_X_DISPLAY (f));
     font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
     if (x_had_errors_p (FRAME_X_DISPLAY (f)))
       {
     font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
     if (x_had_errors_p (FRAME_X_DISPLAY (f)))
       {
@@ -9907,7 +9770,7 @@ x_load_font (f, fontname, size)
        font = NULL;
        x_clear_errors (FRAME_X_DISPLAY (f));
       }
        font = NULL;
        x_clear_errors (FRAME_X_DISPLAY (f));
       }
-    x_uncatch_errors (FRAME_X_DISPLAY (f), count);
+    x_uncatch_errors ();
     UNBLOCK_INPUT;
     if (!font)
       return NULL;
     UNBLOCK_INPUT;
     if (!font)
       return NULL;
@@ -9940,6 +9803,43 @@ x_load_font (f, fontname, size)
     fontp->name = (char *) xmalloc (strlen (fontname) + 1);
     bcopy (fontname, fontp->name, strlen (fontname) + 1);
 
     fontp->name = (char *) xmalloc (strlen (fontname) + 1);
     bcopy (fontname, fontp->name, strlen (fontname) + 1);
 
+    if (font->min_bounds.width == font->max_bounds.width)
+      {
+       /* Fixed width font.  */
+       fontp->average_width = fontp->space_width = font->min_bounds.width;
+      }
+    else
+      {
+       XChar2b char2b;
+       XCharStruct *pcm;
+
+       char2b.byte1 = 0x00, char2b.byte2 = 0x20;
+       pcm = x_per_char_metric (font, &char2b, 0);
+       if (pcm)
+         fontp->space_width = pcm->width;
+       else
+         fontp->space_width = FONT_WIDTH (font);
+
+       fontp->average_width
+         = (XGetFontProperty (font, dpyinfo->Xatom_AVERAGE_WIDTH, &value)
+            ? (long) value / 10 : 0);
+       if (fontp->average_width < 0)
+         fontp->average_width = - fontp->average_width;
+       if (fontp->average_width == 0)
+         {
+           if (pcm)
+             {
+               int width = pcm->width;
+               for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
+                 if ((pcm = x_per_char_metric (font, &char2b, 0)) != NULL)
+                   width += pcm->width;
+               fontp->average_width = width / 95;
+             }
+           else
+             fontp->average_width = FONT_WIDTH (font);
+         }
+      }
+
     /* Try to get the full name of FONT.  Put it in FULL_NAME.  */
     full_name = 0;
     if (XGetFontProperty (font, XA_FONT, &value))
     /* Try to get the full name of FONT.  Put it in FULL_NAME.  */
     full_name = 0;
     if (XGetFontProperty (font, XA_FONT, &value))
@@ -10489,7 +10389,7 @@ x_term_init (display_name, xrm_option, resource_name)
       get_bits_and_offset (dpyinfo->visual->green_mask,
                            &dpyinfo->green_bits, &dpyinfo->green_offset);
     }
       get_bits_and_offset (dpyinfo->visual->green_mask,
                            &dpyinfo->green_bits, &dpyinfo->green_offset);
     }
-      
+
   /* See if a private colormap is requested.  */
   if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
     {
   /* See if a private colormap is requested.  */
   if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
     {
@@ -10514,10 +10414,12 @@ x_term_init (display_name, xrm_option, resource_name)
     int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
     double pixels = DisplayHeight (dpyinfo->display, screen_number);
     double mm = DisplayHeightMM (dpyinfo->display, screen_number);
     int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
     double pixels = DisplayHeight (dpyinfo->display, screen_number);
     double mm = DisplayHeightMM (dpyinfo->display, screen_number);
-    dpyinfo->resy = pixels * 25.4 / mm;
+    /* Mac OS X 10.3's Xserver sometimes reports 0.0mm.  */
+    dpyinfo->resy = (mm < 1) ? 100 : pixels * 25.4 / mm;
     pixels = DisplayWidth (dpyinfo->display, screen_number);
     pixels = DisplayWidth (dpyinfo->display, screen_number);
+    /* Mac OS X 10.3's Xserver sometimes reports 0.0mm.  */
     mm = DisplayWidthMM (dpyinfo->display, screen_number);
     mm = DisplayWidthMM (dpyinfo->display, screen_number);
-    dpyinfo->resx = pixels * 25.4 / mm;
+    dpyinfo->resx = (mm < 1) ? 100 : pixels * 25.4 / mm;
   }
 
   dpyinfo->Xatom_wm_protocols
   }
 
   dpyinfo->Xatom_wm_protocols
@@ -10565,6 +10467,8 @@ x_term_init (display_name, xrm_option, resource_name)
   /* For properties of font.  */
   dpyinfo->Xatom_PIXEL_SIZE
     = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
   /* For properties of font.  */
   dpyinfo->Xatom_PIXEL_SIZE
     = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
+  dpyinfo->Xatom_AVERAGE_WIDTH
+    = XInternAtom (dpyinfo->display, "AVERAGE_WIDTH", False);
   dpyinfo->Xatom_MULE_BASELINE_OFFSET
     = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
   dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
   dpyinfo->Xatom_MULE_BASELINE_OFFSET
     = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
   dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
@@ -10639,7 +10543,6 @@ x_term_init (display_name, xrm_option, resource_name)
     Display *dpy = dpyinfo->display;
     XrmValue d, fr, to;
     Font font;
     Display *dpy = dpyinfo->display;
     XrmValue d, fr, to;
     Font font;
-    int count;
 
     d.addr = (XPointer)&dpy;
     d.size = sizeof (Display *);
 
     d.addr = (XPointer)&dpy;
     d.size = sizeof (Display *);
@@ -10647,12 +10550,12 @@ x_term_init (display_name, xrm_option, resource_name)
     fr.size = sizeof (XtDefaultFont);
     to.size = sizeof (Font *);
     to.addr = (XPointer)&font;
     fr.size = sizeof (XtDefaultFont);
     to.size = sizeof (Font *);
     to.addr = (XPointer)&font;
-    count = x_catch_errors (dpy);
+    x_catch_errors (dpy);
     if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
       abort ();
     if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
       XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
     if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
       abort ();
     if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
       XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
-    x_uncatch_errors (dpy, count);
+    x_uncatch_errors ();
   }
 #endif
 #endif
   }
 #endif
 #endif
@@ -10819,7 +10722,7 @@ static struct redisplay_interface x_redisplay_interface =
   x_update_window_end,
   x_cursor_to,
   x_flush,
   x_update_window_end,
   x_cursor_to,
   x_flush,
-#ifndef XFlush
+#ifdef XFlush
   x_flush,
 #else
   0,  /* flush_display_optional */
   x_flush,
 #else
   0,  /* flush_display_optional */
@@ -10828,6 +10731,8 @@ static struct redisplay_interface x_redisplay_interface =
   x_get_glyph_overhangs,
   x_fix_overlapping_area,
   x_draw_fringe_bitmap,
   x_get_glyph_overhangs,
   x_fix_overlapping_area,
   x_draw_fringe_bitmap,
+  0, /* define_fringe_bitmap */
+  0, /* destroy_fringe_bitmap */
   x_per_char_metric,
   x_encode_char,
   x_compute_glyph_string_overhangs,
   x_per_char_metric,
   x_encode_char,
   x_compute_glyph_string_overhangs,
@@ -10874,6 +10779,11 @@ x_initialize ()
   x_noop_count = 0;
   last_tool_bar_item = -1;
   any_help_event_p = 0;
   x_noop_count = 0;
   last_tool_bar_item = -1;
   any_help_event_p = 0;
+  ignore_next_mouse_click_timeout = 0;
+
+#ifdef USE_GTK
+  current_count = -1;
+#endif
 
   /* Try to use interrupt input; if we can't, then start polling.  */
   Fset_input_mode (Qt, Qnil, Qt, Qnil);
 
   /* Try to use interrupt input; if we can't, then start polling.  */
   Fset_input_mode (Qt, Qnil, Qt, Qnil);
@@ -10929,8 +10839,7 @@ x_initialize ()
 void
 syms_of_xterm ()
 {
 void
 syms_of_xterm ()
 {
-  staticpro (&x_error_message_string);
-  x_error_message_string = Qnil;
+  x_error_message = NULL;
 
   staticpro (&x_display_name_list);
   x_display_name_list = Qnil;
 
   staticpro (&x_display_name_list);
   x_display_name_list = Qnil;
@@ -10957,6 +10866,16 @@ UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
 to 4.1, set this to nil.  */);
   x_use_underline_position_properties = 1;
 
 to 4.1, set this to nil.  */);
   x_use_underline_position_properties = 1;
 
+  DEFVAR_BOOL ("x-mouse-click-focus-ignore-position",
+              &x_mouse_click_focus_ignore_position,
+    doc: /* Non-nil means that a mouse click to focus a frame does not move point.
+This variable is only used when the window manager requires that you
+click on a frame to select it (give it focus).  In that case, a value
+of nil, means that the selected window and cursor position changes to
+reflect the mouse click position, while a non-nil value means that the
+selected window or cursor position is preserved.  */);
+  x_mouse_click_focus_ignore_position = 0;
+
   DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
     doc: /* What X toolkit scroll bars Emacs uses.
 A value of nil means Emacs doesn't use X toolkit scroll bars.
   DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
     doc: /* What X toolkit scroll bars Emacs uses.
 A value of nil means Emacs doesn't use X toolkit scroll bars.