Don't globally add to change-major-mode-hook.
[bpt/emacs.git] / src / xterm.c
index a369419..67335d4 100644 (file)
@@ -1,5 +1,5 @@
 /* X Communication module for terminals which understand the X protocol.
-   Copyright (C) 1989, 1993, 1994, 1995 Free Software Foundation, Inc.
+   Copyright (C) 1989, 93, 94, 95, 1996 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -51,9 +51,9 @@ Boston, MA 02111-1307, USA.  */
 #endif /* makedev */
 #endif /* USG */
 
-#ifdef BSD
+#ifdef BSD_SYSTEM
 #include <sys/ioctl.h>
-#endif /* ! defined (BSD) */
+#endif /* ! defined (BSD_SYSTEM) */
 
 #include "systty.h"
 #include "systime.h"
@@ -68,6 +68,9 @@ Boston, MA 02111-1307, USA.  */
 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed.  */
 /* #include <sys/param.h>  */
 
+#include "charset.h"
+#include "ccl.h"
+#include "fontset.h"
 #include "frame.h"
 #include "dispextern.h"
 #include "termhooks.h"
@@ -84,6 +87,10 @@ Boston, MA 02111-1307, USA.  */
 #include "keyboard.h"
 #include "intervals.h"
 
+#ifdef USE_X_TOOLKIT
+#include <X11/Shell.h>
+#endif
+
 #ifdef USE_X_TOOLKIT
 extern void free_frame_menubar ();
 extern FRAME_PTR x_menubar_window_to_frame ();
@@ -105,18 +112,24 @@ extern void _XEditResCheckMessages ();
 #endif
 #endif
 
-#ifdef HAVE_X11XTR6
+#ifdef HAVE_SETLOCALE
 /* So we can do setlocale.  */
 #include <locale.h>
 #endif
 
 #ifdef SOLARIS2
-/* For XlibDisplayWriting */
-#include <X11/Xlibint.h>
+/* memmove will be defined as a macro in Xfuncs.h unless
+   <string.h> is included beforehand.  The declaration for memmove in
+   <string.h> will cause a syntax error when Xfuncs.h later includes it.  */
+#include <string.h>
 #endif
 
+#ifndef min
 #define min(a,b) ((a)<(b) ? (a) : (b))
+#endif
+#ifndef max
 #define max(a,b) ((a)>(b) ? (a) : (b))
+#endif
 \f
 /* This is a chain of structures for all the X displays currently in use.  */
 struct x_display_info *x_display_list;
@@ -134,6 +147,8 @@ Lisp_Object x_display_name_list;
    is the frame to apply to.  */
 extern struct frame *updating_frame;
 
+extern waiting_for_input;
+
 /* This is a frame waiting to be autoraised, within XTread_socket.  */
 struct frame *pending_autoraise_frame;
 
@@ -163,6 +178,13 @@ static int curs_y;
 
 /* Mouse movement.
 
+   Formerly, we used PointerMotionHintMask (in STANDARD_EVENT_MASK)
+   so that we would have to call XQueryPointer after each MotionNotify
+   event to ask for another such event.  However, this made mouse tracking
+   slow, and there was a bug that made it eventually stop.
+
+   Simply asking for MotionNotify all the time seems to work better.
+
    In order to avoid asking for motion events and then throwing most
    of them away or busy-polling the server for mouse positions, we ask
    the server for pointer motion hints.  This means that we get only
@@ -172,18 +194,14 @@ static int curs_y;
    get another MotionNotify event the next time the mouse moves.  This
    is at least as efficient as getting motion events when mouse
    tracking is on, and I suspect only negligibly worse when tracking
-   is off.
-
-   The silly O'Reilly & Associates Nutshell guides barely document
-   pointer motion hints at all (I think you have to infer how they
-   work from an example), and the description of XQueryPointer doesn't
-   mention that calling it causes you to get another motion hint from
-   the server, which is very important.  */
+   is off.  */
 
 /* Where the mouse was last time we reported a mouse event.  */
 static FRAME_PTR last_mouse_frame;
 static XRectangle last_mouse_glyph;
 
+static Lisp_Object last_mouse_press_frame;
+
 /* The scroll bar in which the last X motion event occurred.
 
    If the last X motion event occurred in a scroll bar, we set this
@@ -222,9 +240,6 @@ extern Lisp_Object Vcommand_line_args, Vsystem_name;
 
 extern Lisp_Object Vx_no_window_manager;
 
-/* Nonzero enables some debugging for the X interface code. */
-extern int _Xdebug;
-
 extern Lisp_Object Qface, Qmouse_face;
 
 extern int errno;
@@ -253,7 +268,7 @@ static void do_line_dance ();
 static int XTcursor_to ();
 static int XTclear_end_of_line ();
 static int x_io_error_quitter ();
-void x_catch_errors ();
+int x_catch_errors ();
 void x_uncatch_errors ();
 \f
 #if 0
@@ -322,6 +337,9 @@ XTupdate_begin (f)
 
   BLOCK_INPUT;
 
+  curs_x = FRAME_CURSOR_X (f);
+  curs_y = FRAME_CURSOR_Y (f);
+
   if (f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame)
     {
       /* Don't do highlighting for mouse motion during the update.  */
@@ -374,10 +392,9 @@ XTupdate_end (f)
   BLOCK_INPUT;
 
   do_line_dance ();
-  x_display_cursor (f, 1);
+  x_display_cursor (f, 1, curs_x, curs_y);
 
-  if (f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame)
-    FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
+  FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
 #if 0
   /* This fails in the case of having updated only the echo area
      if we have switched buffers.  In that case, FRAME_CURRENT_GLYPHS
@@ -431,7 +448,7 @@ XTchange_line_highlight (new_highlight, vpos, first_unused_hpos)
 {
   highlight = new_highlight;
   XTcursor_to (vpos, 0);
-  XTclear_end_of_line (updating_frame->width);
+  XTclear_end_of_line (FRAME_WINDOW_WIDTH (updating_frame));
 }
 
 /* This is used when starting Emacs and when restarting after suspend.
@@ -470,12 +487,25 @@ XTcursor_to (row, col)
   if (updating_frame == 0)
     {
       BLOCK_INPUT;
-      x_display_cursor (selected_frame, 1);
+      x_display_cursor (selected_frame, 1, curs_x, curs_y);
       XFlush (FRAME_X_DISPLAY (selected_frame));
       UNBLOCK_INPUT;
     }
 }
 \f
+
+/* Return a pointer to per char metric information in FONT of a
+   character pointed by B (*XChar2b).  */
+
+#define PER_CHAR_METRIC(font, b)                                          \
+  ((font)->per_char                                                       \
+   ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2                   \
+      + (((font)->min_byte1 || (font)->max_byte1)                         \
+        ? (((b)->byte1 - (font)->min_byte1)                               \
+           * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
+        : 0))                                                             \
+   : &((font)->max_bounds))
+
 /* Display a sequence of N glyphs found at GP.
    WINDOW is the x-window to output to.  LEFT and TOP are starting coords.
    HL is 1 if this text is highlighted, 2 if the cursor is on it,
@@ -483,6 +513,11 @@ XTcursor_to (row, col)
    JUST_FOREGROUND if 1 means draw only the foreground;
    don't alter the background.
 
+   CMPCHARP if non NULL is a pointer to the struct cmpchar_info, which
+   means drawing glyphs on the same column.  This is set to non NULL
+   only when recursively called within dumpglyphs to draw a composite
+   character specified by CMPCHAR.
+
    FONT is the default font to use (for glyphs whose font-code is 0).
 
    Since the display generation code is responsible for calling
@@ -490,62 +525,131 @@ XTcursor_to (row, col)
    the display structure, we can assume that the face code on each
    glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
    to which we can actually apply intern_face.
-   Call this function with input blocked.  */
+   Call this function with input blocked.
+
+   Return overall pixel width of the drawn glyphs.  */
 
 #if 1
 /* This is the multi-face code.  */
 
-static void
-dumpglyphs (f, left, top, gp, n, hl, just_foreground)
+static int
+dumpglyphs (f, left, top, gp, n, hl, just_foreground, cmpcharp)
      struct frame *f;
      int left, top;
      register GLYPH *gp; /* Points to first GLYPH. */
      register int n;  /* Number of glyphs to display. */
      int hl;
      int just_foreground;
+     struct cmpchar_info *cmpcharp;
 {
   /* Holds characters to be displayed. */
-  char *buf = (char *) alloca (f->width * sizeof (*buf));
-  register char *cp;           /* Steps through buf[]. */
+  XChar2b *buf = (XChar2b *) alloca (FRAME_WINDOW_WIDTH (f) * sizeof (*buf));
+  register XChar2b *cp;                /* Steps through buf[]. */
   register int tlen = GLYPH_TABLE_LENGTH;
   register Lisp_Object *tbase = GLYPH_TABLE_BASE;
   Window window = FRAME_X_WINDOW (f);
   int orig_left = left;
+  int gidx = 0;
+  int i;
 
   while (n > 0)
     {
       /* Get the face-code of the next GLYPH.  */
       int cf, len;
-      int g = *gp;
+      GLYPH g = *gp;
+      int ch, first_ch, charset;
+      /* HIGHEST and LOWEST are used while drawing a composite
+         character.  The meanings are described later.  */
+      int highest, lowest;
 
       GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
-      cf = FAST_GLYPH_FACE (g);
+      cf = (cmpcharp ? cmpcharp->face_work : FAST_GLYPH_FACE (g));
+      ch = FAST_GLYPH_CHAR (g);
+      if (gidx == 0) first_ch = ch;
+      charset = CHAR_CHARSET (ch);
+      if (charset == CHARSET_COMPOSITION)
+       {
+         /* We must draw components of the composite character on the
+             same column.  */
+         cmpcharp = cmpchar_table[COMPOSITE_CHAR_ID (ch)];
+
+         /* Set the face in the slot for work.  */
+         cmpcharp->face_work = cf;
+
+         /* We don't need the return value ... */
+         dumpglyphs (f, left, top, cmpcharp->glyph, cmpcharp->glyph_len,
+                     hl, just_foreground, cmpcharp);
+         /* ... because the width of just drawn text can be
+             calculated as follows.  */
+         left += FONT_WIDTH (f->output_data.x->font) * cmpcharp->width;
+
+         ++gp, --n;
+         while (gp && (*gp & GLYPH_MASK_PADDING)) ++gp, --n;
+         cmpcharp = NULL;
+         continue;
+       }
 
-      /* Find the run of consecutive glyphs with the same face-code.
-        Extract their character codes into BUF.  */
+      /* Find the run of consecutive glyphs which can be drawn with
+        the same GC (i.e. the same charset and the same face-code).
+        Extract their character codes into BUF.
+        If CMPCHARP is not NULL, face-code is not checked because we
+        use only the face specified in `cmpcharp->face_work'.  */
       cp = buf;
       while (n > 0)
        {
+         int this_charset, c1, c2;
+
          g = *gp;
          GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
-         if (FAST_GLYPH_FACE (g) != cf)
+         ch = FAST_GLYPH_CHAR (g);
+         SPLIT_CHAR (ch, this_charset, c1, c2);
+         if (this_charset != charset
+             || (cmpcharp == NULL && FAST_GLYPH_FACE (g) != cf))
            break;
 
-         *cp++ = FAST_GLYPH_CHAR (g);
-         --n;
-         ++gp;
+         if (c2 > 0)
+           cp->byte1 = c1, cp->byte2 = c2;
+         else
+           cp->byte1 = 0, cp->byte2 = c1;
+         ++cp;
+         ++gp, --n;
+         while (gp && (*gp & GLYPH_MASK_PADDING))
+           ++gp, --n;
        }
 
       /* LEN gets the length of the run.  */
       len = cp - buf;
-
       /* Now output this run of chars, with the font and pixel values
         determined by the face code CF.  */
       {
        struct face *face = FRAME_DEFAULT_FACE (f);
-       XFontStruct *font = FACE_FONT (face);
-       GC gc = FACE_GC (face);
+       XFontStruct *font = NULL;
+       GC gc;
        int stippled = 0;
+       int line_height = f->output_data.x->line_height;
+       /* Pixel width of each glyph in this run.  */
+       int glyph_width
+         = (FONT_WIDTH (f->output_data.x->font)
+            * (cmpcharp ? cmpcharp->width : CHARSET_WIDTH (charset)));
+       /* Overall pixel width of this run.  */
+       int run_width
+         = (FONT_WIDTH (f->output_data.x->font)
+            * (cmpcharp ? cmpcharp->width : len * CHARSET_WIDTH (charset)));
+       /* A flag to tell if we have already filled background.  We
+          fill background in advance in the following cases:
+          1) A face has stipple.
+          2) A height of font is shorter than LINE_HEIGHT.
+          3) Drawing a composite character.
+          4) Font has non-zero _MULE_BASELINE_OFFSET property.
+          After filling background, we draw glyphs by XDrawString16.  */
+       int background_filled;
+       /* Baseline position of a character, offset from TOP.  */
+       int baseline;
+       /* The property value of `_MULE_RELATIVE_COMPOSE' and
+           `_MULE_DEFAULT_ASCENT'.  */
+       int relative_compose = 0, default_ascent = 0;
+       /* 1 if we find no font or a font of inappropriate size.  */
+       int require_clipping;
 
        /* HL = 3 means use a mouse face previously chosen.  */
        if (hl == 3)
@@ -564,8 +668,6 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground)
              face = FRAME_MODE_LINE_FACE (f);
            else
              face = intern_face (f, FRAME_COMPUTED_FACES (f) [cf]);
-           font = FACE_FONT (face);
-           gc = FACE_GC (face);
            if (FACE_STIPPLE (face))
              stippled = 1;
          }
@@ -576,25 +678,114 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground)
        else if (hl == 1)
          {
            face = FRAME_MODE_LINE_FACE (f);
-           font = FACE_FONT (face);
-           gc   = FACE_GC   (face);
            if (FACE_STIPPLE (face))
              stippled = 1;
          }
 
 #define FACE_DEFAULT (~0)
 
+       /* Setting appropriate font and gc for this charset.  */
+       if (charset != CHARSET_ASCII)
+         {
+           int font_id;
+           int fontset = FACE_FONTSET (face);
+           struct font_info *fontp;
+
+           if ((fontset < 0 && (fontset = FRAME_FONTSET (f)) < 0)
+               || !(fontp = fs_load_font (f, FRAME_X_FONT_TABLE (f),
+                                          charset, NULL, fontset)))
+             goto font_not_found;
+
+           font = (XFontStruct *) (fontp->font);
+           gc = FACE_NON_ASCII_GC (face);
+           XSetFont (FRAME_X_DISPLAY (f), gc, font->fid);
+           baseline
+             = (font->max_byte1 != 0
+                ? (line_height + font->ascent - font->descent) / 2
+                : f->output_data.x->font_baseline - fontp->baseline_offset);
+           if (FONT_HEIGHT (font) <= line_height
+               && (font->ascent > baseline
+                   || font->descent > line_height - baseline))
+             /* Adjust baseline for this font to show the whole
+                 glyphs in a line.  */
+             baseline = line_height - font->descent;
+             
+           if (cmpcharp && cmpcharp->cmp_rule == NULL)
+             {
+               relative_compose = fontp->relative_compose;
+               default_ascent = fontp->default_ascent;
+             }
+
+           /* We have to change code points in the following cases.  */
+           if (fontp->font_encoder)
+             {
+               /* This font requires CCL program to calculate code
+                   point of characters.  */
+               struct ccl_program *ccl = fontp->font_encoder;
+
+               if (CHARSET_DIMENSION (charset) == 1)
+                 for (cp = buf; cp < buf + len; cp++)
+                   {
+                     ccl->reg[0] = charset;
+                     ccl->reg[1] = cp->byte2;
+                     ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
+                     cp->byte2 = ccl->reg[1];
+                   }
+               else
+                 for (cp = buf; cp < buf + len; cp++)
+                   {
+                     ccl->reg[0] = charset;
+                     ccl->reg[1] = cp->byte1, ccl->reg[2] = cp->byte2;
+                     ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
+                     cp->byte1 = ccl->reg[1], cp->byte2 = ccl->reg[2];
+                   }
+             }
+           else if (fontp->encoding[charset])
+             {
+               int enc = fontp->encoding[charset];
+
+               if ((enc == 1 || enc == 2) && CHARSET_DIMENSION (charset) == 2)
+                 for (cp = buf; cp < buf + len; cp++)
+                   cp->byte1 |= 0x80;
+               if (enc == 1 || enc == 3)
+                 for (cp = buf; cp < buf + len; cp++)
+                   cp->byte2 |= 0x80;
+             }
+         }
+       else
+         {
+         font_not_found:
+           if (charset == CHARSET_ASCII || charset == charset_latin_iso8859_1)
+             {
+               font = FACE_FONT (face);
+               if (font == (XFontStruct *) FACE_DEFAULT)
+                 font = f->output_data.x->font;
+               baseline = FONT_BASE (font);
+               if (charset == charset_latin_iso8859_1)
+                 {
+                   if (font->max_char_or_byte2 < 0x80)
+                     /* This font can't display Latin1 characters.  */
+                     font = NULL;
+                   else
+                     {
+                       for (cp = buf; cp < buf + len; cp++)
+                         cp->byte2 |= 0x80;
+                     }
+                 }
+             }
+           gc = FACE_GC (face);
+         }
+
        /* Now override that if the cursor's on this character.  */
        if (hl == 2)
          {
            /* The cursor overrides stippling.  */
            stippled = 0;
 
-           if ((!face->font
-                || face->font == (XFontStruct *) FACE_DEFAULT
-                || face->font == f->output_data.x->font)
+           if (font == f->output_data.x->font
                && face->background == f->output_data.x->background_pixel
-               && face->foreground == f->output_data.x->foreground_pixel)
+               && face->foreground == f->output_data.x->foreground_pixel
+               && !cmpcharp)
              {
                gc = f->output_data.x->cursor_gc;
              }
@@ -621,7 +812,10 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground)
                    xgcv.background = face->foreground;
                    xgcv.foreground = face->background;
                  }
