(x_destroy_window) [HAVE_X_I18N]: Free xic and xim of frame.
[bpt/emacs.git] / src / xterm.c
index 9755900..352fa42 100644 (file)
@@ -1,5 +1,5 @@
 /* X Communication module for terminals which understand the X protocol.
-   Copyright (C) 1989, 1993, 1994 Free Software Foundation, Inc.
+   Copyright (C) 1989, 93, 94, 95, 1996 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -15,7 +15,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 /* Xt features made by Fred Pierresteguy.  */
 
@@ -85,7 +86,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #ifdef USE_X_TOOLKIT
 extern void free_frame_menubar ();
+extern FRAME_PTR x_menubar_window_to_frame ();
+#if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
+#define HACK_EDITRES
 extern void _XEditResCheckMessages ();
+#endif /* not NO_EDITRES */
 #endif /* USE_X_TOOLKIT */
 
 #ifndef USE_X_TOOLKIT
@@ -94,13 +99,27 @@ extern void _XEditResCheckMessages ();
 #endif
 
 #ifdef USE_X_TOOLKIT
+#include "widget.h"
 #ifndef XtNinitialState
 #define XtNinitialState "initialState"
 #endif
 #endif
 
+#ifdef HAVE_X11XTR6
+/* So we can do setlocale.  */
+#include <locale.h>
+#endif
+
+#ifdef SOLARIS2
+#define X_CONNECTION_LOCK_FLAG XlibDisplayWriting
+#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;
@@ -118,32 +137,17 @@ Lisp_Object x_display_name_list;
    is the frame to apply to.  */
 extern struct frame *updating_frame;
 
-/* The frame (if any) which has the X window that has keyboard focus.
-   Zero if none.  This is examined by Ffocus_frame in frame.c.  Note
-   that a mere EnterNotify event can set this; if you need to know the
-   last frame specified in a FocusIn or FocusOut event, use
-   x_focus_event_frame.  */
-struct frame *x_focus_frame;
-
 /* This is a frame waiting to be autoraised, within XTread_socket.  */
 struct frame *pending_autoraise_frame;
 
-/* The last frame mentioned in a FocusIn or FocusOut event.  This is
-   separate from x_focus_frame, because whether or not LeaveNotify
-   events cause us to lose focus depends on whether or not we have
-   received a FocusIn event for it.  */
-struct frame *x_focus_event_frame;
-
-/* The frame which currently has the visual highlight, and should get
-   keyboard input (other sorts of input have the frame encoded in the
-   event).  It points to the X focus frame's selected window's
-   frame.  It differs from x_focus_frame when we're using a global
-   minibuffer.  */
-static struct frame *x_highlight_frame;
-
 #ifdef USE_X_TOOLKIT
 /* The application context for Xt use.  */
 XtAppContext Xt_app_con;
+
+static String Xt_default_resources[] =
+{
+  0
+};
 #endif
 
 /* During an update, maximum vpos for ins/del line operations to affect.  */
@@ -231,11 +235,14 @@ extern int errno;
 /* A mask of extra modifier bits to put into every keyboard char.  */
 extern int extra_keyboard_modifiers;
 
+static Lisp_Object Qvendor_specific_keysyms;
+
 extern XrmDatabase x_load_resources ();
 
+extern Lisp_Object x_icon_type ();
+
 void x_delete_display ();
 
-static void flashback ();
 static void redraw_previous_char ();
 static void redraw_following_char ();
 static unsigned int x_x_to_emacs_modifiers ();
@@ -249,6 +256,36 @@ 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 ();
+void x_uncatch_errors ();
+\f
+#if 0
+/* This is a function useful for recording debugging information
+   about the sequence of occurrences in this file.  */
+
+struct record 
+{
+  char *locus;
+  int type;
+};
+
+struct record event_record[100];
+
+int event_record_index;
+
+record_event (locus, type)
+     char *locus;
+     int type;
+{
+  if (event_record_index == sizeof (event_record) / sizeof (struct record))
+    event_record_index = 0;
+
+  event_record[event_record_index].locus = locus;
+  event_record[event_record_index].type = type;
+  event_record_index++;
+}
+
+#endif /* 0 */
 \f
 /* Return the struct x_display_info corresponding to DPY.  */
 
@@ -264,19 +301,6 @@ x_display_info_for_display (dpy)
 
   return 0;
 }
-
-#ifdef MULTI_PERDISPLAY
-/* Return the perdisplay struct corresponding to FRAME.  */
-#undef get_perdisplay
-
-PERDISPLAY *
-get_perdisplay(frame)
-     FRAME_PTR frame;
-{
-  return get_perdisplay_macro (frame);
-}
-#define get_perdisplay(frame) get_perdisplay_macro (frame)
-#endif
 \f
 /* Starting and ending updates.
 
@@ -379,6 +403,7 @@ static
 XTframe_up_to_date (f)
      FRAME_PTR f;
 {
+  BLOCK_INPUT;
   if (FRAME_X_DISPLAY_INFO (f)->mouse_face_deferred_gc
       || f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame)
     {
@@ -387,6 +412,7 @@ XTframe_up_to_date (f)
                            FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_y);
       FRAME_X_DISPLAY_INFO (f)->mouse_face_deferred_gc = 0;
     }
+  UNBLOCK_INPUT;
 }
 \f
 /* External interface to control of standout mode.
@@ -568,12 +594,12 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground)
            stippled = 0;
 
            if ((!face->font
-                || (int) face->font == FACE_DEFAULT
-                || face->font == f->display.x->font)
-               && face->background == f->display.x->background_pixel
-               && face->foreground == f->display.x->foreground_pixel)
+                || face->font == (XFontStruct *) FACE_DEFAULT
+                || face->font == f->output_data.x->font)
+               && face->background == f->output_data.x->background_pixel
+               && face->foreground == f->output_data.x->foreground_pixel)
              {
-               gc = f->display.x->cursor_gc;
+               gc = f->output_data.x->cursor_gc;
              }
            /* Cursor on non-default face: must merge.  */
            else
@@ -581,14 +607,14 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground)
                XGCValues xgcv;
                unsigned long mask;
 
-               xgcv.background = f->display.x->cursor_pixel;
+               xgcv.background = f->output_data.x->cursor_pixel;
                xgcv.foreground = face->background;
                /* If the glyph would be invisible,
                   try a different foreground.  */
                if (xgcv.foreground == xgcv.background)
                  xgcv.foreground = face->foreground;
                if (xgcv.foreground == xgcv.background)
-                 xgcv.foreground = f->display.x->cursor_foreground_pixel;
+                 xgcv.foreground = f->output_data.x->cursor_foreground_pixel;
                if (xgcv.foreground == xgcv.background)
                  xgcv.foreground = face->foreground;
                /* Make sure the cursor is distinct from text in this face.  */
@@ -618,8 +644,8 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground)
              }
          }
 
-       if ((int) font == FACE_DEFAULT)
-         font = f->display.x->font;
+       if (font == (XFontStruct *) FACE_DEFAULT)
+         font = f->output_data.x->font;
 
        if (just_foreground)
          XDrawString (FRAME_X_DISPLAY (f), window, gc,
@@ -649,13 +675,13 @@ dumpglyphs (f, left, top, gp, n, hl, just_foreground)
                                left, top + FONT_BASE (font), buf, len);
 
            /* Clear the rest of the line's height.  */
-           if (f->display.x->line_height != FONT_HEIGHT (font))
+           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->display.x->line_height - FONT_HEIGHT (font),
+                         f->output_data.x->line_height - FONT_HEIGHT (font),
                          False);
          }
 
@@ -710,9 +736,9 @@ dumpglyphs (f, left, top, gp, n, hl, font)
 {
   register int len;
   Window window = FRAME_X_WINDOW (f);
-  GC drawing_gc =   (hl == 2 ? f->display.x->cursor_gc
-                            : (hl ? f->display.x->reverse_gc
-                                  : f->display.x->normal_gc));
+  GC drawing_gc =   (hl == 2 ? f->output_data.x->cursor_gc
+                            : (hl ? f->output_data.x->reverse_gc
+                                  : f->output_data.x->normal_gc));
 
   if (sizeof (GLYPH) == sizeof (XChar2b))
     XDrawImageString16 (FRAME_X_DISPLAY (f), window, drawing_gc,
@@ -784,7 +810,7 @@ XTwrite_glyphs (start, len)
    to column FIRST_UNUSED (exclusive).  The idea is that everything
    from FIRST_UNUSED onward is already erased.  */
 
-static int
+static
 XTclear_end_of_line (first_unused)
      register int first_unused;
 {
@@ -815,8 +841,8 @@ XTclear_end_of_line (first_unused)
   XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
              CHAR_TO_PIXEL_COL (f, curs_x),
              CHAR_TO_PIXEL_ROW (f, curs_y),
-             FONT_WIDTH (f->display.x->font) * (first_unused - curs_x),
-             f->display.x->line_height, False);
+             FONT_WIDTH (f->output_data.x->font) * (first_unused - curs_x),
+             f->output_data.x->line_height, False);
 #if 0
   redraw_previous_char (f, curs_x, curs_y, highlight);
 #endif
@@ -882,8 +908,8 @@ redraw_previous_char (f, x, y, highlight_flag)
       XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                  CHAR_TO_PIXEL_COL (f, x - 1),
                  CHAR_TO_PIXEL_ROW (f, y),
-                 FONT_WIDTH (f->display.x->font),
-                 f->display.x->line_height, False);
+                 FONT_WIDTH (f->output_data.x->font),
+                 f->output_data.x->line_height, False);
 
       dumpglyphs (f, CHAR_TO_PIXEL_COL (f, start_x),
                  CHAR_TO_PIXEL_ROW (f, y),
@@ -918,8 +944,8 @@ redraw_following_char (f, x, y, highlight_flag)
       XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                  CHAR_TO_PIXEL_COL (f, x),
                  CHAR_TO_PIXEL_ROW (f, y),
-                 FONT_WIDTH (f->display.x->font),
-                 f->display.x->line_height, False);
+                 FONT_WIDTH (f->output_data.x->font),
+                 f->output_data.x->line_height, False);
 
       dumpglyphs (f, CHAR_TO_PIXEL_COL (f, x),
                  CHAR_TO_PIXEL_ROW (f, y),
@@ -958,7 +984,7 @@ font_char_overlap_left (font, c)
        {
          /* If char is out of range, try the font's default char instead.  */
          c = font->default_char;
-         row = c >> (INTBITS - 8);
+         row = c >> (BITS_PER_INT - 8);
          within = c & 0177;
        }
       if (!(within >= font->min_char_or_byte2
@@ -1003,7 +1029,7 @@ font_char_overlap_right (font, c)
        {
          /* If char is out of range, try the font's default char instead.  */
          c = font->default_char;
-         row = c >> (INTBITS - 8);
+         row = c >> (BITS_PER_INT - 8);
          within = c & 0177;
        }
       if (!(within >= font->min_char_or_byte2
@@ -1074,8 +1100,8 @@ XTflash (f)
       XGCValues values;
 
       values.function = GXxor;
-      values.foreground = (f->display.x->foreground_pixel
-                          ^ f->display.x->background_pixel);
+      values.foreground = (f->output_data.x->foreground_pixel
+                          ^ f->output_data.x->background_pixel);
 
       gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                      GCFunction | GCForeground, &values);
@@ -1112,7 +1138,7 @@ XTflash (f)
              break;
 
            /* Try to wait that long--but we might wake up sooner.  */
-           select (0, 0, 0, 0, &timeout);
+           select (0, NULL, NULL, NULL, &timeout);
          }
       }
 
@@ -1268,7 +1294,7 @@ do_line_dance ()
     abort ();
 
   ht = f->height;
-  intborder = f->display.x->internal_border_width;
+  intborder = f->output_data.x->internal_border_width;
 
   x_display_cursor (updating_frame, 0);
 
@@ -1279,10 +1305,10 @@ do_line_dance ()
                     && line_dance[j]-j == distance); ++j);
        /* Copy [i,j) upward from [i+distance,j+distance) */
        XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                  FRAME_X_WINDOW (f), f->display.x->normal_gc,
+                  FRAME_X_WINDOW (f), f->output_data.x->normal_gc,
                   intborder, CHAR_TO_PIXEL_ROW (f, i+distance),
