]> code.delx.au - gnu-emacs/blobdiff - src/xterm.c
(Version, mh-version): Update for release 8.0.
[gnu-emacs] / src / xterm.c
index e9b1ff3aac4ac92715ee4d0e77e709de22abeab6..ba51dbb8f55e7066e895889fe4e9aeaadab507eb 100644 (file)
@@ -1,6 +1,6 @@
 /* X Communication module for terminals which understand the X protocol.
    Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-     2002, 2003, 2004, 2005  Free Software Foundation, Inc.
+                 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -16,8 +16,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, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 /* New display code by Gerd Moellmann <gerd@gnu.org>.  */
 /* Xt features made by Fred Pierresteguy.  */
@@ -249,6 +249,7 @@ static unsigned long ignore_next_mouse_click_timeout;
 /* Where the mouse was last time we reported a mouse event.  */
 
 static XRectangle last_mouse_glyph;
+static FRAME_PTR last_mouse_glyph_frame;
 static Lisp_Object last_mouse_press_frame;
 
 /* The scroll bar in which the last X motion event occurred.
@@ -321,11 +322,10 @@ static void x_set_window_size_1 P_ ((struct frame *, int, int, int));
 static const XColor *x_color_cells P_ ((Display *, int *));
 static void x_update_window_end P_ ((struct window *, int, int));
 void x_delete_display P_ ((struct x_display_info *));
-static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
-                                               unsigned));
+
 static int x_io_error_quitter P_ ((Display *));
-int x_catch_errors P_ ((Display *));
-void x_uncatch_errors P_ ((Display *, int));
+void x_catch_errors P_ ((Display *));
+void x_uncatch_errors P_ ((void));
 void x_lower_frame P_ ((struct frame *));
 void x_scroll_bar_clear P_ ((struct frame *));
 int x_had_errors_p P_ ((Display *));
@@ -535,6 +535,12 @@ x_draw_vertical_window_border (w, x, y0, y1)
      int x, y0, y1;
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
+  struct face *face;
+
+  face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
+  if (face)
+    XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
+                   face->foreground);
 
   XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
             f->output_data.x->normal_gc, x, y0, x, y1);
@@ -904,6 +910,7 @@ x_encode_char (c, char2b, font_info, two_byte_p)
       /* It's a program.  */
       struct ccl_program *ccl = font_info->font_encoder;
 
+      check_ccl_update (ccl);
       if (CHARSET_DIMENSION (charset) == 1)
        {
          ccl->reg[0] = charset;
@@ -1292,7 +1299,7 @@ x_draw_glyph_string_foreground (s)
         XDrawImageString is usually faster than XDrawString.)  Always
         use XDrawImageString when drawing the cursor so that there is
         no chance that characters under a box cursor are invisible.  */
