Fix C-g handling with multiple ttys.
[bpt/emacs.git] / src / sysdep.c
index 43a7d7c..5a2bb44 100644 (file)
@@ -45,6 +45,8 @@ extern void srandom P_ ((unsigned int));
 #endif
 #endif
 
+#include "sysselect.h"
+
 #include "blockinput.h"
 #undef NULL
 
@@ -184,6 +186,7 @@ extern int quit_char;
 #include "termopts.h"
 #include "dispextern.h"
 #include "process.h"
+#include "cm.h"  /* for reset_sys_modes */
 
 #ifdef WINDOWSNT
 #include <direct.h>
@@ -249,8 +252,8 @@ int emacs_ospeed;
 void croak P_ ((char *));
 
 #ifdef AIXHFT
-void hft_init ();
-void hft_reset ();
+void hft_init P_ ((struct tty_display_info *));
+void hft_reset P_ ((struct tty_display_info *));
 #endif
 
 /* Temporary used by `sigblock' when defined in terms of signprocmask.  */
@@ -269,11 +272,6 @@ discard_tty_input ()
   if (noninteractive)
     return;
 
-  /* Discarding input is not safe when the input could contain
-     replies from the X server.  So don't do it.  */
-  if (read_socket_hook)
-    return;
-
 #ifdef VMS
   end_kbd_input ();
   SYS$QIOW (0, fileno (TTY_INPUT (CURTTY())), IO$_READVBLK|IO$M_PURGE, input_iosb, 0, 0,
@@ -282,8 +280,12 @@ discard_tty_input ()
 #else /* not VMS */
 #ifdef APOLLO
   {
-    int zero = 0;
-    ioctl (fileno (TTY_INPUT (CURTTY())), TIOCFLUSH, &zero);
+    struct tty_display_info *tty;
+    for (tty = tty_list; tty; tty = tty->next)
+      {
+        int zero = 0;
+        ioctl (fileno (TTY_INPUT (tty)), TIOCFLUSH, &zero);
+      }
   }
 #else /* not Apollo */
 #ifdef MSDOS    /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
@@ -291,7 +293,7 @@ discard_tty_input ()
     ;
 #else /* not MSDOS */
   {
-    struct tty_output tty;
+    struct tty_display_info *tty;
     for (tty = tty_list; tty; tty = tty->next)
       {
         EMACS_GET_TTY (fileno (TTY_INPUT (tty)), &buf);
@@ -304,20 +306,18 @@ discard_tty_input ()
 #endif /* not WINDOWSNT */
 }
 
+\f
 #ifdef SIGTSTP
 
 /* Arrange for character C to be read as the next input from
-   the terminal.  */
+   the terminal.
+   XXX What if we have multiple ttys?
+*/
 
 void
-#ifdef PROTOTYPES
 stuff_char (char c)
-#else
-stuff_char (c)
-     char c;
-#endif
 {
-  if (read_socket_hook)
+  if (! FRAME_TERMCAP_P (SELECTED_FRAME ()))
     return;
 
 /* Should perhaps error if in batch mode */
@@ -331,7 +331,7 @@ stuff_char (c)
 #endif /* SIGTSTP */
 \f
 void
-init_baud_rate ()
+init_baud_rate (int fd)
 {
   if (noninteractive)
     emacs_ospeed = 0;
@@ -346,7 +346,7 @@ init_baud_rate ()
 #ifdef VMS
       struct sensemode sg;
 
-      SYS$QIOW (0, fileno (TTY_INPUT (CURTTY())), IO$_SENSEMODE, &sg, 0, 0,
+      SYS$QIOW (0, fd, IO$_SENSEMODE, &sg, 0, 0,
                &sg.class, 12, 0, 0, 0, 0 );
       emacs_ospeed = sg.xmit_baud;
 #else /* not VMS */
@@ -354,7 +354,7 @@ init_baud_rate ()
       struct termios sg;
 
       sg.c_cflag = B9600;
-      tcgetattr (fileno (TTY_INPUT (CURTTY())), &sg);
+      tcgetattr (fd, &sg);
       emacs_ospeed = cfgetospeed (&sg);
 #if defined (USE_GETOBAUD) && defined (getobaud)
       /* m88k-motorola-sysv3 needs this (ghazi@noc.rutgers.edu) 9/1/94. */
@@ -367,16 +367,16 @@ init_baud_rate ()
 
       sg.c_cflag = B9600;
 #ifdef HAVE_TCATTR
-      tcgetattr (fileno (TTY_INPUT (CURTTY())), &sg);
+      tcgetattr (fd, &sg);
 #else
-      ioctl (fileno (TTY_INPUT (CURTTY())), TCGETA, &sg);
+      ioctl (fd, TCGETA, &sg);
 #endif
       emacs_ospeed = sg.c_cflag & CBAUD;
 #else /* neither VMS nor TERMIOS nor TERMIO */
       struct sgttyb sg;
 
       sg.sg_ospeed = B9600;
-      if (ioctl (fileno (TTY_INPUT (CURTTY())), TIOCGETP, &sg) < 0)
+      if (ioctl (fd, TIOCGETP, &sg) < 0)
        abort ();
       emacs_ospeed = sg.sg_ospeed;
 #endif /* not HAVE_TERMIO */
@@ -392,6 +392,7 @@ init_baud_rate ()
     baud_rate = 1200;
 }
 
+\f
 /*ARGSUSED*/
 void
 set_exclusive_use (fd)
@@ -650,7 +651,7 @@ child_setup_tty (out)
 
 #ifdef BSD4_1
   if (interrupt_input)
-    reset_sigio ();
+    reset_sigio (0);
 #endif /* BSD4_1 */
 #ifdef RTU
   {
@@ -907,53 +908,88 @@ restore_signal_handlers (saved_handlers)
     }
 }
 \f
+#ifndef SIGIO
+/* If SIGIO is broken, don't do anything. */
+void
+init_sigio (int fd)
+{
+}
+
+void
+reset_sigio (int fd)
+{
+}
+
+void
+request_sigio (void)
+{
+}
+
+void
+unrequest_sigio (void)
+{
+}
+
+#else
 #ifdef F_SETFL
 
-int old_fcntl_flags;
+int old_fcntl_flags[MAXDESC];
 
 void
 init_sigio (fd)
      int fd;
 {
 #ifdef FASYNC
-  old_fcntl_flags = fcntl (fd, F_GETFL, 0) & ~FASYNC;
-  fcntl (fd, F_SETFL, old_fcntl_flags | FASYNC);
+  old_fcntl_flags[fd] = fcntl (fd, F_GETFL, 0) & ~FASYNC;
+  fcntl (fd, F_SETFL, old_fcntl_flags[fd] | FASYNC);
 #endif
   interrupts_deferred = 0;
 }
 
 void
-reset_sigio ()
+reset_sigio (fd)
+     int fd;
 {
-  unrequest_sigio ();
+#ifdef FASYNC
+  fcntl (fd, F_SETFL, old_fcntl_flags[fd]);
+#endif
 }
 
 #ifdef FASYNC          /* F_SETFL does not imply existence of FASYNC */
+/* XXX Uhm, FASYNC is not used anymore here. */
 
 void
 request_sigio ()
 {
+  /* XXX read_socket_hook is not global anymore.  Is blocking SIGIO
+     bad under X? */
+#if 0
   if (read_socket_hook)
     return;
+#endif
 
 #ifdef SIGWINCH
   sigunblock (sigmask (SIGWINCH));
 #endif
-  fcntl (fileno (TTY_INPUT (CURTTY())), F_SETFL, old_fcntl_flags | FASYNC);
+  sigunblock (sigmask (SIGIO));
 
   interrupts_deferred = 0;
 }
 
 void
-unrequest_sigio ()
-{
+unrequest_sigio (void)
+{ 
+  /* XXX read_socket_hook is not global anymore.  Is blocking SIGIO
+     bad under X? */
+#if 0
   if (read_socket_hook)
     return;
-
+#endif
+  
 #ifdef SIGWINCH
   sigblock (sigmask (SIGWINCH));
 #endif
-  fcntl (fileno (TTY_INPUT (CURTTY())), F_SETFL, old_fcntl_flags);
+  sigblock (sigmask (SIGIO));
   interrupts_deferred = 1;
 }
 
@@ -968,7 +1004,8 @@ request_sigio ()
   if (read_socket_hook)
     return;
 
-  ioctl (fileno (TTY_INPUT (CURTTY())), FIOASYNC, &on);
+  /* XXX CURTTY() is bogus here. */
+  ioctl (fileno (TTY_INPUT (CURTTY ())), FIOASYNC, &on);
   interrupts_deferred = 0;
 }
 
@@ -980,7 +1017,8 @@ unrequest_sigio ()
   if (read_socket_hook)
     return;
 
-  ioctl (fileno (TTY_INPUT (CURTTY())), FIOASYNC, &off);
+  /* XXX CURTTY() is bogus here. */
+  ioctl (fileno (TTY_INPUT (CURTTY ())), FIOASYNC, &off);
   interrupts_deferred = 1;
 }
 
@@ -1001,7 +1039,7 @@ request_sigio ()
 
   sigemptyset (&st);
   sigaddset (&st, SIGIO);
-  ioctl (fileno (TTY_INPUT (CURTTY())), FIOASYNC, &on);
+  ioctl (0, FIOASYNC, &on);     /* XXX This fails for multiple ttys. */
   interrupts_deferred = 0;
   sigprocmask (SIG_UNBLOCK, &st, (sigset_t *)0);
 }
@@ -1014,7 +1052,7 @@ unrequest_sigio ()
   if (read_socket_hook)
     return;
 
-  ioctl (fileno (TTY_INPUT (CURTTY())), FIOASYNC, &off);
+  ioctl (0, FIOASYNC, &off);  /* XXX This fails for multiple ttys. */
   interrupts_deferred = 1;
 }
 