-                  f->width * FONT_WIDTH (f->display.x->font),
-                  (j-i) * f->display.x->line_height,
+                  f->width * 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;
       }
@@ -1294,10 +1320,10 @@ do_line_dance ()
                     && line_dance[j]-j == distance););
        /* Copy (j,i] downward from (j+distance, i+distance] */
        XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                  FRAME_X_WINDOW (f), f->display.x->normal_gc,
+                  FRAME_X_WINDOW (f), f->output_data.x->normal_gc,
                   intborder, CHAR_TO_PIXEL_ROW (f, j+1+distance),
-                  f->width * FONT_WIDTH (f->display.x->font),
-                  (i-j) * f->display.x->line_height,
+                  f->width * 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;
       }
@@ -1309,8 +1335,8 @@ 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->display.x->font),
-                   (j-i) * f->display.x->line_height, False);
+                   f->width * FONT_WIDTH (f->output_data.x->font),
+                   (j-i) * f->output_data.x->line_height, False);
        i = j-1;
       }
   line_dance_in_progress = 0;
@@ -1346,8 +1372,8 @@ dumprectangle (f, left, top, cols, rows)
      Round down for left and top, up for right and bottom.  */
   top  = PIXEL_TO_CHAR_ROW (f, top);
   left = PIXEL_TO_CHAR_COL (f, left);
-  bottom += (f->display.x->line_height - 1);
-  right += (FONT_WIDTH (f->display.x->font) - 1);
+  bottom += (f->output_data.x->line_height - 1);
+  right += (FONT_WIDTH (f->output_data.x->font) - 1);
   bottom = PIXEL_TO_CHAR_ROW (f, bottom);
   right = PIXEL_TO_CHAR_COL (f, right);
 
@@ -1410,9 +1436,9 @@ frame_highlight (f)
      client", so we can always change it to whatever we want.  */
   BLOCK_INPUT;
   XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                   f->display.x->border_pixel);
+                   f->output_data.x->border_pixel);
   UNBLOCK_INPUT;
-  x_display_cursor (f, 1);
+  x_update_cursor (f, 1);
 }
 
 static void
@@ -1425,12 +1451,13 @@ frame_unhighlight (f)
      client", so we can always change it to whatever we want.  */
   BLOCK_INPUT;
   XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                         f->display.x->border_tile);
+                         f->output_data.x->border_tile);
   UNBLOCK_INPUT;
-  x_display_cursor (f, 1);
+  x_update_cursor (f, 1);
 }
 
 static void XTframe_rehighlight ();
+static void x_frame_rehighlight ();
 
 /* The focus has changed.  Update the frames as necessary to reflect
    the new situation.  Note that we can't change the selected frame
@@ -1439,17 +1466,18 @@ static void XTframe_rehighlight ();
    Lisp code can tell when the switch took place by examining the events.  */
 
 static void
-x_new_focus_frame (frame)
+x_new_focus_frame (dpyinfo, frame)
+     struct x_display_info *dpyinfo;
      struct frame *frame;
 {
-  struct frame *old_focus = x_focus_frame;
+  struct frame *old_focus = dpyinfo->x_focus_frame;
   int events_enqueued = 0;
 
-  if (frame != x_focus_frame)
+  if (frame != dpyinfo->x_focus_frame)
     {
       /* Set this before calling other routines, so that they see
         the correct value of x_focus_frame.  */
-      x_focus_frame = frame;
+      dpyinfo->x_focus_frame = frame;
 
       if (old_focus && old_focus->auto_lower)
        x_lower_frame (old_focus);
@@ -1462,55 +1490,65 @@ x_new_focus_frame (frame)
       choose_minibuf_frame ();
 #endif /* ! 0 */
 
-      if (x_focus_frame && x_focus_frame->auto_raise)
-       pending_autoraise_frame = x_focus_frame;
+      if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
+       pending_autoraise_frame = dpyinfo->x_focus_frame;
       else
        pending_autoraise_frame = 0;
     }
 
-  XTframe_rehighlight ();
+  x_frame_rehighlight (dpyinfo);
 }
 
 /* Handle an event saying the mouse has moved out of an Emacs frame.  */
 
 void
-x_mouse_leave ()
+x_mouse_leave (dpyinfo)
+     struct x_display_info *dpyinfo;
 {
-  if (! x_focus_event_frame)
-    x_new_focus_frame (NULL);
-  else
-    x_new_focus_frame (x_focus_event_frame);  /* Was f, but that seems wrong.  */
+  x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
 }
 
 /* The focus has changed, or we have redirected a frame's focus to
    another frame (this happens when a frame uses a surrogate
-   minibuffer frame).  Shift the highlight as appropriate.  */
+   minibuffer frame).  Shift the highlight as appropriate.
+
+   The FRAME argument doesn't necessarily have anything to do with which
+   frame is being highlighted or unhighlighted; we only use it to find
+   the appropriate X display info.  */
+static void
+XTframe_rehighlight (frame)
+     struct frame *frame;
+{
+  x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
+}
+
 static void
-XTframe_rehighlight ()
+x_frame_rehighlight (dpyinfo)
+     struct x_display_info *dpyinfo;
 {
-  struct frame *old_highlight = x_highlight_frame;
+  struct frame *old_highlight = dpyinfo->x_highlight_frame;
 
-  if (x_focus_frame)
+  if (dpyinfo->x_focus_frame)
     {
-      x_highlight_frame
-       = ((GC_FRAMEP (FRAME_FOCUS_FRAME (x_focus_frame)))
-          ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame))
-          : x_focus_frame);
-      if (! FRAME_LIVE_P (x_highlight_frame))
+      dpyinfo->x_highlight_frame
+       = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
+          ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
+          : dpyinfo->x_focus_frame);
+      if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
        {
-         FRAME_FOCUS_FRAME (x_focus_frame) = Qnil;
-         x_highlight_frame = x_focus_frame;
+         FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
+         dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
        }
     }
   else
-    x_highlight_frame = 0;
+    dpyinfo->x_highlight_frame = 0;
 
-  if (x_highlight_frame != old_highlight)
+  if (dpyinfo->x_highlight_frame != old_highlight)
     {
       if (old_highlight)
        frame_unhighlight (old_highlight);
-      if (x_highlight_frame)
-       frame_highlight (x_highlight_frame);
+      if (dpyinfo->x_highlight_frame)
+       frame_highlight (dpyinfo->x_highlight_frame);
     }
 }
 \f
@@ -1535,8 +1573,8 @@ x_find_modifier_meanings (dpyinfo)
 #ifdef HAVE_X11R4
   XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
 #else
-  min_code = display->min_keycode;
-  max_code = display->max_keycode;
+  min_code = dpyinfo->display->min_keycode;
+  max_code = dpyinfo->display->max_keycode;
 #endif
 
   syms = XGetKeyboardMapping (dpyinfo->display,
@@ -1645,6 +1683,21 @@ x_emacs_to_x_modifiers (dpyinfo, state)
          | ((state & ctrl_modifier)    ? ControlMask      : 0)
          | ((state & meta_modifier)    ? dpyinfo->meta_mod_mask  : 0));
 }
+
+/* Convert a keysym to its name.  */
+
+char *
+x_get_keysym_name (keysym)
+     KeySym keysym;
+{
+  char *value;
+
+  BLOCK_INPUT;
+  value = XKeysymToString (keysym);
+  UNBLOCK_INPUT;
+
+  return value;
+}
 \f
 /* Mouse clicks and mouse movement.  Rah.  */
 
@@ -1664,17 +1717,17 @@ pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
   /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
      even for negative values.  */
   if (pix_x < 0)
-    pix_x -= FONT_WIDTH ((f)->display.x->font) - 1;
+    pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
   if (pix_y < 0)
-    pix_y -= (f)->display.x->line_height - 1;
+    pix_y -= (f)->output_data.x->line_height - 1;
 
   pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
   pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
 
   if (bounds)
     {
-      bounds->width  = FONT_WIDTH  (f->display.x->font);
-      bounds->height = f->display.x->line_height;
+      bounds->width  = FONT_WIDTH  (f->output_data.x->font);
+      bounds->height = f->output_data.x->line_height;
       bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
       bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
     }
@@ -1778,13 +1831,12 @@ static void
 note_mouse_movement (frame, event)
      FRAME_PTR frame;
      XMotionEvent *event;
-
 {
   last_mouse_movement_time = event->time;
 
   if (event->window != FRAME_X_WINDOW (frame))
     {
-      mouse_moved = 1;
+      frame->mouse_moved = 1;
       last_mouse_scroll_bar = Qnil;
 
       note_mouse_highlight (frame, -1, -1);
@@ -1807,7 +1859,7 @@ note_mouse_movement (frame, event)
           || event->y < last_mouse_glyph.y
           || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
     {
-      mouse_moved = 1;
+      frame->mouse_moved = 1;
       last_mouse_scroll_bar = Qnil;
 
       note_mouse_highlight (frame, event->x, event->y);
@@ -1849,6 +1901,7 @@ static int disable_mouse_highlight;
 static void
 note_mouse_highlight (f, x, y)
      FRAME_PTR f;
+     int x, y;
 {
   int row, column, portion;
   XRectangle new_glyph;
@@ -2140,8 +2193,8 @@ show_mouse_face (dpyinfo, hl)
       /* If the cursor's in the text we are about to rewrite,
         turn the cursor off.  */
       if (i == curs_y
-         && curs_x >= FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col - 1
-         && curs_x <= FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col)
+         && curs_x >= column - 1
+         && curs_x <= endcolumn)
        {
          x_display_cursor (f, 0);
          cursor_off = 1;
@@ -2166,10 +2219,10 @@ show_mouse_face (dpyinfo, hl)
   /* Change the mouse cursor according to the value of HL.  */
   if (hl > 0)
     XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                  f->display.x->cross_cursor);
+                  f->output_data.x->cross_cursor);
   else
     XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                  f->display.x->text_cursor);
+                  f->output_data.x->text_cursor);
 }
 
 /* Clear out the mouse-highlighted active region.
@@ -2191,13 +2244,14 @@ static struct scroll_bar *x_window_to_scroll_bar ();
 static void x_scroll_bar_report_motion ();
 
 /* Return the current position of the mouse.
+   *fp should be a frame which indicates which display to ask about.
 
-   If the mouse movement started in a scroll bar, set *f, *bar_window,
+   If the mouse movement started in a scroll bar, set *fp, *bar_window,
    and *part to the frame, window, and scroll bar part that the mouse
    is over.  Set *x and *y to the portion and whole of the mouse's
    position on the scroll bar.
 
-   If the mouse movement started elsewhere, set *f to the frame the
+   If the mouse movement started elsewhere, set *fp to the frame the
    mouse is on, *bar_window to nil, and *x and *y to the character cell
    the mouse is over.
 
@@ -2212,8 +2266,9 @@ static void x_scroll_bar_report_motion ();
    again. */
 
 static void
-XTmouse_position (fp, bar_window, part, x, y, time)
+XTmouse_position (fp, insist, bar_window, part, x, y, time)
      FRAME_PTR *fp;
+     int insist;
      Lisp_Object *bar_window;
      enum scroll_bar_part *part;
      Lisp_Object *x, *y;
@@ -2233,7 +2288,13 @@ XTmouse_position (fp, bar_window, part, x, y, time)
       Window dummy_window;
       int dummy;
 
-      mouse_moved = 0;
+      Lisp_Object frame, tail;
+
+      /* Clear the mouse-moved flag for every frame on this display.  */
+      FOR_EACH_FRAME (tail, frame)
+       if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
+         XFRAME (frame)->mouse_moved = 0;
+
       last_mouse_scroll_bar = Qnil;
 
       /* Figure out which root window we're on.  */
@@ -2266,6 +2327,12 @@ XTmouse_position (fp, bar_window, part, x, y, time)
 
        win = root;
 
+       /* XTranslateCoordinates can get errors if the window
+          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));
+
        if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
            && FRAME_LIVE_P (last_mouse_frame))
          {
@@ -2298,7 +2365,7 @@ XTmouse_position (fp, bar_window, part, x, y, time)
                                       /* Child of win.  */
                                       &child);
 
-               if (child == None)
+               if (child == None || child == win)
                  break;
 
                win = child;
