Replace `iff' in comments.
[bpt/emacs.git] / src / msdos.c
index fc1509b..ef65597 100644 (file)
@@ -1,11 +1,12 @@
 /* MS-DOS specific C utilities.          -*- coding: raw-text -*-
-   Copyright (C) 1993, 94, 95, 96, 97, 1999 Free Software Foundation, Inc.
+   Copyright (C) 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002,
+                 2003, 2004, 2005, 2006, 2007 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 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -15,8 +16,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 /* Contributed by Morten Welinder */
 /* New display, keyboard, and mouse control by Kim F. Storm */
@@ -37,7 +38,9 @@ Boston, MA 02111-1307, USA.  */
 #include <string.h>     /* for bzero and string functions */
 #include <sys/stat.h>    /* for _fixpath */
 #include <unistd.h>     /* for chdir, dup, dup2, etc. */
+#include <dir.h>        /* for getdisk */
 #if __DJGPP__ >= 2
+#pragma pack(0)                 /* dir.h does a pack(4), which isn't GCC's default */
 #include <fcntl.h>
 #include <io.h>                 /* for setmode */
 #include <dpmi.h>       /* for __dpmi_xxx stuff */
@@ -61,6 +64,8 @@ Boston, MA 02111-1307, USA.  */
 #include "buffer.h"
 #include "commands.h"
 #include "blockinput.h"
+#include "keyboard.h"
+#include "intervals.h"
 #include <go32.h>
 #include <pc.h>
 #include <ctype.h>
@@ -106,14 +111,14 @@ event_timestamp ()
 {
   struct time t;
   unsigned long s;
-  
+
   gettime (&t);
   s = t.ti_min;
   s *= 60;
   s += t.ti_sec;
   s *= 1000;
   s += t.ti_hund * 10;
-  
+
   return s;
 }
 
@@ -124,6 +129,10 @@ event_timestamp ()
  * Mouse buttons are numbered from left to right and also zero based.
  */
 
+/* This used to be in termhooks.h, but mainstream Emacs code no longer
+   uses it, and it was removed...  */
+#define NUM_MOUSE_BUTTONS (5)
+
 int have_mouse;          /* 0: no, 1: enabled, -1: disabled */
 static int mouse_visible;
 
@@ -163,6 +172,45 @@ mouse_off ()
     }
 }
 
+static void
+mouse_setup_buttons (int n_buttons)
+{
+  if (n_buttons == 3)
+    {
+      mouse_button_count = 3;
+      mouse_button_translate[0] = 0; /* Left */
+      mouse_button_translate[1] = 2; /* Middle */
+      mouse_button_translate[2] = 1; /* Right */
+    }
+  else /* two, what else? */
+    {
+      mouse_button_count = 2;
+      mouse_button_translate[0] = 0;
+      mouse_button_translate[1] = 1;
+    }
+}
+
+DEFUN ("msdos-set-mouse-buttons", Fmsdos_set_mouse_buttons, Smsdos_set_mouse_buttons,
+       1, 1, "NSet number of mouse buttons to: ",
+       doc: /* Set the number of mouse buttons to use by Emacs.
+This is useful with mice that report the number of buttons inconsistently,
+e.g., if the number of buttons is reported as 3, but Emacs only sees 2 of
+them.  This happens with wheeled mice on Windows 9X, for example.  */)
+     (nbuttons)
+     Lisp_Object nbuttons;
+{
+  int n;
+
+  CHECK_NUMBER (nbuttons);
+  n = XINT (nbuttons);
+  if (n < 2 || n > 3)
+    xsignal2 (Qargs_out_of_range,
+             build_string ("only 2 or 3 mouse buttons are supported"),
+             nbuttons);
+  mouse_setup_buttons (n);
+  return Qnil;
+}
+
 static void
 mouse_get_xy (int *x, int *y)
 {
@@ -273,11 +321,26 @@ mouse_check_moved ()
   mouse_last_y = y;
 }
 
+/* Force the mouse driver to ``forget'' about any button clicks until
+   now.  */
+static void
+mouse_clear_clicks (void)
+{
+  int b;
+
+  for (b = 0; b < mouse_button_count; b++)
+    {
+      int dummy_x, dummy_y;
+
+      (void) mouse_pressed (b, &dummy_x, &dummy_y);
+      (void) mouse_released (b, &dummy_x, &dummy_y);
+    }
+}
+
 void
 mouse_init ()
 {
   union REGS regs;
-  int b;
 
   if (termscript)
     fprintf (termscript, "<M_INIT>");
@@ -289,13 +352,7 @@ mouse_init ()
      doesn't do that automatically when function 21h is called, which
      causes Emacs to ``remember'' the click that switched focus to the
      window just before Emacs was started from that window.  */
-  for (b = 0; b < mouse_button_count; b++)
-    {
-      int dummy_x, dummy_y;
-
-      (void) mouse_pressed (b, &dummy_x, &dummy_y);
-      (void) mouse_released (b, &dummy_x, &dummy_y);
-    }
+  mouse_clear_clicks ();
 
   regs.x.ax = 0x0007;
   regs.x.cx = 0;
@@ -320,7 +377,6 @@ static int internal_terminal = 0;
 #ifndef HAVE_X_WINDOWS
 extern unsigned char ScreenAttrib;
 static int screen_face;
-static int highlight;
 
 static int screen_size_X;
 static int screen_size_Y;
@@ -342,6 +398,8 @@ static clock_t startup_time;
 
 static int term_setup_done;
 
+static unsigned short outside_cursor;
+
 /* Similar to the_only_frame.  */
 struct x_output the_only_x_display;
 
@@ -356,6 +414,13 @@ static unsigned short screen_virtual_offset = 0;
 /* A flag to control how to display unibyte 8-bit characters.  */
 extern int unibyte_display_via_language_environment;
 
+extern Lisp_Object Qcursor_type;
+extern Lisp_Object Qbar, Qhbar;
+
+/* The screen colors of the current frame, which serve as the default
+   colors for newly-created frames.  */
+static int initial_screen_colors[2];
+
 #if __DJGPP__ > 1
 /* Update the screen from a part of relocated DOS/V screen buffer which
    begins at OFFSET and includes COUNT characters.  */
@@ -364,7 +429,7 @@ dosv_refresh_virtual_screen (int offset, int count)
 {
   __dpmi_regs regs;
 
-  if (offset < 0 || count < 0) /* paranoia; illegal values crash DOS/V */
+  if (offset < 0 || count < 0) /* paranoia; invalid values crash DOS/V */
     return;
 
   regs.h.ah = 0xff;    /* update relocated screen */
@@ -377,8 +442,7 @@ dosv_refresh_virtual_screen (int offset, int count)
 
 static void
 dos_direct_output (y, x, buf, len)
-     int y;
-     int x;
+     int x, y;
      char *buf;
      int len;
 {
@@ -410,29 +474,29 @@ do_visible_bell (xorattr)
      unsigned char xorattr;
 {
   asm volatile
-    ("  movb   $1,%%dl
-visible_bell_0:
-       movl   _ScreenPrimary,%%eax
-       call   dosmemsetup
-       movl   %%eax,%%ebx
-       movl   %1,%%ecx
-       movb   %0,%%al
-       incl   %%ebx
-visible_bell_1:
-       xorb   %%al,%%gs:(%%ebx)
-       addl   $2,%%ebx
-       decl   %%ecx
-       jne    visible_bell_1
-       decb   %%dl
-       jne    visible_bell_3
-visible_bell_2:
-       movzwl %%ax,%%eax
-        movzwl %%ax,%%eax
-       movzwl %%ax,%%eax
-       movzwl %%ax,%%eax
-       decw   %%cx
-       jne    visible_bell_2
-       jmp    visible_bell_0
+    ("  movb   $1,%%dl                         \n\
+visible_bell_0:                                        \n\
+       movl   _ScreenPrimary,%%eax             \n\
+       call   dosmemsetup                      \n\
+       movl   %%eax,%%ebx                      \n\
+       movl   %1,%%ecx                         \n\
+       movb   %0,%%al                          \n\
+       incl   %%ebx                            \n\
+visible_bell_1:                                        \n\
+       xorb   %%al,%%gs:(%%ebx)                \n\
+       addl   $2,%%ebx                         \n\
+       decl   %%ecx                            \n\
+       jne    visible_bell_1                   \n\
+       decb   %%dl                             \n\
+       jne    visible_bell_3                   \n\
+visible_bell_2:                                        \n\
+       movzwl %%ax,%%eax                       \n\
+        movzwl %%ax,%%eax                      \n\
+       movzwl %%ax,%%eax                       \n\
+       movzwl %%ax,%%eax                       \n\
+       decw   %%cx                             \n\
+       jne    visible_bell_2                   \n\
+       jmp    visible_bell_0                   \n\
 visible_bell_3:"
      : /* no output */
      : "m" (xorattr), "g" (screen_size)
@@ -485,6 +549,19 @@ maybe_enable_blinking (void)
     }
 }
 
+/* Return non-zero if the system has a VGA adapter.  */
+static int
+vga_installed (void)
+{
+  union REGS regs;
+
+  regs.x.ax = 0x1a00;
+  int86 (0x10, &regs, &regs);
+  if (regs.h.al == 0x1a && regs.h.bl > 5 && regs.h.bl < 13)
+    return 1;
+  return 0;
+}
+
 /* Set the screen dimensions so that it can show no less than
    ROWS x COLS frame.  */
 
@@ -493,22 +570,16 @@ dos_set_window_size (rows, cols)
      int *rows, *cols;
 {
   char video_name[30];
-  Lisp_Object video_mode;
-  int video_mode_value;
-  int have_vga = 0;
   union REGS regs;
+  Lisp_Object video_mode;
+  int video_mode_value, have_vga = 0;
   int current_rows = ScreenRows (), current_cols = ScreenCols ();
 
   if (*rows == current_rows && *cols == current_cols)
     return;
 
-  /* Do we have a VGA?  */
-  regs.x.ax = 0x1a00;
-  int86 (0x10, &regs, &regs);
-  if (regs.h.al == 0x1a && regs.h.bl > 5 && regs.h.bl < 13)
-    have_vga = 1;
-
   mouse_off ();
+  have_vga = vga_installed ();
 
   /* If the user specified a special video mode for these dimensions,
      use that mode.  */
@@ -540,8 +611,7 @@ dos_set_window_size (rows, cols)
   else
     {
       static struct {
-       int rows;
-       int need_vga;
+       int rows, need_vga;
       }        std_dimension[] = {
          {25, 0},
          {28, 1},
@@ -612,6 +682,11 @@ dos_set_window_size (rows, cols)
   *rows = ScreenRows ();
   *cols = ScreenCols ();
 
+  /* Update Emacs' notion of screen dimensions.  */
+  screen_size_X = *cols;
+  screen_size_Y = *rows;
+  screen_size = *cols * *rows;
+
 #if __DJGPP__ > 1
   /* If the dimensions changed, the mouse highlight info is invalid.  */
   if (current_rows != *rows || current_cols != *cols)
@@ -645,17 +720,148 @@ static void
 mouse_off_maybe ()
 {
   int x, y;
-  
+
   if (!mouse_visible)
     return;
-  
+
   mouse_get_xy (&x, &y);
   if (y != new_pos_Y || x < new_pos_X)
     return;
-  
+
   mouse_off ();
 }
 
+#define DEFAULT_CURSOR_START (-1)
+#define DEFAULT_CURSOR_WIDTH (-1)
+#define BOX_CURSOR_WIDTH     (-32)
+
+/* Set cursor to begin at scan line START_LINE in the character cell
+   and extend for WIDTH scan lines.  Scan lines are counted from top
+   of the character cell, starting from zero.  */
+static void
+msdos_set_cursor_shape (struct frame *f, int start_line, int width)
+{
+#if __DJGPP__ > 1
+  unsigned desired_cursor;
+  __dpmi_regs regs;
+  int max_line, top_line, bot_line;
+
+  /* Avoid the costly BIOS call if F isn't the currently selected
+     frame.  Allow for NULL as unconditionally meaning the selected
+     frame.  */
+  if (f && f != SELECTED_FRAME())
+    return;
+
+  if (termscript)
+    fprintf (termscript, "\nCURSOR SHAPE=(%d,%d)", start_line, width);
+
+  /* The character cell size in scan lines is stored at 40:85 in the
+     BIOS data area.  */
+  max_line = _farpeekw (_dos_ds, 0x485) - 1;
+  switch (max_line)
+    {
+      default: /* this relies on CGA cursor emulation being ON! */
+      case 7:
+       bot_line = 7;
+       break;
+      case 9:
+       bot_line = 9;
+       break;
+      case 13:
+       bot_line = 12;
+       break;
+      case 15:
+       bot_line = 14;
+       break;
+    }
+
+  if (width < 0)
+    {
+      if (width == BOX_CURSOR_WIDTH)
+       {
+         top_line = 0;
+         bot_line = max_line;
+       }
+      else if (start_line != DEFAULT_CURSOR_START)
+       {
+         top_line = start_line;
+         bot_line = top_line - width - 1;
+       }
+      else if (width != DEFAULT_CURSOR_WIDTH)
+       {
+         top_line = 0;
+         bot_line = -1 - width;
+       }
+      else
+       top_line = bot_line + 1;
+    }
+  else if (width == 0)
+    {
+      /* [31, 0] seems to DTRT for all screen sizes.  */
+      top_line = 31;
+      bot_line = 0;
+    }
+  else /* WIDTH is positive */
+    {
+      if (start_line != DEFAULT_CURSOR_START)
+       bot_line = start_line;
+      top_line = bot_line - (width - 1);
+    }
+
+  /* If the current cursor shape is already what they want, we are
+     history here.  */
+  desired_cursor = ((top_line & 0x1f) << 8) | (bot_line & 0x1f);
+  if (desired_cursor == _farpeekw (_dos_ds, 0x460))
+    return;
+
+  regs.h.ah = 1;
+  regs.x.cx = desired_cursor;
+  __dpmi_int (0x10, &regs);
+#endif /* __DJGPP__ > 1 */
+}
+
+static void
+IT_set_cursor_type (struct frame *f, Lisp_Object cursor_type)
+{
+  if (EQ (cursor_type, Qbar) || EQ (cursor_type, Qhbar))
+    {
+      /* Just BAR means the normal EGA/VGA cursor.  */
+      msdos_set_cursor_shape (f, DEFAULT_CURSOR_START, DEFAULT_CURSOR_WIDTH);
+    }
+  else if (CONSP (cursor_type)
+          && (EQ (XCAR (cursor_type), Qbar)
+              || EQ (XCAR (cursor_type), Qhbar)))
+    {
+      Lisp_Object bar_parms = XCDR (cursor_type);
+      int width;
+
+      if (INTEGERP (bar_parms))
+       {
+         /* Feature: negative WIDTH means cursor at the top
+            of the character cell, zero means invisible cursor.  */
+         width = XINT (bar_parms);
+         msdos_set_cursor_shape (f, width >= 0 ? DEFAULT_CURSOR_START : 0,
+                                 width);
+       }
+      else if (CONSP (bar_parms)
+              && INTEGERP (XCAR (bar_parms))
+              && INTEGERP (XCDR (bar_parms)))
+       {
+         int start_line = XINT (XCDR (bar_parms));
+
+         width = XINT (XCAR (bar_parms));
+         msdos_set_cursor_shape (f, start_line, width);
+       }
+    }
+  else
+    {
+      /* Treat anything unknown as "box cursor".  This includes nil, so
+        that a frame which doesn't specify a cursor type gets a box,
+        which is the default in Emacs.  */
+      msdos_set_cursor_shape (f, 0, BOX_CURSOR_WIDTH);
+    }
+}
+
 static void
 IT_ring_bell (void)
 {
@@ -682,12 +888,13 @@ static void
 IT_set_face (int face)
 {
   struct frame *sf = SELECTED_FRAME();
-  struct face *fp = FACE_FROM_ID (sf, face);
-  unsigned long fg, bg;
+  struct face *fp  = FACE_FROM_ID (sf, face);
+  struct face *dfp = FACE_FROM_ID (sf, DEFAULT_FACE_ID);
+  unsigned long fg, bg, dflt_fg, dflt_bg;
 
   if (!fp)
     {
-      fp = FACE_FROM_ID (sf, DEFAULT_FACE_ID);
+      fp = dfp;
       /* The default face for the frame should always be realized and
         cached.  */
       if (!fp)
@@ -696,13 +903,13 @@ IT_set_face (int face)
   screen_face = face;
   fg = fp->foreground;
   bg = fp->background;
+  dflt_fg = dfp->foreground;
+  dflt_bg = dfp->background;
 
-  /* Don't use invalid colors.  In particular, FACE_TTY_DEFAULT_*
-     colors mean use the colors of the default face, except that if
-     highlight is on, invert the foreground and the background.  Note
-     that we assume all 16 colors to be available for the background,
-     since Emacs switches on this mode (and loses the blinking
-     attribute) at startup.  */
+  /* Don't use invalid colors.  In particular, FACE_TTY_DEFAULT_* colors
+     mean use the colors of the default face.  Note that we assume all
+     16 colors to be available for the background, since Emacs switches
+     on this mode (and loses the blinking attribute) at startup.  */
   if (fg == FACE_TTY_DEFAULT_COLOR || fg == FACE_TTY_DEFAULT_FG_COLOR)
     fg = FRAME_FOREGROUND_PIXEL (sf);
   else if (fg == FACE_TTY_DEFAULT_BG_COLOR)
@@ -713,18 +920,24 @@ IT_set_face (int face)
     bg = FRAME_FOREGROUND_PIXEL (sf);
 
   /* Make sure highlighted lines really stand out, come what may.  */
-  if ((highlight || fp->tty_reverse_p)
-      && (fg == FRAME_FOREGROUND_PIXEL (sf)
-         && bg == FRAME_BACKGROUND_PIXEL (sf)))
+  if (fp->tty_reverse_p && (fg == dflt_fg && bg == dflt_bg))
     {
       unsigned long tem = fg;
 
       fg = bg;
       bg = tem;
     }
+  /* If the user requested inverse video, obey.  */
+  if (inverse_video)
+    {
+      unsigned long tem2 = fg;
+
+      fg = bg;
+      bg = tem2;
+    }
   if (termscript)
-    fprintf (termscript, "<FACE %d%s: %d/%d[FG:%d/BG:%d]>", face,
-            highlight ? "H" : "", fp->foreground, fp->background, fg, bg);
+    fprintf (termscript, "<FACE %d: %d/%d[FG:%d/BG:%d]>", face,
+            fp->foreground, fp->background, fg, bg);
   if (fg >= 0 && fg < 16)
     {
       ScreenAttrib &= 0xf0;
@@ -743,16 +956,20 @@ static void
 IT_write_glyphs (struct glyph *str, int str_len)
 {
   unsigned char *screen_buf, *screen_bp, *screen_buf_end, *bp;
-  int unsupported_face = FAST_GLYPH_FACE (Vdos_unsupported_char_glyph);
-  unsigned unsupported_char= FAST_GLYPH_CHAR (Vdos_unsupported_char_glyph);
+  int unsupported_face = 0;
+  unsigned unsupported_char = '\177';
   int offset = 2 * (new_pos_X + screen_size_X * new_pos_Y);
   register int sl = str_len;
   register int tlen = GLYPH_TABLE_LENGTH;
   register Lisp_Object *tbase = GLYPH_TABLE_BASE;
 
-  struct coding_system *coding = (CODING_REQUIRE_ENCODING (&terminal_coding)
-                                 ? &terminal_coding
-                                 : &safe_terminal_coding);
+  /* If terminal_coding does any conversion, use it, otherwise use
+     safe_terminal_coding.  We can't use CODING_REQUIRE_ENCODING here
+     because it always returns 1 if terminal_coding.src_multibyte is 1.  */
+  struct coding_system *coding =
+    (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK
+     ? &terminal_coding
+     : &safe_terminal_coding);
   struct frame *sf;
 
   /* Do we need to consider conversion of unibyte characters to
@@ -761,8 +978,18 @@ IT_write_glyphs (struct glyph *str, int str_len)
     = (NILP (current_buffer->enable_multibyte_characters)
        && unibyte_display_via_language_environment);
 
+  unsigned char conversion_buffer[256];
+  int conversion_buffer_size = sizeof conversion_buffer;
+
   if (str_len <= 0) return;
-  
+
+  /* Set up the unsupported character glyph */
+  if (!NILP (Vdos_unsupported_char_glyph))
+    {
+      unsupported_char = FAST_GLYPH_CHAR (XINT (Vdos_unsupported_char_glyph));
+      unsupported_face = FAST_GLYPH_FACE (XINT (Vdos_unsupported_char_glyph));
+    }
+
   screen_buf = screen_bp = alloca (str_len * 2);
   screen_buf_end = screen_buf + str_len * 2;
   sf = SELECTED_FRAME();
@@ -773,7 +1000,7 @@ IT_write_glyphs (struct glyph *str, int str_len)
      face of the frame, before writing glyphs, and let the glyphs
      set the right face if it's different from the default.  */
   IT_set_face (DEFAULT_FACE_ID);
-  
+
   /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
      the tail.  */
   terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
@@ -796,6 +1023,9 @@ IT_write_glyphs (struct glyph *str, int str_len)
          register GLYPH g = GLYPH_FROM_CHAR_GLYPH (*str);
          int glyph_not_in_table = 0;
 
+         /* If g is negative, it means we have a multibyte character
+            in *str.  That's what GLYPH_FROM_CHAR_GLYPH returns for
+            multibyte characters.  */
          if (g < 0 || g >= tlen)
            {
              /* This glyph doesn't have an entry in Vglyph_table.  */
@@ -824,14 +1054,14 @@ IT_write_glyphs (struct glyph *str, int str_len)
          if (! CHAR_VALID_P (ch, 0))
            {
              g = !NILP (Vdos_unsupported_char_glyph)
-               ? Vdos_unsupported_char_glyph
+               ? XINT (Vdos_unsupported_char_glyph)
                : MAKE_GLYPH (sf, '\177', GLYPH_FACE (sf, g));
              ch = FAST_GLYPH_CHAR (g);
            }
 
          /* If the face of this glyph is different from the current
             screen face, update the screen attribute byte.  */
-         cf = FAST_GLYPH_FACE (g);
+         cf = str->face_id;
          if (cf != screen_face)
            IT_set_face (cf);   /* handles invalid faces gracefully */
 
@@ -857,6 +1087,7 @@ IT_write_glyphs (struct glyph *str, int str_len)
            }
          else
            {
+             coding->src_multibyte = 1;
              encode_coding (coding, buf, conversion_buffer, chlen,
                             conversion_buffer_size);
              chlen -= coding->consumed;
@@ -866,7 +1097,7 @@ IT_write_glyphs (struct glyph *str, int str_len)
                 terminal_coding with Vdos_unsupported_char_glyph.  */
              if (*conversion_buffer == '?')
                {
-                 char *cbp = conversion_buffer;
+                 unsigned char *cbp = conversion_buffer;
 
                  while (cbp < conversion_buffer + enclen && *cbp == '?')
                    *cbp++ = unsupported_char;
@@ -940,6 +1171,7 @@ IT_write_glyphs (struct glyph *str, int str_len)
       encode_coding (coding, "", conversion_buffer, 0, conversion_buffer_size);
       if (coding->produced > 0)
        {
+         screen_buf = alloca (coding->produced * 2);
          for (screen_bp = screen_buf, bp = conversion_buffer;
               coding->produced--; bp++)
            {
@@ -963,13 +1195,8 @@ IT_write_glyphs (struct glyph *str, int str_len)
                          Mouse Highlight (and friends..)
  ************************************************************************/
 
-/* This is used for debugging, to turn off note_mouse_highlight.  */
-int disable_mouse_highlight;
-
-/* If a string, dos_rawgetc generates an event to display that string.
-   (The display is done in keyboard.c:read_char.)  */
-static Lisp_Object help_echo;
-static Lisp_Object previous_help_echo; /* a helper temporary variable */
+/* Last window where we saw the mouse.  Used by mouse-autoselect-window.  */
+static Lisp_Object last_mouse_window;
 
 static int mouse_preempted = 0;        /* non-zero when XMenu gobbles mouse events */
 
@@ -996,7 +1223,7 @@ show_mouse_face (struct display_info *dpyinfo, int hl)
   int i;
   struct face *fp;
 
-  
+
   /* If window is in the process of being destroyed, don't bother
      doing anything.  */
   if (w->current_matrix == NULL)
@@ -1010,6 +1237,9 @@ show_mouse_face (struct display_info *dpyinfo, int hl)
   /* There's no sense to do anything if the mouse face isn't realized.  */
   if (hl > 0)
     {
+      if (dpyinfo->mouse_face_hidden)
+       goto set_cursor_shape;
+
       fp = FACE_FROM_ID (SELECTED_FRAME(), dpyinfo->mouse_face_face_id);
       if (!fp)
        goto set_cursor_shape;
@@ -1040,10 +1270,13 @@ show_mouse_face (struct display_info *dpyinfo, int hl)
 
       if (end_hpos <= start_hpos)
        continue;
+      /* Record that some glyphs of this row are displayed in
+         mouse-face.  */
+      row->mouse_face_p = hl > 0;
       if (hl > 0)
        {
-         int vpos = row->y + WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w);
-         int kstart = start_hpos + WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X (w);
+         int vpos = row->y + WINDOW_TOP_EDGE_Y (w);
+         int kstart = start_hpos + WINDOW_LEFT_EDGE_X (w);
          int nglyphs = end_hpos - start_hpos;
          int offset = ScreenPrimary + 2*(vpos*screen_size_X + kstart) + 1;
          int start_offset = offset;
@@ -1085,8 +1318,8 @@ show_mouse_face (struct display_info *dpyinfo, int hl)
          /* IT_write_glyphs writes at cursor position, so we need to
             temporarily move cursor coordinates to the beginning of
             the highlight region.  */
-         new_pos_X = start_hpos + WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X (w);
-         new_pos_Y = row->y + WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w);
+         new_pos_X = start_hpos + WINDOW_LEFT_EDGE_X (w);
+         new_pos_Y = row->y + WINDOW_TOP_EDGE_Y (w);
 
          if (termscript)
            fprintf (termscript, "<MH- %d-%d:%d>",
@@ -1100,7 +1333,6 @@ show_mouse_face (struct display_info *dpyinfo, int hl)
     }
 
  set_cursor_shape:
-  
   /* Change the mouse pointer shape.  */
   IT_set_mouse_pointer (hl);
 }
@@ -1110,7 +1342,7 @@ show_mouse_face (struct display_info *dpyinfo, int hl)
 static void
 clear_mouse_face (struct display_info *dpyinfo)
 {
-  if (! NILP (dpyinfo->mouse_face_window))
+  if (!dpyinfo->mouse_face_hidden && ! NILP (dpyinfo->mouse_face_window))
     show_mouse_face (dpyinfo, 0);
 
   dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
@@ -1125,13 +1357,9 @@ clear_mouse_face (struct display_info *dpyinfo)
 static int
 fast_find_position (struct window *w, int pos, int *hpos, int *vpos)
 {
-  int i;
-  int lastcol;
-  int maybe_next_line_p = 0;
-  int line_start_position;
+  int i, lastcol, line_start_position, maybe_next_line_p = 0;
   int yb = window_text_bottom_y (w);
-  struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
-  struct glyph_row *best_row = row;
+  struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0), *best_row = row;
 
   while (row->y < yb)
     {
@@ -1152,10 +1380,15 @@ fast_find_position (struct window *w, int pos, int *hpos, int *vpos)
        }
       else if (line_start_position > 0)
        best_row = row;
-      
+
+      /* Don't overstep the last matrix row, lest we get into the
+        never-never land... */
+      if (row->y + 1 >= yb)
+       break;
+
       ++row;
     }
-  
+
   /* Find the right column within BEST_ROW.  */
   lastcol = 0;
   row = best_row;
@@ -1194,7 +1427,7 @@ fast_find_position (struct window *w, int pos, int *hpos, int *vpos)
 /* Take proper action when mouse has moved to the mode or top line of
    window W, x-position X.  MODE_LINE_P non-zero means mouse is on the
    mode line.  X is relative to the start of the text display area of
-   W, so the width of bitmap areas and scroll bars must be subtracted
+   W, so the width of fringes and scroll bars must be subtracted
    to get a position relative to the start of the mode line.  */
 static void
 IT_note_mode_line_highlight (struct window *w, int x, int mode_line_p)
@@ -1207,30 +1440,37 @@ IT_note_mode_line_highlight (struct window *w, int x, int mode_line_p)
     row = MATRIX_MODE_LINE_ROW (w->current_matrix);
   else
     row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
-  
+
   if (row->enabled_p)
     {
       extern Lisp_Object Qhelp_echo;
       struct glyph *glyph, *end;
       Lisp_Object help, map;
-      
+
       /* Find the glyph under X.  */
-      glyph = row->glyphs[TEXT_AREA]
-       + x - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
+      glyph = (row->glyphs[TEXT_AREA]
+              + x
+              /* in case someone implements scroll bars some day... */
+              - WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w));
       end = glyph + row->used[TEXT_AREA];
       if (glyph < end
          && STRINGP (glyph->object)
-         && XSTRING (glyph->object)->intervals
+         && STRING_INTERVALS (glyph->object)
          && glyph->charpos >= 0
-         && glyph->charpos < XSTRING (glyph->object)->size)
+         && glyph->charpos < SCHARS (glyph->object))
        {
          /* If we're on a string with `help-echo' text property,
             arrange for the help to be displayed.  This is done by
             setting the global variable help_echo to the help string.  */
          help = Fget_text_property (make_number (glyph->charpos),
                                     Qhelp_echo, glyph->object);