-      if (s->for_overlaps_p
+      if (s->for_overlaps
          || (s->background_filled_p && s->hl != DRAW_CURSOR))
        {
          /* Draw characters with 16-bit or 8-bit functions.  */
@@ -2597,7 +2604,7 @@ x_draw_glyph_string (s)
   /* If S draws into the background of its successor, draw the
      background of the successor first so that S can draw into it.
      This makes S->next use XDrawString instead of XDrawImageString.  */
-  if (s->next && s->right_overhang && !s->for_overlaps_p)
+  if (s->next && s->right_overhang && !s->for_overlaps)
     {
       xassert (s->next->img == NULL);
       x_set_glyph_string_gc (s->next);
@@ -2610,7 +2617,7 @@ x_draw_glyph_string (s)
 
   /* Draw relief (if any) in advance for char/composition so that the
      glyph string can be drawn over it.  */
-  if (!s->for_overlaps_p
+  if (!s->for_overlaps
       && s->face->box != FACE_NO_BOX
       && (s->first_glyph->type == CHAR_GLYPH
          || s->first_glyph->type == COMPOSITE_GLYPH))
@@ -2636,7 +2643,7 @@ x_draw_glyph_string (s)
       break;
 
     case CHAR_GLYPH:
-      if (s->for_overlaps_p)
+      if (s->for_overlaps)
        s->background_filled_p = 1;
       else
        x_draw_glyph_string_background (s, 0);
@@ -2644,7 +2651,7 @@ x_draw_glyph_string (s)
       break;
 
     case COMPOSITE_GLYPH:
-      if (s->for_overlaps_p || s->gidx > 0)
+      if (s->for_overlaps || s->gidx > 0)
        s->background_filled_p = 1;
       else
        x_draw_glyph_string_background (s, 1);
@@ -2655,7 +2662,7 @@ x_draw_glyph_string (s)
       abort ();
     }
 
-  if (!s->for_overlaps_p)
+  if (!s->for_overlaps)
     {
       /* Draw underline.  */
       if (s->face->underline_p)
@@ -3456,7 +3463,7 @@ x_find_modifier_meanings (dpyinfo)
 /* Convert between the modifier bits X uses and the modifier bits
    Emacs uses.  */
 
-static unsigned int
+unsigned int
 x_x_to_emacs_modifiers (dpyinfo, state)
      struct x_display_info *dpyinfo;
      unsigned int state;
@@ -3575,7 +3582,7 @@ construct_mouse_click (result, event, f)
 static XMotionEvent last_mouse_motion_event;
 static Lisp_Object last_mouse_motion_frame;
 
-static void
+static int
 note_mouse_movement (frame, event)
      FRAME_PTR frame;
      XMotionEvent *event;
@@ -3584,23 +3591,36 @@ note_mouse_movement (frame, event)
   last_mouse_motion_event = *event;
   XSETFRAME (last_mouse_motion_frame, frame);
 
+  if (!FRAME_X_OUTPUT (frame))
+    return 0;
+
   if (event->window != FRAME_X_WINDOW (frame))
     {
       frame->mouse_moved = 1;
       last_mouse_scroll_bar = Qnil;
       note_mouse_highlight (frame, -1, -1);
+      last_mouse_glyph_frame = 0;
+      return 1;
     }
 
+
   /* Has the mouse moved off the glyph it was on at the last sighting?  */
-  else if (event->x < last_mouse_glyph.x
-          || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
-          || event->y < last_mouse_glyph.y
-          || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
+  if (frame != last_mouse_glyph_frame
+      || event->x < last_mouse_glyph.x
+      || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
+      || event->y < last_mouse_glyph.y
+      || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
     {
       frame->mouse_moved = 1;
       last_mouse_scroll_bar = Qnil;
       note_mouse_highlight (frame, event->x, event->y);
+      /* Remember which glyph we're now on.  */
+      remember_mouse_glyph (frame, event->x, event->y, &last_mouse_glyph);
+      last_mouse_glyph_frame = frame;
+      return 1;
     }
+
+  return 0;
 }
 
 \f
@@ -3619,56 +3639,6 @@ redo_mouse_highlight ()
 }
 
 
-static int glyph_rect P_ ((struct frame *f, int, int, XRectangle *));
-
-
-/* Try to determine frame pixel position and size of the glyph under
-   frame pixel coordinates X/Y on frame F .  Return the position and
-   size in *RECT.  Value is non-zero if we could compute these
-   values.  */
-
-static int
-glyph_rect (f, x, y, rect)
-     struct frame *f;
-     int x, y;
-     XRectangle *rect;
-{
-  Lisp_Object window;
-  struct window *w;
-  struct glyph_row *r, *end_row;
-
-  window = window_from_coordinates (f, x, y, 0, &x, &y, 0);
-  if (NILP (window))
-    return 0;
-
-  w = XWINDOW (window);
-  r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
-  end_row = r + w->current_matrix->nrows - 1;
-
-  for (; r < end_row && r->enabled_p; ++r)
-    {
-      if (r->y >= y)
-       {
-         struct glyph *g = r->glyphs[TEXT_AREA];
-         struct glyph *end = g + r->used[TEXT_AREA];
-         int gx = r->x;
-         while (g < end && gx < x)
-           gx += g->pixel_width, ++g;
-         if (g < end)
-           {
-             rect->width = g->pixel_width;
-             rect->height = r->height;
-             rect->x = WINDOW_TO_FRAME_PIXEL_X (w, gx);
-             rect->y = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
-             return 1;
-           }
-         break;
-       }
-    }
-
-  return 0;
-}
-
 
 /* Return the current position of the mouse.
    *FP should be a frame which indicates which display to ask about.
@@ -3749,7 +3719,6 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
        Window win, child;
        int win_x, win_y;
        int parent_x = 0, parent_y = 0;
-       int count;
 
        win = root;
 
@@ -3757,7 +3726,7 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
           structure is changing at the same time this function
           is running.  So at least we must not crash from them.  */
 
-       count = x_catch_errors (FRAME_X_DISPLAY (*fp));
+       x_catch_errors (FRAME_X_DISPLAY (*fp));
 
        if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
            && FRAME_LIVE_P (last_mouse_frame))
@@ -3826,7 +3795,7 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
        if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
          f1 = 0;
 
-       x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
+       x_uncatch_errors ();
 
        /* If not, is it one of our scroll bars?  */
        if (! f1)
@@ -3856,32 +3825,8 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
               on it, i.e. into the same rectangles that matrices on
               the frame are divided into.  */
 
-           int width, height, gx, gy;
-           XRectangle rect;
-
-           if (glyph_rect (f1, win_x, win_y, &rect))
-             last_mouse_glyph = rect;
-           else
-             {
-               width = FRAME_SMALLEST_CHAR_WIDTH (f1);
-               height = FRAME_SMALLEST_FONT_HEIGHT (f1);
-               gx = win_x;
-               gy = win_y;
-
-               /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
-                  round down even for negative values.  */
-               if (gx < 0)
-                 gx -= width - 1;
-               if (gy < 0)
-                 gy -= height - 1;
-               gx = (gx + width - 1) / width * width;
-               gy = (gy + height - 1) / height * height;
-
-               last_mouse_glyph.width  = width;
-               last_mouse_glyph.height = height;
-               last_mouse_glyph.x = gx;
-               last_mouse_glyph.y = gy;
-             }
+           remember_mouse_glyph (f1, win_x, win_y, &last_mouse_glyph);
+           last_mouse_glyph_frame = f1;
 
            *bar_window = Qnil;
            *part = 0;
@@ -4017,8 +3962,6 @@ static Boolean xaw3d_arrow_scroll;
 
 static Boolean xaw3d_pick_top;
 
-extern void set_vertical_scroll_bar P_ ((struct window *));
-
 /* Action hook installed via XtAppAddActionHook when toolkit scroll
    bars are used..  The hook is responsible for detecting when
    the user ends an interaction with the scroll bar, and generates
@@ -4588,11 +4531,14 @@ x_create_toolkit_scroll_bar (f, bar)
     char *initial = "";
     char *val = initial;
     XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
+#ifdef XtNarrowScrollbars
+                  XtNarrowScrollbars, (XtPointer) &xaw3d_arrow_scroll,
+#endif
                   XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
-    if (val == initial)
+    if (xaw3d_arrow_scroll || val == initial)
       {        /* ARROW_SCROLL */
        xaw3d_arrow_scroll = True;
-       /* Isn't that just a personal preference ?   -sm */
+       /* Isn't that just a personal preference ?   --Stef */
        XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
       }
   }
@@ -5766,7 +5712,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
                     Display *d = event.xclient.display;
                     /* Catch and ignore errors, in case window has been
                        iconified by a window manager such as GWM.  */
-                    int count = x_catch_errors (d);
+                    x_catch_errors (d);
                     XSetInputFocus (d, event.xclient.window,
                                     /* The ICCCM says this is
                                        the only valid choice.  */
@@ -5775,7 +5721,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
                     /* This is needed to detect the error
                        if there is an error.  */
                     XSync (d, False);
-                    x_uncatch_errors (d, count);
+                    x_uncatch_errors ();
                   }
                 /* Not certain about handling scroll bars here */
 #endif /* 0 */
@@ -6137,7 +6083,8 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
 
       f = x_any_window_to_frame (dpyinfo, event.xkey.window);
 
-      if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
+      if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
+         && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
         {
           clear_mouse_face (dpyinfo);
           dpyinfo->mouse_face_hidden = 1;
@@ -6223,7 +6170,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
               if (status_return == XBufferOverflow)
                 {
                   copy_bufsiz = nbytes + 1;
-                  copy_bufptr = (char *) alloca (copy_bufsiz);
+                  copy_bufptr = (unsigned char *) alloca (copy_bufsiz);
                   nbytes = XmbLookupString (FRAME_XIC (f),
                                             &event.xkey, copy_bufptr,
                                             copy_bufsiz, &keysym,
@@ -6241,7 +6188,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
                   if (status_return == XBufferOverflow)
                     {
                       copy_bufsiz = nbytes + 1;
-                      copy_bufptr = (char *) alloca (copy_bufsiz);
+                      copy_bufptr = (unsigned char *) alloca (copy_bufsiz);
                       nbytes = Xutf8LookupString (FRAME_XIC (f),
                                                   &event.xkey,
                                                   copy_bufptr,
@@ -6277,6 +6224,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
           if (compose_status.chars_matched > 0 && nbytes == 0)
             break;
 
+          bzero (&compose_status, sizeof (compose_status));
           orig_keysym = keysym;
 
          /* Common for all keysym input events.  */
@@ -6295,6 +6243,44 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
              goto done_keysym;
            }
 
+         /* Keysyms directly mapped to supported Unicode characters.  */
+         if ((keysym >= 0x01000000 && keysym <= 0x010033ff)
+             || (keysym >= 0x0100e000 && keysym <= 0x0100ffff))
+           {
+             int code = keysym & 0xFFFF, charset_id, c1, c2;
+
+             if (code < 0x80)
+               {
+                 inev.ie.kind = ASCII_KEYSTROKE_EVENT;
+                 inev.ie.code = code;
+               }
+             else if (code < 0x100)
+               {
+                 if (code < 0xA0)
+                   charset_id = CHARSET_8_BIT_CONTROL;
+                 else
+                   charset_id = charset_latin_iso8859_1;
+                 inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+                 inev.ie.code = MAKE_CHAR (charset_id, code, 0);
+               }
+             else
+               {
+                 if (code < 0x2500)
+                   charset_id = charset_mule_unicode_0100_24ff,
+                     code -= 0x100;
+                 else if (code < 0xE000)
+                   charset_id = charset_mule_unicode_2500_33ff,
+                     code -= 0x2500;
+                 else
+                   charset_id = charset_mule_unicode_e000_ffff,
+                     code -= 0xE000;
+                 c1 = (code / 96) + 32, c2 = (code % 96) + 32;
+                 inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+                 inev.ie.code = MAKE_CHAR (charset_id, c1, c2);
+               }
+             goto done_keysym;
+           }
+
          /* Now non-ASCII.  */
          if (HASH_TABLE_P (Vx_keysym_table)
              && (NATNUMP (c = Fgethash (make_number (keysym),
@@ -6511,6 +6497,12 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
         so update things that depend on mouse position.  */
       if (f && !f->output_data.x->hourglass_p)
        note_mouse_movement (f, &event.xmotion);
+#ifdef USE_GTK
+      /* We may get an EnterNotify on the buttons in the toolbar.  In that
+         case we moved out of any highlighted area and need to note this.  */
+      if (!f && last_mouse_glyph_frame)
+        note_mouse_movement (last_mouse_glyph_frame, &event);
+#endif
       goto OTHER;
 
     case FocusIn:
@@ -6538,6 +6530,11 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
           if (any_help_event_p)
            do_help = -1;
         }
+#ifdef USE_GTK
+      /* See comment in EnterNotify above */
+      else if (last_mouse_glyph_frame)
+        note_mouse_movement (last_mouse_glyph_frame, &event);
+#endif
       goto OTHER;
 
     case FocusOut:
@@ -6547,8 +6544,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
     case MotionNotify:
       {
         previous_help_echo_string = help_echo_string;
-        help_echo_string = help_echo_object = help_echo_window = Qnil;
-        help_echo_pos = -1;
+        help_echo_string = Qnil;
 
         if (dpyinfo->grabbed && last_mouse_frame
             && FRAME_LIVE_P (last_mouse_frame))
@@ -6587,7 +6583,8 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
 
                 last_window=window;
               }
-            note_mouse_movement (f, &event.xmotion);
+            if (!note_mouse_movement (f, &event.xmotion))
+             help_echo_string = previous_help_echo_string;
           }
         else
           {
@@ -6696,6 +6693,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
         int tool_bar_p = 0;
 
         bzero (&compose_status, sizeof (compose_status));
+       last_mouse_glyph_frame = 0;
 
         if (dpyinfo->grabbed
             && last_mouse_frame
@@ -6741,13 +6739,13 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
                              && (int)(event.xbutton.time - ignore_next_mouse_click_timeout) > 0)
                            {
                              ignore_next_mouse_click_timeout = 0;
-                             construct_mouse_click (&inev.ie, &event, f);
+                             construct_mouse_click (&inev.ie, &event.xbutton, f);
                            }
                          if (event.type == ButtonRelease)
                            ignore_next_mouse_click_timeout = 0;
                        }
                      else
-                       construct_mouse_click (&inev.ie, &event, f);
+                       construct_mouse_click (&inev.ie, &event.xbutton, f);
                    }
                 }
           }
@@ -6775,12 +6773,6 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
           {
             dpyinfo->grabbed |= (1 << event.xbutton.button);
             last_mouse_frame = f;
-            /* Ignore any mouse motion that happened
-               before this event; any subsequent mouse-movement
-               Emacs events should reflect only motion after
-               the ButtonPress.  */
-            if (f != 0)
-              f->mouse_moved = 0;
 
             if (!tool_bar_p)
               last_tool_bar_item = -1;
@@ -6788,6 +6780,12 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
         else
           dpyinfo->grabbed &= ~(1 << event.xbutton.button);
 
+       /* Ignore any mouse motion that happened before this event;
+          any subsequent mouse-movement Emacs events should reflect
+          only motion after the ButtonPress/Release.  */
+       if (f != 0)
+         f->mouse_moved = 0;
+
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
         f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
         /* For a down-event in the menu bar,
@@ -7181,7 +7179,7 @@ x_draw_hollow_cursor (w, row)
 
   /* Set clipping, draw the rectangle, and reset clipping again.  */
   x_clip_to_row (w, row, TEXT_AREA, gc);
-  XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
+  XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h - 1);
   XSetClipMask (dpy, gc, None);
 }
 
@@ -7394,10 +7392,30 @@ x_bitmap_icon (f, file)
       /* Create the GNU bitmap and mask if necessary.  */
       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);
-         x_create_bitmap_mask (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
+         int rc = -1;
+
+#if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
+#ifdef USE_GTK
+         if (xg_set_icon_from_xpm_data (f, gnu_xpm_bits))
+           return 0;
+#else
+         rc = x_create_bitmap_from_xpm_data (f, gnu_xpm_bits);
+         if (rc != -1)
+           FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id = rc;
+#endif /* USE_GTK */
+#endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
+
+         /* If all else fails, use the (black and white) xbm image. */
+         if (rc == -1)
+           {
+             rc = x_create_bitmap_from_data (f, gnu_xbm_bits,
+                                             gnu_xbm_width, gnu_xbm_height);
+             if (rc == -1)
+               return 1;
+
+             FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id = rc;
+             x_create_bitmap_mask (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
+           }
        }
 
       /* The first time we create the GNU bitmap and mask,
@@ -7451,9 +7469,18 @@ x_text_icon (f, icon_name)
 #define X_ERROR_MESSAGE_SIZE 200
 
 /* If non-nil, this should be a string.
-   It means catch X errors  and store the error message in this string.  */
+   It means catch X errors  and store the error message in this string.
 
-static Lisp_Object x_error_message_string;
+   The reason we use a stack is that x_catch_error/x_uncatch_error can
+   be called from a signal handler.
+*/
+
+struct x_error_message_stack {
+  char string[X_ERROR_MESSAGE_SIZE];
+  Display *dpy;
+  struct x_error_message_stack *prev;
+};
+static struct x_error_message_stack *x_error_message;
 
 /* An X error handler which stores the error message in
    x_error_message_string.  This is called from x_error_handler if
@@ -7465,7 +7492,7 @@ x_error_catcher (display, error)
      XErrorEvent *error;
 {
   XGetErrorText (display, error->error_code,
-                SDATA (x_error_message_string),
+                x_error_message->string,
                 X_ERROR_MESSAGE_SIZE);
 }
 
@@ -7483,47 +7510,41 @@ x_error_catcher (display, error)
    Calling x_uncatch_errors resumes the normal error handling.  */
 
 void x_check_errors ();
-static Lisp_Object x_catch_errors_unwind ();
 
-int
+void
 x_catch_errors (dpy)
      Display *dpy;
 {
-  int count = SPECPDL_INDEX ();
+  struct x_error_message_stack *data = xmalloc (sizeof (*data));
 
   /* Make sure any errors from previous requests have been dealt with.  */
   XSync (dpy, False);
 
-  record_unwind_protect (x_catch_errors_unwind,
-                        Fcons (make_save_value (dpy, 0),
-                               x_error_message_string));
-
-  x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
-  SSET (x_error_message_string, 0, 0);
-
-  return count;
+  data->dpy = dpy;
+  data->string[0] = 0;
+  data->prev = x_error_message;
+  x_error_message = data;
 }
 
-/* Unbind the binding that we made to check for X errors.  */
+/* Undo the last x_catch_errors call.
+   DPY should be the display that was passed to x_catch_errors.  */
 
-static Lisp_Object
-x_catch_errors_unwind (old_val)
-     Lisp_Object old_val;
+void
+x_uncatch_errors ()
 {
-  Lisp_Object first = XCAR (old_val);
-  Display *dpy = XSAVE_VALUE (first)->pointer;
+  struct x_error_message_stack *tmp;
+
+  BLOCK_INPUT;
 
   /* The display may have been closed before this function is called.
      Check if it is still open before calling XSync.  */
-  if (x_display_info_for_display (dpy) != 0)
-    {
-      BLOCK_INPUT;
-      XSync (dpy, False);
-      UNBLOCK_INPUT;
-    }
+  if (x_display_info_for_display (x_error_message->dpy) != 0)
+    XSync (x_error_message->dpy, False);
 
-  x_error_message_string = XCDR (old_val);
-  return Qnil;
+  tmp = x_error_message;
+  x_error_message = x_error_message->prev;
+  xfree (tmp);
+  UNBLOCK_INPUT;
 }
 
 /* If any X protocol errors have arrived since the last call to
@@ -7538,8 +7559,13 @@ x_check_errors (dpy, format)
   /* Make sure to catch any errors incurred so far.  */
   XSync (dpy, False);
 
-  if (SREF (x_error_message_string, 0))
-    error (format, SDATA (x_error_message_string));
+  if (x_error_message->string[0])
+    {
+      char string[X_ERROR_MESSAGE_SIZE];
+      bcopy (x_error_message->string, string, X_ERROR_MESSAGE_SIZE);
+      x_uncatch_errors ();
+      error (format, string);
+    }
 }
 
 /* Nonzero if we had any X protocol errors
@@ -7552,7 +7578,7 @@ x_had_errors_p (dpy)
   /* Make sure to catch any errors incurred so far.  */
   XSync (dpy, False);
 
-  return SREF (x_error_message_string, 0) != 0;
+  return x_error_message->string[0] != 0;
 }
 
 /* Forget about any errors we have had, since we did x_catch_errors on DPY.  */
@@ -7561,20 +7587,24 @@ void
 x_clear_errors (dpy)
      Display *dpy;
 {
-  SSET (x_error_message_string, 0, 0);
+  x_error_message->string[0] = 0;
 }
 
-/* Stop catching X protocol errors and let them make Emacs die.
-   DPY should be the display that was passed to x_catch_errors.
-   COUNT should be the value that was returned by
-   the corresponding call to x_catch_errors.  */
+/* Close off all unclosed x_catch_errors calls.  */
 
 void
-x_uncatch_errors (dpy, count)
-     Display *dpy;
-     int count;
+x_fully_uncatch_errors ()
+{
+  while (x_error_message)
+    x_uncatch_errors ();
+}
+
+/* Nonzero if x_catch_errors has been done and not yet canceled.  */
+
+int
+x_catching_errors ()
 {
-  unbind_to (count, Qnil);
+  return x_error_message != 0;
 }
 
 #if 0
@@ -7633,7 +7663,6 @@ x_connection_closed (dpy, error_message)
 {
   struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
   Lisp_Object frame, tail;
-  int count;
 
   error_msg = (char *) alloca (strlen (error_message) + 1);
   strcpy (error_msg, error_message);
@@ -7643,7 +7672,7 @@ x_connection_closed (dpy, error_message)
      below.  Otherwise, we might end up with printing ``can't find per
      display information'' in the recursive call instead of printing
      the original message here.  */
-  count = x_catch_errors (dpy);
+  x_catch_errors (dpy);
 
   /* We have to close the display to inform Xt that it doesn't
      exist anymore.  If we don't, Xt will continue to wait for
@@ -7711,7 +7740,7 @@ x_connection_closed (dpy, error_message)
   if (dpyinfo)
     x_delete_display (dpyinfo);
 
-  x_uncatch_errors (dpy, count);
+  x_uncatch_errors ();
 
   if (x_display_list == 0)
     {
@@ -7743,7 +7772,7 @@ x_error_handler (display, error)
      Display *display;
      XErrorEvent *error;
 {
-  if (! NILP (x_error_message_string))
+  if (x_error_message)
     x_error_catcher (display, error);
   else
     x_error_quitter (display, error);
@@ -7764,8 +7793,8 @@ x_error_handler (display, error)
 
 /* Some versions of GNU/Linux define noinline in their headers.  */
 
-#ifdef noinclude
-#undef noinclude
+#ifdef noinline
+#undef noinline
 #endif
 
 /* On older GCC versions, just putting x_error_quitter
@@ -8127,7 +8156,6 @@ void
 x_calc_absolute_position (f)
      struct frame *f;
 {
-  int win_x = 0, win_y = 0;
   int flags = f->size_hint_flags;
 
   /* We have nothing to do if the current position
@@ -9239,7 +9267,14 @@ x_wm_set_icon_pixmap (f, pixmap_id)
 #endif
     }
 
-#ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state.  */
+
+#ifdef USE_GTK
+  {
+    xg_set_frame_icon (f, icon_pixmap, icon_mask);
+    return;
+  }
+
+#elif defined (USE_X_TOOLKIT) /* same as in x_wm_set_window_state.  */
 
   {
     Arg al[1];
@@ -9249,12 +9284,12 @@ x_wm_set_icon_pixmap (f, pixmap_id)
     XtSetValues (f->output_data.x->widget, al, 1);
   }
 
-#else /* not USE_X_TOOLKIT */
+#else /* not USE_X_TOOLKIT && not USE_GTK */
 
   f->output_data.x->wm_hints.flags |= (IconPixmapHint | IconMaskHint);
   XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
 
-#endif /* not USE_X_TOOLKIT */
+#endif /* not USE_X_TOOLKIT && not USE_GTK */
 }
 
 void
@@ -9311,7 +9346,6 @@ x_list_fonts (f, pattern, size, maxnames)
     = f ? FRAME_X_DISPLAY_INFO (f) : x_display_list;
   Display *dpy = dpyinfo->display;
   int try_XLoadQueryFont = 0;
-  int count;
   int allow_auto_scaled_font = 0;
 
   if (size < 0)
@@ -9351,7 +9385,7 @@ x_list_fonts (f, pattern, size, maxnames)
       /* At first, put PATTERN in the cache.  */
 
       BLOCK_INPUT;
-      count = x_catch_errors (dpy);
+      x_catch_errors (dpy);
 
       if (try_XLoadQueryFont)
        {
@@ -9432,7 +9466,7 @@ x_list_fonts (f, pattern, size, maxnames)
            }
        }
 