-               xgcv.font = face->font->fid;
+               if (font)
+                 xgcv.font = font->fid;
+               else
+                 xgcv.font = FACE_FONT (face)->fid;
                xgcv.graphics_exposures = 0;
                mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
                if (FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc)
@@ -641,81 +835,258 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground)
              }
          }
 
-       if (font == (XFontStruct *) FACE_DEFAULT)
-         font = f->output_data.x->font;
+       if (font)
+         require_clipping = (!NILP (Vclip_large_size_font)
+                             && (font->ascent > baseline
+                                 || font->descent > line_height - baseline
+                                 || (!cmpcharp
+                                     && FONT_WIDTH (font) > glyph_width)));
+
+       if (font && (just_foreground || (cmpcharp && gidx > 0)))
+         background_filled = 1;
+       else if (stippled)
+         {
+           /* Turn stipple on.  */
+           XSetFillStyle (FRAME_X_DISPLAY (f), gc, FillOpaqueStippled);
+
+           /* Draw stipple or background color on background.  */
+           XFillRectangle (FRAME_X_DISPLAY (f), window, gc,
+                           left, top, run_width, line_height);
 
-       if (just_foreground)
-         XDrawString (FRAME_X_DISPLAY (f), window, gc,
-                      left, top + FONT_BASE (font), buf, len);
+           /* Turn stipple off.  */
+           XSetFillStyle (FRAME_X_DISPLAY (f), gc, FillSolid);
+
+           background_filled = 1;
+         }
+       else if (!font
+                || FONT_HEIGHT (font) < line_height
+                || FONT_WIDTH (font) < glyph_width
+                || cmpcharp)
+         {
+           /* Fill a area for the current run in background pixle of GC.  */
+           XGCValues xgcv;
+           unsigned long mask = GCForeground | GCBackground;
+           unsigned long fore, back;
+
+           /* The current code at first set foreground to background,
+             fill the area, then recover the original foreground.
+             Aren't there any smarter ways?  */
+
+           XGetGCValues (FRAME_X_DISPLAY (f), gc, mask, &xgcv);
+           XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.background);
+           XFillRectangle (FRAME_X_DISPLAY (f), window, gc,
+                           left, top, run_width, line_height);
+           XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.foreground);
+
+           background_filled = 1;
+           if (cmpcharp)
+             /* To assure not to fill background while drawing
+                remaining components.  */
+             just_foreground = 1;
+         }
        else
+         background_filled = 0;
+
+       if (font)
          {
-           if (stippled)
+           if (require_clipping)
+             {
+               Region region;  /* Region used for setting clip mask to GC.  */
+               XPoint x[4];    /* Data used for creating REGION.  */
+
+               x[0].x = x[3].x = left, x[1].x = x[2].x = left + glyph_width;
+               x[0].y = x[1].y = top,  x[2].y = x[3].y = top + line_height;
+               region = XPolygonRegion (x, 4, EvenOddRule);
+               XSetRegion (FRAME_X_DISPLAY (f), gc, region);
+               XDestroyRegion (region);
+             }
+
+           if (!cmpcharp)
+             {
+               if (require_clipping || FONT_WIDTH (font) != glyph_width)
+                 for (i = 0; i < len; i++)
+                   {
+                     if (require_clipping && i > 0) 
+                       XSetClipOrigin (FRAME_X_DISPLAY (f), gc,
+                                       glyph_width * i, 0);
+                     if (background_filled)
+                       XDrawString16 (FRAME_X_DISPLAY (f), window, gc,
+                                      left + glyph_width * i,
+                                      top + baseline, buf + i, 1);
+                     else
+                       XDrawImageString16 (FRAME_X_DISPLAY (f), window, gc,
+                                           left + glyph_width * i,
+                                           top + baseline, buf + i, 1);
+                   }
+               else
+                 {
+                   if (background_filled)
+                     XDrawString16 (FRAME_X_DISPLAY (f), window, gc,
+                                    left, top + baseline, buf, len);
+                   else
+                     XDrawImageString16 (FRAME_X_DISPLAY (f), window, gc,
+                                         left, top + baseline, buf, len);
+                 }
+             }
+           else
              {
-               /* Turn stipple on.  */
-               XSetFillStyle (FRAME_X_DISPLAY (f), gc, FillOpaqueStippled);
+               XCharStruct *pcm; /* Pointer to per char metric info.  */
+
+               if ((cmpcharp->cmp_rule || relative_compose)
+                   && gidx == 0)
+                 {
+                   /* This is the first character.  Initialize variables.
+                      HIGHEST is the highest position of glyphs ever
+                      written, LOWEST the lowest position.  */
+                   int x_offset = 0;
+
+                   if (default_ascent
+                       && CHAR_TABLE_P (Vuse_default_ascent)
+                       && !NILP (Faref (Vuse_default_ascent, first_ch)))
+                     {
+                       highest = default_ascent;
+                       lowest = 0;
+                     }
+                   else
+                     {
+                       pcm = PER_CHAR_METRIC (font, buf);
+                       highest = pcm->ascent + 1;
+                       lowest = - pcm->descent;
+                     }
 
-               /* Draw stipple on background.  */
-               XFillRectangle (FRAME_X_DISPLAY (f), window, gc,
-                               left, top,
-                               FONT_WIDTH (font) * len,
-                               FONT_HEIGHT (font));
+                   if (cmpcharp->cmp_rule)
+                     x_offset = (cmpcharp->col_offset[0]
+                                 * FONT_WIDTH (f->output_data.x->font));
+                   /* Draw the first character at the normal position.  */
+                   XDrawString16 (FRAME_X_DISPLAY (f), window, gc,
+                                  left + x_offset, top + baseline, buf, 1);
+                   i = 1;
+                   gidx++;
+                 }
+               else
+                 i = 0;
 
-               /* Turn stipple off.  */
-               XSetFillStyle (FRAME_X_DISPLAY (f), gc, FillSolid);
+               for (; i < len; i++, gidx++)
+                 {
+                   int x_offset = 0, y_offset = 0;
 
-               /* Draw the text, solidly, onto the stipple pattern.  */
-               XDrawString (FRAME_X_DISPLAY (f), window, gc,
-                            left, top + FONT_BASE (font), buf, len);
+                   if (relative_compose)
+                     {
+                       pcm = PER_CHAR_METRIC (font, buf + i);
+                       if (- pcm->descent >= relative_compose)
+                         {
+                           /* Draw above the current glyphs.  */
+                           y_offset = highest + pcm->descent;
+                           highest += pcm->ascent + pcm->descent;
+                         }
+                       else if (pcm->ascent <= 0)
+                         {
+                           /* Draw beneath the current glyphs.  */
+                           y_offset = lowest - pcm->ascent;
+                           lowest -= pcm->ascent + pcm->descent;
+                         }
+                     }
+                   else if (cmpcharp->cmp_rule)
+                     {
+                       int gref = (cmpcharp->cmp_rule[gidx] - 0xA0) / 9;
+                       int nref = (cmpcharp->cmp_rule[gidx] - 0xA0) % 9;
+                       int bottom, top;
+
+                       /* Re-encode GREF and NREF so that they specify
+                          only Y-axis information:
+                          0:top, 1:base, 2:bottom, 3:center  */
+                       gref = gref / 3 + (gref == 4) * 2;
+                       nref = nref / 3 + (nref == 4) * 2;
+
+                       pcm = PER_CHAR_METRIC (font, buf + i);
+                       bottom = ((gref == 0 ? highest : gref == 1 ? 0
+                                  : gref == 2 ? lowest
+                                  : (highest + lowest) / 2)
+                                 - (nref == 0 ? pcm->ascent + pcm->descent
+                                    : nref == 1 ? pcm->descent : nref == 2 ? 0
+                                    : (pcm->ascent + pcm->descent) / 2));
+                       top = bottom + (pcm->ascent + pcm->descent);
+                       if (top > highest)
+                         highest = top;
+                       if (bottom < lowest)
+                         lowest = bottom;
+                       y_offset = bottom + pcm->descent;
+                       x_offset = (cmpcharp->col_offset[gidx]
+                                   * FONT_WIDTH (f->output_data.x->font));
+                     }
+                   XDrawString16 (FRAME_X_DISPLAY (f), window, gc,
+                                  left + x_offset, top + baseline - y_offset,
+                                  buf + i, 1);
+                 }
              }
-           else
-             XDrawImageString (FRAME_X_DISPLAY (f), window, gc,
-                               left, top + FONT_BASE (font), buf, len);
-
-           /* Clear the rest of the line's height.  */
-           if (f->output_data.x->line_height != FONT_HEIGHT (font))
-             XClearArea (FRAME_X_DISPLAY (f), window, left,
-                         top + FONT_HEIGHT (font),
-                         FONT_WIDTH (font) * len,
-                         /* This is how many pixels of height
-                            we have to clear.  */
-                         f->output_data.x->line_height - FONT_HEIGHT (font),
-                         False);
-         }
+           if (require_clipping)
+             XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
 
 #if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS,
         which often is not up to date yet.  */
-       if (!just_foreground)
+           if (!just_foreground)
+             {
+               if (left == orig_left)
+                 redraw_previous_char (f, PIXEL_TO_CHAR_COL (f, left),
+                                       PIXEL_TO_CHAR_ROW (f, top), hl == 1);
+               if (n == 0)
+                 redraw_following_char (f, PIXEL_TO_CHAR_COL (f, left + len * FONT_WIDTH (font)),
+                                        PIXEL_TO_CHAR_ROW (f, top), hl == 1);
+             }
+#endif
+         }
+       if (!font)
          {
-           if (left == orig_left)
-             redraw_previous_char (f, PIXEL_TO_CHAR_COL (f, left),
-                                   PIXEL_TO_CHAR_ROW (f, top), hl == 1);
-           if (n == 0)
-             redraw_following_char (f, PIXEL_TO_CHAR_COL (f, left + len * FONT_WIDTH (font)),
-                                    PIXEL_TO_CHAR_ROW (f, top), hl == 1);
+           /* Show rectangles to indicate that we found no font.  */
+           int limit = cmpcharp ? 1 : len;
+
+           for (i = 0; i < limit; i++)
+             XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+                             left + glyph_width * i, top,
+                             glyph_width - 1, line_height - 1);
+         }
+       else if (require_clipping && !NILP (Vhighlight_wrong_size_font))
+         {
+           /* Show ??? to indicate that we found a font of
+               inappropriate size.  */
+           int limit = cmpcharp ? 1 : len;
+
+           for (i = 0; i < limit; i++)
+             {
+               XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+                          left + glyph_width * i, top + line_height - 1,
+                          left + glyph_width * i + 1, top + line_height - 1);
+               XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+                          left + glyph_width * i, top + line_height - 3,
+                          left + glyph_width * i, top + line_height - 1);
+             }
          }
