(free_frame_menubar) [USE_X_TOOLKIT]. New function to destroy the X Widget
[bpt/emacs.git] / src / xterm.c
index e43dba3..ccbb59f 100644 (file)
@@ -25,6 +25,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
    
 */
 
+/* Xt features made by Fred Pierresteguy.  */
+
 #define NEW_SELECTIONS
 
 /* On 4.3 these lose if they come after xterm.h.  */
@@ -33,7 +35,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include <stdio.h>
 #include <signal.h>
 
-#include "config.h"
+#include <config.h>
+
+/* Need syssignal.h for various externs and definitions that may be required
+   by some configurations for calls to signal later in this source file.  */
+#include "syssignal.h"
 
 #ifdef HAVE_X_WINDOWS
 
@@ -86,6 +92,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "buffer.h"
 #include "window.h"
 
+#ifdef USE_X_TOOLKIT
+extern XtAppContext Xt_app_con;
+extern Widget Xt_app_shell;
+#endif /* USE_X_TOOLKIT */
+
 #ifdef HAVE_X11
 #define XMapWindow XMapRaised          /* Raise them when mapping. */
 #else /* ! defined (HAVE_X11) */
@@ -119,7 +130,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #define min(a,b) ((a)<(b) ? (a) : (b))
 #define max(a,b) ((a)>(b) ? (a) : (b))
-
+\f
 /* Nonzero means we must reprint all windows
    because 1) we received an ExposeWindow event
    or 2) we received too many ExposeRegion events to record.
@@ -137,7 +148,7 @@ static int expose_all_icons;
 
 static struct event_queue x_expose_queue;
 
-/* ButtonPressed and ButtonReleased events, when received,
+/* ButtonPress and ButtonReleased events, when received,
    are copied into this queue for later processing.  */
 
 struct event_queue x_mouse_queue;
@@ -215,6 +226,50 @@ static int highlight;
 static int curs_x;
 static int curs_y;
 
+/* Mouse movement.
+
+   In order to avoid asking for motion events and then throwing most
+   of them away or busy-polling the server for mouse positions, we ask
+   the server for pointer motion hints.  This means that we get only
+   one event per group of mouse movements.  "Groups" are delimited by
+   other kinds of events (focus changes and button clicks, for
+   example), or by XQueryPointer calls; when one of these happens, we
+   get another MotionNotify event the next time the mouse moves.  This
+   is at least as efficient as getting motion events when mouse
+   tracking is on, and I suspect only negligibly worse when tracking
+   is off.
+
+   The silly O'Reilly & Associates Nutshell guides barely document
+   pointer motion hints at all (I think you have to infer how they
+   work from an example), and the description of XQueryPointer doesn't
+   mention that calling it causes you to get another motion hint from
+   the server, which is very important.  */
+
+/* Where the mouse was last time we reported a mouse event.  */
+static FRAME_PTR last_mouse_frame;
+static XRectangle last_mouse_glyph;
+
+/* The scroll bar in which the last X motion event occurred.
+
+   If the last X motion event occurred in a scroll bar, we set this
+   so XTmouse_position can know whether to report a scroll bar motion or
+   an ordinary motion.
+
+   If the last X motion event didn't occur in a scroll bar, we set this
+   to Qnil, to tell XTmouse_position to return an ordinary motion event.  */
+static Lisp_Object last_mouse_scroll_bar;
+
+/* Record which buttons are currently pressed. */
+unsigned int x_mouse_grabbed;
+
+/* This is a hack.  We would really prefer that XTmouse_position would
+   return the time associated with the position it returns, but there
+   doesn't seem to be any way to wrest the timestamp from the server
+   along with the position query.  So, we just keep track of the time
+   of the last movement we received, and return that in hopes that
+   it's somewhat accurate.  */
+static Time last_mouse_movement_time;
+
 #ifdef HAVE_X11
 /* `t' if a mouse button is depressed. */
 
@@ -271,6 +326,8 @@ extern Cursor XCreateCursor ();
 extern FONT_TYPE *XOpenFont ();
 
 static void flashback ();
+static void redraw_previous_char ();
+static unsigned int x_x_to_emacs_modifiers ();
 
 #ifndef HAVE_X11
 static void dumpqueue ();
@@ -288,7 +345,7 @@ static int XTclear_end_of_line ();
    of the frame being updated, so that the XT... functions do not
    need to take a frame as argument.  Most of the XT... functions
    should never be called except during an update, the only exceptions
-   being XTcursor_to, XTwrite_char and XTreassert_line_highlight.  */
+   being XTcursor_to, XTwrite_glyphs and XTreassert_line_highlight.  */
 
 extern int mouse_track_top, mouse_track_left, mouse_track_width;
 
