diff options
| -rw-r--r-- | README.multi-tty | 16 | ||||
| -rw-r--r-- | lisp/env.el | 84 | ||||
| -rw-r--r-- | lisp/frame.el | 8 | ||||
| -rw-r--r-- | lisp/server.el | 12 | ||||
| -rw-r--r-- | src/callproc.c | 71 | ||||
| -rw-r--r-- | src/frame.c | 59 | ||||
| -rw-r--r-- | src/frame.h | 1 | ||||
| -rw-r--r-- | src/lisp.h | 1 |
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. |
| 99 | VARIABLE should be a string. VALUE is optional; if not provided or | 99 | VARIABLE should be a string. VALUE is optional; if not provided or |
| 100 | nil, the environment variable VARIABLE will be removed. UNSET | 100 | nil, the environment variable VARIABLE will be removed. UNSET |
| @@ -112,12 +112,15 @@ Interactively, always replace environment variables in the new value. | |||
| 112 | If VARIABLE is set in `process-environment', then this function | 112 | If VARIABLE is set in `process-environment', then this function |
| 113 | modifies its value there. Otherwise, this function works by | 113 | modifies its value there. Otherwise, this function works by |
| 114 | modifying either `global-environment' or the environment | 114 | modifying either `global-environment' or the environment |
| 115 | belonging to the terminal device of the selected frame, depending | 115 | belonging to the selected frame, depending on the value of |
| 116 | on the value of `local-environment-variables'. | 116 | `local-environment-variables'. |
| 117 | 117 | ||
| 118 | If optional parameter TERMINAL is non-nil, then it should be a | 118 | If optional parameter FRAME is non-nil, then it should be a a |
| 119 | terminal id or a frame. If the specified terminal device has its own | 119 | frame. If the specified frame has its own set of environment |
| 120 | set of environment variables, this function will modify VAR in it. | 120 | variables, this function will modify VARIABLE in it. Note that |
| 121 | frames on the same terminal device usually share their | ||
| 122 | environment, so calling `setenv' on one of them affects the | ||
| 123 | others as well. | ||
| 121 | 124 | ||
| 122 | As a special case, setting variable `TZ' calls `set-time-zone-rule' as | 125 | As a special case, setting variable `TZ' calls `set-time-zone-rule' as |
| 123 | a side-effect." | 126 | a 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. |
| 206 | VARIABLE should be a string. Value is nil if VARIABLE is undefined in | 211 | VARIABLE should be a string. Value is nil if VARIABLE is undefined in |
| 207 | the environment. Otherwise, value is a string. | 212 | the environment. Otherwise, value is a string. |
| 208 | 213 | ||
| 209 | If optional parameter TERMINAL is non-nil, then it should be a | 214 | If optional parameter FRAME is non-nil, then it should be a |
| 210 | terminal id or a frame. If the specified terminal device has its own | 215 | frame. If the specified terminal device has its own set of |
| 211 | set of environment variables, this function will look up VARIABLE in | 216 | environment variables, this function will look up VARIABLE in it. |
| 212 | it. | ||
| 213 | 217 | ||
| 214 | Otherwise, this function searches `process-environment' for VARIABLE. | 218 | Otherwise, this function searches `process-environment' for |
| 215 | If it was not found there, then it continues the search in either | 219 | VARIABLE. If it was not found there, then it continues the |
| 216 | `global-environment' or the local environment list of the current | 220 | search in either `global-environment' or the environment list of |
| 217 | terminal device, depending on the value of | 221 | the 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 | ||
| 237 | The list is constructed from elements of `process-environment', | 241 | The 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 |
| 239 | current terminal, as specified by `local-environment-variables'. | 243 | selected frame, as specified by `local-environment-variables'. |
| 240 | 244 | ||
| 241 | Non-ASCII characters are encoded according to the initial value of | 245 | Non-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. |
| 243 | See `setenv' and `getenv'." | 247 | See `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 |
| 120 | Lisp_Object Qbuffer_file_type; | 120 | Lisp_Object Qbuffer_file_type; |
| 121 | #endif /* DOS_NT */ | 121 | #endif /* DOS_NT */ |
| 122 | Lisp_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 | ||
| 1490 | static int | 1489 | static int |
| 1491 | getenv_internal (var, varlen, value, valuelen, terminal) | 1490 | getenv_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, | |||
| 1594 | VARIABLE should be a string. Value is nil if VARIABLE is undefined in | 1595 | VARIABLE should be a string. Value is nil if VARIABLE is undefined in |
| 1595 | the environment. Otherwise, value is a string. | 1596 | the environment. Otherwise, value is a string. |
| 1596 | 1597 | ||
| 1597 | If optional parameter TERMINAL is non-nil, then it should be a | 1598 | If optional parameter FRAME is non-nil, then it should be a frame. If |
| 1598 | terminal id or a frame. If the specified terminal device has its own | 1599 | that frame has its own set of environment variables, this function |
| 1599 | set of environment variables, this function will look up VARIABLE in | 1600 | will look up VARIABLE in there. |
| 1600 | it. | ||
| 1601 | 1601 | ||
| 1602 | Otherwise, this function searches `process-environment' for VARIABLE. | 1602 | Otherwise, this function searches `process-environment' for VARIABLE. |
| 1603 | If it was not found there, then it continues the search in either | 1603 | If 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 |
| 1605 | terminal device, depending on the value of | 1605 | frame, 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. | |||
| 1842 | The environment which Emacs inherits is placed in this variable when | 1841 | The environment which Emacs inherits is placed in this variable when |
| 1843 | Emacs starts. | 1842 | Emacs starts. |
| 1844 | 1843 | ||
| 1845 | Some terminal devices may have their own local list of environment | 1844 | Some frames may have their own local list of environment variables in |
| 1846 | variables in their 'environment parameter, which may override this | 1845 | their 'environment parameter, which may override this global list; see |
| 1847 | global 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 | 1847 | modify an environment variable on all frames. |
| 1849 | all terminals. | ||
| 1850 | 1848 | ||
| 1851 | If multiple entries define the same variable, the first one always | 1849 | If multiple entries define the same variable, the first one always |
| 1852 | takes precedence. | 1850 | takes precedence. |
| @@ -1860,12 +1858,12 @@ See `setenv' and `getenv'. */); | |||
| 1860 | Each element should be a string of the form ENVVARNAME=VALUE. | 1858 | Each element should be a string of the form ENVVARNAME=VALUE. |
| 1861 | 1859 | ||
| 1862 | Entries in this list take precedence to those in `global-environment' | 1860 | Entries in this list take precedence to those in `global-environment' |
| 1863 | or the terminal environment. (See `local-environment-variables' for | 1861 | or the frame-local environment. (See `local-environment-variables'.) |
| 1864 | an explanation of the terminal-local environment.) Therefore, | 1862 | Therefore, let-binding `process-environment' is an easy way to |
| 1865 | let-binding `process-environment' is an easy way to temporarily change | 1863 | temporarily change the value of an environment variable, irrespective |
| 1866 | the value of an environment variable, irrespective of where it comes | 1864 | of where it comes from. To use `process-environment' to remove an |
| 1867 | from. To use `process-environment' to remove an environment variable, | 1865 | environment variable, include only its name in the list, without |
| 1868 | include only its name in the list, without "=VALUE". | 1866 | "=VALUE". |
| 1869 | 1867 | ||
| 1870 | This variable is set to nil when Emacs starts. | 1868 | This 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. |
| 1890 | If set to t, `getenv', `setenv' and subprocess creation functions use | 1888 | If set to t, `getenv', `setenv' and subprocess creation functions use |
| 1891 | the local environment of the terminal device of the selected frame, | 1889 | the local environment of the selected frame, ignoring |
| 1892 | ignoring `global-environment'. | 1890 | `global-environment'. |
| 1893 | 1891 | ||
| 1894 | If set to nil, Emacs uses `global-environment' and ignores the | 1892 | If set to nil, Emacs uses `global-environment' and ignores the |
| 1895 | terminal environment. | 1893 | frame-local environment. |
| 1896 | 1894 | ||
| 1897 | Otherwise, `local-environment-variables' should be a list of variable | 1895 | Otherwise, `local-environment-variables' should be a list of variable |
| 1898 | names (represented by Lisp strings) to look up in the terminal's | 1896 | names (represented by Lisp strings) to look up in the frame's |
| 1899 | environment. The rest will come from `global-environment'. */); | 1897 | environment. 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; | |||
| 111 | Lisp_Object Qtty_color_mode; | 111 | Lisp_Object Qtty_color_mode; |
| 112 | Lisp_Object Qtty, Qtty_type; | 112 | Lisp_Object Qtty, Qtty_type; |
| 113 | Lisp_Object Qwindow_system; | 113 | Lisp_Object Qwindow_system; |
| 114 | Lisp_Object Qenvironment; | ||
| 114 | 115 | ||
| 115 | Lisp_Object Qfullscreen, Qfullwidth, Qfullheight, Qfullboth; | 116 | Lisp_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 | |||
| 2600 | DEFUN ("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 | |||
| 2603 | The frame-local environment variable list is normally shared between | ||
| 2604 | frames that were created in the same Emacsclient session. The | ||
| 2605 | environment list is stored in a single frame's 'environment parameter; | ||
| 2606 | the other frames' 'environment parameter is set to this frame. This | ||
| 2607 | function follows to chain of 'environment references to reach the | ||
| 2608 | frame that stores the actual local environment list, and returns that | ||
| 2609 | frame. */) | ||
| 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 | ||
| 2581 | DEFUN ("frame-char-height", Fframe_char_height, Sframe_char_height, | 2637 | DEFUN ("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; | |||
| 781 | extern Lisp_Object Qframep, Qframe_live_p; | 781 | extern Lisp_Object Qframep, Qframe_live_p; |
| 782 | extern Lisp_Object Qtty, Qtty_type; | 782 | extern Lisp_Object Qtty, Qtty_type; |
| 783 | extern Lisp_Object Qdevice, Qdisplay_live_p; | 783 | extern Lisp_Object Qdevice, Qdisplay_live_p; |
| 784 | extern Lisp_Object Qenvironment; | ||
| 784 | 785 | ||
| 785 | extern struct frame *last_nonminibuf_frame; | 786 | extern 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); | |||
| 2998 | EXFUN (Fframe_parameter, 2); | 2998 | EXFUN (Fframe_parameter, 2); |
| 2999 | EXFUN (Fframe_parameters, 1); | 2999 | EXFUN (Fframe_parameters, 1); |
| 3000 | EXFUN (Fmodify_frame_parameters, 2); | 3000 | EXFUN (Fmodify_frame_parameters, 2); |
| 3001 | EXFUN (Fframe_with_environment, 1); | ||
| 3001 | EXFUN (Fset_frame_height, 3); | 3002 | EXFUN (Fset_frame_height, 3); |
| 3002 | EXFUN (Fset_frame_width, 3); | 3003 | EXFUN (Fset_frame_width, 3); |
| 3003 | EXFUN (Fset_frame_size, 3); | 3004 | EXFUN (Fset_frame_size, 3); |