-#endif
 
        /* We should probably check for XA_UNDERLINE_POSITION and
           XA_UNDERLINE_THICKNESS properties on the font, but let's
           just get the thing working, and come back to that.  */
        {
-         int underline_position = 1;
+         /* Setting underline position based on the metric of the
+            current font results in shaky underline if it strides
+            over different fonts.  So, we set the position based only
+            on the default font of this frame.  */
+         int underline_position = f->output_data.x->font_baseline + 1;
 
-         if (font->descent <= underline_position)
-           underline_position = font->descent - 1;
+         if (underline_position >= line_height)
+           underline_position = line_height - 1;
 
          if (face->underline)
            XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                            FACE_GC (face),
-                           left, (top
-                                  + FONT_BASE (font)
-                                  + underline_position),
-                           len * FONT_WIDTH (font), 1);
+                           left, top + underline_position, run_width, 1);
        }
 
-       left += len * FONT_WIDTH (font);
+       if (!cmpcharp)
+         left += run_width;
       }
     }
+
+  return (left - orig_left);
 }
 #endif /* 1 */
 
@@ -782,20 +1153,16 @@ XTwrite_glyphs (start, len)
   dumpglyphs (f,
              CHAR_TO_PIXEL_COL (f, curs_x),
              CHAR_TO_PIXEL_ROW (f, curs_y),
-             start, len, highlight, 0);
+             start, len, highlight, 0, NULL);
 
   /* If we drew on top of the cursor, note that it is turned off.  */
   if (curs_y == f->phys_cursor_y
       && curs_x <= f->phys_cursor_x
       && curs_x + len > f->phys_cursor_x)
-    f->phys_cursor_x = -1;
+    f->phys_cursor_on = 0;
 
   if (updating_frame == 0)
-    {
-      f->cursor_x += len;
-      x_display_cursor (f, 1);
-      f->cursor_x -= len;
-    }
+    x_display_cursor (f, 1, FRAME_CURSOR_X (f) + len, FRAME_CURSOR_Y (f));
   else
     curs_x += len;
 
@@ -822,8 +1189,10 @@ XTclear_end_of_line (first_unused)
   if (first_unused <= 0)
     return;
 
-  if (first_unused >= f->width)
-    first_unused = f->width;
+  if (first_unused >= FRAME_WINDOW_WIDTH (f))
+    first_unused = FRAME_WINDOW_WIDTH (f);
+
+  first_unused += FRAME_LEFT_SCROLL_BAR_WIDTH (f);
 
   BLOCK_INPUT;
 
@@ -833,7 +1202,7 @@ XTclear_end_of_line (first_unused)
   if (curs_y == f->phys_cursor_y
       && curs_x <= f->phys_cursor_x
       && f->phys_cursor_x < first_unused)
-    f->phys_cursor_x = -1;
+    f->phys_cursor_on = 0;
 
   XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
              CHAR_TO_PIXEL_COL (f, curs_x),
@@ -856,7 +1225,7 @@ XTclear_frame ()
   if (f == 0)
     f = selected_frame;
 
-  f->phys_cursor_x = -1;       /* Cursor not visible.  */
+  f->phys_cursor_on = 0;       /* Cursor not visible.  */
   curs_x = 0;                  /* Nominal cursor position is top left.  */
   curs_y = 0;
 
@@ -911,7 +1280,7 @@ redraw_previous_char (f, x, y, highlight_flag)
       dumpglyphs (f, CHAR_TO_PIXEL_COL (f, start_x),
                  CHAR_TO_PIXEL_ROW (f, y),
                  &FRAME_CURRENT_GLYPHS (f)->glyphs[y][start_x],
-                 x - start_x, highlight_flag, 1);
+                 x - start_x, highlight_flag, 1, NULL);
     }
 }
 
@@ -947,7 +1316,7 @@ redraw_following_char (f, x, y, highlight_flag)
       dumpglyphs (f, CHAR_TO_PIXEL_COL (f, x),
                  CHAR_TO_PIXEL_ROW (f, y),
                  &FRAME_CURRENT_GLYPHS (f)->glyphs[y][x],
-                 end_x - x, highlight_flag, 1);
+                 end_x - x, highlight_flag, 1, NULL);
     }
 }
 #endif /* 0 */
@@ -1105,11 +1474,49 @@ XTflash (f)
     }
 
     {
-      int width  = PIXEL_WIDTH  (f);
-      int height = PIXEL_HEIGHT (f);
+      /* Get the height not including a menu bar widget.  */
+      int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
+      /* Height of each line to flash.  */
+      int flash_height = FRAME_LINE_HEIGHT (f);
+      /* These will be the left and right margins of the rectangles.  */
+      int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
+      int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
+
+      int width;
+
+      /* Don't flash the area between a scroll bar and the frame
+        edge it is next to.  */
+      switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
+       {
+       case vertical_scroll_bar_left:
+         flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
+         break;
+
+       case vertical_scroll_bar_right:
+         flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
+         break;
+       }
+
+      width = flash_right - flash_left;
+
+      /* If window is tall, flash top and bottom line.  */
+      if (height > 3 * FRAME_LINE_HEIGHT (f))
+       {
+         XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+                         flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
+                         width, flash_height);
+         XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+                         flash_left,
+                         (height - flash_height
+                          - FRAME_INTERNAL_BORDER_WIDTH (f)),
+                         width, flash_height);
+       }
+      else
+       /* If it is short, flash it all.  */ 
+       XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+                       flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
+                       width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
 
-      XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
-                     width/4, height/4, width/2, height/2);
       XFlush (FRAME_X_DISPLAY (f));
 
       {
@@ -1139,8 +1546,24 @@ XTflash (f)
          }
       }
 
-      XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
-                     width/4, height/4, width/2, height/2);
+      /* If window is tall, flash top and bottom line.  */
+      if (height > 3 * FRAME_LINE_HEIGHT (f))
+       {
+         XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+                         flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
+                         width, flash_height);
+         XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+                         flash_left,
+                         (height - flash_height
+                          - FRAME_INTERNAL_BORDER_WIDTH (f)),
+                         width, flash_height);
+       }
+      else
+       /* If it is short, flash it all.  */ 
+       XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+                       flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
+                       width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
+
       XFreeGC (FRAME_X_DISPLAY (f), gc);
       XFlush (FRAME_X_DISPLAY (f));
     }
@@ -1291,9 +1714,9 @@ do_line_dance ()
     abort ();
 
   ht = f->height;
-  intborder = f->output_data.x->internal_border_width;
+  intborder = CHAR_TO_PIXEL_COL (f, FRAME_LEFT_SCROLL_BAR_WIDTH (f));
 
-  x_display_cursor (updating_frame, 0);
+  x_update_cursor (updating_frame, 0);
 
   for (i = 0; i < ht; ++i)
     if (line_dance[i] != -1 && (distance = line_dance[i]-i) > 0)
@@ -1304,7 +1727,7 @@ do_line_dance ()
        XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                   FRAME_X_WINDOW (f), f->output_data.x->normal_gc,
                   intborder, CHAR_TO_PIXEL_ROW (f, i+distance),
-                  f->width * FONT_WIDTH (f->output_data.x->font),
+                  FRAME_WINDOW_WIDTH (f) * FONT_WIDTH (f->output_data.x->font),
                   (j-i) * f->output_data.x->line_height,
                   intborder, CHAR_TO_PIXEL_ROW (f, i));
        i = j-1;
@@ -1319,7 +1742,7 @@ do_line_dance ()
        XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                   FRAME_X_WINDOW (f), f->output_data.x->normal_gc,
                   intborder, CHAR_TO_PIXEL_ROW (f, j+1+distance),
-                  f->width * FONT_WIDTH (f->output_data.x->font),
+                  FRAME_WINDOW_WIDTH (f) * FONT_WIDTH (f->output_data.x->font),
                   (i-j) * f->output_data.x->line_height,
                   intborder, CHAR_TO_PIXEL_ROW (f, j+1));
        i = j+1;
@@ -1332,7 +1755,7 @@ do_line_dance ()
        /* Clear [i,j) */
        XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                    intborder, CHAR_TO_PIXEL_ROW (f, i),
-                   f->width * FONT_WIDTH (f->output_data.x->font),
+                   FRAME_WINDOW_WIDTH (f) * FONT_WIDTH (f->output_data.x->font),
                    (j-i) * f->output_data.x->line_height, False);
        i = j-1;
       }
@@ -1379,8 +1802,8 @@ dumprectangle (f, left, top, cols, rows)
     left = 0;
   if (top < 0)
     top = 0;
-  if (right > f->width)
-    right = f->width;
+  if (right > FRAME_WINDOW_WIDTH (f))
+    right = FRAME_WINDOW_WIDTH (f);
   if (bottom > f->height)
     bottom = f->height;
 
@@ -1410,17 +1833,25 @@ dumprectangle (f, left, top, cols, rows)
       if (! active_frame->enable[y] || left > active_frame->used[y])
        continue;
 
+      while (*line & GLYPH_MASK_PADDING)
+       {
+         /* We must display the whole glyph of a wide-column
+             character.  */
+         left--;
+         line--;
+         cols++;
+       }
       dumpglyphs (f,
                  CHAR_TO_PIXEL_COL (f, left),
                  CHAR_TO_PIXEL_ROW (f, y),
                  line, min (cols, active_frame->used[y] - left),
-                 active_frame->highlight[y], 0);
+                 active_frame->highlight[y], 0, NULL);
     }
 
   /* Turn the cursor on if we turned it off.  */
 
   if (cursor_cleared)
-    x_display_cursor (f, 1);
+    x_update_cursor (f, 1);
 }
 \f
 static void
@@ -1733,8 +2164,8 @@ pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
     {
       if (pix_x < 0)
        pix_x = 0;
-      else if (pix_x > f->width)
-       pix_x = f->width;
+      else if (pix_x > FRAME_WINDOW_WIDTH (f))
+       pix_x = FRAME_WINDOW_WIDTH (f);
 
       if (pix_y < 0)
        pix_y = 0;
@@ -1803,7 +2234,7 @@ construct_menu_click (result, event, f)
   /* Make the event type no_event; we'll change that when we decide
      otherwise.  */
   result->kind = mouse_click;
-  XSETINT (result->code, event->button - Button1);
+  result->code = event->button - Button1;
   result->timestamp = event->time;
   result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
                                               event->state)
@@ -1837,17 +2268,6 @@ note_mouse_movement (frame, event)
       last_mouse_scroll_bar = Qnil;
 
       note_mouse_highlight (frame, -1, -1);
-
-      /* Ask for another mouse motion event.  */
-      {
-       int dummy;
-       Window dummy_window;
-
-       XQueryPointer (event->display, FRAME_X_WINDOW (frame),
-                      &dummy_window, &dummy_window,
-                      &dummy, &dummy, &dummy, &dummy,
-                      (unsigned int *) &dummy);
-      }
     }
 
   /* Has the mouse moved off the glyph it was on at the last sighting?  */
@@ -1860,30 +2280,6 @@ note_mouse_movement (frame, event)
       last_mouse_scroll_bar = Qnil;
 
       note_mouse_highlight (frame, event->x, event->y);
-
-      /* Ask for another mouse motion event.  */
-      {
-       int dummy;
-       Window dummy_window;
-
-       XQueryPointer (event->display, FRAME_X_WINDOW (frame),
-                      &dummy_window, &dummy_window,
-                      &dummy, &dummy, &dummy, &dummy,
-                      (unsigned int *) &dummy);
-      }
-    }
-  else
-    {
-      /* It's on the same glyph.  Call XQueryPointer so we'll get an
-        event the next time the mouse moves and we can see if it's
-        *still* on the same glyph.  */
-      int dummy;
-      Window dummy_window;
-
-      XQueryPointer (event->display, FRAME_X_WINDOW (frame),
-                    &dummy_window, &dummy_window,
-                    &dummy, &dummy, &dummy, &dummy,
-                    (unsigned int *) &dummy);
     }
 }
 
