*** empty log message ***
[bpt/emacs.git] / src / xterm.c
index 3e5da25..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>
@@ -161,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.  */
 
@@ -251,8 +245,6 @@ static WINDOWINFO_TYPE windowinfo;
 
 extern int errno;
 
-extern Lisp_Object Vglobal_minibuffer_screen;
-
 extern Display *XOpenDisplay ();
 extern Window XCreateWindow ();
 
@@ -266,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
@@ -295,7 +287,6 @@ XTupdate_begin (s)
 #ifndef HAVE_X11
   dumpqueue ();
 #endif
-  x_display_cursor (s, 0);
   UNBLOCK_INPUT;
 }
 
@@ -370,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;
 {
@@ -403,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
@@ -563,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)
     {
@@ -590,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;
 {
@@ -610,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,
@@ -948,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);
@@ -1102,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;
@@ -1286,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.  */
@@ -1396,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;
@@ -1469,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;
     }
@@ -1508,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;
@@ -1520,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.
@@ -1647,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,
@@ -1755,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;
              }
          }
@@ -1796,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,
@@ -1804,17 +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->screen = XSCREEN (SCREEN_FOCUS_SCREEN (s));
-                     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--;
@@ -1825,11 +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;
-                         bufp->screen = XSCREEN (SCREEN_FOCUS_SCREEN (s));
                          XSET (bufp->code, Lisp_Int, *copy_buffer);
+                         bufp->screen = s;
+                         bufp->timestamp = event.xkey.time;
                          bufp++;
                        }
                      else
@@ -1837,7 +2034,8 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                          {
                            bufp->kind = ascii_keystroke;
                            XSET (bufp->code, Lisp_Int, copy_buffer[i]);
-                           bufp->screen = XSCREEN (SCREEN_FOCUS_SCREEN (s));
+                           bufp->screen = s;
+                           bufp->timestamp = event.xkey.time;
                            bufp++;
                          }
 
@@ -1885,7 +2083,8 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                  {
                    bufp->kind = ascii_keystroke;
                    XSET (bufp->code, Lisp_Int, where_mapping[i]);
-                   bufp->screen = XSCREEN (SCREEN_FOCUS_SCREEN (s));
+                   XSET (bufp->time, Lisp_Int, event.xkey.time);
+                   bufp->screen = s;
                    bufp++;
                  }
                count += nbytes;
@@ -1980,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_focus_screen (s);
+           x_new_focus_screen (s);
          }
          break;
 
@@ -2016,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)))
@@ -2051,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;
          }
 
@@ -2136,12 +2321,14 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
            {
              bufp->kind = ascii_keystroke;
              bufp->code = (char) 'X' & 037; /* C-x */
-             bufp->screen = XSCREEN (SCREEN_FOCUS_SCREEN (s));
+             bufp->screen = s;
+             XSET (bufp->time, Lisp_Int, event.xkey.time);
              bufp++;
 
              bufp->kind = ascii_keystroke;
              bufp->code = (char) 0; /* C-@ */
-             bufp->screen = XSCREEN (SCREEN_FOCUS_SCREEN (s));
+             bufp->screen = s;
+             XSET (bufp->time, Lisp_Int, event.xkey.time);
              bufp++;
 
              count += 2;
@@ -2183,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);
     }
@@ -2262,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.  */
 
@@ -2366,6 +2522,7 @@ clear_cursor (s)
   s->phys_cursor_x = -1;
 }
 
+static void
 x_display_bar_cursor (s, on)
      struct screen *s;
      int on;
@@ -2415,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.
@@ -2474,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;
 
@@ -2488,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_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,6 +2643,11 @@ x_display_box_cursor (s, on)
          || (s->display.x->text_cursor_kind != filled_box_cursor
              && s == x_highlight_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);
@@ -2516,12 +2655,13 @@ x_display_box_cursor (s, on)
        }
       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)
@@ -2647,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
@@ -2665,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)
@@ -2712,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",
@@ -2898,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 ()
@@ -2953,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;
 
@@ -2970,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
     {
@@ -2994,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
@@ -3225,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;
 }
 
@@ -3482,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;
 
@@ -3566,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;
@@ -3606,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
@@ -3625,10 +3751,10 @@ 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);
@@ -3682,7 +3808,7 @@ x_term_init (display_name)
   cursor_to_hook = XTcursor_to;
   reassert_line_highlight_hook = XTreassert_line_highlight;
   screen_rehighlight_hook = XTscreen_rehighlight;
-  mouse_tracking_enable_hook = XTmouse_tracking_enable;
+  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 */
@@ -3692,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);
 
@@ -3702,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 */