@@ -321,10 +378,6 @@ XTupdate_end (f)
 {      
   int mask;
 
-  if (updating_frame == 0
-      || updating_frame != f)
-    abort ();
-
   BLOCK_INPUT;
 #ifndef HAVE_X11
   dumpqueue ();
@@ -411,7 +464,8 @@ XTcursor_to (row, col)
    compute_char_face and compute_glyph_face on everything it puts in
    the display structure, we can assume that the face code on each
    glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
-   to which we can actually apply intern_face.  */
+   to which we can actually apply intern_face.
+   Call this function with input blocked.  */
 
 #if 1
 /* This is the multi-face code.  */
@@ -470,11 +524,11 @@ dumpglyphs (f, left, top, gp, n, hl)
        /* First look at the face of the text itself.  */
        if (cf != 0)
          {
-           /* The face codes on the glyphs must be valid indices into the
-              frame's face table.  */
+           /* It's possible for the display table to specify
+              a face code that is out of range.  Use 0 in that case.  */
            if (cf < 0 || cf >= FRAME_N_COMPUTED_FACES (f)
                || FRAME_COMPUTED_FACES (f) [cf] == 0)
-             abort ();
+             cf = 0;
 
            if (cf == 1)
              face = FRAME_MODE_LINE_FACE (f);
@@ -680,7 +734,9 @@ XTclear_end_of_line (first_unused)
              CHAR_TO_PIXEL_ROW (f, curs_y),
              FONT_WIDTH (f->display.x->font) * (first_unused - curs_x),
              FONT_HEIGHT (f->display.x->font), False);
-             
+#if 0
+  redraw_previous_char (f, curs_x, curs_y);
+#endif
 #else /* ! defined (HAVE_X11) */
   XPixSet (FRAME_X_WINDOW (f),
           CHAR_TO_PIXEL_COL (f, curs_x),
@@ -693,6 +749,39 @@ XTclear_end_of_line (first_unused)
   UNBLOCK_INPUT;
 }
 
+/* Erase the character (if any) at the position just before X, Y in frame F,
+   then redraw it and the character before it.
+   This is necessary when we erase starting at X,
+   in case the character after X overlaps into the one before X.
+   Call this function with input blocked.  */
+
+static void
+redraw_previous_char (f, x, y)
+     FRAME_PTR f;
+     int x, y;
+{
+  /* Erase the character before the new ones, in case
+     what was here before overlaps it.
+     Reoutput that character, and the previous character
+     (in case the previous character overlaps it).  */
+  if (x > 0)
+    {
+      int start_x = x - 2;
+      if (start_x < 0)
+       start_x = 0;
+      XClearArea (x_current_display, FRAME_X_WINDOW (f),
+                 CHAR_TO_PIXEL_COL (f, x - 1),
+                 CHAR_TO_PIXEL_ROW (f, y),
+                 FONT_WIDTH (f->display.x->font),
+                 FONT_HEIGHT (f->display.x->font), False);
+
+      dumpglyphs (f, CHAR_TO_PIXEL_COL (f, start_x),
+                 CHAR_TO_PIXEL_ROW (f, y),
+                 &FRAME_CURRENT_GLYPHS (f)->glyphs[y][start_x],
+                 x - start_x, highlight);
+    }
+}
+
 static
 XTclear_frame ()
 {
@@ -792,7 +881,7 @@ XTflash (f)
       {
        struct timeval wakeup, now;
 
-       gettimeofday (&wakeup, (struct timezone *) 0);
+       EMACS_GET_TIME (wakeup);
 
        /* Compute time to wait until, propagating carry from usecs.  */
        wakeup.tv_usec += 150000;
@@ -804,7 +893,7 @@ XTflash (f)
          {
            struct timeval timeout;
 
-           gettimeofday (&timeout, (struct timezone *)0);
+           EMACS_GET_TIME (timeout);
 
            /* In effect, timeout = wakeup - timeout.
               Break if result would be negative.  */
@@ -832,9 +921,9 @@ XTflash (f)
 /* Make audible bell.  */
 
 #ifdef HAVE_X11
-#define XRINGBELL XBell(x_current_display, 0)
+#define XRINGBELL XBell (x_current_display, 0)
 #else /* ! defined (HAVE_X11) */
-#define XRINGBELL XFeep(0);
+#define XRINGBELL XFeep (0);
 #endif /* ! defined (HAVE_X11) */
 
 XTring_bell ()
@@ -1059,7 +1148,8 @@ static void clear_cursor ();
 /* Output into a rectangle of an X-window (for frame F)
    the characters in f->phys_lines that overlap that rectangle.
    TOP and LEFT are the position of the upper left corner of the rectangle.
-   ROWS and COLS are the size of the rectangle.  */
+   ROWS and COLS are the size of the rectangle.
+   Call this function with input blocked.  */
 
 static void
 dumprectangle (f, left, top, cols, rows)
@@ -1510,6 +1600,30 @@ x_find_modifier_meanings ()
   XFreeModifiermap (mods);
 }
 
+/* Prepare a menu-event in *RESULT for placement in the input queue.  */
+
+static Lisp_Object
+construct_menu_click (result, event, f)
+     struct input_event *result;
+     XButtonEvent *event;
+     struct frame *f;
+{
+  /* Make the event type no_event; we'll change that when we decide
+     otherwise.  */
+  result->kind = mouse_click;
+  XSET (result->code, Lisp_Int, event->button - Button1);
+  result->timestamp = event->time;
+  result->modifiers = (x_x_to_emacs_modifiers (event->state)
+                      | (event->type == ButtonRelease
+                         ? up_modifier 
+                         : down_modifier));
+
+  {
+    XFASTINT (result->x) = event->x;
+    XFASTINT (result->y) = -1;    /* special meaning for menubar */
+    XSET (result->frame_or_window, Lisp_Frame, f);
+  }
+}
 
 /* Convert between the modifier bits X uses and the modifier bits
    Emacs uses.  */
@@ -1558,14 +1672,24 @@ x_is_vendor_fkey (sym)
 
 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
    glyph co-ordinates in (*X, *Y).  Set *BOUNDS to the rectangle
-   that the glyph at X, Y occupies, if BOUNDS != 0.  */
+   that the glyph at X, Y occupies, if BOUNDS != 0.
+   If NOCLIP is nonzero, do not force the value into range.  */
+
 static void
-pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds)
+pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
      FRAME_PTR f;
-     register unsigned int pix_x, pix_y;
+     register int pix_x, pix_y;
      register int *x, *y;
      XRectangle *bounds;
+     int 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;
+  if (pix_y < 0)
+    pix_y -= FONT_HEIGHT ((f)->display.x->font) - 1;
+
   pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
   pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
 
@@ -1577,19 +1701,23 @@ pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds)
       bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
     }
 
-  if (pix_x < 0) pix_x = 0;
-  else if (pix_x > f->width) pix_x = f->width;
-
-  if (pix_y < 0) pix_y = 0;
-  else if (pix_y > f->height) pix_y = f->height;
+  if (!noclip)
+    {
+      if (pix_x < 0)
+       pix_x = 0;
+      else if (pix_x > f->width)
+       pix_x = f->width;
+
+      if (pix_y < 0)
+       pix_y = 0;
+      else if (pix_y > f->height)
+       pix_y = f->height;
+    }
 
   *x = pix_x;
   *y = pix_y;
 }
 
-/* Any buttons grabbed. */
-unsigned int x_mouse_grabbed;
-
 /* Prepare a mouse-event in *RESULT for placement in the input queue.
 
    If the event is a button press, then note that we have grabbed
@@ -1604,7 +1732,7 @@ construct_mouse_click (result, event, f)
   /* Make the event type no_event; we'll change that when we decide
      otherwise.  */
   result->kind = mouse_click;
-  XSET (result->code, Lisp_Int, event->button - Button1);
+  result->code = event->button - Button1;
   result->timestamp = event->time;
   result->modifiers = (x_x_to_emacs_modifiers (event->state)
                       | (event->type == ButtonRelease
@@ -1617,6 +1745,7 @@ construct_mouse_click (result, event, f)
       if (! x_mouse_grabbed)
        Vmouse_depressed = Qt;
       x_mouse_grabbed |= (1 << event->button);
+      last_mouse_frame = f;
     }
   else if (event->type == ButtonRelease)
     {
@@ -1628,55 +1757,13 @@ construct_mouse_click (result, event, f)
   {
     int row, column;
 
-    pixel_to_glyph_coords (f, event->x, event->y, &column, &row, NULL);
+    pixel_to_glyph_coords (f, event->x, event->y, &column, &row, NULL, 0);
     XFASTINT (result->x) = column;
     XFASTINT (result->y) = row;
     XSET (result->frame_or_window, Lisp_Frame, f);
   }
 }
-
-
-/* Mouse movement.  Rah.
-
-   In order to avoid asking for motion events and then throwing most
-   of them away or busy-polling the server for mouse positions, we ask
-   the server for pointer motion hints.  This means that we get only
-   one event per group of mouse movements.  "Groups" are delimited by
-   other kinds of events (focus changes and button clicks, for
-   example), or by XQueryPointer calls; when one of these happens, we
-   get another MotionNotify event the next time the mouse moves.  This
-   is at least as efficient as getting motion events when mouse
-   tracking is on, and I suspect only negligibly worse when tracking
-   is off.
-
-   The silly O'Reilly & Associates Nutshell guides barely document
-   pointer motion hints at all (I think you have to infer how they
-   work from an example), and the description of XQueryPointer doesn't
-   mention that calling it causes you to get another motion hint from
-   the server, which is very important.  */
-
-/* Where the mouse was last time we reported a mouse event.  */
-static FRAME_PTR last_mouse_frame;
-static XRectangle last_mouse_glyph;
-
-/* The scroll bar in which the last X motion event occurred.
-
-   If the last X motion event occurred in a scroll bar, we set this
-   so XTmouse_position can know whether to report a scroll bar motion or
-   an ordinary motion.
-
-   If the last X motion event didn't occur in a scroll bar, we set this
-   to Qnil, to tell XTmouse_position to return an ordinary motion event.  */
-static Lisp_Object last_mouse_scroll_bar;
-
-/* This is a hack.  We would really prefer that XTmouse_position would
-   return the time associated with the position it returns, but there
-   doesn't seem to be any way to wrest the timestamp from the server
-   along with the position query.  So, we just keep track of the time
-   of the last movement we received, and return that in hopes that
-   it's somewhat accurate.  */
-static Time last_mouse_movement_time;
-
+\f
 /* Function to report a mouse movement to the mainstream Emacs code.
    The input handler calls this.
 
@@ -1793,40 +1880,60 @@ XTmouse_position (f, bar_window, part, x, y, time)
        int parent_x, parent_y;
 
        win = root;
-       for (;;)
+
+       if (x_mouse_grabbed)
          {
+           /* If mouse was grabbed on a frame, give coords for that frame
+              even if the mouse is now outside it.  */
            XTranslateCoordinates (x_current_display,
-                              
+
                                   /* From-window, to-window.  */
-                                  root, win,
+                                  root, FRAME_X_WINDOW (last_mouse_frame),
 
                                   /* From-position, to-position.  */
                                   root_x, root_y, &win_x, &win_y,
 
                                   /* Child of win.  */
                                   &child);
+           f1 = last_mouse_frame;
+         }
+       else
+         {
+           while (1)
+             {
+               XTranslateCoordinates (x_current_display,
 
-           if (child == None)
-             break;
+                                      /* From-window, to-window.  */
+                                      root, win,
 
-           win = child;
-           parent_x = win_x;
-           parent_y = win_y;
-         }
+                                      /* From-position, to-position.  */
+                                      root_x, root_y, &win_x, &win_y,
 
-       /* Now we know that:
-          win is the innermost window containing the pointer
-          (XTC says it has no child containing the pointer),
-          win_x and win_y are the pointer's position in it
-          (XTC did this the last time through), and
-          parent_x and parent_y are the pointer's position in win's parent.
-          (They are what win_x and win_y were when win was child.
-          If win is the root window, it has no parent, and
-          parent_{x,y} are invalid, but that's okay, because we'll
-          never use them in that case.)  */
-
-       /* Is win one of our frames?  */
-       f1 = x_window_to_frame (win);
+                                      /* Child of win.  */
+                                      &child);
+
+               if (child == None)
+                 break;
+
+               win = child;
+               parent_x = win_x;
+               parent_y = win_y;
+             }
+
+           /* Now we know that:
+              win is the innermost window containing the pointer
+              (XTC says it has no child containing the pointer),
+              win_x and win_y are the pointer's position in it
+              (XTC did this the last time through), and
+              parent_x and parent_y are the pointer's position in win's parent.
+              (They are what win_x and win_y were when win was child.
+              If win is the root window, it has no parent, and
+              parent_{x,y} are invalid, but that's okay, because we'll
+              never use them in that case.)  */
+
+           /* Is win one of our frames?  */
+           f1 = x_window_to_frame (win);
+         }
       
        /* If not, is it one of our scroll bars?  */
        if (! f1)
