changeset 83009:b2b37c85b00a

Numerous bugfixes and small improvements. lisp/bindings.el (mode-line-frame-identification): Use %T, not %F. lisp/faces.el (x-create-frame-with-faces): Added frame-creation-function parameter. (tty-create-frame-with-faces): Ditto. lisp/frame.el (frame-creation-function): Make it frame-local. (select-frame-set-input-focus): Use the window-system function, not the variable. lisp/server.el (server-handle-delete-tty): Make sure the client process is removed from server-clients after the delete-process call. It seems that the sentinel is not called. Added docs. (server-process-filter): Immediately add the client to server-clients when a new termcap frame is created. Fixed a case of `not' called with two parameters. Ignore errors while sending the evaluation result back to the client. (server-kill-buffer-query-function): Don't ask the user if the server process is already dead. lisp/term/x-win.el: Don't change mode-line-frame-identification. src/buffer.c (syms_of_buffer): Added %T to the docs of mode-line-format. src/dispnew.c (init_display): Increment the reference count of the new termcap display. src/frame.c (make_terminal_frame): Set the old top frame's visibility to `obscured'. (Fmake_terminal_frame): Look at the current termcap display's name, not just the similar frame parameter. Try to get the type from the current display first, and only then from Vdefault_frame_alist. src/keyboard.c (handle_interrupt): New function to separate the signal handling from C-g processing. (interrupt_signal): Call handle_interrupt to do the real work. (kbd_buffer_store_event): Use handle_interrupt instead of interrupt_signal. (cmd_error_internal): Use FRAME_INITIAL_P instead of ugly hacks. src/termhooks.h (initial_display): New declaration. src/xdisp.c (decode_mode_spec): Added '%T' (termcap-only frame name). git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-49
author Karoly Lorentey <lorentey@elte.hu>
date Sat, 10 Jan 2004 12:56:22 +0000
parents 040dd41ed7d0
children 82554ed1aed8
files README.multi-tty lisp/bindings.el lisp/faces.el lisp/frame.el lisp/server.el lisp/term/x-win.el src/buffer.c src/dispextern.h src/dispnew.c src/frame.c src/keyboard.c src/termhooks.h src/xdisp.c
diffstat 13 files changed, 124 insertions(+), 55 deletions(-) [+]
line wrap: on
line diff
--- a/README.multi-tty	Fri Jan 09 18:57:53 2004 +0000
+++ b/README.multi-tty	Sat Jan 10 12:56:22 2004 +0000
@@ -104,7 +104,7 @@
    specify a terminal device (`tty' parameter) and a terminal type
    (`tty-type' parameter) to `make-terminal-frame'. `tty' must be a
    terminal device created by the updated emacsclient, or there will
-   be problems with terminal input and window resizes.  
+   be problems with terminal input and window resizes.
 
    You can test for the presence of multiple terminal support by
    testing for the `multi-tty' feature.
@@ -138,7 +138,10 @@
    should simply be removed and make-frame changed to do the right
    thing.
 
-** The command `emacsclient -t -e '(delete-frame)'' fails to exit.
+** Fix interactive use of temacs.  There are face-related SEGVs, most
+   likely because of changes in realize_default_face, realize_face.
+
+** Allow opening an X session after -nw.
 
 ** Find out the best way to support suspending Emacs with multiple
    ttys.  My guess: disable it on the controlling tty, but from other
@@ -146,18 +149,11 @@
    extend emacsclient to handle suspend/resume.  A `kill -STOP' almost
    works right now.)
 
-** If there are no frames on its controlling terminal, Emacs should
-   exit if the uses presses C-c there.  (See the SIGTERM comment in
-   interrupt_signal on why this seems to be impossible to solve
-   generally.)
-
-** During an X session, Emacs seems to read from stdin.
+** Exiting Emacs while there are emacsclient frames don't restore the
+   ttys to their default states.
 
 ** Move baud_rate to struct display.
 
