]> code.delx.au - gnu-emacs/blobdiff - src/xterm.c
Don't declare logb if it is a macro.
[gnu-emacs] / src / xterm.c
index 5d22c27ae1ee3bab33c189821028220fd738c16e..e994465c4bc82ee54b35fb04d70257160e952df5 100644 (file)
@@ -17,18 +17,8 @@ You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
-/* Serious problems:
-
-   Kludge: dup2 is used to put the X-connection socket into desc # 0
-   so that wait_reading_process_input will wait for it in place of
-   actual terminal input.
-   
-*/
-
 /* Xt features made by Fred Pierresteguy.  */
 
-#define NEW_SELECTIONS
-
 /* On 4.3 these lose if they come after xterm.h.  */
 /* On HP-UX 8.0 signal.h loses if it comes after config.h.  */
 /* Putting these at the beginning seems to be standard for other .c files.  */
@@ -98,10 +88,12 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 extern XtAppContext Xt_app_con;
 extern Widget Xt_app_shell;
 extern void free_frame_menubar ();
+extern void _XEditResCheckMessages ();
 #endif /* USE_X_TOOLKIT */
 
 #ifndef USE_X_TOOLKIT
 #define x_any_window_to_frame x_window_to_frame
+#define x_top_window_to_frame x_window_to_frame
 #endif
 
 #ifdef HAVE_X11
@@ -201,6 +193,9 @@ extern struct frame *updating_frame;
    x_focus_event_frame.  */
 struct frame *x_focus_frame;
 
+/* This is a frame waiting to be autoraised, within XTread_socket.  */
+struct frame *pending_autoraise_frame;
+
 /* The last frame mentioned in a FocusIn or FocusOut event.  This is
    separate from x_focus_frame, because whether or not LeaveNotify
    events cause us to lose focus depends on whether or not we have
@@ -266,7 +261,7 @@ static XRectangle last_mouse_glyph;
    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. */
+/* Record which buttons are currently pressed.  */
 unsigned int x_mouse_grabbed;
 
 /* This is a hack.  We would really prefer that XTmouse_position would
@@ -281,10 +276,15 @@ static Time last_mouse_movement_time;
    in its mouse-face, together with the window they apply to.
    As long as the mouse stays within this range, we need not
    redraw anything on its account.  */
-static int mouse_face_beg, mouse_face_end;
+static int mouse_face_beg_row, mouse_face_beg_col;
+static int mouse_face_end_row, mouse_face_end_col;
 static Lisp_Object mouse_face_window;
 static int mouse_face_face_id;
 
+/* 1 if a mouse motion event came and we didn't handle it right away because
+   gc was in progress.  */
+static int mouse_face_deferred_gc;
+
 /* FRAME and X, Y position of mouse when last checked for highlighting.  */
 static FRAME_PTR mouse_face_mouse_frame;
 static int mouse_face_mouse_x, mouse_face_mouse_y;
@@ -310,7 +310,7 @@ extern Window requestor_window;
 /* Nonzero enables some debugging for the X interface code. */
 extern int _Xdebug;
 
-extern Qface, Qmouse_face;
+extern Lisp_Object Qface, Qmouse_face;
 
 #else /* ! defined (HAVE_X11) */
 
@@ -351,8 +351,10 @@ extern FONT_TYPE *XOpenFont ();
 
 static void flashback ();
 static void redraw_previous_char ();
+static void redraw_following_char ();
 static unsigned int x_x_to_emacs_modifiers ();
 
+static int fast_find_position ();
 static void note_mouse_highlight ();
 static void clear_mouse_face ();
 static void show_mouse_face ();
@@ -393,9 +395,34 @@ XTupdate_begin (f)
 
   if (f == mouse_face_mouse_frame)
     {
+      /* Don't do highlighting for mouse motion during the update.  */
       mouse_face_defer = 1;
       if (!NILP (mouse_face_window))
-       clear_mouse_face ();
+       {
+         int firstline, lastline, i;
+         struct window *w = XWINDOW (mouse_face_window);
+
+         /* Find the first, and the last+1, lines affected by redisplay.  */
+         for (firstline = 0; firstline < f->height; firstline++)
+           if (FRAME_DESIRED_GLYPHS (f)->enable[firstline])
+             break;
+
+         lastline = f->height;
+         for (i = f->height - 1; i >= 0; i--)
+           {
+             if (FRAME_DESIRED_GLYPHS (f)->enable[i])
+               break;
+             else
+               lastline = i;
+           }
+
+         /* Can we tell that this update does not affect the window
+            where the mouse highlight is?  If so, no need to turn off.  */
+         if (! (firstline > (XFASTINT (w->top) + window_internal_height (w))
+                || lastline < XFASTINT (w->top)))
+           /* Otherwise turn off the mouse highlight now.  */
+           clear_mouse_face ();
+       }
     }
 #ifndef HAVE_X11
   dumpqueue ();
@@ -438,14 +465,18 @@ XTupdate_end (f)
   UNBLOCK_INPUT;
 }
 
-/* This is called when all windows on frame F are now up to date.  */
+/* This is called after a redisplay on frame F.  */
 
 static
 XTframe_up_to_date (f)
      FRAME_PTR f;
 {
-  if (f == mouse_face_mouse_frame)
-    note_mouse_highlight (f, mouse_face_mouse_x, mouse_face_mouse_y);
+  if (mouse_face_deferred_gc || f == mouse_face_mouse_frame)
+    {
+      note_mouse_highlight (mouse_face_mouse_frame,
+                           mouse_face_mouse_x, mouse_face_mouse_y);
+      mouse_face_deferred_gc = 0;
+    }
 }
 \f
 /* External interface to control of standout mode.
@@ -516,6 +547,8 @@ XTcursor_to (row, col)
    WINDOW is the x-window to output to.  LEFT and TOP are starting coords.
    HL is 1 if this text is highlighted, 2 if the cursor is on it,
    3 if should appear in its mouse-face.
+   JUST_FOREGROUND if 1 means draw only the foreground;
+   don't alter the background.
 
    FONT is the default font to use (for glyphs whose font-code is 0).
 
@@ -530,12 +563,13 @@ XTcursor_to (row, col)
 /* This is the multi-face code.  */
 
 static void
-dumpglyphs (f, left, top, gp, n, hl)
+dumpglyphs (f, left, top, gp, n, hl, just_foreground)
      struct frame *f;
      int left, top;
      register GLYPH *gp; /* Points to first GLYPH. */
      register int n;  /* Number of glyphs to display. */
      int hl;
+     int just_foreground;
 {
   /* Holds characters to be displayed. */
   char *buf = (char *) alloca (f->width * sizeof (*buf));
@@ -543,6 +577,7 @@ dumpglyphs (f, left, top, gp, n, hl)
   register int tlen = GLYPH_TABLE_LENGTH;
   register Lisp_Object *tbase = GLYPH_TABLE_BASE;
   Window window = FRAME_X_WINDOW (f);
+  int orig_left = left;
 
   while (n > 0)
     {
@@ -577,7 +612,6 @@ dumpglyphs (f, left, top, gp, n, hl)
        struct face *face = FRAME_DEFAULT_FACE (f);
        FONT_TYPE *font = FACE_FONT (face);
        GC gc = FACE_GC (face);
-       int defaulted = 1;
        int gc_temporary = 0;
 
        /* HL = 3 means use a mouse face previously chosen.  */
@@ -599,7 +633,6 @@ dumpglyphs (f, left, top, gp, n, hl)
              face = intern_face (f, FRAME_COMPUTED_FACES (f) [cf]);
            font = FACE_FONT (face);
            gc = FACE_GC (face);
-           defaulted = 0;
          }
 
        /* Then comes the distinction between modeline and normal text.  */
@@ -610,7 +643,6 @@ dumpglyphs (f, left, top, gp, n, hl)
            face = FRAME_MODE_LINE_FACE (f);
            font = FACE_FONT (face);
            gc   = FACE_GC   (face);
-           defaulted = 0;
          }
 
 #define FACE_DEFAULT (~0)
