Reimplement and extend support for terminal-local environment variables.
authorKaroly Lorentey <lorentey@elte.hu>
Thu, 22 Dec 2005 21:02:45 +0000 (21:02 +0000)
committerKaroly Lorentey <lorentey@elte.hu>
Thu, 22 Dec 2005 21:02:45 +0000 (21:02 +0000)
* lisp/termdev.el: New file.  Move terminal parameter-related functions
  here from frame.el.
  (terminal-getenv, with-terminal-environment): Reimplement and extend.
  (terminal-setenv, terminal-setenv-internal): New functions.

* lisp/frame.el (make-frame-on-tty, framep-on-display, suspend-frame):
  Extend doc string, update parameter names.
  (terminal-id, terminal-parameter-alist, terminal-parameters)
  (terminal-parameter-p, terminal-parameter, set-terminal-parameter)
  (terminal-handle-delete-frame, terminal-getenv, terminal-getenv)
  (with-terminal-environment): Move to termdev.el.

* lisp/loadup.el: Load termdev as well.
* lisp/Makefile.in (lisp, shortlisp): Add termdev.elc.
* lisp/makefile.MPW (shortlisp): Ditto.

* lisp/ebuff-menu.el (electric-buffer-menu-mode-map): Bind C-z to
  `suspend-frame', not `suspend-emacs'.
* lisp/echistory.el (electric-history-map): Ditto.
* lisp/ebrowse.el (ebrowse-electric-list-mode-map): Ditto.
* lisp/ebrowse.el (ebrowse-electric-position-mode-map): Ditto.

* lisp/startup.el (normal-splash-screen): Use `save-buffers-kill-display'
  instead of `save-buffers-kill-emacs'.