@@ -1044,6 +1082,7 @@ unrequest_sigio ()
 #endif /* STRIDE */
 #endif /* FASYNC */
 #endif /* F_SETFL */
+#endif /* SIGIO */
 \f
 /* Saving and restoring the process group of Emacs's terminal.  */
 
@@ -1074,23 +1113,25 @@ int inherited_pgroup;
    group, redirect the TTY to point to our own process group.  We need
    to be in our own process group to receive SIGIO properly.  */
 void
-narrow_foreground_group ()
+narrow_foreground_group (int fd)
 {
   int me = getpid ();
 
-  setpgrp (0, inherited_pgroup);
+  if (! inherited_pgroup)
+    inherited_pgroup = getpgid (0);
+  /* XXX This only works on the controlling tty. */
   if (inherited_pgroup != me)
-    EMACS_SET_TTY_PGRP (fileno (stdin), &me); /* stdin is intentional here */
-  setpgrp (0, me);
+    EMACS_SET_TTY_PGRP (fd, &me);
+  setpgid (0, me);
 }
 
 /* Set the tty to our original foreground group.  */
 void
-widen_foreground_group ()
+widen_foreground_group (int fd)
 {
   if (inherited_pgroup != getpid ())
-    EMACS_SET_TTY_PGRP (fileno (stdin), &inherited_pgroup); /* stdin is intentional here */
-  setpgrp (0, inherited_pgroup);
+    EMACS_SET_TTY_PGRP (fd, &inherited_pgroup);
+  setpgid (0, inherited_pgroup);
 }
 
 #endif /* BSD_PGRPS */
