Overhaul and simplify single_kboard API. Allow calls to `recursive-edit' in process...
[bpt/emacs.git] / lisp / server.el
index 7aed300..382befd 100644 (file)
@@ -247,7 +247,7 @@ ENV should be in the same format as `process-environment'."
           (setenv (car ,pair) (cdr ,pair)))))))
 
 (defun server-delete-client (client &optional noframe)
-  "Delete CLIENT, including its buffers, devices and frames.
+  "Delete CLIENT, including its buffers, terminals and frames.
 If NOFRAME is non-nil, let the frames live.  (To be used from
 `delete-frame-functions'."
   ;; Force a new lookup of client (prevents infinite recursion).
@@ -270,17 +270,20 @@ If NOFRAME is non-nil, let the frames live.  (To be used from
                           (server-temp-file-p)))
              (kill-buffer (current-buffer))))))
 
-      ;; Delete the client's tty.
-      (let ((device (server-client-get client 'device)))
-       (when (eq (display-live-p device) t)
-         (delete-display device)))
-
       ;; Delete the client's frames.
       (unless noframe
        (dolist (frame (frame-list))
-         (if (and (frame-live-p frame)
-                  (equal (car client) (frame-parameter frame 'client)))
-             (delete-frame frame))))
+         (when (and (frame-live-p frame)
+                    (equal proc (frame-parameter frame 'client)))
+           ;; Prevent `server-handle-delete-frame' from calling us
+           ;; recursively.
+           (set-frame-parameter frame 'client nil)
+           (delete-frame frame))))
+
+      ;; Delete the client's tty.
+      (let ((terminal (server-client-get client 'terminal)))
+       (when (eq (terminal-live-p terminal) t)
+         (delete-terminal terminal)))
 
       ;; Delete the client's process.
       (if (eq (process-status (car client)) 'open)
@@ -318,23 +321,19 @@ message."
   (let ((proc (frame-parameter frame 'client)))
     (when (and (frame-live-p frame)
               proc
-              (or (window-system frame)
-                  ;; A terminal device must not yet be deleted if
-                  ;; there are other frames on it.
-                  (< 0 (let ((frame-num 0))
-                         (mapc (lambda (f)
-                                 (when (eq (frame-display f)
-                                           (frame-display frame))
-                                   (setq frame-num (1+ frame-num))))
-                               (frame-list))
-                         frame-num))))
+              ;; See if this is the last frame for this client.
+              (>= 1 (let ((frame-num 0))
+                     (dolist (f (frame-list))
+                       (when (eq proc (frame-parameter f 'client))
+                         (setq frame-num (1+ frame-num))))
+                     frame-num)))
       (server-log (format "server-handle-delete-frame, frame %s" frame) proc)
       (server-delete-client proc 'noframe)))) ; Let delete-frame delete the frame later.
 
-(defun server-handle-suspend-tty (device)
+(defun server-handle-suspend-tty (terminal)
   "Notify the emacsclient process to suspend itself when its tty device is suspended."
-  (dolist (proc (server-clients-with 'device device))
-    (server-log (format "server-handle-suspend-tty, device %s" device) proc)
+  (dolist (proc (server-clients-with 'terminal terminal))
+    (server-log (format "server-handle-suspend-tty, terminal %s" terminal) proc)
     (condition-case err
        (server-send-string proc "-suspend \n")
       (file-error (condition-case nil (server-delete-client proc) (error nil))))))
@@ -618,13 +617,13 @@ The following commands are accepted by the client:
                                          ;; Flag frame as client-created, but use a dummy client.
                                          ;; This will prevent the frame from being deleted when
                                          ;; emacsclient quits while also preventing
-                                         ;; `server-save-buffers-kill-display' from unexpectedly
+                                         ;; `server-save-buffers-kill-terminal' from unexpectedly
                                          ;; killing emacs on that frame.
-                                         (list (cons 'client 'nowait))
-                                       (list (cons 'client proc)))))
+                                         (list (cons 'client 'nowait) (cons 'environment env))
+                                       (list (cons 'client proc) (cons 'environment env)))))
                          (setq frame (make-frame-on-display
                                       (or display
-                                          (frame-parameter nil 'device)
+                                          (frame-parameter nil 'display)
                                           (getenv "DISPLAY")
                                           (error "Please specify display"))
                                       params))
@@ -636,8 +635,7 @@ The following commands are accepted by the client:
                          (modify-frame-parameters frame params)
                          (select-frame frame)
                          (server-client-set client 'frame frame)
-                         (server-client-set client 'device (frame-display frame))
-                         (set-terminal-parameter frame 'environment env)
+                         (server-client-set client 'terminal (frame-terminal frame))
                          (setq dontkill t))
                      ;; This emacs does not support X.
                      (server-log "Window system unsupported" proc)
@@ -646,19 +644,19 @@ The following commands are accepted by the client:
 
                 ;; -resume:  Resume a suspended tty frame.
                 ((equal "-resume" arg)
-                 (let ((device (server-client-get client 'device)))
+                 (let ((terminal (server-client-get client 'terminal)))
                    (setq dontkill t)
-                   (when (eq (display-live-p device) t)
-                     (resume-tty device))))
+                   (when (eq (terminal-live-p terminal) t)
+                     (resume-tty terminal))))
 
                 ;; -suspend:  Suspend the client's frame.  (In case we
                 ;; get out of sync, and a C-z sends a SIGTSTP to
                 ;; emacsclient.)
                 ((equal "-suspend" arg)
-                 (let ((device (server-client-get client 'device)))
+                 (let ((terminal (server-client-get client 'terminal)))
                    (setq dontkill t)
-                   (when (eq (display-live-p device) t)
-                     (suspend-tty device))))
+                   (when (eq (terminal-live-p terminal) t)
+                     (suspend-tty terminal))))
 
                 ;; -ignore COMMENT:  Noop; useful for debugging emacsclient.
                 ;; (The given comment appears in the server log.)
@@ -684,12 +682,12 @@ The following commands are accepted by the client:
                        (setq frame (make-frame-on-tty tty type
                                                       ;; Ignore nowait here; we always need to clean
                                                       ;; up opened ttys when the client dies.
-                                                      `((client . ,proc)))))
+                                                      `((client . ,proc)
+                                                        (environment . ,env)))))
                      (select-frame frame)
                      (server-client-set client 'frame frame)
-                     (server-client-set client 'tty (display-name frame))
-                     (server-client-set client 'device (frame-display frame))
-                     (set-terminal-parameter frame 'environment env)
+                     (server-client-set client 'tty (terminal-name frame))
+                     (server-client-set client 'terminal (frame-terminal frame))
 
                      ;; Reply with our pid.
                      (server-send-string proc (concat "-emacs-pid " (number-to-string (emacs-pid)) "\n"))
@@ -740,8 +738,7 @@ The following commands are accepted by the client:
                 ;; -env NAME=VALUE:  An environment variable.
                 ((and (equal "-env" arg) (string-match "\\([^ ]+\\) " request))
                  (let ((var (server-unquote-arg (match-string 1 request))))
-                   (when coding-system
-                     (setq var (decode-coding-string var coding-system)))
+                   ;; XXX Variables should be encoded as in getenv/setenv.
                    (setq request (substring request (match-end 0)))
                    (setq env (cons var env))))
 
@@ -754,6 +751,22 @@ The following commands are accepted by the client:
                (setq buffers (server-visit-files files client nowait))
                (run-hooks 'post-command-hook))
 
+             (when frame
+               (with-selected-frame frame
+                 (switch-to-buffer (or (car buffers)
+                                       (get-buffer-create "*scratch*")))
+                 (display-startup-echo-area-message)
+                 (unless inhibit-splash-screen
+                   (condition-case err
+                       ;; This looks scary because `fancy-splash-screens'
+                       ;; will call `recursive-edit' from a process filter.
+                       ;; However, that should be safe to do now.
+                       (display-splash-screen)
+                     ;; `recursive-edit' will throw an error if Emacs is
+                     ;; already doing a recursive edit elsewhere.  Catch it
+                     ;; here so that we can finish normally.
+                     (error nil)))))
+
              ;; Delete the client if necessary.
              (cond
               (nowait
@@ -1039,8 +1052,8 @@ done that."
               (get-window-with-predicate
                (lambda (w)
                  (and (not (window-dedicated-p w))
-                      (equal (frame-parameter (window-frame w) 'device)
-                             (frame-parameter (selected-frame) 'device))))
+                      (equal (frame-terminal (window-frame w))
+                             (frame-terminal (selected-frame)))))
                'nomini 'visible (selected-window))))
            (condition-case nil
                (switch-to-buffer next-buffer)
@@ -1049,7 +1062,7 @@ done that."
              (error (pop-to-buffer next-buffer)))))))))
 
 ;;;###autoload
-(defun server-save-buffers-kill-display (proc &optional arg)
+(defun server-save-buffers-kill-terminal (proc &optional arg)
   "Offer to save each buffer, then kill PROC.
 
 With prefix arg, silently save all file-visiting buffers, then kill.