-      x_uncatch_errors (dpy, count);
+      x_uncatch_errors ();
       UNBLOCK_INPUT;
 
       if (names)
@@ -9523,7 +9557,7 @@ x_list_fonts (f, pattern, size, maxnames)
              XFontStruct *thisinfo;
 
              BLOCK_INPUT;
-             count = x_catch_errors (dpy);
+             x_catch_errors (dpy);
              thisinfo = XLoadQueryFont (dpy,
                                         SDATA (XCAR (tem)));
              if (x_had_errors_p (dpy))
@@ -9533,7 +9567,7 @@ x_list_fonts (f, pattern, size, maxnames)
                  thisinfo = NULL;
                  x_clear_errors (dpy);
                }
-             x_uncatch_errors (dpy, count);
+             x_uncatch_errors ();
              UNBLOCK_INPUT;
 
              if (thisinfo)
@@ -9689,7 +9723,6 @@ x_load_font (f, fontname, size)
 {
   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
   Lisp_Object font_names;
-  int count;
 
   /* Get a list of all the fonts that match this name.  Once we
      have a list of matching fonts, we compare them against the fonts
@@ -9728,7 +9761,7 @@ x_load_font (f, fontname, size)
       fontname = (char *) SDATA (XCAR (font_names));
 
     BLOCK_INPUT;
-    count = x_catch_errors (FRAME_X_DISPLAY (f));
+    x_catch_errors (FRAME_X_DISPLAY (f));
     font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
     if (x_had_errors_p (FRAME_X_DISPLAY (f)))
       {
@@ -9737,7 +9770,7 @@ x_load_font (f, fontname, size)
        font = NULL;
        x_clear_errors (FRAME_X_DISPLAY (f));
       }
-    x_uncatch_errors (FRAME_X_DISPLAY (f), count);
+    x_uncatch_errors ();
     UNBLOCK_INPUT;
     if (!font)
       return NULL;
@@ -10007,6 +10040,10 @@ static XrmOptionDescRec emacs_options[] = {
 
 static int x_initialized;
 
+#ifdef HAVE_X_SM
+static int x_session_initialized;
+#endif
+
 #ifdef MULTI_KBOARD
 /* Test whether two display-name strings agree up to the dot that separates
    the screen number from the server number.  */
@@ -10084,6 +10121,21 @@ get_bits_and_offset (mask, bits, offset)
   *bits = nr;
 }
 