@@ -618,8 +650,7 @@ dumpglyphs (f, left, top, gp, n, hl)
        /* Now override that if the cursor's on this character.  */
        if (hl == 2)
          {
-           if (defaulted
-               || !face->font
+           if (!face->font
                || (int) face->font == FACE_DEFAULT)
              {
                gc = f->display.x->cursor_gc;
@@ -666,8 +697,36 @@ dumpglyphs (f, left, top, gp, n, hl)
        if ((int) font == FACE_DEFAULT)
          font = f->display.x->font;
 
-       XDrawImageString (x_current_display, window, gc,
-                         left, top + FONT_BASE (font), buf, len);
+       if (just_foreground)
+         XDrawString (x_current_display, window, gc,
+                      left, top + FONT_BASE (font), buf, len);
+       else
+         {
+           XDrawImageString (x_current_display, window, gc,
+                             left, top + FONT_BASE (font), buf, len);
+           /* Clear the rest of the line's height.  */
+           if (f->display.x->line_height != FONT_HEIGHT (font))
+             XClearArea (x_current_display, window, left,
+                         top + FONT_HEIGHT (font),
+                         FONT_WIDTH (font) * len,
+                         /* This is how many pixels of height
+                            we have to clear.  */
+                         f->display.x->line_height - FONT_HEIGHT (font),
+                         False);
+         }
+
+#if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS,
+        which often is not up to date yet.  */
+       if (!just_foreground)
+         {
+           if (left == orig_left)
+             redraw_previous_char (f, PIXEL_TO_CHAR_COL (f, left),
+                                   PIXEL_TO_CHAR_ROW (f, top), hl == 1);
+           if (n == 0)
+             redraw_following_char (f, PIXEL_TO_CHAR_COL (f, left + len * FONT_WIDTH (font)),
+                                    PIXEL_TO_CHAR_ROW (f, top), hl == 1);
+         }
+#endif
 
        if (gc_temporary)
          XFreeGC (x_current_display, gc);
@@ -758,7 +817,7 @@ XTwrite_glyphs (start, len)
   dumpglyphs (f,
              CHAR_TO_PIXEL_COL (f, curs_x),
              CHAR_TO_PIXEL_ROW (f, curs_y),
-             start, len, highlight);
+             start, len, highlight, 0);
 
   /* If we drew on top of the cursor, note that it is turned off.  */
   if (curs_y == f->phys_cursor_y
@@ -814,22 +873,60 @@ XTclear_end_of_line (first_unused)
              CHAR_TO_PIXEL_COL (f, curs_x),
              CHAR_TO_PIXEL_ROW (f, curs_y),
              FONT_WIDTH (f->display.x->font) * (first_unused - curs_x),
-             FONT_HEIGHT (f->display.x->font), False);
+             f->display.x->line_height, False);
 #if 0
-  redraw_previous_char (f, curs_x, curs_y);
+  redraw_previous_char (f, curs_x, curs_y, highlight);
 #endif
 #else /* ! defined (HAVE_X11) */
   XPixSet (FRAME_X_WINDOW (f),
           CHAR_TO_PIXEL_COL (f, curs_x),
           CHAR_TO_PIXEL_ROW (f, curs_y),
           FONT_WIDTH (f->display.x->font) * (first_unused - curs_x),
-          FONT_HEIGHT (f->display.x->font),
+          f->display.x->line_height,
           f->display.x->background_pixel);     
 #endif /* ! defined (HAVE_X11) */
 
   UNBLOCK_INPUT;
 }
 
+static
+XTclear_frame ()
+{
+  int mask;
+  struct frame *f = updating_frame;
+
+  if (f == 0)
+    f = selected_frame;
+
+  f->phys_cursor_x = -1;       /* Cursor not visible.  */
+  curs_x = 0;                  /* Nominal cursor position is top left.  */
+  curs_y = 0;
+  
+  BLOCK_INPUT;
+
+  XClear (FRAME_X_WINDOW (f));
+
+  /* We have to clear the scroll bars, too.  If we have changed
+     colors or something like that, then they should be notified.  */
+  x_scroll_bar_clear (f);
+
+#ifndef HAVE_X11
+  dumpborder (f, 0);
+#endif /* HAVE_X11 */
+
+  XFlushQueue ();
+  UNBLOCK_INPUT;
+}
+\f
+#if 0
+/* This currently does not work because FRAME_CURRENT_GLYPHS doesn't
+   always contain the right glyphs to use.
+
+   It also needs to be changed to look at the details of the font and
+   see whether there is really overlap, and do nothing when there is
+   not.  This can use font_char_overlap_left and font_char_overlap_right,
+   but just how to use them is not clear.  */
+
 /* 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,
@@ -837,9 +934,10 @@ XTclear_end_of_line (first_unused)
    Call this function with input blocked.  */
 
 static void
-redraw_previous_char (f, x, y)
+redraw_previous_char (f, x, y, highlight_flag)
      FRAME_PTR f;
      int x, y;
