Fix up multi-tty merge
[bpt/emacs.git] / src / xterm.c
index 2e8fca7..a1beab4 100644 (file)
@@ -6,7 +6,7 @@ This file is part of GNU Emacs.
 
 GNU Emacs is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -54,7 +54,6 @@ Boston, MA 02110-1301, USA.  */
 #include <sys/ioctl.h>
 #endif /* ! defined (BSD_SYSTEM) */
 
-#include "systty.h"
 #include "systime.h"
 
 #ifndef INCLUDED_FCNTL
@@ -68,6 +67,7 @@ Boston, MA 02110-1301, USA.  */
 /* #include <sys/param.h>  */
 
 #include "charset.h"
+#include "character.h"
 #include "coding.h"
 #include "ccl.h"
 #include "frame.h"
@@ -101,6 +101,10 @@ Boston, MA 02110-1301, USA.  */
 #include "gtkutil.h"
 #endif
 
+#ifdef USE_FONT_BACKEND
+#include "font.h"
+#endif /* USE_FONT_BACKEND */
+
 #ifdef USE_LUCID
 extern int xlwmenu_window_p P_ ((Widget w, Window window));
 extern void xlwmenu_redisplay P_ ((Widget));
@@ -155,8 +159,6 @@ extern void _XEditResCheckMessages ();
 #endif
 #endif
 
-#define abs(x) ((x) < 0 ? -(x) : (x))
-
 /* Default to using XIM if available.  */
 #ifdef USE_XIM
 int use_xim = 1;
@@ -322,6 +324,10 @@ static Lisp_Object Qalt, Qhyper, Qmeta, Qsuper, Qmodifier_value;
 static Lisp_Object Qvendor_specific_keysyms;
 static Lisp_Object Qlatin_1;
 
+/* Used in x_flush.  */
+
+extern Lisp_Object Vinhibit_redisplay;
+
 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
 extern int x_bitmap_mask P_ ((FRAME_PTR, int));
 
@@ -331,13 +337,15 @@ static const XColor *x_color_cells P_ ((Display *, int *));
 static void x_update_window_end P_ ((struct window *, int, int));
 
 static int x_io_error_quitter P_ ((Display *));
+static struct terminal *x_create_terminal P_ ((struct x_display_info *));
+void x_delete_terminal P_ ((struct terminal *));
 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
 static int x_compute_min_glyph_bounds P_ ((struct frame *));
 static void x_update_end P_ ((struct frame *));
 static void XTframe_up_to_date P_ ((struct frame *));
-static void XTset_terminal_modes P_ ((void));
-static void XTreset_terminal_modes P_ ((void));
-static void x_clear_frame P_ ((void));
+static void XTset_terminal_modes P_ ((struct terminal *));
+static void XTreset_terminal_modes P_ ((struct terminal *));
+static void x_clear_frame P_ ((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 *));
@@ -377,12 +385,18 @@ static void
 x_flush (f)
      struct frame *f;
 {
+  /* Don't call XFlush when it is not safe to redisplay; the X
+     connection may be broken.  */
+  if (!NILP (Vinhibit_redisplay))
+    return;
+
   BLOCK_INPUT;
   if (f == NULL)
     {
       Lisp_Object rest, frame;
       FOR_EACH_FRAME (rest, frame)
-       x_flush (XFRAME (frame));
+        if (FRAME_X_P (XFRAME (frame)))
+          x_flush (XFRAME (frame));
     }
   else if (FRAME_X_P (f))
     XFlush (FRAME_X_DISPLAY (f));
@@ -720,8 +734,10 @@ x_draw_fringe_bitmap (w, row, p)
   else
     x_clip_to_row (w, row, -1, gc);
 
-  if (p->bx >= 0 && !p->overlay_p)
+  if (!p->overlay_p)
     {
+      int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
+
       /* In case the same realized face is used for fringes and
         for something displayed in the text (e.g. face `region' on
         mono-displays, the fill style may have been changed to
@@ -731,8 +747,55 @@ x_draw_fringe_bitmap (w, row, p)
       else
        XSetForeground (display, face->gc, face->background);
 
-      XFillRectangle (display, window, face->gc,
-                     p->bx, p->by, p->nx, p->ny);
+#ifdef USE_TOOLKIT_SCROLL_BARS
+      /* If the fringe is adjacent to the left (right) scroll bar of a
+        leftmost (rightmost, respectively) window, then extend its
+        background to the gap between the fringe and the bar.  */
+      if ((WINDOW_LEFTMOST_P (w)
+          && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
+         || (WINDOW_RIGHTMOST_P (w)
+             && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
+       {
+         int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
+
+         if (sb_width > 0)
+           {
+             int left = WINDOW_SCROLL_BAR_AREA_X (w);
+             int width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
+                          * FRAME_COLUMN_WIDTH (f));
+
+             if (bx < 0)
+               {
+                 /* Bitmap fills the fringe.  */
+                 if (left + width == p->x)
+                   bx = left + sb_width;
+                 else if (p->x + p->wd == left)
+                   bx = left;
+                 if (bx >= 0)
+                   {
+                     int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
+
+                     nx = width - sb_width;
+                     by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
+                                                           row->y));
+                     ny = row->visible_height;
+                   }
+               }
+             else
+               {
+                 if (left + width == bx)
+                   {
+                     bx = left + sb_width;
+                     nx += width - sb_width;
+                   }
+                 else if (bx + nx == left)
+                   nx += width - sb_width;
+               }
+           }
+       }
+#endif
+      if (bx >= 0 && nx > 0)
+       XFillRectangle (display, window, face->gc, bx, by, nx, ny);
 
       if (!face->stipple)
        XSetForeground (display, face->gc, face->foreground);
@@ -794,7 +857,7 @@ x_draw_fringe_bitmap (w, row, p)
    rarely happens).  */
 
 static void
-XTset_terminal_modes ()
+XTset_terminal_modes (struct terminal *terminal)
 {
 }
 
@@ -802,7 +865,7 @@ XTset_terminal_modes ()
    the X-windows go away, and suspending requires no action.  */
 
 static void
-XTreset_terminal_modes ()
+XTreset_terminal_modes (struct terminal *terminal)
 {
 }
 
@@ -814,7 +877,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
@@ -893,13 +957,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.
@@ -913,31 +977,31 @@ x_encode_char (c, char2b, font_info, two_byte_p)
       check_ccl_update (ccl);
       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)
@@ -1065,15 +1129,20 @@ 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);
 
   /* If font in this face is same as S->font, use it.  */
   if (s->font == s->face->font)
     s->gc = s->face->gc;