@@ -1256,7 +1297,7 @@ int lmode;
 
 #ifndef F_SETOWN_BUG
 #ifdef F_SETOWN
-int old_fcntl_owner;
+int old_fcntl_owner[MAXDESC];
 #endif /* F_SETOWN */
 #endif /* F_SETOWN_BUG */
 
@@ -1284,16 +1325,14 @@ static struct tchars new_tchars = {-1,-1,-1,-1,-1,-1};
 void
 init_all_sys_modes (void)
 {
-  struct tty_output *tty = tty_list;
-  while (tty) {
+  struct tty_display_info *tty;
+  for (tty = tty_list; tty; tty = tty->next)
     init_sys_modes (tty);
-    tty = tty->next;
-  }
 }
 
 void
 init_sys_modes (tty_out)
-     struct tty_output *tty_out;
+     struct tty_display_info *tty_out;
 {
   struct emacs_tty tty;
 
@@ -1352,24 +1391,29 @@ nil means don't delete them until `list-processes' is run.  */);
 #endif /* VMS */
 
 #ifdef BSD_PGRPS
+#if 0
+  /* read_socket_hook is not global anymore.  I think doing this
+     unconditionally will not cause any problems. */
   if (! read_socket_hook && EQ (Vwindow_system, Qnil))
-    narrow_foreground_group ();
+#endif
+    narrow_foreground_group (fileno (TTY_INPUT (tty_out)));
 #endif
 
 #ifdef HAVE_WINDOW_SYSTEM
   /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
      needs the initialization code below.  */
