changeset 83008:040dd41ed7d0

Hookified termcap devices, added bootstrap display device, plus many bugfixes. lisp/frame.el (display-color-cells): Pass display parameter to tty-display-color-cells. lisp/term/xterm.el (xterm-register-default-colors): Pass the selected-frame to display-color-cells. src/dispextern.h (set_terminal_modes, reset_terminal_modes): Removed declarations. (get_named_tty_display): New prototype. (tty_clear_end_of_line, term_init): Updated to new prototype. (initial_term_init): Renamed to init_initial_display. src/dispnew.c (Fredraw_frame): ifdef-out DOS-specific code. Add display parameter to set_terminal_modes call. (update_frame): Don't flush the tty of there is no tty. (init_display): Set up a termcap display on the controlling tty and change the initial frame to use that. Delete the initial display. src/frame.c (Fframep): Return t for the initial frame. (make_initial_frame): New function for creating the initial frame during bootstrap. Use init_initial_display, not initial_term_init. (make_terminal_frame): Removed special cases for creating the initial frame. src/frame.h (enum output_method): New entry: output_initial for the bootstrap display. (FRAME_INITIAL_P): New macro. (make_initial_frame): New prototype. src/keyboard.c (interrupt_signal): Exit Emacs on SIGINT from the (frameless) controlling tty, if possible. Explain this in a comment. (init_keyboard): Added comment about exiting on SIGINT. (Fset_input_mode): A termcap frame is never the initial frame anymore. src/sysdep.c (init_sys_modes): Update tty_set_terminal_modes call to the new prototype. (reset_sys_modes): Comment out tty_clear_end_of_line call; it doesn't work anymore. Update tty_reset_terminal_modes call. src/termchar.h (struct tty_display_info): Added pointer to the display structure, for reset_sys_modes. src/termhooks.h (struct display): Added display parameter to set_terminal_modes_hook and reset_terminal_modes_hook. src/term.c (initial_display): New variable. (tty_ring_bell, tty_update_end, tty_set_terminal_window, tty_cursor_to) (tty_raw_cursor_to, tty_clear_to_end, tty_clear_frame, tty_clear_end_of_line) (tty_write_glyphs, tty_insert_glyphs, tty_delete_glyphs, tty_ins_del_lines): New functions. (ring_bell, update_end, set_terminal_window, cursor_to, raw_cursor_to) (clear_to_end, clear_frame, clear_end_of_line, write_glyphs, insert_glyphs) (delete_glyphs, ins_del_lines): Removed special casing of termcap displays. (get_tty_display): New function. (Ftty_display_color_p, Ftty_display_color_cells): Use it. (get_named_tty_display): Removed static. (tty_set_terminal_modes, tty_reset_terminal_modes): Changed to use a display parameter instead of tty_display_info for hook compatibility. (set_terminal_modes, reset_terminal_modes): Removed. (initial_term_init): Renamed to init_initial_display. Set up an output_initial device, not a termcap display. (delete_initial_display): New function. (maybe_fatal): New function, for private use of term_init. (term_init): New parameter for choosing between fatal and simple errors. Removed incomprehensible special casing for the second initialization of the controlling tty. Use maybe_fatal for error handling. Initialize termcap display hooks in the new device. Initialize the display pointer in the tty_display_info structure. (delete_tty): Replace order of reset_sys_modes and delete_display. src/window.c (init_window_once): Call make_initial_frame instead of make_terminal_frame. src/xfaces.c (realize_default_face, realize_face): Don't abort on the bootstrap display device. src/xterm.c (XTset_terminal_modes, XTreset_terminal_modes): Added display parameter. git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-48
author Karoly Lorentey <lorentey@elte.hu>
date Fri, 09 Jan 2004 18:57:53 +0000
parents c0cb35d94ea7
children b2b37c85b00a
files README.multi-tty lisp/frame.el lisp/term/xterm.el src/dispextern.h src/dispnew.c src/frame.c src/frame.h src/keyboard.c src/sysdep.c src/term.c src/termchar.h src/termhooks.h src/window.c src/xfaces.c src/xterm.c
diffstat 15 files changed, 591 insertions(+), 352 deletions(-) [+]
line wrap: on
line diff
--- a/README.multi-tty	Fri Jan 09 13:12:28 2004 +0000
+++ b/README.multi-tty	Fri Jan 09 18:57:53 2004 +0000
@@ -1,4 +1,4 @@
-			-*- coding: utf-8; -*-
+			-*- coding: utf-8; mode: text; -*-
 GOAL
 ----
 
@@ -131,7 +131,12 @@
    sessions automatically convert the face colors to terminal colors
    when the face is loaded.  This conversion must happen instead on
    the fly in write_glyphs, which might be problematic, as color
