]> code.delx.au - gnu-emacs/blobdiff - src/xterm.c
Revision: miles@gnu.org--gnu-2004/emacs--unicode--0--patch-22
[gnu-emacs] / src / xterm.c
index a31178467020f9fc32012641d322afa4ef057da3..6eb106e5b3fae63a4c8481d1dc1121d685173414 100644 (file)
@@ -1,5 +1,5 @@
 /* X Communication module for terminals which understand the X protocol.
-   Copyright (C) 1989, 93, 94, 95, 96, 97, 98, 1999, 2000, 01, 02, 2003
+   Copyright (C) 1989, 93, 94, 95, 96, 97, 98, 1999, 2000,01,02,03,04
    Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -68,6 +68,7 @@ Boston, MA 02111-1307, USA.  */
 /* #include <sys/param.h>  */
 
 #include "charset.h"
+#include "character.h"
 #include "coding.h"
 #include "ccl.h"
 #include "frame.h"
@@ -217,6 +218,17 @@ static String Xt_default_resources[] = {0};
 
 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)
@@ -287,7 +299,7 @@ extern Lisp_Object Vcommand_line_args, Vsystem_name;
 
 extern Lisp_Object Vx_no_window_manager;
 
-extern Lisp_Object Qface, Qmouse_face, Qeql;
+extern Lisp_Object Qeql;
 
 extern int errno;
 
@@ -336,16 +348,10 @@ 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 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 *));
@@ -364,11 +370,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 *));
-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.  */
@@ -570,6 +573,9 @@ x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
                                output_cursor.x, output_cursor.y);
 
       x_draw_vertical_border (w);
+
+      draw_window_fringes (w);
+
       UNBLOCK_INPUT;
     }
 
@@ -649,11 +655,7 @@ x_after_update_window_line (desired_row)
   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
@@ -697,11 +699,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;
+  int rowY;
 
   /* 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, gc);
+      row->y = oldY;
+      row->visible_height = oldVH;
+    }
+  else
+    x_clip_to_row (w, row, 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
@@ -719,20 +736,49 @@ x_draw_fringe_bitmap (w, row, p)
        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));
+      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,
-                                           face->foreground,
+                                           (p->cursor_p
+                                            ? (p->overlay_p ? face->background
+                                               : f->output_data.x->cursor_pixel)
+                                            : face->foreground),
                                            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);
+
+      if (p->overlay_p)
+       {
+         gcv.clip_mask = (Pixmap) 0;
+         XChangeGC (display, gc, GCClipMask, &gcv);
+         XFreePixmap (display, clipmask);
+       }
     }
 
   XSetClipMask (display, gc, None);
@@ -766,7 +812,8 @@ XTreset_terminal_modes ()
 
 /* Function prototypes of this page.  */
 
-static int x_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
+static int x_encode_char P_ ((int, XChar2b *, struct font_info *,
+                             struct charset *, int *));
 
 
 /* Get metrics of character CHAR2B in FONT.  Value is null if CHAR2B
@@ -845,13 +892,13 @@ x_per_char_metric (font, char2b, font_type)
    the two-byte form of C.  Encoding is returned in *CHAR2B.  */
 
 static int
-x_encode_char (c, char2b, font_info, two_byte_p)
+x_encode_char (c, char2b, font_info, charset, two_byte_p)
      int c;
      XChar2b *char2b;
      struct font_info *font_info;
+     struct charset *charset;
      int *two_byte_p;
 {
-  int charset = CHAR_CHARSET (c);
   XFontStruct *font = font_info->font;
 
   /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
@@ -864,31 +911,31 @@ x_encode_char (c, char2b, font_info, two_byte_p)
 
       if (CHARSET_DIMENSION (charset) == 1)
        {
-         ccl->reg[0] = charset;
+         ccl->reg[0] = CHARSET_ID (charset);
          ccl->reg[1] = char2b->byte2;
          ccl->reg[2] = -1;
        }
       else
        {
-         ccl->reg[0] = charset;
+         ccl->reg[0] = CHARSET_ID (charset);
          ccl->reg[1] = char2b->byte1;
          ccl->reg[2] = char2b->byte2;
        }
 
-      ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
+      ccl_driver (ccl, NULL, NULL, 0, 0, Qnil);
 
       /* We assume that MSBs are appropriately set/reset by CCL
         program.  */
       if (font->max_byte1 == 0)        /* 1-byte font */
-       char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
+       STORE_XCHAR2B (char2b, 0, ccl->reg[1]);
       else
-       char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
+       STORE_XCHAR2B (char2b, ccl->reg[1], ccl->reg[2]);
     }