-         if (STRINGP (help))
-           help_echo = help;
+         if (!NILP (help))
+           {
+             help_echo_string = help;
+             XSETWINDOW (help_echo_window, w);
+             help_echo_object = glyph->object;
+             help_echo_pos = glyph->charpos;
+           }
        }
     }
 }
@@ -1243,7 +1483,7 @@ static void
 IT_note_mouse_highlight (struct frame *f, int x, int y)
 {
   struct display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-  int portion;
+  enum window_part part = ON_NOTHING;
   Lisp_Object window;
   struct window *w;
 
@@ -1251,7 +1491,8 @@ IT_note_mouse_highlight (struct frame *f, int x, int y)
   if (mouse_preempted)
     return;
 
-  if (disable_mouse_highlight)
+  if (NILP (Vmouse_highlight)
+      || !f->glyphs_initialized_p)
     return;
 
   dpyinfo->mouse_face_mouse_x = x;
@@ -1268,7 +1509,7 @@ IT_note_mouse_highlight (struct frame *f, int x, int y)
     }
 
   /* Which window is that in?  */
-  window = window_from_coordinates (f, x, y, &portion, 0);
+  window = window_from_coordinates (f, x, y, &part, &x, &y, 0);
 
   /* If we were displaying active text in another window, clear that.  */
   if (! EQ (window, dpyinfo->mouse_face_window))
