mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2025-01-24 19:03:29 +00:00
Implemented suspending of emacsclient frames.
lib-src/emacsclient.c (quote_file_name): Renamed to quote_argument. (unquote_argument, handle_sigcont, handle_sigtstp): New functions. (out, in): New global variables for communicating with the Emacs process. (init_signals): Set up handlers for SIGCONT, SIGTSTP and SIGTTOU. (main): Changed out and in to global variables. Prepend `-eval' or '-file' to each argument. Use fsync to force sending the strings to Emacs. Removed obsolete -bad-version code. Support the -suspend command. Cleaned up newline handling. lisp/frame.el (suspend-frame): New function. Substitute key definition of suspend-emacs with suspend-frame. lisp/server.el (server-log): Cosmetic change in log format. (server-handle-delete-tty, server-handle-delete-frame): Added logging. (server-handle-suspend-tty, server-quote-arg): New functions. (server-start): Install server-handle-suspend-tty. (server-process-filter): Reorganized source code for clarity. Implemented -resume, -suspend and -ignore commands. lisp/term/x-win.el (x-initialize-window-system): Don't change the binding of C-z. src/cm.c: Replaced TTY_INPUT, TTY_OUTPUT, TTY_TERMSCRIPT calls with their macro expansion. src/dispnew.c: Ditto. src/frame.c: Ditto. src/keyboard.c: Ditto. src/sysdep.c: Ditto. src/keyboard.c (tty_read_avail_input): Don't read if the terminal is suspended. src/sysdep.c (discard_tty_input, init_sys_modes, reset_sys_modes): Ditto. src/term.c (tty_set_terminal_modes, tty_reset_terminal_modes): Ditto. src/term.c (Vsuspend_tty_functions, Vresume_tty_functions): New hooks. (syms_of_term): Defvar them. (term_init): Don't allow opening a new frame on a suspended tty device. (Fsuspend_tty, Fresume_tty): New functions. (syms_of_term): Defsubr them. src/termchar.c (struct tty_display_info): Update documentation of input and output. (TTY_INPUT, TTY_OUTPUT, TTY_TERMSCRIPT): Removed. git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-105
This commit is contained in:
parent
2fc0cf2aef
commit
0b0d3e0bce
@ -200,22 +200,50 @@ THINGS TO DO
|
||||
argument-handling is done in Lisp, so this should be quite easy to
|
||||
implement.
|
||||
|
||||
** Very strange bug: visible-bell does not work on secondary
|
||||
terminals. This might be something xterm (konsole) specific.
|
||||
** Make `struct display' accessible to Lisp programs. Accessor functions:
|
||||
|
||||
** Find out the best way to support suspending Emacs with multiple
|
||||
ttys. My guess: disable it on the controlling tty, but from other
|
||||
ttys pass it on to emacsclient somehow. (It is (I hope) trivial to
|
||||
extend emacsclient to handle suspend/resume. A `kill -STOP' almost
|
||||
works right now.)
|
||||
(displayp OBJECT): Returns t if OBJECT is a display.
|
||||
|
||||
** Clean up the frame-local variable system. I think it's ugly and
|
||||
error-prone. But maybe I just haven't yet fully understood it.
|
||||
(selected-display): Returns the display object of the selected frame.
|
||||
|
||||
(frame-display FRAME): Returns the display object of FRAME.
|
||||
|
||||
(display-frames DISPLAY): Returns a list of frames on DISPLAY.
|
||||
|
||||
(display-type DISPLAY): Returns the type of DISPLAY, as a
|
||||
symbol. (See `framep'.)
|
||||
|
||||
(display-device DISPLAY): Returns the name of the device that
|
||||
DISPLAY uses, as a string. (E.g: "/dev/pts/16", or
|
||||
":0.0")
|
||||
|
||||
See next issue why this is necessary.
|
||||
|
||||
** The following needs to be supported:
|
||||
|
||||
$ emacsclient -t
|
||||
C-z
|
||||
$ bg
|
||||
$ emacsclient -t
|
||||
(This fails now.)
|
||||
|
||||
The cleanest way to solve this is to allow multiple displays on the
|
||||
same terminal device; each new emacsclient process should create
|
||||
its own display. As displays are currently identified by their
|
||||
device names, this is not possible until struct display becomes
|
||||
accessible as a Lisp-level object.
|
||||
|
||||
** Add an elaborate mechanism for display-local variables. (There are
|
||||
already a few of these; search for `terminal-local' in the Elisp
|
||||
manual.)
|
||||
|
||||
** Very strange bug: visible-bell does not work on secondary
|
||||
terminals in xterm and konsole. The screen does flicker a bit,
|
||||
but it's so quick it isn't noticable.
|
||||
|
||||
** Clean up the frame-local variable system. I think it's ugly and
|
||||
error-prone. But maybe I just haven't yet fully understood it.
|
||||
|
||||
** Move baud_rate to struct display.
|
||||
|
||||
** Implement support for starting an interactive Emacs session without
|
||||
@ -667,4 +695,15 @@ DIARY OF CHANGES
|
||||
complaints seem to be caused by bugs in term.el; they are not
|
||||
related to multi-tty.)
|
||||
|
||||
-- Find out the best way to support suspending Emacs with multiple
|
||||
ttys. My guess: disable it on the controlling tty, but from other
|
||||
ttys pass it on to emacsclient somehow. (It is (I hope) trivial to
|
||||
extend emacsclient to handle suspend/resume. A `kill -STOP' almost
|
||||
works right now.)
|
||||
|
||||
(Done. I needed to play with signal handling and the server
|
||||
protocol a bit to make emacsclient behave as a normal UNIX program
|
||||
wrt foreground/background process groups.)
|
||||
|
||||
|
||||
;;; arch-tag: 8da1619e-2e79-41a8-9ac9-a0485daad17d
|
||||
|
@ -114,7 +114,7 @@ decode_options (argc, argv)
|
||||
display = getenv ("DISPLAY");
|
||||
if (display && strlen (display) == 0)
|
||||
display = NULL;
|
||||
|
||||
|
||||
if (display)
|
||||
window_system = 1;
|
||||
else
|
||||
@ -169,7 +169,7 @@ decode_options (argc, argv)
|
||||
window_system = 0;
|
||||
tty = 0;
|
||||
break;
|
||||
|
||||
|
||||
case 'H':
|
||||
print_help_and_exit ();
|
||||
break;
|
||||
@ -212,19 +212,21 @@ Report bugs to bug-gnu-emacs@gnu.org.\n", progname);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
/* In NAME, insert a & before each &, each space, each newline, and
|
||||
/* In STR, insert a & before each &, each space, each newline, and
|
||||
any initial -. Change spaces to underscores, too, so that the
|
||||
return value never contains a space. */
|
||||
return value never contains a space.
|
||||
|
||||
Does not change the string. Outputs the result to STREAM. */
|
||||
|
||||
void
|
||||
quote_file_name (name, stream)
|
||||
char *name;
|
||||
quote_argument (str, stream)
|
||||
char *str;
|
||||
FILE *stream;
|
||||
{
|
||||
char *copy = (char *) malloc (strlen (name) * 2 + 1);
|
||||
char *copy = (char *) malloc (strlen (str) * 2 + 1);
|
||||
char *p, *q;
|
||||
|
||||
p = name;
|
||||
p = str;
|
||||
q = copy;
|
||||
while (*p)
|
||||
{
|
||||
@ -242,7 +244,7 @@ quote_file_name (name, stream)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*p == '&' || (*p == '-' && p == name))
|
||||
if (*p == '&' || (*p == '-' && p == str))
|
||||
*q++ = '&';
|
||||
*q++ = *p++;
|
||||
}
|
||||
@ -254,6 +256,41 @@ quote_file_name (name, stream)
|
||||
free (copy);
|
||||
}
|
||||
|
||||
|
||||
/* The inverse of quote_argument. Removes quoting in string STR by
|
||||
modifying the string in place. Returns STR. */
|
||||
|
||||
char *
|
||||
unquote_argument (str)
|
||||
char *str;
|
||||
{
|
||||
char *p, *q;
|
||||
|
||||
if (! str)
|
||||
return str;
|
||||
|
||||
p = str;
|
||||
q = str;
|
||||
while (*p)
|
||||
{
|
||||
if (*p == '&')
|
||||
{
|
||||
p++;
|
||||
if (*p == '&')
|
||||
*p = '&';
|
||||
else if (*p == '_')
|
||||
*p = ' ';
|
||||
else if (*p == 'n')
|
||||
*p = '\n';
|
||||
else if (*p == '-')
|
||||
*p = '-';
|
||||
}
|
||||
*q++ = *p++;
|
||||
}
|
||||
*q = 0;
|
||||
return str;
|
||||
}
|
||||
|
||||
/* Like malloc but get fatal error if memory is exhausted. */
|
||||
|
||||
long *
|
||||
@ -288,8 +325,12 @@ fail (void)
|
||||
}
|
||||
}
|
||||
|
||||
/* The process id of Emacs. */
|
||||
int emacs_pid;
|
||||
|
||||
/* File handles for communicating with Emacs. */
|
||||
FILE *out, *in;
|
||||
|
||||
/* A signal handler that passes the signal to the Emacs process.
|
||||
Useful for SIGWINCH. */
|
||||
|
||||
@ -305,8 +346,62 @@ pass_signal_to_emacs (int signalnum)
|
||||
errno = old_errno;
|
||||
}
|
||||
|
||||
/* Signal handler for SIGCONT; notify the Emacs process that it can
|
||||
now resume our tty frame. */
|
||||
|
||||
SIGTYPE
|
||||
handle_sigcont (int signalnum)
|
||||
{
|
||||
int old_errno = errno;
|
||||
|
||||
if (tcgetpgrp (1) == getpgrp ())
|
||||
{
|
||||
/* We are in the foreground. */
|
||||
fprintf (out, "-resume \n");
|
||||
fflush (out);
|
||||
fsync (fileno (out));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We are in the background; cancel the continue. */
|
||||
kill (getpid (), SIGSTOP);
|
||||
}
|
||||
errno = old_errno;
|
||||
}
|
||||
|
||||
/* Signal handler for SIGTSTP; notify the Emacs process that we are
|
||||
going to sleep. Normally the suspend is initiated by Emacs via
|
||||
server-handle-suspend-tty, but if the server gets out of sync with
|
||||
reality, we may get a SIGTSTP on C-z. Handling this signal and
|
||||
notifying Emacs about it should get things under control again. */
|
||||
|
||||
SIGTYPE
|
||||
handle_sigtstp (int signalnum)
|
||||
{
|
||||
int old_errno = errno;
|
||||
sigset_t set;
|
||||
|
||||
if (out)
|
||||
{
|
||||
fprintf (out, "-suspend \n");
|
||||
fflush (out);
|
||||
fsync (fileno (out));
|
||||
}
|
||||
|
||||
/* Unblock this signal and call the default handler by temprarily
|
||||
changing the handler and resignalling. */
|
||||
sigprocmask (SIG_BLOCK, NULL, &set);
|
||||
sigdelset (&set, signalnum);
|
||||
signal (signalnum, SIG_DFL);
|
||||
kill (getpid (), signalnum);
|
||||
sigprocmask (SIG_SETMASK, &set, NULL); /* Let's the above signal through. */
|
||||
signal (signalnum, handle_sigtstp);
|
||||
|
||||
errno = old_errno;
|
||||
}
|
||||
|
||||
/* Set up signal handlers before opening a frame on the current tty. */
|
||||
|
||||
|
||||
void
|
||||
init_signals (void)
|
||||
{
|
||||
@ -320,6 +415,10 @@ init_signals (void)
|
||||
signal (SIGINT, pass_signal_to_emacs);
|
||||
signal (SIGQUIT, pass_signal_to_emacs);
|
||||
#endif
|
||||
|
||||
signal (SIGCONT, handle_sigcont);
|
||||
signal (SIGTSTP, handle_sigtstp);
|
||||
signal (SIGTTOU, handle_sigtstp);
|
||||
}
|
||||
|
||||
|
||||
@ -378,7 +477,7 @@ strprefix (char *prefix, char *string)
|
||||
|
||||
if (!string)
|
||||
return 0;
|
||||
|
||||
|
||||
for (i = 0; prefix[i]; i++)
|
||||
if (!string[i] || string[i] != prefix[i])
|
||||
return 0;
|
||||
@ -391,7 +490,6 @@ main (argc, argv)
|
||||
char **argv;
|
||||
{
|
||||
int s, i, needlf = 0;
|
||||
FILE *out, *in;
|
||||
struct sockaddr_un server;
|
||||
char *cwd, *str;
|
||||
char string[BUFSIZ];
|
||||
@ -427,9 +525,9 @@ main (argc, argv)
|
||||
int sock_status = 0;
|
||||
int default_sock = !socket_name;
|
||||
int saved_errno = 0;
|
||||
|
||||
|
||||
char *server_name = "server";
|
||||
|
||||
|
||||
if (socket_name && !index (socket_name, '/') && !index (socket_name, '\\'))
|
||||
{ /* socket_name is a file name component. */
|
||||
server_name = socket_name;
|
||||
@ -571,17 +669,14 @@ To start the server in Emacs, type \"M-x server-start\".\n",
|
||||
|
||||
/* First of all, send our version number for verification. */
|
||||
fprintf (out, "-version %s ", VERSION);
|
||||
|
||||
|
||||
if (nowait)
|
||||
fprintf (out, "-nowait ");
|
||||
|
||||
if (eval)
|
||||
fprintf (out, "-eval ");
|
||||
|
||||
if (display)
|
||||
{
|
||||
fprintf (out, "-display ");
|
||||
quote_file_name (display, out);
|
||||
quote_argument (display, out);
|
||||
fprintf (out, " ");
|
||||
}
|
||||
|
||||
@ -589,7 +684,7 @@ To start the server in Emacs, type \"M-x server-start\".\n",
|
||||
{
|
||||
char *tty_name = ttyname (fileno (stdin));
|
||||
char *type = getenv ("TERM");
|
||||
|
||||
|
||||
if (! tty_name)
|
||||
{
|
||||
fprintf (stderr, "%s: could not get terminal name\n", progname);
|
||||
@ -610,44 +705,60 @@ To start the server in Emacs, type \"M-x server-start\".\n",
|
||||
" is not supported\n", progname);
|
||||
fail ();
|
||||
}
|
||||
|
||||
|
||||
init_signals ();
|
||||
|
||||
|
||||
fprintf (out, "-tty ");
|
||||
quote_file_name (tty_name, out);
|
||||
quote_argument (tty_name, out);
|
||||
fprintf (out, " ");
|
||||
quote_file_name (type, out);
|
||||
quote_argument (type, out);
|
||||
fprintf (out, " ");
|
||||
}
|
||||
|
||||
if (window_system)
|
||||
fprintf (out, "-window-system ");
|
||||
|
||||
|
||||
if ((argc - optind > 0))
|
||||
{
|
||||
for (i = optind; i < argc; i++)
|
||||
{
|
||||
int relative = 0;
|
||||
|
||||
if (eval)
|
||||
; /* Don't prepend any cwd or anything like that. */
|
||||
else if (*argv[i] == '+')
|
||||
{
|
||||
{
|
||||
/* Don't prepend any cwd or anything like that. */
|
||||
fprintf (out, "-eval ");
|
||||
quote_argument (argv[i], out);
|
||||
fprintf (out, " ");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*argv[i] == '+')
|
||||
{
|
||||
char *p = argv[i] + 1;
|
||||
while (isdigit ((unsigned char) *p) || *p == ':') p++;
|
||||
if (*p != 0)
|
||||
{
|
||||
quote_file_name (cwd, out);
|
||||
fprintf (out, "/");
|
||||
}
|
||||
}
|
||||
else if (*argv[i] != '/')
|
||||
{
|
||||
quote_file_name (cwd, out);
|
||||
fprintf (out, "/");
|
||||
}
|
||||
if (*p == 0)
|
||||
{
|
||||
fprintf (out, "-position ");
|
||||
quote_argument (argv[i], out);
|
||||
fprintf (out, " ");
|
||||
continue;
|
||||
}
|
||||
else
|
||||
relative = 1;
|
||||
}
|
||||
else if (*argv[i] != '/')
|
||||
relative = 1;
|
||||
|
||||
quote_file_name (argv[i], out);
|
||||
fprintf (out, " ");
|
||||
}
|
||||
fprintf (out, "-file ");
|
||||
if (relative)
|
||||
{
|
||||
quote_argument (cwd, out);
|
||||
fprintf (out, "/");
|
||||
}
|
||||
quote_argument (argv[i], out);
|
||||
fprintf (out, " ");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -655,14 +766,19 @@ To start the server in Emacs, type \"M-x server-start\".\n",
|
||||
{
|
||||
while ((str = fgets (string, BUFSIZ, stdin)))
|
||||
{
|
||||
quote_file_name (str, out);
|
||||
if (eval)
|
||||
fprintf (out, "-eval ");
|
||||
else
|
||||
fprintf (out, "-file ");
|
||||
quote_argument (str, out);
|
||||
}
|
||||
fprintf (out, " ");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fprintf (out, "\n");
|
||||
fflush (out);
|
||||
fsync (fileno (out));
|
||||
|
||||
/* Maybe wait for an answer. */
|
||||
if (nowait)
|
||||
@ -676,44 +792,49 @@ To start the server in Emacs, type \"M-x server-start\".\n",
|
||||
needlf = 2;
|
||||
}
|
||||
fflush (stdout);
|
||||
fsync (1);
|
||||
|
||||
/* Now, wait for an answer and print any messages. */
|
||||
while ((str = fgets (string, BUFSIZ, in)))
|
||||
{
|
||||
char *p = str + strlen (str) - 1;
|
||||
while (p > str && *p == '\n')
|
||||
*p-- = 0;
|
||||
|
||||
if (strprefix ("-good-version ", str))
|
||||
{
|
||||
/* OK, we got the green light. */
|
||||
}
|
||||
else if (strprefix ("-bad-version ", str))
|
||||
{
|
||||
if (str[strlen (str) - 1] == '\n')
|
||||
str[strlen (str) - 1] = 0;
|
||||
|
||||
fprintf (stderr, "%s: Version mismatch: Emacs is %s, but we are %s\n",
|
||||
argv[0], str + strlen ("-bad-version "), VERSION);
|
||||
fail ();
|
||||
}
|
||||
else if (strprefix ("-emacs-pid ", str))
|
||||
{
|
||||
emacs_pid = strtol (string + strlen ("-emacs-pid"), NULL, 10);
|
||||
}
|
||||
else if (strprefix ("-print ", str))
|
||||
{
|
||||
if (needlf == 2)
|
||||
str = unquote_argument (str + strlen ("-print "));
|
||||
if (needlf)
|
||||
printf ("\n");
|
||||
printf ("%s", str + strlen ("-print "));
|
||||
needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n';
|
||||
printf ("%s", str);
|
||||
needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n';
|
||||
}
|
||||
else if (strprefix ("-error ", str))
|
||||
{
|
||||
if (needlf == 2)
|
||||
str = unquote_argument (str + strlen ("-error "));
|
||||
if (needlf)
|
||||
printf ("\n");
|
||||
printf ("*ERROR*: %s", str + strlen ("-print "));
|
||||
needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n';
|
||||
printf ("*ERROR*: %s", str);
|
||||
needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n';
|
||||
}
|
||||
else if (strprefix ("-suspend ", str))
|
||||
{
|
||||
if (needlf)
|
||||
printf ("\n");
|
||||
needlf = 0;
|
||||
kill (0, SIGSTOP);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (needlf == 2)
|
||||
if (needlf)
|
||||
printf ("\n");
|
||||
printf ("*ERROR*: Unknown message: %s", str);
|
||||
needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n';
|
||||
@ -723,6 +844,7 @@ To start the server in Emacs, type \"M-x server-start\".\n",
|
||||
if (needlf)
|
||||
printf ("\n");
|
||||
fflush (stdout);
|
||||
fsync (1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -750,6 +750,22 @@ Otherwise, that variable should be nil."
|
||||
(iconify-frame)
|
||||
(make-frame-visible)))
|
||||
|
||||
(defun suspend-frame ()
|
||||
"Do whatever is right to suspend the current frame.
|
||||
Calls `suspend-emacs' if invoked from the controlling terminal,
|
||||
`suspend-tty' from a secondary terminal, and
|
||||
`iconify-or-deiconify-frame' from an X frame."
|
||||
(interactive)
|
||||
(let ((type (framep (selected-frame))))
|
||||
(cond
|
||||
((eq type 'x) (iconify-or-deiconify-frame))
|
||||
((eq type t)
|
||||
(if (frame-tty-name)
|
||||
(suspend-tty)
|
||||
(suspend-emacs)))
|
||||
(t (suspend-emacs)))))
|
||||
|
||||
|
||||
(defun make-frame-names-alist ()
|
||||
(let* ((current-frame (selected-frame))
|
||||
(falist
|
||||
@ -1374,6 +1390,8 @@ Use Custom to set this variable to get the display updated."
|
||||
(define-key ctl-x-5-map "0" 'delete-frame)
|
||||
(define-key ctl-x-5-map "o" 'other-frame)
|
||||
|
||||
(substitute-key-definition 'suspend-emacs 'suspend-frame global-map)
|
||||
|
||||
(provide 'frame)
|
||||
|
||||
;;; arch-tag: 82979c70-b8f2-4306-b2ad-ddbd6b328b56
|
||||
|
282
lisp/server.el
282
lisp/server.el
@ -186,7 +186,7 @@ are done with it in the server.")
|
||||
(with-current-buffer "*server*"
|
||||
(goto-char (point-max))
|
||||
(insert (current-time-string)
|
||||
(if client (format " %s:" client) " ")
|
||||
(if client (format " %s: " client) " ")
|
||||
string)
|
||||
(or (bolp) (newline)))))
|
||||
|
||||
@ -227,6 +227,7 @@ are done with it in the server.")
|
||||
(term (nth 1 entry)))
|
||||
(when (equal term tty)
|
||||
(let ((client (assq proc server-clients)))
|
||||
(server-log (format "server-handle-delete-tty, tty %s" tty) (car client))
|
||||
(setq server-ttys (delq entry server-ttys))
|
||||
(delete-process (car client))
|
||||
(when (assq proc server-clients)
|
||||
@ -234,6 +235,16 @@ are done with it in the server.")
|
||||
;; `emacsclient -t -e '(delete-frame)'' correctly.
|
||||
(setq server-clients (delq client server-clients))))))))
|
||||
|
||||
(defun server-handle-suspend-tty (tty)
|
||||
"Notify the emacsclient process to suspend itself when its tty device is suspended."
|
||||
(dolist (entry server-ttys)
|
||||
(let ((proc (nth 0 entry))
|
||||
(term (nth 1 entry)))
|
||||
(when (equal term tty)
|
||||
(let ((process (car (assq proc server-clients))))
|
||||
(server-log (format "server-handle-suspend-tty, tty %s" tty) process)
|
||||
(process-send-string process "-suspend \n"))))))
|
||||
|
||||
(defun server-handle-delete-frame (frame)
|
||||
"Delete the client connection when the emacsclient frame is deleted."
|
||||
(dolist (entry server-frames)
|
||||
@ -241,6 +252,7 @@ are done with it in the server.")
|
||||
(f (nth 1 entry)))
|
||||
(when (equal frame f)
|
||||
(let ((client (assq proc server-clients)))
|
||||
(server-log (format "server-handle-delete-frame, frame %s" frame) (car client))
|
||||
(setq server-frames (delq entry server-frames))
|
||||
(delete-process (car client))
|
||||
(when (assq proc server-clients)
|
||||
@ -278,6 +290,19 @@ are done with it in the server.")
|
||||
(t " ")))
|
||||
arg t t))
|
||||
|
||||
(defun server-quote-arg (arg)
|
||||
"In NAME, insert a & before each &, each space, each newline, and -.
|
||||
Change spaces to underscores, too, so that the return value never
|
||||
contains a space."
|
||||
(replace-regexp-in-string
|
||||
"[-&\n ]" (lambda (s)
|
||||
(case (aref s 0)
|
||||
(?& "&&")
|
||||
(?- "&-")
|
||||
(?\n "&n")
|
||||
(?\s "&_")))
|
||||
arg t t))
|
||||
|
||||
(defun server-ensure-safe-dir (dir)
|
||||
"Make sure DIR is a directory with no race-condition issues.
|
||||
Creates the directory if necessary and makes sure:
|
||||
@ -325,6 +350,7 @@ Prefix arg means just kill any existing server communications subprocess."
|
||||
(server-log (message "Restarting server")))
|
||||
(letf (((default-file-modes) ?\700))
|
||||
(add-to-list 'delete-tty-after-functions 'server-handle-delete-tty)
|
||||
(add-to-list 'suspend-tty-functions 'server-handle-suspend-tty)
|
||||
(add-to-list 'delete-frame-functions 'server-handle-delete-frame)
|
||||
(setq server-process
|
||||
(make-network-process
|
||||
@ -358,140 +384,182 @@ PROC is the server process. Format of STRING is \"PATH PATH PATH... \\n\"."
|
||||
(setq string (concat prev string))
|
||||
(process-put proc 'previous-string nil)))
|
||||
(condition-case err
|
||||
;; If the input is multiple lines,
|
||||
;; process each line individually.
|
||||
(while (string-match "\n" string)
|
||||
(let ((request (substring string 0 (match-beginning 0)))
|
||||
(coding-system (and default-enable-multibyte-characters
|
||||
(or file-name-coding-system
|
||||
default-file-name-coding-system)))
|
||||
client nowait eval newframe display version-checked
|
||||
registered ; t if the client is already added to server-clients.
|
||||
(files nil)
|
||||
(lineno 1)
|
||||
(columnno 0))
|
||||
;; Remove this line from STRING.
|
||||
(setq string (substring string (match-end 0)))
|
||||
(setq client (cons proc nil))
|
||||
(while (string-match "[^ ]* " request)
|
||||
(let ((arg (substring request (match-beginning 0) (1- (match-end 0)))))
|
||||
(setq request (substring request (match-end 0)))
|
||||
(cond
|
||||
;; Check version numbers.
|
||||
((and (equal "-version" arg) (string-match "\\([0-9.]+\\) " request))
|
||||
(let* ((client-version (match-string 1 request))
|
||||
(truncated-emacs-version (substring emacs-version 0 (length client-version))))
|
||||
(setq request (substring request (match-end 0)))
|
||||
(if (equal client-version truncated-emacs-version)
|
||||
(progn
|
||||
(process-send-string proc "-good-version \n")
|
||||
(setq version-checked t))
|
||||
(error (concat "Version mismatch: Emacs is " truncated-emacs-version ", emacsclient is " client-version)))))
|
||||
(progn
|
||||
;; If the input is multiple lines,
|
||||
;; process each line individually.
|
||||
(while (string-match "\n" string)
|
||||
(let ((request (substring string 0 (match-beginning 0)))
|
||||
(coding-system (and default-enable-multibyte-characters
|
||||
(or file-name-coding-system
|
||||
default-file-name-coding-system)))
|
||||
client nowait newframe display version-checked
|
||||
dontkill ; t if the client should not be killed.
|
||||
registered ; t if the client is already added to server-clients.
|
||||
(files nil)
|
||||
(lineno 1)
|
||||
(columnno 0))
|
||||
;; Remove this line from STRING.
|
||||
(setq string (substring string (match-end 0)))
|
||||
(setq client (cons proc nil))
|
||||
(while (string-match "[^ ]* " request)
|
||||
(let ((arg (substring request (match-beginning 0) (1- (match-end 0)))))
|
||||
(setq request (substring request (match-end 0)))
|
||||
(cond
|
||||
;; Check version numbers.
|
||||
((and (equal "-version" arg) (string-match "\\([0-9.]+\\) " request))
|
||||
(let* ((client-version (match-string 1 request))
|
||||
(truncated-emacs-version (substring emacs-version 0 (length client-version))))
|
||||
(setq request (substring request (match-end 0)))
|
||||
(if (equal client-version truncated-emacs-version)
|
||||
(progn
|
||||
(process-send-string proc "-good-version \n")
|
||||
(setq version-checked t))
|
||||
(error (concat "Version mismatch: Emacs is " truncated-emacs-version ", emacsclient is " client-version)))))
|
||||
|
||||
((equal "-nowait" arg) (setq nowait t))
|
||||
((equal "-eval" arg) (setq eval t))
|
||||
((equal "-nowait" arg) (setq nowait t))
|
||||
|
||||
((and (equal "-display" arg) (string-match "\\([^ ]*\\) " request))
|
||||
(setq display (match-string 1 request)
|
||||
request (substring request (match-end 0))))
|
||||
((and (equal "-display" arg) (string-match "\\([^ ]*\\) " request))
|
||||
(setq display (match-string 1 request)
|
||||
request (substring request (match-end 0))))
|
||||
|
||||
;; Open a new X frame.
|
||||
((equal "-window-system" arg)
|
||||
(unless version-checked
|
||||
(error "Protocol error; make sure to use the correct version of emacsclient"))
|
||||
(let ((frame (make-frame-on-display
|
||||
(or display
|
||||
(frame-parameter nil 'display)
|
||||
(getenv "DISPLAY")
|
||||
(error "Please specify display")))))
|
||||
(push (list proc frame) server-frames)
|
||||
(select-frame frame)
|
||||
;; This makes sure that `emacsclient -w -e '(delete-frame)'' works right.
|
||||
(push client server-clients)
|
||||
(setq registered t
|
||||
newframe t)))
|
||||
|
||||
;; Open a new tty frame at the client. ARG is the name of the pseudo tty.
|
||||
((and (equal "-tty" arg) (string-match "\\([^ ]*\\) \\([^ ]*\\) " request))
|
||||
(let ((tty (server-unquote-arg (match-string 1 request)))
|
||||
(type (server-unquote-arg (match-string 2 request))))
|
||||
(setq request (substring request (match-end 0)))
|
||||
;; Open a new X frame.
|
||||
((equal "-window-system" arg)
|
||||
(unless version-checked
|
||||
(error "Protocol error; make sure to use the correct version of emacsclient"))
|
||||
(let ((frame (make-frame-on-tty tty type)))
|
||||
(push (list (car client) (frame-tty-name frame)) server-ttys)
|
||||
(process-send-string proc (concat "-emacs-pid " (number-to-string (emacs-pid)) "\n"))
|
||||
(let ((frame (make-frame-on-display
|
||||
(or display
|
||||
(frame-parameter nil 'display)
|
||||
(getenv "DISPLAY")
|
||||
(error "Please specify display")))))
|
||||
(push (list proc frame) server-frames)
|
||||
(select-frame frame)
|
||||
;; This makes sure that `emacsclient -t -e '(delete-frame)'' works right.
|
||||
;; This makes sure that `emacsclient -w -e '(delete-frame)'' works right.
|
||||
(push client server-clients)
|
||||
(setq registered t
|
||||
newframe t))))
|
||||
newframe t
|
||||
dontkill t)))
|
||||
|
||||
;; ARG is a line number option.
|
||||
((string-match "\\`\\+[0-9]+\\'" arg)
|
||||
(setq lineno (string-to-int (substring arg 1))))
|
||||
;; Resume a suspended tty frame.
|
||||
((equal "-resume" arg)
|
||||
(let ((tty (cadr (assq (car client) server-ttys))))
|
||||
(setq dontkill t)
|
||||
(when tty (resume-tty tty))))
|
||||
|
||||
;; ARG is line number:column option.
|
||||
((string-match "\\`\\+\\([0-9]+\\):\\([0-9]+\\)\\'" arg)
|
||||
(setq lineno (string-to-int (match-string 1 arg))
|
||||
columnno (string-to-int (match-string 2 arg))))
|
||||
;; Suspend the client's frame. (In case we get out of
|
||||
;; sync, and a C-z sends a SIGTSTP to emacsclient.)
|
||||
((equal "-suspend" arg)
|
||||
(let ((tty (cadr (assq (car client) server-ttys))))
|
||||
(setq dontkill t)
|
||||
(when tty (suspend-tty tty))))
|
||||
|
||||
;; ARG is a filename or a Lisp expression.
|
||||
(t
|
||||
;; Undo the quoting that emacsclient does
|
||||
;; for certain special characters.
|
||||
(setq arg (server-unquote-arg arg))
|
||||
;; Now decode the file name if necessary.
|
||||
(if coding-system
|
||||
(setq arg (decode-coding-string arg coding-system)))
|
||||
(unless version-checked
|
||||
(error "Protocol error; make sure to use the correct version of emacsclient"))
|
||||
(if eval
|
||||
;; ARG is a Lisp expression.
|
||||
(let ((v (eval (car (read-from-string arg)))))
|
||||
;; Noop; useful for debugging emacsclient.
|
||||
((and (equal "-ignore" arg) (string-match "\\([^ ]*\\) " request))
|
||||
(setq dontkill t
|
||||
request (substring request (match-end 0))))
|
||||
|
||||
;; Open a new tty frame at the client. ARG is the name of the pseudo tty.
|
||||
((and (equal "-tty" arg) (string-match "\\([^ ]*\\) \\([^ ]*\\) " request))
|
||||
(let ((tty (server-unquote-arg (match-string 1 request)))
|
||||
(type (server-unquote-arg (match-string 2 request))))
|
||||
(setq request (substring request (match-end 0)))
|
||||
(unless version-checked
|
||||
(error "Protocol error; make sure to use the correct version of emacsclient"))
|
||||
(let ((frame (make-frame-on-tty tty type)))
|
||||
(push (list (car client) (frame-tty-name frame)) server-ttys)
|
||||
(process-send-string proc (concat "-emacs-pid " (number-to-string (emacs-pid)) "\n"))
|
||||
(select-frame frame)
|
||||
;; This makes sure that `emacsclient -t -e '(delete-frame)'' works right.
|
||||
(push client server-clients)
|
||||
(setq registered t
|
||||
dontkill t
|
||||
newframe t))))
|
||||
|
||||
;; ARG is a line number option.
|
||||
((and (equal "-position" arg) (string-match "\\(\\+[0-9]+\\) " request))
|
||||
(setq request (substring request (match-end 0))
|
||||
lineno (string-to-int (substring (match-string 1 request) 1))))
|
||||
|
||||
;; ARG is line number:column option.
|
||||
((and (equal "-position" arg) (string-match "\\+\\([0-9]+\\):\\([0-9]+\\) " request))
|
||||
(setq request (substring request (match-end 0))
|
||||
lineno (string-to-int (match-string 1 request))
|
||||
columnno (string-to-int (match-string 2 request))))
|
||||
|
||||
;; ARG is a file to load.
|
||||
((and (equal "-file" arg) (string-match "\\([^ ]+\\) " request))
|
||||
(let ((file (server-unquote-arg (match-string 1 request))))
|
||||
(setq request (substring request (match-end 0)))
|
||||
(if coding-system
|
||||
(setq file (decode-coding-string file coding-system)))
|
||||
(setq file (command-line-normalize-file-name file))
|
||||
(push (list file lineno columnno) files))
|
||||
(setq lineno 1
|
||||
columnno 0))
|
||||
|
||||
;; ARG is a Lisp expression.
|
||||
((and (equal "-eval" arg) (string-match "\\([^ ]+\\) " request))
|
||||
(let ((expr (server-unquote-arg (match-string 1 request))))
|
||||
(setq request (substring request (match-end 0)))
|
||||
(if coding-system
|
||||
(setq expr (decode-coding-string expr coding-system)))
|
||||
(let ((v (eval (car (read-from-string expr)))))
|
||||
(when (and (not newframe) v)
|
||||
(with-temp-buffer
|
||||
(let ((standard-output (current-buffer)))
|
||||
(pp v)
|
||||
(process-send-string proc "-print ")
|
||||
(process-send-region proc (point-min) (point-max))))))
|
||||
;; ARG is a file name.
|
||||
;; Collapse multiple slashes to single slashes.
|
||||
(setq arg (command-line-normalize-file-name arg))
|
||||
(push (list arg lineno columnno) files))
|
||||
(setq lineno 1)
|
||||
(setq columnno 0)))))
|
||||
(process-send-string
|
||||
proc (server-quote-arg
|
||||
(buffer-substring-no-properties (point-min)
|
||||
(point-max))))
|
||||
(process-send-string proc "\n")))))
|
||||
(setq lineno 1
|
||||
columnno 0)))
|
||||
|
||||
;; Unknown command.
|
||||
(t (error "Unknown command: %s" arg)))))
|
||||
|
||||
(if (not version-checked)
|
||||
(error "Protocol error; make sure to use the correct version of emacsclient")
|
||||
(when files
|
||||
(run-hooks 'pre-command-hook)
|
||||
(server-visit-files files client nowait)
|
||||
(run-hooks 'post-command-hook))
|
||||
|
||||
;; CLIENT is now a list (CLIENTNUM BUFFERS...)
|
||||
(if (and (not newframe) (null (cdr client)))
|
||||
;; This client is empty; get rid of it immediately.
|
||||
(progn
|
||||
(delete-process proc)
|
||||
(server-log "Close empty client" proc))
|
||||
;; We visited some buffer for this client.
|
||||
(or nowait registered (push client server-clients))
|
||||
(unless (or isearch-mode (minibufferp))
|
||||
(if (and newframe (null (cdr client)))
|
||||
(message (substitute-command-keys
|
||||
"When done with this frame, type \\[delete-frame]"))
|
||||
(server-switch-buffer (nth 1 client))
|
||||
(run-hooks 'server-switch-hook)
|
||||
(unless nowait
|
||||
(message (substitute-command-keys
|
||||
"When done with a buffer, type \\[server-edit]"))))))))
|
||||
|
||||
;; Delete the client if necessary.
|
||||
(cond
|
||||
;; Client requested nowait; return immediately.
|
||||
(nowait
|
||||
(delete-process proc)
|
||||
(server-log "Close nowait client" proc))
|
||||
;; This client is empty; get rid of it immediately.
|
||||
((and (not dontkill) (null (cdr client)))
|
||||
(delete-process proc)
|
||||
(server-log "Close empty client" proc))
|
||||
((not registered)
|
||||
(push client server-clients)))
|
||||
|
||||
;; We visited some buffer for this client.
|
||||
(cond
|
||||
((or isearch-mode (minibufferp))
|
||||
nil)
|
||||
((and newframe (null (cdr client)))
|
||||
(message (substitute-command-keys
|
||||
"When done with this frame, type \\[delete-frame]")))
|
||||
((not (null (cdr client)))
|
||||
(server-switch-buffer (nth 1 client))
|
||||
(run-hooks 'server-switch-hook)
|
||||
(unless nowait
|
||||
(message (substitute-command-keys
|
||||
"When done with a buffer, type \\[server-edit]")))))))
|
||||
|
||||
;; Save for later any partial line that remains.
|
||||
(when (> (length string) 0)
|
||||
(process-put proc 'previous-string string)))
|
||||
;; condition-case
|
||||
(error (ignore-errors
|
||||
(process-send-string
|
||||
proc (concat "-error " (error-message-string err)))
|
||||
proc (concat "-error " (server-quote-arg (error-message-string err))))
|
||||
(setq string "")
|
||||
(server-log (error-message-string err) proc)
|
||||
(delete-process proc)))))
|
||||
|
@ -2442,11 +2442,7 @@ order until succeed.")
|
||||
(if res-selection-timeout
|
||||
(setq x-selection-timeout (string-to-number res-selection-timeout))))
|
||||
|
||||
;; XXX This is wrong in general with multi-tty support.
|
||||
(substitute-key-definition 'suspend-emacs 'iconify-or-deiconify-frame
|
||||
global-map)
|
||||
|
||||
;; XXX This is wrong in general with multi-tty support.
|
||||
;; Don't let Emacs suspend under X.
|
||||
(add-hook 'suspend-hook 'x-win-suspend-error)
|
||||
|
||||
;; Arrange for the kill and yank functions to set and check the clipboard.
|
||||
|
18
src/cm.c
18
src/cm.c
@ -64,9 +64,9 @@ int
|
||||
cmputc (c)
|
||||
char c;
|
||||
{
|
||||
if (TTY_TERMSCRIPT (current_tty))
|
||||
putc (c & 0177, TTY_TERMSCRIPT (current_tty));
|
||||
putc (c & 0177, TTY_OUTPUT (current_tty));
|
||||
if (current_tty->termscript)
|
||||
putc (c & 0177, current_tty->termscript);
|
||||
putc (c & 0177, current_tty->output);
|
||||
return c;
|
||||
}
|
||||
|
||||
@ -136,12 +136,12 @@ cmcheckmagic (struct tty_display_info *tty)
|
||||
{
|
||||
if (!MagicWrap (tty) || curY (tty) >= FrameRows (tty) - 1)
|
||||
abort ();
|
||||
if (TTY_TERMSCRIPT (tty))
|
||||
putc ('\r', TTY_TERMSCRIPT (tty));
|
||||
putc ('\r', TTY_OUTPUT (tty));
|
||||
if (TTY_TERMSCRIPT (tty))
|
||||
putc ('\n', TTY_TERMSCRIPT (tty));
|
||||
putc ('\n', TTY_OUTPUT (tty));
|
||||
if (tty->termscript)
|
||||
putc ('\r', tty->termscript);
|
||||
putc ('\r', tty->output);
|
||||
if (tty->termscript)
|
||||
putc ('\n', tty->termscript);
|
||||
putc ('\n', tty->output);
|
||||
curX (tty) = 0;
|
||||
curY (tty)++;
|
||||
}
|
||||
|
@ -3316,7 +3316,7 @@ DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
|
||||
clear_current_matrices (f);
|
||||
update_end (f);
|
||||
if (FRAME_TERMCAP_P (f))
|
||||
fflush (TTY_OUTPUT (FRAME_TTY (f)));
|
||||
fflush (FRAME_TTY (f)->output);
|
||||
windows_or_buffers_changed++;
|
||||
/* Mark all windows as inaccurate, so that every window will have
|
||||
its redisplay done. */
|
||||
@ -3659,7 +3659,7 @@ direct_output_for_insert (g)
|
||||
update_end (f);
|
||||
updated_row = NULL;
|
||||
if (FRAME_TERMCAP_P (f))
|
||||
fflush (TTY_OUTPUT (FRAME_TTY (f)));
|
||||
fflush (FRAME_TTY (f)->output);
|
||||
|
||||
TRACE ((stderr, "direct output for insert\n"));
|
||||
mark_window_display_accurate (it.window, 1);
|
||||
@ -3751,7 +3751,7 @@ direct_output_forward_char (n)
|
||||
}
|
||||
|
||||
if (FRAME_TERMCAP_P (f))
|
||||
fflush (TTY_OUTPUT (FRAME_TTY (f)));
|
||||
fflush (FRAME_TTY (f)->output);
|
||||
redisplay_performed_directly_p = 1;
|
||||
return 1;
|
||||
}
|
||||
@ -3849,9 +3849,9 @@ update_frame (f, force_p, inhibit_hairy_id_p)
|
||||
|
||||
if (FRAME_TERMCAP_P (f))
|
||||
{
|
||||
if (TTY_TERMSCRIPT (FRAME_TTY (f)))
|
||||
fflush (TTY_TERMSCRIPT (FRAME_TTY (f)));
|
||||
fflush (TTY_OUTPUT (FRAME_TTY (f)));
|
||||
if (FRAME_TTY (f)->termscript)
|
||||
fflush (FRAME_TTY (f)->termscript);
|
||||
fflush (FRAME_TTY (f)->output);
|
||||
}
|
||||
|
||||
/* Check window matrices for lost pointers. */
|
||||
@ -5133,18 +5133,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 (TTY_OUTPUT (FRAME_TTY (f)));
|
||||
int outq = PENDING_OUTPUT_COUNT (FRAME_TTY (f)->output);
|
||||
if (outq > 900
|
||||
|| (outq > 20 && ((i - 1) % preempt_count == 0)))
|
||||
{
|
||||
fflush (TTY_OUTPUT (FRAME_TTY (f)));
|
||||
fflush (FRAME_TTY (f)->output);
|
||||
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 (TTY_OUTPUT (FRAME_TTY (f)));
|
||||
outq = PENDING_OUTPUT_COUNT (FRAME_TTY (f->output));
|
||||
#endif
|
||||
outq *= 10;
|
||||
if (baud_rate <= outq && baud_rate > 0)
|
||||
@ -5999,7 +5999,7 @@ window_change_signal (signalnum) /* If we don't have an argument, */
|
||||
if (! tty->term_initted)
|
||||
continue;
|
||||
|
||||
get_tty_size (fileno (TTY_INPUT (tty)), &width, &height);
|
||||
get_tty_size (fileno (tty->input), &width, &height);
|
||||
|
||||
{
|
||||
Lisp_Object tail, frame;
|
||||
@ -6211,15 +6211,22 @@ FILE = nil means just close any termscript file currently open. */)
|
||||
(file)
|
||||
Lisp_Object file;
|
||||
{
|
||||
if (TTY_TERMSCRIPT (CURTTY ()) != 0)
|
||||
fclose (TTY_TERMSCRIPT (CURTTY ()));
|
||||
TTY_TERMSCRIPT (CURTTY ()) = 0;
|
||||
struct tty_display_info *tty;
|
||||
|
||||
if (! FRAME_TERMCAP_P (SELECTED_FRAME ()))
|
||||
error ("Current frame is not on a tty device");
|
||||
|
||||
tty = CURTTY ();
|
||||
|
||||
if (tty->termscript != 0)
|
||||
fclose (tty->termscript);
|
||||
tty->termscript = 0;
|
||||
|
||||
if (! NILP (file))
|
||||
{
|
||||
file = Fexpand_file_name (file, Qnil);
|
||||
TTY_TERMSCRIPT (CURTTY ()) = fopen (SDATA (file), "w");
|
||||
if (TTY_TERMSCRIPT (CURTTY ()) == 0)
|
||||
tty->termscript = fopen (SDATA (file), "w");
|
||||
if (tty->termscript == 0)
|
||||
report_file_error ("Opening termscript", Fcons (file, Qnil));
|
||||
}
|
||||
return Qnil;
|
||||
@ -6233,20 +6240,23 @@ Control characters in STRING will have terminal-dependent effects. */)
|
||||
(string)
|
||||
Lisp_Object string;
|
||||
{
|
||||
struct tty_display_info *tty;
|
||||
|
||||
/* ??? Perhaps we should do something special for multibyte strings here. */
|
||||
CHECK_STRING (string);
|
||||
|
||||
if (! FRAME_TERMCAP_P (SELECTED_FRAME ()))
|
||||
error ("Current frame is not on a tty device");
|
||||
|
||||
tty = CURTTY ();
|
||||
|
||||
if (TTY_TERMSCRIPT (CURTTY ()))
|
||||
if (tty->termscript)
|
||||
{
|
||||
fwrite (SDATA (string), 1, SBYTES (string),
|
||||
TTY_TERMSCRIPT (CURTTY ()));
|
||||
fflush (TTY_TERMSCRIPT (CURTTY ()));
|
||||
fwrite (SDATA (string), 1, SBYTES (string), tty->termscript);
|
||||
fflush (tty->termscript);
|
||||
}
|
||||
fwrite (SDATA (string), 1, SBYTES (string),
|
||||
TTY_OUTPUT (CURTTY ()));
|
||||
fflush (TTY_OUTPUT (CURTTY ()));
|
||||
fwrite (SDATA (string), 1, SBYTES (string), tty->output);
|
||||
fflush (tty->output);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
@ -6265,7 +6275,7 @@ terminate any keyboard macro currently executing. */)
|
||||
else
|
||||
ring_bell ();
|
||||
if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
|
||||
fflush (TTY_OUTPUT (CURTTY ()));
|
||||
fflush (CURTTY ()->output);
|
||||
}
|
||||
else
|
||||
bitch_at_user ();
|
||||
@ -6283,7 +6293,7 @@ bitch_at_user ()
|
||||
else
|
||||
ring_bell ();
|
||||
if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
|
||||
fflush (TTY_OUTPUT (CURTTY ()));
|
||||
fflush (CURTTY ()->output);
|
||||
}
|
||||
|
||||
|
||||
|
@ -667,7 +667,8 @@ and the `tty-type' parameter specifies the terminal type. Example:
|
||||
|
||||
(make-terminal-frame '((tty . "/dev/pts/5") (tty-type . "xterm")))
|
||||
|
||||
Note that changing the size of one terminal frame automatically affects all. */)
|
||||
Note that changing the size of one terminal frame automatically
|
||||
affects all frames on the same terminal device. */)
|
||||
(parms)
|
||||
Lisp_Object parms;
|
||||
{
|
||||
@ -742,7 +743,7 @@ Note that changing the size of one terminal frame automatically affects all. */
|
||||
|
||||
{
|
||||
int width, height;
|
||||
get_tty_size (fileno (TTY_INPUT (FRAME_TTY (f))), &width, &height);
|
||||
get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height);
|
||||
change_frame_size (f, height, width, 0, 0, 0);
|
||||
}
|
||||
|
||||
|
@ -6704,10 +6704,13 @@ tty_read_avail_input (struct display *display,
|
||||
if (! tty->term_initted) /* In case we get called during bootstrap. */
|
||||
return 0;
|
||||
|
||||
if (! tty->input)
|
||||
return 0; /* The terminal is suspended. */
|
||||
|
||||
/* Determine how many characters we should *try* to read. */
|
||||
#ifdef FIONREAD
|
||||
/* Find out how much input is available. */
|
||||
if (ioctl (fileno (TTY_INPUT (tty)), FIONREAD, &n_to_read) < 0)
|
||||
if (ioctl (fileno (tty->input), FIONREAD, &n_to_read) < 0)
|
||||
{
|
||||
if (! noninteractive)
|
||||
return -2; /* Close this display. */
|
||||
@ -6722,7 +6725,7 @@ tty_read_avail_input (struct display *display,
|
||||
#if defined (USG) || defined (DGUX) || defined(CYGWIN)
|
||||
/* Read some input if available, but don't wait. */
|
||||
n_to_read = sizeof cbuf;
|
||||
fcntl (fileno (TTY_INPUT (tty)), F_SETFL, O_NDELAY);
|
||||
fcntl (fileno (tty->input), F_SETFL, O_NDELAY);
|
||||
#else
|
||||
you lose;
|
||||
#endif
|
||||
@ -6732,7 +6735,7 @@ tty_read_avail_input (struct display *display,
|
||||
NREAD is set to the number of chars read. */
|
||||
do
|
||||
{
|
||||
nread = emacs_read (fileno (TTY_INPUT (tty)), cbuf, n_to_read);
|
||||
nread = emacs_read (fileno (tty->input), 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
|
||||
@ -6770,7 +6773,7 @@ tty_read_avail_input (struct display *display,
|
||||
|
||||
#ifndef FIONREAD
|
||||
#if defined (USG) || defined (DGUX) || defined (CYGWIN)
|
||||
fcntl (fileno (TTY_INPUT (tty)), F_SETFL, 0);
|
||||
fcntl (fileno (tty->input), F_SETFL, 0);
|
||||
#endif /* USG or DGUX or CYGWIN */
|
||||
#endif /* no FIONREAD */
|
||||
|
||||
@ -10168,7 +10171,7 @@ On such systems, Emacs starts a subshell instead of suspending. */)
|
||||
call1 (Vrun_hooks, intern ("suspend-hook"));
|
||||
|
||||
GCPRO1 (stuffstring);
|
||||
get_tty_size (fileno (TTY_INPUT (CURTTY ())), &old_width, &old_height);
|
||||
get_tty_size (fileno (CURTTY ()->input), &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. */
|
||||
@ -10184,7 +10187,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_tty_size (fileno (TTY_INPUT (CURTTY ())), &width, &height);
|
||||
get_tty_size (fileno (CURTTY ()->input), &width, &height);
|
||||
if (width != old_width || height != old_height)
|
||||
change_frame_size (SELECTED_FRAME (), height, width, 0, 0, 0);
|
||||
|
||||
|
96
src/sysdep.c
96
src/sysdep.c
@ -274,7 +274,7 @@ discard_tty_input ()
|
||||
|
||||
#ifdef VMS
|
||||
end_kbd_input ();
|
||||
SYS$QIOW (0, fileno (TTY_INPUT (CURTTY())), IO$_READVBLK|IO$M_PURGE, input_iosb, 0, 0,
|
||||
SYS$QIOW (0, fileno (CURTTY()->input), IO$_READVBLK|IO$M_PURGE, input_iosb, 0, 0,
|
||||
&buf.main, 0, 0, terminator_mask, 0, 0);
|
||||
queue_kbd_input ();
|
||||
#else /* not VMS */
|
||||
@ -284,7 +284,8 @@ discard_tty_input ()
|
||||
for (tty = tty_list; tty; tty = tty->next)
|
||||
{
|
||||
int zero = 0;
|
||||
ioctl (fileno (TTY_INPUT (tty)), TIOCFLUSH, &zero);
|
||||
if (tty->input)
|
||||
ioctl (fileno (tty->input), TIOCFLUSH, &zero);
|
||||
}
|
||||
}
|
||||
#else /* not Apollo */
|
||||
@ -296,8 +297,11 @@ discard_tty_input ()
|
||||
struct tty_display_info *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);
|
||||
if (tty->input) /* Is the device suspended? */
|
||||
{
|
||||
EMACS_GET_TTY (fileno (tty->input), &buf);
|
||||
EMACS_SET_TTY (fileno (tty->input), &buf, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* not MSDOS */
|
||||
@ -322,7 +326,7 @@ stuff_char (char c)
|
||||
|
||||
/* Should perhaps error if in batch mode */
|
||||
#ifdef TIOCSTI
|
||||
ioctl (fileno (TTY_INPUT (CURTTY())), TIOCSTI, &c);
|
||||
ioctl (fileno (CURTTY()->input), TIOCSTI, &c);
|
||||
#else /* no TIOCSTI */
|
||||
error ("Cannot stuff terminal input characters in this version of Unix");
|
||||
#endif /* no TIOCSTI */
|
||||
@ -1005,7 +1009,7 @@ request_sigio ()
|
||||
return;
|
||||
|
||||
/* XXX CURTTY() is bogus here. */
|
||||
ioctl (fileno (TTY_INPUT (CURTTY ())), FIOASYNC, &on);
|
||||
ioctl (fileno (CURTTY ()->input), FIOASYNC, &on);
|
||||
interrupts_deferred = 0;
|
||||
}
|
||||
|
||||
@ -1018,7 +1022,7 @@ unrequest_sigio ()
|
||||
return;
|
||||
|
||||
/* XXX CURTTY() is bogus here. */
|
||||
ioctl (fileno (TTY_INPUT (CURTTY ())), FIOASYNC, &off);
|
||||
ioctl (fileno (CURTTY ()->input), FIOASYNC, &off);
|
||||
interrupts_deferred = 1;
|
||||
}
|
||||
|
||||
@ -1366,6 +1370,9 @@ nil means don't delete them until `list-processes' is run. */);
|
||||
if (noninteractive)
|
||||
return;
|
||||
|
||||
if (!tty_out->output)
|
||||
return; /* The tty is suspended. */
|
||||
|
||||
#ifdef VMS
|
||||
if (!input_ef)
|
||||
input_ef = get_kbd_event_flag ();
|
||||
@ -1404,13 +1411,13 @@ nil means don't delete them until `list-processes' is run. */);
|
||||
unconditionally will not cause any problems. */
|
||||
if (! read_socket_hook && EQ (Vinitial_window_system, Qnil))
|
||||
#endif
|
||||
narrow_foreground_group (fileno (TTY_INPUT (tty_out)));
|
||||
narrow_foreground_group (fileno (tty_out->input));
|
||||
#endif
|
||||
|
||||
if (! tty_out->old_tty)
|
||||
tty_out->old_tty = (struct emacs_tty *) xmalloc (sizeof (struct emacs_tty));
|
||||
|
||||
EMACS_GET_TTY (fileno (TTY_INPUT (tty_out)), tty_out->old_tty);
|
||||
EMACS_GET_TTY (fileno (tty_out->input), tty_out->old_tty);
|
||||
|
||||
tty = *tty_out->old_tty;
|
||||
|
||||
@ -1626,23 +1633,23 @@ nil means don't delete them until `list-processes' is run. */);
|
||||
dos_ttraw ();
|
||||
#endif
|
||||
|
||||
EMACS_SET_TTY (fileno (TTY_INPUT (tty_out)), &tty, 0);
|
||||
EMACS_SET_TTY (fileno (tty_out->input), &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 (!tty_out->flow_control) ioctl (fileno (TTY_INPUT (tty_out)), TCXONC, 1);
|
||||
if (!tty_out->flow_control) ioctl (fileno (tty_out->input), TCXONC, 1);
|
||||
#endif
|
||||
#ifndef APOLLO
|
||||
#ifdef TIOCSTART
|
||||
if (!tty_out->flow_control) ioctl (fileno (TTY_INPUT (tty_out)), TIOCSTART, 0);
|
||||
if (!tty_out->flow_control) ioctl (fileno (tty_out->input), TIOCSTART, 0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_TERMIOS) || defined (HPUX9)
|
||||
#ifdef TCOON
|
||||
if (!tty_out->flow_control) tcflow (fileno (TTY_INPUT (tty_out)), TCOON);
|
||||
if (!tty_out->flow_control) tcflow (fileno (tty_out->input), TCOON);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -1662,7 +1669,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, fileno (TTY_INPUT (tty_out)), IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0,
|
||||
SYS$QIOW (0, fileno (tty_out->input), IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0,
|
||||
interrupt_signal, oob_chars, 0, 0, 0, 0);
|
||||
*/
|
||||
queue_kbd_input (0);
|
||||
@ -1673,10 +1680,10 @@ nil means don't delete them until `list-processes' is run. */);
|
||||
#ifdef F_GETOWN /* F_SETFL does not imply existence of F_GETOWN */
|
||||
if (interrupt_input)
|
||||
{
|
||||
old_fcntl_owner[fileno (TTY_INPUT (tty_out))] =
|
||||
fcntl (fileno (TTY_INPUT (tty_out)), F_GETOWN, 0);
|
||||
fcntl (fileno (TTY_INPUT (tty_out)), F_SETOWN, getpid ());
|
||||
init_sigio (fileno (TTY_INPUT (tty_out)));
|
||||
old_fcntl_owner[fileno (tty_out->input)] =
|
||||
fcntl (fileno (tty_out->input), F_GETOWN, 0);
|
||||
fcntl (fileno (tty_out->input), F_SETOWN, getpid ());
|
||||
init_sigio (fileno (tty_out->input));
|
||||
}
|
||||
#endif /* F_GETOWN */
|
||||
#endif /* F_SETOWN_BUG */
|
||||
@ -1684,7 +1691,7 @@ nil means don't delete them until `list-processes' is run. */);
|
||||
|
||||
#ifdef BSD4_1
|
||||
if (interrupt_input)
|
||||
init_sigio (fileno (TTY_INPUT (tty_out)));
|
||||
init_sigio (fileno (tty_out->input));
|
||||
#endif
|
||||
|
||||
#ifdef VMS /* VMS sometimes has this symbol but lacks setvbuf. */
|
||||
@ -1694,9 +1701,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 (TTY_OUTPUT (tty_out), (char *) _sobuf, _IOFBF, sizeof _sobuf);
|
||||
setvbuf (tty_out->output, (char *) _sobuf, _IOFBF, sizeof _sobuf);
|
||||
#else
|
||||
setbuf (TTY_OUTPUT (tty_out), (char *) _sobuf);
|
||||
setbuf (tty_out->output, (char *) _sobuf);
|
||||
#endif
|
||||
|
||||
tty_set_terminal_modes (tty_out->display);
|
||||
@ -1867,10 +1874,13 @@ reset_sys_modes (tty_out)
|
||||
if (!tty_out->term_initted)
|
||||
return;
|
||||
|
||||
if (!tty_out->output)
|
||||
return; /* The tty is suspended. */
|
||||
|
||||
/* Go to and clear the last line of the terminal. */
|
||||
|
||||
cmgoto (tty_out, FrameRows (tty_out) - 1, 0);
|
||||
|
||||
|
||||
/* Code adapted from tty_clear_end_of_line. */
|
||||
if (tty_out->TS_clr_line)
|
||||
{
|
||||
@ -1880,13 +1890,13 @@ reset_sys_modes (tty_out)
|
||||
{ /* have to do it the hard way */
|
||||
int i;
|
||||
turn_off_insert (tty_out);
|
||||
|
||||
|
||||
for (i = curX (tty_out); i < FrameCols (tty_out) - 1; i++)
|
||||
{
|
||||
fputc (' ', TTY_OUTPUT (tty_out));
|
||||
}
|
||||
{
|
||||
fputc (' ', tty_out->output);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
cmgoto (tty_out, FrameRows (tty_out) - 1, 0);
|
||||
fflush (tty_out->output);
|
||||
|
||||
@ -1902,11 +1912,11 @@ reset_sys_modes (tty_out)
|
||||
#endif
|
||||
|
||||
tty_reset_terminal_modes (tty_out->display);
|
||||
fflush (TTY_OUTPUT (tty_out));
|
||||
fflush (tty_out->output);
|
||||
#ifdef BSD_SYSTEM
|
||||
#ifndef BSD4_1
|
||||
/* Avoid possible loss of output when changing terminal modes. */
|
||||
fsync (fileno (TTY_OUTPUT (tty_out)));
|
||||
fsync (fileno (tty_out->output));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -1915,24 +1925,24 @@ reset_sys_modes (tty_out)
|
||||
#ifdef F_SETOWN /* F_SETFL does not imply existence of F_SETOWN */
|
||||
if (interrupt_input)
|
||||
{
|
||||
reset_sigio (fileno (TTY_INPUT (tty_out)));
|
||||
fcntl (fileno (TTY_INPUT (tty_out)), F_SETOWN,
|
||||
old_fcntl_owner[fileno (TTY_INPUT (tty_out))]);
|
||||
reset_sigio (fileno (tty_out->input));
|
||||
fcntl (fileno (tty_out->input), F_SETOWN,
|
||||
old_fcntl_owner[fileno (tty_out->input)]);
|
||||
}
|
||||
#endif /* F_SETOWN */
|
||||
#endif /* F_SETOWN_BUG */
|
||||
#ifdef O_NDELAY
|
||||
fcntl (fileno (TTY_INPUT (tty_out)), F_SETFL,
|
||||
fcntl (fileno (TTY_INPUT (tty_out)), F_GETFL, 0) & ~O_NDELAY);
|
||||
fcntl (fileno (tty_out->input), F_SETFL,
|
||||
fcntl (fileno (tty_out->input), F_GETFL, 0) & ~O_NDELAY);
|
||||
#endif
|
||||
#endif /* F_SETFL */
|
||||
#ifdef BSD4_1
|
||||
if (interrupt_input)
|
||||
reset_sigio (fileno (TTY_INPUT (tty_out)));
|
||||
reset_sigio (fileno (tty_out->input));
|
||||
#endif /* BSD4_1 */
|
||||
|
||||
if (tty_out->old_tty)
|
||||
while (EMACS_SET_TTY (fileno (TTY_INPUT (tty_out)),
|
||||
while (EMACS_SET_TTY (fileno (tty_out->input),
|
||||
tty_out->old_tty, 0) < 0 && errno == EINTR)
|
||||
;
|
||||
|
||||
@ -1952,7 +1962,7 @@ reset_sys_modes (tty_out)
|
||||
#endif
|
||||
|
||||
#ifdef BSD_PGRPS
|
||||
widen_foreground_group (fileno (TTY_INPUT (tty_out)));
|
||||
widen_foreground_group (fileno (tty_out->input));
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -2017,9 +2027,9 @@ init_vms_input ()
|
||||
{
|
||||
int status;
|
||||
|
||||
if (fileno (TTY_INPUT (CURTTY())) == 0)
|
||||
if (fileno (CURTTY ()->input)) == 0)
|
||||
{
|
||||
status = SYS$ASSIGN (&input_dsc, &fileno (TTY_INPUT (CURTTY())), 0, 0);
|
||||
status = SYS$ASSIGN (&input_dsc, &fileno (CURTTY ()->input)), 0, 0);
|
||||
if (! (status & 1))
|
||||
LIB$STOP (status);
|
||||
}
|
||||
@ -2030,7 +2040,7 @@ init_vms_input ()
|
||||
void
|
||||
stop_vms_input ()
|
||||
{
|
||||
return SYS$DASSGN (fileno (TTY_INPUT (CURTTY())));
|
||||
return SYS$DASSGN (fileno (CURTTY ()->input)));
|
||||
}
|
||||
|
||||
short input_buffer;
|
||||
@ -2046,7 +2056,7 @@ queue_kbd_input ()
|
||||
|
||||
waiting_for_ast = 0;
|
||||
stop_input = 0;
|
||||
status = SYS$QIO (0, fileno (TTY_INPUT (CURTTY())), IO$_READVBLK,
|
||||
status = SYS$QIO (0, fileno (CURTTY()->input), IO$_READVBLK,
|
||||
&input_iosb, kbd_input_ast, 1,
|
||||
&input_buffer, 1, 0, terminator_mask, 0, 0);
|
||||
}
|
||||
@ -2163,7 +2173,7 @@ end_kbd_input ()
|
||||
#endif
|
||||
if (LIB$AST_IN_PROG ()) /* Don't wait if suspending from kbd_buffer_store_event! */
|
||||
{
|
||||
SYS$CANCEL (fileno (TTY_INPUT (CURTTY())));
|
||||
SYS$CANCEL (fileno (CURTTY()->input));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2172,7 +2182,7 @@ end_kbd_input ()
|
||||
SYS$CLREF (input_ef);
|
||||
waiting_for_ast = 1;
|
||||
stop_input = 1;
|
||||
SYS$CANCEL (fileno (TTY_INPUT (CURTTY())));
|
||||
SYS$CANCEL (fileno (CURTTY()->input));
|
||||
SYS$SETAST (1);
|
||||
SYS$WAITFR (input_ef);
|
||||
waiting_for_ast = 0;
|
||||
|
234
src/term.c
234
src/term.c
@ -106,9 +106,15 @@ void delete_tty_output P_ ((struct frame *));
|
||||
|
||||
Lisp_Object Vring_bell_function;
|
||||
|
||||
/* Functions to call after a tty was deleted. */
|
||||
/* Functions to call after deleting a tty. */
|
||||
Lisp_Object Vdelete_tty_after_functions;
|
||||
|
||||
/* Functions to call after suspending a tty. */
|
||||
Lisp_Object Vsuspend_tty_functions;
|
||||
|
||||
/* Functions to call after resuming a tty. */
|
||||
Lisp_Object Vresume_tty_functions;
|
||||
|
||||
/* Chain of all displays currently in use. */
|
||||
struct display *display_list;
|
||||
|
||||
@ -231,10 +237,13 @@ tty_set_terminal_modes (struct display *display)
|
||||
{
|
||||
struct tty_display_info *tty = display->display_info.tty;
|
||||
|
||||
OUTPUT_IF (tty, tty->TS_termcap_modes);
|
||||
OUTPUT_IF (tty, tty->TS_cursor_visible);
|
||||
OUTPUT_IF (tty, tty->TS_keypad_mode);
|
||||
losecursor (tty);
|
||||
if (tty->output)
|
||||
{
|
||||
OUTPUT_IF (tty, tty->TS_termcap_modes);
|
||||
OUTPUT_IF (tty, tty->TS_cursor_visible);
|
||||
OUTPUT_IF (tty, tty->TS_keypad_mode);
|
||||
losecursor (tty);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset termcap modes before exiting Emacs. */
|
||||
@ -243,16 +252,19 @@ void
|
||||
tty_reset_terminal_modes (struct display *display)
|
||||
{
|
||||
struct tty_display_info *tty = display->display_info.tty;
|
||||
|
||||
turn_off_highlight (tty);
|
||||
turn_off_insert (tty);
|
||||
OUTPUT_IF (tty, tty->TS_end_keypad_mode);
|
||||
OUTPUT_IF (tty, tty->TS_cursor_normal);
|
||||
OUTPUT_IF (tty, tty->TS_end_termcap_modes);
|
||||
OUTPUT_IF (tty, tty->TS_orig_pair);
|
||||
/* Output raw CR so kernel can track the cursor hpos. */
|
||||
current_tty = tty;
|
||||
cmputc ('\r');
|
||||
|
||||
if (tty->output)
|
||||
{
|
||||
turn_off_highlight (tty);
|
||||
turn_off_insert (tty);
|
||||
OUTPUT_IF (tty, tty->TS_end_keypad_mode);
|
||||
OUTPUT_IF (tty, tty->TS_cursor_normal);
|
||||
OUTPUT_IF (tty, tty->TS_end_termcap_modes);
|
||||
OUTPUT_IF (tty, tty->TS_orig_pair);
|
||||
/* Output raw CR so kernel can track the cursor hpos. */
|
||||
current_tty = tty;
|
||||
cmputc ('\r');
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -619,9 +631,9 @@ tty_clear_end_of_line (int first_unused_hpos)
|
||||
|
||||
for (i = curX (tty); i < first_unused_hpos; i++)
|
||||
{
|
||||
if (TTY_TERMSCRIPT (tty))
|
||||
fputc (' ', TTY_TERMSCRIPT (tty));
|
||||
fputc (' ', TTY_OUTPUT (tty));
|
||||
if (tty->termscript)
|
||||
fputc (' ', tty->termscript);
|
||||
fputc (' ', tty->output);
|
||||
}
|
||||
cmplus (tty, first_unused_hpos - curX (tty));
|
||||
}
|
||||
@ -807,12 +819,12 @@ tty_write_glyphs (struct glyph *string, int len)
|
||||
if (produced > 0)
|
||||
{
|
||||
fwrite (conversion_buffer, 1, produced,
|
||||
TTY_OUTPUT (tty));
|
||||
if (ferror (TTY_OUTPUT (tty)))
|
||||
clearerr (TTY_OUTPUT (tty));
|
||||
if (TTY_TERMSCRIPT (tty))
|
||||
tty->output);
|
||||
if (ferror (tty->output))
|
||||
clearerr (tty->output);
|
||||
if (tty->termscript)
|
||||
fwrite (conversion_buffer, 1, produced,
|
||||
TTY_TERMSCRIPT (tty));
|
||||
tty->termscript);
|
||||
}
|
||||
len -= consumed;
|
||||
n -= consumed;
|
||||
@ -833,12 +845,12 @@ tty_write_glyphs (struct glyph *string, int len)
|
||||
if (terminal_coding.produced > 0)
|
||||
{
|
||||
fwrite (conversion_buffer, 1, terminal_coding.produced,
|
||||
TTY_OUTPUT (tty));
|
||||
if (ferror (TTY_OUTPUT (tty)))
|
||||
clearerr (TTY_OUTPUT (tty));
|
||||
if (TTY_TERMSCRIPT (tty))
|
||||
tty->output);
|
||||
if (ferror (tty->output))
|
||||
clearerr (tty->output);
|
||||
if (tty->termscript)
|
||||
fwrite (conversion_buffer, 1, terminal_coding.produced,
|
||||
TTY_TERMSCRIPT (tty));
|
||||
tty->termscript);
|
||||
}
|
||||
}
|
||||
|
||||
@ -927,12 +939,12 @@ tty_insert_glyphs (struct glyph *start, int len)
|
||||
if (produced > 0)
|
||||
{
|
||||
fwrite (conversion_buffer, 1, produced,
|
||||
TTY_OUTPUT (tty));
|
||||
if (ferror (TTY_OUTPUT (tty)))
|
||||
clearerr (TTY_OUTPUT (tty));
|
||||
if (TTY_TERMSCRIPT (tty))
|
||||
tty->output);
|
||||
if (ferror (tty->output))
|
||||
clearerr (tty->output);
|
||||
if (tty->termscript)
|
||||
fwrite (conversion_buffer, 1, produced,
|
||||
TTY_TERMSCRIPT (tty));
|
||||
tty->termscript);
|
||||
}
|
||||
|
||||
OUTPUT1_IF (tty, tty->TS_pad_inserted_char);
|
||||
@ -2240,7 +2252,11 @@ term_init (char *name, char *terminal_type, int must_succeed)
|
||||
|
||||
display = get_named_tty_display (name);
|
||||
if (display)
|
||||
return display; /* We have already opened a display there. */
|
||||
{
|
||||
if (! display->display_info.tty->input)
|
||||
error ("%s already has a suspended frame on it, can't open it twice", name);
|
||||
return display;
|
||||
}
|
||||
|
||||
display = create_display ();
|
||||
tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info));
|
||||
@ -2550,7 +2566,7 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
|
||||
/* Get frame size from system, or else from termcap. */
|
||||
{
|
||||
int height, width;
|
||||
get_tty_size (fileno (TTY_INPUT (tty)), &width, &height);
|
||||
get_tty_size (fileno (tty->input), &width, &height);
|
||||
FrameCols (tty) = width;
|
||||
FrameRows (tty) = height;
|
||||
}
|
||||
@ -2735,7 +2751,7 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
|
||||
&& tty->TS_end_standout_mode
|
||||
&& !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode));
|
||||
|
||||
UseTabs (tty) = tabs_safe_p (fileno (TTY_INPUT (tty))) && TabWidth (tty) == 8;
|
||||
UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8;
|
||||
|
||||
display->scroll_region_ok
|
||||
= (tty->Wcm->cm_abs
|
||||
@ -2754,7 +2770,7 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
|
||||
|
||||
display->fast_clear_end_of_line = tty->TS_clr_line != 0;
|
||||
|
||||
init_baud_rate (fileno (TTY_INPUT (tty)));
|
||||
init_baud_rate (fileno (tty->input));
|
||||
|
||||
#ifdef AIXHFT
|
||||
/* The HFT system on AIX doesn't optimize for scrolling, so it's
|
||||
@ -3067,6 +3083,134 @@ delete_display (struct display *dev)
|
||||
xfree (dev);
|
||||
}
|
||||
|
||||
|
||||
|
||||
DEFUN ("suspend-tty", Fsuspend_tty, Ssuspend_tty, 0, 1, 0,
|
||||
doc: /* Suspend the terminal device TTY.
|
||||
The terminal is restored to its default state, and Emacs closes all
|
||||
access to the terminal device. Frames that use the device are not
|
||||
deleted, but input is not read from them and if they change, their
|
||||
display is not updated.
|
||||
|
||||
TTY may a string (a device name), a frame, or nil for the display
|
||||
device of the currently selected frame.
|
||||
|
||||
This function runs `suspend-tty-functions' after suspending the
|
||||
device. The functions are run with one arg, the name of the terminal
|
||||
device.
|
||||
|
||||
`suspend-tty' does nothing if it is called on an already suspended
|
||||
device.
|
||||
|
||||
A suspended terminal device may be resumed by calling `resume-tty' on
|
||||
it. */)
|
||||
(tty)
|
||||
Lisp_Object tty;
|
||||
{
|
||||
struct display *d = get_tty_display (tty);
|
||||
FILE *f;
|
||||
|
||||
if (!d)
|
||||
error ("Unknown tty device");
|
||||
|
||||
f = d->display_info.tty->input;
|
||||
|
||||
if (f)
|
||||
{
|
||||
reset_sys_modes (d->display_info.tty);
|
||||
|
||||
delete_keyboard_wait_descriptor (fileno (f));
|
||||
|
||||
fclose (f);
|
||||
if (f != d->display_info.tty->output)
|
||||
fclose (d->display_info.tty->output);
|
||||
|
||||
d->display_info.tty->input = 0;
|
||||
d->display_info.tty->output = 0;
|
||||
|
||||
if (FRAMEP (d->display_info.tty->top_frame))
|
||||
FRAME_SET_VISIBLE (XFRAME (d->display_info.tty->top_frame), 0);
|
||||
|
||||
/* Run `suspend-tty-functions'. */
|
||||
if (!NILP (Vrun_hooks))
|
||||
{
|
||||
Lisp_Object args[2];
|
||||
args[0] = intern ("suspend-tty-functions");
|
||||
if (d->display_info.tty->name)
|
||||
{
|
||||
args[1] = build_string (d->display_info.tty->name);
|
||||
}
|
||||
else
|
||||
args[1] = Qnil;
|
||||
Frun_hook_with_args (2, args);
|
||||
}
|
||||
}
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
|
||||
DEFUN ("resume-tty", Fresume_tty, Sresume_tty, 0, 1, 0,
|
||||
doc: /* Resume the previously suspended terminal device TTY.
|
||||
The terminal is opened and reinitialized. Frames that used the
|
||||
suspended device are revived.
|
||||
|
||||
This function runs `resume-tty-functions' after resuming the device.
|
||||
The functions are run with one arg, the name of the terminal device.
|
||||
|
||||
`resume-tty' does nothing if it is called on a device that is not
|
||||
suspended.
|
||||
|
||||
TTY may a string (a device name), a frame, or nil for the display
|
||||
device of the currently selected frame. */)
|
||||
(tty)
|
||||
Lisp_Object tty;
|
||||
{
|
||||
struct display *d = get_tty_display (tty);
|
||||
int fd;
|
||||
|
||||
if (!d)
|
||||
error ("Unknown tty device");
|
||||
|
||||
if (!d->display_info.tty->input)
|
||||
{
|
||||
fd = emacs_open (d->display_info.tty->name, O_RDWR | O_NOCTTY, 0);
|
||||
|
||||
#ifdef TIOCNOTTY
|
||||
/* Drop our controlling tty if it is the same device. */
|
||||
if (ioctl (fd, TIOCNOTTY, 0) != -1)
|
||||
{
|
||||
no_controlling_tty = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
d->display_info.tty->output = fdopen (fd, "w+");
|
||||
d->display_info.tty->input = d->display_info.tty->output;
|
||||
|
||||
add_keyboard_wait_descriptor (fd);
|
||||
|
||||
if (FRAMEP (d->display_info.tty->top_frame))
|
||||
FRAME_SET_VISIBLE (XFRAME (d->display_info.tty->top_frame), 1);
|
||||
|
||||
init_sys_modes (d->display_info.tty);
|
||||
|
||||
/* Run `suspend-tty-functions'. */
|
||||
if (!NILP (Vrun_hooks))
|
||||
{
|
||||
Lisp_Object args[2];
|
||||
args[0] = intern ("resume-tty-functions");
|
||||
if (d->display_info.tty->name)
|
||||
{
|
||||
args[1] = build_string (d->display_info.tty->name);
|
||||
}
|
||||
else
|
||||
args[1] = Qnil;
|
||||
Frun_hook_with_args (2, args);
|
||||
}
|
||||
}
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
@ -3092,6 +3236,20 @@ The functions are run with one argument, the name of the tty to be deleted.
|
||||
See `delete-tty'. */);
|
||||
Vdelete_tty_after_functions = Qnil;
|
||||
|
||||
|
||||
DEFVAR_LISP ("suspend-tty-functions", &Vsuspend_tty_functions,
|
||||
doc: /* Functions to be run after suspending a tty.
|
||||
The functions are run with one argument, the name of the tty to be suspended.
|
||||
See `suspend-tty'. */);
|
||||
Vsuspend_tty_functions = Qnil;
|
||||
|
||||
|
||||
DEFVAR_LISP ("resume-tty-functions", &Vresume_tty_functions,
|
||||
doc: /* Functions to be run after resuming a tty.
|
||||
The functions are run with one argument, the name of the tty that was revived.
|
||||
See `resume-tty'. */);
|
||||
Vresume_tty_functions = Qnil;
|
||||
|
||||
Qframe_tty_name = intern ("frame-tty-name");
|
||||
staticpro (&Qframe_tty_name);
|
||||
|
||||
@ -3103,6 +3261,8 @@ See `delete-tty'. */);
|
||||
defsubr (&Sframe_tty_name);
|
||||
defsubr (&Sframe_tty_type);
|
||||
defsubr (&Sdelete_tty);
|
||||
defsubr (&Ssuspend_tty);
|
||||
defsubr (&Sresume_tty);
|
||||
|
||||
Fprovide (intern ("multi-tty"), Qnil);
|
||||
|
||||
|
@ -42,8 +42,10 @@ struct tty_display_info
|
||||
|
||||
/* Input/output */
|
||||
|
||||
FILE *input; /* The stream to be used for terminal input. */
|
||||
FILE *output; /* The stream to be used for terminal output. */
|
||||
FILE *input; /* The stream to be used for terminal input.
|
||||
NULL if the terminal is suspended. */
|
||||
FILE *output; /* The stream to be used for terminal output.
|
||||
NULL if the terminal is suspended. */
|
||||
|
||||
FILE *termscript; /* If nonzero, send all terminal output
|
||||
characters to this stream also. */
|
||||
@ -200,9 +202,5 @@ extern struct tty_display_info *tty_list;
|
||||
|
||||
#define CURTTY() FRAME_TTY (SELECTED_FRAME())
|
||||
|
||||
#define TTY_INPUT(t) ((t)->input)
|
||||
#define TTY_OUTPUT(t) ((t)->output)
|
||||
#define TTY_TERMSCRIPT(t) ((t)->termscript)
|
||||
|
||||
/* arch-tag: bf9f0d49-842b-42fb-9348-ec8759b27193
|
||||
(do not change this comment) */
|
||||
|
@ -513,7 +513,6 @@ struct display
|
||||
frames on the display when it calls this hook, so infinite
|
||||
recursion is prevented. */
|
||||
void (*delete_display_hook) P_ ((struct display *));
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user