-  else if (font_info->encoding[charset])
+  else if (font_info->encoding_type)
     {
       /* Fixed encoding scheme.  See fontset.h for the meaning of the
         encoding numbers.  */
-      int enc = font_info->encoding[charset];
+      unsigned char enc = font_info->encoding_type;
 
       if ((enc == 1 || enc == 2)
          && CHARSET_DIMENSION (charset) == 2)
@@ -936,7 +983,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,
-                                   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 *));
 
@@ -1015,9 +1063,9 @@ x_set_mouse_face_gc (s)
     face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
 
   if (s->first_glyph->type == CHAR_GLYPH)
-    face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
+    face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch, -1, Qnil);
   else
-    face_id = FACE_FOR_CHAR (s->f, face, 0);
+    face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil);
   s->face = FACE_FROM_ID (s->f, face_id);
   PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
 
@@ -1125,8 +1173,7 @@ x_set_glyph_string_clipping (s)
 
 
 /* RIF:
-   Compute left and right overhang of glyph string S.  If S is a glyph
-   string for a composition, assume overhangs don't exist.  */
+   Compute left and right overhang of glyph string S.  */
 
 static void
 x_compute_glyph_string_overhangs (s)
@@ -1142,6 +1189,11 @@ x_compute_glyph_string_overhangs (s)
       s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
       s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
     }
+  else if (s->cmp)
+    {
+      s->right_overhang = s->cmp->rbearing - s->cmp->pixel_width;
+      s->left_overhang = - s->cmp->lbearing;
+    }
 }
 
 
@@ -1974,9 +2026,10 @@ x_setup_relief_colors (s)
 
 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;
-     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);
@@ -1991,10 +2044,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.  */
-  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)
@@ -2010,10 +2064,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.  */
-  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)
@@ -2121,7 +2176,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,
-                         width, raised_p, left_p, right_p, &clip_rect);
+                         width, raised_p, 1, 1, left_p, right_p, &clip_rect);
     }
 }
 
@@ -2132,21 +2187,22 @@ static void
 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
-      && 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.  */
-  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)
     {
@@ -2171,11 +2227,12 @@ x_draw_image_foreground (s)
          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,
-                      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
        {
@@ -2184,11 +2241,12 @@ x_draw_image_foreground (s)
          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,
-                      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
@@ -2200,15 +2258,17 @@ x_draw_image_foreground (s)
            {
              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,
-                   s->img->width - 1, s->img->height - 1);
+                   s->slice.width - 1, s->slice.height - 1);
 }
 
 
@@ -2220,21 +2280,22 @@ x_draw_image_relief (s)
 {
   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
-      && 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.  */
-  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)
@@ -2250,12 +2311,17 @@ x_draw_image_relief (s)
 
   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_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 +2332,22 @@ x_draw_image_foreground_1 (s, 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
-      && 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.  */
-  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)
     {
@@ -2296,19 +2363,21 @@ x_draw_image_foreground_1 (s, pixmap)
          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,
-                    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,
-                    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
@@ -2321,14 +2390,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,
-                             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,
-                   s->img->width - 1, s->img->height - 1);
+                   s->slice.width - 1, s->slice.height - 1);
 }
 
 
@@ -2370,33 +2440,28 @@ static void
 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;
 
-  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;
-  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)
     {
-      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
@@ -2435,7 +2500,19 @@ x_draw_image_glyph_string (s)
            }
        }
       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;
     }
@@ -3124,20 +3201,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
-   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 numchars;
 {
-  int nr_events = 0;
-
   if (type == FocusIn)
     {
       if (dpyinfo->x_focus_event_frame != frame)
@@ -3147,17 +3220,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.  */
-          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);
-              bufp->arg = Qnil;
-              ++bufp;
-              numchars--;
-              ++nr_events;
             }
         }
 
@@ -3183,27 +3251,24 @@ x_focus_changed (type, state, dpyinfo, frame, bufp, numchars)
         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.
 
