From xemacs-m  Tue Mar  4 00:42:33 1997
Received: from corona.pixar.com (corona.pixar.com [138.72.20.84])
	by xemacs.org (8.8.5/8.8.5) with SMTP id AAA11720
	for <xemacs-beta@xemacs.org>; Tue, 4 Mar 1997 00:42:31 -0600 (CST)
Received: by corona.pixar.com (Smail3.1.29.1 #2)
	id m0w1nu3-0001YBC; Mon, 3 Mar 97 22:40 PST
Sender: retnuh@pixar.com (Hunter Kelly)
Sender: retnuh@corona
To: xemacs-beta@xemacs.org
Subject: gnuattach mondo patch
Mime-Version: 1.0 (generated by tm-edit 7.103)
Content-Type: multipart/mixed;
 boundary="Multipart_Mon_Mar__3_22:40:46_1997-1"
Content-Transfer-Encoding: 7bit
From: Hunter Kelly <retnuh@corona.pixar.com>
Date: 03 Mar 1997 22:40:46 -0800
Message-ID: <yvtybc46txt.fsf@corona.pixar.com>
Lines: 664
X-Mailer: Gnus v5.4.11/XEmacs 19.15

--Multipart_Mon_Mar__3_22:40:46_1997-1
Content-Type: text/plain; charset=US-ASCII

Okay, I have managed to scrape a few spare hours together to finish my
gnuattach hackage.

Basically what II have done is add a slot in tty-consoles to mark the
"controlling-process" for that tty console.  This allows signals to be
sent to that process.

On the gnuattach side, I changed it so it passes signals (like
SIGQUIT) on to the master emacs process.  

Together these things allow gnuattach look like a clean extension of
the emacs process.

Potential problems:
I have no idea how to suspend a process on VMS, so a VMS type is going
to need to look at this patch.

Probably weird results on machines that can't suspend processes.

Anyway, please test this out.  It might be a little rough, but in my
opinion, it makes gnuattach a genuinely useful tool as opposed to a
neat but broken toy.

Steven, I am planning on looking at that server.el patch you mentioned
last week.

Hrvoje, I will take a look at multiple frames on a tty.  Wanted to get
this finished first.

This was patched against 19.15-b93, but seems to apply cleanly to b96.


-- 

Hunter



--Multipart_Mon_Mar__3_22:40:46_1997-1
Content-Type: application/octet-stream
Content-Disposition: attachment; filename="gpatch"
Content-Transfer-Encoding: 8bit

--- lib-src/gnuclient.c.orig	Mon Mar  3 21:58:29 1997
+++ lib-src/gnuclient.c	Mon Mar  3 21:06:38 1997
@@ -66,7 +66,68 @@
 static char cwd[MAXPATHLEN+2];	/* current working directory when calculated */
 static char *cp = NULL;		/* ptr into valid bit of cwd above */
 
+#ifdef GNUATTACH
+#include <signal.h>
+
+static pid_t emacs_pid;			/* Process id for emacs process */
+
+void tell_emacs_to_resume(int sig)
+{
+    char buffer[GSERV_BUFSZ+1];
+    int s;					/* socket / msqid to server */
+    int connect_type;           			/* CONN_UNIX, CONN_INTERNET, or
+						 * CONN_IPC */
+
+  /* Why is SYSV so retarded? */
+  /* We want emacs to realize that we are resuming */
+    signal(SIGCONT, tell_emacs_to_resume); 
+
+    connect_type = make_connection (NULL, (u_short) 0, &s);
+
+    sprintf(buffer,"(server-eval '(resume-pid-console %d))", getpid());
+    send_string(s, buffer);
+  
+#ifdef SYSV_IPC
+  if (connect_type == (int) CONN_IPC)
+    disconnect_from_ipc_server (s, msgp, FALSE);
+#else /* !SYSV_IPC */
+  if (connect_type != (int) CONN_IPC)
+    disconnect_from_server (s, FALSE);
+#endif /* !SYSV_IPC */
+}
+
+void pass_signal_to_emacs(int sig)
+{
+  if (kill(emacs_pid, sig) == -1) {
+    fprintf(stderr, "gnuattach: Could not pass signal to emacs process\n");
+    exit(1);
+  }
+}
+
+void initialize_signals()
+{
+  /* Set up signal handler to pass relevant signals to emacs process */
+  signal(SIGHUP, pass_signal_to_emacs);
+  signal(SIGQUIT, pass_signal_to_emacs);
+  signal(SIGILL, pass_signal_to_emacs);
+  signal(SIGTRAP, pass_signal_to_emacs);
+  signal(SIGSEGV, pass_signal_to_emacs);
+  signal(SIGPIPE, pass_signal_to_emacs);
+  signal(SIGTERM, pass_signal_to_emacs);
+#ifdef SIGBUS
+  signal(SIGBUS, pass_signal_to_emacs);
+#endif
+#ifdef SIGIOT
+  signal(SIGIOT, pass_signal_to_emacs);
+#endif
+
+  /* We want emacs to realize that we are resuming */
+  signal(SIGCONT, tell_emacs_to_resume);
+}
 
+#endif /* GNUATTACH */
+
+
 /*
   get_current_working_directory -- return the cwd.
 */
@@ -131,7 +192,7 @@
 main (int argc, char *argv[])
 {
   int starting_line = 1;			/* line to start editing at */
-  char command[MAXPATHLEN+50];			/* emacs command buffer */
+  char command[MAXPATHLEN+50];		/* emacs command buffer */
   char fullpath[MAXPATHLEN+1];			/* full pathname to file */
 #ifndef GNUATTACH
   int qflg = 0;					/* quick edit, don't wait for 
@@ -155,6 +216,7 @@
 #endif /* SYSV_IPC */
 #ifdef GNUATTACH
   char *tty;
+  char buffer[GSERV_BUFSZ+1];		/* buffer to read pid */
 #endif
 
 #ifdef INTERNET_DOMAIN_SOCKETS
@@ -166,11 +228,7 @@
   while ((c = getopt (argc, argv,
 
 #ifdef INTERNET_DOMAIN_SOCKETS
-# ifdef GNUATTACH
-		      "h:p:r"
-# else
 		      "h:p:r:q"
-# endif
 #else /* !INTERNET_DOMAIN_SOCKETS */
 # ifdef GNUATTACH
 		      ""
@@ -209,13 +267,8 @@
     {
       fprintf (stderr,
 #ifdef INTERNET_DOMAIN_SOCKETS
-# ifdef GNUATTACH
-	       "usage: %s [-h hostname] [-p port] [-r pathname] "
-	       "[[+line] path] ...\n",
-# else
 	       "usage: %s [-q] [-h hostname] [-p port] [-r pathname] "
 	       "[[+line] path] ...\n",
-# endif
 #else /* !INTERNET_DOMAIN_SOCKETS */
 # ifdef GNUATTACH
 	       "usage: %s [[+line] path] ...\n",
@@ -234,9 +287,35 @@
       fprintf (stderr, "%s: Not connected to a tty", progname);
       exit (1);
     }
-#endif
 
-#ifdef INTERNET_DOMAIN_SOCKETS
+  /* This next stuff added in an attempt to make handling of
+     the tty do the right thing when dealing with signals.
+     Idea is to pass all the appropriate signals to the emacs process
+     */
+
+  connect_type = make_connection (NULL, (u_short) 0, &s);
+
+  send_string(s,"(server-eval '(emacs-pid))");
+  send_string(s,EOT_STR);
+  
+  if (read_line(s,buffer) == 0) {
+    fprintf(stderr, "%s: Could not establish emacs procces id\n",progname);
+    exit(1);
+  }
+  /* don't do disconnect_from_server becasue we have already read data,
+     and disconnect doesn't do anything else
+   */
+#ifdef SYSV_IPC
+  if (connect_type == (int) CONN_IPC)
+    disconnect_from_ipc_server (s, msgp, FALSE);
+#endif /* !SYSV_IPC */
+
+  emacs_pid = (pid_t)atol(buffer);
+  initialize_signals();
+      
+#endif /*GNUATTACH */ 
+
+#if defined(INTERNET_DOMAIN_SOCKETS) && !defined(GNUATTACH)
   connect_type = make_connection (hostarg, portarg, &s);
 #else
   connect_type = make_connection (NULL, (u_short) 0, &s);
@@ -288,7 +367,8 @@
       fprintf (stderr, "%s: unknown terminal type\n", progname);
       exit (1);
     }
-  sprintf (command, "(server-tty-edit-files \"%s\" \"%s\" '(", tty, ptr);
+  sprintf (command, "(server-tty-edit-files \"%s\" \"%s\" %d '(", 
+	   tty, ptr, getpid());
   send_string (s, command);
 #else
   if (qflg)
--- lib-src/gnuserv.c.orig	Mon Mar  3 21:58:29 1997
+++ lib-src/gnuserv.c	Mon Mar  3 20:45:15 1997
@@ -345,7 +345,10 @@
     fprintf(stderr,"%s: garbage after result\n",progname);
     exit(1);
   }
-  close(s);
+  /* send the newline */
+  buf[1] = '\0';
+  send_string(s,buf);
+  close(s); 
 
 } /* handle_response */
 #endif /* INTERNET_DOMAIN_SOCKETS || UNIX_DOMAIN_SOCKETS */
--- lib-src/gnuslib.c.orig	Mon Mar  3 21:58:29 1997
+++ lib-src/gnuslib.c	Mon Mar  3 21:00:59 1997
@@ -33,6 +33,7 @@
 static char rcsid [] = "!Header: gnuslib.c,v 2.4 95/02/16 11:57:37 arup alpha !";
 #endif
 
+#include <errno.h>
 #include "gnuserv.h"
 
 #ifdef SYSV_IPC
@@ -216,6 +217,34 @@
   }; /* while */ 
 #endif
 } /* send_string */
+
+/*
+  read_line -- read a \n terminated line from a socket
+*/
+int read_line(s,dest)
+     int s;
+     char *dest;
+{
+  char *index = NULL;
+  int length = 0;
+  int difference;
+  char buffer[GSERV_BUFSZ+1];
+
+  do {
+    if ((length = recv(s,buffer,GSERV_BUFSZ, MSG_PEEK)) > 0)
+      buffer[length] = '\0';
+    else
+      return 0;
+  } while ((index = strchr(buffer, '\n')) == NULL);
+
+  difference = (int)(index - buffer);
+  length = read(s,buffer,difference);
+  if (length == 0)
+    return 0;
+  buffer[length] = '\0';
+  strcpy(dest,buffer);
+  return 1;
+} /* read_line */
 #endif /* INTERNET_DOMAIN_SOCKETS || UNIX_DOMAIN_SOCKETS */
 
 
@@ -405,11 +434,14 @@
     add_newline = (buffer[length-1] != '\n');
   }; /* while */
 #else