+     int highlight_flag;
 {
   /* Erase the character before the new ones, in case
      what was here before overlaps it.
@@ -854,43 +952,144 @@ redraw_previous_char (f, x, y)
                  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);
+                 f->display.x->line_height, 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);
+                 x - start_x, highlight_flag, 1);
     }
 }
 
-static
-XTclear_frame ()
+/* Erase the character (if any) at the position X, Y in frame F,
+   then redraw it and the character after it.
+   This is necessary when we erase endng at X,
+   in case the character after X overlaps into the one before X.
+   Call this function with input blocked.  */
+
+static void
+redraw_following_char (f, x, y, highlight_flag)
+     FRAME_PTR f;
+     int x, y;
+     int highlight_flag;
 {
-  int mask;
-  struct frame *f = updating_frame;
+  int limit = FRAME_CURRENT_GLYPHS (f)->used[y];
+  /* Erase the character after the new ones, in case
+     what was here before overlaps it.
+     Reoutput that character, and the following character
+     (in case the following character overlaps it).  */
+  if (x < limit
+      && FRAME_CURRENT_GLYPHS (f)->glyphs[y][x] != SPACEGLYPH)
+    {
+      int end_x = x + 2;
+      if (end_x > limit)
+       end_x = limit;
+      XClearArea (x_current_display, FRAME_X_WINDOW (f),
+                 CHAR_TO_PIXEL_COL (f, x),
+                 CHAR_TO_PIXEL_ROW (f, y),
+                 FONT_WIDTH (f->display.x->font),
+                 f->display.x->line_height, False);
 
-  if (f == 0)
-    f = selected_frame;
+      dumpglyphs (f, CHAR_TO_PIXEL_COL (f, x),
+                 CHAR_TO_PIXEL_ROW (f, y),
+                 &FRAME_CURRENT_GLYPHS (f)->glyphs[y][x],
+                 end_x - x, highlight_flag, 1);
+    }
+}
+#endif /* 0 */
+\f
+#if 0 /* Not in use yet */
 
-  f->phys_cursor_x = -1;       /* Cursor not visible.  */
-  curs_x = 0;                  /* Nominal cursor position is top left.  */
-  curs_y = 0;
-  
-  BLOCK_INPUT;
+/* Return 1 if character C in font F extends past its left edge.  */
 
-  XClear (FRAME_X_WINDOW (f));
+static int
+font_char_overlap_left (font, c)
+     XFontStruct *font;
+     int c;
+{
+  XCharStruct *s;
 
-  /* We have to clear the scroll bars, too.  If we have changed
-     colors or something like that, then they should be notified.  */
-  x_scroll_bar_clear (f);
+  /* Find the bounding-box info for C.  */
+  if (font->per_char == 0)
+    s = &font->max_bounds;
+  else
+    {
+      int rowlen = font->max_char_or_byte2 - font->min_char_or_byte2 + 1;
+      int row, within;
+       
+      /* Decode char into row number (byte 1) and code within row (byte 2).  */
+      row = c >> 8;
+      within = c & 0177;
+      if (!(within >= font->min_char_or_byte2
+           && within <= font->max_char_or_byte2
+           && row >= font->min_byte1
+           && row <= font->max_byte1))
+       {
+         /* If char is out of range, try the font's default char instead.  */
+         c = font->default_char;
+         row = c >> (INTBITS - 8);
+         within = c & 0177;
+       }
+      if (!(within >= font->min_char_or_byte2
+           && within <= font->max_char_or_byte2
+           && row >= font->min_byte1
+           && row <= font->max_byte1))
+       /* Still out of range means this char does not overlap.  */
+       return 0;
+      else
+       /* We found the info for this char.  */
+       s = (font->per_char + (within - font->min_char_or_byte2)
+            + row * rowlen);
+    }
 
-#ifndef HAVE_X11
-  dumpborder (f, 0);
-#endif /* HAVE_X11 */
+  return (s && s->lbearing < 0);
+}
 
-  XFlushQueue ();
-  UNBLOCK_INPUT;
+/* Return 1 if character C in font F extends past its right edge.  */
+
+static int
+font_char_overlap_right (font, c)
+     XFontStruct *font;
+     int c;
+{
+  XCharStruct *s;
+
+  /* Find the bounding-box info for C.  */
+  if (font->per_char == 0)
+    s = &font->max_bounds;
+  else
+    {
+      int rowlen = font->max_char_or_byte2 - font->min_char_or_byte2 + 1;
+      int row, within;
+       
+      /* Decode char into row number (byte 1) and code within row (byte 2).  */
+      row = c >> 8;
+      within = c & 0177;
+      if (!(within >= font->min_char_or_byte2
+           && within <= font->max_char_or_byte2
+           && row >= font->min_byte1
+           && row <= font->max_byte1))
+       {
+         /* If char is out of range, try the font's default char instead.  */
+         c = font->default_char;
+         row = c >> (INTBITS - 8);
+         within = c & 0177;
+       }
+      if (!(within >= font->min_char_or_byte2
+           && within <= font->max_char_or_byte2
+           && row >= font->min_byte1
+           && row <= font->max_byte1))
+       /* Still out of range means this char does not overlap.  */
+       return 0;
+      else
+       /* We found the info for this char.  */
+       s = (font->per_char + (within - font->min_char_or_byte2)
+            + row * rowlen);
+    }
+
+  return (s && s->rbearing >= s->width);
 }
+#endif /* 0 */
 \f
 /* Invert the middle quarter of the frame for .15 sec.  */
 
@@ -1093,14 +1292,14 @@ stufflines (n)
                 FRAME_X_WINDOW (f), f->display.x->normal_gc,
                 intborder, CHAR_TO_PIXEL_ROW (f, topregion),
                 f->width * FONT_WIDTH (f->display.x->font),
-                length * FONT_HEIGHT (f->display.x->font), intborder,
+                length * f->display.x->line_height, intborder,
                 CHAR_TO_PIXEL_ROW (f, newtop));
 #else /* ! defined (HAVE_X11) */
       XMoveArea (FRAME_X_WINDOW (f),
                 intborder, CHAR_TO_PIXEL_ROW (f, topregion),
                 intborder, CHAR_TO_PIXEL_ROW (f, newtop),
                 f->width * FONT_WIDTH (f->display.x->font),
-                length * FONT_HEIGHT (f->display.x->font));
+                length * f->display.x->line_height);
       /* Now we must process any ExposeRegion events that occur
         if the area being copied from is obscured.
         We can't let it wait because further i/d operations
@@ -1117,13 +1316,13 @@ stufflines (n)
       XClearArea (x_current_display, FRAME_X_WINDOW (f), intborder, 
                  CHAR_TO_PIXEL_ROW (f, topregion),
                  f->width * FONT_WIDTH (f->display.x->font),
-                 n * FONT_HEIGHT (f->display.x->font), False);
+                 n * f->display.x->line_height, False);
 #else /* ! defined (HAVE_X11) */
       XPixSet (FRAME_X_WINDOW (f),
               intborder,
               CHAR_TO_PIXEL_ROW (f, topregion),
               f->width * FONT_WIDTH (f->display.x->font),
-              n * FONT_HEIGHT (f->display.x->font),
+              n * f->display.x->line_height,
               f->display.x->background_pixel);
 #endif /* ! defined (HAVE_X11) */
     }
@@ -1155,12 +1354,12 @@ scraplines (n)
          XClearArea (x_current_display, FRAME_X_WINDOW (f), intborder,
                      CHAR_TO_PIXEL_ROW (f, curs_y),
                      f->width * FONT_WIDTH (f->display.x->font),
-                     (flexlines - curs_y) * FONT_HEIGHT (f->display.x->font), False);
+                     (flexlines - curs_y) * f->display.x->line_height, False);
 #else /* ! defined (HAVE_X11) */
          XPixSet (FRAME_X_WINDOW (f),
                   intborder, CHAR_TO_PIXEL_ROW (f, curs_y),
                   f->width * FONT_WIDTH (f->display.x->font),
-                  (flexlines - curs_y) * FONT_HEIGHT (f->display.x->font),
+                  (flexlines - curs_y) * f->display.x->line_height,
                   f->display.x->background_pixel);
 #endif /* ! defined (HAVE_X11) */
        }
@@ -1173,20 +1372,20 @@ scraplines (n)
                 intborder,
                 CHAR_TO_PIXEL_ROW (f, curs_y + n),
                 f->width * FONT_WIDTH (f->display.x->font),
-                (flexlines - (curs_y + n)) * FONT_HEIGHT (f->display.x->font),
+                (flexlines - (curs_y + n)) * f->display.x->line_height,
                 intborder, CHAR_TO_PIXEL_ROW (f, curs_y));
       XClearArea (x_current_display, FRAME_X_WINDOW (f),
                  intborder,
                  CHAR_TO_PIXEL_ROW (f, flexlines - n),
                  f->width * FONT_WIDTH (f->display.x->font),
-                 n * FONT_HEIGHT (f->display.x->font), False);
+                 n * f->display.x->line_height, False);
 #else /* ! defined (HAVE_X11) */
       XMoveArea (FRAME_X_WINDOW (f),
                 intborder,
                 CHAR_TO_PIXEL_ROW (f, curs_y + n),
                 intborder, CHAR_TO_PIXEL_ROW (f, curs_y),
                 f->width * FONT_WIDTH (f->display.x->font),
-                (flexlines - (curs_y + n)) * FONT_HEIGHT (f->display.x->font));
+                (flexlines - (curs_y + n)) * f->display.x->line_height);
       /* Now we must process any ExposeRegion events that occur
         if the area being copied from is obscured.
         We can't let it wait because further i/d operations
@@ -1195,7 +1394,7 @@ scraplines (n)
       XPixSet (FRAME_X_WINDOW (f), intborder,
               CHAR_TO_PIXEL_ROW (f, flexlines - n),
               f->width * FONT_WIDTH (f->display.x->font),
-              n * FONT_HEIGHT (f->display.x->font), f->display.x->background_pixel);
+              n * f->display.x->line_height, f->display.x->background_pixel);
 #endif /* ! defined (HAVE_X11) */
     }
 }
@@ -1256,8 +1455,8 @@ dumprectangle (f, left, top, cols, rows)
     /* If the rectangle includes any of the internal border area,
        redisplay the border emphasis.  */
     if (top < intborder || left < intborder
-       || bottom > intborder + f->height * FONT_HEIGHT (f->display.x->font)
-       || right > intborder + f->width * FONT_WIDTH (f->display.x->font))
+       || bottom > intborder + f->height * f->display.x->line_height
+       || right > intborder + f->width * f->display.x->line_height)
       dumpborder (f, 0);
   }
 #endif /* not HAVE_X11         Window manger does this for X11. */