-   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;
-     int numchars;
 {
   struct frame *frame;
-  int nr_events = 0;
 
   frame = x_any_window_to_frame (dpyinfo, event->xany.window);
-  if (! frame) return nr_events;
+  if (! frame)
+    return;
 
   switch (event->type)
     {
@@ -3217,29 +3282,20 @@ x_detect_focus_change (dpyinfo, event, bufp, numchars)
         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:
-      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;
     }
-
-  return nr_events;
 }
 
 
@@ -3584,35 +3640,39 @@ glyph_rect (f, x, y, rect)
      XRectangle *rect;
 {
   Lisp_Object window;
-  int found = 0;
+  struct window *w;
+  struct glyph_row *r, *end_row;
 
   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;
+  if (NILP (window))
+    return 0;
 
-      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;
+  w = XWINDOW (window);
+  r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+  end_row = r + w->current_matrix->nrows - 1;
 
-           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;
-               }
-         }
+  for (; r < end_row && 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 = r->x;
+         while (g < end && gx < x)
+           gx += g->pixel_width, ++g;
+         if (g < end)
+           {
+             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);
+             return 1;
+           }
+         break;
+       }
     }
 
-  return found;
+  return 0;
 }
 
 
@@ -5605,6 +5665,11 @@ static XComposeStatus compose_status;
 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.  */
 
@@ -5624,15 +5689,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);     \
-         if (numchars >= 1)                                            \
-           {                                                           \
-             bufp->kind = MENU_BAR_ACTIVATE_EVENT;                     \
-             XSETFRAME (bufp->frame_or_window, f);                     \
-             bufp->arg = Qnil;                                         \
-             bufp++;                                                   \
-             count++;                                                  \
-             numchars--;                                               \
-           }                                                           \
+        inev.kind = MENU_BAR_ACTIVATE_EVENT;                           \
+        XSETFRAME (inev.frame_or_window, f);                           \
        }                                                               \
      while (0)
 
@@ -5674,14 +5732,13 @@ x_filter_event (dpyinfo, event)
 #endif
 
 #ifdef USE_GTK
-static struct input_event **current_bufp;
-static int *current_numcharsp;
 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,
