Merge from emacs-24; up to 2013-01-03T02:37:57Z!rgm@gnu.org
[bpt/emacs.git] / src / term.c
index d5c5f6e..f86d71a 100644 (file)
@@ -51,6 +51,10 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 static int been_here = -1;
 #endif
 
 static int been_here = -1;
 #endif
 
+#ifdef USE_X_TOOLKIT
+#include "../lwlib/lwlib.h"
+#endif
+
 #include "cm.h"
 #ifdef HAVE_X_WINDOWS
 #include "xterm.h"
 #include "cm.h"
 #ifdef HAVE_X_WINDOWS
 #include "xterm.h"
@@ -216,6 +220,7 @@ tty_update_end (struct frame *f)
     tty_show_cursor (tty);
   tty_turn_off_insert (tty);
   tty_background_highlight (tty);
     tty_show_cursor (tty);
   tty_turn_off_insert (tty);
   tty_background_highlight (tty);
+  fflush (tty->output);
 }
 
 /* The implementation of set_terminal_window for termcap frames. */
 }
 
 /* The implementation of set_terminal_window for termcap frames. */
@@ -495,8 +500,12 @@ static ptrdiff_t encode_terminal_dst_size;
    Set CODING->produced to the byte-length of the resulting byte
    sequence, and return a pointer to that byte sequence.  */
 
    Set CODING->produced to the byte-length of the resulting byte
    sequence, and return a pointer to that byte sequence.  */
 
+#ifndef WINDOWSNT
+static
+#endif
 unsigned char *
 unsigned char *