@@ -1266,7 +1465,7 @@ dumprectangle (f, left, top, cols, rows)
      Round down for left and top, up for right and bottom.  */
   top  = PIXEL_TO_CHAR_ROW (f, top);
   left = PIXEL_TO_CHAR_COL (f, left);
-  bottom += (FONT_HEIGHT (f->display.x->font) - 1);
+  bottom += (f->display.x->line_height - 1);
   right += (FONT_WIDTH (f->display.x->font) - 1);
   bottom = PIXEL_TO_CHAR_ROW (f, bottom);
   right = PIXEL_TO_CHAR_COL (f, right);
@@ -1311,7 +1510,7 @@ dumprectangle (f, left, top, cols, rows)
                  CHAR_TO_PIXEL_COL (f, left),
                  CHAR_TO_PIXEL_ROW (f, y),
                  line, min (cols, active_frame->used[y] - left),
-                 active_frame->highlight[y]);
+                 active_frame->highlight[y], 0);
     }
 
   /* Turn the cursor on if we turned it off.  */
@@ -1381,7 +1580,7 @@ x_do_pending_expose ()
                        / FONT_WIDTH (f->display.x->font));
          temp_height = ((windowinfo.height- 2 * intborder
                          - f->display.x->h_scroll_bar_height)
-                        / FONT_HEIGHT (f->display.x->font));
+                        / f->display.x->line_height);
          if (temp_width != f->width || temp_height != f->height)
            {
              change_frame_size (f, max (1, temp_height),
@@ -1519,7 +1718,9 @@ x_new_focus_frame (frame)
 #endif /* ! 0 */
 
       if (x_focus_frame && x_focus_frame->auto_raise)
-       x_raise_frame (x_focus_frame);
+       pending_autoraise_frame = x_focus_frame;
+      else
+       pending_autoraise_frame = 0;
     }
 
   XTframe_rehighlight ();
@@ -1748,7 +1949,7 @@ pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
   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_y -= (f)->display.x->line_height - 1;
 
   pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
   pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
@@ -1756,7 +1957,7 @@ pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
   if (bounds)
     {
       bounds->width  = FONT_WIDTH  (f->display.x->font);
-      bounds->height = FONT_HEIGHT (f->display.x->font);
+      bounds->height = f->display.x->line_height;
       bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
       bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
     }
@@ -1938,6 +2139,12 @@ note_mouse_highlight (f, x, y)
   if (mouse_face_defer)
     return;
 
+  if (gc_in_progress)
+    {
+      mouse_face_deferred_gc = 1;
+      return;
+    }
+
   /* Find out which glyph the mouse is on.  */
   pixel_to_glyph_coords (f, x, y, &column, &row,
                         &new_glyph, x_mouse_grabbed);
@@ -1950,9 +2157,11 @@ note_mouse_highlight (f, x, y)
   if (! EQ (window, mouse_face_window))
     clear_mouse_face ();
 
-  /* Are we in a window whose display is up to date?  */
+  /* Are we in a window whose display is up to date?
+     And verify the buffer's text has not changed.  */
   if (WINDOWP (window) && portion == 0
-      && EQ (w->window_end_valid, Qt))
+      && EQ (w->window_end_valid, w->buffer)
+      && w->last_modified == BUF_MODIFF (XBUFFER (w->buffer)))
     {
       int *ptr = FRAME_CURRENT_GLYPHS (f)->charstarts[row];
       int i, pos;
@@ -1963,24 +2172,32 @@ note_mouse_highlight (f, x, y)
          break;
       pos = ptr[i];
       /* Is it outside the displayed active region (if any)?  */
-      if (pos > 0
-         && ! (EQ (window, mouse_face_window)
-               && pos >= mouse_face_beg && pos < mouse_face_end))
+      if (pos <= 0)
+       clear_mouse_face ();
+      else if (! (EQ (window, mouse_face_window)
+                 && row >= mouse_face_beg_row
+                 && row <= mouse_face_end_row
+                 && (row > mouse_face_beg_row || column >= mouse_face_beg_col)
+                 && (row < mouse_face_end_row || column < mouse_face_end_col)))
        {
          Lisp_Object mouse_face, overlay, position;
          Lisp_Object *overlay_vec;
          int len, noverlays, ignor1;
          struct buffer *obuf;
+         int obegv, ozv;
 
-         /* If we get an out-of-range value, return now;
-            don't get an error.  */
-         if (pos > BUF_ZV (XBUFFER (w->buffer)))
+         /* If we get an out-of-range value, return now; avoid an error.  */
+         if (pos > BUF_Z (XBUFFER (w->buffer)))
            return;
 
          /* Make the window's buffer temporarily current for
             overlays_at and compute_char_face.  */
          obuf = current_buffer;
          current_buffer = XBUFFER (w->buffer);
+         obegv = BEGV;
+         ozv = ZV;
+         BEGV = BEG;
+         ZV = Z;
 
          /* Yes.  Clear the display of the old active region, if any.  */
          clear_mouse_face ();
@@ -2023,8 +2240,10 @@ note_mouse_highlight (f, x, y)
              before = Foverlay_start (overlay);
              after = Foverlay_end (overlay);
              /* Record this as the current active region.  */
-             mouse_face_beg = XFASTINT (before);
-             mouse_face_end = XFASTINT (after);
+             fast_find_position (window, before,
+                                 &mouse_face_beg_col, &mouse_face_beg_row);
+             fast_find_position (window, after,
+                                 &mouse_face_end_col, &mouse_face_end_row);
              mouse_face_window = window;
              mouse_face_face_id = compute_char_face (f, w, pos, 0, 0,
                                                      &ignore, pos + 1, 1);
@@ -2052,8 +2271,10 @@ note_mouse_highlight (f, x, y)
                = Fnext_single_property_change (position, Qmouse_face,
                                                w->buffer, end);
              /* Record this as the current active region.  */
-             mouse_face_beg = XFASTINT (before);
-             mouse_face_end = XFASTINT (after);
+             fast_find_position (window, before,
+                                 &mouse_face_beg_col, &mouse_face_beg_row);
+             fast_find_position (window, after,
+                                 &mouse_face_end_col, &mouse_face_end_row);
              mouse_face_window = window;
              mouse_face_face_id
                = compute_char_face (f, w, pos, 0, 0,
@@ -2062,10 +2283,10 @@ note_mouse_highlight (f, x, y)
              /* Display it as active.  */
              show_mouse_face (1);
            }
+         BEGV = obegv;
+         ZV = ozv;
          current_buffer = obuf;
        }
-      else if (pos <= 0)
-       clear_mouse_face ();
     }
 }
 \f