-   approximation is done in lisp (term/tty-colors.el).)
+   approximation is currently done in lisp (term/tty-colors.el).)
+
+** frame-creation-function should always create a frame that is on the
+   same display as the selected frame.  Maybe frame-creation-function
+   should simply be removed and make-frame changed to do the right
+   thing.
 
 ** The command `emacsclient -t -e '(delete-frame)'' fails to exit.
 
@@ -141,6 +146,11 @@
    extend emacsclient to handle suspend/resume.  A `kill -STOP' almost
    works right now.)
 
+** If there are no frames on its controlling terminal, Emacs should
+   exit if the uses presses C-c there.  (See the SIGTERM comment in
+   interrupt_signal on why this seems to be impossible to solve
+   generally.)
+
 ** During an X session, Emacs seems to read from stdin.
 
 ** Move baud_rate to struct display.
@@ -152,11 +162,20 @@
    an initial frame.  (The user would connect to it and open frames
    later, with emacsclient.)  Not necessarily a good idea.
 
-** Fix Mac support (I can't do this myself).
+** Fix Mac support (I can't do this myself).  Note that the current
+   state of Mac-specific source files in the multi-tty tree are not
+   useful; before starting work on Mac support, revert to pristine,
+   pre-multi-tty versions.
 
-** Fix W32 support (I can't do this myself).
+** Fix W32 support (I can't do this myself).  Note that the current
+   state of W32-specific source files in the multi-tty tree are not
+   useful; before starting work on W32 support, revert to pristine,
+   pre-multi-tty versions.
 
-** Fix DOS support (I can't do this myself).
+** Fix DOS support (I can't do this myself).  Note that the current
+   state of DOS-specific source files in the multi-tty tree are not
+   useful; before starting work on DOS support, revert to pristine,
+   pre-multi-tty versions.
 
 ** Do a grep on XXX and ?? for more issues.
 
@@ -349,7 +368,7 @@
 	while true; do TERM=no-such-terminal-definition emacsclient -h; done
 
    Emacs usually dumps core after a few dozen iterations.  (The bug
-   seems to be related to the xfree()ing or bzero()ing of
+   seems to be related to the xfreeing or bzeroing of
    tty_output.Wcm.  Maybe there are outside references to struct Wcm?
    Why were these vars collected into a struct before multi-tty
    support?)
@@ -358,18 +377,18 @@
    with hypothetical external references to Wcm, or any other
    tty_output component; it was simply that delete_tty closed the
    filehandles of secondary ttys twice, resulting in fclose doubly
-   free()ing memory.  Utterly trivial matter.  I love the C's memory
+   freeing memory.  Utterly trivial matter.  I love the C's memory
    management, it puts hair on your chest.)
 
 -- Support raw secondary terminals.  (Note that SIGIO works only on
-   the controlling terminal.) Hint: extend read_input_waiting() for
+   the controlling terminal.) Hint: extend read_input_waiting for
    multiple ttys and hopefully this will be fixed.
 
    (Done, it seems to have been working already for some time.  It
    seems F_SETOWN does work, after all.  Not sure what made it fail
    earlier, but it seems to be fixed (there were several changes
    around request_sigio, maybe one of them did it).
-   read_input_waiting() is only used in sys_select(), don't change
+   read_input_waiting is only used in sys_select, don't change
    it.)  (Update: After adding X support, it's broken again.)
 
 -- Find out why does Emacs abort when it wants to close its
@@ -381,7 +400,7 @@
    term_init/delete_tty.  The hint was right, in a way.)
 
 -- Issue with SIGIO: it needs to be disabled during redisplay.  See if
-   fcntl() kernel behaviour could be emulated by emacsclient.
+   fcntl kernel behaviour could be emulated by emacsclient.
 
    (Done.  Simply disabled the SIGIO emulation hack in emacsclient.)
    (Update: it was added back.)
--- a/lisp/frame.el	Fri Jan 09 13:12:28 2004 +0000
+++ b/lisp/frame.el	Fri Jan 09 18:57:53 2004 +0000
@@ -1137,7 +1137,7 @@
      ((eq frame-type 'pc)
       16)
      (t
-      (tty-display-color-cells)))))
+      (tty-display-color-cells display)))))
 
 (defun display-visual-class (&optional display)
   "Returns the visual class of DISPLAY.
--- a/lisp/term/xterm.el	Fri Jan 09 13:12:28 2004 +0000
+++ b/lisp/term/xterm.el	Fri Jan 09 18:57:53 2004 +0000
@@ -123,7 +123,7 @@
 `xterm-standard-colors', which see, while the rest are computed assuming
 either the 88- or 256-color standard color scheme supported by latest
 versions of xterm."
-  (let* ((ncolors (display-color-cells))
+  (let* ((ncolors (display-color-cells (selected-frame)))
 	 (colors xterm-standard-colors)
 	 (color (car colors)))
     (if (> ncolors 0)
--- a/src/dispextern.h	Fri Jan 09 13:12:28 2004 +0000
+++ b/src/dispextern.h	Fri Jan 09 18:57:53 2004 +0000
@@ -2728,8 +2728,6 @@
 /* Defined in term.c */
 
 extern void ring_bell P_ ((void));
-extern void set_terminal_modes P_ ((void));
-extern void reset_terminal_modes P_ ((void));
 extern void update_begin P_ ((struct frame *));
 extern void update_end P_ ((struct frame *));
 extern void set_terminal_window P_ ((int));
@@ -2740,7 +2738,7 @@
 extern void clear_frame P_ ((void));
 extern void clear_end_of_line P_ ((int));
 extern void clear_end_of_line_raw P_ ((int));
-extern void tty_clear_end_of_line P_ ((struct tty_display_info *, int));
+extern void tty_clear_end_of_line P_ ((int));
 extern void delete_glyphs P_ ((int));
 extern void ins_del_lines P_ ((int, int));
 extern int string_cost P_ ((char *));
@@ -2748,8 +2746,9 @@
 extern void calculate_costs P_ ((struct frame *));
 extern void set_tty_color_mode P_ ((struct frame *, Lisp_Object));
 extern void tty_setup_colors P_ ((struct tty_display_info *, int));
-extern struct display *term_init P_ ((char *, char *));
-extern struct display *initial_term_init P_ ((void));
+extern struct display *get_named_tty_display P_ ((char *));
+extern struct display *init_initial_display P_ ((void));
+extern struct display *term_init P_ ((char *, char *, int));
 extern void fatal P_ ((/* char *, ... */));
 void cursor_to P_ ((int, int));
 extern int tty_capable_p P_ ((struct tty_display_info *, unsigned, unsigned long, unsigned long));
--- a/src/dispnew.c	Fri Jan 09 13:12:28 2004 +0000
+++ b/src/dispnew.c	Fri Jan 09 18:57:53 2004 +0000
@@ -3306,8 +3306,10 @@
     return Qnil;
 
   update_begin (f);
+#ifdef MSDOS
   if (FRAME_MSDOS_P (f))
-    set_terminal_modes ();
+    set_terminal_modes (FRAME_DISPLAY (f));
+#endif
   clear_frame ();
   clear_current_matrices (f);
   update_end (f);
@@ -3833,9 +3835,12 @@
       paused_p = update_frame_1 (f, force_p, inhibit_hairy_id_p);
       update_end (f);
 
-      if (TTY_TERMSCRIPT (FRAME_TTY (f)))
-	fflush (TTY_TERMSCRIPT (FRAME_TTY (f)));
-      fflush (TTY_OUTPUT (FRAME_TTY (f)));
+      if (FRAME_TERMCAP_P (f))
+        {
+          if (TTY_TERMSCRIPT (FRAME_TTY (f)))
+            fflush (TTY_TERMSCRIPT (FRAME_TTY (f)));
+          fflush (TTY_OUTPUT (FRAME_TTY (f)));
+        }
 
       /* Check window matrices for lost pointers.  */
 #if GLYPH_DEBUG
@@ -6634,10 +6639,24 @@
 
   {
     struct display *d;
-    
-    d = term_init (0, terminal_type);
+    struct frame *f = XFRAME (selected_frame);
+
+    /* Open a display on the controlling tty. */
+    d = term_init (0, terminal_type, 1); /* Errors are fatal. */
+
+    /* Convert the initial frame to use the new display. */
+    if (! f->output_method == output_initial)
+      abort ();
+    f->output_method = d->type;
+    f->display = d;
+
     d->display_info.tty->top_frame = selected_frame;
     change_frame_size (XFRAME (selected_frame), FrameRows (d->display_info.tty), FrameCols (d->display_info.tty), 0, 0, 1);
+
+    /* Delete the initial display. */
+    if (--initial_display->reference_count == 0
+        && initial_display->delete_display_hook)
+      (*initial_display->delete_display_hook) (initial_display);
   }
   
   {
--- a/src/frame.c	Fri Jan 09 13:12:28 2004 +0000
+++ b/src/frame.c	Fri Jan 09 18:57:53 2004 +0000
@@ -202,6 +202,7 @@
     return Qnil;
   switch (XFRAME (object)->output_method)
     {
+    case output_initial: /* The initial frame is like a termcap frame. */
     case output_termcap:
       return Qt;
     case output_x_window:
@@ -502,15 +503,12 @@
 static int terminal_frame_count;
 
 struct frame *
-make_terminal_frame (tty_name, tty_type)
-     char *tty_name;
-     char *tty_type;
+make_initial_frame (void)
 {
-  register struct frame *f;
+  struct frame *f;
   struct display *display;
   Lisp_Object frame;
-  char name[20];
-  
+
 #ifdef MULTI_KBOARD
   /* Create the initial keyboard. */
   if (!initial_kboard)
@@ -526,12 +524,51 @@
   if (! (NILP (Vframe_list) || CONSP (Vframe_list)))
     Vframe_list = Qnil;
 
+  display = init_initial_display ();
+
+  f = make_frame (1);
+  XSETFRAME (frame, f);
+
+  Vframe_list = Fcons (frame, Vframe_list);
+
+  terminal_frame_count = 1;
+  f->name = build_string ("F1");
+
+  f->visible = 1;
+  f->async_visible = 1;
+
+  f->output_method = display->type;
+  f->display = display;
+  f->display->reference_count++;
+  f->output_data.nothing = 0;
+  
+  FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
+  FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
+    
+  FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
+  FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
+
+#ifdef MULTI_KBOARD
+  f->kboard = initial_kboard;
+#endif
+
+  return f;
+}
+
+
+struct frame *
+make_terminal_frame (tty_name, tty_type)
+     char *tty_name;
+     char *tty_type;
+{
+  register struct frame *f;
+  struct display *display;
+  Lisp_Object frame;
+  char name[20];
+  
   /* Open the display before creating the new frame, because
      create_tty_display might throw an error. */
-  if (initialized)
-    display = term_init (tty_name, tty_type);
-  else
-    display = initial_term_init ();
+  display = term_init (tty_name, tty_type, 0); /* Errors are not fatal. */
   
   f = make_frame (1);
 
--- a/src/frame.h	Fri Jan 09 13:12:28 2004 +0000
+++ b/src/frame.h	Fri Jan 09 18:57:53 2004 +0000
@@ -41,6 +41,7 @@
 
 enum output_method
 {
+  output_initial,
   output_termcap,
   output_x_window,
   output_msdos_raw,
@@ -462,6 +463,7 @@
 #define WINDOW_FRAME(w) (w)->frame
 
 /* Test a frame for particular kinds of display methods.  */
+#define FRAME_INITIAL_P(f) ((f)->output_method == output_initial)
 #define FRAME_TERMCAP_P(f) ((f)->output_method == output_termcap)
 #define FRAME_X_P(f) ((f)->output_method == output_x_window)
 #define FRAME_W32_P(f) ((f)->output_method == output_w32)
@@ -771,7 +773,8 @@
 
 extern struct frame *last_nonminibuf_frame;
 
-extern struct frame *make_terminal_frame P_ ((char *tty, char *tty_type));
+extern struct frame *make_initial_frame P_ ((void));
+extern struct frame *make_terminal_frame P_ ((char *, char *));
 extern struct frame *make_frame P_ ((int));
 #ifdef HAVE_WINDOW_SYSTEM
 extern struct frame *make_minibuffer_frame P_ ((void));
--- a/src/keyboard.c	Fri Jan 09 13:12:28 2004 +0000
+++ b/src/keyboard.c	Fri Jan 09 18:57:53 2004 +0000
@@ -10281,8 +10281,26 @@
   signal (SIGQUIT, interrupt_signal);
 #endif /* USG */
 
+  if (! tty_list)
+    {
+      /* If there are no tty frames, exit Emacs.
+
+         Emacs should exit on SIGINT if and only if there are no
+         frames on its controlling tty and the signal came from there.
+         We can check for the first condition, but (alas) not for the
+         second.  The best we can do is that we only exit if we are
+         sure that the SIGINT was from the controlling tty, i.e., if
+         there are no termcap frames.
+      */
+      Fkill_emacs (Qnil);
+      
+      errno = old_errno;
+      return;
+    }
+
   cancel_echoing ();
 
+  /* XXX This code needs to be revised for multi-tty support. */
   if (!NILP (Vquit_flag)
       && (FRAME_TERMCAP_P (sf) || FRAME_MSDOS_P (sf)))
     {
@@ -10463,7 +10481,7 @@
 
 #ifndef DOS_NT
   /* this causes startup screen to be restored and messes with the mouse */
-  if (FRAME_TERMCAP_P (SELECTED_FRAME ()) && CURTTY ()->type)
+  if (FRAME_TERMCAP_P (SELECTED_FRAME ()))
     reset_sys_modes (CURTTY ());
 #endif
 
@@ -10502,7 +10520,7 @@
         tty->meta_key = 2;
     }
   
-  if (!NILP (quit))
+  if (FRAME_TERMCAP_P (XFRAME (selected_frame)) && !NILP (quit))
     /* Don't let this value be out of range.  */
     quit_char = XINT (quit) & (CURTTY ()->meta_key ? 0377 : 0177);
 
@@ -10660,6 +10678,11 @@
 
   if (!noninteractive)
     {
+      /* Before multi-tty support, these handlers used to be installed
+         only if the current session was a tty session.  Now an Emacs
+         session may have multiple display types, so we always handle
+         SIGINT.  There is special code in interrupt_signal to exit
+         Emacs on SIGINT when there are no termcap frames. */
       signal (SIGINT, interrupt_signal);
 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
       /* For systems with SysV TERMIO, C-g is set up for both SIGINT and
--- a/src/sysdep.c	Fri Jan 09 13:12:28 2004 +0000
+++ b/src/sysdep.c	Fri Jan 09 18:57:53 2004 +0000
@@ -1689,7 +1689,7 @@
       )
 #endif
 #endif
-    tty_set_terminal_modes (tty_out);
+    tty_set_terminal_modes (tty_out->display);
 
   if (!tty_out->term_initted)
     {
@@ -1869,7 +1869,9 @@
 #endif
   
   cmgoto (tty_out, FrameRows (tty_out) - 1, 0);
+#if 0  /* XXX This doesn't work anymore, the signature has changed. */
   tty_clear_end_of_line (tty_out, FrameCols (tty_out));
+#endif
   cmgoto (tty_out, FrameRows (tty_out) - 1, 0);
   fflush (tty_out->output);
   
@@ -1884,7 +1886,7 @@
   }
 #endif
 
-  tty_reset_terminal_modes (tty_out);
+  tty_reset_terminal_modes (tty_out->display);
   fflush (TTY_OUTPUT (tty_out));
 #ifdef BSD_SYSTEM
 #ifndef BSD4_1
--- a/src/term.c	Fri Jan 09 13:12:28 2004 +0000
+++ b/src/term.c	Fri Jan 09 18:57:53 2004 +0000
@@ -71,6 +71,7 @@
 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 *));
@@ -105,6 +106,9 @@
 /* Chain of all displays currently in use. */
 struct display *display_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;
 
@@ -172,7 +176,9 @@
 void
 ring_bell ()
 {
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
+  struct frame *f = (updating_frame
+                     ? updating_frame
+                     : XFRAME (selected_frame));
 
   if (!NILP (Vring_bell_function))
     {
@@ -195,32 +201,36 @@
     }
   else if (FRAME_DISPLAY (f)->ring_bell_hook)
     (*FRAME_DISPLAY (f)->ring_bell_hook) ();
-  else {
-    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_display_info *tty)
+void
+tty_ring_bell ()
 {
+  struct frame *f = (updating_frame
+                     ? updating_frame
+                     : 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 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 ()
+void tty_reset_terminal_modes (struct display *display)
 {
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-  if (FRAME_DISPLAY (f)->set_terminal_modes_hook)
-    (*FRAME_DISPLAY (f)->set_terminal_modes_hook) ();
-  else 
-    tty_set_terminal_modes (FRAME_TTY (f));
-}
-
-void tty_reset_terminal_modes (struct tty_display_info *tty)
-{
+  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);
@@ -233,16 +243,6 @@
 }
 
 void
-reset_terminal_modes ()
-{
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-  if (FRAME_DISPLAY (f)->reset_terminal_modes_hook)
-    (*FRAME_DISPLAY (f)->reset_terminal_modes_hook) ();
-  else
-    tty_reset_terminal_modes (FRAME_TTY (f));
-}
-
-void
 update_begin (f)
      struct frame *f;
 {
@@ -257,32 +257,44 @@
 {
   if (FRAME_DISPLAY (f)->update_end_hook)
     (*FRAME_DISPLAY (f)->update_end_hook) (f);
-  else if (FRAME_TERMCAP_P (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);
-    }
-
   updating_frame = NULL;
 }
 
 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);
+}
+
+void
 set_terminal_window (size)
      int size;
 {
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
+  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);
-  else if (FRAME_TERMCAP_P (f))
-    {
-      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
+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
@@ -290,7 +302,10 @@
      int start, stop;
 {
   char *buf;
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
+  struct frame *f = (updating_frame
+                     ? updating_frame
+                     : XFRAME (selected_frame));
+
   struct tty_display_info *tty = FRAME_TTY (f);
 
   if (tty->TS_set_scroll_region)
@@ -412,16 +427,22 @@
 cursor_to (vpos, hpos)
      int vpos, hpos;
 {
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-  struct tty_display_info *tty;
+  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);
-      return;
-    }
-
-  tty = FRAME_TTY (f);
+    (*FRAME_DISPLAY (f)->cursor_to_hook) (vpos, hpos);
+}
+
+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.  */
@@ -444,14 +465,23 @@
 raw_cursor_to (row, col)
      int row, col;
 {
-  struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
-  struct tty_display_info *tty;
+  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);
-      return;
-    }
-  tty = FRAME_TTY (f);
+    (*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;
@@ -468,17 +498,23 @@
 void
 clear_to_end ()
 {
-  register int i;
-
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-  struct tty_display_info *tty;
+  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) ();
-      return;
-    }
-  tty = FRAME_TTY (f);
+    (*FRAME_DISPLAY (f)->clear_to_end_hook) ();
+}
+
+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);
+
   if (tty->TS_clr_to_bottom)
     {
       background_highlight (tty);
@@ -500,14 +536,20 @@
 clear_frame ()
 {
   struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-  struct tty_display_info *tty;
 
   if (FRAME_DISPLAY (f)->clear_frame_hook)
-    {
-      (*FRAME_DISPLAY (f)->clear_frame_hook) ();
-      return;
-    }
-  tty = FRAME_TTY (f);
+    (*FRAME_DISPLAY (f)->clear_frame_hook) ();
+}
+
+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);
@@ -530,22 +572,23 @@
 clear_end_of_line (first_unused_hpos)
      int first_unused_hpos;
 {
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-  struct tty_display_info *tty;
+  struct frame *f = (updating_frame
+                     ? updating_frame
+                     : XFRAME (selected_frame));
 
   if (FRAME_DISPLAY (f)->clear_end_of_line_hook)
-    {
-      (*FRAME_DISPLAY (f)->clear_end_of_line_hook) (first_unused_hpos);
-      return;
-    }
-
-  tty_clear_end_of_line (FRAME_TTY (f), first_unused_hpos);
+    (*FRAME_DISPLAY (f)->clear_end_of_line_hook) (first_unused_hpos);
 }
 
 void
-tty_clear_end_of_line (struct tty_display_info *tty, int first_unused_hpos)
+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.  */
   if (! tty->costs_set)
@@ -692,19 +735,26 @@
      register struct glyph *string;
      register int len;
 {
-  int produced, consumed;
-  struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
-  struct tty_display_info *tty;
-  unsigned char conversion_buffer[1024];
-  int conversion_buffer_size = sizeof conversion_buffer;
+  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);
-      return;
-    }
-
-  tty = FRAME_TTY (f);
+    (*FRAME_DISPLAY (f)->write_glyphs_hook) (string, len);
+}
+
+void
+tty_write_glyphs (struct glyph *string, int len)
+{
+  int produced, consumed;
+  unsigned char conversion_buffer[1024];
+  int conversion_buffer_size = sizeof conversion_buffer;
+
+  struct frame *f = (updating_frame
+                     ? updating_frame
+                     : XFRAME (selected_frame));
+
+  struct tty_display_info *tty = FRAME_TTY (f);
 
   turn_off_insert (tty);
   tty_hide_cursor (tty);
@@ -795,23 +845,27 @@
      register struct glyph *start;
      register int len;
 {
-  char *buf;
-  struct glyph *glyph = NULL;
-  struct frame *f;
-  struct tty_display_info *tty;
+  struct frame *f = (updating_frame
+                     ? updating_frame
+                     : XFRAME (selected_frame));
 
   if (len <= 0)
     return;
 
-  f = (updating_frame ? updating_frame : XFRAME (selected_frame));
-
   if (FRAME_DISPLAY (f)->insert_glyphs_hook)
-    {
-      (*FRAME_DISPLAY (f)->insert_glyphs_hook) (start, len);
-      return;
-    }
-
-  tty = FRAME_TTY (f);
+    (*FRAME_DISPLAY (f)->insert_glyphs_hook) (start, len);
+}
+
+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)
     {
@@ -889,17 +943,24 @@
 delete_glyphs (n)
      register int n;
 {
-  char *buf;
-  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));
 
   if (FRAME_DISPLAY (f)->delete_glyphs_hook)
-    {
-      (*FRAME_DISPLAY (f)->delete_glyphs_hook) (n);
-      return;
-    }
-
+    (*FRAME_DISPLAY (f)->delete_glyphs_hook) (n);
+}
+
+void
+tty_delete_glyphs (int n)
+{
+  char *buf;
+  register int i;
+  struct frame *f = (updating_frame
+                     ? updating_frame
+                     : XFRAME (selected_frame));
+
+  struct tty_display_info *tty = FRAME_TTY (f);
 
   if (tty->delete_in_insert_mode)
     {
@@ -930,73 +991,79 @@
 ins_del_lines (vpos, n)
      int vpos, n;
 {
-  struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
+  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);
+}
+
+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)
     {
-      (*FRAME_DISPLAY (f)->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_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)
-        {
-          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 (!FRAME_SCROLL_REGION_OK (f)
-          && FRAME_MEMORY_BELOW_FRAME (f)
-          && 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 ();
     }
 }
 
@@ -1809,6 +1876,48 @@
   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.  */
 
@@ -1818,13 +1927,11 @@
      (display)
      Lisp_Object display;
 {
-  struct tty_display_info *tty;
-
-  if (! FRAMEP (display))
+  struct display *d = get_tty_display (display);
+  if (!d)
     return Qnil;
-  
-  tty = FRAME_TTY (XFRAME (display));
-  return tty->TN_max_colors > 0 ? Qt : Qnil;
+  else
+    return d->display_info.tty->TN_max_colors > 0 ? Qt : Qnil;
 }
 
 /* Return the number of supported colors.  */
@@ -1834,13 +1941,11 @@
      (display)
      Lisp_Object display;
 {
-  struct tty_display_info *tty;
-
-  if (! FRAMEP (display))
+  struct display *d = get_tty_display (display);
+  if (!d)
     return Qnil;
-  
-  tty = FRAME_TTY (XFRAME (display));
-  return make_number (tty->TN_max_colors);
+  else
+    return make_number (d->display_info.tty->TN_max_colors);
 }
 
 #ifndef WINDOWSNT
@@ -1982,7 +2087,7 @@
 
 
 
-static struct display *
+struct display *
 get_named_tty_display (name)
      char *name;
 {
@@ -2058,33 +2163,50 @@
 			    Initialization
  ***********************************************************************/
 
+/* Create the bootstrap display device for the initial frame.
+
+Returns a display of type output_initial. */
 struct display *
-initial_term_init (void)
+init_initial_display (void)
 {
+  struct tty_display_info *tty;
+  
   if (initialized || display_list || tty_list)
     abort ();
 
-  display_list = create_display ();
-
-  tty_list = xmalloc (sizeof (struct tty_display_info));
-  bzero (tty_list, sizeof (struct tty_display_info));
-  tty_list->name = 0;
-  tty_list->input = stdin;
-  tty_list->output = stdout;
-  tty_list->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
-#ifdef MULTI_KBOARD
-  tty_list->kboard = initial_kboard;
-#endif
+  initial_display = create_display ();
+  initial_display->type = output_initial;
+  
+  initial_display->delete_display_hook = &delete_initial_display;
+  /* All other hooks are NULL. */
   
-  display_list->type = output_termcap;
-  display_list->display_info.tty = tty_list;
-  
-  return display_list;
+  return initial_display;
+}
+
+/* Deletes the bootstrap display device.
+   Called through delete_display_hook. */
+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)
+term_init (char *name, char *terminal_type, int must_succeed)
 {
   char *area;
   char **address = &area;
@@ -2095,39 +2217,65 @@
   struct tty_display_info *tty;
   struct display *display;
 
+  static void maybe_fatal();
+
+  if (!terminal_type)
+    maybe_fatal (must_succeed, 0, 0,
+                 "Unknown terminal type",
+                 "Unknown terminal type");
+  
   display = get_named_tty_display (name);
   if (display)
-    {
-      tty = display->display_info.tty;
-
-      /* Return the previously initialized terminal, except if it is
-         the dummy terminal created for the initial frame. */
-      if (tty->type)
-        return display;
-
-      /* Free up temporary structures. */
-      if (tty->Wcm)
-        xfree (tty->Wcm);
-      if (tty->kboard != initial_kboard)
-        abort ();
-      tty->kboard = 0;
-    }
-  else
-    {
-      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;
-
-      display->type = output_termcap;
-      display->display_info.tty = tty;
-    }
+    return display;             /* We have already opened a display there. */
+
+  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;
+
+  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 = 0; /* Not needed. */
+  display->frame_up_to_date_hook = 0; /* Not needed. */
+  
   display->delete_frame_hook = &delete_tty_output;
   display->delete_display_hook = &delete_tty;
   
@@ -2196,55 +2344,35 @@
   if (status < 0)
     {
 #ifdef TERMINFO
-      if (name)
-        {
-          xfree (buffer);
-          delete_tty (display);
-          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)
-        {
-          xfree (buffer);
-          delete_tty (display);
-          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)
-        {
-          xfree (buffer);
-          delete_tty (display);
-          error ("Terminal type %s is not defined", terminal_type);
-        }
-      else
-        fatal ("Terminal type %s is not defined.\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)
-        {
-          xfree (buffer);
-          delete_tty (display);
-          error ("Terminal type %s is not defined", terminal_type);
-        }
-      else
-        fatal ("Terminal type %s is not defined.\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
     }
 
@@ -2384,19 +2512,10 @@
     FrameRows (tty) = tgetnum ("li");
 
   if (FrameRows (tty) < 3 || FrameCols (tty) < 3)
-    {
-      if (initialized)
-        {
-          delete_tty (display);
-          error ("Screen size %dx%d is too small",
+    maybe_fatal (must_succeed, NULL, display,
+                 "Screen size %dx%d is too small"
+                 "Screen size %dx%d is too small",
                  FrameCols (tty), FrameRows (tty));
-        }
-      else
-        {
-          fatal ("Screen size %dx%d is too small",
-                 FrameCols (tty), FrameRows (tty));
-        }
-    }
 
 #if 0  /* This is not used anywhere. */
   tty->display->min_padding_speed = tgetnum ("pb");
@@ -2525,51 +2644,39 @@
   tty->specified_window = FrameRows (tty);
 
   if (Wcm_init (tty) == -1)	/* can't do cursor motion */
-    if (name)
-      {
-        delete_tty (display);
-        error ("Terminal type \"%s\" is not powerful enough to run Emacs",
-               terminal_type);
-      }
-    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\
+                   "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\
+                   "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 */
+                   terminal_type);
     }
 
   if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
-    {
-      if (name)
-        {
-          delete_tty (display);
-          error ("The frame size has not been specified");
-        }
-      else
-        fatal ("The frame size has not been specified");
-    }
+    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
@@ -2635,6 +2742,31 @@
 #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);
+
+  if (display)
+    delete_tty (display);
+  
+  if (must_succeed)
+    fatal (str2, arg1, arg2);
+  else
+    error (str1, arg1, arg2);
+
+  abort ();
+}
+
 /* VARARGS 1 */
 void
 fatal (str, arg1, arg2)
@@ -2725,10 +2857,12 @@
         }
     }
 
+  /* reset_sys_modes needs a valid display, so this call needs to be
+     before delete_display. */
+  reset_sys_modes (tty);
+
   delete_display (display);
 
-  reset_sys_modes (tty);
-
   tty_name = tty->name;
   if (tty->type)
     xfree (tty->type);
--- a/src/termchar.h	Fri Jan 09 13:12:28 2004 +0000
+++ b/src/termchar.h	Fri Jan 09 18:57:53 2004 +0000
@@ -52,6 +52,9 @@
 
 
   int reference_count;          /* Number of frames that are on this display. */
+
+  struct display *display;      /* Points back to the generic display
+                                   structure.  This is sometimes handy. */
   
   /* Info on cursor positioning.  */
   struct cm *Wcm;
--- a/src/termhooks.h	Fri Jan 09 13:12:28 2004 +0000
+++ b/src/termhooks.h	Fri Jan 09 18:57:53 2004 +0000
@@ -344,8 +344,8 @@
   
   void (*ring_bell_hook) P_ ((void));
   
-  void (*reset_terminal_modes_hook) P_ ((void));
-  void (*set_terminal_modes_hook) P_ ((void));
+  void (*reset_terminal_modes_hook) P_ ((struct display *));
+  void (*set_terminal_modes_hook) P_ ((struct display *));
   void (*update_begin_hook) P_ ((struct frame *));
   void (*update_end_hook) P_ ((struct frame *));
   void (*set_terminal_window_hook) P_ ((int));
--- a/src/window.c	Fri Jan 09 13:12:28 2004 +0000
+++ b/src/window.c	Fri Jan 09 18:57:53 2004 +0000
@@ -6394,7 +6394,7 @@
 void
 init_window_once ()
 {
-  struct frame *f = make_terminal_frame (0, 0);
+  struct frame *f = make_initial_frame ();
   XSETFRAME (selected_frame, f);
   Vterminal_frame = selected_frame;
   minibuf_window = f->minibuffer_window;
--- a/src/xfaces.c	Fri Jan 09 13:12:28 2004 +0000
+++ b/src/xfaces.c	Fri Jan 09 18:57:53 2004 +0000
@@ -6728,7 +6728,7 @@
 	LFACE_FOREGROUND (lface) = XCDR (color);
       else if (FRAME_WINDOW_P (f))
 	return 0;
-      else if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
+      else if (FRAME_INITIAL_P (f) || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
 	LFACE_FOREGROUND (lface) = build_string (unspecified_fg);
       else
 	abort ();
@@ -6743,7 +6743,7 @@
 	LFACE_BACKGROUND (lface) = XCDR (color);
       else if (FRAME_WINDOW_P (f))
 	return 0;
-      else if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
+      else if (FRAME_INITIAL_P (f) || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
 	LFACE_BACKGROUND (lface) = build_string (unspecified_bg);
       else
 	abort ();
@@ -6830,7 +6830,7 @@
 
   if (FRAME_WINDOW_P (cache->f))
     face = realize_x_face (cache, attrs, c, base_face);
-  else if (FRAME_TERMCAP_P (cache->f) || FRAME_MSDOS_P (cache->f))
+  else if (FRAME_INITIAL_P (cache->f) || FRAME_TERMCAP_P (cache->f) || FRAME_MSDOS_P (cache->f))
     face = realize_tty_face (cache, attrs, c);
   else
     abort ();
--- a/src/xterm.c	Fri Jan 09 13:12:28 2004 +0000
+++ b/src/xterm.c	Fri Jan 09 18:57:53 2004 +0000
@@ -331,8 +331,8 @@
 static int x_compute_min_glyph_bounds P_ ((struct frame *));
 static void x_update_end P_ ((struct frame *));
 static void XTframe_up_to_date P_ ((struct frame *));
-static void XTset_terminal_modes P_ ((void));
-static void XTreset_terminal_modes P_ ((void));
+static void XTset_terminal_modes P_ ((struct display *));
+static void XTreset_terminal_modes P_ ((struct display *));
 static void x_clear_frame P_ ((void));
 static void frame_highlight P_ ((struct frame *));
 static void frame_unhighlight P_ ((struct frame *));
@@ -747,7 +747,7 @@
    rarely happens).  */
 
 static void
-XTset_terminal_modes ()
+XTset_terminal_modes (struct display *display)
 {
 }
 
@@ -755,7 +755,7 @@
    the X-windows go away, and suspending requires no action.  */
 
 static void
-XTreset_terminal_modes ()
+XTreset_terminal_modes (struct display *display)
 {
 }