(x_destroy_window) [HAVE_X_I18N]: Free xic and xim of frame.
[bpt/emacs.git] / src / xterm.c
index 4367976..352fa42 100644 (file)
@@ -1,5 +1,5 @@
 /* X Communication module for terminals which understand the X protocol.
-   Copyright (C) 1989, 1993, 1994, 1995 Free Software Foundation, Inc.
+   Copyright (C) 1989, 93, 94, 95, 1996 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -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,8 +86,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #ifdef USE_X_TOOLKIT
 extern void free_frame_menubar ();
-extern void _XEditResCheckMessages ();
 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
@@ -106,8 +110,16 @@ extern FRAME_PTR x_menubar_window_to_frame ();
 #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;
@@ -391,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)
     {
@@ -399,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.
@@ -970,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
@@ -1015,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
@@ -1559,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,
@@ -2179,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;
@@ -2351,7 +2365,7 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
                                       /* Child of win.  */
                                       &child);
 
-               if (child == None)
+               if (child == None || child == win)
                  break;
 
                win = child;
@@ -2765,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.
@@ -3262,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)
     {
@@ -3286,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) */
@@ -3336,6 +3356,11 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                        /* 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,
@@ -3409,7 +3434,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                        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)
                  {
@@ -3418,7 +3443,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                    _XEditResCheckMessages (f->output_data.x->widget, NULL,
                                            &event, NULL);
                  }
-#endif /* USE_X_TOOLKIT and HAVE_X11R5 */
+#endif /* HACK_EDITRES */
              }
              break;
 
@@ -3445,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;
@@ -3474,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;
@@ -3554,7 +3581,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
              break;
 
            case UnmapNotify:
-             f = x_any_window_to_frame (dpyinfo, 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.  */
                {
@@ -3575,10 +3602,7 @@ 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
@@ -3607,10 +3631,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                       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:
@@ -3642,8 +3663,25 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                                        | 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;
 
@@ -3757,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
@@ -3785,10 +3823,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                 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 (dpyinfo, event.xfocus.window);
@@ -3796,11 +3831,13 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                dpyinfo->x_focus_event_frame = f;
              if (f)
                x_new_focus_frame (dpyinfo, f);
-#ifdef USE_X_TOOLKIT
-             goto OTHER;
-#endif /* USE_X_TOOLKIT */
-             break;
 
+#ifdef HAVE_X_I18N
+             if (f && FRAME_XIC (f))
+               XSetICFocus (FRAME_XIC (f));
+#endif
+
+             goto OTHER;
 
            case LeaveNotify:
              f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
@@ -3821,10 +3858,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                        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 (dpyinfo, event.xfocus.window);
@@ -3833,10 +3867,13 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                dpyinfo->x_focus_event_frame = 0;
              if (f && f == dpyinfo->x_focus_frame)
                x_new_focus_frame (dpyinfo, 0);
-#ifdef USE_X_TOOLKIT
+
+#ifdef HAVE_X_I18N
+             if (f && FRAME_XIC (f))
+               XUnsetICFocus (FRAME_XIC (f));
+#endif
+
              goto OTHER;
-#endif /* USE_X_TOOLKIT */
-             break;
 
            case MotionNotify:
              {
@@ -3860,10 +3897,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                    clear_mouse_face (dpyinfo);
                  }
              }
-#ifdef USE_X_TOOLKIT
              goto OTHER;
-#endif /* USE_X_TOOLKIT */
-             break;
 
            case ConfigureNotify:
              f = x_any_window_to_frame (dpyinfo, event.xconfigure.window);
@@ -3952,11 +3986,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
 /* #endif */
                  }
                }
-#ifdef USE_X_TOOLKIT
              goto OTHER;
-#else
-             break;
-#endif
 
            case ButtonPress:
            case ButtonRelease:
@@ -4013,7 +4043,14 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                   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)
+               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
@@ -4051,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;
@@ -4359,6 +4393,11 @@ 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)
@@ -4476,14 +4515,13 @@ x_connection_closed (display, error_message)
   struct x_display_info *dpyinfo = x_display_info_for_display (display);
   Lisp_Object frame, tail;
 
-  /* Whatever we were in the middle of, we are going to throw out of it,
-     so reassure various things that have error checks about being
-     called with input blocked.  */
-  TOTALLY_UNBLOCK_INPUT;
-
   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)
@@ -4511,7 +4549,8 @@ x_connection_closed (display, error_message)
        Fdelete_frame (frame, Qt);
       }
 
-  x_delete_display (dpyinfo);
+  if (dpyinfo)
+    x_delete_display (dpyinfo);
 
   if (x_display_list == 0)
     {
@@ -4530,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.  */
@@ -4557,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);
 }