@@ -1847,7 +1954,7 @@ XTmouse_position (f, bar_window, part, x, y, time)
               and store all the values.  */
 
            pixel_to_glyph_coords (f1, win_x, win_y, &win_x, &win_y,
-                                  &last_mouse_glyph);
+                                  &last_mouse_glyph, x_mouse_grabbed);
 
            *bar_window = Qnil;
            *part = 0;
@@ -1897,7 +2004,7 @@ x_window_to_scroll_bar (window_id)
           ! GC_NILP (bar) || (bar = condemned,
                               condemned = Qnil,
                               ! GC_NILP (bar));
-          bar = XSCROLL_BAR(bar)->next)
+          bar = XSCROLL_BAR (bar)->next)
        if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
          return XSCROLL_BAR (bar);
     }
@@ -1921,7 +2028,6 @@ x_scroll_bar_create (window, top, left, width, height)
   {
     XSetWindowAttributes a;
     unsigned long mask;
-
     a.background_pixel = frame->display.x->background_pixel;
     a.event_mask = (ButtonPressMask | ButtonReleaseMask
                    | ButtonMotionMask | PointerMotionHintMask
@@ -1930,7 +2036,21 @@ x_scroll_bar_create (window, top, left, width, height)
 
     mask = (CWBackPixel | CWEventMask | CWCursor);
 
-    SET_SCROLL_BAR_X_WINDOW
+#if 0
+
+    ac = 0;
+    XtSetArg (al[ac], XtNx, left); ac++;
+    XtSetArg (al[ac], XtNy, top); ac++;
+    XtSetArg (al[ac], XtNwidth, width); ac++;
+    XtSetArg (al[ac], XtNheight, height); ac++;
+    XtSetArg (al[ac], XtNborderWidth, 0); ac++;
+    sb_widget = XtCreateManagedWidget ("box",
+                                        boxWidgetClass,
+                                        frame->display.x->edit_widget, al, ac);
+   SET_SCROLL_BAR_X_WINDOW
+      (bar, sb_widget->core.window);
+#endif    
+   SET_SCROLL_BAR_X_WINDOW
       (bar, 
        XCreateWindow (x_current_display, FRAME_X_WINDOW (frame),
 
@@ -2326,7 +2446,7 @@ x_scroll_bar_handle_click (bar, event, emacs_event)
     abort ();
 
   emacs_event->kind = scroll_bar_click;
-  XSET (emacs_event->code, Lisp_Int, event->xbutton.button - Button1);
+  emacs_event->code = event->xbutton.button - Button1;
   emacs_event->modifiers =
     (x_x_to_emacs_modifiers (event->xbutton.state)
      | (event->type == ButtonRelease
@@ -2521,6 +2641,45 @@ x_scroll_bar_clear (f)
                0, 0, 0, 0, True);
 }
 
+/* This processes Expose events from the menubar specific X event
+   loop in menubar.c.  This allows to redisplay the frame if necessary
+   when handling menubar or popup items.  */
+
+void
+process_expose_from_menu (event)
+     XEvent event;
+{
+  FRAME_PTR f;
+
+  BLOCK_INPUT;
+
+  f = x_window_to_frame (event.xexpose.window);
+  if (f)
+    {
+      if (f->async_visible == 0)
+       {
+         f->async_visible = 1;
+         f->async_iconified = 0;
+         SET_FRAME_GARBAGED (f);
+       }
+      else
+       {
+         dumprectangle (x_window_to_frame (event.xexpose.window),
+                        event.xexpose.x, event.xexpose.y,
+                        event.xexpose.width, event.xexpose.height);
+       }
+    }
+  else
+    {
+      struct scroll_bar *bar
+       = x_window_to_scroll_bar (event.xexpose.window);
+      
+      if (bar)
+       x_scroll_bar_expose (bar, &event);
+    }
+
+  UNBLOCK_INPUT;
+}
 
 \f
 /* The main X event-reading loop - XTread_socket.  */
@@ -2636,7 +2795,12 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
              {
                if (event.xclient.data.l[0] == Xatom_wm_take_focus)
                  {
+#ifdef USE_X_TOOLKIT
+                   /* f = x_any_window_to_frame (event.xclient.window); */
+                   f = x_window_to_frame (event.xclient.window);
+#else
                    f = x_window_to_frame (event.xclient.window);
+#endif
                    if (f)
                      x_focus_on_frame (f);
                    /* Not certain about handling scroll bars here */
@@ -2657,9 +2821,17 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                    struct frame *f = x_window_to_frame (event.xclient.window);
 
                    if (f)
-                     if (numchars > 0)
-                       {
-                       }
+                     {
+                       if (numchars == 0)
+                         abort ();
+
+                       bufp->kind = delete_window_event;
+                       XSET (bufp->frame_or_window, Lisp_Frame, f);
+                       bufp++;
+
+                       count += 1;
+                       numchars -= 1;
+                     }
                  }
              }
            else if (event.xclient.message_type == Xatom_wm_configure_denied)
@@ -2668,22 +2840,40 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
            else if (event.xclient.message_type == Xatom_wm_window_moved)
              {
                int new_x, new_y;
-
+               struct frame *f = x_window_to_frame (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;
+                 }
              }
          }
          break;
 
 #ifdef NEW_SELECTIONS
        case SelectionNotify:
+#ifdef USE_X_TOOLKIT
+         if (x_window_to_frame (event.xselection.requestor))
+           x_handle_selection_notify (&event);
+         else
+           goto OTHER;
+#else /* not USE_X_TOOLKIT */
          x_handle_selection_notify (&event);
+#endif /* not USE_X_TOOLKIT */
          break;
-#endif
+#endif /* NEW_SELECTIONS */
 
        case SelectionClear:    /* Someone has grabbed ownership. */
 #ifdef NEW_SELECTIONS
          {
+#ifdef USE_X_TOOLKIT
+         if (x_window_to_frame (event.xselectionclear.window))
+           {
+#endif /* USE_X_TOOLKIT */
            XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
 
            if (numchars == 0)
@@ -2697,17 +2887,26 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
 
            count += 1;
            numchars -= 1;
+#ifdef USE_X_TOOLKIT
          }
-#else
+         else
+           goto OTHER;
+#endif /* USE_X_TOOLKIT */
+         }
+#else /* not NEW_SELECTIONS */
          x_disown_selection (event.xselectionclear.window,
                              event.xselectionclear.selection,
                              event.xselectionclear.time);
-#endif
+#endif /* not NEW_SELECTIONS */
          break;
 
        case SelectionRequest:  /* Someone wants our selection. */
 #ifdef NEW_SELECTIONS
          {
+#ifdef USE_X_TOOLKIT
+         if (x_window_to_frame (event.xselectionrequest.owner))
+           {
+#endif /* USE_X_TOOLKIT */
            XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
 
            if (numchars == 0)
@@ -2724,16 +2923,28 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
 
            count += 1;
            numchars -= 1;
+#ifdef USE_X_TOOLKIT
          }
-#else
+         else
+           goto OTHER;
+#endif /* USE_X_TOOLKIT */
+         }
+#else /* not NEW_SELECTIONS */
          x_answer_selection_request (event);
-#endif
+#endif /* not NEW_SELECTIONS */
          break;
 
        case PropertyNotify:
 #ifdef NEW_SELECTIONS
+#ifdef USE_X_TOOLKIT
+         if (x_any_window_to_frame (event.xproperty.window))
+           x_handle_property_notify (&event);
+         else
+           goto OTHER;
+#else /* not USE_X_TOOLKIT */
          x_handle_property_notify (&event);
-#else
+#endif /* not USE_X_TOOLKIT */
+#else /* not NEW_SELECTIONS */
          /* If we're being told about a root window property, then it's
             a cut buffer change.  */
          if (event.xproperty.window == ROOT_WINDOW)
@@ -2747,7 +2958,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                 about re-selecting. */
              x_send_incremental (event);
            }
-#endif
+#endif /* not NEW_SELECTIONS */
          break;
 
        case ReparentNotify:
@@ -2777,9 +2988,13 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
            {
              struct scroll_bar *bar
                = x_window_to_scroll_bar (event.xexpose.window);
-
+             
              if (bar)
-               x_scroll_bar_expose (bar, &event);
+               x_scroll_bar_expose (bar, &event);
+#ifdef USE_X_TOOLKIT
+             else
+               goto OTHER;
+#endif /* USE_X_TOOLKIT */
            }
          break;
 
@@ -2794,6 +3009,10 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                             event.xgraphicsexpose.width,
                             event.xgraphicsexpose.height);
            }