@@ -2130,24 +2351,28 @@ static void
 show_mouse_face (hl)
      int hl;
 {
-  int begcol, begrow, endcol, endrow;
   struct window *w = XWINDOW (mouse_face_window);
   int width = window_internal_width (w);
   FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
   int i;
+  int curs_x = f->phys_cursor_x;
+  int curs_y = f->phys_cursor_y;
+  int cursor_off = 0;
 
-  fast_find_position (mouse_face_window, mouse_face_beg,
-                     &begcol, &begrow);
-  fast_find_position (mouse_face_window, mouse_face_end,
-                     &endcol, &endrow);
-
-  x_display_cursor (f, 0);
-
-  for (i = begrow; i <= endrow; i++)
+  for (i = mouse_face_beg_row; i <= mouse_face_end_row; i++)
     {
-      int column = (i == begrow ? begcol : w->left);
-      int endcolumn = (i == endrow ? endcol : w->left + width);
-      endcolumn = min (endcolumn, FRAME_CURRENT_GLYPHS (f)->used[i] - w->left),
+      int column = (i == mouse_face_beg_row ? mouse_face_beg_col : w->left);
+      int endcolumn = (i == mouse_face_end_row ? mouse_face_end_col : w->left + width);
+      endcolumn = min (endcolumn, FRAME_CURRENT_GLYPHS (f)->used[i] - w->left);
+
+      /* If the cursor's in the text we are about to rewrite,
+        turn the cursor off.  */
+      if (i == curs_y
+         && curs_x >= mouse_face_beg_col - 1 && curs_x <= mouse_face_end_col)
+       {
+         x_display_cursor (f, 0);
+         cursor_off = 1;
+       }
 
       dumpglyphs (f,
                  CHAR_TO_PIXEL_COL (f, column),
@@ -2155,10 +2380,18 @@ show_mouse_face (hl)
                  FRAME_CURRENT_GLYPHS (f)->glyphs[i] + column,
                  endcolumn - column,
                  /* Highlight with mouse face if hl > 0.  */
-                 hl > 0 ? 3 : 0);
+                 hl > 0 ? 3 : 0, 0);
     }
 
-  x_display_cursor (f, 1);
+  /* If we turned the cursor off, turn it back on.  */
+  if (cursor_off)
+    x_display_cursor (f, 1);
+
+  /* Change the mouse cursor according to the value of HL.  */
+  if (hl > 0)
+    XDefineCursor (XDISPLAY FRAME_X_WINDOW (f), f->display.x->cross_cursor);
+  else
+    XDefineCursor (XDISPLAY FRAME_X_WINDOW (f), f->display.x->text_cursor);
 }
 
 /* Clear out the mouse-highlighted active region.
@@ -2170,8 +2403,8 @@ clear_mouse_face ()
   if (! NILP (mouse_face_window))
     show_mouse_face (0);
 
-  mouse_face_beg = -1;
-  mouse_face_end = -1;
+  mouse_face_beg_row = mouse_face_beg_col = -1;
+  mouse_face_end_row = mouse_face_end_col = -1;
   mouse_face_window = Qnil;
 }
 \f
@@ -2254,7 +2487,7 @@ XTmouse_position (f, bar_window, part, x, y, time)
 
        win = root;
 
-       if (x_mouse_grabbed)
+       if (x_mouse_grabbed && FRAME_LIVE_P (last_mouse_frame))
          {
            /* If mouse was grabbed on a frame, give coords for that frame
               even if the mouse is now outside it.  */
@@ -3081,6 +3314,9 @@ Atom Xatom_wm_window_moved;         /* When the WM moves us. */
 /* Window manager communication.  */
 Atom Xatom_wm_change_state;
 
+/* EditRes protocol */
+Atom Xatom_editres_name;
+
 /* Record the last 100 characters stored
    to help debug the loss-of-chars-during-GC problem.  */
 int temp_index;
@@ -3163,14 +3399,15 @@ 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
+                   /* Since we set WM_TAKE_FOCUS, we must call
+                      XSetInputFocus explicitly.  But not if f is null,
+                      since that might be an event for a deleted frame.  */
                    if (f)
-                     x_focus_on_frame (f);
+                     XSetInputFocus (event.xclient.display,
+                                     event.xclient.window,
+                                     RevertToPointerRoot,
+                                     event.xclient.data.l[1]);
                    /* Not certain about handling scroll bars here */
                  }
                else if (event.xclient.data.l[0] == Xatom_wm_save_yourself)
@@ -3219,29 +3456,30 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                    f->display.x->top_pos = new_y;
                  }
              }
+#if defined (USE_X_TOOLKIT) && defined (HAVE_X11R5)
+           else if (event.xclient.message_type == Xatom_editres_name)
+             {
+               struct frame *f = x_any_window_to_frame (event.xclient.window);
+               _XEditResCheckMessages (f->display.x->widget, NULL, &event, NULL);
+             }
+#endif /* USE_X_TOOLKIT and HAVE_X11R5 */
          }
          break;
 
-#ifdef NEW_SELECTIONS
        case SelectionNotify:
 #ifdef USE_X_TOOLKIT
-         if (x_window_to_frame (event.xselection.requestor))
-           x_handle_selection_notify (&event);
-         else
+         if (! x_window_to_frame (event.xselection.requestor))
            goto OTHER;
-#else /* not USE_X_TOOLKIT */
-         x_handle_selection_notify (&event);
 #endif /* not USE_X_TOOLKIT */
+         x_handle_selection_notify (&event);
          break;
-#endif /* NEW_SELECTIONS */
 
        case SelectionClear:    /* Someone has grabbed ownership. */