+int
+x_display_ok (display)
+    const char * display;
+{
+    int dpy_ok = 1;
+    Display *dpy;
+
+    dpy = XOpenDisplay (display);
+    if (dpy)
+      XCloseDisplay (dpy);
+    else
+      dpy_ok = 0;
+    return dpy_ok;
+}
+
 struct x_display_info *
 x_term_init (display_name, xrm_option, resource_name)
      Lisp_Object display_name;
@@ -10153,18 +10205,14 @@ x_term_init (display_name, xrm_option, resource_name)
 
         /* Load our own gtkrc if it exists.  */
         {
-          struct gcpro gcpro1, gcpro2;
           char *file = "~/.emacs.d/gtkrc";
           Lisp_Object s, abs_file;
 
-          GCPRO2 (s, abs_file);
           s = make_string (file, strlen (file));
           abs_file = Fexpand_file_name (s, Qnil);
 
           if (! NILP (abs_file) && !NILP (Ffile_readable_p (abs_file)))
             gtk_rc_parse (SDATA (abs_file));
-
-          UNGCPRO;
         }
 
         XSetErrorHandler (x_error_handler);
@@ -10510,7 +10558,6 @@ x_term_init (display_name, xrm_option, resource_name)
     Display *dpy = dpyinfo->display;
     XrmValue d, fr, to;
     Font font;
