Removed %T in mode-line-format. Trivial documentation changes.
[bpt/emacs.git] / src / term.c
index 53171e9..65b6c15 100644 (file)
@@ -29,7 +29,6 @@ Boston, MA 02111-1307, USA.  */
 #include <sys/file.h>
 
 #include "lisp.h"
-#include "systty.h" /* For emacs_tty in termchar.h */
 #include "termchar.h"
 #include "termopts.h"
 #include "charset.h"
@@ -69,12 +68,13 @@ extern int tgetnum P_ ((char *id));
 
 static void turn_on_face P_ ((struct frame *, int face_id));
 static void turn_off_face P_ ((struct frame *, int face_id));
-static void tty_show_cursor P_ ((struct tty_output *));
-static void tty_hide_cursor P_ ((struct tty_output *));
-
-void delete_tty P_ ((struct tty_output *));
-static void delete_tty_1 P_ ((struct tty_output *));
+static void tty_show_cursor P_ ((struct tty_display_info *));
+static void tty_hide_cursor P_ ((struct tty_display_info *));
 
+void delete_initial_display P_ ((struct display *));
+void delete_tty P_ ((struct display *));
+void create_tty_output P_ ((struct frame *));
+void delete_tty_output P_ ((struct frame *));
 
 #define OUTPUT(tty, a)                                          \
   emacs_tputs ((tty), a,                                        \
@@ -100,143 +100,26 @@ static void delete_tty_1 P_ ((struct tty_output *));
 
 Lisp_Object Vring_bell_function;
 
-/* Terminal characteristics that higher levels want to look at. */
+/* Functions to call after a tty was deleted. */
+Lisp_Object Vdelete_tty_after_functions;
+
+/* Chain of all displays currently in use. */
+struct display *display_list;
 
-struct tty_output *tty_list;
+/* The initial display device, created by initial_term_init. */
+struct display *initial_display;
+
+/* Chain of all tty device parameters. */
+struct tty_display_info *tty_list;
 
 /* Nonzero means no need to redraw the entire frame on resuming a
    suspended Emacs.  This is useful on terminals with multiple
    pages, where one page is used for Emacs and another for all
    else. */
 int no_redraw_on_reenter;
-  
-/* Hook functions that you can set to snap out the functions in this file.
-   These are all extern'd in termhooks.h  */
-
-void (*cursor_to_hook) P_ ((int, int));
-void (*raw_cursor_to_hook) P_ ((int, int));
-void (*clear_to_end_hook) P_ ((void));
-void (*clear_frame_hook) P_ ((void));
-void (*clear_end_of_line_hook) P_ ((int));
-
-void (*ins_del_lines_hook) P_ ((int, int));
-
-void (*delete_glyphs_hook) P_ ((int));
-
-void (*ring_bell_hook) P_ ((void));
-
-void (*reset_terminal_modes_hook) P_ ((void));
-void (*set_terminal_modes_hook) P_ ((void));
-void (*update_begin_hook) P_ ((struct frame *));
-void (*update_end_hook) P_ ((struct frame *));
-void (*set_terminal_window_hook) P_ ((int));
-void (*insert_glyphs_hook) P_ ((struct glyph *, int));
-void (*write_glyphs_hook) P_ ((struct glyph *, int));
-void (*delete_glyphs_hook) P_ ((int));
-
-int (*read_socket_hook) P_ ((struct input_event *, int, int));
-
-void (*frame_up_to_date_hook) P_ ((struct frame *));
-
-/* Return the current position of the mouse.
-
-   Set *f to the frame the mouse is in, or zero if the mouse is in no
-   Emacs frame.  If it is set to zero, all the other arguments are
-   garbage.
-
-   If the motion started in a scroll bar, set *bar_window to the
-   scroll bar's window, *part to the part the mouse is currently over,
-   *x to the position of the mouse along the scroll bar, and *y to the
-   overall length of the scroll bar.
-
-   Otherwise, set *bar_window to Qnil, and *x and *y to the column and
-   row of the character cell the mouse is over.
-
-   Set *time to the time the mouse was at the returned position.
-
-   This should clear mouse_moved until the next motion
-   event arrives.  */
-
-void (*mouse_position_hook) P_ ((FRAME_PTR *f, int insist,
-                                Lisp_Object *bar_window,
-                                enum scroll_bar_part *part,
-                                Lisp_Object *x,
-                                Lisp_Object *y,
-                                unsigned long *time));
-
-/* When reading from a minibuffer in a different frame, Emacs wants
-   to shift the highlight from the selected frame to the mini-buffer's
-   frame; under X, this means it lies about where the focus is.
-   This hook tells the window system code to re-decide where to put
-   the highlight.  */
-
-void (*frame_rehighlight_hook) P_ ((FRAME_PTR f));
-
-/* If we're displaying frames using a window system that can stack
-   frames on top of each other, this hook allows you to bring a frame
-   to the front, or bury it behind all the other windows.  If this
-   hook is zero, that means the device we're displaying on doesn't
-   support overlapping frames, so there's no need to raise or lower
-   anything.
-
-   If RAISE is non-zero, F is brought to the front, before all other
-   windows.  If RAISE is zero, F is sent to the back, behind all other
-   windows.  */
-
-void (*frame_raise_lower_hook) P_ ((FRAME_PTR f, int raise));
-
-/* Set the vertical scroll bar for WINDOW to have its upper left corner
-   at (TOP, LEFT), and be LENGTH rows high.  Set its handle to
-   indicate that we are displaying PORTION characters out of a total
-   of WHOLE characters, starting at POSITION.  If WINDOW doesn't yet
-   have a scroll bar, create one for it.  */
-
-void (*set_vertical_scroll_bar_hook)
-     P_ ((struct window *window,
-         int portion, int whole, int position));
-
-
-/* The following three hooks are used when we're doing a thorough
-   redisplay of the frame.  We don't explicitly know which scroll bars
-   are going to be deleted, because keeping track of when windows go
-   away is a real pain - can you say set-window-configuration?
-   Instead, we just assert at the beginning of redisplay that *all*
-   scroll bars are to be removed, and then save scroll bars from the
-   fiery pit when we actually redisplay their window.  */
-
-/* Arrange for all scroll bars on FRAME to be removed at the next call
-   to `*judge_scroll_bars_hook'.  A scroll bar may be spared if
-   `*redeem_scroll_bar_hook' is applied to its window before the judgment.
-
-   This should be applied to each frame each time its window tree is
-   redisplayed, even if it is not displaying scroll bars at the moment;
-   if the HAS_SCROLL_BARS flag has just been turned off, only calling
-   this and the judge_scroll_bars_hook will get rid of them.
-
-   If non-zero, this hook should be safe to apply to any frame,
-   whether or not it can support scroll bars, and whether or not it is
-   currently displaying them.  */
-
-void (*condemn_scroll_bars_hook) P_ ((FRAME_PTR frame));
-
-/* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
-   Note that it's okay to redeem a scroll bar that is not condemned.  */
 
-void (*redeem_scroll_bar_hook) P_ ((struct window *window));
+Lisp_Object Qframe_tty_name, Qframe_tty_type;
 
-/* Remove all scroll bars on FRAME that haven't been saved since the
-   last call to `*condemn_scroll_bars_hook'.
-
-   This should be applied to each frame after each time its window
-   tree is redisplayed, even if it is not displaying scroll bars at the
-   moment; if the HAS_SCROLL_BARS flag has just been turned off, only
-   calling this and condemn_scroll_bars_hook will get rid of them.
-
-   If non-zero, this hook should be safe to apply to any frame,
-   whether or not it can support scroll bars, and whether or not it is
-   currently displaying them.  */
-
-void (*judge_scroll_bars_hook) P_ ((FRAME_PTR FRAME));
 
 
 /* Meaning of bits in no_color_video.  Each bit set means that the
@@ -293,7 +176,7 @@ extern char *tgetstr ();
 void
 ring_bell ()
 {
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
+  struct frame *f = XFRAME (selected_frame);
 
   if (!NILP (Vring_bell_function))
     {
@@ -314,34 +197,43 @@ ring_bell ()
 
       Vring_bell_function = function;
     }
-  else if (!FRAME_TERMCAP_P (f))
-    (*ring_bell_hook) ();
-  else {
-    struct tty_output *tty = FRAME_TTY (f);
-    OUTPUT (tty, tty->TS_visible_bell && visible_bell ? tty->TS_visible_bell : tty->TS_bell);
-  }
+  else if (FRAME_DISPLAY (f)->ring_bell_hook)
+    (*FRAME_DISPLAY (f)->ring_bell_hook) ();
+}
+
+/* Ring the bell on a tty. */
+
+void
+tty_ring_bell ()
+{
+  struct frame *f = XFRAME (selected_frame);
+  struct tty_display_info *tty = FRAME_TTY (f);
+
+  OUTPUT (tty, (tty->TS_visible_bell && visible_bell
+                ? tty->TS_visible_bell
+                : tty->TS_bell));
 }
 
-void tty_set_terminal_modes (struct tty_output *tty)
+/* Set up termcap modes for Emacs. */
+
+void
+tty_set_terminal_modes (struct display *display)
 {
+  struct tty_display_info *tty = display->display_info.tty;
+  
   OUTPUT_IF (tty, tty->TS_termcap_modes);
   OUTPUT_IF (tty, tty->TS_cursor_visible);
   OUTPUT_IF (tty, tty->TS_keypad_mode);
   losecursor (tty);
 }
 
-void
-set_terminal_modes ()
-{
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-  if (FRAME_TERMCAP_P (f))
-    tty_set_terminal_modes (FRAME_TTY (f));
-  else
-    (*set_terminal_modes_hook) ();
-}
+/* Reset termcap modes before exiting Emacs. */
 
-void tty_reset_terminal_modes (struct tty_output *tty)
+void
+tty_reset_terminal_modes (struct display *display)
 {
+  struct tty_display_info *tty = display->display_info.tty;
+  
   turn_off_highlight (tty);
   turn_off_insert (tty);
   OUTPUT_IF (tty, tty->TS_end_keypad_mode);
@@ -353,57 +245,68 @@ void tty_reset_terminal_modes (struct tty_output *tty)
   cmputc ('\r');
 }
 
-void
-reset_terminal_modes ()
-{
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-  if (FRAME_TERMCAP_P (f))
-    tty_reset_terminal_modes (FRAME_TTY (f));
-  else if (reset_terminal_modes_hook)
-    (*reset_terminal_modes_hook) ();
-}
-
 void
 update_begin (f)
      struct frame *f;
 {
   updating_frame = f;
-  if (!FRAME_TERMCAP_P (f))
-    update_begin_hook (f);
+  if (FRAME_DISPLAY (f)->update_begin_hook)
+    (*FRAME_DISPLAY (f)->update_begin_hook) (f);
 }
 
 void
 update_end (f)
      struct frame *f;
 {
-  if (FRAME_TERMCAP_P (f))
-    {
-      struct tty_output *tty = FRAME_TTY (f);
-      if (!XWINDOW (selected_window)->cursor_off_p)
-       tty_show_cursor (tty);
-      turn_off_insert (tty);
-      background_highlight (tty);
-    }
-  else
-    update_end_hook (f);
-
+  if (FRAME_DISPLAY (f)->update_end_hook)
+    (*FRAME_DISPLAY (f)->update_end_hook) (f);
   updating_frame = NULL;
 }
 
+/* Flag the end of a display update on a termcap display. */
+
+void
+tty_update_end (struct frame *f)
+{
+  struct tty_display_info *tty = FRAME_TTY (f);
+
+  if (!XWINDOW (selected_window)->cursor_off_p)
+    tty_show_cursor (tty);
+  turn_off_insert (tty);
+  background_highlight (tty);
+}
+
+/* Specify how many text lines, from the top of the window,
+   should be affected by insert-lines and delete-lines operations.
+   This, and those operations, are used only within an update
+   that is bounded by calls to update_begin and update_end.  */
+
 void
 set_terminal_window (size)
      int size;
 {
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-  if (FRAME_TERMCAP_P (f))
-    {
-      struct tty_output *tty = FRAME_TTY (f);
-      tty->specified_window = size ? size : FRAME_LINES (f);
-      if (TTY_SCROLL_REGION_OK (tty))
-       set_scroll_region (0, tty->specified_window);
-    }
-  else
-    set_terminal_window_hook (size);
+  struct frame *f = (updating_frame
+                     ? updating_frame
+                     : XFRAME (selected_frame));
+
+  if (FRAME_DISPLAY (f)->set_terminal_window_hook)
+    (*FRAME_DISPLAY (f)->set_terminal_window_hook) (size);
+}
+
+/* The implementation of set_terminal_window for termcap frames. */
+
+void
+tty_set_terminal_window (int size)
+{
+  struct frame *f = (updating_frame
+                     ? updating_frame
+                     : XFRAME (selected_frame));
+
+  struct tty_display_info *tty = FRAME_TTY (f);
+
+  tty->specified_window = size ? size : FRAME_LINES (f);
+  if (FRAME_SCROLL_REGION_OK (f))
+    set_scroll_region (0, tty->specified_window);
 }
 
 void
@@ -411,8 +314,11 @@ set_scroll_region (start, stop)
      int start, stop;
 {
   char *buf;
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-  struct tty_output *tty = FRAME_TTY (f);
+  struct frame *f = (updating_frame
+                     ? updating_frame
+                     : XFRAME (selected_frame));
+
+  struct tty_display_info *tty = FRAME_TTY (f);
 
   if (tty->TS_set_scroll_region)
     buf = tparam (tty->TS_set_scroll_region, 0, 0, start, stop - 1);
@@ -431,7 +337,7 @@ set_scroll_region (start, stop)
 
 \f
 static void
-turn_on_insert (struct tty_output *tty)
+turn_on_insert (struct tty_display_info *tty)
 {
   if (!tty->insert_mode)
     OUTPUT (tty, tty->TS_insert_mode);
@@ -439,7 +345,7 @@ turn_on_insert (struct tty_output *tty)
 }
 
 void
-turn_off_insert (struct tty_output *tty)
+turn_off_insert (struct tty_display_info *tty)
 {
   if (tty->insert_mode)
     OUTPUT (tty, tty->TS_end_insert_mode);
@@ -449,7 +355,7 @@ turn_off_insert (struct tty_output *tty)
 /* Handle highlighting.  */
 
 void
-turn_off_highlight (struct tty_output *tty)
+turn_off_highlight (struct tty_display_info *tty)
 {
   if (tty->standout_mode)
     OUTPUT_IF (tty, tty->TS_end_standout_mode);
@@ -457,7 +363,7 @@ turn_off_highlight (struct tty_output *tty)
 }
 
 static void
-turn_on_highlight (struct tty_output *tty)
+turn_on_highlight (struct tty_display_info *tty)
 {
   if (!tty->standout_mode)
     OUTPUT_IF (tty, tty->TS_standout_mode);
@@ -465,7 +371,7 @@ turn_on_highlight (struct tty_output *tty)
 }
 
 static void
-toggle_highlight (struct tty_output *tty)
+toggle_highlight (struct tty_display_info *tty)
 {
   if (tty->standout_mode)
     turn_off_highlight (tty);
@@ -477,7 +383,7 @@ toggle_highlight (struct tty_output *tty)
 /* Make cursor invisible.  */
 
 static void
-tty_hide_cursor (struct tty_output *tty)
+tty_hide_cursor (struct tty_display_info *tty)
 {
   if (tty->cursor_hidden == 0)
     {
@@ -490,7 +396,7 @@ tty_hide_cursor (struct tty_output *tty)
 /* Ensure that cursor is visible.  */
 
 static void
-tty_show_cursor (struct tty_output *tty)
+tty_show_cursor (struct tty_display_info *tty)
 {
   if (tty->cursor_hidden)
     {
@@ -506,7 +412,7 @@ tty_show_cursor (struct tty_output *tty)
    depends on the user option inverse-video.  */
 
 void
-background_highlight (struct tty_output *tty)
+background_highlight (struct tty_display_info *tty)
 {
   if (inverse_video)
     turn_on_highlight (tty);
@@ -517,7 +423,7 @@ background_highlight (struct tty_output *tty)
 /* Set standout mode to the mode specified for the text to be output.  */
 
 static void
-highlight_if_desired (struct tty_output *tty)
+highlight_if_desired (struct tty_display_info *tty)
 {
   if (inverse_video)
     turn_on_highlight (tty);
@@ -533,16 +439,22 @@ void
 cursor_to (vpos, hpos)
      int vpos, hpos;
 {
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-  struct tty_output *tty;
-  
-  if (! FRAME_TERMCAP_P (f) && cursor_to_hook)
-    {
-      (*cursor_to_hook) (vpos, hpos);
-      return;
-    }
+  struct frame *f = (updating_frame
+                     ? updating_frame
+                     : XFRAME (selected_frame));
+
+  if (FRAME_DISPLAY (f)->cursor_to_hook)
+    (*FRAME_DISPLAY (f)->cursor_to_hook) (vpos, hpos);
+}
 
-  tty = FRAME_TTY (f);
+void
+tty_cursor_to (int vpos, int hpos)
+{
+  struct frame *f = (updating_frame
+                     ? updating_frame
+                     : XFRAME (selected_frame));
+  
+  struct tty_display_info *tty = FRAME_TTY (f);
 
   /* Detect the case where we are called from reset_sys_modes
      and the costs have never been calculated.  Do nothing.  */
@@ -565,14 +477,23 @@ void
 raw_cursor_to (row, col)
      int row, col;
 {
-  struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
-  struct tty_output *tty;
-  if (! FRAME_TERMCAP_P (f))
-    {
-      (*raw_cursor_to_hook) (row, col);
-      return;
-    }
-  tty = FRAME_TTY (f);
+  struct frame *f = (updating_frame
+                     ? updating_frame
+                     : XFRAME (selected_frame));
+
+  if (FRAME_DISPLAY (f)->raw_cursor_to_hook)
+    (*FRAME_DISPLAY (f)->raw_cursor_to_hook) (row, col);  
+}
+
+void
+tty_raw_cursor_to (int row, int col)
+{
+  struct frame *f = (updating_frame
+                     ? updating_frame
+                     : XFRAME (selected_frame));
+
+  struct tty_display_info *tty = FRAME_TTY (f);
+
   if (curY (tty) == row
       && curX (tty) == col)
     return;
@@ -585,21 +506,29 @@ raw_cursor_to (row, col)
 \f
 /* Erase operations */
 
-/* clear from cursor to end of frame */
+/* Clear from cursor to end of frame. */
 void
 clear_to_end ()
+{
+  struct frame *f = (updating_frame
+                     ? updating_frame
+                     : XFRAME (selected_frame));
+
+  if (FRAME_DISPLAY (f)->clear_to_end_hook)
+    (*FRAME_DISPLAY (f)->clear_to_end_hook) ();
+}
+
+/* Clear from cursor to end of frame on a termcap device. */
+
+void
+tty_clear_to_end (void)
 {
   register int i;
+  struct frame *f = (updating_frame
+                     ? updating_frame
+                     : XFRAME (selected_frame));
+  struct tty_display_info *tty = FRAME_TTY (f);
 
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-  struct tty_output *tty;
-  
-  if (clear_to_end_hook && ! FRAME_TERMCAP_P (f))
-    {
-      (*clear_to_end_hook) ();
-      return;
-    }
-  tty = FRAME_TTY (f);
   if (tty->TS_clr_to_bottom)
     {
       background_highlight (tty);
@@ -621,14 +550,22 @@ void
 clear_frame ()
 {
   struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-  struct tty_output *tty;
-  
-  if (clear_frame_hook && ! FRAME_TERMCAP_P (f))
-    {
-      (*clear_frame_hook) ();
-      return;
-    }
-  tty = FRAME_TTY (f);
+
+  if (FRAME_DISPLAY (f)->clear_frame_hook)
+    (*FRAME_DISPLAY (f)->clear_frame_hook) ();
+}
+
+/* Clear an entire termcap frame. */
+
+void
+tty_clear_frame ()
+{
+  struct frame *f = (updating_frame
+                     ? updating_frame
+                     : XFRAME (selected_frame));
+
+  struct tty_display_info *tty = FRAME_TTY (f);
+
   if (tty->TS_clr_frame)
     {
       background_highlight (tty);
@@ -651,19 +588,26 @@ void
 clear_end_of_line (first_unused_hpos)
      int first_unused_hpos;
 {
-  register int i;
+  struct frame *f = (updating_frame
+                     ? updating_frame
+                     : XFRAME (selected_frame));
 
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-  struct tty_output *tty;
-  
-  if (clear_end_of_line_hook
-      && ! FRAME_TERMCAP_P (f))
-    {
-      (*clear_end_of_line_hook) (first_unused_hpos);
-      return;
-    }
+  if (FRAME_DISPLAY (f)->clear_end_of_line_hook)
+    (*FRAME_DISPLAY (f)->clear_end_of_line_hook) (first_unused_hpos);
+}
+
+/* An implementation of clear_end_of_line for termcap frames.
 
-  tty = FRAME_TTY (f);
+   Note that the cursor may be moved, on terminals lacking a `ce' string.  */
+
+void
+tty_clear_end_of_line (int first_unused_hpos)
+{
+  register int i;
+  struct frame *f = (updating_frame
+                     ? updating_frame
+                     : XFRAME (selected_frame));
+  struct tty_display_info *tty = FRAME_TTY (f);
 
   /* Detect the case where we are called from reset_sys_modes
      and the costs have never been calculated.  Do nothing.  */
@@ -683,8 +627,8 @@ clear_end_of_line (first_unused_hpos)
 
       /* Do not write in last row last col with Auto-wrap on. */
       if (AutoWrap (tty)
-          && curY (tty) == FRAME_LINES (f) - 1
-         && first_unused_hpos == FRAME_COLS (f))
+          && curY (tty) == FrameRows (tty) - 1
+         && first_unused_hpos == FrameCols (tty))
        first_unused_hpos--;
 
       for (i = curX (tty); i < first_unused_hpos; i++)
@@ -806,25 +750,36 @@ encode_terminal_code (src, dst, src_len, dst_len, consumed)
 }
 
 
+/* Output LEN glyphs starting at STRING at the nominal cursor position.
+   Advance the nominal cursor over the text.  */
+
 void
 write_glyphs (string, len)
      register struct glyph *string;
      register int len;
+{
+  struct frame *f = (updating_frame
+                     ? updating_frame
+                     : XFRAME (selected_frame));
+
+  if (FRAME_DISPLAY (f)->write_glyphs_hook)
+    (*FRAME_DISPLAY (f)->write_glyphs_hook) (string, len);
+}
+
+/* An implementation of write_glyphs for termcap frames. */
+
+void
+tty_write_glyphs (struct glyph *string, int len)
 {
   int produced, consumed;
-  struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
-  struct tty_output *tty;
   unsigned char conversion_buffer[1024];
   int conversion_buffer_size = sizeof conversion_buffer;
 
-  if (write_glyphs_hook
-      && ! FRAME_TERMCAP_P (f))
-    {
-      (*write_glyphs_hook) (string, len);
-      return;
-    }
+  struct frame *f = (updating_frame
+                     ? updating_frame
+                     : XFRAME (selected_frame));
 
-  tty = FRAME_TTY (f);
+  struct tty_display_info *tty = FRAME_TTY (f);
 
   turn_off_insert (tty);
   tty_hide_cursor (tty);
@@ -908,28 +863,38 @@ write_glyphs (string, len)
   cmcheckmagic (tty);
 }
 
-/* If start is zero, insert blanks instead of a string at start */
+/* Insert LEN glyphs from START at the nominal cursor position.
+
+   If start is zero, insert blanks instead of a string at start */
 
 void
 insert_glyphs (start, len)
      register struct glyph *start;
      register int len;
 {
-  char *buf;
-  struct glyph *glyph = NULL;
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-  struct tty_output *tty;
-  
+  struct frame *f = (updating_frame
+                     ? updating_frame
+                     : XFRAME (selected_frame));
+
   if (len <= 0)
     return;
 
-  if (insert_glyphs_hook  && ! FRAME_TERMCAP_P (f))
-    {
-      (*insert_glyphs_hook) (start, len);
-      return;
-    }
+  if (FRAME_DISPLAY (f)->insert_glyphs_hook)
+    (*FRAME_DISPLAY (f)->insert_glyphs_hook) (start, len);
+}
 
-  tty = FRAME_TTY (f);
+/* An implementation of insert_glyphs for termcap frames. */
+
+void
+tty_insert_glyphs (struct glyph *start, int len)
+{
+  char *buf;
+  struct glyph *glyph = NULL;
+  struct frame *f = (updating_frame
+                     ? updating_frame
+                     : XFRAME (selected_frame));
+
+  struct tty_display_info *tty = FRAME_TTY (f);
 
   if (tty->TS_ins_multi_chars)
     {
@@ -1003,21 +968,32 @@ insert_glyphs (start, len)
   cmcheckmagic (tty);
 }
 
+/* Delete N glyphs at the nominal cursor position. */
+
 void
 delete_glyphs (n)
      register int n;
+{
+  struct frame *f = (updating_frame
+                     ? updating_frame
+                     : XFRAME (selected_frame));
+
+  if (FRAME_DISPLAY (f)->delete_glyphs_hook)
+    (*FRAME_DISPLAY (f)->delete_glyphs_hook) (n);
+}
+
+/* An implementation of delete_glyphs for termcap frames. */
+
+void
+tty_delete_glyphs (int n)
 {
   char *buf;
   register int i;
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-  struct tty_output *tty = FRAME_TTY (f);
-
-  if (delete_glyphs_hook && ! FRAME_TERMCAP_P (f))
-    {
-      (*delete_glyphs_hook) (n);
-      return;
-    }
+  struct frame *f = (updating_frame
+                     ? updating_frame
+                     : XFRAME (selected_frame));
 
+  struct tty_display_info *tty = FRAME_TTY (f);
 
   if (tty->delete_in_insert_mode)
     {
@@ -1028,7 +1004,7 @@ delete_glyphs (n)
       turn_off_insert (tty);
       OUTPUT_IF (tty, tty->TS_delete_mode);
     }
-  
+
   if (tty->TS_del_multi_chars)
     {
       buf = tparam (tty->TS_del_multi_chars, 0, 0, n);
@@ -1048,73 +1024,81 @@ void
 ins_del_lines (vpos, n)
      int vpos, n;
 {
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-  if (ins_del_lines_hook && ! FRAME_TERMCAP_P (f))
+  struct frame *f = (updating_frame
+                     ? updating_frame
+                     : XFRAME (selected_frame));
+  
+  if (FRAME_DISPLAY (f)->ins_del_lines_hook)
+    (*FRAME_DISPLAY (f)->ins_del_lines_hook) (vpos, n);
+}
+
+/* An implementation of ins_del_lines for termcap frames. */
+
+void
+tty_ins_del_lines (int vpos, int n)
+{
+  struct frame *f = (updating_frame
+                     ? updating_frame
+                     : XFRAME (selected_frame));
+
+  struct tty_display_info *tty = FRAME_TTY (f);
+  char *multi = n > 0 ? tty->TS_ins_multi_lines : tty->TS_del_multi_lines;
+  char *single = n > 0 ? tty->TS_ins_line : tty->TS_del_line;
+  char *scroll = n > 0 ? tty->TS_rev_scroll : tty->TS_fwd_scroll;
+
+  register int i = n > 0 ? n : -n;
+  register char *buf;
+
+  /* If the lines below the insertion are being pushed
+     into the end of the window, this is the same as clearing;
+     and we know the lines are already clear, since the matching
+     deletion has already been done.  So can ignore this.  */
+  /* If the lines below the deletion are blank lines coming
+     out of the end of the window, don't bother,
+     as there will be a matching inslines later that will flush them. */
+  if (FRAME_SCROLL_REGION_OK (f)
+      && vpos + i >= tty->specified_window)
+    return;
+  if (!FRAME_MEMORY_BELOW_FRAME (f)
+      && vpos + i >= FRAME_LINES (f))
+    return;
+  
+  if (multi)
     {
-      (*ins_del_lines_hook) (vpos, n);
-      return;
+      raw_cursor_to (vpos, 0);
+      background_highlight (tty);
+      buf = tparam (multi, 0, 0, i);
+      OUTPUT (tty, buf);
+      xfree (buf);
+    }
+  else if (single)
+    {
+      raw_cursor_to (vpos, 0);
+      background_highlight (tty);
+      while (--i >= 0)
+        OUTPUT (tty, single);
+      if (tty->TF_teleray)
+        curX (tty) = 0;
     }
   else
     {
-      struct tty_output *tty = FRAME_TTY (f);
-      char *multi = n > 0 ? tty->TS_ins_multi_lines : tty->TS_del_multi_lines;
-      char *single = n > 0 ? tty->TS_ins_line : tty->TS_del_line;
-      char *scroll = n > 0 ? tty->TS_rev_scroll : tty->TS_fwd_scroll;
-      
-      register int i = n > 0 ? n : -n;
-      register char *buf;
-      
-      /* If the lines below the insertion are being pushed
-         into the end of the window, this is the same as clearing;
-         and we know the lines are already clear, since the matching
-         deletion has already been done.  So can ignore this.  */
-      /* If the lines below the deletion are blank lines coming
-         out of the end of the window, don't bother,
-         as there will be a matching inslines later that will flush them. */
-      if (TTY_SCROLL_REGION_OK (tty)
-          && vpos + i >= tty->specified_window)
-        return;
-      if (!TTY_MEMORY_BELOW_FRAME (tty)
-          && vpos + i >= FRAME_LINES (f))
-        return;
-      
-      if (multi)
-        {
-          raw_cursor_to (vpos, 0);
-          background_highlight (tty);
-          buf = tparam (multi, 0, 0, i);
-          OUTPUT (tty, buf);
-          xfree (buf);
-        }
-      else if (single)
-        {
-          raw_cursor_to (vpos, 0);
-          background_highlight (tty);
-          while (--i >= 0)
-            OUTPUT (tty, single);
-          if (tty->TF_teleray)
-            curX (tty) = 0;
-        }
+      set_scroll_region (vpos, tty->specified_window);
+      if (n < 0)
+        raw_cursor_to (tty->specified_window - 1, 0);
       else
-        {
-          set_scroll_region (vpos, tty->specified_window);
-          if (n < 0)
-            raw_cursor_to (tty->specified_window - 1, 0);
-          else
-            raw_cursor_to (vpos, 0);
-          background_highlight (tty);
-          while (--i >= 0)
-            OUTPUTL (tty, scroll, tty->specified_window - vpos);
-          set_scroll_region (0, tty->specified_window);
-        }
-      
-      if (!TTY_SCROLL_REGION_OK (tty)
-          && TTY_MEMORY_BELOW_FRAME (tty)
-          && n < 0)
-        {
-          cursor_to (FRAME_LINES (f) + n, 0);
-          clear_to_end ();
-        }
+        raw_cursor_to (vpos, 0);
+      background_highlight (tty);
+      while (--i >= 0)
+        OUTPUTL (tty, scroll, tty->specified_window - vpos);
+      set_scroll_region (0, tty->specified_window);
+    }
+  
+  if (!FRAME_SCROLL_REGION_OK (f)
+      && FRAME_MEMORY_BELOW_FRAME (f)
+      && n < 0)
+    {
+      cursor_to (FRAME_LINES (f) + n, 0);
+      clear_to_end ();
     }
 }
 \f
@@ -1175,7 +1159,7 @@ static void
 calculate_ins_del_char_costs (f)
      FRAME_PTR f;
 {
-  struct tty_output *tty = FRAME_TTY (f);
+  struct tty_display_info *tty = FRAME_TTY (f);
   int ins_startup_cost, del_startup_cost;
   int ins_cost_per_char, del_cost_per_char;
   register int i;
@@ -1237,60 +1221,64 @@ void
 calculate_costs (frame)
      FRAME_PTR frame;
 {
-  struct tty_output *tty = FRAME_TTY (frame);
-  register char *f = (tty->TS_set_scroll_region
-                     ? tty->TS_set_scroll_region
-                     : tty->TS_set_scroll_region_1);
-
   FRAME_COST_BAUD_RATE (frame) = baud_rate;
 
   if (FRAME_TERMCAP_P (frame))
-    TTY_SCROLL_REGION_COST (frame->output_data.tty) = string_cost (f);
+    {
+      struct tty_display_info *tty = FRAME_TTY (frame);
+      register char *f = (tty->TS_set_scroll_region
+                          ? tty->TS_set_scroll_region
+                          : tty->TS_set_scroll_region_1);
 
-  /* These variables are only used for terminal stuff.  They are allocated
-     once for the terminal frame of X-windows emacs, but not used afterwards.
+      FRAME_SCROLL_REGION_COST (frame) = string_cost (f);
 
-     char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
-     X turns off char_ins_del_ok. */
+      tty->costs_set = 1;
 
-  max_frame_lines = max (max_frame_lines, FRAME_LINES (frame));
-  max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
+      /* These variables are only used for terminal stuff.  They are
+         allocated once for the terminal frame of X-windows emacs, but not
+         used afterwards.
 
-  tty->costs_set = 1;
+         char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
+         X turns off char_ins_del_ok. */
 
-  if (char_ins_del_vector != 0)
-    char_ins_del_vector
-      = (int *) xrealloc (char_ins_del_vector,
-                         (sizeof (int)
-                          + 2 * max_frame_cols * sizeof (int)));
-  else
-    char_ins_del_vector
-      = (int *) xmalloc (sizeof (int)
-                        + 2 * max_frame_cols * sizeof (int));
-
-  bzero (char_ins_del_vector, (sizeof (int)
-                              + 2 * max_frame_cols * sizeof (int)));
-
-  if (f && (!tty->TS_ins_line && !tty->TS_del_line))
-    do_line_insertion_deletion_costs (frame,
-                                     tty->TS_rev_scroll, tty->TS_ins_multi_lines,
-                                     tty->TS_fwd_scroll, tty->TS_del_multi_lines,
-                                     f, f, 1);
-  else
-    do_line_insertion_deletion_costs (frame,
-                                     tty->TS_ins_line, tty->TS_ins_multi_lines,
-                                     tty->TS_del_line, tty->TS_del_multi_lines,
-                                     0, 0, 1);
+      max_frame_lines = max (max_frame_lines, FRAME_LINES (frame));
+      max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
+
+      if (char_ins_del_vector != 0)
+        char_ins_del_vector
+          = (int *) xrealloc (char_ins_del_vector,
+                              (sizeof (int)
+                               + 2 * max_frame_cols * sizeof (int)));
+      else
+        char_ins_del_vector
+          = (int *) xmalloc (sizeof (int)
+                             + 2 * max_frame_cols * sizeof (int));
 
-  calculate_ins_del_char_costs (frame);
+      bzero (char_ins_del_vector, (sizeof (int)
+                                   + 2 * max_frame_cols * sizeof (int)));
 
-  /* Don't use TS_repeat if its padding is worse than sending the chars */
-  if (tty->TS_repeat && per_line_cost (tty->TS_repeat) * baud_rate < 9000)
-    tty->RPov = string_cost (tty->TS_repeat);
-  else
-    tty->RPov = FRAME_COLS (frame) * 2;
 
-  cmcostinit (FRAME_TTY (frame)); /* set up cursor motion costs */
+      if (f && (!tty->TS_ins_line && !tty->TS_del_line))
+        do_line_insertion_deletion_costs (frame,
+                                          tty->TS_rev_scroll, tty->TS_ins_multi_lines,
+                                          tty->TS_fwd_scroll, tty->TS_del_multi_lines,
+                                          f, f, 1);
+      else
+        do_line_insertion_deletion_costs (frame,
+                                          tty->TS_ins_line, tty->TS_ins_multi_lines,
+                                          tty->TS_del_line, tty->TS_del_multi_lines,
+                                          0, 0, 1);
+
+      calculate_ins_del_char_costs (frame);
+
+      /* Don't use TS_repeat if its padding is worse than sending the chars */
+      if (tty->TS_repeat && per_line_cost (tty->TS_repeat) * baud_rate < 9000)
+        tty->RPov = string_cost (tty->TS_repeat);
+      else
+        tty->RPov = FRAME_COLS (frame) * 2;
+
+      cmcostinit (FRAME_TTY (frame)); /* set up cursor motion costs */
+    }
 }
 \f
 struct fkey_table {
@@ -1755,7 +1743,7 @@ turn_on_face (f, face_id)
   struct face *face = FACE_FROM_ID (f, face_id);
   long fg = face->foreground;
   long bg = face->background;
-  struct tty_output *tty = FRAME_TTY (f);
+  struct tty_display_info *tty = FRAME_TTY (f);
 
   /* Do this first because TS_end_standout_mode may be the same
      as TS_exit_attribute_mode, which turns all appearances off. */
@@ -1853,7 +1841,7 @@ turn_off_face (f, face_id)
      int face_id;
 {
   struct face *face = FACE_FROM_ID (f, face_id);
-  struct tty_output *tty = FRAME_TTY (f);
+  struct tty_display_info *tty = FRAME_TTY (f);
 
   xassert (face != NULL);
 
@@ -1904,7 +1892,7 @@ turn_off_face (f, face_id)
 
 int
 tty_capable_p (tty, caps, fg, bg)
-     struct tty_output *tty;
+     struct tty_display_info *tty;
      unsigned caps;
      unsigned long fg, bg;
 {
@@ -1923,6 +1911,48 @@ tty_capable_p (tty, caps, fg, bg)
   return 1;
 }
 
+/* Return the tty display object specified by DISPLAY.
+   DISPLAY may be a frame or a string. */
+
+static struct display *
+get_tty_display (Lisp_Object display)
+{
+  struct display *d;
+
+  if (! FRAMEP (display) && ! STRINGP (display))
+    return 0;
+
+  /* The initial frame does not support colors. */
+  if (FRAMEP (display) && FRAME_INITIAL_P (XFRAME (display)))
+    return 0;
+
+  if (FRAMEP (display))
+    {
+      if (! FRAME_TERMCAP_P (XFRAME (display)))
+#if 0   /* XXX We need a predicate as the first argument; find one. */
+        wrong_type_argument ("Not a termcap frame", display);
+#else /* Until we fix the wrong_type_argument call above, simply throw
+         a dumb error. */
+      error ("DISPLAY is not a termcap frame");
+#endif  
+  
+      d = FRAME_DISPLAY (XFRAME (display));
+    }
+  else if (STRINGP (display))
+    {
+      char *name = (char *) alloca (SBYTES (display) + 1);
+      strncpy (name, SDATA (display), SBYTES (display));
+      name[SBYTES (display)] = 0;
+
+      d = get_named_tty_display (name);
+
+      if (!d)
+        error ("There is no tty display on %s", name);
+    }
+
+  return d;
+}
+
 
 /* Return non-zero if the terminal is capable to display colors.  */
 
@@ -1932,8 +1962,11 @@ DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
      (display)
      Lisp_Object display;
 {
-  struct tty_output *tty = FRAME_TTY (SELECTED_FRAME ());
-  return tty->TN_max_colors > 0 ? Qt : Qnil;
+  struct display *d = get_tty_display (display);
+  if (!d)
+    return Qnil;
+  else
+    return d->display_info.tty->TN_max_colors > 0 ? Qt : Qnil;
 }
 
 /* Return the number of supported colors.  */
@@ -1943,8 +1976,11 @@ DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
      (display)
      Lisp_Object display;
 {
-  struct tty_output *tty = FRAME_TTY (SELECTED_FRAME ());
-  return make_number (tty->TN_max_colors);
+  struct display *d = get_tty_display (display);
+  if (!d)
+    return Qnil;
+  else
+    return make_number (d->display_info.tty->TN_max_colors);
 }
 
 #ifndef WINDOWSNT
@@ -1952,7 +1988,7 @@ DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
 /* Save or restore the default color-related capabilities of this
    terminal.  */
 static void
-tty_default_color_capabilities (struct tty_output *tty, int save)
+tty_default_color_capabilities (struct tty_display_info *tty, int save)
 {
   static char
     *default_orig_pair, *default_set_foreground, *default_set_background;
@@ -1994,7 +2030,7 @@ tty_default_color_capabilities (struct tty_output *tty, int save)
    support; zero means set up for the default capabilities, the ones
    we saw at term_init time; -1 means turn off color support.  */
 void
-tty_setup_colors (struct tty_output *tty, int mode)
+tty_setup_colors (struct tty_display_info *tty, int mode)
 {
   /* Canonicalize all negative values of MODE.  */
   if (mode < -1)
@@ -2086,46 +2122,133 @@ set_tty_color_mode (f, val)
 
 \f
 
-struct tty_output *
-get_named_tty (name)
+/* Return the termcap display with the given name.  If NAME is null,
+   return the display corresponding to our controlling terminal.
+
+   Returns NULL if the named terminal device is not opened.  */
+struct display *
+get_named_tty_display (name)
      char *name;
 {
-  struct tty_output *tty = tty_list;
-
-  while (tty) {
-    if ((tty->name == 0 && name == 0)
-        || (name && tty->name && !strcmp (tty->name, name)))
-      return tty;
-    tty = tty->next;
+  struct display *d;
+
+  for (d = display_list; d; d = d->next_display) {
+    if (d->type == output_termcap
+        && ((d->display_info.tty->name == 0 && name == 0)
+            || (name && d->display_info.tty->name
+                && !strcmp (d->display_info.tty->name, name))))
+      return d;
   };
 
   return 0;
 }
 
 \f
+
+DEFUN ("frame-tty-name", Fframe_tty_name, Sframe_tty_name, 0, 1, 0,
+       doc: /* Return the name of the TTY device that FRAME is displayed on. */)
+  (frame)
+     Lisp_Object frame;
+{
+  struct frame *f;
+
+  if (NILP (frame))
+    {
+      f = XFRAME (selected_frame);
+    }
+  else
+    {
+      CHECK_LIVE_FRAME (frame);
+      f = XFRAME (frame);
+    }
+
+  if (f->output_method != output_termcap)
+    wrong_type_argument (Qframe_tty_name, frame);
+
+  if (FRAME_TTY (f)->name)
+    return build_string (FRAME_TTY (f)->name);
+  else
+    return Qnil;
+}
+
+DEFUN ("frame-tty-type", Fframe_tty_type, Sframe_tty_type, 0, 1, 0,
+       doc: /* Return the type of the TTY device that FRAME is displayed on. */)
+  (frame)
+     Lisp_Object frame;
+{
+  struct frame *f;
+
+  if (NILP (frame))
+    {
+      f = XFRAME (selected_frame);
+    }
+  else
+    {
+      CHECK_LIVE_FRAME (frame);
+      f = XFRAME (frame);
+    }
+
+  if (f->output_method != output_termcap)
+    wrong_type_argument (Qframe_tty_type, frame);
+
+  if (FRAME_TTY (f)->type)
+    return build_string (FRAME_TTY (f)->type);
+  else
+    return Qnil;
+}
+
+\f
 /***********************************************************************
                            Initialization
  ***********************************************************************/
 
-struct tty_output *
-term_dummy_init (void)
+/* Create the bootstrap display device for the initial frame.
+   Returns a display of type output_initial. */
+
+struct display *
+init_initial_display (void)
 {
-  if (initialized || tty_list)
-    error ("tty already initialized");
+  struct tty_display_info *tty;
+  
+  if (initialized || display_list || tty_list)
+    abort ();
 
-  tty_list = xmalloc (sizeof (struct tty_output));
-  bzero (tty_list, sizeof (struct tty_output));
-  TTY_NAME (tty_list) = 0;
-  TTY_INPUT (tty_list) = stdin;
-  TTY_OUTPUT (tty_list) = stdout;
-  return tty_list;
+  initial_display = create_display ();
+  initial_display->type = output_initial;
+  
+  initial_display->delete_display_hook = &delete_initial_display;
+  /* All other hooks are NULL. */
+  
+  return initial_display;
 }
 
+/* Deletes the bootstrap display device.
+   Called through delete_display_hook. */
 
-struct tty_output *
-term_init (name, terminal_type)
-     char *name;
-     char *terminal_type;
+void
+delete_initial_display (struct display *display)
+{
+  if (display != initial_display)
+    abort ();
+
+  delete_display (display);
+  initial_display = NULL;
+}
+
+/* Create a termcap display on the tty device with the given name and
+   type.
+
+   If NAME is NULL, then use the controlling tty, i.e., stdin/stdout.
+   Otherwise NAME should be a path to the tty device file,
+   e.g. "/dev/pts/7".
+
+   TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
+
+   If MUST_SUCCEED is true, then all errors are fatal. */
+
+struct display *
+term_init (char *name, char *terminal_type, int must_succeed)
 {
   char *area;
   char **address = &area;
@@ -2133,61 +2256,97 @@ term_init (name, terminal_type)
   int buffer_size = 4096;
   register char *p;
   int status;
-  struct frame *sf = XFRAME (selected_frame);
+  struct tty_display_info *tty;
+  struct display *display;
 
-  struct tty_output *tty;
+  static void maybe_fatal();
 
-  tty = get_named_tty (name);
-  if (tty)
-    {
-      /* Return the previously initialized terminal, except if it is the dummy
-         terminal created for the initial frame. */
-      if (tty->type)
-        return tty;
+  if (!terminal_type)
+    maybe_fatal (must_succeed, 0, 0,
+                 "Unknown terminal type",
+                 "Unknown terminal type");
+  
+  display = get_named_tty_display (name);
+  if (display)
+    return display;             /* We have already opened a display there. */
 
-      /* In the latter case, initialize top_frame to the current terminal. */
-      tty->top_frame = selected_frame;
-    }
-  else
-    {
-      tty = (struct tty_output *) xmalloc (sizeof (struct tty_output));
-      bzero (tty, sizeof (struct tty_output));
-      tty->next = tty_list;
-      tty_list = tty;
-    }
+  display = create_display ();
+  tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info));
+  bzero (tty, sizeof (struct tty_display_info));
+  tty->next = tty_list;
+  tty_list = tty;
 
-  if (tty->Wcm)
-    Wcm_clear (tty);
-  else
-    tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
+  display->type = output_termcap;
+  display->display_info.tty = tty;
+  tty->display = display;
+
+  tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
+  Wcm_clear (tty);
+
+  display->rif = 0; /* ttys don't support window-based redisplay. */
+
+  display->cursor_to_hook = &tty_cursor_to;
+  display->raw_cursor_to_hook = &tty_raw_cursor_to;
+
+  display->clear_to_end_hook = &tty_clear_to_end;
+  display->clear_frame_hook = &tty_clear_frame;
+  display->clear_end_of_line_hook = &tty_clear_end_of_line;
+
+  display->ins_del_lines_hook = &tty_ins_del_lines;
+
+  display->insert_glyphs_hook = &tty_insert_glyphs;
+  display->write_glyphs_hook = &tty_write_glyphs;
+  display->delete_glyphs_hook = &tty_delete_glyphs;
+
+  display->ring_bell_hook = &tty_ring_bell;
+  
+  display->reset_terminal_modes_hook = &tty_reset_terminal_modes;
+  display->set_terminal_modes_hook = &tty_set_terminal_modes;
+  display->update_begin_hook = 0; /* Not needed. */
+  display->update_end_hook = &tty_update_end;
+  display->set_terminal_window_hook = &tty_set_terminal_window;
+
+  display->mouse_position_hook = 0; /* Not needed. */
+  display->frame_rehighlight_hook = 0; /* Not needed. */
+  display->frame_raise_lower_hook = 0; /* Not needed. */
+
+  display->set_vertical_scroll_bar_hook = 0; /* Not needed. */
+  display->condemn_scroll_bars_hook = 0; /* Not needed. */
+  display->redeem_scroll_bar_hook = 0; /* Not needed. */
+  display->judge_scroll_bars_hook = 0; /* Not needed. */
+
+  display->read_socket_hook = &tty_read_avail_input; /* keyboard.c */
+  display->frame_up_to_date_hook = 0; /* Not needed. */
+  
+  display->delete_frame_hook = &delete_tty_output;
+  display->delete_display_hook = &delete_tty;
   
   if (name)
     {
       int fd;
-      FILE *f;
+      FILE *file;
       fd = emacs_open (name, O_RDWR, 0);
       if (fd < 0)
         {
-          tty_list = tty->next;
-          xfree (tty);
+          delete_tty (display);
           error ("Could not open file: %s", name);
         }
-      f = fdopen (fd, "w+");
-      TTY_NAME (tty) = xstrdup (name);
-      TTY_INPUT (tty) = f;
-      TTY_OUTPUT (tty) = f;
+      file = fdopen (fd, "w+");
+      tty->name = xstrdup (name);
+      tty->input = file;
+      tty->output = file;
     }
   else
     {
-      TTY_NAME (tty) = 0;
-      TTY_INPUT (tty) = stdin;
-      TTY_OUTPUT (tty) = stdout;
+      tty->name = 0;
+      tty->input = stdin;
+      tty->output = stdout;
     }
 
-  TTY_TYPE (tty) = xstrdup (terminal_type);
+  tty->type = xstrdup (terminal_type);
+
+  add_keyboard_wait_descriptor (fileno (tty->input));
 
-  init_sys_modes (tty);
-  
 #ifdef WINDOWSNT
   initialize_w32_display ();
 
@@ -2195,30 +2354,29 @@ term_init (name, terminal_type)
 
   area = (char *) xmalloc (2044);
 
-  FrameRows = FRAME_LINES (sf);
-  FrameCols = FRAME_COLS (sf);
-  specified_window = FRAME_LINES (sf);
+  FrameRows (tty) = FRAME_LINES (f); /* XXX */
+  FrameCols (tty) = FRAME_COLS (f);  /* XXX */
+  tty->specified_window = FRAME_LINES (f); /* XXX */
 
-  delete_in_insert_mode = 1;
+  tty->display->delete_in_insert_mode = 1;
 
-  UseTabs = 0;
-  TTY_SCROLL_REGION_OK (tty) = 0;
+  UseTabs (tty) = 0;
+  display->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.  */
-  TTY_LINE_INS_DEL_OK (tty) = 0;
-
-  TTY_CHAR_INS_DEL_OK (tty) = 1;
+  display->line_ins_del_ok = 0;
+  display->char_ins_del_ok = 1;
 
   baud_rate = 19200;
 
-  FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0;
-  FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none;
+  FRAME_CAN_HAVE_SCROLL_BARS (f) = 0; /* XXX */
+  FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none; /* XXX */
   TN_max_colors = 16;  /* Required to be non-zero for tty-display-color-p */
 
-  return tty;
+  return display;
 #else  /* not WINDOWSNT */
 
   Wcm_clear (tty);
@@ -2228,51 +2386,35 @@ term_init (name, terminal_type)
   if (status < 0)
     {
 #ifdef TERMINFO
-      if (name)
-        {
-          delete_tty (tty);
-          error ("Cannot open terminfo database file");
-        }
-      else
-        fatal ("Cannot open terminfo database file");
+      maybe_fatal (must_succeed, buffer, display,
+                   "Cannot open terminfo database file",
+                   "Cannot open terminfo database file");
 #else
-      if (name)
-        {
-          delete_tty (tty);
-          error ("Cannot open termcap database file");
-        }
-      else
-        fatal ("Cannot open termcap database file");
+      maybe_fatal (must_succeed, buffer, display,
+                   "Cannot open termcap database file",
+                   "Cannot open termcap database file");
 #endif
     }
   if (status == 0)
     {
 #ifdef TERMINFO
-      if (name)
-        {
-          delete_tty (tty);
-          error ("Terminal type %s is not defined", terminal_type);
-        }
-      else
-        fatal ("Terminal type %s is not defined.\n\
-If that is not the actual type of terminal you have,\n          \
+      maybe_fatal (must_succeed, buffer, display,
+                   "Terminal type %s is not defined",
+                   "Terminal type %s is not defined.\n\
+If that is not the actual type of terminal you have,\n\
 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
 `setenv TERM ...') to specify the correct type.  It may be necessary\n\
 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
-               terminal_type);
+                   terminal_type);
 #else
-      if (name)
-        {
-          delete_tty (tty);
-          error ("Terminal type %s is not defined", terminal_type);
-        }
-      else
-        fatal ("Terminal type %s is not defined.\n\
-If that is not the actual type of terminal you have,\n          \
+      maybe_fatal (must_succeed, buffer, display,
+                   "Terminal type %s is not defined",
+                   "Terminal type %s is not defined.\n\
+If that is not the actual type of terminal you have,\n\
 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
 `setenv TERM ...') to specify the correct type.  It may be necessary\n\
 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
-               terminal_type);
+                   terminal_type);
 #endif
     }
 
@@ -2387,9 +2529,9 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
   /* Since we make MagicWrap terminals look like AutoWrap, we need to have
      the former flag imply the latter.  */
   AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
-  TTY_MEMORY_BELOW_FRAME (tty) = tgetflag ("db");
+  display->memory_below_frame = tgetflag ("db");
   tty->TF_hazeltine = tgetflag ("hz");
-  TTY_MUST_WRITE_SPACES (tty) = tgetflag ("in");
+  display->must_write_spaces = tgetflag ("in");
   tty->meta_key = tgetflag ("km") || tgetflag ("MT");
   tty->TF_insmode_motion = tgetflag ("mi");
   tty->TF_standout_motion = tgetflag ("ms");
@@ -2401,25 +2543,24 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
   /* Get frame size from system, or else from termcap.  */
   {
     int height, width;
-    get_tty_size (tty, &width, &height);
-    FRAME_COLS (sf) = width;
-    FRAME_LINES (sf) = height;
+    get_tty_size (fileno (TTY_INPUT (tty)), &width, &height);
+    FrameCols (tty) = width;
+    FrameRows (tty) = height;
   }
 
-  if (FRAME_COLS (sf) <= 0)
-    SET_FRAME_COLS (sf, tgetnum ("co"));
-  else
-    /* Keep width and external_width consistent */
-    SET_FRAME_COLS (sf, FRAME_COLS (sf));
-  if (FRAME_LINES (sf) <= 0)
-    FRAME_LINES (sf) = tgetnum ("li");
+  if (FrameCols (tty) <= 0)
+    FrameCols (tty) = tgetnum ("co");
+  if (FrameRows (tty) <= 0)
+    FrameRows (tty) = tgetnum ("li");
 
-  if (FRAME_LINES (sf) < 3 || FRAME_COLS (sf) < 3)
-    fatal ("Screen size %dx%d is too small",
-           FRAME_LINES (sf), FRAME_COLS (sf));
+  if (FrameRows (tty) < 3 || FrameCols (tty) < 3)
+    maybe_fatal (must_succeed, NULL, display,
+                 "Screen size %dx%d is too small"
+                 "Screen size %dx%d is too small",
+                 FrameCols (tty), FrameRows (tty));
 
 #if 0  /* This is not used anywhere. */
-  TTY_MIN_PADDING_SPEED (tty) = tgetnum ("pb");
+  tty->display->min_padding_speed = tgetnum ("pb");
 #endif
 
   TabWidth (tty) = tgetnum ("tw");
@@ -2497,7 +2638,7 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
 
   if (!strcmp (terminal_type, "supdup"))
     {
-      TTY_MEMORY_BELOW_FRAME (tty) = 1;
+      display->memory_below_frame = 1;
       tty->Wcm->cm_losewrap = 1;
     }
   if (!strncmp (terminal_type, "c10", 3)
@@ -2507,7 +2648,7 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
         This string is not valid in general since it works only
         for windows starting at the upper left corner;
         but that is all Emacs uses.
-        
+
         This string works only if the frame is using
         the top of the video memory, because addressing is memory-relative.
         So first check the :ti string to see if that is true.
@@ -2524,7 +2665,7 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
            tty->TS_set_window = "\033v%C %C %C %C ";
        }
       /* Termcap entry often fails to have :in: flag */
-      TTY_MUST_WRITE_SPACES (tty) = 1;
+      display->must_write_spaces = 1;
       /* :ti string typically fails to have \E^G! in it */
       /* This limits scope of insert-char to one line.  */
       strcpy (area, tty->TS_termcap_modes);
@@ -2542,57 +2683,43 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
         }
     }
 
-  FrameRows (tty) = FRAME_LINES (sf);
-  FrameCols (tty) = FRAME_COLS (sf);
-  tty->specified_window = FRAME_LINES (sf);
+  tty->specified_window = FrameRows (tty);
 
   if (Wcm_init (tty) == -1)    /* can't do cursor motion */
-    if (name)
-      {
-        delete_tty (tty);
-        error ("Terminal type \"%s\" is not powerful enough to run Emacs");
-      }
-    else {
+    {
+      maybe_fatal (must_succeed, NULL, display,
+                   "Terminal type \"%s\" is not powerful enough to run Emacs",
 #ifdef VMS
-      fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
+                   "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
 It lacks the ability to position the cursor.\n\
 If that is not the actual type of terminal you have, use either the\n\
 DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
 or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
-             terminal_type);
 #else /* not VMS */
 # ifdef TERMINFO
-      fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
-It lacks the ability to position the cursor.\n                          \
-If that is not the actual type of terminal you have,\n                  \
+                   "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
+It lacks the ability to position the cursor.\n\
+If that is not the actual type of terminal you have,\n\
 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
 `setenv TERM ...') to specify the correct type.  It may be necessary\n\
 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
-             terminal_type);
 # else /* TERMCAP */
-      fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
-It lacks the ability to position the cursor.\n                       \
+                   "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
+It lacks the ability to position the cursor.\n\
 If that is not the actual type of terminal you have,\n\
 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
 `setenv TERM ...') to specify the correct type.  It may be necessary\n\
 to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
-             terminal_type);
 # endif /* TERMINFO */
 #endif /*VMS */
-    }
-  
-  if (FRAME_LINES (sf) <= 0
-      || FRAME_COLS (sf) <= 0)
-    {
-      if (name)
-        {
-          delete_tty (tty);
-          error ("The frame size has not been specified");
-        }
-      else
-        fatal ("The frame size has not been specified");
+                   terminal_type);
     }
 
+  if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
+    maybe_fatal (must_succeed, NULL, display,
+                 "Could not determine the frame size",
+                 "Could not determine the frame size");
+
   tty->delete_in_insert_mode
     = tty->TS_delete_mode && tty->TS_insert_mode
     && !strcmp (tty->TS_delete_mode, tty->TS_insert_mode);
@@ -2601,39 +2728,80 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
               && tty->TS_end_standout_mode
               && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode));
 
-  UseTabs (tty) = tabs_safe_p (tty) && TabWidth (tty) == 8;
+  UseTabs (tty) = tabs_safe_p (fileno (TTY_INPUT (tty))) && TabWidth (tty) == 8;
 
-  TTY_SCROLL_REGION_OK (tty)
+  display->scroll_region_ok
     = (tty->Wcm->cm_abs
        && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
 
-  TTY_LINE_INS_DEL_OK (tty)
+  display->line_ins_del_ok
     = (((tty->TS_ins_line || tty->TS_ins_multi_lines)
         && (tty->TS_del_line || tty->TS_del_multi_lines))
-       || (TTY_SCROLL_REGION_OK (tty)
+       || (display->scroll_region_ok
            && tty->TS_fwd_scroll && tty->TS_rev_scroll));
 
-  TTY_CHAR_INS_DEL_OK (tty)
+  display->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_FAST_CLEAR_END_OF_LINE (tty) = tty->TS_clr_line != 0;
+  display->fast_clear_end_of_line = tty->TS_clr_line != 0;
 
-  init_baud_rate ();
-  if (read_socket_hook)                /* Baudrate is somewhat
-                                   meaningless in this case */
-    baud_rate = 9600;
+  init_baud_rate (fileno (TTY_INPUT (tty)));
 
-  FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0;
-  FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none;
-#endif /* WINDOWSNT */
+#ifdef AIXHFT
+  /* The HFT system on AIX doesn't optimize for scrolling, so it's
+     really ugly at times.  */
+  display->line_ins_del_ok = 0;
+  display->char_ins_del_ok = 0;
+#endif
 
-  xfree (buffer);
+#ifdef MULTI_KBOARD
+  tty->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
+  init_kboard (tty->kboard);
+  tty->kboard->next_kboard = all_kboards;
+  all_kboards = tty->kboard;
+  /* Don't let the initial kboard remain current longer than necessary.
+     That would cause problems if a file loaded on startup tries to
+     prompt in the mini-buffer.  */
+  if (current_kboard == initial_kboard)
+    current_kboard = tty->kboard;
+  tty->kboard->reference_count++;
+#endif
+
+  /* Don't do this.  I think termcap may still need the buffer. */
+  /* xfree (buffer); */
+
+  /* Init system terminal modes (RAW or CBREAK, etc.).  */
+  init_sys_modes (tty);
+
+  return display;
+#endif /* not WINDOWSNT */
+}
+
+/* Auxiliary error-handling function for term_init.
+   Free BUFFER and delete DISPLAY, then call error or fatal
+   with str1 or str2, respectively, according to MUST_SUCCEED.  */
+
+static void
+maybe_fatal (must_succeed, buffer, display, str1, str2, arg1, arg2)
+     int must_succeed;
+     char *buffer;
+     struct display *display;
+     char *str1, *str2, *arg1, *arg2;
+{
+  if (buffer)
+    xfree (buffer);
 
-  tty_set_terminal_modes (tty);
+  if (display)
+    delete_tty (display);
+  
+  if (must_succeed)
+    fatal (str2, arg1, arg2);
+  else
+    error (str1, arg1, arg2);
 
-  return tty;
+  abort ();
 }
 
 /* VARARGS 1 */
@@ -2648,57 +2816,66 @@ fatal (str, arg1, arg2)
   exit (1);
 }
 
-void
-syms_of_term ()
+\f
+
+DEFUN ("delete-tty", Fdelete_tty, Sdelete_tty, 0, 1, 0,
+       doc: /* Delete all frames on the terminal named TTY, and close the device.
+If omitted, TTY defaults to the controlling terminal.
+
+This function runs `delete-tty-after-functions' after closing the
+tty.  The functions are run with one arg, the frame to be deleted.  */)
+  (tty)
+     Lisp_Object tty;
 {
-  DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
-    doc: /* Non-nil means the system uses terminfo rather than termcap.
-This variable can be used by terminal emulator packages.  */);
-#ifdef TERMINFO
-  system_uses_terminfo = 1;
-#else
-  system_uses_terminfo = 0;
-#endif
+  struct display *d;
+  char *name = 0;
 
-  DEFVAR_LISP ("ring-bell-function", &Vring_bell_function,
-    doc: /* Non-nil means call this function to ring the bell.
-The function should accept no arguments.  */);
-  Vring_bell_function = Qnil;
+  CHECK_STRING (tty);
 
-  defsubr (&Stty_display_color_p);
-  defsubr (&Stty_display_color_cells);
+  if (SBYTES (tty) > 0)
+    {
+      name = (char *) alloca (SBYTES (tty) + 1);
+      strncpy (name, SDATA (tty), SBYTES (tty));
+      name[SBYTES (tty)] = 0;
+    }
 
-  Fprovide (intern ("multi-tty"), Qnil);
+  d = get_named_tty_display (name);
+
+  if (! d)
+    error ("No such terminal device: %s", name);
+
+  delete_tty (d);
 }
 
+static int deleting_tty = 0;
+
+
+/* Delete the given terminal device, closing all frames on it. */
+
 void
-delete_tty (struct tty_output *tty)
+delete_tty (struct display *display)
 {
+  struct tty_display_info *tty;
   Lisp_Object tail, frame;
-
-  FOR_EACH_FRAME (tail, frame)
-    {
-      struct frame *f = XFRAME (frame);
-      if (FRAME_LIVE_P (f) && FRAME_TTY (f) == tty)
-        {
-          Fdelete_frame (frame, Qt);
-          f->output_data.tty = 0;
-        }
-    }
+  char *tty_name;
   
-  /* Close the terminal and free memory. */
-  delete_tty_1 (tty);
-}
+  if (deleting_tty)
+    /* We get a recursive call when we delete the last frame on this
+       display. */
+    return;
 
-static void
-delete_tty_1 (struct tty_output *tty)
-{
+  deleting_tty = 1;
 
+  if (display->type != output_termcap)
+    abort ();
+
+  tty = display->display_info.tty;
+  
   if (tty == tty_list)
     tty_list = tty->next;
   else
     {
-      struct tty_output *p;
+      struct tty_display_info *p;
       for (p = tty_list; p && p->next != tty; p = p->next)
         ;
 
@@ -2706,58 +2883,209 @@ delete_tty_1 (struct tty_output *tty)
         /* This should not happen. */
         abort ();
 
-      p->next = p->next->next;
+      p->next = tty->next;
+      tty->next = 0;
+    }
+
+  FOR_EACH_FRAME (tail, frame)
+    {
+      struct frame *f = XFRAME (frame);
+      if (FRAME_TERMCAP_P (f) && FRAME_LIVE_P (f) && FRAME_TTY (f) == tty)
+        {
+          Fdelete_frame (frame, Qt);
+        }
     }
 
-  /* This hangs. */
-  /*  reset_sys_modes (tty); */
+  /* reset_sys_modes needs a valid display, so this call needs to be
+     before delete_display. */
+  reset_sys_modes (tty);
 
-    if (tty->name)
-    xfree (tty->name);
+  delete_display (display);
+
+  tty_name = tty->name;
   if (tty->type)
     xfree (tty->type);
+
   if (tty->input)
-    fclose (tty->input);
-  if (tty->output)
+    {
+      delete_keyboard_wait_descriptor (fileno (tty->input));
+      if (tty->input != stdin)
+        fclose (tty->input);
+    }
+  if (tty->output && tty->output != stdout && tty->output != tty->input)
     fclose (tty->output);
   if (tty->termscript)
     fclose (tty->termscript);
 
-  /*
   if (tty->old_tty)
     xfree (tty->old_tty);
 
-    if (tty->Wcm)
-    {
-      bzero (tty->Wcm, sizeof (struct cm));
-    }
-    xfree (tty->Wcm); 
-  
-  bzero (tty, sizeof (struct tty_output));
+  if (tty->Wcm)
+    xfree (tty->Wcm);
+
+#ifdef MULTI_KBOARD
+  if (tty->kboard && --tty->kboard->reference_count > 0)
+    abort ();
+  if (tty->kboard)
+    delete_kboard (tty->kboard);
+#endif
   
+  bzero (tty, sizeof (struct tty_display_info));
   xfree (tty);
-  */
+  deleting_tty = 0;
+
+  /* Run `delete-tty-after-functions'.  */
+  if (!NILP (Vrun_hooks))
+    {
+      Lisp_Object args[2];
+      args[0] = intern ("delete-tty-after-functions");
+      if (tty_name)
+        {
+          args[1] = build_string (tty_name);
+          xfree (tty_name);
+        }
+      else
+        args[1] = Qnil;
+      Frun_hook_with_args (2, args);
+    }
+}
+
+\f
+
+/* Initialize the tty-dependent part of frame F.  The frame must
+   already have its display initialized. */
+
+void
+create_tty_output (struct frame *f)
+{
+  struct tty_output *t;
+
+  if (! FRAME_TERMCAP_P (f))
+    abort ();
+
+  t = xmalloc (sizeof (struct tty_output));
+  bzero (t, sizeof (struct tty_output));
+
+  t->display_info = FRAME_DISPLAY (f)->display_info.tty;
+
+  f->output_data.tty = t;
 }
 
+/* Delete the tty-dependent part of frame F. */
 
-struct tty_output *
-get_current_tty ()
+void
+delete_tty_output (struct frame *f)
 {
-  return CURTTY();
+  if (! FRAME_TERMCAP_P (f))
+    abort ();
+
+  xfree (f->output_data.tty);
 }
 
+
+\f
+
+/* Mark the pointers in the tty_display_info objects.
+   Called by the Fgarbage_collector.  */
+
 void
-print_all_frames ()
+mark_ttys ()
 {
-  /* XXX Debug function. */
-  Lisp_Object frame, tail;
+  struct tty_display_info *tty;
+  Lisp_Object *p;
+  for (tty = tty_list; tty; tty = tty->next)
+    {
+      if (tty->top_frame)
+        mark_object (tty->top_frame);
+    }
+}
+
+\f
+
+/* Create a new display object and add it to the display list. */
+
+struct display *
+create_display (void)
+{
+  struct display *dev = (struct display *) xmalloc (sizeof (struct display));
+  
+  bzero (dev, sizeof (struct display));
+  dev->next_display = display_list;
+  display_list = dev;
+
+  return dev;
+}
+
+/* Remove a display from the display list and free its memory. */
+
+void
+delete_display (struct display *dev)
+{
+  struct display **dp;
+  Lisp_Object tail, frame;
+  
+  /* Check for and close live frames that are still on this
+     display. */
   FOR_EACH_FRAME (tail, frame)
     {
-      fprintf (stderr, "Frame: %x\n", XFRAME (frame));
-      fflush (stderr);
+      struct frame *f = XFRAME (frame);
+      if (FRAME_LIVE_P (f) && f->display == dev)
+        {
+          Fdelete_frame (frame, Qt);
+        }
     }
+
+  for (dp = &display_list; *dp != dev; dp = &(*dp)->next_display)
+    if (! *dp)
+      abort ();
+  *dp = dev->next_display;
+
+  bzero (dev, sizeof (struct display));
+  xfree (dev);
 }
 
 
+\f
+void
+syms_of_term ()
+{
+  DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
+    doc: /* Non-nil means the system uses terminfo rather than termcap.
+This variable can be used by terminal emulator packages.  */);
+#ifdef TERMINFO
+  system_uses_terminfo = 1;
+#else
+  system_uses_terminfo = 0;
+#endif
+
+  DEFVAR_LISP ("ring-bell-function", &Vring_bell_function,
+    doc: /* Non-nil means call this function to ring the bell.
+The function should accept no arguments.  */);
+  Vring_bell_function = Qnil;
+
+  DEFVAR_LISP ("delete-tty-after-functions", &Vdelete_tty_after_functions,
+    doc: /* Functions to be run after deleting a tty.
+The functions are run with one argument, the name of the tty to be deleted.
+See `delete-tty'.  */);
+  Vdelete_tty_after_functions = Qnil;
+
+  Qframe_tty_name = intern ("frame-tty-name");
+  staticpro (&Qframe_tty_name);
+
+  Qframe_tty_type = intern ("frame-tty-type");
+  staticpro (&Qframe_tty_type);
+
+  defsubr (&Stty_display_color_p);
+  defsubr (&Stty_display_color_cells);
+  defsubr (&Sframe_tty_name);
+  defsubr (&Sframe_tty_type);
+  defsubr (&Sdelete_tty);
+
+  Fprovide (intern ("multi-tty"), Qnil);
+
+}
+
+
+
 /* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193
    (do not change this comment) */