-#ifdef NEW_SELECTIONS
-         {
 #ifdef USE_X_TOOLKIT
-         if (x_window_to_frame (event.xselectionclear.window))
-           {
+         if (x_window_to_frame (event.xselectionclear.window))
+           goto OTHER;
 #endif /* USE_X_TOOLKIT */
+         {
            XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
 
            if (numchars == 0)
@@ -3255,26 +3493,15 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
 
            count += 1;
            numchars -= 1;
-#ifdef USE_X_TOOLKIT
          }
-         else
-           goto OTHER;
-#endif /* USE_X_TOOLKIT */
-         }
-#else /* not NEW_SELECTIONS */
-         x_disown_selection (event.xselectionclear.window,
-                             event.xselectionclear.selection,
-                             event.xselectionclear.time);
-#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))
-           {
+         if (!x_window_to_frame (event.xselectionrequest.owner))
+           goto OTHER;
 #endif /* USE_X_TOOLKIT */
+         {
            XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
 
            if (numchars == 0)
@@ -3291,48 +3518,27 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
 
            count += 1;
            numchars -= 1;
-#ifdef USE_X_TOOLKIT
          }
-         else
-           goto OTHER;
-#endif /* USE_X_TOOLKIT */
-         }
-#else /* not NEW_SELECTIONS */
-         x_answer_selection_request (event);
-#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
+         if (!x_any_window_to_frame (event.xproperty.window))
            goto OTHER;
-#else /* not USE_X_TOOLKIT */
-         x_handle_property_notify (&event);
 #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)
-           x_invalidate_cut_buffer_cache (&event.xproperty);
-
-         /* Otherwise, we're probably handling an incremental
-             selection transmission.  */
-         else
-           {
-             /* If we were to do this synchronously, there'd be no worry
-                about re-selecting. */
-             x_send_incremental (event);
-           }
-#endif /* not NEW_SELECTIONS */
+         x_handle_property_notify (&event);
          break;
 
        case ReparentNotify:
-         f = x_window_to_frame (event.xreparent.window);
+         f = x_top_window_to_frame (event.xreparent.window);
          if (f)
-           f->display.x->parent_desc = event.xreparent.parent;
+           {
+             int x, y;
+             f->display.x->parent_desc = event.xreparent.parent;
+             x_real_positions (f, &x, &y);
+             f->display.x->left_pos = x;
+             f->display.x->top_pos = y;
+           }
          break;
 
        case Expose:
@@ -3346,11 +3552,9 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                  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);
-               }
+               dumprectangle (x_window_to_frame (event.xexpose.window),
+                              event.xexpose.x, event.xexpose.y,
+                              event.xexpose.width, event.xexpose.height);
            }
          else
            {
@@ -3437,7 +3641,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
 
 #ifdef HAVE_X11
        case UnmapNotify:
-         f = x_window_to_frame (event.xunmap.window);
+         f = x_any_window_to_frame (event.xunmap.window);
          if (f)                /* F may no longer exist if
                                   the frame was deleted.  */
            {
@@ -3445,10 +3649,10 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                 disabled; you don't want to spend time updating a
                 display that won't ever be seen.  */
              f->async_visible = 0;
-             /* 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.  */
+             /* We can't distinguish, from the event, whether the window
+                has become iconified or invisible.  So assume, if it
+                was previously visible, than now it is iconified.
+                We depend on x_make_frame_invisible to mark it iconified.  */
              if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
                f->async_iconified = 1;
            }
@@ -3458,11 +3662,9 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
          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 */
+         /* We use x_top_window_to_frame because map events can come
+            for subwindows and they don't mean that the frame is visible.  */
+         f = x_top_window_to_frame (event.xmap.window);
          if (f)
            {
              f->async_visible = 1;
@@ -3475,7 +3677,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
 #ifdef USE_X_TOOLKIT
          goto OTHER;
 #endif /* USE_X_TOOLKIT */
-  break;
+         break;
 
          /* Turn off processing if we become fully obscured. */
        case VisibilityNotify:
@@ -3719,26 +3921,28 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
 
 
        case LeaveNotify:
-         f = x_any_window_to_frame (event.xcrossing.window);
-
-         if (f == mouse_face_mouse_frame)
-           /* If we move outside the frame,
-              then we're certainly no longer on any text in the frame.  */
-           clear_mouse_face ();
-
-         if (event.xcrossing.focus)
-           {
-             if (! x_focus_event_frame)
-               x_new_focus_frame (0);
-             else
-               x_new_focus_frame (f);
-           }
-         else 
+         f = x_top_window_to_frame (event.xcrossing.window);
+         if (f)
            {
-             if (f == x_focus_event_frame)
-               x_focus_event_frame = 0;
-             if (f == x_focus_frame)
-               x_new_focus_frame (0);
+             if (f == mouse_face_mouse_frame)
+               /* If we move outside the frame,
+                  then we're certainly no longer on any text in the frame.  */
+               clear_mouse_face ();
+
+             if (event.xcrossing.focus)
+               {
+                 if (! x_focus_event_frame)
+                   x_new_focus_frame (0);
+                 else
+                   x_new_focus_frame (f);
+               }
+             else 
+               {
+                 if (f == x_focus_event_frame)
+                   x_focus_event_frame = 0;
+                 if (f == x_focus_frame)
+                   x_new_focus_frame (0);
+               }
            }
 #ifdef USE_X_TOOLKIT
          goto OTHER;
@@ -3796,7 +4000,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
 #ifdef HAVE_X11
        case MotionNotify:
          {
-           if (x_mouse_grabbed)
+           if (x_mouse_grabbed && FRAME_LIVE_P (last_mouse_frame))
              f = last_mouse_frame;
            else
              f = x_window_to_frame (event.xmotion.window);
@@ -3815,16 +4019,23 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                clear_mouse_face ();
              }
          }
+#if 0 /* This should be unnecessary, since the toolkit has no use
+        for motion events that happen outside of the menu event loop,
+        and it seems to cause the bug that mouse events stop coming
+        after a while.  */
 #ifdef USE_X_TOOLKIT
          goto OTHER;
 #endif /* USE_X_TOOLKIT */
+#endif
          break;
 
        case ConfigureNotify:
           f = x_any_window_to_frame (event.xconfigure.window);
 #ifdef USE_X_TOOLKIT
           if (f
+#if 0
               && ! event.xconfigure.send_event
+#endif
               && (event.xconfigure.window == XtWindow (f->display.x->widget)))
             {
               Window win, child;
@@ -3855,6 +4066,15 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
               f->display.x->pixel_height = event.xconfigure.height;
               f->display.x->left_pos = event.xconfigure.x;
               f->display.x->top_pos = event.xconfigure.y;
+
+             /* What we have now is the position of Emacs's own window.
+                Convert that to the position of the window manager window.  */
+             {
+               int x, y;
+               x_real_positions (f, &x, &y);
+               f->display.x->left_pos = x;
+               f->display.x->top_pos = y;
+             }
             }
           goto OTHER;
 #else /* not USE_X_TOOLKIT */
@@ -3906,6 +4126,15 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
              f->display.x->pixel_height = event.xconfigure.height;
              f->display.x->left_pos = event.xconfigure.x;
              f->display.x->top_pos = event.xconfigure.y;
+
+             /* What we have now is the position of Emacs's own window.
+                Convert that to the position of the window manager window.  */
+             {
+               int x, y;
+               x_real_positions (f, &x, &y);
+               f->display.x->left_pos = x;
+               f->display.x->top_pos = y;
+             }
            }
 #endif /* not USE_X_TOOLKIT */
          break;
@@ -4072,6 +4301,16 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
     x_do_pending_expose ();
 #endif
 
+  /* If the focus was just given to an autoraising frame,
+     raise it now.  */
+#ifdef HAVE_X11
+  if (pending_autoraise_frame)
+    {
+      x_raise_frame (pending_autoraise_frame);
+      pending_autoraise_frame = 0;
+    }
+#endif
+
   UNBLOCK_INPUT;
   return count;
 }
@@ -4154,7 +4393,7 @@ x_draw_box (f)
   int left = CHAR_TO_PIXEL_COL (f, f->cursor_x);
   int top  = CHAR_TO_PIXEL_ROW (f, f->cursor_y);
   int width = FONT_WIDTH (f->display.x->font);
-  int height = FONT_HEIGHT (f->display.x->font);
+  int height = f->display.x->line_height;
 
 #ifdef HAVE_X11
   XDrawRectangle (x_current_display, FRAME_X_WINDOW (f),
@@ -4200,7 +4439,7 @@ clear_cursor (f)
   XPixSet (FRAME_X_WINDOW (f),
           CHAR_TO_PIXEL_COL (f, f->phys_cursor_x),
           CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y),
-          FONT_WIDTH (f->display.x->font), FONT_HEIGHT (f->display.x->font),
+          FONT_WIDTH (f->display.x->font), f->display.x->line_height,
           f->display.x->background_pixel);
 #endif /* ! defined (HAVE_X11) */
   f->phys_cursor_x = -1;
@@ -4220,7 +4459,7 @@ x_draw_single_glyph (f, row, column, glyph, highlight)
   dumpglyphs (f,
              CHAR_TO_PIXEL_COL (f, column),
              CHAR_TO_PIXEL_ROW (f, row),
-             &glyph, 1, highlight);
+             &glyph, 1, highlight, 0);
 }
 
 static void
@@ -4275,7 +4514,7 @@ x_display_bar_cursor (f, on)
                      f->display.x->cursor_gc,
                      CHAR_TO_PIXEL_COL (f, curs_x),
                      CHAR_TO_PIXEL_ROW (f, curs_y),
-                     1, FONT_HEIGHT (f->display.x->font));
+                     1, f->display.x->line_height);
 
       f->phys_cursor_x = curs_x;
       f->phys_cursor_y = curs_y;
@@ -4328,6 +4567,14 @@ x_display_box_cursor (f, on)
          || (f->display.x->current_cursor != hollow_box_cursor
              && (f != x_highlight_frame))))
     {
+      /* If the font is not as tall as a whole line,
+        we must explicitly clear the line's whole height.  */
+      if (FONT_HEIGHT (f->display.x->font) != f->display.x->line_height)
+       XClearArea (x_current_display, FRAME_X_WINDOW (f),
+                   CHAR_TO_PIXEL_COL (f, f->phys_cursor_x),
+                   CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y),
+                   FONT_WIDTH (f->display.x->font),
+                   f->display.x->line_height, False);
       /* Erase the cursor by redrawing the character underneath it.  */
       x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
                           f->phys_cursor_glyph,
@@ -4843,8 +5090,13 @@ x_new_font (f, fontname)
       XSetFont (x_current_display, f->display.x->cursor_gc,
                f->display.x->font->fid);
 
+      frame_update_line_height (f);
       x_set_window_size (f, 0, f->width, f->height);
     }