-encode_terminal_code (struct glyph *src, int src_len, struct coding_system *coding)
+encode_terminal_code (struct glyph *src, int src_len,
+                     struct coding_system *coding)
 {
   struct glyph *src_end = src + src_len;
   unsigned char *buf;
 {
   struct glyph *src_end = src + src_len;
   unsigned char *buf;
@@ -1883,55 +1892,18 @@ static void
 turn_on_face (struct frame *f, int face_id)
 {
   struct face *face = FACE_FROM_ID (f, face_id);
 turn_on_face (struct frame *f, int face_id)
 {
   struct face *face = FACE_FROM_ID (f, face_id);
-  long fg = face->foreground;
-  long bg = face->background;
+  unsigned long fg = face->foreground;
+  unsigned long bg = face->background;
   struct tty_display_info *tty = FRAME_TTY (f);
 
   struct tty_display_info *tty = FRAME_TTY (f);
 
-  /* Do this first because TS_end_standout_mode may be the same
+  /* Use reverse video if the face specifies that.
+     Do this first because TS_end_standout_mode may be the same
      as TS_exit_attribute_mode, which turns all appearances off. */
      as TS_exit_attribute_mode, which turns all appearances off. */
-  if (MAY_USE_WITH_COLORS_P (tty, NC_REVERSE))
-    {
-      if (tty->TN_max_colors > 0)
-       {
-         if (fg >= 0 && bg >= 0)
-           {
-             /* If the terminal supports colors, we can set them
-                below without using reverse video.  The face's fg
-                and bg colors are set as they should appear on
-                the screen, i.e. they take the inverse-video'ness
-                of the face already into account.  */
-           }
-         else if (inverse_video)
-           {
-             if (fg == FACE_TTY_DEFAULT_FG_COLOR
-                 || bg == FACE_TTY_DEFAULT_BG_COLOR)
-               tty_toggle_highlight (tty);
-           }
-         else
-           {
-             if (fg == FACE_TTY_DEFAULT_BG_COLOR
-                 || bg == FACE_TTY_DEFAULT_FG_COLOR)
-               tty_toggle_highlight (tty);
-           }
-       }
-      else
-       {
-         /* If we can't display colors, use reverse video
-            if the face specifies that.  */
-         if (inverse_video)
-           {
-             if (fg == FACE_TTY_DEFAULT_FG_COLOR
-                 || bg == FACE_TTY_DEFAULT_BG_COLOR)
-               tty_toggle_highlight (tty);
-           }
-         else
-           {
-             if (fg == FACE_TTY_DEFAULT_BG_COLOR
-                 || bg == FACE_TTY_DEFAULT_FG_COLOR)
-               tty_toggle_highlight (tty);
-           }
-       }
-    }
+  if (MAY_USE_WITH_COLORS_P (tty, NC_REVERSE)
+      && (inverse_video
+         ? fg == FACE_TTY_DEFAULT_FG_COLOR || bg == FACE_TTY_DEFAULT_BG_COLOR
+         : fg == FACE_TTY_DEFAULT_BG_COLOR || bg == FACE_TTY_DEFAULT_FG_COLOR))
+    tty_toggle_highlight (tty);
 
   if (face->tty_bold_p && MAY_USE_WITH_COLORS_P (tty, NC_BOLD))
     OUTPUT1_IF (tty, tty->TS_enter_bold_mode);
 
   if (face->tty_bold_p && MAY_USE_WITH_COLORS_P (tty, NC_BOLD))
     OUTPUT1_IF (tty, tty->TS_enter_bold_mode);
@@ -1956,7 +1928,7 @@ turn_on_face (struct frame *f, int face_id)
       char *p;
 
       ts = tty->standout_mode ? tty->TS_set_background : tty->TS_set_foreground;
       char *p;
 
       ts = tty->standout_mode ? tty->TS_set_background : tty->TS_set_foreground;
-      if (fg >= 0 && ts)
+      if (face_tty_specified_color (fg) && ts)
        {
           p = tparam (ts, NULL, 0, fg, 0, 0, 0);
          OUTPUT (tty, p);
        {
           p = tparam (ts, NULL, 0, fg, 0, 0, 0);
          OUTPUT (tty, p);
@@ -1964,7 +1936,7 @@ turn_on_face (struct frame *f, int face_id)
        }
 
       ts = tty->standout_mode ? tty->TS_set_foreground : tty->TS_set_background;
        }
 
       ts = tty->standout_mode ? tty->TS_set_foreground : tty->TS_set_background;
-      if (bg >= 0 && ts)
+      if (face_tty_specified_color (bg) && ts)
        {
           p = tparam (ts, NULL, 0, bg, 0, 0, 0);
          OUTPUT (tty, p);
        {
           p = tparam (ts, NULL, 0, bg, 0, 0, 0);
          OUTPUT (tty, p);
@@ -2018,12 +1990,10 @@ turn_off_face (struct frame *f, int face_id)
 
 
 /* Return true if the terminal on frame F supports all of the
 
 
 /* Return true if the terminal on frame F supports all of the
-   capabilities in CAPS simultaneously, with foreground and background
-   colors FG and BG.  */
+   capabilities in CAPS simultaneously.  */
 
 bool
 
 bool
-tty_capable_p (struct tty_display_info *tty, unsigned int caps,
-              unsigned long fg, unsigned long bg)
+tty_capable_p (struct tty_display_info *tty, unsigned int caps)
 {
 #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit)                                \
   if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit)))        \
 {
 #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit)                                \
   if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit)))        \
@@ -2776,10 +2746,10 @@ DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop, Sgpm_mouse_stop,
    However, unlike on MSDOS, where the menu text is drawn directly to
    the display video memory, on a TTY we use display_string (see
    display_tty_menu_item in xdisp.c) to put the glyphs produced from
    However, unlike on MSDOS, where the menu text is drawn directly to
    the display video memory, on a TTY we use display_string (see
    display_tty_menu_item in xdisp.c) to put the glyphs produced from
-   the menu items directly into the frame's 'desired_matrix' glyph
-   matrix, and then call update_frame_with_menu to deliver the results
-   to the glass.  The previous contents of the screen, in the form of
-   the current_matrix, is stashed away, and used to restore screen
+   the menu items into the frame's 'desired_matrix' glyph matrix, and
+   then call update_frame_with_menu to deliver the results to the
+   glass.  The previous contents of the screen, in the form of the
+   current_matrix, is stashed away, and used to restore screen
    contents when the menu selection changes or when the final
    selection is made and the menu should be popped down.
 
    contents when the menu selection changes or when the final
    selection is made and the menu should be popped down.
 
@@ -2789,6 +2759,8 @@ DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop, Sgpm_mouse_stop,
 #define TTYM_SUCCESS 1
 #define TTYM_NO_SELECT 2
 #define TTYM_IA_SELECT 3
 #define TTYM_SUCCESS 1
 #define TTYM_NO_SELECT 2
 #define TTYM_IA_SELECT 3
+#define TTYM_NEXT 4
+#define TTYM_PREV 5
 
 /* These hold text of the current and the previous menu help messages.  */
 static const char *menu_help_message, *prev_menu_help_message;
 
 /* These hold text of the current and the previous menu help messages.  */
 static const char *menu_help_message, *prev_menu_help_message;
@@ -2808,7 +2780,7 @@ typedef struct tty_menu_struct
   char **text;
   struct tty_menu_struct **submenu;
   int *panenumber; /* Also used as enabled flag.  */
   char **text;
   struct tty_menu_struct **submenu;
   int *panenumber; /* Also used as enabled flag.  */
-  int allocated;
+  ptrdiff_t allocated;
   int panecount;
   int width;
   const char **help_text;
   int panecount;
   int width;
   const char **help_text;
@@ -2819,38 +2791,27 @@ typedef struct tty_menu_struct
 static tty_menu *
 tty_menu_create (void)
 {
 static tty_menu *
 tty_menu_create (void)
 {
-  tty_menu *menu;
-
-  menu = (tty_menu *) xmalloc (sizeof (tty_menu));
-  menu->allocated = menu->count = menu->panecount = menu->width = 0;
-  return menu;
+  return xzalloc (sizeof *tty_menu_create ());
 }
 
 /* Allocate some (more) memory for MENU ensuring that there is room for one
 }
 
 /* Allocate some (more) memory for MENU ensuring that there is room for one
-   for item.  */
+   more item.  */
 
 static void
 tty_menu_make_room (tty_menu *menu)
 {
 
 static void
 tty_menu_make_room (tty_menu *menu)
 {
-  if (menu->allocated == 0)
+  if (menu->allocated == menu->count)
     {
     {
-      int count = menu->allocated = 10;
-      menu->text = (char **) xmalloc (count * sizeof (char *));
-      menu->submenu = (tty_menu **) xmalloc (count * sizeof (tty_menu *));
-      menu->panenumber = (int *) xmalloc (count * sizeof (int));
-      menu->help_text = (const char **) xmalloc (count * sizeof (char *));
-    }
-  else if (menu->allocated == menu->count)
-    {
-      int count = menu->allocated = menu->allocated + 10;
-      menu->text
-       = (char **) xrealloc (menu->text, count * sizeof (char *));
-      menu->submenu
-       = (tty_menu **) xrealloc (menu->submenu, count * sizeof (tty_menu *));
-      menu->panenumber
-       = (int *) xrealloc (menu->panenumber, count * sizeof (int));
-      menu->help_text
-       = (const char **) xrealloc (menu->help_text, count * sizeof (char *));
+      ptrdiff_t allocated = menu->allocated;
+      menu->text = xpalloc (menu->text, &allocated, 1, -1, sizeof *menu->text);
+      menu->text = xrealloc (menu->text, allocated * sizeof *menu->text);
+      menu->submenu = xrealloc (menu->submenu,
+                               allocated * sizeof *menu->submenu);
+      menu->panenumber = xrealloc (menu->panenumber,
+                                  allocated * sizeof *menu->panenumber);
+      menu->help_text = xrealloc (menu->help_text,
+                                 allocated * sizeof *menu->help_text);
+      menu->allocated = allocated;
     }
 }
 
     }
 }
 
@@ -2867,7 +2828,8 @@ tty_menu_search_pane (tty_menu *menu, int pane)
       {
        if (pane == menu->panenumber[i])
          return menu->submenu[i];
       {
        if (pane == menu->panenumber[i])
          return menu->submenu[i];
-       if ((try = tty_menu_search_pane (menu->submenu[i], pane)))
+       try = tty_menu_search_pane (menu->submenu[i], pane);
+       if (try)
          return try;
       }
   return (tty_menu *) 0;
          return try;
       }
   return (tty_menu *) 0;
@@ -2915,30 +2877,35 @@ mouse_get_xy (int *x, int *y)
     }
 }
 
     }
 }
 