-   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;
@@ -5690,7 +5747,7 @@ event_handler_gdk (gxev, ev, data)
 {
   XEvent *xev = (XEvent *) gxev;
 
-  if (current_numcharsp)
+  if (current_count >= 0)
     {
       struct x_display_info *dpyinfo;
 
@@ -5708,11 +5765,11 @@ event_handler_gdk (gxev, ev, data)
       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);
@@ -5731,28 +5788,29 @@ 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.
 
-   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
-handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
+handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
      struct x_display_info *dpyinfo;
      XEvent *eventp;
-     /* register */ struct input_event **bufp_r;
-     /* register */ int *numcharsp;
      int *finish;
+     struct input_event *hold_quit;
 {
+  struct input_event inev;
   int count = 0;
+  int do_help = 0;
   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;
 
+  EVENT_INIT (inev);
+  inev.kind = NO_EVENT;
+  inev.arg = Qnil;
+
   switch (event.type)
     {
     case ClientMessage:
@@ -5807,8 +5865,10 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
                   }
                 /* 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
@@ -5819,11 +5879,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 (numchars > 0
 #ifdef HAVE_X_SM
-                    && ! x_session_have_connection ()
+                if (! x_session_have_connection ())
 #endif
-                    )
                   {
                     f = x_top_window_to_frame (dpyinfo,
                                                event.xclient.window);
@@ -5838,41 +5896,36 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
                                    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);
+                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.kind = DELETE_WINDOW_EVENT;
+               XSETFRAME (inev.frame_or_window, f);
+               goto done;
               }
+
+           goto done;
           }
-        else if (event.xclient.message_type
+
+        if (event.xclient.message_type
                  == 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;
-            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];
@@ -5882,45 +5935,55 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
                 f->left_pos = new_x;
                 f->top_pos = new_y;
               }
+           goto done;
           }
+
 #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);
+           goto done;
           }
 #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];
-            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);
+           goto done;
           }
+
 #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);
+           *finish = X_EVENT_GOTO_OUT;
+            goto done;
           }
 #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))
+         *finish = X_EVENT_DROP;
       }
       break;
 
@@ -5940,19 +6003,11 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
       {
         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.kind = SELECTION_CLEAR_EVENT;
+        SELECTION_EVENT_DISPLAY (&inev) = eventp->display;
+        SELECTION_EVENT_SELECTION (&inev) = eventp->selection;
+        SELECTION_EVENT_TIME (&inev) = eventp->time;
+        inev.frame_or_window = Qnil;
       }
       break;
 
@@ -5969,22 +6024,14 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
           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.kind = SELECTION_REQUEST_EVENT;
+          SELECTION_EVENT_DISPLAY (&inev) = eventp->display;
+          SELECTION_EVENT_REQUESTOR (&inev) = eventp->requestor;
+          SELECTION_EVENT_SELECTION (&inev) = eventp->selection;
+          SELECTION_EVENT_TARGET (&inev) = eventp->target;
+          SELECTION_EVENT_PROPERTY (&inev) = eventp->property;
+          SELECTION_EVENT_TIME (&inev) = eventp->time;
+          inev.frame_or_window = Qnil;
         }
       break;
 
@@ -6014,7 +6061,6 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
           FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_UNKNOWN;
         }
       goto OTHER;
-      break;
 
     case Expose:
       f = x_window_to_frame (dpyinfo, event.xexpose.window);
@@ -6116,12 +6162,8 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
             {
               f->async_iconified = 1;
 
-              bufp->kind = ICONIFY_EVENT;
-              XSETFRAME (bufp->frame_or_window, f);
-              bufp->arg = Qnil;
-              bufp++;
-              count++;
-              numchars--;
+              inev.kind = ICONIFY_EVENT;
+              XSETFRAME (inev.frame_or_window, f);
             }
         }
       goto OTHER;
@@ -6153,12 +6195,8 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
 
           if (f->iconified)
             {
-              bufp->kind = DEICONIFY_EVENT;
-              XSETFRAME (bufp->frame_or_window, f);
-              bufp->arg = Qnil;
-              bufp++;
-              count++;
-              numchars--;
+              inev.kind = DEICONIFY_EVENT;
+              XSETFRAME (inev.frame_or_window, f);
             }
           else if (! NILP (Vframe_list)
                    && ! NILP (XCDR (Vframe_list)))
@@ -6171,6 +6209,8 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
 
     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 ())
@@ -6181,8 +6221,8 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
 
       if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
         {
-          dpyinfo->mouse_face_hidden = 1;
           clear_mouse_face (dpyinfo);
+          dpyinfo->mouse_face_hidden = 1;
         }
 
 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
@@ -6219,6 +6259,15 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
           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),
@@ -6305,51 +6354,44 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
                                   &compose_status);
 #endif
 
+          /* If not using XIM/XIC, and a compose sequence is in progress,
+             we break here.  Otherwise, chars_matched is always 0.  */
+          if (compose_status.chars_matched > 0 && nbytes == 0)
+            break;
+
           orig_keysym = keysym;
 
-          if (numchars > 1)
-            {
-              Lisp_Object c;
+         /* Common for all keysym input events.  */
+         XSETFRAME (inev.frame_or_window, f);
+         inev.modifiers
+           = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), modifiers);
+         inev.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.kind = ASCII_KEYSTROKE_EVENT;
+             inev.code = keysym;
+             goto done_keysym;
+           }
+
+         /* Now non-ASCII.  */
+         if (HASH_TABLE_P (Vx_keysym_table)
+             && (NATNUMP (c = Fgethash (make_number (keysym),
+                                        Vx_keysym_table,
+                                        Qnil))))
+           {
+             inev.kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
+                           ? ASCII_KEYSTROKE_EVENT
+                           : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
+             inev.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
@@ -6430,104 +6472,81 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
                                  <= 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.kind = NON_ASCII_KEYSTROKE_EVENT;
+             inev.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;
 
-                  /* 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++;
-                    }
+           for (i = 0, nchars = 0; i < nbytes; i++)
+             {
+               if (ASCII_BYTE_P (copy_bufptr[i]))
+                 nchars++;
+               STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]);
+             }
 
-                  count += nchars;
-                  numchars -= nchars;
+           if (nchars < nbytes)
+             {
+               /* Decode the input data.  */
+               int require;
+               unsigned char *p;
+
+               /* 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.common_flags &= ~CODING_ANNOTATION_MASK;
+
+               require = MAX_MULTIBYTE_LENGTH * nbytes;
+               coding.destination = alloca (require);
+               coding.dst_bytes = require;
+               coding.mode |= CODING_MODE_LAST_BLOCK;
+               decode_coding_c_string (&coding, copy_bufptr, nbytes, Qnil);
+               nbytes = coding.produced;
+               nchars = coding.produced_char;
+               copy_bufptr = coding.destination;
+             }
 
-                  if (keysym == NoSymbol)
-                    break;
-                }
-              else
-                abort ();
-            }
-          else
-            abort ();
+           /* 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.kind = (SINGLE_BYTE_CHAR_P (c)
+                             ? ASCII_KEYSTROKE_EVENT
+                             : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
+               inev.code = c;
+               kbd_buffer_store_event_hold (&inev, hold_quit);
+             }
+
+           /* Previous code updated count by nchars rather than nbytes,
+              but that seems bogus to me.  ++kfs  */
+           count += nbytes;
+
+           inev.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
@@ -6548,63 +6567,41 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
 #endif
 
     case EnterNotify:
-      {
-        int n;
+      x_detect_focus_change (dpyinfo, &event, &inev);
 
-        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 (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
 
-        /* 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);
+      goto OTHER;
 
     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);
       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);
 
       f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
       if (f)
@@ -6622,31 +6619,12 @@ 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)
-            {
-              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;
         }
       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);
       goto OTHER;
 
     case MotionNotify:
@@ -6684,13 +6662,10 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
                    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.kind = SELECT_WINDOW_EVENT;
+                    inev.frame_or_window = window;
                   }
 
                 last_window=window;
@@ -6717,22 +6692,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))
-          {
-            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;
       }
 
@@ -6816,10 +6776,8 @@ 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.  */
-        struct input_event emacs_event;
         int tool_bar_p = 0;
 
-        emacs_event.kind = NO_EVENT;
         bzero (&compose_status, sizeof (compose_status));
 
         if (dpyinfo->grabbed
@@ -6859,7 +6817,21 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
 #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, &event, f);
+                           }
+                         if (event.type == ButtonRelease)
+                           ignore_next_mouse_click_timeout = 0;
+                       }
+                     else
+                       construct_mouse_click (&inev, &event, f);
+                   }
                 }
           }
         else
