aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorVincent Belaïche2016-01-20 08:30:51 +0100
committerVincent Belaïche2016-01-20 08:30:51 +0100
commitb895c72059521fec064ff27b4cfcfa4104081c4e (patch)
treec1697f0e4d95d8c3556798f6c4c53c98a4714bd0 /lisp
parentbadcd38aa86ed7973f2be2743c405710973a0bdd (diff)
parent1b76d9168336ede8976b980aeaed64ae2908501a (diff)
downloademacs-b895c72059521fec064ff27b4cfcfa4104081c4e.tar.gz
emacs-b895c72059521fec064ff27b4cfcfa4104081c4e.zip
Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs
Diffstat (limited to 'lisp')
-rw-r--r--lisp/cedet/mode-local.el2
-rw-r--r--lisp/descr-text.el2
-rw-r--r--lisp/desktop.el151
-rw-r--r--lisp/dired-aux.el35
-rw-r--r--lisp/dired-x.el14
-rw-r--r--lisp/dired.el4
-rw-r--r--lisp/dos-fns.el4
-rw-r--r--lisp/electric.el3
-rw-r--r--lisp/emacs-lisp/check-declare.el1
-rw-r--r--lisp/emacs-lisp/cursor-sensor.el4
-rw-r--r--lisp/emacs-lisp/inline.el2
-rw-r--r--lisp/emacs-lisp/package.el2
-rw-r--r--lisp/emacs-lisp/syntax.el6
-rw-r--r--lisp/epg-config.el1
-rw-r--r--lisp/erc/erc.el6
-rw-r--r--lisp/eshell/em-term.el1
-rw-r--r--lisp/files-x.el6
-rw-r--r--lisp/files.el24
-rw-r--r--lisp/font-lock.el3
-rw-r--r--lisp/gnus/gnus-fun.el4
-rw-r--r--lisp/gnus/gnus-util.el15
-rw-r--r--lisp/gnus/gnus.el1
-rw-r--r--lisp/gnus/mml-sec.el539
-rw-r--r--lisp/gnus/mml-smime.el265
-rw-r--r--lisp/gnus/mml1991.el203
-rw-r--r--lisp/gnus/mml2015.el306
-rw-r--r--lisp/gnus/nntp.el26
-rw-r--r--lisp/help-fns.el27
-rw-r--r--lisp/international/mule-util.el2
-rw-r--r--lisp/mail/rmail.el5
-rw-r--r--lisp/mh-e/mh-e.el4
-rw-r--r--lisp/net/browse-url.el2
-rw-r--r--lisp/net/newst-reader.el1
-rw-r--r--lisp/net/newst-treeview.el4
-rw-r--r--lisp/net/shr.el4
-rw-r--r--lisp/net/tramp-sh.el19
-rw-r--r--lisp/net/tramp.el18
-rw-r--r--lisp/nxml/nxml-enc.el4
-rw-r--r--lisp/nxml/nxml-glyph.el423
-rw-r--r--lisp/nxml/nxml-maint.el44
-rw-r--r--lisp/nxml/nxml-mode.el329
-rw-r--r--lisp/nxml/nxml-outln.el28
-rw-r--r--lisp/nxml/nxml-parse.el2
-rw-r--r--lisp/nxml/nxml-rap.el129
-rw-r--r--lisp/nxml/nxml-uchnm.el251
-rw-r--r--lisp/nxml/nxml-util.el14
-rw-r--r--lisp/nxml/rng-cmpct.el2
-rw-r--r--lisp/nxml/rng-dt.el4
-rw-r--r--lisp/nxml/rng-loc.el15
-rw-r--r--lisp/nxml/rng-maint.el2
-rw-r--r--lisp/nxml/rng-match.el5
-rw-r--r--lisp/nxml/rng-nxml.el250
-rw-r--r--lisp/nxml/rng-parse.el2
-rw-r--r--lisp/nxml/rng-pttrn.el2
-rw-r--r--lisp/nxml/rng-uri.el2
-rw-r--r--lisp/nxml/rng-util.el63
-rw-r--r--lisp/nxml/rng-valid.el53
-rw-r--r--lisp/nxml/rng-xsd.el8
-rw-r--r--lisp/nxml/xmltok.el43
-rw-r--r--lisp/nxml/xsd-regexp.el6
-rw-r--r--lisp/progmodes/elisp-mode.el7
-rw-r--r--lisp/progmodes/etags.el1
-rw-r--r--lisp/progmodes/gud.el1
-rw-r--r--lisp/progmodes/hideif.el29
-rw-r--r--lisp/progmodes/prog-mode.el1
-rw-r--r--lisp/progmodes/project.el8
-rw-r--r--lisp/progmodes/python.el13
-rw-r--r--lisp/progmodes/ruby-mode.el9
-rw-r--r--lisp/progmodes/xref.el66
-rw-r--r--lisp/rect.el1
-rw-r--r--lisp/term/screen.el1
-rw-r--r--lisp/term/xterm.el1
-rw-r--r--lisp/textmodes/css-mode.el10
-rw-r--r--lisp/textmodes/sgml-mode.el11
-rw-r--r--lisp/textmodes/tildify.el2
-rw-r--r--lisp/thingatpt.el4
-rw-r--r--lisp/time-stamp.el50
-rw-r--r--lisp/url/url-tramp.el4
78 files changed, 1325 insertions, 2291 deletions
diff --git a/lisp/cedet/mode-local.el b/lisp/cedet/mode-local.el
index 30320b00946..ce367485c16 100644
--- a/lisp/cedet/mode-local.el
+++ b/lisp/cedet/mode-local.el
@@ -670,7 +670,7 @@ SYMBOL is a function that can be overridden."
670 670
671(add-hook 'help-fns-describe-function-functions 'describe-mode-local-overload) 671(add-hook 'help-fns-describe-function-functions 'describe-mode-local-overload)
672 672
673(declare-function xref-item-location "xref" (xref)) 673(declare-function xref-item-location "xref" (xref) t)
674 674
675(defun xref-mode-local--override-present (sym xrefs) 675(defun xref-mode-local--override-present (sym xrefs)
676 "Return non-nil if SYM is in XREFS." 676 "Return non-nil if SYM is in XREFS."
diff --git a/lisp/descr-text.el b/lisp/descr-text.el
index dcc697e1b9a..a352ed0849c 100644
--- a/lisp/descr-text.el
+++ b/lisp/descr-text.el
@@ -322,7 +322,7 @@ This function is semi-obsolete. Use `get-char-code-property'."
322 (nth 13 fields) 16))))))))))) 322 (nth 13 fields) 16)))))))))))
323 323
324;; Not defined on builds without X, but behind display-graphic-p. 324;; Not defined on builds without X, but behind display-graphic-p.
325(declare-function internal-char-font "fontset.c" (position &optional ch)) 325(declare-function internal-char-font "font.c" (position &optional ch))
326 326
327;; Return information about how CHAR is displayed at the buffer 327;; Return information about how CHAR is displayed at the buffer
328;; position POS. If the selected frame is on a graphic display, 328;; position POS. If the selected frame is on a graphic display,
diff --git a/lisp/desktop.el b/lisp/desktop.el
index cb973c48f8d..e795d9c2300 100644
--- a/lisp/desktop.el
+++ b/lisp/desktop.el
@@ -140,8 +140,15 @@
140 140
141(defvar desktop-file-version "208" 141(defvar desktop-file-version "208"
142 "Version number of desktop file format. 142 "Version number of desktop file format.
143Written into the desktop file and used at desktop read to provide 143Used at desktop read to provide backward compatibility.")
144backward compatibility.") 144
145(defconst desktop-native-file-version 208
146 "Format version of the current desktop package, an integer.")
147(defvar desktop-io-file-version nil
148 "The format version of the current desktop file (an integer) or nil.")
149;; Note: Historically, the version number is embedded in the entry for
150;; each buffer. It is highly inadvisable for different buffer entries
151;; to have different format versions.
145 152
146;; ---------------------------------------------------------------------------- 153;; ----------------------------------------------------------------------------
147;; USER OPTIONS -- settings you might want to play with. 154;; USER OPTIONS -- settings you might want to play with.
@@ -693,6 +700,7 @@ deletes all frames except the selected one (and its minibuffer frame,
693if different)." 700if different)."
694 (interactive) 701 (interactive)
695 (desktop-lazy-abort) 702 (desktop-lazy-abort)
703 (setq desktop-io-file-version nil)
696 (dolist (var desktop-globals-to-clear) 704 (dolist (var desktop-globals-to-clear)
697 (if (symbolp var) 705 (if (symbolp var)
698 (eval `(setq-default ,var nil)) 706 (eval `(setq-default ,var nil))
@@ -781,44 +789,46 @@ buffer, which is (in order):
781 local variables; 789 local variables;
782 auxiliary information given by `desktop-var-serdes-funs'." 790 auxiliary information given by `desktop-var-serdes-funs'."
783 (set-buffer buffer) 791 (set-buffer buffer)
784 (list 792 `(
785 ;; base name of the buffer; replaces the buffer name if managed by uniquify 793 ;; base name of the buffer; replaces the buffer name if managed by uniquify
786 (and (fboundp 'uniquify-buffer-base-name) (uniquify-buffer-base-name)) 794 ,(and (fboundp 'uniquify-buffer-base-name) (uniquify-buffer-base-name))
787 ;; basic information 795 ;; basic information
788 (desktop-file-name (buffer-file-name) desktop-dirname) 796 ,(desktop-file-name (buffer-file-name) desktop-dirname)
789 (buffer-name) 797 ,(buffer-name)
790 major-mode 798 ,major-mode
791 ;; minor modes 799 ;; minor modes
792 (let (ret) 800 ,(let (ret)
793 (dolist (minor-mode (mapcar #'car minor-mode-alist) ret) 801 (dolist (minor-mode (mapcar #'car minor-mode-alist) ret)
794 (and (boundp minor-mode) 802 (and (boundp minor-mode)
795 (symbol-value minor-mode) 803 (symbol-value minor-mode)
796 (let* ((special (assq minor-mode desktop-minor-mode-table)) 804 (let* ((special (assq minor-mode desktop-minor-mode-table))
797 (value (cond (special (cadr special)) 805 (value (cond (special (cadr special))
798 ((functionp minor-mode) minor-mode)))) 806 ((functionp minor-mode) minor-mode))))
799 (when value (cl-pushnew value ret)))))) 807 (when value (cl-pushnew value ret))))))
800 ;; point and mark, and read-only status 808 ;; point and mark, and read-only status
801 (point) 809 ,(point)
802 (list (mark t) mark-active) 810 ,(list (mark t) mark-active)
803 buffer-read-only 811 ,buffer-read-only
804 ;; auxiliary information 812 ;; auxiliary information
805 (when (functionp desktop-save-buffer) 813 ,(when (functionp desktop-save-buffer)
806 (funcall desktop-save-buffer desktop-dirname)) 814 (funcall desktop-save-buffer desktop-dirname))
807 ;; local variables 815 ;; local variables
808 (let ((loclist (buffer-local-variables)) 816 ,(let ((loclist (buffer-local-variables))
809 (ll nil)) 817 (ll nil))
810 (dolist (local desktop-locals-to-save) 818 (dolist (local desktop-locals-to-save)
811 (let ((here (assq local loclist))) 819 (let ((here (assq local loclist)))
812 (cond (here 820 (cond (here
813 (push here ll)) 821 (push here ll))
814 ((member local loclist) 822 ((member local loclist)
815 (push local ll))))) 823 (push local ll)))))
816 ll) 824 ll)
817 (mapcar (lambda (record) 825 ,@(when (>= desktop-io-file-version 208)
818 (let ((var (car record))) 826 (list
819 (list var 827 (mapcar (lambda (record)
820 (funcall (cadr record) (symbol-value var))))) 828 (let ((var (car record)))
821 desktop-var-serdes-funs))) 829 (list var
830 (funcall (cadr record) (symbol-value var)))))
831 desktop-var-serdes-funs)))))
822 832
823;; ---------------------------------------------------------------------------- 833;; ----------------------------------------------------------------------------
824(defun desktop--v2s (value) 834(defun desktop--v2s (value)
@@ -983,20 +993,41 @@ Frames with a non-nil `desktop-dont-save' parameter are not saved."
983 :predicate #'desktop--check-dont-save)))) 993 :predicate #'desktop--check-dont-save))))
984 994
985;;;###autoload 995;;;###autoload
986(defun desktop-save (dirname &optional release only-if-changed) 996(defun desktop-save (dirname &optional release only-if-changed version)
987 "Save the desktop in a desktop file. 997 "Save the desktop in a desktop file.
988Parameter DIRNAME specifies where to save the desktop file. 998Parameter DIRNAME specifies where to save the desktop file.
989Optional parameter RELEASE says whether we're done with this desktop. 999Optional parameter RELEASE says whether we're done with this
990If ONLY-IF-CHANGED is non-nil, compare the current desktop information 1000desktop. If ONLY-IF-CHANGED is non-nil, compare the current
991to that in the desktop file, and if the desktop information has not 1001desktop information to that in the desktop file, and if the
992changed since it was last saved then do not rewrite the file." 1002desktop information has not changed since it was last saved then
1003do not rewrite the file.
1004
1005This function can save the desktop in either format version
1006208 (which only Emacs 25.1 and later can read) or version
1007206 (which is readable by any Emacs from version 22.1 onwards).
1008By default, it will use the same format the desktop file had when
1009it was last saved, or version 208 when writing a fresh desktop
1010file.
1011
1012To upgrade a version 206 file to version 208, call this command
1013explicitly with a bare prefix argument: C-u M-x desktop-save.
1014You are recommended to do this once you have firmly upgraded to
1015Emacs 25.1 (or later). To downgrade a version 208 file to version
1016206, use a double command prefix: C-u C-u M-x desktop-save.
1017Confirmation will be requested in either case. In a non-interactive
1018call, VERSION can be given as an integer, either 206 or 208, which
1019will be accepted as the format version in which to save the file
1020without further confirmation."
993 (interactive (list 1021 (interactive (list
994 ;; Or should we just use (car desktop-path)? 1022 ;; Or should we just use (car desktop-path)?
995 (let ((default (if (member "." desktop-path) 1023 (let ((default (if (member "." desktop-path)
996 default-directory 1024 default-directory
997 user-emacs-directory))) 1025 user-emacs-directory)))
998 (read-directory-name "Directory to save desktop file in: " 1026 (read-directory-name "Directory to save desktop file in: "
999 default default t)))) 1027 default default t))
1028 nil
1029 nil
1030 current-prefix-arg))
1000 (setq desktop-dirname (file-name-as-directory (expand-file-name dirname))) 1031 (setq desktop-dirname (file-name-as-directory (expand-file-name dirname)))
1001 (save-excursion 1032 (save-excursion
1002 (let ((eager desktop-restore-eager) 1033 (let ((eager desktop-restore-eager)
@@ -1017,12 +1048,34 @@ changed since it was last saved then do not rewrite the file."
1017 (desktop-release-lock) 1048 (desktop-release-lock)
1018 (unless (and new-modtime (desktop-owner)) (desktop-claim-lock))) 1049 (unless (and new-modtime (desktop-owner)) (desktop-claim-lock)))
1019 1050
1051 ;; What format are we going to write the file in?
1052 (setq desktop-io-file-version
1053 (cond
1054 ((equal version '(4))
1055 (if (or (eq desktop-io-file-version 208)
1056 (yes-or-no-p "Save desktop file in format 208 \
1057\(Readable by Emacs 25.1 and later only)? "))
1058 208
1059 (or desktop-io-file-version desktop-native-file-version)))
1060 ((equal version '(16))
1061 (if (or (eq desktop-io-file-version 206)
1062 (yes-or-no-p "Save desktop file in format 206 \
1063\(Readable by all Emacs versions since 22.1)? "))
1064 206
1065 (or desktop-io-file-version desktop-native-file-version)))
1066 ((memq version '(206 208))
1067 version)
1068 ((null desktop-io-file-version) ; As yet, no desktop file exists.
1069 desktop-native-file-version)
1070 (t
1071 desktop-io-file-version)))
1072
1020 (with-temp-buffer 1073 (with-temp-buffer
1021 (insert 1074 (insert
1022 ";; -*- mode: emacs-lisp; coding: emacs-mule; -*-\n" 1075 ";; -*- mode: emacs-lisp; coding: emacs-mule; -*-\n"
1023 desktop-header 1076 desktop-header
1024 ";; Created " (current-time-string) "\n" 1077 ";; Created " (current-time-string) "\n"
1025 ";; Desktop file format version " desktop-file-version "\n" 1078 ";; Desktop file format version " (format "%d" desktop-io-file-version) "\n"
1026 ";; Emacs version " emacs-version "\n") 1079 ";; Emacs version " emacs-version "\n")
1027 (save-excursion (run-hooks 'desktop-save-hook)) 1080 (save-excursion (run-hooks 'desktop-save-hook))
1028 (goto-char (point-max)) 1081 (goto-char (point-max))
@@ -1052,7 +1105,7 @@ changed since it was last saved then do not rewrite the file."
1052 "desktop-create-buffer" 1105 "desktop-create-buffer"
1053 "desktop-append-buffer-args") 1106 "desktop-append-buffer-args")
1054 " " 1107 " "
1055 desktop-file-version) 1108 (format "%d" desktop-io-file-version))
1056 ;; If there's a non-empty base name, we save it instead of the buffer name 1109 ;; If there's a non-empty base name, we save it instead of the buffer name
1057 (when (and base (not (string= base ""))) 1110 (when (and base (not (string= base "")))
1058 (setcar (nthcdr 1 l) base)) 1111 (setcar (nthcdr 1 l) base))
@@ -1390,6 +1443,8 @@ and try to load that."
1390 compacted-vars 1443 compacted-vars
1391 &rest _unsupported) 1444 &rest _unsupported)
1392 1445
1446 (setq desktop-io-file-version file-version)
1447
1393 (let ((desktop-file-version file-version) 1448 (let ((desktop-file-version file-version)
1394 (desktop-buffer-file-name buffer-filename) 1449 (desktop-buffer-file-name buffer-filename)
1395 (desktop-buffer-name buffer-name) 1450 (desktop-buffer-name buffer-name)
diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el
index a678fca3ea3..ab10edeedbf 100644
--- a/lisp/dired-aux.el
+++ b/lisp/dired-aux.el
@@ -2713,6 +2713,41 @@ with the command \\[tags-loop-continue]."
2713 (tags-query-replace from to delimited 2713 (tags-query-replace from to delimited
2714 '(dired-get-marked-files nil nil 'dired-nondirectory-p))) 2714 '(dired-get-marked-files nil nil 'dired-nondirectory-p)))
2715 2715
2716(declare-function xref--show-xrefs "xref")
2717(declare-function xref-query-replace "xref")
2718
2719;;;###autoload
2720(defun dired-do-find-regexp (regexp)
2721 "Find all matches for REGEXP in all marked files, recursively."
2722 (interactive "sSearch marked files (regexp): ")
2723 (require 'grep)
2724 (defvar grep-find-ignored-files)
2725 (let* ((files (dired-get-marked-files))
2726 (ignores (nconc (mapcar
2727 (lambda (s) (concat s "/"))
2728 vc-directory-exclusion-list)
2729 grep-find-ignored-files))
2730 (xrefs (cl-mapcan
2731 (lambda (file)
2732 (xref-collect-matches regexp "*" file
2733 (and (file-directory-p file)
2734 ignores)))
2735 files)))
2736 (unless xrefs
2737 (user-error "No matches for: %s" regexp))
2738 (xref--show-xrefs xrefs nil t)))
2739
2740;;;###autoload
2741(defun dired-do-find-regexp-and-replace (from to)
2742 "Replace matches of FROM with TO, in all marked files, recursively."
2743 (interactive
2744 (let ((common
2745 (query-replace-read-args
2746 "Query replace regexp in marked files" t t)))
2747 (list (nth 0 common) (nth 1 common))))
2748 (with-current-buffer (dired-do-find-regexp from)
2749 (xref-query-replace from to)))
2750
2716(defun dired-nondirectory-p (file) 2751(defun dired-nondirectory-p (file)
2717 (not (file-directory-p file))) 2752 (not (file-directory-p file)))
2718 2753
diff --git a/lisp/dired-x.el b/lisp/dired-x.el
index 053b3cb9738..e8cea85d988 100644
--- a/lisp/dired-x.el
+++ b/lisp/dired-x.el
@@ -816,16 +816,14 @@ If in a Dired buffer, reverts it."
816 (interactive) 816 (interactive)
817 (if (file-exists-p dired-local-variables-file) 817 (if (file-exists-p dired-local-variables-file)
818 (error "Old-style dired-local-variables-file `./%s' found; 818 (error "Old-style dired-local-variables-file `./%s' found;
819replace it with a dir-locals-file `./%s'" 819replace it with a dir-locals-file `./%s.el'"
820 dired-local-variables-file 820 dired-local-variables-file
821 dir-locals-file)) 821 dir-locals-file))
822 (if (file-exists-p dir-locals-file) 822 (if (dir-locals--all-files default-directory)
823 (message "File `./%s' already exists." dir-locals-file) 823 (message "File `./%s' already exists."
824 (with-temp-buffer 824 (car (dir-locals--all-files default-directory)))
825 (insert "\ 825 (add-dir-local-variable 'dired-mode 'subdirs nil)
826\((dired-mode . ((subdirs . nil) 826 (add-dir-local-variable 'dired-mode 'dired-omit-mode t)
827 (dired-omit-mode . t))))\n")
828 (write-file dir-locals-file))
829 ;; Run extra-hooks and revert directory. 827 ;; Run extra-hooks and revert directory.
830 (when (derived-mode-p 'dired-mode) 828 (when (derived-mode-p 'dired-mode)
831 (hack-dir-local-variables-non-file-buffer) 829 (hack-dir-local-variables-non-file-buffer)
diff --git a/lisp/dired.el b/lisp/dired.el
index 63124fce5e5..6c7445c3486 100644
--- a/lisp/dired.el
+++ b/lisp/dired.el
@@ -1453,7 +1453,7 @@ Do so according to the former subdir alist OLD-SUBDIR-ALIST."
1453 (define-key map "." 'dired-clean-directory) 1453 (define-key map "." 'dired-clean-directory)
1454 (define-key map "~" 'dired-flag-backup-files) 1454 (define-key map "~" 'dired-flag-backup-files)
1455 ;; Upper case keys (except !) for operating on the marked files 1455 ;; Upper case keys (except !) for operating on the marked files
1456 (define-key map "A" 'dired-do-search) 1456 (define-key map "A" 'dired-do-find-regexp)
1457 (define-key map "C" 'dired-do-copy) 1457 (define-key map "C" 'dired-do-copy)
1458 (define-key map "B" 'dired-do-byte-compile) 1458 (define-key map "B" 'dired-do-byte-compile)
1459 (define-key map "D" 'dired-do-delete) 1459 (define-key map "D" 'dired-do-delete)
@@ -1463,7 +1463,7 @@ Do so according to the former subdir alist OLD-SUBDIR-ALIST."
1463 (define-key map "M" 'dired-do-chmod) 1463 (define-key map "M" 'dired-do-chmod)
1464 (define-key map "O" 'dired-do-chown) 1464 (define-key map "O" 'dired-do-chown)
1465 (define-key map "P" 'dired-do-print) 1465 (define-key map "P" 'dired-do-print)
1466 (define-key map "Q" 'dired-do-query-replace-regexp) 1466 (define-key map "Q" 'dired-do-find-regexp-and-replace)
1467 (define-key map "R" 'dired-do-rename) 1467 (define-key map "R" 'dired-do-rename)
1468 (define-key map "S" 'dired-do-symlink) 1468 (define-key map "S" 'dired-do-symlink)
1469 (define-key map "T" 'dired-do-touch) 1469 (define-key map "T" 'dired-do-touch)
diff --git a/lisp/dos-fns.el b/lisp/dos-fns.el
index 7defb388b74..0ce2b23527d 100644
--- a/lisp/dos-fns.el
+++ b/lisp/dos-fns.el
@@ -201,8 +201,8 @@ that are used in Emacs Lisp sources; any other file name will be
201returned unaltered." 201returned unaltered."
202 (cond 202 (cond
203 ;; See files.el:dir-locals-file. 203 ;; See files.el:dir-locals-file.
204 ((string= file-name ".dir-locals.el") 204 ((string= file-name ".dir-locals")
205 "_dir-locals.el") 205 "_dir-locals")
206 (t 206 (t
207 file-name))) 207 file-name)))
208 208
diff --git a/lisp/electric.el b/lisp/electric.el
index abddd986ef8..ab79943c9dd 100644
--- a/lisp/electric.el
+++ b/lisp/electric.el
@@ -417,14 +417,17 @@ The variable `electric-layout-rules' says when and how to insert newlines."
417 417
418(defcustom electric-quote-comment t 418(defcustom electric-quote-comment t
419 "Non-nil means to use electric quoting in program comments." 419 "Non-nil means to use electric quoting in program comments."
420 :version "25.1"
420 :type 'boolean :safe 'booleanp :group 'electricity) 421 :type 'boolean :safe 'booleanp :group 'electricity)
421 422
422(defcustom electric-quote-string nil 423(defcustom electric-quote-string nil
423 "Non-nil means to use electric quoting in program strings." 424 "Non-nil means to use electric quoting in program strings."
425 :version "25.1"
424 :type 'boolean :safe 'booleanp :group 'electricity) 426 :type 'boolean :safe 'booleanp :group 'electricity)
425 427
426(defcustom electric-quote-paragraph t 428(defcustom electric-quote-paragraph t
427 "Non-nil means to use electric quoting in text paragraphs." 429 "Non-nil means to use electric quoting in text paragraphs."
430 :version "25.1"
428 :type 'boolean :safe 'booleanp :group 'electricity) 431 :type 'boolean :safe 'booleanp :group 'electricity)
429 432
430(defun electric--insertable-p (string) 433(defun electric--insertable-p (string)
diff --git a/lisp/emacs-lisp/check-declare.el b/lisp/emacs-lisp/check-declare.el
index 513aa319798..b6fa0546088 100644
--- a/lisp/emacs-lisp/check-declare.el
+++ b/lisp/emacs-lisp/check-declare.el
@@ -131,6 +131,7 @@ With optional argument FULL, sums the number of elements in each element."
131 131
132(defcustom check-declare-ext-errors nil 132(defcustom check-declare-ext-errors nil
133 "When non-nil, warn about functions not found in :ext." 133 "When non-nil, warn about functions not found in :ext."
134 :version "25.1"
134 :type 'boolean) 135 :type 'boolean)
135 136
136(defun check-declare-verify (fnfile fnlist) 137(defun check-declare-verify (fnfile fnlist)
diff --git a/lisp/emacs-lisp/cursor-sensor.el b/lisp/emacs-lisp/cursor-sensor.el
index 70c4458d300..ac063d4896a 100644
--- a/lisp/emacs-lisp/cursor-sensor.el
+++ b/lisp/emacs-lisp/cursor-sensor.el
@@ -167,8 +167,8 @@
167This property should hold a list of functions which react to the motion 167This property should hold a list of functions which react to the motion
168of the cursor. They're called with three arguments (WINDOW OLDPOS DIR) 168of the cursor. They're called with three arguments (WINDOW OLDPOS DIR)
169where WINDOW is the affected window, OLDPOS is the last known position of 169where WINDOW is the affected window, OLDPOS is the last known position of
170the cursor and DIR can be `left' or `entered' depending on whether the cursor is 170the cursor and DIR can be `entered' or `left' depending on whether the cursor
171entering the area covered by the text-property property or leaving it." 171is entering the area covered by the text-property property or leaving it."
172 nil nil nil 172 nil nil nil
173 (if cursor-sensor-mode 173 (if cursor-sensor-mode
174 (add-hook 'pre-redisplay-functions #'cursor-sensor--detect 174 (add-hook 'pre-redisplay-functions #'cursor-sensor--detect
diff --git a/lisp/emacs-lisp/inline.el b/lisp/emacs-lisp/inline.el
index 56780fbb05a..058c56c3b49 100644
--- a/lisp/emacs-lisp/inline.el
+++ b/lisp/emacs-lisp/inline.el
@@ -102,7 +102,7 @@ VARS should be a list of elements of the form (VAR EXP) or just VAR, in case
102EXP is equal to VAR. The result is to evaluate EXP and bind the result to VAR. 102EXP is equal to VAR. The result is to evaluate EXP and bind the result to VAR.
103 103
104The tail of VARS can be either nil or a symbol VAR which should hold a list 104The tail of VARS can be either nil or a symbol VAR which should hold a list
105of arguments,in which case each argument is evaluated and the resulting 105of arguments, in which case each argument is evaluated and the resulting
106new list is re-bound to VAR. 106new list is re-bound to VAR.
107 107
108After VARS is handled, BODY is evaluated in the new environment." 108After VARS is handled, BODY is evaluated in the new environment."
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index 057d01488cc..08f64147d44 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -329,6 +329,7 @@ by running `package-install-selected-packages'.
329To check if a package is contained in this list here, use 329To check if a package is contained in this list here, use
330`package--user-selected-p', as it may populate the variable with 330`package--user-selected-p', as it may populate the variable with
331a sane initial value." 331a sane initial value."
332 :version "25.1"
332 :type '(repeat symbol)) 333 :type '(repeat symbol))
333 334
334(defcustom package-menu-async t 335(defcustom package-menu-async t
@@ -2654,6 +2655,7 @@ omitted from the package menu. To toggle this, type \\[package-menu-toggle-hidi
2654 2655
2655Values can be interactively added to this list by typing 2656Values can be interactively added to this list by typing
2656\\[package-menu-hide-package] on a package" 2657\\[package-menu-hide-package] on a package"
2658 :version "25.1"
2657 :type '(repeat (regexp :tag "Hide packages with name matching"))) 2659 :type '(repeat (regexp :tag "Hide packages with name matching")))
2658 2660
2659(defun package-menu--refresh (&optional packages keywords) 2661(defun package-menu--refresh (&optional packages keywords)
diff --git a/lisp/emacs-lisp/syntax.el b/lisp/emacs-lisp/syntax.el
index e20a210de71..c221a017f51 100644
--- a/lisp/emacs-lisp/syntax.el
+++ b/lisp/emacs-lisp/syntax.el
@@ -416,6 +416,9 @@ point (where the PPSS is equivalent to nil).")
416 (error nil))) 416 (error nil)))
417 syntax-ppss-stats)) 417 syntax-ppss-stats))
418 418
419(defvar-local syntax-ppss-table nil
420 "Syntax-table to use during `syntax-ppss', if any.")
421
419(defun syntax-ppss (&optional pos) 422(defun syntax-ppss (&optional pos)
420 "Parse-Partial-Sexp State at POS, defaulting to point. 423 "Parse-Partial-Sexp State at POS, defaulting to point.
421The returned value is the same as that of `parse-partial-sexp' 424The returned value is the same as that of `parse-partial-sexp'
@@ -431,6 +434,7 @@ running the hook."
431 (unless pos (setq pos (point))) 434 (unless pos (setq pos (point)))
432 (syntax-propertize pos) 435 (syntax-propertize pos)
433 ;; 436 ;;
437 (with-syntax-table (or syntax-ppss-table (syntax-table))
434 (let ((old-ppss (cdr syntax-ppss-last)) 438 (let ((old-ppss (cdr syntax-ppss-last))
435 (old-pos (car syntax-ppss-last)) 439 (old-pos (car syntax-ppss-last))
436 (ppss nil) 440 (ppss nil)
@@ -567,7 +571,7 @@ running the hook."
567 ;; we may end up calling parse-partial-sexp with a position before 571 ;; we may end up calling parse-partial-sexp with a position before
568 ;; point-min. In that case, just parse from point-min assuming 572 ;; point-min. In that case, just parse from point-min assuming
569 ;; a nil state. 573 ;; a nil state.
570 (parse-partial-sexp (point-min) pos))))) 574 (parse-partial-sexp (point-min) pos))))))
571 575
572;; Debugging functions 576;; Debugging functions
573 577
diff --git a/lisp/epg-config.el b/lisp/epg-config.el
index 5fac079d3c0..e92bcd62a66 100644
--- a/lisp/epg-config.el
+++ b/lisp/epg-config.el
@@ -53,6 +53,7 @@
53 53
54(defcustom epg-gpgconf-program "gpgconf" 54(defcustom epg-gpgconf-program "gpgconf"
55 "The `gpgconf' executable." 55 "The `gpgconf' executable."
56 :version "25.1"
56 :group 'epg 57 :group 'epg
57 :type 'string) 58 :type 'string)
58 59
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index 3824c195d39..56317b83a98 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -265,14 +265,16 @@ A typical value would be \(\"JOIN\" \"PART\" \"QUIT\")."
265(defcustom erc-network-hide-list nil 265(defcustom erc-network-hide-list nil
266 "A list of IRC networks to hide message types from. 266 "A list of IRC networks to hide message types from.
267A typical value would be \((\"freenode\" \"MODE\") 267A typical value would be \((\"freenode\" \"MODE\")
268(\"OFTC\" \"JOIN\" \"QUIT\"))." 268 \(\"OFTC\" \"JOIN\" \"QUIT\"))."
269 :version "25.1"
269 :group 'erc-ignore 270 :group 'erc-ignore
270 :type 'erc-message-type) 271 :type 'erc-message-type)
271 272
272(defcustom erc-channel-hide-list nil 273(defcustom erc-channel-hide-list nil
273 "A list of IRC channels to hide message types from. 274 "A list of IRC channels to hide message types from.
274A typical value would be \((\"#emacs\" \"QUIT\" \"JOIN\") 275A typical value would be \((\"#emacs\" \"QUIT\" \"JOIN\")
275(\"#erc\" \"NICK\")." 276 \(\"#erc\" \"NICK\")."
277 :version "25.1"
276 :group 'erc-ignore 278 :group 'erc-ignore
277 :type 'erc-message-type) 279 :type 'erc-message-type)
278 280
diff --git a/lisp/eshell/em-term.el b/lisp/eshell/em-term.el
index aabc5fdb1a2..3e5de0c0097 100644
--- a/lisp/eshell/em-term.el
+++ b/lisp/eshell/em-term.el
@@ -136,6 +136,7 @@ character to the invoked process."
136 "If non-nil, term buffers are destroyed after their processes die. 136 "If non-nil, term buffers are destroyed after their processes die.
137WARNING: Setting this to non-nil may result in unexpected 137WARNING: Setting this to non-nil may result in unexpected
138behavior for short-lived processes, see bug#18108." 138behavior for short-lived processes, see bug#18108."
139 :version "25.1"
139 :type 'boolean 140 :type 'boolean
140 :group 'eshell-term) 141 :group 'eshell-term)
141 142
diff --git a/lisp/files-x.el b/lisp/files-x.el
index ed3d49df385..2e1a728356e 100644
--- a/lisp/files-x.el
+++ b/lisp/files-x.el
@@ -444,10 +444,8 @@ from the MODE alist ignoring the input argument VALUE."
444 (if (nth 2 variables-file) 444 (if (nth 2 variables-file)
445 (car (last (dir-locals--all-files (car variables-file)))) 445 (car (last (dir-locals--all-files (car variables-file))))
446 (cadr variables-file))) 446 (cadr variables-file)))
447 ;; Try to make a proper file-name. This doesn't cover all 447 ;; Try to make a proper file-name.
448 ;; wildcards, but it covers the default value of `dir-locals-file'. 448 (t (concat dir-locals-file ".el"))))
449 (t (replace-regexp-in-string
450 "\\*" "" (replace-regexp-in-string "\\?" "-" dir-locals-file)))))
451 ;; I can't be bothered to handle this case right now. 449 ;; I can't be bothered to handle this case right now.
452 ;; Dir locals were set directly from a class. You need to 450 ;; Dir locals were set directly from a class. You need to
453 ;; directly modify the class in dir-locals-class-alist. 451 ;; directly modify the class in dir-locals-class-alist.
diff --git a/lisp/files.el b/lisp/files.el
index 9cb46fcd0a9..5a15c71aab6 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -3713,7 +3713,7 @@ VARIABLES list of the class. The list is processed in order.
3713 applied by recursively following these rules." 3713 applied by recursively following these rules."
3714 (setf (alist-get class dir-locals-class-alist) variables)) 3714 (setf (alist-get class dir-locals-class-alist) variables))
3715 3715
3716(defconst dir-locals-file ".dir-locals*.el" 3716(defconst dir-locals-file ".dir-locals"
3717 "Pattern for files that contain directory-local variables. 3717 "Pattern for files that contain directory-local variables.
3718It has to be constant to enforce uniform values across different 3718It has to be constant to enforce uniform values across different
3719environments and users. 3719environments and users.
@@ -3730,16 +3730,20 @@ return a sorted list of all files matching `dir-locals-file' in
3730this directory. 3730this directory.
3731The returned list is sorted by `string<' order." 3731The returned list is sorted by `string<' order."
3732 (require 'seq) 3732 (require 'seq)
3733 (let ((default-directory (if (file-directory-p file-or-dir) 3733 (let ((dir (if (file-directory-p file-or-dir)
3734 file-or-dir 3734 file-or-dir
3735 default-directory))) 3735 (or (file-name-directory file-or-dir)
3736 default-directory)))
3737 (file (cond ((not (file-directory-p file-or-dir)) (file-name-nondirectory file-or-dir))
3738 ((eq system-type 'ms-dos) (dosified-file-name dir-locals-file))
3739 (t dir-locals-file))))
3736 (seq-filter (lambda (f) (and (file-readable-p f) 3740 (seq-filter (lambda (f) (and (file-readable-p f)
3737 (file-regular-p f))) 3741 (file-regular-p f)
3738 (file-expand-wildcards 3742 (not (file-directory-p f))))
3739 (cond ((not (file-directory-p file-or-dir)) file-or-dir) 3743 (mapcar (lambda (f) (expand-file-name f dir))
3740 ((eq system-type 'ms-dos) (dosified-file-name dir-locals-file)) 3744 (nreverse
3741 (t dir-locals-file)) 3745 (let ((completion-regexp-list '("\\.el\\'")))
3742 'full)))) 3746 (file-name-all-completions file dir)))))))
3743 3747
3744(defun dir-locals-find-file (file) 3748(defun dir-locals-find-file (file)
3745 "Find the directory-local variables for FILE. 3749 "Find the directory-local variables for FILE.
diff --git a/lisp/font-lock.el b/lisp/font-lock.el
index 3c1f01d5886..c79835dda49 100644
--- a/lisp/font-lock.el
+++ b/lisp/font-lock.el
@@ -1564,6 +1564,7 @@ START should be at the beginning of a line."
1564 "Put proper face on each string and comment between START and END. 1564 "Put proper face on each string and comment between START and END.
1565START should be at the beginning of a line." 1565START should be at the beginning of a line."
1566 (syntax-propertize end) ; Apply any needed syntax-table properties. 1566 (syntax-propertize end) ; Apply any needed syntax-table properties.
1567 (with-syntax-table (or syntax-ppss-table (syntax-table))
1567 (let ((comment-end-regexp 1568 (let ((comment-end-regexp
1568 (or font-lock-comment-end-skip 1569 (or font-lock-comment-end-skip
1569 (regexp-quote 1570 (regexp-quote
@@ -1598,7 +1599,7 @@ START should be at the beginning of a line."
1598 font-lock-comment-delimiter-face)))) 1599 font-lock-comment-delimiter-face))))
1599 (< (point) end)) 1600 (< (point) end))
1600 (setq state (parse-partial-sexp (point) end nil nil state 1601 (setq state (parse-partial-sexp (point) end nil nil state
1601 'syntax-table))))) 1602 'syntax-table))))))
1602 1603
1603;;; End of Syntactic fontification functions. 1604;;; End of Syntactic fontification functions.
1604 1605
diff --git a/lisp/gnus/gnus-fun.el b/lisp/gnus/gnus-fun.el
index fa78b5c6e15..a6b27300233 100644
--- a/lisp/gnus/gnus-fun.el
+++ b/lisp/gnus/gnus-fun.el
@@ -44,7 +44,7 @@
44 "Regexp to match faces in `gnus-x-face-directory' to be omitted." 44 "Regexp to match faces in `gnus-x-face-directory' to be omitted."
45 :version "25.1" 45 :version "25.1"
46 :group 'gnus-fun 46 :group 'gnus-fun
47 :type 'string) 47 :type '(choice (const nil) string))
48 48
49(defcustom gnus-face-directory (expand-file-name "faces" gnus-directory) 49(defcustom gnus-face-directory (expand-file-name "faces" gnus-directory)
50 "*Directory where Face PNG files are stored." 50 "*Directory where Face PNG files are stored."
@@ -56,7 +56,7 @@
56 "Regexp to match faces in `gnus-face-directory' to be omitted." 56 "Regexp to match faces in `gnus-face-directory' to be omitted."
57 :version "25.1" 57 :version "25.1"
58 :group 'gnus-fun 58 :group 'gnus-fun
59 :type 'string) 59 :type '(choice (const nil) string))
60 60
61(defcustom gnus-convert-pbm-to-x-face-command "pbmtoxbm %s | compface" 61(defcustom gnus-convert-pbm-to-x-face-command "pbmtoxbm %s | compface"
62 "Command for converting a PBM to an X-Face." 62 "Command for converting a PBM to an X-Face."
diff --git a/lisp/gnus/gnus-util.el b/lisp/gnus/gnus-util.el
index ea5f3155478..31645fcd315 100644
--- a/lisp/gnus/gnus-util.el
+++ b/lisp/gnus/gnus-util.el
@@ -1996,6 +1996,14 @@ to case differences."
1996 (defun gnus-timer--function (timer) 1996 (defun gnus-timer--function (timer)
1997 (elt timer 5))) 1997 (elt timer 5)))
1998 1998
1999(defun gnus-test-list (list predicate)
2000 "To each element of LIST apply PREDICATE.
2001Return nil if LIST is no list or is empty or some test returns nil;
2002otherwise, return t."
2003 (when (and list (listp list))
2004 (let ((result (mapcar predicate list)))
2005 (not (memq nil result)))))
2006
1999(defun gnus-subsetp (list1 list2) 2007(defun gnus-subsetp (list1 list2)
2000 "Return t if LIST1 is a subset of LIST2. 2008 "Return t if LIST1 is a subset of LIST2.
2001Similar to `subsetp' but use member for element test so that this works for 2009Similar to `subsetp' but use member for element test so that this works for
@@ -2006,6 +2014,13 @@ lists of strings."
2006 (gnus-subsetp (cdr list1) list2)) 2014 (gnus-subsetp (cdr list1) list2))
2007 t))) 2015 t)))
2008 2016
2017(defun gnus-setdiff (list1 list2)
2018 "Return member-based set difference of LIST1 and LIST2."
2019 (when (and list1 (listp list1) (listp list2))
2020 (if (member (car list1) list2)
2021 (gnus-setdiff (cdr list1) list2)
2022 (cons (car list1) (gnus-setdiff (cdr list1) list2)))))
2023
2009(provide 'gnus-util) 2024(provide 'gnus-util)
2010 2025
2011;;; gnus-util.el ends here 2026;;; gnus-util.el ends here
diff --git a/lisp/gnus/gnus.el b/lisp/gnus/gnus.el
index 1196ea9dfec..5d2ce7ee19f 100644
--- a/lisp/gnus/gnus.el
+++ b/lisp/gnus/gnus.el
@@ -1637,6 +1637,7 @@ this variable. I think."
1637 (const post-mail)) 1637 (const post-mail))
1638 (checklist :inline t :greedy t 1638 (checklist :inline t :greedy t
1639 (const :format "%v " address) 1639 (const :format "%v " address)
1640 (const cloud)
1640 (const global) 1641 (const global)
1641 (const :format "%v " prompt-address) 1642 (const :format "%v " prompt-address)
1642 (const :format "%v " physical-address) 1643 (const :format "%v " physical-address)
diff --git a/lisp/gnus/mml-sec.el b/lisp/gnus/mml-sec.el
index dbd31629f97..48e6384497e 100644
--- a/lisp/gnus/mml-sec.el
+++ b/lisp/gnus/mml-sec.el
@@ -25,7 +25,9 @@
25 25
26(eval-when-compile (require 'cl)) 26(eval-when-compile (require 'cl))
27 27
28(autoload 'gnus-subsetp "gnus-util") 28(require 'gnus-util)
29(require 'epg)
30
29(autoload 'mail-strip-quoted-names "mail-utils") 31(autoload 'mail-strip-quoted-names "mail-utils")
30(autoload 'mml2015-sign "mml2015") 32(autoload 'mml2015-sign "mml2015")
31(autoload 'mml2015-encrypt "mml2015") 33(autoload 'mml2015-encrypt "mml2015")
@@ -40,6 +42,7 @@
40(autoload 'mml-smime-encrypt-query "mml-smime") 42(autoload 'mml-smime-encrypt-query "mml-smime")
41(autoload 'mml-smime-verify "mml-smime") 43(autoload 'mml-smime-verify "mml-smime")
42(autoload 'mml-smime-verify-test "mml-smime") 44(autoload 'mml-smime-verify-test "mml-smime")
45(autoload 'epa--select-keys "epa")
43 46
44(defvar mml-sign-alist 47(defvar mml-sign-alist
45 '(("smime" mml-smime-sign-buffer mml-smime-sign-query) 48 '(("smime" mml-smime-sign-buffer mml-smime-sign-query)
@@ -91,7 +94,7 @@ signs and encrypt the message in one step.
91 94
92Note that the output generated by using a `combined' mode is NOT 95Note that the output generated by using a `combined' mode is NOT
93understood by all PGP implementations, in particular PGP version 96understood by all PGP implementations, in particular PGP version
942 does not support it! See Info node `(message)Security' for 972 does not support it! See Info node `(message) Security' for
95details." 98details."
96 :version "22.1" 99 :version "22.1"
97 :group 'message 100 :group 'message
@@ -111,7 +114,9 @@ details."
111 (if (boundp 'password-cache) 114 (if (boundp 'password-cache)
112 password-cache 115 password-cache
113 t) 116 t)
114 "If t, cache passphrase." 117 "If t, cache OpenPGP or S/MIME passphrases inside Emacs.
118Passphrase caching in Emacs is NOT recommended. Use gpg-agent instead.
119See Info node `(message) Security'."
115 :group 'message 120 :group 'message
116 :type 'boolean) 121 :type 'boolean)
117 122
@@ -425,6 +430,534 @@ If called with a prefix argument, only encrypt (do NOT sign)."
425 (interactive "P") 430 (interactive "P")
426 (mml-secure-message "pgpauto" (if dontsign 'encrypt 'signencrypt))) 431 (mml-secure-message "pgpauto" (if dontsign 'encrypt 'signencrypt)))
427 432
433;;; Common functionality for mml1991.el, mml2015.el, mml-smime.el
434
435(define-obsolete-variable-alias 'mml1991-signers 'mml-secure-openpgp-signers
436 "25.1")
437(define-obsolete-variable-alias 'mml2015-signers 'mml-secure-openpgp-signers
438 "25.1")
439(defcustom mml-secure-openpgp-signers nil
440 "A list of your own key ID(s) which will be used to sign OpenPGP messages.
441If set, it is added to the setting of `mml-secure-openpgp-sign-with-sender'."
442 :group 'mime-security
443 :type '(repeat (string :tag "Key ID")))
444
445(define-obsolete-variable-alias 'mml-smime-signers 'mml-secure-smime-signers
446 "25.1")
447(defcustom mml-secure-smime-signers nil
448 "A list of your own key ID(s) which will be used to sign S/MIME messages.
449If set, it is added to the setting of `mml-secure-smime-sign-with-sender'."
450 :group 'mime-security
451 :type '(repeat (string :tag "Key ID")))
452
453(define-obsolete-variable-alias
454 'mml1991-encrypt-to-self 'mml-secure-openpgp-encrypt-to-self "25.1")
455(define-obsolete-variable-alias
456 'mml2015-encrypt-to-self 'mml-secure-openpgp-encrypt-to-self "25.1")
457(defcustom mml-secure-openpgp-encrypt-to-self nil
458 "List of own key ID(s) or t; determines additional recipients with OpenPGP.
459If t, also encrypt to key for message sender; if list, encrypt to those keys.
460With this variable, you can ensure that you can decrypt your own messages.
461Alternatives to this variable include Bcc'ing the message to yourself or
462using the encrypt-to or hidden-encrypt-to option in gpg.conf (see man gpg(1)).
463Note that this variable and the encrypt-to option give away your identity
464for *every* encryption without warning, which is not what you want if you are
465using, e.g., remailers.
466Also, use of Bcc gives away your identity for *every* encryption without
467warning, which is a bug, see:
468https://debbugs.gnu.org/cgi/bugreport.cgi?bug=18718"
469 :group 'mime-security
470 :type '(choice (const :tag "None" nil)
471 (const :tag "From address" t)
472 (repeat (string :tag "Key ID"))))
473
474(define-obsolete-variable-alias
475 'mml-smime-encrypt-to-self 'mml-secure-smime-encrypt-to-self "25.1")
476(defcustom mml-secure-smime-encrypt-to-self nil
477 "List of own key ID(s) or t; determines additional recipients with S/MIME.
478If t, also encrypt to key for message sender; if list, encrypt to those keys.
479With this variable, you can ensure that you can decrypt your own messages.
480Alternatives to this variable include Bcc'ing the message to yourself or
481using the encrypt-to option in gpgsm.conf (see man gpgsm(1)).
482Note that this variable and the encrypt-to option give away your identity
483for *every* encryption without warning, which is not what you want if you are
484using, e.g., remailers.
485Also, use of Bcc gives away your identity for *every* encryption without
486warning, which is a bug, see:
487https://debbugs.gnu.org/cgi/bugreport.cgi?bug=18718"
488 :group 'mime-security
489 :type '(choice (const :tag "None" nil)
490 (const :tag "From address" t)
491 (repeat (string :tag "Key ID"))))
492
493(define-obsolete-variable-alias
494 'mml2015-sign-with-sender 'mml-secure-openpgp-sign-with-sender "25.1")
495;mml1991-sign-with-sender did never exist.
496(defcustom mml-secure-openpgp-sign-with-sender nil
497 "If t, use message sender to find an OpenPGP key to sign with."
498 :group 'mime-security
499 :type 'boolean)
500
501(define-obsolete-variable-alias
502 'mml-smime-sign-with-sender 'mml-secure-smime-sign-with-sender "25.1")
503(defcustom mml-secure-smime-sign-with-sender nil
504 "If t, use message sender to find an S/MIME key to sign with."
505 :group 'mime-security
506 :type 'boolean)
507
508(define-obsolete-variable-alias
509 'mml2015-always-trust 'mml-secure-openpgp-always-trust "25.1")
510;mml1991-always-trust did never exist.
511(defcustom mml-secure-openpgp-always-trust t
512 "If t, skip key validation of GnuPG on encryption."
513 :group 'mime-security
514 :type 'boolean)
515
516(defcustom mml-secure-fail-when-key-problem nil
517 "If t, raise an error if some key is missing or several keys exist.
518Otherwise, ask the user."
519 :version "25.1"
520 :group 'mime-security
521 :type 'boolean)
522
523(defcustom mml-secure-key-preferences
524 '((OpenPGP (sign) (encrypt)) (CMS (sign) (encrypt)))
525 "Protocol- and usage-specific fingerprints of preferred keys.
526This variable is only relevant if a recipient owns multiple key pairs (for
527encryption) or you own multiple key pairs (for signing). In such cases,
528you will be asked which key(s) should be used, and your choice can be
529customized in this variable."
530 :version "25.1"
531 :group 'mime-security
532 :type '(alist :key-type (symbol :tag "Protocol") :value-type
533 (alist :key-type (symbol :tag "Usage") :value-type
534 (alist :key-type (string :tag "Name") :value-type
535 (repeat (string :tag "Fingerprint"))))))
536
537(defun mml-secure-cust-usage-lookup (context usage)
538 "Return preferences for CONTEXT and USAGE."
539 (let* ((protocol (epg-context-protocol context))
540 (protocol-prefs (cdr (assoc protocol mml-secure-key-preferences))))
541 (assoc usage protocol-prefs)))
542
543(defun mml-secure-cust-fpr-lookup (context usage name)
544 "Return fingerprints of preferred keys for CONTEXT, USAGE, and NAME."
545 (let* ((usage-prefs (mml-secure-cust-usage-lookup context usage))
546 (fprs (assoc name (cdr usage-prefs))))
547 (when fprs
548 (cdr fprs))))
549
550(defun mml-secure-cust-record-keys (context usage name keys &optional save)
551 "For CONTEXT, USAGE, and NAME record fingerprint(s) of KEYS.
552If optional SAVE is not nil, save customized fingerprints.
553Return keys."
554 (assert keys)
555 (let* ((usage-prefs (mml-secure-cust-usage-lookup context usage))
556 (curr-fprs (cdr (assoc name (cdr usage-prefs))))
557 (key-fprs (mapcar 'mml-secure-fingerprint keys))
558 (new-fprs (gnus-union curr-fprs key-fprs :test 'equal)))
559 (if curr-fprs
560 (setcdr (assoc name (cdr usage-prefs)) new-fprs)
561 (setcdr usage-prefs (cons (cons name new-fprs) (cdr usage-prefs))))
562 (when save
563 (customize-save-variable
564 'mml-secure-key-preferences mml-secure-key-preferences))
565 keys))
566
567(defun mml-secure-cust-remove-keys (context usage name)
568 "Remove keys for CONTEXT, USAGE, and NAME.
569Return t if a customization for NAME was present (and has been removed)."
570 (let* ((usage-prefs (mml-secure-cust-usage-lookup context usage))
571 (current (assoc name usage-prefs)))
572 (when current
573 (setcdr usage-prefs (remove current (cdr usage-prefs)))
574 t)))
575
576(defvar mml-secure-secret-key-id-list nil)
577
578(defun mml-secure-add-secret-key-id (key-id)
579 "Record KEY-ID in list of secret keys."
580 (add-to-list 'mml-secure-secret-key-id-list key-id))
581
582(defun mml-secure-clear-secret-key-id-list ()
583 "Remove passwords from cache and clear list of secret keys."
584 ;; Loosely based on code inside mml2015-epg-encrypt,
585 ;; mml2015-epg-clear-decrypt, and mml2015-epg-decrypt
586 (dolist (key-id mml-secure-secret-key-id-list nil)
587 (password-cache-remove key-id))
588 (setq mml-secure-secret-key-id-list nil))
589
590(defvar mml1991-cache-passphrase)
591(defvar mml1991-passphrase-cache-expiry)
592
593(defun mml-secure-cache-passphrase-p (protocol)
594 "Return t if OpenPGP or S/MIME passphrases should be cached for PROTOCOL.
595Passphrase caching in Emacs is NOT recommended. Use gpg-agent instead."
596 (or (and (eq 'OpenPGP protocol)
597 (or mml-secure-cache-passphrase
598 (and (boundp 'mml2015-cache-passphrase)
599 mml2015-cache-passphrase)
600 (and (boundp 'mml1991-cache-passphrase)
601 mml1991-cache-passphrase)))
602 (and (eq 'CMS protocol)
603 (or mml-secure-cache-passphrase
604 (and (boundp 'mml-smime-cache-passphrase)
605 mml-smime-cache-passphrase)))))
606
607(defun mml-secure-cache-expiry-interval (protocol)
608 "Return time in seconds to cache passphrases for PROTOCOL.
609Passphrase caching in Emacs is NOT recommended. Use gpg-agent instead."
610 (or (and (eq 'OpenPGP protocol)
611 (or (and (boundp 'mml2015-passphrase-cache-expiry)
612 mml2015-passphrase-cache-expiry)
613 (and (boundp 'mml1991-passphrase-cache-expiry)
614 mml1991-passphrase-cache-expiry)
615 mml-secure-passphrase-cache-expiry))
616 (and (eq 'CMS protocol)
617 (or (and (boundp 'mml-smime-passphrase-cache-expiry)
618 mml-smime-passphrase-cache-expiry)
619 mml-secure-passphrase-cache-expiry))))
620
621(defun mml-secure-passphrase-callback (context key-id standard)
622 "Ask for passphrase in CONTEXT for KEY-ID for STANDARD.
623The passphrase is read and cached."
624 ;; Based on mml2015-epg-passphrase-callback.
625 (if (eq key-id 'SYM)
626 (epg-passphrase-callback-function context key-id nil)
627 (let* ((password-cache-key-id
628 (if (eq key-id 'PIN)
629 "PIN"
630 key-id))
631 (entry (assoc key-id epg-user-id-alist))
632 (passphrase
633 (password-read
634 (if (eq key-id 'PIN)
635 "Passphrase for PIN: "
636 (if entry
637 (format "Passphrase for %s %s: " key-id (cdr entry))
638 (format "Passphrase for %s: " key-id)))
639 ;; TODO: With mml-smime.el, password-cache-key-id is not passed
640 ;; as argument to password-read.
641 ;; Is that on purpose? If so, the following needs to be placed
642 ;; inside an if statement.
643 password-cache-key-id)))
644 (when passphrase
645 (let ((password-cache-expiry (mml-secure-cache-expiry-interval
646 (epg-context-protocol context))))
647 (password-cache-add password-cache-key-id passphrase))
648 (mml-secure-add-secret-key-id password-cache-key-id)
649 (copy-sequence passphrase)))))
650
651(defun mml-secure-check-user-id (key recipient)
652 "Check whether KEY has a non-revoked, non-expired UID for RECIPIENT."
653 ;; Based on mml2015-epg-check-user-id.
654 (let ((uids (epg-key-user-id-list key)))
655 (catch 'break
656 (dolist (uid uids nil)
657 (if (and (stringp (epg-user-id-string uid))
658 (equal (car (mail-header-parse-address
659 (epg-user-id-string uid)))
660 (car (mail-header-parse-address
661 recipient)))
662 (not (memq (epg-user-id-validity uid)
663 '(revoked expired))))
664 (throw 'break t))))))
665
666(defun mml-secure-secret-key-exists-p (context subkey)
667 "Return t if keyring for CONTEXT contains secret key for public SUBKEY."
668 (let* ((fpr (epg-sub-key-fingerprint subkey))
669 (candidates (epg-list-keys context fpr 'secret))
670 (candno (length candidates)))
671 ;; If two or more subkeys with the same fingerprint exist, something is
672 ;; terribly wrong.
673 (when (>= candno 2)
674 (error "Found %d secret keys with same fingerprint %s" candno fpr))
675 (= 1 candno)))
676
677(defun mml-secure-check-sub-key (context key usage &optional fingerprint)
678 "Check whether in CONTEXT the public KEY has a usable subkey for USAGE.
679This is the case if KEY is not disabled, and there is a subkey for
680USAGE that is neither revoked nor expired. Additionally, if optional
681FINGERPRINT is present and if it is not the primary key's fingerprint, then
682the returned subkey must have that FINGERPRINT. FINGERPRINT must consist of
683hexadecimal digits only (no leading \"0x\" allowed).
684If USAGE is not `encrypt', then additionally an appropriate secret key must
685be present in the keyring."
686 ;; Based on mml2015-epg-check-sub-key, extended by
687 ;; - check for secret keys if usage is not 'encrypt and
688 ;; - check for new argument FINGERPRINT.
689 (let* ((subkeys (epg-key-sub-key-list key))
690 (primary (car subkeys))
691 (fpr (epg-sub-key-fingerprint primary)))
692 ;; The primary key will be marked as disabled, when the entire
693 ;; key is disabled (see 12 Field, Format of colon listings, in
694 ;; gnupg/doc/DETAILS)
695 (unless (memq 'disabled (epg-sub-key-capability primary))
696 (catch 'break
697 (dolist (subkey subkeys nil)
698 (if (and (memq usage (epg-sub-key-capability subkey))
699 (not (memq (epg-sub-key-validity subkey)
700 '(revoked expired)))
701 (or (eq 'encrypt usage) ; Encryption works with public key.
702 ;; In contrast, signing requires secret key.
703 (mml-secure-secret-key-exists-p context subkey))
704 (or (not fingerprint)
705 (gnus-string-match-p (concat fingerprint "$") fpr)
706 (gnus-string-match-p (concat fingerprint "$")
707 (epg-sub-key-fingerprint subkey))))
708 (throw 'break t)))))))
709
710(defun mml-secure-find-usable-keys (context name usage &optional justone)
711 "In CONTEXT return a list of keys for NAME and USAGE.
712If USAGE is `encrypt' public keys are returned, otherwise secret ones.
713Only non-revoked and non-expired keys are returned whose primary key is
714not disabled.
715NAME can be an e-mail address or a key ID.
716If NAME just consists of hexadecimal digits (possibly prefixed by \"0x\"), it
717is treated as key ID for which at most one key must exist in the keyring.
718Otherwise, NAME is treated as user ID, for which no keys are returned if it
719is expired or revoked.
720If optional JUSTONE is not nil, return the first key instead of a list."
721 (let* ((keys (epg-list-keys context name))
722 (iskeyid (string-match "\\(0x\\)?\\([0-9a-fA-F]\\{8,\\}\\)" name))
723 (fingerprint (match-string 2 name))
724 result)
725 (when (and iskeyid (>= (length keys) 2))
726 (error
727 "Name %s (for %s) looks like a key ID but multiple keys found"
728 name usage))
729 (catch 'break
730 (dolist (key keys result)
731 (if (and (or iskeyid
732 (mml-secure-check-user-id key name))
733 (mml-secure-check-sub-key context key usage fingerprint))
734 (if justone
735 (throw 'break key)
736 (push key result)))))))
737
738(defun mml-secure-select-preferred-keys (context names usage)
739 "Return list of preferred keys in CONTEXT for NAMES and USAGE.
740This inspects the keyrings to find keys for each name in NAMES. If several
741keys are found for a name, `mml-secure-select-keys' is used to look for
742customized preferences or have the user select preferable ones.
743When `mml-secure-fail-when-key-problem' is t, fail with an error in
744case of missing, outdated, or multiple keys."
745 ;; Loosely based on code appearing inside mml2015-epg-sign and
746 ;; mml2015-epg-encrypt.
747 (apply
748 #'nconc
749 (mapcar
750 (lambda (name)
751 (let* ((keys (mml-secure-find-usable-keys context name usage))
752 (keyno (length keys)))
753 (cond ((= 0 keyno)
754 (when (or mml-secure-fail-when-key-problem
755 (not (y-or-n-p
756 (format "No %s key for %s; skip it? "
757 usage name))))
758 (error "No %s key for %s" usage name)))
759 ((= 1 keyno) keys)
760 (t (mml-secure-select-keys context name keys usage)))))
761 names)))
762
763(defun mml-secure-fingerprint (key)
764 "Return fingerprint for public KEY."
765 (epg-sub-key-fingerprint (car (epg-key-sub-key-list key))))
766
767(defun mml-secure-filter-keys (keys fprs)
768 "Filter KEYS to subset with fingerprints in FPRS."
769 (when keys
770 (if (member (mml-secure-fingerprint (car keys)) fprs)
771 (cons (car keys) (mml-secure-filter-keys (cdr keys) fprs))
772 (mml-secure-filter-keys (cdr keys) fprs))))
773
774(defun mml-secure-normalize-cust-name (name)
775 "Normalize NAME to be used for customization.
776Currently, remove ankle brackets."
777 (if (string-match "^<\\(.*\\)>$" name)
778 (match-string 1 name)
779 name))
780
781(defun mml-secure-select-keys (context name keys usage)
782 "In CONTEXT for NAME select among KEYS for USAGE.
783KEYS should be a list with multiple entries.
784NAME is normalized first as customized keys are inspected.
785When `mml-secure-fail-when-key-problem' is t, fail with an error in case of
786outdated or multiple keys."
787 (let* ((nname (mml-secure-normalize-cust-name name))
788 (fprs (mml-secure-cust-fpr-lookup context usage nname))
789 (usable-fprs (mapcar 'mml-secure-fingerprint keys)))
790 (if fprs
791 (if (gnus-subsetp fprs usable-fprs)
792 (mml-secure-filter-keys keys fprs)
793 (mml-secure-cust-remove-keys context usage nname)
794 (let ((diff (gnus-setdiff fprs usable-fprs)))
795 (if mml-secure-fail-when-key-problem
796 (error "Customization of %s keys for %s outdated" usage nname)
797 (mml-secure-select-keys-1
798 context nname keys usage (format "\
799Customized keys
800 (%s)
801for %s not available any more.
802Select anew. "
803 diff nname)))))
804 (if mml-secure-fail-when-key-problem
805 (error "Multiple %s keys for %s" usage nname)
806 (mml-secure-select-keys-1
807 context nname keys usage (format "\
808Multiple %s keys for:
809 %s
810Select preferred one(s). "
811 usage nname))))))
812
813(defun mml-secure-select-keys-1 (context name keys usage message)
814 "In CONTEXT for NAME let user select among KEYS for USAGE, showing MESSAGE.
815Return selected keys."
816 (let* ((selected (epa--select-keys message keys))
817 (selno (length selected))
818 ;; TODO: y-or-n-p does not always resize the echo area but may
819 ;; truncate the message. Why? The following does not help.
820 ;; yes-or-no-p shows full message, though.
821 (message-truncate-lines nil))
822 (if selected
823 (if (y-or-n-p
824 (format "%d %s key(s) selected. Store for %s? "
825 selno usage name))
826 (mml-secure-cust-record-keys context usage name selected 'save)
827 selected)
828 (unless (y-or-n-p
829 (format "No %s key for %s; skip it? " usage name))
830 (error "No %s key for %s" usage name)))))
831
832(defun mml-secure-signer-names (protocol sender)
833 "Determine signer names for PROTOCOL and message from SENDER.
834Returned names may be e-mail addresses or key IDs and are determined based
835on `mml-secure-openpgp-signers' and `mml-secure-openpgp-sign-with-sender' with
836OpenPGP or `mml-secure-smime-signers' and `mml-secure-smime-sign-with-sender'
837with S/MIME."
838 (if (eq 'OpenPGP protocol)
839 (append mml-secure-openpgp-signers
840 (if (and mml-secure-openpgp-sign-with-sender sender)
841 (list (concat "<" sender ">"))))
842 (append mml-secure-smime-signers
843 (if (and mml-secure-smime-sign-with-sender sender)
844 (list (concat "<" sender ">"))))))
845
846(defun mml-secure-signers (context signer-names)
847 "Determine signing keys in CONTEXT from SIGNER-NAMES.
848If `mm-sign-option' is `guided', the user is asked to choose.
849Otherwise, `mml-secure-select-preferred-keys' is used."
850 ;; Based on code appearing inside mml2015-epg-sign and
851 ;; mml2015-epg-encrypt.
852 (if (eq mm-sign-option 'guided)
853 (epa-select-keys context "\
854Select keys for signing.
855If no one is selected, default secret key is used. "
856 signer-names t)
857 (mml-secure-select-preferred-keys context signer-names 'sign)))
858
859(defun mml-secure-self-recipients (protocol sender)
860 "Determine additional recipients based on encrypt-to-self variables.
861PROTOCOL specifies OpenPGP or S/MIME for a message from SENDER."
862 (let ((encrypt-to-self
863 (if (eq 'OpenPGP protocol)
864 mml-secure-openpgp-encrypt-to-self
865 mml-secure-smime-encrypt-to-self)))
866 (when encrypt-to-self
867 (if (listp encrypt-to-self)
868 encrypt-to-self
869 (list sender)))))
870
871(defun mml-secure-recipients (protocol context config sender)
872 "Determine encryption recipients.
873PROTOCOL specifies OpenPGP or S/MIME with matching CONTEXT and CONFIG
874for a message from SENDER."
875 ;; Based on code appearing inside mml2015-epg-encrypt.
876 (let ((recipients
877 (apply #'nconc
878 (mapcar
879 (lambda (recipient)
880 (or (epg-expand-group config recipient)
881 (list (concat "<" recipient ">"))))
882 (split-string
883 (or (message-options-get 'message-recipients)
884 (message-options-set 'message-recipients
885 (read-string "Recipients: ")))
886 "[ \f\t\n\r\v,]+")))))
887 (nconc recipients (mml-secure-self-recipients protocol sender))
888 (if (eq mm-encrypt-option 'guided)
889 (setq recipients
890 (epa-select-keys context "\
891Select recipients for encryption.
892If no one is selected, symmetric encryption will be performed. "
893 recipients))
894 (setq recipients
895 (mml-secure-select-preferred-keys context recipients 'encrypt))
896 (unless recipients
897 (error "No recipient specified")))
898 recipients))
899
900(defun mml-secure-epg-encrypt (protocol cont &optional sign)
901 ;; Based on code appearing inside mml2015-epg-encrypt.
902 (let* ((context (epg-make-context protocol))
903 (config (epg-configuration))
904 (sender (message-options-get 'message-sender))
905 (recipients (mml-secure-recipients protocol context config sender))
906 (signer-names (mml-secure-signer-names protocol sender))
907 cipher signers)
908 (when sign
909 (setq signers (mml-secure-signers context signer-names))
910 (epg-context-set-signers context signers))
911 (when (eq 'OpenPGP protocol)
912 (epg-context-set-armor context t)
913 (epg-context-set-textmode context t))
914 (when (mml-secure-cache-passphrase-p protocol)
915 (epg-context-set-passphrase-callback
916 context
917 (cons 'mml-secure-passphrase-callback protocol)))
918 (condition-case error
919 (setq cipher
920 (if (eq 'OpenPGP protocol)
921 (epg-encrypt-string context (buffer-string) recipients sign
922 mml-secure-openpgp-always-trust)
923 (epg-encrypt-string context (buffer-string) recipients))
924 mml-secure-secret-key-id-list nil)
925 (error
926 (mml-secure-clear-secret-key-id-list)
927 (signal (car error) (cdr error))))
928 cipher))
929
930(defun mml-secure-epg-sign (protocol mode)
931 ;; Based on code appearing inside mml2015-epg-sign.
932 (let* ((context (epg-make-context protocol))
933 (sender (message-options-get 'message-sender))
934 (signer-names (mml-secure-signer-names protocol sender))
935 (signers (mml-secure-signers context signer-names))
936 signature micalg)
937 (when (eq 'OpenPGP protocol)
938 (epg-context-set-armor context t)
939 (epg-context-set-textmode context t))
940 (epg-context-set-signers context signers)
941 (when (mml-secure-cache-passphrase-p protocol)
942 (epg-context-set-passphrase-callback
943 context
944 (cons 'mml-secure-passphrase-callback protocol)))
945 (condition-case error
946 (setq signature
947 (if (eq 'OpenPGP protocol)
948 (epg-sign-string context (buffer-string) mode)
949 (epg-sign-string context
950 (mm-replace-in-string (buffer-string)
951 "\n" "\r\n") t))
952 mml-secure-secret-key-id-list nil)
953 (error
954 (mml-secure-clear-secret-key-id-list)
955 (signal (car error) (cdr error))))
956 (if (epg-context-result-for context 'sign)
957 (setq micalg (epg-new-signature-digest-algorithm
958 (car (epg-context-result-for context 'sign)))))
959 (cons signature micalg)))
960
428(provide 'mml-sec) 961(provide 'mml-sec)
429 962
430;;; mml-sec.el ends here 963;;; mml-sec.el ends here
diff --git a/lisp/gnus/mml-smime.el b/lisp/gnus/mml-smime.el
index b19c9e89ba9..2d8f25c5003 100644
--- a/lisp/gnus/mml-smime.el
+++ b/lisp/gnus/mml-smime.el
@@ -32,9 +32,17 @@
32(autoload 'message-narrow-to-headers "message") 32(autoload 'message-narrow-to-headers "message")
33(autoload 'message-fetch-field "message") 33(autoload 'message-fetch-field "message")
34 34
35;; Prefer epg over openssl if it is available as epg uses GnuPG's gpgsm,
36;; which features full-fledged certificate management, while openssl requires
37;; major manual efforts for certificate revocation and expiry and has bugs
38;; as documented under man smime(1).
39(ignore-errors (require 'epg))
40
35(defcustom mml-smime-use (if (featurep 'epg) 'epg 'openssl) 41(defcustom mml-smime-use (if (featurep 'epg) 'epg 'openssl)
36 "Whether to use OpenSSL or EPG to decrypt S/MIME messages. 42 "Whether to use OpenSSL or EasyPG (EPG) to handle S/MIME messages.
37Defaults to EPG if it's loaded." 43Defaults to EPG if it's available.
44If you think about using OpenSSL, please read the BUGS section in the manual
45for the `smime' command coming with OpenSSL first. EasyPG is recommended."
38 :group 'mime-security 46 :group 'mime-security
39 :type '(choice (const :tag "EPG" epg) 47 :type '(choice (const :tag "EPG" epg)
40 (const :tag "OpenSSL" openssl))) 48 (const :tag "OpenSSL" openssl)))
@@ -57,6 +65,9 @@ Defaults to EPG if it's loaded."
57 "If t, cache passphrase." 65 "If t, cache passphrase."
58 :group 'mime-security 66 :group 'mime-security
59 :type 'boolean) 67 :type 'boolean)
68(make-obsolete-variable 'mml-smime-cache-passphrase
69 'mml-secure-cache-passphrase
70 "25.1")
60 71
61(defcustom mml-smime-passphrase-cache-expiry mml-secure-passphrase-cache-expiry 72(defcustom mml-smime-passphrase-cache-expiry mml-secure-passphrase-cache-expiry
62 "How many seconds the passphrase is cached. 73 "How many seconds the passphrase is cached.
@@ -64,6 +75,9 @@ Whether the passphrase is cached at all is controlled by
64`mml-smime-cache-passphrase'." 75`mml-smime-cache-passphrase'."
65 :group 'mime-security 76 :group 'mime-security
66 :type 'integer) 77 :type 'integer)
78(make-obsolete-variable 'mml-smime-passphrase-cache-expiry
79 'mml-secure-passphrase-cache-expiry
80 "25.1")
67 81
68(defcustom mml-smime-signers nil 82(defcustom mml-smime-signers nil
69 "A list of your own key ID which will be used to sign a message." 83 "A list of your own key ID which will be used to sign a message."
@@ -202,7 +216,7 @@ Whether the passphrase is cached at all is controlled by
202 ""))))) 216 "")))))
203 (if (setq cert (smime-cert-by-dns who)) 217 (if (setq cert (smime-cert-by-dns who))
204 (setq result (list 'certfile (buffer-name cert))) 218 (setq result (list 'certfile (buffer-name cert)))
205 (setq bad (gnus-format-message "`%s' not found. " who)))) 219 (setq bad (format "`%s' not found. " who))))
206 (quit)) 220 (quit))
207 result)) 221 result))
208 222
@@ -221,7 +235,7 @@ Whether the passphrase is cached at all is controlled by
221 ""))))) 235 "")))))
222 (if (setq cert (smime-cert-by-ldap who)) 236 (if (setq cert (smime-cert-by-ldap who))
223 (setq result (list 'certfile (buffer-name cert))) 237 (setq result (list 'certfile (buffer-name cert)))
224 (setq bad (gnus-format-message "`%s' not found. " who)))) 238 (setq bad (format "`%s' not found. " who))))
225 (quit)) 239 (quit))
226 result)) 240 result))
227 241
@@ -317,83 +331,29 @@ Whether the passphrase is cached at all is controlled by
317(defvar inhibit-redisplay) 331(defvar inhibit-redisplay)
318(defvar password-cache-expiry) 332(defvar password-cache-expiry)
319 333
320(autoload 'epg-make-context "epg") 334(eval-when-compile
321(autoload 'epg-passphrase-callback-function "epg") 335 (autoload 'epg-make-context "epg")
322(declare-function epg-context-set-signers "epg" (context signers)) 336 (autoload 'epg-context-set-armor "epg")
323(declare-function epg-context-result-for "epg" (context name)) 337 (autoload 'epg-context-set-signers "epg")
324(declare-function epg-new-signature-digest-algorithm "epg" (cl-x) t) 338 (autoload 'epg-context-result-for "epg")
325(declare-function epg-verify-result-to-string "epg" (verify-result)) 339 (autoload 'epg-new-signature-digest-algorithm "epg")
326(declare-function epg-list-keys "epg" (context &optional name mode)) 340 (autoload 'epg-verify-result-to-string "epg")
327(declare-function epg-verify-string "epg" 341 (autoload 'epg-list-keys "epg")
328 (context signature &optional signed-text)) 342 (autoload 'epg-decrypt-string "epg")
329(declare-function epg-sign-string "epg" (context plain &optional mode)) 343 (autoload 'epg-verify-string "epg")
330(declare-function epg-encrypt-string "epg" 344 (autoload 'epg-sign-string "epg")
331 (context plain recipients &optional sign always-trust)) 345 (autoload 'epg-encrypt-string "epg")
332(declare-function epg-context-set-passphrase-callback "epg" 346 (autoload 'epg-passphrase-callback-function "epg")
333 (context passphrase-callback)) 347 (autoload 'epg-context-set-passphrase-callback "epg")
334(declare-function epg-sub-key-fingerprint "epg" (cl-x) t) 348 (autoload 'epg-sub-key-fingerprint "epg")
335(declare-function epg-configuration "epg-config" ()) 349 (autoload 'epg-configuration "epg-config")
336(declare-function epg-expand-group "epg-config" (config group)) 350 (autoload 'epg-expand-group "epg-config")
337(declare-function epa-select-keys "epa" 351 (autoload 'epa-select-keys "epa"))
338 (context prompt &optional names secret))
339
340(defvar mml-smime-epg-secret-key-id-list nil)
341
342(defun mml-smime-epg-passphrase-callback (context key-id ignore)
343 (if (eq key-id 'SYM)
344 (epg-passphrase-callback-function context key-id nil)
345 (let* (entry
346 (passphrase
347 (password-read
348 (if (eq key-id 'PIN)
349 "Passphrase for PIN: "
350 (if (setq entry (assoc key-id epg-user-id-alist))
351 (format "Passphrase for %s %s: " key-id (cdr entry))
352 (format "Passphrase for %s: " key-id)))
353 (if (eq key-id 'PIN)
354 "PIN"
355 key-id))))
356 (when passphrase
357 (let ((password-cache-expiry mml-smime-passphrase-cache-expiry))
358 (password-cache-add key-id passphrase))
359 (setq mml-smime-epg-secret-key-id-list
360 (cons key-id mml-smime-epg-secret-key-id-list))
361 (copy-sequence passphrase)))))
362 352
363(declare-function epg-key-sub-key-list "epg" (key) t) 353(declare-function epg-key-sub-key-list "epg" (key) t)
364(declare-function epg-sub-key-capability "epg" (sub-key) t) 354(declare-function epg-sub-key-capability "epg" (sub-key) t)
365(declare-function epg-sub-key-validity "epg" (sub-key) t) 355(declare-function epg-sub-key-validity "epg" (sub-key) t)
366 356
367(defun mml-smime-epg-find-usable-key (keys usage)
368 (catch 'found
369 (while keys
370 (let ((pointer (epg-key-sub-key-list (car keys))))
371 (while pointer
372 (if (and (memq usage (epg-sub-key-capability (car pointer)))
373 (not (memq (epg-sub-key-validity (car pointer))
374 '(revoked expired))))
375 (throw 'found (car keys)))
376 (setq pointer (cdr pointer))))
377 (setq keys (cdr keys)))))
378
379;; XXX: since gpg --list-secret-keys does not return validity of each
380;; key, `mml-smime-epg-find-usable-key' defined above is not enough for
381;; secret keys. The function `mml-smime-epg-find-usable-secret-key'
382;; below looks at appropriate public keys to check usability.
383(defun mml-smime-epg-find-usable-secret-key (context name usage)
384 (let ((secret-keys (epg-list-keys context name t))
385 secret-key)
386 (while (and (not secret-key) secret-keys)
387 (if (mml-smime-epg-find-usable-key
388 (epg-list-keys context (epg-sub-key-fingerprint
389 (car (epg-key-sub-key-list
390 (car secret-keys)))))
391 usage)
392 (setq secret-key (car secret-keys)
393 secret-keys nil)
394 (setq secret-keys (cdr secret-keys))))
395 secret-key))
396
397(autoload 'mml-compute-boundary "mml") 357(autoload 'mml-compute-boundary "mml")
398 358
399;; We require mm-decode, which requires mm-bodies, which autoloads 359;; We require mm-decode, which requires mm-bodies, which autoloads
@@ -401,146 +361,37 @@ Whether the passphrase is cached at all is controlled by
401(declare-function message-options-set "message" (symbol value)) 361(declare-function message-options-set "message" (symbol value))
402 362
403(defun mml-smime-epg-sign (cont) 363(defun mml-smime-epg-sign (cont)
404 (let* ((inhibit-redisplay t) 364 (let ((inhibit-redisplay t)
405 (context (epg-make-context 'CMS)) 365 (boundary (mml-compute-boundary cont)))
406 (boundary (mml-compute-boundary cont))
407 (sender (message-options-get 'message-sender))
408 (signer-names (or mml-smime-signers
409 (if (and mml-smime-sign-with-sender sender)
410 (list (concat "<" sender ">")))))
411 signer-key
412 (signers
413 (or (message-options-get 'mml-smime-epg-signers)
414 (message-options-set
415 'mml-smime-epg-signers
416 (if (eq mm-sign-option 'guided)
417 (epa-select-keys context "\
418Select keys for signing.
419If no one is selected, default secret key is used. "
420 signer-names
421 t)
422 (if (or sender mml-smime-signers)
423 (delq nil
424 (mapcar
425 (lambda (signer)
426 (setq signer-key
427 (mml-smime-epg-find-usable-secret-key
428 context signer 'sign))
429 (unless (or signer-key
430 (y-or-n-p
431 (format
432 "No secret key for %s; skip it? "
433 signer)))
434 (error "No secret key for %s" signer))
435 signer-key)
436 signer-names)))))))
437 signature micalg)
438 (epg-context-set-signers context signers)
439 (if mml-smime-cache-passphrase
440 (epg-context-set-passphrase-callback
441 context
442 #'mml-smime-epg-passphrase-callback))
443 (condition-case error
444 (setq signature (epg-sign-string context
445 (mm-replace-in-string (buffer-string)
446 "\n" "\r\n")
447 t)
448 mml-smime-epg-secret-key-id-list nil)
449 (error
450 (while mml-smime-epg-secret-key-id-list
451 (password-cache-remove (car mml-smime-epg-secret-key-id-list))
452 (setq mml-smime-epg-secret-key-id-list
453 (cdr mml-smime-epg-secret-key-id-list)))
454 (signal (car error) (cdr error))))
455 (if (epg-context-result-for context 'sign)
456 (setq micalg (epg-new-signature-digest-algorithm
457 (car (epg-context-result-for context 'sign)))))
458 (goto-char (point-min)) 366 (goto-char (point-min))
459 (insert (format "Content-Type: multipart/signed; boundary=\"%s\";\n" 367 (let* ((pair (mml-secure-epg-sign 'CMS cont))
460 boundary)) 368 (signature (car pair))
461 (if micalg 369 (micalg (cdr pair)))
462 (insert (format "\tmicalg=%s; " 370 (insert (format "Content-Type: multipart/signed; boundary=\"%s\";\n"
463 (downcase 371 boundary))
464 (cdr (assq micalg 372 (if micalg
465 epg-digest-algorithm-alist)))))) 373 (insert (format "\tmicalg=%s; "
466 (insert "protocol=\"application/pkcs7-signature\"\n") 374 (downcase
467 (insert (format "\n--%s\n" boundary)) 375 (cdr (assq micalg
468 (goto-char (point-max)) 376 epg-digest-algorithm-alist))))))
469 (insert (format "\n--%s\n" boundary)) 377 (insert "protocol=\"application/pkcs7-signature\"\n")
470 (insert "Content-Type: application/pkcs7-signature; name=smime.p7s 378 (insert (format "\n--%s\n" boundary))
379 (goto-char (point-max))
380 (insert (format "\n--%s\n" boundary))
381 (insert "Content-Type: application/pkcs7-signature; name=smime.p7s
471Content-Transfer-Encoding: base64 382Content-Transfer-Encoding: base64
472Content-Disposition: attachment; filename=smime.p7s 383Content-Disposition: attachment; filename=smime.p7s
473 384
474") 385")
475 (insert (base64-encode-string signature) "\n") 386 (insert (base64-encode-string signature) "\n")
476 (goto-char (point-max)) 387 (goto-char (point-max))
477 (insert (format "--%s--\n" boundary)) 388 (insert (format "--%s--\n" boundary))
478 (goto-char (point-max)))) 389 (goto-char (point-max)))))
479 390
480(defun mml-smime-epg-encrypt (cont) 391(defun mml-smime-epg-encrypt (cont)
481 (let* ((inhibit-redisplay t) 392 (let* ((inhibit-redisplay t)
482 (context (epg-make-context 'CMS))
483 (config (epg-configuration))
484 (recipients (message-options-get 'mml-smime-epg-recipients))
485 cipher signers
486 (sender (message-options-get 'message-sender))
487 (signer-names (or mml-smime-signers
488 (if (and mml-smime-sign-with-sender sender)
489 (list (concat "<" sender ">")))))
490 (boundary (mml-compute-boundary cont)) 393 (boundary (mml-compute-boundary cont))
491 recipient-key) 394 (cipher (mml-secure-epg-encrypt 'CMS cont)))
492 (unless recipients
493 (setq recipients
494 (apply #'nconc
495 (mapcar
496 (lambda (recipient)
497 (or (epg-expand-group config recipient)
498 (list recipient)))
499 (split-string
500 (or (message-options-get 'message-recipients)
501 (message-options-set 'message-recipients
502 (read-string "Recipients: ")))
503 "[ \f\t\n\r\v,]+"))))
504 (when mml-smime-encrypt-to-self
505 (unless signer-names
506 (error "Neither message sender nor mml-smime-signers are set"))
507 (setq recipients (nconc recipients signer-names)))
508 (if (eq mm-encrypt-option 'guided)
509 (setq recipients
510 (epa-select-keys context "\
511Select recipients for encryption.
512If no one is selected, symmetric encryption will be performed. "
513 recipients))
514 (setq recipients
515 (mapcar
516 (lambda (recipient)
517 (setq recipient-key (mml-smime-epg-find-usable-key
518 (epg-list-keys context recipient)
519 'encrypt))
520 (unless (or recipient-key
521 (y-or-n-p
522 (format "No public key for %s; skip it? "
523 recipient)))
524 (error "No public key for %s" recipient))
525 recipient-key)
526 recipients))
527 (unless recipients
528 (error "No recipient specified")))
529 (message-options-set 'mml-smime-epg-recipients recipients))
530 (if mml-smime-cache-passphrase
531 (epg-context-set-passphrase-callback
532 context
533 #'mml-smime-epg-passphrase-callback))
534 (condition-case error
535 (setq cipher
536 (epg-encrypt-string context (buffer-string) recipients)
537 mml-smime-epg-secret-key-id-list nil)
538 (error
539 (while mml-smime-epg-secret-key-id-list
540 (password-cache-remove (car mml-smime-epg-secret-key-id-list))
541 (setq mml-smime-epg-secret-key-id-list
542 (cdr mml-smime-epg-secret-key-id-list)))
543 (signal (car error) (cdr error))))
544 (delete-region (point-min) (point-max)) 395 (delete-region (point-min) (point-max))
545 (goto-char (point-min)) 396 (goto-char (point-min))
546 (insert "\ 397 (insert "\
diff --git a/lisp/gnus/mml1991.el b/lisp/gnus/mml1991.el
index 6469636451f..bb5c940f173 100644
--- a/lisp/gnus/mml1991.el
+++ b/lisp/gnus/mml1991.el
@@ -63,11 +63,17 @@
63 63
64(defvar mml1991-cache-passphrase mml-secure-cache-passphrase 64(defvar mml1991-cache-passphrase mml-secure-cache-passphrase
65 "If t, cache passphrase.") 65 "If t, cache passphrase.")
66(make-obsolete-variable 'mml1991-cache-passphrase
67 'mml-secure-cache-passphrase
68 "25.1")
66 69
67(defvar mml1991-passphrase-cache-expiry mml-secure-passphrase-cache-expiry 70(defvar mml1991-passphrase-cache-expiry mml-secure-passphrase-cache-expiry
68 "How many seconds the passphrase is cached. 71 "How many seconds the passphrase is cached.
69Whether the passphrase is cached at all is controlled by 72Whether the passphrase is cached at all is controlled by
70`mml1991-cache-passphrase'.") 73`mml1991-cache-passphrase'.")
74(make-obsolete-variable 'mml1991-passphrase-cache-expiry
75 'mml-secure-passphrase-cache-expiry
76 "25.1")
71 77
72(defvar mml1991-signers nil 78(defvar mml1991-signers nil
73 "A list of your own key ID which will be used to sign a message.") 79 "A list of your own key ID which will be used to sign a message.")
@@ -75,6 +81,7 @@ Whether the passphrase is cached at all is controlled by
75(defvar mml1991-encrypt-to-self nil 81(defvar mml1991-encrypt-to-self nil
76 "If t, add your own key ID to recipient list when encryption.") 82 "If t, add your own key ID to recipient list when encryption.")
77 83
84
78;;; mailcrypt wrapper 85;;; mailcrypt wrapper
79 86
80(autoload 'mc-sign-generic "mc-toplev") 87(autoload 'mc-sign-generic "mc-toplev")
@@ -255,91 +262,9 @@ Whether the passphrase is cached at all is controlled by
255(autoload 'epg-configuration "epg-config") 262(autoload 'epg-configuration "epg-config")
256(autoload 'epg-expand-group "epg-config") 263(autoload 'epg-expand-group "epg-config")
257 264
258(defvar mml1991-epg-secret-key-id-list nil)
259
260(defun mml1991-epg-passphrase-callback (context key-id ignore)
261 (if (eq key-id 'SYM)
262 (epg-passphrase-callback-function context key-id nil)
263 (let* ((entry (assoc key-id epg-user-id-alist))
264 (passphrase
265 (password-read
266 (format "GnuPG passphrase for %s: "
267 (if entry
268 (cdr entry)
269 key-id))
270 (if (eq key-id 'PIN)
271 "PIN"
272 key-id))))
273 (when passphrase
274 (let ((password-cache-expiry mml1991-passphrase-cache-expiry))
275 (password-cache-add key-id passphrase))
276 (setq mml1991-epg-secret-key-id-list
277 (cons key-id mml1991-epg-secret-key-id-list))
278 (copy-sequence passphrase)))))
279
280(defun mml1991-epg-find-usable-key (keys usage)
281 (catch 'found
282 (while keys
283 (let ((pointer (epg-key-sub-key-list (car keys))))
284 ;; The primary key will be marked as disabled, when the entire
285 ;; key is disabled (see 12 Field, Format of colon listings, in
286 ;; gnupg/doc/DETAILS)
287 (unless (memq 'disabled (epg-sub-key-capability (car pointer)))
288 (while pointer
289 (if (and (memq usage (epg-sub-key-capability (car pointer)))
290 (not (memq (epg-sub-key-validity (car pointer))
291 '(revoked expired))))
292 (throw 'found (car keys)))
293 (setq pointer (cdr pointer)))))
294 (setq keys (cdr keys)))))
295
296;; XXX: since gpg --list-secret-keys does not return validity of each
297;; key, `mml1991-epg-find-usable-key' defined above is not enough for
298;; secret keys. The function `mml1991-epg-find-usable-secret-key'
299;; below looks at appropriate public keys to check usability.
300(defun mml1991-epg-find-usable-secret-key (context name usage)
301 (let ((secret-keys (epg-list-keys context name t))
302 secret-key)
303 (while (and (not secret-key) secret-keys)
304 (if (mml1991-epg-find-usable-key
305 (epg-list-keys context (epg-sub-key-fingerprint
306 (car (epg-key-sub-key-list
307 (car secret-keys)))))
308 usage)
309 (setq secret-key (car secret-keys)
310 secret-keys nil)
311 (setq secret-keys (cdr secret-keys))))
312 secret-key))
313
314(defun mml1991-epg-sign (cont) 265(defun mml1991-epg-sign (cont)
315 (let ((context (epg-make-context)) 266 (let ((inhibit-redisplay t)
316 headers cte signer-key signers signature) 267 headers cte)
317 (if (eq mm-sign-option 'guided)
318 (setq signers (epa-select-keys context "Select keys for signing.
319If no one is selected, default secret key is used. "
320 mml1991-signers t))
321 (if mml1991-signers
322 (setq signers (delq nil
323 (mapcar
324 (lambda (name)
325 (setq signer-key
326 (mml1991-epg-find-usable-secret-key
327 context name 'sign))
328 (unless (or signer-key
329 (y-or-n-p
330 (format
331 "No secret key for %s; skip it? "
332 name)))
333 (error "No secret key for %s" name))
334 signer-key)
335 mml1991-signers)))))
336 (epg-context-set-armor context t)
337 (epg-context-set-textmode context t)
338 (epg-context-set-signers context signers)
339 (if mml1991-cache-passphrase
340 (epg-context-set-passphrase-callback
341 context
342 #'mml1991-epg-passphrase-callback))
343 ;; Don't sign headers. 268 ;; Don't sign headers.
344 (goto-char (point-min)) 269 (goto-char (point-min))
345 (when (re-search-forward "^$" nil t) 270 (when (re-search-forward "^$" nil t)
@@ -352,28 +277,21 @@ If no one is selected, default secret key is used. "
352 (when cte 277 (when cte
353 (setq cte (intern (downcase cte))) 278 (setq cte (intern (downcase cte)))
354 (mm-decode-content-transfer-encoding cte))) 279 (mm-decode-content-transfer-encoding cte)))
355 (condition-case error 280 (let* ((pair (mml-secure-epg-sign 'OpenPGP 'clear))
356 (setq signature (epg-sign-string context (buffer-string) 'clear) 281 (signature (car pair)))
357 mml1991-epg-secret-key-id-list nil) 282 (delete-region (point-min) (point-max))
358 (error 283 (mm-with-unibyte-current-buffer
359 (while mml1991-epg-secret-key-id-list 284 (insert signature)
360 (password-cache-remove (car mml1991-epg-secret-key-id-list)) 285 (goto-char (point-min))
361 (setq mml1991-epg-secret-key-id-list 286 (while (re-search-forward "\r+$" nil t)
362 (cdr mml1991-epg-secret-key-id-list))) 287 (replace-match "" t t))
363 (signal (car error) (cdr error)))) 288 (when cte
364 (delete-region (point-min) (point-max)) 289 (mm-encode-content-transfer-encoding cte))
365 (mm-with-unibyte-current-buffer 290 (goto-char (point-min))
366 (insert signature) 291 (when headers
367 (goto-char (point-min)) 292 (insert headers))
368 (while (re-search-forward "\r+$" nil t) 293 (insert "\n"))
369 (replace-match "" t t)) 294 t)))
370 (when cte
371 (mm-encode-content-transfer-encoding cte))
372 (goto-char (point-min))
373 (when headers
374 (insert headers))
375 (insert "\n"))
376 t))
377 295
378(defun mml1991-epg-encrypt (cont &optional sign) 296(defun mml1991-epg-encrypt (cont &optional sign)
379 (goto-char (point-min)) 297 (goto-char (point-min))
@@ -386,78 +304,7 @@ If no one is selected, default secret key is used. "
386 (delete-region (point-min) (point)) 304 (delete-region (point-min) (point))
387 (when cte 305 (when cte
388 (mm-decode-content-transfer-encoding (intern (downcase cte)))))) 306 (mm-decode-content-transfer-encoding (intern (downcase cte))))))
389 (let ((context (epg-make-context)) 307 (let ((cipher (mml-secure-epg-encrypt 'OpenPGP cont sign)))
390 (recipients
391 (if (message-options-get 'message-recipients)
392 (split-string
393 (message-options-get 'message-recipients)
394 "[ \f\t\n\r\v,]+")))
395 recipient-key signer-key cipher signers config)
396 (when mml1991-encrypt-to-self
397 (unless mml1991-signers
398 (error "mml1991-signers is not set"))
399 (setq recipients (nconc recipients mml1991-signers)))
400 ;; We should remove this check if epg-0.0.6 is released.
401 (if (and (condition-case nil
402 (require 'epg-config)
403 (error))
404 (functionp #'epg-expand-group))
405 (setq config (epg-configuration)
406 recipients
407 (apply #'nconc
408 (mapcar (lambda (recipient)
409 (or (epg-expand-group config recipient)
410 (list recipient)))
411 recipients))))
412 (if (eq mm-encrypt-option 'guided)
413 (setq recipients
414 (epa-select-keys context "Select recipients for encryption.
415If no one is selected, symmetric encryption will be performed. "
416 recipients))
417 (setq recipients
418 (delq nil (mapcar
419 (lambda (name)
420 (setq recipient-key (mml1991-epg-find-usable-key
421 (epg-list-keys context name)
422 'encrypt))
423 (unless (or recipient-key
424 (y-or-n-p
425 (format "No public key for %s; skip it? "
426 name)))
427 (error "No public key for %s" name))
428 recipient-key)
429 recipients)))
430 (unless recipients
431 (error "No recipient specified")))
432 (when sign
433 (if (eq mm-sign-option 'guided)
434 (setq signers (epa-select-keys context "Select keys for signing.
435If no one is selected, default secret key is used. "
436 mml1991-signers t))
437 (if mml1991-signers
438 (setq signers (delq nil
439 (mapcar
440 (lambda (name)
441 (mml1991-epg-find-usable-secret-key
442 context name 'sign))
443 mml1991-signers)))))
444 (epg-context-set-signers context signers))
445 (epg-context-set-armor context t)
446 (epg-context-set-textmode context t)
447 (if mml1991-cache-passphrase
448 (epg-context-set-passphrase-callback
449 context
450 #'mml1991-epg-passphrase-callback))
451 (condition-case error
452 (setq cipher
453 (epg-encrypt-string context (buffer-string) recipients sign)
454 mml1991-epg-secret-key-id-list nil)
455 (error
456 (while mml1991-epg-secret-key-id-list
457 (password-cache-remove (car mml1991-epg-secret-key-id-list))
458 (setq mml1991-epg-secret-key-id-list
459 (cdr mml1991-epg-secret-key-id-list)))
460 (signal (car error) (cdr error))))
461 (delete-region (point-min) (point-max)) 308 (delete-region (point-min) (point-max))
462 (insert "\n" cipher)) 309 (insert "\n" cipher))
463 t) 310 t)
diff --git a/lisp/gnus/mml2015.el b/lisp/gnus/mml2015.el
index 10ba126ae2b..e2e99771801 100644
--- a/lisp/gnus/mml2015.el
+++ b/lisp/gnus/mml2015.el
@@ -111,6 +111,9 @@ Valid packages include `epg', `pgg' and `mailcrypt'.")
111 "If t, cache passphrase." 111 "If t, cache passphrase."
112 :group 'mime-security 112 :group 'mime-security
113 :type 'boolean) 113 :type 'boolean)
114(make-obsolete-variable 'mml2015-cache-passphrase
115 'mml-secure-cache-passphrase
116 "25.1")
114 117
115(defcustom mml2015-passphrase-cache-expiry mml-secure-passphrase-cache-expiry 118(defcustom mml2015-passphrase-cache-expiry mml-secure-passphrase-cache-expiry
116 "How many seconds the passphrase is cached. 119 "How many seconds the passphrase is cached.
@@ -118,6 +121,9 @@ Whether the passphrase is cached at all is controlled by
118`mml2015-cache-passphrase'." 121`mml2015-cache-passphrase'."
119 :group 'mime-security 122 :group 'mime-security
120 :type 'integer) 123 :type 'integer)
124(make-obsolete-variable 'mml2015-passphrase-cache-expiry
125 'mml-secure-passphrase-cache-expiry
126 "25.1")
121 127
122(defcustom mml2015-signers nil 128(defcustom mml2015-signers nil
123 "A list of your own key ID(s) which will be used to sign a message. 129 "A list of your own key ID(s) which will be used to sign a message.
@@ -774,99 +780,6 @@ If set, it overrides the setting of `mml2015-sign-with-sender'."
774(autoload 'epg-expand-group "epg-config") 780(autoload 'epg-expand-group "epg-config")
775(autoload 'epa-select-keys "epa") 781(autoload 'epa-select-keys "epa")
776 782
777(defvar mml2015-epg-secret-key-id-list nil)
778
779(defun mml2015-epg-passphrase-callback (context key-id ignore)
780 (if (eq key-id 'SYM)
781 (epg-passphrase-callback-function context key-id nil)
782 (let* ((password-cache-key-id
783 (if (eq key-id 'PIN)
784 "PIN"
785 key-id))
786 entry
787 (passphrase
788 (password-read
789 (if (eq key-id 'PIN)
790 "Passphrase for PIN: "
791 (if (setq entry (assoc key-id epg-user-id-alist))
792 (format "Passphrase for %s %s: " key-id (cdr entry))
793 (format "Passphrase for %s: " key-id)))
794 password-cache-key-id)))
795 (when passphrase
796 (let ((password-cache-expiry mml2015-passphrase-cache-expiry))
797 (password-cache-add password-cache-key-id passphrase))
798 (setq mml2015-epg-secret-key-id-list
799 (cons password-cache-key-id mml2015-epg-secret-key-id-list))
800 (copy-sequence passphrase)))))
801
802(defun mml2015-epg-check-user-id (key recipient)
803 (let ((pointer (epg-key-user-id-list key))
804 result)
805 (while pointer
806 (if (and (equal (car (mail-header-parse-address
807 (epg-user-id-string (car pointer))))
808 (car (mail-header-parse-address
809 recipient)))
810 (not (memq (epg-user-id-validity (car pointer))
811 '(revoked expired))))
812 (setq result t
813 pointer nil)
814 (setq pointer (cdr pointer))))
815 result))
816
817(defun mml2015-epg-check-sub-key (key usage)
818 (let ((pointer (epg-key-sub-key-list key))
819 result)
820 ;; The primary key will be marked as disabled, when the entire
821 ;; key is disabled (see 12 Field, Format of colon listings, in
822 ;; gnupg/doc/DETAILS)
823 (unless (memq 'disabled (epg-sub-key-capability (car pointer)))
824 (while pointer
825 (if (and (memq usage (epg-sub-key-capability (car pointer)))
826 (not (memq (epg-sub-key-validity (car pointer))
827 '(revoked expired))))
828 (setq result t
829 pointer nil)
830 (setq pointer (cdr pointer)))))
831 result))
832
833(defun mml2015-epg-find-usable-key (context name usage
834 &optional name-is-key-id)
835 (let ((keys (epg-list-keys context name))
836 key)
837 (while keys
838 (if (and (or name-is-key-id
839 ;; Non email user-id can be supplied through
840 ;; mml2015-signers if mml2015-encrypt-to-self is set.
841 ;; Treat it as valid, as it is user's intention.
842 (not (string-match "\\`<" name))
843 (mml2015-epg-check-user-id (car keys) name))
844 (mml2015-epg-check-sub-key (car keys) usage))
845 (setq key (car keys)
846 keys nil)
847 (setq keys (cdr keys))))
848 key))
849
850;; XXX: since gpg --list-secret-keys does not return validity of each
851;; key, `mml2015-epg-find-usable-key' defined above is not enough for
852;; secret keys. The function `mml2015-epg-find-usable-secret-key'
853;; below looks at appropriate public keys to check usability.
854(defun mml2015-epg-find-usable-secret-key (context name usage)
855 (let ((secret-keys (epg-list-keys context name t))
856 secret-key)
857 (while (and (not secret-key) secret-keys)
858 (if (mml2015-epg-find-usable-key
859 context
860 (epg-sub-key-fingerprint
861 (car (epg-key-sub-key-list
862 (car secret-keys))))
863 usage
864 t)
865 (setq secret-key (car secret-keys)
866 secret-keys nil)
867 (setq secret-keys (cdr secret-keys))))
868 secret-key))
869
870(autoload 'gnus-create-image "gnus-ems") 783(autoload 'gnus-create-image "gnus-ems")
871 784
872(defun mml2015-epg-key-image (key-id) 785(defun mml2015-epg-key-image (key-id)
@@ -921,18 +834,15 @@ If set, it overrides the setting of `mml2015-sign-with-sender'."
921 mm-security-handle 'gnus-info "Corrupted") 834 mm-security-handle 'gnus-info "Corrupted")
922 (throw 'error handle)) 835 (throw 'error handle))
923 (setq context (epg-make-context)) 836 (setq context (epg-make-context))
924 (if mml2015-cache-passphrase 837 (if (or mml2015-cache-passphrase mml-secure-cache-passphrase)
925 (epg-context-set-passphrase-callback 838 (epg-context-set-passphrase-callback
926 context 839 context
927 #'mml2015-epg-passphrase-callback)) 840 (cons 'mml-secure-passphrase-callback 'OpenPGP)))
928 (condition-case error 841 (condition-case error
929 (setq plain (epg-decrypt-string context (mm-get-part child)) 842 (setq plain (epg-decrypt-string context (mm-get-part child))
930 mml2015-epg-secret-key-id-list nil) 843 mml-secure-secret-key-id-list nil)
931 (error 844 (error
932 (while mml2015-epg-secret-key-id-list 845 (mml-secure-clear-secret-key-id-list)
933 (password-cache-remove (car mml2015-epg-secret-key-id-list))
934 (setq mml2015-epg-secret-key-id-list
935 (cdr mml2015-epg-secret-key-id-list)))
936 (mm-set-handle-multipart-parameter 846 (mm-set-handle-multipart-parameter
937 mm-security-handle 'gnus-info "Failed") 847 mm-security-handle 'gnus-info "Failed")
938 (if (eq (car error) 'quit) 848 (if (eq (car error) 'quit)
@@ -968,18 +878,15 @@ If set, it overrides the setting of `mml2015-sign-with-sender'."
968 (let ((inhibit-redisplay t) 878 (let ((inhibit-redisplay t)
969 (context (epg-make-context)) 879 (context (epg-make-context))
970 plain) 880 plain)
971 (if mml2015-cache-passphrase 881 (if (or mml2015-cache-passphrase mml-secure-cache-passphrase)
972 (epg-context-set-passphrase-callback 882 (epg-context-set-passphrase-callback
973 context 883 context
974 #'mml2015-epg-passphrase-callback)) 884 (cons 'mml-secure-passphrase-callback 'OpenPGP)))
975 (condition-case error 885 (condition-case error
976 (setq plain (epg-decrypt-string context (buffer-string)) 886 (setq plain (epg-decrypt-string context (buffer-string))
977 mml2015-epg-secret-key-id-list nil) 887 mml-secure-secret-key-id-list nil)
978 (error 888 (error
979 (while mml2015-epg-secret-key-id-list 889 (mml-secure-clear-secret-key-id-list)
980 (password-cache-remove (car mml2015-epg-secret-key-id-list))
981 (setq mml2015-epg-secret-key-id-list
982 (cdr mml2015-epg-secret-key-id-list)))
983 (mm-set-handle-multipart-parameter 890 (mm-set-handle-multipart-parameter
984 mm-security-handle 'gnus-info "Failed") 891 mm-security-handle 'gnus-info "Failed")
985 (if (eq (car error) 'quit) 892 (if (eq (car error) 'quit)
@@ -1065,176 +972,37 @@ If set, it overrides the setting of `mml2015-sign-with-sender'."
1065 (mml2015-extract-cleartext-signature)))) 972 (mml2015-extract-cleartext-signature))))
1066 973
1067(defun mml2015-epg-sign (cont) 974(defun mml2015-epg-sign (cont)
1068 (let* ((inhibit-redisplay t) 975 (let ((inhibit-redisplay t)
1069 (context (epg-make-context)) 976 (boundary (mml-compute-boundary cont)))
1070 (boundary (mml-compute-boundary cont))
1071 (sender (message-options-get 'message-sender))
1072 (signer-names (or mml2015-signers
1073 (if (and mml2015-sign-with-sender sender)
1074 (list (concat "<" sender ">")))))
1075 signer-key
1076 (signers
1077 (or (message-options-get 'mml2015-epg-signers)
1078 (message-options-set
1079 'mml2015-epg-signers
1080 (if (eq mm-sign-option 'guided)
1081 (epa-select-keys context "\
1082Select keys for signing.
1083If no one is selected, default secret key is used. "
1084 signer-names
1085 t)
1086 (if (or sender mml2015-signers)
1087 (delq nil
1088 (mapcar
1089 (lambda (signer)
1090 (setq signer-key
1091 (mml2015-epg-find-usable-secret-key
1092 context signer 'sign))
1093 (unless (or signer-key
1094 (y-or-n-p
1095 (format
1096 "No secret key for %s; skip it? "
1097 signer)))
1098 (error "No secret key for %s" signer))
1099 signer-key)
1100 signer-names)))))))
1101 signature micalg)
1102 (epg-context-set-armor context t)
1103 (epg-context-set-textmode context t)
1104 (epg-context-set-signers context signers)
1105 (if mml2015-cache-passphrase
1106 (epg-context-set-passphrase-callback
1107 context
1108 #'mml2015-epg-passphrase-callback))
1109 ;; Signed data must end with a newline (RFC 3156, 5). 977 ;; Signed data must end with a newline (RFC 3156, 5).
1110 (goto-char (point-max)) 978 (goto-char (point-max))
1111 (unless (bolp) 979 (unless (bolp)
1112 (insert "\n")) 980 (insert "\n"))
1113 (condition-case error 981 (let* ((pair (mml-secure-epg-sign 'OpenPGP t))
1114 (setq signature (epg-sign-string context (buffer-string) t) 982 (signature (car pair))
1115 mml2015-epg-secret-key-id-list nil) 983 (micalg (cdr pair)))
1116 (error 984 (goto-char (point-min))
1117 (while mml2015-epg-secret-key-id-list 985 (insert (format "Content-Type: multipart/signed; boundary=\"%s\";\n"
1118 (password-cache-remove (car mml2015-epg-secret-key-id-list)) 986 boundary))
1119 (setq mml2015-epg-secret-key-id-list 987 (if micalg
1120 (cdr mml2015-epg-secret-key-id-list))) 988 (insert (format "\tmicalg=pgp-%s; "
1121 (signal (car error) (cdr error)))) 989 (downcase
1122 (if (epg-context-result-for context 'sign) 990 (cdr (assq micalg
1123 (setq micalg (epg-new-signature-digest-algorithm 991 epg-digest-algorithm-alist))))))
1124 (car (epg-context-result-for context 'sign))))) 992 (insert "protocol=\"application/pgp-signature\"\n")
1125 (goto-char (point-min)) 993 (insert (format "\n--%s\n" boundary))
1126 (insert (format "Content-Type: multipart/signed; boundary=\"%s\";\n" 994 (goto-char (point-max))
1127 boundary)) 995 (insert (format "\n--%s\n" boundary))
1128 (if micalg 996 (insert "Content-Type: application/pgp-signature; name=\"signature.asc\"\n\n")
1129 (insert (format "\tmicalg=pgp-%s; " 997 (insert signature)
1130 (downcase 998 (goto-char (point-max))
1131 (cdr (assq micalg 999 (insert (format "--%s--\n" boundary))
1132 epg-digest-algorithm-alist)))))) 1000 (goto-char (point-max)))))
1133 (insert "protocol=\"application/pgp-signature\"\n")
1134 (insert (format "\n--%s\n" boundary))
1135 (goto-char (point-max))
1136 (insert (format "\n--%s\n" boundary))
1137 (insert "Content-Type: application/pgp-signature; name=\"signature.asc\"\n\n")
1138 (insert signature)
1139 (goto-char (point-max))
1140 (insert (format "--%s--\n" boundary))
1141 (goto-char (point-max))))
1142 1001
1143(defun mml2015-epg-encrypt (cont &optional sign) 1002(defun mml2015-epg-encrypt (cont &optional sign)
1144 (let* ((inhibit-redisplay t) 1003 (let* ((inhibit-redisplay t)
1145 (context (epg-make-context))
1146 (boundary (mml-compute-boundary cont)) 1004 (boundary (mml-compute-boundary cont))
1147 (config (epg-configuration)) 1005 (cipher (mml-secure-epg-encrypt 'OpenPGP cont sign)))
1148 (recipients (message-options-get 'mml2015-epg-recipients))
1149 cipher
1150 (sender (message-options-get 'message-sender))
1151 (signer-names (or mml2015-signers
1152 (if (and mml2015-sign-with-sender sender)
1153 (list (concat "<" sender ">")))))
1154 signers
1155 recipient-key signer-key)
1156 (unless recipients
1157 (setq recipients
1158 (apply #'nconc
1159 (mapcar
1160 (lambda (recipient)
1161 (or (epg-expand-group config recipient)
1162 (list (concat "<" recipient ">"))))
1163 (split-string
1164 (or (message-options-get 'message-recipients)
1165 (message-options-set 'message-recipients
1166 (read-string "Recipients: ")))
1167 "[ \f\t\n\r\v,]+"))))
1168 (when mml2015-encrypt-to-self
1169 (unless signer-names
1170 (error "Neither message sender nor mml2015-signers are set"))
1171 (setq recipients (nconc recipients signer-names)))
1172 (if (eq mm-encrypt-option 'guided)
1173 (setq recipients
1174 (epa-select-keys context "\
1175Select recipients for encryption.
1176If no one is selected, symmetric encryption will be performed. "
1177 recipients))
1178 (setq recipients
1179 (delq nil
1180 (mapcar
1181 (lambda (recipient)
1182 (setq recipient-key (mml2015-epg-find-usable-key
1183 context recipient 'encrypt))
1184 (unless (or recipient-key
1185 (y-or-n-p
1186 (format "No public key for %s; skip it? "
1187 recipient)))
1188 (error "No public key for %s" recipient))
1189 recipient-key)
1190 recipients)))
1191 (unless recipients
1192 (error "No recipient specified")))
1193 (message-options-set 'mml2015-epg-recipients recipients))
1194 (when sign
1195 (setq signers
1196 (or (message-options-get 'mml2015-epg-signers)
1197 (message-options-set
1198 'mml2015-epg-signers
1199 (if (eq mm-sign-option 'guided)
1200 (epa-select-keys context "\
1201Select keys for signing.
1202If no one is selected, default secret key is used. "
1203 signer-names
1204 t)
1205 (if (or sender mml2015-signers)
1206 (delq nil
1207 (mapcar
1208 (lambda (signer)
1209 (setq signer-key
1210 (mml2015-epg-find-usable-secret-key
1211 context signer 'sign))
1212 (unless (or signer-key
1213 (y-or-n-p
1214 (format
1215 "No secret key for %s; skip it? "
1216 signer)))
1217 (error "No secret key for %s" signer))
1218 signer-key)
1219 signer-names)))))))
1220 (epg-context-set-signers context signers))
1221 (epg-context-set-armor context t)
1222 (epg-context-set-textmode context t)
1223 (if mml2015-cache-passphrase
1224 (epg-context-set-passphrase-callback
1225 context
1226 #'mml2015-epg-passphrase-callback))
1227 (condition-case error
1228 (setq cipher
1229 (epg-encrypt-string context (buffer-string) recipients sign
1230 mml2015-always-trust)
1231 mml2015-epg-secret-key-id-list nil)
1232 (error
1233 (while mml2015-epg-secret-key-id-list
1234 (password-cache-remove (car mml2015-epg-secret-key-id-list))
1235 (setq mml2015-epg-secret-key-id-list
1236 (cdr mml2015-epg-secret-key-id-list)))
1237 (signal (car error) (cdr error))))
1238 (delete-region (point-min) (point-max)) 1006 (delete-region (point-min) (point-max))
1239 (goto-char (point-min)) 1007 (goto-char (point-min))
1240 (insert (format "Content-Type: multipart/encrypted; boundary=\"%s\";\n" 1008 (insert (format "Content-Type: multipart/encrypted; boundary=\"%s\";\n"
diff --git a/lisp/gnus/nntp.el b/lisp/gnus/nntp.el
index 0e10dfdb8be..f56b04568c8 100644
--- a/lisp/gnus/nntp.el
+++ b/lisp/gnus/nntp.el
@@ -1115,24 +1115,14 @@ command whose response triggered the error."
1115 1115
1116(deffoo nntp-request-newgroups (date &optional server) 1116(deffoo nntp-request-newgroups (date &optional server)
1117 (nntp-with-open-group 1117 (nntp-with-open-group
1118 nil server 1118 nil server
1119 (with-current-buffer nntp-server-buffer 1119 (with-current-buffer nntp-server-buffer
1120 (let* ((time (date-to-time date)) 1120 (prog1
1121 (ls (- (cadr time) (nth 8 (decode-time time))))) 1121 (nntp-send-command
1122 (cond ((< ls 0) 1122 "^\\.\r?\n" "NEWGROUPS"
1123 (setcar time (1- (car time))) 1123 (format-time-string "%y%m%d %H%M%S" (date-to-time date) t)
1124 (setcar (cdr time) (+ ls 65536))) 1124 "GMT")
1125 ((>= ls 65536) 1125 (nntp-decode-text)))))
1126 (setcar time (1+ (car time)))
1127 (setcar (cdr time) (- ls 65536)))
1128 (t
1129 (setcar (cdr time) ls)))
1130 (prog1
1131 (nntp-send-command
1132 "^\\.\r?\n" "NEWGROUPS"
1133 (format-time-string "%y%m%d %H%M%S" time)
1134 "GMT")
1135 (nntp-decode-text))))))
1136 1126
1137(deffoo nntp-request-post (&optional server) 1127(deffoo nntp-request-post (&optional server)
1138 (nntp-with-open-group 1128 (nntp-with-open-group
diff --git a/lisp/help-fns.el b/lisp/help-fns.el
index bc96601a45c..2021885e996 100644
--- a/lisp/help-fns.el
+++ b/lisp/help-fns.el
@@ -918,29 +918,28 @@ if it is given a local binding.\n"))))
918 ;; If the cache element has an mtime, we 918 ;; If the cache element has an mtime, we
919 ;; assume it came from a file. 919 ;; assume it came from a file.
920 (if (nth 2 file) 920 (if (nth 2 file)
921 (setq file (expand-file-name 921 ;; (car file) is a directory.
922 dir-locals-file (car file))) 922 (setq file (dir-locals--all-files (car file)))
923 ;; Otherwise, assume it was set directly. 923 ;; Otherwise, assume it was set directly.
924 (setq file (car file) 924 (setq file (car file)
925 is-directory t))) 925 is-directory t)))
926 (if (null file) 926 (if (null file)
927 (princ ".\n") 927 (princ ".\n")
928 (princ ", set ") 928 (princ ", set ")
929 (let ((files (file-expand-wildcards file))) 929 (princ (substitute-command-keys
930 (princ (substitute-command-keys 930 (cond
931 (cond 931 (is-directory "for the directory\n `")
932 (is-directory "for the directory\n `") 932 ;; Many files matched.
933 ;; Many files matched. 933 ((and (consp file) (cdr file))
934 ((cdr files) 934 (setq file (file-name-directory (car file)))
935 (setq file (file-name-directory (car files))) 935 (format "by one of the\n %s files in the directory\n `"
936 (format "by a file\n matching `%s' in the directory\n `" 936 dir-locals-file))
937 dir-locals-file)) 937 (t (setq file (car file))
938 (t (setq file (car files)) 938 "by the file\n `"))))
939 "by the file\n `"))))
940 (with-current-buffer standard-output 939 (with-current-buffer standard-output
941 (insert-text-button 940 (insert-text-button
942 file 'type 'help-dir-local-var-def 941 file 'type 'help-dir-local-var-def
943 'help-args (list variable file)))) 942 'help-args (list variable file)))
944 (princ (substitute-command-keys "'.\n")))) 943 (princ (substitute-command-keys "'.\n"))))
945 (princ (substitute-command-keys 944 (princ (substitute-command-keys
946 " This variable's value is file-local.\n")))) 945 " This variable's value is file-local.\n"))))
diff --git a/lisp/international/mule-util.el b/lisp/international/mule-util.el
index 24ad342d4e0..ae58f1ec7e1 100644
--- a/lisp/international/mule-util.el
+++ b/lisp/international/mule-util.el
@@ -259,7 +259,7 @@ language environment LANG-ENV."
259 (with-coding-priority coding-priority 259 (with-coding-priority coding-priority
260 (detect-coding-region from to))))) 260 (detect-coding-region from to)))))
261 261
262(declare-function internal-char-font "fontset.c" (position &optional ch)) 262(declare-function internal-char-font "font.c" (position &optional ch))
263 263
264;;;###autoload 264;;;###autoload
265(defun char-displayable-p (char) 265(defun char-displayable-p (char)
diff --git a/lisp/mail/rmail.el b/lisp/mail/rmail.el
index 05511a84540..5464c38af76 100644
--- a/lisp/mail/rmail.el
+++ b/lisp/mail/rmail.el
@@ -694,8 +694,9 @@ Element N specifies the summary line for message N+1.")
694This is set to nil by default.") 694This is set to nil by default.")
695 695
696(defcustom rmail-get-coding-function nil 696(defcustom rmail-get-coding-function nil
697 "Function of no args to try to determine coding system for a message." 697 "Function of no args to try to determine coding system for a message.
698 :type 'function 698If nil, just search for `rmail-mime-charset-pattern'."
699 :type '(choice (const nil) function)
699 :group 'rmail 700 :group 'rmail
700 :version "24.4") 701 :version "24.4")
701 702
diff --git a/lisp/mh-e/mh-e.el b/lisp/mh-e/mh-e.el
index c900248c9b6..20029f8e0b5 100644
--- a/lisp/mh-e/mh-e.el
+++ b/lisp/mh-e/mh-e.el
@@ -5,7 +5,7 @@
5 5
6;; Author: Bill Wohler <wohler@newt.com> 6;; Author: Bill Wohler <wohler@newt.com>
7;; Maintainer: Bill Wohler <wohler@newt.com> 7;; Maintainer: Bill Wohler <wohler@newt.com>
8;; Version: 8.6 8;; Version: 8.6+git
9;; Keywords: mail 9;; Keywords: mail
10 10
11;; This file is part of GNU Emacs. 11;; This file is part of GNU Emacs.
@@ -127,7 +127,7 @@
127;; Try to keep variables local to a single file. Provide accessors if 127;; Try to keep variables local to a single file. Provide accessors if
128;; variables are shared. Use this section as a last resort. 128;; variables are shared. Use this section as a last resort.
129 129
130(defconst mh-version "8.6" "Version number of MH-E.") 130(defconst mh-version "8.6+git" "Version number of MH-E.")
131 131
132;; Variants 132;; Variants
133 133
diff --git a/lisp/net/browse-url.el b/lisp/net/browse-url.el
index 26fa0d94b88..2bda97f95d0 100644
--- a/lisp/net/browse-url.el
+++ b/lisp/net/browse-url.el
@@ -349,6 +349,7 @@ functionality is not available there."
349 "Whether to open up new windows in a buffer or a new window. 349 "Whether to open up new windows in a buffer or a new window.
350If non-nil, then open the URL in a new buffer rather than a new window if 350If non-nil, then open the URL in a new buffer rather than a new window if
351`browse-url-conkeror' is asked to open it in a new window." 351`browse-url-conkeror' is asked to open it in a new window."
352 :version "25.1"
352 :type 'boolean 353 :type 'boolean
353 :group 'browse-url) 354 :group 'browse-url)
354 355
@@ -415,6 +416,7 @@ commands reverses the effect of this variable."
415 416
416(defcustom browse-url-conkeror-arguments nil 417(defcustom browse-url-conkeror-arguments nil
417 "A list of strings to pass to Conkeror as arguments." 418 "A list of strings to pass to Conkeror as arguments."
419 :version "25.1"
418 :type '(repeat (string :tag "Argument")) 420 :type '(repeat (string :tag "Argument"))
419 :group 'browse-url) 421 :group 'browse-url)
420 422
diff --git a/lisp/net/newst-reader.el b/lisp/net/newst-reader.el
index 1647ef85364..9c29216ccaf 100644
--- a/lisp/net/newst-reader.el
+++ b/lisp/net/newst-reader.el
@@ -69,6 +69,7 @@ This must be one of the functions `newsticker-plainview' or
69(defcustom newsticker-download-logos 69(defcustom newsticker-download-logos
70 t 70 t
71 "If non-nil newsticker downloads logo images of subscribed feeds." 71 "If non-nil newsticker downloads logo images of subscribed feeds."
72 :version "25.1"
72 :type 'boolean 73 :type 'boolean
73 :group 'newsticker-reader) 74 :group 'newsticker-reader)
74 75
diff --git a/lisp/net/newst-treeview.el b/lisp/net/newst-treeview.el
index 0e75236154b..4de3d1d1125 100644
--- a/lisp/net/newst-treeview.el
+++ b/lisp/net/newst-treeview.el
@@ -132,9 +132,9 @@ Example: (\"Topmost group\" \"feed1\" (\"subgroup1\" \"feed 2\")
132 132
133(defcustom newsticker-groups-filename 133(defcustom newsticker-groups-filename
134 nil 134 nil
135 "Name of the newsticker groups settings file. This variable is obsolete." 135 "Name of the newsticker groups settings file."
136 :version "25.1" ; changed default value to nil 136 :version "25.1" ; changed default value to nil
137 :type 'string 137 :type '(choice (const nil) string)
138 :group 'newsticker-treeview) 138 :group 'newsticker-treeview)
139(make-obsolete-variable 'newsticker-groups-filename 'newsticker-dir "23.1") 139(make-obsolete-variable 'newsticker-groups-filename 'newsticker-dir "23.1")
140 140
diff --git a/lisp/net/shr.el b/lisp/net/shr.el
index 2511d673e7e..290a6422bd7 100644
--- a/lisp/net/shr.el
+++ b/lisp/net/shr.el
@@ -1617,7 +1617,9 @@ The preference is a float determined from `shr-prefer-media-type'."
1617 (shr-insert-table (shr-make-table dom sketch-widths t) sketch-widths))) 1617 (shr-insert-table (shr-make-table dom sketch-widths t) sketch-widths)))
1618 1618
1619(defun shr-table-body (dom) 1619(defun shr-table-body (dom)
1620 (let ((tbodies (dom-by-tag dom 'tbody))) 1620 (let ((tbodies (seq-filter (lambda (child)
1621 (eq (dom-tag child) 'tbody))
1622 (dom-children dom))))
1621 (cond 1623 (cond
1622 ((null tbodies) 1624 ((null tbodies)
1623 dom) 1625 dom)
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index 7b1aa2a13b0..baebb13dd22 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -284,6 +284,15 @@ The string is used in `tramp-methods'.")
284 (tramp-remote-shell-args ("-c")) 284 (tramp-remote-shell-args ("-c"))
285 (tramp-connection-timeout 10))) 285 (tramp-connection-timeout 10)))
286;;;###tramp-autoload 286;;;###tramp-autoload
287(add-to-list
288 'tramp-methods
289 '("sg"
290 (tramp-login-program "sg")
291 (tramp-login-args (("-") ("%u")))
292 (tramp-remote-shell "/bin/sh")
293 (tramp-remote-shell-args ("-c"))
294 (tramp-connection-timeout 10)))
295;;;###tramp-autoload
287(add-to-list 'tramp-methods 296(add-to-list 'tramp-methods
288 '("sudo" 297 '("sudo"
289 (tramp-login-program "sudo") 298 (tramp-login-program "sudo")
@@ -445,12 +454,17 @@ The string is used in `tramp-methods'.")
445 "Default list of (FUNCTION FILE) pairs to be examined for su methods.") 454 "Default list of (FUNCTION FILE) pairs to be examined for su methods.")
446 455
447;;;###tramp-autoload 456;;;###tramp-autoload
457(defconst tramp-completion-function-alist-sg
458 '((tramp-parse-etc-group "/etc/group"))
459 "Default list of (FUNCTION FILE) pairs to be examined for sg methods.")
460
461;;;###tramp-autoload
448(defconst tramp-completion-function-alist-putty 462(defconst tramp-completion-function-alist-putty
449 `((tramp-parse-putty 463 `((tramp-parse-putty
450 ,(if (memq system-type '(windows-nt)) 464 ,(if (memq system-type '(windows-nt))
451 "HKEY_CURRENT_USER\\Software\\SimonTatham\\PuTTY\\Sessions" 465 "HKEY_CURRENT_USER\\Software\\SimonTatham\\PuTTY\\Sessions"
452 "~/.putty/sessions"))) 466 "~/.putty/sessions")))
453 "Default list of (FUNCTION REGISTRY) pairs to be examined for putty sessions.") 467 "Default list of (FUNCTION REGISTRY) pairs to be examined for putty sessions.")
454 468
455;;;###tramp-autoload 469;;;###tramp-autoload
456(eval-after-load 'tramp 470(eval-after-load 'tramp
@@ -470,6 +484,7 @@ The string is used in `tramp-methods'.")
470 (tramp-set-completion-function "su" tramp-completion-function-alist-su) 484 (tramp-set-completion-function "su" tramp-completion-function-alist-su)
471 (tramp-set-completion-function "sudo" tramp-completion-function-alist-su) 485 (tramp-set-completion-function "sudo" tramp-completion-function-alist-su)
472 (tramp-set-completion-function "ksu" tramp-completion-function-alist-su) 486 (tramp-set-completion-function "ksu" tramp-completion-function-alist-su)
487 (tramp-set-completion-function "sg" tramp-completion-function-alist-sg)
473 (tramp-set-completion-function 488 (tramp-set-completion-function
474 "krlogin" tramp-completion-function-alist-rsh) 489 "krlogin" tramp-completion-function-alist-rsh)
475 (tramp-set-completion-function "plink" tramp-completion-function-alist-ssh) 490 (tramp-set-completion-function "plink" tramp-completion-function-alist-ssh)
@@ -5724,5 +5739,7 @@ function cell is returned to be applied on a buffer."
5724;; rsync). 5739;; rsync).
5725;; * Keep a second connection open for out-of-band methods like scp or 5740;; * Keep a second connection open for out-of-band methods like scp or
5726;; rsync. 5741;; rsync.
5742;; * Check, whether we could also use "getent passwd" and "getent
5743;; group" for user/group name completion.
5727 5744
5728;;; tramp-sh.el ends here 5745;;; tramp-sh.el ends here
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index 5c6788082b1..e52f1958592 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -432,6 +432,7 @@ names from FILE for completion. The following predefined FUNCTIONs exists:
432 * `tramp-parse-sknownhosts' for \"~/.ssh2/knownhosts/*\" like files, 432 * `tramp-parse-sknownhosts' for \"~/.ssh2/knownhosts/*\" like files,
433 * `tramp-parse-hosts' for \"/etc/hosts\" like files, 433 * `tramp-parse-hosts' for \"/etc/hosts\" like files,
434 * `tramp-parse-passwd' for \"/etc/passwd\" like files. 434 * `tramp-parse-passwd' for \"/etc/passwd\" like files.
435 * `tramp-parse-etc-group' for \"/etc/group\" like files.
435 * `tramp-parse-netrc' for \"~/.netrc\" like files. 436 * `tramp-parse-netrc' for \"~/.netrc\" like files.
436 * `tramp-parse-putty' for PuTTY registered sessions. 437 * `tramp-parse-putty' for PuTTY registered sessions.
437 438
@@ -509,6 +510,7 @@ This regexp must match both `tramp-initial-end-of-output' and
509 510
510(defcustom tramp-password-prompt-regexp 511(defcustom tramp-password-prompt-regexp
511 (format "^.*\\(%s\\).*:\^@? *" 512 (format "^.*\\(%s\\).*:\^@? *"
513 ;; `password-word-equivalents' has been introduced with Emacs 24.4.
512 (if (boundp 'password-word-equivalents) 514 (if (boundp 'password-word-equivalents)
513 (regexp-opt (symbol-value 'password-word-equivalents)) 515 (regexp-opt (symbol-value 'password-word-equivalents))
514 "password\\|passphrase")) 516 "password\\|passphrase"))
@@ -2645,6 +2647,22 @@ Host is always \"localhost\"."
2645 result)) 2647 result))
2646 2648
2647;;;###tramp-autoload 2649;;;###tramp-autoload
2650(defun tramp-parse-etc-group (filename)
2651 "Return a list of (group host) tuples allowed to access.
2652Host is always \"localhost\"."
2653 (tramp-parse-file filename 'tramp-parse-etc-group-group))
2654
2655(defun tramp-parse-etc-group-group ()
2656 "Return a (group host) tuple allowed to access.
2657Host is always \"localhost\"."
2658 (let ((result)
2659 (split (split-string (buffer-substring (point) (point-at-eol)) ":")))
2660 (when (member (user-login-name) (split-string (nth 3 split) "," 'omit))
2661 (setq result (list (nth 0 split) "localhost")))
2662 (forward-line 1)
2663 result))
2664
2665;;;###tramp-autoload
2648(defun tramp-parse-netrc (filename) 2666(defun tramp-parse-netrc (filename)
2649 "Return a list of (user host) tuples allowed to access. 2667 "Return a list of (user host) tuples allowed to access.
2650User may be nil." 2668User may be nil."
diff --git a/lisp/nxml/nxml-enc.el b/lisp/nxml/nxml-enc.el
index bcee0882aa2..6406f57ff63 100644
--- a/lisp/nxml/nxml-enc.el
+++ b/lisp/nxml/nxml-enc.el
@@ -1,4 +1,4 @@
1;;; nxml-enc.el --- XML encoding auto-detection 1;;; nxml-enc.el --- XML encoding auto-detection -*- lexical-binding:t -*-
2 2
3;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. 3;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc.
4 4
@@ -68,7 +68,7 @@
68 (and nxml-non-xml-set-auto-coding-function 68 (and nxml-non-xml-set-auto-coding-function
69 (funcall nxml-non-xml-set-auto-coding-function file-name size)))) 69 (funcall nxml-non-xml-set-auto-coding-function file-name size))))
70 70
71(defun nxml-set-xml-coding (file-name size) 71(defun nxml-set-xml-coding (_file-name size)
72 "Function to use as `set-auto-coding-function' when file is known to be XML." 72 "Function to use as `set-auto-coding-function' when file is known to be XML."
73 (nxml-detect-coding-system (+ (point) (min size 1024)))) 73 (nxml-detect-coding-system (+ (point) (min size 1024))))
74 74
diff --git a/lisp/nxml/nxml-glyph.el b/lisp/nxml/nxml-glyph.el
deleted file mode 100644
index 4a518218c23..00000000000
--- a/lisp/nxml/nxml-glyph.el
+++ /dev/null
@@ -1,423 +0,0 @@
1;;; nxml-glyph.el --- glyph-handling for nxml-mode
2
3;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc.
4
5;; Author: James Clark
6;; Keywords: wp, hypermedia, languages, XML
7
8;; This file is part of GNU Emacs.
9
10;; GNU Emacs is free software: you can redistribute it and/or modify
11;; it under the terms of the GNU General Public License as published by
12;; the Free Software Foundation, either version 3 of the License, or
13;; (at your option) any later version.
14
15;; GNU Emacs is distributed in the hope that it will be useful,
16;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18;; GNU General Public License for more details.
19
20;; You should have received a copy of the GNU General Public License
21;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
22
23;;; Commentary:
24
25;; The entry point to this file is `nxml-glyph-display-string'.
26;; The current implementation is heuristic due to a lack of
27;; Emacs primitives necessary to implement it properly. The user
28;; can tweak the heuristics using `nxml-glyph-set-functions'.
29
30;;; Code:
31
32(defconst nxml-ascii-glyph-set
33 [(#x0020 . #x007E)])
34
35(defconst nxml-latin1-glyph-set
36 [(#x0020 . #x007E)
37 (#x00A0 . #x00FF)])
38
39;; These were generated by using nxml-insert-target-repertoire-glyph-set
40;; on the TARGET[123] files in
41;; http://www.cl.cam.ac.uk/~mgk25/download/ucs-fonts.tar.gz
42
43(defconst nxml-misc-fixed-1-glyph-set
44 [(#x0020 . #x007E)
45 (#x00A0 . #x00FF)
46 (#x0100 . #x017F)
47 #x018F #x0192
48 (#x0218 . #x021B)
49 #x0259
50 (#x02C6 . #x02C7)
51 (#x02D8 . #x02DD)
52 (#x0374 . #x0375)
53 #x037A #x037E
54 (#x0384 . #x038A)
55 #x038C
56 (#x038E . #x03A1)
57 (#x03A3 . #x03CE)
58 (#x0401 . #x040C)
59 (#x040E . #x044F)
60 (#x0451 . #x045C)
61 (#x045E . #x045F)
62 (#x0490 . #x0491)
63 (#x05D0 . #x05EA)
64 (#x1E02 . #x1E03)
65 (#x1E0A . #x1E0B)
66 (#x1E1E . #x1E1F)
67 (#x1E40 . #x1E41)
68 (#x1E56 . #x1E57)
69 (#x1E60 . #x1E61)
70 (#x1E6A . #x1E6B)
71 (#x1E80 . #x1E85)
72 (#x1EF2 . #x1EF3)
73 (#x2010 . #x2022)
74 #x2026 #x2030
75 (#x2039 . #x203A)
76 #x20AC #x2116 #x2122 #x2126
77 (#x215B . #x215E)
78 (#x2190 . #x2193)
79 #x2260
80 (#x2264 . #x2265)
81 (#x23BA . #x23BD)
82 (#x2409 . #x240D)
83 #x2424 #x2500 #x2502 #x250C #x2510 #x2514 #x2518 #x251C #x2524 #x252C #x2534 #x253C #x2592 #x25C6 #x266A #xFFFD]
84 "Glyph set for TARGET1 glyph repertoire of misc-fixed-* font.
85This repertoire is supported for the bold and oblique fonts.")
86
87(defconst nxml-misc-fixed-2-glyph-set
88 [(#x0020 . #x007E)
89 (#x00A0 . #x00FF)
90 (#x0100 . #x017F)
91 #x018F #x0192
92 (#x01FA . #x01FF)
93 (#x0218 . #x021B)
94 #x0259
95 (#x02C6 . #x02C7)
96 #x02C9
97 (#x02D8 . #x02DD)
98 (#x0300 . #x0311)
99 (#x0374 . #x0375)
100 #x037A #x037E
101 (#x0384 . #x038A)
102 #x038C
103 (#x038E . #x03A1)
104 (#x03A3 . #x03CE)
105 #x03D1
106 (#x03D5 . #x03D6)
107 #x03F1
108 (#x0401 . #x040C)
109 (#x040E . #x044F)
110 (#x0451 . #x045C)
111 (#x045E . #x045F)
112 (#x0490 . #x0491)
113 (#x05D0 . #x05EA)
114 (#x1E02 . #x1E03)
115 (#x1E0A . #x1E0B)
116 (#x1E1E . #x1E1F)
117 (#x1E40 . #x1E41)
118 (#x1E56 . #x1E57)
119 (#x1E60 . #x1E61)
120 (#x1E6A . #x1E6B)
121 (#x1E80 . #x1E85)
122 (#x1EF2 . #x1EF3)
123 (#x2010 . #x2022)
124 #x2026 #x2030
125 (#x2032 . #x2034)
126 (#x2039 . #x203A)
127 #x203C #x203E #x2044
128 (#x2070 . #x2071)
129 (#x2074 . #x208E)
130 (#x20A3 . #x20A4)
131 #x20A7 #x20AC
132 (#x20D0 . #x20D7)
133 #x2102 #x2105 #x2113
134 (#x2115 . #x2116)
135 #x211A #x211D #x2122 #x2124 #x2126 #x212E
136 (#x215B . #x215E)
137 (#x2190 . #x2195)
138 (#x21A4 . #x21A8)
139 (#x21D0 . #x21D5)
140 (#x2200 . #x2209)
141 (#x220B . #x220C)
142 #x220F
143 (#x2211 . #x2213)
144 #x2215
145 (#x2218 . #x221A)
146 (#x221D . #x221F)
147 #x2221
148 (#x2224 . #x222B)
149 #x222E #x223C #x2243 #x2245
150 (#x2248 . #x2249)
151 #x2259
152 (#x225F . #x2262)
153 (#x2264 . #x2265)
154 (#x226A . #x226B)
155 (#x2282 . #x228B)
156 #x2295 #x2297
157 (#x22A4 . #x22A7)
158 (#x22C2 . #x22C3)
159 #x22C5 #x2300 #x2302
160 (#x2308 . #x230B)
161 #x2310
162 (#x2320 . #x2321)
163 (#x2329 . #x232A)
164 (#x23BA . #x23BD)
165 (#x2409 . #x240D)
166 #x2424 #x2500 #x2502 #x250C #x2510 #x2514 #x2518 #x251C #x2524 #x252C #x2534 #x253C
167 (#x254C . #x2573)
168 (#x2580 . #x25A1)
169 (#x25AA . #x25AC)
170 (#x25B2 . #x25B3)
171 #x25BA #x25BC #x25C4 #x25C6
172 (#x25CA . #x25CB)
173 #x25CF
174 (#x25D8 . #x25D9)
175 #x25E6
176 (#x263A . #x263C)
177 #x2640 #x2642 #x2660 #x2663
178 (#x2665 . #x2666)
179 (#x266A . #x266B)
180 (#xFB01 . #xFB02)
181 #xFFFD]
182 "Glyph set for TARGET2 glyph repertoire of the misc-fixed-* fonts.
183This repertoire is supported for the following fonts:
1845x7.bdf 5x8.bdf 6x9.bdf 6x10.bdf 6x12.bdf 7x13.bdf 7x14.bdf clR6x12.bdf")
185
186(defconst nxml-misc-fixed-3-glyph-set
187 [(#x0020 . #x007E)
188 (#x00A0 . #x00FF)
189 (#x0100 . #x01FF)
190 (#x0200 . #x0220)
191 (#x0222 . #x0233)
192 (#x0250 . #x02AD)
193 (#x02B0 . #x02EE)
194 (#x0300 . #x034F)
195 (#x0360 . #x036F)
196 (#x0374 . #x0375)
197 #x037A #x037E
198 (#x0384 . #x038A)
199 #x038C
200 (#x038E . #x03A1)
201 (#x03A3 . #x03CE)
202 (#x03D0 . #x03F6)
203 (#x0400 . #x0486)
204 (#x0488 . #x04CE)
205 (#x04D0 . #x04F5)
206 (#x04F8 . #x04F9)
207 (#x0500 . #x050F)
208 (#x0531 . #x0556)
209 (#x0559 . #x055F)
210 (#x0561 . #x0587)
211 (#x0589 . #x058A)
212 (#x05B0 . #x05B9)
213 (#x05BB . #x05C4)
214 (#x05D0 . #x05EA)
215 (#x05F0 . #x05F4)
216 (#x10D0 . #x10F8)
217 #x10FB
218 (#x1E00 . #x1E9B)
219 (#x1EA0 . #x1EF9)
220 (#x1F00 . #x1F15)
221 (#x1F18 . #x1F1D)
222 (#x1F20 . #x1F45)
223 (#x1F48 . #x1F4D)
224 (#x1F50 . #x1F57)
225 #x1F59 #x1F5B #x1F5D
226 (#x1F5F . #x1F7D)
227 (#x1F80 . #x1FB4)
228 (#x1FB6 . #x1FC4)
229 (#x1FC6 . #x1FD3)
230 (#x1FD6 . #x1FDB)
231 (#x1FDD . #x1FEF)
232 (#x1FF2 . #x1FF4)
233 (#x1FF6 . #x1FFE)
234 (#x2000 . #x200A)
235 (#x2010 . #x2027)
236 (#x202F . #x2052)
237 #x2057
238 (#x205F . #x2063)
239 (#x2070 . #x2071)
240 (#x2074 . #x208E)
241 (#x20A0 . #x20B1)
242 (#x20D0 . #x20EA)
243 (#x2100 . #x213A)
244 (#x213D . #x214B)
245 (#x2153 . #x2183)
246 (#x2190 . #x21FF)
247 (#x2200 . #x22FF)
248 (#x2300 . #x23CE)
249 (#x2400 . #x2426)
250 (#x2440 . #x244A)
251 (#x2500 . #x25FF)
252 (#x2600 . #x2613)
253 (#x2616 . #x2617)
254 (#x2619 . #x267D)
255 (#x2680 . #x2689)
256 (#x27E6 . #x27EB)
257 (#x27F5 . #x27FF)
258 (#x2A00 . #x2A06)
259 #x2A1D #x2A3F #x303F
260 (#xFB00 . #xFB06)
261 (#xFB13 . #xFB17)
262 (#xFB1D . #xFB36)
263 (#xFB38 . #xFB3C)
264 #xFB3E
265 (#xFB40 . #xFB41)
266 (#xFB43 . #xFB44)
267 (#xFB46 . #xFB4F)
268 (#xFE20 . #xFE23)
269 (#xFF61 . #xFF9F)
270 #xFFFD]
271 "Glyph set for TARGET3 glyph repertoire of the misc-fixed-* fonts.
272This repertoire is supported for the following fonts:
2736x13.bdf 8x13.bdf 9x15.bdf 9x18.bdf 10x20.bdf")
274
275(defconst nxml-wgl4-glyph-set
276 [(#x0020 . #x007E)
277 (#x00A0 . #x017F)
278 #x0192
279 (#x01FA . #x01FF)
280 (#x02C6 . #x02C7)
281 #x02C9
282 (#x02D8 . #x02DB)
283 #x02DD
284 (#x0384 . #x038A)
285 #x038C
286 (#x038E . #x03A1)
287 (#x03A3 . #x03CE)
288 (#x0401 . #x040C)
289 (#x040E . #x044F)
290 (#x0451 . #x045C)
291 (#x045E . #x045F)
292 (#x0490 . #x0491)
293 (#x1E80 . #x1E85)
294 (#x1EF2 . #x1EF3)
295 (#x2013 . #x2015)
296 (#x2017 . #x201E)
297 (#x2020 . #x2022)
298 #x2026 #x2030
299 (#x2032 . #x2033)
300 (#x2039 . #x203A)
301 #x203C #x203E #x2044 #x207F
302 (#x20A3 . #x20A4)
303 #x20A7 #x20AC #x2105 #x2113 #x2116 #x2122 #x2126 #x212E
304 (#x215B . #x215E)
305 (#x2190 . #x2195)
306 #x21A8 #x2202 #x2206 #x220F
307 (#x2211 . #x2212)
308 #x2215
309 (#x2219 . #x221A)
310 (#x221E . #x221F)
311 #x2229 #x222B #x2248
312 (#x2260 . #x2261)
313 (#x2264 . #x2265)
314 #x2302 #x2310
315 (#x2320 . #x2321)
316 #x2500 #x2502 #x250C #x2510 #x2514 #x2518 #x251C #x2524
317 #x252C #x2534 #x253C
318 (#x2550 . #x256C)
319 #x2580 #x2584 #x2588 #x258C
320 (#x2590 . #x2593)
321 (#x25A0 . #x25A1)
322 (#x25AA . #x25AC)
323 #x25B2 #x25BA #x25BC #x25C4
324 (#x25CA . #x25CB)
325 #x25CF
326 (#x25D8 . #x25D9)
327 #x25E6
328 (#x263A . #x263C)
329 #x2640 #x2642 #x2660 #x2663
330 (#x2665 . #x2666)
331 (#x266A . #x266B)
332 (#xFB01 . #xFB02)]
333 "Glyph set corresponding to Windows Glyph List 4.")
334
335(defvar nxml-glyph-set-functions nil
336 "Abnormal hook for determining the set of glyphs in a face.
337Each function in this hook is called in turn, unless one of them
338returns non-nil. Each function is called with a single argument
339FACE. If it can determine the set of glyphs representable by
340FACE, it must set the variable `nxml-glyph-set' and return
341non-nil. Otherwise, it must return nil.
342
343The constants `nxml-ascii-glyph-set', `nxml-latin1-glyph-set',
344`nxml-misc-fixed-1-glyph-set', `nxml-misc-fixed-2-glyph-set',
345`nxml-misc-fixed-3-glyph-set' and `nxml-wgl4-glyph-set' are
346predefined for use by `nxml-glyph-set-functions'.")
347
348(define-obsolete-variable-alias 'nxml-glyph-set-hook
349 'nxml-glyph-set-functions "24.3")
350
351(defvar nxml-glyph-set nil
352 "Used by `nxml-glyph-set-functions' to return set of glyphs in a FACE.
353This should dynamically bound by any function that runs
354`nxml-glyph-set-functions'. The value must be either nil representing an
355empty set or a vector. Each member of the vector is either a single
356integer or a cons (FIRST . LAST) representing the range of integers
357from FIRST to LAST. An integer represents a glyph with that Unicode
358code-point. The vector must be ordered.")
359
360(defun nxml-x-set-glyph-set (face)
361 (setq nxml-glyph-set
362 (if (equal (face-attribute face :family) "misc-fixed")
363 nxml-misc-fixed-3-glyph-set
364 nxml-wgl4-glyph-set)))
365
366(defun nxml-w32-set-glyph-set (face)
367 (setq nxml-glyph-set nxml-wgl4-glyph-set))
368
369(defun nxml-window-system-set-glyph-set (face)
370 (setq nxml-glyph-set nxml-latin1-glyph-set))
371
372(defun nxml-terminal-set-glyph-set (face)
373 (setq nxml-glyph-set nxml-ascii-glyph-set))
374
375(add-hook 'nxml-glyph-set-functions
376 (or (cdr (assq window-system
377 '((x . nxml-x-set-glyph-set)
378 (w32 . nxml-w32-set-glyph-set)
379 (nil . nxml-terminal-set-glyph-set))))
380 'nxml-window-system-set-glyph-set)
381 t)
382
383;;;###autoload
384(defun nxml-glyph-display-string (n face)
385 "Return a string that can display a glyph for Unicode code-point N.
386FACE gives the face that will be used for displaying the string.
387Return nil if the face cannot display a glyph for N."
388 (let ((nxml-glyph-set nil))
389 (run-hook-with-args-until-success 'nxml-glyph-set-functions face)
390 (and nxml-glyph-set
391 (nxml-glyph-set-contains-p n nxml-glyph-set)
392 (let ((ch (decode-char 'ucs n)))
393 (and ch (string ch))))))
394
395(defun nxml-glyph-set-contains-p (n v)
396 (let ((start 0)
397 (end (length v))
398 found mid mid-val mid-start-val mid-end-val)
399 (while (> end start)
400 (setq mid (+ start
401 (/ (- end start) 2)))
402 (setq mid-val (aref v mid))
403 (if (consp mid-val)
404 (setq mid-start-val (car mid-val)
405 mid-end-val (cdr mid-val))
406 (setq mid-start-val mid-val
407 mid-end-val mid-val))
408 (cond ((and (<= mid-start-val n)
409 (<= n mid-end-val))
410 (setq found t)
411 (setq start end))
412 ((< n mid-start-val)
413 (setq end mid))
414 (t
415 (setq start
416 (if (eq start mid)
417 end
418 mid)))))
419 found))
420
421(provide 'nxml-glyph)
422
423;;; nxml-glyph.el ends here
diff --git a/lisp/nxml/nxml-maint.el b/lisp/nxml/nxml-maint.el
index b81e3113efb..5d24d9b3138 100644
--- a/lisp/nxml/nxml-maint.el
+++ b/lisp/nxml/nxml-maint.el
@@ -1,4 +1,4 @@
1;;; nxml-maint.el --- commands for maintainers of nxml-*.el 1;;; nxml-maint.el --- commands for maintainers of nxml-*.el -*- lexical-binding:t -*-
2 2
3;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. 3;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc.
4 4
@@ -24,48 +24,6 @@
24 24
25;;; Code: 25;;; Code:
26 26
27;;; Generating files with Unicode char names.
28
29(require 'nxml-uchnm)
30
31(defun nxml-create-unicode-char-name-sets (file)
32 "Generate files containing char names from Unicode standard."
33 (interactive "fUnicodeData file: ")
34 (mapc (lambda (block)
35 (let ((nameset (nxml-unicode-block-char-name-set (nth 0 block))))
36 (save-excursion
37 (find-file (concat (get nameset 'nxml-char-name-set-file)
38 ".el"))
39 (erase-buffer)
40 (insert "(nxml-define-char-name-set '")
41 (prin1 nameset (current-buffer))
42 (insert "\n '())\n")
43 (goto-char (- (point) 3)))))
44 nxml-unicode-blocks)
45 (save-excursion
46 (find-file file)
47 (goto-char (point-min))
48 (let ((blocks nxml-unicode-blocks)
49 code name)
50 (while (re-search-forward "^\\([0-9A-F]+\\);\\([^<;][^;]*\\);"
51 nil
52 t)
53 (setq code (string-to-number (match-string 1) 16))
54 (setq name (match-string 2))
55 (while (and blocks
56 (> code (nth 2 (car blocks))))
57 (setq blocks (cdr blocks)))
58 (when (and (<= (nth 1 (car blocks)) code)
59 (<= code (nth 2 (car blocks))))
60 (save-excursion
61 (find-file (concat (get (nxml-unicode-block-char-name-set
62 (nth 0 (car blocks)))
63 'nxml-char-name-set-file)
64 ".el"))
65 (insert "(")
66 (prin1 name (current-buffer))
67 (insert (format " #x%04X)\n " code))))))))
68
69;;; Parsing target repertoire files from ucs-fonts. 27;;; Parsing target repertoire files from ucs-fonts.
70;; This is for converting the TARGET? files in 28;; This is for converting the TARGET? files in
71;; http://www.cl.cam.ac.uk/~mgk25/download/ucs-fonts.tar.gz 29;; http://www.cl.cam.ac.uk/~mgk25/download/ucs-fonts.tar.gz
diff --git a/lisp/nxml/nxml-mode.el b/lisp/nxml/nxml-mode.el
index 324350f591c..edc7414bfbf 100644
--- a/lisp/nxml/nxml-mode.el
+++ b/lisp/nxml/nxml-mode.el
@@ -26,14 +26,10 @@
26 26
27;;; Code: 27;;; Code:
28 28
29(when (featurep 'mucs)
30 (error "nxml-mode is not compatible with Mule-UCS"))
31
32(eval-when-compile (require 'cl-lib)) 29(eval-when-compile (require 'cl-lib))
33 30
34(require 'xmltok) 31(require 'xmltok)
35(require 'nxml-enc) 32(require 'nxml-enc)
36(require 'nxml-glyph)
37(require 'nxml-util) 33(require 'nxml-util)
38(require 'nxml-rap) 34(require 'nxml-rap)
39(require 'nxml-outln) 35(require 'nxml-outln)
@@ -41,6 +37,7 @@
41;; So we might as well just require it and silence the compiler. 37;; So we might as well just require it and silence the compiler.
42(provide 'nxml-mode) ; avoid recursive require 38(provide 'nxml-mode) ; avoid recursive require
43(require 'rng-nxml) 39(require 'rng-nxml)
40(require 'sgml-mode)
44 41
45;;; Customization 42;;; Customization
46 43
@@ -55,9 +52,7 @@
55 52
56(defcustom nxml-char-ref-display-glyph-flag t 53(defcustom nxml-char-ref-display-glyph-flag t
57 "Non-nil means display glyph following character reference. 54 "Non-nil means display glyph following character reference.
58The glyph is displayed in face `nxml-glyph'. The abnormal hook 55The glyph is displayed in face `nxml-glyph'."
59`nxml-glyph-set-functions' can be used to change the characters
60for which glyphs are displayed."
61 :group 'nxml 56 :group 'nxml
62 :type 'boolean) 57 :type 'boolean)
63 58
@@ -153,16 +148,6 @@ This is not used directly, but only via inheritance by other faces."
153 "Face used to highlight text." 148 "Face used to highlight text."
154 :group 'nxml-faces) 149 :group 'nxml-faces)
155 150
156(defface nxml-comment-content
157 '((t (:inherit font-lock-comment-face)))
158 "Face used to highlight the content of comments."
159 :group 'nxml-faces)
160
161(defface nxml-comment-delimiter
162 '((t (:inherit font-lock-comment-delimiter-face)))
163 "Face used for the delimiters of comments, i.e., <!-- and -->."
164 :group 'nxml-faces)
165
166(defface nxml-processing-instruction-delimiter 151(defface nxml-processing-instruction-delimiter
167 '((t (:inherit nxml-delimiter))) 152 '((t (:inherit nxml-delimiter)))
168 "Face used for the delimiters of processing instructions, i.e., <? and ?>." 153 "Face used for the delimiters of processing instructions, i.e., <? and ?>."
@@ -280,15 +265,6 @@ This includes ths `x' in hex references."
280 "Face used for the delimiters of attribute values." 265 "Face used for the delimiters of attribute values."
281 :group 'nxml-faces) 266 :group 'nxml-faces)
282 267
283(defface nxml-namespace-attribute-value
284 '((t (:inherit nxml-attribute-value)))
285 "Face used for the value of namespace attributes."
286 :group 'nxml-faces)
287
288(defface nxml-namespace-attribute-value-delimiter
289 '((t (:inherit nxml-attribute-value-delimiter)))
290 "Face used for the delimiters of namespace attribute values."
291 :group 'nxml-faces)
292 268
293(defface nxml-prolog-literal-delimiter 269(defface nxml-prolog-literal-delimiter
294 '((t (:inherit nxml-delimited-data))) 270 '((t (:inherit nxml-delimited-data)))
@@ -342,22 +318,19 @@ The delimiters are <! and >."
342 318
343;;; Global variables 319;;; Global variables
344 320
345(defvar nxml-parent-document nil 321(defvar-local nxml-parent-document nil
346 "The parent document for a part of a modular document. 322 "The parent document for a part of a modular document.
347Use `nxml-parent-document-set' to set it.") 323Use `nxml-parent-document-set' to set it.")
348(make-variable-buffer-local 'nxml-parent-document)
349(put 'nxml-parent-document 'safe-local-variable 'stringp) 324(put 'nxml-parent-document 'safe-local-variable 'stringp)
350 325
351(defvar nxml-prolog-regions nil 326(defvar-local nxml-prolog-regions nil
352 "List of regions in the prolog to be fontified. 327 "List of regions in the prolog to be fontified.
353See the function `xmltok-forward-prolog' for more information.") 328See the function `xmltok-forward-prolog' for more information.")
354(make-variable-buffer-local 'nxml-prolog-regions)
355 329
356(defvar nxml-degraded nil 330(defvar-local nxml-degraded nil
357 "Non-nil if currently operating in degraded mode. 331 "Non-nil if currently operating in degraded mode.
358Degraded mode is enabled when an internal error is encountered in the 332Degraded mode is enabled when an internal error is encountered in the
359fontification or after-change functions.") 333fontification or after-change functions.")
360(make-variable-buffer-local 'nxml-degraded)
361 334
362(defvar nxml-completion-hook nil 335(defvar nxml-completion-hook nil
363 "Hook run by `nxml-complete'. 336 "Hook run by `nxml-complete'.
@@ -375,13 +348,12 @@ one of the functions returns nil.")
375(defvar nxml-end-tag-indent-scan-distance 4000 348(defvar nxml-end-tag-indent-scan-distance 4000
376 "Maximum distance from point to scan backwards when indenting end-tag.") 349 "Maximum distance from point to scan backwards when indenting end-tag.")
377 350
378(defvar nxml-char-ref-extra-display t 351(defvar-local nxml-char-ref-extra-display t
379 "Non-nil means display extra information for character references. 352 "Non-nil means display extra information for character references.
380The extra information consists of a tooltip with the character name 353The extra information consists of a tooltip with the character name
381and, if `nxml-char-ref-display-glyph-flag' is non-nil, a glyph 354and, if `nxml-char-ref-display-glyph-flag' is non-nil, a glyph
382corresponding to the referenced character following the character 355corresponding to the referenced character following the character
383reference.") 356reference.")
384(make-variable-buffer-local 'nxml-char-ref-extra-display)
385 357
386(defvar nxml-mode-map 358(defvar nxml-mode-map
387 (let ((map (make-sparse-keymap))) 359 (let ((map (make-sparse-keymap)))
@@ -415,7 +387,9 @@ reference.")
415 387
416(defsubst nxml-set-face (start end face) 388(defsubst nxml-set-face (start end face)
417 (when (and face (< start end)) 389 (when (and face (< start end))
418 (font-lock-append-text-property start end 'face face))) 390 ;; Prepend, so the character reference highlighting takes precedence over
391 ;; the string highlighting applied syntactically.
392 (font-lock-prepend-text-property start end 'face face)))
419 393
420(defun nxml-parent-document-set (parent-document) 394(defun nxml-parent-document-set (parent-document)
421 "Set `nxml-parent-document' and inherit the DTD &c." 395 "Set `nxml-parent-document' and inherit the DTD &c."
@@ -519,53 +493,39 @@ Many aspects this mode can be customized using
519 ;; FIXME: Use the fact that we're parsing the document already 493 ;; FIXME: Use the fact that we're parsing the document already
520 ;; rather than using regex-based filtering. 494 ;; rather than using regex-based filtering.
521 (setq-local tildify-foreach-region-function 495 (setq-local tildify-foreach-region-function
522 (apply-partially 'tildify-foreach-ignore-environments 496 (apply-partially #'tildify-foreach-ignore-environments
523 '(("<! *--" . "-- *>") ("<" . ">")))) 497 '(("<! *--" . "-- *>") ("<" . ">"))))
524 (set (make-local-variable 'mode-line-process) '((nxml-degraded "/degraded"))) 498 (setq-local mode-line-process '((nxml-degraded "/degraded")))
525 ;; We'll determine the fill prefix ourselves 499 ;; We'll determine the fill prefix ourselves
526 (make-local-variable 'adaptive-fill-mode) 500 (setq-local adaptive-fill-mode nil)
527 (setq adaptive-fill-mode nil) 501 (setq-local forward-sexp-function #'nxml-forward-balanced-item)
528 (make-local-variable 'forward-sexp-function) 502 (setq-local indent-line-function #'nxml-indent-line)
529 (setq forward-sexp-function 'nxml-forward-balanced-item) 503 (setq-local fill-paragraph-function #'nxml-do-fill-paragraph)
530 (make-local-variable 'indent-line-function)
531 (setq indent-line-function 'nxml-indent-line)
532 (make-local-variable 'fill-paragraph-function)
533 (setq fill-paragraph-function 'nxml-do-fill-paragraph)
534 ;; Comment support 504 ;; Comment support
535 ;; This doesn't seem to work too well; 505 ;; This doesn't seem to work too well;
536 ;; I think we should probably roll our own nxml-comment-dwim function. 506 ;; I think we should probably roll our own nxml-comment-dwim function.
537 (make-local-variable 'comment-indent-function) 507 (setq-local comment-indent-function #'nxml-indent-line)
538 (setq comment-indent-function 'nxml-indent-line) 508 (setq-local comment-start "<!--")
539 (make-local-variable 'comment-start) 509 (setq-local comment-start-skip "<!--[ \t\r\n]*")
540 (setq comment-start "<!--") 510 (setq-local comment-end "-->")
541 (make-local-variable 'comment-start-skip) 511 (setq-local comment-end-skip "[ \t\r\n]*-->")
542 (setq comment-start-skip "<!--[ \t\r\n]*") 512 (setq-local comment-line-break-function #'nxml-newline-and-indent)
543 (make-local-variable 'comment-end) 513 (setq-local comment-quote-nested-function #'nxml-comment-quote-nested)
544 (setq comment-end "-->")
545 (make-local-variable 'comment-end-skip)
546 (setq comment-end-skip "[ \t\r\n]*-->")
547 (make-local-variable 'comment-line-break-function)
548 (setq comment-line-break-function 'nxml-newline-and-indent)
549 (setq-local comment-quote-nested-function 'nxml-comment-quote-nested)
550 (use-local-map nxml-mode-map)
551 (save-excursion 514 (save-excursion
552 (save-restriction 515 (save-restriction
553 (widen) 516 (widen)
554 (setq nxml-scan-end (copy-marker (point-min) nil))
555 (with-silent-modifications 517 (with-silent-modifications
556 (nxml-clear-inside (point-min) (point-max))
557 (nxml-with-invisible-motion 518 (nxml-with-invisible-motion
558 (nxml-scan-prolog))))) 519 (nxml-scan-prolog)))))
559 (add-hook 'completion-at-point-functions 520 (setq-local syntax-ppss-table sgml-tag-syntax-table)
560 #'nxml-completion-at-point-function nil t) 521 (setq-local syntax-propertize-function sgml-syntax-propertize-function)
561 (setq-local syntax-propertize-function #'nxml-after-change) 522 (add-hook 'change-major-mode-hook #'nxml-cleanup nil t)
562 (add-hook 'change-major-mode-hook 'nxml-cleanup nil t)
563 523
564 ;; Emacs 23 handles the encoding attribute on the xml declaration 524 ;; Emacs 23 handles the encoding attribute on the xml declaration
565 ;; transparently to nxml-mode, so there is no longer a need for the below 525 ;; transparently to nxml-mode, so there is no longer a need for the below
566 ;; hook. The hook also had the drawback of overriding explicit user 526 ;; hook. The hook also had the drawback of overriding explicit user
567 ;; instruction to save as some encoding other than utf-8. 527 ;; instruction to save as some encoding other than utf-8.
568 ;;(add-hook 'write-contents-hooks 'nxml-prepare-to-save) 528 ;;(add-hook 'write-contents-hooks #'nxml-prepare-to-save)
569 (when (not (and (buffer-file-name) (file-exists-p (buffer-file-name)))) 529 (when (not (and (buffer-file-name) (file-exists-p (buffer-file-name))))
570 (when (and nxml-default-buffer-file-coding-system 530 (when (and nxml-default-buffer-file-coding-system
571 (not (local-variable-p 'buffer-file-coding-system))) 531 (not (local-variable-p 'buffer-file-coding-system)))
@@ -575,16 +535,14 @@ Many aspects this mode can be customized using
575 535
576 (setq font-lock-defaults 536 (setq font-lock-defaults
577 '(nxml-font-lock-keywords 537 '(nxml-font-lock-keywords
578 t ; keywords-only; we highlight comments and strings here 538 nil ; highlight comments and strings based on syntax-tables
579 nil ; font-lock-keywords-case-fold-search. XML is case sensitive 539 nil ; font-lock-keywords-case-fold-search. XML is case sensitive
580 nil ; no special syntax table 540 nil ; no special syntax table
581 nil ; no automatic syntactic fontification
582 (font-lock-extend-region-functions . (nxml-extend-region)) 541 (font-lock-extend-region-functions . (nxml-extend-region))
583 (jit-lock-contextually . t) 542 (jit-lock-contextually . t)
584 (font-lock-unfontify-region-function . nxml-unfontify-region))) 543 (font-lock-unfontify-region-function . nxml-unfontify-region)))
585 544
586 (rng-nxml-mode-init) 545 (with-demoted-errors (rng-nxml-mode-init)))
587 (nxml-enable-unicode-char-name-sets))
588 546
589(defun nxml-cleanup () 547(defun nxml-cleanup ()
590 "Clean up after nxml-mode." 548 "Clean up after nxml-mode."
@@ -596,7 +554,7 @@ Many aspects this mode can be customized using
596 (with-silent-modifications 554 (with-silent-modifications
597 (nxml-with-invisible-motion 555 (nxml-with-invisible-motion
598 (remove-text-properties (point-min) (point-max) '(face))))) 556 (remove-text-properties (point-min) (point-max) '(face)))))
599 (remove-hook 'change-major-mode-hook 'nxml-cleanup t)) 557 (remove-hook 'change-major-mode-hook #'nxml-cleanup t))
600 558
601(defun nxml-degrade (context err) 559(defun nxml-degrade (context err)
602 (message "Internal nXML mode error in %s (%s), degrading" 560 (message "Internal nXML mode error in %s (%s), degrading"
@@ -604,12 +562,7 @@ Many aspects this mode can be customized using
604 (error-message-string err)) 562 (error-message-string err))
605 (ding) 563 (ding)
606 (setq nxml-degraded t) 564 (setq nxml-degraded t)
607 (setq nxml-prolog-end 1) 565 (setq nxml-prolog-end 1))
608 (save-excursion
609 (save-restriction
610 (widen)
611 (with-silent-modifications
612 (nxml-clear-inside (point-min) (point-max))))))
613 566
614;;; Change management 567;;; Change management
615 568
@@ -622,41 +575,6 @@ Many aspects this mode can be customized using
622 (goto-char font-lock-beg) 575 (goto-char font-lock-beg)
623 (set-mark font-lock-end))) 576 (set-mark font-lock-end)))
624 577
625(defun nxml-after-change (start end)
626 ;; Called via syntax-propertize-function.
627 (unless nxml-degraded
628 (nxml-with-degradation-on-error 'nxml-after-change
629 (save-restriction
630 (widen)
631 (nxml-with-invisible-motion
632 (nxml-after-change1 start end))))))
633
634(defun nxml-after-change1 (start end)
635 "After-change bookkeeping.
636Returns a cons cell containing a possibly-enlarged change region.
637You must call `nxml-extend-region' on this expanded region to obtain
638the full extent of the area needing refontification.
639
640For bookkeeping, call this function even when fontification is
641disabled."
642 ;; If the prolog might have changed, rescan the prolog.
643 (when (<= start
644 ;; Add 2 so as to include the < and following char that
645 ;; start the instance (document element), since changing
646 ;; these can change where the prolog ends.
647 (+ nxml-prolog-end 2))
648 (nxml-scan-prolog)
649 (setq start (point-min)))
650
651 (when (> end nxml-prolog-end)
652 (goto-char start)
653 (nxml-move-tag-backwards (point-min))
654 (setq start (point))
655 (setq end (max (nxml-scan-after-change start end)
656 end)))
657
658 (nxml-debug-change "nxml-after-change1" start end))
659
660;;; Encodings 578;;; Encodings
661 579
662(defun nxml-insert-xml-declaration () 580(defun nxml-insert-xml-declaration ()
@@ -982,11 +900,11 @@ faces appropriately."
982 [1 -1 nxml-entity-ref-name] 900 [1 -1 nxml-entity-ref-name]
983 [-1 nil nxml-entity-ref-delimiter])) 901 [-1 nil nxml-entity-ref-delimiter]))
984 902
985(put 'comment 903;; (put 'comment
986 'nxml-fontify-rule 904;; 'nxml-fontify-rule
987 '([nil 4 nxml-comment-delimiter] 905;; '([nil 4 nxml-comment-delimiter]
988 [4 -3 nxml-comment-content] 906;; [4 -3 nxml-comment-content]
989 [-3 nil nxml-comment-delimiter])) 907;; [-3 nil nxml-comment-delimiter]))
990 908
991(put 'processing-instruction 909(put 'processing-instruction
992 'nxml-fontify-rule 910 'nxml-fontify-rule
@@ -1018,7 +936,7 @@ faces appropriately."
1018 'nxml-fontify-rule 936 'nxml-fontify-rule
1019 '([nil nil nxml-attribute-local-name])) 937 '([nil nil nxml-attribute-local-name]))
1020 938
1021(put 'xml-declaration-attribute-value 939(put 'xml-declaration-attribute-value ;FIXME: What is this for?
1022 'nxml-fontify-rule 940 'nxml-fontify-rule
1023 '([nil 1 nxml-attribute-value-delimiter] 941 '([nil 1 nxml-attribute-value-delimiter]
1024 [1 -1 nxml-attribute-value] 942 [1 -1 nxml-attribute-value]
@@ -1137,28 +1055,11 @@ faces appropriately."
1137 'nxml-attribute-prefix 1055 'nxml-attribute-prefix
1138 'nxml-attribute-colon 1056 'nxml-attribute-colon
1139 'nxml-attribute-local-name)) 1057 'nxml-attribute-local-name))
1140 (let ((start (xmltok-attribute-value-start att)) 1058 (dolist (ref (xmltok-attribute-refs att))
1141 (end (xmltok-attribute-value-end att)) 1059 (let* ((ref-type (aref ref 0))
1142 (refs (xmltok-attribute-refs att)) 1060 (ref-start (aref ref 1))
1143 (delimiter-face (if namespace-declaration 1061 (ref-end (aref ref 2)))
1144 'nxml-namespace-attribute-value-delimiter 1062 (nxml-apply-fontify-rule ref-type ref-start ref-end))))
1145 'nxml-attribute-value-delimiter))
1146 (value-face (if namespace-declaration
1147 'nxml-namespace-attribute-value
1148 'nxml-attribute-value)))
1149 (when start
1150 (nxml-set-face (1- start) start delimiter-face)
1151 (nxml-set-face end (1+ end) delimiter-face)
1152 (while refs
1153 (let* ((ref (car refs))
1154 (ref-type (aref ref 0))
1155 (ref-start (aref ref 1))
1156 (ref-end (aref ref 2)))
1157 (nxml-set-face start ref-start value-face)
1158 (nxml-apply-fontify-rule ref-type ref-start ref-end)
1159 (setq start ref-end))
1160 (setq refs (cdr refs)))
1161 (nxml-set-face start end value-face))))
1162 1063
1163(defun nxml-fontify-qname (start 1064(defun nxml-fontify-qname (start
1164 colon 1065 colon
@@ -1599,30 +1500,7 @@ of the line. This expects the xmltok-* variables to be set up as by
1599 (t (back-to-indentation))) 1500 (t (back-to-indentation)))
1600 (current-column)) 1501 (current-column))
1601 1502
1602;;; Completion 1503(define-obsolete-function-alias 'nxml-complete #'completion-at-point "26.1")
1603
1604(defun nxml-complete ()
1605 "Perform completion on the symbol preceding point.
1606
1607Inserts as many characters as can be completed. However, if not even
1608one character can be completed, then a buffer with the possibilities
1609is popped up and the symbol is read from the minibuffer with
1610completion. If the symbol is complete, then any characters that must
1611follow the symbol are also inserted.
1612
1613The name space used for completion and what is treated as a symbol
1614depends on the context. The contexts in which completion is performed
1615depend on `nxml-completion-hook'."
1616 (interactive)
1617 (unless (run-hook-with-args-until-success 'nxml-completion-hook)
1618 ;; Eventually we will complete on entity names here.
1619 (ding)
1620 (message "Cannot complete in this context")))
1621
1622(defun nxml-completion-at-point-function ()
1623 "Call `nxml-complete' to perform completion at point."
1624 (when nxml-bind-meta-tab-to-complete-flag
1625 #'nxml-complete))
1626 1504
1627;;; Movement 1505;;; Movement
1628 1506
@@ -1674,7 +1552,7 @@ single name. A character reference contains a character number."
1674 (t end))))) 1552 (t end)))))
1675 (nxml-scan-error 1553 (nxml-scan-error
1676 (goto-char (cadr err)) 1554 (goto-char (cadr err))
1677 (apply 'error (cddr err))))) 1555 (apply #'error (cddr err)))))
1678 1556
1679(defun nxml-backward-single-balanced-item () 1557(defun nxml-backward-single-balanced-item ()
1680 (condition-case err 1558 (condition-case err
@@ -1696,7 +1574,7 @@ single name. A character reference contains a character number."
1696 (t xmltok-start))))) 1574 (t xmltok-start)))))
1697 (nxml-scan-error 1575 (nxml-scan-error
1698 (goto-char (cadr err)) 1576 (goto-char (cadr err))
1699 (apply 'error (cddr err))))) 1577 (apply #'error (cddr err)))))
1700 1578
1701(defun nxml-scan-forward-within (end) 1579(defun nxml-scan-forward-within (end)
1702 (setq end (- end (nxml-end-delimiter-length xmltok-type))) 1580 (setq end (- end (nxml-end-delimiter-length xmltok-type)))
@@ -1880,7 +1758,7 @@ single name. A character reference contains a character number."
1880 (setq arg (1- arg))) 1758 (setq arg (1- arg)))
1881 (nxml-scan-error 1759 (nxml-scan-error
1882 (goto-char (cadr err)) 1760 (goto-char (cadr err))
1883 (apply 'error (cddr err)))))) 1761 (apply #'error (cddr err))))))
1884 1762
1885(defun nxml-backward-up-element (&optional arg) 1763(defun nxml-backward-up-element (&optional arg)
1886 (interactive "p") 1764 (interactive "p")
@@ -1909,7 +1787,7 @@ single name. A character reference contains a character number."
1909 (setq arg (1- arg))) 1787 (setq arg (1- arg)))
1910 (nxml-scan-error 1788 (nxml-scan-error
1911 (goto-char (cadr err)) 1789 (goto-char (cadr err))
1912 (apply 'error (cddr err)))))) 1790 (apply #'error (cddr err))))))
1913 1791
1914(defun nxml-down-element (&optional arg) 1792(defun nxml-down-element (&optional arg)
1915 "Move forward down into the content of an element. 1793 "Move forward down into the content of an element.
@@ -1974,7 +1852,7 @@ Negative ARG means move backward."
1974 (setq arg (1- arg))) 1852 (setq arg (1- arg)))
1975 (nxml-scan-error 1853 (nxml-scan-error
1976 (goto-char (cadr err)) 1854 (goto-char (cadr err))
1977 (apply 'error (cddr err)))))) 1855 (apply #'error (cddr err))))))
1978 1856
1979(defun nxml-backward-element (&optional arg) 1857(defun nxml-backward-element (&optional arg)
1980 "Move backward over one element. 1858 "Move backward over one element.
@@ -1996,7 +1874,7 @@ Negative ARG means move forward."
1996 (setq arg (1- arg))) 1874 (setq arg (1- arg)))
1997 (nxml-scan-error 1875 (nxml-scan-error
1998 (goto-char (cadr err)) 1876 (goto-char (cadr err))
1999 (apply 'error (cddr err)))))) 1877 (apply #'error (cddr err))))))
2000 1878
2001(defun nxml-mark-token-after () 1879(defun nxml-mark-token-after ()
2002 (interactive) 1880 (interactive)
@@ -2477,116 +2355,15 @@ and attempts to find another possible way to do the markup."
2477 2355
2478;;; Character names 2356;;; Character names
2479 2357
2480(defvar nxml-char-name-ignore-case t)
2481
2482(defvar nxml-char-name-alist nil
2483 "Alist of character names.
2484Each member of the list has the form (NAME CODE . NAMESET),
2485where NAME is a string naming a character, NAMESET is a symbol
2486identifying a set of names and CODE is an integer specifying the
2487Unicode scalar value of the named character.
2488The NAME will only be used for completion if NAMESET has
2489a non-nil `nxml-char-name-set-enabled' property.
2490If NAMESET does does not have `nxml-char-name-set-defined' property,
2491then it must have a `nxml-char-name-set-file' property and `load'
2492will be applied to the value of this property if the nameset
2493is enabled.")
2494
2495(defvar nxml-char-name-table (make-hash-table :test 'eq)
2496 "Hash table for mapping char codes to names.
2497Each key is a Unicode scalar value.
2498Each value is a list of pairs of the form (NAMESET . NAME),
2499where NAMESET is a symbol identifying a set of names,
2500and NAME is a string naming a character.")
2501
2502(defvar nxml-autoload-char-name-set-list nil
2503 "List of char namesets that can be autoloaded.")
2504
2505(defun nxml-enable-char-name-set (nameset)
2506 (put nameset 'nxml-char-name-set-enabled t))
2507
2508(defun nxml-disable-char-name-set (nameset)
2509 (put nameset 'nxml-char-name-set-enabled nil))
2510
2511(defun nxml-char-name-set-enabled-p (nameset)
2512 (get nameset 'nxml-char-name-set-enabled))
2513
2514(defun nxml-autoload-char-name-set (nameset file)
2515 (unless (memq nameset nxml-autoload-char-name-set-list)
2516 (setq nxml-autoload-char-name-set-list
2517 (cons nameset nxml-autoload-char-name-set-list)))
2518 (put nameset 'nxml-char-name-set-file file))
2519
2520(defun nxml-define-char-name-set (nameset alist)
2521 "Define a set of character names.
2522NAMESET is a symbol identifying the set.
2523ALIST is a list where each member has the form (NAME CODE),
2524where NAME is a string naming a character and code is an
2525integer giving the Unicode scalar value of the character."
2526 (when (get nameset 'nxml-char-name-set-defined)
2527 (error "Nameset `%s' already defined" nameset))
2528 (let ((iter alist))
2529 (while iter
2530 (let* ((name-code (car iter))
2531 (name (car name-code))
2532 (code (cadr name-code)))
2533 (puthash code
2534 (cons (cons nameset name)
2535 (gethash code nxml-char-name-table))
2536 nxml-char-name-table))
2537 (setcdr (cdr (car iter)) nameset)
2538 (setq iter (cdr iter))))
2539 (setq nxml-char-name-alist
2540 (nconc alist nxml-char-name-alist))
2541 (put nameset 'nxml-char-name-set-defined t))
2542
2543(defun nxml-get-char-name (code)
2544 (mapc 'nxml-maybe-load-char-name-set nxml-autoload-char-name-set-list)
2545 (let ((names (gethash code nxml-char-name-table))
2546 name)
2547 (while (and names (not name))
2548 (if (nxml-char-name-set-enabled-p (caar names))
2549 (setq name (cdar names))
2550 (setq names (cdr names))))
2551 name))
2552
2553(defvar nxml-named-char-history nil)
2554
2555(defun nxml-insert-named-char (arg) 2358(defun nxml-insert-named-char (arg)
2556 "Insert a character using its name. 2359 "Insert a character using its name.
2557The name is read from the minibuffer. 2360The name is read from the minibuffer.
2558Normally, inserts the character as a numeric character reference. 2361Normally, inserts the character as a numeric character reference.
2559With a prefix argument, inserts the character directly." 2362With a prefix argument, inserts the character directly."
2560 (interactive "*P") 2363 (interactive "*P")
2561 (mapc 'nxml-maybe-load-char-name-set nxml-autoload-char-name-set-list) 2364 (let ((code (read-char-by-name "Character name: ")))
2562 (let ((name
2563 (let ((completion-ignore-case nxml-char-name-ignore-case))
2564 (completing-read "Character name: "
2565 nxml-char-name-alist
2566 (lambda (member)
2567 (get (cddr member) 'nxml-char-name-set-enabled))
2568 t
2569 nil
2570 'nxml-named-char-history)))
2571 (alist nxml-char-name-alist)
2572 elt code)
2573 (while (and alist (not code))
2574 (setq elt (assoc name alist))
2575 (if (get (cddr elt) 'nxml-char-name-set-enabled)
2576 (setq code (cadr elt))
2577 (setq alist (cdr (member elt alist)))))
2578 (when code 2365 (when code
2579 (insert (if arg 2366 (insert (if arg code (format "&#x%X;" code))))))
2580 (or (decode-char 'ucs code)
2581 (error "Character %x is not supported by Emacs"
2582 code))
2583 (format "&#x%X;" code))))))
2584
2585(defun nxml-maybe-load-char-name-set (sym)
2586 (when (and (get sym 'nxml-char-name-set-enabled)
2587 (not (get sym 'nxml-char-name-set-defined))
2588 (stringp (get sym 'nxml-char-name-set-file)))
2589 (load (get sym 'nxml-char-name-set-file))))
2590 2367
2591(defun nxml-toggle-char-ref-extra-display (arg) 2368(defun nxml-toggle-char-ref-extra-display (arg)
2592 "Toggle the display of extra information for character references." 2369 "Toggle the display of extra information for character references."
@@ -2602,9 +2379,11 @@ With a prefix argument, inserts the character directly."
2602 2379
2603(defun nxml-char-ref-display-extra (start end n) 2380(defun nxml-char-ref-display-extra (start end n)
2604 (when nxml-char-ref-extra-display 2381 (when nxml-char-ref-extra-display
2605 (let ((name (nxml-get-char-name n)) 2382 (let ((name (or (get-char-code-property n 'name)
2383 (get-char-code-property n 'old-name)))
2606 (glyph-string (and nxml-char-ref-display-glyph-flag 2384 (glyph-string (and nxml-char-ref-display-glyph-flag
2607 (nxml-glyph-display-string n 'nxml-glyph))) 2385 (char-displayable-p n)
2386 (string n)))
2608 ov) 2387 ov)
2609 (when (or name glyph-string) 2388 (when (or name glyph-string)
2610 (setq ov (make-overlay start end nil t)) 2389 (setq ov (make-overlay start end nil t))
diff --git a/lisp/nxml/nxml-outln.el b/lisp/nxml/nxml-outln.el
index 962160cb435..289816a1bba 100644
--- a/lisp/nxml/nxml-outln.el
+++ b/lisp/nxml/nxml-outln.el
@@ -1,4 +1,4 @@
1;;; nxml-outln.el --- outline support for nXML mode 1;;; nxml-outln.el --- outline support for nXML mode -*- lexical-binding:t -*-
2 2
3;; Copyright (C) 2004, 2007-2016 Free Software Foundation, Inc. 3;; Copyright (C) 2004, 2007-2016 Free Software Foundation, Inc.
4 4
@@ -248,6 +248,16 @@ customize which elements are recognized as sections and headings."
248 (interactive) 248 (interactive)
249 (nxml-transform-subtree-outline '((hide-children . t)))) 249 (nxml-transform-subtree-outline '((hide-children . t))))
250 250
251;; These variables are dynamically bound. They are use to pass information to
252;; nxml-section-tag-transform-outline-state.
253
254(defvar nxml-outline-state-transform-exceptions nil)
255(defvar nxml-target-section-pos nil)
256(defvar nxml-depth-in-target-section nil)
257(defvar nxml-outline-state-transform-alist nil)
258
259(defvar nxml-outline-display-section-tag-function nil)
260
251(defun nxml-hide-other () 261(defun nxml-hide-other ()
252 "Hide text content other than that directly in the section containing point. 262 "Hide text content other than that directly in the section containing point.
253Hide headings other than those of ancestors of that section and their 263Hide headings other than those of ancestors of that section and their
@@ -275,14 +285,6 @@ customize which elements are recognized as sections and headings."
275 (nxml-transform-buffer-outline '((nil . hide-children) 285 (nxml-transform-buffer-outline '((nil . hide-children)
276 (t . hide-children))))) 286 (t . hide-children)))))
277 287
278;; These variables are dynamically bound. They are use to pass information to
279;; nxml-section-tag-transform-outline-state.
280
281(defvar nxml-outline-state-transform-exceptions nil)
282(defvar nxml-target-section-pos nil)
283(defvar nxml-depth-in-target-section nil)
284(defvar nxml-outline-state-transform-alist nil)
285
286(defun nxml-transform-buffer-outline (alist) 288(defun nxml-transform-buffer-outline (alist)
287 (let ((nxml-target-section-pos nil) 289 (let ((nxml-target-section-pos nil)
288 (nxml-depth-in-target-section 0) 290 (nxml-depth-in-target-section 0)
@@ -350,7 +352,7 @@ customize which elements are recognized as sections and headings."
350(defun nxml-section-tag-transform-outline-state (startp 352(defun nxml-section-tag-transform-outline-state (startp
351 section-start-pos 353 section-start-pos
352 &optional 354 &optional
353 heading-start-pos) 355 _heading-start-pos)
354 (if (not startp) 356 (if (not startp)
355 (setq nxml-depth-in-target-section 357 (setq nxml-depth-in-target-section
356 (and nxml-depth-in-target-section 358 (and nxml-depth-in-target-section
@@ -427,8 +429,6 @@ customize which elements are recognized as sections and headings."
427 (nxml-outline-error 429 (nxml-outline-error
428 (nxml-report-outline-error "Cannot display outline: %s" err))))) 430 (nxml-report-outline-error "Cannot display outline: %s" err)))))
429 431
430(defvar nxml-outline-display-section-tag-function nil)
431
432(defun nxml-outline-display-rest (outline-state start-tag-indent tag-qnames) 432(defun nxml-outline-display-rest (outline-state start-tag-indent tag-qnames)
433 "Display up to and including the end of the current element. 433 "Display up to and including the end of the current element.
434OUTLINE-STATE can be nil, t, hide-children. START-TAG-INDENT is the 434OUTLINE-STATE can be nil, t, hide-children. START-TAG-INDENT is the
@@ -789,7 +789,7 @@ no new overlay will be created."
789(defun nxml-end-of-heading () 789(defun nxml-end-of-heading ()
790 "Move from the start of the content of the heading to the end. 790 "Move from the start of the content of the heading to the end.
791Do not move past the end of the line." 791Do not move past the end of the line."
792 (let ((pos (condition-case err 792 (let ((pos (condition-case nil
793 (and (nxml-scan-element-forward (point) t) 793 (and (nxml-scan-element-forward (point) t)
794 xmltok-start) 794 xmltok-start)
795 (nxml-scan-error nil)))) 795 (nxml-scan-error nil))))
@@ -888,7 +888,7 @@ Point is at the end of the tag. `xmltok-start' is the start."
888 (nxml-ensure-scan-up-to-date) 888 (nxml-ensure-scan-up-to-date)
889 (let ((pos (nxml-inside-start (point)))) 889 (let ((pos (nxml-inside-start (point))))
890 (when pos 890 (when pos
891 (goto-char (1- pos)) 891 (goto-char pos)
892 t)))) 892 t))))
893 ((progn 893 ((progn
894 (xmltok-forward) 894 (xmltok-forward)
diff --git a/lisp/nxml/nxml-parse.el b/lisp/nxml/nxml-parse.el
index 41b2e8ee513..edf012921a9 100644
--- a/lisp/nxml/nxml-parse.el
+++ b/lisp/nxml/nxml-parse.el
@@ -1,4 +1,4 @@
1;;; nxml-parse.el --- XML parser, sharing infrastructure with nxml-mode 1;;; nxml-parse.el --- XML parser, sharing infrastructure with nxml-mode -*- lexical-binding:t -*-
2 2
3;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. 3;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc.
4 4
diff --git a/lisp/nxml/nxml-rap.el b/lisp/nxml/nxml-rap.el
index 47b23da62ad..e66289d042a 100644
--- a/lisp/nxml/nxml-rap.el
+++ b/lisp/nxml/nxml-rap.el
@@ -1,4 +1,4 @@
1;;; nxml-rap.el --- low-level support for random access parsing for nXML mode 1;;; nxml-rap.el --- low-level support for random access parsing for nXML mode -*- lexical-binding:t -*-
2 2
3;; Copyright (C) 2003-2004, 2007-2016 Free Software Foundation, Inc. 3;; Copyright (C) 2003-2004, 2007-2016 Free Software Foundation, Inc.
4 4
@@ -46,8 +46,7 @@
46;; look like it scales to large numbers of overlays in a buffer. 46;; look like it scales to large numbers of overlays in a buffer.
47;; 47;;
48;; We don't in fact track all these constructs, but only track them in 48;; We don't in fact track all these constructs, but only track them in
49;; some initial part of the instance. The variable `nxml-scan-end' 49;; some initial part of the instance.
50;; contains the limit of where we have scanned up to for them.
51;; 50;;
52;; Thus to parse some random point in the file we first ensure that we 51;; Thus to parse some random point in the file we first ensure that we
53;; have scanned up to that point. Then we search backwards for a 52;; have scanned up to that point. Then we search backwards for a
@@ -74,93 +73,33 @@
74 73
75(require 'xmltok) 74(require 'xmltok)
76(require 'nxml-util) 75(require 'nxml-util)
76(require 'sgml-mode)
77 77
78(defvar nxml-prolog-end nil 78(defvar-local nxml-prolog-end nil
79 "Integer giving position following end of the prolog.") 79 "Integer giving position following end of the prolog.")
80(make-variable-buffer-local 'nxml-prolog-end)
81
82(defvar nxml-scan-end nil
83 "Marker giving position up to which we have scanned.
84nxml-scan-end must be >= nxml-prolog-end. Furthermore, nxml-scan-end
85must not be an inside position in the following sense. A position is
86inside if the following character is a part of, but not the first
87character of, a CDATA section, comment or processing instruction.
88Furthermore all positions >= nxml-prolog-end and < nxml-scan-end that
89are inside positions must have a non-nil `nxml-inside' property whose
90value is a symbol specifying what it is inside. Any characters with a
91non-nil `fontified' property must have position < nxml-scan-end and
92the correct face. Dependent regions must also be established for any
93unclosed constructs starting before nxml-scan-end.
94There must be no `nxml-inside' properties after nxml-scan-end.")
95(make-variable-buffer-local 'nxml-scan-end)
96 80
97(defsubst nxml-get-inside (pos) 81(defsubst nxml-get-inside (pos)
98 (get-text-property pos 'nxml-inside)) 82 (save-excursion (nth 8 (syntax-ppss pos))))
99
100(defsubst nxml-clear-inside (start end)
101 (nxml-debug-clear-inside start end)
102 (remove-text-properties start end '(nxml-inside nil)))
103
104(defsubst nxml-set-inside (start end type)
105 (nxml-debug-set-inside start end)
106 (put-text-property start end 'nxml-inside type))
107 83
108(defun nxml-inside-end (pos) 84(defun nxml-inside-end (pos)
109 "Return the end of the inside region containing POS. 85 "Return the end of the inside region containing POS.
110Return nil if the character at POS is not inside." 86Return nil if the character at POS is not inside."
111 (if (nxml-get-inside pos) 87 (save-excursion
112 (or (next-single-property-change pos 'nxml-inside) 88 (let ((ppss (syntax-ppss pos)))
113 (point-max)) 89 (when (nth 8 ppss)
114 nil)) 90 (goto-char (nth 8 ppss))
91 (with-syntax-table sgml-tag-syntax-table
92 (if (nth 3 ppss)
93 (progn (forward-comment 1) (point))
94 (or (scan-sexps (point) 1) (point-max))))))))
115 95
116(defun nxml-inside-start (pos) 96(defun nxml-inside-start (pos)
117 "Return the start of the inside region containing POS. 97 "Return the start of the inside region containing POS.
118Return nil if the character at POS is not inside." 98Return nil if the character at POS is not inside."
119 (if (nxml-get-inside pos) 99 (save-excursion (nth 8 (syntax-ppss pos))))
120 (or (previous-single-property-change (1+ pos) 'nxml-inside)
121 (point-min))
122 nil))
123 100
124;;; Change management 101;;; Change management
125 102
126(defun nxml-scan-after-change (start end)
127 "Restore `nxml-scan-end' invariants after a change.
128The change happened between START and END.
129Return position after which lexical state is unchanged.
130END must be > `nxml-prolog-end'. START must be outside
131any “inside” regions and at the beginning of a token."
132 (if (>= start nxml-scan-end)
133 nxml-scan-end
134 (let ((inside-remove-start start)
135 xmltok-errors)
136 (while (or (when (xmltok-forward-special (min end nxml-scan-end))
137 (when (memq xmltok-type
138 '(comment
139 cdata-section
140 processing-instruction))
141 (nxml-clear-inside inside-remove-start
142 (1+ xmltok-start))
143 (nxml-set-inside (1+ xmltok-start)
144 (point)
145 xmltok-type)
146 (setq inside-remove-start (point)))
147 (if (< (point) (min end nxml-scan-end))
148 t
149 (setq end (point))
150 nil))
151 ;; The end of the change was inside but is now outside.
152 ;; Imagine something really weird like
153 ;; <![CDATA[foo <!-- bar ]]> <![CDATA[ stuff --> <!-- ]]> -->
154 ;; and suppose we deleted "<![CDATA[f"
155 (let ((inside-end (nxml-inside-end end)))
156 (when inside-end
157 (setq end inside-end)
158 t))))
159 (nxml-clear-inside inside-remove-start end))
160 (when (> end nxml-scan-end)
161 (set-marker nxml-scan-end end))
162 end))
163
164;; n-s-p only called from nxml-mode.el, where this variable is defined. 103;; n-s-p only called from nxml-mode.el, where this variable is defined.
165(defvar nxml-prolog-regions) 104(defvar nxml-prolog-regions)
166 105
@@ -169,10 +108,7 @@ any “inside” regions and at the beginning of a token."
169 (let (xmltok-dtd 108 (let (xmltok-dtd
170 xmltok-errors) 109 xmltok-errors)
171 (setq nxml-prolog-regions (xmltok-forward-prolog)) 110 (setq nxml-prolog-regions (xmltok-forward-prolog))
172 (setq nxml-prolog-end (point)) 111 (setq nxml-prolog-end (point))))
173 (nxml-clear-inside (point-min) nxml-prolog-end))
174 (when (< nxml-scan-end nxml-prolog-end)
175 (set-marker nxml-scan-end nxml-prolog-end)))
176 112
177 113
178;;; Random access parsing 114;;; Random access parsing
@@ -223,14 +159,7 @@ Sets variables like `nxml-token-after'."
223 159
224(defun nxml-tokenize-forward () 160(defun nxml-tokenize-forward ()
225 (let (xmltok-errors) 161 (let (xmltok-errors)
226 (when (and (xmltok-forward) 162 (xmltok-forward)
227 (> (point) nxml-scan-end))
228 (cond ((memq xmltok-type '(comment
229 cdata-section
230 processing-instruction))
231 (with-silent-modifications
232 (nxml-set-inside (1+ xmltok-start) (point) xmltok-type))))
233 (set-marker nxml-scan-end (point)))
234 xmltok-type)) 163 xmltok-type))
235 164
236(defun nxml-move-tag-backwards (bound) 165(defun nxml-move-tag-backwards (bound)
@@ -253,32 +182,12 @@ As a precondition, point must be >= BOUND."
253Leave point unmoved if it is not inside anything special." 182Leave point unmoved if it is not inside anything special."
254 (let ((start (nxml-inside-start (point)))) 183 (let ((start (nxml-inside-start (point))))
255 (when start 184 (when start
256 (goto-char (1- start)) 185 (goto-char start)
257 (when (nxml-get-inside (point)) 186 (when (nxml-get-inside (point))
258 (error "Char before inside-start at %s had nxml-inside property %s" 187 (error "Char before inside-start at %s is still \"inside\"" (point))))))
259 (point)
260 (nxml-get-inside (point)))))))
261 188
262(defun nxml-ensure-scan-up-to-date () 189(defun nxml-ensure-scan-up-to-date ()
263 (let ((pos (point))) 190 (syntax-propertize (point)))
264 (when (< nxml-scan-end pos)
265 (save-excursion
266 (goto-char nxml-scan-end)
267 (let (xmltok-errors)
268 (while (when (xmltok-forward-special pos)
269 (when (memq xmltok-type
270 '(comment
271 processing-instruction
272 cdata-section))
273 (with-silent-modifications
274 (nxml-set-inside (1+ xmltok-start)
275 (point)
276 xmltok-type)))
277 (if (< (point) pos)
278 t
279 (setq pos (point))
280 nil)))
281 (set-marker nxml-scan-end pos))))))
282 191
283;;; Element scanning 192;;; Element scanning
284 193
diff --git a/lisp/nxml/nxml-uchnm.el b/lisp/nxml/nxml-uchnm.el
deleted file mode 100644
index 7d7d785f152..00000000000
--- a/lisp/nxml/nxml-uchnm.el
+++ /dev/null
@@ -1,251 +0,0 @@
1;;; nxml-uchnm.el --- support for Unicode standard cha names in nxml-mode
2
3;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc.
4
5;; Author: James Clark
6;; Keywords: wp, hypermedia, languages, XML
7
8;; This file is part of GNU Emacs.
9
10;; GNU Emacs is free software: you can redistribute it and/or modify
11;; it under the terms of the GNU General Public License as published by
12;; the Free Software Foundation, either version 3 of the License, or
13;; (at your option) any later version.
14
15;; GNU Emacs is distributed in the hope that it will be useful,
16;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18;; GNU General Public License for more details.
19
20;; You should have received a copy of the GNU General Public License
21;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
22
23;;; Commentary:
24
25;; This enables the use of the character names defined in the Unicode
26;; Standard. The use of the names can be controlled on a per-block
27;; basis, so as both to reduce memory usage and loading time,
28;; and to make completion work better.
29
30;;; Code:
31
32(require 'nxml-mode)
33
34(defconst nxml-unicode-blocks
35 '(("Basic Latin" #x0000 #x007F)
36 ("Latin-1 Supplement" #x0080 #x00FF)
37 ("Latin Extended-A" #x0100 #x017F)
38 ("Latin Extended-B" #x0180 #x024F)
39 ("IPA Extensions" #x0250 #x02AF)
40 ("Spacing Modifier Letters" #x02B0 #x02FF)
41 ("Combining Diacritical Marks" #x0300 #x036F)
42 ("Greek and Coptic" #x0370 #x03FF)
43 ("Cyrillic" #x0400 #x04FF)
44 ("Cyrillic Supplementary" #x0500 #x052F)
45 ("Armenian" #x0530 #x058F)
46 ("Hebrew" #x0590 #x05FF)
47 ("Arabic" #x0600 #x06FF)
48 ("Syriac" #x0700 #x074F)
49 ("Thaana" #x0780 #x07BF)
50 ("Devanagari" #x0900 #x097F)
51 ("Bengali" #x0980 #x09FF)
52 ("Gurmukhi" #x0A00 #x0A7F)
53 ("Gujarati" #x0A80 #x0AFF)
54 ("Oriya" #x0B00 #x0B7F)
55 ("Tamil" #x0B80 #x0BFF)
56 ("Telugu" #x0C00 #x0C7F)
57 ("Kannada" #x0C80 #x0CFF)
58 ("Malayalam" #x0D00 #x0D7F)
59 ("Sinhala" #x0D80 #x0DFF)
60 ("Thai" #x0E00 #x0E7F)
61 ("Lao" #x0E80 #x0EFF)
62 ("Tibetan" #x0F00 #x0FFF)
63 ("Myanmar" #x1000 #x109F)
64 ("Georgian" #x10A0 #x10FF)
65 ("Hangul Jamo" #x1100 #x11FF)
66 ("Ethiopic" #x1200 #x137F)
67 ("Cherokee" #x13A0 #x13FF)
68 ("Unified Canadian Aboriginal Syllabics" #x1400 #x167F)
69 ("Ogham" #x1680 #x169F)
70 ("Runic" #x16A0 #x16FF)
71 ("Tagalog" #x1700 #x171F)
72 ("Hanunoo" #x1720 #x173F)
73 ("Buhid" #x1740 #x175F)
74 ("Tagbanwa" #x1760 #x177F)
75 ("Khmer" #x1780 #x17FF)
76 ("Mongolian" #x1800 #x18AF)
77 ("Latin Extended Additional" #x1E00 #x1EFF)
78 ("Greek Extended" #x1F00 #x1FFF)
79 ("General Punctuation" #x2000 #x206F)
80 ("Superscripts and Subscripts" #x2070 #x209F)
81 ("Currency Symbols" #x20A0 #x20CF)
82 ("Combining Diacritical Marks for Symbols" #x20D0 #x20FF)
83 ("Letterlike Symbols" #x2100 #x214F)
84 ("Number Forms" #x2150 #x218F)
85 ("Arrows" #x2190 #x21FF)
86 ("Mathematical Operators" #x2200 #x22FF)
87 ("Miscellaneous Technical" #x2300 #x23FF)
88 ("Control Pictures" #x2400 #x243F)
89 ("Optical Character Recognition" #x2440 #x245F)
90 ("Enclosed Alphanumerics" #x2460 #x24FF)
91 ("Box Drawing" #x2500 #x257F)
92 ("Block Elements" #x2580 #x259F)
93 ("Geometric Shapes" #x25A0 #x25FF)
94 ("Miscellaneous Symbols" #x2600 #x26FF)
95 ("Dingbats" #x2700 #x27BF)
96 ("Miscellaneous Mathematical Symbols-A" #x27C0 #x27EF)
97 ("Supplemental Arrows-A" #x27F0 #x27FF)
98 ("Braille Patterns" #x2800 #x28FF)
99 ("Supplemental Arrows-B" #x2900 #x297F)
100 ("Miscellaneous Mathematical Symbols-B" #x2980 #x29FF)
101 ("Supplemental Mathematical Operators" #x2A00 #x2AFF)
102 ("CJK Radicals Supplement" #x2E80 #x2EFF)
103 ("Kangxi Radicals" #x2F00 #x2FDF)
104 ("Ideographic Description Characters" #x2FF0 #x2FFF)
105 ("CJK Symbols and Punctuation" #x3000 #x303F)
106 ("Hiragana" #x3040 #x309F)
107 ("Katakana" #x30A0 #x30FF)
108 ("Bopomofo" #x3100 #x312F)
109 ("Hangul Compatibility Jamo" #x3130 #x318F)
110 ("Kanbun" #x3190 #x319F)
111 ("Bopomofo Extended" #x31A0 #x31BF)
112 ("Katakana Phonetic Extensions" #x31F0 #x31FF)
113 ("Enclosed CJK Letters and Months" #x3200 #x32FF)
114 ("CJK Compatibility" #x3300 #x33FF)
115 ("CJK Unified Ideographs Extension A" #x3400 #x4DBF)
116 ;;("CJK Unified Ideographs" #x4E00 #x9FFF)
117 ("Yi Syllables" #xA000 #xA48F)
118 ("Yi Radicals" #xA490 #xA4CF)
119 ;;("Hangul Syllables" #xAC00 #xD7AF)
120 ;;("High Surrogates" #xD800 #xDB7F)
121 ;;("High Private Use Surrogates" #xDB80 #xDBFF)
122 ;;("Low Surrogates" #xDC00 #xDFFF)
123 ;;("Private Use Area" #xE000 #xF8FF)
124 ;;("CJK Compatibility Ideographs" #xF900 #xFAFF)
125 ("Alphabetic Presentation Forms" #xFB00 #xFB4F)
126 ("Arabic Presentation Forms-A" #xFB50 #xFDFF)
127 ("Variation Selectors" #xFE00 #xFE0F)
128 ("Combining Half Marks" #xFE20 #xFE2F)
129 ("CJK Compatibility Forms" #xFE30 #xFE4F)
130 ("Small Form Variants" #xFE50 #xFE6F)
131 ("Arabic Presentation Forms-B" #xFE70 #xFEFF)
132 ("Halfwidth and Fullwidth Forms" #xFF00 #xFFEF)
133 ("Specials" #xFFF0 #xFFFF)
134 ("Old Italic" #x10300 #x1032F)
135 ("Gothic" #x10330 #x1034F)
136 ("Deseret" #x10400 #x1044F)
137 ("Byzantine Musical Symbols" #x1D000 #x1D0FF)
138 ("Musical Symbols" #x1D100 #x1D1FF)
139 ("Mathematical Alphanumeric Symbols" #x1D400 #x1D7FF)
140 ;;("CJK Unified Ideographs Extension B" #x20000 #x2A6DF)
141 ;;("CJK Compatibility Ideographs Supplement" #x2F800 #x2FA1F)
142 ("Tags" #xE0000 #xE007F)
143 ;;("Supplementary Private Use Area-A" #xF0000 #xFFFFF)
144 ;;("Supplementary Private Use Area-B" #x100000 #x10FFFF)
145 )
146 "List of Unicode blocks.
147For each block there is a list (NAME FIRST LAST), where
148NAME is a string giving the official name of the block,
149FIRST is the first code-point and LAST is the last code-point.
150Blocks containing only characters with algorithmic names or no names
151are omitted.")
152
153(defun nxml-unicode-block-char-name-set (name)
154 "Return a symbol for a block whose official Unicode name is NAME.
155The symbol is generated by downcasing and replacing each space
156by a hyphen."
157 (intern (replace-regexp-in-string " " "-" (downcase name))))
158
159;; This is intended to be a superset of the coverage
160;; of existing standard entity sets.
161(defvar nxml-enabled-unicode-blocks-default
162 '(basic-latin
163 latin-1-supplement
164 latin-extended-a
165 latin-extended-b
166 ipa-extensions
167 spacing-modifier-letters
168 combining-diacritical-marks
169 greek-and-coptic
170 cyrillic
171 general-punctuation
172 superscripts-and-subscripts
173 currency-symbols
174 combining-diacritical-marks-for-symbols
175 letterlike-symbols
176 number-forms
177 arrows
178 mathematical-operators
179 miscellaneous-technical
180 control-pictures
181 optical-character-recognition
182 enclosed-alphanumerics
183 box-drawing
184 block-elements
185 geometric-shapes
186 miscellaneous-symbols
187 dingbats
188 miscellaneous-mathematical-symbols-a
189 supplemental-arrows-a
190 supplemental-arrows-b
191 miscellaneous-mathematical-symbols-b
192 supplemental-mathematical-operators
193 cjk-symbols-and-punctuation
194 alphabetic-presentation-forms
195 variation-selectors
196 small-form-variants
197 specials
198 mathematical-alphanumeric-symbols)
199 "Default value for `nxml-enabled-unicode-blocks'.")
200
201(mapc (lambda (block)
202 (nxml-autoload-char-name-set
203 (nxml-unicode-block-char-name-set (car block))
204 (expand-file-name
205 (format "nxml/%05X-%05X"
206 (nth 1 block)
207 (nth 2 block))
208 data-directory)))
209 nxml-unicode-blocks)
210
211;; Internal flag to control whether customize reloads the character tables.
212;; Should be set the first time the
213(defvar nxml-internal-unicode-char-name-sets-enabled nil)
214
215(defcustom nxml-enabled-unicode-blocks nxml-enabled-unicode-blocks-default
216 "List of Unicode blocks for which Unicode character names are enabled.
217Each block is identified by a symbol derived from the name
218of the block by downcasing and replacing each space by a hyphen."
219 :group 'nxml
220 :set (lambda (sym value)
221 (set-default 'nxml-enabled-unicode-blocks value)
222 (when nxml-internal-unicode-char-name-sets-enabled
223 (nxml-enable-unicode-char-name-sets)))
224 :type (cons 'set
225 (mapcar (lambda (block)
226 `(const :tag ,(format "%s (%04X-%04X)"
227 (nth 0 block)
228 (nth 1 block)
229 (nth 2 block))
230 ,(nxml-unicode-block-char-name-set
231 (nth 0 block))))
232 nxml-unicode-blocks)))
233
234;;;###autoload
235(defun nxml-enable-unicode-char-name-sets ()
236 "Enable the use of Unicode standard names for characters.
237The Unicode blocks for which names are enabled is controlled by
238the variable `nxml-enabled-unicode-blocks'."
239 (interactive)
240 (setq nxml-internal-unicode-char-name-sets-enabled t)
241 (mapc (lambda (block)
242 (nxml-disable-char-name-set
243 (nxml-unicode-block-char-name-set (car block))))
244 nxml-unicode-blocks)
245 (mapc (lambda (nameset)
246 (nxml-enable-char-name-set nameset))
247 nxml-enabled-unicode-blocks))
248
249(provide 'nxml-uchnm)
250
251;;; nxml-uchnm.el ends here
diff --git a/lisp/nxml/nxml-util.el b/lisp/nxml/nxml-util.el
index 14b887ea085..282d4952bf7 100644
--- a/lisp/nxml/nxml-util.el
+++ b/lisp/nxml/nxml-util.el
@@ -36,20 +36,6 @@
36 `(nxml-debug "%s: %S" ,name 36 `(nxml-debug "%s: %S" ,name
37 (buffer-substring-no-properties ,start ,end)))) 37 (buffer-substring-no-properties ,start ,end))))
38 38
39(defmacro nxml-debug-set-inside (start end)
40 (when nxml-debug
41 `(let ((overlay (make-overlay ,start ,end)))
42 (overlay-put overlay 'face '(:background "red"))
43 (overlay-put overlay 'nxml-inside-debug t)
44 (nxml-debug-change "nxml-set-inside" ,start ,end))))
45
46(defmacro nxml-debug-clear-inside (start end)
47 (when nxml-debug
48 `(cl-loop for overlay in (overlays-in ,start ,end)
49 if (overlay-get overlay 'nxml-inside-debug)
50 do (delete-overlay overlay)
51 finally (nxml-debug-change "nxml-clear-inside" ,start ,end))))
52
53(defun nxml-make-namespace (str) 39(defun nxml-make-namespace (str)
54 "Return a symbol for the namespace URI STR. 40 "Return a symbol for the namespace URI STR.
55STR must be a string. If STR is the empty string, return nil. 41STR must be a string. If STR is the empty string, return nil.
diff --git a/lisp/nxml/rng-cmpct.el b/lisp/nxml/rng-cmpct.el
index 39aee9780ff..a699e9e3d96 100644
--- a/lisp/nxml/rng-cmpct.el
+++ b/lisp/nxml/rng-cmpct.el
@@ -1,4 +1,4 @@
1;;; rng-cmpct.el --- parsing of RELAX NG Compact Syntax schemas 1;;; rng-cmpct.el --- parsing of RELAX NG Compact Syntax schemas -*- lexical-binding:t -*-
2 2
3;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. 3;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc.
4 4
diff --git a/lisp/nxml/rng-dt.el b/lisp/nxml/rng-dt.el
index 07166e38fea..a3cb8bc6aa5 100644
--- a/lisp/nxml/rng-dt.el
+++ b/lisp/nxml/rng-dt.el
@@ -1,4 +1,4 @@
1;;; rng-dt.el --- datatype library interface for RELAX NG 1;;; rng-dt.el --- datatype library interface for RELAX NG -*- lexical-binding:t -*-
2 2
3;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. 3;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc.
4 4
@@ -57,7 +57,7 @@ a datatype library.")
57 (t 57 (t
58 (rng-dt-error "There is no built-in datatype %s" name)))) 58 (rng-dt-error "There is no built-in datatype %s" name))))
59 59
60(put (rng-make-datatypes-uri "") 'rng-dt-compile 'rng-dt-builtin-compile) 60(put (rng-make-datatypes-uri "") 'rng-dt-compile #'rng-dt-builtin-compile)
61 61
62(provide 'rng-dt) 62(provide 'rng-dt)
63 63
diff --git a/lisp/nxml/rng-loc.el b/lisp/nxml/rng-loc.el
index 553d8ca359d..376e9169d37 100644
--- a/lisp/nxml/rng-loc.el
+++ b/lisp/nxml/rng-loc.el
@@ -1,4 +1,4 @@
1;;; rng-loc.el --- locate the schema to use for validation 1;;; rng-loc.el --- Locate the schema to use for validation -*- lexical-binding:t -*-
2 2
3;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. 3;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc.
4 4
@@ -31,10 +31,9 @@
31(require 'rng-util) 31(require 'rng-util)
32(require 'xmltok) 32(require 'xmltok)
33 33
34(defvar rng-current-schema-file-name nil 34(defvar-local rng-current-schema-file-name nil
35 "Filename of schema being used for current buffer. 35 "Filename of schema being used for current buffer.
36It is nil if using a vacuous schema.") 36It is nil if using a vacuous schema.")
37(make-variable-buffer-local 'rng-current-schema-file-name)
38 37
39(defvar rng-schema-locating-files-default 38(defvar rng-schema-locating-files-default
40 (list "schemas.xml" (expand-file-name "schema/schemas.xml" data-directory)) 39 (list "schemas.xml" (expand-file-name "schema/schemas.xml" data-directory))
@@ -233,11 +232,11 @@ or nil."
233 rules)))))))) 232 rules))))))))
234 best-so-far)) 233 best-so-far))
235 234
236(put 'documentElement 'rng-rule-matcher 'rng-match-document-element-rule) 235(put 'documentElement 'rng-rule-matcher #'rng-match-document-element-rule)
237(put 'namespace 'rng-rule-matcher 'rng-match-namespace-rule) 236(put 'namespace 'rng-rule-matcher #'rng-match-namespace-rule)
238(put 'uri 'rng-rule-matcher 'rng-match-uri-rule) 237(put 'uri 'rng-rule-matcher #'rng-match-uri-rule)
239(put 'transformURI 'rng-rule-matcher 'rng-match-transform-uri-rule) 238(put 'transformURI 'rng-rule-matcher #'rng-match-transform-uri-rule)
240(put 'default 'rng-rule-matcher 'rng-match-default-rule) 239(put 'default 'rng-rule-matcher #'rng-match-default-rule)
241 240
242(defun rng-match-document-element-rule (props) 241(defun rng-match-document-element-rule (props)
243 (let ((document-element (rng-document-element)) 242 (let ((document-element (rng-document-element))
diff --git a/lisp/nxml/rng-maint.el b/lisp/nxml/rng-maint.el
index 165ca8930a4..32a041e0c17 100644
--- a/lisp/nxml/rng-maint.el
+++ b/lisp/nxml/rng-maint.el
@@ -1,4 +1,4 @@
1;;; rng-maint.el --- commands for RELAX NG maintainers 1;;; rng-maint.el --- commands for RELAX NG maintainers -*- lexical-binding:t -*-
2 2
3;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. 3;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc.
4 4
diff --git a/lisp/nxml/rng-match.el b/lisp/nxml/rng-match.el
index df9c0192557..d2b629e8d83 100644
--- a/lisp/nxml/rng-match.el
+++ b/lisp/nxml/rng-match.el
@@ -56,9 +56,8 @@ Used to detect invalid recursive references.")
56;;; Inline functions 56;;; Inline functions
57 57
58(defsubst rng-update-match-state (new-state) 58(defsubst rng-update-match-state (new-state)
59 (if (and (eq new-state rng-not-allowed-ipattern) 59 (if (eq new-state rng-not-allowed-ipattern)
60 (not (eq rng-match-state rng-not-allowed-ipattern))) 60 (eq rng-match-state rng-not-allowed-ipattern)
61 nil
62 (setq rng-match-state new-state) 61 (setq rng-match-state new-state)
63 t)) 62 t))
64 63
diff --git a/lisp/nxml/rng-nxml.el b/lisp/nxml/rng-nxml.el
index fe90dffb555..954a1eb9599 100644
--- a/lisp/nxml/rng-nxml.el
+++ b/lisp/nxml/rng-nxml.el
@@ -1,4 +1,4 @@
1;;; rng-nxml.el --- make nxml-mode take advantage of rng-validate-mode 1;;; rng-nxml.el --- make nxml-mode take advantage of rng-validate-mode -*- lexical-binding:t -*-
2 2
3;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. 3;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc.
4 4
@@ -33,6 +33,7 @@
33(require 'rng-valid) 33(require 'rng-valid)
34(require 'nxml-mode) 34(require 'nxml-mode)
35(require 'rng-loc) 35(require 'rng-loc)
36(require 'sgml-mode)
36 37
37(defcustom rng-nxml-auto-validate-flag t 38(defcustom rng-nxml-auto-validate-flag t
38 "Non-nil means automatically turn on validation with nxml-mode." 39 "Non-nil means automatically turn on validation with nxml-mode."
@@ -65,6 +66,9 @@ Complete on start-tag names regardless.")
65 ["Validation" rng-validate-mode 66 ["Validation" rng-validate-mode
66 :style toggle 67 :style toggle
67 :selected rng-validate-mode] 68 :selected rng-validate-mode]
69 ["Electric Pairs" sgml-electric-tag-pair-mode
70 :style toggle
71 :selected sgml-electric-tag-pair-mode]
68 "---" 72 "---"
69 ("Set Schema" 73 ("Set Schema"
70 ["Automatically" rng-auto-set-schema] 74 ["Automatically" rng-auto-set-schema]
@@ -107,25 +111,15 @@ Validation will be enabled if `rng-nxml-auto-validate-flag' is non-nil."
107 'append) 111 'append)
108 (cond (rng-nxml-auto-validate-flag 112 (cond (rng-nxml-auto-validate-flag
109 (rng-validate-mode 1) 113 (rng-validate-mode 1)
110 (add-hook 'nxml-completion-hook 'rng-complete nil t) 114 (add-hook 'completion-at-point-functions #'rng-completion-at-point nil t)
111 (add-hook 'nxml-in-mixed-content-hook 'rng-in-mixed-content-p nil t)) 115 (add-hook 'nxml-in-mixed-content-hook #'rng-in-mixed-content-p nil t))
112 (t 116 (t
113 (rng-validate-mode 0) 117 (rng-validate-mode 0)
114 (remove-hook 'nxml-completion-hook 'rng-complete t) 118 (remove-hook 'completion-at-point-functions #'rng-completion-at-point t)
115 (remove-hook 'nxml-in-mixed-content-hook 'rng-in-mixed-content-p t)))) 119 (remove-hook 'nxml-in-mixed-content-hook #'rng-in-mixed-content-p t))))
116
117(defvar rng-tag-history nil)
118(defvar rng-attribute-name-history nil)
119(defvar rng-attribute-value-history nil)
120
121(defvar rng-complete-target-names nil)
122(defvar rng-complete-name-attribute-flag nil)
123(defvar rng-complete-extra-strings nil)
124 120
125(defun rng-complete () 121(defun rng-completion-at-point ()
126 "Complete the string before point using the current schema. 122 "Return completion data for the string before point using the current schema."
127Return non-nil if in a context it understands."
128 (interactive)
129 (and rng-validate-mode 123 (and rng-validate-mode
130 (let ((lt-pos (save-excursion (search-backward "<" nil t))) 124 (let ((lt-pos (save-excursion (search-backward "<" nil t)))
131 xmltok-dtd) 125 xmltok-dtd)
@@ -145,53 +139,48 @@ Return non-nil if in a context it understands."
145 t)) 139 t))
146 140
147(defun rng-complete-tag (lt-pos) 141(defun rng-complete-tag (lt-pos)
148 (let (rng-complete-extra-strings) 142 (let ((extra-strings
149 (when (and (= lt-pos (1- (point))) 143 (when (and (= lt-pos (1- (point)))
150 rng-complete-end-tags-after-< 144 rng-complete-end-tags-after-<
151 rng-open-elements 145 rng-open-elements
152 (not (eq (car rng-open-elements) t)) 146 (not (eq (car rng-open-elements) t))
153 (or rng-collecting-text 147 (or rng-collecting-text
154 (rng-match-save 148 (rng-match-save
155 (rng-match-end-tag)))) 149 (rng-match-end-tag))))
156 (setq rng-complete-extra-strings 150 (list (concat "/"
157 (cons (concat "/" 151 (if (caar rng-open-elements)
158 (if (caar rng-open-elements) 152 (concat (caar rng-open-elements)
159 (concat (caar rng-open-elements) 153 ":"
160 ":" 154 (cdar rng-open-elements))
161 (cdar rng-open-elements)) 155 (cdar rng-open-elements)))))))
162 (cdar rng-open-elements)))
163 rng-complete-extra-strings)))
164 (when (save-excursion 156 (when (save-excursion
165 (re-search-backward rng-in-start-tag-name-regex 157 (re-search-backward rng-in-start-tag-name-regex
166 lt-pos 158 lt-pos
167 t)) 159 t))
168 (and rng-collecting-text (rng-flush-text)) 160 (and rng-collecting-text (rng-flush-text))
169 (let ((completion 161 (let ((target-names (rng-match-possible-start-tag-names)))
170 (let ((rng-complete-target-names 162 `(,(1+ lt-pos)
171 (rng-match-possible-start-tag-names)) 163 ,(save-excursion (skip-chars-forward "[[:alnum:]_.-:]") (point))
172 (rng-complete-name-attribute-flag nil)) 164 ,(apply-partially #'rng-complete-qname-function
173 (rng-complete-before-point (1+ lt-pos) 165 target-names nil extra-strings)
174 'rng-complete-qname-function 166 :exit-function
175 "Tag: " 167 ,(lambda (completion status)
176 nil 168 (cond
177 'rng-tag-history))) 169 ((not (eq status 'finished)) nil)
178 name) 170 ((rng-qname-p completion)
179 (when completion 171 (let ((name (rng-expand-qname completion
180 (cond ((rng-qname-p completion) 172 t
181 (setq name (rng-expand-qname completion 173 #'rng-start-tag-expand-recover)))
182 t 174 (when (and name
183 'rng-start-tag-expand-recover)) 175 (rng-match-start-tag-open name)
184 (when (and name 176 (or (not (rng-match-start-tag-close))
185 (rng-match-start-tag-open name) 177 ;; need a namespace decl on the root element
186 (or (not (rng-match-start-tag-close)) 178 (and (car name)
187 ;; need a namespace decl on the root element 179 (not rng-open-elements))))
188 (and (car name) 180 ;; attributes are required
189 (not rng-open-elements)))) 181 (insert " "))))
190 ;; attributes are required 182 ((member completion extra-strings)
191 (insert " "))) 183 (insert ">")))))))))
192 ((member completion rng-complete-extra-strings)
193 (insert ">")))))
194 t)))
195 184
196(defconst rng-in-end-tag-name-regex 185(defconst rng-in-end-tag-name-regex
197 (replace-regexp-in-string 186 (replace-regexp-in-string
@@ -216,29 +205,18 @@ Return non-nil if in a context it understands."
216 (concat (caar rng-open-elements) 205 (concat (caar rng-open-elements)
217 ":" 206 ":"
218 (cdar rng-open-elements)) 207 (cdar rng-open-elements))
219 (cdar rng-open-elements))) 208 (cdar rng-open-elements))))
220 (end-tag-name 209 `(,(+ (match-beginning 0) 2)
221 (buffer-substring-no-properties (+ (match-beginning 0) 2) 210 ,(save-excursion (skip-chars-forward "[[:alnum:]_.-:]") (point))
222 (point)))) 211 ,(list start-tag-name) ;Sole completion candidate.
223 (cond ((or (> (length end-tag-name) 212 :exit-function
224 (length start-tag-name)) 213 ,(lambda (_completion status)
225 (not (string= (substring start-tag-name 214 (when (eq status 'finished)
226 0 215 (unless (eq (char-after) ?>) (insert ">"))
227 (length end-tag-name)) 216 (when (not (or rng-collecting-text
228 end-tag-name))) 217 (rng-match-end-tag)))
229 (message "Expected end-tag %s" 218 (message "Element \"%s\" is incomplete"
230 (rng-quote-string 219 start-tag-name))))))))))
231 (concat "</" start-tag-name ">")))
232 (ding))
233 (t
234 (delete-region (- (point) (length end-tag-name))
235 (point))
236 (insert start-tag-name ">")
237 (when (not (or rng-collecting-text
238 (rng-match-end-tag)))
239 (message "Element %s is incomplete"
240 (rng-quote-string start-tag-name))))))))
241 t))
242 220
243(defconst rng-in-attribute-regex 221(defconst rng-in-attribute-regex
244 (replace-regexp-in-string 222 (replace-regexp-in-string
@@ -260,22 +238,24 @@ Return non-nil if in a context it understands."
260 rng-undeclared-prefixes) 238 rng-undeclared-prefixes)
261 (and (rng-adjust-state-for-attribute lt-pos 239 (and (rng-adjust-state-for-attribute lt-pos
262 attribute-start) 240 attribute-start)
263 (let ((rng-complete-target-names 241 (let ((target-names
264 (rng-match-possible-attribute-names)) 242 (rng-match-possible-attribute-names))
265 (rng-complete-extra-strings 243 (extra-strings
266 (mapcar (lambda (prefix) 244 (mapcar (lambda (prefix)
267 (if prefix 245 (if prefix
268 (concat "xmlns:" prefix) 246 (concat "xmlns:" prefix)
269 "xmlns")) 247 "xmlns"))
270 rng-undeclared-prefixes)) 248 rng-undeclared-prefixes)))
271 (rng-complete-name-attribute-flag t)) 249 `(,attribute-start
272 (rng-complete-before-point attribute-start 250 ,(save-excursion (skip-chars-forward "[[:alnum:]_.-:]") (point))
273 'rng-complete-qname-function 251 ,(apply-partially #'rng-complete-qname-function
274 "Attribute: " 252 target-names t extra-strings)
275 nil 253 :exit-function
276 'rng-attribute-name-history)) 254 ,(lambda (_completion status)
277 (insert "=\""))) 255 (when (and (eq status 'finished)
278 t)) 256 (not (looking-at "=")))
257 (insert "=\"\"")
258 (forward-char -1)))))))))
279 259
280(defconst rng-in-attribute-value-regex 260(defconst rng-in-attribute-value-regex
281 (replace-regexp-in-string 261 (replace-regexp-in-string
@@ -292,43 +272,40 @@ Return non-nil if in a context it understands."
292(defun rng-complete-attribute-value (lt-pos) 272(defun rng-complete-attribute-value (lt-pos)
293 (when (save-excursion 273 (when (save-excursion
294 (re-search-backward rng-in-attribute-value-regex lt-pos t)) 274 (re-search-backward rng-in-attribute-value-regex lt-pos t))
295 (let ((name-start (match-beginning 1)) 275 (let* ((name-start (match-beginning 1))
296 (name-end (match-end 1)) 276 (name-end (match-end 1))
297 (colon (match-beginning 2)) 277 (colon (match-beginning 2))
298 (value-start (1+ (match-beginning 3)))) 278 (value-start (1+ (match-beginning 3)))
279 (exit-function
280 (lambda (_completion status)
281 (when (eq status 'finished)
282 (let ((delim (char-before value-start)))
283 (unless (eq (char-after) delim) (insert delim)))))))
299 (and (rng-adjust-state-for-attribute lt-pos 284 (and (rng-adjust-state-for-attribute lt-pos
300 name-start) 285 name-start)
301 (if (string= (buffer-substring-no-properties name-start 286 (if (string= (buffer-substring-no-properties name-start
302 (or colon name-end)) 287 (or colon name-end))
303 "xmlns") 288 "xmlns")
304 (rng-complete-before-point 289 `(,value-start ,(point)
305 value-start 290 ,(rng-strings-to-completion-table
306 (rng-strings-to-completion-alist 291 (rng-possible-namespace-uris
307 (rng-possible-namespace-uris 292 (and colon
308 (and colon 293 (buffer-substring-no-properties (1+ colon) name-end))))
309 (buffer-substring-no-properties (1+ colon) name-end)))) 294 :exit-function ,exit-function)
310 "Namespace URI: "
311 nil
312 'rng-namespace-uri-history)
313 (rng-adjust-state-for-attribute-value name-start 295 (rng-adjust-state-for-attribute-value name-start
314 colon 296 colon
315 name-end) 297 name-end)
316 (rng-complete-before-point 298 `(,value-start ,(point)
317 value-start 299 ,(rng-strings-to-completion-table
318 (rng-strings-to-completion-alist 300 (rng-match-possible-value-strings))
319 (rng-match-possible-value-strings)) 301 :exit-function ,exit-function))))))
320 "Value: "
321 nil
322 'rng-attribute-value-history))
323 (insert (char-before value-start))))
324 t))
325 302
326(defun rng-possible-namespace-uris (prefix) 303(defun rng-possible-namespace-uris (prefix)
327 (let ((ns (if prefix (nxml-ns-get-prefix prefix) 304 (let ((ns (if prefix (nxml-ns-get-prefix prefix)
328 (nxml-ns-get-default)))) 305 (nxml-ns-get-default))))
329 (if (and ns (memq prefix (nxml-ns-changed-prefixes))) 306 (if (and ns (memq prefix (nxml-ns-changed-prefixes)))
330 (list (nxml-namespace-name ns)) 307 (list (nxml-namespace-name ns))
331 (mapcar 'nxml-namespace-name 308 (mapcar #'nxml-namespace-name
332 (delq nxml-xml-namespace-uri 309 (delq nxml-xml-namespace-uri
333 (rng-match-possible-namespace-uris)))))) 310 (rng-match-possible-namespace-uris))))))
334 311
@@ -349,7 +326,7 @@ Return non-nil if in a context it understands."
349 (recover-fun (funcall recover-fun prefix (cdr qname))))) 326 (recover-fun (funcall recover-fun prefix (cdr qname)))))
350 (cons (and defaultp (nxml-ns-get-default)) (cdr qname))))) 327 (cons (and defaultp (nxml-ns-get-default)) (cdr qname)))))
351 328
352(defun rng-start-tag-expand-recover (prefix local-name) 329(defun rng-start-tag-expand-recover (_prefix local-name)
353 (let ((ns (rng-match-infer-start-tag-namespace local-name))) 330 (let ((ns (rng-match-infer-start-tag-namespace local-name)))
354 (and ns 331 (and ns
355 (cons ns local-name)))) 332 (cons ns local-name))))
@@ -386,7 +363,7 @@ set `xmltok-dtd'. Returns the position of the end of the token."
386 (save-restriction 363 (save-restriction
387 (widen) 364 (widen)
388 (nxml-with-invisible-motion 365 (nxml-with-invisible-motion
389 (if (= pos 1) 366 (if (= pos (point-min))
390 (rng-set-initial-state) 367 (rng-set-initial-state)
391 (let ((state (get-text-property (1- pos) 'rng-state))) 368 (let ((state (get-text-property (1- pos) 'rng-state)))
392 (cond (state 369 (cond (state
@@ -501,24 +478,21 @@ set `xmltok-dtd'. Returns the position of the end of the token."
501 (and (or (not prefix) ns) 478 (and (or (not prefix) ns)
502 (rng-match-attribute-name (cons ns local-name))))) 479 (rng-match-attribute-name (cons ns local-name)))))
503 480
504(defun rng-complete-qname-function (string predicate flag) 481(defun rng-complete-qname-function (candidates attributes-flag extra-strings
505 (let ((alist (mapcar (lambda (name) (cons name nil)) 482 string predicate flag)
506 (rng-generate-qname-list string)))) 483 (complete-with-action flag
507 (cond ((not flag) 484 (rng-generate-qname-list
508 (try-completion string alist predicate)) 485 string candidates attributes-flag extra-strings)
509 ((eq flag t) 486 string predicate))
510 (all-completions string alist predicate)) 487
511 ((eq flag 'lambda) 488(defun rng-generate-qname-list (&optional string candidates attribute-flag extra-strings)
512 (and (assoc string alist) t)))))
513
514(defun rng-generate-qname-list (&optional string)
515 (let ((forced-prefix (and string 489 (let ((forced-prefix (and string
516 (string-match ":" string) 490 (string-match ":" string)
517 (> (match-beginning 0) 0) 491 (> (match-beginning 0) 0)
518 (substring string 492 (substring string
519 0 493 0
520 (match-beginning 0)))) 494 (match-beginning 0))))
521 (namespaces (mapcar 'car rng-complete-target-names)) 495 (namespaces (mapcar #'car candidates))
522 ns-prefixes-alist ns-prefixes iter ns prefer) 496 ns-prefixes-alist ns-prefixes iter ns prefer)
523 (while namespaces 497 (while namespaces
524 (setq ns (car namespaces)) 498 (setq ns (car namespaces))
@@ -526,7 +500,7 @@ set `xmltok-dtd'. Returns the position of the end of the token."
526 (setq ns-prefixes-alist 500 (setq ns-prefixes-alist
527 (cons (cons ns (nxml-ns-prefixes-for 501 (cons (cons ns (nxml-ns-prefixes-for
528 ns 502 ns
529 rng-complete-name-attribute-flag)) 503 attribute-flag))
530 ns-prefixes-alist))) 504 ns-prefixes-alist)))
531 (setq namespaces (delq ns (cdr namespaces)))) 505 (setq namespaces (delq ns (cdr namespaces))))
532 (setq iter ns-prefixes-alist) 506 (setq iter ns-prefixes-alist)
@@ -546,12 +520,12 @@ set `xmltok-dtd'. Returns the position of the end of the token."
546 (setcdr ns-prefixes (list prefer))) 520 (setcdr ns-prefixes (list prefer)))
547 ;; Unless it's an attribute with a non-nil namespace, 521 ;; Unless it's an attribute with a non-nil namespace,
548 ;; allow no prefix for this namespace. 522 ;; allow no prefix for this namespace.
549 (unless rng-complete-name-attribute-flag 523 (unless attribute-flag
550 (setcdr ns-prefixes (cons nil (cdr ns-prefixes)))))) 524 (setcdr ns-prefixes (cons nil (cdr ns-prefixes))))))
551 (setq iter (cdr iter))) 525 (setq iter (cdr iter)))
552 (rng-uniquify-equal 526 (rng-uniquify-equal
553 (sort (apply 'append 527 (sort (apply #'append
554 (cons rng-complete-extra-strings 528 (cons extra-strings
555 (mapcar (lambda (name) 529 (mapcar (lambda (name)
556 (if (car name) 530 (if (car name)
557 (mapcar (lambda (prefix) 531 (mapcar (lambda (prefix)
@@ -563,7 +537,7 @@ set `xmltok-dtd'. Returns the position of the end of the token."
563 (cdr (assoc (car name) 537 (cdr (assoc (car name)
564 ns-prefixes-alist))) 538 ns-prefixes-alist)))
565 (list (cdr name)))) 539 (list (cdr name))))
566 rng-complete-target-names))) 540 candidates)))
567 'string<)))) 541 'string<))))
568 542
569(defun rng-get-preferred-unused-prefix (ns) 543(defun rng-get-preferred-unused-prefix (ns)
@@ -582,10 +556,8 @@ set `xmltok-dtd'. Returns the position of the end of the token."
582 nil)))) 556 nil))))
583 prefix)) 557 prefix))
584 558
585(defun rng-strings-to-completion-alist (strings) 559(defun rng-strings-to-completion-table (strings)
586 (mapcar (lambda (s) (cons s s)) 560 (mapcar #'rng-escape-string strings))
587 (rng-uniquify-equal (sort (mapcar 'rng-escape-string strings)
588 'string<))))
589 561
590(provide 'rng-nxml) 562(provide 'rng-nxml)
591 563
diff --git a/lisp/nxml/rng-parse.el b/lisp/nxml/rng-parse.el
index cde749db672..3ae4b5cc9c4 100644
--- a/lisp/nxml/rng-parse.el
+++ b/lisp/nxml/rng-parse.el
@@ -1,4 +1,4 @@
1;;; rng-parse.el --- parse an XML file and validate it against a schema 1;;; rng-parse.el --- parse an XML file and validate it against a schema -*- lexical-binding:t -*-
2 2
3;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. 3;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc.
4 4
diff --git a/lisp/nxml/rng-pttrn.el b/lisp/nxml/rng-pttrn.el
index f358d3c87d4..e847f5e02a8 100644
--- a/lisp/nxml/rng-pttrn.el
+++ b/lisp/nxml/rng-pttrn.el
@@ -1,4 +1,4 @@
1;;; rng-pttrn.el --- RELAX NG patterns 1;;; rng-pttrn.el --- RELAX NG patterns -*- lexical-binding:t -*-
2 2
3;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. 3;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc.
4 4
diff --git a/lisp/nxml/rng-uri.el b/lisp/nxml/rng-uri.el
index 75cf23f888d..8fc0a01e293 100644
--- a/lisp/nxml/rng-uri.el
+++ b/lisp/nxml/rng-uri.el
@@ -1,4 +1,4 @@
1;;; rng-uri.el --- URI parsing and manipulation 1;;; rng-uri.el --- URI parsing and manipulation -*- lexical-binding:t -*-
2 2
3;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. 3;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc.
4 4
diff --git a/lisp/nxml/rng-util.el b/lisp/nxml/rng-util.el
index 4c14e2b6597..c5d4b6567ed 100644
--- a/lisp/nxml/rng-util.el
+++ b/lisp/nxml/rng-util.el
@@ -82,69 +82,6 @@ LIST is not modified."
82 (cons item nil)))))))) 82 (cons item nil))))))))
83 list))) 83 list)))
84 84
85(defun rng-complete-before-point (start table prompt &optional predicate hist)
86 "Complete text between START and point.
87Replaces the text between START and point with a string chosen using a
88completion table and, when needed, input read from the user with the
89minibuffer.
90Returns the new string if either a complete and unique completion was
91determined automatically or input was read from the user. Otherwise,
92returns nil.
93TABLE is an alist, a symbol bound to a function or an obarray as with
94the function `completing-read'.
95PROMPT is the string to prompt with if user input is needed.
96PREDICATE is nil or a function as with `completing-read'.
97HIST, if non-nil, specifies a history list as with `completing-read'."
98 (let* ((orig (buffer-substring-no-properties start (point)))
99 (completion (try-completion orig table predicate)))
100 (cond ((not completion)
101 (if (string= orig "")
102 (message "No completions available")
103 (message "No completion for %s" (rng-quote-string orig)))
104 (ding)
105 nil)
106 ((eq completion t) orig)
107 ((not (string= completion orig))
108 (delete-region start (point))
109 (insert completion)
110 (cond ((not (rng-completion-exact-p completion table predicate))
111 (message "Incomplete")
112 nil)
113 ((eq (try-completion completion table predicate) t)
114 completion)
115 (t
116 (message "Complete but not unique")
117 nil)))
118 (t
119 (setq completion
120 (let ((saved-minibuffer-setup-hook
121 (default-value 'minibuffer-setup-hook)))
122 (add-hook 'minibuffer-setup-hook
123 'minibuffer-completion-help
124 t)
125 (unwind-protect
126 (completing-read prompt
127 table
128 predicate
129 nil
130 orig
131 hist)
132 (setq-default minibuffer-setup-hook
133 saved-minibuffer-setup-hook))))
134 (delete-region start (point))
135 (insert completion)
136 completion))))
137
138(defun rng-completion-exact-p (string table predicate)
139 (cond ((symbolp table)
140 (funcall table string predicate 'lambda))
141 ((vectorp table)
142 (intern-soft string table))
143 (t (assoc string table))))
144
145(defun rng-quote-string (s)
146 (concat "\"" s "\""))
147
148(defun rng-escape-string (s) 85(defun rng-escape-string (s)
149 (replace-regexp-in-string "[&\"<>]" 86 (replace-regexp-in-string "[&\"<>]"
150 (lambda (match) 87 (lambda (match)
diff --git a/lisp/nxml/rng-valid.el b/lisp/nxml/rng-valid.el
index 1020cad2089..946bf791ff8 100644
--- a/lisp/nxml/rng-valid.el
+++ b/lisp/nxml/rng-valid.el
@@ -1,4 +1,4 @@
1;;; rng-valid.el --- real-time validation of XML using RELAX NG 1;;; rng-valid.el --- real-time validation of XML using RELAX NG -*- lexical-binding:t -*-
2 2
3;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. 3;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc.
4 4
@@ -430,13 +430,13 @@ The schema is set like `rng-auto-set-schema'."
430 (when (buffer-live-p buffer) ; bug#13999 430 (when (buffer-live-p buffer) ; bug#13999
431 (with-current-buffer buffer 431 (with-current-buffer buffer
432 (if rng-validate-mode 432 (if rng-validate-mode
433 (if (let ((rng-validate-display-point (point)) 433 (if (let ((rng-validate-display-point (point))
434 (rng-validate-display-modified-p (buffer-modified-p))) 434 (rng-validate-display-modified-p (buffer-modified-p)))
435 (rng-do-some-validation 'rng-validate-while-idle-continue-p)) 435 (rng-do-some-validation 'rng-validate-while-idle-continue-p))
436 (force-mode-line-update) 436 (force-mode-line-update)
437 (rng-validate-done)) 437 (rng-validate-done))
438 ;; must have done kill-all-local-variables 438 ;; Must have done kill-all-local-variables.
439 (rng-kill-timers))))) 439 (rng-kill-timers)))))
440 440
441(defun rng-validate-quick-while-idle (buffer) 441(defun rng-validate-quick-while-idle (buffer)
442 (when (buffer-live-p buffer) ; bug#13999 442 (when (buffer-live-p buffer) ; bug#13999
@@ -709,7 +709,7 @@ Return t if there is work to do, nil otherwise."
709 709
710;; If we don't do this, then the front delimiter can move 710;; If we don't do this, then the front delimiter can move
711;; past the end delimiter. 711;; past the end delimiter.
712(defun rng-error-modified (overlay after-p beg end &optional pre-change-len) 712(defun rng-error-modified (overlay after-p _beg _end &optional _pre-change-len)
713 (when (and after-p 713 (when (and after-p
714 (overlay-start overlay) ; check not deleted 714 (overlay-start overlay) ; check not deleted
715 (>= (overlay-start overlay) 715 (>= (overlay-start overlay)
@@ -1138,9 +1138,8 @@ as empty-element."
1138 (rng-match-start-tag-open required) 1138 (rng-match-start-tag-open required)
1139 (rng-match-after) 1139 (rng-match-after)
1140 (rng-match-start-tag-open name)) 1140 (rng-match-start-tag-open name))
1141 (rng-mark-invalid (concat "Missing element " 1141 (rng-mark-invalid (format "Missing element \"%s\""
1142 (rng-quote-string 1142 (rng-name-to-string required))
1143 (rng-name-to-string required)))
1144 xmltok-start 1143 xmltok-start
1145 (1+ xmltok-start))) 1144 (1+ xmltok-start)))
1146 ((and (rng-match-optionalize-elements) 1145 ((and (rng-match-optionalize-elements)
@@ -1177,16 +1176,14 @@ as empty-element."
1177 (cond ((not required-attributes) 1176 (cond ((not required-attributes)
1178 "Required attributes missing") 1177 "Required attributes missing")
1179 ((not (cdr required-attributes)) 1178 ((not (cdr required-attributes))
1180 (concat "Missing attribute " 1179 (format "Missing attribute \"%s\""
1181 (rng-quote-string 1180 (rng-name-to-string (car required-attributes) t)))
1182 (rng-name-to-string (car required-attributes) t))))
1183 (t 1181 (t
1184 (concat "Missing attributes " 1182 (format "Missing attributes \"%s\""
1185 (mapconcat (lambda (nm) 1183 (mapconcat (lambda (nm)
1186 (rng-quote-string 1184 (rng-name-to-string nm t))
1187 (rng-name-to-string nm t)))
1188 required-attributes 1185 required-attributes
1189 ", ")))))) 1186 "\", \""))))))
1190 1187
1191(defun rng-process-end-tag (&optional partial) 1188(defun rng-process-end-tag (&optional partial)
1192 (cond ((not rng-open-elements) 1189 (cond ((not rng-open-elements)
@@ -1229,8 +1226,7 @@ as empty-element."
1229(defun rng-missing-element-message () 1226(defun rng-missing-element-message ()
1230 (let ((element (rng-match-required-element-name))) 1227 (let ((element (rng-match-required-element-name)))
1231 (if element 1228 (if element
1232 (concat "Missing element " 1229 (format "Missing element \"%s\"" (rng-name-to-string element))
1233 (rng-quote-string (rng-name-to-string element)))
1234 "Required child elements missing"))) 1230 "Required child elements missing")))
1235 1231
1236(defun rng-recover-mismatched-end-tag () 1232(defun rng-recover-mismatched-end-tag ()
@@ -1258,17 +1254,16 @@ as empty-element."
1258 1254
1259(defun rng-mark-missing-end-tags (missing) 1255(defun rng-mark-missing-end-tags (missing)
1260 (rng-mark-not-well-formed 1256 (rng-mark-not-well-formed
1261 (format "Missing end-tag%s %s" 1257 (format "Missing end-tag%s \"%s\""
1262 (if (null (cdr missing)) "" "s") 1258 (if (null (cdr missing)) "" "s")
1263 (mapconcat (lambda (name) 1259 (mapconcat (lambda (name)
1264 (rng-quote-string 1260 (if (car name)
1265 (if (car name) 1261 (concat (car name)
1266 (concat (car name) 1262 ":"
1267 ":" 1263 (cdr name))
1268 (cdr name)) 1264 (cdr name)))
1269 (cdr name))))
1270 missing 1265 missing
1271 ", ")) 1266 "\", \""))
1272 xmltok-start 1267 xmltok-start
1273 (+ xmltok-start 2))) 1268 (+ xmltok-start 2)))
1274 1269
diff --git a/lisp/nxml/rng-xsd.el b/lisp/nxml/rng-xsd.el
index 378319851a0..c0989ae1073 100644
--- a/lisp/nxml/rng-xsd.el
+++ b/lisp/nxml/rng-xsd.el
@@ -1,4 +1,4 @@
1;;; rng-xsd.el --- W3C XML Schema datatypes library for RELAX NG 1;;; rng-xsd.el --- W3C XML Schema datatypes library for RELAX NG -*- lexical-binding:t -*-
2 2
3;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. 3;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc.
4 4
@@ -42,7 +42,7 @@
42;;;###autoload 42;;;###autoload
43(put 'http://www.w3.org/2001/XMLSchema-datatypes 43(put 'http://www.w3.org/2001/XMLSchema-datatypes
44 'rng-dt-compile 44 'rng-dt-compile
45 'rng-xsd-compile) 45 #'rng-xsd-compile)
46 46
47;;;###autoload 47;;;###autoload
48(defun rng-xsd-compile (name params) 48(defun rng-xsd-compile (name params)
@@ -50,9 +50,9 @@
50NAME is a symbol giving the local name of the datatype. PARAMS is a 50NAME is a symbol giving the local name of the datatype. PARAMS is a
51list of pairs (PARAM-NAME . PARAM-VALUE) where PARAM-NAME is a symbol 51list of pairs (PARAM-NAME . PARAM-VALUE) where PARAM-NAME is a symbol
52giving the name of the parameter and PARAM-VALUE is a string giving 52giving the name of the parameter and PARAM-VALUE is a string giving
53its value. If NAME or PARAMS are invalid, it calls rng-dt-error 53its value. If NAME or PARAMS are invalid, it calls `rng-dt-error'
54passing it arguments in the same style as format; the value from 54passing it arguments in the same style as format; the value from
55rng-dt-error will be returned. Otherwise, it returns a list. The 55`rng-dt-error' will be returned. Otherwise, it returns a list. The
56first member of the list is t if any string is a legal value for the 56first member of the list is t if any string is a legal value for the
57datatype and nil otherwise. The second argument is a symbol; this 57datatype and nil otherwise. The second argument is a symbol; this
58symbol will be called as a function passing it a string followed by 58symbol will be called as a function passing it a string followed by
diff --git a/lisp/nxml/xmltok.el b/lisp/nxml/xmltok.el
index 8fc66c99a45..f12905a86d0 100644
--- a/lisp/nxml/xmltok.el
+++ b/lisp/nxml/xmltok.el
@@ -34,10 +34,7 @@
34;; preceding part of the instance. This allows the instance to be 34;; preceding part of the instance. This allows the instance to be
35;; parsed incrementally. The main entry point is `xmltok-forward': 35;; parsed incrementally. The main entry point is `xmltok-forward':
36;; this can be called at any point in the instance provided it is 36;; this can be called at any point in the instance provided it is
37;; between tokens. The other entry point is `xmltok-forward-special' 37;; between tokens.
38;; which skips over tokens other comments, processing instructions or
39;; CDATA sections (i.e. the constructs in an instance that can contain
40;; less than signs that don't start a token).
41;; 38;;
42;; This is a non-validating XML 1.0 processor. It does not resolve 39;; This is a non-validating XML 1.0 processor. It does not resolve
43;; parameter entities (including the external DTD subset) and it does 40;; parameter entities (including the external DTD subset) and it does
@@ -262,11 +259,10 @@ and VALUE-END, otherwise a STRING giving the value."
262 (vector message start end)) 259 (vector message start end))
263 260
264(defun xmltok-add-error (message &optional start end) 261(defun xmltok-add-error (message &optional start end)
265 (setq xmltok-errors 262 (push (xmltok-make-error message
266 (cons (xmltok-make-error message 263 (or start xmltok-start)
267 (or start xmltok-start) 264 (or end (point)))
268 (or end (point))) 265 xmltok-errors))
269 xmltok-errors)))
270 266
271(defun xmltok-forward () 267(defun xmltok-forward ()
272 (setq xmltok-start (point)) 268 (setq xmltok-start (point))
@@ -308,18 +304,6 @@ and VALUE-END, otherwise a STRING giving the value."
308 (goto-char (point-max)) 304 (goto-char (point-max))
309 (setq xmltok-type 'data))))) 305 (setq xmltok-type 'data)))))
310 306
311(defun xmltok-forward-special (bound)
312 "Scan forward past the first special token starting at or after point.
313Return nil if there is no special token that starts before BOUND.
314CDATA sections, processing instructions and comments (and indeed
315anything starting with < following by ? or !) count as special.
316Return the type of the token."
317 (when (re-search-forward "<[?!]" (1+ bound) t)
318 (setq xmltok-start (match-beginning 0))
319 (goto-char (1+ xmltok-start))
320 (let ((case-fold-search nil))
321 (xmltok-scan-after-lt))))
322
323(eval-when-compile 307(eval-when-compile
324 308
325 ;; A symbolic regexp is represented by a list whose CAR is the string 309 ;; A symbolic regexp is represented by a list whose CAR is the string
@@ -739,19 +723,10 @@ Return the type of the token."
739 (setq xmltok-type 'processing-instruction)) 723 (setq xmltok-type 'processing-instruction))
740 724
741(defun xmltok-scan-after-comment-open () 725(defun xmltok-scan-after-comment-open ()
742 (let ((found-- (search-forward "--" nil 'move))) 726 (while (and (re-search-forward "--\\(>\\)?" nil 'move)
743 (setq xmltok-type 727 (not (match-end 1)))
744 (cond ((or (eq (char-after) ?>) (not found--)) 728 (xmltok-add-error "`--' not followed by `>'" (match-beginning 0)))
745 (goto-char (1+ (point))) 729 (setq xmltok-type 'comment))
746 'comment)
747 (t
748 ;; just include the <!-- in the token
749 (goto-char (+ xmltok-start 4))
750 ;; Need do this after the goto-char because
751 ;; marked error should just apply to <!--
752 (xmltok-add-error "First following `--' not followed by `>'")
753 (goto-char (point-max))
754 'comment)))))
755 730
756(defun xmltok-scan-attributes () 731(defun xmltok-scan-attributes ()
757 (let ((recovering nil) 732 (let ((recovering nil)
diff --git a/lisp/nxml/xsd-regexp.el b/lisp/nxml/xsd-regexp.el
index e91e6b77a7d..a3f476d00be 100644
--- a/lisp/nxml/xsd-regexp.el
+++ b/lisp/nxml/xsd-regexp.el
@@ -1,4 +1,4 @@
1;;; xsd-regexp.el --- translate W3C XML Schema regexps to Emacs regexps 1;;; xsd-regexp.el --- translate W3C XML Schema regexps to Emacs regexps -*- lexical-binding:t -*-
2 2
3;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc. 3;; Copyright (C) 2003, 2007-2016 Free Software Foundation, Inc.
4 4
@@ -147,7 +147,7 @@ ranges are merged wherever possible."
147(defun xsdre-range-list-difference (orig subtract) 147(defun xsdre-range-list-difference (orig subtract)
148 "Return a range-list for the difference of two range-lists." 148 "Return a range-list for the difference of two range-lists."
149 (when orig 149 (when orig
150 (let (new head next first last) 150 (let (new head first last)
151 (while orig 151 (while orig
152 (setq head (car orig)) 152 (setq head (car orig))
153 (setq first (xsdre-range-first head)) 153 (setq first (xsdre-range-first head))
@@ -745,7 +745,7 @@ Code is inserted into the current buffer."
745 (save-excursion 745 (save-excursion
746 (goto-char start) 746 (goto-char start)
747 (down-list 2) 747 (down-list 2)
748 (while (condition-case err 748 (while (condition-case nil
749 (progn 749 (progn
750 (forward-sexp) 750 (forward-sexp)
751 t) 751 t)
diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el
index 9e175a20e22..8f0b4f13b9e 100644
--- a/lisp/progmodes/elisp-mode.el
+++ b/lisp/progmodes/elisp-mode.el
@@ -245,11 +245,8 @@ Blank lines separate paragraphs. Semicolons start comments.
245;; Font-locking support. 245;; Font-locking support.
246 246
247(defun elisp--font-lock-flush-elisp-buffers (&optional file) 247(defun elisp--font-lock-flush-elisp-buffers (&optional file)
248 ;; FIXME: Aren't we only ever called from after-load-functions? 248 ;; We're only ever called from after-load-functions, load-in-progress can
249 ;; Don't flush during load unless called from after-load-functions. 249 ;; still be t in case of nested loads.
250 ;; In that case, FILE is non-nil. It's somehow strange that
251 ;; load-in-progress is t when an after-load-function is called since
252 ;; that should run *after* the load...
253 (when (or (not load-in-progress) file) 250 (when (or (not load-in-progress) file)
254 ;; FIXME: If the loaded file did not define any macros, there shouldn't 251 ;; FIXME: If the loaded file did not define any macros, there shouldn't
255 ;; be any need to font-lock-flush all the Elisp buffers. 252 ;; be any need to font-lock-flush all the Elisp buffers.
diff --git a/lisp/progmodes/etags.el b/lisp/progmodes/etags.el
index 2db7220de5c..271033b15f8 100644
--- a/lisp/progmodes/etags.el
+++ b/lisp/progmodes/etags.el
@@ -1794,7 +1794,6 @@ Two variables control the processing we do on each file: the value of
1794interesting (it returns non-nil if so) and `tags-loop-operate' is a form to 1794interesting (it returns non-nil if so) and `tags-loop-operate' is a form to
1795evaluate to operate on an interesting file. If the latter evaluates to 1795evaluate to operate on an interesting file. If the latter evaluates to
1796nil, we exit; otherwise we scan the next file." 1796nil, we exit; otherwise we scan the next file."
1797 (declare (obsolete "use `xref-find-definitions' interface instead." "25.1"))
1798 (interactive) 1797 (interactive)
1799 (let (new 1798 (let (new
1800 ;; Non-nil means we have finished one file 1799 ;; Non-nil means we have finished one file
diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el
index c22de2f77ac..1a0385e167e 100644
--- a/lisp/progmodes/gud.el
+++ b/lisp/progmodes/gud.el
@@ -1742,6 +1742,7 @@ and source-file directory for your debugger."
1742(defcustom gud-guiler-command-name "guile" 1742(defcustom gud-guiler-command-name "guile"
1743 "File name for executing the Guile debugger. 1743 "File name for executing the Guile debugger.
1744This should be an executable on your path, or an absolute file name." 1744This should be an executable on your path, or an absolute file name."
1745 :version "25.1"
1745 :type 'string 1746 :type 'string
1746 :group 'gud) 1747 :group 'gud)
1747 1748
diff --git a/lisp/progmodes/hideif.el b/lisp/progmodes/hideif.el
index 43cf42c048b..8a87eb9770a 100644
--- a/lisp/progmodes/hideif.el
+++ b/lisp/progmodes/hideif.el
@@ -138,7 +138,7 @@
138 138
139(defcustom hide-ifdef-exclude-define-regexp nil 139(defcustom hide-ifdef-exclude-define-regexp nil
140 "Ignore #define names if those names match this exclusion pattern." 140 "Ignore #define names if those names match this exclusion pattern."
141 :type 'string 141 :type '(choice (const nil) string)
142 :version "25.1") 142 :version "25.1")
143 143
144(defcustom hide-ifdef-expand-reinclusion-protection t 144(defcustom hide-ifdef-expand-reinclusion-protection t
@@ -1581,14 +1581,17 @@ Refer to `hide-ifdef-expand-reinclusion-protection' for more details."
1581 result)) 1581 result))
1582 1582
1583(defun hif-evaluate-macro (rstart rend) 1583(defun hif-evaluate-macro (rstart rend)
1584 "Evaluate the macro expansion result for a region. 1584 "Evaluate the macro expansion result for the active region.
1585If no region active, find the current #ifdefs and evaluate the result. 1585If no region active, find the current #ifdefs and evaluate the result.
1586Currently it supports only math calculations, strings or argumented macros can 1586Currently it supports only math calculations, strings or argumented macros can
1587not be expanded." 1587not be expanded."
1588 (interactive "r") 1588 (interactive
1589 (if (use-region-p)
1590 (list (region-beginning) (region-end))
1591 '(nil nil)))
1589 (let ((case-fold-search nil)) 1592 (let ((case-fold-search nil))
1590 (save-excursion 1593 (save-excursion
1591 (unless mark-active 1594 (unless (use-region-p)
1592 (setq rstart nil rend nil) 1595 (setq rstart nil rend nil)
1593 (beginning-of-line) 1596 (beginning-of-line)
1594 (when (and (re-search-forward hif-macro-expr-prefix-regexp nil t) 1597 (when (and (re-search-forward hif-macro-expr-prefix-regexp nil t)
@@ -1844,9 +1847,13 @@ This allows #ifdef VAR to be hidden."
1844 1847
1845(defun hide-ifdef-undef (start end) 1848(defun hide-ifdef-undef (start end)
1846 "Undefine a VAR so that #ifdef VAR would not be included." 1849 "Undefine a VAR so that #ifdef VAR would not be included."
1847 (interactive "r") 1850 (interactive
1851 (if (use-region-p)
1852 (list (region-beginning) (region-end))
1853 '(nil nil)))
1848 (let* ((symstr 1854 (let* ((symstr
1849 (or (and mark-active 1855 (or (and (number-or-marker-p start)
1856 (number-or-marker-p end)
1850 (buffer-substring-no-properties start end)) 1857 (buffer-substring-no-properties start end))
1851 (read-string "Undefine what? " (current-word)))) 1858 (read-string "Undefine what? " (current-word))))
1852 (sym (and symstr 1859 (sym (and symstr
@@ -1915,7 +1922,7 @@ Return as (TOP . BOTTOM) the extent of ifdef block."
1915With optional prefix argument ARG, also hide the #ifdefs themselves." 1922With optional prefix argument ARG, also hide the #ifdefs themselves."
1916 (interactive "P\nr") 1923 (interactive "P\nr")
1917 (let ((hide-ifdef-lines arg)) 1924 (let ((hide-ifdef-lines arg))
1918 (if mark-active 1925 (if (use-region-p)
1919 (let ((hif-recurse-level (1+ hif-recurse-level))) 1926 (let ((hif-recurse-level (1+ hif-recurse-level)))
1920 (hif-recurse-on start end t) 1927 (hif-recurse-on start end t)
1921 (setq mark-active nil)) 1928 (setq mark-active nil))
@@ -1931,8 +1938,12 @@ With optional prefix argument ARG, also hide the #ifdefs themselves."
1931 1938
1932(defun show-ifdef-block (&optional start end) 1939(defun show-ifdef-block (&optional start end)
1933 "Show the ifdef block (true or false part) enclosing or before the cursor." 1940 "Show the ifdef block (true or false part) enclosing or before the cursor."
1934 (interactive "r") 1941 (interactive
1935 (if mark-active 1942 (if (use-region-p)
1943 (list (region-beginning) (region-end))
1944 '(nil nil)))
1945 (if (and (number-or-marker-p start)
1946 (number-or-marker-p end))
1936 (progn 1947 (progn
1937 (dolist (o (overlays-in start end)) 1948 (dolist (o (overlays-in start end))
1938 (if (overlay-get o 'hide-ifdef) 1949 (if (overlay-get o 'hide-ifdef)
diff --git a/lisp/progmodes/prog-mode.el b/lisp/progmodes/prog-mode.el
index 2f12df47723..718b33932ed 100644
--- a/lisp/progmodes/prog-mode.el
+++ b/lisp/progmodes/prog-mode.el
@@ -202,6 +202,7 @@ is immediately after the symbol. The prettification will be
202reapplied as soon as point moves away from the symbol. If 202reapplied as soon as point moves away from the symbol. If
203set to nil, the prettification persists even when point is 203set to nil, the prettification persists even when point is
204on the symbol." 204on the symbol."
205 :version "25.1"
205 :type '(choice (const :tag "Never unprettify" nil) 206 :type '(choice (const :tag "Never unprettify" nil)
206 (const :tag "Unprettify when point is inside" t) 207 (const :tag "Unprettify when point is inside" t)
207 (const :tag "Unprettify when point is inside or at right edge" right-edge)) 208 (const :tag "Unprettify when point is inside or at right edge" right-edge))
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index fe28ed776b2..85f390746d9 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -156,10 +156,11 @@ end it with `/'. DIR must be one of `project-roots' or
156 156
157(defgroup project-vc nil 157(defgroup project-vc nil
158 "Project implementation using the VC package." 158 "Project implementation using the VC package."
159 :version "25.1"
159 :group 'tools) 160 :group 'tools)
160 161
161(defcustom project-vc-ignores nil 162(defcustom project-vc-ignores nil
162 "List ot patterns to include in `project-ignores'." 163 "List of patterns to include in `project-ignores'."
163 :type '(repeat string) 164 :type '(repeat string)
164 :safe 'listp) 165 :safe 'listp)
165 166
@@ -263,7 +264,6 @@ DIRS must contain directory names."
263 (symbol-value var))) 264 (symbol-value var)))
264 265
265(declare-function grep-read-files "grep") 266(declare-function grep-read-files "grep")
266(declare-function xref-collect-matches "xref")
267(declare-function xref--show-xrefs "xref") 267(declare-function xref--show-xrefs "xref")
268(declare-function xref-backend-identifier-at-point "xref") 268(declare-function xref-backend-identifier-at-point "xref")
269(declare-function xref--find-ignores-arguments "xref") 269(declare-function xref--find-ignores-arguments "xref")
@@ -294,8 +294,8 @@ pattern to search for."
294 (project--find-regexp-in dirs regexp pr))) 294 (project--find-regexp-in dirs regexp pr)))
295 295
296(defun project--read-regexp () 296(defun project--read-regexp ()
297 (read-regexp "Find regexp" 297 (let ((id (xref-backend-identifier-at-point (xref-find-backend))))
298 (xref-backend-identifier-at-point (xref-find-backend)))) 298 (read-regexp "Find regexp" (and id (regexp-quote id)))))
299 299
300(defun project--find-regexp-in (dirs regexp project) 300(defun project--find-regexp-in (dirs regexp project)
301 (require 'grep) 301 (require 'grep)
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 4984c9908bf..a8c65fa23a9 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -715,6 +715,7 @@ It makes underscores and dots word constituent chars.")
715 715
716(defcustom python-indent-guess-indent-offset-verbose t 716(defcustom python-indent-guess-indent-offset-verbose t
717 "Non-nil means to emit a warning when indentation guessing fails." 717 "Non-nil means to emit a warning when indentation guessing fails."
718 :version "25.1"
718 :type 'boolean 719 :type 'boolean
719 :group 'python 720 :group 'python
720 :safe' booleanp) 721 :safe' booleanp)
@@ -1999,6 +2000,7 @@ hosts PATH before starting processes. Values defined in
1999here. Normally you wont use this variable directly unless you 2000here. Normally you wont use this variable directly unless you
2000plan to ensure a particular set of paths to all Python shell 2001plan to ensure a particular set of paths to all Python shell
2001executed through tramp connections." 2002executed through tramp connections."
2003 :version "25.1"
2002 :type '(repeat string) 2004 :type '(repeat string)
2003 :group 'python) 2005 :group 'python)
2004 2006
@@ -2042,8 +2044,8 @@ virtualenv."
2042(defun python-shell-calculate-pythonpath () 2044(defun python-shell-calculate-pythonpath ()
2043 "Calculate the PYTHONPATH using `python-shell-extra-pythonpaths'." 2045 "Calculate the PYTHONPATH using `python-shell-extra-pythonpaths'."
2044 (let ((pythonpath 2046 (let ((pythonpath
2045 (tramp-compat-split-string 2047 (split-string
2046 (or (getenv "PYTHONPATH") "") path-separator))) 2048 (or (getenv "PYTHONPATH") "") path-separator 'omit)))
2047 (python-shell--add-to-path-with-priority 2049 (python-shell--add-to-path-with-priority
2048 pythonpath python-shell-extra-pythonpaths) 2050 pythonpath python-shell-extra-pythonpaths)
2049 (mapconcat 'identity pythonpath path-separator))) 2051 (mapconcat 'identity pythonpath path-separator)))
@@ -2114,7 +2116,7 @@ appends `python-shell-remote-exec-path' instead of `exec-path'."
2114 (md5 tramp-end-of-output))) 2116 (md5 tramp-end-of-output)))
2115 unset vars item) 2117 unset vars item)
2116 (while env 2118 (while env
2117 (setq item (tramp-compat-split-string (car env) "=")) 2119 (setq item (split-string (car env) "=" 'omit))
2118 (setcdr item (mapconcat 'identity (cdr item) "=")) 2120 (setcdr item (mapconcat 'identity (cdr item) "="))
2119 (if (and (stringp (cdr item)) (not (string-equal (cdr item) ""))) 2121 (if (and (stringp (cdr item)) (not (string-equal (cdr item) "")))
2120 (push (format "%s %s" (car item) (cdr item)) vars) 2122 (push (format "%s %s" (car item) (cdr item)) vars)
@@ -2621,6 +2623,7 @@ current process to not hang waiting for output by safeguarding
2621interactive actions can be performed. This is useful to safely 2623interactive actions can be performed. This is useful to safely
2622attach setup code for long-running processes that eventually 2624attach setup code for long-running processes that eventually
2623provide a shell." 2625provide a shell."
2626 :version "25.1"
2624 :type 'hook 2627 :type 'hook
2625 :group 'python) 2628 :group 'python)
2626 2629
@@ -3258,18 +3261,22 @@ the full statement in the case of imports."
3258 (list "pypy") 3261 (list "pypy")
3259 "List of disabled interpreters. 3262 "List of disabled interpreters.
3260When a match is found, native completion is disabled." 3263When a match is found, native completion is disabled."
3264 :version "25.1"
3261 :type '(repeat string)) 3265 :type '(repeat string))
3262 3266
3263(defcustom python-shell-completion-native-enable t 3267(defcustom python-shell-completion-native-enable t
3264 "Enable readline based native completion." 3268 "Enable readline based native completion."
3269 :version "25.1"
3265 :type 'boolean) 3270 :type 'boolean)
3266 3271
3267(defcustom python-shell-completion-native-output-timeout 5.0 3272(defcustom python-shell-completion-native-output-timeout 5.0
3268 "Time in seconds to wait for completion output before giving up." 3273 "Time in seconds to wait for completion output before giving up."
3274 :version "25.1"
3269 :type 'float) 3275 :type 'float)
3270 3276
3271(defcustom python-shell-completion-native-try-output-timeout 1.0 3277(defcustom python-shell-completion-native-try-output-timeout 1.0
3272 "Time in seconds to wait for *trying* native completion output." 3278 "Time in seconds to wait for *trying* native completion output."
3279 :version "25.1"
3273 :type 'float) 3280 :type 'float)
3274 3281
3275(defvar python-shell-completion-native-redirect-buffer 3282(defvar python-shell-completion-native-redirect-buffer
diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el
index 8f08b7c9e60..53f8a6bb4c0 100644
--- a/lisp/progmodes/ruby-mode.el
+++ b/lisp/progmodes/ruby-mode.el
@@ -1830,7 +1830,7 @@ It will be properly highlighted even when the call omits parens.")
1830 "\\)\\s *") 1830 "\\)\\s *")
1831 "Regexp to match text that can be followed by a regular expression.")) 1831 "Regexp to match text that can be followed by a regular expression."))
1832 1832
1833(defun ruby-syntax-propertize-function (start end) 1833(defun ruby-syntax-propertize (start end)
1834 "Syntactic keywords for Ruby mode. See `syntax-propertize-function'." 1834 "Syntactic keywords for Ruby mode. See `syntax-propertize-function'."
1835 (let (case-fold-search) 1835 (let (case-fold-search)
1836 (goto-char start) 1836 (goto-char start)
@@ -1856,6 +1856,8 @@ It will be properly highlighted even when the call omits parens.")
1856 (zerop (skip-syntax-backward "w_"))) 1856 (zerop (skip-syntax-backward "w_")))
1857 (memq (preceding-char) '(?@ ?$)))) 1857 (memq (preceding-char) '(?@ ?$))))
1858 (string-to-syntax "_")))) 1858 (string-to-syntax "_"))))
1859 ;; Backtick method redefinition.
1860 ("^[ \t]*def +\\(`\\)" (1 "_"))
1859 ;; Regular expressions. Start with matching unescaped slash. 1861 ;; Regular expressions. Start with matching unescaped slash.
1860 ("\\(?:\\=\\|[^\\]\\)\\(?:\\\\\\\\\\)*\\(/\\)" 1862 ("\\(?:\\=\\|[^\\]\\)\\(?:\\\\\\\\\\)*\\(/\\)"
1861 (1 (let ((state (save-excursion (syntax-ppss (match-beginning 1))))) 1863 (1 (let ((state (save-excursion (syntax-ppss (match-beginning 1)))))
@@ -1891,6 +1893,9 @@ It will be properly highlighted even when the call omits parens.")
1891 (1 (prog1 "|" (ruby-syntax-propertize-percent-literal end))))) 1893 (1 (prog1 "|" (ruby-syntax-propertize-percent-literal end)))))
1892 (point) end))) 1894 (point) end)))
1893 1895
1896(define-obsolete-function-alias
1897 'ruby-syntax-propertize-function 'ruby-syntax-propertize "25.1")
1898
1894(defun ruby-syntax-propertize-heredoc (limit) 1899(defun ruby-syntax-propertize-heredoc (limit)
1895 (let ((ppss (syntax-ppss)) 1900 (let ((ppss (syntax-ppss))
1896 (res '())) 1901 (res '()))
@@ -2252,7 +2257,7 @@ See `font-lock-syntax-table'.")
2252 (setq-local font-lock-keywords ruby-font-lock-keywords) 2257 (setq-local font-lock-keywords ruby-font-lock-keywords)
2253 (setq-local font-lock-syntax-table ruby-font-lock-syntax-table) 2258 (setq-local font-lock-syntax-table ruby-font-lock-syntax-table)
2254 2259
2255 (setq-local syntax-propertize-function #'ruby-syntax-propertize-function)) 2260 (setq-local syntax-propertize-function #'ruby-syntax-propertize))
2256 2261
2257;;; Invoke ruby-mode when appropriate 2262;;; Invoke ruby-mode when appropriate
2258 2263
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el
index fe39122d24f..2bccd857576 100644
--- a/lisp/progmodes/xref.el
+++ b/lisp/progmodes/xref.el
@@ -76,6 +76,7 @@
76 (require 'semantic/symref)) ;; for hit-lines slot 76 (require 'semantic/symref)) ;; for hit-lines slot
77 77
78(defgroup xref nil "Cross-referencing commands" 78(defgroup xref nil "Cross-referencing commands"
79 :version "25.1"
79 :group 'tools) 80 :group 'tools)
80 81
81 82
@@ -510,11 +511,18 @@ references displayed in the current *xref* buffer."
510 (let ((fr (read-regexp "Xref query-replace (regexp)" ".*"))) 511 (let ((fr (read-regexp "Xref query-replace (regexp)" ".*")))
511 (list fr 512 (list fr
512 (read-regexp (format "Xref query-replace (regexp) %s with: " fr))))) 513 (read-regexp (format "Xref query-replace (regexp) %s with: " fr)))))
513 (let (pairs item) 514 (let ((reporter (make-progress-reporter (format "Saving search results...")
515 0 (line-number-at-pos (point-max))))
516 (counter 0)
517 pairs item)
514 (unwind-protect 518 (unwind-protect
515 (progn 519 (progn
516 (save-excursion 520 (save-excursion
517 (goto-char (point-min)) 521 (goto-char (point-min))
522 ;; TODO: This list should be computed on-demand instead.
523 ;; As long as the UI just iterates through matches one by
524 ;; one, there's no need to compute them all in advance.
525 ;; Then we can throw away the reporter.
518 (while (setq item (xref--search-property 'xref-item)) 526 (while (setq item (xref--search-property 'xref-item))
519 (when (xref-match-length item) 527 (when (xref-match-length item)
520 (save-excursion 528 (save-excursion
@@ -534,9 +542,11 @@ references displayed in the current *xref* buffer."
534 (line-end-position)) 542 (line-end-position))
535 (xref-item-summary item)) 543 (xref-item-summary item))
536 (user-error "Search results out of date")) 544 (user-error "Search results out of date"))
545 (progress-reporter-update reporter (cl-incf counter))
537 (push (cons beg end) pairs))))) 546 (push (cons beg end) pairs)))))
538 (setq pairs (nreverse pairs))) 547 (setq pairs (nreverse pairs)))
539 (unless pairs (user-error "No suitable matches here")) 548 (unless pairs (user-error "No suitable matches here"))
549 (progress-reporter-done reporter)
540 (xref--query-replace-1 from to pairs)) 550 (xref--query-replace-1 from to pairs))
541 (dolist (pair pairs) 551 (dolist (pair pairs)
542 (move-marker (car pair) nil) 552 (move-marker (car pair) nil)
@@ -712,9 +722,9 @@ Return an alist of the form ((FILENAME . (XREF ...)) ...)."
712 722
713(defvar xref--read-pattern-history nil) 723(defvar xref--read-pattern-history nil)
714 724
715(defun xref--show-xrefs (xrefs window) 725(defun xref--show-xrefs (xrefs window &optional always-show-list)
716 (cond 726 (cond
717 ((not (cdr xrefs)) 727 ((and (not (cdr xrefs)) (not always-show-list))
718 (xref-push-marker-stack) 728 (xref-push-marker-stack)
719 (xref--pop-to-location (car xrefs) window)) 729 (xref--pop-to-location (car xrefs) window))
720 (t 730 (t
@@ -865,11 +875,12 @@ tools are used, and when."
865 (mapc #'kill-buffer 875 (mapc #'kill-buffer
866 (cl-set-difference (buffer-list) orig-buffers))))) 876 (cl-set-difference (buffer-list) orig-buffers)))))
867 877
878;;;###autoload
868(defun xref-collect-matches (regexp files dir ignores) 879(defun xref-collect-matches (regexp files dir ignores)
869 "Collect matches for REGEXP inside FILES in DIR. 880 "Collect matches for REGEXP inside FILES in DIR.
870FILES is a string with glob patterns separated by spaces. 881FILES is a string with glob patterns separated by spaces.
871IGNORES is a list of glob patterns." 882IGNORES is a list of glob patterns."
872 (cl-assert (directory-name-p dir)) 883 ;; DIR can also be a regular file for now; let's not advertise that.
873 (require 'semantic/fw) 884 (require 'semantic/fw)
874 (grep-compute-defaults) 885 (grep-compute-defaults)
875 (defvar grep-find-template) 886 (defvar grep-find-template)
@@ -884,6 +895,8 @@ IGNORES is a list of glob patterns."
884 (orig-buffers (buffer-list)) 895 (orig-buffers (buffer-list))
885 (buf (get-buffer-create " *xref-grep*")) 896 (buf (get-buffer-create " *xref-grep*"))
886 (grep-re (caar grep-regexp-alist)) 897 (grep-re (caar grep-regexp-alist))
898 (counter 0)
899 reporter
887 hits) 900 hits)
888 (with-current-buffer buf 901 (with-current-buffer buf
889 (erase-buffer) 902 (erase-buffer)
@@ -893,9 +906,17 @@ IGNORES is a list of glob patterns."
893 (push (cons (string-to-number (match-string 2)) 906 (push (cons (string-to-number (match-string 2))
894 (match-string 1)) 907 (match-string 1))
895 hits))) 908 hits)))
909 (setq reporter (make-progress-reporter
910 (format "Collecting search results...")
911 0 (length hits)))
896 (unwind-protect 912 (unwind-protect
897 (cl-mapcan (lambda (hit) (xref--collect-matches hit regexp)) 913 (cl-mapcan (lambda (hit)
914 (prog1
915 (progress-reporter-update reporter counter)
916 (cl-incf counter))
917 (xref--collect-matches hit regexp))
898 (nreverse hits)) 918 (nreverse hits))
919 (progress-reporter-done reporter)
899 ;; TODO: Same as above. 920 ;; TODO: Same as above.
900 (mapc #'kill-buffer 921 (mapc #'kill-buffer
901 (cl-set-difference (buffer-list) orig-buffers))))) 922 (cl-set-difference (buffer-list) orig-buffers)))))
@@ -921,23 +942,24 @@ IGNORES is a list of glob patterns."
921(defun xref--find-ignores-arguments (ignores dir) 942(defun xref--find-ignores-arguments (ignores dir)
922 ;; `shell-quote-argument' quotes the tilde as well. 943 ;; `shell-quote-argument' quotes the tilde as well.
923 (cl-assert (not (string-match-p "\\`~" dir))) 944 (cl-assert (not (string-match-p "\\`~" dir)))
924 (concat 945 (when ignores
925 (shell-quote-argument "(") 946 (concat
926 " -path " 947 (shell-quote-argument "(")
927 (mapconcat 948 " -path "
928 (lambda (ignore) 949 (mapconcat
929 (when (string-match-p "/\\'" ignore) 950 (lambda (ignore)
930 (setq ignore (concat ignore "*"))) 951 (when (string-match-p "/\\'" ignore)
931 (if (string-match "\\`\\./" ignore) 952 (setq ignore (concat ignore "*")))
932 (setq ignore (replace-match dir t t ignore)) 953 (if (string-match "\\`\\./" ignore)
933 (unless (string-prefix-p "*" ignore) 954 (setq ignore (replace-match dir t t ignore))
934 (setq ignore (concat "*/" ignore)))) 955 (unless (string-prefix-p "*" ignore)
935 (shell-quote-argument ignore)) 956 (setq ignore (concat "*/" ignore))))
936 ignores 957 (shell-quote-argument ignore))
937 " -o -path ") 958 ignores
938 " " 959 " -o -path ")
939 (shell-quote-argument ")") 960 " "
940 " -prune -o ")) 961 (shell-quote-argument ")")
962 " -prune -o ")))
941 963
942(defun xref--regexp-to-extended (str) 964(defun xref--regexp-to-extended (str)
943 (replace-regexp-in-string 965 (replace-regexp-in-string
diff --git a/lisp/rect.el b/lisp/rect.el
index 789d0e9082d..73790f2f92a 100644
--- a/lisp/rect.el
+++ b/lisp/rect.el
@@ -403,6 +403,7 @@ With a prefix (or a FILL) argument, also fill too short lines."
403 403
404(defcustom rectangle-preview t 404(defcustom rectangle-preview t
405 "If non-nil, `string-rectangle' will show an-the-fly preview." 405 "If non-nil, `string-rectangle' will show an-the-fly preview."
406 :version "25.1"
406 :type 'boolean) 407 :type 'boolean)
407 408
408(defun rectangle--string-preview () 409(defun rectangle--string-preview ()
diff --git a/lisp/term/screen.el b/lisp/term/screen.el
index 704fbefb0ad..7f681154d6e 100644
--- a/lisp/term/screen.el
+++ b/lisp/term/screen.el
@@ -7,6 +7,7 @@
7 "Extra capabilities supported under \"screen\". 7 "Extra capabilities supported under \"screen\".
8Some features of screen depend on the terminal emulator in which 8Some features of screen depend on the terminal emulator in which
9it runs, which can change when the screen session is moved to another tty." 9it runs, which can change when the screen session is moved to another tty."
10 :version "25.1"
10 :type xterm--extra-capabilities-type 11 :type xterm--extra-capabilities-type
11 :group 'xterm) 12 :group 'xterm)
12 13
diff --git a/lisp/term/xterm.el b/lisp/term/xterm.el
index 104f98311a8..e06423ccfdd 100644
--- a/lisp/term/xterm.el
+++ b/lisp/term/xterm.el
@@ -65,6 +65,7 @@ using the OSC 52 sequence.
65If you select a region larger than this size, it won't be copied to your system 65If you select a region larger than this size, it won't be copied to your system
66clipboard. Since clipboard data is base 64 encoded, the actual number of 66clipboard. Since clipboard data is base 64 encoded, the actual number of
67string bytes that can be copied is 3/4 of this value." 67string bytes that can be copied is 3/4 of this value."
68 :version "25.1"
68 :type 'integer) 69 :type 'integer)
69 70
70(defconst xterm-paste-ending-sequence "\e[201~" 71(defconst xterm-paste-ending-sequence "\e[201~"
diff --git a/lisp/textmodes/css-mode.el b/lisp/textmodes/css-mode.el
index 48c24844a68..d402fb19955 100644
--- a/lisp/textmodes/css-mode.el
+++ b/lisp/textmodes/css-mode.el
@@ -257,13 +257,13 @@
257 (if (not sassy) 257 (if (not sassy)
258 ;; We don't allow / as first char, so as not to 258 ;; We don't allow / as first char, so as not to
259 ;; take a comment as the beginning of a selector. 259 ;; take a comment as the beginning of a selector.
260 "[^@/:{} \t\n][^:{}]+" 260 "[^@/:{}() \t\n][^:{}()]+"
261 ;; Same as for non-sassy except we do want to allow { and } 261 ;; Same as for non-sassy except we do want to allow { and }
262 ;; chars in selectors in the case of #{$foo} 262 ;; chars in selectors in the case of #{$foo}
263 ;; variable interpolation! 263 ;; variable interpolation!
264 (concat "\\(?:" scss--hash-re 264 (concat "\\(?:" scss--hash-re
265 "\\|[^@/:{} \t\n#]\\)" 265 "\\|[^@/:{}() \t\n#]\\)"
266 "[^:{}#]*\\(?:" scss--hash-re "[^:{}#]*\\)*")) 266 "[^:{}()#]*\\(?:" scss--hash-re "[^:{}()#]*\\)*"))
267 ;; Even though pseudo-elements should be prefixed by ::, a 267 ;; Even though pseudo-elements should be prefixed by ::, a
268 ;; single colon is accepted for backward compatibility. 268 ;; single colon is accepted for backward compatibility.
269 "\\(?:\\(:" (regexp-opt (append css-pseudo-class-ids 269 "\\(?:\\(:" (regexp-opt (append css-pseudo-class-ids
@@ -271,8 +271,8 @@
271 "\\|\\::" (regexp-opt css-pseudo-element-ids t) "\\)" 271 "\\|\\::" (regexp-opt css-pseudo-element-ids t) "\\)"
272 "\\(?:([^)]+)\\)?" 272 "\\(?:([^)]+)\\)?"
273 (if (not sassy) 273 (if (not sassy)
274 "[^:{}\n]*" 274 "[^:{}()\n]*"
275 (concat "[^:{}\n#]*\\(?:" scss--hash-re "[^:{}\n#]*\\)*")) 275 (concat "[^:{}()\n#]*\\(?:" scss--hash-re "[^:{}()\n#]*\\)*"))
276 "\\)*" 276 "\\)*"
277 "\\)\\(?:\n[ \t]*\\)*{") 277 "\\)\\(?:\n[ \t]*\\)*{")
278 (1 'css-selector keep)) 278 (1 'css-selector keep))
diff --git a/lisp/textmodes/sgml-mode.el b/lisp/textmodes/sgml-mode.el
index 98a01e8d83f..f729760e9ca 100644
--- a/lisp/textmodes/sgml-mode.el
+++ b/lisp/textmodes/sgml-mode.el
@@ -862,11 +862,12 @@ Return non-nil if we skipped over matched tags."
862 (if endp 862 (if endp
863 (when (sgml-skip-tag-backward 1) (forward-char 1) t) 863 (when (sgml-skip-tag-backward 1) (forward-char 1) t)
864 (with-syntax-table sgml-tag-syntax-table 864 (with-syntax-table sgml-tag-syntax-table
865 (up-list -1) 865 (let ((forward-sexp-function nil))
866 (when (sgml-skip-tag-forward 1) 866 (up-list -1)
867 (backward-sexp 1) 867 (when (sgml-skip-tag-forward 1)
868 (forward-char 2) 868 (backward-sexp 1)
869 t)))) 869 (forward-char 2)
870 t)))))
870 (clones (get-char-property (point) 'text-clones))) 871 (clones (get-char-property (point) 'text-clones)))
871 (when (and match 872 (when (and match
872 (/= cl-end cl-start) 873 (/= cl-end cl-start)
diff --git a/lisp/textmodes/tildify.el b/lisp/textmodes/tildify.el
index eb799c09510..598060e9ec8 100644
--- a/lisp/textmodes/tildify.el
+++ b/lisp/textmodes/tildify.el
@@ -417,7 +417,7 @@ current `case-fold-search' setting."
417 "A list of predicate functions for `tildify-space' function." 417 "A list of predicate functions for `tildify-space' function."
418 :version "25.1" 418 :version "25.1"
419 :group 'tildify 419 :group 'tildify
420 :type '(repeat 'function)) 420 :type '(repeat function))
421 421
422(defcustom tildify-double-space-undos t 422(defcustom tildify-double-space-undos t
423 "Weather `tildify-space' should undo hard space when space is typed again." 423 "Weather `tildify-space' should undo hard space when space is typed again."
diff --git a/lisp/thingatpt.el b/lisp/thingatpt.el
index 9794d002149..1686c02ada3 100644
--- a/lisp/thingatpt.el
+++ b/lisp/thingatpt.el
@@ -280,8 +280,8 @@ If nil, construct the regexp from `thing-at-point-uri-schemes'.")
280 "finger://" "fish://" "ftp://" "geo:" "git://" "go:" "gopher://" 280 "finger://" "fish://" "ftp://" "geo:" "git://" "go:" "gopher://"
281 "h323:" "http://" "https://" "im:" "imap://" "info:" "ipp:" 281 "h323:" "http://" "https://" "im:" "imap://" "info:" "ipp:"
282 "irc://" "irc6://" "ircs://" "iris.beep:" "jar:" "ldap://" 282 "irc://" "irc6://" "ircs://" "iris.beep:" "jar:" "ldap://"
283 "ldaps://" "mailto:" "mid:" "mtqp://" "mupdate://" "news:" 283 "ldaps://" "magnet:" "mailto:" "mid:" "mtqp://" "mupdate://"
284 "nfs://" "nntp://" "opaquelocktoken:" "pop://" "pres:" 284 "news:" "nfs://" "nntp://" "opaquelocktoken:" "pop://" "pres:"
285 "resource://" "rmi://" "rsync://" "rtsp://" "rtspu://" "service:" 285 "resource://" "rmi://" "rsync://" "rtsp://" "rtspu://" "service:"
286 "sftp://" "sip:" "sips:" "smb://" "sms:" "snmp://" "soap.beep://" 286 "sftp://" "sip:" "sips:" "smb://" "sms:" "snmp://" "soap.beep://"
287 "soap.beeps://" "ssh://" "svn://" "svn+ssh://" "tag:" "tel:" 287 "soap.beeps://" "ssh://" "svn://" "svn+ssh://" "tag:" "tel:"
diff --git a/lisp/time-stamp.el b/lisp/time-stamp.el
index 46c993e1f5f..d58942c3a2b 100644
--- a/lisp/time-stamp.el
+++ b/lisp/time-stamp.el
@@ -5,7 +5,6 @@
5 5
6;; This file is part of GNU Emacs. 6;; This file is part of GNU Emacs.
7 7
8;; Maintainer's Time-stamp: <2006-04-12 20:30:56 rms>
9;; Maintainer: Stephen Gildea <gildea@stop.mail-abuse.org> 8;; Maintainer: Stephen Gildea <gildea@stop.mail-abuse.org>
10;; Keywords: tools 9;; Keywords: tools
11 10
@@ -27,7 +26,6 @@
27;; A template in a file can be updated with a new time stamp when 26;; A template in a file can be updated with a new time stamp when
28;; you save the file. For example: 27;; you save the file. For example:
29;; static char *ts = "sdmain.c Time-stamp: <2001-08-13 10:20:51 gildea>"; 28;; static char *ts = "sdmain.c Time-stamp: <2001-08-13 10:20:51 gildea>";
30;; See the top of `time-stamp.el' for another example.
31 29
32;; To use time-stamping, add this line to your init file: 30;; To use time-stamping, add this line to your init file:
33;; (add-hook 'before-save-hook 'time-stamp) 31;; (add-hook 'before-save-hook 'time-stamp)
@@ -121,9 +119,12 @@ If nil, no notification is given."
121 :group 'time-stamp) 119 :group 'time-stamp)
122 120
123(defcustom time-stamp-time-zone nil 121(defcustom time-stamp-time-zone nil
124 "If non-nil, a string naming the timezone to be used by \\[time-stamp]. 122 "The time zone to be used by \\[time-stamp].
125Format is the same as that used by the environment variable TZ on your system." 123Its format is that of the ZONE argument of the `format-time-string' function,"
126 :type '(choice (const nil) string) 124 :type '(choice (const :tag "Emacs local time" nil)
125 (const :tag "Universal Time" t)
126 (const :tag "system wall clock time" wall)
127 (string :tag "TZ environment variable value"))
127 :group 'time-stamp 128 :group 'time-stamp
128 :version "20.1") 129 :version "20.1")
129;;;###autoload(put 'time-stamp-time-zone 'safe-local-variable 'string-or-null-p) 130;;;###autoload(put 'time-stamp-time-zone 'safe-local-variable 'string-or-null-p)
@@ -412,6 +413,8 @@ With ARG, turn time stamping on if and only if arg is positive."
412 (> (prefix-numeric-value arg) 0))) 413 (> (prefix-numeric-value arg) 0)))
413 (message "time-stamp is now %s." (if time-stamp-active "active" "off"))) 414 (message "time-stamp is now %s." (if time-stamp-active "active" "off")))
414 415
416(defun time-stamp--format (format time)
417 (format-time-string format time time-stamp-time-zone))
415 418
416(defun time-stamp-string (&optional ts-format) 419(defun time-stamp-string (&optional ts-format)
417 "Generate the new string to be inserted by \\[time-stamp]. 420 "Generate the new string to be inserted by \\[time-stamp].
@@ -420,8 +423,7 @@ format the string."
420 (or ts-format 423 (or ts-format
421 (setq ts-format time-stamp-format)) 424 (setq ts-format time-stamp-format))
422 (if (stringp ts-format) 425 (if (stringp ts-format)
423 (format-time-string (time-stamp-string-preprocess ts-format) 426 (time-stamp--format (time-stamp-string-preprocess ts-format) nil)
424 nil time-stamp-time-zone)
425 ;; handle version 1 compatibility 427 ;; handle version 1 compatibility
426 (cond ((or (eq time-stamp-old-format-warn 'error) 428 (cond ((or (eq time-stamp-old-format-warn 'error)
427 (and (eq time-stamp-old-format-warn 'ask) 429 (and (eq time-stamp-old-format-warn 'ask)
@@ -515,32 +517,32 @@ and all `time-stamp-format' compatibility."
515 "%%") 517 "%%")
516 ((eq cur-char ?a) ;day of week 518 ((eq cur-char ?a) ;day of week
517 (if change-case 519 (if change-case
518 (format-time-string "%#a" time) 520 (time-stamp--format "%#a" time)
519 (or alt-form (not (string-equal field-width "")) 521 (or alt-form (not (string-equal field-width ""))
520 (time-stamp-conv-warn "%a" "%:a")) 522 (time-stamp-conv-warn "%a" "%:a"))
521 (if (and alt-form (not (string-equal field-width ""))) 523 (if (and alt-form (not (string-equal field-width "")))
522 "" ;discourage "%:3a" 524 "" ;discourage "%:3a"
523 (format-time-string "%A" time)))) 525 (time-stamp--format "%A" time))))
524 ((eq cur-char ?A) 526 ((eq cur-char ?A)
525 (if alt-form 527 (if alt-form
526 (format-time-string "%A" time) 528 (time-stamp--format "%A" time)
527 (or change-case (not (string-equal field-width "")) 529 (or change-case (not (string-equal field-width ""))
528 (time-stamp-conv-warn "%A" "%#A")) 530 (time-stamp-conv-warn "%A" "%#A"))
529 (format-time-string "%#A" time))) 531 (time-stamp--format "%#A" time)))
530 ((eq cur-char ?b) ;month name 532 ((eq cur-char ?b) ;month name
531 (if change-case 533 (if change-case
532 (format-time-string "%#b" time) 534 (time-stamp--format "%#b" time)
533 (or alt-form (not (string-equal field-width "")) 535 (or alt-form (not (string-equal field-width ""))
534 (time-stamp-conv-warn "%b" "%:b")) 536 (time-stamp-conv-warn "%b" "%:b"))
535 (if (and alt-form (not (string-equal field-width ""))) 537 (if (and alt-form (not (string-equal field-width "")))
536 "" ;discourage "%:3b" 538 "" ;discourage "%:3b"
537 (format-time-string "%B" time)))) 539 (time-stamp--format "%B" time))))
538 ((eq cur-char ?B) 540 ((eq cur-char ?B)
539 (if alt-form 541 (if alt-form
540 (format-time-string "%B" time) 542 (time-stamp--format "%B" time)
541 (or change-case (not (string-equal field-width "")) 543 (or change-case (not (string-equal field-width ""))
542 (time-stamp-conv-warn "%B" "%#B")) 544 (time-stamp-conv-warn "%B" "%#B"))
543 (format-time-string "%#B" time))) 545 (time-stamp--format "%#B" time)))
544 ((eq cur-char ?d) ;day of month, 1-31 546 ((eq cur-char ?d) ;day of month, 1-31
545 (time-stamp-do-number cur-char alt-form field-width time)) 547 (time-stamp-do-number cur-char alt-form field-width time))
546 ((eq cur-char ?H) ;hour, 0-23 548 ((eq cur-char ?H) ;hour, 0-23
@@ -554,27 +556,27 @@ and all `time-stamp-format' compatibility."
554 ((eq cur-char ?p) ;am or pm 556 ((eq cur-char ?p) ;am or pm
555 (or change-case 557 (or change-case
556 (time-stamp-conv-warn "%p" "%#p")) 558 (time-stamp-conv-warn "%p" "%#p"))
557 (format-time-string "%#p" time)) 559 (time-stamp--format "%#p" time))
558 ((eq cur-char ?P) ;AM or PM 560 ((eq cur-char ?P) ;AM or PM
559 (format-time-string "%p" time)) 561 (time-stamp--format "%p" time))
560 ((eq cur-char ?S) ;seconds, 00-60 562 ((eq cur-char ?S) ;seconds, 00-60
561 (time-stamp-do-number cur-char alt-form field-width time)) 563 (time-stamp-do-number cur-char alt-form field-width time))
562 ((eq cur-char ?w) ;weekday number, Sunday is 0 564 ((eq cur-char ?w) ;weekday number, Sunday is 0
563 (format-time-string "%w" time)) 565 (time-stamp--format "%w" time))
564 ((eq cur-char ?y) ;year 566 ((eq cur-char ?y) ;year
565 (or alt-form (not (string-equal field-width "")) 567 (or alt-form (not (string-equal field-width ""))
566 (time-stamp-conv-warn "%y" "%:y")) 568 (time-stamp-conv-warn "%y" "%:y"))
567 (string-to-number (format-time-string "%Y" time))) 569 (string-to-number (time-stamp--format "%Y" time)))
568 ((eq cur-char ?Y) ;4-digit year, new style 570 ((eq cur-char ?Y) ;4-digit year, new style
569 (string-to-number (format-time-string "%Y" time))) 571 (string-to-number (time-stamp--format "%Y" time)))
570 ((eq cur-char ?z) ;time zone lower case 572 ((eq cur-char ?z) ;time zone lower case
571 (if change-case 573 (if change-case
572 "" ;discourage %z variations 574 "" ;discourage %z variations
573 (format-time-string "%#Z" time))) 575 (time-stamp--format "%#Z" time)))
574 ((eq cur-char ?Z) 576 ((eq cur-char ?Z)
575 (if change-case 577 (if change-case
576 (format-time-string "%#Z" time) 578 (time-stamp--format "%#Z" time)
577 (format-time-string "%Z" time))) 579 (time-stamp--format "%Z" time)))
578 ((eq cur-char ?f) ;buffer-file-name, base name only 580 ((eq cur-char ?f) ;buffer-file-name, base name only
579 (if buffer-file-name 581 (if buffer-file-name
580 (file-name-nondirectory buffer-file-name) 582 (file-name-nondirectory buffer-file-name)
@@ -634,7 +636,7 @@ width specification or \"\". TIME is the time to convert."
634 (format "%%:%c" format-char))) 636 (format "%%:%c" format-char)))
635 (if (and alt-form (not (string-equal field-width ""))) 637 (if (and alt-form (not (string-equal field-width "")))
636 "" ;discourage "%:2d" and the like 638 "" ;discourage "%:2d" and the like
637 (string-to-number (format-time-string format-string time))))) 639 (string-to-number (time-stamp--format format-string time)))))
638 640
639(defvar time-stamp-conversion-warn t 641(defvar time-stamp-conversion-warn t
640 "Warn about soon-to-be-unsupported forms in `time-stamp-format'. 642 "Warn about soon-to-be-unsupported forms in `time-stamp-format'.
diff --git a/lisp/url/url-tramp.el b/lisp/url/url-tramp.el
index 9e191579d47..192a0459f33 100644
--- a/lisp/url/url-tramp.el
+++ b/lisp/url/url-tramp.el
@@ -30,11 +30,11 @@
30 30
31;;;###autoload 31;;;###autoload
32(defcustom url-tramp-protocols '("ftp" "ssh" "scp" "rsync" "telnet") 32(defcustom url-tramp-protocols '("ftp" "ssh" "scp" "rsync" "telnet")
33 "List of URL protocols the work is handled by Tramp. 33 "List of URL protocols for which the work is handled by Tramp.
34They must also be covered by `url-handler-regexp'." 34They must also be covered by `url-handler-regexp'."
35 :group 'url 35 :group 'url
36 :version "25.1" 36 :version "25.1"
37 :type '(list string)) 37 :type '(repeat string))
38 38
39(defun url-tramp-convert-url-to-tramp (url) 39(defun url-tramp-convert-url-to-tramp (url)
40 "Convert URL to a Tramp file name." 40 "Convert URL to a Tramp file name."