-  if (!read_socket_hook && EQ (Vwindow_system, Qnil))
+  if (tty_out->input != stdin || EQ (Vwindow_system, Qnil))
 #endif
     {
-      EMACS_GET_TTY (fileno (TTY_INPUT (tty_out)), &tty_out->old_tty);
-
-      tty_out->old_tty_valid = 1;
+      if (! tty_out->old_tty)
+        tty_out->old_tty = (struct emacs_tty *) xmalloc (sizeof (struct emacs_tty));
+      
+      EMACS_GET_TTY (fileno (TTY_INPUT (tty_out)), tty_out->old_tty);
 
-      tty = tty_out->old_tty;
+      tty = *tty_out->old_tty;
 
 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
-      XSETINT (Vtty_erase_char, tty_out->old_tty.main.c_cc[VERASE]);
+      XSETINT (Vtty_erase_char, tty.main.c_cc[VERASE]);
 
 #ifdef DGUX
       /* This allows meta to be sent on 8th bit.  */
@@ -1390,7 +1434,7 @@ nil means don't delete them until `list-processes' is run.  */);
       tty.main.c_lflag &= ~IEXTEN;     /* Disable other editing characters.  */
 #endif
       tty.main.c_lflag |= ISIG;        /* Enable signals */
-      if (flow_control)
+      if (tty_out->flow_control)
        {
          tty.main.c_iflag |= IXON;     /* Enable start/stop output control */
 #ifdef IXANY
@@ -1403,17 +1447,40 @@ nil means don't delete them until `list-processes' is run.  */);
                                           on output */
       tty.main.c_oflag &= ~TAB3;       /* Disable tab expansion */
 #ifdef CS8
-      if (meta_key)
+      if (tty_out->meta_key)
        {
          tty.main.c_cflag |= CS8;      /* allow 8th bit on input */
          tty.main.c_cflag &= ~PARENB;/* Don't check parity */
        }
 #endif