+#ifdef USE_X_TOOLKIT
+         else
+           goto OTHER;
+#endif /* USE_X_TOOLKIT */
          break;
 
        case NoExpose:          /* This occurs when an XCopyArea's
@@ -2861,14 +3080,21 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
              /* The window manager never makes a window invisible
                 ("withdrawn"); all it does is switch between visible
                 and iconified.  Frames get into the invisible state
-                only through x_make_frame_invisible.
+                only through x_make_frame_invisible.  */
              if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
                f->async_iconified = 1;
            }
+#ifdef USE_X_TOOLKIT
+         goto OTHER;
+#endif /* USE_X_TOOLKIT */
          break;
 
        case MapNotify:
+#ifdef USE_X_TOOLKIT
+         f = x_any_window_to_frame (event.xmap.window);
+#else /* not USE_X_TOOLKIT */
          f = x_window_to_frame (event.xmap.window);
+#endif /* not USE_X_TOOLKIT */
          if (f)
            {
              f->async_visible = 1;
@@ -2878,7 +3104,10 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                 the frame's display structures.  */
              SET_FRAME_GARBAGED (f);
            }
-         break;
+#ifdef USE_X_TOOLKIT
+         goto OTHER;
+#endif /* USE_X_TOOLKIT */
+  break;
 
          /* Turn off processing if we become fully obscured. */
        case VisibilityNotify:
@@ -2901,7 +3130,9 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
          if (f != 0)
            {
              KeySym keysym, orig_keysym;
-             char copy_buffer[80];
+             /* al%imercury@uunet.uu.net says that making this 81 instead of
+                80 fixed a bug whereby meta chars made his Emacs hang.  */
+             unsigned char copy_buffer[81];
              int modifiers;
 
              event.xkey.state
@@ -2936,17 +3167,65 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                          incorrectly.  */
                       || ((unsigned) (keysym) >= XK_Select
                           && (unsigned)(keysym) < XK_KP_Space)
+#endif
+#ifdef XK_dead_circumflex
+                      || orig_keysym == XK_dead_circumflex
+#endif
+#ifdef XK_dead_grave
+                      || orig_keysym == XK_dead_grave
+#endif
+#ifdef XK_dead_tilde
+                      || orig_keysym == XK_dead_tilde
+#endif
+#ifdef XK_dead_diaeresis
+                      || orig_keysym == XK_dead_diaeresis
+#endif
+#ifdef XK_dead_macron
+                      || orig_keysym == XK_dead_macron
+#endif
+#ifdef XK_dead_degree
+                      || orig_keysym == XK_dead_degree
+#endif
+#ifdef XK_dead_acute
+                      || orig_keysym == XK_dead_acute
+#endif
+#ifdef XK_dead_cedilla
+                      || orig_keysym == XK_dead_cedilla
+#endif
+#ifdef XK_dead_breve
+                      || orig_keysym == XK_dead_breve
+#endif
+#ifdef XK_dead_ogonek
+                      || orig_keysym == XK_dead_ogonek
+#endif
+#ifdef XK_dead_caron
+                      || orig_keysym == XK_dead_caron
+#endif
+#ifdef XK_dead_doubleacute
+                      || orig_keysym == XK_dead_doubleacute
+#endif
+#ifdef XK_dead_abovedot
+                      || orig_keysym == XK_dead_abovedot
 #endif
                       || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
                       || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
                       || x_is_vendor_fkey (orig_keysym))
-                     && ! IsModifierKey (orig_keysym)) /* wherever */
+                     && ! (IsModifierKey (orig_keysym)
+#ifndef HAVE_X11R5
+#ifdef XK_Mode_switch
+                           || ((unsigned)(orig_keysym) == XK_Mode_switch)
+#endif
+#ifdef XK_Num_Lock
+                           || ((unsigned)(orig_keysym) == XK_Num_Lock)
+#endif
+#endif /* not HAVE_X11R5 */
+                           ))
                    {
                      if (temp_index == sizeof temp_buffer / sizeof (short))
                        temp_index = 0;
                      temp_buffer[temp_index++] = keysym;
                      bufp->kind = non_ascii_keystroke;
-                     XSET (bufp->code, Lisp_Int, (unsigned) keysym - 0xff00);
+                     bufp->code = keysym;
                      XSET (bufp->frame_or_window, Lisp_Frame, f);
                      bufp->modifiers = x_x_to_emacs_modifiers (modifiers);
                      bufp->timestamp = event.xkey.time;
@@ -2964,7 +3243,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                            temp_index = 0;
                          temp_buffer[temp_index++] = copy_buffer[i];
                          bufp->kind = ascii_keystroke;
-                         XSET (bufp->code, Lisp_Int, copy_buffer[i]);
+                         bufp->code = copy_buffer[i];
                          XSET (bufp->frame_or_window, Lisp_Frame, f);
                          bufp->modifiers = x_x_to_emacs_modifiers (modifiers);
                          bufp->timestamp = event.xkey.time;
@@ -3018,7 +3297,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                for (i = 0; i < nbytes; i++)
                  {
                    bufp->kind = ascii_keystroke;
-                   XSET (bufp->code, Lisp_Int, where_mapping[i]);
+                   bufp->code = where_mapping[i];
                    XSET (bufp->time, Lisp_Int, event.xkey.time);
                    XSET (bufp->frame_or_window, Lisp_Frame, f);
                    bufp++;
@@ -3054,7 +3333,9 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
            }
          else if (f == x_focus_frame)
            x_new_focus_frame (0);
-
+#ifdef USE_X_TOOLKIT
+         goto OTHER;
+#endif /* USE_X_TOOLKIT */
          break;
 
        case FocusIn:
@@ -3063,6 +3344,9 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
            x_focus_event_frame = f;
          if (f)
            x_new_focus_frame (f);
+#ifdef USE_X_TOOLKIT
+         goto OTHER;
+#endif /* USE_X_TOOLKIT */
          break;
 
 
@@ -3083,6 +3367,9 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
              if (f == x_focus_frame)
                x_new_focus_frame (0);
            }
+#ifdef USE_X_TOOLKIT
+         goto OTHER;
+#endif /* USE_X_TOOLKIT */
          break;
 
        case FocusOut:
@@ -3092,6 +3379,9 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
            x_focus_event_frame = 0;
          if (f && f == x_focus_frame)
            x_new_focus_frame (0);
+#ifdef USE_X_TOOLKIT
+         goto OTHER;
+#endif /* USE_X_TOOLKIT */
          break;
 
 #else /* ! defined (HAVE_X11) */
@@ -3133,21 +3423,31 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
 #ifdef HAVE_X11
        case MotionNotify:
          {
-           f = x_window_to_frame (event.xmotion.window);
+           if (x_mouse_grabbed)
+             f = last_mouse_frame;
+           else
+             f = x_window_to_frame (event.xmotion.window);
            if (f)
              note_mouse_movement (f, &event.xmotion);
            else
              {
-               struct scroll_bar *bar =
-                 x_window_to_scroll_bar (event.xmotion.window);
+               struct scroll_bar *bar
+                 x_window_to_scroll_bar (event.xmotion.window);
 
                if (bar)
                  x_scroll_bar_note_movement (bar, &event);
              }
          }
+#ifdef USE_X_TOOLKIT
+         goto OTHER;
+#endif /* USE_X_TOOLKIT */
          break;
 
        case ConfigureNotify:
+#ifdef USE_X_TOOLKIT
+             /* process done in widget.c */
+         goto OTHER;
+#else /* not USE_X_TOOLKIT */
          f = x_window_to_frame (event.xconfigure.window);
          if (f)
            {
@@ -3198,6 +3498,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
              f->display.x->left_pos = event.xconfigure.x;
              f->display.x->top_pos = event.xconfigure.y;
            }
+#endif /* not USE_X_TOOLKIT */
          break;
 
        case ButtonPress:
@@ -3212,8 +3513,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
            if (f)
              {
                if (!x_focus_frame || (f == x_focus_frame))
-                 construct_mouse_click (&emacs_event,
-                                        &event, f);
+                 construct_mouse_click (&emacs_event, &event, f);
              }
            else
              {
@@ -3222,6 +3522,15 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
 
                if (bar)
                  x_scroll_bar_handle_click (bar, &event, &emacs_event);
+#ifdef USE_X_TOOLKIT
+               else
+                 {
+                   f = x_any_window_to_frame (event.xbutton.window);
+                   if (f && event.type == ButtonPress)
+                     construct_menu_click (&emacs_event,
+                                           &event, f);
+                 }
+#endif /* USE_X_TOOLKIT */
              }
 
            if (numchars >= 1 && emacs_event.kind != no_event)
@@ -3231,6 +3540,10 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                count++;
                numchars--;
              }
+
+#ifdef USE_X_TOOLKIT
+           goto OTHER;
+#endif /* USE_X_TOOLKIT */
          }
          break;
 
@@ -3258,13 +3571,13 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
          if (numchars >= 2)
            {
              bufp->kind = ascii_keystroke;
-             bufp->code = (char) 'X' & 037; /* C-x */
+             bufp->code = 'X' & 037; /* C-x */
              XSET (bufp->frame_or_window, Lisp_Frame, f);
              XSET (bufp->time, Lisp_Int, event.xkey.time);
              bufp++;
 
              bufp->kind = ascii_keystroke;
-             bufp->code = (char) 0; /* C-@ */
+             bufp->code = 0; /* C-@ */
              XSET (bufp->frame_or_window, Lisp_Frame, f);
              XSET (bufp->time, Lisp_Int, event.xkey.time);
              bufp++;
@@ -3295,13 +3608,29 @@ 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:
+         BLOCK_INPUT;
+         XtDispatchEvent (&event);
+         UNBLOCK_INPUT;
+#endif /* USE_X_TOOLKIT */
          break;
        }
     }
 
+#ifdef X_IO_BUG
+  if (! event_found)
+    /* On some systems, an X bug causes Emacs to get no more events
+       when the window is destroyed.  Detect that.  */
+    XNoOp (x_current_display);
+#endif /* X_IO_BUG */
+
 #ifdef HAVE_SELECT
   if (expected && ! event_found)
     {
@@ -3309,16 +3638,19 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
         there is an EOF condition; in other words, that X has died.
         Act as if there had been a hangup. */
       int fd = ConnectionNumber (x_current_display);
-      SELECT_TYPE mask;
+      SELECT_TYPE mask, junk1, junk2;
       EMACS_TIME timeout;
 
-      FD_SET(fd, &mask);
+      FD_ZERO (&mask);
+      FD_SET (fd, &mask);
       EMACS_SET_SECS_USECS (timeout, 0, 0);
-      if (0 != select (fd + 1, &mask, (long *) 0, (long *) 0, &timeout)
+      FD_ZERO (&junk1);
+      FD_ZERO (&junk2);
+      if (0 != select (fd + 1, &mask, &junk1, &junk2, &timeout)
          && !XStuffPending ())
        kill (getpid (), SIGHUP);
     }
-#endif /* ! defined (HAVE_SELECT) */
+#endif /* HAVE_SELECT */
 
 #ifndef HAVE_X11
   if (updating_frame == 0)
@@ -3625,6 +3957,8 @@ x_display_cursor (f, on)
      struct frame *f;
      int on;
 {
+  BLOCK_INPUT;
+
   if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
     x_display_box_cursor (f, on);
   else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
@@ -3632,6 +3966,8 @@ x_display_cursor (f, on)
   else
     /* Those are the only two we have implemented!  */
     abort ();
+
+  UNBLOCK_INPUT;
 }
 \f
 /* Icons.  */
@@ -3892,7 +4228,7 @@ x_error_catcher (display, error)
 
    Calling x_uncatch_errors resumes the normal error handling.  */
 
-void x_catch_errors(), x_check_errors (), x_uncatch_errors ();
+void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
 
 void
 x_catch_errors ()
@@ -3954,8 +4290,14 @@ x_trace_wire ()
 
 #ifdef HAVE_X11
 
+struct font_info
+{
+  XFontStruct *font;
+  char *name;
+};
+
 /* A table of all the fonts we have already loaded.  */
-static XFontStruct **x_font_table;
+static struct font_info *x_font_table;
 
 /* The current capacity of x_font_table.  */
 static int x_font_table_size;
@@ -3978,9 +4320,8 @@ x_new_font (f, fontname)
   /* Get a list of all the fonts that match this name.  Once we
      have a list of matching fonts, we compare them against the fonts
      we already have by comparing font ids.  */
-  font_names = (char **) XListFontsWithInfo (x_current_display, fontname,
-                                            1024, &n_matching_fonts,
-                                            &font_info);
+  font_names = (char **) XListFonts (x_current_display, fontname,
+                                    1024, &n_matching_fonts);
   /* Apparently it doesn't set n_matching_fonts to zero when it can't
      find any matches; font_names == 0 is the only clue.  */
   if (! font_names)
@@ -3998,7 +4339,7 @@ x_new_font (f, fontname)
 
       for (i = 0; i < n_fonts; i++)
        for (j = 0; j < n_matching_fonts; j++)
-         if (x_font_table[i]->fid == font_info[j].fid)
+         if (!strcmp (x_font_table[i].name, font_names[j]))
            {
              already_loaded = i;
              fontname = font_names[j];
@@ -4008,8 +4349,8 @@ x_new_font (f, fontname)
  found_font:
   
   /* If we have, just return it from the table.  */
-  if (already_loaded > 0)
-    f->display.x->font = x_font_table[already_loaded];
+  if (already_loaded >= 0)
+    f->display.x->font = x_font_table[already_loaded].font;
   
   /* Otherwise, load the font and add it to the table.  */
   else
@@ -4034,9 +4375,9 @@ x_new_font (f, fontname)
       font = (XFontStruct *) XLoadQueryFont (x_current_display, fontname);
       if (! font)
        {
-         /* Free the information from XListFontsWithInfo.  */
+         /* Free the information from XListFonts.  */
          if (n_matching_fonts)
-           XFreeFontInfo (font_names, font_info, n_matching_fonts);
+           XFreeFontNames (font_names);
          return Qnil;
        }
 
@@ -4045,22 +4386,24 @@ x_new_font (f, fontname)
        {
          x_font_table_size = 16;
          x_font_table
-           = (XFontStruct **) xmalloc (x_font_table_size
-                                       * sizeof (x_font_table[0]));
+           = (struct font_info *) xmalloc (x_font_table_size
+                                           * sizeof (x_font_table[0]));
        }
       /* Do we need to grow the table?  */
       else if (n_fonts >= x_font_table_size)
        {
          x_font_table_size *= 2;
          x_font_table
-           = (XFontStruct **) xrealloc (x_font_table,
-                                        (x_font_table_size
-                                         * sizeof (x_font_table[0])));
+           = (struct font_info *) xrealloc (x_font_table,
+                                            (x_font_table_size
+                                             * sizeof (x_font_table[0])));
        }
 
-      f->display.x->font = x_font_table[n_fonts++] = font;
+      x_font_table[n_fonts].name = (char *) xmalloc (strlen (fontname) + 1);
+      bcopy (fontname, x_font_table[n_fonts].name, strlen (fontname) + 1);
+      f->display.x->font = x_font_table[n_fonts++].font = font;
     }
-  
+
   /* Now make the frame display the given font.  */
   if (FRAME_X_WINDOW (f) != 0)
     {
@@ -4071,16 +4414,16 @@ x_new_font (f, fontname)
       XSetFont (x_current_display, f->display.x->cursor_gc,
                f->display.x->font->fid);
 
-      x_set_window_size (f, f->width, f->height);
+      x_set_window_size (f, 0, f->width, f->height);
     }
 
   {
     Lisp_Object lispy_name = build_string (fontname);
 
 
-    /* Free the information from XListFontsWithInfo.  The data
+    /* Free the information from XListFonts.  The data
        we actually retain comes from XLoadQueryFont.  */
-    XFreeFontInfo (font_names, font_info, n_matching_fonts);
+    XFreeFontNames (font_names);
 
     return lispy_name;
   }
@@ -4103,29 +4446,52 @@ x_new_font (f, newname)
   f->display.x->font = temp;
 
   if (FRAME_X_WINDOW (f) != 0)
-    x_set_window_size (f, f->width, f->height);
+    x_set_window_size (f, 0, f->width, f->height);
 
   return 0;
 }
 #endif /* ! defined (HAVE_X11) */
 \f
-/* X Window sizes and positions.  */
-
 x_calc_absolute_position (f)
      struct frame *f;
 {
 #ifdef HAVE_X11
+  Window win, child;
+  int win_x = 0, win_y = 0;
+
+  /* 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 != ROOT_WINDOW)
+    {
+      BLOCK_INPUT;
+      XTranslateCoordinates (x_current_display,
+                              
+                            /* From-window, to-window.  */
+                            f->display.x->window_desc,
+                            f->display.x->parent_desc,
+
+                            /* From-position, to-position.  */
+                            0, 0, &win_x, &win_y,
+
+                            /* Child of win.  */
+                            &child);
+      UNBLOCK_INPUT;
+    }
+
+  /* Treat negative positions as relative to the leftmost bottommost
+     position that fits on the screen.  */
   if (f->display.x->left_pos < 0)
     f->display.x->left_pos = (x_screen_width 
-                             - 2 * f->display.x->border_width
+                             - 2 * f->display.x->border_width - win_x
                              - PIXEL_WIDTH (f)
                              + f->display.x->left_pos);
 
   if (f->display.x->top_pos < 0)
     f->display.x->top_pos = (x_screen_height
-                            - 2 * f->display.x->border_width
+                            - 2 * f->display.x->border_width - win_y
                             - PIXEL_HEIGHT (f)
                             + f->display.x->top_pos);
+
 #else /* ! defined (HAVE_X11) */
   WINDOWINFO_TYPE parentinfo;
 
@@ -4150,35 +4516,51 @@ x_set_offset (f, xoff, yoff)
   x_calc_absolute_position (f);
 
   BLOCK_INPUT;
+#ifdef USE_X_TOOLKIT
+  XMoveWindow (XDISPLAY XtWindow (f->display.x->widget),
+              f->display.x->left_pos, f->display.x->top_pos);
+#else /* not USE_X_TOOLKIT */
   XMoveWindow (XDISPLAY FRAME_X_WINDOW (f),
               f->display.x->left_pos, f->display.x->top_pos);
+#endif /* not USE_X_TOOLKIT */
 #ifdef HAVE_X11
-  x_wm_set_size_hint (f, 0);
+  x_wm_set_size_hint (f, 0, 1, xoff, yoff);
 #endif /* ! defined (HAVE_X11) */
   UNBLOCK_INPUT;
 }
 
-/* Call this to change the size of frame F's x-window. */
+/* Call this to change the size of frame F's x-window.
+   If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
+   for this size change and subsequent size changes.
+   Otherwise we leave the window gravity unchanged.  */
 
-x_set_window_size (f, cols, rows)
+x_set_window_size (f, change_gravity, cols, rows)
      struct frame *f;
+     int change_gravity;
      int cols, rows;
 {
   int pixelwidth, pixelheight;
   int mask;
 
+#ifdef USE_X_TOOLKIT
+  BLOCK_INPUT;
+  EmacsFrameSetCharSize (f->display.x->edit_widget, cols, rows);
+  UNBLOCK_INPUT;
+
+#else /* not USE_X_TOOLKIT */
+
   BLOCK_INPUT;
 
   check_frame_size (f, &rows, &cols);
-  f->display.x->vertical_scroll_bar_extra =
-    (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
-     ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f)
-     : 0);
+  f->display.x->vertical_scroll_bar_extra
+    (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
+       ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f)
+       : 0);
   pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
   pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
 
 #ifdef HAVE_X11
-  x_wm_set_size_hint (f, 0);
+  x_wm_set_size_hint (f, 0, change_gravity, 0, 0);
 #endif /* ! defined (HAVE_X11) */
   XChangeWindowSize (FRAME_X_WINDOW (f), pixelwidth, pixelheight);
 
@@ -4204,6 +4586,7 @@ x_set_window_size (f, cols, rows)
 
   XFlushQueue ();
   UNBLOCK_INPUT;
+#endif /* not USE_X_TOOLKIT */
 }
 
 #ifndef HAVE_X11
@@ -4226,7 +4609,9 @@ x_set_mouse_position (f, x, y)
 {
   int pix_x, pix_y;
 
+#if 0 /* Let the user ask for this if he wants it.  */
   x_raise_frame (f);
+#endif
 
   pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH  (f->display.x->font) / 2;
   pix_y = CHAR_TO_PIXEL_ROW (f, y) + FONT_HEIGHT (f->display.x->font) / 2;
@@ -4247,7 +4632,9 @@ x_set_mouse_position (f, x, y)
 x_focus_on_frame (f)
      struct frame *f;
 {
+#if 0  /* This proves to be unpleasant.  */
   x_raise_frame (f);
+#endif
 #if 0
   /* I don't think that the ICCCM allows programs to do things like this
      without the interaction of the window manager.  Whatever you end up
@@ -4278,7 +4665,11 @@ x_raise_frame (f)
   if (f->async_visible)
     {
       BLOCK_INPUT;
+#ifdef USE_X_TOOLKIT
+      XRaiseWindow (XDISPLAY XtWindow (f->display.x->widget));
+#else /* not USE_X_TOOLKIT */
       XRaiseWindow (XDISPLAY FRAME_X_WINDOW (f));
+#endif /* not USE_X_TOOLKIT */
       XFlushQueue ();
       UNBLOCK_INPUT;
     }
@@ -4292,7 +4683,11 @@ x_lower_frame (f)
   if (f->async_visible)
     {
       BLOCK_INPUT;
+#ifdef USE_X_TOOLKIT
+      XLowerWindow (XDISPLAY XtWindow (f->display.x->widget));
+#else /* not USE_X_TOOLKIT */
       XLowerWindow (XDISPLAY FRAME_X_WINDOW (f));
+#endif /* not USE_X_TOOLKIT */
       XFlushQueue ();
       UNBLOCK_INPUT;
     }
@@ -4324,8 +4719,11 @@ x_make_frame_visible (f)
 #ifdef HAVE_X11
       if (! EQ (Vx_no_window_manager, Qt))
        x_wm_set_window_state (f, NormalState);
-
+#ifdef USE_X_TOOLKIT
+      XtPopup (f->display.x->widget, XtGrabNone);
+#else /* not USE_X_TOOLKIT */
       XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
+#endif /* not USE_X_TOOLKIT */
       if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
        XMapSubwindows (x_current_display, FRAME_X_WINDOW (f));
 #else /* ! defined (HAVE_X11) */
@@ -4365,8 +4763,13 @@ x_make_frame_invisible (f)
 
 #ifdef HAVE_X11R4
 
+#ifdef USE_X_TOOLKIT
+  if (! XWithdrawWindow (x_current_display, XtWindow (f->display.x->widget),
+                        DefaultScreen (x_current_display)))
+#else /* not USE_X_TOOLKIT */
   if (! XWithdrawWindow (x_current_display, FRAME_X_WINDOW (f),
                         DefaultScreen (x_current_display)))
+#endif /* not USE_X_TOOLKIT */
     {
       UNBLOCK_INPUT_RESIGNAL;
       error ("can't notify window manager of window withdrawal");
@@ -4381,7 +4784,11 @@ x_make_frame_invisible (f)
       XEvent unmap;
 
       unmap.xunmap.type = UnmapNotify;
+#ifdef USE_X_TOOLKIT
+      unmap.xunmap.window = XtWindow (f->display.x->widget);
+#else /* not USE_X_TOOLKIT */
       unmap.xunmap.window = FRAME_X_WINDOW (f);
+#endif /* not USE_X_TOOLKIT */
       unmap.xunmap.event = DefaultRootWindow (x_current_display);
       unmap.xunmap.from_configure = False;
       if (! XSendEvent (x_current_display,
@@ -4396,8 +4803,11 @@ x_make_frame_invisible (f)
     }
 
   /* Unmap the window ourselves.  Cheeky!  */
+#ifdef USE_X_TOOLKIT
+  XUnmapWindow (x_current_display, XtWindow (f->display.x->widget));
+#else /* not USE_X_TOOLKIT */
   XUnmapWindow (x_current_display, FRAME_X_WINDOW (f));
-
+#endif /* not USE_X_TOOLKIT */
 #else /* ! defined (HAVE_X11) */
 
   XUnmapWindow (FRAME_X_WINDOW (f));
@@ -4418,6 +4828,7 @@ x_iconify_frame (f)
      struct frame *f;
 {
   int mask;
+  int result;
 
   /* Don't keep the highlight on an invisible frame.  */
   if (x_highlight_frame == f)
@@ -4426,6 +4837,23 @@ x_iconify_frame (f)
   if (f->async_iconified)
     return;
 
+#ifdef USE_X_TOOLKIT
+  BLOCK_INPUT;
+  result = XIconifyWindow (x_current_display,
+                          XtWindow (f->display.x->widget),
+                          DefaultScreen (x_current_display));
+  UNBLOCK_INPUT;
+
+  if (!result)
+    error ("Can't notify window manager of iconification.");
+
+  f->async_iconified = 1;
+
+  BLOCK_INPUT;
+  XFlushQueue ();
+  UNBLOCK_INPUT;
+#else /* not USE_X_TOOLKIT */
+
   BLOCK_INPUT;
 
 #ifdef HAVE_X11
@@ -4458,6 +4886,14 @@ x_iconify_frame (f)
      IconicState.  */
   x_wm_set_window_state (f, IconicState);
 
+  if (!FRAME_VISIBLE_P (f))
+    {
+      /* If the frame was withdrawn, before, we must map it.  */
+      XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
+      if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
+       XMapSubwindows (x_current_display, FRAME_X_WINDOW (f));
+    }
+
   f->async_iconified = 1;
 #else /* ! defined (HAVE_X11) */
   XUnmapWindow (XDISPLAY FRAME_X_WINDOW (f));
@@ -4472,6 +4908,7 @@ x_iconify_frame (f)
 
   XFlushQueue ();
   UNBLOCK_INPUT;
+#endif /* not USE_X_TOOLKIT */
 }
 
 /* Destroy the X window of frame F.  */
@@ -4484,6 +4921,10 @@ x_destroy_window (f)
   if (f->display.x->icon_desc != 0)
     XDestroyWindow (XDISPLAY f->display.x->icon_desc);
   XDestroyWindow (XDISPLAY f->display.x->window_desc);
+#ifdef USE_X_TOOLKIT
+  XtDestroyWidget (f->display.x->widget);
+#endif /* USE_X_TOOLKIT */
+
   free_frame_faces (f);
   XFlushQueue ();
 
@@ -4513,7 +4954,7 @@ x_destroy_window (f)
    of certain kinds into our private queues.
 
    All ExposeRegion events are put in x_expose_queue.
-   All ButtonPressed and ButtonReleased events are put in x_mouse_queue.  */
+   All ButtonPress and ButtonRelease events are put in x_mouse_queue.  */
 
 
 /* Write the event *P_XREP into the event queue *QUEUE.
@@ -4575,12 +5016,27 @@ mouse_event_pending_p ()
 
 #ifdef HAVE_X11
 
-x_wm_set_size_hint (f, prompting)
+/* Record the gravity used previously, in case CHANGE_GRAVITY is 0.  */
+static int previous_gravity;
+
+/* SPEC_X and SPEC_Y are the specified positions.
+   We look only at their sign, to decide the gravity.
+   If CHANGE_GRAVITY is 0, we ignore SPEC_X and SPEC_Y
+   and leave the gravity unchanged.  */
+
+x_wm_set_size_hint (f, prompting, change_gravity, spec_x, spec_y)
      struct frame *f;
      long prompting;
+     int change_gravity;
+     int spec_x, spec_y;
 {
   XSizeHints size_hints;
+
+#ifdef USE_X_TOOLKIT
+  Window window = XtWindow (f->display.x->widget);
+#else /* not USE_X_TOOLKIT */
   Window window = FRAME_X_WINDOW (f);
+#endif /* not USE_X_TOOLKIT */
 
   size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
 
@@ -4647,6 +5103,31 @@ x_wm_set_size_hint (f, prompting)
       if (hints.flags & USSize)
        size_hints.flags |= USSize;
     }
+#if defined (PWinGravity)
+  if (change_gravity)
+    {
+      switch (((spec_x < 0) << 1) + (spec_y < 0))
+       {
+       case 0:
+         size_hints.win_gravity = NorthWestGravity;
+         break;
+       case 1:
+         size_hints.win_gravity = NorthEastGravity;
+         break;
+       case 2:
+         size_hints.win_gravity = SouthWestGravity;
+         break;
+       case 3:
+         size_hints.win_gravity = SouthEastGravity;
+         break;
+       }
+      previous_gravity = size_hints.win_gravity;
+    }
+  else
+    size_hints.win_gravity = previous_gravity;
+
+  size_hints.flags |= PWinGravity;
+#endif /* PWinGravity */
 
 #ifdef HAVE_X11R4
   XSetWMNormalHints (x_current_display, window, &size_hints);
@@ -4660,7 +5141,11 @@ x_wm_set_window_state (f, state)
      struct frame *f;
      int state;
 {
+#ifdef USE_X_TOOLKIT
+  Window window = XtWindow (f->display.x->widget);
+#else /* not USE_X_TOOLKIT */
   Window window = FRAME_X_WINDOW (f);
+#endif /* not USE_X_TOOLKIT */
 
   f->display.x->wm_hints.flags |= StateHint;
   f->display.x->wm_hints.initial_state = state;
@@ -4701,49 +5186,68 @@ x_wm_set_icon_position (f, icon_x, icon_y)
 \f
 /* Initialization.  */
 
+#ifdef USE_X_TOOLKIT
+static XrmOptionDescRec emacs_options[] = {
+  {"-geometry",        ".geometry", XrmoptionSepArg, NULL},
+  {"-iconic",  ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
+
+  {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
+     XrmoptionSepArg, NULL},
+  {"-ib",      "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
+
+  {"-T",       "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
+  {"-wn",      "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
+  {"-title",   "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
+  {"-iconname",        "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
+  {"-in",      "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
+  {"-mc",      "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
+  {"-cr",      "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
+};
+#endif /* USE_X_TOOLKIT */
+
 void
 x_term_init (display_name)
      char *display_name;
 {
   Lisp_Object frame;
   char *defaultvalue;
+  int argc = 0;
+  char** argv = 0;
+#ifndef F_SETOWN_BUG
 #ifdef F_SETOWN
   extern int old_fcntl_owner;
 #endif /* ! defined (F_SETOWN) */
+#endif /* F_SETOWN_BUG */
   
   x_focus_frame = x_highlight_frame = 0;
 
+#ifdef USE_X_TOOLKIT
+  argv = (char **) XtMalloc (3 * sizeof (char *));
+  argv [0] = "";
+  argv [1] = "-display";
+  argv [2] = display_name;
+  argc = 3;
+  Xt_app_shell = XtAppInitialize (&Xt_app_con, "Emacs",
+                                 emacs_options, XtNumber (emacs_options),
+                                 &argc, argv,
+                                 NULL, NULL, 0);
+  XtFree (argv);
+  x_current_display = XtDisplay (Xt_app_shell);
+
+#else /* not USE_X_TOOLKIT */
   x_current_display = XOpenDisplay (display_name);
+#endif /* not USE_X_TOOLKIT */
   if (x_current_display == 0)
-    fatal ("X server %s not responding; check the DISPLAY environment variable or use \"-d\"\n",
+    fatal ("X server %s not responding.\n\
+Check the DISPLAY environment variable or use \"-d\"\n",
           display_name);
 
 #ifdef HAVE_X11
   {
-    int hostname_size = 256;
-
-    hostname = (char *) xmalloc (hostname_size);
-
 #if 0
     XSetAfterFunction (x_current_display, x_trace_wire);
 #endif /* ! 0 */
-
-    /* Try to get the host name; if the buffer is too short, try
-       again.  Apparently, the only indication gethostname gives of
-       whether the buffer was large enough is the presence or absence
-       of a '\0' in the string.  Eech.  */
-    for (;;)
-      {
-       gethostname (hostname, hostname_size - 1);
-       hostname[hostname_size - 1] = '\0';
-
-       /* Was the buffer large enough for gethostname to store the '\0'?  */
-       if (strlen (hostname) < hostname_size - 1)
-         break;
-
-       hostname_size <<= 1;
-       hostname = (char *) xrealloc (hostname, hostname_size);
-      }
+    hostname = get_system_name ();
     x_id_name = (char *) xmalloc (XSTRING (Vinvocation_name)->size
                                + strlen (hostname)
                                + 2);
@@ -4764,40 +5268,27 @@ x_term_init (display_name)
 #endif
 
   if (ConnectionNumber (x_current_display) != 0)
-    {
-      dup2 (ConnectionNumber (x_current_display), 0);
-
-#ifndef SYSV_STREAMS
-      /* Streams somehow keeps track of which descriptor number
-        is being used to talk to X.  So it is not safe to substitute
-        descriptor 0.  But it is safe to make descriptor 0 a copy of it.  */
-      close (ConnectionNumber (x_current_display));
-      ConnectionNumber (x_current_display) = 0;        /* Looks a little strange?
-                                                * check the def of the macro;
-                                                * it is a genuine lvalue */
-#endif /* SYSV_STREAMS */
-    }
+    change_keyboard_wait_descriptor (ConnectionNumber (x_current_display));
+  change_input_fd (ConnectionNumber (x_current_display));
 
 #endif /* ! defined (HAVE_X11) */
   
+#ifndef F_SETOWN_BUG
 #ifdef F_SETOWN
-  old_fcntl_owner = fcntl (0, F_GETOWN, 0);
+  old_fcntl_owner = fcntl (ConnectionNumber (x_current_display), F_GETOWN, 0);
 #ifdef F_SETOWN_SOCK_NEG
-  fcntl (0, F_SETOWN, -getpid ());     /* stdin is a socket here */
+  /* stdin is a socket here */
+  fcntl (ConnectionNumber (x_current_display), F_SETOWN, -getpid ());
 #else /* ! defined (F_SETOWN_SOCK_NEG) */
-  fcntl (0, F_SETOWN, getpid ());
+  fcntl (ConnectionNumber (x_current_display), F_SETOWN, getpid ());
 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
 #endif /* ! defined (F_SETOWN) */
+#endif /* F_SETOWN_BUG */
 
 #ifdef SIGIO
   init_sigio ();
 #endif /* ! defined (SIGIO) */
 
-  /* Must use interrupt input because we cannot otherwise
-     arrange for C-g to be noticed immediately.
-     We cannot connect it to SIGINT.  */
-  Fset_input_mode (Qt, Qnil, Qt, Qnil);
-
   expose_all_windows = 0;
 
   clear_frame_hook = XTclear_frame;
@@ -4832,6 +5323,9 @@ x_term_init (display_name)
                                   off the bottom */
   baud_rate = 19200;
 
+  /* Try to use interrupt input; if we can't, then start polling.  */
+  Fset_input_mode (Qt, Qnil, Qt, Qnil);
+
   /* Note that there is no real way portable across R3/R4 to get the 
      original error handler.  */
   XHandleError (x_error_quitter);
@@ -4849,6 +5343,7 @@ void
 syms_of_xterm ()
 {
   staticpro (&last_mouse_scroll_bar);
+  last_mouse_scroll_bar = Qnil;
 }
 #endif /* ! defined (HAVE_X11) */
 #endif /* ! defined (HAVE_X_WINDOWS) */