@@ -1280,37 +1521,39 @@ IT_note_mouse_highlight (struct frame *f, int x, int y)
 
   /* Convert to window-relative coordinates.  */
   w = XWINDOW (window);
-  x -= WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X (w);
-  y -= WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w);
 
-  if (portion == 1 || portion == 3)
+  if (part == ON_MODE_LINE || part == ON_HEADER_LINE)
     {
       /* Mouse is on the mode or top line.  */
-      IT_note_mode_line_highlight (w, x, portion == 1);
+      IT_note_mode_line_highlight (w, x, part == ON_MODE_LINE);
       return;
     }
-  else
-    IT_set_mouse_pointer (0);
+
+  IT_set_mouse_pointer (0);
 
   /* Are we in a window whose display is up to date?
      And verify the buffer's text has not changed.  */
-  if (/* Within text portion of the window.  */
-      portion == 0
+  if (part == ON_TEXT
       && EQ (w->window_end_valid, w->buffer)
       && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
       && (XFASTINT (w->last_overlay_modified)
          == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
     {
-      int pos, i, area;
+      int pos, i, nrows = w->current_matrix->nrows;
       struct glyph_row *row;
       struct glyph *glyph;
 
       /* Find the glyph under X/Y.  */
       glyph = NULL;
-      if (y < w->current_matrix->nrows)
+      if (y >= 0 && y < nrows)
        {
          row = MATRIX_ROW (w->current_matrix, y);
-         if (row->enabled_p
+         /* Give up if some row before the one we are looking for is
+            not enabled.  */
+         for (i = 0; i <= y; i++)
+           if (!MATRIX_ROW (w->current_matrix, i)->enabled_p)
+             break;
+         if (i > y  /* all rows upto and including the one at Y are enabled */
              && row->displays_text_p
              && x <  window_box_width (w, TEXT_AREA))
            {
@@ -1340,11 +1583,9 @@ IT_note_mouse_highlight (struct frame *f, int x, int y)
       /* Check for mouse-face and help-echo.  */
       {
        extern Lisp_Object Qmouse_face;
-       Lisp_Object mouse_face, overlay, position;
-       Lisp_Object *overlay_vec;
-       int len, noverlays;
+       Lisp_Object mouse_face, overlay, position, *overlay_vec;
+       int noverlays, obegv, ozv;
        struct buffer *obuf;
-       int obegv, ozv;
 
        /* If we get an out-of-range value, return now; avoid an error.  */
        if (pos > BUF_Z (XBUFFER (w->buffer)))
@@ -1362,19 +1603,9 @@ IT_note_mouse_highlight (struct frame *f, int x, int y)
        /* Is this char mouse-active or does it have help-echo?  */
        XSETINT (position, pos);
 
-       /* Put all the overlays we want in a vector in overlay_vec.
-          Store the length in len.  If there are more than 10, make
-          enough space for all, and try again.  */
-       len = 10;
-       overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
-       noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
-       if (noverlays > len)
-         {
-           len = noverlays;
-           overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
-           noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
-         }
-         
+       /* Put all the overlays we want in a vector in overlay_vec. */
+       GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL, 0);
+       /* Sort overlays into increasing priority order.  */
        noverlays = sort_overlays (overlay_vec, noverlays, w);
 
        /* Check mouse-face highlighting.  */
@@ -1392,7 +1623,7 @@ IT_note_mouse_highlight (struct frame *f, int x, int y)
 
            /* Find highest priority overlay that has a mouse-face prop.  */
            overlay = Qnil;
-           for (i = 0; i < noverlays; i++)
+           for (i = noverlays - 1; i >= 0; --i)
              {
                mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
                if (!NILP (mouse_face))
@@ -1428,7 +1659,8 @@ IT_note_mouse_highlight (struct frame *f, int x, int y)
                dpyinfo->mouse_face_window = window;
                dpyinfo->mouse_face_face_id
                  = face_at_buffer_position (w, pos, 0, 0,
-                                            &ignore, pos + 1, 1);
+                                            &ignore, pos + 1,
+                                            !dpyinfo->mouse_face_hidden);
 
                /* Display it as active.  */
                show_mouse_face (dpyinfo, 1);
@@ -1462,7 +1694,8 @@ IT_note_mouse_highlight (struct frame *f, int x, int y)
                dpyinfo->mouse_face_window = window;
                dpyinfo->mouse_face_face_id
                  = face_at_buffer_position (w, pos, 0, 0,
-                                            &ignore, pos + 1, 1);
+                                            &ignore, pos + 1,
+                                            !dpyinfo->mouse_face_hidden);
 
                /* Display it as active.  */
                show_mouse_face (dpyinfo, 1);
@@ -1476,24 +1709,40 @@ IT_note_mouse_highlight (struct frame *f, int x, int y)
 
          /* Check overlays first.  */
          help = Qnil;
-         for (i = 0; i < noverlays && !STRINGP (help); ++i)
-           help = Foverlay_get (overlay_vec[i], Qhelp_echo); 
-           
+         for (i = noverlays - 1; i >= 0 && NILP (help); --i)
+           {
+             overlay = overlay_vec[i];
+             help = Foverlay_get (overlay, Qhelp_echo);
+           }
+
+         if (!NILP (help))
+           {
+             help_echo_string = help;
+             help_echo_window = window;
+             help_echo_object = overlay;
+             help_echo_pos = pos;
+           }
          /* Try text properties.  */
-         if (!STRINGP (help)
-             && ((STRINGP (glyph->object)
-                  && glyph->charpos >= 0
-                  && glyph->charpos < XSTRING (glyph->object)->size)
-                 || (BUFFERP (glyph->object)
-                     && glyph->charpos >= BEGV
-                     && glyph->charpos < ZV)))
-           help = Fget_text_property (make_number (glyph->charpos),
-                                      Qhelp_echo, glyph->object);
-
-         if (STRINGP (help))
-           help_echo = help;
+         else if (NILP (help)
+                  && ((STRINGP (glyph->object)
+                       && glyph->charpos >= 0
+                       && glyph->charpos < SCHARS (glyph->object))
+                      || (BUFFERP (glyph->object)
+                          && glyph->charpos >= BEGV
+                          && glyph->charpos < ZV)))
+           {
+             help = Fget_text_property (make_number (glyph->charpos),
+                                        Qhelp_echo, glyph->object);
+             if (!NILP (help))
+               {
+                 help_echo_string = help;
+                 help_echo_window = window;
+                 help_echo_object = glyph->object;
+                 help_echo_pos = glyph->charpos;
+               }
+           }
        }
-         
+
        BEGV = obegv;
        ZV = ozv;
        current_buffer = obuf;
@@ -1505,19 +1754,18 @@ static void
 IT_clear_end_of_line (int first_unused)
 {
   char *spaces, *sp;
-  int i, j;
-  int offset = 2 * (new_pos_X + screen_size_X * new_pos_Y);
+  int i, j, offset = 2 * (new_pos_X + screen_size_X * new_pos_Y);
   extern int fatal_error_in_progress;
 
   if (new_pos_X >= first_unused || fatal_error_in_progress)
     return;
 
   IT_set_face (0);
-  if (termscript)
-    fprintf (termscript, "<CLR:EOL>");
   i = (j = first_unused - new_pos_X) * 2;
+  if (termscript)
+    fprintf (termscript, "<CLR:EOL[%d..%d)>", new_pos_X, first_unused);
   spaces = sp = alloca (i);
-  
+
   while (--j >= 0)
     {
       *sp++ = ' ';
@@ -1539,7 +1787,16 @@ IT_clear_screen (void)
 {
   if (termscript)
     fprintf (termscript, "<CLR:SCR>");
-  IT_set_face (0);
+  /* We are sometimes called (from clear_garbaged_frames) when a new
+     frame is being created, but its faces are not yet realized.  In
+     such a case we cannot call IT_set_face, since it will fail to find
+     any valid faces and will abort.  Instead, use the initial screen
+     colors; that should mimic what a Unix tty does, which simply clears
+     the screen with whatever default colors are in use.  */
+  if (FACE_FROM_ID (SELECTED_FRAME (), DEFAULT_FACE_ID) == NULL)
+    ScreenAttrib = (initial_screen_colors[0] << 4) | initial_screen_colors[1];
+  else
+    IT_set_face (0);
   mouse_off ();
   ScreenClear ();
   if (screen_virtual_segment)
@@ -1555,7 +1812,7 @@ IT_clear_to_end (void)
 
   while (new_pos_Y < screen_size_Y) {
     new_pos_X = 0;
-    IT_clear_end_of_line (0);
+    IT_clear_end_of_line (screen_size_X);
     new_pos_Y++;
   }
 }
@@ -1574,6 +1831,8 @@ static int cursor_cleared;
 static void
 IT_display_cursor (int on)
 {
+  if (termscript)
+    fprintf (termscript, "\nCURSOR %s", on ? "ON" : "OFF");
   if (on && cursor_cleared)
     {
       ScreenSetCursor (current_pos_Y, current_pos_X);
@@ -1627,7 +1886,7 @@ IT_cmgoto (FRAME_PTR f)
   /* If we are in the echo area, put the cursor at the
      end of the echo area message.  */
   if (!update_cursor_pos
-      && XFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top) <= new_pos_Y)
+      && WINDOW_TOP_EDGE_LINE (XWINDOW (FRAME_MINIBUF_WINDOW (f))) <= new_pos_Y)
     {
       int tem_X = current_pos_X, dummy;
 
@@ -1673,30 +1932,15 @@ IT_cmgoto (FRAME_PTR f)
     mouse_on ();
 }
 
-static void
-IT_reassert_line_highlight (int new, int vpos)
-{
-  highlight = new;
-}
-
-static void
-IT_change_line_highlight (int new_highlight, int y, int vpos, int first_unused_hpos)
-{
-  highlight = new_highlight;
-  IT_cursor_to (vpos, 0);
-  IT_clear_end_of_line (first_unused_hpos);
-}
-
 static void
 IT_update_begin (struct frame *f)
 {
   struct display_info *display_info = FRAME_X_DISPLAY_INFO (f);
-  
-  highlight = 0;
+  struct frame *mouse_face_frame = display_info->mouse_face_mouse_frame;
 
   BLOCK_INPUT;
 
-  if (f == display_info->mouse_face_mouse_frame)
+  if (f && f == mouse_face_frame)
     {
       /* Don't do highlighting for mouse motion during the update.  */
       display_info->mouse_face_defer = 1;
@@ -1708,9 +1952,8 @@ IT_update_begin (struct frame *f)
 
       /* Can we tell that this update does not affect the window
         where the mouse highlight is?  If so, no need to turn off.
-        Likewise, don't do anything if the frame is garbaged;
-        in that case, the frame's current matrix that we would use
-        is all wrong, and we will redisplay that line anyway.  */
+        Likewise, don't do anything if none of the enabled rows
+        contains glyphs highlighted in mouse face.  */
       if (!NILP (display_info->mouse_face_window)
          && WINDOWP (display_info->mouse_face_window))
        {
@@ -1725,7 +1968,8 @@ IT_update_begin (struct frame *f)
          else
            {
              for (i = 0; i < w->desired_matrix->nrows; ++i)
-               if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
+               if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i)
+                   && MATRIX_ROW (w->current_matrix, i)->mouse_face_p)
                  break;
            }
 
@@ -1733,7 +1977,7 @@ IT_update_begin (struct frame *f)
            clear_mouse_face (display_info);
        }
     }
-  else if (!FRAME_LIVE_P (display_info->mouse_face_mouse_frame))
+  else if (mouse_face_frame && !FRAME_LIVE_P (mouse_face_frame))
     {
       /* If the frame with mouse highlight was deleted, invalidate the
         highlight info.  */
@@ -1750,7 +1994,6 @@ IT_update_begin (struct frame *f)
 static void
 IT_update_end (struct frame *f)
 {
-  highlight = 0;
   FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
 }
 
@@ -1758,9 +2001,11 @@ static void
 IT_frame_up_to_date (struct frame *f)
 {
   struct display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  Lisp_Object new_cursor, frame_desired_cursor;
+  struct window *sw;
 
   if (dpyinfo->mouse_face_deferred_gc
-      || f == dpyinfo->mouse_face_mouse_frame)
+      || (f && f == dpyinfo->mouse_face_mouse_frame))
     {
       BLOCK_INPUT;
       if (dpyinfo->mouse_face_mouse_frame)
@@ -1771,6 +2016,33 @@ IT_frame_up_to_date (struct frame *f)
       UNBLOCK_INPUT;
     }
 
+  /* Set the cursor type to whatever they wanted.  In a minibuffer
+     window, we want the cursor to appear only if we are reading input
+     from this window, and we want the cursor to be taken from the
+     frame parameters.  For the selected window, we use either its
+     buffer-local value or the value from the frame parameters if the
+     buffer doesn't define its local value for the cursor type.  */
+  sw = XWINDOW (f->selected_window);
+  frame_desired_cursor = Fcdr (Fassq (Qcursor_type, f->param_alist));
+  if (cursor_in_echo_area
+      && FRAME_HAS_MINIBUF_P (f)
+      && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window)
+      && sw == XWINDOW (echo_area_window))
+    new_cursor = frame_desired_cursor;
+  else
+    {
+      struct buffer *b = XBUFFER (sw->buffer);
+
+      if (EQ (b->cursor_type, Qt))
+       new_cursor = frame_desired_cursor;
+      else if (NILP (b->cursor_type)) /* nil means no cursor */
+       new_cursor = Fcons (Qbar, make_number (0));
+      else
+       new_cursor = b->cursor_type;
+    }
+
+  IT_set_cursor_type (f, new_cursor);
+
   IT_cmgoto (f);  /* position cursor when update is done */
 }
 
@@ -1841,10 +2113,11 @@ x_set_menu_bar_lines (f, value, oldval)
   set_menu_bar_lines (f, value, oldval);
 }
 
-/* This was copied from xfns.c  */
+/* This was copied from xfaces.c  */
 
-Lisp_Object Qbackground_color;
-Lisp_Object Qforeground_color;
+extern Lisp_Object Qbackground_color;
+extern Lisp_Object Qforeground_color;
+Lisp_Object Qreverse;
 extern Lisp_Object Qtitle;
 
 /* IT_set_terminal_modes is called when emacs is started,
@@ -1855,19 +2128,18 @@ IT_set_terminal_modes (void)
 {
   if (termscript)
     fprintf (termscript, "\n<SET_TERM>");
-  highlight = 0;
 
   screen_size_X = ScreenCols ();
   screen_size_Y = ScreenRows ();
   screen_size = screen_size_X * screen_size_Y;
-  
+
   new_pos_X = new_pos_Y = 0;
   current_pos_X = current_pos_Y = -1;
 
   if (term_setup_done)
     return;
   term_setup_done = 1;
-  
+
   startup_screen_size_X = screen_size_X;
   startup_screen_size_Y = screen_size_Y;
   startup_screen_attrib = ScreenAttrib;
@@ -1923,21 +2195,17 @@ IT_reset_terminal_modes (void)
 {
   int display_row_start = (int) ScreenPrimary;
   int saved_row_len     = startup_screen_size_X * 2;
-  int update_row_len    = ScreenCols () * 2;
-  int current_rows      = ScreenRows ();
+  int update_row_len    = ScreenCols () * 2, current_rows = ScreenRows ();
   int to_next_row       = update_row_len;
   unsigned char *saved_row = startup_screen_buffer;
-  int cursor_pos_X = ScreenCols () - 1;
-  int cursor_pos_Y = ScreenRows () - 1;
+  int cursor_pos_X = ScreenCols () - 1, cursor_pos_Y = ScreenRows () - 1;
 
   if (termscript)
     fprintf (termscript, "\n<RESET_TERM>");
 
-  highlight = 0;
-
   if (!term_setup_done)
     return;
-  
+
   mouse_off ();
 
   /* Leave the video system in the same state as we found it,
@@ -2004,26 +2272,31 @@ IT_set_terminal_window (int foo)
 
 /* Remember the screen colors of the curent frame, to serve as the
    default colors for newly-created frames.  */
-
-static int initial_screen_colors[2];
-
 DEFUN ("msdos-remember-default-colors", Fmsdos_remember_default_colors,
        Smsdos_remember_default_colors, 1, 1, 0,
-  "Remember the screen colors of the current frame.")
+       doc: /* Remember the screen colors of the current frame.  */)
      (frame)
      Lisp_Object frame;
 {
-  int reverse;
   struct frame *f;
 
-  CHECK_FRAME (frame, 0);
+  CHECK_FRAME (frame);
   f= XFRAME (frame);
-  reverse = EQ (Fcdr (Fassq (intern ("reverse"), f->param_alist)), Qt);
 
-  initial_screen_colors[0]
-    = reverse ? FRAME_BACKGROUND_PIXEL (f) : FRAME_FOREGROUND_PIXEL (f);
-  initial_screen_colors[1]
-    = reverse ? FRAME_FOREGROUND_PIXEL (f) : FRAME_BACKGROUND_PIXEL (f);
+  /* This function is called after applying default-frame-alist to the
+     initial frame.  At that time, if reverse-colors option was
+     specified in default-frame-alist, it was already applied, and
+     frame colors are reversed.  We need to account for that.  */
+  if (EQ (Fcdr (Fassq (Qreverse, f->param_alist)), Qt))
+    {
+      initial_screen_colors[0] = FRAME_BACKGROUND_PIXEL (f);
+      initial_screen_colors[1] = FRAME_FOREGROUND_PIXEL (f);
+    }
+  else
+    {
+      initial_screen_colors[0] = FRAME_FOREGROUND_PIXEL (f);
+      initial_screen_colors[1] = FRAME_BACKGROUND_PIXEL (f);
+    }
 }
 
 void
@@ -2032,23 +2305,22 @@ IT_set_frame_parameters (f, alist)
      Lisp_Object alist;
 {
   Lisp_Object tail;
-  int length = XINT (Flength (alist));
-  int i, j;
+  int i, j, length = XINT (Flength (alist));
   Lisp_Object *parms
     = (Lisp_Object *) alloca (length * sizeof (Lisp_Object));
   Lisp_Object *values
     = (Lisp_Object *) alloca (length * sizeof (Lisp_Object));
-  Lisp_Object qreverse = intern ("reverse");
   /* Do we have to reverse the foreground and background colors?  */
-  int reverse = EQ (Fcdr (Fassq (qreverse, f->param_alist)), Qt);
-  int was_reverse = reverse;
+  int reverse = EQ (Fcdr (Fassq (Qreverse, f->param_alist)), Qt);
+  int need_to_reverse, was_reverse = reverse;
   int redraw = 0, fg_set = 0, bg_set = 0;
-  unsigned long orig_fg;
-  unsigned long orig_bg;
+  unsigned long orig_fg, orig_bg;
+  Lisp_Object frame_bg, frame_fg;
+  extern Lisp_Object Qdefault, QCforeground, QCbackground;
 
   /* If we are creating a new frame, begin with the original screen colors
      used for the initial frame.  */
-  if (alist == Vdefault_frame_alist
+  if (EQ (alist, Vdefault_frame_alist)
       && initial_screen_colors[0] != -1 && initial_screen_colors[1] != -1)
     {
       FRAME_FOREGROUND_PIXEL (f) = initial_screen_colors[0];
@@ -2056,6 +2328,15 @@ IT_set_frame_parameters (f, alist)
     }
   orig_fg = FRAME_FOREGROUND_PIXEL (f);
   orig_bg = FRAME_BACKGROUND_PIXEL (f);
+  frame_fg = Fcdr (Fassq (Qforeground_color, f->param_alist));
+  frame_bg = Fcdr (Fassq (Qbackground_color, f->param_alist));
+  /* frame_fg and frame_bg could be nil if, for example,
+     f->param_alist is nil, e.g. if we are called from
+     Fmake_terminal_frame.  */
+  if (NILP (frame_fg))
+    frame_fg = build_string (unspecified_fg);
+  if (NILP (frame_bg))
+    frame_bg = build_string (unspecified_bg);
 
   /* Extract parm names and values into those vectors.  */
   i = 0;
@@ -2065,7 +2346,7 @@ IT_set_frame_parameters (f, alist)
 
       elt = Fcar (tail);
       parms[i] = Fcar (elt);
-      CHECK_SYMBOL (parms[i], 1);
+      CHECK_SYMBOL (parms[i]);
       values[i] = Fcdr (elt);
       i++;
     }
@@ -2074,58 +2355,85 @@ IT_set_frame_parameters (f, alist)
 
   for (i = 0; i < j; i++)
     {
-      Lisp_Object prop = parms[i];
-      Lisp_Object val  = values[i];
+      Lisp_Object prop, val;
 
-      if (EQ (prop, qreverse))
+      prop = parms[i];
+      val  = values[i];
+
+      if (EQ (prop, Qreverse))
        reverse = EQ (val, Qt);
     }
-       
-  if (termscript && reverse && !was_reverse)
+
+  need_to_reverse = reverse && !was_reverse;
+  if (termscript && need_to_reverse)
     fprintf (termscript, "<INVERSE-VIDEO>\n");
 
   /* Now process the alist elements in reverse of specified order.  */
   for (i--; i >= 0; i--)
     {
-      Lisp_Object prop = parms[i];
-      Lisp_Object val  = values[i];
+      Lisp_Object prop, val, frame;
+
+      prop = parms[i];
+      val  = values[i];
 
       if (EQ (prop, Qforeground_color))
        {
-         unsigned long new_color = load_color (f, NULL, val, reverse
+         unsigned long new_color = load_color (f, NULL, val, need_to_reverse
                                                ? LFACE_BACKGROUND_INDEX
                                                : LFACE_FOREGROUND_INDEX);
          if (new_color !=  FACE_TTY_DEFAULT_COLOR
              && new_color != FACE_TTY_DEFAULT_FG_COLOR
              && new_color != FACE_TTY_DEFAULT_BG_COLOR)
            {
-             if (reverse)
-               /* FIXME: should the fore-/background of the default
-                  face change here as well?  */
-               FRAME_BACKGROUND_PIXEL (f) = new_color;
+             FRAME_FOREGROUND_PIXEL (f) = new_color;
+             /* Make sure the foreground of the default face for this
+                frame is changed as well.  */
+             XSETFRAME (frame, f);
+             if (need_to_reverse)
+               {
+                 Finternal_set_lisp_face_attribute (Qdefault, QCbackground,
+                                                    val, frame);
+                 prop = Qbackground_color;
+                 bg_set = 1;
+               }
              else
-               FRAME_FOREGROUND_PIXEL (f) = new_color;
+               {
+                 Finternal_set_lisp_face_attribute (Qdefault, QCforeground,
+                                                    val, frame);
+                 fg_set = 1;
+               }
              redraw = 1;
-             fg_set = 1;
              if (termscript)
                fprintf (termscript, "<FGCOLOR %lu>\n", new_color);
            }
        }
       else if (EQ (prop, Qbackground_color))
        {
-         unsigned long new_color = load_color (f, NULL, val, reverse
+         unsigned long new_color = load_color (f, NULL, val, need_to_reverse
                                                ? LFACE_FOREGROUND_INDEX
                                                : LFACE_BACKGROUND_INDEX);
          if (new_color != FACE_TTY_DEFAULT_COLOR
              && new_color != FACE_TTY_DEFAULT_FG_COLOR
              && new_color != FACE_TTY_DEFAULT_BG_COLOR)
            {
-             if (reverse)
-               FRAME_FOREGROUND_PIXEL (f) = new_color;
+             FRAME_BACKGROUND_PIXEL (f) = new_color;
+             /* Make sure the background of the default face for this
+                frame is changed as well.  */
+             XSETFRAME (frame, f);
+             if (need_to_reverse)
+               {
+                 Finternal_set_lisp_face_attribute (Qdefault, QCforeground,
+                                                    val, frame);
+                 prop = Qforeground_color;
+                 fg_set = 1;
+               }
              else
-               FRAME_BACKGROUND_PIXEL (f) = new_color;
+               {
+                 Finternal_set_lisp_face_attribute (Qdefault, QCbackground,
+                                                    val, frame);
+                 bg_set = 1;
+               }
              redraw = 1;
-             bg_set = 1;
              if (termscript)
                fprintf (termscript, "<BGCOLOR %lu>\n", new_color);
            }
@@ -2134,23 +2442,41 @@ IT_set_frame_parameters (f, alist)
        {
          x_set_title (f, val);
          if (termscript)
-           fprintf (termscript, "<TITLE: %s>\n", XSTRING (val)->data);
+           fprintf (termscript, "<TITLE: %s>\n", SDATA (val));
+       }
+      else if (EQ (prop, Qcursor_type))
+       {
+         IT_set_cursor_type (f, val);
+         if (termscript)
+           fprintf (termscript, "<CTYPE: %s>\n",
+                    EQ (val, Qbar) || EQ (val, Qhbar)
+                    || CONSP (val) && (EQ (XCAR (val), Qbar)
+                                       || EQ (XCAR (val), Qhbar))
+                    ? "bar" : "box");
        }
       store_frame_param (f, prop, val);
     }
 
   /* If they specified "reverse", but not the colors, we need to swap
      the current frame colors.  */
-  if (reverse && !was_reverse)
+  if (need_to_reverse)
     {
+      Lisp_Object frame;
+
       if (!fg_set)
        {
-         FRAME_BACKGROUND_PIXEL (f) = orig_fg;
+         XSETFRAME (frame, f);
+         Finternal_set_lisp_face_attribute (Qdefault, QCforeground,
+                                            tty_color_name (f, orig_bg),
+                                            frame);
          redraw = 1;
        }
       if (!bg_set)
        {
-         FRAME_FOREGROUND_PIXEL (f) = orig_bg;
+         XSETFRAME (frame, f);
+         Finternal_set_lisp_face_attribute (Qdefault, QCbackground,
+                                            tty_color_name (f, orig_fg),
+                                            frame);
          redraw = 1;
        }
     }
@@ -2173,8 +2499,7 @@ extern void init_frame_faces (FRAME_PTR);
 void
 internal_terminal_init ()
 {
-  char *term = getenv ("TERM");
-  char *colors;
+  char *term = getenv ("TERM"), *colors;
   struct frame *sf = SELECTED_FRAME();
 
 #ifdef HAVE_X_WINDOWS
@@ -2187,7 +2512,7 @@ internal_terminal_init ()
 
   if (getenv ("EMACSTEST"))
     termscript = fopen (getenv ("EMACSTEST"), "wt");
-  
+
 #ifndef HAVE_X_WINDOWS
   if (!internal_terminal || inhibit_window_system)
     {
@@ -2226,7 +2551,6 @@ internal_terminal_init ()
       if (colors[1] >= 0 && colors[1] < 16)
         the_only_x_display.background_pixel = colors[1];
     }
-  the_only_x_display.line_height = 1;
   the_only_x_display.font = (XFontStruct *)1;   /* must *not* be zero */
   the_only_x_display.display_info.mouse_face_mouse_frame = NULL;
   the_only_x_display.display_info.mouse_face_deferred_gc = 0;
@@ -2239,6 +2563,7 @@ internal_terminal_init ()
   the_only_x_display.display_info.mouse_face_mouse_x =
     the_only_x_display.display_info.mouse_face_mouse_y = 0;
   the_only_x_display.display_info.mouse_face_defer = 0;
+  the_only_x_display.display_info.mouse_face_hidden = 0;
 
   init_frame_faces (sf);
 
@@ -2250,10 +2575,8 @@ internal_terminal_init ()
   clear_to_end_hook = IT_clear_to_end;
   clear_end_of_line_hook = IT_clear_end_of_line;
   clear_frame_hook = IT_clear_screen;
-  change_line_highlight_hook = IT_change_line_highlight;
   update_begin_hook = IT_update_begin;
   update_end_hook = IT_update_end;
-  reassert_line_highlight_hook = IT_reassert_line_highlight;
   frame_up_to_date_hook = IT_frame_up_to_date;
 
   /* These hooks are called by term.c without being checked.  */
@@ -2276,7 +2599,7 @@ dos_get_saved_screen (screen, rows, cols)
   return *screen != (char *)0;
 #else
   return 0;
-#endif  
+#endif
 }
 
 #ifndef HAVE_X_WINDOWS
@@ -2316,7 +2639,7 @@ check_x (void)
 #define Ctrl   0x0200  /* ctrl scan-code */
 #define Shift  0x0400  /* shift scan-code */
 
-static int extended_kbd; /* 101 (102) keyboard present.        */
+static int extended_kbd; /* 101 (102) keyboard present. */
 
 struct kbd_translate {
   unsigned char  sc;
@@ -2446,7 +2769,7 @@ dos_set_keyboard (code, always)
   keyboard = keyboard_layout_list[0].keyboard_map;
   keyboard_map_all = always;
   dos_keyboard_layout = 1;
-  
+
   for (i = 0; i < (sizeof (keyboard_layout_list)/sizeof (struct keyboard_layout_list)); i++)
     if (code == keyboard_layout_list[i].country_code)
       {
@@ -2523,7 +2846,7 @@ ibmpc_translate_map[] =
   Map | 23,                    /* 'o' */
   Map | 24,                    /* 'p' */
   Map | 25,                    /* '[' */
-  Map | 26,                    /* ']' */ 
+  Map | 26,                    /* ']' */
   ModFct | 0x0d,               /* Return */
   Ignore,                      /* Ctrl */
   Map | 30,                    /* 'a' */
@@ -2699,23 +3022,22 @@ dos_get_modifiers (keymask)
      int *keymask;
 {
   union REGS regs;
-  int mask;
-  int modifiers = 0;
-  
+  int mask, modifiers = 0;
+
   /* Calculate modifier bits */
   regs.h.ah = extended_kbd ? 0x12 : 0x02;
   int86 (0x16, &regs, &regs);
 
   if (!extended_kbd)
     {
-      mask = regs.h.al & (SHIFT_P | CTRL_P | ALT_P | 
+      mask = regs.h.al & (SHIFT_P | CTRL_P | ALT_P |
                          SCRLOCK_P | NUMLOCK_P | CAPSLOCK_P);
     }
   else
     {
       mask = regs.h.al & (SHIFT_P |
                          SCRLOCK_P | NUMLOCK_P | CAPSLOCK_P);
-  
+
       /* Do not break international keyboard support.   */
       /* When Keyb.Com is loaded, the right Alt key is  */
       /* used for accessing characters like { and }      */
@@ -2743,7 +3065,7 @@ dos_get_modifiers (keymask)
              mask |= ALT_P;
            }
        }
-      
+
       if (regs.h.ah & 1)               /* Left CTRL pressed ? */
        mask |= CTRL_P;
 
@@ -2782,13 +3104,12 @@ int total_doskeys;              /* Total number of elements stored into recent_doskeys */
 Lisp_Object recent_doskeys; /* A vector, holding the last 100 keystrokes */
 
 DEFUN ("recent-doskeys", Frecent_doskeys, Srecent_doskeys, 0, 0, 0,
-  "Return vector of last 100 keyboard input values seen in dos_rawgetc.\n\
-Each input key receives two values in this vector: first the ASCII code,\n\
-and then the scan code.")
+       doc: /* Return vector of last 100 keyboard input values seen in dos_rawgetc.
+Each input key receives two values in this vector: first the ASCII code,
+and then the scan code.  */)
      ()
 {
-  Lisp_Object *keys = XVECTOR (recent_doskeys)->contents;
-  Lisp_Object val;
+  Lisp_Object val, *keys = XVECTOR (recent_doskeys)->contents;
 
   if (total_doskeys < NUM_RECENT_DOSKEYS)
     return Fvector (total_doskeys, keys);
@@ -2806,15 +3127,14 @@ and then the scan code.")
 }
 
 /* Get a char from keyboard.  Function keys are put into the event queue.  */
-
-extern void kbd_buffer_store_event (struct input_event *);
-
 static int
 dos_rawgetc ()
 {
   struct input_event event;
   union REGS regs;
-  
+  struct display_info *dpyinfo = FRAME_X_DISPLAY_INFO (SELECTED_FRAME());
+  EVENT_INIT (event);
+
 #ifndef HAVE_X_WINDOWS
   /* Maybe put the cursor where it should be.  */
   IT_cmgoto (SELECTED_FRAME());
@@ -2828,8 +3148,7 @@ dos_rawgetc ()
     {
       union REGS regs;
       register unsigned char c;
-      int sc, code = -1, mask, kp_mode;
-      int modifiers;
+      int modifiers, sc, code = -1, mask, kp_mode;
 
       regs.h.ah = extended_kbd ? 0x10 : 0x00;
       int86 (0x16, &regs, &regs);
@@ -2847,7 +3166,7 @@ dos_rawgetc ()
        recent_doskeys_index = 0;
 
       modifiers = dos_get_modifiers (&mask);
-      
+
 #ifndef HAVE_X_WINDOWS
       if (!NILP (Vdos_display_scancodes))
        {
@@ -2903,7 +3222,7 @@ dos_rawgetc ()
                continue;
            }
        }
-      
+
       if (c == 0)
        {
         /* We only look at the keyboard Ctrl/Shift/Alt keys when
@@ -2912,7 +3231,7 @@ dos_rawgetc ()
            `dos_get_modifiers', they might have already released the
            Alt key, and Emacs gets just `x', which is BAD.
            However, for keys with the `Map' property set, the ASCII
-           code returns zero iff Alt is pressed.  So, when we DON'T
+           code returns zero only if Alt is pressed.  So, when we DON'T
            have to support international_keyboard, we don't have to
            distinguish between the left and  right Alt keys, and we
            can set the META modifier for any keys with the `Map'
@@ -2925,22 +3244,22 @@ dos_rawgetc ()
          if (code & Shift)
            modifiers |= shift_modifier;
        }
-      
+
       switch (code & 0xf000)
        {
        case ModFct:
          if (c && !(mask & (SHIFT_P | ALT_P | CTRL_P | HYPER_P | SUPER_P)))
            return c;
          c = 0;                /* Special */
-         
+
        case FctKey:
          if (c != 0)
            return c;
-           
+
        case Special:
          code |= 0xff00;
          break;
-         
+
        case Normal:
          if (sc == 0)
            {
@@ -2955,7 +3274,7 @@ dos_rawgetc ()
              code = c;
              break;
            }
-         
+
        case Map:
          if (c && !(mask & ALT_P) && !((mask & SHIFT_P) && (mask & CTRL_P)))
            if (!keyboard_map_all)
@@ -2964,7 +3283,7 @@ dos_rawgetc ()
          code &= 0xff;
          if (mask & ALT_P && code <= 10 && code > 0 && dos_keypad_mode & 0x200)
            mask |= SHIFT_P;    /* ALT-1 => M-! etc. */
-         
+
          if (mask & SHIFT_P)
            {
              code = keyboard->shifted[code];
@@ -2987,7 +3306,7 @@ dos_rawgetc ()
              kp_mode = dos_keypad_mode & 0x03;
            else
              kp_mode = (dos_keypad_mode >> 4) & 0x03;
-         
+
          switch (kp_mode)
            {
            case 0:
@@ -3003,13 +3322,13 @@ dos_rawgetc ()
              code = keypad_translate_map[code].meta_code;
              modifiers = meta_modifier;
              break;
-             
+
            case 3:
              code = 0xff00 | keypad_translate_map[code].editkey_code;
              break;
            }
          break;
-         
+
        case Grey:
          code &= 0xff;
          kp_mode = ((mask & (NUMLOCK_P|CTRL_P|SHIFT_P|ALT_P)) == NUMLOCK_P) ? 0x04 : 0x40;
@@ -3019,18 +3338,25 @@ dos_rawgetc ()
            code = grey_key_translate_map[code].char_code;
          break;
        }
-      
+
     make_event:
       if (code == 0)
        continue;
-      
+
+      if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
+       {
+         clear_mouse_face (dpyinfo);
+         dpyinfo->mouse_face_hidden = 1;
+       }
+
       if (code >= 0x100)
-       event.kind = non_ascii_keystroke;
+       event.kind = NON_ASCII_KEYSTROKE_EVENT;
       else
-       event.kind = ascii_keystroke;
+       event.kind = ASCII_KEYSTROKE_EVENT;
       event.code = code;
       event.modifiers =        modifiers;
       event.frame_or_window = selected_frame;
+      event.arg = Qnil;
       event.timestamp = event_timestamp ();
       kbd_buffer_store_event (&event);
     }
@@ -3039,6 +3365,7 @@ dos_rawgetc ()
     {
       int but, press, x, y, ok;
       int mouse_prev_x = mouse_last_x, mouse_prev_y = mouse_last_y;
+      Lisp_Object mouse_window = Qnil;
 
       /* Check for mouse movement *before* buttons.  */
       mouse_check_moved ();
@@ -3047,17 +3374,55 @@ dos_rawgetc ()
          might need to update mouse highlight.  */
       if (mouse_last_x != mouse_prev_x || mouse_last_y != mouse_prev_y)
        {
-         previous_help_echo = help_echo;
-         help_echo = Qnil;
+         if (dpyinfo->mouse_face_hidden)
+           {
+             dpyinfo->mouse_face_hidden = 0;
+             clear_mouse_face (dpyinfo);
+           }
+
+         /* Generate SELECT_WINDOW_EVENTs when needed.  */
+         if (!NILP (Vmouse_autoselect_window))
+           {
+             mouse_window = window_from_coordinates (SELECTED_FRAME(),
+                                                     mouse_last_x,
+                                                     mouse_last_y,
+                                                     0, 0, 0, 0);
+             /* A window will be selected only when it is not
+                selected now, and the last mouse movement event was
+                not in it.  A minibuffer window will be selected iff
+                it is active.  */
+             if (WINDOWP (mouse_window)
+                 && !EQ (mouse_window, last_mouse_window)
+                 && !EQ (mouse_window, selected_window))
+               {
+                 event.kind = SELECT_WINDOW_EVENT;
+                 event.frame_or_window = mouse_window;
+                 event.arg = Qnil;
+                 event.timestamp = event_timestamp ();
+                 kbd_buffer_store_event (&event);
+               }
+             last_mouse_window = mouse_window;
+           }
+         else
+           last_mouse_window = Qnil;
+
+         previous_help_echo_string = help_echo_string;
+         help_echo_string = help_echo_object = help_echo_window = Qnil;
+         help_echo_pos = -1;
          IT_note_mouse_highlight (SELECTED_FRAME(),
                                   mouse_last_x, mouse_last_y);
          /* If the contents of the global variable help_echo has
             changed, generate a HELP_EVENT.  */
-         if (STRINGP (help_echo) || STRINGP (previous_help_echo))
+         if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
            {
              event.kind = HELP_EVENT;
-             event.frame_or_window = Fcons (selected_frame, help_echo);
+             event.frame_or_window = selected_frame;
+             event.arg = help_echo_object;
+             event.x = WINDOWP (help_echo_window)
+               ? help_echo_window : selected_frame;
+             event.y = help_echo_string;
              event.timestamp = event_timestamp ();
+             event.code = help_echo_pos;
              kbd_buffer_store_event (&event);
            }
        }
@@ -3094,13 +3459,14 @@ dos_rawgetc ()
                      }
                  }
 
-               event.kind = mouse_click;
+               event.kind = MOUSE_CLICK_EVENT;
                event.code = button_num;
                event.modifiers = dos_get_modifiers (0)
                  | (press ? down_modifier : up_modifier);
-               event.x = x;
-               event.y = y;
+               event.x = make_number (x);
+               event.y = make_number (y);
                event.frame_or_window = selected_frame;
+               event.arg = Qnil;
                event.timestamp = event_timestamp ();
                kbd_buffer_store_event (&event);
              }
@@ -3137,33 +3503,7 @@ dos_keyread ()
 }
 \f
 #ifndef HAVE_X_WINDOWS
-/* See xterm.c for more info.  */
-void
-pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
-     FRAME_PTR f;
-     register int pix_x, pix_y;
-     register int *x, *y;
-     XRectangle *bounds;
-     int noclip;
-{
-  if (bounds) abort ();
-
-  /* Ignore clipping.  */
-
-  *x = pix_x;
-  *y = pix_y;
-}
 
-void
-glyph_to_pixel_coords (f, x, y, pix_x, pix_y)
-     FRAME_PTR f;
-     register int x, y;
-     register int *pix_x, *pix_y;
-{
-  *pix_x = x;
-  *pix_y = y;
-}
-\f
 /* Simulation of X's menus.  Nothing too fancy here -- just make it work
    for now.
 
@@ -3172,6 +3512,12 @@ glyph_to_pixel_coords (f, x, y, pix_x, pix_y)
    grab the nearest Xlib manual (down the hall, second-to-last door on the
    left), but I don't think it's worth the effort.  */
 
+/* These hold text of the current and the previous menu help messages.  */
+static char *menu_help_message, *prev_menu_help_message;
+/* Pane number and item number of the menu item which generated the
+   last menu help message.  */
+static int menu_help_paneno, menu_help_itemno;
+
 static XMenu *
 IT_menu_create ()
 {
@@ -3194,6 +3540,7 @@ IT_menu_make_room (XMenu *menu)
       menu->text = (char **) xmalloc (count * sizeof (char *));
       menu->submenu = (XMenu **) xmalloc (count * sizeof (XMenu *));
       menu->panenumber = (int *) xmalloc (count * sizeof (int));
+      menu->help_text = (char **) xmalloc (count * sizeof (char *));
     }
   else if (menu->allocated == menu->count)
     {
@@ -3204,6 +3551,8 @@ IT_menu_make_room (XMenu *menu)
        = (XMenu **) xrealloc (menu->submenu, count * sizeof (XMenu *));
       menu->panenumber
        = (int *) xrealloc (menu->panenumber, count * sizeof (int));
+      menu->help_text
+       = (char **) xrealloc (menu->help_text, count * sizeof (char *));
     }
 }
 
@@ -3251,16 +3600,15 @@ IT_menu_calc_size (XMenu *menu, int *width, int *height)
 /* Display MENU at (X,Y) using FACES.  */
 
 static void
-IT_menu_display (XMenu *menu, int y, int x, int *faces)
+IT_menu_display (XMenu *menu, int y, int x, int pn, int *faces, int disp_help)
 {
-  int i, j, face, width;
+  int i, j, face, width,  mx, my, enabled, mousehere, row, col;
   struct glyph *text, *p;
   char *q;
-  int mx, my;
-  int enabled, mousehere;
-  int row, col;
   struct frame *sf = SELECTED_FRAME();
 
+  menu_help_message = NULL;
+
   width = menu->width;
   text = (struct glyph *) xmalloc ((width + 2) * sizeof (struct glyph));
   ScreenGetCursor (&row, &col);
@@ -3275,6 +3623,14 @@ IT_menu_display (XMenu *menu, int y, int x, int *faces)
        = (!menu->submenu[i] && menu->panenumber[i]) || (menu->submenu[i]);
       mousehere = (y + i == my && x <= mx && mx < x + width + 2);
       face = faces[enabled + mousehere * 2];
+      /* The following if clause means that we display the menu help
+        strings even if the menu item is currently disabled.  */
+      if (disp_help && enabled + mousehere * 2 >= 2)
+       {
+         menu_help_message = menu->help_text[i];
+         menu_help_paneno = pn - 1;
+         menu_help_itemno = i;
+       }
       p = text;
       SET_CHAR_GLYPH (*p, ' ', face, 0);
       p++;
@@ -3317,10 +3673,7 @@ IT_menu_display (XMenu *menu, int y, int x, int *faces)
 /* Report availability of menus.  */
 
 int
-have_menus_p ()
-{
-  return 1;
-}
+have_menus_p () {  return 1; }
 
 /* Create a brand new menu structure.  */
 
@@ -3347,6 +3700,7 @@ XMenuAddPane (Display *foo, XMenu *menu, char *txt, int enable)
   menu->submenu[menu->count] = IT_menu_create ();
   menu->text[menu->count] = txt;
   menu->panenumber[menu->count] = ++menu->panecount;
+  menu->help_text[menu->count] = NULL;
   menu->count++;
 
   /* Adjust length for possible control characters (which will
@@ -3365,7 +3719,7 @@ XMenuAddPane (Display *foo, XMenu *menu, char *txt, int enable)
 
 int
 XMenuAddSelection (Display *bar, XMenu *menu, int pane,
-                  int foo, char *txt, int enable)
+                  int foo, char *txt, int enable, char *help_text)
 {
   int len;
   char *p;
@@ -3377,6 +3731,7 @@ XMenuAddSelection (Display *bar, XMenu *menu, int pane,
   menu->submenu[menu->count] = (XMenu *) 0;
   menu->text[menu->count] = txt;
   menu->panenumber[menu->count] = enable;
+  menu->help_text[menu->count] = help_text;
   menu->count++;
 
   /* Adjust length for possible control characters (which will
@@ -3416,18 +3771,15 @@ struct IT_menu_state
 
 int
 XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx,
-              int x0, int y0, unsigned ButtonMask, char **txt)
+              int x0, int y0, unsigned ButtonMask, char **txt,
+              void (*help_callback)(char *, int, int))
 {
   struct IT_menu_state *state;
-  int statecount;
-  int x, y, i, b;
-  int screensize;
-  int faces[4];
-  Lisp_Object selectface;
-  int leave, result, onepane;
+  int statecount, x, y, i, b, screensize, leave, result, onepane;
   int title_faces[4];          /* face to display the menu title */
-  int buffers_num_deleted = 0;
+  int faces[4], buffers_num_deleted = 0;
   struct frame *sf = SELECTED_FRAME();
+  Lisp_Object saved_echo_area_message, selectface;
 
   /* Just in case we got here without a mouse present...  */
   if (have_mouse <= 0)
@@ -3440,22 +3792,22 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx,
     y0 = 1;
 
   /* We will process all the mouse events directly, so we had
-     better prevented dos_rawgetc from stealing them from us.  */
+     better prevent dos_rawgetc from stealing them from us.  */
   mouse_preempted++;
 
   state = alloca (menu->panecount * sizeof (struct IT_menu_state));
   screensize = screen_size * 2;
   faces[0]
     = lookup_derived_face (sf, intern ("msdos-menu-passive-face"),
-                          CHARSET_ASCII, DEFAULT_FACE_ID);
+                          0, DEFAULT_FACE_ID, 1);
   faces[1]
     = lookup_derived_face (sf, intern ("msdos-menu-active-face"),
-                          CHARSET_ASCII, DEFAULT_FACE_ID);
+                          0, DEFAULT_FACE_ID, 1);
   selectface = intern ("msdos-menu-select-face");
   faces[2] = lookup_derived_face (sf, selectface,
-                                 CHARSET_ASCII, faces[0]);
+                                 0, faces[0], 1);
   faces[3] = lookup_derived_face (sf, selectface,
-                                 CHARSET_ASCII, faces[1]);
+                                 0, faces[1], 1);
 
   /* Make sure the menu title is always displayed with
      `msdos-menu-active-face', no matter where the mouse pointer is.  */
@@ -3466,7 +3818,7 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx,
 
   /* Don't let the title for the "Buffers" popup menu include a
      digit (which is ugly).
-     
+
      This is a terrible kludge, but I think the "Buffers" case is
      the only one where the title includes a number, so it doesn't
      seem to be necessary to make this more general.  */
@@ -3475,6 +3827,11 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx,
       menu->text[0][7] = '\0';
       buffers_num_deleted = 1;
     }
+
+  /* We need to save the current echo area message, so that we could
+     restore it below, before we exit.  See the commentary below,
+     before the call to message_with_string.  */
+  saved_echo_area_message = Fcurrent_message ();
   state[0].menu = menu;
   mouse_off ();
   ScreenRetrieve (state[0].screen_behind = xmalloc (screensize));
@@ -3483,7 +3840,8 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx,
      panes, which is ugly.  */
   IT_display_cursor (0);
 
-  IT_menu_display (menu, y0 - 1, x0 - 1, title_faces); /* display menu title */
+  /* Display the menu title.  */
+  IT_menu_display (menu, y0 - 1, x0 - 1, 1, title_faces, 0);
   if (buffers_num_deleted)
     menu->text[0][7] = ' ';
   if ((onepane = menu->count == 1 && menu->submenu[0]))
@@ -3542,7 +3900,8 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx,
                        IT_menu_display (state[i].menu,
                                         state[i].y,
                                         state[i].x,
-                                        faces);
+                                        state[i].pane,
+                                        faces, 1);
                        state[statecount].menu = state[i].menu->submenu[dy];
                        state[statecount].pane = state[i].menu->panenumber[dy];
                        mouse_off ();
@@ -3551,19 +3910,30 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx,
                        state[statecount].x
                          = state[i].x + state[i].menu->width + 2;
                        state[statecount].y = y;
-                       statecount++;                     
+                       statecount++;
                      }
                  }
              }
          IT_menu_display (state[statecount - 1].menu,
                           state[statecount - 1].y,
                           state[statecount - 1].x,
-                          faces);
+                          state[statecount - 1].pane,
+                          faces, 1);
        }
       else
