changeset 53226:dd3018b4785b

Implemented multiple tty support. README.multi-tty: New file. src/termchar.h (struct terminal): Renamed to struct tty_output. Added name, type, input, output, termscript, old_tty, term_initted, old_tty_valid, background_pixel, foreground_pixel, next fields. (TERMINAL_*): Renamed to TTY_* for brevity. (CURRENT_TERMINAL): Renamed to CURTTY for brevity. (tty_list): New variable. (TERMINAL_PTR): Removed. (FRAME_TTY): New function. (TTY_NAME, TTY_TYPE): New macros. src/term.c (current_terminal): Removed. (_current_terminal): Removed. (tty_list): New variable. (OUTPUT, OUTPUT1, OUTPUTL, OUTPUT_IF, OUTPUT1_IF): Added tty parameter. (set_terminal_modes): Added tty parameter. (reset_terminal_modes): Added tty parameter. (cursor_to, raw_cursor_to): Updated cmgoto() calls. (clear_end_of_line, write_glyphs): Add indirection to terminal output, updated cmcheckmagic() calls. (get_named_tty): New function. (term_dummy_init): New function. (term_init): Added name parameter, added tty_output return value. Changed algorithm to update tty_list. Call init_sys_modes() to set up tty mode on the newly opened terminal device. (get_current_tty): New function, intended for debugging. src/termhooks.h (termscript): Removed. src/w32term.h (FRAME_FOREGROUND_PIXEL, FRAME_BACKGROUND_PIXEL): Removed redundant definition. src/macterm.h (FRAME_FOREGROUND_PIXEL, FRAME_BACKGROUND_PIXEL): Ditto. src/window.c (init_window_once): Call make_terminal_frame with two zero parameters. src/cm.h (emacs_tputs): New macro to set current_tty, and then call tputs(). (current_tty): New variable, for cmputc(). (cmcheckmagic, cmputc, cmgoto): Added prototypes. src/cm.c (current_tty): New variable, for cmputc(). (cmputc): Use it. (cmcheckmagic): Added tty parameter, look up terminal streams there. (calccost): Added tty parameter. Use emacs_tputs() instead of tputs(). (cmgoto): Added tty parameter. Pass it on to calccost(). Use emacs_tputs() instead of tputs(). src/dispextern.h (set_terminal_modes, reset_terminal_modes): Added tty parameter. (term_init): Added name parameter (the filename of the terminal device). Added return value (struct tty_output). src/dispnew.c: Replace CURTTY() with local variables throughout the file (where applicable). (termscript): Moved to struct tty_output. (terminal_type): Removed. src/emacs.c (main): Don't call init_sys_modes(), the new term_init() already does that during init_display(). (shut_down_emacs): Call reset_all_sys_modes() instead of reset_sys_modes(). src/frame.c (Qtty, Qtty_type): New variables. (syms_of_frame): Initialize them. (tty_display): Removed. (make_terminal_frame): New parameters (tty filename and type). Initialize output_data.tty field instead of output_data.x. Use term_init() to find the right tty_output. (Use term_dummy_init() during bootstrap.) (Fmake_terminal_frame): Get device filename and type from frame parameters. src/frame.h (FRAME_FOREGROUND_PIXEL, FRAME_BACKGROUND_PIXEL): Do the right thing if the frame is a tty. (struct frame): New member in output_data: tty. (make_terminal_frame): Updated of prototype. src/keyboard.c (Fset_input_mode): Call reset_all_sys_modes(), not reset_sys_modes(). Ditto with init_sys_modes(). src/lisp.h (tty_output): Added forward declaration. (init_sys_modes, reset_sys_modes): Updated prototype. (init_all_sys_modes, reset_all_sys_modes): New prototypes. src/scroll.c: Replace CURTTY() with local variables throughout the file (where applicable). src/sysdep.c (old_tty, term_initted, old_tty_valid): Moved to struct tty_output.( (init_all_sys_modes): New function. (init_sys_modes): Added tty_output parameter. Use it. (reset_all_sys_modes): New function. (reset_sys_modes): Added tty_output parameter. Use it. src/Makefile.in: Update dependencies. git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-2
author Karoly Lorentey <lorentey@elte.hu>
date Thu, 25 Dec 2003 06:59:31 +0000
parents 4250e7e26247
children 1595c5e1e9bb
files README.multi-tty src/Makefile.in src/cm.c src/cm.h src/dispextern.h src/dispnew.c src/emacs.c src/frame.c src/frame.h src/indent.c src/keyboard.c src/lisp.h src/macterm.c src/macterm.h src/msdos.c src/print.c src/scroll.c src/sysdep.c src/term.c src/termchar.h src/termhooks.h src/w32term.c src/w32term.h src/window.c src/xdisp.c src/xfaces.c src/xfns.c
diffstat 27 files changed, 682 insertions(+), 307 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README.multi-tty	Thu Dec 25 06:59:31 2003 +0000
@@ -0,0 +1,129 @@
+			-*- coding: utf-8; -*-
+GOAL
+----
+
+The ultimate goal of this branch is to implement support for opening
+multiple, different tty devices and simultaneous X and tty frames from
+a single Emacs session.
+
+WHO IS DOING IT
+---------------
+
+I'm Károly Lőrentey.  My address: lorentey@elte.hu.
+
+Patches or suggestions are welcome!
+
+
+STATUS
+------
+
+We can create frames on new tty devices, but there are problems with
+refresh (only the (single) selected frame is refreshed), and input is
+read only from the initial terminal.  At the moment, the type of the
+new terminals must be the same as the initial terminal.
+
+To try it out, start up emacs, and evaluate the following:
+
+	(make-terminal-frame '((tty . "/dev/pts/5") (tty-type . "xterm")))
+
+(With your own values, of course.)  If you switch to the new frame
+with M-x other-frame, the new tty is refreshed with the frame
+contents.  The result of input from the original terminal appears on
+the new.  If you exit emacs, both terminals are restored to their
+previous states.
+
+X, Mac, Windows and DOS support is broken.
+
+NEWS
+----
+
+For the NEWS file:
+
+** Support for multiple terminal devices has been added.  You can
+   specify a terminal device (`tty' parameter) and a terminal type
+   (`tty-type' parameter) to `make-terminal-frame'.
+
+
+CHANGELOG
+---------
+
+See arch logs.
+
+
+THINGS THAT ARE DONE
+--------------------
+
+-- Introduce a new abstraction for terminal devices.  
+
+   (Done, see struct tty_output.  The abstraction is not yet
+   complete.)
+
+
+-- Change the bootstrap procedure to initialize tty_list.
+
+   (Done, but needs review.)
+
+
+-- Change make-terminal-frame to support specifying another tty.
+
+   (Done, new frame parameters: `tty' and `tty-type'.)
+
+
+THINGS TO DO
+------------
+
+** Make make-terminal-frame look up the tty and tty-type parameters
+   from the currently selected terminal before the global default.
+
+** Move optimalization parameters (costs) from union output_data to
+   struct frame.
+
+** Implement terminal deletion, i.e., closing the tty device and
+   restoring its previous state without exiting Emacs.  This should be
+   exported to the Lisp interpreter.
+
+** Implement automatic deletion of terminals, when the last frame on
+   that terminal is closed.
+
+** Put all cached terminal escape sequences into struct tty_output.
+   Currently, they are still stored in global variables, so we don't
+   really support multiple terminal types.
+
+** Support different terminal sizes.  (Should be solved by the
+   previous entry.)
+
+** Make sure terminal resizes are handled gracefully.  (Could be
+   problematic.)
+
+** Implement support for reading from multiple terminals.
+
+** other-frame should cycle through the frames on the `current'
+   terminal.  This means that Emacs must know from which terminal the
+   last keyboard event came from.  (Multikeyboard support may help
+   with this.)
+
+** Redisplay must refresh the topmost on all terminals, not just
+   the initial terminal.
+
+** Make struct tty_output available from Lisp.
+
+** Extend emacsclient to automatically open a new tty when it connects
+   to Emacs.
+
+** Implement support for starting an interactive Emacs session without
+   an initial frame.  (The user would connect to it and open frames
+   later, with emacsclient.)  Not necessary a good idea.
+
+** Fix X support.
+
+** Allow simultaneous X and tty frames.
+
+** Fix Mac support (I can't do this myself).
+
+** Fix W32 support (I can't do this myself).
+
+** Fix DOS support (I can't do this myself).
+
+
+
+;;; arch-tag: 8da1619e-2e79-41a8-9ac9-a0485daad17d
--- a/src/Makefile.in	Wed Dec 24 18:55:24 2003 +0000
+++ b/src/Makefile.in	Thu Dec 25 06:59:31 2003 +0000
@@ -1047,7 +1047,7 @@
 charset.o: charset.c charset.h buffer.h coding.h composite.h disptab.h \
 	$(config_h)
 coding.o: coding.c coding.h ccl.h buffer.h charset.h intervals.h composite.h window.h $(config_h)
-cm.o: cm.c cm.h termhooks.h $(config_h)
+cm.o: cm.c frame.h cm.h termhooks.h systty.h termchar.h $(config_h)
 cmds.o: cmds.c syntax.h buffer.h charset.h commands.h window.h $(config_h) \
 	msdos.h dispextern.h
 pre-crt0.o: pre-crt0.c
@@ -1055,7 +1055,7 @@
 	CRT0_COMPILE ${srcdir}/ecrt0.c
 dired.o: dired.c commands.h buffer.h $(config_h) charset.h coding.h regex.h \
    systime.h
-dispnew.o: dispnew.c  systty.h systime.h commands.h process.h frame.h \
+dispnew.o: dispnew.c systty.h systime.h commands.h process.h frame.h \
    window.h buffer.h dispextern.h termchar.h termopts.h termhooks.h cm.h \
    disptab.h \
    xterm.h blockinput.h atimer.h charset.h msdos.h composite.h keyboard.h \
@@ -1073,12 +1073,12 @@
 filelock.o: filelock.c buffer.h systime.h epaths.h $(config_h)
 filemode.o: filemode.c  $(config_h)
 frame.o: frame.c xterm.h window.h frame.h termhooks.h commands.h keyboard.h \
-   blockinput.h atimer.h systime.h buffer.h charset.h fontset.h \
+   blockinput.h systty.h atimer.h systime.h buffer.h charset.h fontset.h \
    msdos.h dosfns.h dispextern.h $(config_h)
 fontset.o: dispextern.h fontset.h fontset.c ccl.h buffer.h charset.h frame.h \
    keyboard.h $(config_h)
 getloadavg.o: getloadavg.c $(config_h)
-indent.o: indent.c frame.h window.h indent.h buffer.h $(config_h) termchar.h \
+indent.o: indent.c frame.h window.h systty.h indent.h buffer.h $(config_h) termchar.h \
    termopts.h disptab.h region-cache.h charset.h composite.h dispextern.h \
    keyboard.h
 insdel.o: insdel.c window.h buffer.h $(INTERVAL_SRC) blockinput.h charset.h \
@@ -1110,7 +1110,7 @@
    keyboard.h $(config_h)
 regex.o: regex.c syntax.h buffer.h $(config_h) regex.h category.h charset.h
 region-cache.o: region-cache.c buffer.h region-cache.h
-scroll.o: scroll.c termchar.h dispextern.h frame.h msdos.h keyboard.h \
+scroll.o: scroll.c systty.h termchar.h dispextern.h frame.h msdos.h keyboard.h \
    $(config_h)
 search.o: search.c regex.h commands.h buffer.h region-cache.h syntax.h \
    blockinput.h atimer.h systime.h category.h charset.h composite.h $(config_h)
@@ -1120,7 +1120,7 @@
 sysdep.o: sysdep.c syssignal.h systty.h systime.h syswait.h blockinput.h \
    process.h dispextern.h termhooks.h termchar.h termopts.h \
    frame.h atimer.h window.h msdos.h dosfns.h keyboard.h  $(config_h)
-term.o: term.c termchar.h termhooks.h termopts.h $(config_h) cm.h frame.h \
+term.o: term.c systty.h termchar.h termhooks.h termopts.h $(config_h) cm.h frame.h \
    disptab.h dispextern.h keyboard.h charset.h coding.h ccl.h msdos.h
 termcap.o: termcap.c $(config_h)
 terminfo.o: terminfo.c $(config_h)
@@ -1134,17 +1134,18 @@
    msdos.h $(config_h)
 widget.o: widget.c xterm.h frame.h dispextern.h widgetprv.h \
    $(srcdir)/../lwlib/lwlib.h $(config_h)
-window.o: window.c indent.h commands.h frame.h window.h buffer.h termchar.h \
+window.o: window.c indent.h commands.h frame.h window.h buffer.h systty.h termchar.h \
    termhooks.h disptab.h keyboard.h dispextern.h msdos.h composite.h \
    $(config_h)
 xdisp.o: xdisp.c macros.h commands.h process.h indent.h buffer.h dispextern.h coding.h \
-   termchar.h frame.h window.h disptab.h termhooks.h charset.h $(config_h) \
+   systty.h termchar.h frame.h window.h disptab.h termhooks.h charset.h $(config_h) \
    msdos.h composite.h fontset.h blockinput.h atimer.h systime.h keymap.h
 xfaces.o: xfaces.c dispextern.h frame.h xterm.h buffer.h blockinput.h \
-   window.h charset.h msdos.h dosfns.h composite.h atimer.h systime.h $(config_h)
+   window.h charset.h msdos.h dosfns.h composite.h atimer.h systime.h \
+   systty.h termchar.h $(config_h)
 xfns.o: xfns.c buffer.h frame.h window.h keyboard.h xterm.h dispextern.h \
    $(srcdir)/../lwlib/lwlib.h blockinput.h atimer.h systime.h epaths.h \
-   charset.h gtkutil.h $(config_h)
+   charset.h gtkutil.h systty.h termchar.h $(config_h)
 xmenu.o: xmenu.c xterm.h termhooks.h window.h dispextern.h frame.h buffer.h \
    keyboard.h $(srcdir)/../lwlib/lwlib.h blockinput.h atimer.h systime.h \
    gtkutil.h msdos.h coding.h $(config_h)
@@ -1176,7 +1177,7 @@
 fns.o: fns.c commands.h $(config_h) frame.h buffer.h charset.h keyboard.h \
  frame.h window.h dispextern.h $(INTERVAL_SRC) coding.h md5.h
 print.o: print.c process.h frame.h window.h buffer.h keyboard.h charset.h \
-   $(config_h) dispextern.h msdos.h composite.h
+   $(config_h) dispextern.h msdos.h composite.h systty.h termchar.h intervals.h
 lread.o: lread.c commands.h keyboard.h buffer.h epaths.h charset.h $(config_h) \
  termhooks.h coding.h msdos.h
 
--- a/src/cm.c	Wed Dec 24 18:55:24 2003 +0000
+++ b/src/cm.c	Thu Dec 25 06:59:31 2003 +0000
@@ -22,8 +22,16 @@
 
 #include <config.h>
 #include <stdio.h>
+
+/* For CURTTY */
+#include "lisp.h"
+#include "frame.h"
+
 #include "cm.h"
 #include "termhooks.h"
+#include "systty.h" /* For emacs_tty in termchar.h */
+#include "termchar.h"
+
 
 /* For now, don't try to include termcap.h.  On some systems,
    configure finds a non-standard termcap.h that the main build
@@ -41,6 +49,7 @@
 
 extern char *BC, *UP;
 
+
 int cost;		/* sums up costs */
 
 /* ARGSUSED */
@@ -52,13 +61,16 @@
   return c;
 }
 
+/* The terminal to use for low-level output. */
+struct tty_output * current_tty;
+
 int
 cmputc (c)
      char c;
 {
-  if (termscript)
-    fputc (c & 0177, termscript);
-  putchar (c & 0177);
+  if (TTY_TERMSCRIPT (current_tty))
+    putc (c & 0177, TTY_TERMSCRIPT (current_tty));
+  putc (c & 0177, TTY_OUTPUT (current_tty));
   return c;
 }
 
@@ -122,18 +134,19 @@
  * after we reach the last column; this takes us to a known state.
  */
 void
-cmcheckmagic ()
+cmcheckmagic (tty)
+     struct tty_output *tty;
 {
   if (curX == FrameCols)
     {
       if (!MagicWrap || curY >= FrameRows - 1)
 	abort ();
-      if (termscript)
-	putc ('\r', termscript);
-      putchar ('\r');
-      if (termscript)
-	putc ('\n', termscript);
-      putchar ('\n');
+      if (TTY_TERMSCRIPT (tty))
+	putc ('\r', TTY_TERMSCRIPT (tty));
+      putc ('\r', TTY_OUTPUT (tty));
+      if (TTY_TERMSCRIPT (tty))
+	putc ('\n', TTY_TERMSCRIPT (tty));
+      putc ('\n', TTY_OUTPUT (tty));
       curX = 0;
       curY++;
     }
@@ -187,8 +200,7 @@
  */
 
 static int
-calccost (srcy, srcx, dsty, dstx, doit)
-     int srcy, srcx, dsty, dstx, doit;
+calccost (struct tty_output *tty, int srcy, int srcx, int dsty, int dstx, int doit)
 {
     register int    deltay,
                     deltax,
@@ -223,7 +235,7 @@
     totalcost = c * deltay;
     if (doit)
 	while (--deltay >= 0)
-	    tputs (p, 1, cmputc);
+          emacs_tputs (tty, p, 1, cmputc);
 x:
     if ((deltax = dstx - srcx) == 0)
 	goto done;
@@ -278,7 +290,7 @@
 	totalcost += tabcost;	/* use the tabs */
 	if (doit)
 	    while (--ntabs >= 0)
-		tputs (Wcm.cm_tab, 1, cmputc);
+              emacs_tputs (tty, Wcm.cm_tab, 1, cmputc);
 	srcx = tabx;
     }
 
@@ -305,7 +317,7 @@
     totalcost += c * deltax;
     if (doit)
 	while (--deltax >= 0)
-	    tputs (p, 1, cmputc);
+          emacs_tputs (tty, p, 1, cmputc);
 done:
     return totalcost;
 }
@@ -323,7 +335,8 @@
 #define	USECR	3
 
 void
-cmgoto (row, col)
+cmgoto (tty, row, col)
+     struct tty_output *tty;
      int row, col;
 {
     int     homecost,
@@ -346,24 +359,24 @@
        * start where we are.  Examine the options, and pick the cheapest.
        */
 
-      relcost = calccost (curY, curX, row, col, 0);
+      relcost = calccost (tty, curY, curX, row, col, 0);
       use = USEREL;
       if ((homecost = Wcm.cc_home) < BIG)
-	  homecost += calccost (0, 0, row, col, 0);
+          homecost += calccost (tty, 0, 0, row, col, 0);
       if (homecost < relcost)
-	  relcost = homecost, use = USEHOME;
+          relcost = homecost, use = USEHOME;
       if ((llcost = Wcm.cc_ll) < BIG)
-	  llcost += calccost (Wcm.cm_rows - 1, 0, row, col, 0);
+          llcost += calccost (tty, Wcm.cm_rows - 1, 0, row, col, 0);
       if (llcost < relcost)
-	  relcost = llcost, use = USELL;
+          relcost = llcost, use = USELL;
       if ((crcost = Wcm.cc_cr) < BIG) {
 	  if (Wcm.cm_autolf)
 	      if (curY + 1 >= Wcm.cm_rows)
 		  crcost = BIG;
 	      else
-		  crcost += calccost (curY + 1, 0, row, col, 0);
+                  crcost += calccost (tty, curY + 1, 0, row, col, 0);
 	  else
-	      crcost += calccost (curY, 0, row, col, 0);
+	      crcost += calccost (tty, curY, 0, row, col, 0);
       }
       if (crcost < relcost)
 	  relcost = crcost, use = USECR;
@@ -389,10 +402,10 @@
       cost = 0;
       p = dcm == Wcm.cm_habs ? tgoto (dcm, row, col) :
 			       tgoto (dcm, col, row);
-      tputs (p, 1, evalcost);
+      emacs_tputs (tty, p, 1, evalcost);
       if (cost <= relcost)
 	{	/* really is cheaper */
-	  tputs (p, 1, cmputc);
+	  emacs_tputs (tty, p, 1, cmputc);
 	  curY = row, curX = col;
 	  return;
 	}
@@ -401,24 +414,24 @@
   switch (use)
     {
     case USEHOME:
-      tputs (Wcm.cm_home, 1, cmputc);
+      emacs_tputs (tty, Wcm.cm_home, 1, cmputc);
       curY = 0, curX = 0;
       break;
 
     case USELL:
-      tputs (Wcm.cm_ll, 1, cmputc);
+      emacs_tputs (tty, Wcm.cm_ll, 1, cmputc);
       curY = Wcm.cm_rows - 1, curX = 0;
       break;
 
     case USECR:
-      tputs (Wcm.cm_cr, 1, cmputc);
+      emacs_tputs (tty, Wcm.cm_cr, 1, cmputc);
       if (Wcm.cm_autolf)
 	curY++;
       curX = 0;
       break;
     }
 
-  (void) calccost (curY, curX, row, col, 1);
+  (void) calccost (tty, curY, curX, row, col, 1);
   curY = row, curX = col;
 }
 
--- a/src/cm.h	Wed Dec 24 18:55:24 2003 +0000
+++ b/src/cm.h	Thu Dec 25 06:59:31 2003 +0000
@@ -162,10 +162,13 @@
 extern int cost;
 extern int evalcost ();
 
-extern void cmcheckmagic ();
-extern int cmputc ();
+#define emacs_tputs(tty, str, affcnt, putc) (current_tty = (tty), tputs (str, affcnt, putc))
+
+extern struct tty_output *current_tty;
+extern void cmcheckmagic P_ ((struct tty_output *));
+extern int cmputc P_ ((int));
 extern void cmcostinit ();
-extern void cmgoto ();
+extern void cmgoto P_ ((struct tty_output *, int, int));
 extern void Wcm_clear ();
 extern int Wcm_init ();
 
--- a/src/dispextern.h	Wed Dec 24 18:55:24 2003 +0000
+++ b/src/dispextern.h	Thu Dec 25 06:59:31 2003 +0000
@@ -2724,8 +2724,8 @@
 /* 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 set_terminal_modes P_ ((struct tty_output *));
+extern void reset_terminal_modes P_ ((struct tty_output *));
 extern void update_begin P_ ((struct frame *));
 extern void update_end P_ ((struct frame *));
 extern void set_terminal_window P_ ((int));
@@ -2743,7 +2743,8 @@
 extern void calculate_costs P_ ((struct frame *));
 extern void set_tty_color_mode P_ ((struct frame *, Lisp_Object));
 extern void tty_setup_colors P_ ((int));
-extern void term_init P_ ((char *));
+extern struct tty_output *term_init P_ ((char *, char *));
+extern struct tty_output *term_dummy_init P_ ((void));
 extern void fatal P_ ((/* char *, ... */));
 void cursor_to P_ ((int, int));
 extern int tty_capable_p P_ ((struct frame *, unsigned, unsigned long, unsigned long));
--- a/src/dispnew.c	Wed Dec 24 18:55:24 2003 +0000
+++ b/src/dispnew.c	Thu Dec 25 06:59:31 2003 +0000
@@ -29,6 +29,7 @@
 #endif
 
 #include "lisp.h"
+#include "systty.h"             /* For emacs_tty in termchar.h */
 #include "termchar.h"
 #include "termopts.h"
 #include "termhooks.h"
@@ -258,10 +259,6 @@
 
 struct frame *last_nonminibuf_frame;
 
-/* Stdio stream being used for copy of all output.  */
-
-FILE *termscript;
-
 /* Structure for info on cursor positioning.  */
 
 struct cm Wcm;
@@ -1397,7 +1394,7 @@
 	{
 	  int c = glyph->u.ch;
 	  int face_id = glyph->face_id;
-	  if (TERMINAL_MUST_WRITE_SPACES (CURRENT_TERMINAL ()))
+	  if (TTY_MUST_WRITE_SPACES (CURTTY ()))
 	    c -= SPACEGLYPH;
 	  hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + c;
 	  hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + face_id;
@@ -1429,7 +1426,7 @@
   int glyph_table_len = GLYPH_TABLE_LENGTH;
 
   /* Ignore trailing and leading spaces if we can.  */
-  if (!TERMINAL_MUST_WRITE_SPACES (CURRENT_TERMINAL ()))
+  if (!TTY_MUST_WRITE_SPACES (CURTTY ()))
     {
       /* Skip from the end over trailing spaces.  */
       while (end > beg && CHAR_GLYPH_SPACE_P (*(end - 1)))
@@ -1643,8 +1640,10 @@
 #if GLYPH_DEBUG
 
 
-/* Flush standard output.  This is sometimes useful to call from
-   the debugger.  */
+/* Flush standard output.  This is sometimes useful to call from the debugger.
+   XXX Maybe this should be changed to flush the current terminal instead of
+   stdout.
+*/
 
 void
 flush_stdout ()
@@ -3318,7 +3317,7 @@
 
   update_begin (f);
   if (FRAME_MSDOS_P (f))
-    set_terminal_modes ();
+    set_terminal_modes (0);
   clear_frame ();
   clear_current_matrices (f);
   update_end (f);
@@ -3462,7 +3461,7 @@
 
   /* If we can't insert glyphs, we can use this method only
      at the end of a line.  */
-  if (!TERMINAL_CHAR_INS_DEL_OK (CURRENT_TERMINAL ()))
+  if (!TTY_CHAR_INS_DEL_OK (CURTTY ()))
     if (PT != ZV && FETCH_BYTE (PT_BYTE) != '\n')
       return 0;
 
@@ -3841,9 +3840,9 @@
       paused_p = update_frame_1 (f, force_p, inhibit_hairy_id_p);
       update_end (f);
 
-      if (termscript)
-	fflush (termscript);
-      fflush (stdout);
+      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
@@ -5075,7 +5074,7 @@
     }
 
   /* If we cannot insert/delete lines, it's no use trying it.  */
-  if (!TERMINAL_LINE_INS_DEL_OK (CURRENT_TERMINAL ()))
+  if (!TTY_LINE_INS_DEL_OK (FRAME_TTY (f)))
     inhibit_id_p = 1;
 
   /* See if any of the desired lines are enabled; don't compute for
@@ -5293,7 +5292,7 @@
     }
 
   /* If changed lines are few, don't allow preemption, don't scroll.  */
-  if ((!TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ())
+  if ((!TTY_SCROLL_REGION_OK (FRAME_TTY (frame))
        && changed_lines < baud_rate / 2400)
       || unchanged_at_bottom == FRAME_LINES (frame))
     return 1;
@@ -5301,14 +5300,14 @@
   window_size = (FRAME_LINES (frame) - unchanged_at_top
 		 - unchanged_at_bottom);
 
-  if (TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ()))
+  if (TTY_SCROLL_REGION_OK (FRAME_TTY (frame)))
     free_at_end_vpos -= unchanged_at_bottom;
-  else if (TERMINAL_MEMORY_BELOW_FRAME (CURRENT_TERMINAL ()))
+  else if (TTY_MEMORY_BELOW_FRAME (FRAME_TTY (frame)))
     free_at_end_vpos = -1;
 
   /* If large window, fast terminal and few lines in common between
      current frame and desired frame, don't bother with i/d calc.  */
-  if (!TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ())
+  if (!TTY_SCROLL_REGION_OK (FRAME_TTY (frame))
       && window_size >= 18 && baud_rate > 2400
       && (window_size >=
 	  10 * scrolling_max_lines_saved (unchanged_at_top,
@@ -5389,7 +5388,7 @@
   struct glyph_row *current_row = MATRIX_ROW (current_matrix, vpos);
   struct glyph_row *desired_row = MATRIX_ROW (desired_matrix, vpos);
   int must_write_whole_line_p;
-  int write_spaces_p = TERMINAL_MUST_WRITE_SPACES (CURRENT_TERMINAL ());
+  int write_spaces_p = TTY_MUST_WRITE_SPACES (FRAME_TTY (f));
   int colored_spaces_p = (FACE_FROM_ID (f, DEFAULT_FACE_ID)->background
 			  != FACE_TTY_DEFAULT_BG_COLOR);
 
@@ -5468,7 +5467,7 @@
       nlen--;
 
   /* If there's no i/d char, quickly do the best we can without it.  */
-  if (!TERMINAL_CHAR_INS_DEL_OK (CURRENT_TERMINAL ()))
+  if (!TTY_CHAR_INS_DEL_OK (FRAME_TTY (f)))
     {
       int i, j;
 
@@ -5571,7 +5570,7 @@
 
   tem = (nlen - nsp) - (olen - osp);
   if (endmatch && tem
-      && (!TERMINAL_CHAR_INS_DEL_OK (CURRENT_TERMINAL ())
+      && (!TTY_CHAR_INS_DEL_OK (FRAME_TTY (f))
           || endmatch <= char_ins_del_cost (f)[tem]))
     endmatch = 0;
 
@@ -5581,7 +5580,7 @@
      Is it worth it?  */
 
   if (nsp != osp
-      && (!TERMINAL_CHAR_INS_DEL_OK (CURRENT_TERMINAL ())
+      && (!TTY_CHAR_INS_DEL_OK (FRAME_TTY (f))
 	  || begmatch + endmatch <= char_ins_del_cost (f)[nsp - osp]))
     {
       begmatch = 0;
@@ -6113,14 +6112,15 @@
      (file)
      Lisp_Object file;
 {
-  if (termscript != 0) fclose (termscript);
-  termscript = 0;
+  if (TTY_TERMSCRIPT (CURTTY ()) != 0)
+    fclose (TTY_TERMSCRIPT (CURTTY ()));
+  TTY_TERMSCRIPT (CURTTY ()) = 0;
 
   if (! NILP (file))
     {
       file = Fexpand_file_name (file, Qnil);
-      termscript = fopen (SDATA (file), "w");
-      if (termscript == 0)
+      TTY_TERMSCRIPT (CURTTY ()) = fopen (SDATA (file), "w");
+      if (TTY_TERMSCRIPT (CURTTY ()) == 0)
 	report_file_error ("Opening termscript", Fcons (file, Qnil));
     }
   return Qnil;
@@ -6136,14 +6136,15 @@
 {
   /* ??? Perhaps we should do something special for multibyte strings here.  */
   CHECK_STRING (string);
-  fwrite (SDATA (string), 1, SBYTES (string), stdout);
-  fflush (stdout);
-  if (termscript)
+  if (TTY_TERMSCRIPT (CURTTY ()))
     {
       fwrite (SDATA (string), 1, SBYTES (string),
-	      termscript);
-      fflush (termscript);
+	      TTY_TERMSCRIPT (CURTTY ()));
+      fflush (TTY_TERMSCRIPT (CURTTY ()));
     }
+  fwrite (SDATA (string), 1, SBYTES (string),
+          TTY_OUTPUT (CURTTY ()));
+  fflush (TTY_OUTPUT (CURTTY ()));
   return Qnil;
 }
 
@@ -6463,8 +6464,6 @@
 			    Initialization
 ***********************************************************************/
 
-char *terminal_type;
-
 /* Initialization done when Emacs fork is started, before doing stty.
    Determine terminal type and set terminal_driver.  Then invoke its
    decoding routine to set up variables in the terminal package.  */
@@ -6472,6 +6471,8 @@
 void
 init_display ()
 {
+  char *terminal_type;
+
 #ifdef HAVE_X_WINDOWS
   extern int display_arg;
 #endif
@@ -6593,7 +6594,7 @@
   }
 #endif /* VMS */
 
-  term_init (terminal_type);
+  term_init (0, terminal_type);
 
   {
     struct frame *sf = SELECTED_FRAME ();
--- a/src/emacs.c	Wed Dec 24 18:55:24 2003 +0000
+++ b/src/emacs.c	Thu Dec 25 06:59:31 2003 +0000
@@ -1566,7 +1566,7 @@
 #ifdef VMS
       init_vms_input ();/* init_display calls get_frame_size, that needs this.  */
 #endif /* VMS */
-      init_display ();	/* Determine terminal type.  init_sys_modes uses results.  */
+      init_display ();	/* Determine terminal type.  Calls init_sys_modes.  */
     }
 #ifndef MAC_OS8
   /* Called before init_window_once for Mac OS Classic.  */
@@ -1575,7 +1575,7 @@
 #ifdef VMS
   init_vmsproc ();	/* And this too.  */
 #endif /* VMS */
-  init_sys_modes ();	/* Init system terminal modes (RAW or CBREAK, etc.).  */
+  /* init_sys_modes (); */	/* Init system terminal modes (RAW or CBREAK, etc.).  */
 #if defined (HAVE_X_WINDOWS) || defined (WINDOWSNT)
   init_xfns ();
 #endif /* HAVE_X_WINDOWS */
@@ -1992,7 +1992,7 @@
 	&& tpgrp == pgrp)
       {
 	fflush (stdout);
-	reset_sys_modes ();
+	reset_all_sys_modes ();
 	if (sig && sig != SIGTERM)
 	  fprintf (stderr, "Fatal error (%d)", sig);
       }
--- a/src/frame.c	Wed Dec 24 18:55:24 2003 +0000
+++ b/src/frame.c	Thu Dec 25 06:59:31 2003 +0000
@@ -42,6 +42,8 @@
 #include "fontset.h"
 #endif
 #include "blockinput.h"
+#include "systty.h" /* For emacs_tty in termchar.h */
+#include "termchar.h"
 #include "termhooks.h"
 #include "dispextern.h"
 #include "window.h"
@@ -106,6 +108,7 @@
 Lisp_Object Qleft_fringe, Qright_fringe;
 Lisp_Object Qbuffer_predicate, Qbuffer_list;
 Lisp_Object Qtty_color_mode;
+Lisp_Object Qtty, Qtty_type;
 
 Lisp_Object Qfullscreen, Qfullwidth, Qfullheight, Qfullboth;
 
@@ -180,8 +183,6 @@
 Lisp_Object Vemacs_iconified;
 Lisp_Object Vframe_list;
 
-struct x_output tty_display;
-
 extern Lisp_Object Vminibuffer_list;
 extern Lisp_Object get_minibuffer ();
 extern Lisp_Object Fhandle_switch_frame ();
@@ -474,12 +475,14 @@
 }
 #endif /* HAVE_WINDOW_SYSTEM */
 
-/* Construct a frame that refers to the terminal (stdin and stdout).  */
+/* Construct a frame that refers to a terminal.  */
 
 static int terminal_frame_count;
 
 struct frame *
-make_terminal_frame ()
+make_terminal_frame (tty, tty_type)
+     char *tty;
+     char *tty_type;
 {
   register struct frame *f;
   Lisp_Object frame;
@@ -537,12 +540,16 @@
 #else
 #ifdef WINDOWSNT
   f->output_method = output_termcap;
-  f->output_data.x = &tty_display;
+  f->output_data.x = &tty_display; /* XXX */
 #else
 #ifdef MAC_OS8
   make_mac_terminal_frame (f);
 #else
-  f->output_data.x = &tty_display;
+  f->output_method = output_termcap;
+  if (initialized)
+    f->output_data.tty = term_init (tty, tty_type);
+  else
+    f->output_data.tty = term_dummy_init ();
 #ifdef CANNOT_DUMP
   FRAME_FOREGROUND_PIXEL(f) = FACE_TTY_DEFAULT_FG_COLOR;
   FRAME_BACKGROUND_PIXEL(f) = FACE_TTY_DEFAULT_BG_COLOR;
@@ -559,11 +566,19 @@
 
 DEFUN ("make-terminal-frame", Fmake_terminal_frame, Smake_terminal_frame,
        1, 1, 0,
-       doc: /* Create an additional terminal frame.
-You can create multiple frames on a text-only terminal in this way.
-Only the selected terminal frame is actually displayed.
+       doc: /* Create an additional terminal frame, possibly on another terminal.
 This function takes one argument, an alist specifying frame parameters.
-In practice, generally you don't need to specify any parameters.
+
+You can create multiple frames on a single text-only terminal, but
+only one of them (the selected terminal frame) is actually displayed.
+
+In practice, generally you don't need to specify any parameters,
+except when you want to create a new frame on another terminal.
+In that case, the `tty' parameter specifies the device file to open,
+and the `tty-type' parameter specifies the terminal type.  Example:
+
+   (make-terminal-frame '((tty . "/dev/pts/5") (tty-type . "xterm")))
+
 Note that changing the size of one terminal frame automatically affects all.  */)
      (parms)
      Lisp_Object parms;
@@ -587,7 +602,44 @@
 #endif
 #endif /* not MSDOS */
 
-  f = make_terminal_frame ();
+  { 
+    Lisp_Object tty, tty_type;
+    char *name = 0, *type = 0;
+
+    /* XXX Ugh, there must be a better way to do this. */
+    tty = Fassq (Qtty, parms);
+    if (EQ (tty, Qnil))
+      tty = Fassq (Qtty, Vdefault_frame_alist);
+    if (! EQ (tty, Qnil))
+      tty = XCDR (tty);
+    if (EQ (tty, Qnil) || !STRINGP (tty))
+      tty = Qnil;
+
+    tty_type = Fassq (Qtty_type, parms);
+    if (EQ (tty_type, Qnil))
+      tty_type = Fassq (Qtty_type, Vdefault_frame_alist);
+    if (! EQ (tty_type, Qnil))
+      tty_type = XCDR (tty_type);
+    if (EQ (tty_type, Qnil) || !STRINGP (tty_type))
+      tty_type = Qnil;
+
+    if (! EQ (tty, Qnil))
+      {
+        name = (char *) alloca (SBYTES (tty) + 1);
+        strncpy (name, SDATA (tty), SBYTES (tty));
+        name[SBYTES (tty)] = 0;
+      }
+
+    if (! EQ (tty_type, Qnil))
+      {
+        type = (char *) alloca (SBYTES (tty_type) + 1);
+        strncpy (type, SDATA (tty_type), SBYTES (tty_type));
+        type[SBYTES (tty_type)] = 0;
+      }
+
+    
+    f = make_terminal_frame (name, type);
+  }
 
   change_frame_size (f, FRAME_LINES (sf),
 		     FRAME_COLS (sf), 0, 0, 0);
@@ -3937,6 +3989,10 @@
   staticpro (&Qbackground_mode);
   Qtty_color_mode = intern ("tty-color-mode");
   staticpro (&Qtty_color_mode);
+  Qtty = intern ("tty");
+  staticpro (&Qtty);
+  Qtty_type = intern ("tty-type");
+  staticpro (&Qtty_type);
 
   Qface_set_after_frame_default = intern ("face-set-after-frame-default");
   staticpro (&Qface_set_after_frame_default);
--- a/src/frame.h	Wed Dec 24 18:55:24 2003 +0000
+++ b/src/frame.h	Thu Dec 25 06:59:31 2003 +0000
@@ -84,11 +84,15 @@
 #endif /* ! HAVE_X_WINDOWS */
 
 
-#define FRAME_FOREGROUND_PIXEL(f) ((f)->output_data.x->foreground_pixel)
-#define FRAME_BACKGROUND_PIXEL(f) ((f)->output_data.x->background_pixel)
+#define FRAME_FOREGROUND_PIXEL(f)             \
+  (((f)->output_method == output_termcap)     \
+   ? ((f)->output_data.tty->foreground_pixel) \
+   : ((f)->output_data.x->foreground_pixel))
 
-/* A structure describing a termcap frame display.  */
-extern struct x_output tty_display;
+#define FRAME_BACKGROUND_PIXEL(f)             \
+  (((f)->output_method == output_termcap)     \
+   ? ((f)->output_data.tty->background_pixel) \
+   : ((f)->output_data.x->background_pixel))
 
 #endif /* ! MSDOS && ! WINDOWSNT && ! MAC_OS */
 
@@ -283,12 +287,15 @@
   enum output_method output_method;
 
   /* A structure of auxiliary data used for displaying the contents.
+     struct tty_output is used for terminal frames;
+     it is defined in term.h.
      struct x_output is used for X window frames;
      it is defined in xterm.h.
      struct w32_output is used for W32 window frames;
      it is defined in w32term.h.  */
   union output_data
   {
+    struct tty_output *tty;
     struct x_output *x;
     struct w32_output *w32;
     struct mac_output *mac;
@@ -779,7 +786,7 @@
 
 extern struct frame *last_nonminibuf_frame;
 
-extern struct frame *make_terminal_frame P_ ((void));
+extern struct frame *make_terminal_frame P_ ((char *tty, char *tty_type));
 extern struct frame *make_frame P_ ((int));
 #ifdef HAVE_WINDOW_SYSTEM
 extern struct frame *make_minibuffer_frame P_ ((void));
--- a/src/indent.c	Wed Dec 24 18:55:24 2003 +0000
+++ b/src/indent.c	Thu Dec 25 06:59:31 2003 +0000
@@ -28,6 +28,7 @@
 #include "keyboard.h"
 #include "frame.h"
 #include "window.h"
+#include "systty.h" /* For emacs_tty in termchar.h */
 #include "termchar.h"
 #include "termopts.h"
 #include "disptab.h"
--- a/src/keyboard.c	Wed Dec 24 18:55:24 2003 +0000
+++ b/src/keyboard.c	Thu Dec 25 06:59:31 2003 +0000
@@ -22,6 +22,7 @@
 #include <config.h>
 #include <signal.h>
 #include <stdio.h>
+#include "systty.h" /* This must be included befor termchar.h. */
 #include "termchar.h"
 #include "termopts.h"
 #include "lisp.h"
@@ -55,7 +56,6 @@
 #endif /* not MSDOS */
 
 #include "syssignal.h"
-#include "systty.h"
 
 #include <sys/types.h>
 #ifdef HAVE_UNISTD_H
@@ -10067,7 +10067,7 @@
 
   GCPRO1 (stuffstring);
   get_frame_size (&old_width, &old_height);
-  reset_sys_modes ();
+  reset_all_sys_modes ();
   /* sys_suspend can get an error if it tries to fork a subshell
      and the system resources aren't available for that.  */
   record_unwind_protect ((Lisp_Object (*) P_ ((Lisp_Object))) init_sys_modes,
@@ -10206,7 +10206,7 @@
       sigblock (sigmask (SIGINT));
 
       fflush (stdout);
-      reset_sys_modes ();
+      reset_all_sys_modes ();
 
 #ifdef SIGTSTP			/* Support possible in later USG versions */
 /*
@@ -10285,7 +10285,7 @@
       printf ("Continuing...\n");
 #endif /* not MSDOS */
       fflush (stdout);
-      init_sys_modes ();
+      init_all_sys_modes ();
       sigfree ();
     }
   else
@@ -10372,7 +10372,7 @@
 
 #ifndef DOS_NT
   /* this causes startup screen to be restored and messes with the mouse */
-  reset_sys_modes ();
+  reset_all_sys_modes ();
 #endif
 
 #ifdef SIGIO
@@ -10410,7 +10410,7 @@
     quit_char = XINT (quit) & (meta_key ? 0377 : 0177);
 
 #ifndef DOS_NT
-  init_sys_modes ();
+  init_all_sys_modes ();
 #endif
 
 #ifdef POLL_FOR_INPUT
--- a/src/lisp.h	Wed Dec 24 18:55:24 2003 +0000
+++ b/src/lisp.h	Thu Dec 25 06:59:31 2003 +0000
@@ -2931,17 +2931,21 @@
 EXFUN (Fx_popup_dialog, 2);
 extern void syms_of_xmenu P_ ((void));
 
+/* defined in termchar.h */
+struct tty_output;
+
 /* defined in sysdep.c */
 extern void stuff_char P_ ((char c));
 extern void init_sigio P_ ((int));
 extern void request_sigio P_ ((void));
 extern void unrequest_sigio P_ ((void));
-extern void reset_sys_modes P_ ((void));
 extern void sys_subshell P_ ((void));
 extern void sys_suspend P_ ((void));
 extern void discard_tty_input P_ ((void));
-extern void init_sys_modes P_ ((void));
-extern void reset_sys_modes P_ ((void));
+extern void init_sys_modes P_ ((struct tty_output *));
+extern void reset_sys_modes P_ ((struct tty_output *));
+extern void init_all_sys_modes P_ ((void));
+extern void reset_all_sys_modes P_ ((void));
 extern void get_frame_size P_ ((int *, int *));
 extern void wait_for_termination P_ ((int));
 extern void flush_pending_output P_ ((int));
--- a/src/macterm.c	Wed Dec 24 18:55:24 2003 +0000
+++ b/src/macterm.c	Thu Dec 25 06:59:31 2003 +0000
@@ -8674,11 +8674,11 @@
   redeem_scroll_bar_hook = XTredeem_scroll_bar;
   judge_scroll_bars_hook = XTjudge_scroll_bars;
 
-  TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ()) = 1; /* we'll scroll partial frames */
-  TERMINAL_CHAR_INS_DEL_OK (CURRENT_TERMINAL ()) = 1;
-  TERMINAL_LINE_INS_DEL_OK (CURRENT_TERMINAL ()) = 1; /* we'll just blt 'em */
-  TERMINAL_FAST_CLEAR_END_OF_LINE (CURRENT_TERMINAL ()) = 1; /* X does this well */
-  TERMINAL_MEMORY_BELOW_FRAME (CURRENT_TERMINAL ()) = 0; /* we don't remember what
+  TTY_SCROLL_REGION_OK (CURTTY ()) = 1; /* we'll scroll partial frames */
+  TTY_CHAR_INS_DEL_OK (CURTTY ()) = 1;
+  TTY_LINE_INS_DEL_OK (CURTTY ()) = 1; /* we'll just blt 'em */
+  TTY_FAST_CLEAR_END_OF_LINE (CURTTY ()) = 1; /* X does this well */
+  TTY_MEMORY_BELOW_FRAME (CURTTY ()) = 0; /* we don't remember what
                                                          scrolls off the
                                                          bottom */
   baud_rate = 19200;
--- a/src/macterm.h	Wed Dec 24 18:55:24 2003 +0000
+++ b/src/macterm.h	Thu Dec 25 06:59:31 2003 +0000
@@ -406,9 +406,6 @@
 #define FRAME_MAC_WINDOW(f) ((f)->output_data.mac->mWP)
 #define FRAME_X_WINDOW(f) ((f)->output_data.mac->mWP)
 
-#define FRAME_FOREGROUND_PIXEL(f) ((f)->output_data.x->foreground_pixel)
-#define FRAME_BACKGROUND_PIXEL(f) ((f)->output_data.x->background_pixel)
-
 #define FRAME_FONT(f) ((f)->output_data.mac->font)
 #define FRAME_FONTSET(f) ((f)->output_data.mac->fontset)
 
--- a/src/msdos.c	Wed Dec 24 18:55:24 2003 +0000
+++ b/src/msdos.c	Thu Dec 25 06:59:31 2003 +0000
@@ -2580,7 +2580,7 @@
   set_terminal_modes_hook = IT_set_terminal_modes;
   reset_terminal_modes_hook = IT_reset_terminal_modes;
   set_terminal_window_hook = IT_set_terminal_window;
-  TERMINAL_CHAR_INS_DEL_OK (CURRENT_TERMINAL ()) = 0;
+  TTY_CHAR_INS_DEL_OK (CURTTY ()) = 0;
 #endif
 }
 
--- a/src/print.c	Wed Dec 24 18:55:24 2003 +0000
+++ b/src/print.c	Thu Dec 25 06:59:31 2003 +0000
@@ -30,6 +30,7 @@
 #include "window.h"
 #include "process.h"
 #include "dispextern.h"
+#include "systty.h" /* For emacs_tty in termchar.h */
 #include "termchar.h"
 #include "intervals.h"
 
--- a/src/scroll.c	Wed Dec 24 18:55:24 2003 +0000
+++ b/src/scroll.c	Thu Dec 25 06:59:31 2003 +0000
@@ -22,6 +22,7 @@
 #include <config.h>
 #include <stdio.h>
 #include <string.h>
+#include "systty.h" /* For emacs_tty in termchar.h */
 #include "termchar.h"
 #include "lisp.h"
 #include "dispextern.h"
@@ -101,7 +102,7 @@
   register int cost, cost1;
 
   int lines_moved = window_size
-    + (TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ()) ? 0 : lines_below);
+    + (TTY_SCROLL_REGION_OK (FRAME_TTY (frame)) ? 0 : lines_below);
   /* first_insert_cost[I] is the cost of doing the first insert-line
      at the i'th line of the lines we are considering,
      where I is origin 1 (as it is below).  */
@@ -468,7 +469,7 @@
      cost of scrolling by a distance of one.  The extra cost is
      added once for consistency with the cost vectors */
   scroll_overhead
-    = TERMINAL_SCROLL_REGION_COST (CURRENT_TERMINAL ()) + extra_cost;
+    = TTY_SCROLL_REGION_COST (FRAME_TTY (frame)) + extra_cost;
 
   /* initialize the top left corner of the matrix */
   matrix->writecost = 0;
@@ -820,7 +821,7 @@
   matrix = ((struct matrix_elt *)
 	    alloca ((window_size + 1) * (window_size + 1) * sizeof *matrix));
 
-  if (TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ()))
+  if (TTY_SCROLL_REGION_OK (FRAME_TTY (frame)))
     {
       calculate_direct_scrolling (frame, matrix, window_size,
 				  unchanged_at_bottom,
@@ -916,7 +917,7 @@
   if (amount == 0)
     return 0;
 
-  if (! TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ()))
+  if (! TTY_SCROLL_REGION_OK (FRAME_TTY (frame)))
     limit = height;
   else if (amount > 0)
     limit += amount;
--- a/src/sysdep.c	Wed Dec 24 18:55:24 2003 +0000
+++ b/src/sysdep.c	Thu Dec 25 06:59:31 2003 +0000
@@ -1255,14 +1255,6 @@
 }
 
 
-/* The initial tty mode bits */
-struct emacs_tty old_tty;
-
-/* 1 if we have been through init_sys_modes.  */
-int term_initted;
-
-/* 1 if outer tty status has been recorded.  */
-int old_tty_valid;
 
 #ifdef BSD4_1
 /* BSD 4.1 needs to keep track of the lmode bits in order to start
@@ -1298,7 +1290,18 @@
 #endif
 
 void
-init_sys_modes ()
+init_all_sys_modes (void)
+{
+  struct tty_output *tty = tty_list;
+  while (tty) {
+    init_sys_modes (tty);
+    tty = tty->next;
+  }
+}
+
+void
+init_sys_modes (otty)
+     struct tty_output *otty;
 {
   struct emacs_tty tty;
 
@@ -1367,14 +1370,14 @@
   if (!read_socket_hook && EQ (Vwindow_system, Qnil))
 #endif
     {
-      EMACS_GET_TTY (input_fd, &old_tty);
-
-      old_tty_valid = 1;
-
-      tty = old_tty;
+      EMACS_GET_TTY (input_fd, &otty->old_tty);
+
+      otty->old_tty_valid = 1;
+
+      tty = otty->old_tty;
 
 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
-      XSETINT (Vtty_erase_char, old_tty.main.c_cc[VERASE]);
+      XSETINT (Vtty_erase_char, otty->old_tty.main.c_cc[VERASE]);
 
 #ifdef DGUX
       /* This allows meta to be sent on 8th bit.  */
@@ -1539,7 +1542,7 @@
 	  tty.tchars.t_stopc = '\023';
 	}
 
-      tty.lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | old_tty.lmode;
+      tty.lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | otty->old_tty.lmode;
 #ifdef ultrix
       /* Under Ultrix 4.2a, leaving this out doesn't seem to hurt
 	 anything, and leaving it in breaks the meta key.  Go figure.  */
@@ -1557,7 +1560,7 @@
       tty.ltchars = new_ltchars;
 #endif /* HAVE_LTCHARS */
 #ifdef MSDOS	/* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
-      if (!term_initted)
+      if (!otty->term_initted)
 	internal_terminal_init ();
       dos_ttraw ();
 #endif
@@ -1646,14 +1649,14 @@
 #endif
       )
 #endif
-    set_terminal_modes ();
-
-  if (!term_initted
+    set_terminal_modes (otty);
+
+  if (!otty->term_initted
       && FRAMEP (Vterminal_frame)
       && FRAME_TERMCAP_P (XFRAME (Vterminal_frame)))
     init_frame_faces (XFRAME (Vterminal_frame));
 
-  if (term_initted && no_redraw_on_reenter)
+  if (otty->term_initted && no_redraw_on_reenter)
     {
       if (display_completed)
 	direct_output_forward_char (0);
@@ -1665,7 +1668,7 @@
 	FRAME_GARBAGED_P (XFRAME (Vterminal_frame)) = 1;
     }
 
-  term_initted = 1;
+  otty->term_initted = 1;
 }
 
 /* Return nonzero if safe to use tabs in output.
@@ -1778,10 +1781,21 @@
 }
 
 
+void
+reset_all_sys_modes (void)
+{
+  struct tty_output *tty = tty_list;
+  while (tty) {
+    reset_sys_modes (tty);
+    tty = tty->next;
+  }
+}
+
 /* Prepare the terminal for exiting Emacs; move the cursor to the
    bottom of the frame, turn off interrupt-driven I/O, etc.  */
 void
-reset_sys_modes ()
+reset_sys_modes (otty)
+     struct tty_output *otty;
 {
   struct frame *sf;
 
@@ -1790,7 +1804,7 @@
       fflush (stdout);
       return;
     }
-  if (!term_initted)
+  if (!otty->term_initted)
     return;
 #ifdef HAVE_WINDOW_SYSTEM
   /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
@@ -1820,7 +1834,7 @@
   }
 #endif
 
-  reset_terminal_modes ();
+  reset_terminal_modes (otty);
   fflush (stdout);
 #ifdef BSD_SYSTEM
 #ifndef BSD4_1
@@ -1848,8 +1862,8 @@
     reset_sigio ();
 #endif /* BSD4_1 */
 
-  if (old_tty_valid)
-    while (EMACS_SET_TTY (input_fd, &old_tty, 0) < 0 && errno == EINTR)
+  if (otty->old_tty_valid)
+    while (EMACS_SET_TTY (input_fd, &otty->old_tty, 0) < 0 && errno == EINTR)
       ;
 
 #ifdef MSDOS	/* Demacs 1.1.2 91/10/20 Manabu Higashida */
@@ -1860,7 +1874,7 @@
   /* Ultrix's termios *ignores* any line discipline except TERMIODISC.
      A different old line discipline is therefore not restored, yet.
      Restore the old line discipline by hand.  */
-  ioctl (0, TIOCSETD, &old_tty.main.c_line);
+  ioctl (0, TIOCSETD, &otty->old_tty.main.c_line);
 #endif
 
 #ifdef AIXHFT
@@ -3470,7 +3484,7 @@
      char *badfunc;
 {
   printf ("%s not yet implemented\r\n", badfunc);
-  reset_sys_modes ();
+  reset_all_sys_modes ();
   exit (1);
 }
 
@@ -5056,7 +5070,7 @@
      char *badfunc;
 {
   printf ("%s not yet implemented\r\n", badfunc);
-  reset_sys_modes ();
+  reset_all_sys_modes ();
   exit (1);
 }
 
@@ -5126,8 +5140,8 @@
   }
   /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly
      at times.  */
-  TERMINAL_LINE_INS_DEL_OK (CURRENT_TERMINAL ()) = 0;
-  TERMINAL_CHAR_INS_DEL_OK (CURRENT_TERMINAL ()) = 0;
+  TTY_LINE_INS_DEL_OK (CURTTY ()) = 0;
+  TTY_CHAR_INS_DEL_OK (CURTTY ()) = 0;
 }
 
 /* Reset the rubout key to backspace.  */
--- a/src/term.c	Wed Dec 24 18:55:24 2003 +0000
+++ b/src/term.c	Thu Dec 25 06:59:31 2003 +0000
@@ -26,6 +26,9 @@
 #include <ctype.h>
 #include <string.h>
 
+#include <sys/file.h>
+
+#include "systty.h" /* For emacs_tty in termchar.h */
 #include "termchar.h"
 #include "termopts.h"
 #include "lisp.h"
@@ -60,32 +63,36 @@
 #include "macterm.h"
 #endif
 
+#ifndef O_RDWR
+#define O_RDWR 2
+#endif
+
 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_ ((void));
 static void tty_hide_cursor P_ ((void));
 
-#define OUTPUT(a) \
-     tputs (a, (int) (FRAME_LINES (XFRAME (selected_frame)) - curY), cmputc)
-#define OUTPUT1(a) tputs (a, 1, cmputc)
-#define OUTPUTL(a, lines) tputs (a, lines, cmputc)
-
-#define OUTPUT_IF(a)							\
+#define OUTPUT(tty, a) \
+    emacs_tputs ((tty), a, (int) (FRAME_LINES (XFRAME (selected_frame)) - curY), cmputc)
+#define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
+#define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
+
+#define OUTPUT_IF(tty, a)                                               \
      do {								\
-       if (a)								\
-         tputs (a, (int) (FRAME_LINES (XFRAME (selected_frame))	\
+       if (a)                                                           \
+         emacs_tputs ((tty), a, (int) (FRAME_LINES (XFRAME (selected_frame)) \
 			  - curY), cmputc);				\
      } while (0)
 
-#define OUTPUT1_IF(a) do { if (a) tputs (a, 1, cmputc); } while (0)
+#define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
 
 /* Function to use to ring the bell.  */
 
 Lisp_Object Vring_bell_function;
 
 /* Terminal characteristics that higher levels want to look at. */
-static struct terminal _current_terminal;
-TERMINAL_PTR current_terminal = &_current_terminal;
+
+struct tty_output *tty_list;
 
 /* Nonzero means no need to redraw the entire frame on resuming
    a suspended Emacs.  This is useful on terminals with multiple pages,
@@ -421,18 +428,19 @@
     }
   else if (!FRAME_TERMCAP_P (XFRAME (selected_frame)))
     (*ring_bell_hook) ();
-  else
-    OUTPUT (TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell);
+  else {
+    OUTPUT (CURTTY (), TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell);
+  }
 }
 
 void
-set_terminal_modes ()
+set_terminal_modes (struct tty_output *tty)
 {
   if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
     {
-      OUTPUT_IF (TS_termcap_modes);
-      OUTPUT_IF (TS_cursor_visible);
-      OUTPUT_IF (TS_keypad_mode);
+      OUTPUT_IF (tty, TS_termcap_modes);
+      OUTPUT_IF (tty, TS_cursor_visible);
+      OUTPUT_IF (tty, TS_keypad_mode);
       losecursor ();
     }
   else
@@ -440,17 +448,18 @@
 }
 
 void
-reset_terminal_modes ()
+reset_terminal_modes (struct tty_output *tty)
 {
   if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
     {
       turn_off_highlight ();
       turn_off_insert ();
-      OUTPUT_IF (TS_end_keypad_mode);
-      OUTPUT_IF (TS_cursor_normal);
-      OUTPUT_IF (TS_end_termcap_modes);
-      OUTPUT_IF (TS_orig_pair);
+      OUTPUT_IF (tty, TS_end_keypad_mode);
+      OUTPUT_IF (tty, TS_cursor_normal);
+      OUTPUT_IF (tty, TS_end_termcap_modes);
+      OUTPUT_IF (tty, TS_orig_pair);
       /* Output raw CR so kernel can track the cursor hpos.  */
+      current_tty = tty;
       cmputc ('\r');
     }
   else if (reset_terminal_modes_hook)
@@ -490,7 +499,7 @@
   if (FRAME_TERMCAP_P (updating_frame))
     {
       specified_window = size ? size : FRAME_LINES (updating_frame);
-      if (TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ()))
+      if (TTY_SCROLL_REGION_OK (FRAME_TTY (updating_frame)))
 	set_scroll_region (0, specified_window);
     }
   else
@@ -514,7 +523,7 @@
   else
     buf = tparam (TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (sf));
 
-  OUTPUT (buf);
+  OUTPUT (CURTTY (), buf);
   xfree (buf);
   losecursor ();
 }
@@ -524,7 +533,7 @@
 turn_on_insert ()
 {
   if (!insert_mode)
-    OUTPUT (TS_insert_mode);
+    OUTPUT (CURTTY (), TS_insert_mode);
   insert_mode = 1;
 }
 
@@ -532,7 +541,7 @@
 turn_off_insert ()
 {
   if (insert_mode)
-    OUTPUT (TS_end_insert_mode);
+    OUTPUT (CURTTY (), TS_end_insert_mode);
   insert_mode = 0;
 }
 
@@ -542,7 +551,7 @@
 turn_off_highlight ()
 {
   if (standout_mode)
-    OUTPUT_IF (TS_end_standout_mode);
+    OUTPUT_IF (CURTTY (), TS_end_standout_mode);
   standout_mode = 0;
 }
 
@@ -550,7 +559,7 @@
 turn_on_highlight ()
 {
   if (!standout_mode)
-    OUTPUT_IF (TS_standout_mode);
+    OUTPUT_IF (CURTTY(), TS_standout_mode);
   standout_mode = 1;
 }
 
@@ -572,7 +581,7 @@
   if (tty_cursor_hidden == 0)
     {
       tty_cursor_hidden = 1;
-      OUTPUT_IF (TS_cursor_invisible);
+      OUTPUT_IF (CURTTY (), TS_cursor_invisible);
     }
 }
 
@@ -585,8 +594,8 @@
   if (tty_cursor_hidden)
     {
       tty_cursor_hidden = 0;
-      OUTPUT_IF (TS_cursor_normal);
-      OUTPUT_IF (TS_cursor_visible);
+      OUTPUT_IF (CURTTY (), TS_cursor_normal);
+      OUTPUT_IF (CURTTY (), TS_cursor_visible);
     }
 }
 
@@ -642,7 +651,7 @@
     background_highlight ();
   if (!TF_insmode_motion)
     turn_off_insert ();
-  cmgoto (vpos, hpos);
+  cmgoto (FRAME_TTY (f), vpos, hpos);
 }
 
 /* Similar but don't take any account of the wasted characters.  */
@@ -663,7 +672,7 @@
     background_highlight ();
   if (!TF_insmode_motion)
     turn_off_insert ();
-  cmgoto (row, col);
+  cmgoto (FRAME_TTY (f), row, col);
 }
 
 /* Erase operations */
@@ -682,7 +691,7 @@
   if (TS_clr_to_bottom)
     {
       background_highlight ();
-      OUTPUT (TS_clr_to_bottom);
+      OUTPUT (CURTTY (), TS_clr_to_bottom);
     }
   else
     {
@@ -710,7 +719,7 @@
   if (TS_clr_frame)
     {
       background_highlight ();
-      OUTPUT (TS_clr_frame);
+      OUTPUT (FRAME_TTY (updating_frame ? updating_frame : sf), TS_clr_frame);
       cmat (0, 0);
     }
   else
@@ -750,7 +759,7 @@
   background_highlight ();
   if (TS_clr_line)
     {
-      OUTPUT1 (TS_clr_line);
+      OUTPUT1 (CURTTY (), TS_clr_line);
     }
   else
     {			/* have to do it the hard way */
@@ -764,9 +773,9 @@
 
       for (i = curX; i < first_unused_hpos; i++)
 	{
-	  if (termscript)
-	    fputc (' ', termscript);
-	  putchar (' ');
+	  if (TTY_TERMSCRIPT (CURTTY ()))
+	    fputc (' ', TTY_TERMSCRIPT (CURTTY ()));
+	  fputc (' ', TTY_OUTPUT (CURTTY ()));
 	}
       cmplus (first_unused_hpos - curX);
     }
@@ -942,11 +951,13 @@
 					   &consumed);
 	  if (produced > 0)
 	    {
-	      fwrite (conversion_buffer, 1, produced, stdout);
-	      if (ferror (stdout))
-		clearerr (stdout);
-	      if (termscript)
-		fwrite (conversion_buffer, 1, produced, termscript);
+	      fwrite (conversion_buffer, 1, produced,
+                      TTY_OUTPUT (FRAME_TTY (f)));
+	      if (ferror (TTY_OUTPUT (FRAME_TTY (f))))
+		clearerr (TTY_OUTPUT (FRAME_TTY (f)));
+	      if (TTY_TERMSCRIPT (FRAME_TTY (f)))
+		fwrite (conversion_buffer, 1, produced,
+                        TTY_TERMSCRIPT (FRAME_TTY (f)));
 	    }
 	  len -= consumed;
 	  n -= consumed;
@@ -966,16 +977,17 @@
 		     0, conversion_buffer_size);
       if (terminal_coding.produced > 0)
 	{
-	  fwrite (conversion_buffer, 1, terminal_coding.produced, stdout);
-	  if (ferror (stdout))
-	    clearerr (stdout);
-	  if (termscript)
+	  fwrite (conversion_buffer, 1, terminal_coding.produced,
+                  TTY_OUTPUT (FRAME_TTY (f)));
+	  if (ferror (TTY_OUTPUT (FRAME_TTY (f))))
+	    clearerr (TTY_OUTPUT (FRAME_TTY (f)));
+	  if (TTY_TERMSCRIPT (FRAME_TTY (f)))
 	    fwrite (conversion_buffer, 1, terminal_coding.produced,
-		    termscript);
+		    TTY_TERMSCRIPT (FRAME_TTY (f)));
 	}
     }
 
-  cmcheckmagic ();
+  cmcheckmagic (FRAME_TTY (f));
 }
 
 /* If start is zero, insert blanks instead of a string at start */
@@ -1004,7 +1016,7 @@
   if (TS_ins_multi_chars)
     {
       buf = tparam (TS_ins_multi_chars, 0, 0, len);
-      OUTPUT1 (buf);
+      OUTPUT1 (FRAME_TTY (f), buf);
       xfree (buf);
       if (start)
 	write_glyphs (start, len);
@@ -1021,7 +1033,7 @@
       unsigned char conversion_buffer[1024];
       int conversion_buffer_size = sizeof conversion_buffer;
 
-      OUTPUT1_IF (TS_ins_char);
+      OUTPUT1_IF (FRAME_TTY (f), TS_ins_char);
       if (!start)
 	{
 	  conversion_buffer[0] = SPACEGLYPH;
@@ -1037,7 +1049,7 @@
 	     occupies more than one column.  */
 	  while (len && CHAR_GLYPH_PADDING_P (*start))
 	    {
-	      OUTPUT1_IF (TS_ins_char);
+	      OUTPUT1_IF (FRAME_TTY (f), TS_ins_char);
 	      start++, len--;
 	    }
 
@@ -1053,14 +1065,16 @@
 
       if (produced > 0)
 	{
-	  fwrite (conversion_buffer, 1, produced, stdout);
-	  if (ferror (stdout))
-	    clearerr (stdout);
-	  if (termscript)
-	    fwrite (conversion_buffer, 1, produced, termscript);
+	  fwrite (conversion_buffer, 1, produced,
+                  TTY_OUTPUT (FRAME_TTY (f)));
+	  if (ferror (TTY_OUTPUT (FRAME_TTY (f))))
+	    clearerr (TTY_OUTPUT (FRAME_TTY (f)));
+	  if (TTY_TERMSCRIPT (FRAME_TTY (f)))
+	    fwrite (conversion_buffer, 1, produced,
+                    TTY_TERMSCRIPT (FRAME_TTY (f)));
 	}
 
-      OUTPUT1_IF (TS_pad_inserted_char);
+      OUTPUT1_IF (FRAME_TTY (f), TS_pad_inserted_char);
       if (start)
 	{
 	  turn_off_face (f, glyph->face_id);
@@ -1068,7 +1082,7 @@
 	}
     }
 
-  cmcheckmagic ();
+  cmcheckmagic (FRAME_TTY (f));
 }
 
 void
@@ -1091,20 +1105,20 @@
   else
     {
       turn_off_insert ();
-      OUTPUT_IF (TS_delete_mode);
+      OUTPUT_IF (FRAME_TTY (updating_frame), TS_delete_mode);
     }
 
   if (TS_del_multi_chars)
     {
       buf = tparam (TS_del_multi_chars, 0, 0, n);
-      OUTPUT1 (buf);
+      OUTPUT1 (FRAME_TTY (updating_frame), buf);
       xfree (buf);
     }
   else
     for (i = 0; i < n; i++)
-      OUTPUT1 (TS_del_char);
+      OUTPUT1 (FRAME_TTY (updating_frame), TS_del_char);
   if (!delete_in_insert_mode)
-    OUTPUT_IF (TS_end_delete_mode);
+    OUTPUT_IF (FRAME_TTY (updating_frame), TS_end_delete_mode);
 }
 
 /* Insert N lines at vpos VPOS.  If N is negative, delete -N lines.  */
@@ -1136,10 +1150,10 @@
   /* 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 (TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ())
+  if (TTY_SCROLL_REGION_OK (FRAME_TTY (sf))
       && vpos + i >= specified_window)
     return;
-  if (!TERMINAL_MEMORY_BELOW_FRAME (CURRENT_TERMINAL ())
+  if (!TTY_MEMORY_BELOW_FRAME (FRAME_TTY (sf))
       && vpos + i >= FRAME_LINES (sf))
     return;
 
@@ -1148,7 +1162,7 @@
       raw_cursor_to (vpos, 0);
       background_highlight ();
       buf = tparam (multi, 0, 0, i);
-      OUTPUT (buf);
+      OUTPUT (FRAME_TTY (sf), buf);
       xfree (buf);
     }
   else if (single)
@@ -1156,7 +1170,7 @@
       raw_cursor_to (vpos, 0);
       background_highlight ();
       while (--i >= 0)
-	OUTPUT (single);
+	OUTPUT (FRAME_TTY (sf), single);
       if (TF_teleray)
 	curX = 0;
     }
@@ -1169,12 +1183,12 @@
 	raw_cursor_to (vpos, 0);
       background_highlight ();
       while (--i >= 0)
-	OUTPUTL (scroll, specified_window - vpos);
+	OUTPUTL (FRAME_TTY (sf), scroll, specified_window - vpos);
       set_scroll_region (0, specified_window);
     }
 
-  if (!TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ())
-      && TERMINAL_MEMORY_BELOW_FRAME (CURRENT_TERMINAL ())
+  if (!TTY_SCROLL_REGION_OK (FRAME_TTY (sf))
+      && TTY_MEMORY_BELOW_FRAME (FRAME_TTY (sf))
       && n < 0)
     {
       cursor_to (FRAME_LINES (sf) + n, 0);
@@ -1306,7 +1320,8 @@
 
   FRAME_COST_BAUD_RATE (frame) = baud_rate;
 
-  TERMINAL_SCROLL_REGION_COST (CURRENT_TERMINAL ()) = string_cost (f);
+  if (FRAME_TERMCAP_P (frame))
+    TTY_SCROLL_REGION_COST (frame->output_data.tty) = string_cost (f);
 
   /* These variables are only used for terminal stuff.  They are allocated
      once for the terminal frame of X-windows emacs, but not used afterwards.
@@ -1866,23 +1881,23 @@
   if (face->tty_bold_p)
     {
       if (MAY_USE_WITH_COLORS_P (NC_BOLD))
-	OUTPUT1_IF (TS_enter_bold_mode);
+	OUTPUT1_IF (FRAME_TTY (f), TS_enter_bold_mode);
     }
   else if (face->tty_dim_p)
     if (MAY_USE_WITH_COLORS_P (NC_DIM))
-      OUTPUT1_IF (TS_enter_dim_mode);
+      OUTPUT1_IF (FRAME_TTY (f), TS_enter_dim_mode);
 
   /* Alternate charset and blinking not yet used.  */
   if (face->tty_alt_charset_p
       && MAY_USE_WITH_COLORS_P (NC_ALT_CHARSET))
-    OUTPUT1_IF (TS_enter_alt_charset_mode);
+    OUTPUT1_IF (FRAME_TTY (f), TS_enter_alt_charset_mode);
 
   if (face->tty_blinking_p
       && MAY_USE_WITH_COLORS_P (NC_BLINK))
-    OUTPUT1_IF (TS_enter_blink_mode);
+    OUTPUT1_IF (FRAME_TTY (f), TS_enter_blink_mode);
 
   if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (NC_UNDERLINE))
-    OUTPUT1_IF (TS_enter_underline_mode);
+    OUTPUT1_IF (FRAME_TTY (f), TS_enter_underline_mode);
 
   if (TN_max_colors > 0)
     {
@@ -1891,14 +1906,14 @@
       if (fg >= 0 && TS_set_foreground)
 	{
 	  p = tparam (TS_set_foreground, NULL, 0, (int) fg);
-	  OUTPUT (p);
+	  OUTPUT (FRAME_TTY (f), p);
 	  xfree (p);
 	}
 
       if (bg >= 0 && TS_set_background)
 	{
 	  p = tparam (TS_set_background, NULL, 0, (int) bg);
-	  OUTPUT (p);
+	  OUTPUT (FRAME_TTY (f), p);
 	  xfree (p);
 	}
     }
@@ -1928,23 +1943,23 @@
 	  || face->tty_blinking_p
 	  || face->tty_underline_p)
 	{
-	  OUTPUT1_IF (TS_exit_attribute_mode);
+	  OUTPUT1_IF (FRAME_TTY (f), TS_exit_attribute_mode);
 	  if (strcmp (TS_exit_attribute_mode, TS_end_standout_mode) == 0)
 	    standout_mode = 0;
 	}
 
       if (face->tty_alt_charset_p)
-	OUTPUT_IF (TS_exit_alt_charset_mode);
+	OUTPUT_IF (FRAME_TTY (f), TS_exit_alt_charset_mode);
     }
   else
     {
       /* If we don't have "me" we can only have those appearances
 	 that have exit sequences defined.  */
       if (face->tty_alt_charset_p)
-	OUTPUT_IF (TS_exit_alt_charset_mode);
+	OUTPUT_IF (FRAME_TTY (f), TS_exit_alt_charset_mode);
 
       if (face->tty_underline_p)
-	OUTPUT_IF (TS_exit_underline_mode);
+	OUTPUT_IF (FRAME_TTY (f), TS_exit_underline_mode);
     }
 
   /* Switch back to default colors.  */
@@ -1953,7 +1968,7 @@
 	   && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
 	  || (face->background != FACE_TTY_DEFAULT_COLOR
 	      && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
-    OUTPUT1_IF (TS_orig_pair);
+    OUTPUT1_IF (FRAME_TTY (f), TS_orig_pair);
 }
 
 
@@ -2144,12 +2159,46 @@
 #endif /* !WINDOWSNT */
 
 
+
+struct tty_output *
+get_named_tty (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;
+  };
+
+  return 0;
+}
+
+
 /***********************************************************************
 			    Initialization
  ***********************************************************************/
 
-void
-term_init (terminal_type)
+struct tty_output *
+term_dummy_init (void)
+{
+  if (initialized || tty_list)
+    error ("tty already initialized");
+
+  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;
+}
+
+
+struct tty_output *
+term_init (name, terminal_type)
+     char *name;
      char *terminal_type;
 {
   char *area;
@@ -2160,6 +2209,52 @@
   int status;
   struct frame *sf = XFRAME (selected_frame);
 
+  struct tty_output *tty;
+
+  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;
+    }
+  else
+    {
+      if (!terminal_type)
+        error ("Unknown terminal type");
+
+      tty = (struct tty_output *) xmalloc (sizeof (struct tty_output));
+      bzero (tty, sizeof (struct tty_output));
+      tty->next = tty_list;
+      tty_list = tty;
+    }
+
+  if (name)
+    {
+      int fd;
+      FILE *f;
+      fd = emacs_open (name, O_RDWR, 0);
+      if (fd < 0)
+        {
+          tty_list = tty->next;
+          xfree (tty);
+          error ("could not open file: %s", name);
+        }
+      f = fdopen (fd, "w+");
+      TTY_NAME (tty) = xstrdup (name);
+      TTY_INPUT (tty) = f;
+      TTY_OUTPUT (tty) = f;
+    }
+  else
+    {
+      TTY_NAME (tty) = 0;
+      TTY_INPUT (tty) = stdin;
+      TTY_OUTPUT (tty) = stdout;
+    }
+
+  init_sys_modes (tty);
+
 #ifdef WINDOWSNT
   initialize_w32_display ();
 
@@ -2174,15 +2269,15 @@
   delete_in_insert_mode = 1;
 
   UseTabs = 0;
-  TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ()) = 0;
+  TTY_SCROLL_REGION_OK (tty) = 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.  */
-
-  TERMINAL_LINE_INS_DEL_OK (CURRENT_TERMINAL ()) = 0;
-  TERMINAL_CHAR_INS_DEL_OK (CURRENT_TERMINAL ()) = 1;
+  TTY_LINE_INS_DEL_OK (tty) = 0;
+
+  TTY_CHAR_INS_DEL_OK (tty) = 1;
 
   baud_rate = 19200;
 
@@ -2190,11 +2285,13 @@
   FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none;
   TN_max_colors = 16;  /* Required to be non-zero for tty-display-color-p */
 
-  return;
+  return tty;
 #else  /* not WINDOWSNT */
 
   Wcm_clear ();
 
+  TTY_TYPE (tty) = xstrdup (terminal_type);
+
   buffer = (char *) xmalloc (buffer_size);
   status = tgetent (buffer, terminal_type);
   if (status < 0)
@@ -2213,14 +2310,14 @@
 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
       fatal ("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
     }
 
@@ -2326,7 +2423,7 @@
 
       TN_no_color_video = tgetnum ("NC");
       if (TN_no_color_video == -1)
-	TN_no_color_video = 0;
+        TN_no_color_video = 0;
     }
 
   tty_default_color_capabilities (1);
@@ -2335,9 +2432,9 @@
   /* Since we make MagicWrap terminals look like AutoWrap, we need to have
      the former flag imply the latter.  */
   AutoWrap = MagicWrap || tgetflag ("am");
-  TERMINAL_MEMORY_BELOW_FRAME (CURRENT_TERMINAL ()) = tgetflag ("db");
+  TTY_MEMORY_BELOW_FRAME (tty) = tgetflag ("db");
   TF_hazeltine = tgetflag ("hz");
-  TERMINAL_MUST_WRITE_SPACES (CURRENT_TERMINAL ()) = tgetflag ("in");
+  TTY_MUST_WRITE_SPACES (tty) = tgetflag ("in");
   meta_key = tgetflag ("km") || tgetflag ("MT");
   TF_insmode_motion = tgetflag ("mi");
   TF_standout_motion = tgetflag ("ms");
@@ -2364,12 +2461,12 @@
 
   if (FRAME_LINES (sf) < 3 || FRAME_COLS (sf) < 3)
     fatal ("Screen size %dx%d is too small",
-	   FRAME_LINES (sf), FRAME_COLS (sf));
+           FRAME_LINES (sf), FRAME_COLS (sf));
 
 #if 0  /* This is not used anywhere. */
-  TERMINAL_MIN_PADDING_SPEED (CURRENT_TERMINAL ()) = tgetnum ("pb");
+  TTY_MIN_PADDING_SPEED (tty) = tgetnum ("pb");
 #endif
-  
+
   TabWidth = tgetnum ("tw");
 
 #ifdef VMS
@@ -2424,9 +2521,9 @@
     {
       char *s = tgetstr ("me", address);
       if (s != 0)
-	TS_end_standout_mode = s;
+        TS_end_standout_mode = s;
       else
-	TS_standout_mode = 0;
+        TS_standout_mode = 0;
     }
 
   if (TF_teleray)
@@ -2445,7 +2542,7 @@
 
   if (!strcmp (terminal_type, "supdup"))
     {
-      TERMINAL_MEMORY_BELOW_FRAME (CURRENT_TERMINAL ()) = 1;
+      TTY_MEMORY_BELOW_FRAME (tty) = 1;
       Wcm.cm_losewrap = 1;
     }
   if (!strncmp (terminal_type, "c10", 3)
@@ -2455,7 +2552,7 @@
 	 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.
@@ -2472,7 +2569,7 @@
 	    TS_set_window = "\033v%C %C %C %C ";
 	}
       /* Termcap entry often fails to have :in: flag */
-      TERMINAL_MUST_WRITE_SPACES (CURRENT_TERMINAL ()) = 1;
+      TTY_MUST_WRITE_SPACES (tty) = 1;
       /* :ti string typically fails to have \E^G! in it */
       /* This limits scope of insert-char to one line.  */
       strcpy (area, TS_termcap_modes);
@@ -2481,13 +2578,13 @@
       area += strlen (area) + 1;
       p = AbsPosition;
       /* Change all %+ parameters to %C, to handle
-	 values above 96 correctly for the C100.  */
+         values above 96 correctly for the C100.  */
       while (*p)
-	{
-	  if (p[0] == '%' && p[1] == '+')
-	    p[1] = 'C';
-	  p++;
-	}
+        {
+          if (p[0] == '%' && p[1] == '+')
+            p[1] = 'C';
+          p++;
+        }
     }
 
   FrameRows = FRAME_LINES (sf);
@@ -2504,21 +2601,21 @@
            terminal_type);
 #else /* not VMS */
 # ifdef TERMINFO
-    fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
+  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\
 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 /* TERMCAP */
-    fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
+  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\
 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 /* TERMINFO */
 #endif /*VMS */
   if (FRAME_LINES (sf) <= 0
@@ -2527,34 +2624,34 @@
 
   delete_in_insert_mode
     = TS_delete_mode && TS_insert_mode
-      && !strcmp (TS_delete_mode, TS_insert_mode);
+    && !strcmp (TS_delete_mode, TS_insert_mode);
 
   se_is_so = (TS_standout_mode
-	      && TS_end_standout_mode
-	      && !strcmp (TS_standout_mode, TS_end_standout_mode));
+              && TS_end_standout_mode
+              && !strcmp (TS_standout_mode, TS_end_standout_mode));
 
   UseTabs = tabs_safe_p () && TabWidth == 8;
 
-  TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ())
+  TTY_SCROLL_REGION_OK (tty)
     = (Wcm.cm_abs
        && (TS_set_window || TS_set_scroll_region || TS_set_scroll_region_1));
 
-  TERMINAL_LINE_INS_DEL_OK (CURRENT_TERMINAL ())
+  TTY_LINE_INS_DEL_OK (tty)
     = (((TS_ins_line || TS_ins_multi_lines)
         && (TS_del_line || TS_del_multi_lines))
-       || (TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ())
+       || (TTY_SCROLL_REGION_OK (tty)
            && TS_fwd_scroll && TS_rev_scroll));
-  
-  TERMINAL_CHAR_INS_DEL_OK (CURRENT_TERMINAL ())
+
+  TTY_CHAR_INS_DEL_OK (tty)
     = ((TS_ins_char || TS_insert_mode
         || TS_pad_inserted_char || TS_ins_multi_chars)
        && (TS_del_char || TS_del_multi_chars));
 
-  TERMINAL_FAST_CLEAR_END_OF_LINE (CURRENT_TERMINAL ()) = TS_clr_line != 0;
+  TTY_FAST_CLEAR_END_OF_LINE (tty) = TS_clr_line != 0;
 
   init_baud_rate ();
-  if (read_socket_hook)		/* Baudrate is somewhat */
-				/* meaningless in this case */
+  if (read_socket_hook)		/* Baudrate is somewhat
+                                   meaningless in this case */
     baud_rate = 9600;
 
   FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0;
@@ -2562,6 +2659,8 @@
 #endif /* WINDOWSNT */
 
   xfree (buffer);
+
+  return tty;
 }
 
 /* VARARGS 1 */
@@ -2597,5 +2696,12 @@
   defsubr (&Stty_display_color_cells);
 }
 
+struct tty_output *
+get_current_tty ()
+{
+  return CURTTY();
+}
+
+
 /* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193
    (do not change this comment) */
--- a/src/termchar.h	Wed Dec 24 18:55:24 2003 +0000
+++ b/src/termchar.h	Thu Dec 25 06:59:31 2003 +0000
@@ -18,10 +18,37 @@
 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
-struct terminal
+/* Each termcap frame points to its own struct tty_output object in the
+   output_data.tty field.  The tty_output structure contains the information
+   that is specific to terminals. */
+struct tty_output
 {
+  char *name;                   /* The name of the device file or 0 if
+                                   stdin/stdout. */
+  char *type;                   /* The type of the tty. */
   
-  /* EMACS_INT baud_rate; */	/* Output speed in baud */
+  /* Input/output */
+  
+  FILE *input;                  /* The stream to be used for terminal input. */
+  FILE *output;                 /* The stream to be used for terminal output. */
+  
+  FILE *termscript;             /* If nonzero, send all terminal output
+                                   characters to this stream also.  */
+
+  struct emacs_tty old_tty;     /* The initial tty mode bits */
+
+  int term_initted;             /* 1 if we have been through init_sys_modes. */
+  int old_tty_valid;            /* 1 if outer tty status has been recorded.  */
+  
+  
+  /* Pixel values.
+     XXX What are these used for? */
+  
+  unsigned long background_pixel;
+  unsigned long foreground_pixel;
+
+  /* Terminal characteristics. */
+  
   int must_write_spaces;	/* Nonzero means spaces in the text must
 				   actually be output; can't just skip over
 				   some columns to leave them blank.  */
@@ -37,31 +64,43 @@
                                    off bottom */
 
 #if 0  /* These are not used anywhere. */
+  /* EMACS_INT baud_rate; */	/* Output speed in baud */
   int min_padding_speed;	/* Speed below which no padding necessary. */
   int dont_calculate_costs;     /* Nonzero means don't bother computing
                                    various cost tables; we won't use them. */
 #endif
+
+  struct tty_output *next;
 };
 
-typedef struct terminal *TERMINAL_PTR;
+extern struct tty_output *tty_list;
+
 
-extern TERMINAL_PTR current_terminal;
+#define FRAME_TTY(f) \
+  ((f)->output_method == output_termcap \
+   ? (f)->output_data.tty : (abort(), (struct tty_output *) 0))
+  
+#define CURTTY() FRAME_TTY (SELECTED_FRAME())
 
-#define CURRENT_TERMINAL() \
-  (current_terminal ? current_terminal : (abort(), (TERMINAL_PTR) 0))
+#define TTY_NAME(t) ((t)->name)
+#define TTY_TYPE(t) ((t)->type)
 
-#define TERMINAL_MUST_WRITE_SPACES(t) ((t)->must_write_spaces)
-#define TERMINAL_FAST_CLEAR_END_OF_LINE(t) ((t)->fast_clear_end_of_line)
-#define TERMINAL_LINE_INS_DEL_OK(t) ((t)->line_ins_del_ok)
-#define TERMINAL_CHAR_INS_DEL_OK(t) ((t)->char_ins_del_ok)
-#define TERMINAL_SCROLL_REGION_OK(t) ((t)->scroll_region_ok)
-#define TERMINAL_SCROLL_REGION_COST(t) ((t)->scroll_region_cost)
-#define TERMINAL_MEMORY_BELOW_FRAME(t) ((t)->memory_below_frame)
+#define TTY_INPUT(t) ((t)->input)
+#define TTY_OUTPUT(t) ((t)->output)
+#define TTY_TERMSCRIPT(t) ((t)->termscript)
+
+#define TTY_MUST_WRITE_SPACES(t) ((t)->must_write_spaces)
+#define TTY_FAST_CLEAR_END_OF_LINE(t) ((t)->fast_clear_end_of_line)
+#define TTY_LINE_INS_DEL_OK(t) ((t)->line_ins_del_ok)
+#define TTY_CHAR_INS_DEL_OK(t) ((t)->char_ins_del_ok)
+#define TTY_SCROLL_REGION_OK(t) ((t)->scroll_region_ok)
+#define TTY_SCROLL_REGION_COST(t) ((t)->scroll_region_cost)
+#define TTY_MEMORY_BELOW_FRAME(t) ((t)->memory_below_frame)
 
 #if 0
 /* These are not used anywhere. */
-#define TERMINAL_MIN_PADDING_SPEED(t) ((t)->min_padding_speed)
-#define TERMINAL_DONT_CALCULATE_COSTS(t) ((t)->dont_calculate_costs)
+#define TTY_MIN_PADDING_SPEED(t) ((t)->min_padding_speed)
+#define TTY_DONT_CALCULATE_COSTS(t) ((t)->dont_calculate_costs)
 #endif
 
 /* arch-tag: bf9f0d49-842b-42fb-9348-ec8759b27193
--- a/src/termhooks.h	Wed Dec 24 18:55:24 2003 +0000
+++ b/src/termhooks.h	Thu Dec 25 06:59:31 2003 +0000
@@ -25,9 +25,6 @@
 struct glyph;
 struct frame;
 
-/* If nonzero, send all terminal output characters to this stream also.  */
-extern FILE *termscript;
-
 /* Only use prototypes when lisp.h has been included.  */
 #ifndef P_
 #define P_(X) ()
--- a/src/w32term.c	Wed Dec 24 18:55:24 2003 +0000
+++ b/src/w32term.c	Thu Dec 25 06:59:31 2003 +0000
@@ -6366,11 +6366,11 @@
   redeem_scroll_bar_hook = w32_redeem_scroll_bar;
   judge_scroll_bars_hook = w32_judge_scroll_bars;
 
-  TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ()) = 1; /* we'll scroll partial frames */
-  TERMINAL_CHAR_INS_DEL_OK (CURRENT_TERMINAL ()) = 1;
-  TERMINAL_LINE_INS_DEL_OK (CURRENT_TERMINAL ()) = 1; /* we'll just blt 'em */
-  TERMINAL_FAST_CLEAR_END_OF_LINE (CURRENT_TERMINAL ()) = 1; /* X does this well */
-  TERMINAL_MEMORY_BELOW_FRAME (CURRENT_TERMINAL ()) = 0; /* we don't remember what
+  TTY_SCROLL_REGION_OK (CURTTY ()) = 1; /* we'll scroll partial frames */
+  TTY_CHAR_INS_DEL_OK (CURTTY ()) = 1;
+  TTY_LINE_INS_DEL_OK (CURTTY ()) = 1; /* we'll just blt 'em */
+  TTY_FAST_CLEAR_END_OF_LINE (CURTTY ()) = 1; /* X does this well */
+  TTY_MEMORY_BELOW_FRAME (CURTTY ()) = 0; /* we don't remember what
                                                             scrolls off the
                                                             bottom */
   baud_rate = 19200;
--- a/src/w32term.h	Wed Dec 24 18:55:24 2003 +0000
+++ b/src/w32term.h	Thu Dec 25 06:59:31 2003 +0000
@@ -389,8 +389,6 @@
 #define FRAME_W32_WINDOW(f) ((f)->output_data.w32->window_desc)
 #define FRAME_X_WINDOW(f) ((f)->output_data.w32->window_desc)
 
-#define FRAME_FOREGROUND_PIXEL(f) ((f)->output_data.x->foreground_pixel)
-#define FRAME_BACKGROUND_PIXEL(f) ((f)->output_data.x->background_pixel)
 #define FRAME_FONT(f) ((f)->output_data.w32->font)
 #define FRAME_FONTSET(f) ((f)->output_data.w32->fontset)
 #define FRAME_BASELINE_OFFSET(f) ((f)->output_data.w32->baseline_offset)
--- a/src/window.c	Wed Dec 24 18:55:24 2003 +0000
+++ b/src/window.c	Thu Dec 25 06:59:31 2003 +0000
@@ -29,6 +29,7 @@
 #include "window.h"
 #include "commands.h"
 #include "indent.h"
+#include "systty.h" /* For emacs_tty in termchar.h */
 #include "termchar.h"
 #include "disptab.h"
 #include "dispextern.h"
@@ -6381,7 +6382,7 @@
 void
 init_window_once ()
 {
-  struct frame *f = make_terminal_frame ();
+  struct frame *f = make_terminal_frame (0, 0);
   XSETFRAME (selected_frame, f);
   Vterminal_frame = selected_frame;
   minibuf_window = f->minibuffer_window;
--- a/src/xdisp.c	Wed Dec 24 18:55:24 2003 +0000
+++ b/src/xdisp.c	Thu Dec 25 06:59:31 2003 +0000
@@ -173,6 +173,7 @@
 #include "keyboard.h"
 #include "frame.h"
 #include "window.h"
+#include "systty.h" /* For emacs_tty in termchar.h */
 #include "termchar.h"
 #include "dispextern.h"
 #include "buffer.h"
@@ -12889,7 +12890,7 @@
 
   /* Window must either use window-based redisplay or be full width.  */
   if (!FRAME_WINDOW_P (f)
-      && (!TERMINAL_LINE_INS_DEL_OK (CURRENT_TERMINAL ())
+      && (!TTY_LINE_INS_DEL_OK (CURTTY ())
 	  || !WINDOW_FULL_WIDTH_P (w)))
     GIVE_UP (4);
 
@@ -13322,7 +13323,7 @@
 
 	      /* On dumb terminals delete dvpos lines at the end
 		 before inserting dvpos empty lines.  */
-	      if (!TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ()))
+	      if (!TTY_SCROLL_REGION_OK (CURTTY ()))
 		ins_del_lines (end - dvpos, -dvpos);
 
 	      /* Insert dvpos empty lines in front of
@@ -13343,7 +13344,7 @@
 
 	      /* On a dumb terminal insert dvpos empty lines at the
                  end.  */
-	      if (!TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ()))
+	      if (!TTY_SCROLL_REGION_OK (CURTTY ()))
 		ins_del_lines (end + dvpos, -dvpos);
 	    }
 
--- a/src/xfaces.c	Wed Dec 24 18:55:24 2003 +0000
+++ b/src/xfaces.c	Thu Dec 25 06:59:31 2003 +0000
@@ -241,6 +241,8 @@
 #include "blockinput.h"
 #include "window.h"
 #include "intervals.h"
+#include "systty.h" /* For emacs_tty in termchar.h */
+#include "termchar.h"
 
 #ifdef HAVE_X_WINDOWS
 
--- a/src/xfns.c	Wed Dec 24 18:55:24 2003 +0000
+++ b/src/xfns.c	Thu Dec 25 06:59:31 2003 +0000
@@ -48,6 +48,8 @@
 #include "systime.h"
 #include "termhooks.h"
 #include "atimer.h"
+#include "systty.h"
+#include "termchar.h"
 
 #ifdef HAVE_X_WINDOWS