# HG changeset patch # User Karoly Lorentey # Date 1135285365 0 # Node ID 4513d8dcdfd57f5d5e39176541492fd989c4cd0d # Parent d2c799f58129fae23bf7a2c2f588ea0a94aed354 Reimplement and extend support for terminal-local environment variables. * 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 diff -r d2c799f58129 -r 4513d8dcdfd5 README.multi-tty --- a/README.multi-tty Tue Dec 20 21:35:03 2005 +0000 +++ b/README.multi-tty Thu Dec 22 21:02:45 2005 +0000 @@ -89,7 +89,7 @@ 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 @@ 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 + baz register-archive -f http://aszt.inf.elte.hu/~lorentey/mirror/arch/2004 + baz get lorentey@elte.hu--2004/emacs--multi-tty -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 + baz register-archive -f http://lorentey.hu/arch/2004/ + baz get lorentey@elte.hu--2004/emacs--multi-tty - 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 + baz register-archive -f http://mirrors.sourcecontrol.net/lorentey%40elte.hu--2004 + baz get lorentey@elte.hu--2004/emacs--multi-tty My GPG key id is 0FB27A3F; it is available from hkp://wwwkeys.eu.pgp.net/, or from my homepage at @@ -179,16 +179,20 @@ 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 @@ 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 @@ *** 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 @@ 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) diff -r d2c799f58129 -r 4513d8dcdfd5 lisp/ebuff-menu.el --- a/lisp/ebuff-menu.el Tue Dec 20 21:35:03 2005 +0000 +++ b/lisp/ebuff-menu.el Thu Dec 22 21:02:45 2005 +0000 @@ -175,7 +175,7 @@ (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) diff -r d2c799f58129 -r 4513d8dcdfd5 lisp/echistory.el --- a/lisp/echistory.el Tue Dec 20 21:35:03 2005 +0000 +++ b/lisp/echistory.el Thu Dec 22 21:02:45 2005 +0000 @@ -65,7 +65,7 @@ (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) diff -r d2c799f58129 -r 4513d8dcdfd5 lisp/frame.el --- a/lisp/frame.el Tue Dec 20 21:35:03 2005 +0000 +++ b/lisp/frame.el Thu Dec 22 21:02:45 2005 +0000 @@ -598,15 +598,18 @@ (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 @@ (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 @@ (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 @@ (suspend-tty))) (t (suspend-emacs))))) - (defun make-frame-names-alist () (let* ((current-frame (selected-frame)) (falist @@ -1425,146 +1427,6 @@ (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 diff -r d2c799f58129 -r 4513d8dcdfd5 lisp/loadup.el --- a/lisp/loadup.el Tue Dec 20 21:35:03 2005 +0000 +++ b/lisp/loadup.el Thu Dec 22 21:02:45 2005 +0000 @@ -132,6 +132,7 @@ (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' diff -r d2c799f58129 -r 4513d8dcdfd5 lisp/progmodes/ebrowse.el --- a/lisp/progmodes/ebrowse.el Tue Dec 20 21:35:03 2005 +0000 +++ b/lisp/progmodes/ebrowse.el Thu Dec 22 21:02:45 2005 +0000 @@ -2004,7 +2004,7 @@ (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 @@ (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) diff -r d2c799f58129 -r 4513d8dcdfd5 lisp/startup.el --- a/lisp/startup.el Tue Dec 20 21:35:03 2005 +0000 +++ b/lisp/startup.el Thu Dec 22 21:02:45 2005 +0000 @@ -1429,7 +1429,7 @@ ;; 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 @@ 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))) diff -r d2c799f58129 -r 4513d8dcdfd5 lisp/term/x-win.el --- a/lisp/term/x-win.el Tue Dec 20 21:35:03 2005 +0000 +++ b/lisp/term/x-win.el Thu Dec 22 21:02:45 2005 +0000 @@ -2407,7 +2407,7 @@ (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 -r d2c799f58129 -r 4513d8dcdfd5 lisp/termdev.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/termdev.el Thu Dec 22 21:02:45 2005 +0000 @@ -0,0 +1,255 @@ +;;; termdev.el --- functions for dealing with terminals + +;; Copyright (C) 2005 Free Software Foundation, Inc. + +;; Author: Karoly Lorentey +;; 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 diff -r d2c799f58129 -r 4513d8dcdfd5 mac/makefile.MPW --- a/mac/makefile.MPW Tue Dec 20 21:35:03 2005 +0000 +++ b/mac/makefile.MPW Thu Dec 22 21:02:45 2005 +0000 @@ -1021,6 +1021,7 @@ {Lisp}emacs-lisp:float-sup.elc ¶ {Lisp}format.elc ¶ {Lisp}frame.elc ¶ + {Lisp}termdev.elc ¶ {Lisp}help.elc ¶ {Lisp}indent.elc ¶ {Lisp}isearch.elc ¶ diff -r d2c799f58129 -r 4513d8dcdfd5 src/Makefile.in --- a/src/Makefile.in Tue Dec 20 21:35:03 2005 +0000 +++ b/src/Makefile.in Thu Dec 22 21:02:45 2005 +0000 @@ -722,6 +722,7 @@ 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 @@ ../lisp/emacs-lisp/float-sup.elc \ ../lisp/format.elc \ ../lisp/frame.elc \ + ../lisp/termdev.elc \ ../lisp/help.elc \ ../lisp/indent.elc \ ../lisp/isearch.elc \ diff -r d2c799f58129 -r 4513d8dcdfd5 src/print.c --- a/src/print.c Tue Dec 20 21:35:03 2005 +0000 +++ b/src/print.c Thu Dec 22 21:02:45 2005 +0000 @@ -1343,7 +1343,7 @@ 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; } diff -r d2c799f58129 -r 4513d8dcdfd5 src/term.c --- a/src/term.c Tue Dec 20 21:35:03 2005 +0000 +++ b/src/term.c Thu Dec 22 21:02:45 2005 +0000 @@ -3270,23 +3270,23 @@ 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. - -`suspend-tty' does nothing if it is called on an already suspended -device. - -A suspended terminal device may be resumed by calling `resume-tty' on -it. */) +terminal device. + +`suspend-tty' does nothing if it is called on a device that is already +suspended. + +A suspended tty may be resumed by calling `resume-tty' on it. */) (tty) Lisp_Object tty; {