-       /* We are busy-waiting for the mouse to move, so let's be nice
-          to other Windows applications by releasing our time slice.  */
-       __dpmi_yield ();
+       {
+         if ((menu_help_message || prev_menu_help_message)
+             && menu_help_message != prev_menu_help_message)
+           {
+             help_callback (menu_help_message,
+                            menu_help_paneno, menu_help_itemno);
+             IT_display_cursor (0);
+             prev_menu_help_message = menu_help_message;
+           }
+         /* We are busy-waiting for the mouse to move, so let's be nice
+            to other Windows applications by releasing our time slice.  */
+         __dpmi_yield ();
+       }
       for (b = 0; b < mouse_button_count && !leave; b++)
        {
          /* Only leave if user both pressed and released the mouse, and in
@@ -3583,6 +3953,27 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx,
   ScreenUpdate (state[0].screen_behind);
   if (screen_virtual_segment)
     dosv_refresh_virtual_screen (0, screen_size);
+
+  /* We have a situation here.  ScreenUpdate has just restored the
+     screen contents as it was before we started drawing this menu.
+     That includes any echo area message that could have been
+     displayed back then.  (In reality, that echo area message will
+     almost always be the ``keystroke echo'' that echoes the sequence
+     of menu items chosen by the user.)  However, if the menu had some
+     help messages, then displaying those messages caused Emacs to
+     forget about the original echo area message.  So when
+     ScreenUpdate restored it, it created a discrepancy between the
+     actual screen contents and what Emacs internal data structures
+     know about it.
+
+     To avoid this conflict, we force Emacs to restore the original
+     echo area message as we found it when we entered this function.
+     The irony of this is that we then erase the restored message
+     right away, so the only purpose of restoring it is so that
+     erasing it works correctly...  */
+  if (! NILP (saved_echo_area_message))
+    message_with_string ("%s", saved_echo_area_message, 0);
+  message (0);
   while (statecount--)
     xfree (state[statecount].screen_behind);
   IT_display_cursor (1);       /* turn cursor back on */
@@ -3592,6 +3983,9 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx,
      (which invoked the menu) too quickly.  If we don't remove these events,
      Emacs will process them after we return and surprise the user.  */
   discard_mouse_events ();
+  mouse_clear_clicks ();
+  if (!kbd_buffer_events_waiting (1))
+    clear_input_pending ();
   /* Allow mouse events generation by dos_rawgetc.  */
   mouse_preempted--;
   return result;
@@ -3611,20 +4005,22 @@ XMenuDestroy (Display *foo, XMenu *menu)
       xfree (menu->text);
       xfree (menu->submenu);
       xfree (menu->panenumber);
+      xfree (menu->help_text);
     }
   xfree (menu);