+#ifdef USE_FONT_BACKEND
+  else if (enable_font_backend)
+    /* No need of setting a font for s->gc.  */
+    s->gc = s->face->gc;
+#endif /* USE_FONT_BACKEND */
   else
     {
       /* Otherwise construct scratch_cursor_gc with values from FACE
@@ -1167,16 +1236,61 @@ x_set_glyph_string_gc (s)
 static INLINE void
 x_set_glyph_string_clipping (s)
      struct glyph_string *s;
+{
+#ifdef USE_FONT_BACKEND
+  XRectangle *r = s->clip;
+#else
+  XRectangle r[2];
+#endif
+  int n = get_glyph_string_clip_rects (s, r, 2);
+
+  if (n > 0)
+    XSetClipRectangles (s->display, s->gc, 0, 0, r, n, Unsorted);
+#ifdef USE_FONT_BACKEND
+  s->num_clips = n;
+#endif
+}
+
+
+/* Set SRC's clipping for output of glyph string DST.  This is called
+   when we are drawing DST's left_overhang or right_overhang only in
+   the area of SRC.  */
+
+static void
+x_set_glyph_string_clipping_exactly (src, dst)
+     struct glyph_string *src, *dst;
 {
   XRectangle r;
-  get_glyph_string_clip_rect (s, &r);
-  XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
+
+#ifdef USE_FONT_BACKEND
+  if (enable_font_backend)
+    {
+      r.x = src->x;
+      r.width = src->width;
+      r.y = src->y;
+      r.height = src->height;
+      dst->clip[0] = r;
+      dst->num_clips = 1;
+    }
+  else
+    {
+#endif /* USE_FONT_BACKEND */
+  struct glyph_string *clip_head = src->clip_head;
+  struct glyph_string *clip_tail = src->clip_tail;
+
+  /* This foces clipping just this glyph string.  */
+  src->clip_head = src->clip_tail = src;
+  get_glyph_string_clip_rect (src, &r);
+  src->clip_head = clip_head, src->clip_tail = clip_tail;
+#ifdef USE_FONT_BACKEND
+    }
+#endif /* USE_FONT_BACKEND */
+  XSetClipRectangles (dst->display, dst->gc, 0, 0, &r, 1, Unsorted);
 }
 
 
 /* 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)
@@ -1187,11 +1301,34 @@ x_compute_glyph_string_overhangs (s)
     {
       XCharStruct cs;
       int direction, font_ascent, font_descent;
+
+#ifdef USE_FONT_BACKEND
+      if (enable_font_backend)
+       {
+         unsigned *code = alloca (sizeof (unsigned) * s->nchars);
+         struct font *font = (struct font *) s->font_info;
+         struct font_metrics metrics;
+         int i;
+
+         for (i = 0; i < s->nchars; i++)
+           code[i] = (s->char2b[i].byte1 << 8) | s->char2b[i].byte2;
+         font->driver->text_extents (font, code, s->nchars, &metrics);
+         cs.rbearing = metrics.rbearing;
+         cs.lbearing = metrics.lbearing;
+         cs.width = metrics.width;
+       }
+      else
+#endif /* USE_FONT_BACKEND */
       XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
                      &font_ascent, &font_descent, &cs);
       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;
+    }
 }
 
 
@@ -1281,6 +1418,26 @@ x_draw_glyph_string_foreground (s)
          x += g->pixel_width;
        }
     }
