mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-16 17:24:23 +00:00
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
This commit is contained in:
parent
a18b8cb507
commit
f35ca2fe35
13 changed files with 331 additions and 199 deletions
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
176
lisp/frame.el
176
lisp/frame.el
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)))
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
255
lisp/termdev.el
Normal file
255
lisp/termdev.el
Normal file
|
|
@ -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
|
||||
|
|
@ -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 ¶
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
22
src/term.c
22
src/term.c
|
|
@ -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;
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue