*** empty log message ***
[bpt/emacs.git] / src / xterm.c
index 17a0c46..43f59d0 100644 (file)
@@ -1,11 +1,11 @@
 /* X Communication module for terminals which understand the X protocol.
-   Copyright (C) 1989 Free Software Foundation, Inc.
+   Copyright (C) 1989, 1992 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 GNU Emacs is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
+the Free Software Foundation; either version 2, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -30,7 +30,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #ifdef HAVE_X_WINDOWS
 
 #include "lisp.h"
-#undef NULL
 
 /* On 4.3 this loses if it comes after xterm.h.  */
 #include <signal.h>
@@ -66,13 +65,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #endif
 #endif
 
-#ifdef NEED_TIME_H
-#include <time.h>
-#else /* not NEED_TIME_H */
-#ifdef HAVE_TIMEVAL
-#include <sys/time.h>
-#endif /* HAVE_TIMEVAL */
-#endif /* not NEED_TIME_H */
+#include "systime.h"
 
 #include <fcntl.h>
 #include <stdio.h>
@@ -93,9 +86,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "gnu.h"
 #include "screen.h"
 #include "disptab.h"
-#include "window.h"
 #include "buffer.h"
-#include "xfns.h"
 
 #ifdef HAVE_X11
 #define XMapWindow XMapRaised          /* Raise them when mapping. */
@@ -163,7 +154,8 @@ static FONT_TYPE *icon_font_info;
 /* Stuff for dealing with the main icon title. */
 
 extern Lisp_Object Vcommand_line_args;
-char *hostname, *id_name, *invocation_name;
+char *hostname, *x_id_name;
+Lisp_Object invocation_name;
 
 /* This is the X connection that we are using.  */
 
@@ -178,10 +170,16 @@ Display *x_current_display;
 static struct screen *updating_screen;
 
 /* The screen (if any) which has the X window that has keyboard focus.
-   Zero if none.  This is examined by Ffocus_screen in screen.c */
-
+   Zero if none.  This is examined by Ffocus_screen in screen.c.  */
 struct screen *x_focus_screen;
 
+/* The screen which currently has the visual highlight, and should get
+   keyboard input (other sorts of input have the screen encoded in the
+   event).  It points to the X focus screen's selected window's
+   screen.  It differs from x_focus_screen when we're using a global
+   minibuffer.  */
+static struct screen *x_highlight_screen;
+
 /* From .Xdefaults, the value of "emacs.WarpMouse".  If non-zero,
    mouse is moved to inside of screen when screen is de-iconified.  */
 
@@ -247,8 +245,6 @@ static WINDOWINFO_TYPE windowinfo;
 
 extern int errno;
 
-extern Lisp_Object Vglobal_minibuffer_screen;
-
 extern Display *XOpenDisplay ();
 extern Window XCreateWindow ();
 
@@ -262,8 +258,8 @@ static void dumpqueue ();
 #endif
 
 void dumpborder ();
-static XTcursor_to ();
-static XTclear_end_of_line ();
+static int XTcursor_to ();
+static int XTclear_end_of_line ();
 \f
 /* These hooks are called by update_screen at the beginning and end
    of a screen update.  We record in `updating_screen' the identity
@@ -287,14 +283,6 @@ XTupdate_begin (s)
   flexlines = s->height;
   highlight = 0;
 
-#if 0
-  if (mouse_track_width != 0)
-    {
-      x_rectangle (s, s->display.x->reverse_gc,
-                  mouse_track_top, mouse_track_left, mouse_track_width, 1);
-      mouse_track_width = 0;
-    }
-#endif
   BLOCK_INPUT;
 #ifndef HAVE_X11
   dumpqueue ();
@@ -373,6 +361,7 @@ XTreset_terminal_modes ()
    where display update commands will take effect.
    This does not affect the place where the cursor-box is displayed.  */
 
+static int
 XTcursor_to (row, col)
      register int row, col;
 {
@@ -406,8 +395,6 @@ dumpglyphs (s, left, top, gp, n, hl, font)
      int hl;
      FONT_TYPE *font;
 {
-  char buf[s->width];
-  register char *cp = buf;
   register int len;
   Window window = s->display.x->window_desc;
   GC drawing_gc =   (hl == 2 ? s->display.x->cursor_gc
@@ -566,16 +553,18 @@ XTwrite_glyphs (start, len)
       curs_y = s->cursor_y;
     }
 
-  /* Clear the cursor if it appears on this line.  */
-  if (curs_y == s->cursor_y)
-    x_display_cursor (s, 0);
-
   dumpglyphs (s,
             (curs_x * FONT_WIDTH (s->display.x->font)
              + s->display.x->internal_border_width),
             (curs_y * FONT_HEIGHT (s->display.x->font)
              + s->display.x->internal_border_width),
             start, len, highlight, s->display.x->font);
+
+  /* If we drew on top of the cursor, note that it is turned off.  */
+  if (curs_y == s->phys_cursor_y
+      && curs_x <= s->phys_cursor_x
+      && curs_x + len > s->phys_cursor_x)
+    s->phys_cursor_x = -1;
   
   if (updating_screen == 0)
     {
@@ -593,7 +582,7 @@ XTwrite_glyphs (start, len)
    to column FIRST_UNUSED (exclusive).  The idea is that everything
    from FIRST_UNUSED onward is already erased.  */
   
-static
+static int
 XTclear_end_of_line (first_unused)
      register int first_unused;
 {
@@ -613,9 +602,11 @@ XTclear_end_of_line (first_unused)
 
   BLOCK_INPUT;
 
-  /* Clear the cursor if it appears on this line.  */
-  if (curs_y == s->cursor_y)
-    x_display_cursor (s, 0);
+  /* Notice if the cursor will be cleared by this operation.  */
+  if (curs_y == s->phys_cursor_y
+      && curs_x <= s->phys_cursor_x
+      && s->phys_cursor_x < first_unused)
+    s->phys_cursor_x = -1;
 
 #ifdef HAVE_X11
   XClearArea (x_current_display, s->display.x->window_desc,
@@ -951,7 +942,7 @@ XTins_del_lines (vpos, n)
   if (updating_screen == 0)
     abort ();
 
-  /* Clear the cursor.  */
+  /* Hide the cursor.  */
   x_display_cursor (updating_screen, 0);
 
   XTcursor_to (vpos, 0);
@@ -1105,7 +1096,7 @@ x_do_pending_expose ()
          if (XTYPE (screen) != Lisp_Screen)
            continue;
          s = XSCREEN (screen);
-         if (s->output_method != output_x_window)
+         if (! SCREEN_IS_X (s))
            continue;
          if (!s->visible)
            continue;
@@ -1215,61 +1206,71 @@ dumpborder (s, always)
 }
 #endif /* X10 */
 
+static void XTscreen_rehighlight ();
+
 /* The focus has changed.  Update the screens as necessary to reflect
    the new situation.  Note that we can't change the selected screen
    here, because the lisp code we are interrupting might become confused.
-   For that, we enqueue a screen_selected event.
+   Each event gets marked with the screen in which it occured, so the
+   lisp code can tell when the switch took place by examining the events.  */
 
-   Return the number of events stored at bufp.  */
-static int
-x_new_focus_screen (screen, bufp, buf_free)
+static void
+x_new_focus_screen (screen)
      struct screen *screen;
-     struct input_event *bufp;
-     int buf_free;
 {
   struct screen *old_focus = x_focus_screen;
   int events_enqueued = 0;
 
-  if (screen == x_focus_screen)
-    return 0;
-
-  /* Set this before calling screen_{un,}highlight, so that they see 
-     the correct value of x_focus_screen.  */
-  x_focus_screen = screen;
-
-  if (old_focus)
+  if (screen != x_focus_screen)
     {
-      if (old_focus->auto_lower)
+      /* Set this before calling other routines, so that they see 
+        the correct value of x_focus_screen.  */
+      x_focus_screen = screen;
+
+      if (old_focus && old_focus->auto_lower)
        x_lower_screen (old_focus);
-      screen_unhighlight (old_focus);
-    }
 
 #if 0
-  selected_screen = screen;
-  XSET (XWINDOW (selected_screen->selected_window)->screen,
-       Lisp_Screen, selected_screen);
-  Fselect_window (selected_screen->selected_window);
-  choose_minibuf_screen ();
+      selected_screen = screen;
+      XSET (XWINDOW (selected_screen->selected_window)->screen,
+           Lisp_Screen, selected_screen);
+      Fselect_window (selected_screen->selected_window);
+      choose_minibuf_screen ();
 #endif
 
-  if (x_focus_screen)
-    {
-      if (x_focus_screen->auto_raise)
+      if (x_focus_screen && x_focus_screen->auto_raise)
        x_raise_screen (x_focus_screen);
-      screen_highlight (x_focus_screen);
+    }
 
-      /* Enqueue an event.  It's kind of important not to drop these
-        events, but the event queue's fixed size is a real pain
-        anyway.  */
-      if (buf_free > 0)
-       {
-         bufp->kind = screen_selected;
-         bufp->screen = screen;
-         events_enqueued++;
-       }
+  XTscreen_rehighlight ();
+}
+
+
+/* The focus has changed, or we have make a screen's selected window
+   point to a window on a different screen (this happens with global
+   minibuffer screens).  Shift the highlight as appropriate.  */
+static void
+XTscreen_rehighlight ()
+{
+  struct screen *old_highlight = x_highlight_screen;
+
+  if (x_focus_screen)
+    {
+      x_highlight_screen = XSCREEN (SCREEN_FOCUS_SCREEN (x_focus_screen));
+      if (x_highlight_screen->display.nothing == 0)
+       XSET (SCREEN_FOCUS_SCREEN (x_focus_screen), Lisp_Screen,
+             (x_highlight_screen = x_focus_screen));
     }
+  else
+    x_highlight_screen = 0;
 
-  return events_enqueued;
+  if (x_highlight_screen != old_highlight)
+    {
+      if (old_highlight)
+       screen_unhighlight (old_highlight);
+      if (x_highlight_screen)
+       screen_highlight (x_highlight_screen);
+    }
 }
 \f
 enum window_type
@@ -1279,22 +1280,12 @@ enum window_type
   text_window,
 };
 
-/* Symbol returned in input stream to indicate mouse movement. */
-Lisp_Object Qmouse_moved;
-
 /* Position of the mouse in characters */
 unsigned int x_mouse_x, x_mouse_y;
 
-/* Emacs window the mouse is in, if any. */
-extern Lisp_Object Vmouse_window;
-
 /* Offset in buffer of character under the pointer, or 0. */
 extern int mouse_buffer_offset;
 
-/* Part of the screen the mouse is in. */
-extern Lisp_Object Vmouse_screen_part;
-
-extern void pixel_to_glyph_translation ();
 extern int buffer_posn_from_coords ();
 
 /* Symbols from xfns.c to denote the different parts of a window.  */
@@ -1389,39 +1380,51 @@ notice_mouse_movement (result, motion_event, s, window_type, part)
 }
 #endif
 
-/* Given a pixel position (pix_x, pix_y) on the screen s, return
-   character co-ordinates in (*x, *y).  */
-void
-pixel_to_glyph_translation (s, pix_x, pix_y, x, y)
+\f
+/* Mouse clicks and mouse movement.  Rah.  */
+#ifdef HAVE_X11
+
+/* Given a pixel position (PIX_X, PIX_Y) on the screen S, return
+   glyph co-ordinates in (*X, *Y).  Set *BOUNDS to the rectangle
+   that the glyph at X, Y occupies, if BOUNDS != 0.  */
+static void
+pixel_to_glyph_coords (s, pix_x, pix_y, x, y, bounds)
      SCREEN_PTR s;
      register unsigned int pix_x, pix_y;
      register int *x, *y;
+     XRectangle *bounds;
 {
-  register struct screen_glyphs *s_glyphs = SCREEN_CURRENT_GLYPHS (s);
-  register int line = SCREEN_HEIGHT (s) - 1;
   int ibw = s->display.x->internal_border_width;
+  int width, height;
+  FONT_TYPE *font = s->display.x->font;
+
+  width = FONT_WIDTH (font);
+  height = FONT_HEIGHT (font);
 
   /* What line is it on?  */
-  line = SCREEN_HEIGHT (s) - 1;
-  while (s_glyphs->top_left_y[line] > pix_y)
-    line--;
-  *y = line;
+  if (pix_y < ibw)
+    *y = 0;
+  else if (pix_y > s->display.x->pixel_height - ibw)
+    *y = SCREEN_HEIGHT (s) - 1;
+  else
+    *y = (pix_y - ibw) / height;
 
-  /* Horizontally, is it in the border? */
+  /* And what column?  */
   if (pix_x < ibw)
     *x = 0;
-  
-  /* If it's off the right edge, clip it.  */
   else if (pix_x > s->display.x->pixel_width - ibw)
     *x = SCREEN_WIDTH (s) - 1;
-
-  /* It's in the midst of the screen; assume all the characters are
-     the same width, and figure the column.  */
   else
-    *x = (pix_x - ibw) / FONT_WIDTH (s->display.x->font);
+    *x = (pix_x - ibw) / width;
+
+  if (bounds)
+    {
+      bounds->width = width;
+      bounds->height = height;
+      bounds->x = ibw + (*x * width);
+      bounds->y = ibw + (*y * height);
+    }
 }
-\f
-#ifdef HAVE_X11
 
 /* Any buttons grabbed. */
 unsigned int x_mouse_grabbed;
@@ -1462,20 +1465,20 @@ construct_mouse_click (result, event, s, part, prefix)
      otherwise.  */
   result->kind = no_event;
   XSET (result->code, Lisp_Int, event->button);
+  result->timestamp = event->time;
   result->modifiers = (x_convert_modifiers (event->state)
                       | (event->type == ButtonRelease ? up_modifier : 0));
-  XSET (result->timestamp, Lisp_Int, (event->time & 0x7fffff));
 
   /* Notice if the mouse is still grabbed.  */
   if (event->type == ButtonPress)
     {
       if (! x_mouse_grabbed)
        Vmouse_depressed = Qt;
-      x_mouse_grabbed |= event->button;
+      x_mouse_grabbed |= (1 << event->button);
     }
   else if (event->type == ButtonRelease)
     {
-      x_mouse_grabbed &= ~(event->button);
+      x_mouse_grabbed &= ~(1 << event->button);
       if (!x_mouse_grabbed)
        Vmouse_depressed = Qnil;
     }
@@ -1501,10 +1504,7 @@ construct_mouse_click (result, event, s, part, prefix)
     {
       int row, column;
 
-      pixel_to_glyph_translation (s,
-                                 event->x, event->y,
-                                 &column, &row);
-
+      pixel_to_glyph_coords (s, event->x, event->y, &column, &row, NULL);
       result->kind = mouse_click;
       result->x = column;
       result->y = row;
@@ -1513,63 +1513,208 @@ construct_mouse_click (result, event, s, part, prefix)
 }
 
 
+/* 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 SCREEN_PTR last_mouse_screen;
+static XRectangle last_mouse_glyph;
+
+/* 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;
+
+/* Function to report a mouse movement to the mainstream Emacs code.
+   The input handler calls this.
+
+   We have received a mouse movement event, which is given in *event.
+   If the mouse is over a different glyph than it was last time, tell
+   the mainstream emacs code by setting mouse_moved.  If not, ask for
+   another motion event, so we can check again the next time it moves.  */
+static void
+note_mouse_position (screen, event)
+     SCREEN_PTR screen;
+     XMotionEvent *event;
+
+{
+  last_mouse_movement_time = event->time;
+
+  /* Has the mouse moved off the glyph it was on at the last sighting?  */
+  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)
+    mouse_moved = 1;
+  else
+    {
+      /* It's on the same glyph.  Call XQueryPointer so we'll get an
+        event the next time the mouse moves and we can see if it's
+        *still* on the same glyph.  */
+      int dummy;
+      
+      XQueryPointer (event->display, event->window,
+                    (Window *) &dummy, (Window *) &dummy,
+                    &dummy, &dummy, &dummy, &dummy,
+                    (unsigned int *) &dummy);
+    }
+}
+
+/* Return the current position of the mouse.
+
+   This clears the mouse_moved flag, so we can wait for the next mouse
+   position.  This also calls XQueryPointer, which will cause the
+   server to give us another MotionNotify when the mouse moves again.
+   */
+
+static void
+XTmouse_position (s, x, y, time)
+     SCREEN_PTR *s;
+     Lisp_Object *x, *y;
+     unsigned long *time;
+{
+  int ix, iy, dummy;
+  Display *d = x_current_display;
+  Window guess, root, child;
+
+  BLOCK_INPUT;
+
+  /* I would like to have an X function that just told me the
+     innermost window containing the mouse.  
+
+  /* There doesn't seem to be any way to just get the innermost window
+     containing the pointer, no matter what X screen it's on; you have
+     to guess a window, and then X will tell you which one of that
+     window's children it's in.  If the pointer isn't in any of that
+     window's children, it gives you a root window that contains it.
+
+     So we start with the selected screen's window and chase down
+     branches under the guidance of XQueryPointer until we hit a leaf
+     (all of the Emacs windows we care about are leaf windows).  If at
+     any time XQueryPointer returns false, that means that the current
+     window does not contain the pointer any more (perhaps it moved),
+     so we start with the root window XQueryPointer has given us and
+     start again.  */
+
+  guess = selected_screen->display.x->window_desc;
+  for (;;)
+    if (XQueryPointer (d, guess, &root, &child,
+                      &dummy, &dummy, &ix, &iy, (unsigned int *) &dummy))
+      {
+       if (child == None)
+         /* Guess is a leaf window, and it contains the pointer.  */
+         break;
+       else 
+         guess = child;
+      }
+    else
+      /* When XQueryPointer returns False, the pointer isn't in guess
+         anymore, but root is the root window of the screen we should
+         try instead.  */
+      guess = root;
+
+  *s = last_mouse_screen = x_window_to_screen (guess);
+  if (! *s)
+    *x = *y = Qnil;
+  else
+    {
+      pixel_to_glyph_coords (*s, ix, iy, &ix, &iy, &last_mouse_glyph);
+      XSET (*x, Lisp_Int, ix);
+      XSET (*y, Lisp_Int, iy);
+    }
+
+  mouse_moved = 0;
+
+  /* I don't know how to find the time for the last movement; it seems
+     like XQueryPointer ought to return it, but it doesn't.  So, we'll
+     return the time of the last MotionNotify event we received.  Note
+     that the use of motion hints means that this isn't guaranteed to
+     be accurate at all.  */
+  *time = last_mouse_movement_time;
+
+  UNBLOCK_INPUT;
+}
+
+\f
 static char *events[] =
 {
   "0: ERROR!",
   "1: REPLY",
   "KeyPress",
-   "KeyRelease",
-   "ButtonPress",
-   "ButtonRelease",
-   "MotionNotify",
-   "EnterNotify",
-   "LeaveNotify",
-   "FocusIn",
-   "FocusOut",
-   "KeymapNotify",
-   "Expose",
-   "GraphicsExpose",
-   "NoExpose",
-   "VisibilityNotify",
-   "CreateNotify",
-   "DestroyNotify",
-   "UnmapNotify",
-   "MapNotify",
-   "MapRequest",
-   "ReparentNotify",
-   "ConfigureNotify",
-   "ConfigureRequest",
-   "GravityNotify",
-   "ResizeRequest",
-   "CirculateNotify",
-   "CirculateRequest",
-   "PropertyNotify",
-   "SelectionClear",
-   "SelectionRequest",
-   "SelectionNotify",
-   "ColormapNotify",
-   "ClientMessage",
-   "MappingNotify",
-   "LASTEvent"
+  "KeyRelease",
+  "ButtonPress",
+  "ButtonRelease",
+  "MotionNotify",
+  "EnterNotify",
+  "LeaveNotify",
+  "FocusIn",
+  "FocusOut",
+  "KeymapNotify",
+  "Expose",
+  "GraphicsExpose",
+  "NoExpose",
+  "VisibilityNotify",
+  "CreateNotify",
+  "DestroyNotify",
+  "UnmapNotify",
+  "MapNotify",
+  "MapRequest",
+  "ReparentNotify",
+  "ConfigureNotify",
+  "ConfigureRequest",
+  "GravityNotify",
+  "ResizeRequest",
+  "CirculateNotify",
+  "CirculateRequest",
+  "PropertyNotify",
+  "SelectionClear",
+  "SelectionRequest",
+  "SelectionNotify",
+  "ColormapNotify",
+  "ClientMessage",
+  "MappingNotify",
+  "LASTEvent"
 };
 #else  /* X10 */
 #define XEvent XKeyPressedEvent
 #endif /* HAVE_X11 */ 
 
-/* Symbols returned in the input stream to indicate various X events.  */
-Lisp_Object Qmapped_screen;
-Lisp_Object Qunmapped_screen;
-Lisp_Object Qexited_scrollbar;
-Lisp_Object Qexited_window;
-Lisp_Object Qredraw_screen;
-Lisp_Object Qmouse_click;
-Lisp_Object Qscrollbar_click;
-
 /* Timestamp of enter window event.  This is only used by XTread_socket,
    but we have to put it out here, since static variables within functions
    sometimes don't work.  */
 static Time enter_timestamp;
 
+/* Communication with window managers. */
+Atom Xatom_wm_protocols;
+
+/* Kinds of protocol things we may receive. */
+Atom Xatom_wm_take_focus;
+Atom Xatom_wm_save_yourself;
+Atom Xatom_wm_delete_window;
+
+/* Other WM communication */
+Atom Xatom_wm_configure_denied;          /* When our config request is denied */
+Atom Xatom_wm_window_moved;      /* When the WM moves us. */
+
 /* Read events coming from the X server.
    This routine is called by the SIGIO handler.
    We return as soon as there are no more events to be read.
@@ -1640,6 +1785,51 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
       switch (event.type)
        {
 #ifdef HAVE_X11
+       case ClientMessage:
+         {
+           if (event.xclient.message_type == Xatom_wm_protocols
+               && event.xclient.format == 32)
+             {
+               if (event.xclient.data.l[0] == Xatom_wm_take_focus)
+                 {
+                   s = x_window_to_screen (event.xclient.window);
+                   if (s)
+                     x_focus_on_screen (s);
+                   /* Not certain about handling scrollbars here */
+                 }
+               else if (event.xclient.data.l[0] == Xatom_wm_save_yourself)
+                 {
+                   /* Save state modify the WM_COMMAND property to
+                      something which can reinstate us. This notifies
+                      the session manager, who's looking for such a
+                      PropertyNotify.  Can restart processing when
+                      a keyboard or mouse event arrives. */
+                   if (numchars > 0)
+                     {
+                     }
+                 }
+               else if (event.xclient.data.l[0] == Xatom_wm_delete_window)
+                 {
+                   struct screen *s = x_window_to_screen (event.xclient.window);
+
+                   if (s)
+                     if (numchars > 0)
+                       {
+                       }
+                 }
+             }
+           else if (event.xclient.message_type == Xatom_wm_configure_denied)
+             {
+             }
+           else if (event.xclient.message_type == Xatom_wm_window_moved)
+             {
+               int new_x, new_y;
+
+               new_x = event.xclient.data.s[0];
+               new_y = event.xclient.data.s[1];
+             }
+         }
+         break;
 
        case SelectionClear:    /* Someone has grabbed ownership. */
          x_disown_selection (event.xselectionclear.window,
@@ -1748,7 +1938,6 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                   disabled; you don't want to spend time updating a
                   display that won't ever be seen.  */
                s->visible = 0;
-               Vmouse_window = Vmouse_screen_part = Qnil;
                x_mouse_x = x_mouse_y = -1;
              }
          }
@@ -1789,6 +1978,14 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
              KeySym keysym;
              XComposeStatus status;
              char copy_buffer[80];
+             int modifiers = event.xkey.state;
+
+             /* Some keyboards generate different characters
+                depending on the state of the meta key, in an attempt
+                to support non-English typists.  It would be nice to
+                keep this functionality somehow, but for now, we will
+                just clear the meta-key flag to get the 'pure' character.  */
+             event.xkey.state &= ~Mod1Mask;
 
              /* This will have to go some day... */
              nbytes = XLookupString (&event.xkey,
@@ -1797,16 +1994,23 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                                      &keysym,
                                      &status);
 
+             /* Strip off the vendor-specific keysym bit, and take a shot
+                at recognizing the codes.  HP servers have extra keysyms
+                that fit into the MiscFunctionKey category.  */
+             keysym &= ~(1<<28);
+
              if (numchars > 1)
                {
-                 if (IsCursorKey (keysym)          /* >= 0xff50  < 0xff60 */
-                     || IsMiscFunctionKey (keysym) /* >= 0xff60  < 0xff80 */
-                     || IsKeypadKey (keysym) /* >= 0xff80  <= 0xffbd */
-                     || IsFunctionKey (keysym)) /* >= 0xffbe  <= 0xffe0 */
+                 if (IsCursorKey (keysym)          /* 0xff50 <= x < 0xff60 */
+                     || IsMiscFunctionKey (keysym) /* 0xff60 <= x < 0xff80 */
+                     || IsKeypadKey (keysym)       /* 0xff80 <= x < 0xffbe */
+                     || IsFunctionKey (keysym))    /* 0xffbe <= x < 0xffe1 */
                    {
                      bufp->kind = non_ascii_keystroke;
-                     bufp->code = (unsigned) keysym - 0xff50;
-                     bufp->modifiers = x_convert_modifiers (event.xkey.state);
+                     XSET (bufp->code, Lisp_Int, (unsigned) keysym - 0xff50);
+                     bufp->screen = s;
+                     bufp->modifiers = x_convert_modifiers (modifiers);
+                     bufp->timestamp = event.xkey.time;
                      bufp++;
                      count++;
                      numchars--;
@@ -1817,10 +2021,12 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
 
                      if (nbytes == 1)
                        {
-                         if (event.xkey.state & Mod1Mask)
+                         if (modifiers & Mod1Mask)
                            *copy_buffer |= METABIT;
                          bufp->kind = ascii_keystroke;
                          XSET (bufp->code, Lisp_Int, *copy_buffer);
+                         bufp->screen = s;
+                         bufp->timestamp = event.xkey.time;
                          bufp++;
                        }
                      else
@@ -1828,6 +2034,8 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                          {
                            bufp->kind = ascii_keystroke;
                            XSET (bufp->code, Lisp_Int, copy_buffer[i]);
+                           bufp->screen = s;
+                           bufp->timestamp = event.xkey.time;
                            bufp++;
                          }
 
@@ -1875,6 +2083,8 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                  {
                    bufp->kind = ascii_keystroke;
                    XSET (bufp->code, Lisp_Int, where_mapping[i]);
+                   XSET (bufp->time, Lisp_Int, event.xkey.time);
+                   bufp->screen = s;
                    bufp++;
                  }
                count += nbytes;
@@ -1886,6 +2096,8 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
 
 #ifdef HAVE_X11
        case EnterNotify:
+         s = x_window_to_screen (event.xcrossing.window);
+
          if (event.xcrossing.detail == NotifyInferior) /* Left Scrollbar */
            ;
          else if (event.xcrossing.focus)               /* Entered Window */
@@ -1895,17 +2107,12 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
              struct input_event emacs_event;
              emacs_event.kind = no_event;
 
-             s = x_window_to_screen (event.xcrossing.window);
-
              /* Avoid nasty pop/raise loops. */
              if (s && (!(s->auto_raise)
                        || !(s->auto_lower)
                        || (event.xcrossing.time - enter_timestamp) > 500))
                {
-                 int n = x_new_focus_screen (s, bufp, numchars);
-                 bufp += n;
-                 count += n;
-                 numchars -= n;
+                 x_new_focus_screen (s);
                  enter_timestamp = event.xcrossing.time;
                }
 #if 0
@@ -1929,6 +2136,8 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                }
 #endif
            }
+         else if (s == x_focus_screen)
+           x_new_focus_screen (0);
 #if 0
          else if (s = x_window_to_screen (event.xcrossing.window))
            x_mouse_screen = s;
@@ -1939,12 +2148,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
        case FocusIn:
          s = x_window_to_screen (event.xfocus.window);
          if (s)
-           {
-             int n = x_new_focus_screen (s, bufp, numchars);
-             bufp += n;
-             count += n;
-             numchars -= n;
-           }
+           x_new_focus_screen (s);
          break;
 
        case LeaveNotify:
@@ -1952,27 +2156,18 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
              && event.xcrossing.subwindow == None
              && event.xcrossing.mode == NotifyNormal)
            {
+             s = x_window_to_screen (event.xcrossing.window);
              if (event.xcrossing.focus)
-               {
-                 int n;
-                 s = x_window_to_screen (event.xcrossing.window);
-                 n = x_new_focus_screen (s, bufp, numchars);
-                 bufp += n;
-                 count += n;
-                 numchars -= n;
-               }
+               x_new_focus_screen (s);
+             else if (s == x_focus_screen)
+               x_new_focus_screen (0);
            }
          break;
 
        case FocusOut:
          s = x_window_to_screen (event.xfocus.window);
          if (s && s == x_focus_screen)
-           {
-             int n = x_new_focus_screen (0, bufp, numchars);
-             bufp += n;
-             count += n;
-             numchars -= n;
-           }
+           x_new_focus_screen (0);
          break;
 
 #else /* not HAVE_X11 */
@@ -1984,14 +2179,12 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
            break;              /* Entering our own subwindow.  */
 
          {
-           extern int waiting_for_input;
            struct screen *old_s = x_input_screen;
 
            s = x_window_to_screen (event.window);
            x_mouse_screen = s;
 
-           if (waiting_for_input && x_focus_screen == 0)
-             x_new_selected_screen (s);
+           x_new_focus_screen (s);
          }
          break;
 
@@ -2020,15 +2213,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
          {
            s = x_window_to_screen (event.xmotion.window);
            if (s)
-             {
-               int row, column;
-               
-               pixel_to_glyph_translation (s,
-                                           event.xmotion.x, event.xmotion.y,
-                                           &column, &row);
-
-               note_mouse_position (s, column, row, event.xmotion.time);
-             }
+             note_mouse_position (s, &event.xmotion);
 #if 0
            else if ((s = x_window_to_scrollbar (event.xmotion.window,
                                                 &part, &prefix)))
@@ -2055,27 +2240,23 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                     - s->display.x->h_scrollbar_height)
                    / FONT_HEIGHT (s->display.x->font));
 
-           if (columns != s->width || rows != s->height)
+           /* Even if the number of character rows and columns has
+              not changed, the font size may have changed, so we need
+              to check the pixel dimensions as well.  */
+           if (columns != s->width
+               || rows != s->height
+               || event.xconfigure.width != s->display.x->pixel_width
+               || event.xconfigure.height != s->display.x->pixel_height)
              {
-               XEvent ignored_event;
-
                change_screen_size (s, rows, columns, 0);
                x_resize_scrollbars (s);
                SET_SCREEN_GARBAGED (s);
-#if 0
-               dumprectangle (s, 0, 0, PIXEL_WIDTH (s), PIXEL_HEIGHT (s));
-               /* Throw away the exposures generated by this reconfigure. */
-               while (XCheckWindowEvent (x_current_display,
-                                         event.xconfigure.window,
-                                         ExposureMask, &ignored_event)
-                      == True);
-#endif
              }
 
-           s->display.x->left_pos = event.xconfigure.x;
-           s->display.x->top_pos = event.xconfigure.y;
            s->display.x->pixel_width = event.xconfigure.width;
            s->display.x->pixel_height = event.xconfigure.height;
+           s->display.x->left_pos = event.xconfigure.x;
+           s->display.x->top_pos = event.xconfigure.y;
            break;
          }
 
@@ -2140,10 +2321,14 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
            {
              bufp->kind = ascii_keystroke;
              bufp->code = (char) 'X' & 037; /* C-x */
+             bufp->screen = s;
+             XSET (bufp->time, Lisp_Int, event.xkey.time);
              bufp++;
 
              bufp->kind = ascii_keystroke;
              bufp->code = (char) 0; /* C-@ */
+             bufp->screen = s;
+             XSET (bufp->time, Lisp_Int, event.xkey.time);
              bufp++;
 
              count += 2;
@@ -2185,7 +2370,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
       int mask = 1 << fd;
 
       if (0 != select (fd + 1, &mask, (long *) 0, (long *) 0,
-                      (struct timeval *) 0)
+                      (EMACS_TIME) 0)
          && !XStuffPending ())
        kill (getpid (), SIGHUP);
     }
@@ -2264,37 +2449,6 @@ x_read_exposes ()
 }
 #endif /* HAVE_X11 */
 
-static int
-XTmouse_tracking_enable (enable)
-     int enable;
-{
-  Lisp_Object tail;
-
-  /* Go through the list of screens and turn on/off mouse tracking for
-     each of them.  */
-  for (tail = Vscreen_list; CONSP (tail); tail = XCONS (tail)->cdr)
-    {
-      if (XTYPE (XCONS (tail)->car) != Lisp_Screen)
-       abort ();
-      if (XSCREEN (XCONS (tail)->car)->output_method == output_x_window)
-       XSelectInput (x_current_display,
-                     XSCREEN (XCONS (tail)->car)->display.x->window_desc,
-                     (enable
-                      ? (STANDARD_EVENT_SET
-                         | PointerMotionMask
-                         | ButtonReleaseMask)
-                      : STANDARD_EVENT_SET));
-    }
-}
-
-
-static Lisp_Object
-XTmouse_position ()
-{
-  
-}
-
-
 \f
 /* Draw a hollow box cursor.  Don't change the inside of the box.  */
 
@@ -2368,6 +2522,7 @@ clear_cursor (s)
   s->phys_cursor_x = -1;
 }
 
+static void
 x_display_bar_cursor (s, on)
      struct screen *s;
      int on;
@@ -2397,7 +2552,7 @@ x_display_bar_cursor (s, on)
       s->phys_cursor_x = phys_x = -1;
     }
 
-  if (on && s == x_focus_screen)
+  if (on && s == x_highlight_screen)
     {
       x1 = s->cursor_x * FONT_WIDTH (s->display.x->font)
        + s->display.x->internal_border_width;
@@ -2417,54 +2572,23 @@ x_display_bar_cursor (s, on)
 }
 
 
-/* Redraw the glyph at ROW, COLUMN on screen S, in the style HIGHLIGHT.
-   If there is no character there, erase the area.  HIGHLIGHT is as
-   defined for dumpglyphs.  */
+/* Redraw the glyph at ROW, COLUMN on screen S, in the style
+   HIGHLIGHT.  HIGHLIGHT is as defined for dumpglyphs.  Return the
+   glyph drawn.  */
 
 static void
-x_draw_single_glyph (s, row, column, highlight)
+x_draw_single_glyph (s, row, column, glyph, highlight)
      struct screen *s;
      int row, column;
+     GLYPH glyph;
      int highlight;
 {
-  register struct screen_glyphs *current_screen = SCREEN_CURRENT_GLYPHS (s);
-
-  /* If there is supposed to be a character there, redraw it
-     in that line's normal video.  */
-  if (current_screen->enable[row]
-      && column < current_screen->used[row])
-    dumpglyphs (s,
-               (column * FONT_WIDTH (s->display.x->font)
-                + s->display.x->internal_border_width),
-               (row * FONT_HEIGHT (s->display.x->font)
-                + s->display.x->internal_border_width),
-               &current_screen->glyphs[row][column],
-               1, highlight, s->display.x->font);
-  else
-    {
-#ifdef HAVE_X11
-      static GLYPH a_space_glyph = SPACEGLYPH;
-      dumpglyphs (s,
-                 (column * FONT_WIDTH (s->display.x->font)
-                  + s->display.x->internal_border_width),
-                 (row * FONT_HEIGHT (s->display.x->font)
-                  + s->display.x->internal_border_width),
-                 &a_space_glyph, 1, highlight, s->display.x->font);
-#else
-      XPixSet (s->display.x->window_desc,
-              (column * FONT_WIDTH (s->display.x->font)
-               + s->display.x->internal_border_width),
-              (row * FONT_HEIGHT (s->display.x->font)
-               + s->display.x->internal_border_width),
-              FONT_WIDTH (s->display.x->font),
-              FONT_HEIGHT (s->display.x->font),
-              (highlight == 0
-               ? s->display.x->background_pixel
-               : (highlight == 1
-                  ? s->display.x->foreground_pixel
-                  : s->display.x->cursor_pixel)));
-#endif /* HAVE_X11 */
-    }
+  dumpglyphs (s,
+             (column * FONT_WIDTH (s->display.x->font)
+              + s->display.x->internal_border_width),
+             (row * FONT_HEIGHT (s->display.x->font)
+              + s->display.x->internal_border_width),
+             &glyph, 1, highlight, s->display.x->font);
 }
 
 /* Turn the displayed cursor of screen S on or off according to ON.
@@ -2476,11 +2600,20 @@ x_display_box_cursor (s, on)
      struct screen *s;
      int on;
 {
+  struct screen_glyphs *current_glyphs = SCREEN_CURRENT_GLYPHS (s);
+
+  /* If we're not updating, then we want to use the current screen's
+     cursor position, not our local idea of where the cursor ought to be.  */
+  if (s != updating_screen)
+    {
+      curs_x = SCREEN_CURSOR_X (s);
+      curs_y = SCREEN_CURSOR_Y (s);
+    }
+
   if (! s->visible)
     return;
 
   /* If cursor is off and we want it off, return quickly.  */
-
   if (!on && s->phys_cursor_x < 0)
     return;
 
@@ -2490,16 +2623,15 @@ x_display_box_cursor (s, on)
      erase it.  */
   if (s->phys_cursor_x >= 0
       && (!on
-         || s->phys_cursor_x != s->cursor_x
-         || s->phys_cursor_y != s->cursor_y
+         || s->phys_cursor_x != curs_x
+         || s->phys_cursor_y != curs_y
          || (s->display.x->text_cursor_kind != hollow_box_cursor
-             && (s != x_focus_screen))))
+             && (s != x_highlight_screen))))
     {
       /* Erase the cursor by redrawing the character underneath it.  */
       x_draw_single_glyph (s, s->phys_cursor_y, s->phys_cursor_x,
-                          (SCREEN_CURRENT_GLYPHS (s)
-                           ->highlight[s->phys_cursor_y]));
-
+                          s->phys_cursor_glyph,
+                          current_glyphs->highlight[s->phys_cursor_y]);
       s->phys_cursor_x = -1;
     }
 
@@ -2509,21 +2641,27 @@ x_display_box_cursor (s, on)
   if (on
       && (s->phys_cursor_x < 0
          || (s->display.x->text_cursor_kind != filled_box_cursor
-             && s == x_focus_screen)))
+             && s == x_highlight_screen)))
     {
-      if (s != x_focus_screen)
+      s->phys_cursor_glyph
+       = ((current_glyphs->enable[curs_y]
+           && curs_x < current_glyphs->used[curs_y])
+          ? current_glyphs->glyphs[curs_y][curs_x]
+          : SPACEGLYPH);
+      if (s != x_highlight_screen)
        {
          x_draw_box (s);
          s->display.x->text_cursor_kind = hollow_box_cursor;
        }
       else
        {
-         x_draw_single_glyph (s, s->cursor_y, s->cursor_x, 2);
+         x_draw_single_glyph (s, curs_y, curs_x,
+                              s->phys_cursor_glyph, 2);
          s->display.x->text_cursor_kind = filled_box_cursor;
        }
 
-      s->phys_cursor_x = s->cursor_x;
-      s->phys_cursor_y = s->cursor_y;
+      s->phys_cursor_x = curs_x;
+      s->phys_cursor_y = curs_y;
     }
 
   if (updating_screen != s)
@@ -2649,10 +2787,6 @@ x_text_icon (s, icon_name)
   char *X_DefaultValue;
   Bitmap b1;
 
-#if 0  /* This doesn't seem to be used, but I can't quite believe it.  */
-  static Pixmap grey_pixmap;
-#endif
-
 #ifndef WhitePixel
 #define WhitePixel 1
 #endif
@@ -2667,7 +2801,9 @@ x_text_icon (s, icon_name)
 
   if (icon_font_info == 0)
     icon_font_info
-      = XGetFont (XGetDefault (XDISPLAY invocation_name, "BodyFont"));
+      = XGetFont (XGetDefault (XDISPLAY
+                              (char *) XSTRING (invocation_name)->data,
+                              "BodyFont"));
 
 #ifdef HAVE_X11
   if (icon_name)
@@ -2714,6 +2850,19 @@ x_text_icon (s, icon_name)
   return 0;
 }
 \f
+/* Handling X errors.  */
+
+/* A handler for SIGPIPE, when it occurs on the X server's connection.
+   This basically does an orderly shutdown of Emacs.  */
+static SIGTYPE
+x_death_handler ()
+{
+  if (_Xdebug)
+    abort ();
+  else
+    Fkill_emacs (make_number (70));
+}
+
 static char *x_proto_requests[] =
 {
   "CreateWindow",
@@ -2900,14 +3049,9 @@ x_error_handler (disp, event)
     }
   UNBLOCK_INPUT;
 
-  if (_Xdebug)
-    abort ();
-  else
-    Fkill_emacs (make_number (70));
+  x_death_handler ();
 }
 
-/* Initialize communication with the X window server.  */
-
 #if 0
 static unsigned int x_wire_count;
 x_trace_wire ()
@@ -2955,7 +3099,7 @@ x_new_font (s, fontname)
   if (n_matching_fonts == 0)
     return 1;
 
-  /* See if we've already loaded this font. */
+  /* See if we've already loaded a matching font. */
   {
     int i, j;
 
@@ -2972,10 +3116,8 @@ x_new_font (s, fontname)
   
   /* If we have, just return it from the table.  */
   if (already_loaded)
-    {
-      s->display.x->font = x_font_table[already_loaded];
-    }
-
+    s->display.x->font = x_font_table[already_loaded];
+  
   /* Otherwise, load the font and add it to the table.  */
   else
     {
@@ -2996,7 +3138,7 @@ x_new_font (s, fontname)
       /* Do we need to grow the table?  */
       else if (n_fonts >= x_font_table_size)
        {
-         x_font_table_size <<= 1;
+         x_font_table_size *= 2;
          x_font_table
            = (XFontStruct **) xrealloc (x_font_table,
                                         (x_font_table_size
@@ -3170,16 +3312,24 @@ x_focus_on_screen (s)
      struct screen *s;
 {
   x_raise_screen (s);
+#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
+     doing with this code, do it to x_unfocus_screen too.  */
   XSetInputFocus (x_current_display, s->display.x->window_desc,
                  RevertToPointerRoot, CurrentTime);
+#endif
 }
 
 x_unfocus_screen (s)
      struct screen *s;
 {
+#if 0
+  /* Look at the remarks in x_focus_on_screen.  */
   if (x_focus_screen == s)
     XSetInputFocus (x_current_display, PointerRoot,
                    RevertToPointerRoot, CurrentTime);
+#endif
 }
 
 #endif
@@ -3219,40 +3369,33 @@ x_make_screen_visible (s)
 {
   int mask;
 
-  if (s->visible)
-    {
-      BLOCK_INPUT;
-      XRaiseWindow (XDISPLAY s->display.x->window_desc);
-      XFlushQueue ();
-      UNBLOCK_INPUT;
-      return;
-    }
-
   BLOCK_INPUT;
-#ifdef HAVE_X11
-
-  if (! EQ (Vx_no_window_manager, Qt))
-    x_wm_set_window_state (s, NormalState);
 
-  XMapWindow (XDISPLAY s->display.x->window_desc);
-  if (s->display.x->v_scrollbar != 0 || s->display.x->h_scrollbar != 0)
-    XMapSubwindows (x_current_display, s->display.x->window_desc);
+  if (! SCREEN_VISIBLE_P (s))
+    {
+#ifdef HAVE_X11
+      if (! EQ (Vx_no_window_manager, Qt))
+       x_wm_set_window_state (s, NormalState);
 
+      XMapWindow (XDISPLAY s->display.x->window_desc);
+      if (s->display.x->v_scrollbar != 0 || s->display.x->h_scrollbar != 0)
+       XMapSubwindows (x_current_display, s->display.x->window_desc);
 #else
-  XMapWindow (XDISPLAY s->display.x->window_desc);
-  if (s->display.x->icon_desc != 0)
-    XUnmapWindow (s->display.x->icon_desc);
+      XMapWindow (XDISPLAY s->display.x->window_desc);
+      if (s->display.x->icon_desc != 0)
+       XUnmapWindow (s->display.x->icon_desc);
 
-  /* Handled by the MapNotify event for X11 */
-  s->visible = 1;
-  s->iconified = 0;
+      /* Handled by the MapNotify event for X11 */
+      s->visible = 1;
+      s->iconified = 0;
 
-  /* NOTE: this may cause problems for the first screen. */
-  XTcursor_to (0, 0);
-#endif /* not HAVE_X11 */
+      /* NOTE: this may cause problems for the first screen. */
+      XTcursor_to (0, 0);
+#endif                         /* not HAVE_X11 */
+    }
 
-  XRaiseWindow (XDISPLAY s->display.x->window_desc);
   XFlushQueue ();
+
   UNBLOCK_INPUT;
 }
 
@@ -3390,6 +3533,8 @@ x_destroy_window (s, displ)
   free (displ.x);
   if (s == x_focus_screen)
     x_focus_screen = 0;
+  if (s == x_highlight_screen)
+    x_highlight_screen = 0;
 }
 \f
 #ifndef HAVE_X11
@@ -3474,6 +3619,9 @@ x_wm_set_size_hint (s, prompting)
   Window window = s->display.x->window_desc;
 
   size_hints.flags = PResizeInc | PMinSize | PMaxSize;
+#ifdef PBaseSize
+  size_hints.flags |= PBaseSize;
+#endif
 
   flexlines = s->height;
 
@@ -3558,19 +3706,6 @@ x_wm_set_icon_position (s, icon_x, icon_y)
 }
 
 \f
-static void
-init_input_symbols ()
-{
-  Qmapped_screen = intern ("mapped-screen");
-  Qunmapped_screen = intern ("unmapped-screen");
-  Qexited_scrollbar = intern ("exited-scrollbar");
-  Qexited_window = intern ("exited-window");
-  Qredraw_screen = intern ("redraw-screen");
-  Qmouse_moved = intern ("mouse-moved");
-  Qmouse_click = intern ("mouse-click");
-  Qscrollbar_click = intern ("scrollbar-click");
-}
-
 void
 x_term_init (display_name)
      char *display_name;
@@ -3580,6 +3715,8 @@ x_term_init (display_name)
 #ifdef F_SETOWN
   extern int old_fcntl_owner;
 #endif
+  
+  x_focus_screen = x_highlight_screen = 0;
 
   x_current_display = XOpenDisplay (display_name);
   if (x_current_display == 0)
@@ -3596,8 +3733,7 @@ x_term_init (display_name)
     XSetAfterFunction (x_current_display, x_trace_wire);
 #endif
 
-    invocation_name = (char *)
-      XSTRING (Ffile_name_nondirectory (Fcar (Vcommand_line_args)))->data;
+    invocation_name = Ffile_name_nondirectory (Fcar (Vcommand_line_args));
 
     /* Try to get the host name; if the buffer is too short, try
        again.  Apparently, the only indication gethostname gives of
@@ -3615,15 +3751,24 @@ x_term_init (display_name)
        hostname_size <<= 1;
        hostname = (char *) xrealloc (hostname, hostname_size);
       }
-    id_name = (char *) xmalloc (strlen (invocation_name)
+    x_id_name = (char *) xmalloc (XSTRING (invocation_name)->size
                                + strlen (hostname)
                                + 2);
-    sprintf (id_name, "%s@%s", invocation_name, hostname);
+    sprintf (x_id_name, "%s@%s", XSTRING (invocation_name)->data, hostname);
   }
   
   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;
+  ConnectionNumber (x_current_display) = 0;    /* Looks a little strange?
+                                                * check the def of the macro;
+                                                * it is a genuine lvalue */
+#endif /* not SYSV_STREAMS */
+
 #endif /* HAVE_X11 */
   
 #ifdef F_SETOWN
@@ -3662,7 +3807,8 @@ x_term_init (display_name)
   read_socket_hook = XTread_socket;
   cursor_to_hook = XTcursor_to;
   reassert_line_highlight_hook = XTreassert_line_highlight;
-  mouse_tracking_enable_hook = XTmouse_tracking_enable;
+  screen_rehighlight_hook = XTscreen_rehighlight;
+  mouse_position_hook = XTmouse_position;
   
   scroll_region_ok = 1;                /* we'll scroll partial screens */
   char_ins_del_ok = 0;         /* just as fast to write the line */
@@ -3672,8 +3818,6 @@ x_term_init (display_name)
                                   off the bottom */
   baud_rate = 19200;
 
-  init_input_symbols ();
-
   XHandleError (x_error_handler);
   XHandleIOError (x_error_handler);
 
@@ -3682,7 +3826,14 @@ x_term_init (display_name)
   signal (SIGWINCH, SIG_DFL);
 #endif /* SIGWINCH */
 
-  signal (SIGPIPE, x_error_handler);
+  signal (SIGPIPE, x_death_handler);
+}
+
+void
+syms_of_xterm ()
+{
+  staticpro (&invocation_name);
+  invocation_name = Qnil;
 }
 #endif /* HAVE_X11 */
 #endif /* HAVE_X_WINDOWS */