-      tty.main.c_cc[VINTR] = quit_char;        /* C-g (usually) gives SIGINT */
-      /* Set up C-g for both SIGQUIT and SIGINT.
-        We don't know which we will get, but we handle both alike
-        so which one it really gives us does not matter.  */
-      tty.main.c_cc[VQUIT] = quit_char;
+      if (tty_out->input == stdin)
+        {
+          tty.main.c_cc[VINTR] = quit_char;    /* C-g (usually) gives SIGINT */
+          /* Set up C-g for both SIGQUIT and SIGINT.
+             We don't know which we will get, but we handle both alike
+             so which one it really gives us does not matter.  */
+          tty.main.c_cc[VQUIT] = quit_char;
+        }
+      else
+        {
+          /* We normally don't get interrupt or quit signals from tty
+             devices other than our controlling terminal; therefore,
+             we must handle C-g as normal input.  Unfortunately, this
+             means that the interrupt and quit feature must be
+             disabled on secondary ttys, or we would not even see the
+             keypress.
+
+             Note that even though emacsclient could have special code
+             to pass SIGINT to Emacs, we should _not_ enable
+             interrupt/quit keys for emacsclient frames.  This means
+             that we can't break out of loops in C code from a
+             secondary tty frame, but we can always decide what
+             display the C-g came from, which is more important from a
+             usability point of view.  (Consider the case when two
+             people work together using the same Emacs instance.)  */
+          tty.main.c_cc[VINTR] = CDISABLE;
+          tty.main.c_cc[VQUIT] = CDISABLE;
+        }
       tty.main.c_cc[VMIN] = 1; /* Input should wait for at least 1 char */
       tty.main.c_cc[VTIME] = 0;        /* no matter how long that takes.  */
 #ifdef VSWTCH
@@ -1444,7 +1511,7 @@ nil means don't delete them until `list-processes' is run.  */);
       tty.main.c_cc[VDISCARD] = CDISABLE;
 #endif /* VDISCARD */
 
-      if (flow_control)
+      if (tty_out->flow_control)
        {
 #ifdef VSTART
          tty.main.c_cc[VSTART] = '\021';
@@ -1480,7 +1547,7 @@ nil means don't delete them until `list-processes' is run.  */);
       tty.main.c_cc[VSUSP] = 255;
       tty.main.c_cc[VDSUSP] = 255;
 #endif /* IBMR2AIX */
-      if (flow_control)
+      if (tty_out->flow_control)
        {
 #ifdef VSTART
          tty.main.c_cc[VSTART] = '\021';
@@ -1501,7 +1568,7 @@ nil means don't delete them until `list-processes' is run.  */);
       tty.main.tt_char |= TT$M_NOECHO;
       if (meta_key)
        tty.main.tt_char |= TT$M_EIGHTBIT;
-      if (flow_control)
+      if (tty_out->flow_control)
        tty.main.tt_char |= TT$M_TTSYNC;
       else
        tty.main.tt_char &= ~TT$M_TTSYNC;
@@ -1528,7 +1595,7 @@ nil means don't delete them until `list-processes' is run.  */);
         set this */
       tty.tchars = new_tchars;
       tty.tchars.t_intrc = quit_char;
-      if (flow_control)
+      if (tty_out->flow_control)
        {
          tty.tchars.t_startc = '\021';
          tty.tchars.t_stopc = '\023';
@@ -1563,22 +1630,22 @@ nil means don't delete them until `list-processes' is run.  */);
         we have an unlocked terminal at the start. */
 
 #ifdef TCXONC
-      if (!flow_control) ioctl (fileno (TTY_INPUT (tty_out)), TCXONC, 1);
+      if (!tty_out->flow_control) ioctl (fileno (TTY_INPUT (tty_out)), TCXONC, 1);
 #endif
 #ifndef APOLLO
 #ifdef TIOCSTART
-      if (!flow_control) ioctl (fileno (TTY_INPUT (tty_out)), TIOCSTART, 0);
+      if (!tty_out->flow_control) ioctl (fileno (TTY_INPUT (tty_out)), TIOCSTART, 0);
 #endif
 #endif
 
 #if defined (HAVE_TERMIOS) || defined (HPUX9)
 #ifdef TCOON
-      if (!flow_control) tcflow (fileno (TTY_INPUT (tty_out)), TCOON);
+      if (!tty_out->flow_control) tcflow (fileno (TTY_INPUT (tty_out)), TCOON);
 #endif
 #endif
 
 #ifdef AIXHFT