@@ -6873,12 +6845,12 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
                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);
                 *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);
 #endif /* not USE_TOOLKIT_SCROLL_BARS */
           }
 
@@ -6899,14 +6871,6 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
         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--;
-          }
-
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
         f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
         /* For a down-event in the menu bar,
@@ -6993,16 +6957,38 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
     break;
     }
 
-  goto ret;
+ done:
+  if (inev.kind != NO_EVENT)
+    {
+      kbd_buffer_store_event_hold (&inev, 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;
 }
 
@@ -7018,28 +7004,12 @@ x_dispatch_event (event, display)
      Display *display;
 {
   struct x_display_info *dpyinfo;
-  struct input_event bufp[10];
-  struct input_event *bufpp;
-  int numchars = 10;
   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)
-    {
-      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;
 }
@@ -7049,19 +7019,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.
 
-   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
-XTread_socket (sd, bufp, numchars, expected)
+XTread_socket (sd, expected, hold_quit)
      register int sd;
-     /* register */ struct input_event *bufp;
-     /* register */ int numchars;
      int expected;
+     struct input_event *hold_quit;
 {
   int count = 0;
   XEvent event;
@@ -7080,9 +7047,6 @@ XTread_socket (sd, bufp, numchars, expected)
   /* 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.
@@ -7124,9 +7088,18 @@ XTread_socket (sd, bufp, numchars, expected)
        }
 
 #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
@@ -7143,11 +7116,7 @@ XTread_socket (sd, bufp, numchars, expected)
 #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;
@@ -7168,14 +7137,13 @@ XTread_socket (sd, bufp, numchars, expected)
   while (gtk_events_pending ())
     {
       current_count = count;
-      current_numcharsp = &numchars;
-      current_bufp = &bufp;
+      current_hold_quit = hold_quit;
 
       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;
@@ -7215,8 +7183,9 @@ XTread_socket (sd, bufp, numchars, expected)
       pending_autoraise_frame = 0;
     }
 
-  UNBLOCK_INPUT;
   --handling_signal;
+  UNBLOCK_INPUT;
+
   return count;
 }
 
@@ -7271,13 +7240,6 @@ x_draw_hollow_cursor (w, row)
   struct glyph *cursor_glyph;
   GC gc;
 
-  /* Compute frame-relative coordinates from window-relative
-     coordinates.  */
-  x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
-  y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
-       + row->ascent - w->phys_cursor_ascent);
-  h = row->height - 1;
-
   /* Get the glyph the cursor is on.  If we can't tell because
      the current matrix is invalid or such, give up.  */
   cursor_glyph = get_phys_cursor_glyph (w);