@@ -1938,7 +2334,9 @@ note_mouse_highlight (f, x, y)
   if (WINDOWP (window) && portion == 0 && row >= 0 && column >= 0
       && row < FRAME_HEIGHT (f) && column < FRAME_WIDTH (f)
       && EQ (w->window_end_valid, w->buffer)
-      && w->last_modified == BUF_MODIFF (XBUFFER (w->buffer)))
+      && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
+      && (XFASTINT (w->last_overlay_modified)
+         == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
     {
       int *ptr = FRAME_CURRENT_GLYPHS (f)->charstarts[row];
       int i, pos;
@@ -1990,7 +2388,7 @@ note_mouse_highlight (f, x, y)
 
          /* Put all the overlays we want in a vector in overlay_vec.
             Store the length in len.  */
-         noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len,
+         noverlays = overlays_at (pos, 1, &overlay_vec, &len,
                                   NULL, NULL);
          noverlays = sort_overlays (overlay_vec, noverlays, w);
 
@@ -2021,11 +2419,11 @@ note_mouse_highlight (f, x, y)
              before = Foverlay_start (overlay);
              after = Foverlay_end (overlay);
              /* Record this as the current active region.  */
-             fast_find_position (window, before,
+             fast_find_position (window, XFASTINT (before),
                                  &FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col,
                                  &FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row);
              FRAME_X_DISPLAY_INFO (f)->mouse_face_past_end
-               = !fast_find_position (window, after,
+               = !fast_find_position (window, XFASTINT (after),
                                       &FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col,
                                       &FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row);
              FRAME_X_DISPLAY_INFO (f)->mouse_face_window = window;
@@ -2055,11 +2453,11 @@ note_mouse_highlight (f, x, y)
                = Fnext_single_property_change (position, Qmouse_face,
                                                w->buffer, end);
              /* Record this as the current active region.  */
-             fast_find_position (window, before,
+             fast_find_position (window, XFASTINT (before),
                                  &FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col,
                                  &FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row);
              FRAME_X_DISPLAY_INFO (f)->mouse_face_past_end
-               = !fast_find_position (window, after,
+               = !fast_find_position (window, XFASTINT (after),
                                       &FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col,
                                       &FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row);
              FRAME_X_DISPLAY_INFO (f)->mouse_face_window = window;
@@ -2096,8 +2494,8 @@ fast_find_position (window, pos, columnp, rowp)
   FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
   int i;
   int row = 0;
-  int left = w->left;
-  int top = w->top;
+  int left = WINDOW_LEFT_MARGIN (w);
+  int top = XFASTINT (w->top);
   int height = XFASTINT (w->height) - ! MINI_WINDOW_P (w);
   int width = window_internal_width (w);
   int *charstarts;
@@ -2146,7 +2544,7 @@ fast_find_position (window, pos, columnp, rowp)
   if (maybe_next_line)
     {
       row++;
-      i = 0;
+      lastcol = left;
     }
 
   *rowp = row + top;
@@ -2174,17 +2572,16 @@ show_mouse_face (dpyinfo, hl)
      so that if we have to turn the cursor off and on again
      we will put it back at the same place.  */
   curs_x = f->phys_cursor_x;
-  curs_y = f->phys_cursor_y;
-
+  curs_y = f->phys_cursor_y;  
   for (i = FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row;
        i <= FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row; i++)
     {
       int column = (i == FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row
                    ? FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col
-                   : w->left);
+                   : WINDOW_LEFT_MARGIN (w));
       int endcolumn = (i == FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row
                       ? FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col
-                      : w->left + width);
+                      : WINDOW_LEFT_MARGIN (w) + width);
       endcolumn = min (endcolumn, FRAME_CURRENT_GLYPHS (f)->used[i]);
 
       /* If the cursor's in the text we are about to rewrite,
@@ -2193,7 +2590,7 @@ show_mouse_face (dpyinfo, hl)
          && curs_x >= column - 1
          && curs_x <= endcolumn)
        {
-         x_display_cursor (f, 0);
+         x_update_cursor (f, 0);
          cursor_off = 1;
        }
 
@@ -2203,12 +2600,12 @@ show_mouse_face (dpyinfo, hl)
                  FRAME_CURRENT_GLYPHS (f)->glyphs[i] + column,
                  endcolumn - column,
                  /* Highlight with mouse face if hl > 0.  */
-                 hl > 0 ? 3 : 0, 0);
+                 hl > 0 ? 3 : 0, 0, NULL);
     }
 
   /* If we turned the cursor off, turn it back on.  */
   if (cursor_off)
-    x_display_cursor (f, 1);
+    x_display_cursor (f, 1, curs_x, curs_y);
 
   curs_x = old_curs_x;
   curs_y = old_curs_y;
@@ -2236,6 +2633,24 @@ clear_mouse_face (dpyinfo)
   dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
   dpyinfo->mouse_face_window = Qnil;
 }
+
+/* Just discard the mouse face information for frame F, if any.
+   This is used when the size of F is changed.  */
+
+cancel_mouse_face (f)
+     FRAME_PTR f;
+{
+  Lisp_Object window;
+  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+
+  window = dpyinfo->mouse_face_window;
+  if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
+    {
+      dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
+      dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
+      dpyinfo->mouse_face_window = Qnil;
+    }
+}
 \f
 static struct scroll_bar *x_window_to_scroll_bar ();
 static void x_scroll_bar_report_motion ();
@@ -2258,9 +2673,7 @@ static void x_scroll_bar_report_motion ();
    Don't store anything if we don't have a valid set of values to report.
 
    This clears the mouse_moved flag, so we can wait for the next mouse
-   movement.  This also calls XQueryPointer, which will cause the
-   server to give us another MotionNotify when the mouse moves
-   again. */
+   movement.  */
 
 static void
 XTmouse_position (fp, insist, bar_window, part, x, y, time)
@@ -2321,6 +2734,7 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
        Window win, child;
        int win_x, win_y;
        int parent_x, parent_y;
+       int count;
 
        win = root;
 
@@ -2328,7 +2742,7 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
           structure is changing at the same time this function
           is running.  So at least we must not crash from them.  */
 
-       x_catch_errors (FRAME_X_DISPLAY (*fp));
+       count = x_catch_errors (FRAME_X_DISPLAY (*fp));
 
        if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
            && FRAME_LIVE_P (last_mouse_frame))
@@ -2388,7 +2802,7 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
        if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
          f1 = 0;
 
-       x_uncatch_errors (FRAME_X_DISPLAY (*fp));
+       x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
 
        /* If not, is it one of our scroll bars?  */
        if (! f1)
@@ -2512,7 +2926,8 @@ x_scroll_bar_create (window, top, left, width, height)
        XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
 
                      /* Position and size of scroll bar.  */
-                     left, top, width, height,
+                     left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, top,
+                     width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2, height,
 
                      /* Border width, depth, class, and visual.  */
                      0, CopyFromParent, CopyFromParent, CopyFromParent,
@@ -2575,9 +2990,9 @@ x_scroll_bar_set_handle (bar, start, end, rebuild)
   BLOCK_INPUT;
 
   {
-    int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar->width));
-    int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
-    int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
+    int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
+    int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
+    int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
 
     /* Make sure the values are reasonable, and try to preserve
        the distance between start and end.  */
@@ -2661,9 +3076,10 @@ x_scroll_bar_move (bar, top, left, width, height)
     XWindowChanges wc;
     unsigned int mask = 0;
 
-    wc.x = left;
+    wc.x = left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
     wc.y = top;
-    wc.width = width;
+
+    wc.width = width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
     wc.height = height;
 
     if (left != XINT (bar->left))      mask |= CWX;
@@ -2744,7 +3160,7 @@ XTset_vertical_scroll_bar (window, portion, whole, position)
      dragged.  */
   if (NILP (bar->dragging))
     {
-      int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height);
+      int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, pixel_height);
 
       if (whole == 0)
        x_scroll_bar_set_handle (bar, 0, top_range, 0);
@@ -2878,6 +3294,7 @@ x_scroll_bar_expose (bar, event)
   Window w = SCROLL_BAR_X_WINDOW (bar);
   FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
   GC gc = f->output_data.x->normal_gc;
+  int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
 
   BLOCK_INPUT;
 
@@ -2887,8 +3304,10 @@ x_scroll_bar_expose (bar, event)
   XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
 
                  /* x, y, width, height */
-                 0, 0, XINT (bar->width) - 1, XINT (bar->height) - 1);
-
+                 0, 0,
+                 XINT (bar->width) - 1 - width_trim - width_trim,
+                 XINT (bar->height) - 1);
+    
   UNBLOCK_INPUT;
 }
 
@@ -2918,10 +3337,11 @@ x_scroll_bar_handle_click (bar, event, emacs_event)
   emacs_event->frame_or_window = bar->window;
   emacs_event->timestamp = event->xbutton.time;
   {
+    FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
     int internal_height
-      = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
+      = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
     int top_range
-      = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
+      = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
     int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
 
     if (y < 0) y = 0;
@@ -3001,18 +3421,6 @@ x_scroll_bar_note_movement (bar, event)
          x_scroll_bar_set_handle (bar, new_start, new_end, 0);
        }
     }
-
-  /* Call XQueryPointer so we'll get an event the next time the mouse
-     moves and we can see *still* on the same position.  */
-  {
-    int dummy;
-    Window dummy_window;
-
-    XQueryPointer (event->xmotion.display, event->xmotion.window,
-                  &dummy_window, &dummy_window,
-                  &dummy, &dummy, &dummy, &dummy,
-                  (unsigned int *) &dummy);
-  }
 }
 
 /* Return information to the user about the current position of the mouse
@@ -3052,9 +3460,9 @@ x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
   else
     {
       int inside_height
-       = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
+       = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
       int top_range
-       = VERTICAL_SCROLL_BAR_TOP_RANGE     (XINT (bar->height));
+       = VERTICAL_SCROLL_BAR_TOP_RANGE     (f, XINT (bar->height));
 
       win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
 
@@ -3101,10 +3509,14 @@ x_scroll_bar_clear (f)
 {
   Lisp_Object bar;
 
-  for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
-       bar = XSCROLL_BAR (bar)->next)
-    XClearArea (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
-               0, 0, 0, 0, True);
+  /* We can have scroll bars even if this is 0,
+     if we just turned off scroll bar mode.
+     But in that case we should not clear them.  */
+  if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
+    for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
+        bar = XSCROLL_BAR (bar)->next)
+      XClearArea (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
+                 0, 0, 0, 0, True);
 }
 
 /* This processes Expose events from the menubar specific X event
@@ -3128,6 +3540,7 @@ process_expose_from_menu (event)
        {
          f->async_visible = 1;
          f->async_iconified = 0;
+         f->output_data.x->has_been_visible = 1;
          SET_FRAME_GARBAGED (f);
        }
       else
@@ -3246,6 +3659,22 @@ struct x_display_info *XTread_socket_fake_io_error;
    This variable is used for cycling thru the displays.  */
 static struct x_display_info *next_noop_dpyinfo;
 
+#define SET_SAVED_MENU_EVENT(size) { \
+  if (f->output_data.x->saved_menu_event == 0) \
+    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++; \
+      count++; \
+      numchars--; \
+    } \
+  }
+#define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
+#define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
+
 /* Read events coming from the X server.
    This routine is called by the SIGIO handler.
    We return as soon as there are no more events to be read.
@@ -3255,15 +3684,13 @@ static struct x_display_info *next_noop_dpyinfo;
    We return the number of characters stored into the buffer,
    thus pretending to be `read'.
 
-   WAITP is nonzero if we should block until input arrives.
    EXPECTED is nonzero if the caller knows input is available.  */
 
 int
-XTread_socket (sd, bufp, numchars, waitp, expected)
+XTread_socket (sd, bufp, numchars, expected)
      register int sd;
-     register struct input_event *bufp;
-     register int numchars;
-     int waitp;
+     /* register */ struct input_event *bufp;
+     /* register */ int numchars;
      int expected;
 {
   int count = 0;
@@ -3335,7 +3762,22 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
 
       while (XPending (dpyinfo->display) != 0)
        {
+#ifdef USE_X_TOOLKIT
+          /* needed to raise Motif submenus */
+         XtAppNextEvent (Xt_app_con, &event);
+#else
          XNextEvent (dpyinfo->display, &event);
+#endif
+#ifdef HAVE_X_I18N
+         {
+           struct frame *f1 = x_any_window_to_frame (dpyinfo,
+                                                     &event.xclient.window);
+           /* The necessity of the following line took me
+              a full work-day to decipher from the docs!!  */
+           if (f1 != 0 && FRAME_XIC (f1) && XFilterEvent (&event, None))
+             break;
+         }
+#endif
          event_found = 1;
 
          switch (event.type)
@@ -3384,7 +3826,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                              XSetCommand (FRAME_X_DISPLAY (f),
                                           event.xclient.window,
                                           initial_argv, initial_argc);
-                           else
+                           else if (f)
                              XSetCommand (FRAME_X_DISPLAY (f),
                                           event.xclient.window,
                                           0, 0);
@@ -3533,6 +3975,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                    {
                      f->async_visible = 1;
                      f->async_iconified = 0;
+                     f->output_data.x->has_been_visible = 1;
                      SET_FRAME_GARBAGED (f);
                    }
                  else
@@ -3589,15 +4032,19 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                  /* We can't distinguish, from the event, whether the window
                     has become iconified or invisible.  So assume, if it
                     was previously visible, than now it is iconified.
-                    We depend on x_make_frame_invisible to mark it iconified.  */
+                    But x_make_frame_invisible clears both
+                    the visible flag and the iconified flag;
+                    and that way, we know the window is not iconified now.  */
                  if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
-                   f->async_iconified = 1;
+                   {
+                     f->async_iconified = 1;
 
-                 bufp->kind = iconify_event;
-                 XSETFRAME (bufp->frame_or_window, f);
-                 bufp++;
-                 count++;
-                 numchars--;
+                     bufp->kind = iconify_event;
+                     XSETFRAME (bufp->frame_or_window, f);
+                     bufp++;
+                     count++;
+                     numchars--;
+                   }
                }
              goto OTHER;
 
@@ -3609,6 +4056,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                {
                  f->async_visible = 1;
                  f->async_iconified = 0;
+                 f->output_data.x->has_been_visible = 1;
 
                  /* wait_reading_process_input will notice this and update
                     the frame's display structures.  */
@@ -3622,7 +4070,8 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                      count++;
                      numchars--;
                    }
-                 else
+                 else if (! NILP (Vframe_list)
+                          && ! NILP (XCONS (Vframe_list)->cdr))
                    /* Force a redisplay sooner or later
                       to update the frame titles
                       in case this is the second frame.  */
@@ -3645,6 +4094,21 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                  unsigned char copy_buffer[81];
                  int modifiers;
 
+#if 0 /* This was how we made f10 work in Motif.
+        The drawback is, you can't type at Emacs when the
+        the mouse is in the menu bar.  So it is better to
+        turn off f10 in Motif and let Emacs handle it.  */
+#ifdef USE_MOTIF
+                  if (lw_window_is_in_menubar (event.xkey.window,
+                                               f->output_data.x->menubar_widget
+                                               ))
+                    {
+                      SET_SAVED_KEY_EVENT;
+                      break;
+                    }
+#endif /* USE_MOTIF */
+#endif /* 0 */
+
                  event.xkey.state
                    |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
                                               extra_keyboard_modifiers);
@@ -3660,13 +4124,17 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                                        | dpyinfo->hyper_mod_mask
                                        | dpyinfo->alt_mod_mask);
 
