aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.multi-tty16
-rw-r--r--lisp/env.el84
-rw-r--r--lisp/frame.el8
-rw-r--r--lisp/server.el12
-rw-r--r--src/callproc.c71
-rw-r--r--src/frame.c59
-rw-r--r--src/frame.h1
-rw-r--r--src/lisp.h1
8 files changed, 167 insertions, 85 deletions
diff --git a/README.multi-tty b/README.multi-tty
index 9f3e048e2e2..346d27102bf 100644
--- a/README.multi-tty
+++ b/README.multi-tty
@@ -412,7 +412,10 @@ THINGS TO DO
412 412
413 make_terminal_frame 413 make_terminal_frame
414 create_tty_output 414 create_tty_output
415 415
416** Decide whether to keep the C implementation of terminal parameters,
417 or revert to the previous, purely Lisp code. It turned out that
418 local environments do not need terminal parameters after all.
416 419
417** Move Fsend_string_to_terminal to term.c, and declare get_named_tty 420** Move Fsend_string_to_terminal to term.c, and declare get_named_tty
418 as static, removing it from dispextern.h. 421 as static, removing it from dispextern.h.
@@ -1362,5 +1365,16 @@ DIARY OF CHANGES
1362 `getenv' and `setenv', and the new `local-environment-variables' 1365 `getenv' and `setenv', and the new `local-environment-variables'
1363 facility. Yay!) 1366 facility. Yay!)
1364 1367
1368 (Updated in patch-465 to fix the semantics of let-binding
1369 `process-environment'. `process-environment' was changed to
1370 override all local/global environment variables, and a new variable
1371 `global-environment' was introduced to have `process-environment's
1372 old meaning.)
1373
1374 (Updated in patch-466 to fix the case when two emacsclient sessions
1375 share the same terminal, but have different environment. The local
1376 environment lists are now stored as frame parameters, so the
1377 C-level terminal parameters are not strictly necessary any more.)
1378
1365;;; arch-tag: 8da1619e-2e79-41a8-9ac9-a0485daad17d 1379;;; arch-tag: 8da1619e-2e79-41a8-9ac9-a0485daad17d
1366 1380
diff --git a/lisp/env.el b/lisp/env.el
index 7099a72ca2c..38a9e865283 100644
--- a/lisp/env.el
+++ b/lisp/env.el
@@ -55,7 +55,7 @@ If it is also not t, RET does not exit if it does non-null completion."
55 (substring enventry 0 55 (substring enventry 0
56 (string-match "=" enventry))))) 56 (string-match "=" enventry)))))
57 (append process-environment 57 (append process-environment
58 (terminal-parameter nil 'environment) 58 (frame-parameter (frame-with-environment) 'environment)
59 global-environment)) 59 global-environment))
60 nil mustmatch nil 'read-envvar-name-history)) 60 nil mustmatch nil 'read-envvar-name-history))
61 61
@@ -94,7 +94,7 @@ Use `$$' to insert a single dollar sign."
94 94
95;; Fixme: Should the environment be recoded if LC_CTYPE &c is set? 95;; Fixme: Should the environment be recoded if LC_CTYPE &c is set?
96 96
97(defun setenv (variable &optional value unset substitute-env-vars terminal) 97(defun setenv (variable &optional value unset substitute-env-vars frame)
98 "Set the value of the environment variable named VARIABLE to VALUE. 98 "Set the value of the environment variable named VARIABLE to VALUE.
99VARIABLE should be a string. VALUE is optional; if not provided or 99VARIABLE should be a string. VALUE is optional; if not provided or
100nil, the environment variable VARIABLE will be removed. UNSET 100nil, the environment variable VARIABLE will be removed. UNSET
@@ -112,12 +112,15 @@ Interactively, always replace environment variables in the new value.
112If VARIABLE is set in `process-environment', then this function 112If VARIABLE is set in `process-environment', then this function
113modifies its value there. Otherwise, this function works by 113modifies its value there. Otherwise, this function works by
114modifying either `global-environment' or the environment 114modifying either `global-environment' or the environment
115belonging to the terminal device of the selected frame, depending 115belonging to the selected frame, depending on the value of
116on the value of `local-environment-variables'. 116`local-environment-variables'.
117 117
118If optional parameter TERMINAL is non-nil, then it should be a 118If optional parameter FRAME is non-nil, then it should be a a
119terminal id or a frame. If the specified terminal device has its own 119frame. If the specified frame has its own set of environment
120set of environment variables, this function will modify VAR in it. 120variables, this function will modify VARIABLE in it. Note that
121frames on the same terminal device usually share their
122environment, so calling `setenv' on one of them affects the
123others as well.
121 124
122As a special case, setting variable `TZ' calls `set-time-zone-rule' as 125As a special case, setting variable `TZ' calls `set-time-zone-rule' as
123a side-effect." 126a side-effect."
@@ -153,9 +156,11 @@ a side-effect."
153 (error "Environment variable name `%s' contains `='" variable)) 156 (error "Environment variable name `%s' contains `='" variable))
154 (let ((pattern (concat "\\`" (regexp-quote variable) "\\(=\\|\\'\\)")) 157 (let ((pattern (concat "\\`" (regexp-quote variable) "\\(=\\|\\'\\)"))
155 (case-fold-search nil) 158 (case-fold-search nil)
156 (terminal-env (terminal-parameter terminal 'environment)) 159 (frame-env (frame-parameter (frame-with-environment frame) 'environment))
160 (frame-forced (not frame))
157 (scan process-environment) 161 (scan process-environment)
158 found) 162 found)
163 (setq frame (frame-with-environment frame))
159 (if (string-equal "TZ" variable) 164 (if (string-equal "TZ" variable)
160 (set-time-zone-rule value)) 165 (set-time-zone-rule value))
161 (block nil 166 (block nil
@@ -166,55 +171,54 @@ a side-effect."
166 (setcar scan (concat variable "=" value)) 171 (setcar scan (concat variable "=" value))
167 ;; Leave unset variables in `process-environment', 172 ;; Leave unset variables in `process-environment',
168 ;; otherwise the overridden value in `global-environment' 173 ;; otherwise the overridden value in `global-environment'
169 ;; or terminal-env would become unmasked. 174 ;; or frame-env would become unmasked.
170 (setcar scan variable)) 175 (setcar scan variable))
171 (return value)) 176 (return value))
172 (setq scan (cdr scan))) 177 (setq scan (cdr scan)))
173 178
174 ;; Look in the local or global environment, whichever is relevant. 179 ;; Look in the local or global environment, whichever is relevant.
175 (let ((local-var-p (and terminal-env 180 (let ((local-var-p (and frame-env
176 (or terminal 181 (or frame-forced
177 (eq t local-environment-variables) 182 (eq t local-environment-variables)
178 (member variable local-environment-variables))))) 183 (member variable local-environment-variables)))))
179 (setq scan (if local-var-p 184 (setq scan (if local-var-p
180 terminal-env 185 frame-env
181 global-environment)) 186 global-environment))
182 (while scan 187 (while scan
183 (when (string-match pattern (car scan)) 188 (when (string-match pattern (car scan))
184 (if value 189 (if value
185 (setcar scan (concat variable "=" value)) 190 (setcar scan (concat variable "=" value))
186 (if local-var-p 191 (if local-var-p
187 (set-terminal-parameter terminal 'environment 192 (set-frame-parameter frame 'environment
188 (delq (car scan) terminal-env)) 193 (delq (car scan) frame-env))
189 (setq global-environment (delq (car scan) global-environment))) 194 (setq global-environment (delq (car scan) global-environment))))
190 (return value))) 195 (return value))
191 (setq scan (cdr scan))) 196 (setq scan (cdr scan)))
192 197
193 ;; VARIABLE is not in any environment list. 198 ;; VARIABLE is not in any environment list.
194 (if value 199 (if value
195 (if local-var-p 200 (if local-var-p
196 (set-terminal-parameter nil 'environment 201 (set-frame-parameter frame 'environment
197 (cons (concat variable "=" value) 202 (cons (concat variable "=" value)
198 terminal-env)) 203 frame-env))
199 (setq global-environment 204 (setq global-environment
200 (cons (concat variable "=" value) 205 (cons (concat variable "=" value)
201 global-environment)))) 206 global-environment))))
202 (return value))))) 207 (return value)))))
203 208
204(defun getenv (variable &optional terminal) 209(defun getenv (variable &optional frame)
205 "Get the value of environment variable VARIABLE. 210 "Get the value of environment variable VARIABLE.
206VARIABLE should be a string. Value is nil if VARIABLE is undefined in 211VARIABLE should be a string. Value is nil if VARIABLE is undefined in
207the environment. Otherwise, value is a string. 212the environment. Otherwise, value is a string.
208 213
209If optional parameter TERMINAL is non-nil, then it should be a 214If optional parameter FRAME is non-nil, then it should be a
210terminal id or a frame. If the specified terminal device has its own 215frame. If the specified terminal device has its own set of
211set of environment variables, this function will look up VARIABLE in 216environment variables, this function will look up VARIABLE in it.
212it.
213 217
214Otherwise, this function searches `process-environment' for VARIABLE. 218Otherwise, this function searches `process-environment' for
215If it was not found there, then it continues the search in either 219VARIABLE. If it was not found there, then it continues the
216`global-environment' or the local environment list of the current 220search in either `global-environment' or the environment list of
217terminal device, depending on the value of 221the selected frame, depending on the value of
218`local-environment-variables'." 222`local-environment-variables'."
219 (interactive (list (read-envvar-name "Get environment variable: " t))) 223 (interactive (list (read-envvar-name "Get environment variable: " t)))
220 (let ((value (getenv-internal (if (multibyte-string-p variable) 224 (let ((value (getenv-internal (if (multibyte-string-p variable)
@@ -236,21 +240,23 @@ variables, only read them. See `setenv' to do that.
236 240
237The list is constructed from elements of `process-environment', 241The list is constructed from elements of `process-environment',
238`global-environment' and the local environment list of the 242`global-environment' and the local environment list of the
239current terminal, as specified by `local-environment-variables'. 243selected frame, as specified by `local-environment-variables'.
240 244
241Non-ASCII characters are encoded according to the initial value of 245Non-ASCII characters are encoded according to the initial value of
242`locale-coding-system', i.e. the elements must normally be decoded for use. 246`locale-coding-system', i.e. the elements must normally be decoded for use.
243See `setenv' and `getenv'." 247See `setenv' and `getenv'."
244 (let ((env (cond ((or (not local-environment-variables) 248 (let ((env (let ((local-env (frame-parameter (frame-with-environment)
245 (not (terminal-parameter nil 'environment))) 249 'environment)))
246 (append process-environment global-environment nil)) 250 (cond ((or (not local-environment-variables)
247 ((consp local-environment-variables) 251 (not local-env))
248 (let ((e (reverse process-environment))) 252 (append process-environment global-environment nil))
249 (dolist (entry local-environment-variables) 253 ((consp local-environment-variables)
250 (setq e (cons (getenv entry) e))) 254 (let ((e (reverse process-environment)))
251 (append (nreverse e) global-environment nil))) 255 (dolist (entry local-environment-variables)
252 (t 256 (setq e (cons (getenv entry) e)))
253 (append process-environment (terminal-parameter nil 'environment) nil)))) 257 (append (nreverse e) global-environment nil)))
258 (t
259 (append process-environment local-env nil)))))
254 scan seen) 260 scan seen)
255 ;; Find the first valid entry in env. 261 ;; Find the first valid entry in env.
256 (while (and env (stringp (car env)) 262 (while (and env (stringp (car env))
diff --git a/lisp/frame.el b/lisp/frame.el
index ecf0697cae4..339100bbff5 100644
--- a/lisp/frame.el
+++ b/lisp/frame.el
@@ -674,12 +674,20 @@ setup is for focus to follow the pointer."
674 (cdr (assq 'window-system parameters))) 674 (cdr (assq 'window-system parameters)))
675 (t window-system))) 675 (t window-system)))
676 (frame-creation-function (cdr (assq w frame-creation-function-alist))) 676 (frame-creation-function (cdr (assq w frame-creation-function-alist)))
677 (oldframe (selected-frame))
677 frame) 678 frame)
678 (unless frame-creation-function 679 (unless frame-creation-function
679 (error "Don't know how to create a frame on window system %s" w)) 680 (error "Don't know how to create a frame on window system %s" w))
680 (run-hooks 'before-make-frame-hook) 681 (run-hooks 'before-make-frame-hook)
681 (setq frame (funcall frame-creation-function (append parameters (cdr (assq w window-system-default-frame-alist))))) 682 (setq frame (funcall frame-creation-function (append parameters (cdr (assq w window-system-default-frame-alist)))))
682 (normal-erase-is-backspace-setup-frame frame) 683 (normal-erase-is-backspace-setup-frame frame)
684 ;; Set up the frame-local environment, if needed.
685 (when (eq (frame-display frame) (frame-display oldframe))
686 (let ((env (frame-parameter oldframe 'environment)))
687 (if (not (framep env))
688 (setq env oldframe))
689 (if env
690 (set-frame-parameter frame 'environment env))))
683 (run-hook-with-args 'after-make-frame-functions frame) 691 (run-hook-with-args 'after-make-frame-functions frame)
684 frame)) 692 frame))
685 693
diff --git a/lisp/server.el b/lisp/server.el
index fb587b640a3..f98be109c92 100644
--- a/lisp/server.el
+++ b/lisp/server.el
@@ -620,8 +620,8 @@ The following commands are accepted by the client:
620 ;; emacsclient quits while also preventing 620 ;; emacsclient quits while also preventing
621 ;; `server-save-buffers-kill-display' from unexpectedly 621 ;; `server-save-buffers-kill-display' from unexpectedly
622 ;; killing emacs on that frame. 622 ;; killing emacs on that frame.
623 (list (cons 'client 'nowait)) 623 (list (cons 'client 'nowait) (cons 'environment env))
624 (list (cons 'client proc))))) 624 (list (cons 'client proc) (cons 'environment env)))))
625 (setq frame (make-frame-on-display 625 (setq frame (make-frame-on-display
626 (or display 626 (or display
627 (frame-parameter nil 'display) 627 (frame-parameter nil 'display)
@@ -637,7 +637,6 @@ The following commands are accepted by the client:
637 (select-frame frame) 637 (select-frame frame)
638 (server-client-set client 'frame frame) 638 (server-client-set client 'frame frame)
639 (server-client-set client 'device (frame-display frame)) 639 (server-client-set client 'device (frame-display frame))
640 (set-terminal-parameter frame 'environment env)
641 (setq dontkill t)) 640 (setq dontkill t))
642 ;; This emacs does not support X. 641 ;; This emacs does not support X.
643 (server-log "Window system unsupported" proc) 642 (server-log "Window system unsupported" proc)
@@ -684,12 +683,12 @@ The following commands are accepted by the client:
684 (setq frame (make-frame-on-tty tty type 683 (setq frame (make-frame-on-tty tty type
685 ;; Ignore nowait here; we always need to clean 684 ;; Ignore nowait here; we always need to clean
686 ;; up opened ttys when the client dies. 685 ;; up opened ttys when the client dies.
687 `((client . ,proc))))) 686 `((client . ,proc)
687 (environment . ,env)))))
688 (select-frame frame) 688 (select-frame frame)
689 (server-client-set client 'frame frame) 689 (server-client-set client 'frame frame)
690 (server-client-set client 'tty (display-name frame)) 690 (server-client-set client 'tty (display-name frame))
691 (server-client-set client 'device (frame-display frame)) 691 (server-client-set client 'device (frame-display frame))
692 (set-terminal-parameter frame 'environment env)
693 692
694 ;; Reply with our pid. 693 ;; Reply with our pid.
695 (server-send-string proc (concat "-emacs-pid " (number-to-string (emacs-pid)) "\n")) 694 (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 ;; -env NAME=VALUE: An environment variable. 739 ;; -env NAME=VALUE: An environment variable.
741 ((and (equal "-env" arg) (string-match "\\([^ ]+\\) " request)) 740 ((and (equal "-env" arg) (string-match "\\([^ ]+\\) " request))
742 (let ((var (server-unquote-arg (match-string 1 request)))) 741 (let ((var (server-unquote-arg (match-string 1 request))))
743 (when coding-system 742 ;; XXX Variables should be encoded as in getenv/setenv.
744 (setq var (decode-coding-string var coding-system)))
745 (setq request (substring request (match-end 0))) 743 (setq request (substring request (match-end 0)))
746 (setq env (cons var env)))) 744 (setq env (cons var env))))
747 745
diff --git a/src/callproc.c b/src/callproc.c
index ee702fef8c7..715178f8fb2 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -119,7 +119,6 @@ Lisp_Object Vprocess_environment;
119#ifdef DOS_NT 119#ifdef DOS_NT
120Lisp_Object Qbuffer_file_type; 120Lisp_Object Qbuffer_file_type;
121#endif /* DOS_NT */ 121#endif /* DOS_NT */
122Lisp_Object Qenvironment;
123 122
124/* True iff we are about to fork off a synchronous process or if we 123/* True iff we are about to fork off a synchronous process or if we
125 are waiting for it. */ 124 are waiting for it. */
@@ -1319,8 +1318,8 @@ child_setup (in, out, err, new_argv, set_pgrp, current_dir)
1319 1318
1320 if (!NILP (Vlocal_environment_variables)) 1319 if (!NILP (Vlocal_environment_variables))
1321 { 1320 {
1322 local = get_terminal_param (FRAME_DEVICE (XFRAME (selected_frame)), 1321 local = get_frame_param (XFRAME (Fframe_with_environment (selected_frame)),
1323 Qenvironment); 1322 Qenvironment);
1324 if (EQ (Vlocal_environment_variables, Qt) 1323 if (EQ (Vlocal_environment_variables, Qt)
1325 && !NILP (local)) 1324 && !NILP (local))
1326 environment = local; 1325 environment = local;
@@ -1356,7 +1355,7 @@ child_setup (in, out, err, new_argv, set_pgrp, current_dir)
1356 new_env = add_env (env, new_env, egetenv (SDATA (XCAR (tem)))); 1355 new_env = add_env (env, new_env, egetenv (SDATA (XCAR (tem))));
1357 1356
1358 /* The rest of the environment (either Vglobal_environment or the 1357 /* The rest of the environment (either Vglobal_environment or the
1359 'environment terminal parameter). */ 1358 'environment frame parameter). */
1360 for (tem = environment; 1359 for (tem = environment;
1361 CONSP (tem) && STRINGP (XCAR (tem)); 1360 CONSP (tem) && STRINGP (XCAR (tem));
1362 tem = XCDR (tem)) 1361 tem = XCDR (tem))
@@ -1488,12 +1487,12 @@ relocate_fd (fd, minfd)
1488} 1487}
1489 1488
1490static int 1489static int
1491getenv_internal (var, varlen, value, valuelen, terminal) 1490getenv_internal (var, varlen, value, valuelen, frame)
1492 char *var; 1491 char *var;
1493 int varlen; 1492 int varlen;
1494 char **value; 1493 char **value;
1495 int *valuelen; 1494 int *valuelen;
1496 Lisp_Object terminal; 1495 Lisp_Object frame;
1497{ 1496{
1498 Lisp_Object scan; 1497 Lisp_Object scan;
1499 Lisp_Object environment = Vglobal_environment; 1498 Lisp_Object environment = Vglobal_environment;
@@ -1528,17 +1527,19 @@ getenv_internal (var, varlen, value, valuelen, terminal)
1528 } 1527 }
1529 1528
1530 /* Find the environment in which to search the variable. */ 1529 /* Find the environment in which to search the variable. */
1531 if (!NILP (terminal)) 1530 if (!NILP (frame))
1532 { 1531 {
1533 Lisp_Object local = get_terminal_param (get_device (terminal, 1), Qenvironment); 1532 CHECK_FRAME (frame);
1533 frame = Fframe_with_environment (frame);
1534 Lisp_Object local = get_frame_param (XFRAME (frame), Qenvironment);
1534 /* Use Vglobal_environment if there is no local environment. */ 1535 /* Use Vglobal_environment if there is no local environment. */
1535 if (!NILP (local)) 1536 if (!NILP (local))
1536 environment = local; 1537 environment = local;
1537 } 1538 }
1538 else if (!NILP (Vlocal_environment_variables)) 1539 else if (!NILP (Vlocal_environment_variables))
1539 { 1540 {
1540 Lisp_Object local = get_terminal_param (FRAME_DEVICE (XFRAME (selected_frame)), 1541 Lisp_Object local = get_frame_param (XFRAME (Fframe_with_environment (selected_frame)),
1541 Qenvironment); 1542 Qenvironment);
1542 if (EQ (Vlocal_environment_variables, Qt) 1543 if (EQ (Vlocal_environment_variables, Qt)
1543 && !NILP (local)) 1544 && !NILP (local))
1544 environment = local; 1545 environment = local;
@@ -1594,25 +1595,23 @@ DEFUN ("getenv-internal", Fgetenv_internal, Sgetenv_internal, 1, 2, 0,
1594VARIABLE should be a string. Value is nil if VARIABLE is undefined in 1595VARIABLE should be a string. Value is nil if VARIABLE is undefined in
1595the environment. Otherwise, value is a string. 1596the environment. Otherwise, value is a string.
1596 1597
1597If optional parameter TERMINAL is non-nil, then it should be a 1598If optional parameter FRAME is non-nil, then it should be a frame. If
1598terminal id or a frame. If the specified terminal device has its own 1599that frame has its own set of environment variables, this function
1599set of environment variables, this function will look up VARIABLE in 1600will look up VARIABLE in there.
1600it.
1601 1601
1602Otherwise, this function searches `process-environment' for VARIABLE. 1602Otherwise, this function searches `process-environment' for VARIABLE.
1603If it was not found there, then it continues the search in either 1603If it was not found there, then it continues the search in either
1604`global-environment' or the local environment list of the current 1604`global-environment' or the local environment list of the current
1605terminal device, depending on the value of 1605frame, depending on the value of `local-environment-variables'. */)
1606`local-environment-variables'. */) 1606 (variable, frame)
1607 (variable, terminal) 1607 Lisp_Object variable, frame;
1608 Lisp_Object variable, terminal;
1609{ 1608{
1610 char *value; 1609 char *value;
1611 int valuelen; 1610 int valuelen;
1612 1611
1613 CHECK_STRING (variable); 1612 CHECK_STRING (variable);
1614 if (getenv_internal (SDATA (variable), SBYTES (variable), 1613 if (getenv_internal (SDATA (variable), SBYTES (variable),
1615 &value, &valuelen, terminal)) 1614 &value, &valuelen, frame))
1616 return make_string (value, valuelen); 1615 return make_string (value, valuelen);
1617 else 1616 else
1618 return Qnil; 1617 return Qnil;
@@ -1842,11 +1841,10 @@ Each element should be a string of the form ENVVARNAME=VALUE.
1842The environment which Emacs inherits is placed in this variable when 1841The environment which Emacs inherits is placed in this variable when
1843Emacs starts. 1842Emacs starts.
1844 1843
1845Some terminal devices may have their own local list of environment 1844Some frames may have their own local list of environment variables in
1846variables in their 'environment parameter, which may override this 1845their 'environment parameter, which may override this global list; see
1847global list; see `local-environment-variables'. See 1846`local-environment-variables'. See `process-environment' for a way to
1848`process-environment' for a way to modify an environment variable on 1847modify an environment variable on all frames.
1849all terminals.
1850 1848
1851If multiple entries define the same variable, the first one always 1849If multiple entries define the same variable, the first one always
1852takes precedence. 1850takes precedence.
@@ -1860,12 +1858,12 @@ See `setenv' and `getenv'. */);
1860Each element should be a string of the form ENVVARNAME=VALUE. 1858Each element should be a string of the form ENVVARNAME=VALUE.
1861 1859
1862Entries in this list take precedence to those in `global-environment' 1860Entries in this list take precedence to those in `global-environment'
1863or the terminal environment. (See `local-environment-variables' for 1861or the frame-local environment. (See `local-environment-variables'.)
1864an explanation of the terminal-local environment.) Therefore, 1862Therefore, let-binding `process-environment' is an easy way to
1865let-binding `process-environment' is an easy way to temporarily change 1863temporarily change the value of an environment variable, irrespective
1866the value of an environment variable, irrespective of where it comes 1864of where it comes from. To use `process-environment' to remove an
1867from. To use `process-environment' to remove an environment variable, 1865environment variable, include only its name in the list, without
1868include only its name in the list, without "=VALUE". 1866"=VALUE".
1869 1867
1870This variable is set to nil when Emacs starts. 1868This variable is set to nil when Emacs starts.
1871 1869
@@ -1886,21 +1884,18 @@ See `setenv' and `getenv'. */);
1886 defsubr (&Scall_process_region); 1884 defsubr (&Scall_process_region);
1887 1885
1888 DEFVAR_LISP ("local-environment-variables", &Vlocal_environment_variables, 1886 DEFVAR_LISP ("local-environment-variables", &Vlocal_environment_variables,
1889 doc: /* Enable or disable terminal-local environment variables. 1887 doc: /* Enable or disable frame-local environment variables.
1890If set to t, `getenv', `setenv' and subprocess creation functions use 1888If set to t, `getenv', `setenv' and subprocess creation functions use
1891the local environment of the terminal device of the selected frame, 1889the local environment of the selected frame, ignoring
1892ignoring `global-environment'. 1890`global-environment'.
1893 1891
1894If set to nil, Emacs uses `global-environment' and ignores the 1892If set to nil, Emacs uses `global-environment' and ignores the
1895terminal environment. 1893frame-local environment.
1896 1894
1897Otherwise, `local-environment-variables' should be a list of variable 1895Otherwise, `local-environment-variables' should be a list of variable
1898names (represented by Lisp strings) to look up in the terminal's 1896names (represented by Lisp strings) to look up in the frame's
1899environment. The rest will come from `global-environment'. */); 1897environment. The rest will come from `global-environment'. */);
1900 Vlocal_environment_variables = Qnil; 1898 Vlocal_environment_variables = Qnil;
1901
1902 Qenvironment = intern ("environment");
1903 staticpro (&Qenvironment);
1904} 1899}
1905 1900
1906/* arch-tag: 769b8045-1df7-4d2b-8968-e3fb49017f95 1901/* arch-tag: 769b8045-1df7-4d2b-8968-e3fb49017f95
diff --git a/src/frame.c b/src/frame.c
index c3140628cec..f0657975402 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -111,6 +111,7 @@ Lisp_Object Qbuffer_predicate, Qbuffer_list, Qburied_buffer_list;
111Lisp_Object Qtty_color_mode; 111Lisp_Object Qtty_color_mode;
112Lisp_Object Qtty, Qtty_type; 112Lisp_Object Qtty, Qtty_type;
113Lisp_Object Qwindow_system; 113Lisp_Object Qwindow_system;
114Lisp_Object Qenvironment;
114 115
115Lisp_Object Qfullscreen, Qfullwidth, Qfullheight, Qfullboth; 116Lisp_Object Qfullscreen, Qfullwidth, Qfullheight, Qfullboth;
116 117
@@ -1473,6 +1474,24 @@ The functions are run with one arg, the frame to be deleted. */)
1473 if (EQ (f->minibuffer_window, echo_area_window)) 1474 if (EQ (f->minibuffer_window, echo_area_window))
1474 echo_area_window = sf->minibuffer_window; 1475 echo_area_window = sf->minibuffer_window;
1475 1476
1477 /* Don't allow other frames to refer to a deleted frame in their
1478 'environment parameter. */
1479 {
1480 Lisp_Object tail, frame1;
1481 Lisp_Object env = get_frame_param (XFRAME (frame), Qenvironment);
1482 FOR_EACH_FRAME (tail, frame1)
1483 {
1484 if (EQ (frame, frame1) || !FRAME_LIVE_P (XFRAME (frame1)))
1485 continue;
1486 if (EQ (frame, get_frame_param (XFRAME (frame1), Qenvironment)))
1487 {
1488 store_frame_param (XFRAME (frame1), Qenvironment, env);
1489 if (!FRAMEP (env))
1490 env = frame1;
1491 }
1492 }
1493 }
1494
1476 /* Clear any X selections for this frame. */ 1495 /* Clear any X selections for this frame. */
1477#ifdef HAVE_X_WINDOWS 1496#ifdef HAVE_X_WINDOWS
1478 if (FRAME_X_P (f)) 1497 if (FRAME_X_P (f))
@@ -2577,6 +2596,43 @@ enabled such bindings for that variable with `make-variable-frame-local'. */)
2577 2596
2578 return unbind_to (count, Qnil); 2597 return unbind_to (count, Qnil);
2579} 2598}
2599
2600DEFUN ("frame-with-environment", Fframe_with_environment, Sframe_with_environment, 0, 1, 0,
2601 doc: /* Return the frame that has the environment variable list for FRAME.
2602
2603The frame-local environment variable list is normally shared between
2604frames that were created in the same Emacsclient session. The
2605environment list is stored in a single frame's 'environment parameter;
2606the other frames' 'environment parameter is set to this frame. This
2607function follows to chain of 'environment references to reach the
2608frame that stores the actual local environment list, and returns that
2609frame. */)
2610 (frame)
2611 Lisp_Object frame;
2612{
2613 Lisp_Object hare, tortoise;
2614
2615 if (NILP (frame))
2616 frame = selected_frame;
2617 CHECK_FRAME (frame);
2618
2619 hare = tortoise = get_frame_param (XFRAME (frame), Qenvironment);
2620 while (!NILP (hare) && FRAMEP (hare))
2621 {
2622 frame = hare;
2623 hare = get_frame_param (XFRAME (hare), Qenvironment);
2624 if (NILP (hare) || !FRAMEP (hare))
2625 break;
2626 frame = hare;
2627 hare = get_frame_param (XFRAME (hare), Qenvironment);
2628 tortoise = get_frame_param (XFRAME (tortoise), Qenvironment);
2629 if (EQ (hare, tortoise))
2630 error ("Cyclic frame-local environment indirection");
2631 }
2632
2633 return frame;
2634}
2635
2580 2636
2581DEFUN ("frame-char-height", Fframe_char_height, Sframe_char_height, 2637DEFUN ("frame-char-height", Fframe_char_height, Sframe_char_height,
2582 0, 1, 0, 2638 0, 1, 0,
@@ -4232,6 +4288,8 @@ syms_of_frame ()
4232 staticpro (&Qtty_type); 4288 staticpro (&Qtty_type);
4233 Qwindow_system = intern ("window-system"); 4289 Qwindow_system = intern ("window-system");
4234 staticpro (&Qwindow_system); 4290 staticpro (&Qwindow_system);
4291 Qenvironment = intern ("environment");
4292 staticpro (&Qenvironment);
4235 4293
4236 Qface_set_after_frame_default = intern ("face-set-after-frame-default"); 4294 Qface_set_after_frame_default = intern ("face-set-after-frame-default");
4237 staticpro (&Qface_set_after_frame_default); 4295 staticpro (&Qface_set_after_frame_default);
@@ -4416,6 +4474,7 @@ This variable is local to the current terminal and cannot be buffer-local. */);
4416 defsubr (&Sframe_parameters); 4474 defsubr (&Sframe_parameters);
4417 defsubr (&Sframe_parameter); 4475 defsubr (&Sframe_parameter);
4418 defsubr (&Smodify_frame_parameters); 4476 defsubr (&Smodify_frame_parameters);
4477 defsubr (&Sframe_with_environment);
4419 defsubr (&Sframe_char_height); 4478 defsubr (&Sframe_char_height);
4420 defsubr (&Sframe_char_width); 4479 defsubr (&Sframe_char_width);
4421 defsubr (&Sframe_pixel_height); 4480 defsubr (&Sframe_pixel_height);
diff --git a/src/frame.h b/src/frame.h
index c63b0bec464..6c54c328923 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -781,6 +781,7 @@ typedef struct frame *FRAME_PTR;
781extern Lisp_Object Qframep, Qframe_live_p; 781extern Lisp_Object Qframep, Qframe_live_p;
782extern Lisp_Object Qtty, Qtty_type; 782extern Lisp_Object Qtty, Qtty_type;
783extern Lisp_Object Qdevice, Qdisplay_live_p; 783extern Lisp_Object Qdevice, Qdisplay_live_p;
784extern Lisp_Object Qenvironment;
784 785
785extern struct frame *last_nonminibuf_frame; 786extern struct frame *last_nonminibuf_frame;
786 787
diff --git a/src/lisp.h b/src/lisp.h
index 4b71cd67e98..0aa2d7cb510 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -2998,6 +2998,7 @@ EXFUN (Fvisible_frame_list, 0);
2998EXFUN (Fframe_parameter, 2); 2998EXFUN (Fframe_parameter, 2);
2999EXFUN (Fframe_parameters, 1); 2999EXFUN (Fframe_parameters, 1);
3000EXFUN (Fmodify_frame_parameters, 2); 3000EXFUN (Fmodify_frame_parameters, 2);
3001EXFUN (Fframe_with_environment, 1);
3001EXFUN (Fset_frame_height, 3); 3002EXFUN (Fset_frame_height, 3);
3002EXFUN (Fset_frame_width, 3); 3003EXFUN (Fset_frame_width, 3);
3003EXFUN (Fset_frame_size, 3); 3004EXFUN (Fset_frame_size, 3);