+  else
+    /* If we are setting a new frame's font for the first time,
+       there are no faces yet, so this font's height is the line height.  */
+    f->display.x->line_height = FONT_HEIGHT (f->display.x->font);
 
   {
     Lisp_Object lispy_name;
@@ -4888,6 +5140,7 @@ x_calc_absolute_position (f)
 #ifdef HAVE_X11
   Window win, child;
   int win_x = 0, win_y = 0;
+  int flags = f->display.x->size_hint_flags;
 
   /* Find the position of the outside upper-left corner of
      the inner window, with respect to the outer window.  */
@@ -4910,18 +5163,21 @@ x_calc_absolute_position (f)
 
   /* Treat negative positions as relative to the leftmost bottommost
      position that fits on the screen.  */
-  if (f->display.x->left_pos < 0)
+  if (flags & XNegative)
     f->display.x->left_pos = (x_screen_width 
                              - 2 * f->display.x->border_width - win_x
                              - PIXEL_WIDTH (f)
                              + f->display.x->left_pos);
 
-  if (f->display.x->top_pos < 0)
+  if (flags & YNegative)
     f->display.x->top_pos = (x_screen_height
                             - 2 * f->display.x->border_width - win_y
                             - PIXEL_HEIGHT (f)
                             + f->display.x->top_pos);
-
+  /* The left_pos and top_pos
+     are now relative to the top and left screen edges,
+     so the flags should correspond.  */
+  f->display.x->size_hint_flags &= ~ (XNegative | YNegative);
 #else /* ! defined (HAVE_X11) */
   WINDOWINFO_TYPE parentinfo;
 
@@ -4937,15 +5193,32 @@ x_calc_absolute_position (f)
 #endif /* ! defined (HAVE_X11) */
 }
 
-x_set_offset (f, xoff, yoff)
+/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
+   to really change the position, and 0 when calling from
+   x_make_frame_visible (in that case, XOFF and YOFF are the current
+   position values).  */
+
+x_set_offset (f, xoff, yoff, change_gravity)
      struct frame *f;
      register int xoff, yoff;
+     int change_gravity;
 {
-  f->display.x->top_pos = yoff;
-  f->display.x->left_pos = xoff;
+  if (change_gravity)
+    {
+      f->display.x->top_pos = yoff;
+      f->display.x->left_pos = xoff;
+      f->display.x->size_hint_flags &= ~ (XNegative | YNegative);
+      if (xoff < 0)
+       f->display.x->size_hint_flags |= XNegative;
+      if (yoff < 0)
+       f->display.x->size_hint_flags |= YNegative;
+      f->display.x->win_gravity = NorthWestGravity;
+    }
   x_calc_absolute_position (f);
 
   BLOCK_INPUT;
+  x_wm_set_size_hint (f, 0, 0);
+
 #ifdef USE_X_TOOLKIT
   XMoveWindow (XDISPLAY XtWindow (f->display.x->widget),
               f->display.x->left_pos, f->display.x->top_pos);
@@ -4953,9 +5226,6 @@ x_set_offset (f, xoff, yoff)
   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, 1, xoff, yoff);
-#endif /* ! defined (HAVE_X11) */
   UNBLOCK_INPUT;
 }
 
@@ -4974,7 +5244,17 @@ x_set_window_size (f, change_gravity, cols, rows)
 
 #ifdef USE_X_TOOLKIT
   BLOCK_INPUT;
-  EmacsFrameSetCharSize (f->display.x->edit_widget, cols, rows);
+  {
+    /* The x and y position of the widget is clobbered by the
+       call to XtSetValues within EmacsFrameSetCharSize.
+       This is a real kludge, but I don't understand Xt so I can't
+       figure out a correct fix.  Can anyone else tell me? -- rms.  */
+    int xpos = f->display.x->widget->core.x;
+    int ypos = f->display.x->widget->core.y;
+    EmacsFrameSetCharSize (f->display.x->edit_widget, cols, rows);
+    f->display.x->widget->core.x = xpos;
+    f->display.x->widget->core.y = ypos;
+  }
   UNBLOCK_INPUT;
 
 #else /* not USE_X_TOOLKIT */
@@ -4990,8 +5270,10 @@ x_set_window_size (f, change_gravity, cols, rows)
   pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
 
 #ifdef HAVE_X11
-  x_wm_set_size_hint (f, 0, change_gravity, 0, 0);
+  f->display.x->win_gravity = NorthWestGravity;
+  x_wm_set_size_hint (f, 0, 0);
 #endif /* ! defined (HAVE_X11) */
+  XSync (x_current_display, False);
   XChangeWindowSize (FRAME_X_WINDOW (f), pixelwidth, pixelheight);
 
   /* Now, strictly speaking, we can't be sure that this is accurate,
@@ -5027,24 +5309,21 @@ x_set_resize_hint (f)
                  2 * f->display.x->internal_border_width,
                  2 * f->display.x->internal_border_width,
                  FONT_WIDTH (f->display.x->font),
-                 FONT_HEIGHT (f->display.x->font));
+                 f->display.x->line_height);
 }
 #endif /* HAVE_X11 */
 \f
 /* Mouse warping, focus shifting, raising and lowering.  */
 
+void
 x_set_mouse_position (f, x, y)
      struct frame *f;
      int 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;
+  pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->display.x->line_height / 2;
 
   if (pix_x < 0) pix_x = 0;
   if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
@@ -5058,6 +5337,19 @@ x_set_mouse_position (f, x, y)
   UNBLOCK_INPUT;
 }
 
+/* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F.  */
+
+void
+x_set_mouse_pixel_position (f, pix_x, pix_y)
+     struct frame *f;
+     int pix_x, pix_y;
+{
+  BLOCK_INPUT;
+
+  XWarpMousePointer (FRAME_X_WINDOW (f), pix_x, pix_y);
+  UNBLOCK_INPUT;
+}
+
 #ifdef HAVE_X11
 x_focus_on_frame (f)
      struct frame *f;
@@ -5147,15 +5439,24 @@ x_make_frame_visible (f)
   if (! FRAME_VISIBLE_P (f))
     {
 #ifdef HAVE_X11
+#ifndef USE_X_TOOLKIT
+      x_set_offset (f, f->display.x->left_pos, f->display.x->top_pos, 0);
+#endif
+
       if (! EQ (Vx_no_window_manager, Qt))
        x_wm_set_window_state (f, NormalState);
 #ifdef USE_X_TOOLKIT
-      XtPopup (f->display.x->widget, XtGrabNone);
+      /* This was XtPopup, but that did nothing for an iconified frame.  */
+      XtMapWidget (f->display.x->widget);
 #else /* not USE_X_TOOLKIT */
       XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
 #endif /* not USE_X_TOOLKIT */
+#if 0 /* This seems to bring back scroll bars in the wrong places
+        if the window configuration has changed.  They seem
+        to come back ok without this.  */
       if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
        XMapSubwindows (x_current_display, FRAME_X_WINDOW (f));
+#endif
 #else /* ! defined (HAVE_X11) */
       XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
       if (f->display.x->icon_desc != 0)
@@ -5186,11 +5487,20 @@ x_make_frame_invisible (f)
   if (x_highlight_frame == f)
     x_highlight_frame = 0;
 
+#if 0/* This might add unreliability; I don't trust it -- rms.  */
   if (! f->async_visible && ! f->async_iconified)
     return;
+#endif
 
   BLOCK_INPUT;
 
+  /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
+     that the current position of the window is user-specified, rather than
+     program-specified, so that when the window is mapped again, it will be
+     placed at the same location, without forcing the user to position it
+     by hand again (they have already done that once for this window.)  */
+  x_wm_set_size_hint (f, 0, 1);
+
 #ifdef HAVE_X11R4
 
 #ifdef USE_X_TOOLKIT
@@ -5199,11 +5509,11 @@ x_make_frame_invisible (f)
 #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");
     }
+#endif /* not USE_X_TOOLKIT */
 
 #else /* ! defined (HAVE_X11R4) */
 #ifdef HAVE_X11