+                 /* In case Meta is ComposeCharacter,
+                    clear its status.  According to Markus Ehrnsperger
+                    Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
+                    this enables ComposeCharacter to work whether or
+                    not it is combined with Meta.  */
+                 if (modifiers & dpyinfo->meta_mod_mask)
+                   bzero (&compose_status, sizeof (compose_status));
+
 #ifdef HAVE_X_I18N
                  if (FRAME_XIC (f))
                    {
-                     /* The necessity of the following line took me
-                        a full work-day to decipher from the docs!!  */
-                     if (XFilterEvent (&event, None))
-                       break;
                      nbytes = XmbLookupString (FRAME_XIC (f),
                                                &event.xkey, copy_buffer,
                                                80, &keysym,
@@ -3686,6 +4154,9 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                    {
                      if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
                           || keysym == XK_Delete
+#ifdef XK_ISO_Left_Tab
+                          || (keysym >= XK_ISO_Left_Tab && keysym <= XK_ISO_Enter)
+#endif
                           || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
                           || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
 #ifdef HPUX
@@ -3897,12 +4368,8 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
              goto OTHER;
 
            case ConfigureNotify:
-             f = x_any_window_to_frame (dpyinfo, event.xconfigure.window);
-             if (f
-#ifdef USE_X_TOOLKIT
-                 && (event.xconfigure.window == XtWindow (f->output_data.x->widget))
-#endif
-                 )
+             f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
+             if (f)
                {
 #ifndef USE_X_TOOLKIT
                  /* In the toolkit version, change_frame_size
@@ -3922,66 +4389,25 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                    {
                      change_frame_size (f, rows, columns, 0, 1);
                      SET_FRAME_GARBAGED (f);
+                     cancel_mouse_face (f);
                    }
 #endif
 
-                 /* Formerly, in the USE_X_TOOLKIT version,
-                    we did not test send_event here.  */
-                 if (1
-#ifndef USE_X_TOOLKIT
-                     && ! event.xconfigure.send_event
-#endif
-                     )
-                   {
-                     Window win, child;
-                     int win_x, win_y;
-
-                     /* Find the position of the outside upper-left corner of
-                        the window, in the root coordinate system.  Don't
-                        refer to the parent window here; we may be processing
-                        this event after the window manager has changed our
-                        parent, but before we have reached the ReparentNotify.  */
-                     XTranslateCoordinates (FRAME_X_DISPLAY (f),
-
-                                            /* From-window, to-window.  */
-                                            event.xconfigure.window,
-                                            FRAME_X_DISPLAY_INFO (f)->root_window,
-
-                                            /* From-position, to-position.  */
-                                            -event.xconfigure.border_width,
-                                            -event.xconfigure.border_width,
-                                            &win_x, &win_y,
-
-                                            /* Child of win.  */
-                                            &child);
-                     event.xconfigure.x = win_x;
-                     event.xconfigure.y = win_y;
-                   }
-
                  f->output_data.x->pixel_width = event.xconfigure.width;
                  f->output_data.x->pixel_height = event.xconfigure.height;
-                 f->output_data.x->left_pos = event.xconfigure.x;
-                 f->output_data.x->top_pos = event.xconfigure.y;
 
                  /* What we have now is the position of Emacs's own window.
                     Convert that to the position of the window manager window.  */
-                 {
-                   int x, y;
-                   x_real_positions (f, &x, &y);
-                   f->output_data.x->left_pos = x;
-                   f->output_data.x->top_pos = y;
-                   /* Formerly we did not do this in the USE_X_TOOLKIT
-                      version.  Let's try making them the same.  */
-/* #ifndef USE_X_TOOLKIT */
-                   if (y != event.xconfigure.y)
-                     {
-                       /* Since the WM decorations come below top_pos now,
-                          we must put them below top_pos in the future.  */
-                       f->output_data.x->win_gravity = NorthWestGravity;
-                       x_wm_set_size_hint (f, (long) 0, 0);
-                     }
-/* #endif */
-                 }
+                 x_real_positions (f, &f->output_data.x->left_pos,
+                                   &f->output_data.x->top_pos);
+
+                 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
+                   {
+                     /* Since the WM decorations come below top_pos now,
+                        we must put them below top_pos in the future.  */
+                     f->output_data.x->win_gravity = NorthWestGravity;
+                     x_wm_set_size_hint (f, (long) 0, 0);
+                   }
                }
              goto OTHER;
 
@@ -4049,20 +4475,30 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                    && event.xbutton.y < f->output_data.x->menubar_height
                    && event.xbutton.same_screen)
                  {
-                   if (f->output_data.x->saved_button_event == 0)
-                     f->output_data.x->saved_button_event
-                       = (XButtonEvent *) xmalloc (sizeof (XButtonEvent)); 
-                   bcopy (&event, f->output_data.x->saved_button_event,
-                          sizeof (XButtonEvent));
-                   if (numchars >= 1)
+                   SET_SAVED_BUTTON_EVENT;
+                   XSETFRAME (last_mouse_press_frame, f);
+                 }
+               else if (event.type == ButtonPress)
+                 {
+                   last_mouse_press_frame = Qnil;
+                   goto OTHER;
+                 }
+#ifdef USE_MOTIF /* This should do not harm for Lucid,
+                   but I am trying to be cautious.  */
+               else if (event.type == ButtonRelease)
+                 {
+                   if (!NILP (last_mouse_press_frame))
                      {
-                       bufp->kind = menu_bar_activate_event;
-                       XSETFRAME (bufp->frame_or_window, f);
-                       bufp++;
-                       count++;
-                       numchars--;
+                       f = XFRAME (last_mouse_press_frame);
+                       if (f->output_data.x)
+                         {
+                           SET_SAVED_BUTTON_EVENT;
+                         }
                      }
+                   else 
+                     goto OTHER;
                  }
+#endif /* USE_MOTIF */
                else
                  goto OTHER;
 #endif /* USE_X_TOOLKIT */
@@ -4149,7 +4585,13 @@ x_draw_box (f, x, y)
   int top  = CHAR_TO_PIXEL_ROW (f, y);
   int width = FONT_WIDTH (f->output_data.x->font);
   int height = f->output_data.x->line_height;
+  int c = FAST_GLYPH_CHAR (f->phys_cursor_glyph);
+  int charset = CHAR_CHARSET (c);
 
+  /* If cursor is on a multi-column character, multiply WIDTH by columns.  */
+  width *= (charset == CHARSET_COMPOSITION
+           ? cmpchar_table[COMPOSITE_CHAR_ID (c)]->width
+           : CHARSET_WIDTH (charset));
   XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                  f->output_data.x->cursor_gc,
                  left, top, width - 1, height - 1);
@@ -4167,11 +4609,11 @@ clear_cursor (f)
   int mask;
 
   if (! FRAME_VISIBLE_P (f)
-      || f->phys_cursor_x < 0)
+      || ! f->phys_cursor_on)
     return;
 
-  x_display_cursor (f, 0);
-  f->phys_cursor_x = -1;
+  x_update_cursor (f, 0);
+  f->phys_cursor_on = 0;
 }
 
 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
@@ -4188,7 +4630,7 @@ x_draw_single_glyph (f, row, column, glyph, highlight)
   dumpglyphs (f,
              CHAR_TO_PIXEL_COL (f, column),
              CHAR_TO_PIXEL_ROW (f, row),
-             &glyph, 1, highlight, 0);
+             &glyph, 1, highlight, 0, NULL);
 }
 
 static void
@@ -4205,11 +4647,11 @@ x_display_bar_cursor (f, on, x, y)
   if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
     return;
 
-  if (! on && f->phys_cursor_x < 0)
+  if (! on && ! f->phys_cursor_on)
     return;
 
   /* If there is anything wrong with the current cursor state, remove it.  */