@@ -7294,6 +7256,20 @@ x_draw_hollow_cursor (w, row)
     wd = min (FRAME_COLUMN_WIDTH (f), wd);
   w->phys_cursor_width = wd;
 
+  /* Compute frame-relative coordinates from window-relative
+     coordinates.  */
+  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 (min (FRAME_LINE_HEIGHT (f), row->height),
+          cursor_glyph->ascent + cursor_glyph->descent);
+  if (h < row->height)
+    y += row->ascent /* - w->phys_cursor_ascent */ + cursor_glyph->descent - h;
+  h--;
+
   /* The foreground of cursor_gc is typically the same as the normal
      background color, which can cause the cursor box to be invisible.  */
   xgcv.foreground = f->output_data.x->cursor_pixel;
@@ -7437,6 +7413,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;
 
+      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:
@@ -7908,11 +7891,16 @@ x_new_font (f, fontname)
      register char *fontname;
 {
   struct font_info *fontp
-    = FS_LOAD_FONT (f, 0, fontname, -1);
+    = FS_LOAD_FONT (f, fontname);
 
   if (!fontp)
     return Qnil;
 
+  if (FRAME_FONT (f) == (XFontStruct *) (fontp->font))
+    /* This font is already set in frame F.  There's nothing more to
+       do.  */
+    return build_string (fontp->full_name);
+
   FRAME_FONT (f) = (XFontStruct *) (fontp->font);
   FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
   FRAME_FONTSET (f) = -1;
@@ -7955,33 +7943,45 @@ x_new_font (f, fontname)
   return build_string (fontp->full_name);
 }
 
-/* Give frame F the fontset named FONTSETNAME as its default font, and
-   return the full name of that fontset.  FONTSETNAME may be a wildcard
-   pattern; in that case, we choose some fontset that fits the pattern.
-   The return value shows which fontset we chose.  */
+/* Give frame F the fontset named FONTSETNAME as its default fontset,
+   and return the full name of that fontset.  FONTSETNAME may be a
+   wildcard pattern; in that case, we choose some fontset that fits
+   the pattern.  FONTSETNAME may be a font name for ASCII characters;
+   in that case, we create a fontset from that font name.
+
+   The return value shows which fontset we chose.
+   If FONTSETNAME specifies the default fontset, return Qt.
+   If an ASCII font in the specified fontset can't be loaded, return
+   Qnil.  */
 
 Lisp_Object
 x_new_fontset (f, fontsetname)
      struct frame *f;
-     char *fontsetname;
+     Lisp_Object fontsetname;
 {
-  int fontset = fs_query_fontset (build_string (fontsetname), 0);
+  int fontset = fs_query_fontset (fontsetname, 0);
   Lisp_Object result;
 
-  if (fontset < 0)
-    return Qnil;
-
-  if (FRAME_FONTSET (f) == fontset)
+  if (fontset > 0 && f->output_data.x->fontset == fontset)
     /* This fontset is already set in frame F.  There's nothing more
        to do.  */
     return fontset_name (fontset);
+  else if (fontset == 0)
+    /* The default fontset can't be the default font.   */
+    return Qt;
 
-  result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
+  if (fontset > 0)
+    result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
+  else
+    result = x_new_font (f, SDATA (fontsetname));
 
   if (!STRINGP (result))
     /* Can't load ASCII font.  */
     return Qnil;
 
+  if (fontset < 0)
+    fontset = new_fontset_from_font_name (result);
+
   /* Since x_new_font doesn't update any fontset information, do it now.  */
   FRAME_FONTSET (f) = fontset;
 
@@ -7991,7 +7991,7 @@ x_new_fontset (f, fontsetname)
     xic_set_xfontset (f, SDATA (fontset_ascii (fontset)));
 #endif
 
-  return build_string (fontsetname);
+  return fontset_name (fontset);
 }
 
 \f