@@ -5241,14 +5551,24 @@ x_make_frame_invisible (f)
 #else /* ! defined (HAVE_X11) */
 
   XUnmapWindow (FRAME_X_WINDOW (f));
-  f->async_visible = 0;                /* Handled by the UnMap event for X11 */
   if (f->display.x->icon_desc != 0)
     XUnmapWindow (f->display.x->icon_desc);
 
 #endif /* ! defined (HAVE_X11) */
 #endif /* ! defined (HAVE_X11R4) */
 
-  XFlushQueue ();
+  /* We can't distinguish this from iconification
+     just by the event that we get from the server.
+     So we can't win using the usual strategy of letting
+     FRAME_SAMPLE_VISIBILITY set this.  So do it by hand,
+     and synchronize with the server to make sure we agree.  */
+  f->visible = 0;
+  FRAME_ICONIFIED_P (f) = 0;
+  f->async_visible = 0;
+  f->async_iconified = 0;
+
+  x_sync ();
+
   UNBLOCK_INPUT;
 }
 
@@ -5320,8 +5640,10 @@ x_iconify_frame (f)
     {
       /* If the frame was withdrawn, before, we must map it.  */
       XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
+#if 0 /* We don't have subwindows in the icon.  */
       if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
        XMapSubwindows (x_current_display, FRAME_X_WINDOW (f));
+#endif
     }
 
   f->async_iconified = 1;
@@ -5366,6 +5688,13 @@ x_destroy_window (f)
   if (f == x_highlight_frame)
     x_highlight_frame = 0;
 
+  if (f == mouse_face_mouse_frame)
+    {
+      mouse_face_beg_row = mouse_face_beg_col = -1;
+      mouse_face_end_row = mouse_face_end_col = -1;
+      mouse_face_window = Qnil;
+    }
+
   UNBLOCK_INPUT;
 }
 \f
@@ -5447,19 +5776,16 @@ mouse_event_pending_p ()
 
 #ifdef HAVE_X11
 
-/* Record the gravity used previously, in case CHANGE_GRAVITY is 0.  */
-static int previous_gravity;
+/* Set the normal size hints for the window manager, for frame F.
+   FLAGS is the flags word to use--or 0 meaning preserve the flags
+   that the window now has.
+   If USER_POSITION is nonzero, we set the USPosition
+   flag (this is useful when FLAGS is 0).  */
 
-/* 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)
+x_wm_set_size_hint (f, flags, user_position)
      struct frame *f;
-     long prompting;
-     int change_gravity;
-     int spec_x, spec_y;
+     long flags;
+     int user_position;
 {
   XSizeHints size_hints;
 
@@ -5472,12 +5798,14 @@ x_wm_set_size_hint (f, prompting, change_gravity, spec_x, spec_y)
   Window window = FRAME_X_WINDOW (f);
 #endif /* not USE_X_TOOLKIT */
 
+  /* Setting PMaxSize caused various problems.  */
   size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
 
   flexlines = f->height;
 
   size_hints.x = f->display.x->left_pos;
   size_hints.y = f->display.x->top_pos;
+
 #ifdef USE_X_TOOLKIT
   XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
   XtSetArg (al[ac], XtNheight, &widget_height); ac++;
@@ -5488,53 +5816,59 @@ x_wm_set_size_hint (f, prompting, change_gravity, spec_x, spec_y)
   size_hints.height = PIXEL_HEIGHT (f);
   size_hints.width = PIXEL_WIDTH (f);
 #endif /* not USE_X_TOOLKIT */
+
   size_hints.width_inc = FONT_WIDTH (f->display.x->font);
-  size_hints.height_inc = FONT_HEIGHT (f->display.x->font);
-#if 0
+  size_hints.height_inc = f->display.x->line_height;
   size_hints.max_width = x_screen_width - CHAR_TO_PIXEL_WIDTH (f, 0);
   size_hints.max_height = x_screen_height - CHAR_TO_PIXEL_HEIGHT (f, 0);
-#endif    
+
   {
     int base_width, base_height;
+    int min_rows = 0, min_cols = 0;
 
     base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
     base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
 
-    {
-      int min_rows = 0, min_cols = 0;
-      check_frame_size (f, &min_rows, &min_cols);
-
-      /* The window manager uses the base width hints to calculate the
-        current number of rows and columns in the frame while
-        resizing; min_width and min_height aren't useful for this
-        purpose, since they might not give the dimensions for a
-        zero-row, zero-column frame.
+    check_frame_size (f, &min_rows, &min_cols);
 
-        We use the base_width and base_height members if we have
-        them; otherwise, we set the min_width and min_height members
-        to the size for a zero x zero frame.  */
+    /* The window manager uses the base width hints to calculate the
+       current number of rows and columns in the frame while
+       resizing; min_width and min_height aren't useful for this
+       purpose, since they might not give the dimensions for a
+       zero-row, zero-column frame.
+       
+       We use the base_width and base_height members if we have
+       them; otherwise, we set the min_width and min_height members
+       to the size for a zero x zero frame.  */
 
 #ifdef HAVE_X11R4
-      size_hints.flags |= PBaseSize;
-      size_hints.base_width = base_width;
-      size_hints.base_height = base_height;
-      size_hints.min_width  = base_width + min_cols * size_hints.width_inc;
-      size_hints.min_height = base_height + min_rows * size_hints.height_inc;
+    size_hints.flags |= PBaseSize;
+    size_hints.base_width = base_width;
+    size_hints.base_height = base_height;
+    size_hints.min_width  = base_width + min_cols * size_hints.width_inc;
+    size_hints.min_height = base_height + min_rows * size_hints.height_inc;
 #else
-      size_hints.min_width = base_width;
-      size_hints.min_height = base_height;
+    size_hints.min_width = base_width;
+    size_hints.min_height = base_height;
 #endif
-    }
-
   }
 
-  if (prompting)
-    size_hints.flags |= prompting;
+  if (flags)
+    size_hints.flags |= flags;
   else
     {
       XSizeHints hints;                /* Sometimes I hate X Windows... */
+      long supplied_return;
+      int value;
+
+#ifdef HAVE_X11R4
+      value = XGetWMNormalHints (x_current_display, window, &hints,
+                                &supplied_return);
+#else
+      value = XGetNormalHints (x_current_display, window, &hints);
+#endif
       
-      if (XGetNormalHints (x_current_display, window, &hints) == 0)
+      if (value == 0)
        hints.flags = 0;
       if (hints.flags & PSize)
        size_hints.flags |= PSize;
@@ -5545,30 +5879,16 @@ x_wm_set_size_hint (f, prompting, change_gravity, spec_x, spec_y)
       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;
 
+#ifdef PWinGravity
+  size_hints.win_gravity = f->display.x->win_gravity;
   size_hints.flags |= PWinGravity;
+
+  if (user_position)
+    {
+      size_hints.flags &= ~ PPosition;
+      size_hints.flags |= USPosition;
+    }
 #endif /* PWinGravity */
 
 #ifdef HAVE_X11R4
@@ -5664,16 +5984,18 @@ x_term_init (display_name)
   x_focus_frame = x_highlight_frame = 0;
 
 #ifdef USE_X_TOOLKIT
-  argv = (char **) XtMalloc (3 * sizeof (char *));
+  argv = (char **) XtMalloc (5 * sizeof (char *));
   argv [0] = "";
   argv [1] = "-display";
   argv [2] = display_name;
-  argc = 3;
+  argv [3] = "-name";
+  argv [4] = "emacs";
+  argc = 5;
   Xt_app_shell = XtAppInitialize (&Xt_app_con, "Emacs",
                                  emacs_options, XtNumber (emacs_options),
                                  &argc, argv,
                                  NULL, NULL, 0);
-  XtFree (argv);
+  XtFree ((char *)argv);
   x_current_display = XtDisplay (Xt_app_shell);
 
 #else /* not USE_X_TOOLKIT */