changeset 53341:d4e6a050c9b1

Bugfix festival. lib-src/emacsclient.c (main_argc, main_argv): New variables. (main): Initialize them. (fail): Use them. (window_change, copy_from_to): Don't kill if emacs_pid is zero. (pty_conversation): Watch the command socket, too. Read emacs_pid here. Emacs and emacsclient could deadlock if Emacs tried to do a reset_sys_modes before sending its pid. lisp/server.el: Automatically delete the client frame when done editing. (server-frames): New variable. (server-process-filter, server-sentinel, server-buffer-done): Use it. (server-process-filter): Do a redisplay before evaluating other parameters. (Prevents "emacsclient -h -e '(delete-frame)'" from messing up the system. src/dispextern.h: Update prototypes. src/dispnew.c (window_change_signal): Do nothing if !term_initted. (init_display): Set the frame size from the tty data after term_init. src/emacs.c (main): Make sure things that init_sys_modes needs are initialized before init_display (which calls init_sys_modes now). (sort_args): Use xfree, not free. (shut_down_emacs) [!EMACS_HAVE_TTY_PGRP]: Use reset_all_sys_modes instead of reset_sys_modes. src/frame.c (make_terminal_frame): Sigh. Move terminal initialization back to the middle of frame setup. Handle errors by making sure that the delete_tty() called from term_init() will see and delete this frame. (Fdelete_frame): Kill the frame before calling delete_tty(). Fix condition for tty deletion. src/keyboard.c (Fset_input_mode): Use reset_sys_modes on the current terminal only. src/lisp.h: Remove duplicate prototypes. src/msdos.c (croak): use reset_all_sys_modes(). src/sysdeps.c (init_baud_rate): Added tty parameter, use it instead of CURTTY. (child_setup_tty): Reset sigio on stdin, not CURTTY(). (reset_sigio): Added fd parameter, put explicit fcntl there. (request_sigio, unrequest_sigio)[FASYNC]: Simply block/unblock the SIGIO signal, don't touch the file params. There are multiple ttys now, and we can't disable the SIGIO from emacsclient. (get_tty_size)[VMS]: Use tty_out instead of CURTTY(). (reset_sys_modes): Don't call cursor_to, clear_end_of_line; call cmgoto and tty_clear_end_of_line instead. The frame may already be dead. Updated reset_sigio call. src/term.c (clear_and_of_line): Separate tty-dependent stuff to tty_clear_end_of_line() for reset_sys_modes. (tty_clear_end_of_line): New function. (term_init): Added frame parameter, don't use selected_frame. Set the frame's output_data.tty value (in case there is an error later). Set the frame size in Wcm, not in the frame. Only free the termcap buffer if there is a termcap-related error. Call init_sys_modes last, not first. (deleting_tty): New variable. (delete_tty): Use it for handling recursive calls. Free deleted tty, except its Wcm (there is still a dangling reference somewhere). git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-19
author Karoly Lorentey <lorentey@elte.hu>
date Mon, 29 Dec 2003 07:16:26 +0000
parents db645482d6bc
children 201b17b0f2e5
files README.multi-tty lib-src/emacsclient.c lisp/server.el src/Makefile.in src/dispextern.h src/dispnew.c src/emacs.c src/frame.c src/keyboard.c src/lisp.h src/msdos.c src/sysdep.c src/term.c
diffstat 13 files changed, 269 insertions(+), 195 deletions(-) [+]
line wrap: on
line diff
--- a/README.multi-tty	Sun Dec 28 22:28:52 2003 +0000
+++ b/README.multi-tty	Mon Dec 29 07:16:26 2003 +0000
@@ -67,11 +67,7 @@
    specify a terminal device (`tty' parameter) and a terminal type
    (`tty-type' parameter) to `make-terminal-frame'. `tty' must be a
    terminal device created by the updated emacsclient, or there will
-   be problems with terminal input and window resizes.  (The kernel
-   notifies processes about pending input or terminal resizes only on
-   the controlling terminal, so we need emacsclient to sit on the real
-   terminal device, create SIGIO signals upon terminal input, and
-   forward SIGWINCH signals to us.)
+   be problems with terminal input and window resizes.  
 
    You can test for the presence of multiple terminal support by
    testing for the `multi-tty' feature.
@@ -160,6 +156,9 @@
    terminal.  Note that this means that multi-tty does not work with
    raw ttys!)
 
+   (Update: This is bullshit.  There is a read_input_waiting function,
+   extend that somehow.)
+
 -- Make make-terminal-frame look up the `tty' and `tty-type' frame
    parameters from the currently selected terminal before the global
    default.
@@ -191,6 +190,13 @@
 
    (Done.)
 
+-- Restore tty screen after closing the terminal.
+
+   (Done, we do the same as Emacs 21.2 for all terminals.)
+
+-- 'TERM=dumb src/emacs' does not restore the terminal state.
+   
+   (Done.)
 
 THINGS TO DO
 ------------
@@ -216,35 +222,38 @@
 
 ** Export delete_tty to the Lisp environment, for emacsclient.
 