@@ -2318,9 +2385,14 @@ XTmouse_position (fp, bar_window, part, x, y, time)
               never use them in that case.)  */
 
            /* Is win one of our frames?  */
-           f1 = x_any_window_to_frame (win);
+           f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
          }
 
+       if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
+         f1 = 0;
+
+       x_uncatch_errors (FRAME_X_DISPLAY (*fp));
+
        /* If not, is it one of our scroll bars?  */
        if (! f1)
          {
@@ -2334,6 +2406,9 @@ XTmouse_position (fp, bar_window, part, x, y, time)
              }
          }
 
+       if (f1 == 0 && insist)
+         f1 = selected_frame;
+
        if (f1)
          {
            int ignore1, ignore2;
@@ -2342,7 +2417,8 @@ XTmouse_position (fp, bar_window, part, x, y, time)
 
            pixel_to_glyph_coords (f1, win_x, win_y, &ignore1, &ignore2,
                                   &last_mouse_glyph,
-                                  FRAME_X_DISPLAY_INFO (f1)->grabbed);
+                                  FRAME_X_DISPLAY_INFO (f1)->grabbed
+                                  || insist);
 
            *bar_window = Qnil;
            *part = 0;
@@ -2412,7 +2488,7 @@ x_scroll_bar_create (window, top, left, width, height)
   {
     XSetWindowAttributes a;
     unsigned long mask;
-    a.background_pixel = f->display.x->background_pixel;
+    a.background_pixel = f->output_data.x->background_pixel;
     a.event_mask = (ButtonPressMask | ButtonReleaseMask
                    | ButtonMotionMask | PointerMotionHintMask
                    | ExposureMask);
@@ -2430,7 +2506,7 @@ x_scroll_bar_create (window, top, left, width, height)
     XtSetArg (al[ac], XtNborderWidth, 0); ac++;
     sb_widget = XtCreateManagedWidget ("box",
                                       boxWidgetClass,
-                                      f->display.x->edit_widget, al, ac);
+                                      f->output_data.x->edit_widget, al, ac);
     SET_SCROLL_BAR_X_WINDOW
       (bar, sb_widget->core.window);
 #endif
@@ -2491,7 +2567,7 @@ x_scroll_bar_set_handle (bar, start, end, rebuild)
   int dragging = ! NILP (bar->dragging);
   Window w = SCROLL_BAR_X_WINDOW (bar);
   FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
-  GC gc = f->display.x->normal_gc;
+  GC gc = f->output_data.x->normal_gc;
 
   /* If the display is already accurate, do nothing.  */
   if (! rebuild
@@ -2650,7 +2726,7 @@ XTset_vertical_scroll_bar (window, portion, whole, position)
   int pixel_width
     = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
        ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
-       : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->display.x->font)));
+       : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
   int pixel_height = VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f, height);
 
   struct scroll_bar *bar;
@@ -2703,15 +2779,18 @@ static void
 XTcondemn_scroll_bars (frame)
      FRAME_PTR frame;
 {
-  /* The condemned list should be empty at this point; if it's not,
-     then the rest of Emacs isn't using the condemn/redeem/judge
-     protocol correctly.  */
-  if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
-    abort ();
-
-  /* Move them all to the "condemned" list.  */
-  FRAME_CONDEMNED_SCROLL_BARS (frame) = FRAME_SCROLL_BARS (frame);
-  FRAME_SCROLL_BARS (frame) = Qnil;
+  /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS.  */
+  while (! NILP (FRAME_SCROLL_BARS (frame)))
+    {
+      Lisp_Object bar;
+      bar = FRAME_SCROLL_BARS (frame);
+      FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
+      XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
+      XSCROLL_BAR (bar)->prev = Qnil;
+      if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
+       XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
+      FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
+    }
 }
 
 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
@@ -2801,7 +2880,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->display.x->normal_gc;
+  GC gc = f->output_data.x->normal_gc;
 
   BLOCK_INPUT;
 
@@ -2905,9 +2984,11 @@ x_scroll_bar_note_movement (bar, event)
      struct scroll_bar *bar;
      XEvent *event;
 {
+  FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
+
   last_mouse_movement_time = event->xmotion.time;
 
-  mouse_moved = 1;
+  f->mouse_moved = 1;
   XSETVECTOR (last_mouse_scroll_bar, bar);
 
   /* If we're dragging the bar, display it.  */
@@ -3003,7 +3084,7 @@ x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
       XSETINT (*x, win_y);
       XSETINT (*y, top_range);
 
-      mouse_moved = 0;
+      f->mouse_moved = 0;
       last_mouse_scroll_bar = Qnil;
     }
 
@@ -3030,7 +3111,7 @@ x_scroll_bar_clear (f)
 }
 
 /* This processes Expose events from the menubar specific X event
-   loop in menubar.c.  This allows to redisplay the frame if necessary
+   loop in xmenu.c.  This allows to redisplay the frame if necessary
    when handling menubar or popup items.  */
 
 void