-  while ((length = read(s,buffer,GSERV_BUFSZ)) > 0) {
-    buffer[length] = '\0';
-    if (echo) {
-      fputs(buffer,stdout);
-      add_newline = (buffer[length-1] != '\n');
+  while ((length = read(s,buffer,GSERV_BUFSZ)) > 0 ||
+      (length == -1 && errno == EINTR)) {
+    if (length) {
+      buffer[length] = '\0';
+      if (echo) {
+	fputs(buffer,stdout);
+	add_newline = (buffer[length-1] != '\n');
+      }; /* if */
     }; /* if */
   }; /* while */
 #endif
--- lisp/packages/gnuserv.el.orig	Mon Mar  3 21:58:29 1997
+++ lisp/packages/gnuserv.el	Mon Mar  3 21:48:44 1997
@@ -244,8 +244,8 @@
 	      ;; give window chance to re-display text
 	      (accept-process-output)))))
 
-(defun server-tty-find-file (tty termtype file)
-  (let ((device (make-tty-device tty termtype)))
+(defun server-tty-find-file (tty termtype pid file)
+  (let ((device (make-tty-device tty termtype pid )))
     (select-frame (make-frame nil device))
     (if (not file)
 	(switch-to-buffer (get-buffer-create "*scratch*"))
@@ -347,7 +347,7 @@
 		"Type {\\[server-edit]} or select Frame/Delete to finish edit."
 	      "When done with a buffer, type \\[server-edit]."))))
 
-(defun server-tty-edit-files (tty termtype list)
+(defun server-tty-edit-files (tty termtype pid list)
   "For each (line-number . file) pair in LIST, edit the file at line-number.
 Save enough information for (server-kill-buffer) to inform the client when
 the edit is finished."
@@ -355,7 +355,7 @@
   (while list
     (let ((line (car (car list)))
 	  (path (cdr (car list))))
-      (server-tty-find-file tty termtype path)
+      (server-tty-find-file tty termtype pid path)
       (server-make-window-visible)
       (let ((old-clients (assq current-client server-clients))
 	    (buffer (current-buffer)))
@@ -452,14 +452,18 @@
 	;; tell it that it is done, and forget it entirely.
 	(if (cdr client)
 	    nil
-	  (server-write-to-client (car client) nil)
-	  (setq server-clients (delq client server-clients))))
+	  (if (buffer-name buffer)
+	      (save-excursion
+		(set-buffer buffer)
+		(setq server-buffer-clients nil)))
+	  ; Order is important here --
+	  ; server-kill-buffer tries to notify clients that
+	  ; they are done, too, but if we try and notify twice,
+	  ; we are h0zed -- Hunter Kelly 3/3/97
+	  (setq server-clients (delq client server-clients))
+	  (funcall server-done-function buffer)
+	  (server-write-to-client (car client) nil)))
       (setq old-clients (cdr old-clients)))
-    (if (buffer-name buffer)
-	(save-excursion
-	  (set-buffer buffer)
-	  (setq server-buffer-clients nil)))
-   (funcall server-done-function buffer)
     next-buffer))
 
 