* lisp/x-win.el (x-initialize-window-system): Add 'global-ok option to
  `terminal-getenv'.

* src/term.c (suspend-tty): Update doc string.

git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-456

13 files changed:
README.multi-tty
lisp/ebuff-menu.el
lisp/echistory.el
lisp/frame.el
lisp/loadup.el
lisp/progmodes/ebrowse.el
lisp/startup.el
lisp/term/x-win.el
lisp/termdev.el [new file with mode: 0644]
mac/makefile.MPW
src/Makefile.in
src/print.c
src/term.c

index 5deb706..5cc5fbc 100644 (file)
@@ -89,7 +89,7 @@ frames.  It has been changed open new Emacs frames by default.
 
 The multi-tty branch has been scheduled for inclusion in the next
 major release of Emacs (version 23).  I expect the merge into the
-development trunk to occur sometime during next year (2005), after the
+development trunk to occur sometime during next year (2006), after the
 merge of the Unicode branch.
 
 Tested on GNU/Linux, Solaris 8, FreeBSD and OpenBSD.  Please let me
@@ -140,36 +140,36 @@ Known problems:
          system-dependent source files need to be adapted
          accordingly.  The changes are mostly trivial, so almost
          anyone can help, if only by compiling the branch and
-         reporting the compiler errors.  (It is not worth to do this
-         yet, though.)
+         reporting the compiler errors.
 
 
 HOW TO GET THE BRANCH
 ---------------------
 
-The branch uses GNU Arch (http://www.gnuarch.org) for version control.
+The branch uses Bazaar 1 (http://bazaar.canonical.com) for version control.
 
 Retrieving the latest version of the branch:
 
-       tla register-archive -f http://lorentey.hu/arch/2004/
-       tla get lorentey@elte.hu--2004/emacs--multi-tty <directory>
+       baz register-archive -f http://aszt.inf.elte.hu/~lorentey/mirror/arch/2004
+       baz get lorentey@elte.hu--2004/emacs--multi-tty <directory>
 
-This incantation uses my private archive mirror that is hosted on a
-relatively low-bandwidth site; if you are outside Hungary, you will
-probably want to you use my secondary mirror: (Note that the -f option
-will overwrite the archive location if you have previously registered
-the Hungarian one.)
+This incantation uses an archive mirror that is hosted on a
+high-bandwidth site.  Please note that on average there is a two-hour
+delay for commits to arrive on this mirror.  My primary mirror is on the
+low-bandwidth http://lorentey.hu/ site:
 
-       tla register-archive -f http://aszt.inf.elte.hu/~lorentey/mirror/arch/2004
-       tla get lorentey@elte.hu--2004/emacs--multi-tty <directory>
+       baz register-archive -f http://lorentey.hu/arch/2004/
+       baz get lorentey@elte.hu--2004/emacs--multi-tty <directory>
 
-       http://aszt.inf.elte.hu/~lorentey/mirror/arch/2004
+This is "instantly" updated, but very slow from outside Hungary.
+(By "instantly" I mean as soon as I connect the notebook I work on to
+a network.  It could take days.)
 
 The Arch supermirror provides mirroring services for all public Arch
 repositories.  We have a mirror there, too, if you prefer.
 
-       tla register-archive -f http://mirrors.sourcecontrol.net/lorentey%40elte.hu--2004
-       tla get lorentey@elte.hu--2004/emacs--multi-tty <directory>
+       baz register-archive -f http://mirrors.sourcecontrol.net/lorentey%40elte.hu--2004
+       baz get lorentey@elte.hu--2004/emacs--multi-tty <directory>
 
 My GPG key id is 0FB27A3F; it is available from
 hkp://wwwkeys.eu.pgp.net/, or from my homepage at
@@ -179,16 +179,20 @@ Don't worry if the above checkout takes a few minutes to complete;
 once you have a source tree, updating it to the latest revision will
 be _much_ faster.  Use the following command for the update:
 
-       tla replay
+       baz replay
 
-You can find more information about Arch on http://wiki.gnuarch.org/.
-It's a wonderful source control system, I highly recommend it.
+You can find more information about Bazaar on
+http://bazaar.canonical.com/.  It's a distributed source control
+system that is somewhat less broken than competing projects.
 
-If you don't have tla, the branch has a homepage from which you can
+If you don't have Bazaar, the branch has a homepage from which you can
 download conventional patches against Emacs CVS HEAD:
 
        http://lorentey.hu/project/emacs.html
 
+I suggest you use Bazaar whenever feasible.
+
+
 DEBIAN PACKAGES
 ---------------
 
@@ -244,9 +248,10 @@ finish editing the specified files (C-x #), but delete-frame (C-x 5 0)
 also works.  Of course, you can create frames on more than two tty
 devices.
 
-Creating new frames on the same tty with C-x 5 2 works, and they
-behave the same way as in previous Emacs versions.  If you exit emacs,
-all terminals should be restored to their previous states.
+Creating new frames on the same tty with C-x 5 2 (make-frame-command)
+works, and they behave the same way as in previous Emacs versions.  If
+you exit emacs, all terminals should be restored to their previous
+states.
 
 This is work in progress, and probably full of bugs.  It is a good
 idea to run emacs from gdb, so that you'll have a live instance to
@@ -384,6 +389,8 @@ For the NEWS file:  (Needs much, much work)
 
 *** talk.el has been extended for multiple tty support.
 
+*** C-z now invokes `suspend-frame', C-x C-c now invokes
+    `save-buffers-kill-frame'.
 
 * * *
 
@@ -393,6 +400,10 @@ is probably not very interesting for anyone else.)
 THINGS TO DO
 ------------
 
+** Search for `suspend-emacs' references and replace them with
+   `suspend-frame', if necessary.  Ditto for `save-buffers-kill-emacs'
+   vs. `save-buffers-kill-display'.
+
 ** Emacs crashes when a tty frame is resized so that there is no space
    for all its windows.  (Tom Schutzer-Weissmann)
 
index 2ee9019..61895db 100644 (file)
@@ -175,7 +175,7 @@ Entry to this mode via command `electric-buffer-list' calls the value of
   (let ((map (make-keymap)))
     (fillarray (car (cdr map)) 'Electric-buffer-menu-undefined)
     (define-key map "\e" nil)
-    (define-key map "\C-z" 'suspend-emacs)
+    (define-key map "\C-z" 'suspend-frame)
     (define-key map "v" 'Electric-buffer-menu-mode-view-buffer)
     (define-key map (char-to-string help-char) 'Helper-help)
     (define-key map "?" 'Helper-describe-bindings)
index 6556680..a8ec763 100644 (file)
@@ -65,7 +65,7 @@ With prefix arg NOCONFIRM, execute current line as-is without editing."
   (define-key electric-history-map "\C-c" nil)
   (define-key electric-history-map "\C-c\C-c" 'Electric-history-quit)
   (define-key electric-history-map "\C-]" 'Electric-history-quit)
-  (define-key electric-history-map "\C-z" 'suspend-emacs)
+  (define-key electric-history-map "\C-z" 'suspend-frame)
   (define-key electric-history-map (char-to-string help-char) 'Helper-help)
   (define-key electric-history-map "?" 'Helper-describe-bindings)
   (define-key electric-history-map "\e>" 'end-of-buffer)
index 0061119..ecf0697 100644 (file)
@@ -598,15 +598,18 @@ The optional second argument PARAMETERS specifies additional frame parameters."
     (x-initialize-window-system))
   (make-frame `((window-system . x) (display . ,display) . ,parameters)))
 
-(defun make-frame-on-tty (device type &optional parameters)
-  "Make a frame on terminal DEVICE which is of type TYPE (e.g., \"xterm\").
-The optional third argument PARAMETERS specifies additional frame parameters."
+(defun make-frame-on-tty (tty type &optional parameters)
+  "Make a frame on terminal device TTY.
+TTY should be the file name of the tty device to use.  TYPE
+should be the terminal type string of TTY, for example \"xterm\"
+or \"vt100\".  The optional third argument PARAMETERS specifies
+additional frame parameters."
   (interactive "fOpen frame on tty device: \nsTerminal type of %s: ")
-  (unless device
+  (unless tty
     (error "Invalid terminal device"))
   (unless type
     (error "Invalid terminal type"))
-  (make-frame `((window-system . nil) (tty . ,device) (tty-type . ,type) . ,parameters)))
+  (make-frame `((window-system . nil) (tty . ,tty) (tty-type . ,type) . ,parameters)))
 
 (defun make-frame-command ()
   "Make a new frame, and select it if the terminal displays only one frame."
@@ -710,15 +713,15 @@ frame's terminal device."
                   (eq (frame-display frame) terminal))))
     (filtered-frame-list func)))
 
-(defun framep-on-display (&optional display)
-  "Return the type of frames on DISPLAY.
-DISPLAY may be a display id, a display name or a frame.  If it is
-a frame, its type is returned.
-If DISPLAY is omitted or nil, it defaults to the selected frame's display.
-All frames on a given display are of the same type."
-  (or (display-live-p display)
-      (framep display)
-      (framep (car (frames-on-display-list display)))))
+(defun framep-on-display (&optional terminal)
+  "Return the type of frames on TERMINAL.
+TERMINAL may be a terminal id, a display name or a frame.  If it
+is a frame, its type is returned.  If TERMINAL is omitted or nil,
+it defaults to the selected frame's terminal device.  All frames
+on a given display are of the same type."
+  (or (display-live-p terminal)
+      (framep terminal)
+      (framep (car (frames-on-display-list terminal)))))
 
 (defun frame-remove-geometry-params (param-list)
   "Return the parameter list PARAM-LIST, but with geometry specs removed.
@@ -796,8 +799,8 @@ Otherwise, that variable should be nil."
 
 (defun suspend-frame ()
   "Do whatever is right to suspend the current frame.
-Calls `suspend-emacs' if invoked from the controlling terminal,
-`suspend-tty' from a secondary terminal, and
+Calls `suspend-emacs' if invoked from the controlling tty device,
+`suspend-tty' from a secondary tty device, and
 `iconify-or-deiconify-frame' from an X frame."
   (interactive)
   (let ((type (framep (selected-frame))))
@@ -809,7 +812,6 @@ Calls `suspend-emacs' if invoked from the controlling terminal,
        (suspend-tty)))
      (t (suspend-emacs)))))
 
-
 (defun make-frame-names-alist ()
   (let* ((current-frame (selected-frame))
         (falist
@@ -1425,146 +1427,6 @@ Use Custom to set this variable to get the display updated."
 (define-key ctl-x-5-map "0" 'delete-frame)
 (define-key ctl-x-5-map "o" 'other-frame)
 
-(substitute-key-definition 'suspend-emacs 'suspend-frame global-map)
-
-
-(defun terminal-id (terminal)
-  "Return the numerical id of terminal TERMINAL.
-
-TERMINAL can be a terminal id (an integer), a frame, or
-nil (meaning the selected frame's terminal).  Alternatively,
-TERMINAL may be the name of an X display
-device (HOST.SERVER.SCREEN) or a tty device file."
-  (cond
-   ((integerp terminal)
-    (if (display-live-p terminal)
-       terminal
-      (signal 'wrong-type-argument (list 'display-live-p terminal))))
-   ((or (null terminal) (framep terminal))
-    (frame-display terminal))
-   ((stringp terminal)
-    (let ((f (car (filtered-frame-list (lambda (frame)
-                                        (or (equal (frame-parameter frame 'display) terminal)
-                                            (equal (frame-parameter frame 'tty) terminal)))))))
-      (or f (error "Display %s does not exist" terminal))
-      (frame-display f)))
-   (t
-    (error "Invalid argument %s in `terminal-id'" terminal))))
-
-(defvar terminal-parameter-alist nil
-  "An alist of terminal parameter alists.")
-
-(defun terminal-parameters (&optional terminal)
-  "Return the paramater-alist of terminal TERMINAL.
-It is a list of elements of the form (PARM . VALUE), where PARM is a symbol.
-
-TERMINAL can be a terminal id, a frame, or nil (meaning the
-selected frame's terminal)."
-  (cdr (assq (terminal-id terminal) terminal-parameter-alist)))
-
-(defun terminal-parameter-p (terminal parameter)
-  "Return non-nil if PARAMETER is a terminal parameter on TERMINAL.
-
-The actual value returned in that case is a cell (PARAMETER . VALUE),
-where VALUE is the current value of PARAMETER.
-
-TERMINAL can be a terminal id, a frame, or nil (meaning the
-selected frame's terminal)."
-  (assq parameter (cdr (assq (terminal-id terminal) terminal-parameter-alist))))
-
-(defun terminal-parameter (terminal parameter)
-  "Return TERMINAL's value for parameter PARAMETER.
-
-TERMINAL can be a terminal id, a frame, or nil (meaning the
-selected frame's terminal)."
-  (cdr (terminal-parameter-p terminal parameter)))
-
-(defun set-terminal-parameter (terminal parameter value)
-  "Set TERMINAL's value for parameter PARAMETER to VALUE.
-Returns the previous value of PARAMETER.
-
-TERMINAL can be a terminal id, a frame, or nil (meaning the
-selected frame's terminal)."
-  (setq terminal (terminal-id terminal))
-  (let* ((alist (assq terminal terminal-parameter-alist))
-        (pair (assq parameter (cdr alist)))
-        (result (cdr pair)))
-    (cond
-     (pair (setcdr pair value))
-     (alist (setcdr alist (cons (cons parameter value) (cdr alist))))
-     (t (setq terminal-parameter-alist
-             (cons (cons terminal
-                         (cons (cons parameter value)
-                               nil))
-                   terminal-parameter-alist))))
-    result))
-
-(defun terminal-handle-delete-frame (frame)
-  "Clean up terminal parameters of FRAME, if it's the last frame on its terminal."
-  ;; XXX We assume that the display is closed immediately after the
-  ;; last frame is deleted on it.  It would be better to create a hook
-  ;; called `delete-display-functions', and use it instead.
-  (when (and (frame-live-p frame)
-            (= 1 (length (frames-on-display-list (frame-display frame)))))
-    (setq terminal-parameter-alist
-         (assq-delete-all (frame-display frame) terminal-parameter-alist))))
-
-(add-hook 'delete-frame-functions 'terminal-handle-delete-frame)
-
-(defun terminal-getenv (variable &optional terminal)
-  "Get the value of VARIABLE in the client environment of TERMINAL.
-VARIABLE should be a string.  Value is nil if VARIABLE is undefined in
-the environment.  Otherwise, value is a string.
-
-If TERMINAL was created by an emacsclient invocation, then the
-variable is looked up in the environment of the emacsclient
-process; otherwise the function consults the environment of the
-Emacs process.
-
-TERMINAL can be a terminal id, a frame, or nil (meaning the
-selected frame's terminal)."
-  (setq terminal (terminal-id terminal))
-  (if (not (terminal-parameter-p terminal 'environment))
-      (getenv variable)
-    (let ((env (terminal-parameter terminal 'environment))
-         result entry)
-      (while (and env (null result))
-       (setq entry (car env)
-             env (cdr env))
-       (if (and (> (length entry) (length variable))
-                (eq ?= (aref entry (length variable)))
-                (equal variable (substring entry 0 (length variable))))
-           (setq result (substring entry (+ (length variable) 1)))))
-      (if (null result)
-         (getenv variable)
-       result))))
-
-(defmacro with-terminal-environment (terminal vars &rest body)
-  "Evaluate BODY with environment variables VARS set to those of TERMINAL.
-The environment variables are then restored to their previous values.
-
-VARS should be a list of strings.
-
-TERMINAL can be a terminal id, a frame, or nil (meaning the
-selected frame's terminal).
-
-See also `terminal-getenv'."
-  (declare (indent 2))
-  (let ((oldvalues (make-symbol "oldvalues"))
-       (var (make-symbol "var"))
-       (value (make-symbol "value"))
-       (pair (make-symbol "pair")))
-    `(let (,oldvalues)
-       (dolist (,var ,vars)
-        (let ((,value (terminal-getenv ,var ,terminal)))
-          (setq ,oldvalues (cons (cons ,var (getenv ,var)) ,oldvalues))
-          (setenv ,var ,value)))
-       (unwind-protect
-          (progn ,@body)
-        (dolist (,pair ,oldvalues)
-          (setenv (car ,pair) (cdr ,pair)))))))
-
-
 (provide 'frame)
 
 ;; arch-tag: 82979c70-b8f2-4306-b2ad-ddbd6b328b56
index a8e23c4..e5bcf24 100644 (file)
 (load "indent")
 (load "window")
 (load "frame")
+(load "termdev")
 (load "term/tty-colors")
 (load "font-core")
 ;; facemenu must be loaded before font-lock, because `facemenu-keymap'
index 47e9a12..371cb48 100644 (file)
@@ -2004,7 +2004,7 @@ COLLAPSE non-nil means collapse the branch."
     (fillarray (car (cdr map)) 'ebrowse-electric-list-undefined)
     (fillarray (car (cdr submap)) 'ebrowse-electric-list-undefined)
     (define-key map "\e" submap)
-    (define-key map "\C-z" 'suspend-emacs)
+    (define-key map "\C-z" 'suspend-frame)
     (define-key map "\C-h" 'Helper-help)
     (define-key map "?" 'Helper-describe-bindings)
     (define-key map "\C-c" nil)
@@ -3964,7 +3964,7 @@ Prefix arg ARG says how much."
     (fillarray (car (cdr map)) 'ebrowse-electric-position-undefined)
     (fillarray (car (cdr submap)) 'ebrowse-electric-position-undefined)
     (define-key map "\e" submap)
-    (define-key map "\C-z" 'suspend-emacs)
+    (define-key map "\C-z" 'suspend-frame)
     (define-key map "\C-h" 'Helper-help)
     (define-key map "?" 'Helper-describe-bindings)
     (define-key map "\C-c" nil)
index e895d33..533f9db 100644 (file)
@@ -1429,7 +1429,7 @@ Copyright (C) 2005 Free Software Foundation, Inc."))
              ;; use precomputed string to save lots of time.
              (if (and (eq (key-binding "\C-h") 'help-command)
                       (eq (key-binding "\C-xu") 'advertised-undo)
-                      (eq (key-binding "\C-x\C-c") 'save-buffers-kill-emacs)
+                      (eq (key-binding "\C-x\C-c") 'save-buffers-kill-display)
                       (eq (key-binding "\C-ht") 'help-with-tutorial)
                       (eq (key-binding "\C-hi") 'info)
                       (eq (key-binding "\C-hr") 'info-emacs-manual)
@@ -1446,7 +1446,7 @@ Browse manuals     C-h i")
 Get help          %s
 Emacs manual      \\[info-emacs-manual]
 Emacs tutorial    \\[help-with-tutorial]\tUndo changes\t\\[advertised-undo]
-Buy manuals        \\[view-order-manuals]\tExit Emacs\t\\[save-buffers-kill-emacs]
+Buy manuals        \\[view-order-manuals]\tExit Emacs\t\\[save-buffers-kill-display]
 Browse manuals     \\[info]"
                                 (let ((where (where-is-internal
                                               'help-command nil t)))
index ff36914..49ef4cb 100644 (file)
@@ -2407,7 +2407,7 @@ order until succeed.")
          (aset x-resource-name i ?-))))
 
   (x-open-connection (or x-display-name
-                        (setq x-display-name (terminal-getenv "DISPLAY")))
+                        (setq x-display-name (terminal-getenv "DISPLAY" nil 'global-ok)))
                     x-command-line-resources
                     ;; Exit Emacs with fatal error if this fails and we
                     ;; are the initial display.
diff --git a/lisp/termdev.el b/lisp/termdev.el
new file mode 100644 (file)
index 0000000..667975b
--- /dev/null
@@ -0,0 +1,255 @@
+;;; termdev.el --- functions for dealing with terminals
+
+;; Copyright (C) 2005 Free Software Foundation, Inc.
+
+;; Author: Karoly Lorentey <karoly@lorentey.hu>
+;; Created: 2005-12-22
+;; Keywords: internal
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+(substitute-key-definition 'suspend-emacs 'suspend-frame global-map)
+
+(defun terminal-id (terminal)
+  "Return the numerical id of terminal TERMINAL.
+
+TERMINAL can be a terminal id (an integer), a frame, or
+nil (meaning the selected frame's terminal).  Alternatively,
+TERMINAL may be the name of an X display
+device (HOST.SERVER.SCREEN) or a tty device file."
+  (cond
+   ((integerp terminal)
+    (if (display-live-p terminal)
+       terminal
+      (signal 'wrong-type-argument (list 'display-live-p terminal))))
+   ((or (null terminal) (framep terminal))
+    (frame-display terminal))
+   ((stringp terminal)
+    (let ((f (car (filtered-frame-list (lambda (frame)
+                                        (or (equal (frame-parameter frame 'display) terminal)
+                                            (equal (frame-parameter frame 'tty) terminal)))))))
+      (or f (error "Display %s does not exist" terminal))
+      (frame-display f)))
+   (t
+    (error "Invalid argument %s in `terminal-id'" terminal))))
+
+(defvar terminal-parameter-alist nil
+  "An alist of terminal parameter alists.")
+
+(defun terminal-parameters (&optional terminal)
+  "Return the paramater-alist of terminal TERMINAL.
+It is a list of elements of the form (PARM . VALUE), where PARM is a symbol.
+
+TERMINAL can be a terminal id, a frame, or nil (meaning the
+selected frame's terminal)."
+  (cdr (assq (terminal-id terminal) terminal-parameter-alist)))
+
+(defun terminal-parameter-p (terminal parameter)
+  "Return non-nil if PARAMETER is a terminal parameter on TERMINAL.
+
+The actual value returned in that case is a cell (PARAMETER . VALUE),
+where VALUE is the current value of PARAMETER.
+
+TERMINAL can be a terminal id, a frame, or nil (meaning the
+selected frame's terminal)."
+  (assq parameter (cdr (assq (terminal-id terminal) terminal-parameter-alist))))
+
+(defun terminal-parameter (terminal parameter)
+  "Return TERMINAL's value for parameter PARAMETER.
+
+TERMINAL can be a terminal id, a frame, or nil (meaning the
+selected frame's terminal)."
+  (cdr (terminal-parameter-p terminal parameter)))
+
+(defun set-terminal-parameter (terminal parameter value)
+  "Set TERMINAL's value for parameter PARAMETER to VALUE.
+Returns the previous value of PARAMETER.
+
+TERMINAL can be a terminal id, a frame, or nil (meaning the
+selected frame's terminal)."
+  (setq terminal (terminal-id terminal))
+  (let* ((alist (assq terminal terminal-parameter-alist))
+        (pair (assq parameter (cdr alist)))
+        (result (cdr pair)))
+    (cond
+     (pair (setcdr pair value))
+     (alist (setcdr alist (cons (cons parameter value) (cdr alist))))
+     (t (setq terminal-parameter-alist
+             (cons (cons terminal
+                         (cons (cons parameter value)
+                               nil))
+                   terminal-parameter-alist))))
+    result))
+
+(defun terminal-handle-delete-frame (frame)
+  "Clean up terminal parameters of FRAME, if it's the last frame on its terminal."
+  ;; XXX We assume that the display is closed immediately after the
+  ;; last frame is deleted on it.  It would be better to create a hook
+  ;; called `delete-display-functions', and use it instead.
+  (when (and (frame-live-p frame)
+            (= 1 (length (frames-on-display-list (frame-display frame)))))
+    (setq terminal-parameter-alist
+         (assq-delete-all (frame-display frame) terminal-parameter-alist))))
+
+(add-hook 'delete-frame-functions 'terminal-handle-delete-frame)
+
+(defun terminal-getenv (variable &optional terminal global-ok)
+  "Get the value of VARIABLE in the client environment of TERMINAL.
+VARIABLE should be a string.  Value is nil if VARIABLE is undefined in
+the environment.  Otherwise, value is a string.
+
+If TERMINAL has an associated emacsclient process, then
+`terminal-getenv' looks up VARIABLE in the environment of that
+process; otherwise the function consults the global environment,
+i.e., the environment of the Emacs process itself.
+
+If GLOBAL-OK is non-nil, and VARIABLE is not defined in the
+terminal-local environment, then `terminal-getenv' will return
+its value in the global environment instead.
+
+TERMINAL can be a terminal id, a frame, or nil (meaning the
+selected frame's terminal)."
+  (setq terminal (terminal-id terminal))
+  (if (not (terminal-parameter-p terminal 'environment))
+      (getenv variable)
+    (if (multibyte-string-p variable)
+       (setq variable (encode-coding-string variable locale-coding-system)))
+    (let ((env (terminal-parameter terminal 'environment))
+         result entry)
+      (while (and env (null result))
+       (setq entry (car env)
+             env (cdr env))
+       (if (and (> (length entry) (length variable))
+                (eq ?= (aref entry (length variable)))
+                (equal variable (substring entry 0 (length variable))))
+           (setq result (substring entry (+ (length variable) 1)))))
+      (if (and global-ok (null result))
+         (getenv variable)
+       (and result (decode-coding-string result locale-coding-system))))))
+
+(defun terminal-setenv (variable &optional value terminal)
+  "Set the value of VARIABLE in the environment of TERMINAL.
+VARIABLE should be string.  VALUE is optional; if not provided or
+nil, the environment variable VARIABLE is removed.  Returned
+value is the new value of VARIABLE, or nil if it was removed from
+the environment.
+
+If TERMINAL was created by an emacsclient invocation, then the
+variable is set in the environment of the emacsclient process;
+otherwise the function changes the environment of the Emacs
+process itself.
+
+TERMINAL can be a terminal id, a frame, or nil (meaning the
+selected frame's terminal)."
+  (if (not (terminal-parameter-p terminal 'environment))
+      (setenv variable value)
+    (with-terminal-environment terminal variable
+      (setenv variable value))))
+
+(defun terminal-setenv-internal (variable value terminal)
+  "Set the value of VARIABLE in the environment of TERMINAL.
+The caller is responsible to ensure that both VARIABLE and VALUE
+are usable in environment variables and that TERMINAL is a
+remote terminal."
+  (if (multibyte-string-p variable)
+      (setq variable (encode-coding-string variable locale-coding-system)))
+  (if (and value (multibyte-string-p value))
+      (setq value (encode-coding-string value locale-coding-system)))
+  (let ((env (terminal-parameter terminal 'environment))
+       found)
+    (while (and env (not found))
+      (if (and (> (length (car env)) (length variable))
+                (eq ?= (aref (car env) (length variable)))
+                (equal variable (substring (car env) 0 (length variable))))
+         (progn
+           (if value
+               (setcar env (concat variable "=" value))
+             (set-terminal-parameter terminal 'environment
+                                     (delq (car env)
+                                           (terminal-parameter terminal
+                                                               'environment))))
+           (setq found t))
+       (setq env (cdr env))))
+    (cond
+     ((and value found)
+      (setcar env (concat variable "=" value)))
+     ((and value (not found))
+      (set-terminal-parameter terminal 'environment
+                             (cons (concat variable "=" value)
+                                   (terminal-parameter terminal
+                                                       'environment))))
+     ((and (not value) found)
+      (set-terminal-parameter terminal 'environment
+                             (delq (car env)
+                                   (terminal-parameter terminal
+                                                       'environment)))))))
+
+(defmacro with-terminal-environment (terminal vars &rest body)
+  "Evaluate BODY with environment variables VARS set to those of TERMINAL.
+The environment variables are then restored to their previous values.
+
+VARS should be a single string, a list of strings, or t for all
+environment variables.
+
+TERMINAL can be a terminal id, a frame, or nil (meaning the
+selected frame's terminal).
+
+If BODY uses `setenv' to change environment variables in VARS,
+then the new variable values will be remembered for TERMINAL, and
+`terminal-getenv' will return them even outside BODY."
+  (declare (indent 2))
+  (let ((var (make-symbol "var"))
+       (term (make-symbol "term"))
+       (v (make-symbol "v"))
+       (old-env (make-symbol "old-env")))
+    `(let ((,term ,terminal)           ; Evaluate arguments only once.
+          (,v ,vars))
+       (if (stringp ,v)
+          (setq ,v (list ,v)))
+       (cond
+       ((not (terminal-parameter-p ,term 'environment))
+        ;; Not a remote terminal; nothing to do.
+        (progn ,@body))
+       ((eq ,v t)
+        ;; Switch the entire process-environment.
+        (let (,old-env process-environment)
+          (setq process-environment (terminal-parameter ,term 'environment))
+          (unwind-protect
+              (progn ,@body)
+            (set-terminal-parameter ,term 'environment process-environment)
+            (setq process-environment ,old-env))))
+       (t
+        ;; Do only a set of variables.
+        (let (,old-env)
+          (dolist (,var ,v)
+            (setq ,old-env (cons (cons ,var (getenv ,var)) ,old-env))
+            (setenv ,var (terminal-getenv ,var ,term)))
+          (unwind-protect
+              (progn ,@body)
+            ;; Split storing new values and restoring old ones so
+            ;; that we DTRT even if a variable is specified twice in
+            ;; VARS.
+            (dolist (,var ,v)
+              (terminal-setenv-internal ,var (getenv ,var) ,term))
+            (dolist (,var ,old-env)
+              (setenv (car ,var) (cdr ,var))))))))))
+
+(provide 'termdev)
+
+;;; arch-tag: 4c4df277-1ec1-4f56-bfde-7f156fe62fb2
+;;; termdev.el ends here
index 60edb1f..d63ef5b 100644 (file)
@@ -1021,6 +1021,7 @@ shortlisp = 
        {Lisp}emacs-lisp:float-sup.elc ¶
        {Lisp}format.elc ¶
        {Lisp}frame.elc ¶
+       {Lisp}termdev.elc ¶
        {Lisp}help.elc ¶
        {Lisp}indent.elc ¶
        {Lisp}isearch.elc ¶
index 2799b3f..e0ba8a2 100644 (file)
@@ -722,6 +722,7 @@ lisp= \
        MOUSE_SUPPORT \
        ${lispsource}emacs-lisp/float-sup.elc \
        ${lispsource}frame.elc \
+       ${lispsource}termdev.elc \
        ${lispsource}help.elc \
        ${lispsource}indent.elc \
        ${lispsource}isearch.elc \
@@ -819,6 +820,7 @@ shortlisp= \
        ../lisp/emacs-lisp/float-sup.elc \
        ../lisp/format.elc \
        ../lisp/frame.elc \
+       ../lisp/termdev.elc \
        ../lisp/help.elc \
        ../lisp/indent.elc \
        ../lisp/isearch.elc \
index 20c359f..3a1fe33 100644 (file)
@@ -1343,7 +1343,7 @@ print_preprocess (obj)
          for (i = 0; i < print_number_index; i++)
            if (EQ (PRINT_NUMBER_OBJECT (Vprint_number_table, i), obj))
              {
-               /* OBJ appears more than once.  Let's remember that.  */
+               /* OBJ appears more than once.  Let's remember that.  */
                PRINT_NUMBER_STATUS (Vprint_number_table, i) = Qt;
                return;
              }
index 234be4a..679def9 100644 (file)
@@ -3270,23 +3270,23 @@ Display devices are represented by their integer identifiers. */)
 
 DEFUN ("suspend-tty", Fsuspend_tty, Ssuspend_tty, 0, 1, 0,
        doc: /* Suspend the terminal device TTY.
-The terminal is restored to its default state, and Emacs ceases all
-access to the terminal device.  Frames that use the device are not
-deleted, but input is not read from them and if they change, their
-display is not updated.
 
-TTY may be a display id, a frame, or nil for the display device of the
-currently selected frame.
+The device is restored to its default state, and Emacs ceases all
+access to the tty device.  Frames that use the device are not deleted,
+but input is not read from them and if they change, their display is
+not updated.
+
+TTY may be a terminal id, a frame, or nil for the terminal device of
+the currently selected frame.
 
 This function runs `suspend-tty-functions' after suspending the
 device.  The functions are run with one arg, the id of the suspended
-display device.
+terminal device.
 
-`suspend-tty' does nothing if it is called on an already suspended
-device.
+`suspend-tty' does nothing if it is called on a device that is already
+suspended.
 
-A suspended terminal device may be resumed by calling `resume-tty' on
-it. */)
+A suspended tty may be resumed by calling `resume-tty' on it.  */)
   (tty)
      Lisp_Object tty;
 {