-  if (f->phys_cursor_x >= 0
+  if (f->phys_cursor_on
       && (!on
          || f->phys_cursor_x != x
          || f->phys_cursor_y != y
@@ -4219,12 +4661,12 @@ x_display_bar_cursor (f, on, x, y)
       x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
                           f->phys_cursor_glyph,
                           current_glyphs->highlight[f->phys_cursor_y]);
-      f->phys_cursor_x = -1;
+      f->phys_cursor_on = 0;
     }
 
   /* If we now need a cursor in the new place or in the new form, do it so.  */
   if (on
-      && (f->phys_cursor_x < 0
+      && (! f->phys_cursor_on
          || (f->output_data.x->current_cursor != bar_cursor)))
     {
       f->phys_cursor_glyph
@@ -4241,6 +4683,7 @@ x_display_bar_cursor (f, on, x, y)
 
       f->phys_cursor_x = x;
       f->phys_cursor_y = y;
+      f->phys_cursor_on = 1;
 
       f->output_data.x->current_cursor = bar_cursor;
     }
@@ -4268,14 +4711,14 @@ x_display_box_cursor (f, on, x, y)
     return;
 
   /* If cursor is off and we want it off, return quickly.  */
-  if (!on && f->phys_cursor_x < 0)
+  if (!on && ! f->phys_cursor_on)
     return;
 
   /* If cursor is currently being shown and we don't want it to be
      or it is in the wrong place,
      or we want a hollow box and it's not so, (pout!)
      erase it.  */
-  if (f->phys_cursor_x >= 0
+  if (f->phys_cursor_on
       && (!on
          || f->phys_cursor_x != x
          || f->phys_cursor_y != y
@@ -4316,14 +4759,14 @@ x_display_box_cursor (f, on, x, y)
                           (mouse_face_here
                            ? 3
                            : current_glyphs->highlight[f->phys_cursor_y]));
-      f->phys_cursor_x = -1;
+      f->phys_cursor_on = 0;
     }
 
   /* If we want to show a cursor,
      or we want a box cursor and it's not so,
      write it in the right place.  */
   if (on
-      && (f->phys_cursor_x < 0
+      && (! f->phys_cursor_on
          || (f->output_data.x->current_cursor != filled_box_cursor
              && f == FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)))
     {
@@ -4346,6 +4789,7 @@ x_display_box_cursor (f, on, x, y)
 
       f->phys_cursor_x = x;
       f->phys_cursor_y = y;
+      f->phys_cursor_on = 1;
     }
 
   if (updating_frame != f)
@@ -4353,29 +4797,19 @@ x_display_box_cursor (f, on, x, y)
 }
 
 /* Display the cursor on frame F, or clear it, according to ON.
-   Use the position specified by curs_x and curs_y
-   if we are doing an update of frame F now.
-   Otherwise use the position in the FRAME_CURSOR_X and FRAME_CURSOR_Y fields
-   of F.  */
+   Also set the frame's cursor position to X and Y.  */
 
-x_display_cursor (f, on)
+x_display_cursor (f, on, x, y)
      struct frame *f;
      int on;
+     int x, y;
 {
   BLOCK_INPUT;
 
-  /* If we're not updating, then don't change the physical cursor
-     position.  Just change (if appropriate) the style of display.  */
-  if (f != updating_frame)
-    {
-      curs_x = FRAME_CURSOR_X (f);
-      curs_y = FRAME_CURSOR_Y (f);
-    }
-
   if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
-    x_display_box_cursor (f, on, curs_x, curs_y);
+    x_display_box_cursor (f, on, x, y);
   else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
-    x_display_bar_cursor (f, on, curs_x, curs_y);
+    x_display_bar_cursor (f, on, x, y);
   else
     /* Those are the only two we have implemented!  */
     abort ();
@@ -4495,272 +4929,264 @@ x_text_icon (f, icon_name)
   return 0;
 }
 \f
-/* Handling X errors.  */
+#define X_ERROR_MESSAGE_SIZE 200
 
-/* Handle the loss of connection to display DISPLAY.  */
+/* If non-nil, this should be a string.
+   It means catch X errors  and store the error message in this string.  */
 
-static SIGTYPE
-x_connection_closed (display, error_message)
+static Lisp_Object x_error_message_string;
+
+/* An X error handler which stores the error message in
+   x_error_message_string.  This is called from x_error_handler if
+   x_catch_errors is in effect.  */
+
+static int
+x_error_catcher (display, error)
      Display *display;
-     char *error_message;
+     XErrorEvent *error;
 {
-  struct x_display_info *dpyinfo = x_display_info_for_display (display);
-  Lisp_Object frame, tail;
+  XGetErrorText (display, error->error_code,
+                XSTRING (x_error_message_string)->data,
+                X_ERROR_MESSAGE_SIZE);
+}
 
-  /* Whatever we were in the middle of, we are going to throw out of it,
-     so reassure various things that have error checks about being
-     called with input blocked.  */
-  TOTALLY_UNBLOCK_INPUT;
+/* Begin trapping X errors for display DPY.  Actually we trap X errors
+   for all displays, but DPY should be the display you are actually
+   operating on.
 
-  if (_Xdebug)
-    abort ();
+   After calling this function, X protocol errors no longer cause
+   Emacs to exit; instead, they are recorded in the string
+   stored in x_error_message_string.
 
-  /* First delete frames whose minibuffers 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);
-    }
+   Calling x_check_errors signals an Emacs error if an X error has
+   occurred since the last call to x_catch_errors or x_check_errors.
 
-  /* Now delete all remaining frames on the dead display.
-     We are now sure none of these is used as the minibuffer
-     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);
-      }
+   Calling x_uncatch_errors resumes the normal error handling.  */
 
-  if (dpyinfo)
-    x_delete_display (dpyinfo);
+void x_check_errors ();
+static Lisp_Object x_catch_errors_unwind ();
 
-  if (x_display_list == 0)
-    {
-      fprintf (stderr, "%s", error_message);
-      shut_down_emacs (0, 0, Qnil);
-      exit (70);
-    }
+int
+x_catch_errors (dpy)
+     Display *dpy;
+{
+  int count = specpdl_ptr - specpdl;
 
-  /* Ordinary stack unwind doesn't deal with these.  */
-#ifdef SIGIO
-  sigunblock (sigmask (SIGIO));
-#endif
-  sigunblock (sigmask (SIGALRM));
-  TOTALLY_UNBLOCK_INPUT;
+  /* Make sure any errors from previous requests have been dealt with.  */
+  XSync (dpy, False);
 
-  error ("%s", error_message);
+  record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
+
+  x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
+  XSTRING (x_error_message_string)->data[0] = 0;
+
+  return count;
 }
 
-/* This is the usual handler for X protocol errors.
-   It kills all frames on the display that we got the error for.
-   If that was the only one, it prints an error message and kills Emacs.  */
+/* Unbind the binding that we made to check for X errors.  */
 
-static int
-x_error_quitter (display, error)
-     Display *display;
-     XErrorEvent *error;
+static Lisp_Object
+x_catch_errors_unwind (old_val)
+     Lisp_Object old_val;
 {
-  char buf[256], buf1[356];
+  x_error_message_string = old_val;
+  return Qnil;
+}
 
-  /* Note that there is no real way portable across R3/R4 to get the
-     original error handler.  */
+/* If any X protocol errors have arrived since the last call to
+   x_catch_errors or x_check_errors, signal an Emacs error using
+   sprintf (a buffer, FORMAT, the x error message text) as the text.  */
 
-  XGetErrorText (display, error->error_code, buf, sizeof (buf));
-  sprintf (buf1, "X protocol error: %s on protocol request %d",
-          buf, error->request_code);
-  x_connection_closed (display, buf1);
+void
+x_check_errors (dpy, format)
+     Display *dpy;
+     char *format;
+{
+  /* Make sure to catch any errors incurred so far.  */
+  XSync (dpy, False);
+
+  if (XSTRING (x_error_message_string)->data[0])
+    error (format, XSTRING (x_error_message_string)->data);
 }
 
-/* This is the handler for X IO errors, always.
-   It kills all frames on the display that we lost touch with.
-   If that was the only one, it prints an error message and kills Emacs.  */
+/* Nonzero if we had any X protocol errors
+   since we did x_catch_errors on DPY.  */
 
-static int
-x_io_error_quitter (display)
-     Display *display;
+int
+x_had_errors_p (dpy)
+     Display *dpy;
 {
-  char buf[256];
+  /* Make sure to catch any errors incurred so far.  */
+  XSync (dpy, False);
 
-  sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
-  x_connection_closed (display, buf);
+  return XSTRING (x_error_message_string)->data[0] != 0;
 }
-\f
-/* Handle SIGPIPE, which can happen when the connection to a server
-   simply goes away.  SIGPIPE is handled by x_connection_signal.
-   It works by sending a no-op command to each X server connection.
-   When we try a connection that has closed, we get SIGPIPE again.
-   But this time, it is handled by x_connection_signal_1.
-   That function knows which connection we were testing,
-   so it closes that one.
-   
-   x_connection_closed never returns,
-   so if more than one connection was lost at once,
-   we only find one.  But XTread_socket keeps trying them all,
-   so it will notice the other closed one sooner or later.  */
-   
 
-static struct x_display_info *x_connection_signal_dpyinfo;
+/* Forget about any errors we have had, since we did x_catch_errors on DPY.  */
 
-static SIGTYPE x_connection_signal ();
+int
+x_clear_errors (dpy)
+     Display *dpy;
+{
+  XSTRING (x_error_message_string)->data[0] = 0;
+}
 
-static SIGTYPE
-x_connection_signal_1 (signalnum)      /* If we don't have an argument, */
-     int signalnum;            /* some compilers complain in signal calls. */
+/* Stop catching X protocol errors and let them make Emacs die.
+   DPY should be the display that was passed to x_catch_errors.
+   COUNT should be the value that was returned by
+   the corresponding call to x_catch_errors.  */
+
+void
+x_uncatch_errors (dpy, count)
+     Display *dpy;
+     int count;
 {
-  signal (SIGPIPE, x_connection_signal);
-  x_connection_closed (x_connection_signal_dpyinfo,
-                      "connection was lost");
+  unbind_to (count, Qnil);
 }
 
+#if 0
+static unsigned int x_wire_count;
+x_trace_wire ()
+{
+  fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
+}
+#endif /* ! 0 */
+
+\f
+/* Handle SIGPIPE, which can happen when the connection to a server
+   simply goes away.  SIGPIPE is handled by x_connection_signal.
+   Don't need to do anything, because the write which caused the 
+   SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
+   which will do the appropriate cleanup for us. */
+   
 static SIGTYPE
 x_connection_signal (signalnum)        /* If we don't have an argument, */
      int signalnum;            /* some compilers complain in signal calls. */
 {
-  x_connection_signal_dpyinfo = x_display_list;
-
-  stop_polling ();
-  sigunblock (SIGPIPE);
-
-  while (x_connection_signal_dpyinfo)
-    {
-      signal (SIGPIPE, x_connection_signal_1);
-      signal (SIGALRM, x_connection_signal_1);
-
-#ifdef SOLARIS2
-#ifdef XlibDisplayWriting
-      /* If the thread-interlock is locked, assume this connection is dead.
-        This assumes that the library does not make other threads
-        that can be locking the display legitimately.  */
-      if (x_connection_signal_dpyinfo->display->flags & XlibDisplayWriting)
-       x_connection_closed (x_connection_signal_dpyinfo,
-                            "connection was lost");
-#endif
-#endif
-
-      XNoOp (x_connection_signal_dpyinfo->display);
-
-      XSync (x_connection_signal_dpyinfo->display, False);
-
-      /* Each time we get here, cycle through the displays now open.  */
-      x_connection_signal_dpyinfo = x_connection_signal_dpyinfo->next;
-    }
-
-  /* We should have found some closed connection.  */
-  abort ();
+#ifdef USG
+  /* USG systems forget handlers when they are used;
+     must reestablish each time */
+  signal (signalnum, x_connection_signal);
+#endif /* USG */
 }
 \f
-/* A buffer for storing X error messages.  */
-static char *x_caught_error_message;
-#define X_CAUGHT_ERROR_MESSAGE_SIZE 200
+/* Handling X errors.  */
 
-/* An X error handler which stores the error message in
-   x_caught_error_message.  This is what's installed when
-   x_catch_errors is in effect.  */
+/* Handle the loss of connection to display DISPLAY.  */
 
-static int
-x_error_catcher (display, error)
+static SIGTYPE
+x_connection_closed (display, error_message)
      Display *display;
-     XErrorEvent *error;
+     char *error_message;
 {
-  XGetErrorText (display, error->error_code,
-                x_caught_error_message, X_CAUGHT_ERROR_MESSAGE_SIZE);
-}
+  struct x_display_info *dpyinfo = x_display_info_for_display (display);
+  Lisp_Object frame, tail;
 
+  /* Indicate that this display is dead.  */
 
-/* Begin trapping X errors for display DPY.  Actually we trap X errors
-   for all displays, but DPY should be the display you are actually
-   operating on.
+#ifdef USE_X_TOOLKIT
+  XtCloseDisplay (display);
+#endif
 
-   After calling this function, X protocol errors no longer cause
-   Emacs to exit; instead, they are recorded in x_cfc_error_message.
+  dpyinfo->display = 0;
 
-   Calling x_check_errors signals an Emacs error if an X error has
-   occurred since the last call to x_catch_errors or x_check_errors.
+  /* First delete frames whose minibuffers 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);
+    }
 
-   Calling x_uncatch_errors resumes the normal error handling.  */
+  /* Now delete all remaining frames on the dead display.
+     We are now sure none of these is used as the minibuffer
+     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);
+      }
 
-void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
+  if (dpyinfo)
+    x_delete_display (dpyinfo);
 
-void
-x_catch_errors (dpy)
-     Display *dpy;
-{
-  /* Make sure any errors from previous requests have been dealt with.  */
-  XSync (dpy, False);
+  if (x_display_list == 0)
+    {
+      fprintf (stderr, "%s\n", error_message);
+      shut_down_emacs (0, 0, Qnil);
+      exit (70);
+    }
 
-  /* Set up the error buffer.  */
-  x_caught_error_message
-    = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE);
-  x_caught_error_message[0] = '\0';
+  /* Ordinary stack unwind doesn't deal with these.  */
+#ifdef SIGIO
+  sigunblock (sigmask (SIGIO));
+#endif
+  sigunblock (sigmask (SIGALRM));
+  TOTALLY_UNBLOCK_INPUT;
 
-  /* Install our little error handler.  */
-  XSetErrorHandler (x_error_catcher);
+  clear_waiting_for_input ();
+  error ("%s", error_message);
 }
 
-/* If any X protocol errors have arrived since the last call to
-   x_catch_errors or x_check_errors, signal an Emacs error using
-   sprintf (a buffer, FORMAT, the x error message text) as the text.  */
+/* This is the usual handler for X protocol errors.
+   It kills all frames on the display that we got the error for.
+   If that was the only one, it prints an error message and kills Emacs.  */
 
-void
-x_check_errors (dpy, format)
-     Display *dpy;
-     char *format;
+static int
+x_error_quitter (display, error)
+     Display *display;
+     XErrorEvent *error;
 {
-  /* Make sure to catch any errors incurred so far.  */
-  XSync (dpy, False);
+  char buf[256], buf1[356];
 
-  if (x_caught_error_message[0])
-    {
-      char buf[X_CAUGHT_ERROR_MESSAGE_SIZE + 56];
+  /* Note that there is no real way portable across R3/R4 to get the
+     original error handler.  */
 
-      sprintf (buf, format, x_caught_error_message);
-      x_uncatch_errors (dpy);
-      error (buf);
-    }
+  XGetErrorText (display, error->error_code, buf, sizeof (buf));
+  sprintf (buf1, "X protocol error: %s on protocol request %d",
+          buf, error->request_code);
+  x_connection_closed (display, buf1);
 }
 
-/* Nonzero if we had any X protocol errors since we did x_catch_errors.  */
+/* This is the first-level handler for X protocol errors.
+   It calls x_error_quitter or x_error_catcher.  */
 
-int
-x_had_errors_p (dpy)
-     Display *dpy;
+static int
+x_error_handler (display, error)
+     Display *display;
+     XErrorEvent *error;
 {
-  /* Make sure to catch any errors incurred so far.  */
-  XSync (dpy, False);
+  char buf[256], buf1[356];
 
-  return x_caught_error_message[0] != 0;
+  if (! NILP (x_error_message_string))
+    x_error_catcher (display, error);
+  else
+    x_error_quitter (display, error);
 }
 
-/* Stop catching X protocol errors and let them make Emacs die.  */
+/* This is the handler for X IO errors, always.
+   It kills all frames on the display that we lost touch with.
+   If that was the only one, it prints an error message and kills Emacs.  */
 
-void
-x_uncatch_errors (dpy)
-     Display *dpy;
+static int
+x_io_error_quitter (display)
+     Display *display;
 {
-  xfree (x_caught_error_message);
-  x_caught_error_message = 0;
-  XSetErrorHandler (x_error_quitter);
-}
+  char buf[256];
 
-#if 0
-static unsigned int x_wire_count;
-x_trace_wire ()
-{
-  fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
+  sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
+  x_connection_closed (display, buf);
 }
-#endif /* ! 0 */
-
 \f
 /* Changing the font of the frame.  */
 
@@ -4774,144 +5200,17 @@ x_new_font (f, fontname)
      struct frame *f;
      register char *fontname;
 {
-  int already_loaded;
-  int n_matching_fonts;
-  XFontStruct *font_info;
-  char **font_names;
-
-  /* Get a list of all the fonts that match this name.  Once we
-     have a list of matching fonts, we compare them against the fonts
-     we already have by comparing font ids.  */
-  font_names = (char **) XListFonts (FRAME_X_DISPLAY (f), fontname,
-                                    1024, &n_matching_fonts);
-  /* Apparently it doesn't set n_matching_fonts to zero when it can't
-     find any matches; font_names == 0 is the only clue.  */
-  if (! font_names)
-    n_matching_fonts = 0;
-
-  /* Don't just give up if n_matching_fonts is 0.
-     Apparently there's a bug on Suns: XListFontsWithInfo can
-     fail to find a font, but XLoadQueryFont may still find it.  */
-
-  /* See if we've already loaded a matching font. */
-  already_loaded = -1;
-  if (n_matching_fonts != 0)
-    {
-      int i, j;
-
-      for (i = 0; i < FRAME_X_DISPLAY_INFO (f)->n_fonts; i++)
-       for (j = 0; j < n_matching_fonts; j++)
-         if (!strcmp (FRAME_X_DISPLAY_INFO (f)->font_table[i].name, font_names[j])
-             || !strcmp (FRAME_X_DISPLAY_INFO (f)->font_table[i].full_name, font_names[j]))
-           {
-             already_loaded = i;
-             fontname = FRAME_X_DISPLAY_INFO (f)->font_table[i].full_name;
-             goto found_font;
-           }
-    }
- found_font:
-
-  /* If we have, just return it from the table.  */
-  if (already_loaded >= 0)
-    f->output_data.x->font = FRAME_X_DISPLAY_INFO (f)->font_table[already_loaded].font;
-  /* Otherwise, load the font and add it to the table.  */
-  else
-    {
-      int i;
-      char *full_name;
-      XFontStruct *font;
-      int n_fonts;
-
-      /* Try to find a character-cell font in the list.  */
-#if 0
-      /* A laudable goal, but this isn't how to do it.  */
-      for (i = 0; i < n_matching_fonts; i++)
-       if (! font_info[i].per_char)
-         break;
-#else
-      i = 0;
-#endif
-
-      /* See comment above.  */
-      if (n_matching_fonts != 0)
-       fontname = font_names[i];
-
-      font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
-      if (! font)
-       {
-         /* Free the information from XListFonts.  */
-         if (n_matching_fonts)
-           XFreeFontNames (font_names);
-         return Qnil;
-       }
+  struct font_info *fontp
+    = fs_load_font (f, FRAME_X_FONT_TABLE (f), CHARSET_ASCII, fontname, -1);
 
-      /* Do we need to create the table?  */
-      if (FRAME_X_DISPLAY_INFO (f)->font_table_size == 0)
-       {
-         FRAME_X_DISPLAY_INFO (f)->font_table_size = 16;
-         FRAME_X_DISPLAY_INFO (f)->font_table
-           = (struct font_info *) xmalloc (FRAME_X_DISPLAY_INFO (f)->font_table_size
-                                           * sizeof (struct font_info));
-       }
-      /* Do we need to grow the table?  */
-      else if (FRAME_X_DISPLAY_INFO (f)->n_fonts
-              >= FRAME_X_DISPLAY_INFO (f)->font_table_size)
-       {
-         FRAME_X_DISPLAY_INFO (f)->font_table_size *= 2;
-         FRAME_X_DISPLAY_INFO (f)->font_table
-           = (struct font_info *) xrealloc (FRAME_X_DISPLAY_INFO (f)->font_table,
-                                            (FRAME_X_DISPLAY_INFO (f)->font_table_size
-                                             * sizeof (struct font_info)));
-       }
-
-      /* Try to get the full name of FONT.  Put it in full_name.  */
-      full_name = 0;
-      for (i = 0; i < font->n_properties; i++)
-       {
-         char *atom
-           = XGetAtomName (FRAME_X_DISPLAY (f), font->properties[i].name);
-         if (!strcmp (atom, "FONT"))
-           {
-             char *name = XGetAtomName (FRAME_X_DISPLAY (f),
-                                        (Atom) (font->properties[i].card32));
-             char *p = name;
-             int dashes = 0;
-
-             /* Count the number of dashes in the "full name".
-                If it is too few, this isn't really the font's full name,
-                so don't use it.
-                In X11R4, the fonts did not come with their canonical names
-                stored in them.  */
-             while (*p)
-               {
-                 if (*p == '-')
-                   dashes++;
-                 p++;
-               }
-
-             if (dashes >= 13)
-               full_name = name;
-
-             break;
-           }
-
-         XFree (atom);
-       }
-
-      n_fonts = FRAME_X_DISPLAY_INFO (f)->n_fonts;
-      FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].name = (char *) xmalloc (strlen (fontname) + 1);
-      bcopy (fontname, FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].name, strlen (fontname) + 1);
-      if (full_name != 0)
-       FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].full_name = full_name;
-      else
-       FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].full_name = FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].name;
-      f->output_data.x->font = FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].font = font;
-      FRAME_X_DISPLAY_INFO (f)->n_fonts++;
-
-      if (full_name)
-       fontname = full_name;
-    }
+  if (!fontp)
+    return Qnil;
 