-      hft_init ();
+      hft_init (tty_out);
 #ifdef IBMR2AIX
       {
        /* IBM's HFT device usually thinks a ^J should be LF/CR.  We need it
@@ -1604,9 +1671,10 @@ nil means don't delete them until `list-processes' is run.  */);
 #ifndef F_SETOWN_BUG
 #ifdef F_GETOWN                /* F_SETFL does not imply existence of F_GETOWN */
   if (interrupt_input
-      && ! read_socket_hook && EQ (Vwindow_system, Qnil))
+      && (tty_out->input != stdin || EQ (Vwindow_system, Qnil)))
     {
-      old_fcntl_owner = fcntl (fileno (TTY_INPUT (tty_out)), F_GETOWN, 0);
+      old_fcntl_owner[fileno (TTY_INPUT (tty_out))] =
+        fcntl (fileno (TTY_INPUT (tty_out)), F_GETOWN, 0);
       fcntl (fileno (TTY_INPUT (tty_out)), F_SETOWN, getpid ());
       init_sigio (fileno (TTY_INPUT (tty_out)));
     }
@@ -1630,6 +1698,8 @@ nil means don't delete them until `list-processes' is run.  */);
 #else
   setbuf (TTY_OUTPUT (tty_out), (char *) _sobuf);
 #endif
+
+#if 0                /* We always need this with multi-tty support. */
 #ifdef HAVE_WINDOW_SYSTEM
   /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
      needs the initialization code below.  */
@@ -1641,13 +1711,15 @@ nil means don't delete them until `list-processes' is run.  */);
 #endif
       )
 #endif