-** Do tty output through struct display, like graphical display
-   backends.
-
 ** Implement support for starting an interactive Emacs session without
    an initial frame.  (The user would connect to it and open frames
    later, with emacsclient.)  Not necessarily a good idea.
@@ -212,10 +208,6 @@
    instead of nread > 0 after calling read_socket_hook in
    read_avail_input.
 
-** Define an output_initial value for output_method for the initial
-   frame that is dumped with Emacs.  Checking for this frame (e.g. in
-   cmd_error_internal) is ugly.
-
 ** emacsclient -t from an Emacs term buffer does not work, complains
    about face problems.  This can even lock up Emacs (if the recursive
    frame sets single_kboard).  Update: the face problems are caused by
@@ -227,7 +219,7 @@
 
 (ex-TODO items with explanations.)
 
--- Introduce a new struct for terminal devices.  
+-- Introduce a new struct for terminal devices.
 
    (Done, see struct tty_output.  The list of members is not yet
    complete.)
@@ -251,12 +243,12 @@
    (Update2: After enabling X, they don't.)
 
 -- other-frame should cycle through the frames on the `current'
-   terminal only.  
+   terminal only.
 
    (Done, by trivially modifiying next_frame and prev_frame.)
 
 -- Support different terminal sizes.
-   
+
    (Done, no problem.)
 
 -- Make sure terminal resizes are handled gracefully.  (Could be
@@ -267,12 +259,12 @@
 
 -- Extend emacsclient to automatically open a new tty when it connects
    to Emacs.
-   
+
    (Done.  It's an ugly hack, needs more work.)
 
 -- Redisplay must refresh the topmost frame on *all* terminals, not
    just the initial terminal.
-   
+
    (Done, but introduced an ugly redisplay problems.  Ugh.)
 
 -- Fix redisplay problems.
@@ -343,7 +335,7 @@
    (Done, we do the same as Emacs 21.2 for all terminals.)
 
 -- 'TERM=dumb src/emacs' does not restore the terminal state.
-   
+
    (Done.)
 
 -- C-g should work on secondary terminals.
@@ -500,4 +492,32 @@
    terminal frame during bootstrap which prevented echo_area_display
    from working correctly on a tty frame during a combo session.)
 
+-- If there are no frames on its controlling terminal, Emacs should
+   exit if the uses presses C-c there.
+
+   (Done, as far as possible.  See the SIGTERM comment in
+   interrupt_signal on why this seems to be impossible to solve this
+   in general.)
+
+-- During an X session, Emacs seems to read from stdin.  Also, Emacs
+   fails to start without a controlling tty.
+
+   (Fixed by replacing the troublesome termcap display with a dummy
+   bootstrap display during bootstrap.
+
+-- Do tty output through struct display, like graphical display
+   backends.
+
+   (Done.)
+
+-- Define an output_initial value for output_method for the initial
+   frame that is dumped with Emacs.  Checking for this frame (e.g. in
+   cmd_error_internal) is ugly.
+
+   (Done, broking interactive temacs.)
+
+-- The command `emacsclient -t -e '(delete-frame)'' fails to exit.
+
+   (Fixed.)
+
 ;;; arch-tag: 8da1619e-2e79-41a8-9ac9-a0485daad17d
--- a/lisp/bindings.el	Fri Jan 09 18:57:53 2004 +0000
+++ b/lisp/bindings.el	Sat Jan 10 12:56:22 2004 +0000
@@ -212,7 +212,7 @@
 
 (make-variable-buffer-local 'mode-line-buffer-identification)
 
-(defvar mode-line-frame-identification '("-%F  ")
+(defvar mode-line-frame-identification '("-%T  ")
   "Mode-line control to describe the current frame.")
 
 (defvar mode-line-process nil "\
--- a/lisp/faces.el	Fri Jan 09 18:57:53 2004 +0000
+++ b/lisp/faces.el	Sat Jan 10 12:56:22 2004 +0000
@@ -1658,7 +1658,8 @@
   (setq parameters (x-handle-named-frame-geometry parameters))
   (let ((visibility-spec (assq 'visibility parameters))
 	(frame-list (frame-list))
-	(frame (x-create-frame (cons '(visibility . nil) parameters)))
+	(frame (x-create-frame `((frame-creation-function . x-create-frame-with-faces)
+				 (visibility . nil) . ,parameters)))
 	success)
     (unwind-protect
 	(progn
@@ -1744,7 +1745,8 @@
 `default-frame-alist'.  If either PARAMETERS or `default-frame-alist'
 contains a `reverse' parameter, handle that.  Value is the new frame
 created."
-  (let ((frame (make-terminal-frame parameters))
+  (let ((frame (make-terminal-frame `((frame-creation-function . tty-create-frame-with-faces) .
+				      ,parameters)))
 	success)
     (unwind-protect
 	(progn
--- a/lisp/frame.el	Fri Jan 09 18:57:53 2004 +0000
+++ b/lisp/frame.el	Sat Jan 10 12:56:22 2004 +0000
@@ -32,6 +32,8 @@
 The window system startup file should set this to its frame creation
 function, which should take an alist of parameters as its argument.")
 
+(make-variable-frame-local 'frame-creation-function)
+
 ;; The initial value given here used to ask for a minibuffer.
 ;; But that's not necessary, because the default is to have one.
 ;; By not specifying it here, we let an X resource specify it.
@@ -706,9 +708,9 @@
     (select-frame frame)
     (raise-frame frame)
     ;; Ensure, if possible, that frame gets input focus.
-    (cond ((eq window-system 'x)
+    (cond ((eq (window-system frame) 'x)
 	   (x-focus-frame frame))
-	  ((eq window-system 'w32)
+	  ((eq (window-system frame) 'w32)
 	   (w32-focus-frame frame)))
     (cond (focus-follows-mouse
 	   (set-mouse-position (selected-frame) (1- (frame-width)) 0))))
--- a/lisp/server.el	Fri Jan 09 18:57:53 2004 +0000
+++ b/lisp/server.el	Sat Jan 10 12:56:22 2004 +0000
@@ -212,13 +212,18 @@
   (server-log (format "Status changed to %s" (process-status proc)) proc))
 
 (defun server-handle-delete-tty (tty)
+  "Delete the client connection when the emacsclient frame is deleted."
   (dolist (entry server-ttys)
     (let ((proc (nth 0 entry))
 	  (term (nth 1 entry)))
       (when (equal term tty)
 	(let ((client (assq proc server-clients)))
 	  (setq server-ttys (delq entry server-ttys))
-	  (delete-process (car client)))))))
+	  (delete-process (car client))
+	  (when (assq proc server-clients)
+	    ;; This seems to be necessary to handle
+	    ;; `emacsclient -t -e '(delete-frame)'' correctly.
+	    (setq server-clients (delq client server-clients))))))))
 
 (defun server-select-display (display)
   ;; If the current frame is on `display' we're all set.
@@ -336,6 +341,7 @@
 			      (or file-name-coding-system
 				  default-file-name-coding-system)))
 	  client nowait eval newframe
+	  registered	; t if the client is already added to server-clients.
 	  (files nil)
 	  (lineno 1)
 	  (columnno 0))
@@ -363,11 +369,13 @@
 	      (condition-case err
 		  (let ((frame (make-frame-on-tty tty type)))
 		    (setq server-ttys (cons (list (car client) (frame-tty-name frame)) server-ttys))
-		    (sit-for 0)
 		    (process-send-string proc (concat "emacs-pid " (number-to-string (emacs-pid)) "\n"))
 		    (select-frame frame)
-		    (setq newframe t))
-		(error (ignore-errors (process-send-string proc (concat (nth 1 err) "\n")))
+		    ;; This makes sure that `emacsclient -t -e '(delete-frame)'' works right.
+		    (push client server-clients)
+		    (setq registered t
+			  newframe t))
+		(error (process-send-string proc (concat (nth 1 err) "\n"))
 		       (setq request "")))))
 	   ;; ARG is a line number option.
 	   ((string-match "\\`\\+[0-9]+\\'" arg)
@@ -386,12 +394,15 @@
 	    (if eval
 		(condition-case err
 		    (let ((v (eval (car (read-from-string arg)))))
-		      (when (and (not newframe v))
+		      (when (and (not newframe) v)
 			(with-temp-buffer
 			  (let ((standard-output (current-buffer)))
 			    (pp v)
 			    (process-send-region proc (point-min) (point-max))))))
-		  (error (process-send-string proc (concat "*Error* " (error-message-string err)))))
+		  (error
+		   (ignore-errors
+		     (process-send-string
+		      proc (concat "*Error* " (error-message-string err))))))
 
 	      ;; ARG is a file name.
 	      ;; Collapse multiple slashes to single slashes.
@@ -410,7 +421,7 @@
 	    (delete-process proc)
 	    (server-log "Close empty client" proc))
 	;; We visited some buffer for this client.
-	(or nowait (push client server-clients))
+	(or nowait registered (push client server-clients))
 	(unless (or isearch-mode (minibufferp))
 	  (if (and newframe (null (cdr client)))
 	      (message (substitute-command-keys
@@ -571,6 +582,11 @@
 ;; using whatever is on disk in that file. -- rms.
 (defun server-kill-buffer-query-function ()
   (or (not server-buffer-clients)
+      (let ((res t))
+	(dolist (proc server-buffer-clients res)
+	  (setq proc (assq proc server-clients))
+	  (when (and proc (eq (process-status (car proc)) 'open))
+	    (setq res nil))))
       (yes-or-no-p (format "Buffer `%s' still has clients; kill it? "
 			   (buffer-name (current-buffer))))))
 
--- a/lisp/term/x-win.el	Fri Jan 09 18:57:53 2004 +0000
+++ b/lisp/term/x-win.el	Sat Jan 10 12:56:22 2004 +0000
@@ -2443,9 +2443,6 @@
 ;;; that this is only annoying.
 (setq split-window-keep-point t)
 
-;; Don't show the frame name; that's redundant with X.
-(setq-default mode-line-frame-identification "  ")
-
 ;; Motif direct handling of f10 wasn't working right,
 ;; So temporarily we've turned it off in lwlib-Xm.c
 ;; and turned the Emacs f10 back on.
--- a/src/buffer.c	Fri Jan 09 18:57:53 2004 +0000
+++ b/src/buffer.c	Sat Jan 10 12:56:22 2004 +0000
@@ -5364,7 +5364,7 @@
   (%-constructs are allowed when the string is the entire mode-line-format
    or when it is found in a cons-cell or a list)
   %b -- print buffer name.      %f -- print visited file name.
-  %F -- print frame name.
+  %F -- print frame name.       %T -- print frame name if on tty.
   %* -- print %, * or hyphen.   %+ -- print *, % or hyphen.
 	%& is like %*, but ignore read-only-ness.
 	% means buffer is read-only and * means it is modified.
--- a/src/dispextern.h	Fri Jan 09 18:57:53 2004 +0000
+++ b/src/dispextern.h	Sat Jan 10 12:56:22 2004 +0000
@@ -2750,7 +2750,7 @@
 extern struct display *init_initial_display P_ ((void));
 extern struct display *term_init P_ ((char *, char *, int));
 extern void fatal P_ ((/* char *, ... */));
-void cursor_to P_ ((int, int));
+extern void cursor_to P_ ((int, int));
 extern int tty_capable_p P_ ((struct tty_display_info *, unsigned, unsigned long, unsigned long));
 
 /* Defined in scroll.c */
--- a/src/dispnew.c	Fri Jan 09 18:57:53 2004 +0000
+++ b/src/dispnew.c	Sat Jan 10 12:56:22 2004 +0000
@@ -6650,6 +6650,7 @@
     f->output_method = d->type;
     f->display = d;
 
+    d->reference_count++;
     d->display_info.tty->top_frame = selected_frame;
     change_frame_size (XFRAME (selected_frame), FrameRows (d->display_info.tty), FrameCols (d->display_info.tty), 0, 0, 1);
 
--- a/src/frame.c	Fri Jan 09 18:57:53 2004 +0000
+++ b/src/frame.c	Sat Jan 10 12:56:22 2004 +0000
@@ -630,6 +630,10 @@
 #endif
 
     /* Set the top frame to the newly created frame. */
+    if (FRAME_TTY (f)->top_frame
+        && FRAME_LIVE_P (XFRAME (FRAME_TTY (f)->top_frame)))
+      XFRAME (FRAME_TTY (f)->top_frame)->async_visible = 2; /* obscured */
+    
     FRAME_TTY (f)->top_frame = frame;
   }
   
@@ -695,19 +699,25 @@
     tty = Fassq (Qtty, parms);
     if (EQ (tty, Qnil))
       tty = Fassq (Qtty, XFRAME (selected_frame)->param_alist);
+    if (EQ (tty, Qnil) && FRAME_TERMCAP_P (XFRAME (selected_frame))
+        && FRAME_TTY (XFRAME (selected_frame))->name)
+      tty = build_string (FRAME_TTY (XFRAME (selected_frame))->name);
     if (EQ (tty, Qnil))
       tty = Fassq (Qtty, Vdefault_frame_alist);
-    if (! EQ (tty, Qnil))
+    if (! EQ (tty, Qnil) && ! STRINGP (tty))
       tty = XCDR (tty);
     if (EQ (tty, Qnil) || !STRINGP (tty))
       tty = Qnil;
 
     tty_type = Fassq (Qtty_type, parms);
     if (EQ (tty_type, Qnil))
-      tty_type = Fassq (Qtty_type, Vdefault_frame_alist);
+      tty_type = Fassq (Qtty, XFRAME (selected_frame)->param_alist);
+    if (EQ (tty_type, Qnil) && FRAME_TERMCAP_P (XFRAME (selected_frame))
+        && FRAME_TTY (XFRAME (selected_frame))->type)
+      tty_type = build_string (FRAME_TTY (XFRAME (selected_frame))->type);
     if (EQ (tty_type, Qnil))
-      tty_type = Fassq (Qtty, XFRAME (selected_frame)->param_alist);
-    if (! EQ (tty_type, Qnil))
+      tty_type = Fassq (Qtty_type, Vdefault_frame_alist);
+    if (! EQ (tty_type, Qnil) && ! STRINGP (tty_type))
       tty_type = XCDR (tty_type);
     if (EQ (tty_type, Qnil) || !STRINGP (tty_type))
       tty_type = Qnil;
--- a/src/keyboard.c	Fri Jan 09 18:57:53 2004 +0000
+++ b/src/keyboard.c	Sat Jan 10 12:56:22 2004 +0000
@@ -692,6 +692,7 @@
 static void clear_event P_ ((struct input_event *));
 static void any_kboard_state P_ ((void));
 static SIGTYPE interrupt_signal P_ ((int signalnum));
+static void handle_interrupt P_ ((void));
 
 /* Nonzero means don't try to suspend even if the operating system seems
    to support it.  */
@@ -1202,10 +1203,7 @@
   if (!sf->glyphs_initialized_p
       /* This is the case of the frame dumped with Emacs, when we're
 	 running under a window system.  */
-      || (!NILP (Vwindow_system)
-	  && !inhibit_window_system
-	  && FRAME_TERMCAP_P (sf)
-          && !FRAME_TTY (sf)->type) /* XXX This is ugly. */
+      || FRAME_INITIAL_P (sf)
       || noninteractive)
     {
       stream = Qexternal_debugging_output;
@@ -3606,7 +3604,7 @@
 	  }
 
 	  last_event_timestamp = event->timestamp;
-	  interrupt_signal (0 /* dummy */);
+	  handle_interrupt ();
 	  return;
 	}
 
@@ -10235,10 +10233,10 @@
 {
   input_available_clear_time = time_to_clear;
 
-  /* Tell interrupt_signal to throw back to read_char,  */
+  /* Tell handle_interrupt to throw back to read_char,  */
   waiting_for_input = 1;
 
-  /* If interrupt_signal was called before and buffered a C-g,
+  /* If handle_interrupt was called before and buffered a C-g,
      make it run again now, to avoid timing error. */
   if (!NILP (Vquit_flag))
     quit_throw_to_read_char ();
@@ -10247,7 +10245,7 @@
 void
 clear_waiting_for_input ()
 {
-  /* Tell interrupt_signal not to throw back to read_char,  */
+  /* Tell handle_interrupt not to throw back to read_char,  */
   waiting_for_input = 0;
   input_available_clear_time = 0;
 }
@@ -10263,16 +10261,16 @@
 
    Otherwise it sets the Lisp variable quit-flag not-nil.  This causes
    eval to throw, when it gets a chance.  If quit-flag is already
-   non-nil, it stops the job right away.  */
+   non-nil, it stops the job right away.
+
+   XXX This comment needs to be updated.  */
 
 static SIGTYPE
 interrupt_signal (signalnum)	/* If we don't have an argument, */
      int signalnum;		/* some compilers complain in signal calls. */
 {
-  char c;
   /* Must preserve main program's value of errno.  */
   int old_errno = errno;
-  struct frame *sf = SELECTED_FRAME ();
 
 #if defined (USG) && !defined (POSIX_SIGNALS)
   /* USG systems forget handlers when they are used;
@@ -10298,6 +10296,20 @@
       return;
     }
 
+  handle_interrupt ();
+
+  errno = old_errno;
+}
+
+/* C-g processing, signal independent code.
+
+   XXX Expand this comment.  */
+static void
+handle_interrupt ()
+{
+  char c; 
+  struct frame *sf = SELECTED_FRAME ();
+
   cancel_echoing ();
 
   /* XXX This code needs to be revised for multi-tty support. */
@@ -10418,8 +10430,6 @@
 
   if (waiting_for_input && !echoing)
     quit_throw_to_read_char ();
-
-  errno = old_errno;
 }
 
 /* Handle a C-g by making read_char return C-g.  */
--- a/src/termhooks.h	Fri Jan 09 18:57:53 2004 +0000
+++ b/src/termhooks.h	Sat Jan 10 12:56:22 2004 +0000
@@ -528,5 +528,8 @@
 extern struct display *create_display P_ ((void));
 extern void delete_display P_ ((struct display *));
 
+/* The initial display device, created by initial_term_init. */
+extern struct display *initial_display;
+
 /* arch-tag: 33a00ecc-52b5-4186-a410-8801ac9f087d
    (do not change this comment) */
--- a/src/xdisp.c	Fri Jan 09 18:57:53 2004 +0000
+++ b/src/xdisp.c	Sat Jan 10 12:56:22 2004 +0000
@@ -16213,6 +16213,14 @@
       return "T";
 #endif
 
+    case 'T':
+      /* %T is the frame name on a termcap frame, the empty string otherwise. */
+      if (! FRAME_TERMCAP_P (f))
+        return "";
+      if (!NILP (f->title))
+	return (char *) SDATA (f->title);
+      return (char *) SDATA (f->name);
+
     case 'z':
       /* coding-system (not including end-of-line format) */
     case 'Z':