summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaroly Lorentey <lorentey@elte.hu>2003-12-26 04:24:54 +0000
committerKaroly Lorentey <lorentey@elte.hu>2003-12-26 04:24:54 +0000
commit9628b8878f46b2b7eeeb4f272d20f2e64de19f4a (patch)
treecfccb4da4a6b898780d3bc9856b377fd5d85e4e6
parent4f0359deff8eb9ec9ed95e75d77a0dd59f39428c (diff)
downloademacs-9628b8878f46b2b7eeeb4f272d20f2e64de19f4a.tar.gz
lib-src/emacsclient.c: Implemented --here option (open a new Emacs tty). Needs more work.
(here): New variable. (decode_options): Use it. (ec_get_tty, ec_set_tty, init_tty, window_change, hang_up_signal): New functions. (window_change_signal, init_signals, reset_tty, init_pty, copy_from_to): Ditto. (pty_conversation): Ditto. (main): Use them. (master, pty_name, old_tty, tty, old_tty_valid, tty_erase_char): New variables. (flow_control, meta_key, _sobuf, in_conversation, quit_conversation): Ditto. lisp/server.el (server-process-filter): Added support for opening a new terminal frame. dispextern.h (get_frame_size): Renamed to get_tty_size, added tty_output parameter. dispnew.c (Fredraw_frame): fflush the current terminal instead of stdout. (direct_output_for_insert, direct_output_forward_char, update_frame_1): Ditto. (Fding, bitch_at_user): Ditto. (update_frame_1): Count pending output for current terminal instead of stdout. (window_change_signal): Resize all terminals. (change_frame_size): Don't resize all terminals to the same size. frame.c (Vterminal_frame): Removed. (syms_of_frame): Removed declaration of Vterminal_frame. (make_terminal_frame): Set the top frame of the terminal to the new frame. (Fmake_terminal_frame): Get a new frame size from get_tty_size, don't copy it. (do_switch_frame): Handle terminal frame visibility. (next_frame, prev_frame): Skip over frames on different terminals. frame.h (Vterminal_frame): Removed. keyboard.c (input_fd): Removed. (read_avail_input): Removed first argument from read_socket_hook. Try to read from each available tty, until one succeeds. (Fsuspend_emacs): Don't suspend if there are multiple terminals. lisp.h (get_frame_size): Removed superflous declaration. xterm.c (Xtread_socket): Removed first parameter. macterm.h (XTread_socket): Ditto. w32inevt.c (w32_console_read_socket): Ditto. w32term.c (w32_read_socket): Ditto. sysdep.c (input_fd): Removed. (change_input_fd): Removed. (discard_tty_input): Discard pending input on _all_ input descriptors. (stuff_char, tabs_safe_p): Use current terminal instead of input_fd. (init_baud_rate, request_sigio, unrequest_sigio): Ditto. (init_sys_modes, reset_sys_modes): Ditto. (narrow_foreground_group, widen_foreground_group): Use stdin. (init_sys_modes, reset_sys_modes): otty parameter renamed to tty_out. (get_frame_size): Renamed to get_tty_size, added tty_out parameter. term.c (read_socket_hook): Removed first parameter. (clear_end_of_line): Use updating_frame, if possible. (write_glyphs, insert_glyphs, ins_del_lines): Ditto. (term_init): Renamed get_frame_size to get_tty_size. termchar.h (struct tty_output): New entries: top_frame, previous_terminal_frame. termhooks.h (read_socket_hook): Removed first parameter. window.c (init_window_once): Removed reference to Vterminal_frame. xdisp.c (previous_terminal_frame): Moved to struct tty_output. (redisplay_internal): Updated to use previous_terminal_frame in tty_output. Allow for simultaneous refresh of multiple ttys. git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-5
-rw-r--r--README.multi-tty77
-rw-r--r--lib-src/emacsclient.c581
-rw-r--r--lib-src/pty.c20
-rw-r--r--lib-src/pty.h224
-rw-r--r--lisp/server.el9
-rw-r--r--src/dispextern.h2
-rw-r--r--src/dispnew.c71
-rw-r--r--src/emacs.c2
-rw-r--r--src/frame.c34
-rw-r--r--src/frame.h13
-rw-r--r--src/keyboard.c170
-rw-r--r--src/lisp.h1
-rw-r--r--src/macterm.c2
-rw-r--r--src/scroll.c2
-rw-r--r--src/sysdep.c174
-rw-r--r--src/term.c45
-rw-r--r--src/termchar.h10
-rw-r--r--src/termhooks.h2
-rw-r--r--src/w32inevt.c2
-rw-r--r--src/w32term.c3
-rw-r--r--src/window.c1
-rw-r--r--src/xdisp.c30
-rw-r--r--src/xterm.c3
23 files changed, 1187 insertions, 291 deletions
diff --git a/README.multi-tty b/README.multi-tty
index 31e71446039..c8cd7279adf 100644
--- a/README.multi-tty
+++ b/README.multi-tty
@@ -25,19 +25,18 @@ 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.
+redisplay. Input is read from all terminals (NOT via MULTIKBOARD!).
+At the moment, the type of the new terminals must be the same as the
+initial terminal. Emacsclient is extended to support opening a new
+terminal frame.
-To try it out, start up emacs, and evaluate the following:
+To try it out, start up the emacs server (M-x server-start), and then
+start emacsclient with
- (make-terminal-frame '((tty . "/dev/pts/5") (tty-type . "xterm")))
+ emacsclient -h
-(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.
+If you exit emacs, both terminals are restored to their previous
+states.
X, Mac, Windows and DOS support is broken.
@@ -50,6 +49,8 @@ For the NEWS file:
specify a terminal device (`tty' parameter) and a terminal type
(`tty-type' parameter) to `make-terminal-frame'.
+** Emacsclient has been extended to support opening a new terminal
+ frame.
CHANGELOG
---------
@@ -76,15 +77,50 @@ THINGS THAT ARE DONE
(Done, new frame parameters: `tty' and `tty-type'.)
+-- Implement support for reading from multiple terminals.
+
+ (Done, read_avail_input tries to read from each terminal, until one
+ succeeds.)
+
+-- other-frame should cycle through the frames on the `current'
+ terminal.
+
+ (Done. A little fragile, but seems to work.)
+
+-- Support different terminal sizes.
+
+ (Done, no problem.)
+
+-- Make sure terminal resizes are handled gracefully. (Could be
+ problematic.)
+
+ (Done. We don't get SIGWINCH for additional ttys, though.)
+
+-- Extend emacsclient to automatically open a new tty when it connects
+ to Emacs.
+
+ (Done. It's an ugly hack, needs more work.)
+
+-- Redisplay must refresh the topmost frame on all terminals, not just
+ the initial terminal.
+
+ (Done, but introduced ugly redisplay problems. Ugh.)
+
+
THINGS TO DO
------------
+** Fix redisplay problems.
+
** 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.
+** Provide a way for emacsclient to tell Emacs that the tty has been
+ resized.
+
** 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.
@@ -96,27 +132,14 @@ THINGS TO DO
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.
+** Each keypress should automatically select the frame corresponding
+ to the terminal that it was coming from. This means that Emacs
+ must know from which terminal the last keyboard event came from.
+ (Multikeyboard support may help with this.)
** 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.
diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c
index aafc531ac5b..2f0f45e1f59 100644
--- a/lib-src/emacsclient.c
+++ b/lib-src/emacsclient.c
@@ -41,6 +41,54 @@ Boston, MA 02111-1307, USA. */
# include <pwd.h>
#endif /* not VMS */
+
+/****************************************/
+
+#include <errno.h>
+#include <signal.h>
+
+#ifndef INCLUDED_FCNTL
+#define INCLUDED_FCNTL
+#include <fcntl.h>
+#endif
+
+#ifdef HAVE_TERMIOS
+#ifndef NO_TERMIO
+#include <termio.h>
+#endif
+#include <termios.h>
+#endif /* not HAVE_TERMIOS */
+
+#ifdef __GNU_LIBRARY__
+#include <sys/ioctl.h>
+#include <termios.h>
+#endif
+
+#if (defined (POSIX) || defined (NEED_UNISTD_H)) && defined (HAVE_UNISTD_H)
+#include <unistd.h>
+#endif
+
+
+
+/* Try to establish the correct character to disable terminal functions
+ in a system-independent manner. Note that USG (at least) define
+ _POSIX_VDISABLE as 0! */
+
+#ifdef _POSIX_VDISABLE
+#define CDISABLE _POSIX_VDISABLE
+#else /* not _POSIX_VDISABLE */
+#ifdef CDEL
+#undef CDISABLE
+#define CDISABLE CDEL
+#else /* not CDEL */
+#define CDISABLE 255
+#endif /* not CDEL */
+#endif /* not _POSIX_VDISABLE */
+
+
+
+/****************************************/
+
char *getenv (), *getwd ();
char *getcwd ();
@@ -63,6 +111,9 @@ int eval = 0;
/* The display on which Emacs should work. --display. */
char *display = NULL;
+/* Nonzero means open a new Emacs frame on the current terminal. */
+int here = 0;
+
/* If non-NULL, the name of an editor to fallback to if the server
is not running. --alternate-editor. */
const char * alternate_editor = NULL;
@@ -78,6 +129,7 @@ struct option longopts[] =
{ "eval", no_argument, NULL, 'e' },
{ "help", no_argument, NULL, 'H' },
{ "version", no_argument, NULL, 'V' },
+ { "here", no_argument, NULL, 'h' },
{ "alternate-editor", required_argument, NULL, 'a' },
{ "socket-name", required_argument, NULL, 's' },
{ "display", required_argument, NULL, 'd' },
@@ -95,7 +147,7 @@ decode_options (argc, argv)
while (1)
{
int opt = getopt_long (argc, argv,
- "VHnea:s:d:", longopts, 0);
+ "VHnea:s:d:h", longopts, 0);
if (opt == EOF)
break;
@@ -134,6 +186,10 @@ decode_options (argc, argv)
exit (0);
break;
+ case 'h':
+ here = 1;
+ break;
+
case 'H':
print_help_and_exit ();
break;
@@ -144,6 +200,12 @@ decode_options (argc, argv)
break;
}
}
+
+ if (here) {
+ nowait = 0;
+ display = 0;
+ }
+
}
void
@@ -157,6 +219,7 @@ Every FILE can be either just a FILENAME or [+LINE[:COLUMN]] FILENAME.\n\
The following OPTIONS are accepted:\n\
-V, --version Just print a version info and return\n\
-H, --help Print this usage information message\n\
+-h, --here Open a new Emacs frame on the current terminal\n\
-n, --no-wait Don't wait for the server to return\n\
-e, --eval Evaluate the FILE arguments as ELisp expressions\n\
-d, --display=DISPLAY Visit the file in the given display\n\
@@ -247,6 +310,455 @@ fail (argc, argv)
}
}
+
+#ifdef HAVE_TERMIOS
+
+/* Adapted from emacs_get_tty() in sysdep.c. */
+int
+ec_get_tty (int fd, struct termios *settings)
+{
+ bzero (settings, sizeof (struct termios));
+ if (tcgetattr (fd, settings) < 0)
+ return -1;
+ return 0;
+}
+
+/* Adapted from emacs_set_tty() in sysdep.c. */
+int
+ec_set_tty (int fd, struct termios *settings, int flushp)
+{
+ /* Set the primary parameters - baud rate, character size, etcetera. */
+
+ int i;
+ /* We have those nifty POSIX tcmumbleattr functions.
+ William J. Smith <wjs@wiis.wang.com> writes:
+ "POSIX 1003.1 defines tcsetattr to return success if it was
+ able to perform any of the requested actions, even if some
+ of the requested actions could not be performed.
+ We must read settings back to ensure tty setup properly.
+ AIX requires this to keep tty from hanging occasionally." */
+ /* This make sure that we don't loop indefinitely in here. */
+ for (i = 0 ; i < 10 ; i++)
+ if (tcsetattr (fd, flushp ? TCSAFLUSH : TCSADRAIN, settings) < 0)
+ {
+ if (errno == EINTR)
+ continue;
+ else
+ return -1;
+ }
+ else
+ {
+ struct termios new;
+
+ bzero (&new, sizeof (new));
+ /* Get the current settings, and see if they're what we asked for. */
+ tcgetattr (fd, &new);
+ /* We cannot use memcmp on the whole structure here because under
+ * aix386 the termios structure has some reserved field that may
+ * not be filled in.
+ */
+ if ( new.c_iflag == settings->c_iflag
+ && new.c_oflag == settings->c_oflag
+ && new.c_cflag == settings->c_cflag
+ && new.c_lflag == settings->c_lflag
+ && memcmp (new.c_cc, settings->c_cc, NCCS) == 0)
+ break;
+ else
+ continue;
+ }
+ return 0;
+}
+
+int master;
+char *pty_name;
+
+struct termios old_tty;
+struct termios tty;
+int old_tty_valid;
+
+int tty_erase_char;
+int flow_control = 0;
+int meta_key = 0;
+char _sobuf[BUFSIZ];
+
+/* Adapted from init_sys_modes() in sysdep.c. */
+int
+init_tty ()
+{
+ if (! isatty (0))
+ {
+ fprintf (stderr, "%s: Input is not a terminal", "init_tty");
+ return 0;
+ }
+
+ ec_get_tty (0, &old_tty);
+ old_tty_valid = 1;
+ tty = old_tty;
+
+ tty_erase_char = old_tty.c_cc[VERASE];
+
+ tty.c_iflag |= (IGNBRK); /* Ignore break condition */
+ tty.c_iflag &= ~ICRNL; /* Disable map of CR to NL on input */
+#ifdef INLCR
+ tty.c_iflag &= ~INLCR; /* Disable map of NL to CR on input */
+#endif
+#ifdef ISTRIP
+ tty.c_iflag &= ~ISTRIP; /* don't strip 8th bit on input */
+#endif
+ tty.c_lflag &= ~ECHO; /* Disable echo */
+ tty.c_lflag &= ~ICANON; /* Disable erase/kill processing */
+#ifdef IEXTEN
+ tty.c_lflag &= ~IEXTEN; /* Disable other editing characters. */
+#endif
+ tty.c_lflag |= ISIG; /* Enable signals */
+ if (flow_control)
+ {
+ tty.c_iflag |= IXON; /* Enable start/stop output control */
+#ifdef IXANY
+ tty.c_iflag &= ~IXANY;
+#endif /* IXANY */
+ }
+ else
+ tty.c_iflag &= ~IXON; /* Disable start/stop output control */
+ tty.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL
+ on output */
+ tty.c_oflag &= ~TAB3; /* Disable tab expansion */
+#ifdef CS8
+ if (meta_key)
+ {
+ tty.c_cflag |= CS8; /* allow 8th bit on input */
+ tty.c_cflag &= ~PARENB; /* Don't check parity */
+ }
+#endif
+ tty.c_cc[VINTR] = CDISABLE;
+ tty.c_cc[VQUIT] = CDISABLE;
+ tty.c_cc[VMIN] = 1; /* Input should wait for at least 1 char */
+ tty.c_cc[VTIME] = 0; /* no matter how long that takes. */
+#ifdef VSWTCH
+ tty.c_cc[VSWTCH] = CDISABLE; /* Turn off shell layering use of C-z */
+#endif
+
+#ifdef VSUSP
+ tty.c_cc[VSUSP] = CDISABLE; /* Turn off mips handling of C-z. */
+#endif /* VSUSP */
+#ifdef V_DSUSP
+ tty.c_cc[V_DSUSP] = CDISABLE; /* Turn off mips handling of C-y. */
+#endif /* V_DSUSP */
+#ifdef VDSUSP /* Some systems have VDSUSP, some have V_DSUSP. */
+ tty.c_cc[VDSUSP] = CDISABLE;
+#endif /* VDSUSP */
+#ifdef VLNEXT
+ tty.c_cc[VLNEXT] = CDISABLE;
+#endif /* VLNEXT */
+#ifdef VREPRINT
+ tty.c_cc[VREPRINT] = CDISABLE;
+#endif /* VREPRINT */
+#ifdef VWERASE
+ tty.c_cc[VWERASE] = CDISABLE;
+#endif /* VWERASE */
+#ifdef VDISCARD
+ tty.c_cc[VDISCARD] = CDISABLE;
+#endif /* VDISCARD */
+
+ if (flow_control)
+ {
+#ifdef VSTART
+ tty.c_cc[VSTART] = '\021';
+#endif /* VSTART */
+#ifdef VSTOP
+ tty.c_cc[VSTOP] = '\023';
+#endif /* VSTOP */
+ }
+ else
+ {
+#ifdef VSTART
+ tty.c_cc[VSTART] = CDISABLE;
+#endif /* VSTART */
+#ifdef VSTOP
+ tty.c_cc[VSTOP] = CDISABLE;
+#endif /* VSTOP */
+ }
+
+#ifdef SET_LINE_DISCIPLINE
+ /* Need to explicitly request TERMIODISC line discipline or
+ Ultrix's termios does not work correctly. */
+ tty.c_line = SET_LINE_DISCIPLINE;
+#endif
+
+#ifdef AIX
+#ifndef IBMR2AIX
+ /* AIX enhanced edit loses NULs, so disable it. */
+ tty.c_line = 0;
+ tty.c_iflag &= ~ASCEDIT;
+#else
+ tty.c_cc[VSTRT] = 255;
+ tty.c_cc[VSTOP] = 255;
+ tty.c_cc[VSUSP] = 255;
+ tty.c_cc[VDSUSP] = 255;
+#endif /* IBMR2AIX */
+ if (flow_control)
+ {
+#ifdef VSTART
+ tty.c_cc[VSTART] = '\021';
+#endif /* VSTART */
+#ifdef VSTOP
+ tty.c_cc[VSTOP] = '\023';
+#endif /* VSTOP */
+ }
+ /* Also, PTY overloads NUL and BREAK.
+ don't ignore break, but don't signal either, so it looks like NUL.
+ This really serves a purpose only if running in an XTERM window
+ or via TELNET or the like, but does no harm elsewhere. */
+ tty.c_iflag &= ~IGNBRK;
+ tty.c_iflag &= ~BRKINT;
+#endif /* AIX */
+
+ ec_set_tty (0, &tty, 0);
+
+ /* This code added to insure that, if flow-control is not to be used,
+ we have an unlocked terminal at the start. */
+
+#ifdef TCXONC
+ if (!flow_control) ioctl (0, TCXONC, 1);
+#endif
+#ifndef APOLLO
+#ifdef TIOCSTART
+ if (!flow_control) ioctl (0, TIOCSTART, 0);
+#endif
+#endif
+
+#if defined (HAVE_TERMIOS) || defined (HPUX9)
+#ifdef TCOON
+ if (!flow_control) tcflow (0, TCOON);
+#endif
+#endif
+
+#ifdef _IOFBF
+ /* This symbol is defined on recent USG systems.
+ Someone says without this call USG won't really buffer the file
+ even with a call to setbuf. */
+ setvbuf (stdout, (char *) _sobuf, _IOFBF, sizeof _sobuf);
+#else
+ setbuf (stdout, (char *) _sobuf);
+#endif
+
+ return 1;
+}
+
+void
+window_change ()
+{
+ int width, height;
+
+#ifdef TIOCGWINSZ
+ {
+ /* BSD-style. */
+ struct winsize size;
+
+ if (ioctl (0, TIOCGWINSZ, &size) == -1)
+ width = height = 0;
+ else
+ {
+ width = size.ws_col;
+ height = size.ws_row;
+ }
+ }
+#else
+#ifdef TIOCGSIZE
+ {
+ /* SunOS - style. */
+ struct ttysize size;
+
+ if (ioctl (0, TIOCGSIZE, &size) == -1)
+ width = height = 0;
+ else
+ {
+ width = size.ts_cols;
+ height = size.ts_lines;
+ }
+ }
+#endif /* not SunOS-style */
+#endif /* not BSD-style */
+
+#ifdef TIOCSWINSZ
+ {
+ /* BSD-style. */
+ struct winsize size;
+ size.ws_row = height;
+ size.ws_col = width;
+
+ ioctl (master, TIOCSWINSZ, &size);
+ }
+#else
+#ifdef TIOCSSIZE
+ {
+ /* SunOS - style. */
+ struct ttysize size;
+ size.ts_lines = height;
+ size.ts_cols = width;
+
+ ioctl (master, TIOCGSIZE, &size);
+ }
+#endif /* not SunOS-style */
+#endif /* not BSD-style */
+}
+
+int in_conversation = 0;
+int quit_conversation = 0;
+
+SIGTYPE
+hang_up_signal (int signalnum)
+{
+ int old_errno = errno;
+
+ if (! in_conversation)
+ return;
+
+ quit_conversation = 1;
+
+ errno = old_errno;
+}
+
+SIGTYPE
+window_change_signal (int signalnum)
+{
+ int old_errno = errno;
+
+ if (! in_conversation)
+ goto end;
+
+ window_change();
+
+ end:
+ signal (SIGWINCH, window_change_signal);
+ errno = old_errno;
+}
+
+int
+init_signals ()
+{
+ /* Set up signal handlers. */
+ signal (SIGWINCH, window_change_signal);
+ signal (SIGHUP, hang_up_signal);
+
+ return 1;
+}
+
+
+
+/* Adapted from reset_sys_modes in sysdep.c. */
+int
+reset_tty ()
+{
+ fflush (stdout);
+#ifdef BSD_SYSTEM
+#ifndef BSD4_1
+ /* Avoid possible loss of output when changing terminal modes. */
+ fsync (fileno (stdout));
+#endif
+#endif
+
+#ifdef F_SETFL
+#ifdef O_NDELAY
+ fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~O_NDELAY);
+#endif
+#endif /* F_SETFL */
+
+ if (old_tty_valid)
+ while (ec_set_tty (0, &old_tty, 0) < 0 && errno == EINTR)
+ ;
+
+ return 1;
+}
+
+
+int
+init_pty ()
+{
+ master = getpt ();
+ if (master < 0)
+ return 0;
+
+ if (grantpt (master) < 0 || unlockpt (master) < 0)
+ goto close_master;
+ pty_name = strdup (ptsname (master));
+ if (! pty_name)
+ goto close_master;
+
+ /* Propagate window size. */
+ window_change ();
+
+ return 1;
+
+ close_master:
+ close (master);
+ return 0;
+}
+
+int
+copy_from_to (int in, int out)
+{
+ static char buf[BUFSIZ];
+ int nread = read (in, &buf, BUFSIZ);
+ if (nread == 0)
+ return 1; /* EOF */
+ else if (nread < 0 && errno != EAGAIN)
+ return 0; /* Error */
+ else if (nread > 0)
+ {
+ int r = 0;
+ int written = 0;
+
+ do {
+ r = write (out, &buf, nread);
+ } while ((r < 0 && errno == EAGAIN)
+ || (r > 0 && (written += r) && written != nread));
+
+ if (r < 0)
+ return 0; /* Error */
+ }
+ return 1;
+}
+
+int
+pty_conversation ()
+{
+ fd_set set;
+
+ in_conversation = 1;
+
+ while (! quit_conversation) {
+ int res;
+
+ FD_ZERO (&set);
+ FD_SET (master, &set);
+ FD_SET (1, &set);
+ res = select (FD_SETSIZE, &set, NULL, NULL, NULL);
+ if (res < 0)
+ {
+ if (errno != EINTR)
+ return 0;
+ }
+ else if (res > 0)
+ {
+ if (FD_ISSET (master, &set))
+ {
+ /* Copy Emacs output to stdout. */
+ if (! copy_from_to (master, 0))
+ return 1;
+ }
+ if (FD_ISSET (1, &set))
+ {
+ /* Forward user input to Emacs. */
+ if (! copy_from_to (1, master))
+ return 1;
+ }
+ }
+ }
+ return 1;
+}
+
+#endif /* HAVE_TERMIOS */
#if !defined (HAVE_SOCKETS) || defined (NO_SOCKETS_IN_FILE_SYSTEM)
@@ -312,7 +824,7 @@ main (argc, argv)
/* Process options. */
decode_options (argc, argv);
- if ((argc - optind < 1) && !eval)
+ if ((argc - optind < 1) && !eval && !here)
{
fprintf (stderr, "%s: file name or argument required\n", progname);
fprintf (stderr, "Try `%s --help' for more information\n", progname);
@@ -484,6 +996,38 @@ To start the server in Emacs, type \"M-x server-start\".\n",
fprintf (out, " ");
}
+ if (here)
+ {
+ if (! init_signals ())
+ {
+ fprintf (stderr, "%s: ", argv[0]);
+ perror ("fdopen");
+ fail (argc, argv);
+ }
+
+ if (! init_tty ())
+ {
+ reset_tty ();
+ fprintf (stderr, "%s: ", argv[0]);
+ perror ("fdopen");
+ fail (argc, argv);
+ }
+
+ if (! init_pty ())
+ {
+ reset_tty ();
+ fprintf (stderr, "%s: ", argv[0]);
+ perror ("fdopen");
+ fail (argc, argv);
+ }
+
+ fprintf (out, "-pty ");
+ quote_file_name (pty_name, out);
+ fprintf (out, " ");
+ quote_file_name (getenv("TERM"), out);
+ fprintf (out, " ");
+ }
+
if ((argc - optind > 0))
{
for (i = optind; i < argc; i++)
@@ -512,11 +1056,14 @@ To start the server in Emacs, type \"M-x server-start\".\n",
}
else
{
- while ((str = fgets (string, BUFSIZ, stdin)))
- {
- quote_file_name (str, out);
- }
- fprintf (out, " ");
+ if (!here)
+ {
+ while ((str = fgets (string, BUFSIZ, stdin)))
+ {
+ quote_file_name (str, out);
+ }
+ fprintf (out, " ");
+ }
}
fprintf (out, "\n");
@@ -524,8 +1071,25 @@ To start the server in Emacs, type \"M-x server-start\".\n",
/* Maybe wait for an answer. */
if (nowait)
- return 0;
+ {
+ reset_tty ();
+ return 0;
+ }
+ if (here)
+ {
+ if (! pty_conversation ())
+ {
+ reset_tty ();
+ fprintf (stderr, "%s: ", argv[0]);
+ perror ("fdopen");
+ fail (argc, argv);
+ }
+ close (master);
+ reset_tty ();
+ return 0;
+ }
+
if (!eval)
{
printf ("Waiting for Emacs...");
@@ -546,6 +1110,7 @@ To start the server in Emacs, type \"M-x server-start\".\n",
printf ("\n");
fflush (stdout);
+ reset_tty ();
return 0;
}
diff --git a/lib-src/pty.c b/lib-src/pty.c
new file mode 100644
index 00000000000..05c54c63ff5
--- /dev/null
+++ b/lib-src/pty.c
@@ -0,0 +1,20 @@
+/* Terminal initialization for emacsclient.
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
diff --git a/lib-src/pty.h b/lib-src/pty.h
new file mode 100644
index 00000000000..d8f6318176a
--- /dev/null
+++ b/lib-src/pty.h
@@ -0,0 +1,224 @@
+/* Terminal initialization for emacsclient.
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Adapted from systty.h */
+
+
+#ifdef HAVE_TERMIOS
+#define HAVE_TCATTR
+#endif
+
+
+/* Include the proper files. */
+#ifdef HAVE_TERMIO
+#ifdef __DGUX
+#include <sys/ioctl.h>
+#endif
+#ifndef NO_TERMIO
+#include <termio.h>
+#endif /* not NO_TERMIO */
+#ifndef INCLUDED_FCNTL
+#define INCLUDED_FCNTL
+#include <fcntl.h>
+#endif
+#else /* not HAVE_TERMIO */
+#ifdef HAVE_TERMIOS
+#if defined(_AIX) && defined(_I386)
+#include <termios.h> /* termios.h needs to be before termio.h */
+#include <termio.h>
+#else /* not (_AIX && _I386) */
+#ifndef NO_TERMIO
+#include <termio.h>
+#endif
+#include <termios.h>
+#endif /* not (_AIX && _I386) */
+#define INCLUDED_FCNTL
+#include <fcntl.h>
+#else /* neither HAVE_TERMIO nor HAVE_TERMIOS */
+#ifndef VMS
+#ifndef DOS_NT
+#include <sgtty.h>
+#endif /* not DOS_NT */
+#else /* VMS */
+#include <descrip.h>
+static struct iosb
+{
+ short status;
+ short offset;
+ short termlen;
+ short term;
+} input_iosb;
+
+extern int waiting_for_ast;
+extern int stop_input;
+extern int input_ef;
+extern int timer_ef;
+extern int process_ef;
+extern int input_eflist;
+extern int timer_eflist;
+
+static $DESCRIPTOR (input_dsc, "TT");
+static int terminator_mask[2] = { 0, 0 };
+
+static struct sensemode {
+ short status;
+ unsigned char xmit_baud;
+ unsigned char rcv_baud;
+ unsigned char crfill;
+ unsigned char lffill;
+ unsigned char parity;
+ unsigned char unused;
+ char class;
+ char type;
+ short scr_wid;
+ unsigned long tt_char : 24, scr_len : 8;
+ unsigned long tt2_char;
+} sensemode_iosb;
+#endif /* VMS */
+#endif /* not HAVE_TERMIOS */
+#endif /* not HAVE_TERMIO */
+
+#ifdef __GNU_LIBRARY__
+#include <sys/ioctl.h>
+#include <termios.h>
+#endif
+
+#ifdef AIXHFT
+/* Get files for keyboard remapping */
+#define HFNKEYS 2
+#include <sys/hft.h>
+#include <sys/devinfo.h>
+#endif
+
+/* Get rid of LLITOUT in 4.1, since it is said to stimulate kernel bugs. */
+#ifdef BSD4_1
+#undef LLITOUT
+#define LLITOUT 0
+#endif /* 4.1 */
+
+#ifdef NEED_BSDTTY
+#include <sys/bsdtty.h>
+#endif
+
+#if defined (HPUX) && defined (HAVE_PTYS)
+#include <sys/ptyio.h>
+#endif
+
+#ifdef AIX
+#include <sys/pty.h>
+#endif /* AIX */
+
+#if (defined (POSIX) || defined (NEED_UNISTD_H)) && defined (HAVE_UNISTD_H)
+#include <unistd.h>
+#endif
+
+#ifdef SYSV_PTYS
+#include <sys/types.h>
+#include <sys/tty.h>
+#ifdef titan
+#include <sys/ttyhw.h>
+#include <sys/stream.h>
+#endif
+#ifndef NO_PTY_H
+#include <sys/pty.h>
+#endif
+#endif
+
+/* saka@pfu.fujitsu.co.JP writes:
+ FASYNC defined in this file. But, FASYNC don't working.
+ so no problem, because unrequest_sigio only need. */
+#if defined (pfa)
+#include <sys/file.h>
+#endif
+
+
+/* Special cases - inhibiting the use of certain features. */
+
+#ifdef APOLLO
+#undef TIOCSTART
+#endif
+
+#ifdef XENIX
+#undef TIOCGETC /* Avoid confusing some conditionals that test this. */
+#endif
+
+#ifdef BROKEN_TIOCGETC
+#undef TIOCGETC /* Avoid confusing some conditionals that test this. */
+#endif
+
+/* UNIPLUS systems may have FIONREAD. */
+#ifdef UNIPLUS
+#include <sys.ioctl.h>
+#endif
+
+/* Allow m- file to inhibit use of FIONREAD. */
+#ifdef BROKEN_FIONREAD
+#undef FIONREAD
+#undef ASYNC
+#endif
+
+/* Interrupt input is not used if there is no FIONREAD. */
+#ifndef FIONREAD
+#undef SIGIO
+#endif
+
+/* On TERMIOS systems, the tcmumbleattr calls take care of these
+ parameters, and it's a bad idea to use them (on AIX, it makes the
+ tty hang for a long time). */
+#if defined (TIOCGLTC) && !defined (HAVE_TERMIOS)
+#define HAVE_LTCHARS
+#endif
+
+#if defined (TIOCGETC) && !defined (HAVE_TERMIOS)
+#define HAVE_TCHARS
+#endif
+
+
+/* Try to establish the correct character to disable terminal functions
+ in a system-independent manner. Note that USG (at least) define
+ _POSIX_VDISABLE as 0! */
+
+#ifdef _POSIX_VDISABLE
+#define CDISABLE _POSIX_VDISABLE
+#else /* not _POSIX_VDISABLE */
+#ifdef CDEL
+#undef CDISABLE
+#define CDISABLE CDEL
+#else /* not CDEL */
+#define CDISABLE 255
+#endif /* not CDEL */
+#endif /* not _POSIX_VDISABLE */
+
+/* Get the number of characters queued for output. */
+
+/* EMACS_OUTQSIZE(FD, int *SIZE) stores the number of characters
+ queued for output to the terminal FD in *SIZE, if FD is a tty.
+ Returns -1 if there was an error (i.e. FD is not a tty), 0
+ otherwise. */
+#ifdef TIOCOUTQ
+#define EMACS_OUTQSIZE(fd, size) (ioctl ((fd), TIOCOUTQ, (size)))
+#endif
+
+#ifdef HAVE_TERMIO
+#ifdef TCOUTQ
+#undef EMACS_OUTQSIZE
+#define EMACS_OUTQSIZE(fd, size) (ioctl ((fd), TCOUTQ, (size)))
+#endif
+#endif
diff --git a/lisp/server.el b/lisp/server.el
index 8e3b7e9a2cd..37b8eeb7574 100644
--- a/lisp/server.el
+++ b/lisp/server.el
@@ -319,6 +319,15 @@ PROC is the server process. Format of STRING is \"PATH PATH PATH... \\n\"."
(server-select-display display)
(error (process-send-string proc (nth 1 err))
(setq request "")))))
+ ;; Open a new tty at the client.
+ ((and (equal "-pty" arg) (string-match "\\([^ ]*\\) \\([^ ]*\\) " request))
+ (let ((pty (server-unquote-arg (match-string 1 request)))
+ (type (server-unquote-arg (match-string 2 request))))
+ (setq request (substring request (match-end 0)))
+ (condition-case err
+ (make-terminal-frame `((tty . ,pty) (tty-type . ,type)))
+ (error (process-send-string proc (nth 1 err))
+ (setq request "")))))
;; ARG is a line number option.
((string-match "\\`\\+[0-9]+\\'" arg)
(setq lineno (string-to-int (substring arg 1))))
diff --git a/src/dispextern.h b/src/dispextern.h
index 2538460dee2..0d127ba778d 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -2555,7 +2555,7 @@ extern int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
/* Defined in sysdep.c */
-void get_frame_size P_ ((int *, int *));
+void get_tty_size P_ ((struct tty_output *, int *, int *));
void request_sigio P_ ((void));
void unrequest_sigio P_ ((void));
int tabs_safe_p P_ ((void));
diff --git a/src/dispnew.c b/src/dispnew.c
index cf335cfeed6..3558934d83a 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -3321,7 +3321,7 @@ DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
clear_frame ();
clear_current_matrices (f);
update_end (f);
- fflush (stdout);
+ fflush (TTY_OUTPUT (FRAME_TTY (f)));
windows_or_buffers_changed++;
/* Mark all windows as inaccurate, so that every window will have
its redisplay done. */
@@ -3461,7 +3461,7 @@ direct_output_for_insert (g)
/* If we can't insert glyphs, we can use this method only
at the end of a line. */
- if (!TTY_CHAR_INS_DEL_OK (CURTTY ()))
+ if (!TTY_CHAR_INS_DEL_OK (FRAME_TTY (f)))
if (PT != ZV && FETCH_BYTE (PT_BYTE) != '\n')
return 0;
@@ -3658,7 +3658,7 @@ direct_output_for_insert (g)
rif->update_window_end_hook (w, 1, 0);
update_end (f);
updated_row = NULL;
- fflush (stdout);
+ fflush (TTY_OUTPUT (CURTTY ());
TRACE ((stderr, "direct output for insert\n"));
mark_window_display_accurate (it.window, 1);
@@ -3749,7 +3749,7 @@ direct_output_forward_char (n)
cursor_to (y, x);
}
- fflush (stdout);
+ fflush (TTY_OUTPUT (CURTTY ()));
redisplay_performed_directly_p = 1;
return 1;
}
@@ -5102,18 +5102,18 @@ update_frame_1 (f, force_p, inhibit_id_p)
Also flush out if likely to have more than 1k buffered
otherwise. I'm told that some telnet connections get
really screwed by more than 1k output at once. */
- int outq = PENDING_OUTPUT_COUNT (stdout);
+ int outq = PENDING_OUTPUT_COUNT (TTY_OUTPUT (FRAME_TTY (f)));
if (outq > 900
|| (outq > 20 && ((i - 1) % preempt_count == 0)))
{
- fflush (stdout);
+ fflush (TTY_OUTPUT (FRAME_TTY (f)));
if (preempt_count == 1)
{
#ifdef EMACS_OUTQSIZE
if (EMACS_OUTQSIZE (0, &outq) < 0)
/* Probably not a tty. Ignore the error and reset
the outq count. */
- outq = PENDING_OUTPUT_COUNT (stdout);
+ outq = PENDING_OUTPUT_COUNT (TTY_OUTPUT (FRAME_TTY (f)));
#endif
outq *= 10;
if (baud_rate <= outq && baud_rate > 0)
@@ -5893,28 +5893,34 @@ window_change_signal (signalnum) /* If we don't have an argument, */
#endif
int old_errno = errno;
- get_frame_size (&width, &height);
+ struct tty_output *tty;
+
+ /* 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) {
- /* The frame size change obviously applies to a termcap-controlled
- frame. Find such a frame in the list, and assume it's the only
- one (since the redisplay code always writes to stdout, not a
- FILE * specified in the frame structure). Record the new size,
- but don't reallocate the data structures now. Let that be done
- later outside of the signal handler. */
-
- {
- Lisp_Object tail, frame;
-
- FOR_EACH_FRAME (tail, frame)
- {
- if (FRAME_TERMCAP_P (XFRAME (frame)))
- {
- change_frame_size (XFRAME (frame), height, width, 0, 1, 0);
- break;
- }
- }
+ get_tty_size (tty, &width, &height);
+
+ {
+ Lisp_Object tail, frame;
+
+ FOR_EACH_FRAME (tail, frame)
+ {
+ if (FRAME_TERMCAP_P (XFRAME (frame)) && FRAME_TTY (XFRAME (frame)) == tty)
+ {
+ /* Record the new sizes, but don't reallocate the data structures
+ now. Let that be done later outside of the signal handler. */
+ change_frame_size (XFRAME (frame), height, width, 0, 1, 0);
+ break;
+ }
+ }
+ }
}
-
+
signal (SIGWINCH, window_change_signal);
errno = old_errno;
}
@@ -5969,10 +5975,11 @@ change_frame_size (f, newheight, newwidth, pretend, delay, safe)
{
Lisp_Object tail, frame;
- if (! FRAME_WINDOW_P (f))
+ if (FRAME_MSDOS_P (f))
{
- /* When using termcap, or on MS-DOS, all frames use
- the same screen, so a change in size affects all frames. */
+ /* On MS-DOS, all frames use the same screen, so a change in
+ size affects all frames. Termcap now supports multiple
+ ttys. */
FOR_EACH_FRAME (tail, frame)
if (! FRAME_WINDOW_P (XFRAME (frame)))
change_frame_size_1 (XFRAME (frame), newheight, newwidth,
@@ -6162,7 +6169,7 @@ terminate any keyboard macro currently executing. */)
putchar (07);
else
ring_bell ();
- fflush (stdout);
+ fflush (TTY_OUTPUT (CURTTY ()));
}
else
bitch_at_user ();
@@ -6179,7 +6186,7 @@ bitch_at_user ()
error ("Keyboard macro terminated by a command ringing the bell");
else
ring_bell ();
- fflush (stdout);
+ fflush (TTY_OUTPUT (CURTTY ()));
}
diff --git a/src/emacs.c b/src/emacs.c
index 9b07b5a17b2..4f6d5168c6d 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -1564,7 +1564,7 @@ main (argc, argv
if (!noninteractive)
{
#ifdef VMS
- init_vms_input ();/* init_display calls get_frame_size, that needs this. */
+ init_vms_input ();/* init_display calls get_tty_size, that needs this. */
#endif /* VMS */
init_display (); /* Determine terminal type. Calls init_sys_modes. */
}
diff --git a/src/frame.c b/src/frame.c
index 4a97befaf0e..7945ba0454b 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -114,8 +114,6 @@ Lisp_Object Qfullscreen, Qfullwidth, Qfullheight, Qfullboth;
Lisp_Object Qface_set_after_frame_default;
-
-Lisp_Object Vterminal_frame;
Lisp_Object Vdefault_frame_alist;
Lisp_Object Vdefault_frame_scroll_bars;
Lisp_Object Vmouse_position_function;
@@ -550,6 +548,7 @@ make_terminal_frame (tty, tty_type)
f->output_data.tty = term_init (tty, tty_type);
else
f->output_data.tty = term_dummy_init ();
+ f->output_data.tty->top_frame = frame;
#ifdef CANNOT_DUMP
FRAME_FOREGROUND_PIXEL(f) = FACE_TTY_DEFAULT_FG_COLOR;
FRAME_BACKGROUND_PIXEL(f) = FACE_TTY_DEFAULT_BG_COLOR;
@@ -637,12 +636,15 @@ Note that changing the size of one terminal frame automatically affects all. */
type[SBYTES (tty_type)] = 0;
}
-
f = make_terminal_frame (name, type);
}
- change_frame_size (f, FRAME_LINES (sf),
- FRAME_COLS (sf), 0, 0, 0);
+ {
+ int width, height;
+ get_tty_size (FRAME_TTY (f), &width, &height);
+ change_frame_size (f, height, width, 0, 0, 0);
+ }
+
adjust_glyphs (f);
calculate_costs (f);
XSETFRAME (frame, f);
@@ -746,6 +748,15 @@ do_switch_frame (frame, track, for_deletion)
if (!for_deletion && FRAME_HAS_MINIBUF_P (sf))
resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1);
+ if (FRAME_TERMCAP_P (XFRAME (selected_frame))
+ && FRAME_TERMCAP_P (XFRAME (frame))
+ && FRAME_TTY (XFRAME (selected_frame)) == FRAME_TTY (XFRAME (frame)))
+ {
+ XFRAME (selected_frame)->async_visible = 0;
+ XFRAME (frame)->async_visible = 1;
+ FRAME_TTY (XFRAME (frame))->top_frame = frame;
+ }
+
selected_frame = frame;
if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame)))
last_nonminibuf_frame = XFRAME (selected_frame);
@@ -979,7 +990,10 @@ next_frame (frame, minibuf)
f = XCAR (tail);
if (passed
- && FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame)))
+ && ((!FRAME_TERMCAP_P (XFRAME (f)) && !FRAME_TERMCAP_P (XFRAME (frame))
+ && FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame)))
+ || (FRAME_TERMCAP_P (XFRAME (f)) && FRAME_TERMCAP_P (XFRAME (frame))
+ && FRAME_TTY (XFRAME (f)) == FRAME_TTY (XFRAME (frame)))))
{
/* Decide whether this frame is eligible to be returned. */
@@ -1056,7 +1070,10 @@ prev_frame (frame, minibuf)
if (EQ (frame, f) && !NILP (prev))
return prev;
- if (FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame)))
+ if ((!FRAME_TERMCAP_P (XFRAME (f)) && !FRAME_TERMCAP_P (XFRAME (frame))
+ && FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame)))
+ || (FRAME_TERMCAP_P (XFRAME (f)) && FRAME_TERMCAP_P (XFRAME (frame))
+ && FRAME_TTY (XFRAME (f)) == FRAME_TTY (XFRAME (frame))))
{
/* Decide whether this frame is eligible to be returned,
according to minibuf. */
@@ -4081,9 +4098,6 @@ Setting this variable does not affect existing frames, only new ones. */);
= intern ("inhibit-default-face-x-resources");
staticpro (&Qinhibit_default_face_x_resources);
- DEFVAR_LISP ("terminal-frame", &Vterminal_frame,
- doc: /* The initial frame-object, which represents Emacs's stdout. */);
-
DEFVAR_LISP ("emacs-iconified", &Vemacs_iconified,
doc: /* Non-nil if all of emacs is iconified and frame updates are not needed. */);
Vemacs_iconified = Qnil;
diff --git a/src/frame.h b/src/frame.h
index 6d7f1fffa80..8b081e881a9 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -28,9 +28,7 @@ Boston, MA 02111-1307, USA. */
/* Miscellanea. */
-/* Nonzero means don't assume anything about current contents of
- actual terminal frame */
-
+/* Nonzero means there is at least one garbaged frame. */
extern int frame_garbaged;
/* Nonzero means FRAME_MESSAGE_BUF (selected_frame) is being used by
@@ -71,7 +69,7 @@ enum text_cursor_kinds
#if !defined(HAVE_X_WINDOWS)
-#define PIX_TYPE int
+#define PIX_TYPE unsigned long
/* A (mostly empty) x_output structure definition for building Emacs
on Unix and GNU/Linux without X support. */
@@ -743,7 +741,10 @@ typedef struct frame *FRAME_PTR;
Also, if a frame used to be invisible, but has just become visible,
it must be marked as garbaged, since redisplay hasn't been keeping
- up its contents. */
+ up its contents.
+
+ Note that a tty frame is visible if and only if it is the topmost
+ frame. */
#define FRAME_SAMPLE_VISIBILITY(f) \
(((f)->async_visible && (f)->visible != (f)->async_visible) ? \
@@ -799,8 +800,6 @@ extern int other_visible_frames P_ ((struct frame *));
extern Lisp_Object Vframe_list;
extern Lisp_Object Vdefault_frame_alist;
-extern Lisp_Object Vterminal_frame;
-
extern Lisp_Object Vmouse_highlight;
/* The currently selected frame. */
diff --git a/src/keyboard.c b/src/keyboard.c
index dd4619d7967..069c605dc6a 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -22,10 +22,10 @@ Boston, MA 02111-1307, USA. */
#include <config.h>
#include <signal.h>
#include <stdio.h>
+#include "lisp.h"
#include "systty.h" /* This must be included befor termchar.h. */
#include "termchar.h"
#include "termopts.h"
-#include "lisp.h"
#include "termhooks.h"
#include "macros.h"
#include "keyboard.h"
@@ -89,9 +89,6 @@ int interrupt_input_blocked;
int interrupt_input_pending;
-/* File descriptor to use for input. */
-extern int input_fd;
-
#ifdef HAVE_WINDOW_SYSTEM
/* Make all keyboard buffers much bigger when using X windows. */
#ifdef MAC_OS8
@@ -6588,7 +6585,7 @@ read_avail_input (expected)
if (read_socket_hook)
/* No need for FIONREAD or fcntl; just say don't wait. */
- nread = (*read_socket_hook) (input_fd, buf, KBD_BUFFER_SIZE, expected);
+ nread = (*read_socket_hook) (buf, KBD_BUFFER_SIZE, expected);
else
{
/* Using KBD_BUFFER_SIZE - 1 here avoids reading more than
@@ -6597,7 +6594,6 @@ read_avail_input (expected)
unsigned char cbuf[KBD_BUFFER_SIZE - 1];
int n_to_read;
- /* Determine how many characters we should *try* to read. */
#ifdef WINDOWSNT
return 0;
#else /* not WINDOWSNT */
@@ -6605,88 +6601,121 @@ read_avail_input (expected)
n_to_read = dos_keysns ();
if (n_to_read == 0)
return 0;
+
+ cbuf[0] = dos_keyread ();
+ nread = 1;
+
#else /* not MSDOS */
+
+ struct tty_output *tty;
+ nread = 0;
+
+ /* Try to read from each available tty, until one succeeds. */
+ for (tty = tty_list; tty && !nread; tty = tty->next) {
+
+ /* Determine how many characters we should *try* to read. */
#ifdef FIONREAD
- /* Find out how much input is available. */
- if (ioctl (input_fd, FIONREAD, &n_to_read) < 0)
- /* Formerly simply reported no input, but that sometimes led to
- a failure of Emacs to terminate.
- SIGHUP seems appropriate if we can't reach the terminal. */
- /* ??? Is it really right to send the signal just to this process
- rather than to the whole process group?
- Perhaps on systems with FIONREAD Emacs is alone in its group. */
- {
- if (! noninteractive)
- kill (getpid (), SIGHUP);
- else
- n_to_read = 0;
- }
- if (n_to_read == 0)
- return 0;
- if (n_to_read > sizeof cbuf)
- n_to_read = sizeof cbuf;
+ /* Find out how much input is available. */
+ if (ioctl (fileno (TTY_INPUT (tty)), FIONREAD, &n_to_read) < 0)
+ {
+ /* Formerly simply reported no input, but that sometimes led to
+ a failure of Emacs to terminate.
+ SIGHUP seems appropriate if we can't reach the terminal. */
+ /* ??? Is it really right to send the signal just to this process
+ rather than to the whole process group?
+ Perhaps on systems with FIONREAD Emacs is alone in its group. */
+ if (! noninteractive)
+ {
+ if (! tty_list->next)
+ kill (getpid (), SIGHUP); /* This was the last terminal. */
+ else
+ n_to_read = 0; /* XXX tty should be closed here. */
+ }
+ else
+ {
+ n_to_read = 0;
+ }
+ }
+ if (n_to_read == 0)
+ continue;
+ if (n_to_read > sizeof cbuf)
+ n_to_read = sizeof cbuf;
#else /* no FIONREAD */
#if defined (USG) || defined (DGUX) || defined(CYGWIN)
- /* Read some input if available, but don't wait. */
- n_to_read = sizeof cbuf;
- fcntl (input_fd, F_SETFL, O_NDELAY);
+ /* Read some input if available, but don't wait. */
+ n_to_read = sizeof cbuf;
+ fcntl (fileno (TTY_INPUT (tty)), F_SETFL, O_NDELAY);
#else
- you lose;
+ you lose;
#endif
#endif
-#endif /* not MSDOS */
-#endif /* not WINDOWSNT */
- /* Now read; for one reason or another, this will not block.
- NREAD is set to the number of chars read. */
- do
- {
-#ifdef MSDOS
- cbuf[0] = dos_keyread ();
- nread = 1;
-#else
- nread = emacs_read (input_fd, cbuf, n_to_read);
-#endif
- /* POSIX infers that processes which are not in the session leader's
- process group won't get SIGHUP's at logout time. BSDI adheres to
- this part standard and returns -1 from read (0) with errno==EIO
- when the control tty is taken away.
- Jeffrey Honig <jch@bsdi.com> says this is generally safe. */
- if (nread == -1 && errno == EIO)
- kill (0, SIGHUP);
+ /* Now read; for one reason or another, this will not block.
+ NREAD is set to the number of chars read. */
+ do
+ {
+ nread = emacs_read (fileno (TTY_INPUT (tty)), cbuf, n_to_read);
+ /* POSIX infers that processes which are not in the session leader's
+ process group won't get SIGHUP's at logout time. BSDI adheres to
+ this part standard and returns -1 from read (0) with errno==EIO
+ when the control tty is taken away.
+ Jeffrey Honig <jch@bsdi.com> says this is generally safe. */
+ if (nread == -1 && errno == EIO)
+ {
+ if (! tty_list->next)
+ kill (0, SIGHUP); /* This was the last terminal. */
+ else
+ ; /* XXX tty should be closed here. */
+ }
#if defined (AIX) && (! defined (aix386) && defined (_BSD))
- /* The kernel sometimes fails to deliver SIGHUP for ptys.
- This looks incorrect, but it isn't, because _BSD causes
- O_NDELAY to be defined in fcntl.h as O_NONBLOCK,
- and that causes a value other than 0 when there is no input. */
- if (nread == 0)
- kill (0, SIGHUP);
+ /* The kernel sometimes fails to deliver SIGHUP for ptys.
+ This looks incorrect, but it isn't, because _BSD causes
+ O_NDELAY to be defined in fcntl.h as O_NONBLOCK,
+ and that causes a value other than 0 when there is no input. */
+ if (nread == 0)
+ {
+ if (! tty_list->next)
+ kill (0, SIGHUP); /* This was the last terminal. */
+ else
+ ; /* XXX tty should be closed here. */
+ }
#endif
- }
- while (
- /* We used to retry the read if it was interrupted.
- But this does the wrong thing when O_NDELAY causes
- an EAGAIN error. Does anybody know of a situation
- where a retry is actually needed? */
+ }
+ while (
+ /* We used to retry the read if it was interrupted.
+ But this does the wrong thing when O_NDELAY causes
+ an EAGAIN error. Does anybody know of a situation
+ where a retry is actually needed? */
#if 0
- nread < 0 && (errno == EAGAIN
+ nread < 0 && (errno == EAGAIN
#ifdef EFAULT
- || errno == EFAULT
+ || errno == EFAULT
#endif
#ifdef EBADSLT
- || errno == EBADSLT
+ || errno == EBADSLT
#endif
- )
+ )
#else
- 0
+ 0
#endif
- );
-
+ );
+
#ifndef FIONREAD
#if defined (USG) || defined (DGUX) || defined (CYGWIN)
- fcntl (input_fd, F_SETFL, 0);
+ fcntl (fileno (TTY_INPUT (tty)), F_SETFL, 0);
#endif /* USG or DGUX or CYGWIN */
#endif /* no FIONREAD */
+
+ } /* for each tty */
+
+ if (! nread)
+ return 0;
+
+#endif /* not MSDOS */
+#endif /* not WINDOWSNT */
+
+ /* XXX Select frame corresponding to the tty. */
+
for (i = 0; i < nread; i++)
{
buf[i].kind = ASCII_KEYSTROKE_EVENT;
@@ -10058,6 +10087,9 @@ On such systems, Emacs starts a subshell instead of suspending. */)
int width, height;
struct gcpro gcpro1;
+ if (tty_list && tty_list->next)
+ error ("Suspend is not supported with multiple ttys");
+
if (!NILP (stuffstring))
CHECK_STRING (stuffstring);
@@ -10066,7 +10098,7 @@ On such systems, Emacs starts a subshell instead of suspending. */)
call1 (Vrun_hooks, intern ("suspend-hook"));
GCPRO1 (stuffstring);
- get_frame_size (&old_width, &old_height);
+ get_tty_size (CURTTY (), &old_width, &old_height);
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. */
@@ -10082,7 +10114,7 @@ On such systems, Emacs starts a subshell instead of suspending. */)
/* Check if terminal/window size has changed.
Note that this is not useful when we are running directly
with a window system; but suspend should be disabled in that case. */
- get_frame_size (&width, &height);
+ get_tty_size (CURTTY (), &width, &height);
if (width != old_width || height != old_height)
change_frame_size (SELECTED_FRAME (), height, width, 0, 0, 0);
diff --git a/src/lisp.h b/src/lisp.h
index 2c30549d53b..c2df96fe82d 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -2946,7 +2946,6 @@ 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));
extern void child_setup_tty P_ ((int));
diff --git a/src/macterm.c b/src/macterm.c
index dd031919a1f..39dfb8cb9a7 100644
--- a/src/macterm.c
+++ b/src/macterm.c
@@ -7598,7 +7598,7 @@ keycode_to_xkeysym (int keyCode, int *xKeySym)
/* Emacs calls this whenever it wants to read an input event from the
user. */
int
-XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
+XTread_socket (struct input_event *bufp, int numchars, int expected)
{
int count = 0;
#if USE_CARBON_EVENTS
diff --git a/src/scroll.c b/src/scroll.c
index f4faca2fad8..c4371377e03 100644
--- a/src/scroll.c
+++ b/src/scroll.c
@@ -22,9 +22,9 @@ Boston, MA 02111-1307, USA. */
#include <config.h>
#include <stdio.h>
#include <string.h>
+#include "lisp.h"
#include "systty.h" /* For emacs_tty in termchar.h */
#include "termchar.h"
-#include "lisp.h"
#include "dispextern.h"
#include "keyboard.h"
#include "frame.h"
diff --git a/src/sysdep.c b/src/sysdep.c
index 7573cc4b9de..43a7d7c25da 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -246,11 +246,6 @@ static int baud_convert[] =
int emacs_ospeed;
-/* The file descriptor for Emacs's input terminal.
- Under Unix, this is normally zero except when using X;
- under VMS, we place the input channel number here. */
-int input_fd;
-
void croak P_ ((char *));
#ifdef AIXHFT
@@ -263,16 +258,7 @@ void hft_reset ();
SIGMASKTYPE sigprocmask_set;
-/* Specify a different file descriptor for further input operations. */
-
-void
-change_input_fd (fd)
- int fd;
-{
- input_fd = fd;
-}
-
-/* Discard pending input on descriptor input_fd. */
+/* Discard pending input on all input descriptors. */
void
discard_tty_input ()
@@ -290,22 +276,28 @@ discard_tty_input ()
#ifdef VMS
end_kbd_input ();
- SYS$QIOW (0, input_fd, IO$_READVBLK|IO$M_PURGE, input_iosb, 0, 0,
+ SYS$QIOW (0, fileno (TTY_INPUT (CURTTY())), IO$_READVBLK|IO$M_PURGE, input_iosb, 0, 0,
&buf.main, 0, 0, terminator_mask, 0, 0);
queue_kbd_input ();
#else /* not VMS */
#ifdef APOLLO
{
int zero = 0;
- ioctl (input_fd, TIOCFLUSH, &zero);
+ ioctl (fileno (TTY_INPUT (CURTTY())), TIOCFLUSH, &zero);
}
#else /* not Apollo */
#ifdef MSDOS /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
while (dos_keyread () != -1)
;
#else /* not MSDOS */
- EMACS_GET_TTY (input_fd, &buf);
- EMACS_SET_TTY (input_fd, &buf, 0);
+ {
+ struct tty_output tty;
+ for (tty = tty_list; tty; tty = tty->next)
+ {
+ EMACS_GET_TTY (fileno (TTY_INPUT (tty)), &buf);
+ EMACS_SET_TTY (fileno (TTY_INPUT (tty)), &buf, 0);
+ }
+ }
#endif /* not MSDOS */
#endif /* not Apollo */
#endif /* not VMS */
@@ -330,7 +322,7 @@ stuff_char (c)
/* Should perhaps error if in batch mode */
#ifdef TIOCSTI
- ioctl (input_fd, TIOCSTI, &c);
+ ioctl (fileno (TTY_INPUT (CURTTY())), TIOCSTI, &c);
#else /* no TIOCSTI */
error ("Cannot stuff terminal input characters in this version of Unix");
#endif /* no TIOCSTI */
@@ -354,7 +346,7 @@ init_baud_rate ()
#ifdef VMS
struct sensemode sg;
- SYS$QIOW (0, input_fd, IO$_SENSEMODE, &sg, 0, 0,
+ SYS$QIOW (0, fileno (TTY_INPUT (CURTTY())), IO$_SENSEMODE, &sg, 0, 0,
&sg.class, 12, 0, 0, 0, 0 );
emacs_ospeed = sg.xmit_baud;
#else /* not VMS */
@@ -362,7 +354,7 @@ init_baud_rate ()
struct termios sg;
sg.c_cflag = B9600;
- tcgetattr (input_fd, &sg);
+ tcgetattr (fileno (TTY_INPUT (CURTTY())), &sg);
emacs_ospeed = cfgetospeed (&sg);
#if defined (USE_GETOBAUD) && defined (getobaud)
/* m88k-motorola-sysv3 needs this (ghazi@noc.rutgers.edu) 9/1/94. */
@@ -375,16 +367,16 @@ init_baud_rate ()
sg.c_cflag = B9600;
#ifdef HAVE_TCATTR
- tcgetattr (input_fd, &sg);
+ tcgetattr (fileno (TTY_INPUT (CURTTY())), &sg);
#else
- ioctl (input_fd, TCGETA, &sg);
+ ioctl (fileno (TTY_INPUT (CURTTY())), 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 (input_fd, TIOCGETP, &sg) < 0)
+ if (ioctl (fileno (TTY_INPUT (CURTTY())), TIOCGETP, &sg) < 0)
abort ();
emacs_ospeed = sg.sg_ospeed;
#endif /* not HAVE_TERMIO */
@@ -947,7 +939,7 @@ request_sigio ()
#ifdef SIGWINCH
sigunblock (sigmask (SIGWINCH));
#endif
- fcntl (input_fd, F_SETFL, old_fcntl_flags | FASYNC);
+ fcntl (fileno (TTY_INPUT (CURTTY())), F_SETFL, old_fcntl_flags | FASYNC);
interrupts_deferred = 0;
}
@@ -961,7 +953,7 @@ unrequest_sigio ()
#ifdef SIGWINCH
sigblock (sigmask (SIGWINCH));
#endif
- fcntl (input_fd, F_SETFL, old_fcntl_flags);
+ fcntl (fileno (TTY_INPUT (CURTTY())), F_SETFL, old_fcntl_flags);
interrupts_deferred = 1;
}
@@ -976,7 +968,7 @@ request_sigio ()
if (read_socket_hook)
return;
- ioctl (input_fd, FIOASYNC, &on);
+ ioctl (fileno (TTY_INPUT (CURTTY())), FIOASYNC, &on);
interrupts_deferred = 0;
}
@@ -988,7 +980,7 @@ unrequest_sigio ()
if (read_socket_hook)
return;
- ioctl (input_fd, FIOASYNC, &off);
+ ioctl (fileno (TTY_INPUT (CURTTY())), FIOASYNC, &off);
interrupts_deferred = 1;
}
@@ -1009,7 +1001,7 @@ request_sigio ()
sigemptyset (&st);
sigaddset (&st, SIGIO);
- ioctl (input_fd, FIOASYNC, &on);
+ ioctl (fileno (TTY_INPUT (CURTTY())), FIOASYNC, &on);
interrupts_deferred = 0;
sigprocmask (SIG_UNBLOCK, &st, (sigset_t *)0);
}
@@ -1022,7 +1014,7 @@ unrequest_sigio ()
if (read_socket_hook)
return;
- ioctl (input_fd, FIOASYNC, &off);
+ ioctl (fileno (TTY_INPUT (CURTTY())), FIOASYNC, &off);
interrupts_deferred = 1;
}
@@ -1088,7 +1080,7 @@ narrow_foreground_group ()
setpgrp (0, inherited_pgroup);
if (inherited_pgroup != me)
- EMACS_SET_TTY_PGRP (input_fd, &me);
+ EMACS_SET_TTY_PGRP (fileno (stdin), &me); /* stdin is intentional here */
setpgrp (0, me);
}
@@ -1097,7 +1089,7 @@ void
widen_foreground_group ()
{
if (inherited_pgroup != getpid ())
- EMACS_SET_TTY_PGRP (input_fd, &inherited_pgroup);
+ EMACS_SET_TTY_PGRP (fileno (stdin), &inherited_pgroup); /* stdin is intentional here */
setpgrp (0, inherited_pgroup);
}
@@ -1300,8 +1292,8 @@ init_all_sys_modes (void)
}
void
-init_sys_modes (otty)
- struct tty_output *otty;
+init_sys_modes (tty_out)
+ struct tty_output *tty_out;
{
struct emacs_tty tty;
@@ -1357,7 +1349,7 @@ nil means don't delete them until `list-processes' is run. */);
#ifndef VMS4_4
sys_access_reinit ();
#endif
-#endif /* not VMS */
+#endif /* VMS */
#ifdef BSD_PGRPS
if (! read_socket_hook && EQ (Vwindow_system, Qnil))
@@ -1370,14 +1362,14 @@ nil means don't delete them until `list-processes' is run. */);
if (!read_socket_hook && EQ (Vwindow_system, Qnil))
#endif
{
- EMACS_GET_TTY (input_fd, &otty->old_tty);
+ EMACS_GET_TTY (fileno (TTY_INPUT (tty_out)), &tty_out->old_tty);
- otty->old_tty_valid = 1;
+ tty_out->old_tty_valid = 1;
- tty = otty->old_tty;
+ tty = tty_out->old_tty;
#if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
- XSETINT (Vtty_erase_char, otty->old_tty.main.c_cc[VERASE]);
+ XSETINT (Vtty_erase_char, tty_out->old_tty.main.c_cc[VERASE]);
#ifdef DGUX
/* This allows meta to be sent on 8th bit. */
@@ -1542,7 +1534,7 @@ nil means don't delete them until `list-processes' is run. */);
tty.tchars.t_stopc = '\023';
}
- tty.lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | otty->old_tty.lmode;
+ tty.lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | tty_out->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. */
@@ -1560,28 +1552,28 @@ nil means don't delete them until `list-processes' is run. */);
tty.ltchars = new_ltchars;
#endif /* HAVE_LTCHARS */
#ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
- if (!otty->term_initted)
+ if (!tty_out->term_initted)
internal_terminal_init ();
dos_ttraw ();
#endif
- EMACS_SET_TTY (input_fd, &tty, 0);
+ EMACS_SET_TTY (fileno (TTY_INPUT (tty_out)), &tty, 0);
/* This code added to insure that, if flow-control is not to be used,
we have an unlocked terminal at the start. */
#ifdef TCXONC
- if (!flow_control) ioctl (input_fd, TCXONC, 1);
+ if (!flow_control) ioctl (fileno (TTY_INPUT (tty_out)), TCXONC, 1);
#endif
#ifndef APOLLO
#ifdef TIOCSTART
- if (!flow_control) ioctl (input_fd, TIOCSTART, 0);
+ if (!flow_control) ioctl (fileno (TTY_INPUT (tty_out)), TIOCSTART, 0);
#endif
#endif
#if defined (HAVE_TERMIOS) || defined (HPUX9)
#ifdef TCOON
- if (!flow_control) tcflow (input_fd, TCOON);
+ if (!flow_control) tcflow (fileno (TTY_INPUT (tty_out)), TCOON);
#endif
#endif
@@ -1601,7 +1593,7 @@ nil means don't delete them until `list-processes' is run. */);
#ifdef VMS
/* Appears to do nothing when in PASTHRU mode.
- SYS$QIOW (0, input_fd, IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0,
+ SYS$QIOW (0, fileno (TTY_INPUT (tty_out)), IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0,
interrupt_signal, oob_chars, 0, 0, 0, 0);
*/
queue_kbd_input (0);
@@ -1614,9 +1606,9 @@ nil means don't delete them until `list-processes' is run. */);
if (interrupt_input
&& ! read_socket_hook && EQ (Vwindow_system, Qnil))
{
- old_fcntl_owner = fcntl (input_fd, F_GETOWN, 0);
- fcntl (input_fd, F_SETOWN, getpid ());
- init_sigio (input_fd);
+ old_fcntl_owner = 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)));
}
#endif /* F_GETOWN */
#endif /* F_SETOWN_BUG */
@@ -1624,7 +1616,7 @@ nil means don't delete them until `list-processes' is run. */);
#ifdef BSD4_1
if (interrupt_input)
- init_sigio (input_fd);
+ init_sigio (fileno (TTY_INPUT (tty_out)));
#endif
#ifdef VMS /* VMS sometimes has this symbol but lacks setvbuf. */
@@ -1634,9 +1626,9 @@ nil means don't delete them until `list-processes' is run. */);
/* This symbol is defined on recent USG systems.
Someone says without this call USG won't really buffer the file
even with a call to setbuf. */
- setvbuf (stdout, (char *) _sobuf, _IOFBF, sizeof _sobuf);
+ setvbuf (TTY_OUTPUT (tty_out), (char *) _sobuf, _IOFBF, sizeof _sobuf);
#else
- setbuf (stdout, (char *) _sobuf);
+ setbuf (TTY_OUTPUT (tty_out), (char *) _sobuf);
#endif
#ifdef HAVE_WINDOW_SYSTEM
/* Emacs' window system on MSDOG uses the `internal terminal' and therefore
@@ -1649,26 +1641,37 @@ nil means don't delete them until `list-processes' is run. */);
#endif
)
#endif
- set_terminal_modes (otty);
+ set_terminal_modes (tty_out);
- if (!otty->term_initted
- && FRAMEP (Vterminal_frame)
- && FRAME_TERMCAP_P (XFRAME (Vterminal_frame)))
- init_frame_faces (XFRAME (Vterminal_frame));
+ if (!tty_out->term_initted)
+ {
+ Lisp_Object tail, frame;
+ FOR_EACH_FRAME (tail, frame)
+ {
+ if (FRAME_TERMCAP_P (XFRAME (frame))
+ && FRAME_TTY (XFRAME (frame)) == tty_out)
+ init_frame_faces (XFRAME (frame));
+ }
+ }
- if (otty->term_initted && no_redraw_on_reenter)
+ if (tty_out->term_initted && no_redraw_on_reenter)
{
if (display_completed)
direct_output_forward_char (0);
}
else
{
+ Lisp_Object tail, frame;
frame_garbaged = 1;
- if (FRAMEP (Vterminal_frame))
- FRAME_GARBAGED_P (XFRAME (Vterminal_frame)) = 1;
+ FOR_EACH_FRAME (tail, frame)
+ {
+ if (FRAME_TERMCAP_P (XFRAME (frame))
+ && FRAME_TTY (XFRAME (frame)) == tty_out)
+ FRAME_GARBAGED_P (XFRAME (frame)) = 1;
+ }
}
- otty->term_initted = 1;
+ tty_out->term_initted = 1;
}
/* Return nonzero if safe to use tabs in output.
@@ -1679,7 +1682,7 @@ tabs_safe_p ()
{
struct emacs_tty tty;
- EMACS_GET_TTY (input_fd, &tty);
+ EMACS_GET_TTY (fileno (TTY_INPUT (CURTTY())), &tty);
return EMACS_TTY_TABS_OK (&tty);
}
@@ -1688,7 +1691,8 @@ tabs_safe_p ()
We store 0 if there's no valid information. */
void
-get_frame_size (widthp, heightp)
+get_tty_size (tty_out, widthp, heightp)
+ struct tty_output *tty_out;
int *widthp, *heightp;
{
@@ -1697,7 +1701,7 @@ get_frame_size (widthp, heightp)
/* BSD-style. */
struct winsize size;
- if (ioctl (input_fd, TIOCGWINSZ, &size) == -1)
+ if (ioctl (fileno (TTY_INPUT (tty_out)), TIOCGWINSZ, &size) == -1)
*widthp = *heightp = 0;
else
{
@@ -1711,7 +1715,7 @@ get_frame_size (widthp, heightp)
/* SunOS - style. */
struct ttysize size;
- if (ioctl (input_fd, TIOCGSIZE, &size) == -1)
+ if (ioctl (fileno (TTY_INPUT (tty_out)), TIOCGSIZE, &size) == -1)
*widthp = *heightp = 0;
else
{
@@ -1724,7 +1728,7 @@ get_frame_size (widthp, heightp)
struct sensemode tty;
- SYS$QIOW (0, input_fd, IO$_SENSEMODE, &tty, 0, 0,
+ SYS$QIOW (0, fileno (TTY_INPUT (CURTTY())), IO$_SENSEMODE, &tty, 0, 0,
&tty.class, 12, 0, 0, 0, 0);
*widthp = tty.scr_wid;
*heightp = tty.scr_len;
@@ -1794,8 +1798,8 @@ reset_all_sys_modes (void)
/* 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 (otty)
- struct tty_output *otty;
+reset_sys_modes (tty_out)
+ struct tty_output *tty_out;
{
struct frame *sf;
@@ -1804,7 +1808,7 @@ reset_sys_modes (otty)
fflush (stdout);
return;
}
- if (!otty->term_initted)
+ if (!tty_out->term_initted)
return;
#ifdef HAVE_WINDOW_SYSTEM
/* Emacs' window system on MSDOG uses the `internal terminal' and therefore
@@ -1834,12 +1838,12 @@ reset_sys_modes (otty)
}
#endif
- reset_terminal_modes (otty);
- fflush (stdout);
+ reset_terminal_modes (tty_out);
+ fflush (TTY_OUTPUT (tty_out));
#ifdef BSD_SYSTEM
#ifndef BSD4_1
/* Avoid possible loss of output when changing terminal modes. */
- fsync (fileno (stdout));
+ fsync (TTY_OUTPUT (tty_out));
#endif
#endif
@@ -1849,12 +1853,13 @@ reset_sys_modes (otty)
if (interrupt_input)
{
reset_sigio ();
- fcntl (input_fd, F_SETOWN, old_fcntl_owner);
+ fcntl (fileno (TTY_INPUT (tty_out)), F_SETOWN, old_fcntl_owner);
}
#endif /* F_SETOWN */
#endif /* F_SETOWN_BUG */
#ifdef O_NDELAY
- fcntl (input_fd, F_SETFL, fcntl (input_fd, F_GETFL, 0) & ~O_NDELAY);
+ fcntl (fileno (TTY_INPUT (tty_out)), F_SETFL,
+ fcntl (fileno (TTY_INPUT (tty_out)), F_GETFL, 0) & ~O_NDELAY);
#endif
#endif /* F_SETFL */
#ifdef BSD4_1
@@ -1862,8 +1867,9 @@ reset_sys_modes (otty)
reset_sigio ();
#endif /* BSD4_1 */
- if (otty->old_tty_valid)
- while (EMACS_SET_TTY (input_fd, &otty->old_tty, 0) < 0 && errno == EINTR)
+ if (tty_out->old_tty_valid)
+ while (EMACS_SET_TTY (fileno (TTY_INPUT (tty_out)),
+ &tty_out->old_tty, 0) < 0 && errno == EINTR)
;
#ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
@@ -1874,7 +1880,7 @@ reset_sys_modes (otty)
/* 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, &otty->old_tty.main.c_line);
+ ioctl (0, TIOCSETD, &tty_out->old_tty.main.c_line);
#endif
#ifdef AIXHFT
@@ -1947,9 +1953,9 @@ init_vms_input ()
{
int status;
- if (input_fd == 0)
+ if (fileno (TTY_INPUT (CURTTY())) == 0)
{
- status = SYS$ASSIGN (&input_dsc, &input_fd, 0, 0);
+ status = SYS$ASSIGN (&input_dsc, &fileno (TTY_INPUT (CURTTY())), 0, 0);
if (! (status & 1))
LIB$STOP (status);
}
@@ -1960,7 +1966,7 @@ init_vms_input ()
void
stop_vms_input ()
{
- return SYS$DASSGN (input_fd);
+ return SYS$DASSGN (fileno (TTY_INPUT (CURTTY())));
}
short input_buffer;
@@ -1976,7 +1982,7 @@ queue_kbd_input ()
waiting_for_ast = 0;
stop_input = 0;
- status = SYS$QIO (0, input_fd, IO$_READVBLK,
+ status = SYS$QIO (0, fileno (TTY_INPUT (CURTTY())), IO$_READVBLK,
&input_iosb, kbd_input_ast, 1,
&input_buffer, 1, 0, terminator_mask, 0, 0);
}
@@ -2093,7 +2099,7 @@ end_kbd_input ()
#endif
if (LIB$AST_IN_PROG ()) /* Don't wait if suspending from kbd_buffer_store_event! */
{
- SYS$CANCEL (input_fd);
+ SYS$CANCEL (fileno (TTY_INPUT (CURTTY())));
return;
}
@@ -2102,7 +2108,7 @@ end_kbd_input ()
SYS$CLREF (input_ef);
waiting_for_ast = 1;
stop_input = 1;
- SYS$CANCEL (input_fd);
+ SYS$CANCEL (fileno (TTY_INPUT (CURTTY())));
SYS$SETAST (1);
SYS$WAITFR (input_ef);
waiting_for_ast = 0;
diff --git a/src/term.c b/src/term.c
index 4ecca5770a9..1df6e67a353 100644
--- a/src/term.c
+++ b/src/term.c
@@ -28,10 +28,10 @@ Boston, MA 02111-1307, USA. */
#include <sys/file.h>
+#include "lisp.h"
#include "systty.h" /* For emacs_tty in termchar.h */
#include "termchar.h"
#include "termopts.h"
-#include "lisp.h"
#include "charset.h"
#include "coding.h"
#include "keyboard.h"
@@ -123,7 +123,7 @@ void (*insert_glyphs_hook) P_ ((struct glyph *, int));
void (*write_glyphs_hook) P_ ((struct glyph *, int));
void (*delete_glyphs_hook) P_ ((int));
-int (*read_socket_hook) P_ ((int, struct input_event *, int, int));
+int (*read_socket_hook) P_ ((struct input_event *, int, int));
void (*frame_up_to_date_hook) P_ ((struct frame *));
@@ -792,12 +792,11 @@ clear_end_of_line (first_unused_hpos)
}
else
{ /* have to do it the hard way */
- struct frame *sf = XFRAME (selected_frame);
turn_off_insert ();
/* Do not write in last row last col with Auto-wrap on. */
- if (AutoWrap && curY == FRAME_LINES (sf) - 1
- && first_unused_hpos == FRAME_COLS (sf))
+ if (AutoWrap && curY == FRAME_LINES (f) - 1
+ && first_unused_hpos == FRAME_COLS (f))
first_unused_hpos--;
for (i = curX; i < first_unused_hpos; i++)
@@ -925,8 +924,7 @@ write_glyphs (string, len)
register int len;
{
int produced, consumed;
- struct frame *sf = XFRAME (selected_frame);
- struct frame *f = updating_frame ? updating_frame : sf;
+ struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame);
unsigned char conversion_buffer[1024];
int conversion_buffer_size = sizeof conversion_buffer;
@@ -944,8 +942,8 @@ write_glyphs (string, len)
since that would scroll the whole frame on some terminals. */
if (AutoWrap
- && curY + 1 == FRAME_LINES (sf)
- && (curX + len) == FRAME_COLS (sf))
+ && curY + 1 == FRAME_LINES (f)
+ && (curX + len) == FRAME_COLS (f))
len --;
if (len <= 0)
return;
@@ -1028,7 +1026,7 @@ insert_glyphs (start, len)
{
char *buf;
struct glyph *glyph = NULL;
- struct frame *f, *sf;
+ struct frame *f;
if (len <= 0)
return;
@@ -1039,8 +1037,7 @@ insert_glyphs (start, len)
return;
}
- sf = XFRAME (selected_frame);
- f = updating_frame ? updating_frame : sf;
+ f = updating_frame ? updating_frame : XFRAME (selected_frame);
if (TS_ins_multi_chars)
{
@@ -1159,7 +1156,7 @@ ins_del_lines (vpos, n)
char *multi = n > 0 ? TS_ins_multi_lines : TS_del_multi_lines;
char *single = n > 0 ? TS_ins_line : TS_del_line;
char *scroll = n > 0 ? TS_rev_scroll : TS_fwd_scroll;
- struct frame *sf;
+ struct frame *f;
register int i = n > 0 ? n : -n;
register char *buf;
@@ -1170,7 +1167,7 @@ ins_del_lines (vpos, n)
return;
}
- sf = XFRAME (selected_frame);
+ f = (updating_frame ? updating_frame : XFRAME (selected_frame));
/* If the lines below the insertion are being pushed
into the end of the window, this is the same as clearing;
@@ -1179,11 +1176,11 @@ ins_del_lines (vpos, n)
/* 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 (TTY_SCROLL_REGION_OK (FRAME_TTY (sf))
+ if (TTY_SCROLL_REGION_OK (FRAME_TTY (f))
&& vpos + i >= specified_window)
return;
- if (!TTY_MEMORY_BELOW_FRAME (FRAME_TTY (sf))
- && vpos + i >= FRAME_LINES (sf))
+ if (!TTY_MEMORY_BELOW_FRAME (FRAME_TTY (f))
+ && vpos + i >= FRAME_LINES (f))
return;
if (multi)
@@ -1191,7 +1188,7 @@ ins_del_lines (vpos, n)
raw_cursor_to (vpos, 0);
background_highlight ();
buf = tparam (multi, 0, 0, i);
- OUTPUT (FRAME_TTY (sf), buf);
+ OUTPUT (FRAME_TTY (f), buf);
xfree (buf);
}
else if (single)
@@ -1199,7 +1196,7 @@ ins_del_lines (vpos, n)
raw_cursor_to (vpos, 0);
background_highlight ();
while (--i >= 0)
- OUTPUT (FRAME_TTY (sf), single);
+ OUTPUT (FRAME_TTY (f), single);
if (TF_teleray)
curX = 0;
}
@@ -1212,15 +1209,15 @@ ins_del_lines (vpos, n)
raw_cursor_to (vpos, 0);
background_highlight ();
while (--i >= 0)
- OUTPUTL (FRAME_TTY (sf), scroll, specified_window - vpos);
+ OUTPUTL (FRAME_TTY (f), scroll, specified_window - vpos);
set_scroll_region (0, specified_window);
}
- if (!TTY_SCROLL_REGION_OK (FRAME_TTY (sf))
- && TTY_MEMORY_BELOW_FRAME (FRAME_TTY (sf))
+ if (!TTY_SCROLL_REGION_OK (FRAME_TTY (f))
+ && TTY_MEMORY_BELOW_FRAME (FRAME_TTY (f))
&& n < 0)
{
- cursor_to (FRAME_LINES (sf) + n, 0);
+ cursor_to (FRAME_LINES (f) + n, 0);
clear_to_end ();
}
}
@@ -2475,7 +2472,7 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
/* Get frame size from system, or else from termcap. */
{
int height, width;
- get_frame_size (&width, &height);
+ get_tty_size (tty, &width, &height);
FRAME_COLS (sf) = width;
FRAME_LINES (sf) = height;
}
diff --git a/src/termchar.h b/src/termchar.h
index 9d7399e80d9..a58dbc62125 100644
--- a/src/termchar.h
+++ b/src/termchar.h
@@ -39,8 +39,16 @@ struct tty_output
int term_initted; /* 1 if we have been through init_sys_modes. */
int old_tty_valid; /* 1 if outer tty status has been recorded. */
+
+
+ /* Redisplay. */
+
+ /* XXX This may cause problems with GC. */
+ Lisp_Object top_frame; /* The topmost frame on this tty. */
-
+ /* The previous terminal frame we displayed on this tty. */
+ struct frame *previous_terminal_frame;
+
/* Pixel values.
XXX What are these used for? */
diff --git a/src/termhooks.h b/src/termhooks.h
index c1ada7b851f..0fc48a883e8 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -371,7 +371,7 @@ struct input_event
#define EVENT_INIT(event) bzero (&(event), sizeof (struct input_event))
/* Called to read input events. */
-extern int (*read_socket_hook) P_ ((int, struct input_event *, int, int));
+extern int (*read_socket_hook) P_ ((struct input_event *, int, int));
/* Called when a frame's display becomes entirely up to date. */
extern void (*frame_up_to_date_hook) P_ ((struct frame *));
diff --git a/src/w32inevt.c b/src/w32inevt.c
index b3f8e3ff737..24295e122d0 100644
--- a/src/w32inevt.c
+++ b/src/w32inevt.c
@@ -642,7 +642,7 @@ maybe_generate_resize_event ()
}
int
-w32_console_read_socket (int sd, struct input_event *bufp, int numchars,
+w32_console_read_socket (struct input_event *bufp, int numchars,
int expected)
{
BOOL no_events = TRUE;
diff --git a/src/w32term.c b/src/w32term.c
index 06d82a7bee3..7f29cfe0869 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -4078,8 +4078,7 @@ static short temp_buffer[100];
*/
int
-w32_read_socket (sd, bufp, numchars, expected)
- register int sd;
+w32_read_socket (bufp, numchars, expected)
/* register */ struct input_event *bufp;
/* register */ int numchars;
int expected;
diff --git a/src/window.c b/src/window.c
index 48e517a68f7..4efc43bb9ce 100644
--- a/src/window.c
+++ b/src/window.c
@@ -6384,7 +6384,6 @@ init_window_once ()
{
struct frame *f = make_terminal_frame (0, 0);
XSETFRAME (selected_frame, f);
- Vterminal_frame = selected_frame;
minibuf_window = f->minibuffer_window;
selected_window = f->selected_window;
last_nonminibuf_frame = f;
diff --git a/src/xdisp.c b/src/xdisp.c
index cedfa9a72d5..79630ebab22 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -736,10 +736,6 @@ enum move_it_result
#define CLEAR_FACE_CACHE_COUNT 500
static int clear_face_cache_count;
-/* Record the previous terminal frame we displayed. */
-
-static struct frame *previous_terminal_frame;
-
/* Non-zero while redisplay_internal is in progress. */
int redisplaying_p;
@@ -2012,7 +2008,7 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
/* If realized faces have been removed, e.g. because of face
attribute changes of named faces, recompute them. When running
- in batch mode, the face cache of Vterminal_frame is null. If
+ in batch mode, the face cache of the initial frame is null. If
we happen to get called, make a dummy face cache. */
if (noninteractive && FRAME_FACE_CACHE (it->f) == NULL)
init_frame_faces (it->f);
@@ -7559,11 +7555,11 @@ clear_garbaged_frames ()
{
Lisp_Object tail, frame;
int changed_count = 0;
-
+
FOR_EACH_FRAME (tail, frame)
{
struct frame *f = XFRAME (frame);
-
+
if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f))
{
if (f->resized_p)
@@ -7574,7 +7570,7 @@ clear_garbaged_frames ()
f->resized_p = 0;
}
}
-
+
frame_garbaged = 0;
if (changed_count)
++windows_or_buffers_changed;
@@ -7610,7 +7606,7 @@ echo_area_display (update_frame_p)
/* When Emacs starts, selected_frame may be a visible terminal
frame, even if we run under a window system. If we let this
through, a message would be displayed on the terminal. */
- if (EQ (selected_frame, Vterminal_frame)
+ if (!FRAME_WINDOW_P (XFRAME (selected_frame))
&& !NILP (Vwindow_system))
return 0;
#endif /* HAVE_WINDOW_SYSTEM */
@@ -9687,17 +9683,16 @@ redisplay_internal (preserve_echo_area)
if (face_change_count)
++windows_or_buffers_changed;
- if (! FRAME_WINDOW_P (sf)
- && previous_terminal_frame != sf)
+ if (FRAME_TERMCAP_P (sf)
+ && FRAME_TTY (sf)->previous_terminal_frame != sf)
{
- /* Since frames on an ASCII terminal share the same display
- area, displaying a different frame means redisplay the whole
- thing. */
+ /* Since frames on a single ASCII terminal share the same
+ display area, displaying a different frame means redisplay
+ the whole thing. */
windows_or_buffers_changed++;
SET_FRAME_GARBAGED (sf);
- XSETFRAME (Vterminal_frame, sf);
+ FRAME_TTY (sf)->previous_terminal_frame = sf;
}
- previous_terminal_frame = sf;
/* Set the visible flags for all frames. Do this before checking
for resized or garbaged frames; they want to know if their frames
@@ -9719,6 +9714,7 @@ redisplay_internal (preserve_echo_area)
}
}
+
/* Notice any pending interrupt request to change frame size. */
do_pending_window_change (1);
@@ -10076,7 +10072,7 @@ redisplay_internal (preserve_echo_area)
{
struct frame *f = XFRAME (frame);
- if (FRAME_WINDOW_P (f) || f == sf)
+ if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
{
if (! EQ (frame, selected_frame))
/* Select the frame, for the sake of frame-local
diff --git a/src/xterm.c b/src/xterm.c
index 8718d76bc31..30de48aa5e7 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -7057,8 +7057,7 @@ x_dispatch_event (event, display)
EXPECTED is nonzero if the caller knows input is available. */
static int
-XTread_socket (sd, bufp, numchars, expected)
- register int sd;
+XTread_socket (bufp, numchars, expected)
/* register */ struct input_event *bufp;
/* register */ int numchars;
int expected;