-    set_terminal_modes (tty_out);
+#endif
+    tty_set_terminal_modes (tty_out->display);
 
   if (!tty_out->term_initted)
     {
       Lisp_Object tail, frame;
       FOR_EACH_FRAME (tail, frame)
         {
+          /* XXX This needs to be revised. */
           if (FRAME_TERMCAP_P (XFRAME (frame))
               && FRAME_TTY (XFRAME (frame)) == tty_out)
             init_frame_faces (XFRAME (frame));
@@ -1678,12 +1750,12 @@ nil means don't delete them until `list-processes' is run.  */);
    At the time this is called, init_sys_modes has not been done yet.  */
 
 int
-tabs_safe_p ()
+tabs_safe_p (int fd)
 {
-  struct emacs_tty tty;
+  struct emacs_tty etty;
 
-  EMACS_GET_TTY (fileno (TTY_INPUT (CURTTY())), &tty);
-  return EMACS_TTY_TABS_OK (&tty);
+  EMACS_GET_TTY (fd, &etty);
+  return EMACS_TTY_TABS_OK (&etty);
 }
 \f
 /* Get terminal size from system.
@@ -1691,9 +1763,7 @@ tabs_safe_p ()
    We store 0 if there's no valid information.  */
 
 void
-get_tty_size (tty_out, widthp, heightp)
-     struct tty_output *tty_out;
-     int *widthp, *heightp;
+get_tty_size (int fd, int *widthp, int *heightp)
 {
 
 #ifdef TIOCGWINSZ
@@ -1701,7 +1771,7 @@ get_tty_size (tty_out, widthp, heightp)
   /* BSD-style.  */
   struct winsize size;
 
-  if (ioctl (fileno (TTY_INPUT (tty_out)), TIOCGWINSZ, &size) == -1)
+  if (ioctl (fd, TIOCGWINSZ, &size) == -1)
     *widthp = *heightp = 0;
   else
     {
@@ -1715,7 +1785,7 @@ get_tty_size (tty_out, widthp, heightp)
   /* SunOS - style.  */
   struct ttysize size;
 
-  if (ioctl (fileno (TTY_INPUT (tty_out)), TIOCGSIZE, &size) == -1)
+  if (ioctl (fd, TIOCGSIZE, &size) == -1)
     *widthp = *heightp = 0;
   else
     {
@@ -1728,7 +1798,7 @@ get_tty_size (tty_out, widthp, heightp)
 
   struct sensemode tty;
 
-  SYS$QIOW (0, fileno (TTY_INPUT (CURTTY())), IO$_SENSEMODE, &tty, 0, 0,
+  SYS$QIOW (0, fd, IO$_SENSEMODE, &tty, 0, 0,
            &tty.class, 12, 0, 0, 0, 0);
   *widthp = tty.scr_wid;
   *heightp = tty.scr_len;
@@ -1741,7 +1811,6 @@ get_tty_size (tty_out, widthp, heightp)
   *widthp = 0;
   *heightp = 0;
 #endif
-
 #endif /* not VMS */
 #endif /* not SunOS-style */
 #endif /* not BSD-style */
@@ -1788,21 +1857,17 @@ set_window_size (fd, height, width)
 void
 reset_all_sys_modes (void)
 {
-  struct tty_output *tty = tty_list;
-  while (tty) {
+  struct tty_display_info *tty;
+  for (tty = tty_list; tty; tty = tty->next)
     reset_sys_modes (tty);
-    tty = tty->next;
-  }
 }
 
-/* Prepare the terminal for exiting Emacs; move the cursor to the
+/* Prepare the terminal for closing it; move the cursor to the
    bottom of the frame, turn off interrupt-driven I/O, etc.  */
 void
 reset_sys_modes (tty_out)
-     struct tty_output *tty_out;
+     struct tty_display_info *tty_out;
 {
-  struct frame *sf;
-
   if (noninteractive)
     {
       fflush (stdout);
@@ -1810,23 +1875,29 @@ reset_sys_modes (tty_out)
     }
   if (!tty_out->term_initted)
     return;
+#if 0                           /* We always need to do this with multi-tty support. */
 #ifdef HAVE_WINDOW_SYSTEM
   /* Emacs' window system on MSDOG uses the `internal terminal' and therefore
      needs the clean-up code below.  */
-  if (!EQ (Vwindow_system, Qnil)
+  if (tty_out->input != stdin
+      || (!EQ (Vwindow_system, Qnil)
 #ifndef WINDOWSNT
       /* When running in tty mode on NT/Win95, we have a read_socket
         hook, but still need the rest of the clean-up code below.  */
       || read_socket_hook
 #endif
-      )
+          ))
     return;
 #endif
-  sf = SELECTED_FRAME ();
-  cursor_to (FRAME_LINES (sf) - 1, 0);
-  clear_end_of_line (FRAME_COLS (sf));
-  /* clear_end_of_line may move the cursor */
-  cursor_to (FRAME_LINES (sf) - 1, 0);
+#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);
+  
 #if defined (IBMR2AIX) && defined (AIXHFT)
   {
     /* HFT devices normally use ^J as a LF/CR.  We forced it to
@@ -1838,12 +1909,12 @@ reset_sys_modes (tty_out)
   }
 #endif
 
-  reset_terminal_modes (tty_out);
+  tty_reset_terminal_modes (tty_out->display);
   fflush (TTY_OUTPUT (tty_out));
 #ifdef BSD_SYSTEM
 #ifndef BSD4_1
   /* Avoid possible loss of output when changing terminal modes.  */
-  fsync (TTY_OUTPUT (tty_out));
+  fsync (fileno (TTY_OUTPUT (tty_out)));
 #endif
 #endif
 
@@ -1852,8 +1923,9 @@ reset_sys_modes (tty_out)
 #ifdef F_SETOWN                /* F_SETFL does not imply existence of F_SETOWN */
   if (interrupt_input)
     {
-      reset_sigio ();
-      fcntl (fileno (TTY_INPUT (tty_out)), F_SETOWN, old_fcntl_owner);
+      reset_sigio (fileno (TTY_INPUT (tty_out)));
+      fcntl (fileno (TTY_INPUT (tty_out)), F_SETOWN,
+             old_fcntl_owner[fileno (TTY_INPUT (tty_out))]);
     }
 #endif /* F_SETOWN */
 #endif /* F_SETOWN_BUG */
@@ -1864,12 +1936,12 @@ reset_sys_modes (tty_out)
 #endif /* F_SETFL */
 #ifdef BSD4_1
   if (interrupt_input)
-    reset_sigio ();
+    reset_sigio (fileno (TTY_INPUT (tty_out)));
 #endif /* BSD4_1 */
 
-  if (tty_out->old_tty_valid)
+  if (tty_out->old_tty)
     while (EMACS_SET_TTY (fileno (TTY_INPUT (tty_out)),
-                          &tty_out->old_tty, 0) < 0 && errno == EINTR)
+                          tty_out->old_tty, 0) < 0 && errno == EINTR)
       ;
 
 #ifdef MSDOS   /* Demacs 1.1.2 91/10/20 Manabu Higashida */
@@ -1888,7 +1960,7 @@ reset_sys_modes (tty_out)
 #endif
 
 #ifdef BSD_PGRPS
-  widen_foreground_group ();
+  widen_foreground_group (fileno (TTY_INPUT (tty_out)));
 #endif
 }
 \f
@@ -2170,7 +2242,8 @@ init_sigio (fd)
   request_sigio ();
 }
 
-reset_sigio ()
+reset_sigio (fd)
+     int fd;
 {
   unrequest_sigio ();
 }
@@ -2629,7 +2702,7 @@ sys_select (nfds, rfds, wfds, efds, timeout)
     }
   return ravail;
 }
-#endif /* not WINDOWSNT */
+#endif not WINDOWSNT
 
 /* Read keyboard input into the standard buffer,
    waiting for at least one character.  */
@@ -2644,6 +2717,8 @@ sys_select (nfds, rfds, wfds, efds, timeout)
 void
 read_input_waiting ()
 {
+  /* XXX This needs to be updated for multi-tty support.  Does
+     anybody need to emulate select these days?  */
   int nread, i;
   extern int quit_char;
 
@@ -2704,6 +2779,10 @@ read_input_waiting ()
     }
 }
 