-** Restore tty screen after closing the terminal.
-
-** 'TERM=dumb src/emacs' does not restore the terminal state.
-
 ** C-g should work on secondary terminals.
 
 ** Make parts of struct tty_output accessible from Lisp.  The device
    name and the type is sufficient.
 
 ** Find out why does Emacs abort when it wants to close its
-   controlling tty.
+   controlling tty.  Hint: chan_process[] array.  Hey, maybe
+   noninterrupt-IO would work, too?
 
 ** 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 necessarily a good idea.
 
-** Support raw secondary terminals.  (This one is tricky, SIGIO works
-   only on the controlling terminal.  The emacsclient solution works
-   nicely, so this is not that important anyway.)
+** Support raw secondary terminals.  (Note that SIGIO works only on
+   the controlling terminal.) Hint: extend read_input_waiting() for
+   multiple ttys and hopefully this will be fixed.
 
 ** What does interrupt_input do?  I tried to disable it for raw
    secondary tty support, but it does not seem to do anything useful.
 
+** Issue with SIGIO: it needs to be disabled during redisplay.  See if
+   fcntl() kernel behaviour could be emulated by emacsclient.
+
 ** Move optimalization parameters (costs) from union output_data to
    a backend-neutral per-device structure.
 
 ** Find out the best way to support suspending Emacs with multiple
    ttys.
 
+** Deal with SIGHUP in Emacs and in emacsclient.  (After this, the
+   server-frames may be removed from server.el.)
+
 ** Do tty output through term_hooks, like all other display backends.
 
 ** Fix X support.
--- a/lib-src/emacsclient.c	Sun Dec 28 22:28:52 2003 +0000
+++ b/lib-src/emacsclient.c	Mon Dec 29 07:16:26 2003 +0000
@@ -102,6 +102,12 @@
 /* Name used to invoke this program.  */
 char *progname;
 
+/* The first argument to main. */
+int main_argc;
+
+/* The second argument to main. */
+char **main_argv;
+
 /* Nonzero means don't wait for a response from Emacs.  --no-wait.  */
 int nowait = 0;
 
@@ -294,14 +300,12 @@
   defined-- exit with an errorcode.
 */
 void
-fail (argc, argv)
-     int argc;
-     char **argv;
+fail ()
 {
   if (alternate_editor)
     {
       int i = optind - 1;
-      execvp (alternate_editor, argv + i);
+      execvp (alternate_editor, main_argv + i);
       return;
     }
   else
@@ -603,7 +607,7 @@
 #endif /* not SunOS-style */
 #endif /* not BSD-style */
 
-  if (width != 0 && height != 0)
+  if (emacs_pid && width && height)
     kill (emacs_pid, SIGWINCH);
 }
 
@@ -721,7 +725,7 @@
       if (r < 0)
         return 0;               /* Error */
 
-      if (sigio)
+      if (emacs_pid && sigio)
         {
           kill (emacs_pid, SIGIO);
         }
@@ -730,8 +734,10 @@
 }
 
 int
-pty_conversation ()
+pty_conversation (FILE *in)
 {
+  char *str;
+  char string[BUFSIZ];              
   fd_set set;
 
   in_conversation = 1;
@@ -742,6 +748,7 @@
     FD_ZERO (&set);
     FD_SET (master, &set);
     FD_SET (1, &set);
+    FD_SET (fileno (in), &set);
     res = select (FD_SETSIZE, &set, NULL, NULL, NULL);
     if (res < 0)
       {
@@ -762,6 +769,24 @@
             if (! copy_from_to (1, master, 1))
               return 1;
           }
+        if (FD_ISSET (fileno (in), &set))
+          {
+            if (! emacs_pid)
+              {
+                /* Get the pid of the Emacs process.
+                   XXX Is there is some nifty libc/kernel feature for doing this?
+                */
+                str = fgets (string, BUFSIZ, in);
+                if (! str)
+                  {
+                    reset_tty ();
+                    fprintf (stderr, "%s: %s\n", progname, str);
+                    fail ();
+                  }
+                
+                emacs_pid = atoi (str);
+              }
+          }
       }
   }
   return 1;
@@ -828,6 +853,8 @@
   char *cwd, *str;
   char string[BUFSIZ];
 
+  main_argc = argc;
+  main_argv = argv;
   progname = argv[0];
 
   /* Process options.  */