@@ -3038,10 +3119,12 @@ process_expose_from_menu (event)
      XEvent event;
 {
   FRAME_PTR f;
+  struct x_display_info *dpyinfo;
 
   BLOCK_INPUT;
 
-  f = x_window_to_frame (event.xexpose.window);
+  dpyinfo = x_display_info_for_display (event.xexpose.display);
+  f = x_window_to_frame (dpyinfo, event.xexpose.window);
   if (f)
     {
       if (f->async_visible == 0)
@@ -3052,7 +3135,7 @@ process_expose_from_menu (event)
        }
       else
        {
-         dumprectangle (x_window_to_frame (event.xexpose.window),
+         dumprectangle (x_window_to_frame (dpyinfo, event.xexpose.window),
                         event.xexpose.x, event.xexpose.y,
                         event.xexpose.width, event.xexpose.height);
        }
@@ -3153,13 +3236,19 @@ static XComposeStatus compose_status;
 
 /* Record the last 100 characters stored
    to help debug the loss-of-chars-during-GC problem.  */
-int temp_index;
-short temp_buffer[100];
+static int temp_index;
+static short temp_buffer[100];
 
 /* Set this to nonzero to fake an "X I/O error"
    on a particular display.  */
 struct x_display_info *XTread_socket_fake_io_error;
 
+/* When we find no input here, we occasionally do a no-op command
+   to verify that the X server is still running and we can still talk with it.
+   We try all the open displays, one by one.
+   This variable is used for cycling thru the displays.  */
+static struct x_display_info *next_noop_dpyinfo;
+
 /* 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.
@@ -3190,6 +3279,9 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
   int prefix;
   Lisp_Object part;
   struct x_display_info *dpyinfo;
+#ifdef HAVE_X_I18N
+  Status status_return;
+#endif
 
   if (interrupt_input_blocked)
     {
@@ -3214,7 +3306,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
 #ifdef FIOSNBIO
       /* If available, Xlib uses FIOSNBIO to make the socket
         non-blocking, and then looks for EWOULDBLOCK.  If O_NDELAY is set,
-        FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
+        FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
         a read returns 0, which Xlib interprets as equivalent to EPIPE. */
       fcntl (dpyinfo->connection, F_SETFL, 0);
 #endif /* ! defined (FIOSNBIO) */
@@ -3260,10 +3352,15 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                    if (event.xclient.data.l[0]
                        == dpyinfo->Xatom_wm_take_focus)
                      {
-                       f = x_window_to_frame (event.xclient.window);
+                       f = x_window_to_frame (dpyinfo, event.xclient.window);
                        /* Since we set WM_TAKE_FOCUS, we must call
                           XSetInputFocus explicitly.  But not if f is null,
                           since that might be an event for a deleted frame.  */
+#ifdef HAVE_X_I18N
+                       /* Not quite sure this is needed -pd */
+                       if (f)
+                         XSetICFocus (FRAME_XIC (f));
+#endif
                        if (f)
                          XSetInputFocus (event.xclient.display,
                                          event.xclient.window,
@@ -3281,7 +3378,8 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                           a keyboard or mouse event arrives. */
                        if (numchars > 0)
                          {
-                           f = x_top_window_to_frame (event.xclient.window);
+                           f = x_top_window_to_frame (dpyinfo,
+                                                      event.xclient.window);
 
                            /* This is just so we only give real data once
                               for a single Emacs process.  */
@@ -3298,7 +3396,9 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                    else if (event.xclient.data.l[0]
                             == dpyinfo->Xatom_wm_delete_window)
                      {
-                       struct frame *f = x_any_window_to_frame (event.xclient.window);
+                       struct frame *f
+                         = x_any_window_to_frame (dpyinfo,
+                                                  event.xclient.window);
 
                        if (f)
                          {
@@ -3322,31 +3422,34 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                         == dpyinfo->Xatom_wm_window_moved)
                  {
                    int new_x, new_y;
-                   struct frame *f = x_window_to_frame (event.xclient.window);
+                   struct frame *f
+                     = x_window_to_frame (dpyinfo, event.xclient.window);
 
                    new_x = event.xclient.data.s[0];
                    new_y = event.xclient.data.s[1];
 
                    if (f)
                      {
-                       f->display.x->left_pos = new_x;
-                       f->display.x->top_pos = new_y;
+                       f->output_data.x->left_pos = new_x;
+                       f->output_data.x->top_pos = new_y;
                      }
                  }
-#if defined (USE_X_TOOLKIT) && defined (HAVE_X11R5)
+#ifdef HACK_EDITRES
                else if (event.xclient.message_type
                         == dpyinfo->Xatom_editres)
                  {
-                   struct frame *f = x_any_window_to_frame (event.xclient.window);
-                   _XEditResCheckMessages (f->display.x->widget, NULL, &event, NULL);
+                   struct frame *f
+                     = x_any_window_to_frame (dpyinfo, event.xclient.window);
+                   _XEditResCheckMessages (f->output_data.x->widget, NULL,
+                                           &event, NULL);
                  }
-#endif /* USE_X_TOOLKIT and HAVE_X11R5 */
+#endif /* HACK_EDITRES */
              }
              break;
 
            case SelectionNotify:
 #ifdef USE_X_TOOLKIT
-             if (! x_window_to_frame (event.xselection.requestor))
+             if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
                goto OTHER;
 #endif /* not USE_X_TOOLKIT */
              x_handle_selection_notify (&event);
@@ -3354,7 +3457,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
 
            case SelectionClear:        /* Someone has grabbed ownership. */
 #ifdef USE_X_TOOLKIT
-             if (! x_window_to_frame (event.xselectionclear.window))
+             if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
                goto OTHER;
 #endif /* USE_X_TOOLKIT */
              {
@@ -3367,6 +3470,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
                SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
                SELECTION_EVENT_TIME (bufp) = eventp->time;
+               bufp->frame_or_window = Qnil;
                bufp++;
 
                count += 1;
@@ -3376,11 +3480,11 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
 
            case SelectionRequest:      /* Someone wants our selection. */
 #ifdef USE_X_TOOLKIT
-             if (!x_window_to_frame (event.xselectionrequest.owner))
+             if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
                goto OTHER;
 #endif /* USE_X_TOOLKIT */
              if (x_queue_selection_requests)
-               x_queue_event (x_window_to_frame (event.xselectionrequest.owner),
+               x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
                               &event);
              else
                {
@@ -3396,6 +3500,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                  SELECTION_EVENT_TARGET (bufp) = eventp->target;
                  SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
                  SELECTION_EVENT_TIME (bufp) = eventp->time;
+                 bufp->frame_or_window = Qnil;
                  bufp++;
 
                  count += 1;
@@ -3405,26 +3510,26 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
 
            case PropertyNotify:
 #ifdef USE_X_TOOLKIT
-             if (!x_any_window_to_frame (event.xproperty.window))
+             if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
                goto OTHER;
 #endif /* not USE_X_TOOLKIT */
              x_handle_property_notify (&event);
              break;
 
            case ReparentNotify:
-             f = x_top_window_to_frame (event.xreparent.window);
+             f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
              if (f)
                {
                  int x, y;
-                 f->display.x->parent_desc = event.xreparent.parent;
+                 f->output_data.x->parent_desc = event.xreparent.parent;
                  x_real_positions (f, &x, &y);
-                 f->display.x->left_pos = x;
-                 f->display.x->top_pos = y;
+                 f->output_data.x->left_pos = x;
+                 f->output_data.x->top_pos = y;
                }
              break;
 
            case Expose:
-             f = x_window_to_frame (event.xexpose.window);
+             f = x_window_to_frame (dpyinfo, event.xexpose.window);
              if (f)
                {
                  if (f->async_visible == 0)
@@ -3434,7 +3539,8 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                      SET_FRAME_GARBAGED (f);
                    }
                  else
-                   dumprectangle (x_window_to_frame (event.xexpose.window),
+                   dumprectangle (x_window_to_frame (dpyinfo,
+                                                     event.xexpose.window),
                                   event.xexpose.x, event.xexpose.y,
                                   event.xexpose.width, event.xexpose.height);
                }
@@ -3455,7 +3561,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
            case GraphicsExpose:        /* This occurs when an XCopyArea's
                                      source area was obscured or not
                                      available.*/
-             f = x_window_to_frame (event.xgraphicsexpose.drawable);
+             f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
              if (f)
                {
                  dumprectangle (f,
@@ -3475,7 +3581,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
              break;
 
            case UnmapNotify:
-             f = x_any_window_to_frame (event.xunmap.window);
+             f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
              if (f)            /* F may no longer exist if
                                       the frame was deleted.  */
                {
@@ -3496,15 +3602,12 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                  count++;
                  numchars--;
                }
-#ifdef USE_X_TOOLKIT
              goto OTHER;
-#endif /* USE_X_TOOLKIT */
-             break;
 
            case MapNotify:
              /* We use x_top_window_to_frame because map events can come
                 for subwindows and they don't mean that the frame is visible.  */
-             f = x_top_window_to_frame (event.xmap.window);
+             f = x_top_window_to_frame (dpyinfo, event.xmap.window);
              if (f)
                {
                  f->async_visible = 1;
@@ -3514,23 +3617,28 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                     the frame's display structures.  */
                  SET_FRAME_GARBAGED (f);
 
-                 bufp->kind = deiconify_event;
-                 XSETFRAME (bufp->frame_or_window, f);
-                 bufp++;
-                 count++;
-                 numchars--;
+                 if (f->iconified)
+                   {
+                     bufp->kind = deiconify_event;
+                     XSETFRAME (bufp->frame_or_window, f);
+                     bufp++;
+                     count++;
+                     numchars--;
+                   }
+                 else
+                   /* Force a redisplay sooner or later
+                      to update the frame titles
+                      in case this is the second frame.  */
+                   record_asynch_buffer_change ();
                }
-#ifdef USE_X_TOOLKIT
              goto OTHER;
-#endif /* USE_X_TOOLKIT */
-             break;
 
              /* Turn off processing if we become fully obscured. */
            case VisibilityNotify:
              break;
 
            case KeyPress:
-             f = x_any_window_to_frame (event.xkey.window);
+             f = x_any_window_to_frame (dpyinfo, event.xkey.window);
 
              if (f != 0)
                {
@@ -3550,8 +3658,30 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                  /* make_lispy_event turns chars into control chars.
                     Don't do it here because XLookupString is too eager.  */
                  event.xkey.state &= ~ControlMask;
+                 event.xkey.state &= ~(dpyinfo->meta_mod_mask
+                                       | dpyinfo->super_mod_mask
+                                       | dpyinfo->hyper_mod_mask
+                                       | dpyinfo->alt_mod_mask);
+
+#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,
+                                               &status_return);
+                   }
+                 else
+                   nbytes = XLookupString (&event.xkey, copy_buffer,
+                                           80, &keysym, &compose_status);
+#else
                  nbytes = XLookupString (&event.xkey, copy_buffer,
                                          80, &keysym, &compose_status);
+#endif
 
                  orig_keysym = keysym;
 
@@ -3665,7 +3795,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                  else
                    abort ();
                }
-             break;
+             goto OTHER;
 
              /* Here's a possible interpretation of the whole
                 FocusIn-EnterNotify FocusOut-LeaveNotify mess.  If you get a
@@ -3674,7 +3804,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                 then a mere LeaveNotify is enough to free you.  */
 
            case EnterNotify:
-             f = x_any_window_to_frame (event.xcrossing.window);
+             f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
 
              if (event.xcrossing.focus)                /* Entered Window */
                {
@@ -3683,35 +3813,34 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                            || !(f->auto_lower)
                            || (event.xcrossing.time - enter_timestamp) > 500))
                    {
-                     x_new_focus_frame (f);
+                     x_new_focus_frame (dpyinfo, f);
                      enter_timestamp = event.xcrossing.time;
                    }
                }
-             else if (f == x_focus_frame)
-               x_new_focus_frame (0);
+             else if (f == dpyinfo->x_focus_frame)
+               x_new_focus_frame (dpyinfo, 0);
              /* EnterNotify counts as mouse movement,
                 so update things that depend on mouse position.  */
              if (f)
                note_mouse_movement (f, &event.xmotion);
-#ifdef USE_X_TOOLKIT
              goto OTHER;
-#endif /* USE_X_TOOLKIT */
-             break;
 
            case FocusIn:
-             f = x_any_window_to_frame (event.xfocus.window);
+             f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
              if (event.xfocus.detail != NotifyPointer)
-               x_focus_event_frame = f;
+               dpyinfo->x_focus_event_frame = f;
              if (f)
-               x_new_focus_frame (f);
-#ifdef USE_X_TOOLKIT
-             goto OTHER;
-#endif /* USE_X_TOOLKIT */
-             break;
+               x_new_focus_frame (dpyinfo, f);
+
+#ifdef HAVE_X_I18N
+             if (f && FRAME_XIC (f))
+               XSetICFocus (FRAME_XIC (f));
+#endif
 
+             goto OTHER;
 
            case LeaveNotify:
-             f = x_top_window_to_frame (event.xcrossing.window);
+             f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
              if (f)
                {
                  if (f == dpyinfo->mouse_face_mouse_frame)
@@ -3720,31 +3849,31 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                    clear_mouse_face (dpyinfo);
 
                  if (event.xcrossing.focus)
-                   x_mouse_leave ();
+                   x_mouse_leave (dpyinfo);
                  else
                    {
-                     if (f == x_focus_event_frame)
-                       x_focus_event_frame = 0;
-                     if (f == x_focus_frame)
-                       x_new_focus_frame (0);
+                     if (f == dpyinfo->x_focus_event_frame)
+                       dpyinfo->x_focus_event_frame = 0;
+                     if (f == dpyinfo->x_focus_frame)
+                       x_new_focus_frame (dpyinfo, 0);
                    }
                }
-#ifdef USE_X_TOOLKIT
              goto OTHER;
-#endif /* USE_X_TOOLKIT */
-             break;
 
            case FocusOut:
-             f = x_any_window_to_frame (event.xfocus.window);
+             f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
              if (event.xfocus.detail != NotifyPointer
-                 && f == x_focus_event_frame)
-               x_focus_event_frame = 0;
-             if (f && f == x_focus_frame)
-               x_new_focus_frame (0);
-#ifdef USE_X_TOOLKIT
+                 && f == dpyinfo->x_focus_event_frame)
+               dpyinfo->x_focus_event_frame = 0;
+             if (f && f == dpyinfo->x_focus_frame)
+               x_new_focus_frame (dpyinfo, 0);
+
+#ifdef HAVE_X_I18N
+             if (f && FRAME_XIC (f))
+               XUnsetICFocus (FRAME_XIC (f));
+#endif
+
              goto OTHER;
-#endif /* USE_X_TOOLKIT */
-             break;
 
            case MotionNotify:
              {
@@ -3752,7 +3881,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                    && FRAME_LIVE_P (last_mouse_frame))
                  f = last_mouse_frame;
                else
-                 f = x_window_to_frame (event.xmotion.window);
+                 f = x_window_to_frame (dpyinfo, event.xmotion.window);
                if (f)
                  note_mouse_movement (f, &event.xmotion);
                else
@@ -3768,67 +3897,21 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                    clear_mouse_face (dpyinfo);
                  }
              }
-#if 0 /* This should be unnecessary, since the toolkit has no use
-            for motion events that happen outside of the menu event loop,
-            and it seems to cause the bug that mouse events stop coming
-            after a while.  */
-#ifdef USE_X_TOOLKIT
              goto OTHER;
-#endif /* USE_X_TOOLKIT */
-#endif
-             break;
 
            case ConfigureNotify:
-             f = x_any_window_to_frame (event.xconfigure.window);
-#ifdef USE_X_TOOLKIT
+             f = x_any_window_to_frame (dpyinfo, event.xconfigure.window);
              if (f
-#if 0
-                 && ! event.xconfigure.send_event
+#ifdef USE_X_TOOLKIT
+                 && (event.xconfigure.window == XtWindow (f->output_data.x->widget))
 #endif
-                 && (event.xconfigure.window == XtWindow (f->display.x->widget)))
+                 )
                {
-                 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.  */
-                                        XtWindow (f->display.x->widget),
-                                        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->display.x->pixel_width = event.xconfigure.width;
-                 f->display.x->pixel_height = event.xconfigure.height;
-                 f->display.x->left_pos = event.xconfigure.x;
-                 f->display.x->top_pos = event.xconfigure.y;
+#ifndef USE_X_TOOLKIT
+                 /* In the toolkit version, change_frame_size
+                    is called by the code that handles resizing
+                    of the EmacsFrame widget.  */
 
-                 /* 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->display.x->left_pos = x;
-                   f->display.x->top_pos = y;
-                 }
-               }
-             goto OTHER;
-#else /* not USE_X_TOOLKIT */
-             if (f)
-               {
                  int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
                  int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
 
@@ -3837,14 +3920,21 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                     to check the pixel dimensions as well.  */
                  if (columns != f->width
                      || rows != f->height
-                     || event.xconfigure.width != f->display.x->pixel_width
-                     || event.xconfigure.height != f->display.x->pixel_height)
+                     || event.xconfigure.width != f->output_data.x->pixel_width
+                     || event.xconfigure.height != f->output_data.x->pixel_height)
                    {
                      change_frame_size (f, rows, columns, 0, 1);
                      SET_FRAME_GARBAGED (f);
                    }
+#endif
 
-                 if (! event.xconfigure.send_event)
+                 /* 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;
@@ -3857,7 +3947,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                      XTranslateCoordinates (FRAME_X_DISPLAY (f),
 
                                             /* From-window, to-window.  */
-                                            f->display.x->window_desc,
+                                            event.xconfigure.window,
                                             FRAME_X_DISPLAY_INFO (f)->root_window,
 
                                             /* From-position, to-position.  */
@@ -3871,29 +3961,32 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                      event.xconfigure.y = win_y;
                    }
 
-                 f->display.x->pixel_width = event.xconfigure.width;
-                 f->display.x->pixel_height = event.xconfigure.height;
-                 f->display.x->left_pos = event.xconfigure.x;
-                 f->display.x->top_pos = event.xconfigure.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->display.x->left_pos = x;
-                   f->display.x->top_pos = 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->display.x->win_gravity = NorthWestGravity;
-                       x_wm_set_size_hint (f, 0, 0);
+                       f->output_data.x->win_gravity = NorthWestGravity;
+                       x_wm_set_size_hint (f, (long) 0, 0);
                      }
+/* #endif */
                  }
                }
-#endif /* not USE_X_TOOLKIT */
-             break;
+             goto OTHER;
 
            case ButtonPress:
            case ButtonRelease:
@@ -3909,11 +4002,11 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                    && FRAME_LIVE_P (last_mouse_frame))
                  f = last_mouse_frame;
                else
-                 f = x_window_to_frame (event.xmotion.window);
+                 f = x_window_to_frame (dpyinfo, event.xbutton.window);
 
                if (f)
                  {
-                   if (!x_focus_frame || (f == x_focus_frame))
+                   if (!dpyinfo->x_focus_frame || f == dpyinfo->x_focus_frame)
                      construct_mouse_click (&emacs_event, &event, f);
                  }
                else
@@ -3923,15 +4016,6 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
 
                    if (bar)
                      x_scroll_bar_handle_click (bar, &event, &emacs_event);
-#ifdef USE_X_TOOLKIT
-                   else
-                     {
-                       /* Assume we have a menubar button press. A bad
-                          assumption should behave benignly. */
-                       popup_get_selection (&event);
-                       break;
-                     }
-#endif /* USE_X_TOOLKIT */
                  }
 
                if (event.type == ButtonPress)