-/* Display MENU at (X,Y) using FACES.  */
+/* Display MENU at (X,Y) using FACES, starting with FIRST_ITEM
+   (zero-based).  */
 
 static void
 tty_menu_display (tty_menu *menu, int x, int y, int pn, int *faces,
 
 static void
 tty_menu_display (tty_menu *menu, int x, int y, int pn, int *faces,
-                 int mx, int my, int disp_help)
+                 int mx, int my, int first_item, bool disp_help)
 {
   int i, face, width, enabled, mousehere, row, col;
   struct frame *sf = SELECTED_FRAME ();
   struct tty_display_info *tty = FRAME_TTY (sf);
 {
   int i, face, width, enabled, mousehere, row, col;
   struct frame *sf = SELECTED_FRAME ();
   struct tty_display_info *tty = FRAME_TTY (sf);
+  /* Don't try to display more menu items than the console can display
+     using the available screen lines.  Exclude the echo area line, as
+     it will be overwritten by the help-echo anyway.  */
+  int max_items = min (menu->count - first_item, FRAME_LINES (sf) - 1 - y);
 
   menu_help_message = NULL;
 
   width = menu->width;
   col = cursorX (tty);
   row = cursorY (tty);
 
   menu_help_message = NULL;
 
   width = menu->width;
   col = cursorX (tty);
   row = cursorY (tty);
-  for (i = 0; i < menu->count; i++)
+  for (i = 0; i < max_items; i++)
     {
       int max_width = width + 2; /* +2 for padding blanks on each side */
     {
       int max_width = width + 2; /* +2 for padding blanks on each side */
+      int j = i + first_item;
 
 
-      cursor_to (sf, y + i, x);
-      if (menu->submenu[i])
+      if (menu->submenu[j])
        max_width += 2; /* for displaying " >" after the item */
       enabled
        max_width += 2; /* for displaying " >" after the item */
       enabled
-       = (!menu->submenu[i] && menu->panenumber[i]) || (menu->submenu[i]);
+       = (!menu->submenu[j] && menu->panenumber[j]) || (menu->submenu[j]);
       mousehere = (y + i == my && x <= mx && mx < x + max_width);
       face = faces[enabled + mousehere * 2];
       /* Display the menu help string for the i-th menu item even if
       mousehere = (y + i == my && x <= mx && mx < x + max_width);
       face = faces[enabled + mousehere * 2];
       /* Display the menu help string for the i-th menu item even if
@@ -2946,12 +2913,12 @@ tty_menu_display (tty_menu *menu, int x, int y, int pn, int *faces,
         code does.  */
       if (disp_help && enabled + mousehere * 2 >= 2)
        {
         code does.  */
       if (disp_help && enabled + mousehere * 2 >= 2)
        {
-         menu_help_message = menu->help_text[i];
+         menu_help_message = menu->help_text[j];
          menu_help_paneno = pn - 1;
          menu_help_paneno = pn - 1;
-         menu_help_itemno = i;
+         menu_help_itemno = j;
        }
        }
-      display_tty_menu_item (menu->text[i], max_width, face, x, y + i,
-                            menu->submenu[i] != NULL);
+      display_tty_menu_item (menu->text[j], max_width, face, x, y + i,
+                            menu->submenu[j] != NULL);
     }
   update_frame_with_menu (sf);
   cursor_to (sf, row, col);
     }
   update_frame_with_menu (sf);
   cursor_to (sf, row, col);
@@ -2959,18 +2926,13 @@ tty_menu_display (tty_menu *menu, int x, int y, int pn, int *faces,
 
 /* --------------------------- X Menu emulation ---------------------- */
 
 
 /* --------------------------- X Menu emulation ---------------------- */
 
-/* Report availability of menus.  */
-
-int
-have_menus_p (void) {  return 1; }
-
 /* Create a new pane and place it on the outer-most level.  */
 
 static int
 tty_menu_add_pane (tty_menu *menu, const char *txt)
 {
   int len;
 /* Create a new pane and place it on the outer-most level.  */
 
 static int
 tty_menu_add_pane (tty_menu *menu, const char *txt)
 {
   int len;
-  const char *p;
+  const unsigned char *p;
 
   tty_menu_make_room (menu);
   menu->submenu[menu->count] = tty_menu_create ();
 
   tty_menu_make_room (menu);
   menu->submenu[menu->count] = tty_menu_create ();
@@ -2980,7 +2942,7 @@ tty_menu_add_pane (tty_menu *menu, const char *txt)
   menu->count++;
 
   /* Update the menu width, if necessary.  */
   menu->count++;
 
   /* Update the menu width, if necessary.  */
-  for (len = 0, p = txt; *p; )
+  for (len = 0, p = (unsigned char *) txt; *p; )
     {
       int ch_len;
       int ch = STRING_CHAR_AND_LENGTH (p, ch_len);
     {
       int ch_len;
       int ch = STRING_CHAR_AND_LENGTH (p, ch_len);
@@ -2997,16 +2959,19 @@ tty_menu_add_pane (tty_menu *menu, const char *txt)
 
 /* Create a new item in a menu pane.  */
 
 
 /* Create a new item in a menu pane.  */
 
-int
+static bool
 tty_menu_add_selection (tty_menu *menu, int pane,
 tty_menu_add_selection (tty_menu *menu, int pane,
-                       char *txt, int enable, char const *help_text)
+                       char *txt, bool enable, char const *help_text)
 {
   int len;
 {
   int len;
-  char *p;
+  unsigned char *p;
 
   if (pane)
 
   if (pane)
-    if (!(menu = tty_menu_search_pane (menu, pane)))
-      return TTYM_FAILURE;
+    {
+      menu = tty_menu_search_pane (menu, pane);
+      if (! menu)
+       return 0;
+    }
   tty_menu_make_room (menu);
   menu->submenu[menu->count] = (tty_menu *) 0;
   menu->text[menu->count] = txt;
   tty_menu_make_room (menu);
   menu->submenu[menu->count] = (tty_menu *) 0;
   menu->text[menu->count] = txt;
@@ -3015,7 +2980,7 @@ tty_menu_add_selection (tty_menu *menu, int pane,
   menu->count++;
 
   /* Update the menu width, if necessary.  */
   menu->count++;
 
   /* Update the menu width, if necessary.  */
-  for (len = 0, p = txt; *p; )
+  for (len = 0, p = (unsigned char *) txt; *p; )
     {
       int ch_len;
       int ch = STRING_CHAR_AND_LENGTH (p, ch_len);
     {
       int ch_len;
       int ch = STRING_CHAR_AND_LENGTH (p, ch_len);
@@ -3027,12 +2992,12 @@ tty_menu_add_selection (tty_menu *menu, int pane,
   if (len > menu->width)
     menu->width = len;
 
   if (len > menu->width)
     menu->width = len;
 
-  return TTYM_SUCCESS;
+  return 1;
 }
 
 /* Decide where the menu would be placed if requested at (X,Y).  */
 
 }
 
 /* Decide where the menu would be placed if requested at (X,Y).  */
 
-void
+static void
 tty_menu_locate (tty_menu *menu, int x, int y,
                 int *ulx, int *uly, int *width, int *height)
 {
 tty_menu_locate (tty_menu *menu, int x, int y,
                 int *ulx, int *uly, int *width, int *height)
 {
@@ -3054,7 +3019,7 @@ struct tty_menu_state
    enable all its rows.  Value is a glyph matrix holding the contents
    of F's current frame matrix with all its glyph rows enabled.  */
 
    enable all its rows.  Value is a glyph matrix holding the contents
    of F's current frame matrix with all its glyph rows enabled.  */
 
-struct glyph_matrix *
+static struct glyph_matrix *
 save_and_enable_current_matrix (struct frame *f)
 {
   int i;
 save_and_enable_current_matrix (struct frame *f)
 {
   int i;
@@ -3076,22 +3041,6 @@ save_and_enable_current_matrix (struct frame *f)
         screen will not be redrawn anyway.)  */
       to->enabled_p = 1;
       to->hash = from->hash;
         screen will not be redrawn anyway.)  */
       to->enabled_p = 1;
       to->hash = from->hash;
-      if (from->used[LEFT_MARGIN_AREA])
-       {
-         nbytes = from->used[LEFT_MARGIN_AREA] * sizeof (struct glyph);
-         to->glyphs[LEFT_MARGIN_AREA] = (struct glyph *) xmalloc (nbytes);
-         memcpy (to->glyphs[LEFT_MARGIN_AREA],
-                 from->glyphs[LEFT_MARGIN_AREA], nbytes);
-         to->used[LEFT_MARGIN_AREA] = from->used[LEFT_MARGIN_AREA];
-       }
-      if (from->used[RIGHT_MARGIN_AREA])
-       {
-         nbytes = from->used[RIGHT_MARGIN_AREA] * sizeof (struct glyph);
-         to->glyphs[RIGHT_MARGIN_AREA] = (struct glyph *) xmalloc (nbytes);
-         memcpy (to->glyphs[RIGHT_MARGIN_AREA],
-                 from->glyphs[RIGHT_MARGIN_AREA], nbytes);
-         to->used[RIGHT_MARGIN_AREA] = from->used[RIGHT_MARGIN_AREA];
-       }
     }
 
   return saved;
     }
 
   return saved;
@@ -3116,26 +3065,6 @@ restore_desired_matrix (struct frame *f, struct glyph_matrix *saved)
       to->used[TEXT_AREA] = from->used[TEXT_AREA];
       to->enabled_p = from->enabled_p;
       to->hash = from->hash;
       to->used[TEXT_AREA] = from->used[TEXT_AREA];
       to->enabled_p = from->enabled_p;
       to->hash = from->hash;
-      nbytes = from->used[LEFT_MARGIN_AREA] * sizeof (struct glyph);
-      if (nbytes)
-       {
-         eassert (to->glyphs[LEFT_MARGIN_AREA] != from->glyphs[LEFT_MARGIN_AREA]);
-         memcpy (to->glyphs[LEFT_MARGIN_AREA],
-                 from->glyphs[LEFT_MARGIN_AREA], nbytes);
-         to->used[LEFT_MARGIN_AREA] = from->used[LEFT_MARGIN_AREA];
-       }
-      else
-       to->used[LEFT_MARGIN_AREA] = 0;
-      nbytes = from->used[RIGHT_MARGIN_AREA] * sizeof (struct glyph);
-      if (nbytes)
-       {
-         eassert (to->glyphs[RIGHT_MARGIN_AREA] != from->glyphs[RIGHT_MARGIN_AREA]);
-         memcpy (to->glyphs[RIGHT_MARGIN_AREA],
-                 from->glyphs[RIGHT_MARGIN_AREA], nbytes);
-         to->used[RIGHT_MARGIN_AREA] = from->used[RIGHT_MARGIN_AREA];
-       }
-      else
-       to->used[RIGHT_MARGIN_AREA] = 0;
     }
 }
 
     }
 }
 
@@ -3152,10 +3081,6 @@ free_saved_screen (struct glyph_matrix *saved)
       struct glyph_row *from = saved->rows + i;
 
       xfree (from->glyphs[TEXT_AREA]);
       struct glyph_row *from = saved->rows + i;
 
       xfree (from->glyphs[TEXT_AREA]);
-      if (from->used[LEFT_MARGIN_AREA])
-       xfree (from->glyphs[LEFT_MARGIN_AREA]);
-      if (from->used[RIGHT_MARGIN_AREA])
-       xfree (from->glyphs[RIGHT_MARGIN_AREA]);
     }
 
   xfree (saved->rows);
     }
 
   xfree (saved->rows);
@@ -3170,13 +3095,20 @@ screen_update (struct frame *f, struct glyph_matrix *mtx)
   update_frame_with_menu (f);
 }
 
   update_frame_with_menu (f);
 }
 
-/* Read user input and return X and Y coordinates where that input
-   puts us.  We only consider mouse movement and click events and
-   keyboard movement commands; the rest are ignored.
+typedef enum {
+  MI_QUIT_MENU      = -1,
+  MI_CONTINUE       = 0,
+  MI_ITEM_SELECTED  = 1,
+  MI_NEXT_ITEM      = 2,
+  MI_PREV_ITEM      = 3,
+  MI_SCROLL_FORWARD = 4,
+  MI_SCROLL_BACK    = 5
+} mi_result;
 
 
-   Value is -1 if C-g was pressed, 1 if an item was selected, zero
-   otherwise.  */
-static int
+/* Read user input and return X and Y coordinates where that input
+   puts us.  We only consider mouse movement and click events, and
+   keyboard movement commands; the rest are ignored.  */
+static mi_result
 read_menu_input (struct frame *sf, int *x, int *y, int min_y, int max_y,
                 bool *first_time)
 {
 read_menu_input (struct frame *sf, int *x, int *y, int min_y, int max_y,
                 bool *first_time)
 {
@@ -3184,16 +3116,12 @@ read_menu_input (struct frame *sf, int *x, int *y, int min_y, int max_y,
     {
       *first_time = false;
       sf->mouse_moved = 1;
     {
       *first_time = false;
       sf->mouse_moved = 1;
-      return 0;
     }
     }
-
-  while (1)
+  else
     {
     {
-#if 1
-      extern Lisp_Object read_menu_command (void);
       Lisp_Object cmd;
       Lisp_Object cmd;
-      int usable_input = 1;
-      int st = 0;
+      bool usable_input = 1;
+      mi_result st = MI_CONTINUE;
       struct tty_display_info *tty = FRAME_TTY (sf);
       Lisp_Object saved_mouse_tracking = do_mouse_tracking;
 
       struct tty_display_info *tty = FRAME_TTY (sf);
       Lisp_Object saved_mouse_tracking = do_mouse_tracking;
 
@@ -3209,65 +3137,62 @@ read_menu_input (struct frame *sf, int *x, int *y, int min_y, int max_y,
       do_mouse_tracking = saved_mouse_tracking;
 
       if (EQ (cmd, Qt) || EQ (cmd, Qtty_menu_exit))
       do_mouse_tracking = saved_mouse_tracking;
 
       if (EQ (cmd, Qt) || EQ (cmd, Qtty_menu_exit))
-       return -1;
+       return MI_QUIT_MENU;
       if (EQ (cmd, Qtty_menu_mouse_movement))
       if (EQ (cmd, Qtty_menu_mouse_movement))
+       mouse_get_xy (x, y);
+      else if (EQ (cmd, Qtty_menu_next_menu))
        {
        {
-         int mx, my;
-
-         mouse_get_xy (&mx, &my);
-         *x = mx;
-         *y = my;
+         usable_input = 0;
+         st = MI_NEXT_ITEM;
        }
        }
-      else if (EQ (cmd, Qtty_menu_next_menu))
-       *x += 1;
       else if (EQ (cmd, Qtty_menu_prev_menu))
       else if (EQ (cmd, Qtty_menu_prev_menu))
-       *x -= 1;
+       {
+         usable_input = 0;
+         st = MI_PREV_ITEM;
+       }
       else if (EQ (cmd, Qtty_menu_next_item))
        {
          if (*y < max_y)
            *y += 1;
       else if (EQ (cmd, Qtty_menu_next_item))
        {
          if (*y < max_y)
            *y += 1;
+         else
+           st = MI_SCROLL_FORWARD;
        }
       else if (EQ (cmd, Qtty_menu_prev_item))
        {
          if (*y > min_y)
            *y -= 1;
        }
       else if (EQ (cmd, Qtty_menu_prev_item))
        {
          if (*y > min_y)
            *y -= 1;
+         else
+           st = MI_SCROLL_BACK;
        }
       else if (EQ (cmd, Qtty_menu_select))
        }
       else if (EQ (cmd, Qtty_menu_select))
-       st = 1;
+       st = MI_ITEM_SELECTED;
       else if (!EQ (cmd, Qtty_menu_ignore))
        usable_input = 0;
       if (usable_input)
        sf->mouse_moved = 1;
       else if (!EQ (cmd, Qtty_menu_ignore))
        usable_input = 0;
       if (usable_input)
        sf->mouse_moved = 1;
-#else
-      int volatile dx = 0;
-      int volatile dy = 0;
-      int volatile st = 0;
-
-      *x += dx;
-      *y += dy;
-      if (dx != 0 || dy != 0)
-       sf->mouse_moved = 1;
-      Sleep (300);
-#endif
       return st;
     }
       return st;
     }
-  return 0;
+  return MI_CONTINUE;
 }
 
 /* Display menu, wait for user's response, and return that response.  */
 }
 
 /* Display menu, wait for user's response, and return that response.  */
-int
+static int
 tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
                   int x0, int y0, char **txt,
 tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
                   int x0, int y0, char **txt,
-                  void (*help_callback)(char const *, int, int))
+                  void (*help_callback)(char const *, int, int),
+                  bool kbd_navigation)
 {
   struct tty_menu_state *state;
 {
   struct tty_menu_state *state;
-  int statecount, x, y, i, b, leave, result, onepane;
+  int statecount, x, y, i;
+  bool leave, onepane;
+  int result IF_LINT (= 0);
   int title_faces[4];          /* face to display the menu title */
   int faces[4], buffers_num_deleted = 0;
   struct frame *sf = SELECTED_FRAME ();
   struct tty_display_info *tty = FRAME_TTY (sf);
   bool first_time;
   int title_faces[4];          /* face to display the menu title */
   int faces[4], buffers_num_deleted = 0;
   struct frame *sf = SELECTED_FRAME ();
   struct tty_display_info *tty = FRAME_TTY (sf);
   bool first_time;
-  Lisp_Object saved_echo_area_message, selectface;
+  Lisp_Object selectface;
+  int first_item = 0;
 
   /* Don't allow non-positive x0 and y0, lest the menu will wrap
      around the display.  */
 
   /* Don't allow non-positive x0 and y0, lest the menu will wrap
      around the display.  */
@@ -3319,14 +3244,15 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
      want to interpret them as zero-based column and row coordinates,
      and also because we want the first item of the menu, not its
      title, to appear at x0,y0.  */
      want to interpret them as zero-based column and row coordinates,
      and also because we want the first item of the menu, not its
      title, to appear at x0,y0.  */
-  tty_menu_display (menu, x0 - 1, y0 - 1, 1, title_faces, x0 - 1, y0 - 1, 0);
+  tty_menu_display (menu, x0 - 1, y0 - 1, 1, title_faces, x0 - 1, y0 - 1, 0, 0);
 
   /* Turn off the cursor.  Otherwise it shows through the menu
      panes, which is ugly.  */
   tty_hide_cursor (tty);
   if (buffers_num_deleted)
     menu->text[0][7] = ' ';
 
   /* Turn off the cursor.  Otherwise it shows through the menu
      panes, which is ugly.  */
   tty_hide_cursor (tty);
   if (buffers_num_deleted)
     menu->text[0][7] = ' ';
-  if ((onepane = menu->count == 1 && menu->submenu[0]))
+  onepane = menu->count == 1 && menu->submenu[0];
+  if (onepane)
     {
       menu->width = menu->submenu[0]->width;
       state[0].menu = menu->submenu[0];
     {
       menu->width = menu->submenu[0]->width;
       state[0].menu = menu->submenu[0];
@@ -3346,30 +3272,67 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
   leave = 0;
   while (!leave)
     {
   leave = 0;
   while (!leave)
     {
-      int mouse_button_count = 3; /* FIXME */
-      int input_status;
-      int min_y = state[0].y, max_y = min_y + state[0].menu->count - 1;
+      mi_result input_status;
+      int min_y = state[0].y;
+      int max_y = min (min_y + state[0].menu->count, FRAME_LINES (sf) - 1) - 1;
 
       input_status = read_menu_input (sf, &x, &y, min_y, max_y, &first_time);
       if (input_status)
        {
 
       input_status = read_menu_input (sf, &x, &y, min_y, max_y, &first_time);
       if (input_status)
        {
-         if (input_status == -1)
+         leave = 1;
+         switch (input_status)
            {
            {
+           case MI_QUIT_MENU:
              /* Remove the last help-echo, so that it doesn't
                 re-appear after "Quit".  */
              show_help_echo (Qnil, Qnil, Qnil, Qnil);
              result = TTYM_NO_SELECT;
              /* Remove the last help-echo, so that it doesn't
                 re-appear after "Quit".  */
              show_help_echo (Qnil, Qnil, Qnil, Qnil);
              result = TTYM_NO_SELECT;
+             break;
+           case MI_NEXT_ITEM:
+             if (kbd_navigation)
+               result = TTYM_NEXT;
+             else
+               leave = 0;
+             break;
+           case MI_PREV_ITEM:
+             if (kbd_navigation)
+               result = TTYM_PREV;
+             else
+               leave = 0;
+             break;
+           case MI_SCROLL_FORWARD:
+             if (y - min_y == state[0].menu->count - 1 - first_item)
+               {
+                 y = min_y;
+                 first_item = 0;
+               }
+             else
+               first_item++;
+             leave = 0;
+             break;
+           case MI_SCROLL_BACK:
+             if (first_item == 0)
+               {
+                 y = max_y;
+                 first_item = state[0].menu->count - 1 - (y - min_y);
+               }
+             else
+               first_item--;
+             leave = 0;
+             break;
+           default:
+             /* MI_ITEM_SELECTED is handled below, so nothing to do.  */
+             break;
            }
            }
-         leave = 1;
        }
        }
-      if (sf->mouse_moved && input_status != -1)
+      if (sf->mouse_moved && input_status != MI_QUIT_MENU)
        {
          sf->mouse_moved = 0;
          result = TTYM_IA_SELECT;
          for (i = 0; i < statecount; i++)
            if (state[i].x <= x && x < state[i].x + state[i].menu->width + 2)
              {
        {
          sf->mouse_moved = 0;
          result = TTYM_IA_SELECT;
          for (i = 0; i < statecount; i++)
            if (state[i].x <= x && x < state[i].x + state[i].menu->width + 2)
              {
-               int dy = y - state[i].y;
+               int dy = y - state[i].y + first_item;
                if (0 <= dy && dy < state[i].menu->count)
                  {
                    if (!state[i].menu->submenu[dy])
                if (0 <= dy && dy < state[i].menu->count)
                  {
                    if (!state[i].menu->submenu[dy])
@@ -3398,7 +3361,7 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
                                          state[i].x,
                                          state[i].y,
                                          state[i].pane,
                                          state[i].x,
                                          state[i].y,
                                          state[i].pane,
-                                         faces, x, y, 1);
+                                         faces, x, y, first_item, 1);
                        state[statecount].menu = state[i].menu->submenu[dy];
                        state[statecount].pane = state[i].menu->panenumber[dy];
                        state[statecount].screen_behind
                        state[statecount].menu = state[i].menu->submenu[dy];
                        state[statecount].pane = state[i].menu->panenumber[dy];
                        state[statecount].screen_behind
@@ -3414,7 +3377,7 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
                            state[statecount - 1].x,
                            state[statecount - 1].y,
                            state[statecount - 1].pane,
                            state[statecount - 1].x,
                            state[statecount - 1].y,
                            state[statecount - 1].pane,
-                           faces, x, y, 1);
+                           faces, x, y, first_item, 1);
          tty_hide_cursor (tty);
          fflush (tty->output);
        }
          tty_hide_cursor (tty);
          fflush (tty->output);
        }
@@ -3433,12 +3396,11 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
     }
 
   sf->mouse_moved = 0;
     }
 
   sf->mouse_moved = 0;
-  /* FIXME: Since we set the fram's garbaged flag, do we need this
-     call to screen_update?  */
   screen_update (sf, state[0].screen_behind);
   while (statecount--)
     free_saved_screen (state[statecount].screen_behind);
   tty_show_cursor (tty);       /* turn cursor back on */
   screen_update (sf, state[0].screen_behind);
   while (statecount--)
     free_saved_screen (state[statecount].screen_behind);
   tty_show_cursor (tty);       /* turn cursor back on */
+  fflush (tty->output);
 
 /* Clean up any mouse events that are waiting inside Emacs event queue.
      These events are likely to be generated before the menu was even
 
 /* Clean up any mouse events that are waiting inside Emacs event queue.
      These events are likely to be generated before the menu was even
@@ -3448,13 +3410,12 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
   discard_mouse_events ();
   if (!kbd_buffer_events_waiting ())
     clear_input_pending ();
   discard_mouse_events ();
   if (!kbd_buffer_events_waiting ())
     clear_input_pending ();
-  SET_FRAME_GARBAGED (sf);
   return result;
 }
 
 /* Dispose of a menu.  */
 
   return result;
 }
 
 /* Dispose of a menu.  */
 
-void
+static void
 tty_menu_destroy (tty_menu *menu)
 {
   int i;
 tty_menu_destroy (tty_menu *menu)
 {
   int i;
@@ -3484,7 +3445,7 @@ tty_menu_help_callback (char const *help_string, int pane, int item)
   Lisp_Object pane_name;
   Lisp_Object menu_object;
 
   Lisp_Object pane_name;
   Lisp_Object menu_object;
 
-  first_item = XVECTOR (menu_items)->u.contents;
+  first_item = XVECTOR (menu_items)->contents;
   if (EQ (first_item[0], Qt))
     pane_name = first_item[MENU_ITEMS_PANE_NAME];
   else if (EQ (first_item[0], Qquote))
   if (EQ (first_item[0], Qt))
     pane_name = first_item[MENU_ITEMS_PANE_NAME];
   else if (EQ (first_item[0], Qquote))
@@ -3509,24 +3470,103 @@ tty_pop_down_menu (Lisp_Object arg)
   unblock_input ();
 }
 
   unblock_input ();
 }
 
+/* Return the zero-based index of the last menu-bar item on frame F.  */
+static int
+tty_menu_last_menubar_item (struct frame *f)
+{
+  int i = 0;
+
+  eassert (FRAME_TERMCAP_P (f) && FRAME_LIVE_P (f));
+  if (FRAME_TERMCAP_P (f) && FRAME_LIVE_P (f))
+    {
+      Lisp_Object items = FRAME_MENU_BAR_ITEMS (f);
+
+      while (i < ASIZE (items))
+       {
+         Lisp_Object str;
+
+         str = AREF (items, i + 1);
+         if (NILP (str))
+           break;
+         i += 4;
+       }
+      i -= 4;  /* went one too far */
+    }
+  return i;
+}
+
+/* Find in frame F's menu bar the menu item that is next or previous
+   to the item at X/Y, and return that item's position in X/Y.  WHICH
+   says which one--next or previous--item to look for.  X and Y are
+   measured in character cells.  This should only be called on TTY
+   frames.  */
+static void
+tty_menu_new_item_coords (struct frame *f, int which, int *x, int *y)
+{
+  eassert (FRAME_TERMCAP_P (f) && FRAME_LIVE_P (f));
+  if (FRAME_TERMCAP_P (f) && FRAME_LIVE_P (f))
+    {
+      Lisp_Object items = FRAME_MENU_BAR_ITEMS (f);
+      int last_i = tty_menu_last_menubar_item (f);
+      int i, prev_x;
+
+      /* This loop assumes a single menu-bar line, and will fail to
+        find an item if it is not in the first line.  Note that
+        make_lispy_event in keyboard.c makes the same assumption.  */
+      for (i = 0, prev_x = -1; i < ASIZE (items); i += 4)
+       {
+         Lisp_Object pos, str;
+         int ix;
+
+         str = AREF (items, i + 1);
+         pos = AREF (items, i + 3);
+         if (NILP (str))
+           return;
+         ix = XINT (pos);
+         if (ix <= *x
+             /* We use <= so the blank between 2 items on a TTY is
+                considered part of the previous item.  */
+             && *x <= ix + menu_item_width (SDATA (str)))
+           {
+             /* Found current item.  Now compute the X coordinate of
+                the previous or next item.  */
+             if (which == TTYM_NEXT)
+               {
+                 if (i < last_i)
+                   *x = XINT (AREF (items, i + 4 + 3));
+                 else
+                   *x = 0;     /* wrap around to the first item */
+               }
+             else if (prev_x < 0)
+               {
+                 /* Wrap around to the last item.  */
+                 *x = XINT (AREF (items, last_i + 3));
+               }
+             else
+               *x = prev_x;
+             return;
+           }
+         prev_x = ix;
+       }
+    }
+}
+
 Lisp_Object
 Lisp_Object
-tty_menu_show (struct frame *f, int x, int y, int for_click, int keymaps,
-              Lisp_Object title, const char **error_name)
+tty_menu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
+              Lisp_Object title, bool kbd_navigation, const char **error_name)
 {
   tty_menu *menu;
   int pane, selidx, lpane, status;
   Lisp_Object entry, pane_prefix;
   char *datap;
   int ulx, uly, width, height;
 {
   tty_menu *menu;
   int pane, selidx, lpane, status;
   Lisp_Object entry, pane_prefix;
   char *datap;
   int ulx, uly, width, height;
+  int item_x, item_y;
   int dispwidth, dispheight;
   int i, j, lines, maxlines;
   int maxwidth;
   int dispwidth, dispheight;
   int i, j, lines, maxlines;
   int maxwidth;
-  int dummy_int;
-  unsigned int dummy_uint;
-  ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+  ptrdiff_t specpdl_count;
 
 
-  if (! FRAME_TERMCAP_P (f))
-    emacs_abort ();
+  eassert (FRAME_TERMCAP_P (f));
 
   *error_name = 0;
   if (menu_items_n_panes == 0)
 
   *error_name = 0;
   if (menu_items_n_panes == 0)
@@ -3548,11 +3588,11 @@ tty_menu_show (struct frame *f, int x, int y, int for_click, int keymaps,
 
   /* Don't GC while we prepare and show the menu, because we give the
      menu functions pointers to the contents of strings.  */
 
   /* Don't GC while we prepare and show the menu, because we give the
      menu functions pointers to the contents of strings.  */
-  inhibit_garbage_collection ();
+  specpdl_count = inhibit_garbage_collection ();
 
   /* Adjust coordinates to be root-window-relative.  */
 
   /* Adjust coordinates to be root-window-relative.  */
-  x += f->left_pos;
-  y += f->top_pos;
+  item_x = x += f->left_pos;
+  item_y = y += f->top_pos;
 
   /* Create all the necessary panes and their items.  */
   maxwidth = maxlines = lines = i = 0;
 
   /* Create all the necessary panes and their items.  */
   maxwidth = maxlines = lines = i = 0;
@@ -3579,7 +3619,8 @@ tty_menu_show (struct frame *f, int x, int y, int for_click, int keymaps,
            {
              tty_menu_destroy (menu);
              *error_name = "Can't create pane";
            {
              tty_menu_destroy (menu);
              *error_name = "Can't create pane";
-             return Qnil;
+             entry = Qnil;
+             goto tty_menu_end;
            }
          i += MENU_ITEMS_PANE_LENGTH;
 
            }
          i += MENU_ITEMS_PANE_LENGTH;
 
@@ -3635,13 +3676,13 @@ tty_menu_show (struct frame *f, int x, int y, int for_click, int keymaps,
            item_data = SSDATA (item_name);
 
          if (lpane == TTYM_FAILURE
            item_data = SSDATA (item_name);
 
          if (lpane == TTYM_FAILURE
-             || (tty_menu_add_selection (menu, lpane, item_data,
-                                         !NILP (enable), help_string)
-                 == TTYM_FAILURE))
+             || (! tty_menu_add_selection (menu, lpane, item_data,
+                                           !NILP (enable), help_string)))
            {
              tty_menu_destroy (menu);
              *error_name = "Can't add selection to menu";
            {
              tty_menu_destroy (menu);
              *error_name = "Can't add selection to menu";
-             return Qnil;
+             entry = Qnil;
+             goto tty_menu_end;
            }
          i += MENU_ITEMS_ITEM_LENGTH;
           lines++;
            }
          i += MENU_ITEMS_ITEM_LENGTH;
           lines++;
@@ -3658,12 +3699,12 @@ tty_menu_show (struct frame *f, int x, int y, int for_click, int keymaps,
   x = max (x, 1);
   y = max (y, 1);
   tty_menu_locate (menu, x, y, &ulx, &uly, &width, &height);
   x = max (x, 1);
   y = max (y, 1);
   tty_menu_locate (menu, x, y, &ulx, &uly, &width, &height);
-  if (ulx+width > dispwidth)
+  if (ulx + width > dispwidth)
     {
       x -= (ulx + width) - dispwidth;
       ulx = dispwidth - width;
     }
     {
       x -= (ulx + width) - dispwidth;
       ulx = dispwidth - width;
     }
-  if (uly+height > dispheight)
+  if (uly + height > dispheight)
     {
       y -= (uly + height) - dispheight;
       uly = dispheight - height;
     {
       y -= (uly + height) - dispheight;
       uly = dispheight - height;
@@ -3710,7 +3751,7 @@ tty_menu_show (struct frame *f, int x, int y, int for_click, int keymaps,
   specbind (Qoverriding_terminal_local_map,
            Fsymbol_value (Qtty_menu_navigation_map));
   status = tty_menu_activate (menu, &pane, &selidx, x, y, &datap,
   specbind (Qoverriding_terminal_local_map,
            Fsymbol_value (Qtty_menu_navigation_map));
   status = tty_menu_activate (menu, &pane, &selidx, x, y, &datap,
-                             tty_menu_help_callback);
+                             tty_menu_help_callback, kbd_navigation);
   entry = pane_prefix = Qnil;
 
   switch (status)
   entry = pane_prefix = Qnil;
 
   switch (status)
@@ -3751,6 +3792,12 @@ tty_menu_show (struct frame *f, int x, int y, int for_click, int keymaps,
        }
       break;
 
        }
       break;
 
+    case TTYM_NEXT:
+    case TTYM_PREV:
+      tty_menu_new_item_coords (f, status, &item_x, &item_y);
+      entry = Fcons (make_number (item_x), make_number (item_y));
+      break;
+
     case TTYM_FAILURE:
       *error_name = "Can't activate menu";
     case TTYM_IA_SELECT:
     case TTYM_FAILURE:
       *error_name = "Can't activate menu";
     case TTYM_IA_SELECT:
@@ -3763,8 +3810,9 @@ tty_menu_show (struct frame *f, int x, int y, int for_click, int keymaps,
       break;
     }
 
       break;
     }
 
-  unbind_to (specpdl_count, Qnil);
+ tty_menu_end:
 
 
+  unbind_to (specpdl_count, Qnil);
   return entry;
 }
 
   return entry;
 }
 
@@ -4157,9 +4205,9 @@ use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
   /* Since we make MagicWrap terminals look like AutoWrap, we need to have
      the former flag imply the latter.  */
   AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
   /* Since we make MagicWrap terminals look like AutoWrap, we need to have
      the former flag imply the latter.  */
   AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
-  terminal->memory_below_frame = tgetflag ("db");
+  tty->memory_below_frame = tgetflag ("db");
   tty->TF_hazeltine = tgetflag ("hz");
   tty->TF_hazeltine = tgetflag ("hz");
-  terminal->must_write_spaces = tgetflag ("in");
+  tty->must_write_spaces = tgetflag ("in");
   tty->meta_key = tgetflag ("km") || tgetflag ("MT");
   tty->TF_insmode_motion = tgetflag ("mi");
   tty->TF_standout_motion = tgetflag ("ms");
   tty->meta_key = tgetflag ("km") || tgetflag ("MT");
   tty->TF_insmode_motion = tgetflag ("mi");
   tty->TF_standout_motion = tgetflag ("ms");
@@ -4179,7 +4227,7 @@ use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
     tty->specified_window = height;
 
     FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
     tty->specified_window = height;
 
     FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
-    terminal->char_ins_del_ok = 1;
+    tty->char_ins_del_ok = 1;
     baud_rate = 19200;
   }
 #else  /* MSDOS */
     baud_rate = 19200;
   }
 #else  /* MSDOS */
@@ -4192,7 +4240,7 @@ use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
     get_tty_size (fileno (tty->input), &width, &height);
     FrameCols (tty) = width;
     FrameRows (tty) = height;
     get_tty_size (fileno (tty->input), &width, &height);
     FrameCols (tty) = width;
     FrameRows (tty) = height;
-    terminal->char_ins_del_ok = 0;
+    tty->char_ins_del_ok = 0;
     init_baud_rate (fileno (tty->input));
   }
 #endif /* MSDOS */
     init_baud_rate (fileno (tty->input));
   }
 #endif /* MSDOS */
@@ -4211,12 +4259,12 @@ use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
   tty->delete_in_insert_mode = 1;
 
   UseTabs (tty) = 0;
   tty->delete_in_insert_mode = 1;
 
   UseTabs (tty) = 0;
-  terminal->scroll_region_ok = 0;
+  tty->scroll_region_ok = 0;
 
   /* Seems to insert lines when it's not supposed to, messing up the
      display.  In doing a trace, it didn't seem to be called much, so I
      don't think we're losing anything by turning it off.  */
 
   /* Seems to insert lines when it's not supposed to, messing up the
      display.  In doing a trace, it didn't seem to be called much, so I
      don't think we're losing anything by turning it off.  */
-  terminal->line_ins_del_ok = 0;
+  tty->line_ins_del_ok = 0;
 
   tty->TN_max_colors = 16;  /* Must be non-zero for tty-display-color-p.  */
 #endif /* DOS_NT */
 
   tty->TN_max_colors = 16;  /* Must be non-zero for tty-display-color-p.  */
 #endif /* DOS_NT */
@@ -4226,11 +4274,7 @@ use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
   tty->mouse_highlight.mouse_face_window = Qnil;
 #endif
 
   tty->mouse_highlight.mouse_face_window = Qnil;
 #endif
 
-  terminal->kboard = xmalloc (sizeof *terminal->kboard);
-  init_kboard (terminal->kboard);
-  kset_window_system (terminal->kboard, Qnil);
-  terminal->kboard->next_kboard = all_kboards;
-  all_kboards = terminal->kboard;
+  terminal->kboard = allocate_kboard (Qnil);
   terminal->kboard->reference_count++;
   /* Don't let the initial kboard remain current longer than necessary.
      That would cause problems if a file loaded on startup tries to
   terminal->kboard->reference_count++;
   /* Don't let the initial kboard remain current longer than necessary.
      That would cause problems if a file loaded on startup tries to
@@ -4351,23 +4395,21 @@ use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
 
   UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8;
 
 
   UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8;
 
-  terminal->scroll_region_ok
+  tty->scroll_region_ok
     = (tty->Wcm->cm_abs
        && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
 
     = (tty->Wcm->cm_abs
        && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
 
-  terminal->line_ins_del_ok
+  tty->line_ins_del_ok
     = (((tty->TS_ins_line || tty->TS_ins_multi_lines)
         && (tty->TS_del_line || tty->TS_del_multi_lines))
     = (((tty->TS_ins_line || tty->TS_ins_multi_lines)
         && (tty->TS_del_line || tty->TS_del_multi_lines))
-       || (terminal->scroll_region_ok
+       || (tty->scroll_region_ok
            && tty->TS_fwd_scroll && tty->TS_rev_scroll));
 
            && tty->TS_fwd_scroll && tty->TS_rev_scroll));
 
-  terminal->char_ins_del_ok
+  tty->char_ins_del_ok
     = ((tty->TS_ins_char || tty->TS_insert_mode
         || tty->TS_pad_inserted_char || tty->TS_ins_multi_chars)
        && (tty->TS_del_char || tty->TS_del_multi_chars));
 
     = ((tty->TS_ins_char || tty->TS_insert_mode
         || tty->TS_pad_inserted_char || tty->TS_ins_multi_chars)
        && (tty->TS_del_char || tty->TS_del_multi_chars));
 
-  terminal->fast_clear_end_of_line = tty->TS_clr_line != 0;
-
   init_baud_rate (fileno (tty->input));
 
 #endif /* not DOS_NT */
   init_baud_rate (fileno (tty->input));
 
 #endif /* not DOS_NT */