@@ -1087,19 +1114,7 @@
 
   if (here)
     {
-      /* First of all, get the pid of the Emacs process.
-         XXX Is there is some nifty libc/kernel feature for doing this?
-       */
-      str = fgets (string, BUFSIZ, in);
-      emacs_pid = atoi (str);
-      if (emacs_pid == 0)
-        {
-          reset_tty ();
-          fprintf (stderr, "%s: %s\n", argv[0], str);
-          fail (argc, argv);
-        }
-      
-      if (! pty_conversation ())
+      if (! pty_conversation (out))
         {
           reset_tty ();
           fprintf (stderr, "%s: ", argv[0]);
--- a/lisp/server.el	Sun Dec 28 22:28:52 2003 +0000
+++ b/lisp/server.el	Mon Dec 29 07:16:26 2003 +0000
@@ -106,6 +106,13 @@
 that can be given to the server process to identify a client.
 When a buffer is marked as \"done\", it is removed from this list.")
 
+(defvar server-frames nil
+  "List of current server frames.
+Each element is (CLIENTID FRAME) where CLIENTID is a string
+that can be given to the server process to identify a client.
+When all the buffers of the client are marked as \"done\", 
+the frame is deleted.")
+
 (defvar server-buffer-clients nil
   "List of client ids for clients requesting editing of current buffer.")
 (make-variable-buffer-local 'server-buffer-clients)
@@ -178,6 +185,7 @@
     ;; Remove PROC from the list of clients.
     (when client
       (setq server-clients (delq client server-clients))
+      (setq server-frames (delq client server-frames))
       (dolist (buf (cdr client))
 	(with-current-buffer buf
 	  ;; Remove PROC from the clients of each buffer.
@@ -326,6 +334,8 @@
 	      (setq request (substring request (match-end 0)))
 	      (condition-case err
 		  (let ((frame (make-terminal-frame `((tty . ,pty) (tty-type . ,type)))))
+		    (setq server-frames (cons (list (car client) frame) server-frames))
+		    (sit-for 0)
 		    (process-send-string proc (concat (number-to-string (emacs-pid)) "\n"))
 		    (select-frame frame))
 		(error (process-send-string proc (nth 1 err))
@@ -368,6 +378,9 @@
       (if (null (cdr client))
 	  ;; This client is empty; get rid of it immediately.
 	  (progn
+	    (let ((frame (cadr (assq (car client) server-frames))))
+	      ;; Close the client's frame.
+	      (when frame (delete-frame frame)))
 	    (delete-process proc)
 	    (server-log "Close empty client" proc))
 	;; We visited some buffer for this client.
@@ -454,6 +467,9 @@
 	;; If client now has no pending buffers,
 	;; tell it that it is done, and forget it entirely.
 	(unless (cdr client)
+	  (let ((frame (cadr (assq (car client) server-frames))))
+	    ;; Close the client's frame.
+	    (when frame (delete-frame frame)))
 	  (delete-process (car client))
 	  (server-log "Close" (car client))
 	  (setq server-clients (delq client server-clients))))
--- a/src/Makefile.in	Sun Dec 28 22:28:52 2003 +0000
+++ b/src/Makefile.in	Mon Dec 29 07:16:26 2003 +0000
@@ -1119,7 +1119,7 @@
    composite.h $(config_h)
 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)
+   frame.h atimer.h window.h msdos.h dosfns.h keyboard.h cm.h $(config_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)
--- a/src/dispextern.h	Sun Dec 28 22:28:52 2003 +0000
+++ b/src/dispextern.h	Mon Dec 29 07:16:26 2003 +0000
@@ -2566,7 +2566,7 @@
 void request_sigio P_ ((void));
 void unrequest_sigio P_ ((void));
 int tabs_safe_p P_ ((struct tty_output *));
-void init_baud_rate P_ ((void));
+void init_baud_rate P_ ((struct tty_output *));
 void init_sigio P_ ((int));
 
 /* Defined in xfaces.c */
@@ -2743,6 +2743,7 @@
 extern void clear_frame P_ ((void));
 extern void clear_end_of_line P_ ((int));
 extern void clear_end_of_line_raw P_ ((int));
+extern void tty_clear_end_of_line P_ ((struct tty_output *, int));
 extern void delete_glyphs P_ ((int));
 extern void ins_del_lines P_ ((int, int));
 extern int string_cost P_ ((char *));
@@ -2750,7 +2751,7 @@
 extern void calculate_costs P_ ((struct frame *));
 extern void set_tty_color_mode P_ ((struct frame *, Lisp_Object));
 extern void tty_setup_colors P_ ((struct tty_output *, int));
-extern struct tty_output *term_init P_ ((char *, char *));
+extern struct tty_output *term_init P_ ((Lisp_Object, char *, char *));
 extern struct tty_output *term_dummy_init P_ ((void));
 extern void fatal P_ ((/* char *, ... */));
 void cursor_to P_ ((int, int));
--- a/src/dispnew.c	Sun Dec 28 22:28:52 2003 +0000
+++ b/src/dispnew.c	Mon Dec 29 07:16:26 2003 +0000
@@ -5921,11 +5921,12 @@
   /* The frame size change obviously applies to a single
      termcap-controlled terminal, but we can't decide which.
      Therefore, we resize the frames corresponding to each tty.
-     
-     XXX In fact we only get the signal for the initial terminal.
   */
   for (tty = tty_list; tty; tty = tty->next) {
 
+    if (! tty->term_initted)
+      continue;
+    
     get_tty_size (tty, &width, &height);
     
     {
@@ -6623,8 +6624,13 @@
   }
 #endif /* VMS */
 
-  term_init (0, terminal_type);
-
+  {
+    struct tty_output *tty;
+    
+    tty = term_init (selected_frame, 0, terminal_type);
+    change_frame_size (XFRAME (selected_frame), FrameRows (tty), FrameCols (tty), 0, 0, 0);
+  }
+  
   {
     struct frame *sf = SELECTED_FRAME ();
     int width = FRAME_TOTAL_COLS (sf);
--- a/src/emacs.c	Sun Dec 28 22:28:52 2003 +0000
+++ b/src/emacs.c	Mon Dec 29 07:16:26 2003 +0000
@@ -1561,6 +1561,13 @@
 #endif  /* end #ifdef HAVE_NTGUI */
     }
 
+#ifndef MAC_OS8
+  /* Called before init_window_once for Mac OS Classic.  */
+  init_keyboard ();	/* This too must precede init_sys_modes.  */
+#endif
+#ifdef VMS
+  init_vmsproc ();	/* And this too.  */
+#endif /* VMS */
   if (!noninteractive)
     {
 #ifdef VMS
@@ -1568,14 +1575,6 @@
 #endif /* VMS */
       init_display ();	/* Determine terminal type.  Calls init_sys_modes.  */
     }
-#ifndef MAC_OS8
-  /* Called before init_window_once for Mac OS Classic.  */
-  init_keyboard ();	/* This too must precede init_sys_modes.  */
-#endif
-#ifdef VMS
-  init_vmsproc ();	/* And this too.  */
-#endif /* VMS */
-  /* init_sys_modes (); */	/* Init system terminal modes (RAW or CBREAK, etc.).  */
 #if defined (HAVE_X_WINDOWS) || defined (WINDOWSNT)
   init_xfns ();
 #endif /* HAVE_X_WINDOWS */
@@ -1910,9 +1909,9 @@
 
   bcopy (new, argv, sizeof (char *) * argc);
 
-  free (options);
-  free (new);
-  free (priority);
+  xfree (options);
+  xfree (new);
+  xfree (priority);
 }
 
 DEFUN ("kill-emacs", Fkill_emacs, Skill_emacs, 0, 1, "P",
@@ -1999,7 +1998,7 @@
   }
 #else
   fflush (stdout);
-  reset_sys_modes ();
+  reset_all_sys_modes ();
 #endif
 
   stuff_buffered_input (stuff);
--- a/src/frame.c	Sun Dec 28 22:28:52 2003 +0000
+++ b/src/frame.c	Mon Dec 29 07:16:26 2003 +0000
@@ -485,13 +485,6 @@
   register struct frame *f;
   Lisp_Object frame;
   char name[20];
-  struct tty_output *tty;
-
-  /* init_term may throw an error, so create the tty first. */
-  if (initialized)
-    tty = term_init (tty_name, tty_type);
-  else
-    tty = term_dummy_init ();
   
 #ifdef MULTI_KBOARD
   if (!initial_kboard)
@@ -550,9 +543,23 @@
 #ifdef MAC_OS8
   make_mac_terminal_frame (f);
 #else
-  f->output_method = output_termcap;
-  f->output_data.tty = tty;
-  f->output_data.tty->top_frame = frame;
+  {
+    struct tty_output *tty;
+    f->output_method = output_termcap;
+    
+    if (initialized)
+      {
+        /* Note that term_init may signal an error, but then it is its
+           responsibility to make sure this frame is deleted. */
+        f->output_data.tty = term_init (frame, tty_name, tty_type);
+      }
+    else
+      {
+        /* init_display() will reinitialize the terminal with correct values after dump. */
+        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;
@@ -1383,25 +1390,33 @@
 
   if (FRAME_TERMCAP_P (f))
     {
-      /* See if the terminal needs to be closed. */
       Lisp_Object tail, frame1;
       int delete = 1;
+      struct tty_output *tty = FRAME_TTY (f);
+
+      /* delete_tty will call us recursively, so better kill the
+         frame now. */
+      f->output_data.nothing = 0;
       
+      /* See if the terminal needs to be closed. */
       FOR_EACH_FRAME (tail, frame1)
         {
-          if (!FRAME_LIVE_P (XFRAME (frame1)) &&
-              FRAME_TERMCAP_P (XFRAME (frame1)) &&
-              FRAME_TTY (XFRAME (frame1)) == FRAME_TTY (f))
+          if (frame1 != frame
+              && FRAME_LIVE_P (XFRAME (frame1))
+              && FRAME_TERMCAP_P (XFRAME (frame1))
+              && FRAME_TTY (XFRAME (frame1)) == FRAME_TTY (f))
             {
               delete = 0;
               break;
             }
         }
       if (delete)
-        delete_tty (FRAME_TTY (f));
+        delete_tty (tty);
     }
-      
-  f->output_data.nothing = 0;
+  else
+    {
+      f->output_data.nothing = 0;
+    }
 
   /* If we've deleted the last_nonminibuf_frame, then try to find
      another one.  */
--- a/src/keyboard.c	Sun Dec 28 22:28:52 2003 +0000
+++ b/src/keyboard.c	Mon Dec 29 07:16:26 2003 +0000
@@ -10433,7 +10433,7 @@
 
 #ifndef DOS_NT
   /* this causes startup screen to be restored and messes with the mouse */
-  reset_all_sys_modes ();
+  reset_sys_modes (CURTTY ());
 #endif
 
 #ifdef SIGIO
@@ -10461,17 +10461,17 @@
 
   flow_control = !NILP (flow);
   if (NILP (meta))
-    FRAME_TTY (SELECTED_FRAME ())->meta_key = 0;
+    CURTTY ()->meta_key = 0;
   else if (EQ (meta, Qt))
-    FRAME_TTY (SELECTED_FRAME ())->meta_key = 1;
+    CURTTY ()->meta_key = 1;
   else
-    FRAME_TTY (SELECTED_FRAME ())->meta_key = 2;
+    CURTTY ()->meta_key = 2;
   if (!NILP (quit))
     /* Don't let this value be out of range.  */
-    quit_char = XINT (quit) & (FRAME_TTY (SELECTED_FRAME ())->meta_key ? 0377 : 0177);
+    quit_char = XINT (quit) & (CURTTY ()->meta_key ? 0377 : 0177);
 
 #ifndef DOS_NT
-  init_all_sys_modes ();
+  init_sys_modes (CURTTY ());
 #endif
 
 #ifdef POLL_FOR_INPUT
--- a/src/lisp.h	Sun Dec 28 22:28:52 2003 +0000
+++ b/src/lisp.h	Mon Dec 29 07:16:26 2003 +0000
@@ -2942,8 +2942,6 @@
 /* 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 sys_subshell P_ ((void));
 extern void sys_suspend P_ ((void));
 extern void discard_tty_input P_ ((void));
@@ -2957,7 +2955,6 @@
 extern void setup_pty P_ ((int));
 extern int set_window_size P_ ((int, int, int));
 extern void create_process P_ ((Lisp_Object, char **, Lisp_Object));
-extern void init_baud_rate P_ ((void));
 extern int emacs_open P_ ((const char *, int, int));
 extern int emacs_close P_ ((int));
 extern int emacs_read P_ ((int, char *, unsigned int));
--- a/src/msdos.c	Sun Dec 28 22:28:52 2003 +0000
+++ b/src/msdos.c	Mon Dec 29 07:16:26 2003 +0000
@@ -4858,7 +4858,7 @@
      char *badfunc;
 {
   fprintf (stderr, "%s not yet implemented\r\n", badfunc);
-  reset_sys_modes ();
+  reset_all_sys_modes ();
   exit (1);
 }
 
--- a/src/sysdep.c	Sun Dec 28 22:28:52 2003 +0000
+++ b/src/sysdep.c	Mon Dec 29 07:16:26 2003 +0000
@@ -184,6 +184,7 @@
 #include "termopts.h"
 #include "dispextern.h"
 #include "process.h"
+#include "cm.h"  /* for reset_sys_modes */
 
 #ifdef WINDOWSNT
 #include <direct.h>
@@ -330,7 +331,7 @@
 #endif /* SIGTSTP */
 
 void
-init_baud_rate ()
+init_baud_rate (struct tty_output *tty)
 {
   if (noninteractive)
     emacs_ospeed = 0;
@@ -345,7 +346,7 @@
 #ifdef VMS
       struct sensemode sg;
 
-      SYS$QIOW (0, fileno (TTY_INPUT (CURTTY())), IO$_SENSEMODE, &sg, 0, 0,
+      SYS$QIOW (0, fileno (TTY_INPUT (tty)), IO$_SENSEMODE, &sg, 0, 0,
 		&sg.class, 12, 0, 0, 0, 0 );
       emacs_ospeed = sg.xmit_baud;
 #else /* not VMS */
@@ -353,7 +354,7 @@
       struct termios sg;
 
       sg.c_cflag = B9600;
-      tcgetattr (fileno (TTY_INPUT (CURTTY())), &sg);
+      tcgetattr (fileno (TTY_INPUT (tty)), &sg);
       emacs_ospeed = cfgetospeed (&sg);
 #if defined (USE_GETOBAUD) && defined (getobaud)
       /* m88k-motorola-sysv3 needs this (ghazi@noc.rutgers.edu) 9/1/94. */
@@ -366,16 +367,16 @@
 
       sg.c_cflag = B9600;
 #ifdef HAVE_TCATTR
-      tcgetattr (fileno (TTY_INPUT (CURTTY())), &sg);
+      tcgetattr (fileno (TTY_INPUT (tty)), &sg);
 #else
-      ioctl (fileno (TTY_INPUT (CURTTY())), TCGETA, &sg);
+      ioctl (fileno (TTY_INPUT (tty)), 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 (fileno (TTY_INPUT (tty)), TIOCGETP, &sg) < 0)
 	abort ();
       emacs_ospeed = sg.sg_ospeed;
 #endif /* not HAVE_TERMIO */
@@ -649,7 +650,7 @@
 
 #ifdef BSD4_1
   if (interrupt_input)
-    reset_sigio ();
+    reset_sigio (0);
 #endif /* BSD4_1 */
 #ifdef RTU
   {
@@ -915,6 +916,7 @@
      int fd;
 {
 #ifdef FASYNC
+  /* XXX What if we get called with more than one fds? */
   old_fcntl_flags = fcntl (fd, F_GETFL, 0) & ~FASYNC;
   fcntl (fd, F_SETFL, old_fcntl_flags | FASYNC);
 #endif
@@ -922,9 +924,10 @@
 }
 
 void
-reset_sigio ()
+reset_sigio (fd)
+     int fd;
 {
-  unrequest_sigio ();
+  fcntl (fd, F_SETFL, old_fcntl_flags);
 }
 
 #ifdef FASYNC		/* F_SETFL does not imply existence of FASYNC */
@@ -938,13 +941,13 @@
 #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)
 {
   if (read_socket_hook)
     return;
@@ -952,7 +955,7 @@
 #ifdef SIGWINCH
   sigblock (sigmask (SIGWINCH));
 #endif
-  fcntl (fileno (TTY_INPUT (CURTTY())), F_SETFL, old_fcntl_flags);
+  sigblock (sigmask (SIGIO));
   interrupts_deferred = 1;
 }
 
@@ -967,19 +970,21 @@
   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;
 }
 
 void
-unrequest_sigio ()
+unrequest_sigio (struct tty_output *tty)
 {
   int off = 0;
 
   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;
 }
 
@@ -1000,7 +1005,7 @@
 
   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);
 }
@@ -1013,7 +1018,7 @@
   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;
 }
 
@@ -1728,7 +1733,7 @@
 
   struct sensemode tty;
 
-  SYS$QIOW (0, fileno (TTY_INPUT (CURTTY())), IO$_SENSEMODE, &tty, 0, 0,
+  SYS$QIOW (0, fileno (TTY_INPUT (tty_out)), IO$_SENSEMODE, &tty, 0, 0,
 	    &tty.class, 12, 0, 0, 0, 0);
   *widthp = tty.scr_wid;
   *heightp = tty.scr_len;
@@ -1795,14 +1800,12 @@
   }
 }
 
-/* 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 frame *sf;
-
   if (noninteractive)
     {
       fflush (stdout);
@@ -1822,11 +1825,9 @@
       )
     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);
+  cmgoto (tty_out, FrameRows (tty_out) - 1, 0);
+  tty_clear_end_of_line (tty_out, FrameCols (tty_out));
+  cmgoto (tty_out, FrameRows (tty_out) - 1, 0);
 #if defined (IBMR2AIX) && defined (AIXHFT)
   {
     /* HFT devices normally use ^J as a LF/CR.  We forced it to
@@ -1852,7 +1853,7 @@
 #ifdef F_SETOWN		/* F_SETFL does not imply existence of F_SETOWN */
   if (interrupt_input)
     {
-      reset_sigio ();
+      reset_sigio (tty_out);
       fcntl (fileno (TTY_INPUT (tty_out)), F_SETOWN, old_fcntl_owner);
     }
 #endif /* F_SETOWN */
@@ -1864,7 +1865,7 @@
 #endif /* F_SETFL */
 #ifdef BSD4_1
   if (interrupt_input)
-    reset_sigio ();
+    reset_sigio (tty_out);
 #endif /* BSD4_1 */
 
   if (tty_out->old_tty)
@@ -2170,7 +2171,8 @@
   request_sigio ();
 }
 
-reset_sigio ()
+reset_sigio (fd)
+     int fd;
 {
   unrequest_sigio ();
 }
@@ -2720,12 +2722,13 @@
 }
 
 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 +3176,7 @@
 #undef abort
 sys_abort ()
 {
-  reset_sys_modes ();
+  reset_all_sys_modes ();
   LIB$SIGNAL (SS$_DEBUG);
 }
 #endif /* abort */
--- a/src/term.c	Sun Dec 28 22:28:52 2003 +0000
+++ b/src/term.c	Mon Dec 29 07:16:26 2003 +0000
@@ -651,8 +651,6 @@
 clear_end_of_line (first_unused_hpos)
      int first_unused_hpos;
 {
-  register int i;
-
   struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame));
   struct tty_output *tty;
   
@@ -663,8 +661,13 @@
       return;
     }
 
-  tty = FRAME_TTY (f);
-
+  tty_clear_end_of_line (FRAME_TTY (f), first_unused_hpos);
+}
+
+void
+tty_clear_end_of_line (struct tty_output *tty, int first_unused_hpos)
+{
+  register int i;
   /* Detect the case where we are called from reset_sys_modes
      and the costs have never been calculated.  Do nothing.  */
   if (! tty->costs_set)
@@ -683,8 +686,8 @@
 
       /* Do not write in last row last col with Auto-wrap on. */
       if (AutoWrap (tty)
-          && curY (tty) == FRAME_LINES (f) - 1
-	  && first_unused_hpos == FRAME_COLS (f))
+          && curY (tty) == FrameRows (tty) - 1
+	  && first_unused_hpos == FrameCols (tty))
 	first_unused_hpos--;
 
       for (i = curX (tty); i < first_unused_hpos; i++)
@@ -2124,9 +2127,7 @@
 
 
 struct tty_output *
-term_init (name, terminal_type)
-     char *name;
-     char *terminal_type;
+term_init (Lisp_Object frame, char *name, char *terminal_type)
 {
   char *area;
   char **address = &area;
@@ -2134,20 +2135,16 @@
   int buffer_size = 4096;
   register char *p;
   int status;
-  struct frame *sf = XFRAME (selected_frame);
-
+  struct frame *f = XFRAME (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. */
+      /* Return the previously initialized terminal, except if it is
+         the dummy terminal created for the initial frame. */
       if (tty->type)
         return tty;
-
-      /* In the latter case, initialize top_frame to the current terminal. */
-      tty->top_frame = selected_frame;
     }
   else
     {
@@ -2160,21 +2157,25 @@
   if (! tty->Wcm)
       tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
 
+  /* Make sure the frame is live; if an error happens, it must be
+     deleted. */
+  f->output_method = output_termcap;
+  f->output_data.tty = tty;
+  
   if (name)
     {
       int fd;
-      FILE *f;
+      FILE *file;
       fd = emacs_open (name, O_RDWR, 0);
       if (fd < 0)
         {
-          tty_list = tty->next;
-          xfree (tty);
+          delete_tty (tty);
           error ("Could not open file: %s", name);
         }
-      f = fdopen (fd, "w+");
+      file = fdopen (fd, "w+");
       TTY_NAME (tty) = xstrdup (name);
-      TTY_INPUT (tty) = f;
-      TTY_OUTPUT (tty) = f;
+      TTY_INPUT (tty) = file;
+      TTY_OUTPUT (tty) = file;
     }
   else
     {
@@ -2185,8 +2186,6 @@
 
   TTY_TYPE (tty) = xstrdup (terminal_type);
 
-  init_sys_modes (tty);
-  
 #ifdef WINDOWSNT
   initialize_w32_display ();
 
@@ -2194,9 +2193,9 @@
 
   area = (char *) xmalloc (2044);
 
-  FrameRows = FRAME_LINES (sf);
-  FrameCols = FRAME_COLS (sf);
-  specified_window = FRAME_LINES (sf);
+  FrameRows = FRAME_LINES (f);
+  FrameCols = FRAME_COLS (f);
+  specified_window = FRAME_LINES (f);
 
   delete_in_insert_mode = 1;
 
@@ -2213,8 +2212,8 @@
 
   baud_rate = 19200;
 
-  FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0;
-  FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none;
+  FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
+  FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
   TN_max_colors = 16;  /* Required to be non-zero for tty-display-color-p */
 
   return tty;
@@ -2229,6 +2228,7 @@
 #ifdef TERMINFO
       if (name)
         {
+          xfree (buffer);
           delete_tty (tty);
           error ("Cannot open terminfo database file");
         }
@@ -2237,6 +2237,7 @@
 #else
       if (name)
         {
+          xfree (buffer);
           delete_tty (tty);
           error ("Cannot open termcap database file");
         }
@@ -2249,12 +2250,13 @@
 #ifdef TERMINFO
       if (name)
         {
+          xfree (buffer);
           delete_tty (tty);
           error ("Terminal type %s is not defined", terminal_type);
         }
       else
         fatal ("Terminal type %s is not defined.\n\
-If that is not the actual type of terminal you have,\n          \
+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.",
@@ -2262,12 +2264,13 @@
 #else
       if (name)
         {
+          xfree (buffer);
           delete_tty (tty);
           error ("Terminal type %s is not defined", terminal_type);
         }
       else
         fatal ("Terminal type %s is not defined.\n\
-If that is not the actual type of terminal you have,\n          \
+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.",
@@ -2401,21 +2404,29 @@
   {
     int height, width;
     get_tty_size (tty, &width, &height);
-    FRAME_COLS (sf) = width;
-    FRAME_LINES (sf) = height;
+    FrameCols (tty) = width;
+    FrameRows (tty) = height;
   }
 
-  if (FRAME_COLS (sf) <= 0)
-    SET_FRAME_COLS (sf, tgetnum ("co"));
-  else
-    /* Keep width and external_width consistent */
-    SET_FRAME_COLS (sf, FRAME_COLS (sf));
-  if (FRAME_LINES (sf) <= 0)
-    FRAME_LINES (sf) = tgetnum ("li");
-
-  if (FRAME_LINES (sf) < 3 || FRAME_COLS (sf) < 3)
-    fatal ("Screen size %dx%d is too small",
-           FRAME_LINES (sf), FRAME_COLS (sf));
+  if (FrameCols (tty) <= 0)
+    FrameCols (tty) = tgetnum ("co");
+  if (FrameRows (tty) <= 0)
+    FrameRows (tty) = tgetnum ("li");
+
+  if (FrameRows (tty) < 3 || FrameCols (tty) < 3)
+    {
+      if (initialized)
+        {
+          delete_tty (tty);
+          error ("Screen size %dx%d is too small",
+                 FrameCols (tty), FrameRows (tty));
+        }
+      else
+        {
+          fatal ("Screen size %dx%d is too small",
+                 FrameCols (tty), FrameRows (tty));
+        }
+    }
 
 #if 0  /* This is not used anywhere. */
   TTY_MIN_PADDING_SPEED (tty) = tgetnum ("pb");
@@ -2541,15 +2552,14 @@
         }
     }
 
-  FrameRows (tty) = FRAME_LINES (sf);
-  FrameCols (tty) = FRAME_COLS (sf);
-  tty->specified_window = FRAME_LINES (sf);
+  tty->specified_window = FrameRows (tty);
 
   if (Wcm_init (tty) == -1)	/* can't do cursor motion */
     if (name)
       {
         delete_tty (tty);
-        error ("Terminal type \"%s\" is not powerful enough to run Emacs");
+        error ("Terminal type \"%s\" is not powerful enough to run Emacs",
+               terminal_type);
       }
     else {
 #ifdef VMS
@@ -2562,15 +2572,15 @@
 #else /* not VMS */
 # ifdef TERMINFO
       fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
-It lacks the ability to position the cursor.\n                          \
-If that is not the actual type of terminal you have,\n                  \
+It lacks the ability to position the cursor.\n\
+If that is not the actual type of terminal you have,\n\
 use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
 `setenv TERM ...') to specify the correct type.  It may be necessary\n\
 to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
              terminal_type);
 # else /* TERMCAP */
       fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
-It lacks the ability to position the cursor.\n                       \
+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\
@@ -2580,8 +2590,7 @@
 #endif /*VMS */
     }
   
-  if (FRAME_LINES (sf) <= 0
-      || FRAME_COLS (sf) <= 0)
+  if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
     {
       if (name)
         {
@@ -2619,20 +2628,29 @@
 
   TTY_FAST_CLEAR_END_OF_LINE (tty) = tty->TS_clr_line != 0;
 
-  init_baud_rate ();
+  init_baud_rate (tty);
   if (read_socket_hook)		/* Baudrate is somewhat
                                    meaningless in this case */
     baud_rate = 9600;
 
-  FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0;
-  FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none;
-#endif /* WINDOWSNT */
-
-  xfree (buffer);
-
+  FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
+  FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
+
+  /* Don't do this.  I think termcap may still need the buffer. */
+  /* xfree (buffer); */
+
+  tty->top_frame = frame;
+  
+  tty->foreground_pixel = FACE_TTY_DEFAULT_FG_COLOR;
+  tty->background_pixel = FACE_TTY_DEFAULT_BG_COLOR;
+  
+  /* Init system terminal modes (RAW or CBREAK, etc.).  */
+  init_sys_modes (tty);
+  
   tty_set_terminal_modes (tty);
 
   return tty;
+#endif /* WINDOWSNT */
 }
 
 /* VARARGS 1 */
@@ -2670,11 +2688,20 @@
   Fprovide (intern ("multi-tty"), Qnil);
 }
 
+static int deleting_tty = 0;
+
 void
 delete_tty (struct tty_output *tty)
 {
   Lisp_Object tail, frame;
-
+  
+  if (deleting_tty)
+    /* We get a recursive call when we delete the last frame on this
+       tty. */
+    return;
+
+  deleting_tty = 1;
+  
   if (tty == tty_list)
     tty_list = tty->next;
   else
@@ -2687,7 +2714,8 @@
         /* This should not happen. */
         abort ();
 
-      p->next = p->next->next;
+      p->next = tty->next;
+      tty->next = 0;
     }
 
   FOR_EACH_FRAME (tail, frame)
@@ -2700,46 +2728,31 @@
         }
     }
   
-  /* This hangs. */
-  /*
   reset_sys_modes (tty);
 
   if (tty->name)
     xfree (tty->name);
   if (tty->type)
     xfree (tty->type);
-  */
+
   if (tty->input)
     fclose (tty->input);
   if (tty->output)
     fclose (tty->output);
   if (tty->termscript)
     fclose (tty->termscript);
-
-  tty->input = 0;
-  tty->output = 0;
-  tty->termscript = 0;
   
-  /*
   if (tty->old_tty)
-    {
-      memset (tty->old_tty, 'Z', sizeof (struct emacs_tty));
-      tty->old_tty = 0;
-    }
-  
-    
-    /*    xfree (tty->old_tty);
-
-    if (tty->Wcm)
-    {
-      bzero (tty->Wcm, sizeof (struct cm));
-    }
+    xfree (tty->old_tty);
+
+#if 0  /* XXX There is a dangling reference somewhere into this. */
+  if (tty->Wcm)
     xfree (tty->Wcm); 
+#endif
   
   bzero (tty, sizeof (struct tty_output));
-  
   xfree (tty);
-  */
+  deleting_tty = 0;
 }