@@ -3953,7 +4037,37 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                  }
 
 #ifdef USE_X_TOOLKIT
-               goto OTHER;
+               f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
+               /* For a down-event in the menu bar,
+                  don't pass it to Xt right now.
+                  Instead, save it away
+                  and we will pass it to Xt from kbd_buffer_get_event.
+                  That way, we can run some Lisp code first.  */
+               if (f && event.type == ButtonPress
+                   /* Verify the event is really within the menu bar
+                      and not just sent to it due to grabbing.  */
+                   && event.xbutton.x >= 0
+                   && event.xbutton.x < f->output_data.x->pixel_width
+                   && event.xbutton.y >= 0
+                   && 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)
+                     {
+                       bufp->kind = menu_bar_activate_event;
+                       XSETFRAME (bufp->frame_or_window, f);
+                       bufp++;
+                       count++;
+                       numchars--;
+                     }
+                 }
+               else
+                 goto OTHER;
 #endif /* USE_X_TOOLKIT */
              }
              break;
@@ -3974,14 +4088,11 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                case MappingKeyboard:
                  XRefreshKeyboardMapping (&event.xmapping);
                }
-#ifdef USE_X_TOOLKIT
              goto OTHER;
-#endif /* USE_X_TOOLKIT */
-             break;
 
            default:
-#ifdef USE_X_TOOLKIT
            OTHER:
+#ifdef USE_X_TOOLKIT
              BLOCK_INPUT;
              XtDispatchEvent (&event);
              UNBLOCK_INPUT;
@@ -4002,8 +4113,14 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
       if (x_noop_count >= 100)
        {
          x_noop_count=0;
-         /* Use the first display in the list.  Why not?  */
-         XNoOp (x_display_list->display);
+
+         if (next_noop_dpyinfo == 0)
+           next_noop_dpyinfo = x_display_list;
+
+         XNoOp (next_noop_dpyinfo->display);
+
+         /* Each time we get here, cycle through the displays now open.  */
+         next_noop_dpyinfo = next_noop_dpyinfo->next;
        }
     }
 
@@ -4023,19 +4140,21 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
 /* Drawing the cursor.  */
 
 
-/* Draw a hollow box cursor.  Don't change the inside of the box.  */
+/* Draw a hollow box cursor on frame F at X, Y.
+   Don't change the inside of the box.  */
 
 static void
-x_draw_box (f)
+x_draw_box (f, x, y)
      struct frame *f;
+     int x, y;
 {
-  int left = CHAR_TO_PIXEL_COL (f, curs_x);
-  int top  = CHAR_TO_PIXEL_ROW (f, curs_y);
-  int width = FONT_WIDTH (f->display.x->font);
-  int height = f->display.x->line_height;
+  int left = CHAR_TO_PIXEL_COL (f, x);
+  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;
 
   XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                 f->display.x->cursor_gc,
+                 f->output_data.x->cursor_gc,
                  left, top, width - 1, height - 1);
 }
 
@@ -4076,35 +4195,28 @@ x_draw_single_glyph (f, row, column, glyph, highlight)
 }
 
 static void
-x_display_bar_cursor (f, on)
+x_display_bar_cursor (f, on, x, y)
      struct frame *f;
      int on;
+     int x, y;
 {
   struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
 
   /* This is pointless on invisible frames, and dangerous on garbaged
      frames; in the latter case, the frame may be in the midst of
-     changing its size, and curs_x and curs_y may be off the frame.  */
+     changing its size, and x and y may be off the frame.  */
   if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
     return;
 
   if (! on && f->phys_cursor_x < 0)
     return;
 
-  /* If we're not updating, then we want to use the current frame's
-     cursor position, not our local idea of where the cursor ought to be.  */
-  if (f != updating_frame)
-    {
-      curs_x = FRAME_CURSOR_X (f);
-      curs_y = FRAME_CURSOR_Y (f);
-    }
-
   /* If there is anything wrong with the current cursor state, remove it.  */
   if (f->phys_cursor_x >= 0
       && (!on
-         || f->phys_cursor_x != curs_x
-         || f->phys_cursor_y != curs_y
-         || f->display.x->current_cursor != bar_cursor))
+         || f->phys_cursor_x != x
+         || f->phys_cursor_y != y
+         || f->output_data.x->current_cursor != bar_cursor))
     {
       /* Erase the cursor by redrawing the character underneath it.  */
       x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
@@ -4116,24 +4228,24 @@ x_display_bar_cursor (f, on)
   /* 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->display.x->current_cursor != bar_cursor)))
+         || (f->output_data.x->current_cursor != bar_cursor)))
     {
       f->phys_cursor_glyph
-       = ((current_glyphs->enable[curs_y]
-           && curs_x < current_glyphs->used[curs_y])
-          ? current_glyphs->glyphs[curs_y][curs_x]
+       = ((current_glyphs->enable[y]
+           && x < current_glyphs->used[y])
+          ? current_glyphs->glyphs[y][x]
           : SPACEGLYPH);
       XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                     f->display.x->cursor_gc,
-                     CHAR_TO_PIXEL_COL (f, curs_x),
-                     CHAR_TO_PIXEL_ROW (f, curs_y),
-                     max (f->display.x->cursor_width, 1),
-                     f->display.x->line_height);
+                     f->output_data.x->cursor_gc,
+                     CHAR_TO_PIXEL_COL (f, x),
+                     CHAR_TO_PIXEL_ROW (f, y),
+                     max (f->output_data.x->cursor_width, 1),
+                     f->output_data.x->line_height);
 
-      f->phys_cursor_x = curs_x;
-      f->phys_cursor_y = curs_y;
+      f->phys_cursor_x = x;
+      f->phys_cursor_y = y;
 
-      f->display.x->current_cursor = bar_cursor;
+      f->output_data.x->current_cursor = bar_cursor;
     }
 
   if (updating_frame != f)
@@ -4142,19 +4254,19 @@ x_display_bar_cursor (f, on)
 
 
 /* Turn the displayed cursor of frame F on or off according to ON.
-   If ON is nonzero, where to put the cursor is specified
-   by F->cursor_x and F->cursor_y.  */
+   If ON is nonzero, where to put the cursor is specified by X and Y.  */
 
 static void
-x_display_box_cursor (f, on)
+x_display_box_cursor (f, on, x, y)
      struct frame *f;
      int on;
+     int x, y;
 {
   struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
 
   /* This is pointless on invisible frames, and dangerous on garbaged
      frames; in the latter case, the frame may be in the midst of
-     changing its size, and curs_x and curs_y may be off the frame.  */
+     changing its size, and x and y may be off the frame.  */
   if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
     return;
 
@@ -4162,24 +4274,16 @@ x_display_box_cursor (f, on)
   if (!on && f->phys_cursor_x < 0)
     return;
 
-  /* If we're not updating, then we want to use the current frame's
-     cursor position, not our local idea of where the cursor ought to be.  */
-  if (f != updating_frame)
-    {
-      curs_x = FRAME_CURSOR_X (f);
-      curs_y = FRAME_CURSOR_Y (f);
-    }
-
   /* 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
       && (!on
-         || f->phys_cursor_x != curs_x
-         || f->phys_cursor_y != curs_y
-         || (f->display.x->current_cursor != hollow_box_cursor
-             && (f != x_highlight_frame))))
+         || f->phys_cursor_x != x
+         || f->phys_cursor_y != y
+         || (f->output_data.x->current_cursor != hollow_box_cursor
+             && (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame))))
     {
       int mouse_face_here = 0;
       struct frame_glyphs *active_glyphs = FRAME_CURRENT_GLYPHS (f);
@@ -4203,12 +4307,12 @@ x_display_box_cursor (f, on)
 
       /* If the font is not as tall as a whole line,
         we must explicitly clear the line's whole height.  */
-      if (FONT_HEIGHT (f->display.x->font) != f->display.x->line_height)
+      if (FONT_HEIGHT (f->output_data.x->font) != f->output_data.x->line_height)
        XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                    CHAR_TO_PIXEL_COL (f, f->phys_cursor_x),
                    CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y),
-                   FONT_WIDTH (f->display.x->font),
-                   f->display.x->line_height, False);
+                   FONT_WIDTH (f->output_data.x->font),
+                   f->output_data.x->line_height, False);
       /* Erase the cursor by redrawing the character underneath it.  */
       x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
                           f->phys_cursor_glyph,
@@ -4223,44 +4327,83 @@ x_display_box_cursor (f, on)
      write it in the right place.  */
   if (on
       && (f->phys_cursor_x < 0
-         || (f->display.x->current_cursor != filled_box_cursor
-             && f == x_highlight_frame)))
+         || (f->output_data.x->current_cursor != filled_box_cursor
+             && f == FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)))
     {
       f->phys_cursor_glyph
-       = ((current_glyphs->enable[curs_y]
-           && curs_x < current_glyphs->used[curs_y])
-          ? current_glyphs->glyphs[curs_y][curs_x]
+       = ((current_glyphs->enable[y]
+           && x < current_glyphs->used[y])
+          ? current_glyphs->glyphs[y][x]
           : SPACEGLYPH);
-      if (f != x_highlight_frame)
+      if (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
        {
-         x_draw_box (f);
-         f->display.x->current_cursor = hollow_box_cursor;
+         x_draw_box (f, x, y);
+         f->output_data.x->current_cursor = hollow_box_cursor;
        }
       else
        {
-         x_draw_single_glyph (f, curs_y, curs_x,
+         x_draw_single_glyph (f, y, x,
                               f->phys_cursor_glyph, 2);
-         f->display.x->current_cursor = filled_box_cursor;
+         f->output_data.x->current_cursor = filled_box_cursor;
        }
 
-      f->phys_cursor_x = curs_x;
-      f->phys_cursor_y = curs_y;
+      f->phys_cursor_x = x;
+      f->phys_cursor_y = y;
     }
 
   if (updating_frame != f)
     XFlush (FRAME_X_DISPLAY (f));
 }
 
+/* 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.  */
+
 x_display_cursor (f, on)
      struct frame *f;
      int on;
 {
   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);
+  else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
+    x_display_bar_cursor (f, on, curs_x, curs_y);
+  else
+    /* Those are the only two we have implemented!  */
+    abort ();
+
+  UNBLOCK_INPUT;
+}
+
+/* Display the cursor on frame F, or clear it, according to ON.
+   Don't change the cursor's position.  */
+
+x_update_cursor (f, on)
+     struct frame *f;
+     int on;
+{
+  /* If we don't have any previous cursor position to use,
+     leave the cursor off.  */
+  if (f->phys_cursor_x < 0)
+    return;
+
+  BLOCK_INPUT;
+
   if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
-    x_display_box_cursor (f, on);
+    x_display_box_cursor (f, on, f->phys_cursor_x, f->phys_cursor_y);
   else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
-    x_display_bar_cursor (f, on);
+    x_display_bar_cursor (f, on, f->phys_cursor_x, f->phys_cursor_y);
   else
     /* Those are the only two we have implemented!  */
     abort ();
@@ -4293,16 +4436,16 @@ x_bitmap_icon (f, file)
     return 1;
 
   /* Free up our existing icon bitmap if any.  */
-  if (f->display.x->icon_bitmap > 0)
-    x_destroy_bitmap (f, f->display.x->icon_bitmap);
-  f->display.x->icon_bitmap = 0;
+  if (f->output_data.x->icon_bitmap > 0)
+    x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
+  f->output_data.x->icon_bitmap = 0;
 
   if (STRINGP (file))
     bitmap_id = x_create_bitmap_from_file (f, file);
   else
     {
       /* Create the GNU bitmap if necessary.  */
-      if (!FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
+      if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
        FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
          = x_create_bitmap_from_data (f, gnu_bits,
                                       gnu_width, gnu_height);
@@ -4317,13 +4460,14 @@ x_bitmap_icon (f, file)
     }
 
   x_wm_set_icon_pixmap (f, bitmap_id);
-  f->display.x->icon_bitmap = bitmap_id;
+  f->output_data.x->icon_bitmap = bitmap_id;
 
   return 0;
 }
 
 
-/* Make the x-window of frame F use a rectangle with text.  */
+/* Make the x-window of frame F use a rectangle with text.
+   Use ICON_NAME as the text.  */
 
 int
 x_text_icon (f, icon_name)
@@ -4333,20 +4477,27 @@ x_text_icon (f, icon_name)
   if (FRAME_X_WINDOW (f) == 0)
     return 1;
 
-  if (icon_name)
-    f->display.x->icon_label = icon_name;
-  else
-    if (! f->display.x->icon_label)
-      f->display.x->icon_label = " *emacs* ";
-
-#if 0
-  XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-               (char *) f->display.x->icon_label);
-#endif
+#ifdef HAVE_X11R4
+  {
+    XTextProperty text;
+    text.value = (unsigned char *) icon_name;
+    text.encoding = XA_STRING;
+    text.format = 8;
+    text.nitems = strlen (icon_name);
+#ifdef USE_X_TOOLKIT
+    XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
+                   &text);
+#else /* not USE_X_TOOLKIT */
+    XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
+#endif /* not USE_X_TOOLKIT */
+  }
+#else /* not HAVE_X11R4 */
+  XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
+#endif /* not HAVE_X11R4 */
 
