aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/misc/flymake.texi8
-rw-r--r--etc/NEWS8
-rw-r--r--lisp/files.el55
-rw-r--r--lisp/isearch.el1
-rw-r--r--lisp/progmodes/cc-mode.el214
-rw-r--r--lisp/progmodes/flymake.el10
-rw-r--r--src/.gdbinit3
-rw-r--r--src/buffer.c2
-rw-r--r--src/bytecode.c3
-rw-r--r--src/dispextern.h9
-rw-r--r--src/dispnew.c3
-rw-r--r--src/editfns.c45
-rw-r--r--src/eval.c6
-rw-r--r--src/font.c4
-rw-r--r--src/fringe.c22
-rw-r--r--src/ftfont.c7
-rw-r--r--src/lisp.h46
-rw-r--r--src/lread.c6
-rw-r--r--src/msdos.c8
-rw-r--r--src/term.c8
-rw-r--r--src/window.c2
-rw-r--r--src/xdisp.c51
-rw-r--r--src/xfaces.c303
-rw-r--r--src/xwidget.c20
24 files changed, 575 insertions, 269 deletions
diff --git a/doc/misc/flymake.texi b/doc/misc/flymake.texi
index e7f4da75bb9..502d408f2b8 100644
--- a/doc/misc/flymake.texi
+++ b/doc/misc/flymake.texi
@@ -84,6 +84,10 @@ Syntax check is done ``on-the-fly''. It is started whenever
84@code{flymake-start-on-flymake-mode} is nil; 84@code{flymake-start-on-flymake-mode} is nil;
85 85
86@item 86@item
87the buffer is saved, unless @code{flymake-start-on-save-buffer} is
88nil;
89
90@item
87a newline character is added to the buffer, unless 91a newline character is added to the buffer, unless
88@code{flymake-start-syntax-check-on-newline} is nil; 92@code{flymake-start-syntax-check-on-newline} is nil;
89 93
@@ -220,6 +224,10 @@ after a newline character is inserted into the buffer.
220A boolean flag indicating whether to start syntax check immediately 224A boolean flag indicating whether to start syntax check immediately
221after enabling @code{flymake-mode}. 225after enabling @code{flymake-mode}.
222 226
227@item flymake-start-on-save-buffer
228A boolean flag indicating whether to start syntax check after saving
229the buffer.
230
223@item flymake-error 231@item flymake-error
224A custom face for highlighting regions for which an error has been 232A custom face for highlighting regions for which an error has been
225reported. 233reported.
diff --git a/etc/NEWS b/etc/NEWS
index d6b7485f7ff..46a57b1888c 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -183,6 +183,9 @@ shown in the currently selected window.
183You should instead set properties on known diagnostic symbols, like 183You should instead set properties on known diagnostic symbols, like
184':error' and ':warning', as demonstrated in the Flymake manual. 184':error' and ':warning', as demonstrated in the Flymake manual.
185 185
186*** New customizable variable 'flymake-start-on-save-buffer'
187Control whether Flymake starts checking the buffer on save.
188
186** Package 189** Package
187*** New 'package-quickstart' feature 190*** New 'package-quickstart' feature
188When 'package-quickstart' is non-nil, package.el precomputes a big autoloads 191When 'package-quickstart' is non-nil, package.el precomputes a big autoloads
@@ -573,6 +576,11 @@ manual for more details.
573* Lisp Changes in Emacs 27.1 576* Lisp Changes in Emacs 27.1
574 577
575+++ 578+++
579** Face specifications (of the kind used in `face-remapping-alist')
580 now support filters, allowing faces to vary between windows display
581 the same buffer.
582
583+++
576** New function assoc-delete-all. 584** New function assoc-delete-all.
577 585
578+++ 586+++
diff --git a/lisp/files.el b/lisp/files.el
index dbe95bb6659..3921040fa9b 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -2014,17 +2014,47 @@ think it does, because \"free\" is pretty hard to define in practice."
2014 :version "25.1" 2014 :version "25.1"
2015 :type '(choice integer (const :tag "Never issue warning" nil))) 2015 :type '(choice integer (const :tag "Never issue warning" nil)))
2016 2016
2017(defun abort-if-file-too-large (size op-type filename) 2017(declare-function x-popup-dialog "menu.c" (position contents &optional header))
2018
2019(defun files--ask-user-about-large-file (size op-type filename offer-raw)
2020 (let ((prompt (format "File %s is large (%s), really %s?"
2021 (file-name-nondirectory filename)
2022 (file-size-human-readable size) op-type)))
2023 (if (not offer-raw)
2024 (if (y-or-n-p prompt) nil 'abort)
2025 (let* ((use-dialog (and (display-popup-menus-p)
2026 last-input-event
2027 (listp last-nonmenu-event)
2028 use-dialog-box))
2029 (choice
2030 (if use-dialog
2031 (x-popup-dialog t `(,prompt
2032 ("Yes" . ?y)
2033 ("No" . ?n)
2034 ("Open in raw mode" . ?r)))
2035 (read-char-choice
2036 (concat prompt " (y)es or (n)o or (r)aw ")
2037 '(?y ?Y ?n ?N ?r ?R)))))
2038 (cond ((memq choice '(?y ?Y)) nil)
2039 ((memq choice '(?r ?R)) 'raw)
2040 (t 'abort))))))
2041
2042(defun abort-if-file-too-large (size op-type filename &optional offer-raw)
2018 "If file SIZE larger than `large-file-warning-threshold', allow user to abort. 2043 "If file SIZE larger than `large-file-warning-threshold', allow user to abort.
2019OP-TYPE specifies the file operation being performed (for message to user)." 2044OP-TYPE specifies the file operation being performed (for message
2020 (when (and large-file-warning-threshold size 2045to user). If OFFER-RAW is true, give user the additional option
2021 (> size large-file-warning-threshold) 2046to open the file in raw mode. If the user chooses this option,
2022 ;; No point in warning if we can't read it. 2047`abort-if-file-too-large' returns the symbol `raw'. Otherwise, it
2023 (file-readable-p filename) 2048returns nil or exits non-locally."
2024 (not (y-or-n-p (format "File %s is large (%s), really %s? " 2049 (let ((choice (and large-file-warning-threshold size
2025 (file-name-nondirectory filename) 2050 (> size large-file-warning-threshold)
2026 (file-size-human-readable size) op-type)))) 2051 ;; No point in warning if we can't read it.
2027 (user-error "Aborted"))) 2052 (file-readable-p filename)
2053 (files--ask-user-about-large-file
2054 size op-type filename offer-raw))))
2055 (when (eq choice 'abort)
2056 (user-error "Aborted"))
2057 choice))
2028 2058
2029(defun warn-maybe-out-of-memory (size) 2059(defun warn-maybe-out-of-memory (size)
2030 "Warn if an attempt to open file of SIZE bytes may run out of memory." 2060 "Warn if an attempt to open file of SIZE bytes may run out of memory."
@@ -2104,7 +2134,10 @@ the various files."
2104 (setq buf other)))) 2134 (setq buf other))))
2105 ;; Check to see if the file looks uncommonly large. 2135 ;; Check to see if the file looks uncommonly large.
2106 (when (not (or buf nowarn)) 2136 (when (not (or buf nowarn))
2107 (abort-if-file-too-large (nth 7 attributes) "open" filename) 2137 (when (eq (abort-if-file-too-large
2138 (nth 7 attributes) "open" filename t)
2139 'raw)
2140 (setf rawfile t))
2108 (warn-maybe-out-of-memory (nth 7 attributes))) 2141 (warn-maybe-out-of-memory (nth 7 attributes)))
2109 (if buf 2142 (if buf
2110 ;; We are using an existing buffer. 2143 ;; We are using an existing buffer.
diff --git a/lisp/isearch.el b/lisp/isearch.el
index feadf10e8b7..1e785a44c51 100644
--- a/lisp/isearch.el
+++ b/lisp/isearch.el
@@ -2036,6 +2036,7 @@ If search string is empty, just beep."
2036(defun isearch-yank-kill () 2036(defun isearch-yank-kill ()
2037 "Pull string from kill ring into search string." 2037 "Pull string from kill ring into search string."
2038 (interactive) 2038 (interactive)
2039 (unless isearch-mode (isearch-mode t))
2039 (isearch-yank-string (current-kill 0))) 2040 (isearch-yank-string (current-kill 0)))
2040 2041
2041(defun isearch-yank-pop () 2042(defun isearch-yank-pop ()
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index a1411ad5ea2..e619fac43f2 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -1110,13 +1110,56 @@ Note that the style variables are always made local to the buffer."
1110 (goto-char start) 1110 (goto-char start)
1111 (while (progn 1111 (while (progn
1112 (parse-partial-sexp (point) end nil nil st-s 'syntax-table) 1112 (parse-partial-sexp (point) end nil nil st-s 'syntax-table)
1113 (c-clear-char-property (1- (point)) 'syntax-table) 1113 (unless (bobp)
1114 (c-clear-char-property (1- (point)) 'syntax-table))
1114 (setq st-pos (point)) 1115 (setq st-pos (point))
1115 (and (< (point) end) 1116 (and (< (point) end)
1116 (not (eq (char-before) ?\"))))) 1117 (not (eq (char-before) ?\")))))
1117 (goto-char (min no-st-pos st-pos)) 1118 (goto-char (min no-st-pos st-pos))
1118 nil)) 1119 nil))
1119 1120
1121(defun c-multiline-string-check-final-quote ()
1122 ;; Check that the final quote in the buffer is correctly marked or not with
1123 ;; a string-fence syntax-table text propery. The return value has no
1124 ;; significance.
1125 (let (pos-ll pos-lt)
1126 (save-excursion
1127 (goto-char (point-max))
1128 (skip-chars-backward "^\"")
1129 (while
1130 (and
1131 (not (bobp))
1132 (cond
1133 ((progn
1134 (setq pos-ll (c-literal-limits)
1135 pos-lt (c-literal-type pos-ll))
1136 (memq pos-lt '(c c++)))
1137 ;; In a comment.
1138 (goto-char (car pos-ll)))
1139 ((save-excursion
1140 (backward-char) ; over "
1141 (eq (logand (skip-chars-backward "\\\\") 1) 1))
1142 ;; At an escaped string.
1143 (backward-char)
1144 t)
1145 (t
1146 ;; At a significant "
1147 (c-clear-char-property (1- (point)) 'syntax-table)
1148 (setq pos-ll (c-literal-limits)
1149 pos-lt (c-literal-type pos-ll))
1150 nil)))
1151 (skip-chars-backward "^\""))
1152 (cond
1153 ((bobp))
1154 ((eq pos-lt 'string)
1155 (c-put-char-property (1- (point)) 'syntax-table '(15)))
1156 (t nil)))))
1157
1158(defvar c-bc-changed-stringiness nil)
1159;; Non-nil when, in a before-change function, the deletion of a range of text
1160;; will change the "stringiness" of the subsequent text. Only used when
1161;; `c-multiline-sting-start-char' is a non-nil value which isn't a character.
1162
1120(defun c-before-change-check-unbalanced-strings (beg end) 1163(defun c-before-change-check-unbalanced-strings (beg end)
1121 ;; If BEG or END is inside an unbalanced string, remove the syntax-table 1164 ;; If BEG or END is inside an unbalanced string, remove the syntax-table
1122 ;; text property from respectively the start or end of the string. Also 1165 ;; text property from respectively the start or end of the string. Also
@@ -1175,6 +1218,18 @@ Note that the style variables are always made local to the buffer."
1175 (< (point) (point-max)))))) 1218 (< (point) (point-max))))))
1176 (setq c-new-END (max (point) c-new-END))) 1219 (setq c-new-END (max (point) c-new-END)))
1177 1220
1221 (c-multiline-string-start-char
1222 (setq c-bc-changed-stringiness
1223 (not (eq (eq end-literal-type 'string)
1224 (eq beg-literal-type 'string))))
1225 ;; Deal with deletion of backslashes before "s.
1226 (goto-char end)
1227 (if (and (looking-at "\\\\*\"")
1228 (eq (logand (skip-chars-backward "\\\\" beg) 1) 1))
1229 (setq c-bc-changed-stringiness (not c-bc-changed-stringiness)))
1230 (if (eq beg-literal-type 'string)
1231 (setq c-new-BEG (min (car beg-limits) c-new-BEG))))
1232
1178 ((< c-new-END (point-max)) 1233 ((< c-new-END (point-max))
1179 (goto-char (1+ c-new-END)) ; might be a newline. 1234 (goto-char (1+ c-new-END)) ; might be a newline.
1180 ;; In the following regexp, the initial \n caters for a newline getting 1235 ;; In the following regexp, the initial \n caters for a newline getting
@@ -1183,7 +1238,6 @@ Note that the style variables are always made local to the buffer."
1183 nil t) 1238 nil t)
1184 ;; We're at an EOLL or point-max. 1239 ;; We're at an EOLL or point-max.
1185 (setq c-new-END (min (1+ (point)) (point-max))) 1240 (setq c-new-END (min (1+ (point)) (point-max)))
1186 ;; FIXME!!! Write a clever comment here.
1187 (goto-char c-new-END) 1241 (goto-char c-new-END)
1188 (if (equal (c-get-char-property (1- (point)) 'syntax-table) '(15)) 1242 (if (equal (c-get-char-property (1- (point)) 'syntax-table) '(15))
1189 (if (memq (char-before) '(?\n ?\r)) 1243 (if (memq (char-before) '(?\n ?\r))
@@ -1202,14 +1256,16 @@ Note that the style variables are always made local to the buffer."
1202 (if (c-search-backward-char-property 'syntax-table '(15) c-new-BEG) 1256 (if (c-search-backward-char-property 'syntax-table '(15) c-new-BEG)
1203 (c-clear-char-property (point) 'syntax-table)))) 1257 (c-clear-char-property (point) 'syntax-table))))
1204 1258
1205 (when (eq end-literal-type 'string) 1259 (unless (and c-multiline-string-start-char
1206 (c-clear-char-property (1- (cdr end-limits)) 'syntax-table)) 1260 (not (c-characterp c-multiline-string-start-char)))
1261 (when (eq end-literal-type 'string)
1262 (c-clear-char-property (1- (cdr end-limits)) 'syntax-table))
1207 1263
1208 (when (eq beg-literal-type 'string) 1264 (when (eq beg-literal-type 'string)
1209 (setq c-new-BEG (min c-new-BEG (car beg-limits))) 1265 (setq c-new-BEG (min c-new-BEG (car beg-limits)))
1210 (c-clear-char-property (car beg-limits) 'syntax-table)))) 1266 (c-clear-char-property (car beg-limits) 'syntax-table)))))
1211 1267
1212(defun c-after-change-re-mark-unbalanced-strings (beg _end _old-len) 1268(defun c-after-change-re-mark-unbalanced-strings (beg end _old-len)
1213 ;; Mark any unbalanced strings in the region (c-new-BEG c-new-END) with 1269 ;; Mark any unbalanced strings in the region (c-new-BEG c-new-END) with
1214 ;; string fence syntax-table text properties. 1270 ;; string fence syntax-table text properties.
1215 ;; 1271 ;;
@@ -1218,66 +1274,90 @@ Note that the style variables are always made local to the buffer."
1218 ;; 1274 ;;
1219 ;; This function is called exclusively as an after-change function via 1275 ;; This function is called exclusively as an after-change function via
1220 ;; `c-before-font-lock-functions'. 1276 ;; `c-before-font-lock-functions'.
1221 (c-save-buffer-state 1277 (if (and c-multiline-string-start-char
1222 ((cll (progn (goto-char c-new-BEG) 1278 (not (c-characterp c-multiline-string-start-char)))
1223 (c-literal-limits))) 1279 ;; Only the last " might need to be marked.
1224 (beg-literal-type (and cll (c-literal-type cll))) 1280 (c-save-buffer-state
1225 (beg-limits 1281 ((beg-literal-limits
1226 (cond 1282 (progn (goto-char beg) (c-literal-limits)))
1227 ((and (eq beg-literal-type 'string) 1283 (beg-literal-type (c-literal-type beg-literal-limits))
1228 (c-unescaped-nls-in-string-p (car cll))) 1284 end-literal-limits end-literal-type)
1229 (cons 1285 (when (and (eq beg-literal-type 'string)
1230 (car cll) 1286 (c-get-char-property (car beg-literal-limits) 'syntax-table))
1287 (c-clear-char-property (car beg-literal-limits) 'syntax-table)
1288 (setq c-bc-changed-stringiness (not c-bc-changed-stringiness)))
1289 (setq end-literal-limits (progn (goto-char end) (c-literal-limits))
1290 end-literal-type (c-literal-type end-literal-limits))
1291 ;; Deal with the insertion of backslashes before a ".
1292 (goto-char end)
1293 (if (and (looking-at "\\\\*\"")
1294 (eq (logand (skip-chars-backward "\\\\" beg) 1) 1))
1295 (setq c-bc-changed-stringiness (not c-bc-changed-stringiness)))
1296 (when (eq (eq (eq beg-literal-type 'string)
1297 (eq end-literal-type 'string))
1298 c-bc-changed-stringiness)
1299 (c-multiline-string-check-final-quote)))
1300 ;; There could be several "s needing marking.
1301 (c-save-buffer-state
1302 ((cll (progn (goto-char c-new-BEG)
1303 (c-literal-limits)))
1304 (beg-literal-type (and cll (c-literal-type cll)))
1305 (beg-limits
1306 (cond
1307 ((and (eq beg-literal-type 'string)
1308 (c-unescaped-nls-in-string-p (car cll)))
1309 (cons
1310 (car cll)
1311 (progn
1312 (goto-char (1+ (car cll)))
1313 (search-forward-regexp
1314 (cdr (assq (char-after (car cll)) c-string-innards-re-alist))
1315 nil t)
1316 (min (1+ (point)) (point-max)))))
1317 ((and (null beg-literal-type)
1318 (goto-char beg)
1319 (eq (char-before) c-multiline-string-start-char)
1320 (memq (char-after) c-string-delims))
1321 (cons (point)
1322 (progn
1323 (forward-char)
1324 (search-forward-regexp
1325 (cdr (assq (char-before) c-string-innards-re-alist)) nil t)
1326 (1+ (point)))))
1327 (cll)))
1328 s)
1329 (goto-char
1330 (cond ((null beg-literal-type)
1331 c-new-BEG)
1332 ((eq beg-literal-type 'string)
1333 (car beg-limits))
1334 (t ; comment
1335 (cdr beg-limits))))
1336 (while
1337 (and
1338 (< (point) c-new-END)
1231 (progn 1339 (progn
1232 (goto-char (1+ (car cll))) 1340 ;; Skip over any comments before the next string.
1233 (search-forward-regexp 1341 (while (progn
1234 (cdr (assq (char-after (car cll)) c-string-innards-re-alist)) 1342 (setq s (parse-partial-sexp (point) c-new-END nil
1235 nil t) 1343 nil s 'syntax-table))
1236 (min (1+ (point)) (point-max))))) 1344 (and (not (nth 3 s))
1237 ((and (null beg-literal-type) 1345 (< (point) c-new-END)
1238 (goto-char beg) 1346 (not (memq (char-before) c-string-delims)))))
1239 (eq (char-before) c-multiline-string-start-char) 1347 ;; We're at the start of a string.
1240 (memq (char-after) c-string-delims)) 1348 (memq (char-before) c-string-delims)))
1241 (cons (point) 1349 (if (c-unescaped-nls-in-string-p (1- (point)))
1242 (progn 1350 (looking-at "\\(\\\\\\(.\\|\n|\\\r\\)\\|[^\"]\\)*")
1243 (forward-char) 1351 (looking-at (cdr (assq (char-before) c-string-innards-re-alist))))
1244 (search-forward-regexp 1352 (cond
1245 (cdr (assq (char-before) c-string-innards-re-alist)) nil t) 1353 ((memq (char-after (match-end 0)) '(?\n ?\r))
1246 (1+ (point))))) 1354 (c-put-char-property (1- (point)) 'syntax-table '(15))
1247 (cll))) 1355 (c-put-char-property (match-end 0) 'syntax-table '(15)))
1248 s) 1356 ((or (eq (match-end 0) (point-max))
1249 (goto-char 1357 (eq (char-after (match-end 0)) ?\\)) ; \ at EOB
1250 (cond ((null beg-literal-type) 1358 (c-put-char-property (1- (point)) 'syntax-table '(15))))
1251 c-new-BEG) 1359 (goto-char (min (1+ (match-end 0)) (point-max)))
1252 ((eq beg-literal-type 'string) 1360 (setq s nil)))))
1253 (car beg-limits))
1254 (t ; comment
1255 (cdr beg-limits))))
1256 (while
1257 (and
1258 (< (point) c-new-END)
1259 (progn
1260 ;; Skip over any comments before the next string.
1261 (while (progn
1262 (setq s (parse-partial-sexp (point) c-new-END nil
1263 nil s 'syntax-table))
1264 (and (not (nth 3 s))
1265 (< (point) c-new-END)
1266 (not (memq (char-before) c-string-delims)))))
1267 ;; We're at the start of a string.
1268 (memq (char-before) c-string-delims)))
1269 (if (c-unescaped-nls-in-string-p (1- (point)))
1270 (looking-at "[^\"]*")
1271 (looking-at (cdr (assq (char-before) c-string-innards-re-alist))))
1272 (cond
1273 ((memq (char-after (match-end 0)) '(?\n ?\r))
1274 (c-put-char-property (1- (point)) 'syntax-table '(15))
1275 (c-put-char-property (match-end 0) 'syntax-table '(15)))
1276 ((or (eq (match-end 0) (point-max))
1277 (eq (char-after (match-end 0)) ?\\)) ; \ at EOB
1278 (c-put-char-property (1- (point)) 'syntax-table '(15))))
1279 (goto-char (min (1+ (match-end 0)) (point-max)))
1280 (setq s nil))))
1281 1361
1282;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1362;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1283;; Parsing of quotes. 1363;; Parsing of quotes.
diff --git a/lisp/progmodes/flymake.el b/lisp/progmodes/flymake.el
index d8959c8356a..fdb22ccaf34 100644
--- a/lisp/progmodes/flymake.el
+++ b/lisp/progmodes/flymake.el
@@ -196,11 +196,17 @@ If nil, never start checking buffer automatically like this."
196 'flymake-start-on-flymake-mode "26.1") 196 'flymake-start-on-flymake-mode "26.1")
197 197
198(defcustom flymake-start-on-flymake-mode t 198(defcustom flymake-start-on-flymake-mode t
199 "Start syntax check when `flymake-mode' is enabled. 199 "If non-nil, start syntax check when `flymake-mode' is enabled.
200Specifically, start it when the buffer is actually displayed." 200Specifically, start it when the buffer is actually displayed."
201 :version "26.1" 201 :version "26.1"
202 :type 'boolean) 202 :type 'boolean)
203 203
204(defcustom flymake-start-on-save-buffer t
205 "If non-nil start syntax check when a buffer is saved.
206Specifically, start it when the saved buffer is actually displayed."
207 :version "27.1"
208 :type 'boolean)
209
204(defcustom flymake-log-level -1 210(defcustom flymake-log-level -1
205 "Obsolete and ignored variable." 211 "Obsolete and ignored variable."
206 :type 'integer) 212 :type 'integer)
@@ -962,7 +968,7 @@ Do it only if `flymake-no-changes-timeout' is non-nil."
962 (flymake--schedule-timer-maybe))) 968 (flymake--schedule-timer-maybe)))
963 969
964(defun flymake-after-save-hook () 970(defun flymake-after-save-hook ()
965 (when flymake-mode 971 (when flymake-start-on-save-buffer
966 (flymake-log :debug "starting syntax check as buffer was saved") 972 (flymake-log :debug "starting syntax check as buffer was saved")
967 (flymake-start t))) 973 (flymake-start t)))
968 974
diff --git a/src/.gdbinit b/src/.gdbinit
index 7a0cf02ea13..67dcf718e3c 100644
--- a/src/.gdbinit
+++ b/src/.gdbinit
@@ -1020,9 +1020,6 @@ define xpr
1020 if $misc == Lisp_Misc_Overlay 1020 if $misc == Lisp_Misc_Overlay
1021 xoverlay 1021 xoverlay
1022 end 1022 end
1023# if $misc == Lisp_Misc_Save_Value
1024# xsavevalue
1025# end
1026 end 1023 end
1027 if $type == Lisp_Vectorlike 1024 if $type == Lisp_Vectorlike
1028 set $size = ((struct Lisp_Vector *) $ptr)->header.size 1025 set $size = ((struct Lisp_Vector *) $ptr)->header.size
diff --git a/src/buffer.c b/src/buffer.c
index 14837372d34..244c1851fab 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -1696,7 +1696,7 @@ cleaning up all windows currently displaying the buffer to be killed. */)
1696 { 1696 {
1697 ptrdiff_t count = SPECPDL_INDEX (); 1697 ptrdiff_t count = SPECPDL_INDEX ();
1698 1698
1699 record_unwind_protect (save_excursion_restore, save_excursion_save ()); 1699 record_unwind_protect_excursion ();
1700 set_buffer_internal (b); 1700 set_buffer_internal (b);
1701 1701
1702 /* First run the query functions; if any query is answered no, 1702 /* First run the query functions; if any query is answered no,
diff --git a/src/bytecode.c b/src/bytecode.c
index 55b193ffb2f..772cc982f9a 100644
--- a/src/bytecode.c
+++ b/src/bytecode.c
@@ -739,8 +739,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
739 NEXT; 739 NEXT;
740 740
741 CASE (Bsave_excursion): 741 CASE (Bsave_excursion):
742 record_unwind_protect (save_excursion_restore, 742 record_unwind_protect_excursion ();
743 save_excursion_save ());
744 NEXT; 743 NEXT;
745 744
746 CASE (Bsave_current_buffer): /* Obsolete since ??. */ 745 CASE (Bsave_current_buffer): /* Obsolete since ??. */
diff --git a/src/dispextern.h b/src/dispextern.h
index bc2a76f1e02..2180c9ae63f 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -3429,11 +3429,12 @@ char *choose_face_font (struct frame *, Lisp_Object *, Lisp_Object,
3429#ifdef HAVE_WINDOW_SYSTEM 3429#ifdef HAVE_WINDOW_SYSTEM
3430void prepare_face_for_display (struct frame *, struct face *); 3430void prepare_face_for_display (struct frame *, struct face *);
3431#endif 3431#endif
3432int lookup_named_face (struct frame *, Lisp_Object, bool); 3432int lookup_named_face (struct window *, struct frame *, Lisp_Object, bool);
3433int lookup_basic_face (struct frame *, int); 3433int lookup_basic_face (struct window *, struct frame *, int);
3434int smaller_face (struct frame *, int, int); 3434int smaller_face (struct frame *, int, int);
3435int face_with_height (struct frame *, int, int); 3435int face_with_height (struct frame *, int, int);
3436int lookup_derived_face (struct frame *, Lisp_Object, int, bool); 3436int lookup_derived_face (struct window *, struct frame *,
3437 Lisp_Object, int, bool);
3437void init_frame_faces (struct frame *); 3438void init_frame_faces (struct frame *);
3438void free_frame_faces (struct frame *); 3439void free_frame_faces (struct frame *);
3439void recompute_basic_faces (struct frame *); 3440void recompute_basic_faces (struct frame *);
@@ -3443,7 +3444,7 @@ int face_for_overlay_string (struct window *, ptrdiff_t, ptrdiff_t *, ptrdiff_t,
3443 bool, Lisp_Object); 3444 bool, Lisp_Object);
3444int face_at_string_position (struct window *, Lisp_Object, ptrdiff_t, ptrdiff_t, 3445int face_at_string_position (struct window *, Lisp_Object, ptrdiff_t, ptrdiff_t,
3445 ptrdiff_t *, enum face_id, bool); 3446 ptrdiff_t *, enum face_id, bool);
3446int merge_faces (struct frame *, Lisp_Object, int, int); 3447int merge_faces (struct window *, Lisp_Object, int, int);
3447int compute_char_face (struct frame *, int, Lisp_Object); 3448int compute_char_face (struct frame *, int, Lisp_Object);
3448void free_all_realized_faces (Lisp_Object); 3449void free_all_realized_faces (Lisp_Object);
3449extern char unspecified_fg[], unspecified_bg[]; 3450extern char unspecified_fg[], unspecified_bg[];
diff --git a/src/dispnew.c b/src/dispnew.c
index b854d179d51..46e0c83ef6a 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -2508,8 +2508,7 @@ spec_glyph_lookup_face (struct window *w, GLYPH *glyph)
2508 /* Convert the glyph's specified face to a realized (cache) face. */ 2508 /* Convert the glyph's specified face to a realized (cache) face. */
2509 if (lface_id > 0) 2509 if (lface_id > 0)
2510 { 2510 {
2511 int face_id = merge_faces (XFRAME (w->frame), 2511 int face_id = merge_faces (w, Qt, lface_id, DEFAULT_FACE_ID);
2512 Qt, lface_id, DEFAULT_FACE_ID);
2513 SET_GLYPH_FACE (*glyph, face_id); 2512 SET_GLYPH_FACE (*glyph, face_id);
2514 } 2513 }
2515} 2514}
diff --git a/src/editfns.c b/src/editfns.c
index 608304c09ad..e672c0eb74d 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -1016,37 +1016,30 @@ save_excursion_save (void)
1016void 1016void
1017save_excursion_restore (Lisp_Object info) 1017save_excursion_restore (Lisp_Object info)
1018{ 1018{
1019 Lisp_Object tem, tem1; 1019 Lisp_Object marker = XSAVE_OBJECT (info, 0);
1020 1020 Lisp_Object window = XSAVE_OBJECT (info, 2);
1021 tem = Fmarker_buffer (XSAVE_OBJECT (info, 0)); 1021 free_misc (info);
1022 Lisp_Object buffer = Fmarker_buffer (marker);
1022 /* If we're unwinding to top level, saved buffer may be deleted. This 1023 /* If we're unwinding to top level, saved buffer may be deleted. This
1023 means that all of its markers are unchained and so tem is nil. */ 1024 means that all of its markers are unchained and so BUFFER is nil. */
1024 if (NILP (tem)) 1025 if (NILP (buffer))
1025 goto out; 1026 return;
1026 1027
1027 Fset_buffer (tem); 1028 Fset_buffer (buffer);
1028 1029
1029 /* Point marker. */ 1030 Fgoto_char (marker);
1030 tem = XSAVE_OBJECT (info, 0); 1031 unchain_marker (XMARKER (marker));
1031 Fgoto_char (tem);
1032 unchain_marker (XMARKER (tem));
1033 1032
1034 /* If buffer was visible in a window, and a different window was 1033 /* If buffer was visible in a window, and a different window was
1035 selected, and the old selected window is still showing this 1034 selected, and the old selected window is still showing this
1036 buffer, restore point in that window. */ 1035 buffer, restore point in that window. */
1037 tem = XSAVE_OBJECT (info, 2); 1036 if (WINDOWP (window) && !EQ (window, selected_window))
1038 if (WINDOWP (tem) 1037 {
1039 && !EQ (tem, selected_window) 1038 /* Set window point if WINDOW is live and shows the current buffer. */
1040 && (tem1 = XWINDOW (tem)->contents, 1039 Lisp_Object contents = XWINDOW (window)->contents;
1041 (/* Window is live... */ 1040 if (BUFFERP (contents) && XBUFFER (contents) == current_buffer)
1042 BUFFERP (tem1) 1041 Fset_window_point (window, make_number (PT));
1043 /* ...and it shows the current buffer. */ 1042 }
1044 && XBUFFER (tem1) == current_buffer)))
1045 Fset_window_point (tem, make_number (PT));
1046
1047 out:
1048
1049 free_misc (info);
1050} 1043}
1051 1044
1052DEFUN ("save-excursion", Fsave_excursion, Ssave_excursion, 0, UNEVALLED, 0, 1045DEFUN ("save-excursion", Fsave_excursion, Ssave_excursion, 0, UNEVALLED, 0,
@@ -1068,7 +1061,7 @@ usage: (save-excursion &rest BODY) */)
1068 register Lisp_Object val; 1061 register Lisp_Object val;
1069 ptrdiff_t count = SPECPDL_INDEX (); 1062 ptrdiff_t count = SPECPDL_INDEX ();
1070 1063
1071 record_unwind_protect (save_excursion_restore, save_excursion_save ()); 1064 record_unwind_protect_excursion ();
1072 1065
1073 val = Fprogn (args); 1066 val = Fprogn (args);
1074 return unbind_to (count, val); 1067 return unbind_to (count, val);
@@ -3242,7 +3235,7 @@ buffer stay intact. */)
3242 3235
3243 Fundo_boundary (); 3236 Fundo_boundary ();
3244 ptrdiff_t count = SPECPDL_INDEX (); 3237 ptrdiff_t count = SPECPDL_INDEX ();
3245 record_unwind_protect (save_excursion_restore, save_excursion_save ()); 3238 record_unwind_protect_excursion ();
3246 3239
3247 ptrdiff_t i = size_a; 3240 ptrdiff_t i = size_a;
3248 ptrdiff_t j = size_b; 3241 ptrdiff_t j = size_b;
diff --git a/src/eval.c b/src/eval.c
index 90d8c335185..86011a234c0 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -3415,6 +3415,12 @@ record_unwind_protect_int (void (*function) (int), int arg)
3415} 3415}
3416 3416
3417void 3417void
3418record_unwind_protect_excursion (void)
3419{
3420 record_unwind_protect (save_excursion_restore, save_excursion_save ());
3421}
3422
3423void
3418record_unwind_protect_void (void (*function) (void)) 3424record_unwind_protect_void (void (*function) (void))
3419{ 3425{
3420 specpdl_ptr->unwind_void.kind = SPECPDL_UNWIND_VOID; 3426 specpdl_ptr->unwind_void.kind = SPECPDL_UNWIND_VOID;
diff --git a/src/font.c b/src/font.c
index 305bb14576a..c886c299d19 100644
--- a/src/font.c
+++ b/src/font.c
@@ -3810,7 +3810,7 @@ font_range (ptrdiff_t pos, ptrdiff_t pos_byte, ptrdiff_t *limit,
3810 face_id = 3810 face_id =
3811 NILP (Vface_remapping_alist) 3811 NILP (Vface_remapping_alist)
3812 ? DEFAULT_FACE_ID 3812 ? DEFAULT_FACE_ID
3813 : lookup_basic_face (f, DEFAULT_FACE_ID); 3813 : lookup_basic_face (w, f, DEFAULT_FACE_ID);
3814 3814
3815 face_id = face_at_string_position (w, string, pos, 0, &ignore, 3815 face_id = face_at_string_position (w, string, pos, 0, &ignore,
3816 face_id, false); 3816 face_id, false);
@@ -4559,7 +4559,7 @@ DEFUN ("internal-char-font", Finternal_char_font, Sinternal_char_font, 1, 2, 0,
4559 CHECK_CHARACTER (ch); 4559 CHECK_CHARACTER (ch);
4560 c = XINT (ch); 4560 c = XINT (ch);
4561 f = XFRAME (selected_frame); 4561 f = XFRAME (selected_frame);
4562 face_id = lookup_basic_face (f, DEFAULT_FACE_ID); 4562 face_id = lookup_basic_face (NULL, f, DEFAULT_FACE_ID);
4563 pos = -1; 4563 pos = -1;
4564 } 4564 }
4565 else 4565 else
diff --git a/src/fringe.c b/src/fringe.c
index 85aa14da727..60691846814 100644
--- a/src/fringe.c
+++ b/src/fringe.c
@@ -587,8 +587,8 @@ draw_fringe_bitmap_1 (struct window *w, struct glyph_row *row, int left_p, int o
587 if (face_id == DEFAULT_FACE_ID) 587 if (face_id == DEFAULT_FACE_ID)
588 { 588 {
589 Lisp_Object face = fringe_faces[which]; 589 Lisp_Object face = fringe_faces[which];
590 face_id = NILP (face) ? lookup_named_face (f, Qfringe, false) 590 face_id = NILP (face) ? lookup_named_face (w, f, Qfringe, false)
591 : lookup_derived_face (f, face, FRINGE_FACE_ID, 0); 591 : lookup_derived_face (w, f, face, FRINGE_FACE_ID, 0);
592 if (face_id < 0) 592 if (face_id < 0)
593 face_id = FRINGE_FACE_ID; 593 face_id = FRINGE_FACE_ID;
594 } 594 }
@@ -1633,20 +1633,10 @@ If FACE is nil, reset face to default fringe face. */)
1633 if (!n) 1633 if (!n)
1634 error ("Undefined fringe bitmap"); 1634 error ("Undefined fringe bitmap");
1635 1635
1636 /* The purpose of the following code is to signal an error if FACE 1636 /* We used to check, as a convenience to callers, for basic face
1637 is not a face. This is for the caller's convenience only; the 1637 validity here, but since validity can depend on the specific
1638 redisplay code should be able to fail gracefully. Skip the check 1638 _window_ in which this buffer is being displayed, defer the check
1639 if FRINGE_FACE_ID is unrealized (as in batch mode and during 1639 to redisplay, which can cope with bad face specifications. */
1640 daemon startup). */
1641 if (!NILP (face))
1642 {
1643 struct frame *f = SELECTED_FRAME ();
1644
1645 if (FACE_FROM_ID_OR_NULL (f, FRINGE_FACE_ID)
1646 && lookup_derived_face (f, face, FRINGE_FACE_ID, 1) < 0)
1647 error ("No such face");
1648 }
1649
1650 fringe_faces[n] = face; 1640 fringe_faces[n] = face;
1651 return Qnil; 1641 return Qnil;
1652} 1642}
diff --git a/src/ftfont.c b/src/ftfont.c
index 9a8777ef078..a53467000f3 100644
--- a/src/ftfont.c
+++ b/src/ftfont.c
@@ -1131,16 +1131,19 @@ ftfont_open2 (struct frame *f,
1131 return Qnil; 1131 return Qnil;
1132 } 1132 }
1133 } 1133 }
1134 set_save_integer (val, 1, XSAVE_INTEGER (val, 1) + 1);
1135 size = XINT (AREF (entity, FONT_SIZE_INDEX)); 1134 size = XINT (AREF (entity, FONT_SIZE_INDEX));
1136 if (size == 0) 1135 if (size == 0)
1137 size = pixel_size; 1136 size = pixel_size;
1138 if (FT_Set_Pixel_Sizes (ft_face, size, size) != 0) 1137 if (FT_Set_Pixel_Sizes (ft_face, size, size) != 0)
1139 { 1138 {
1140 if (XSAVE_INTEGER (val, 1) == 0) 1139 if (XSAVE_INTEGER (val, 1) == 0)
1141 FT_Done_Face (ft_face); 1140 {
1141 FT_Done_Face (ft_face);
1142 cache_data->ft_face = NULL;
1143 }
1142 return Qnil; 1144 return Qnil;
1143 } 1145 }
1146 set_save_integer (val, 1, XSAVE_INTEGER (val, 1) + 1);
1144 1147
1145 ASET (font_object, FONT_FILE_INDEX, filename); 1148 ASET (font_object, FONT_FILE_INDEX, filename);
1146 font = XFONT_OBJECT (font_object); 1149 font = XFONT_OBJECT (font_object);
diff --git a/src/lisp.h b/src/lisp.h
index ee2e72d32b7..293cf2783c3 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -228,8 +228,8 @@ extern bool suppress_checking EXTERNALLY_VISIBLE;
228 228
229 USE_LSB_TAG not only requires the least 3 bits of pointers returned by 229 USE_LSB_TAG not only requires the least 3 bits of pointers returned by
230 malloc to be 0 but also needs to be able to impose a mult-of-8 alignment 230 malloc to be 0 but also needs to be able to impose a mult-of-8 alignment
231 on the few static Lisp_Objects used, all of which are aligned via 231 on some non-GC Lisp_Objects, all of which are aligned via
232 'char alignas (GCALIGNMENT) gcaligned;' inside a union. */ 232 GCALIGNED_UNION at the end of a union. */
233 233
234enum Lisp_Bits 234enum Lisp_Bits
235 { 235 {
@@ -277,6 +277,12 @@ DEFINE_GDB_SYMBOL_END (VALMASK)
277error !; 277error !;
278#endif 278#endif
279 279
280#if USE_LSB_TAG
281# define GCALIGNED_UNION char alignas (GCALIGNMENT) gcaligned;
282#else
283# define GCALIGNED_UNION
284#endif
285
280/* Lisp_Word is a scalar word suitable for holding a tagged pointer or 286/* Lisp_Word is a scalar word suitable for holding a tagged pointer or
281 integer. Usually it is a pointer to a deliberately-incomplete type 287 integer. Usually it is a pointer to a deliberately-incomplete type
282 'union Lisp_X'. However, it is EMACS_INT when Lisp_Objects and 288 'union Lisp_X'. However, it is EMACS_INT when Lisp_Objects and
@@ -776,10 +782,10 @@ struct Lisp_Symbol
776 /* Next symbol in obarray bucket, if the symbol is interned. */ 782 /* Next symbol in obarray bucket, if the symbol is interned. */
777 struct Lisp_Symbol *next; 783 struct Lisp_Symbol *next;
778 } s; 784 } s;
779 char alignas (GCALIGNMENT) gcaligned; 785 GCALIGNED_UNION
780 } u; 786 } u;
781}; 787};
782verify (alignof (struct Lisp_Symbol) % GCALIGNMENT == 0); 788verify (!USE_LSB_TAG || alignof (struct Lisp_Symbol) % GCALIGNMENT == 0);
783 789
784/* Declare a Lisp-callable function. The MAXARGS parameter has the same 790/* Declare a Lisp-callable function. The MAXARGS parameter has the same
785 meaning as in the DEFUN macro, and is used to construct a prototype. */ 791 meaning as in the DEFUN macro, and is used to construct a prototype. */
@@ -890,9 +896,9 @@ union vectorlike_header
890 Current layout limits the pseudovectors to 63 PVEC_xxx subtypes, 896 Current layout limits the pseudovectors to 63 PVEC_xxx subtypes,
891 4095 Lisp_Objects in GC-ed area and 4095 word-sized other slots. */ 897 4095 Lisp_Objects in GC-ed area and 4095 word-sized other slots. */
892 ptrdiff_t size; 898 ptrdiff_t size;
893 char alignas (GCALIGNMENT) gcaligned; 899 GCALIGNED_UNION
894 }; 900 };
895verify (alignof (union vectorlike_header) % GCALIGNMENT == 0); 901verify (!USE_LSB_TAG || alignof (union vectorlike_header) % GCALIGNMENT == 0);
896 902
897INLINE bool 903INLINE bool
898(SYMBOLP) (Lisp_Object x) 904(SYMBOLP) (Lisp_Object x)
@@ -1250,10 +1256,10 @@ struct Lisp_Cons
1250 struct Lisp_Cons *chain; 1256 struct Lisp_Cons *chain;
1251 } u; 1257 } u;
1252 } s; 1258 } s;
1253 char alignas (GCALIGNMENT) gcaligned; 1259 GCALIGNED_UNION
1254 } u; 1260 } u;
1255}; 1261};
1256verify (alignof (struct Lisp_Cons) % GCALIGNMENT == 0); 1262verify (!USE_LSB_TAG || alignof (struct Lisp_Cons) % GCALIGNMENT == 0);
1257 1263
1258INLINE bool 1264INLINE bool
1259(NILP) (Lisp_Object x) 1265(NILP) (Lisp_Object x)
@@ -1372,10 +1378,10 @@ struct Lisp_String
1372 unsigned char *data; 1378 unsigned char *data;
1373 } s; 1379 } s;
1374 struct Lisp_String *next; 1380 struct Lisp_String *next;
1375 char alignas (GCALIGNMENT) gcaligned; 1381 GCALIGNED_UNION
1376 } u; 1382 } u;
1377}; 1383};
1378verify (alignof (struct Lisp_String) % GCALIGNMENT == 0); 1384verify (!USE_LSB_TAG || alignof (struct Lisp_String) % GCALIGNMENT == 0);
1379 1385
1380INLINE bool 1386INLINE bool
1381STRINGP (Lisp_Object x) 1387STRINGP (Lisp_Object x)
@@ -3977,6 +3983,7 @@ extern void record_unwind_protect (void (*) (Lisp_Object), Lisp_Object);
3977extern void record_unwind_protect_ptr (void (*) (void *), void *); 3983extern void record_unwind_protect_ptr (void (*) (void *), void *);
3978extern void record_unwind_protect_int (void (*) (int), int); 3984extern void record_unwind_protect_int (void (*) (int), int);
3979extern void record_unwind_protect_void (void (*) (void)); 3985extern void record_unwind_protect_void (void (*) (void));
3986extern void record_unwind_protect_excursion (void);
3980extern void record_unwind_protect_nothing (void); 3987extern void record_unwind_protect_nothing (void);
3981extern void clear_unwind_protect (ptrdiff_t); 3988extern void clear_unwind_protect (ptrdiff_t);
3982extern void set_unwind_protect (ptrdiff_t, void (*) (Lisp_Object), Lisp_Object); 3989extern void set_unwind_protect (ptrdiff_t, void (*) (Lisp_Object), Lisp_Object);
@@ -4680,13 +4687,14 @@ extern void *record_xmalloc (size_t) ATTRIBUTE_ALLOC_SIZE ((1));
4680#define SAFE_ALLOCA_LISP(buf, nelt) SAFE_ALLOCA_LISP_EXTRA (buf, nelt, 0) 4687#define SAFE_ALLOCA_LISP(buf, nelt) SAFE_ALLOCA_LISP_EXTRA (buf, nelt, 0)
4681 4688
4682 4689
4683/* If USE_STACK_LISP_OBJECTS, define macros that and functions that allocate 4690/* If USE_STACK_LISP_OBJECTS, define macros and functions that
4684 block-scoped conses and strings. These objects are not 4691 allocate some Lisp objects on the C stack. As the storage is not
4685 managed by the garbage collector, so they are dangerous: passing them 4692 managed by the garbage collector, these objects are dangerous:
4686 out of their scope (e.g., to user code) results in undefined behavior. 4693 passing them to user code could result in undefined behavior if the
4687 Conversely, they have better performance because GC is not involved. 4694 objects are in use after the C function returns. Conversely, these
4695 objects have better performance because GC is not involved.
4688 4696
4689 This feature is experimental and requires careful debugging. 4697 While debugging you may want to disable allocation on the C stack.
4690 Build with CPPFLAGS='-DUSE_STACK_LISP_OBJECTS=0' to disable it. */ 4698 Build with CPPFLAGS='-DUSE_STACK_LISP_OBJECTS=0' to disable it. */
4691 4699
4692#if (!defined USE_STACK_LISP_OBJECTS \ 4700#if (!defined USE_STACK_LISP_OBJECTS \
@@ -4751,7 +4759,8 @@ enum
4751 Take its unibyte value from the null-terminated string STR, 4759 Take its unibyte value from the null-terminated string STR,
4752 an expression that should not have side effects. 4760 an expression that should not have side effects.
4753 STR's value is not necessarily copied. The resulting Lisp string 4761 STR's value is not necessarily copied. The resulting Lisp string
4754 should not be modified or made visible to user code. */ 4762 should not be modified or given text properties or made visible to
4763 user code. */
4755 4764
4756#define AUTO_STRING(name, str) \ 4765#define AUTO_STRING(name, str) \
4757 AUTO_STRING_WITH_LEN (name, str, strlen (str)) 4766 AUTO_STRING_WITH_LEN (name, str, strlen (str))
@@ -4760,7 +4769,8 @@ enum
4760 Take its unibyte value from the null-terminated string STR with length LEN. 4769 Take its unibyte value from the null-terminated string STR with length LEN.
4761 STR may have side effects and may contain null bytes. 4770 STR may have side effects and may contain null bytes.
4762 STR's value is not necessarily copied. The resulting Lisp string 4771 STR's value is not necessarily copied. The resulting Lisp string
4763 should not be modified or made visible to user code. */ 4772 should not be modified or given text properties or made visible to
4773 user code. */
4764 4774
4765#define AUTO_STRING_WITH_LEN(name, str, len) \ 4775#define AUTO_STRING_WITH_LEN(name, str, len) \
4766 Lisp_Object name = \ 4776 Lisp_Object name = \
diff --git a/src/lread.c b/src/lread.c
index 239c66ccb85..d2c7eae20f9 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -1976,11 +1976,11 @@ readevalloop (Lisp_Object readcharfun,
1976 if (!NILP (start)) 1976 if (!NILP (start))
1977 { 1977 {
1978 /* Switch to the buffer we are reading from. */ 1978 /* Switch to the buffer we are reading from. */
1979 record_unwind_protect (save_excursion_restore, save_excursion_save ()); 1979 record_unwind_protect_excursion ();
1980 set_buffer_internal (b); 1980 set_buffer_internal (b);
1981 1981
1982 /* Save point in it. */ 1982 /* Save point in it. */
1983 record_unwind_protect (save_excursion_restore, save_excursion_save ()); 1983 record_unwind_protect_excursion ();
1984 /* Save ZV in it. */ 1984 /* Save ZV in it. */
1985 record_unwind_protect (save_restriction_restore, save_restriction_save ()); 1985 record_unwind_protect (save_restriction_restore, save_restriction_save ());
1986 /* Those get unbound after we read one expression. */ 1986 /* Those get unbound after we read one expression. */
@@ -2137,7 +2137,7 @@ This function preserves the position of point. */)
2137 2137
2138 specbind (Qeval_buffer_list, Fcons (buf, Veval_buffer_list)); 2138 specbind (Qeval_buffer_list, Fcons (buf, Veval_buffer_list));
2139 specbind (Qstandard_output, tem); 2139 specbind (Qstandard_output, tem);
2140 record_unwind_protect (save_excursion_restore, save_excursion_save ()); 2140 record_unwind_protect_excursion ();
2141 BUF_TEMP_SET_PT (XBUFFER (buf), BUF_BEGV (XBUFFER (buf))); 2141 BUF_TEMP_SET_PT (XBUFFER (buf), BUF_BEGV (XBUFFER (buf)));
2142 specbind (Qlexical_binding, lisp_file_lexically_bound_p (buf) ? Qt : Qnil); 2142 specbind (Qlexical_binding, lisp_file_lexically_bound_p (buf) ? Qt : Qnil);
2143 BUF_TEMP_SET_PT (XBUFFER (buf), BUF_BEGV (XBUFFER (buf))); 2143 BUF_TEMP_SET_PT (XBUFFER (buf), BUF_BEGV (XBUFFER (buf)));
diff --git a/src/msdos.c b/src/msdos.c
index eedbf7b1a6c..6c0dfa0c46a 100644
--- a/src/msdos.c
+++ b/src/msdos.c
@@ -3063,15 +3063,15 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx,
3063 state = alloca (menu->panecount * sizeof (struct IT_menu_state)); 3063 state = alloca (menu->panecount * sizeof (struct IT_menu_state));
3064 screensize = screen_size * 2; 3064 screensize = screen_size * 2;
3065 faces[0] 3065 faces[0]
3066 = lookup_derived_face (sf, intern ("msdos-menu-passive-face"), 3066 = lookup_derived_face (NULL, sf, intern ("msdos-menu-passive-face"),
3067 DEFAULT_FACE_ID, 1); 3067 DEFAULT_FACE_ID, 1);
3068 faces[1] 3068 faces[1]
3069 = lookup_derived_face (sf, intern ("msdos-menu-active-face"), 3069 = lookup_derived_face (NULL, sf, intern ("msdos-menu-active-face"),
3070 DEFAULT_FACE_ID, 1); 3070 DEFAULT_FACE_ID, 1);
3071 selectface = intern ("msdos-menu-select-face"); 3071 selectface = intern ("msdos-menu-select-face");
3072 faces[2] = lookup_derived_face (sf, selectface, 3072 faces[2] = lookup_derived_face (NULL, sf, selectface,
3073 faces[0], 1); 3073 faces[0], 1);
3074 faces[3] = lookup_derived_face (sf, selectface, 3074 faces[3] = lookup_derived_face (NULL, sf, selectface,
3075 faces[1], 1); 3075 faces[1], 1);
3076 3076
3077 /* Make sure the menu title is always displayed with 3077 /* Make sure the menu title is always displayed with
diff --git a/src/term.c b/src/term.c
index 08d483f4fa0..bcd7dd82d6f 100644
--- a/src/term.c
+++ b/src/term.c
@@ -3132,15 +3132,15 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
3132 SAFE_NALLOCA (state, 1, menu->panecount); 3132 SAFE_NALLOCA (state, 1, menu->panecount);
3133 memset (state, 0, sizeof (*state)); 3133 memset (state, 0, sizeof (*state));
3134 faces[0] 3134 faces[0]
3135 = lookup_derived_face (sf, intern ("tty-menu-disabled-face"), 3135 = lookup_derived_face (NULL, sf, intern ("tty-menu-disabled-face"),
3136 DEFAULT_FACE_ID, 1); 3136 DEFAULT_FACE_ID, 1);
3137 faces[1] 3137 faces[1]
3138 = lookup_derived_face (sf, intern ("tty-menu-enabled-face"), 3138 = lookup_derived_face (NULL, sf, intern ("tty-menu-enabled-face"),
3139 DEFAULT_FACE_ID, 1); 3139 DEFAULT_FACE_ID, 1);
3140 selectface = intern ("tty-menu-selected-face"); 3140 selectface = intern ("tty-menu-selected-face");
3141 faces[2] = lookup_derived_face (sf, selectface, 3141 faces[2] = lookup_derived_face (NULL, sf, selectface,
3142 faces[0], 1); 3142 faces[0], 1);
3143 faces[3] = lookup_derived_face (sf, selectface, 3143 faces[3] = lookup_derived_face (NULL, sf, selectface,
3144 faces[1], 1); 3144 faces[1], 1);
3145 3145
3146 /* Make sure the menu title is always displayed with 3146 /* Make sure the menu title is always displayed with
diff --git a/src/window.c b/src/window.c
index f654d87e14a..2c6ff01ea43 100644
--- a/src/window.c
+++ b/src/window.c
@@ -5656,7 +5656,7 @@ scroll_command (Lisp_Object window, Lisp_Object n, int direction)
5656 the moment. But don't screw up if window_scroll gets an error. */ 5656 the moment. But don't screw up if window_scroll gets an error. */
5657 if (XBUFFER (w->contents) != current_buffer) 5657 if (XBUFFER (w->contents) != current_buffer)
5658 { 5658 {
5659 record_unwind_protect (save_excursion_restore, save_excursion_save ()); 5659 record_unwind_protect_excursion ();
5660 Fset_buffer (w->contents); 5660 Fset_buffer (w->contents);
5661 } 5661 }
5662 5662
diff --git a/src/xdisp.c b/src/xdisp.c
index ad1c044557d..a2b6513e571 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -2809,7 +2809,7 @@ init_iterator (struct it *it, struct window *w,
2809 /* Perhaps remap BASE_FACE_ID to a user-specified alternative. */ 2809 /* Perhaps remap BASE_FACE_ID to a user-specified alternative. */
2810 if (! NILP (Vface_remapping_alist)) 2810 if (! NILP (Vface_remapping_alist))
2811 remapped_base_face_id 2811 remapped_base_face_id
2812 = lookup_basic_face (XFRAME (w->frame), base_face_id); 2812 = lookup_basic_face (w, XFRAME (w->frame), base_face_id);
2813 2813
2814 /* Use one of the mode line rows of W's desired matrix if 2814 /* Use one of the mode line rows of W's desired matrix if
2815 appropriate. */ 2815 appropriate. */
@@ -4060,7 +4060,7 @@ handle_face_prop (struct it *it)
4060 might be a big deal. */ 4060 might be a big deal. */
4061 base_face_id = it->string_from_prefix_prop_p 4061 base_face_id = it->string_from_prefix_prop_p
4062 ? (!NILP (Vface_remapping_alist) 4062 ? (!NILP (Vface_remapping_alist)
4063 ? lookup_basic_face (it->f, DEFAULT_FACE_ID) 4063 ? lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID)
4064 : DEFAULT_FACE_ID) 4064 : DEFAULT_FACE_ID)
4065 : underlying_face_id (it); 4065 : underlying_face_id (it);
4066 } 4066 }
@@ -4988,7 +4988,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
4988 struct face *f; 4988 struct face *f;
4989 4989
4990 f = FACE_FROM_ID (it->f, 4990 f = FACE_FROM_ID (it->f,
4991 lookup_basic_face (it->f, DEFAULT_FACE_ID)); 4991 lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID));
4992 new_height = (XFLOATINT (it->font_height) 4992 new_height = (XFLOATINT (it->font_height)
4993 * XINT (f->lface[LFACE_HEIGHT_INDEX])); 4993 * XINT (f->lface[LFACE_HEIGHT_INDEX]));
4994 } 4994 }
@@ -5175,12 +5175,12 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
5175 5175
5176 if (it) 5176 if (it)
5177 { 5177 {
5178 int face_id = lookup_basic_face (it->f, DEFAULT_FACE_ID); 5178 int face_id = lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID);
5179 5179
5180 if (CONSP (XCDR (XCDR (spec)))) 5180 if (CONSP (XCDR (XCDR (spec))))
5181 { 5181 {
5182 Lisp_Object face_name = XCAR (XCDR (XCDR (spec))); 5182 Lisp_Object face_name = XCAR (XCDR (XCDR (spec)));
5183 int face_id2 = lookup_derived_face (it->f, face_name, 5183 int face_id2 = lookup_derived_face (it->w, it->f, face_name,
5184 FRINGE_FACE_ID, false); 5184 FRINGE_FACE_ID, false);
5185 if (face_id2 >= 0) 5185 if (face_id2 >= 0)
5186 face_id = face_id2; 5186 face_id = face_id2;
@@ -6985,7 +6985,7 @@ merge_escape_glyph_face (struct it *it)
6985 else 6985 else
6986 { 6986 {
6987 /* Merge the `escape-glyph' face into the current face. */ 6987 /* Merge the `escape-glyph' face into the current face. */
6988 face_id = merge_faces (it->f, Qescape_glyph, 0, it->face_id); 6988 face_id = merge_faces (it->w, Qescape_glyph, 0, it->face_id);
6989 last_escape_glyph_frame = it->f; 6989 last_escape_glyph_frame = it->f;
6990 last_escape_glyph_face_id = it->face_id; 6990 last_escape_glyph_face_id = it->face_id;
6991 last_escape_glyph_merged_face_id = face_id; 6991 last_escape_glyph_merged_face_id = face_id;
@@ -7010,7 +7010,7 @@ merge_glyphless_glyph_face (struct it *it)
7010 else 7010 else
7011 { 7011 {
7012 /* Merge the `glyphless-char' face into the current face. */ 7012 /* Merge the `glyphless-char' face into the current face. */
7013 face_id = merge_faces (it->f, Qglyphless_char, 0, it->face_id); 7013 face_id = merge_faces (it->w, Qglyphless_char, 0, it->face_id);
7014 last_glyphless_glyph_frame = it->f; 7014 last_glyphless_glyph_frame = it->f;
7015 last_glyphless_glyph_face_id = it->face_id; 7015 last_glyphless_glyph_face_id = it->face_id;
7016 last_glyphless_glyph_merged_face_id = face_id; 7016 last_glyphless_glyph_merged_face_id = face_id;
@@ -7184,7 +7184,7 @@ get_next_display_element (struct it *it)
7184 } 7184 }
7185 7185
7186 face_id = (lface_id 7186 face_id = (lface_id
7187 ? merge_faces (it->f, Qt, lface_id, it->face_id) 7187 ? merge_faces (it->w, Qt, lface_id, it->face_id)
7188 : merge_escape_glyph_face (it)); 7188 : merge_escape_glyph_face (it));
7189 7189
7190 XSETINT (it->ctl_chars[0], g); 7190 XSETINT (it->ctl_chars[0], g);
@@ -7199,7 +7199,7 @@ get_next_display_element (struct it *it)
7199 if (nonascii_space_p && EQ (Vnobreak_char_display, Qt)) 7199 if (nonascii_space_p && EQ (Vnobreak_char_display, Qt))
7200 { 7200 {
7201 /* Merge `nobreak-space' into the current face. */ 7201 /* Merge `nobreak-space' into the current face. */
7202 face_id = merge_faces (it->f, Qnobreak_space, 0, 7202 face_id = merge_faces (it->w, Qnobreak_space, 0,
7203 it->face_id); 7203 it->face_id);
7204 XSETINT (it->ctl_chars[0], ' '); 7204 XSETINT (it->ctl_chars[0], ' ');
7205 ctl_len = 1; 7205 ctl_len = 1;
@@ -7212,7 +7212,7 @@ get_next_display_element (struct it *it)
7212 if (nonascii_hyphen_p && EQ (Vnobreak_char_display, Qt)) 7212 if (nonascii_hyphen_p && EQ (Vnobreak_char_display, Qt))
7213 { 7213 {
7214 /* Merge `nobreak-space' into the current face. */ 7214 /* Merge `nobreak-space' into the current face. */
7215 face_id = merge_faces (it->f, Qnobreak_hyphen, 0, 7215 face_id = merge_faces (it->w, Qnobreak_hyphen, 0,
7216 it->face_id); 7216 it->face_id);
7217 XSETINT (it->ctl_chars[0], '-'); 7217 XSETINT (it->ctl_chars[0], '-');
7218 ctl_len = 1; 7218 ctl_len = 1;
@@ -7232,7 +7232,7 @@ get_next_display_element (struct it *it)
7232 } 7232 }
7233 7233
7234 face_id = (lface_id 7234 face_id = (lface_id
7235 ? merge_faces (it->f, Qt, lface_id, it->face_id) 7235 ? merge_faces (it->w, Qt, lface_id, it->face_id)
7236 : merge_escape_glyph_face (it)); 7236 : merge_escape_glyph_face (it));
7237 7237
7238 /* Draw non-ASCII space/hyphen with escape glyph: */ 7238 /* Draw non-ASCII space/hyphen with escape glyph: */
@@ -7860,7 +7860,7 @@ next_element_from_display_vector (struct it *it)
7860 { 7860 {
7861 int lface_id = GLYPH_CODE_FACE (gc); 7861 int lface_id = GLYPH_CODE_FACE (gc);
7862 if (lface_id > 0) 7862 if (lface_id > 0)
7863 it->face_id = merge_faces (it->f, Qt, lface_id, 7863 it->face_id = merge_faces (it->w, Qt, lface_id,
7864 it->saved_face_id); 7864 it->saved_face_id);
7865 } 7865 }
7866 7866
@@ -7889,7 +7889,7 @@ next_element_from_display_vector (struct it *it)
7889 GLYPH_CODE_FACE (it->dpvec[it->current.dpvec_index + 1]); 7889 GLYPH_CODE_FACE (it->dpvec[it->current.dpvec_index + 1]);
7890 7890
7891 if (lface_id > 0) 7891 if (lface_id > 0)
7892 next_face_id = merge_faces (it->f, Qt, lface_id, 7892 next_face_id = merge_faces (it->w, Qt, lface_id,
7893 it->saved_face_id); 7893 it->saved_face_id);
7894 } 7894 }
7895 } 7895 }
@@ -20084,7 +20084,7 @@ append_space_for_newline (struct it *it, bool default_face_p)
20084 /* If the default face was remapped, be sure to use the 20084 /* If the default face was remapped, be sure to use the
20085 remapped face for the appended newline. */ 20085 remapped face for the appended newline. */
20086 if (default_face_p) 20086 if (default_face_p)
20087 it->face_id = lookup_basic_face (it->f, DEFAULT_FACE_ID); 20087 it->face_id = lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID);
20088 else if (it->face_before_selective_p) 20088 else if (it->face_before_selective_p)
20089 it->face_id = it->saved_face_id; 20089 it->face_id = it->saved_face_id;
20090 face = FACE_FROM_ID (it->f, it->face_id); 20090 face = FACE_FROM_ID (it->f, it->face_id);
@@ -20231,8 +20231,9 @@ extend_face_to_end_of_line (struct it *it)
20231 return; 20231 return;
20232 20232
20233 /* The default face, possibly remapped. */ 20233 /* The default face, possibly remapped. */
20234 default_face = FACE_FROM_ID_OR_NULL (f, 20234 default_face = FACE_FROM_ID_OR_NULL (
20235 lookup_basic_face (f, DEFAULT_FACE_ID)); 20235 f,
20236 lookup_basic_face (it->w, f, DEFAULT_FACE_ID));
20236 20237
20237 /* Face extension extends the background and box of IT->face_id 20238 /* Face extension extends the background and box of IT->face_id
20238 to the end of the line. If the background equals the background 20239 to the end of the line. If the background equals the background
@@ -20486,11 +20487,12 @@ trailing_whitespace_p (ptrdiff_t charpos)
20486} 20487}
20487 20488
20488 20489
20489/* Highlight trailing whitespace, if any, in ROW. */ 20490/* Highlight trailing whitespace, if any, in row at IT. */
20490 20491
20491static void 20492static void
20492highlight_trailing_whitespace (struct frame *f, struct glyph_row *row) 20493highlight_trailing_whitespace (struct it *it)
20493{ 20494{
20495 struct glyph_row *row = it->glyph_row;
20494 int used = row->used[TEXT_AREA]; 20496 int used = row->used[TEXT_AREA];
20495 20497
20496 if (used) 20498 if (used)
@@ -20535,7 +20537,7 @@ highlight_trailing_whitespace (struct frame *f, struct glyph_row *row)
20535 && glyph->u.ch == ' ')) 20537 && glyph->u.ch == ' '))
20536 && trailing_whitespace_p (glyph->charpos)) 20538 && trailing_whitespace_p (glyph->charpos))
20537 { 20539 {
20538 int face_id = lookup_named_face (f, Qtrailing_whitespace, false); 20540 int face_id = lookup_named_face (it->w, it->f, Qtrailing_whitespace, false);
20539 if (face_id < 0) 20541 if (face_id < 0)
20540 return; 20542 return;
20541 20543
@@ -21107,9 +21109,9 @@ maybe_produce_line_number (struct it *it)
21107 char lnum_buf[INT_STRLEN_BOUND (ptrdiff_t) + 1]; 21109 char lnum_buf[INT_STRLEN_BOUND (ptrdiff_t) + 1];
21108 bool beyond_zv = IT_BYTEPOS (*it) >= ZV_BYTE ? true : false; 21110 bool beyond_zv = IT_BYTEPOS (*it) >= ZV_BYTE ? true : false;
21109 ptrdiff_t lnum_offset = -1; /* to produce 1-based line numbers */ 21111 ptrdiff_t lnum_offset = -1; /* to produce 1-based line numbers */
21110 int lnum_face_id = merge_faces (it->f, Qline_number, 0, DEFAULT_FACE_ID); 21112 int lnum_face_id = merge_faces (it->w, Qline_number, 0, DEFAULT_FACE_ID);
21111 int current_lnum_face_id 21113 int current_lnum_face_id
21112 = merge_faces (it->f, Qline_number_current_line, 0, DEFAULT_FACE_ID); 21114 = merge_faces (it->w, Qline_number_current_line, 0, DEFAULT_FACE_ID);
21113 /* Compute point's line number if needed. */ 21115 /* Compute point's line number if needed. */
21114 if ((EQ (Vdisplay_line_numbers, Qrelative) 21116 if ((EQ (Vdisplay_line_numbers, Qrelative)
21115 || EQ (Vdisplay_line_numbers, Qvisual) 21117 || EQ (Vdisplay_line_numbers, Qvisual)
@@ -21559,7 +21561,8 @@ display_line (struct it *it, int cursor_vpos)
21559 portions of the screen will clear with the default face's 21561 portions of the screen will clear with the default face's
21560 background color. */ 21562 background color. */
21561 if (row->reversed_p 21563 if (row->reversed_p
21562 || lookup_basic_face (it->f, DEFAULT_FACE_ID) != DEFAULT_FACE_ID) 21564 || lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID)
21565 != DEFAULT_FACE_ID)
21563 extend_face_to_end_of_line (it); 21566 extend_face_to_end_of_line (it);
21564 break; 21567 break;
21565 } 21568 }
@@ -22192,7 +22195,7 @@ display_line (struct it *it, int cursor_vpos)
22192 22195
22193 /* Highlight trailing whitespace. */ 22196 /* Highlight trailing whitespace. */
22194 if (!NILP (Vshow_trailing_whitespace)) 22197 if (!NILP (Vshow_trailing_whitespace))
22195 highlight_trailing_whitespace (it->f, it->glyph_row); 22198 highlight_trailing_whitespace (it);
22196 22199
22197 /* Compute pixel dimensions of this line. */ 22200 /* Compute pixel dimensions of this line. */
22198 compute_line_metrics (it); 22201 compute_line_metrics (it);
@@ -27862,7 +27865,7 @@ calc_line_height_property (struct it *it, Lisp_Object val, struct font *font,
27862 int face_id; 27865 int face_id;
27863 struct face *face; 27866 struct face *face;
27864 27867
27865 face_id = lookup_named_face (it->f, face_name, false); 27868 face_id = lookup_named_face (it->w, it->f, face_name, false);
27866 face = FACE_FROM_ID_OR_NULL (it->f, face_id); 27869 face = FACE_FROM_ID_OR_NULL (it->f, face_id);
27867 if (face == NULL || ((font = face->font) == NULL)) 27870 if (face == NULL || ((font = face->font) == NULL))
27868 return make_number (-1); 27871 return make_number (-1);
diff --git a/src/xfaces.c b/src/xfaces.c
index a9c2f37e9f2..961bef7c9ce 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -350,7 +350,8 @@ static bool realize_default_face (struct frame *);
350static void realize_named_face (struct frame *, Lisp_Object, int); 350static void realize_named_face (struct frame *, Lisp_Object, int);
351static struct face_cache *make_face_cache (struct frame *); 351static struct face_cache *make_face_cache (struct frame *);
352static void free_face_cache (struct face_cache *); 352static void free_face_cache (struct face_cache *);
353static bool merge_face_ref (struct frame *, Lisp_Object, Lisp_Object *, 353static bool merge_face_ref (struct window *w,
354 struct frame *, Lisp_Object, Lisp_Object *,
354 bool, struct named_merge_point *); 355 bool, struct named_merge_point *);
355static int color_distance (XColor *x, XColor *y); 356static int color_distance (XColor *x, XColor *y);
356 357
@@ -1551,7 +1552,7 @@ the WIDTH times as wide as FACE on FRAME. */)
1551 { 1552 {
1552 /* This is of limited utility since it works with character 1553 /* This is of limited utility since it works with character
1553 widths. Keep it for compatibility. --gerd. */ 1554 widths. Keep it for compatibility. --gerd. */
1554 int face_id = lookup_named_face (f, face, false); 1555 int face_id = lookup_named_face (NULL, f, face, false);
1555 struct face *width_face = FACE_FROM_ID_OR_NULL (f, face_id); 1556 struct face *width_face = FACE_FROM_ID_OR_NULL (f, face_id);
1556 1557
1557 if (width_face && width_face->font) 1558 if (width_face && width_face->font)
@@ -1907,19 +1908,22 @@ get_lface_attributes_no_remap (struct frame *f, Lisp_Object face_name,
1907 return !NILP (lface); 1908 return !NILP (lface);
1908} 1909}
1909 1910
1910/* Get face attributes of face FACE_NAME from frame-local faces on frame 1911/* Get face attributes of face FACE_NAME from frame-local faces on
1911 F. Store the resulting attributes in ATTRS which must point to a 1912 frame F. Store the resulting attributes in ATTRS which must point
1912 vector of Lisp_Objects of size LFACE_VECTOR_SIZE. If FACE_NAME is an 1913 to a vector of Lisp_Objects of size LFACE_VECTOR_SIZE.
1913 alias for another face, use that face's definition. 1914 If FACE_NAME is an alias for another face, use that face's
1914 If SIGNAL_P, signal an error if FACE_NAME does not name a face. 1915 definition. If SIGNAL_P, signal an error if FACE_NAME does not
1915 Otherwise, return true iff FACE_NAME is a face. */ 1916 name a face. Otherwise, return true iff FACE_NAME is a face. If W
1916 1917 is non-NULL, also consider remappings attached to the window.
1918 */
1917static bool 1919static bool
1918get_lface_attributes (struct frame *f, Lisp_Object face_name, 1920get_lface_attributes (struct window *w,
1921 struct frame *f, Lisp_Object face_name,
1919 Lisp_Object attrs[LFACE_VECTOR_SIZE], bool signal_p, 1922 Lisp_Object attrs[LFACE_VECTOR_SIZE], bool signal_p,
1920 struct named_merge_point *named_merge_points) 1923 struct named_merge_point *named_merge_points)
1921{ 1924{
1922 Lisp_Object face_remapping; 1925 Lisp_Object face_remapping;
1926 eassert (w == NULL || WINDOW_XFRAME (w) == f);
1923 1927
1924 face_name = resolve_face_name (face_name, signal_p); 1928 face_name = resolve_face_name (face_name, signal_p);
1925 1929
@@ -1939,7 +1943,7 @@ get_lface_attributes (struct frame *f, Lisp_Object face_name,
1939 for (i = 1; i < LFACE_VECTOR_SIZE; ++i) 1943 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
1940 attrs[i] = Qunspecified; 1944 attrs[i] = Qunspecified;
1941 1945
1942 return merge_face_ref (f, XCDR (face_remapping), attrs, 1946 return merge_face_ref (w, f, XCDR (face_remapping), attrs,
1943 signal_p, named_merge_points); 1947 signal_p, named_merge_points);
1944 } 1948 }
1945 } 1949 }
@@ -2072,15 +2076,16 @@ merge_face_heights (Lisp_Object from, Lisp_Object to, Lisp_Object invalid)
2072 2076
2073/* Merge two Lisp face attribute vectors on frame F, FROM and TO, and 2077/* Merge two Lisp face attribute vectors on frame F, FROM and TO, and
2074 store the resulting attributes in TO, which must be already be 2078 store the resulting attributes in TO, which must be already be
2075 completely specified and contain only absolute attributes. Every 2079 completely specified and contain only absolute attributes.
2076 specified attribute of FROM overrides the corresponding attribute of 2080 Every specified attribute of FROM overrides the corresponding
2077 TO; relative attributes in FROM are merged with the absolute value in 2081 attribute of TO; relative attributes in FROM are merged with the
2078 TO and replace it. NAMED_MERGE_POINTS is used internally to detect 2082 absolute value in TO and replace it. NAMED_MERGE_POINTS is used
2079 loops in face inheritance/remapping; it should be 0 when called from 2083 internally to detect loops in face inheritance/remapping; it should
2080 other places. */ 2084 be 0 when called from other places. If window W is non-NULL, use W
2081 2085 to interpret face specifications. */
2082static void 2086static void
2083merge_face_vectors (struct frame *f, Lisp_Object *from, Lisp_Object *to, 2087merge_face_vectors (struct window *w,
2088 struct frame *f, Lisp_Object *from, Lisp_Object *to,
2084 struct named_merge_point *named_merge_points) 2089 struct named_merge_point *named_merge_points)
2085{ 2090{
2086 int i; 2091 int i;
@@ -2093,7 +2098,8 @@ merge_face_vectors (struct frame *f, Lisp_Object *from, Lisp_Object *to,
2093 other code uses `unspecified' as a generic value for face attributes. */ 2098 other code uses `unspecified' as a generic value for face attributes. */
2094 if (!UNSPECIFIEDP (from[LFACE_INHERIT_INDEX]) 2099 if (!UNSPECIFIEDP (from[LFACE_INHERIT_INDEX])
2095 && !NILP (from[LFACE_INHERIT_INDEX])) 2100 && !NILP (from[LFACE_INHERIT_INDEX]))
2096 merge_face_ref (f, from[LFACE_INHERIT_INDEX], to, false, named_merge_points); 2101 merge_face_ref (w, f, from[LFACE_INHERIT_INDEX],
2102 to, false, named_merge_points);
2097 2103
2098 if (FONT_SPEC_P (from[LFACE_FONT_INDEX])) 2104 if (FONT_SPEC_P (from[LFACE_FONT_INDEX]))
2099 { 2105 {
@@ -2153,10 +2159,12 @@ merge_face_vectors (struct frame *f, Lisp_Object *from, Lisp_Object *to,
2153/* Merge the named face FACE_NAME on frame F, into the vector of face 2159/* Merge the named face FACE_NAME on frame F, into the vector of face
2154 attributes TO. Use NAMED_MERGE_POINTS to detect loops in face 2160 attributes TO. Use NAMED_MERGE_POINTS to detect loops in face
2155 inheritance. Return true if FACE_NAME is a valid face name and 2161 inheritance. Return true if FACE_NAME is a valid face name and
2156 merging succeeded. */ 2162 merging succeeded. Window W, if non-NULL, is used to filter face
2163 specifications. */
2157 2164
2158static bool 2165static bool
2159merge_named_face (struct frame *f, Lisp_Object face_name, Lisp_Object *to, 2166merge_named_face (struct window *w,
2167 struct frame *f, Lisp_Object face_name, Lisp_Object *to,
2160 struct named_merge_point *named_merge_points) 2168 struct named_merge_point *named_merge_points)
2161{ 2169{
2162 struct named_merge_point named_merge_point; 2170 struct named_merge_point named_merge_point;
@@ -2166,11 +2174,11 @@ merge_named_face (struct frame *f, Lisp_Object face_name, Lisp_Object *to,
2166 &named_merge_points)) 2174 &named_merge_points))
2167 { 2175 {
2168 Lisp_Object from[LFACE_VECTOR_SIZE]; 2176 Lisp_Object from[LFACE_VECTOR_SIZE];
2169 bool ok = get_lface_attributes (f, face_name, from, false, 2177 bool ok = get_lface_attributes (w, f, face_name, from, false,
2170 named_merge_points); 2178 named_merge_points);
2171 2179
2172 if (ok) 2180 if (ok)
2173 merge_face_vectors (f, from, to, named_merge_points); 2181 merge_face_vectors (w, f, from, to, named_merge_points);
2174 2182
2175 return ok; 2183 return ok;
2176 } 2184 }
@@ -2178,6 +2186,111 @@ merge_named_face (struct frame *f, Lisp_Object face_name, Lisp_Object *to,
2178 return false; 2186 return false;
2179} 2187}
2180 2188
2189/* Determine whether the face filter FILTER evaluated in window W
2190 matches. W can be NULL if the window context is unknown.
2191
2192 A face filter is either nil, which always matches, or a list
2193 (:window PARAMETER VALUE), which matches if the current window has
2194 a PARAMETER EQ to VALUE.
2195
2196 If the filter is invalid, set *OK to false and, if ERR_MSGS is
2197 true, log an error message. */
2198static bool
2199evaluate_face_filter (Lisp_Object filter, struct window *w,
2200 bool *ok, bool err_msgs)
2201{
2202 Lisp_Object orig_filter = filter;
2203
2204 {
2205 if (NILP (filter))
2206 return true;
2207
2208 if (face_filters_always_match)
2209 return true;
2210
2211 if (!CONSP (filter))
2212 goto err;
2213
2214 if (!EQ (XCAR (filter), Qwindow_kw))
2215 goto err;
2216 filter = XCDR (filter);
2217
2218 Lisp_Object parameter = XCAR (filter);
2219 filter = XCDR (filter);
2220 if (!CONSP (filter))
2221 goto err;
2222
2223 Lisp_Object value = XCAR (filter);
2224 filter = XCDR (filter);
2225 if (!NILP (filter))
2226 goto err;
2227
2228 bool match = false;
2229 if (w) {
2230 Lisp_Object found = assq_no_quit (parameter, w->window_parameters);
2231 if (!NILP (found) && EQ (XCDR (found), value))
2232 match = true;
2233 }
2234
2235 return match;
2236 }
2237
2238 err:
2239 if (err_msgs)
2240 add_to_log ("Invalid face filter %S", orig_filter);
2241 *ok = false;
2242 return false;
2243}
2244
2245/* Determine whether FACE_REF is a "filter" face specification (case
2246 #4 in merge_face_ref). If it is, evaluate the filter, and if the
2247 filter matches, return the filtered expression. Otherwise, return
2248 the original expression.
2249
2250 On error, set *OK to false, having logged an error message if
2251 ERR_MSGS is true, with return value unspecified.
2252
2253 W is either NULL or a window used to evaluate filters. If W is
2254 null, no window-based face specification filter matches.
2255*/
2256static Lisp_Object
2257filter_face_ref (Lisp_Object face_ref,
2258 struct window *w,
2259 bool *ok,
2260 bool err_msgs)
2261{
2262 Lisp_Object orig_face_ref = face_ref;
2263 if (!CONSP (face_ref))
2264 return face_ref;
2265
2266 {
2267 if (!EQ (XCAR (face_ref), Qfiltered_kw))
2268 return face_ref;
2269 face_ref = XCDR (face_ref);
2270
2271 if (!CONSP (face_ref))
2272 goto err;
2273 Lisp_Object filter = XCAR (face_ref);
2274 face_ref = XCDR (face_ref);
2275
2276 if (!CONSP (face_ref))
2277 goto err;
2278 Lisp_Object filtered_face_ref = XCAR (face_ref);
2279 face_ref = XCDR (face_ref);
2280
2281 if (!NILP (face_ref))
2282 goto err;
2283
2284 return evaluate_face_filter (filter, w, ok, err_msgs)
2285 ? filtered_face_ref : Qnil;
2286 }
2287
2288 err:
2289 if (err_msgs)
2290 add_to_log ("Invalid face ref %S", orig_face_ref);
2291 *ok = false;
2292 return Qnil;
2293}
2181 2294
2182/* Merge face attributes from the lisp `face reference' FACE_REF on 2295/* Merge face attributes from the lisp `face reference' FACE_REF on
2183 frame F into the face attribute vector TO. If ERR_MSGS, 2296 frame F into the face attribute vector TO. If ERR_MSGS,
@@ -2199,21 +2312,44 @@ merge_named_face (struct frame *f, Lisp_Object face_name, Lisp_Object *to,
2199 (BACKGROUND-COLOR . COLOR) where COLOR is a color name. This is 2312 (BACKGROUND-COLOR . COLOR) where COLOR is a color name. This is
2200 for compatibility with 20.2. 2313 for compatibility with 20.2.
2201 2314
2315 4. Conses of the form
2316 (:filter (:window PARAMETER VALUE) FACE-SPECIFICATION),
2317 which applies FACE-SPECIFICATION only if the
2318 given face attributes are being evaluated in the context of a
2319 window with a parameter named PARAMETER being EQ VALUE.
2320
2321 5. nil, which means to merge nothing.
2322
2202 Face specifications earlier in lists take precedence over later 2323 Face specifications earlier in lists take precedence over later
2203 specifications. */ 2324 specifications. */
2204 2325
2205static bool 2326static bool
2206merge_face_ref (struct frame *f, Lisp_Object face_ref, Lisp_Object *to, 2327merge_face_ref (struct window *w,
2328 struct frame *f, Lisp_Object face_ref, Lisp_Object *to,
2207 bool err_msgs, struct named_merge_point *named_merge_points) 2329 bool err_msgs, struct named_merge_point *named_merge_points)
2208{ 2330{
2209 bool ok = true; /* Succeed without an error? */ 2331 bool ok = true; /* Succeed without an error? */
2332 Lisp_Object filtered_face_ref;
2333
2334 filtered_face_ref = face_ref;
2335 do
2336 {
2337 face_ref = filtered_face_ref;
2338 filtered_face_ref = filter_face_ref (face_ref, w, &ok, err_msgs);
2339 } while (ok && !EQ (face_ref, filtered_face_ref));
2340
2341 if (!ok)
2342 return false;
2343
2344 if (NILP (face_ref))
2345 return true;
2210 2346
2211 if (CONSP (face_ref)) 2347 if (CONSP (face_ref))
2212 { 2348 {
2213 Lisp_Object first = XCAR (face_ref); 2349 Lisp_Object first = XCAR (face_ref);
2214 2350
2215 if (EQ (first, Qforeground_color) 2351 if (EQ (first, Qforeground_color)
2216 || EQ (first, Qbackground_color)) 2352 || EQ (first, Qbackground_color))
2217 { 2353 {
2218 /* One of (FOREGROUND-COLOR . COLOR) or (BACKGROUND-COLOR 2354 /* One of (FOREGROUND-COLOR . COLOR) or (BACKGROUND-COLOR
2219 . COLOR). COLOR must be a string. */ 2355 . COLOR). COLOR must be a string. */
@@ -2400,7 +2536,7 @@ merge_face_ref (struct frame *f, Lisp_Object face_ref, Lisp_Object *to,
2400 { 2536 {
2401 /* This is not really very useful; it's just like a 2537 /* This is not really very useful; it's just like a
2402 normal face reference. */ 2538 normal face reference. */
2403 if (! merge_face_ref (f, value, to, 2539 if (! merge_face_ref (w, f, value, to,
2404 err_msgs, named_merge_points)) 2540 err_msgs, named_merge_points))
2405 err = true; 2541 err = true;
2406 } 2542 }
@@ -2424,16 +2560,16 @@ merge_face_ref (struct frame *f, Lisp_Object face_ref, Lisp_Object *to,
2424 Lisp_Object next = XCDR (face_ref); 2560 Lisp_Object next = XCDR (face_ref);
2425 2561
2426 if (! NILP (next)) 2562 if (! NILP (next))
2427 ok = merge_face_ref (f, next, to, err_msgs, named_merge_points); 2563 ok = merge_face_ref (w, f, next, to, err_msgs, named_merge_points);
2428 2564
2429 if (! merge_face_ref (f, first, to, err_msgs, named_merge_points)) 2565 if (! merge_face_ref (w, f, first, to, err_msgs, named_merge_points))
2430 ok = false; 2566 ok = false;
2431 } 2567 }
2432 } 2568 }
2433 else 2569 else
2434 { 2570 {
2435 /* FACE_REF ought to be a face name. */ 2571 /* FACE_REF ought to be a face name. */
2436 ok = merge_named_face (f, face_ref, to, named_merge_points); 2572 ok = merge_named_face (w, f, face_ref, to, named_merge_points);
2437 if (!ok && err_msgs) 2573 if (!ok && err_msgs)
2438 add_to_log ("Invalid face reference: %s", face_ref); 2574 add_to_log ("Invalid face reference: %s", face_ref);
2439 } 2575 }
@@ -3701,7 +3837,7 @@ Default face attributes override any local face attributes. */)
3701 /* Ensure that the face vector is fully specified by merging 3837 /* Ensure that the face vector is fully specified by merging
3702 the previously-cached vector. */ 3838 the previously-cached vector. */
3703 memcpy (attrs, oldface->lface, sizeof attrs); 3839 memcpy (attrs, oldface->lface, sizeof attrs);
3704 merge_face_vectors (f, lvec, attrs, 0); 3840 merge_face_vectors (NULL, f, lvec, attrs, 0);
3705 vcopy (local_lface, 0, attrs, LFACE_VECTOR_SIZE); 3841 vcopy (local_lface, 0, attrs, LFACE_VECTOR_SIZE);
3706 newface = realize_face (c, lvec, DEFAULT_FACE_ID); 3842 newface = realize_face (c, lvec, DEFAULT_FACE_ID);
3707 3843
@@ -3774,7 +3910,7 @@ return the font name used for CHARACTER. */)
3774 else 3910 else
3775 { 3911 {
3776 struct frame *f = decode_live_frame (frame); 3912 struct frame *f = decode_live_frame (frame);
3777 int face_id = lookup_named_face (f, face, true); 3913 int face_id = lookup_named_face (NULL, f, face, true);
3778 struct face *fface = FACE_FROM_ID_OR_NULL (f, face_id); 3914 struct face *fface = FACE_FROM_ID_OR_NULL (f, face_id);
3779 3915
3780 if (! fface) 3916 if (! fface)
@@ -4432,10 +4568,12 @@ face_for_font (struct frame *f, Lisp_Object font_object, struct face *base_face)
4432/* Return the face id of the realized face for named face SYMBOL on 4568/* Return the face id of the realized face for named face SYMBOL on
4433 frame F suitable for displaying ASCII characters. Value is -1 if 4569 frame F suitable for displaying ASCII characters. Value is -1 if
4434 the face couldn't be determined, which might happen if the default 4570 the face couldn't be determined, which might happen if the default
4435 face isn't realized and cannot be realized. */ 4571 face isn't realized and cannot be realized. If window W is given,
4436 4572 consider face remappings specified for W or for W's buffer. If W is
4573 NULL, consider only frame-level face configuration. */
4437int 4574int
4438lookup_named_face (struct frame *f, Lisp_Object symbol, bool signal_p) 4575lookup_named_face (struct window *w, struct frame *f,
4576 Lisp_Object symbol, bool signal_p)
4439{ 4577{
4440 Lisp_Object attrs[LFACE_VECTOR_SIZE]; 4578 Lisp_Object attrs[LFACE_VECTOR_SIZE];
4441 Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE]; 4579 Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE];
@@ -4448,11 +4586,11 @@ lookup_named_face (struct frame *f, Lisp_Object symbol, bool signal_p)
4448 default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID); 4586 default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
4449 } 4587 }
4450 4588
4451 if (! get_lface_attributes (f, symbol, symbol_attrs, signal_p, 0)) 4589 if (! get_lface_attributes (w, f, symbol, symbol_attrs, signal_p, 0))
4452 return -1; 4590 return -1;
4453 4591
4454 memcpy (attrs, default_face->lface, sizeof attrs); 4592 memcpy (attrs, default_face->lface, sizeof attrs);
4455 merge_face_vectors (f, symbol_attrs, attrs, 0); 4593 merge_face_vectors (w, f, symbol_attrs, attrs, 0);
4456 4594
4457 return lookup_face (f, attrs); 4595 return lookup_face (f, attrs);
4458} 4596}
@@ -4462,10 +4600,10 @@ lookup_named_face (struct frame *f, Lisp_Object symbol, bool signal_p)
4462 is FACE_ID. The return value will usually simply be FACE_ID, unless that 4600 is FACE_ID. The return value will usually simply be FACE_ID, unless that
4463 basic face has bee remapped via Vface_remapping_alist. This function is 4601 basic face has bee remapped via Vface_remapping_alist. This function is
4464 conservative: if something goes wrong, it will simply return FACE_ID 4602 conservative: if something goes wrong, it will simply return FACE_ID
4465 rather than signal an error. */ 4603 rather than signal an error. Window W, if non-NULL, is used to filter
4466 4604 face specifications for remapping. */
4467int 4605int
4468lookup_basic_face (struct frame *f, int face_id) 4606lookup_basic_face (struct window *w, struct frame *f, int face_id)
4469{ 4607{
4470 Lisp_Object name, mapping; 4608 Lisp_Object name, mapping;
4471 int remapped_face_id; 4609 int remapped_face_id;
@@ -4505,7 +4643,7 @@ lookup_basic_face (struct frame *f, int face_id)
4505 4643
4506 /* If there is a remapping entry, lookup the face using NAME, which will 4644 /* If there is a remapping entry, lookup the face using NAME, which will
4507 handle the remapping too. */ 4645 handle the remapping too. */
4508 remapped_face_id = lookup_named_face (f, name, false); 4646 remapped_face_id = lookup_named_face (w, f, name, false);
4509 if (remapped_face_id < 0) 4647 if (remapped_face_id < 0)
4510 return face_id; /* Give up. */ 4648 return face_id; /* Give up. */
4511 4649
@@ -4603,22 +4741,23 @@ face_with_height (struct frame *f, int face_id, int height)
4603 attributes of the face FACE_ID for attributes that aren't 4741 attributes of the face FACE_ID for attributes that aren't
4604 completely specified by SYMBOL. This is like lookup_named_face, 4742 completely specified by SYMBOL. This is like lookup_named_face,
4605 except that the default attributes come from FACE_ID, not from the 4743 except that the default attributes come from FACE_ID, not from the
4606 default face. FACE_ID is assumed to be already realized. */ 4744 default face. FACE_ID is assumed to be already realized.
4607 4745 Window W, if non-NULL, filters face specifications. */
4608int 4746int
4609lookup_derived_face (struct frame *f, Lisp_Object symbol, int face_id, 4747lookup_derived_face (struct window *w,
4748 struct frame *f, Lisp_Object symbol, int face_id,
4610 bool signal_p) 4749 bool signal_p)
4611{ 4750{
4612 Lisp_Object attrs[LFACE_VECTOR_SIZE]; 4751 Lisp_Object attrs[LFACE_VECTOR_SIZE];
4613 Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE]; 4752 Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE];
4614 struct face *default_face; 4753 struct face *default_face;
4615 4754
4616 if (!get_lface_attributes (f, symbol, symbol_attrs, signal_p, 0)) 4755 if (!get_lface_attributes (w, f, symbol, symbol_attrs, signal_p, 0))
4617 return -1; 4756 return -1;
4618 4757
4619 default_face = FACE_FROM_ID (f, face_id); 4758 default_face = FACE_FROM_ID (f, face_id);
4620 memcpy (attrs, default_face->lface, sizeof attrs); 4759 memcpy (attrs, default_face->lface, sizeof attrs);
4621 merge_face_vectors (f, symbol_attrs, attrs, 0); 4760 merge_face_vectors (w, f, symbol_attrs, attrs, 0);
4622 return lookup_face (f, attrs); 4761 return lookup_face (f, attrs);
4623} 4762}
4624 4763
@@ -4630,7 +4769,8 @@ DEFUN ("face-attributes-as-vector", Fface_attributes_as_vector,
4630 Lisp_Object lface; 4769 Lisp_Object lface;
4631 lface = Fmake_vector (make_number (LFACE_VECTOR_SIZE), 4770 lface = Fmake_vector (make_number (LFACE_VECTOR_SIZE),
4632 Qunspecified); 4771 Qunspecified);
4633 merge_face_ref (XFRAME (selected_frame), plist, XVECTOR (lface)->contents, 4772 merge_face_ref (NULL, XFRAME (selected_frame),
4773 plist, XVECTOR (lface)->contents,
4634 true, 0); 4774 true, 0);
4635 return lface; 4775 return lface;
4636} 4776}
@@ -4714,7 +4854,7 @@ x_supports_face_attributes_p (struct frame *f,
4714 4854
4715 memcpy (merged_attrs, def_attrs, sizeof merged_attrs); 4855 memcpy (merged_attrs, def_attrs, sizeof merged_attrs);
4716 4856
4717 merge_face_vectors (f, attrs, merged_attrs, 0); 4857 merge_face_vectors (NULL, f, attrs, merged_attrs, 0);
4718 4858
4719 face_id = lookup_face (f, merged_attrs); 4859 face_id = lookup_face (f, merged_attrs);
4720 face = FACE_FROM_ID_OR_NULL (f, face_id); 4860 face = FACE_FROM_ID_OR_NULL (f, face_id);
@@ -4985,7 +5125,7 @@ face for italic. */)
4985 5125
4986 for (i = 0; i < LFACE_VECTOR_SIZE; i++) 5126 for (i = 0; i < LFACE_VECTOR_SIZE; i++)
4987 attrs[i] = Qunspecified; 5127 attrs[i] = Qunspecified;
4988 merge_face_ref (f, attributes, attrs, true, 0); 5128 merge_face_ref (NULL, f, attributes, attrs, true, 0);
4989 5129
4990 def_face = FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID); 5130 def_face = FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID);
4991 if (def_face == NULL) 5131 if (def_face == NULL)
@@ -5354,7 +5494,7 @@ realize_named_face (struct frame *f, Lisp_Object symbol, int id)
5354 5494
5355 /* Merge SYMBOL's face with the default face. */ 5495 /* Merge SYMBOL's face with the default face. */
5356 get_lface_attributes_no_remap (f, symbol, symbol_attrs, true); 5496 get_lface_attributes_no_remap (f, symbol, symbol_attrs, true);
5357 merge_face_vectors (f, symbol_attrs, attrs, 0); 5497 merge_face_vectors (NULL, f, symbol_attrs, attrs, 0);
5358 5498
5359 /* Realize the face. */ 5499 /* Realize the face. */
5360 realize_face (c, attrs, id); 5500 realize_face (c, attrs, id);
@@ -5869,7 +6009,7 @@ compute_char_face (struct frame *f, int ch, Lisp_Object prop)
5869 Lisp_Object attrs[LFACE_VECTOR_SIZE]; 6009 Lisp_Object attrs[LFACE_VECTOR_SIZE];
5870 struct face *default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID); 6010 struct face *default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
5871 memcpy (attrs, default_face->lface, sizeof attrs); 6011 memcpy (attrs, default_face->lface, sizeof attrs);
5872 merge_face_ref (f, prop, attrs, true, 0); 6012 merge_face_ref (NULL, f, prop, attrs, true, 0);
5873 face_id = lookup_face (f, attrs); 6013 face_id = lookup_face (f, attrs);
5874 } 6014 }
5875 6015
@@ -5948,7 +6088,7 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos,
5948 else if (NILP (Vface_remapping_alist)) 6088 else if (NILP (Vface_remapping_alist))
5949 face_id = DEFAULT_FACE_ID; 6089 face_id = DEFAULT_FACE_ID;
5950 else 6090 else
5951 face_id = lookup_basic_face (f, DEFAULT_FACE_ID); 6091 face_id = lookup_basic_face (w, f, DEFAULT_FACE_ID);
5952 6092
5953 default_face = FACE_FROM_ID (f, face_id); 6093 default_face = FACE_FROM_ID (f, face_id);
5954 } 6094 }
@@ -5966,7 +6106,7 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos,
5966 6106
5967 /* Merge in attributes specified via text properties. */ 6107 /* Merge in attributes specified via text properties. */
5968 if (!NILP (prop)) 6108 if (!NILP (prop))
5969 merge_face_ref (f, prop, attrs, true, 0); 6109 merge_face_ref (w, f, prop, attrs, true, 0);
5970 6110
5971 /* Now merge the overlay data. */ 6111 /* Now merge the overlay data. */
5972 noverlays = sort_overlays (overlay_vec, noverlays, w); 6112 noverlays = sort_overlays (overlay_vec, noverlays, w);
@@ -5986,7 +6126,7 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos,
5986 so discard the mouse-face text property, if any, and 6126 so discard the mouse-face text property, if any, and
5987 use the overlay property instead. */ 6127 use the overlay property instead. */
5988 memcpy (attrs, default_face->lface, sizeof attrs); 6128 memcpy (attrs, default_face->lface, sizeof attrs);
5989 merge_face_ref (f, prop, attrs, true, 0); 6129 merge_face_ref (w, f, prop, attrs, true, 0);
5990 } 6130 }
5991 6131
5992 oend = OVERLAY_END (overlay_vec[i]); 6132 oend = OVERLAY_END (overlay_vec[i]);
@@ -6004,7 +6144,7 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos,
6004 6144
6005 prop = Foverlay_get (overlay_vec[i], propname); 6145 prop = Foverlay_get (overlay_vec[i], propname);
6006 if (!NILP (prop)) 6146 if (!NILP (prop))
6007 merge_face_ref (f, prop, attrs, true, 0); 6147 merge_face_ref (w, f, prop, attrs, true, 0);
6008 6148
6009 oend = OVERLAY_END (overlay_vec[i]); 6149 oend = OVERLAY_END (overlay_vec[i]);
6010 oendpos = OVERLAY_POSITION (oend); 6150 oendpos = OVERLAY_POSITION (oend);
@@ -6065,12 +6205,12 @@ face_for_overlay_string (struct window *w, ptrdiff_t pos,
6065 return DEFAULT_FACE_ID; 6205 return DEFAULT_FACE_ID;
6066 6206
6067 /* Begin with attributes from the default face. */ 6207 /* Begin with attributes from the default face. */
6068 default_face = FACE_FROM_ID (f, lookup_basic_face (f, DEFAULT_FACE_ID)); 6208 default_face = FACE_FROM_ID (f, lookup_basic_face (w, f, DEFAULT_FACE_ID));
6069 memcpy (attrs, default_face->lface, sizeof attrs); 6209 memcpy (attrs, default_face->lface, sizeof attrs);
6070 6210
6071 /* Merge in attributes specified via text properties. */ 6211 /* Merge in attributes specified via text properties. */
6072 if (!NILP (prop)) 6212 if (!NILP (prop))
6073 merge_face_ref (f, prop, attrs, true, 0); 6213 merge_face_ref (w, f, prop, attrs, true, 0);
6074 6214
6075 *endptr = endpos; 6215 *endptr = endpos;
6076 6216
@@ -6149,7 +6289,7 @@ face_at_string_position (struct window *w, Lisp_Object string,
6149 6289
6150 /* Merge in attributes specified via text properties. */ 6290 /* Merge in attributes specified via text properties. */
6151 if (!NILP (prop)) 6291 if (!NILP (prop))
6152 merge_face_ref (f, prop, attrs, true, 0); 6292 merge_face_ref (w, f, prop, attrs, true, 0);
6153 6293
6154 /* Look up a realized face with the given face attributes, 6294 /* Look up a realized face with the given face attributes,
6155 or realize a new one for ASCII characters. */ 6295 or realize a new one for ASCII characters. */
@@ -6159,7 +6299,7 @@ face_at_string_position (struct window *w, Lisp_Object string,
6159 6299
6160/* Merge a face into a realized face. 6300/* Merge a face into a realized face.
6161 6301
6162 F is frame where faces are (to be) realized. 6302 W is a window in the frame where faces are (to be) realized.
6163 6303
6164 FACE_NAME is named face to merge. 6304 FACE_NAME is named face to merge.
6165 6305
@@ -6173,9 +6313,10 @@ face_at_string_position (struct window *w, Lisp_Object string,
6173*/ 6313*/
6174 6314
6175int 6315int
6176merge_faces (struct frame *f, Lisp_Object face_name, int face_id, 6316merge_faces (struct window *w, Lisp_Object face_name, int face_id,
6177 int base_face_id) 6317 int base_face_id)
6178{ 6318{
6319 struct frame *f = WINDOW_XFRAME (w);
6179 Lisp_Object attrs[LFACE_VECTOR_SIZE]; 6320 Lisp_Object attrs[LFACE_VECTOR_SIZE];
6180 struct face *base_face; 6321 struct face *base_face;
6181 6322
@@ -6190,7 +6331,7 @@ merge_faces (struct frame *f, Lisp_Object face_name, int face_id,
6190 face_name = lface_id_to_name[face_id]; 6331 face_name = lface_id_to_name[face_id];
6191 /* When called during make-frame, lookup_derived_face may fail 6332 /* When called during make-frame, lookup_derived_face may fail
6192 if the faces are uninitialized. Don't signal an error. */ 6333 if the faces are uninitialized. Don't signal an error. */
6193 face_id = lookup_derived_face (f, face_name, base_face_id, 0); 6334 face_id = lookup_derived_face (w, f, face_name, base_face_id, 0);
6194 return (face_id >= 0 ? face_id : base_face_id); 6335 return (face_id >= 0 ? face_id : base_face_id);
6195 } 6336 }
6196 6337
@@ -6199,7 +6340,7 @@ merge_faces (struct frame *f, Lisp_Object face_name, int face_id,
6199 6340
6200 if (!NILP (face_name)) 6341 if (!NILP (face_name))
6201 { 6342 {
6202 if (!merge_named_face (f, face_name, attrs, 0)) 6343 if (!merge_named_face (w, f, face_name, attrs, 0))
6203 return base_face_id; 6344 return base_face_id;
6204 } 6345 }
6205 else 6346 else
@@ -6210,7 +6351,7 @@ merge_faces (struct frame *f, Lisp_Object face_name, int face_id,
6210 face = FACE_FROM_ID_OR_NULL (f, face_id); 6351 face = FACE_FROM_ID_OR_NULL (f, face_id);
6211 if (!face) 6352 if (!face)
6212 return base_face_id; 6353 return base_face_id;
6213 merge_face_vectors (f, face->lface, attrs, 0); 6354 merge_face_vectors (w, f, face->lface, attrs, 0);
6214 } 6355 }
6215 6356
6216 /* Look up a realized face with the given face attributes, 6357 /* Look up a realized face with the given face attributes,
@@ -6421,6 +6562,11 @@ syms_of_xfaces (void)
6421 DEFSYM (Qunspecified, "unspecified"); 6562 DEFSYM (Qunspecified, "unspecified");
6422 DEFSYM (QCignore_defface, ":ignore-defface"); 6563 DEFSYM (QCignore_defface, ":ignore-defface");
6423 6564
6565 /* Used for limiting character attributes to windows with specific
6566 characteristics. */
6567 DEFSYM (Qwindow_kw, ":window");
6568 DEFSYM (Qfiltered_kw, ":filtered");
6569
6424 /* The symbol `face-alias'. A symbol having that property is an 6570 /* The symbol `face-alias'. A symbol having that property is an
6425 alias for another face. Value of the property is the name of 6571 alias for another face. Value of the property is the name of
6426 the aliased face. */ 6572 the aliased face. */
@@ -6496,6 +6642,10 @@ syms_of_xfaces (void)
6496 defsubr (&Sdump_colors); 6642 defsubr (&Sdump_colors);
6497#endif 6643#endif
6498 6644
6645 DEFVAR_BOOL ("face-filters-always-match", face_filters_always_match,
6646 doc: /* Non-nil means that face filters are always deemed to
6647match. Use only when evaluating face attributes. */);
6648
6499 DEFVAR_LISP ("face-new-frame-defaults", Vface_new_frame_defaults, 6649 DEFVAR_LISP ("face-new-frame-defaults", Vface_new_frame_defaults,
6500 doc: /* List of global face definitions (for internal use only.) */); 6650 doc: /* List of global face definitions (for internal use only.) */);
6501 Vface_new_frame_defaults = Qnil; 6651 Vface_new_frame_defaults = Qnil;
@@ -6544,7 +6694,7 @@ REPLACEMENT is a face specification, i.e. one of the following:
6544 6694
6545 (1) a face name 6695 (1) a face name
6546 (2) a property list of attribute/value pairs, or 6696 (2) a property list of attribute/value pairs, or
6547 (3) a list in which each element has the form of (1) or (2). 6697 (3) a list in which each element has one of the above forms.
6548 6698
6549List values for REPLACEMENT are merged to form the final face 6699List values for REPLACEMENT are merged to form the final face
6550specification, with earlier entries taking precedence, in the same way 6700specification, with earlier entries taking precedence, in the same way
@@ -6564,13 +6714,32 @@ causes EXTRA-FACE... or (FACE-ATTR VAL ...) to be _merged_ with the
6564existing definition of FACE. Note that this isn't necessary for the 6714existing definition of FACE. Note that this isn't necessary for the
6565default face, since every face inherits from the default face. 6715default face, since every face inherits from the default face.
6566 6716
6567If this variable is made buffer-local, the face remapping takes effect 6717An entry in the list can also be a filtered face expression of the
6568only in that buffer. For instance, the mode my-mode could define a 6718form:
6569face `my-mode-default', and then in the mode setup function, do: 6719
6720 (:filtered FILTER FACE-SPECIFICATION)
6721
6722This construct applies FACE-SPECIFICATION (which can have any of the
6723forms allowed for face specifications generally) only if FILTER
6724matches at the moment Emacs wants to draw text with the combined face.
6725
6726The only filters currently defined are NIL (which always matches) and
6727(:window PARAMETER VALUE), which matches only in the context of a
6728window with a parameter EQ-equal to VALUE.
6729
6730An entry in the face list can also be nil, which does nothing.
6731
6732If `face-remapping-alist' is made buffer-local, the face remapping
6733takes effect only in that buffer. For instance, the mode my-mode
6734could define a face `my-mode-default', and then in the mode setup
6735function, do:
6570 6736
6571 (set (make-local-variable \\='face-remapping-alist) 6737 (set (make-local-variable \\='face-remapping-alist)
6572 \\='((default my-mode-default)))). 6738 \\='((default my-mode-default)))).
6573 6739
6740You probably want to use the face-remap package included in Emacs
6741instead of manipulating face-remapping-alist directly.
6742
6574Because Emacs normally only redraws screen areas when the underlying 6743Because Emacs normally only redraws screen areas when the underlying
6575buffer contents change, you may need to call `redraw-display' after 6744buffer contents change, you may need to call `redraw-display' after
6576changing this variable for it to take effect. */); 6745changing this variable for it to take effect. */);
diff --git a/src/xwidget.c b/src/xwidget.c
index 32022abf341..5f2651214e3 100644
--- a/src/xwidget.c
+++ b/src/xwidget.c
@@ -749,8 +749,10 @@ argument procedure FUN.*/)
749 /* JavaScript execution happens asynchronously. If an elisp 749 /* JavaScript execution happens asynchronously. If an elisp
750 callback function is provided we pass it to the C callback 750 callback function is provided we pass it to the C callback
751 procedure that retrieves the return value. */ 751 procedure that retrieves the return value. */
752 gchar *script_string
753 = XSAVE_POINTER (XCAR (AREF (xw->script_callbacks, idx)), 0);
752 webkit_web_view_run_javascript (WEBKIT_WEB_VIEW (xw->widget_osr), 754 webkit_web_view_run_javascript (WEBKIT_WEB_VIEW (xw->widget_osr),
753 XSAVE_POINTER (XCAR (AREF (xw->script_callbacks, idx)), 0), 755 script_string,
754 NULL, /* cancelable */ 756 NULL, /* cancelable */
755 webkit_javascript_finished_cb, 757 webkit_javascript_finished_cb,
756 (gpointer) idx); 758 (gpointer) idx);
@@ -1221,15 +1223,13 @@ kill_buffer_xwidgets (Lisp_Object buffer)
1221 gtk_widget_destroy (xw->widgetwindow_osr); 1223 gtk_widget_destroy (xw->widgetwindow_osr);
1222 } 1224 }
1223 if (!NILP (xw->script_callbacks)) 1225 if (!NILP (xw->script_callbacks))
1224 { 1226 for (ptrdiff_t idx = 0; idx < ASIZE (xw->script_callbacks); idx++)
1225 ptrdiff_t idx; 1227 {
1226 for (idx = 0; idx < ASIZE (xw->script_callbacks); idx++) 1228 Lisp_Object cb = AREF (xw->script_callbacks, idx);
1227 { 1229 if (!NILP (cb))
1228 if (!NILP (AREF (xw->script_callbacks, idx))) 1230 xfree (XSAVE_POINTER (XCAR (cb), 0));
1229 xfree (XSAVE_POINTER (XCAR (AREF (xw->script_callbacks, idx)), 0)); 1231 ASET (xw->script_callbacks, idx, Qnil);
1230 ASET (xw->script_callbacks, idx, Qnil); 1232 }
1231 }
1232 }
1233 } 1233 }
1234 } 1234 }
1235} 1235}