+  menu_help_message = prev_menu_help_message = NULL;
 }
 
 int
 x_pixel_width (struct frame *f)
 {
-  return FRAME_WIDTH (f);
+  return FRAME_COLS (f);
 }
 
 int
 x_pixel_height (struct frame *f)
 {
-  return FRAME_HEIGHT (f);
+  return FRAME_LINES (f);
 }
 #endif /* !HAVE_X_WINDOWS */
 \f
@@ -3675,8 +4071,7 @@ getdefdir (drive, dst)
      int drive;
      char *dst;
 {
-  char in_path[4], *p = in_path;
-  int e = errno;
+  char in_path[4], *p = in_path, e = errno;
 
   /* Generate "X:." (when drive is X) or "." (when drive is 0).  */
   if (drive != 0)
@@ -3700,6 +4095,16 @@ getdefdir (drive, dst)
   return 1;
 }
 
+char *
+emacs_root_dir (void)
+{
+  static char root_dir[4];
+
+  sprintf (root_dir, "%c:/", 'A' + getdisk ());
+  root_dir[0] = tolower (root_dir[0]);
+  return root_dir;
+}
+
 /* Remove all CR's that are followed by a LF.  */
 
 int
@@ -3707,9 +4112,7 @@ crlf_to_lf (n, buf)
      register int n;
      register unsigned char *buf;
 {
-  unsigned char *np = buf;
-  unsigned char *startp = buf;
-  unsigned char *endp = buf + n;
+  unsigned char *np = buf, *startp = buf, *endp = buf + n;
 
   if (n == 0)
     return n;
@@ -3804,7 +4207,7 @@ __write (int handle, const void *buffer, size_t count)
    used when you compile with DJGPP v2.0.  */
 
 #include <io.h>
+
 int _rename(const char *old, const char *new)
 {
   __dpmi_regs r;
@@ -3918,9 +4321,9 @@ int _rename(const char *old, const char *new)
 #endif /* __DJGPP__ == 2 && __DJGPP_MINOR__ == 0 */
 
 DEFUN ("msdos-long-file-names", Fmsdos_long_file_names, Smsdos_long_file_names,
-  0, 0, 0,
-  "Return non-nil if long file names are supported on MSDOS.")
-  ()
+       0, 0, 0,
+       doc: /* Return non-nil if long file names are supported on MSDOS.  */)
+     ()
 {
   return (_USE_LFN ? Qt : Qnil);
 }
@@ -3951,11 +4354,11 @@ msdos_downcase_filename (p)
 
 DEFUN ("msdos-downcase-filename", Fmsdos_downcase_filename, Smsdos_downcase_filename,
        1, 1, 0,
-  "Convert alphabetic characters in FILENAME to lower case and return that.\n\
-When long filenames are supported, doesn't change FILENAME.\n\
-If FILENAME is not a string, returns nil.\n\
-The argument object is never altered--the value is a copy.")
-  (filename)
+       doc: /* Convert alphabetic characters in FILENAME to lower case and return that.
+When long filenames are supported, doesn't change FILENAME.
+If FILENAME is not a string, returns nil.
+The argument object is never altered--the value is a copy.  */)
+     (filename)
      Lisp_Object filename;
 {
   Lisp_Object tem;
@@ -3964,7 +4367,7 @@ The argument object is never altered--the value is a copy.")
     return Qnil;
 
   tem = Fcopy_sequence (filename);
-  msdos_downcase_filename (XSTRING (tem)->data);
+  msdos_downcase_filename (SDATA (tem));
   return tem;
 }
 \f