-  if (f->display.x->icon_bitmap > 0)
-    x_destroy_bitmap (f, f->display.x->icon_bitmap);
-  f->display.x->icon_bitmap = 0;
+  if (f->output_data.x->icon_bitmap > 0)
+    x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
+  f->output_data.x->icon_bitmap = 0;
   x_wm_set_icon_pixmap (f, 0);
 
   return 0;
@@ -4367,6 +4518,10 @@ x_connection_closed (display, error_message)
   if (_Xdebug)
     abort ();
 
+  /* Indicate that this display is dead.  */
+
+  dpyinfo->display = 0;
+
   /* First delete frames whose minibuffers are on frames
      that are on the dead display.  */
   FOR_EACH_FRAME (tail, frame)
@@ -4374,8 +4529,10 @@ x_connection_closed (display, error_message)
       Lisp_Object minibuf_frame;
       minibuf_frame
        = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
-      if (! EQ (frame, minibuf_frame)
-         && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
+      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);
     }
 
@@ -4383,10 +4540,17 @@ x_connection_closed (display, error_message)
      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_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
-      Fdelete_frame (frame, Qt);
+    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);
+      }
 
-  x_delete_display (dpyinfo);
+  if (dpyinfo)
+    x_delete_display (dpyinfo);
 
   if (x_display_list == 0)
     {
@@ -4405,18 +4569,6 @@ x_connection_closed (display, error_message)
   error ("%s", error_message);
 }
 
-static SIGTYPE
-x_connection_signal (signalnum)        /* If we don't have an argument, */
-     int signalnum;            /* some compilers complain in signal calls. */
-{
-  /* We really ought to close the connection to the display
-     that actually failed.
-     But do we actually get this signal ever with X11?  */
-  fprintf (stderr, "X connection closed");
-  shut_down_emacs (0, 0, Qnil);
-  exit (70);
-}
-
 /* 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.  */
@@ -4432,7 +4584,7 @@ x_error_quitter (display, error)
      original error handler.  */
 
   XGetErrorText (display, error->error_code, buf, sizeof (buf));
-  sprintf (buf1, "X protocol error: %s on protocol request %d",
+  sprintf (buf1, "X protocol error: %s on protocol request %d\n",
           buf, error->request_code);
   x_connection_closed (display, buf1);
 }
@@ -4451,6 +4603,59 @@ x_io_error_quitter (display)
   x_connection_closed (display, buf);
 }
 \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;
+
+static SIGTYPE x_connection_signal ();
+
+static SIGTYPE
+x_connection_signal_1 (signalnum)      /* If we don't have an argument, */
+     int signalnum;            /* some compilers complain in signal calls. */
+{
+  signal (SIGPIPE, x_connection_signal);
+  x_connection_closed (x_connection_signal_dpyinfo,
+                      "connection was lost");
+}
+
+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;
+
+  sigunblock (SIGPIPE);
+
+  while (x_connection_signal_dpyinfo)
+    {
+      signal (SIGPIPE, x_connection_signal_1);
+
+      x_connection_close_if_hung (x_connection_signal_dpyinfo);
+
+      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 ();
+}
+\f
 /* A buffer for storing X error messages.  */
 static char *x_caught_error_message;
 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
@@ -4604,7 +4809,7 @@ x_new_font (f, fontname)
 
   /* If we have, just return it from the table.  */
   if (already_loaded >= 0)
-    f->display.x->font = FRAME_X_DISPLAY_INFO (f)->font_table[already_loaded].font;
+    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
     {
@@ -4696,7 +4901,7 @@ x_new_font (f, fontname)
        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->display.x->font = FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].font = font;
+      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)
@@ -4706,7 +4911,7 @@ x_new_font (f, fontname)
   /* Compute the scroll bar width in character columns.  */
   if (f->scroll_bar_pixel_width > 0)
     {
-      int wid = FONT_WIDTH (f->display.x->font);
+      int wid = FONT_WIDTH (f->output_data.x->font);
       f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
     }
   else
@@ -4715,12 +4920,12 @@ x_new_font (f, fontname)
   /* Now make the frame display the given font.  */
   if (FRAME_X_WINDOW (f) != 0)
     {
-      XSetFont (FRAME_X_DISPLAY (f), f->display.x->normal_gc,
-               f->display.x->font->fid);
-      XSetFont (FRAME_X_DISPLAY (f), f->display.x->reverse_gc,
-               f->display.x->font->fid);
-      XSetFont (FRAME_X_DISPLAY (f), f->display.x->cursor_gc,
-               f->display.x->font->fid);
+      XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
+               f->output_data.x->font->fid);
+      XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
+               f->output_data.x->font->fid);
+      XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
+               f->output_data.x->font->fid);
 
       frame_update_line_height (f);
       x_set_window_size (f, 0, f->width, f->height);
@@ -4728,7 +4933,7 @@ x_new_font (f, fontname)
   else
     /* If we are setting a new frame's font for the first time,
        there are no faces yet, so this font's height is the line height.  */
-    f->display.x->line_height = FONT_HEIGHT (f->display.x->font);
+    f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
 
   {
     Lisp_Object lispy_name;
@@ -4743,23 +4948,33 @@ x_new_font (f, fontname)
   }
 }
 \f
+/* Calculate the absolute position in frame F
+   from its current recorded position values and gravity.  */
+
 x_calc_absolute_position (f)
      struct frame *f;
 {
   Window win, child;
   int win_x = 0, win_y = 0;
-  int flags = f->display.x->size_hint_flags;
+  int flags = f->output_data.x->size_hint_flags;
+  int this_window;
+
+#ifdef USE_X_TOOLKIT
+  this_window = XtWindow (f->output_data.x->widget);
+#else
+  this_window = FRAME_X_WINDOW (f);
+#endif
 
   /* Find the position of the outside upper-left corner of
      the inner window, with respect to the outer window.  */
-  if (f->display.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
+  if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
     {
       BLOCK_INPUT;
       XTranslateCoordinates (FRAME_X_DISPLAY (f),
 
                             /* From-window, to-window.  */
-                            f->display.x->window_desc,
-                            f->display.x->parent_desc,
+                            this_window,
+                            f->output_data.x->parent_desc,
 
                             /* From-position, to-position.  */
                             0, 0, &win_x, &win_y,
@@ -4772,54 +4987,70 @@ x_calc_absolute_position (f)
   /* Treat negative positions as relative to the leftmost bottommost
      position that fits on the screen.  */
   if (flags & XNegative)
-    f->display.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
-                             - 2 * f->display.x->border_width - win_x
-                             - PIXEL_WIDTH (f)
-                             + f->display.x->left_pos);
+    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);
 
   if (flags & YNegative)
-    f->display.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
-                            - 2 * f->display.x->border_width - win_y
-                            - PIXEL_HEIGHT (f)
-                            + f->display.x->top_pos);
+    /* 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)
+                                + 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.  */
-  f->display.x->size_hint_flags &= ~ (XNegative | YNegative);
+  f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
 }
 
 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
    to really change the position, and 0 when calling from
    x_make_frame_visible (in that case, XOFF and YOFF are the current
-   position values).  */
+   position values).  It is -1 when calling from x_set_frame_parameters,
+   which means, do adjust for borders but don't change the gravity.  */
 
 x_set_offset (f, xoff, yoff, change_gravity)
      struct frame *f;
      register int xoff, yoff;
      int change_gravity;
 {
-  if (change_gravity)
+  int modified_top, modified_left;
+
+  if (change_gravity > 0)
     {
-      f->display.x->top_pos = yoff;
-      f->display.x->left_pos = xoff;
-      f->display.x->size_hint_flags &= ~ (XNegative | YNegative);
+      f->output_data.x->top_pos = yoff;
+      f->output_data.x->left_pos = xoff;
+      f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
       if (xoff < 0)
-       f->display.x->size_hint_flags |= XNegative;
+       f->output_data.x->size_hint_flags |= XNegative;
       if (yoff < 0)
-       f->display.x->size_hint_flags |= YNegative;
-      f->display.x->win_gravity = NorthWestGravity;
+       f->output_data.x->size_hint_flags |= YNegative;
+      f->output_data.x->win_gravity = NorthWestGravity;
     }
   x_calc_absolute_position (f);
 
   BLOCK_INPUT;
-  x_wm_set_size_hint (f, 0, 0);
+  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 (change_gravity != 0)
+    {
+      modified_left += f->output_data.x->border_width;
+      modified_top += f->output_data.x->border_width;
+    }
 
 #ifdef USE_X_TOOLKIT
-  XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->display.x->widget),
-              f->display.x->left_pos, f->display.x->top_pos);
+  XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
+              modified_left, modified_top);
 #else /* not USE_X_TOOLKIT */
   XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-              f->display.x->left_pos, f->display.x->top_pos);
+              modified_left, modified_top);
 #endif /* not USE_X_TOOLKIT */
   UNBLOCK_INPUT;
 }
@@ -4836,38 +5067,38 @@ x_set_window_size (f, change_gravity, cols, rows)
 {
   int pixelwidth, pixelheight;
   int mask;
+  Lisp_Object window;
+  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.
        This is a real kludge, but I don't understand Xt so I can't
        figure out a correct fix.  Can anyone else tell me? -- rms.  */
-    int xpos = f->display.x->widget->core.x;
-    int ypos = f->display.x->widget->core.y;
-    EmacsFrameSetCharSize (f->display.x->edit_widget, cols, rows);
-    f->display.x->widget->core.x = xpos;
-    f->display.x->widget->core.y = ypos;
+    int xpos = f->output_data.x->widget->core.x;
+    int ypos = f->output_data.x->widget->core.y;
+    EmacsFrameSetCharSize (f->output_data.x->edit_widget, 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->display.x->vertical_scroll_bar_extra
+  f->output_data.x->vertical_scroll_bar_extra
     = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
        ? 0
        : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
        ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
-       : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->display.x->font)));
+       : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
   pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
   pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
 
-  f->display.x->win_gravity = NorthWestGravity;
-  x_wm_set_size_hint (f, 0, 0);
+  f->output_data.x->win_gravity = NorthWestGravity;
+  x_wm_set_size_hint (f, (long) 0, 0);
 
   XSync (FRAME_X_DISPLAY (f), False);
   XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
@@ -4887,6 +5118,16 @@ x_set_window_size (f, change_gravity, cols, rows)
   PIXEL_WIDTH (f) = pixelwidth;
   PIXEL_HEIGHT (f) = pixelheight;
 
+  /* 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
+     we have to make sure to do it here.  */
+  SET_FRAME_GARBAGED (f);
+
+  XFlush (FRAME_X_DISPLAY (f));
+
+#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)
@@ -4895,18 +5136,22 @@ x_set_window_size (f, change_gravity, cols, rows)
       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
-     we have to make sure to do it here.  */
-  SET_FRAME_GARBAGED (f);
+  /* 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.  */
+  window = dpyinfo->mouse_face_window;
+  if (! NILP (window) && XFRAME (window) == 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;
+    }
 
-  XFlush (FRAME_X_DISPLAY (f));
   UNBLOCK_INPUT;
-#endif /* not USE_X_TOOLKIT */
 }
 \f