--- lisp/prim/frame.el.orig	Mon Mar  3 21:58:30 1997
+++ lisp/prim/frame.el	Mon Mar  3 16:05:07 1997
@@ -741,9 +741,13 @@
 (defun suspend-or-iconify-emacs ()
   "Calls iconify-emacs if frame is an X frame, otherwise calls suspend-emacs"
   (interactive)
-  (if (eq (frame-type (selected-frame)) 'x)
-      (iconify-emacs)
-    (suspend-emacs)))
+  (cond
+   ((eq (frame-type (selected-frame)) 'x) (iconify-emacs))
+   ((and (eq (frame-type (selected-frame)) 'tty)
+	 (console-tty-controlling-process (selected-console)))
+    (suspend-console (selected-console)))
+   (t
+    (suspend-emacs))))
 
 
 ;;; auto-raise and auto-lower
--- lisp/prim/device.el.orig	Mon Mar  3 21:58:30 1997
+++ lisp/prim/device.el	Wed Feb 12 19:47:38 1997
@@ -43,7 +43,7 @@
   (if (not (device-live-p device)) 'dead
     (console-type (device-console device))))
 
-(defun make-tty-device (&optional tty terminal-type)
+(defun make-tty-device (&optional tty terminal-type controlling-process)
   "Create a new device on TTY.
   TTY should be the name of a tty device file (e.g. \"/dev/ttyp3\" under
 SunOS et al.), as returned by the `tty' command.  A value of nil means
@@ -50,8 +50,12 @@
 use the stdin and stdout as passed to XEmacs from the shell.
   If TERMINAL-TYPE is non-nil, it should be a string specifying the
 type of the terminal attached to the specified tty.  If it is nil,
-the terminal type will be inferred from the TERM environment variable."
-  (make-device 'tty tty (list 'terminal-type terminal-type)))
+the terminal type will be inferred from the TERM environment variable.
+  If CONTROLLING-PROCESS is non-nil, it should be an integer
+specifying the process id of the process in control of the specified tty.  If
+it is nil, it is assumes to be the value returned by emacs-pid."
+  (make-device 'tty tty (list 'terminal-type terminal-type 
+			      'controlling-process controlling-process)))
 
 (defun make-x-device (&optional display)
   "Create a new device connected to DISPLAY."
--- lisp/prim/console.el.orig	Mon Mar  3 21:58:30 1997
+++ lisp/prim/console.el	Mon Mar  3 20:12:36 1997
@@ -30,3 +30,12 @@
 that the information is returned for; nil means the current console."
   (nth 3 (current-input-mode console)))
 
+(defun resume-pid-console (pid)
+  "Resume the consoles with a controlling process of PID."
+  (mapc (lambda (c) 
+	  (if (and (eq (console-type c) 'tty)
+		   (= pid (console-tty-controlling-process c)))
+	      (resume-console c)))
+	(console-list))
+  ; documentation for mapc lies!
+  nil)
--- src/sysdep.h.orig	Mon Mar  3 21:58:30 1997
+++ src/sysdep.h	Wed Feb 12 20:40:45 1997
@@ -60,6 +60,8 @@
 
 /* Suspend the Emacs process; give terminal to its superior.  */
 void sys_suspend (void);
+/* Suspend a process if possible; give termianl to its superior. */
+void sys_suspend_process (int process);
 
 void request_sigio (void);
 void unrequest_sigio (void);
--- src/console-tty.h.orig	Mon Mar  3 21:58:31 1997
+++ src/console-tty.h	Wed Feb 12 19:24:51 1997
@@ -43,6 +43,7 @@
   int infd, outfd;
   Lisp_Object instream, outstream;
   Lisp_Object terminal_type;
+  Lisp_Object controlling_process;
   char *term_entry_buffer;
 
   /* Physical location of cursor on this console. */
--- src/console-tty.c.orig	Mon Mar  3 21:58:31 1997
+++ src/console-tty.c	Mon Mar  3 15:32:42 1997
@@ -42,6 +42,7 @@
 DEFINE_CONSOLE_TYPE (tty);
 
 Lisp_Object Qterminal_type;
+Lisp_Object Qcontrolling_process;
 
 extern Lisp_Object Vstdio_str; /* in console-stream.c */
 
@@ -62,14 +63,16 @@
 static void
 tty_init_console (struct console *con, Lisp_Object props)
 {
-  Lisp_Object tty = CONSOLE_CONNECTION (con), terminal_type = Qnil;
+  Lisp_Object tty = CONSOLE_CONNECTION (con);
+  Lisp_Object terminal_type = Qnil, controlling_process = Qnil;
   int infd, outfd;
-  struct gcpro gcpro1;
+  struct gcpro gcpro1, gcpro2;
 
-  GCPRO1 (terminal_type);
+  GCPRO2 (terminal_type, controlling_process);
 
   terminal_type = Fplist_get (props, Qterminal_type, Qnil);
-
+  controlling_process = Fplist_get(props, Qcontrolling_process, Qnil);
+  
   /* Determine the terminal type */
 
   if (!NILP (terminal_type))
@@ -86,6 +89,10 @@
 	terminal_type = build_string (temp_type);
     }
 
+  /* Determine the controlling process */
+  if (!NILP (controlling_process))
+    CHECK_INT (controlling_process);
+
   /* Open the specified console */
 
   allocate_tty_console_struct (con);
@@ -110,6 +117,7 @@
   CONSOLE_TTY_DATA (con)->outstream = make_filedesc_output_stream (outfd, 0,
 								   -1, 0);
   CONSOLE_TTY_DATA (con)->terminal_type = terminal_type;
+  CONSOLE_TTY_DATA (con)->controlling_process = controlling_process;
   if (NILP (CONSOLE_NAME (con)))
     CONSOLE_NAME (con) = Ffile_name_nondirectory (tty);
   {
@@ -197,6 +205,14 @@
   return CONSOLE_TTY_DATA (decode_tty_console (console))->terminal_type;
 }
 
+DEFUN ("console-tty-controlling-process", Fconsole_tty_controlling_process, 0, 1, 0, /*
+Return the controlling process of TTY console CONSOLE.
+*/
+       (console))
+{
+  return CONSOLE_TTY_DATA (decode_tty_console (console))->controlling_process;
+}
+
 extern Lisp_Object stream_semi_canonicalize_console_connection(Lisp_Object,
 							       Error_behavior);
 Lisp_Object
@@ -238,7 +254,9 @@
 syms_of_console_tty (void)
 {
   DEFSUBR (Fconsole_tty_terminal_type);
+  DEFSUBR (Fconsole_tty_controlling_process);
   defsymbol (&Qterminal_type, "terminal-type");
+  defsymbol (&Qcontrolling_process, "controlling-process");
 }
 
 void
--- src/console.c.orig	Mon Mar  3 21:58:31 1997
+++ src/console.c	Mon Mar  3 20:05:18 1997
@@ -904,6 +904,81 @@
 #endif /* BSD */
 }
 
+DEFUN ("suspend-console", Fsuspend_console, 0, 1, "", /*
+Suspend a console.  For tty consoles, it sends a signal to suspend
+the process in charge of the tty, and removes the devices and
+frames of that console from the display.
+
+If optional arg CONSOLE is non-nil, it is the console to be suspended.
+Otherwise it is assumed to be the selected console.
+
+Some operating systems cannot stop processes and resume them later.
+On such systems, who knows what will happen.
+*/
+       (console))
+{
+  Lisp_Object devcons;
+  Lisp_Object framecons;
+  struct console *c;
+  struct gcpro gcpro1;
+
+  if (NILP (console))
+      console=Fselected_console();
+
+  GCPRO1 (console);
+
+  c = decode_console(console);
+
+  if (CONSOLE_TTY_P (c)) 
+  {
+    CONSOLE_DEVICE_LOOP (devcons, c)
+      {
+	struct device *d = XDEVICE (XCAR (devcons)); 
+	DEVICE_FRAME_LOOP (framecons, d)
+	  {
+	    Fmake_frame_invisible(XCAR(framecons), Qt);
+	  }
+      }
+    reset_one_console(c);
+    sys_suspend_process(XINT(Fconsole_tty_controlling_process(console)));
+  }
+
+  UNGCPRO;
+  return Qnil;
+}
+
+DEFUN ("resume-console", Fresume_console, 1, 1, "", /*
+Re-initialize a previously suspended console.  For tty consoles,
+do stuff to the tty to make it sane again.
+*/
+       (console))
+{
+  Lisp_Object devcons;
+  Lisp_Object framecons;
+  struct console *c;
+  struct gcpro gcpro1, gcpro2, gcpro3;
+
+  GCPRO2 (console, devcons);
+
+  c = decode_console(console);
+
+  if (CONSOLE_TTY_P(c)) 
+  {
+    CONSOLE_DEVICE_LOOP (devcons, c)
+      {
+	struct device *d = XDEVICE (XCAR (devcons)); 
+	DEVICE_FRAME_LOOP (framecons, d)
+	  {
+	    Fmake_frame_visible(XCAR(framecons));
+	  }
+      }
+    init_one_console(c);
+  }
+
+  UNGCPRO;
+  return Qnil;
+}
+
 DEFUN ("set-input-mode", Fset_input_mode, 3, 5, 0, /*
 Set mode of reading keyboard input.
 First arg is ignored, for backward compatibility.
@@ -1007,7 +1082,9 @@
   DEFSUBR (Fconsole_enable_input);
   DEFSUBR (Fconsole_disable_input);
   DEFSUBR (Fconsole_on_window_system_p);
-
+  DEFSUBR (Fsuspend_console);
+  DEFSUBR (Fresume_console);
+  
   DEFSUBR (Fsuspend_emacs);
   DEFSUBR (Fset_input_mode);
   DEFSUBR (Fcurrent_input_mode);
--- src/sysdep.c.orig	Mon Mar  3 21:58:31 1997
+++ src/sysdep.c	Wed Feb 12 20:36:42 1997
@@ -733,6 +733,20 @@
 #endif
 }
 
+/* Suspend a process if possible; give terminal to its superior.  */
+void
+sys_suspend_process (process)
+    int process;
+{
+    /* I don't doubt that it is possible to suspend processes on
+     * VMS machines or thost that use USG_JOBCTRL,
+     * but I don't know how to do it, so...
+     */
+#if defined (SIGTSTP) && !defined (MSDOS)
+    kill(process, SIGTSTP);
+#endif
+}
+
 /* Set the logical window size associated with descriptor FD
    to HEIGHT and WIDTH.  This is used mainly with ptys.  */
 
--- src/frame-tty.c.orig	Mon Mar  3 21:58:31 1997
+++ src/frame-tty.c	Mon Mar  3 20:20:47 1997
@@ -62,6 +62,31 @@
       call1 (Qinit_post_tty_win, FRAME_CONSOLE (f));
 }
 
+/* Change from withdrawn state to mapped state. */
+static void
+tty_make_frame_visible (struct frame *f)
+{
+  if (!FRAME_VISIBLE_P(f))
+    {
+      SET_FRAME_CLEAR(f);
+      f->visible = 1;
+    }
+  
+}
+
+/* Change from mapped state to withdrawn state. */
+static void
+tty_make_frame_invisible (struct frame *f)
+{
+    f->visible = 0;
+}
+
+static int
+tty_frame_visible_p (struct frame *f)
+{
+  return FRAME_VISIBLE_P(f);
+}
+
 
 /************************************************************************/
 /*                            initialization                            */
@@ -72,6 +97,9 @@
 {
   CONSOLE_HAS_METHOD (tty, init_frame_1);
   CONSOLE_HAS_METHOD (tty, after_init_frame);
+  CONSOLE_HAS_METHOD (tty, make_frame_visible);
+  CONSOLE_HAS_METHOD (tty, make_frame_invisible);
+  CONSOLE_HAS_METHOD (tty, frame_visible_p);
 }
 
 void

--Multipart_Mon_Mar__3_22:40:46_1997-1--

