Commit da8e8fc1 authored by Karoly Lorentey's avatar Karoly Lorentey
Browse files

Store local environment in frame (not terminal) parameters.

* src/callproc.c (child_setup, getenv_internal, Fgetenv_internal):
  Store the local environment in a frame (not terminal) parameter.
  Update doc strings.
  (syms_of_callproc): Update doc strings.
  (Qenvironment): Moved to frame.c. 

* lisp/env.el (read-envvar-name, setenv, getenv, environment): Use frame
  parameters to store the local environment, not terminal parameters.

* server.el (server-process-filter): Store the local environment in a
  frame (not terminal) parameter.  Do not try to decode environment
  strings.

* lisp/frame.el (make-frame): Set up the 'environment frame parameter,
  when needed.

* src/frame.c (Qenvironment): Move here from callproc.c.
  (Fdelete_frame): Don't allow other frames to refer to a deleted frame
  in their 'environment parameter.
  (Fframe_with_environment): New function.
  (syms_of_frame): Defsubr it.  Initialize and staticpro Qenvironment.

* frame.h (Qenvironment): Declare.
* lisp.h (Fframe_with_environment): EXFUN it.

git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-467
parent 86f5ca04
...@@ -412,7 +412,10 @@ THINGS TO DO ...@@ -412,7 +412,10 @@ THINGS TO DO
make_terminal_frame make_terminal_frame
create_tty_output create_tty_output
** Decide whether to keep the C implementation of terminal parameters,
or revert to the previous, purely Lisp code. It turned out that
local environments do not need terminal parameters after all.
** Move Fsend_string_to_terminal to term.c, and declare get_named_tty ** Move Fsend_string_to_terminal to term.c, and declare get_named_tty
as static, removing it from dispextern.h. as static, removing it from dispextern.h.
...@@ -1362,5 +1365,16 @@ DIARY OF CHANGES ...@@ -1362,5 +1365,16 @@ DIARY OF CHANGES
`getenv' and `setenv', and the new `local-environment-variables' `getenv' and `setenv', and the new `local-environment-variables'
facility. Yay!) facility. Yay!)
(Updated in patch-465 to fix the semantics of let-binding
`process-environment'. `process-environment' was changed to
override all local/global environment variables, and a new variable
`global-environment' was introduced to have `process-environment's
old meaning.)
(Updated in patch-466 to fix the case when two emacsclient sessions
share the same terminal, but have different environment. The local
environment lists are now stored as frame parameters, so the
C-level terminal parameters are not strictly necessary any more.)
;;; arch-tag: 8da1619e-2e79-41a8-9ac9-a0485daad17d ;;; arch-tag: 8da1619e-2e79-41a8-9ac9-a0485daad17d
...@@ -55,7 +55,7 @@ If it is also not t, RET does not exit if it does non-null completion." ...@@ -55,7 +55,7 @@ If it is also not t, RET does not exit if it does non-null completion."
(substring enventry 0 (substring enventry 0
(string-match "=" enventry))))) (string-match "=" enventry)))))
(append process-environment (append process-environment
(terminal-parameter nil 'environment) (frame-parameter (frame-with-environment) 'environment)
global-environment)) global-environment))
nil mustmatch nil 'read-envvar-name-history)) nil mustmatch nil 'read-envvar-name-history))
...@@ -94,7 +94,7 @@ Use `$$' to insert a single dollar sign." ...@@ -94,7 +94,7 @@ Use `$$' to insert a single dollar sign."
;; Fixme: Should the environment be recoded if LC_CTYPE &c is set? ;; Fixme: Should the environment be recoded if LC_CTYPE &c is set?
(defun setenv (variable &optional value unset substitute-env-vars terminal) (defun setenv (variable &optional value unset substitute-env-vars frame)
"Set the value of the environment variable named VARIABLE to VALUE. "Set the value of the environment variable named VARIABLE to VALUE.
VARIABLE should be a string. VALUE is optional; if not provided or VARIABLE should be a string. VALUE is optional; if not provided or
nil, the environment variable VARIABLE will be removed. UNSET nil, the environment variable VARIABLE will be removed. UNSET
...@@ -112,12 +112,15 @@ Interactively, always replace environment variables in the new value. ...@@ -112,12 +112,15 @@ Interactively, always replace environment variables in the new value.
If VARIABLE is set in `process-environment', then this function If VARIABLE is set in `process-environment', then this function
modifies its value there. Otherwise, this function works by modifies its value there. Otherwise, this function works by
modifying either `global-environment' or the environment modifying either `global-environment' or the environment
belonging to the terminal device of the selected frame, depending belonging to the selected frame, depending on the value of
on the value of `local-environment-variables'. `local-environment-variables'.
If optional parameter TERMINAL is non-nil, then it should be a If optional parameter FRAME is non-nil, then it should be a a
terminal id or a frame. If the specified terminal device has its own frame. If the specified frame has its own set of environment
set of environment variables, this function will modify VAR in it. variables, this function will modify VARIABLE in it. Note that
frames on the same terminal device usually share their
environment, so calling `setenv' on one of them affects the
others as well.
As a special case, setting variable `TZ' calls `set-time-zone-rule' as As a special case, setting variable `TZ' calls `set-time-zone-rule' as
a side-effect." a side-effect."
...@@ -153,9 +156,11 @@ a side-effect." ...@@ -153,9 +156,11 @@ a side-effect."
(error "Environment variable name `%s' contains `='" variable)) (error "Environment variable name `%s' contains `='" variable))
(let ((pattern (concat "\\`" (regexp-quote variable) "\\(=\\|\\'\\)")) (let ((pattern (concat "\\`" (regexp-quote variable) "\\(=\\|\\'\\)"))
(case-fold-search nil) (case-fold-search nil)
(terminal-env (terminal-parameter terminal 'environment)) (frame-env (frame-parameter (frame-with-environment frame) 'environment))
(frame-forced (not frame))
(scan process-environment) (scan process-environment)
found) found)
(setq frame (frame-with-environment frame))
(if (string-equal "TZ" variable) (if (string-equal "TZ" variable)
(set-time-zone-rule value)) (set-time-zone-rule value))
(block nil (block nil
...@@ -166,55 +171,54 @@ a side-effect." ...@@ -166,55 +171,54 @@ a side-effect."
(setcar scan (concat variable "=" value)) (setcar scan (concat variable "=" value))
;; Leave unset variables in `process-environment', ;; Leave unset variables in `process-environment',
;; otherwise the overridden value in `global-environment' ;; otherwise the overridden value in `global-environment'
;; or terminal-env would become unmasked. ;; or frame-env would become unmasked.
(setcar scan variable)) (setcar scan variable))
(return value)) (return value))
(setq scan (cdr scan))) (setq scan (cdr scan)))
;; Look in the local or global environment, whichever is relevant. ;; Look in the local or global environment, whichever is relevant.
(let ((local-var-p (and terminal-env (let ((local-var-p (and frame-env
(or terminal (or frame-forced
(eq t local-environment-variables) (eq t local-environment-variables)
(member variable local-environment-variables))))) (member variable local-environment-variables)))))
(setq scan (if local-var-p (setq scan (if local-var-p
terminal-env frame-env
global-environment)) global-environment))
(while scan (while scan
(when (string-match pattern (car scan)) (when (string-match pattern (car scan))
(if value (if value
(setcar scan (concat variable "=" value)) (setcar scan (concat variable "=" value))
(if local-var-p (if local-var-p
(set-terminal-parameter terminal 'environment (set-frame-parameter frame 'environment
(delq (car scan) terminal-env)) (delq (car scan) frame-env))
(setq global-environment (delq (car scan) global-environment))) (setq global-environment (delq (car scan) global-environment))))
(return value))) (return value))
(setq scan (cdr scan))) (setq scan (cdr scan)))
;; VARIABLE is not in any environment list. ;; VARIABLE is not in any environment list.
(if value (if value
(if local-var-p (if local-var-p
(set-terminal-parameter nil 'environment (set-frame-parameter frame 'environment
(cons (concat variable "=" value) (cons (concat variable "=" value)
terminal-env)) frame-env))
(setq global-environment (setq global-environment
(cons (concat variable "=" value) (cons (concat variable "=" value)
global-environment)))) global-environment))))
(return value))))) (return value)))))
(defun getenv (variable &optional terminal) (defun getenv (variable &optional frame)
"Get the value of environment variable VARIABLE. "Get the value of environment variable VARIABLE.
VARIABLE should be a string. Value is nil if VARIABLE is undefined in VARIABLE should be a string. Value is nil if VARIABLE is undefined in
the environment. Otherwise, value is a string. the environment. Otherwise, value is a string.
If optional parameter TERMINAL is non-nil, then it should be a If optional parameter FRAME is non-nil, then it should be a
terminal id or a frame. If the specified terminal device has its own frame. If the specified terminal device has its own set of
set of environment variables, this function will look up VARIABLE in environment variables, this function will look up VARIABLE in it.
it.
Otherwise, this function searches `process-environment' for VARIABLE. Otherwise, this function searches `process-environment' for
If it was not found there, then it continues the search in either VARIABLE. If it was not found there, then it continues the
`global-environment' or the local environment list of the current search in either `global-environment' or the environment list of
terminal device, depending on the value of the selected frame, depending on the value of
`local-environment-variables'." `local-environment-variables'."
(interactive (list (read-envvar-name "Get environment variable: " t))) (interactive (list (read-envvar-name "Get environment variable: " t)))
(let ((value (getenv-internal (if (multibyte-string-p variable) (let ((value (getenv-internal (if (multibyte-string-p variable)
...@@ -236,21 +240,23 @@ variables, only read them. See `setenv' to do that. ...@@ -236,21 +240,23 @@ variables, only read them. See `setenv' to do that.
The list is constructed from elements of `process-environment', The list is constructed from elements of `process-environment',
`global-environment' and the local environment list of the `global-environment' and the local environment list of the
current terminal, as specified by `local-environment-variables'. selected frame, as specified by `local-environment-variables'.
Non-ASCII characters are encoded according to the initial value of Non-ASCII characters are encoded according to the initial value of
`locale-coding-system', i.e. the elements must normally be decoded for use. `locale-coding-system', i.e. the elements must normally be decoded for use.
See `setenv' and `getenv'." See `setenv' and `getenv'."
(let ((env (cond ((or (not local-environment-variables) (let ((env (let ((local-env (frame-parameter (frame-with-environment)
(not (terminal-parameter nil 'environment))) 'environment)))
(append process-environment global-environment nil)) (cond ((or (not local-environment-variables)
((consp local-environment-variables) (not local-env))
(let ((e (reverse process-environment))) (append process-environment global-environment nil))
(dolist (entry local-environment-variables) ((consp local-environment-variables)
(setq e (cons (getenv entry) e))) (let ((e (reverse process-environment)))
(append (nreverse e) global-environment nil))) (dolist (entry local-environment-variables)
(t (setq e (cons (getenv entry) e)))
(append process-environment (terminal-parameter nil 'environment) nil)))) (append (nreverse e) global-environment nil)))
(t
(append process-environment local-env nil)))))
scan seen) scan seen)
;; Find the first valid entry in env. ;; Find the first valid entry in env.
(while (and env (stringp (car env)) (while (and env (stringp (car env))
......
...@@ -674,12 +674,20 @@ setup is for focus to follow the pointer." ...@@ -674,12 +674,20 @@ setup is for focus to follow the pointer."
(cdr (assq 'window-system parameters))) (cdr (assq 'window-system parameters)))
(t window-system))) (t window-system)))
(frame-creation-function (cdr (assq w frame-creation-function-alist))) (frame-creation-function (cdr (assq w frame-creation-function-alist)))
(oldframe (selected-frame))
frame) frame)
(unless frame-creation-function (unless frame-creation-function
(error "Don't know how to create a frame on window system %s" w)) (error "Don't know how to create a frame on window system %s" w))
(run-hooks 'before-make-frame-hook) (run-hooks 'before-make-frame-hook)
(setq frame (funcall frame-creation-function (append parameters (cdr (assq w window-system-default-frame-alist))))) (setq frame (funcall frame-creation-function (append parameters (cdr (assq w window-system-default-frame-alist)))))
(normal-erase-is-backspace-setup-frame frame) (normal-erase-is-backspace-setup-frame frame)
;; Set up the frame-local environment, if needed.
(when (eq (frame-display frame) (frame-display oldframe))
(let ((env (frame-parameter oldframe 'environment)))
(if (not (framep env))
(setq env oldframe))
(if env
(set-frame-parameter frame 'environment env))))
(run-hook-with-args 'after-make-frame-functions frame) (run-hook-with-args 'after-make-frame-functions frame)
frame)) frame))
......
...@@ -620,8 +620,8 @@ The following commands are accepted by the client: ...@@ -620,8 +620,8 @@ The following commands are accepted by the client:
;; emacsclient quits while also preventing ;; emacsclient quits while also preventing
;; `server-save-buffers-kill-display' from unexpectedly ;; `server-save-buffers-kill-display' from unexpectedly
;; killing emacs on that frame. ;; killing emacs on that frame.
(list (cons 'client 'nowait)) (list (cons 'client 'nowait) (cons 'environment env))
(list (cons 'client proc))))) (list (cons 'client proc) (cons 'environment env)))))
(setq frame (make-frame-on-display (setq frame (make-frame-on-display
(or display (or display
(frame-parameter nil 'display) (frame-parameter nil 'display)
...@@ -637,7 +637,6 @@ The following commands are accepted by the client: ...@@ -637,7 +637,6 @@ The following commands are accepted by the client:
(select-frame frame) (select-frame frame)
(server-client-set client 'frame frame) (server-client-set client 'frame frame)
(server-client-set client 'device (frame-display frame)) (server-client-set client 'device (frame-display frame))
(set-terminal-parameter frame 'environment env)
(setq dontkill t)) (setq dontkill t))
;; This emacs does not support X. ;; This emacs does not support X.
(server-log "Window system unsupported" proc) (server-log "Window system unsupported" proc)
...@@ -684,12 +683,12 @@ The following commands are accepted by the client: ...@@ -684,12 +683,12 @@ The following commands are accepted by the client:
(setq frame (make-frame-on-tty tty type (setq frame (make-frame-on-tty tty type
;; Ignore nowait here; we always need to clean ;; Ignore nowait here; we always need to clean
;; up opened ttys when the client dies. ;; up opened ttys when the client dies.
`((client . ,proc))))) `((client . ,proc)
(environment . ,env)))))
(select-frame frame) (select-frame frame)
(server-client-set client 'frame frame) (server-client-set client 'frame frame)
(server-client-set client 'tty (display-name frame)) (server-client-set client 'tty (display-name frame))
(server-client-set client 'device (frame-display frame)) (server-client-set client 'device (frame-display frame))
(set-terminal-parameter frame 'environment env)
;; Reply with our pid. ;; Reply with our pid.
(server-send-string proc (concat "-emacs-pid " (number-to-string (emacs-pid)) "\n")) (server-send-string proc (concat "-emacs-pid " (number-to-string (emacs-pid)) "\n"))
...@@ -740,8 +739,7 @@ The following commands are accepted by the client: ...@@ -740,8 +739,7 @@ The following commands are accepted by the client:
;; -env NAME=VALUE: An environment variable. ;; -env NAME=VALUE: An environment variable.
((and (equal "-env" arg) (string-match "\\([^ ]+\\) " request)) ((and (equal "-env" arg) (string-match "\\([^ ]+\\) " request))
(let ((var (server-unquote-arg (match-string 1 request)))) (let ((var (server-unquote-arg (match-string 1 request))))
(when coding-system ;; XXX Variables should be encoded as in getenv/setenv.
(setq var (decode-coding-string var coding-system)))
(setq request (substring request (match-end 0))) (setq request (substring request (match-end 0)))
(setq env (cons var env)))) (setq env (cons var env))))
......
...@@ -119,7 +119,6 @@ Lisp_Object Vprocess_environment; ...@@ -119,7 +119,6 @@ Lisp_Object Vprocess_environment;
#ifdef DOS_NT #ifdef DOS_NT
Lisp_Object Qbuffer_file_type; Lisp_Object Qbuffer_file_type;
#endif /* DOS_NT */ #endif /* DOS_NT */
Lisp_Object Qenvironment;
/* True iff we are about to fork off a synchronous process or if we /* True iff we are about to fork off a synchronous process or if we
are waiting for it. */ are waiting for it. */
...@@ -1319,8 +1318,8 @@ child_setup (in, out, err, new_argv, set_pgrp, current_dir) ...@@ -1319,8 +1318,8 @@ child_setup (in, out, err, new_argv, set_pgrp, current_dir)
if (!NILP (Vlocal_environment_variables)) if (!NILP (Vlocal_environment_variables))
{ {
local = get_terminal_param (FRAME_DEVICE (XFRAME (selected_frame)), local = get_frame_param (XFRAME (Fframe_with_environment (selected_frame)),
Qenvironment); Qenvironment);
if (EQ (Vlocal_environment_variables, Qt) if (EQ (Vlocal_environment_variables, Qt)
&& !NILP (local)) && !NILP (local))
environment = local; environment = local;
...@@ -1356,7 +1355,7 @@ child_setup (in, out, err, new_argv, set_pgrp, current_dir) ...@@ -1356,7 +1355,7 @@ child_setup (in, out, err, new_argv, set_pgrp, current_dir)
new_env = add_env (env, new_env, egetenv (SDATA (XCAR (tem)))); new_env = add_env (env, new_env, egetenv (SDATA (XCAR (tem))));
/* The rest of the environment (either Vglobal_environment or the /* The rest of the environment (either Vglobal_environment or the
'environment terminal parameter). */ 'environment frame parameter). */
for (tem = environment; for (tem = environment;
CONSP (tem) && STRINGP (XCAR (tem)); CONSP (tem) && STRINGP (XCAR (tem));
tem = XCDR (tem)) tem = XCDR (tem))
...@@ -1488,12 +1487,12 @@ relocate_fd (fd, minfd) ...@@ -1488,12 +1487,12 @@ relocate_fd (fd, minfd)
} }
static int static int
getenv_internal (var, varlen, value, valuelen, terminal) getenv_internal (var, varlen, value, valuelen, frame)
char *var; char *var;
int varlen; int varlen;
char **value; char **value;
int *valuelen; int *valuelen;
Lisp_Object terminal; Lisp_Object frame;
{ {
Lisp_Object scan; Lisp_Object scan;
Lisp_Object environment = Vglobal_environment; Lisp_Object environment = Vglobal_environment;
...@@ -1528,17 +1527,19 @@ getenv_internal (var, varlen, value, valuelen, terminal) ...@@ -1528,17 +1527,19 @@ getenv_internal (var, varlen, value, valuelen, terminal)
} }
/* Find the environment in which to search the variable. */ /* Find the environment in which to search the variable. */
if (!NILP (terminal)) if (!NILP (frame))
{ {
Lisp_Object local = get_terminal_param (get_device (terminal, 1), Qenvironment); CHECK_FRAME (frame);
frame = Fframe_with_environment (frame);
Lisp_Object local = get_frame_param (XFRAME (frame), Qenvironment);
/* Use Vglobal_environment if there is no local environment. */ /* Use Vglobal_environment if there is no local environment. */
if (!NILP (local)) if (!NILP (local))
environment = local; environment = local;
} }
else if (!NILP (Vlocal_environment_variables)) else if (!NILP (Vlocal_environment_variables))
{ {
Lisp_Object local = get_terminal_param (FRAME_DEVICE (XFRAME (selected_frame)), Lisp_Object local = get_frame_param (XFRAME (Fframe_with_environment (selected_frame)),
Qenvironment); Qenvironment);
if (EQ (Vlocal_environment_variables, Qt) if (EQ (Vlocal_environment_variables, Qt)
&& !NILP (local)) && !NILP (local))
environment = local; environment = local;
...@@ -1594,25 +1595,23 @@ DEFUN ("getenv-internal", Fgetenv_internal, Sgetenv_internal, 1, 2, 0, ...@@ -1594,25 +1595,23 @@ DEFUN ("getenv-internal", Fgetenv_internal, Sgetenv_internal, 1, 2, 0,
VARIABLE should be a string. Value is nil if VARIABLE is undefined in VARIABLE should be a string. Value is nil if VARIABLE is undefined in
the environment. Otherwise, value is a string. the environment. Otherwise, value is a string.
If optional parameter TERMINAL is non-nil, then it should be a If optional parameter FRAME is non-nil, then it should be a frame. If
terminal id or a frame. If the specified terminal device has its own that frame has its own set of environment variables, this function
set of environment variables, this function will look up VARIABLE in will look up VARIABLE in there.
it.
Otherwise, this function searches `process-environment' for VARIABLE. Otherwise, this function searches `process-environment' for VARIABLE.
If it was not found there, then it continues the search in either If it was not found there, then it continues the search in either
`global-environment' or the local environment list of the current `global-environment' or the local environment list of the current
terminal device, depending on the value of frame, depending on the value of `local-environment-variables'. */)
`local-environment-variables'. */) (variable, frame)
(variable, terminal) Lisp_Object variable, frame;
Lisp_Object variable, terminal;
{ {
char *value; char *value;
int valuelen; int valuelen;
CHECK_STRING (variable); CHECK_STRING (variable);
if (getenv_internal (SDATA (variable), SBYTES (variable), if (getenv_internal (SDATA (variable), SBYTES (variable),
&value, &valuelen, terminal)) &value, &valuelen, frame))
return make_string (value, valuelen); return make_string (value, valuelen);
else else
return Qnil; return Qnil;
...@@ -1842,11 +1841,10 @@ Each element should be a string of the form ENVVARNAME=VALUE. ...@@ -1842,11 +1841,10 @@ Each element should be a string of the form ENVVARNAME=VALUE.
The environment which Emacs inherits is placed in this variable when The environment which Emacs inherits is placed in this variable when
Emacs starts. Emacs starts.
Some terminal devices may have their own local list of environment Some frames may have their own local list of environment variables in
variables in their 'environment parameter, which may override this their 'environment parameter, which may override this global list; see
global list; see `local-environment-variables'. See `local-environment-variables'. See `process-environment' for a way to
`process-environment' for a way to modify an environment variable on modify an environment variable on all frames.
all terminals.
If multiple entries define the same variable, the first one always If multiple entries define the same variable, the first one always
takes precedence. takes precedence.
...@@ -1860,12 +1858,12 @@ See `setenv' and `getenv'. */); ...@@ -1860,12 +1858,12 @@ See `setenv' and `getenv'. */);
Each element should be a string of the form ENVVARNAME=VALUE. Each element should be a string of the form ENVVARNAME=VALUE.
Entries in this list take precedence to those in `global-environment' Entries in this list take precedence to those in `global-environment'
or the terminal environment. (See `local-environment-variables' for or the frame-local environment. (See `local-environment-variables'.)
an explanation of the terminal-local environment.) Therefore, Therefore, let-binding `process-environment' is an easy way to
let-binding `process-environment' is an easy way to temporarily change temporarily change the value of an environment variable, irrespective
the value of an environment variable, irrespective of where it comes of where it comes from. To use `process-environment' to remove an
from. To use `process-environment' to remove an environment variable, environment variable, include only its name in the list, without
include only its name in the list, without "=VALUE". "=VALUE".
This variable is set to nil when Emacs starts. This variable is set to nil when Emacs starts.
...@@ -1886,21 +1884,18 @@ See `setenv' and `getenv'. */); ...@@ -1886,21 +1884,18 @@ See `setenv' and `getenv'. */);
defsubr (&Scall_process_region); defsubr (&Scall_process_region);
DEFVAR_LISP ("local-environment-variables", &Vlocal_environment_variables, DEFVAR_LISP ("local-environment-variables", &Vlocal_environment_variables,
doc: /* Enable or disable terminal-local environment variables. doc: /* Enable or disable frame-local environment variables.
If set to t, `getenv', `setenv' and subprocess creation functions use If set to t, `getenv', `setenv' and subprocess creation functions use
the local environment of the terminal device of the selected frame, the local environment of the selected frame, ignoring
ignoring `global-environment'. `global-environment'.
If set to nil, Emacs uses `global-environment' and ignores the If set to nil, Emacs uses `global-environment' and ignores the
terminal environment. frame-local environment.
Otherwise, `local-environment-variables' should be a list of variable Otherwise, `local-environment-variables' should be a list of variable
names (represented by Lisp strings) to look up in the terminal's names (represented by Lisp strings) to look up in the frame's
environment. The rest will come from `global-environment'. */); environment. The rest will come from `global-environment'. */);
Vlocal_environment_variables = Qnil; Vlocal_environment_variables = Qnil;
Qenvironment = intern ("environment");
staticpro (&Qenvironment);
} }
/* arch-tag: 769b8045-1df7-4d2b-8968-e3fb49017f95 /* arch-tag: 769b8045-1df7-4d2b-8968-e3fb49017f95
......
...@@ -111,6 +111,7 @@ Lisp_Object Qbuffer_predicate, Qbuffer_list, Qburied_buffer_list; ...@@ -111,6 +111,7 @@ Lisp_Object Qbuffer_predicate, Qbuffer_list, Qburied_buffer_list;
Lisp_Object Qtty_color_mode; Lisp_Object Qtty_color_mode;
Lisp_Object Qtty, Qtty_type; Lisp_Object Qtty, Qtty_type;
Lisp_Object Qwindow_system; Lisp_Object Qwindow_system;
Lisp_Object Qenvironment;
Lisp_Object Qfullscreen, Qfullwidth, Qfullheight, Qfullboth; Lisp_Object Qfullscreen, Qfullwidth, Qfullheight, Qfullboth;
...@@ -1473,6 +1474,24 @@ The functions are run with one arg, the frame to be deleted. */) ...@@ -1473,6 +1474,24 @@ The functions are run with one arg, the frame to be deleted. */)
if (EQ (f->minibuffer_window, echo_area_window)) if (EQ (f->minibuffer_window, echo_area_window))
echo_area_window = sf->minibuffer_window; echo_area_window = sf->minibuffer_window;
/* Don't allow other frames to refer to a deleted frame in their
'environment parameter. */
{
Lisp_Object tail, frame1;
Lisp_Object env = get_frame_param (XFRAME (frame), Qenvironment);
FOR_EACH_FRAME (tail, frame1)
{
if (EQ (frame, frame1) || !FRAME_LIVE_P (XFRAME (frame1)))
continue;
if (EQ (frame, get_frame_param (XFRAME (frame1), Qenvironment)))
{
store_frame_param (XFRAME (frame1), Qenvironment, env);
if (!FRAMEP (env))
env = frame1;
}
}
}
/* Clear any X selections for this frame. */ /* Clear any X selections for this frame. */
#ifdef HAVE_X_WINDOWS #ifdef HAVE_X_WINDOWS
if (FRAME_X_P (f)) if (FRAME_X_P (f))
...@@ -2577,6 +2596,43 @@ enabled such bindings for that variable with `make-variable-frame-local'. */) ...@@ -2577,6 +2596,43 @@ enabled such bindings for that variable with `make-variable-frame-local'. */)
return unbind_to (count, Qnil); return unbind_to (count, Qnil);
} }
DEFUN ("frame-with-environment", Fframe_with_environment, Sframe_with_environment, 0, 1, 0,
doc: /* Return the frame that has the environment variable list for FRAME.
The frame-local environment variable list is normally shared between
frames that were created in the same Emacsclient session. The
environment list is stored in a single frame's 'environment parameter;
the other frames' 'environment parameter is set to this frame. This
function follows to chain of 'environment references to reach the
frame that stores the actual local environment list, and returns that
frame. */)
(frame)
Lisp_Object frame;
{