+#ifdef USE_FONT_BACKEND
+  else if (enable_font_backend)
+    {
+      int boff = s->font_info->baseline_offset;
+      struct font *font = (struct font *) s->font_info;
+      int y;
+
+      if (s->font_info->vertical_centering)
+       boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
+
+      y = s->ybase - boff;
+      if (s->for_overlaps
+         || (s->background_filled_p && s->hl != DRAW_CURSOR))
+       font->driver->draw (s, 0, s->nchars, x, y, 0);
+      else
+       font->driver->draw (s, 0, s->nchars, x, y, 1);
+      if (s->face->overstrike)
+       font->driver->draw (s, 0, s->nchars, x + 1, y, 0);
+    }
+#endif /* USE_FONT_BACKEND */
   else
     {
       char *char1b = (char *) s->char2b;
@@ -1340,11 +1497,11 @@ static void
 x_draw_composite_glyph_string_foreground (s)
      struct glyph_string *s;
 {
-  int i, x;
+  int i, j, x;
 
   /* If first glyph of S has a left box line, start drawing the text
      of S to the right of that box line.  */
-  if (s->face->box != FACE_NO_BOX
+  if (s->face && s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
     x = s->x + abs (s->face->box_line_width);
   else
@@ -1363,21 +1520,79 @@ x_draw_composite_glyph_string_foreground (s)
        XDrawRectangle (s->display, s->window, s->gc, x, s->y,
                        s->width - 1, s->height - 1);
     }
-  else
+#ifdef USE_FONT_BACKEND
+  else if (enable_font_backend)
     {
-      for (i = 0; i < s->nchars; i++, ++s->gidx)
+      struct font *font = (struct font *) s->font_info;
+      int y = s->ybase;
+      int width = 0;
+
+      if (s->cmp->method == COMPOSITION_WITH_GLYPH_STRING)
        {
-         XDrawString16 (s->display, s->window, s->gc,
-                        x + s->cmp->offsets[s->gidx * 2],
-                        s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
-                        s->char2b + i, 1);
-         if (s->face->overstrike)
-           XDrawString16 (s->display, s->window, s->gc,
-                          x + s->cmp->offsets[s->gidx * 2] + 1,
-                          s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
-                          s->char2b + i, 1);
+         Lisp_Object gstring = AREF (XHASH_TABLE (composition_hash_table)
+                                     ->key_and_value,
+                                     s->cmp->hash_index * 2);
+         int from;
+
+         for (i = from = 0; i < s->nchars; i++)
+           {
+             Lisp_Object g = LGSTRING_GLYPH (gstring, i);
+             Lisp_Object adjustment = LGLYPH_ADJUSTMENT (g);
+             int xoff, yoff, wadjust;
+
+             if (! VECTORP (adjustment))
+               {
+                 width += XINT (LGLYPH_WIDTH (g));
+                 continue;
+               }
+             if (from < i)
+               {
+                 font->driver->draw (s, from, i, x, y, 0);
+                 x += width;
+               }
+             xoff = XINT (AREF (adjustment, 0));
+             yoff = XINT (AREF (adjustment, 1));
+             wadjust = XINT (AREF (adjustment, 2));
+
+             font->driver->draw (s, i, i + 1, x + xoff, y + yoff, 0);
+             x += XINT (LGLYPH_WIDTH (g)) + wadjust;
+             from = i + 1;
+             width = 0;
+           }
+         if (from < i)
+           font->driver->draw (s, from, i, x, y, 0);
+       }
+      else
+       {
+         for (i = 0, j = s->gidx; i < s->nchars; i++, j++)
+           if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
+             {
+               int xx = x + s->cmp->offsets[j * 2];
+               int yy = y - s->cmp->offsets[j * 2 + 1];
+
+               font->driver->draw (s, j, j + 1, xx, yy, 0);
+               if (s->face->overstrike)
+                 font->driver->draw (s, j, j + 1, xx + 1, yy, 0);
+             }
        }
     }
+#endif /* USE_FONT_BACKEND */
+  else
+    {
+      for (i = 0, j = s->gidx; i < s->nchars; i++, j++)
+       if (s->face)
+         {
+           XDrawString16 (s->display, s->window, s->gc,
+                          x + s->cmp->offsets[j * 2],
+                          s->ybase - s->cmp->offsets[j * 2 + 1],
+                          s->char2b + j, 1);
+           if (s->face->overstrike)
+             XDrawString16 (s->display, s->window, s->gc,
+                            x + s->cmp->offsets[j * 2] + 1,
+                            s->ybase - s->cmp->offsets[j * 2 + 1],
+                            s->char2b + j, 1);
+         }
+    }
 }
 
 
@@ -1412,10 +1627,11 @@ x_frame_of_widget (widget)
 
   /* Look for a frame with that top-level widget.  Allocate the color
      on that frame to get the right gamma correction value.  */
-  for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
-    if (GC_FRAMEP (XCAR (tail))
+  for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
+    if (FRAMEP (XCAR (tail))
        && (f = XFRAME (XCAR (tail)),
-           (f->output_data.nothing != 1
+           (FRAME_X_P (f)
+             && f->output_data.nothing != 1
             && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
        && f->output_data.x->widget == widget)
       return f;
@@ -2476,9 +2692,11 @@ x_draw_image_glyph_string (s)
            {
              /* Fill background with a stipple pattern.  */
              XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
+             XSetTSOrigin (s->display, s->gc, - s->x, - s->y);
              XFillRectangle (s->display, pixmap, s->gc,
                              0, 0, s->background_width, s->height);
              XSetFillStyle (s->display, s->gc, FillSolid);
+             XSetTSOrigin (s->display, s->gc, 0, 0);
            }
          else
            {
@@ -2622,15 +2840,25 @@ x_draw_glyph_string (s)
 {
   int relief_drawn_p = 0;
 
-  /* If S draws into the background of its successor, draw the
-     background of the successor first so that S can draw into it.
+  /* If S draws into the background of its successors, draw the
+     background of the successors 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)
     {
-      xassert (s->next->img == NULL);
-      x_set_glyph_string_gc (s->next);
-      x_set_glyph_string_clipping (s->next);
-      x_draw_glyph_string_background (s->next, 1);
+      int width;
+      struct glyph_string *next;
+
+      for (width = 0, next = s->next; next;
+          width += next->width, next = next->next)
+       if (next->first_glyph->type != IMAGE_GLYPH)
+         {
+           x_set_glyph_string_gc (next);
+           x_set_glyph_string_clipping (next);
+           x_draw_glyph_string_background (next, 1);
+#ifdef USE_FONT_BACKEND
+           next->num_clips = 0;
+#endif /* USE_FONT_BACKEND */
+         }
     }
 
   /* Set up S->gc, set clipping and draw S.  */
@@ -2650,6 +2878,12 @@ x_draw_glyph_string (s)
       x_set_glyph_string_clipping (s);
       relief_drawn_p = 1;
     }
+  else if ((s->prev && s->prev->hl != s->hl && s->left_overhang)
+          || (s->next && s->next->hl != s->hl && s->right_overhang))
+    /* We must clip just this glyph.  left_overhang part has already
+       drawn when s->prev was drawn, and right_overhang part will be
+       drawn later when s->next is drawn. */
+    x_set_glyph_string_clipping_exactly (s, s);
   else
     x_set_glyph_string_clipping (s);
 
@@ -2692,26 +2926,45 @@ x_draw_glyph_string (s)
          int y;
 
          /* Get the underline thickness.  Default is 1 pixel.  */
+#ifdef USE_FONT_BACKEND
+         if (enable_font_backend)
+           /* In the future, we must use information of font.  */
+           h = 1;
+         else
+#endif /* USE_FONT_BACKEND */
          if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
            h = 1;
 
-         y = s->y + s->height - h;
-         if (!x_underline_at_descent_line)
-            {
-             /* Get the underline position.  This is the recommended
-                 vertical offset in pixels from the baseline to the top of
-                 the underline.  This is a signed value according to the
-                 specs, and its default is
-
-                ROUND ((maximum descent) / 2), with
-                ROUND(x) = floor (x + 0.5)  */
-
-              if (x_use_underline_position_properties
-                  && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
-                y = s->ybase + (long) tem;
-              else if (s->face->font)
-                y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
-            }
+#ifdef USE_FONT_BACKEND
+         if (enable_font_backend)
+           {
+             if (s->face->font)
+               /* In the future, we must use information of font.  */
+               y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
+             else
+               y = s->y + s->height - h;
+           }
+         else
+#endif
+           {
+             y = s->y + s->height - h;
+             if (!x_underline_at_descent_line)
+               {
+                 /* Get the underline position.  This is the recommended
+                    vertical offset in pixels from the baseline to the top of
+                    the underline.  This is a signed value according to the
+                    specs, and its default is
+
+                    ROUND ((maximum descent) / 2), with
+                    ROUND(x) = floor (x + 0.5)  */
+
+                 if (x_use_underline_position_properties
+                     && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
+                   y = s->ybase + (long) tem;
+                 else if (s->face->font)
+                   y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
+               }
+           }
 
          if (s->face->underline_defaulted_p)
            XFillRectangle (s->display, s->window, s->gc,
@@ -2769,10 +3022,67 @@ x_draw_glyph_string (s)
       /* Draw relief if not yet drawn.  */
       if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
        x_draw_glyph_string_box (s);
+
+      if (s->prev)
+       {
+         struct glyph_string *prev;
+
+         for (prev = s->prev; prev; prev = prev->prev)
+           if (prev->hl != s->hl
+               && prev->x + prev->width + prev->right_overhang > s->x)
+             {
+               /* As prev was drawn while clipped to its own area, we
+                  must draw the right_overhang part using s->hl now.  */
+               enum draw_glyphs_face save = prev->hl;
+
+               prev->hl = s->hl;
+               x_set_glyph_string_gc (prev);
+               x_set_glyph_string_clipping_exactly (s, prev);
+               if (prev->first_glyph->type == CHAR_GLYPH)
+                 x_draw_glyph_string_foreground (prev);
+               else
+                 x_draw_composite_glyph_string_foreground (prev);
+               XSetClipMask (prev->display, prev->gc, None);
+               prev->hl = save;
+#ifdef USE_FONT_BACKEND
+               prev->num_clips = 0;
+#endif /* USE_FONT_BACKEND */
+             }
+       }
+
+      if (s->next)
+       {
+         struct glyph_string *next;
+
+         for (next = s->next; next; next = next->next)
+           if (next->hl != s->hl
+               && next->x - next->left_overhang < s->x + s->width)
+             {
+               /* As next will be drawn while clipped to its own area,
+                  we must draw the left_overhang part using s->hl now.  */
+               enum draw_glyphs_face save = next->hl;
+
+               next->hl = s->hl;
+               x_set_glyph_string_gc (next);
+               x_set_glyph_string_clipping_exactly (s, next);
+               if (next->first_glyph->type == CHAR_GLYPH)
+                 x_draw_glyph_string_foreground (next);
+               else
+                 x_draw_composite_glyph_string_foreground (next);
+               XSetClipMask (next->display, next->gc, None);
+               next->hl = save;
+#ifdef USE_FONT_BACKEND
+               next->num_clips = 0;
+#endif /* USE_FONT_BACKEND */
+             }
+       }
     }
 
   /* Reset clipping.  */
   XSetClipMask (s->display, s->gc, None);
+#ifdef USE_FONT_BACKEND
+  s->num_clips = 0;
+#endif /* USE_FONT_BACKEND */
 }
 
 /* Shift display to make room for inserted glyphs.   */
@@ -2792,7 +3102,8 @@ x_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
    for X frames.  */
 
 static void
-x_delete_glyphs (n)
+x_delete_glyphs (f, n)
+     struct frame *f;
      register int n;
 {
   abort ();
@@ -2815,19 +3126,11 @@ x_clear_area (dpy, window, x, y, width, height, exposures)
 }
 
 
-/* Clear entire frame.  If updating_frame is non-null, clear that
-   frame.  Otherwise clear the selected frame.  */
+/* Clear an entire frame.  */
 
 static void
-x_clear_frame ()
+x_clear_frame (struct frame *f)
 {
-  struct frame *f;
-
-  if (updating_frame)
-    f = updating_frame;
-  else
-    f = SELECTED_FRAME ();
-
   /* Clearing the frame will erase any cursor, so mark them all as no
      longer visible.  */
   mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
@@ -2906,8 +3209,8 @@ XTflash (f)
       XGCValues values;
 
       values.function = GXxor;
-      values.foreground = (f->output_data.x->foreground_pixel
-                          ^ f->output_data.x->background_pixel);
+      values.foreground = (FRAME_FOREGROUND_PIXEL (f)
+                          ^ FRAME_BACKGROUND_PIXEL (f));
 
       gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                      GCFunction | GCForeground, &values);
@@ -3073,7 +3376,8 @@ XTset_terminal_window (n)
    lines or deleting -N lines at vertical position VPOS.  */
 
 static void
-x_ins_del_lines (vpos, n)
+x_ins_del_lines (f, vpos, n)
+     struct frame *f;
      int vpos, n;
 {
   abort ();
@@ -3231,9 +3535,9 @@ x_focus_changed (type, state, dpyinfo, frame, bufp)
 
           /* Don't stop displaying the initial startup message
              for a switch-frame event we don't need.  */
-          if (GC_NILP (Vterminal_frame)
-              && GC_CONSP (Vframe_list)
-              && !GC_NILP (XCDR (Vframe_list)))
+          if (NILP (Vterminal_frame)
+              && CONSP (Vframe_list)
+              && !NILP (XCDR (Vframe_list)))
             {
               bufp->kind = FOCUS_IN_EVENT;
               XSETFRAME (bufp->frame_or_window, frame);
@@ -3343,7 +3647,7 @@ x_frame_rehighlight (dpyinfo)
   if (dpyinfo->x_focus_frame)
     {
       dpyinfo->x_highlight_frame
-       = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
+       = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
           ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
           : dpyinfo->x_focus_frame);
       if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
@@ -3710,7 +4014,8 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
 
       /* Clear the mouse-moved flag for every frame on this display.  */
       FOR_EACH_FRAME (tail, frame)
-       if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
+       if (FRAME_X_P (XFRAME (frame))
+            && FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
          XFRAME (frame)->mouse_moved = 0;
 
       last_mouse_scroll_bar = Qnil;
@@ -3888,26 +4193,27 @@ x_window_to_scroll_bar (display, window_id)
   window_id = (Window) xg_get_scroll_id_for_window (display, window_id);
 #endif /* USE_GTK  && USE_TOOLKIT_SCROLL_BARS */
 
-  for (tail = Vframe_list;
-       XGCTYPE (tail) == Lisp_Cons;
-       tail = XCDR (tail))
+  for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
     {
       Lisp_Object frame, bar, condemned;
 
       frame = XCAR (tail);
       /* All elements of Vframe_list should be frames.  */
-      if (! GC_FRAMEP (frame))
+      if (! FRAMEP (frame))
        abort ();
 
+      if (! FRAME_X_P (XFRAME (frame)))
+        continue;
+      
       /* Scan this frame's scroll bar list for a scroll bar with the
          right window ID.  */
       condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
       for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
           /* This trick allows us to search both the ordinary and
               condemned scroll bar lists with one loop.  */
-          ! GC_NILP (bar) || (bar = condemned,
+          ! NILP (bar) || (bar = condemned,
                               condemned = Qnil,
-                              ! GC_NILP (bar));
+                              ! NILP (bar));
           bar = XSCROLL_BAR (bar)->next)
        if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id &&
             FRAME_X_DISPLAY (XFRAME (frame)) == display)
@@ -3929,15 +4235,16 @@ x_window_to_menu_bar (window)
 {
   Lisp_Object tail;
 
-  for (tail = Vframe_list;
-       XGCTYPE (tail) == Lisp_Cons;
-       tail = XCDR (tail))
+  for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
     {
-      Lisp_Object frame = XCAR (tail);
-      Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
+      if (FRAME_X_P (XFRAME (XCAR (tail))))
+        {
+          Lisp_Object frame = XCAR (tail);
+          Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
 
-      if (menu_bar && xlwmenu_window_p (menu_bar, window))
-       return menu_bar;
+          if (menu_bar && xlwmenu_window_p (menu_bar, window))
+            return menu_bar;
+        }
     }
 
   return NULL;
@@ -4745,7 +5052,7 @@ x_scroll_bar_create (w, top, left, width, height)
 
     a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
     if (a.background_pixel == -1)
-      a.background_pixel = f->output_data.x->background_pixel;
+      a.background_pixel = FRAME_BACKGROUND_PIXEL (f);
 
     a.event_mask = (ButtonPressMask | ButtonReleaseMask
                    | ButtonMotionMask | PointerMotionHintMask
@@ -4787,6 +5094,9 @@ x_scroll_bar_create (w, top, left, width, height)
   XSETINT (bar->start, 0);
   XSETINT (bar->end, 0);
   bar->dragging = Qnil;
+#ifdef USE_TOOLKIT_SCROLL_BARS
+  bar->fringe_extended_p = Qnil;
+#endif
 
   /* Add bar to its frame's list of scroll bars.  */
   bar->next = FRAME_SCROLL_BARS (f);
@@ -4919,7 +5229,7 @@ x_scroll_bar_set_handle (bar, start, end, rebuild)
     /* Restore the foreground color of the GC if we changed it above.  */
     if (f->output_data.x->scroll_bar_foreground_pixel != -1)
       XSetForeground (FRAME_X_DISPLAY (f), gc,
-                     f->output_data.x->foreground_pixel);
+                     FRAME_FOREGROUND_PIXEL (f));
 
     /* Draw the empty space below the handle.  Note that we can't
        clear zero-height areas; that means "clear to end of window." */
@@ -4979,6 +5289,9 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
   struct scroll_bar *bar;
   int top, height, left, sb_left, width, sb_width;
   int window_y, window_height;
+#ifdef USE_TOOLKIT_SCROLL_BARS
+  int fringe_extended_p;
+#endif
 
   /* Get window dimensions.  */
   window_box (w, -1, 0, &window_y, 0, &window_height);
@@ -4999,15 +5312,9 @@ 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))
-    sb_left = (left +
-              (WINDOW_RIGHTMOST_P (w)
-               ? width - sb_width - (width - sb_width) / 2
-               : 0));
+    sb_left = left + (WINDOW_RIGHTMOST_P (w) ? width - sb_width : 0);
   else
-    sb_left = (left +
-              (WINDOW_LEFTMOST_P (w)
-               ? (width - sb_width) / 2
-               : width - sb_width));
+    sb_left = left + (WINDOW_LEFTMOST_P (w) ? 0 : width - sb_width);
 #else
   if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
     sb_left = left + width - sb_width;
@@ -5015,14 +5322,33 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
     sb_left = left;
 #endif
 
+#ifdef USE_TOOLKIT_SCROLL_BARS
+  if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
+    fringe_extended_p = (WINDOW_LEFTMOST_P (w)
+                        && WINDOW_LEFT_FRINGE_WIDTH (w)
+                        && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+                            || WINDOW_LEFT_MARGIN_COLS (w) == 0));
+  else
+    fringe_extended_p = (WINDOW_RIGHTMOST_P (w)
+                        && WINDOW_RIGHT_FRINGE_WIDTH (w)
+                        && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+                            || WINDOW_RIGHT_MARGIN_COLS (w) == 0));
+#endif
+
   /* Does the scroll bar exist yet?  */
   if (NILP (w->vertical_scroll_bar))
     {
       if (width > 0 && height > 0)
        {
          BLOCK_INPUT;
-         x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                       left, top, width, height, False);
+#ifdef USE_TOOLKIT_SCROLL_BARS
+         if (fringe_extended_p)
+           x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                         sb_left, top, sb_width, height, False);
+         else
+#endif
+           x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                         left, top, width, height, False);
          UNBLOCK_INPUT;
        }
 
@@ -5049,13 +5375,19 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
 #ifdef USE_TOOLKIT_SCROLL_BARS
 
       /* Move/size the scroll bar widget.  */
-      if (mask)
+      if (mask || !NILP (bar->fringe_extended_p) != fringe_extended_p)
        {
          /* 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);
+           {
+             if (fringe_extended_p)
+               x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                             sb_left, top, sb_width, height, False);
+             else
+               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),
@@ -5130,6 +5462,8 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
     }
 
 #ifdef USE_TOOLKIT_SCROLL_BARS
+  bar->fringe_extended_p = fringe_extended_p ? Qt : Qnil;
+
   x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
 #else /* not USE_TOOLKIT_SCROLL_BARS */
   /* Set the scroll bar's current state, unless we're currently being
@@ -5297,7 +5631,7 @@ x_scroll_bar_expose (bar, event)
    /* Restore the foreground color of the GC if we changed it above.  */
    if (f->output_data.x->scroll_bar_foreground_pixel != -1)
      XSetForeground (FRAME_X_DISPLAY (f), gc,
-                   f->output_data.x->foreground_pixel);
+                    FRAME_FOREGROUND_PIXEL (f));
 
    UNBLOCK_INPUT;
 
@@ -5317,7 +5651,7 @@ x_scroll_bar_handle_click (bar, event, emacs_event)
      XEvent *event;
      struct input_event *emacs_event;
 {
-  if (! GC_WINDOWP (bar->window))
+  if (! WINDOWP (bar->window))
     abort ();
 
   emacs_event->kind = SCROLL_BAR_CLICK_EVENT;
@@ -5412,7 +5746,7 @@ x_scroll_bar_note_movement (bar, event)
   XSETVECTOR (last_mouse_scroll_bar, bar);
 
   /* If we're dragging the bar, display it.  */
-  if (! GC_NILP (bar->dragging))
+  if (! NILP (bar->dragging))
     {
       /* Where should the handle be now?  */
       int new_start = event->xmotion.y - XINT (bar->dragging);
@@ -5697,7 +6031,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
   int count = 0;
   int do_help = 0;
   int nbytes = 0;
-  struct frame *f;
+  struct frame *f = NULL;
   struct coding_system coding;
   XEvent event = *eventp;
 
@@ -6273,75 +6607,48 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
           bzero (&compose_status, sizeof (compose_status));
           orig_keysym = keysym;
 
-         /* 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.  */
-           {
-             inev.ie.kind = ASCII_KEYSTROKE_EVENT;
-             inev.ie.code = keysym;
+         /* 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.  */
+           {
+             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))
+         /* Keysyms directly mapped to Unicode characters.  */
+         if (keysym >= 0x01000000 && keysym <= 0x0110FFFF)
            {
-             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);
-               }
+             if (keysym < 0x01000080)
+               inev.ie.kind = ASCII_KEYSTROKE_EVENT;
              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);
-               }
+               inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+             inev.ie.code = keysym & 0xFFFFFF;
              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)
+                                        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
@@ -6436,38 +6743,39 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
            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++)