-/* Mouse warping, focus shifting, raising and lowering.  */
+/* Mouse warping.  */
 
 void
 x_set_mouse_position (f, x, y)
@@ -4915,8 +5160,8 @@ x_set_mouse_position (f, x, y)
 {
   int pix_x, pix_y;
 
-  pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH  (f->display.x->font) / 2;
-  pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->display.x->line_height / 2;
+  pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH  (f->output_data.x->font) / 2;
+  pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
 
   if (pix_x < 0) pix_x = 0;
   if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
@@ -4944,6 +5189,8 @@ x_set_mouse_pixel_position (f, pix_x, pix_y)
                0, 0, 0, 0, pix_x, pix_y);
   UNBLOCK_INPUT;
 }
+\f
+/* focus shifting, raising and lowering.  */
 
 x_focus_on_frame (f)
      struct frame *f;
@@ -4965,7 +5212,7 @@ x_unfocus_frame (f)
 {
 #if 0
   /* Look at the remarks in x_focus_on_frame.  */
-  if (x_focus_frame == f)
+  if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
     XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
                    RevertToPointerRoot, CurrentTime);
 #endif /* ! 0 */
@@ -4980,7 +5227,7 @@ x_raise_frame (f)
     {
       BLOCK_INPUT;
 #ifdef USE_X_TOOLKIT
-      XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->display.x->widget));
+      XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
 #else /* not USE_X_TOOLKIT */
       XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
 #endif /* not USE_X_TOOLKIT */
@@ -4998,7 +5245,7 @@ x_lower_frame (f)
     {
       BLOCK_INPUT;
 #ifdef USE_X_TOOLKIT
-      XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->display.x->widget));
+      XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
 #else /* not USE_X_TOOLKIT */
       XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
 #endif /* not USE_X_TOOLKIT */
@@ -5008,18 +5255,24 @@ 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);
 }
+\f
+/* Change of visibility.  */
 
-/* Change from withdrawn state to mapped state,
-   or deiconify. */
+/* This tries to wait until the frame is really visible.
+   However, if the window manager asks the user where to position
+   the frame, this will return before the user finishes doing that.
+   The frame will not actually be visible at that time,
+   but it will become visible later when the window manager
+   finishes with it.  */
 
 x_make_frame_visible (f)
      struct frame *f;
@@ -5035,16 +5288,21 @@ x_make_frame_visible (f)
 
   if (! FRAME_VISIBLE_P (f))
     {
-#ifndef USE_X_TOOLKIT
-      if (! FRAME_ICONIFIED_P (f))
-       x_set_offset (f, f->display.x->left_pos, f->display.x->top_pos, 0);
-#endif
+      /* We test FRAME_GARBAGED_P here to make sure we don't
+        call x_set_offset a second time
+        if we get to x_make_frame_visible a second time
+        before the window gets really visible.  */
+      if (! FRAME_ICONIFIED_P (f)
+         && ! f->output_data.x->asked_for_visible)
+       x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
+
+      f->output_data.x->asked_for_visible = 1;
 
       if (! EQ (Vx_no_window_manager, Qt))
        x_wm_set_window_state (f, NormalState);
 #ifdef USE_X_TOOLKIT
       /* This was XtPopup, but that did nothing for an iconified frame.  */
-      XtMapWidget (f->display.x->widget);
+      XtMapWidget (f->output_data.x->widget);
 #else /* not USE_X_TOOLKIT */
       XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
 #endif /* not USE_X_TOOLKIT */
@@ -5106,6 +5364,8 @@ x_make_frame_visible (f)
 
 /* Change from mapped state to withdrawn state. */
 
+/* Make the frame visible (mapped and not iconified).  */
+
 x_make_frame_invisible (f)
      struct frame *f;
 {
@@ -5114,14 +5374,14 @@ x_make_frame_invisible (f)
 
 #ifdef USE_X_TOOLKIT
   /* Use the frame's outermost window, not the one we normally draw on.  */
-  window = XtWindow (f->display.x->widget);
+  window = XtWindow (f->output_data.x->widget);
 #else /* not USE_X_TOOLKIT */
   window = FRAME_X_WINDOW (f);
 #endif /* not USE_X_TOOLKIT */
 
   /* Don't keep the highlight on an invisible frame.  */
-  if (x_highlight_frame == f)
-    x_highlight_frame = 0;
+  if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
+    FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
 
 #if 0/* This might add unreliability; I don't trust it -- rms.  */
   if (! f->async_visible && ! f->async_iconified)
@@ -5135,7 +5395,7 @@ x_make_frame_invisible (f)
      program-specified, so that when the window is mapped again, it will be
      placed at the same location, without forcing the user to position it
      by hand again (they have already done that once for this window.)  */
-  x_wm_set_size_hint (f, 0, 1);
+  x_wm_set_size_hint (f, (long) 0, 1);
 
 #ifdef HAVE_X11R4
 
@@ -5196,14 +5456,16 @@ x_iconify_frame (f)
   Lisp_Object type;
 
   /* Don't keep the highlight on an invisible frame.  */
-  if (x_highlight_frame == f)
-    x_highlight_frame = 0;
+  if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
+    FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
 
   if (f->async_iconified)
     return;
 
   BLOCK_INPUT;
 
+  FRAME_SAMPLE_VISIBILITY (f);
+
   type = x_icon_type (f);
   if (!NILP (type))
     x_bitmap_icon (f, type);
@@ -5215,13 +5477,13 @@ x_iconify_frame (f)
       if (! EQ (Vx_no_window_manager, Qt))
        x_wm_set_window_state (f, IconicState);
       /* This was XtPopup, but that did nothing for an iconified frame.  */
-      XtMapWidget (f->display.x->widget);
+      XtMapWidget (f->output_data.x->widget);
       UNBLOCK_INPUT;
       return;
     }
 
   result = XIconifyWindow (FRAME_X_DISPLAY (f),
-                          XtWindow (f->display.x->widget),
+                          XtWindow (f->output_data.x->widget),
                           DefaultScreen (FRAME_X_DISPLAY (f)));
   UNBLOCK_INPUT;
 
@@ -5238,7 +5500,7 @@ x_iconify_frame (f)
   /* Make sure the X server knows where the window should be positioned,
      in case the user deiconifies with the window manager.  */
   if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
-    x_set_offset (f, f->display.x->left_pos, f->display.x->top_pos, 0);
+    x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
 
   /* Since we don't know which revision of X we're running, we'll use both
      the X11R3 and X11R4 techniques.  I don't know if this is a good idea.  */
@@ -5281,7 +5543,7 @@ x_iconify_frame (f)
   UNBLOCK_INPUT;
 #endif /* not USE_X_TOOLKIT */
 }
-
+\f
 /* Destroy the X window of frame F.  */
 
 x_destroy_window (f)
@@ -5291,25 +5553,37 @@ x_destroy_window (f)
 
   BLOCK_INPUT;
 
-  if (f->display.x->icon_desc != 0)
-    XDestroyWindow (FRAME_X_DISPLAY (f), f->display.x->icon_desc);
-  XDestroyWindow (FRAME_X_DISPLAY (f), f->display.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));
+         XCloseIM (FRAME_XIM (f));
+       }
+#endif
+      XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
 #ifdef USE_X_TOOLKIT
-  XtDestroyWidget (f->display.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));
+    }
 
-  xfree (f->display.x);
-  f->display.x = 0;
-  if (f == x_focus_frame)
-    x_focus_frame = 0;
-  if (f == x_focus_event_frame)
-    x_focus_event_frame = 0;
-  if (f == x_highlight_frame)
-    x_highlight_frame = 0;
+  xfree (f->output_data.x);
+  f->output_data.x = 0;
+  if (f == dpyinfo->x_focus_frame)
+    dpyinfo->x_focus_frame = 0;
+  if (f == dpyinfo->x_focus_event_frame)
+    dpyinfo->x_focus_event_frame = 0;
+  if (f == dpyinfo->x_highlight_frame)
+    dpyinfo->x_highlight_frame = 0;
 
   dpyinfo->reference_count--;
 
@@ -5344,7 +5618,7 @@ x_wm_set_size_hint (f, flags, user_position)
   Arg al[2];
   int ac = 0;
   Dimension widget_width, widget_height;
-  Window window = XtWindow (f->display.x->widget);
+  Window window = XtWindow (f->output_data.x->widget);
 #else /* not USE_X_TOOLKIT */
   Window window = FRAME_X_WINDOW (f);
 #endif /* not USE_X_TOOLKIT */
@@ -5354,13 +5628,13 @@ x_wm_set_size_hint (f, flags, user_position)
 
   flexlines = f->height;
 
-  size_hints.x = f->display.x->left_pos;
-  size_hints.y = f->display.x->top_pos;
+  size_hints.x = f->output_data.x->left_pos;
+  size_hints.y = f->output_data.x->top_pos;
 
 #ifdef USE_X_TOOLKIT
   XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
   XtSetArg (al[ac], XtNheight, &widget_height); ac++;
-  XtGetValues (f->display.x->column_widget, al, ac);
+  XtGetValues (f->output_data.x->widget, al, ac);
   size_hints.height = widget_height;
   size_hints.width = widget_width;
 #else /* not USE_X_TOOLKIT */
@@ -5368,13 +5642,18 @@ x_wm_set_size_hint (f, flags, user_position)
   size_hints.width = PIXEL_WIDTH (f);
 #endif /* not USE_X_TOOLKIT */
 
-  size_hints.width_inc = FONT_WIDTH (f->display.x->font);
-  size_hints.height_inc = f->display.x->line_height;
+  size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
+  size_hints.height_inc = f->output_data.x->line_height;
   size_hints.max_width
     = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
   size_hints.max_height
     = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
 
+  /* Calculate the base and minimum sizes.
+
+     (When we use the X toolkit, we don't do it here.
+     Instead we copy the values that the widgets are using, below.)  */
+#ifndef USE_X_TOOLKIT
   {
     int base_width, base_height;
     int min_rows = 0, min_cols = 0;
@@ -5406,35 +5685,54 @@ x_wm_set_size_hint (f, flags, user_position)
 #endif
   }
 
+  /* If we don't need the old flags, we don't need the old hint at all.  */
   if (flags)
-    size_hints.flags |= flags;
-  else
     {
-      XSizeHints hints;                /* Sometimes I hate X Windows... */
-      long supplied_return;
-      int value;
+      size_hints.flags |= flags;
+      goto no_read;
+    }
+#endif /* not USE_X_TOOLKIT */
+
+  {
+    XSizeHints hints;          /* Sometimes I hate X Windows... */
+    long supplied_return;
+    int value;
 
 #ifdef HAVE_X11R4
-      value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
-                                &supplied_return);
+    value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
+                              &supplied_return);
 #else
-      value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
+    value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
 #endif
 
-      if (value == 0)
-       hints.flags = 0;
-      if (hints.flags & PSize)
-       size_hints.flags |= PSize;
-      if (hints.flags & PPosition)
-       size_hints.flags |= PPosition;
-      if (hints.flags & USPosition)
-       size_hints.flags |= USPosition;
-      if (hints.flags & USSize)
-       size_hints.flags |= USSize;
-    }
+#ifdef USE_X_TOOLKIT
+    size_hints.base_height = hints.base_height;
+    size_hints.base_width = hints.base_width;
+    size_hints.min_height = hints.min_height;
+    size_hints.min_width = hints.min_width;
+#endif
+
+    if (flags)
+      size_hints.flags |= flags;
+    else
+      {
+       if (value == 0)
+         hints.flags = 0;
+       if (hints.flags & PSize)
+         size_hints.flags |= PSize;
+       if (hints.flags & PPosition)
+         size_hints.flags |= PPosition;
+       if (hints.flags & USPosition)
+         size_hints.flags |= USPosition;
+       if (hints.flags & USSize)
+         size_hints.flags |= USSize;
+      }
+  }
+
+ no_read:
 
 #ifdef PWinGravity
-  size_hints.win_gravity = f->display.x->win_gravity;
+  size_hints.win_gravity = f->output_data.x->win_gravity;
   size_hints.flags |= PWinGravity;
 
   if (user_position)
@@ -5460,14 +5758,14 @@ x_wm_set_window_state (f, state)
   Arg al[1];
 
   XtSetArg (al[0], XtNinitialState, state);