+  f->output_data.x->font = (XFontStruct *) (fontp->font);
+  f->output_data.x->font_baseline
+    = (f->output_data.x->font->ascent + fontp->baseline_offset);
+  f->output_data.x->fontset = -1;
+  
   /* Compute the scroll bar width in character columns.  */
   if (f->scroll_bar_pixel_width > 0)
     {
@@ -4939,19 +5238,49 @@ x_new_font (f, fontname)
        there are no faces yet, so this font's height is the line height.  */
     f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
 
-  {
-    Lisp_Object lispy_name;
+  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.  */
+
+Lisp_Object
+x_new_fontset (f, fontsetname)
+     struct frame *f;
+     char *fontsetname;
+{
+  int fontset = fs_query_fontset (f, fontsetname);
+  struct fontset_info *fontsetp;
+  Lisp_Object result;
 
-    lispy_name = build_string (fontname);
+  if (fontset < 0)
+    return Qnil;
 
-    /* Free the information from XListFonts.  The data
-       we actually retain comes from XLoadQueryFont.  */
-    XFreeFontNames (font_names);
+  fontsetp = FRAME_FONTSET_DATA (f)->fontset_table[fontset];
 
-    return lispy_name;
-  }
+  if (!fontsetp->fontname[CHARSET_ASCII])
+    /* This fontset doesn't contain ASCII font.  */
+    return Qnil;
+
+  result = x_new_font (f, fontsetp->fontname[CHARSET_ASCII]);
+
+  if (!STRINGP (result))
+    /* Can't load ASCII font.  */
+    return Qnil;
+
+  /* Since x_new_font doesn't update any fontset information, do it now.  */
+  f->output_data.x->fontset = fontset;
+  fs_load_font (f, FRAME_X_FONT_TABLE (f),
+               CHARSET_ASCII, XSTRING (result)->data, fontset);
+
+  return build_string (fontsetname);
 }
 \f
+/* Calculate the absolute position in frame F
+   from its current recorded position values and gravity.  */
+
 x_calc_absolute_position (f)
      struct frame *f;
 {
@@ -4960,6 +5289,11 @@ x_calc_absolute_position (f)
   int flags = f->output_data.x->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;
+
 #ifdef USE_X_TOOLKIT
   this_window = XtWindow (f->output_data.x->widget);
 #else
@@ -4967,21 +5301,47 @@ x_calc_absolute_position (f)
 #endif
 
   /* Find the position of the outside upper-left corner of
-     the inner window, with respect to the outer window.  */
+     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;
-      XTranslateCoordinates (FRAME_X_DISPLAY (f),
+      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-window, to-window.  */
-                            this_window,
-                            f->output_data.x->parent_desc,
+                                /* From-position, to-position.  */
+                                0, 0, &win_x, &win_y,
 
-                            /* 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;
+             int nchildren;
 
-                            /* Child of win.  */
-                            &child);
+             if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
+                               &newparent, &newchildren, &nchildren))
+               break;
+
+             XFree (newchildren);
+
+             f->output_data.x->parent_desc = newparent;
+           }
+         else
+           break;
+       }
+
+      x_uncatch_errors (FRAME_X_DISPLAY (f), count);
       UNBLOCK_INPUT;
     }
 
@@ -4989,17 +5349,18 @@ x_calc_absolute_position (f)
      position that fits on the screen.  */
   if (flags & XNegative)
     f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
-                             - 2 * f->output_data.x->border_width - win_x
-                             - PIXEL_WIDTH (f)
-                             + f->output_data.x->left_pos);
+                                 - 2 * f->output_data.x->border_width - win_x
+                                 - PIXEL_WIDTH (f)
+                                 + f->output_data.x->left_pos);
 
   if (flags & YNegative)
+    /* We used to subtract f->output_data.x->menubar_height here
+       in the toolkit case, but PIXEL_HEIGHT already includes that.  */
     f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
-                            - 2 * f->output_data.x->border_width - win_y
-                            - PIXEL_HEIGHT (f)
-                            - (FRAME_EXTERNAL_MENU_BAR (f)
-                               ? f->output_data.x->menubar_height : 0)
-                            + f->output_data.x->top_pos);
+                                - 2 * f->output_data.x->border_width - win_y
+                                - PIXEL_HEIGHT (f)
+                                + f->output_data.x->top_pos);
+
   /* The left_pos and top_pos
      are now relative to the top and left screen edges,
      so the flags should correspond.  */
@@ -5035,15 +5396,18 @@ x_set_offset (f, xoff, yoff, change_gravity)
   BLOCK_INPUT;
   x_wm_set_size_hint (f, (long) 0, 0);
 
-  /* It is a mystery why we need to add the border_width here
-     when the frame is already visible, but experiment says we do.  */
   modified_left = f->output_data.x->left_pos;
   modified_top = f->output_data.x->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->output_data.x->border_width;
       modified_top += f->output_data.x->border_width;
     }
+#endif
 
 #ifdef USE_X_TOOLKIT
   XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
@@ -5067,9 +5431,11 @@ x_set_window_size (f, change_gravity, cols, rows)
 {
   int pixelwidth, pixelheight;
   int mask;
+  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
 
-#ifdef USE_X_TOOLKIT
   BLOCK_INPUT;
+
+#ifdef USE_X_TOOLKIT
   {
     /* The x and y position of the widget is clobbered by the
        call to XtSetValues within EmacsFrameSetCharSize.
@@ -5081,12 +5447,9 @@ x_set_window_size (f, change_gravity, cols, rows)
     f->output_data.x->widget->core.x = xpos;
     f->output_data.x->widget->core.y = ypos;
   }
-  UNBLOCK_INPUT;
 
 #else /* not USE_X_TOOLKIT */
 
-  BLOCK_INPUT;
-
   check_frame_size (f, &rows, &cols);
   f->output_data.x->vertical_scroll_bar_extra
     = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
@@ -5118,14 +5481,6 @@ x_set_window_size (f, change_gravity, cols, rows)
   PIXEL_WIDTH (f) = pixelwidth;
   PIXEL_HEIGHT (f) = pixelheight;
 
-  /* If cursor was outside the new size, mark it as off.  */
-  if (f->phys_cursor_y >= rows
-      || f->phys_cursor_x >= cols)
-    {
-      f->phys_cursor_x = -1;
-      f->phys_cursor_y = -1;
-    }
-
   /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
      receive in the ConfigureNotify event; if we get what we asked
      for, then the event won't cause the screen to become garbaged, so
@@ -5133,8 +5488,25 @@ x_set_window_size (f, change_gravity, cols, rows)
   SET_FRAME_GARBAGED (f);
 
   XFlush (FRAME_X_DISPLAY (f));
-  UNBLOCK_INPUT;
+
 #endif /* not USE_X_TOOLKIT */
+
+  /* If cursor was outside the new size, mark it as off.  */
+  if (f->phys_cursor_y >= rows
+      || f->phys_cursor_x >= cols)
+    {
+      f->phys_cursor_x = 0;
+      f->phys_cursor_y = 0;
+      f->phys_cursor_on = 0;
+    }
+
+  /* Clear out any recollection of where the mouse highlighting was,
+     since it might be in a place that's outside the new frame size. 
+     Actually checking whether it is outside is a pain in the neck,
+     so don't try--just let the highlighting be done afresh with new size.  */
+  cancel_mouse_face (f);
+
+  UNBLOCK_INPUT;
 }
 \f
 /* Mouse warping.  */
@@ -5241,11 +5613,11 @@ x_lower_frame (f)
 }
 
 static void
-XTframe_raise_lower (f, raise)
+XTframe_raise_lower (f, raise_flag)
      FRAME_PTR f;
-     int raise;
+     int raise_flag;
 {
-  if (raise)
+  if (raise_flag)
     x_raise_frame (f);
   else
     x_lower_frame (f);
@@ -5265,6 +5637,8 @@ x_make_frame_visible (f)
 {
   int mask;
   Lisp_Object type;
+  int starting_flags = f->output_data.x->size_hint_flags;
+  int original_top, original_left;
 
   BLOCK_INPUT;
 
@@ -5309,9 +5683,35 @@ x_make_frame_visible (f)
     Lisp_Object frame;
     int count = input_signal_count;
 
+    original_left = f->output_data.x->left_pos;
+    original_top = f->output_data.x->top_pos;
+
     /* This must come after we set COUNT.  */
     UNBLOCK_INPUT;
 
+    /* Arriving X events are processed here.  */
+
+    /* Now move the window back to where it was "supposed to be".
+       But don't do it if the gravity is negative.
+       When the gravity is negative, this uses a position
+       that is 3 pixels too low.  Perhaps that's really the border width.  */
+
+    if (! FRAME_VISIBLE_P (f)
+       && f->output_data.x->win_gravity == NorthWestGravity
+       && f->output_data.x->has_been_visible)
+      {
+       BLOCK_INPUT;
+
+#ifdef USE_X_TOOLKIT
+       XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
+                    original_left, original_top);
+#else /* not USE_X_TOOLKIT */
+       XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                    original_left, original_top);
+#endif /* not USE_X_TOOLKIT */
+       UNBLOCK_INPUT;
+      }
+
     XSETFRAME (frame, f);
 
     while (1)
@@ -5464,6 +5864,13 @@ x_iconify_frame (f)
        x_wm_set_window_state (f, IconicState);
       /* This was XtPopup, but that did nothing for an iconified frame.  */
       XtMapWidget (f->output_data.x->widget);
+      /* The server won't give us any event to indicate
+        that an invisible frame was changed to an icon,
+        so we have to record it here.  */
+      f->iconified = 1;
+      f->visible = 1;
+      f->async_iconified = 1;
+      f->async_visible = 0;
       UNBLOCK_INPUT;
       return;
     }
@@ -5477,6 +5884,8 @@ x_iconify_frame (f)
     error ("Can't notify window manager of iconification");
 
   f->async_iconified = 1;
+  f->async_visible = 0;
+
 
   BLOCK_INPUT;
   XFlush (FRAME_X_DISPLAY (f));
@@ -5524,6 +5933,7 @@ x_iconify_frame (f)
     }
 
   f->async_iconified = 1;
+  f->async_visible = 0;
 
   XFlush (FRAME_X_DISPLAY (f));
   UNBLOCK_INPUT;
@@ -5539,16 +5949,36 @@ x_destroy_window (f)
 
   BLOCK_INPUT;
 
-  if (f->output_data.x->icon_desc != 0)
-    XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
-  XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
+  /* If a display connection is dead, don't try sending more
+     commands to the X server.  */
+  if (dpyinfo->display != 0)
+    {
+      if (f->output_data.x->icon_desc != 0)
+       XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
+#ifdef HAVE_X_I18N
+      if (FRAME_XIM (f))
+       {
+         XDestroyIC (FRAME_XIC (f));
+#if ! defined (SOLARIS2) || defined (HAVE_X11R6)
+         /* This line causes crashes on Solaris with Openwin,
+            due to an apparent bug in XCloseIM.
+            X11R6 seems not to have the bug.  */
+         XCloseIM (FRAME_XIM (f));
+#endif
+       }
+#endif
+      XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
 #ifdef USE_X_TOOLKIT
-  XtDestroyWidget (f->output_data.x->widget);
-  free_frame_menubar (f);
+      XtDestroyWidget (f->output_data.x->widget);
+      free_frame_menubar (f);
 #endif /* USE_X_TOOLKIT */
 
-  free_frame_faces (f);
-  XFlush (FRAME_X_DISPLAY (f));
+      free_frame_faces (f);
+      XFlush (FRAME_X_DISPLAY (f));
+    }
+
+  if (f->output_data.x->saved_menu_event)
+    free (f->output_data.x->saved_menu_event);
 
   xfree (f->output_data.x);
   f->output_data.x = 0;
@@ -5747,6 +6177,8 @@ x_wm_set_icon_pixmap (f, pixmap_id)
      struct frame *f;
      int pixmap_id;
 {
+  Pixmap icon_pixmap;
+
 #ifdef USE_X_TOOLKIT
   Window window = XtWindow (f->output_data.x->widget);
 #else
@@ -5755,7 +6187,7 @@ x_wm_set_icon_pixmap (f, pixmap_id)
 
   if (pixmap_id > 0)
     {
-      Pixmap icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
+      icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
       f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
     }
   else
@@ -5774,8 +6206,20 @@ x_wm_set_icon_pixmap (f, pixmap_id)
 #endif
     }
 
+#ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state.  */
+
+  {
+    Arg al[1];
+    XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
+    XtSetValues (f->output_data.x->widget, al, 1);
+  }
+
+#else /* not USE_X_TOOLKIT */
+  
   f->output_data.x->wm_hints.flags |= IconPixmapHint;
   XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
+
+#endif /* not USE_X_TOOLKIT */
 }
 
 x_wm_set_icon_position (f, icon_x, icon_y)
@@ -5796,6 +6240,369 @@ x_wm_set_icon_position (f, icon_x, icon_y)
 }
 
 \f