+           for (i = 0, nchars = 0; i < nbytes; i++)
              {
+               if (ASCII_BYTE_P (copy_bufptr[i]))
+                 nchars++;
                STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]);
              }
 
-           {
-             /* 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;
-           }
+           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;
+             }
 
            /* Convert the input data to a sequence of
               character events.  */
@@ -6479,8 +6787,8 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
                  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);
+                               ? ASCII_KEYSTROKE_EVENT
+                               : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
                inev.ie.code = c;
                kbd_buffer_store_event_hold (&inev.ie, hold_quit);
              }
@@ -6549,7 +6857,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
       /* 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);
+        note_mouse_movement (last_mouse_glyph_frame, &event.xmotion);
 #endif
       goto OTHER;
 
@@ -6582,7 +6890,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
 #ifdef USE_GTK
       /* See comment in EnterNotify above */
       else if (last_mouse_glyph_frame)
-        note_mouse_movement (last_mouse_glyph_frame, &event);
+        note_mouse_movement (last_mouse_glyph_frame, &event.xmotion);
 #endif
       goto OTHER;
 
@@ -6622,10 +6930,16 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
 
                 /* Window will be selected only when it is not selected now and
                    last mouse movement event was not in it.  Minibuffer window
-                   will be selected iff it is active.  */
+                   will be selected only when it is active.  */
                 if (WINDOWP (window)
                     && !EQ (window, last_window)
-                    && !EQ (window, selected_window))
+                   && !EQ (window, selected_window)
+                   /* For click-to-focus window managers
+                      create event iff we don't leave the
+                      selected frame.  */
+                   && (focus_follows_mouse
+                       || (EQ (XWINDOW (window)->frame,
+                               XWINDOW (selected_window)->frame))))
                   {
                     inev.ie.kind = SELECT_WINDOW_EVENT;
                     inev.ie.frame_or_window = window;
@@ -6775,27 +7089,23 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
               }
 
             if (!tool_bar_p)
