diff options
| author | Karoly Lorentey | 2004-02-28 01:23:39 +0000 |
|---|---|---|
| committer | Karoly Lorentey | 2004-02-28 01:23:39 +0000 |
| commit | 0b0d3e0bcefdde298893aaad2e816e1503cef222 (patch) | |
| tree | 439342044857514ad784de0470f5546eb9c3ef9a | |
| parent | 2fc0cf2aefa777e5fe48596e2d43774b28051931 (diff) | |
| download | emacs-0b0d3e0bcefdde298893aaad2e816e1503cef222.tar.gz emacs-0b0d3e0bcefdde298893aaad2e816e1503cef222.zip | |
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
| -rw-r--r-- | README.multi-tty | 57 | ||||
| -rw-r--r-- | lib-src/emacsclient.c | 244 | ||||
| -rw-r--r-- | lisp/frame.el | 18 | ||||
| -rw-r--r-- | lisp/server.el | 296 | ||||
| -rw-r--r-- | lisp/term/x-win.el | 6 | ||||
| -rw-r--r-- | src/cm.c | 18 | ||||
| -rw-r--r-- | src/dispnew.c | 58 | ||||
| -rw-r--r-- | src/frame.c | 5 | ||||
| -rw-r--r-- | src/keyboard.c | 15 | ||||
| -rw-r--r-- | src/sysdep.c | 96 | ||||
| -rw-r--r-- | src/term.c | 234 | ||||
| -rw-r--r-- | src/termchar.h | 10 | ||||
| -rw-r--r-- | src/termhooks.h | 1 |
13 files changed, 741 insertions, 317 deletions
diff --git a/README.multi-tty b/README.multi-tty index 68cae7a2060..43dfdcbc91f 100644 --- a/README.multi-tty +++ b/README.multi-tty | |||
| @@ -200,22 +200,50 @@ THINGS TO DO | |||
| 200 | argument-handling is done in Lisp, so this should be quite easy to | 200 | argument-handling is done in Lisp, so this should be quite easy to |
| 201 | implement. | 201 | implement. |
| 202 | 202 | ||
| 203 | ** Very strange bug: visible-bell does not work on secondary | 203 | ** Make `struct display' accessible to Lisp programs. Accessor functions: |
| 204 | terminals. This might be something xterm (konsole) specific. | ||
| 205 | 204 | ||
| 206 | ** Find out the best way to support suspending Emacs with multiple | 205 | (displayp OBJECT): Returns t if OBJECT is a display. |
| 207 | ttys. My guess: disable it on the controlling tty, but from other | ||
| 208 | ttys pass it on to emacsclient somehow. (It is (I hope) trivial to | ||
| 209 | extend emacsclient to handle suspend/resume. A `kill -STOP' almost | ||
| 210 | works right now.) | ||
| 211 | 206 | ||
| 212 | ** Clean up the frame-local variable system. I think it's ugly and | 207 | (selected-display): Returns the display object of the selected frame. |
| 213 | error-prone. But maybe I just haven't yet fully understood it. | 208 | |
| 209 | (frame-display FRAME): Returns the display object of FRAME. | ||
| 210 | |||
| 211 | (display-frames DISPLAY): Returns a list of frames on DISPLAY. | ||
| 212 | |||
| 213 | (display-type DISPLAY): Returns the type of DISPLAY, as a | ||
| 214 | symbol. (See `framep'.) | ||
| 215 | |||
| 216 | (display-device DISPLAY): Returns the name of the device that | ||
| 217 | DISPLAY uses, as a string. (E.g: "/dev/pts/16", or | ||
| 218 | ":0.0") | ||
| 219 | |||
| 220 | See next issue why this is necessary. | ||
| 221 | |||
| 222 | ** The following needs to be supported: | ||
| 223 | |||
| 224 | $ emacsclient -t | ||
| 225 | C-z | ||
| 226 | $ bg | ||
| 227 | $ emacsclient -t | ||
| 228 | (This fails now.) | ||
| 229 | |||
| 230 | The cleanest way to solve this is to allow multiple displays on the | ||
| 231 | same terminal device; each new emacsclient process should create | ||
| 232 | its own display. As displays are currently identified by their | ||
| 233 | device names, this is not possible until struct display becomes | ||
| 234 | accessible as a Lisp-level object. | ||
| 214 | 235 | ||
| 215 | ** Add an elaborate mechanism for display-local variables. (There are | 236 | ** Add an elaborate mechanism for display-local variables. (There are |
| 216 | already a few of these; search for `terminal-local' in the Elisp | 237 | already a few of these; search for `terminal-local' in the Elisp |
| 217 | manual.) | 238 | manual.) |
| 218 | 239 | ||
| 240 | ** Very strange bug: visible-bell does not work on secondary | ||
| 241 | terminals in xterm and konsole. The screen does flicker a bit, | ||
| 242 | but it's so quick it isn't noticable. | ||
| 243 | |||
| 244 | ** Clean up the frame-local variable system. I think it's ugly and | ||
| 245 | error-prone. But maybe I just haven't yet fully understood it. | ||
| 246 | |||
| 219 | ** Move baud_rate to struct display. | 247 | ** Move baud_rate to struct display. |
| 220 | 248 | ||
| 221 | ** Implement support for starting an interactive Emacs session without | 249 | ** Implement support for starting an interactive Emacs session without |
| @@ -667,4 +695,15 @@ DIARY OF CHANGES | |||
| 667 | complaints seem to be caused by bugs in term.el; they are not | 695 | complaints seem to be caused by bugs in term.el; they are not |
| 668 | related to multi-tty.) | 696 | related to multi-tty.) |
| 669 | 697 | ||
| 698 | -- Find out the best way to support suspending Emacs with multiple | ||
| 699 | ttys. My guess: disable it on the controlling tty, but from other | ||
| 700 | ttys pass it on to emacsclient somehow. (It is (I hope) trivial to | ||
| 701 | extend emacsclient to handle suspend/resume. A `kill -STOP' almost | ||
| 702 | works right now.) | ||
| 703 | |||
| 704 | (Done. I needed to play with signal handling and the server | ||
| 705 | protocol a bit to make emacsclient behave as a normal UNIX program | ||
| 706 | wrt foreground/background process groups.) | ||
| 707 | |||
| 708 | |||
| 670 | ;;; arch-tag: 8da1619e-2e79-41a8-9ac9-a0485daad17d | 709 | ;;; arch-tag: 8da1619e-2e79-41a8-9ac9-a0485daad17d |
diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c index c1c8ee8f160..79642cbe47e 100644 --- a/lib-src/emacsclient.c +++ b/lib-src/emacsclient.c | |||
| @@ -114,7 +114,7 @@ decode_options (argc, argv) | |||
| 114 | display = getenv ("DISPLAY"); | 114 | display = getenv ("DISPLAY"); |
| 115 | if (display && strlen (display) == 0) | 115 | if (display && strlen (display) == 0) |
| 116 | display = NULL; | 116 | display = NULL; |
| 117 | 117 | ||
| 118 | if (display) | 118 | if (display) |
| 119 | window_system = 1; | 119 | window_system = 1; |
| 120 | else | 120 | else |
| @@ -169,7 +169,7 @@ decode_options (argc, argv) | |||
| 169 | window_system = 0; | 169 | window_system = 0; |
| 170 | tty = 0; | 170 | tty = 0; |
| 171 | break; | 171 | break; |
| 172 | 172 | ||
| 173 | case 'H': | 173 | case 'H': |
| 174 | print_help_and_exit (); | 174 | print_help_and_exit (); |
| 175 | break; | 175 | break; |
| @@ -212,19 +212,21 @@ Report bugs to bug-gnu-emacs@gnu.org.\n", progname); | |||
| 212 | exit (0); | 212 | exit (0); |
| 213 | } | 213 | } |
| 214 | 214 | ||
| 215 | /* In NAME, insert a & before each &, each space, each newline, and | 215 | /* In STR, insert a & before each &, each space, each newline, and |
| 216 | any initial -. Change spaces to underscores, too, so that the | 216 | any initial -. Change spaces to underscores, too, so that the |
| 217 | return value never contains a space. */ | 217 | return value never contains a space. |
| 218 | |||
| 219 | Does not change the string. Outputs the result to STREAM. */ | ||
| 218 | 220 | ||
| 219 | void | 221 | void |
| 220 | quote_file_name (name, stream) | 222 | quote_argument (str, stream) |
| 221 | char *name; | 223 | char *str; |
| 222 | FILE *stream; | 224 | FILE *stream; |
| 223 | { | 225 | { |
| 224 | char *copy = (char *) malloc (strlen (name) * 2 + 1); | 226 | char *copy = (char *) malloc (strlen (str) * 2 + 1); |
| 225 | char *p, *q; | 227 | char *p, *q; |
| 226 | 228 | ||
| 227 | p = name; | 229 | p = str; |
| 228 | q = copy; | 230 | q = copy; |
| 229 | while (*p) | 231 | while (*p) |
| 230 | { | 232 | { |
| @@ -242,7 +244,7 @@ quote_file_name (name, stream) | |||
| 242 | } | 244 | } |
| 243 | else | 245 | else |
| 244 | { | 246 | { |
| 245 | if (*p == '&' || (*p == '-' && p == name)) | 247 | if (*p == '&' || (*p == '-' && p == str)) |
| 246 | *q++ = '&'; | 248 | *q++ = '&'; |
| 247 | *q++ = *p++; | 249 | *q++ = *p++; |
| 248 | } | 250 | } |
| @@ -254,6 +256,41 @@ quote_file_name (name, stream) | |||
| 254 | free (copy); | 256 | free (copy); |
| 255 | } | 257 | } |
| 256 | 258 | ||
| 259 | |||
| 260 | /* The inverse of quote_argument. Removes quoting in string STR by | ||
| 261 | modifying the string in place. Returns STR. */ | ||
| 262 | |||
| 263 | char * | ||
| 264 | unquote_argument (str) | ||
| 265 | char *str; | ||
| 266 | { | ||
| 267 | char *p, *q; | ||
| 268 | |||
| 269 | if (! str) | ||
| 270 | return str; | ||
| 271 | |||
| 272 | p = str; | ||
| 273 | q = str; | ||
| 274 | while (*p) | ||
| 275 | { | ||
| 276 | if (*p == '&') | ||
| 277 | { | ||
| 278 | p++; | ||
| 279 | if (*p == '&') | ||
| 280 | *p = '&'; | ||
| 281 | else if (*p == '_') | ||
| 282 | *p = ' '; | ||
| 283 | else if (*p == 'n') | ||
| 284 | *p = '\n'; | ||
| 285 | else if (*p == '-') | ||
| 286 | *p = '-'; | ||
| 287 | } | ||
| 288 | *q++ = *p++; | ||
| 289 | } | ||
| 290 | *q = 0; | ||
| 291 | return str; | ||
| 292 | } | ||
| 293 | |||
| 257 | /* Like malloc but get fatal error if memory is exhausted. */ | 294 | /* Like malloc but get fatal error if memory is exhausted. */ |
| 258 | 295 | ||
| 259 | long * | 296 | long * |
| @@ -288,8 +325,12 @@ fail (void) | |||
| 288 | } | 325 | } |
| 289 | } | 326 | } |
| 290 | 327 | ||
| 328 | /* The process id of Emacs. */ | ||
| 291 | int emacs_pid; | 329 | int emacs_pid; |
| 292 | 330 | ||
| 331 | /* File handles for communicating with Emacs. */ | ||
| 332 | FILE *out, *in; | ||
| 333 | |||
| 293 | /* A signal handler that passes the signal to the Emacs process. | 334 | /* A signal handler that passes the signal to the Emacs process. |
| 294 | Useful for SIGWINCH. */ | 335 | Useful for SIGWINCH. */ |
| 295 | 336 | ||
| @@ -305,8 +346,62 @@ pass_signal_to_emacs (int signalnum) | |||
| 305 | errno = old_errno; | 346 | errno = old_errno; |
| 306 | } | 347 | } |
| 307 | 348 | ||
| 349 | /* Signal handler for SIGCONT; notify the Emacs process that it can | ||
| 350 | now resume our tty frame. */ | ||
| 351 | |||
| 352 | SIGTYPE | ||
| 353 | handle_sigcont (int signalnum) | ||
| 354 | { | ||
| 355 | int old_errno = errno; | ||
| 356 | |||
| 357 | if (tcgetpgrp (1) == getpgrp ()) | ||
| 358 | { | ||
| 359 | /* We are in the foreground. */ | ||
| 360 | fprintf (out, "-resume \n"); | ||
| 361 | fflush (out); | ||
| 362 | fsync (fileno (out)); | ||
| 363 | } | ||
| 364 | else | ||
| 365 | { | ||
| 366 | /* We are in the background; cancel the continue. */ | ||
| 367 | kill (getpid (), SIGSTOP); | ||
| 368 | } | ||
| 369 | errno = old_errno; | ||
| 370 | } | ||
| 371 | |||
| 372 | /* Signal handler for SIGTSTP; notify the Emacs process that we are | ||
| 373 | going to sleep. Normally the suspend is initiated by Emacs via | ||
| 374 | server-handle-suspend-tty, but if the server gets out of sync with | ||
| 375 | reality, we may get a SIGTSTP on C-z. Handling this signal and | ||
| 376 | notifying Emacs about it should get things under control again. */ | ||
| 377 | |||
| 378 | SIGTYPE | ||
| 379 | handle_sigtstp (int signalnum) | ||
| 380 | { | ||
| 381 | int old_errno = errno; | ||
| 382 | sigset_t set; | ||
| 383 | |||
| 384 | if (out) | ||
| 385 | { | ||
| 386 | fprintf (out, "-suspend \n"); | ||
| 387 | fflush (out); | ||
| 388 | fsync (fileno (out)); | ||
| 389 | } | ||
| 390 | |||
| 391 | /* Unblock this signal and call the default handler by temprarily | ||
| 392 | changing the handler and resignalling. */ | ||
| 393 | sigprocmask (SIG_BLOCK, NULL, &set); | ||
| 394 | sigdelset (&set, signalnum); | ||
| 395 | signal (signalnum, SIG_DFL); | ||
| 396 | kill (getpid (), signalnum); | ||
| 397 | sigprocmask (SIG_SETMASK, &set, NULL); /* Let's the above signal through. */ | ||
| 398 | signal (signalnum, handle_sigtstp); | ||
| 399 | |||
| 400 | errno = old_errno; | ||
| 401 | } | ||
| 402 | |||
| 308 | /* Set up signal handlers before opening a frame on the current tty. */ | 403 | /* Set up signal handlers before opening a frame on the current tty. */ |
| 309 | 404 | ||
| 310 | void | 405 | void |
| 311 | init_signals (void) | 406 | init_signals (void) |
| 312 | { | 407 | { |
| @@ -320,6 +415,10 @@ init_signals (void) | |||
| 320 | signal (SIGINT, pass_signal_to_emacs); | 415 | signal (SIGINT, pass_signal_to_emacs); |
| 321 | signal (SIGQUIT, pass_signal_to_emacs); | 416 | signal (SIGQUIT, pass_signal_to_emacs); |
| 322 | #endif | 417 | #endif |
| 418 | |||
| 419 | signal (SIGCONT, handle_sigcont); | ||
| 420 | signal (SIGTSTP, handle_sigtstp); | ||
| 421 | signal (SIGTTOU, handle_sigtstp); | ||
| 323 | } | 422 | } |
| 324 | 423 | ||
| 325 | 424 | ||
| @@ -378,7 +477,7 @@ strprefix (char *prefix, char *string) | |||
| 378 | 477 | ||
| 379 | if (!string) | 478 | if (!string) |
| 380 | return 0; | 479 | return 0; |
| 381 | 480 | ||
| 382 | for (i = 0; prefix[i]; i++) | 481 | for (i = 0; prefix[i]; i++) |
| 383 | if (!string[i] || string[i] != prefix[i]) | 482 | if (!string[i] || string[i] != prefix[i]) |
| 384 | return 0; | 483 | return 0; |
| @@ -391,7 +490,6 @@ main (argc, argv) | |||
| 391 | char **argv; | 490 | char **argv; |
| 392 | { | 491 | { |
| 393 | int s, i, needlf = 0; | 492 | int s, i, needlf = 0; |
| 394 | FILE *out, *in; | ||
| 395 | struct sockaddr_un server; | 493 | struct sockaddr_un server; |
| 396 | char *cwd, *str; | 494 | char *cwd, *str; |
| 397 | char string[BUFSIZ]; | 495 | char string[BUFSIZ]; |
| @@ -427,9 +525,9 @@ main (argc, argv) | |||
| 427 | int sock_status = 0; | 525 | int sock_status = 0; |
| 428 | int default_sock = !socket_name; | 526 | int default_sock = !socket_name; |
| 429 | int saved_errno = 0; | 527 | int saved_errno = 0; |
| 430 | 528 | ||
| 431 | char *server_name = "server"; | 529 | char *server_name = "server"; |
| 432 | 530 | ||
| 433 | if (socket_name && !index (socket_name, '/') && !index (socket_name, '\\')) | 531 | if (socket_name && !index (socket_name, '/') && !index (socket_name, '\\')) |
| 434 | { /* socket_name is a file name component. */ | 532 | { /* socket_name is a file name component. */ |
| 435 | server_name = socket_name; | 533 | server_name = socket_name; |
| @@ -571,17 +669,14 @@ To start the server in Emacs, type \"M-x server-start\".\n", | |||
| 571 | 669 | ||
| 572 | /* First of all, send our version number for verification. */ | 670 | /* First of all, send our version number for verification. */ |
| 573 | fprintf (out, "-version %s ", VERSION); | 671 | fprintf (out, "-version %s ", VERSION); |
| 574 | 672 | ||
| 575 | if (nowait) | 673 | if (nowait) |
| 576 | fprintf (out, "-nowait "); | 674 | fprintf (out, "-nowait "); |
| 577 | 675 | ||
| 578 | if (eval) | ||
| 579 | fprintf (out, "-eval "); | ||
| 580 | |||
| 581 | if (display) | 676 | if (display) |
| 582 | { | 677 | { |
| 583 | fprintf (out, "-display "); | 678 | fprintf (out, "-display "); |
| 584 | quote_file_name (display, out); | 679 | quote_argument (display, out); |
| 585 | fprintf (out, " "); | 680 | fprintf (out, " "); |
| 586 | } | 681 | } |
| 587 | 682 | ||
| @@ -589,7 +684,7 @@ To start the server in Emacs, type \"M-x server-start\".\n", | |||
| 589 | { | 684 | { |
| 590 | char *tty_name = ttyname (fileno (stdin)); | 685 | char *tty_name = ttyname (fileno (stdin)); |
| 591 | char *type = getenv ("TERM"); | 686 | char *type = getenv ("TERM"); |
| 592 | 687 | ||
| 593 | if (! tty_name) | 688 | if (! tty_name) |
| 594 | { | 689 | { |
| 595 | fprintf (stderr, "%s: could not get terminal name\n", progname); | 690 | 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", | |||
| 610 | " is not supported\n", progname); | 705 | " is not supported\n", progname); |
| 611 | fail (); | 706 | fail (); |
| 612 | } | 707 | } |
| 613 | 708 | ||
| 614 | init_signals (); | 709 | init_signals (); |
| 615 | 710 | ||
| 616 | fprintf (out, "-tty "); | 711 | fprintf (out, "-tty "); |
| 617 | quote_file_name (tty_name, out); | 712 | quote_argument (tty_name, out); |
| 618 | fprintf (out, " "); | 713 | fprintf (out, " "); |
| 619 | quote_file_name (type, out); | 714 | quote_argument (type, out); |
| 620 | fprintf (out, " "); | 715 | fprintf (out, " "); |
| 621 | } | 716 | } |
| 622 | 717 | ||
| 623 | if (window_system) | 718 | if (window_system) |
| 624 | fprintf (out, "-window-system "); | 719 | fprintf (out, "-window-system "); |
| 625 | 720 | ||
| 626 | if ((argc - optind > 0)) | 721 | if ((argc - optind > 0)) |
| 627 | { | 722 | { |
| 628 | for (i = optind; i < argc; i++) | 723 | for (i = optind; i < argc; i++) |
| 629 | { | 724 | { |
| 725 | int relative = 0; | ||
| 726 | |||
| 630 | if (eval) | 727 | if (eval) |
| 631 | ; /* Don't prepend any cwd or anything like that. */ | 728 | { |
| 632 | else if (*argv[i] == '+') | 729 | /* Don't prepend any cwd or anything like that. */ |
| 633 | { | 730 | fprintf (out, "-eval "); |
| 731 | quote_argument (argv[i], out); | ||
| 732 | fprintf (out, " "); | ||
| 733 | continue; | ||
| 734 | } | ||
| 735 | |||
| 736 | if (*argv[i] == '+') | ||
| 737 | { | ||
| 634 | char *p = argv[i] + 1; | 738 | char *p = argv[i] + 1; |
| 635 | while (isdigit ((unsigned char) *p) || *p == ':') p++; | 739 | while (isdigit ((unsigned char) *p) || *p == ':') p++; |
| 636 | if (*p != 0) | 740 | if (*p == 0) |
| 637 | { | 741 | { |
| 638 | quote_file_name (cwd, out); | 742 | fprintf (out, "-position "); |
| 639 | fprintf (out, "/"); | 743 | quote_argument (argv[i], out); |
| 640 | } | 744 | fprintf (out, " "); |
| 641 | } | 745 | continue; |
| 642 | else if (*argv[i] != '/') | 746 | } |
| 643 | { | 747 | else |
| 644 | quote_file_name (cwd, out); | 748 | relative = 1; |
| 645 | fprintf (out, "/"); | 749 | } |
| 646 | } | 750 | else if (*argv[i] != '/') |
| 647 | 751 | relative = 1; | |
| 648 | quote_file_name (argv[i], out); | 752 | |
| 649 | fprintf (out, " "); | 753 | fprintf (out, "-file "); |
| 650 | } | 754 | if (relative) |
| 755 | { | ||
| 756 | quote_argument (cwd, out); | ||
| 757 | fprintf (out, "/"); | ||
| 758 | } | ||
| 759 | quote_argument (argv[i], out); | ||
| 760 | fprintf (out, " "); | ||
| 761 | } | ||
| 651 | } | 762 | } |
| 652 | else | 763 | else |
| 653 | { | 764 | { |
| @@ -655,14 +766,19 @@ To start the server in Emacs, type \"M-x server-start\".\n", | |||
| 655 | { | 766 | { |
| 656 | while ((str = fgets (string, BUFSIZ, stdin))) | 767 | while ((str = fgets (string, BUFSIZ, stdin))) |
| 657 | { | 768 | { |
| 658 | quote_file_name (str, out); | 769 | if (eval) |
| 770 | fprintf (out, "-eval "); | ||
| 771 | else | ||
| 772 | fprintf (out, "-file "); | ||
| 773 | quote_argument (str, out); | ||
| 659 | } | 774 | } |
| 660 | fprintf (out, " "); | 775 | fprintf (out, " "); |
| 661 | } | 776 | } |
| 662 | } | 777 | } |
| 663 | 778 | ||
| 664 | fprintf (out, "\n"); | 779 | fprintf (out, "\n"); |
| 665 | fflush (out); | 780 | fflush (out); |
| 781 | fsync (fileno (out)); | ||
| 666 | 782 | ||
| 667 | /* Maybe wait for an answer. */ | 783 | /* Maybe wait for an answer. */ |
| 668 | if (nowait) | 784 | if (nowait) |
| @@ -676,44 +792,49 @@ To start the server in Emacs, type \"M-x server-start\".\n", | |||
| 676 | needlf = 2; | 792 | needlf = 2; |
| 677 | } | 793 | } |
| 678 | fflush (stdout); | 794 | fflush (stdout); |
| 795 | fsync (1); | ||
| 679 | 796 | ||
| 680 | /* Now, wait for an answer and print any messages. */ | 797 | /* Now, wait for an answer and print any messages. */ |
| 681 | while ((str = fgets (string, BUFSIZ, in))) | 798 | while ((str = fgets (string, BUFSIZ, in))) |
| 682 | { | 799 | { |
| 800 | char *p = str + strlen (str) - 1; | ||
| 801 | while (p > str && *p == '\n') | ||
| 802 | *p-- = 0; | ||
| 803 | |||
| 683 | if (strprefix ("-good-version ", str)) | 804 | if (strprefix ("-good-version ", str)) |
| 684 | { | 805 | { |
| 685 | /* OK, we got the green light. */ | 806 | /* OK, we got the green light. */ |
| 686 | } | 807 | } |
| 687 | else if (strprefix ("-bad-version ", str)) | ||
| 688 | { | ||
| 689 | if (str[strlen (str) - 1] == '\n') | ||
| 690 | str[strlen (str) - 1] = 0; | ||
| 691 | |||
| 692 | fprintf (stderr, "%s: Version mismatch: Emacs is %s, but we are %s\n", | ||
| 693 | argv[0], str + strlen ("-bad-version "), VERSION); | ||
| 694 | fail (); | ||
| 695 | } | ||
| 696 | else if (strprefix ("-emacs-pid ", str)) | 808 | else if (strprefix ("-emacs-pid ", str)) |
| 697 | { | 809 | { |
| 698 | emacs_pid = strtol (string + strlen ("-emacs-pid"), NULL, 10); | 810 | emacs_pid = strtol (string + strlen ("-emacs-pid"), NULL, 10); |
| 699 | } | 811 | } |
| 700 | else if (strprefix ("-print ", str)) | 812 | else if (strprefix ("-print ", str)) |
| 701 | { | 813 | { |
| 702 | if (needlf == 2) | 814 | str = unquote_argument (str + strlen ("-print ")); |
| 815 | if (needlf) | ||
| 703 | printf ("\n"); | 816 | printf ("\n"); |
| 704 | printf ("%s", str + strlen ("-print ")); | 817 | printf ("%s", str); |
| 705 | needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n'; | 818 | needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n'; |
| 706 | } | 819 | } |
| 707 | else if (strprefix ("-error ", str)) | 820 | else if (strprefix ("-error ", str)) |
| 708 | { | 821 | { |
| 709 | if (needlf == 2) | 822 | str = unquote_argument (str + strlen ("-error ")); |
| 823 | if (needlf) | ||
| 824 | printf ("\n"); | ||
| 825 | printf ("*ERROR*: %s", str); | ||
| 826 | needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n'; | ||
| 827 | } | ||
| 828 | else if (strprefix ("-suspend ", str)) | ||
| 829 | { | ||
| 830 | if (needlf) | ||
| 710 | printf ("\n"); | 831 | printf ("\n"); |
| 711 | printf ("*ERROR*: %s", str + strlen ("-print ")); | 832 | needlf = 0; |
| 712 | needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n'; | 833 | kill (0, SIGSTOP); |
| 713 | } | 834 | } |
| 714 | else | 835 | else |
| 715 | { | 836 | { |
| 716 | if (needlf == 2) | 837 | if (needlf) |
| 717 | printf ("\n"); | 838 | printf ("\n"); |
| 718 | printf ("*ERROR*: Unknown message: %s", str); | 839 | printf ("*ERROR*: Unknown message: %s", str); |
| 719 | needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n'; | 840 | 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", | |||
| 723 | if (needlf) | 844 | if (needlf) |
| 724 | printf ("\n"); | 845 | printf ("\n"); |
| 725 | fflush (stdout); | 846 | fflush (stdout); |
| 847 | fsync (1); | ||
| 726 | 848 | ||
| 727 | return 0; | 849 | return 0; |
| 728 | } | 850 | } |
diff --git a/lisp/frame.el b/lisp/frame.el index 8d76c7b70ba..54bccd93970 100644 --- a/lisp/frame.el +++ b/lisp/frame.el | |||
| @@ -750,6 +750,22 @@ Otherwise, that variable should be nil." | |||
| 750 | (iconify-frame) | 750 | (iconify-frame) |
| 751 | (make-frame-visible))) | 751 | (make-frame-visible))) |
| 752 | 752 | ||
| 753 | (defun suspend-frame () | ||
| 754 | "Do whatever is right to suspend the current frame. | ||
| 755 | Calls `suspend-emacs' if invoked from the controlling terminal, | ||
| 756 | `suspend-tty' from a secondary terminal, and | ||
| 757 | `iconify-or-deiconify-frame' from an X frame." | ||
| 758 | (interactive) | ||
| 759 | (let ((type (framep (selected-frame)))) | ||
| 760 | (cond | ||
| 761 | ((eq type 'x) (iconify-or-deiconify-frame)) | ||
| 762 | ((eq type t) | ||
| 763 | (if (frame-tty-name) | ||
| 764 | (suspend-tty) | ||
| 765 | (suspend-emacs))) | ||
| 766 | (t (suspend-emacs))))) | ||
| 767 | |||
| 768 | |||
| 753 | (defun make-frame-names-alist () | 769 | (defun make-frame-names-alist () |
| 754 | (let* ((current-frame (selected-frame)) | 770 | (let* ((current-frame (selected-frame)) |
| 755 | (falist | 771 | (falist |
| @@ -1374,6 +1390,8 @@ Use Custom to set this variable to get the display updated." | |||
| 1374 | (define-key ctl-x-5-map "0" 'delete-frame) | 1390 | (define-key ctl-x-5-map "0" 'delete-frame) |
| 1375 | (define-key ctl-x-5-map "o" 'other-frame) | 1391 | (define-key ctl-x-5-map "o" 'other-frame) |
| 1376 | 1392 | ||
| 1393 | (substitute-key-definition 'suspend-emacs 'suspend-frame global-map) | ||
| 1394 | |||
| 1377 | (provide 'frame) | 1395 | (provide 'frame) |
| 1378 | 1396 | ||
| 1379 | ;;; arch-tag: 82979c70-b8f2-4306-b2ad-ddbd6b328b56 | 1397 | ;;; arch-tag: 82979c70-b8f2-4306-b2ad-ddbd6b328b56 |
diff --git a/lisp/server.el b/lisp/server.el index a1619471e56..aac3da13e4f 100644 --- a/lisp/server.el +++ b/lisp/server.el | |||
| @@ -186,7 +186,7 @@ are done with it in the server.") | |||
| 186 | (with-current-buffer "*server*" | 186 | (with-current-buffer "*server*" |
| 187 | (goto-char (point-max)) | 187 | (goto-char (point-max)) |
| 188 | (insert (current-time-string) | 188 | (insert (current-time-string) |
| 189 | (if client (format " %s:" client) " ") | 189 | (if client (format " %s: " client) " ") |
| 190 | string) | 190 | string) |
| 191 | (or (bolp) (newline))))) | 191 | (or (bolp) (newline))))) |
| 192 | 192 | ||
| @@ -227,6 +227,7 @@ are done with it in the server.") | |||
| 227 | (term (nth 1 entry))) | 227 | (term (nth 1 entry))) |
| 228 | (when (equal term tty) | 228 | (when (equal term tty) |
| 229 | (let ((client (assq proc server-clients))) | 229 | (let ((client (assq proc server-clients))) |
| 230 | (server-log (format "server-handle-delete-tty, tty %s" tty) (car client)) | ||
| 230 | (setq server-ttys (delq entry server-ttys)) | 231 | (setq server-ttys (delq entry server-ttys)) |
| 231 | (delete-process (car client)) | 232 | (delete-process (car client)) |
| 232 | (when (assq proc server-clients) | 233 | (when (assq proc server-clients) |
| @@ -234,6 +235,16 @@ are done with it in the server.") | |||
| 234 | ;; `emacsclient -t -e '(delete-frame)'' correctly. | 235 | ;; `emacsclient -t -e '(delete-frame)'' correctly. |
| 235 | (setq server-clients (delq client server-clients)))))))) | 236 | (setq server-clients (delq client server-clients)))))))) |
| 236 | 237 | ||
| 238 | (defun server-handle-suspend-tty (tty) | ||
| 239 | "Notify the emacsclient process to suspend itself when its tty device is suspended." | ||
| 240 | (dolist (entry server-ttys) | ||
| 241 | (let ((proc (nth 0 entry)) | ||
| 242 | (term (nth 1 entry))) | ||
| 243 | (when (equal term tty) | ||
| 244 | (let ((process (car (assq proc server-clients)))) | ||
| 245 | (server-log (format "server-handle-suspend-tty, tty %s" tty) process) | ||
| 246 | (process-send-string process "-suspend \n")))))) | ||
| 247 | |||
| 237 | (defun server-handle-delete-frame (frame) | 248 | (defun server-handle-delete-frame (frame) |
| 238 | "Delete the client connection when the emacsclient frame is deleted." | 249 | "Delete the client connection when the emacsclient frame is deleted." |
| 239 | (dolist (entry server-frames) | 250 | (dolist (entry server-frames) |
| @@ -241,6 +252,7 @@ are done with it in the server.") | |||
| 241 | (f (nth 1 entry))) | 252 | (f (nth 1 entry))) |
| 242 | (when (equal frame f) | 253 | (when (equal frame f) |
| 243 | (let ((client (assq proc server-clients))) | 254 | (let ((client (assq proc server-clients))) |
| 255 | (server-log (format "server-handle-delete-frame, frame %s" frame) (car client)) | ||
| 244 | (setq server-frames (delq entry server-frames)) | 256 | (setq server-frames (delq entry server-frames)) |
| 245 | (delete-process (car client)) | 257 | (delete-process (car client)) |
| 246 | (when (assq proc server-clients) | 258 | (when (assq proc server-clients) |
| @@ -278,6 +290,19 @@ are done with it in the server.") | |||
| 278 | (t " "))) | 290 | (t " "))) |
| 279 | arg t t)) | 291 | arg t t)) |
| 280 | 292 | ||
| 293 | (defun server-quote-arg (arg) | ||
| 294 | "In NAME, insert a & before each &, each space, each newline, and -. | ||
| 295 | Change spaces to underscores, too, so that the return value never | ||
| 296 | contains a space." | ||
| 297 | (replace-regexp-in-string | ||
| 298 | "[-&\n ]" (lambda (s) | ||
| 299 | (case (aref s 0) | ||
| 300 | (?& "&&") | ||
| 301 | (?- "&-") | ||
| 302 | (?\n "&n") | ||
| 303 | (?\s "&_"))) | ||
| 304 | arg t t)) | ||
| 305 | |||
| 281 | (defun server-ensure-safe-dir (dir) | 306 | (defun server-ensure-safe-dir (dir) |
| 282 | "Make sure DIR is a directory with no race-condition issues. | 307 | "Make sure DIR is a directory with no race-condition issues. |
| 283 | Creates the directory if necessary and makes sure: | 308 | Creates the directory if necessary and makes sure: |
| @@ -325,6 +350,7 @@ Prefix arg means just kill any existing server communications subprocess." | |||
| 325 | (server-log (message "Restarting server"))) | 350 | (server-log (message "Restarting server"))) |
| 326 | (letf (((default-file-modes) ?\700)) | 351 | (letf (((default-file-modes) ?\700)) |
| 327 | (add-to-list 'delete-tty-after-functions 'server-handle-delete-tty) | 352 | (add-to-list 'delete-tty-after-functions 'server-handle-delete-tty) |
| 353 | (add-to-list 'suspend-tty-functions 'server-handle-suspend-tty) | ||
| 328 | (add-to-list 'delete-frame-functions 'server-handle-delete-frame) | 354 | (add-to-list 'delete-frame-functions 'server-handle-delete-frame) |
| 329 | (setq server-process | 355 | (setq server-process |
| 330 | (make-network-process | 356 | (make-network-process |
| @@ -358,140 +384,182 @@ PROC is the server process. Format of STRING is \"PATH PATH PATH... \\n\"." | |||
| 358 | (setq string (concat prev string)) | 384 | (setq string (concat prev string)) |
| 359 | (process-put proc 'previous-string nil))) | 385 | (process-put proc 'previous-string nil))) |
| 360 | (condition-case err | 386 | (condition-case err |
| 361 | ;; If the input is multiple lines, | 387 | (progn |
| 362 | ;; process each line individually. | 388 | ;; If the input is multiple lines, |
| 363 | (while (string-match "\n" string) | 389 | ;; process each line individually. |
| 364 | (let ((request (substring string 0 (match-beginning 0))) | 390 | (while (string-match "\n" string) |
| 365 | (coding-system (and default-enable-multibyte-characters | 391 | (let ((request (substring string 0 (match-beginning 0))) |
| 366 | (or file-name-coding-system | 392 | (coding-system (and default-enable-multibyte-characters |
| 367 | default-file-name-coding-system))) | 393 | (or file-name-coding-system |
| 368 | client nowait eval newframe display version-checked | 394 | default-file-name-coding-system))) |
| 369 | registered ; t if the client is already added to server-clients. | 395 | client nowait newframe display version-checked |
| 370 | (files nil) | 396 | dontkill ; t if the client should not be killed. |
| 371 | (lineno 1) | 397 | registered ; t if the client is already added to server-clients. |
| 372 | (columnno 0)) | 398 | (files nil) |
| 373 | ;; Remove this line from STRING. | 399 | (lineno 1) |
| 374 | (setq string (substring string (match-end 0))) | 400 | (columnno 0)) |
| 375 | (setq client (cons proc nil)) | 401 | ;; Remove this line from STRING. |
| 376 | (while (string-match "[^ ]* " request) | 402 | (setq string (substring string (match-end 0))) |
| 377 | (let ((arg (substring request (match-beginning 0) (1- (match-end 0))))) | 403 | (setq client (cons proc nil)) |
| 378 | (setq request (substring request (match-end 0))) | 404 | (while (string-match "[^ ]* " request) |
| 379 | (cond | 405 | (let ((arg (substring request (match-beginning 0) (1- (match-end 0))))) |
| 380 | ;; Check version numbers. | 406 | (setq request (substring request (match-end 0))) |
| 381 | ((and (equal "-version" arg) (string-match "\\([0-9.]+\\) " request)) | 407 | (cond |
| 382 | (let* ((client-version (match-string 1 request)) | 408 | ;; Check version numbers. |
| 383 | (truncated-emacs-version (substring emacs-version 0 (length client-version)))) | 409 | ((and (equal "-version" arg) (string-match "\\([0-9.]+\\) " request)) |
| 384 | (setq request (substring request (match-end 0))) | 410 | (let* ((client-version (match-string 1 request)) |
| 385 | (if (equal client-version truncated-emacs-version) | 411 | (truncated-emacs-version (substring emacs-version 0 (length client-version)))) |
| 386 | (progn | 412 | (setq request (substring request (match-end 0))) |
| 387 | (process-send-string proc "-good-version \n") | 413 | (if (equal client-version truncated-emacs-version) |
| 388 | (setq version-checked t)) | 414 | (progn |
| 389 | (error (concat "Version mismatch: Emacs is " truncated-emacs-version ", emacsclient is " client-version))))) | 415 | (process-send-string proc "-good-version \n") |
| 390 | 416 | (setq version-checked t)) | |
| 391 | ((equal "-nowait" arg) (setq nowait t)) | 417 | (error (concat "Version mismatch: Emacs is " truncated-emacs-version ", emacsclient is " client-version))))) |
| 392 | ((equal "-eval" arg) (setq eval t)) | 418 | |
| 393 | 419 | ((equal "-nowait" arg) (setq nowait t)) | |
| 394 | ((and (equal "-display" arg) (string-match "\\([^ ]*\\) " request)) | 420 | |
| 395 | (setq display (match-string 1 request) | 421 | ((and (equal "-display" arg) (string-match "\\([^ ]*\\) " request)) |
| 396 | request (substring request (match-end 0)))) | 422 | (setq display (match-string 1 request) |
| 397 | 423 | request (substring request (match-end 0)))) | |
| 398 | ;; Open a new X frame. | 424 | |
| 399 | ((equal "-window-system" arg) | 425 | ;; Open a new X frame. |
| 400 | (unless version-checked | 426 | ((equal "-window-system" arg) |
| 401 | (error "Protocol error; make sure to use the correct version of emacsclient")) | ||
| 402 | (let ((frame (make-frame-on-display | ||
| 403 | (or display | ||
| 404 | (frame-parameter nil 'display) | ||
| 405 | (getenv "DISPLAY") | ||
| 406 | (error "Please specify display"))))) | ||
| 407 | (push (list proc frame) server-frames) | ||
| 408 | (select-frame frame) | ||
| 409 | ;; This makes sure that `emacsclient -w -e '(delete-frame)'' works right. | ||
| 410 | (push client server-clients) | ||
| 411 | (setq registered t | ||
| 412 | newframe t))) | ||
| 413 | |||
| 414 | ;; Open a new tty frame at the client. ARG is the name of the pseudo tty. | ||
| 415 | ((and (equal "-tty" arg) (string-match "\\([^ ]*\\) \\([^ ]*\\) " request)) | ||
| 416 | (let ((tty (server-unquote-arg (match-string 1 request))) | ||
| 417 | (type (server-unquote-arg (match-string 2 request)))) | ||
| 418 | (setq request (substring request (match-end 0))) | ||
| 419 | (unless version-checked | 427 | (unless version-checked |
| 420 | (error "Protocol error; make sure to use the correct version of emacsclient")) | 428 | (error "Protocol error; make sure to use the correct version of emacsclient")) |
| 421 | (let ((frame (make-frame-on-tty tty type))) | 429 | (let ((frame (make-frame-on-display |
| 422 | (push (list (car client) (frame-tty-name frame)) server-ttys) | 430 | (or display |
| 423 | (process-send-string proc (concat "-emacs-pid " (number-to-string (emacs-pid)) "\n")) | 431 | (frame-parameter nil 'display) |
| 432 | (getenv "DISPLAY") | ||
| 433 | (error "Please specify display"))))) | ||
| 434 | (push (list proc frame) server-frames) | ||
| 424 | (select-frame frame) | 435 | (select-frame frame) |
| 425 | ;; This makes sure that `emacsclient -t -e '(delete-frame)'' works right. | 436 | ;; This makes sure that `emacsclient -w -e '(delete-frame)'' works right. |
| 426 | (push client server-clients) | 437 | (push client server-clients) |
| 427 | (setq registered t | 438 | (setq registered t |
| 428 | newframe t)))) | 439 | newframe t |
| 429 | 440 | dontkill t))) | |
| 430 | ;; ARG is a line number option. | 441 | |
| 431 | ((string-match "\\`\\+[0-9]+\\'" arg) | 442 | ;; Resume a suspended tty frame. |
| 432 | (setq lineno (string-to-int (substring arg 1)))) | 443 | ((equal "-resume" arg) |
| 433 | 444 | (let ((tty (cadr (assq (car client) server-ttys)))) | |
| 434 | ;; ARG is line number:column option. | 445 | (setq dontkill t) |
| 435 | ((string-match "\\`\\+\\([0-9]+\\):\\([0-9]+\\)\\'" arg) | 446 | (when tty (resume-tty tty)))) |
| 436 | (setq lineno (string-to-int (match-string 1 arg)) | 447 | |
| 437 | columnno (string-to-int (match-string 2 arg)))) | 448 | ;; Suspend the client's frame. (In case we get out of |
| 438 | 449 | ;; sync, and a C-z sends a SIGTSTP to emacsclient.) | |
| 439 | ;; ARG is a filename or a Lisp expression. | 450 | ((equal "-suspend" arg) |
| 440 | (t | 451 | (let ((tty (cadr (assq (car client) server-ttys)))) |
| 441 | ;; Undo the quoting that emacsclient does | 452 | (setq dontkill t) |
| 442 | ;; for certain special characters. | 453 | (when tty (suspend-tty tty)))) |
| 443 | (setq arg (server-unquote-arg arg)) | 454 | |
| 444 | ;; Now decode the file name if necessary. | 455 | ;; Noop; useful for debugging emacsclient. |
| 445 | (if coding-system | 456 | ((and (equal "-ignore" arg) (string-match "\\([^ ]*\\) " request)) |
| 446 | (setq arg (decode-coding-string arg coding-system))) | 457 | (setq dontkill t |
| 447 | (unless version-checked | 458 | request (substring request (match-end 0)))) |
| 448 | (error "Protocol error; make sure to use the correct version of emacsclient")) | 459 | |
| 449 | (if eval | 460 | ;; Open a new tty frame at the client. ARG is the name of the pseudo tty. |
| 450 | ;; ARG is a Lisp expression. | 461 | ((and (equal "-tty" arg) (string-match "\\([^ ]*\\) \\([^ ]*\\) " request)) |
| 451 | (let ((v (eval (car (read-from-string arg))))) | 462 | (let ((tty (server-unquote-arg (match-string 1 request))) |
| 463 | (type (server-unquote-arg (match-string 2 request)))) | ||
| 464 | (setq request (substring request (match-end 0))) | ||
| 465 | (unless version-checked | ||
| 466 | (error "Protocol error; make sure to use the correct version of emacsclient")) | ||
| 467 | (let ((frame (make-frame-on-tty tty type))) | ||
| 468 | (push (list (car client) (frame-tty-name frame)) server-ttys) | ||
| 469 | (process-send-string proc (concat "-emacs-pid " (number-to-string (emacs-pid)) "\n")) | ||
| 470 | (select-frame frame) | ||
| 471 | ;; This makes sure that `emacsclient -t -e '(delete-frame)'' works right. | ||
| 472 | (push client server-clients) | ||
| 473 | (setq registered t | ||
| 474 | dontkill t | ||
| 475 | newframe t)))) | ||
| 476 | |||
| 477 | ;; ARG is a line number option. | ||
| 478 | ((and (equal "-position" arg) (string-match "\\(\\+[0-9]+\\) " request)) | ||
| 479 | (setq request (substring request (match-end 0)) | ||
| 480 | lineno (string-to-int (substring (match-string 1 request) 1)))) | ||
| 481 | |||
| 482 | ;; ARG is line number:column option. | ||
| 483 | ((and (equal "-position" arg) (string-match "\\+\\([0-9]+\\):\\([0-9]+\\) " request)) | ||
| 484 | (setq request (substring request (match-end 0)) | ||
| 485 | lineno (string-to-int (match-string 1 request)) | ||
| 486 | columnno (string-to-int (match-string 2 request)))) | ||
| 487 | |||
| 488 | ;; ARG is a file to load. | ||
| 489 | ((and (equal "-file" arg) (string-match "\\([^ ]+\\) " request)) | ||
| 490 | (let ((file (server-unquote-arg (match-string 1 request)))) | ||
| 491 | (setq request (substring request (match-end 0))) | ||
| 492 | (if coding-system | ||
| 493 | (setq file (decode-coding-string file coding-system))) | ||
| 494 | (setq file (command-line-normalize-file-name file)) | ||
| 495 | (push (list file lineno columnno) files)) | ||
| 496 | (setq lineno 1 | ||
| 497 | columnno 0)) | ||
| 498 | |||
| 499 | ;; ARG is a Lisp expression. | ||
| 500 | ((and (equal "-eval" arg) (string-match "\\([^ ]+\\) " request)) | ||
| 501 | (let ((expr (server-unquote-arg (match-string 1 request)))) | ||
| 502 | (setq request (substring request (match-end 0))) | ||
| 503 | (if coding-system | ||
| 504 | (setq expr (decode-coding-string expr coding-system))) | ||
| 505 | (let ((v (eval (car (read-from-string expr))))) | ||
| 452 | (when (and (not newframe) v) | 506 | (when (and (not newframe) v) |
| 453 | (with-temp-buffer | 507 | (with-temp-buffer |
| 454 | (let ((standard-output (current-buffer))) | 508 | (let ((standard-output (current-buffer))) |
| 455 | (pp v) | 509 | (pp v) |
| 456 | (process-send-string proc "-print ") | 510 | (process-send-string proc "-print ") |
| 457 | (process-send-region proc (point-min) (point-max)))))) | 511 | (process-send-string |
| 458 | ;; ARG is a file name. | 512 | proc (server-quote-arg |
| 459 | ;; Collapse multiple slashes to single slashes. | 513 | (buffer-substring-no-properties (point-min) |
| 460 | (setq arg (command-line-normalize-file-name arg)) | 514 | (point-max)))) |
| 461 | (push (list arg lineno columnno) files)) | 515 | (process-send-string proc "\n"))))) |
| 462 | (setq lineno 1) | 516 | (setq lineno 1 |
| 463 | (setq columnno 0))))) | 517 | columnno 0))) |
| 464 | 518 | ||
| 465 | (if (not version-checked) | 519 | ;; Unknown command. |
| 466 | (error "Protocol error; make sure to use the correct version of emacsclient") | 520 | (t (error "Unknown command: %s" arg))))) |
| 521 | |||
| 467 | (when files | 522 | (when files |
| 468 | (run-hooks 'pre-command-hook) | 523 | (run-hooks 'pre-command-hook) |
| 469 | (server-visit-files files client nowait) | 524 | (server-visit-files files client nowait) |
| 470 | (run-hooks 'post-command-hook)) | 525 | (run-hooks 'post-command-hook)) |
| 526 | |||
| 471 | ;; CLIENT is now a list (CLIENTNUM BUFFERS...) | 527 | ;; CLIENT is now a list (CLIENTNUM BUFFERS...) |
| 472 | (if (and (not newframe) (null (cdr client))) | 528 | |
| 473 | ;; This client is empty; get rid of it immediately. | 529 | ;; Delete the client if necessary. |
| 474 | (progn | 530 | (cond |
| 475 | (delete-process proc) | 531 | ;; Client requested nowait; return immediately. |
| 476 | (server-log "Close empty client" proc)) | 532 | (nowait |
| 477 | ;; We visited some buffer for this client. | 533 | (delete-process proc) |
| 478 | (or nowait registered (push client server-clients)) | 534 | (server-log "Close nowait client" proc)) |
| 479 | (unless (or isearch-mode (minibufferp)) | 535 | ;; This client is empty; get rid of it immediately. |
| 480 | (if (and newframe (null (cdr client))) | 536 | ((and (not dontkill) (null (cdr client))) |
| 481 | (message (substitute-command-keys | 537 | (delete-process proc) |
| 482 | "When done with this frame, type \\[delete-frame]")) | 538 | (server-log "Close empty client" proc)) |
| 483 | (server-switch-buffer (nth 1 client)) | 539 | ((not registered) |
| 484 | (run-hooks 'server-switch-hook) | 540 | (push client server-clients))) |
| 485 | (unless nowait | 541 | |
| 486 | (message (substitute-command-keys | 542 | ;; We visited some buffer for this client. |
| 487 | "When done with a buffer, type \\[server-edit]")))))))) | 543 | (cond |
| 544 | ((or isearch-mode (minibufferp)) | ||
| 545 | nil) | ||
| 546 | ((and newframe (null (cdr client))) | ||
| 547 | (message (substitute-command-keys | ||
| 548 | "When done with this frame, type \\[delete-frame]"))) | ||
| 549 | ((not (null (cdr client))) | ||
| 550 | (server-switch-buffer (nth 1 client)) | ||
| 551 | (run-hooks 'server-switch-hook) | ||
| 552 | (unless nowait | ||
| 553 | (message (substitute-command-keys | ||
| 554 | "When done with a buffer, type \\[server-edit]"))))))) | ||
| 555 | |||
| 488 | ;; Save for later any partial line that remains. | 556 | ;; Save for later any partial line that remains. |
| 489 | (when (> (length string) 0) | 557 | (when (> (length string) 0) |
| 490 | (process-put proc 'previous-string string))) | 558 | (process-put proc 'previous-string string))) |
| 491 | ;; condition-case | 559 | ;; condition-case |
| 492 | (error (ignore-errors | 560 | (error (ignore-errors |
| 493 | (process-send-string | 561 | (process-send-string |
| 494 | proc (concat "-error " (error-message-string err))) | 562 | proc (concat "-error " (server-quote-arg (error-message-string err)))) |
| 495 | (setq string "") | 563 | (setq string "") |
| 496 | (server-log (error-message-string err) proc) | 564 | (server-log (error-message-string err) proc) |
| 497 | (delete-process proc))))) | 565 | (delete-process proc))))) |
diff --git a/lisp/term/x-win.el b/lisp/term/x-win.el index e09285e86c1..da5ac04a6c9 100644 --- a/lisp/term/x-win.el +++ b/lisp/term/x-win.el | |||
| @@ -2442,11 +2442,7 @@ order until succeed.") | |||
| 2442 | (if res-selection-timeout | 2442 | (if res-selection-timeout |
| 2443 | (setq x-selection-timeout (string-to-number res-selection-timeout)))) | 2443 | (setq x-selection-timeout (string-to-number res-selection-timeout)))) |
| 2444 | 2444 | ||
| 2445 | ;; XXX This is wrong in general with multi-tty support. | 2445 | ;; Don't let Emacs suspend under X. |
| 2446 | (substitute-key-definition 'suspend-emacs 'iconify-or-deiconify-frame | ||
| 2447 | global-map) | ||
| 2448 | |||
| 2449 | ;; XXX This is wrong in general with multi-tty support. | ||
| 2450 | (add-hook 'suspend-hook 'x-win-suspend-error) | 2446 | (add-hook 'suspend-hook 'x-win-suspend-error) |
| 2451 | 2447 | ||
| 2452 | ;; Arrange for the kill and yank functions to set and check the clipboard. | 2448 | ;; Arrange for the kill and yank functions to set and check the clipboard. |
| @@ -64,9 +64,9 @@ int | |||
| 64 | cmputc (c) | 64 | cmputc (c) |
| 65 | char c; | 65 | char c; |
| 66 | { | 66 | { |
| 67 | if (TTY_TERMSCRIPT (current_tty)) | 67 | if (current_tty->termscript) |
| 68 | putc (c & 0177, TTY_TERMSCRIPT (current_tty)); | 68 | putc (c & 0177, current_tty->termscript); |
| 69 | putc (c & 0177, TTY_OUTPUT (current_tty)); | 69 | putc (c & 0177, current_tty->output); |
| 70 | return c; | 70 | return c; |
| 71 | } | 71 | } |
| 72 | 72 | ||
| @@ -136,12 +136,12 @@ cmcheckmagic (struct tty_display_info *tty) | |||
| 136 | { | 136 | { |
| 137 | if (!MagicWrap (tty) || curY (tty) >= FrameRows (tty) - 1) | 137 | if (!MagicWrap (tty) || curY (tty) >= FrameRows (tty) - 1) |
| 138 | abort (); | 138 | abort (); |
| 139 | if (TTY_TERMSCRIPT (tty)) | 139 | if (tty->termscript) |
| 140 | putc ('\r', TTY_TERMSCRIPT (tty)); | 140 | putc ('\r', tty->termscript); |
| 141 | putc ('\r', TTY_OUTPUT (tty)); | 141 | putc ('\r', tty->output); |
| 142 | if (TTY_TERMSCRIPT (tty)) | 142 | if (tty->termscript) |
| 143 | putc ('\n', TTY_TERMSCRIPT (tty)); | 143 | putc ('\n', tty->termscript); |
| 144 | putc ('\n', TTY_OUTPUT (tty)); | 144 | putc ('\n', tty->output); |
| 145 | curX (tty) = 0; | 145 | curX (tty) = 0; |
| 146 | curY (tty)++; | 146 | curY (tty)++; |
| 147 | } | 147 | } |
diff --git a/src/dispnew.c b/src/dispnew.c index aaf3c440f34..8a3d7013c3e 100644 --- a/src/dispnew.c +++ b/src/dispnew.c | |||
| @@ -3316,7 +3316,7 @@ DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0, | |||
| 3316 | clear_current_matrices (f); | 3316 | clear_current_matrices (f); |
| 3317 | update_end (f); | 3317 | update_end (f); |
| 3318 | if (FRAME_TERMCAP_P (f)) | 3318 | if (FRAME_TERMCAP_P (f)) |
| 3319 | fflush (TTY_OUTPUT (FRAME_TTY (f))); | 3319 | fflush (FRAME_TTY (f)->output); |
| 3320 | windows_or_buffers_changed++; | 3320 | windows_or_buffers_changed++; |
| 3321 | /* Mark all windows as inaccurate, so that every window will have | 3321 | /* Mark all windows as inaccurate, so that every window will have |
| 3322 | its redisplay done. */ | 3322 | its redisplay done. */ |
| @@ -3659,7 +3659,7 @@ direct_output_for_insert (g) | |||
| 3659 | update_end (f); | 3659 | update_end (f); |
| 3660 | updated_row = NULL; | 3660 | updated_row = NULL; |
| 3661 | if (FRAME_TERMCAP_P (f)) | 3661 | if (FRAME_TERMCAP_P (f)) |
| 3662 | fflush (TTY_OUTPUT (FRAME_TTY (f))); | 3662 | fflush (FRAME_TTY (f)->output); |
| 3663 | 3663 | ||
| 3664 | TRACE ((stderr, "direct output for insert\n")); | 3664 | TRACE ((stderr, "direct output for insert\n")); |
| 3665 | mark_window_display_accurate (it.window, 1); | 3665 | mark_window_display_accurate (it.window, 1); |
| @@ -3751,7 +3751,7 @@ direct_output_forward_char (n) | |||
| 3751 | } | 3751 | } |
| 3752 | 3752 | ||
| 3753 | if (FRAME_TERMCAP_P (f)) | 3753 | if (FRAME_TERMCAP_P (f)) |
| 3754 | fflush (TTY_OUTPUT (FRAME_TTY (f))); | 3754 | fflush (FRAME_TTY (f)->output); |
| 3755 | redisplay_performed_directly_p = 1; | 3755 | redisplay_performed_directly_p = 1; |
| 3756 | return 1; | 3756 | return 1; |
| 3757 | } | 3757 | } |
| @@ -3849,9 +3849,9 @@ update_frame (f, force_p, inhibit_hairy_id_p) | |||
| 3849 | 3849 | ||
| 3850 | if (FRAME_TERMCAP_P (f)) | 3850 | if (FRAME_TERMCAP_P (f)) |
| 3851 | { | 3851 | { |
| 3852 | if (TTY_TERMSCRIPT (FRAME_TTY (f))) | 3852 | if (FRAME_TTY (f)->termscript) |
| 3853 | fflush (TTY_TERMSCRIPT (FRAME_TTY (f))); | 3853 | fflush (FRAME_TTY (f)->termscript); |
| 3854 | fflush (TTY_OUTPUT (FRAME_TTY (f))); | 3854 | fflush (FRAME_TTY (f)->output); |
| 3855 | } | 3855 | } |
| 3856 | 3856 | ||
| 3857 | /* Check window matrices for lost pointers. */ | 3857 | /* Check window matrices for lost pointers. */ |
| @@ -5133,18 +5133,18 @@ update_frame_1 (f, force_p, inhibit_id_p) | |||
| 5133 | Also flush out if likely to have more than 1k buffered | 5133 | Also flush out if likely to have more than 1k buffered |
| 5134 | otherwise. I'm told that some telnet connections get | 5134 | otherwise. I'm told that some telnet connections get |
| 5135 | really screwed by more than 1k output at once. */ | 5135 | really screwed by more than 1k output at once. */ |
| 5136 | int outq = PENDING_OUTPUT_COUNT (TTY_OUTPUT (FRAME_TTY (f))); | 5136 | int outq = PENDING_OUTPUT_COUNT (FRAME_TTY (f)->output); |
| 5137 | if (outq > 900 | 5137 | if (outq > 900 |
| 5138 | || (outq > 20 && ((i - 1) % preempt_count == 0))) | 5138 | || (outq > 20 && ((i - 1) % preempt_count == 0))) |
| 5139 | { | 5139 | { |
| 5140 | fflush (TTY_OUTPUT (FRAME_TTY (f))); | 5140 | fflush (FRAME_TTY (f)->output); |
| 5141 | if (preempt_count == 1) | 5141 | if (preempt_count == 1) |
| 5142 | { | 5142 | { |
| 5143 | #ifdef EMACS_OUTQSIZE | 5143 | #ifdef EMACS_OUTQSIZE |
| 5144 | if (EMACS_OUTQSIZE (0, &outq) < 0) | 5144 | if (EMACS_OUTQSIZE (0, &outq) < 0) |
| 5145 | /* Probably not a tty. Ignore the error and reset | 5145 | /* Probably not a tty. Ignore the error and reset |
| 5146 | the outq count. */ | 5146 | the outq count. */ |
| 5147 | outq = PENDING_OUTPUT_COUNT (TTY_OUTPUT (FRAME_TTY (f))); | 5147 | outq = PENDING_OUTPUT_COUNT (FRAME_TTY (f->output)); |
| 5148 | #endif | 5148 | #endif |
| 5149 | outq *= 10; | 5149 | outq *= 10; |
| 5150 | if (baud_rate <= outq && baud_rate > 0) | 5150 | if (baud_rate <= outq && baud_rate > 0) |
| @@ -5999,7 +5999,7 @@ window_change_signal (signalnum) /* If we don't have an argument, */ | |||
| 5999 | if (! tty->term_initted) | 5999 | if (! tty->term_initted) |
| 6000 | continue; | 6000 | continue; |
| 6001 | 6001 | ||
| 6002 | get_tty_size (fileno (TTY_INPUT (tty)), &width, &height); | 6002 | get_tty_size (fileno (tty->input), &width, &height); |
| 6003 | 6003 | ||
| 6004 | { | 6004 | { |
| 6005 | Lisp_Object tail, frame; | 6005 | Lisp_Object tail, frame; |
| @@ -6211,15 +6211,22 @@ FILE = nil means just close any termscript file currently open. */) | |||
| 6211 | (file) | 6211 | (file) |
| 6212 | Lisp_Object file; | 6212 | Lisp_Object file; |
| 6213 | { | 6213 | { |
| 6214 | if (TTY_TERMSCRIPT (CURTTY ()) != 0) | 6214 | struct tty_display_info *tty; |
| 6215 | fclose (TTY_TERMSCRIPT (CURTTY ())); | 6215 | |
| 6216 | TTY_TERMSCRIPT (CURTTY ()) = 0; | 6216 | if (! FRAME_TERMCAP_P (SELECTED_FRAME ())) |
| 6217 | error ("Current frame is not on a tty device"); | ||
| 6218 | |||
| 6219 | tty = CURTTY (); | ||
| 6220 | |||
| 6221 | if (tty->termscript != 0) | ||
| 6222 | fclose (tty->termscript); | ||
| 6223 | tty->termscript = 0; | ||
| 6217 | 6224 | ||
| 6218 | if (! NILP (file)) | 6225 | if (! NILP (file)) |
| 6219 | { | 6226 | { |
| 6220 | file = Fexpand_file_name (file, Qnil); | 6227 | file = Fexpand_file_name (file, Qnil); |
| 6221 | TTY_TERMSCRIPT (CURTTY ()) = fopen (SDATA (file), "w"); | 6228 | tty->termscript = fopen (SDATA (file), "w"); |
| 6222 | if (TTY_TERMSCRIPT (CURTTY ()) == 0) | 6229 | if (tty->termscript == 0) |
| 6223 | report_file_error ("Opening termscript", Fcons (file, Qnil)); | 6230 | report_file_error ("Opening termscript", Fcons (file, Qnil)); |
| 6224 | } | 6231 | } |
| 6225 | return Qnil; | 6232 | return Qnil; |
| @@ -6233,20 +6240,23 @@ Control characters in STRING will have terminal-dependent effects. */) | |||
| 6233 | (string) | 6240 | (string) |
| 6234 | Lisp_Object string; | 6241 | Lisp_Object string; |
| 6235 | { | 6242 | { |
| 6243 | struct tty_display_info *tty; | ||
| 6244 | |||
| 6236 | /* ??? Perhaps we should do something special for multibyte strings here. */ | 6245 | /* ??? Perhaps we should do something special for multibyte strings here. */ |
| 6237 | CHECK_STRING (string); | 6246 | CHECK_STRING (string); |
| 6247 | |||
| 6238 | if (! FRAME_TERMCAP_P (SELECTED_FRAME ())) | 6248 | if (! FRAME_TERMCAP_P (SELECTED_FRAME ())) |
| 6239 | error ("Current frame is not on a tty device"); | 6249 | error ("Current frame is not on a tty device"); |
| 6250 | |||
| 6251 | tty = CURTTY (); | ||
| 6240 | 6252 | ||
| 6241 | if (TTY_TERMSCRIPT (CURTTY ())) | 6253 | if (tty->termscript) |
| 6242 | { | 6254 | { |
| 6243 | fwrite (SDATA (string), 1, SBYTES (string), | 6255 | fwrite (SDATA (string), 1, SBYTES (string), tty->termscript); |
| 6244 | TTY_TERMSCRIPT (CURTTY ())); | 6256 | fflush (tty->termscript); |
| 6245 | fflush (TTY_TERMSCRIPT (CURTTY ())); | ||
| 6246 | } | 6257 | } |
| 6247 | fwrite (SDATA (string), 1, SBYTES (string), | 6258 | fwrite (SDATA (string), 1, SBYTES (string), tty->output); |
| 6248 | TTY_OUTPUT (CURTTY ())); | 6259 | fflush (tty->output); |
| 6249 | fflush (TTY_OUTPUT (CURTTY ())); | ||
| 6250 | return Qnil; | 6260 | return Qnil; |
| 6251 | } | 6261 | } |
| 6252 | 6262 | ||
| @@ -6265,7 +6275,7 @@ terminate any keyboard macro currently executing. */) | |||
| 6265 | else | 6275 | else |
| 6266 | ring_bell (); | 6276 | ring_bell (); |
| 6267 | if (FRAME_TERMCAP_P (XFRAME (selected_frame))) | 6277 | if (FRAME_TERMCAP_P (XFRAME (selected_frame))) |
| 6268 | fflush (TTY_OUTPUT (CURTTY ())); | 6278 | fflush (CURTTY ()->output); |
| 6269 | } | 6279 | } |
| 6270 | else | 6280 | else |
| 6271 | bitch_at_user (); | 6281 | bitch_at_user (); |
| @@ -6283,7 +6293,7 @@ bitch_at_user () | |||
| 6283 | else | 6293 | else |
| 6284 | ring_bell (); | 6294 | ring_bell (); |
| 6285 | if (FRAME_TERMCAP_P (XFRAME (selected_frame))) | 6295 | if (FRAME_TERMCAP_P (XFRAME (selected_frame))) |
| 6286 | fflush (TTY_OUTPUT (CURTTY ())); | 6296 | fflush (CURTTY ()->output); |
| 6287 | } | 6297 | } |
| 6288 | 6298 | ||
| 6289 | 6299 | ||
diff --git a/src/frame.c b/src/frame.c index 8ffabfa8b89..c7b5491500f 100644 --- a/src/frame.c +++ b/src/frame.c | |||
| @@ -667,7 +667,8 @@ and the `tty-type' parameter specifies the terminal type. Example: | |||
| 667 | 667 | ||
| 668 | (make-terminal-frame '((tty . "/dev/pts/5") (tty-type . "xterm"))) | 668 | (make-terminal-frame '((tty . "/dev/pts/5") (tty-type . "xterm"))) |
| 669 | 669 | ||
| 670 | Note that changing the size of one terminal frame automatically affects all. */) | 670 | Note that changing the size of one terminal frame automatically |
| 671 | affects all frames on the same terminal device. */) | ||
| 671 | (parms) | 672 | (parms) |
| 672 | Lisp_Object parms; | 673 | Lisp_Object parms; |
| 673 | { | 674 | { |
| @@ -742,7 +743,7 @@ Note that changing the size of one terminal frame automatically affects all. */ | |||
| 742 | 743 | ||
| 743 | { | 744 | { |
| 744 | int width, height; | 745 | int width, height; |
| 745 | get_tty_size (fileno (TTY_INPUT (FRAME_TTY (f))), &width, &height); | 746 | get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height); |
| 746 | change_frame_size (f, height, width, 0, 0, 0); | 747 | change_frame_size (f, height, width, 0, 0, 0); |
| 747 | } | 748 | } |
| 748 | 749 | ||
diff --git a/src/keyboard.c b/src/keyboard.c index 2c6edc68f99..5bcd53a260f 100644 --- a/src/keyboard.c +++ b/src/keyboard.c | |||
| @@ -6704,10 +6704,13 @@ tty_read_avail_input (struct display *display, | |||
| 6704 | if (! tty->term_initted) /* In case we get called during bootstrap. */ | 6704 | if (! tty->term_initted) /* In case we get called during bootstrap. */ |
| 6705 | return 0; | 6705 | return 0; |
| 6706 | 6706 | ||
| 6707 | if (! tty->input) | ||
| 6708 | return 0; /* The terminal is suspended. */ | ||
| 6709 | |||
| 6707 | /* Determine how many characters we should *try* to read. */ | 6710 | /* Determine how many characters we should *try* to read. */ |
| 6708 | #ifdef FIONREAD | 6711 | #ifdef FIONREAD |
| 6709 | /* Find out how much input is available. */ | 6712 | /* Find out how much input is available. */ |
| 6710 | if (ioctl (fileno (TTY_INPUT (tty)), FIONREAD, &n_to_read) < 0) | 6713 | if (ioctl (fileno (tty->input), FIONREAD, &n_to_read) < 0) |
| 6711 | { | 6714 | { |
| 6712 | if (! noninteractive) | 6715 | if (! noninteractive) |
| 6713 | return -2; /* Close this display. */ | 6716 | return -2; /* Close this display. */ |
| @@ -6722,7 +6725,7 @@ tty_read_avail_input (struct display *display, | |||
| 6722 | #if defined (USG) || defined (DGUX) || defined(CYGWIN) | 6725 | #if defined (USG) || defined (DGUX) || defined(CYGWIN) |
| 6723 | /* Read some input if available, but don't wait. */ | 6726 | /* Read some input if available, but don't wait. */ |
| 6724 | n_to_read = sizeof cbuf; | 6727 | n_to_read = sizeof cbuf; |
| 6725 | fcntl (fileno (TTY_INPUT (tty)), F_SETFL, O_NDELAY); | 6728 | fcntl (fileno (tty->input), F_SETFL, O_NDELAY); |
| 6726 | #else | 6729 | #else |
| 6727 | you lose; | 6730 | you lose; |
| 6728 | #endif | 6731 | #endif |
| @@ -6732,7 +6735,7 @@ tty_read_avail_input (struct display *display, | |||
| 6732 | NREAD is set to the number of chars read. */ | 6735 | NREAD is set to the number of chars read. */ |
| 6733 | do | 6736 | do |
| 6734 | { | 6737 | { |
| 6735 | nread = emacs_read (fileno (TTY_INPUT (tty)), cbuf, n_to_read); | 6738 | nread = emacs_read (fileno (tty->input), cbuf, n_to_read); |
| 6736 | /* POSIX infers that processes which are not in the session leader's | 6739 | /* POSIX infers that processes which are not in the session leader's |
| 6737 | process group won't get SIGHUP's at logout time. BSDI adheres to | 6740 | process group won't get SIGHUP's at logout time. BSDI adheres to |
| 6738 | this part standard and returns -1 from read (0) with errno==EIO | 6741 | this part standard and returns -1 from read (0) with errno==EIO |
| @@ -6770,7 +6773,7 @@ tty_read_avail_input (struct display *display, | |||
| 6770 | 6773 | ||
| 6771 | #ifndef FIONREAD | 6774 | #ifndef FIONREAD |
| 6772 | #if defined (USG) || defined (DGUX) || defined (CYGWIN) | 6775 | #if defined (USG) || defined (DGUX) || defined (CYGWIN) |
| 6773 | fcntl (fileno (TTY_INPUT (tty)), F_SETFL, 0); | 6776 | fcntl (fileno (tty->input), F_SETFL, 0); |
| 6774 | #endif /* USG or DGUX or CYGWIN */ | 6777 | #endif /* USG or DGUX or CYGWIN */ |
| 6775 | #endif /* no FIONREAD */ | 6778 | #endif /* no FIONREAD */ |
| 6776 | 6779 | ||
| @@ -10168,7 +10171,7 @@ On such systems, Emacs starts a subshell instead of suspending. */) | |||
| 10168 | call1 (Vrun_hooks, intern ("suspend-hook")); | 10171 | call1 (Vrun_hooks, intern ("suspend-hook")); |
| 10169 | 10172 | ||
| 10170 | GCPRO1 (stuffstring); | 10173 | GCPRO1 (stuffstring); |
| 10171 | get_tty_size (fileno (TTY_INPUT (CURTTY ())), &old_width, &old_height); | 10174 | get_tty_size (fileno (CURTTY ()->input), &old_width, &old_height); |
| 10172 | reset_all_sys_modes (); | 10175 | reset_all_sys_modes (); |
| 10173 | /* sys_suspend can get an error if it tries to fork a subshell | 10176 | /* sys_suspend can get an error if it tries to fork a subshell |
| 10174 | and the system resources aren't available for that. */ | 10177 | and the system resources aren't available for that. */ |
| @@ -10184,7 +10187,7 @@ On such systems, Emacs starts a subshell instead of suspending. */) | |||
| 10184 | /* Check if terminal/window size has changed. | 10187 | /* Check if terminal/window size has changed. |
| 10185 | Note that this is not useful when we are running directly | 10188 | Note that this is not useful when we are running directly |
| 10186 | with a window system; but suspend should be disabled in that case. */ | 10189 | with a window system; but suspend should be disabled in that case. */ |
| 10187 | get_tty_size (fileno (TTY_INPUT (CURTTY ())), &width, &height); | 10190 | get_tty_size (fileno (CURTTY ()->input), &width, &height); |
| 10188 | if (width != old_width || height != old_height) | 10191 | if (width != old_width || height != old_height) |
| 10189 | change_frame_size (SELECTED_FRAME (), height, width, 0, 0, 0); | 10192 | change_frame_size (SELECTED_FRAME (), height, width, 0, 0, 0); |
| 10190 | 10193 | ||
diff --git a/src/sysdep.c b/src/sysdep.c index febf59253e1..d4693f99a94 100644 --- a/src/sysdep.c +++ b/src/sysdep.c | |||
| @@ -274,7 +274,7 @@ discard_tty_input () | |||
| 274 | 274 | ||
| 275 | #ifdef VMS | 275 | #ifdef VMS |
| 276 | end_kbd_input (); | 276 | end_kbd_input (); |
| 277 | SYS$QIOW (0, fileno (TTY_INPUT (CURTTY())), IO$_READVBLK|IO$M_PURGE, input_iosb, 0, 0, | 277 | SYS$QIOW (0, fileno (CURTTY()->input), IO$_READVBLK|IO$M_PURGE, input_iosb, 0, 0, |
| 278 | &buf.main, 0, 0, terminator_mask, 0, 0); | 278 | &buf.main, 0, 0, terminator_mask, 0, 0); |
| 279 | queue_kbd_input (); | 279 | queue_kbd_input (); |
| 280 | #else /* not VMS */ | 280 | #else /* not VMS */ |
| @@ -284,7 +284,8 @@ discard_tty_input () | |||
| 284 | for (tty = tty_list; tty; tty = tty->next) | 284 | for (tty = tty_list; tty; tty = tty->next) |
| 285 | { | 285 | { |
| 286 | int zero = 0; | 286 | int zero = 0; |
| 287 | ioctl (fileno (TTY_INPUT (tty)), TIOCFLUSH, &zero); | 287 | if (tty->input) |
| 288 | ioctl (fileno (tty->input), TIOCFLUSH, &zero); | ||
| 288 | } | 289 | } |
| 289 | } | 290 | } |
| 290 | #else /* not Apollo */ | 291 | #else /* not Apollo */ |
| @@ -296,8 +297,11 @@ discard_tty_input () | |||
| 296 | struct tty_display_info *tty; | 297 | struct tty_display_info *tty; |
| 297 | for (tty = tty_list; tty; tty = tty->next) | 298 | for (tty = tty_list; tty; tty = tty->next) |
| 298 | { | 299 | { |
| 299 | EMACS_GET_TTY (fileno (TTY_INPUT (tty)), &buf); | 300 | if (tty->input) /* Is the device suspended? */ |
| 300 | EMACS_SET_TTY (fileno (TTY_INPUT (tty)), &buf, 0); | 301 | { |
| 302 | EMACS_GET_TTY (fileno (tty->input), &buf); | ||
| 303 | EMACS_SET_TTY (fileno (tty->input), &buf, 0); | ||
| 304 | } | ||
| 301 | } | 305 | } |
| 302 | } | 306 | } |
| 303 | #endif /* not MSDOS */ | 307 | #endif /* not MSDOS */ |
| @@ -322,7 +326,7 @@ stuff_char (char c) | |||
| 322 | 326 | ||
| 323 | /* Should perhaps error if in batch mode */ | 327 | /* Should perhaps error if in batch mode */ |
| 324 | #ifdef TIOCSTI | 328 | #ifdef TIOCSTI |
| 325 | ioctl (fileno (TTY_INPUT (CURTTY())), TIOCSTI, &c); | 329 | ioctl (fileno (CURTTY()->input), TIOCSTI, &c); |
| 326 | #else /* no TIOCSTI */ | 330 | #else /* no TIOCSTI */ |
| 327 | error ("Cannot stuff terminal input characters in this version of Unix"); | 331 | error ("Cannot stuff terminal input characters in this version of Unix"); |
| 328 | #endif /* no TIOCSTI */ | 332 | #endif /* no TIOCSTI */ |
| @@ -1005,7 +1009,7 @@ request_sigio () | |||
| 1005 | return; | 1009 | return; |
| 1006 | 1010 | ||
| 1007 | /* XXX CURTTY() is bogus here. */ | 1011 | /* XXX CURTTY() is bogus here. */ |
| 1008 | ioctl (fileno (TTY_INPUT (CURTTY ())), FIOASYNC, &on); | 1012 | ioctl (fileno (CURTTY ()->input), FIOASYNC, &on); |
| 1009 | interrupts_deferred = 0; | 1013 | interrupts_deferred = 0; |
| 1010 | } | 1014 | } |
| 1011 | 1015 | ||
| @@ -1018,7 +1022,7 @@ unrequest_sigio () | |||
| 1018 | return; | 1022 | return; |
| 1019 | 1023 | ||
| 1020 | /* XXX CURTTY() is bogus here. */ | 1024 | /* XXX CURTTY() is bogus here. */ |
| 1021 | ioctl (fileno (TTY_INPUT (CURTTY ())), FIOASYNC, &off); | 1025 | ioctl (fileno (CURTTY ()->input), FIOASYNC, &off); |
| 1022 | interrupts_deferred = 1; | 1026 | interrupts_deferred = 1; |
| 1023 | } | 1027 | } |
| 1024 | 1028 | ||
| @@ -1366,6 +1370,9 @@ nil means don't delete them until `list-processes' is run. */); | |||
| 1366 | if (noninteractive) | 1370 | if (noninteractive) |
| 1367 | return; | 1371 | return; |
| 1368 | 1372 | ||
| 1373 | if (!tty_out->output) | ||
| 1374 | return; /* The tty is suspended. */ | ||
| 1375 | |||
| 1369 | #ifdef VMS | 1376 | #ifdef VMS |
| 1370 | if (!input_ef) | 1377 | if (!input_ef) |
| 1371 | input_ef = get_kbd_event_flag (); | 1378 | input_ef = get_kbd_event_flag (); |
| @@ -1404,13 +1411,13 @@ nil means don't delete them until `list-processes' is run. */); | |||
| 1404 | unconditionally will not cause any problems. */ | 1411 | unconditionally will not cause any problems. */ |
| 1405 | if (! read_socket_hook && EQ (Vinitial_window_system, Qnil)) | 1412 | if (! read_socket_hook && EQ (Vinitial_window_system, Qnil)) |
| 1406 | #endif | 1413 | #endif |
| 1407 | narrow_foreground_group (fileno (TTY_INPUT (tty_out))); | 1414 | narrow_foreground_group (fileno (tty_out->input)); |
| 1408 | #endif | 1415 | #endif |
| 1409 | 1416 | ||
| 1410 | if (! tty_out->old_tty) | 1417 | if (! tty_out->old_tty) |
| 1411 | tty_out->old_tty = (struct emacs_tty *) xmalloc (sizeof (struct emacs_tty)); | 1418 | tty_out->old_tty = (struct emacs_tty *) xmalloc (sizeof (struct emacs_tty)); |
| 1412 | 1419 | ||
| 1413 | EMACS_GET_TTY (fileno (TTY_INPUT (tty_out)), tty_out->old_tty); | 1420 | EMACS_GET_TTY (fileno (tty_out->input), tty_out->old_tty); |
| 1414 | 1421 | ||
| 1415 | tty = *tty_out->old_tty; | 1422 | tty = *tty_out->old_tty; |
| 1416 | 1423 | ||
| @@ -1626,23 +1633,23 @@ nil means don't delete them until `list-processes' is run. */); | |||
| 1626 | dos_ttraw (); | 1633 | dos_ttraw (); |
| 1627 | #endif | 1634 | #endif |
| 1628 | 1635 | ||
| 1629 | EMACS_SET_TTY (fileno (TTY_INPUT (tty_out)), &tty, 0); | 1636 | EMACS_SET_TTY (fileno (tty_out->input), &tty, 0); |
| 1630 | 1637 | ||
| 1631 | /* This code added to insure that, if flow-control is not to be used, | 1638 | /* This code added to insure that, if flow-control is not to be used, |
| 1632 | we have an unlocked terminal at the start. */ | 1639 | we have an unlocked terminal at the start. */ |
| 1633 | 1640 | ||
| 1634 | #ifdef TCXONC | 1641 | #ifdef TCXONC |
| 1635 | if (!tty_out->flow_control) ioctl (fileno (TTY_INPUT (tty_out)), TCXONC, 1); | 1642 | if (!tty_out->flow_control) ioctl (fileno (tty_out->input), TCXONC, 1); |
| 1636 | #endif | 1643 | #endif |
| 1637 | #ifndef APOLLO | 1644 | #ifndef APOLLO |
| 1638 | #ifdef TIOCSTART | 1645 | #ifdef TIOCSTART |
| 1639 | if (!tty_out->flow_control) ioctl (fileno (TTY_INPUT (tty_out)), TIOCSTART, 0); | 1646 | if (!tty_out->flow_control) ioctl (fileno (tty_out->input), TIOCSTART, 0); |
| 1640 | #endif | 1647 | #endif |
| 1641 | #endif | 1648 | #endif |
| 1642 | 1649 | ||
| 1643 | #if defined (HAVE_TERMIOS) || defined (HPUX9) | 1650 | #if defined (HAVE_TERMIOS) || defined (HPUX9) |
| 1644 | #ifdef TCOON | 1651 | #ifdef TCOON |
| 1645 | if (!tty_out->flow_control) tcflow (fileno (TTY_INPUT (tty_out)), TCOON); | 1652 | if (!tty_out->flow_control) tcflow (fileno (tty_out->input), TCOON); |
| 1646 | #endif | 1653 | #endif |
| 1647 | #endif | 1654 | #endif |
| 1648 | 1655 | ||
| @@ -1662,7 +1669,7 @@ nil means don't delete them until `list-processes' is run. */); | |||
| 1662 | 1669 | ||
| 1663 | #ifdef VMS | 1670 | #ifdef VMS |
| 1664 | /* Appears to do nothing when in PASTHRU mode. | 1671 | /* Appears to do nothing when in PASTHRU mode. |
| 1665 | SYS$QIOW (0, fileno (TTY_INPUT (tty_out)), IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0, | 1672 | SYS$QIOW (0, fileno (tty_out->input), IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0, |
| 1666 | interrupt_signal, oob_chars, 0, 0, 0, 0); | 1673 | interrupt_signal, oob_chars, 0, 0, 0, 0); |
| 1667 | */ | 1674 | */ |
| 1668 | queue_kbd_input (0); | 1675 | queue_kbd_input (0); |
| @@ -1673,10 +1680,10 @@ nil means don't delete them until `list-processes' is run. */); | |||
| 1673 | #ifdef F_GETOWN /* F_SETFL does not imply existence of F_GETOWN */ | 1680 | #ifdef F_GETOWN /* F_SETFL does not imply existence of F_GETOWN */ |
| 1674 | if (interrupt_input) | 1681 | if (interrupt_input) |
| 1675 | { | 1682 | { |
| 1676 | old_fcntl_owner[fileno (TTY_INPUT (tty_out))] = | 1683 | old_fcntl_owner[fileno (tty_out->input)] = |
| 1677 | fcntl (fileno (TTY_INPUT (tty_out)), F_GETOWN, 0); | 1684 | fcntl (fileno (tty_out->input), F_GETOWN, 0); |
| 1678 | fcntl (fileno (TTY_INPUT (tty_out)), F_SETOWN, getpid ()); | 1685 | fcntl (fileno (tty_out->input), F_SETOWN, getpid ()); |
| 1679 | init_sigio (fileno (TTY_INPUT (tty_out))); | 1686 | init_sigio (fileno (tty_out->input)); |
| 1680 | } | 1687 | } |
| 1681 | #endif /* F_GETOWN */ | 1688 | #endif /* F_GETOWN */ |
| 1682 | #endif /* F_SETOWN_BUG */ | 1689 | #endif /* F_SETOWN_BUG */ |
| @@ -1684,7 +1691,7 @@ nil means don't delete them until `list-processes' is run. */); | |||
| 1684 | 1691 | ||
| 1685 | #ifdef BSD4_1 | 1692 | #ifdef BSD4_1 |
| 1686 | if (interrupt_input) | 1693 | if (interrupt_input) |
| 1687 | init_sigio (fileno (TTY_INPUT (tty_out))); | 1694 | init_sigio (fileno (tty_out->input)); |
| 1688 | #endif | 1695 | #endif |
| 1689 | 1696 | ||
| 1690 | #ifdef VMS /* VMS sometimes has this symbol but lacks setvbuf. */ | 1697 | #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. */); | |||
| 1694 | /* This symbol is defined on recent USG systems. | 1701 | /* This symbol is defined on recent USG systems. |
| 1695 | Someone says without this call USG won't really buffer the file | 1702 | Someone says without this call USG won't really buffer the file |
| 1696 | even with a call to setbuf. */ | 1703 | even with a call to setbuf. */ |
| 1697 | setvbuf (TTY_OUTPUT (tty_out), (char *) _sobuf, _IOFBF, sizeof _sobuf); | 1704 | setvbuf (tty_out->output, (char *) _sobuf, _IOFBF, sizeof _sobuf); |
| 1698 | #else | 1705 | #else |
| 1699 | setbuf (TTY_OUTPUT (tty_out), (char *) _sobuf); | 1706 | setbuf (tty_out->output, (char *) _sobuf); |
| 1700 | #endif | 1707 | #endif |
| 1701 | 1708 | ||
| 1702 | tty_set_terminal_modes (tty_out->display); | 1709 | tty_set_terminal_modes (tty_out->display); |
| @@ -1867,10 +1874,13 @@ reset_sys_modes (tty_out) | |||
| 1867 | if (!tty_out->term_initted) | 1874 | if (!tty_out->term_initted) |
| 1868 | return; | 1875 | return; |
| 1869 | 1876 | ||
| 1877 | if (!tty_out->output) | ||
| 1878 | return; /* The tty is suspended. */ | ||
| 1879 | |||
| 1870 | /* Go to and clear the last line of the terminal. */ | 1880 | /* Go to and clear the last line of the terminal. */ |
| 1871 | 1881 | ||
| 1872 | cmgoto (tty_out, FrameRows (tty_out) - 1, 0); | 1882 | cmgoto (tty_out, FrameRows (tty_out) - 1, 0); |
| 1873 | 1883 | ||
| 1874 | /* Code adapted from tty_clear_end_of_line. */ | 1884 | /* Code adapted from tty_clear_end_of_line. */ |
| 1875 | if (tty_out->TS_clr_line) | 1885 | if (tty_out->TS_clr_line) |
| 1876 | { | 1886 | { |
| @@ -1880,13 +1890,13 @@ reset_sys_modes (tty_out) | |||
| 1880 | { /* have to do it the hard way */ | 1890 | { /* have to do it the hard way */ |
| 1881 | int i; | 1891 | int i; |
| 1882 | turn_off_insert (tty_out); | 1892 | turn_off_insert (tty_out); |
| 1883 | 1893 | ||
| 1884 | for (i = curX (tty_out); i < FrameCols (tty_out) - 1; i++) | 1894 | for (i = curX (tty_out); i < FrameCols (tty_out) - 1; i++) |
| 1885 | { | 1895 | { |
| 1886 | fputc (' ', TTY_OUTPUT (tty_out)); | 1896 | fputc (' ', tty_out->output); |
| 1887 | } | 1897 | } |
| 1888 | } | 1898 | } |
| 1889 | 1899 | ||
| 1890 | cmgoto (tty_out, FrameRows (tty_out) - 1, 0); | 1900 | cmgoto (tty_out, FrameRows (tty_out) - 1, 0); |
| 1891 | fflush (tty_out->output); | 1901 | fflush (tty_out->output); |
| 1892 | 1902 | ||
| @@ -1902,11 +1912,11 @@ reset_sys_modes (tty_out) | |||
| 1902 | #endif | 1912 | #endif |
| 1903 | 1913 | ||
| 1904 | tty_reset_terminal_modes (tty_out->display); | 1914 | tty_reset_terminal_modes (tty_out->display); |
| 1905 | fflush (TTY_OUTPUT (tty_out)); | 1915 | fflush (tty_out->output); |
| 1906 | #ifdef BSD_SYSTEM | 1916 | #ifdef BSD_SYSTEM |
| 1907 | #ifndef BSD4_1 | 1917 | #ifndef BSD4_1 |
| 1908 | /* Avoid possible loss of output when changing terminal modes. */ | 1918 | /* Avoid possible loss of output when changing terminal modes. */ |
| 1909 | fsync (fileno (TTY_OUTPUT (tty_out))); | 1919 | fsync (fileno (tty_out->output)); |
| 1910 | #endif | 1920 | #endif |
| 1911 | #endif | 1921 | #endif |
| 1912 | 1922 | ||
| @@ -1915,24 +1925,24 @@ reset_sys_modes (tty_out) | |||
| 1915 | #ifdef F_SETOWN /* F_SETFL does not imply existence of F_SETOWN */ | 1925 | #ifdef F_SETOWN /* F_SETFL does not imply existence of F_SETOWN */ |
| 1916 | if (interrupt_input) | 1926 | if (interrupt_input) |
| 1917 | { | 1927 | { |
| 1918 | reset_sigio (fileno (TTY_INPUT (tty_out))); | 1928 | reset_sigio (fileno (tty_out->input)); |
| 1919 | fcntl (fileno (TTY_INPUT (tty_out)), F_SETOWN, | 1929 | fcntl (fileno (tty_out->input), F_SETOWN, |
| 1920 | old_fcntl_owner[fileno (TTY_INPUT (tty_out))]); | 1930 | old_fcntl_owner[fileno (tty_out->input)]); |
| 1921 | } | 1931 | } |
| 1922 | #endif /* F_SETOWN */ | 1932 | #endif /* F_SETOWN */ |
| 1923 | #endif /* F_SETOWN_BUG */ | 1933 | #endif /* F_SETOWN_BUG */ |
| 1924 | #ifdef O_NDELAY | 1934 | #ifdef O_NDELAY |
| 1925 | fcntl (fileno (TTY_INPUT (tty_out)), F_SETFL, | 1935 | fcntl (fileno (tty_out->input), F_SETFL, |
| 1926 | fcntl (fileno (TTY_INPUT (tty_out)), F_GETFL, 0) & ~O_NDELAY); | 1936 | fcntl (fileno (tty_out->input), F_GETFL, 0) & ~O_NDELAY); |
| 1927 | #endif | 1937 | #endif |
| 1928 | #endif /* F_SETFL */ | 1938 | #endif /* F_SETFL */ |
| 1929 | #ifdef BSD4_1 | 1939 | #ifdef BSD4_1 |
| 1930 | if (interrupt_input) | 1940 | if (interrupt_input) |
| 1931 | reset_sigio (fileno (TTY_INPUT (tty_out))); | 1941 | reset_sigio (fileno (tty_out->input)); |
| 1932 | #endif /* BSD4_1 */ | 1942 | #endif /* BSD4_1 */ |
| 1933 | 1943 | ||
| 1934 | if (tty_out->old_tty) | 1944 | if (tty_out->old_tty) |
| 1935 | while (EMACS_SET_TTY (fileno (TTY_INPUT (tty_out)), | 1945 | while (EMACS_SET_TTY (fileno (tty_out->input), |
| 1936 | tty_out->old_tty, 0) < 0 && errno == EINTR) | 1946 | tty_out->old_tty, 0) < 0 && errno == EINTR) |
| 1937 | ; | 1947 | ; |
| 1938 | 1948 | ||
| @@ -1952,7 +1962,7 @@ reset_sys_modes (tty_out) | |||
| 1952 | #endif | 1962 | #endif |
| 1953 | 1963 | ||
| 1954 | #ifdef BSD_PGRPS | 1964 | #ifdef BSD_PGRPS |
| 1955 | widen_foreground_group (fileno (TTY_INPUT (tty_out))); | 1965 | widen_foreground_group (fileno (tty_out->input)); |
| 1956 | #endif | 1966 | #endif |
| 1957 | } | 1967 | } |
| 1958 | 1968 | ||
| @@ -2017,9 +2027,9 @@ init_vms_input () | |||
| 2017 | { | 2027 | { |
| 2018 | int status; | 2028 | int status; |
| 2019 | 2029 | ||
| 2020 | if (fileno (TTY_INPUT (CURTTY())) == 0) | 2030 | if (fileno (CURTTY ()->input)) == 0) |
| 2021 | { | 2031 | { |
| 2022 | status = SYS$ASSIGN (&input_dsc, &fileno (TTY_INPUT (CURTTY())), 0, 0); | 2032 | status = SYS$ASSIGN (&input_dsc, &fileno (CURTTY ()->input)), 0, 0); |
| 2023 | if (! (status & 1)) | 2033 | if (! (status & 1)) |
| 2024 | LIB$STOP (status); | 2034 | LIB$STOP (status); |
| 2025 | } | 2035 | } |
| @@ -2030,7 +2040,7 @@ init_vms_input () | |||
| 2030 | void | 2040 | void |
| 2031 | stop_vms_input () | 2041 | stop_vms_input () |
| 2032 | { | 2042 | { |
| 2033 | return SYS$DASSGN (fileno (TTY_INPUT (CURTTY()))); | 2043 | return SYS$DASSGN (fileno (CURTTY ()->input))); |
| 2034 | } | 2044 | } |
| 2035 | 2045 | ||
| 2036 | short input_buffer; | 2046 | short input_buffer; |
| @@ -2046,7 +2056,7 @@ queue_kbd_input () | |||
| 2046 | 2056 | ||
| 2047 | waiting_for_ast = 0; | 2057 | waiting_for_ast = 0; |
| 2048 | stop_input = 0; | 2058 | stop_input = 0; |
| 2049 | status = SYS$QIO (0, fileno (TTY_INPUT (CURTTY())), IO$_READVBLK, | 2059 | status = SYS$QIO (0, fileno (CURTTY()->input), IO$_READVBLK, |
| 2050 | &input_iosb, kbd_input_ast, 1, | 2060 | &input_iosb, kbd_input_ast, 1, |
| 2051 | &input_buffer, 1, 0, terminator_mask, 0, 0); | 2061 | &input_buffer, 1, 0, terminator_mask, 0, 0); |
| 2052 | } | 2062 | } |
| @@ -2163,7 +2173,7 @@ end_kbd_input () | |||
| 2163 | #endif | 2173 | #endif |
| 2164 | if (LIB$AST_IN_PROG ()) /* Don't wait if suspending from kbd_buffer_store_event! */ | 2174 | if (LIB$AST_IN_PROG ()) /* Don't wait if suspending from kbd_buffer_store_event! */ |
| 2165 | { | 2175 | { |
| 2166 | SYS$CANCEL (fileno (TTY_INPUT (CURTTY()))); | 2176 | SYS$CANCEL (fileno (CURTTY()->input)); |
| 2167 | return; | 2177 | return; |
| 2168 | } | 2178 | } |
| 2169 | 2179 | ||
| @@ -2172,7 +2182,7 @@ end_kbd_input () | |||
| 2172 | SYS$CLREF (input_ef); | 2182 | SYS$CLREF (input_ef); |
| 2173 | waiting_for_ast = 1; | 2183 | waiting_for_ast = 1; |
| 2174 | stop_input = 1; | 2184 | stop_input = 1; |
| 2175 | SYS$CANCEL (fileno (TTY_INPUT (CURTTY()))); | 2185 | SYS$CANCEL (fileno (CURTTY()->input)); |
| 2176 | SYS$SETAST (1); | 2186 | SYS$SETAST (1); |
| 2177 | SYS$WAITFR (input_ef); | 2187 | SYS$WAITFR (input_ef); |
| 2178 | waiting_for_ast = 0; | 2188 | waiting_for_ast = 0; |
diff --git a/src/term.c b/src/term.c index e3b176c51ea..785f2a3bb33 100644 --- a/src/term.c +++ b/src/term.c | |||
| @@ -106,9 +106,15 @@ void delete_tty_output P_ ((struct frame *)); | |||
| 106 | 106 | ||
| 107 | Lisp_Object Vring_bell_function; | 107 | Lisp_Object Vring_bell_function; |
| 108 | 108 | ||
| 109 | /* Functions to call after a tty was deleted. */ | 109 | /* Functions to call after deleting a tty. */ |
| 110 | Lisp_Object Vdelete_tty_after_functions; | 110 | Lisp_Object Vdelete_tty_after_functions; |
| 111 | 111 | ||
| 112 | /* Functions to call after suspending a tty. */ | ||
| 113 | Lisp_Object Vsuspend_tty_functions; | ||
| 114 | |||
| 115 | /* Functions to call after resuming a tty. */ | ||
| 116 | Lisp_Object Vresume_tty_functions; | ||
| 117 | |||
| 112 | /* Chain of all displays currently in use. */ | 118 | /* Chain of all displays currently in use. */ |
| 113 | struct display *display_list; | 119 | struct display *display_list; |
| 114 | 120 | ||
| @@ -231,10 +237,13 @@ tty_set_terminal_modes (struct display *display) | |||
| 231 | { | 237 | { |
| 232 | struct tty_display_info *tty = display->display_info.tty; | 238 | struct tty_display_info *tty = display->display_info.tty; |
| 233 | 239 | ||
| 234 | OUTPUT_IF (tty, tty->TS_termcap_modes); | 240 | if (tty->output) |
| 235 | OUTPUT_IF (tty, tty->TS_cursor_visible); | 241 | { |
| 236 | OUTPUT_IF (tty, tty->TS_keypad_mode); | 242 | OUTPUT_IF (tty, tty->TS_termcap_modes); |
| 237 | losecursor (tty); | 243 | OUTPUT_IF (tty, tty->TS_cursor_visible); |
| 244 | OUTPUT_IF (tty, tty->TS_keypad_mode); | ||
| 245 | losecursor (tty); | ||
| 246 | } | ||
| 238 | } | 247 | } |
| 239 | 248 | ||
| 240 | /* Reset termcap modes before exiting Emacs. */ | 249 | /* Reset termcap modes before exiting Emacs. */ |
| @@ -243,16 +252,19 @@ void | |||
| 243 | tty_reset_terminal_modes (struct display *display) | 252 | tty_reset_terminal_modes (struct display *display) |
| 244 | { | 253 | { |
| 245 | struct tty_display_info *tty = display->display_info.tty; | 254 | struct tty_display_info *tty = display->display_info.tty; |
| 246 | 255 | ||
| 247 | turn_off_highlight (tty); | 256 | if (tty->output) |
| 248 | turn_off_insert (tty); | 257 | { |
| 249 | OUTPUT_IF (tty, tty->TS_end_keypad_mode); | 258 | turn_off_highlight (tty); |
| 250 | OUTPUT_IF (tty, tty->TS_cursor_normal); | 259 | turn_off_insert (tty); |
| 251 | OUTPUT_IF (tty, tty->TS_end_termcap_modes); | 260 | OUTPUT_IF (tty, tty->TS_end_keypad_mode); |
| 252 | OUTPUT_IF (tty, tty->TS_orig_pair); | 261 | OUTPUT_IF (tty, tty->TS_cursor_normal); |
| 253 | /* Output raw CR so kernel can track the cursor hpos. */ | 262 | OUTPUT_IF (tty, tty->TS_end_termcap_modes); |
| 254 | current_tty = tty; | 263 | OUTPUT_IF (tty, tty->TS_orig_pair); |
| 255 | cmputc ('\r'); | 264 | /* Output raw CR so kernel can track the cursor hpos. */ |
| 265 | current_tty = tty; | ||
| 266 | cmputc ('\r'); | ||
| 267 | } | ||
| 256 | } | 268 | } |
| 257 | 269 | ||
| 258 | void | 270 | void |
| @@ -619,9 +631,9 @@ tty_clear_end_of_line (int first_unused_hpos) | |||
| 619 | 631 | ||
| 620 | for (i = curX (tty); i < first_unused_hpos; i++) | 632 | for (i = curX (tty); i < first_unused_hpos; i++) |
| 621 | { | 633 | { |
| 622 | if (TTY_TERMSCRIPT (tty)) | 634 | if (tty->termscript) |
| 623 | fputc (' ', TTY_TERMSCRIPT (tty)); | 635 | fputc (' ', tty->termscript); |
| 624 | fputc (' ', TTY_OUTPUT (tty)); | 636 | fputc (' ', tty->output); |
| 625 | } | 637 | } |
| 626 | cmplus (tty, first_unused_hpos - curX (tty)); | 638 | cmplus (tty, first_unused_hpos - curX (tty)); |
| 627 | } | 639 | } |
| @@ -807,12 +819,12 @@ tty_write_glyphs (struct glyph *string, int len) | |||
| 807 | if (produced > 0) | 819 | if (produced > 0) |
| 808 | { | 820 | { |
| 809 | fwrite (conversion_buffer, 1, produced, | 821 | fwrite (conversion_buffer, 1, produced, |
| 810 | TTY_OUTPUT (tty)); | 822 | tty->output); |
| 811 | if (ferror (TTY_OUTPUT (tty))) | 823 | if (ferror (tty->output)) |
| 812 | clearerr (TTY_OUTPUT (tty)); | 824 | clearerr (tty->output); |
| 813 | if (TTY_TERMSCRIPT (tty)) | 825 | if (tty->termscript) |
| 814 | fwrite (conversion_buffer, 1, produced, | 826 | fwrite (conversion_buffer, 1, produced, |
| 815 | TTY_TERMSCRIPT (tty)); | 827 | tty->termscript); |
| 816 | } | 828 | } |
| 817 | len -= consumed; | 829 | len -= consumed; |
| 818 | n -= consumed; | 830 | n -= consumed; |
| @@ -833,12 +845,12 @@ tty_write_glyphs (struct glyph *string, int len) | |||
| 833 | if (terminal_coding.produced > 0) | 845 | if (terminal_coding.produced > 0) |
| 834 | { | 846 | { |
| 835 | fwrite (conversion_buffer, 1, terminal_coding.produced, | 847 | fwrite (conversion_buffer, 1, terminal_coding.produced, |
| 836 | TTY_OUTPUT (tty)); | 848 | tty->output); |
| 837 | if (ferror (TTY_OUTPUT (tty))) | 849 | if (ferror (tty->output)) |
| 838 | clearerr (TTY_OUTPUT (tty)); | 850 | clearerr (tty->output); |
| 839 | if (TTY_TERMSCRIPT (tty)) | 851 | if (tty->termscript) |
| 840 | fwrite (conversion_buffer, 1, terminal_coding.produced, | 852 | fwrite (conversion_buffer, 1, terminal_coding.produced, |
| 841 | TTY_TERMSCRIPT (tty)); | 853 | tty->termscript); |
| 842 | } | 854 | } |
| 843 | } | 855 | } |
| 844 | 856 | ||
| @@ -927,12 +939,12 @@ tty_insert_glyphs (struct glyph *start, int len) | |||
| 927 | if (produced > 0) | 939 | if (produced > 0) |
| 928 | { | 940 | { |
| 929 | fwrite (conversion_buffer, 1, produced, | 941 | fwrite (conversion_buffer, 1, produced, |
| 930 | TTY_OUTPUT (tty)); | 942 | tty->output); |
| 931 | if (ferror (TTY_OUTPUT (tty))) | 943 | if (ferror (tty->output)) |
| 932 | clearerr (TTY_OUTPUT (tty)); | 944 | clearerr (tty->output); |
| 933 | if (TTY_TERMSCRIPT (tty)) | 945 | if (tty->termscript) |
| 934 | fwrite (conversion_buffer, 1, produced, | 946 | fwrite (conversion_buffer, 1, produced, |
| 935 | TTY_TERMSCRIPT (tty)); | 947 | tty->termscript); |
| 936 | } | 948 | } |
| 937 | 949 | ||
| 938 | OUTPUT1_IF (tty, tty->TS_pad_inserted_char); | 950 | OUTPUT1_IF (tty, tty->TS_pad_inserted_char); |
| @@ -2240,7 +2252,11 @@ term_init (char *name, char *terminal_type, int must_succeed) | |||
| 2240 | 2252 | ||
| 2241 | display = get_named_tty_display (name); | 2253 | display = get_named_tty_display (name); |
| 2242 | if (display) | 2254 | if (display) |
| 2243 | return display; /* We have already opened a display there. */ | 2255 | { |
| 2256 | if (! display->display_info.tty->input) | ||
| 2257 | error ("%s already has a suspended frame on it, can't open it twice", name); | ||
| 2258 | return display; | ||
| 2259 | } | ||
| 2244 | 2260 | ||
| 2245 | display = create_display (); | 2261 | display = create_display (); |
| 2246 | tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info)); | 2262 | 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.", | |||
| 2550 | /* Get frame size from system, or else from termcap. */ | 2566 | /* Get frame size from system, or else from termcap. */ |
| 2551 | { | 2567 | { |
| 2552 | int height, width; | 2568 | int height, width; |
| 2553 | get_tty_size (fileno (TTY_INPUT (tty)), &width, &height); | 2569 | get_tty_size (fileno (tty->input), &width, &height); |
| 2554 | FrameCols (tty) = width; | 2570 | FrameCols (tty) = width; |
| 2555 | FrameRows (tty) = height; | 2571 | FrameRows (tty) = height; |
| 2556 | } | 2572 | } |
| @@ -2735,7 +2751,7 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", | |||
| 2735 | && tty->TS_end_standout_mode | 2751 | && tty->TS_end_standout_mode |
| 2736 | && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode)); | 2752 | && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode)); |
| 2737 | 2753 | ||
| 2738 | UseTabs (tty) = tabs_safe_p (fileno (TTY_INPUT (tty))) && TabWidth (tty) == 8; | 2754 | UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8; |
| 2739 | 2755 | ||
| 2740 | display->scroll_region_ok | 2756 | display->scroll_region_ok |
| 2741 | = (tty->Wcm->cm_abs | 2757 | = (tty->Wcm->cm_abs |
| @@ -2754,7 +2770,7 @@ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", | |||
| 2754 | 2770 | ||
| 2755 | display->fast_clear_end_of_line = tty->TS_clr_line != 0; | 2771 | display->fast_clear_end_of_line = tty->TS_clr_line != 0; |
| 2756 | 2772 | ||
| 2757 | init_baud_rate (fileno (TTY_INPUT (tty))); | 2773 | init_baud_rate (fileno (tty->input)); |
| 2758 | 2774 | ||
| 2759 | #ifdef AIXHFT | 2775 | #ifdef AIXHFT |
| 2760 | /* The HFT system on AIX doesn't optimize for scrolling, so it's | 2776 | /* The HFT system on AIX doesn't optimize for scrolling, so it's |
| @@ -3067,6 +3083,134 @@ delete_display (struct display *dev) | |||
| 3067 | xfree (dev); | 3083 | xfree (dev); |
| 3068 | } | 3084 | } |
| 3069 | 3085 | ||
| 3086 | |||
| 3087 | |||
| 3088 | DEFUN ("suspend-tty", Fsuspend_tty, Ssuspend_tty, 0, 1, 0, | ||
| 3089 | doc: /* Suspend the terminal device TTY. | ||
| 3090 | The terminal is restored to its default state, and Emacs closes all | ||
| 3091 | access to the terminal device. Frames that use the device are not | ||
| 3092 | deleted, but input is not read from them and if they change, their | ||
| 3093 | display is not updated. | ||
| 3094 | |||
| 3095 | TTY may a string (a device name), a frame, or nil for the display | ||
| 3096 | device of the currently selected frame. | ||
| 3097 | |||
| 3098 | This function runs `suspend-tty-functions' after suspending the | ||
| 3099 | device. The functions are run with one arg, the name of the terminal | ||
| 3100 | device. | ||
| 3101 | |||
| 3102 | `suspend-tty' does nothing if it is called on an already suspended | ||
| 3103 | device. | ||
| 3104 | |||
| 3105 | A suspended terminal device may be resumed by calling `resume-tty' on | ||
| 3106 | it. */) | ||
| 3107 | (tty) | ||
| 3108 | Lisp_Object tty; | ||
| 3109 | { | ||
| 3110 | struct display *d = get_tty_display (tty); | ||
| 3111 | FILE *f; | ||
| 3112 | |||
| 3113 | if (!d) | ||
| 3114 | error ("Unknown tty device"); | ||
| 3115 | |||
| 3116 | f = d->display_info.tty->input; | ||
| 3117 | |||
| 3118 | if (f) | ||
| 3119 | { | ||
| 3120 | reset_sys_modes (d->display_info.tty); | ||
| 3121 | |||
| 3122 | delete_keyboard_wait_descriptor (fileno (f)); | ||
| 3123 | |||
| 3124 | fclose (f); | ||
| 3125 | if (f != d->display_info.tty->output) | ||
| 3126 | fclose (d->display_info.tty->output); | ||
| 3127 | |||
| 3128 | d->display_info.tty->input = 0; | ||
| 3129 | d->display_info.tty->output = 0; | ||
| 3130 | |||
| 3131 | if (FRAMEP (d->display_info.tty->top_frame)) | ||
| 3132 | FRAME_SET_VISIBLE (XFRAME (d->display_info.tty->top_frame), 0); | ||
| 3133 | |||
| 3134 | /* Run `suspend-tty-functions'. */ | ||
| 3135 | if (!NILP (Vrun_hooks)) | ||
| 3136 | { | ||
| 3137 | Lisp_Object args[2]; | ||
| 3138 | args[0] = intern ("suspend-tty-functions"); | ||
| 3139 | if (d->display_info.tty->name) | ||
| 3140 | { | ||
| 3141 | args[1] = build_string (d->display_info.tty->name); | ||
| 3142 | } | ||
| 3143 | else | ||
| 3144 | args[1] = Qnil; | ||
| 3145 | Frun_hook_with_args (2, args); | ||
| 3146 | } | ||
| 3147 | } | ||
| 3148 | |||
| 3149 | return Qnil; | ||
| 3150 | } | ||
| 3151 | |||
| 3152 | |||
| 3153 | DEFUN ("resume-tty", Fresume_tty, Sresume_tty, 0, 1, 0, | ||
| 3154 | doc: /* Resume the previously suspended terminal device TTY. | ||
| 3155 | The terminal is opened and reinitialized. Frames that used the | ||
| 3156 | suspended device are revived. | ||
| 3157 | |||
| 3158 | This function runs `resume-tty-functions' after resuming the device. | ||
| 3159 | The functions are run with one arg, the name of the terminal device. | ||
| 3160 | |||
| 3161 | `resume-tty' does nothing if it is called on a device that is not | ||
| 3162 | suspended. | ||
| 3163 | |||
| 3164 | TTY may a string (a device name), a frame, or nil for the display | ||
| 3165 | device of the currently selected frame. */) | ||
| 3166 | (tty) | ||
| 3167 | Lisp_Object tty; | ||
| 3168 | { | ||
| 3169 | struct display *d = get_tty_display (tty); | ||
| 3170 | int fd; | ||
| 3171 | |||
| 3172 | if (!d) | ||
| 3173 | error ("Unknown tty device"); | ||
| 3174 | |||
| 3175 | if (!d->display_info.tty->input) | ||
| 3176 | { | ||
| 3177 | fd = emacs_open (d->display_info.tty->name, O_RDWR | O_NOCTTY, 0); | ||
| 3178 | |||
| 3179 | #ifdef TIOCNOTTY | ||
| 3180 | /* Drop our controlling tty if it is the same device. */ | ||
| 3181 | if (ioctl (fd, TIOCNOTTY, 0) != -1) | ||
| 3182 | { | ||
| 3183 | no_controlling_tty = 1; | ||
| 3184 | } | ||
| 3185 | #endif | ||
| 3186 | |||
| 3187 | d->display_info.tty->output = fdopen (fd, "w+"); | ||
| 3188 | d->display_info.tty->input = d->display_info.tty->output; | ||
| 3189 | |||
| 3190 | add_keyboard_wait_descriptor (fd); | ||
| 3191 | |||
| 3192 | if (FRAMEP (d->display_info.tty->top_frame)) | ||
| 3193 | FRAME_SET_VISIBLE (XFRAME (d->display_info.tty->top_frame), 1); | ||
| 3194 | |||
| 3195 | init_sys_modes (d->display_info.tty); | ||
| 3196 | |||
| 3197 | /* Run `suspend-tty-functions'. */ | ||
| 3198 | if (!NILP (Vrun_hooks)) | ||
| 3199 | { | ||
| 3200 | Lisp_Object args[2]; | ||
| 3201 | args[0] = intern ("resume-tty-functions"); | ||
| 3202 | if (d->display_info.tty->name) | ||
| 3203 | { | ||
| 3204 | args[1] = build_string (d->display_info.tty->name); | ||
| 3205 | } | ||
| 3206 | else | ||
| 3207 | args[1] = Qnil; | ||
| 3208 | Frun_hook_with_args (2, args); | ||
| 3209 | } | ||
| 3210 | } | ||
| 3211 | |||
| 3212 | return Qnil; | ||
| 3213 | } | ||
| 3070 | 3214 | ||
| 3071 | 3215 | ||
| 3072 | void | 3216 | void |
| @@ -3092,6 +3236,20 @@ The functions are run with one argument, the name of the tty to be deleted. | |||
| 3092 | See `delete-tty'. */); | 3236 | See `delete-tty'. */); |
| 3093 | Vdelete_tty_after_functions = Qnil; | 3237 | Vdelete_tty_after_functions = Qnil; |
| 3094 | 3238 | ||
| 3239 | |||
| 3240 | DEFVAR_LISP ("suspend-tty-functions", &Vsuspend_tty_functions, | ||
| 3241 | doc: /* Functions to be run after suspending a tty. | ||
| 3242 | The functions are run with one argument, the name of the tty to be suspended. | ||
| 3243 | See `suspend-tty'. */); | ||
| 3244 | Vsuspend_tty_functions = Qnil; | ||
| 3245 | |||
| 3246 | |||
| 3247 | DEFVAR_LISP ("resume-tty-functions", &Vresume_tty_functions, | ||
| 3248 | doc: /* Functions to be run after resuming a tty. | ||
| 3249 | The functions are run with one argument, the name of the tty that was revived. | ||
| 3250 | See `resume-tty'. */); | ||
| 3251 | Vresume_tty_functions = Qnil; | ||
| 3252 | |||
| 3095 | Qframe_tty_name = intern ("frame-tty-name"); | 3253 | Qframe_tty_name = intern ("frame-tty-name"); |
| 3096 | staticpro (&Qframe_tty_name); | 3254 | staticpro (&Qframe_tty_name); |
| 3097 | 3255 | ||
| @@ -3103,6 +3261,8 @@ See `delete-tty'. */); | |||
| 3103 | defsubr (&Sframe_tty_name); | 3261 | defsubr (&Sframe_tty_name); |
| 3104 | defsubr (&Sframe_tty_type); | 3262 | defsubr (&Sframe_tty_type); |
| 3105 | defsubr (&Sdelete_tty); | 3263 | defsubr (&Sdelete_tty); |
| 3264 | defsubr (&Ssuspend_tty); | ||
| 3265 | defsubr (&Sresume_tty); | ||
| 3106 | 3266 | ||
| 3107 | Fprovide (intern ("multi-tty"), Qnil); | 3267 | Fprovide (intern ("multi-tty"), Qnil); |
| 3108 | 3268 | ||
diff --git a/src/termchar.h b/src/termchar.h index fbf91f2458f..3053061c1b7 100644 --- a/src/termchar.h +++ b/src/termchar.h | |||
| @@ -42,8 +42,10 @@ struct tty_display_info | |||
| 42 | 42 | ||
| 43 | /* Input/output */ | 43 | /* Input/output */ |
| 44 | 44 | ||
| 45 | FILE *input; /* The stream to be used for terminal input. */ | 45 | FILE *input; /* The stream to be used for terminal input. |
| 46 | FILE *output; /* The stream to be used for terminal output. */ | 46 | NULL if the terminal is suspended. */ |
| 47 | FILE *output; /* The stream to be used for terminal output. | ||
| 48 | NULL if the terminal is suspended. */ | ||
| 47 | 49 | ||
| 48 | FILE *termscript; /* If nonzero, send all terminal output | 50 | FILE *termscript; /* If nonzero, send all terminal output |
| 49 | characters to this stream also. */ | 51 | characters to this stream also. */ |
| @@ -200,9 +202,5 @@ extern struct tty_display_info *tty_list; | |||
| 200 | 202 | ||
| 201 | #define CURTTY() FRAME_TTY (SELECTED_FRAME()) | 203 | #define CURTTY() FRAME_TTY (SELECTED_FRAME()) |
| 202 | 204 | ||
| 203 | #define TTY_INPUT(t) ((t)->input) | ||
| 204 | #define TTY_OUTPUT(t) ((t)->output) | ||
| 205 | #define TTY_TERMSCRIPT(t) ((t)->termscript) | ||
| 206 | |||
| 207 | /* arch-tag: bf9f0d49-842b-42fb-9348-ec8759b27193 | 205 | /* arch-tag: bf9f0d49-842b-42fb-9348-ec8759b27193 |
| 208 | (do not change this comment) */ | 206 | (do not change this comment) */ |
diff --git a/src/termhooks.h b/src/termhooks.h index c79e77379b1..6b2b0d07867 100644 --- a/src/termhooks.h +++ b/src/termhooks.h | |||
| @@ -513,7 +513,6 @@ struct display | |||
| 513 | frames on the display when it calls this hook, so infinite | 513 | frames on the display when it calls this hook, so infinite |
| 514 | recursion is prevented. */ | 514 | recursion is prevented. */ |
| 515 | void (*delete_display_hook) P_ ((struct display *)); | 515 | void (*delete_display_hook) P_ ((struct display *)); |
| 516 | |||
| 517 | }; | 516 | }; |
| 518 | 517 | ||
| 519 | 518 | ||