@@ -8222,68 +8222,26 @@ void
 x_calc_absolute_position (f)
      struct frame *f;
 {
-  Window child;
   int win_x = 0, win_y = 0;
   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;
 
-  this_window = FRAME_OUTER_WINDOW (f);
-
-  /* Find the position of the outside upper-left corner of
+  /* Find the offsets 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;
-    }
+    /* This is to get *_pixels_outer_diff.  */
+    x_real_positions (f, &win_x, &win_y);
 
   /* 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
+                   - 2 * FRAME_X_OUTPUT (f)->x_pixels_outer_diff
                   - FRAME_PIXEL_WIDTH (f)
                   + f->left_pos);
 
@@ -8308,8 +8266,12 @@ x_calc_absolute_position (f)
 
   if (flags & YNegative)
     f->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
-                 - 2 * f->border_width
-                 - win_y
+                  - FRAME_X_OUTPUT (f)->y_pixels_outer_diff
+
+                  /* Assume the window manager decorations are the same size on
+                     three sides, i.e. left, right and bottom.  This is to
+                     compensate for the bottom part.  */
+                  - FRAME_X_OUTPUT (f)->x_pixels_outer_diff
                  - height
                  + f->top_pos);
   }
@@ -8346,24 +8308,13 @@ x_set_offset (f, xoff, yoff, change_gravity)
       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;
 
-#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
@@ -9451,7 +9402,7 @@ x_get_font_info (f, font_idx)
    If SIZE is > 0, it is the size (maximum bounds width) of fonts
    to be listed.
 
-   SIZE < 0 means include scalable fonts.
+   SIZE < 0 means include auto scaled fonts.
 
    Frame F null means we have not yet created any frame on X, and
    consult the first display in x_display_list.  MAXNAMES sets a limit
@@ -9926,6 +9877,7 @@ x_load_font (f, fontname, size)
     bzero (fontp, sizeof (*fontp));
     fontp->font = font;
     fontp->font_idx = i;
+    fontp->charset = -1;       /* fs_load_font sets it.  */
     fontp->name = (char *) xmalloc (strlen (fontname) + 1);
     bcopy (fontname, fontp->name, strlen (fontname) + 1);
 
@@ -10000,10 +9952,10 @@ x_load_font (f, fontname, size)
        the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
        (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
        2:0xA020..0xFF7F).  For the moment, we don't know which charset
-       uses this font.  So, we set information in fontp->encoding[1]
+       uses this font.  So, we set information in fontp->encoding_type
        which is never used by any charset.  If mapping can't be
        decided, set FONT_ENCODING_NOT_DECIDED.  */