@@ -4576,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
@@ -4868,6 +4948,9 @@ 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;
 {
@@ -4905,17 +4988,18 @@ x_calc_absolute_position (f)
      position that fits on the screen.  */
   if (flags & XNegative)
     f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
-                             - 2 * f->output_data.x->border_width - win_x
-                             - PIXEL_WIDTH (f)
-                             + f->output_data.x->left_pos);
+                                 - 2 * f->output_data.x->border_width - win_x
+                                 - PIXEL_WIDTH (f)
+                                 + f->output_data.x->left_pos);
 
   if (flags & YNegative)
+    /* We used to subtract f->output_data.x->menubar_height here
+       in the toolkit case, but PIXEL_HEIGHT already includes that.  */
     f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
-                            - 2 * f->output_data.x->border_width - win_y
-                            - PIXEL_HEIGHT (f)
-                            - (FRAME_EXTERNAL_MENU_BAR (f)
-                               ? f->output_data.x->menubar_height : 0)
-                            + f->output_data.x->top_pos);
+                                - 2 * f->output_data.x->border_width - win_y
+                                - PIXEL_HEIGHT (f)
+                                + f->output_data.x->top_pos);
+
   /* The left_pos and top_pos
      are now relative to the top and left screen edges,
      so the flags should correspond.  */
@@ -4983,9 +5067,12 @@ 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.
@@ -4997,12 +5084,9 @@ x_set_window_size (f, change_gravity, cols, rows)
     f->output_data.x->widget->core.x = xpos;
     f->output_data.x->widget->core.y = ypos;
   }
-  UNBLOCK_INPUT;
 
 #else /* not USE_X_TOOLKIT */
 
-  BLOCK_INPUT;
-
   check_frame_size (f, &rows, &cols);
   f->output_data.x->vertical_scroll_bar_extra
     = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
@@ -5034,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)
@@ -5042,15 +5136,19 @@ 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.  */
@@ -5157,11 +5255,11 @@ x_lower_frame (f)
 }
 
 static void
-XTframe_raise_lower (f, raise)
+XTframe_raise_lower (f, raise_flag)
      FRAME_PTR f;
-     int raise;
+     int raise_flag;
 {
-  if (raise)
+  if (raise_flag)
     x_raise_frame (f);
   else
     x_lower_frame (f);
@@ -5366,6 +5464,8 @@ x_iconify_frame (f)
 
   BLOCK_INPUT;
 
+  FRAME_SAMPLE_VISIBILITY (f);
+
   type = x_icon_type (f);
   if (!NILP (type))
     x_bitmap_icon (f, type);
@@ -5453,16 +5553,28 @@ x_destroy_window (f)
 
   BLOCK_INPUT;
 
-  if (f->output_data.x->icon_desc != 0)
-    XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
-  XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
+  /* If a display connection is dead, don't try sending more
+     commands to the X server.  */
+  if (dpyinfo->display != 0)
+    {
+      if (f->output_data.x->icon_desc != 0)
+       XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
+#ifdef HAVE_X_I18N
+      if (FRAME_XIM (f))
+       {
+         XDestroyIC (FRAME_XIC (f));
+         XCloseIM (FRAME_XIM (f));
+       }
+#endif
+      XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
 #ifdef USE_X_TOOLKIT
-  XtDestroyWidget (f->output_data.x->widget);
-  free_frame_menubar (f);
+      XtDestroyWidget (f->output_data.x->widget);
+      free_frame_menubar (f);
 #endif /* USE_X_TOOLKIT */
 
-  free_frame_faces (f);
-  XFlush (FRAME_X_DISPLAY (f));
+      free_frame_faces (f);
+      XFlush (FRAME_X_DISPLAY (f));
+    }
 
   xfree (f->output_data.x);
   f->output_data.x = 0;
@@ -5673,7 +5785,20 @@ x_wm_set_icon_pixmap (f, pixmap_id)
       f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
     }
   else
-    f->output_data.x->wm_hints.icon_pixmap = None;
+    {
+      /* 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
+    }
 
   f->output_data.x->wm_hints.flags |= IconPixmapHint;
   XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
@@ -5762,6 +5887,10 @@ x_term_init (display_name, xrm_option, resource_name)
       x_initialized = 1;
     }
 
+#ifdef HAVE_X_I18N
+  setlocale (LC_ALL, "");
+#endif
+
 #ifdef USE_X_TOOLKIT
   /* weiner@footloose.sps.mot.com reports that this causes
      errors with X11R5:
@@ -6027,10 +6156,11 @@ 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
+#endif
 #ifdef MULTI_KBOARD
   if (--dpyinfo->kboard->reference_count == 0)
     delete_kboard (dpyinfo->kboard);
@@ -6113,4 +6243,49 @@ syms_of_xterm ()
   staticpro (&Qvendor_specific_keysyms);
   Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
 }
-#endif /* ! defined (HAVE_X_WINDOWS) */
+\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 */
+}
+
+/* Don't put any additional functions here!  */
+
+#endif /* not HAVE_X_WINDOWS */