+/* Interface to fontset handler.  */
+
+/* Return a pointer to struct font_info of font FONT_IDX of frame F.  */
+struct font_info *
+x_get_font_info (f, font_idx)
+     FRAME_PTR f;
+     int font_idx;
+{
+  return (FRAME_X_FONT_TABLE (f) + font_idx);
+}
+
+
+/* Return a list of names of available fonts matching PATTERN on frame
+   F.  If SIZE is not 0, it is the size (maximum bound width) of fonts
+   to be listed.  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 on how many fonts to match.  */
+
+Lisp_Object
+x_list_fonts (f, pattern, size, maxnames)
+     FRAME_PTR f;
+     Lisp_Object pattern;
+     int size;
+     int maxnames;
+{
+  Lisp_Object list, patterns = Qnil, newlist = Qnil, key, tem, second_best;
+  Display *dpy = f != NULL ? FRAME_X_DISPLAY (f) : x_display_list->display;
+
+  for (list = Valternative_fontname_alist; CONSP (list);
+       list = XCONS (list)->cdr)
+    {
+      tem = XCONS (list)->car;
+      if (CONSP (tem)
+         && STRINGP (XCONS (tem)->car)
+         && !NILP (Fstring_equal (XCONS (tem)->car, pattern)))
+       {
+         patterns = XCONS (tem)->cdr;
+         break;
+       }
+    }
+
+  for (patterns = Fcons (pattern, patterns); CONSP (patterns);
+       patterns = XCONS (patterns)->cdr, pattern = XCONS (patterns)->car)
+    {
+      int num_fonts;
+      char **names;
+
+      /* See if we cached the result for this particular query.  */
+      if (f && (tem = XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr,
+               key = Fcons (pattern, make_number (maxnames)),
+               !NILP (list = Fassoc (key, tem))))
+       {
+         list = Fcdr_safe (list);
+         /* We have a cashed list.  Don't have to get the list again.  */
+         goto label_cached;
+       }
+
+      /* At first, put PATTERN in the cache.  */
+      BLOCK_INPUT;
+      names = XListFonts (dpy, XSTRING (pattern)->data, maxnames, &num_fonts);
+      UNBLOCK_INPUT;
+
+      if (names)
+       {
+         int i;
+
+         /* Make a list of all the fonts we got back.
+            Store that in the font cache for the display.  */
+         for (i = 0; i < num_fonts; i++)
+           {
+             char *p = names[i];
+             int average_width = -1, dashes = 0, width = 0;
+
+             /* Count the number of dashes in NAMES[I].  If there are
+               14 dashes, and the field value following 12th dash
+               (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
+               is usually too ugly to be used for editing.  Let's
+               ignore it.  */
+             while (*p)
+               if (*p++ == '-')
+                 {
+                   dashes++;
+                   if (dashes == 7) /* PIXEL_SIZE field */
+                     width = atoi (p);
+                   else if (dashes == 12) /* AVERAGE_WIDTH field */
+                     average_width = atoi (p);
+                 }
+             if (dashes < 14 || average_width != 0)
+               {
+                 tem = build_string (names[i]);
+                 if (NILP (Fassoc (tem, list)))
+                   {
+                     if (STRINGP (Vx_pixel_size_width_font_regexp)
+                         && ((fast_c_string_match_ignore_case
+                              (Vx_pixel_size_width_font_regexp, names[i]))
+                             >= 0))
+                       /* We can set the value of PIXEL_SIZE to the
+                         width of this font.  */
+                       list = Fcons (Fcons (tem, make_number (width)), list);
+                     else
+                       /* For the moment, width is not known.  */
+                       list = Fcons (Fcons (tem, Qnil), list);
+                   }
+               }
+           }
+         XFreeFontNames (names);
+       }
+
+      /* Now store the result in the cache.  */
+      if (f != NULL)
+       XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr
+         = Fcons (Fcons (key, list),
+                  XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr);
+
+    label_cached:
+      if (NILP (list)) continue; /* Try the remaining alternatives.  */
+
+      newlist = second_best = Qnil;
+      /* Make a list of the fonts that have the right width.  */
+      for (; CONSP (list); list = XCONS (list)->cdr)
+       {
+         tem = XCONS (list)->car;
+
+         if (!CONSP (tem) || NILP (XCONS (tem)->car))
+           continue;
+         if (!size)
+           {
+             newlist = Fcons (XCONS (tem)->car, newlist);
+             continue;
+           }
+
+         if (!INTEGERP (XCONS (tem)->cdr))
+           {
+             /* Since we have not yet known the size of this font, we
+               must try slow function call XLoadQueryFont.  */
+             XFontStruct *thisinfo;
+
+             BLOCK_INPUT;
+             thisinfo = XLoadQueryFont (dpy,
+                                        XSTRING (XCONS (tem)->car)->data);
+             UNBLOCK_INPUT;
+
+             if (thisinfo)
+               {
+                 XCONS (tem)->cdr =  make_number (thisinfo->max_bounds.width);
+                 XFreeFont (dpy, thisinfo);
+               }
+             else
+               /* For unknown reason, the previous call of XListFont had
+                 retruned a font which can't be opened.  Record the size
+                 as 0 not to try to open it again.  */
+               XCONS (tem)->cdr = make_number (0);
+           }
+         if (XINT (XCONS (tem)->cdr) == size)
+           newlist = Fcons (XCONS (tem)->car, newlist);
+         else if (NILP (second_best))
+           second_best = tem;
+         else if (XINT (XCONS (tem)->cdr) < size)
+           {
+             if (XINT (XCONS (second_best)->cdr) > size
+                 || XINT (XCONS (second_best)->cdr) < XINT (XCONS (tem)->cdr))
+               second_best = tem;
+           }
+         else
+           {
+             if (XINT (XCONS (second_best)->cdr) > size
+                 && XINT (XCONS (second_best)->cdr) > XINT (XCONS (tem)->cdr))
+               second_best = tem;
+           }
+       }
+      if (!NILP (newlist))
+       break;
+      else if (!NILP (second_best))
+       {
+         newlist = Fcons (XCONS (second_best)->car, Qnil);
+         break;
+       }
+    }
+
+  return newlist;
+}  
+
+/* Load font named FONTNAME of the size SIZE for frame F, and return a
+   pointer to the structure font_info while allocating it dynamically.
+   If SIZE is 0, load any size of font.
+   If loading is failed, return NULL.  */
+
+struct font_info *
+x_load_font (f, fontname, size)
+     struct frame *f;
+     register char *fontname;
+     int size;
+{
+  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  Lisp_Object font_names;
+
+  /* Get a list of all the fonts that match this name.  Once we
+     have a list of matching fonts, we compare them against the fonts
+     we already have by comparing names.  */
+  font_names = x_list_fonts (f, build_string (fontname), size, 256);
+
+  if (!NILP (font_names))
+    {
+      Lisp_Object tail;
+      int i;
+
+      for (i = 0; i < dpyinfo->n_fonts; i++)
+       for (tail = font_names; CONSP (tail); tail = XCONS (tail)->cdr)
+         if (!strcmp (dpyinfo->font_table[i].name,
+                      XSTRING (XCONS (tail)->car)->data)
+             || !strcmp (dpyinfo->font_table[i].full_name,
+                         XSTRING (XCONS (tail)->car)->data))
+           return (dpyinfo->font_table + i);
+    }
+
+  /* Load the font and add it to the table.  */
+  {
+    char *full_name;
+    XFontStruct *font;
+    struct font_info *fontp;
+    unsigned long value;
+
+    if (!NILP (font_names))
+      fontname = (char *) XSTRING (XCONS (font_names)->car)->data;
+
+    BLOCK_INPUT;
+    font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
+    UNBLOCK_INPUT;
+    if (!font)
+      return NULL;
+
+    /* Do we need to create the table?  */
+    if (dpyinfo->font_table_size == 0)
+      {
+       dpyinfo->font_table_size = 16;
+       dpyinfo->font_table
+         = (struct font_info *) xmalloc (dpyinfo->font_table_size
+                                         * sizeof (struct font_info));
+      }
+    /* Do we need to grow the table?  */
+    else if (dpyinfo->n_fonts
+            >= dpyinfo->font_table_size)
+      {
+       dpyinfo->font_table_size *= 2;
+       dpyinfo->font_table
+         = (struct font_info *) xrealloc (dpyinfo->font_table,
+                                          (dpyinfo->font_table_size
+                                           * sizeof (struct font_info)));
+      }
+
+    fontp = dpyinfo->font_table + dpyinfo->n_fonts;
+
+    /* Now fill in the slots of *FONTP.  */
+    BLOCK_INPUT;
+    fontp->font = font;
+    fontp->font_idx = dpyinfo->n_fonts;
+    fontp->name = (char *) xmalloc (strlen (fontname) + 1);
+    bcopy (fontname, fontp->name, strlen (fontname) + 1);
+
+    /* Try to get the full name of FONT.  Put it in FULL_NAME.  */
+    full_name = 0;
+    if (XGetFontProperty (font, XA_FONT, &value))
+      {
+       char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
+       char *p = name;
+       int dashes = 0;
+
+       /* Count the number of dashes in the "full name".
+          If it is too few, this isn't really the font's full name,
+          so don't use it.
+          In X11R4, the fonts did not come with their canonical names
+          stored in them.  */
+       while (*p)
+         {
+           if (*p == '-')
+             dashes++;
+           p++;
+         }
+
+       if (dashes >= 13)
+         {
+           full_name = (char *) xmalloc (p - name + 1);
+           bcopy (name, full_name, p - name + 1);
+         }
+
+       XFree (name);
+      }
+    
+    if (full_name != 0)
+      fontp->full_name = full_name;
+    else
+      fontp->full_name = fontp->name;
+
+    fontp->size = font->max_bounds.width;
+    fontp->height = font->ascent + font->descent;
+
+    /* The slot `encoding' specifies how to map a character
+       code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
+       the font code-points (0:0x20..0x7F, 1:0xA0..0xFF, 0:0x2020..0x7F7F,
+       the font code-points (0:0x20..0x7F, 1:0xA0..0xFF,
+       0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF, or
+       2:0xA020..0xFF7F).  For the moment, we don't know which charset
+       uses this font.  So, we set informatoin in fontp->encoding[1]
+       which is never used by any charset.  If mapping can't be
+       decided, set FONT_ENCODING_NOT_DECIDED.  */
+    fontp->encoding[1]
+      = (font->max_byte1 == 0
+        /* 1-byte font */
+        ? (font->min_char_or_byte2 < 0x80
+           ? (font->max_char_or_byte2 < 0x80
+              ? 0              /* 0x20..0x7F */
+              : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
+           : 1)                /* 0xA0..0xFF */
+        /* 2-byte font */
+        : (font->min_byte1 < 0x80
+           ? (font->max_byte1 < 0x80
+              ? (font->min_char_or_byte2 < 0x80
+                 ? (font->max_char_or_byte2 < 0x80
+                    ? 0                /* 0x2020..0x7F7F */
+                    : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
+                 : 3)          /* 0x20A0..0x7FFF */
+              : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
+           : (font->min_char_or_byte2 < 0x80
+              ? (font->max_char_or_byte2 < 0x80
+                 ? 2           /* 0xA020..0xFF7F */
+                 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
+              : 1)));          /* 0xA0A0..0xFFFF */
+
+    fontp->baseline_offset
+      = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
+        ? (long) value : 0);
+    fontp->relative_compose
+      = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
+        ? (long) value : 0);
+    fontp->default_ascent
+      = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
+        ? (long) value : 0);
+
+    UNBLOCK_INPUT;
+    dpyinfo->n_fonts++;
+
+    return fontp;
+  }
+}
+
+/* Return a pointer to struct font_info of a font named FONTNAME for frame F.
+   If no such font is loaded, return NULL.  */
+struct font_info *
+x_query_font (f, fontname)
+     struct frame *f;
+     register char *fontname;
+{
+  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  int i;
+
+  for (i = 0; i < dpyinfo->n_fonts; i++)
+    if (!strcmp (dpyinfo->font_table[i].name, fontname)
+       || !strcmp (dpyinfo->font_table[i].full_name, fontname))
+      return (dpyinfo->font_table + i);
+  return NULL;
+}
+
+\f
 /* Initialization.  */
 
 #ifdef USE_X_TOOLKIT
@@ -5862,7 +6669,10 @@ x_term_init (display_name, xrm_option, resource_name)
     }
 
 #ifdef HAVE_X_I18N
-  setlocale (LC_ALL, NULL);
+  setlocale (LC_ALL, "");
+  /* In case we just overrode what init_lread did, redo it.  */
+  setlocale (LC_NUMERIC, "C");
+  setlocale (LC_TIME, "C");
 #endif
 
 #ifdef USE_X_TOOLKIT
@@ -5892,6 +6702,7 @@ x_term_init (display_name, xrm_option, resource_name)
                         &argc, argv);
 
 #ifdef HAVE_X11XTR6
+    /* I think this is to compensate for XtSetLanguageProc.  */
     setlocale (LC_NUMERIC, "C");
     setlocale (LC_TIME, "C");
 #endif
@@ -6041,6 +6852,8 @@ x_term_init (display_name, xrm_option, resource_name)
     = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
   dpyinfo->Xatom_TEXT
     = XInternAtom (dpyinfo->display, "TEXT", False);
+  dpyinfo->Xatom_COMPOUND_TEXT
+    = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
   dpyinfo->Xatom_DELETE
     = XInternAtom (dpyinfo->display, "DELETE", False);
   dpyinfo->Xatom_MULTIPLE
@@ -6055,12 +6868,30 @@ x_term_init (display_name, xrm_option, resource_name)
     = XInternAtom (dpyinfo->display, "NULL", False);
   dpyinfo->Xatom_ATOM_PAIR
     = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
+  /* For properties of font.  */
+  dpyinfo->Xatom_PIXEL_SIZE
+    = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
+  dpyinfo->Xatom_MULE_BASELINE_OFFSET
+    = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
+  dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
+    = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
+  dpyinfo->Xatom_MULE_DEFAULT_ASCENT
+    = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
 
   dpyinfo->cut_buffers_initialized = 0;
 
   connection = ConnectionNumber (dpyinfo->display);
   dpyinfo->connection = connection;
 
+  {
+    char null_bits[] = { 0x00 };
+
+    dpyinfo->null_pixel
+      = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window, 
+                                    null_bits, 1, 1, (long) 0, (long) 0,
+                                    1);
+  }
+
 #ifdef subprocesses
   /* This is only needed for distinguishing keyboard and process input.  */
   if (connection != 0)
@@ -6083,6 +6914,31 @@ x_term_init (display_name, xrm_option, resource_name)
     init_sigio (connection);
 #endif /* ! defined (SIGIO) */
 
+#ifdef USE_LUCID
+  /* Make sure that we have a valid font for dialog boxes
+     so that Xt does not crash.  */
+  {
+    Display *dpy = dpyinfo->display;
+    XrmValue d, fr, to;
+    Font font;
+    int count;
+    
+    d.addr = (XPointer)&dpy;
+    d.size = sizeof (Display *);
+    fr.addr = XtDefaultFont;
+    fr.size = sizeof (XtDefaultFont);
+    to.size = sizeof (Font *);
+    to.addr = (XPointer)&font;
+    count = x_catch_errors (dpy);
+    if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
+      abort ();
+    if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
+      XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
+    x_uncatch_errors (dpy, count);
+  }
+#endif
+
+
   UNBLOCK_INPUT;
 
   return dpyinfo;
@@ -6194,7 +7050,7 @@ x_initialize ()
 
   /* Note that there is no real way portable across R3/R4 to get the
      original error handler.  */
-  XSetErrorHandler (x_error_quitter);
+  XSetErrorHandler (x_error_handler);
   XSetIOErrorHandler (x_io_error_quitter);
 
   /* Disable Window Change signals;  they are handled by X events. */
@@ -6208,6 +7064,9 @@ x_initialize ()
 void
 syms_of_xterm ()
 {
+  staticpro (&x_error_message_string);
+  x_error_message_string = Qnil;
+
   staticpro (&x_display_name_list);
   x_display_name_list = Qnil;
 
@@ -6216,5 +7075,9 @@ syms_of_xterm ()
 
   staticpro (&Qvendor_specific_keysyms);
   Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
+
+  staticpro (&last_mouse_press_frame);
+  last_mouse_press_frame = Qnil;
 }
-#endif /* ! defined (HAVE_X_WINDOWS) */
+
+#endif /* not HAVE_X_WINDOWS */