-  XtSetValues (f->display.x->widget, al, 1);
+  XtSetValues (f->output_data.x->widget, al, 1);
 #else /* not USE_X_TOOLKIT */
   Window window = FRAME_X_WINDOW (f);
 
-  f->display.x->wm_hints.flags |= StateHint;
-  f->display.x->wm_hints.initial_state = state;
+  f->output_data.x->wm_hints.flags |= StateHint;
+  f->output_data.x->wm_hints.initial_state = state;
 
-  XSetWMHints (FRAME_X_DISPLAY (f), window, &f->display.x->wm_hints);
+  XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
 #endif /* not USE_X_TOOLKIT */
 }
 
@@ -5476,7 +5774,7 @@ x_wm_set_icon_pixmap (f, pixmap_id)
      int pixmap_id;
 {
 #ifdef USE_X_TOOLKIT
-  Window window = XtWindow (f->display.x->widget);
+  Window window = XtWindow (f->output_data.x->widget);
 #else
   Window window = FRAME_X_WINDOW (f);
 #endif
@@ -5484,16 +5782,26 @@ x_wm_set_icon_pixmap (f, pixmap_id)
   if (pixmap_id > 0)
     {
       Pixmap icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
-      f->display.x->wm_hints.icon_pixmap = icon_pixmap;
-      f->display.x->wm_hints.flags |= IconPixmapHint;
+      f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
     }
   else
     {
-      f->display.x->wm_hints.icon_pixmap = None;
-      f->display.x->wm_hints.flags &= ~IconPixmapHint;
+      /* It seems there is no way to turn off use of an icon pixmap.
+        The following line does it, only if no icon has yet been created,
+        for some window managers.  But with mwm it crashes.
+        Some people say it should clear the IconPixmapHint bit in this case,
+        but that doesn't work, and the X consortium said it isn't the
+        right thing at all.  Since there is no way to win,
+        best to explicitly give up.  */
+#if 0
+      f->output_data.x->wm_hints.icon_pixmap = None;
+#else
+      return;
+#endif
     }
 
-  XSetWMHints (FRAME_X_DISPLAY (f), window, &f->display.x->wm_hints);
+  f->output_data.x->wm_hints.flags |= IconPixmapHint;
+  XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
 }
 
 x_wm_set_icon_position (f, icon_x, icon_y)
@@ -5501,16 +5809,16 @@ x_wm_set_icon_position (f, icon_x, icon_y)
      int icon_x, icon_y;
 {
 #ifdef USE_X_TOOLKIT
-  Window window = XtWindow (f->display.x->widget);
+  Window window = XtWindow (f->output_data.x->widget);
 #else
   Window window = FRAME_X_WINDOW (f);
 #endif
 
-  f->display.x->wm_hints.flags |= IconPositionHint;
-  f->display.x->wm_hints.icon_x = icon_x;
-  f->display.x->wm_hints.icon_y = icon_y;
+  f->output_data.x->wm_hints.flags |= IconPositionHint;
+  f->output_data.x->wm_hints.icon_x = icon_x;
+  f->output_data.x->wm_hints.icon_y = icon_y;
 
-  XSetWMHints (FRAME_X_DISPLAY (f), window, &f->display.x->wm_hints);
+  XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
 }
 
 \f
@@ -5537,6 +5845,27 @@ static XrmOptionDescRec emacs_options[] = {
 
 static int x_initialized;
 
+#ifdef MULTI_KBOARD
+/* Test whether two display-name strings agree up to the dot that separates
+   the screen number from the server number.  */
+static int
+same_x_server (name1, name2)
+     char *name1, *name2;
+{
+  int seen_colon = 0;
+  for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
+    {
+      if (*name1 == ':')
+       seen_colon++;
+      if (seen_colon && *name1 == '.')
+       return 1;
+    }
+  return (seen_colon
+         && (*name1 == '.' || *name1 == '\0')
+         && (*name2 == '.' || *name2 == '\0'));
+}
+#endif
+
 struct x_display_info *
 x_term_init (display_name, xrm_option, resource_name)
      Lisp_Object display_name;
@@ -5550,14 +5879,25 @@ x_term_init (display_name, xrm_option, resource_name)
   struct x_display_info *dpyinfo;
   XrmDatabase xrdb;
 
+  BLOCK_INPUT;
+
   if (!x_initialized)
     {
       x_initialize ();
       x_initialized = 1;
     }
 
+#ifdef HAVE_X_I18N
+  setlocale (LC_ALL, "");
+#endif
+
 #ifdef USE_X_TOOLKIT
-#ifdef HAVE_X11R5
+  /* weiner@footloose.sps.mot.com reports that this causes
+     errors with X11R5:
+          X protocol error: BadAtom (invalid Atom parameter)
+          on protocol request 18skiloaf.
+     So let's not use it until R6.  */
+#ifdef HAVE_X11XTR6
   XtSetLanguageProc (NULL, NULL, NULL);
 #endif
 
@@ -5576,6 +5916,11 @@ x_term_init (display_name, xrm_option, resource_name)
                         resource_name, EMACS_CLASS,
                         emacs_options, XtNumber (emacs_options),
                         &argc, argv);
+
+#ifdef HAVE_X11XTR6
+    setlocale (LC_NUMERIC, "C");
+    setlocale (LC_TIME, "C");
+#endif
   }
 
 #else /* not USE_X_TOOLKIT */
@@ -5587,16 +5932,49 @@ x_term_init (display_name, xrm_option, resource_name)
 
   /* Detect failure.  */
   if (dpy == 0)
-    return 0;
+    {
+      UNBLOCK_INPUT;
+      return 0;
+    }
 
   /* We have definitely succeeded.  Record the new connection.  */
 
   dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
 
-#ifdef MULTI_PERDISPLAY
-  init_perdisplay (&dpyinfo->perdisplay);
-  dpyinfo->perdisplay.next_perdisplay = all_perdisplays;
-  all_perdisplays = &dpyinfo->perdisplay;
+#ifdef MULTI_KBOARD
+  {
+    struct x_display_info *share;
+    Lisp_Object tail;
+
+    for (share = x_display_list, tail = x_display_name_list; share;
+        share = share->next, tail = XCONS (tail)->cdr)
+      if (same_x_server (XSTRING (XCONS (XCONS (tail)->car)->car)->data,
+                        XSTRING (display_name)->data))
+       break;
+    if (share)
+      dpyinfo->kboard = share->kboard;
+    else
+      {
+       dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
+       init_kboard (dpyinfo->kboard);
+       if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
+         {
+           char *vendor = ServerVendor (dpy);
+           dpyinfo->kboard->Vsystem_key_alist
+             = call1 (Qvendor_specific_keysyms,
+                      build_string (vendor ? vendor : ""));
+         }
+
+       dpyinfo->kboard->next_kboard = all_kboards;
+       all_kboards = dpyinfo->kboard;
+       /* Don't let the initial kboard remain current longer than necessary.
+          That would cause problems if a file loaded on startup tries to
+          prompt in the minibuffer.  */
+       if (current_kboard == initial_kboard)
+         current_kboard = dpyinfo->kboard;
+      }
+    dpyinfo->kboard->reference_count++;
+  }
 #endif
 
   /* Put this display on the chain.  */
@@ -5635,7 +6013,7 @@ x_term_init (display_name, xrm_option, resource_name)
 #else
   dpyinfo->display->db = xrdb;
 #endif
-  /* Put thr rdb where we can find it in a way that works on
+  /* Put the rdb where we can find it in a way that works on
      all versions.  */
   dpyinfo->xrdb = xrdb;
 
@@ -5663,6 +6041,9 @@ x_term_init (display_name, xrm_option, resource_name)
   dpyinfo->mouse_face_window = Qnil;
   dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
   dpyinfo->mouse_face_defer = 0;
+  dpyinfo->x_focus_frame = 0;
+  dpyinfo->x_focus_event_frame = 0;
+  dpyinfo->x_highlight_frame = 0;
 
   dpyinfo->Xatom_wm_protocols
     = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
@@ -5701,6 +6082,8 @@ x_term_init (display_name, xrm_option, resource_name)
   dpyinfo->Xatom_ATOM_PAIR
     = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
 
+  dpyinfo->cut_buffers_initialized = 0;
+
   connection = ConnectionNumber (dpyinfo->display);
   dpyinfo->connection = connection;
 
@@ -5722,9 +6105,12 @@ x_term_init (display_name, xrm_option, resource_name)
 #endif /* F_SETOWN_BUG */
 
 #ifdef SIGIO
-  init_sigio (connection);
+  if (interrupt_input)
+    init_sigio (connection);
 #endif /* ! defined (SIGIO) */
 
+  UNBLOCK_INPUT;
+
   return dpyinfo;
 }
 \f
@@ -5770,20 +6156,14 @@ x_delete_display (dpyinfo)
          tail->next = tail->next->next;
     }
 
-#ifndef USE_X_TOOLKIT
-  /* I'm told Xt does this itself.  */
+#ifndef USE_X_TOOLKIT   /* I'm told Xt does this itself.  */
+#ifndef AIX            /* On AIX, XCloseDisplay calls this.  */
   XrmDestroyDatabase (dpyinfo->xrdb);
 #endif
-#ifdef MULTI_PERDISPLAY
-  {
-    PERDISPLAY **perdp;
-    for (perdp = &all_perdisplays; *perdp != &dpyinfo->perdisplay;
-        perdp = &(*perdp)->next_perdisplay)
-      if (*perdp == NULL)
-       abort ();
-    *perdp = dpyinfo->perdisplay.next_perdisplay;
-  }
-  wipe_perdisplay (&dpyinfo->perdisplay);
+#endif
+#ifdef MULTI_KBOARD
+  if (--dpyinfo->kboard->reference_count == 0)
+    delete_kboard (dpyinfo->kboard);
 #endif
   xfree (dpyinfo->font_table);
   xfree (dpyinfo->x_id_name);
@@ -5829,14 +6209,13 @@ x_initialize ()
 
   x_noop_count = 0;
 
-  x_focus_frame = x_highlight_frame = 0;
-
   /* Try to use interrupt input; if we can't, then start polling.  */
   Fset_input_mode (Qt, Qnil, Qt, Qnil);
 
 #ifdef USE_X_TOOLKIT
   XtToolkitInitialize ();
   Xt_app_con = XtCreateApplicationContext ();
+  XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
 #endif
 
   /* Note that there is no real way portable across R3/R4 to get the
@@ -5860,5 +6239,53 @@ syms_of_xterm ()
 
   staticpro (&last_mouse_scroll_bar);
   last_mouse_scroll_bar = Qnil;
+
+  staticpro (&Qvendor_specific_keysyms);
+  Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
+}
+\f
+/* Avoid warnings or errors from including Xlibint.h.
+   We don't need these functions for the rest of this file.  */
+#undef bzero
+#undef bcopy
+#undef bcmp
+#undef min
+#undef max
+
+#ifdef X_CONNECTION_LOCK_FLAG
+#define free loserfree
+#define malloc losermalloc
+#define exit loserexit
+#define abort loserabort
+/* For XlibDisplayWriting */
+#include <X11/Xlibint.h>
+#endif
+
+/* Check whether display connection DPYINFO is hung
+   because its thread-interlock is locked.
+   If it is, close the connection.
+   Do nothing if this system does not have a thread interlock.  */
+
+x_connection_close_if_hung (dpyinfo)
+     struct x_display_info *dpyinfo;
+{      
+  /* This tests (1) whether X_CONNECTION_LOCK_FLAG is defined at all,
+     and (2) whether the name it is defined as is itself defined.
+     (It ought to have been defined by Xlibint.h.  */
+#if X_CONNECTION_LOCK_FLAG
+
+  if (dpyinfo->display->flags & X_CONNECTION_LOCK_FLAG)
+    {
+      /* 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.  */
+
+      dpyinfo->display->flags &= ~X_CONNECTION_LOCK_FLAG;
+      x_connection_closed (dpyinfo->display, "connection was lost");
+    }
+#endif /* X_CONNECTION_LOCK_FLAG */
 }
-#endif /* ! defined (HAVE_X_WINDOWS) */
+
+/* Don't put any additional functions here!  */
+
+#endif /* not HAVE_X_WINDOWS */