+#if !defined (HAVE_SELECT) || defined (BROKEN_SELECT_NON_X)
+#define select sys_select
+#endif
+
 #endif /* not HAVE_SELECT */
 #endif /* not VMS */
 #endif /* not MSDOS */
@@ -2720,12 +2799,13 @@ init_sigio (fd)
 }
 
 void
-reset_sigio ()
+reset_sigio (fd)
+     int fd;
 {
   if (noninteractive)
     return;
   lmode = ~LINTRUP & lmode;
-  ioctl (0, TIOCLSET, &lmode);
+  ioctl (fd, TIOCLSET, &lmode);
 }
 
 void
@@ -3173,7 +3253,7 @@ sys_getenv (name)
 #undef abort
 sys_abort ()
 {
-  reset_sys_modes ();
+  reset_all_sys_modes ();
   LIB$SIGNAL (SS$_DEBUG);
 }
 #endif /* abort */
@@ -5098,7 +5178,7 @@ srandom (seed)
 
 /* Called from init_sys_modes.  */
 void
-hft_init ()
+hft_init (struct tty_display_info *tty_out)
 {
   int junk;
 
@@ -5144,16 +5224,12 @@ hft_init ()
     keymap.hfkey[1].hf_char = 127;
     hftctl (0, HFSKBD, &buf);
   }
-  /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly
-     at times.  */
-  TTY_LINE_INS_DEL_OK (CURTTY ()) = 0;
-  TTY_CHAR_INS_DEL_OK (CURTTY ()) = 0;
 }
 
 /* Reset the rubout key to backspace.  */
 
 void
-hft_reset ()
+hft_reset (struct tty_display_info *tty_out)
 {
   struct hfbuf buf;
   struct hfkeymap keymap;