-    fontp->encoding[1]
+    fontp->encoding_type
       = (font->max_byte1 == 0
         /* 1-byte font */
         ? (font->min_char_or_byte2 < 0x80
@@ -10103,6 +10055,160 @@ x_find_ccl_program (fontp)
 }
 
 
+/* Return a char-table whose elements are t if the font FONT_INFO
+   contains a glyph for the corresponding character, and nil if
+   not.  */
+
+Lisp_Object
+x_get_font_repertory (f, font_info)
+     FRAME_PTR f;
+     struct font_info *font_info;
+{
+  XFontStruct *font = (XFontStruct *) font_info->font;
+  Lisp_Object table;
+  int min_byte1, max_byte1, min_byte2, max_byte2;
+  int c;
+  struct charset *charset = CHARSET_FROM_ID (font_info->charset);
+  int offset = CHARSET_OFFSET (charset);
+
+  table = Fmake_char_table (Qnil, Qnil);
+
+  min_byte1 = font->min_byte1;
+  max_byte1 = font->max_byte1;
+  min_byte2 = font->min_char_or_byte2;
+  max_byte2 = font->max_char_or_byte2;
+  if (min_byte1 == 0 && max_byte1 == 0)
+    {
+      if (! font->per_char || font->all_chars_exist == True)
+       {
+         if (offset >= 0)
+           char_table_set_range (table, offset + min_byte2,
+                                 offset + max_byte2, Qt);
+         else
+           for (; min_byte2 <= max_byte2; min_byte2++)
+             {
+               c = DECODE_CHAR (charset, min_byte2);
+               CHAR_TABLE_SET (table, c, Qt);
+             }
+       }
+      else
+       {
+         XCharStruct *pcm = font->per_char;
+         int from = -1;
+         int i;
+
+         for (i = min_byte2; i <= max_byte2; i++, pcm++)
+           {
+             if (pcm->width == 0 && pcm->rbearing == pcm->lbearing)
+               {
+                 if (from >= 0)
+                   {
+                     if (offset >= 0)
+                       char_table_set_range (table, offset + from,
+                                             offset + i - 1, Qt);
+                     else
+                       for (; from < i; from++)
+                         {
+                           c = DECODE_CHAR (charset, from);
+                           CHAR_TABLE_SET (table, c, Qt);
+                         }
+                     from = -1;
+                   }
+               }
+             else if (from < 0)
+               from = i;
+           }
+         if (from >= 0)
+           {
+             if (offset >= 0)
+               char_table_set_range (table, offset + from, offset + i - 1,
+                                     Qt);
+             else
+               for (; from < i; from++)
+                 {
+                   c = DECODE_CHAR (charset, from);
+                   CHAR_TABLE_SET (table, c, Qt);
+                 }
+           }
+       }
+    }
+  else
+    {
+      if (! font->per_char || font->all_chars_exist == True)
+       {
+         int i, j;
+
+         if (offset >= 0)
+           for (i = min_byte1; i <= max_byte1; i++)
+             char_table_set_range
+               (table, offset + ((i << 8) | min_byte2),
+                offset + ((i << 8) | max_byte2), Qt);
+         else
+           for (i = min_byte1; i <= max_byte1; i++)        
+             for (j = min_byte2; j <= max_byte2; j++)
+               {
+                 unsigned code = (i << 8) | j;
+                 c = DECODE_CHAR (charset, code);
+                 CHAR_TABLE_SET (table, c, Qt);
+               }
+       }
+      else
+       {
+         XCharStruct *pcm = font->per_char;
+         int i;
+
+         for (i = min_byte1; i <= max_byte1; i++)
+           {
+             int from = -1;
+             int j;
+
+             for (j = min_byte2; j <= max_byte2; j++, pcm++)
+               {
+                 if (pcm->width == 0 && pcm->rbearing == pcm->lbearing)
+                   {
+                     if (from >= 0)
+                       {
+                         if (offset >= 0)
+                           char_table_set_range
+                             (table, offset + ((i << 8) | from),
+                              offset + ((i << 8) | (j - 1)), Qt);
+                         else
+                           {
+                             for (; from < j; from++)
+                               {
+                                 unsigned code = (i << 8) | from;
+                                 c = ENCODE_CHAR (charset, code);
+                                 CHAR_TABLE_SET (table, c, Qt);
+                               }
+                           }
+                         from = -1;
+                       }
+                   }
+                 else if (from < 0)
+                   from = j;
+               }
+             if (from >= 0)
+               {
+                 if (offset >= 0)
+                   char_table_set_range
+                     (table, offset + ((i << 8) | from),
+                      offset + ((i << 8) | (j - 1)), Qt);
+                 else
+                   {
+                     for (; from < j; from++)
+                       {
+                         unsigned code = (i << 8) | from;
+                         c = DECODE_CHAR (charset, code);
+                         CHAR_TABLE_SET (table, c, Qt);
+                       }
+                   }
+               }
+           }
+       }
+    }
+
+  return table;
+}
 \f
 /***********************************************************************
                            Initialization
@@ -10478,7 +10584,7 @@ x_term_init (display_name, xrm_option, resource_name)
       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))
     {
@@ -10817,6 +10923,8 @@ static struct redisplay_interface x_redisplay_interface =
   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,
@@ -10863,6 +10971,11 @@ x_initialize ()
   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);
@@ -10930,8 +11043,6 @@ syms_of_xterm ()
   staticpro (&Qvendor_specific_keysyms);
   Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
 
-  staticpro (&Qutf_8);
-  Qutf_8 = intern ("utf-8");
   staticpro (&Qlatin_1);
   Qlatin_1 = intern ("latin-1");
 
@@ -10946,6 +11057,16 @@ UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
 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.