-    int count;
 
     d.addr = (XPointer)&dpy;
     d.size = sizeof (Display *);
@@ -10518,12 +10565,12 @@ x_term_init (display_name, xrm_option, resource_name)
     fr.size = sizeof (XtDefaultFont);
     to.size = sizeof (Font *);
     to.addr = (XPointer)&font;
-    count = x_catch_errors (dpy);
+    x_catch_errors (dpy);
     if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
       abort ();
     if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
       XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
-    x_uncatch_errors (dpy, count);
+    x_uncatch_errors ();
   }
 #endif
 #endif
@@ -10563,7 +10610,7 @@ x_term_init (display_name, xrm_option, resource_name)
 
 #ifdef HAVE_X_SM
   /* Only do this for the first display.  */
-  if (x_initialized == 1)
+  if (!x_session_initialized++)
     x_session_initialize (dpyinfo);
 #endif
 
@@ -10748,6 +10795,9 @@ x_initialize ()
   last_tool_bar_item = -1;
   any_help_event_p = 0;
   ignore_next_mouse_click_timeout = 0;
+#ifdef HAVE_X_SM
+  x_session_initialized = 0;
+#endif
 
 #ifdef USE_GTK
   current_count = -1;
@@ -10807,8 +10857,7 @@ x_initialize ()
 void
 syms_of_xterm ()
 {
-  staticpro (&x_error_message_string);
-  x_error_message_string = Qnil;
+  x_error_message = NULL;
 
   staticpro (&x_display_name_list);
   x_display_name_list = Qnil;