@@ -3995,11 +4398,10 @@ init_environment (argc, argv, skip_args)
      int skip_args;
 {
   char *s, *t, *root;
-  int len;
+  int len, i;
   static const char * const tempdirs[] = {
     "$TMPDIR", "$TEMP", "$TMP", "c:/"
   };
-  int i;
   const int imax = sizeof (tempdirs) / sizeof (tempdirs[0]);
 
   /* Make sure they have a usable $TMPDIR.  Many Emacs functions use
@@ -4009,9 +4411,28 @@ init_environment (argc, argv, skip_args)
   for (i = 0; i < imax ; i++)
     {
       const char *tmp = tempdirs[i];
+      char buf[FILENAME_MAX];
 
       if (*tmp == '$')
-       tmp = getenv (tmp + 1);
+       {
+         int tmp_len;
+
+         tmp = getenv (tmp + 1);
+         if (!tmp)
+           continue;
+
+         /* Some lusers set TMPDIR=e:, probably because some losing
+            programs cannot handle multiple slashes if they use e:/.
+            e: fails in `access' below, so we interpret e: as e:/.  */
+         tmp_len = strlen(tmp);
+         if (tmp[tmp_len - 1] != '/' && tmp[tmp_len - 1] != '\\')
+           {
+             strcpy(buf, tmp);
+             buf[tmp_len++] = '/', buf[tmp_len] = 0;
+             tmp = buf;
+           }
+       }
+
       /* Note that `access' can lie to us if the directory resides on a
         read-only filesystem, like CD-ROM or a write-protected floppy.
         The only way to be really sure is to actually create a file and
@@ -4185,7 +4606,7 @@ dos_ttraw ()
 {
   union REGS inregs, outregs;
   static int first_time = 1;
-  
+
   break_stat = getcbrk ();
   setcbrk (0);
 #if __DJGPP__ < 2
@@ -4197,7 +4618,7 @@ dos_ttraw ()
       inregs.h.ah = 0xc0;
       int86 (0x15, &inregs, &outregs);
       extended_kbd = (!outregs.x.cflag) && (outregs.h.ah == 0);
-  
+
       have_mouse = 0;
 
       if (internal_terminal
@@ -4223,23 +4644,17 @@ dos_ttraw ()
            {
              have_mouse = 1;   /* enable mouse */
              mouse_visible = 0;