-              if (!dpyinfo->x_focus_frame
-                  || f == dpyinfo->x_focus_frame)
-                {
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
-                  if (! popup_activated ())
+              if (! popup_activated ())
 #endif
-                   {
-                     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);
-                   }
+                {
+                  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
@@ -6989,8 +7299,8 @@ x_dispatch_event (event, display)
    EXPECTED is nonzero if the caller knows input is available.  */
 
 static int
-XTread_socket (sd, expected, hold_quit)
-     register int sd;
+XTread_socket (terminal, expected, hold_quit)
+     struct terminal *terminal;
      int expected;
      struct input_event *hold_quit;
 {
@@ -7013,6 +7323,31 @@ XTread_socket (sd, expected, hold_quit)
 
   ++handling_signal;
 
+#ifdef HAVE_X_SM
+  /* Only check session manager input for the primary display. */
+  if (terminal->id == 1 && x_session_have_connection ())
+    {
+      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
+
+  /* For debugging, this gives a way to fake an I/O error.  */
+  if (terminal->display_info.x == XTread_socket_fake_io_error)
+    {
+      XTread_socket_fake_io_error = 0;
+      x_io_error_quitter (dpyinfo->display);
+    }
+  
+#if 0 /* This loop is a noop now.  */
   /* Find the display we are supposed to read input for.
      It's the one communicating on descriptor SD.  */
   for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
@@ -7043,52 +7378,31 @@ XTread_socket (sd, expected, hold_quit)
 #endif /* HAVE_SELECT */
 #endif /* SIGIO */
 #endif
-
-      /* For debugging, this gives a way to fake an I/O error.  */
-      if (dpyinfo == XTread_socket_fake_io_error)
-       {
-         XTread_socket_fake_io_error = 0;
-         x_io_error_quitter (dpyinfo->display);
-       }
-
-#ifdef HAVE_X_SM
-      {
-       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
-      while (XPending (dpyinfo->display))
-       {
-          int finish;
+  while (XPending (terminal->display_info.x->display))
+    {
+      int finish;
 
-         XNextEvent (dpyinfo->display, &event);
+      XNextEvent (terminal->display_info.x->display, &event);
 
 #ifdef HAVE_X_I18N
-          /* Filter events for the current X input method.  */
-          if (x_filter_event (dpyinfo, &event))
-            break;
+      /* Filter events for the current X input method.  */
+      if (x_filter_event (terminal->display_info.x, &event))
+        break;
 #endif
-         event_found = 1;
+      event_found = 1;
 
-          count += handle_one_xevent (dpyinfo, &event, &finish, hold_quit);
+      count += handle_one_xevent (terminal->display_info.x,
+                                  &event, &finish, hold_quit);
 
-          if (finish == X_EVENT_GOTO_OUT)
-            goto out;
-        }
-#endif /* not USE_GTK */
+      if (finish == X_EVENT_GOTO_OUT)
+        goto out;
     }
 
-#ifdef USE_GTK
+#else /* USE_GTK */
 
   /* For GTK we must use the GTK event loop.  But XEvents gets passed
      to our filter function above, and then to the big event switch.
@@ -7399,8 +7713,7 @@ x_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, activ
     }
 
 #ifndef XFlush
-  if (updating_frame != f)
-    XFlush (FRAME_X_DISPLAY (f));
+  XFlush (FRAME_X_DISPLAY (f));
 #endif
 }
 
@@ -7638,6 +7951,8 @@ x_clear_errors (dpy)
   x_error_message->string[0] = 0;
 }
 
+#if 0 /* See comment in unwind_to_catch why calling this is a bad
+       * idea.  --lorentey   */
 /* Close off all unclosed x_catch_errors calls.  */
 
 void
@@ -7646,6 +7961,7 @@ x_fully_uncatch_errors ()
   while (x_error_message)
     x_uncatch_errors ();
 }
+#endif
 
 /* Nonzero if x_catch_errors has been done and not yet canceled.  */
 
@@ -7711,6 +8027,7 @@ x_connection_closed (dpy, error_message)
 {
   struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
   Lisp_Object frame, tail;
+  int index = SPECPDL_INDEX ();
 
   error_msg = (char *) alloca (strlen (error_message) + 1);
   strcpy (error_msg, error_message);
@@ -7722,6 +8039,44 @@ x_connection_closed (dpy, error_message)
      the original message here.  */
   x_catch_errors (dpy);
 
+  /* Inhibit redisplay while frames are being deleted. */
+  specbind (Qinhibit_redisplay, Qt);
+
+  if (dpyinfo)
+    {
+      /* Protect display from being closed when we delete the last
+         frame on it. */
+      dpyinfo->reference_count++;
+      dpyinfo->terminal->reference_count++;
+    }
+  
+  /* First delete frames whose mini-buffers are on frames
+     that are on the dead display.  */
+  FOR_EACH_FRAME (tail, frame)
+    {
+      Lisp_Object minibuf_frame;
+      minibuf_frame
+       = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
+      if (FRAME_X_P (XFRAME (frame))
+         && FRAME_X_P (XFRAME (minibuf_frame))
+         && ! EQ (frame, minibuf_frame)
+         && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
+       Fdelete_frame (frame, Qt);
+    }
+
+  /* Now delete all remaining frames on the dead display.
+     We are now sure none of these is used as the mini-buffer
+     for another frame that we need to delete.  */
+  FOR_EACH_FRAME (tail, frame)
+    if (FRAME_X_P (XFRAME (frame))
+       && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
+      {
+       /* Set this to t so that Fdelete_frame won't get confused
+          trying to find a replacement.  */
+       FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
+       Fdelete_frame (frame, Qt);
+      }
+
   /* We have to close the display to inform Xt that it doesn't
      exist anymore.  If we don't, Xt will continue to wait for
      events from the display.  As a consequence, a sequence of
@@ -7754,43 +8109,23 @@ x_connection_closed (dpy, error_message)
     xg_display_close (dpyinfo->display);
 #endif
 
-  /* Indicate that this display is dead.  */
   if (dpyinfo)
-    dpyinfo->display = 0;
-
-  /* First delete frames whose mini-buffers are on frames
-     that are on the dead display.  */
-  FOR_EACH_FRAME (tail, frame)
     {
-      Lisp_Object minibuf_frame;
-      minibuf_frame
-       = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
-      if (FRAME_X_P (XFRAME (frame))
-         && FRAME_X_P (XFRAME (minibuf_frame))
-         && ! EQ (frame, minibuf_frame)
-         && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
-       Fdelete_frame (frame, Qt);
-    }
+      /* Indicate that this display is dead.  */
+      dpyinfo->display = 0;
 
-  /* Now delete all remaining frames on the dead display.
-     We are now sure none of these is used as the mini-buffer
-     for another frame that we need to delete.  */
-  FOR_EACH_FRAME (tail, frame)
-    if (FRAME_X_P (XFRAME (frame))
-       && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
-      {
-       /* Set this to t so that Fdelete_frame won't get confused
-          trying to find a replacement.  */
-       FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
-       Fdelete_frame (frame, Qt);
-      }
+      dpyinfo->reference_count--;
+      dpyinfo->terminal->reference_count--;
+      if (dpyinfo->reference_count != 0)
+        /* We have just closed all frames on this display. */
+        abort ();
 
-  if (dpyinfo)
-    x_delete_display (dpyinfo);
+      x_delete_display (dpyinfo);
+    }
 
   x_uncatch_errors ();
 
-  if (x_display_list == 0)
+  if (terminal_list == 0)
     {
       fprintf (stderr, "%s\n", error_msg);
       shut_down_emacs (0, 0, Qnil);
@@ -7804,6 +8139,7 @@ x_connection_closed (dpy, error_message)
   sigunblock (sigmask (SIGALRM));
   TOTALLY_UNBLOCK_INPUT;
 
+  unbind_to (index, Qnil);
   clear_waiting_for_input ();
   error ("%s", error_msg);
 }
@@ -7899,11 +8235,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;
@@ -7947,33 +8288,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;
 
@@ -7983,8 +8336,70 @@ x_new_fontset (f, fontsetname)
     xic_set_xfontset (f, SDATA (fontset_ascii (fontset)));
 #endif
 
-  return build_string (fontsetname);
+  return fontset_name (fontset);
+}
+
+#ifdef USE_FONT_BACKEND
+Lisp_Object
+x_new_fontset2 (f, fontset, font_object)
+     struct frame *f;
+     int fontset;
+     Lisp_Object font_object;
+{
+  struct font *font = XSAVE_VALUE (font_object)->pointer;
+
+  if (FRAME_FONT_OBJECT (f) == font)
+    /* This font is already set in frame F.  There's nothing more to
+       do.  */
+    return fontset_name (fontset);
+
+  BLOCK_INPUT;
+
+  FRAME_FONT_OBJECT (f) = font;
+  FRAME_FONT (f) = font->font.font;
+  FRAME_BASELINE_OFFSET (f) = font->font.baseline_offset;
+  FRAME_FONTSET (f) = fontset;
+
+  FRAME_COLUMN_WIDTH (f) = font->font.average_width;
+  FRAME_SPACE_WIDTH (f) = font->font.space_width;
+  FRAME_LINE_HEIGHT (f) = font->font.height;
+
+  compute_fringe_widths (f, 1);
+
+  /* Compute the scroll bar width in character columns.  */
+  if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
+    {
+      int wid = FRAME_COLUMN_WIDTH (f);
+      FRAME_CONFIG_SCROLL_BAR_COLS (f)
+       = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid - 1) / wid;
+    }
+  else
+    {
+      int wid = FRAME_COLUMN_WIDTH (f);
+      FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
+    }
+
+  /* Now make the frame display the given font.  */
+  if (FRAME_X_WINDOW (f) != 0)
+    {
+      /* Don't change the size of a tip frame; there's no point in
+        doing it because it's done in Fx_show_tip, and it leads to
+        problems because the tip frame has no widget.  */
+      if (NILP (tip_frame) || XFRAME (tip_frame) != f)
+       x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
+    }
+
+#ifdef HAVE_X_I18N
+  if (FRAME_XIC (f)
+      && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
+    xic_set_xfontset (f, SDATA (fontset_ascii (fontset)));
+#endif
+
+  UNBLOCK_INPUT;
+
+  return fontset_name (fontset);
 }
+#endif /* USE_FONT_BACKEND */
 
 \f
 /***********************************************************************
@@ -8014,7 +8429,7 @@ xim_destroy_callback (xim, client_data, call_data)
   FOR_EACH_FRAME (tail, frame)
     {
       struct frame *f = XFRAME (frame);
-      if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
+      if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo)
        {
          FRAME_XIC (f) = NULL;
           xic_free_xfontset (f);
@@ -8113,7 +8528,8 @@ xim_instantiate_callback (display, client_data, call_data)
        {
          struct frame *f = XFRAME (frame);
 
-         if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
+         if (FRAME_X_P (f)
+              && FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
            if (FRAME_XIC (f) == NULL)
              {
                create_frame_xic (f);
@@ -9279,6 +9695,15 @@ x_free_frame_resources (f)
      commands to the X server.  */
   if (dpyinfo->display)
     {
+#ifdef USE_FONT_BACKEND
+      /* We must free faces before destroying windows because some
+        font-driver (e.g. xft) access a window while finishing a
+        face.  */
+      if (enable_font_backend
+         && FRAME_FACE_CACHE (f))
+       free_frame_faces (f);
+#endif /* USE_FONT_BACKEND */
+
       if (f->output_data.x->icon_desc)
        XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
 
@@ -9328,8 +9753,8 @@ x_free_frame_resources (f)
        XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
 #endif /* !USE_X_TOOLKIT */
 
-      unload_color (f, f->output_data.x->foreground_pixel);
-      unload_color (f, f->output_data.x->background_pixel);
+      unload_color (f, FRAME_FOREGROUND_PIXEL (f));
+      unload_color (f, FRAME_BACKGROUND_PIXEL (f));
       unload_color (f, f->output_data.x->cursor_pixel);
       unload_color (f, f->output_data.x->cursor_foreground_pixel);
       unload_color (f, f->output_data.x->border_pixel);
@@ -9673,7 +10098,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
@@ -10146,6 +10571,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);
 
@@ -10257,10 +10683,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
@@ -10360,6 +10786,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
@@ -10472,9 +11052,12 @@ get_bits_and_offset (mask, bits, offset)
   *bits = nr;
 }
 
+/* Return 1 if display DISPLAY is available for use, 0 otherwise.
+   But don't permanently open it, just test its availability.  */
+
 int
 x_display_ok (display)
-    const char * display;
+    const char *display;
 {
     int dpy_ok = 1;
     Display *dpy;
@@ -10487,6 +11070,10 @@ x_display_ok (display)
     return dpy_ok;
 }
 
+/* Open a connection to X display DISPLAY_NAME, and return
+   the structure that describes the open display.
+   If we cannot contact the display, return null.  */
+
 struct x_display_info *
 x_term_init (display_name, xrm_option, resource_name)
      Lisp_Object display_name;
@@ -10495,6 +11082,7 @@ x_term_init (display_name, xrm_option, resource_name)
 {
   int connection;
   Display *dpy;
+  struct terminal *terminal;
   struct x_display_info *dpyinfo;
   XrmDatabase xrdb;
 
@@ -10506,6 +11094,9 @@ x_term_init (display_name, xrm_option, resource_name)
       ++x_initialized;
     }
 
+  if (! x_display_ok (SDATA (display_name)))
+    error ("Display %s can't be opened", SDATA (display_name));
+
 #ifdef USE_GTK
   {
 #define NUM_ARGV 10
@@ -10514,14 +11105,21 @@ x_term_init (display_name, xrm_option, resource_name)
     char **argv2 = argv;
     GdkAtom atom;
 
+#ifndef HAVE_GTK_MULTIDISPLAY
+    if (!EQ (Vinitial_window_system, intern ("x")))
+      error ("Sorry, you cannot connect to X servers with the GTK toolkit");
+#endif
+
     if (x_initialized++ > 1)
       {
+#ifdef HAVE_GTK_MULTIDISPLAY
         /* Opening another display.  If xg_display_open returns less
            than zero, we are probably on GTK 2.0, which can only handle
            one display.  GTK 2.2 or later can handle more than one.  */
         if (xg_display_open (SDATA (display_name), &dpy) < 0)
+#endif
           error ("Sorry, this version of GTK can only handle one display");
-     }
+      }
     else
       {
         for (argc = 0; argc < NUM_ARGV; ++argc)
@@ -10625,6 +11223,8 @@ x_term_init (display_name, xrm_option, resource_name)
   dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
   bzero (dpyinfo, sizeof *dpyinfo);
 
+  terminal = x_create_terminal (dpyinfo);
+
 #ifdef MULTI_KBOARD
   {
     struct x_display_info *share;
@@ -10636,30 +11236,30 @@ x_term_init (display_name, xrm_option, resource_name)
                         SDATA (display_name)))
        break;
     if (share)
-      dpyinfo->kboard = share->kboard;
+      terminal->kboard = share->terminal->kboard;
     else
       {
-       dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
-       init_kboard (dpyinfo->kboard);
+       terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
+       init_kboard (terminal->kboard);
        if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
          {
            char *vendor = ServerVendor (dpy);
            UNBLOCK_INPUT;
-           dpyinfo->kboard->Vsystem_key_alist
+           terminal->kboard->Vsystem_key_alist
              = call1 (Qvendor_specific_keysyms,
                       vendor ? build_string (vendor) : empty_unibyte_string);
            BLOCK_INPUT;
          }
 
-       dpyinfo->kboard->next_kboard = all_kboards;
-       all_kboards = dpyinfo->kboard;
+       terminal->kboard->next_kboard = all_kboards;
+       all_kboards = terminal->kboard;
        /* Don't let the initial kboard remain current longer than necessary.
           That would cause problems if a file loaded on startup tries to
           prompt in the mini-buffer.  */
        if (current_kboard == initial_kboard)
-         current_kboard = dpyinfo->kboard;
+         current_kboard = terminal->kboard;
       }
-    dpyinfo->kboard->reference_count++;
+    terminal->kboard->reference_count++;
   }
 #endif
 
@@ -10674,6 +11274,11 @@ x_term_init (display_name, xrm_option, resource_name)
 
   dpyinfo->display = dpy;
 
+  /* Set the name of the terminal. */
+  terminal->name = (char *) xmalloc (SBYTES (display_name) + 1);
+  strncpy (terminal->name, SDATA (display_name), SBYTES (display_name));
+  terminal->name[SBYTES (display_name)] = 0;
+  
 #if 0
   XSetAfterFunction (x_current_display, x_trace_wire);
 #endif /* ! 0 */
@@ -10969,8 +11574,10 @@ x_term_init (display_name, xrm_option, resource_name)
   }
 
 #ifdef HAVE_X_SM
-  /* Only do this for the first display.  */
-  if (!x_session_initialized++)
+  /* Only do this for the very first display in the Emacs session.
+     Ignore X session management when Emacs was first started on a
+     tty.  */
+  if (terminal->id == 1)
     x_session_initialize (dpyinfo);
 #endif
 
@@ -10979,7 +11586,7 @@ x_term_init (display_name, xrm_option, resource_name)
   return dpyinfo;
 }
 \f
-/* Get rid of display DPYINFO, assuming all frames are already gone,
+/* Get rid of display DPYINFO, deleting all frames on it,
    and without sending any more commands to the X server.  */
 
 void
@@ -10987,6 +11594,21 @@ x_delete_display (dpyinfo)
      struct x_display_info *dpyinfo;
 {
   int i;
+  struct terminal *t;
+
+  /* Close all frames and delete the generic struct terminal for this
+     X display.  */
+  for (t = terminal_list; t; t = t->next_terminal)
+    if (t->type == output_x_window && t->display_info.x == dpyinfo)
+      {
+#ifdef HAVE_X_SM
+        /* Close X session management when we close its display.  */
+        if (t->id == 1 && x_session_have_connection ())
+          x_session_close();
+#endif
+        delete_terminal (t);
+        break;
+      }
 
   delete_keyboard_wait_descriptor (dpyinfo->connection);
 
@@ -11030,10 +11652,6 @@ x_delete_display (dpyinfo)
   XrmDestroyDatabase (dpyinfo->xrdb);
 #endif
 #endif
-#ifdef MULTI_KBOARD
-  if (--dpyinfo->kboard->reference_count == 0)
-    delete_kboard (dpyinfo->kboard);
-#endif
 #ifdef HAVE_X_I18N
   if (dpyinfo->xim)
     xim_close_dpy (dpyinfo);
@@ -11115,71 +11733,131 @@ x_activate_timeout_atimer ()
 extern frame_parm_handler x_frame_parm_handlers[];
 
 static struct redisplay_interface x_redisplay_interface =
-{
-  x_frame_parm_handlers,
-  x_produce_glyphs,
-  x_write_glyphs,
-  x_insert_glyphs,
-  x_clear_end_of_line,
-  x_scroll_run,
-  x_after_update_window_line,
-  x_update_window_begin,
-  x_update_window_end,
-  x_cursor_to,
-  x_flush,
+  {
+    x_frame_parm_handlers,
+    x_produce_glyphs,
+    x_write_glyphs,
+    x_insert_glyphs,
+    x_clear_end_of_line,
+    x_scroll_run,
+    x_after_update_window_line,
+    x_update_window_begin,
+    x_update_window_end,
+    x_cursor_to,
+    x_flush,
 #ifdef XFlush
-  x_flush,
+    x_flush,
 #else
-  0,  /* flush_display_optional */
-#endif
-  x_clear_window_mouse_face,
-  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_draw_glyph_string,
-  x_define_frame_cursor,
-  x_clear_frame_area,
-  x_draw_window_cursor,
-  x_draw_vertical_window_border,
-  x_shift_glyphs_for_insert
-};
+    0,  /* flush_display_optional */
+#endif
+    x_clear_window_mouse_face,
+    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_draw_glyph_string,
+    x_define_frame_cursor,
+    x_clear_frame_area,
+    x_draw_window_cursor,
+    x_draw_vertical_window_border,
+    x_shift_glyphs_for_insert
+  };
+
+
+/* This function is called when the last frame on a display is deleted. */
+void
+x_delete_terminal (struct terminal *terminal)
+{
+  struct x_display_info *dpyinfo = terminal->display_info.x;
+  int i;
+
+  /* Protect against recursive calls.  Fdelete_frame in
+     delete_terminal calls us back when it deletes our last frame.  */
+  if (!terminal->name)
+    return;
+
+  BLOCK_INPUT;
+  /* Free the fonts in the font table.  */
+  for (i = 0; i < dpyinfo->n_fonts; i++)
+    if (dpyinfo->font_table[i].name)
+      {
+       XFreeFont (dpyinfo->display, dpyinfo->font_table[i].font);
+      }
+
+  x_destroy_all_bitmaps (dpyinfo);
+  XSetCloseDownMode (dpyinfo->display, DestroyAll);
+
+#ifdef USE_GTK
+  xg_display_close (dpyinfo->display);
+#else
+#ifdef USE_X_TOOLKIT
+  XtCloseDisplay (dpyinfo->display);
+#else
+  XCloseDisplay (dpyinfo->display);
+#endif
+#endif /* ! USE_GTK */
+
+  x_delete_display (dpyinfo);
+  UNBLOCK_INPUT;
+}
+
+/* Create a struct terminal, initialize it with the X11 specific
+   functions and make DISPLAY->TERMINAL point to it.  */
+
+static struct terminal *
+x_create_terminal (struct x_display_info *dpyinfo)
+{
+  struct terminal *terminal;
+  
+  terminal = create_terminal ();
+
+  terminal->type = output_x_window;
+  terminal->display_info.x = dpyinfo;
+  dpyinfo->terminal = terminal;
+
+  /* kboard is initialized in x_term_init. */
+  
+  terminal->clear_frame_hook = x_clear_frame;
+  terminal->ins_del_lines_hook = x_ins_del_lines;
+  terminal->delete_glyphs_hook = x_delete_glyphs;
+  terminal->ring_bell_hook = XTring_bell;
+  terminal->reset_terminal_modes_hook = XTreset_terminal_modes;
+  terminal->set_terminal_modes_hook = XTset_terminal_modes;
+  terminal->update_begin_hook = x_update_begin;
+  terminal->update_end_hook = x_update_end;
+  terminal->set_terminal_window_hook = XTset_terminal_window;
+  terminal->read_socket_hook = XTread_socket;
+  terminal->frame_up_to_date_hook = XTframe_up_to_date;
+  terminal->mouse_position_hook = XTmouse_position;
+  terminal->frame_rehighlight_hook = XTframe_rehighlight;
+  terminal->frame_raise_lower_hook = XTframe_raise_lower;
+  terminal->fullscreen_hook = XTfullscreen_hook;
+  terminal->set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
+  terminal->condemn_scroll_bars_hook = XTcondemn_scroll_bars;
+  terminal->redeem_scroll_bar_hook = XTredeem_scroll_bar;
+  terminal->judge_scroll_bars_hook = XTjudge_scroll_bars;
+
+  terminal->delete_frame_hook = x_destroy_window;
+  terminal->delete_terminal_hook = x_delete_terminal;
+  
+  terminal->rif = &x_redisplay_interface;
+  terminal->scroll_region_ok = 1;    /* We'll scroll partial frames. */
+  terminal->char_ins_del_ok = 1;
+  terminal->line_ins_del_ok = 1;         /* We'll just blt 'em. */
+  terminal->fast_clear_end_of_line = 1;  /* X does this well. */
+  terminal->memory_below_frame = 0;   /* We don't remember what scrolls
+                                        off the bottom. */
+
+  return terminal;
+}
 
 void
 x_initialize ()
 {
-  rif = &x_redisplay_interface;
-
-  clear_frame_hook = x_clear_frame;
-  ins_del_lines_hook = x_ins_del_lines;
-  delete_glyphs_hook = x_delete_glyphs;
-  ring_bell_hook = XTring_bell;
-  reset_terminal_modes_hook = XTreset_terminal_modes;
-  set_terminal_modes_hook = XTset_terminal_modes;
-  update_begin_hook = x_update_begin;
-  update_end_hook = x_update_end;
-  set_terminal_window_hook = XTset_terminal_window;
-  read_socket_hook = XTread_socket;
-  frame_up_to_date_hook = XTframe_up_to_date;
-  mouse_position_hook = XTmouse_position;
-  frame_rehighlight_hook = XTframe_rehighlight;
-  frame_raise_lower_hook = XTframe_raise_lower;
-  set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
-  condemn_scroll_bars_hook = XTcondemn_scroll_bars;
-  redeem_scroll_bar_hook = XTredeem_scroll_bar;
-  judge_scroll_bars_hook = XTjudge_scroll_bars;
-  fullscreen_hook = XTfullscreen_hook;
-
-  scroll_region_ok = 1;                /* we'll scroll partial frames */
-  char_ins_del_ok = 1;
-  line_ins_del_ok = 1;         /* we'll just blt 'em */
-  fast_clear_end_of_line = 1;  /* X does this well */
-  memory_below_frame = 0;      /* we don't remember what scrolls
-                                  off the bottom */
   baud_rate = 19200;
 
   x_noop_count = 0;
@@ -11195,7 +11873,7 @@ x_initialize ()
 #endif
 
   /* Try to use interrupt input; if we can't, then start polling.  */
-  Fset_input_mode (Qt, Qnil, Qt, Qnil);
+  Fset_input_interrupt_mode (Qt);
 
 #ifdef USE_X_TOOLKIT
   XtToolkitInitialize ();
@@ -11226,9 +11904,11 @@ x_initialize ()
   XSetIOErrorHandler (x_io_error_quitter);
 
   /* Disable Window Change signals;  they are handled by X events.  */
+#if 0              /* Don't.  We may want to open tty frames later. */
 #ifdef SIGWINCH
   signal (SIGWINCH, SIG_DFL);
 #endif /* SIGWINCH */
+#endif
 
   signal (SIGPIPE, x_connection_signal);
 }
@@ -11248,8 +11928,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");