aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaroly Lorentey2003-12-31 05:09:29 +0000
committerKaroly Lorentey2003-12-31 05:09:29 +0000
commit819b8f00ed7b8a9a2190efaa02376ed332ecf763 (patch)
treec30ab72204225385c428db008580a9f67f5c215c
parent16c290d8c16fb0fdb574c837c6b1badbc655efe2 (diff)
downloademacs-819b8f00ed7b8a9a2190efaa02376ed332ecf763.tar.gz
emacs-819b8f00ed7b8a9a2190efaa02376ed332ecf763.zip
A few more bugfixes and new features.
(Sigh.) I obviously need to remember to separate individual changes to multiple commits. src/emacsclient.c: Improved error handling. (decode_options): Changed frame option (again) from -f to -t. (print_help_and_exit): Ditto. (copy_from_to): Check EINTR after write, not EAGAIN. Removed SIGIO hack. (pty_conversation): Handle errors transmitted through the socket. Handle pty errors by not reading from it anymore. (main): Restore correct errno after socket_status failed. Send -tty on -t, not -pty. lisp/server.el (server-process-filter): Watch -tty, not -pty. Use make-frame-on-tty instead of make-terminal-frame. Don't set newframe to t if make-frame-on-tty failed. Don't delete frames here. Print correct message when there are no files to edit, but a new frame was requested. (server-sentinel): Delete the frame after the process. (server-handle-delete-frame): New function for delete-frame-functions. (server-start): Add server-handle-delete-frame to delete-frame-functions. (server-buffer-done): Don't delete frames here. src/alloc.c (mark_ttys): Add prototype. (Fgarbage_collect): Call mark_ttys. src/emacs.c: (shut_down_emacs): Don't flush stdout before reset_sys_modes(). src/process.c (add_keyboard_wait_descriptor_called_flag): Removed. (add_keyboard_wait_descriptor): Removed stdin hack. src/sysdep.c: Unconditionally include sysselect.h. (old_fcntl_flags): Changed to an array. (init_sigio, reset_sigio): Use it. (narrow_foreground_group, widen_foreground_group): Use setpgid, not setpgrp. (old_fcntl_owner): Changed to an array. (init_sys_modes, reset_sys_modes): Use it. Fix fsync() and reset_sigio() calls. src/term.c (Qframe_tty_name, Qframe_tty_type): New variables. (syms_of_term): Initialize them. (Fframe_tty_name, Fframe_tty_type): New functions. (term_init): Call add_keyboard_wait_descriptor(). (Fdelete_tty): New function. (delete_tty): Call delete_keyboard_wait_descriptor(). (get_current_tty): Removed. (mark_ttys): New function. git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-28
-rw-r--r--README.multi-tty118
-rw-r--r--lib-src/emacsclient.c150
-rw-r--r--lisp/server.el52
-rw-r--r--src/alloc.c2
-rw-r--r--src/emacs.c1
-rw-r--r--src/process.c14
-rw-r--r--src/sysdep.c39
-rw-r--r--src/term.c163
8 files changed, 367 insertions, 172 deletions
diff --git a/README.multi-tty b/README.multi-tty
index 2ee943b6ed5..4519be4e756 100644
--- a/README.multi-tty
+++ b/README.multi-tty
@@ -45,15 +45,13 @@ You'll hopefully have two fully working, independent frames on
45separate terminals. (This seems to be very useful, emacsclient starts 45separate terminals. (This seems to be very useful, emacsclient starts
46up even faster than vi!) :-) You can close the newly opened frame and 46up even faster than vi!) :-) You can close the newly opened frame and
47return to the shell without exiting Emacs by pressing C-x 5 0, i.e., 47return to the shell without exiting Emacs by pressing C-x 5 0, i.e.,
48delete-frame. (Note that this does not seem to work yet on the 48delete-frame. Creating new frames on the same tty with C-x 5 2
49original terminal.) Creating new frames on the same tty with C-x 5 2
50works exactly as before. Suspending Emacs is disabled at the moment. 49works exactly as before. Suspending Emacs is disabled at the moment.
51If you exit emacs, all terminals should be restored to their previous 50If you exit emacs, all terminals should be restored to their previous
52states. 51states.
53 52
54X, Mac, Windows and DOS support is broken, probably doesn't even 53X, Mac, Windows and DOS support is broken, probably doesn't even
55compile -- this will be solved later. Please see the attached README 54compile -- this will be solved later.
56for other issues, implementation notes and sub-TODO items.
57 55
58Only tested on my GNU/Linux box. 56Only tested on my GNU/Linux box.
59 57
@@ -75,6 +73,10 @@ For the NEWS file:
75** A make-frame-on-tty function has been added to make it easier to 73** A make-frame-on-tty function has been added to make it easier to
76 create frames on new terminals. 74 create frames on new terminals.
77 75
76** New functions: frame-tty-name, frame-tty-type for accessing
77 terminal parameters, and delete-tty for closing the terminal
78 device.
79
78** Emacsclient has been extended to support opening a new terminal 80** Emacsclient has been extended to support opening a new terminal
79 frame. 81 frame.
80 82
@@ -108,6 +110,8 @@ DIARY OF CHANGES
108 succeeds. MULTIKBOARD is not used. Secondary terminals don't send 110 succeeds. MULTIKBOARD is not used. Secondary terminals don't send
109 SIGIO!) 111 SIGIO!)
110 112
113 (Update: They do, now.)
114
111-- other-frame should cycle through the frames on the `current' 115-- other-frame should cycle through the frames on the `current'
112 terminal only. 116 terminal only.
113 117
@@ -159,6 +163,10 @@ DIARY OF CHANGES
159 (Update: This is bullshit. There is a read_input_waiting function, 163 (Update: This is bullshit. There is a read_input_waiting function,
160 extend that somehow.) 164 extend that somehow.)
161 165
166 (Update of update: The first update was not right either, extending
167 read_input_waiting was not necessary. Secondary ttys do seem to
168 send signals on input.)
169
162-- Make make-terminal-frame look up the `tty' and `tty-type' frame 170-- Make make-terminal-frame look up the `tty' and `tty-type' frame
163 parameters from the currently selected terminal before the global 171 parameters from the currently selected terminal before the global
164 default. 172 default.
@@ -231,56 +239,67 @@ DIARY OF CHANGES
231 free()ing memory. Utterly trivial matter. I love the C's memory 239 free()ing memory. Utterly trivial matter. I love the C's memory
232 management, it puts hair on your chest.) 240 management, it puts hair on your chest.)
233 241
234THINGS TO DO 242-- Support raw secondary terminals. (Note that SIGIO works only on
235------------ 243 the controlling terminal.) Hint: extend read_input_waiting() for
244 multiple ttys and hopefully this will be fixed.
236 245
237** Understand Emacs's low-level input system (it seems complicated) :-) 246 (Done, it seems to have been working already for some time. It
238 and maybe rewrite multi-tty input in terms of MULTIKBOARD. 247 seems F_SETOWN does work, after all. Not sure what made it fail
248 earlier, but it seems to be fixed (there were several changes
249 around request_sigio, maybe one of them did it).
250 read_input_waiting() is only used in sys_select(), don't change
251 it.)
239 252
240** Find out why does Emacs abort when it wants to close its 253-- Find out why does Emacs abort when it wants to close its
241 controlling tty. Hint: chan_process[] array. Hey, maybe 254 controlling tty. Hint: chan_process[] array. Hey, maybe
242 noninterrupt-IO would work, too? Update: no, there is no process 255 noninterrupt-IO would work, too? Update: no, there is no process
243 for stdin/out. 256 for stdin/out.
244 257
245** Support raw secondary terminals. (Note that SIGIO works only on 258 (Done. Added add/delete_keyboard_wait_descriptor to
246 the controlling terminal.) Hint: extend read_input_waiting() for 259 term_init/delete_tty. The hint was right, in a way.)
247 multiple ttys and hopefully this will be fixed.
248
249** What does interrupt_input do? I tried to disable it for raw
250 secondary tty support, but it does not seem to do anything useful.
251 260
252** Issue with SIGIO: it needs to be disabled during redisplay. See if 261-- Issue with SIGIO: it needs to be disabled during redisplay. See if
253 fcntl() kernel behaviour could be emulated by emacsclient. 262 fcntl() kernel behaviour could be emulated by emacsclient.
254 263
255** Get rid of the accessor macros in termchar.h, or define macros for 264 (Done. Simply disabled the SIGIO emulation hack in emacsclient.)
256 all members.
257
258** Make parts of struct tty_output accessible from Lisp. The device
259 name and the type is sufficient.
260 265
261** server.el: There are issues with saving files in buffers of closed 266-- server.el: There are issues with saving files in buffers of closed
262 clients. Try editing a file with emacsclient -f, and (without 267 clients. Try editing a file with emacsclient -f, and (without
263 saving it) do a delete-frame. The frame is closed without 268 saving it) do a delete-frame. The frame is closed without
264 question, and a surprising confirmation prompt appears in another 269 question, and a surprising confirmation prompt appears in another
265 frame. 270 frame.
266 271
267** emacsclient.el, server.el: Handle eval or file open errors when 272 (Done. delete-frame now asks for confirmation if it still has
273 pending buffers, and modified buffers don't seem to be deleted.)
274
275-- emacsclient.el, server.el: Handle eval or file open errors when
268 doing -f. 276 doing -f.
269 277
270** Export delete_tty to the Lisp environment, for emacsclient. 278 (Done.)
271 279
272** Make sure C-g goes to the right frame. This is hard, as SIGINT 280-- Make parts of struct tty_output accessible from Lisp. The device
273 doesn't have a tty parameter. :-( 281 name and the type is sufficient.
274 282
275** Implement support for starting an interactive Emacs session without 283 (Done, see frame-tty-name and frame-tty-type.)
276 an initial frame. (The user would connect to it and open frames 284
277 later, with emacsclient.) Not necessarily a good idea. 285-- Export delete_tty to the Lisp environment, for emacsclient.
278 286
279** Move optimalization parameters (costs) from union output_data to 287 (Done, see delete-tty.)
280 a backend-neutral per-device structure. 288
289
290THINGS TO DO
291------------
281 292
282** Find out the best way to support suspending Emacs with multiple 293** Find out the best way to support suspending Emacs with multiple
283 ttys. 294 ttys. My guess: disable it on the controlling tty, but other ttys
295 should pass it on to emacsclient somehow. (It is (I hope) trivial
296 to extend emacsclient to handle suspend/resume. A `kill -STOP'
297 almost works right now.)
298
299** Move baud_rate to tty_output.
300
301** Move device-specific parameters (like costs) commonly used by
302 device backends to a common, device-dependent structure.
284 303
285** Do tty output through term_hooks, like graphical display backends. 304** Do tty output through term_hooks, like graphical display backends.
286 305
@@ -289,6 +308,10 @@ THINGS TO DO
289** Allow simultaneous X and tty frames. (Handling input could be 308** Allow simultaneous X and tty frames. (Handling input could be
290 tricky.) 309 tricky.)
291 310
311** Implement support for starting an interactive Emacs session without
312 an initial frame. (The user would connect to it and open frames
313 later, with emacsclient.) Not necessarily a good idea.
314
292** Fix Mac support (I can't do this myself). 315** Fix Mac support (I can't do this myself).
293 316
294** Fix W32 support (I can't do this myself). 317** Fix W32 support (I can't do this myself).
@@ -297,4 +320,35 @@ THINGS TO DO
297 320
298** Do a grep on XXX and ?? for more issues. 321** Do a grep on XXX and ?? for more issues.
299 322
323** Get rid of the accessor macros in termchar.h, or define macros for
324 all members.
325
326** Understand Emacs's low-level input system (it seems complicated) :-)
327 and maybe rewrite multi-tty input in terms of MULTIKBOARD.
328
329** What does interrupt_input do? I tried to disable it for raw
330 secondary tty support, but it does not seem to do anything useful.
331
332** Make sure C-g goes to the right frame. This is hard, as SIGINT
333 doesn't have a tty parameter. :-(
334
335** I have seen a case when Emacs with multiple ttys went ate 100% of
336 CPU time. Strace showed this loop:
337
338
339 getpid() = 30284
340 kill(30284, SIGIO) = 0
341 --- SIGIO (I/O possible) @ 0 (0) ---
342 ioctl(6, FIONREAD, [0]) = -1 EIO (Input/output error)
343 ioctl(5, FIONREAD, [0]) = -1 EIO (Input/output error)
344 ioctl(0, FIONREAD, [0]) = 0
345 sigreturn() = ? (mask now [])
346 gettimeofday({1072842297, 747760}, NULL) = 0
347 gettimeofday({1072842297, 747806}, NULL) = 0
348 select(9, [0 3 5 6], NULL, NULL, {0, 0}) = 2 (in [5 6], left {0, 0})
349 select(9, [0 3 5 6], NULL, NULL, {0, 0}) = 2 (in [5 6], left {0, 0})
350 gettimeofday({1072842297, 748245}, NULL) = 0
351
352 I have not been able to reproduce this.
353
300;;; arch-tag: 8da1619e-2e79-41a8-9ac9-a0485daad17d 354;;; arch-tag: 8da1619e-2e79-41a8-9ac9-a0485daad17d
diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c
index 9f08e4dac37..544bebeaeda 100644
--- a/lib-src/emacsclient.c
+++ b/lib-src/emacsclient.c
@@ -153,7 +153,7 @@ decode_options (argc, argv)
153 while (1) 153 while (1)
154 { 154 {
155 int opt = getopt_long (argc, argv, 155 int opt = getopt_long (argc, argv,
156 "VHnea:s:d:f", longopts, 0); 156 "VHnea:s:d:t", longopts, 0);
157 157
158 if (opt == EOF) 158 if (opt == EOF)
159 break; 159 break;
@@ -192,7 +192,7 @@ decode_options (argc, argv)
192 exit (0); 192 exit (0);
193 break; 193 break;
194 194
195 case 'f': 195 case 't':
196 frame = 1; 196 frame = 1;
197 break; 197 break;
198 198
@@ -225,7 +225,7 @@ Every FILE can be either just a FILENAME or [+LINE[:COLUMN]] FILENAME.\n\
225The following OPTIONS are accepted:\n\ 225The following OPTIONS are accepted:\n\
226-V, --version Just print a version info and return\n\ 226-V, --version Just print a version info and return\n\
227-H, --help Print this usage information message\n\ 227-H, --help Print this usage information message\n\
228-f, --frame Open a new Emacs frame on the current terminal\n\ 228-t, --tty Open a new Emacs frame on the current terminal\n\
229-n, --no-wait Don't wait for the server to return\n\ 229-n, --no-wait Don't wait for the server to return\n\
230-e, --eval Evaluate the FILE arguments as ELisp expressions\n\ 230-e, --eval Evaluate the FILE arguments as ELisp expressions\n\
231-d, --display=DISPLAY Visit the file in the given display\n\ 231-d, --display=DISPLAY Visit the file in the given display\n\
@@ -300,7 +300,7 @@ xmalloc (size)
300 defined-- exit with an errorcode. 300 defined-- exit with an errorcode.
301*/ 301*/
302void 302void
303fail () 303fail (void)
304{ 304{
305 if (alternate_editor) 305 if (alternate_editor)
306 { 306 {
@@ -720,14 +720,14 @@ init_pty ()
720} 720}
721 721
722int 722int
723copy_from_to (int in, int out, int sigio) 723copy_from_to (int in, int out)
724{ 724{
725 static char buf[BUFSIZ]; 725 static char buf[BUFSIZ];
726 int nread = read (in, &buf, BUFSIZ); 726 int nread = read (in, &buf, BUFSIZ);
727 if (nread == 0) 727 if (nread == 0)
728 return 1; /* EOF */ 728 return 1; /* EOF */
729 else if (nread < 0 && errno != EAGAIN) 729 else if (nread < 0 && errno != EAGAIN)
730 return 0; /* Error */ 730 return 0;
731 else if (nread > 0) 731 else if (nread > 0)
732 { 732 {
733 int r = 0; 733 int r = 0;
@@ -735,16 +735,11 @@ copy_from_to (int in, int out, int sigio)
735 735
736 do { 736 do {
737 r = write (out, &buf, nread); 737 r = write (out, &buf, nread);
738 } while ((r < 0 && errno == EAGAIN) 738 } while ((r < 0 && errno == EINTR)
739 || (r > 0 && (written += r) && written != nread)); 739 || (r > 0 && (written += r) && written != nread));
740 740
741 if (r < 0) 741 if (r < 0)
742 return 0; /* Error */ 742 return 0;
743
744 if (emacs_pid && sigio)
745 {
746 kill (emacs_pid, SIGIO);
747 }
748 } 743 }
749 return 1; 744 return 1;
750} 745}
@@ -754,53 +749,85 @@ pty_conversation (FILE *in)
754{ 749{
755 char *str; 750 char *str;
756 char string[BUFSIZ]; 751 char string[BUFSIZ];
757 fd_set set; 752 fd_set set, rset;
753 int res;
754
755 FD_ZERO (&set);
756 FD_SET (master, &set);
757 FD_SET (1, &set);
758 FD_SET (fileno (in), &set);
758 759
759 in_conversation = 1; 760 in_conversation = 1;
760 761
761 while (! quit_conversation) { 762 while (! quit_conversation) {
762 int res; 763 rset = set;
763 764 res = select (FD_SETSIZE, &rset, NULL, NULL, NULL);
764 FD_ZERO (&set); 765 if (res < 0 && errno != EINTR)
765 FD_SET (master, &set);
766 FD_SET (1, &set);
767 FD_SET (fileno (in), &set);
768 res = select (FD_SETSIZE, &set, NULL, NULL, NULL);
769 if (res < 0)
770 { 766 {
771 if (errno != EINTR) 767 reset_tty ();
772 return 0; 768 fprintf (stderr, "%s: ", progname);
769 perror ("select");
770 return 0; /* Error */
773 } 771 }
774 else if (res > 0) 772 else if (res > 0)
775 { 773 {
776 if (FD_ISSET (master, &set)) 774 if (FD_ISSET (master, &rset))
777 { 775 {
778 /* Copy Emacs output to stdout. */ 776 /* Copy Emacs output to stdout. */
779 if (! copy_from_to (master, 0, 0)) 777 if (! copy_from_to (master, 0))
780 return 1; 778 {
779 FD_CLR (master, &set);
780 }
781 } 781 }
782 if (FD_ISSET (1, &set)) 782 if (FD_ISSET (1, &rset))
783 { 783 {
784 /* Forward user input to Emacs. */ 784 /* Forward user input to Emacs. */
785 if (! copy_from_to (1, master, 1)) 785 if (! copy_from_to (1, master))
786 return 1; 786 {
787 FD_CLR (master, &set);
788 }
787 } 789 }
788 if (FD_ISSET (fileno (in), &set)) 790 if (FD_ISSET (fileno (in), &rset))
789 { 791 {
792 do {
793 res = read (fileno (in), string, BUFSIZ-1);
794 } while (res == EINTR);
795 if (res < 0)
796 {
797 reset_tty ();
798 fprintf (stderr, "%s: ", progname);
799 perror ("read");
800 return 0;
801 }
802 if (!res)
803 {
804 return 1;
805 }
806
807 string[res] = 0;
808 if (string[res-1] == '\n')
809 string[res-1] = 0;
810
790 if (! emacs_pid) 811 if (! emacs_pid)
791 { 812 {
792 /* Get the pid of the Emacs process. 813 /* Get the pid of the Emacs process.
793 XXX Is there is some nifty libc/kernel feature for doing this? 814 XXX Is there some nifty libc/kernel feature for doing this?
794 */ 815 */
795 str = fgets (string, BUFSIZ, in); 816 if (! string[0])
796 if (! str)
797 { 817 {
798 reset_tty (); 818 reset_tty ();
799 fprintf (stderr, "%s: %s\n", progname, str); 819 fprintf (stderr, "%s: could not get Emacs process id\n"
800 fail (); 820 "Maybe this Emacs does not support multiple terminals.\n", progname);
821 return 0;
801 } 822 }
802 823 emacs_pid = strtol (string, NULL, 10);
803 emacs_pid = atoi (str); 824 }
825
826 if (! emacs_pid) /* emacs_pid should be set above */
827 {
828 reset_tty ();
829 fprintf (stderr, "%s: %s\n", progname, string);
830 return 0;
804 } 831 }
805 } 832 }
806 } 833 }
@@ -822,7 +849,7 @@ main (argc, argv)
822 argv[0]); 849 argv[0]);
823 fprintf (stderr, "on systems with Berkeley sockets.\n"); 850 fprintf (stderr, "on systems with Berkeley sockets.\n");
824 851
825 fail (argc, argv); 852 fail ();
826} 853}
827 854
828#else /* HAVE_SOCKETS */ 855#else /* HAVE_SOCKETS */
@@ -891,7 +918,7 @@ main (argc, argv)
891 { 918 {
892 fprintf (stderr, "%s: ", argv[0]); 919 fprintf (stderr, "%s: ", argv[0]);
893 perror ("socket"); 920 perror ("socket");
894 fail (argc, argv); 921 fail ();
895 } 922 }
896 923
897 server.sun_family = AF_UNIX; 924 server.sun_family = AF_UNIX;
@@ -922,7 +949,8 @@ main (argc, argv)
922 949
923 { 950 {
924 int sock_status = 0; 951 int sock_status = 0;
925 952 int oerrno = 0;
953
926 if (! socket_name) 954 if (! socket_name)
927 { 955 {
928 socket_name = alloca (system_name_length + 100); 956 socket_name = alloca (system_name_length + 100);
@@ -933,11 +961,15 @@ main (argc, argv)
933 if (strlen (socket_name) < sizeof (server.sun_path)) 961 if (strlen (socket_name) < sizeof (server.sun_path))
934 strcpy (server.sun_path, socket_name); 962 strcpy (server.sun_path, socket_name);
935 else 963 else
936 fprintf (stderr, "%s: socket-name %s too long", 964 {
937 argv[0], socket_name); 965 fprintf (stderr, "%s: socket-name %s too long",
966 argv[0], socket_name);
967 fail ();
968 }
938 969
939 /* See if the socket exists, and if it's owned by us. */ 970 /* See if the socket exists, and if it's owned by us. */
940 sock_status = socket_status (server.sun_path); 971 sock_status = socket_status (server.sun_path);
972 oerrno = errno;
941 if (sock_status) 973 if (sock_status)
942 { 974 {
943 /* Failing that, see if LOGNAME or USER exist and differ from 975 /* Failing that, see if LOGNAME or USER exist and differ from
@@ -958,6 +990,7 @@ main (argc, argv)
958 sprintf (server.sun_path, "/tmp/esrv%d-%s", 990 sprintf (server.sun_path, "/tmp/esrv%d-%s",
959 (int) pw->pw_uid, system_name); 991 (int) pw->pw_uid, system_name);
960 sock_status = socket_status (server.sun_path); 992 sock_status = socket_status (server.sun_path);
993 oerrno = errno;
961 } 994 }
962 } 995 }
963 } 996 }
@@ -970,7 +1003,7 @@ main (argc, argv)
970 if (0 != geteuid ()) 1003 if (0 != geteuid ())
971 { 1004 {
972 fprintf (stderr, "%s: Invalid socket owner\n", argv[0]); 1005 fprintf (stderr, "%s: Invalid socket owner\n", argv[0]);
973 fail (argc, argv); 1006 fail ();
974 } 1007 }
975 break; 1008 break;
976 1009
@@ -978,13 +1011,13 @@ main (argc, argv)
978 /* `stat' failed */ 1011 /* `stat' failed */
979 if (errno == ENOENT) 1012 if (errno == ENOENT)
980 fprintf (stderr, 1013 fprintf (stderr,
981 "%s: can't find socket; have you started the server?\n\ 1014 "%s: Can't find socket; have you started the server?\n\
982To start the server in Emacs, type \"M-x server-start\".\n", 1015To start the server in Emacs, type \"M-x server-start\".\n",
983 argv[0]); 1016 argv[0]);
984 else 1017 else
985 fprintf (stderr, "%s: can't stat %s: %s\n", 1018 fprintf (stderr, "%s: Can't stat %s: %s\n",
986 argv[0], server.sun_path, strerror (errno)); 1019 argv[0], server.sun_path, strerror (oerrno));
987 fail (argc, argv); 1020 fail ();
988 break; 1021 break;
989 } 1022 }
990 } 1023 }
@@ -994,7 +1027,7 @@ To start the server in Emacs, type \"M-x server-start\".\n",
994 { 1027 {
995 fprintf (stderr, "%s: ", argv[0]); 1028 fprintf (stderr, "%s: ", argv[0]);
996 perror ("connect"); 1029 perror ("connect");
997 fail (argc, argv); 1030 fail ();
998 } 1031 }
999 1032
1000 /* We use the stream OUT to send our command to the server. */ 1033 /* We use the stream OUT to send our command to the server. */
@@ -1002,7 +1035,7 @@ To start the server in Emacs, type \"M-x server-start\".\n",
1002 { 1035 {
1003 fprintf (stderr, "%s: ", argv[0]); 1036 fprintf (stderr, "%s: ", argv[0]);
1004 perror ("fdopen"); 1037 perror ("fdopen");
1005 fail (argc, argv); 1038 fail ();
1006 } 1039 }
1007 1040
1008 /* We use the stream IN to read the response. 1041 /* We use the stream IN to read the response.
@@ -1014,7 +1047,7 @@ To start the server in Emacs, type \"M-x server-start\".\n",
1014 { 1047 {
1015 fprintf (stderr, "%s: ", argv[0]); 1048 fprintf (stderr, "%s: ", argv[0]);
1016 perror ("fdopen"); 1049 perror ("fdopen");
1017 fail (argc, argv); 1050 fail ();
1018 } 1051 }
1019 1052
1020#ifdef HAVE_GETCWD 1053#ifdef HAVE_GETCWD
@@ -1032,7 +1065,7 @@ To start the server in Emacs, type \"M-x server-start\".\n",
1032#else 1065#else
1033 fprintf (stderr, "%s: %s (%s)\n", argv[0], string, strerror (errno)); 1066 fprintf (stderr, "%s: %s (%s)\n", argv[0], string, strerror (errno));
1034#endif 1067#endif
1035 fail (argc, argv); 1068 fail ();
1036 } 1069 }
1037 1070
1038 if (nowait) 1071 if (nowait)
@@ -1054,7 +1087,7 @@ To start the server in Emacs, type \"M-x server-start\".\n",
1054 { 1087 {
1055 fprintf (stderr, "%s: ", argv[0]); 1088 fprintf (stderr, "%s: ", argv[0]);
1056 perror ("fdopen"); 1089 perror ("fdopen");
1057 fail (argc, argv); 1090 fail ();
1058 } 1091 }
1059 1092
1060 if (! init_tty ()) 1093 if (! init_tty ())
@@ -1062,7 +1095,7 @@ To start the server in Emacs, type \"M-x server-start\".\n",
1062 reset_tty (); 1095 reset_tty ();
1063 fprintf (stderr, "%s: ", argv[0]); 1096 fprintf (stderr, "%s: ", argv[0]);
1064 perror ("fdopen"); 1097 perror ("fdopen");
1065 fail (argc, argv); 1098 fail ();
1066 } 1099 }
1067 1100
1068 if (! init_pty ()) 1101 if (! init_pty ())
@@ -1070,10 +1103,10 @@ To start the server in Emacs, type \"M-x server-start\".\n",
1070 reset_tty (); 1103 reset_tty ();
1071 fprintf (stderr, "%s: ", argv[0]); 1104 fprintf (stderr, "%s: ", argv[0]);
1072 perror ("fdopen"); 1105 perror ("fdopen");
1073 fail (argc, argv); 1106 fail ();
1074 } 1107 }
1075 1108
1076 fprintf (out, "-pty "); 1109 fprintf (out, "-tty ");
1077 quote_file_name (pty_name, out); 1110 quote_file_name (pty_name, out);
1078 fprintf (out, " "); 1111 fprintf (out, " ");
1079 quote_file_name (getenv("TERM"), out); 1112 quote_file_name (getenv("TERM"), out);
@@ -1133,11 +1166,8 @@ To start the server in Emacs, type \"M-x server-start\".\n",
1133 if (! pty_conversation (out)) 1166 if (! pty_conversation (out))
1134 { 1167 {
1135 reset_tty (); 1168 reset_tty ();
1136 fprintf (stderr, "%s: ", argv[0]); 1169 fail ();
1137 perror ("fdopen");
1138 fail (argc, argv);
1139 } 1170 }
1140 close (master);
1141 reset_tty (); 1171 reset_tty ();
1142 return 0; 1172 return 0;
1143 } 1173 }
diff --git a/lisp/server.el b/lisp/server.el
index bf7d4a5d358..ef9aa47b6bd 100644
--- a/lisp/server.el
+++ b/lisp/server.el
@@ -185,9 +185,6 @@ are done with it in the server.")
185 ;; Remove PROC from the list of clients. 185 ;; Remove PROC from the list of clients.
186 (when client 186 (when client
187 (setq server-clients (delq client server-clients)) 187 (setq server-clients (delq client server-clients))
188 (let ((frame (assq (car client) server-frames)))
189 (setq server-frames (delq frame server-frames))
190 (when (frame-live-p (cadr frame)) (delete-frame (cadr frame) 'force)))
191 (dolist (buf (cdr client)) 188 (dolist (buf (cdr client))
192 (with-current-buffer buf 189 (with-current-buffer buf
193 ;; Remove PROC from the clients of each buffer. 190 ;; Remove PROC from the clients of each buffer.
@@ -197,9 +194,24 @@ are done with it in the server.")
197 (or (and server-kill-new-buffers 194 (or (and server-kill-new-buffers
198 (not server-existing-buffer)) 195 (not server-existing-buffer))
199 (server-temp-file-p))) 196 (server-temp-file-p)))
200 (kill-buffer (current-buffer))))))) 197 (kill-buffer (current-buffer)))))
198 (let ((frame (assq (car client) server-frames)))
199 (when frame
200 (setq server-frames (delq frame server-frames))
201 (when (frame-live-p (cadr frame)) (delete-frame (cadr frame) 'force))))))
201 (server-log (format "Status changed to %s" (process-status proc)) proc)) 202 (server-log (format "Status changed to %s" (process-status proc)) proc))
202 203
204(defun server-handle-delete-frame (frame)
205 (dolist (entry server-frames)
206 (let ((proc (nth 0 entry))
207 (f (nth 1 entry)))
208 (when (eq f frame)
209 (let ((client (assq proc server-clients)))
210 (if (and (cdr client) (not (yes-or-no-p "Frame has pending buffers; close anyway? ")))
211 (error "Frame deletion cancelled")
212 (setq server-frames (delq entry server-frames))
213 (delete-process (car client))))))))
214
203(defun server-select-display (display) 215(defun server-select-display (display)
204 ;; If the current frame is on `display' we're all set. 216 ;; If the current frame is on `display' we're all set.
205 (unless (equal (frame-parameter (selected-frame) 'display) display) 217 (unless (equal (frame-parameter (selected-frame) 'display) display)
@@ -276,6 +288,7 @@ Prefix arg means just kill any existing server communications subprocess."
276 (if server-process 288 (if server-process
277 (server-log (message "Restarting server"))) 289 (server-log (message "Restarting server")))
278 (letf (((default-file-modes) ?\700)) 290 (letf (((default-file-modes) ?\700))
291 (add-to-list 'delete-frame-functions 'server-handle-delete-frame)
279 (setq server-process 292 (setq server-process
280 (make-network-process 293 (make-network-process
281 :name "server" :family 'local :server t :noquery t 294 :name "server" :family 'local :server t :noquery t
@@ -335,18 +348,18 @@ PROC is the server process. Format of STRING is \"PATH PATH PATH... \\n\"."
335 (error (process-send-string proc (nth 1 err)) 348 (error (process-send-string proc (nth 1 err))
336 (setq request ""))))) 349 (setq request "")))))
337 ;; Open a new frame at the client. ARG is the name of the pseudo tty. 350 ;; Open a new frame at the client. ARG is the name of the pseudo tty.
338 ((and (equal "-pty" arg) (string-match "\\([^ ]*\\) \\([^ ]*\\) " request)) 351 ((and (equal "-tty" arg) (string-match "\\([^ ]*\\) \\([^ ]*\\) " request))
339 (setq newframe t) 352 (let ((tty (server-unquote-arg (match-string 1 request)))
340 (let ((pty (server-unquote-arg (match-string 1 request)))
341 (type (server-unquote-arg (match-string 2 request)))) 353 (type (server-unquote-arg (match-string 2 request))))
342 (setq request (substring request (match-end 0))) 354 (setq request (substring request (match-end 0)))
343 (condition-case err 355 (condition-case err
344 (let ((frame (make-terminal-frame `((tty . ,pty) (tty-type . ,type))))) 356 (let ((frame (make-frame-on-tty tty type)))
345 (setq server-frames (cons (list (car client) frame) server-frames)) 357 (setq server-frames (cons (list (car client) frame) server-frames))
346 (sit-for 0) 358 (sit-for 0)
347 (process-send-string proc (concat (number-to-string (emacs-pid)) "\n")) 359 (process-send-string proc (concat (number-to-string (emacs-pid)) "\n"))
348 (select-frame frame)) 360 (select-frame frame)
349 (error (process-send-string proc (nth 1 err)) 361 (setq newframe t))
362 (error (ignore-errors (process-send-string proc (concat (nth 1 err) "\n")))
350 (setq request ""))))) 363 (setq request "")))))
351 ;; ARG is a line number option. 364 ;; ARG is a line number option.
352 ((string-match "\\`\\+[0-9]+\\'" arg) 365 ((string-match "\\`\\+[0-9]+\\'" arg)
@@ -386,19 +399,19 @@ PROC is the server process. Format of STRING is \"PATH PATH PATH... \\n\"."
386 (if (and (not newframe) (null (cdr client))) 399 (if (and (not newframe) (null (cdr client)))
387 ;; This client is empty; get rid of it immediately. 400 ;; This client is empty; get rid of it immediately.
388 (progn 401 (progn
389 (let ((frame (assq (car client) server-frames)))
390 (setq server-frames (delq frame server-frames))
391 (when (frame-live-p (cadr frame)) (delete-frame (cadr frame) 'force)))
392 (delete-process proc) 402 (delete-process proc)
393 (server-log "Close empty client" proc)) 403 (server-log "Close empty client" proc))
394 ;; We visited some buffer for this client. 404 ;; We visited some buffer for this client.
395 (or nowait (push client server-clients)) 405 (or nowait (push client server-clients))
396 (unless (or isearch-mode (minibufferp)) 406 (unless (or isearch-mode (minibufferp))
397 (server-switch-buffer (nth 1 client)) 407 (if (and newframe (null (cdr client)))
398 (run-hooks 'server-switch-hook) 408 (message (substitute-command-keys
399 (unless nowait 409 "When done with this frame, type \\[delete-frame]"))
400 (message (substitute-command-keys 410 (server-switch-buffer (nth 1 client))
401 "When done with a buffer, type \\[server-edit]"))))))) 411 (run-hooks 'server-switch-hook)
412 (unless nowait
413 (message (substitute-command-keys
414 "When done with a buffer, type \\[server-edit]"))))))))
402 ;; Save for later any partial line that remains. 415 ;; Save for later any partial line that remains.
403 (when (> (length string) 0) 416 (when (> (length string) 0)
404 (process-put proc 'previous-string string))) 417 (process-put proc 'previous-string string)))
@@ -475,9 +488,6 @@ FOR-KILLING if non-nil indicates that we are called from `kill-buffer'."
475 ;; If client now has no pending buffers, 488 ;; If client now has no pending buffers,
476 ;; tell it that it is done, and forget it entirely. 489 ;; tell it that it is done, and forget it entirely.
477 (unless (cdr client) 490 (unless (cdr client)
478 (let ((frame (assq (car client) server-frames)))
479 (setq server-frames (delq frame server-frames))
480 (when (frame-live-p (cadr frame)) (delete-frame (cadr frame) 'force)))
481 (delete-process (car client)) 491 (delete-process (car client))
482 (server-log "Close" (car client)) 492 (server-log "Close" (car client))
483 (setq server-clients (delq client server-clients)))) 493 (setq server-clients (delq client server-clients))))
diff --git a/src/alloc.c b/src/alloc.c
index 1835d2a59eb..700845ab6c5 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -256,6 +256,7 @@ EMACS_INT gcs_done; /* accumulated GCs */
256 256
257static void mark_buffer P_ ((Lisp_Object)); 257static void mark_buffer P_ ((Lisp_Object));
258extern void mark_kboards P_ ((void)); 258extern void mark_kboards P_ ((void));
259extern void mark_ttys P_ ((void));
259static void gc_sweep P_ ((void)); 260static void gc_sweep P_ ((void));
260static void mark_glyph_matrix P_ ((struct glyph_matrix *)); 261static void mark_glyph_matrix P_ ((struct glyph_matrix *));
261static void mark_face_cache P_ ((struct face_cache *)); 262static void mark_face_cache P_ ((struct face_cache *));
@@ -4441,6 +4442,7 @@ returns nil, because real GC can't be done. */)
4441 mark_object (backlist->args[i]); 4442 mark_object (backlist->args[i]);
4442 } 4443 }
4443 mark_kboards (); 4444 mark_kboards ();
4445 mark_ttys ();
4444 4446
4445 /* Look thru every buffer's undo list 4447 /* Look thru every buffer's undo list
4446 for elements that update markers that were not marked, 4448 for elements that update markers that were not marked,
diff --git a/src/emacs.c b/src/emacs.c
index 62b550a4e2c..d6f040f3f51 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -1990,7 +1990,6 @@ shut_down_emacs (sig, no_x, stuff)
1990 if (EMACS_GET_TTY_PGRP (0, &tpgrp) != -1 1990 if (EMACS_GET_TTY_PGRP (0, &tpgrp) != -1
1991 && tpgrp == pgrp) 1991 && tpgrp == pgrp)
1992 { 1992 {
1993 fflush (stdout);
1994 reset_all_sys_modes (); 1993 reset_all_sys_modes ();
1995 if (sig && sig != SIGTERM) 1994 if (sig && sig != SIGTERM)
1996 fprintf (stderr, "Fatal error (%d)", sig); 1995 fprintf (stderr, "Fatal error (%d)", sig);
diff --git a/src/process.c b/src/process.c
index ed0d5fe765b..3334f3258ae 100644
--- a/src/process.c
+++ b/src/process.c
@@ -275,11 +275,11 @@ extern int keyboard_bit_set P_ ((SELECT_TYPE *));
275 275
276static SELECT_TYPE input_wait_mask; 276static SELECT_TYPE input_wait_mask;
277 277
278/* Mask that excludes keyboard input descriptor (s). */ 278/* Mask that excludes keyboard input descriptor(s). */
279 279
280static SELECT_TYPE non_keyboard_wait_mask; 280static SELECT_TYPE non_keyboard_wait_mask;
281 281
282/* Mask that excludes process input descriptor (s). */ 282/* Mask that excludes process input descriptor(s). */
283 283
284static SELECT_TYPE non_process_wait_mask; 284static SELECT_TYPE non_process_wait_mask;
285 285
@@ -6430,20 +6430,10 @@ DEFUN ("process-filter-multibyte-p", Fprocess_filter_multibyte_p,
6430 6430
6431 6431
6432 6432
6433/* The first time this is called, assume keyboard input comes from DESC
6434 instead of from where we used to expect it.
6435 Subsequent calls mean assume input keyboard can come from DESC
6436 in addition to other places. */
6437
6438static int add_keyboard_wait_descriptor_called_flag;
6439
6440void 6433void
6441add_keyboard_wait_descriptor (desc) 6434add_keyboard_wait_descriptor (desc)
6442 int desc; 6435 int desc;
6443{ 6436{
6444 if (! add_keyboard_wait_descriptor_called_flag)
6445 FD_CLR (0, &input_wait_mask);
6446 add_keyboard_wait_descriptor_called_flag = 1;
6447 FD_SET (desc, &input_wait_mask); 6437 FD_SET (desc, &input_wait_mask);
6448 FD_SET (desc, &non_process_wait_mask); 6438 FD_SET (desc, &non_process_wait_mask);
6449 if (desc > max_keyboard_desc) 6439 if (desc > max_keyboard_desc)
diff --git a/src/sysdep.c b/src/sysdep.c
index 7453be6e3a7..98a671ddbdc 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -45,6 +45,8 @@ extern void srandom P_ ((unsigned int));
45#endif 45#endif
46#endif 46#endif
47 47
48#include "sysselect.h"
49
48#include "blockinput.h" 50#include "blockinput.h"
49#undef NULL 51#undef NULL
50 52
@@ -913,16 +915,15 @@ restore_signal_handlers (saved_handlers)
913 915
914#ifdef F_SETFL 916#ifdef F_SETFL
915 917
916int old_fcntl_flags; 918int old_fcntl_flags[MAXDESC];
917 919
918void 920void
919init_sigio (fd) 921init_sigio (fd)
920 int fd; 922 int fd;
921{ 923{
922#ifdef FASYNC 924#ifdef FASYNC
923 /* XXX What if we get called with more than one fds? */ 925 old_fcntl_flags[fd] = fcntl (fd, F_GETFL, 0) & ~FASYNC;
924 old_fcntl_flags = fcntl (fd, F_GETFL, 0) & ~FASYNC; 926 fcntl (fd, F_SETFL, old_fcntl_flags[fd] | FASYNC);
925 fcntl (fd, F_SETFL, old_fcntl_flags | FASYNC);
926#endif 927#endif
927 interrupts_deferred = 0; 928 interrupts_deferred = 0;
928} 929}
@@ -931,7 +932,7 @@ void
931reset_sigio (fd) 932reset_sigio (fd)
932 int fd; 933 int fd;
933{ 934{
934 fcntl (fd, F_SETFL, old_fcntl_flags); 935 fcntl (fd, F_SETFL, old_fcntl_flags[fd]);
935} 936}
936 937
937#ifdef FASYNC /* F_SETFL does not imply existence of FASYNC */ 938#ifdef FASYNC /* F_SETFL does not imply existence of FASYNC */
@@ -1086,11 +1087,12 @@ narrow_foreground_group (int fd)
1086{ 1087{
1087 int me = getpid (); 1088 int me = getpid ();
1088 1089
1089 setpgrp (0, inherited_pgroup); 1090 if (! inherited_pgroup)
1091 inherited_pgroup = getpgid (0);
1090 /* XXX This only works on the controlling tty. */ 1092 /* XXX This only works on the controlling tty. */
1091 if (inherited_pgroup != me) 1093 if (inherited_pgroup != me)
1092 EMACS_SET_TTY_PGRP (fd, &me); 1094 EMACS_SET_TTY_PGRP (fd, &me);
1093 setpgrp (0, me); 1095 setpgid (0, me);
1094} 1096}
1095 1097
1096/* Set the tty to our original foreground group. */ 1098/* Set the tty to our original foreground group. */
@@ -1099,7 +1101,7 @@ widen_foreground_group (int fd)
1099{ 1101{
1100 if (inherited_pgroup != getpid ()) 1102 if (inherited_pgroup != getpid ())
1101 EMACS_SET_TTY_PGRP (fd, &inherited_pgroup); 1103 EMACS_SET_TTY_PGRP (fd, &inherited_pgroup);
1102 setpgrp (0, inherited_pgroup); 1104 setpgid (0, inherited_pgroup);
1103} 1105}
1104 1106
1105#endif /* BSD_PGRPS */ 1107#endif /* BSD_PGRPS */
@@ -1265,7 +1267,7 @@ int lmode;
1265 1267
1266#ifndef F_SETOWN_BUG 1268#ifndef F_SETOWN_BUG
1267#ifdef F_SETOWN 1269#ifdef F_SETOWN
1268int old_fcntl_owner; 1270int old_fcntl_owner[MAXDESC];
1269#endif /* F_SETOWN */ 1271#endif /* F_SETOWN */
1270#endif /* F_SETOWN_BUG */ 1272#endif /* F_SETOWN_BUG */
1271 1273
@@ -1614,7 +1616,8 @@ nil means don't delete them until `list-processes' is run. */);
1614 if (interrupt_input 1616 if (interrupt_input
1615 && ! read_socket_hook && EQ (Vwindow_system, Qnil)) 1617 && ! read_socket_hook && EQ (Vwindow_system, Qnil))
1616 { 1618 {
1617 old_fcntl_owner = fcntl (fileno (TTY_INPUT (tty_out)), F_GETOWN, 0); 1619 old_fcntl_owner[fileno (TTY_INPUT (tty_out))] =
1620 fcntl (fileno (TTY_INPUT (tty_out)), F_GETOWN, 0);
1618 fcntl (fileno (TTY_INPUT (tty_out)), F_SETOWN, getpid ()); 1621 fcntl (fileno (TTY_INPUT (tty_out)), F_SETOWN, getpid ());
1619 init_sigio (fileno (TTY_INPUT (tty_out))); 1622 init_sigio (fileno (TTY_INPUT (tty_out)));
1620 } 1623 }
@@ -1823,9 +1826,12 @@ reset_sys_modes (tty_out)
1823 ) 1826 )
1824 return; 1827 return;
1825#endif 1828#endif
1829
1826 cmgoto (tty_out, FrameRows (tty_out) - 1, 0); 1830 cmgoto (tty_out, FrameRows (tty_out) - 1, 0);
1827 tty_clear_end_of_line (tty_out, FrameCols (tty_out)); 1831 tty_clear_end_of_line (tty_out, FrameCols (tty_out));
1828 cmgoto (tty_out, FrameRows (tty_out) - 1, 0); 1832 cmgoto (tty_out, FrameRows (tty_out) - 1, 0);
1833 fflush (tty_out->output);
1834
1829#if defined (IBMR2AIX) && defined (AIXHFT) 1835#if defined (IBMR2AIX) && defined (AIXHFT)
1830 { 1836 {
1831 /* HFT devices normally use ^J as a LF/CR. We forced it to 1837 /* HFT devices normally use ^J as a LF/CR. We forced it to
@@ -1842,7 +1848,7 @@ reset_sys_modes (tty_out)
1842#ifdef BSD_SYSTEM 1848#ifdef BSD_SYSTEM
1843#ifndef BSD4_1 1849#ifndef BSD4_1
1844 /* Avoid possible loss of output when changing terminal modes. */ 1850 /* Avoid possible loss of output when changing terminal modes. */
1845 fsync (TTY_OUTPUT (tty_out)); 1851 fsync (fileno (TTY_OUTPUT (tty_out)));
1846#endif 1852#endif
1847#endif 1853#endif
1848 1854
@@ -1851,8 +1857,9 @@ reset_sys_modes (tty_out)
1851#ifdef F_SETOWN /* F_SETFL does not imply existence of F_SETOWN */ 1857#ifdef F_SETOWN /* F_SETFL does not imply existence of F_SETOWN */
1852 if (interrupt_input) 1858 if (interrupt_input)
1853 { 1859 {
1854 reset_sigio (tty_out); 1860 reset_sigio (fileno (TTY_INPUT (tty_out)));
1855 fcntl (fileno (TTY_INPUT (tty_out)), F_SETOWN, old_fcntl_owner); 1861 fcntl (fileno (TTY_INPUT (tty_out)), F_SETOWN,
1862 old_fcntl_owner[fileno (TTY_INPUT (tty_out))]);
1856 } 1863 }
1857#endif /* F_SETOWN */ 1864#endif /* F_SETOWN */
1858#endif /* F_SETOWN_BUG */ 1865#endif /* F_SETOWN_BUG */
@@ -1863,7 +1870,7 @@ reset_sys_modes (tty_out)
1863#endif /* F_SETFL */ 1870#endif /* F_SETFL */
1864#ifdef BSD4_1 1871#ifdef BSD4_1
1865 if (interrupt_input) 1872 if (interrupt_input)
1866 reset_sigio (tty_out); 1873 reset_sigio (fileno (TTY_INPUT (tty_out)));
1867#endif /* BSD4_1 */ 1874#endif /* BSD4_1 */
1868 1875
1869 if (tty_out->old_tty) 1876 if (tty_out->old_tty)
@@ -2704,6 +2711,10 @@ read_input_waiting ()
2704 } 2711 }
2705} 2712}
2706 2713
2714#if !defined (HAVE_SELECT) || defined (BROKEN_SELECT_NON_X)
2715#define select sys_select
2716#endif
2717
2707#endif /* not HAVE_SELECT */ 2718#endif /* not HAVE_SELECT */
2708#endif /* not VMS */ 2719#endif /* not VMS */
2709#endif /* not MSDOS */ 2720#endif /* not MSDOS */
diff --git a/src/term.c b/src/term.c
index 72698ed3b2c..25f26e3c6e2 100644
--- a/src/term.c
+++ b/src/term.c
@@ -109,7 +109,9 @@ struct tty_output *tty_list;
109 pages, where one page is used for Emacs and another for all 109 pages, where one page is used for Emacs and another for all
110 else. */ 110 else. */
111int no_redraw_on_reenter; 111int no_redraw_on_reenter;
112 112
113Lisp_Object Qframe_tty_name, Qframe_tty_type;
114
113/* Hook functions that you can set to snap out the functions in this file. 115/* Hook functions that you can set to snap out the functions in this file.
114 These are all extern'd in termhooks.h */ 116 These are all extern'd in termhooks.h */
115 117
@@ -2107,6 +2109,60 @@ get_named_tty (name)
2107} 2109}
2108 2110
2109 2111
2112
2113DEFUN ("frame-tty-name", Fframe_tty_name, Sframe_tty_name, 0, 1, 0,
2114 doc: /* Return the name of the TTY device that FRAME is displayed on. */)
2115 (frame)
2116 Lisp_Object frame;
2117{
2118 struct frame *f;
2119
2120 if (NILP (frame))
2121 {
2122 f = XFRAME (selected_frame);
2123 }
2124 else
2125 {
2126 CHECK_LIVE_FRAME (frame);
2127 f = XFRAME (frame);
2128 }
2129
2130 if (f->output_method != output_termcap)
2131 wrong_type_argument (Qframe_tty_name, frame);
2132
2133 if (f->output_data.tty->name)
2134 return build_string (f->output_data.tty->name);
2135 else
2136 return Qnil;
2137}
2138
2139DEFUN ("frame-tty-type", Fframe_tty_type, Sframe_tty_type, 0, 1, 0,
2140 doc: /* Return the type of the TTY device that FRAME is displayed on. */)
2141 (frame)
2142 Lisp_Object frame;
2143{
2144 struct frame *f;
2145
2146 if (NILP (frame))
2147 {
2148 f = XFRAME (selected_frame);
2149 }
2150 else
2151 {
2152 CHECK_LIVE_FRAME (frame);
2153 f = XFRAME (frame);
2154 }
2155
2156 if (f->output_method != output_termcap)
2157 wrong_type_argument (Qframe_tty_type, frame);
2158
2159 if (f->output_data.tty->type)
2160 return build_string (f->output_data.tty->type);
2161 else
2162 return Qnil;
2163}
2164
2165
2110/*********************************************************************** 2166/***********************************************************************
2111 Initialization 2167 Initialization
2112 ***********************************************************************/ 2168 ***********************************************************************/
@@ -2186,6 +2242,8 @@ term_init (Lisp_Object frame, char *name, char *terminal_type)
2186 2242
2187 TTY_TYPE (tty) = xstrdup (terminal_type); 2243 TTY_TYPE (tty) = xstrdup (terminal_type);
2188 2244
2245 add_keyboard_wait_descriptor (fileno (tty->input));
2246
2189#ifdef WINDOWSNT 2247#ifdef WINDOWSNT
2190 initialize_w32_display (); 2248 initialize_w32_display ();
2191 2249
@@ -2665,27 +2723,31 @@ fatal (str, arg1, arg2)
2665 exit (1); 2723 exit (1);
2666} 2724}
2667 2725
2668void 2726
2669syms_of_term () 2727
2728DEFUN ("delete-tty", Fdelete_tty, Sdelete_tty, 0, 1, 0,
2729 doc: /* Delete all frames on the terminal named TTY, and close the device. */)
2730 (tty)
2731 Lisp_Object tty;
2670{ 2732{
2671 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo, 2733 struct tty_output *t;
2672 doc: /* Non-nil means the system uses terminfo rather than termcap. 2734 char *name = 0;
2673This variable can be used by terminal emulator packages. */);
2674#ifdef TERMINFO
2675 system_uses_terminfo = 1;
2676#else
2677 system_uses_terminfo = 0;
2678#endif
2679 2735
2680 DEFVAR_LISP ("ring-bell-function", &Vring_bell_function, 2736 CHECK_STRING (tty);
2681 doc: /* Non-nil means call this function to ring the bell. 2737
2682The function should accept no arguments. */); 2738 if (SBYTES (tty) > 0)
2683 Vring_bell_function = Qnil; 2739 {
2740 name = (char *) alloca (SBYTES (tty) + 1);
2741 strncpy (name, SDATA (tty), SBYTES (tty));
2742 name[SBYTES (tty)] = 0;
2743 }
2684 2744
2685 defsubr (&Stty_display_color_p); 2745 t = get_named_tty (name);
2686 defsubr (&Stty_display_color_cells);
2687 2746
2688 Fprovide (intern ("multi-tty"), Qnil); 2747 if (! t)
2748 error ("No such tty device: %s", name);
2749
2750 delete_tty (t);
2689} 2751}
2690 2752
2691static int deleting_tty = 0; 2753static int deleting_tty = 0;
@@ -2734,10 +2796,14 @@ delete_tty (struct tty_output *tty)
2734 xfree (tty->name); 2796 xfree (tty->name);
2735 if (tty->type) 2797 if (tty->type)
2736 xfree (tty->type); 2798 xfree (tty->type);
2737 2799
2738 if (tty->input) 2800 if (tty->input)
2739 fclose (tty->input); 2801 {
2740 if (tty->output && tty->output != tty->input) 2802 delete_keyboard_wait_descriptor (fileno (tty->input));
2803 if (tty->input != stdin)
2804 fclose (tty->input);
2805 }
2806 if (tty->output && tty->output != stdout && tty->output != tty->input)
2741 fclose (tty->output); 2807 fclose (tty->output);
2742 if (tty->termscript) 2808 if (tty->termscript)
2743 fclose (tty->termscript); 2809 fclose (tty->termscript);
@@ -2754,24 +2820,57 @@ delete_tty (struct tty_output *tty)
2754} 2820}
2755 2821
2756 2822
2757struct tty_output * 2823
2758get_current_tty ()
2759{
2760 return CURTTY();
2761}
2762 2824
2825/* Mark the pointers in the tty_output objects.
2826 Called by the Fgarbage_collector. */
2763void 2827void
2764print_all_frames () 2828mark_ttys ()
2765{ 2829{
2766 /* XXX Debug function. */ 2830 struct tty_output *tty;
2767 Lisp_Object frame, tail; 2831 Lisp_Object *p;
2768 FOR_EACH_FRAME (tail, frame) 2832 for (tty = tty_list; tty; tty = tty->next)
2769 { 2833 {
2770 fprintf (stderr, "Frame: %x\n", XFRAME (frame)); 2834 if (tty->top_frame)
2771 fflush (stderr); 2835 mark_object (tty->top_frame);
2772 } 2836 }
2773} 2837}
2774 2838
2775 2839
2840
2841void
2842syms_of_term ()
2843{
2844 DEFVAR_BOOL ("system-uses-terminfo", &system_uses_terminfo,
2845 doc: /* Non-nil means the system uses terminfo rather than termcap.
2846This variable can be used by terminal emulator packages. */);
2847#ifdef TERMINFO
2848 system_uses_terminfo = 1;
2849#else
2850 system_uses_terminfo = 0;
2851#endif
2852
2853 DEFVAR_LISP ("ring-bell-function", &Vring_bell_function,
2854 doc: /* Non-nil means call this function to ring the bell.
2855The function should accept no arguments. */);
2856 Vring_bell_function = Qnil;
2857
2858 Qframe_tty_name = intern ("frame-tty-name");
2859 staticpro (&Qframe_tty_name);
2860
2861 Qframe_tty_type = intern ("frame-tty-type");
2862 staticpro (&Qframe_tty_type);
2863
2864 defsubr (&Stty_display_color_p);
2865 defsubr (&Stty_display_color_cells);
2866 defsubr (&Sframe_tty_name);
2867 defsubr (&Sframe_tty_type);
2868 defsubr (&Sdelete_tty);
2869
2870 Fprovide (intern ("multi-tty"), Qnil);
2871}
2872
2873
2874
2776/* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193 2875/* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193
2777 (do not change this comment) */ 2876 (do not change this comment) */