-             
-             if (outregs.x.bx == 3)
-               {
-                 mouse_button_count = 3;
-                 mouse_button_translate[0] = 0; /* Left */
-                 mouse_button_translate[1] = 2; /* Middle */
-                 mouse_button_translate[2] = 1; /* Right */
-               }
-             else
-               {
-                 mouse_button_count = 2;
-                 mouse_button_translate[0] = 0;
-                 mouse_button_translate[1] = 1;
-               }
+             mouse_setup_buttons (outregs.x.bx);
              mouse_position_hook = &mouse_get_pos;
              mouse_init ();
            }
+
+#ifndef HAVE_X_WINDOWS
+#if __DJGPP__ >= 2
+         /* Save the cursor shape used outside Emacs.  */
+         outside_cursor = _farpeekw (_dos_ds, 0x460);
+#endif
+#endif
        }
 
       first_time = 0;
@@ -4285,6 +4700,16 @@ dos_ttcooked ()
 
 #if __DJGPP__ >= 2
 
+#ifndef HAVE_X_WINDOWS
+  /* Restore the cursor shape we found on startup.  */
+  if (outside_cursor)
+    {
+      inregs.h.ah = 1;
+      inregs.x.cx = outside_cursor;
+      int86 (0x10, &inregs, &outregs);
+    }
+#endif
+
   return (setmode (fileno (stdin), stdin_stat) != -1);
 
 #else  /* not __DJGPP__ >= 2 */
@@ -4312,9 +4737,7 @@ run_msdos_command (argv, working_dir, tempin, tempout, temperr, envv)
 {
   char *saveargv1, *saveargv2, *lowcase_argv0, *pa, *pl;
   char oldwd[MAXPATHLEN + 1]; /* Fixed size is safe on MSDOS.  */
-  int msshell, result = -1;
-  int inbak, outbak, errbak;
-  int x, y;
+  int msshell, result = -1, inbak, outbak, errbak, x, y;
   Lisp_Object cmd;
 
   /* Get current directory as MSDOS cwd is not per-process.  */
@@ -4340,18 +4763,23 @@ run_msdos_command (argv, working_dir, tempin, tempout, temperr, envv)
       saveargv1 = argv[1];
       saveargv2 = argv[2];
       argv[1] = "/c";
-      if (argv[2])
+      /* We only need to mirror slashes if a DOS shell will be invoked
+        not via `system' (which does the mirroring itself).  Yes, that
+        means DJGPP v1.x will lose here.  */
+      if (argv[2] && argv[3])
        {
          char *p = alloca (strlen (argv[2]) + 1);
 
          strcpy (argv[2] = p, saveargv2);
          while (*p && isspace (*p))
            p++;
-         while (*p && !isspace (*p))
-           if (*p == '/')
-             *p++ = '\\';
-           else
-             p++;
+         while (*p)
+           {
+             if (*p == '/')
+               *p++ = '\\';
+             else
+               p++;
+           }
        }
     }
 
@@ -4366,7 +4794,7 @@ run_msdos_command (argv, working_dir, tempin, tempout, temperr, envv)
     mouse_get_xy (&x, &y);
 
   dos_ttcooked ();     /* do it here while 0 = stdin */
-  
+
   dup2 (tempin, 0);
   dup2 (tempout, 1);
   dup2 (temperr, 2);
@@ -4392,6 +4820,7 @@ run_msdos_command (argv, working_dir, tempin, tempout, temperr, envv)
       if (*cmnd)
        {
          extern char **environ;
+         char **save_env = environ;
          int save_system_flags = __system_flags;
 
          /* Request the most powerful version of `system'.  We need
@@ -4406,6 +4835,7 @@ run_msdos_command (argv, working_dir, tempin, tempout, temperr, envv)
          environ = envv;
          result = system (cmnd);
          __system_flags = save_system_flags;
+         environ = save_env;
        }
       else
        result = 0;     /* emulate Unixy shell behavior with empty cmd line */
@@ -4415,7 +4845,7 @@ run_msdos_command (argv, working_dir, tempin, tempout, temperr, envv)
 #endif /* __DJGPP__ > 1 */
 
   result = spawnve (P_WAIT, argv[0], argv, envv);
-  
+
   dup2 (inbak, 0);
   dup2 (outbak, 1);
   dup2 (errbak, 2);
@@ -4434,7 +4864,7 @@ run_msdos_command (argv, working_dir, tempin, tempout, temperr, envv)
      text attribute byte, so we get blinking characters instead of the
      bright background colors.  Restore that.  */
   bright_bg ();
-  
+
  done:
   chdir (oldwd);
   if (msshell)
@@ -4445,6 +4875,7 @@ run_msdos_command (argv, working_dir, tempin, tempout, temperr, envv)
   return result;
 }
 
+void
 croak (badfunc)
      char *badfunc;
 {
@@ -4477,7 +4908,7 @@ gethostname (p, size)
 /* When time zones are set from Ms-Dos too many C-libraries are playing
    tricks with time values.  We solve this by defining our own version
    of `gettimeofday' bypassing GO32.  Our version needs to be initialized
-   once and after each call to `tzset' with TZ changed.  That is 
+   once and after each call to `tzset' with TZ changed.  That is
    accomplished by aliasing tzset to init_gettimeofday. */
 
 static struct tm time_rec;
@@ -4489,7 +4920,7 @@ gettimeofday (struct timeval *tp, struct timezone *tzp)
     {
       struct time t;
       struct tm tm;
-      
+
       gettime (&t);
       if (t.ti_hour < time_rec.tm_hour) /* midnight wrap */
        {
@@ -4499,14 +4930,14 @@ gettimeofday (struct timeval *tp, struct timezone *tzp)
          time_rec.tm_mon = d.da_mon - 1;
          time_rec.tm_mday = d.da_day;
        }
-      
+
       time_rec.tm_hour = t.ti_hour;
       time_rec.tm_min = t.ti_min;
       time_rec.tm_sec = t.ti_sec;
 
       tm = time_rec;
       tm.tm_gmtoff = dos_timezone_offset;
-      
+
       tp->tv_sec = mktime (&tm);       /* may modify tm */
       tp->tv_usec = t.ti_hund * (1000000 / 100);
     }
@@ -4527,7 +4958,7 @@ int kill (x, y) int x, y; { return -1; }
 nice (p) int p; {}
 void volatile pause () {}
 sigsetmask (x) int x; { return 0; }
-sigblock (mask) int mask; { return 0; } 
+sigblock (mask) int mask; { return 0; }
 #endif
 
 void request_sigio (void) {}
@@ -4536,6 +4967,7 @@ setpriority (x,y,z) int x,y,z; { return 0; }
 void unrequest_sigio (void) {}
 
 #if __DJGPP__ > 1
+#if __DJGPP_MINOR__ < 2
 
 #ifdef POSIX_SIGNALS
 
@@ -4557,7 +4989,7 @@ static sigset_t pending_signals;
 typedef void (*sighandler_t)(int);
 static sighandler_t prev_handlers[320];
 
-/* A signal handler which just records that a signal occured
+/* A signal handler which just records that a signal occurred
    (it will be raised later, if and when the signal is unblocked).  */
 static void
 sig_suspender (signo)
@@ -4639,9 +5071,10 @@ sigprocmask (how, new_set, old_set)
 #else /* not POSIX_SIGNALS */
 
 sigsetmask (x) int x; { return 0; }
-sigblock (mask) int mask; { return 0; } 
+sigblock (mask) int mask; { return 0; }
 
 #endif /* not POSIX_SIGNALS */
+#endif /* not __DJGPP_MINOR__ < 2 */
 #endif /* __DJGPP__ > 1 */
 
 #ifndef HAVE_SELECT
@@ -4676,7 +5109,7 @@ dos_yield_time_slice (void)
 
 /* Only event queue is checked.  */
 /* We don't have to call timer_check here
-   because wait_reading_process_input takes care of that.  */
+   because wait_reading_process_output takes care of that.  */
 int
 sys_select (nfds, rfds, wfds, efds, timeout)
      int nfds;
@@ -4699,7 +5132,7 @@ sys_select (nfds, rfds, wfds, efds, timeout)
 
   if (nfds != 1)
     abort ();
-  
+
   /* If we are looking only for the terminal, with no timeout,
      just read it and wait -- that's more efficient.  */
   if (!timeout)
@@ -4735,7 +5168,7 @@ sys_select (nfds, rfds, wfds, efds, timeout)
          dos_yield_time_slice ();
        }
     }
-  
+
   FD_SET (0, rfds);
   return 1;
 }
@@ -4767,7 +5200,7 @@ sys_chdir (path)
       tmp += 2;        /* strip drive: KFS 1995-07-06 */
       len -= 2;
     }
-  
+
   if (len > 1 && (tmp[len - 1] == '/'))
     {
       char *tmp1 = (char *) alloca (len + 1);
@@ -4808,7 +5241,7 @@ dos_abort (file, line)
 {
   char buffer1[200], buffer2[400];
   int i, j;
-  
+
   sprintf (buffer1, "<EMACS FATAL ERROR IN %s LINE %d>", file, line);
   for (i = j = 0; buffer1[i]; i++) {
     buffer2[j++] = buffer1[i];
@@ -4842,11 +5275,6 @@ abort ()
 
 /* The following variables are required so that cus-start.el won't
    complain about unbound variables.  */
-#ifndef HAVE_X_WINDOWS
-/* Search path for bitmap files (xfns.c).  */
-Lisp_Object Vx_bitmap_file_path;
-int x_stretch_cursor_p;
-#endif
 #ifndef subprocesses
 /* Nonzero means delete a process right away if it exits (process.c).  */
 static int delete_exited_processes;
@@ -4856,38 +5284,23 @@ syms_of_msdos ()
 {
   recent_doskeys = Fmake_vector (make_number (NUM_RECENT_DOSKEYS), Qnil);
   staticpro (&recent_doskeys);
+
 #ifndef HAVE_X_WINDOWS
-  staticpro (&help_echo);
-  help_echo = Qnil;
-  staticpro (&previous_help_echo);
-  previous_help_echo = Qnil;
-
-  DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
-    "List of directories to search for bitmap files for X.");
-  Vx_bitmap_file_path = decode_env_path ((char *) 0, ".");
-
-  DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
-    "*Non-nil means draw block cursor as wide as the glyph under it.\n\
-For example, if a block cursor is over a tab, it will be drawn as\n\
-wide as that tab on the display.  (No effect on MS-DOS.)");
-  x_stretch_cursor_p = 0;
-
-  /* The following three are from xfns.c:  */
-  Qbackground_color = intern ("background-color");
-  staticpro (&Qbackground_color);
-  Qforeground_color = intern ("foreground-color");
-  staticpro (&Qforeground_color);
+
+  /* The following two are from xfns.c:  */
+  Qreverse = intern ("reverse");
+  staticpro (&Qreverse);
 
   DEFVAR_LISP ("dos-unsupported-char-glyph", &Vdos_unsupported_char_glyph,
-   "*Glyph to display instead of chars not supported by current codepage.\n\
+              doc: /* *Glyph to display instead of chars not supported by current codepage.
+This variable is used only by MSDOS terminals.  */);
+  Vdos_unsupported_char_glyph = make_number ('\177');
 
-This variable is used only by MSDOS terminals.");
-    Vdos_unsupported_char_glyph = '\177';
 #endif
 #ifndef subprocesses
   DEFVAR_BOOL ("delete-exited-processes", &delete_exited_processes,
-    "*Non-nil means delete processes immediately when they exit.\n\
-nil means don't delete them until `list-processes' is run.");
+              doc: /* *Non-nil means delete processes immediately when they exit.
+A value of nil means don't delete them until `list-processes' is run.  */);
   delete_exited_processes = 0;
 #endif
 
@@ -4895,7 +5308,10 @@ nil means don't delete them until `list-processes' is run.");
   defsubr (&Smsdos_long_file_names);
   defsubr (&Smsdos_downcase_filename);
   defsubr (&Smsdos_remember_default_colors);
+  defsubr (&Smsdos_set_mouse_buttons);
 }
 
 #endif /* MSDOS */
+
+/* arch-tag: db404e92-52a5-475f-9eb2-1cb78dd05f30
+   (do not change this comment) */