emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

feature/pgtk 8c74536: Merge branch 'master' of git.sv.gnu.org:/srv/git/e


From: Yuuki Harano
Subject: feature/pgtk 8c74536: Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk
Date: Mon, 5 Apr 2021 11:21:07 -0400 (EDT)

branch: feature/pgtk
commit 8c7453632e8f45ed65ce814eafc0a1af637774c1
Merge: 5d2f319 0342354
Author: Yuuki Harano <masm+github@masm11.me>
Commit: Yuuki Harano <masm+github@masm11.me>

    Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk
---
 ChangeLog.3                                        |    18 +-
 GNUmakefile                                        |     2 +
 Makefile.in                                        |     4 +-
 admin/admin.el                                     |     4 +-
 admin/charsets/Makefile.in                         |    12 +-
 admin/grammars/Makefile.in                         |    35 +-
 admin/make-tarball.txt                             |    66 +-
 admin/notes/emba                                   |    15 +
 admin/unidata/Makefile.in                          |    16 +-
 doc/emacs/emacs.texi                               |     1 +
 doc/emacs/maintaining.texi                         |    16 +
 doc/emacs/mini.texi                                |     4 +-
 doc/lispintro/emacs-lisp-intro.texi                |    96 +-
 doc/lispref/display.texi                           |    22 +
 doc/lispref/files.texi                             |     2 +
 doc/lispref/strings.texi                           |    16 +
 doc/misc/Makefile.in                               |    15 +-
 doc/misc/gnus-faq.texi                             |     4 +-
 doc/misc/nxml-mode.texi                            |     2 +-
 doc/misc/reftex.texi                               |    85 +-
 doc/misc/texinfo.tex                               |     4 +-
 doc/misc/tramp.texi                                |    20 +
 doc/misc/woman.texi                                |     8 +-
 etc/NEWS                                           |    32 +-
 etc/NEWS.27                                        |     1 -
 etc/images/README                                  |    27 +
 etc/images/checkbox-mixed.svg                      |     6 +
 etc/images/checked.svg                             |     6 +
 etc/images/down.svg                                |    40 +
 etc/images/left.svg                                |    40 +
 etc/images/radio-checked.svg                       |     6 +
 etc/images/radio-mixed.svg                         |     6 +
 etc/images/radio.svg                               |     3 +
 etc/images/right.svg                               |    40 +
 etc/images/unchecked.svg                           |     3 +
 etc/images/up.svg                                  |    40 +
 .../OpenDocument-schema-v1.3+libreoffice.rnc       |   892 ++
 ...ma-v1.2-os.rnc => OpenDocument-schema-v1.3.rnc} | 11694 ++++++++++---------
 etc/schema/schemas.xml                             |     6 +-
 leim/Makefile.in                                   |    14 +-
 lib/pipe2.c                                        |     2 +-
 lisp/Makefile.in                                   |     4 +-
 lisp/allout-widgets.el                             |    98 +-
 lisp/allout.el                                     |   135 +-
 lisp/auth-source-pass.el                           |     8 +-
 lisp/avoid.el                                      |    17 +-
 lisp/bs.el                                         |     2 -
 lisp/calendar/cal-bahai.el                         |     2 +-
 lisp/calendar/icalendar.el                         |    11 +-
 lisp/calendar/iso8601.el                           |     2 +-
 lisp/calendar/timeclock.el                         |     2 -
 lisp/cedet/mode-local.el                           |    40 +-
 lisp/cedet/pulse.el                                |     3 +-
 lisp/cedet/semantic.el                             |    18 +-
 lisp/cedet/semantic/bovine/c.el                    |     4 +-
 lisp/cedet/semantic/bovine/grammar.el              |     5 +-
 lisp/cedet/semantic/db-ebrowse.el                  |     2 +-
 lisp/cedet/semantic/db-global.el                   |     2 +-
 lisp/cedet/semantic/edit.el                        |     4 +-
 lisp/cedet/semantic/fw.el                          |    10 +-
 lisp/cedet/semantic/grammar.el                     |    46 +-
 lisp/cedet/semantic/idle.el                        |    12 +-
 lisp/cedet/semantic/imenu.el                       |    12 +-
 lisp/cedet/semantic/java.el                        |    50 +-
 lisp/cedet/semantic/lex-spp.el                     |    20 +-
 lisp/cedet/semantic/lex.el                         |    10 +-
 lisp/cedet/semantic/util-modes.el                  |     2 +-
 lisp/cedet/semantic/wisent.el                      |     5 +-
 lisp/cedet/semantic/wisent/comp.el                 |    39 +-
 lisp/cedet/semantic/wisent/grammar.el              |    24 +-
 lisp/cedet/semantic/wisent/java-tags.el            |     3 -
 lisp/cedet/semantic/wisent/python.el               |     2 -
 lisp/cedet/semantic/wisent/wisent.el               |     3 -
 lisp/chistory.el                                   |    21 +-
 lisp/cmuscheme.el                                  |     4 +-
 lisp/comint.el                                     |     6 +-
 lisp/completion.el                                 |    82 +-
 lisp/dframe.el                                     |     2 +-
 lisp/dirtrack.el                                   |    10 +-
 lisp/doc-view.el                                   |    13 +-
 lisp/double.el                                     |     4 +-
 lisp/dynamic-setting.el                            |     4 +-
 lisp/ebuff-menu.el                                 |    90 +-
 lisp/echistory.el                                  |    77 +-
 lisp/emacs-lisp/checkdoc.el                        |     9 +-
 lisp/emacs-lisp/lisp-mode.el                       |     2 +-
 lisp/emacs-lisp/seq.el                             |     3 +
 lisp/emacs-lisp/shortdoc.el                        |     3 -
 lisp/emacs-lisp/smie.el                            |     2 +-
 lisp/emacs-lisp/subr-x.el                          |    22 -
 lisp/emulation/edt-mapper.el                       |     2 +
 lisp/emulation/edt.el                              |     8 +-
 lisp/emulation/viper-cmd.el                        |    31 +-
 lisp/epg-config.el                                 |     6 +-
 lisp/erc/erc.el                                    |     3 -
 lisp/eshell/em-dirs.el                             |     8 +-
 lisp/eshell/em-hist.el                             |     2 +-
 lisp/eshell/em-pred.el                             |    58 +-
 lisp/eshell/em-script.el                           |    10 +-
 lisp/eshell/esh-mode.el                            |     2 +-
 lisp/eshell/esh-opt.el                             |     8 -
 lisp/eshell/esh-util.el                            |    36 +-
 lisp/eshell/eshell.el                              |     6 +-
 lisp/faces.el                                      |    16 +-
 lisp/files-x.el                                    |    13 +-
 lisp/foldout.el                                    |    19 +-
 lisp/follow.el                                     |   140 +-
 lisp/forms.el                                      |    82 +-
 lisp/frame.el                                      |    11 +-
 lisp/gnus/gnus-art.el                              |     7 +-
 lisp/gnus/gnus-cite.el                             |     4 +-
 lisp/gnus/gnus-group.el                            |    38 +-
 lisp/gnus/gnus-range.el                            |    17 +-
 lisp/gnus/gnus-registry.el                         |     6 +-
 lisp/gnus/gnus-score.el                            |     4 +-
 lisp/gnus/gnus-sum.el                              |    42 +-
 lisp/gnus/gnus-util.el                             |     8 +-
 lisp/gnus/gnus-uu.el                               |     4 +-
 lisp/gnus/message.el                               |     2 +-
 lisp/gnus/mm-partial.el                            |    16 +-
 lisp/gnus/mml-sec.el                               |     2 +-
 lisp/gnus/nndiary.el                               |     2 +-
 lisp/gnus/nnimap.el                                |    11 +-
 lisp/gnus/nnmaildir.el                             |     2 +-
 lisp/gnus/nnselect.el                              |    68 +-
 lisp/gnus/nnvirtual.el                             |     6 +-
 lisp/gnus/smime.el                                 |     2 +-
 lisp/gnus/spam-stat.el                             |     2 +-
 lisp/gnus/spam.el                                  |    14 +-
 lisp/help-at-pt.el                                 |     5 +-
 lisp/hilit-chg.el                                  |   117 +-
 lisp/htmlfontify.el                                |    61 +-
 lisp/iimage.el                                     |    13 +-
 lisp/image-dired.el                                |     6 +-
 lisp/image.el                                      |     9 +-
 lisp/international/ccl.el                          |     6 -
 lisp/international/characters.el                   |    60 +-
 lisp/international/fontset.el                      |    48 +-
 lisp/international/latin1-disp.el                  |     4 +-
 lisp/international/mule-cmds.el                    |    60 +-
 lisp/international/mule-conf.el                    |     6 +-
 lisp/international/mule-diag.el                    |    18 +-
 lisp/international/mule.el                         |    28 +-
 lisp/international/quail.el                        |    32 +-
 lisp/international/titdic-cnv.el                   |    26 +-
 lisp/isearchb.el                                   |     8 +-
 lisp/json.el                                       |     2 +-
 lisp/language/cyrillic.el                          |     2 +-
 lisp/ldefs-boot.el                                 |   303 +-
 lisp/leim/quail/ipa-praat.el                       |     2 +-
 lisp/leim/quail/ipa.el                             |     4 +-
 lisp/leim/quail/latin-post.el                      |     2 +-
 lisp/leim/quail/latin-pre.el                       |     2 +-
 lisp/leim/quail/programmer-dvorak.el               |     2 +-
 lisp/linum.el                                      |     6 +-
 lisp/loadhist.el                                   |    15 +-
 lisp/lpr.el                                        |    39 +-
 lisp/mail/feedmail.el                              |     2 +-
 lisp/mail/mail-extr.el                             |     4 +-
 lisp/mail/rmail.el                                 |     6 +-
 lisp/mail/smtpmail.el                              |    18 +-
 lisp/man.el                                        |     4 +-
 lisp/master.el                                     |    15 +-
 lisp/mh-e/mh-alias.el                              |    19 +-
 lisp/mh-e/mh-buffers.el                            |     2 +-
 lisp/mh-e/mh-comp.el                               |    20 +-
 lisp/mh-e/mh-compat.el                             |     2 +-
 lisp/mh-e/mh-e.el                                  |    64 +-
 lisp/mh-e/mh-folder.el                             |    24 +-
 lisp/mh-e/mh-funcs.el                              |     4 +-
 lisp/mh-e/mh-gnus.el                               |     4 +-
 lisp/mh-e/mh-identity.el                           |    12 +-
 lisp/mh-e/mh-inc.el                                |    18 +-
 lisp/mh-e/mh-junk.el                               |     2 +-
 lisp/mh-e/mh-letter.el                             |    15 +-
 lisp/mh-e/mh-limit.el                              |     4 +-
 lisp/mh-e/mh-mime.el                               |    58 +-
 lisp/mh-e/mh-print.el                              |     7 +-
 lisp/mh-e/mh-scan.el                               |     4 +-
 lisp/mh-e/mh-search.el                             |    12 +-
 lisp/mh-e/mh-seq.el                                |    28 +-
 lisp/mh-e/mh-show.el                               |     8 +-
 lisp/mh-e/mh-speed.el                              |    12 +-
 lisp/mh-e/mh-thread.el                             |     2 +-
 lisp/mh-e/mh-tool-bar.el                           |     6 +-
 lisp/mh-e/mh-utils.el                              |    22 +-
 lisp/mh-e/mh-xface.el                              |     4 +-
 lisp/minibuffer.el                                 |     6 +-
 lisp/mpc.el                                        |    14 +-
 lisp/net/dbus.el                                   |     5 +-
 lisp/net/gnutls.el                                 |     6 +-
 lisp/net/imap.el                                   |     6 +-
 lisp/net/newst-backend.el                          |    11 +-
 lisp/net/newst-plainview.el                        |     3 +-
 lisp/net/newst-treeview.el                         |     5 +-
 lisp/net/nsm.el                                    |     2 +-
 lisp/net/pop3.el                                   |     6 +-
 lisp/net/tramp-integration.el                      |     1 +
 lisp/net/tramp-sh.el                               |   211 +-
 lisp/notifications.el                              |    99 +-
 lisp/nxml/rng-cmpct.el                             |     2 +-
 lisp/nxml/rng-loc.el                               |     2 +-
 lisp/nxml/rng-match.el                             |     2 +-
 lisp/nxml/rng-nxml.el                              |     2 +-
 lisp/nxml/rng-util.el                              |    28 +-
 lisp/nxml/rng-xsd.el                               |     6 +-
 lisp/obsolete/bruce.el                             |     2 +-
 lisp/obsolete/inversion.el                         |     2 +-
 lisp/obsolete/nnir.el                              |     4 +-
 lisp/obsolete/terminal.el                          |     2 +-
 lisp/obsolete/tpu-extras.el                        |    29 +-
 lisp/obsolete/vc-arch.el                           |     2 +-
 lisp/org/ob-clojure.el                             |     2 +-
 lisp/org/ob-ocaml.el                               |     2 +-
 lisp/org/org-install.el                            |     2 +-
 lisp/org/org-macs.el                               |     3 +-
 lisp/org/org-version.el                            |     2 +-
 lisp/pcmpl-linux.el                                |     5 -
 lisp/pcmpl-x.el                                    |     2 +-
 lisp/pcomplete.el                                  |    27 +-
 lisp/pixel-scroll.el                               |     8 +-
 lisp/play/bubbles.el                               |     8 +-
 lisp/play/doctor.el                                |     2 +-
 lisp/play/morse.el                                 |     2 +-
 lisp/printing.el                                   |    85 +-
 lisp/progmodes/antlr-mode.el                       |     2 +-
 lisp/progmodes/cc-defs.el                          |    20 +-
 lisp/progmodes/cc-engine.el                        |    39 +-
 lisp/progmodes/cc-styles.el                        |     4 +-
 lisp/progmodes/cfengine.el                         |     4 +-
 lisp/progmodes/compile.el                          |     5 +-
 lisp/progmodes/cperl-mode.el                       |    32 +-
 lisp/progmodes/cwarn.el                            |     2 +-
 lisp/progmodes/dcl-mode.el                         |    59 +-
 lisp/progmodes/ebnf-abn.el                         |     6 +-
 lisp/progmodes/ebnf-bnf.el                         |     2 +-
 lisp/progmodes/ebnf-dtd.el                         |     2 +-
 lisp/progmodes/ebnf-ebx.el                         |     2 +-
 lisp/progmodes/ebnf-iso.el                         |     4 +-
 lisp/progmodes/ebnf-otz.el                         |     2 +-
 lisp/progmodes/ebnf-yac.el                         |    10 +-
 lisp/progmodes/ebnf2ps.el                          |    18 +-
 lisp/progmodes/elisp-mode.el                       |    19 +
 lisp/progmodes/etags.el                            |    16 +-
 lisp/progmodes/executable.el                       |     2 +-
 lisp/progmodes/grep.el                             |    28 +-
 lisp/progmodes/hideif.el                           |     4 +-
 lisp/progmodes/idlw-complete-structtag.el          |     9 +-
 lisp/progmodes/idlw-help.el                        |    97 +-
 lisp/progmodes/idlw-shell.el                       |   213 +-
 lisp/progmodes/idlw-toolbar.el                     |   117 +-
 lisp/progmodes/idlwave.el                          |  1042 +-
 lisp/progmodes/inf-lisp.el                         |   118 +-
 lisp/progmodes/modula2.el                          |    56 +-
 lisp/progmodes/octave.el                           |     8 +-
 lisp/progmodes/perl-mode.el                        |     6 +-
 lisp/progmodes/project.el                          |    35 +-
 lisp/progmodes/python.el                           |     8 +-
 lisp/progmodes/ruby-mode.el                        |     2 +-
 lisp/progmodes/scheme.el                           |     2 +-
 lisp/progmodes/simula.el                           |    87 +-
 lisp/progmodes/sql.el                              |     2 +-
 lisp/progmodes/tcl.el                              |     4 +-
 lisp/progmodes/vera-mode.el                        |     4 +-
 lisp/progmodes/verilog-mode.el                     |   473 +-
 lisp/progmodes/vhdl-mode.el                        |     2 +-
 lisp/progmodes/xref.el                             |     4 +-
 lisp/recentf.el                                    |   107 +-
 lisp/repeat.el                                     |     2 +-
 lisp/ruler-mode.el                                 |    54 +-
 lisp/scroll-all.el                                 |    21 +-
 lisp/ses.el                                        |    12 +-
 lisp/shadowfile.el                                 |    31 +-
 lisp/shell.el                                      |     7 +-
 lisp/simple.el                                     |    16 +-
 lisp/strokes.el                                    |   166 +-
 lisp/subr.el                                       |    26 +-
 lisp/tab-bar.el                                    |    53 +-
 lisp/talk.el                                       |     4 +-
 lisp/term.el                                       |     6 +-
 lisp/term/w32-win.el                               |     3 +
 lisp/textmodes/artist.el                           |    23 +-
 lisp/textmodes/bibtex-style.el                     |     2 +-
 lisp/textmodes/bibtex.el                           |     2 +-
 lisp/textmodes/css-mode.el                         |     2 +-
 lisp/textmodes/fill.el                             |    25 +-
 lisp/textmodes/ispell.el                           |     6 +-
 lisp/textmodes/reftex-auc.el                       |    14 +-
 lisp/textmodes/reftex-vars.el                      |    98 +-
 lisp/textmodes/remember.el                         |    11 +-
 lisp/textmodes/rst.el                              |   332 +-
 lisp/textmodes/sgml-mode.el                        |     2 +-
 lisp/textmodes/table.el                            |     6 +-
 lisp/thumbs.el                                     |    10 +-
 lisp/time.el                                       |    13 +-
 lisp/tree-widget.el                                |     4 +-
 lisp/url/ChangeLog.1                               |     2 +-
 lisp/url/url-cookie.el                             |    10 +-
 lisp/url/url-dav.el                                |    17 +-
 lisp/url/url-history.el                            |    16 +-
 lisp/url/url-mailto.el                             |     4 +-
 lisp/url/url-news.el                               |     5 -
 lisp/url/url-vars.el                               |     9 +-
 lisp/userlock.el                                   |    10 +
 lisp/vc/diff-mode.el                               |     2 +-
 lisp/vc/ediff-mult.el                              |     6 +-
 lisp/vc/ediff-util.el                              |     7 +-
 lisp/vc/vc-git.el                                  |    10 +-
 lisp/vc/vc-hg.el                                   |     5 -
 lisp/vcursor.el                                    |   298 +-
 lisp/view.el                                       |   169 +-
 lisp/wdired.el                                     |   273 +-
 lisp/wid-browse.el                                 |    10 +-
 lisp/wid-edit.el                                   |    25 +-
 lisp/window.el                                     |     5 +-
 lisp/woman.el                                      |   217 +-
 lwlib/Makefile.in                                  |     4 +-
 src/coding.c                                       |     6 +
 src/data.c                                         |     1 +
 src/dispextern.h                                   |     5 +
 src/filelock.c                                     |    26 +-
 src/fns.c                                          |    56 +-
 src/frame.c                                        |    14 +-
 src/frame.h                                        |     7 +
 src/image.c                                        |   109 +-
 src/lisp.h                                         |     3 +-
 src/minibuf.c                                      |   296 +-
 src/nsterm.m                                       |     2 +-
 src/pdumper.c                                      |    14 +-
 src/window.c                                       |     3 +-
 src/xdisp.c                                        |     3 +-
 src/xfns.c                                         |     2 +-
 test/infra/Dockerfile.emba                         |     5 +-
 test/infra/gitlab-ci.yml                           |    37 +-
 test/lisp/autorevert-tests.el                      |     4 +-
 test/lisp/electric-tests.el                        |   124 +-
 test/lisp/epg-config-tests.el                      |    47 +
 test/lisp/filenotify-tests.el                      |   250 +-
 test/lisp/files-tests.el                           |    55 +-
 test/lisp/lpr-tests.el                             |    41 +
 test/lisp/progmodes/cperl-mode-tests.el            |    19 +
 test/lisp/progmodes/executable-tests.el            |    51 +
 test/lisp/progmodes/xref-tests.el                  |     2 +-
 test/src/data-tests.el                             |    23 +
 test/src/filelock-tests.el                         |   183 +
 test/src/process-tests.el                          |     1 -
 test/src/thread-tests.el                           |     6 +-
 347 files changed, 12313 insertions(+), 10705 deletions(-)

diff --git a/ChangeLog.3 b/ChangeLog.3
index ed7704e..8b872a0 100644
--- a/ChangeLog.3
+++ b/ChangeLog.3
@@ -2,6 +2,20 @@
 
        * Version 27.2 released.
 
+2021-03-18 Basil L. Contovounesios <contovob@tcd.ie>
+
+       Fix 'frame-inner-height' in non-GUI builds
+
+       Include tab bar in frame's inner height in non-GUI builds that
+       don't define 'tab-bar-height'.  This is consistent with the
+       inclusion of the menu bar in the calculated height.  It is also
+       consistent with TTY frames of GUI builds, for which
+       'tab-bar-height' is always zero anyway (bug#47234).
+       Fix suggested by Eli Zaretskii <eliz@gnu.org>.
+
+       * lisp/frame.el (frame-inner-height): Don't assume
+       'tab-bar-height' is defined in builds --without-x.
+
 2021-03-18  Eli Zaretskii  <eliz@gnu.org>
 
        * etc/HISTORY: Update for Emacs 27.2.
@@ -76935,7 +76949,7 @@
 
        * lisp/emacs-lisp/lisp-mode.el (lisp-cl-font-lock-keywords-2):
        Highlight the Common Lisp conventional names as described in
-       http://www.cliki.net/Naming+conventions.
+       https://www.cliki.net/Naming+conventions.
        (lisp-el-font-lock-keywords-2): Remove the already commented out
        code for `do-' and `with-' because Emacs Lisp does not have a similar
        convention.
@@ -122126,7 +122140,7 @@
 
        I roughly followed the Bordeaux threads API:
 
-       http://trac.common-lisp.net/bordeaux-threads/wiki/ApiDocumentation
+       https://sionescu.github.io/bordeaux-threads/
 
        ... but not identically.  In particular I chose not to implement
        interrupt-thread or destroy-thread, but instead a thread-signaling
diff --git a/GNUmakefile b/GNUmakefile
index f271638..5155487 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -50,6 +50,8 @@ help:
        @echo "make distclean        -- delete all build and configuration 
files,"
        @echo "                         leave only files included in source 
distribution"
        @echo "make maintainer-clean -- delete almost everything that can be 
regenerated"
+       @echo "make extraclean       -- like maintainer-clean, and also delete"
+       @echo "                         backup and autosave files"
        @echo "make bootstrap        -- delete all compiled files to force a 
new bootstrap"
        @echo "                         from a clean slate, then build in the 
normal way"
        @echo "make uninstall        -- remove files installed by 'make 
install'"
diff --git a/Makefile.in b/Makefile.in
index 2e0390b..059ce1a 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -48,8 +48,6 @@
 #
 # make extraclean
 #      Still more severe - delete backup and autosave files, too.
-#      Also generated files that do not normally change and can be slow
-#      to rebuild (eg leim/ja-dic).
 #
 # make bootstrap
 #      Removes all the compiled files to force a new bootstrap from a
@@ -930,7 +928,7 @@ maintainer-clean: bootstrap-clean 
$(maintainer_clean_dirs:=_maintainer-clean)
 ### Note that we abuse this in some subdirectories (eg leim),
 ### to delete some generated files that are slow to rebuild.
 extraclean_dirs = ${NTDIR} lib-src src leim \
-  admin/charsets admin/grammars admin/unidata lisp lib
+  admin/charsets admin/grammars admin/unidata lisp lib lwlib
 
 $(foreach dir,$(extraclean_dirs),$(eval $(call 
submake_template,$(dir),extraclean)))
 
diff --git a/admin/admin.el b/admin/admin.el
index e370107..ad4208b 100644
--- a/admin/admin.el
+++ b/admin/admin.el
@@ -151,7 +151,7 @@ Root must be the root of an Emacs source tree."
           (display-warning 'admin
                            "NEWS file contains empty sections - remove them?"))
         (goto-char (point-min))
-        (if (re-search-forward "^\\(\\+\\+\\+ *$\\|--- *$\\|Temporary 
note:\\)" nil t)
+        (if (re-search-forward "^\\(\\+\\+\\+? *$\\|---? *$\\|Temporary 
note:\\)" nil t)
             (display-warning 'admin
                              "NEWS file still contains temporary markup.
 Documentation changes might not have been completed!"))))
@@ -545,7 +545,7 @@ Leave point after the table."
        (forward-line 1)
        (while (not done)
          (cond ((re-search-forward "<tr><td.*&bull; \\(<a.*</a>\\)\
-:</td><td>&nbsp;&nbsp;</td><td[^>]*>\\(.*\\)" (line-end-position) t)
+:?</td><td>&nbsp;&nbsp;</td><td[^>]*>\\(.*\\)" (line-end-position) t)
                 (replace-match (format "<tr><td%s>\\1</td>\n<td>\\2"
                                        (if table-workaround
                                            " bgcolor=\"white\"" "")))
diff --git a/admin/charsets/Makefile.in b/admin/charsets/Makefile.in
index 1fe0299..0042484 100644
--- a/admin/charsets/Makefile.in
+++ b/admin/charsets/Makefile.in
@@ -297,17 +297,19 @@ ${charsetdir}/%.map: ${GLIBC_CHARMAPS}/%.gz ${mapconv} 
${compact}
        ${AM_V_GEN}${run_mapconv} $< '/^<.*[    ]\/x/' GLIBC-1 ${compact} > $@
 
 
-.PHONY: clean bootstrap-clean distclean maintainer-clean extraclean
+.PHONY: clean bootstrap-clean distclean maintainer-clean extraclean gen-clean
 
 clean:
 
+## IMO this should also run gen-clean.
 bootstrap-clean: clean
 
 distclean: clean
        rm -f Makefile
 
-maintainer-clean: distclean
-
-## Do not remove these files, even in a bootstrap.  They rarely change.
-extraclean:
+gen-clean:
        rm -f ${CHARSETS} ${SED_SCRIPT} ${TRANS_TABLE} ${srcdir}/charsets.stamp
+
+maintainer-clean: gen-clean distclean
+
+extraclean: maintainer-clean
diff --git a/admin/grammars/Makefile.in b/admin/grammars/Makefile.in
index aa09d9e..35ce554 100644
--- a/admin/grammars/Makefile.in
+++ b/admin/grammars/Makefile.in
@@ -34,7 +34,7 @@ top_builddir = @top_builddir@
 unexport EMACSDATA EMACSDOC EMACSPATH
 
 EMACS = ${top_builddir}/src/emacs
-emacs = EMACSLOADPATH= "${EMACS}" -batch --no-site-file --no-site-lisp
+emacs = EMACSLOADPATH= "${EMACS}" -batch --no-site-file --no-site-lisp --eval 
'(setq load-prefer-newer t)'
 
 make_bovine = ${emacs} -l semantic/bovine/grammar -f bovine-batch-make-parser
 make_wisent = ${emacs} -l semantic/wisent/grammar -f wisent-batch-make-parser
@@ -43,6 +43,9 @@ cedetdir = ${top_srcdir}/lisp/cedet
 bovinedir = ${cedetdir}/semantic/bovine
 wisentdir = ${cedetdir}/semantic/wisent
 
+grammar_bovine = ${bovinedir}/grammar.el
+grammar_wisent = ${wisentdir}/grammar.el
+
 BOVINE = \
        ${bovinedir}/c-by.el \
        ${bovinedir}/make-by.el \
@@ -51,7 +54,7 @@ BOVINE = \
 ## FIXME Should include this one too:
 ##     ${cedetdir}/semantic/grammar-wy.el
 ## but semantic/grammar.el (which is what we use to generate grammar-wy.el)
-## requires it!
+## requires it!  https://debbugs.gnu.org/16008
 WISENT = \
        ${wisentdir}/javat-wy.el \
        ${wisentdir}/js-wy.el \
@@ -69,46 +72,46 @@ bovine: ${BOVINE}
 wisent: ${WISENT}
 
 ## c-by.el, make-by.el.
-${bovinedir}/%-by.el: ${srcdir}/%.by
+${bovinedir}/%-by.el: ${srcdir}/%.by ${grammar_bovine}
        $(AM_V_GEN)[ ! -f "$@" ] || chmod +w "$@"
        $(AM_V_at)${make_bovine} -o "$@" $<
 
-${bovinedir}/scm-by.el: ${srcdir}/scheme.by
+${bovinedir}/scm-by.el: ${srcdir}/scheme.by ${grammar_bovine}
        $(AM_V_GEN)[ ! -f "$@" ] || chmod +w "$@"
        $(AM_V_at)${make_bovine} -o "$@" $<
 
 ## grammar-wy.el
-${cedetdir}/semantic/%-wy.el: ${srcdir}/%.wy
+${cedetdir}/semantic/%-wy.el: ${srcdir}/%.wy ${grammar_wisent}
        $(AM_V_GEN)[ ! -f "$@" ] || chmod +w "$@"
        $(AM_V_at)${make_wisent} -o "$@" $<
 
 ## js-wy.el, python-wy.el
-${wisentdir}/%-wy.el: ${srcdir}/%.wy
+${wisentdir}/%-wy.el: ${srcdir}/%.wy ${grammar_wisent}
        $(AM_V_GEN)[ ! -f "$@" ] || chmod +w "$@"
        $(AM_V_at)${make_wisent} -o "$@" $<
 
-${wisentdir}/javat-wy.el: ${srcdir}/java-tags.wy
+${wisentdir}/javat-wy.el: ${srcdir}/java-tags.wy ${grammar_wisent}
        $(AM_V_GEN)[ ! -f "$@" ] || chmod +w "$@"
        $(AM_V_at)${make_wisent} -o "$@" $<
 
-${cedetdir}/srecode/srt-wy.el: ${srcdir}/srecode-template.wy
+${cedetdir}/srecode/srt-wy.el: ${srcdir}/srecode-template.wy ${grammar_wisent}
        $(AM_V_GEN)[ ! -f "$@" ] || chmod +w "$@"
        $(AM_V_at)${make_wisent} -o "$@" $<
 
-
-.PHONY: distclean bootstrap-clean maintainer-clean extraclean
+.PHONY: distclean bootstrap-clean maintainer-clean extraclean gen-clean
 
 distclean:
        rm -f Makefile
 
-## Perhaps this should do what extraclean (qv) does.
+## IMO this should run gen-clean.
 bootstrap-clean:
 
-maintainer-clean: distclean
-
-## We do not normally delete the generated files, even in bootstrap.
-## Creating them does not take long, so we could easily change this.
-extraclean:
+gen-clean:
        rm -f ${ALL}
 
+maintainer-clean: gen-clean distclean
+
+extraclean: maintainer-clean
+
+
 # Makefile.in ends here
diff --git a/admin/make-tarball.txt b/admin/make-tarball.txt
index 9caf22d..c207895 100644
--- a/admin/make-tarball.txt
+++ b/admin/make-tarball.txt
@@ -91,6 +91,12 @@ General steps (for each step, check for possible errors):
     versioned ChangeLog.N and commit that along with etc/HISTORY.
     Then you can tag that commit as the release.
 
+    Alternatively, you can commit and tag with the RC tag right away,
+    and delay the final tagging until you actually decide to make a
+    release and announce it.  The "git tag" command can tag a specific
+    commit if you give it the SHA1 of that commit, even if additional
+    commits have been pushed in the meantime.
+
     Name the tar file as emacs-XX.Y-rc1.tar.  If all goes well in the
     following week, you can simply rename the file and use it for the
     actual release.  If you need another release candidate, remember
@@ -104,11 +110,11 @@ General steps (for each step, check for possible errors):
     Never replace an existing tarfile!  If you need to fix something,
     always upload it with a different name.
 
-4.   autoreconf -i -I m4 --force
-     make bootstrap
+4.    autoreconf -i -I m4 --force
+      make bootstrap
 
-     make -C etc/refcards
-     make -C etc/refcards clean
+      make -C etc/refcards
+      make -C etc/refcards clean
 
     If some of the etc/refcards, especially the non-English ones, fail
     to build, you probably need to install some TeX/LaTeX packages, in
@@ -122,13 +128,18 @@ General steps (for each step, check for possible errors):
 5.  Copy lisp/loaddefs.el to lisp/ldefs-boot.el.
 
     Commit ChangeLog.N, etc/AUTHORS, lisp/ldefs-boot.el, and the
-    files changed by M-x set-version.
+    files changed by M-x set-version.  The easiest way of doing that
+    is "C-x v d ROOT-DIR RET", then go to the first modified file,
+    press 'M' to mark all modified files, and finally 'v' to commit
+    them.  Make sure the commit log message mentions all the changes
+    in all modified files, as by default 'v' doesn't necessarily do
+    so.
 
     If someone else made a commit between step 1 and now,
     you need to repeat from step 4 onwards.  (You can commit the files
     from step 2 and 3 earlier to reduce the chance of this.)
 
-6.  ./make-dist --snapshot --no-compress
+6.   ./make-dist --snapshot --no-compress
 
     Check the contents of the new tar with admin/diff-tar-files
     against the previous release (if this is the first pretest) or the
@@ -136,6 +147,14 @@ General steps (for each step, check for possible errors):
     yourself, find it at <https://alpha.gnu.org/gnu/emacs/pretest>.
     Releases are of course at <https://ftp.gnu.org/pub/gnu/emacs/>.
 
+     ./admin/diff-tar-files emacs-OLD.tar.gz emacs-NEW.tar.gz
+
+    Alternatively:
+
+     tar tJf emacs-OLD.tar.xz | sed -e 's,^[^/]*,,' | sort > old_tmp
+     tar tJf emacs-NEW.tar.xz | sed -e 's,^[^/]*,,' | sort > new_tmp
+     diff -u old_tmp new_tmp
+
     If this is the first pretest of a major release, just comparing
     with the previous release may overlook many new files.  You can try
     something like 'find . | sort' in a clean repository, and compare the
@@ -143,6 +162,7 @@ General steps (for each step, check for possible errors):
 
 7.   tar -xf emacs-NEW.tar; cd emacs-NEW
      ./configure --prefix=/tmp/emacs && make check && make install
+
     Use 'script' or M-x compile to save the compilation log in
     compile-NEW.log and compare it against an old one.  The easiest way
     to do that is to visit the old log in Emacs, change the version
@@ -150,8 +170,23 @@ General steps (for each step, check for possible errors):
     M-x ediff.  Especially check that Info files aren't built, and that
     no autotools (autoconf etc) run.
 
-8.  cd EMACS_ROOT_DIR && git tag -a TAG && git push origin tag TAG
-    TAG is emacs-XX.Y.ZZ for a pretest, emacs-XX.Y for a release.
+8.  You can now tag the release/pretest and push it together with the
+    last commit:
+
+     cd EMACS_ROOT_DIR && git tag -a TAG -m "Emacs TAG"
+     git push
+     git push --tags
+
+    Here TAG is emacs-XX.Y.ZZ for a pretest, emacs-XX.Y for a release.
+    For a release, if you are producing a release candidate first, use
+    emacs-XX.Y-rcN (N = 1, 2, ...) when you tar the RC, and add the
+    actual release tag later, when the official release tarball is
+    uploaded to ftp.gnu.org.  When adding a tag later, it is safer to
+    use the SHA1 of the last commit which went into the release
+    tarball, in case there were some intervening commits since then:
+
+     git tag -a TAG -m "Emacs TAG" SHA1
+     git push --tags
 
 9. Decide what compression schemes to offer.
     For a release, at least gz and xz:
@@ -215,8 +250,12 @@ General steps (for each step, check for possible errors):
     because replies that invariably are not announcements also get
     sent out as if they were.)
 
-12. After a release, update the Emacs pages as below.
+12. After a release, update the Emacs pages as described below.
 
+13. Bump the Emacs version on the release branch.
+    If the released version was XX.Y, use 'set-version' from
+    admin/admin.el to bump the version on the release branch to
+    XX.Y.50.  Commit the changes.
 
 UPDATING THE EMACS WEB PAGES AFTER A RELEASE
 
@@ -236,5 +275,14 @@ page for about a month, then comment it again.
 Regenerate the various manuals in manual/.
 The scripts admin/make-manuals and admin/upload-manuals summarize the process.
 
+If you have Texinfo installed locally, make-manuals might fail if it
+cannot find epsf.tex.  In that case define in the environment
+
+  TEXINPUTS=:/path/to/texinfo-tree/doc
+
+where /path/to/texinfo-tree is the absolute file name of the top-level
+directory where you have the Texinfo source tree.  Then re-run
+make-manuals.
+
 Browsing <https://web.cvs.savannah.gnu.org/viewvc/?root=emacs> is one
 way to check for any files that still need updating.
diff --git a/admin/notes/emba b/admin/notes/emba
index adebcef..36b126e 100644
--- a/admin/notes/emba
+++ b/admin/notes/emba
@@ -36,6 +36,21 @@ of the Emacs git repository to perform a bootstrap and test 
of Emacs.
 This could happen for several jobs with changed configuration, compile
 and test parameters.
 
+There are different types of jobs: 'prep-image-base' is responsible to
+prepare the environment for the following jobs.  'build-image-*' jobs
+are responsible to compile Emacs in different configuration.  The
+corresponding 'test-*' jobs run the ert tests.
+
+A special job is 'test-all-inotify', which runs 'make check-expensive'.
+While most of the jobs run as soon as a respective file has been
+committed into the Emacs git repository, this test job runs scheduled,
+every 8 hours.
+
+The log files for every test job are kept on the server for a week.
+They can be downloaded from the server, visiting the URL
+<https://emba.gnu.org/emacs/emacs/-/pipelines>, and selecting the job
+in question.
+
 * Emba configuration
 
 The emba configuration files are hosted on
diff --git a/admin/unidata/Makefile.in b/admin/unidata/Makefile.in
index 183569f..b7a927d 100644
--- a/admin/unidata/Makefile.in
+++ b/admin/unidata/Makefile.in
@@ -85,26 +85,26 @@ ${unidir}/charscript.el: ${srcdir}/Blocks.txt ${blocks}
        $(AM_V_GEN)$(AWK) -f ${blocks} < $< > $@
 
 
-.PHONY: clean bootstrap-clean distclean maintainer-clean extraclean
+.PHONY: clean bootstrap-clean distclean maintainer-clean extraclean gen-clean
 
 clean:
        rm -f ${srcdir}/*.elc unidata.txt
 
+## IMO this should also run gen-clean.
 bootstrap-clean: clean
 
 distclean: clean
        rm -f Makefile
 
-maintainer-clean: distclean
-
-## Do not remove these files, even in a bootstrap, because they rarely
-## change and it slows down bootstrap (a tiny bit).
-## Cf leim/ja-dic (which is much slower).
-
 ## macuvs.h is a generated file, but it's also checked in because
 ## macOS builds would need to do a headless bootstrap without it,
 ## which is currently awkward.  To avoid changing checked-in files
 ## from a make target, we don't delete it here.
-extraclean: distclean
+gen-clean:
        rm -f ${unidir}/charscript.el*
        rm -f ${unifiles} ${unidir}/charprop.el
+## ref: https://lists.gnu.org/r/emacs-devel/2013-11/msg01029.html
+
+maintainer-clean: gen-clean distclean
+
+extraclean: maintainer-clean
diff --git a/doc/emacs/emacs.texi b/doc/emacs/emacs.texi
index 4054b09..925c701 100644
--- a/doc/emacs/emacs.texi
+++ b/doc/emacs/emacs.texi
@@ -861,6 +861,7 @@ Projects
 * Project File Commands::   Commands for handling project files.
 * Project Buffer Commands:: Commands for handling project buffers.
 * Switching Projects::      Switching between projects.
+* Managing Projects::       Managing the project list file.
 
 Change Logs
 
diff --git a/doc/emacs/maintaining.texi b/doc/emacs/maintaining.texi
index 2750418..dfe4eb0 100644
--- a/doc/emacs/maintaining.texi
+++ b/doc/emacs/maintaining.texi
@@ -1664,6 +1664,7 @@ the project back-end.  For example, the VC back-end 
doesn't consider
 * Project File Commands::   Commands for handling project files.
 * Project Buffer Commands:: Commands for handling project buffers.
 * Switching Projects::      Switching between projects.
+* Managing Projects::       Managing the project list file.
 @end menu
 
 @node Project File Commands
@@ -1843,6 +1844,21 @@ in the menu, and which key invokes each command.
 records the list of known projects.  It defaults to the file
 @file{projects} in @code{user-emacs-directory} (@pxref{Find Init}).
 
+@node Managing Projects
+@subsection Managing the Project List File
+
+@table @kbd
+@item M-x project-remove-known-project
+Remove a known project from the @code{project-list-file}.
+@end table
+
+@findex project-remove-known-project
+  Normally Emacs automatically adds and removes projects to and from the
+@code{project-list-file}, but sometimes you may want to manually edit
+the available projects.  @kbd{M-x project-remove-known-project}
+prompts you to choose one of the available projects, and then removes
+it from the file.
+
 @node Change Log
 @section Change Logs
 
diff --git a/doc/emacs/mini.texi b/doc/emacs/mini.texi
index 9c1b975..d0865c5 100644
--- a/doc/emacs/mini.texi
+++ b/doc/emacs/mini.texi
@@ -82,7 +82,9 @@ after a recursive minibuffer has been opened in the current 
command
 (@pxref{Recursive Mini,,, elisp}).  This option is mainly to retain
 (approximately) the behavior prior to Emacs 28.1.  Note that the
 effect of the command, when you finally finish using the minibuffer,
-always takes place in the frame where you first opened it.
+always takes place in the frame where you first opened it.  The sole
+exception is that when that frame no longer exists, the action takes
+place in the currently selected frame.
 
 @node Minibuffer File
 @section Minibuffers for File Names
diff --git a/doc/lispintro/emacs-lisp-intro.texi 
b/doc/lispintro/emacs-lisp-intro.texi
index 5b15a45..fade409 100644
--- a/doc/lispintro/emacs-lisp-intro.texi
+++ b/doc/lispintro/emacs-lisp-intro.texi
@@ -1364,19 +1364,6 @@ C-e}:
 (this is an unquoted list)
 @end smallexample
 
-@ignore
-@noindent
-What you see depends on which version of Emacs you are running.  GNU
-Emacs version 22 provides more information than version 20 and before.
-First, the more recent result of generating an error; then the
-earlier, version 20 result.
-
-@need 1250
-@noindent
-In GNU Emacs version 22, a @file{*Backtrace*} window will open up and
-you will see the following in it:
-@end ignore
-
 A @file{*Backtrace*} window will open up and you should see the
 following in it:
 
@@ -1838,19 +1825,6 @@ Debugger entered--Lisp error: (void-function fill-column)
 (Remember, to quit the debugger and make the debugger window go away,
 type @kbd{q} in the @file{*Backtrace*} buffer.)
 
-@ignore
-@need 800
-In GNU Emacs 20 and before, you will produce an error message that says:
-
-@smallexample
-Symbol's function definition is void:@: fill-column
-@end smallexample
-
-@noindent
-(The message will go away as soon as you move the cursor or type
-another key.)
-@end ignore
-
 @node Void Variable
 @subsection Error Message for a Symbol Without a Value
 @cindex Symbol without value error
@@ -1907,18 +1881,6 @@ Since @code{+} does not have a value bound to it, just 
the function
 definition, the error message reported that the symbol's value as a
 variable was void.
 
-@ignore
-@need 800
-In GNU Emacs version 20 and before, your error message will say:
-
-@example
-Symbol's value as variable is void:@: +
-@end example
-
-@noindent
-The meaning is the same as in GNU Emacs 22.
-@end ignore
-
 @node Arguments
 @section Arguments
 @cindex Arguments
@@ -2197,19 +2159,6 @@ addition had been passed the correct type of object, the 
value passed
 would have been a number, such as 37, rather than a symbol like
 @code{hello}.  But then you would not have got the error message.
 
-@ignore
-@need 1250
-In GNU Emacs version 20 and before, the echo area displays an error
-message that says:
-
-@smallexample
-Wrong type argument:@: number-or-marker-p, hello
-@end smallexample
-
-This says, in different words, the same as the top line of the
-@file{*Backtrace*} buffer.
-@end ignore
-
 @node message
 @subsection The @code{message} Function
 @findex message
@@ -6663,9 +6612,9 @@ original text of the function:
 @end group
 @end smallexample
 
-(In recent versions of GNU Emacs, the @code{what-line} function has
+(In modern versions of GNU Emacs, the @code{what-line} function has
 been expanded to tell you your line number in a narrowed buffer as
-well as your line number in a widened buffer.  The recent version is
+well as your line number in a widened buffer.  The modern version is
 more complex than the version shown here.  If you feel adventurous,
 you might want to look at it after figuring out how this version
 works.  You will probably need to use @kbd{C-h f}
@@ -10392,9 +10341,8 @@ echo area: 
@code{^Jgazelle^J^Jgiraffe^J^Jlion^J^Jtiger^Jnil}, in which
 each @samp{^J} stands for a newline.)
 
 @need 1500
-In a recent instance of GNU Emacs, you can evaluate these expressions
-directly in the Info buffer, and the echo area will grow to show the
-results.
+You can evaluate these expressions directly in the Info buffer, and
+the echo area will grow to show the results.
 
 @smallexample
 @group
@@ -18104,8 +18052,7 @@ argument of 4:
 @end smallexample
 
 @noindent
-In a recent GNU Emacs, you will create and enter a @file{*Backtrace*}
-buffer that says:
+This will create and enter a @file{*Backtrace*} buffer that says:
 
 @noindent
 @smallexample
@@ -18139,25 +18086,12 @@ In practice, for a bug as simple as this, the Lisp 
error line will
 tell you what you need to know to correct the definition.  The
 function @code{1=} is void.
 
-@ignore
-@need 800
-In GNU Emacs 20 and before, you will see:
-
-@smallexample
-Symbol's function definition is void:@: 1=
-@end smallexample
-
-@noindent
-which has the same meaning as the @file{*Backtrace*} buffer line in
-version 21.
-@end ignore
-
 However, suppose you are not quite certain what is going on?
 You can read the complete backtrace.
 
-In this case, you need to run a recent GNU Emacs, which automatically
-starts the debugger that puts you in the @file{*Backtrace*} buffer; or
-else, you need to start the debugger manually as described below.
+Emacs automatically starts the debugger that puts you in the
+@file{*Backtrace*} buffer.  You can also start the debugger manually
+as described below.
 
 Read the @file{*Backtrace*} buffer from the bottom up; it tells you
 what Emacs did that led to the error.  Emacs made an interactive call
@@ -18197,14 +18131,8 @@ then run your test again.
 @section @code{debug-on-entry}
 @findex debug-on-entry
 
-A recent GNU Emacs starts the debugger automatically when your
-function has an error.
-
-@ignore
-GNU Emacs version 20 and before did not; it simply
-presented you with an error message.  You had to start the debugger
-manually.
-@end ignore
+Emacs starts the debugger automatically when your function has an
+error.
 
 Incidentally, you can start the debugger manually for all versions of
 Emacs; the advantage is that the debugger runs even if you do not have
@@ -20079,8 +20007,8 @@ the tic marks themselves and their spacing:
 @code{defvar}.  The @code{boundp} predicate checks whether it has
 already been set; @code{boundp} returns @code{nil} if it has not.  If
 @code{graph-blank} were unbound and we did not use this conditional
-construction, in a recent GNU Emacs, we would enter the debugger and
-see an error message saying @samp{@w{Debugger entered--Lisp error:}
+construction, we would enter the debugger and see an error message
+saying @samp{@w{Debugger entered--Lisp error:}
 @w{(void-variable graph-blank)}}.)
 
 @need 1200
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index 2e1b4a6..68d7e82 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -5751,6 +5751,28 @@ Cropping is performed after scaling but before rotation.
 @cindex SVG images
 
 SVG (Scalable Vector Graphics) is an XML format for specifying images.
+SVG images support the following additional image descriptor
+properties:
+
+@table @code
+@item :foreground @var{foreground}
+@var{foreground}, if non-@code{nil}, should be a string specifying a
+color, which is used as the image's foreground color.  If the value is
+@code{nil}, it defaults to the faces's foreground color.
+
+@item :background @var{background}
+@var{background}, if non-@code{nil}, should be a string specifying a
+color, which is used as the image's background color if the image
+supports transparency.  If the value is @code{nil}, it defaults to the
+faces's background color.
+
+@item :css @var{css}
+@var{css}, if non-@code{nil}, should be a string specifying the CSS to
+override the default CSS used when generating the image.
+@end table
+
+@subsubheading SVG library
+
 If your Emacs build has SVG support, you can create and manipulate
 these images with the following functions from the @file{svg.el}
 library.
diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi
index 2828b50..a8b921e 100644
--- a/doc/lispref/files.texi
+++ b/doc/lispref/files.texi
@@ -764,6 +764,8 @@ This function unlocks the file being visited in the current 
buffer,
 if the buffer is modified.  If the buffer is not modified, then
 the file should not be locked, so this function does nothing.  It also
 does nothing if the current buffer is not visiting a file, or is not locked.
+This function handles file system errors by calling @code{display-warning}
+and otherwise ignores the error.
 @end defun
 
 @defopt create-lockfiles
diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi
index 5cae939..b4d7bc7 100644
--- a/doc/lispref/strings.texi
+++ b/doc/lispref/strings.texi
@@ -390,6 +390,22 @@ whitespace to a single space character, as well as 
removing all
 whitespace from the start and the end of @var{string}.
 @end defun
 
+@defun string-trim-left string &optional regexp
+Remove the leading text that matches @var{regexp} from @var{string}.
+@var{regexp} defaults to @samp{[ \t\n\r]+}.
+@end defun
+
+@defun string-trim-right string &optional regexp
+Remove the trailing text that matches @var{regexp} from @var{string}.
+@var{regexp} defaults to @samp{[ \t\n\r]+}.
+@end defun
+
+@defun string-trim string &optional trim-left trim-right
+Remove the leading text that matches @var{trim-left} and trailing text
+that matches @var{trim-right} from from @var{string}.  Both regexps
+default to @samp{[ \t\n\r]+}.
+@end defun
+
 @defun string-fill string length
 Attempt to Word-wrap @var{string} so that no lines are longer than
 @var{length}.  Filling is done on whitespace boundaries only.  If
diff --git a/doc/misc/Makefile.in b/doc/misc/Makefile.in
index 63d4bf0..7982c0d 100644
--- a/doc/misc/Makefile.in
+++ b/doc/misc/Makefile.in
@@ -22,7 +22,7 @@ SHELL = @SHELL@
 # Where to find the source code.  $(srcdir) will be the doc/misc subdirectory
 # of the source tree.  This is set by configure's '--srcdir' option.
 srcdir=@srcdir@
-
+top_srcdir = @top_srcdir@
 top_builddir = @top_builddir@
 
 ## Where the output files go.
@@ -100,10 +100,6 @@ texi_sources = $(addsuffix .texi,${TARGETS})
 texi_notgen = $(filter-out $(notdir ${TEXI_FROM_ORG}),${texi_sources})
 texi_and_org = $(notdir ${ORG_SRC}) ${texi_notgen}
 SOURCES = $(sort ${texi_and_org})
-.PHONY: echo-sources
-## Used by the top-level Makefile.
-echo-sources:
-       @echo ${SOURCES}
 
 DVI_TARGETS  = $(TARGETS:=.dvi)
 HTML_TARGETS = $(TARGETS:=.html)
@@ -122,7 +118,7 @@ ENVADD = 
$(AM_V_GEN)TEXINPUTS="$(srcdir):$(emacsdir):$(TEXINPUTS)" \
 gfdl = ${srcdir}/doclicense.texi
 style = ${emacsdir}/docstyle.texi
 
-.PHONY: info dvi html pdf ps echo-info $(INFO_TARGETS)
+.PHONY: info dvi html pdf ps echo-info echo-sources $(INFO_TARGETS)
 ## Prevent implicit rule triggering for foo.info.
 .SUFFIXES:
 
@@ -138,6 +134,9 @@ echo-info:
        @echo "$(INFO_INSTALL) " | \
          sed -e 's|[^ ]*/||g' -e 's/\.info//g' -e "s/  */.info /g"
 
+echo-sources:
+       @echo ${SOURCES}
+
 dvi: $(DVI_TARGETS)
 
 html: $(HTML_TARGETS)
@@ -235,14 +234,14 @@ ${buildinfodir}/tramp.info tramp.html: 
${srcdir}/trampver.texi
 
 abs_top_builddir = @abs_top_builddir@
 EMACS = ${abs_top_builddir}/src/emacs
-emacs = "${EMACS}" -batch --no-site-file --no-site-lisp
+emacs = "${EMACS}" -batch --no-site-file --no-site-lisp --eval '(setq 
load-prefer-newer t)'
 
 # Generated .texi files go in srcdir so they can be included in the
 # release tarfile along with the others.
 # Work in srcdir (and use abs_top_builddir) so that +setupfile and
 # things like org-setup's "version" macro work.  Sigh.
 define org_template
- $(1:.org=.texi): $(1)
+ $(1:.org=.texi): $(1) ${top_srcdir}/lisp/org/ox-texinfo.el
        $${AM_V_GEN}cd "$${srcdir}" && $${emacs} -l ox-texinfo \
          -f org-texinfo-export-to-texinfo-batch $$(notdir $$<) $$(notdir $$@)
 endef
diff --git a/doc/misc/gnus-faq.texi b/doc/misc/gnus-faq.texi
index 35a2526..d3db940 100644
--- a/doc/misc/gnus-faq.texi
+++ b/doc/misc/gnus-faq.texi
@@ -1935,13 +1935,13 @@ when you're online.
 
 Let's talk about Unix systems first: For the news part,
 the easiest solution is a small nntp server like
-@uref{http://www.leafnode.org/, Leafnode} or
+@uref{https://www.leafnode.org/, Leafnode} or
 @uref{http://patrik.iki.fi/sn/, sn},
 of course you can also install a full featured news
 server like
 @uref{https://www.isc.org/othersoftware/, inn}.
 Then you want to fetch your Mail, popular choices
-are @uref{http://www.fetchmail.info/, fetchmail}
+are @uref{https://www.fetchmail.info/, fetchmail}
 and @uref{http://pyropus.ca/software/getmail/, getmail}.
 You should tell those to write the mail to your disk and
 Gnus to read it from there. Last but not least the mail
diff --git a/doc/misc/nxml-mode.texi b/doc/misc/nxml-mode.texi
index 3671ac8..4ca223d 100644
--- a/doc/misc/nxml-mode.texi
+++ b/doc/misc/nxml-mode.texi
@@ -82,7 +82,7 @@ documents.
 To get validation and schema-sensitive editing, you need a RELAX NG Compact
 Syntax (RNC) schema for your document (@pxref{Locating a schema}).  The
 @file{etc/schema} directory includes some schemas for popular document
-types.  See @url{http://relaxng.org/} for more information on RELAX NG@.
+types.  See @url{https://relaxng.org/} for more information on RELAX NG@.
 You can use the @samp{Trang} program from
 @url{http://www.thaiopensource.com/relaxng/trang.html} to
 automatically create RNC schemas.  This program can:
diff --git a/doc/misc/reftex.texi b/doc/misc/reftex.texi
index 599252f..f1074d3 100644
--- a/doc/misc/reftex.texi
+++ b/doc/misc/reftex.texi
@@ -254,73 +254,6 @@ version 20.2.  It has also been bundled and pre-installed 
with XEmacs
 plug-in package which is available from the @value{XEMACSFTP}.  See the
 XEmacs 21.x documentation on package installation for details.
 
-Users of earlier Emacs distributions (including Emacs 19) or people
-craving for new features and bugs can get a copy of the @RefTeX{}
-distribution from the maintainer's web page.  @xref{Imprint}, for more
-information.  The following instructions will guide you through the
-process of installing such a distribution.
-
-@subsection Building and Installing
-
-Note: Currently installation is supported for Emacs only.  XEmacs users
-might want to refer to the @RefTeX{} package available through the
-package system of XEmacs.
-
-@subsubheading Installation with make
-
-In order to install RefTeX, unpack the distribution and edit the header
-of the Makefile.  Basically, you need to change the path specifications
-for Emacs Lisp files and info files.  Also, enter the name of your Emacs
-executable (usually either @samp{emacs} or @samp{xemacs}).
-
-Then, type
-
-@example
-make
-make install
-@end example
-
-to compile and install the code and documentation.
-
-Per default @RefTeX{} is installed in its own subdirectory which might
-not be on your load path.  In this case, add it to load path with a
-command like the following, replacing the sample directory with the one
-where @RefTeX{} is installed in your case.
-
-@example
-(add-to-list 'load-path "/path/to/reftex")
-@end example
-
-Put this command into your init file before other @RefTeX{}-related
-settings.
-
-@subsubheading Installation by Hand
-
-If you want to get your hands dirty, there is also the possibility to
-install by manually copying files.
-
-@enumerate a
-@item
-Copy the reftex*.el lisp files to a directory on your load path.  Make
-sure that no old copy of @RefTeX{} shadows these files.
-@item
-Byte compile the files.  The sequence of compiling should be:
-reftex-var.el, reftex.el, and then all the others.
-@item
-Copy the info file reftex.info to the info directory.
-@end enumerate
-
-@subsection Loading @RefTeX{}
-
-In order to make the most important functions for entering @RefTeX{}
-mode available add the following line to your init file.
-
-@example
-(require 'reftex)
-@end example
-
-@subsection Entering @RefTeX{} Mode
-
 @findex turn-on-reftex
 @findex reftex-mode
 @vindex LaTeX-mode-hook
@@ -3259,9 +3192,9 @@ with the @kbd{g} key.  To get this behavior, use instead
 
 @AUCTeX{} is without doubt the best major mode for editing @TeX{} and @LaTeX{}
 files with Emacs (@pxref{Top,AUCTeX,,auctex, The AUCTeX User Manual}).
-If @AUCTeX{} is not part of your Emacs distribution, you can get
-it@footnote{XEmacs 21.x users may want to install the corresponding
-XEmacs package.} by FTP from the @value{AUCTEXSITE}.
+You can get it from its home page at @value{AUCTEXSITE}, but since
+it is available from GNU ELPA, you can simply install it from @kbd{M-x
+list-packages}.
 
 @menu
 * AUCTeX-RefTeX Interface::          How both packages work together
@@ -3611,18 +3544,6 @@ after the @samp{@{step+@}}, also when specifying how to 
get
 context.
 
 @item
-@b{Idle timers in XEmacs}@*
-@cindex Idle timer restart
-@vindex reftex-use-itimer-in-xemacs
-In XEmacs, idle timer restart does not work reliably after fast
-keystrokes.  Therefore @RefTeX{} currently uses the post command
-hook to start the timer used for automatic crossref information.  When
-this bug gets fixed, a real idle timer can be requested with
-@lisp
-(setq reftex-use-itimer-in-xemacs t)
-@end lisp
-
-@item
 @b{Viper mode}@*
 @cindex Viper mode
 @cindex Key bindings, problems with Viper mode
diff --git a/doc/misc/texinfo.tex b/doc/misc/texinfo.tex
index dac7ae3..a91181b 100644
--- a/doc/misc/texinfo.tex
+++ b/doc/misc/texinfo.tex
@@ -1181,7 +1181,7 @@ where each line of input produces a line of output.}
 % double any backslashes.  Otherwise, a name like "\node" will be
 % interpreted as a newline (\n), followed by o, d, e.  Not good.
 %
-% See http://www.ntg.nl/pipermail/ntg-pdftex/2004-July/000654.html and
+% See https://mailman.ntg.nl/pipermail/ntg-pdftex/2004-July/000654.html and
 % related messages.  The final outcome is that it is up to the TeX user
 % to double the backslashes and otherwise make the string valid, so
 % that's what we do.  pdftex 1.30.0 (ca.2005) introduced a primitive to
@@ -3539,7 +3539,7 @@ $$%
 % We use the free feym* fonts from the eurosym package by Henrik
 % Theiling, which support regular, slanted, bold and bold slanted (and
 % "outlined" (blackboard board, sort of) versions, which we don't need).
-% It is available from http://www.ctan.org/tex-archive/fonts/eurosym.
+% It is available from https://www.ctan.org/tex-archive/fonts/eurosym.
 %
 % Although only regular is the truly official Euro symbol, we ignore
 % that.  The Euro is designed to be slightly taller than the regular
diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi
index 7ae5622..5ea0275 100644
--- a/doc/misc/tramp.texi
+++ b/doc/misc/tramp.texi
@@ -2305,6 +2305,8 @@ which support this.
 This approach has also the advantage, that settings in
 @code{tramp-sh-extra-args} will be applied.  For @command{zsh}, the
 trouble with the shell prompt due to set zle options will be avoided.
+For @command{bash}, loading @file{~/.editrc} or @file{~/.inputrc} is
+suppressed.
 
 Similar problems can happen with the local shell Tramp uses to create
 a process.  By default, it uses the command @command{/bin/sh} for
@@ -5077,6 +5079,24 @@ In case you have installed it from its Git repository, 
@ref{Recompilation}.
 
 
 @item
+I get an error @samp{tramp-file-name-handler: Invalid function:
+tramp-compat-with-mutex}
+
+Likely, you have a running Emacs session with loaded @value{tramp},
+and you try to upgrade it to another version from GNU ELPA.  Since
+@value{tramp} is not forward compatible, you must unload / reload it.
+Try the following steps:
+
+@example
+@kbd{M-x tramp-unload-tramp @key{RET}}
+@kbd{M-x load-library @key{RET} tramp @key{RET}}
+@end example
+
+If this doesn't work, you must restart Emacs with proper
+@code{load-path} for the new @value{tramp} version.
+
+
+@item
 I get an error @samp{Remote file error: Forbidden reentrant call of Tramp}
 
 @vindex remote-file-error
diff --git a/doc/misc/woman.texi b/doc/misc/woman.texi
index 4470afc..33b3a33 100644
--- a/doc/misc/woman.texi
+++ b/doc/misc/woman.texi
@@ -105,11 +105,9 @@ Mile End Road, London E1 4NS, UK
 @chapter Introduction
 @cindex introduction
 
-This version of WoMan should run with GNU Emacs 20.3 or later on any
-platform.  It has not been tested, and may not run, with any other
-version of Emacs.  It was developed primarily on various versions of
-Microsoft Windows, but has also been tested on MS-DOS, and various
-versions of UNIX and GNU/Linux.
+WoMan was developed primarily on various versions of Microsoft
+Windows, but has also been tested on MS-DOS, and various versions of
+UNIX and GNU/Linux.
 
 WoMan is distributed with GNU Emacs.
 
diff --git a/etc/NEWS b/etc/NEWS
index c602166..1421efc 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -562,7 +562,9 @@ It also supports a negative argument.
 *** 'C-x t G' assigns a group name to the tab.
 'tab-close-group' can close all tabs that belong to the selected group.
 The user option 'tab-bar-new-tab-group' defines the default group of a
-new tab.
+new tab.  After customizing 'tab-bar-tab-post-change-group-functions'
+to 'tab-bar-move-tab-to-group', changing the tab group will also move it
+closer to other tabs in the same group.
 
 ---
 *** New user option 'tab-bar-tab-name-format-function'.
@@ -1054,6 +1056,10 @@ the commands 'customize', 'customize-group', 
'customize-apropos' and
 To customize obsolete user options, use 'customize-option' or
 'customize-saved'.
 
+*** New SVG icons for checkboxes and arrows.
+They will be used automatically instead of the old icons.  If Emacs is
+built without SVG support, the old icons will be used instead.
+
 ** Edebug
 
 *** Obsoletions
@@ -1509,6 +1515,15 @@ This controls whether to use smoothing or not for an 
image.  Values
 include nil (no smoothing), t (do smoothing) or a predicate function
 that's called with the image object and should return nil/t.
 
++++
+*** SVG images now support user stylesheets.
+The ':css' image attribute can be used to override the default CSS
+stylesheet for an image.  The default sets 'font-family' and
+'font-size' to match the current face, so an image with 'height="1em"'
+will match the font size in use where it is embedded.
+
+This feature relies on librsvg 2.48 or above being available.
+
 ** EWW
 
 +++
@@ -1573,6 +1588,11 @@ project's root directory, respectively.
 +++
 *** New user option 'project-list-file'.
 
++++
+*** New command 'project-remove-known-project'.
+This command lets you interactively remove an entry from the list of projects
+in 'project-list-file'.
+
 ** xref
 
 ---
@@ -2300,6 +2320,10 @@ since the latter uses 'M-s' as a prefix key of the 
search prefix map.
 ** 'vc-print-branch-log' shows the change log for BRANCH from its root
 directory instead of the default directory.
 
+---
+** 'project-shell' and 'shell' now use 'pop-to-buffer-same-window'.
+This is to keep the same behavior as Eshell.
+
 
 * Incompatible Lisp Changes in Emacs 28.1
 
@@ -2491,6 +2515,12 @@ back in Emacs 23.1.  The affected functions are: 
'make-obsolete',
 * Lisp Changes in Emacs 28.1
 
 +++
+** 'unlock-buffer' displays warnings instead of signaling.
+Instead of signaling 'file-error' conditions for file system level
+errors, the function now calls 'display-warning' and continues as if
+the error did not occur.
+
++++
 ** New function 'always'.
 This is identical to 'ignore', but returns t instead.
 
diff --git a/etc/NEWS.27 b/etc/NEWS.27
index d969257..55045d1 100644
--- a/etc/NEWS.27
+++ b/etc/NEWS.27
@@ -966,7 +966,6 @@ the entire list as before.  An integer value limits the 
list length
 
 *** 'vc-git-stash' is now bound to 'C' in the stash headers.
 
---
 *** Some stash keybindings are now available in the stash button.
 'vc-git-stash' and 'vc-git-stash-snapshot' can now be run using 'C'
 and 'S' respectively, including when there are no stashes.
diff --git a/etc/images/README b/etc/images/README
index 00aac4f..9bbe796 100644
--- a/etc/images/README
+++ b/etc/images/README
@@ -104,3 +104,30 @@ same conditions.
 
 The *.pbm files were generally converted from *.xpm by running GIMP or
 ImageMagick's 'convert'.
+
+
+* The following icons are from the Adwaita Icon Theme (made by the
+GNOME project).  They are not part of Emacs, but are distributed and
+used by Emacs.  They are licensed under either the GNU LGPL v3 or the
+Creative Commons Attribution-Share Alike 3.0 United States License.
+
+To view a copy of the CC-BY-SA licence, visit
+http://creativecommons.org/licenses/by-sa/3.0/ or send a letter to Creative
+Commons, 171 Second Street, Suite 300, San Francisco, California 94105, USA.
+
+For more information see the adwaita-icon-theme repository at:
+
+    https://gitlab.gnome.org/GNOME/adwaita-icon-theme
+
+Emacs images and their source in the Adwaita/scalable directory:
+
+  checked.svg               ui/checkbox-checked-symbolic.svg
+  unchecked.svg             ui/checkbox-symbolic.svg
+  checkbox-mixed.svg        ui/checkbox-mixed-symbolic.svg
+  radio.svg                 ui/radio-symbolic.svg
+  radio-mixed.svg           ui/radio-mixed-symbolic.svg
+  radio-checked.svg         ui/radio-checked-symbolic.svg
+  down.svg                  ui/pan-down-symbolic.svg
+  left.svg                  ui/pan-start-symbolic.svg
+  right.svg                 ui/pan-end-symbolic.svg
+  up.svg                    ui/pan-up-symbolic.svg
diff --git a/etc/images/checkbox-mixed.svg b/etc/images/checkbox-mixed.svg
new file mode 100644
index 0000000..6e46b80
--- /dev/null
+++ b/etc/images/checkbox-mixed.svg
@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg"; height="1em" viewBox="0 0 16 16">
+  <g>
+    <path d="M3.5 1A2.506 2.506 0 0 0 1 3.5v9C1 13.876 2.124 15 3.5 15h9c1.376 
0 2.5-1.124 2.5-2.5v-9C15 2.124 13.876 1 12.5 1zm0 1h9c.84 0 1.5 .66 1.5 
1.5v9c0 .84-.66 1.5-1.5 1.5h-9c-.84 0-1.5-.66-1.5-1.5v-9C2 2.66 2.66 2 3.5 2z" 
overflow="visible" />
+    <path d="M5 6a2 2 0 1 0 0 4h6a2 2 0 1 0 0 -4z" overflow="visible" />
+  </g>
+</svg>
diff --git a/etc/images/checked.svg b/etc/images/checked.svg
new file mode 100644
index 0000000..4cbdef0
--- /dev/null
+++ b/etc/images/checked.svg
@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg"; height="1em" viewBox="0 0 16 16">
+  <g>
+    <path d="M3.5 1A2.506 2.506 0 0 0 1 3.5v9C1 13.876 2.124 15 3.5 15h9c1.376 
0 2.5-1.124 2.5-2.5v-9C15 2.124 13.876 1 12.5 1zm0 1h9c.84 0 1.5 .66 1.5 
1.5v9c0 .84-.66 1.5-1.5 1.5h-9c-.84 0-1.5-.66-1.5-1.5v-9C2 2.66 2.66 2 3.5 2z" 
overflow="visible" />
+    <path d="M14.5 3l-.5-.5L7.5 9 5 6.5l-2 2L7.5 13l7-7z" overflow="visible" />
+  </g>
+</svg>
diff --git a/etc/images/down.svg b/etc/images/down.svg
new file mode 100644
index 0000000..e276042
--- /dev/null
+++ b/etc/images/down.svg
@@ -0,0 +1,40 @@
+<?xml version='1.0' encoding='UTF-8' standalone='no'?>
+<svg xmlns:cc='http://creativecommons.org/ns#' 
xmlns:dc='http://purl.org/dc/elements/1.1/' 
sodipodi:docname='pan-down-symbolic.svg' 
inkscape:export-filename='/home/sam/source-symbolic.png' 
inkscape:export-xdpi='270' inkscape:export-ydpi='270' height='16' id='svg7384' 
xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape' 
xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' 
xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd' 
style='enable-background:new' xmlns:svg [...]
+  <sodipodi:namedview inkscape:bbox-nodes='true' inkscape:bbox-paths='false' 
bordercolor='#000000' borderlayer='false' borderopacity='0.50196078' 
inkscape:current-layer='layer10' inkscape:cx='-8.85234' inkscape:cy='7.9624984' 
inkscape:document-rotation='0' gridtolerance='10' inkscape:guide-bbox='true' 
guidetolerance='10' id='namedview88' inkscape:measure-end='0,0' 
inkscape:measure-start='0,0' inkscape:object-nodes='true' 
inkscape:object-paths='true' objecttolerance='10' pagecolor='#e2e2e [...]
+    <inkscape:grid color='#000000' dotted='false' empcolor='#0800ff' 
empopacity='0.4627451' empspacing='4' enabled='true' id='grid4866' 
opacity='0.16470588' originx='-152.00586' originy='-952' 
snapvisiblegridlinesonly='true' spacingx='1' spacingy='1' type='xygrid' 
visible='true'/>
+    <inkscape:grid dotted='true' empcolor='#3f3fff' empopacity='0' 
empspacing='4' id='grid3540' originx='-152.00586' originy='-952' spacingx='0.5' 
spacingy='0.5' type='xygrid'/>
+  </sodipodi:namedview>
+  <metadata id='metadata90'>
+    <rdf:RDF>
+      <cc:Work rdf:about=''>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type rdf:resource='http://purl.org/dc/dcmitype/StillImage'/>
+        <dc:title>Gnome Symbolic Icons</dc:title>
+        <cc:license 
rdf:resource='http://creativecommons.org/licenses/by-sa/4.0/'/>
+      </cc:Work>
+      <cc:License rdf:about='http://creativecommons.org/licenses/by-sa/4.0/'>
+        <cc:permits rdf:resource='http://creativecommons.org/ns#Reproduction'/>
+        <cc:permits rdf:resource='http://creativecommons.org/ns#Distribution'/>
+        <cc:requires rdf:resource='http://creativecommons.org/ns#Notice'/>
+        <cc:requires rdf:resource='http://creativecommons.org/ns#Attribution'/>
+        <cc:permits 
rdf:resource='http://creativecommons.org/ns#DerivativeWorks'/>
+        <cc:requires rdf:resource='http://creativecommons.org/ns#ShareAlike'/>
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <title id='title8473'>Gnome Symbolic Icons</title>
+  <defs id='defs7386'/>
+  <g inkscape:groupmode='layer' id='layer10' inkscape:label='ui' 
transform='translate(-152.00586,-952)'>
+    <path inkscape:connector-curvature='0' d='m 166,957 -5.99414,5.99999 L 
154,957 Z' id='path6424' sodipodi:nodetypes='cccc' 
style='fill:#2e3436;fill-opacity:1;stroke:none'/>
+  </g>
+  <g inkscape:groupmode='layer' id='layer1' inkscape:label='status' 
transform='translate(-152.00586,-888)'/>
+  <g inkscape:groupmode='layer' id='layer11' inkscape:label='legacy' 
transform='translate(-152.00586,-952)'/>
+  <g inkscape:groupmode='layer' id='layer7' inkscape:label='places' 
transform='translate(-152.00586,-888)'/>
+  <g inkscape:groupmode='layer' id='layer6' inkscape:label='mimetypes' 
transform='translate(-152.00586,-888)'/>
+  <g inkscape:groupmode='layer' id='layer5' inkscape:label='emotes' 
transform='translate(-152.00586,-888)'/>
+  <g inkscape:groupmode='layer' id='layer9' inkscape:label='emblems' 
transform='translate(-152.00586,-888)'/>
+  <g inkscape:groupmode='layer' id='layer2' inkscape:label='devices' 
transform='translate(-152.00586,-888)'/>
+  <g inkscape:groupmode='layer' id='layer8' inkscape:label='categories' 
transform='translate(-152.00586,-888)'/>
+  <g inkscape:groupmode='layer' id='layer3' inkscape:label='apps' 
transform='translate(-152.00586,-888)'/>
+  <g inkscape:groupmode='layer' id='layer4' inkscape:label='actions' 
transform='translate(-152.00586,-888)'/>
+</svg>
diff --git a/etc/images/left.svg b/etc/images/left.svg
new file mode 100644
index 0000000..d6429bc
--- /dev/null
+++ b/etc/images/left.svg
@@ -0,0 +1,40 @@
+<?xml version='1.0' encoding='UTF-8' standalone='no'?>
+<svg xmlns:cc='http://creativecommons.org/ns#' 
xmlns:dc='http://purl.org/dc/elements/1.1/' 
sodipodi:docname='pan-start-symbolic.svg' 
inkscape:export-filename='/home/sam/source-symbolic.png' 
inkscape:export-xdpi='270' inkscape:export-ydpi='270' height='16' id='svg7384' 
xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape' 
xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' 
xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd' 
style='enable-background:new' xmlns:sv [...]
+  <sodipodi:namedview inkscape:bbox-nodes='true' inkscape:bbox-paths='false' 
bordercolor='#000000' borderlayer='false' borderopacity='0.50196078' 
inkscape:current-layer='layer10' inkscape:cx='51.147672' inkscape:cy='7.96251' 
inkscape:document-rotation='0' gridtolerance='10' inkscape:guide-bbox='true' 
guidetolerance='10' id='namedview88' inkscape:measure-end='0,0' 
inkscape:measure-start='0,0' inkscape:object-nodes='true' 
inkscape:object-paths='true' objecttolerance='10' pagecolor='#e2e2e2 [...]
+    <inkscape:grid color='#000000' dotted='false' empcolor='#0800ff' 
empopacity='0.4627451' empspacing='4' enabled='true' id='grid4866' 
opacity='0.16470588' originx='-92.005848' originy='-951.99999' 
snapvisiblegridlinesonly='true' spacingx='1' spacingy='1' type='xygrid' 
visible='true'/>
+    <inkscape:grid dotted='true' empcolor='#3f3fff' empopacity='0' 
empspacing='4' id='grid3540' originx='-92.005848' originy='-951.99999' 
spacingx='0.5' spacingy='0.5' type='xygrid'/>
+  </sodipodi:namedview>
+  <metadata id='metadata90'>
+    <rdf:RDF>
+      <cc:Work rdf:about=''>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type rdf:resource='http://purl.org/dc/dcmitype/StillImage'/>
+        <dc:title>Gnome Symbolic Icons</dc:title>
+        <cc:license 
rdf:resource='http://creativecommons.org/licenses/by-sa/4.0/'/>
+      </cc:Work>
+      <cc:License rdf:about='http://creativecommons.org/licenses/by-sa/4.0/'>
+        <cc:permits rdf:resource='http://creativecommons.org/ns#Reproduction'/>
+        <cc:permits rdf:resource='http://creativecommons.org/ns#Distribution'/>
+        <cc:requires rdf:resource='http://creativecommons.org/ns#Notice'/>
+        <cc:requires rdf:resource='http://creativecommons.org/ns#Attribution'/>
+        <cc:permits 
rdf:resource='http://creativecommons.org/ns#DerivativeWorks'/>
+        <cc:requires rdf:resource='http://creativecommons.org/ns#ShareAlike'/>
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <title id='title8473'>Gnome Symbolic Icons</title>
+  <defs id='defs7386'/>
+  <g inkscape:groupmode='layer' id='layer10' inkscape:label='ui' 
transform='translate(-92.005848,-951.99999)'>
+    <path inkscape:connector-curvature='0' d='M 103,966 97.00585,959.99999 
103,954 Z' id='path6400' sodipodi:nodetypes='cccc' 
style='fill:#2e3436;fill-opacity:1;stroke:none'/>
+  </g>
+  <g inkscape:groupmode='layer' id='layer1' inkscape:label='status' 
transform='translate(-92.005848,-887.99999)'/>
+  <g inkscape:groupmode='layer' id='layer11' inkscape:label='legacy' 
transform='translate(-92.005848,-951.99999)'/>
+  <g inkscape:groupmode='layer' id='layer7' inkscape:label='places' 
transform='translate(-92.005848,-887.99999)'/>
+  <g inkscape:groupmode='layer' id='layer6' inkscape:label='mimetypes' 
transform='translate(-92.005848,-887.99999)'/>
+  <g inkscape:groupmode='layer' id='layer5' inkscape:label='emotes' 
transform='translate(-92.005848,-887.99999)'/>
+  <g inkscape:groupmode='layer' id='layer9' inkscape:label='emblems' 
transform='translate(-92.005848,-887.99999)'/>
+  <g inkscape:groupmode='layer' id='layer2' inkscape:label='devices' 
transform='translate(-92.005848,-887.99999)'/>
+  <g inkscape:groupmode='layer' id='layer8' inkscape:label='categories' 
transform='translate(-92.005848,-887.99999)'/>
+  <g inkscape:groupmode='layer' id='layer3' inkscape:label='apps' 
transform='translate(-92.005848,-887.99999)'/>
+  <g inkscape:groupmode='layer' id='layer4' inkscape:label='actions' 
transform='translate(-92.005848,-887.99999)'/>
+</svg>
diff --git a/etc/images/radio-checked.svg b/etc/images/radio-checked.svg
new file mode 100644
index 0000000..8950b44
--- /dev/null
+++ b/etc/images/radio-checked.svg
@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg"; height="1em" viewBox="0 0 16 16">
+  <g>
+    <path d="M8 5a3.001 3.001 0 0 0 0 6 3.001 3.001 0 0 0 0 -6z" 
overflow="visible"/>
+    <path d="M8.004 1C4.144 1 1 4.144 1 8.004c0 3.86 3.144 7.006 7.004 7.006 
3.86 0 7.006-3.146 7.006-7.006C15.01 4.144 11.864 1 8.004 1zm0 1a6.002 6.002 0 
0 1 6.006 6.004 6.004 6.004 0 0 1 -6.006 6.006A6.002 6.002 0 0 1 2 8.004 6 6 0 
0 1 8.004 2z" overflow="visible"/>
+  </g>
+</svg>
diff --git a/etc/images/radio-mixed.svg b/etc/images/radio-mixed.svg
new file mode 100644
index 0000000..1b3bfa7
--- /dev/null
+++ b/etc/images/radio-mixed.svg
@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg"; height="1em" viewBox="0 0 16 16">
+  <g>
+    <path d="M8 1C4.142 1 1 4.142 1 8s3.142 7 7 7 7-3.142 7-7-3.142-7-7-7zm0 
1c3.316 0 6 2.684 6 6s-2.684 6-6 6-6-2.684-6-6 2.684-6 6-6z" overflow="visible" 
/>
+    <path d="M5 6a2 2 0 1 0 0 4h6a2 2 0 1 0 0 -4z" overflow="visible" />
+  </g>
+</svg>
diff --git a/etc/images/radio.svg b/etc/images/radio.svg
new file mode 100644
index 0000000..2593a78
--- /dev/null
+++ b/etc/images/radio.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg"; height="1em" viewBox="0 0 16 16">
+  <path d="M8 1C4.142 1 1 4.142 1 8s3.142 7 7 7 7-3.142 7-7-3.142-7-7-7zm0 
1c3.316 0 6 2.684 6 6s-2.684 6-6 6-6-2.684-6-6 2.684-6 6-6z" overflow="visible" 
/>
+</svg>
diff --git a/etc/images/right.svg b/etc/images/right.svg
new file mode 100644
index 0000000..d58cd36
--- /dev/null
+++ b/etc/images/right.svg
@@ -0,0 +1,40 @@
+<?xml version='1.0' encoding='UTF-8' standalone='no'?>
+<svg xmlns:cc='http://creativecommons.org/ns#' 
xmlns:dc='http://purl.org/dc/elements/1.1/' 
sodipodi:docname='pan-end-symbolic.svg' 
inkscape:export-filename='/home/sam/source-symbolic.png' 
inkscape:export-xdpi='270' inkscape:export-ydpi='270' height='16' id='svg7384' 
xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape' 
xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' 
xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd' 
style='enable-background:new' xmlns:svg= [...]
+  <sodipodi:namedview inkscape:bbox-nodes='true' inkscape:bbox-paths='false' 
bordercolor='#000000' borderlayer='false' borderopacity='0.50196078' 
inkscape:current-layer='layer10' inkscape:cx='31.147668' inkscape:cy='7.96251' 
inkscape:document-rotation='0' gridtolerance='10' inkscape:guide-bbox='true' 
guidetolerance='10' id='namedview88' inkscape:measure-end='0,0' 
inkscape:measure-start='0,0' inkscape:object-nodes='true' 
inkscape:object-paths='true' objecttolerance='10' pagecolor='#e2e2e2 [...]
+    <inkscape:grid color='#000000' dotted='false' empcolor='#0800ff' 
empopacity='0.4627451' empspacing='4' enabled='true' id='grid4866' 
opacity='0.16470588' originx='-112.00585' originy='-951.99999' 
snapvisiblegridlinesonly='true' spacingx='1' spacingy='1' type='xygrid' 
visible='true'/>
+    <inkscape:grid dotted='true' empcolor='#3f3fff' empopacity='0' 
empspacing='4' id='grid3540' originx='-112.00585' originy='-951.99999' 
spacingx='0.5' spacingy='0.5' type='xygrid'/>
+  </sodipodi:namedview>
+  <metadata id='metadata90'>
+    <rdf:RDF>
+      <cc:Work rdf:about=''>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type rdf:resource='http://purl.org/dc/dcmitype/StillImage'/>
+        <dc:title>Gnome Symbolic Icons</dc:title>
+        <cc:license 
rdf:resource='http://creativecommons.org/licenses/by-sa/4.0/'/>
+      </cc:Work>
+      <cc:License rdf:about='http://creativecommons.org/licenses/by-sa/4.0/'>
+        <cc:permits rdf:resource='http://creativecommons.org/ns#Reproduction'/>
+        <cc:permits rdf:resource='http://creativecommons.org/ns#Distribution'/>
+        <cc:requires rdf:resource='http://creativecommons.org/ns#Notice'/>
+        <cc:requires rdf:resource='http://creativecommons.org/ns#Attribution'/>
+        <cc:permits 
rdf:resource='http://creativecommons.org/ns#DerivativeWorks'/>
+        <cc:requires rdf:resource='http://creativecommons.org/ns#ShareAlike'/>
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <title id='title8473'>Gnome Symbolic Icons</title>
+  <defs id='defs7386'/>
+  <g inkscape:groupmode='layer' id='layer10' inkscape:label='ui' 
transform='translate(-112.00585,-951.99999)'>
+    <path inkscape:connector-curvature='0' d='m 117,966 6.00585,-6.00001 L 
117,954 Z' id='path6412' sodipodi:nodetypes='cccc' 
style='fill:#2e3436;fill-opacity:1;stroke:none'/>
+  </g>
+  <g inkscape:groupmode='layer' id='layer1' inkscape:label='status' 
transform='translate(-112.00585,-887.99999)'/>
+  <g inkscape:groupmode='layer' id='layer11' inkscape:label='legacy' 
transform='translate(-112.00585,-951.99999)'/>
+  <g inkscape:groupmode='layer' id='layer7' inkscape:label='places' 
transform='translate(-112.00585,-887.99999)'/>
+  <g inkscape:groupmode='layer' id='layer6' inkscape:label='mimetypes' 
transform='translate(-112.00585,-887.99999)'/>
+  <g inkscape:groupmode='layer' id='layer5' inkscape:label='emotes' 
transform='translate(-112.00585,-887.99999)'/>
+  <g inkscape:groupmode='layer' id='layer9' inkscape:label='emblems' 
transform='translate(-112.00585,-887.99999)'/>
+  <g inkscape:groupmode='layer' id='layer2' inkscape:label='devices' 
transform='translate(-112.00585,-887.99999)'/>
+  <g inkscape:groupmode='layer' id='layer8' inkscape:label='categories' 
transform='translate(-112.00585,-887.99999)'/>
+  <g inkscape:groupmode='layer' id='layer3' inkscape:label='apps' 
transform='translate(-112.00585,-887.99999)'/>
+  <g inkscape:groupmode='layer' id='layer4' inkscape:label='actions' 
transform='translate(-112.00585,-887.99999)'/>
+</svg>
diff --git a/etc/images/unchecked.svg b/etc/images/unchecked.svg
new file mode 100644
index 0000000..09bab8d
--- /dev/null
+++ b/etc/images/unchecked.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg"; height="1em" viewBox="0 0 16 16">
+  <path d="M3.5 1A2.506 2.506 0 0 0 1 3.5v9C1 13.876 2.124 15 3.5 15h9c1.376 0 
2.5-1.124 2.5-2.5v-9C15 2.124 13.876 1 12.5 1zm0 1h9c.84 0 1.5 .66 1.5 1.5v9c0 
.84-.66 1.5-1.5 1.5h-9c-.84 0-1.5-.66-1.5-1.5v-9C2 2.66 2.66 2 3.5 2z" 
overflow="visible" />
+</svg>
diff --git a/etc/images/up.svg b/etc/images/up.svg
new file mode 100644
index 0000000..9e1a245
--- /dev/null
+++ b/etc/images/up.svg
@@ -0,0 +1,40 @@
+<?xml version='1.0' encoding='UTF-8' standalone='no'?>
+<svg xmlns:cc='http://creativecommons.org/ns#' 
xmlns:dc='http://purl.org/dc/elements/1.1/' 
sodipodi:docname='pan-up-symbolic.svg' 
inkscape:export-filename='/home/sam/source-symbolic.png' 
inkscape:export-xdpi='270' inkscape:export-ydpi='270' height='16' id='svg7384' 
xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape' 
xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' 
xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd' 
style='enable-background:new' xmlns:svg=' [...]
+  <sodipodi:namedview inkscape:bbox-nodes='true' inkscape:bbox-paths='false' 
bordercolor='#000000' borderlayer='false' borderopacity='0.50196078' 
inkscape:current-layer='layer10' inkscape:cx='11.14767' inkscape:cy='7.9625016' 
inkscape:document-rotation='0' gridtolerance='10' inkscape:guide-bbox='true' 
guidetolerance='10' id='namedview88' inkscape:measure-end='0,0' 
inkscape:measure-start='0,0' inkscape:object-nodes='true' 
inkscape:object-paths='true' objecttolerance='10' pagecolor='#e2e2e [...]
+    <inkscape:grid color='#000000' dotted='false' empcolor='#0800ff' 
empopacity='0.4627451' empspacing='4' enabled='true' id='grid4866' 
opacity='0.16470588' originx='-132.00585' originy='-952' 
snapvisiblegridlinesonly='true' spacingx='1' spacingy='1' type='xygrid' 
visible='true'/>
+    <inkscape:grid dotted='true' empcolor='#3f3fff' empopacity='0' 
empspacing='4' id='grid3540' originx='-132.00585' originy='-952' spacingx='0.5' 
spacingy='0.5' type='xygrid'/>
+  </sodipodi:namedview>
+  <metadata id='metadata90'>
+    <rdf:RDF>
+      <cc:Work rdf:about=''>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type rdf:resource='http://purl.org/dc/dcmitype/StillImage'/>
+        <dc:title>Gnome Symbolic Icons</dc:title>
+        <cc:license 
rdf:resource='http://creativecommons.org/licenses/by-sa/4.0/'/>
+      </cc:Work>
+      <cc:License rdf:about='http://creativecommons.org/licenses/by-sa/4.0/'>
+        <cc:permits rdf:resource='http://creativecommons.org/ns#Reproduction'/>
+        <cc:permits rdf:resource='http://creativecommons.org/ns#Distribution'/>
+        <cc:requires rdf:resource='http://creativecommons.org/ns#Notice'/>
+        <cc:requires rdf:resource='http://creativecommons.org/ns#Attribution'/>
+        <cc:permits 
rdf:resource='http://creativecommons.org/ns#DerivativeWorks'/>
+        <cc:requires rdf:resource='http://creativecommons.org/ns#ShareAlike'/>
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <title id='title8473'>Gnome Symbolic Icons</title>
+  <defs id='defs7386'/>
+  <g inkscape:groupmode='layer' id='layer10' inkscape:label='ui' 
transform='translate(-132.00585,-952)'>
+    <path inkscape:connector-curvature='0' d='M 146,963 140.00585,956.99999 
134,963 Z' id='path6418' sodipodi:nodetypes='cccc' 
style='fill:#2e3436;fill-opacity:1;stroke:none'/>
+  </g>
+  <g inkscape:groupmode='layer' id='layer1' inkscape:label='status' 
transform='translate(-132.00585,-888)'/>
+  <g inkscape:groupmode='layer' id='layer11' inkscape:label='legacy' 
transform='translate(-132.00585,-952)'/>
+  <g inkscape:groupmode='layer' id='layer7' inkscape:label='places' 
transform='translate(-132.00585,-888)'/>
+  <g inkscape:groupmode='layer' id='layer6' inkscape:label='mimetypes' 
transform='translate(-132.00585,-888)'/>
+  <g inkscape:groupmode='layer' id='layer5' inkscape:label='emotes' 
transform='translate(-132.00585,-888)'/>
+  <g inkscape:groupmode='layer' id='layer9' inkscape:label='emblems' 
transform='translate(-132.00585,-888)'/>
+  <g inkscape:groupmode='layer' id='layer2' inkscape:label='devices' 
transform='translate(-132.00585,-888)'/>
+  <g inkscape:groupmode='layer' id='layer8' inkscape:label='categories' 
transform='translate(-132.00585,-888)'/>
+  <g inkscape:groupmode='layer' id='layer3' inkscape:label='apps' 
transform='translate(-132.00585,-888)'/>
+  <g inkscape:groupmode='layer' id='layer4' inkscape:label='actions' 
transform='translate(-132.00585,-888)'/>
+</svg>
diff --git a/etc/schema/OpenDocument-schema-v1.3+libreoffice.rnc 
b/etc/schema/OpenDocument-schema-v1.3+libreoffice.rnc
new file mode 100644
index 0000000..5239c84
--- /dev/null
+++ b/etc/schema/OpenDocument-schema-v1.3+libreoffice.rnc
@@ -0,0 +1,892 @@
+# Open Document Format for Office Applications (OpenDocument) Version 1.3
+# OASIS Standard, In progress
+# Relax-NG Schema
+# Source: https://tools.oasis-open.org/version-control/svn/office/
+# Copyright (c) OASIS Open 2002-2015. All Rights Reserved.
+#
+# All capitalized terms in the following text have the meanings assigned to 
them
+# in the OASIS Intellectual Property Rights Policy (the "OASIS IPR Policy"). 
The
+# full Policy may be found at the OASIS website.
+#
+# This document and translations of it may be copied and furnished to others, 
and
+# derivative works that comment on or otherwise explain it or assist in its
+# implementation may be prepared, copied, published, and distributed, in whole 
or
+# in part, without restriction of any kind, provided that the above copyright
+# notice and this section are included on all such copies and derivative works.
+# However, this document itself may not be modified in any way, including by
+# removing the copyright notice or references to OASIS, except as needed for 
the
+# purpose of developing any document or deliverable produced by an OASIS
+# Technical Committee (in which case the rules applicable to copyrights, as set
+# forth in the OASIS IPR Policy, must be followed) or as required to translate 
it
+# into languages other than English.
+#
+# The limited permissions granted above are perpetual and will not be revoked 
by
+# OASIS or its successors or assigns.
+#
+# This document and the information contained herein is provided on an "AS IS"
+# basis and OASIS DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT 
NOT
+# LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT
+# INFRINGE ANY OWNERSHIP RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR
+# FITNESS FOR A PARTICULAR PURPOSE.
+
+namespace anim = "urn:oasis:names:tc:opendocument:xmlns:animation:1.0"
+namespace calcext =
+  "urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0"
+namespace chart = "urn:oasis:names:tc:opendocument:xmlns:chart:1.0"
+namespace chartooo = "http://openoffice.org/2010/chart";
+namespace config = "urn:oasis:names:tc:opendocument:xmlns:config:1.0"
+namespace css3t = "http://www.w3.org/TR/css3-text/";
+namespace db = "urn:oasis:names:tc:opendocument:xmlns:database:1.0"
+namespace dc = "http://purl.org/dc/elements/1.1/";
+namespace dr3d = "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"
+namespace draw = "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"
+namespace drawooo = "http://openoffice.org/2010/draw";
+namespace field =
+  "urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0"
+namespace fo =
+  "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
+namespace form = "urn:oasis:names:tc:opendocument:xmlns:form:1.0"
+namespace grddl = "http://www.w3.org/2003/g/data-view#";
+namespace loext =
+  "urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"
+namespace math = "http://www.w3.org/1998/Math/MathML";
+namespace meta = "urn:oasis:names:tc:opendocument:xmlns:meta:1.0"
+namespace number = "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"
+namespace office = "urn:oasis:names:tc:opendocument:xmlns:office:1.0"
+namespace officeooo = "http://openoffice.org/2009/office";
+namespace presentation =
+  "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0"
+namespace rng = "http://relaxng.org/ns/structure/1.0";
+namespace script = "urn:oasis:names:tc:opendocument:xmlns:script:1.0"
+namespace smil =
+  "urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0"
+namespace style = "urn:oasis:names:tc:opendocument:xmlns:style:1.0"
+namespace svg =
+  "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"
+namespace table = "urn:oasis:names:tc:opendocument:xmlns:table:1.0"
+namespace tableooo = "http://openoffice.org/2009/table";
+namespace text = "urn:oasis:names:tc:opendocument:xmlns:text:1.0"
+namespace xforms = "http://www.w3.org/2002/xforms";
+namespace xhtml = "http://www.w3.org/1999/xhtml";
+namespace xlink = "http://www.w3.org/1999/xlink";
+
+include "OpenDocument-schema-v1.3.rnc" {
+  office-document-common-attrs =
+    attribute office:version {
+      # FIXME remove this hack once we write 1.3
+      "1.3" | "1.2"
+    }
+    & attribute grddl:transformation {
+        list { anyIRI* }
+      }?
+  style-graphic-properties-attlist =
+    attribute draw:stroke { "none" | "dash" | "solid" }?
+    & attribute draw:stroke-dash { styleNameRef }?
+    & attribute draw:stroke-dash-names { styleNameRefs }?
+    & attribute svg:stroke-width { length }?
+    & attribute svg:stroke-color { color }?
+    & attribute draw:marker-start { styleNameRef }?
+    & attribute draw:marker-end { styleNameRef }?
+    & attribute draw:marker-start-width { length }?
+    & attribute draw:marker-end-width { length }?
+    & attribute draw:marker-start-center { boolean }?
+    & attribute draw:marker-end-center { boolean }?
+    & attribute svg:stroke-opacity {
+        xsd:double { minInclusive = "0" maxInclusive = "1" }
+        | zeroToHundredPercent
+      }?
+    & attribute draw:stroke-linejoin {
+        "miter" | "round" | "bevel" | "middle" | "none"
+      }?
+    & attribute svg:stroke-linecap { "butt" | "square" | "round" }?
+    & attribute draw:symbol-color { color }?
+    & attribute text:animation {
+        "none" | "scroll" | "alternate" | "slide"
+      }?
+    & attribute text:animation-direction {
+        "left" | "right" | "up" | "down"
+      }?
+    & attribute text:animation-start-inside { boolean }?
+    & attribute text:animation-stop-inside { boolean }?
+    & attribute text:animation-repeat { nonNegativeInteger }?
+    & attribute text:animation-delay { duration }?
+    & attribute text:animation-steps { length }?
+    & attribute draw:auto-grow-width { boolean }?
+    & attribute draw:auto-grow-height { boolean }?
+    & # FIXME remove this once the export bug is fixed
+      attribute draw:fit-to-size {
+        "true" | "false" | "all" | "shrink-to-fit"
+      }?
+    & attribute draw:fit-to-contour { boolean }?
+    & attribute draw:textarea-vertical-align {
+        "top" | "middle" | "bottom" | "justify"
+      }?
+    & attribute draw:textarea-horizontal-align {
+        "left" | "center" | "right" | "justify"
+      }?
+    & attribute fo:wrap-option { "no-wrap" | "wrap" }?
+    & attribute style:shrink-to-fit { boolean }?
+    & attribute draw:color-mode {
+        "greyscale" | "mono" | "watermark" | "standard"
+      }?
+    & attribute draw:color-inversion { boolean }?
+    & attribute draw:luminance { signedZeroToHundredPercent }
+      # https://issues.oasis-open.org/browse/OFFICE-3821
+      ?
+    & attribute draw:contrast { percent }?
+    & attribute draw:gamma { percent }?
+    & attribute draw:red { signedZeroToHundredPercent }?
+    & attribute draw:green { signedZeroToHundredPercent }?
+    & attribute draw:blue { signedZeroToHundredPercent }?
+    & attribute draw:image-opacity { zeroToHundredPercent }?
+    & attribute draw:shadow { "visible" | "hidden" }?
+    & attribute draw:shadow-offset-x { length }?
+    & attribute draw:shadow-offset-y { length }?
+    & attribute draw:shadow-color { color }?
+    & attribute draw:shadow-opacity { zeroToHundredPercent }?
+    & # TODO: no proposal for loext:shadow-blur
+      attribute loext:shadow-blur { length }?
+    & attribute draw:start-line-spacing-horizontal { distance }?
+    & attribute draw:start-line-spacing-vertical { distance }?
+    & attribute draw:end-line-spacing-horizontal { distance }?
+    & attribute draw:end-line-spacing-vertical { distance }?
+    & attribute draw:line-distance { distance }?
+    & attribute draw:guide-overhang { length }?
+    & attribute draw:guide-distance { distance }?
+    & attribute draw:start-guide { length }?
+    & attribute draw:end-guide { length }?
+    & attribute draw:placing { "below" | "above" }?
+    & attribute draw:parallel { boolean }?
+    & attribute draw:measure-align {
+        "automatic" | "left-outside" | "inside" | "right-outside"
+      }?
+    & attribute draw:measure-vertical-align {
+        "automatic" | "above" | "below" | "center"
+      }?
+    & attribute draw:unit {
+        "automatic"
+        | "mm"
+        | "cm"
+        | "m"
+        | "km"
+        | "pt"
+        | "pc"
+        | "inch"
+        | "ft"
+        | "mi"
+      }?
+    & attribute draw:show-unit { boolean }?
+    & attribute draw:decimal-places { nonNegativeInteger }?
+    & attribute draw:caption-type {
+        "straight-line" | "angled-line" | "angled-connector-line"
+      }?
+    & attribute draw:caption-angle-type { "fixed" | "free" }?
+    & attribute draw:caption-angle { angle }?
+    & attribute draw:caption-gap { distance }?
+    & attribute draw:caption-escape-direction {
+        "horizontal" | "vertical" | "auto"
+      }?
+    & attribute draw:caption-escape { length | percent }?
+    & attribute draw:caption-line-length { length }?
+    & attribute draw:caption-fit-line-length { boolean }?
+    & attribute dr3d:horizontal-segments { nonNegativeInteger }?
+    & attribute dr3d:vertical-segments { nonNegativeInteger }?
+    & attribute dr3d:edge-rounding { percent }?
+    & attribute dr3d:edge-rounding-mode { "correct" | "attractive" }?
+    & attribute dr3d:back-scale { percent }?
+    & attribute dr3d:depth { length }?
+    & attribute dr3d:backface-culling { "enabled" | "disabled" }?
+    & attribute dr3d:end-angle { angle }?
+    & attribute dr3d:close-front { boolean }?
+    & attribute dr3d:close-back { boolean }?
+    & attribute dr3d:lighting-mode { "standard" | "double-sided" }?
+    & attribute dr3d:normals-kind { "object" | "flat" | "sphere" }?
+    & attribute dr3d:normals-direction { "normal" | "inverse" }?
+    & attribute dr3d:texture-generation-mode-x {
+        "object" | "parallel" | "sphere"
+      }?
+    & attribute dr3d:texture-generation-mode-y {
+        "object" | "parallel" | "sphere"
+      }?
+    & attribute dr3d:texture-kind {
+        "luminance" | "intensity" | "color"
+      }?
+    & attribute dr3d:texture-filter { "enabled" | "disabled" }?
+    & attribute dr3d:texture-mode { "replace" | "modulate" | "blend" }?
+    & attribute dr3d:ambient-color { color }?
+    & attribute dr3d:emissive-color { color }?
+    & attribute dr3d:specular-color { color }?
+    & attribute dr3d:diffuse-color { color }?
+    & attribute dr3d:shininess { percent }?
+    & attribute dr3d:shadow { "visible" | "hidden" }?
+    & common-draw-rel-size-attlist
+    & attribute fo:min-width { length | percent }?
+    & attribute fo:min-height { length | percent }?
+    & attribute fo:max-height { length | percent }?
+    & attribute fo:max-width { length | percent }?
+    & common-horizontal-margin-attlist
+    & common-vertical-margin-attlist
+    & common-margin-attlist
+    & attribute style:print-content { boolean }?
+    & attribute style:protect {
+        "none"
+        | list { ("content" | "position" | "size")+ }
+      }?
+    & attribute style:horizontal-pos {
+        "left"
+        | "center"
+        | "right"
+        | "from-left"
+        | "inside"
+        | "outside"
+        | "from-inside"
+      }?
+    & attribute svg:x { coordinate }?
+    & attribute style:horizontal-rel {
+        "page"
+        | "page-content"
+        | "page-start-margin"
+        | "page-end-margin"
+        | "frame"
+        | "frame-content"
+        | "frame-start-margin"
+        | "frame-end-margin"
+        | "paragraph"
+        | "paragraph-content"
+        | "paragraph-start-margin"
+        | "paragraph-end-margin"
+        | "char"
+      }?
+    & common-vertical-pos-attlist
+    & common-vertical-rel-attlist
+    & common-text-anchor-attlist
+    & common-border-attlist
+    & common-border-line-width-attlist
+    & common-padding-attlist
+    & common-shadow-attlist
+    & common-background-color-attlist
+    & common-background-transparency-attlist
+    & common-editable-attlist
+    & attribute style:wrap {
+        "none"
+        | "left"
+        | "right"
+        | "parallel"
+        | "dynamic"
+        | "run-through"
+        | "biggest"
+      }?
+    & attribute style:wrap-dynamic-threshold { nonNegativeLength }?
+    & attribute style:number-wrapped-paragraphs {
+        "no-limit" | positiveInteger
+      }?
+    & attribute style:wrap-contour { boolean }?
+    & attribute style:wrap-contour-mode { "full" | "outside" }?
+    & attribute style:run-through { "foreground" | "background" }?
+    & attribute style:flow-with-text { boolean }?
+    & attribute style:overflow-behavior {
+        "clip" | "auto-create-new-frame"
+      }?
+    & attribute style:mirror {
+        "none"
+        | "vertical"
+        | horizontal-mirror
+        | list { "vertical", horizontal-mirror }
+        | list { horizontal-mirror, "vertical" }
+      }?
+    & attribute fo:clip { "auto" | clipShape }?
+    & attribute draw:wrap-influence-on-position {
+        "iterative" | "once-concurrent" | "once-successive"
+      }?
+    & common-writing-mode-attlist
+    & attribute draw:frame-display-scrollbar { boolean }?
+    & attribute draw:frame-display-border { boolean }?
+    & attribute draw:frame-margin-horizontal { nonNegativePixelLength }?
+    & attribute draw:frame-margin-vertical { nonNegativePixelLength }?
+    & attribute draw:visible-area-left { nonNegativeLength }?
+    & attribute draw:visible-area-top { nonNegativeLength }?
+    & attribute draw:visible-area-width { positiveLength }?
+    & attribute draw:visible-area-height { positiveLength }?
+    & attribute draw:draw-aspect {
+        "content" | "thumbnail" | "icon" | "print-view"
+      }?
+    & attribute draw:ole-draw-aspect { nonNegativeInteger }?
+    & # https://issues.oasis-open.org/browse/OFFICE-4047
+      attribute loext:allow-overlap { boolean }?
+    & # TODO: no proposal for loext:glow*
+      attribute loext:glow-radius { length }?
+    & attribute loext:glow-color { color }?
+    & attribute loext:glow-transparency { zeroToHundredPercent }?
+    & # TODO: no proposal for loext:softedge-radius
+      attribute loext:softedge-radius { length }?
+  draw-text =
+    (text-p
+     | text-list
+     | # https://issues.oasis-open.org/browse/OFFICE-3761
+       loext-table)*
+  office-annotation-attlist &=
+    attribute office:display { boolean }?
+    & common-office-annotation-name-attlist?
+    & attribute loext:resolved { boolean }?
+  style-style-content =
+    (attribute style:family { "text" },
+     style-text-properties?)
+    | (attribute style:family { "paragraph" },
+       # TODO no proposal
+       loext-graphic-properties?,
+       style-paragraph-properties?,
+       style-text-properties?)
+    | (attribute style:family { "section" },
+       style-section-properties?)
+    | (attribute style:family { "ruby" },
+       style-ruby-properties?)
+    | (attribute style:family { "table" },
+       style-table-properties?)
+    | (attribute style:family { "table-column" },
+       style-table-column-properties?)
+    | (attribute style:family { "table-row" },
+       style-table-row-properties?)
+    | (attribute style:family { "table-cell" },
+       # TODO no proposal
+       loext-graphic-properties?,
+       style-table-cell-properties?,
+       style-paragraph-properties?,
+       style-text-properties?)
+    | (attribute style:family { "graphic" | "presentation" },
+       style-graphic-properties?,
+       style-paragraph-properties?,
+       style-text-properties?)
+    | (attribute style:family { "drawing-page" },
+       style-drawing-page-properties?)
+    | (attribute style:family { "chart" },
+       style-chart-properties?,
+       style-graphic-properties?,
+       style-paragraph-properties?,
+       style-text-properties?)
+  table-table-template =
+    element table:table-template {
+      table-table-template-attlist,
+      table-first-row?,
+      table-last-row?,
+      table-first-column?,
+      table-last-column?,
+      table-body,
+      table-even-rows?,
+      table-odd-rows?,
+      table-even-columns?,
+      table-odd-columns?,
+      table-background?,
+      # TODO no proposal
+      table-first-row-even-column?,
+      table-last-row-even-column?,
+      table-first-row-end-column?,
+      table-first-row-start-column?,
+      table-last-row-end-column?,
+      table-last-row-start-column?
+    }
+  draw-frame =
+    element draw:frame {
+      common-draw-shape-with-text-and-styles-attlist,
+      common-draw-position-attlist,
+      common-draw-rel-size-attlist,
+      common-draw-caption-id-attlist,
+      presentation-shape-attlist,
+      draw-frame-attlist,
+      (draw-text-box
+       | draw-image
+       | draw-object
+       | draw-object-ole
+       | draw-applet
+       | draw-floating-frame
+       | draw-plugin
+       | table-table)*,
+      office-event-listeners?,
+      draw-glue-point*,
+      draw-image-map?,
+      svg-title?,
+      svg-desc?,
+      (draw-contour-polygon | draw-contour-path)?,
+      # TODO no proposal
+      loext-signatureline?,
+      loext-qrcode?
+    }
+  common-value-and-type-attlist =
+    (attribute office:value-type { "float" },
+     attribute calcext:value-type { "float" }?,
+     attribute office:value { double })
+    | (attribute office:value-type { "percentage" },
+       attribute calcext:value-type { "percentage" }?,
+       attribute office:value { double })
+    | (attribute office:value-type { "currency" },
+       attribute calcext:value-type { "currency" }?,
+       attribute office:value { double },
+       attribute office:currency { \string }?)
+    | (attribute office:value-type { "date" },
+       attribute calcext:value-type { "date" }?,
+       attribute office:date-value { dateOrDateTime })
+    | (attribute office:value-type { "time" },
+       attribute calcext:value-type { "time" }?,
+       attribute office:time-value { duration })
+    | (attribute office:value-type { "boolean" },
+       attribute calcext:value-type { "boolean" }?,
+       attribute office:boolean-value { boolean })
+    | (attribute office:value-type { "string" },
+       # OFFICE-3759
+       attribute calcext:value-type { "string" | "error" }?,
+       attribute office:string-value { \string }?)
+  chart-axis =
+    element chart:axis {
+      chart-axis-attlist,
+      # OFFICE-2119
+      ((attribute chartooo:axis-type { "auto" },
+        chartooo-date-scale?)
+       | (attribute chartooo:axis-type { "date" },
+          chartooo-date-scale)
+       | attribute chartooo:axis-type { "text" })?,
+      chart-title?,
+      chart-categories?,
+      chart-grid*
+    }
+  table-table =
+    element table:table {
+      table-table-attlist,
+      table-title?,
+      table-desc?,
+      # TODO add to proposal, OFFICE-2112
+      table-table-protection?,
+      table-table-source?,
+      office-dde-source?,
+      table-scenario?,
+      office-forms?,
+      table-shapes?,
+      table-columns-and-groups,
+      table-rows-and-groups,
+      table-named-expressions?,
+      # TODO no proposal, this is wild guessing, OFFICE-3785
+      element calcext:conditional-formats {
+        element calcext:conditional-format {
+          attribute calcext:target-range-address { cellRangeAddress },
+          (element calcext:condition {
+             attribute calcext:apply-style-name { styleNameRef },
+             attribute calcext:value { \string },
+             attribute calcext:base-cell-address { cellAddress }
+           }+
+           | element calcext:data-bar {
+               attribute calcext:max-length { \string },
+               attribute calcext:negative-color { color },
+               attribute calcext:positive-color { color },
+               attribute calcext:axis-color { color },
+               attribute calcext:axis-position { "middle" }?,
+               element calcext:formatting-entry {
+                 attribute calcext:value { \string },
+                 attribute calcext:type {
+                   "auto-minimum"
+                   | "auto-maximum"
+                   | "minimum"
+                   | "maximum"
+                   | "percent"
+                   | "percentile"
+                   | "number"
+                   | "formula"
+                 }
+               },
+               element calcext:formatting-entry {
+                 attribute calcext:value { \string },
+                 attribute calcext:type {
+                   "auto-minimum"
+                   | "auto-maximum"
+                   | "minimum"
+                   | "maximum"
+                   | "percent"
+                   | "percentile"
+                   | "number"
+                   | "formula"
+                 }
+               }
+             }
+           | element calcext:color-scale {
+               element calcext:color-scale-entry {
+                 attribute calcext:value { \string },
+                 attribute calcext:type {
+                   "minimum"
+                   | "maximum"
+                   | "percent"
+                   | "percentile"
+                   | "number"
+                   | "formula"
+                 },
+                 attribute calcext:color { color }
+               },
+               element calcext:color-scale-entry {
+                 attribute calcext:value { \string },
+                 attribute calcext:type {
+                   "minimum"
+                   | "maximum"
+                   | "percent"
+                   | "percentile"
+                   | "number"
+                   | "formula"
+                 },
+                 attribute calcext:color { color }
+               },
+               element calcext:color-scale-entry {
+                 attribute calcext:value { \string },
+                 attribute calcext:type {
+                   "minimum"
+                   | "maximum"
+                   | "percent"
+                   | "percentile"
+                   | "number"
+                   | "formula"
+                 },
+                 attribute calcext:color { color }
+               }?
+             })
+        }+
+      }?
+    }
+  # TODO no proposal
+  draw-object =
+    element draw:object {
+      draw-object-attlist,
+      loext-text,
+      (common-draw-data-attlist | office-document | math-math)
+    }
+  draw-object-ole =
+    element draw:object-ole {
+      draw-object-ole-attlist,
+      loext-text,
+      (common-draw-data-attlist | office-binary-data)
+    }
+  # FIXME: one test exports 250 here, which is probably a bug
+  fontWeight =
+    "normal"
+    | "bold"
+    | "100"
+    | "200"
+    | "250"
+    | "300"
+    | "400"
+    | "500"
+    | "600"
+    | "700"
+    | "800"
+    | "900"
+}
+# TODO no proposal
+loext-p =
+  element loext:p { paragraph-attrs, paragraph-content-or-hyperlink* }
+loext-text = (loext-p | text-list | loext-table)*
+# OFFICE-2119
+chartooo-date-scale =
+  element chartooo:date-scale {
+    attribute chart:base-time-unit { chart-time-unit }?
+    & (attribute chart:major-interval-value { positiveInteger },
+       attribute chart:major-interval-unit { chart-time-unit })?
+    & (attribute chart:minor-interval-value { positiveInteger },
+       attribute chart:minor-interval-unit { chart-time-unit })?
+  }
+chart-time-unit = "days" | "months" | "years"
+# TODO no proposal
+loext-signatureline =
+  element loext:signatureline {
+    attribute loext:id { \string },
+    attribute loext:suggested-signer-name { \string },
+    attribute loext:suggested-signer-title { \string },
+    attribute loext:suggested-signer-email { \string },
+    attribute loext:signing-instructions { \string },
+    attribute loext:show-sign-date { boolean },
+    attribute loext:can-add-comment { boolean }
+  }
+loext-qrcode =
+  element loext:qrcode {
+    attribute office:string-value { \string },
+    attribute loext:qrcode-errorcorrection {
+      "low" | "medium" | "quartile" | "high"
+    },
+    attribute loext:qrcode-border { nonNegativeInteger }
+  }
+# https://issues.oasis-open.org/browse/OFFICE-3761
+loext-table =
+  element loext:table {
+    table-table-attlist,
+    table-title?,
+    table-desc?,
+    table-table-source?,
+    office-dde-source?,
+    table-scenario?,
+    office-forms?,
+    table-shapes?,
+    loext-columns-and-groups,
+    loext-rows-and-groups,
+    table-named-expressions?
+  }
+loext-rows-and-groups = (table-table-row-group | loext-rows-no-group)+
+loext-rows-no-group =
+  (loext-rows, (table-table-header-rows, loext-rows?)?)
+  | (table-table-header-rows, loext-rows?)
+loext-rows =
+  table-table-rows | (text-soft-page-break?, loext-table-row)+
+loext-table-row =
+  element loext:table-row {
+    table-table-row-attlist,
+    (loext-table-cell | loext-covered-table-cell)+
+  }
+loext-table-cell =
+  element loext:table-cell {
+    table-table-cell-attlist,
+    table-table-cell-attlist-extra,
+    table-table-cell-content
+  }
+loext-covered-table-cell =
+  element loext:covered-table-cell {
+    table-table-cell-attlist, table-table-cell-content
+  }
+loext-columns-and-groups =
+  (table-table-column-group | loext-columns-no-group)+
+loext-columns-no-group =
+  (loext-columns, (table-table-header-columns, loext-columns?)?)
+  | (table-table-header-columns, loext-columns?)
+loext-columns = loext-table-columns | loext-table-column+
+loext-table-columns =
+  element loext:table-columns { loext-table-column+ }
+loext-table-column =
+  element loext:table-column { table-table-column-attlist, empty }
+loext-graphic-properties =
+  element loext:graphic-properties {
+    style-graphic-properties-content-strict
+  }
+table-first-row-even-column =
+  element loext:first-row-even-column {
+    common-table-template-attlist, empty
+  }
+table-last-row-even-column =
+  element loext:last-row-even-column {
+    common-table-template-attlist, empty
+  }
+table-first-row-end-column =
+  element loext:first-row-end-column {
+    common-table-template-attlist, empty
+  }
+table-first-row-start-column =
+  element loext:first-row-start-column {
+    common-table-template-attlist, empty
+  }
+table-last-row-end-column =
+  element loext:last-row-end-column {
+    common-table-template-attlist, empty
+  }
+table-last-row-start-column =
+  element loext:last-row-start-column {
+    common-table-template-attlist, empty
+  }
+common-draw-rel-size-attlist &=
+  # OFFICE-3854
+  attribute loext:rel-width-rel {
+    "page"
+    | [
+        # TODO layout-environment ?
+
+      ]
+      "paragraph"
+  }?,
+  attribute loext:rel-height-rel { "page" | "paragraph" }?
+common-svg-font-face-xlink-attlist &=
+  # TODO no proposal
+  attribute loext:font-style { fontStyle }?,
+  attribute loext:font-weight { fontWeight }?
+# TODO no proposal
+
+# there's no ref-attrs so add it here
+text-common-ref-content &=
+  attribute loext:reference-language { language }?
+style-list-level-label-alignment-attlist &=
+  # TODO no proposal
+  attribute loext:label-followed-by {
+    "listtab" | "space" | "nothing" | "newline"
+  }?
+style-ruby-properties-attlist &=
+  # TODO proposal, OFFICE-3944
+  attribute loext:ruby-position {
+    "above" | "below" | "inter-character"
+  }?
+style-text-properties-attlist &=
+  # TODO no proposal
+  attribute officeooo:rsid { \string }?,
+  attribute officeooo:paragraph-rsid { \string }?,
+  # https://issues.oasis-open.org/browse/OFFICE-4049
+  attribute loext:opacity { zeroToHundredPercent }?
+style-text-properties-attlist &=
+  # OFFICE-3843
+  attribute loext:padding { nonNegativeLength }?,
+  attribute loext:padding-left { nonNegativeLength }?,
+  attribute loext:padding-right { nonNegativeLength }?,
+  attribute loext:padding-top { nonNegativeLength }?,
+  attribute loext:padding-bottom { nonNegativeLength }?,
+  attribute loext:border { \string }?,
+  attribute loext:border-left { \string }?,
+  attribute loext:border-right { \string }?,
+  attribute loext:border-top { \string }?,
+  attribute loext:border-bottom { \string }?,
+  attribute loext:shadow { shadowType }?
+# TODO no proposal
+style-chart-properties-attlist &=
+  attribute loext:try-staggering-first { boolean }?
+# TODO no proposal
+style-chart-properties-attlist &=
+  attribute loext:std-weight { \string }?
+# TODO no proposal
+chart-series-attlist &= attribute loext:label-string { \string }?
+# OFFICE-1148
+style-chart-properties-attlist &=
+  attribute loext:regression-max-degree { positiveInteger }?,
+  attribute loext:regression-force-intercept { boolean }?,
+  attribute loext:regression-intercept-value { double }?,
+  attribute loext:regression-name { \string }?,
+  attribute loext:regression-period { \string }?,
+  attribute loext:regression-extrapolate-forward { \string }?,
+  attribute loext:regression-extrapolate-backward { \string }?
+# TODO no proposal
+table-data-pilot-field-attlist &=
+  attribute tableooo:display-name { \string }?
+# TODO no proposal, 9009663d
+chart-chart-attlist &= attribute loext:data-pilot-source { \string }?
+# OFFICE-2112, TODO half of this missing in proposal
+table-table-protection =
+  element loext:table-protection {
+    attribute loext:select-protected-cells { boolean }?,
+    attribute loext:select-unprotected-cells { boolean }?,
+    attribute loext:insert-columns { boolean }?,
+    attribute loext:insert-rows { boolean }?,
+    attribute loext:delete-columns { boolean }?,
+    attribute loext:delete-rows { boolean }?
+  }
+office-spreadsheet-attlist &=
+  attribute loext:protection-key-digest-algorithm-2 { anyURI }?
+table-table-attlist &=
+  attribute loext:protection-key-digest-algorithm-2 { anyURI }?
+# https://issues.oasis-open.org/browse/OFFICE-2317
+vertJustifyValues = "auto" | "distribute"
+common-text-justify =
+  attribute css3t:text-justify { vertJustifyValues }?
+style-vertical-justify =
+  attribute loext:vertical-justify { vertJustifyValues }?,
+  attribute style:vertical-justify { vertJustifyValues }?
+style-paragraph-properties-attlist &=
+  (common-text-justify, style-vertical-justify)?
+style-table-cell-properties-attlist &=
+  (common-text-justify, style-vertical-justify)?
+number-fraction-attlist &=
+  # OFFICE-3695
+
+  # TODO no proposal, 1544a26ac9f7dd60605dd21e9cbe29d490aafdce
+  attribute loext:max-numerator-digits { positiveInteger }?
+# TODO no proposal
+table-data-pilot-level-attlist &=
+  attribute calcext:repeat-item-labels { boolean }?
+# TODO no proposal
+draw-enhanced-geometry-attlist &=
+  attribute drawooo:sub-view-size { \string }?,
+  attribute drawooo:enhanced-path { \string }?
+# TODO no proposal
+draw-custom-shape-attlist &= common-draw-rel-size-attlist
+# TODO no proposal
+style-page-layout-properties-attlist &=
+  style-graphic-fill-properties-attlist
+style-header-footer-properties-attlist &=
+  style-graphic-fill-properties-attlist
+# TODO no proposal
+text-index-entry-tab-stop-attrs &= attribute style:with-tab { boolean }?
+# TODO no proposal
+style-text-properties-attlist &=
+  attribute loext:char-shading-value { \string }?
+# TODO no proposal
+text-bookmark-start-attlist &=
+  (attribute loext:hidden { boolean },
+   attribute loext:condition { \string }?)?
+# TODO no proposal; see 7a5d79f2297a43d0a854e304b0792164272edfe0
+
+# FIXME this is almost certainly incomplete: need to figure out which elements 
can have this and which named pattern can be extended with it to get exactly 
these elements
+form-checkbox-attlist &= attribute form:input-required { boolean }?
+# https://issues.oasis-open.org/browse/OFFICE-4030
+common-writing-mode-attlist &= attribute loext:writing-mode { "bt-lr" }?
+# https://issues.oasis-open.org/browse/OFFICE-4073
+common-vertical-rel-attlist &=
+  attribute loext:vertical-rel {
+    "page-content-top" | "page-content-bottom"
+  }?
+# https://issues.oasis-open.org/browse/OFFICE-4105
+style-page-layout-properties-attlist &=
+  attribute loext:margin-gutter { length }?
+# just a test-case for user-defined attributes, move along, nothing to see 
here...
+style-table-cell-properties-attlist &= attribute proName { \string }?
+# TODO no proposal
+chart-data-point-attlist &=
+  attribute loext:custom-label-field { \string }?
+# TODO no proposal
+style-text-properties-attlist &=
+  attribute loext:hyphenation-no-caps { boolean }?
+# TODO no proposal
+chart-data-point-attlist &=
+  (attribute loext:custom-label-pos-x { double },
+   attribute loext:custom-label-pos-y { double })?
+# TODO no proposal
+chart-legend-attlist &= attribute loext:overlay { boolean }?
+# https://issues.oasis-open.org/browse/OFFICE-3936
+style-chart-properties-attlist &=
+  attribute loext:major-origin { double }?
+# TODO no proposal
+text-index-entry-chapter-attrs &=
+  attribute loext:outline-content-visible { boolean }?
+# https://issues.oasis-open.org/browse/OFFICE-2096
+paragraph-content |=
+  element field:fieldmark-start {
+    attribute text:name { \string },
+    attribute field:type {
+      # TODO <rng:ref name="namespacedToken"/>
+      \string
+    },
+    element field:param {
+      attribute field:name { \string },
+      attribute field:value { \string }
+    }*
+  }
+paragraph-content |= element field:fieldmark-end { empty }
+paragraph-content |=
+  element field:fieldmark {
+    attribute text:name { \string },
+    attribute field:type {
+      # TODO <rng:ref name="namespacedToken"/>
+      \string
+    },
+    element field:param {
+      attribute field:name { \string },
+      attribute field:value { \string }
+    }*
+  }
+# TODO no proposal
+animation-element |=
+  element loext:animatePhysics {
+    common-anim-target-attlist,
+    common-timing-attlist,
+    animate-physics-attlist
+  }
+animate-physics-attlist =
+  # default value: 0
+  attribute loext:velocity-x { double }?,
+  # default value: 0
+  attribute loext:velocity-y { double }?,
+  # default value: 0.1
+  attribute loext:bounciness {
+    xsd:double { minInclusive = "0" maxInclusive = "1" }
+  }?,
+  # default value: 1
+  attribute loext:density {
+    xsd:double { minInclusive = "0" }
+  }?
+# TODO no proposal
+style-chart-properties-attlist &=
+  attribute loext:custom-leader-lines { boolean }?
+# TODO no proposal
+style-chart-properties-attlist &=
+  attribute loext:external-data { \string }?
diff --git a/etc/schema/od-schema-v1.2-os.rnc 
b/etc/schema/OpenDocument-schema-v1.3.rnc
similarity index 96%
rename from etc/schema/od-schema-v1.2-os.rnc
rename to etc/schema/OpenDocument-schema-v1.3.rnc
index 8d679d6..2a78679 100644
--- a/etc/schema/od-schema-v1.2-os.rnc
+++ b/etc/schema/OpenDocument-schema-v1.3.rnc
@@ -1,33 +1,16 @@
-# Open Document Format for Office Applications (OpenDocument) Version 1.2
-# OASIS Standard, 29 September 2011
-# Relax-NG Schema
-# Source: http://docs.oasis-open.org/office/v1.2/os/
-# Copyright (c) OASIS Open 2002-2011, 2013. All Rights Reserved.
+# Open Document Format for Office Applications (OpenDocument) Version 1.3
+# Committee Specification 02
+# 30 October 2020
+# Copyright (c) OASIS Open 2020. All Rights Reserved.
+# Source: https://docs.oasis-open.org/office/OpenDocument/v1.3/cs02/schemas/
+# Latest stage of specification: 
https://docs.oasis-open.org/office/OpenDocument/v1.3/OpenDocument-v1.3-part1-introduction.html
+# TC IPR Statement: https://www.oasis-open.org/committees/office/ipr.php
 #
-# All capitalized terms in the following text have the meanings assigned to 
them
-# in the OASIS Intellectual Property Rights Policy (the "OASIS IPR Policy"). 
The
-# full Policy may be found at the OASIS website.
-#
-# This document and translations of it may be copied and furnished to others, 
and
-# derivative works that comment on or otherwise explain it or assist in its
-# implementation may be prepared, copied, published, and distributed, in whole 
or
-# in part, without restriction of any kind, provided that the above copyright
-# notice and this section are included on all such copies and derivative works.
-# However, this document itself may not be modified in any way, including by
-# removing the copyright notice or references to OASIS, except as needed for 
the
-# purpose of developing any document or deliverable produced by an OASIS
-# Technical Committee (in which case the rules applicable to copyrights, as set
-# forth in the OASIS IPR Policy, must be followed) or as required to translate 
it
-# into languages other than English.
-#
-# The limited permissions granted above are perpetual and will not be revoked 
by
-# OASIS or its successors or assigns.
-#
-# This document and the information contained herein is provided on an "AS IS"
-# basis and OASIS DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT 
NOT
-# LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT
-# INFRINGE ANY OWNERSHIP RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR
-# FITNESS FOR A PARTICULAR PURPOSE.
+#    Open Document Format for Office Applications (OpenDocument) Version 1.3
+#    Relax-NG Schema
+#    OpenDocument-v1.3-schema.rng
+
+# https://issues.oasis-open.org/browse/OFFICE-2153
 
 namespace anim = "urn:oasis:names:tc:opendocument:xmlns:animation:1.0"
 namespace chart = "urn:oasis:names:tc:opendocument:xmlns:chart:1.0"
@@ -46,6 +29,7 @@ namespace number = 
"urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"
 namespace office = "urn:oasis:names:tc:opendocument:xmlns:office:1.0"
 namespace presentation =
   "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0"
+namespace rng = "http://relaxng.org/ns/structure/1.0";
 namespace script = "urn:oasis:names:tc:opendocument:xmlns:script:1.0"
 namespace smil =
   "urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0"
@@ -58,2090 +42,1874 @@ namespace xforms = "http://www.w3.org/2002/xforms";
 namespace xhtml = "http://www.w3.org/1999/xhtml";
 namespace xlink = "http://www.w3.org/1999/xlink";
 
-office-process-content = attribute office:process-content { boolean }?
 start =
   office-document
   | office-document-content
   | office-document-styles
   | office-document-meta
   | office-document-settings
-office-document =
-  element office:document {
-    office-document-attrs,
-    office-document-common-attrs,
-    office-meta,
-    office-settings,
-    office-scripts,
-    office-font-face-decls,
-    office-styles,
-    office-automatic-styles,
-    office-master-styles,
-    office-body
-  }
-office-document-content =
-  element office:document-content {
-    office-document-common-attrs,
-    office-scripts,
-    office-font-face-decls,
-    office-automatic-styles,
-    office-body
-  }
-office-document-styles =
-  element office:document-styles {
-    office-document-common-attrs,
-    office-font-face-decls,
-    office-styles,
-    office-automatic-styles,
-    office-master-styles
-  }
-office-document-meta =
-  element office:document-meta {
-    office-document-common-attrs, office-meta
-  }
-office-document-settings =
-  element office:document-settings {
-    office-document-common-attrs, office-settings
+CURIE =
+  xsd:string { pattern = "(([\i-[:]][\c-[:]]*)?:)?.+" minLength = "1" }
+CURIEs = list { CURIE+ }
+ID = xsd:ID
+IDREF = xsd:IDREF
+IDREFS = xsd:IDREFS
+NCName = xsd:NCName
+SafeCURIE =
+  xsd:string {
+    pattern = "\[(([\i-[:]][\c-[:]]*)?:)?.+\]"
+    minLength = "3"
   }
-office-document-common-attrs =
-  attribute office:version { "1.2" }
-  & attribute grddl:transformation {
-      list { anyIRI* }
+URIorSafeCURIE = anyURI | SafeCURIE
+angle = xsd:string
+anim-animate-color-attlist =
+  attribute anim:color-interpolation { "rgb" | "hsl" }?
+  & attribute anim:color-interpolation-direction {
+      "clockwise" | "counter-clockwise"
     }?
-office-document-attrs = attribute office:mimetype { \string }
-office-meta = element office:meta { office-meta-content-strict }?
-office-meta-content-strict = office-meta-data*
-office-body = element office:body { office-body-content }
-office-body-content =
-  element office:text {
-    office-text-attlist,
-    office-text-content-prelude,
-    office-text-content-main,
-    office-text-content-epilogue
+anim-animate-motion-attlist =
+  attribute svg:path { pathData }?
+  & attribute svg:origin { \string }?
+  & attribute smil:calcMode {
+      "discrete" | "linear" | "paced" | "spline"
+    }?
+anim-animate-transform-attlist =
+  attribute svg:type {
+    "translate" | "scale" | "rotate" | "skewX" | "skewY"
   }
-  | element office:drawing {
-      office-drawing-attlist,
-      office-drawing-content-prelude,
-      office-drawing-content-main,
-      office-drawing-content-epilogue
+anim-audio-attlist =
+  attribute xlink:href { anyIRI }?
+  & attribute anim:audio-level { double }?
+anim-command-attlist = attribute anim:command { \string }
+anim-iterate-attlist =
+  common-anim-target-attlist
+  & attribute anim:iterate-type { \string }?
+  & attribute anim:iterate-interval { duration }?
+anim-transition-filter-attlist =
+  attribute smil:type { \string }
+  & attribute smil:subtype { \string }?
+  & attribute smil:direction { "forward" | "reverse" }?
+  & attribute smil:fadeColor { color }?
+  & attribute smil:mode { "in" | "out" }?
+animation-element =
+  element anim:animate {
+    common-anim-target-attlist,
+    common-anim-named-target-attlist,
+    common-anim-values-attlist,
+    common-anim-spline-mode-attlist,
+    common-spline-anim-value-attlist,
+    common-timing-attlist,
+    common-anim-add-accum-attlist
+  }
+  | element anim:set {
+      common-anim-target-attlist,
+      common-anim-named-target-attlist,
+      common-anim-set-values-attlist,
+      common-timing-attlist,
+      common-anim-add-accum-attlist
     }
-  | element office:presentation {
-      office-presentation-attlist,
-      office-presentation-content-prelude,
-      office-presentation-content-main,
-      office-presentation-content-epilogue
+  | element anim:animateMotion {
+      anim-animate-motion-attlist,
+      common-anim-target-attlist,
+      common-anim-named-target-attlist,
+      common-anim-add-accum-attlist,
+      common-anim-values-attlist,
+      common-timing-attlist,
+      common-spline-anim-value-attlist
     }
-  | element office:spreadsheet {
-      office-spreadsheet-attlist,
-      office-spreadsheet-content-prelude,
-      office-spreadsheet-content-main,
-      office-spreadsheet-content-epilogue
+  | element anim:animateColor {
+      common-anim-target-attlist,
+      common-anim-named-target-attlist,
+      common-anim-add-accum-attlist,
+      common-anim-values-attlist,
+      common-anim-spline-mode-attlist,
+      common-spline-anim-value-attlist,
+      anim-animate-color-attlist,
+      common-timing-attlist
     }
-  | element office:chart {
-      office-chart-attlist,
-      office-chart-content-prelude,
-      office-chart-content-main,
-      office-chart-content-epilogue
+  | element anim:animateTransform {
+      common-anim-target-attlist,
+      common-anim-named-target-attlist,
+      common-anim-add-accum-attlist,
+      common-anim-values-attlist,
+      anim-animate-transform-attlist,
+      common-timing-attlist
     }
-  | element office:image {
-      office-image-attlist,
-      office-image-content-prelude,
-      office-image-content-main,
-      office-image-content-epilogue
+  | element anim:transitionFilter {
+      common-anim-target-attlist,
+      common-anim-add-accum-attlist,
+      common-anim-values-attlist,
+      common-anim-spline-mode-attlist,
+      anim-transition-filter-attlist,
+      common-timing-attlist
     }
-  | office-database
-office-text-content-prelude =
-  office-forms, text-tracked-changes, text-decls, table-decls
-office-text-content-main =
-  text-content*
-  | (text-page-sequence, (shape)*)
-text-content =
-  text-h
-  | text-p
-  | text-list
-  | text-numbered-paragraph
-  | table-table
-  | text-section
-  | text-soft-page-break
-  | text-table-of-content
-  | text-illustration-index
-  | text-table-index
-  | text-object-index
-  | text-user-index
-  | text-alphabetical-index
-  | text-bibliography
-  | shape
-  | change-marks
-office-text-content-epilogue = table-functions
-office-text-attlist =
-  attribute text:global { boolean }?
-  & attribute text:use-soft-page-breaks { boolean }?
-office-drawing-attlist = empty
-office-drawing-content-prelude = text-decls, table-decls
-office-drawing-content-main = draw-page*
-office-drawing-content-epilogue = table-functions
-office-presentation-attlist = empty
-office-presentation-content-prelude =
-  text-decls, table-decls, presentation-decls
-office-presentation-content-main = draw-page*
-office-presentation-content-epilogue =
-  presentation-settings, table-functions
-office-spreadsheet-content-prelude =
-  table-tracked-changes?, text-decls, table-decls
-table-decls =
-  table-calculation-settings?,
-  table-content-validations?,
-  table-label-ranges?
-office-spreadsheet-content-main = table-table*
-office-spreadsheet-content-epilogue = table-functions
-table-functions =
-  table-named-expressions?,
-  table-database-ranges?,
-  table-data-pilot-tables?,
-  table-consolidation?,
-  table-dde-links?
-office-chart-attlist = empty
-office-chart-content-prelude = text-decls, table-decls
-office-chart-content-main = chart-chart
-office-chart-content-epilogue = table-functions
-office-image-attlist = empty
-office-image-content-prelude = empty
-office-image-content-main = draw-frame
-office-image-content-epilogue = empty
-office-settings = element office:settings { config-config-item-set+ }?
-config-config-item-set =
-  element config:config-item-set {
-    config-config-item-set-attlist, config-items
-  }
-config-items =
-  (config-config-item
-   | config-config-item-set
-   | config-config-item-map-named
-   | config-config-item-map-indexed)+
-config-config-item-set-attlist = attribute config:name { \string }
-config-config-item =
-  element config:config-item { config-config-item-attlist, text }
-config-config-item-attlist =
-  attribute config:name { \string }
-  & attribute config:type {
-      "boolean"
-      | "short"
-      | "int"
-      | "long"
-      | "double"
-      | "string"
-      | "datetime"
-      | "base64Binary"
+  | element anim:par {
+      common-anim-attlist,
+      common-timing-attlist,
+      common-endsync-timing-attlist,
+      animation-element*
     }
-config-config-item-map-indexed =
-  element config:config-item-map-indexed {
-    config-config-item-map-indexed-attlist,
-    config-config-item-map-entry+
-  }
-config-config-item-map-indexed-attlist =
-  attribute config:name { \string }
-config-config-item-map-entry =
-  element config:config-item-map-entry {
-    config-config-item-map-entry-attlist, config-items
-  }
-config-config-item-map-entry-attlist =
-  attribute config:name { \string }?
-config-config-item-map-named =
-  element config:config-item-map-named {
-    config-config-item-map-named-attlist, config-config-item-map-entry+
-  }
-config-config-item-map-named-attlist = attribute config:name { \string }
-office-scripts =
-  element office:scripts { office-script*, office-event-listeners? }?
-office-script =
-  element office:script {
-    office-script-attlist,
-    mixed { anyElements }
-  }
-office-script-attlist = attribute script:language { \string }
-office-font-face-decls =
-  element office:font-face-decls { style-font-face* }?
-office-styles =
-  element office:styles {
-    styles
-    & style-default-style*
-    & style-default-page-layout?
-    & text-outline-style?
-    & text-notes-configuration*
-    & text-bibliography-configuration?
-    & text-linenumbering-configuration?
-    & draw-gradient*
-    & svg-linearGradient*
-    & svg-radialGradient*
-    & draw-hatch*
-    & draw-fill-image*
-    & draw-marker*
-    & draw-stroke-dash*
-    & draw-opacity*
-    & style-presentation-page-layout*
-    & table-table-template*
-  }?
-office-automatic-styles =
-  element office:automatic-styles { styles & style-page-layout* }?
-office-master-styles =
-  element office:master-styles {
-    style-master-page* & style-handout-master? & draw-layer-set?
-  }?
-styles =
-  style-style*
-  & text-list-style*
-  & number-number-style*
-  & number-currency-style*
-  & number-percentage-style*
-  & number-date-style*
-  & number-time-style*
-  & number-boolean-style*
-  & number-text-style*
-office-meta-data =
-  element meta:generator { \string }
-  | element dc:title { \string }
-  | element dc:description { \string }
-  | element dc:subject { \string }
-  | element meta:keyword { \string }
-  | element meta:initial-creator { \string }
-  | dc-creator
-  | element meta:printed-by { \string }
-  | element meta:creation-date { dateTime }
-  | dc-date
-  | element meta:print-date { dateTime }
-  | element meta:template {
-      attribute xlink:type { "simple" },
-      attribute xlink:href { anyIRI },
-      attribute xlink:actuate { "onRequest" }?,
-      attribute xlink:title { \string }?,
-      attribute meta:date { dateTime }?
-    }
-  | element meta:auto-reload {
-      (attribute xlink:type { "simple" },
-       attribute xlink:href { anyIRI },
-       attribute xlink:show { "replace" }?,
-       attribute xlink:actuate { "onLoad" }?)?,
-      attribute meta:delay { duration }?
+  | element anim:seq {
+      common-anim-attlist,
+      common-endsync-timing-attlist,
+      common-timing-attlist,
+      animation-element*
     }
-  | element meta:hyperlink-behaviour {
-      attribute office:target-frame-name { targetFrameName }?,
-      attribute xlink:show { "new" | "replace" }?
+  | element anim:iterate {
+      common-anim-attlist,
+      anim-iterate-attlist,
+      common-timing-attlist,
+      common-endsync-timing-attlist,
+      animation-element*
     }
-  | element dc:language { language }
-  | element meta:editing-cycles { nonNegativeInteger }
-  | element meta:editing-duration { duration }
-  | element meta:document-statistic {
-      attribute meta:page-count { nonNegativeInteger }?,
-      attribute meta:table-count { nonNegativeInteger }?,
-      attribute meta:draw-count { nonNegativeInteger }?,
-      attribute meta:image-count { nonNegativeInteger }?,
-      attribute meta:ole-object-count { nonNegativeInteger }?,
-      attribute meta:object-count { nonNegativeInteger }?,
-      attribute meta:paragraph-count { nonNegativeInteger }?,
-      attribute meta:word-count { nonNegativeInteger }?,
-      attribute meta:character-count { nonNegativeInteger }?,
-      attribute meta:frame-count { nonNegativeInteger }?,
-      attribute meta:sentence-count { nonNegativeInteger }?,
-      attribute meta:syllable-count { nonNegativeInteger }?,
-      attribute meta:non-whitespace-character-count {
-        nonNegativeInteger
-      }?,
-      attribute meta:row-count { nonNegativeInteger }?,
-      attribute meta:cell-count { nonNegativeInteger }?
+  | element anim:audio {
+      common-anim-attlist,
+      anim-audio-attlist,
+      common-basic-timing-attlist
     }
-  | element meta:user-defined {
-      attribute meta:name { \string },
-      ((attribute meta:value-type { "float" },
-        double)
-       | (attribute meta:value-type { "date" },
-          dateOrDateTime)
-       | (attribute meta:value-type { "time" },
-          duration)
-       | (attribute meta:value-type { "boolean" },
-          boolean)
-       | (attribute meta:value-type { "string" },
-          \string)
-       | text)
+  | element anim:command {
+      common-anim-attlist,
+      anim-command-attlist,
+      common-begin-end-timing-attlist,
+      common-anim-target-attlist,
+      element anim:param {
+        attribute anim:name { \string },
+        attribute anim:value { \string }
+      }*
     }
-dc-creator = element dc:creator { \string }
-dc-date = element dc:date { dateTime }
-text-h =
-  element text:h {
-    heading-attrs,
-    paragraph-attrs,
-    text-number?,
-    paragraph-content-or-hyperlink*
+any-date =
+  number-day
+  | number-month
+  | number-year
+  | number-era
+  | number-day-of-week
+  | number-week-of-year
+  | number-quarter
+  | number-hours
+  | number-am-pm
+  | number-minutes
+  | number-seconds
+any-number = number-number | number-scientific-number | number-fraction
+any-time = number-hours | number-am-pm | number-minutes | number-seconds
+anyAttListOrElements =
+  attribute * { text }*,
+  anyElements
+anyElements =
+  element * {
+    mixed { anyAttListOrElements }
+  }*
+anyIRI =
+  xsd:anyURI
+  >> dc:description [
+       "An IRI-reference as defined in [RFC3987]. See ODF 1.3 Part 3 section 
18.3."
+     ]
+anyURI = xsd:anyURI
+base64Binary = xsd:base64Binary
+boolean = "true" | "false"
+borderWidths = list { positiveLength, positiveLength, positiveLength }
+bound-column = attribute form:bound-column { \string }?
+button-type = attribute form:button-type { types }?
+cellAddress =
+  xsd:string {
+    pattern = "($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+"
   }
-heading-attrs =
-  attribute text:outline-level { positiveInteger }
-  & attribute text:restart-numbering { boolean }?
-  & attribute text:start-value { nonNegativeInteger }?
-  & attribute text:is-list-header { boolean }?
-text-number = element text:number { \string }
-text-p =
-  element text:p { paragraph-attrs, paragraph-content-or-hyperlink* }
-paragraph-attrs =
-  attribute text:style-name { styleNameRef }?
-  & attribute text:class-names { styleNameRefs }?
-  & attribute text:cond-style-name { styleNameRef }?
-  & (xml-id,
-     attribute text:id { NCName }?)?
-  & common-in-content-meta-attlist?
-text-page-sequence = element text:page-sequence { text-page+ }
-text-page = element text:page { text-page-attlist, empty }
-text-page-attlist = attribute text:master-page-name { styleNameRef }
-text-list =
-  element text:list {
-    text-list-attr, text-list-header?, text-list-item*
+cellRangeAddress =
+  xsd:string {
+    pattern =
+      "($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+(:($?([^\. 
']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+)?"
   }
-text-list-attr =
-  attribute text:style-name { styleNameRef }?
-  & attribute text:continue-numbering { boolean }?
-  & attribute text:continue-list { IDREF }?
-  & xml-id?
-text-list-item =
-  element text:list-item { text-list-item-attr, text-list-item-content }
-text-list-item-content =
-  text-number?, (text-p | text-h | text-list | text-soft-page-break)*
-text-list-item-attr =
-  attribute text:start-value { nonNegativeInteger }?
-  & attribute text:style-override { styleNameRef }?
-  & xml-id?
-text-list-header =
-  element text:list-header {
-    text-list-header-attr, text-list-item-content
+  | xsd:string {
+      pattern =
+        "($?([^\. ']+|'([^']|'')+'))?\.$?[0-9]+:($?([^\. 
']+|'([^']|'')+'))?\.$?[0-9]+"
+    }
+  | xsd:string {
+      pattern =
+        "($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+:($?([^\. 
']+|'([^']|'')+'))?\.$?[A-Z]+"
+    }
+cellRangeAddressList =
+  xsd:string
+  >> dc:description [
+       'Value is a space separated list of "cellRangeAddress" patterns'
+     ]
+change-mark-attr = attribute text:change-id { IDREF }
+change-marks =
+  element text:change { change-mark-attr }
+  | element text:change-start { change-mark-attr }
+  | element text:change-end { change-mark-attr }
+character = xsd:string { length = "1" }
+chart-axis =
+  element chart:axis {
+    chart-axis-attlist, chart-title?, chart-categories?, chart-grid*
   }
-text-list-header-attr = xml-id?
-text-numbered-paragraph =
-  element text:numbered-paragraph {
-    text-numbered-paragraph-attr, text-number?, (text-p | text-h)
+chart-axis-attlist =
+  attribute chart:dimension { chart-dimension }
+  & attribute chart:name { \string }?
+  & attribute chart:style-name { styleNameRef }?
+chart-categories =
+  element chart:categories {
+    attribute table:cell-range-address { cellRangeAddressList }?
   }
-text-numbered-paragraph-attr =
-  attribute text:list-id { NCName }
-  & attribute text:level { positiveInteger }?
-  & (attribute text:style-name { styleNameRef },
-     attribute text:continue-numbering { boolean },
-     attribute text:start-value { nonNegativeInteger })?
+chart-chart =
+  element chart:chart {
+    chart-chart-attlist,
+    chart-title?,
+    chart-subtitle?,
+    chart-footer?,
+    chart-legend?,
+    chart-plot-area,
+    shape*,
+    # https://issues.oasis-open.org/browse/OFFICE-2123
+    table-table?
+  }
+chart-chart-attlist =
+  attribute chart:class { namespacedToken }
+  & common-draw-size-attlist
+  & attribute chart:column-mapping { \string }?
+  & attribute chart:row-mapping { \string }?
+  & attribute chart:style-name { styleNameRef }?
+  & (attribute xlink:type { "simple" },
+     attribute xlink:href { anyIRI })?
   & xml-id?
-text-section =
-  element text:section {
-    text-section-attlist,
-    (text-section-source | text-section-source-dde | empty),
-    text-content*
+chart-coordinate-region =
+  element chart:coordinate-region {
+    chart-coordinate-region-attlist, empty
   }
-text-section-attlist =
-  common-section-attlist
-  & (attribute text:display { "true" | "none" }
-     | (attribute text:display { "condition" },
-        attribute text:condition { \string })
+chart-coordinate-region-attlist =
+  common-draw-position-attlist, common-draw-size-attlist
+# https://issues.oasis-open.org/browse/OFFICE-3928
+chart-data-label =
+  element chart:data-label { chart-data-label-attlist, text-p? }
+chart-data-label-attlist =
+  common-draw-position-attlist
+  & attribute chart:style-name { styleNameRef }?
+chart-data-point =
+  element chart:data-point {
+    chart-data-point-attlist, chart-data-label?
+  }
+chart-data-point-attlist =
+  attribute chart:repeated { positiveInteger }?
+  & attribute chart:style-name { styleNameRef }?
+  & xml-id?
+chart-dimension = "x" | "y" | "z"
+chart-domain =
+  element chart:domain {
+    attribute table:cell-range-address { cellRangeAddressList }?
+  }
+chart-equation =
+  element chart:equation { chart-equation-attlist, text-p? }
+chart-equation-attlist =
+  attribute chart:automatic-content { boolean }?
+  & attribute chart:display-r-square { boolean }?
+  & attribute chart:display-equation { boolean }?
+  & common-draw-position-attlist
+  & attribute chart:style-name { styleNameRef }?
+chart-error-indicator =
+  element chart:error-indicator { chart-error-indicator-attlist, empty }
+chart-error-indicator-attlist =
+  attribute chart:style-name { styleNameRef }?
+  & attribute chart:dimension { chart-dimension }
+chart-floor = element chart:floor { chart-floor-attlist, empty }
+chart-floor-attlist =
+  attribute svg:width { length }?
+  & attribute chart:style-name { styleNameRef }?
+chart-footer = element chart:footer { chart-title-attlist, text-p? }
+chart-grid = element chart:grid { chart-grid-attlist }
+chart-grid-attlist =
+  attribute chart:class { "major" | "minor" }?
+  & attribute chart:style-name { styleNameRef }?
+chart-legend = element chart:legend { chart-legend-attlist, text-p? }
+chart-legend-attlist =
+  ((attribute chart:legend-position {
+      "start" | "end" | "top" | "bottom"
+    },
+    attribute chart:legend-align { "start" | "center" | "end" }?)
+   | attribute chart:legend-position {
+       "top-start" | "bottom-start" | "top-end" | "bottom-end"
+     }
+   | empty)
+  & common-draw-position-attlist
+  & (attribute style:legend-expansion { "wide" | "high" | "balanced" }
+     | (attribute style:legend-expansion { "custom" },
+        attribute style:legend-expansion-aspect-ratio { double },
+        common-draw-size-attlist
+        # https://issues.oasis-open.org/browse/OFFICE-3883
+        )
      | empty)
-common-section-attlist =
-  attribute text:style-name { styleNameRef }?
-  & attribute text:name { \string }
-  & attribute text:protected { boolean }?
-  & attribute text:protection-key { \string }?
-  & attribute text:protection-key-digest-algorithm { anyIRI }?
+  & attribute chart:style-name { styleNameRef }?
+chart-mean-value =
+  element chart:mean-value { chart-mean-value-attlist, empty }
+chart-mean-value-attlist = attribute chart:style-name { styleNameRef }?
+chart-plot-area =
+  element chart:plot-area {
+    chart-plot-area-attlist,
+    # https://issues.oasis-open.org/browse/OFFICE-3928
+    chart-coordinate-region?,
+    dr3d-light*,
+    chart-axis*,
+    chart-series*,
+    chart-stock-gain-marker?,
+    chart-stock-loss-marker?,
+    chart-stock-range-line?,
+    chart-wall?,
+    chart-floor?
+  }
+chart-plot-area-attlist =
+  common-draw-position-attlist
+  & common-draw-size-attlist
+  & attribute chart:style-name { styleNameRef }?
+  & attribute table:cell-range-address { cellRangeAddressList }?
+  & attribute chart:data-source-has-labels {
+      "none" | "row" | "column" | "both"
+    }?
+  & dr3d-scene-attlist
+  & common-dr3d-transform-attlist
   & xml-id?
-text-section-source =
-  element text:section-source { text-section-source-attr }
-text-section-source-attr =
-  (attribute xlink:type { "simple" },
-   attribute xlink:href { anyIRI },
-   attribute xlink:show { "embed" }?)?
-  & attribute text:section-name { \string }?
-  & attribute text:filter-name { \string }?
-text-section-source-dde = office-dde-source
-text-tracked-changes =
-  element text:tracked-changes {
-    text-tracked-changes-attr, text-changed-region*
-  }?
-text-tracked-changes-attr = attribute text:track-changes { boolean }?
-text-changed-region =
-  element text:changed-region {
-    text-changed-region-attr, text-changed-region-content
+chart-regression-curve =
+  element chart:regression-curve {
+    chart-regression-curve-attlist, chart-equation?
   }
-text-changed-region-attr =
-  xml-id,
-  attribute text:id { NCName }?
-text-changed-region-content =
-  element text:insertion { office-change-info }
-  | element text:deletion { office-change-info, text-content* }
-  | element text:format-change { office-change-info }
-change-marks =
-  element text:change { change-mark-attr }
-  | element text:change-start { change-mark-attr }
-  | element text:change-end { change-mark-attr }
-change-mark-attr = attribute text:change-id { IDREF }
-text-soft-page-break = element text:soft-page-break { empty }
-text-decls =
-  element text:variable-decls { text-variable-decl* }?,
-  element text:sequence-decls { text-sequence-decl* }?,
-  element text:user-field-decls { text-user-field-decl* }?,
-  element text:dde-connection-decls { text-dde-connection-decl* }?,
-  text-alphabetical-index-auto-mark-file?
-paragraph-content-or-hyperlink = paragraph-content | text-a
-paragraph-content =
-  text
-  | element text:s {
-      attribute text:c { nonNegativeInteger }?
+chart-regression-curve-attlist =
+  attribute chart:style-name { styleNameRef }?
+chart-series =
+  element chart:series {
+    chart-series-attlist,
+    chart-domain*,
+    chart-mean-value?,
+    chart-regression-curve*,
+    chart-error-indicator*,
+    chart-data-point*,
+    chart-data-label?
+  }
+chart-series-attlist =
+  attribute chart:values-cell-range-address { cellRangeAddressList }?
+  & attribute chart:label-cell-address { cellRangeAddressList }?
+  & attribute chart:class { namespacedToken }?
+  & attribute chart:attached-axis { \string }?
+  & attribute chart:style-name { styleNameRef }?
+  & xml-id?
+chart-stock-gain-marker =
+  element chart:stock-gain-marker { common-stock-marker-attlist }
+chart-stock-loss-marker =
+  element chart:stock-loss-marker { common-stock-marker-attlist }
+chart-stock-range-line =
+  element chart:stock-range-line { common-stock-marker-attlist }
+chart-subtitle = element chart:subtitle { chart-title-attlist, text-p? }
+chart-title = element chart:title { chart-title-attlist, text-p? }
+chart-title-attlist =
+  attribute table:cell-range { cellRangeAddressList }?
+  & common-draw-position-attlist
+  & attribute chart:style-name { styleNameRef }?
+chart-wall = element chart:wall { chart-wall-attlist, empty }
+chart-wall-attlist =
+  attribute svg:width { length }?
+  & attribute chart:style-name { styleNameRef }?
+clipShape =
+  xsd:string {
+    pattern =
+      "rect\([ 
]*((-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)))|(auto))([ ]*,[ 
]*((-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc))))|(auto)){3}[ ]*\)"
+  }
+color = xsd:string { pattern = "#[0-9a-fA-F]{6}" }
+column-controls =
+  element form:text { form-text-attlist, common-form-control-content }
+  | element form:textarea {
+      form-textarea-attlist, common-form-control-content, text-p*
     }
-  | element text:tab { text-tab-attr }
-  | element text:line-break { empty }
-  | text-soft-page-break
-  | element text:span {
-      attribute text:style-name { styleNameRef }?,
-      attribute text:class-names { styleNameRefs }?,
-      paragraph-content-or-hyperlink*
+  | element form:formatted-text {
+      form-formatted-text-attlist, common-form-control-content
     }
-  | element text:meta {
-      text-meta-attlist, paragraph-content-or-hyperlink*
+  | element form:number {
+      form-number-attlist,
+      common-numeric-control-attlist,
+      common-form-control-content,
+      common-linked-cell,
+      common-spin-button,
+      common-repeat,
+      common-delay-for-repeat
     }
-  | (text-bookmark | text-bookmark-start | text-bookmark-end)
-  | element text:reference-mark {
-      attribute text:name { \string }
+  | element form:date {
+      form-date-attlist,
+      common-numeric-control-attlist,
+      common-form-control-content,
+      common-linked-cell,
+      common-spin-button,
+      common-repeat,
+      common-delay-for-repeat
     }
-  | (element text:reference-mark-start {
-       attribute text:name { \string }
-     }
-     | element text:reference-mark-end {
-         attribute text:name { \string }
-       })
-  | element text:note {
-      text-note-class,
-      attribute text:id { \string }?,
-      element text:note-citation {
-        attribute text:label { \string }?,
-        text
-      },
-      element text:note-body { text-content* }
-    }
-  | element text:ruby {
-      attribute text:style-name { styleNameRef }?,
-      element text:ruby-base { paragraph-content-or-hyperlink* },
-      element text:ruby-text {
-        attribute text:style-name { styleNameRef }?,
-        text
-      }
-    }
-  | (office-annotation | office-annotation-end)
-  | change-marks
-  | shape
-  | element text:date { text-date-attlist, text }
-  | element text:time { text-time-attlist, text }
-  | element text:page-number { text-page-number-attlist, text }
-  | element text:page-continuation {
-      text-page-continuation-attlist, text
-    }
-  | element text:sender-firstname { common-field-fixed-attlist, text }
-  | element text:sender-lastname { common-field-fixed-attlist, text }
-  | element text:sender-initials { common-field-fixed-attlist, text }
-  | element text:sender-title { common-field-fixed-attlist, text }
-  | element text:sender-position { common-field-fixed-attlist, text }
-  | element text:sender-email { common-field-fixed-attlist, text }
-  | element text:sender-phone-private {
-      common-field-fixed-attlist, text
-    }
-  | element text:sender-fax { common-field-fixed-attlist, text }
-  | element text:sender-company { common-field-fixed-attlist, text }
-  | element text:sender-phone-work { common-field-fixed-attlist, text }
-  | element text:sender-street { common-field-fixed-attlist, text }
-  | element text:sender-city { common-field-fixed-attlist, text }
-  | element text:sender-postal-code { common-field-fixed-attlist, text }
-  | element text:sender-country { common-field-fixed-attlist, text }
-  | element text:sender-state-or-province {
-      common-field-fixed-attlist, text
-    }
-  | element text:author-name { common-field-fixed-attlist, text }
-  | element text:author-initials { common-field-fixed-attlist, text }
-  | element text:chapter { text-chapter-attlist, text }
-  | element text:file-name { text-file-name-attlist, text }
-  | element text:template-name { text-template-name-attlist, text }
-  | element text:sheet-name { text }
-  | element text:variable-set {
-      (common-field-name-attlist
-       & common-field-formula-attlist
-       & common-value-and-type-attlist
-       & common-field-display-value-none-attlist
-       & common-field-data-style-name-attlist),
-      text
-    }
-  | element text:variable-get {
-      (common-field-name-attlist
-       & common-field-display-value-formula-attlist
-       & common-field-data-style-name-attlist),
-      text
-    }
-  | element text:variable-input {
-      (common-field-name-attlist
-       & common-field-description-attlist
-       & common-value-type-attlist
-       & common-field-display-value-none-attlist
-       & common-field-data-style-name-attlist),
-      text
-    }
-  | element text:user-field-get {
-      (common-field-name-attlist
-       & common-field-display-value-formula-none-attlist
-       & common-field-data-style-name-attlist),
-      text
-    }
-  | element text:user-field-input {
-      (common-field-name-attlist
-       & common-field-description-attlist
-       & common-field-data-style-name-attlist),
-      text
-    }
-  | element text:sequence {
-      (common-field-name-attlist
-       & common-field-formula-attlist
-       & common-field-num-format-attlist
-       & text-sequence-ref-name),
-      text
-    }
-  | element text:expression {
-      (common-field-formula-attlist
-       & common-value-and-type-attlist?
-       & common-field-display-value-formula-attlist
-       & common-field-data-style-name-attlist),
-      text
-    }
-  | element text:text-input { common-field-description-attlist, text }
-  | element text:initial-creator { common-field-fixed-attlist, text }
-  | element text:creation-date {
-      (common-field-fixed-attlist
-       & common-field-data-style-name-attlist
-       & attribute text:date-value { dateOrDateTime }?),
-      text
-    }
-  | element text:creation-time {
-      (common-field-fixed-attlist
-       & common-field-data-style-name-attlist
-       & attribute text:time-value { timeOrDateTime }?),
-      text
-    }
-  | element text:description { common-field-fixed-attlist, text }
-  | element text:user-defined {
-      (common-field-fixed-attlist
-       & attribute text:name { \string }
-       & common-field-data-style-name-attlist
-       & attribute office:value { double }?
-       & attribute office:date-value { dateOrDateTime }?
-       & attribute office:time-value { duration }?
-       & attribute office:boolean-value { boolean }?
-       & attribute office:string-value { \string }?),
-      text
-    }
-  | element text:print-time {
-      (common-field-fixed-attlist
-       & common-field-data-style-name-attlist
-       & attribute text:time-value { time }?),
-      text
-    }
-  | element text:print-date {
-      (common-field-fixed-attlist
-       & common-field-data-style-name-attlist
-       & attribute text:date-value { date }?),
-      text
-    }
-  | element text:printed-by { common-field-fixed-attlist, text }
-  | element text:title { common-field-fixed-attlist, text }
-  | element text:subject { common-field-fixed-attlist, text }
-  | element text:keywords { common-field-fixed-attlist, text }
-  | element text:editing-cycles { common-field-fixed-attlist, text }
-  | element text:editing-duration {
-      (common-field-fixed-attlist
-       & common-field-data-style-name-attlist
-       & attribute text:duration { duration }?),
-      text
-    }
-  | element text:modification-time {
-      (common-field-fixed-attlist
-       & common-field-data-style-name-attlist
-       & attribute text:time-value { time }?),
-      text
-    }
-  | element text:modification-date {
-      (common-field-fixed-attlist
-       & common-field-data-style-name-attlist
-       & attribute text:date-value { date }?),
-      text
-    }
-  | element text:creator { common-field-fixed-attlist, text }
-  | element text:page-count
-            | text:paragraph-count
-            | text:word-count
-            | text:character-count
-            | text:table-count
-            | text:image-count
-            | text:object-count {
-      common-field-num-format-attlist, text
-    }
-  | element text:database-display {
-      text-database-display-attlist, text
-    }
-  | element text:database-next { text-database-next-attlist }
-  | element text:database-row-select {
-      text-database-row-select-attlist
-    }
-  | element text:database-row-number {
-      (common-field-database-table
-       & common-field-num-format-attlist
-       & attribute text:value { nonNegativeInteger }?),
-      text
-    }
-  | element text:database-name { common-field-database-table, text }
-  | element text:page-variable-set {
-      text-set-page-variable-attlist, text
-    }
-  | element text:page-variable-get {
-      text-get-page-variable-attlist, text
-    }
-  | element text:placeholder { text-placeholder-attlist, text }
-  | element text:conditional-text {
-      text-conditional-text-attlist, text
-    }
-  | element text:hidden-text { text-hidden-text-attlist, text }
-  | element text:reference-ref | text:bookmark-ref {
-      text-common-ref-content & text-bookmark-ref-content
-    }
-  | element text:note-ref {
-      text-common-ref-content & text-note-ref-content
-    }
-  | element text:sequence-ref {
-      text-common-ref-content & text-sequence-ref-content
-    }
-  | element text:script {
-      ((attribute xlink:type { "simple" },
-        attribute xlink:href { anyIRI })
-       | text)
-      & attribute script:language { \string }?
-    }
-  | element text:execute-macro {
-      attribute text:name { \string }?,
-      office-event-listeners?,
-      text
-    }
-  | element text:hidden-paragraph {
-      text-hidden-paragraph-attlist, text
-    }
-  | element text:dde-connection {
-      attribute text:connection-name { \string },
-      text
-    }
-  | element text:measure {
-      attribute text:kind { "value" | "unit" | "gap" },
-      text
-    }
-  | element text:table-formula {
-      (common-field-formula-attlist
-       & common-field-display-value-formula-attlist
-       & common-field-data-style-name-attlist),
-      text
-    }
-  | element text:meta-field {
-      text-meta-field-attlist, paragraph-content-or-hyperlink*
+  | element form:time {
+      form-time-attlist,
+      common-numeric-control-attlist,
+      common-form-control-content,
+      common-linked-cell,
+      common-spin-button,
+      common-repeat,
+      common-delay-for-repeat
     }
-  | element text:toc-mark-start { text-toc-mark-start-attrs }
-  | element text:toc-mark-end { text-id }
-  | element text:toc-mark {
-      attribute text:string-value { \string },
-      text-outline-level
+  | element form:combobox {
+      form-combobox-attlist, common-form-control-content, form-item*
     }
-  | element text:user-index-mark-start {
-      text-id, text-outline-level, text-index-name
+  | element form:listbox {
+      form-listbox-attlist, common-form-control-content, form-option*
     }
-  | element text:user-index-mark-end { text-id }
-  | element text:user-index-mark {
-      attribute text:string-value { \string },
-      text-outline-level,
-      text-index-name
+  | element form:checkbox {
+      form-checkbox-attlist, common-form-control-content
     }
-  | element text:alphabetical-index-mark-start {
-      text-id, text-alphabetical-index-mark-attrs
-    }
-  | element text:alphabetical-index-mark-end { text-id }
-  | element text:alphabetical-index-mark {
-      attribute text:string-value { \string },
-      text-alphabetical-index-mark-attrs
-    }
-  | element text:bibliography-mark {
-      attribute text:bibliography-type { text-bibliography-types },
-      attribute text:identifier
-                | text:address
-                | text:annote
-                | text:author
-                | text:booktitle
-                | text:chapter
-                | text:edition
-                | text:editor
-                | text:howpublished
-                | text:institution
-                | text:journal
-                | text:month
-                | text:note
-                | text:number
-                | text:organizations
-                | text:pages
-                | text:publisher
-                | text:school
-                | text:series
-                | text:title
-                | text:report-type
-                | text:volume
-                | text:year
-                | text:url
-                | text:custom1
-                | text:custom2
-                | text:custom3
-                | text:custom4
-                | text:custom5
-                | text:isbn
-                | text:issn { \string }*,
-      text
-    }
-  | element presentation:header { empty }
-  | element presentation:footer { empty }
-  | element presentation:date-time { empty }
-text-tab-attr = attribute text:tab-ref { nonNegativeInteger }?
-text-a =
-  element text:a {
-    text-a-attlist, office-event-listeners?, paragraph-content*
-  }
-text-a-attlist =
-  attribute office:name { \string }?
-  & attribute office:title { \string }?
-  & attribute xlink:type { "simple" }
-  & attribute xlink:href { anyIRI }
-  & attribute xlink:actuate { "onRequest" }?
-  & attribute office:target-frame-name { targetFrameName }?
-  & attribute xlink:show { "new" | "replace" }?
-  & attribute text:style-name { styleNameRef }?
-  & attribute text:visited-style-name { styleNameRef }?
-text-meta-attlist = common-in-content-meta-attlist? & xml-id?
-text-bookmark = element text:bookmark { text-bookmark-attlist, empty }
-text-bookmark-start =
-  element text:bookmark-start { text-bookmark-start-attlist, empty }
-text-bookmark-end =
-  element text:bookmark-end { text-bookmark-end-attlist, empty }
-text-bookmark-attlist =
-  attribute text:name { \string }
-  & xml-id?
-text-bookmark-start-attlist =
-  attribute text:name { \string }
-  & xml-id?
-  & common-in-content-meta-attlist?
-text-bookmark-end-attlist = attribute text:name { \string }
-text-note-class = attribute text:note-class { "footnote" | "endnote" }
-text-date-attlist =
-  (common-field-fixed-attlist & common-field-data-style-name-attlist)
-  & attribute text:date-value { dateOrDateTime }?
-  & attribute text:date-adjust { duration }?
-text-time-attlist =
-  (common-field-fixed-attlist & common-field-data-style-name-attlist)
-  & attribute text:time-value { timeOrDateTime }?
-  & attribute text:time-adjust { duration }?
-text-page-number-attlist =
-  (common-field-num-format-attlist & common-field-fixed-attlist)
-  & attribute text:page-adjust { integer }?
-  & attribute text:select-page { "previous" | "current" | "next" }?
-text-page-continuation-attlist =
-  attribute text:select-page { "previous" | "next" }
-  & attribute text:string-value { \string }?
-text-chapter-attlist =
-  attribute text:display {
-    "name"
-    | "number"
-    | "number-and-name"
-    | "plain-number-and-name"
-    | "plain-number"
-  }
-  & attribute text:outline-level { nonNegativeInteger }
-text-file-name-attlist =
-  attribute text:display {
-    "full" | "path" | "name" | "name-and-extension"
+common-anim-add-accum-attlist =
+  attribute smil:accumulate { "none" | "sum" }?
+  & attribute smil:additive { "replace" | "sum" }?
+common-anim-attlist =
+  attribute presentation:node-type {
+    "default"
+    | "on-click"
+    | "with-previous"
+    | "after-previous"
+    | "timing-root"
+    | "main-sequence"
+    | "interactive-sequence"
   }?
-  & common-field-fixed-attlist
-text-template-name-attlist =
-  attribute text:display {
-    "full" | "path" | "name" | "name-and-extension" | "area" | "title"
+  & attribute presentation:preset-id { \string }?
+  & attribute presentation:preset-sub-type { \string }?
+  & attribute presentation:preset-class {
+      "custom"
+      | "entrance"
+      | "exit"
+      | "emphasis"
+      | "motion-path"
+      | "ole-action"
+      | "media-call"
+    }?
+  & attribute presentation:master-element { IDREF }?
+  & attribute presentation:group-id { \string }?
+  & (xml-id,
+     attribute anim:id { NCName }?)?
+common-anim-named-target-attlist =
+  attribute smil:attributeName { \string }
+common-anim-set-values-attlist = attribute smil:to { \string }?
+common-anim-spline-mode-attlist =
+  attribute smil:calcMode {
+    "discrete" | "linear" | "paced" | "spline"
   }?
-text-variable-decl =
-  element text:variable-decl {
-    common-field-name-attlist, common-value-type-attlist
-  }
-text-user-field-decl =
-  element text:user-field-decl {
-    common-field-name-attlist,
-    common-field-formula-attlist?,
-    common-value-and-type-attlist
-  }
-text-sequence-decl =
-  element text:sequence-decl { text-sequence-decl-attlist }
-text-sequence-decl-attlist =
-  common-field-name-attlist
-  & attribute text:display-outline-level { nonNegativeInteger }
-  & attribute text:separation-character { character }?
-text-sequence-ref-name = attribute text:ref-name { \string }?
-common-field-database-table =
-  common-field-database-table-attlist, common-field-database-name
-common-field-database-name =
-  attribute text:database-name { \string }?
-  | form-connection-resource
-common-field-database-table-attlist =
-  attribute text:table-name { \string }
-  & attribute text:table-type { "table" | "query" | "command" }?
-text-database-display-attlist =
-  common-field-database-table
-  & common-field-data-style-name-attlist
-  & attribute text:column-name { \string }
-text-database-next-attlist =
-  common-field-database-table
-  & attribute text:condition { \string }?
-text-database-row-select-attlist =
-  common-field-database-table
-  & attribute text:condition { \string }?
-  & attribute text:row-number { nonNegativeInteger }?
-text-set-page-variable-attlist =
-  attribute text:active { boolean }?
-  & attribute text:page-adjust { integer }?
-text-get-page-variable-attlist = common-field-num-format-attlist
-text-placeholder-attlist =
-  attribute text:placeholder-type {
-    "text" | "table" | "text-box" | "image" | "object"
-  }
-  & common-field-description-attlist
-text-conditional-text-attlist =
-  attribute text:condition { \string }
-  & attribute text:string-value-if-true { \string }
-  & attribute text:string-value-if-false { \string }
-  & attribute text:current-value { boolean }?
-text-hidden-text-attlist =
-  attribute text:condition { \string }
-  & attribute text:string-value { \string }
-  & attribute text:is-hidden { boolean }?
-text-common-ref-content =
-  text
-  & attribute text:ref-name { \string }?
-text-bookmark-ref-content =
-  attribute text:reference-format {
-    common-ref-format-values
-    | "number-no-superior"
-    | "number-all-superior"
-    | "number"
+common-anim-target-attlist =
+  attribute smil:targetElement { IDREF }?
+  & attribute anim:sub-item { \string }?
+common-anim-values-attlist =
+  attribute smil:values { \string }?
+  & attribute anim:formula { \string }?
+  & common-anim-set-values-attlist
+  & attribute smil:from { \string }?
+  & attribute smil:by { \string }?
+common-auto-reorder-attlist =
+  attribute number:automatic-order { boolean }?
+common-background-color-attlist =
+  attribute fo:background-color { "transparent" | color }?
+common-background-transparency-attlist =
+  attribute style:background-transparency { zeroToHundredPercent }?
+common-basic-timing-attlist =
+  common-begin-end-timing-attlist,
+  common-dur-timing-attlist,
+  common-repeat-timing-attlist,
+  common-restart-timing-attlist,
+  common-restart-default-attlist,
+  common-fill-timing-attlist,
+  common-fill-default-attlist
+common-begin-end-timing-attlist =
+  attribute smil:begin { \string }?
+  & attribute smil:end { \string }?
+common-border-attlist =
+  attribute fo:border { \string }?,
+  attribute fo:border-top { \string }?,
+  attribute fo:border-bottom { \string }?,
+  attribute fo:border-left { \string }?,
+  attribute fo:border-right { \string }?
+common-border-line-width-attlist =
+  attribute style:border-line-width { borderWidths }?,
+  attribute style:border-line-width-top { borderWidths }?,
+  attribute style:border-line-width-bottom { borderWidths }?,
+  attribute style:border-line-width-left { borderWidths }?,
+  attribute style:border-line-width-right { borderWidths }?
+common-break-attlist =
+  attribute fo:break-before { "auto" | "column" | "page" }?,
+  attribute fo:break-after { "auto" | "column" | "page" }?
+common-calendar-attlist =
+  attribute number:calendar {
+    "gregorian"
+    | "gengou"
+    | "ROC"
+    | "hanja_yoil"
+    | "hanja"
+    | "hijri"
+    | "jewish"
+    | "buddhist"
+    | \string
   }?
-text-note-ref-content =
-  attribute text:reference-format { common-ref-format-values }?
-  & text-note-class
-text-sequence-ref-content =
-  attribute text:reference-format {
-    common-ref-format-values
-    | "category-and-value"
-    | "caption"
-    | "value"
-  }?
-common-ref-format-values = "page" | "chapter" | "direction" | "text"
-text-hidden-paragraph-attlist =
-  attribute text:condition { \string }
-  & attribute text:is-hidden { boolean }?
-text-meta-field-attlist = xml-id & common-field-data-style-name-attlist
-common-value-type-attlist = attribute office:value-type { valueType }
-common-value-and-type-attlist =
-  (attribute office:value-type { "float" },
-   attribute office:value { double })
-  | (attribute office:value-type { "percentage" },
-     attribute office:value { double })
-  | (attribute office:value-type { "currency" },
-     attribute office:value { double },
-     attribute office:currency { \string }?)
-  | (attribute office:value-type { "date" },
-     attribute office:date-value { dateOrDateTime })
-  | (attribute office:value-type { "time" },
-     attribute office:time-value { duration })
-  | (attribute office:value-type { "boolean" },
-     attribute office:boolean-value { boolean })
-  | (attribute office:value-type { "string" },
-     attribute office:string-value { \string }?)
-common-field-fixed-attlist = attribute text:fixed { boolean }?
-common-field-name-attlist = attribute text:name { variableName }
+common-contour-attlist = attribute draw:recreate-on-edit { boolean }
+common-control-id-attlist =
+  xml-id,
+  attribute form:id { NCName }?
+common-convert-empty-attlist =
+  attribute form:convert-empty-to-null { boolean }?
+common-current-value-attlist = attribute form:current-value { \string }?
+common-data-field-attlist = attribute form:data-field { \string }?
+common-data-style-attlist =
+  attribute style:name { styleName }
+  & attribute style:display-name { \string }?
+  & attribute number:language { languageCode }?
+  & attribute number:country { countryCode }?
+  & attribute number:script { scriptCode }?
+  & attribute number:rfc-language-tag { language }?
+  & attribute number:title { \string }?
+  & attribute style:volatile { boolean }?
+  & attribute number:transliteration-format { \string }?
+  & attribute number:transliteration-language { countryCode }?
+  & attribute number:transliteration-country { countryCode }?
+  & attribute number:transliteration-style {
+      "short" | "medium" | "long"
+    }?
+common-db-default-value = common-value-and-type-attlist?
+common-db-object-description = attribute db:description { \string }?
+common-db-object-name = attribute db:name { \string }
+common-db-object-title = attribute db:title { \string }?
+common-db-table-name-attlist =
+  attribute db:name { \string }
+  & attribute db:catalog-name { \string }?
+  & attribute db:schema-name { \string }?
+common-db-table-style-name =
+  attribute db:style-name { styleNameRef }?
+  & attribute db:default-row-style-name { styleNameRef }?
+common-dde-connection-decl-attlist =
+  attribute office:dde-application { \string }
+  & attribute office:dde-topic { \string }
+  & attribute office:dde-item { \string }
+  & attribute office:automatic-update { boolean }?
+common-decimal-places-attlist =
+  attribute number:decimal-places { integer }?,
+  (attribute number:min-decimal-places { integer }?)
+  # https://issues.oasis-open.org/browse/OFFICE-3860  added 
number:min-decimal-places
+
+common-delay-for-repeat = attribute form:delay-for-repeat { duration }?
+common-disabled-attlist = attribute form:disabled { boolean }?
+common-dr3d-transform-attlist = attribute dr3d:transform { \string }?
+common-draw-area-attlist =
+  (attribute xlink:type { "simple" },
+   attribute xlink:href { anyIRI },
+   attribute office:target-frame-name { targetFrameName }?,
+   attribute xlink:show { "new" | "replace" }?)?
+  & attribute office:name { \string }?
+  & attribute draw:nohref { "nohref" }?
+common-draw-caption-id-attlist = attribute draw:caption-id { IDREF }?
+common-draw-circle-ellipse-attlist =
+  attribute draw:kind { "full" | "section" | "cut" | "arc" }?
+  & attribute draw:start-angle { angle }?
+  & attribute draw:end-angle { angle }?
+common-draw-circle-ellipse-pos-attlist =
+  attribute svg:cx { coordinate },
+  attribute svg:cy { coordinate }
+common-draw-data-attlist =
+  attribute xlink:type { "simple" },
+  attribute xlink:href { anyIRI },
+  attribute xlink:show { "embed" }?,
+  attribute xlink:actuate { "onLoad" }?
+common-draw-gradient-attlist =
+  attribute draw:name { styleName }?
+  & attribute draw:display-name { \string }?
+  & attribute draw:style { gradient-style }
+  & attribute draw:cx { percent }?
+  & attribute draw:cy { percent }?
+  & attribute draw:angle { angle }?
+  & attribute draw:border { percent }?
+common-draw-id-attlist =
+  (xml-id,
+   attribute draw:id { NCName }?)?
+common-draw-layer-name-attlist = attribute draw:layer { \string }?
+common-draw-mime-type-attlist = attribute draw:mime-type { \string }?
+# https://issues.oasis-open.org/browse/OFFICE-3943
+common-draw-name-attlist = attribute draw:name { \string }?
+common-draw-path-data-attlist = attribute svg:d { pathData }
+common-draw-points-attlist = attribute draw:points { points }
+common-draw-position-attlist =
+  attribute svg:x { coordinate }?,
+  attribute svg:y { coordinate }?
+common-draw-rel-size-attlist =
+  common-draw-size-attlist,
+  attribute style:rel-width { percent | "scale" | "scale-min" }?,
+  attribute style:rel-height { percent | "scale" | "scale-min" }?
+common-draw-shape-with-styles-attlist =
+  common-draw-z-index-attlist,
+  common-draw-id-attlist,
+  common-draw-layer-name-attlist,
+  common-draw-style-name-attlist,
+  common-draw-transform-attlist,
+  common-draw-name-attlist,
+  common-text-spreadsheet-shape-attlist
+common-draw-shape-with-text-and-styles-attlist =
+  common-draw-shape-with-styles-attlist,
+  common-draw-text-style-name-attlist
+common-draw-size-attlist =
+  attribute svg:width { length }?,
+  attribute svg:height { length }?
+common-draw-style-name-attlist =
+  (attribute draw:style-name { styleNameRef }?,
+   attribute draw:class-names { styleNameRefs }?)
+  | (attribute presentation:style-name { styleNameRef }?,
+     attribute presentation:class-names { styleNameRefs }?)
+common-draw-text-style-name-attlist =
+  attribute draw:text-style-name { styleNameRef }?
+common-draw-transform-attlist = attribute draw:transform { \string }?
+common-draw-viewbox-attlist =
+  attribute svg:viewBox {
+    list { integer, integer, integer, integer }
+  }
+common-draw-z-index-attlist =
+  attribute draw:z-index { nonNegativeInteger }?
+common-dur-timing-attlist = attribute smil:dur { \string }?
+common-editable-attlist = attribute style:editable { boolean }?
+common-endsync-timing-attlist =
+  attribute smil:endsync { "first" | "last" | "all" | "media" | IDREF }?
+common-field-data-style-name-attlist =
+  attribute style:data-style-name { styleNameRef }?
+common-field-database-name =
+  attribute text:database-name { \string }?
+  | form-connection-resource
+common-field-database-table =
+  common-field-database-table-attlist, common-field-database-name
+common-field-database-table-attlist =
+  attribute text:table-name { \string }
+  & attribute text:table-type { "table" | "query" | "command" }?
 common-field-description-attlist =
   attribute text:description { \string }?
-common-field-display-value-none-attlist =
-  attribute text:display { "value" | "none" }?
-common-field-display-value-formula-none-attlist =
-  attribute text:display { "value" | "formula" | "none" }?
 common-field-display-value-formula-attlist =
   attribute text:display { "value" | "formula" }?
+common-field-display-value-formula-none-attlist =
+  attribute text:display { "value" | "formula" | "none" }?
+common-field-display-value-none-attlist =
+  attribute text:display { "value" | "none" }?
+common-field-fixed-attlist = attribute text:fixed { boolean }?
 common-field-formula-attlist = attribute text:formula { \string }?
-common-field-data-style-name-attlist =
-  attribute style:data-style-name { styleNameRef }?
+common-field-name-attlist = attribute text:name { variableName }
 common-field-num-format-attlist = common-num-format-attlist?
-text-toc-mark-start-attrs = text-id, text-outline-level
-text-outline-level = attribute text:outline-level { positiveInteger }?
-text-id = attribute text:id { \string }
-text-index-name = attribute text:index-name { \string }
-text-alphabetical-index-mark-attrs =
-  attribute text:key1 { \string }?
-  & attribute text:key2 { \string }?
-  & attribute text:string-value-phonetic { \string }?
-  & attribute text:key1-phonetic { \string }?
-  & attribute text:key2-phonetic { \string }?
-  & attribute text:main-entry { boolean }?
-text-bibliography-types =
-  "article"
-  | "book"
-  | "booklet"
-  | "conference"
-  | "custom1"
-  | "custom2"
-  | "custom3"
-  | "custom4"
-  | "custom5"
-  | "email"
-  | "inbook"
-  | "incollection"
-  | "inproceedings"
-  | "journal"
-  | "manual"
-  | "mastersthesis"
-  | "misc"
-  | "phdthesis"
-  | "proceedings"
-  | "techreport"
-  | "unpublished"
-  | "www"
-text-index-body = element text:index-body { index-content-main* }
-index-content-main = text-content | text-index-title
-text-index-title =
-  element text:index-title {
-    common-section-attlist, index-content-main*
-  }
-text-table-of-content =
-  element text:table-of-content {
-    common-section-attlist,
-    text-table-of-content-source,
-    text-index-body
-  }
-text-table-of-content-source =
-  element text:table-of-content-source {
-    text-table-of-content-source-attlist,
-    text-index-title-template?,
-    text-table-of-content-entry-template*,
-    text-index-source-styles*
-  }
-text-table-of-content-source-attlist =
-  attribute text:outline-level { positiveInteger }?
-  & attribute text:use-outline-level { boolean }?
-  & attribute text:use-index-marks { boolean }?
-  & attribute text:use-index-source-styles { boolean }?
-  & attribute text:index-scope { "document" | "chapter" }?
-  & attribute text:relative-tab-stop-position { boolean }?
-text-table-of-content-entry-template =
-  element text:table-of-content-entry-template {
-    text-table-of-content-entry-template-attlist,
-    text-table-of-content-children*
-  }
-text-table-of-content-children =
-  text-index-entry-chapter
-  | text-index-entry-page-number
-  | text-index-entry-text
-  | text-index-entry-span
-  | text-index-entry-tab-stop
-  | text-index-entry-link-start
-  | text-index-entry-link-end
-text-table-of-content-entry-template-attlist =
-  attribute text:outline-level { positiveInteger }
-  & attribute text:style-name { styleNameRef }
-text-illustration-index =
-  element text:illustration-index {
-    common-section-attlist,
-    text-illustration-index-source,
-    text-index-body
-  }
-text-illustration-index-source =
-  element text:illustration-index-source {
-    text-illustration-index-source-attrs,
-    text-index-title-template?,
-    text-illustration-index-entry-template?
-  }
-text-illustration-index-source-attrs =
-  text-index-scope-attr
-  & text-relative-tab-stop-position-attr
-  & attribute text:use-caption { boolean }?
-  & attribute text:caption-sequence-name { \string }?
-  & attribute text:caption-sequence-format {
-      "text" | "category-and-value" | "caption"
+common-fill-default-attlist =
+  attribute smil:fillDefault {
+    "remove" | "freeze" | "hold" | "transition" | "auto" | "inherit"
+  }?
+common-fill-timing-attlist =
+  attribute smil:fill {
+    "remove" | "freeze" | "hold" | "auto" | "default" | "transition"
+  }?
+common-form-control-attlist =
+  attribute form:name { \string }?
+  & attribute form:control-implementation { namespacedToken }?
+common-form-control-content = form-properties?, office-event-listeners?
+common-form-relative-image-position-attlist =
+  attribute form:image-position { "center" }?
+  | (attribute form:image-position {
+       "start" | "end" | "top" | "bottom"
+     },
+     attribute form:image-align { "start" | "center" | "end" }?)
+common-form-visual-effect-attlist =
+  attribute form:visual-effect { "flat" | "3d" }?
+common-format-source-attlist =
+  attribute number:format-source { "fixed" | "language" }?
+common-horizontal-margin-attlist =
+  attribute fo:margin-left { length | percent }?,
+  attribute fo:margin-right { length | percent }?
+common-in-content-meta-attlist =
+  attribute xhtml:about { URIorSafeCURIE },
+  attribute xhtml:property { CURIEs },
+  common-meta-literal-attlist
+common-keep-with-next-attlist =
+  attribute fo:keep-with-next { "auto" | "always" }?
+common-linked-cell =
+  attribute form:linked-cell { cellAddress | \string }?
+common-margin-attlist =
+  attribute fo:margin { nonNegativeLength | percent }?
+common-maxlength-attlist =
+  attribute form:max-length { nonNegativeInteger }?
+common-meta-literal-attlist =
+  attribute xhtml:datatype { CURIE }?,
+  attribute xhtml:content { \string }?
+common-num-format-attlist =
+  attribute style:num-format { "1" | "i" | "I" | \string | empty }
+  | (attribute style:num-format { "a" | "A" },
+     style-num-letter-sync-attlist)
+  | empty
+common-num-format-prefix-suffix-attlist =
+  attribute style:num-prefix { \string }?,
+  attribute style:num-suffix { \string }?
+common-number-attlist =
+  attribute number:min-integer-digits { integer }?
+  & attribute number:grouping { boolean }?
+common-numeric-control-attlist =
+  form-control-attlist,
+  common-disabled-attlist,
+  common-maxlength-attlist,
+  common-printable-attlist,
+  common-readonly-attlist,
+  common-tab-attlist,
+  common-title-attlist,
+  common-convert-empty-attlist,
+  common-data-field-attlist
+common-office-annotation-name-attlist =
+  attribute office:name { \string }
+common-padding-attlist =
+  attribute fo:padding { nonNegativeLength }?,
+  attribute fo:padding-top { nonNegativeLength }?,
+  attribute fo:padding-bottom { nonNegativeLength }?,
+  attribute fo:padding-left { nonNegativeLength }?,
+  attribute fo:padding-right { nonNegativeLength }?
+common-page-number-attlist =
+  attribute style:page-number {
+    (nonNegativeInteger | "auto")
+    # https://issues.oasis-open.org/browse/OFFICE-3923
+
+  }?
+common-presentation-effect-attlist =
+  attribute draw:shape-id { IDREF }
+  & attribute presentation:effect { presentationEffects }?
+  & attribute presentation:direction { presentationEffectDirections }?
+  & attribute presentation:speed { presentationSpeeds }?
+  & attribute presentation:delay { duration }?
+  & attribute presentation:start-scale { percent }?
+  & attribute presentation:path-id { \string }?
+common-presentation-header-footer-attlist =
+  attribute presentation:use-header-name { \string }?
+  & attribute presentation:use-footer-name { \string }?
+  & attribute presentation:use-date-time-name { \string }?
+common-printable-attlist = attribute form:printable { boolean }?
+common-readonly-attlist = attribute form:readonly { boolean }?
+common-ref-format-values = "page" | "chapter" | "direction" | "text"
+common-repeat = attribute form:repeat { boolean }?
+common-repeat-timing-attlist =
+  attribute smil:repeatDur { \string }?,
+  attribute smil:repeatCount { nonNegativeDecimal | "indefinite" }?
+common-restart-default-attlist =
+  attribute smil:restartDefault {
+    "never" | "always" | "whenNotActive" | "inherit"
+  }?
+common-restart-timing-attlist =
+  attribute smil:restart {
+    "never" | "always" | "whenNotActive" | "default"
+  }?
+common-rotation-angle-attlist =
+  attribute style:rotation-angle { angle }?
+common-section-attlist =
+  attribute text:style-name { styleNameRef }?
+  & attribute text:name { \string }
+  & attribute text:protected { boolean }?
+  & attribute text:protection-key { \string }?
+  & attribute text:protection-key-digest-algorithm { anyIRI }?
+  & xml-id?
+common-shadow-attlist = attribute style:shadow { shadowType }?
+common-source-cell-range =
+  attribute form:source-cell-range { cellRangeAddress | \string }?
+common-spin-button = attribute form:spin-button { boolean }?
+common-spline-anim-value-attlist =
+  attribute smil:keyTimes { \string }?
+  & attribute smil:keySplines { \string }?
+common-stock-marker-attlist =
+  attribute chart:style-name { styleNameRef }?
+common-style-direction-attlist =
+  attribute style:direction { "ltr" | "ttb" }?
+common-style-header-footer-attlist =
+  attribute style:display { boolean }?
+common-svg-font-face-xlink-attlist =
+  attribute xlink:type { "simple" },
+  attribute xlink:href { anyIRI },
+  attribute xlink:actuate { "onRequest" }?
+common-svg-gradient-attlist =
+  attribute svg:gradientUnits { "objectBoundingBox" }?
+  & attribute svg:gradientTransform { \string }?
+  & attribute svg:spreadMethod { "pad" | "reflect" | "repeat" }?
+  & attribute draw:name { styleName }
+  & attribute draw:display-name { \string }?
+common-tab-attlist =
+  attribute form:tab-index { nonNegativeInteger }?
+  & attribute form:tab-stop { boolean }?
+common-table-cell-address-attlist =
+  attribute table:column { integer },
+  attribute table:row { integer },
+  attribute table:table { integer }
+common-table-cell-range-address-attlist =
+  attribute table:start-column { integer },
+  attribute table:start-row { integer },
+  attribute table:start-table { integer },
+  attribute table:end-column { integer },
+  attribute table:end-row { integer },
+  attribute table:end-table { integer }
+common-table-change-attlist =
+  attribute table:id { \string }
+  & attribute table:acceptance-state {
+      "accepted" | "rejected" | "pending"
     }?
-text-index-scope-attr =
-  attribute text:index-scope { "document" | "chapter" }?
-text-relative-tab-stop-position-attr =
-  attribute text:relative-tab-stop-position { boolean }?
-text-illustration-index-entry-template =
-  element text:illustration-index-entry-template {
-    text-illustration-index-entry-content
+  & attribute table:rejecting-change-id { \string }?
+common-table-range-attlist =
+  common-table-cell-address-attlist
+  | common-table-cell-range-address-attlist
+common-table-template-attlist =
+  attribute table:style-name { styleNameRef },
+  attribute table:paragraph-style-name { styleNameRef }?
+common-text-align =
+  attribute fo:text-align {
+    "start" | "end" | "left" | "right" | "center" | "justify"
+  }?
+common-text-anchor-attlist =
+  attribute text:anchor-type {
+    "page" | "frame" | "paragraph" | "char" | "as-char"
+  }?
+  & attribute text:anchor-page-number { positiveInteger }?
+common-text-spreadsheet-shape-attlist =
+  attribute table:end-cell-address { cellAddress }?
+  & attribute table:end-x { coordinate }?
+  & attribute table:end-y { coordinate }?
+  & attribute table:table-background { boolean }?
+  & common-text-anchor-attlist
+common-time-manip-attlist =
+  attribute smil:accelerate { zeroToOneDecimal }?
+  & attribute smil:decelerate { zeroToOneDecimal }?
+  & attribute smil:autoReverse { boolean }?
+common-timing-attlist =
+  common-basic-timing-attlist, common-time-manip-attlist
+common-title-attlist = attribute form:title { \string }?
+common-value-and-type-attlist =
+  (attribute office:value-type { "float" },
+   attribute office:value { double })
+  | (attribute office:value-type { "percentage" },
+     attribute office:value { double })
+  | (attribute office:value-type { "currency" },
+     attribute office:value { double },
+     attribute office:currency { \string }?)
+  | (attribute office:value-type { "date" },
+     attribute office:date-value { dateOrDateTime })
+  | (attribute office:value-type { "time" },
+     attribute office:time-value { duration })
+  | (attribute office:value-type { "boolean" },
+     attribute office:boolean-value { boolean })
+  | (attribute office:value-type { "string" },
+     attribute office:string-value { \string }?)
+common-value-attlist = attribute form:value { \string }?
+common-value-type-attlist = attribute office:value-type { valueType }
+common-vertical-margin-attlist =
+  attribute fo:margin-top { nonNegativeLength | percent }?,
+  attribute fo:margin-bottom { nonNegativeLength | percent }?
+common-vertical-pos-attlist =
+  attribute style:vertical-pos {
+    "top" | "middle" | "bottom" | "from-top" | "below"
+  }?,
+  attribute svg:y { coordinate }?
+common-vertical-rel-attlist =
+  attribute style:vertical-rel {
+    "page"
+    | "page-content"
+    | "frame"
+    | "frame-content"
+    | "paragraph"
+    | "paragraph-content"
+    | "char"
+    | "line"
+    | "baseline"
+    | "text"
+  }?
+common-writing-mode-attlist =
+  attribute style:writing-mode {
+    "lr-tb" | "rl-tb" | "tb-rl" | "tb-lr" | "lr" | "rl" | "tb" | "page"
+  }?
+config-config-item =
+  element config:config-item { config-config-item-attlist, text }
+config-config-item-attlist =
+  attribute config:name { \string }
+  & attribute config:type {
+      "boolean"
+      | "short"
+      | "int"
+      | "long"
+      | "double"
+      | "string"
+      | "datetime"
+      | "base64Binary"
+    }
+config-config-item-map-entry =
+  element config:config-item-map-entry {
+    config-config-item-map-entry-attlist, config-items
   }
-text-illustration-index-entry-content =
-  text-illustration-index-entry-template-attrs,
-  (text-index-entry-chapter
-   | text-index-entry-page-number
-   | text-index-entry-text
-   | text-index-entry-span
-   | text-index-entry-tab-stop)*
-text-illustration-index-entry-template-attrs =
-  attribute text:style-name { styleNameRef }
-text-table-index =
-  element text:table-index {
-    common-section-attlist, text-table-index-source, text-index-body
-  }
-text-table-index-source =
-  element text:table-index-source {
-    text-illustration-index-source-attrs,
-    text-index-title-template?,
-    text-table-index-entry-template?
+config-config-item-map-entry-attlist =
+  attribute config:name { \string }?
+config-config-item-map-indexed =
+  element config:config-item-map-indexed {
+    config-config-item-map-indexed-attlist,
+    config-config-item-map-entry+
   }
-text-table-index-entry-template =
-  element text:table-index-entry-template {
-    text-illustration-index-entry-content
+config-config-item-map-indexed-attlist =
+  attribute config:name { \string }
+config-config-item-map-named =
+  element config:config-item-map-named {
+    config-config-item-map-named-attlist, config-config-item-map-entry+
   }
-text-object-index =
-  element text:object-index {
-    common-section-attlist, text-object-index-source, text-index-body
+config-config-item-map-named-attlist = attribute config:name { \string }
+config-config-item-set =
+  element config:config-item-set {
+    config-config-item-set-attlist, config-items
   }
-text-object-index-source =
-  element text:object-index-source {
-    text-object-index-source-attrs,
-    text-index-title-template?,
-    text-object-index-entry-template?
+config-config-item-set-attlist = attribute config:name { \string }
+config-items =
+  (config-config-item
+   | config-config-item-set
+   | config-config-item-map-named
+   | config-config-item-map-indexed)+
+controls =
+  column-controls
+  | element form:password {
+      form-password-attlist, common-form-control-content
+    }
+  | element form:file { form-file-attlist, common-form-control-content }
+  | element form:fixed-text {
+      form-fixed-text-attlist, common-form-control-content
+    }
+  | element form:button {
+      form-button-attlist, common-form-control-content
+    }
+  | element form:image {
+      form-image-attlist, common-form-control-content
+    }
+  | element form:radio {
+      form-radio-attlist, common-form-control-content
+    }
+  | element form:frame {
+      form-frame-attlist, common-form-control-content
+    }
+  | element form:image-frame {
+      form-image-frame-attlist, common-form-control-content
+    }
+  | element form:hidden {
+      form-hidden-attlist, common-form-control-content
+    }
+  | element form:grid {
+      form-grid-attlist, common-form-control-content, form-column*
+    }
+  | element form:value-range {
+      form-value-range-attlist, common-form-control-content
+    }
+  | element form:generic-control {
+      form-generic-control-attlist, common-form-control-content
+    }
+coordinate = length
+countryCode = xsd:token { pattern = "[A-Za-z0-9]{1,8}" }
+currency-symbol-and-text =
+  number-currency-symbol,
+  number-text-with-fillchar
+  # https://issues.oasis-open.org/browse/OFFICE-3765
+  ?
+current-selected = attribute form:current-selected { boolean }?
+custom-shape-type = "non-primitive" | \string
+date = xsd:date
+dateOrDateTime = xsd:date | xsd:dateTime
+dateTime = xsd:dateTime
+db-application-connection-settings =
+  element db:application-connection-settings {
+    db-application-connection-settings-attlist,
+    db-table-filter?,
+    db-table-type-filter?,
+    db-data-source-settings?
   }
-text-object-index-source-attrs =
-  text-index-scope-attr
-  & text-relative-tab-stop-position-attr
-  & attribute text:use-spreadsheet-objects { boolean }?
-  & attribute text:use-math-objects { boolean }?
-  & attribute text:use-draw-objects { boolean }?
-  & attribute text:use-chart-objects { boolean }?
-  & attribute text:use-other-objects { boolean }?
-text-object-index-entry-template =
-  element text:object-index-entry-template {
-    text-illustration-index-entry-content
+db-application-connection-settings-attlist =
+  attribute db:is-table-name-length-limited { boolean }?
+  & attribute db:enable-sql92-check { boolean }?
+  & attribute db:append-table-alias-name { boolean }?
+  & attribute db:ignore-driver-privileges { boolean }?
+  & attribute db:boolean-comparison-mode {
+      "equal-integer"
+      | "is-boolean"
+      | "equal-boolean"
+      | "equal-use-only-zero"
+    }?
+  & attribute db:use-catalog { boolean }?
+  & attribute db:max-row-count { integer }?
+  & attribute db:suppress-version-columns { boolean }?
+db-apply-command = attribute db:apply-command { boolean }?
+db-auto-increment =
+  element db:auto-increment { db-auto-increment-attlist, empty }
+db-auto-increment-attlist =
+  attribute db:additional-column-statement { \string }?
+  & attribute db:row-retrieving-statement { \string }?
+db-character-set =
+  element db:character-set { db-character-set-attlist, empty }
+db-character-set-attlist = attribute db:encoding { textEncoding }?
+db-column =
+  element db:column {
+    db-column-attlist,
+    common-db-object-name,
+    common-db-object-title,
+    common-db-object-description,
+    common-db-default-value
   }
-text-user-index =
-  element text:user-index {
-    common-section-attlist, text-user-index-source, text-index-body
+db-column-attlist =
+  attribute db:visible { boolean }?
+  & attribute db:style-name { styleNameRef }?
+  & attribute db:default-cell-style-name { styleNameRef }?
+db-column-definition =
+  element db:column-definition {
+    db-column-definition-attlist, common-db-default-value
   }
-text-user-index-source =
-  element text:user-index-source {
-    text-user-index-source-attr,
-    text-index-title-template?,
-    text-user-index-entry-template*,
-    text-index-source-styles*
+db-column-definition-attlist =
+  attribute db:name { \string }
+  & attribute db:data-type { db-data-types }?
+  & attribute db:type-name { \string }?
+  & attribute db:precision { positiveInteger }?
+  & attribute db:scale { positiveInteger }?
+  & attribute db:is-nullable { "no-nulls" | "nullable" }?
+  & attribute db:is-empty-allowed { boolean }?
+  & attribute db:is-autoincrement { boolean }?
+db-column-definitions =
+  element db:column-definitions {
+    db-column-definitions-attlist, db-column-definition+
   }
-text-user-index-source-attr =
-  text-index-scope-attr
-  & text-relative-tab-stop-position-attr
-  & attribute text:use-index-marks { boolean }?
-  & attribute text:use-index-source-styles { boolean }?
-  & attribute text:use-graphics { boolean }?
-  & attribute text:use-tables { boolean }?
-  & attribute text:use-floating-frames { boolean }?
-  & attribute text:use-objects { boolean }?
-  & attribute text:copy-outline-levels { boolean }?
-  & attribute text:index-name { \string }
-text-user-index-entry-template =
-  element text:user-index-entry-template {
-    text-user-index-entry-template-attrs,
-    (text-index-entry-chapter
-     | text-index-entry-page-number
-     | text-index-entry-text
-     | text-index-entry-span
-     | text-index-entry-tab-stop)*
+db-column-definitions-attlist = empty
+db-columns = element db:columns { db-columns-attlist, db-column+ }
+db-columns-attlist = empty
+db-command = attribute db:command { \string }
+db-component =
+  element db:component {
+    db-component-attlist,
+    common-db-object-name,
+    common-db-object-title,
+    common-db-object-description,
+    (office-document | math-math)?
   }
-text-user-index-entry-template-attrs =
-  attribute text:outline-level { positiveInteger }
-  & attribute text:style-name { styleNameRef }
-text-alphabetical-index =
-  element text:alphabetical-index {
-    common-section-attlist,
-    text-alphabetical-index-source,
-    text-index-body
+db-component-attlist =
+  (attribute xlink:type { "simple" },
+   attribute xlink:href { anyIRI },
+   attribute xlink:show { "none" }?,
+   attribute xlink:actuate { "onRequest" }?)?
+  & attribute db:as-template { boolean }?
+db-component-collection =
+  element db:component-collection {
+    db-component-collection-attlist,
+    common-db-object-name,
+    common-db-object-title,
+    common-db-object-description,
+    (db-component | db-component-collection)*
   }
-text-alphabetical-index-source =
-  element text:alphabetical-index-source {
-    text-alphabetical-index-source-attrs,
-    text-index-title-template?,
-    text-alphabetical-index-entry-template*
+db-component-collection-attlist = empty
+db-connection-data =
+  element db:connection-data {
+    db-connection-data-attlist,
+    (db-database-description | db-connection-resource),
+    db-login?
   }
-text-alphabetical-index-source-attrs =
-  text-index-scope-attr
-  & text-relative-tab-stop-position-attr
-  & attribute text:ignore-case { boolean }?
-  & attribute text:main-entry-style-name { styleNameRef }?
-  & attribute text:alphabetical-separators { boolean }?
-  & attribute text:combine-entries { boolean }?
-  & attribute text:combine-entries-with-dash { boolean }?
-  & attribute text:combine-entries-with-pp { boolean }?
-  & attribute text:use-keys-as-entries { boolean }?
-  & attribute text:capitalize-entries { boolean }?
-  & attribute text:comma-separated { boolean }?
-  & attribute fo:language { languageCode }?
-  & attribute fo:country { countryCode }?
-  & attribute fo:script { scriptCode }?
-  & attribute style:rfc-language-tag { language }?
-  & attribute text:sort-algorithm { \string }?
-text-alphabetical-index-auto-mark-file =
-  element text:alphabetical-index-auto-mark-file {
-    attribute xlink:type { "simple" },
-    attribute xlink:href { anyIRI }
+db-connection-data-attlist = empty
+db-connection-resource =
+  element db:connection-resource {
+    db-connection-resource-attlist, empty
   }
-text-alphabetical-index-entry-template =
-  element text:alphabetical-index-entry-template {
-    text-alphabetical-index-entry-template-attrs,
-    (text-index-entry-chapter
-     | text-index-entry-page-number
-     | text-index-entry-text
-     | text-index-entry-span
-     | text-index-entry-tab-stop)*
+db-connection-resource-attlist =
+  attribute xlink:type { "simple" },
+  attribute xlink:href { anyIRI },
+  attribute xlink:show { "none" }?,
+  attribute xlink:actuate { "onRequest" }?
+db-data-source =
+  element db:data-source {
+    db-data-source-attlist,
+    db-connection-data,
+    db-driver-settings?,
+    db-application-connection-settings?
   }
-text-alphabetical-index-entry-template-attrs =
-  attribute text:outline-level { "1" | "2" | "3" | "separator" }
-  & attribute text:style-name { styleNameRef }
-text-bibliography =
-  element text:bibliography {
-    common-section-attlist, text-bibliography-source, text-index-body
+db-data-source-attlist = empty
+db-data-source-setting =
+  element db:data-source-setting {
+    db-data-source-setting-attlist, db-data-source-setting-value+
   }
-text-bibliography-source =
-  element text:bibliography-source {
-    text-index-title-template?, text-bibliography-entry-template*
+db-data-source-setting-attlist =
+  attribute db:data-source-setting-is-list { boolean }?
+  & attribute db:data-source-setting-name { \string }
+  & attribute db:data-source-setting-type {
+      db-data-source-setting-types
+    }
+db-data-source-setting-types =
+  "boolean" | "short" | "int" | "long" | "double" | "string"
+db-data-source-setting-value =
+  element db:data-source-setting-value {
+    db-data-source-setting-value-attlist, \string
   }
-text-bibliography-entry-template =
-  element text:bibliography-entry-template {
-    text-bibliography-entry-template-attrs,
-    (text-index-entry-span
-     | text-index-entry-tab-stop
-     | text-index-entry-bibliography)*
+db-data-source-setting-value-attlist = empty
+db-data-source-settings =
+  element db:data-source-settings {
+    db-data-source-settings-attlist, db-data-source-setting+
   }
-text-bibliography-entry-template-attrs =
-  attribute text:bibliography-type { text-bibliography-types }
-  & attribute text:style-name { styleNameRef }
-text-index-source-styles =
-  element text:index-source-styles {
-    attribute text:outline-level { positiveInteger },
-    text-index-source-style*
+db-data-source-settings-attlist = empty
+db-data-types =
+  "bit"
+  | "boolean"
+  | "tinyint"
+  | "smallint"
+  | "integer"
+  | "bigint"
+  | "float"
+  | "real"
+  | "double"
+  | "numeric"
+  | "decimal"
+  | "char"
+  | "varchar"
+  | "longvarchar"
+  | "date"
+  | "time"
+  | "timestmp"
+  | "binary"
+  | "varbinary"
+  | "longvarbinary"
+  | "sqlnull"
+  | "other"
+  | "object"
+  | "distinct"
+  | "struct"
+  | "array"
+  | "blob"
+  | "clob"
+  | "ref"
+db-database-description =
+  element db:database-description {
+    db-database-description-attlist,
+    (db-file-based-database | db-server-database)
   }
-text-index-source-style =
-  element text:index-source-style {
-    attribute text:style-name { styleName },
-    empty
+db-database-description-attlist = empty
+db-delimiter = element db:delimiter { db-delimiter-attlist, empty }
+db-delimiter-attlist =
+  attribute db:field { \string }?
+  & attribute db:string { \string }?
+  & attribute db:decimal { \string }?
+  & attribute db:thousand { \string }?
+db-driver-settings =
+  element db:driver-settings {
+    db-driver-settings-attlist,
+    db-auto-increment?,
+    db-delimiter?,
+    db-character-set?,
+    db-table-settings?
   }
-text-index-title-template =
-  element text:index-title-template {
-    attribute text:style-name { styleNameRef }?,
-    text
+db-driver-settings-attlist =
+  db-show-deleted
+  & attribute db:system-driver-settings { \string }?
+  & attribute db:base-dn { \string }?
+  & db-is-first-row-header-line
+  & attribute db:parameter-name-substitution { boolean }?
+db-file-based-database =
+  element db:file-based-database { db-file-based-database-attlist }
+db-file-based-database-attlist =
+  attribute xlink:type { "simple" }
+  & attribute xlink:href { anyIRI }
+  & attribute db:media-type { \string }
+  & attribute db:extension { \string }?
+db-filter-statement =
+  element db:filter-statement { db-command, db-apply-command, empty }
+db-forms =
+  element db:forms {
+    db-forms-attlist, (db-component | db-component-collection)*
   }
-text-index-entry-chapter =
-  element text:index-entry-chapter {
-    attribute text:style-name { styleNameRef }?,
-    text-index-entry-chapter-attrs
+db-forms-attlist = empty
+db-host-and-port =
+  attribute db:hostname { \string },
+  attribute db:port { positiveInteger }?
+db-index = element db:index { db-index-attlist, db-index-columns+ }
+db-index-attlist =
+  attribute db:name { \string }
+  & attribute db:catalog-name { \string }?
+  & attribute db:is-unique { boolean }?
+  & attribute db:is-clustered { boolean }?
+db-index-column =
+  element db:index-column { db-index-column-attlist, empty }
+db-index-column-attlist =
+  attribute db:name { \string }
+  & attribute db:is-ascending { boolean }?
+db-index-columns = element db:index-columns { db-index-column+ }
+db-indices = element db:indices { db-indices-attlist, db-index+ }
+db-indices-attlist = empty
+db-is-first-row-header-line =
+  attribute db:is-first-row-header-line { boolean }?
+db-key = element db:key { db-key-attlist, db-key-columns+ }
+db-key-attlist =
+  attribute db:name { \string }?
+  & attribute db:type { "primary" | "unique" | "foreign" }
+  & attribute db:referenced-table-name { \string }?
+  & attribute db:update-rule {
+      "cascade" | "restrict" | "set-null" | "no-action" | "set-default"
+    }?
+  & attribute db:delete-rule {
+      "cascade" | "restrict" | "set-null" | "no-action" | "set-default"
+    }?
+db-key-column = element db:key-column { db-key-column-attlist, empty }
+db-key-column-attlist =
+  attribute db:name { \string }?
+  & attribute db:related-column-name { \string }?
+db-key-columns =
+  element db:key-columns { db-key-columns-attlist, db-key-column+ }
+db-key-columns-attlist = empty
+db-keys = element db:keys { db-keys-attlist, db-key+ }
+db-keys-attlist = empty
+db-local-socket-name = attribute db:local-socket { \string }?
+db-login = element db:login { db-login-attlist, empty }
+db-login-attlist =
+  (attribute db:user-name { \string }
+   | attribute db:use-system-user { boolean })?
+  & attribute db:is-password-required { boolean }?
+  & attribute db:login-timeout { positiveInteger }?
+db-order-statement =
+  element db:order-statement { db-command, db-apply-command, empty }
+db-queries =
+  element db:queries {
+    db-queries-attlist, (db-query | db-query-collection)*
   }
-text-index-entry-chapter-attrs =
-  attribute text:display {
-    "name"
-    | "number"
-    | "number-and-name"
-    | "plain-number"
-    | "plain-number-and-name"
-  }?
-  & attribute text:outline-level { positiveInteger }?
-text-index-entry-text =
-  element text:index-entry-text {
-    attribute text:style-name { styleNameRef }?
+db-queries-attlist = empty
+db-query =
+  element db:query {
+    db-query-attlist,
+    common-db-object-name,
+    common-db-object-title,
+    common-db-object-description,
+    common-db-table-style-name,
+    db-order-statement?,
+    db-filter-statement?,
+    db-columns?,
+    db-update-table?
   }
-text-index-entry-page-number =
-  element text:index-entry-page-number {
-    attribute text:style-name { styleNameRef }?
+db-query-attlist =
+  attribute db:command { \string }
+  & attribute db:escape-processing { boolean }?
+db-query-collection =
+  element db:query-collection {
+    db-query-collection-attlist,
+    common-db-object-name,
+    common-db-object-title,
+    common-db-object-description,
+    (db-query | db-query-collection)*
   }
-text-index-entry-span =
-  element text:index-entry-span {
-    attribute text:style-name { styleNameRef }?,
-    text
+db-query-collection-attlist = empty
+db-reports =
+  element db:reports {
+    db-reports-attlist, (db-component | db-component-collection)*
   }
-text-index-entry-bibliography =
-  element text:index-entry-bibliography {
-    text-index-entry-bibliography-attrs
+db-reports-attlist = empty
+db-schema-definition =
+  element db:schema-definition {
+    db-schema-definition-attlist, db-table-definitions
   }
-text-index-entry-bibliography-attrs =
-  attribute text:style-name { styleNameRef }?
-  & attribute text:bibliography-data-field {
-      "address"
-      | "annote"
-      | "author"
-      | "bibliography-type"
-      | "booktitle"
-      | "chapter"
-      | "custom1"
-      | "custom2"
-      | "custom3"
-      | "custom4"
-      | "custom5"
-      | "edition"
-      | "editor"
-      | "howpublished"
-      | "identifier"
-      | "institution"
-      | "isbn"
-      | "issn"
-      | "journal"
-      | "month"
-      | "note"
-      | "number"
-      | "organizations"
-      | "pages"
-      | "publisher"
-      | "report-type"
-      | "school"
-      | "series"
-      | "title"
-      | "url"
-      | "volume"
-      | "year"
-    }
-text-index-entry-tab-stop =
-  element text:index-entry-tab-stop {
-    attribute text:style-name { styleNameRef }?,
-    text-index-entry-tab-stop-attrs
+db-schema-definition-attlist = empty
+db-server-database =
+  element db:server-database { db-server-database-attlist, empty }
+db-server-database-attlist =
+  attribute db:type { namespacedToken }
+  & (db-host-and-port | db-local-socket-name)
+  & attribute db:database-name { \string }?
+db-show-deleted = attribute db:show-deleted { boolean }?
+db-table-definition =
+  element db:table-definition {
+    common-db-table-name-attlist,
+    db-table-definition-attlist,
+    db-column-definitions,
+    db-keys?,
+    db-indices?
   }
-text-index-entry-tab-stop-attrs =
-  attribute style:leader-char { character }?
-  & (attribute style:type { "right" }
-     | (attribute style:type { "left" },
-        attribute style:position { length }))
-text-index-entry-link-start =
-  element text:index-entry-link-start {
-    attribute text:style-name { styleNameRef }?
+db-table-definition-attlist = attribute db:type { \string }?
+db-table-definitions =
+  element db:table-definitions {
+    db-table-definitions-attlist, db-table-definition*
   }
-text-index-entry-link-end =
-  element text:index-entry-link-end {
-    attribute text:style-name { styleNameRef }?
+db-table-definitions-attlist = empty
+db-table-exclude-filter =
+  element db:table-exclude-filter {
+    db-table-exclude-filter-attlist, db-table-filter-pattern+
   }
-table-table =
-  element table:table {
-    table-table-attlist,
-    table-title?,
-    table-desc?,
-    table-table-source?,
-    office-dde-source?,
-    table-scenario?,
-    office-forms?,
-    table-shapes?,
-    table-columns-and-groups,
-    table-rows-and-groups,
-    table-named-expressions?
+db-table-exclude-filter-attlist = empty
+db-table-filter =
+  element db:table-filter {
+    db-table-filter-attlist,
+    db-table-include-filter?,
+    db-table-exclude-filter?
   }
-table-columns-and-groups =
-  (table-table-column-group | table-columns-no-group)+
-table-columns-no-group =
-  (table-columns, (table-table-header-columns, table-columns?)?)
-  | (table-table-header-columns, table-columns?)
-table-columns = table-table-columns | table-table-column+
-table-rows-and-groups = (table-table-row-group | table-rows-no-group)+
-table-rows-no-group =
-  (table-rows, (table-table-header-rows, table-rows?)?)
-  | (table-table-header-rows, table-rows?)
-table-rows =
-  table-table-rows | (text-soft-page-break?, table-table-row)+
-table-table-attlist =
-  attribute table:name { \string }?
-  & attribute table:style-name { styleNameRef }?
-  & attribute table:template-name { \string }?
-  & attribute table:use-first-row-styles { boolean }?
-  & attribute table:use-last-row-styles { boolean }?
-  & attribute table:use-first-column-styles { boolean }?
-  & attribute table:use-last-column-styles { boolean }?
-  & attribute table:use-banding-rows-styles { boolean }?
-  & attribute table:use-banding-columns-styles { boolean }?
-  & attribute table:protected { boolean }?
-  & attribute table:protection-key { \string }?
-  & attribute table:protection-key-digest-algorithm { anyIRI }?
-  & attribute table:print { boolean }?
-  & attribute table:print-ranges { cellRangeAddressList }?
-  & xml-id?
-  & attribute table:is-sub-table { boolean }?
-table-title = element table:title { text }
-table-desc = element table:desc { text }
-table-table-row =
-  element table:table-row {
-    table-table-row-attlist,
-    (table-table-cell | table-covered-table-cell)+
+db-table-filter-attlist = empty
+db-table-filter-pattern =
+  element db:table-filter-pattern {
+    db-table-filter-pattern-attlist, \string
   }
-table-table-row-attlist =
-  attribute table:number-rows-repeated { positiveInteger }?
-  & attribute table:style-name { styleNameRef }?
-  & attribute table:default-cell-style-name { styleNameRef }?
-  & attribute table:visibility { table-visibility-value }?
-  & xml-id?
-table-visibility-value = "visible" | "collapse" | "filter"
-table-table-cell =
-  element table:table-cell {
-    table-table-cell-attlist,
-    table-table-cell-attlist-extra,
-    table-table-cell-content
+db-table-filter-pattern-attlist = empty
+db-table-include-filter =
+  element db:table-include-filter {
+    db-table-include-filter-attlist, db-table-filter-pattern+
   }
-table-covered-table-cell =
-  element table:covered-table-cell {
-    table-table-cell-attlist, table-table-cell-content
+db-table-include-filter-attlist = empty
+db-table-presentation =
+  element db:table-representation {
+    db-table-presentation-attlist,
+    common-db-table-name-attlist,
+    common-db-object-title,
+    common-db-object-description,
+    common-db-table-style-name,
+    db-order-statement?,
+    db-filter-statement?,
+    db-columns?
   }
-table-table-cell-content =
-  table-cell-range-source?,
-  office-annotation?,
-  table-detective?,
-  text-content*
-table-table-cell-attlist =
-  attribute table:number-columns-repeated { positiveInteger }?
-  & attribute table:style-name { styleNameRef }?
-  & attribute table:content-validation-name { \string }?
-  & attribute table:formula { \string }?
-  & common-value-and-type-attlist?
-  & attribute table:protect { boolean }?
-  & attribute table:protected { boolean }?
-  & xml-id?
-  & common-in-content-meta-attlist?
-table-table-cell-attlist-extra =
-  attribute table:number-columns-spanned { positiveInteger }?
-  & attribute table:number-rows-spanned { positiveInteger }?
-  & attribute table:number-matrix-columns-spanned { positiveInteger }?
-  & attribute table:number-matrix-rows-spanned { positiveInteger }?
-table-table-column =
-  element table:table-column { table-table-column-attlist, empty }
-table-table-column-attlist =
-  attribute table:number-columns-repeated { positiveInteger }?
-  & attribute table:style-name { styleNameRef }?
-  & attribute table:visibility { table-visibility-value }?
-  & attribute table:default-cell-style-name { styleNameRef }?
-  & xml-id?
-table-table-header-columns =
-  element table:table-header-columns { table-table-column+ }
-table-table-columns =
-  element table:table-columns { table-table-column+ }
-table-table-column-group =
-  element table:table-column-group {
-    table-table-column-group-attlist, table-columns-and-groups
+db-table-presentation-attlist = empty
+db-table-presentations =
+  element db:table-representations {
+    db-table-presentations-attlist, db-table-presentation*
   }
-table-table-column-group-attlist = attribute table:display { boolean }?
-table-table-header-rows =
-  element table:table-header-rows {
-    (text-soft-page-break?, table-table-row)+
+db-table-presentations-attlist = empty
+db-table-setting =
+  element db:table-setting {
+    db-table-setting-attlist, db-delimiter?, db-character-set?, empty
   }
-table-table-rows =
-  element table:table-rows { (text-soft-page-break?, table-table-row)+ }
-table-table-row-group =
-  element table:table-row-group {
-    table-table-row-group-attlist, table-rows-and-groups
+db-table-setting-attlist = db-is-first-row-header-line, db-show-deleted
+db-table-settings = element db:table-settings { db-table-setting* }
+db-table-type = element db:table-type { db-table-type-attlist, \string }
+db-table-type-attlist = empty
+db-table-type-filter =
+  element db:table-type-filter {
+    db-table-type-filter-attlist, db-table-type*
   }
-table-table-row-group-attlist = attribute table:display { boolean }?
-cellAddress =
-  xsd:string {
-    pattern = "($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+"
+db-table-type-filter-attlist = empty
+db-update-table =
+  element db:update-table { common-db-table-name-attlist }
+dc-creator = element dc:creator { \string }
+dc-date = element dc:date { dateTime }
+distance = length
+double = xsd:double
+dr3d-cube =
+  element dr3d:cube {
+    dr3d-cube-attlist,
+    common-draw-z-index-attlist,
+    common-draw-id-attlist,
+    common-draw-layer-name-attlist,
+    common-draw-style-name-attlist,
+    common-dr3d-transform-attlist,
+    empty
   }
-cellRangeAddress =
-  xsd:string {
-    pattern =
-      "($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+(:($?([^\. 
']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+)?"
+dr3d-cube-attlist =
+  attribute dr3d:min-edge { vector3D }?,
+  attribute dr3d:max-edge { vector3D }?
+dr3d-extrude =
+  element dr3d:extrude {
+    common-draw-path-data-attlist,
+    common-draw-viewbox-attlist,
+    common-draw-id-attlist,
+    common-draw-z-index-attlist,
+    common-draw-layer-name-attlist,
+    common-draw-style-name-attlist,
+    common-dr3d-transform-attlist,
+    empty
   }
-  | xsd:string {
-      pattern =
-        "($?([^\. ']+|'([^']|'')+'))?\.$?[0-9]+:($?([^\. 
']+|'([^']|'')+'))?\.$?[0-9]+"
-    }
-  | xsd:string {
-      pattern =
-        "($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+:($?([^\. 
']+|'([^']|'')+'))?\.$?[A-Z]+"
-    }
-cellRangeAddressList =
-  xsd:string
-  >> dc:description [
-       'Value is a space separated list of "cellRangeAddress" patterns'
-     ]
-table-table-source =
-  element table:table-source {
-    table-table-source-attlist, table-linked-source-attlist, empty
-  }
-table-table-source-attlist =
-  attribute table:mode { "copy-all" | "copy-results-only" }?
-  & attribute table:table-name { \string }?
-table-linked-source-attlist =
-  attribute xlink:type { "simple" }
-  & attribute xlink:href { anyIRI }
-  & attribute xlink:actuate { "onRequest" }?
-  & attribute table:filter-name { \string }?
-  & attribute table:filter-options { \string }?
-  & attribute table:refresh-delay { duration }?
-table-scenario =
-  element table:scenario { table-scenario-attlist, empty }
-table-scenario-attlist =
-  attribute table:scenario-ranges { cellRangeAddressList }
-  & attribute table:is-active { boolean }
-  & attribute table:display-border { boolean }?
-  & attribute table:border-color { color }?
-  & attribute table:copy-back { boolean }?
-  & attribute table:copy-styles { boolean }?
-  & attribute table:copy-formulas { boolean }?
-  & attribute table:comment { \string }?
-  & attribute table:protected { boolean }?
-table-shapes = element table:shapes { shape+ }
-table-cell-range-source =
-  element table:cell-range-source {
-    table-table-cell-range-source-attlist,
-    table-linked-source-attlist,
-    empty
-  }
-table-table-cell-range-source-attlist =
-  attribute table:name { \string }
-  & attribute table:last-column-spanned { positiveInteger }
-  & attribute table:last-row-spanned { positiveInteger }
-table-detective =
-  element table:detective { table-highlighted-range*, table-operation* }
-table-operation =
-  element table:operation { table-operation-attlist, empty }
-table-operation-attlist =
-  attribute table:name {
-    "trace-dependents"
-    | "remove-dependents"
-    | "trace-precedents"
-    | "remove-precedents"
-    | "trace-errors"
-  }
-  & attribute table:index { nonNegativeInteger }
-table-highlighted-range =
-  element table:highlighted-range {
-    (table-highlighted-range-attlist
-     | table-highlighted-range-attlist-invalid),
+dr3d-light = element dr3d:light { dr3d-light-attlist, empty }
+dr3d-light-attlist =
+  attribute dr3d:diffuse-color { color }?
+  & attribute dr3d:direction { vector3D }
+  & attribute dr3d:enabled { boolean }?
+  & attribute dr3d:specular { boolean }?
+dr3d-rotate =
+  element dr3d:rotate {
+    common-draw-viewbox-attlist,
+    common-draw-path-data-attlist,
+    common-draw-z-index-attlist,
+    common-draw-id-attlist,
+    common-draw-layer-name-attlist,
+    common-draw-style-name-attlist,
+    common-dr3d-transform-attlist,
     empty
   }
-table-highlighted-range-attlist =
-  attribute table:cell-range-address { cellRangeAddress }?
-  & attribute table:direction {
-      "from-another-table" | "to-another-table" | "from-same-table"
-    }
-  & attribute table:contains-error { boolean }?
-table-highlighted-range-attlist-invalid =
-  attribute table:marked-invalid { boolean }
-office-spreadsheet-attlist =
-  attribute table:structure-protected { boolean }?,
-  attribute table:protection-key { \string }?,
-  attribute table:protection-key-digest-algorithm { anyIRI }?
-table-calculation-settings =
-  element table:calculation-settings {
-    table-calculation-setting-attlist,
-    table-null-date?,
-    table-iteration?
+dr3d-scene =
+  element dr3d:scene {
+    dr3d-scene-attlist,
+    common-draw-position-attlist,
+    common-draw-size-attlist,
+    common-draw-style-name-attlist,
+    common-draw-z-index-attlist,
+    common-draw-id-attlist,
+    common-draw-layer-name-attlist,
+    common-text-spreadsheet-shape-attlist,
+    common-dr3d-transform-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?,
+    dr3d-light*,
+    shapes3d*,
+    draw-glue-point*
   }
-table-calculation-setting-attlist =
-  attribute table:case-sensitive { boolean }?
-  & attribute table:precision-as-shown { boolean }?
-  & attribute table:search-criteria-must-apply-to-whole-cell {
-      boolean
+dr3d-scene-attlist =
+  attribute dr3d:vrp { vector3D }?
+  & attribute dr3d:vpn { vector3D }?
+  & attribute dr3d:vup { vector3D }?
+  & attribute dr3d:projection { "parallel" | "perspective" }?
+  & attribute dr3d:distance { length }?
+  & attribute dr3d:focal-length { length }?
+  & attribute dr3d:shadow-slant { angle }?
+  & attribute dr3d:shade-mode {
+      "flat" | "phong" | "gouraud" | "draft"
     }?
-  & attribute table:automatic-find-labels { boolean }?
-  & attribute table:use-regular-expressions { boolean }?
-  & attribute table:use-wildcards { boolean }?
-  & attribute table:null-year { positiveInteger }?
-table-null-date =
-  element table:null-date {
-    attribute table:value-type { "date" }?,
-    attribute table:date-value { date }?,
-    empty
-  }
-table-iteration =
-  element table:iteration {
-    attribute table:status { "enable" | "disable" }?,
-    attribute table:steps { positiveInteger }?,
-    attribute table:maximum-difference { double }?,
+  & attribute dr3d:ambient-color { color }?
+  & attribute dr3d:lighting-mode { boolean }?
+dr3d-sphere =
+  element dr3d:sphere {
+    dr3d-sphere-attlist,
+    common-draw-z-index-attlist,
+    common-draw-id-attlist,
+    common-draw-layer-name-attlist,
+    common-draw-style-name-attlist,
+    common-dr3d-transform-attlist,
     empty
   }
-table-content-validations =
-  element table:content-validations { table-content-validation+ }
-table-content-validation =
-  element table:content-validation {
-    table-validation-attlist,
-    table-help-message?,
-    (table-error-message | (table-error-macro, office-event-listeners))?
+dr3d-sphere-attlist =
+  attribute dr3d:center { vector3D }?
+  & attribute dr3d:size { vector3D }?
+draw-a = element draw:a { draw-a-attlist, shape-instance }
+draw-a-attlist =
+  attribute xlink:type { "simple" }
+  & attribute xlink:href { anyIRI }
+  & attribute xlink:actuate { "onRequest" }?
+  & attribute office:target-frame-name { targetFrameName }?
+  & attribute xlink:show { "new" | "replace" }?
+  & attribute office:name { \string }?
+  & attribute office:title { \string }?
+  & attribute office:server-map { boolean }?
+  & xml-id?
+draw-applet =
+  element draw:applet {
+    draw-applet-attlist, common-draw-data-attlist?, draw-param*
   }
-table-validation-attlist =
-  attribute table:name { \string }
-  & attribute table:condition { \string }?
-  & attribute table:base-cell-address { cellAddress }?
-  & attribute table:allow-empty-cell { boolean }?
-  & attribute table:display-list {
-      "none" | "unsorted" | "sort-ascending"
-    }?
-table-help-message =
-  element table:help-message {
-    attribute table:title { \string }?,
-    attribute table:display { boolean }?,
-    text-p*
+draw-applet-attlist =
+  attribute draw:code { \string }?
+  & attribute draw:object { \string }?
+  & attribute draw:archive { \string }?
+  & attribute draw:may-script { boolean }?
+  & xml-id?
+draw-area-circle =
+  element draw:area-circle {
+    common-draw-area-attlist,
+    attribute svg:cx { coordinate },
+    attribute svg:cy { coordinate },
+    attribute svg:r { length },
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?
   }
-table-error-message =
-  element table:error-message {
-    attribute table:title { \string }?,
-    attribute table:display { boolean }?,
-    attribute table:message-type {
-      "stop" | "warning" | "information"
-    }?,
-    text-p*
+draw-area-polygon =
+  element draw:area-polygon {
+    common-draw-area-attlist,
+    attribute svg:x { coordinate },
+    attribute svg:y { coordinate },
+    attribute svg:width { length },
+    attribute svg:height { length },
+    common-draw-viewbox-attlist,
+    common-draw-points-attlist,
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?
   }
-table-error-macro =
-  element table:error-macro {
-    attribute table:execute { boolean }?
+draw-area-rectangle =
+  element draw:area-rectangle {
+    common-draw-area-attlist,
+    attribute svg:x { coordinate },
+    attribute svg:y { coordinate },
+    attribute svg:width { length },
+    attribute svg:height { length },
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?
   }
-table-label-ranges = element table:label-ranges { table-label-range* }
-table-label-range =
-  element table:label-range { table-label-range-attlist, empty }
-table-label-range-attlist =
-  attribute table:label-cell-range-address { cellRangeAddress }
-  & attribute table:data-cell-range-address { cellRangeAddress }
-  & attribute table:orientation { "column" | "row" }
-table-named-expressions =
-  element table:named-expressions {
-    (table-named-range | table-named-expression)*
+draw-caption =
+  element draw:caption {
+    draw-caption-attlist,
+    common-draw-position-attlist,
+    common-draw-size-attlist,
+    common-draw-shape-with-text-and-styles-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?,
+    draw-glue-point*,
+    draw-text
   }
-table-named-range =
-  element table:named-range { table-named-range-attlist, empty }
-table-named-range-attlist =
-  attribute table:name { \string },
-  attribute table:cell-range-address { cellRangeAddress },
-  attribute table:base-cell-address { cellAddress }?,
-  attribute table:range-usable-as {
-    "none"
-    | list {
-        ("print-range" | "filter" | "repeat-row" | "repeat-column")+
-      }
-  }?
-table-named-expression =
-  element table:named-expression {
-    table-named-expression-attlist, empty
-  }
-table-named-expression-attlist =
-  attribute table:name { \string },
-  attribute table:expression { \string },
-  attribute table:base-cell-address { cellAddress }?
-table-database-ranges =
-  element table:database-ranges { table-database-range* }
-table-database-range =
-  element table:database-range {
-    table-database-range-attlist,
-    (table-database-source-sql
-     | table-database-source-table
-     | table-database-source-query)?,
-    table-filter?,
-    table-sort?,
-    table-subtotal-rules?
-  }
-table-database-range-attlist =
-  attribute table:name { \string }?
-  & attribute table:is-selection { boolean }?
-  & attribute table:on-update-keep-styles { boolean }?
-  & attribute table:on-update-keep-size { boolean }?
-  & attribute table:has-persistent-data { boolean }?
-  & attribute table:orientation { "column" | "row" }?
-  & attribute table:contains-header { boolean }?
-  & attribute table:display-filter-buttons { boolean }?
-  & attribute table:target-range-address { cellRangeAddress }
-  & attribute table:refresh-delay { boolean }?
-table-database-source-sql =
-  element table:database-source-sql {
-    table-database-source-sql-attlist, empty
-  }
-table-database-source-sql-attlist =
-  attribute table:database-name { \string }
-  & attribute table:sql-statement { \string }
-  & attribute table:parse-sql-statement { boolean }?
-table-database-source-query =
-  element table:database-source-table {
-    table-database-source-table-attlist, empty
+draw-caption-attlist =
+  (attribute draw:caption-point-x { coordinate },
+   attribute draw:caption-point-y { coordinate })?
+  & attribute draw:corner-radius { nonNegativeLength }?
+draw-circle =
+  element draw:circle {
+    ((draw-circle-attlist, common-draw-circle-ellipse-pos-attlist)
+     | (common-draw-position-attlist, common-draw-size-attlist)),
+    common-draw-circle-ellipse-attlist,
+    common-draw-shape-with-text-and-styles-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?,
+    draw-glue-point*,
+    draw-text
   }
-table-database-source-table-attlist =
-  attribute table:database-name { \string }
-  & attribute table:database-table-name { \string }
-table-database-source-table =
-  element table:database-source-query {
-    table-database-source-query-attlist, empty
+draw-circle-attlist = attribute svg:r { length }
+draw-connector =
+  element draw:connector {
+    draw-connector-attlist,
+    common-draw-shape-with-text-and-styles-attlist,
+    common-draw-caption-id-attlist,
+    common-draw-viewbox-attlist,
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?,
+    draw-glue-point*,
+    draw-text
   }
-table-database-source-query-attlist =
-  attribute table:database-name { \string }
-  & attribute table:query-name { \string }
-table-sort = element table:sort { table-sort-attlist, table-sort-by+ }
-table-sort-attlist =
-  attribute table:bind-styles-to-content { boolean }?
-  & attribute table:target-range-address { cellRangeAddress }?
-  & attribute table:case-sensitive { boolean }?
-  & attribute table:language { languageCode }?
-  & attribute table:country { countryCode }?
-  & attribute table:script { scriptCode }?
-  & attribute table:rfc-language-tag { language }?
-  & attribute table:algorithm { \string }?
-  & attribute table:embedded-number-behavior {
-      "alpha-numeric" | "integer" | "double"
-    }?
-table-sort-by = element table:sort-by { table-sort-by-attlist, empty }
-table-sort-by-attlist =
-  attribute table:field-number { nonNegativeInteger }
-  & attribute table:data-type {
-      "text" | "number" | "automatic" | \string
+draw-connector-attlist =
+  attribute draw:type { "standard" | "lines" | "line" | "curve" }?
+  & (attribute svg:x1 { coordinate },
+     attribute svg:y1 { coordinate })?
+  & attribute draw:start-shape { IDREF }?
+  & attribute draw:start-glue-point { nonNegativeInteger }?
+  & (attribute svg:x2 { coordinate },
+     attribute svg:y2 { coordinate })?
+  & attribute draw:end-shape { IDREF }?
+  & attribute draw:end-glue-point { nonNegativeInteger }?
+  & attribute draw:line-skew {
+      list { length, (length, length?)? }
     }?
-  & attribute table:order { "ascending" | "descending" }?
-table-subtotal-rules =
-  element table:subtotal-rules {
-    table-subtotal-rules-attlist,
-    table-sort-groups?,
-    table-subtotal-rule*
-  }
-table-subtotal-rules-attlist =
-  attribute table:bind-styles-to-content { boolean }?
-  & attribute table:case-sensitive { boolean }?
-  & attribute table:page-breaks-on-group-change { boolean }?
-table-sort-groups =
-  element table:sort-groups { table-sort-groups-attlist, empty }
-table-sort-groups-attlist =
-  attribute table:data-type {
-    "text" | "number" | "automatic" | \string
-  }?
-  & attribute table:order { "ascending" | "descending" }?
-table-subtotal-rule =
-  element table:subtotal-rule {
-    table-subtotal-rule-attlist, table-subtotal-field*
-  }
-table-subtotal-rule-attlist =
-  attribute table:group-by-field-number { nonNegativeInteger }
-table-subtotal-field =
-  element table:subtotal-field { table-subtotal-field-attlist, empty }
-table-subtotal-field-attlist =
-  attribute table:field-number { nonNegativeInteger }
-  & attribute table:function {
-      "average"
-      | "count"
-      | "countnums"
-      | "max"
-      | "min"
-      | "product"
-      | "stdev"
-      | "stdevp"
-      | "sum"
-      | "var"
-      | "varp"
-      | \string
-    }
-table-filter =
-  element table:filter {
-    table-filter-attlist,
-    (table-filter-condition | table-filter-and | table-filter-or)
+  & attribute svg:d { pathData }?
+draw-contour-path =
+  element draw:contour-path {
+    common-contour-attlist,
+    common-draw-size-attlist,
+    common-draw-viewbox-attlist,
+    common-draw-path-data-attlist,
+    empty
   }
-table-filter-attlist =
-  attribute table:target-range-address { cellRangeAddress }?
-  & attribute table:condition-source { "self" | "cell-range" }?
-  & attribute table:condition-source-range-address { cellRangeAddress }?
-  & attribute table:display-duplicates { boolean }?
-table-filter-and =
-  element table:filter-and {
-    (table-filter-or | table-filter-condition)+
+draw-contour-polygon =
+  element draw:contour-polygon {
+    common-contour-attlist,
+    common-draw-size-attlist,
+    common-draw-viewbox-attlist,
+    common-draw-points-attlist,
+    empty
   }
-table-filter-or =
-  element table:filter-or {
-    (table-filter-and | table-filter-condition)+
+draw-control =
+  element draw:control {
+    draw-control-attlist,
+    common-draw-position-attlist,
+    common-draw-size-attlist,
+    common-draw-shape-with-text-and-styles-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?,
+    draw-glue-point*
   }
-table-filter-condition =
-  element table:filter-condition {
-    table-filter-condition-attlist, table-filter-set-item*
+draw-control-attlist = attribute draw:control { IDREF }
+draw-custom-shape =
+  element draw:custom-shape {
+    draw-custom-shape-attlist,
+    common-draw-position-attlist,
+    common-draw-size-attlist,
+    common-draw-shape-with-text-and-styles-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?,
+    draw-glue-point*,
+    draw-text,
+    draw-enhanced-geometry?
   }
-table-filter-condition-attlist =
-  attribute table:field-number { nonNegativeInteger }
-  & attribute table:value { \string | double }
-  & attribute table:operator { \string }
-  & attribute table:case-sensitive { \string }?
-  & attribute table:data-type { "text" | "number" }?
-table-filter-set-item =
-  element table:filter-set-item {
-    attribute table:value { \string },
-    empty
+draw-custom-shape-attlist =
+  attribute draw:engine { namespacedToken }?
+  & attribute draw:data { \string }?
+draw-ellipse =
+  element draw:ellipse {
+    ((draw-ellipse-attlist, common-draw-circle-ellipse-pos-attlist)
+     | (common-draw-position-attlist, common-draw-size-attlist)),
+    common-draw-circle-ellipse-attlist,
+    common-draw-shape-with-text-and-styles-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?,
+    draw-glue-point*,
+    draw-text
   }
-table-data-pilot-tables =
-  element table:data-pilot-tables { table-data-pilot-table* }
-table-data-pilot-table =
-  element table:data-pilot-table {
-    table-data-pilot-table-attlist,
-    (table-database-source-sql
-     | table-database-source-table
-     | table-database-source-query
-     | table-source-service
-     | table-source-cell-range)?,
-    table-data-pilot-field+
+draw-ellipse-attlist =
+  attribute svg:rx { length },
+  attribute svg:ry { length }
+draw-enhanced-geometry =
+  element draw:enhanced-geometry {
+    draw-enhanced-geometry-attlist, draw-equation*, draw-handle*
   }
-table-data-pilot-table-attlist =
-  attribute table:name { \string }
-  & attribute table:application-data { \string }?
-  & attribute table:grand-total { "none" | "row" | "column" | "both" }?
-  & attribute table:ignore-empty-rows { boolean }?
-  & attribute table:identify-categories { boolean }?
-  & attribute table:target-range-address { cellRangeAddress }
-  & attribute table:buttons { cellRangeAddressList }?
-  & attribute table:show-filter-button { boolean }?
-  & attribute table:drill-down-on-double-click { boolean }?
-table-source-cell-range =
-  element table:source-cell-range {
-    table-source-cell-range-attlist, table-filter?
-  }
-table-source-cell-range-attlist =
-  attribute table:cell-range-address { cellRangeAddress }
-table-source-service =
-  element table:source-service { table-source-service-attlist, empty }
-table-source-service-attlist =
-  attribute table:name { \string }
-  & attribute table:source-name { \string }
-  & attribute table:object-name { \string }
-  & attribute table:user-name { \string }?
-  & attribute table:password { \string }?
-table-data-pilot-field =
-  element table:data-pilot-field {
-    table-data-pilot-field-attlist,
-    table-data-pilot-level?,
-    table-data-pilot-field-reference?,
-    table-data-pilot-groups?
-  }
-table-data-pilot-field-attlist =
-  attribute table:source-field-name { \string }
-  & (attribute table:orientation {
-       "row" | "column" | "data" | "hidden"
-     }
-     | (attribute table:orientation { "page" },
-        attribute table:selected-page { \string }))
-  & attribute table:is-data-layout-field { \string }?
-  & attribute table:function {
-      "auto"
-      | "average"
-      | "count"
-      | "countnums"
-      | "max"
-      | "min"
-      | "product"
-      | "stdev"
-      | "stdevp"
-      | "sum"
-      | "var"
-      | "varp"
-      | \string
+draw-enhanced-geometry-attlist =
+  attribute draw:type { custom-shape-type }?
+  & attribute svg:viewBox {
+      list { integer, integer, integer, integer }
     }?
-  & attribute table:used-hierarchy { integer }?
-table-data-pilot-level =
-  element table:data-pilot-level {
-    table-data-pilot-level-attlist,
-    table-data-pilot-subtotals?,
-    table-data-pilot-members?,
-    table-data-pilot-display-info?,
-    table-data-pilot-sort-info?,
-    table-data-pilot-layout-info?
-  }
-table-data-pilot-level-attlist = attribute table:show-empty { boolean }?
-table-data-pilot-subtotals =
-  element table:data-pilot-subtotals { table-data-pilot-subtotal* }
-table-data-pilot-subtotal =
-  element table:data-pilot-subtotal {
-    table-data-pilot-subtotal-attlist, empty
-  }
-table-data-pilot-subtotal-attlist =
-  attribute table:function {
-    "auto"
-    | "average"
-    | "count"
-    | "countnums"
-    | "max"
-    | "min"
-    | "product"
-    | "stdev"
-    | "stdevp"
-    | "sum"
-    | "var"
-    | "varp"
-    | \string
+  & attribute draw:mirror-vertical { boolean }?
+  & attribute draw:mirror-horizontal { boolean }?
+  & attribute draw:text-rotate-angle { angle }?
+  & attribute draw:extrusion-allowed { boolean }?
+  & attribute draw:text-path-allowed { boolean }?
+  & attribute draw:concentric-gradient-fill-allowed { boolean }?
+  & attribute draw:extrusion { boolean }?
+  & attribute draw:extrusion-brightness { zeroToHundredPercent }?
+  & attribute draw:extrusion-depth {
+      list { length, double }
+    }?
+  & attribute draw:extrusion-diffusion { percent }?
+  & attribute draw:extrusion-number-of-line-segments { integer }?
+  & attribute draw:extrusion-light-face { boolean }?
+  & attribute draw:extrusion-first-light-harsh { boolean }?
+  & attribute draw:extrusion-second-light-harsh { boolean }?
+  & attribute draw:extrusion-first-light-level { zeroToHundredPercent }?
+  & attribute draw:extrusion-second-light-level {
+      zeroToHundredPercent
+    }?
+  & attribute draw:extrusion-first-light-direction { vector3D }?
+  & attribute draw:extrusion-second-light-direction { vector3D }?
+  & attribute draw:extrusion-metal { boolean }?
+  & attribute dr3d:shade-mode {
+      "flat" | "phong" | "gouraud" | "draft"
+    }?
+  & attribute draw:extrusion-rotation-angle {
+      list { angle, angle }
+    }?
+  & attribute draw:extrusion-rotation-center { vector3D }?
+  & attribute draw:extrusion-shininess { zeroToHundredPercent }?
+  & attribute draw:extrusion-skew {
+      list { double, angle }
+    }?
+  & attribute draw:extrusion-specularity { zeroToHundredPercent }?
+  & attribute dr3d:projection { "parallel" | "perspective" }?
+  & attribute draw:extrusion-viewpoint { point3D }?
+  & attribute draw:extrusion-origin {
+      list { extrusionOrigin, extrusionOrigin }
+    }?
+  & attribute draw:extrusion-color { boolean }?
+  & attribute draw:enhanced-path { \string }?
+  & attribute draw:path-stretchpoint-x { double }?
+  & attribute draw:path-stretchpoint-y { double }?
+  & attribute draw:text-areas { \string }?
+  & attribute draw:glue-points { \string }?
+  & attribute draw:glue-point-type {
+      "none" | "segments" | "rectangle"
+    }?
+  & attribute draw:glue-point-leaving-directions { \string }?
+  & attribute draw:text-path { boolean }?
+  & attribute draw:text-path-mode { "normal" | "path" | "shape" }?
+  & attribute draw:text-path-scale { "path" | "shape" }?
+  & attribute draw:text-path-same-letter-heights { boolean }?
+  & attribute draw:modifiers { \string }?
+draw-equation = element draw:equation { draw-equation-attlist, empty }
+draw-equation-attlist =
+  attribute draw:name { \string }?
+  & attribute draw:formula { \string }?
+draw-fill-image =
+  element draw:fill-image {
+    draw-fill-image-attlist,
+    # XLink duplicate declaration removed. see common-draw-data-attlist
+    ((common-draw-data-attlist, empty) | office-binary-data)
+    # https://issues.oasis-open.org/browse/OFFICE-3933
+
   }
-table-data-pilot-members =
-  element table:data-pilot-members { table-data-pilot-member* }
-table-data-pilot-member =
-  element table:data-pilot-member {
-    table-data-pilot-member-attlist, empty
+draw-fill-image-attlist =
+  attribute draw:name { styleName }
+  & attribute draw:display-name { \string }?
+  & attribute svg:width { length }?
+  & attribute svg:height { length }?
+draw-floating-frame =
+  element draw:floating-frame {
+    draw-floating-frame-attlist, common-draw-data-attlist
   }
-table-data-pilot-member-attlist =
-  attribute table:name { \string }
-  & attribute table:display { boolean }?
-  & attribute table:show-details { boolean }?
-table-data-pilot-display-info =
-  element table:data-pilot-display-info {
-    table-data-pilot-display-info-attlist, empty
+draw-floating-frame-attlist =
+  attribute draw:frame-name { \string }?
+  & xml-id?
+draw-frame =
+  element draw:frame {
+    common-draw-shape-with-text-and-styles-attlist,
+    common-draw-position-attlist,
+    common-draw-rel-size-attlist,
+    common-draw-caption-id-attlist,
+    presentation-shape-attlist,
+    draw-frame-attlist,
+    (draw-text-box
+     | draw-image
+     | draw-object
+     | draw-object-ole
+     | draw-applet
+     | draw-floating-frame
+     | draw-plugin
+     | table-table)*,
+    office-event-listeners?,
+    draw-glue-point*,
+    draw-image-map?,
+    svg-title?,
+    svg-desc?,
+    (draw-contour-polygon | draw-contour-path)?
   }
-table-data-pilot-display-info-attlist =
-  attribute table:enabled { boolean }
-  & attribute table:data-field { \string }
-  & attribute table:member-count { nonNegativeInteger }
-  & attribute table:display-member-mode { "from-top" | "from-bottom" }
-table-data-pilot-sort-info =
-  element table:data-pilot-sort-info {
-    table-data-pilot-sort-info-attlist, empty
+draw-frame-attlist = attribute draw:copy-of { \string }?
+draw-g =
+  element draw:g {
+    draw-g-attlist,
+    common-draw-z-index-attlist,
+    common-draw-name-attlist,
+    common-draw-id-attlist,
+    common-draw-style-name-attlist,
+    common-text-spreadsheet-shape-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?,
+    draw-glue-point*,
+    shape*
   }
-table-data-pilot-sort-info-attlist =
-  ((attribute table:sort-mode { "data" },
-    attribute table:data-field { \string })
-   | attribute table:sort-mode { "none" | "manual" | "name" })
-  & attribute table:order { "ascending" | "descending" }
-table-data-pilot-layout-info =
-  element table:data-pilot-layout-info {
-    table-data-pilot-layout-info-attlist, empty
+draw-g-attlist = attribute svg:y { coordinate }?
+draw-glue-point =
+  element draw:glue-point { draw-glue-point-attlist, empty }
+draw-glue-point-attlist =
+  attribute draw:id { nonNegativeInteger }
+  & attribute svg:x { distance | percent }
+  & attribute svg:y { distance | percent }
+  & attribute draw:align {
+      "top-left"
+      | "top"
+      | "top-right"
+      | "left"
+      | "center"
+      | "right"
+      | "bottom-left"
+      | "bottom-right"
+    }?
+  & attribute draw:escape-direction {
+      "auto"
+      | "left"
+      | "right"
+      | "up"
+      | "down"
+      | "horizontal"
+      | "vertical"
+    }
+draw-gradient =
+  element draw:gradient {
+    common-draw-gradient-attlist, draw-gradient-attlist, empty
   }
-table-data-pilot-layout-info-attlist =
-  attribute table:layout-mode {
-    "tabular-layout"
-    | "outline-subtotals-top"
-    | "outline-subtotals-bottom"
-  }
-  & attribute table:add-empty-lines { boolean }
-table-data-pilot-field-reference =
-  element table:data-pilot-field-reference {
-    table-data-pilot-field-reference-attlist
-  }
-table-data-pilot-field-reference-attlist =
-  attribute table:field-name { \string }
-  & ((attribute table:member-type { "named" },
-      attribute table:member-name { \string })
-     | attribute table:member-type { "previous" | "next" })
-  & attribute table:type {
-      "none"
-      | "member-difference"
-      | "member-percentage"
-      | "member-percentage-difference"
-      | "running-total"
-      | "row-percentage"
-      | "column-percentage"
-      | "total-percentage"
-      | "index"
-    }
-table-data-pilot-groups =
-  element table:data-pilot-groups {
-    table-data-pilot-groups-attlist, table-data-pilot-group+
-  }
-table-data-pilot-groups-attlist =
-  attribute table:source-field-name { \string }
-  & (attribute table:date-start { dateOrDateTime | "auto" }
-     | attribute table:start { double | "auto" })
-  & (attribute table:date-end { dateOrDateTime | "auto" }
-     | attribute table:end { double | "auto" })
-  & attribute table:step { double }
-  & attribute table:grouped-by {
-      "seconds"
-      | "minutes"
-      | "hours"
-      | "days"
-      | "months"
-      | "quarters"
-      | "years"
-    }
-table-data-pilot-group =
-  element table:data-pilot-group {
-    table-data-pilot-group-attlist, table-data-pilot-group-member+
-  }
-table-data-pilot-group-attlist = attribute table:name { \string }
-table-data-pilot-group-member =
-  element table:data-pilot-group-member {
-    table-data-pilot-group-member-attlist
-  }
-table-data-pilot-group-member-attlist = attribute table:name { \string }
-table-consolidation =
-  element table:consolidation { table-consolidation-attlist, empty }
-table-consolidation-attlist =
-  attribute table:function {
-    "average"
-    | "count"
-    | "countnums"
-    | "max"
-    | "min"
-    | "product"
-    | "stdev"
-    | "stdevp"
-    | "sum"
-    | "var"
-    | "varp"
-    | \string
+draw-gradient-attlist =
+  attribute draw:start-color { color }?
+  & attribute draw:end-color { color }?
+  & attribute draw:start-intensity { zeroToHundredPercent }?
+  & attribute draw:end-intensity { zeroToHundredPercent }?
+draw-handle = element draw:handle { draw-handle-attlist, empty }
+draw-handle-attlist =
+  attribute draw:handle-mirror-vertical { boolean }?
+  & attribute draw:handle-mirror-horizontal { boolean }?
+  & attribute draw:handle-switched { boolean }?
+  & attribute draw:handle-position { \string }
+  & attribute draw:handle-range-x-minimum { \string }?
+  & attribute draw:handle-range-x-maximum { \string }?
+  & attribute draw:handle-range-y-minimum { \string }?
+  & attribute draw:handle-range-y-maximum { \string }?
+  & attribute draw:handle-polar { \string }?
+  & attribute draw:handle-radius-range-minimum { \string }?
+  & attribute draw:handle-radius-range-maximum { \string }?
+draw-hatch = element draw:hatch { draw-hatch-attlist, empty }
+draw-hatch-attlist =
+  attribute draw:name { styleName }
+  & attribute draw:display-name { \string }?
+  & attribute draw:style { "single" | "double" | "triple" }
+  & attribute draw:color { color }?
+  & attribute draw:distance { length }?
+  & attribute draw:rotation { angle }?
+draw-image =
+  element draw:image {
+    draw-image-attlist,
+    (common-draw-data-attlist | office-binary-data),
+    draw-text
   }
-  & attribute table:source-cell-range-addresses { cellRangeAddressList }
-  & attribute table:target-cell-address { cellAddress }
-  & attribute table:use-labels { "none" | "row" | "column" | "both" }?
-  & attribute table:link-to-source-data { boolean }?
-table-dde-links = element table:dde-links { table-dde-link+ }
-table-tracked-changes =
-  element table:tracked-changes {
-    table-tracked-changes-attlist,
-    (table-cell-content-change
-     | table-insertion
-     | table-deletion
-     | table-movement)*
+draw-image-attlist =
+  attribute draw:filter-name { \string }?
+  & common-draw-mime-type-attlist
+  & # https://issues.oasis-open.org/browse/OFFICE-3943
+    xml-id?
+draw-image-map =
+  element draw:image-map {
+    (draw-area-rectangle | draw-area-circle | draw-area-polygon)*
   }
-table-tracked-changes-attlist =
-  attribute table:track-changes { boolean }?
-table-insertion =
-  element table:insertion {
-    table-insertion-attlist,
-    common-table-change-attlist,
-    office-change-info,
-    table-dependencies?,
-    table-deletions?
+draw-layer =
+  element draw:layer { draw-layer-attlist, svg-title?, svg-desc? }
+draw-layer-attlist =
+  attribute draw:name { \string }
+  & attribute draw:protected { boolean }?
+  & attribute draw:display { "always" | "screen" | "printer" | "none" }?
+draw-layer-set = element draw:layer-set { draw-layer* }
+draw-line =
+  element draw:line {
+    draw-line-attlist,
+    common-draw-shape-with-text-and-styles-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?,
+    draw-glue-point*,
+    draw-text
   }
-table-insertion-attlist =
-  attribute table:type { "row" | "column" | "table" }
-  & attribute table:position { integer }
-  & attribute table:count { positiveInteger }?
-  & attribute table:table { integer }?
-table-dependencies = element table:dependencies { table-dependency+ }
-table-dependency =
-  element table:dependency {
-    attribute table:id { \string },
+draw-line-attlist =
+  attribute svg:x1 { coordinate }
+  & attribute svg:y1 { coordinate }
+  & attribute svg:x2 { coordinate }
+  & attribute svg:y2 { coordinate }
+draw-marker =
+  element draw:marker {
+    draw-marker-attlist,
+    common-draw-viewbox-attlist,
+    common-draw-path-data-attlist,
     empty
   }
-table-deletions =
-  element table:deletions {
-    (table-cell-content-deletion | table-change-deletion)+
-  }
-table-cell-content-deletion =
-  element table:cell-content-deletion {
-    attribute table:id { \string }?,
-    table-cell-address?,
-    table-change-track-table-cell?
-  }
-table-change-deletion =
-  element table:change-deletion {
-    attribute table:id { \string }?,
-    empty
+draw-marker-attlist =
+  attribute draw:name { styleName }
+  & attribute draw:display-name { \string }?
+draw-measure =
+  element draw:measure {
+    draw-measure-attlist,
+    common-draw-shape-with-text-and-styles-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?,
+    office-event-listeners?,
+    draw-glue-point*,
+    draw-text
   }
-table-deletion =
-  element table:deletion {
-    table-deletion-attlist,
-    common-table-change-attlist,
-    office-change-info,
-    table-dependencies?,
-    table-deletions?,
-    table-cut-offs?
+draw-measure-attlist =
+  attribute svg:x1 { coordinate }
+  & attribute svg:y1 { coordinate }
+  & attribute svg:x2 { coordinate }
+  & attribute svg:y2 { coordinate }
+draw-object =
+  element draw:object {
+    draw-object-attlist,
+    (common-draw-data-attlist | office-document | math-math)
   }
-table-deletion-attlist =
-  attribute table:type { "row" | "column" | "table" }
-  & attribute table:position { integer }
-  & attribute table:table { integer }?
-  & attribute table:multi-deletion-spanned { integer }?
-table-cut-offs =
-  element table:cut-offs {
-    table-movement-cut-off+
-    | (table-insertion-cut-off, table-movement-cut-off*)
+draw-object-attlist =
+  attribute draw:notify-on-update-of-ranges {
+    cellRangeAddressList | \string
+  }?
+  & xml-id?
+draw-object-ole =
+  element draw:object-ole {
+    draw-object-ole-attlist,
+    (common-draw-data-attlist | office-binary-data)
   }
-table-insertion-cut-off =
-  element table:insertion-cut-off {
-    table-insertion-cut-off-attlist, empty
+draw-object-ole-attlist =
+  attribute draw:class-id { \string }?
+  & xml-id?
+draw-opacity =
+  element draw:opacity {
+    common-draw-gradient-attlist, draw-opacity-attlist, empty
   }
-table-insertion-cut-off-attlist =
-  attribute table:id { \string }
-  & attribute table:position { integer }
-table-movement-cut-off =
-  element table:movement-cut-off {
-    table-movement-cut-off-attlist, empty
-  }
-table-movement-cut-off-attlist =
-  attribute table:position { integer }
-  | (attribute table:start-position { integer },
-     attribute table:end-position { integer })
-table-movement =
-  element table:movement {
-    common-table-change-attlist,
-    table-source-range-address,
-    table-target-range-address,
-    office-change-info,
-    table-dependencies?,
-    table-deletions?
-  }
-table-source-range-address =
-  element table:source-range-address {
-    common-table-range-attlist, empty
-  }
-table-target-range-address =
-  element table:target-range-address {
-    common-table-range-attlist, empty
-  }
-common-table-range-attlist =
-  common-table-cell-address-attlist
-  | common-table-cell-range-address-attlist
-common-table-cell-address-attlist =
-  attribute table:column { integer },
-  attribute table:row { integer },
-  attribute table:table { integer }
-common-table-cell-range-address-attlist =
-  attribute table:start-column { integer },
-  attribute table:start-row { integer },
-  attribute table:start-table { integer },
-  attribute table:end-column { integer },
-  attribute table:end-row { integer },
-  attribute table:end-table { integer }
-table-change-track-table-cell =
-  element table:change-track-table-cell {
-    table-change-track-table-cell-attlist, text-p*
-  }
-table-change-track-table-cell-attlist =
-  attribute table:cell-address { cellAddress }?
-  & attribute table:matrix-covered { boolean }?
-  & attribute table:formula { \string }?
-  & attribute table:number-matrix-columns-spanned { positiveInteger }?
-  & attribute table:number-matrix-rows-spanned { positiveInteger }?
-  & common-value-and-type-attlist?
-table-cell-content-change =
-  element table:cell-content-change {
-    common-table-change-attlist,
-    table-cell-address,
-    office-change-info,
-    table-dependencies?,
-    table-deletions?,
-    table-previous
-  }
-table-cell-address =
-  element table:cell-address {
-    common-table-cell-address-attlist, empty
-  }
-table-previous =
-  element table:previous {
-    attribute table:id { \string }?,
-    table-change-track-table-cell
-  }
-common-table-change-attlist =
-  attribute table:id { \string }
-  & attribute table:acceptance-state {
-      "accepted" | "rejected" | "pending"
-    }?
-  & attribute table:rejecting-change-id { \string }?
-style-handout-master =
-  element style:handout-master {
-    common-presentation-header-footer-attlist,
-    style-handout-master-attlist,
-    shape*
-  }
-style-handout-master-attlist =
-  attribute presentation:presentation-page-layout-name { styleNameRef }?
-  & attribute style:page-layout-name { styleNameRef }
-  & attribute draw:style-name { styleNameRef }?
-draw-layer-set = element draw:layer-set { draw-layer* }
-draw-layer =
-  element draw:layer { draw-layer-attlist, svg-title?, svg-desc? }
-draw-layer-attlist =
-  attribute draw:name { \string }
-  & attribute draw:protected { boolean }?
-  & attribute draw:display { "always" | "screen" | "printer" | "none" }?
-draw-page =
-  element draw:page {
-    common-presentation-header-footer-attlist,
-    draw-page-attlist,
-    svg-title?,
-    svg-desc?,
-    draw-layer-set?,
-    office-forms?,
-    shape*,
-    (presentation-animations | animation-element)?,
-    presentation-notes?
+draw-opacity-attlist =
+  attribute draw:start { zeroToHundredPercent }?,
+  attribute draw:end { zeroToHundredPercent }?
+draw-page =
+  element draw:page {
+    common-presentation-header-footer-attlist,
+    draw-page-attlist,
+    svg-title?,
+    svg-desc?,
+    draw-layer-set?,
+    office-forms?,
+    shape*,
+    (presentation-animations | animation-element)?,
+    presentation-notes?
   }
 draw-page-attlist =
   attribute draw:name { \string }?
@@ -2153,34 +1921,29 @@ draw-page-attlist =
   & (xml-id,
      attribute draw:id { NCName }?)?
   & attribute draw:nav-order { IDREFS }?
-common-presentation-header-footer-attlist =
-  attribute presentation:use-header-name { \string }?
-  & attribute presentation:use-footer-name { \string }?
-  & attribute presentation:use-date-time-name { \string }?
-shape = shape-instance | draw-a
-shape-instance =
-  draw-rect
-  | draw-line
-  | draw-polyline
-  | draw-polygon
-  | draw-regular-polygon
-  | draw-path
-  | draw-circle
-  | draw-ellipse
-  | draw-g
-  | draw-page-thumbnail
-  | draw-frame
-  | draw-measure
-  | draw-caption
-  | draw-connector
-  | draw-control
-  | dr3d-scene
-  | draw-custom-shape
-draw-rect =
-  element draw:rect {
-    draw-rect-attlist,
+draw-page-thumbnail =
+  element draw:page-thumbnail {
+    draw-page-thumbnail-attlist,
+    common-draw-position-attlist,
+    common-draw-size-attlist,
+    presentation-shape-attlist,
+    common-draw-shape-with-styles-attlist,
+    common-draw-caption-id-attlist,
+    svg-title?,
+    svg-desc?
+  }
+draw-page-thumbnail-attlist =
+  attribute draw:page-number { positiveInteger }?
+draw-param = element draw:param { draw-param-attlist, empty }
+draw-param-attlist =
+  attribute draw:name { \string }?
+  & attribute draw:value { \string }?
+draw-path =
+  element draw:path {
+    common-draw-path-data-attlist,
     common-draw-position-attlist,
     common-draw-size-attlist,
+    common-draw-viewbox-attlist,
     common-draw-shape-with-text-and-styles-attlist,
     common-draw-caption-id-attlist,
     svg-title?,
@@ -2189,13 +1952,18 @@ draw-rect =
     draw-glue-point*,
     draw-text
   }
-draw-rect-attlist =
-  attribute draw:corner-radius { nonNegativeLength }?
-  | (attribute svg:rx { nonNegativeLength }?,
-     attribute svg:ry { nonNegativeLength }?)
-draw-line =
-  element draw:line {
-    draw-line-attlist,
+draw-plugin =
+  element draw:plugin {
+    draw-plugin-attlist, common-draw-data-attlist, draw-param*
+  }
+draw-plugin-attlist = common-draw-mime-type-attlist & xml-id?
+# https://issues.oasis-open.org/browse/OFFICE-3943
+draw-polygon =
+  element draw:polygon {
+    common-draw-points-attlist,
+    common-draw-position-attlist,
+    common-draw-size-attlist,
+    common-draw-viewbox-attlist,
     common-draw-shape-with-text-and-styles-attlist,
     common-draw-caption-id-attlist,
     svg-title?,
@@ -2204,11 +1972,6 @@ draw-line =
     draw-glue-point*,
     draw-text
   }
-draw-line-attlist =
-  attribute svg:x1 { coordinate }
-  & attribute svg:y1 { coordinate }
-  & attribute svg:x2 { coordinate }
-  & attribute svg:y2 { coordinate }
 draw-polyline =
   element draw:polyline {
     common-draw-points-attlist,
@@ -2223,13 +1986,11 @@ draw-polyline =
     draw-glue-point*,
     draw-text
   }
-common-draw-points-attlist = attribute draw:points { points }
-draw-polygon =
-  element draw:polygon {
-    common-draw-points-attlist,
+draw-rect =
+  element draw:rect {
+    draw-rect-attlist,
     common-draw-position-attlist,
     common-draw-size-attlist,
-    common-draw-viewbox-attlist,
     common-draw-shape-with-text-and-styles-attlist,
     common-draw-caption-id-attlist,
     svg-title?,
@@ -2238,6 +1999,10 @@ draw-polygon =
     draw-glue-point*,
     draw-text
   }
+draw-rect-attlist =
+  attribute draw:corner-radius { nonNegativeLength }?
+  | (attribute svg:rx { nonNegativeLength }?,
+     attribute svg:ry { nonNegativeLength }?)
 draw-regular-polygon =
   element draw:regular-polygon {
     draw-regular-polygon-attlist,
@@ -2258,262 +2023,18 @@ draw-regular-polygon-attlist =
   & attribute draw:corners { positiveInteger }
 draw-regular-polygon-sharpness-attlist =
   attribute draw:sharpness { percent }
-draw-path =
-  element draw:path {
-    common-draw-path-data-attlist,
-    common-draw-position-attlist,
-    common-draw-size-attlist,
-    common-draw-viewbox-attlist,
-    common-draw-shape-with-text-and-styles-attlist,
-    common-draw-caption-id-attlist,
-    svg-title?,
-    svg-desc?,
-    office-event-listeners?,
-    draw-glue-point*,
-    draw-text
-  }
-common-draw-path-data-attlist = attribute svg:d { pathData }
-draw-circle =
-  element draw:circle {
-    ((draw-circle-attlist, common-draw-circle-ellipse-pos-attlist)
-     | (common-draw-position-attlist, common-draw-size-attlist)),
-    common-draw-circle-ellipse-attlist,
-    common-draw-shape-with-text-and-styles-attlist,
-    common-draw-caption-id-attlist,
-    svg-title?,
-    svg-desc?,
-    office-event-listeners?,
-    draw-glue-point*,
-    draw-text
-  }
-common-draw-circle-ellipse-pos-attlist =
-  attribute svg:cx { coordinate },
-  attribute svg:cy { coordinate }
-draw-circle-attlist = attribute svg:r { length }
-common-draw-circle-ellipse-attlist =
-  attribute draw:kind { "full" | "section" | "cut" | "arc" }?
-  & attribute draw:start-angle { angle }?
-  & attribute draw:end-angle { angle }?
-draw-ellipse =
-  element draw:ellipse {
-    ((draw-ellipse-attlist, common-draw-circle-ellipse-pos-attlist)
-     | (common-draw-position-attlist, common-draw-size-attlist)),
-    common-draw-circle-ellipse-attlist,
-    common-draw-shape-with-text-and-styles-attlist,
-    common-draw-caption-id-attlist,
-    svg-title?,
-    svg-desc?,
-    office-event-listeners?,
-    draw-glue-point*,
-    draw-text
-  }
-draw-ellipse-attlist =
-  attribute svg:rx { length },
-  attribute svg:ry { length }
-draw-connector =
-  element draw:connector {
-    draw-connector-attlist,
-    common-draw-shape-with-text-and-styles-attlist,
-    common-draw-caption-id-attlist,
-    common-draw-viewbox-attlist,
-    svg-title?,
-    svg-desc?,
-    office-event-listeners?,
-    draw-glue-point*,
-    draw-text
-  }
-draw-connector-attlist =
-  attribute draw:type { "standard" | "lines" | "line" | "curve" }?
-  & (attribute svg:x1 { coordinate },
-     attribute svg:y1 { coordinate })?
-  & attribute draw:start-shape { IDREF }?
-  & attribute draw:start-glue-point { nonNegativeInteger }?
-  & (attribute svg:x2 { coordinate },
-     attribute svg:y2 { coordinate })?
-  & attribute draw:end-shape { IDREF }?
-  & attribute draw:end-glue-point { nonNegativeInteger }?
-  & attribute draw:line-skew {
-      list { length, (length, length?)? }
-    }?
-  & attribute svg:d { pathData }?
-draw-caption =
-  element draw:caption {
-    draw-caption-attlist,
-    common-draw-position-attlist,
-    common-draw-size-attlist,
-    common-draw-shape-with-text-and-styles-attlist,
-    common-draw-caption-id-attlist,
-    svg-title?,
-    svg-desc?,
-    office-event-listeners?,
-    draw-glue-point*,
-    draw-text
-  }
-draw-caption-attlist =
-  (attribute draw:caption-point-x { coordinate },
-   attribute draw:caption-point-y { coordinate })?
-  & attribute draw:corner-radius { nonNegativeLength }?
-draw-measure =
-  element draw:measure {
-    draw-measure-attlist,
-    common-draw-shape-with-text-and-styles-attlist,
-    common-draw-caption-id-attlist,
-    svg-title?,
-    svg-desc?,
-    office-event-listeners?,
-    draw-glue-point*,
-    draw-text
-  }
-draw-measure-attlist =
-  attribute svg:x1 { coordinate }
-  & attribute svg:y1 { coordinate }
-  & attribute svg:x2 { coordinate }
-  & attribute svg:y2 { coordinate }
-draw-control =
-  element draw:control {
-    draw-control-attlist,
-    common-draw-position-attlist,
-    common-draw-size-attlist,
-    common-draw-shape-with-text-and-styles-attlist,
-    common-draw-caption-id-attlist,
-    svg-title?,
-    svg-desc?,
-    draw-glue-point*
-  }
-draw-control-attlist = attribute draw:control { IDREF }
-draw-page-thumbnail =
-  element draw:page-thumbnail {
-    draw-page-thumbnail-attlist,
-    common-draw-position-attlist,
-    common-draw-size-attlist,
-    presentation-shape-attlist,
-    common-draw-shape-with-styles-attlist,
-    common-draw-caption-id-attlist,
-    svg-title?,
-    svg-desc?
-  }
-draw-page-thumbnail-attlist =
-  attribute draw:page-number { positiveInteger }?
-draw-g =
-  element draw:g {
-    draw-g-attlist,
-    common-draw-z-index-attlist,
-    common-draw-name-attlist,
-    common-draw-id-attlist,
-    common-draw-style-name-attlist,
-    common-text-spreadsheet-shape-attlist,
-    common-draw-caption-id-attlist,
-    svg-title?,
-    svg-desc?,
-    office-event-listeners?,
-    draw-glue-point*,
-    shape*
-  }
-draw-g-attlist = attribute svg:y { coordinate }?
-common-draw-name-attlist = attribute draw:name { \string }?
-common-draw-caption-id-attlist = attribute draw:caption-id { IDREF }?
-common-draw-position-attlist =
-  attribute svg:x { coordinate }?,
-  attribute svg:y { coordinate }?
-common-draw-size-attlist =
-  attribute svg:width { length }?,
-  attribute svg:height { length }?
-common-draw-transform-attlist = attribute draw:transform { \string }?
-common-draw-viewbox-attlist =
-  attribute svg:viewBox {
-    list { integer, integer, integer, integer }
-  }
-common-draw-style-name-attlist =
-  (attribute draw:style-name { styleNameRef }?,
-   attribute draw:class-names { styleNameRefs }?)
-  | (attribute presentation:style-name { styleNameRef }?,
-     attribute presentation:class-names { styleNameRefs }?)
-common-draw-text-style-name-attlist =
-  attribute draw:text-style-name { styleNameRef }?
-common-draw-layer-name-attlist = attribute draw:layer { \string }?
-common-draw-id-attlist =
-  (xml-id,
-   attribute draw:id { NCName }?)?
-common-draw-z-index-attlist =
-  attribute draw:z-index { nonNegativeInteger }?
-common-text-spreadsheet-shape-attlist =
-  attribute table:end-cell-address { cellAddress }?
-  & attribute table:end-x { coordinate }?
-  & attribute table:end-y { coordinate }?
-  & attribute table:table-background { boolean }?
-  & common-text-anchor-attlist
-common-text-anchor-attlist =
-  attribute text:anchor-type {
-    "page" | "frame" | "paragraph" | "char" | "as-char"
-  }?
-  & attribute text:anchor-page-number { positiveInteger }?
+draw-stroke-dash =
+  element draw:stroke-dash { draw-stroke-dash-attlist, empty }
+draw-stroke-dash-attlist =
+  attribute draw:name { styleName }
+  & attribute draw:display-name { \string }?
+  & attribute draw:style { "rect" | "round" }?
+  & attribute draw:dots1 { integer }?
+  & attribute draw:dots1-length { length | percent }?
+  & attribute draw:dots2 { integer }?
+  & attribute draw:dots2-length { length | percent }?
+  & attribute draw:distance { length | percent }?
 draw-text = (text-p | text-list)*
-common-draw-shape-with-styles-attlist =
-  common-draw-z-index-attlist,
-  common-draw-id-attlist,
-  common-draw-layer-name-attlist,
-  common-draw-style-name-attlist,
-  common-draw-transform-attlist,
-  common-draw-name-attlist,
-  common-text-spreadsheet-shape-attlist
-common-draw-shape-with-text-and-styles-attlist =
-  common-draw-shape-with-styles-attlist,
-  common-draw-text-style-name-attlist
-draw-glue-point =
-  element draw:glue-point { draw-glue-point-attlist, empty }
-draw-glue-point-attlist =
-  attribute draw:id { nonNegativeInteger }
-  & attribute svg:x { distance | percent }
-  & attribute svg:y { distance | percent }
-  & attribute draw:align {
-      "top-left"
-      | "top"
-      | "top-right"
-      | "left"
-      | "center"
-      | "right"
-      | "bottom-left"
-      | "bottom-right"
-    }?
-  & attribute draw:escape-direction {
-      "auto"
-      | "left"
-      | "right"
-      | "up"
-      | "down"
-      | "horizontal"
-      | "vertical"
-    }
-svg-title = element svg:title { text }
-svg-desc = element svg:desc { text }
-draw-frame =
-  element draw:frame {
-    common-draw-shape-with-text-and-styles-attlist,
-    common-draw-position-attlist,
-    common-draw-rel-size-attlist,
-    common-draw-caption-id-attlist,
-    presentation-shape-attlist,
-    draw-frame-attlist,
-    (draw-text-box
-     | draw-image
-     | draw-object
-     | draw-object-ole
-     | draw-applet
-     | draw-floating-frame
-     | draw-plugin
-     | table-table)*,
-    office-event-listeners?,
-    draw-glue-point*,
-    draw-image-map?,
-    svg-title?,
-    svg-desc?,
-    (draw-contour-polygon | draw-contour-path)?
-  }
-common-draw-rel-size-attlist =
-  common-draw-size-attlist,
-  attribute style:rel-width { percent | "scale" | "scale-min" }?,
-  attribute style:rel-height { percent | "scale" | "scale-min" }?
-draw-frame-attlist = attribute draw:copy-of { \string }?
 draw-text-box =
   element draw:text-box { draw-text-box-attlist, text-content* }
 draw-text-box-attlist =
@@ -2525,2177 +2046,539 @@ draw-text-box-attlist =
   & attribute fo:max-width { length | percent }?
   & (xml-id,
      attribute text:id { NCName }?)?
-draw-image =
-  element draw:image {
-    draw-image-attlist,
-    (common-draw-data-attlist | office-binary-data),
-    draw-text
-  }
-common-draw-data-attlist =
-  attribute xlink:type { "simple" },
-  attribute xlink:href { anyIRI },
-  attribute xlink:show { "embed" }?,
-  attribute xlink:actuate { "onLoad" }?
-office-binary-data = element office:binary-data { base64Binary }
-draw-image-attlist =
-  attribute draw:filter-name { \string }?
-  & xml-id?
-draw-object =
-  element draw:object {
-    draw-object-attlist,
-    (common-draw-data-attlist | office-document | math-math)
-  }
-draw-object-ole =
-  element draw:object-ole {
-    draw-object-ole-attlist,
-    (common-draw-data-attlist | office-binary-data)
-  }
-draw-object-attlist =
-  attribute draw:notify-on-update-of-ranges {
-    cellRangeAddressList | \string
-  }?
-  & xml-id?
-draw-object-ole-attlist =
-  attribute draw:class-id { \string }?
-  & xml-id?
-draw-applet =
-  element draw:applet {
-    draw-applet-attlist, common-draw-data-attlist?, draw-param*
-  }
-draw-applet-attlist =
-  attribute draw:code { \string }?
-  & attribute draw:object { \string }?
-  & attribute draw:archive { \string }?
-  & attribute draw:may-script { boolean }?
-  & xml-id?
-draw-plugin =
-  element draw:plugin {
-    draw-plugin-attlist, common-draw-data-attlist, draw-param*
-  }
-draw-plugin-attlist =
-  attribute draw:mime-type { \string }?
-  & xml-id?
-draw-param = element draw:param { draw-param-attlist, empty }
-draw-param-attlist =
-  attribute draw:name { \string }?
-  & attribute draw:value { \string }?
-draw-floating-frame =
-  element draw:floating-frame {
-    draw-floating-frame-attlist, common-draw-data-attlist
-  }
-draw-floating-frame-attlist =
-  attribute draw:frame-name { \string }?
-  & xml-id?
-draw-contour-polygon =
-  element draw:contour-polygon {
-    common-contour-attlist,
-    common-draw-size-attlist,
-    common-draw-viewbox-attlist,
-    common-draw-points-attlist,
-    empty
-  }
-draw-contour-path =
-  element draw:contour-path {
-    common-contour-attlist,
-    common-draw-size-attlist,
-    common-draw-viewbox-attlist,
-    common-draw-path-data-attlist,
+dropdown = attribute form:dropdown { boolean }?
+duration = xsd:duration
+extrusionOrigin =
+  xsd:double { minInclusive = "-0.5" maxInclusive = "0.5" }
+fontFamilyGeneric =
+  "roman" | "swiss" | "modern" | "decorative" | "script" | "system"
+fontPitch = "fixed" | "variable"
+fontStyle = "normal" | "italic" | "oblique"
+fontVariant = "normal" | "small-caps"
+fontWeight =
+  "normal"
+  | "bold"
+  | "100"
+  | "200"
+  | "300"
+  | "400"
+  | "500"
+  | "600"
+  | "700"
+  | "800"
+  | "900"
+for = attribute form:for { \string }?
+form-button-attlist =
+  form-control-attlist
+  & button-type
+  & common-disabled-attlist
+  & label
+  & image-data
+  & common-printable-attlist
+  & common-tab-attlist
+  & target-frame
+  & target-location
+  & common-title-attlist
+  & common-value-attlist
+  & common-form-relative-image-position-attlist
+  & common-repeat
+  & common-delay-for-repeat
+  & attribute form:default-button { boolean }?
+  & attribute form:toggle { boolean }?
+  & attribute form:focus-on-click { boolean }?
+  & attribute form:xforms-submission { \string }?
+form-checkbox-attlist =
+  form-control-attlist
+  & common-disabled-attlist
+  & label
+  & common-printable-attlist
+  & common-tab-attlist
+  & common-title-attlist
+  & common-value-attlist
+  & common-data-field-attlist
+  & common-form-visual-effect-attlist
+  & common-form-relative-image-position-attlist
+  & common-linked-cell
+  & attribute form:current-state { states }?
+  & attribute form:is-tristate { boolean }?
+  & attribute form:state { states }?
+form-column =
+  element form:column { form-column-attlist, column-controls+ }
+form-column-attlist =
+  common-form-control-attlist, label, text-style-name
+form-combobox-attlist =
+  form-control-attlist
+  & common-current-value-attlist
+  & common-disabled-attlist
+  & dropdown
+  & common-maxlength-attlist
+  & common-printable-attlist
+  & common-readonly-attlist
+  & size
+  & common-tab-attlist
+  & common-title-attlist
+  & common-value-attlist
+  & common-convert-empty-attlist
+  & common-data-field-attlist
+  & list-source
+  & list-source-type
+  & common-linked-cell
+  & common-source-cell-range
+  & attribute form:auto-complete { boolean }?
+form-connection-resource =
+  element form:connection-resource {
+    attribute xlink:href { anyIRI },
     empty
   }
-common-contour-attlist = attribute draw:recreate-on-edit { boolean }
-draw-a = element draw:a { draw-a-attlist, shape-instance }
-draw-a-attlist =
-  attribute xlink:type { "simple" }
-  & attribute xlink:href { anyIRI }
-  & attribute xlink:actuate { "onRequest" }?
-  & attribute office:target-frame-name { targetFrameName }?
-  & attribute xlink:show { "new" | "replace" }?
-  & attribute office:name { \string }?
-  & attribute office:title { \string }?
-  & attribute office:server-map { boolean }?
-  & xml-id?
-draw-image-map =
-  element draw:image-map {
-    (draw-area-rectangle | draw-area-circle | draw-area-polygon)*
-  }
-draw-area-rectangle =
-  element draw:area-rectangle {
-    common-draw-area-attlist,
-    attribute svg:x { coordinate },
-    attribute svg:y { coordinate },
-    attribute svg:width { length },
-    attribute svg:height { length },
-    svg-title?,
-    svg-desc?,
-    office-event-listeners?
-  }
-draw-area-circle =
-  element draw:area-circle {
-    common-draw-area-attlist,
-    attribute svg:cx { coordinate },
-    attribute svg:cy { coordinate },
-    attribute svg:r { length },
-    svg-title?,
-    svg-desc?,
-    office-event-listeners?
-  }
-draw-area-polygon =
-  element draw:area-polygon {
-    common-draw-area-attlist,
-    attribute svg:x { coordinate },
-    attribute svg:y { coordinate },
-    attribute svg:width { length },
-    attribute svg:height { length },
-    common-draw-viewbox-attlist,
-    common-draw-points-attlist,
-    svg-title?,
-    svg-desc?,
-    office-event-listeners?
+form-control-attlist =
+  common-form-control-attlist,
+  common-control-id-attlist,
+  xforms-bind-attlist
+form-date-attlist =
+  attribute form:value { date }?
+  & attribute form:current-value { date }?
+  & attribute form:min-value { date }?
+  & attribute form:max-value { date }?
+form-file-attlist =
+  form-control-attlist,
+  common-current-value-attlist,
+  common-disabled-attlist,
+  common-maxlength-attlist,
+  common-printable-attlist,
+  common-readonly-attlist,
+  common-tab-attlist,
+  common-title-attlist,
+  common-value-attlist,
+  common-linked-cell
+form-fixed-text-attlist =
+  form-control-attlist
+  & for
+  & common-disabled-attlist
+  & label
+  & common-printable-attlist
+  & common-title-attlist
+  & attribute form:multi-line { boolean }?
+form-form =
+  element form:form {
+    common-form-control-attlist,
+    form-form-attlist,
+    form-properties?,
+    office-event-listeners?,
+    (controls | form-form)*,
+    form-connection-resource?
   }
-common-draw-area-attlist =
+form-form-attlist =
   (attribute xlink:type { "simple" },
    attribute xlink:href { anyIRI },
-   attribute office:target-frame-name { targetFrameName }?,
-   attribute xlink:show { "new" | "replace" }?)?
-  & attribute office:name { \string }?
-  & attribute draw:nohref { "nohref" }?
-dr3d-scene =
-  element dr3d:scene {
-    dr3d-scene-attlist,
-    common-draw-position-attlist,
-    common-draw-size-attlist,
-    common-draw-style-name-attlist,
-    common-draw-z-index-attlist,
-    common-draw-id-attlist,
-    common-draw-layer-name-attlist,
-    common-text-spreadsheet-shape-attlist,
-    common-dr3d-transform-attlist,
-    common-draw-caption-id-attlist,
-    svg-title?,
-    svg-desc?,
-    dr3d-light*,
-    shapes3d*,
-    draw-glue-point*
-  }
-shapes3d =
-  dr3d-scene | dr3d-extrude | dr3d-sphere | dr3d-rotate | dr3d-cube
-dr3d-scene-attlist =
-  attribute dr3d:vrp { vector3D }?
-  & attribute dr3d:vpn { vector3D }?
-  & attribute dr3d:vup { vector3D }?
-  & attribute dr3d:projection { "parallel" | "perspective" }?
-  & attribute dr3d:distance { length }?
-  & attribute dr3d:focal-length { length }?
-  & attribute dr3d:shadow-slant { angle }?
-  & attribute dr3d:shade-mode {
-      "flat" | "phong" | "gouraud" | "draft"
-    }?
-  & attribute dr3d:ambient-color { color }?
-  & attribute dr3d:lighting-mode { boolean }?
-common-dr3d-transform-attlist = attribute dr3d:transform { \string }?
-dr3d-light = element dr3d:light { dr3d-light-attlist, empty }
-dr3d-light-attlist =
-  attribute dr3d:diffuse-color { color }?
-  & attribute dr3d:direction { vector3D }
-  & attribute dr3d:enabled { boolean }?
-  & attribute dr3d:specular { boolean }?
-dr3d-cube =
-  element dr3d:cube {
-    dr3d-cube-attlist,
-    common-draw-z-index-attlist,
-    common-draw-id-attlist,
-    common-draw-layer-name-attlist,
-    common-draw-style-name-attlist,
-    common-dr3d-transform-attlist,
-    empty
-  }
-dr3d-cube-attlist =
-  attribute dr3d:min-edge { vector3D }?,
-  attribute dr3d:max-edge { vector3D }?
-dr3d-sphere =
-  element dr3d:sphere {
-    dr3d-sphere-attlist,
-    common-draw-z-index-attlist,
-    common-draw-id-attlist,
-    common-draw-layer-name-attlist,
-    common-draw-style-name-attlist,
-    common-dr3d-transform-attlist,
-    empty
-  }
-dr3d-sphere-attlist =
-  attribute dr3d:center { vector3D }?
-  & attribute dr3d:size { vector3D }?
-dr3d-extrude =
-  element dr3d:extrude {
-    common-draw-path-data-attlist,
-    common-draw-viewbox-attlist,
-    common-draw-id-attlist,
-    common-draw-z-index-attlist,
-    common-draw-layer-name-attlist,
-    common-draw-style-name-attlist,
-    common-dr3d-transform-attlist,
-    empty
-  }
-dr3d-rotate =
-  element dr3d:rotate {
-    common-draw-viewbox-attlist,
-    common-draw-path-data-attlist,
-    common-draw-z-index-attlist,
-    common-draw-id-attlist,
-    common-draw-layer-name-attlist,
-    common-draw-style-name-attlist,
-    common-dr3d-transform-attlist,
-    empty
-  }
-draw-custom-shape =
-  element draw:custom-shape {
-    draw-custom-shape-attlist,
-    common-draw-position-attlist,
-    common-draw-size-attlist,
-    common-draw-shape-with-text-and-styles-attlist,
-    common-draw-caption-id-attlist,
-    svg-title?,
-    svg-desc?,
-    office-event-listeners?,
-    draw-glue-point*,
-    draw-text,
-    draw-enhanced-geometry?
-  }
-draw-custom-shape-attlist =
-  attribute draw:engine { namespacedToken }?
-  & attribute draw:data { \string }?
-draw-enhanced-geometry =
-  element draw:enhanced-geometry {
-    draw-enhanced-geometry-attlist, draw-equation*, draw-handle*
-  }
-draw-enhanced-geometry-attlist =
-  attribute draw:type { custom-shape-type }?
-  & attribute svg:viewBox {
-      list { integer, integer, integer, integer }
-    }?
-  & attribute draw:mirror-vertical { boolean }?
-  & attribute draw:mirror-horizontal { boolean }?
-  & attribute draw:text-rotate-angle { angle }?
-  & attribute draw:extrusion-allowed { boolean }?
-  & attribute draw:text-path-allowed { boolean }?
-  & attribute draw:concentric-gradient-fill-allowed { boolean }?
-  & attribute draw:extrusion { boolean }?
-  & attribute draw:extrusion-brightness { zeroToHundredPercent }?
-  & attribute draw:extrusion-depth {
-      list { length, double }
-    }?
-  & attribute draw:extrusion-diffusion { percent }?
-  & attribute draw:extrusion-number-of-line-segments { integer }?
-  & attribute draw:extrusion-light-face { boolean }?
-  & attribute draw:extrusion-first-light-harsh { boolean }?
-  & attribute draw:extrusion-second-light-harsh { boolean }?
-  & attribute draw:extrusion-first-light-level { zeroToHundredPercent }?
-  & attribute draw:extrusion-second-light-level {
-      zeroToHundredPercent
-    }?
-  & attribute draw:extrusion-first-light-direction { vector3D }?
-  & attribute draw:extrusion-second-light-direction { vector3D }?
-  & attribute draw:extrusion-metal { boolean }?
-  & attribute dr3d:shade-mode {
-      "flat" | "phong" | "gouraud" | "draft"
-    }?
-  & attribute draw:extrusion-rotation-angle {
-      list { angle, angle }
-    }?
-  & attribute draw:extrusion-rotation-center { vector3D }?
-  & attribute draw:extrusion-shininess { zeroToHundredPercent }?
-  & attribute draw:extrusion-skew {
-      list { double, angle }
-    }?
-  & attribute draw:extrusion-specularity { zeroToHundredPercent }?
-  & attribute dr3d:projection { "parallel" | "perspective" }?
-  & attribute draw:extrusion-viewpoint { point3D }?
-  & attribute draw:extrusion-origin {
-      list { extrusionOrigin, extrusionOrigin }
-    }?
-  & attribute draw:extrusion-color { boolean }?
-  & attribute draw:enhanced-path { \string }?
-  & attribute draw:path-stretchpoint-x { double }?
-  & attribute draw:path-stretchpoint-y { double }?
-  & attribute draw:text-areas { \string }?
-  & attribute draw:glue-points { \string }?
-  & attribute draw:glue-point-type {
-      "none" | "segments" | "rectangle"
-    }?
-  & attribute draw:glue-point-leaving-directions { \string }?
-  & attribute draw:text-path { boolean }?
-  & attribute draw:text-path-mode { "normal" | "path" | "shape" }?
-  & attribute draw:text-path-scale { "path" | "shape" }?
-  & attribute draw:text-path-same-letter-heights { boolean }?
-  & attribute draw:modifiers { \string }?
-custom-shape-type = "non-primitive" | \string
-point3D =
-  xsd:string {
-    pattern =
-      "\([ ]*-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc))([ 
]+-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc))){2}[ ]*\)"
-  }
-extrusionOrigin =
-  xsd:double { minInclusive = "-0.5" maxInclusive = "0.5" }
-draw-equation = element draw:equation { draw-equation-attlist, empty }
-draw-equation-attlist =
-  attribute draw:name { \string }?
-  & attribute draw:formula { \string }?
-draw-handle = element draw:handle { draw-handle-attlist, empty }
-draw-handle-attlist =
-  attribute draw:handle-mirror-vertical { boolean }?
-  & attribute draw:handle-mirror-horizontal { boolean }?
-  & attribute draw:handle-switched { boolean }?
-  & attribute draw:handle-position { \string }
-  & attribute draw:handle-range-x-minimum { \string }?
-  & attribute draw:handle-range-x-maximum { \string }?
-  & attribute draw:handle-range-y-minimum { \string }?
-  & attribute draw:handle-range-y-maximum { \string }?
-  & attribute draw:handle-polar { \string }?
-  & attribute draw:handle-radius-range-minimum { \string }?
-  & attribute draw:handle-radius-range-maximum { \string }?
-presentation-shape-attlist =
-  attribute presentation:class { presentation-classes }?
-  & attribute presentation:placeholder { boolean }?
-  & attribute presentation:user-transformed { boolean }?
-presentation-classes =
-  "title"
-  | "outline"
-  | "subtitle"
-  | "text"
-  | "graphic"
-  | "object"
-  | "chart"
-  | "table"
-  | "orgchart"
-  | "page"
-  | "notes"
-  | "handout"
-  | "header"
-  | "footer"
-  | "date-time"
-  | "page-number"
-presentation-animations =
-  element presentation:animations {
-    (presentation-animation-elements | presentation-animation-group)*
-  }
-presentation-animation-elements =
-  presentation-show-shape
-  | presentation-show-text
-  | presentation-hide-shape
-  | presentation-hide-text
-  | presentation-dim
-  | presentation-play
-presentation-sound =
-  element presentation:sound {
-    presentation-sound-attlist,
-    attribute xlink:type { "simple" },
-    attribute xlink:href { anyIRI },
-    attribute xlink:actuate { "onRequest" }?,
-    attribute xlink:show { "new" | "replace" }?,
-    empty
-  }
-presentation-sound-attlist =
-  attribute presentation:play-full { boolean }?
-  & xml-id?
-presentation-show-shape =
-  element presentation:show-shape {
-    common-presentation-effect-attlist, presentation-sound?
-  }
-common-presentation-effect-attlist =
-  attribute draw:shape-id { IDREF }
-  & attribute presentation:effect { presentationEffects }?
-  & attribute presentation:direction { presentationEffectDirections }?
-  & attribute presentation:speed { presentationSpeeds }?
-  & attribute presentation:delay { duration }?
-  & attribute presentation:start-scale { percent }?
-  & attribute presentation:path-id { \string }?
-presentationEffects =
-  "none"
-  | "fade"
-  | "move"
-  | "stripes"
-  | "open"
-  | "close"
-  | "dissolve"
-  | "wavyline"
-  | "random"
-  | "lines"
-  | "laser"
-  | "appear"
-  | "hide"
-  | "move-short"
-  | "checkerboard"
-  | "rotate"
-  | "stretch"
-presentationEffectDirections =
-  "none"
-  | "from-left"
-  | "from-top"
-  | "from-right"
-  | "from-bottom"
-  | "from-center"
-  | "from-upper-left"
-  | "from-upper-right"
-  | "from-lower-left"
-  | "from-lower-right"
-  | "to-left"
-  | "to-top"
-  | "to-right"
-  | "to-bottom"
-  | "to-upper-left"
-  | "to-upper-right"
-  | "to-lower-right"
-  | "to-lower-left"
-  | "path"
-  | "spiral-inward-left"
-  | "spiral-inward-right"
-  | "spiral-outward-left"
-  | "spiral-outward-right"
-  | "vertical"
-  | "horizontal"
-  | "to-center"
-  | "clockwise"
-  | "counter-clockwise"
-presentationSpeeds = "slow" | "medium" | "fast"
-presentation-show-text =
-  element presentation:show-text {
-    common-presentation-effect-attlist, presentation-sound?
-  }
-presentation-hide-shape =
-  element presentation:hide-shape {
-    common-presentation-effect-attlist, presentation-sound?
-  }
-presentation-hide-text =
-  element presentation:hide-text {
-    common-presentation-effect-attlist, presentation-sound?
-  }
-presentation-dim =
-  element presentation:dim {
-    presentation-dim-attlist, presentation-sound?
-  }
-presentation-dim-attlist =
-  attribute draw:shape-id { IDREF }
-  & attribute draw:color { color }
-presentation-play =
-  element presentation:play { presentation-play-attlist, empty }
-presentation-play-attlist =
-  attribute draw:shape-id { IDREF },
-  attribute presentation:speed { presentationSpeeds }?
-presentation-animation-group =
-  element presentation:animation-group {
-    presentation-animation-elements*
-  }
-common-anim-attlist =
-  attribute presentation:node-type {
-    "default"
-    | "on-click"
-    | "with-previous"
-    | "after-previous"
-    | "timing-root"
-    | "main-sequence"
-    | "interactive-sequence"
-  }?
-  & attribute presentation:preset-id { \string }?
-  & attribute presentation:preset-sub-type { \string }?
-  & attribute presentation:preset-class {
-      "custom"
-      | "entrance"
-      | "exit"
-      | "emphasis"
-      | "motion-path"
-      | "ole-action"
-      | "media-call"
-    }?
-  & attribute presentation:master-element { IDREF }?
-  & attribute presentation:group-id { \string }?
-  & (xml-id,
-     attribute anim:id { NCName }?)?
-presentation-event-listener =
-  element presentation:event-listener {
-    presentation-event-listener-attlist, presentation-sound?
-  }
-presentation-event-listener-attlist =
-  attribute script:event-name { \string }
-  & attribute presentation:action {
-      "none"
-      | "previous-page"
-      | "next-page"
-      | "first-page"
-      | "last-page"
-      | "hide"
-      | "stop"
-      | "execute"
-      | "show"
-      | "verb"
-      | "fade-out"
-      | "sound"
-      | "last-visited-page"
-    }
-  & attribute presentation:effect { presentationEffects }?
-  & attribute presentation:direction { presentationEffectDirections }?
-  & attribute presentation:speed { presentationSpeeds }?
-  & attribute presentation:start-scale { percent }?
-  & (attribute xlink:type { "simple" },
-     attribute xlink:href { anyIRI },
-     attribute xlink:show { "embed" }?,
-     attribute xlink:actuate { "onRequest" }?)?
-  & attribute presentation:verb { nonNegativeInteger }?
-presentation-decls = presentation-decl*
-presentation-decl =
-  element presentation:header-decl {
-    presentation-header-decl-attlist, text
-  }
-  | element presentation:footer-decl {
-      presentation-footer-decl-attlist, text
-    }
-  | element presentation:date-time-decl {
-      presentation-date-time-decl-attlist, text
-    }
-presentation-header-decl-attlist =
-  attribute presentation:name { \string }
-presentation-footer-decl-attlist =
-  attribute presentation:name { \string }
-presentation-date-time-decl-attlist =
-  attribute presentation:name { \string }
-  & attribute presentation:source { "fixed" | "current-date" }
-  & attribute style:data-style-name { styleNameRef }?
-presentation-settings =
-  element presentation:settings {
-    presentation-settings-attlist, presentation-show*
-  }?
-presentation-settings-attlist =
-  attribute presentation:start-page { \string }?
-  & attribute presentation:show { \string }?
-  & attribute presentation:full-screen { boolean }?
-  & attribute presentation:endless { boolean }?
-  & attribute presentation:pause { duration }?
-  & attribute presentation:show-logo { boolean }?
-  & attribute presentation:force-manual { boolean }?
-  & attribute presentation:mouse-visible { boolean }?
-  & attribute presentation:mouse-as-pen { boolean }?
-  & attribute presentation:start-with-navigator { boolean }?
-  & attribute presentation:animations { "enabled" | "disabled" }?
-  & attribute presentation:transition-on-click {
-      "enabled" | "disabled"
-    }?
-  & attribute presentation:stay-on-top { boolean }?
-  & attribute presentation:show-end-of-presentation-slide { boolean }?
-presentation-show =
-  element presentation:show { presentation-show-attlist, empty }
-presentation-show-attlist =
-  attribute presentation:name { \string }
-  & attribute presentation:pages { \string }
-chart-chart =
-  element chart:chart {
-    chart-chart-attlist,
-    chart-title?,
-    chart-subtitle?,
-    chart-footer?,
-    chart-legend?,
-    chart-plot-area,
-    table-table?
-  }
-chart-chart-attlist =
-  attribute chart:class { namespacedToken }
-  & common-draw-size-attlist
-  & attribute chart:column-mapping { \string }?
-  & attribute chart:row-mapping { \string }?
-  & attribute chart:style-name { styleNameRef }?
-  & (attribute xlink:type { "simple" },
-     attribute xlink:href { anyIRI })?
-  & xml-id?
-chart-title = element chart:title { chart-title-attlist, text-p? }
-chart-title-attlist =
-  attribute table:cell-range { cellRangeAddressList }?
-  & common-draw-position-attlist
-  & attribute chart:style-name { styleNameRef }?
-chart-subtitle = element chart:subtitle { chart-title-attlist, text-p? }
-chart-footer = element chart:footer { chart-title-attlist, text-p? }
-chart-legend = element chart:legend { chart-legend-attlist, text-p? }
-chart-legend-attlist =
-  ((attribute chart:legend-position {
-      "start" | "end" | "top" | "bottom"
-    },
-    attribute chart:legend-align { "start" | "center" | "end" }?)
-   | attribute chart:legend-position {
-       "top-start" | "bottom-start" | "top-end" | "bottom-end"
-     }
-   | empty)
-  & common-draw-position-attlist
-  & (attribute style:legend-expansion { "wide" | "high" | "balanced" }
-     | (attribute style:legend-expansion { "custom" },
-        attribute style:legend-expansion-aspect-ratio { double })
-     | empty)
-  & attribute chart:style-name { styleNameRef }?
-chart-plot-area =
-  element chart:plot-area {
-    chart-plot-area-attlist,
-    dr3d-light*,
-    chart-axis*,
-    chart-series*,
-    chart-stock-gain-marker?,
-    chart-stock-loss-marker?,
-    chart-stock-range-line?,
-    chart-wall?,
-    chart-floor?
-  }
-chart-plot-area-attlist =
-  common-draw-position-attlist
-  & common-draw-size-attlist
-  & attribute chart:style-name { styleNameRef }?
-  & attribute table:cell-range-address { cellRangeAddressList }?
-  & attribute chart:data-source-has-labels {
-      "none" | "row" | "column" | "both"
-    }?
-  & dr3d-scene-attlist
-  & common-dr3d-transform-attlist
-  & xml-id?
-chart-wall = element chart:wall { chart-wall-attlist, empty }
-chart-wall-attlist =
-  attribute svg:width { length }?
-  & attribute chart:style-name { styleNameRef }?
-chart-floor = element chart:floor { chart-floor-attlist, empty }
-chart-floor-attlist =
-  attribute svg:width { length }?
-  & attribute chart:style-name { styleNameRef }?
-chart-axis =
-  element chart:axis {
-    chart-axis-attlist, chart-title?, chart-categories?, chart-grid*
-  }
-chart-axis-attlist =
-  attribute chart:dimension { chart-dimension }
-  & attribute chart:name { \string }?
-  & attribute chart:style-name { styleNameRef }?
-chart-dimension = "x" | "y" | "z"
-chart-categories =
-  element chart:categories {
-    attribute table:cell-range-address { cellRangeAddressList }?
-  }
-chart-grid = element chart:grid { chart-grid-attlist }
-chart-grid-attlist =
-  attribute chart:class { "major" | "minor" }?
-  & attribute chart:style-name { styleNameRef }?
-chart-series =
-  element chart:series {
-    chart-series-attlist,
-    chart-domain*,
-    chart-mean-value?,
-    chart-regression-curve*,
-    chart-error-indicator*,
-    chart-data-point*,
-    chart-data-label?
-  }
-chart-series-attlist =
-  attribute chart:values-cell-range-address { cellRangeAddressList }?
-  & attribute chart:label-cell-address { cellRangeAddressList }?
-  & attribute chart:class { namespacedToken }?
-  & attribute chart:attached-axis { \string }?
-  & attribute chart:style-name { styleNameRef }?
-  & xml-id?
-chart-domain =
-  element chart:domain {
-    attribute table:cell-range-address { cellRangeAddressList }?
-  }
-chart-data-point =
-  element chart:data-point {
-    chart-data-point-attlist, chart-data-label?
-  }
-chart-data-point-attlist =
-  attribute chart:repeated { positiveInteger }?
-  & attribute chart:style-name { styleNameRef }?
-  & xml-id?
-chart-data-label =
-  element chart:data-label { chart-data-label-attlist, text-p? }
-chart-data-label-attlist =
-  common-draw-position-attlist
-  & attribute chart:style-name { styleNameRef }?
-chart-mean-value =
-  element chart:mean-value { chart-mean-value-attlist, empty }
-chart-mean-value-attlist = attribute chart:style-name { styleNameRef }?
-chart-error-indicator =
-  element chart:error-indicator { chart-error-indicator-attlist, empty }
-chart-error-indicator-attlist =
-  attribute chart:style-name { styleNameRef }?
-  & attribute chart:dimension { chart-dimension }
-chart-regression-curve =
-  element chart:regression-curve {
-    chart-regression-curve-attlist, chart-equation?
-  }
-chart-regression-curve-attlist =
-  attribute chart:style-name { styleNameRef }?
-chart-equation =
-  element chart:equation { chart-equation-attlist, text-p? }
-chart-equation-attlist =
-  attribute chart:automatic-content { boolean }?
-  & attribute chart:display-r-square { boolean }?
-  & attribute chart:display-equation { boolean }?
-  & common-draw-position-attlist
-  & attribute chart:style-name { styleNameRef }?
-chart-stock-gain-marker =
-  element chart:stock-gain-marker { common-stock-marker-attlist }
-chart-stock-loss-marker =
-  element chart:stock-loss-marker { common-stock-marker-attlist }
-chart-stock-range-line =
-  element chart:stock-range-line { common-stock-marker-attlist }
-common-stock-marker-attlist =
-  attribute chart:style-name { styleNameRef }?
-office-database =
-  element office:database {
-    db-data-source,
-    db-forms?,
-    db-reports?,
-    db-queries?,
-    db-table-presentations?,
-    db-schema-definition?
-  }
-db-data-source =
-  element db:data-source {
-    db-data-source-attlist,
-    db-connection-data,
-    db-driver-settings?,
-    db-application-connection-settings?
-  }
-db-data-source-attlist = empty
-db-connection-data =
-  element db:connection-data {
-    db-connection-data-attlist,
-    (db-database-description | db-connection-resource),
-    db-login?
-  }
-db-connection-data-attlist = empty
-db-database-description =
-  element db:database-description {
-    db-database-description-attlist,
-    (db-file-based-database | db-server-database)
-  }
-db-database-description-attlist = empty
-db-file-based-database =
-  element db:file-based-database { db-file-based-database-attlist }
-db-file-based-database-attlist =
-  attribute xlink:type { "simple" }
-  & attribute xlink:href { anyIRI }
-  & attribute db:media-type { \string }
-  & attribute db:extension { \string }?
-db-server-database =
-  element db:server-database { db-server-database-attlist, empty }
-db-server-database-attlist =
-  attribute db:type { namespacedToken }
-  & (db-host-and-port | db-local-socket-name)
-  & attribute db:database-name { \string }?
-db-host-and-port =
-  attribute db:hostname { \string },
-  attribute db:port { positiveInteger }?
-db-local-socket-name = attribute db:local-socket { \string }?
-db-connection-resource =
-  element db:connection-resource {
-    db-connection-resource-attlist, empty
-  }
-db-connection-resource-attlist =
-  attribute xlink:type { "simple" },
-  attribute xlink:href { anyIRI },
-  attribute xlink:show { "none" }?,
-  attribute xlink:actuate { "onRequest" }?
-db-login = element db:login { db-login-attlist, empty }
-db-login-attlist =
-  (attribute db:user-name { \string }
-   | attribute db:use-system-user { boolean })?
-  & attribute db:is-password-required { boolean }?
-  & attribute db:login-timeout { positiveInteger }?
-db-driver-settings =
-  element db:driver-settings {
-    db-driver-settings-attlist,
-    db-auto-increment?,
-    db-delimiter?,
-    db-character-set?,
-    db-table-settings?
-  }
-db-driver-settings-attlist =
-  db-show-deleted
-  & attribute db:system-driver-settings { \string }?
-  & attribute db:base-dn { \string }?
-  & db-is-first-row-header-line
-  & attribute db:parameter-name-substitution { boolean }?
-db-show-deleted = attribute db:show-deleted { boolean }?
-db-is-first-row-header-line =
-  attribute db:is-first-row-header-line { boolean }?
-db-auto-increment =
-  element db:auto-increment { db-auto-increment-attlist, empty }
-db-auto-increment-attlist =
-  attribute db:additional-column-statement { \string }?
-  & attribute db:row-retrieving-statement { \string }?
-db-delimiter = element db:delimiter { db-delimiter-attlist, empty }
-db-delimiter-attlist =
-  attribute db:field { \string }?
-  & attribute db:string { \string }?
-  & attribute db:decimal { \string }?
-  & attribute db:thousand { \string }?
-db-character-set =
-  element db:character-set { db-character-set-attlist, empty }
-db-character-set-attlist = attribute db:encoding { textEncoding }?
-db-table-settings = element db:table-settings { db-table-setting* }
-db-table-setting =
-  element db:table-setting {
-    db-table-setting-attlist, db-delimiter?, db-character-set?, empty
-  }
-db-table-setting-attlist = db-is-first-row-header-line, db-show-deleted
-db-application-connection-settings =
-  element db:application-connection-settings {
-    db-application-connection-settings-attlist,
-    db-table-filter?,
-    db-table-type-filter?,
-    db-data-source-settings?
-  }
-db-application-connection-settings-attlist =
-  attribute db:is-table-name-length-limited { boolean }?
-  & attribute db:enable-sql92-check { boolean }?
-  & attribute db:append-table-alias-name { boolean }?
-  & attribute db:ignore-driver-privileges { boolean }?
-  & attribute db:boolean-comparison-mode {
-      "equal-integer"
-      | "is-boolean"
-      | "equal-boolean"
-      | "equal-use-only-zero"
-    }?
-  & attribute db:use-catalog { boolean }?
-  & attribute db:max-row-count { integer }?
-  & attribute db:suppress-version-columns { boolean }?
-db-table-filter =
-  element db:table-filter {
-    db-table-filter-attlist,
-    db-table-include-filter?,
-    db-table-exclude-filter?
-  }
-db-table-filter-attlist = empty
-db-table-include-filter =
-  element db:table-include-filter {
-    db-table-include-filter-attlist, db-table-filter-pattern+
-  }
-db-table-include-filter-attlist = empty
-db-table-exclude-filter =
-  element db:table-exclude-filter {
-    db-table-exclude-filter-attlist, db-table-filter-pattern+
-  }
-db-table-exclude-filter-attlist = empty
-db-table-filter-pattern =
-  element db:table-filter-pattern {
-    db-table-filter-pattern-attlist, \string
-  }
-db-table-filter-pattern-attlist = empty
-db-table-type-filter =
-  element db:table-type-filter {
-    db-table-type-filter-attlist, db-table-type*
-  }
-db-table-type-filter-attlist = empty
-db-table-type = element db:table-type { db-table-type-attlist, \string }
-db-table-type-attlist = empty
-db-data-source-settings =
-  element db:data-source-settings {
-    db-data-source-settings-attlist, db-data-source-setting+
-  }
-db-data-source-settings-attlist = empty
-db-data-source-setting =
-  element db:data-source-setting {
-    db-data-source-setting-attlist, db-data-source-setting-value+
-  }
-db-data-source-setting-attlist =
-  attribute db:data-source-setting-is-list { boolean }?
-  & attribute db:data-source-setting-name { \string }
-  & attribute db:data-source-setting-type {
-      db-data-source-setting-types
-    }
-db-data-source-setting-types =
-  "boolean" | "short" | "int" | "long" | "double" | "string"
-db-data-source-setting-value =
-  element db:data-source-setting-value {
-    db-data-source-setting-value-attlist, \string
-  }
-db-data-source-setting-value-attlist = empty
-db-forms =
-  element db:forms {
-    db-forms-attlist, (db-component | db-component-collection)*
-  }
-db-forms-attlist = empty
-db-reports =
-  element db:reports {
-    db-reports-attlist, (db-component | db-component-collection)*
-  }
-db-reports-attlist = empty
-db-component-collection =
-  element db:component-collection {
-    db-component-collection-attlist,
-    common-db-object-name,
-    common-db-object-title,
-    common-db-object-description,
-    (db-component | db-component-collection)*
-  }
-db-component-collection-attlist = empty
-db-component =
-  element db:component {
-    db-component-attlist,
-    common-db-object-name,
-    common-db-object-title,
-    common-db-object-description,
-    (office-document | math-math)?
-  }
-db-component-attlist =
-  (attribute xlink:type { "simple" },
-   attribute xlink:href { anyIRI },
-   attribute xlink:show { "none" }?,
-   attribute xlink:actuate { "onRequest" }?)?
-  & attribute db:as-template { boolean }?
-db-queries =
-  element db:queries {
-    db-queries-attlist, (db-query | db-query-collection)*
-  }
-db-queries-attlist = empty
-db-query-collection =
-  element db:query-collection {
-    db-query-collection-attlist,
-    common-db-object-name,
-    common-db-object-title,
-    common-db-object-description,
-    (db-query | db-query-collection)*
-  }
-db-query-collection-attlist = empty
-db-query =
-  element db:query {
-    db-query-attlist,
-    common-db-object-name,
-    common-db-object-title,
-    common-db-object-description,
-    common-db-table-style-name,
-    db-order-statement?,
-    db-filter-statement?,
-    db-columns?,
-    db-update-table?
-  }
-db-query-attlist =
-  attribute db:command { \string }
-  & attribute db:escape-processing { boolean }?
-db-order-statement =
-  element db:order-statement { db-command, db-apply-command, empty }
-db-filter-statement =
-  element db:filter-statement { db-command, db-apply-command, empty }
-db-update-table =
-  element db:update-table { common-db-table-name-attlist }
-db-table-presentations =
-  element db:table-representations {
-    db-table-presentations-attlist, db-table-presentation*
-  }
-db-table-presentations-attlist = empty
-db-table-presentation =
-  element db:table-representation {
-    db-table-presentation-attlist,
-    common-db-table-name-attlist,
-    common-db-object-title,
-    common-db-object-description,
-    common-db-table-style-name,
-    db-order-statement?,
-    db-filter-statement?,
-    db-columns?
-  }
-db-table-presentation-attlist = empty
-db-columns = element db:columns { db-columns-attlist, db-column+ }
-db-columns-attlist = empty
-db-column =
-  element db:column {
-    db-column-attlist,
-    common-db-object-name,
-    common-db-object-title,
-    common-db-object-description,
-    common-db-default-value
-  }
-db-column-attlist =
-  attribute db:visible { boolean }?
-  & attribute db:style-name { styleNameRef }?
-  & attribute db:default-cell-style-name { styleNameRef }?
-db-command = attribute db:command { \string }
-db-apply-command = attribute db:apply-command { boolean }?
-common-db-table-name-attlist =
-  attribute db:name { \string }
-  & attribute db:catalog-name { \string }?
-  & attribute db:schema-name { \string }?
-common-db-object-name = attribute db:name { \string }
-common-db-object-title = attribute db:title { \string }?
-common-db-object-description = attribute db:description { \string }?
-common-db-table-style-name =
-  attribute db:style-name { styleNameRef }?
-  & attribute db:default-row-style-name { styleNameRef }?
-common-db-default-value = common-value-and-type-attlist?
-db-schema-definition =
-  element db:schema-definition {
-    db-schema-definition-attlist, db-table-definitions
-  }
-db-schema-definition-attlist = empty
-db-table-definitions =
-  element db:table-definitions {
-    db-table-definitions-attlist, db-table-definition*
-  }
-db-table-definitions-attlist = empty
-db-table-definition =
-  element db:table-definition {
-    common-db-table-name-attlist,
-    db-table-definition-attlist,
-    db-column-definitions,
-    db-keys?,
-    db-indices?
-  }
-db-table-definition-attlist = attribute db:type { \string }?
-db-column-definitions =
-  element db:column-definitions {
-    db-column-definitions-attlist, db-column-definition+
-  }
-db-column-definitions-attlist = empty
-db-column-definition =
-  element db:column-definition {
-    db-column-definition-attlist, common-db-default-value
-  }
-db-column-definition-attlist =
-  attribute db:name { \string }
-  & attribute db:data-type { db-data-types }?
-  & attribute db:type-name { \string }?
-  & attribute db:precision { positiveInteger }?
-  & attribute db:scale { positiveInteger }?
-  & attribute db:is-nullable { "no-nulls" | "nullable" }?
-  & attribute db:is-empty-allowed { boolean }?
-  & attribute db:is-autoincrement { boolean }?
-db-data-types =
-  "bit"
-  | "boolean"
-  | "tinyint"
-  | "smallint"
-  | "integer"
-  | "bigint"
-  | "float"
-  | "real"
-  | "double"
-  | "numeric"
-  | "decimal"
-  | "char"
-  | "varchar"
-  | "longvarchar"
-  | "date"
-  | "time"
-  | "timestmp"
-  | "binary"
-  | "varbinary"
-  | "longvarbinary"
-  | "sqlnull"
-  | "other"
-  | "object"
-  | "distinct"
-  | "struct"
-  | "array"
-  | "blob"
-  | "clob"
-  | "ref"
-db-keys = element db:keys { db-keys-attlist, db-key+ }
-db-keys-attlist = empty
-db-key = element db:key { db-key-attlist, db-key-columns+ }
-db-key-attlist =
-  attribute db:name { \string }?
-  & attribute db:type { "primary" | "unique" | "foreign" }
-  & attribute db:referenced-table-name { \string }?
-  & attribute db:update-rule {
-      "cascade" | "restrict" | "set-null" | "no-action" | "set-default"
-    }?
-  & attribute db:delete-rule {
-      "cascade" | "restrict" | "set-null" | "no-action" | "set-default"
-    }?
-db-key-columns =
-  element db:key-columns { db-key-columns-attlist, db-key-column+ }
-db-key-columns-attlist = empty
-db-key-column = element db:key-column { db-key-column-attlist, empty }
-db-key-column-attlist =
-  attribute db:name { \string }?
-  & attribute db:related-column-name { \string }?
-db-indices = element db:indices { db-indices-attlist, db-index+ }
-db-indices-attlist = empty
-db-index = element db:index { db-index-attlist, db-index-columns+ }
-db-index-attlist =
-  attribute db:name { \string }
-  & attribute db:catalog-name { \string }?
-  & attribute db:is-unique { boolean }?
-  & attribute db:is-clustered { boolean }?
-db-index-columns = element db:index-columns { db-index-column+ }
-db-index-column =
-  element db:index-column { db-index-column-attlist, empty }
-db-index-column-attlist =
-  attribute db:name { \string }
-  & attribute db:is-ascending { boolean }?
-office-forms =
-  element office:forms {
-    office-forms-attlist, (form-form | xforms-model)*
-  }?
-office-forms-attlist =
-  attribute form:automatic-focus { boolean }?
-  & attribute form:apply-design-mode { boolean }?
-form-form =
-  element form:form {
-    common-form-control-attlist,
-    form-form-attlist,
-    form-properties?,
-    office-event-listeners?,
-    (controls | form-form)*,
-    form-connection-resource?
-  }
-form-form-attlist =
-  (attribute xlink:type { "simple" },
-   attribute xlink:href { anyIRI },
-   attribute xlink:actuate { "onRequest" }?)?
-  & attribute office:target-frame { targetFrameName }?
-  & attribute form:method { "get" | "post" | \string }?
-  & attribute form:enctype { \string }?
-  & attribute form:allow-deletes { boolean }?
-  & attribute form:allow-inserts { boolean }?
-  & attribute form:allow-updates { boolean }?
-  & attribute form:apply-filter { boolean }?
-  & attribute form:command-type { "table" | "query" | "command" }?
-  & attribute form:command { \string }?
-  & attribute form:datasource { anyIRI | \string }?
-  & attribute form:master-fields { \string }?
-  & attribute form:detail-fields { \string }?
-  & attribute form:escape-processing { boolean }?
-  & attribute form:filter { \string }?
-  & attribute form:ignore-result { boolean }?
-  & attribute form:navigation-mode { navigation }?
-  & attribute form:order { \string }?
-  & attribute form:tab-cycle { tab-cycles }?
-navigation = "none" | "current" | "parent"
-tab-cycles = "records" | "current" | "page"
-form-connection-resource =
-  element form:connection-resource {
-    attribute xlink:href { anyIRI },
-    empty
-  }
-xforms-model = element xforms:model { anyAttListOrElements }
-column-controls =
-  element form:text { form-text-attlist, common-form-control-content }
-  | element form:textarea {
-      form-textarea-attlist, common-form-control-content, text-p*
-    }
-  | element form:formatted-text {
-      form-formatted-text-attlist, common-form-control-content
-    }
-  | element form:number {
-      form-number-attlist,
-      common-numeric-control-attlist,
-      common-form-control-content,
-      common-linked-cell,
-      common-spin-button,
-      common-repeat,
-      common-delay-for-repeat
-    }
-  | element form:date {
-      form-date-attlist,
-      common-numeric-control-attlist,
-      common-form-control-content,
-      common-linked-cell,
-      common-spin-button,
-      common-repeat,
-      common-delay-for-repeat
-    }
-  | element form:time {
-      form-time-attlist,
-      common-numeric-control-attlist,
-      common-form-control-content,
-      common-linked-cell,
-      common-spin-button,
-      common-repeat,
-      common-delay-for-repeat
-    }
-  | element form:combobox {
-      form-combobox-attlist, common-form-control-content, form-item*
-    }
-  | element form:listbox {
-      form-listbox-attlist, common-form-control-content, form-option*
-    }
-  | element form:checkbox {
-      form-checkbox-attlist, common-form-control-content
-    }
-controls =
-  column-controls
-  | element form:password {
-      form-password-attlist, common-form-control-content
-    }
-  | element form:file { form-file-attlist, common-form-control-content }
-  | element form:fixed-text {
-      form-fixed-text-attlist, common-form-control-content
-    }
-  | element form:button {
-      form-button-attlist, common-form-control-content
-    }
-  | element form:image {
-      form-image-attlist, common-form-control-content
-    }
-  | element form:radio {
-      form-radio-attlist, common-form-control-content
-    }
-  | element form:frame {
-      form-frame-attlist, common-form-control-content
-    }
-  | element form:image-frame {
-      form-image-frame-attlist, common-form-control-content
-    }
-  | element form:hidden {
-      form-hidden-attlist, common-form-control-content
-    }
-  | element form:grid {
-      form-grid-attlist, common-form-control-content, form-column*
-    }
-  | element form:value-range {
-      form-value-range-attlist, common-form-control-content
-    }
-  | element form:generic-control {
-      form-generic-control-attlist, common-form-control-content
-    }
-form-text-attlist =
-  form-control-attlist,
-  common-current-value-attlist,
-  common-disabled-attlist,
-  common-maxlength-attlist,
-  common-printable-attlist,
-  common-readonly-attlist,
-  common-tab-attlist,
-  common-title-attlist,
-  common-value-attlist,
-  common-convert-empty-attlist,
-  common-data-field-attlist,
-  common-linked-cell
-form-control-attlist =
-  common-form-control-attlist,
-  common-control-id-attlist,
-  xforms-bind-attlist
-common-form-control-content = form-properties?, office-event-listeners?
-form-textarea-attlist =
-  form-control-attlist,
-  common-current-value-attlist,
-  common-disabled-attlist,
-  common-maxlength-attlist,
-  common-printable-attlist,
-  common-readonly-attlist,
-  common-tab-attlist,
-  common-title-attlist,
-  common-value-attlist,
-  common-convert-empty-attlist,
-  common-data-field-attlist,
-  common-linked-cell
-form-password-attlist =
-  form-control-attlist
-  & common-disabled-attlist
-  & common-maxlength-attlist
-  & common-printable-attlist
-  & common-tab-attlist
-  & common-title-attlist
-  & common-value-attlist
-  & common-convert-empty-attlist
-  & common-linked-cell
-  & attribute form:echo-char { character }?
-form-file-attlist =
-  form-control-attlist,
-  common-current-value-attlist,
-  common-disabled-attlist,
-  common-maxlength-attlist,
-  common-printable-attlist,
-  common-readonly-attlist,
-  common-tab-attlist,
-  common-title-attlist,
-  common-value-attlist,
-  common-linked-cell
-form-formatted-text-attlist =
-  form-control-attlist
-  & common-current-value-attlist
-  & common-disabled-attlist
-  & common-maxlength-attlist
-  & common-printable-attlist
-  & common-readonly-attlist
-  & common-tab-attlist
-  & common-title-attlist
-  & common-value-attlist
-  & common-convert-empty-attlist
-  & common-data-field-attlist
-  & common-linked-cell
-  & common-spin-button
-  & common-repeat
-  & common-delay-for-repeat
-  & attribute form:max-value { \string }?
-  & attribute form:min-value { \string }?
-  & attribute form:validation { boolean }?
-common-numeric-control-attlist =
-  form-control-attlist,
-  common-disabled-attlist,
-  common-maxlength-attlist,
-  common-printable-attlist,
-  common-readonly-attlist,
-  common-tab-attlist,
-  common-title-attlist,
-  common-convert-empty-attlist,
-  common-data-field-attlist
-form-number-attlist =
-  attribute form:value { double }?
-  & attribute form:current-value { double }?
-  & attribute form:min-value { double }?
-  & attribute form:max-value { double }?
-form-date-attlist =
-  attribute form:value { date }?
-  & attribute form:current-value { date }?
-  & attribute form:min-value { date }?
-  & attribute form:max-value { date }?
-form-time-attlist =
-  attribute form:value { time }?
-  & attribute form:current-value { time }?
-  & attribute form:min-value { time }?
-  & attribute form:max-value { time }?
-form-fixed-text-attlist =
-  form-control-attlist
-  & for
-  & common-disabled-attlist
-  & label
-  & common-printable-attlist
-  & common-title-attlist
-  & attribute form:multi-line { boolean }?
-form-combobox-attlist =
-  form-control-attlist
-  & common-current-value-attlist
-  & common-disabled-attlist
-  & dropdown
-  & common-maxlength-attlist
-  & common-printable-attlist
-  & common-readonly-attlist
-  & size
-  & common-tab-attlist
-  & common-title-attlist
-  & common-value-attlist
-  & common-convert-empty-attlist
-  & common-data-field-attlist
-  & list-source
-  & list-source-type
-  & common-linked-cell
-  & common-source-cell-range
-  & attribute form:auto-complete { boolean }?
-form-item = element form:item { form-item-attlist, text }
-form-item-attlist = label
-form-listbox-attlist =
-  form-control-attlist
-  & common-disabled-attlist
-  & dropdown
-  & common-printable-attlist
-  & size
-  & common-tab-attlist
-  & common-title-attlist
-  & bound-column
-  & common-data-field-attlist
-  & list-source
-  & list-source-type
-  & common-linked-cell
-  & list-linkage-type
-  & common-source-cell-range
-  & attribute form:multiple { boolean }?
-  & attribute form:xforms-list-source { \string }?
-list-linkage-type =
-  attribute form:list-linkage-type {
-    "selection" | "selection-indices"
-  }?
-form-option = element form:option { form-option-attlist, text }
-form-option-attlist =
-  current-selected, selected, label, common-value-attlist
-form-button-attlist =
-  form-control-attlist
-  & button-type
-  & common-disabled-attlist
-  & label
-  & image-data
-  & common-printable-attlist
-  & common-tab-attlist
-  & target-frame
-  & target-location
-  & common-title-attlist
-  & common-value-attlist
-  & common-form-relative-image-position-attlist
-  & common-repeat
-  & common-delay-for-repeat
-  & attribute form:default-button { boolean }?
-  & attribute form:toggle { boolean }?
-  & attribute form:focus-on-click { boolean }?
-  & attribute form:xforms-submission { \string }?
-form-image-attlist =
-  form-control-attlist,
-  button-type,
-  common-disabled-attlist,
-  image-data,
-  common-printable-attlist,
-  common-tab-attlist,
-  target-frame,
-  target-location,
-  common-title-attlist,
-  common-value-attlist
-form-checkbox-attlist =
-  form-control-attlist
-  & common-disabled-attlist
-  & label
-  & common-printable-attlist
-  & common-tab-attlist
-  & common-title-attlist
-  & common-value-attlist
-  & common-data-field-attlist
-  & common-form-visual-effect-attlist
-  & common-form-relative-image-position-attlist
-  & common-linked-cell
-  & attribute form:current-state { states }?
-  & attribute form:is-tristate { boolean }?
-  & attribute form:state { states }?
-states = "unchecked" | "checked" | "unknown"
-form-radio-attlist =
-  form-control-attlist,
-  current-selected,
-  common-disabled-attlist,
-  label,
-  common-printable-attlist,
-  selected,
-  common-tab-attlist,
-  common-title-attlist,
-  common-value-attlist,
-  common-data-field-attlist,
-  common-form-visual-effect-attlist,
-  common-form-relative-image-position-attlist,
-  common-linked-cell
-form-frame-attlist =
-  form-control-attlist,
-  common-disabled-attlist,
-  for,
-  label,
-  common-printable-attlist,
-  common-title-attlist
-form-image-frame-attlist =
-  form-control-attlist,
-  common-disabled-attlist,
-  image-data,
-  common-printable-attlist,
-  common-readonly-attlist,
-  common-title-attlist,
-  common-data-field-attlist
-form-hidden-attlist = form-control-attlist, common-value-attlist
-form-grid-attlist =
-  form-control-attlist,
-  common-disabled-attlist,
-  common-printable-attlist,
-  common-tab-attlist,
-  common-title-attlist
-form-column =
-  element form:column { form-column-attlist, column-controls+ }
-form-column-attlist =
-  common-form-control-attlist, label, text-style-name
-text-style-name = attribute form:text-style-name { styleNameRef }?
-form-value-range-attlist =
-  form-control-attlist
-  & common-disabled-attlist
-  & common-printable-attlist
-  & common-tab-attlist
-  & common-title-attlist
-  & common-value-attlist
-  & common-linked-cell
-  & common-repeat
-  & common-delay-for-repeat
-  & attribute form:max-value { integer }?
-  & attribute form:min-value { integer }?
-  & attribute form:step-size { positiveInteger }?
-  & attribute form:page-step-size { positiveInteger }?
-  & attribute form:orientation { "horizontal" | "vertical" }?
-form-generic-control-attlist = form-control-attlist
-common-form-control-attlist =
-  attribute form:name { \string }?
-  & attribute form:control-implementation { namespacedToken }?
-xforms-bind-attlist = attribute xforms:bind { \string }?
-types = "submit" | "reset" | "push" | "url"
-button-type = attribute form:button-type { types }?
-common-control-id-attlist =
-  xml-id,
-  attribute form:id { NCName }?
-current-selected = attribute form:current-selected { boolean }?
-common-value-attlist = attribute form:value { \string }?
-common-current-value-attlist = attribute form:current-value { \string }?
-common-disabled-attlist = attribute form:disabled { boolean }?
-dropdown = attribute form:dropdown { boolean }?
-for = attribute form:for { \string }?
-image-data = attribute form:image-data { anyIRI }?
-label = attribute form:label { \string }?
-common-maxlength-attlist =
-  attribute form:max-length { nonNegativeInteger }?
-common-printable-attlist = attribute form:printable { boolean }?
-common-readonly-attlist = attribute form:readonly { boolean }?
-selected = attribute form:selected { boolean }?
-size = attribute form:size { nonNegativeInteger }?
-common-tab-attlist =
-  attribute form:tab-index { nonNegativeInteger }?
-  & attribute form:tab-stop { boolean }?
-target-frame = attribute office:target-frame { targetFrameName }?
-target-location = attribute xlink:href { anyIRI }?
-common-title-attlist = attribute form:title { \string }?
-common-form-visual-effect-attlist =
-  attribute form:visual-effect { "flat" | "3d" }?
-common-form-relative-image-position-attlist =
-  attribute form:image-position { "center" }?
-  | (attribute form:image-position {
-       "start" | "end" | "top" | "bottom"
-     },
-     attribute form:image-align { "start" | "center" | "end" }?)
-bound-column = attribute form:bound-column { \string }?
-common-convert-empty-attlist =
-  attribute form:convert-empty-to-null { boolean }?
-common-data-field-attlist = attribute form:data-field { \string }?
-list-source = attribute form:list-source { \string }?
-list-source-type =
-  attribute form:list-source-type {
-    "table"
-    | "query"
-    | "sql"
-    | "sql-pass-through"
-    | "value-list"
-    | "table-fields"
-  }?
-common-linked-cell =
-  attribute form:linked-cell { cellAddress | \string }?
-common-source-cell-range =
-  attribute form:source-cell-range { cellRangeAddress | \string }?
-common-spin-button = attribute form:spin-button { boolean }?
-common-repeat = attribute form:repeat { boolean }?
-common-delay-for-repeat = attribute form:delay-for-repeat { duration }?
-form-properties = element form:properties { form-property+ }
-form-property =
-  element form:property {
-    form-property-name, form-property-value-and-type-attlist
-  }
-  | element form:list-property {
-      form-property-name, form-property-type-and-value-list
-    }
-form-property-name = attribute form:property-name { \string }
-form-property-value-and-type-attlist =
-  common-value-and-type-attlist
-  | attribute office:value-type { "void" }
-form-property-type-and-value-list =
-  (attribute office:value-type { "float" },
-   element form:list-value {
-     attribute office:value { double }
-   }*)
-  | (attribute office:value-type { "percentage" },
-     element form:list-value {
-       attribute office:value { double }
-     }*)
-  | (attribute office:value-type { "currency" },
-     element form:list-value {
-       attribute office:value { double },
-       attribute office:currency { \string }?
-     }*)
-  | (attribute office:value-type { "date" },
-     element form:list-value {
-       attribute office:date-value { dateOrDateTime }
-     }*)
-  | (attribute office:value-type { "time" },
-     element form:list-value {
-       attribute office:time-value { duration }
-     }*)
-  | (attribute office:value-type { "boolean" },
-     element form:list-value {
-       attribute office:boolean-value { boolean }
-     }*)
-  | (attribute office:value-type { "string" },
-     element form:list-value {
-       attribute office:string-value { \string }
-     }*)
-  | attribute office:value-type { "void" }
-office-annotation =
-  element office:annotation {
-    office-annotation-attlist,
-    draw-caption-attlist,
-    common-draw-position-attlist,
-    common-draw-size-attlist,
-    common-draw-shape-with-text-and-styles-attlist,
-    dc-creator?,
-    dc-date?,
-    meta-date-string?,
-    (text-p | text-list)*
-  }
-office-annotation-end =
-  element office:annotation-end { office-annotation-end-attlist }
-office-annotation-attlist =
-  attribute office:display { boolean }?
-  & common-office-annotation-name-attlist?
-office-annotation-end-attlist = common-office-annotation-name-attlist
-common-office-annotation-name-attlist =
-  attribute office:name { \string }
-meta-date-string = element meta:date-string { \string }
-common-num-format-prefix-suffix-attlist =
-  attribute style:num-prefix { \string }?,
-  attribute style:num-suffix { \string }?
-common-num-format-attlist =
-  attribute style:num-format { "1" | "i" | "I" | \string | empty }
-  | (attribute style:num-format { "a" | "A" },
-     style-num-letter-sync-attlist)
-  | empty
-style-num-letter-sync-attlist =
-  attribute style:num-letter-sync { boolean }?
-office-change-info =
-  element office:change-info { dc-creator, dc-date, text-p* }
-office-event-listeners =
-  element office:event-listeners {
-    (script-event-listener | presentation-event-listener)*
-  }
-script-event-listener =
-  element script:event-listener { script-event-listener-attlist, empty }
-script-event-listener-attlist =
-  attribute script:event-name { \string }
-  & attribute script:language { \string }
-  & (attribute script:macro-name { \string }
-     | (attribute xlink:type { "simple" },
-        attribute xlink:href { anyIRI },
-        attribute xlink:actuate { "onRequest" }?))
-math-math = element math:math { mathMarkup }
-[
-  dc:description [
-    "To avoid inclusion of the complete MathML schema, anything is allowed 
within a math:math top-level element"
-  ]
-]
-mathMarkup =
-  (attribute * { text }
-   | text
-   | element * { mathMarkup })*
-text-dde-connection-decl =
-  element text:dde-connection-decl {
-    text-dde-connection-decl-attlist, common-dde-connection-decl-attlist
-  }
-text-dde-connection-decl-attlist = attribute office:name { \string }
-common-dde-connection-decl-attlist =
-  attribute office:dde-application { \string }
-  & attribute office:dde-topic { \string }
-  & attribute office:dde-item { \string }
-  & attribute office:automatic-update { boolean }?
-table-dde-link =
-  element table:dde-link { office-dde-source, table-table }
-office-dde-source =
-  element office:dde-source {
-    office-dde-source-attlist, common-dde-connection-decl-attlist
-  }
-office-dde-source-attlist =
-  attribute office:name { \string }?
-  & attribute office:conversion-mode {
-      "into-default-style-data-style"
-      | "into-english-number"
-      | "keep-text"
-    }?
-animation-element =
-  element anim:animate {
-    common-anim-target-attlist,
-    common-anim-named-target-attlist,
-    common-anim-values-attlist,
-    common-anim-spline-mode-attlist,
-    common-spline-anim-value-attlist,
-    common-timing-attlist,
-    common-anim-add-accum-attlist
-  }
-  | element anim:set {
-      common-anim-target-attlist,
-      common-anim-named-target-attlist,
-      common-anim-set-values-attlist,
-      common-timing-attlist,
-      common-anim-add-accum-attlist
-    }
-  | element anim:animateMotion {
-      anim-animate-motion-attlist,
-      common-anim-target-attlist,
-      common-anim-named-target-attlist,
-      common-anim-add-accum-attlist,
-      common-anim-values-attlist,
-      common-timing-attlist,
-      common-spline-anim-value-attlist
-    }
-  | element anim:animateColor {
-      common-anim-target-attlist,
-      common-anim-named-target-attlist,
-      common-anim-add-accum-attlist,
-      common-anim-values-attlist,
-      common-anim-spline-mode-attlist,
-      common-spline-anim-value-attlist,
-      anim-animate-color-attlist,
-      common-timing-attlist
-    }
-  | element anim:animateTransform {
-      common-anim-target-attlist,
-      common-anim-named-target-attlist,
-      common-anim-add-accum-attlist,
-      common-anim-values-attlist,
-      anim-animate-transform-attlist,
-      common-timing-attlist
-    }
-  | element anim:transitionFilter {
-      common-anim-target-attlist,
-      common-anim-add-accum-attlist,
-      common-anim-values-attlist,
-      common-anim-spline-mode-attlist,
-      anim-transition-filter-attlist,
-      common-timing-attlist
-    }
-  | element anim:par {
-      common-anim-attlist,
-      common-timing-attlist,
-      common-endsync-timing-attlist,
-      animation-element*
-    }
-  | element anim:seq {
-      common-anim-attlist,
-      common-endsync-timing-attlist,
-      common-timing-attlist,
-      animation-element*
-    }
-  | element anim:iterate {
-      common-anim-attlist,
-      anim-iterate-attlist,
-      common-timing-attlist,
-      common-endsync-timing-attlist,
-      animation-element*
-    }
-  | element anim:audio {
-      common-anim-attlist,
-      anim-audio-attlist,
-      common-basic-timing-attlist
-    }
-  | element anim:command {
-      common-anim-attlist,
-      anim-command-attlist,
-      common-begin-end-timing-attlist,
-      common-anim-target-attlist,
-      element anim:param {
-        attribute anim:name { \string },
-        attribute anim:value { \string }
-      }*
-    }
-anim-animate-motion-attlist =
-  attribute svg:path { pathData }?
-  & attribute svg:origin { \string }?
-  & attribute smil:calcMode {
-      "discrete" | "linear" | "paced" | "spline"
-    }?
-anim-animate-color-attlist =
-  attribute anim:color-interpolation { "rgb" | "hsl" }?
-  & attribute anim:color-interpolation-direction {
-      "clockwise" | "counter-clockwise"
-    }?
-anim-animate-transform-attlist =
-  attribute svg:type {
-    "translate" | "scale" | "rotate" | "skewX" | "skewY"
-  }
-anim-transition-filter-attlist =
-  attribute smil:type { \string }
-  & attribute smil:subtype { \string }?
-  & attribute smil:direction { "forward" | "reverse" }?
-  & attribute smil:fadeColor { color }?
-  & attribute smil:mode { "in" | "out" }?
-common-anim-target-attlist =
-  attribute smil:targetElement { IDREF }?
-  & attribute anim:sub-item { \string }?
-common-anim-named-target-attlist =
-  attribute smil:attributeName { \string }
-common-anim-values-attlist =
-  attribute smil:values { \string }?
-  & attribute anim:formula { \string }?
-  & common-anim-set-values-attlist
-  & attribute smil:from { \string }?
-  & attribute smil:by { \string }?
-common-anim-spline-mode-attlist =
-  attribute smil:calcMode {
-    "discrete" | "linear" | "paced" | "spline"
-  }?
-common-spline-anim-value-attlist =
-  attribute smil:keyTimes { \string }?
-  & attribute smil:keySplines { \string }?
-common-anim-add-accum-attlist =
-  attribute smil:accumulate { "none" | "sum" }?
-  & attribute smil:additive { "replace" | "sum" }?
-common-anim-set-values-attlist = attribute smil:to { \string }?
-common-begin-end-timing-attlist =
-  attribute smil:begin { \string }?
-  & attribute smil:end { \string }?
-common-dur-timing-attlist = attribute smil:dur { \string }?
-common-endsync-timing-attlist =
-  attribute smil:endsync { "first" | "last" | "all" | "media" | IDREF }?
-common-repeat-timing-attlist =
-  attribute smil:repeatDur { \string }?,
-  attribute smil:repeatCount { nonNegativeDecimal | "indefinite" }?
-nonNegativeDecimal = xsd:decimal { minInclusive = "0.0" }
-common-fill-timing-attlist =
-  attribute smil:fill {
-    "remove" | "freeze" | "hold" | "auto" | "default" | "transition"
-  }?
-common-fill-default-attlist =
-  attribute smil:fillDefault {
-    "remove" | "freeze" | "hold" | "transition" | "auto" | "inherit"
-  }?
-common-restart-timing-attlist =
-  attribute smil:restart {
-    "never" | "always" | "whenNotActive" | "default"
-  }?
-common-restart-default-attlist =
-  attribute smil:restartDefault {
-    "never" | "always" | "whenNotActive" | "inherit"
-  }?
-common-time-manip-attlist =
-  attribute smil:accelerate { zeroToOneDecimal }?
-  & attribute smil:decelerate { zeroToOneDecimal }?
-  & attribute smil:autoReverse { boolean }?
-zeroToOneDecimal = xsd:decimal { minInclusive = "0" maxInclusive = "1" }
-common-basic-timing-attlist =
-  common-begin-end-timing-attlist,
-  common-dur-timing-attlist,
-  common-repeat-timing-attlist,
-  common-restart-timing-attlist,
-  common-restart-default-attlist,
-  common-fill-timing-attlist,
-  common-fill-default-attlist
-common-timing-attlist =
-  common-basic-timing-attlist, common-time-manip-attlist
-anim-iterate-attlist =
-  common-anim-target-attlist
-  & attribute anim:iterate-type { \string }?
-  & attribute anim:iterate-interval { duration }?
-anim-audio-attlist =
-  attribute xlink:href { anyIRI }?
-  & attribute anim:audio-level { double }?
-anim-command-attlist = attribute anim:command { \string }
-style-style =
-  element style:style {
-    style-style-attlist, style-style-content, style-map*
-  }
-common-in-content-meta-attlist =
-  attribute xhtml:about { URIorSafeCURIE },
-  attribute xhtml:property { CURIEs },
-  common-meta-literal-attlist
-common-meta-literal-attlist =
-  attribute xhtml:datatype { CURIE }?,
-  attribute xhtml:content { \string }?
-xml-id = attribute xml:id { ID }
-style-style-attlist =
-  attribute style:name { styleName }
-  & attribute style:display-name { \string }?
-  & attribute style:parent-style-name { styleNameRef }?
-  & attribute style:next-style-name { styleNameRef }?
-  & attribute style:list-level { positiveInteger | empty }?
-  & attribute style:list-style-name { styleName | empty }?
-  & attribute style:master-page-name { styleNameRef }?
-  & attribute style:auto-update { boolean }?
-  & attribute style:data-style-name { styleNameRef }?
-  & attribute style:percentage-data-style-name { styleNameRef }?
-  & attribute style:class { \string }?
-  & attribute style:default-outline-level { positiveInteger | empty }?
-style-map = element style:map { style-map-attlist, empty }
-style-map-attlist =
-  attribute style:condition { \string }
-  & attribute style:apply-style-name { styleNameRef }
-  & attribute style:base-cell-address { cellAddress }?
-style-default-style =
-  element style:default-style { style-style-content }
-style-page-layout =
-  element style:page-layout {
-    style-page-layout-attlist, style-page-layout-content
-  }
-style-page-layout-content =
-  style-page-layout-properties?,
-  style-header-style?,
-  style-footer-style?
-style-page-layout-attlist =
-  attribute style:name { styleName }
-  & attribute style:page-usage {
-      "all" | "left" | "right" | "mirrored"
-    }?
-style-header-style =
-  element style:header-style { style-header-footer-properties? }
-style-footer-style =
-  element style:footer-style { style-header-footer-properties? }
-style-default-page-layout =
-  element style:default-page-layout { style-page-layout-content }
-style-master-page =
-  element style:master-page {
-    style-master-page-attlist,
-    (style-header, style-header-left?)?,
-    (style-footer, style-footer-left?)?,
-    draw-layer-set?,
-    office-forms?,
-    shape*,
-    animation-element?,
-    presentation-notes?
-  }
-style-master-page-attlist =
-  attribute style:name { styleName }
-  & attribute style:display-name { \string }?
-  & attribute style:page-layout-name { styleNameRef }
-  & attribute draw:style-name { styleNameRef }?
-  & attribute style:next-style-name { styleNameRef }?
-style-header =
-  element style:header {
-    common-style-header-footer-attlist, header-footer-content
-  }
-style-footer =
-  element style:footer {
-    common-style-header-footer-attlist, header-footer-content
-  }
-style-header-left =
-  element style:header-left {
-    common-style-header-footer-attlist, header-footer-content
-  }
-style-footer-left =
-  element style:footer-left {
-    common-style-header-footer-attlist, header-footer-content
-  }
-header-footer-content =
-  (text-tracked-changes,
-   text-decls,
-   (text-h
-    | text-p
-    | text-list
-    | table-table
-    | text-section
-    | text-table-of-content
-    | text-illustration-index
-    | text-table-index
-    | text-object-index
-    | text-user-index
-    | text-alphabetical-index
-    | text-bibliography
-    | text-index-title
-    | change-marks)*)
-  | (style-region-left?, style-region-center?, style-region-right?)
-common-style-header-footer-attlist =
-  attribute style:display { boolean }?
-style-region-left = element style:region-left { region-content }
-style-region-center = element style:region-center { region-content }
-style-region-right = element style:region-right { region-content }
-region-content = text-p*
-presentation-notes =
-  element presentation:notes {
-    common-presentation-header-footer-attlist,
-    presentation-notes-attlist,
-    office-forms,
-    shape*
-  }
-presentation-notes-attlist =
-  attribute style:page-layout-name { styleNameRef }?
-  & attribute draw:style-name { styleNameRef }?
-table-table-template =
-  element table:table-template {
-    table-table-template-attlist,
-    table-first-row?,
-    table-last-row?,
-    table-first-column?,
-    table-last-column?,
-    table-body,
-    table-even-rows?,
-    table-odd-rows?,
-    table-even-columns?,
-    table-odd-columns?,
-    table-background?
-  }
-table-table-template-attlist =
-  attribute table:name { \string }
-  & attribute table:first-row-start-column { rowOrCol }
-  & attribute table:first-row-end-column { rowOrCol }
-  & attribute table:last-row-start-column { rowOrCol }
-  & attribute table:last-row-end-column { rowOrCol }
-rowOrCol = "row" | "column"
-table-first-row =
-  element table:first-row { common-table-template-attlist, empty }
-table-last-row =
-  element table:last-row { common-table-template-attlist, empty }
-table-first-column =
-  element table:first-column { common-table-template-attlist, empty }
-table-last-column =
-  element table:last-column { common-table-template-attlist, empty }
-table-body = element table:body { common-table-template-attlist, empty }
-table-even-rows =
-  element table:even-rows { common-table-template-attlist, empty }
-table-odd-rows =
-  element table:odd-rows { common-table-template-attlist, empty }
-table-even-columns =
-  element table:even-columns { common-table-template-attlist, empty }
-table-odd-columns =
-  element table:odd-columns { common-table-template-attlist, empty }
-common-table-template-attlist =
-  attribute table:style-name { styleNameRef },
-  attribute table:paragraph-style-name { styleNameRef }?
-table-background =
-  element table:background { table-background-attlist, empty }
-table-background-attlist = attribute table:style-name { styleNameRef }
-style-font-face =
-  element style:font-face {
-    style-font-face-attlist, svg-font-face-src?, svg-definition-src?
-  }
-style-font-face-attlist =
-  attribute svg:font-family { \string }?
-  & attribute svg:font-style { fontStyle }?
-  & attribute svg:font-variant { fontVariant }?
-  & attribute svg:font-weight { fontWeight }?
-  & attribute svg:font-stretch {
-      "normal"
-      | "ultra-condensed"
-      | "extra-condensed"
-      | "condensed"
-      | "semi-condensed"
-      | "semi-expanded"
-      | "expanded"
-      | "extra-expanded"
-      | "ultra-expanded"
-    }?
-  & attribute svg:font-size { positiveLength }?
-  & attribute svg:unicode-range { \string }?
-  & attribute svg:units-per-em { integer }?
-  & attribute svg:panose-1 { \string }?
-  & attribute svg:stemv { integer }?
-  & attribute svg:stemh { integer }?
-  & attribute svg:slope { integer }?
-  & attribute svg:cap-height { integer }?
-  & attribute svg:x-height { integer }?
-  & attribute svg:accent-height { integer }?
-  & attribute svg:ascent { integer }?
-  & attribute svg:descent { integer }?
-  & attribute svg:widths { \string }?
-  & attribute svg:bbox { \string }?
-  & attribute svg:ideographic { integer }?
-  & attribute svg:alphabetic { integer }?
-  & attribute svg:mathematical { integer }?
-  & attribute svg:hanging { integer }?
-  & attribute svg:v-ideographic { integer }?
-  & attribute svg:v-alphabetic { integer }?
-  & attribute svg:v-mathematical { integer }?
-  & attribute svg:v-hanging { integer }?
-  & attribute svg:underline-position { integer }?
-  & attribute svg:underline-thickness { integer }?
-  & attribute svg:strikethrough-position { integer }?
-  & attribute svg:strikethrough-thickness { integer }?
-  & attribute svg:overline-position { integer }?
-  & attribute svg:overline-thickness { integer }?
-  & attribute style:name { \string }
-  & attribute style:font-adornments { \string }?
-  & attribute style:font-family-generic { fontFamilyGeneric }?
-  & attribute style:font-pitch { fontPitch }?
-  & attribute style:font-charset { textEncoding }?
-svg-font-face-src =
-  element svg:font-face-src {
-    (svg-font-face-uri | svg-font-face-name)+
-  }
-svg-font-face-uri =
-  element svg:font-face-uri {
-    common-svg-font-face-xlink-attlist, svg-font-face-format*
-  }
-svg-font-face-format =
-  element svg:font-face-format {
-    attribute svg:string { \string }?,
-    empty
+   attribute xlink:actuate { "onRequest" }?)?
+  & attribute office:target-frame { targetFrameName }?
+  & attribute form:method { "get" | "post" | \string }?
+  & attribute form:enctype { \string }?
+  & attribute form:allow-deletes { boolean }?
+  & attribute form:allow-inserts { boolean }?
+  & attribute form:allow-updates { boolean }?
+  & attribute form:apply-filter { boolean }?
+  & attribute form:command-type { "table" | "query" | "command" }?
+  & attribute form:command { \string }?
+  & attribute form:datasource { anyIRI | \string }?
+  & attribute form:master-fields { \string }?
+  & attribute form:detail-fields { \string }?
+  & attribute form:escape-processing { boolean }?
+  & attribute form:filter { \string }?
+  & attribute form:ignore-result { boolean }?
+  & attribute form:navigation-mode { navigation }?
+  & attribute form:order { \string }?
+  & attribute form:tab-cycle { tab-cycles }?
+form-formatted-text-attlist =
+  form-control-attlist
+  & common-current-value-attlist
+  & common-disabled-attlist
+  & common-maxlength-attlist
+  & common-printable-attlist
+  & common-readonly-attlist
+  & common-tab-attlist
+  & common-title-attlist
+  & common-value-attlist
+  & common-convert-empty-attlist
+  & common-data-field-attlist
+  & common-linked-cell
+  & common-spin-button
+  & common-repeat
+  & common-delay-for-repeat
+  & attribute form:max-value { \string }?
+  & attribute form:min-value { \string }?
+  & attribute form:validation { boolean }?
+form-frame-attlist =
+  form-control-attlist,
+  common-disabled-attlist,
+  for,
+  label,
+  common-printable-attlist,
+  common-title-attlist
+form-generic-control-attlist = form-control-attlist
+form-grid-attlist =
+  form-control-attlist,
+  common-disabled-attlist,
+  common-printable-attlist,
+  common-tab-attlist,
+  common-title-attlist
+form-hidden-attlist = form-control-attlist, common-value-attlist
+form-image-attlist =
+  form-control-attlist,
+  button-type,
+  common-disabled-attlist,
+  image-data,
+  common-printable-attlist,
+  common-tab-attlist,
+  target-frame,
+  target-location,
+  common-title-attlist,
+  common-value-attlist
+form-image-frame-attlist =
+  form-control-attlist,
+  common-disabled-attlist,
+  image-data,
+  common-printable-attlist,
+  common-readonly-attlist,
+  common-title-attlist,
+  common-data-field-attlist
+form-item = element form:item { form-item-attlist, text }
+form-item-attlist = label
+form-listbox-attlist =
+  form-control-attlist
+  & common-disabled-attlist
+  & dropdown
+  & common-printable-attlist
+  & size
+  & common-tab-attlist
+  & common-title-attlist
+  & bound-column
+  & common-data-field-attlist
+  & list-source
+  & list-source-type
+  & common-linked-cell
+  & list-linkage-type
+  & common-source-cell-range
+  & attribute form:multiple { boolean }?
+  & attribute form:xforms-list-source { \string }?
+form-number-attlist =
+  attribute form:value { double }?
+  & attribute form:current-value { double }?
+  & attribute form:min-value { double }?
+  & attribute form:max-value { double }?
+form-option = element form:option { form-option-attlist, text }
+form-option-attlist =
+  current-selected, selected, label, common-value-attlist
+form-password-attlist =
+  form-control-attlist
+  & common-disabled-attlist
+  & common-maxlength-attlist
+  & common-printable-attlist
+  & common-tab-attlist
+  & common-title-attlist
+  & common-value-attlist
+  & common-convert-empty-attlist
+  & common-linked-cell
+  & attribute form:echo-char { character }?
+form-properties = element form:properties { form-property+ }
+form-property =
+  element form:property {
+    form-property-name, form-property-value-and-type-attlist
   }
-svg-font-face-name =
-  element svg:font-face-name {
-    attribute svg:name { \string }?,
-    empty
+  | element form:list-property {
+      form-property-name, form-property-type-and-value-list
+    }
+form-property-name = attribute form:property-name { \string }
+form-property-type-and-value-list =
+  (attribute office:value-type { "float" },
+   element form:list-value {
+     attribute office:value { double }
+   }*)
+  | (attribute office:value-type { "percentage" },
+     element form:list-value {
+       attribute office:value { double }
+     }*)
+  | (attribute office:value-type { "currency" },
+     element form:list-value {
+       attribute office:value { double },
+       attribute office:currency { \string }?
+     }*)
+  | (attribute office:value-type { "date" },
+     element form:list-value {
+       attribute office:date-value { dateOrDateTime }
+     }*)
+  | (attribute office:value-type { "time" },
+     element form:list-value {
+       attribute office:time-value { duration }
+     }*)
+  | (attribute office:value-type { "boolean" },
+     element form:list-value {
+       attribute office:boolean-value { boolean }
+     }*)
+  | (attribute office:value-type { "string" },
+     element form:list-value {
+       attribute office:string-value { \string }
+     }*)
+  | attribute office:value-type { "void" }
+form-property-value-and-type-attlist =
+  common-value-and-type-attlist
+  | attribute office:value-type { "void" }
+form-radio-attlist =
+  form-control-attlist,
+  current-selected,
+  common-disabled-attlist,
+  label,
+  common-printable-attlist,
+  selected,
+  common-tab-attlist,
+  common-title-attlist,
+  common-value-attlist,
+  common-data-field-attlist,
+  common-form-visual-effect-attlist,
+  common-form-relative-image-position-attlist,
+  common-linked-cell
+form-text-attlist =
+  form-control-attlist,
+  common-current-value-attlist,
+  common-disabled-attlist,
+  common-maxlength-attlist,
+  common-printable-attlist,
+  common-readonly-attlist,
+  common-tab-attlist,
+  common-title-attlist,
+  common-value-attlist,
+  common-convert-empty-attlist,
+  common-data-field-attlist,
+  common-linked-cell
+form-textarea-attlist =
+  form-control-attlist,
+  common-current-value-attlist,
+  common-disabled-attlist,
+  common-maxlength-attlist,
+  common-printable-attlist,
+  common-readonly-attlist,
+  common-tab-attlist,
+  common-title-attlist,
+  common-value-attlist,
+  common-convert-empty-attlist,
+  common-data-field-attlist,
+  common-linked-cell
+form-time-attlist =
+  attribute form:value { time }?
+  & attribute form:current-value { time }?
+  & attribute form:min-value { time }?
+  & attribute form:max-value { time }?
+form-value-range-attlist =
+  form-control-attlist
+  & common-disabled-attlist
+  & common-printable-attlist
+  & common-tab-attlist
+  & common-title-attlist
+  & common-value-attlist
+  & common-linked-cell
+  & common-repeat
+  & common-delay-for-repeat
+  & attribute form:max-value { integer }?
+  & attribute form:min-value { integer }?
+  & attribute form:step-size { positiveInteger }?
+  & attribute form:page-step-size { positiveInteger }?
+  & attribute form:orientation { "horizontal" | "vertical" }?
+gradient-style =
+  "linear" | "axial" | "radial" | "ellipsoid" | "square" | "rectangular"
+header-footer-content =
+  (text-tracked-changes,
+   text-decls,
+   (text-h
+    | text-p
+    | text-list
+    | table-table
+    | text-section
+    | text-table-of-content
+    | text-illustration-index
+    | text-table-index
+    | text-object-index
+    | text-user-index
+    | text-alphabetical-index
+    | text-bibliography
+    | text-index-title
+    | change-marks)*)
+  | (style-region-left?, style-region-center?, style-region-right?)
+heading-attrs =
+  attribute text:outline-level { positiveInteger }
+  & attribute text:restart-numbering { boolean }?
+  & attribute text:start-value { nonNegativeInteger }?
+  & attribute text:is-list-header { boolean }?
+horiBackPos = "left" | "center" | "right"
+horizontal-mirror =
+  "horizontal" | "horizontal-on-odd" | "horizontal-on-even"
+image-data = attribute form:image-data { anyIRI }?
+index-content-main = text-content | text-index-title
+integer = xsd:integer
+label = attribute form:label { \string }?
+labelPositions =
+  "avoid-overlap"
+  | "center"
+  | "top"
+  | "top-right"
+  | "right"
+  | "bottom-right"
+  | "bottom"
+  | "bottom-left"
+  | "left"
+  | "top-left"
+  | "inside"
+  | "outside"
+  | "near-origin"
+language = xsd:language
+languageCode = xsd:token { pattern = "[A-Za-z]{1,8}" }
+length =
+  xsd:string {
+    pattern =
+      "-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)|(px))"
   }
-svg-definition-src =
-  element svg:definition-src {
-    common-svg-font-face-xlink-attlist, empty
+lineMode = "continuous" | "skip-white-space"
+lineStyle =
+  "none"
+  | "solid"
+  | "dotted"
+  | "dash"
+  | "long-dash"
+  | "dot-dash"
+  | "dot-dot-dash"
+  | "wave"
+lineType = "none" | "single" | "double"
+lineWidth =
+  "auto"
+  | "normal"
+  | "bold"
+  | "thin"
+  | "medium"
+  | "thick"
+  | positiveInteger
+  | percent
+  | positiveLength
+list-linkage-type =
+  attribute form:list-linkage-type {
+    "selection" | "selection-indices"
+  }?
+list-source = attribute form:list-source { \string }?
+list-source-type =
+  attribute form:list-source-type {
+    "table"
+    | "query"
+    | "sql"
+    | "sql-pass-through"
+    | "value-list"
+    | "table-fields"
+  }?
+math-math = element math:math { mathMarkup }
+[
+  dc:description [
+    "To avoid inclusion of the complete MathML schema, anything is allowed 
within a math:math top-level element"
+  ]
+]
+mathMarkup =
+  (attribute * { text }
+   | text
+   | element * { mathMarkup })*
+meta-date-string = element meta:date-string { \string }
+namespacedToken = xsd:QName { pattern = "[^:]+:[^:]+" }
+navigation = "none" | "current" | "parent"
+nonNegativeDecimal = xsd:decimal { minInclusive = "0.0" }
+nonNegativeInteger = xsd:nonNegativeInteger
+nonNegativeLength =
+  xsd:string {
+    pattern =
+      "([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)|(px))"
   }
-common-svg-font-face-xlink-attlist =
-  attribute xlink:type { "simple" },
-  attribute xlink:href { anyIRI },
-  attribute xlink:actuate { "onRequest" }?
-number-number-style =
-  element number:number-style {
+nonNegativePixelLength =
+  xsd:string { pattern = "([0-9]+(\.[0-9]*)?|\.[0-9]+)(px)" }
+number-am-pm = element number:am-pm { empty }
+number-and-text =
+  number-number,
+  (number-text-with-fillchar?)
+  # https://issues.oasis-open.org/browse/OFFICE-3765
+
+number-boolean = element number:boolean { empty }
+number-boolean-style =
+  element number:boolean-style {
     common-data-style-attlist,
     style-text-properties?,
     number-text?,
-    (any-number, number-text?)?,
+    (number-boolean, number-text?)?,
     style-map*
   }
-any-number = number-number | number-scientific-number | number-fraction
-number-number =
-  element number:number {
-    number-number-attlist,
-    common-decimal-places-attlist,
-    common-number-attlist,
-    number-embedded-text*
-  }
-number-number-attlist =
-  attribute number:decimal-replacement { \string }?
-  & attribute number:display-factor { double }?
-number-embedded-text =
-  element number:embedded-text { number-embedded-text-attlist, text }
-number-embedded-text-attlist = attribute number:position { integer }
-number-scientific-number =
-  element number:scientific-number {
-    number-scientific-number-attlist,
-    common-decimal-places-attlist,
-    common-number-attlist,
-    empty
-  }
-number-scientific-number-attlist =
-  attribute number:min-exponent-digits { integer }?
-number-fraction =
-  element number:fraction {
-    number-fraction-attlist, common-number-attlist, empty
-  }
-number-fraction-attlist =
-  attribute number:min-numerator-digits { integer }?
-  & attribute number:min-denominator-digits { integer }?
-  & attribute number:denominator-value { integer }?
 number-currency-style =
   element number:currency-style {
     common-data-style-attlist,
     common-auto-reorder-attlist,
     style-text-properties?,
-    number-text?,
+    number-text-with-fillchar?,
+    # https://issues.oasis-open.org/browse/OFFICE-3765
     ((number-and-text, currency-symbol-and-text?)
      | (currency-symbol-and-text, number-and-text?))?,
     style-map*
   }
-currency-symbol-and-text = number-currency-symbol, number-text?
-number-and-text = number-number, number-text?
 number-currency-symbol =
-  element number:currency-symbol {
-    number-currency-symbol-attlist, text
-  }
-number-currency-symbol-attlist =
-  attribute number:language { languageCode }?,
-  attribute number:country { countryCode }?,
-  attribute number:script { scriptCode }?,
-  attribute number:rfc-language-tag { language }?
-number-percentage-style =
-  element number:percentage-style {
-    common-data-style-attlist,
-    style-text-properties?,
-    number-text?,
-    number-and-text?,
-    style-map*
+  element number:currency-symbol {
+    number-currency-symbol-attlist, text
   }
+number-currency-symbol-attlist =
+  attribute number:language { languageCode }?,
+  attribute number:country { countryCode }?,
+  attribute number:script { scriptCode }?,
+  attribute number:rfc-language-tag { language }?
 number-date-style =
   element number:date-style {
     common-data-style-attlist,
     common-auto-reorder-attlist,
     common-format-source-attlist,
     style-text-properties?,
-    number-text?,
-    (any-date, number-text?)+,
+    number-text-with-fillchar?,
+    # https://issues.oasis-open.org/browse/OFFICE-3765
+    (any-date,
+     (number-text-with-fillchar?)
+     # https://issues.oasis-open.org/browse/OFFICE-3765
+     )+,
     style-map*
   }
-any-date =
-  number-day
-  | number-month
-  | number-year
-  | number-era
-  | number-day-of-week
-  | number-week-of-year
-  | number-quarter
-  | number-hours
-  | number-am-pm
-  | number-minutes
-  | number-seconds
 number-day =
   element number:day {
     number-day-attlist, common-calendar-attlist, empty
   }
 number-day-attlist = attribute number:style { "short" | "long" }?
+number-day-of-week =
+  element number:day-of-week {
+    number-day-of-week-attlist, common-calendar-attlist, empty
+  }
+number-day-of-week-attlist =
+  attribute number:style { "short" | "long" }?
+number-embedded-text =
+  element number:embedded-text { number-embedded-text-attlist, text }
+number-embedded-text-attlist = attribute number:position { integer }
+number-era =
+  element number:era {
+    number-era-attlist, common-calendar-attlist, empty
+  }
+number-era-attlist = attribute number:style { "short" | "long" }?
+number-fill-character = element number:fill-character { text }
+# https://issues.oasis-open.org/browse/OFFICE-3765
+number-fraction =
+  element number:fraction {
+    number-fraction-attlist, common-number-attlist, empty
+  }
+number-fraction-attlist =
+  attribute number:min-numerator-digits { integer }?
+  & attribute number:min-denominator-digits { integer }?
+  & attribute number:denominator-value { integer }?
+  & (attribute number:max-denominator-value { positiveInteger }?)
+    # https://issues.oasis-open.org/browse/OFFICE-3695 max-denominator-value
+
+number-hours = element number:hours { number-hours-attlist, empty }
+number-hours-attlist = attribute number:style { "short" | "long" }?
+number-minutes =
+  element number:minutes { number-minutes-attlist, empty }
+number-minutes-attlist = attribute number:style { "short" | "long" }?
 number-month =
   element number:month {
     number-month-attlist, common-calendar-attlist, empty
@@ -4704,743 +2587,991 @@ number-month-attlist =
   attribute number:textual { boolean }?
   & attribute number:possessive-form { boolean }?
   & attribute number:style { "short" | "long" }?
-number-year =
-  element number:year {
-    number-year-attlist, common-calendar-attlist, empty
+number-number =
+  element number:number {
+    number-number-attlist,
+    common-decimal-places-attlist,
+    common-number-attlist,
+    number-embedded-text*
   }
-number-year-attlist = attribute number:style { "short" | "long" }?
-number-era =
-  element number:era {
-    number-era-attlist, common-calendar-attlist, empty
+number-number-attlist =
+  attribute number:decimal-replacement { \string }?
+  & attribute number:display-factor { double }?
+number-number-style =
+  element number:number-style {
+    common-data-style-attlist,
+    style-text-properties?,
+    number-text-with-fillchar?,
+    # https://issues.oasis-open.org/browse/OFFICE-3765
+    (any-number, number-text-with-fillchar?)?,
+    # https://issues.oasis-open.org/browse/OFFICE-3765
+    style-map*
   }
-number-era-attlist = attribute number:style { "short" | "long" }?
-number-day-of-week =
-  element number:day-of-week {
-    number-day-of-week-attlist, common-calendar-attlist, empty
+number-percentage-style =
+  element number:percentage-style {
+    common-data-style-attlist,
+    style-text-properties?,
+    number-text-with-fillchar?,
+    # https://issues.oasis-open.org/browse/OFFICE-3765
+    number-and-text?,
+    style-map*
   }
-number-day-of-week-attlist =
-  attribute number:style { "short" | "long" }?
-number-week-of-year =
-  element number:week-of-year { common-calendar-attlist, empty }
 number-quarter =
   element number:quarter {
     number-quarter-attlist, common-calendar-attlist, empty
   }
 number-quarter-attlist = attribute number:style { "short" | "long" }?
-number-time-style =
-  element number:time-style {
-    number-time-style-attlist,
-    common-data-style-attlist,
-    common-format-source-attlist,
-    style-text-properties?,
-    number-text?,
-    (any-time, number-text?)+,
-    style-map*
+number-scientific-number =
+  element number:scientific-number {
+    number-scientific-number-attlist,
+    common-decimal-places-attlist,
+    common-number-attlist,
+    empty
   }
-any-time = number-hours | number-am-pm | number-minutes | number-seconds
-number-time-style-attlist =
-  attribute number:truncate-on-overflow { boolean }?
-number-hours = element number:hours { number-hours-attlist, empty }
-number-hours-attlist = attribute number:style { "short" | "long" }?
-number-minutes =
-  element number:minutes { number-minutes-attlist, empty }
-number-minutes-attlist = attribute number:style { "short" | "long" }?
+number-scientific-number-attlist =
+  attribute number:min-exponent-digits { integer }?
+  & attribute number:exponent-interval { positiveInteger }?
+  & # https://issues.oasis-open.org/browse/OFFICE-1828 exponent-interval
+    attribute number:forced-exponent-sign { boolean }
+    # https://issues.oasis-open.org/browse/OFFICE-3860 added 
number:forced-exponent-sign
+    ?
 number-seconds =
   element number:seconds { number-seconds-attlist, empty }
 number-seconds-attlist =
   attribute number:style { "short" | "long" }?
   & attribute number:decimal-places { integer }?
-number-am-pm = element number:am-pm { empty }
-number-boolean-style =
-  element number:boolean-style {
+number-text = element number:text { text }
+number-text-content = element number:text-content { empty }
+number-text-style =
+  element number:text-style {
     common-data-style-attlist,
     style-text-properties?,
-    number-text?,
-    (number-boolean, number-text?)?,
+    number-text-with-fillchar?,
+    # https://issues.oasis-open.org/browse/OFFICE-3765
+    (number-text-content,
+     (number-text-with-fillchar?)
+     # https://issues.oasis-open.org/browse/OFFICE-3765
+     )*,
     style-map*
   }
-number-boolean = element number:boolean { empty }
-number-text-style =
-  element number:text-style {
+number-text-with-fillchar =
+  number-text?, (number-fill-character, number-text?)?
+# https://issues.oasis-open.org/browse/OFFICE-3765
+number-time-style =
+  element number:time-style {
+    number-time-style-attlist,
     common-data-style-attlist,
+    common-format-source-attlist,
     style-text-properties?,
-    number-text?,
-    (number-text-content, number-text?)*,
+    number-text-with-fillchar?,
+    # https://issues.oasis-open.org/browse/OFFICE-3765
+    (any-time,
+     (number-text-with-fillchar?)
+     # https://issues.oasis-open.org/browse/OFFICE-3765
+     )+,
     style-map*
   }
-number-text = element number:text { text }
-number-text-content = element number:text-content { empty }
-common-data-style-attlist =
-  attribute style:name { styleName }
-  & attribute style:display-name { \string }?
-  & attribute number:language { languageCode }?
-  & attribute number:country { countryCode }?
-  & attribute number:script { scriptCode }?
-  & attribute number:rfc-language-tag { language }?
-  & attribute number:title { \string }?
-  & attribute style:volatile { boolean }?
-  & attribute number:transliteration-format { \string }?
-  & attribute number:transliteration-language { countryCode }?
-  & attribute number:transliteration-country { countryCode }?
-  & attribute number:transliteration-style {
-      "short" | "medium" | "long"
-    }?
-common-auto-reorder-attlist =
-  attribute number:automatic-order { boolean }?
-common-format-source-attlist =
-  attribute number:format-source { "fixed" | "language" }?
-common-decimal-places-attlist =
-  attribute number:decimal-places { integer }?
-common-number-attlist =
-  attribute number:min-integer-digits { integer }?
-  & attribute number:grouping { boolean }?
-common-calendar-attlist =
-  attribute number:calendar {
-    "gregorian"
-    | "gengou"
-    | "ROC"
-    | "hanja_yoil"
-    | "hanja"
-    | "hijri"
-    | "jewish"
-    | "buddhist"
-    | \string
-  }?
-style-style-content =
-  (attribute style:family { "text" },
-   style-text-properties?)
-  | (attribute style:family { "paragraph" },
-     style-paragraph-properties?,
-     style-text-properties?)
-  | (attribute style:family { "section" },
-     style-section-properties?)
-  | (attribute style:family { "ruby" },
-     style-ruby-properties?)
-  | (attribute style:family { "table" },
-     style-table-properties?)
-  | (attribute style:family { "table-column" },
-     style-table-column-properties?)
-  | (attribute style:family { "table-row" },
-     style-table-row-properties?)
-  | (attribute style:family { "table-cell" },
-     style-table-cell-properties?,
-     style-paragraph-properties?,
-     style-text-properties?)
-  | (attribute style:family { "graphic" | "presentation" },
-     style-graphic-properties?,
-     style-paragraph-properties?,
-     style-text-properties?)
-  | (attribute style:family { "drawing-page" },
-     style-drawing-page-properties?)
-  | (attribute style:family { "chart" },
-     style-chart-properties?,
-     style-graphic-properties?,
-     style-paragraph-properties?,
-     style-text-properties?)
-text-linenumbering-configuration =
-  element text:linenumbering-configuration {
-    text-linenumbering-configuration-attlist,
-    text-linenumbering-separator?
+number-time-style-attlist =
+  attribute number:truncate-on-overflow { boolean }?
+number-week-of-year =
+  element number:week-of-year { common-calendar-attlist, empty }
+number-year =
+  element number:year {
+    number-year-attlist, common-calendar-attlist, empty
+  }
+number-year-attlist = attribute number:style { "short" | "long" }?
+office-annotation =
+  element office:annotation {
+    office-annotation-attlist,
+    draw-caption-attlist,
+    common-draw-position-attlist,
+    common-draw-size-attlist,
+    common-draw-shape-with-text-and-styles-attlist,
+    dc-creator?,
+    dc-date?,
+    meta-date-string?,
+    element meta:creator-initials { text }?,
+    # https://issues.oasis-open.org/browse/OFFICE-3776
+    (text-p | text-list)*
+  }
+office-annotation-attlist =
+  attribute office:display { boolean }?
+  & common-office-annotation-name-attlist?
+office-annotation-end =
+  element office:annotation-end { office-annotation-end-attlist }
+office-annotation-end-attlist = common-office-annotation-name-attlist
+office-automatic-styles =
+  element office:automatic-styles { styles & style-page-layout* }?
+office-binary-data = element office:binary-data { base64Binary }
+office-body = element office:body { office-body-content }
+office-body-content =
+  element office:text {
+    office-text-attlist,
+    office-text-content-prelude,
+    office-text-content-main,
+    office-text-content-epilogue
+  }
+  | element office:drawing {
+      office-drawing-attlist,
+      office-drawing-content-prelude,
+      office-drawing-content-main,
+      office-drawing-content-epilogue
+    }
+  | element office:presentation {
+      office-presentation-attlist,
+      office-presentation-content-prelude,
+      office-presentation-content-main,
+      office-presentation-content-epilogue
+    }
+  | element office:spreadsheet {
+      office-spreadsheet-attlist,
+      office-spreadsheet-content-prelude,
+      office-spreadsheet-content-main,
+      office-spreadsheet-content-epilogue
+    }
+  | element office:chart {
+      office-chart-attlist,
+      office-chart-content-prelude,
+      office-chart-content-main,
+      office-chart-content-epilogue
+    }
+  | element office:image {
+      office-image-attlist,
+      office-image-content-prelude,
+      office-image-content-main,
+      office-image-content-epilogue
+    }
+  | office-database
+office-change-info =
+  element office:change-info { dc-creator, dc-date, text-p* }
+office-chart-attlist = empty
+office-chart-content-epilogue = table-functions
+office-chart-content-main = chart-chart
+office-chart-content-prelude = text-decls, table-decls
+office-database =
+  element office:database {
+    db-data-source,
+    db-forms?,
+    db-reports?,
+    db-queries?,
+    db-table-presentations?,
+    db-schema-definition?
   }
-text-linenumbering-configuration-attlist =
-  attribute text:number-lines { boolean }?
-  & common-num-format-attlist?
-  & attribute text:style-name { styleNameRef }?
-  & attribute text:increment { nonNegativeInteger }?
-  & attribute text:number-position {
-      "left" | "right" | "inner" | "outer"
-    }?
-  & attribute text:offset { nonNegativeLength }?
-  & attribute text:count-empty-lines { boolean }?
-  & attribute text:count-in-text-boxes { boolean }?
-  & attribute text:restart-on-page { boolean }?
-text-linenumbering-separator =
-  element text:linenumbering-separator {
-    attribute text:increment { nonNegativeInteger }?,
-    text
+office-dde-source =
+  element office:dde-source {
+    office-dde-source-attlist, common-dde-connection-decl-attlist
   }
-text-notes-configuration =
-  element text:notes-configuration { text-notes-configuration-content }
-text-notes-configuration-content =
-  text-note-class
-  & attribute text:citation-style-name { styleNameRef }?
-  & attribute text:citation-body-style-name { styleNameRef }?
-  & attribute text:default-style-name { styleNameRef }?
-  & attribute text:master-page-name { styleNameRef }?
-  & attribute text:start-value { nonNegativeInteger }?
-  & common-num-format-prefix-suffix-attlist
-  & common-num-format-attlist?
-  & attribute text:start-numbering-at {
-      "document" | "chapter" | "page"
+office-dde-source-attlist =
+  attribute office:name { \string }?
+  & attribute office:conversion-mode {
+      "into-default-style-data-style"
+      | "into-english-number"
+      | "keep-text"
     }?
-  & attribute text:footnotes-position {
-      "text" | "page" | "section" | "document"
+office-document =
+  element office:document {
+    office-document-attrs,
+    office-document-common-attrs,
+    office-meta,
+    office-settings,
+    office-scripts,
+    office-font-face-decls,
+    office-styles,
+    office-automatic-styles,
+    office-master-styles,
+    office-body
+  }
+office-document-attrs = attribute office:mimetype { \string }
+office-document-common-attrs =
+  attribute office:version { "1.3" }
+  & attribute grddl:transformation {
+      list { anyIRI* }
     }?
-  & element text:note-continuation-notice-forward { text }?
-  & element text:note-continuation-notice-backward { text }?
-text-bibliography-configuration =
-  element text:bibliography-configuration {
-    text-bibliography-configuration-attlist, text-sort-key*
+office-document-content =
+  element office:document-content {
+    office-document-common-attrs,
+    office-scripts,
+    office-font-face-decls,
+    office-automatic-styles,
+    office-body
   }
-text-bibliography-configuration-attlist =
-  attribute text:prefix { \string }?
-  & attribute text:suffix { \string }?
-  & attribute text:numbered-entries { boolean }?
-  & attribute text:sort-by-position { boolean }?
-  & attribute fo:language { languageCode }?
-  & attribute fo:country { countryCode }?
-  & attribute fo:script { scriptCode }?
-  & attribute style:rfc-language-tag { language }?
-  & attribute text:sort-algorithm { \string }?
-text-sort-key = element text:sort-key { text-sort-key-attlist, empty }
-text-sort-key-attlist =
-  attribute text:key {
-    "address"
-    | "annote"
-    | "author"
-    | "bibliography-type"
-    | "booktitle"
-    | "chapter"
-    | "custom1"
-    | "custom2"
-    | "custom3"
-    | "custom4"
-    | "custom5"
-    | "edition"
-    | "editor"
-    | "howpublished"
-    | "identifier"
-    | "institution"
-    | "isbn"
-    | "issn"
-    | "journal"
-    | "month"
-    | "note"
-    | "number"
-    | "organizations"
-    | "pages"
-    | "publisher"
-    | "report-type"
-    | "school"
-    | "series"
-    | "title"
-    | "url"
-    | "volume"
-    | "year"
-  },
-  attribute text:sort-ascending { boolean }?
-text-list-style =
-  element text:list-style {
-    text-list-style-attr, text-list-style-content*
+office-document-meta =
+  element office:document-meta {
+    office-document-common-attrs, office-meta
   }
-text-list-style-attr =
-  attribute style:name { styleName }
-  & attribute style:display-name { \string }?
-  & attribute text:consecutive-numbering { boolean }?
-text-list-style-content =
-  element text:list-level-style-number {
-    text-list-level-style-attr,
-    text-list-level-style-number-attr,
-    style-list-level-properties?,
-    style-text-properties?
+office-document-settings =
+  element office:document-settings {
+    office-document-common-attrs, office-settings
+  }
+office-document-styles =
+  element office:document-styles {
+    office-document-common-attrs,
+    office-font-face-decls,
+    office-styles,
+    office-automatic-styles,
+    office-master-styles
+  }
+office-drawing-attlist = empty
+office-drawing-content-epilogue = table-functions
+office-drawing-content-main = draw-page*
+office-drawing-content-prelude = text-decls, table-decls
+office-event-listeners =
+  element office:event-listeners {
+    (script-event-listener | presentation-event-listener)*
+  }
+office-font-face-decls =
+  element office:font-face-decls { style-font-face* }?
+office-forms =
+  element office:forms {
+    office-forms-attlist, (form-form | xforms-model)*
+  }?
+office-forms-attlist =
+  attribute form:automatic-focus { boolean }?
+  & attribute form:apply-design-mode { boolean }?
+office-image-attlist = empty
+office-image-content-epilogue = empty
+office-image-content-main = draw-frame
+office-image-content-prelude = empty
+office-master-styles =
+  element office:master-styles {
+    style-master-page* & style-handout-master? & draw-layer-set?
+  }?
+office-meta = element office:meta { office-meta-content-strict }?
+office-meta-content-strict = office-meta-data*
+office-meta-data =
+  element meta:generator { \string }
+  | element dc:title { \string }
+  | element dc:description { \string }
+  | element dc:subject { \string }
+  | element meta:keyword { \string }
+  | element meta:initial-creator { \string }
+  | dc-creator
+  | element meta:printed-by { \string }
+  | element meta:creation-date { dateTime }
+  | dc-date
+  | element meta:print-date { dateTime }
+  | element meta:template {
+      attribute xlink:type { "simple" },
+      attribute xlink:href { anyIRI },
+      attribute xlink:actuate { "onRequest" }?,
+      attribute xlink:title { \string }?,
+      attribute meta:date { dateTime }?
+    }
+  | element meta:auto-reload {
+      (attribute xlink:type { "simple" },
+       attribute xlink:href { anyIRI },
+       attribute xlink:show { "replace" }?,
+       attribute xlink:actuate { "onLoad" }?)?,
+      attribute meta:delay { duration }?
+    }
+  | element meta:hyperlink-behaviour {
+      attribute office:target-frame-name { targetFrameName }?,
+      attribute xlink:show { "new" | "replace" }?
+    }
+  | element dc:language { language }
+  | element meta:editing-cycles { nonNegativeInteger }
+  | element meta:editing-duration { duration }
+  | element meta:document-statistic {
+      attribute meta:page-count { nonNegativeInteger }?,
+      attribute meta:table-count { nonNegativeInteger }?,
+      attribute meta:draw-count { nonNegativeInteger }?,
+      attribute meta:image-count { nonNegativeInteger }?,
+      attribute meta:ole-object-count { nonNegativeInteger }?,
+      attribute meta:object-count { nonNegativeInteger }?,
+      attribute meta:paragraph-count { nonNegativeInteger }?,
+      attribute meta:word-count { nonNegativeInteger }?,
+      attribute meta:character-count { nonNegativeInteger }?,
+      attribute meta:frame-count { nonNegativeInteger }?,
+      attribute meta:sentence-count { nonNegativeInteger }?,
+      attribute meta:syllable-count { nonNegativeInteger }?,
+      attribute meta:non-whitespace-character-count {
+        nonNegativeInteger
+      }?,
+      attribute meta:row-count { nonNegativeInteger }?,
+      attribute meta:cell-count { nonNegativeInteger }?
+    }
+  | element meta:user-defined {
+      attribute meta:name { \string },
+      ((attribute meta:value-type { "float" },
+        double)
+       | (attribute meta:value-type { "date" },
+          dateOrDateTime)
+       | (attribute meta:value-type { "time" },
+          duration)
+       | (attribute meta:value-type { "boolean" },
+          boolean)
+       | (attribute meta:value-type { "string" },
+          \string)
+       | text)
+    }
+office-presentation-attlist = empty
+office-presentation-content-epilogue =
+  presentation-settings, table-functions
+office-presentation-content-main = draw-page*
+office-presentation-content-prelude =
+  text-decls, table-decls, presentation-decls
+# removed from text as well
+# <rng:define name="office-process-content">
+#   <rng:optional>
+#     <rng:attribute name="office:process-content">
+#       <rng:ref name="boolean"/>
+#     </rng:attribute>
+#   </rng:optional>
+# </rng:define>
+office-script =
+  element office:script {
+    office-script-attlist,
+    mixed { anyElements }
   }
-  | element text:list-level-style-bullet {
-      text-list-level-style-attr,
-      text-list-level-style-bullet-attr,
-      style-list-level-properties?,
-      style-text-properties?
+office-script-attlist = attribute script:language { \string }
+office-scripts =
+  element office:scripts { office-script*, office-event-listeners? }?
+office-settings = element office:settings { config-config-item-set+ }?
+office-spreadsheet-attlist =
+  attribute table:structure-protected { boolean }?,
+  attribute table:protection-key { \string }?,
+  attribute table:protection-key-digest-algorithm { anyIRI }?
+office-spreadsheet-content-epilogue = table-functions
+office-spreadsheet-content-main = table-table*
+office-spreadsheet-content-prelude =
+  table-tracked-changes?, text-decls, table-decls
+office-styles =
+  element office:styles {
+    styles
+    & style-default-style*
+    & style-default-page-layout?
+    & text-outline-style?
+    & text-notes-configuration*
+    & text-bibliography-configuration?
+    & text-linenumbering-configuration?
+    & draw-gradient*
+    & svg-linearGradient*
+    & svg-radialGradient*
+    & draw-hatch*
+    & draw-fill-image*
+    & draw-marker*
+    & draw-stroke-dash*
+    & draw-opacity*
+    & style-presentation-page-layout*
+    & table-table-template*
+  }?
+office-text-attlist =
+  attribute text:global { boolean }?
+  & attribute text:use-soft-page-breaks { boolean }?
+office-text-content-epilogue = table-functions
+office-text-content-main =
+  text-content*
+  | (text-page-sequence, (shape)*)
+office-text-content-prelude =
+  office-forms, text-tracked-changes, text-decls, table-decls
+paragraph-attrs =
+  attribute text:style-name { styleNameRef }?
+  & attribute text:class-names { styleNameRefs }?
+  & attribute text:cond-style-name { styleNameRef }?
+  & (xml-id,
+     attribute text:id { NCName }?)?
+  & common-in-content-meta-attlist?
+paragraph-content =
+  text
+  | element text:s {
+      attribute text:c { nonNegativeInteger }?
+    }
+  | element text:tab { text-tab-attr }
+  | element text:line-break { empty }
+  | text-soft-page-break
+  | element text:span {
+      attribute text:style-name { styleNameRef }?,
+      attribute text:class-names { styleNameRefs }?,
+      paragraph-content-or-hyperlink*
+    }
+  | element text:meta {
+      text-meta-attlist, paragraph-content-or-hyperlink*
+    }
+  | (text-bookmark | text-bookmark-start | text-bookmark-end)
+  | element text:reference-mark {
+      attribute text:name { \string }
+    }
+  | (element text:reference-mark-start {
+       attribute text:name { \string }
+     }
+     | element text:reference-mark-end {
+         attribute text:name { \string }
+       })
+  | element text:note {
+      text-note-class,
+      attribute text:id { \string }?,
+      element text:note-citation {
+        attribute text:label { \string }?,
+        text
+      },
+      element text:note-body { text-content* }
+    }
+  | element text:ruby {
+      attribute text:style-name { styleNameRef }?,
+      element text:ruby-base { paragraph-content-or-hyperlink* },
+      element text:ruby-text {
+        attribute text:style-name { styleNameRef }?,
+        text
+      }
+    }
+  | (office-annotation | office-annotation-end)
+  | change-marks
+  | shape
+  | element text:date { text-date-attlist, text }
+  | element text:time { text-time-attlist, text }
+  | element text:page-number { text-page-number-attlist, text }
+  | element text:page-continuation {
+      text-page-continuation-attlist, text
+    }
+  | element text:sender-firstname { common-field-fixed-attlist, text }
+  | element text:sender-lastname { common-field-fixed-attlist, text }
+  | element text:sender-initials { common-field-fixed-attlist, text }
+  | element text:sender-title { common-field-fixed-attlist, text }
+  | element text:sender-position { common-field-fixed-attlist, text }
+  | element text:sender-email { common-field-fixed-attlist, text }
+  | element text:sender-phone-private {
+      common-field-fixed-attlist, text
+    }
+  | element text:sender-fax { common-field-fixed-attlist, text }
+  | element text:sender-company { common-field-fixed-attlist, text }
+  | element text:sender-phone-work { common-field-fixed-attlist, text }
+  | element text:sender-street { common-field-fixed-attlist, text }
+  | element text:sender-city { common-field-fixed-attlist, text }
+  | element text:sender-postal-code { common-field-fixed-attlist, text }
+  | element text:sender-country { common-field-fixed-attlist, text }
+  | element text:sender-state-or-province {
+      common-field-fixed-attlist, text
+    }
+  | element text:author-name { common-field-fixed-attlist, text }
+  | element text:author-initials { common-field-fixed-attlist, text }
+  | element text:chapter { text-chapter-attlist, text }
+  | element text:file-name { text-file-name-attlist, text }
+  | element text:template-name { text-template-name-attlist, text }
+  | element text:sheet-name { text }
+  | element text:variable-set {
+      (common-field-name-attlist
+       & common-field-formula-attlist
+       & common-value-and-type-attlist
+       & common-field-display-value-none-attlist
+       & common-field-data-style-name-attlist),
+      text
+    }
+  | element text:variable-get {
+      (common-field-name-attlist
+       & common-field-display-value-formula-attlist
+       & common-field-data-style-name-attlist),
+      text
+    }
+  | element text:variable-input {
+      (common-field-name-attlist
+       & common-field-description-attlist
+       & common-value-type-attlist
+       & common-field-display-value-none-attlist
+       & common-field-data-style-name-attlist),
+      text
+    }
+  | element text:user-field-get {
+      (common-field-name-attlist
+       & common-field-display-value-formula-none-attlist
+       & common-field-data-style-name-attlist),
+      text
+    }
+  | element text:user-field-input {
+      (common-field-name-attlist
+       & common-field-description-attlist
+       & common-field-data-style-name-attlist),
+      text
+    }
+  | element text:sequence {
+      (common-field-name-attlist
+       & common-field-formula-attlist
+       & common-field-num-format-attlist
+       & text-sequence-ref-name),
+      text
+    }
+  | element text:expression {
+      (common-field-formula-attlist
+       & common-value-and-type-attlist?
+       & common-field-display-value-formula-attlist
+       & common-field-data-style-name-attlist),
+      text
+    }
+  | element text:text-input { common-field-description-attlist, text }
+  | text-drop-down
+  | # OFFICE-3881
+    element text:initial-creator { common-field-fixed-attlist, text }
+  | element text:creation-date {
+      (common-field-fixed-attlist
+       & common-field-data-style-name-attlist
+       & attribute text:date-value { dateOrDateTime }?),
+      text
+    }
+  | element text:creation-time {
+      (common-field-fixed-attlist
+       & common-field-data-style-name-attlist
+       & attribute text:time-value { timeOrDateTime }?),
+      text
+    }
+  | element text:description { common-field-fixed-attlist, text }
+  | element text:user-defined {
+      (common-field-fixed-attlist
+       & attribute text:name { \string }
+       & common-field-data-style-name-attlist
+       & attribute office:value { double }?
+       & attribute office:date-value { dateOrDateTime }?
+       & attribute office:time-value { duration }?
+       & attribute office:boolean-value { boolean }?
+       & attribute office:string-value { \string }?),
+      text
+    }
+  | element text:print-time {
+      (common-field-fixed-attlist
+       & common-field-data-style-name-attlist
+       & attribute text:time-value { time }?),
+      text
+    }
+  | element text:print-date {
+      (common-field-fixed-attlist
+       & common-field-data-style-name-attlist
+       & attribute text:date-value { date }?),
+      text
+    }
+  | element text:printed-by { common-field-fixed-attlist, text }
+  | element text:title { common-field-fixed-attlist, text }
+  | element text:subject { common-field-fixed-attlist, text }
+  | element text:keywords { common-field-fixed-attlist, text }
+  | element text:editing-cycles { common-field-fixed-attlist, text }
+  | element text:editing-duration {
+      (common-field-fixed-attlist
+       & common-field-data-style-name-attlist
+       & attribute text:duration { duration }?),
+      text
+    }
+  | element text:modification-time {
+      (common-field-fixed-attlist
+       & common-field-data-style-name-attlist
+       & attribute text:time-value { time }?),
+      text
+    }
+  | element text:modification-date {
+      (common-field-fixed-attlist
+       & common-field-data-style-name-attlist
+       & attribute text:date-value { date }?),
+      text
+    }
+  | element text:creator { common-field-fixed-attlist, text }
+  | element text:page-count
+            | text:paragraph-count
+            | text:word-count
+            | text:character-count
+            | text:table-count
+            | text:image-count
+            | text:object-count {
+      common-field-num-format-attlist, text
     }
-  | element text:list-level-style-image {
-      text-list-level-style-attr,
-      text-list-level-style-image-attr,
-      style-list-level-properties?
+  | element text:database-display {
+      text-database-display-attlist, text
     }
-text-list-level-style-number-attr =
-  attribute text:style-name { styleNameRef }?
-  & common-num-format-attlist
-  & common-num-format-prefix-suffix-attlist
-  & attribute text:display-levels { positiveInteger }?
-  & attribute text:start-value { positiveInteger }?
-text-list-level-style-bullet-attr =
-  attribute text:style-name { styleNameRef }?
-  & attribute text:bullet-char { character }
-  & common-num-format-prefix-suffix-attlist
-  & attribute text:bullet-relative-size { percent }?
-text-list-level-style-image-attr =
-  common-draw-data-attlist | office-binary-data
-text-list-level-style-attr = attribute text:level { positiveInteger }
-text-outline-style =
-  element text:outline-style {
-    text-outline-style-attr, text-outline-level-style+
-  }
-text-outline-style-attr = attribute style:name { styleName }
-text-outline-level-style =
-  element text:outline-level-style {
-    text-outline-level-style-attlist,
-    style-list-level-properties?,
-    style-text-properties?
-  }
-text-outline-level-style-attlist =
-  attribute text:level { positiveInteger }
-  & attribute text:style-name { styleNameRef }?
-  & common-num-format-attlist
-  & common-num-format-prefix-suffix-attlist
-  & attribute text:display-levels { positiveInteger }?
-  & attribute text:start-value { positiveInteger }?
-style-graphic-properties =
-  element style:graphic-properties {
-    style-graphic-properties-content-strict
-  }
-style-graphic-properties-content-strict =
-  style-graphic-properties-attlist,
-  style-graphic-fill-properties-attlist,
-  style-graphic-properties-elements
-style-drawing-page-properties =
-  element style:drawing-page-properties {
-    style-drawing-page-properties-content-strict
-  }
-style-drawing-page-properties-content-strict =
-  style-graphic-fill-properties-attlist,
-  style-drawing-page-properties-attlist,
-  style-drawing-page-properties-elements
-draw-gradient =
-  element draw:gradient {
-    common-draw-gradient-attlist, draw-gradient-attlist, empty
-  }
-common-draw-gradient-attlist =
-  attribute draw:name { styleName }?
-  & attribute draw:display-name { \string }?
-  & attribute draw:style { gradient-style }
-  & attribute draw:cx { percent }?
-  & attribute draw:cy { percent }?
-  & attribute draw:angle { angle }?
-  & attribute draw:border { percent }?
-gradient-style =
-  "linear" | "axial" | "radial" | "ellipsoid" | "square" | "rectangular"
-draw-gradient-attlist =
-  attribute draw:start-color { color }?
-  & attribute draw:end-color { color }?
-  & attribute draw:start-intensity { zeroToHundredPercent }?
-  & attribute draw:end-intensity { zeroToHundredPercent }?
-svg-linearGradient =
-  element svg:linearGradient {
-    common-svg-gradient-attlist,
-    attribute svg:x1 { coordinate | percent }?,
-    attribute svg:y1 { coordinate | percent }?,
-    attribute svg:x2 { coordinate | percent }?,
-    attribute svg:y2 { coordinate | percent }?,
-    svg-stop*
-  }
-svg-radialGradient =
-  element svg:radialGradient {
-    common-svg-gradient-attlist,
-    attribute svg:cx { coordinate | percent }?,
-    attribute svg:cy { coordinate | percent }?,
-    attribute svg:r { coordinate | percent }?,
-    attribute svg:fx { coordinate | percent }?,
-    attribute svg:fy { coordinate | percent }?,
-    svg-stop*
-  }
-svg-stop =
-  element svg:stop {
-    attribute svg:offset { double | percent },
-    attribute svg:stop-color { color }?,
-    attribute svg:stop-opacity { double }?
-  }
-common-svg-gradient-attlist =
-  attribute svg:gradientUnits { "objectBoundingBox" }?
-  & attribute svg:gradientTransform { \string }?
-  & attribute svg:spreadMethod { "pad" | "reflect" | "repeat" }?
-  & attribute draw:name { styleName }
-  & attribute draw:display-name { \string }?
-draw-hatch = element draw:hatch { draw-hatch-attlist, empty }
-draw-hatch-attlist =
-  attribute draw:name { styleName }
-  & attribute draw:display-name { \string }?
-  & attribute draw:style { "single" | "double" | "triple" }
-  & attribute draw:color { color }?
-  & attribute draw:distance { length }?
-  & attribute draw:rotation { angle }?
-draw-fill-image =
-  element draw:fill-image {
-    draw-fill-image-attlist,
-    attribute xlink:type { "simple" },
-    attribute xlink:href { anyIRI },
-    attribute xlink:show { "embed" }?,
-    attribute xlink:actuate { "onLoad" }?,
-    empty
-  }
-draw-fill-image-attlist =
-  attribute draw:name { styleName }
-  & attribute draw:display-name { \string }?
-  & attribute svg:width { length }?
-  & attribute svg:height { length }?
-draw-opacity =
-  element draw:opacity {
-    common-draw-gradient-attlist, draw-opacity-attlist, empty
-  }
-draw-opacity-attlist =
-  attribute draw:start { zeroToHundredPercent }?,
-  attribute draw:end { zeroToHundredPercent }?
-draw-marker =
-  element draw:marker {
-    draw-marker-attlist,
-    common-draw-viewbox-attlist,
-    common-draw-path-data-attlist,
-    empty
-  }
-draw-marker-attlist =
-  attribute draw:name { styleName }
-  & attribute draw:display-name { \string }?
-draw-stroke-dash =
-  element draw:stroke-dash { draw-stroke-dash-attlist, empty }
-draw-stroke-dash-attlist =
-  attribute draw:name { styleName }
-  & attribute draw:display-name { \string }?
-  & attribute draw:style { "rect" | "round" }?
-  & attribute draw:dots1 { integer }?
-  & attribute draw:dots1-length { length | percent }?
-  & attribute draw:dots2 { integer }?
-  & attribute draw:dots2-length { length | percent }?
-  & attribute draw:distance { length | percent }?
-style-presentation-page-layout =
-  element style:presentation-page-layout {
-    attribute style:name { styleName },
-    attribute style:display-name { \string }?,
-    presentation-placeholder*
+  | element text:database-next { text-database-next-attlist }
+  | element text:database-row-select {
+      text-database-row-select-attlist
+    }
+  | element text:database-row-number {
+      (common-field-database-table
+       & common-field-num-format-attlist
+       & attribute text:value { nonNegativeInteger }?),
+      text
+    }
+  | element text:database-name { common-field-database-table, text }
+  | element text:page-variable-set {
+      text-set-page-variable-attlist, text
+    }
+  | element text:page-variable-get {
+      text-get-page-variable-attlist, text
+    }
+  | element text:placeholder { text-placeholder-attlist, text }
+  | element text:conditional-text {
+      text-conditional-text-attlist, text
+    }
+  | element text:hidden-text { text-hidden-text-attlist, text }
+  | element text:reference-ref | text:bookmark-ref {
+      text-common-ref-content & text-bookmark-ref-content
+    }
+  | element text:note-ref {
+      text-common-ref-content & text-note-ref-content
+    }
+  | element text:sequence-ref {
+      text-common-ref-content & text-sequence-ref-content
+    }
+  | element text:script {
+      ((attribute xlink:type { "simple" },
+        attribute xlink:href { anyIRI })
+       | text)
+      & attribute script:language { \string }?
+    }
+  | element text:execute-macro {
+      attribute text:name { \string }?,
+      office-event-listeners?,
+      text
+    }
+  | element text:hidden-paragraph {
+      text-hidden-paragraph-attlist, text
+    }
+  | element text:dde-connection {
+      attribute text:connection-name { \string },
+      text
+    }
+  | element text:measure {
+      attribute text:kind { "value" | "unit" | "gap" },
+      text
+    }
+  | element text:table-formula {
+      (common-field-formula-attlist
+       & common-field-display-value-formula-attlist
+       & common-field-data-style-name-attlist),
+      text
+    }
+  | element text:meta-field {
+      text-meta-field-attlist, paragraph-content-or-hyperlink*
+    }
+  | element text:toc-mark-start { text-toc-mark-start-attrs }
+  | element text:toc-mark-end { text-id }
+  | element text:toc-mark {
+      attribute text:string-value { \string },
+      text-outline-level
+    }
+  | element text:user-index-mark-start {
+      text-id, text-outline-level, text-index-name
+    }
+  | element text:user-index-mark-end { text-id }
+  | element text:user-index-mark {
+      attribute text:string-value { \string },
+      text-outline-level,
+      text-index-name
+    }
+  | element text:alphabetical-index-mark-start {
+      text-id, text-alphabetical-index-mark-attrs
+    }
+  | element text:alphabetical-index-mark-end { text-id }
+  | element text:alphabetical-index-mark {
+      attribute text:string-value { \string },
+      text-alphabetical-index-mark-attrs
+    }
+  | element text:bibliography-mark {
+      attribute text:bibliography-type { text-bibliography-types },
+      attribute text:identifier
+                | text:address
+                | text:annote
+                | text:author
+                | text:booktitle
+                | text:chapter
+                | text:edition
+                | text:editor
+                | text:howpublished
+                | text:institution
+                | text:journal
+                | text:month
+                | text:note
+                | text:number
+                | text:organizations
+                | text:pages
+                | text:publisher
+                | text:school
+                | text:series
+                | text:title
+                | text:report-type
+                | text:volume
+                | text:year
+                | text:url
+                | text:custom1
+                | text:custom2
+                | text:custom3
+                | text:custom4
+                | text:custom5
+                | text:isbn
+                | text:issn { \string }*,
+      text
+    }
+  | element presentation:header { empty }
+  | element presentation:footer { empty }
+  | element presentation:date-time { empty }
+paragraph-content-or-hyperlink = paragraph-content | text-a
+pathData = xsd:string
+percent = xsd:string { pattern = "-?([0-9]+(\.[0-9]*)?|\.[0-9]+)%" }
+point3D =
+  xsd:string {
+    pattern =
+      "\([ ]*-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc))([ 
]+-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc))){2}[ ]*\)"
   }
-presentation-placeholder =
-  element presentation:placeholder {
-    attribute presentation:object { presentation-classes },
-    attribute svg:x { coordinate | percent },
-    attribute svg:y { coordinate | percent },
-    attribute svg:width { length | percent },
-    attribute svg:height { length | percent },
-    empty
+points =
+  xsd:string { pattern = "-?[0-9]+,-?[0-9]+([ ]+-?[0-9]+,-?[0-9]+)*" }
+positiveInteger = xsd:positiveInteger
+positiveLength =
+  xsd:string {
+    pattern =
+      
"([0-9]*[1-9][0-9]*(\.[0-9]*)?|0+\.[0-9]*[1-9][0-9]*|\.[0-9]*[1-9][0-9]*)((cm)|(mm)|(in)|(pt)|(pc)|(px))"
   }
-style-page-layout-properties =
-  element style:page-layout-properties {
-    style-page-layout-properties-content-strict
+presentation-animation-elements =
+  presentation-show-shape
+  | presentation-show-text
+  | presentation-hide-shape
+  | presentation-hide-text
+  | presentation-dim
+  | presentation-play
+presentation-animation-group =
+  element presentation:animation-group {
+    presentation-animation-elements*
   }
-style-page-layout-properties-content-strict =
-  style-page-layout-properties-attlist,
-  style-page-layout-properties-elements
-style-page-layout-properties-attlist =
-  attribute fo:page-width { length }?
-  & attribute fo:page-height { length }?
-  & common-num-format-attlist?
-  & common-num-format-prefix-suffix-attlist
-  & attribute style:paper-tray-name { "default" | \string }?
-  & attribute style:print-orientation { "portrait" | "landscape" }?
-  & common-horizontal-margin-attlist
-  & common-vertical-margin-attlist
-  & common-margin-attlist
-  & common-border-attlist
-  & common-border-line-width-attlist
-  & common-padding-attlist
-  & common-shadow-attlist
-  & common-background-color-attlist
-  & attribute style:register-truth-ref-style-name { styleNameRef }?
-  & attribute style:print {
-      list {
-        ("headers"
-         | "grid"
-         | "annotations"
-         | "objects"
-         | "charts"
-         | "drawings"
-         | "formulas"
-         | "zero-values")*
-      }
-    }?
-  & attribute style:print-page-order { "ttb" | "ltr" }?
-  & attribute style:first-page-number { positiveInteger | "continue" }?
-  & attribute style:scale-to { percent }?
-  & attribute style:scale-to-pages { positiveInteger }?
-  & attribute style:table-centering {
-      "horizontal" | "vertical" | "both" | "none"
-    }?
-  & attribute style:footnote-max-height { length }?
-  & common-writing-mode-attlist
-  & attribute style:layout-grid-mode { "none" | "line" | "both" }?
-  & attribute style:layout-grid-standard-mode { boolean }?
-  & attribute style:layout-grid-base-height { length }?
-  & attribute style:layout-grid-ruby-height { length }?
-  & attribute style:layout-grid-lines { positiveInteger }?
-  & attribute style:layout-grid-base-width { length }?
-  & attribute style:layout-grid-color { color }?
-  & attribute style:layout-grid-ruby-below { boolean }?
-  & attribute style:layout-grid-print { boolean }?
-  & attribute style:layout-grid-display { boolean }?
-  & attribute style:layout-grid-snap-to { boolean }?
-style-page-layout-properties-elements =
-  style-background-image & style-columns & style-footnote-sep
-style-footnote-sep =
-  element style:footnote-sep { style-footnote-sep-attlist, empty }?
-style-footnote-sep-attlist =
-  attribute style:width { length }?,
-  attribute style:rel-width { percent }?,
-  attribute style:color { color }?,
-  attribute style:line-style { lineStyle }?,
-  attribute style:adjustment { "left" | "center" | "right" }?,
-  attribute style:distance-before-sep { length }?,
-  attribute style:distance-after-sep { length }?
-style-header-footer-properties =
-  element style:header-footer-properties {
-    style-header-footer-properties-content-strict
+presentation-animations =
+  element presentation:animations {
+    (presentation-animation-elements | presentation-animation-group)*
   }
-style-header-footer-properties-content-strict =
-  style-header-footer-properties-attlist,
-  style-header-footer-properties-elements
-style-header-footer-properties-attlist =
-  attribute svg:height { length }?
-  & attribute fo:min-height { length }?
-  & common-horizontal-margin-attlist
-  & common-vertical-margin-attlist
-  & common-margin-attlist
-  & common-border-attlist
-  & common-border-line-width-attlist
-  & common-padding-attlist
-  & common-background-color-attlist
-  & common-shadow-attlist
-  & attribute style:dynamic-spacing { boolean }?
-style-header-footer-properties-elements = style-background-image
-style-text-properties =
-  element style:text-properties { style-text-properties-content-strict }
-style-text-properties-content-strict =
-  style-text-properties-attlist, style-text-properties-elements
-style-text-properties-elements = empty
-style-text-properties-attlist =
-  attribute fo:font-variant { fontVariant }?
-  & attribute fo:text-transform {
-      "none" | "lowercase" | "uppercase" | "capitalize"
-    }?
-  & attribute fo:color { color }?
-  & attribute style:use-window-font-color { boolean }?
-  & attribute style:text-outline { boolean }?
-  & attribute style:text-line-through-type { lineType }?
-  & attribute style:text-line-through-style { lineStyle }?
-  & attribute style:text-line-through-width { lineWidth }?
-  & attribute style:text-line-through-color { "font-color" | color }?
-  & attribute style:text-line-through-text { \string }?
-  & attribute style:text-line-through-text-style { styleNameRef }?
-  & attribute style:text-position {
-      list { (percent | "super" | "sub"), percent? }
-    }?
-  & attribute style:font-name { \string }?
-  & attribute style:font-name-asian { \string }?
-  & attribute style:font-name-complex { \string }?
-  & attribute fo:font-family { \string }?
-  & attribute style:font-family-asian { \string }?
-  & attribute style:font-family-complex { \string }?
-  & attribute style:font-family-generic { fontFamilyGeneric }?
-  & attribute style:font-family-generic-asian { fontFamilyGeneric }?
-  & attribute style:font-family-generic-complex { fontFamilyGeneric }?
-  & attribute style:font-style-name { \string }?
-  & attribute style:font-style-name-asian { \string }?
-  & attribute style:font-style-name-complex { \string }?
-  & attribute style:font-pitch { fontPitch }?
-  & attribute style:font-pitch-asian { fontPitch }?
-  & attribute style:font-pitch-complex { fontPitch }?
-  & attribute style:font-charset { textEncoding }?
-  & attribute style:font-charset-asian { textEncoding }?
-  & attribute style:font-charset-complex { textEncoding }?
-  & attribute fo:font-size { positiveLength | percent }?
-  & attribute style:font-size-asian { positiveLength | percent }?
-  & attribute style:font-size-complex { positiveLength | percent }?
-  & attribute style:font-size-rel { length }?
-  & attribute style:font-size-rel-asian { length }?
-  & attribute style:font-size-rel-complex { length }?
-  & attribute style:script-type {
-      "latin" | "asian" | "complex" | "ignore"
-    }?
-  & attribute fo:letter-spacing { length | "normal" }?
-  & attribute fo:language { languageCode }?
-  & attribute style:language-asian { languageCode }?
-  & attribute style:language-complex { languageCode }?
-  & attribute fo:country { countryCode }?
-  & attribute style:country-asian { countryCode }?
-  & attribute style:country-complex { countryCode }?
-  & attribute fo:script { scriptCode }?
-  & attribute style:script-asian { scriptCode }?
-  & attribute style:script-complex { scriptCode }?
-  & attribute style:rfc-language-tag { language }?
-  & attribute style:rfc-language-tag-asian { language }?
-  & attribute style:rfc-language-tag-complex { language }?
-  & attribute fo:font-style { fontStyle }?
-  & attribute style:font-style-asian { fontStyle }?
-  & attribute style:font-style-complex { fontStyle }?
-  & attribute style:font-relief { "none" | "embossed" | "engraved" }?
-  & attribute fo:text-shadow { shadowType }?
-  & attribute style:text-underline-type { lineType }?
-  & attribute style:text-underline-style { lineStyle }?
-  & attribute style:text-underline-width { lineWidth }?
-  & attribute style:text-underline-color { "font-color" | color }?
-  & attribute style:text-overline-type { lineType }?
-  & attribute style:text-overline-style { lineStyle }?
-  & attribute style:text-overline-width { lineWidth }?
-  & attribute style:text-overline-color { "font-color" | color }?
-  & attribute style:text-overline-mode { lineMode }?
-  & attribute fo:font-weight { fontWeight }?
-  & attribute style:font-weight-asian { fontWeight }?
-  & attribute style:font-weight-complex { fontWeight }?
-  & attribute style:text-underline-mode { lineMode }?
-  & attribute style:text-line-through-mode { lineMode }?
-  & attribute style:letter-kerning { boolean }?
-  & attribute style:text-blinking { boolean }?
-  & common-background-color-attlist
-  & attribute style:text-combine { "none" | "letters" | "lines" }?
-  & attribute style:text-combine-start-char { character }?
-  & attribute style:text-combine-end-char { character }?
-  & attribute style:text-emphasize {
+presentation-classes =
+  "title"
+  | "outline"
+  | "subtitle"
+  | "text"
+  | "graphic"
+  | "object"
+  | "chart"
+  | "table"
+  | "orgchart"
+  | "page"
+  | "notes"
+  | "handout"
+  | "header"
+  | "footer"
+  | "date-time"
+  | "page-number"
+presentation-date-time-decl-attlist =
+  attribute presentation:name { \string }
+  & attribute presentation:source { "fixed" | "current-date" }
+  & attribute style:data-style-name { styleNameRef }?
+presentation-decl =
+  element presentation:header-decl {
+    presentation-header-decl-attlist, text
+  }
+  | element presentation:footer-decl {
+      presentation-footer-decl-attlist, text
+    }
+  | element presentation:date-time-decl {
+      presentation-date-time-decl-attlist, text
+    }
+presentation-decls = presentation-decl*
+presentation-dim =
+  element presentation:dim {
+    presentation-dim-attlist, presentation-sound?
+  }
+presentation-dim-attlist =
+  attribute draw:shape-id { IDREF }
+  & attribute draw:color { color }
+presentation-event-listener =
+  element presentation:event-listener {
+    presentation-event-listener-attlist, presentation-sound?
+  }
+presentation-event-listener-attlist =
+  attribute script:event-name { \string }
+  & attribute presentation:action {
       "none"
-      | list {
-          ("none" | "accent" | "dot" | "circle" | "disc"),
-          ("above" | "below")
-        }
+      | "previous-page"
+      | "next-page"
+      | "first-page"
+      | "last-page"
+      | "hide"
+      | "stop"
+      | "execute"
+      | "show"
+      | "verb"
+      | "fade-out"
+      | "sound"
+      | "last-visited-page"
+    }
+  & attribute presentation:effect { presentationEffects }?
+  & attribute presentation:direction { presentationEffectDirections }?
+  & attribute presentation:speed { presentationSpeeds }?
+  & attribute presentation:start-scale { percent }?
+  & (attribute xlink:type { "simple" },
+     attribute xlink:href { anyIRI },
+     attribute xlink:show { "embed" }?,
+     attribute xlink:actuate { "onRequest" }?)?
+  & attribute presentation:verb { nonNegativeInteger }?
+presentation-footer-decl-attlist =
+  attribute presentation:name { \string }
+presentation-header-decl-attlist =
+  attribute presentation:name { \string }
+presentation-hide-shape =
+  element presentation:hide-shape {
+    common-presentation-effect-attlist, presentation-sound?
+  }
+presentation-hide-text =
+  element presentation:hide-text {
+    common-presentation-effect-attlist, presentation-sound?
+  }
+presentation-notes =
+  element presentation:notes {
+    common-presentation-header-footer-attlist,
+    presentation-notes-attlist,
+    office-forms,
+    shape*
+  }
+presentation-notes-attlist =
+  attribute style:page-layout-name { styleNameRef }?
+  & attribute draw:style-name { styleNameRef }?
+presentation-placeholder =
+  element presentation:placeholder {
+    attribute presentation:object { presentation-classes },
+    attribute svg:x { coordinate | percent },
+    attribute svg:y { coordinate | percent },
+    attribute svg:width { length | percent },
+    attribute svg:height { length | percent },
+    empty
+  }
+presentation-play =
+  element presentation:play { presentation-play-attlist, empty }
+presentation-play-attlist =
+  attribute draw:shape-id { IDREF },
+  attribute presentation:speed { presentationSpeeds }?
+presentation-settings =
+  element presentation:settings {
+    presentation-settings-attlist, presentation-show*
+  }?
+presentation-settings-attlist =
+  attribute presentation:start-page { \string }?
+  & attribute presentation:show { \string }?
+  & attribute presentation:full-screen { boolean }?
+  & attribute presentation:endless { boolean }?
+  & attribute presentation:pause { duration }?
+  & attribute presentation:show-logo { boolean }?
+  & attribute presentation:force-manual { boolean }?
+  & attribute presentation:mouse-visible { boolean }?
+  & attribute presentation:mouse-as-pen { boolean }?
+  & attribute presentation:start-with-navigator { boolean }?
+  & attribute presentation:animations { "enabled" | "disabled" }?
+  & attribute presentation:transition-on-click {
+      "enabled" | "disabled"
     }?
-  & attribute style:text-scale { percent }?
-  & attribute style:text-rotation-angle { angle }?
-  & attribute style:text-rotation-scale { "fixed" | "line-height" }?
-  & attribute fo:hyphenate { boolean }?
-  & attribute fo:hyphenation-remain-char-count { positiveInteger }?
-  & attribute fo:hyphenation-push-char-count { positiveInteger }?
-  & (attribute text:display { "true" }
-     | attribute text:display { "none" }
-     | (attribute text:display { "condition" },
-        attribute text:condition { "none" })
-     | empty)
-fontVariant = "normal" | "small-caps"
-fontFamilyGeneric =
-  "roman" | "swiss" | "modern" | "decorative" | "script" | "system"
-fontPitch = "fixed" | "variable"
-textEncoding = xsd:string { pattern = "[A-Za-z][A-Za-z0-9._\-]*" }
-fontStyle = "normal" | "italic" | "oblique"
-shadowType = "none" | \string
-lineType = "none" | "single" | "double"
-lineStyle =
+  & attribute presentation:stay-on-top { boolean }?
+  & attribute presentation:show-end-of-presentation-slide { boolean }?
+presentation-shape-attlist =
+  attribute presentation:class { presentation-classes }?
+  & attribute presentation:placeholder { boolean }?
+  & attribute presentation:user-transformed { boolean }?
+presentation-show =
+  element presentation:show { presentation-show-attlist, empty }
+presentation-show-attlist =
+  attribute presentation:name { \string }
+  & attribute presentation:pages { \string }
+presentation-show-shape =
+  element presentation:show-shape {
+    common-presentation-effect-attlist, presentation-sound?
+  }
+presentation-show-text =
+  element presentation:show-text {
+    common-presentation-effect-attlist, presentation-sound?
+  }
+presentation-sound =
+  element presentation:sound {
+    presentation-sound-attlist,
+    attribute xlink:type { "simple" },
+    attribute xlink:href { anyIRI },
+    attribute xlink:actuate { "onRequest" }?,
+    attribute xlink:show { "new" | "replace" }?,
+    empty
+  }
+presentation-sound-attlist =
+  attribute presentation:play-full { boolean }?
+  & xml-id?
+presentationEffectDirections =
   "none"
-  | "solid"
-  | "dotted"
-  | "dash"
-  | "long-dash"
-  | "dot-dash"
-  | "dot-dot-dash"
-  | "wave"
-lineWidth =
-  "auto"
-  | "normal"
-  | "bold"
-  | "thin"
-  | "medium"
-  | "thick"
-  | positiveInteger
-  | percent
-  | positiveLength
-fontWeight =
-  "normal"
-  | "bold"
-  | "100"
-  | "200"
-  | "300"
-  | "400"
-  | "500"
-  | "600"
-  | "700"
-  | "800"
-  | "900"
-lineMode = "continuous" | "skip-white-space"
-style-paragraph-properties =
-  element style:paragraph-properties {
-    style-paragraph-properties-content-strict
+  | "from-left"
+  | "from-top"
+  | "from-right"
+  | "from-bottom"
+  | "from-center"
+  | "from-upper-left"
+  | "from-upper-right"
+  | "from-lower-left"
+  | "from-lower-right"
+  | "to-left"
+  | "to-top"
+  | "to-right"
+  | "to-bottom"
+  | "to-upper-left"
+  | "to-upper-right"
+  | "to-lower-right"
+  | "to-lower-left"
+  | "path"
+  | "spiral-inward-left"
+  | "spiral-inward-right"
+  | "spiral-outward-left"
+  | "spiral-outward-right"
+  | "vertical"
+  | "horizontal"
+  | "to-center"
+  | "clockwise"
+  | "counter-clockwise"
+presentationEffects =
+  "none"
+  | "fade"
+  | "move"
+  | "stripes"
+  | "open"
+  | "close"
+  | "dissolve"
+  | "wavyline"
+  | "random"
+  | "lines"
+  | "laser"
+  | "appear"
+  | "hide"
+  | "move-short"
+  | "checkerboard"
+  | "rotate"
+  | "stretch"
+presentationSpeeds = "slow" | "medium" | "fast"
+region-content = text-p*
+relativeLength = xsd:string { pattern = "[0-9]+\*" }
+rowOrCol = "row" | "column"
+script-event-listener =
+  element script:event-listener { script-event-listener-attlist, empty }
+script-event-listener-attlist =
+  attribute script:event-name { \string }
+  & attribute script:language { \string }
+  & (attribute script:macro-name { \string }
+     | (attribute xlink:type { "simple" },
+        attribute xlink:href { anyIRI },
+        attribute xlink:actuate { "onRequest" }?))
+scriptCode = xsd:token { pattern = "[A-Za-z0-9]{1,8}" }
+selected = attribute form:selected { boolean }?
+shadowType = "none" | \string
+shape = shape-instance | draw-a
+shape-instance =
+  draw-rect
+  | draw-line
+  | draw-polyline
+  | draw-polygon
+  | draw-regular-polygon
+  | draw-path
+  | draw-circle
+  | draw-ellipse
+  | draw-g
+  | draw-page-thumbnail
+  | draw-frame
+  | draw-measure
+  | draw-caption
+  | draw-connector
+  | draw-control
+  | dr3d-scene
+  | draw-custom-shape
+shapes3d =
+  dr3d-scene | dr3d-extrude | dr3d-sphere | dr3d-rotate | dr3d-cube
+signedZeroToHundredPercent =
+  xsd:string {
+    pattern = "-?([0-9]?[0-9](\.[0-9]*)?|100(\.0*)?|\.[0-9]+)%"
   }
-style-paragraph-properties-content-strict =
-  style-paragraph-properties-attlist,
-  style-paragraph-properties-elements
-style-paragraph-properties-attlist =
-  attribute fo:line-height { "normal" | nonNegativeLength | percent }?
-  & attribute style:line-height-at-least { nonNegativeLength }?
-  & attribute style:line-spacing { length }?
-  & attribute style:font-independent-line-spacing { boolean }?
-  & common-text-align
-  & attribute fo:text-align-last { "start" | "center" | "justify" }?
-  & attribute style:justify-single-word { boolean }?
-  & attribute fo:keep-together { "auto" | "always" }?
-  & attribute fo:widows { nonNegativeInteger }?
-  & attribute fo:orphans { nonNegativeInteger }?
-  & attribute style:tab-stop-distance { nonNegativeLength }?
-  & attribute fo:hyphenation-keep { "auto" | "page" }?
-  & attribute fo:hyphenation-ladder-count {
-      "no-limit" | positiveInteger
-    }?
-  & attribute style:register-true { boolean }?
-  & common-horizontal-margin-attlist
-  & attribute fo:text-indent { length | percent }?
-  & attribute style:auto-text-indent { boolean }?
-  & common-vertical-margin-attlist
-  & common-margin-attlist
-  & common-break-attlist
-  & common-background-color-attlist
-  & common-border-attlist
-  & common-border-line-width-attlist
-  & attribute style:join-border { boolean }?
-  & common-padding-attlist
-  & common-shadow-attlist
-  & common-keep-with-next-attlist
-  & attribute text:number-lines { boolean }?
-  & attribute text:line-number { nonNegativeInteger }?
-  & attribute style:text-autospace { "none" | "ideograph-alpha" }?
-  & attribute style:punctuation-wrap { "simple" | "hanging" }?
-  & attribute style:line-break { "normal" | "strict" }?
-  & attribute style:vertical-align {
-      "top" | "middle" | "bottom" | "auto" | "baseline"
-    }?
-  & common-writing-mode-attlist
-  & attribute style:writing-mode-automatic { boolean }?
-  & attribute style:snap-to-layout-grid { boolean }?
-  & common-page-number-attlist
-  & common-background-transparency-attlist
-common-text-align =
-  attribute fo:text-align {
-    "start" | "end" | "left" | "right" | "center" | "justify"
-  }?
-style-paragraph-properties-elements =
-  style-tab-stops & style-drop-cap & style-background-image
-style-tab-stops = element style:tab-stops { style-tab-stop* }?
-style-tab-stop =
-  element style:tab-stop { style-tab-stop-attlist, empty }
-style-tab-stop-attlist =
-  attribute style:position { length }
-  & (attribute style:type { "left" | "center" | "right" }?
-     | (attribute style:type { "char" },
-        style-tab-stop-char-attlist))
-  & attribute style:leader-type { lineType }?
-  & attribute style:leader-style { lineStyle }?
-  & attribute style:leader-width { lineWidth }?
-  & attribute style:leader-color { "font-color" | color }?
-  & attribute style:leader-text { character }?
-  & attribute style:leader-text-style { styleNameRef }?
-style-tab-stop-char-attlist = attribute style:char { character }
-style-drop-cap =
-  element style:drop-cap { style-drop-cap-attlist, empty }?
-style-drop-cap-attlist =
-  attribute style:length { "word" | positiveInteger }?
-  & attribute style:lines { positiveInteger }?
-  & attribute style:distance { length }?
-  & attribute style:style-name { styleNameRef }?
-common-horizontal-margin-attlist =
-  attribute fo:margin-left { length | percent }?,
-  attribute fo:margin-right { length | percent }?
-common-vertical-margin-attlist =
-  attribute fo:margin-top { nonNegativeLength | percent }?,
-  attribute fo:margin-bottom { nonNegativeLength | percent }?
-common-margin-attlist =
-  attribute fo:margin { nonNegativeLength | percent }?
-common-break-attlist =
-  attribute fo:break-before { "auto" | "column" | "page" }?,
-  attribute fo:break-after { "auto" | "column" | "page" }?
-common-background-color-attlist =
-  attribute fo:background-color { "transparent" | color }?
+size = attribute form:size { nonNegativeInteger }?
+states = "unchecked" | "checked" | "unknown"
+\string = xsd:string
 style-background-image =
   element style:background-image {
     style-background-image-attlist,
@@ -5459,74 +3590,159 @@ style-background-image-attlist =
     }?
   & attribute style:filter-name { \string }?
   & attribute draw:opacity { zeroToHundredPercent }?
-horiBackPos = "left" | "center" | "right"
-vertBackPos = "top" | "center" | "bottom"
-common-border-attlist =
-  attribute fo:border { \string }?,
-  attribute fo:border-top { \string }?,
-  attribute fo:border-bottom { \string }?,
-  attribute fo:border-left { \string }?,
-  attribute fo:border-right { \string }?
-common-border-line-width-attlist =
-  attribute style:border-line-width { borderWidths }?,
-  attribute style:border-line-width-top { borderWidths }?,
-  attribute style:border-line-width-bottom { borderWidths }?,
-  attribute style:border-line-width-left { borderWidths }?,
-  attribute style:border-line-width-right { borderWidths }?
-borderWidths = list { positiveLength, positiveLength, positiveLength }
-common-padding-attlist =
-  attribute fo:padding { nonNegativeLength }?,
-  attribute fo:padding-top { nonNegativeLength }?,
-  attribute fo:padding-bottom { nonNegativeLength }?,
-  attribute fo:padding-left { nonNegativeLength }?,
-  attribute fo:padding-right { nonNegativeLength }?
-common-shadow-attlist = attribute style:shadow { shadowType }?
-common-keep-with-next-attlist =
-  attribute fo:keep-with-next { "auto" | "always" }?
-common-writing-mode-attlist =
-  attribute style:writing-mode {
-    "lr-tb" | "rl-tb" | "tb-rl" | "tb-lr" | "lr" | "rl" | "tb" | "page"
-  }?
-common-page-number-attlist =
-  attribute style:page-number { positiveInteger | "auto" }?
-common-background-transparency-attlist =
-  attribute style:background-transparency { zeroToHundredPercent }?
-style-ruby-properties =
-  element style:ruby-properties { style-ruby-properties-content-strict }
-style-ruby-properties-content-strict =
-  style-ruby-properties-attlist, style-ruby-properties-elements
-style-ruby-properties-elements = empty
-style-ruby-properties-attlist =
-  attribute style:ruby-position { "above" | "below" }?
-  & attribute style:ruby-align {
-      "left"
-      | "center"
-      | "right"
-      | "distribute-letter"
-      | "distribute-space"
+style-chart-properties =
+  element style:chart-properties {
+    style-chart-properties-content-strict
+  }
+style-chart-properties-attlist =
+  attribute chart:scale-text { boolean }?
+  & attribute chart:three-dimensional { boolean }?
+  & attribute chart:deep { boolean }?
+  & attribute chart:right-angled-axes { boolean }?
+  & (attribute chart:symbol-type { "none" }
+     | attribute chart:symbol-type { "automatic" }
+     | (attribute chart:symbol-type { "named-symbol" },
+        attribute chart:symbol-name {
+          "square"
+          | "diamond"
+          | "arrow-down"
+          | "arrow-up"
+          | "arrow-right"
+          | "arrow-left"
+          | "bow-tie"
+          | "hourglass"
+          | "circle"
+          | "star"
+          | "x"
+          | "plus"
+          | "asterisk"
+          | "horizontal-bar"
+          | "vertical-bar"
+        })
+     | (attribute chart:symbol-type { "image" },
+        element chart:symbol-image {
+          attribute xlink:href { anyIRI }
+        })
+     | empty)
+  & attribute chart:symbol-width { nonNegativeLength }?
+  & attribute chart:symbol-height { nonNegativeLength }?
+  & attribute chart:sort-by-x-values { boolean }?
+  & attribute chart:vertical { boolean }?
+  & attribute chart:connect-bars { boolean }?
+  & attribute chart:gap-width { integer }?
+  & attribute chart:overlap { integer }?
+  & attribute chart:group-bars-per-axis { boolean }?
+  & attribute chart:japanese-candle-stick { boolean }?
+  & attribute chart:interpolation {
+      "none"
+      | "cubic-spline"
+      | "b-spline"
+      | "step-start"
+      | "step-end"
+      | "step-center-x"
+      | "step-center-y"
+    }?
+  & attribute chart:spline-order { positiveInteger }?
+  & attribute chart:spline-resolution { positiveInteger }?
+  & attribute chart:pie-offset { nonNegativeInteger }?
+  & attribute chart:angle-offset { angle }?
+  & attribute chart:hole-size { percent }?
+  & attribute chart:lines { boolean }?
+  & attribute chart:solid-type {
+      "cuboid" | "cylinder" | "cone" | "pyramid"
+    }?
+  & attribute chart:stacked { boolean }?
+  & attribute chart:percentage { boolean }?
+  & attribute chart:treat-empty-cells {
+      "use-zero" | "leave-gap" | "ignore"
+    }?
+  & attribute chart:link-data-style-to-source { boolean }?
+  & attribute chart:logarithmic { boolean }?
+  & attribute chart:maximum { double }?
+  & attribute chart:minimum { double }?
+  & attribute chart:origin { double }?
+  & attribute chart:interval-major { double }?
+  & attribute chart:interval-minor-divisor { positiveInteger }?
+  & attribute chart:tick-marks-major-inner { boolean }?
+  & attribute chart:tick-marks-major-outer { boolean }?
+  & attribute chart:tick-marks-minor-inner { boolean }?
+  & attribute chart:tick-marks-minor-outer { boolean }?
+  & attribute chart:reverse-direction { boolean }?
+  & attribute chart:display-label { boolean }?
+  & attribute chart:text-overlap { boolean }?
+  & attribute text:line-break { boolean }?
+  & attribute chart:label-arrangement {
+      "side-by-side" | "stagger-even" | "stagger-odd"
+    }?
+  & common-style-direction-attlist
+  & common-rotation-angle-attlist
+  & attribute chart:data-label-number {
+      "none" | "value" | "percentage" | "value-and-percentage"
+    }?
+  & attribute chart:data-label-text { boolean }?
+  & attribute chart:data-label-symbol { boolean }?
+  & element chart:label-separator { text-p }?
+  & attribute chart:label-position { labelPositions }?
+  & attribute chart:label-position-negative { labelPositions }?
+  & attribute chart:visible { boolean }?
+  & attribute chart:auto-position { boolean }?
+  & attribute chart:auto-size { boolean }?
+  & attribute chart:mean-value { boolean }?
+  & attribute chart:error-category {
+      "none"
+      | "variance"
+      | "standard-deviation"
+      | "percentage"
+      | "error-margin"
+      | "constant"
+      | "standard-error"
+      | "cell-range"
+    }?
+  & attribute chart:error-percentage { double }?
+  & attribute chart:error-margin { double }?
+  & attribute chart:error-lower-limit { double }?
+  & attribute chart:error-upper-limit { double }?
+  & attribute chart:error-upper-indicator { boolean }?
+  & attribute chart:error-lower-indicator { boolean }?
+  & attribute chart:error-lower-range { cellRangeAddressList }?
+  & attribute chart:error-upper-range { cellRangeAddressList }?
+  & attribute chart:series-source { "columns" | "rows" }?
+  & attribute chart:regression-type {
+      "none"
+      | "linear"
+      | "logarithmic"
+      | "moving-average"
+      | "exponential"
+      | "power"
+      | "polynomial"
     }?
-style-section-properties =
-  element style:section-properties {
-    style-section-properties-content-strict
-  }
-style-section-properties-content-strict =
-  style-section-properties-attlist, style-section-properties-elements
-style-section-properties-attlist =
-  common-background-color-attlist
-  & common-horizontal-margin-attlist
-  & attribute style:protect { boolean }?
-  & common-editable-attlist
-  & attribute text:dont-balance-text-columns { boolean }?
-  & common-writing-mode-attlist
-style-section-properties-elements =
-  style-background-image & style-columns & text-notes-configuration*
-style-columns =
-  element style:columns {
-    style-columns-attlist, style-column-sep?, style-column*
-  }?
-style-columns-attlist =
-  attribute fo:column-count { positiveInteger }
-  & attribute fo:column-gap { length }?
+  & attribute chart:regression-max-degree { positiveInteger }?
+  & attribute chart:regression-force-intercept { boolean }?
+  & attribute chart:regression-intercept-value { double }?
+  & attribute chart:regression-name { \string }?
+  & # https://issues.oasis-open.org/browse/OFFICE-3958
+    attribute chart:regression-period { positiveInteger }?
+  & attribute chart:regression-moving-type {
+      "prior" | "central" | "averaged-abscissa"
+    }?
+  & # https://issues.oasis-open.org/browse/OFFICE-3959
+    attribute chart:axis-position { "start" | "end" | double }?
+  & attribute chart:axis-label-position {
+      "near-axis"
+      | "near-axis-other-side"
+      | "outside-start"
+      | "outside-end"
+    }?
+  & attribute chart:tick-mark-position {
+      "at-labels" | "at-axis" | "at-labels-and-axis"
+    }?
+  & attribute chart:include-hidden-cells { boolean }?
+  & (attribute chart:data-label-series { boolean }?)
+    # https://issues.oasis-open.org/browse/OFFICE-2117
+
+style-chart-properties-content-strict =
+  style-chart-properties-attlist, style-chart-properties-elements
+style-chart-properties-elements = empty
 style-column = element style:column { style-column-attlist }
 style-column-attlist =
   attribute style:rel-width { relativeLength }
@@ -5543,132 +3759,235 @@ style-column-sep-attlist =
   & attribute style:height { zeroToHundredPercent }?
   & attribute style:vertical-align { "top" | "middle" | "bottom" }?
   & attribute style:color { color }?
-style-table-properties =
-  element style:table-properties {
-    style-table-properties-content-strict
-  }
-style-table-properties-content-strict =
-  style-table-properties-attlist, style-table-properties-elements
-style-table-properties-attlist =
-  attribute style:width { positiveLength }?
-  & attribute style:rel-width { percent }?
-  & attribute table:align { "left" | "center" | "right" | "margins" }?
-  & common-horizontal-margin-attlist
-  & common-vertical-margin-attlist
-  & common-margin-attlist
-  & common-page-number-attlist
-  & common-break-attlist
-  & common-background-color-attlist
-  & common-shadow-attlist
-  & common-keep-with-next-attlist
-  & attribute style:may-break-between-rows { boolean }?
-  & attribute table:border-model { "collapsing" | "separating" }?
-  & common-writing-mode-attlist
-  & attribute table:display { boolean }?
-style-table-properties-elements = style-background-image
-style-table-column-properties =
-  element style:table-column-properties {
-    style-table-column-properties-content-strict
+style-columns =
+  element style:columns {
+    style-columns-attlist, style-column-sep?, style-column*
+  }?
+style-columns-attlist =
+  attribute fo:column-count { positiveInteger }
+  & attribute fo:column-gap { length }?
+style-default-page-layout =
+  element style:default-page-layout { style-page-layout-content }
+style-default-style =
+  element style:default-style { style-style-content }
+style-drawing-page-properties =
+  element style:drawing-page-properties {
+    style-drawing-page-properties-content-strict
   }
-style-table-column-properties-content-strict =
-  style-table-column-properties-attlist,
-  style-table-column-properties-elements
-style-table-column-properties-elements = empty
-style-table-column-properties-attlist =
-  attribute style:column-width { positiveLength }?
-  & attribute style:rel-column-width { relativeLength }?
-  & attribute style:use-optimal-column-width { boolean }?
-  & common-break-attlist
-style-table-row-properties =
-  element style:table-row-properties {
-    style-table-row-properties-content-strict
+style-drawing-page-properties-attlist =
+  attribute presentation:transition-type {
+    "manual" | "automatic" | "semi-automatic"
+  }?
+  & attribute presentation:transition-style {
+      "none"
+      | "fade-from-left"
+      | "fade-from-top"
+      | "fade-from-right"
+      | "fade-from-bottom"
+      | "fade-from-upperleft"
+      | "fade-from-upperright"
+      | "fade-from-lowerleft"
+      | "fade-from-lowerright"
+      | "move-from-left"
+      | "move-from-top"
+      | "move-from-right"
+      | "move-from-bottom"
+      | "move-from-upperleft"
+      | "move-from-upperright"
+      | "move-from-lowerleft"
+      | "move-from-lowerright"
+      | "uncover-to-left"
+      | "uncover-to-top"
+      | "uncover-to-right"
+      | "uncover-to-bottom"
+      | "uncover-to-upperleft"
+      | "uncover-to-upperright"
+      | "uncover-to-lowerleft"
+      | "uncover-to-lowerright"
+      | "fade-to-center"
+      | "fade-from-center"
+      | "vertical-stripes"
+      | "horizontal-stripes"
+      | "clockwise"
+      | "counterclockwise"
+      | "open-vertical"
+      | "open-horizontal"
+      | "close-vertical"
+      | "close-horizontal"
+      | "wavyline-from-left"
+      | "wavyline-from-top"
+      | "wavyline-from-right"
+      | "wavyline-from-bottom"
+      | "spiralin-left"
+      | "spiralin-right"
+      | "spiralout-left"
+      | "spiralout-right"
+      | "roll-from-top"
+      | "roll-from-left"
+      | "roll-from-right"
+      | "roll-from-bottom"
+      | "stretch-from-left"
+      | "stretch-from-top"
+      | "stretch-from-right"
+      | "stretch-from-bottom"
+      | "vertical-lines"
+      | "horizontal-lines"
+      | "dissolve"
+      | "random"
+      | "vertical-checkerboard"
+      | "horizontal-checkerboard"
+      | "interlocking-horizontal-left"
+      | "interlocking-horizontal-right"
+      | "interlocking-vertical-top"
+      | "interlocking-vertical-bottom"
+      | "fly-away"
+      | "open"
+      | "close"
+      | "melt"
+    }?
+  & attribute presentation:transition-speed { presentationSpeeds }?
+  & attribute smil:type { \string }?
+  & attribute smil:subtype { \string }?
+  & attribute smil:direction { "forward" | "reverse" }?
+  & attribute smil:fadeColor { color }?
+  & attribute presentation:duration { duration }?
+  & attribute presentation:visibility { "visible" | "hidden" }?
+  & attribute draw:background-size { "full" | "border" }?
+  & attribute presentation:background-objects-visible { boolean }?
+  & attribute presentation:background-visible { boolean }?
+  & attribute presentation:display-header { boolean }?
+  & attribute presentation:display-footer { boolean }?
+  & attribute presentation:display-page-number { boolean }?
+  & attribute presentation:display-date-time { boolean }?
+style-drawing-page-properties-content-strict =
+  style-graphic-fill-properties-attlist,
+  style-drawing-page-properties-attlist,
+  style-drawing-page-properties-elements
+style-drawing-page-properties-elements = presentation-sound?
+style-drop-cap =
+  element style:drop-cap { style-drop-cap-attlist, empty }?
+style-drop-cap-attlist =
+  attribute style:length { "word" | positiveInteger }?
+  & attribute style:lines { positiveInteger }?
+  & attribute style:distance { length }?
+  & attribute style:style-name { styleNameRef }?
+style-font-face =
+  element style:font-face {
+    style-font-face-attlist, svg-font-face-src?, svg-definition-src?
   }
-style-table-row-properties-content-strict =
-  style-table-row-properties-attlist,
-  style-table-row-properties-elements
-style-table-row-properties-attlist =
-  attribute style:row-height { positiveLength }?
-  & attribute style:min-row-height { nonNegativeLength }?
-  & attribute style:use-optimal-row-height { boolean }?
-  & common-background-color-attlist
-  & common-break-attlist
-  & attribute fo:keep-together { "auto" | "always" }?
-style-table-row-properties-elements = style-background-image
-style-table-cell-properties =
-  element style:table-cell-properties {
-    style-table-cell-properties-content-strict
+style-font-face-attlist =
+  attribute svg:font-family { \string }?
+  & attribute svg:font-style { fontStyle }?
+  & attribute svg:font-variant { fontVariant }?
+  & attribute svg:font-weight { fontWeight }?
+  & attribute svg:font-stretch {
+      "normal"
+      | "ultra-condensed"
+      | "extra-condensed"
+      | "condensed"
+      | "semi-condensed"
+      | "semi-expanded"
+      | "expanded"
+      | "extra-expanded"
+      | "ultra-expanded"
+    }?
+  & attribute svg:font-size { positiveLength }?
+  & attribute svg:unicode-range { \string }?
+  & attribute svg:units-per-em { integer }?
+  & attribute svg:panose-1 { \string }?
+  & attribute svg:stemv { integer }?
+  & attribute svg:stemh { integer }?
+  & attribute svg:slope { integer }?
+  & attribute svg:cap-height { integer }?
+  & attribute svg:x-height { integer }?
+  & attribute svg:accent-height { integer }?
+  & attribute svg:ascent { integer }?
+  & attribute svg:descent { integer }?
+  & attribute svg:widths { \string }?
+  & attribute svg:bbox { \string }?
+  & attribute svg:ideographic { integer }?
+  & attribute svg:alphabetic { integer }?
+  & attribute svg:mathematical { integer }?
+  & attribute svg:hanging { integer }?
+  & attribute svg:v-ideographic { integer }?
+  & attribute svg:v-alphabetic { integer }?
+  & attribute svg:v-mathematical { integer }?
+  & attribute svg:v-hanging { integer }?
+  & attribute svg:underline-position { integer }?
+  & attribute svg:underline-thickness { integer }?
+  & attribute svg:strikethrough-position { integer }?
+  & attribute svg:strikethrough-thickness { integer }?
+  & attribute svg:overline-position { integer }?
+  & attribute svg:overline-thickness { integer }?
+  & attribute style:name { \string }
+  & attribute style:font-adornments { \string }?
+  & attribute style:font-family-generic { fontFamilyGeneric }?
+  & attribute style:font-pitch { fontPitch }?
+  & attribute style:font-charset { textEncoding }?
+style-footer =
+  element style:footer {
+    common-style-header-footer-attlist, header-footer-content
   }
-style-table-cell-properties-content-strict =
-  style-table-cell-properties-attlist,
-  style-table-cell-properties-elements
-style-table-cell-properties-attlist =
-  attribute style:vertical-align {
-    "top" | "middle" | "bottom" | "automatic"
+style-footer-first =
+  element style:footer-first {
+    common-style-header-footer-attlist,
+    header-footer-content
+    # https://issues.oasis-open.org/browse/OFFICE-3789
+
+  }
+style-footer-left =
+  element style:footer-left {
+    common-style-header-footer-attlist, header-footer-content
+  }
+style-footer-style =
+  element style:footer-style { style-header-footer-properties? }
+style-footnote-sep =
+  element style:footnote-sep { style-footnote-sep-attlist, empty }?
+style-footnote-sep-attlist =
+  attribute style:width { length }?,
+  attribute style:rel-width { percent }?,
+  attribute style:color { color }?,
+  attribute style:line-style { lineStyle }?,
+  attribute style:adjustment { "left" | "center" | "right" }?,
+  attribute style:distance-before-sep { length }?,
+  attribute style:distance-after-sep { length }?
+style-graphic-fill-properties-attlist =
+  attribute draw:fill {
+    "none" | "solid" | "bitmap" | "gradient" | "hatch"
   }?
-  & attribute style:text-align-source { "fix" | "value-type" }?
-  & common-style-direction-attlist
-  & attribute style:glyph-orientation-vertical {
-      "auto" | "0" | "0deg" | "0rad" | "0grad"
-    }?
-  & common-writing-mode-attlist
-  & common-shadow-attlist
-  & common-background-color-attlist
-  & common-border-attlist
-  & attribute style:diagonal-tl-br { \string }?
-  & attribute style:diagonal-tl-br-widths { borderWidths }?
-  & attribute style:diagonal-bl-tr { \string }?
-  & attribute style:diagonal-bl-tr-widths { borderWidths }?
-  & common-border-line-width-attlist
-  & common-padding-attlist
-  & attribute fo:wrap-option { "no-wrap" | "wrap" }?
-  & common-rotation-angle-attlist
-  & attribute style:rotation-align {
-      "none" | "bottom" | "top" | "center"
+  & attribute draw:fill-color { color }?
+  & attribute draw:secondary-fill-color { color }?
+  & attribute draw:fill-gradient-name { styleNameRef }?
+  & attribute draw:gradient-step-count { nonNegativeInteger }?
+  & attribute draw:fill-hatch-name { styleNameRef }?
+  & attribute draw:fill-hatch-solid { boolean }?
+  & attribute draw:fill-image-name { styleNameRef }?
+  & attribute style:repeat { "no-repeat" | "repeat" | "stretch" }?
+  & attribute draw:fill-image-width { length | percent }?
+  & attribute draw:fill-image-height { length | percent }?
+  & attribute draw:fill-image-ref-point-x { percent }?
+  & attribute draw:fill-image-ref-point-y { percent }?
+  & attribute draw:fill-image-ref-point {
+      "top-left"
+      | "top"
+      | "top-right"
+      | "left"
+      | "center"
+      | "right"
+      | "bottom-left"
+      | "bottom"
+      | "bottom-right"
     }?
-  & attribute style:cell-protect {
-      "none"
-      | "hidden-and-protected"
-      | list { ("protected" | "formula-hidden")+ }
+  & attribute draw:tile-repeat-offset {
+      list { zeroToHundredPercent, ("horizontal" | "vertical") }
     }?
-  & attribute style:print-content { boolean }?
-  & attribute style:decimal-places { nonNegativeInteger }?
-  & attribute style:repeat-content { boolean }?
-  & attribute style:shrink-to-fit { boolean }?
-common-style-direction-attlist =
-  attribute style:direction { "ltr" | "ttb" }?
-style-table-cell-properties-elements = style-background-image
-common-rotation-angle-attlist =
-  attribute style:rotation-angle { angle }?
-style-list-level-properties =
-  element style:list-level-properties {
-    style-list-level-properties-content-strict
+  & attribute draw:opacity { zeroToHundredPercent }?
+  & attribute draw:opacity-name { styleNameRef }?
+  & attribute svg:fill-rule { "nonzero" | "evenodd" }?
+style-graphic-properties =
+  element style:graphic-properties {
+    style-graphic-properties-content-strict
   }
-style-list-level-properties-content-strict =
-  style-list-level-properties-attlist,
-  style-list-level-properties-elements
-style-list-level-properties-attlist =
-  common-text-align
-  & attribute text:space-before { length }?
-  & attribute text:min-label-width { nonNegativeLength }?
-  & attribute text:min-label-distance { nonNegativeLength }?
-  & attribute style:font-name { \string }?
-  & attribute fo:width { positiveLength }?
-  & attribute fo:height { positiveLength }?
-  & common-vertical-rel-attlist
-  & common-vertical-pos-attlist
-  & attribute text:list-level-position-and-space-mode {
-      "label-width-and-position" | "label-alignment"
-    }?
-style-list-level-properties-elements = style-list-level-label-alignment
-style-list-level-label-alignment =
-  element style:list-level-label-alignment {
-    style-list-level-label-alignment-attlist, empty
-  }?
-style-list-level-label-alignment-attlist =
-  attribute text:label-followed-by { "listtab" | "space" | "nothing" }
-  & attribute text:list-tab-stop-position { length }?
-  & attribute fo:text-indent { length }?
-  & attribute fo:margin-left { length }?
 style-graphic-properties-attlist =
   attribute draw:stroke { "none" | "dash" | "solid" }?
   & attribute draw:stroke-dash { styleNameRef }?
@@ -5717,7 +4036,9 @@ style-graphic-properties-attlist =
       "greyscale" | "mono" | "watermark" | "standard"
     }?
   & attribute draw:color-inversion { boolean }?
-  & attribute draw:luminance { zeroToHundredPercent }?
+  & attribute draw:luminance { signedZeroToHundredPercent }
+    # https://issues.oasis-open.org/browse/OFFICE-3821
+    ?
   & attribute draw:contrast { percent }?
   & attribute draw:gamma { percent }?
   & attribute draw:red { signedZeroToHundredPercent }?
@@ -5758,497 +4079,2316 @@ style-graphic-properties-attlist =
       | "ft"
       | "mi"
     }?
-  & attribute draw:show-unit { boolean }?
-  & attribute draw:decimal-places { nonNegativeInteger }?
-  & attribute draw:caption-type {
-      "straight-line" | "angled-line" | "angled-connector-line"
+  & attribute draw:show-unit { boolean }?
+  & attribute draw:decimal-places { nonNegativeInteger }?
+  & attribute draw:caption-type {
+      "straight-line" | "angled-line" | "angled-connector-line"
+    }?
+  & attribute draw:caption-angle-type { "fixed" | "free" }?
+  & attribute draw:caption-angle { angle }?
+  & attribute draw:caption-gap { distance }?
+  & attribute draw:caption-escape-direction {
+      "horizontal" | "vertical" | "auto"
+    }?
+  & attribute draw:caption-escape { length | percent }?
+  & attribute draw:caption-line-length { length }?
+  & attribute draw:caption-fit-line-length { boolean }?
+  & attribute dr3d:horizontal-segments { nonNegativeInteger }?
+  & attribute dr3d:vertical-segments { nonNegativeInteger }?
+  & attribute dr3d:edge-rounding { percent }?
+  & attribute dr3d:edge-rounding-mode { "correct" | "attractive" }?
+  & attribute dr3d:back-scale { percent }?
+  & attribute dr3d:depth { length }?
+  & attribute dr3d:backface-culling { "enabled" | "disabled" }?
+  & attribute dr3d:end-angle { angle }?
+  & attribute dr3d:close-front { boolean }?
+  & attribute dr3d:close-back { boolean }?
+  & attribute dr3d:lighting-mode { "standard" | "double-sided" }?
+  & attribute dr3d:normals-kind { "object" | "flat" | "sphere" }?
+  & attribute dr3d:normals-direction { "normal" | "inverse" }?
+  & attribute dr3d:texture-generation-mode-x {
+      "object" | "parallel" | "sphere"
+    }?
+  & attribute dr3d:texture-generation-mode-y {
+      "object" | "parallel" | "sphere"
+    }?
+  & attribute dr3d:texture-kind { "luminance" | "intensity" | "color" }?
+  & attribute dr3d:texture-filter { "enabled" | "disabled" }?
+  & attribute dr3d:texture-mode { "replace" | "modulate" | "blend" }?
+  & attribute dr3d:ambient-color { color }?
+  & attribute dr3d:emissive-color { color }?
+  & attribute dr3d:specular-color { color }?
+  & attribute dr3d:diffuse-color { color }?
+  & attribute dr3d:shininess { percent }?
+  & attribute dr3d:shadow { "visible" | "hidden" }?
+  & common-draw-rel-size-attlist
+  & attribute fo:min-width { length | percent }?
+  & attribute fo:min-height { length | percent }?
+  & attribute fo:max-height { length | percent }?
+  & attribute fo:max-width { length | percent }?
+  & common-horizontal-margin-attlist
+  & common-vertical-margin-attlist
+  & common-margin-attlist
+  & attribute style:print-content { boolean }?
+  & attribute style:protect {
+      "none"
+      | list { ("content" | "position" | "size")+ }
+    }?
+  & attribute style:horizontal-pos {
+      "left"
+      | "center"
+      | "right"
+      | "from-left"
+      | "inside"
+      | "outside"
+      | "from-inside"
+    }?
+  & attribute svg:x { coordinate }?
+  & attribute style:horizontal-rel {
+      "page"
+      | "page-content"
+      | "page-start-margin"
+      | "page-end-margin"
+      | "frame"
+      | "frame-content"
+      | "frame-start-margin"
+      | "frame-end-margin"
+      | "paragraph"
+      | "paragraph-content"
+      | "paragraph-start-margin"
+      | "paragraph-end-margin"
+      | "char"
+    }?
+  & common-vertical-pos-attlist
+  & common-vertical-rel-attlist
+  & common-text-anchor-attlist
+  & common-border-attlist
+  & common-border-line-width-attlist
+  & common-padding-attlist
+  & common-shadow-attlist
+  & common-background-color-attlist
+  & common-background-transparency-attlist
+  & common-editable-attlist
+  & attribute style:wrap {
+      "none"
+      | "left"
+      | "right"
+      | "parallel"
+      | "dynamic"
+      | "run-through"
+      | "biggest"
+    }?
+  & attribute style:wrap-dynamic-threshold { nonNegativeLength }?
+  & attribute style:number-wrapped-paragraphs {
+      "no-limit" | positiveInteger
+    }?
+  & attribute style:wrap-contour { boolean }?
+  & attribute style:wrap-contour-mode { "full" | "outside" }?
+  & attribute style:run-through { "foreground" | "background" }?
+  & attribute style:flow-with-text { boolean }?
+  & attribute style:overflow-behavior {
+      "clip" | "auto-create-new-frame"
+    }?
+  & attribute style:mirror {
+      "none"
+      | "vertical"
+      | horizontal-mirror
+      | list { "vertical", horizontal-mirror }
+      | list { horizontal-mirror, "vertical" }
+    }?
+  & attribute fo:clip { "auto" | clipShape }?
+  & attribute draw:wrap-influence-on-position {
+      "iterative" | "once-concurrent" | "once-successive"
+    }?
+  & common-writing-mode-attlist
+  & attribute draw:frame-display-scrollbar { boolean }?
+  & attribute draw:frame-display-border { boolean }?
+  & attribute draw:frame-margin-horizontal { nonNegativePixelLength }?
+  & attribute draw:frame-margin-vertical { nonNegativePixelLength }?
+  & attribute draw:visible-area-left { nonNegativeLength }?
+  & attribute draw:visible-area-top { nonNegativeLength }?
+  & attribute draw:visible-area-width { positiveLength }?
+  & attribute draw:visible-area-height { positiveLength }?
+  & attribute draw:draw-aspect {
+      "content" | "thumbnail" | "icon" | "print-view"
+    }?
+  & attribute draw:ole-draw-aspect { nonNegativeInteger }?
+style-graphic-properties-content-strict =
+  style-graphic-properties-attlist,
+  style-graphic-fill-properties-attlist,
+  style-graphic-properties-elements
+style-graphic-properties-elements =
+  text-list-style? & style-background-image & style-columns
+style-handout-master =
+  element style:handout-master {
+    common-presentation-header-footer-attlist,
+    style-handout-master-attlist,
+    shape*
+  }
+style-handout-master-attlist =
+  attribute presentation:presentation-page-layout-name { styleNameRef }?
+  & attribute style:page-layout-name { styleNameRef }
+  & attribute draw:style-name { styleNameRef }?
+style-header =
+  element style:header {
+    common-style-header-footer-attlist, header-footer-content
+  }
+style-header-first =
+  element style:header-first {
+    common-style-header-footer-attlist,
+    header-footer-content
+    # https://issues.oasis-open.org/browse/OFFICE-3789
+
+  }
+style-header-footer-properties =
+  element style:header-footer-properties {
+    style-header-footer-properties-content-strict
+  }
+style-header-footer-properties-attlist =
+  attribute svg:height { length }?
+  & attribute fo:min-height { length }?
+  & common-horizontal-margin-attlist
+  & common-vertical-margin-attlist
+  & common-margin-attlist
+  & common-border-attlist
+  & common-border-line-width-attlist
+  & common-padding-attlist
+  & common-background-color-attlist
+  & common-shadow-attlist
+  & attribute style:dynamic-spacing { boolean }?
+style-header-footer-properties-content-strict =
+  style-header-footer-properties-attlist,
+  style-header-footer-properties-elements
+style-header-footer-properties-elements = style-background-image
+style-header-left =
+  element style:header-left {
+    common-style-header-footer-attlist, header-footer-content
+  }
+style-header-style =
+  element style:header-style { style-header-footer-properties? }
+style-list-level-label-alignment =
+  element style:list-level-label-alignment {
+    style-list-level-label-alignment-attlist, empty
+  }?
+style-list-level-label-alignment-attlist =
+  attribute text:label-followed-by { "listtab" | "space" | "nothing" }
+  & attribute text:list-tab-stop-position { length }?
+  & attribute fo:text-indent { length }?
+  & attribute fo:margin-left { length }?
+style-list-level-properties =
+  element style:list-level-properties {
+    style-list-level-properties-content-strict
+  }
+style-list-level-properties-attlist =
+  common-text-align
+  & attribute text:space-before { length }?
+  & attribute text:min-label-width { nonNegativeLength }?
+  & attribute text:min-label-distance { nonNegativeLength }?
+  & attribute style:font-name { \string }?
+  & attribute fo:width { positiveLength }?
+  & attribute fo:height { positiveLength }?
+  & common-vertical-rel-attlist
+  & common-vertical-pos-attlist
+  & attribute text:list-level-position-and-space-mode {
+      "label-width-and-position" | "label-alignment"
     }?
-  & attribute draw:caption-angle-type { "fixed" | "free" }?
-  & attribute draw:caption-angle { angle }?
-  & attribute draw:caption-gap { distance }?
-  & attribute draw:caption-escape-direction {
-      "horizontal" | "vertical" | "auto"
+style-list-level-properties-content-strict =
+  style-list-level-properties-attlist,
+  style-list-level-properties-elements
+style-list-level-properties-elements = style-list-level-label-alignment
+style-map = element style:map { style-map-attlist, empty }
+style-map-attlist =
+  attribute style:condition { \string }
+  & attribute style:apply-style-name { styleNameRef }
+  & attribute style:base-cell-address { cellAddress }?
+style-master-page =
+  element style:master-page {
+    style-master-page-attlist,
+    (style-header,
+     style-header-left?,
+     (style-header-first?)
+     # https://issues.oasis-open.org/browse/OFFICE-3789
+     )?,
+    (style-footer,
+     style-footer-left?,
+     (style-footer-first?)
+     # https://issues.oasis-open.org/browse/OFFICE-3789
+     )?,
+    draw-layer-set?,
+    office-forms?,
+    shape*,
+    animation-element?,
+    presentation-notes?
+  }
+style-master-page-attlist =
+  attribute style:name { styleName }
+  & attribute style:display-name { \string }?
+  & attribute style:page-layout-name { styleNameRef }
+  & attribute draw:style-name { styleNameRef }?
+  & attribute style:next-style-name { styleNameRef }?
+style-num-letter-sync-attlist =
+  attribute style:num-letter-sync { boolean }?
+style-page-layout =
+  element style:page-layout {
+    style-page-layout-attlist, style-page-layout-content
+  }
+style-page-layout-attlist =
+  attribute style:name { styleName }
+  & attribute style:page-usage {
+      "all" | "left" | "right" | "mirrored"
     }?
-  & attribute draw:caption-escape { length | percent }?
-  & attribute draw:caption-line-length { length }?
-  & attribute draw:caption-fit-line-length { boolean }?
-  & attribute dr3d:horizontal-segments { nonNegativeInteger }?
-  & attribute dr3d:vertical-segments { nonNegativeInteger }?
-  & attribute dr3d:edge-rounding { percent }?
-  & attribute dr3d:edge-rounding-mode { "correct" | "attractive" }?
-  & attribute dr3d:back-scale { percent }?
-  & attribute dr3d:depth { length }?
-  & attribute dr3d:backface-culling { "enabled" | "disabled" }?
-  & attribute dr3d:end-angle { angle }?
-  & attribute dr3d:close-front { boolean }?
-  & attribute dr3d:close-back { boolean }?
-  & attribute dr3d:lighting-mode { "standard" | "double-sided" }?
-  & attribute dr3d:normals-kind { "object" | "flat" | "sphere" }?
-  & attribute dr3d:normals-direction { "normal" | "inverse" }?
-  & attribute dr3d:texture-generation-mode-x {
-      "object" | "parallel" | "sphere"
+style-page-layout-content =
+  style-page-layout-properties?,
+  style-header-style?,
+  style-footer-style?
+style-page-layout-properties =
+  element style:page-layout-properties {
+    style-page-layout-properties-content-strict
+  }
+style-page-layout-properties-attlist =
+  attribute fo:page-width { length }?
+  & attribute fo:page-height { length }?
+  & common-num-format-attlist?
+  & common-num-format-prefix-suffix-attlist
+  & attribute style:paper-tray-name { "default" | \string }?
+  & attribute style:print-orientation { "portrait" | "landscape" }?
+  & common-horizontal-margin-attlist
+  & common-vertical-margin-attlist
+  & common-margin-attlist
+  & common-border-attlist
+  & common-border-line-width-attlist
+  & common-padding-attlist
+  & common-shadow-attlist
+  & common-background-color-attlist
+  & attribute style:register-truth-ref-style-name { styleNameRef }?
+  & attribute style:print {
+      list {
+        ("headers"
+         | "grid"
+         | "annotations"
+         | "objects"
+         | "charts"
+         | "drawings"
+         | "formulas"
+         | "zero-values")*
+      }
     }?
-  & attribute dr3d:texture-generation-mode-y {
-      "object" | "parallel" | "sphere"
+  & attribute style:print-page-order { "ttb" | "ltr" }?
+  & attribute style:first-page-number { positiveInteger | "continue" }?
+  & (attribute style:scale-to { percent }?
+     | attribute style:scale-to-pages { positiveInteger }?
+     | (attribute style:scale-to-X { positiveInteger }?,
+        attribute style:scale-to-Y { positiveInteger }?))
+  & # https://issues.oasis-open.org/browse/OFFICE-3857
+    attribute style:table-centering {
+      "horizontal" | "vertical" | "both" | "none"
     }?
-  & attribute dr3d:texture-kind { "luminance" | "intensity" | "color" }?
-  & attribute dr3d:texture-filter { "enabled" | "disabled" }?
-  & attribute dr3d:texture-mode { "replace" | "modulate" | "blend" }?
-  & attribute dr3d:ambient-color { color }?
-  & attribute dr3d:emissive-color { color }?
-  & attribute dr3d:specular-color { color }?
-  & attribute dr3d:diffuse-color { color }?
-  & attribute dr3d:shininess { percent }?
-  & attribute dr3d:shadow { "visible" | "hidden" }?
-  & common-draw-rel-size-attlist
-  & attribute fo:min-width { length | percent }?
-  & attribute fo:min-height { length | percent }?
-  & attribute fo:max-height { length | percent }?
-  & attribute fo:max-width { length | percent }?
+  & attribute style:footnote-max-height { length }?
+  & common-writing-mode-attlist
+  & attribute style:layout-grid-mode { "none" | "line" | "both" }?
+  & attribute style:layout-grid-standard-mode { boolean }?
+  & attribute style:layout-grid-base-height { length }?
+  & attribute style:layout-grid-ruby-height { length }?
+  & attribute style:layout-grid-lines { positiveInteger }?
+  & attribute style:layout-grid-base-width { length }?
+  & attribute style:layout-grid-color { color }?
+  & attribute style:layout-grid-ruby-below { boolean }?
+  & attribute style:layout-grid-print { boolean }?
+  & attribute style:layout-grid-display { boolean }?
+  & attribute style:layout-grid-snap-to { boolean }?
+style-page-layout-properties-content-strict =
+  style-page-layout-properties-attlist,
+  style-page-layout-properties-elements
+style-page-layout-properties-elements =
+  style-background-image & style-columns & style-footnote-sep
+style-paragraph-properties =
+  element style:paragraph-properties {
+    style-paragraph-properties-content-strict
+  }
+style-paragraph-properties-attlist =
+  attribute style:contextual-spacing { boolean }?
+  & # https://issues.oasis-open.org/browse/OFFICE-3767
+    attribute fo:line-height { "normal" | nonNegativeLength | percent }?
+  & attribute style:line-height-at-least { nonNegativeLength }?
+  & attribute style:line-spacing { length }?
+  & attribute style:font-independent-line-spacing { boolean }?
+  & common-text-align
+  & attribute fo:text-align-last { "start" | "center" | "justify" }?
+  & attribute style:justify-single-word { boolean }?
+  & attribute fo:keep-together { "auto" | "always" }?
+  & attribute fo:widows { nonNegativeInteger }?
+  & attribute fo:orphans { nonNegativeInteger }?
+  & attribute style:tab-stop-distance { nonNegativeLength }?
+  & attribute fo:hyphenation-keep { "auto" | "page" }?
+  & attribute fo:hyphenation-ladder-count {
+      "no-limit" | positiveInteger
+    }?
+  & attribute style:register-true { boolean }?
   & common-horizontal-margin-attlist
+  & attribute fo:text-indent { length | percent }?
+  & attribute style:auto-text-indent { boolean }?
   & common-vertical-margin-attlist
   & common-margin-attlist
-  & attribute style:print-content { boolean }?
-  & attribute style:protect {
-      "none"
-      | list { ("content" | "position" | "size")+ }
+  & common-break-attlist
+  & common-background-color-attlist
+  & common-border-attlist
+  & common-border-line-width-attlist
+  & attribute style:join-border { boolean }?
+  & common-padding-attlist
+  & common-shadow-attlist
+  & common-keep-with-next-attlist
+  & attribute text:number-lines { boolean }?
+  & attribute text:line-number { nonNegativeInteger }?
+  & attribute style:text-autospace { "none" | "ideograph-alpha" }?
+  & attribute style:punctuation-wrap { "simple" | "hanging" }?
+  & attribute style:line-break { "normal" | "strict" }?
+  & attribute style:vertical-align {
+      "top" | "middle" | "bottom" | "auto" | "baseline"
     }?
-  & attribute style:horizontal-pos {
+  & common-writing-mode-attlist
+  & attribute style:writing-mode-automatic { boolean }?
+  & attribute style:snap-to-layout-grid { boolean }?
+  & common-page-number-attlist
+  & common-background-transparency-attlist
+style-paragraph-properties-content-strict =
+  style-paragraph-properties-attlist,
+  style-paragraph-properties-elements
+style-paragraph-properties-elements =
+  style-tab-stops & style-drop-cap & style-background-image
+style-presentation-page-layout =
+  element style:presentation-page-layout {
+    attribute style:name { styleName },
+    attribute style:display-name { \string }?,
+    presentation-placeholder*
+  }
+style-region-center = element style:region-center { region-content }
+style-region-left = element style:region-left { region-content }
+style-region-right = element style:region-right { region-content }
+style-ruby-properties =
+  element style:ruby-properties { style-ruby-properties-content-strict }
+style-ruby-properties-attlist =
+  attribute style:ruby-position { "above" | "below" }?
+  & attribute style:ruby-align {
       "left"
       | "center"
       | "right"
-      | "from-left"
-      | "inside"
-      | "outside"
-      | "from-inside"
+      | "distribute-letter"
+      | "distribute-space"
     }?
-  & attribute svg:x { coordinate }?
-  & attribute style:horizontal-rel {
-      "page"
-      | "page-content"
-      | "page-start-margin"
-      | "page-end-margin"
-      | "frame"
-      | "frame-content"
-      | "frame-start-margin"
-      | "frame-end-margin"
-      | "paragraph"
-      | "paragraph-content"
-      | "paragraph-start-margin"
-      | "paragraph-end-margin"
-      | "char"
+style-ruby-properties-content-strict =
+  style-ruby-properties-attlist, style-ruby-properties-elements
+style-ruby-properties-elements = empty
+style-section-properties =
+  element style:section-properties {
+    style-section-properties-content-strict
+  }
+style-section-properties-attlist =
+  common-background-color-attlist
+  & common-horizontal-margin-attlist
+  & attribute style:protect { boolean }?
+  & common-editable-attlist
+  & attribute text:dont-balance-text-columns { boolean }?
+  & common-writing-mode-attlist
+style-section-properties-content-strict =
+  style-section-properties-attlist, style-section-properties-elements
+style-section-properties-elements =
+  style-background-image & style-columns & text-notes-configuration*
+style-style =
+  element style:style {
+    style-style-attlist, style-style-content, style-map*
+  }
+style-style-attlist =
+  attribute style:name { styleName }
+  & attribute style:display-name { \string }?
+  & attribute style:parent-style-name { styleNameRef }?
+  & attribute style:next-style-name { styleNameRef }?
+  & attribute style:list-level { positiveInteger | empty }?
+  & attribute style:list-style-name { styleName | empty }?
+  & attribute style:master-page-name { styleNameRef }?
+  & attribute style:auto-update { boolean }?
+  & attribute style:data-style-name { styleNameRef }?
+  & attribute style:percentage-data-style-name { styleNameRef }?
+  & attribute style:class { \string }?
+  & attribute style:default-outline-level { positiveInteger | empty }?
+style-style-content =
+  (attribute style:family { "text" },
+   style-text-properties?)
+  | (attribute style:family { "paragraph" },
+     style-paragraph-properties?,
+     style-text-properties?)
+  | (attribute style:family { "section" },
+     style-section-properties?)
+  | (attribute style:family { "ruby" },
+     style-ruby-properties?)
+  | (attribute style:family { "table" },
+     style-table-properties?)
+  | (attribute style:family { "table-column" },
+     style-table-column-properties?)
+  | (attribute style:family { "table-row" },
+     style-table-row-properties?)
+  | (attribute style:family { "table-cell" },
+     style-table-cell-properties?,
+     style-paragraph-properties?,
+     style-text-properties?)
+  | (attribute style:family { "graphic" | "presentation" },
+     style-graphic-properties?,
+     style-paragraph-properties?,
+     style-text-properties?)
+  | (attribute style:family { "drawing-page" },
+     style-drawing-page-properties?)
+  | (attribute style:family { "chart" },
+     style-chart-properties?,
+     style-graphic-properties?,
+     style-paragraph-properties?,
+     style-text-properties?)
+style-tab-stop =
+  element style:tab-stop { style-tab-stop-attlist, empty }
+style-tab-stop-attlist =
+  attribute style:position { length }
+  & (attribute style:type { "left" | "center" | "right" }?
+     | (attribute style:type { "char" },
+        style-tab-stop-char-attlist))
+  & attribute style:leader-type { lineType }?
+  & attribute style:leader-style { lineStyle }?
+  & attribute style:leader-width { lineWidth }?
+  & attribute style:leader-color { "font-color" | color }?
+  & attribute style:leader-text { character }?
+  & attribute style:leader-text-style { styleNameRef }?
+style-tab-stop-char-attlist = attribute style:char { character }
+style-tab-stops = element style:tab-stops { style-tab-stop* }?
+style-table-cell-properties =
+  element style:table-cell-properties {
+    style-table-cell-properties-content-strict
+  }
+style-table-cell-properties-attlist =
+  attribute style:vertical-align {
+    "top" | "middle" | "bottom" | "automatic"
+  }?
+  & attribute style:text-align-source { "fix" | "value-type" }?
+  & common-style-direction-attlist
+  & attribute style:glyph-orientation-vertical {
+      "auto" | "0" | "0deg" | "0rad" | "0grad"
     }?
-  & common-vertical-pos-attlist
-  & common-vertical-rel-attlist
-  & common-text-anchor-attlist
+  & common-writing-mode-attlist
+  & common-shadow-attlist
+  & common-background-color-attlist
   & common-border-attlist
+  & attribute style:diagonal-tl-br { \string }?
+  & attribute style:diagonal-tl-br-widths { borderWidths }?
+  & attribute style:diagonal-bl-tr { \string }?
+  & attribute style:diagonal-bl-tr-widths { borderWidths }?
   & common-border-line-width-attlist
   & common-padding-attlist
+  & attribute fo:wrap-option { "no-wrap" | "wrap" }?
+  & common-rotation-angle-attlist
+  & attribute style:rotation-align {
+      "none" | "bottom" | "top" | "center"
+    }?
+  & attribute style:cell-protect {
+      "none"
+      | "hidden-and-protected"
+      | list { ("protected" | "formula-hidden")+ }
+    }?
+  & attribute style:print-content { boolean }?
+  & attribute style:decimal-places { nonNegativeInteger }?
+  & attribute style:repeat-content { boolean }?
+  & attribute style:shrink-to-fit { boolean }?
+style-table-cell-properties-content-strict =
+  style-table-cell-properties-attlist,
+  style-table-cell-properties-elements
+style-table-cell-properties-elements = style-background-image
+style-table-column-properties =
+  element style:table-column-properties {
+    style-table-column-properties-content-strict
+  }
+style-table-column-properties-attlist =
+  attribute style:column-width { positiveLength }?
+  & attribute style:rel-column-width { relativeLength }?
+  & attribute style:use-optimal-column-width { boolean }?
+  & common-break-attlist
+style-table-column-properties-content-strict =
+  style-table-column-properties-attlist,
+  style-table-column-properties-elements
+style-table-column-properties-elements = empty
+style-table-properties =
+  element style:table-properties {
+    style-table-properties-content-strict
+  }
+style-table-properties-attlist =
+  attribute style:width { positiveLength }?
+  & attribute style:rel-width { percent }?
+  & attribute table:align { "left" | "center" | "right" | "margins" }?
+  & common-horizontal-margin-attlist
+  & common-vertical-margin-attlist
+  & common-margin-attlist
+  & common-page-number-attlist
+  & common-break-attlist
+  & common-background-color-attlist
   & common-shadow-attlist
+  & common-keep-with-next-attlist
+  & attribute style:may-break-between-rows { boolean }?
+  & attribute table:border-model { "collapsing" | "separating" }?
+  & common-writing-mode-attlist
+  & attribute table:display { boolean }?
+  & (attribute table:tab-color { color }?)
+    # https://issues.oasis-open.org/browse/OFFICE-2173
+
+style-table-properties-content-strict =
+  style-table-properties-attlist, style-table-properties-elements
+style-table-properties-elements = style-background-image
+style-table-row-properties =
+  element style:table-row-properties {
+    style-table-row-properties-content-strict
+  }
+style-table-row-properties-attlist =
+  attribute style:row-height { positiveLength }?
+  & attribute style:min-row-height { nonNegativeLength }?
+  & attribute style:use-optimal-row-height { boolean }?
+  & common-background-color-attlist
+  & common-break-attlist
+  & attribute fo:keep-together { "auto" | "always" }?
+style-table-row-properties-content-strict =
+  style-table-row-properties-attlist,
+  style-table-row-properties-elements
+style-table-row-properties-elements = style-background-image
+style-text-properties =
+  element style:text-properties { style-text-properties-content-strict }
+style-text-properties-attlist =
+  attribute fo:font-variant { fontVariant }?
+  & attribute fo:text-transform {
+      "none" | "lowercase" | "uppercase" | "capitalize"
+    }?
+  & attribute fo:color { color }?
+  & attribute style:use-window-font-color { boolean }?
+  & attribute style:text-outline { boolean }?
+  & attribute style:text-line-through-type { lineType }?
+  & attribute style:text-line-through-style { lineStyle }?
+  & attribute style:text-line-through-width { lineWidth }?
+  & attribute style:text-line-through-color { "font-color" | color }?
+  & attribute style:text-line-through-text { \string }?
+  & attribute style:text-line-through-text-style { styleNameRef }?
+  & attribute style:text-position {
+      list { (percent | "super" | "sub"), percent? }
+    }?
+  & attribute style:font-name { \string }?
+  & attribute style:font-name-asian { \string }?
+  & attribute style:font-name-complex { \string }?
+  & attribute fo:font-family { \string }?
+  & attribute style:font-family-asian { \string }?
+  & attribute style:font-family-complex { \string }?
+  & attribute style:font-family-generic { fontFamilyGeneric }?
+  & attribute style:font-family-generic-asian { fontFamilyGeneric }?
+  & attribute style:font-family-generic-complex { fontFamilyGeneric }?
+  & attribute style:font-style-name { \string }?
+  & attribute style:font-style-name-asian { \string }?
+  & attribute style:font-style-name-complex { \string }?
+  & attribute style:font-pitch { fontPitch }?
+  & attribute style:font-pitch-asian { fontPitch }?
+  & attribute style:font-pitch-complex { fontPitch }?
+  & attribute style:font-charset { textEncoding }?
+  & attribute style:font-charset-asian { textEncoding }?
+  & attribute style:font-charset-complex { textEncoding }?
+  & attribute fo:font-size { positiveLength | percent }?
+  & attribute style:font-size-asian { positiveLength | percent }?
+  & attribute style:font-size-complex { positiveLength | percent }?
+  & attribute style:font-size-rel { length }?
+  & attribute style:font-size-rel-asian { length }?
+  & attribute style:font-size-rel-complex { length }?
+  & attribute style:script-type {
+      "latin" | "asian" | "complex" | "ignore"
+    }?
+  & attribute fo:letter-spacing { length | "normal" }?
+  & attribute fo:language { languageCode }?
+  & attribute style:language-asian { languageCode }?
+  & attribute style:language-complex { languageCode }?
+  & attribute fo:country { countryCode }?
+  & attribute style:country-asian { countryCode }?
+  & attribute style:country-complex { countryCode }?
+  & attribute fo:script { scriptCode }?
+  & attribute style:script-asian { scriptCode }?
+  & attribute style:script-complex { scriptCode }?
+  & attribute style:rfc-language-tag { language }?
+  & attribute style:rfc-language-tag-asian { language }?
+  & attribute style:rfc-language-tag-complex { language }?
+  & attribute fo:font-style { fontStyle }?
+  & attribute style:font-style-asian { fontStyle }?
+  & attribute style:font-style-complex { fontStyle }?
+  & attribute style:font-relief { "none" | "embossed" | "engraved" }?
+  & attribute fo:text-shadow { shadowType }?
+  & attribute style:text-underline-type { lineType }?
+  & attribute style:text-underline-style { lineStyle }?
+  & attribute style:text-underline-width { lineWidth }?
+  & attribute style:text-underline-color { "font-color" | color }?
+  & attribute style:text-overline-type { lineType }?
+  & attribute style:text-overline-style { lineStyle }?
+  & attribute style:text-overline-width { lineWidth }?
+  & attribute style:text-overline-color { "font-color" | color }?
+  & attribute style:text-overline-mode { lineMode }?
+  & attribute fo:font-weight { fontWeight }?
+  & attribute style:font-weight-asian { fontWeight }?
+  & attribute style:font-weight-complex { fontWeight }?
+  & attribute style:text-underline-mode { lineMode }?
+  & attribute style:text-line-through-mode { lineMode }?
+  & attribute style:letter-kerning { boolean }?
+  & attribute style:text-blinking { boolean }?
   & common-background-color-attlist
-  & common-background-transparency-attlist
-  & common-editable-attlist
-  & attribute style:wrap {
+  & attribute style:text-combine { "none" | "letters" | "lines" }?
+  & attribute style:text-combine-start-char { character }?
+  & attribute style:text-combine-end-char { character }?
+  & attribute style:text-emphasize {
       "none"
-      | "left"
-      | "right"
-      | "parallel"
-      | "dynamic"
-      | "run-through"
-      | "biggest"
+      | list {
+          ("none" | "accent" | "dot" | "circle" | "disc"),
+          ("above" | "below")
+        }
     }?
-  & attribute style:wrap-dynamic-threshold { nonNegativeLength }?
-  & attribute style:number-wrapped-paragraphs {
-      "no-limit" | positiveInteger
+  & attribute style:text-scale { percent }?
+  & attribute style:text-rotation-angle { angle }?
+  & attribute style:text-rotation-scale { "fixed" | "line-height" }?
+  & attribute fo:hyphenate { boolean }?
+  & attribute fo:hyphenation-remain-char-count { positiveInteger }?
+  & attribute fo:hyphenation-push-char-count { positiveInteger }?
+  & (attribute text:display { "true" }
+     | attribute text:display { "none" }
+     | (attribute text:display { "condition" },
+        attribute text:condition { "none" })
+     | empty)
+style-text-properties-content-strict =
+  style-text-properties-attlist, style-text-properties-elements
+style-text-properties-elements = empty
+styleName = xsd:NCName
+styleNameRef = xsd:NCName | empty
+styleNameRefs = list { xsd:NCName* }
+styles =
+  style-style*
+  & text-list-style*
+  & number-number-style*
+  & number-currency-style*
+  & number-percentage-style*
+  & number-date-style*
+  & number-time-style*
+  & number-boolean-style*
+  & number-text-style*
+svg-definition-src =
+  element svg:definition-src {
+    common-svg-font-face-xlink-attlist, empty
+  }
+svg-desc = element svg:desc { text }
+svg-font-face-format =
+  element svg:font-face-format {
+    attribute svg:string { \string }?,
+    empty
+  }
+svg-font-face-name =
+  element svg:font-face-name {
+    attribute svg:name { \string }?,
+    empty
+  }
+svg-font-face-src =
+  element svg:font-face-src {
+    (svg-font-face-uri | svg-font-face-name)+
+  }
+svg-font-face-uri =
+  element svg:font-face-uri {
+    common-svg-font-face-xlink-attlist, svg-font-face-format*
+  }
+svg-linearGradient =
+  element svg:linearGradient {
+    common-svg-gradient-attlist,
+    attribute svg:x1 { coordinate | percent }?,
+    attribute svg:y1 { coordinate | percent }?,
+    attribute svg:x2 { coordinate | percent }?,
+    attribute svg:y2 { coordinate | percent }?,
+    svg-stop*
+  }
+svg-radialGradient =
+  element svg:radialGradient {
+    common-svg-gradient-attlist,
+    attribute svg:cx { coordinate | percent }?,
+    attribute svg:cy { coordinate | percent }?,
+    attribute svg:r { coordinate | percent }?,
+    attribute svg:fx { coordinate | percent }?,
+    attribute svg:fy { coordinate | percent }?,
+    svg-stop*
+  }
+svg-stop =
+  element svg:stop {
+    attribute svg:offset { double | percent },
+    attribute svg:stop-color { color }?,
+    attribute svg:stop-opacity { double }?
+  }
+svg-title = element svg:title { text }
+tab-cycles = "records" | "current" | "page"
+table-background =
+  element table:background { table-background-attlist, empty }
+table-background-attlist = attribute table:style-name { styleNameRef }
+table-body = element table:body { common-table-template-attlist, empty }
+table-calculation-setting-attlist =
+  attribute table:case-sensitive { boolean }?
+  & attribute table:precision-as-shown { boolean }?
+  & attribute table:search-criteria-must-apply-to-whole-cell {
+      boolean
     }?
-  & attribute style:wrap-contour { boolean }?
-  & attribute style:wrap-contour-mode { "full" | "outside" }?
-  & attribute style:run-through { "foreground" | "background" }?
-  & attribute style:flow-with-text { boolean }?
-  & attribute style:overflow-behavior {
-      "clip" | "auto-create-new-frame"
+  & attribute table:automatic-find-labels { boolean }?
+  & attribute table:use-regular-expressions { boolean }?
+  & attribute table:use-wildcards { boolean }?
+  & attribute table:null-year { positiveInteger }?
+table-calculation-settings =
+  element table:calculation-settings {
+    table-calculation-setting-attlist,
+    table-null-date?,
+    table-iteration?
+  }
+table-cell-address =
+  element table:cell-address {
+    common-table-cell-address-attlist, empty
+  }
+table-cell-content-change =
+  element table:cell-content-change {
+    common-table-change-attlist,
+    table-cell-address,
+    office-change-info,
+    table-dependencies?,
+    table-deletions?,
+    table-previous
+  }
+table-cell-content-deletion =
+  element table:cell-content-deletion {
+    attribute table:id { \string }?,
+    table-cell-address?,
+    table-change-track-table-cell?
+  }
+table-cell-range-source =
+  element table:cell-range-source {
+    table-table-cell-range-source-attlist,
+    table-linked-source-attlist,
+    empty
+  }
+table-change-deletion =
+  element table:change-deletion {
+    attribute table:id { \string }?,
+    empty
+  }
+table-change-track-table-cell =
+  element table:change-track-table-cell {
+    table-change-track-table-cell-attlist, text-p*
+  }
+table-change-track-table-cell-attlist =
+  attribute table:cell-address { cellAddress }?
+  & attribute table:matrix-covered { boolean }?
+  & attribute table:formula { \string }?
+  & attribute table:number-matrix-columns-spanned { positiveInteger }?
+  & attribute table:number-matrix-rows-spanned { positiveInteger }?
+  & common-value-and-type-attlist?
+table-columns = table-table-columns | table-table-column+
+table-columns-and-groups =
+  (table-table-column-group | table-columns-no-group)+
+table-columns-no-group =
+  (table-columns, (table-table-header-columns, table-columns?)?)
+  | (table-table-header-columns, table-columns?)
+table-consolidation =
+  element table:consolidation { table-consolidation-attlist, empty }
+table-consolidation-attlist =
+  attribute table:function {
+    "average"
+    | "count"
+    | "countnums"
+    | "max"
+    | "min"
+    | "product"
+    | "stdev"
+    | "stdevp"
+    | "sum"
+    | "var"
+    | "varp"
+    | \string
+  }
+  & attribute table:source-cell-range-addresses { cellRangeAddressList }
+  & attribute table:target-cell-address { cellAddress }
+  & attribute table:use-labels { "none" | "row" | "column" | "both" }?
+  & attribute table:link-to-source-data { boolean }?
+table-content-validation =
+  element table:content-validation {
+    table-validation-attlist,
+    table-help-message?,
+    (table-error-message | (table-error-macro, office-event-listeners))?
+  }
+table-content-validations =
+  element table:content-validations { table-content-validation+ }
+table-covered-table-cell =
+  element table:covered-table-cell {
+    table-table-cell-attlist, table-table-cell-content
+  }
+table-cut-offs =
+  element table:cut-offs {
+    table-movement-cut-off+
+    | (table-insertion-cut-off, table-movement-cut-off*)
+  }
+table-data-pilot-display-info =
+  element table:data-pilot-display-info {
+    table-data-pilot-display-info-attlist, empty
+  }
+table-data-pilot-display-info-attlist =
+  attribute table:enabled { boolean }
+  & attribute table:data-field { \string }
+  & attribute table:member-count { nonNegativeInteger }
+  & attribute table:display-member-mode { "from-top" | "from-bottom" }
+table-data-pilot-field =
+  element table:data-pilot-field {
+    table-data-pilot-field-attlist,
+    table-data-pilot-level?,
+    table-data-pilot-field-reference?,
+    table-data-pilot-groups?
+  }
+table-data-pilot-field-attlist =
+  attribute table:source-field-name { \string }
+  & (attribute table:orientation {
+       "row" | "column" | "data" | "hidden"
+     }
+     | (attribute table:orientation { "page" },
+        attribute table:selected-page { \string }))
+  & attribute table:is-data-layout-field { \string }?
+  & attribute table:function {
+      "auto"
+      | "average"
+      | "count"
+      | "countnums"
+      | "max"
+      | "min"
+      | "product"
+      | "stdev"
+      | "stdevp"
+      | "sum"
+      | "var"
+      | "varp"
+      | \string
     }?
-  & attribute style:mirror {
+  & attribute table:used-hierarchy { integer }?
+table-data-pilot-field-reference =
+  element table:data-pilot-field-reference {
+    table-data-pilot-field-reference-attlist
+  }
+table-data-pilot-field-reference-attlist =
+  attribute table:field-name { \string }
+  & ((attribute table:member-type { "named" },
+      attribute table:member-name { \string })
+     | attribute table:member-type { "previous" | "next" })
+  & attribute table:type {
       "none"
-      | "vertical"
-      | horizontal-mirror
-      | list { "vertical", horizontal-mirror }
-      | list { horizontal-mirror, "vertical" }
+      | "member-difference"
+      | "member-percentage"
+      | "member-percentage-difference"
+      | "running-total"
+      | "row-percentage"
+      | "column-percentage"
+      | "total-percentage"
+      | "index"
+    }
+table-data-pilot-group =
+  element table:data-pilot-group {
+    table-data-pilot-group-attlist, table-data-pilot-group-member+
+  }
+table-data-pilot-group-attlist = attribute table:name { \string }
+table-data-pilot-group-member =
+  element table:data-pilot-group-member {
+    table-data-pilot-group-member-attlist
+  }
+table-data-pilot-group-member-attlist = attribute table:name { \string }
+table-data-pilot-groups =
+  element table:data-pilot-groups {
+    table-data-pilot-groups-attlist, table-data-pilot-group+
+  }
+table-data-pilot-groups-attlist =
+  attribute table:source-field-name { \string }
+  & (attribute table:date-start { dateOrDateTime | "auto" }
+     | attribute table:start { double | "auto" })?
+  & (attribute table:date-end { dateOrDateTime | "auto" }
+     | attribute table:end { double | "auto" })?
+  & attribute table:step { double }?
+  & attribute table:grouped-by {
+      "seconds"
+      | "minutes"
+      | "hours"
+      | "days"
+      | "months"
+      | "quarters"
+      | "years"
+    }?
+# https://issues.oasis-open.org/browse/OFFICE-2118
+table-data-pilot-layout-info =
+  element table:data-pilot-layout-info {
+    table-data-pilot-layout-info-attlist, empty
+  }
+table-data-pilot-layout-info-attlist =
+  attribute table:layout-mode {
+    "tabular-layout"
+    | "outline-subtotals-top"
+    | "outline-subtotals-bottom"
+  }
+  & attribute table:add-empty-lines { boolean }
+table-data-pilot-level =
+  element table:data-pilot-level {
+    table-data-pilot-level-attlist,
+    table-data-pilot-subtotals?,
+    table-data-pilot-members?,
+    table-data-pilot-display-info?,
+    table-data-pilot-sort-info?,
+    table-data-pilot-layout-info?
+  }
+table-data-pilot-level-attlist = attribute table:show-empty { boolean }?
+table-data-pilot-member =
+  element table:data-pilot-member {
+    table-data-pilot-member-attlist, empty
+  }
+table-data-pilot-member-attlist =
+  attribute table:name { \string }
+  & attribute table:display { boolean }?
+  & attribute table:show-details { boolean }?
+table-data-pilot-members =
+  element table:data-pilot-members { table-data-pilot-member* }
+table-data-pilot-sort-info =
+  element table:data-pilot-sort-info {
+    table-data-pilot-sort-info-attlist, empty
+  }
+table-data-pilot-sort-info-attlist =
+  ((attribute table:sort-mode { "data" },
+    attribute table:data-field { \string })
+   | attribute table:sort-mode { "none" | "manual" | "name" })
+  & attribute table:order { "ascending" | "descending" }
+table-data-pilot-subtotal =
+  element table:data-pilot-subtotal {
+    table-data-pilot-subtotal-attlist, empty
+  }
+table-data-pilot-subtotal-attlist =
+  attribute table:function {
+    "auto"
+    | "average"
+    | "count"
+    | "countnums"
+    | "max"
+    | "min"
+    | "product"
+    | "stdev"
+    | "stdevp"
+    | "sum"
+    | "var"
+    | "varp"
+    | \string
+  }
+table-data-pilot-subtotals =
+  element table:data-pilot-subtotals { table-data-pilot-subtotal* }
+table-data-pilot-table =
+  element table:data-pilot-table {
+    table-data-pilot-table-attlist,
+    (table-database-source-sql
+     | table-database-source-table
+     | table-database-source-query
+     | table-source-service
+     | table-source-cell-range)?,
+    table-data-pilot-field+
+  }
+table-data-pilot-table-attlist =
+  attribute table:name { \string }
+  & attribute table:application-data { \string }?
+  & attribute table:grand-total { "none" | "row" | "column" | "both" }?
+  & attribute table:ignore-empty-rows { boolean }?
+  & attribute table:identify-categories { boolean }?
+  & attribute table:target-range-address { cellRangeAddress }
+  & attribute table:buttons { cellRangeAddressList }?
+  & attribute table:show-filter-button { boolean }?
+  & attribute table:drill-down-on-double-click { boolean }?
+table-data-pilot-tables =
+  element table:data-pilot-tables { table-data-pilot-table* }
+table-database-range =
+  element table:database-range {
+    table-database-range-attlist,
+    (table-database-source-sql
+     | table-database-source-table
+     | table-database-source-query)?,
+    table-filter?,
+    table-sort?,
+    table-subtotal-rules?
+  }
+table-database-range-attlist =
+  attribute table:name { \string }?
+  & attribute table:is-selection { boolean }?
+  & attribute table:on-update-keep-styles { boolean }?
+  & attribute table:on-update-keep-size { boolean }?
+  & attribute table:has-persistent-data { boolean }?
+  & attribute table:orientation { "column" | "row" }?
+  & attribute table:contains-header { boolean }?
+  & attribute table:display-filter-buttons { boolean }?
+  & attribute table:target-range-address { cellRangeAddress }
+  & attribute table:refresh-delay { boolean }?
+table-database-ranges =
+  element table:database-ranges { table-database-range* }
+table-database-source-query =
+  element table:database-source-table {
+    table-database-source-table-attlist, empty
+  }
+table-database-source-query-attlist =
+  attribute table:database-name { \string }
+  & attribute table:query-name { \string }
+table-database-source-sql =
+  element table:database-source-sql {
+    table-database-source-sql-attlist, empty
+  }
+table-database-source-sql-attlist =
+  attribute table:database-name { \string }
+  & attribute table:sql-statement { \string }
+  & attribute table:parse-sql-statement { boolean }?
+table-database-source-table =
+  element table:database-source-query {
+    table-database-source-query-attlist, empty
+  }
+table-database-source-table-attlist =
+  attribute table:database-name { \string }
+  & attribute table:database-table-name { \string }
+table-dde-link =
+  element table:dde-link { office-dde-source, table-table }
+table-dde-links = element table:dde-links { table-dde-link+ }
+table-decls =
+  table-calculation-settings?,
+  table-content-validations?,
+  table-label-ranges?
+table-deletion =
+  element table:deletion {
+    table-deletion-attlist,
+    common-table-change-attlist,
+    office-change-info,
+    table-dependencies?,
+    table-deletions?,
+    table-cut-offs?
+  }
+table-deletion-attlist =
+  attribute table:type { "row" | "column" | "table" }
+  & attribute table:position { integer }
+  & attribute table:table { integer }?
+  & attribute table:multi-deletion-spanned { integer }?
+table-deletions =
+  element table:deletions {
+    (table-cell-content-deletion | table-change-deletion)+
+  }
+table-dependencies = element table:dependencies { table-dependency+ }
+table-dependency =
+  element table:dependency {
+    attribute table:id { \string },
+    empty
+  }
+table-desc = element table:desc { text }
+table-detective =
+  element table:detective { table-highlighted-range*, table-operation* }
+table-error-macro =
+  element table:error-macro {
+    attribute table:execute { boolean }?
+  }
+table-error-message =
+  element table:error-message {
+    attribute table:title { \string }?,
+    attribute table:display { boolean }?,
+    attribute table:message-type {
+      "stop" | "warning" | "information"
+    }?,
+    text-p*
+  }
+table-even-columns =
+  element table:even-columns { common-table-template-attlist, empty }
+table-even-rows =
+  element table:even-rows { common-table-template-attlist, empty }
+table-filter =
+  element table:filter {
+    table-filter-attlist,
+    (table-filter-condition | table-filter-and | table-filter-or)
+  }
+table-filter-and =
+  element table:filter-and {
+    (table-filter-or | table-filter-condition)+
+  }
+table-filter-attlist =
+  attribute table:target-range-address { cellRangeAddress }?
+  & attribute table:condition-source { "self" | "cell-range" }?
+  & attribute table:condition-source-range-address { cellRangeAddress }?
+  & attribute table:display-duplicates { boolean }?
+table-filter-condition =
+  element table:filter-condition {
+    table-filter-condition-attlist, table-filter-set-item*
+  }
+table-filter-condition-attlist =
+  attribute table:field-number { nonNegativeInteger }
+  & attribute table:value { \string | double }
+  & attribute table:operator { \string }
+  & attribute table:case-sensitive { \string }?
+  & attribute table:data-type { "text" | "number" }?
+table-filter-or =
+  element table:filter-or {
+    (table-filter-and | table-filter-condition)+
+  }
+table-filter-set-item =
+  element table:filter-set-item {
+    attribute table:value { \string },
+    empty
+  }
+table-first-column =
+  element table:first-column { common-table-template-attlist, empty }
+table-first-row =
+  element table:first-row { common-table-template-attlist, empty }
+table-functions =
+  table-named-expressions?,
+  table-database-ranges?,
+  table-data-pilot-tables?,
+  table-consolidation?,
+  table-dde-links?
+table-help-message =
+  element table:help-message {
+    attribute table:title { \string }?,
+    attribute table:display { boolean }?,
+    text-p*
+  }
+table-highlighted-range =
+  element table:highlighted-range {
+    (table-highlighted-range-attlist
+     | table-highlighted-range-attlist-invalid),
+    empty
+  }
+table-highlighted-range-attlist =
+  attribute table:cell-range-address { cellRangeAddress }?
+  & attribute table:direction {
+      "from-another-table" | "to-another-table" | "from-same-table"
+    }
+  & attribute table:contains-error { boolean }?
+table-highlighted-range-attlist-invalid =
+  attribute table:marked-invalid { boolean }
+table-insertion =
+  element table:insertion {
+    table-insertion-attlist,
+    common-table-change-attlist,
+    office-change-info,
+    table-dependencies?,
+    table-deletions?
+  }
+table-insertion-attlist =
+  attribute table:type { "row" | "column" | "table" }
+  & attribute table:position { integer }
+  & attribute table:count { positiveInteger }?
+  & attribute table:table { integer }?
+table-insertion-cut-off =
+  element table:insertion-cut-off {
+    table-insertion-cut-off-attlist, empty
+  }
+table-insertion-cut-off-attlist =
+  attribute table:id { \string }
+  & attribute table:position { integer }
+table-iteration =
+  element table:iteration {
+    attribute table:status { "enable" | "disable" }?,
+    attribute table:steps { positiveInteger }?,
+    attribute table:maximum-difference { double }?,
+    empty
+  }
+table-label-range =
+  element table:label-range { table-label-range-attlist, empty }
+table-label-range-attlist =
+  attribute table:label-cell-range-address { cellRangeAddress }
+  & attribute table:data-cell-range-address { cellRangeAddress }
+  & attribute table:orientation { "column" | "row" }
+table-label-ranges = element table:label-ranges { table-label-range* }
+table-last-column =
+  element table:last-column { common-table-template-attlist, empty }
+table-last-row =
+  element table:last-row { common-table-template-attlist, empty }
+table-linked-source-attlist =
+  attribute xlink:type { "simple" }
+  & attribute xlink:href { anyIRI }
+  & attribute xlink:actuate { "onRequest" }?
+  & attribute table:filter-name { \string }?
+  & attribute table:filter-options { \string }?
+  & attribute table:refresh-delay { duration }?
+table-movement =
+  element table:movement {
+    common-table-change-attlist,
+    table-source-range-address,
+    table-target-range-address,
+    office-change-info,
+    table-dependencies?,
+    table-deletions?
+  }
+table-movement-cut-off =
+  element table:movement-cut-off {
+    table-movement-cut-off-attlist, empty
+  }
+table-movement-cut-off-attlist =
+  attribute table:position { integer }
+  | (attribute table:start-position { integer },
+     attribute table:end-position { integer })
+table-named-expression =
+  element table:named-expression {
+    table-named-expression-attlist, empty
+  }
+table-named-expression-attlist =
+  attribute table:name { \string },
+  attribute table:expression { \string },
+  attribute table:base-cell-address { cellAddress }?
+table-named-expressions =
+  element table:named-expressions {
+    (table-named-range | table-named-expression)*
+  }
+table-named-range =
+  element table:named-range { table-named-range-attlist, empty }
+table-named-range-attlist =
+  attribute table:name { \string },
+  attribute table:cell-range-address { cellRangeAddress },
+  attribute table:base-cell-address { cellAddress }?,
+  attribute table:range-usable-as {
+    "none"
+    | list {
+        ("print-range" | "filter" | "repeat-row" | "repeat-column")+
+      }
+  }?
+table-null-date =
+  element table:null-date {
+    attribute table:value-type { "date" }?,
+    attribute table:date-value { date }?,
+    empty
+  }
+table-odd-columns =
+  element table:odd-columns { common-table-template-attlist, empty }
+table-odd-rows =
+  element table:odd-rows { common-table-template-attlist, empty }
+table-operation =
+  element table:operation { table-operation-attlist, empty }
+table-operation-attlist =
+  attribute table:name {
+    "trace-dependents"
+    | "remove-dependents"
+    | "trace-precedents"
+    | "remove-precedents"
+    | "trace-errors"
+  }
+  & attribute table:index { nonNegativeInteger }
+table-previous =
+  element table:previous {
+    attribute table:id { \string }?,
+    table-change-track-table-cell
+  }
+table-rows =
+  table-table-rows | (text-soft-page-break?, table-table-row)+
+table-rows-and-groups = (table-table-row-group | table-rows-no-group)+
+table-rows-no-group =
+  (table-rows, (table-table-header-rows, table-rows?)?)
+  | (table-table-header-rows, table-rows?)
+table-scenario =
+  element table:scenario { table-scenario-attlist, empty }
+table-scenario-attlist =
+  attribute table:scenario-ranges { cellRangeAddressList }
+  & attribute table:is-active { boolean }
+  & attribute table:display-border { boolean }?
+  & attribute table:border-color { color }?
+  & attribute table:copy-back { boolean }?
+  & attribute table:copy-styles { boolean }?
+  & attribute table:copy-formulas { boolean }?
+  & attribute table:comment { \string }?
+  & attribute table:protected { boolean }?
+table-shapes = element table:shapes { shape+ }
+table-sort = element table:sort { table-sort-attlist, table-sort-by+ }
+table-sort-attlist =
+  attribute table:bind-styles-to-content { boolean }?
+  & attribute table:target-range-address { cellRangeAddress }?
+  & attribute table:case-sensitive { boolean }?
+  & attribute table:language { languageCode }?
+  & attribute table:country { countryCode }?
+  & attribute table:script { scriptCode }?
+  & attribute table:rfc-language-tag { language }?
+  & attribute table:algorithm { \string }?
+  & attribute table:embedded-number-behavior {
+      "alpha-numeric" | "integer" | "double"
     }?
-  & attribute fo:clip { "auto" | clipShape }?
-  & attribute draw:wrap-influence-on-position {
-      "iterative" | "once-concurrent" | "once-successive"
+table-sort-by = element table:sort-by { table-sort-by-attlist, empty }
+table-sort-by-attlist =
+  attribute table:field-number { nonNegativeInteger }
+  & attribute table:data-type {
+      "text" | "number" | "automatic" | \string
     }?
-  & common-writing-mode-attlist
-  & attribute draw:frame-display-scrollbar { boolean }?
-  & attribute draw:frame-display-border { boolean }?
-  & attribute draw:frame-margin-horizontal { nonNegativePixelLength }?
-  & attribute draw:frame-margin-vertical { nonNegativePixelLength }?
-  & attribute draw:visible-area-left { nonNegativeLength }?
-  & attribute draw:visible-area-top { nonNegativeLength }?
-  & attribute draw:visible-area-width { positiveLength }?
-  & attribute draw:visible-area-height { positiveLength }?
-  & attribute draw:draw-aspect {
-      "content" | "thumbnail" | "icon" | "print-view"
+  & attribute table:order { "ascending" | "descending" }?
+table-sort-groups =
+  element table:sort-groups { table-sort-groups-attlist, empty }
+table-sort-groups-attlist =
+  attribute table:data-type {
+    "text" | "number" | "automatic" | \string
+  }?
+  & attribute table:order { "ascending" | "descending" }?
+table-source-cell-range =
+  element table:source-cell-range {
+    table-source-cell-range-attlist, table-filter?
+  }
+table-source-cell-range-attlist =
+  # OFFICE-3665
+  (attribute table:cell-range-address { cellRangeAddress }
+   | (attribute table:name { \string },
+      attribute table:cell-range-address { cellRangeAddress }?))
+table-source-range-address =
+  element table:source-range-address {
+    common-table-range-attlist, empty
+  }
+table-source-service =
+  element table:source-service { table-source-service-attlist, empty }
+table-source-service-attlist =
+  attribute table:name { \string }
+  & attribute table:source-name { \string }
+  & attribute table:object-name { \string }
+  & attribute table:user-name { \string }?
+  & attribute table:password { \string }?
+table-subtotal-field =
+  element table:subtotal-field { table-subtotal-field-attlist, empty }
+table-subtotal-field-attlist =
+  attribute table:field-number { nonNegativeInteger }
+  & attribute table:function {
+      "average"
+      | "count"
+      | "countnums"
+      | "max"
+      | "min"
+      | "product"
+      | "stdev"
+      | "stdevp"
+      | "sum"
+      | "var"
+      | "varp"
+      | \string
+    }
+table-subtotal-rule =
+  element table:subtotal-rule {
+    table-subtotal-rule-attlist, table-subtotal-field*
+  }
+table-subtotal-rule-attlist =
+  attribute table:group-by-field-number { nonNegativeInteger }
+table-subtotal-rules =
+  element table:subtotal-rules {
+    table-subtotal-rules-attlist,
+    table-sort-groups?,
+    table-subtotal-rule*
+  }
+table-subtotal-rules-attlist =
+  attribute table:bind-styles-to-content { boolean }?
+  & attribute table:case-sensitive { boolean }?
+  & attribute table:page-breaks-on-group-change { boolean }?
+table-table =
+  element table:table {
+    table-table-attlist,
+    table-title?,
+    table-desc?,
+    table-table-source?,
+    office-dde-source?,
+    table-scenario?,
+    office-forms?,
+    table-shapes?,
+    table-columns-and-groups,
+    table-rows-and-groups,
+    table-named-expressions?
+  }
+table-table-attlist =
+  attribute table:name { \string }?
+  & attribute table:style-name { styleNameRef }?
+  & attribute table:template-name { \string }?
+  & attribute table:use-first-row-styles { boolean }?
+  & attribute table:use-last-row-styles { boolean }?
+  & attribute table:use-first-column-styles { boolean }?
+  & attribute table:use-last-column-styles { boolean }?
+  & attribute table:use-banding-rows-styles { boolean }?
+  & attribute table:use-banding-columns-styles { boolean }?
+  & attribute table:protected { boolean }?
+  & attribute table:protection-key { \string }?
+  & attribute table:protection-key-digest-algorithm { anyIRI }?
+  & attribute table:print { boolean }?
+  & attribute table:print-ranges { cellRangeAddressList }?
+  & xml-id?
+  & attribute table:is-sub-table { boolean }?
+table-table-cell =
+  element table:table-cell {
+    table-table-cell-attlist,
+    table-table-cell-attlist-extra,
+    table-table-cell-content
+  }
+table-table-cell-attlist =
+  attribute table:number-columns-repeated { positiveInteger }?
+  & attribute table:style-name { styleNameRef }?
+  & attribute table:content-validation-name { \string }?
+  & attribute table:formula { \string }?
+  & common-value-and-type-attlist?
+  & attribute table:protect { boolean }?
+  & attribute table:protected { boolean }?
+  & xml-id?
+  & common-in-content-meta-attlist?
+table-table-cell-attlist-extra =
+  attribute table:number-columns-spanned { positiveInteger }?
+  & attribute table:number-rows-spanned { positiveInteger }?
+  & attribute table:number-matrix-columns-spanned { positiveInteger }?
+  & attribute table:number-matrix-rows-spanned { positiveInteger }?
+table-table-cell-content =
+  table-cell-range-source?,
+  office-annotation?,
+  table-detective?,
+  text-content*
+table-table-cell-range-source-attlist =
+  attribute table:name { \string }
+  & attribute table:last-column-spanned { positiveInteger }
+  & attribute table:last-row-spanned { positiveInteger }
+table-table-column =
+  element table:table-column { table-table-column-attlist, empty }
+table-table-column-attlist =
+  attribute table:number-columns-repeated { positiveInteger }?
+  & attribute table:style-name { styleNameRef }?
+  & attribute table:visibility { table-visibility-value }?
+  & attribute table:default-cell-style-name { styleNameRef }?
+  & xml-id?
+table-table-column-group =
+  element table:table-column-group {
+    table-table-column-group-attlist, table-columns-and-groups
+  }
+table-table-column-group-attlist = attribute table:display { boolean }?
+table-table-columns =
+  element table:table-columns { table-table-column+ }
+table-table-header-columns =
+  element table:table-header-columns { table-table-column+ }
+table-table-header-rows =
+  element table:table-header-rows {
+    (text-soft-page-break?, table-table-row)+
+  }
+table-table-row =
+  element table:table-row {
+    table-table-row-attlist,
+    (table-table-cell | table-covered-table-cell)+
+  }
+table-table-row-attlist =
+  attribute table:number-rows-repeated { positiveInteger }?
+  & attribute table:style-name { styleNameRef }?
+  & attribute table:default-cell-style-name { styleNameRef }?
+  & attribute table:visibility { table-visibility-value }?
+  & xml-id?
+table-table-row-group =
+  element table:table-row-group {
+    table-table-row-group-attlist, table-rows-and-groups
+  }
+table-table-row-group-attlist = attribute table:display { boolean }?
+table-table-rows =
+  element table:table-rows { (text-soft-page-break?, table-table-row)+ }
+table-table-source =
+  element table:table-source {
+    table-table-source-attlist, table-linked-source-attlist, empty
+  }
+table-table-source-attlist =
+  attribute table:mode { "copy-all" | "copy-results-only" }?
+  & attribute table:table-name { \string }?
+table-table-template =
+  element table:table-template {
+    table-table-template-attlist,
+    table-first-row?,
+    table-last-row?,
+    table-first-column?,
+    table-last-column?,
+    table-body,
+    table-even-rows?,
+    table-odd-rows?,
+    table-even-columns?,
+    table-odd-columns?,
+    table-background?
+  }
+table-table-template-attlist =
+  attribute table:name { \string }
+  & attribute table:first-row-start-column { rowOrCol }
+  & attribute table:first-row-end-column { rowOrCol }
+  & attribute table:last-row-start-column { rowOrCol }
+  & attribute table:last-row-end-column { rowOrCol }
+table-target-range-address =
+  element table:target-range-address {
+    common-table-range-attlist, empty
+  }
+table-title = element table:title { text }
+table-tracked-changes =
+  element table:tracked-changes {
+    table-tracked-changes-attlist,
+    (table-cell-content-change
+     | table-insertion
+     | table-deletion
+     | table-movement)*
+  }
+table-tracked-changes-attlist =
+  attribute table:track-changes { boolean }?
+table-validation-attlist =
+  attribute table:name { \string }
+  & attribute table:condition { \string }?
+  & attribute table:base-cell-address { cellAddress }?
+  & attribute table:allow-empty-cell { boolean }?
+  & attribute table:display-list {
+      "none" | "unsorted" | "sort-ascending"
     }?
-  & attribute draw:ole-draw-aspect { nonNegativeInteger }?
-style-graphic-fill-properties-attlist =
-  attribute draw:fill {
-    "none" | "solid" | "bitmap" | "gradient" | "hatch"
+table-visibility-value = "visible" | "collapse" | "filter"
+target-frame = attribute office:target-frame { targetFrameName }?
+target-location = attribute xlink:href { anyIRI }?
+targetFrameName = "_self" | "_blank" | "_parent" | "_top" | \string
+text-a =
+  element text:a {
+    text-a-attlist, office-event-listeners?, paragraph-content*
+  }
+text-a-attlist =
+  attribute office:name { \string }?
+  & attribute office:title { \string }?
+  & attribute xlink:type { "simple" }
+  & attribute xlink:href { anyIRI }
+  & attribute xlink:actuate { "onRequest" }?
+  & attribute office:target-frame-name { targetFrameName }?
+  & attribute xlink:show { "new" | "replace" }?
+  & attribute text:style-name { styleNameRef }?
+  & attribute text:visited-style-name { styleNameRef }?
+text-alphabetical-index =
+  element text:alphabetical-index {
+    common-section-attlist,
+    text-alphabetical-index-source,
+    text-index-body
+  }
+text-alphabetical-index-auto-mark-file =
+  element text:alphabetical-index-auto-mark-file {
+    attribute xlink:type { "simple" },
+    attribute xlink:href { anyIRI }
+  }
+text-alphabetical-index-entry-template =
+  element text:alphabetical-index-entry-template {
+    text-alphabetical-index-entry-template-attrs,
+    (text-index-entry-chapter
+     | text-index-entry-page-number
+     | text-index-entry-text
+     | text-index-entry-span
+     | text-index-entry-tab-stop)*
+  }
+text-alphabetical-index-entry-template-attrs =
+  attribute text:outline-level { "1" | "2" | "3" | "separator" }
+  & attribute text:style-name { styleNameRef }
+text-alphabetical-index-mark-attrs =
+  attribute text:key1 { \string }?
+  & attribute text:key2 { \string }?
+  & attribute text:string-value-phonetic { \string }?
+  & attribute text:key1-phonetic { \string }?
+  & attribute text:key2-phonetic { \string }?
+  & attribute text:main-entry { boolean }?
+text-alphabetical-index-source =
+  element text:alphabetical-index-source {
+    text-alphabetical-index-source-attrs,
+    text-index-title-template?,
+    text-alphabetical-index-entry-template*
+  }
+text-alphabetical-index-source-attrs =
+  text-index-scope-attr
+  & text-relative-tab-stop-position-attr
+  & attribute text:ignore-case { boolean }?
+  & attribute text:main-entry-style-name { styleNameRef }?
+  & attribute text:alphabetical-separators { boolean }?
+  & attribute text:combine-entries { boolean }?
+  & attribute text:combine-entries-with-dash { boolean }?
+  & attribute text:combine-entries-with-pp { boolean }?
+  & attribute text:use-keys-as-entries { boolean }?
+  & attribute text:capitalize-entries { boolean }?
+  & attribute text:comma-separated { boolean }?
+  & attribute fo:language { languageCode }?
+  & attribute fo:country { countryCode }?
+  & attribute fo:script { scriptCode }?
+  & attribute style:rfc-language-tag { language }?
+  & attribute text:sort-algorithm { \string }?
+text-bibliography =
+  element text:bibliography {
+    common-section-attlist, text-bibliography-source, text-index-body
+  }
+text-bibliography-configuration =
+  element text:bibliography-configuration {
+    text-bibliography-configuration-attlist, text-sort-key*
+  }
+text-bibliography-configuration-attlist =
+  attribute text:prefix { \string }?
+  & attribute text:suffix { \string }?
+  & attribute text:numbered-entries { boolean }?
+  & attribute text:sort-by-position { boolean }?
+  & attribute fo:language { languageCode }?
+  & attribute fo:country { countryCode }?
+  & attribute fo:script { scriptCode }?
+  & attribute style:rfc-language-tag { language }?
+  & attribute text:sort-algorithm { \string }?
+text-bibliography-entry-template =
+  element text:bibliography-entry-template {
+    text-bibliography-entry-template-attrs,
+    (text-index-entry-span
+     | text-index-entry-tab-stop
+     | text-index-entry-bibliography)*
+  }
+text-bibliography-entry-template-attrs =
+  attribute text:bibliography-type { text-bibliography-types }
+  & attribute text:style-name { styleNameRef }
+text-bibliography-source =
+  element text:bibliography-source {
+    text-index-title-template?, text-bibliography-entry-template*
+  }
+text-bibliography-types =
+  "article"
+  | "book"
+  | "booklet"
+  | "conference"
+  | "custom1"
+  | "custom2"
+  | "custom3"
+  | "custom4"
+  | "custom5"
+  | "email"
+  | "inbook"
+  | "incollection"
+  | "inproceedings"
+  | "journal"
+  | "manual"
+  | "mastersthesis"
+  | "misc"
+  | "phdthesis"
+  | "proceedings"
+  | "techreport"
+  | "unpublished"
+  | "www"
+text-bookmark = element text:bookmark { text-bookmark-attlist, empty }
+text-bookmark-attlist =
+  attribute text:name { \string }
+  & xml-id?
+text-bookmark-end =
+  element text:bookmark-end { text-bookmark-end-attlist, empty }
+text-bookmark-end-attlist = attribute text:name { \string }
+text-bookmark-ref-content =
+  attribute text:reference-format {
+    common-ref-format-values
+    | "number-no-superior"
+    | "number-all-superior"
+    | "number"
   }?
-  & attribute draw:fill-color { color }?
-  & attribute draw:secondary-fill-color { color }?
-  & attribute draw:fill-gradient-name { styleNameRef }?
-  & attribute draw:gradient-step-count { nonNegativeInteger }?
-  & attribute draw:fill-hatch-name { styleNameRef }?
-  & attribute draw:fill-hatch-solid { boolean }?
-  & attribute draw:fill-image-name { styleNameRef }?
-  & attribute style:repeat { "no-repeat" | "repeat" | "stretch" }?
-  & attribute draw:fill-image-width { length | percent }?
-  & attribute draw:fill-image-height { length | percent }?
-  & attribute draw:fill-image-ref-point-x { percent }?
-  & attribute draw:fill-image-ref-point-y { percent }?
-  & attribute draw:fill-image-ref-point {
-      "top-left"
-      | "top"
-      | "top-right"
-      | "left"
-      | "center"
-      | "right"
-      | "bottom-left"
-      | "bottom"
-      | "bottom-right"
-    }?
-  & attribute draw:tile-repeat-offset {
-      list { zeroToHundredPercent, ("horizontal" | "vertical") }
+text-bookmark-start =
+  element text:bookmark-start { text-bookmark-start-attlist, empty }
+text-bookmark-start-attlist =
+  attribute text:name { \string }
+  & xml-id?
+  & common-in-content-meta-attlist?
+text-changed-region =
+  element text:changed-region {
+    text-changed-region-attr, text-changed-region-content
+  }
+text-changed-region-attr =
+  xml-id,
+  attribute text:id { NCName }?
+text-changed-region-content =
+  element text:insertion { office-change-info }
+  | element text:deletion { office-change-info, text-content* }
+  | element text:format-change { office-change-info }
+text-chapter-attlist =
+  attribute text:display {
+    "name"
+    | "number"
+    | "number-and-name"
+    | "plain-number-and-name"
+    | "plain-number"
+  }
+  & attribute text:outline-level { nonNegativeInteger }
+text-common-ref-content =
+  text
+  & attribute text:ref-name { \string }?
+text-conditional-text-attlist =
+  attribute text:condition { \string }
+  & attribute text:string-value-if-true { \string }
+  & attribute text:string-value-if-false { \string }
+  & attribute text:current-value { boolean }?
+text-content =
+  text-h
+  | text-p
+  | text-list
+  | text-numbered-paragraph
+  | table-table
+  | text-section
+  | text-soft-page-break
+  | text-table-of-content
+  | text-illustration-index
+  | text-table-index
+  | text-object-index
+  | text-user-index
+  | text-alphabetical-index
+  | text-bibliography
+  | shape
+  | change-marks
+text-database-display-attlist =
+  common-field-database-table
+  & common-field-data-style-name-attlist
+  & attribute text:column-name { \string }
+text-database-next-attlist =
+  common-field-database-table
+  & attribute text:condition { \string }?
+text-database-row-select-attlist =
+  common-field-database-table
+  & attribute text:condition { \string }?
+  & attribute text:row-number { nonNegativeInteger }?
+text-date-attlist =
+  (common-field-fixed-attlist & common-field-data-style-name-attlist)
+  & attribute text:date-value { dateOrDateTime }?
+  & attribute text:date-adjust { duration }?
+text-dde-connection-decl =
+  element text:dde-connection-decl {
+    text-dde-connection-decl-attlist, common-dde-connection-decl-attlist
+  }
+text-dde-connection-decl-attlist = attribute office:name { \string }
+text-decls =
+  element text:variable-decls { text-variable-decl* }?,
+  element text:sequence-decls { text-sequence-decl* }?,
+  element text:user-field-decls { text-user-field-decl* }?,
+  element text:dde-connection-decls { text-dde-connection-decl* }?,
+  text-alphabetical-index-auto-mark-file?
+text-drop-down =
+  element text:drop-down {
+    attribute text:name { \string },
+    element text:label {
+      attribute text:value { \string }?,
+      attribute text:current-selected { boolean }?
+    }*,
+    text
+  }
+text-file-name-attlist =
+  attribute text:display {
+    "full" | "path" | "name" | "name-and-extension"
+  }?
+  & common-field-fixed-attlist
+text-get-page-variable-attlist = common-field-num-format-attlist
+text-h =
+  element text:h {
+    heading-attrs,
+    paragraph-attrs,
+    text-number?,
+    paragraph-content-or-hyperlink*
+  }
+text-hidden-paragraph-attlist =
+  attribute text:condition { \string }
+  & attribute text:is-hidden { boolean }?
+text-hidden-text-attlist =
+  attribute text:condition { \string }
+  & attribute text:string-value { \string }
+  & attribute text:is-hidden { boolean }?
+text-id = attribute text:id { \string }
+text-illustration-index =
+  element text:illustration-index {
+    common-section-attlist,
+    text-illustration-index-source,
+    text-index-body
+  }
+text-illustration-index-entry-content =
+  text-illustration-index-entry-template-attrs,
+  (text-index-entry-chapter
+   | text-index-entry-page-number
+   | text-index-entry-text
+   | text-index-entry-span
+   | text-index-entry-tab-stop
+   | text-index-entry-link-start
+   | text-index-entry-link-end
+     # https://issues.oasis-open.org/browse/OFFICE-3941
+     )*
+text-illustration-index-entry-template =
+  element text:illustration-index-entry-template {
+    text-illustration-index-entry-content
+  }
+text-illustration-index-entry-template-attrs =
+  attribute text:style-name { styleNameRef }
+text-illustration-index-source =
+  element text:illustration-index-source {
+    text-illustration-index-source-attrs,
+    text-index-title-template?,
+    text-illustration-index-entry-template?
+  }
+text-illustration-index-source-attrs =
+  text-index-scope-attr
+  & text-relative-tab-stop-position-attr
+  & attribute text:use-caption { boolean }?
+  & attribute text:caption-sequence-name { \string }?
+  & attribute text:caption-sequence-format {
+      "text" | "category-and-value" | "caption"
     }?
-  & attribute draw:opacity { zeroToHundredPercent }?
-  & attribute draw:opacity-name { styleNameRef }?
-  & attribute svg:fill-rule { "nonzero" | "evenodd" }?
-style-graphic-properties-elements =
-  text-list-style? & style-background-image & style-columns
-common-vertical-pos-attlist =
-  attribute style:vertical-pos {
-    "top" | "middle" | "bottom" | "from-top" | "below"
-  }?,
-  attribute svg:y { coordinate }?
-common-vertical-rel-attlist =
-  attribute style:vertical-rel {
-    "page"
-    | "page-content"
-    | "frame"
-    | "frame-content"
-    | "paragraph"
-    | "paragraph-content"
-    | "char"
-    | "line"
-    | "baseline"
-    | "text"
+text-index-body = element text:index-body { index-content-main* }
+text-index-entry-bibliography =
+  element text:index-entry-bibliography {
+    text-index-entry-bibliography-attrs
+  }
+text-index-entry-bibliography-attrs =
+  attribute text:style-name { styleNameRef }?
+  & attribute text:bibliography-data-field {
+      "address"
+      | "annote"
+      | "author"
+      | "bibliography-type"
+      | "booktitle"
+      | "chapter"
+      | "custom1"
+      | "custom2"
+      | "custom3"
+      | "custom4"
+      | "custom5"
+      | "edition"
+      | "editor"
+      | "howpublished"
+      | "identifier"
+      | "institution"
+      | "isbn"
+      | "issn"
+      | "journal"
+      | "month"
+      | "note"
+      | "number"
+      | "organizations"
+      | "pages"
+      | "publisher"
+      | "report-type"
+      | "school"
+      | "series"
+      | "title"
+      | "url"
+      | "volume"
+      | "year"
+    }
+text-index-entry-chapter =
+  element text:index-entry-chapter {
+    attribute text:style-name { styleNameRef }?,
+    text-index-entry-chapter-attrs
+  }
+text-index-entry-chapter-attrs =
+  attribute text:display {
+    "name"
+    | "number"
+    | "number-and-name"
+    | "plain-number"
+    | "plain-number-and-name"
   }?
-common-editable-attlist = attribute style:editable { boolean }?
-horizontal-mirror =
-  "horizontal" | "horizontal-on-odd" | "horizontal-on-even"
-clipShape =
-  xsd:string {
-    pattern =
-      "rect\([ 
]*((-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)))|(auto))([ ]*,[ 
]*((-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc))))|(auto)){3}[ ]*\)"
+  & attribute text:outline-level { positiveInteger }?
+text-index-entry-link-end =
+  element text:index-entry-link-end {
+    attribute text:style-name { styleNameRef }?
   }
-nonNegativePixelLength =
-  xsd:string { pattern = "([0-9]+(\.[0-9]*)?|\.[0-9]+)(px)" }
-style-chart-properties =
-  element style:chart-properties {
-    style-chart-properties-content-strict
+text-index-entry-link-start =
+  element text:index-entry-link-start {
+    attribute text:style-name { styleNameRef }?
   }
-style-chart-properties-content-strict =
-  style-chart-properties-attlist, style-chart-properties-elements
-style-chart-properties-elements = empty
-style-chart-properties-attlist =
-  attribute chart:scale-text { boolean }?
-  & attribute chart:three-dimensional { boolean }?
-  & attribute chart:deep { boolean }?
-  & attribute chart:right-angled-axes { boolean }?
-  & (attribute chart:symbol-type { "none" }
-     | attribute chart:symbol-type { "automatic" }
-     | (attribute chart:symbol-type { "named-symbol" },
-        attribute chart:symbol-name {
-          "square"
-          | "diamond"
-          | "arrow-down"
-          | "arrow-up"
-          | "arrow-right"
-          | "arrow-left"
-          | "bow-tie"
-          | "hourglass"
-          | "circle"
-          | "star"
-          | "x"
-          | "plus"
-          | "asterisk"
-          | "horizontal-bar"
-          | "vertical-bar"
-        })
-     | (attribute chart:symbol-type { "image" },
-        element chart:symbol-image {
-          attribute xlink:href { anyIRI }
-        })
-     | empty)
-  & attribute chart:symbol-width { nonNegativeLength }?
-  & attribute chart:symbol-height { nonNegativeLength }?
-  & attribute chart:sort-by-x-values { boolean }?
-  & attribute chart:vertical { boolean }?
-  & attribute chart:connect-bars { boolean }?
-  & attribute chart:gap-width { integer }?
-  & attribute chart:overlap { integer }?
-  & attribute chart:group-bars-per-axis { boolean }?
-  & attribute chart:japanese-candle-stick { boolean }?
-  & attribute chart:interpolation {
-      "none" | "cubic-spline" | "b-spline"
-    }?
-  & attribute chart:spline-order { positiveInteger }?
-  & attribute chart:spline-resolution { positiveInteger }?
-  & attribute chart:pie-offset { nonNegativeInteger }?
-  & attribute chart:angle-offset { angle }?
-  & attribute chart:hole-size { percent }?
-  & attribute chart:lines { boolean }?
-  & attribute chart:solid-type {
-      "cuboid" | "cylinder" | "cone" | "pyramid"
-    }?
-  & attribute chart:stacked { boolean }?
-  & attribute chart:percentage { boolean }?
-  & attribute chart:treat-empty-cells {
-      "use-zero" | "leave-gap" | "ignore"
-    }?
-  & attribute chart:link-data-style-to-source { boolean }?
-  & attribute chart:logarithmic { boolean }?
-  & attribute chart:maximum { double }?
-  & attribute chart:minimum { double }?
-  & attribute chart:origin { double }?
-  & attribute chart:interval-major { double }?
-  & attribute chart:interval-minor-divisor { positiveInteger }?
-  & attribute chart:tick-marks-major-inner { boolean }?
-  & attribute chart:tick-marks-major-outer { boolean }?
-  & attribute chart:tick-marks-minor-inner { boolean }?
-  & attribute chart:tick-marks-minor-outer { boolean }?
-  & attribute chart:reverse-direction { boolean }?
-  & attribute chart:display-label { boolean }?
-  & attribute chart:text-overlap { boolean }?
-  & attribute text:line-break { boolean }?
-  & attribute chart:label-arrangement {
-      "side-by-side" | "stagger-even" | "stagger-odd"
-    }?
-  & common-style-direction-attlist
-  & common-rotation-angle-attlist
-  & attribute chart:data-label-number {
-      "none" | "value" | "percentage" | "value-and-percentage"
-    }?
-  & attribute chart:data-label-text { boolean }?
-  & attribute chart:data-label-symbol { boolean }?
-  & element chart:label-separator { text-p }?
-  & attribute chart:label-position { labelPositions }?
-  & attribute chart:label-position-negative { labelPositions }?
-  & attribute chart:visible { boolean }?
-  & attribute chart:auto-position { boolean }?
-  & attribute chart:auto-size { boolean }?
-  & attribute chart:mean-value { boolean }?
-  & attribute chart:error-category {
-      "none"
-      | "variance"
-      | "standard-deviation"
-      | "percentage"
-      | "error-margin"
-      | "constant"
-      | "standard-error"
-      | "cell-range"
-    }?
-  & attribute chart:error-percentage { double }?
-  & attribute chart:error-margin { double }?
-  & attribute chart:error-lower-limit { double }?
-  & attribute chart:error-upper-limit { double }?
-  & attribute chart:error-upper-indicator { boolean }?
-  & attribute chart:error-lower-indicator { boolean }?
-  & attribute chart:error-lower-range { cellRangeAddressList }?
-  & attribute chart:error-upper-range { cellRangeAddressList }?
-  & attribute chart:series-source { "columns" | "rows" }?
-  & attribute chart:regression-type {
-      "none" | "linear" | "logarithmic" | "exponential" | "power"
-    }?
-  & attribute chart:axis-position { "start" | "end" | double }?
-  & attribute chart:axis-label-position {
-      "near-axis"
-      | "near-axis-other-side"
-      | "outside-start"
-      | "outside-end"
+text-index-entry-page-number =
+  element text:index-entry-page-number {
+    attribute text:style-name { styleNameRef }?
+  }
+text-index-entry-span =
+  element text:index-entry-span {
+    attribute text:style-name { styleNameRef }?,
+    text
+  }
+text-index-entry-tab-stop =
+  element text:index-entry-tab-stop {
+    attribute text:style-name { styleNameRef }?,
+    text-index-entry-tab-stop-attrs
+  }
+text-index-entry-tab-stop-attrs =
+  attribute style:leader-char { character }?
+  & (attribute style:type { "right" }
+     | (attribute style:type { "left" },
+        attribute style:position { length }))
+text-index-entry-text =
+  element text:index-entry-text {
+    attribute text:style-name { styleNameRef }?
+  }
+text-index-name = attribute text:index-name { \string }
+text-index-scope-attr =
+  attribute text:index-scope { "document" | "chapter" }?
+text-index-source-style =
+  element text:index-source-style {
+    attribute text:style-name { styleNameRef },
+    empty
+  }
+# https://issues.oasis-open.org/browse/OFFICE-3675
+text-index-source-styles =
+  element text:index-source-styles {
+    attribute text:outline-level { positiveInteger },
+    text-index-source-style*
+  }
+text-index-title =
+  element text:index-title {
+    common-section-attlist, index-content-main*
+  }
+text-index-title-template =
+  element text:index-title-template {
+    attribute text:style-name { styleNameRef }?,
+    text
+  }
+text-linenumbering-configuration =
+  element text:linenumbering-configuration {
+    text-linenumbering-configuration-attlist,
+    text-linenumbering-separator?
+  }
+text-linenumbering-configuration-attlist =
+  attribute text:number-lines { boolean }?
+  & common-num-format-attlist?
+  & attribute text:style-name { styleNameRef }?
+  & attribute text:increment { nonNegativeInteger }?
+  & attribute text:number-position {
+      "left" | "right" | "inner" | "outer"
     }?
-  & attribute chart:tick-mark-position {
-      "at-labels" | "at-axis" | "at-labels-and-axis"
+  & attribute text:offset { nonNegativeLength }?
+  & attribute text:count-empty-lines { boolean }?
+  & attribute text:count-in-text-boxes { boolean }?
+  & attribute text:restart-on-page { boolean }?
+text-linenumbering-separator =
+  element text:linenumbering-separator {
+    attribute text:increment { nonNegativeInteger }?,
+    text
+  }
+text-list =
+  element text:list {
+    text-list-attr, text-list-header?, text-list-item*
+  }
+text-list-attr =
+  attribute text:style-name { styleNameRef }?
+  & attribute text:continue-numbering { boolean }?
+  & attribute text:continue-list { IDREF }?
+  & xml-id?
+text-list-header =
+  element text:list-header {
+    text-list-header-attr, text-list-item-content
+  }
+text-list-header-attr = xml-id?
+text-list-item =
+  element text:list-item { text-list-item-attr, text-list-item-content }
+text-list-item-attr =
+  attribute text:start-value { nonNegativeInteger }?
+  & attribute text:style-override { styleNameRef }?
+  & xml-id?
+text-list-item-content =
+  text-number?, (text-p | text-h | text-list | text-soft-page-break)*
+text-list-level-style-attr = attribute text:level { positiveInteger }
+text-list-level-style-bullet-attr =
+  attribute text:style-name { styleNameRef }?
+  & attribute text:bullet-char { character }
+  & common-num-format-prefix-suffix-attlist
+  & attribute text:bullet-relative-size { percent }?
+text-list-level-style-image-attr =
+  common-draw-data-attlist | office-binary-data
+text-list-level-style-number-attr =
+  attribute text:style-name { styleNameRef }?
+  & common-num-format-attlist
+  & common-num-format-prefix-suffix-attlist
+  & attribute text:display-levels { positiveInteger }?
+  & attribute text:start-value { positiveInteger }?
+text-list-style =
+  element text:list-style {
+    text-list-style-attr, text-list-style-content*
+  }
+text-list-style-attr =
+  attribute style:name { styleName }
+  & attribute style:display-name { \string }?
+  & attribute text:consecutive-numbering { boolean }?
+text-list-style-content =
+  element text:list-level-style-number {
+    text-list-level-style-attr,
+    text-list-level-style-number-attr,
+    style-list-level-properties?,
+    style-text-properties?
+  }
+  | element text:list-level-style-bullet {
+      text-list-level-style-attr,
+      text-list-level-style-bullet-attr,
+      style-list-level-properties?,
+      style-text-properties?
+    }
+  | element text:list-level-style-image {
+      text-list-level-style-attr,
+      text-list-level-style-image-attr,
+      style-list-level-properties?
+    }
+text-meta-attlist = common-in-content-meta-attlist? & xml-id?
+text-meta-field-attlist = xml-id & common-field-data-style-name-attlist
+text-note-class = attribute text:note-class { "footnote" | "endnote" }
+text-note-ref-content =
+  attribute text:reference-format { common-ref-format-values }?
+  & text-note-class
+text-notes-configuration =
+  element text:notes-configuration { text-notes-configuration-content }
+text-notes-configuration-content =
+  text-note-class
+  & attribute text:citation-style-name { styleNameRef }?
+  & attribute text:citation-body-style-name { styleNameRef }?
+  & attribute text:default-style-name { styleNameRef }?
+  & attribute text:master-page-name { styleNameRef }?
+  & attribute text:start-value { nonNegativeInteger }?
+  & common-num-format-prefix-suffix-attlist
+  & common-num-format-attlist?
+  & attribute text:start-numbering-at {
+      "document" | "chapter" | "page"
     }?
-  & attribute chart:include-hidden-cells { boolean }?
-labelPositions =
-  "avoid-overlap"
-  | "center"
-  | "top"
-  | "top-right"
-  | "right"
-  | "bottom-right"
-  | "bottom"
-  | "bottom-left"
-  | "left"
-  | "top-left"
-  | "inside"
-  | "outside"
-  | "near-origin"
-style-drawing-page-properties-attlist =
-  attribute presentation:transition-type {
-    "manual" | "automatic" | "semi-automatic"
-  }?
-  & attribute presentation:transition-style {
-      "none"
-      | "fade-from-left"
-      | "fade-from-top"
-      | "fade-from-right"
-      | "fade-from-bottom"
-      | "fade-from-upperleft"
-      | "fade-from-upperright"
-      | "fade-from-lowerleft"
-      | "fade-from-lowerright"
-      | "move-from-left"
-      | "move-from-top"
-      | "move-from-right"
-      | "move-from-bottom"
-      | "move-from-upperleft"
-      | "move-from-upperright"
-      | "move-from-lowerleft"
-      | "move-from-lowerright"
-      | "uncover-to-left"
-      | "uncover-to-top"
-      | "uncover-to-right"
-      | "uncover-to-bottom"
-      | "uncover-to-upperleft"
-      | "uncover-to-upperright"
-      | "uncover-to-lowerleft"
-      | "uncover-to-lowerright"
-      | "fade-to-center"
-      | "fade-from-center"
-      | "vertical-stripes"
-      | "horizontal-stripes"
-      | "clockwise"
-      | "counterclockwise"
-      | "open-vertical"
-      | "open-horizontal"
-      | "close-vertical"
-      | "close-horizontal"
-      | "wavyline-from-left"
-      | "wavyline-from-top"
-      | "wavyline-from-right"
-      | "wavyline-from-bottom"
-      | "spiralin-left"
-      | "spiralin-right"
-      | "spiralout-left"
-      | "spiralout-right"
-      | "roll-from-top"
-      | "roll-from-left"
-      | "roll-from-right"
-      | "roll-from-bottom"
-      | "stretch-from-left"
-      | "stretch-from-top"
-      | "stretch-from-right"
-      | "stretch-from-bottom"
-      | "vertical-lines"
-      | "horizontal-lines"
-      | "dissolve"
-      | "random"
-      | "vertical-checkerboard"
-      | "horizontal-checkerboard"
-      | "interlocking-horizontal-left"
-      | "interlocking-horizontal-right"
-      | "interlocking-vertical-top"
-      | "interlocking-vertical-bottom"
-      | "fly-away"
-      | "open"
-      | "close"
-      | "melt"
+  & attribute text:footnotes-position {
+      "text" | "page" | "section" | "document"
     }?
-  & attribute presentation:transition-speed { presentationSpeeds }?
-  & attribute smil:type { \string }?
-  & attribute smil:subtype { \string }?
-  & attribute smil:direction { "forward" | "reverse" }?
-  & attribute smil:fadeColor { color }?
-  & attribute presentation:duration { duration }?
-  & attribute presentation:visibility { "visible" | "hidden" }?
-  & attribute draw:background-size { "full" | "border" }?
-  & attribute presentation:background-objects-visible { boolean }?
-  & attribute presentation:background-visible { boolean }?
-  & attribute presentation:display-header { boolean }?
-  & attribute presentation:display-footer { boolean }?
-  & attribute presentation:display-page-number { boolean }?
-  & attribute presentation:display-date-time { boolean }?
-style-drawing-page-properties-elements = presentation-sound?
-\string = xsd:string
-date = xsd:date
-time = xsd:time
-dateTime = xsd:dateTime
-duration = xsd:duration
-integer = xsd:integer
-nonNegativeInteger = xsd:nonNegativeInteger
-positiveInteger = xsd:positiveInteger
-double = xsd:double
-anyURI = xsd:anyURI
-base64Binary = xsd:base64Binary
-ID = xsd:ID
-IDREF = xsd:IDREF
-IDREFS = xsd:IDREFS
-NCName = xsd:NCName
-boolean = "true" | "false"
-dateOrDateTime = xsd:date | xsd:dateTime
-timeOrDateTime = xsd:time | xsd:dateTime
-language = xsd:language
-countryCode = xsd:token { pattern = "[A-Za-z0-9]{1,8}" }
-languageCode = xsd:token { pattern = "[A-Za-z]{1,8}" }
-scriptCode = xsd:token { pattern = "[A-Za-z0-9]{1,8}" }
-character = xsd:string { length = "1" }
-length =
-  xsd:string {
-    pattern =
-      "-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)|(px))"
+  & element text:note-continuation-notice-forward { text }?
+  & element text:note-continuation-notice-backward { text }?
+text-number = element text:number { \string }
+text-numbered-paragraph =
+  element text:numbered-paragraph {
+    text-numbered-paragraph-attr, text-number?, (text-p | text-h)
+  }
+text-numbered-paragraph-attr =
+  attribute text:list-id { NCName }
+  & attribute text:level { positiveInteger }?
+  & (attribute text:style-name { styleNameRef },
+     attribute text:continue-numbering { boolean },
+     attribute text:start-value { nonNegativeInteger })?
+  & xml-id?
+text-object-index =
+  element text:object-index {
+    common-section-attlist, text-object-index-source, text-index-body
+  }
+text-object-index-entry-template =
+  element text:object-index-entry-template {
+    text-illustration-index-entry-content
+  }
+text-object-index-source =
+  element text:object-index-source {
+    text-object-index-source-attrs,
+    text-index-title-template?,
+    text-object-index-entry-template?
+  }
+text-object-index-source-attrs =
+  text-index-scope-attr
+  & text-relative-tab-stop-position-attr
+  & attribute text:use-spreadsheet-objects { boolean }?
+  & attribute text:use-math-objects { boolean }?
+  & attribute text:use-draw-objects { boolean }?
+  & attribute text:use-chart-objects { boolean }?
+  & attribute text:use-other-objects { boolean }?
+text-outline-level = attribute text:outline-level { positiveInteger }?
+text-outline-level-style =
+  element text:outline-level-style {
+    text-outline-level-style-attlist,
+    style-list-level-properties?,
+    style-text-properties?
+  }
+text-outline-level-style-attlist =
+  attribute text:level { positiveInteger }
+  & attribute text:style-name { styleNameRef }?
+  & common-num-format-attlist
+  & common-num-format-prefix-suffix-attlist
+  & attribute text:display-levels { positiveInteger }?
+  & attribute text:start-value { positiveInteger }?
+text-outline-style =
+  element text:outline-style {
+    text-outline-style-attr, text-outline-level-style+
+  }
+text-outline-style-attr = attribute style:name { styleName }
+text-p =
+  element text:p { paragraph-attrs, paragraph-content-or-hyperlink* }
+text-page = element text:page { text-page-attlist, empty }
+text-page-attlist = attribute text:master-page-name { styleNameRef }
+text-page-continuation-attlist =
+  attribute text:select-page { "previous" | "next" }
+  & attribute text:string-value { \string }?
+text-page-number-attlist =
+  (common-field-num-format-attlist & common-field-fixed-attlist)
+  & attribute text:page-adjust { integer }?
+  & attribute text:select-page { "previous" | "current" | "next" }?
+text-page-sequence = element text:page-sequence { text-page+ }
+text-placeholder-attlist =
+  attribute text:placeholder-type {
+    "text" | "table" | "text-box" | "image" | "object"
   }
-nonNegativeLength =
-  xsd:string {
-    pattern =
-      "([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)|(px))"
+  & common-field-description-attlist
+text-relative-tab-stop-position-attr =
+  attribute text:relative-tab-stop-position { boolean }?
+text-section =
+  element text:section {
+    text-section-attlist,
+    (text-section-source | text-section-source-dde | empty),
+    text-content*
   }
-positiveLength =
-  xsd:string {
-    pattern =
-      
"([0-9]*[1-9][0-9]*(\.[0-9]*)?|0+\.[0-9]*[1-9][0-9]*|\.[0-9]*[1-9][0-9]*)((cm)|(mm)|(in)|(pt)|(pc)|(px))"
+text-section-attlist =
+  common-section-attlist
+  & (attribute text:display { "true" | "none" }
+     | (attribute text:display { "condition" },
+        attribute text:condition { \string })
+     | empty)
+text-section-source =
+  element text:section-source { text-section-source-attr }
+text-section-source-attr =
+  (attribute xlink:type { "simple" },
+   attribute xlink:href { anyIRI },
+   attribute xlink:show { "embed" }?)?
+  & attribute text:section-name { \string }?
+  & attribute text:filter-name { \string }?
+text-section-source-dde = office-dde-source
+text-sequence-decl =
+  element text:sequence-decl { text-sequence-decl-attlist }
+text-sequence-decl-attlist =
+  common-field-name-attlist
+  & attribute text:display-outline-level { nonNegativeInteger }
+  & attribute text:separation-character { character }?
+text-sequence-ref-content =
+  attribute text:reference-format {
+    common-ref-format-values
+    | "category-and-value"
+    | "caption"
+    | "value"
+  }?
+text-sequence-ref-name = attribute text:ref-name { \string }?
+text-set-page-variable-attlist =
+  attribute text:active { boolean }?
+  & attribute text:page-adjust { integer }?
+text-soft-page-break = element text:soft-page-break { empty }
+text-sort-key = element text:sort-key { text-sort-key-attlist, empty }
+text-sort-key-attlist =
+  attribute text:key {
+    "address"
+    | "annote"
+    | "author"
+    | "bibliography-type"
+    | "booktitle"
+    | "chapter"
+    | "custom1"
+    | "custom2"
+    | "custom3"
+    | "custom4"
+    | "custom5"
+    | "edition"
+    | "editor"
+    | "howpublished"
+    | "identifier"
+    | "institution"
+    | "isbn"
+    | "issn"
+    | "journal"
+    | "month"
+    | "note"
+    | "number"
+    | "organizations"
+    | "pages"
+    | "publisher"
+    | "report-type"
+    | "school"
+    | "series"
+    | "title"
+    | "url"
+    | "volume"
+    | "year"
+  },
+  attribute text:sort-ascending { boolean }?
+text-style-name = attribute form:text-style-name { styleNameRef }?
+text-tab-attr = attribute text:tab-ref { nonNegativeInteger }?
+text-table-index =
+  element text:table-index {
+    common-section-attlist, text-table-index-source, text-index-body
   }
-percent = xsd:string { pattern = "-?([0-9]+(\.[0-9]*)?|\.[0-9]+)%" }
-zeroToHundredPercent =
-  xsd:string {
-    pattern = "([0-9]?[0-9](\.[0-9]*)?|100(\.0*)?|\.[0-9]+)%"
+text-table-index-entry-template =
+  element text:table-index-entry-template {
+    text-illustration-index-entry-content
   }
-signedZeroToHundredPercent =
-  xsd:string {
-    pattern = "-?([0-9]?[0-9](\.[0-9]*)?|100(\.0*)?|\.[0-9]+)%"
+text-table-index-source =
+  element text:table-index-source {
+    text-illustration-index-source-attrs,
+    text-index-title-template?,
+    text-table-index-entry-template?
   }
-relativeLength = xsd:string { pattern = "[0-9]+\*" }
-coordinate = length
-distance = length
-color = xsd:string { pattern = "#[0-9a-fA-F]{6}" }
-angle = xsd:string
-CURIE =
-  xsd:string { pattern = "(([\i-[:]][\c-[:]]*)?:)?.+" minLength = "1" }
-CURIEs = list { CURIE+ }
-SafeCURIE =
-  xsd:string {
-    pattern = "\[(([\i-[:]][\c-[:]]*)?:)?.+\]"
-    minLength = "3"
+text-table-of-content =
+  element text:table-of-content {
+    common-section-attlist,
+    text-table-of-content-source,
+    text-index-body
   }
-URIorSafeCURIE = anyURI | SafeCURIE
-styleName = xsd:NCName
-styleNameRef = xsd:NCName | empty
-styleNameRefs = list { xsd:NCName* }
-variableName = xsd:string
-targetFrameName = "_self" | "_blank" | "_parent" | "_top" | \string
+text-table-of-content-children =
+  text-index-entry-chapter
+  | text-index-entry-page-number
+  | text-index-entry-text
+  | text-index-entry-span
+  | text-index-entry-tab-stop
+  | text-index-entry-link-start
+  | text-index-entry-link-end
+text-table-of-content-entry-template =
+  element text:table-of-content-entry-template {
+    text-table-of-content-entry-template-attlist,
+    text-table-of-content-children*
+  }
+text-table-of-content-entry-template-attlist =
+  attribute text:outline-level { positiveInteger }
+  & attribute text:style-name { styleNameRef }
+text-table-of-content-source =
+  element text:table-of-content-source {
+    text-table-of-content-source-attlist,
+    text-index-title-template?,
+    text-table-of-content-entry-template*,
+    text-index-source-styles*
+  }
+text-table-of-content-source-attlist =
+  attribute text:outline-level { positiveInteger }?
+  & attribute text:use-outline-level { boolean }?
+  & attribute text:use-index-marks { boolean }?
+  & attribute text:use-index-source-styles { boolean }?
+  & attribute text:index-scope { "document" | "chapter" }?
+  & attribute text:relative-tab-stop-position { boolean }?
+text-template-name-attlist =
+  attribute text:display {
+    "full" | "path" | "name" | "name-and-extension" | "area" | "title"
+  }?
+text-time-attlist =
+  (common-field-fixed-attlist & common-field-data-style-name-attlist)
+  & attribute text:time-value { timeOrDateTime }?
+  & attribute text:time-adjust { duration }?
+text-toc-mark-start-attrs = text-id, text-outline-level
+text-tracked-changes =
+  element text:tracked-changes {
+    text-tracked-changes-attr, text-changed-region*
+  }?
+text-tracked-changes-attr = attribute text:track-changes { boolean }?
+text-user-field-decl =
+  element text:user-field-decl {
+    common-field-name-attlist,
+    common-field-formula-attlist?,
+    common-value-and-type-attlist
+  }
+text-user-index =
+  element text:user-index {
+    common-section-attlist, text-user-index-source, text-index-body
+  }
+text-user-index-entry-template =
+  element text:user-index-entry-template {
+    text-user-index-entry-template-attrs,
+    (text-index-entry-chapter
+     | text-index-entry-page-number
+     | text-index-entry-text
+     | text-index-entry-span
+     | text-index-entry-tab-stop
+     | text-index-entry-link-start
+     | text-index-entry-link-end
+       # https://issues.oasis-open.org/browse/OFFICE-3941
+       )*
+  }
+text-user-index-entry-template-attrs =
+  attribute text:outline-level { positiveInteger }
+  & attribute text:style-name { styleNameRef }
+text-user-index-source =
+  element text:user-index-source {
+    text-user-index-source-attr,
+    text-index-title-template?,
+    text-user-index-entry-template*,
+    text-index-source-styles*
+  }
+text-user-index-source-attr =
+  text-index-scope-attr
+  & text-relative-tab-stop-position-attr
+  & attribute text:use-index-marks { boolean }?
+  & attribute text:use-index-source-styles { boolean }?
+  & attribute text:use-graphics { boolean }?
+  & attribute text:use-tables { boolean }?
+  & attribute text:use-floating-frames { boolean }?
+  & attribute text:use-objects { boolean }?
+  & attribute text:copy-outline-levels { boolean }?
+  & attribute text:index-name { \string }
+text-variable-decl =
+  element text:variable-decl {
+    common-field-name-attlist, common-value-type-attlist
+  }
+textEncoding = xsd:string { pattern = "[A-Za-z][A-Za-z0-9._\-]*" }
+time = xsd:time
+timeOrDateTime = xsd:time | xsd:dateTime
+types = "submit" | "reset" | "push" | "url"
 valueType =
   "float"
   | "time"
@@ -6257,24 +6397,18 @@ valueType =
   | "currency"
   | "boolean"
   | "string"
-points =
-  xsd:string { pattern = "-?[0-9]+,-?[0-9]+([ ]+-?[0-9]+,-?[0-9]+)*" }
-pathData = xsd:string
+variableName = xsd:string
 vector3D =
   xsd:string {
     pattern =
       "\([ ]*-?([0-9]+(\.[0-9]*)?|\.[0-9]+)([ 
]+-?([0-9]+(\.[0-9]*)?|\.[0-9]+)){2}[ ]*\)"
   }
-namespacedToken = xsd:QName { pattern = "[^:]+:[^:]+" }
-anyIRI =
-  xsd:anyURI
-  >> dc:description [
-       "An IRI-reference as defined in [RFC3987]. See ODF 1.2 Part 1 section 
18.3."
-     ]
-anyAttListOrElements =
-  attribute * { text }*,
-  anyElements
-anyElements =
-  element * {
-    mixed { anyAttListOrElements }
-  }*
+vertBackPos = "top" | "center" | "bottom"
+xforms-bind-attlist = attribute xforms:bind { \string }?
+xforms-model = element xforms:model { anyAttListOrElements }
+xml-id = attribute xml:id { ID }
+zeroToHundredPercent =
+  xsd:string {
+    pattern = "([0-9]?[0-9](\.[0-9]*)?|100(\.0*)?|\.[0-9]+)%"
+  }
+zeroToOneDecimal = xsd:decimal { minInclusive = "0" maxInclusive = "1" }
diff --git a/etc/schema/schemas.xml b/etc/schema/schemas.xml
index 7fd91b8..f8acb0d 100644
--- a/etc/schema/schemas.xml
+++ b/etc/schema/schemas.xml
@@ -31,6 +31,10 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>. -->
   <namespace ns="http://relaxng.org/ns/structure/1.0"; typeId="RELAX NG"/>
   <namespace ns="http://thaiopensource.com/ns/locating-rules/1.0";
             uri="locate.rnc"/>
+  <namespace ns="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
typeId="LibreOffice"/>
+  <namespace 
ns="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" 
typeId="LibreOffice"/>
+  <namespace 
ns="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" 
typeId="LibreOffice"/>
+  <namespace ns="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" 
typeId="OpenDocument Manifest"/>
 
   <documentElement localName="stylesheet" typeId="XSLT"/>
   <documentElement prefix="xsl" localName="transform" typeId="XSLT"/>
@@ -59,7 +63,7 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>. -->
 
   <documentElement prefix="office" typeId="OpenDocument"/>
   <documentElement prefix="manifest" localName="manifest" typeId="OpenDocument 
Manifest"/>
-  <typeId id="OpenDocument" uri="od-schema-v1.2-os.rnc"/>
+  <typeId id="LibreOffice" uri="OpenDocument-schema-v1.3+libreoffice.rnc"/>
   <typeId id="OpenDocument Manifest" uri="od-manifest-schema-v1.2-os.rnc"/>
 
 </locatingRules>
diff --git a/leim/Makefile.in b/leim/Makefile.in
index c2f9cf5..2646abc 100644
--- a/leim/Makefile.in
+++ b/leim/Makefile.in
@@ -137,19 +137,23 @@ ${srcdir}/../lisp/language/pinyin.el: 
${srcdir}/MISC-DIC/pinyin.map
        $(AM_V_GEN)${RUN_EMACS} -l titdic-cnv -f pinyin-convert $< $@
 
 
-.PHONY: bootstrap-clean distclean maintainer-clean extraclean
+.PHONY: bootstrap-clean distclean maintainer-clean extraclean gen-clean
 
+## Perhaps this should run gen-clean.
 bootstrap-clean:
        rm -f ${TIT_MISC} ${leimdir}/leim-list.el
 
 distclean:
        rm -f Makefile
 
-maintainer-clean: distclean bootstrap-clean
+maintainer-clean: gen-clean distclean
 
-## We do not delete ja-dic, even in a bootstrap, because it rarely
-## changes and is slow to regenerate.
-extraclean: bootstrap-clean
+## ja-dic rarely changes and is slow to regenerate, and tends to be a
+## bottleneck in parallel builds.
+gen-clean:
+       rm -f ${TIT_MISC} ${leimdir}/leim-list.el
        rm -rf ${leimdir}/ja-dic
 
+extraclean: maintainer-clean
+
 ### Makefile.in ends here
diff --git a/lib/pipe2.c b/lib/pipe2.c
index 41493aa..adbaa4a 100644
--- a/lib/pipe2.c
+++ b/lib/pipe2.c
@@ -41,7 +41,7 @@ pipe2 (int fd[2], int flags)
 {
   /* Mingw _pipe() corrupts fd on failure; also, if we succeed at
      creating the pipe but later fail at changing fcntl, we want
-     to leave fd unchanged: http://austingroupbugs.net/view.php?id=467  */
+     to leave fd unchanged: https://austingroupbugs.net/view.php?id=467  */
   int tmp[2];
   tmp[0] = fd[0];
   tmp[1] = fd[1];
diff --git a/lisp/Makefile.in b/lisp/Makefile.in
index 8ea2841..d62c2cf 100644
--- a/lisp/Makefile.in
+++ b/lisp/Makefile.in
@@ -449,8 +449,10 @@ maintainer-clean: distclean bootstrap-clean
        rm -f TAGS
 
 extraclean: bootstrap-clean distclean
-       -for file in $(LOADDEFS); do rm -f $${file}~; done
+       -for file in $(loaddefs); do rm -f $${file}~; done
        -rm -f $(lisp)/loaddefs.el~
+       -find $(lisp) -name '*~' $(FIND_DELETE)
+       -find $(lisp) -name '#*' $(FIND_DELETE)
 
 .PHONY: check-declare
 
diff --git a/lisp/allout-widgets.el b/lisp/allout-widgets.el
index f251be8..931dfbc 100644
--- a/lisp/allout-widgets.el
+++ b/lisp/allout-widgets.el
@@ -1,4 +1,4 @@
-;; allout-widgets.el --- Visually highlight allout outline structure.
+;; allout-widgets.el --- Visually highlight allout outline structure.  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2005-2021 Free Software Foundation, Inc.
 
@@ -6,7 +6,7 @@
 ;; Version: 1.0
 ;; Created: Dec 2005
 ;; Keywords: outlines
-;; Website: http://myriadicity.net/software-and-systems/craft/emacs-allout
+;; Website: https://myriadicity.net/software-and-systems/craft/emacs-allout
 
 ;; This file is part of GNU Emacs.
 
@@ -38,7 +38,7 @@
 ;; See the `allout-widgets-mode' docstring for more details.
 ;;
 ;; Info about allout and allout-widgets development are available at
-;; http://myriadicity.net/Sundry/EmacsAllout
+;; https://myriadicity.net/software-and-systems/craft/emacs-allout
 ;;
 ;; The graphics include:
 ;;
@@ -72,11 +72,11 @@
 (eval-when-compile (require 'cl-lib))
 
 ;;;_ : internal variables needed before user-customization variables
-;;; In order to enable activation of allout-widgets-mode via customization,
-;;; allout-widgets-auto-activation uses a setting function.  That function
-;;; is invoked when the customization variable definition is evaluated,
-;;; during file load, so the involved code must reside above that
-;;; definition in the file.
+;; In order to enable activation of allout-widgets-mode via customization,
+;; allout-widgets-auto-activation uses a setting function.  That function
+;; is invoked when the customization variable definition is evaluated,
+;; during file load, so the involved code must reside above that
+;; definition in the file.
 ;;;_  = allout-widgets-mode
 (defvar-local allout-widgets-mode nil
   "Allout mode enhanced with graphical widgets.")
@@ -100,8 +100,8 @@ with allout-mode."
 
 See `allout-widgets-mode-inhibit' for per-file/per-buffer
 inhibition of allout-widgets-mode."
-  (add-hook 'allout-mode-off-hook 'allout-widgets-mode-off)
-  (add-hook 'allout-mode-on-hook 'allout-widgets-mode-on)
+  (add-hook 'allout-mode-off-hook #'allout-widgets-mode-off)
+  (add-hook 'allout-mode-on-hook #'allout-widgets-mode-on)
   t)
 ;;;_  > allout-widgets-mode-disable
 (defun allout-widgets-mode-disable ()
@@ -109,8 +109,8 @@ inhibition of allout-widgets-mode."
 
 See `allout-widgets-mode-inhibit' for per-file/per-buffer
 inhibition of allout-widgets-mode."
-  (remove-hook 'allout-mode-off-hook 'allout-widgets-mode-off)
-  (remove-hook 'allout-mode-on-hook 'allout-widgets-mode-on)
+  (remove-hook 'allout-mode-off-hook #'allout-widgets-mode-off)
+  (remove-hook 'allout-mode-on-hook #'allout-widgets-mode-on)
   t)
 ;;;_  > allout-widgets-setup (varname value)
 ;;;###autoload
@@ -141,7 +141,7 @@ See `allout-widgets-mode' for allout widgets mode features."
   :version "24.1"
   :type 'boolean
   :group 'allout-widgets
-  :set 'allout-widgets-setup
+  :set #'allout-widgets-setup
  )
 ;; ;;;_  = allout-widgets-allow-unruly-edits
 ;; (defcustom allout-widgets-allow-unruly-edits nil
@@ -307,7 +307,7 @@ In addition, you can invoked `allout-widgets-mode' 
allout-mode
 buffers where this is set to enable and disable widget
 enhancements, directly.")
 ;;;###autoload
-(put 'allout-widgets-mode-inhibit 'safe-local-variable 'booleanp)
+(put 'allout-widgets-mode-inhibit 'safe-local-variable #'booleanp)
 ;;;_    = allout-inhibit-body-modification-hook
 (defvar-local allout-inhibit-body-modification-hook nil
   "Override de-escaping of text-prefixes in item bodies during specific 
changes.
@@ -402,14 +402,14 @@ not altered with an escape sequence.")
     (set-keymap-parent km as-parent)
     (dolist (digit '("0" "1" "2" "3"
                      "4" "5" "6" "7" "8" "9"))
-      (define-key km digit 'digit-argument))
-    (define-key km "-" 'negative-argument)
+      (define-key km digit #'digit-argument))
+    (define-key km "-" #'negative-argument)
     ;; Override underlying mouse-1 and mouse-2 bindings in icon territory:
-    (define-key km [(mouse-1)] (lambda () (interactive) nil))
-    (define-key km [(mouse-2)] (lambda () (interactive) nil))
+    (define-key km [(mouse-1)] #'ignore)
+    (define-key km [(mouse-2)] #'ignore)
 
     ;; Catchall, handles actual keybindings, dynamically doing keymap lookups:
-    (define-key km [t] 'allout-item-icon-key-handler)
+    (define-key km [t] #'allout-item-icon-key-handler)
 
     km)
   "General tree-node key bindings.")
@@ -535,7 +535,7 @@ outline hot-spot navigation (see `allout-mode')."
                      "\\1\\3"))
          )
 
-        (add-hook 'after-change-functions 'allout-widgets-after-change-handler
+        (add-hook 'after-change-functions #'allout-widgets-after-change-handler
                   nil t)
 
         (allout-setup-text-properties)
@@ -551,23 +551,23 @@ outline hot-spot navigation (see `allout-mode')."
           (set-keymap-parent allout-item-icon-keymap as-parent))
 
         (add-hook 'allout-exposure-change-functions
-                  'allout-widgets-exposure-change-recorder nil 'local)
+                  #'allout-widgets-exposure-change-recorder nil 'local)
         (add-hook 'allout-structure-added-functions
-                  'allout-widgets-additions-recorder nil 'local)
+                  #'allout-widgets-additions-recorder nil 'local)
         (add-hook 'allout-structure-deleted-functions
-                  'allout-widgets-deletions-recorder nil 'local)
+                  #'allout-widgets-deletions-recorder nil 'local)
         (add-hook 'allout-structure-shifted-functions
-                  'allout-widgets-shifts-recorder nil 'local)
+                  #'allout-widgets-shifts-recorder nil 'local)
         (add-hook 'allout-after-copy-or-kill-hook
-                  'allout-widgets-after-copy-or-kill-function nil 'local)
+                  #'allout-widgets-after-copy-or-kill-function nil 'local)
         (add-hook 'allout-post-undo-hook
-                  'allout-widgets-after-undo-function nil 'local)
+                  #'allout-widgets-after-undo-function nil 'local)
 
-        (add-hook 'before-change-functions 
'allout-widgets-before-change-handler
+        (add-hook 'before-change-functions
+                  #'allout-widgets-before-change-handler nil 'local)
+        (add-hook 'post-command-hook #'allout-widgets-post-command-business
                   nil 'local)
-        (add-hook 'post-command-hook 'allout-widgets-post-command-business
-                  nil 'local)
-        (add-hook 'pre-command-hook 'allout-widgets-pre-command-business
+        (add-hook 'pre-command-hook #'allout-widgets-pre-command-business
                   nil 'local)
 
         ;; init the widgets tally for debugging:
@@ -596,23 +596,23 @@ outline hot-spot navigation (see `allout-mode')."
       (remove-from-invisibility-spec 'allout-escapes)
 
       (remove-hook 'after-change-functions
-                   'allout-widgets-after-change-handler 'local)
+                   #'allout-widgets-after-change-handler 'local)
       (remove-hook 'allout-exposure-change-functions
-                   'allout-widgets-exposure-change-recorder 'local)
+                   #'allout-widgets-exposure-change-recorder 'local)
       (remove-hook 'allout-structure-added-functions
-                   'allout-widgets-additions-recorder 'local)
+                   #'allout-widgets-additions-recorder 'local)
       (remove-hook 'allout-structure-deleted-functions
-                   'allout-widgets-deletions-recorder 'local)
+                   #'allout-widgets-deletions-recorder 'local)
       (remove-hook 'allout-structure-shifted-functions
-                   'allout-widgets-shifts-recorder 'local)
+                   #'allout-widgets-shifts-recorder 'local)
       (remove-hook 'allout-after-copy-or-kill-hook
-                   'allout-widgets-after-copy-or-kill-function 'local)
+                   #'allout-widgets-after-copy-or-kill-function 'local)
       (remove-hook 'before-change-functions
-                   'allout-widgets-before-change-handler 'local)
+                   #'allout-widgets-before-change-handler 'local)
       (remove-hook 'post-command-hook
-                   'allout-widgets-post-command-business 'local)
+                   #'allout-widgets-post-command-business 'local)
       (remove-hook 'pre-command-hook
-                   'allout-widgets-pre-command-business 'local)
+                   #'allout-widgets-pre-command-business 'local)
       (assq-delete-all 'allout-widgets-mode-inhibit minor-mode-alist)
       (set-buffer-modified-p was-modified))))
 ;;;_   > allout-widgets-mode-off
@@ -710,7 +710,7 @@ Optional RECURSING is for internal use, to limit recursion."
 
         (when allout-widgets-reenable-before-change-handler
           (add-hook 'before-change-functions
-                    'allout-widgets-before-change-handler
+                    #'allout-widgets-before-change-handler
                     nil 'local)
           (setq allout-widgets-reenable-before-change-handler nil))
 
@@ -879,7 +879,7 @@ encompassing condition-case."
     (message header) (sit-for allout-widgets-hook-error-post-time)
     ;; reraise the error, or one concerning this function if unexpected:
     (if (equal mode 'error)
-        (apply 'signal args)
+        (apply #'signal args)
       (error "%s: unexpected mode, %s %s" this mode args))))
 ;;;_   > allout-widgets-changes-exceed-threshold-p ()
 (defun allout-widgets-adjusting-message (message)
@@ -973,9 +973,8 @@ Generally invoked via `allout-exposure-change-functions'."
         deactivate-mark)
 
     (dolist (change changes)
-      (let (handling
-            (from (cadr change))
-            bucket got
+      (let ((from (cadr change))
+            bucket
             (to (caddr change))
             (flag (cadddr change))
             parent)
@@ -986,10 +985,11 @@ Generally invoked via `allout-exposure-change-functions'."
                               from bucket))
 
         ;; have we already handled exposure changes in this region?
-        (setq handling (if flag 'handled-conceal 'handled-expose)
-              got (allout-range-overlaps from to (symbol-value handling))
-              covered (car got))
-        (set handling (cadr got))
+        (cl-callf (lambda (x)
+                    (let ((got (allout-range-overlaps from to x)))
+                      (setq covered (car got))
+                      (cadr got)))
+            (if flag handled-conceal handled-expose))
 
         (when (not covered)
           (save-excursion
@@ -1825,7 +1825,7 @@ reapplying this method will rectify the glyphs."
             (if (> increment 1) (setq increment 1))
             (when extenders
               ;; paint extenders after a connector, else leave spaces.
-              (dotimes (i extenders)
+              (dotimes (_ extenders)
                 (put-text-property
                  position (setq position (1+ position))
                  'display (allout-fetch-icon-image
diff --git a/lisp/allout.el b/lisp/allout.el
index 3981fdd..f50f5fd 100644
--- a/lisp/allout.el
+++ b/lisp/allout.el
@@ -1,12 +1,12 @@
-;;; allout.el --- extensive outline mode for use alone and with other modes
+;;; allout.el --- extensive outline mode for use alone and with other modes  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 1992-1994, 2001-2021 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2021 Free Software Foundation, Inc.
 
 ;; Author: Ken Manheimer <ken dot manheimer at gmail...>
 ;; Created: Dec 1991 -- first release to usenet
 ;; Version: 2.3
 ;; Keywords: outlines, wp, languages, PGP, GnuPG
-;; Website: http://myriadicity.net/software-and-systems/craft/emacs-allout
+;; Website: https://myriadicity.net/software-and-systems/craft/emacs-allout
 
 ;; This file is part of GNU Emacs.
 
@@ -57,7 +57,7 @@
 ;; mode.
 ;;
 ;; Directions to the latest development version and helpful notes are
-;; available at http://myriadicity.net/Sundry/EmacsAllout .
+;; available at 
https://myriadicity.net/software-and-systems/craft/emacs-allout .
 ;;
 ;; The outline menubar additions provide quick reference to many of the
 ;; features.  See the docstring of the variables `allout-layout' and
@@ -133,13 +133,14 @@ respective allout-mode keybinding variables, 
`allout-command-prefix',
     (when (boundp 'allout-unprefixed-keybindings)
       (dolist (entry allout-unprefixed-keybindings)
         (define-key map (car (read-from-string (car entry))) (cadr entry))))
-    (substitute-key-definition 'beginning-of-line 'allout-beginning-of-line
+    (substitute-key-definition #'beginning-of-line #'allout-beginning-of-line
                                map global-map)
-    (substitute-key-definition 'move-beginning-of-line 
'allout-beginning-of-line
+    (substitute-key-definition #'move-beginning-of-line
+                               #'allout-beginning-of-line
                                map global-map)
-    (substitute-key-definition 'end-of-line 'allout-end-of-line
+    (substitute-key-definition #'end-of-line #'allout-end-of-line
                                map global-map)
-    (substitute-key-definition 'move-end-of-line 'allout-end-of-line
+    (substitute-key-definition #'move-end-of-line #'allout-end-of-line
                                map global-map)
     (allout-institute-keymap map)))
 ;;;_  > allout-institute-keymap (map)
@@ -169,7 +170,7 @@ Default is `\C-c<space>'; just `\C-c' is more 
short-and-sweet, if you're
 willing to let allout use a bunch of \C-c keybindings."
   :type 'string
   :group 'allout-keybindings
-  :set 'allout-compose-and-institute-keymap)
+  :set #'allout-compose-and-institute-keymap)
 ;;;_   = allout-keybindings-binding
 (define-widget 'allout-keybindings-binding 'lazy
   "Structure of allout keybindings customization items."
@@ -230,7 +231,7 @@ prevails."
   :version "24.1"
   :type 'allout-keybindings-binding
   :group 'allout-keybindings
-  :set 'allout-compose-and-institute-keymap
+  :set #'allout-compose-and-institute-keymap
  )
 ;;;_   = allout-unprefixed-keybindings
 (defcustom allout-unprefixed-keybindings
@@ -254,7 +255,7 @@ See the existing keys for examples."
   :version "24.1"
   :type 'allout-keybindings-binding
   :group 'allout-keybindings
-  :set 'allout-compose-and-institute-keymap
+  :set #'allout-compose-and-institute-keymap
   )
 
 ;;;_  > allout-auto-activation-helper (var value)
@@ -276,8 +277,8 @@ Establishes allout processing as part of visiting a file if
 The proper way to use this is through customizing the setting of
 `allout-auto-activation'."
   (if (not allout-auto-activation)
-      (remove-hook 'find-file-hook 'allout-find-file-hook)
-      (add-hook 'find-file-hook 'allout-find-file-hook)))
+      (remove-hook 'find-file-hook #'allout-find-file-hook)
+      (add-hook 'find-file-hook #'allout-find-file-hook)))
 ;;;_  = allout-auto-activation
 ;;;###autoload
 (defcustom allout-auto-activation nil
@@ -298,7 +299,7 @@ With value \"activate\", only auto-mode-activation is 
enabled.
 Auto-layout is not.
 
 With value nil, inhibit any automatic allout-mode activation."
-  :set 'allout-auto-activation-helper
+  :set #'allout-auto-activation-helper
   ;; FIXME: Using strings here is unusual and less efficient than symbols.
   :type '(choice (const :tag "On" t)
                 (const :tag "Ask about layout" "ask")
@@ -405,7 +406,7 @@ where auto-fill occurs."
   :group 'allout)
 (make-variable-buffer-local 'allout-use-hanging-indents)
 ;;;###autoload
-(put 'allout-use-hanging-indents 'safe-local-variable 'booleanp)
+(put 'allout-use-hanging-indents 'safe-local-variable #'booleanp)
 ;;;_  = allout-reindent-bodies
 (defcustom allout-reindent-bodies (if allout-use-hanging-indents
                                    'text)
@@ -434,7 +435,7 @@ just the header."
   :group 'allout)
 (make-variable-buffer-local 'allout-show-bodies)
 ;;;###autoload
-(put 'allout-show-bodies 'safe-local-variable 'booleanp)
+(put 'allout-show-bodies 'safe-local-variable #'booleanp)
 
 ;;;_  = allout-beginning-of-line-cycles
 (defcustom allout-beginning-of-line-cycles t
@@ -507,7 +508,7 @@ character, which is typically set to the 
`allout-primary-bullet'."
   :group 'allout)
 (make-variable-buffer-local 'allout-header-prefix)
 ;;;###autoload
-(put 'allout-header-prefix 'safe-local-variable 'stringp)
+(put 'allout-header-prefix 'safe-local-variable #'stringp)
 ;;;_  = allout-primary-bullet
 (defcustom allout-primary-bullet "*"
   "Bullet used for top-level outline topics.
@@ -524,7 +525,7 @@ bullets."
   :group 'allout)
 (make-variable-buffer-local 'allout-primary-bullet)
 ;;;###autoload
-(put 'allout-primary-bullet 'safe-local-variable 'stringp)
+(put 'allout-primary-bullet 'safe-local-variable #'stringp)
 ;;;_  = allout-plain-bullets-string
 (defcustom allout-plain-bullets-string ".,"
   "The bullets normally used in outline topic prefixes.
@@ -540,7 +541,7 @@ of this var to take effect."
   :group 'allout)
 (make-variable-buffer-local 'allout-plain-bullets-string)
 ;;;###autoload
-(put 'allout-plain-bullets-string 'safe-local-variable 'stringp)
+(put 'allout-plain-bullets-string 'safe-local-variable #'stringp)
 ;;;_  = allout-distinctive-bullets-string
 (defcustom allout-distinctive-bullets-string "*+-=>()[{}&!?#%\"X@$~_\\:;^"
   "Persistent outline header bullets used to distinguish special topics.
@@ -588,7 +589,7 @@ strings."
   :group 'allout)
 (make-variable-buffer-local 'allout-distinctive-bullets-string)
 ;;;###autoload
-(put 'allout-distinctive-bullets-string 'safe-local-variable 'stringp)
+(put 'allout-distinctive-bullets-string 'safe-local-variable #'stringp)
 
 ;;;_  = allout-use-mode-specific-leader
 (defcustom allout-use-mode-specific-leader t
@@ -655,7 +656,7 @@ are always respected by the topic maneuvering functions."
   :group 'allout)
 (make-variable-buffer-local 'allout-old-style-prefixes)
 ;;;###autoload
-(put 'allout-old-style-prefixes 'safe-local-variable 'booleanp)
+(put 'allout-old-style-prefixes 'safe-local-variable #'booleanp)
 ;;;_  = allout-stylish-prefixes -- alternating bullets
 (defcustom allout-stylish-prefixes t
   "Do fancy stuff with topic prefix bullets according to level, etc.
@@ -703,7 +704,7 @@ is non-nil."
   :group 'allout)
 (make-variable-buffer-local 'allout-stylish-prefixes)
 ;;;###autoload
-(put 'allout-stylish-prefixes 'safe-local-variable 'booleanp)
+(put 'allout-stylish-prefixes 'safe-local-variable #'booleanp)
 
 ;;;_  = allout-numbered-bullet
 (defcustom allout-numbered-bullet "#"
@@ -717,7 +718,7 @@ disables numbering maintenance."
   :group 'allout)
 (make-variable-buffer-local 'allout-numbered-bullet)
 ;;;###autoload
-(put 'allout-numbered-bullet 'safe-local-variable 'string-or-null-p)
+(put 'allout-numbered-bullet 'safe-local-variable #'string-or-null-p)
 ;;;_  = allout-file-xref-bullet
 (defcustom allout-file-xref-bullet "@"
   "Bullet signifying file cross-references, for `allout-resolve-xref'.
@@ -726,7 +727,7 @@ Set this var to the bullet you want to use for file 
cross-references."
   :type '(choice (const nil) string)
   :group 'allout)
 ;;;###autoload
-(put 'allout-file-xref-bullet 'safe-local-variable 'string-or-null-p)
+(put 'allout-file-xref-bullet 'safe-local-variable #'string-or-null-p)
 ;;;_  = allout-presentation-padding
 (defcustom allout-presentation-padding 2
   "Presentation-format white-space padding factor, for greater indent."
@@ -735,7 +736,7 @@ Set this var to the bullet you want to use for file 
cross-references."
 
 (make-variable-buffer-local 'allout-presentation-padding)
 ;;;###autoload
-(put 'allout-presentation-padding 'safe-local-variable 'integerp)
+(put 'allout-presentation-padding 'safe-local-variable #'integerp)
 
 ;;;_  = allout-flattened-numbering-abbreviation
 (define-obsolete-variable-alias 'allout-abbreviate-flattened-numbering
@@ -1056,7 +1057,7 @@ invoking it directly."
           (setq allout-primary-bullet leader))
       allout-header-prefix)))
 (defalias 'allout-infer-header-lead
-  'allout-infer-header-lead-and-primary-bullet)
+  #'allout-infer-header-lead-and-primary-bullet)
 ;;;_   > allout-infer-body-reindent ()
 (defun allout-infer-body-reindent ()
   "Determine proper setting for `allout-reindent-bodies'.
@@ -1196,7 +1197,7 @@ Also refresh various data structures that hinge on the 
regexp."
                             "[^" allout-primary-bullet "]"))
                   "\\)"
                   ))))
-(define-obsolete-function-alias 'set-allout-regexp 'allout-set-regexp "26.1")
+(define-obsolete-function-alias 'set-allout-regexp #'allout-set-regexp "26.1")
 ;;;_  : Menu bar
 (defvar allout-mode-exposure-menu)
 (defvar allout-mode-editing-menu)
@@ -1589,17 +1590,6 @@ non-nil in a lasting way.")
 (defvar-local allout-explicitly-deactivated nil
   "If t, `allout-mode's last deactivation was deliberate.
 So `allout-post-command-business' should not reactivate it...")
-;;;_  > allout-setup-menubar ()
-(defun allout-setup-menubar ()
-  "Populate the current buffer's menubar with `allout-mode' stuff."
-  (let ((menus (list allout-mode-exposure-menu
-                    allout-mode-editing-menu
-                    allout-mode-navigation-menu
-                    allout-mode-misc-menu))
-       cur)
-    (while menus
-      (setq cur (car menus)
-            menus (cdr menus)))))
 ;;;_  > allout-overlay-preparations
 (defun allout-overlay-preparations ()
   "Set the properties of the allout invisible-text overlay and others."
@@ -1613,7 +1603,7 @@ So `allout-post-command-business' should not reactivate 
it...")
   ;; property controls the isearch _arrival_ behavior.  This is the case at
   ;; least in emacs 21, 22.1, and xemacs 21.4.
   (put 'allout-exposure-category 'isearch-open-invisible
-       'allout-isearch-end-handler)
+       #'allout-isearch-end-handler)
   (put 'allout-exposure-category 'insert-in-front-hooks
        '(allout-overlay-insert-in-front-handler))
   (put 'allout-exposure-category 'modification-hooks
@@ -1903,12 +1893,12 @@ OPEN:   A TOPIC that is not CLOSED, though its 
OFFSPRING or BODY may be."
           (allout-do-resumptions)
 
           (remove-from-invisibility-spec '(allout . t))
-          (remove-hook 'pre-command-hook 'allout-pre-command-business t)
-          (remove-hook 'post-command-hook 'allout-post-command-business t)
-          (remove-hook 'before-change-functions 'allout-before-change-handler 
t)
-          (remove-hook 'isearch-mode-end-hook 'allout-isearch-end-handler t)
+          (remove-hook 'pre-command-hook #'allout-pre-command-business t)
+          (remove-hook 'post-command-hook #'allout-post-command-business t)
+          (remove-hook 'before-change-functions #'allout-before-change-handler 
t)
+          (remove-hook 'isearch-mode-end-hook #'allout-isearch-end-handler t)
           (remove-hook 'write-contents-functions
-                       'allout-write-contents-hook-handler t)
+                       #'allout-write-contents-hook-handler t)
 
           (remove-overlays (point-min) (point-max)
                            'category 'allout-exposure-category))
@@ -1937,11 +1927,11 @@ OPEN:   A TOPIC that is not CLOSED, though its 
OFFSPRING or BODY may be."
       (add-to-invisibility-spec '(allout . t))
 
       (allout-add-resumptions '(line-move-ignore-invisible t))
-      (add-hook 'pre-command-hook 'allout-pre-command-business nil t)
-      (add-hook 'post-command-hook 'allout-post-command-business nil t)
-      (add-hook 'before-change-functions 'allout-before-change-handler nil t)
-      (add-hook 'isearch-mode-end-hook 'allout-isearch-end-handler nil t)
-      (add-hook 'write-contents-functions 'allout-write-contents-hook-handler
+      (add-hook 'pre-command-hook #'allout-pre-command-business nil t)
+      (add-hook 'post-command-hook #'allout-post-command-business nil t)
+      (add-hook 'before-change-functions #'allout-before-change-handler nil t)
+      (add-hook 'isearch-mode-end-hook #'allout-isearch-end-handler nil t)
+      (add-hook 'write-contents-functions #'allout-write-contents-hook-handler
                 nil t)
 
       ;; Stash auto-fill settings and adjust so custom allout auto-fill
@@ -1966,8 +1956,6 @@ OPEN:     A TOPIC that is not CLOSED, though its 
OFFSPRING or BODY may be."
           ;; allout-auto-fill will use the stashed values and so forth.
           (allout-add-resumptions '(auto-fill-function allout-auto-fill)))
 
-      (allout-setup-menubar)
-
       ;; Do auto layout if warranted:
       (when (and allout-layout
                  allout-auto-activation
@@ -1987,7 +1975,7 @@ OPEN:     A TOPIC that is not CLOSED, though its 
OFFSPRING or BODY may be."
           (allout-this-or-next-heading)
           (condition-case err
               (progn
-                (apply 'allout-expose-topic (list use-layout))
+                (apply #'allout-expose-topic (list use-layout))
                 (message "Adjusting `%s' exposure... done."
                          (buffer-name)))
             ;; Problem applying exposure -- notify user, but don't
@@ -1999,7 +1987,7 @@ OPEN:     A TOPIC that is not CLOSED, though its 
OFFSPRING or BODY may be."
     )                                   ; let (())
   )                                    ; define-minor-mode
 ;;;_  > allout-minor-mode alias
-(defalias 'allout-minor-mode 'allout-mode)
+(defalias 'allout-minor-mode #'allout-mode)
 ;;;_  > allout-unload-function
 (defun allout-unload-function ()
   "Unload the allout outline library."
@@ -2068,7 +2056,7 @@ internal functions use this feature cohesively bunch 
changes."
                 (error "Concealed-text change abandoned, text reconcealed"))))
       (goto-char start))))
 ;;;_  > allout-before-change-handler (beg end)
-(defun allout-before-change-handler (beg end)
+(defun allout-before-change-handler (_beg _end)
   "Protect against changes to invisible text.
 
 See `allout-overlay-interior-modification-handler' for details."
@@ -2232,7 +2220,7 @@ Actually, returns prefix beginning point."
            (or (not (allout-do-doublecheck))
                (not (allout-aberrant-container-p)))))))
 ;;;_    > allout-on-heading-p ()
-(defalias 'allout-on-heading-p 'allout-on-current-heading-p)
+(defalias 'allout-on-heading-p #'allout-on-current-heading-p)
 ;;;_    > allout-e-o-prefix-p ()
 (defun allout-e-o-prefix-p ()
   "True if point is located where current topic prefix ends, heading begins."
@@ -2768,7 +2756,7 @@ of (before any) topics, in which case we return nil."
         (goto-char (point-min))
         nil))))
 ;;;_   > allout-back-to-heading ()
-(defalias 'allout-back-to-heading 'allout-back-to-current-heading)
+(defalias 'allout-back-to-heading #'allout-back-to-current-heading)
 ;;;_   > allout-pre-next-prefix ()
 (defun allout-pre-next-prefix ()
   "Skip forward to just before the next heading line.
@@ -2850,7 +2838,7 @@ collapsed."
   (allout-beginning-of-current-entry)
   (search-forward "\n" nil t)
   (forward-char -1))
-(defalias 'allout-end-of-heading 'allout-end-of-current-heading)
+(defalias 'allout-end-of-heading #'allout-end-of-current-heading)
 ;;;_   > allout-get-body-text ()
 (defun allout-get-body-text ()
   "Return the unmangled body text of the topic immediately containing point."
@@ -3289,10 +3277,6 @@ Returns the qualifying command, if any, else nil."
   (interactive)
   (let* ((modified (event-modifiers last-command-event))
          (key-num (cond ((numberp last-command-event) last-command-event)
-                        ;; for XEmacs character type:
-                        ((and (fboundp 'characterp)
-                              (apply 'characterp (list last-command-event)))
-                         (apply 'char-to-int (list last-command-event)))
                         (t 0)))
          mapped-binding)
 
@@ -5137,7 +5121,7 @@ Optional FOLLOWERS arguments dictate exposure for 
succeeding siblings."
             (if (and spec
                      (allout-descend-to-depth new-depth)
                      (not (allout-hidden-p)))
-                (progn (setq got (apply 'allout-old-expose-topic spec))
+                (progn (setq got (apply #'allout-old-expose-topic spec))
                        (if (and got (or (not max-pos) (> got max-pos)))
                            (setq max-pos got)))))))
     (while (and followers
@@ -5215,7 +5199,7 @@ Optional arg CONTEXT indicates interior levels to 
include."
            (setq flat-index (cdr flat-index)))
          ;; Dispose of single extra delim:
          (setq result (cdr result))))
-    (apply 'concat result)))
+    (apply #'concat result)))
 ;;;_   > allout-stringify-flat-index-plain (flat-index)
 (defun allout-stringify-flat-index-plain (flat-index)
   "Convert list representing section/subsection/... to document string."
@@ -5226,7 +5210,7 @@ Optional arg CONTEXT indicates interior levels to 
include."
                             (if result
                                 (cons delim result))))
          (setq flat-index (cdr flat-index)))
-    (apply 'concat result)))
+    (apply #'concat result)))
 ;;;_   > allout-stringify-flat-index-indented (flat-index)
 (defun allout-stringify-flat-index-indented (flat-index)
   "Convert list representing section/subsection/... to document string."
@@ -5255,7 +5239,7 @@ Optional arg CONTEXT indicates interior levels to 
include."
            (setq flat-index (cdr flat-index)))
          ;; Dispose of single extra delim:
          (setq result (cdr result))))
-    (apply 'concat result)))
+    (apply #'concat result)))
 ;;;_   > allout-listify-exposed (&optional start end format)
 (defun allout-listify-exposed (&optional start end format)
 
@@ -5381,7 +5365,7 @@ header and body.  The elements of that list are:
       ;; Put the list with first at front, to last at back:
       (nreverse result))))
 
-(define-obsolete-function-alias 'allout-region-active-p 'region-active-p 
"28.1")
+(define-obsolete-function-alias 'allout-region-active-p #'region-active-p 
"28.1")
 
 ;;_   > allout-process-exposed (&optional func from to frombuf
 ;;;                                        tobuf format)
@@ -5498,7 +5482,7 @@ alternate presentation format for the outline:
         (beg (if arg (allout-back-to-current-heading) (point-min)))
         (end (if arg (allout-end-of-current-subtree) (point-max)))
         (buf (current-buffer))
-        (start-list ()))
+        ) ;; (start-list ())
     (if (eq format 'flat)
        (setq format (if arg (save-excursion
                                   (goto-char beg)
@@ -5510,7 +5494,7 @@ alternate presentation format for the outline:
                             end
                             (current-buffer)
                             tobuf
-                            format start-list)
+                            format nil) ;; start-list
     (goto-char (point-min))
     (pop-to-buffer buf)
     (goto-char start-pt)))
@@ -5622,11 +5606,12 @@ environment.  Leaves point at the end of the line."
        (begindoc "\\begin{document}\n\\begin{center}\n")
        (title (format "%s%s%s%s"
                       "\\titlecmd{"
-                      (allout-latex-verb-quote (if allout-title
-                                               (condition-case nil
-                                                   (eval allout-title)
-                                                 (error "<unnamed buffer>"))
-                                             "Unnamed Outline"))
+                      (allout-latex-verb-quote
+                       (if allout-title
+                           (condition-case nil
+                               (eval allout-title t)
+                             (error "<unnamed buffer>"))
+                         "Unnamed Outline"))
                       "}\n"
                       "\\end{center}\n\n"))
        (hsize "\\hsize = 7.5 true in\n")
@@ -6219,7 +6204,7 @@ save.  See `allout-encrypt-unencrypted-on-saves' for more 
info."
 ;;;_   > outlineify-sticky ()
 ;; outlinify-sticky is correct spelling; provide this alias for sticklers:
 ;;;###autoload
-(defalias 'outlinify-sticky 'outlineify-sticky)
+(defalias 'outlinify-sticky #'outlineify-sticky)
 ;;;###autoload
 (defun outlineify-sticky (&optional _arg)
   "Activate outline mode and establish file var so it is started subsequently.
@@ -6441,7 +6426,7 @@ If BEG is bigger than END we return 0."
 ;;;_   > allout-format-quote (string)
 (defun allout-format-quote (string)
   "Return a copy of string with all \"%\" characters doubled."
-  (apply 'concat
+  (apply #'concat
          (mapcar (lambda (char) (if (= char ?%) "%%" (char-to-string char)))
                  string)))
 (define-obsolete-function-alias 'allout-flatten #'flatten-tree "27.1")
diff --git a/lisp/auth-source-pass.el b/lisp/auth-source-pass.el
index 39db1a7..a7b959c 100644
--- a/lisp/auth-source-pass.el
+++ b/lisp/auth-source-pass.el
@@ -27,16 +27,18 @@
 
 ;;; Commentary:
 
-;; Integrates password-store (http://passwordstore.org/) within
+;; Integrates password-store (https://passwordstore.org/) within
 ;; auth-source.
 
 ;;; Code:
 
 (require 'seq)
-(eval-when-compile (require 'subr-x))
 (require 'cl-lib)
 (require 'auth-source)
 (require 'url-parse)
+;; Use `eval-when-compile' after the other `require's to avoid spurious
+;; "might not be defined at runtime" warnings.
+(eval-when-compile (require 'subr-x))
 
 (defgroup auth-source-pass nil
   "password-store integration within auth-source."
@@ -123,7 +125,7 @@ ENTRY is the name of a password-store entry.
 The key used to retrieve the password is the symbol `secret'.
 
 The convention used as the format for a password-store file is
-the following (see http://www.passwordstore.org/#organization):
+the following (see https://www.passwordstore.org/#organization):
 
 secret
 key1: value1
diff --git a/lisp/avoid.el b/lisp/avoid.el
index 3b3848e..d3afecf 100644
--- a/lisp/avoid.el
+++ b/lisp/avoid.el
@@ -1,4 +1,4 @@
-;;; avoid.el --- make mouse pointer stay out of the way of editing
+;;; avoid.el --- make mouse pointer stay out of the way of editing  -*- 
lexical-binding: t -*-
 
 ;; Copyright (C) 1993-1994, 2000-2021 Free Software Foundation, Inc.
 
@@ -80,7 +80,6 @@ use either \\[customize] or \\[mouse-avoidance-mode]."
   :initialize 'custom-initialize-default
   :type '(choice (const :tag "none" nil) (const banish) (const jump)
                 (const animate) (const exile) (const proteus))
-  :group 'avoid
   :require 'avoid
   :version "20.3")
 
@@ -89,25 +88,21 @@ use either \\[customize] or \\[mouse-avoidance-mode]."
   "Average distance that mouse will be moved when approached by cursor.
 Only applies in Mouse Avoidance mode `jump' and its derivatives.
 For best results make this larger than `mouse-avoidance-threshold'."
-  :type 'integer
-  :group 'avoid)
+  :type 'integer)
 
 (defcustom mouse-avoidance-nudge-var 10
   "Variability of `mouse-avoidance-nudge-dist' (which see)."
-  :type 'integer
-  :group 'avoid)
+  :type 'integer)
 
 (defcustom mouse-avoidance-animation-delay .01
   "Delay between animation steps, in seconds."
-  :type 'number
-  :group 'avoid)
+  :type 'number)
 
 (defcustom mouse-avoidance-threshold 5
   "Mouse-pointer's flight distance.
 If the cursor gets closer than this, the mouse pointer will move away.
 Only applies in Mouse Avoidance modes `animate' and `jump'."
-  :type 'integer
-  :group 'avoid)
+  :type 'integer)
 
 (defcustom mouse-avoidance-banish-position '((frame-or-window . frame)
                                              (side . right)
@@ -380,7 +375,7 @@ redefine this function to suit your own tastes."
        (mouse-avoidance-nudge-mouse)
        (if (not (eq (selected-frame) (car old-pos)))
            ;; This should never happen.
-           (apply 'set-mouse-position old-pos)))))
+            (apply #'set-mouse-position old-pos)))))
 
 ;;;###autoload
 (defun mouse-avoidance-mode (&optional mode)
diff --git a/lisp/bs.el b/lisp/bs.el
index 9ed0ee5..154e359 100644
--- a/lisp/bs.el
+++ b/lisp/bs.el
@@ -120,8 +120,6 @@
 ;; can cycle through all file buffers and *scratch* although your current
 ;; configuration perhaps is "files" which ignores buffer *scratch*.
 
-;;; History:
-
 ;;; Code:
 
 ;; ----------------------------------------------------------------------
diff --git a/lisp/calendar/cal-bahai.el b/lisp/calendar/cal-bahai.el
index c2e4205..ff419c7 100644
--- a/lisp/calendar/cal-bahai.el
+++ b/lisp/calendar/cal-bahai.el
@@ -27,7 +27,7 @@
 ;; This collection of functions implements the features of calendar.el
 ;; and diary-lib.el that deal with the Bahá’í calendar.
 
-;; The Bahá’í (http://www.bahai.org) calendar system is based on a
+;; The Bahá’í (https://www.bahai.org) calendar system is based on a
 ;; solar cycle of 19 months with 19 days each.  The four remaining
 ;; "intercalary" days are called the Ayyám-i-Há (days of Há), and are
 ;; placed between the 18th and 19th months.  They are meant as a time
diff --git a/lisp/calendar/icalendar.el b/lisp/calendar/icalendar.el
index 8f4dbf0..04b525e 100644
--- a/lisp/calendar/icalendar.el
+++ b/lisp/calendar/icalendar.el
@@ -66,7 +66,7 @@
 ;;  0.02:
 ;;  - Should work in XEmacs now.  Thanks to Len Trigg for the XEmacs patches!
 ;;  - Added exporting from Emacs diary to ical.
-;;  - Some bugfixes, after testing with calendars from http://icalshare.com.
+;;  - Some bugfixes, after testing with calendars from https://icalshare.com.
 ;;  - Tested with Emacs 21.3.2 and XEmacs 21.4.12
 
 ;;  0.01: (2003-03-21)
@@ -105,10 +105,6 @@
 
 ;;; Code:
 
-(defconst icalendar-version "0.19"
-  "Version number of icalendar.el.")
-(make-obsolete-variable 'icalendar-version nil "28.1")
-
 ;; ======================================================================
 ;; Customizables
 ;; ======================================================================
@@ -2557,6 +2553,11 @@ the entry."
           (or (icalendar--get-event-property event 'URL) "")
           (or (icalendar--get-event-property event 'CLASS) "")))
 
+;; Obsolete
+
+(defconst icalendar-version "0.19" "Version number of icalendar.el.")
+(make-obsolete-variable 'icalendar-version 'emacs-version "28.1")
+
 (provide 'icalendar)
 
 ;;; icalendar.el ends here
diff --git a/lisp/calendar/iso8601.el b/lisp/calendar/iso8601.el
index 5a109a7..44c4811 100644
--- a/lisp/calendar/iso8601.el
+++ b/lisp/calendar/iso8601.el
@@ -41,7 +41,7 @@
 ;;
 ;; The standard can be found at:
 ;;
-;; 
http://www.loc.gov/standards/datetime/iso-tc154-wg5_n0038_iso_wd_8601-1_2016-02-16.pdf
+;; 
https://www.loc.gov/standards/datetime/iso-tc154-wg5_n0038_iso_wd_8601-1_2016-02-16.pdf
 ;;
 ;; The Wikipedia page on the standard is also informative:
 ;;
diff --git a/lisp/calendar/timeclock.el b/lisp/calendar/timeclock.el
index 0bbaa1e..4a4b65d 100644
--- a/lisp/calendar/timeclock.el
+++ b/lisp/calendar/timeclock.el
@@ -69,8 +69,6 @@
 ;; your average working time, and will make sure that the various
 ;; display functions return the correct value.
 
-;;; History:
-
 ;;; Code:
 
 (require 'cl-lib)
diff --git a/lisp/cedet/mode-local.el b/lisp/cedet/mode-local.el
index 4218b23..247f78e 100644
--- a/lisp/cedet/mode-local.el
+++ b/lisp/cedet/mode-local.el
@@ -91,13 +91,13 @@ MODES can be a symbol or a list of symbols.
 FUNCTION does not have arguments."
   (or (listp modes) (setq modes (list modes)))
   (mode-local-map-file-buffers
-   function #'(lambda ()
-               (let ((mm (mode-local-equivalent-mode-p major-mode))
-                     (ans nil))
-                 (while (and (not ans) mm)
-                   (setq ans (memq (car mm) modes)
-                         mm (cdr mm)) )
-                 ans))))
+   function (lambda ()
+              (let ((mm (mode-local-equivalent-mode-p major-mode))
+                    (ans nil))
+                (while (and (not ans) mm)
+                  (setq ans (memq (car mm) modes)
+                        mm (cdr mm)) )
+                ans))))
 
 ;;; Hook machinery
 ;;
@@ -323,14 +323,14 @@ Elements are (SYMBOL . PREVIOUS-VALUE), describing one 
variable."
       (dolist (mode modes)
        (when (setq table (get mode 'mode-local-symbol-table))
          (mapatoms
-          #'(lambda (var)
-              (when (get var 'mode-variable-flag)
-                (let ((v (intern (symbol-name var))))
-                  ;; Save the current buffer-local value of the
-                  ;; mode-local variable.
-                  (and (local-variable-p v (current-buffer))
-                       (push (cons v (symbol-value v)) old-locals))
-                  (set (make-local-variable v) (symbol-value var)))))
+           (lambda (var)
+             (when (get var 'mode-variable-flag)
+               (let ((v (intern (symbol-name var))))
+                 ;; Save the current buffer-local value of the
+                 ;; mode-local variable.
+                 (and (local-variable-p v (current-buffer))
+                      (push (cons v (symbol-value v)) old-locals))
+                 (set (make-local-variable v) (symbol-value var)))))
           table)))
       old-locals)))
 
@@ -348,9 +348,9 @@ If MODE is not specified it defaults to current 
`major-mode'."
     (while mode
       (when (setq table (get mode 'mode-local-symbol-table))
         (mapatoms
-         #'(lambda (var)
-             (when (get var 'mode-variable-flag)
-               (kill-local-variable (intern (symbol-name var)))))
+         (lambda (var)
+           (when (get var 'mode-variable-flag)
+             (kill-local-variable (intern (symbol-name var)))))
          table))
       (setq mode (get-mode-local-parent mode)))))
 
@@ -428,7 +428,7 @@ Return the value of the last VAL."
          ;; Save mode bindings
          (mode-local-bind (list ,@bl) '(mode-variable-flag t) ',mode)
          ;; Assign to local variables in all existing buffers in MODE
-         (mode-local-map-mode-buffers #'(lambda () ,@sl) ',mode)
+         (mode-local-map-mode-buffers (lambda () ,@sl) ',mode)
          ;; Return the last value
          ,tmp)
       )))
@@ -893,7 +893,7 @@ invoked interactively."
   (interactive
    (list (completing-read
           "Mode: " obarray
-          #'(lambda (s) (get s 'mode-local-symbol-table))
+          (lambda (s) (get s 'mode-local-symbol-table))
           t (symbol-name major-mode))))
   (when (setq mode (intern-soft mode))
     (mode-local-describe-bindings-1 mode (called-interactively-p 'any))))
diff --git a/lisp/cedet/pulse.el b/lisp/cedet/pulse.el
index d77d635..1e45067 100644
--- a/lisp/cedet/pulse.el
+++ b/lisp/cedet/pulse.el
@@ -153,7 +153,8 @@ Optional argument FACE specifies the face to do the 
highlighting."
       ;; with a reference face needed for the color.
       (pulse-reset-face face)
       (let* ((start (color-name-to-rgb
-                     (face-background 'pulse-highlight-start-face)))
+                     (face-background 'pulse-highlight-start-face
+                                      nil 'default)))
              (stop (color-name-to-rgb (face-background 'default)))
              (colors (mapcar (apply-partially 'apply 'color-rgb-to-hex)
                              (color-gradient start stop pulse-iterations))))
diff --git a/lisp/cedet/semantic.el b/lisp/cedet/semantic.el
index 15388f0..fb443fa 100644
--- a/lisp/cedet/semantic.el
+++ b/lisp/cedet/semantic.el
@@ -678,15 +678,15 @@ This function returns semantic tags without overlays."
       (if tag
           (if (car tag)
               (setq tag (mapcar
-                         #'(lambda (tag)
-                             ;; Set the 'reparse-symbol property to
-                             ;; NONTERM unless it was already setup
-                             ;; by a tag expander
-                             (or (semantic--tag-get-property
-                                  tag 'reparse-symbol)
-                                 (semantic--tag-put-property
-                                  tag 'reparse-symbol nonterm))
-                             tag)
+                         (lambda (tag)
+                           ;; Set the 'reparse-symbol property to
+                           ;; NONTERM unless it was already setup
+                           ;; by a tag expander
+                           (or (semantic--tag-get-property
+                                tag 'reparse-symbol)
+                               (semantic--tag-put-property
+                                tag 'reparse-symbol nonterm))
+                           tag)
                          (semantic--tag-expand tag))
                     result (append result tag))
             ;; No error in this case, a purposeful nil means don't
diff --git a/lisp/cedet/semantic/bovine/c.el b/lisp/cedet/semantic/bovine/c.el
index 5712f9b..e7ecb61 100644
--- a/lisp/cedet/semantic/bovine/c.el
+++ b/lisp/cedet/semantic/bovine/c.el
@@ -2244,8 +2244,8 @@ actually in their parent which is not accessible.")
        (if (obarrayp semantic-lex-spp-project-macro-symbol-obarray)
            (let ((macros nil))
              (mapatoms
-              #'(lambda (symbol)
-                  (setq macros (cons symbol macros)))
+               (lambda (symbol)
+                 (setq macros (cons symbol macros)))
               semantic-lex-spp-project-macro-symbol-obarray)
              (dolist (S macros)
                (princ "    ")
diff --git a/lisp/cedet/semantic/bovine/grammar.el 
b/lisp/cedet/semantic/bovine/grammar.el
index e3df7b1..a2717d7 100644
--- a/lisp/cedet/semantic/bovine/grammar.el
+++ b/lisp/cedet/semantic/bovine/grammar.el
@@ -25,9 +25,8 @@
 ;;
 ;; Major mode for editing Bovine's input grammar (.by) files.
 
-;;; History:
-
 ;;; Code:
+
 (require 'semantic)
 (require 'semantic/grammar)
 (require 'semantic/find)
@@ -476,7 +475,7 @@ Menu items are appended to the common grammar menu.")
             (with-current-buffer (find-file-noselect infile)
               (setq infile buffer-file-name)
               (if outdir (setq default-directory outdir))
-              (semantic-grammar-create-package nil t))
+              (semantic-grammar-create-package t t))
           (error (message "%s" (error-message-string err)) nil)))
        lang filename copyright-end)
     (when (and packagename
diff --git a/lisp/cedet/semantic/db-ebrowse.el 
b/lisp/cedet/semantic/db-ebrowse.el
index db37512..efdf3df 100644
--- a/lisp/cedet/semantic/db-ebrowse.el
+++ b/lisp/cedet/semantic/db-ebrowse.el
@@ -274,7 +274,7 @@ For instance: 
/home/<username>/.semanticdb/!usr!include!BROWSE"
       (insert-file-contents B)
       (let ((ans nil)
            (efcn (symbol-function 'ebrowse-show-progress)))
-       (fset 'ebrowse-show-progress #'(lambda (&rest _junk) nil))
+        (fset 'ebrowse-show-progress (lambda (&rest _junk) nil))
        (unwind-protect ;; Protect against errors w/ ebrowse
            (setq ans (list B (ebrowse-read)))
          ;; These items must always happen
diff --git a/lisp/cedet/semantic/db-global.el b/lisp/cedet/semantic/db-global.el
index 6bdc7b3..fad2448 100644
--- a/lisp/cedet/semantic/db-global.el
+++ b/lisp/cedet/semantic/db-global.el
@@ -56,7 +56,7 @@ values."
   (interactive
    (list (completing-read
           "Enable in Mode: " obarray
-          #'(lambda (s) (get s 'mode-local-symbol-table))
+          (lambda (s) (get s 'mode-local-symbol-table))
           t (symbol-name major-mode))))
 
   ;; First, make sure the version is ok.
diff --git a/lisp/cedet/semantic/edit.el b/lisp/cedet/semantic/edit.el
index 0cca156..b2e5636 100644
--- a/lisp/cedet/semantic/edit.el
+++ b/lisp/cedet/semantic/edit.el
@@ -154,8 +154,8 @@ Optional argument BUFFER is the buffer to search for 
changes in."
        (when (overlay-get (car ol) 'semantic-change)
          (setq ret (cons (car ol) ret)))
        (setq ol (cdr ol)))
-      (sort ret #'(lambda (a b) (< (overlay-start a)
-                                  (overlay-start b)))))))
+      (sort ret (lambda (a b) (< (overlay-start a)
+                                 (overlay-start b)))))))
 
 (defun semantic-edits-change-function-handle-changes  (start end _length)
   "Run whenever a buffer controlled by `semantic-mode' change.
diff --git a/lisp/cedet/semantic/fw.el b/lisp/cedet/semantic/fw.el
index 2a3b0f5..4ad70ff 100644
--- a/lisp/cedet/semantic/fw.el
+++ b/lisp/cedet/semantic/fw.el
@@ -270,11 +270,11 @@ later installation should be done in MODE hook."
   (mode-local-bind
    ;; Add the semantic- prefix to OVERLOAD short names.
    (mapcar
-    #'(lambda (e)
-        (let ((name (symbol-name (car e))))
-          (if (string-match "^semantic-" name)
-              e
-            (cons (intern (format "semantic-%s" name)) (cdr e)))))
+    (lambda (e)
+      (let ((name (symbol-name (car e))))
+        (if (string-match "^semantic-" name)
+            e
+          (cons (intern (format "semantic-%s" name)) (cdr e)))))
     overrides)
    (list 'constant-flag (not transient)
          'override-flag t)))
diff --git a/lisp/cedet/semantic/grammar.el b/lisp/cedet/semantic/grammar.el
index 8d8faac..dba289f 100644
--- a/lisp/cedet/semantic/grammar.el
+++ b/lisp/cedet/semantic/grammar.el
@@ -23,9 +23,6 @@
 ;;
 ;; Major mode framework for editing Semantic's input grammar files.
 
-;;; History:
-;;
-
 ;;; Code:
 
 (require 'semantic)
@@ -143,12 +140,12 @@ It ignores whitespaces, newlines and comments."
 ARGS are ASSOC's key value list."
   (let ((key t))
     `(semantic-tag-make-plist
-      ,@(mapcar #'(lambda (i)
-                    (prog1
-                        (if key
-                            (list 'quote i)
-                          i)
-                      (setq key (not key))))
+      ,@(mapcar (lambda (i)
+                  (prog1
+                      (if key
+                          (list 'quote i)
+                        i)
+                    (setq key (not key))))
                 args))))
 
 (defsubst semantic-grammar-quote-p (sym)
@@ -193,11 +190,11 @@ That is tag names plus names defined in tag attribute 
`:rest'."
                 class (current-buffer))))
     (apply #'append
            (mapcar
-            #'(lambda (tag)
-                (mapcar
-                 #'intern
-                 (cons (semantic-tag-name tag)
-                       (semantic-tag-get-attribute tag :rest))))
+            (lambda (tag)
+              (mapcar
+               #'intern
+               (cons (semantic-tag-name tag)
+                     (semantic-tag-get-attribute tag :rest))))
             tags))))
 
 (defsubst semantic-grammar-item-text (item)
@@ -298,9 +295,9 @@ foo.by it is foo-by."
 That is an alist of (VALUE . TOKEN) where VALUE is the string value of
 the keyword and TOKEN is the terminal symbol identifying the keyword."
   (mapcar
-   #'(lambda (key)
-       (cons (semantic-tag-get-attribute key :value)
-             (intern (semantic-tag-name key))))
+   (lambda (key)
+     (cons (semantic-tag-get-attribute key :value)
+           (intern (semantic-tag-name key))))
    (semantic-find-tags-by-class 'keyword (current-buffer))))
 
 (defun semantic-grammar-keyword-properties (keywords)
@@ -600,9 +597,6 @@ Typically a DEFINE expression should look like this:
 ;; PLEASE DO NOT MANUALLY EDIT THIS FILE!  It is automatically
 ;; generated from the grammar file " gram ".
 
-;;; History:
-;;
-
 ;;; Code:
 
 (require 'semantic/lex)
@@ -1069,7 +1063,7 @@ See also the variable `semantic-grammar-file-regexp'."
            (setq semantic--grammar-macros-regexp-1
                  (concat "(\\s-*"
                          (regexp-opt
-                          (mapcar #'(lambda (e) (symbol-name (car e)))
+                          (mapcar (lambda (e) (symbol-name (car e)))
                                   semantic-grammar-macros)
                           t)
                          "\\>"))
@@ -1862,11 +1856,11 @@ Optional argument COLOR determines if color is added to 
the text."
       (setq label "Keyword: ")
       (let (summary)
         (semantic--find-tags-by-function
-         #'(lambda (put)
-             (unless summary
-               (setq summary (cdr (assoc "summary"
-                                         (semantic-tag-get-attribute
-                                          put :value))))))
+         (lambda (put)
+           (unless summary
+             (setq summary (cdr (assoc "summary"
+                                       (semantic-tag-get-attribute
+                                        put :value))))))
          ;; Get `put' tag with TAG name.
          (semantic-find-tags-by-name-regexp
           (regexp-quote (semantic-tag-name tag))
diff --git a/lisp/cedet/semantic/idle.el b/lisp/cedet/semantic/idle.el
index b6633d7..420a457 100644
--- a/lisp/cedet/semantic/idle.el
+++ b/lisp/cedet/semantic/idle.el
@@ -216,9 +216,9 @@ And also manages services that depend on tag values."
     (let* ((inhibit-quit nil)
            (buffers (delq (current-buffer)
                           (delq nil
-                                (mapcar #'(lambda (b)
-                                            (and (buffer-file-name b)
-                                                 b))
+                                (mapcar (lambda (b)
+                                          (and (buffer-file-name b)
+                                               b))
                                         (buffer-list)))))
           ;; safe ;; This safe is not used, but could be.
            others
@@ -356,9 +356,9 @@ Uses `semantic-idle-work-for-on-buffer' to do the work."
                 (cb (current-buffer))
                 (buffers (delq (current-buffer)
                                (delq nil
-                                     (mapcar #'(lambda (b)
-                                                 (and (buffer-file-name b)
-                                                      b))
+                                      (mapcar (lambda (b)
+                                                (and (buffer-file-name b)
+                                                     b))
                                              (buffer-list)))))
                 safe) ;; errbuf
            ;; First, handle long tasks in the current buffer.
diff --git a/lisp/cedet/semantic/imenu.el b/lisp/cedet/semantic/imenu.el
index 2c5f10a..a5db85b 100644
--- a/lisp/cedet/semantic/imenu.el
+++ b/lisp/cedet/semantic/imenu.el
@@ -429,12 +429,12 @@ Optional argument PARENT is a tag parent of STREAM."
 Clears all imenu menus that may be depending on the database."
   (require 'semantic/db-mode)
   (semantic-map-buffers
-   #'(lambda ()
-       ;; Set up semanticdb environment if enabled.
-       (if (semanticdb-minor-mode-p)
-           (semanticdb-semantic-init-hook-fcn))
-       ;; Clear imenu cache to redraw the imenu.
-       (semantic-imenu-flush-fcn))))
+   (lambda ()
+     ;; Set up semanticdb environment if enabled.
+     (if (semanticdb-minor-mode-p)
+         (semanticdb-semantic-init-hook-fcn))
+     ;; Clear imenu cache to redraw the imenu.
+     (semantic-imenu-flush-fcn))))
 
 (add-hook 'semanticdb-mode-hook #'semantic-imenu-semanticdb-hook)
 
diff --git a/lisp/cedet/semantic/java.el b/lisp/cedet/semantic/java.el
index 8cadffa..f48b835 100644
--- a/lisp/cedet/semantic/java.el
+++ b/lisp/cedet/semantic/java.el
@@ -395,11 +395,11 @@ receives two arguments: the javadoc keyword and its 
associated
 removed from the result list."
   (delq nil
         (mapcar
-         #'(lambda (k)
-             (let* ((tag   (semantic-java-doc-tag k))
-                    (plist (semantic-lex-keyword-get tag 'javadoc)))
-               (if (or (not property) (plist-get plist property))
-                   (funcall fun k plist))))
+         (lambda (k)
+           (let* ((tag   (semantic-java-doc-tag k))
+                  (plist (semantic-lex-keyword-get tag 'javadoc)))
+             (if (or (not property) (plist-get plist property))
+                 (funcall fun k plist))))
          semantic-java-doc-line-tags)))
 
 
@@ -417,59 +417,59 @@ removed from the result list."
   (or semantic-java-doc-with-name-tags
       (setq semantic-java-doc-with-name-tags
             (semantic-java-doc-keywords-map
-             #'(lambda (k _p) k)
+             (lambda (k _p) k)
              'with-name)))
 
   (or semantic-java-doc-with-ref-tags
       (setq semantic-java-doc-with-ref-tags
             (semantic-java-doc-keywords-map
-             #'(lambda (k _p) k)
+             (lambda (k _p) k)
              'with-ref)))
 
   (or semantic-java-doc-extra-type-tags
       (setq semantic-java-doc-extra-type-tags
             (semantic-java-doc-keywords-map
-             #'(lambda (k p)
-                 (if (memq 'type (plist-get p 'usage))
-                     k))
+             (lambda (k p)
+               (if (memq 'type (plist-get p 'usage))
+                   k))
              'opt)))
 
   (or semantic-java-doc-extra-function-tags
       (setq semantic-java-doc-extra-function-tags
             (semantic-java-doc-keywords-map
-             #'(lambda (k p)
-                 (if (memq 'function (plist-get p 'usage))
-                     k))
+             (lambda (k p)
+               (if (memq 'function (plist-get p 'usage))
+                   k))
              'opt)))
 
   (or semantic-java-doc-extra-variable-tags
       (setq semantic-java-doc-extra-variable-tags
             (semantic-java-doc-keywords-map
-             #'(lambda (k p)
-                 (if (memq 'variable (plist-get p 'usage))
-                     k))
+             (lambda (k p)
+               (if (memq 'variable (plist-get p 'usage))
+                   k))
              'opt)))
 
   (or semantic-java-doc-type-tags
       (setq semantic-java-doc-type-tags
             (semantic-java-doc-keywords-map
-             #'(lambda (k p)
-                 (if (memq 'type (plist-get p 'usage))
-                     k)))))
+             (lambda (k p)
+               (if (memq 'type (plist-get p 'usage))
+                   k)))))
 
   (or semantic-java-doc-function-tags
       (setq semantic-java-doc-function-tags
             (semantic-java-doc-keywords-map
-             #'(lambda (k p)
-                 (if (memq 'function (plist-get p 'usage))
-                     k)))))
+             (lambda (k p)
+               (if (memq 'function (plist-get p 'usage))
+                   k)))))
 
   (or semantic-java-doc-variable-tags
       (setq semantic-java-doc-variable-tags
             (semantic-java-doc-keywords-map
-             #'(lambda (k p)
-                 (if (memq 'variable (plist-get p 'usage))
-                     k)))))
+             (lambda (k p)
+               (if (memq 'variable (plist-get p 'usage))
+                   k)))))
 
   )
 
diff --git a/lisp/cedet/semantic/lex-spp.el b/lisp/cedet/semantic/lex-spp.el
index 0b24bd2..8073640 100644
--- a/lisp/cedet/semantic/lex-spp.el
+++ b/lisp/cedet/semantic/lex-spp.el
@@ -278,10 +278,10 @@ The return list is meant to be saved in a semanticdb 
table."
   (let (macros)
     (when (obarrayp semantic-lex-spp-dynamic-macro-symbol-obarray)
       (mapatoms
-       #'(lambda (symbol)
-          (setq macros (cons (cons (symbol-name symbol)
-                                   (symbol-value symbol))
-                             macros)))
+       (lambda (symbol)
+         (setq macros (cons (cons (symbol-name symbol)
+                                  (symbol-value symbol))
+                            macros)))
        semantic-lex-spp-dynamic-macro-symbol-obarray))
     macros))
 
@@ -291,18 +291,18 @@ The value of each symbol is the replacement stream."
   (let (macros)
     (when (obarrayp semantic-lex-spp-macro-symbol-obarray)
       (mapatoms
-       #'(lambda (symbol)
-          (setq macros (cons symbol macros)))
+       (lambda (symbol)
+         (setq macros (cons symbol macros)))
        semantic-lex-spp-macro-symbol-obarray))
     (when (obarrayp semantic-lex-spp-project-macro-symbol-obarray)
       (mapatoms
-       #'(lambda (symbol)
-          (setq macros (cons symbol macros)))
+       (lambda (symbol)
+         (setq macros (cons symbol macros)))
        semantic-lex-spp-project-macro-symbol-obarray))
     (when (obarrayp semantic-lex-spp-dynamic-macro-symbol-obarray)
       (mapatoms
-       #'(lambda (symbol)
-          (setq macros (cons symbol macros)))
+       (lambda (symbol)
+         (setq macros (cons symbol macros)))
        semantic-lex-spp-dynamic-macro-symbol-obarray))
     macros))
 
diff --git a/lisp/cedet/semantic/lex.el b/lisp/cedet/semantic/lex.el
index 121e5c3..69f20de 100644
--- a/lisp/cedet/semantic/lex.el
+++ b/lisp/cedet/semantic/lex.el
@@ -192,9 +192,9 @@ If optional PROPERTY is non-nil, call FUN only on every 
symbol which
 as a PROPERTY value.  FUN receives a symbol as argument."
   (if (obarrayp table)
       (mapatoms
-       #'(lambda (symbol)
-           (if (or (null property) (get symbol property))
-               (funcall fun symbol)))
+       (lambda (symbol)
+         (if (or (null property) (get symbol property))
+             (funcall fun symbol)))
        table)))
 
 ;;; Lexical keyword table handling.
@@ -286,7 +286,7 @@ If optional PROPERTY is non-nil, return only keywords which 
have a
 PROPERTY set."
   (let (keywords)
     (semantic-lex-map-keywords
-     #'(lambda (symbol) (setq keywords (cons symbol keywords)))
+     (lambda (symbol) (setq keywords (cons symbol keywords)))
      property)
     keywords))
 
@@ -462,7 +462,7 @@ If optional PROPERTY is non-nil, return only type symbols 
which have
 PROPERTY set."
   (let (types)
     (semantic-lex-map-types
-     #'(lambda (symbol) (setq types (cons symbol types)))
+     (lambda (symbol) (setq types (cons symbol types)))
      property)
     types))
 
diff --git a/lisp/cedet/semantic/util-modes.el 
b/lisp/cedet/semantic/util-modes.el
index a02d566..1068628 100644
--- a/lisp/cedet/semantic/util-modes.el
+++ b/lisp/cedet/semantic/util-modes.el
@@ -162,7 +162,7 @@ too an interactive function used to toggle the mode."
   ;; Update the minor mode format.
   (semantic-mode-line-update)
   ;; Then turn MODE on or off in every Semantic enabled buffer.
-  (semantic-map-buffers #'(lambda () (funcall mode arg))))
+  (semantic-map-buffers (lambda () (funcall mode arg))))
 
 ;;;;
 ;;;; Minor mode to highlight areas that a user edits.
diff --git a/lisp/cedet/semantic/wisent.el b/lisp/cedet/semantic/wisent.el
index f498e7e..f5f381d 100644
--- a/lisp/cedet/semantic/wisent.el
+++ b/lisp/cedet/semantic/wisent.el
@@ -22,13 +22,10 @@
 ;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Commentary:
-;;
+
 ;; Here are functions necessary to use the Wisent LALR parser from
 ;; Semantic environment.
 
-;;; History:
-;;
-
 ;;; Code:
 
 (require 'semantic)
diff --git a/lisp/cedet/semantic/wisent/comp.el 
b/lisp/cedet/semantic/wisent/comp.el
index 6addc13..b96fa40 100644
--- a/lisp/cedet/semantic/wisent/comp.el
+++ b/lisp/cedet/semantic/wisent/comp.el
@@ -35,9 +35,6 @@
 ;;
 ;; For more details on Wisent itself read the Wisent manual.
 
-;;; History:
-;;
-
 ;;; Code:
 (require 'semantic/wisent)
 (eval-when-compile (require 'cl-lib))
@@ -69,7 +66,7 @@
   "Define a context NAME that will bind variables VARS."
   (declare (indent 1))
   (let* ((context (wisent-context-name name))
-         (declarations (mapcar #'(lambda (v) (list 'defvar v)) vars)))
+         (declarations (mapcar (lambda (v) (list 'defvar v)) vars)))
     `(progn
        ,@declarations
        (eval-when-compile
@@ -3488,11 +3485,11 @@ See also `wisent-compile-grammar' for more details on 
AUTOMATON."
        ;; in local variable OBN.
        ,@(let (obcode)
            (mapatoms
-            #'(lambda (s)
-                (setq obcode
-                      (cons `(fset (intern ,(symbol-name s) ,obn)
-                                   #',(symbol-function s))
-                            obcode)))
+            (lambda (s)
+              (setq obcode
+                    (cons `(fset (intern ,(symbol-name s) ,obn)
+                                 #',(symbol-function s))
+                          obcode)))
             obv)
            obcode)
        ;; Generate code to create the automaton.
@@ -3504,18 +3501,18 @@ See also `wisent-compile-grammar' for more details on 
AUTOMATON."
          ,@(mapcar
             ;; Use name `st' rather than `state' since `state' is
             ;; defined as dynbound in `semantic-actions' context above :-( !
-            #'(lambda (st) ;; for each state
-                `(list
-                  ,@(mapcar
-                     #'(lambda (tr) ;; for each transition
-                         (let ((k (car tr))  ; token
-                               (a (cdr tr))) ; action
-                           (if (and (symbolp a)
-                                    (intern-soft (symbol-name a) obv))
-                               `(cons ,(if (symbolp k) `(quote ,k) k)
-                                      (intern-soft ,(symbol-name a) ,obn))
-                             `(quote ,tr))))
-                     st)))
+            (lambda (st) ;; for each state
+              `(list
+                ,@(mapcar
+                   (lambda (tr) ;; for each transition
+                     (let ((k (car tr))  ; token
+                           (a (cdr tr))) ; action
+                       (if (and (symbolp a)
+                                (intern-soft (symbol-name a) obv))
+                           `(cons ,(if (symbolp k) `(quote ,k) k)
+                                  (intern-soft ,(symbol-name a) ,obn))
+                         `(quote ,tr))))
+                   st)))
             (aref automaton 0)))
         ;; The code of the goto table is unchanged.
         ,(aref automaton 1)
diff --git a/lisp/cedet/semantic/wisent/grammar.el 
b/lisp/cedet/semantic/wisent/grammar.el
index 819ebd5..c5e4554 100644
--- a/lisp/cedet/semantic/wisent/grammar.el
+++ b/lisp/cedet/semantic/wisent/grammar.el
@@ -198,10 +198,10 @@ See also the function `wisent-skip-token'."
 (defun wisent-grammar-assocs ()
   "Return associativity and precedence level definitions."
   (mapcar
-   #'(lambda (tag)
-       (cons (intern (semantic-tag-name tag))
-             (mapcar #'semantic-grammar-item-value
-                     (semantic-tag-get-attribute tag :value))))
+   (lambda (tag)
+     (cons (intern (semantic-tag-name tag))
+           (mapcar #'semantic-grammar-item-value
+                   (semantic-tag-get-attribute tag :value))))
    (semantic-find-tags-by-class 'assoc (current-buffer))))
 
 (defun wisent-grammar-terminals ()
@@ -209,14 +209,14 @@ See also the function `wisent-skip-token'."
 Keep order of declaration in the WY file without duplicates."
   (let (terms)
     (mapc
-     #'(lambda (tag)
-        (mapcar #'(lambda (name)
-                    (add-to-list 'terms (intern name)))
-                (cons (semantic-tag-name tag)
-                      (semantic-tag-get-attribute tag :rest))))
+     (lambda (tag)
+       (mapcar (lambda (name)
+                 (add-to-list 'terms (intern name)))
+               (cons (semantic-tag-name tag)
+                     (semantic-tag-get-attribute tag :rest))))
      (semantic--find-tags-by-function
-      #'(lambda (tag)
-         (memq (semantic-tag-class tag) '(token keyword)))
+      (lambda (tag)
+        (memq (semantic-tag-class tag) '(token keyword)))
       (current-buffer)))
     (nreverse terms)))
 
@@ -477,7 +477,7 @@ Menu items are appended to the common grammar menu.")
         (condition-case err
             (with-current-buffer (find-file-noselect infile)
               (if outdir (setq default-directory outdir))
-              (semantic-grammar-create-package nil t))
+              (semantic-grammar-create-package t t))
           (error (message "%s" (error-message-string err)) nil)))
        output-data)
     (when (setq output-data (assoc packagename 
wisent-make-parsers--parser-file-name))
diff --git a/lisp/cedet/semantic/wisent/java-tags.el 
b/lisp/cedet/semantic/wisent/java-tags.el
index b4a87be..90dd40c 100644
--- a/lisp/cedet/semantic/wisent/java-tags.el
+++ b/lisp/cedet/semantic/wisent/java-tags.el
@@ -24,9 +24,6 @@
 ;;; Commentary:
 ;;
 
-;;; History:
-;;
-
 ;;; Code:
 
 (require 'semantic/wisent)
diff --git a/lisp/cedet/semantic/wisent/python.el 
b/lisp/cedet/semantic/wisent/python.el
index 7a5761c..9ac4ed9 100644
--- a/lisp/cedet/semantic/wisent/python.el
+++ b/lisp/cedet/semantic/wisent/python.el
@@ -27,8 +27,6 @@
 
 ;;; Code:
 
-(require 'rx)
-
 ;; Try to load python support, but fail silently since it is only used
 ;; for optional functionality
 (require 'python nil t)
diff --git a/lisp/cedet/semantic/wisent/wisent.el 
b/lisp/cedet/semantic/wisent/wisent.el
index d205c0e..62d99ef 100644
--- a/lisp/cedet/semantic/wisent/wisent.el
+++ b/lisp/cedet/semantic/wisent/wisent.el
@@ -34,9 +34,6 @@
 ;;
 ;; For more details on Wisent itself read the Wisent manual.
 
-;;; History:
-;;
-
 ;;; Code:
 
 (defgroup wisent nil
diff --git a/lisp/chistory.el b/lisp/chistory.el
index 589b5b5..95c1b49 100644
--- a/lisp/chistory.el
+++ b/lisp/chistory.el
@@ -1,4 +1,4 @@
-;;; chistory.el --- list command history
+;;; chistory.el --- list command history  -*- lexical-binding: t -*-
 
 ;; Copyright (C) 1985, 2001-2021 Free Software Foundation, Inc.
 
@@ -71,8 +71,7 @@ If that function is given a list whose car is an element of 
this list,
 then it will return non-nil (indicating the list should be discarded from
 the history).
 Initially, all commands related to the command history are discarded."
-  :type '(repeat symbol)
-  :group 'chistory)
+  :type '(repeat symbol))
 
 (defvar list-command-history-filter 'default-command-history-filter
   "Predicate to test which commands should be excluded from the history 
listing.
@@ -90,8 +89,7 @@ from the command history."
 
 (defcustom list-command-history-max 32
   "If non-nil, maximum length of the listing produced by 
`list-command-history'."
-  :type '(choice integer (const nil))
-  :group 'chistory)
+  :type '(choice integer (const nil)))
 
 ;;;###autoload
 (defun list-command-history ()
@@ -127,10 +125,10 @@ The buffer is left in Command History mode."
   (let ((map (make-sparse-keymap)))
     (set-keymap-parent map (make-composed-keymap lisp-mode-shared-map
                                                  special-mode-map))
-    (define-key map "x" 'command-history-repeat)
-    (define-key map "\n" 'next-line)
-    (define-key map "\r" 'next-line)
-    (define-key map "\177" 'previous-line)
+    (define-key map "x" #'command-history-repeat)
+    (define-key map "\n" #'next-line)
+    (define-key map "\r" #'next-line)
+    (define-key map "\177" #'previous-line)
     map)
   "Keymap for `command-history-mode'.")
 
@@ -145,8 +143,7 @@ Keybindings:
 
 (defcustom command-history-hook nil
   "If non-nil, its value is called on entry to `command-history-mode'."
-  :type 'hook
-  :group 'chistory)
+  :type 'hook)
 
 (defun command-history-revert (_ignore-auto _noconfirm)
   (list-command-history))
@@ -165,7 +162,7 @@ The buffer for that command is the previous current buffer."
 
 ;;;###autoload
 (defun command-history ()
-  "Examine commands from `command-history' in a buffer.
+  "Examine commands from variable `command-history' in a buffer.
 The number of commands listed is controlled by `list-command-history-max'.
 The command history is filtered by `list-command-history-filter' if non-nil.
 Use \\<command-history-map>\\[command-history-repeat] to repeat the command on 
the current line.
diff --git a/lisp/cmuscheme.el b/lisp/cmuscheme.el
index 772891d..d43cdb1 100644
--- a/lisp/cmuscheme.el
+++ b/lisp/cmuscheme.el
@@ -421,7 +421,7 @@ in the next one.")
 
 (defun scheme-load-file (file-name)
   "Load a Scheme file FILE-NAME into the inferior Scheme process."
-  (interactive (comint-get-source "Load Scheme file: " scheme-prev-l/c-dir/file
+  (interactive (comint-get-source "Load Scheme file" scheme-prev-l/c-dir/file
                                  scheme-source-modes t)) ; t because `load'
                                                           ; needs an exact name
   (comint-check-source file-name) ; Check to see if buffer needs saved.
@@ -433,7 +433,7 @@ in the next one.")
 
 (defun scheme-compile-file (file-name)
   "Compile a Scheme file FILE-NAME in the inferior Scheme process."
-  (interactive (comint-get-source "Compile Scheme file: "
+  (interactive (comint-get-source "Compile Scheme file"
                                  scheme-prev-l/c-dir/file
                                  scheme-source-modes
                                  nil)) ; nil because COMPILE doesn't
diff --git a/lisp/comint.el b/lisp/comint.el
index 65072b0..b04d404 100644
--- a/lisp/comint.el
+++ b/lisp/comint.el
@@ -2946,7 +2946,7 @@ two arguments are used for determining defaults.)  If 
MUSTMATCH-P is true,
 then the filename reader will only accept a file that exists.
 
 A typical use:
- (interactive (comint-get-source \"Compile file: \" prev-lisp-dir/file
+ (interactive (comint-get-source \"Compile file\" prev-lisp-dir/file
                                  \\='(lisp-mode) t))"
   (let* ((def (comint-source-default prev-dir/file source-modes))
         (stringfile (comint-extract-string))
@@ -2959,9 +2959,7 @@ A typical use:
                     (car def)))
         (deffile (if sfile-p (file-name-nondirectory stringfile)
                     (cdr def)))
-        (ans (read-file-name (if deffile (format "%s(default %s) "
-                                                 prompt    deffile)
-                                prompt)
+        (ans (read-file-name (format-prompt prompt deffile)
                              defdir
                              (concat defdir deffile)
                              mustmatch-p)))
diff --git a/lisp/completion.el b/lisp/completion.el
index da2fb38..dc0af36 100644
--- a/lisp/completion.el
+++ b/lisp/completion.el
@@ -1,7 +1,6 @@
-;;; completion.el --- dynamic word-completion code
+;;; completion.el --- dynamic word-completion code  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1990, 1993, 1995, 1997, 2001-2021 Free Software
-;; Foundation, Inc.
+;; Copyright (C) 1990-2021 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: abbrev convenience
@@ -286,62 +285,52 @@
 (defcustom enable-completion t
   "Non-nil means enable recording and saving of completions.
 If nil, no new words are added to the database or saved to the init file."
-  :type 'boolean
-  :group 'completion)
+  :type 'boolean)
 
 (defcustom save-completions-flag t
   "Non-nil means save most-used completions when exiting Emacs.
 See also `save-completions-retention-time'."
-  :type 'boolean
-  :group 'completion)
+  :type 'boolean)
 
 (defcustom save-completions-file-name
   (locate-user-emacs-file "completions" ".completions")
   "The filename to save completions to."
-  :type 'file
-  :group 'completion)
+  :type 'file)
 
 (defcustom save-completions-retention-time 336
   "Discard a completion if unused for this many hours.
 \(1 day = 24, 1 week = 168).  If this is 0, non-permanent completions
 will not be saved unless these are used.  Default is two weeks."
-  :type 'integer
-  :group 'completion)
+  :type 'integer)
 
 (defcustom completion-on-separator-character nil
   "Non-nil means separator characters mark previous word as used.
 This means the word will be saved as a completion."
-  :type 'boolean
-  :group 'completion)
+  :type 'boolean)
 
 (defcustom completions-file-versions-kept kept-new-versions
   "Number of versions to keep for the saved completions file."
-  :type 'integer
-  :group 'completion)
+  :type 'integer)
 
 (defcustom completion-prompt-speed-threshold 4800
   "Minimum output speed at which to display next potential completion."
-  :type 'integer
-  :group 'completion)
+  :type 'integer)
 
 (defcustom completion-cdabbrev-prompt-flag nil
   "If non-nil, the next completion prompt does a cdabbrev search.
 This can be time consuming."
-  :type 'boolean
-  :group 'completion)
+  :type 'boolean)
 
 (defcustom completion-search-distance 15000
   "How far to search in the buffer when looking for completions.
 In number of characters.  If nil, search the whole buffer."
-  :type 'integer
-  :group 'completion)
+  :type 'integer)
 
 (defcustom completions-merging-modes '(lisp c)
   "List of modes {`c' or `lisp'} for automatic completions merging.
 Definitions from visited files which have these modes
 are automatically added to the completion database."
-  :type '(set (const lisp) (const c))
-  :group 'completion)
+  :type '(set (const lisp) (const c)))
 
 ;;(defvar *completion-auto-save-period* 1800
 ;;  "The period in seconds to wait for emacs to be idle before autosaving
@@ -950,9 +939,9 @@ Each symbol is bound to a single completion entry.")
 
 ;; READER Macros
 
-(defalias 'cmpl-prefix-entry-head 'car)
+(defalias 'cmpl-prefix-entry-head #'car)
 
-(defalias 'cmpl-prefix-entry-tail 'cdr)
+(defalias 'cmpl-prefix-entry-tail #'cdr)
 
 ;; WRITER Macros
 
@@ -978,31 +967,27 @@ Each symbol is bound to a single completion entry.")
   (setq cmpl-prefix-obarray (make-vector cmpl-obarray-length 0))
   (setq cmpl-obarray (make-vector cmpl-obarray-length 0)))
 
-(defvar completions-list-return-value)
-
 (defun list-all-completions ()
   "Return a list of all the known completion entries."
-  (let ((completions-list-return-value nil))
-    (mapatoms 'list-all-completions-1 cmpl-prefix-obarray)
-    completions-list-return-value))
-
-(defun list-all-completions-1 (prefix-symbol)
-  (if (boundp prefix-symbol)
-      (setq completions-list-return-value
-           (append (cmpl-prefix-entry-head (symbol-value prefix-symbol))
-                   completions-list-return-value))))
-
-(defun list-all-completions-by-hash-bucket ()
+  (let ((return-value nil))
+    (mapatoms (lambda (prefix-symbol)
+                (if (boundp prefix-symbol)
+                    (setq return-value
+                         (append (cmpl-prefix-entry-head
+                                  (symbol-value prefix-symbol))
+                                 return-value))))
+             cmpl-prefix-obarray)
+    return-value))
+
+(defun list-all-completions-by-hash-bucket () ;FIXME: Unused!
   "Return list of lists of known completion entries, organized by hash bucket."
-  (let ((completions-list-return-value nil))
-    (mapatoms 'list-all-completions-by-hash-bucket-1 cmpl-prefix-obarray)
-    completions-list-return-value))
-
-(defun list-all-completions-by-hash-bucket-1 (prefix-symbol)
-  (if (boundp prefix-symbol)
-      (setq completions-list-return-value
-           (cons (cmpl-prefix-entry-head (symbol-value prefix-symbol))
-                 completions-list-return-value))))
+  (let ((return-value nil))
+    (mapatoms (lambda (prefix-symbol)
+                (if (boundp prefix-symbol)
+                    (push (cmpl-prefix-entry-head (symbol-value prefix-symbol))
+                         return-value)))
+             cmpl-prefix-obarray)
+    return-value))
 
 
 ;;-----------------------------------------------
@@ -2155,7 +2140,6 @@ TYPE is the type of the wrapper to be added.  Can be 
:before or :under."
 (define-minor-mode dynamic-completion-mode
   "Toggle dynamic word-completion on or off."
   :global t
-  :group 'completion
   ;; This is always good, not specific to dynamic-completion-mode.
   (define-key function-key-map [C-return] [?\C-\r])
 
@@ -2239,7 +2223,7 @@ TYPE is the type of the wrapper to be added.  Can be 
:before or :under."
 (completion-def-wrapper 'delete-backward-char-untabify :backward)
 
 ;; Old name, non-namespace-clean.
-(defalias 'initialize-completions 'completion-initialize)
+(defalias 'initialize-completions #'completion-initialize)
 
 (provide 'completion)
 
diff --git a/lisp/dframe.el b/lisp/dframe.el
index e61d2ea..f4208f3 100644
--- a/lisp/dframe.el
+++ b/lisp/dframe.el
@@ -828,7 +828,7 @@ the mode-line."
 
 (defvar dframe-version "1.3"
   "The current version of the dedicated frame library.")
-(make-obsolete-variable 'dframe-version nil "28.1")
+(make-obsolete-variable 'dframe-version 'emacs-version "28.1")
 
 (provide 'dframe)
 
diff --git a/lisp/dirtrack.el b/lisp/dirtrack.el
index 795f1dd..7f76ef6 100644
--- a/lisp/dirtrack.el
+++ b/lisp/dirtrack.el
@@ -1,4 +1,4 @@
-;;; dirtrack.el --- Directory Tracking by watching the prompt
+;;; dirtrack.el --- Directory Tracking by watching the prompt  -*- 
lexical-binding: t -*-
 
 ;; Copyright (C) 1996, 2001-2021 Free Software Foundation, Inc.
 
@@ -77,7 +77,7 @@
 ;;   Running under tcsh:
 ;;   (setq-default dirtrack-list '("^%E \\([^ ]+\\)" 1))
 ;;
-;;   It might be worth mentioning in your file that emacs sources start up
+;;   It might be worth mentioning in your file that Emacs sources start up
 ;;   files of the form: ~/.emacs_<SHELL> where <SHELL> is the name of the
 ;;   shell.  So for example, I have the following in ~/.emacs_tcsh:
 ;;
@@ -123,7 +123,6 @@
   "List for directory tracking.
 First item is a regexp that describes where to find the path in a prompt.
 Second is a number, the regexp group to match."
-  :group 'dirtrack
   :type  '(sexp (regexp  :tag "Prompt Expression")
                (integer :tag "Regexp Group"))
   :version "24.1")
@@ -132,12 +131,10 @@ Second is a number, the regexp group to match."
 
 (defcustom dirtrack-debug nil
   "If non-nil, the function `dirtrack' will report debugging info."
-  :group 'dirtrack
   :type  'boolean)
 
 (defcustom dirtrack-debug-buffer "*Directory Tracking Log*"
   "Buffer in which to write directory tracking debug information."
-  :group 'dirtrack
   :type  'string)
 
 (defcustom dirtrack-directory-function
@@ -145,19 +142,16 @@ Second is a number, the regexp group to match."
       'dirtrack-windows-directory-function
     'file-name-as-directory)
   "Function to apply to the prompt directory for comparison purposes."
-  :group 'dirtrack
   :type  'function)
 
 (defcustom dirtrack-canonicalize-function
   (if (memq system-type '(ms-dos windows-nt cygwin))
       'downcase 'identity)
   "Function to apply to the default directory for comparison purposes."
-  :group 'dirtrack
   :type  'function)
 
 (defcustom dirtrack-directory-change-hook nil
   "Hook that is called when a directory change is made."
-  :group 'dirtrack
   :type 'hook)
 
 
diff --git a/lisp/doc-view.el b/lisp/doc-view.el
index cef0900..0ae2293 100644
--- a/lisp/doc-view.el
+++ b/lisp/doc-view.el
@@ -1802,11 +1802,6 @@ If BACKWARD is non-nil, jump to the previous match."
   (remove-overlays (point-min) (point-max) 'doc-view t)
   (if (consp image-mode-winprops-alist) (setq image-mode-winprops-alist nil)))
 
-(defun doc-view-intersection (l1 l2)
-  (let ((l ()))
-    (dolist (x l1) (if (memq x l2) (push x l)))
-    l))
-
 (defun doc-view-set-doc-type ()
   "Figure out the current document type (`doc-view-doc-type')."
   (let ((name-types
@@ -1841,7 +1836,7 @@ If BACKWARD is non-nil, jump to the previous match."
            ((looking-at "AT&TFORM") '(djvu))))))
     (setq-local
      doc-view-doc-type
-     (car (or (doc-view-intersection name-types content-types)
+     (car (or (nreverse (seq-intersection name-types content-types #'eq))
               (when (and name-types content-types)
                 (error "Conflicting types: name says %s but content says %s"
                        name-types content-types))
@@ -2146,6 +2141,12 @@ See the command `doc-view-mode' for more information on 
this mode."
     (add-hook 'bookmark-after-jump-hook show-fn-sym)
     (bookmark-default-handler bmk)))
 
+;; Obsolete.
+
+(defun doc-view-intersection (l1 l2)
+  (declare (obsolete seq-intersection "28.1"))
+  (nreverse (seq-intersection l1 l2 #'eq)))
+
 (provide 'doc-view)
 
 ;; Local Variables:
diff --git a/lisp/double.el b/lisp/double.el
index 7bc8d92..f9227a8 100644
--- a/lisp/double.el
+++ b/lisp/double.el
@@ -1,4 +1,4 @@
-;;; double.el --- support for keyboard remapping with double clicking
+;;; double.el --- support for keyboard remapping with double clicking  -*- 
lexical-binding: t -*-
 
 ;; Copyright (C) 1994, 1997-1998, 2001-2021 Free Software Foundation,
 ;; Inc.
@@ -67,7 +67,6 @@ Each entry is a list with three elements:
 1. The key activating the translation.
 2. The string to be inserted when the key is pressed once.
 3. The string to be inserted when the key is pressed twice."
-  :group 'double
   :type '(repeat (list (character :tag "Key")
                       (string :tag "Once")
                       (string :tag "Twice"))))
@@ -76,7 +75,6 @@ Each entry is a list with three elements:
   "Non-nil means that Double mode mapping only works for prefix keys.
 That is, for any key `X' in `double-map', `X' alone will be mapped
 but not `C-u X' or `ESC X' since the X is not the prefix key."
-  :group 'double
   :type 'boolean)
 
 ;;; Read Event
diff --git a/lisp/dynamic-setting.el b/lisp/dynamic-setting.el
index d6952ed..39d2a1d 100644
--- a/lisp/dynamic-setting.el
+++ b/lisp/dynamic-setting.el
@@ -1,4 +1,4 @@
-;;; dynamic-setting.el --- Support dynamic changes
+;;; dynamic-setting.el --- Support dynamic changes  -*- lexical-binding: t -*-
 
 ;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
 
@@ -91,4 +91,4 @@ Changes can be
          ((eq type 'tool-bar-style) (force-mode-line-update t)))))
 
 (define-key special-event-map [config-changed-event]
-  'dynamic-setting-handle-config-changed-event)
+  #'dynamic-setting-handle-config-changed-event)
diff --git a/lisp/ebuff-menu.el b/lisp/ebuff-menu.el
index fb73b2d..7fecf1a 100644
--- a/lisp/ebuff-menu.el
+++ b/lisp/ebuff-menu.el
@@ -1,4 +1,4 @@
-;;; ebuff-menu.el --- electric-buffer-list mode
+;;; ebuff-menu.el --- electric-buffer-list mode  -*- lexical-binding: t -*-
 
 ;; Copyright (C) 1985-1986, 1994, 2001-2021 Free Software Foundation,
 ;; Inc.
@@ -34,55 +34,53 @@
 
 (defvar electric-buffer-menu-mode-map
   (let ((map (make-keymap)))
-    (fillarray (car (cdr map)) 'Electric-buffer-menu-undefined)
+    (fillarray (car (cdr map)) #'Electric-buffer-menu-undefined)
     (define-key map "\e" nil)
-    (define-key map "\C-z" 'suspend-frame)
-    (define-key map "v" 'Electric-buffer-menu-mode-view-buffer)
-    (define-key map (char-to-string help-char) 'Helper-help)
-    (define-key map "?" 'Helper-describe-bindings)
+    (define-key map "\C-z" #'suspend-frame)
+    (define-key map "v" #'Electric-buffer-menu-mode-view-buffer)
+    (define-key map (char-to-string help-char) #'Helper-help)
+    (define-key map "?" #'Helper-describe-bindings)
     (define-key map "\C-c" nil)
-    (define-key map "\C-c\C-c" 'Electric-buffer-menu-quit)
-    (define-key map "\C-]" 'Electric-buffer-menu-quit)
-    (define-key map "q" 'Electric-buffer-menu-quit)
-    (define-key map " " 'Electric-buffer-menu-select)
-    (define-key map "\C-m" 'Electric-buffer-menu-select)
-    (define-key map "\C-l" 'recenter)
-    (define-key map "s" 'Buffer-menu-save)
-    (define-key map "d" 'Buffer-menu-delete)
-    (define-key map "k" 'Buffer-menu-delete)
-    (define-key map "\C-d" 'Buffer-menu-delete-backwards)
-    ;; (define-key map "\C-k" 'Buffer-menu-delete)
-    (define-key map "\177" 'Buffer-menu-backup-unmark)
-    (define-key map "~" 'Buffer-menu-not-modified)
-    (define-key map "u" 'Buffer-menu-unmark)
-    (define-key map "\M-\177" 'Buffer-menu-unmark-all-buffers)
-    (define-key map "U" 'Buffer-menu-unmark-all)
-    (let ((i ?0))
-      (while (<= i ?9)
-       (define-key map (char-to-string i) 'digit-argument)
-       (define-key map (concat "\e" (char-to-string i)) 'digit-argument)
-       (setq i (1+ i))))
-    (define-key map "-" 'negative-argument)
-    (define-key map "\e-" 'negative-argument)
-    (define-key map "m" 'Buffer-menu-mark)
-    (define-key map "\C-u" 'universal-argument)
-    (define-key map "\C-p" 'previous-line)
-    (define-key map "\C-n" 'next-line)
-    (define-key map "p" 'previous-line)
-    (define-key map "n" 'next-line)
-    (define-key map "\C-v" 'scroll-up-command)
-    (define-key map "\ev" 'scroll-down-command)
-    (define-key map ">" 'scroll-right)
-    (define-key map "<" 'scroll-left)
-    (define-key map "\e\C-v" 'scroll-other-window)
-    (define-key map "\e>" 'end-of-buffer)
-    (define-key map "\e<" 'beginning-of-buffer)
+    (define-key map "\C-c\C-c" #'Electric-buffer-menu-quit)
+    (define-key map "\C-]" #'Electric-buffer-menu-quit)
+    (define-key map "q" #'Electric-buffer-menu-quit)
+    (define-key map " " #'Electric-buffer-menu-select)
+    (define-key map "\C-m" #'Electric-buffer-menu-select)
+    (define-key map "\C-l" #'recenter)
+    (define-key map "s" #'Buffer-menu-save)
+    (define-key map "d" #'Buffer-menu-delete)
+    (define-key map "k" #'Buffer-menu-delete)
+    (define-key map "\C-d" #'Buffer-menu-delete-backwards)
+    ;; (define-key map "\C-k" #'Buffer-menu-delete)
+    (define-key map "\177" #'Buffer-menu-backup-unmark)
+    (define-key map "~" #'Buffer-menu-not-modified)
+    (define-key map "u" #'Buffer-menu-unmark)
+    (define-key map "\M-\177" #'Buffer-menu-unmark-all-buffers)
+    (define-key map "U" #'Buffer-menu-unmark-all)
+    (dotimes (i 10)
+      (define-key map (char-to-string i) #'digit-argument)
+      (define-key map (concat "\e" (char-to-string i)) #'digit-argument))
+    (define-key map "-" #'negative-argument)
+    (define-key map "\e-" #'negative-argument)
+    (define-key map "m" #'Buffer-menu-mark)
+    (define-key map "\C-u" #'universal-argument)
+    (define-key map "\C-p" #'previous-line)
+    (define-key map "\C-n" #'next-line)
+    (define-key map "p" #'previous-line)
+    (define-key map "n" #'next-line)
+    (define-key map "\C-v" #'scroll-up-command)
+    (define-key map "\ev" #'scroll-down-command)
+    (define-key map ">" #'scroll-right)
+    (define-key map "<" #'scroll-left)
+    (define-key map "\e\C-v" #'scroll-other-window)
+    (define-key map "\e>" #'end-of-buffer)
+    (define-key map "\e<" #'beginning-of-buffer)
     (define-key map "\e\e" nil)
-    (define-key map "\e\e\e" 'Electric-buffer-menu-quit)
+    (define-key map "\e\e\e" #'Electric-buffer-menu-quit)
     ;; This binding prevents the "escape => ESC" function-key-map mapping from
     ;; kicking in!
-    ;; (define-key map [escape escape escape] 'Electric-buffer-menu-quit)
-    (define-key map [mouse-2] 'Electric-buffer-menu-mouse-select)
+    ;; (define-key map [escape escape escape] #'Electric-buffer-menu-quit)
+    (define-key map [mouse-2] #'Electric-buffer-menu-mouse-select)
     map))
 
 (put 'Electric-buffer-menu-quit :advertised-binding "\C-c\C-c")
@@ -205,7 +203,7 @@ See the documentation of `electric-buffer-list' for 
details."
   (setq-local Helper-return-blurb "return to buffer editing"))
 
 (define-obsolete-function-alias 'Electric-buffer-menu-mode
-  'electric-buffer-menu-mode "24.3")
+  #'electric-buffer-menu-mode "24.3")
 
 ;; generally the same as Buffer-menu-mode-map
 ;;  (except we don't indirect to global-map)
diff --git a/lisp/echistory.el b/lisp/echistory.el
index 8f787e7..15679b1 100644
--- a/lisp/echistory.el
+++ b/lisp/echistory.el
@@ -1,4 +1,4 @@
-;;; echistory.el --- Electric Command History Mode
+;;; echistory.el --- Electric Command History Mode  -*- lexical-binding: t -*-
 
 ;; Copyright (C) 1985, 2001-2021 Free Software Foundation, Inc.
 
@@ -44,44 +44,43 @@ With prefix arg NOCONFIRM, execute current line as-is 
without editing."
 
 (defvar electric-history-map
   (let ((map (make-sparse-keymap)))
-    (define-key map [t] 'Electric-history-undefined)
+    (define-key map [t] #'Electric-history-undefined)
     (define-key map "\e" (make-sparse-keymap))
-    (define-key map [?\e t] 'Electric-history-undefined)
-    (define-key map "\C-u" 'universal-argument)
-    (define-key map " " 'Electric-command-history-redo-expression)
-    (define-key map "!" 'Electric-command-history-redo-expression)
-    (define-key map "\e\C-x" 'eval-sexp)
-    (define-key map "\e\C-d" 'down-list)
-    (define-key map "\e\C-u" 'backward-up-list)
-    (define-key map "\e\C-b" 'backward-sexp)
-    (define-key map "\e\C-f" 'forward-sexp)
-    (define-key map "\e\C-a" 'beginning-of-defun)
-    (define-key map "\e\C-e" 'end-of-defun)
-    (define-key map "\e\C-n" 'forward-list)
-    (define-key map "\e\C-p" 'backward-list)
-    (define-key map "q" 'Electric-history-quit)
+    (define-key map [?\e t] #'Electric-history-undefined)
+    (define-key map "\C-u" #'universal-argument)
+    (define-key map " " #'Electric-command-history-redo-expression)
+    (define-key map "!" #'Electric-command-history-redo-expression)
+    (define-key map "\e\C-d" #'down-list)
+    (define-key map "\e\C-u" #'backward-up-list)
+    (define-key map "\e\C-b" #'backward-sexp)
+    (define-key map "\e\C-f" #'forward-sexp)
+    (define-key map "\e\C-a" #'beginning-of-defun)
+    (define-key map "\e\C-e" #'end-of-defun)
+    (define-key map "\e\C-n" #'forward-list)
+    (define-key map "\e\C-p" #'backward-list)
+    (define-key map "q" #'Electric-history-quit)
     (define-key map "\C-c" nil)
-    (define-key map "\C-c\C-c" 'Electric-history-quit)
-    (define-key map "\C-]" 'Electric-history-quit)
-    (define-key map "\C-z" 'suspend-frame)
-    (define-key map (char-to-string help-char) 'Helper-help)
-    (define-key map "?" 'Helper-describe-bindings)
-    (define-key map "\e>" 'end-of-buffer)
-    (define-key map "\e<" 'beginning-of-buffer)
-    (define-key map "\n" 'next-line)
-    (define-key map "\r" 'next-line)
-    (define-key map "\177" 'previous-line)
-    (define-key map "\C-n" 'next-line)
-    (define-key map "\C-p" 'previous-line)
-    (define-key map "\ev" 'scroll-down)
-    (define-key map "\C-v" 'scroll-up)
-    (define-key map [home] 'beginning-of-buffer)
-    (define-key map [down] 'next-line)
-    (define-key map [up] 'previous-line)
-    (define-key map [prior] 'scroll-down)
-    (define-key map [next] 'scroll-up)
-    (define-key map "\C-l" 'recenter)
-    (define-key map "\e\C-v" 'scroll-other-window)
+    (define-key map "\C-c\C-c" #'Electric-history-quit)
+    (define-key map "\C-]" #'Electric-history-quit)
+    (define-key map "\C-z" #'suspend-frame)
+    (define-key map (char-to-string help-char) #'Helper-help)
+    (define-key map "?" #'Helper-describe-bindings)
+    (define-key map "\e>" #'end-of-buffer)
+    (define-key map "\e<" #'beginning-of-buffer)
+    (define-key map "\n" #'next-line)
+    (define-key map "\r" #'next-line)
+    (define-key map "\177" #'previous-line)
+    (define-key map "\C-n" #'next-line)
+    (define-key map "\C-p" #'previous-line)
+    (define-key map "\ev" #'scroll-down)
+    (define-key map "\C-v" #'scroll-up)
+    (define-key map [home] #'beginning-of-buffer)
+    (define-key map [down] #'next-line)
+    (define-key map [up] #'previous-line)
+    (define-key map [prior] #'scroll-down)
+    (define-key map [next] #'scroll-up)
+    (define-key map "\C-l" #'recenter)
+    (define-key map "\e\C-v" #'scroll-other-window)
     map)
   "Keymap for Electric Command History mode.")
 
@@ -141,7 +140,9 @@ The Command History listing is recomputed each time this 
mode is invoked."
 (defun Electric-history-undefined ()
   (interactive)
   (ding)
-  (message "%s" (substitute-command-keys "Type \\[Helper-help] for help, ? for 
commands, C-c C-c to quit, Space to execute"))
+  (message "%s" (substitute-command-keys "Type \\[Helper-help] for help, \
+\\[Helper-describe-bindings] for commands, \\[Electric-history-quit] to quit, \
+\\[Electric-command-history-redo-expression] to execute"))
   (sit-for 4))
 
 (defun Electric-history-quit ()
diff --git a/lisp/emacs-lisp/checkdoc.el b/lisp/emacs-lisp/checkdoc.el
index 6285166..96b16f7 100644
--- a/lisp/emacs-lisp/checkdoc.el
+++ b/lisp/emacs-lisp/checkdoc.el
@@ -160,9 +160,6 @@
 ;;     not specifically docstring related.  Would this even be useful?
 
 ;;; Code:
-(defvar checkdoc-version "0.6.2"
-  "Release version of checkdoc you are currently running.")
-(make-obsolete-variable 'checkdoc-version nil "28.1")
 
 (require 'cl-lib)
 (require 'help-mode) ;; for help-xref-info-regexp
@@ -2709,6 +2706,12 @@ function called to create the messages."
 
 (custom-add-option 'emacs-lisp-mode-hook 'checkdoc-minor-mode)
 
+;; Obsolete
+
+(defvar checkdoc-version "0.6.2"
+  "Release version of checkdoc you are currently running.")
+(make-obsolete-variable 'checkdoc-version 'emacs-version "28.1")
+
 (provide 'checkdoc)
 
 ;;; checkdoc.el ends here
diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el
index 4aa8ddc..67b7546 100644
--- a/lisp/emacs-lisp/lisp-mode.el
+++ b/lisp/emacs-lisp/lisp-mode.el
@@ -527,7 +527,7 @@ This will generate compile-time constants from BINDINGS."
          ;; This is too general -- rms.
          ;; A user complained that he has functions whose names start with `do'
          ;; and that they get the wrong color.
-         ;; That user has violated the http://www.cliki.net/Naming+conventions:
+         ;; That user has violated the 
https://www.cliki.net/Naming+conventions:
          ;; CL (but not EL!) `with-' (context) and `do-' (iteration)
          (,(concat "(\\(\\(do-\\|with-\\)" lisp-mode-symbol-regexp "\\)")
            (1 font-lock-keyword-face))
diff --git a/lisp/emacs-lisp/seq.el b/lisp/emacs-lisp/seq.el
index 2b8807f..6c15463 100644
--- a/lisp/emacs-lisp/seq.el
+++ b/lisp/emacs-lisp/seq.el
@@ -147,6 +147,7 @@ the sequence, and its index within the sequence."
   "Return a shallow copy of SEQUENCE."
   (copy-sequence sequence))
 
+;;;###autoload
 (cl-defgeneric seq-subseq (sequence start &optional end)
   "Return the sequence of elements of SEQUENCE from START to END.
 END is exclusive.
@@ -430,6 +431,7 @@ Equality is defined by TESTFN if non-nil or by `equal' if 
nil."
         (setq index (1+ index)))
       nil)))
 
+;;;###autoload
 (cl-defgeneric seq-uniq (sequence &optional testfn)
   "Return a list of the elements of SEQUENCE with duplicates removed.
 TESTFN is used to compare elements, or `equal' if TESTFN is nil."
@@ -467,6 +469,7 @@ Equality is defined by TESTFN if non-nil or by `equal' if 
nil."
               (seq-reverse sequence1)
               '()))
 
+;;;###autoload
 (cl-defgeneric seq-difference (sequence1 sequence2 &optional testfn)
   "Return a list of the elements that appear in SEQUENCE1 but not in SEQUENCE2.
 Equality is defined by TESTFN if non-nil or by `equal' if nil."
diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el
index 789d632..86d5130 100644
--- a/lisp/emacs-lisp/shortdoc.el
+++ b/lisp/emacs-lisp/shortdoc.el
@@ -168,15 +168,12 @@ There can be any number of :example/:result elements."
   (replace-regexp-in-string
    :eval (replace-regexp-in-string "[a-z]+" "_" "*foo*"))
   (string-trim
-   :no-manual t
    :args (string)
    :doc "Trim STRING of leading and trailing white space."
    :eval (string-trim " foo "))
   (string-trim-left
-   :no-manual t
    :eval (string-trim-left "oofoo" "o+"))
   (string-trim-right
-   :no-manual t
    :eval (string-trim-right "barkss" "s+"))
   (string-truncate-left
    :no-manual t
diff --git a/lisp/emacs-lisp/smie.el b/lisp/emacs-lisp/smie.el
index 44be9af..9944330 100644
--- a/lisp/emacs-lisp/smie.el
+++ b/lisp/emacs-lisp/smie.el
@@ -63,7 +63,7 @@
 ;; building the 2D precedence tables and then computing the precedence levels
 ;; from it) can be found in pages 187-194 of "Parsing techniques" by Dick Grune
 ;; and Ceriel Jacobs (BookBody.pdf available at
-;; http://dickgrune.com/Books/PTAPG_1st_Edition/).
+;; https://dickgrune.com/Books/PTAPG_1st_Edition/).
 ;;
 ;; OTOH we had to kill many chickens, read many coffee grounds, and practice
 ;; untold numbers of black magic spells, to come up with the indentation code.
diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el
index a451445..9c8c967 100644
--- a/lisp/emacs-lisp/subr-x.el
+++ b/lisp/emacs-lisp/subr-x.el
@@ -215,28 +215,6 @@ The variable list SPEC is the same as in `if-let'."
 
 (define-obsolete-function-alias 'string-reverse 'reverse "25.1")
 
-(defsubst string-trim-left (string &optional regexp)
-  "Trim STRING of leading string matching REGEXP.
-
-REGEXP defaults to \"[ \\t\\n\\r]+\"."
-  (if (string-match (concat "\\`\\(?:" (or regexp "[ \t\n\r]+") "\\)") string)
-      (substring string (match-end 0))
-    string))
-
-(defsubst string-trim-right (string &optional regexp)
-  "Trim STRING of trailing string matching REGEXP.
-
-REGEXP defaults to  \"[ \\t\\n\\r]+\"."
-  (let ((i (string-match-p (concat "\\(?:" (or regexp "[ \t\n\r]+") "\\)\\'")
-                           string)))
-    (if i (substring string 0 i) string)))
-
-(defsubst string-trim (string &optional trim-left trim-right)
-  "Trim STRING of leading and trailing strings matching TRIM-LEFT and 
TRIM-RIGHT.
-
-TRIM-LEFT and TRIM-RIGHT default to \"[ \\t\\n\\r]+\"."
-  (string-trim-left (string-trim-right string trim-right) trim-left))
-
 ;;;###autoload
 (defun string-truncate-left (string length)
   "Truncate STRING to LENGTH, replacing initial surplus with \"...\"."
diff --git a/lisp/emulation/edt-mapper.el b/lisp/emulation/edt-mapper.el
index c1c1772..0b15278 100644
--- a/lisp/emulation/edt-mapper.el
+++ b/lisp/emulation/edt-mapper.el
@@ -101,6 +101,8 @@
 (define-obsolete-variable-alias 'edt-window-system 'window-system "27.1")
 
 (defconst edt-xserver (when (eq window-system 'x)
+                        (declare-function x-server-vendor "xfns.c"
+                                          (&optional terminal))
                        ;; The Cygwin window manager has a `/' in its
                        ;; name, which breaks the generated file name of
                        ;; the custom key map file.  Replace `/' with a
diff --git a/lisp/emulation/edt.el b/lisp/emulation/edt.el
index 8f90ed2..f11afb1 100644
--- a/lisp/emulation/edt.el
+++ b/lisp/emulation/edt.el
@@ -178,9 +178,6 @@
 (defvar edt-user-global-map)
 (defvar rect-start-point)
 
-(defconst edt-version "4.0" "EDT Emulation version number.")
-(make-obsolete-variable 'edt-version nil "28.1")
-
 ;;;
 ;;;  User Configurable Variables
 ;;;
@@ -299,6 +296,8 @@ This means that an edt-user.el file was found in the user's 
`load-path'.")
 ;;;     o edt-emulation-on      o edt-load-keys
 ;;;
 (defconst edt-xserver (when (eq window-system 'x)
+                        (declare-function x-server-vendor "xfns.c"
+                                          (&optional terminal))
                        ;; The Cygwin window manager has a `/' in its
                        ;; name, which breaks the generated file name of
                        ;; the custom key map file.  Replace `/' with a
@@ -2531,6 +2530,9 @@ G-C-\\: Split Window                     |  FNDNXT  |   
Yank   |   CUT    |
   (set-frame-width nil 132)
   (message "Terminal width 132"))
 
+(defconst edt-version "4.0" "EDT Emulation version number.")
+(make-obsolete-variable 'edt-version 'emacs-version "28.1")
+
 (provide 'edt)
 
 ;;; edt.el ends here
diff --git a/lisp/emulation/viper-cmd.el b/lisp/emulation/viper-cmd.el
index 42d6c1e..728f790 100644
--- a/lisp/emulation/viper-cmd.el
+++ b/lisp/emulation/viper-cmd.el
@@ -1786,7 +1786,7 @@ Undo previous insertion and inserts new."
        (do-not-change-default t))
     (setq quote-str
          (viper-read-string-with-history
-          "Quote string: "
+          "Quote string"
           nil
           'viper-quote-region-history
            ;; FIXME: Use comment-region.
@@ -1995,24 +1995,17 @@ problems."
            #'viper-minibuffer-standard-hook
            (if (or (not (listp old)) (eq (car old) 'lambda))
                (list old) old))))
-       (val "")
-       (padding "")
-       temp-msg)
+       (val ""))
 
     (setq keymap (or keymap minibuffer-local-map)
          initial (or initial "")
-         viper-initial initial
-         temp-msg (if default
-                      (format "(default %s) " default)
-                    ""))
+         viper-initial initial)
 
     (setq viper-incomplete-ex-cmd nil)
-    (setq val (read-from-minibuffer prompt
-                                   (concat temp-msg initial val padding)
-                                   keymap nil history-var))
-    (setq minibuffer-setup-hook nil
-         padding (viper-array-to-string (this-command-keys))
-         temp-msg "")
+    (setq val (read-from-minibuffer (format-prompt prompt default)
+                                   nil
+                                   keymap nil history-var default))
+    (setq minibuffer-setup-hook nil)
     ;; the following tries to be smart about what to put in history
     (if (not (string= val (car (symbol-value history-var))))
        (push val (symbol-value history-var)))
@@ -3825,7 +3818,7 @@ Null string will repeat previous search."
   (let (buffer buffer-name)
     (setq buffer-name
          (funcall viper-read-buffer-function
-                  (format "Kill buffer (%s): "
+                  (format-prompt "Kill buffer"
                           (buffer-name (current-buffer)))))
     (setq buffer
          (if (null buffer-name)
@@ -4171,8 +4164,8 @@ and regexp replace."
   (interactive)
   (let (str)
     (setq str (viper-read-string-with-history
-              (if viper-re-query-replace "Query replace regexp: "
-                "Query replace: ")
+              (if viper-re-query-replace "Query replace regexp"
+                "Query replace")
               nil  ; no initial
               'viper-replace1-history
               (car viper-replace1-history) ; default
@@ -4187,7 +4180,7 @@ and regexp replace."
          (query-replace-regexp
           str
           (viper-read-string-with-history
-           (format-message "Query replace regexp `%s' with: " str)
+           (format-message "Query replace regexp `%s' with" str)
            nil  ; no initial
            'viper-replace1-history
            (car viper-replace1-history) ; default
@@ -4195,7 +4188,7 @@ and regexp replace."
        (query-replace
         str
         (viper-read-string-with-history
-         (format-message "Query replace `%s' with: " str)
+         (format-message "Query replace `%s' with" str)
          nil  ; no initial
          'viper-replace1-history
          (car viper-replace1-history) ; default
diff --git a/lisp/epg-config.el b/lisp/epg-config.el
index 59d097c..d32c8c8 100644
--- a/lisp/epg-config.el
+++ b/lisp/epg-config.el
@@ -1,4 +1,4 @@
-;;; epg-config.el --- configuration of the EasyPG Library
+;;; epg-config.el --- configuration of the EasyPG Library  -*- 
lexical-binding: t -*-
 
 ;; Copyright (C) 2006-2021 Free Software Foundation, Inc.
 
@@ -21,6 +21,8 @@
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
 
+;;; Commentary:
+
 ;;; Code:
 ;;; Prelude
 
@@ -157,7 +159,7 @@ version requirement is met."
     (setq program-alist epg-config--program-alist))
   (let ((entry (assq protocol program-alist)))
     (unless entry
-      (error "Unknown protocol %S" protocol))
+      (error "Unknown protocol `%S'" protocol))
     (cl-destructuring-bind (symbol . alist)
         (cdr entry)
       (let ((constructor
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index b6dea95..2f6e48d 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -50,9 +50,6 @@
 ;; After you are connected to a server, you can use C-h m or have a look at
 ;; the ERC menu.
 
-;;; History:
-;;
-
 ;;; Code:
 
 (load "erc-loaddefs" nil t)
diff --git a/lisp/eshell/em-dirs.el b/lisp/eshell/em-dirs.el
index c702ee1..c04a1a6 100644
--- a/lisp/eshell/em-dirs.el
+++ b/lisp/eshell/em-dirs.el
@@ -199,10 +199,10 @@ Thus, this does not include the current directory.")
 
   (when eshell-cd-on-directory
     (setq-local eshell-interpreter-alist
-         (cons (cons #'(lambda (file _args)
-                          (eshell-lone-directory-p file))
-                     'eshell-dirs-substitute-cd)
-               eshell-interpreter-alist)))
+                (cons (cons (lambda (file _args)
+                              (eshell-lone-directory-p file))
+                            'eshell-dirs-substitute-cd)
+                      eshell-interpreter-alist)))
 
   (add-hook 'eshell-parse-argument-hook
            #'eshell-parse-user-reference nil t)
diff --git a/lisp/eshell/em-hist.el b/lisp/eshell/em-hist.el
index b7b1778..e559f5b 100644
--- a/lisp/eshell/em-hist.el
+++ b/lisp/eshell/em-hist.el
@@ -758,7 +758,7 @@ matched."
        (setq nth (eshell-hist-word-reference nth)))
       (unless (numberp mth)
        (setq mth (eshell-hist-word-reference mth)))
-      (cons (mapconcat #'identity (eshell-sublist textargs nth mth) " ")
+      (cons (mapconcat #'identity (seq-subseq textargs nth (1+ mth)) " ")
            end))))
 
 (defun eshell-hist-parse-modifier (hist reference)
diff --git a/lisp/eshell/em-pred.el b/lisp/eshell/em-pred.el
index aecc8bb..0780d6e 100644
--- a/lisp/eshell/em-pred.el
+++ b/lisp/eshell/em-pred.el
@@ -85,18 +85,18 @@ ordinary strings."
     (?s . (eshell-pred-file-mode #o4000)) ; setuid
     (?S . (eshell-pred-file-mode #o2000)) ; setgid
     (?t . (eshell-pred-file-mode #o1000)) ; sticky bit
-    (?U . #'(lambda (file)                   ; owned by effective uid
-              (if (file-exists-p file)
-                  (= (file-attribute-user-id (file-attributes file))
-                    (user-uid)))))
-    ;; (?G . #'(lambda (file)               ; owned by effective gid
-    ;;          (if (file-exists-p file)
-    ;;              (= (file-attribute-user-id (file-attributes file))
-    ;;                 (user-uid)))))
-    (?* . #'(lambda (file)
-              (and (file-regular-p file)
-                   (not (file-symlink-p file))
-                   (file-executable-p file))))
+    (?U . (lambda (file)                   ; owned by effective uid
+            (if (file-exists-p file)
+                (= (file-attribute-user-id (file-attributes file))
+                   (user-uid)))))
+    ;; (?G . (lambda (file)               ; owned by effective gid
+    ;;         (if (file-exists-p file)
+    ;;             (= (file-attribute-user-id (file-attributes file))
+    ;;                (user-uid)))))
+    (?* . (lambda (file)
+            (and (file-regular-p file)
+                 (not (file-symlink-p file))
+                 (file-executable-p file))))
     (?l . (eshell-pred-file-links))
     (?u . (eshell-pred-user-or-group ?u "user" 2 'eshell-user-id))
     (?g . (eshell-pred-user-or-group ?g "group" 3 'eshell-group-id))
@@ -114,25 +114,25 @@ The format of each entry is
 (put 'eshell-predicate-alist 'risky-local-variable t)
 
 (defcustom eshell-modifier-alist
-  '((?E . #'(lambda (lst)
-              (mapcar
-               (lambda (str)
-                 (eshell-stringify
-                  (car (eshell-parse-argument str))))
-               lst)))
-    (?L . #'(lambda (lst) (mapcar 'downcase lst)))
-    (?U . #'(lambda (lst) (mapcar 'upcase lst)))
-    (?C . #'(lambda (lst) (mapcar 'capitalize lst)))
-    (?h . #'(lambda (lst) (mapcar 'file-name-directory lst)))
+  '((?E . (lambda (lst)
+            (mapcar
+             (lambda (str)
+               (eshell-stringify
+                (car (eshell-parse-argument str))))
+             lst)))
+    (?L . (lambda (lst) (mapcar #'downcase lst)))
+    (?U . (lambda (lst) (mapcar #'upcase lst)))
+    (?C . (lambda (lst) (mapcar #'capitalize lst)))
+    (?h . (lambda (lst) (mapcar #'file-name-directory lst)))
     (?i . (eshell-include-members))
     (?x . (eshell-include-members t))
-    (?r . #'(lambda (lst) (mapcar 'file-name-sans-extension lst)))
-    (?e . #'(lambda (lst) (mapcar 'file-name-extension lst)))
-    (?t . #'(lambda (lst) (mapcar 'file-name-nondirectory lst)))
-    (?q . #'(lambda (lst) (mapcar 'eshell-escape-arg lst)))
-    (?u . #'(lambda (lst) (eshell-uniquify-list lst)))
-    (?o . #'(lambda (lst) (sort lst 'string-lessp)))
-    (?O . #'(lambda (lst) (nreverse (sort lst 'string-lessp))))
+    (?r . (lambda (lst) (mapcar #'file-name-sans-extension lst)))
+    (?e . (lambda (lst) (mapcar #'file-name-extension lst)))
+    (?t . (lambda (lst) (mapcar #'file-name-nondirectory lst)))
+    (?q . (lambda (lst) (mapcar #'eshell-escape-arg lst)))
+    (?u . (lambda (lst) (seq-uniq lst)))
+    (?o . (lambda (lst) (sort lst #'string-lessp)))
+    (?O . (lambda (lst) (nreverse (sort lst #'string-lessp))))
     (?j . (eshell-join-members))
     (?S . (eshell-split-members))
     (?R . 'reverse)
diff --git a/lisp/eshell/em-script.el b/lisp/eshell/em-script.el
index aecc486..658ea08 100644
--- a/lisp/eshell/em-script.el
+++ b/lisp/eshell/em-script.el
@@ -59,11 +59,11 @@ This includes when running `eshell-command'."
 (defun eshell-script-initialize ()  ;Called from `eshell-mode' via intern-soft!
   "Initialize the script parsing code."
   (setq-local eshell-interpreter-alist
-       (cons (cons #'(lambda (file _args)
-                        (string= (file-name-nondirectory file)
-                                 "eshell"))
-                    'eshell/source)
-             eshell-interpreter-alist))
+              (cons (cons (lambda (file _args)
+                            (string= (file-name-nondirectory file)
+                                     "eshell"))
+                          'eshell/source)
+                    eshell-interpreter-alist))
   (setq-local eshell-complex-commands
        (append '("source" ".") eshell-complex-commands))
   ;; these two variables are changed through usage, but we don't want
diff --git a/lisp/eshell/esh-mode.el b/lisp/eshell/esh-mode.el
index d29b010..f9dbce9 100644
--- a/lisp/eshell/esh-mode.el
+++ b/lisp/eshell/esh-mode.el
@@ -458,7 +458,7 @@ and the hook `eshell-exit-hook'."
   (let ((inhibit-read-only t)
        (no-default (eobp))
        (find-tag-default-function 'ignore))
-    (setq tagname (car (find-tag-interactive "Find tag: " no-default)))
+    (setq tagname (car (find-tag-interactive "Find tag" no-default)))
     (with-suppressed-warnings ((obsolete find-tag))
       (find-tag tagname next-p regexp-p))))
 
diff --git a/lisp/eshell/esh-opt.el b/lisp/eshell/esh-opt.el
index c1db484..7d31845 100644
--- a/lisp/eshell/esh-opt.el
+++ b/lisp/eshell/esh-opt.el
@@ -23,14 +23,6 @@
 
 ;;; Code:
 
-
-;; Unused.
-;; (defgroup eshell-opt nil
-;;   "The options processing code handles command argument parsing for
-;; Eshell commands implemented in Lisp."
-;;   :tag "Command options processing"
-;;   :group 'eshell)
-
 ;;; User Functions:
 
 ;; Macro expansion of eshell-eval-using-options refers to eshell-stringify-list
diff --git a/lisp/eshell/esh-util.el b/lisp/eshell/esh-util.el
index 8ef1ac9..a48f626 100644
--- a/lisp/eshell/esh-util.el
+++ b/lisp/eshell/esh-util.el
@@ -223,18 +223,6 @@ then quoting is done by a backslash, rather than a doubled 
delimiter."
              (string-to-number string)
            string))))))
 
-(defun eshell-sublist (l &optional n m)
-  "Return from LIST the N to M elements.
-If N or M is nil, it means the end of the list."
-  (let ((a (copy-sequence l)))
-    (if (and m (consp (nthcdr m a)))
-       (setcdr (nthcdr m a) nil))
-    (if n
-       (setq a (nthcdr n a))
-      (setq n (1- (length a))
-           a (last a)))
-    a))
-
 (defvar-local eshell-path-env (getenv "PATH")
   "Content of $PATH.
 It might be different from \(getenv \"PATH\"), when
@@ -303,20 +291,6 @@ Prepend remote identification of `default-directory', if 
any."
 
 (define-obsolete-function-alias 'eshell-flatten-list #'flatten-tree "27.1")
 
-(defun eshell-uniquify-list (l)
-  "Remove occurring multiples in L.  You probably want to sort first."
-  (let ((m l))
-    (while m
-      (while (and (cdr m)
-                 (string= (car m)
-                          (cadr m)))
-       (setcdr m (cddr m)))
-      (setq m (cdr m))))
-  l)
-(define-obsolete-function-alias
-  'eshell-uniqify-list
-  'eshell-uniquify-list "27.1")
-
 (defun eshell-stringify (object)
   "Convert OBJECT into a string value."
   (cond
@@ -710,9 +684,19 @@ gid format.  Valid values are `string' and `integer', 
defaulting to
 ;     (or result
 ;      (file-attributes filename))))
 
+;; Obsolete.
+
+(define-obsolete-function-alias 'eshell-uniquify-list #'seq-uniq "28.1")
+(define-obsolete-function-alias 'eshell-uniqify-list #'seq-uniq "28.1")
 (define-obsolete-function-alias 'eshell-copy-tree #'copy-tree "28.1")
 (define-obsolete-function-alias 'eshell-user-name #'user-login-name "28.1")
 
+(defun eshell-sublist (l &optional n m)
+  "Return from LIST the N to M elements.
+If N or M is nil, it means the end of the list."
+  (declare (obsolete seq-subseq "28.1"))
+  (seq-subseq l n (1+ m)))
+
 (provide 'esh-util)
 
 ;;; esh-util.el ends here
diff --git a/lisp/eshell/eshell.el b/lisp/eshell/eshell.el
index 3aaf2fb..101ac86 100644
--- a/lisp/eshell/eshell.el
+++ b/lisp/eshell/eshell.el
@@ -294,9 +294,9 @@ With prefix ARG, insert output into the current buffer at 
point."
     (setq arg current-prefix-arg))
   (let ((eshell-non-interactive-p t))
     ;; Enable `eshell-mode' only in this minibuffer.
-    (minibuffer-with-setup-hook #'(lambda ()
-                                    (eshell-mode)
-                                    (eshell-command-mode +1))
+    (minibuffer-with-setup-hook (lambda ()
+                                  (eshell-mode)
+                                  (eshell-command-mode +1))
       (unless command
         (setq command (read-from-minibuffer "Emacs shell command: "))
        (if (eshell-using-module 'eshell-hist)
diff --git a/lisp/faces.el b/lisp/faces.el
index 92f218b..da848c5 100644
--- a/lisp/faces.el
+++ b/lisp/faces.el
@@ -503,7 +503,8 @@ If INHERIT is t, and FACE doesn't define a foreground 
color, then any
   foreground color that FACE inherits through its `:inherit' attribute
   is considered as well; however the return value may still be nil.
 If INHERIT is a face or a list of faces, then it is used to try to
-  resolve an unspecified foreground color.
+  resolve an unspecified foreground color, in addition to using any
+inherited color.
 
 To ensure that a valid color is always returned, use a value of
 `default' for INHERIT; this will resolve any unspecified values by
@@ -523,7 +524,8 @@ If INHERIT is t, and FACE doesn't define a background 
color, then any
   background color that FACE inherits through its `:inherit' attribute
   is considered as well; however the return value may still be nil.
 If INHERIT is a face or a list of faces, then it is used to try to
-  resolve an unspecified background color.
+  resolve an unspecified background color, in addition to using any
+inherited color.
 
 To ensure that a valid color is always returned, use a value of
 `default' for INHERIT; this will resolve any unspecified values by
@@ -1260,7 +1262,15 @@ of a global face.  Value is the new attribute value."
                   (or (car (rassoc old-value valid))
                       (format "%s" old-value))))
             (setq new-value
-                  (face-read-string face default attribute-name valid))
+                   (if (memq attribute '(:foreground :background))
+                       (let ((color
+                              (read-color
+                               (format-prompt "%s for face `%s'"
+                                              default attribute-name face))))
+                         (if (equal (string-trim color) "")
+                             default
+                           color))
+                    (face-read-string face default attribute-name valid)))
             (if (equal new-value default)
                 ;; Nothing changed, so don't bother with all the stuff
                 ;; below.  In particular, this avoids a non-tty color
diff --git a/lisp/files-x.el b/lisp/files-x.el
index 526a128..23e4562 100644
--- a/lisp/files-x.el
+++ b/lisp/files-x.el
@@ -699,13 +699,14 @@ will not be changed."
         (copy-tree connection-local-variables-alist)))
    (hack-local-variables-apply)))
 
-(defsubst connection-local-criteria-for-default-directory ()
-  "Return a connection-local criteria, which represents `default-directory'."
+(defsubst connection-local-criteria-for-default-directory (&optional 
application)
+  "Return a connection-local criteria, which represents `default-directory'.
+If APPLICATION is nil, the symbol `tramp' is used."
   (when (file-remote-p default-directory)
-    `(:application tramp
-       :protocol ,(file-remote-p default-directory 'method)
-       :user     ,(file-remote-p default-directory 'user)
-       :machine  ,(file-remote-p default-directory 'host))))
+    `(:application ,(or application 'tramp)
+       :protocol   ,(file-remote-p default-directory 'method)
+       :user       ,(file-remote-p default-directory 'user)
+       :machine    ,(file-remote-p default-directory 'host))))
 
 ;;;###autoload
 (defmacro with-connection-local-variables (&rest body)
diff --git a/lisp/foldout.el b/lisp/foldout.el
index 2de49d2..3419d7f 100644
--- a/lisp/foldout.el
+++ b/lisp/foldout.el
@@ -230,14 +230,6 @@ An end marker of nil means the fold ends after 
(point-max).")
       (setcdr outl-entry (nconc foldout-entry (cdr outl-entry)))
       ))
 
-;; outline-flag-region has different `flag' values in outline.el and
-;; noutline.el for hiding and showing text.
-
-(defconst foldout-hide-flag
-  (if (featurep 'noutline) t ?\^M))
-
-(defconst foldout-show-flag
-  (if (featurep 'noutline) nil ?\n))
 
 
 (defun foldout-zoom-subtree (&optional exposure)
@@ -364,8 +356,7 @@ exited and text is left visible."
 
        ;; make sure the next heading is exposed
        (if end-marker
-           (outline-flag-region end-of-subtree beginning-of-heading
-                                foldout-show-flag)))
+            (outline-flag-region end-of-subtree beginning-of-heading nil)))
 
       ;; zap the markers so they don't slow down editing
       (set-marker start-marker nil)
@@ -551,6 +542,14 @@ Valid modifiers are shift, control, meta, alt, hyper and 
super.")
     (define-key outline-minor-mode-map mouse-3 'foldout-mouse-hide-or-exit)
     ))
 
+;; Obsolete.
+
+(defconst foldout-hide-flag t)
+(make-obsolete-variable 'foldout-hide-flag nil "28.1")
+
+(defconst foldout-show-flag nil)
+(make-obsolete-variable 'foldout-show-flag nil "28.1")
+
 (provide 'foldout)
 
 ;;; foldout.el ends here
diff --git a/lisp/follow.el b/lisp/follow.el
index 42e3b60..dde140d 100644
--- a/lisp/follow.el
+++ b/lisp/follow.el
@@ -1,4 +1,4 @@
-;;; follow.el --- synchronize windows showing the same buffer
+;;; follow.el --- synchronize windows showing the same buffer  -*- 
lexical-binding: t -*-
 
 ;; Copyright (C) 1995-1997, 1999, 2001-2021 Free Software Foundation,
 ;; Inc.
@@ -25,7 +25,7 @@
 
 ;;; Commentary:
 
-;; `Follow mode' is a minor mode that combines windows into one tall
+;; `follow-mode' is a minor mode that combines windows into one tall
 ;; virtual window.
 ;;
 ;; The feeling of a "virtual window" has been accomplished by the use
@@ -81,7 +81,7 @@
 ;;   text.  Enter long lines spanning several lines, or several
 ;;   windows.
 ;;
-;; * Should you find `Follow' mode annoying, just type
+;; * Should you find Follow mode annoying, just type
 ;;     M-x follow-mode <RETURN>
 ;;   to turn it off.
 
@@ -93,25 +93,24 @@
 ;; key map.  To do so, add the following lines (replacing `[f7]' and
 ;; `[f8]' with your favorite keys) to the init file:
 ;;
-;; (global-set-key [f8] 'follow-mode)
-;; (global-set-key [f7] 'follow-delete-other-windows-and-split)
+;; (global-set-key [f8] #'follow-mode)
+;; (global-set-key [f7] #'follow-delete-other-windows-and-split)
 
 
 ;; There exist two system variables that control the appearance of
 ;; lines wider than the window containing them.  The default is to
 ;; truncate long lines whenever a window isn't as wide as the frame.
 ;;
-;; To make sure lines are never truncated, please place the following
-;; lines in your init file:
+;; To make sure lines are never truncated, place the following lines
+;; in your Init file:
 ;;
 ;; (setq truncate-lines nil)
 ;; (setq truncate-partial-width-windows nil)
 
 
-;; The correct way to configure Follow mode, or any other mode for
-;; that matter, is to create one or more functions that do
-;; whatever you would like to do.  These functions are then added to
-;; a hook.
+;; One way to configure Follow mode is to create one or more functions
+;; that do whatever you would like to do.  These functions are then
+;; added to a hook.
 ;;
 ;; The keymap `follow-mode-map' contains key bindings activated by
 ;; `follow-mode'.
@@ -120,8 +119,8 @@
 ;; (add-hook 'follow-mode-hook 'my-follow-mode-hook)
 ;;
 ;; (defun my-follow-mode-hook ()
-;;    (define-key follow-mode-map "\C-ca" 'your-favorite-function)
-;;    (define-key follow-mode-map "\C-cb" 'another-function))
+;;    (define-key follow-mode-map "\C-ca" #'your-favorite-function)
+;;    (define-key follow-mode-map "\C-cb" #'another-function))
 
 
 ;; Usage:
@@ -129,60 +128,60 @@
 ;; To activate, issue the command "M-x follow-mode"
 ;; and press Return.  To deactivate, do it again.
 ;;
-;; The following is a list of commands useful when follow-mode is active.
+;; The following is a list of commands useful when `follow-mode' is active.
 ;;
-;;     follow-scroll-up                         C-c . C-v
+;;     `follow-scroll-up'                       C-c . C-v
 ;;             Scroll text in a Follow mode window chain up.
 ;;
-;;     follow-scroll-down                       C-c . v
+;;     `follow-scroll-down'                     C-c . v
 ;;             Like `follow-scroll-up', but in the other direction.
 ;;
-;;     follow-delete-other-windows-and-split    C-c . 1
+;;     `follow-delete-other-windows-and-split'  C-c . 1
 ;;             Maximize the visible area of the current buffer,
-;;             and enter Follow mode.  This is a very convenient
+;;             and enter Follow mode.          This is a very convenient
 ;;             way to start Follow mode, hence we recommend that
 ;;             this command be added to the global keymap.
 ;;
-;;     follow-recenter                          C-c . C-l
+;;     `follow-recenter'                                C-c . C-l
 ;;             Place point in the center of the middle window,
 ;;             or a specified number of lines from either top or bottom.
 ;;
-;;     follow-switch-to-buffer                  C-c . b
+;;     `follow-switch-to-buffer'                        C-c . b
 ;;             Switch buffer in all windows displaying the current buffer
 ;;             in this frame.
 ;;
-;;     follow-switch-to-buffer-all              C-c . C-b
+;;     `follow-switch-to-buffer-all'            C-c . C-b
 ;;             Switch buffer in all windows in the selected frame.
 ;;
-;;     follow-switch-to-current-buffer-all
+;;     `follow-switch-to-current-buffer-all'
 ;;             Show the current buffer in all windows on the current
 ;;             frame and turn on `follow-mode'.
 ;;
-;;     follow-first-window                      C-c . <
+;;     `follow-first-window'                    C-c . <
 ;;             Select the first window in the frame showing the same buffer.
 ;;
-;;     follow-last-window                       C-c . >
+;;     `follow-last-window'                     C-c . >
 ;;             Select the last window in the frame showing the same buffer.
 ;;
-;;     follow-next-window                       C-c . n
+;;     `follow-next-window'                     C-c . n
 ;;             Select the next window in the frame showing the same buffer.
 ;;
-;;     follow-previous-window                   C-c . p
+;;     `follow-previous-window'                         C-c . p
 ;;             Select the previous window showing the same buffer.
 
 
 ;; Well, it seems ok, but what if I really want to look at two different
-;; positions in the text? Here are two simple methods to use:
+;; positions in the text?  Here are two simple methods to use:
 ;;
 ;; 1) Use multiple frames; `follow' mode only affects windows displayed
-;;    in the same frame. (My apologies to you who can't use frames.)
+;;    in the same frame.  (My apologies to you who can't use frames.)
 ;;
 ;; 2) Bind `follow-mode' to key so you can turn it off whenever
-;;    you want to view two locations.  Of course, `follow' mode can
+;;    you want to view two locations.  Of course, `follow-mode' can
 ;;    be reactivated by hitting the same key again.
 ;;
 ;;    Example from my ~/.emacs:
-;;     (global-set-key [f8] 'follow-mode)
+;;     (global-set-key [f8] #'follow-mode)
 
 ;; Implementation:
 ;;
@@ -235,17 +234,17 @@ After that, changing the prefix key requires manipulating 
keymaps."
 (defvar follow-mode-map
   (let ((mainmap (make-sparse-keymap))
         (map (make-sparse-keymap)))
-    (define-key map "\C-v"     'follow-scroll-up)
-    (define-key map "\M-v"     'follow-scroll-down)
-    (define-key map "v"                'follow-scroll-down)
-    (define-key map "1"                'follow-delete-other-windows-and-split)
-    (define-key map "b"                'follow-switch-to-buffer)
-    (define-key map "\C-b"     'follow-switch-to-buffer-all)
-    (define-key map "\C-l"     'follow-recenter)
-    (define-key map "<"                'follow-first-window)
-    (define-key map ">"                'follow-last-window)
-    (define-key map "n"                'follow-next-window)
-    (define-key map "p"                'follow-previous-window)
+    (define-key map "\C-v"     #'follow-scroll-up)
+    (define-key map "\M-v"     #'follow-scroll-down)
+    (define-key map "v"                #'follow-scroll-down)
+    (define-key map "1"                #'follow-delete-other-windows-and-split)
+    (define-key map "b"                #'follow-switch-to-buffer)
+    (define-key map "\C-b"     #'follow-switch-to-buffer-all)
+    (define-key map "\C-l"     #'follow-recenter)
+    (define-key map "<"                #'follow-first-window)
+    (define-key map ">"                #'follow-last-window)
+    (define-key map "n"                #'follow-next-window)
+    (define-key map "p"                #'follow-previous-window)
 
     (define-key mainmap follow-mode-prefix map)
 
@@ -254,13 +253,13 @@ After that, changing the prefix key requires manipulating 
keymaps."
     ;; could be enhanced in Follow mode.  End-of-buffer is a special
     ;; case since it is very simple to define and it greatly enhances
     ;; the look and feel of Follow mode.)
-    (define-key mainmap [remap end-of-buffer] 'follow-end-of-buffer)
+    (define-key mainmap [remap end-of-buffer] #'follow-end-of-buffer)
 
-    (define-key mainmap [remap scroll-bar-toolkit-scroll] 
'follow-scroll-bar-toolkit-scroll)
-    (define-key mainmap [remap scroll-bar-drag] 'follow-scroll-bar-drag)
-    (define-key mainmap [remap scroll-bar-scroll-up] 
'follow-scroll-bar-scroll-up)
-    (define-key mainmap [remap scroll-bar-scroll-down] 
'follow-scroll-bar-scroll-down)
-    (define-key mainmap [remap mwheel-scroll] 'follow-mwheel-scroll)
+    (define-key mainmap [remap scroll-bar-toolkit-scroll] 
#'follow-scroll-bar-toolkit-scroll)
+    (define-key mainmap [remap scroll-bar-drag] #'follow-scroll-bar-drag)
+    (define-key mainmap [remap scroll-bar-scroll-up] 
#'follow-scroll-bar-scroll-up)
+    (define-key mainmap [remap scroll-bar-scroll-down] 
#'follow-scroll-bar-scroll-down)
+    (define-key mainmap [remap mwheel-scroll] #'follow-mwheel-scroll)
 
     mainmap)
   "Minor mode keymap for Follow mode.")
@@ -342,7 +341,7 @@ property `follow-mode-use-cache' to non-nil.")
 ;; Internal variables:
 
 (defvar follow-internal-force-redisplay nil
-  "True when Follow mode should redisplay the windows.")
+  "Non-nil when Follow mode should redisplay the windows.")
 
 (defvar follow-active-menu nil
   "The menu visible when Follow mode is active.")
@@ -369,7 +368,7 @@ This is typically set by explicit scrolling commands.")
 (defsubst follow-debug-message (&rest args)
   "Like `message', but only active when `follow-debug' is non-nil."
   (if (and (boundp 'follow-debug) follow-debug)
-      (apply 'message args)))
+      (apply #'message args)))
 
 ;;; Cache
 
@@ -1019,8 +1018,8 @@ returned by `follow-windows-start-end'."
       (setq win-start-end (cdr win-start-end)))
     result))
 
-;; Check if point is visible in all windows. (So that
-;; no one will be recentered.)
+;; Check if point is visible in all windows.
+;; (So that no one will be recentered.)
 
 (defun follow-point-visible-all-windows-p (win-start-end)
   "Non-nil when the `window-point' is visible in all windows."
@@ -1069,11 +1068,11 @@ Return the selected window."
     win))
 
 ;; Lets select a window showing the end. Make sure we only select it if
-;; it wasn't just moved here. (I.e. M-> shall not unconditionally place
+;; it wasn't just moved here.  (I.e. M-> shall not unconditionally place
 ;; point in the selected window.)
 ;;
 ;; (Compatibility kludge: in Emacs `window-end' is equal to `point-max';
-;; in XEmacs, it is equal to `point-max + 1'. Should I really bother
+;; in XEmacs, it is equal to `point-max + 1'.  Should I really bother
 ;; checking `window-end' now when I check `end-of-buffer' explicitly?)
 
 (defun follow-select-if-end-visible (win-start-end)
@@ -1097,7 +1096,7 @@ Return the selected window."
 
 
 ;; Select a window that will display point if the windows would
-;; be redisplayed with the first window fixed. This is useful for
+;; be redisplayed with the first window fixed.  This is useful for
 ;; example when the user has pressed return at the bottom of a window
 ;; as point is not visible in any window.
 
@@ -1202,7 +1201,7 @@ should be a member of WINDOWS, starts at position START."
       (goto-char guess)
       (while (not done)
        (if (not (= (vertical-motion 1 (car windows)) 1))
-           ;; Hit bottom! (Can we really do this?)
+            ;; Hit bottom!  (Can we really do this?)
            ;; We'll keep it, since it ensures termination.
            (progn
              (setq done t)
@@ -1283,7 +1282,7 @@ non-first windows in Follow mode."
 
 (defvar follow-prev-buffer nil
   "The buffer current at the last call to `follow-adjust-window' or nil.
-follow-mode is not necessarily enabled in this buffer.")
+`follow-mode' is not necessarily enabled in this buffer.")
 
 ;; This function is added to `pre-display-function' and is thus called
 ;; before each redisplay operation.  It supersedes (2018-09) the
@@ -1331,7 +1330,7 @@ follow-mode is not necessarily enabled in this buffer.")
 ;; .
 
 (defun follow-adjust-window (win)
-  ;; Adjust the window WIN and its followers.
+  "Adjust the window WIN and its followers."
   (cl-assert (eq (window-buffer win) (current-buffer)))
 
   ;; Have we moved out of or into a follow-mode window group?
@@ -1646,17 +1645,17 @@ This is updated by redisplay or by calling
 
 (defun follow-window-end (&optional window update)
   "Return position at which display currently ends in the Follow
-  Mode group of windows which includes WINDOW.
+Mode group of windows which includes WINDOW.
 
-  WINDOW must be a live window and defaults to the selected one.
-  This is updated by redisplay, when it runs to completion.
-  Simply changing the buffer text or setting `window-start' does
-  not update this value.
-
-  Return nil if there is no recorded value.  (This can happen if
-  the last redisplay of WINDOW was preempted, and did not
-  finish.)  If UPDATE is non-nil, compute the up-to-date position
-  if it isn't already recorded."
+WINDOW must be a live window and defaults to the selected one.
+This is updated by redisplay, when it runs to completion.
+Simply changing the buffer text or setting `window-start' does
+not update this value.
+
+Return nil if there is no recorded value.  (This can happen if
+the last redisplay of WINDOW was preempted, and did not
+finish.)  If UPDATE is non-nil, compute the up-to-date position
+if it isn't already recorded."
   (let* ((windows (follow-all-followers window))
          (last (car (last windows))))
     (when (and update follow-start-end-invalid)
@@ -1676,7 +1675,7 @@ overriding motion of point in order to display at this 
exact start."
 
 (defun follow-pos-visible-in-window-p (&optional pos window partially)
   "Return non-nil if position POS is currently on the frame in one of
-  the windows in the Follow Mode group which includes WINDOW.
+the windows in the Follow Mode group which includes WINDOW.
 
 WINDOW must be a live window and defaults to the selected one.
 
@@ -1695,8 +1694,7 @@ omitted if the character after POS is fully visible; 
otherwise, RTOP
 and RBOT are the number of pixels off-window at the top and bottom of
 the screen line (\"row\") containing POS, ROWH is the visible height
 of that row, and VPOS is the row number \(zero-based)."
-  (let* ((windows (follow-all-followers window))
-         (last (car (last windows))))
+  (let* ((windows (follow-all-followers window)))
     (when follow-start-end-invalid
       (follow-redisplay windows (car windows)))
     (let* ((cache (follow-windows-start-end windows))
@@ -1724,7 +1722,7 @@ zero means top of the first window in the group, negative 
means
          (start-end (follow-windows-start-end windows))
          (rev-start-end (reverse start-end))
          (lines 0)
-         middle-window elt count)
+         elt count)
     (select-window
      (cond
       ((null arg)
diff --git a/lisp/forms.el b/lisp/forms.el
index 62c4288..8696aea 100644
--- a/lisp/forms.el
+++ b/lisp/forms.el
@@ -1,7 +1,6 @@
-;;; forms.el --- Forms mode: edit a file as a form to fill in
+;;; forms.el --- Forms mode: edit a file as a form to fill in  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1991, 1994-1997, 2001-2021 Free Software Foundation,
-;; Inc.
+;; Copyright (C) 1991-2021 Free Software Foundation, Inc.
 
 ;; Author: Johan Vromans <jvromans@squirrel.nl>
 
@@ -298,7 +297,6 @@
 
 (defcustom forms-mode-hook nil
   "Hook run upon entering Forms mode."
-  :group 'forms
   :type 'hook)
 
 ;;; Mandatory variables - must be set by evaluating the control file.
@@ -316,7 +314,6 @@
 
 (defcustom forms-check-number-of-fields t
   "If non-nil, warn about records with wrong number of fields."
-  :group 'forms
   :type 'boolean)
 
 (defvar forms-field-sep "\t"
@@ -332,13 +329,11 @@ If not nil: use this character to separate multi-line 
fields (default C-k).")
 (defcustom forms-forms-scroll nil
   "Non-nil means replace scroll-up/down commands in Forms mode.
 The replacement commands performs forms-next/prev-record."
-  :group 'forms
   :type 'boolean)
 
 (defcustom forms-forms-jump nil
   "Non-nil means redefine beginning/end-of-buffer in Forms mode.
 The replacement commands performs forms-first/last-record."
-  :group 'forms
   :type 'boolean)
 
 (defvar forms-read-file-filter nil
@@ -363,23 +358,19 @@ The contents may NOT be modified.")
 
 (defcustom forms-use-text-properties t
   "Non-nil means to use text properties. "
-  :group 'forms
   :type 'boolean)
 
 (defcustom forms-insert-after nil
   "Non-nil means: inserts of new records go after current record.
 Also, initial position is at last record."
-  :group 'forms
   :type 'boolean)
 
 (defcustom forms-ro-face 'default
   "The face (a symbol) that is used to display read-only text on the screen."
-  :group 'forms
   :type 'face)
 
 (defcustom forms-rw-face 'region
   "The face (a symbol) that is used to display read-write text on the screen."
-  :group 'forms
   :type 'face)
 
 ;;; Internal variables.
@@ -767,7 +758,7 @@ Commands:                        Equivalent keys in 
read-only mode:
        ;; If it is a symbol, eval it first.
        (if (and (symbolp el)
                 (boundp el))
-           (setq el (eval el)))
+           (setq el (symbol-value el)))
 
        (cond
 
@@ -1261,35 +1252,35 @@ Commands:                        Equivalent keys in 
read-only mode:
 
   ;; `forms-mode-map' is always accessible via \C-c prefix.
   (setq forms-mode-map (make-keymap))
-  (define-key forms-mode-map "\t" 'forms-next-field)
-  (define-key forms-mode-map "\C-k" 'forms-delete-record)
-  (define-key forms-mode-map "\C-q" 'forms-toggle-read-only)
-  (define-key forms-mode-map "\C-o" 'forms-insert-record)
-  (define-key forms-mode-map "\C-l" 'forms-jump-record)
-  (define-key forms-mode-map "\C-n" 'forms-next-record)
-  (define-key forms-mode-map "\C-p" 'forms-prev-record)
-  (define-key forms-mode-map "\C-r" 'forms-search-backward)
-  (define-key forms-mode-map "\C-s" 'forms-search-forward)
-  (define-key forms-mode-map "\C-x" 'forms-exit)
-  (define-key forms-mode-map "<" 'forms-first-record)
-  (define-key forms-mode-map ">" 'forms-last-record)
-  (define-key forms-mode-map "\C-?" 'forms-prev-record)
+  (define-key forms-mode-map "\t" #'forms-next-field)
+  (define-key forms-mode-map "\C-k" #'forms-delete-record)
+  (define-key forms-mode-map "\C-q" #'forms-toggle-read-only)
+  (define-key forms-mode-map "\C-o" #'forms-insert-record)
+  (define-key forms-mode-map "\C-l" #'forms-jump-record)
+  (define-key forms-mode-map "\C-n" #'forms-next-record)
+  (define-key forms-mode-map "\C-p" #'forms-prev-record)
+  (define-key forms-mode-map "\C-r" #'forms-search-backward)
+  (define-key forms-mode-map "\C-s" #'forms-search-forward)
+  (define-key forms-mode-map "\C-x" #'forms-exit)
+  (define-key forms-mode-map "<" #'forms-first-record)
+  (define-key forms-mode-map ">" #'forms-last-record)
+  (define-key forms-mode-map "\C-?" #'forms-prev-record)
 
   ;; `forms-mode-ro-map' replaces the local map when in read-only mode.
   (setq forms-mode-ro-map (make-keymap))
   (suppress-keymap forms-mode-ro-map)
   (define-key forms-mode-ro-map "\C-c" forms-mode-map)
-  (define-key forms-mode-ro-map "q" 'forms-toggle-read-only)
-  (define-key forms-mode-ro-map "l" 'forms-jump-record)
-  (define-key forms-mode-ro-map "n" 'forms-next-record)
-  (define-key forms-mode-ro-map "p" 'forms-prev-record)
-  (define-key forms-mode-ro-map "r" 'forms-search-backward)
-  (define-key forms-mode-ro-map "s" 'forms-search-forward)
-  (define-key forms-mode-ro-map "x" 'forms-exit)
-  (define-key forms-mode-ro-map "<" 'forms-first-record)
-  (define-key forms-mode-ro-map ">" 'forms-last-record)
-  (define-key forms-mode-ro-map "?" 'describe-mode)
-  (define-key forms-mode-ro-map " " 'forms-next-record)
+  (define-key forms-mode-ro-map "q" #'forms-toggle-read-only)
+  (define-key forms-mode-ro-map "l" #'forms-jump-record)
+  (define-key forms-mode-ro-map "n" #'forms-next-record)
+  (define-key forms-mode-ro-map "p" #'forms-prev-record)
+  (define-key forms-mode-ro-map "r" #'forms-search-backward)
+  (define-key forms-mode-ro-map "s" #'forms-search-forward)
+  (define-key forms-mode-ro-map "x" #'forms-exit)
+  (define-key forms-mode-ro-map "<" #'forms-first-record)
+  (define-key forms-mode-ro-map ">" #'forms-last-record)
+  (define-key forms-mode-ro-map "?" #'describe-mode)
+  (define-key forms-mode-ro-map " " #'forms-next-record)
   (forms--mode-commands1 forms-mode-ro-map)
   (forms--mode-menu-ro forms-mode-ro-map)
 
@@ -1395,13 +1386,13 @@ Commands:                        Equivalent keys in 
read-only mode:
 
 (defun forms--mode-commands1 (map)
   "Helper routine to define keys."
-  (define-key map "\t" 'forms-next-field)
-  (define-key map [S-tab] 'forms-prev-field)
-  (define-key map [next] 'forms-next-record)
-  (define-key map [prior] 'forms-prev-record)
-  (define-key map [begin] 'forms-first-record)
-  (define-key map [last] 'forms-last-record)
-  (define-key map [backtab] 'forms-prev-field)
+  (define-key map "\t" #'forms-next-field)
+  (define-key map [S-tab] #'forms-prev-field)
+  (define-key map [next] #'forms-next-record)
+  (define-key map [prior] #'forms-prev-record)
+  (define-key map [begin] #'forms-first-record)
+  (define-key map [last] #'forms-last-record)
+  (define-key map [backtab] #'forms-prev-field)
   )
 
 ;;; Changed functions
@@ -2034,8 +2025,7 @@ Usage: (setq forms-number-of-fields
 
 (defcustom forms--debug nil
   "If non-nil, enable Forms mode debugging."
-  :type 'boolean
-  :group 'forms)
+  :type 'boolean)
 
 (defun forms--debug (&rest args)
   "Internal debugging routine."
@@ -2046,7 +2036,7 @@ Usage: (setq forms-number-of-fields
                (if (stringp el) el
                  (concat (prin1-to-string el) " = "
                          (if (boundp el)
-                             (prin1-to-string (eval el))
+                             (prin1-to-string (symbol-value el))
                            "<unbound>")
                          "\n"
                          (if (fboundp el)
diff --git a/lisp/frame.el b/lisp/frame.el
index b69f0fe..b6f78b4 100644
--- a/lisp/frame.el
+++ b/lisp/frame.el
@@ -367,6 +367,7 @@ there (in decreasing order of priority)."
       ;; by the lines added in x-create-frame for the tab-bar and
       ;; switch `tab-bar-mode' off.
       (when (display-graphic-p)
+        (declare-function tab-bar-height "xdisp.c" (&optional frame pixelwise))
        (let* ((init-lines
                (assq 'tab-bar-lines initial-frame-alist))
               (other-lines
@@ -708,9 +709,11 @@ Return nil if we don't know how to interpret DISPLAY."
 (defun make-frame-on-display (display &optional parameters)
   "Make a frame on display DISPLAY.
 The optional argument PARAMETERS specifies additional frame parameters."
-  (interactive (list (completing-read
-                      (format "Make frame on display: ")
-                      (x-display-list))))
+  (interactive (if (fboundp 'x-display-list)
+                   (list (completing-read
+                          (format "Make frame on display: ")
+                          (x-display-list)))
+                 (user-error "This Emacs build does not support X displays")))
   (make-frame (cons (cons 'display display) parameters)))
 
 (defun make-frame-on-current-monitor (&optional parameters)
@@ -1370,7 +1373,7 @@ FRAME defaults to the selected frame."
 FRAME defaults to the selected frame."
   (setq frame (window-normalize-frame frame))
   (- (frame-native-height frame)
-     (tab-bar-height frame t)
+     (if (fboundp 'tab-bar-height) (tab-bar-height frame t) 0)
      (* 2 (frame-internal-border-width frame))))
 
 (defun frame-outer-width (&optional frame)
diff --git a/lisp/gnus/gnus-art.el b/lisp/gnus/gnus-art.el
index ad32308..d989a4d 100644
--- a/lisp/gnus/gnus-art.el
+++ b/lisp/gnus/gnus-art.el
@@ -971,7 +971,7 @@ see http://www.cs.indiana.edu/picons/ftp/index.html";
   :version "22.1"
   :type '(repeat directory)
   :link '(url-link :tag "download"
-                  "http://www.cs.indiana.edu/picons/ftp/index.html";)
+                   "http://www.cs.indiana.edu/picons/ftp/index.html";)
   :link '(custom-manual "(gnus)Picons")
   :group 'gnus-picon)
 
@@ -6648,9 +6648,10 @@ not have a face in `gnus-article-boring-faces'."
        (catch 'only-boring
          (while (re-search-forward "\\b\\w\\w" nil t)
            (forward-char -1)
-           (when (not (gnus-intersection
+            (when (not (seq-intersection
                        (gnus-faces-at (point))
-                       (symbol-value 'gnus-article-boring-faces)))
+                        (symbol-value 'gnus-article-boring-faces)
+                        #'eq))
              (throw 'only-boring nil)))
          (throw 'only-boring t))))))
 
diff --git a/lisp/gnus/gnus-cite.el b/lisp/gnus/gnus-cite.el
index 1f564f1..4249b50 100644
--- a/lisp/gnus/gnus-cite.el
+++ b/lisp/gnus/gnus-cite.el
@@ -839,7 +839,7 @@ See also the documentation for 
`gnus-article-highlight-citation'."
                 (setq current (car loop)
                       loop (cdr loop))
                 (setcdr current
-                        (gnus-set-difference (cdr current) numbers)))))))))
+                         (seq-difference (cdr current) numbers #'eq)))))))))
 
 (defun gnus-cite-parse-attributions ()
   (let (al-alist)
@@ -999,7 +999,7 @@ See also the documentation for 
`gnus-article-highlight-citation'."
                    loop (cdr loop))
              (if (eq current best)
                  ()
-               (setcdr current (gnus-set-difference (cdr current) numbers))
+                (setcdr current (seq-difference (cdr current) numbers #'eq))
                (when (null (cdr current))
                  (setq gnus-cite-loose-prefix-alist
                        (delq current gnus-cite-loose-prefix-alist)
diff --git a/lisp/gnus/gnus-group.el b/lisp/gnus/gnus-group.el
index 909391b..423b180 100644
--- a/lisp/gnus/gnus-group.el
+++ b/lisp/gnus/gnus-group.el
@@ -4697,20 +4697,20 @@ This command may read the active file."
     (gnus-cache-open))
   (funcall gnus-group-prepare-function
           (or level gnus-level-subscribed)
-          #'(lambda (info)
-              (let ((marks (gnus-info-marks info)))
-                (assq 'cache marks)))
+           (lambda (info)
+             (let ((marks (gnus-info-marks info)))
+               (assq 'cache marks)))
           lowest
-          #'(lambda (group)
-              (or (gethash group
-                           gnus-cache-active-hashtb)
-                  ;; Cache active file might use "."
-                  ;; instead of ":".
-                  (gethash
-                   (mapconcat #'identity
-                              (split-string group ":")
-                              ".")
-                   gnus-cache-active-hashtb))))
+           (lambda (group)
+             (or (gethash group
+                          gnus-cache-active-hashtb)
+                 ;; Cache active file might use "."
+                 ;; instead of ":".
+                 (gethash
+                  (mapconcat #'identity
+                             (split-string group ":")
+                             ".")
+                  gnus-cache-active-hashtb))))
   (goto-char (point-min))
   (gnus-group-position-point))
 
@@ -4728,9 +4728,9 @@ This command may read the active file."
     (gnus-cache-open))
   (funcall gnus-group-prepare-function
           (or level gnus-level-subscribed)
-          #'(lambda (info)
-              (let ((marks (gnus-info-marks info)))
-                (assq 'dormant marks)))
+           (lambda (info)
+             (let ((marks (gnus-info-marks info)))
+               (assq 'dormant marks)))
           lowest
           'ignore)
   (goto-char (point-min))
@@ -4750,9 +4750,9 @@ This command may read the active file."
     (gnus-cache-open))
   (funcall gnus-group-prepare-function
           (or level gnus-level-subscribed)
-          #'(lambda (info)
-              (let ((marks (gnus-info-marks info)))
-                (assq 'tick marks)))
+           (lambda (info)
+             (let ((marks (gnus-info-marks info)))
+               (assq 'tick marks)))
           lowest
           'ignore)
   (goto-char (point-min))
diff --git a/lisp/gnus/gnus-range.el b/lisp/gnus/gnus-range.el
index 6cc60cb..7d12ae9 100644
--- a/lisp/gnus/gnus-range.el
+++ b/lisp/gnus/gnus-range.el
@@ -42,13 +42,8 @@ If RANGE is a single range, return (RANGE).  Otherwise, 
return RANGE."
 
 (defun gnus-set-difference (list1 list2)
   "Return a list of elements of LIST1 that do not appear in LIST2."
-  (let ((hash2 (make-hash-table :test 'eq))
-        (result nil))
-    (dolist (elt list2) (puthash elt t hash2))
-    (dolist (elt list1)
-      (unless (gethash elt hash2)
-        (setq result (cons elt result))))
-    (nreverse result)))
+  (declare (obsolete seq-difference "28.1"))
+  (seq-difference list1 list2 #'eq))
 
 (defun gnus-range-nconcat (&rest ranges)
   "Return a range comprising all the RANGES, which are pre-sorted.
@@ -179,12 +174,8 @@ Both lists have to be sorted over <."
 
 ;;;###autoload
 (defun gnus-intersection (list1 list2)
-  (let ((result nil))
-    (while list2
-      (when (memq (car list2) list1)
-       (setq result (cons (car list2) result)))
-      (setq list2 (cdr list2)))
-    result))
+  (declare (obsolete seq-intersection "28.1"))
+  (nreverse (seq-intersection list1 list2 #'eq)))
 
 ;;;###autoload
 (defun gnus-sorted-intersection (list1 list2)
diff --git a/lisp/gnus/gnus-registry.el b/lisp/gnus/gnus-registry.el
index e3b9c19..6ac646f 100644
--- a/lisp/gnus/gnus-registry.el
+++ b/lisp/gnus/gnus-registry.el
@@ -1290,9 +1290,9 @@ from your existing entries."
       (registry-reindex db)
       (cl-loop for k being the hash-keys of (oref db data)
            using (hash-value v)
-           do (let ((newv (delq nil (mapcar #'(lambda (entry)
-                                                (unless (member (car entry) 
extra)
-                                                  entry))
+            do (let ((newv (delq nil (mapcar (lambda (entry)
+                                               (unless (member (car entry) 
extra)
+                                                 entry))
                                             v))))
                 (registry-delete db (list k) nil)
                 (gnus-registry-insert db k newv)))
diff --git a/lisp/gnus/gnus-score.el b/lisp/gnus/gnus-score.el
index ce64dce..f40da9e 100644
--- a/lisp/gnus/gnus-score.el
+++ b/lisp/gnus/gnus-score.el
@@ -1182,8 +1182,8 @@ If FORMAT, also format the current score file."
       (when (consp rule) ;; the rule exists
        (setq rule (if (symbolp (car rule))
                       (format "(%S)" (car rule))
-                    (mapconcat #'(lambda (obj)
-                                   (regexp-quote (format "%S" obj)))
+                     (mapconcat (lambda (obj)
+                                  (regexp-quote (format "%S" obj)))
                                rule
                                sep)))
        (goto-char (point-min))
diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el
index 97da550..eeb5ac8 100644
--- a/lisp/gnus/gnus-sum.el
+++ b/lisp/gnus/gnus-sum.el
@@ -5676,9 +5676,9 @@ or a straight list of headers."
            (or dependencies
                (with-current-buffer gnus-summary-buffer
                  gnus-newsgroup-dependencies))))
-     (delq nil (mapcar   #'(lambda (header)
-                            (gnus-dependencies-add-header
-                             header dependencies force-new))
+       (delq nil (mapcar (lambda (header)
+                           (gnus-dependencies-add-header
+                            header dependencies force-new))
                         gnus-headers-retrieved-by)))))
   (gnus-message 7 "Fetching headers for %s...done" gnus-newsgroup-name)))
 
@@ -5977,14 +5977,15 @@ If SELECT-ARTICLES, only select those articles from 
GROUP."
                         (input
                          (read-string
                           (if only-read-p
-                              (format
-                               "How many articles from %s (available %d, 
default %d): "
-                               (gnus-group-real-name gnus-newsgroup-name)
-                               number default)
-                            (format
-                             "How many articles from %s (%d default): "
-                             (gnus-group-real-name gnus-newsgroup-name)
-                             default))
+                              (format-prompt
+                                   "How many articles from %s (available %d)"
+                                   default
+                                   (gnus-group-real-name gnus-newsgroup-name)
+                                   number)
+                            (format-prompt
+                             "How many articles from %s"
+                             default
+                             (gnus-group-real-name gnus-newsgroup-name)))
                           nil
                           nil
                           (number-to-string default))))
@@ -8568,8 +8569,9 @@ If UNREPLIED (the prefix), limit to unreplied articles."
   (interactive "P" gnus-summary-mode)
   (if unreplied
       (gnus-summary-limit
-       (gnus-set-difference gnus-newsgroup-articles
-       gnus-newsgroup-replied))
+       (seq-difference gnus-newsgroup-articles
+                       gnus-newsgroup-replied
+                       #'eq))
     (gnus-summary-limit gnus-newsgroup-replied))
   (gnus-summary-position-point))
 
@@ -9514,11 +9516,9 @@ If BACKWARD, search backward instead."
   (interactive
    (list
     (read-string
-     (format "Search article %s (regexp%s): "
-            (if current-prefix-arg "backward" "forward")
-            (if gnus-last-search-regexp
-                (concat ", default " gnus-last-search-regexp)
-              "")))
+     (format-prompt "Search article %s (regexp)"
+                    gnus-last-search-regexp
+                    (if current-prefix-arg "backward" "forward")))
     current-prefix-arg)
    gnus-summary-mode)
   (if (string-equal regexp "")
@@ -9537,10 +9537,8 @@ If BACKWARD, search backward instead."
   (interactive
    (list
     (read-string
-     (format "Search article backward (regexp%s): "
-            (if gnus-last-search-regexp
-                (concat ", default " gnus-last-search-regexp)
-              ""))))
+     (format-prompt "Search article backward (regexp)"
+                    gnus-last-search-regexp)))
    gnus-summary-mode)
   (gnus-summary-search-article-forward regexp 'backward))
 
diff --git a/lisp/gnus/gnus-util.el b/lisp/gnus/gnus-util.el
index f80243c..e558f63 100644
--- a/lisp/gnus/gnus-util.el
+++ b/lisp/gnus/gnus-util.el
@@ -1612,8 +1612,8 @@ empty directories from OLD-PATH."
   "Rescale IMAGE to SIZE if possible.
 SIZE is in format (WIDTH . HEIGHT).  Return a new image.
 Sizes are in pixels."
-  (if (not (display-graphic-p))
-      image
+  (when (display-images-p)
+    (declare-function image-size "image.c" (spec &optional pixels frame))
     (let ((new-width (car size))
           (new-height (cdr size)))
       (when (> (cdr (image-size image t)) new-height)
@@ -1621,8 +1621,8 @@ Sizes are in pixels."
                                   :max-height new-height)))
       (when (> (car (image-size image t)) new-width)
        (setq image (create-image (plist-get (cdr image) :data) nil t
-                                  :max-width new-width)))
-      image)))
+                                  :max-width new-width)))))
+  image)
 
 (defun gnus-recursive-directory-files (dir)
   "Return all regular files below DIR.
diff --git a/lisp/gnus/gnus-uu.el b/lisp/gnus/gnus-uu.el
index bd9a1a3..ceb2ebc 100644
--- a/lisp/gnus/gnus-uu.el
+++ b/lisp/gnus/gnus-uu.el
@@ -578,8 +578,8 @@ didn't work, and overwrite existing files.  Otherwise, ask 
each time."
 
 (defun gnus-new-processable (unmarkp articles)
   (if unmarkp
-      (gnus-intersection gnus-newsgroup-processable articles)
-    (gnus-set-difference articles gnus-newsgroup-processable)))
+      (nreverse (seq-intersection gnus-newsgroup-processable articles #'eq))
+    (seq-difference articles gnus-newsgroup-processable #'eq)))
 
 (defun gnus-uu-mark-by-regexp (regexp &optional unmark)
   "Set the process mark on articles whose subjects match REGEXP.
diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el
index 1e0362a..fad4ef3 100644
--- a/lisp/gnus/message.el
+++ b/lisp/gnus/message.el
@@ -382,7 +382,7 @@ Archives \(such as groups.google.com) respect this header."
   :group 'message-various)
 
 (defcustom message-archive-note
-  "X-No-Archive: Yes - save http://groups.google.com/";
+  "X-No-Archive: Yes - save https://groups.google.com/";
   "Note to insert why you wouldn't want this posting archived.
 If nil, don't insert any text in the body."
   :version "22.1"
diff --git a/lisp/gnus/mm-partial.el b/lisp/gnus/mm-partial.el
index 0c25c8f..0c62805 100644
--- a/lisp/gnus/mm-partial.el
+++ b/lisp/gnus/mm-partial.el
@@ -72,14 +72,14 @@ If NO-DISPLAY is nil, display it.  Otherwise, do nothing 
after replacing."
                         id
                         (with-current-buffer gnus-summary-buffer
                           (gnus-summary-article-number))))
-                 #'(lambda (a b)
-                     (let ((anumber (string-to-number
-                                     (cdr (assq 'number
-                                                (cdr (mm-handle-type a))))))
-                           (bnumber (string-to-number
-                                     (cdr (assq 'number
-                                                (cdr (mm-handle-type b)))))))
-                       (< anumber bnumber)))))
+                  (lambda (a b)
+                    (let ((anumber (string-to-number
+                                    (cdr (assq 'number
+                                               (cdr (mm-handle-type a))))))
+                          (bnumber (string-to-number
+                                    (cdr (assq 'number
+                                               (cdr (mm-handle-type b)))))))
+                      (< anumber bnumber)))))
       (setq gnus-article-mime-handles
            (mm-merge-handles gnus-article-mime-handles phandles))
       (with-current-buffer (generate-new-buffer " *mm*")
diff --git a/lisp/gnus/mml-sec.el b/lisp/gnus/mml-sec.el
index a32eed4..15157e6 100644
--- a/lisp/gnus/mml-sec.el
+++ b/lisp/gnus/mml-sec.el
@@ -140,7 +140,7 @@ by default identifies the used encryption keys, giving away 
the
 Bcc'ed identities.  Clearly, this contradicts the original goal of
 *blind* copies.
 For an academic paper explaining the problem, see URL
-`http://crypto.stanford.edu/portia/papers/bb-bcc.pdf'.
+`https://crypto.stanford.edu/portia/papers/bb-bcc.pdf'.
 Use this variable to specify e-mail addresses whose owners do not
 mind if they are identifiable as recipients.  This may be useful if
 you use Bcc headers to encrypt e-mails to yourself."
diff --git a/lisp/gnus/nndiary.el b/lisp/gnus/nndiary.el
index 15003fa..adf4427 100644
--- a/lisp/gnus/nndiary.el
+++ b/lisp/gnus/nndiary.el
@@ -558,7 +558,7 @@ all.  This may very well take some time.")
     (nnmail-activate 'nndiary)
     ;; Articles not listed in active-articles are already gone,
     ;; so don't try to expire them.
-    (setq articles (gnus-intersection articles active-articles))
+    (setq articles (nreverse (seq-intersection articles active-articles #'eq)))
     (while articles
       (setq article (nndiary-article-to-file (setq number (pop articles))))
       (if (and (nndiary-deletable-article-p group number)
diff --git a/lisp/gnus/nnimap.el b/lisp/gnus/nnimap.el
index 93e1c47..8990b2b 100644
--- a/lisp/gnus/nnimap.el
+++ b/lisp/gnus/nnimap.el
@@ -440,6 +440,7 @@ during splitting, which may be slow."
 
 ;; This is only needed for Windows XP or earlier
 (defun nnimap-map-port (port)
+  (declare-function x-server-version "xfns.c" (&optional terminal))
   (if (and (eq system-type 'windows-nt)
            (<= (car (x-server-version)) 5)
            (equal port "imaps"))
@@ -1613,13 +1614,15 @@ If LIMIT, first try to limit the search to the N last 
articles."
              (setq start-article 1))
            (let* ((unread
                    (gnus-compress-sequence
-                    (gnus-set-difference
-                     (gnus-set-difference
+                     (seq-difference
+                      (seq-difference
                       existing
                       (gnus-sorted-union
                        (cdr (assoc '%Seen flags))
-                       (cdr (assoc '%Deleted flags))))
-                     (cdr (assoc '%Flagged flags)))))
+                        (cdr (assoc '%Deleted flags)))
+                       #'eq)
+                      (cdr (assoc '%Flagged flags))
+                      #'eq)))
                   (read (gnus-range-difference
                          (cons start-article high) unread)))
              (when (> start-article 1)
diff --git a/lisp/gnus/nnmaildir.el b/lisp/gnus/nnmaildir.el
index 46691e3..4867455 100644
--- a/lisp/gnus/nnmaildir.el
+++ b/lisp/gnus/nnmaildir.el
@@ -21,7 +21,7 @@
 
 ;;; Commentary:
 
-;; Maildir format is documented at <URL:http://cr.yp.to/proto/maildir.html>.
+;; Maildir format is documented at <URL:https://cr.yp.to/proto/maildir.html>.
 ;; nnmaildir also stores extra information in the .nnmaildir/ directory
 ;; within a maildir.
 ;;
diff --git a/lisp/gnus/nnselect.el b/lisp/gnus/nnselect.el
index 1daa8aa..e314e1d 100644
--- a/lisp/gnus/nnselect.el
+++ b/lisp/gnus/nnselect.el
@@ -100,8 +100,8 @@
        (setq selection
              (vconcat
               (cl-map 'vector
-                   #'(lambda (art)
-                       (vector artgroup art artrsv))
+                       (lambda (art)
+                         (vector artgroup art artrsv))
                    (gnus-uncompress-sequence artseq)) selection)))
       selection)))
 
@@ -211,12 +211,12 @@ as `(keyfunc member)' and the corresponding element is 
just
                          #'nnselect-article-group #'nnselect-article-number))
     ((eq ,type 'tuple)
      (nnselect-categorize ,articles
-                         #'(lambda (elem)
-                             (nnselect-article-group (car elem)))
-                         #'(lambda (elem)
-                             (cons (nnselect-article-number
-                                    (car elem))
-                                   (cdr elem)))))
+                  (lambda (elem)
+                    (nnselect-article-group (car elem)))
+                  (lambda (elem)
+                    (cons (nnselect-article-number
+                           (car elem))
+                          (cdr elem)))))
     (t
      (nnselect-categorize ,articles
                          #'nnselect-article-group
@@ -464,8 +464,8 @@ If this variable is nil, or if the provided function 
returns nil,
              (error "Group %s does not support article expiration" artgroup))
            (unless (gnus-check-server (gnus-find-method-for-group artgroup))
              (error "Couldn't open server for group %s" artgroup))
-           (push (mapcar #'(lambda (art)
-                             (car (rassq art artids)))
+            (push (mapcar (lambda (art)
+                            (car (rassq art artids)))
                          (let ((nnimap-expunge 'immediately))
                            (gnus-request-expire-articles
                             artlist artgroup force)))
@@ -549,8 +549,8 @@ If this variable is nil, or if the provided function 
returns nil,
              (gnus-add-to-range
               (gnus-info-read info)
               (delq nil (mapcar
-                         #'(lambda (art)
-                             (unless (memq (cdr art) unread) (car art)))
+                          (lambda (art)
+                            (unless (memq (cdr art) unread) (car art)))
                          artids))))
        (pcase-dolist (`(,type . ,mark-list) marks)
          (let ((mark-type (gnus-article-mark-to-type type)) new)
@@ -560,19 +560,19 @@ If this variable is nil, or if the provided function 
returns nil,
                            (cond
                             ((eq mark-type 'tuple)
                              (mapcar
-                              #'(lambda (id)
-                                  (let (mark)
-                                    (when
-                                        (setq mark (assq (cdr id) mark-list))
-                                      (cons (car id) (cdr mark)))))
+                               (lambda (id)
+                                 (let (mark)
+                                   (when
+                                       (setq mark (assq (cdr id) mark-list))
+                                     (cons (car id) (cdr mark)))))
                               artids))
                             (t
                              (setq mark-list
                                    (gnus-uncompress-range mark-list))
                              (mapcar
-                              #'(lambda (id)
-                                  (when (memq (cdr id) mark-list)
-                                    (car id)))  artids)))))
+                               (lambda (id)
+                                 (when (memq (cdr id) mark-list)
+                                   (car id)))  artids)))))
              (let ((previous (alist-get type newmarks)))
                (if previous
                    (nconc previous new)
@@ -607,8 +607,8 @@ If this variable is nil, or if the provided function 
returns nil,
                         (let ((thread
                                (gnus-id-to-thread (mail-header-id header))))
                           (when thread
-                            (cl-some #'(lambda (x)
-                                         (when (and x (> x 0)) x))
+                             (cl-some (lambda (x)
+                                        (when (and x (> x 0)) x))
                                      (gnus-articles-in-thread thread)))))))))
       ;; Check if search-based thread referral is permitted, and
       ;; available.
@@ -642,15 +642,15 @@ If this variable is nil, or if the provided function 
returns nil,
                 old-arts seq
                 headers)
            (mapc
-            #'(lambda (article)
-                (if
-                    (setq seq
-                          (cl-position article
-                                       gnus-newsgroup-selection :test 'equal))
-                    (push (1+ seq) old-arts)
-                  (setq gnus-newsgroup-selection
-                        (vconcat gnus-newsgroup-selection (vector article)))
-                  (cl-incf last)))
+             (lambda (article)
+               (if
+                   (setq seq
+                         (cl-position article
+                                      gnus-newsgroup-selection :test 'equal))
+                   (push (1+ seq) old-arts)
+                 (setq gnus-newsgroup-selection
+                       (vconcat gnus-newsgroup-selection (vector article)))
+                 (cl-incf last)))
             new-nnselect-artlist)
            (setq headers
                  (gnus-fetch-headers
@@ -671,9 +671,9 @@ If this variable is nil, or if the provided function 
returns nil,
                    (when (setq new-marks
                                (delq nil
                                      (mapcar
-                                      #'(lambda (art)
-                                          (when (memq (cdr art) marked)
-                                            (car art)))
+                                       (lambda (art)
+                                         (when (memq (cdr art) marked)
+                                           (car art)))
                                       artids)))
                      (nconc
                       (symbol-value
diff --git a/lisp/gnus/nnvirtual.el b/lisp/gnus/nnvirtual.el
index b3b701e..03a0ff2 100644
--- a/lisp/gnus/nnvirtual.el
+++ b/lisp/gnus/nnvirtual.el
@@ -362,9 +362,9 @@ It is computed from the marks of individual component 
groups.")
     (dolist (group nnvirtual-component-groups)
       (setq unexpired (nconc unexpired
                             (mapcar
-                             #'(lambda (article)
-                                 (nnvirtual-reverse-map-article
-                                  group article))
+                              (lambda (article)
+                                (nnvirtual-reverse-map-article
+                                 group article))
                              (gnus-uncompress-range
                               (gnus-group-expire-articles-1 group))))))
     (sort (delq nil unexpired) #'<)))
diff --git a/lisp/gnus/smime.el b/lisp/gnus/smime.el
index 2446577..e9f703e 100644
--- a/lisp/gnus/smime.el
+++ b/lisp/gnus/smime.el
@@ -42,7 +42,7 @@
 ;; reflect this.
 ;;
 ;; The home of this file is in Gnus, but also available from
-;; http://josefsson.org/smime.html.
+;; https://josefsson.org/smime.html.
 
 ;;; Quick introduction:
 
diff --git a/lisp/gnus/spam-stat.el b/lisp/gnus/spam-stat.el
index 3e804ec..ab9be0d 100644
--- a/lisp/gnus/spam-stat.el
+++ b/lisp/gnus/spam-stat.el
@@ -492,7 +492,7 @@ Add user supplied modifications if supplied."
   (let* ((probs (mapcar #'cadr spam-stat-score-data))
         (prod (apply #'* probs))
         (score0
-         (/ prod (+ prod (apply #'* (mapcar #'(lambda (x) (- 1 x))
+          (/ prod (+ prod (apply #'* (mapcar (lambda (x) (- 1 x))
                                             probs)))))
         (score1s
          (condition-case nil
diff --git a/lisp/gnus/spam.el b/lisp/gnus/spam.el
index d00f0a6..3f97891 100644
--- a/lisp/gnus/spam.el
+++ b/lisp/gnus/spam.el
@@ -710,16 +710,8 @@ finds ham or spam.")
 (defun spam-set-difference (list1 list2)
   "Return a set difference of LIST1 and LIST2.
 When either list is nil, the other is returned."
-  (if (and list1 list2)
-      ;; we have two non-nil lists
-      (progn
-        (dolist (item (append list1 list2))
-          (when (and (memq item list1) (memq item list2))
-            (setq list1 (delq item list1))
-            (setq list2 (delq item list2))))
-        (append list1 list2))
-    ;; if either of the lists was nil, return the other one
-    (if list1 list1 list2)))
+  (declare (obsolete seq-difference "28.1"))
+  (seq-difference list1 list2 #'eq))
 
 (defun spam-group-ham-mark-p (group mark &optional spam)
   "Checks if MARK is considered a ham mark in GROUP."
@@ -1327,7 +1319,7 @@ In the case of mover backends, checks the setting of
              (new-articles (spam-list-articles
                             gnus-newsgroup-articles
                             classification))
-             (changed-articles (spam-set-difference new-articles 
old-articles)))
+             (changed-articles (seq-difference new-articles old-articles 
#'eq)))
         ;; now that we have the changed articles, we go through the processors
         (dolist (backend (spam-backend-list))
           (let (unregister-list)
diff --git a/lisp/help-at-pt.el b/lisp/help-at-pt.el
index e17bd0a..233c505 100644
--- a/lisp/help-at-pt.el
+++ b/lisp/help-at-pt.el
@@ -1,4 +1,4 @@
-;;; help-at-pt.el --- local help through the keyboard
+;;; help-at-pt.el --- local help through the keyboard  -*- lexical-binding: t 
-*-
 
 ;; Copyright (C) 2003-2021 Free Software Foundation, Inc.
 
@@ -42,9 +42,6 @@
 ;;
 ;; (global-set-key [C-tab] 'scan-buf-next-region)
 ;; (global-set-key [C-M-tab] 'scan-buf-previous-region)
-;;
-;; You do not have to do anything special to use the functionality
-;; provided by this file, because all important functions autoload.
 
 ;;; Code:
 
diff --git a/lisp/hilit-chg.el b/lisp/hilit-chg.el
index 89a1a91..3c3c407 100644
--- a/lisp/hilit-chg.el
+++ b/lisp/hilit-chg.el
@@ -1,4 +1,4 @@
-;;; hilit-chg.el --- minor mode displaying buffer changes with special face
+;;; hilit-chg.el --- minor mode displaying buffer changes with special face  
-*- lexical-binding: t -*-
 
 ;; Copyright (C) 1998, 2000-2021 Free Software Foundation, Inc.
 
@@ -68,8 +68,7 @@
 ;; (defun my-highlight-changes-mode-hook ()
 ;;   (if highlight-changes-mode
 ;;       (add-hook 'write-file-functions 'highlight-changes-rotate-faces nil t)
-;;     (remove-hook 'write-file-functions 'highlight-changes-rotate-faces t)
-;;     ))
+;;     (remove-hook 'write-file-functions 'highlight-changes-rotate-faces t)))
 
 
 ;;           Automatically enabling Highlight Changes mode
@@ -114,16 +113,16 @@
 
 
 ;;     Possible bindings:
-;; (global-set-key '[C-right] 'highlight-changes-next-change)
-;; (global-set-key '[C-left]  'highlight-changes-previous-change)
+;; (global-set-key '[C-right] #'highlight-changes-next-change)
+;; (global-set-key '[C-left]  #'highlight-changes-previous-change)
 ;;
 ;;     Other interactive functions (that could be bound if desired):
-;; highlight-changes-mode
-;; highlight-changes-toggle-visibility
-;; highlight-changes-remove-highlight
-;; highlight-compare-with-file
-;; highlight-compare-buffers
-;; highlight-changes-rotate-faces
+;; `highlight-changes-mode'
+;; `highlight-changes-toggle-visibility'
+;; `highlight-changes-remove-highlight'
+;; `highlight-compare-with-file'
+;; `highlight-compare-buffers'
+;; `highlight-changes-rotate-faces'
 
 
 ;;; Bugs:
@@ -179,7 +178,6 @@
   :version "20.4"
   :group 'faces)
 
-
 ;; Face information: How the changes appear.
 
 ;; Defaults for face: red foreground, no change to background,
@@ -192,22 +190,20 @@
   '((((min-colors 88) (class color)) (:foreground "red1"))
     (((class color)) (:foreground "red" ))
     (t (:inverse-video t)))
-  "Face used for highlighting changes."
-  :group 'highlight-changes)
+  "Face used for highlighting changes.")
 
 ;; This looks pretty ugly, actually.  Maybe the underline should be removed.
 (defface highlight-changes-delete
   '((((min-colors 88) (class color)) (:foreground "red1" :underline t))
     (((class color)) (:foreground "red" :underline t))
     (t (:inverse-video t)))
-  "Face used for highlighting deletions."
-  :group 'highlight-changes)
+  "Face used for highlighting deletions.")
 
 ;; A (not very good) default list of colors to rotate through.
 (defcustom highlight-changes-colors
   (if (eq (frame-parameter nil 'background-mode) 'light)
       ;; defaults for light background:
-      '( "magenta" "blue" "darkgreen" "chocolate" "sienna4" "NavyBlue")
+      '("magenta" "blue" "darkgreen" "chocolate" "sienna4" "NavyBlue")
       ;; defaults for dark background:
     '("yellow" "magenta" "blue" "maroon" "firebrick" "green4" "DarkOrchid"))
   "Colors used by `highlight-changes-rotate-faces'.
@@ -218,8 +214,7 @@ This list is used if `highlight-changes-face-list' is nil, 
otherwise that
 variable overrides this list.  If you only care about foreground
 colors then use this, if you want fancier faces then set
 `highlight-changes-face-list'."
-  :type '(repeat color)
-  :group 'highlight-changes)
+  :type '(repeat color))
 
 ;; When you invoke highlight-changes-mode, should 
highlight-changes-visible-mode
 ;; be on or off?
@@ -230,8 +225,7 @@ colors then use this, if you want fancier faces then set
 This controls the initial value of `highlight-changes-visible-mode'.
 When a buffer is in Highlight Changes mode the function
 `highlight-changes-visible-mode' is used to toggle the mode on or off."
-  :type 'boolean
-  :group 'highlight-changes)
+  :type 'boolean)
 
 ;; These are the strings displayed in the mode-line for the minor mode:
 
@@ -240,16 +234,14 @@ When a buffer is in Highlight Changes mode the function
 This should be set to nil if no indication is desired, or to
 a string with a leading space."
   :type '(choice string
-                (const :tag "None"  nil))
-  :group 'highlight-changes)
+                 (const :tag "None" nil)))
 
 (defcustom highlight-changes-invisible-string " -Chg"
   "The string used when in Highlight Changes mode and changes are hidden.
 This should be set to nil if no indication is desired, or to
 a string with a leading space."
   :type '(choice string
-                (const :tag "None"  nil))
-  :group 'highlight-changes)
+                 (const :tag "None" nil)))
 
 (defcustom highlight-changes-global-modes t
   "Determine whether a buffer is suitable for global Highlight Changes mode.
@@ -279,9 +271,7 @@ modes only."
               (repeat :tag "Modes" :inline t (symbol :tag "mode")))
          (function :menu-tag "determined by function"
                           :value buffer-file-name)
-         (const :tag "none" nil)
-         )
-  :group 'highlight-changes)
+          (const :tag "none" nil)))
 
 (defcustom highlight-changes-global-changes-existing-buffers nil
   "If non-nil, toggling global Highlight Changes mode affects existing buffers.
@@ -290,8 +280,7 @@ created).  However, if 
`highlight-changes-global-changes-existing-buffers'
 is non-nil, then turning on `global-highlight-changes-mode' will turn on
 Highlight Changes mode in suitable buffers, and turning the mode off will
 remove it from existing buffers."
-  :type 'boolean
-  :group 'highlight-changes)
+  :type 'boolean)
 
 ;; These are for internal use.
 
@@ -320,9 +309,7 @@ through     various faces.
 \\[highlight-compare-with-file] - mark text as changed by comparing this
 buffer with the contents of a file
 \\[highlight-compare-buffers] highlights differences between two buffers."
-  nil                  ;; init-value
-  hilit-chg-string     ;; lighter
-  nil                  ;; keymap
+  :lighter hilit-chg-string
   (if (or (display-color-p)
          (and (fboundp 'x-display-grayscale-p) (x-display-grayscale-p)))
       (progn
@@ -352,13 +339,8 @@ The default value can be customized with variable
 `highlight-changes-visibility-initial-state'.
 
 This command does not itself set Highlight Changes mode."
-
-  t            ;; init-value
-  nil          ;; lighter
-  nil          ;; keymap
-
-  (hilit-chg-update)
-  )
+  :init-value t
+  (hilit-chg-update))
 
 
 (defun hilit-chg-cust-fix-changes-face-list (w _wc &optional event)
@@ -371,12 +353,10 @@ This command does not itself set Highlight Changes mode."
   ;; faces are saved but not to the actual list itself.
   (let ((old-list (widget-value w)))
     (if (member 'default old-list)
-       (let
-           ((p (reverse old-list))
+        (let ((p (reverse old-list))
             (n (length old-list))
             new-name old-name
-            (new-list nil)
-            )
+             (new-list nil))
          (while p
            (setq old-name (car p))
            (setq new-name (intern (format "highlight-changes-%d" n)))
@@ -396,9 +376,7 @@ This command does not itself set Highlight Changes mode."
          (if (equal new-list (widget-value w))
              nil ;; (message "notify: no change!")
            (widget-value-set w new-list)
-           (widget-setup)
-           )
-         )
+            (widget-setup)))
       ;; (message "notify: no default here!")
       ))
   (let ((parent (widget-get w :parent)))
@@ -417,10 +395,8 @@ Otherwise, this list will be constructed when needed from
   :type '(choice
          (repeat
            :notify hilit-chg-cust-fix-changes-face-list
-           face  )
-         (const :tag "Derive from highlight-changes-colors"  nil)
-         )
-  :group 'highlight-changes)
+            face)
+          (const :tag "Derive from highlight-changes-colors"  nil)))
 
 
 (defun hilit-chg-map-changes (func &optional start-position end-position)
@@ -446,7 +422,7 @@ An overlay from BEG to END containing a change face is added
 from the information in the text property of type `hilit-chg'.
 
 This is the opposite of `hilit-chg-hide-changes'."
-  (hilit-chg-map-changes 'hilit-chg-make-ov beg end))
+  (hilit-chg-map-changes #'hilit-chg-make-ov beg end))
 
 
 (defun hilit-chg-make-ov (prop start end)
@@ -467,8 +443,7 @@ This is the opposite of `hilit-chg-hide-changes'."
          (overlay-put ov 'evaporate t)
          ;; We set the change property so we can tell this is one
          ;; of our overlays (so we don't delete someone else's).
-         (overlay-put ov 'hilit-chg t)
-         )
+          (overlay-put ov 'hilit-chg t))
       (error "hilit-chg-make-ov: no face for prop: %s" prop))))
 
 (defun hilit-chg-hide-changes (&optional beg end)
@@ -726,7 +701,7 @@ this, eval the following in the buffer to be saved:
            ;; remove our existing overlays
            (hilit-chg-hide-changes)
            ;; for each change text property, increment it
-           (hilit-chg-map-changes 'hilit-chg-bump-change)
+            (hilit-chg-map-changes #'hilit-chg-bump-change)
            ;; and display them
            (hilit-chg-display-changes))
        (unless modified
@@ -759,7 +734,7 @@ is non-nil."
           (buf-b-read-only (with-current-buffer buf-b buffer-read-only))
           temp-a temp-b)
       (if (and file-a bufa-modified)
-         (if (y-or-n-p (format "Save buffer %s?  " buf-a))
+          (if (y-or-n-p (format "Save buffer %s? " buf-a))
              (with-current-buffer buf-a
                (save-buffer)
                (setq bufa-modified (buffer-modified-p buf-a)))
@@ -768,7 +743,7 @@ is non-nil."
          (setq temp-a (setq file-a (ediff-make-temp-file buf-a nil))))
 
       (if (and file-b bufb-modified)
-         (if (y-or-n-p (format "Save buffer %s?  " buf-b))
+          (if (y-or-n-p (format "Save buffer %s? " buf-b))
              (with-current-buffer buf-b
                (save-buffer)
                (setq bufb-modified (buffer-modified-p buf-b)))
@@ -809,12 +784,11 @@ is non-nil."
       (if temp-a
          (delete-file temp-a))
       (if temp-b
-         (delete-file temp-b)))
-    ))
+          (delete-file temp-b)))))
 
 ;;;###autoload
 (defun highlight-compare-buffers (buf-a buf-b)
-"Compare two buffers and highlight the differences.
+  "Compare two buffers and highlight the differences.
 
 The default is the current buffer and the one in the next window.
 
@@ -835,8 +809,7 @@ changes are made, so \\[highlight-changes-next-change] and
                  (window-buffer (next-window)) t))))
   (let ((file-a (buffer-file-name buf-a))
        (file-b (buffer-file-name buf-b)))
-    (highlight-markup-buffers buf-a file-a buf-b file-b)
-    ))
+    (highlight-markup-buffers buf-a file-a buf-b file-b)))
 
 ;;;###autoload
 (defun highlight-compare-with-file (file-b)
@@ -876,9 +849,11 @@ changes are made, so \\[highlight-changes-next-change] and
                    (find-file-noselect file-b))))
     (highlight-markup-buffers buf-a file-a buf-b file-b (not existing-buf))
     (unless existing-buf
-      (kill-buffer buf-b))
-    ))
+      (kill-buffer buf-b))))
 
+(defvar hilit-x)                      ; placate the byte-compiler
+(defvar hilit-y)
+(defvar hilit-e)
 
 (defun hilit-chg-get-diff-info (buf-a file-a buf-b file-b)
    ;; hilit-e,x,y are set by function hilit-chg-get-diff-list-hk.
@@ -886,8 +861,7 @@ changes are made, so \\[highlight-changes-next-change] and
     (ediff-setup buf-a file-a buf-b file-b
               nil nil   ; buf-c file-C
               '(hilit-chg-get-diff-list-hk)
-              (list (cons 'ediff-job-name 'something))
-              )
+               (list (cons 'ediff-job-name 'something)))
     (ediff-with-current-buffer hilit-e (ediff-really-quit nil))
     (list hilit-x hilit-y)))
 
@@ -895,9 +869,6 @@ changes are made, so \\[highlight-changes-next-change] and
 (defun hilit-chg-get-diff-list-hk ()
   ;; hilit-e/x/y are dynamically bound by hilit-chg-get-diff-info
   ;; which calls this function as a hook.
-  (defvar hilit-x)                      ; placate the byte-compiler
-  (defvar hilit-y)
-  (defvar hilit-e)
   (setq hilit-e (current-buffer))
   (let ((n 0) extent p va vb a b)
     (setq hilit-x nil hilit-y nil)
@@ -931,7 +902,7 @@ changes are made, so \\[highlight-changes-next-change] and
        (setq extent (list (overlay-start (car p))
                           (overlay-end (car p))))
        (setq p (cdr p))
-       (setq hilit-y (append hilit-y (list extent) )))
+        (setq hilit-y (append hilit-y (list extent))))
       (setq n (1+ n)));; while
     ;; ediff-quit doesn't work here.
     ;; No point in returning a value, since this is a hook function.
@@ -961,8 +932,7 @@ This is called when `global-highlight-changes-mode' is 
turned on."
             (and
              (not (string-match "^[ *]" (buffer-name)))
              (buffer-file-name))))
-         (highlight-changes-mode 1))
-       ))
+          (highlight-changes-mode 1))))
 
 
 ;;;; Desktop support.
@@ -985,8 +955,7 @@ This is called when `global-highlight-changes-mode' is 
turned on."
 ;;   (message "--- hilit-chg-debug-show ---")
 ;;   (hilit-chg-map-changes (lambda (prop start end)
 ;;                          (message "%d-%d: %s" start end prop))
-;;                        beg end
-;;                        ))
+;;                        beg end))
 ;;
 ;; ================== end of debug ===============
 
diff --git a/lisp/htmlfontify.el b/lisp/htmlfontify.el
index bfbe0ee..b453061 100644
--- a/lisp/htmlfontify.el
+++ b/lisp/htmlfontify.el
@@ -523,22 +523,10 @@ therefore no longer care about) will be invalid at any 
time.\n
 (defvar hfy-tmpfont-stack nil
   "An alist of derived fonts resulting from overlays.")
 
-(defconst hfy-hex-regex "[[:xdigit:]]")
-
 (defconst hfy-triplet-regex
-  (concat
-   "\\(" hfy-hex-regex hfy-hex-regex "\\)"
-   "\\(" hfy-hex-regex hfy-hex-regex "\\)"
-   "\\(" hfy-hex-regex hfy-hex-regex "\\)"))
-
-(defun hfy-interq (set-a set-b)
-  "Return the intersection (using `eq') of two lists SET-A and SET-B."
-  (let ((sa set-a) (interq nil) (elt nil))
-    (while sa
-      (setq elt (car sa)
-            sa  (cdr sa))
-      (if (memq elt set-b) (setq interq (cons elt interq))))
-    interq))
+  (rx (group xdigit xdigit)
+      (group xdigit xdigit)
+      (group xdigit xdigit)))
 
 (defun hfy-color-vals (color)
   "Where COLOR is a color name or #XXXXXX style triplet, return a
@@ -887,7 +875,9 @@ See also `hfy-display-class' for details of valid values 
for CLASS."
                        (setq score 0) (ignore "t match"))
                       ((not (cdr (assq key face-class))) ;Neither good nor bad.
                        nil (ignore "non match, non collision"))
-                      ((setq x (hfy-interq val (cdr (assq key face-class))))
+                      ((setq x (nreverse
+                                (seq-intersection val (cdr (assq key 
face-class))
+                                                  #'eq)))
                        (setq score (+ score (length x)))
                        (ignore "intersection"))
                       (t ;; nope.
@@ -983,19 +973,18 @@ merged by the user - `hfy-flatten-style' should do this."
                        (:italic         (hfy-slant 'italic))))))
       (setq that (hfy-face-to-style-i next))
       ;;(lwarn t :warning "%S => %S" fn (nconc this that parent))
-      (nconc this parent that))) )
+      (append this parent that))) )
 
-(defun hfy-size-to-int (spec)
+(defun hfy--size-to-int (spec)
   "Convert SPEC, a CSS font-size specifier, to an Emacs :height attribute 
value.
 Used while merging multiple font-size attributes."
-  ;;(message "hfy-size-to-int");;DBUG
-  (list
-   (if (string-match "\\([0-9]+\\)\\(%\\|pt\\)" spec)
-       (cond ((string= "%"  (match-string 2 spec))
-              (/ (string-to-number (match-string 1 spec)) 100.0))
-             ((string= "pt" (match-string 2 spec))
-              (* (string-to-number (match-string 1 spec))    10)))
-     (string-to-number spec))) )
+  ;;(message "hfy--size-to-int");;DBUG
+  (if (string-match "\\([0-9]+\\)\\(%\\|pt\\)" spec)
+      (cond ((string= "%"  (match-string 2 spec))
+             (/ (string-to-number (match-string 1 spec)) 100.0))
+            ((string= "pt" (match-string 2 spec))
+             (* (string-to-number (match-string 1 spec))    10)))
+    (string-to-number spec)) )
 
 ;; size is different, in that in order to get it right at all,
 ;; we have to trawl the inheritance path, accumulating modifiers,
@@ -1006,19 +995,18 @@ any multiple attributes appropriately.  Currently only 
font-size is merged
 down to a single occurrence - others may need special handling, but I
 haven't encountered them yet.  Returns a `hfy-style-assoc'."
   ;;(message "(hfy-flatten-style %S)" style) ;;DBUG
-  (let ((n        0)
-        (m (list 1))
+  (let ((m (list 1))
         (x      nil)
         (r      nil))
     (dolist (css style)
       (if (string= (car css) "font-size")
           (progn
-            (when (not x) (setq m (nconc m (hfy-size-to-int (cdr css)))))
+            (when (not x) (push (hfy--size-to-int (cdr css)) m))
             (when (string-match "pt" (cdr css)) (setq x t)))
-        (setq r (nconc r (list css)))))
+        (push css r)))
     ;;(message "r: %S" r)
-    (setq  n (apply #'* m))
-    (nconc r (hfy-size (if x (round n) (* n 1.0)))) ))
+    (let ((n (apply #'* m)))
+      (nconc (nreverse r) (hfy-size (if x (round n) (float n)))))))
 
 (defun hfy-face-resolve-face (fn)
   "For FN return a face specification.
@@ -1052,7 +1040,7 @@ See also `hfy-face-to-style-i', `hfy-flatten-style'."
                      ;; text-decoration is not inherited.
                      ;; but it's not wrong and if this ever changes it will
                      ;; be needed, so I think it's better to leave it in? -- v
-                     (nconc final-style '(("text-decoration" . "none"))))))
+                     (push '("text-decoration" . "none") final-style))))
     final-style))
 
 ;; strip redundant bits from a name. Technically, this could result in
@@ -2357,6 +2345,13 @@ You may also want to set `hfy-page-header' and 
`hfy-page-footer'."
   (let ((file (hfy-initfile)))
     (load file 'NOERROR nil nil) ))
 
+;; Obsolete.
+
+(defun hfy-interq (set-a set-b)
+  "Return the intersection (using `eq') of two lists SET-A and SET-B."
+  (declare (obsolete seq-intersection "28.1"))
+  (nreverse (seq-intersection set-a set-b #'eq)))
+
 (provide 'htmlfontify)
 
 ;;; htmlfontify.el ends here
diff --git a/lisp/iimage.el b/lisp/iimage.el
index cc1461d..192530a 100644
--- a/lisp/iimage.el
+++ b/lisp/iimage.el
@@ -1,4 +1,4 @@
-;;; iimage.el --- Inline image minor mode.
+;;; iimage.el --- Inline image minor mode.  -*- lexical-binding: t -*-
 
 ;; Copyright (C) 2004-2021 Free Software Foundation, Inc.
 
@@ -51,8 +51,7 @@
 
 (defcustom iimage-mode-image-search-path nil
   "List of directories to search for image files for iimage-mode."
-  :type '(choice (const nil) (repeat directory))
-  :group 'iimage)
+  :type '(choice (const nil) (repeat directory)))
 
 (defvar iimage-mode-image-filename-regex
   (concat "[-+./_0-9a-zA-Z]+\\."
@@ -74,14 +73,12 @@ Examples of image filename patterns to match:
     \\=`file://foo.png\\='
     \\[\\[foo.gif]]
     <foo.png>
-     foo.JPG
-"
-  :type '(alist :key-type regexp :value-type integer)
-  :group 'iimage)
+     foo.JPG"
+  :type '(alist :key-type regexp :value-type integer))
 
 (defvar iimage-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "\C-l" 'iimage-recenter)
+    (define-key map "\C-l" #'iimage-recenter)
     map)
   "Keymap used in `iimage-mode'.")
 
diff --git a/lisp/image-dired.el b/lisp/image-dired.el
index e4b53bd..2509ecf 100644
--- a/lisp/image-dired.el
+++ b/lisp/image-dired.el
@@ -67,9 +67,9 @@
 ;;
 ;; * For `image-dired-get-exif-data' and `image-dired-set-exif-data' to work,
 ;; the command line tool `exiftool' is needed.  It can be found here:
-;; http://www.sno.phy.queensu.ca/~phil/exiftool/.  These two functions
-;; are, among other things, used for writing comments to image files
-;; using `image-dired-thumbnail-set-image-description' and to create
+;; https://exiftool.org/.  These two functions are, among other
+;; things, used for writing comments to image files using
+;; `image-dired-thumbnail-set-image-description' and to create
 ;; "unique" file names using `image-dired-get-exif-file-name' (used by
 ;; `image-dired-copy-with-exif-file-name').
 ;;
diff --git a/lisp/image.el b/lisp/image.el
index 4ede1fb..610d020 100644
--- a/lisp/image.el
+++ b/lisp/image.el
@@ -603,12 +603,16 @@ means display it in the right marginal area."
 (defun insert-image (image &optional string area slice)
   "Insert IMAGE into current buffer at point.
 IMAGE is displayed by inserting STRING into the current buffer
-with a `display' property whose value is the image.  STRING
-defaults to a single space if you omit it.
+with a `display' property whose value is the image.
+
+STRING defaults to a single space if you omit it, which means
+that the inserted image will behave as whitespace syntactically.
+
 AREA is where to display the image.  AREA nil or omitted means
 display it in the text area, a value of `left-margin' means
 display it in the left marginal area, a value of `right-margin'
 means display it in the right marginal area.
+
 SLICE specifies slice of IMAGE to insert.  SLICE nil or omitted
 means insert whole image.  SLICE is a list (X Y WIDTH HEIGHT)
 specifying the X and Y positions and WIDTH and HEIGHT of image area
@@ -1130,6 +1134,7 @@ default is 20%."
     image))
 
 (defun image--get-imagemagick-and-warn (&optional position)
+  (declare-function image-transforms-p "image.c" (&optional frame))
   (unless (or (fboundp 'imagemagick-types) (image-transforms-p))
     (error "Cannot rescale images on this terminal"))
   (let ((image (image--get-image position)))
diff --git a/lisp/international/ccl.el b/lisp/international/ccl.el
index 3c5a461..0eb009f 100644
--- a/lisp/international/ccl.el
+++ b/lisp/international/ccl.el
@@ -43,12 +43,6 @@
 
 ;;; Code:
 
-;; Unused.
-;;; (defgroup ccl nil
-;;;   "CCL (Code Conversion Language) compiler."
-;;;   :prefix "ccl-"
-;;;   :group 'i18n)
-
 (defconst ccl-command-table
   [if branch loop break repeat write-repeat write-read-repeat
       read read-if read-branch write call end
diff --git a/lisp/international/characters.el b/lisp/international/characters.el
index c643f66..97bf31a 100644
--- a/lisp/international/characters.el
+++ b/lisp/international/characters.el
@@ -484,9 +484,9 @@ with L, LRE, or LRO Unicode bidi character type.")
          (progn
            (modify-syntax-entry chars syntax)
            (modify-category-entry chars category))
-       (mapc #'(lambda (x)
-                 (modify-syntax-entry x syntax)
-                 (modify-category-entry x category))
+        (mapc (lambda (x)
+                (modify-syntax-entry x syntax)
+                (modify-category-entry x category))
              chars)))))
 
 ;; Bidi categories
@@ -1390,8 +1390,8 @@ with L, LRE, or LRO Unicode bidi character type.")
        (dolist (charset-info (nthcdr 2 slot))
          (let ((charset (car charset-info)))
            (dolist (code-range (cdr charset-info))
-             (map-charset-chars #'(lambda (range _arg)
-                                    (set-char-table-range table range 2))
+              (map-charset-chars (lambda (range _arg)
+                                   (set-char-table-range table range 2))
                                 charset nil
                                 (car code-range) (cdr code-range)))))
        (optimize-char-table table)
@@ -1417,8 +1417,8 @@ Setup char-width-table appropriate for non-CJK language 
environment."
   (require 'charscript))
 
 (map-charset-chars
- #'(lambda (range _ignore)
-     (set-char-table-range char-script-table range 'tibetan))
+ (lambda (range _ignore)
+   (set-char-table-range char-script-table range 'tibetan))
  'tibetan)
 
 
@@ -1426,14 +1426,14 @@ Setup char-width-table appropriate for non-CJK language 
environment."
 
 (when (setq unicode-category-table
            (unicode-property-table-internal 'general-category))
-  (map-char-table #'(lambda (key val)
-                     (if val
-                         (cond ((or (and (/= (aref (symbol-name val) 0) ?M)
-                                         (/= (aref (symbol-name val) 0) ?C))
-                                    (eq val 'Zs))
-                                (modify-category-entry key ?.))
-                               ((eq val 'Mn)
-                                (modify-category-entry key ?^)))))
+  (map-char-table (lambda (key val)
+                    (if val
+                        (cond ((or (and (/= (aref (symbol-name val) 0) ?M)
+                                        (/= (aref (symbol-name val) 0) ?C))
+                                   (eq val 'Zs))
+                               (modify-category-entry key ?.))
+                              ((eq val 'Mn)
+                               (modify-category-entry key ?^)))))
                  unicode-category-table))
 
 (optimize-char-table (standard-category-table))
@@ -1524,21 +1524,21 @@ option `glyphless-char-display'."
            ((eq target 'format-control)
             (when unicode-category-table
               (map-char-table
-               #'(lambda (char category)
-                   (if (eq category 'Cf)
-                       (let ((this-method method)
-                             from to)
-                         (if (consp char)
-                             (setq from (car char) to (cdr char))
-                           (setq from char to char))
-                         (while (<= from to)
-                           (when (/= from #xAD)
-                             (if (eq method 'acronym)
-                                 (setq this-method
-                                       (aref char-acronym-table from)))
-                             (set-char-table-range glyphless-char-display
-                                                   from this-method))
-                           (setq from (1+ from))))))
+                (lambda (char category)
+                  (if (eq category 'Cf)
+                      (let ((this-method method)
+                            from to)
+                        (if (consp char)
+                            (setq from (car char) to (cdr char))
+                          (setq from char to char))
+                        (while (<= from to)
+                          (when (/= from #xAD)
+                            (if (eq method 'acronym)
+                                (setq this-method
+                                      (aref char-acronym-table from)))
+                            (set-char-table-range glyphless-char-display
+                                                  from this-method))
+                          (setq from (1+ from))))))
                unicode-category-table)))
            ((eq target 'no-font)
             (set-char-table-extra-slot glyphless-char-display 0 method))
diff --git a/lisp/international/fontset.el b/lisp/international/fontset.el
index 8f0f263..3deaff9 100644
--- a/lisp/international/fontset.el
+++ b/lisp/international/fontset.el
@@ -497,37 +497,37 @@
                     (:registry "iso10646-1"))))
         (cjk-table (make-char-table nil))
         (script-coverage
-         #'(lambda (script)
-             (let ((coverage))
-               (map-char-table
-                #'(lambda (range val)
-                    (when (eq val script)
-                      (if (consp range)
-                          (setq range (cons (car range) (cdr range))))
-                      (push range coverage)))
-                char-script-table)
-               coverage)))
+          (lambda (script)
+            (let ((coverage))
+              (map-char-table
+               (lambda (range val)
+                 (when (eq val script)
+                   (if (consp range)
+                       (setq range (cons (car range) (cdr range))))
+                   (push range coverage)))
+               char-script-table)
+              coverage)))
         (data (list (vconcat (mapcar 'car cjk))))
         (i 0))
     (dolist (elt cjk)
       (let ((mask (ash 1 i)))
        (map-charset-chars
-        #'(lambda (range _arg)
-            (let ((from (car range)) (to (cdr range)))
-              (if (< to #x110000)
-                  (while (<= from to)
-                    (or (memq (aref char-script-table from)
-                              '(kana hangul han cjk-misc))
-                        (aset cjk-table from
-                              (logior (or (aref cjk-table from) 0) mask)))
-                    (setq from (1+ from))))))
+         (lambda (range _arg)
+           (let ((from (car range)) (to (cdr range)))
+             (if (< to #x110000)
+                 (while (<= from to)
+                   (or (memq (aref char-script-table from)
+                             '(kana hangul han cjk-misc))
+                       (aset cjk-table from
+                             (logior (or (aref cjk-table from) 0) mask)))
+                   (setq from (1+ from))))))
         (nth 1 elt) nil (nth 2 elt) (nth 3 elt)))
       (setq i (1+ i)))
     (map-char-table
-     #'(lambda (range val)
-        (if (consp range)
-            (setq range (cons (car range) (cdr range))))
-        (push (cons range val) data))
+     (lambda (range val)
+       (if (consp range)
+           (setq range (cons (car range) (cdr range))))
+       (push (cons range val) data))
      cjk-table)
     (dolist (script scripts)
       (dolist (range (funcall script-coverage (car script)))
@@ -1227,7 +1227,7 @@ Done when `mouse-set-font' is called."
          (string-match "fontset-auto[0-9]+$" fontset)
          (push (list (fontset-plain-name fontset) fontset) l)))
     (cons "Fontset"
-         (sort l #'(lambda (x y) (string< (car x) (car y)))))))
+          (sort l (lambda (x y) (string< (car x) (car y)))))))
 
 (declare-function query-fontset "fontset.c" (pattern &optional regexpp))
 
diff --git a/lisp/international/latin1-disp.el 
b/lisp/international/latin1-disp.el
index 4b6ef98..b3d6a63 100644
--- a/lisp/international/latin1-disp.el
+++ b/lisp/international/latin1-disp.el
@@ -186,8 +186,8 @@ character set."
                     'arabic-iso8859-6
                   (car (remq 'ascii (get-language-info language
                                                        'charset))))))
-    (map-charset-chars #'(lambda (range _arg)
-                          (standard-display-default (car range) (cdr range)))
+    (map-charset-chars (lambda (range _arg)
+                         (standard-display-default (car range) (cdr range)))
                       charset))
   (sit-for 0))
 
diff --git a/lisp/international/mule-cmds.el b/lisp/international/mule-cmds.el
index da75adb..c055523 100644
--- a/lisp/international/mule-cmds.el
+++ b/lisp/international/mule-cmds.el
@@ -679,18 +679,18 @@ DEFAULT is the coding system to use by default in the 
query."
   ;;   ((CODING (POS . CHAR) (POS . CHAR) ...) ...)
   (if unsafe
       (setq unsafe
-           (mapcar #'(lambda (coding)
-                       (cons coding
-                             (if (stringp from)
-                                 (mapcar #'(lambda (pos)
-                                             (cons pos (aref from pos)))
-                                         (unencodable-char-position
-                                          0 (length from) coding
-                                          11 from))
-                               (mapcar #'(lambda (pos)
-                                           (cons pos (char-after pos)))
-                                       (unencodable-char-position
-                                        from to coding 11)))))
+            (mapcar (lambda (coding)
+                      (cons coding
+                            (if (stringp from)
+                                (mapcar (lambda (pos)
+                                          (cons pos (aref from pos)))
+                                        (unencodable-char-position
+                                         0 (length from) coding
+                                         11 from))
+                              (mapcar (lambda (pos)
+                                        (cons pos (char-after pos)))
+                                      (unencodable-char-position
+                                       from to coding 11)))))
                    unsafe)))
 
   (setq codings (sanitize-coding-system-list codings))
@@ -744,19 +744,19 @@ e.g., for sending an email message.\n ")
                (insert (format "  %s cannot encode these:" (car coding)))
                (let ((i 0)
                      (func1
-                      #'(lambda (bufname pos)
-                          (when (buffer-live-p (get-buffer bufname))
-                            (pop-to-buffer bufname)
-                            (goto-char pos))))
+                       (lambda (bufname pos)
+                         (when (buffer-live-p (get-buffer bufname))
+                           (pop-to-buffer bufname)
+                           (goto-char pos))))
                      (func2
-                      #'(lambda (bufname pos coding)
-                          (when (buffer-live-p (get-buffer bufname))
-                            (pop-to-buffer bufname)
-                            (if (< (point) pos)
-                                (goto-char pos)
-                              (forward-char 1)
-                              (search-unencodable-char coding)
-                              (forward-char -1))))))
+                       (lambda (bufname pos coding)
+                         (when (buffer-live-p (get-buffer bufname))
+                           (pop-to-buffer bufname)
+                           (if (< (point) pos)
+                               (goto-char pos)
+                             (forward-char 1)
+                             (search-unencodable-char coding)
+                             (forward-char -1))))))
                  (dolist (elt (cdr coding))
                    (insert " ")
                    (if (stringp from)
@@ -1524,7 +1524,7 @@ To deactivate it programmatically, use 
`deactivate-input-method'."
   (interactive
    (let* ((default (or (car input-method-history) default-input-method)))
      (list (read-input-method-name
-           (if default "Select input method (default %s): " "Select input 
method: ")
+           (format-prompt "Select input method" default)
            default t)
           t)))
   (activate-input-method input-method)
@@ -1569,7 +1569,7 @@ which marks the variable `default-input-method' as set 
for Custom buffers."
        (if (or arg (not default))
           (progn
             (read-input-method-name
-             (if default "Input method (default %s): " "Input method: " )
+             (format-prompt "Input method" default)
              default t))
         default))
       (unless default-input-method
@@ -1620,7 +1620,7 @@ If `default-transient-input-method' was not yet defined, 
prompt for it."
   "Describe input method INPUT-METHOD."
   (interactive
    (list (read-input-method-name
-         "Describe input method (default current choice): ")))
+          (format-prompt "Describe input method" current-input-method))))
   (if (and input-method (symbolp input-method))
       (setq input-method (symbol-name input-method)))
   (help-setup-xref (list #'describe-input-method
@@ -1929,7 +1929,7 @@ runs the hook `exit-language-environment-hook'.  After 
setting up
 the new language environment, it runs `set-language-environment-hook'."
   (interactive (list (read-language-name
                      nil
-                     "Set language environment (default English): ")))
+                     (format-prompt "Set language environment" "English"))))
   (if language-name
       (if (symbolp language-name)
          (setq language-name (symbol-name language-name)))
@@ -2144,7 +2144,7 @@ See `set-language-info-alist' for use in programs."
   (interactive
    (list (read-language-name
          'documentation
-         "Describe language environment (default current choice): ")))
+         (format-prompt "Describe language environment" 
current-language-environment))))
   (if (null language-name)
       (setq language-name current-language-environment))
   (if (or (null language-name)
@@ -2245,7 +2245,7 @@ See `set-language-info-alist' for use in programs."
      ;; LANGUAGE is a language code taken from ISO 639:1988 (E/F)
      ;; with additions from ISO 639/RA Newsletter No.1/1989;
      ;; see Internet RFC 2165 (1997-06) and
-     ;; http://www.evertype.com/standards/iso639/iso639-en.html
+     ;; https://www.evertype.com/standards/iso639/iso639-en.html
      ;; TERRITORY is a country code taken from ISO 3166
      ;; http://www.din.de/gremien/nas/nabd/iso3166ma/codlstp1/en_listp1.html.
      ;; CODESET and MODIFIER are implementation-dependent.
diff --git a/lisp/international/mule-conf.el b/lisp/international/mule-conf.el
index 64aac46..2d36dab 100644
--- a/lisp/international/mule-conf.el
+++ b/lisp/international/mule-conf.el
@@ -41,7 +41,7 @@
 ;; Standards docs equivalent to iso-2022 and iso-8859 are at
 ;; https://www.ecma.ch/.
 
-;; FWIW, http://www.microsoft.com/globaldev/ lists the following for
+;; FWIW, https://www.microsoft.com/globaldev/ lists the following for
 ;; MS Windows, which are presumably the only charsets we really need
 ;; to worry about on such systems:
 ;; `OEM codepages': 437, 720, 737, 775, 850, 852, 855, 857, 858, 862, 866
@@ -358,7 +358,7 @@
   :code-offset #x130000
   :unify-map "BIG5")
 ;; Fixme: AKA cp950 according to
-;; <URL:http://www.microsoft.com/globaldev/reference/WinCP.asp>.  Is
+;; <URL:https://www.microsoft.com/globaldev/reference/WinCP.asp>.  Is
 ;; that correct?
 
 (define-charset 'chinese-big5-1
@@ -708,7 +708,7 @@
 ;; Original name for cp1125, says Serhii Hlodin <hlodin@lutsk.bank.gov.ua>
 (define-charset-alias 'cp866u 'cp1125)
 
-;; Fixme: C.f. iconv, http://czyborra.com/charsets/codepages.html
+;; Fixme: C.f. iconv, https://czyborra.com/charsets/codepages.html
 ;; shows this as not ASCII compatible, with various graphics in
 ;; 0x01-0x1F.
 (define-charset 'cp437
diff --git a/lisp/international/mule-diag.el b/lisp/international/mule-diag.el
index d97d090..2d3cd25b 100644
--- a/lisp/international/mule-diag.el
+++ b/lisp/international/mule-diag.el
@@ -45,8 +45,8 @@
 (define-button-type 'sort-listed-character-sets
   'help-echo (purecopy "mouse-2, RET: sort on this column")
   'face 'bold
-  'action #'(lambda (button)
-             (sort-listed-character-sets (button-get button 'sort-key))))
+  'action (lambda (button)
+            (sort-listed-character-sets (button-get button 'sort-key))))
 
 (define-button-type 'list-charset-chars
   :supertype 'help-xref
@@ -835,6 +835,8 @@ The IGNORED argument is ignored."
    (list (completing-read
           "Font name (default current choice for ASCII chars): "
           (and window-system
+               ;; Implied by `window-system'.
+               (fboundp 'x-list-fonts)
                (fboundp 'fontset-list)
                ;; The final element in `fontset-list' is a default
                ;; (generic) one, so don't include that.
@@ -1170,12 +1172,12 @@ The default is 20.  If LIMIT is negative, do not limit 
the listing."
        (if (or (vectorp elt) (listp elt))
            (let ((i 0))
              (catch 'tag
-               (mapc #'(lambda (x)
-                         (setq i (1+ i))
-                         (when (= i limit)
-                           (insert "  ...\n")
-                           (throw 'tag nil))
-                         (insert (format "  %s\n" x)))
+                (mapc (lambda (x)
+                        (setq i (1+ i))
+                        (when (= i limit)
+                          (insert "  ...\n")
+                          (throw 'tag nil))
+                        (insert (format "  %s\n" x)))
                      elt)))
          (insert (format "  %s\n" elt)))))))
 
diff --git a/lisp/international/mule.el b/lisp/international/mule.el
index 52e743e..a6fccff 100644
--- a/lisp/international/mule.el
+++ b/lisp/international/mule.el
@@ -32,7 +32,7 @@
 
 (defconst mule-version "6.0 (HANACHIRUSATO)" "\
 Version number and name of this version of MULE (multilingual environment).")
-(make-obsolete-variable 'mule-version nil "28.1")
+(make-obsolete-variable 'mule-version 'emacs-version "28.1")
 
 (defconst mule-version-date "2003.9.1" "\
 Distribution date of this version of MULE (multilingual environment).")
@@ -490,27 +490,27 @@ per-character basis, this may not be accurate."
                   (cond
                    ((listp cs-list)
                     (catch 'tag
-                      (mapc #'(lambda (charset)
-                                (if (encode-char char charset)
-                                    (throw 'tag charset)))
+                       (mapc (lambda (charset)
+                               (if (encode-char char charset)
+                                   (throw 'tag charset)))
                             cs-list)
                       nil))
                    ((eq cs-list 'iso-2022)
                     (catch 'tag2
-                      (mapc #'(lambda (charset)
-                                (if (and (plist-get (charset-plist charset)
-                                                    :iso-final-char)
-                                         (encode-char char charset))
-                                    (throw 'tag2 charset)))
+                       (mapc (lambda (charset)
+                               (if (and (plist-get (charset-plist charset)
+                                                   :iso-final-char)
+                                        (encode-char char charset))
+                                   (throw 'tag2 charset)))
                             charset-list)
                       nil))
                    ((eq cs-list 'emacs-mule)
                     (catch 'tag3
-                      (mapc #'(lambda (charset)
-                                (if (and (plist-get (charset-plist charset)
-                                                    :emacs-mule-id)
-                                         (encode-char char charset))
-                                    (throw 'tag3 charset)))
+                       (mapc (lambda (charset)
+                               (if (and (plist-get (charset-plist charset)
+                                                   :emacs-mule-id)
+                                        (encode-char char charset))
+                                   (throw 'tag3 charset)))
                             charset-list)
                       nil)))))))))))
 
diff --git a/lisp/international/quail.el b/lisp/international/quail.el
index 87a9050..fff06de 100644
--- a/lisp/international/quail.el
+++ b/lisp/international/quail.el
@@ -728,9 +728,9 @@ Available types are listed in the variable 
`quail-keyboard-layout-alist'."
   :type (cons 'choice (mapcar (lambda (elt)
                                (list 'const (car elt)))
                              quail-keyboard-layout-alist))
-  :set #'(lambda (symbol value)
-          (quail-update-keyboard-layout value)
-          (set symbol value)))
+  :set (lambda (symbol value)
+         (quail-update-keyboard-layout value)
+         (set symbol value)))
 
 ;;;###autoload
 (defun quail-set-keyboard-layout (kbd-type)
@@ -1571,12 +1571,12 @@ with more keys."
            (let (char)
              (if (stringp quail-current-str)
                  (catch 'tag
-                   (mapc #'(lambda (ch)
-                             (when (/= (unibyte-char-to-multibyte
-                                        (multibyte-char-to-unibyte ch))
-                                       ch)
-                                 (setq char ch)
-                                 (throw 'tag nil)))
+                    (mapc (lambda (ch)
+                            (when (/= (unibyte-char-to-multibyte
+                                       (multibyte-char-to-unibyte ch))
+                                      ch)
+                              (setq char ch)
+                              (throw 'tag nil)))
                          quail-current-str))
                (if (/= (unibyte-char-to-multibyte
                         (multibyte-char-to-unibyte quail-current-str))
@@ -2827,19 +2827,19 @@ If CHAR is an ASCII character and can be input by 
typing itself, return t."
        (key-list nil))
     (if (consp decode-map)
        (let ((str (string char)))
-         (mapc #'(lambda (elt)
-                   (if (string= str (car elt))
-                       (setq key-list (cons (cdr elt) key-list))))
+          (mapc (lambda (elt)
+                  (if (string= str (car elt))
+                      (setq key-list (cons (cdr elt) key-list))))
                (cdr decode-map)))
       (let ((key-head (aref decode-map char)))
        (if (stringp key-head)
            (setq key-list (quail-find-key1
                            (quail-lookup-key key-head nil t)
                            key-head char nil))
-         (mapc #'(lambda (elt)
-                   (setq key-list
-                         (quail-find-key1
-                          (quail-lookup-key elt nil t) elt char key-list)))
+          (mapc (lambda (elt)
+                  (setq key-list
+                        (quail-find-key1
+                         (quail-lookup-key elt nil t) elt char key-list)))
                key-head))))
     (or key-list
        (and (< char 128)
diff --git a/lisp/international/titdic-cnv.el b/lisp/international/titdic-cnv.el
index 64d6644..ccb4c83 100644
--- a/lisp/international/titdic-cnv.el
+++ b/lisp/international/titdic-cnv.el
@@ -781,7 +781,7 @@ To get complete usage, invoke \"emacs -batch -f 
batch-titdic-convert -h\"."
            (if val (setq trans (concat val trans)))
            (puthash key trans table)
            (forward-line 1)))
-       (maphash #'(lambda (key val) (setq dic (cons (cons key val) dic)))
+        (maphash (lambda (key val) (setq dic (cons (cons key val) dic)))
                 table)))
     (setq dic (sort dic (lambda (x y) (string< (car x ) (car y)))))
     (dolist (elt dic)
@@ -931,18 +931,18 @@ method `chinese-tonepy' with which you must specify tones 
by digits
          (if val (setq trans (vconcat val trans)))
          (puthash key trans table)
          (forward-line 1))
-       (maphash #'(lambda (key trans)
-                    (let ((len (length trans))
-                          i)
-                      (if (and (= len 1) (= (length (aref trans 0)) 1))
-                          (setq trans (aref trans 0))
-                        (setq i 0)
-                        (while (and (< i len)
-                                    (= (length (aref trans i)) 1))
-                          (setq i (1+ i)))
-                        (if (= i len)
-                            (setq trans (mapconcat #'identity trans "")))))
-                    (setq dic (cons (cons key trans) dic)))
+        (maphash (lambda (key trans)
+                   (let ((len (length trans))
+                         i)
+                     (if (and (= len 1) (= (length (aref trans 0)) 1))
+                         (setq trans (aref trans 0))
+                       (setq i 0)
+                       (while (and (< i len)
+                                   (= (length (aref trans i)) 1))
+                         (setq i (1+ i)))
+                       (if (= i len)
+                           (setq trans (mapconcat #'identity trans "")))))
+                   (setq dic (cons (cons key trans) dic)))
                 table)))
     (setq dic (sort dic (lambda (x y) (string< (car x) (car y)))))
     (goto-char (point-max))
diff --git a/lisp/isearchb.el b/lisp/isearchb.el
index 3713879..67020b7 100644
--- a/lisp/isearchb.el
+++ b/lisp/isearchb.el
@@ -1,4 +1,4 @@
-;;; isearchb --- a marriage between iswitchb and isearch
+;;; isearchb.el --- a marriage between iswitchb and isearch  -*- 
lexical-binding: t -*-
 
 ;; Copyright (C) 2004-2021 Free Software Foundation, Inc.
 
@@ -89,13 +89,11 @@
   "Number of idle seconds before isearchb turns itself off.
 If nil, don't use a timeout."
   :type '(choice (integer :tag "Seconds")
-                (const :tag "Disable" nil))
-  :group 'isearchb)
+                 (const :tag "Disable" nil)))
 
 (defcustom isearchb-show-completions t
   "If non-nil, show possible completions in the minibuffer."
-  :type 'boolean
-  :group 'isearchb)
+  :type 'boolean)
 
 (defvar isearchb-start-buffer nil)
 (defvar isearchb-last-buffer nil)
diff --git a/lisp/json.el b/lisp/json.el
index 6677c3b..0e61e1a 100644
--- a/lisp/json.el
+++ b/lisp/json.el
@@ -26,7 +26,7 @@
 ;; This is a library for parsing and generating JSON (JavaScript Object
 ;; Notation).
 
-;; Learn all about JSON here: <URL:http://json.org/>.
+;; Learn all about JSON here: <URL:https://json.org/>.
 
 ;; The user-serviceable entry points for the parser are the functions
 ;; `json-read' and `json-read-from-string'.  The encoder has a single
diff --git a/lisp/language/cyrillic.el b/lisp/language/cyrillic.el
index c12096f..b64a237 100644
--- a/lisp/language/cyrillic.el
+++ b/lisp/language/cyrillic.el
@@ -33,7 +33,7 @@
 ;; are converted to Unicode internally.  See
 ;; <URL:http://www.ecma.ch/ecma1/STAND/ECMA-113.HTM>.  For more info
 ;; on Cyrillic charsets, see
-;; <URL:http://czyborra.com/charsets/cyrillic.html>.  The KOI and
+;; <URL:https://czyborra.com/charsets/cyrillic.html>.  The KOI and
 ;; Alternativnyj coding systems should live in code-pages.el, but
 ;; they've always been preloaded and the coding system autoload
 ;; mechanism didn't get accepted, so they have to stay here and
diff --git a/lisp/ldefs-boot.el b/lisp/ldefs-boot.el
index fa971b3..412751b 100644
--- a/lisp/ldefs-boot.el
+++ b/lisp/ldefs-boot.el
@@ -477,31 +477,31 @@ With value nil, inhibit any automatic allout-mode 
activation.")
 
 (custom-autoload 'allout-auto-activation "allout" nil)
 
-(put 'allout-use-hanging-indents 'safe-local-variable 'booleanp)
+(put 'allout-use-hanging-indents 'safe-local-variable #'booleanp)
 
 (put 'allout-reindent-bodies 'safe-local-variable (lambda (x) (memq x '(nil t 
text force))))
 
-(put 'allout-show-bodies 'safe-local-variable 'booleanp)
+(put 'allout-show-bodies 'safe-local-variable #'booleanp)
 
-(put 'allout-header-prefix 'safe-local-variable 'stringp)
+(put 'allout-header-prefix 'safe-local-variable #'stringp)
 
-(put 'allout-primary-bullet 'safe-local-variable 'stringp)
+(put 'allout-primary-bullet 'safe-local-variable #'stringp)
 
-(put 'allout-plain-bullets-string 'safe-local-variable 'stringp)
+(put 'allout-plain-bullets-string 'safe-local-variable #'stringp)
 
-(put 'allout-distinctive-bullets-string 'safe-local-variable 'stringp)
+(put 'allout-distinctive-bullets-string 'safe-local-variable #'stringp)
 
 (put 'allout-use-mode-specific-leader 'safe-local-variable (lambda (x) (or 
(memq x '(t nil allout-mode-leaders comment-start)) (stringp x))))
 
-(put 'allout-old-style-prefixes 'safe-local-variable 'booleanp)
+(put 'allout-old-style-prefixes 'safe-local-variable #'booleanp)
 
-(put 'allout-stylish-prefixes 'safe-local-variable 'booleanp)
+(put 'allout-stylish-prefixes 'safe-local-variable #'booleanp)
 
-(put 'allout-numbered-bullet 'safe-local-variable 'string-or-null-p)
+(put 'allout-numbered-bullet 'safe-local-variable #'string-or-null-p)
 
-(put 'allout-file-xref-bullet 'safe-local-variable 'string-or-null-p)
+(put 'allout-file-xref-bullet 'safe-local-variable #'string-or-null-p)
 
-(put 'allout-presentation-padding 'safe-local-variable 'integerp)
+(put 'allout-presentation-padding 'safe-local-variable #'integerp)
 
 (put 'allout-layout 'safe-local-variable (lambda (x) (or (numberp x) (listp x) 
(memq x '(: * + -)))))
 
@@ -784,7 +784,7 @@ OPEN:       A TOPIC that is not CLOSED, though its 
OFFSPRING or BODY may be.
 
 \(fn &optional ARG)" t nil)
 
-(defalias 'outlinify-sticky 'outlineify-sticky)
+(defalias 'outlinify-sticky #'outlineify-sticky)
 
 (autoload 'outlineify-sticky "allout" "\
 Activate outline mode and establish file var so it is started subsequently.
@@ -827,7 +827,7 @@ See `allout-widgets-mode' for allout widgets mode 
features.")
 
 (custom-autoload 'allout-widgets-auto-activation "allout-widgets" nil)
 
-(put 'allout-widgets-mode-inhibit 'safe-local-variable 'booleanp)
+(put 'allout-widgets-mode-inhibit 'safe-local-variable #'booleanp)
 
 (autoload 'allout-widgets-mode "allout-widgets" "\
 Toggle Allout Widgets mode.
@@ -1161,11 +1161,11 @@ Returns list of symbols and documentation found.
 (autoload 'archive-mode "arc-mode" "\
 Major mode for viewing an archive file in a dired-like way.
 You can move around using the usual cursor motion commands.
-Letters no longer insert themselves.
-Type `e' to pull a file out of the archive and into its own buffer;
+Letters no longer insert themselves.\\<archive-mode-map>
+Type \\[archive-extract] to pull a file out of the archive and into its own 
buffer;
 or click mouse-2 on the file's line in the archive mode buffer.
 
-If you edit a sub-file of this archive (as with the `e' command) and
+If you edit a sub-file of this archive (as with the \\[archive-extract] 
command) and
 save it, the contents of that buffer will be saved back into the
 archive.
 
@@ -1539,7 +1539,7 @@ ENTRY is the name of a password-store entry.
 The key used to retrieve the password is the symbol `secret'.
 
 The convention used as the format for a password-store file is
-the following (see http://www.passwordstore.org/#organization):
+the following (see https://www.passwordstore.org/#organization):
 
 secret
 key1: value1
@@ -1995,6 +1995,20 @@ seconds.
 ;;;;;;  0 0))
 ;;; Generated autoloads from emacs-lisp/benchmark.el
 
+(autoload 'benchmark-call "benchmark" "\
+Measure the run time of calling FUNC a number REPETITIONS of times.
+The result is a list (TIME GC GCTIME)
+where TIME is the total time it took, in seconds.
+GCTIME is the amount of time that was spent in the GC
+and GC is the number of times the GC was called.
+
+REPETITIONS can also be a floating point number, in which case it
+specifies a minimum number of seconds that the benchmark execution
+should take.  In that case the return value is prepended with the
+number of repetitions actually used.
+
+\(fn FUNC &optional REPETITIONS)" nil nil)
+
 (autoload 'benchmark-run "benchmark" "\
 Time execution of FORMS.
 If REPETITIONS is supplied as a number, run FORMS that many times,
@@ -2024,6 +2038,8 @@ Interactively, REPETITIONS is taken from the prefix arg, 
and
 the command prompts for the form to benchmark.
 For non-interactive use see also `benchmark-run' and
 `benchmark-run-compiled'.
+FORM can also be a function in which case we measure the time it takes
+to call it without any argument.
 
 \(fn REPETITIONS FORM)" t nil)
 
@@ -2035,7 +2051,7 @@ The return value is the value of the final form in BODY.
 
 (function-put 'benchmark-progn 'lisp-indent-function '0)
 
-(register-definition-prefixes "benchmark" '("benchmark-elapse"))
+(register-definition-prefixes "benchmark" '("benchmark-"))
 
 ;;;***
 
@@ -4794,7 +4810,7 @@ element to judge if that element should be excluded from 
the list.
 The buffer is left in Command History mode." t nil)
 
 (autoload 'command-history "chistory" "\
-Examine commands from `command-history' in a buffer.
+Examine commands from variable `command-history' in a buffer.
 The number of commands listed is controlled by `list-command-history-max'.
 The command history is filtered by `list-command-history-filter' if non-nil.
 Use \\<command-history-map>\\[command-history-repeat] to repeat the command on 
the current line.
@@ -4892,8 +4908,12 @@ all methods of NAME have to use the same set of 
arguments for dispatch.
 Each dispatch argument and TYPE are specified in ARGS where the corresponding
 formal argument appears as (VAR TYPE) rather than just VAR.
 
-The optional second argument QUALIFIER is a specifier that
-modifies how the method is combined with other methods, including:
+The optional EXTRA element, on the form `:extra STRING', allows
+you to add more methods for the same specializers and qualifiers.
+These are distinguished by STRING.
+
+The optional argument QUALIFIER is a specifier that modifies how
+the method is combined with other methods, including:
    :before  - Method will be called before the primary
    :after   - Method will be called after the primary
    :around  - Method will be called around everything else
@@ -4910,9 +4930,9 @@ method to be applicable.
 The set of acceptable TYPEs (also called \"specializers\") is defined
 \(and can be extended) by the various methods of `cl-generic-generalizers'.
 
-\(fn NAME [QUALIFIER] ARGS &rest [DOCSTRING] BODY)" nil t)
+\(fn NAME [EXTRA] [QUALIFIER] ARGS &rest [DOCSTRING] BODY)" nil t)
 
-(function-put 'cl-defmethod 'doc-string-elt '3)
+(function-put 'cl-defmethod 'doc-string-elt 'cl--defmethod-doc-pos)
 
 (function-put 'cl-defmethod 'lisp-indent-function 'defun)
 
@@ -6769,6 +6789,8 @@ If the HANDLER returns a `dbus-error', it is propagated 
as return message.
 
 \(fn EVENT)" t nil)
 
+(function-put 'dbus-handle-event 'completion-predicate #'ignore)
+
 (autoload 'dbus-monitor "dbus" "\
 Invoke `dbus-register-monitor' interactively, and switch to the buffer.
 BUS is either a Lisp keyword, `:system' or `:session', or a
@@ -10614,7 +10636,7 @@ be invoked for the values of the other parameters.
 
 \(fn &key (SERVER (erc-compute-server)) (PORT (erc-compute-port)) (NICK 
(erc-compute-nick)) PASSWORD (FULL-NAME (erc-compute-full-name)))" t nil)
 
-(defalias 'erc-select 'erc)
+(defalias 'erc-select #'erc)
 
 (autoload 'erc-tls "erc" "\
 Interactively select TLS connection parameters and run ERC.
@@ -10737,7 +10759,7 @@ and how to display message.
 
 \(fn SELECTOR &optional OUTPUT-BUFFER-NAME MESSAGE-FN)" t nil)
 
-(defalias 'ert 'ert-run-tests-interactively)
+(defalias 'ert #'ert-run-tests-interactively)
 
 (autoload 'ert-describe-test "ert" "\
 Display the documentation for TEST-OR-TEST-NAME (a symbol or ert-test).
@@ -11948,6 +11970,13 @@ Besides the choice of face, it is the same as 
`buffer-face-mode'.
 
 ;;;***
 
+;;;### (autoloads nil "facemenu" "facemenu.el" (0 0 0 0))
+;;; Generated autoloads from facemenu.el
+
+(register-definition-prefixes "facemenu" '("facemenu-" "list-colors-"))
+
+;;;***
+
 ;;;### (autoloads nil "faceup" "emacs-lisp/faceup.el" (0 0 0 0))
 ;;; Generated autoloads from emacs-lisp/faceup.el
 (push (purecopy '(faceup 0 0 6)) package--builtin-versions)
@@ -12212,6 +12241,8 @@ Otherwise, signal a `file-notify-error'.
 
 \(fn OBJECT)" t nil)
 
+(function-put 'file-notify-handle-event 'completion-predicate #'ignore)
+
 (register-definition-prefixes "filenotify" '("file-notify-"))
 
 ;;;***
@@ -12711,7 +12742,6 @@ Change the filter on a `find-lisp-find-dired' buffer to 
REGEXP.
 
 ;;;### (autoloads nil "finder" "finder.el" (0 0 0 0))
 ;;; Generated autoloads from finder.el
-(push (purecopy '(finder 1 0)) package--builtin-versions)
 
 (autoload 'finder-list-keywords "finder" "\
 Display descriptions of the keywords in the Finder buffer." t nil)
@@ -12780,7 +12810,7 @@ lines.
 (autoload 'flymake-log "flymake" "\
 Log, at level LEVEL, the message MSG formatted with ARGS.
 LEVEL is passed to `display-warning', which is used to display
-the warning.  If this form is included in a byte-compiled file,
+the warning.  If this form is included in a file,
 the generated warning contains an indication of the file that
 generated it.
 
@@ -14390,15 +14420,15 @@ If FORCE is non-nil, replace the old ones.
 Minor mode for providing mailing-list commands.
 
 If called interactively, toggle `Gnus-Mailing-List mode'.  If the
-prefix argument is positive, enable the mode, and if it is zero
-or negative, disable the mode.
+prefix argument is positive, enable the mode, and if it is zero or
+negative, disable the mode.
 
-If called from Lisp, toggle the mode if ARG is `toggle'.  Enable
-the mode if ARG is nil, omitted, or is a positive number.
-Disable the mode if ARG is a negative number.
+If called from Lisp, toggle the mode if ARG is `toggle'.  Enable the
+mode if ARG is nil, omitted, or is a positive number.  Disable the
+mode if ARG is a negative number.
 
-The mode's hook is called both when the mode is enabled and when
-it is disabled.
+The mode's hook is called both when the mode is enabled and when it is
+disabled.
 
 \\{gnus-mailing-list-mode-map}
 
@@ -16840,7 +16870,7 @@ buffers which are visiting a file.
 
 (autoload 'ibuffer "ibuffer" "\
 Begin using Ibuffer to edit a list of buffers.
-Type `h' after entering ibuffer for more information.
+Type \\<ibuffer-mode-map>\\[describe-mode] after entering ibuffer for more 
information.
 
 All arguments are optional.
 OTHER-WINDOW-P says to use another window.
@@ -17126,7 +17156,7 @@ The main features of this mode are
    Use \\[idlwave-fill-paragraph] to refill a paragraph inside a
    comment.  The indentation of the second line of the paragraph
    relative to the first will be retained.  Use
-   \\[idlwave-auto-fill-mode] to toggle auto-fill mode for these
+   \\[auto-fill-mode] to toggle auto-fill mode for these
    comments.  When the variable `idlwave-fill-comment-line-only' is
    nil, code can also be auto-filled and auto-indented.
 
@@ -18594,25 +18624,6 @@ See Info node `(elisp)Defining Functions' for more 
details.
 
 ;;;***
 
-;;;### (autoloads nil "inversion" "cedet/inversion.el" (0 0 0 0))
-;;; Generated autoloads from cedet/inversion.el
-(push (purecopy '(inversion 1 3)) package--builtin-versions)
-
-(autoload 'inversion-require-emacs "inversion" "\
-Declare that you need either EMACS-VER, XEMACS-VER or SXEMACS-ver.
-Only checks one based on which kind of Emacs is being run.
-
-This function is obsolete; do this instead:
-    (when (version<= \"28.1\" emacs-version) ...)
-
-\(fn EMACS-VER XEMACS-VER SXEMACS-VER)" nil nil)
-
-(make-obsolete 'inversion-require-emacs 'nil '"28.1")
-
-(register-definition-prefixes "inversion" '("inversion-"))
-
-;;;***
-
 ;;;### (autoloads nil "isearch-x" "international/isearch-x.el" (0
 ;;;;;;  0 0 0))
 ;;; Generated autoloads from international/isearch-x.el
@@ -19540,13 +19551,13 @@ A major mode to edit GNU ld script files
 ;;;;;;  (0 0 0 0))
 ;;; Generated autoloads from textmodes/less-css-mode.el
 
-(put 'less-css-compile-at-save 'safe-local-variable 'booleanp)
+(put 'less-css-compile-at-save 'safe-local-variable #'booleanp)
 
 (put 'less-css-lessc-options 'safe-local-variable t)
 
-(put 'less-css-output-directory 'safe-local-variable 'stringp)
+(put 'less-css-output-directory 'safe-local-variable #'stringp)
 
-(put 'less-css-input-file-name 'safe-local-variable 'stringp)
+(put 'less-css-input-file-name 'safe-local-variable #'stringp)
  (add-to-list 'auto-mode-alist '("\\.less\\'" . less-css-mode))
 
 (autoload 'less-css-mode "less-css-mode" "\
@@ -20535,7 +20546,7 @@ Default bookmark handler for Man buffers.
 
 ;;;### (autoloads nil "map" "emacs-lisp/map.el" (0 0 0 0))
 ;;; Generated autoloads from emacs-lisp/map.el
-(push (purecopy '(map 2 1)) package--builtin-versions)
+(push (purecopy '(map 3 0)) package--builtin-versions)
 
 (register-definition-prefixes "map" '("map-"))
 
@@ -22087,6 +22098,32 @@ QUALITY can be:
 ;;;### (autoloads nil "mwheel" "mwheel.el" (0 0 0 0))
 ;;; Generated autoloads from mwheel.el
 
+(defcustom mouse-wheel-mode t "\
+Non-nil if Mouse-Wheel mode is enabled.
+See the `mouse-wheel-mode' command
+for a description of this minor mode.
+Setting this variable directly does not take effect;
+either customize it (see the info node `Easy Customization')
+or call the function `mouse-wheel-mode'." :set #'custom-set-minor-mode 
:initialize 'custom-initialize-delay :group 'mouse :type 'boolean)
+
+(custom-autoload 'mouse-wheel-mode "mwheel" nil)
+
+(autoload 'mouse-wheel-mode "mwheel" "\
+Toggle mouse wheel support (Mouse Wheel mode).
+
+If called interactively, toggle `Mouse-Wheel mode'.  If the prefix
+argument is positive, enable the mode, and if it is zero or negative,
+disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'.  Enable the
+mode if ARG is nil, omitted, or is a positive number.  Disable the
+mode if ARG is a negative number.
+
+The mode's hook is called both when the mode is enabled and when it is
+disabled.
+
+\(fn &optional ARG)" t nil)
+
 (register-definition-prefixes "mwheel" '("mouse-wheel-" "mwheel-"))
 
 ;;;***
@@ -22347,7 +22384,7 @@ gnutls-boot (as returned by `gnutls-boot-parameters').
 
 \(fn NAME BUFFER HOST SERVICE &rest PARAMETERS)" nil nil)
 
-(defalias 'open-protocol-stream 'open-network-stream)
+(define-obsolete-function-alias 'open-protocol-stream #'open-network-stream 
"26.1")
 
 (register-definition-prefixes "network-stream" '("network-stream-"))
 
@@ -24041,6 +24078,8 @@ Turning on outline mode calls the value of 
`text-mode-hook' and then of
 `outline-mode-hook', if they are non-nil.
 
 \(fn)" t nil)
+(put 'outline-minor-mode-cycle 'safe-local-variable 'booleanp)
+(put 'outline-minor-mode-highlight 'safe-local-variable 'booleanp)
 
 (autoload 'outline-minor-mode "outline" "\
 Toggle Outline minor mode.
@@ -24186,7 +24225,11 @@ directory.
 
 (autoload 'package-install-selected-packages "package" "\
 Ensure packages in `package-selected-packages' are installed.
-If some packages are not installed propose to install them." t nil)
+If some packages are not installed, propose to install them.
+If optional argument NOCONFIRM is non-nil, don't ask for
+confirmation to install packages.
+
+\(fn &optional NOCONFIRM)" t nil)
 
 (autoload 'package-reinstall "package" "\
 Reinstall package PKG.
@@ -25898,6 +25941,13 @@ Save the result in `project-list-file' if the list of 
projects has changed.
 
 \(fn PR)" nil nil)
 
+(autoload 'project-remove-known-project "project" "\
+Remove directory PROJECT-ROOT from the project list.
+PROJECT-ROOT is the root directory of a known project listed in
+the project list.
+
+\(fn PROJECT-ROOT)" t nil)
+
 (autoload 'project-known-project-roots "project" "\
 Return the list of root directories of all known projects." nil nil)
 
@@ -25906,19 +25956,6 @@ Execute an extended command in project root." t nil)
 
 (function-put 'project-execute-extended-command 'interactive-only 
'command-execute)
 
-(defvar project-switch-commands '((project-find-file "Find file") 
(project-find-regexp "Find regexp") (project-dired "Dired") (project-vc-dir 
"VC-Dir") (project-eshell "Eshell")) "\
-Alist mapping commands to descriptions.
-Used by `project-switch-project' to construct a dispatch menu of
-commands available upon \"switching\" to another project.
-
-Each element is of the form (COMMAND LABEL &optional KEY) where
-COMMAND is the command to run when KEY is pressed.  LABEL is used
-to distinguish the menu entries in the dispatch menu.  If KEY is
-absent, COMMAND must be bound in `project-prefix-map', and the
-key is looked up in that map.")
-
-(custom-autoload 'project-switch-commands "project" t)
-
 (autoload 'project-switch-project "project" "\
 \"Switch\" to another project by running an Emacs command.
 The available commands are presented as a dispatch menu
@@ -26495,7 +26532,7 @@ Add one translation rule, KEY to TRANSLATION, in the 
current Quail package.
 KEY is a string meaning a sequence of keystrokes to be translated.
 TRANSLATION is a character, a string, a vector, a Quail map,
  a function, or a cons.
-It it is a character, it is the sole translation of KEY.
+If it is a character, it is the sole translation of KEY.
 If it is a string, each character is a candidate for the translation.
 If it is a vector, each element (string or character) is a candidate
  for the translation.
@@ -28351,24 +28388,7 @@ For more details, see Info node `(elisp) Extending Rx'.
 
 (function-put 'rx-define 'lisp-indent-function 'defun)
 
-(autoload 'rx--pcase-macroexpander "rx" "\
-A pattern that matches strings against `rx' REGEXPS in sexp form.
-REGEXPS are interpreted as in `rx'.  The pattern matches any
-string that is a match for REGEXPS, as if by `string-match'.
-
-In addition to the usual `rx' syntax, REGEXPS can contain the
-following constructs:
-
-  (let REF RX...)  binds the symbol REF to a submatch that matches
-                   the regular expressions RX.  REF is bound in
-                   CODE to the string of the submatch or nil, but
-                   can also be used in `backref'.
-  (backref REF)    matches whatever the submatch REF matched.
-                   REF can be a number, as usual, or a name
-                   introduced by a previous (let REF ...)
-                   construct.
-
-\(fn &rest REGEXPS)" nil nil)
+(eval-and-compile (defun rx--pcase-macroexpander (&rest regexps) "A pattern 
that matches strings against `rx' REGEXPS in sexp form.\nREGEXPS are 
interpreted as in `rx'.  The pattern matches any\nstring that is a match for 
REGEXPS, as if by `string-match'.\n\nIn addition to the usual `rx' syntax, 
REGEXPS can contain the\nfollowing constructs:\n\n  (let REF RX...)  binds the 
symbol REF to a submatch that matches\n                   the regular 
expressions RX.  REF is bound in\n             [...]
 
 (define-symbol-prop 'rx--pcase-macroexpander 'edebug-form-spec 'nil)
 
@@ -28863,14 +28883,6 @@ Major mode for editing Bovine grammars.
 
 ;;;***
 
-;;;### (autoloads nil "semantic/grammar-wy" "cedet/semantic/grammar-wy.el"
-;;;;;;  (0 0 0 0))
-;;; Generated autoloads from cedet/semantic/grammar-wy.el
-
-(register-definition-prefixes "semantic/grammar-wy" '("semantic-grammar-wy--"))
-
-;;;***
-
 ;;;### (autoloads nil "semantic/java" "cedet/semantic/java.el" (0
 ;;;;;;  0 0 0))
 ;;; Generated autoloads from cedet/semantic/java.el
@@ -29500,7 +29512,7 @@ or Edit/Text Properties/Face commands.
 Pages can have <a name=\"SOMENAME\">named points</a> and can link other points
 to them with <a href=\"#SOMENAME\">see also somename</a>.  In the same way <a
 href=\"URL\">see also URL</a> where URL is a filename relative to current
-directory, or absolute as in `http://www.cs.indiana.edu/elisp/w3/docs.html'.
+directory, or absolute as in `https://www.cs.indiana.edu/elisp/w3/docs.html'.
 
 Images in many formats can be inlined with <img src=\"URL\">.
 
@@ -31249,7 +31261,7 @@ Major-mode for writing SRecode macros.
 
 \(fn)" t nil)
 
-(defalias 'srt-mode 'srecode-template-mode)
+(defalias 'srt-mode #'srecode-template-mode)
 
 (register-definition-prefixes "srecode/srt-mode" '("semantic-" "srecode-"))
 
@@ -31811,7 +31823,7 @@ Move the point under the table as shown below.
     +--------------+------+--------------------------------+
     -!-
 
-Type M-x table-insert-row instead of \\[table-insert-row-column].  
\\[table-insert-row-column] does not work
+Type \\[table-insert-row] instead of \\[table-insert-row-column].  
\\[table-insert-row-column] does not work
 when the point is outside of the table.  This insertion at
 outside of the table effectively appends a row at the end.
 
@@ -32108,11 +32120,11 @@ HTML:
         URL `https://www.w3.org'
 
 LaTeX:
-        URL `http://www.maths.tcd.ie/~dwilkins/LaTeXPrimer/Tables.html'
+        URL `https://www.maths.tcd.ie/~dwilkins/LaTeXPrimer/Tables.html'
 
 CALS (DocBook DTD):
-        URL `http://www.oasis-open.org/html/a502.htm'
-        URL 
`http://www.oreilly.com/catalog/docbook/chapter/book/table.html#AEN114751'
+        URL `https://www.oasis-open.org/html/a502.htm'
+        URL 
`https://www.oreilly.com/catalog/docbook/chapter/book/table.html#AEN114751'
 
 \(fn LANGUAGE &optional DEST-BUFFER CAPTION)" t nil)
 
@@ -32320,12 +32332,12 @@ Connect to the Emacs talk group from the current X 
display or tty frame." t nil)
 (autoload 'tar-mode "tar-mode" "\
 Major mode for viewing a tar file as a dired-like listing of its contents.
 You can move around using the usual cursor motion commands.
-Letters no longer insert themselves.
-Type `e' to pull a file out of the tar file and into its own buffer;
+Letters no longer insert themselves.\\<tar-mode-map>
+Type \\[tar-extract] to pull a file out of the tar file and into its own 
buffer;
 or click mouse-2 on the file's line in the Tar mode buffer.
-Type `c' to copy an entry from the tar file into another file on disk.
+Type \\[tar-copy] to copy an entry from the tar file into another file on disk.
 
-If you edit a sub-file of this archive (as with the `e' command) and
+If you edit a sub-file of this archive (as with the \\[tar-extract] command) 
and
 save it with \\[save-buffer], the contents of that buffer will be
 saved back into the tar-file buffer; in this way you can edit a file
 inside of a tar archive without extracting it and re-archiving it.
@@ -32679,11 +32691,11 @@ says which mode to use.
 
 \(fn)" t nil)
 
-(defalias 'TeX-mode 'tex-mode)
+(defalias 'TeX-mode #'tex-mode)
 
-(defalias 'plain-TeX-mode 'plain-tex-mode)
+(defalias 'plain-TeX-mode #'plain-tex-mode)
 
-(defalias 'LaTeX-mode 'latex-mode)
+(defalias 'LaTeX-mode #'latex-mode)
 
 (autoload 'plain-tex-mode "tex-mode" "\
 Major mode for editing files of input for plain TeX.
@@ -33339,7 +33351,11 @@ point.
 \(fn &optional FORMAT HERE)" t nil)
 
 (autoload 'emacs-init-time "time" "\
-Return a string giving the duration of the Emacs initialization." t nil)
+Return a string giving the duration of the Emacs initialization.
+FORMAT is a string to format the result, using `format'. If nil,
+the default format \"%f seconds\" is used.
+
+\(fn &optional FORMAT)" t nil)
 
 (register-definition-prefixes "time" '("display-time-" 
"legacy-style-world-list" "time--display-world-list" "world-clock-" 
"zoneinfo-style-world-list"))
 
@@ -34025,6 +34041,13 @@ Add archive file name handler to 
`file-name-handler-alist'." (when tramp-archive
 
 ;;;***
 
+;;;### (autoloads nil "tramp-fuse" "net/tramp-fuse.el" (0 0 0 0))
+;;; Generated autoloads from net/tramp-fuse.el
+
+(register-definition-prefixes "tramp-fuse" '("tramp-fuse-"))
+
+;;;***
+
 ;;;### (autoloads nil "tramp-gvfs" "net/tramp-gvfs.el" (0 0 0 0))
 ;;; Generated autoloads from net/tramp-gvfs.el
 
@@ -34062,6 +34085,13 @@ Add archive file name handler to 
`file-name-handler-alist'." (when tramp-archive
 
 ;;;***
 
+;;;### (autoloads nil "tramp-sshfs" "net/tramp-sshfs.el" (0 0 0 0))
+;;; Generated autoloads from net/tramp-sshfs.el
+
+(register-definition-prefixes "tramp-sshfs" '("tramp-sshfs-"))
+
+;;;***
+
 ;;;### (autoloads nil "tramp-sudoedit" "net/tramp-sudoedit.el" (0
 ;;;;;;  0 0 0))
 ;;; Generated autoloads from net/tramp-sudoedit.el
@@ -34134,8 +34164,8 @@ resumed later.
 ;;;;;;  0 0))
 ;;; Generated autoloads from textmodes/two-column.el
  (autoload '2C-command "two-column" () t 'keymap)
- (global-set-key "\C-x6" '2C-command)
- (global-set-key [f2] '2C-command)
+ (global-set-key "\C-x6" #'2C-command)
+ (global-set-key [f2] #'2C-command)
 
 (autoload '2C-two-columns "two-column" "\
 Split current window vertically for two-column editing.
@@ -35240,7 +35270,12 @@ The buffer in question is current when this function 
is called.
 
 \(fn FILENAME)" nil nil)
 
-(register-definition-prefixes "userlock" '("ask-user-about-" "file-" 
"userlock--check-content-unchanged"))
+(autoload 'userlock--handle-unlock-error "userlock" "\
+Report an ERROR that occurred while unlocking a file.
+
+\(fn ERROR)" nil nil)
+
+(register-definition-prefixes "userlock" '("ask-user-about-" "file-" 
"userlock--"))
 
 ;;;***
 
@@ -36007,7 +36042,7 @@ Add a description of the problem and include a 
reproducible test case.
 Feel free to send questions and enhancement requests to <reto@gnu.org>.
 
 Official distribution is at
-URL `http://www.iis.ee.ethz.ch/~zimmi/emacs/vera-mode.html'
+URL `https://www.iis.ee.ethz.ch/~zimmi/emacs/vera-mode.html'
 
 
                                                   The Vera Mode Maintainer
@@ -36027,7 +36062,7 @@ Key bindings:
 ;;;### (autoloads nil "verilog-mode" "progmodes/verilog-mode.el"
 ;;;;;;  (0 0 0 0))
 ;;; Generated autoloads from progmodes/verilog-mode.el
-(push (purecopy '(verilog-mode 2021 2 2 263931197)) package--builtin-versions)
+(push (purecopy '(verilog-mode 2021 3 30 243771231)) package--builtin-versions)
 
 (autoload 'verilog-mode "verilog-mode" "\
 Major mode for editing Verilog code.
@@ -36782,7 +36817,7 @@ Don't change this variable directly, you must change it 
by one of the
 functions that enable or disable view mode.")
 
 (autoload 'kill-buffer-if-not-modified "view" "\
-Like `kill-buffer', but does nothing if the buffer is modified.
+Like `kill-buffer', but does nothing if buffer BUF is modified.
 
 \(fn BUF)" nil nil)
 
@@ -36848,7 +36883,7 @@ file: Users may suspend viewing in order to modify the 
buffer.
 Exiting View mode will then discard the user's edits.  Setting
 EXIT-ACTION to `kill-buffer-if-not-modified' avoids this.
 
-This function does not enable View mode if the buffer's major-mode
+This function does not enable View mode if the buffer's major mode
 has a `special' mode-class, because such modes usually have their
 own View-like bindings.
 
@@ -36870,7 +36905,7 @@ Optional argument EXIT-ACTION is either nil or a 
function with buffer as
 argument.  This function is called when finished viewing buffer.  Use
 this argument instead of explicitly setting `view-exit-action'.
 
-This function does not enable View mode if the buffer's major-mode
+This function does not enable View mode if the buffer's major mode
 has a `special' mode-class, because such modes usually have their
 own View-like bindings.
 
@@ -36892,7 +36927,7 @@ Optional argument EXIT-ACTION is either nil or a 
function with buffer as
 argument.  This function is called when finished viewing buffer.  Use
 this argument instead of explicitly setting `view-exit-action'.
 
-This function does not enable View mode if the buffer's major-mode
+This function does not enable View mode if the buffer's major mode
 has a `special' mode-class, because such modes usually have their
 own View-like bindings.
 
@@ -38341,15 +38376,15 @@ Zone out, completely." t nil)
 ;;;;;;  "cedet/semantic/db-typecache.el" "cedet/semantic/db.el" 
"cedet/semantic/debug.el"
 ;;;;;;  "cedet/semantic/decorate/include.el" "cedet/semantic/decorate/mode.el"
 ;;;;;;  "cedet/semantic/dep.el" "cedet/semantic/doc.el" 
"cedet/semantic/edit.el"
-;;;;;;  "cedet/semantic/find.el" "cedet/semantic/format.el" 
"cedet/semantic/html.el"
-;;;;;;  "cedet/semantic/ia-sb.el" "cedet/semantic/ia.el" 
"cedet/semantic/idle.el"
-;;;;;;  "cedet/semantic/imenu.el" "cedet/semantic/lex-spp.el" 
"cedet/semantic/lex.el"
-;;;;;;  "cedet/semantic/mru-bookmark.el" "cedet/semantic/scope.el"
-;;;;;;  "cedet/semantic/senator.el" "cedet/semantic/sort.el" 
"cedet/semantic/symref.el"
-;;;;;;  "cedet/semantic/symref/cscope.el" "cedet/semantic/symref/global.el"
-;;;;;;  "cedet/semantic/symref/grep.el" "cedet/semantic/symref/idutils.el"
-;;;;;;  "cedet/semantic/symref/list.el" "cedet/semantic/tag-file.el"
-;;;;;;  "cedet/semantic/tag-ls.el" "cedet/semantic/tag-write.el"
+;;;;;;  "cedet/semantic/find.el" "cedet/semantic/format.el" 
"cedet/semantic/grammar-wy.el"
+;;;;;;  "cedet/semantic/html.el" "cedet/semantic/ia-sb.el" 
"cedet/semantic/ia.el"
+;;;;;;  "cedet/semantic/idle.el" "cedet/semantic/imenu.el" 
"cedet/semantic/lex-spp.el"
+;;;;;;  "cedet/semantic/lex.el" "cedet/semantic/mru-bookmark.el"
+;;;;;;  "cedet/semantic/scope.el" "cedet/semantic/senator.el" 
"cedet/semantic/sort.el"
+;;;;;;  "cedet/semantic/symref.el" "cedet/semantic/symref/cscope.el"
+;;;;;;  "cedet/semantic/symref/global.el" "cedet/semantic/symref/grep.el"
+;;;;;;  "cedet/semantic/symref/idutils.el" "cedet/semantic/symref/list.el"
+;;;;;;  "cedet/semantic/tag-file.el" "cedet/semantic/tag-ls.el" 
"cedet/semantic/tag-write.el"
 ;;;;;;  "cedet/semantic/tag.el" "cedet/semantic/texi.el" 
"cedet/semantic/util-modes.el"
 ;;;;;;  "cedet/semantic/wisent/java-tags.el" 
"cedet/semantic/wisent/javascript.el"
 ;;;;;;  "cedet/semantic/wisent/javat-wy.el" "cedet/semantic/wisent/js-wy.el"
@@ -38381,7 +38416,7 @@ Zone out, completely." t nil)
 ;;;;;;  "eshell/em-ls.el" "eshell/em-pred.el" "eshell/em-prompt.el"
 ;;;;;;  "eshell/em-rebind.el" "eshell/em-script.el" "eshell/em-smart.el"
 ;;;;;;  "eshell/em-term.el" "eshell/em-tramp.el" "eshell/em-unix.el"
-;;;;;;  "eshell/em-xtra.el" "facemenu.el" "faces.el" "files.el" "font-core.el"
+;;;;;;  "eshell/em-xtra.el" "faces.el" "files.el" "font-core.el"
 ;;;;;;  "font-lock.el" "format.el" "frame.el" "help.el" "hfy-cmap.el"
 ;;;;;;  "ibuf-ext.el" "indent.el" "international/characters.el" 
"international/charprop.el"
 ;;;;;;  "international/charscript.el" "international/cp51932.el"
diff --git a/lisp/leim/quail/ipa-praat.el b/lisp/leim/quail/ipa-praat.el
index 0920bc7..1a95395 100644
--- a/lisp/leim/quail/ipa-praat.el
+++ b/lisp/leim/quail/ipa-praat.el
@@ -35,7 +35,7 @@
  "ipa-praat" "IPA" "IPAP" t
  "International Phonetic Alphabet input method.
 This follows the input method of the phonetic analysis program
-Praat (http://www.fon.hum.uva.nl/praat/).
+Praat (https://www.fon.hum.uva.nl/praat/).
 
 
 * Vowels
diff --git a/lisp/leim/quail/ipa.el b/lisp/leim/quail/ipa.el
index e805c6a..c256875 100644
--- a/lisp/leim/quail/ipa.el
+++ b/lisp/leim/quail/ipa.el
@@ -336,12 +336,12 @@ exchange in environments where Unicode is not available.  
This input method
 uses this transliteration to allow you to produce the IPA in your editor
 with a keyboard that's limited to ASCII.
 
-See http://www.phon.ucl.ac.uk/home/sampa/ipasam-x.pdf for a full definition
+See https://www.phon.ucl.ac.uk/home/sampa/ipasam-x.pdf for a full definition
 of the mapping.")
 
 (quail-define-rules
  ;; Table taken from https://en.wikipedia.org/wiki/X-SAMPA, checked with
- ;; http://www.phon.ucl.ac.uk/home/sampa/ipasam-x.pdf
+ ;; https://www.phon.ucl.ac.uk/home/sampa/ipasam-x.pdf
 
  ("d`" "ɖ")    ;; Voiced retroflex plosive             U+0256
  ("g" "ɡ")     ;; Voiced velar plosive                 U+0261
diff --git a/lisp/leim/quail/latin-post.el b/lisp/leim/quail/latin-post.el
index 8e21ed8..1040877 100644
--- a/lisp/leim/quail/latin-post.el
+++ b/lisp/leim/quail/latin-post.el
@@ -744,7 +744,7 @@ Doubling the postfix separates the letter and postfix: e.g. 
a\\='\\=' -> a\\='
 ;;; correctly on most displays.
 
 ;;; This reference is an authoritative guide to Hawaiian orthography:
-;;; http://www2.hawaii.edu/~strauch/tips/HawaiianOrthography.html
+;;; https://www2.hawaii.edu/~strauch/tips/HawaiianOrthography.html
 
 ;;; Initial coding 2018-09-08 Bob Newell, Honolulu, Hawaiʻi
 ;;; Comments to bobnewell@bobnewell.net
diff --git a/lisp/leim/quail/latin-pre.el b/lisp/leim/quail/latin-pre.el
index 2200654..b8b0fab 100644
--- a/lisp/leim/quail/latin-pre.el
+++ b/lisp/leim/quail/latin-pre.el
@@ -1294,7 +1294,7 @@ of characters from a single Latin-N charset.
 ;;; correctly on most displays.
 
 ;;; This reference is an authoritative guide to Hawaiian orthography:
-;;; http://www2.hawaii.edu/~strauch/tips/HawaiianOrthography.html
+;;; https://www2.hawaii.edu/~strauch/tips/HawaiianOrthography.html
 
 ;;; Initial coding 2018-09-08 Bob Newell, Honolulu, Hawaiʻi
 ;;; Comments to bobnewell@bobnewell.net
diff --git a/lisp/leim/quail/programmer-dvorak.el 
b/lisp/leim/quail/programmer-dvorak.el
index 49f9d82..9e1e23c 100644
--- a/lisp/leim/quail/programmer-dvorak.el
+++ b/lisp/leim/quail/programmer-dvorak.el
@@ -24,7 +24,7 @@
 ;;; Commentary:
 
 ;;; This file provides an input method for the programmers Dvorak keyboard
-;;; layout by Roland Kaufman (<http://www.kaufmann.no/roland/dvorak/>).
+;;; layout by Roland Kaufman (<https://www.kaufmann.no/roland/dvorak/>).
 
 ;;; Code:
 
diff --git a/lisp/linum.el b/lisp/linum.el
index f9761d2..b0281d3 100644
--- a/lisp/linum.el
+++ b/lisp/linum.el
@@ -31,9 +31,6 @@
 
 ;;; Code:
 
-(defconst linum-version "0.9x")
-(make-obsolete-variable 'linum-version nil "28.1")
-
 (defvar-local linum-overlays nil "Overlays used in this buffer.")
 (defvar-local linum-available nil "Overlays available for reuse.")
 (defvar linum-before-numbering-hook nil
@@ -244,6 +241,9 @@ Linum mode is a buffer-local minor mode."
   ;; continue standard unloading
   nil)
 
+(defconst linum-version "0.9x")
+(make-obsolete-variable 'linum-version 'emacs-version "28.1")
+
 (provide 'linum)
 
 ;;; linum.el ends here
diff --git a/lisp/loadhist.el b/lisp/loadhist.el
index a60d6b2..59c002d 100644
--- a/lisp/loadhist.el
+++ b/lisp/loadhist.el
@@ -82,12 +82,6 @@ A library name is equivalent to the file name that 
`load-library' would load."
       (when (eq (car-safe x) 'require)
        (push (cdr x) requires)))))
 
-(defsubst file-set-intersect (p q)
-  "Return the set intersection of two lists."
-  (let (ret)
-    (dolist (x p ret)
-      (when (memq x q) (push x ret)))))
-
 (defun file-dependents (file)
   "Return the list of loaded libraries that depend on FILE.
 This can include FILE itself.
@@ -97,7 +91,7 @@ A library name is equivalent to the file name that 
`load-library' would load."
        (dependents nil))
     (dolist (x load-history dependents)
       (when (and (stringp (car x))
-                 (file-set-intersect provides (file-requires (car x))))
+                 (seq-intersection provides (file-requires (car x)) #'eq))
        (push (car x) dependents)))))
 
 (defun read-feature (prompt &optional loaded-p)
@@ -322,6 +316,13 @@ something strange, such as redefining an Emacs function."
   ;; Don't return load-history, it is not useful.
   nil)
 
+;; Obsolete.
+
+(defsubst file-set-intersect (p q)
+  "Return the set intersection of two lists."
+  (declare (obsolete seq-intersection "28.1"))
+  (nreverse (seq-intersection p q #'eq)))
+
 (provide 'loadhist)
 
 ;;; loadhist.el ends here
diff --git a/lisp/lpr.el b/lisp/lpr.el
index 012d251..29a0fd8 100644
--- a/lisp/lpr.el
+++ b/lisp/lpr.el
@@ -1,4 +1,4 @@
-;;; lpr.el --- print Emacs buffer on line printer
+;;; lpr.el --- print Emacs buffer on line printer  -*- lexical-binding: t -*-
 
 ;; Copyright (C) 1985, 1988, 1992, 1994, 2001-2021 Free Software
 ;; Foundation, Inc.
@@ -39,12 +39,10 @@
   (memq system-type '(usg-unix-v hpux))
   "Non-nil if running on a system type that uses the \"lp\" command.")
 
-
 (defgroup lpr nil
   "Print Emacs buffer on line printer."
   :group 'text)
 
-
 ;;;###autoload
 (defcustom printer-name
   (and (eq system-type 'ms-dos) "PRN")
@@ -65,8 +63,7 @@ file.  If you want to discard the printed output, set this to 
\"NUL\"."
                 :tag "Printer Name"
                 (const :tag "Default" nil)
                 ;; could use string but then we lose completion for files.
-                (file :tag "Name"))
-  :group 'lpr)
+                 (file :tag "Name")))
 
 ;;;###autoload
 (defcustom lpr-switches nil
@@ -74,16 +71,14 @@ file.  If you want to discard the printed output, set this 
to \"NUL\"."
 It is recommended to set `printer-name' instead of including an explicit
 switch on this list.
 See `lpr-command'."
-  :type '(repeat (string :tag "Argument"))
-  :group 'lpr)
+  :type '(repeat (string :tag "Argument")))
 
 (defcustom lpr-add-switches (memq system-type '(berkeley-unix gnu/linux))
   "Non-nil means construct `-T' and `-J' options for the printer program.
 These are made assuming that the program is `lpr';
 if you are using some other incompatible printer program,
 this variable should be nil."
-  :type 'boolean
-  :group 'lpr)
+  :type 'boolean)
 
 (defcustom lpr-printer-switch
   (if lpr-lp-system
@@ -94,8 +89,7 @@ This switch is used in conjunction with `printer-name'."
   :type '(choice :menu-tag "Printer Name Switch"
                 :tag "Printer Name Switch"
                 (const :tag "None" nil)
-                (string :tag "Printer Switch"))
-  :group 'lpr)
+                 (string :tag "Printer Switch")))
 
 ;;;###autoload
 (defcustom lpr-command
@@ -116,8 +110,7 @@ Windows NT and Novell Netware respectively) are handled 
specially, using
 `printer-name' as the destination for output; any other program is
 treated like `lpr' except that an explicit filename is given as the last
 argument."
-  :type 'string
-  :group 'lpr)
+  :type 'string)
 
 ;; Default is nil, because that enables us to use pr -f
 ;; which is more reliable than pr with no args, which is what lpr -p does.
@@ -127,22 +120,21 @@ If nil, we run `lpr-page-header-program' to make page 
headings
 and print the result."
   :type '(choice (const nil)
                 (string :tag "Single argument")
-                (repeat :tag "Multiple arguments" (string :tag "Argument")))
-  :group 'lpr)
+                 (repeat :tag "Multiple arguments" (string :tag "Argument"))))
 
 (defcustom print-region-function
   (if (memq system-type '(ms-dos windows-nt))
-      #'w32-direct-print-region-function
+      (progn
+        (declare-function w32-direct-print-region-function "w32-fns")
+        #'w32-direct-print-region-function)
     #'call-process-region)
   "Function to call to print the region on a printer.
 See definition of `print-region-1' for calling conventions."
-  :type 'function
-  :group 'lpr)
+  :type 'function)
 
 (defcustom lpr-page-header-program "pr"
   "Name of program for adding page headers to a file."
-  :type 'string
-  :group 'lpr)
+  :type 'string)
 
 ;; Berkeley systems support -F, and GNU pr supports both -f and -F,
 ;; So it looks like -F is a better default.
@@ -151,8 +143,7 @@ See definition of `print-region-1' for calling conventions."
 If `%s' appears in any of the strings, it is substituted by the page title.
 Note that for correct quoting, `%s' should normally be a separate element.
 The variable `lpr-page-header-program' specifies the program to use."
-  :type '(repeat string)
-  :group 'lpr)
+  :type '(repeat string))
 
 ;;;###autoload
 (defun lpr-buffer ()
@@ -248,7 +239,7 @@ for further customization of the printer command."
              nil
            ;; Run a separate program to get page headers.
            (let ((new-coords (print-region-new-buffer start end)))
-             (apply 'call-process-region (car new-coords) (cdr new-coords)
+              (apply #'call-process-region (car new-coords) (cdr new-coords)
                     lpr-page-header-program t t nil
                     (mapcar (lambda (e) (format e name))
                             lpr-page-header-switches)))
@@ -270,7 +261,7 @@ for further customization of the printer command."
       (let ((retval
              (let ((tempbuf (current-buffer)))
                (with-current-buffer buf
-                 (apply (or print-region-function 'call-process-region)
+                 (apply (or print-region-function #'call-process-region)
                         start end lpr-command
                         nil tempbuf nil
                         (nconc (and name lpr-add-switches
diff --git a/lisp/mail/feedmail.el b/lisp/mail/feedmail.el
index d76017b..cec5736 100644
--- a/lisp/mail/feedmail.el
+++ b/lisp/mail/feedmail.el
@@ -163,7 +163,7 @@
 ;;     (autoload 'feedmail-buffer-to-smtpmail "feedmail" nil t)
 ;;     (setq feedmail-buffer-eating-function 'feedmail-buffer-to-smtpmail)
 ;;
-;; Alternatively, the FLIM <http://www.m17n.org/FLIM/> project
+;; Alternatively, the FLIM <https://www.m17n.org/FLIM/> project
 ;; provides a library called smtp.el.  If you want to use that, the above lines
 ;; would be:
 ;;
diff --git a/lisp/mail/mail-extr.el b/lisp/mail/mail-extr.el
index 7fbdfef..88fb086 100644
--- a/lisp/mail/mail-extr.el
+++ b/lisp/mail/mail-extr.el
@@ -2236,13 +2236,13 @@ place.  It affects how 
`mail-extract-address-components' works."
 
 
 ;(let ((all nil))
-;  (mapatoms #'(lambda (x)
+;  (mapatoms (lambda (x)
 ;              (if (and (boundp x)
 ;                       (string-match "^mail-extr-" (symbol-name x)))
 ;                  (setq all (cons x all)))))
 ;  (setq all (sort all #'string-lessp))
 ;  (cons 'setq
-;      (apply 'nconc (mapcar #'(lambda (x)
+;      (apply 'nconc (mapcar (lambda (x)
 ;                                (list x (symbol-value x)))
 ;                            all))))
 
diff --git a/lisp/mail/rmail.el b/lisp/mail/rmail.el
index c7960f8..455ae7f 100644
--- a/lisp/mail/rmail.el
+++ b/lisp/mail/rmail.el
@@ -3671,9 +3671,9 @@ If BUFFER is not swapped, yank out of its message viewer 
buffer."
     (push (cons "cc" cc) other-headers)
     (push (cons "in-reply-to" in-reply-to) other-headers)
     (setq other-headers
-         (mapcar #'(lambda (elt)
-                     (cons (car elt) (if (stringp (cdr elt))
-                                         (rfc2047-decode-string (cdr elt)))))
+          (mapcar (lambda (elt)
+                    (cons (car elt) (if (stringp (cdr elt))
+                                        (rfc2047-decode-string (cdr elt)))))
                  other-headers))
     (if (stringp to) (setq to (rfc2047-decode-string to)))
     (if (stringp in-reply-to)
diff --git a/lisp/mail/smtpmail.el b/lisp/mail/smtpmail.el
index ac5e8c3..ab58aa4 100644
--- a/lisp/mail/smtpmail.el
+++ b/lisp/mail/smtpmail.el
@@ -489,13 +489,6 @@ for `smtpmail-try-auth-method'.")
       recipient
     (concat recipient "@" smtpmail-sendto-domain)))
 
-(defun smtpmail-intersection (list1 list2)
-  (let ((result nil))
-    (dolist (el2 list2)
-      (when (memq el2 list1)
-       (push el2 result)))
-    (nreverse result)))
-
 (defun smtpmail-command-or-throw (process string &optional code)
   (let (ret)
     (smtpmail-send-command process string)
@@ -512,9 +505,10 @@ for `smtpmail-try-auth-method'.")
        (if port
            (format "%s" port)
          "smtp"))
-  (let* ((mechs (smtpmail-intersection
+  (let* ((mechs (seq-intersection
+                 smtpmail-auth-supported
                  (cdr-safe (assoc 'auth supported-extensions))
-                 smtpmail-auth-supported))
+                 #'eq))
         (auth-source-creation-prompts
           '((user  . "SMTP user name for %h: ")
             (secret . "SMTP password for %u@%h: ")))
@@ -1087,6 +1081,12 @@ many continuation lines."
        (while (and (looking-at "^[ \t].*\n") (< (point) header-end))
          (replace-match ""))))))
 
+;; Obsolete.
+
+(defun smtpmail-intersection (list1 list2)
+  (declare (obsolete seq-intersection "28.1"))
+  (seq-intersection list2 list1 #'eq))
+
 (provide 'smtpmail)
 
 ;;; smtpmail.el ends here
diff --git a/lisp/man.el b/lisp/man.el
index abb9bba..9b941a2 100644
--- a/lisp/man.el
+++ b/lisp/man.el
@@ -1503,7 +1503,9 @@ manpage command."
               (quit-restore-window
                (get-buffer-window Man-buffer t) 'kill)
               ;; Ensure that we end up in the correct window.
-              (select-window (old-selected-window)))
+              (let ((old-window (old-selected-window)))
+                (when (window-live-p old-window)
+                  (select-window old-window))))
           (kill-buffer Man-buffer)))
 
       (when message
diff --git a/lisp/master.el b/lisp/master.el
index 796f218..3dcee50 100644
--- a/lisp/master.el
+++ b/lisp/master.el
@@ -1,4 +1,4 @@
-;;; master.el --- make a buffer the master over another buffer
+;;; master.el --- make a buffer the master over another buffer  -*- 
lexical-binding: t -*-
 
 ;; Copyright (C) 1999-2021 Free Software Foundation, Inc.
 
@@ -23,7 +23,7 @@
 
 ;;; Commentary:
 
-;; master-mode is a minor mode which enables you to scroll another
+;; `master-mode' is a minor mode which enables you to scroll another
 ;; buffer (the slave) without leaving your current buffer (the master).
 
 ;; It can be used by sql.el, for example: The SQL buffer is the master
@@ -47,17 +47,8 @@
 ;;
 ;; Rob Riepel <networking.stanford.edu>
 
-;;; History:
-;;
-
 ;;; Code:
 
-;; Unused.
-;;; (defgroup master nil
-;;;   "Support for master/slave relationships between buffers."
-;;;   :version "22.1"
-;;;   :group 'convenience)
-
 ;; Variables that don't need initialization.
 
 (defvar master-of nil
@@ -93,7 +84,7 @@ yourself the value of `master-of' by calling 
`master-show-slave'."
 ;; Initialize Master mode by setting a slave buffer.
 
 (defun master-set-slave (buffer)
-  "Makes BUFFER the slave of the current buffer.
+  "Make BUFFER the slave of the current buffer.
 Use \\[master-mode] to toggle control of the slave buffer."
   (interactive "bSlave: ")
   (setq-local master-of buffer)
diff --git a/lisp/mh-e/mh-alias.el b/lisp/mh-e/mh-alias.el
index 012725c..67c019a 100644
--- a/lisp/mh-e/mh-alias.el
+++ b/lisp/mh-e/mh-alias.el
@@ -1,4 +1,4 @@
-;;; mh-alias.el --- MH-E mail alias completion and expansion
+;;; mh-alias.el --- MH-E mail alias completion and expansion  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1994-1997, 2001-2021 Free Software Foundation, Inc.
 
@@ -42,8 +42,8 @@
   "Time aliases were last loaded.")
 (defvar mh-alias-read-address-map
   (let ((map (copy-keymap minibuffer-local-completion-map)))
-    (define-key map "," 'mh-alias-minibuffer-confirm-address)
-    (define-key map " " 'self-insert-command)
+    (define-key map "," #'mh-alias-minibuffer-confirm-address)
+    (define-key map " " #'self-insert-command)
     map))
 
 (defcustom mh-alias-system-aliases
@@ -270,9 +270,9 @@ Blind aliases or users from /etc/passwd are not expanded."
                   (t (split-string
                       (completing-read prompt mh-alias-alist nil nil) ",")))))
       (if (not mh-alias-expand-aliases-flag)
-          (mapconcat 'identity the-answer ", ")
+          (mapconcat #'identity the-answer ", ")
         ;; Loop over all elements, checking if in passwd alias or blind first
-        (mapconcat 'mh-alias-expand the-answer ",\n ")))))
+        (mapconcat #'mh-alias-expand the-answer ",\n ")))))
 
 ;;;###mh-autoload
 (defun mh-alias-minibuffer-confirm-address ()
@@ -427,10 +427,10 @@ contains it."
       (if (or (not alias)
               (string-equal alias (mh-alias-ali alias))) ;alias doesn't exist
           (completing-read "Alias file: "
-                           (mapcar 'list mh-alias-insert-file) nil t)
+                           (mapcar #'list mh-alias-insert-file) nil t)
         (or (mh-alias-which-file-has-alias alias mh-alias-insert-file)
             (completing-read "Alias file: "
-                             (mapcar 'list mh-alias-insert-file) nil t)))))
+                             (mapcar #'list mh-alias-insert-file) nil t)))))
    ((and mh-alias-insert-file (stringp mh-alias-insert-file))
     mh-alias-insert-file)
    (t
@@ -449,11 +449,10 @@ set `mh-alias-insert-file' or the \"Aliasfile:\" profile 
component"))
         (car autolist))
        ((or (not alias)
             (string-equal alias (mh-alias-ali alias))) ;alias doesn't exist
-        (completing-read "Alias file: " (mapcar 'list autolist) nil t))
+        (completing-read "Alias file: " autolist nil t))
        (t
         (or (mh-alias-which-file-has-alias alias autolist)
-            (completing-read "Alias file: "
-                             (mapcar 'list autolist) nil t))))))))
+            (completing-read "Alias file: " autolist nil t))))))))
 
 ;;;###mh-autoload
 (defun mh-alias-address-to-alias (address)
diff --git a/lisp/mh-e/mh-buffers.el b/lisp/mh-e/mh-buffers.el
index 55f74b6..a32f61c 100644
--- a/lisp/mh-e/mh-buffers.el
+++ b/lisp/mh-e/mh-buffers.el
@@ -1,4 +1,4 @@
-;;; mh-buffers.el --- MH-E buffer constants and utilities
+;;; mh-buffers.el --- MH-E buffer constants and utilities  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1993, 1995, 1997, 2000-2021 Free Software Foundation,
 ;; Inc.
diff --git a/lisp/mh-e/mh-comp.el b/lisp/mh-e/mh-comp.el
index 0dedb7e..c1cd6c1 100644
--- a/lisp/mh-e/mh-comp.el
+++ b/lisp/mh-e/mh-comp.el
@@ -1,4 +1,4 @@
-;;; mh-comp.el --- MH-E functions for composing and sending messages
+;;; mh-comp.el --- MH-E functions for composing and sending messages  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1993, 1995, 1997, 2000-2021 Free Software Foundation,
 ;; Inc.
@@ -719,12 +719,14 @@ message and scan line."
                (mh-insert-fields field value)))))
          (mh-components-to-list components-file))
         (delete-file components-file))
-      (mh-insert-fields "Resent-To:" (mapconcat 'identity (list to comp-to) ", 
")
-                        "Resent-Cc:" (mapconcat 'identity (list cc comp-cc) ", 
")
-                        "Resent-Fcc:" (mapconcat 'identity (list fcc
-                                                                 comp-fcc) ", 
")
-                        "Resent-Bcc:" (mapconcat 'identity (list bcc
-                                                                 comp-bcc) ", 
")
+      (mh-insert-fields "Resent-To:" (mapconcat #'identity (list to comp-to)
+                                                ", ")
+                        "Resent-Cc:" (mapconcat #'identity (list cc comp-cc)
+                                                ", ")
+                        "Resent-Fcc:" (mapconcat #'identity (list fcc comp-fcc)
+                                                 ", ")
+                        "Resent-Bcc:" (mapconcat #'identity (list bcc comp-bcc)
+                                                 ", ")
                         "Resent-From:" from)
       (save-buffer)
       (message "Redistributing...")
@@ -1096,7 +1098,7 @@ letter."
   (setq mode-line-buffer-identification (list "    {%b}"))
   (mh-logo-display)
   (mh-make-local-hook 'kill-buffer-hook)
-  (add-hook 'kill-buffer-hook 'mh-tidy-draft-buffer nil t)
+  (add-hook 'kill-buffer-hook #'mh-tidy-draft-buffer nil t)
   (run-hook-with-args 'mh-compose-letter-function to subject cc))
 
 (defun mh-insert-x-mailer ()
@@ -1165,7 +1167,7 @@ This should be the last function called when composing 
the draft."
 MSG can be a message number, a list of message numbers, or a sequence.
 The hook `mh-annotate-msg-hook' is run after annotating; see its
 documentation for variables it can use."
-  (apply 'mh-exec-cmd "anno" folder
+  (apply #'mh-exec-cmd "anno" folder
          (if (listp msg) (append msg args) (cons msg args)))
   (save-excursion
     (cond ((get-buffer folder)          ; Buffer may be deleted
diff --git a/lisp/mh-e/mh-compat.el b/lisp/mh-e/mh-compat.el
index 6d657af..0363c5a 100644
--- a/lisp/mh-e/mh-compat.el
+++ b/lisp/mh-e/mh-compat.el
@@ -42,7 +42,7 @@
 (eval-when-compile (require 'mh-acros))
 
 (mh-do-in-gnu-emacs
-  (defalias 'mh-require 'require))
+  (defalias 'mh-require #'require))
 
 (mh-do-in-xemacs
   (defun mh-require (feature &optional filename noerror)
diff --git a/lisp/mh-e/mh-e.el b/lisp/mh-e/mh-e.el
index eaf8eb5..1aac337 100644
--- a/lisp/mh-e/mh-e.el
+++ b/lisp/mh-e/mh-e.el
@@ -522,7 +522,7 @@ parsed by MH-E."
     (let* ((initial-size (mh-truncate-log-buffer))
            (start (point))
            (args (mh-list-to-string args)))
-      (apply 'call-process (expand-file-name command mh-progs) nil t nil args)
+      (apply #'call-process (expand-file-name command mh-progs) nil t nil args)
       (when (> (buffer-size) initial-size)
         (save-excursion
           (goto-char start)
@@ -560,7 +560,7 @@ ARGS are passed to COMMAND as command line arguments."
   (with-current-buffer (get-buffer-create mh-log-buffer)
     (mh-truncate-log-buffer))
   (let* ((process-connection-type nil)
-         (process (apply 'start-process
+         (process (apply #'start-process
                          command nil
                          (expand-file-name command mh-progs)
                          (mh-list-to-string args))))
@@ -602,7 +602,7 @@ RAISE-ERROR is non-nil, in which case an error is signaled 
if
   (set-buffer (get-buffer-create mh-temp-buffer))
   (erase-buffer)
   (let ((value
-         (apply 'call-process
+         (apply #'call-process
                 (expand-file-name command mh-progs) nil t nil
                 args)))
     (goto-char (point-min))
@@ -616,7 +616,7 @@ Put the output into buffer after point.
 Set mark after inserted text.
 Output is expected to be shown to user, not parsed by MH-E."
   (push-mark (point) t)
-  (apply 'call-process
+  (apply #'call-process
          (expand-file-name command mh-progs) nil t display
          (mh-list-to-string args))
 
@@ -650,7 +650,7 @@ preserves whether the mark is active or not."
   "Execute MH library command COMMAND with ARGS.
 Put the output into buffer after point.
 Set mark after inserted text."
-  (apply 'mh-exec-cmd-output (expand-file-name command mh-lib-progs) nil args))
+  (apply #'mh-exec-cmd-output (expand-file-name command mh-lib-progs) nil 
args))
 
 (defun mh-handle-process-error (command status)
   "Raise error if COMMAND returned non-zero STATUS, otherwise return STATUS."
@@ -974,7 +974,7 @@ necessary and can actually cause problems."
   :set (lambda (symbol value)
          (set-default symbol value)     ;Done in mh-variant-set-variant!
          (mh-variant-set value))
-  :initialize 'custom-initialize-default
+  :initialize #'custom-initialize-default
   :group 'mh-e
   :package-version '(MH-E . "8.0"))
 
@@ -1548,7 +1548,7 @@ as the result is undefined."
                                  '(radio)
                                  (mapcar
                                   (lambda (arg) `(const ,arg))
-                                  (mapcar 'car mh-identity-list))))
+                                  (mapcar #'car mh-identity-list))))
                          (cons :tag "Fcc Field"
                                (const "fcc")
                                (string :tag "Value"))
@@ -1575,7 +1575,7 @@ See `mh-identity-list'."
          '(radio)
          (cons '(const :tag "None" nil)
                (mapcar (lambda (arg) `(const ,arg))
-                       (mapcar 'car mh-identity-list))))
+                       (mapcar #'car mh-identity-list))))
   :group 'mh-identity
   :package-version '(MH-E . "7.1"))
 
@@ -1744,7 +1744,7 @@ bogofilter, then you can set this option to 
\"Bogofilter\"."
                  (const :tag "SpamAssassin" spamassassin)
                  (const :tag "Bogofilter" bogofilter)
                  (const :tag "SpamProbe" spamprobe))
-  :set 'mh-junk-choose
+  :set #'mh-junk-choose
   :group 'mh-junk
   :package-version '(MH-E . "7.3"))
 
@@ -1907,7 +1907,7 @@ white image, can be generated using the \"compface\" 
command (see URL
 `ftp://ftp.cs.indiana.edu/pub/faces/compface/compface.tar.Z'). The
 \"Online X-Face Converter\" is a useful resource for quick conversion
 of images into \"X-Face:\" header fields (see URL
-`http://www.dairiki.org/xface/').
+`https://www.dairiki.org/xface/').
 
 Use the \"make-face\" script to convert a JPEG image to the higher
 resolution, color, \"Face:\" header field (see URL
@@ -2005,7 +2005,7 @@ call `mh-set-cmd-note' with the width specified by your 
format file
 you would use \"(mh-set-cmd-note 4)\"."
   :type 'boolean
   :group 'mh-scan-line-formats
-  :set 'mh-adaptive-cmd-note-flag-check
+  :set #'mh-adaptive-cmd-note-flag-check
   :package-version '(MH-E . "7.0"))
 
 (defun mh-scan-format-file-check (symbol value)
@@ -2044,7 +2044,7 @@ Emacs start with 0)."
                  (const :tag "Use Default scan Format" nil)
                  (file  :tag "Specify a scan Format File"))
   :group 'mh-scan-line-formats
-  :set 'mh-scan-format-file-check
+  :set #'mh-scan-format-file-check
   :package-version '(MH-E . "6.0"))
 
 (defun mh-adaptive-cmd-note-flag-check (symbol value)
@@ -2466,9 +2466,9 @@ of citations entirely, choose \"None\"."
     "Disposition-Notification-Options:" ; RFC 2298
     "Disposition-Notification-To:"      ; RFC 2298
     "Distribution:"                     ; RFC 1036
-    "DKIM-"                             ; http://antispam.yahoo.com/domainkeys
+    "DKIM-"                             ; 
https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail
     "DL-Expansion-History:"             ; RFC 2156
-    "DomainKey-"                        ; http://antispam.yahoo.com/domainkeys
+    "DomainKey-"                        ; 
https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail
     "DomainKey-Signature:"
     "Encoding:"                         ; RFC 1505
     "Envelope-to:"
@@ -2555,7 +2555,7 @@ of citations entirely, choose \"None\"."
     "X-Abuse-Info:"
     "X-Accept-Language:"                ; Netscape/Mozilla
     "X-Ack:"
-    "X-ACL-Warn:"                      ; http://www.exim.org
+    "X-ACL-Warn:"                      ; https://www.exim.org
     "X-Admin:"                          ; 
https://people.dsv.su.se/~jpalme/ietf/mail-headers/
     "X-Administrivia-To:"
     "X-AMAZON"                          ; Amazon.com
@@ -2579,8 +2579,8 @@ of citations entirely, choose \"None\"."
     "X-BFI:"
     "X-Bigfish:"
     "X-Bogosity:"                       ; bogofilter
-    "X-BPS1:"                          ; http://www.boggletools.com
-    "X-BPS2:"                          ; http://www.boggletools.com
+    "X-BPS1:"                          ; http://www.boggletools.com [dead 
link?]
+    "X-BPS2:"                          ; http://www.boggletools.com [dead 
link?]
     "X-Brightmail-Tracker:"             ; Brightmail
     "X-BrightmailFiltered:"             ; Brightmail
     "X-Bugzilla-"                       ; Bugzilla
@@ -2596,12 +2596,12 @@ of citations entirely, choose \"None\"."
     "X-Confirm-Reading-To:"             ; 
https://people.dsv.su.se/~jpalme/ietf/mail-headers/
     "X-Content-Filtered-By:"
     "X-ContentStamp:"                   ; NetZero
-    "X-Country-Chain:"                  ; http://www.declude.com/x-note.htm
+    "X-Country-Chain:"                  ; http://www.declude.com/x-note.htm 
[dead link?]
     "X-Cr-Hashedpuzzle:"
     "X-Cr-Puzzleid:"
     "X-Cron-Env:"
     "X-DCC-"                            ; SpamAssassin
-    "X-Declude-"                        ; http://www.declude.com/x-note.htm
+    "X-Declude-"                        ; http://www.declude.com/x-note.htm 
[dead link?]
     "X-Dedicated:"
     "X-Delivered"
     "X-Destination-ID:"
@@ -2616,7 +2616,7 @@ of citations entirely, choose \"None\"."
     "X-EID:"
     "X-ELNK-Trace:"                     ; Earthlink mailer
     "X-EM-"                            ; Some ecommerce software
-    "X-Email-Type-Id:"                 ; Paypal http://www.paypal.com
+    "X-Email-Type-Id:"                 ; Paypal https://www.paypal.com
     "X-Enigmail-Version:"
     "X-Envelope-Date:"                  ; GNU mailutils
     "X-Envelope-From:"                  ; 
https://people.dsv.su.se/~jpalme/ietf/mail-headers/
@@ -2632,21 +2632,21 @@ of citations entirely, choose \"None\"."
     "X-Folder:"                         ; Spam
     "X-Forwarded-"                      ; Google+
     "X-From-Line"
-    "X-FuHaFi:"                                ; http://www.gmx.net/
+    "X-FuHaFi:"                                ; https://www.gmx.net/
     "X-Generated-By:"                   ; launchpad.net
     "X-Gmail-"                          ; Gmail
     "X-Gnus-Mail-Source:"               ; gnus
     "X-Google-"                         ; Google mail
     "X-Google-Sender-Auth:"
     "X-Greylist:"                       ; milter-greylist-1.2.1
-    "X-Habeas-"                                ; http://www.returnpath.net
+    "X-Habeas-"                                ; https://www.returnpath.net
     "X-Hashcash:"                       ; hashcash
     "X-Headers-End:"                    ; SpamCop
     "X-HPL-"
     "X-HR-"
     "X-HTTP-UserAgent:"
     "X-Hz"                             ; Hertz
-    "X-Identity:"                       ; http://www.declude.com/x-note.htm
+    "X-Identity:"                       ; http://www.declude.com/x-note.htm 
[dead link?]
     "X-IEEE-UCE-"                       ; IEEE spam filter
     "X-Image-URL:"
     "X-IMAP:"                           ; 
https://people.dsv.su.se/~jpalme/ietf/mail-headers/
@@ -2667,7 +2667,7 @@ of citations entirely, choose \"None\"."
     "X-Loop:"                           ; 
https://people.dsv.su.se/~jpalme/ietf/mail-headers/
     "X-Lrde-Mailscanner:"
     "X-Lumos-SenderID:"                 ; Roving ConstantContact
-    "X-mail_abuse_inquiries:"          ; http://www.salesforce.com
+    "X-mail_abuse_inquiries:"          ; https://www.salesforce.com
     "X-Mail-from:"                      ; fastmail.fm
     "X-MAIL-INFO:"                      ; NetZero
     "X-Mailer_"
@@ -2680,11 +2680,11 @@ of citations entirely, choose \"None\"."
     "X-Mailutils-Message-Id"            ; GNU Mailutils
     "X-Majordomo:"                      ; Majordomo mailing list manager
     "X-Match:"
-    "X-MaxCode-Template:"              ; Paypal http://www.paypal.com
+    "X-MaxCode-Template:"              ; Paypal https://www.paypal.com
     "X-MB-Message-"                     ; AOL WebMail
     "X-MDaemon-Deliver-To:"
     "X-MDRemoteIP:"
-    "X-ME-Bayesian:"                   ; 
http://www.newmediadevelopment.net/page.cfm/parent/Client-Area/content/Managing-spam/
+    "X-ME-Bayesian:"                   ; 
https://www.newmediadevelopment.net/page.cfm/parent/Client-Area/content/Managing-spam/
     "X-Message-Id"
     "X-Message-Type:"
     "X-MessageWall-Score:"              ; Unknown mailing list manager, AUC TeX
@@ -2755,7 +2755,7 @@ of citations entirely, choose \"None\"."
     "X-Server-Date:"
     "X-Server-Uuid:"
     "X-Service-Code:"
-    "X-SFDC-"                          ; http://www.salesforce.com
+    "X-SFDC-"                          ; https://www.salesforce.com
     "X-Sieve:"                          ; Sieve filtering
     "X-SMFBL:"
     "X-SMHeaderMap:"
@@ -2770,7 +2770,7 @@ of citations entirely, choose \"None\"."
     "X-Submissions-To:"
     "X-Sun-Charset:"
     "X-Telecom-Digest"
-    "X-TM-IMSS-Message-ID:"            ; http://www.trendmicro.com
+    "X-TM-IMSS-Message-ID:"            ; https://www.trendmicro.com
     "X-Trace:"
     "X-UID"
     "X-UIDL:"                           ; 
https://people.dsv.su.se/~jpalme/ietf/mail-headers/
@@ -2790,10 +2790,10 @@ of citations entirely, choose \"None\"."
     "X-WebTV-Signature:"
     "X-Wss-Id:"                         ; Worldtalk gateways
     "X-X-Sender:"                       ; 
https://people.dsv.su.se/~jpalme/ietf/mail-headers/
-    "X-XPT-XSL-Name:"                  ; Paypal http://www.paypal.com
+    "X-XPT-XSL-Name:"                  ; Paypal https://www.paypal.com
     "X-xsi-"
-    "X-XWALL-"                         ; 
http://www.dataenter.co.at/doc/xwall_undocumented_config.htm
-    "X-Y-GMX-Trusted:"                 ; http://www.gmx.net/
+    "X-XWALL-"                         ; 
https://www.dataenter.co.at/doc/xwall_undocumented_config.htm
+    "X-Y-GMX-Trusted:"                 ; https://www.gmx.net/
     "X-Yahoo"
     "X-Yahoo-Newman-"
     "X-YMail-"
@@ -3039,7 +3039,7 @@ XEmacs. For more information, see URL
 `ftp://ftp.cs.indiana.edu/pub/faces/compface/compface.tar.z'). Recent
 versions of XEmacs have internal support for \"X-Face:\" images. If
 your version of XEmacs does not, then you'll need both \"uncompface\"
-and the x-face package (see URL `http://www.jpl.org/ftp/pub/elisp/').
+and the x-face package (see URL `https://www.jpl.org/ftp/pub/elisp/').
 
 Finally, MH-E will display images referenced by the \"X-Image-URL:\"
 header field if neither the \"Face:\" nor the \"X-Face:\" fields are
diff --git a/lisp/mh-e/mh-folder.el b/lisp/mh-e/mh-folder.el
index 555d13d..2e28806 100644
--- a/lisp/mh-e/mh-folder.el
+++ b/lisp/mh-e/mh-folder.el
@@ -1,4 +1,4 @@
-;;; mh-folder.el --- MH-Folder mode
+;;; mh-folder.el --- MH-Folder mode  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2002-2003, 2005-2021 Free Software Foundation, Inc.
 
@@ -209,10 +209,10 @@ annotation.")
 
 ;; Use defalias to make sure the documented primary key bindings
 ;; appear in menu lists.
-(defalias 'mh-alt-show 'mh-show)
-(defalias 'mh-alt-refile-msg 'mh-refile-msg)
-(defalias 'mh-alt-send 'mh-send)
-(defalias 'mh-alt-visit-folder 'mh-visit-folder)
+(defalias 'mh-alt-show #'mh-show)
+(defalias 'mh-alt-refile-msg #'mh-refile-msg)
+(defalias 'mh-alt-send #'mh-send)
+(defalias 'mh-alt-visit-folder #'mh-visit-folder)
 
 ;; Save the "b" binding for a future `back'. Maybe?
 (gnus-define-keys  mh-folder-mode-map
@@ -650,11 +650,11 @@ perform the operation on all messages in that region.
   (auto-save-mode -1)
   (setq buffer-offer-save t)
   (mh-make-local-hook (mh-write-file-functions))
-  (add-hook (mh-write-file-functions) 'mh-execute-commands nil t)
+  (add-hook (mh-write-file-functions) #'mh-execute-commands nil t)
   (make-local-variable 'revert-buffer-function)
   (make-local-variable 'hl-line-mode)   ; avoid pollution
   (mh-funcall-if-exists hl-line-mode 1)
-  (setq revert-buffer-function 'mh-undo-folder)
+  (setq revert-buffer-function #'mh-undo-folder)
   (add-to-list 'minor-mode-alist '(mh-showing-mode " Show"))
   (mh-do-in-xemacs
     (easy-menu-add mh-folder-sequence-menu)
@@ -1117,7 +1117,7 @@ called interactively."
          (message "Destination folder: %s" (cdr mh-last-destination)))
         (t
          (mh-iterate-on-range msg range
-           (apply 'mh-write-msg-to-file msg (cdr mh-last-destination)))
+           (apply #'mh-write-msg-to-file msg (cdr mh-last-destination)))
          (mh-next-msg interactive-flag))))
 
 ;;;###mh-autoload
@@ -1606,7 +1606,7 @@ after the commands are processed."
       ;; Now delete messages
       (cond (mh-delete-list
              (setq redraw-needed-flag t)
-             (apply 'mh-exec-cmd "rmm" folder
+             (apply #'mh-exec-cmd "rmm" folder
                     (mh-coalesce-msg-list mh-delete-list))
              (mh-delete-scan-msgs mh-delete-list)
              (setq mh-delete-list nil)))
@@ -1620,8 +1620,8 @@ after the commands are processed."
           ;; (mh-refile-a-msg nil (intern dest))
           ;; (mh-delete-a-msg nil)))
           (if (null dest)
-              (apply 'mh-exec-cmd "rmm" folder msg-list)
-            (apply 'mh-exec-cmd "refile" "-src" folder dest msg-list)
+              (apply #'mh-exec-cmd "rmm" folder msg-list)
+            (apply #'mh-exec-cmd "refile" "-src" folder dest msg-list)
             (push dest folders-changed))
           (setq redraw-needed-flag t)
           (mh-delete-scan-msgs mh-blacklist)
@@ -1703,7 +1703,7 @@ after the commands are processed."
       (mh-recenter nil)))
 
 ;;;###mh-autoload
-(defun mh-make-folder-mode-line (&optional ignored)
+(defun mh-make-folder-mode-line (&optional _ignored)
   "Set the fields of the mode line for a folder buffer.
 The optional argument is now obsolete and IGNORED. It used to be
 used to pass in what is now stored in the buffer-local variable
diff --git a/lisp/mh-e/mh-funcs.el b/lisp/mh-e/mh-funcs.el
index 309bcb4..38ba431 100644
--- a/lisp/mh-e/mh-funcs.el
+++ b/lisp/mh-e/mh-funcs.el
@@ -1,4 +1,4 @@
-;;; mh-funcs.el --- MH-E functions not everyone will use right away
+;;; mh-funcs.el --- MH-E functions not everyone will use right away  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1993, 1995, 2001-2021 Free Software Foundation, Inc.
 
@@ -348,7 +348,7 @@ See `mh-store-msg' for a description of DIRECTORY."
         (error "Error occurred during execution of %s" command)))))
 
 ;;;###mh-autoload
-(defun mh-undo-folder (&rest ignored)
+(defun mh-undo-folder (&rest _ignored)
   "Undo all refiles and deletes in the current folder.
 Arguments are IGNORED (for `revert-buffer')."
   (interactive)
diff --git a/lisp/mh-e/mh-gnus.el b/lisp/mh-e/mh-gnus.el
index 6a98516..ac46cc6 100644
--- a/lisp/mh-e/mh-gnus.el
+++ b/lisp/mh-e/mh-gnus.el
@@ -1,4 +1,4 @@
-;;; mh-gnus.el --- make MH-E compatible with various versions of Gnus
+;;; mh-gnus.el --- make MH-E compatible with various versions of Gnus  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2003-2004, 2006-2021 Free Software Foundation, Inc.
 
@@ -129,7 +129,7 @@
   (unless default
     (setq default (mml-content-disposition type filename)))
   (let ((disposition (completing-read
-                     (format "Disposition (default %s): " default)
+                     (format-prompt "Disposition" default)
                      '(("attachment") ("inline") (""))
                      nil t nil nil default)))
     (if (not (equal disposition ""))
diff --git a/lisp/mh-e/mh-identity.el b/lisp/mh-e/mh-identity.el
index 1844399..aeab049 100644
--- a/lisp/mh-e/mh-identity.el
+++ b/lisp/mh-e/mh-identity.el
@@ -1,4 +1,4 @@
-;;; mh-identity.el --- multiple identify support for MH-E
+;;; mh-identity.el --- multiple identify support for MH-E  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2002-2021 Free Software Foundation, Inc.
 
@@ -50,7 +50,7 @@ This is normally set as part of an Identity in
 (defvar mh-identity-menu nil
   "The Identity menu.")
 
-(defalias 'mh-identity-make-menu-no-autoload 'mh-identity-make-menu)
+(defalias 'mh-identity-make-menu-no-autoload #'mh-identity-make-menu)
 
 ;;;###mh-autoload
 (defun mh-identity-make-menu ()
@@ -74,7 +74,7 @@ See `mh-identity-add-menu'."
      (mapcar (lambda (arg)
                `[,arg  (mh-insert-identity ,arg) :style radio
                        :selected (equal mh-identity-local ,arg)])
-             (mapcar 'car mh-identity-list))
+             (mapcar #'car mh-identity-list))
      '(["None"
         (mh-insert-identity "None") :style radio
         :selected (not mh-identity-local)]
@@ -142,7 +142,7 @@ See `mh-identity-list'."
           (completing-read
            "Identity: "
            (cons '("None")
-                 (mapcar 'list (mapcar 'car mh-identity-list)))
+                 (mapcar #'list (mapcar #'car mh-identity-list)))
            nil t default nil default))
     (if (eq identity "None")
         nil
@@ -171,8 +171,8 @@ See `mh-identity-list'."
           "Identity: "
           (if mh-identity-local
               (cons '("None")
-                    (mapcar 'list (mapcar 'car mh-identity-list)))
-            (mapcar 'list (mapcar 'car mh-identity-list)))
+                    (mapcar #'list (mapcar #'car mh-identity-list)))
+            (mapcar #'list (mapcar #'car mh-identity-list)))
           nil t)
          nil))
 
diff --git a/lisp/mh-e/mh-inc.el b/lisp/mh-e/mh-inc.el
index 32f7317..6a29195 100644
--- a/lisp/mh-e/mh-inc.el
+++ b/lisp/mh-e/mh-inc.el
@@ -1,4 +1,4 @@
-;;; mh-inc.el --- MH-E "inc" and separate mail spool handling
+;;; mh-inc.el --- MH-E "inc" and separate mail spool handling  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2003-2004, 2006-2021 Free Software Foundation, Inc.
 
@@ -58,19 +58,15 @@
                     (mh-inc-spool-generator folder spool)
                     (mh-inc-spool-def-key key folder))))))
 
-(defalias 'mh-inc-spool-make-no-autoload 'mh-inc-spool-make)
+(defalias 'mh-inc-spool-make-no-autoload #'mh-inc-spool-make)
 
 (defun mh-inc-spool-generator (folder spool)
   "Create a command to inc into FOLDER from SPOOL file."
-  (let ((folder1 (make-symbol "folder"))
-        (spool1 (make-symbol "spool")))
-    (set folder1 folder)
-    (set spool1 spool)
-    (setf (symbol-function (intern (concat "mh-inc-spool-" folder)))
-          `(lambda ()
-             ,(format "Inc spool file %s into folder %s." spool folder)
-             (interactive)
-             (mh-inc-folder ,spool1 (concat "+" ,folder1))))))
+  (defalias (symbol-function (intern (concat "mh-inc-spool-" folder)))
+    (lambda ()
+      (:documentation (format "Inc spool file %s into folder %s." spool 
folder))
+      (interactive)
+      (mh-inc-folder spool (concat "+" folder)))))
 
 (defun mh-inc-spool-def-key (key folder)
   "Define a KEY in `mh-inc-spool-map' to inc FOLDER and collect help string."
diff --git a/lisp/mh-e/mh-junk.el b/lisp/mh-e/mh-junk.el
index b49c632..5a40794 100644
--- a/lisp/mh-e/mh-junk.el
+++ b/lisp/mh-e/mh-junk.el
@@ -1,4 +1,4 @@
-;;; mh-junk.el --- MH-E interface to anti-spam measures
+;;; mh-junk.el --- MH-E interface to anti-spam measures  -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 2003-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/mh-e/mh-letter.el b/lisp/mh-e/mh-letter.el
index f5ad73d..5979018 100644
--- a/lisp/mh-e/mh-letter.el
+++ b/lisp/mh-e/mh-letter.el
@@ -1,4 +1,4 @@
-;;; mh-letter.el --- MH-Letter mode
+;;; mh-letter.el --- MH-Letter mode  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1993, 1995, 1997, 2000-2021 Free Software Foundation,
 ;; Inc.
@@ -334,15 +334,15 @@ order).
   ;; Maybe we want to use the existing Mail menu from mail-mode in
   ;; 9.0; in the mean time, let's remove it since the redundancy will
   ;; only produce confusion.
-  (define-key mh-letter-mode-map [menu-bar mail] 'undefined)
+  (define-key mh-letter-mode-map [menu-bar mail] #'undefined)
   (mh-do-in-xemacs (easy-menu-remove mail-menubar-menu))
   (setq fill-column mh-letter-fill-column)
   (add-hook 'completion-at-point-functions
-            'mh-letter-completion-at-point nil 'local)
+            #'mh-letter-completion-at-point nil 'local)
   ;; If text-mode-hook turned on auto-fill, tune it for messages
   (when auto-fill-function
     (make-local-variable 'auto-fill-function)
-    (setq auto-fill-function 'mh-auto-fill-for-letter)))
+    (setq auto-fill-function #'mh-auto-fill-for-letter)))
 
 
 
@@ -390,10 +390,7 @@ This command leaves the mark before the letter and point 
after it."
                 (or mh-sent-from-msg (nth 0 (mh-translate-range folder "cur")))
               (nth 0 (mh-translate-range folder "cur"))))
           (message
-           (read-string (concat "Message number"
-                                (or (and default
-                                         (format " (default %d): " default))
-                                    ": "))
+           (read-string (format-prompt "Message number" default)
                         nil nil
                         (if (numberp default)
                             (int-to-string default)
@@ -851,7 +848,7 @@ body."
              (forward-line)))))
 
 ;;;###mh-autoload
-(defun mh-position-on-field (field &optional ignored)
+(defun mh-position-on-field (field &optional _ignored)
   "Move to the end of the FIELD in the header.
 Move to end of entire header if FIELD not found.
 Returns non-nil if FIELD was found.
diff --git a/lisp/mh-e/mh-limit.el b/lisp/mh-e/mh-limit.el
index 036522f..08f1b40 100644
--- a/lisp/mh-e/mh-limit.el
+++ b/lisp/mh-e/mh-limit.el
@@ -1,4 +1,4 @@
-;;; mh-limit.el --- MH-E display limits
+;;; mh-limit.el --- MH-E display limits  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2001-2003, 2006-2021 Free Software Foundation, Inc.
 
@@ -237,7 +237,7 @@ Return number of messages put in the sequence:
               (setq list (cons (mh-get-msg-num t) list)))
           (if (assoc 'subject mh-seq-list) (mh-delete-seq 'subject))
           ;; sort the result into a sequence
-          (let ((sorted-list (sort (copy-sequence list) 'mh-lessp)))
+          (let ((sorted-list (sort (copy-sequence list) #'mh-lessp)))
             (while sorted-list
               (mh-add-msgs-to-seq (car sorted-list) 'subject nil)
               (setq sorted-list (cdr sorted-list)))
diff --git a/lisp/mh-e/mh-mime.el b/lisp/mh-e/mh-mime.el
index 70df9e6..fec2293 100644
--- a/lisp/mh-e/mh-mime.el
+++ b/lisp/mh-e/mh-mime.el
@@ -1,4 +1,4 @@
-;;; mh-mime.el --- MH-E MIME support
+;;; mh-mime.el --- MH-E MIME support  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1993, 1995, 2001-2021 Free Software Foundation, Inc.
 
@@ -190,9 +190,9 @@ Set from last use.")
       ;; XEmacs doesn't care.
       (set-keymap-parent map mh-show-mode-map))
     (mh-do-in-gnu-emacs
-     (define-key map [mouse-2] 'mh-push-button))
+     (define-key map [mouse-2] #'mh-push-button))
     (mh-do-in-xemacs
-     (define-key map '(button2) 'mh-push-button))
+     (define-key map '(button2) #'mh-push-button))
     (dolist (c mh-mime-button-commands)
       (define-key map (cadr c) (car c)))
     map))
@@ -214,11 +214,11 @@ Set from last use.")
   (let ((map (make-sparse-keymap)))
     (unless (>= (string-to-number emacs-version) 21)
       (set-keymap-parent map mh-show-mode-map))
-    (define-key map "\r" 'mh-press-button)
+    (define-key map "\r" #'mh-press-button)
     (mh-do-in-gnu-emacs
-     (define-key map [mouse-2] 'mh-push-button))
+     (define-key map [mouse-2] #'mh-push-button))
     (mh-do-in-xemacs
-     (define-key map '(button2) 'mh-push-button))
+     (define-key map '(button2) #'mh-push-button))
     map))
 
 
@@ -259,9 +259,7 @@ usually reads the file \"/etc/mailcap\"."
               (methods (mapcar (lambda (x) (list (cdr (assoc 'viewer x))))
                                (mailcap-mime-info type 'all)))
               (def (caar methods))
-              (prompt (format "Viewer%s: " (if def
-                                               (format " (default %s)" def)
-                                             "")))
+              (prompt (format-prompt "Viewer" def))
               (method (completing-read prompt methods nil nil nil nil def))
               (folder mh-show-folder-buffer)
               (buffer-read-only nil))
@@ -395,9 +393,9 @@ do the work."
           ((and (or prompt
                     (equal t mh-mime-save-parts-default-directory))
                 mh-mime-save-parts-directory)
-           (read-directory-name (format
-                            "Store in directory (default %s): "
-                            mh-mime-save-parts-directory)
+           (read-directory-name (format-prompt
+                                 "Store in directory"
+                                 mh-mime-save-parts-directory)
                            "" mh-mime-save-parts-directory t ""))
           ((stringp mh-mime-save-parts-default-directory)
            mh-mime-save-parts-default-directory)
@@ -413,7 +411,7 @@ do the work."
         (cd directory)
         (setq mh-mime-save-parts-directory directory)
         (let ((initial-size (mh-truncate-log-buffer)))
-          (apply 'call-process
+          (apply #'call-process
                  (expand-file-name command mh-progs) nil t nil
                  (mh-list-to-string (list folder msg "-auto"
                                           (if (not (mh-variant-p 'nmh))
@@ -452,7 +450,7 @@ decoding the same message multiple times."
   (let ((b (point))
         (clean-message-header mh-clean-message-header-flag)
         (invisible-headers mh-invisible-header-fields-compiled)
-        (visible-headers nil))
+        ) ;; (visible-headers nil)
     (save-excursion
       (save-restriction
         (narrow-to-region b b)
@@ -474,7 +472,7 @@ decoding the same message multiple times."
         (cond (clean-message-header
                (mh-clean-msg-header (point-min)
                                     invisible-headers
-                                    visible-headers)
+                                    nil) ;; visible-headers
                (goto-char (point-min)))
               (t
                (mh-start-of-uncleaned-message)))
@@ -489,15 +487,11 @@ decoding the same message multiple times."
         (mh-display-emphasis)
         (mm-handle-set-undisplayer
          handle
-         `(lambda ()
-            (let (buffer-read-only)
-              (if (fboundp 'remove-specifier)
-                  ;; This is only valid on XEmacs.
-                  (mapcar (lambda (prop)
-                            (remove-specifier
-                             (face-property 'default prop) (current-buffer)))
-                          '(background background-pixmap foreground)))
-              (delete-region ,(point-min-marker) ,(point-max-marker)))))))))
+         (let ((beg (point-min-marker))
+               (end (point-max-marker)))
+           (lambda ()
+             (let ((inhibit-read-only t))
+               (delete-region beg end)))))))))
 
 ;;;###mh-autoload
 (defun mh-decode-message-header ()
@@ -783,7 +777,7 @@ This is only useful if a Content-Disposition header is not 
present."
          (funcall media-test handle) ; Since mm-inline-large-images is T,
                                         ; this only tells us if the image is
                                         ; something that emacs can display
-         (let* ((image (mm-get-image handle)))
+         (let ((image (mm-get-image handle)))
            (or (mh-do-in-xemacs
                  (and (mh-funcall-if-exists glyphp image)
                       (< (glyph-width image)
@@ -792,7 +786,7 @@ This is only useful if a Content-Disposition header is not 
present."
                          (or mh-max-inline-image-height
                              (window-pixel-height)))))
                (mh-do-in-gnu-emacs
-                 (let ((size (mh-funcall-if-exists image-size image)))
+                 (let ((size (and (fboundp 'image-size) (image-size image))))
                    (and size
                         (< (cdr size) (or mh-max-inline-image-height
                                           (1- (window-height))))
@@ -1225,7 +1219,7 @@ The option `mh-compose-insertion' controls what type of 
tags are inserted."
                               t)
                           t t)))
      (list description folder range)))
-  (let ((messages (mapconcat 'identity (mh-list-to-string range) " ")))
+  (let ((messages (mapconcat #'identity (mh-list-to-string range) " ")))
     (dolist (message (mh-translate-range folder messages))
       (if (equal mh-compose-insertion 'mml)
           (mh-mml-forward-message description folder (format "%s" message))
@@ -1258,11 +1252,7 @@ See also \\[mh-mh-to-mime]."
   (interactive (list
                 (mml-minibuffer-read-description)
                 (mh-prompt-for-folder "Message from" mh-sent-from-folder nil)
-                (read-string (concat "Messages"
-                                     (if (numberp mh-sent-from-msg)
-                                         (format " (default %d): "
-                                                 mh-sent-from-msg)
-                                       ": ")))))
+                (read-string (format-prompt "Messages" mh-sent-from-msg))))
   (beginning-of-line)
   (insert "#forw [")
   (and description
@@ -1596,7 +1586,7 @@ the possible security methods (see 
`mh-mml-method-default')."
   (if current-prefix-arg
       (let ((def (or (car mh-mml-cryptographic-method-history)
                      mh-mml-method-default)))
-        (completing-read (format "Method (default %s): " def)
+        (completing-read (format-prompt "Method" def)
                          '(("pgp") ("pgpmime") ("smime"))
                          nil t nil 'mh-mml-cryptographic-method-history def))
     mh-mml-method-default))
@@ -1731,7 +1721,7 @@ Optional argument DEFAULT is returned if a type isn't 
entered."
          (type (or (and (not (equal probed-type "application/octet-stream"))
                         probed-type)
                    (completing-read
-                    (format "Content type (default %s): " default)
+                    (format-prompt "Content type" default)
                     (mapcar #'list (mailcap-mime-types))))))
     (if (not (equal type ""))
         type
diff --git a/lisp/mh-e/mh-print.el b/lisp/mh-e/mh-print.el
index 513a1bc..d084cf6 100644
--- a/lisp/mh-e/mh-print.el
+++ b/lisp/mh-e/mh-print.el
@@ -1,4 +1,4 @@
-;;; mh-print.el --- MH-E printing support
+;;; mh-print.el --- MH-E printing support  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2003-2021 Free Software Foundation, Inc.
 
@@ -207,8 +207,9 @@ Consider using \\[mh-ps-print-msg] instead."
     ;; Print scan listing if we have more than one message.
     (if (> (length msgs) 1)
         (let* ((msgs-string
-                (mapconcat 'identity (mh-list-to-string
-                                      (mh-coalesce-msg-list msgs)) " "))
+                (mapconcat #'identity (mh-list-to-string
+                                       (mh-coalesce-msg-list msgs))
+                           " "))
                (lpr-command
                 (format mh-lpr-command-format
                         (cond ((listp range)
diff --git a/lisp/mh-e/mh-scan.el b/lisp/mh-e/mh-scan.el
index cec3313..f00ab22 100644
--- a/lisp/mh-e/mh-scan.el
+++ b/lisp/mh-e/mh-scan.el
@@ -1,4 +1,4 @@
-;;; mh-scan.el --- MH-E scan line constants and utilities
+;;; mh-scan.el --- MH-E scan line constants and utilities  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1993, 1995, 1997, 2000-2021 Free Software Foundation,
 ;; Inc.
@@ -497,7 +497,7 @@ with `mh-scan-msg-format-string'."
         (width 0))
     (with-current-buffer tmp-buffer
       (erase-buffer)
-      (apply 'call-process
+      (apply #'call-process
              (expand-file-name mh-scan-prog mh-progs) nil '(t nil) nil
              (list folder "last" "-format" "%(msg)"))
       (goto-char (point-min))
diff --git a/lisp/mh-e/mh-search.el b/lisp/mh-e/mh-search.el
index 05ba12d..aece03e 100644
--- a/lisp/mh-e/mh-search.el
+++ b/lisp/mh-e/mh-search.el
@@ -1,4 +1,4 @@
-;;; mh-search  ---  MH-Search mode
+;;; mh-search  ---  MH-Search mode  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1993, 1995, 2001-2021 Free Software Foundation, Inc.
 
@@ -332,7 +332,7 @@ configuration and is used when the search folder is 
dismissed."
   (interactive (list (mh-prompt-for-folder "Search" mh-current-folder nil nil 
t)
                      (current-window-configuration)))
   ;; FIXME: `pick-folder' is unused!
-  (let ((pick-folder (if (equal folder "+") mh-current-folder folder)))
+  (let () ;; (pick-folder (if (equal folder "+") mh-current-folder folder))
     (switch-to-buffer-other-window "search-pattern")
     (if (or (zerop (buffer-size))
             (not (y-or-n-p "Reuse pattern? ")))
@@ -356,7 +356,7 @@ configuration and is used when the search folder is 
dismissed."
           "---------\n")
   (mh-search-mode)
   (goto-char (point-min))
-  (dotimes (i 5)
+  (dotimes (_ 5)
     (add-text-properties (point) (1+ (point)) '(front-sticky t))
     (add-text-properties (- (mh-line-end-position) 2)
                          (1- (mh-line-end-position))
@@ -453,7 +453,7 @@ search all folders."
 
 (defvar mh-flists-search-folders)
 
-(defun mh-flists-execute (&rest ignored)
+(defun mh-flists-execute (&rest _ignored)
   "Execute flists.
 Search for messages belonging to `mh-flists-sequence' in the
 folders specified by `mh-flists-search-folders'. If
@@ -880,7 +880,7 @@ used to search."
               folder-path
             (format "%s/" folder-path)))))
 
-(defalias 'mh-swish++-next-result 'mh-swish-next-result)
+(defalias 'mh-swish++-next-result #'mh-swish-next-result)
 
 (defun mh-swish++-regexp-builder (regexp-list)
   "Generate query for swish++.
@@ -1853,7 +1853,7 @@ PROC is used to convert the value to actual data."
                                     (1+ last-slash) (1- last-space)))
                  (buffer-substring-no-properties (1+ last-space) end))))))
 
-(defalias 'mh-md5-parser 'mh-openssl-parser)
+(defalias 'mh-md5-parser #'mh-openssl-parser)
 
 ;;;###mh-autoload
 (defun mh-index-update-maps (folder &optional origin-map)
diff --git a/lisp/mh-e/mh-seq.el b/lisp/mh-e/mh-seq.el
index e8a03f6..9b9675c 100644
--- a/lisp/mh-e/mh-seq.el
+++ b/lisp/mh-e/mh-seq.el
@@ -1,4 +1,4 @@
-;;; mh-seq.el --- MH-E sequences support
+;;; mh-seq.el --- MH-E sequences support  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1993, 1995, 2001-2021 Free Software Foundation, Inc.
 
@@ -156,7 +156,7 @@ The list appears in a buffer named \"*MH-E Sequences*\"."
           (let ((name (mh-seq-name (car seq-list)))
                 (sorted-seq-msgs
                  (mh-coalesce-msg-list
-                  (sort (copy-sequence (mh-seq-msgs (car seq-list))) '<)))
+                  (sort (copy-sequence (mh-seq-msgs (car seq-list))) #'<)))
                 name-spec)
             (insert (setq name-spec (format (format "%%%ss:" max-len) name)))
             (while sorted-seq-msgs
@@ -191,7 +191,7 @@ MESSAGE appears."
              (cond (dest-folder (format " (to be refiled to %s)" dest-folder))
                    (deleted-flag (format " (to be deleted)"))
                    (t ""))
-             (mapconcat 'concat
+             (mapconcat #'concat
                         (mh-list-to-string (mh-seq-containing-msg message t))
                         " "))))
 
@@ -390,10 +390,7 @@ Prompt with PROMPT, raise an error if the sequence is 
empty and
 the NOT-EMPTY flag is non-nil, and supply an optional DEFAULT
 sequence. A reply of `%' defaults to the first sequence
 containing the current message."
-  (let* ((input (completing-read (format "%s sequence%s: " prompt
-                                         (if default
-                                             (format " (default %s)" default)
-                                           ""))
+  (let* ((input (completing-read (format-prompt "%s sequence" default prompt)
                                  (mh-seq-names mh-seq-list)
                                  nil nil nil 'mh-sequence-history))
          (seq (cond ((equal input "%")
@@ -494,13 +491,13 @@ folder buffer are not updated."
   ;; Add to a SEQUENCE each message the list of MSGS.
   (if (and (mh-valid-seq-p seq) (not (mh-folder-name-p seq)))
       (if msgs
-          (apply 'mh-exec-cmd "mark" mh-current-folder "-add"
+          (apply #'mh-exec-cmd "mark" mh-current-folder "-add"
                  "-sequence" (symbol-name seq)
                  (mh-coalesce-msg-list msgs)))))
 
 (defun mh-canonicalize-sequence (msgs)
   "Sort MSGS in decreasing order and remove duplicates."
-  (let* ((sorted-msgs (sort (copy-sequence msgs) '>))
+  (let* ((sorted-msgs (sort (copy-sequence msgs) #'>))
          (head sorted-msgs))
     (while (cdr head)
       (if (= (car head) (cadr head))
@@ -565,7 +562,7 @@ OP is one of `widen' and `unthread'."
 (defvar mh-range-seq-names)
 (defvar mh-range-history ())
 (defvar mh-range-completion-map (copy-keymap minibuffer-local-completion-map))
-(define-key mh-range-completion-map " " 'self-insert-command)
+(define-key mh-range-completion-map " " #'self-insert-command)
 
 ;;;###mh-autoload
 (defun mh-interactive-range (range-prompt &optional default)
@@ -646,13 +643,10 @@ should be replaced with:
                         ((stringp default) default)
                         ((symbolp default) (symbol-name default))))
          (prompt (cond ((and guess large default)
-                        (format "%s (folder has %s messages, default %s)"
-                                prompt (car counts) default))
-                       ((and guess large)
-                        (format "%s (folder has %s messages)"
-                                prompt (car counts)))
+                        (format-prompt "%s (folder has %s messages)"
+                                default prompt (car counts)))
                        (default
-                         (format "%s (default %s)" prompt default))))
+                         (format-prompt prompt default))))
          (minibuffer-local-completion-map mh-range-completion-map)
          (seq-list (if (eq folder mh-current-folder)
                        mh-seq-list
@@ -662,7 +656,7 @@ should be replaced with:
                   (mh-seq-names seq-list)))
          (input (cond ((and (not ask-flag) unseen) (symbol-name mh-unseen-seq))
                       ((and (not ask-flag) (not large)) "all")
-                      (t (completing-read (format "%s: " prompt)
+                      (t (completing-read prompt
                                           'mh-range-completion-function nil nil
                                           nil 'mh-range-history default))))
          msg-list)
diff --git a/lisp/mh-e/mh-show.el b/lisp/mh-e/mh-show.el
index 1d25b14..cb9819f 100644
--- a/lisp/mh-e/mh-show.el
+++ b/lisp/mh-e/mh-show.el
@@ -1,4 +1,4 @@
-;;; mh-show.el --- MH-Show mode
+;;; mh-show.el --- MH-Show mode  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1993, 1995, 1997, 2000-2021 Free Software Foundation,
 ;; Inc.
@@ -195,7 +195,7 @@ Sets the current buffer to the show buffer."
     (let ((formfile mh-mhl-format-file)
           (clean-message-header mh-clean-message-header-flag)
           (invisible-headers mh-invisible-header-fields-compiled)
-          (visible-headers nil)
+          ;; (visible-headers nil)
           (msg-filename (mh-msg-filename msg-num folder-name))
           (show-buffer mh-show-buffer)
           (mm-inline-media-tests mh-mm-inline-media-tests))
@@ -241,7 +241,7 @@ Sets the current buffer to the show buffer."
              (cond (clean-message-header
                     (mh-clean-msg-header (point-min)
                                          invisible-headers
-                                         visible-headers)
+                                         nil) ;; visible-headers
                     (goto-char (point-min)))
                    (t
                     (mh-start-of-uncleaned-message)))
@@ -862,7 +862,7 @@ See also `mh-folder-mode'.
       (turn-on-font-lock))
   (when mh-decode-mime-flag
     (mh-make-local-hook 'kill-buffer-hook)
-    (add-hook 'kill-buffer-hook 'mh-mime-cleanup nil t))
+    (add-hook 'kill-buffer-hook #'mh-mime-cleanup nil t))
   (mh-do-in-xemacs
     (easy-menu-add mh-show-sequence-menu)
     (easy-menu-add mh-show-message-menu)
diff --git a/lisp/mh-e/mh-speed.el b/lisp/mh-e/mh-speed.el
index 7cbd42c..b2deacf 100644
--- a/lisp/mh-e/mh-speed.el
+++ b/lisp/mh-e/mh-speed.el
@@ -1,4 +1,4 @@
-;;; mh-speed.el --- MH-E speedbar support
+;;; mh-speed.el --- MH-E speedbar support  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2002-2021 Free Software Foundation, Inc.
 
@@ -100,9 +100,9 @@
 
 ;; Alphabetical.
 
-(defalias 'mh-speed-contract-folder 'mh-speed-toggle)
+(defalias 'mh-speed-contract-folder #'mh-speed-toggle)
 
-(defalias 'mh-speed-expand-folder 'mh-speed-toggle)
+(defalias 'mh-speed-expand-folder #'mh-speed-toggle)
 
 (defun mh-speed-refresh ()
   "Regenerates the list of folders in the speedbar.
@@ -202,9 +202,9 @@ created."
       (mh-speed-flists nil))))
 
 ;;;###mh-autoload
-(defalias 'mh-show-speedbar-buttons 'mh-folder-speedbar-buttons)
+(defalias 'mh-show-speedbar-buttons #'mh-folder-speedbar-buttons)
 ;;;###mh-autoload
-(defalias 'mh-letter-speedbar-buttons 'mh-folder-speedbar-buttons)
+(defalias 'mh-letter-speedbar-buttons #'mh-folder-speedbar-buttons)
 
 (defmacro mh-speed-select-attached-frame ()
   "Compatibility macro to handle speedbar versions 0.11a and 0.14beta4."
@@ -431,7 +431,7 @@ flists is run only for that one folder."
                (setq mh-speed-flists-folder nil)
                (mh-process-kill-without-query mh-speed-flists-process)
                (set-process-filter mh-speed-flists-process
-                                   'mh-speed-parse-flists-output)))))))
+                                   #'mh-speed-parse-flists-output)))))))
 
 ;; Copied from mh-make-folder-list-filter...
 ;; XXX Refactor to use mh-make-folder-list-filer?
diff --git a/lisp/mh-e/mh-thread.el b/lisp/mh-e/mh-thread.el
index 3657462..a7878aa 100644
--- a/lisp/mh-e/mh-thread.el
+++ b/lisp/mh-e/mh-thread.el
@@ -1,4 +1,4 @@
-;;; mh-thread.el --- MH-E threading support
+;;; mh-thread.el --- MH-E threading support  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2002-2004, 2006-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/mh-e/mh-tool-bar.el b/lisp/mh-e/mh-tool-bar.el
index 7dbddbc..40a430b 100644
--- a/lisp/mh-e/mh-tool-bar.el
+++ b/lisp/mh-e/mh-tool-bar.el
@@ -1,4 +1,4 @@
-;;; mh-tool-bar.el --- MH-E tool bar support
+;;; mh-tool-bar.el --- MH-E tool bar support  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2002-2003, 2005-2021 Free Software Foundation, Inc.
 
@@ -356,7 +356,7 @@ Use SEQUENCE-MAP if display is limited; DEFAULT-MAP 
otherwise."
         '(list ,@(mapcar (lambda (x) `(quote ,x)) folder-defaults))
         "List of buttons to include in MH-Folder tool bar."
         :group 'mh-tool-bar
-        :set 'mh-tool-bar-folder-buttons-set
+        :set #'mh-tool-bar-folder-buttons-set
         :type '(set ,@(cl-loop for x in folder-buttons
                                for y in folder-docs
                                collect `(const :tag ,y ,x)))
@@ -367,7 +367,7 @@ Use SEQUENCE-MAP if display is limited; DEFAULT-MAP 
otherwise."
         '(list ,@(mapcar (lambda (x) `(quote ,x)) letter-defaults))
         "List of buttons to include in MH-Letter tool bar."
         :group 'mh-tool-bar
-        :set 'mh-tool-bar-letter-buttons-set
+        :set #'mh-tool-bar-letter-buttons-set
         :type '(set ,@(cl-loop for x in letter-buttons
                                for y in letter-docs
                                collect `(const :tag ,y ,x)))
diff --git a/lisp/mh-e/mh-utils.el b/lisp/mh-e/mh-utils.el
index d7c607d..be66e62 100644
--- a/lisp/mh-e/mh-utils.el
+++ b/lisp/mh-e/mh-utils.el
@@ -1,4 +1,4 @@
-;;; mh-utils.el --- MH-E general utilities
+;;; mh-utils.el --- MH-E general utilities  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1993, 1995, 1997, 2000-2021 Free Software Foundation,
 ;; Inc.
@@ -268,7 +268,7 @@ and displayed in a help buffer."
   (interactive)
   (let* ((help (or help-messages
                   (cdr (assoc nil (assoc major-mode mh-help-messages)))))
-         (text (substitute-command-keys (mapconcat 'identity help ""))))
+         (text (substitute-command-keys (mapconcat #'identity help ""))))
     (with-electric-help
      (lambda ()
        (insert text))
@@ -298,7 +298,7 @@ and displayed in a help buffer."
 This is the inverse of `mh-read-msg-list', which expands ranges.
 Message lists passed to MH programs should be processed by this
 function to avoid exceeding system command line argument limits."
-  (let ((msgs (sort (copy-sequence messages) 'mh-greaterp))
+  (let ((msgs (sort (copy-sequence messages) #'mh-greaterp))
         (range-high nil)
         (prev -1)
         (ranges nil))
@@ -669,7 +669,7 @@ three arguments so we bind this variable to t or nil.
 This variable should never be set.")
 
 (defvar mh-folder-completion-map (copy-keymap minibuffer-local-completion-map))
-(define-key mh-folder-completion-map " " 'minibuffer-complete)  ;Why???
+(define-key mh-folder-completion-map " " #'minibuffer-complete)  ;Why???
 
 (defvar mh-speed-flists-inhibit-flag nil)
 
@@ -730,8 +730,7 @@ See Info node `(elisp) Programmed Completion' for details."
                    (t (file-directory-p path))))))))
 
 ;; Shush compiler.
-(mh-do-in-xemacs
-  (defvar completion-root-regexp))
+(defvar completion-root-regexp) ;; Apparently used in XEmacs
 
 (defun mh-folder-completing-read (prompt default allow-root-folder-flag)
   "Read folder name with PROMPT and default result DEFAULT.
@@ -758,10 +757,9 @@ function will accept the folder +, which means all folders 
when
 used in searching."
   (if (null default)
       (setq default ""))
-  (let* ((default-string (cond (default-string (format " (default %s)" 
default-string))
-                               ((equal "" default) "")
-                               (t (format " (default %s)" default))))
-         (prompt (format "%s folder%s: " prompt default-string))
+  (let* ((default-string (or default-string
+                             (if (equal default "") nil default)))
+         (prompt (format-prompt "%s folder" default-string prompt))
          (mh-current-folder-name mh-current-folder)
          read-name folder-name)
     (while (and (setq read-name (mh-folder-completing-read
@@ -925,10 +923,10 @@ Handle RFC 822 (or later) continuation lines."
 (defvar mh-hidden-header-keymap
   (let ((map (make-sparse-keymap)))
     (mh-do-in-gnu-emacs
-      (define-key map [mouse-2] 'mh-letter-toggle-header-field-display-button))
+      (define-key map [mouse-2] 
#'mh-letter-toggle-header-field-display-button))
     (mh-do-in-xemacs
       (define-key map '(button2)
-        'mh-letter-toggle-header-field-display-button))
+        #'mh-letter-toggle-header-field-display-button))
     map))
 
 ;;;###mh-autoload
diff --git a/lisp/mh-e/mh-xface.el b/lisp/mh-e/mh-xface.el
index 036575a..0b53829 100644
--- a/lisp/mh-e/mh-xface.el
+++ b/lisp/mh-e/mh-xface.el
@@ -1,4 +1,4 @@
-;;; mh-xface.el --- MH-E X-Face and Face header field display
+;;; mh-xface.el --- MH-E X-Face and Face header field display  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2002-2003, 2005-2021 Free Software Foundation, Inc.
 
@@ -365,7 +365,7 @@ Replace the ?/ character with a ?! character and append 
.png.
 Also replaces special characters with `mh-url-hexify-string'
 since not all characters, such as :, are valid within Windows
 filenames.  In addition, replaces * with %2a. See URL
-`http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/ifaces/iitemnamelimits/GetValidCharacters.asp'."
+`https://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/ifaces/iitemnamelimits/GetValidCharacters.asp'."
   (format "%s/%s.png" mh-x-image-cache-directory
           (mh-replace-regexp-in-string
            "\\*" "%2a"
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 55825e3..5f59467 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -3941,13 +3941,15 @@ it.  See `format' for details.
 If DEFAULT is a list, the first element is used as the default.
 If not, the element is used as is.
 
-If DEFAULT is nil, no \"default value\" string is included in the
-return value."
+If DEFAULT is nil or an empty string, no \"default value\" string
+is included in the return value."
   (concat
    (if (null format-args)
        prompt
      (apply #'format prompt format-args))
    (and default
+        (or (not (stringp default))
+            (length> default 0))
         (format minibuffer-default-prompt-format
                 (if (consp default)
                     (car default)
diff --git a/lisp/mpc.el b/lisp/mpc.el
index 827f8aa..315d8c0 100644
--- a/lisp/mpc.el
+++ b/lisp/mpc.el
@@ -129,12 +129,10 @@
   "Return L1 after removing all elements not found in L2.
 If SELECTFUN is non-nil, elements aren't compared directly, but instead
 they are passed through SELECTFUN before comparison."
-  (let ((res ()))
-    (if selectfun (setq l2 (mapcar selectfun l2)))
-    (dolist (elem l1)
-      (when (member (if selectfun (funcall selectfun elem) elem) l2)
-        (push elem res)))
-    (nreverse res)))
+  (when selectfun
+    (setq l1 (mapcar selectfun l1))
+    (setq l2 (mapcar selectfun l2)))
+  (seq-intersection l1 l2))
 
 (defun mpc-event-set-point (event)
   (condition-case nil (posn-set-point (event-end event))
@@ -698,7 +696,7 @@ The songs are returned as alists."
               (let* ((osongs (mpc-cmd-find other-tag value))
                      (ofiles (mpc-assq-all 'file (apply 'append osongs)))
                      (plfiles (mpc-assq-all 'file (apply 'append plsongs))))
-                (when (mpc-intersection plfiles ofiles)
+                (when (seq-intersection plfiles ofiles)
                   (push pl pls)))))))
       pls))
 
@@ -1669,7 +1667,7 @@ Return non-nil if a selection was deactivated."
                                      (mpc-cmd-list mpc-tag (car cst) val))
                                    (cdr cst)))))
           (setq active
-                (if (listp active) (mpc-intersection active vals) vals))))
+                (if (listp active) (seq-intersection active vals) vals))))
 
       (when (listp active)
         ;; Remove the selections if they are all in conflict with
diff --git a/lisp/net/dbus.el b/lisp/net/dbus.el
index 1e7f836..4116d29 100644
--- a/lisp/net/dbus.el
+++ b/lisp/net/dbus.el
@@ -2029,8 +2029,9 @@ either a method name, a signal name, or an error name."
            ",")
           rule (or rule ""))
 
-    (unless (ignore-errors (dbus-get-unique-name bus-private))
-      (dbus-init-bus bus 'private))
+    (when (fboundp 'dbus-get-unique-name)
+      (unless (ignore-errors (dbus-get-unique-name bus-private))
+        (dbus-init-bus bus 'private)))
     (dbus-call-method
      bus-private dbus-service-dbus dbus-path-dbus dbus-interface-monitoring
      "BecomeMonitor" `(:array :string ,rule) :uint32 0)
diff --git a/lisp/net/gnutls.el b/lisp/net/gnutls.el
index 9c7bcdc..43dd9dc 100644
--- a/lisp/net/gnutls.el
+++ b/lisp/net/gnutls.el
@@ -4,7 +4,7 @@
 
 ;; Author: Ted Zlatanov <tzz@lifelogs.com>
 ;; Keywords: comm, tls, ssl, encryption
-;; Originally-By: Simon Josefsson (See http://josefsson.org/emacs-security/)
+;; Originally-By: Simon Josefsson (See https://josefsson.org/emacs-security/)
 ;; Thanks-To: Lars Magne Ingebrigtsen <larsi@gnus.org>
 
 ;; This file is part of GNU Emacs.
@@ -336,8 +336,8 @@ defaults to GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT."
                              t)
                             ;; if a list, look for hostname matches
                             ((listp gnutls-verify-error)
-                             (cadr (cl-find-if #'(lambda (x)
-                                                   (string-match (car x) 
hostname))
+                             (cadr (cl-find-if (lambda (x)
+                                                 (string-match (car x) 
hostname))
                                                gnutls-verify-error)))
                             ;; else it's nil
                             (t nil))))
diff --git a/lisp/net/imap.el b/lisp/net/imap.el
index 052ef29..d29584e 100644
--- a/lisp/net/imap.el
+++ b/lisp/net/imap.el
@@ -737,9 +737,9 @@ sure of changing the value of `foo'."
                    :end-of-command "\r\n"
                    :success "^1 OK "
                    :starttls-function
-                   #'(lambda (capabilities)
-                       (when (string-match-p "STARTTLS" capabilities)
-                         "1 STARTTLS\r\n"))))
+                   (lambda (capabilities)
+                     (when (string-match-p "STARTTLS" capabilities)
+                       "1 STARTTLS\r\n"))))
          done)
     (when process
       (imap-log buffer)
diff --git a/lisp/net/newst-backend.el b/lisp/net/newst-backend.el
index c548865..e623dab 100644
--- a/lisp/net/newst-backend.el
+++ b/lisp/net/newst-backend.el
@@ -67,9 +67,9 @@ considered to be running if the newsticker timer list is not 
empty."
 ;; Hard-coding URLs like this is a recipe for propagating obsolete info.
 (defconst newsticker--raw-url-list-defaults
   '(("Debian Security Advisories"
-     "http://www.debian.org/security/dsa.en.rdf";)
+     "https://www.debian.org/security/dsa.en.rdf";)
     ("Debian Security Advisories - Long format"
-     "http://www.debian.org/security/dsa-long.en.rdf";)
+     "https://www.debian.org/security/dsa-long.en.rdf";)
     ("Emacs Wiki"
      "https://www.emacswiki.org/emacs?action=rss";
      nil
@@ -77,7 +77,7 @@ considered to be running if the newsticker timer list is not 
empty."
     ("LWN (Linux Weekly News)"
      "https://lwn.net/headlines/rss";)
     ("Quote of the day"
-     "http://feeds.feedburner.com/quotationspage/qotd";
+     "https://feeds.feedburner.com/quotationspage/qotd";
      "07:00"
      86400)
     ("The Register"
@@ -1012,7 +1012,7 @@ Argument BUFFER is the buffer of the retrieval process."
   ;; And another one (20050702)! If description is HTML
   ;; encoded and starts with a `<', wrap the whole
   ;; description in a CDATA expression.  This happened for
-  ;; http://www.thefreedictionary.com/_/WoD/rss.aspx?type=quote
+  ;; https://www.thefreedictionary.com/_/WoD/rss.aspx?type=quote
   (goto-char (point-min))
   (while (re-search-forward
           "<description>\\(<img.*?\\)</description>" nil t)
@@ -1176,7 +1176,7 @@ URL 
`http://www.atompub.org/2005/08/17/draft-ietf-atompub-format-11.html'"
                       ;; unxml the content or the summary node. Atom
                       ;; allows for integrating (x)html into the atom
                       ;; structure but we need the raw html string.
-                      ;; e.g. http://www.heise.de/open/news/news-atom.xml
+                      ;; e.g. https://www.heise.de/open/news/news-atom.xml
                       ;; http://feeds.feedburner.com/ru_nix_blogs
                       (or (newsticker--unxml
                            (car (xml-node-children
@@ -1680,6 +1680,7 @@ Sat, 07 Sep 2002 00:00:01 GMT
              nil))))
     nil))
 
+;; FIXME: Can this be replaced by seq-intersection?
 (defun newsticker--lists-intersect-p (list1 list2)
   "Return t if LIST1 and LIST2 share elements."
   (let ((result nil))
diff --git a/lisp/net/newst-plainview.el b/lisp/net/newst-plainview.el
index 705bff6..420cf82 100644
--- a/lisp/net/newst-plainview.el
+++ b/lisp/net/newst-plainview.el
@@ -4,7 +4,7 @@
 
 ;; Author:      Ulf Jasper <ulf.jasper@web.de>
 ;; Filename:    newst-plainview.el
-;; URL:         http://www.nongnu.org/newsticker
+;; URL:         https://www.nongnu.org/newsticker
 ;; Package:     newsticker
 
 ;; ======================================================================
@@ -273,6 +273,7 @@ images."
 
 (defvar newsticker--plainview-tool-bar-map
   (when (boundp 'tool-bar-map)
+    (defvar tool-bar-map)
     (let ((tool-bar-map (make-sparse-keymap)))
       (tool-bar-add-item "newsticker/prev-feed"
                          'newsticker-previous-feed
diff --git a/lisp/net/newst-treeview.el b/lisp/net/newst-treeview.el
index d778cc1..d524e6d 100644
--- a/lisp/net/newst-treeview.el
+++ b/lisp/net/newst-treeview.el
@@ -31,10 +31,6 @@
 ;; See newsticker.el
 
 ;; ======================================================================
-;;; History:
-;;
-
-;; ======================================================================
 ;;; Code:
 (require 'cl-lib)
 (require 'newst-reader)
@@ -1102,6 +1098,7 @@ Arguments are ignored."
 ;; ======================================================================
 (defvar newsticker-treeview-tool-bar-map
   (when (boundp 'tool-bar-map)
+    (defvar tool-bar-map)
     (let ((tool-bar-map (make-sparse-keymap)))
       (tool-bar-add-item "newsticker/prev-feed"
                          'newsticker-treeview-prev-feed
diff --git a/lisp/net/nsm.el b/lisp/net/nsm.el
index 0ce65a3..1d9ee6d 100644
--- a/lisp/net/nsm.el
+++ b/lisp/net/nsm.el
@@ -640,7 +640,7 @@ References:
 
 [1]: Sotirov A, Stevens M et al (2008).  \"MD5 considered harmful today
 - Creating a rogue CA certificate\",
-`http://www.win.tue.nl/hashclash/rogue-ca/'
+`https://www.win.tue.nl/hashclash/rogue-ca/'
 [2]: Turner S, Chen L (2011).  \"Updated Security Considerations for
 the MD5 Message-Digest and the HMAC-MD5 Algorithms\",
 `https://tools.ietf.org/html/rfc6151'"
diff --git a/lisp/net/pop3.el b/lisp/net/pop3.el
index dcac36f..cb49f75 100644
--- a/lisp/net/pop3.el
+++ b/lisp/net/pop3.el
@@ -725,9 +725,9 @@ Otherwise, return the size of the message-id MSG."
          (setq pop3-read-point (point-marker))
          (goto-char (match-beginning 0))
          (setq end (point-marker))
-         (mapcar #'(lambda (s) (let ((split (split-string s " ")))
-                                 (cons (string-to-number (nth 0 split))
-                                       (string-to-number (nth 1 split)))))
+          (mapcar (lambda (s) (let ((split (split-string s " ")))
+                           (cons (string-to-number (nth 0 split))
+                                 (string-to-number (nth 1 split)))))
                  (split-string (buffer-substring start end) "\r\n" t)))))))
 
 (defun pop3-retr (process msg crashbuf)
diff --git a/lisp/net/tramp-integration.el b/lisp/net/tramp-integration.el
index 9d4dd7d..2931b4f 100644
--- a/lisp/net/tramp-integration.el
+++ b/lisp/net/tramp-integration.el
@@ -49,6 +49,7 @@
 (defvar recentf-exclude)
 (defvar tramp-current-connection)
 (defvar tramp-postfix-host-format)
+(defvar tramp-use-ssh-controlmaster-options)
 
 ;;; Fontification of `read-file-name':
 
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index 7182cd6..c3e1745 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -2584,12 +2584,9 @@ The method used must be an out-of-band method."
        (save-restriction
          (narrow-to-region beg-marker end-marker)
          ;; Check for "--dired" output.
-         (forward-line -2)
-         (when (looking-at-p "//SUBDIRED//")
-           (forward-line -1))
-         (when (looking-at "//DIRED//\\s-+")
-           (let ((beg (match-end 0))
-                 (end (point-at-eol)))
+         (when (re-search-backward "^//DIRED//\\s-+\\(.+\\)$" nil 'noerror)
+           (let ((beg (match-beginning 1))
+                 (end (match-end 0)))
              ;; Now read the numeric positions of file names.
              (goto-char beg)
              (while (< (point) end)
@@ -2599,7 +2596,7 @@ The method used must be an out-of-band method."
                      ;; End is followed by \n or by " -> ".
                      (put-text-property start end 'dired-filename t))))))
          ;; Remove trailing lines.
-         (goto-char (point-at-bol))
+         (beginning-of-line)
          (while (looking-at "//")
            (forward-line 1)
            (delete-region (match-beginning 0) (point))))
@@ -3654,6 +3651,8 @@ Fall back to normal file name handler if no Tramp handler 
exists."
   (setq file-name (expand-file-name file-name))
   (with-parsed-tramp-file-name file-name nil
     (let ((default-directory (file-name-directory file-name))
+          (process-environment
+           (cons "GIO_USE_FILE_MONITOR=help" process-environment))
          command events filter p sequence)
       (cond
        ;; "inotifywait".
@@ -3686,18 +3685,6 @@ Fall back to normal file name handler if no Tramp 
handler exists."
                '(created changed changes-done-hint moved deleted))
               ((memq 'attribute-change flags) '(attribute-changed)))
              sequence `(,command "monitor" ,localname)))
-       ;; "gvfs-monitor-dir".
-       ((setq command (tramp-get-remote-gvfs-monitor-dir v))
-       (setq filter #'tramp-sh-gvfs-monitor-dir-process-filter
-             events
-             (cond
-              ((and (memq 'change flags) (memq 'attribute-change flags))
-               '(created changed changes-done-hint moved deleted
-                         attribute-changed))
-              ((memq 'change flags)
-               '(created changed changes-done-hint moved deleted))
-              ((memq 'attribute-change flags) '(attribute-changed)))
-             sequence `(,command ,localname)))
        ;; None.
        (t (tramp-error
           v 'file-notify-error
@@ -3730,10 +3717,6 @@ Fall back to normal file name handler if no Tramp 
handler exists."
        (unless (process-live-p p)
          (tramp-error
           p 'file-notify-error "Monitoring not supported for `%s'" file-name))
-       ;; Set "gio-file-monitor" property if needed.
-       (when (string-equal (file-name-nondirectory command) "gio")
-         (tramp-set-connection-property
-          p "gio-file-monitor" (tramp-get-remote-gio-file-monitor v)))
        p))))
 
 (defun tramp-sh-gio-monitor-process-filter (proc string)
@@ -3754,91 +3737,69 @@ Fall back to normal file name handler if no Tramp 
handler exists."
                  "changes done" "changes-done-hint" string)
           string (tramp-compat-string-replace
                  "renamed to" "moved" string))
-    ;; https://bugs.launchpad.net/bugs/1742946
-    (when
-       (string-match-p "Monitoring not supported\\|No locations given" string)
-      (delete-process proc))
-
-    ;; Delete empty lines.
-    (setq string (tramp-compat-string-replace "\n\n" "\n" string))
-
-    (while (string-match
-           (eval-when-compile
-             (concat "^[^:]+:"
-                     "[[:space:]]\\([^:]+\\):"
-                     "[[:space:]]" (regexp-opt tramp-gio-events t)
-                     "\\([[:space:]]\\([^:]+\\)\\)?$"))
-           string)
-
-      (let* ((file (match-string 1 string))
-            (file1 (match-string 4 string))
-            (object
-             (list
-              proc
-              (list
-               (intern-soft (match-string 2 string)))
-              ;; File names are returned as absolute paths.  We must
-              ;; add the remote prefix.
-              (concat remote-prefix file)
-              (when file1 (concat remote-prefix file1)))))
-       (setq string (replace-match "" nil nil string))
-       ;; Usually, we would add an Emacs event now.  Unfortunately,
-       ;; `unread-command-events' does not accept several events at
-       ;; once.  Therefore, we apply the handler directly.
-       (when (member (cl-caadr object) events)
-         (tramp-compat-funcall
-          (lookup-key special-event-map [file-notify])
-          `(file-notify ,object file-notify-callback)))))
 
-    ;; Save rest of the string.
-    (when (zerop (length string)) (setq string nil))
-    (when string (tramp-message proc 10 "Rest string:\n%s" string))
-    (process-put proc 'rest-string string)))
-
-(defun tramp-sh-gvfs-monitor-dir-process-filter (proc string)
-  "Read output from \"gvfs-monitor-dir\" and add corresponding \
-`file-notify' events."
-  (let ((events (process-get proc 'events))
-       (remote-prefix
-        (with-current-buffer (process-buffer proc)
-          (file-remote-p default-directory)))
-       (rest-string (process-get proc 'rest-string)))
-    (when rest-string
-      (tramp-message proc 10 "Previous string:\n%s" rest-string))
-    (tramp-message proc 6 "%S\n%s" proc string)
-    (setq string (concat rest-string string)
-         ;; Attribute change is returned in unused wording.
-         string (tramp-compat-string-replace
-                 "ATTRIB CHANGED" "ATTRIBUTE_CHANGED" string))
-
-    (while (string-match
-           (concat "^[\n\r]*"
-                   "Directory Monitor Event:[\n\r]+"
-                   "Child = \\([^\n\r]+\\)[\n\r]+"
-                   "\\(Other = \\([^\n\r]+\\)[\n\r]+\\)?"
-                   "Event = \\([^[:blank:]]+\\)[\n\r]+")
-           string)
-      (let* ((file (match-string 1 string))
-            (file1 (match-string 3 string))
-            (object
-             (list
-              proc
-              (list
-               (intern-soft
-                (tramp-compat-string-replace
-                 "_" "-" (downcase (match-string 4 string)))))
-              ;; File names are returned as absolute paths.  We must
-              ;; add the remote prefix.
-              (concat remote-prefix file)
-              (when file1 (concat remote-prefix file1)))))
-       (setq string (replace-match "" nil nil string))
-       ;; Usually, we would add an Emacs event now.  Unfortunately,
-       ;; `unread-command-events' does not accept several events at
-       ;; once.  Therefore, we apply the handler directly.
-       (when (member (cl-caadr object) events)
-         (tramp-compat-funcall
-          (lookup-key special-event-map [file-notify])
-          `(file-notify ,object file-notify-callback)))))
+    (catch 'doesnt-work
+      ;; https://bugs.launchpad.net/bugs/1742946
+      (when
+          (string-match-p "Monitoring not supported\\|No locations given" 
string)
+        (delete-process proc)
+        (throw 'doesnt-work nil))
+
+      ;; Determine monitor name.
+      (unless (tramp-connection-property-p proc "gio-file-monitor")
+        (cond
+         ;; We have seen this on cygwin gio and on emba.  Let's make some 
assumptions.
+         ((string-match
+           "Can't find module 'help' specified in GIO_USE_FILE_MONITOR" string)
+          (cond
+           ((getenv "EMACS_EMBA_CI")
+            (tramp-set-connection-property
+             proc "gio-file-monitor" 'GInotifyFileMonitor))
+           ((eq system-type 'cygwin)
+            (tramp-set-connection-property
+             proc "gio-file-monitor" 'GPollFileMonitor))
+           (t (tramp-error proc 'file-error "Cannot determine gio monitor"))))
+         ;; TODO: What happens, if several monitor names are reported?
+         ((string-match "\
+Supported arguments for GIO_USE_FILE_MONITOR environment variable:
+\\s-*\\([[:alpha:]]+\\) - 20" string)
+          (tramp-set-connection-property
+           proc "gio-file-monitor"
+           (intern
+            (format "G%sFileMonitor" (capitalize (match-string 1 string))))))
+         (t (throw 'doesnt-work nil)))
+        (setq string (replace-match "" nil nil string)))
+
+      ;; Delete empty lines.
+      (setq string (tramp-compat-string-replace "\n\n" "\n" string))
+
+      (while (string-match
+             (eval-when-compile
+               (concat "^[^:]+:"
+                       "[[:space:]]\\([^:]+\\):"
+                       "[[:space:]]" (regexp-opt tramp-gio-events t)
+                       "\\([[:space:]]\\([^:]+\\)\\)?$"))
+             string)
+
+        (let* ((file (match-string 1 string))
+              (file1 (match-string 4 string))
+              (object
+               (list
+                proc
+                (list
+                 (intern-soft (match-string 2 string)))
+                ;; File names are returned as absolute paths.  We
+                ;; must add the remote prefix.
+                (concat remote-prefix file)
+                (when file1 (concat remote-prefix file1)))))
+         (setq string (replace-match "" nil nil string))
+         ;; Usually, we would add an Emacs event now.  Unfortunately,
+         ;; `unread-command-events' does not accept several events at
+         ;; once.  Therefore, we apply the handler directly.
+         (when (member (cl-caadr object) events)
+           (tramp-compat-funcall
+            (lookup-key special-event-map [file-notify])
+            `(file-notify ,object file-notify-callback))))))
 
     ;; Save rest of the string.
     (when (zerop (length string)) (setq string nil))
@@ -5647,42 +5608,6 @@ This command is returned only if 
`delete-by-moving-to-trash' is non-nil."
     (tramp-message vec 5 "Finding a suitable `gio-monitor' command")
     (tramp-find-executable vec "gio" (tramp-get-remote-path vec) t t)))
 
-(defun tramp-get-remote-gio-file-monitor (vec)
-  "Determine remote GFileMonitor."
-  (with-tramp-connection-property vec "gio-file-monitor"
-    (with-current-buffer (tramp-get-connection-buffer vec)
-      (tramp-message vec 5 "Finding the used GFileMonitor")
-      (when-let ((gio (tramp-get-remote-gio-monitor vec)))
-       ;; Search for the used FileMonitor.  There is no known way to
-       ;; get this information directly from gio, so we check for
-       ;; linked libraries of libgio.
-       (when (tramp-send-command-and-check vec (concat "ldd " gio))
-         (goto-char (point-min))
-         (when (re-search-forward "\\S-+/libgio\\S-+")
-           (when (tramp-send-command-and-check
-                  vec (concat "strings " (match-string 0)))
-             (goto-char (point-min))
-             (re-search-forward
-              (format
-               "^%s$"
-               (regexp-opt
-                '("GFamFileMonitor" "GFenFileMonitor"
-                  "GInotifyFileMonitor" "GKqueueFileMonitor")))
-              nil 'noerror)
-             (intern (match-string 0)))))))))
-
-(defun tramp-get-remote-gvfs-monitor-dir (vec)
-  "Determine remote `gvfs-monitor-dir' command."
-  (with-tramp-connection-property vec "gvfs-monitor-dir"
-    (tramp-message vec 5 "Finding a suitable `gvfs-monitor-dir' command")
-    ;; We distinguish "gvfs-monitor-dir.exe" from cygwin in order to
-    ;; establish better timeouts in filenotify-tests.el.  Any better
-    ;; distinction approach would be welcome!
-    (or (tramp-find-executable
-        vec "gvfs-monitor-dir.exe" (tramp-get-remote-path vec) t t)
-       (tramp-find-executable
-        vec "gvfs-monitor-dir" (tramp-get-remote-path vec) t t))))
-
 (defun tramp-get-remote-inotifywait (vec)
   "Determine remote `inotifywait' command."
   (with-tramp-connection-property vec "inotifywait"
diff --git a/lisp/notifications.el b/lisp/notifications.el
index 2241afa..b439d82 100644
--- a/lisp/notifications.el
+++ b/lisp/notifications.el
@@ -1,4 +1,4 @@
-;;; notifications.el --- Client interface to desktop notifications.
+;;; notifications.el --- Client interface to desktop notifications.  -*- 
lexical-binding: t -*-
 
 ;; Copyright (C) 2010-2021 Free Software Foundation, Inc.
 
@@ -229,56 +229,69 @@ of another `notifications-notify' call."
          id)
       ;; Build hints array
       (when urgency
-       (add-to-list 'hints `(:dict-entry
-                             "urgency"
-                             (:variant :byte ,(pcase urgency
-                                                ('low 0)
-                                                ('critical 2)
-                                                (_ 1)))) t))
+        (push `(:dict-entry
+                "urgency"
+                (:variant :byte ,(pcase urgency
+                                   ('low 0)
+                                   ('critical 2)
+                                   (_ 1))))
+              hints))
       (when category
-       (add-to-list 'hints `(:dict-entry
-                             "category"
-                             (:variant :string ,category)) t))
+        (push `(:dict-entry
+                "category"
+                (:variant :string ,category))
+              hints))
       (when desktop-entry
-       (add-to-list 'hints `(:dict-entry
-                             "desktop-entry"
-                             (:variant :string ,desktop-entry)) t))
+        (push `(:dict-entry
+                "desktop-entry"
+                (:variant :string ,desktop-entry))
+              hints))
       (when image-data
-       (add-to-list 'hints `(:dict-entry
-                             "image-data"
-                             (:variant :struct ,image-data)) t))
+        (push `(:dict-entry
+                "image-data"
+                (:variant :struct ,image-data))
+              hints))
       (when image-path
-       (add-to-list 'hints `(:dict-entry
-                             "image-path"
-                             (:variant :string ,image-path)) t))
+        (push `(:dict-entry
+                "image-path"
+                (:variant :string ,image-path))
+              hints))
       (when action-items
-       (add-to-list 'hints `(:dict-entry
-                             "action-items"
-                             (:variant :boolean ,action-items)) t))
+        (push `(:dict-entry
+                "action-items"
+                (:variant :boolean ,action-items))
+              hints))
       (when sound-file
-       (add-to-list 'hints `(:dict-entry
-                             "sound-file"
-                             (:variant :string ,sound-file)) t))
+        (push `(:dict-entry
+                "sound-file"
+                (:variant :string ,sound-file))
+              hints))
       (when sound-name
-       (add-to-list 'hints `(:dict-entry
-                             "sound-name"
-                             (:variant :string ,sound-name)) t))
+        (push `(:dict-entry
+                "sound-name"
+                (:variant :string ,sound-name))
+              hints))
       (when suppress-sound
-       (add-to-list 'hints `(:dict-entry
-                             "suppress-sound"
-                             (:variant :boolean ,suppress-sound)) t))
+        (push `(:dict-entry
+                "suppress-sound"
+                (:variant :boolean ,suppress-sound))
+              hints))
       (when resident
-       (add-to-list 'hints `(:dict-entry
-                             "resident"
-                             (:variant :boolean ,resident)) t))
+        (push `(:dict-entry
+                "resident"
+                (:variant :boolean ,resident))
+              hints))
       (when transient
-       (add-to-list 'hints `(:dict-entry
-                             "transient"
-                             (:variant :boolean ,transient)) t))
+        (push `(:dict-entry
+                "transient"
+                (:variant :boolean ,transient))
+              hints))
       (when x
-       (add-to-list 'hints `(:dict-entry "x" (:variant :int32 ,x)) t))
+        (push `(:dict-entry "x" (:variant :int32 ,x)) hints))
       (when y
-       (add-to-list 'hints `(:dict-entry "y" (:variant :int32 ,y)) t))
+        (push `(:dict-entry "y" (:variant :int32 ,y)) hints))
+
+      (setq hints (nreverse hints))
 
       ;; Call Notify method.
       (setq id
@@ -313,8 +326,8 @@ of another `notifications-notify' call."
            (on-close (plist-get params :on-close))
            (unique-name (dbus-get-name-owner bus notifications-service)))
        (when on-action
-         (add-to-list 'notifications-on-action-map
-                      (list (list bus unique-name id) on-action))
+          (push (list (list bus unique-name id) on-action)
+                notifications-on-action-map)
          (unless notifications-on-action-object
            (setq notifications-on-action-object
                  (dbus-register-signal
@@ -326,8 +339,8 @@ of another `notifications-notify' call."
                   'notifications-on-action-signal))))
 
        (when on-close
-         (add-to-list 'notifications-on-close-map
-                      (list (list bus unique-name id) on-close))
+          (push (list (list bus unique-name id) on-close)
+                notifications-on-close-map)
          (unless notifications-on-close-object
            (setq notifications-on-close-object
                  (dbus-register-signal
diff --git a/lisp/nxml/rng-cmpct.el b/lisp/nxml/rng-cmpct.el
index 45a69a7..3d4b9f8 100644
--- a/lisp/nxml/rng-cmpct.el
+++ b/lisp/nxml/rng-cmpct.el
@@ -26,7 +26,7 @@
 ;; specified in rng-pttrn.el.
 ;;
 ;; RELAX NG Compact Syntax is specified by
-;;    http://relaxng.org/compact.html
+;;    https://relaxng.org/compact.html
 ;;
 ;; This file uses the prefix "rng-c-".
 
diff --git a/lisp/nxml/rng-loc.el b/lisp/nxml/rng-loc.el
index d5a608d..a38da79 100644
--- a/lisp/nxml/rng-loc.el
+++ b/lisp/nxml/rng-loc.el
@@ -182,7 +182,7 @@ If TYPE-ID is non-nil, then locate the schema for this 
TYPE-ID."
     (while files
       (setq type-ids (rng-possible-type-ids-using (car files) type-ids))
       (setq files (cdr files)))
-    (rng-uniquify-equal (sort type-ids 'string<))))
+    (seq-uniq (sort type-ids 'string<))))
 
 (defun rng-locate-schema-file-using (files)
   "Locate a schema using the schema locating files FILES.
diff --git a/lisp/nxml/rng-match.el b/lisp/nxml/rng-match.el
index 4fc6727..7a2739c 100644
--- a/lisp/nxml/rng-match.el
+++ b/lisp/nxml/rng-match.el
@@ -472,7 +472,7 @@ list is nullable and whose cdr is the normalized list."
     (cons nullable
          (if sorted
              head
-           (rng-uniquify-eq (sort head 'rng-compare-ipattern))))))
+            (seq-uniq (sort head 'rng-compare-ipattern) #'eq)))))
 
 (defun rng-compare-ipattern (p1 p2)
   (< (rng--ipattern-index p1)
diff --git a/lisp/nxml/rng-nxml.el b/lisp/nxml/rng-nxml.el
index 7ea6fb2..33768a4 100644
--- a/lisp/nxml/rng-nxml.el
+++ b/lisp/nxml/rng-nxml.el
@@ -522,7 +522,7 @@ set `xmltok-dtd'.  Returns the position of the end of the 
token."
          (unless attribute-flag
            (setcdr ns-prefixes (cons nil (cdr ns-prefixes))))))
       (setq iter (cdr iter)))
-    (rng-uniquify-equal
+    (seq-uniq
      (sort (apply #'append
                  (cons extra-strings
                        (mapcar (lambda (name)
diff --git a/lisp/nxml/rng-util.el b/lisp/nxml/rng-util.el
index a20e950..67e2ee9 100644
--- a/lisp/nxml/rng-util.el
+++ b/lisp/nxml/rng-util.el
@@ -36,26 +36,6 @@
 
 (defconst rng-builtin-datatypes-uri (rng-make-datatypes-uri ""))
 
-(defun rng-uniquify-eq (list)
-  "Destructively remove `eq' duplicates from LIST."
-  (and list
-       (let ((head list))
-        (while (cdr head)
-          (if (eq (car head) (cadr head))
-              (setcdr head (cddr head)))
-          (setq head (cdr head)))
-        list)))
-
-(defun rng-uniquify-equal (list)
-  "Destructively remove `equal' duplicates from LIST."
-  (and list
-       (let ((head list))
-        (while (cdr head)
-          (if (equal (car head) (cadr head))
-              (setcdr head (cddr head)))
-          (setq head (cdr head)))
-        list)))
-
 (defun rng-blank-p (str) (string-match "\\`[ \t\n\r]*\\'" str))
 
 (defun rng-substq (new old list)
@@ -104,6 +84,14 @@ LIST is not modified."
 
 (define-error 'rng-error nil)
 
+;; Obsolete.
+
+(defun rng-uniquify-eq (list)
+  (declare (obsolete seq-uniq "28.1"))
+  (seq-uniq list #'eq))
+
+(define-obsolete-function-alias 'rng-uniquify-equal #'seq-uniq "28.1")
+
 (provide 'rng-util)
 
 ;;; rng-util.el ends here
diff --git a/lisp/nxml/rng-xsd.el b/lisp/nxml/rng-xsd.el
index 81314b8..9941aba 100644
--- a/lisp/nxml/rng-xsd.el
+++ b/lisp/nxml/rng-xsd.el
@@ -24,14 +24,14 @@
 
 ;; The main entry point is `rng-xsd-compile'. The validator
 ;; knows to use this for the datatype library with URI
-;; http://www.w3.org/2001/XMLSchema-datatypes because it
+;; https://www.w3.org/2001/XMLSchema-datatypes because it
 ;; is the value of the rng-dt-compile property on that URI
 ;; as a symbol.
 ;;
 ;; W3C XML Schema Datatypes are specified by
-;;   http://www.w3.org/TR/xmlschema-2/
+;;   https://www.w3.org/TR/xmlschema-2/
 ;; Guidelines for using them with RELAX NG are described in
-;;   http://relaxng.org/xsd.html
+;;   https://relaxng.org/xsd.html
 
 ;;; Code:
 
diff --git a/lisp/obsolete/bruce.el b/lisp/obsolete/bruce.el
index 4aa6cd2..1c3581f 100644
--- a/lisp/obsolete/bruce.el
+++ b/lisp/obsolete/bruce.el
@@ -30,7 +30,7 @@
 ;; Decency Act of 1996. This Act bans "indecent speech", whatever that is,
 ;; from the Internet. For more on the CDA, see Richard Stallman's essay on
 ;; censorship, included in the etc directory of emacs distributions 19.34
-;; and up. See also http://www.eff.org/blueribbon.html.
+;; and up. See also https://www.eff.org/blueribbon.html.
 
 ;; For many years, emacs has included a program called Spook. This program
 ;; adds a series of "keywords" to email just before it goes out. On the
diff --git a/lisp/obsolete/inversion.el b/lisp/obsolete/inversion.el
index e61b36c..ac7749a 100644
--- a/lisp/obsolete/inversion.el
+++ b/lisp/obsolete/inversion.el
@@ -454,7 +454,7 @@ If it is a URL, wget will be used for download.
 Optional argument VERSION will restrict the list of available versions
 to the file matching VERSION exactly, or nil."
 ;;DIRECTORY should also allow a URL:
-;; \"http://ftp1.sourceforge.net/PACKAGE\";
+;; \"https://ftp1.sourceforge.net/PACKAGE\";
 ;; but then I can get file listings easily.
   (if (symbolp package) (setq package (symbol-name package)))
   (directory-files directory t
diff --git a/lisp/obsolete/nnir.el b/lisp/obsolete/nnir.el
index fef76ba..f2ea5c6 100644
--- a/lisp/obsolete/nnir.el
+++ b/lisp/obsolete/nnir.el
@@ -274,7 +274,7 @@ that it is for swish++, not Namazu."
   :type '(regexp))
 
 ;; Swish-E.
-;; URL: http://swish-e.org/
+;; URL: http://swish-e.org/ [dead link?]
 ;; Variables `nnir-swish-e-index-files', `nnir-swish-e-program' and
 ;; `nnir-swish-e-additional-switches'
 
@@ -311,7 +311,7 @@ that it is for swish-e, not Namazu.
 This could be a server parameter."
   :type '(regexp))
 
-;; HyREX engine, see <URL:http://ls6-www.cs.uni-dortmund.de/>
+;; HyREX engine, see <URL:http://ls6-www.cs.uni-dortmund.de/> [dead link?]
 
 (defcustom nnir-hyrex-program "nnir-search"
   "Name of the nnir-search executable."
diff --git a/lisp/obsolete/terminal.el b/lisp/obsolete/terminal.el
index d28c4a1..dbfc79b 100644
--- a/lisp/obsolete/terminal.el
+++ b/lisp/obsolete/terminal.el
@@ -32,7 +32,7 @@
 
 ;; For information on US government censorship of the Internet, and
 ;; what you can do to bring back freedom of the press, see the web
-;; site http://www.vtw.org/
+;; site https://www.eff.org/ [used to be vtw.org but that link is dead]
 
 ;;; Code:
 
diff --git a/lisp/obsolete/tpu-extras.el b/lisp/obsolete/tpu-extras.el
index 5d59945..f375e05 100644
--- a/lisp/obsolete/tpu-extras.el
+++ b/lisp/obsolete/tpu-extras.el
@@ -368,34 +368,22 @@ A repeat count means scroll that many sections."
      (and (< (point) top) (recenter (min beg top-margin))))))
 
 ;; Advise the newline, newline-and-indent, and do-auto-fill functions.
-(defadvice newline (around tpu-respect-bottom-scroll-margin activate disable)
+(defun tpu--respect-bottom-scroll-margin (orig-fun &optional &rest args)
   "Respect `tpu-bottom-scroll-margin'."
   (let ((beg (tpu-current-line))
-        (num (prefix-numeric-value (ad-get-arg 0))))
-    ad-do-it
+        (num (prefix-numeric-value (car args))))
+    (apply orig-fun args)
     (tpu-bottom-check beg num)))
 
-(defadvice newline-and-indent (around tpu-respect-bottom-scroll-margin)
-  "Respect `tpu-bottom-scroll-margin'."
-  (let ((beg (tpu-current-line)))
-    ad-do-it
-    (tpu-bottom-check beg 1)))
-
-(defadvice do-auto-fill (around tpu-respect-bottom-scroll-margin)
-  "Respect `tpu-bottom-scroll-margin'."
-  (let ((beg (tpu-current-line)))
-    ad-do-it
-    (tpu-bottom-check beg 1)))
-
-
 ;;;  Function to set scroll margins
 
 ;;;###autoload
-(defun tpu-set-scroll-margins (top bottom)
+(defun tpu-set-scroll-margins (top bottom &optional emit-msg)
   "Set scroll margins."
   (interactive
    "sEnter top scroll margin (N lines or N%% or RETURN for current value): \
-\nsEnter bottom scroll margin (N lines or N%% or RETURN for current value): ")
+\nsEnter bottom scroll margin (N lines or N%% or RETURN for current value): \
+\np")
   ;; set top scroll margin
   (or (string= top "")
       (setq tpu-top-scroll-margin
@@ -411,10 +399,9 @@ A repeat count means scroll that many sections."
              (/ (1- (+ (* (string-to-number bottom) 100) (window-height)))
                 (window-height)))))
   (dolist (f '(newline newline-and-indent do-auto-fill))
-    (ad-enable-advice f 'around 'tpu-respect-bottom-scroll-margin)
-    (ad-activate f))
+    (advice-add f :around #'tpu--respect-bottom-scroll-margin))
   ;; report scroll margin settings if running interactively
-  (and (called-interactively-p 'interactive)
+  (and emit-msg
        (message "Scroll margins set.  Top = %s%%, Bottom = %s%%"
                tpu-top-scroll-margin tpu-bottom-scroll-margin)))
 
diff --git a/lisp/obsolete/vc-arch.el b/lisp/obsolete/vc-arch.el
index 00e7d26..cfbf981 100644
--- a/lisp/obsolete/vc-arch.el
+++ b/lisp/obsolete/vc-arch.el
@@ -26,7 +26,7 @@
 
 ;; The home page of the Arch version control system is at
 ;;
-;;      http://www.gnuarch.org/
+;;      https://www.gnu.org/software/gnu-arch/
 ;;
 ;; This is derived from vc-mcvs.el as follows:
 ;; - cp vc-mcvs.el vc-arch.el and then M-% mcvs RET arch RET
diff --git a/lisp/org/ob-clojure.el b/lisp/org/ob-clojure.el
index df2d691..9834509 100644
--- a/lisp/org/ob-clojure.el
+++ b/lisp/org/ob-clojure.el
@@ -38,7 +38,7 @@
 
 ;; For SLIME, the best way to install these components is by following
 ;; the directions as set out by Phil Hagelberg (Technomancy) on the
-;; web page: http://technomancy.us/126
+;; web page: https://technomancy.us/126
 
 ;;; Code:
 (require 'ob)
diff --git a/lisp/org/ob-ocaml.el b/lisp/org/ob-ocaml.el
index 0aa91af..5fd6d1e 100644
--- a/lisp/org/ob-ocaml.el
+++ b/lisp/org/ob-ocaml.el
@@ -32,7 +32,7 @@
 
 ;;; Requirements:
 
-;; - tuareg-mode :: http://www-rocq.inria.fr/~acohen/tuareg/
+;; - tuareg-mode :: https://www-rocq.inria.fr/~acohen/tuareg/
 
 ;;; Code:
 (require 'ob)
diff --git a/lisp/org/org-install.el b/lisp/org/org-install.el
index 5835959..d521d81 100644
--- a/lisp/org/org-install.el
+++ b/lisp/org/org-install.el
@@ -1,4 +1,4 @@
-;;; org-install.el --- backward compatibility file for obsolete configuration
+;;; org-install.el --- backward compatibility file for obsolete configuration  
-*- lexical-binding: t -*-
 ;;
 ;;; Code:
 ;;
diff --git a/lisp/org/org-macs.el b/lisp/org/org-macs.el
index ac6691d..58d3fd3 100644
--- a/lisp/org/org-macs.el
+++ b/lisp/org/org-macs.el
@@ -869,7 +869,8 @@ delimiting S."
                    (let ((width (plist-get props :width)))
                      (and (wholenump width) width)))
                   (`(image . ,_)
-                   (ceiling (car (image-size spec))))
+                    (and (fboundp 'image-size)
+                         (ceiling (car (image-size spec)))))
                   ((pred stringp)
                    ;; Displayed string could contain invisible parts,
                    ;; but no nested display.
diff --git a/lisp/org/org-version.el b/lisp/org/org-version.el
index 25b3354..8871ef7 100644
--- a/lisp/org/org-version.el
+++ b/lisp/org/org-version.el
@@ -1,4 +1,4 @@
-;;; org-version.el --- autogenerated file, do not edit
+;;; org-version.el --- autogenerated file, do not edit  -*- lexical-binding: t 
-*-
 ;;
 ;;; Code:
 ;;;###autoload
diff --git a/lisp/pcmpl-linux.el b/lisp/pcmpl-linux.el
index 263d646..39d4add 100644
--- a/lisp/pcmpl-linux.el
+++ b/lisp/pcmpl-linux.el
@@ -31,11 +31,6 @@
 
 (require 'pcomplete)
 
-;; Unused.
-;;; (defgroup pcmpl-linux nil
-;;;   "Functions for dealing with GNU/Linux completions."
-;;;   :group 'pcomplete)
-
 ;; Functions:
 
 ;;;###autoload
diff --git a/lisp/pcmpl-x.el b/lisp/pcmpl-x.el
index 084f0e6..fd14710 100644
--- a/lisp/pcmpl-x.el
+++ b/lisp/pcmpl-x.el
@@ -27,7 +27,7 @@
 (require 'pcomplete)
 
 
-;;;; tlmgr - http://www.tug.org/texlive/tlmgr.html
+;;;; tlmgr - https://www.tug.org/texlive/tlmgr.html
 
 (defcustom pcmpl-x-tlmgr-program "tlmgr"
   "Name of the tlmgr program."
diff --git a/lisp/pcomplete.el b/lisp/pcomplete.el
index b648ecf..64acc41 100644
--- a/lisp/pcomplete.el
+++ b/lisp/pcomplete.el
@@ -1260,18 +1260,9 @@ If specific documentation can't be given, be generic."
 
 (defun pcomplete-uniquify-list (l)
   "Sort and remove multiples in L."
-  (setq l (sort l 'string-lessp))
-  (let ((m l))
-    (while m
-      (while (and (cdr m)
-                 (string= (car m)
-                          (cadr m)))
-       (setcdr m (cddr m)))
-      (setq m (cdr m))))
-  l)
-(define-obsolete-function-alias
-  'pcomplete-uniqify-list
-  'pcomplete-uniquify-list "27.1")
+  (setq l (sort l #'string-lessp))
+  (seq-uniq l))
+(define-obsolete-function-alias 'pcomplete-uniqify-list 
#'pcomplete-uniquify-list "27.1")
 
 (defun pcomplete-process-result (cmd &rest args)
   "Call CMD using `call-process' and return the simplest result."
@@ -1320,18 +1311,6 @@ If specific documentation can't be given, be generic."
       (pcomplete-read-hosts pcomplete-hosts-file 'pcomplete--host-name-cache
                    'pcomplete--host-name-cache-timestamp)))
 
-;; create a set of aliases which allow completion functions to be not
-;; quite so verbose
-
-;;; jww (1999-10-20): are these a good idea?
-;; (defalias 'pc-here 'pcomplete-here)
-;; (defalias 'pc-test 'pcomplete-test)
-;; (defalias 'pc-opt 'pcomplete-opt)
-;; (defalias 'pc-match 'pcomplete-match)
-;; (defalias 'pc-match-string 'pcomplete-match-string)
-;; (defalias 'pc-match-beginning 'pcomplete-match-beginning)
-;; (defalias 'pc-match-end 'pcomplete-match-end)
-
 (provide 'pcomplete)
 
 ;;; pcomplete.el ends here
diff --git a/lisp/pixel-scroll.el b/lisp/pixel-scroll.el
index 68dc0fb..78b8259 100644
--- a/lisp/pixel-scroll.el
+++ b/lisp/pixel-scroll.el
@@ -1,4 +1,4 @@
-;;; pixel-scroll.el --- Scroll a line smoothly
+;;; pixel-scroll.el --- Scroll a line smoothly  -*- lexical-binding: t -*-
 
 ;; Copyright (C) 2017-2021 Free Software Foundation, Inc.
 ;; Author: Tak Kunihiro <tkk@misasa.okayama-u.ac.jp>
@@ -124,7 +124,7 @@ This is an alternative of `scroll-up'.  Scope moves 
downward."
   (or arg (setq arg 1))
   (if (pixel-scroll-in-rush-p)
       (scroll-up arg)
-    (dotimes (ii arg)                    ; move scope downward
+    (dotimes (_ arg)                    ; move scope downward
       (let ((amt (if pixel-resolution-fine-flag
                      (if (integerp pixel-resolution-fine-flag)
                          pixel-resolution-fine-flag
@@ -145,7 +145,7 @@ This is and alternative of `scroll-down'.  Scope moves 
upward."
   (or arg (setq arg 1))
   (if (pixel-scroll-in-rush-p)
       (scroll-down arg)
-    (dotimes (ii arg)
+    (dotimes (_ arg)
       (let ((amt (if pixel-resolution-fine-flag
                      (if (integerp pixel-resolution-fine-flag)
                          pixel-resolution-fine-flag
@@ -244,7 +244,7 @@ that was scrolled."
          (dst (* line height))         ; goal                  @25  @25  @92
          (delta (- dst src)))          ; pixels to be scrolled  25   17    4
     (pixel--whistlestop-pixel-up (1- delta)) ; until one less  @24  @24  @91
-    (dotimes (ii line)
+    (dotimes (_ line)
       ;; On horizontal scrolling, move cursor.
       (when (> (window-hscroll) 0)
         (vertical-motion 1))
diff --git a/lisp/play/bubbles.el b/lisp/play/bubbles.el
index 50f65a1..e695a75 100644
--- a/lisp/play/bubbles.el
+++ b/lisp/play/bubbles.el
@@ -72,9 +72,6 @@
 
 ;;; Code:
 
-(defconst bubbles-version "0.5" "Version number of bubbles.el.")
-(make-obsolete-variable 'bubbles-version nil "28.1")
-
 (require 'gamegrid)
 
 ;; User options
@@ -1405,6 +1402,11 @@ Return t if new char is non-empty."
             (forward-char 1)))
         (put-text-property (point-min) (point-max) 'pointer 'arrow)))))
 
+;; Obsolete.
+
+(defconst bubbles-version "0.5" "Version number of bubbles.el.")
+(make-obsolete-variable 'bubbles-version 'emacs-version "28.1")
+
 (provide 'bubbles)
 
 ;;; bubbles.el ends here
diff --git a/lisp/play/doctor.el b/lisp/play/doctor.el
index 46fd852..bf923f4 100644
--- a/lisp/play/doctor.el
+++ b/lisp/play/doctor.el
@@ -1583,7 +1583,7 @@ Hack on previous word, setting global variable 
DOCTOR-OWNER to correct result."
                           E-mail: jo@samaritans.org or\, at your option\,
                           anonymous E-mail: samaritans@anon.twwells.com\ \.
                            or find a Befrienders crisis center at
-                          http://www.befrienders.org/\ \.
+                           https://www.befrienders.org/\ \.
                           (doc$ doctor--please) (doc$ doctor--continue) \.)))
        (t (doctor-type (doc$ doctor--deathlst)))))
 
diff --git a/lisp/play/morse.el b/lisp/play/morse.el
index 8e09c22..91dc687 100644
--- a/lisp/play/morse.el
+++ b/lisp/play/morse.el
@@ -146,7 +146,7 @@
   "NATO phonetic alphabet.
 See “International Code of Signals” (INTERCO), United States
 Edition, 1969 Edition (Revised 2003) available from National
-Geospatial-Intelligence Agency at URL `http://www.nga.mil/'")
+Geospatial-Intelligence Agency at URL `https://www.nga.mil/'")
 
 ;;;###autoload
 (defun morse-region (beg end)
diff --git a/lisp/printing.el b/lisp/printing.el
index f5d3c82..b9a2e33 100644
--- a/lisp/printing.el
+++ b/lisp/printing.el
@@ -264,7 +264,7 @@ Please send all bug fixes and enhancements to
 ;;    Also the gsprint utility comes together with gsview distribution.
 ;;
 ;;    For more information about gsprint see
-;;    `http://www.cs.wisc.edu/~ghost/gsview/gsprint.htm'.
+;;    `https://www.cs.wisc.edu/~ghost/gsview/gsprint.htm'.
 ;;
 ;;    As an example of gsprint declaration:
 ;;
@@ -950,18 +950,18 @@ Please send all bug fixes and enhancements to
 ;; * For GNU or Unix system:
 ;;
 ;;    gs, gv         
`https://www.gnu.org/software/ghostscript/ghostscript.html'
-;;    enscript       `http://people.ssh.fi/mtr/genscript/'
+;;    enscript       `https://people.ssh.fi/mtr/genscript/'
 ;;    psnup          `http://www.knackered.org/angus/psutils/'
-;;    mpage          `http://www.mesa.nl/pub/mpage/'
+;;    mpage          `https://www.mesa.nl/pub/mpage/'
 ;;
 ;; * For Windows system:
 ;;
 ;;    gswin32, gsview32
 ;;                   
`https://www.gnu.org/software/ghostscript/ghostscript.html'
-;;    gsprint        `http://www.cs.wisc.edu/~ghost/gsview/gsprint.htm'.
-;;    enscript       `http://people.ssh.fi/mtr/genscript/'
+;;    gsprint        `https://www.cs.wisc.edu/~ghost/gsview/gsprint.htm'.
+;;    enscript       `https://people.ssh.fi/mtr/genscript/'
 ;;    psnup          `http://gnuwin32.sourceforge.net/packages/psutils.htm'
-;;    redmon         `http://www.cs.wisc.edu/~ghost/redmon/'
+;;    redmon         `http://www.ghostgum.com.au/software/redmon.htm'
 ;;
 ;;
 ;; Acknowledgments
@@ -1520,22 +1520,19 @@ Examples:
 Useful links:
 
 * Information about the print command (print.exe)
-  `http://www.computerhope.com/printhlp.htm'
+  `https://www.computerhope.com/printhlp.htm'
 
 * RedMon - Redirection Port Monitor (redpr.exe)
-  `http://www.cs.wisc.edu/~ghost/redmon/index.htm'
+  `http://www.ghostgum.com.au/software/redmon.htm'
 
 * Redirection Port Monitor (redpr.exe on-line help)
-  `http://www.cs.wisc.edu/~ghost/redmon/en/redmon.htm'
+  `https://www.cs.wisc.edu/~ghost/redmon/en/redmon.htm'
 
 * UNIX man pages: lpr (or type `man lpr')
-  `http://bama.ua.edu/cgi-bin/man-cgi?lpr'
-  `http://www.mediacollege.com/cgi-bin/man/page.cgi?section=all&topic=lpr'
+  `https://linux.die.net/man/1/lpr-cups'
 
 * UNIX man pages: lp (or type `man lp')
-  `http://bama.ua.edu/cgi-bin/man-cgi?lp'
-  `http://www.mediacollege.com/cgi-bin/man/page.cgi?section=all&topic=lp'
-"
+  `https://linux.die.net/man/1/lp'"
   :type '(repeat
          (list :tag "Text Printer"
                (symbol :tag "Printer Symbol Name")
@@ -1760,30 +1757,28 @@ are not printed.
 Useful links:
 
 * GSPRINT - Ghostscript print to Windows printer
-  `http://www.cs.wisc.edu/~ghost/gsview/gsprint.htm'
+  `https://www.cs.wisc.edu/~ghost/gsview/gsprint.htm'
 
 * Introduction to Ghostscript
-  `http://www.cs.wisc.edu/~ghost/doc/intro.htm'
+  `https://www.cs.wisc.edu/~ghost/doc/intro.htm'
 
 * How to use Ghostscript
-  `http://www.cs.wisc.edu/~ghost/doc/cvs/Use.htm'
+  `https://www.cs.wisc.edu/~ghost/doc/cvs/Use.htm'
 
 * Information about the print command (print.exe)
-  `http://www.computerhope.com/printhlp.htm'
+  `https://www.computerhope.com/printhlp.htm'
 
 * RedMon - Redirection Port Monitor (redpr.exe)
-  `http://www.cs.wisc.edu/~ghost/redmon/index.htm'
+  `http://www.ghostgum.com.au/software/redmon.htm'
 
 * Redirection Port Monitor (redpr.exe on-line help)
-  `http://www.cs.wisc.edu/~ghost/redmon/en/redmon.htm'
+  `https://www.cs.wisc.edu/~ghost/redmon/en/redmon.htm'
 
 * UNIX man pages: lpr (or type `man lpr')
-  `http://bama.ua.edu/cgi-bin/man-cgi?lpr'
-  `http://www.mediacollege.com/cgi-bin/man/page.cgi?section=all&topic=lpr'
+  `https://linux.die.net/man/1/lpr-cups'
 
 * UNIX man pages: lp (or type `man lp')
-  `http://bama.ua.edu/cgi-bin/man-cgi?lp'
-  `http://www.mediacollege.com/cgi-bin/man/page.cgi?section=all&topic=lp'
+  `https://linux.die.net/man/1/lp'
 
 * GNU utilities for w32 (cp.exe)
   `http://unxutils.sourceforge.net/'
@@ -1873,28 +1868,28 @@ Useful links:
   `https://www.gnu.org/software/gv/manual/gv.html'
 
 * GSview Help
-  `http://www.cs.wisc.edu/~ghost/gsview/gsviewen.htm'
+  `https://www.cs.wisc.edu/~ghost/gsview/gsviewen.htm'
 
 * GSview Help - Common Problems
-  `http://www.cs.wisc.edu/~ghost/gsview/gsviewen.htm#Common_Problems'
+  `https://www.cs.wisc.edu/~ghost/gsview/gsviewen.htm#Common_Problems'
 
 * GSview Readme (compilation & installation)
-  `http://www.cs.wisc.edu/~ghost/gsview/Readme.htm'
+  `https://www.cs.wisc.edu/~ghost/gsview/Readme.htm'
 
 * GSview (main site)
-  `http://www.cs.wisc.edu/~ghost/gsview/index.htm'
+  `https://www.cs.wisc.edu/~ghost/gsview/index.htm'
 
 * Ghostscript, Ghostview and GSview
-  `http://www.cs.wisc.edu/~ghost/'
+  `https://www.cs.wisc.edu/~ghost/'
 
 * Ghostview
-  `http://www.cs.wisc.edu/~ghost/gv/index.htm'
+  `https://www.cs.wisc.edu/~ghost/gv/index.htm'
 
 * gv 3.5, June 1997
-  `http://www.cs.wisc.edu/~ghost/gv/gv_doc/gv.html'
+  `http://pages.cs.wisc.edu/~ghost/gv/gv_doc/gv.html'
 
 * MacGSView (Mac OS)
-  `http://www.cs.wisc.edu/~ghost/macos/index.htm'
+  `http://pages.cs.wisc.edu/~ghost/macos/index.htm'
 "
   :type '(string :tag "Ghostview Utility"))
 
@@ -1910,16 +1905,16 @@ See also `pr-path-alist'.
 Useful links:
 
 * Ghostscript, Ghostview and GSview
-  `http://www.cs.wisc.edu/~ghost/'
+  `https://www.cs.wisc.edu/~ghost/'
 
 * Introduction to Ghostscript
-  `http://www.cs.wisc.edu/~ghost/doc/intro.htm'
+  `https://www.cs.wisc.edu/~ghost/doc/intro.htm'
 
 * How to use Ghostscript
-  `http://www.cs.wisc.edu/~ghost/doc/cvs/Use.htm'
+  `https://www.cs.wisc.edu/~ghost/doc/cvs/Use.htm'
 
 * Printer compatibility
-  `http://www.cs.wisc.edu/~ghost/doc/printer.htm'
+  `https://www.cs.wisc.edu/~ghost/doc/printer.htm'
 "
   :type '(string :tag "Ghostscript Utility"))
 
@@ -1954,13 +1949,13 @@ To see ghostscript documentation for more information:
 Useful links:
 
 * Introduction to Ghostscript
-  `http://www.cs.wisc.edu/~ghost/doc/intro.htm'
+  `https://www.cs.wisc.edu/~ghost/doc/intro.htm'
 
 * How to use Ghostscript
-  `http://www.cs.wisc.edu/~ghost/doc/cvs/Use.htm'
+  `https://www.cs.wisc.edu/~ghost/doc/cvs/Use.htm'
 
 * Printer compatibility
-  `http://www.cs.wisc.edu/~ghost/doc/printer.htm'
+  `https://www.cs.wisc.edu/~ghost/doc/printer.htm'
 "
   :type '(repeat (string :tag "Ghostscript Switch")))
 
@@ -2407,11 +2402,10 @@ Examples:
 Useful links:
 
 * mpage download (GNU or Unix)
-  `http://www.mesa.nl/pub/mpage/'
+  `https://www.mesa.nl/pub/mpage/'
 
 * mpage documentation (GNU or Unix - or type `man mpage')
-  `http://www.cs.umd.edu/faq/guides/manual_unix/node48.html'
-  `http://www.rt.com/man/mpage.1.html'
+  `https://linux.die.net/man/1/mpage'
 
 * psnup (Windows, GNU or Unix)
   `http://www.knackered.org/angus/psutils/'
@@ -2421,14 +2415,13 @@ Useful links:
   `http://gnuwin32.sourceforge.net/packages/psutils.htm'
 
 * psnup documentation (GNU or Unix - or type `man psnup')
-  `http://linux.about.com/library/cmd/blcmdl1_psnup.htm'
-  `http://amath.colorado.edu/computing/software/man/psnup.html'
+  `https://linux.die.net/man/1/psnup'
 
 * GNU Enscript (Windows, GNU or Unix)
-  `http://people.ssh.com/mtr/genscript/'
+  `https://people.ssh.com/mtr/genscript/'
 
 * GNU Enscript documentation (Windows, GNU or Unix)
-  `http://people.ssh.com/mtr/genscript/enscript.man.html'
+  `https://people.ssh.com/mtr/genscript/enscript.man.html'
   (on GNU or Unix, type `man enscript')
 "
   :type '(repeat
diff --git a/lisp/progmodes/antlr-mode.el b/lisp/progmodes/antlr-mode.el
index 8a1d441..2a4b348 100644
--- a/lisp/progmodes/antlr-mode.el
+++ b/lisp/progmodes/antlr-mode.el
@@ -33,7 +33,7 @@
 ;; the manual style, follow all commands mentioned in the documentation of
 ;; `antlr-mode'.  ANTLR is a LL(k)-based recognition tool which generates
 ;; lexers, parsers and tree transformers in Java, C++ or Sather and can be
-;; found at <http://www.antlr.org/>.
+;; found at <https://www.antlr.org/>.
 
 ;; Bug fixes, bug reports, improvements, and suggestions for the newest version
 ;; are strongly appreciated.
diff --git a/lisp/progmodes/cc-defs.el b/lisp/progmodes/cc-defs.el
index 38fe23b..536e676 100644
--- a/lisp/progmodes/cc-defs.el
+++ b/lisp/progmodes/cc-defs.el
@@ -691,14 +691,16 @@ whitespace.
 
 LIMIT sets an upper limit of the forward movement, if specified.  If
 LIMIT or the end of the buffer is reached inside a comment or
-preprocessor directive, the point will be left there.
+preprocessor directive, the point will be left there.  If point starts
+on the wrong side of LIMIT, it stays unchanged.
 
 Note that this function might do hidden buffer changes.  See the
 comment at the start of cc-engine.el for more info."
   (if limit
-      `(save-restriction
-        (narrow-to-region (point-min) (or ,limit (point-max)))
-        (c-forward-sws))
+      `(when (< (point) (or ,limit (point-max)))
+        (save-restriction
+          (narrow-to-region (point-min) (or ,limit (point-max)))
+          (c-forward-sws)))
     '(c-forward-sws)))
 
 (defmacro c-backward-syntactic-ws (&optional limit)
@@ -710,14 +712,16 @@ whitespace.
 
 LIMIT sets a lower limit of the backward movement, if specified.  If
 LIMIT is reached inside a line comment or preprocessor directive then
-the point is moved into it past the whitespace at the end.
+the point is moved into it past the whitespace at the end.  If point
+starts on the wrong side of LIMIT, it stays unchanged.
 
 Note that this function might do hidden buffer changes.  See the
 comment at the start of cc-engine.el for more info."
   (if limit
-      `(save-restriction
-        (narrow-to-region (or ,limit (point-min)) (point-max))
-        (c-backward-sws))
+      `(when (> (point) (or ,limit (point-min)))
+        (save-restriction
+          (narrow-to-region (or ,limit (point-min)) (point-max))
+          (c-backward-sws)))
     '(c-backward-sws)))
 
 (defmacro c-forward-sexp (&optional count)
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index b7ad02c..cc9833a 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -8300,7 +8300,7 @@ comment at the start of cc-engine.el for more info."
   ;; o - nil if no name is found;
   ;; o - 'template if it's an identifier ending with an angle bracket
   ;;   arglist;
-  ;; o - 'operator of it's an operator identifier;
+  ;; o - 'operator if it's an operator identifier;
   ;; o - t if it's some other kind of name.
   ;;
   ;; This function records identifier ranges on
@@ -8320,6 +8320,7 @@ comment at the start of cc-engine.el for more info."
        (lim+ (c-determine-+ve-limit 500)))
     (while
        (and
+        (< (point) lim+)
         (looking-at c-identifier-key)
 
         (progn
@@ -8369,23 +8370,28 @@ comment at the start of cc-engine.el for more info."
                          ;; '*', '&' or a name followed by ":: *",
                          ;; where each can be followed by a sequence
                          ;; of `c-opt-type-modifier-key'.
-                         (while (cond ((looking-at "[*&]")
-                                       (goto-char (match-end 0))
-                                       t)
-                                      ((looking-at c-identifier-start)
-                                       (and (c-forward-name)
-                                            (looking-at "::")
-                                            (progn
-                                              (goto-char (match-end 0))
-                                              (c-forward-syntactic-ws lim+)
-                                              (eq (char-after) ?*))
-                                            (progn
-                                              (forward-char)
-                                              t))))
+                         (while
+                             (and
+                              (< (point) lim+)
+                              (cond ((looking-at "[*&]")
+                                     (goto-char (match-end 0))
+                                     t)
+                                    ((looking-at c-identifier-start)
+                                     (and (c-forward-name)
+                                          (looking-at "::")
+                                          (progn
+                                            (goto-char (match-end 0))
+                                            (c-forward-syntactic-ws lim+)
+                                            (eq (char-after) ?*))
+                                          (progn
+                                            (forward-char)
+                                            t)))))
                            (while (progn
                                     (c-forward-syntactic-ws lim+)
                                     (setq pos (point))
-                                    (looking-at c-opt-type-modifier-key))
+                                    (and
+                                     (<= (point) lim+)
+                                     (looking-at c-opt-type-modifier-key)))
                              (goto-char (match-end 1))))))
 
                       ((looking-at c-overloadable-operators-regexp)
@@ -8431,6 +8437,9 @@ comment at the start of cc-engine.el for more info."
               ;; Maybe an angle bracket arglist.
               (when (let (c-last-identifier-range)
                       (c-forward-<>-arglist nil))
+                ;; <> arglists can legitimately be very long, so recalculate
+                ;; `lim+'.
+                (setq lim+ (c-determine-+ve-limit 500))
 
                 (c-forward-syntactic-ws lim+)
                 (unless (eq (char-after) ?\()
diff --git a/lisp/progmodes/cc-styles.el b/lisp/progmodes/cc-styles.el
index aec259f..29cbe54 100644
--- a/lisp/progmodes/cc-styles.el
+++ b/lisp/progmodes/cc-styles.el
@@ -476,8 +476,8 @@ and exists only for compatibility reasons."
                            (if current-prefix-arg " or add" "")
                            ": ")
                    (mapcar
-                    #'(lambda (langelem)
-                        (cons (format "%s" (car langelem)) nil))
+                    (lambda (langelem)
+                      (cons (format "%s" (car langelem)) nil))
                     (get 'c-offsets-alist 'c-stylevar-fallback))
                    nil (not current-prefix-arg)
                    ;; initial contents tries to be the last element
diff --git a/lisp/progmodes/cfengine.el b/lisp/progmodes/cfengine.el
index 472788d..4649e50 100644
--- a/lisp/progmodes/cfengine.el
+++ b/lisp/progmodes/cfengine.el
@@ -1,4 +1,4 @@
-;;; cfengine.el --- mode for editing Cfengine files
+;;; cfengine.el --- mode for editing Cfengine files  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2001-2021 Free Software Foundation, Inc.
 
@@ -1440,7 +1440,7 @@ to the action header."
       (cfengine3-mode)
     (cfengine2-mode)))
 
-(defalias 'cfengine-mode 'cfengine3-mode)
+(defalias 'cfengine-mode #'cfengine3-mode)
 
 (provide 'cfengine3)
 (provide 'cfengine)
diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el
index d23c77e..7a02c3a 100644
--- a/lisp/progmodes/compile.el
+++ b/lisp/progmodes/compile.el
@@ -2844,8 +2844,9 @@ and overlay is highlighted between MK and END-MK."
     (when (and (not pre-existing) w)
       (compilation-set-window-height w))
 
-    (if from-compilation-buffer
-        ;; If the compilation buffer window was selected,
+    (if (or from-compilation-buffer
+            (eq w (selected-window)))
+        ;; If the compilation buffer window is selected,
         ;; keep the compilation buffer in this window;
         ;; display the source in another window.
         (let ((pop-up-windows t))
diff --git a/lisp/progmodes/cperl-mode.el b/lisp/progmodes/cperl-mode.el
index 7612f8d..7878e91 100644
--- a/lisp/progmodes/cperl-mode.el
+++ b/lisp/progmodes/cperl-mode.el
@@ -3608,7 +3608,8 @@ the sections using `cperl-pod-head-face', 
`cperl-pod-face',
                ;; 1+6+2+1+1+6+1+1+1=20 extra () before this:
                "\\|"
                "\\\\\\(['`\"($]\\)")   ; BACKWACKED something-hairy
-            ""))))
+            "")))
+         warning-message)
     (unwind-protect
        (progn
          (save-excursion
@@ -3671,7 +3672,7 @@ the sections using `cperl-pod-head-face', 
`cperl-pod-face',
                        (looking-at "\\(cut\\|end\\)\\>"))
                    (if (or (nth 3 state) (nth 4 state) ignore-max)
                        nil             ; Doing a chunk only
-                     (message "=cut is not preceded by a POD section")
+                     (setq warning-message "=cut is not preceded by a POD 
section")
                      (or (car err-l) (setcar err-l (point))))
                  (beginning-of-line)
 
@@ -3686,7 +3687,7 @@ the sections using `cperl-pod-head-face', 
`cperl-pod-face',
                        (goto-char b)
                        (if (re-search-forward "\n=\\(cut\\|end\\)\\>" 
stop-point 'toend)
                            (progn
-                             (message "=cut is not preceded by an empty line")
+                             (setq warning-message "=cut is not preceded by an 
empty line")
                              (setq b1 t)
                              (or (car err-l) (setcar err-l b))))))
                  (beginning-of-line 2) ; An empty line after =cut is not POD!
@@ -3829,7 +3830,8 @@ the sections using `cperl-pod-head-face', 
`cperl-pod-face',
                    (progn              ; Pretend we matched at the end
                      (goto-char (point-max))
                      (re-search-forward "\\'")
-                     (message "End of here-document `%s' not found." tag)
+                     (setq warning-message
+                            (format "End of here-document `%s' not found." 
tag))
                      (or (car err-l) (setcar err-l b))))
                  (if cperl-pod-here-fontify
                      (progn
@@ -3906,7 +3908,8 @@ the sections using `cperl-pod-head-face', 
`cperl-pod-face',
                                                    'face font-lock-string-face)
                      (cperl-commentify (point) (+ (point) 2) nil)
                      (cperl-put-do-not-fontify (point) (+ (point) 2) t))
-                 (message "End of format `%s' not found." name)
+                 (setq warning-message
+                        (format "End of format `%s' not found." name))
                  (or (car err-l) (setcar err-l b)))
                (forward-line)
                (if (> (point) max)
@@ -4426,8 +4429,9 @@ the sections using `cperl-pod-head-face', 
`cperl-pod-face',
                                          REx-subgr-end argument) ; continue
                                  (setq argument nil)))
                              (and argument
-                                  (message "Couldn't find end of charclass in 
a REx, pos=%s"
-                                           REx-subgr-start))
+                                  (setq warning-message
+                                         (format "Couldn't find end of 
charclass in a REx, pos=%s"
+                                                REx-subgr-start)))
                              (setq argument (1- (point)))
                              (goto-char REx-subgr-end)
                              (cperl-highlight-charclass
@@ -4483,7 +4487,8 @@ the sections using `cperl-pod-head-face', 
`cperl-pod-face',
                                           (setq qtag "Can't find })")))
                                  (progn
                                    (goto-char (1- e))
-                                   (message "%s" qtag))
+                                   (setq warning-message
+                                          (format "%s" qtag)))
                                (cperl-postpone-fontification
                                 (1- tag) (1- (point))
                                 'face font-lock-variable-name-face)
@@ -4512,9 +4517,9 @@ the sections using `cperl-pod-head-face', 
`cperl-pod-face',
                               ;; (1- e) 'toend)
                               (search-forward ")" (1- e) 'toend)
                               ;;)
-                              (message
-                               "Couldn't find end of (?#...)-comment in a REx, 
pos=%s"
-                               REx-subgr-start))))
+                              (setq warning-message
+                                    (format "Couldn't find end of 
(?#...)-comment in a REx, pos=%s"
+                                            REx-subgr-start)))))
                            (if (>= (point) e)
                                (goto-char (1- e)))
                            (cond
@@ -4592,8 +4597,8 @@ the sections using `cperl-pod-head-face', 
`cperl-pod-face',
              (if (> (point) stop-point)
                  (progn
                    (if end
-                       (message "Garbage after __END__/__DATA__ ignored")
-                     (message "Unbalanced syntax found while scanning")
+                       (setq warning-message "Garbage after __END__/__DATA__ 
ignored")
+                     (setq warning-message "Unbalanced syntax found while 
scanning")
                      (or (car err-l) (setcar err-l b)))
                    (goto-char stop-point))))
            (setq cperl-syntax-state (cons state-point state)
@@ -4612,6 +4617,7 @@ the sections using `cperl-pod-head-face', 
`cperl-pod-face',
       ;; cperl-mode-syntax-table.
       ;; (set-syntax-table cperl-mode-syntax-table)
       )
+    (when warning-message (message warning-message))
     (list (car err-l) overshoot)))
 
 (defun cperl-find-pods-heres-region (min max)
diff --git a/lisp/progmodes/cwarn.el b/lisp/progmodes/cwarn.el
index 63b344b..7fd592f 100644
--- a/lisp/progmodes/cwarn.el
+++ b/lisp/progmodes/cwarn.el
@@ -1,4 +1,4 @@
-;;; cwarn.el --- highlight suspicious C and C++ constructions
+;;; cwarn.el --- highlight suspicious C and C++ constructions  -*- 
lexical-binding: t -*-
 
 ;; Copyright (C) 1999-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/progmodes/dcl-mode.el b/lisp/progmodes/dcl-mode.el
index 14eefdc..ed024f2 100644
--- a/lisp/progmodes/dcl-mode.el
+++ b/lisp/progmodes/dcl-mode.el
@@ -1,4 +1,4 @@
-;;; dcl-mode.el --- major mode for editing DCL command files
+;;; dcl-mode.el --- major mode for editing DCL command files  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1997, 2001-2021 Free Software Foundation, Inc.
 
@@ -23,9 +23,11 @@
 
 ;;; Commentary:
 
-;; DCL mode is a package for editing DCL command files.  It helps you
-;; indent lines, add leading `$' and trailing `-', move around in the
-;; code and insert lexical functions.
+;; DCL mode is a package for editing
+;; [DCL](https://en.wikipedia.org/wiki/DIGITAL_Command_Language)
+;; command files.
+;; It helps you indent lines, add leading `$' and trailing `-', move
+;; around in the code and insert lexical functions.
 ;;
 ;; Type `C-h m' when you are editing a .COM file to get more
 ;; information about this mode.
@@ -270,22 +272,22 @@ See `imenu-generic-expression' for details."
 
 (defvar dcl-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "\e\n"     'dcl-split-line)
-    (define-key map "\e\t"     'tempo-complete-tag)
-    (define-key map "\e^"      'dcl-delete-indentation)
-    (define-key map "\em"      'dcl-back-to-indentation)
-    (define-key map "\ee"        'dcl-forward-command)
-    (define-key map "\ea"        'dcl-backward-command)
-    (define-key map "\e\C-q"   'dcl-indent-command)
-    (define-key map "\t"         'dcl-tab)
-    (define-key map ":"          'dcl-electric-character)
-    (define-key map "F"          'dcl-electric-character)
-    (define-key map "f"          'dcl-electric-character)
-    (define-key map "E"          'dcl-electric-character)
-    (define-key map "e"          'dcl-electric-character)
-    (define-key map "\C-c\C-o"         'dcl-set-option)
-    (define-key map "\C-c\C-f"         'tempo-forward-mark)
-    (define-key map "\C-c\C-b"         'tempo-backward-mark)
+    (define-key map "\e\n"     #'dcl-split-line)
+    (define-key map "\e\t"     #'tempo-complete-tag)
+    (define-key map "\e^"      #'dcl-delete-indentation)
+    (define-key map "\em"      #'dcl-back-to-indentation)
+    (define-key map "\ee"        #'dcl-forward-command)
+    (define-key map "\ea"        #'dcl-backward-command)
+    (define-key map "\e\C-q"   #'dcl-indent-command)
+    (define-key map "\t"         #'dcl-tab)
+    (define-key map ":"          #'dcl-electric-character)
+    (define-key map "F"          #'dcl-electric-character)
+    (define-key map "f"          #'dcl-electric-character)
+    (define-key map "E"          #'dcl-electric-character)
+    (define-key map "e"          #'dcl-electric-character)
+    (define-key map "\C-c\C-o"         #'dcl-set-option)
+    (define-key map "\C-c\C-f"         #'tempo-forward-mark)
+    (define-key map "\C-c\C-b"         #'tempo-backward-mark)
     map)
   "Keymap used in DCL-mode buffers.")
 
@@ -533,7 +535,7 @@ $
 
 There is some minimal font-lock support (see vars
 `dcl-font-lock-defaults' and `dcl-font-lock-keywords')."
-  (setq-local indent-line-function 'dcl-indent-line)
+  (setq-local indent-line-function #'dcl-indent-line)
   (setq-local comment-start "!")
   (setq-local comment-end "")
   (setq-local comment-multi-line nil)
@@ -547,7 +549,7 @@ There is some minimal font-lock support (see vars
 
   (setq imenu-generic-expression dcl-imenu-generic-expression)
   (setq imenu-case-fold-search t)
-  (setq imenu-create-index-function 'dcl-imenu-create-index-function)
+  (setq imenu-create-index-function #'dcl-imenu-create-index-function)
 
   (make-local-variable 'dcl-comment-line-regexp)
   (make-local-variable 'dcl-block-begin-regexp)
@@ -1391,7 +1393,7 @@ regexps in `dcl-electric-reindent-regexps'."
     (let ((case-fold-search t))
       ;; There must be a better way than (memq t ...).
       ;; (apply 'or ...) didn't work
-      (if (memq t (mapcar 'dcl-was-looking-at dcl-electric-reindent-regexps))
+      (if (memq t (mapcar #'dcl-was-looking-at dcl-electric-reindent-regexps))
           (dcl-indent-line)))))
 
 
@@ -1567,7 +1569,7 @@ Must return a string."
                 ((fboundp action)
                  (funcall action option-assoc))
                 ((eq action 'toggle)
-                 (not (eval option)))
+                 (not (symbol-value option)))
                 ((eq action 'curval)
                  (cond ((or (stringp (symbol-value option))
                             (numberp (symbol-value option)))
@@ -1735,7 +1737,7 @@ Set or update the value of VAR in the current buffers
                    (setq continue nil)
                    (beginning-of-line)
                    (insert (concat prefix-string (symbol-name var) ": "
-                                   (prin1-to-string (eval var)) " "
+                                   (prin1-to-string (symbol-value var)) " "
                                    suffix-string "\n")))
                ;; Is it the variable we are looking for?
                (if (eq var found-var)
@@ -1748,7 +1750,7 @@ Set or update the value of VAR in the current buffers
                      (delete-region (point) (progn (read (current-buffer))
                                                    (point)))
                      (insert " ")
-                     (prin1 (eval var) (current-buffer))
+                     (prin1 (symbol-value var) (current-buffer))
                      (skip-chars-backward "\n")
                      (skip-chars-forward " \t")
                      (or (if suffix (looking-at suffix) (eolp))
@@ -1781,7 +1783,7 @@ Set or update the value of VAR in the current buffers
                  (concat " " comment-end))))))
        (insert (concat def-prefix "Local variables:" def-suffix "\n"))
        (insert (concat def-prefix (symbol-name var) ": "
-                       (prin1-to-string (eval var)) def-suffix "\n"))
+                       (prin1-to-string (symbol-value var)) def-suffix "\n"))
        (insert (concat def-prefix "end:" def-suffix)))
       )))
 
@@ -1815,7 +1817,8 @@ still be present in the `Local Variables:' section with 
its old value."
                   (option-name (symbol-name option)))
              (if (and (string-equal "dcl-"
                                     (substring option-name 0 4))
-                      (not (equal (default-value option) (eval option))))
+                      (not (equal (default-value option)
+                                  (symbol-value option))))
                  (dcl-save-local-variable option "$! "))))
          dcl-option-alist))
 
diff --git a/lisp/progmodes/ebnf-abn.el b/lisp/progmodes/ebnf-abn.el
index 9e570b6..2a37110 100644
--- a/lisp/progmodes/ebnf-abn.el
+++ b/lisp/progmodes/ebnf-abn.el
@@ -1,4 +1,4 @@
-;;; ebnf-abn.el --- parser for ABNF (Augmented BNF)
+;;; ebnf-abn.el --- parser for ABNF (Augmented BNF)  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2001-2021 Free Software Foundation, Inc.
 
@@ -39,10 +39,6 @@
 ;;
 ;;     See the URL:
 ;;     `https://www.ietf.org/rfc/rfc2234.txt'
-;;     or
-;;     `http://www.faqs.org/rfcs/rfc2234.html'
-;;     or
-;;     `http://www.rnp.br/ietf/rfc/rfc2234.txt'
 ;;     ("Augmented BNF for Syntax Specifications: ABNF").
 ;;
 ;;
diff --git a/lisp/progmodes/ebnf-bnf.el b/lisp/progmodes/ebnf-bnf.el
index 93ebfe8..e6717cb 100644
--- a/lisp/progmodes/ebnf-bnf.el
+++ b/lisp/progmodes/ebnf-bnf.el
@@ -1,4 +1,4 @@
-;;; ebnf-bnf.el --- parser for EBNF
+;;; ebnf-bnf.el --- parser for EBNF  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1999-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/progmodes/ebnf-dtd.el b/lisp/progmodes/ebnf-dtd.el
index 66e5dd0..93bae5a 100644
--- a/lisp/progmodes/ebnf-dtd.el
+++ b/lisp/progmodes/ebnf-dtd.el
@@ -1,4 +1,4 @@
-;;; ebnf-dtd.el --- parser for DTD (Data Type Description for XML)
+;;; ebnf-dtd.el --- parser for DTD (Data Type Description for XML)  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2001-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/progmodes/ebnf-ebx.el b/lisp/progmodes/ebnf-ebx.el
index 389049e..5d85419 100644
--- a/lisp/progmodes/ebnf-ebx.el
+++ b/lisp/progmodes/ebnf-ebx.el
@@ -1,4 +1,4 @@
-;;; ebnf-ebx.el --- parser for EBNF used to specify XML (EBNFX)
+;;; ebnf-ebx.el --- parser for EBNF used to specify XML (EBNFX)  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2001-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/progmodes/ebnf-iso.el b/lisp/progmodes/ebnf-iso.el
index d25ff3e..b4532c7 100644
--- a/lisp/progmodes/ebnf-iso.el
+++ b/lisp/progmodes/ebnf-iso.el
@@ -1,4 +1,4 @@
-;;; ebnf-iso.el --- parser for ISO EBNF
+;;; ebnf-iso.el --- parser for ISO EBNF  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1999-2021 Free Software Foundation, Inc.
 
@@ -38,7 +38,7 @@
 ;; ---------------
 ;;
 ;;     See the URL:
-;;     `http://www.cl.cam.ac.uk/~mgk25/iso-ebnf.html'
+;;     `https://www.cl.cam.ac.uk/~mgk25/iso-ebnf.html'
 ;;     ("International Standard of the ISO EBNF Notation").
 ;;
 ;;
diff --git a/lisp/progmodes/ebnf-otz.el b/lisp/progmodes/ebnf-otz.el
index b724d75..84e59cc 100644
--- a/lisp/progmodes/ebnf-otz.el
+++ b/lisp/progmodes/ebnf-otz.el
@@ -1,4 +1,4 @@
-;;; ebnf-otz.el --- syntactic chart OpTimiZer
+;;; ebnf-otz.el --- syntactic chart OpTimiZer  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1999-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/progmodes/ebnf-yac.el b/lisp/progmodes/ebnf-yac.el
index 2765d03..816cc43 100644
--- a/lisp/progmodes/ebnf-yac.el
+++ b/lisp/progmodes/ebnf-yac.el
@@ -1,4 +1,4 @@
-;;; ebnf-yac.el --- parser for Yacc/Bison
+;;; ebnf-yac.el --- parser for Yacc/Bison  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1999-2021 Free Software Foundation, Inc.
 
@@ -271,13 +271,13 @@
   (let ((table (make-vector 256 'error)))
     ;; upper & lower case letters:
     (mapc
-     #'(lambda (char)
-        (aset table char 'non-terminal))
+     (lambda (char)
+       (aset table char 'non-terminal))
      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
     ;; printable characters:
     (mapc
-     #'(lambda (char)
-        (aset table char 'character))
+     (lambda (char)
+       (aset table char 'character))
      "!#$&()*+-.0123456789=?@[\\]^_`~")
     ;; Override space characters:
     (aset table ?\n 'space)            ; [NL] linefeed
diff --git a/lisp/progmodes/ebnf2ps.el b/lisp/progmodes/ebnf2ps.el
index b376423..a00440d 100644
--- a/lisp/progmodes/ebnf2ps.el
+++ b/lisp/progmodes/ebnf2ps.el
@@ -330,7 +330,7 @@ Please send all bug fixes and enhancements to
 ;;                     ("Augmented BNF for Syntax Specifications: ABNF").
 ;;
 ;;    `iso-ebnf'       ebnf2ps recognizes the syntax described in the URL:
-;;                     `http://www.cl.cam.ac.uk/~mgk25/iso-ebnf.html'
+;;                     `https://www.cl.cam.ac.uk/~mgk25/iso-ebnf.html'
 ;;                     ("International Standard of the ISO EBNF Notation").
 ;;                     The following variables *ONLY* have effect with this
 ;;                     setting:
@@ -1783,7 +1783,7 @@ Valid values are:
                (\"Augmented BNF for Syntax Specifications: ABNF\").
 
    `iso-ebnf'  ebnf2ps recognizes the syntax described in the URL:
-               `http://www.cl.cam.ac.uk/~mgk25/iso-ebnf.html'
+                `https://www.cl.cam.ac.uk/~mgk25/iso-ebnf.html'
                (\"International Standard of the ISO EBNF Notation\").
                The following variables *ONLY* have effect with this
                setting:
@@ -2920,7 +2920,7 @@ See `ebnf-style-database' documentation."
        value
       (and (car value) (ebnf-apply-style1 (car value)))
       (while (setq value (cdr value))
-       (set (caar value) (eval (cdar value)))))))
+       (set (caar value) (eval (cdar value) t))))))
 
 
 (defun ebnf-check-style-values (values)
@@ -4398,8 +4398,8 @@ end
 
 (defun ebnf-format-float (&rest floats)
   (mapconcat
-   #'(lambda (float)
-       (format ebnf-format-float float))
+   (lambda (float)
+     (format ebnf-format-float float))
    floats
    " "))
 
@@ -4959,8 +4959,8 @@ killed after process termination."
 
 (defvar ebnf-map-name
   (let ((map (make-vector 256 ?\_)))
-    (mapc #'(lambda (char)
-             (aset map char char))
+    (mapc (lambda (char)
+            (aset map char char))
          (concat "#$%&+-.0123456789=?@~"
                  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                  "abcdefghijklmnopqrstuvwxyz"))
@@ -5487,7 +5487,7 @@ killed after process termination."
                      (ebnf-shape-value ebnf-chart-shape
                                        ebnf-terminal-shape-alist))
              (format "/UserArrow{%s}def\n"
-                     (let ((arrow (eval ebnf-user-arrow)))
+                     (let ((arrow (eval ebnf-user-arrow t)))
                        (if (stringp arrow)
                            arrow
                          "")))
@@ -6290,7 +6290,7 @@ killed after process termination."
 (defun ebnf-log-header (format-str &rest args)
   (when ebnf-log
     (apply
-     'ebnf-log
+     #'ebnf-log
      (concat
       "\n\n===============================================================\n\n"
       format-str)
diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el
index cdf6085..8ade718 100644
--- a/lisp/progmodes/elisp-mode.el
+++ b/lisp/progmodes/elisp-mode.el
@@ -530,6 +530,7 @@ functions are annotated with \"<f>\" via the
                     ((elisp--expect-function-p beg)
                      (list nil obarray
                            :predicate #'fboundp
+                           :company-kind #'elisp--company-kind
                            :company-doc-buffer #'elisp--company-doc-buffer
                            :company-docsig #'elisp--company-doc-string
                            :company-location #'elisp--company-location))
@@ -543,6 +544,7 @@ functions are annotated with \"<f>\" via the
                                             (symbol-plist sym)))
                            :annotation-function
                            (lambda (str) (if (fboundp (intern-soft str)) " 
<f>"))
+                           :company-kind #'elisp--company-kind
                            :company-doc-buffer #'elisp--company-doc-buffer
                            :company-docsig #'elisp--company-doc-string
                            :company-location #'elisp--company-location))
@@ -553,6 +555,11 @@ functions are annotated with \"<f>\" via the
                                                  obarray
                                                  #'boundp
                                                  'strict))
+                           :company-kind
+                           (lambda (s)
+                             (if (test-completion s 
elisp--local-variables-completion-table)
+                                 'value
+                               'variable))
                            :company-doc-buffer #'elisp--company-doc-buffer
                            :company-docsig #'elisp--company-doc-string
                            :company-location #'elisp--company-location)))
@@ -599,11 +606,13 @@ functions are annotated with \"<f>\" via the
                                       (looking-at "\\_<let\\*?\\_>"))))
                         (list t obarray
                               :predicate #'boundp
+                              :company-kind (lambda (_) 'variable)
                               :company-doc-buffer #'elisp--company-doc-buffer
                               :company-docsig #'elisp--company-doc-string
                               :company-location #'elisp--company-location))
                        (_ (list nil obarray
                                 :predicate #'fboundp
+                                :company-kind #'elisp--company-kind
                                 :company-doc-buffer #'elisp--company-doc-buffer
                                 :company-docsig #'elisp--company-doc-string
                                 :company-location #'elisp--company-location
@@ -619,6 +628,16 @@ functions are annotated with \"<f>\" via the
                                        " " (cadr table-etc)))
                     (cddr table-etc)))))))))
 
+(defun elisp--company-kind (str)
+  (let ((sym (intern-soft str)))
+    (cond
+     ((or (macrop sym) (special-form-p sym)) 'keyword)
+     ((fboundp sym) 'function)
+     ((boundp sym) 'variable)
+     ((featurep sym) 'module)
+     ((facep sym) 'color)
+     (t 'text))))
+
 (defun lisp-completion-at-point (&optional _predicate)
   (declare (obsolete elisp-completion-at-point "25.1"))
   (elisp-completion-at-point))
diff --git a/lisp/progmodes/etags.el b/lisp/progmodes/etags.el
index 023c90c..13717b1 100644
--- a/lisp/progmodes/etags.el
+++ b/lisp/progmodes/etags.el
@@ -836,11 +836,7 @@ If no tags table is loaded, do nothing and return nil."
   "Read a tag name, with defaulting and completion."
   (let* ((completion-ignore-case (find-tag--completion-ignore-case))
         (default (find-tag--default))
-        (spec (completing-read (if default
-                                   (format "%s (default %s): "
-                                           (substring string 0 (string-match 
"[ :]+\\'" string))
-                                           default)
-                                 string)
+        (spec (completing-read (format-prompt string default)
                                (tags-lazy-completion-table)
                                nil nil nil nil default)))
     (if (equal spec "")
@@ -899,7 +895,7 @@ onto a ring and may be popped back to with \\[pop-tag-mark].
 Contrast this with the ring of marks gone to by the command.
 
 See documentation of variable `tags-file-name'."
-  (interactive (find-tag-interactive "Find tag: "))
+  (interactive (find-tag-interactive "Find tag"))
 
   (setq find-tag-history (cons tagname find-tag-history))
   ;; Save the current buffer's value of `find-tag-hook' before
@@ -971,7 +967,7 @@ Contrast this with the ring of marks gone to by the command.
 
 See documentation of variable `tags-file-name'."
   (declare (obsolete xref-find-definitions "25.1"))
-  (interactive (find-tag-interactive "Find tag: "))
+  (interactive (find-tag-interactive "Find tag"))
   (let* ((buf (find-tag-noselect tagname next-p regexp-p))
         (pos (with-current-buffer buf (point))))
     (condition-case nil
@@ -1000,7 +996,7 @@ Contrast this with the ring of marks gone to by the 
command.
 
 See documentation of variable `tags-file-name'."
   (declare (obsolete xref-find-definitions-other-window "25.1"))
-  (interactive (find-tag-interactive "Find tag other window: "))
+  (interactive (find-tag-interactive "Find tag other window"))
 
   ;; This hair is to deal with the case where the tag is found in the
   ;; selected window's buffer; without the hair, point is moved in both
@@ -1041,7 +1037,7 @@ Contrast this with the ring of marks gone to by the 
command.
 
 See documentation of variable `tags-file-name'."
   (declare (obsolete xref-find-definitions-other-frame "25.1"))
-  (interactive (find-tag-interactive "Find tag other frame: "))
+  (interactive (find-tag-interactive "Find tag other frame"))
   (let ((pop-up-frames t))
     (with-suppressed-warnings ((obsolete find-tag-other-window))
       (find-tag-other-window tagname next-p))))
@@ -1065,7 +1061,7 @@ Contrast this with the ring of marks gone to by the 
command.
 
 See documentation of variable `tags-file-name'."
   (declare (obsolete xref-find-apropos "25.1"))
-  (interactive (find-tag-interactive "Find tag regexp: " t))
+  (interactive (find-tag-interactive "Find tag regexp" t))
   ;; We go through find-tag-other-window to do all the display hair there.
   (funcall (if other-window 'find-tag-other-window 'find-tag)
           regexp next-p t))
diff --git a/lisp/progmodes/executable.el b/lisp/progmodes/executable.el
index 85e9b4b..0d8b09c 100644
--- a/lisp/progmodes/executable.el
+++ b/lisp/progmodes/executable.el
@@ -1,4 +1,4 @@
-;;; executable.el --- base functionality for executable interpreter scripts
+;;; executable.el --- base functionality for executable interpreter scripts  
-*- lexical-binding: t -*-
 
 ;; Copyright (C) 1994-1996, 2000-2021 Free Software Foundation, Inc.
 
diff --git a/lisp/progmodes/grep.el b/lisp/progmodes/grep.el
index 8c9a1b5..e9fbcbb 100644
--- a/lisp/progmodes/grep.el
+++ b/lisp/progmodes/grep.el
@@ -1134,13 +1134,13 @@ command before it's run."
                       (and grep-find-ignored-files
                            (concat " --exclude="
                                    (mapconcat
-                                    #'(lambda (ignore)
-                                        (cond ((stringp ignore)
-                                               (shell-quote-argument ignore))
-                                              ((consp ignore)
-                                               (and (funcall (car ignore) dir)
-                                                    (shell-quote-argument
-                                                     (cdr ignore))))))
+                                     (lambda (ignore)
+                                       (cond ((stringp ignore)
+                                              (shell-quote-argument ignore))
+                                             ((consp ignore)
+                                              (and (funcall (car ignore) dir)
+                                                   (shell-quote-argument
+                                                    (cdr ignore))))))
                                     grep-find-ignored-files
                                     " --exclude=")))
                       (and (eq grep-use-directories-skip t)
@@ -1274,13 +1274,13 @@ command before it's run."
                  ;; we should use shell-quote-argument here
                  " -name "
                  (mapconcat
-                  #'(lambda (ignore)
-                      (cond ((stringp ignore)
-                             (shell-quote-argument ignore))
-                            ((consp ignore)
-                             (and (funcall (car ignore) dir)
-                                  (shell-quote-argument
-                                   (cdr ignore))))))
+                  (lambda (ignore)
+                    (cond ((stringp ignore)
+                           (shell-quote-argument ignore))
+                          ((consp ignore)
+                           (and (funcall (car ignore) dir)
+                                (shell-quote-argument
+                                 (cdr ignore))))))
                   grep-find-ignored-files
                   " -o -name ")
                  " "
diff --git a/lisp/progmodes/hideif.el b/lisp/progmodes/hideif.el
index 923f85f..0d9b4b7 100644
--- a/lisp/progmodes/hideif.el
+++ b/lisp/progmodes/hideif.el
@@ -1600,7 +1600,7 @@ not be expanded."
              (result (funcall hide-ifdef-evaluator expr))
              (exprstring (replace-regexp-in-string
                           ;; Trim off leading/trailing whites
-                          "^[ \t]*\\([^ \t]+\\)[ \t]*" "\\1"
+                          "^[ \t]*\\|[ \t]*$"  ""
                           (replace-regexp-in-string
                            "\\(//.*\\)" "" ; Trim off end-of-line comments
                            (buffer-substring-no-properties start end)))))
@@ -1743,10 +1743,10 @@ first arg will be `hif-etc'."
 (defun hide-ifdef-guts ()
   "Does most of the work of `hide-ifdefs'.
 It does not do the work that's pointless to redo on a recursive entry."
-  ;; (message "hide-ifdef-guts")
   (save-excursion
     (let* ((case-fold-search t) ; Ignore case for `hide-ifdef-header-regexp'
            (expand-header (and hide-ifdef-expand-reinclusion-protection
+                               (buffer-file-name)
                                (string-match hide-ifdef-header-regexp
                                              (buffer-file-name))
                                (zerop hif-recurse-level)))
diff --git a/lisp/progmodes/idlw-complete-structtag.el 
b/lisp/progmodes/idlw-complete-structtag.el
index 25bc5ad..6d2d402 100644
--- a/lisp/progmodes/idlw-complete-structtag.el
+++ b/lisp/progmodes/idlw-complete-structtag.el
@@ -1,4 +1,4 @@
-;;; idlw-complete-structtag.el --- Completion of structure tags.
+;;; idlw-complete-structtag.el --- Completion of structure tags.  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2001-2021 Free Software Foundation, Inc.
 
@@ -100,12 +100,11 @@
 (defvar idlwave-sint-structtags nil)
 
 ;; Create the sintern type for structure talks
-(declare-function idlwave-sintern-structtag "idlw-complete-structtag" t t)
-(idlwave-new-sintern-type 'structtag)
+(idlwave-new-sintern-type structtag)
 
 ;; Hook the plugin into idlwave
-(add-to-list 'idlwave-complete-special 'idlwave-complete-structure-tag)
-(add-hook 'idlwave-update-rinfo-hook 'idlwave-structtag-reset)
+(add-hook 'idlwave-complete-functions #'idlwave-complete-structure-tag)
+(add-hook 'idlwave-update-rinfo-hook #'idlwave-structtag-reset)
 
 ;;; The main code follows below
 (defvar idlwave-completion-help-info)
diff --git a/lisp/progmodes/idlw-help.el b/lisp/progmodes/idlw-help.el
index 2e7b0aa..db76df9 100644
--- a/lisp/progmodes/idlw-help.el
+++ b/lisp/progmodes/idlw-help.el
@@ -1,4 +1,4 @@
-;;; idlw-help.el --- HTML Help code for IDLWAVE
+;;; idlw-help.el --- HTML Help code for IDLWAVE  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2000-2021 Free Software Foundation, Inc.
 ;;
@@ -50,7 +50,6 @@
 
 (defcustom idlwave-html-help-pre-v6 nil
   "Whether pre or post-v6.0 IDL help documents are being used."
-  :group 'idlwave-online-help
   :type 'boolean)
 
 (defvar idlwave-html-link-sep
@@ -60,7 +59,6 @@
   "The directory, relative to `idlwave-system-directory', where the IDL
 HTML help files live, for IDL 6.2 and later.  This location, if found,
 is used in preference to the old `idlwave-html-help-location'."
-  :group 'idlwave-online-help
   :type 'directory)
 
 (defcustom idlwave-html-help-location
@@ -69,7 +67,6 @@ is used in preference to the old 
`idlwave-html-help-location'."
     "/usr/local/etc/")
   "The directory where the idl_html_help/ dir lives.  Obsolete for IDL
 6.2 or later (see `idlwave-html-system-help-location')."
-  :group 'idlwave-online-help
   :type 'directory)
 
 (defvar idlwave-help-use-hh nil
@@ -77,18 +74,15 @@ is used in preference to the old 
`idlwave-html-help-location'."
 
 (defcustom idlwave-help-use-assistant t
   "Whether to use the IDL Assistant as the help browser."
-  :group 'idlwave-online-help
   :type 'boolean)
 
 (defcustom idlwave-help-browser-function browse-url-browser-function
   "Function to use to display HTML help.
 Defaults to `browse-url-browser-function', which see."
-  :group 'idlwave-online-help
   :type 'function)
 
 (defcustom idlwave-help-browser-generic-program browse-url-generic-program
   "Program to run if using `browse-url-generic-program'."
-  :group 'idlwave-online-help
   :type '(choice (const nil) string))
 
 ;; AFAICS, never used since it was introduced in 2004.
@@ -96,7 +90,6 @@ Defaults to `browse-url-browser-function', which see."
   (if (boundp 'browse-url-generic-args)
       browse-url-generic-args "")
   "Program args to use if using `browse-url-generic-program'."
-  :group 'idlwave-online-help
   :type '(repeat string))
 
 (defcustom idlwave-help-browser-is-local nil
@@ -106,7 +99,6 @@ external programs.  If the browser name contains \"-w3\", it 
is
 assumed to be local to Emacs.  For other local browsers, this variable
 must be explicitly set non-nil in order for the variable
 `idlwave-help-use-dedicated-frame' to function."
-  :group 'idlwave-online-help
   :type 'boolean)
 
 (defvar idlwave-help-directory ""
@@ -114,7 +106,6 @@ must be explicitly set non-nil in order for the variable
 
 (defcustom idlwave-help-use-dedicated-frame t
   "Non-nil means, use a separate frame for Online Help if possible."
-  :group 'idlwave-online-help
   :type 'boolean)
 
 (defcustom idlwave-help-frame-parameters
@@ -123,14 +114,12 @@ must be explicitly set non-nil in order for the variable
 See also `idlwave-help-use-dedicated-frame'.
 If you do not set the frame width here, the value specified in
 `idlw-help.el' will be used."
-  :group 'idlwave-online-help
   :type '(repeat
          (cons symbol sexp)))
 
 (defcustom idlwave-max-popup-menu-items 20
   "Maximum number of items per pane in popup menus.
 Currently only used for class selection during completion help."
-  :group 'idlwave-online-help
   :type 'integer)
 
 (defcustom idlwave-extra-help-function 'idlwave-help-with-source
@@ -158,12 +147,10 @@ The default value for this function is 
`idlwave-help-with-source' which
 loads the routine source file into the help buffer.  If you try to write
 a different function which accesses a special help file or so, it is
 probably a good idea to still call this function as a fallback."
-  :group 'idlwave-online-help
   :type 'symbol)
 
 (defcustom idlwave-help-fontify-source-code nil
   "Non-nil means, fontify source code displayed as help like normal code."
-  :group 'idlwave-online-help
   :type 'boolean)
 
 (defcustom idlwave-help-source-try-header t
@@ -173,7 +160,6 @@ help text.  When this variable is non-nil, we try to find a 
description of
 the help item in the first routine doclib header above the routine definition.
 If the variable is nil, or if we cannot find/parse the header, the routine
 definition is displayed instead."
-  :group 'idlwave-online-help
   :type 'boolean)
 
 
@@ -181,20 +167,17 @@ definition is displayed instead."
   "A regexp for the heading word to search for in doclib headers
 which specifies the `name' section.  Can be used for localization
 support."
-  :group 'idlwave-online-help
   :type 'regexp)
 
 (defcustom idlwave-help-doclib-keyword "KEYWORD"
   "A regexp for the heading word to search for in doclib headers
 which specifies the `keywords' section.  Can be used for localization
 support."
-  :group 'idlwave-online-help
   :type 'regexp)
 
 (defface idlwave-help-link
   '((t :inherit link))
-  "Face for highlighting links into IDLWAVE online help."
-  :group 'idlwave-online-help)
+  "Face for highlighting links into IDLWAVE online help.")
 
 (defvar idlwave-help-activate-links-aggressively nil
   "Obsolete variable.")
@@ -219,20 +202,20 @@ support."
 
 (defvar idlwave-help-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "q" 'idlwave-help-quit)
-    (define-key map "w" 'widen)
+    (define-key map "q" #'idlwave-help-quit)
+    (define-key map "w" #'widen)
     (define-key map "\C-m" (lambda (arg)
                              (interactive "p")
                              (scroll-up arg)))
-    (define-key map " " 'scroll-up-command)
-    (define-key map [?\S-\ ] 'scroll-down-command)
-    (define-key map [delete] 'scroll-down-command)
-    (define-key map "h" 'idlwave-help-find-header)
-    (define-key map "H" 'idlwave-help-find-first-header)
-    (define-key map "." 'idlwave-help-toggle-header-match-and-def)
-    (define-key map "F" 'idlwave-help-fontify)
-    (define-key map "\M-?" 'idlwave-help-return-to-calling-frame)
-    (define-key map "x" 'idlwave-help-return-to-calling-frame)
+    (define-key map " " #'scroll-up-command)
+    (define-key map [?\S-\ ] #'scroll-down-command)
+    (define-key map [delete] #'scroll-down-command)
+    (define-key map "h" #'idlwave-help-find-header)
+    (define-key map "H" #'idlwave-help-find-first-header)
+    (define-key map "." #'idlwave-help-toggle-header-match-and-def)
+    (define-key map "F" #'idlwave-help-fontify)
+    (define-key map "\M-?" #'idlwave-help-return-to-calling-frame)
+    (define-key map "x" #'idlwave-help-return-to-calling-frame)
     map)
   "The keymap used in `idlwave-help-mode'.")
 
@@ -374,7 +357,7 @@ It collects and prints the diagnostics messages."
       (setq idlwave-last-context-help-pos marker)
       (idlwave-do-context-help1 arg)
       (if idlwave-help-diagnostics
-         (message "%s" (mapconcat 'identity
+         (message "%s" (mapconcat #'identity
                                   (nreverse idlwave-help-diagnostics)
                                   "; "))))))
 
@@ -384,6 +367,12 @@ It collects and prints the diagnostics messages."
 (defvar idlwave-system-variables-alist)
 (defvar idlwave-executive-commands-alist)
 (defvar idlwave-system-class-info)
+(defvar idlwave-query-class)
+(defvar idlwave-force-class-query)
+(defvar idlw-help-name)
+(defvar idlw-help-kwd)
+(defvar idlw-help-link)
+
 (defun idlwave-do-context-help1 (&optional arg)
   "The work-horse version of `idlwave-context-help', which see."
   (save-excursion
@@ -549,16 +538,16 @@ It collects and prints the diagnostics messages."
        (setq mod1 (append (list t) module))))
       (if mod3
          (condition-case nil
-             (apply 'idlwave-online-help mod1)
+             (apply #'idlwave-online-help mod1)
            (error (condition-case nil
-                      (apply 'idlwave-online-help mod2)
-                    (error (apply 'idlwave-online-help mod3)))))
+                      (apply #'idlwave-online-help mod2)
+                    (error (apply #'idlwave-online-help mod3)))))
        (if mod2
            (condition-case nil
-               (apply 'idlwave-online-help mod1)
-             (error (apply 'idlwave-online-help mod2)))
+               (apply #'idlwave-online-help mod1)
+             (error (apply #'idlwave-online-help mod2)))
          (if mod1
-             (apply 'idlwave-online-help mod1)
+             (apply #'idlwave-online-help mod1)
            (error "Don't know which item to show help for")))))))
 
 (defun idlwave-do-mouse-completion-help (ev)
@@ -660,7 +649,7 @@ Those words in `idlwave-completion-help-links' have links.  
The
                 (props (list 'face 'idlwave-help-link))
                 (info idlwave-completion-help-info) ; global passed in
                 (what (nth 0 info))  ; what was completed, or a func
-                (class (nth 3 info)) ; any class
+                ;; (class (nth 3 info)) ; any class
                 word beg end doit)
            (goto-char (point-min))
            (re-search-forward "possible completions are:" nil t)
@@ -685,7 +674,7 @@ Those words in `idlwave-completion-help-links' have links.  
The
 
 ;; Arrange for this function to be called after completion
 (add-hook 'idlwave-completion-setup-hook
-         'idlwave-highlight-linked-completions)
+         #'idlwave-highlight-linked-completions)
 
 (defvar idlwave-help-return-frame nil
   "The frame to return to from the help frame.")
@@ -947,7 +936,7 @@ This function can be used as `idlwave-extra-help-function'."
     (point)))
 
 
-(defun idlwave-help-find-routine-definition (name type class keyword)
+(defun idlwave-help-find-routine-definition (name type class _keyword)
   "Find the definition of routine CLASS::NAME in current buffer.
 Returns the point of match if successful, nil otherwise.
 KEYWORD is ignored."
@@ -967,7 +956,7 @@ KEYWORD is ignored."
 
 (defvar idlwave-doclib-start)
 (defvar idlwave-doclib-end)
-(defun idlwave-help-find-in-doc-header (name type class keyword
+(defun idlwave-help-find-in-doc-header (name _type class keyword
                                             &optional exact)
   "Find the requested help in the doc-header above point.
 
@@ -1025,9 +1014,9 @@ If there is a match, we assume it is the keyword 
description."
                   ":[ \t]*$\\)"))
 
         ;; Header start plus name
-        (header-re (concat "\\(" idlwave-doclib-start "\\).*\n"
-                           "\\(^;+.*\n\\)*"
-                           "\\(" name-re "\\)"))
+        ;; (header-re (concat "\\(" idlwave-doclib-start "\\).*\n"
+        ;;                 "\\(^;+.*\n\\)*"
+        ;;                 "\\(" name-re "\\)"))
         ;; A keywords section
         (kwds-re (concat                                   ; forgiving
                   "^;+\\*?[ \t]*"
@@ -1095,8 +1084,8 @@ When DING is non-nil, ring the bell as well."
              (cons string idlwave-help-diagnostics))
        (if ding (ding)))))
 
-(defun idlwave-help-toggle-header-top-and-def (arg)
-  (interactive "P")
+(defun idlwave-help-toggle-header-top-and-def (&optional _arg)
+  (interactive)
   (let (pos)
     (if idlwave-help-in-header
        ;; Header was the last thing displayed
@@ -1119,8 +1108,8 @@ When DING is non-nil, ring the bell as well."
          (goto-char pos)
          (recenter 0)))))
 
-(defun idlwave-help-find-first-header (arg)
-  (interactive "P")
+(defun idlwave-help-find-first-header (&optional _arg)
+  (interactive)
   (let (pos)
     (save-excursion
       (goto-char (point-min))
@@ -1140,8 +1129,8 @@ When DING is non-nil, ring the bell as well."
     (setq idlwave-help-in-header nil)
     (idlwave-help-toggle-header-match-and-def arg 'top)))
 
-(defun idlwave-help-toggle-header-match-and-def (arg &optional top)
-  (interactive "P")
+(defun idlwave-help-toggle-header-match-and-def (&optional _arg top)
+  (interactive)
   (let ((args idlwave-help-args)
        pos)
     (if idlwave-help-in-header
@@ -1150,7 +1139,7 @@ When DING is non-nil, ring the bell as well."
          (setq idlwave-help-in-header nil)
          (setq pos idlwave-help-def-pos))
       ;; Try to display header
-      (setq pos (apply 'idlwave-help-find-in-doc-header
+      (setq pos (apply #'idlwave-help-find-in-doc-header
                       (if top
                           (list (car args) (nth 1 args) (nth 2 args) nil)
                         args)))
@@ -1184,7 +1173,7 @@ Useful when source code is displayed as help.  See the 
option
         (with-no-warnings (font-lock-fontify-buffer))))))
 
 
-(defun idlwave-help-error (name type class keyword)
+(defun idlwave-help-error (name _type class keyword)
   (error "Can't find help on %s%s %s"
         (or (and (or class name) (idlwave-make-full-name class name))
             "<unknown>")
@@ -1272,11 +1261,11 @@ IDL assistant.")
          (delete-process idlwave-help-assistant-socket))
 
       (setq idlwave-help-assistant-process
-           (apply 'start-process
+           (apply #'start-process
                   "IDL_ASSISTANT_PROC" nil command "-server" extra-args))
 
       (set-process-filter idlwave-help-assistant-process
-                         (lambda (proc string)
+                         (lambda (_proc string)
                            (setq port (string-to-number string))))
       (unless (accept-process-output idlwave-help-assistant-process 15)
        (error "Failed binding IDL_ASSISTANT socket"))
diff --git a/lisp/progmodes/idlw-shell.el b/lisp/progmodes/idlw-shell.el
index 4bc5224..134a6c6 100644
--- a/lisp/progmodes/idlw-shell.el
+++ b/lisp/progmodes/idlw-shell.el
@@ -729,7 +729,7 @@ IDL is currently stopped.")
 
 
 (defconst idlwave-shell-halt-messages-re
-  (mapconcat 'identity idlwave-shell-halt-messages "\\|")
+  (mapconcat #'identity idlwave-shell-halt-messages "\\|")
   "The regular expression computed from `idlwave-shell-halt-messages'.")
 
 (defconst idlwave-shell-trace-message-re
@@ -934,8 +934,8 @@ IDL has currently stepped.")
                "[ \t\n]*\\'"))
 
   (when idlwave-shell-query-for-class
-      (add-to-list (make-local-variable 'idlwave-determine-class-special)
-                  'idlwave-shell-get-object-class)
+      (add-hook 'idlwave-determine-class-functions
+               #'idlwave-shell-get-object-class nil t)
       (setq idlwave-store-inquired-class t))
 
   ;; Make sure comint-last-input-end does not go to beginning of
@@ -950,10 +950,10 @@ IDL has currently stepped.")
   (setq idlwave-shell-default-directory default-directory)
   (setq idlwave-shell-hide-output nil)
 
-  (add-hook 'kill-buffer-hook 'idlwave-shell-kill-shell-buffer-confirm
+  (add-hook 'kill-buffer-hook #'idlwave-shell-kill-shell-buffer-confirm
            nil 'local)
-  (add-hook 'kill-buffer-hook 'idlwave-shell-delete-temp-files nil 'local)
-  (add-hook 'kill-emacs-hook 'idlwave-shell-delete-temp-files)
+  (add-hook 'kill-buffer-hook #'idlwave-shell-delete-temp-files nil 'local)
+  (add-hook 'kill-emacs-hook #'idlwave-shell-delete-temp-files)
 
   ;; Set the optional comint variables
   (when idlwave-shell-comint-settings
@@ -962,7 +962,7 @@ IDL has currently stepped.")
        (set (make-local-variable (car entry)) (cdr entry)))))
 
 
-  (unless (memq 'comint-carriage-motion
+  (unless (memq #'comint-carriage-motion
                (default-value 'comint-output-filter-functions))
     ;; Strip those pesky ctrl-m's.
     (add-hook 'comint-output-filter-functions
@@ -976,18 +976,21 @@ IDL has currently stepped.")
                      (while (search-forward "\r" pmark t)
                        (delete-region (point) (line-beginning-position)))))))
                'append 'local)
-    (add-hook 'comint-output-filter-functions 'comint-strip-ctrl-m nil 'local))
+    (add-hook 'comint-output-filter-functions #'comint-strip-ctrl-m nil 
'local))
 
   ;; Python-mode, bundled with many Emacs installs, quite cavalierly
   ;; adds this function to the global default hook.  It interferes
   ;; with overlay-arrows.
-  (remove-hook 'comint-output-filter-functions 'py-pdbtrack-track-stack-file)
+  ;; FIXME: We should fix this interference rather than globally turn it off.
+  (when (fboundp 'py-pdbtrack-track-stack-file)
+    (remove-hook 'comint-output-filter-functions
+                 #'py-pdbtrack-track-stack-file))
 
   ;; IDLWAVE syntax, and turn on abbreviations
   (set (make-local-variable 'comment-start) ";")
   (setq abbrev-mode t)
 
-  (add-hook 'post-command-hook 'idlwave-command-hook nil t)
+  (add-hook 'post-command-hook #'idlwave-command-hook nil t)
 
   ;; Read the command history?
   (when (and idlwave-shell-save-command-history
@@ -1045,7 +1048,7 @@ IDL has currently stepped.")
       (setq idlwave-path-alist old-path-alist))))
 
 (if (not (fboundp 'idl-shell))
-    (fset 'idl-shell 'idlwave-shell))
+    (defalias 'idl-shell #'idlwave-shell))
 
 (defvar idlwave-shell-idl-wframe nil
   "Frame for displaying the IDL shell window.")
@@ -1120,7 +1123,7 @@ See also the variable `idlwave-shell-prompt-pattern'.
        (and idlwave-shell-use-dedicated-frame
             (setq idlwave-shell-idl-wframe (selected-frame)))
        (add-hook 'idlwave-shell-sentinel-hook
-                 'save-buffers-kill-emacs t))
+                 #'save-buffers-kill-emacs t))
 
     ;; A non-nil arg means, we want a dedicated frame.  This will last
     ;; for the current editing session.
@@ -1130,7 +1133,7 @@ See also the variable `idlwave-shell-prompt-pattern'.
     ;; Check if the process still exists.  If not, create it.
     (unless (comint-check-proc (idlwave-shell-buffer))
       (let* ((prg (or idlwave-shell-explicit-file-name "idl"))
-            (buf (apply 'make-comint
+            (buf (apply #'make-comint
                         idlwave-shell-process-name prg nil
                         (if (stringp idlwave-shell-command-line-options)
                             (idlwave-split-string
@@ -1138,8 +1141,8 @@ See also the variable `idlwave-shell-prompt-pattern'.
                           idlwave-shell-command-line-options)))
             (process (get-buffer-process buf)))
        (setq idlwave-idlwave_routine_info-compiled nil)
-       (set-process-filter process 'idlwave-shell-filter)
-       (set-process-sentinel process 'idlwave-shell-sentinel)
+       (set-process-filter process #'idlwave-shell-filter)
+       (set-process-sentinel process #'idlwave-shell-sentinel)
        (set-buffer buf)
        (idlwave-shell-mode)))
     (let ((window (idlwave-display-buffer (idlwave-shell-buffer) nil
@@ -1315,10 +1318,7 @@ See also the variable `idlwave-shell-input-mode-spells'."
     (setq idlwave-shell-char-mode-active 'exit))
    ((string-match (nth 1 idlwave-shell-input-mode-spells) string)
     ;; Set a timer which will soon start the character loop
-    (if (fboundp 'start-itimer)
-       (start-itimer "IDLWAVE Char Mode" 'idlwave-shell-char-mode-loop 0.5
-                     nil nil t 'no-error)
-      (run-at-time 0.5 nil 'idlwave-shell-char-mode-loop 'no-error)))))
+    (run-at-time 0.5 nil #'idlwave-shell-char-mode-loop 'no-error))))
 
 (defvar keyboard-quit)
 (defun idlwave-shell-char-mode-loop (&optional no-error)
@@ -1396,7 +1396,7 @@ Otherwise just move the line.  Move down unless UP is 
non-nil."
   (idlwave-shell-move-or-history nil arg))
 
 (define-obsolete-function-alias 'idlwave-shell-comint-filter
-  'comint-output-filter "25.1")
+  #'comint-output-filter "25.1")
 
 (defun idlwave-shell-is-running ()
   "Return t if the shell process is running."
@@ -1510,13 +1510,12 @@ and then calls `idlwave-shell-send-command' for any 
pending commands."
                                   proc filtered))))))
 
                  ;; Call the post-command hook
-                 (if (listp idlwave-shell-post-command-hook)
-                     (progn
-                       ;;(message "Calling list")
-                       ;;(prin1 idlwave-shell-post-command-hook)
-                       (eval idlwave-shell-post-command-hook))
-                   ;;(message "Calling command function")
-                   (funcall idlwave-shell-post-command-hook))
+                 (if (functionp idlwave-shell-post-command-hook)
+                     ;;(message "Calling command function")
+                     (funcall idlwave-shell-post-command-hook)
+                   ;;(message "Calling list")
+                   ;;(prin1 idlwave-shell-post-command-hook)
+                   (eval idlwave-shell-post-command-hook t))
 
                  ;; Reset to default state for next command.
                  ;; Also we do not want to find this prompt again.
@@ -1690,7 +1689,7 @@ the above."
        (if bp
            (let ((cmd (idlwave-shell-bp-get bp 'cmd)))
              (if cmd ;; Execute any breakpoint command
-                 (if (listp cmd) (eval cmd) (funcall cmd))))
+                 (if (functionp cmd) (funcall cmd) (eval cmd t))))
          ;; A breakpoint that we did not know about - perhaps it was
          ;; set by the user...  Let's update our list.
          (idlwave-shell-bp-query)))
@@ -1819,7 +1818,7 @@ The size is given by 
`idlwave-shell-graphics-window-size'."
   (interactive "P")
   (let ((n (if n (prefix-numeric-value n) 0)))
     (idlwave-shell-send-command
-     (apply 'format "window,%d,xs=%d,ys=%d"
+     (apply #'format "window,%d,xs=%d,ys=%d"
            n idlwave-shell-graphics-window-size)
      nil (idlwave-shell-hide-p 'misc) nil t)))
 
@@ -1891,7 +1890,7 @@ HEAP_GC, /VERBOSE"
     (while (string-match "^PATH:[ \t]*<\\(.*\\)>[ \t]*\n" path-string start)
       (push (match-string 1 path-string) dirs)
       (setq start (match-end 0)))
-    (setq dirs (mapcar 'file-name-as-directory dirs))
+    (setq dirs (mapcar #'file-name-as-directory dirs))
     (if (string-match "^SYSDIR:[ \t]*<\\(.*\\)>[ \t]*\n" path-string)
        (setq sysdir (file-name-as-directory
                      (match-string 1 path-string))))
@@ -1938,13 +1937,14 @@ HEAP_GC, /VERBOSE"
            key (nth 4 specs)
            keys (if (and (stringp key)
                          (not (string-match "\\` *\\'" key)))
-                    (mapcar 'list
+                    (mapcar #'list
                             (delete "" (idlwave-split-string key " +")))))
       (setq name (idlwave-sintern-routine-or-method name class t)
            class (idlwave-sintern-class class t)
            file (if (equal file "") nil file)
            keys (mapcar (lambda (x)
-                          (list (idlwave-sintern-keyword (car x) t))) keys))
+                          (list (idlwave-sintern-keyword (car x) t)))
+                        keys))
 
       ;; In the following ignore routines already defined in buffers,
       ;; assuming that if the buffer stuff differs, it is a "new"
@@ -2053,7 +2053,7 @@ Change the default directory for the process buffer to 
concur."
              (match-string 1 idlwave-shell-command-output)))))
 
 (defvar idlwave-sint-sysvars nil)
-(idlwave-new-sintern-type 'execcomm)
+(idlwave-new-sintern-type execcomm)
 
 (defun idlwave-shell-complete (&optional arg)
   "Do completion in the idlwave-shell buffer.
@@ -2180,7 +2180,7 @@ overlays."
 (defun idlwave-shell-parse-stack-and-display ()
   (let* ((lines (delete "" (idlwave-split-string
                            idlwave-shell-command-output "^%")))
-        (stack (delq nil (mapcar 'idlwave-shell-parse-line lines)))
+        (stack (delq nil (mapcar #'idlwave-shell-parse-line lines)))
         (nmax (1- (length stack)))
         (nmin 0) message)
     (cond
@@ -2710,45 +2710,34 @@ Runs to the last statement and then steps 1 statement.  
Use the .out command."
   (interactive "P")
   (idlwave-shell-print arg 'help))
 
-(defmacro idlwave-shell-mouse-examine (help &optional ev)
-  "Create a function for generic examination of expressions."
-  `(lambda (event)
-     "Expansion function for expression examination."
-     (interactive "e")
-     (let* ((drag-track (fboundp 'mouse-drag-track))
-           (transient-mark-mode t)
-           (tracker
-            ;; Emacs 22 no longer completes the drag with
-            ;; mouse-drag-region, without an additional
-            ;; event.  mouse-drag-track does so.
-            (if drag-track 'mouse-drag-track 'mouse-drag-region)))
-       (funcall tracker event)
-       (idlwave-shell-print (if (region-active-p) '(4) nil)
-                           ,help ,ev))))
-
-;; Begin terrible hack section -- XEmacs tests for button2 explicitly
-;; on drag events, calling drag-n-drop code if detected.  Ughhh...
-(defun idlwave-default-mouse-track-event-is-with-button (_event _n)
-  (declare (obsolete nil "28.1"))
-  t)
-
-(define-obsolete-function-alias 'idlwave-xemacs-hack-mouse-track 'ignore 
"27.1")
+(defun idlwave-shell--mouse-examine (event help &optional ev)
+  "Expansion function for expression examination."
+  (let* ((transient-mark-mode t))
+    (mouse-drag-track event)
+    (idlwave-shell-print (if (region-active-p) '(4) nil)
+                        help ev)))
+
+(define-obsolete-function-alias
+  'idlwave-default-mouse-track-event-is-with-button #'always "28.1")
+
+(define-obsolete-function-alias 'idlwave-xemacs-hack-mouse-track
+  #'ignore "27.1")
 ;;; End terrible hack section
 
 (defun idlwave-shell-mouse-print (event)
   "Print value of variable at the mouse position, with `print'."
   (interactive "e")
-  (funcall (idlwave-shell-mouse-examine nil) event))
+  (idlwave-shell--mouse-examine event nil))
 
 (defun idlwave-shell-mouse-help (event)
   "Print value of variable at the mouse position, with `help'."
   (interactive "e")
-  (funcall (idlwave-shell-mouse-examine 'help) event))
+  (idlwave-shell--mouse-examine event 'help))
 
 (defun idlwave-shell-examine-select (event)
   "Pop-up a list to select from for examining the expression."
   (interactive "e")
-  (funcall (idlwave-shell-mouse-examine nil event) event))
+  (idlwave-shell--mouse-examine event nil event))
 
 (defmacro idlwave-shell-examine (help)
   "Create a function for key-driven expression examination."
@@ -2814,7 +2803,7 @@ from `idlwave-shell-examine-alist' via mini-buffer 
shortcut key."
        (setq beg (region-beginning)
              end (region-end)))
        (t
-       (idlwave-with-special-syntax
+       (with-syntax-table idlwave-find-symbol-syntax-table
         ;; Move to beginning of current or previous expression
         (if (looking-at "\\<\\|(")
             ;; At beginning of expression, don't move backwards unless
@@ -2847,9 +2836,9 @@ from `idlwave-shell-examine-alist' via mini-buffer 
shortcut key."
        (move-overlay idlwave-shell-expression-overlay beg end
                      (current-buffer))
        (add-hook 'pre-command-hook
-                 'idlwave-shell-delete-expression-overlay))
+                 #'idlwave-shell-delete-expression-overlay))
       (add-hook 'pre-command-hook
-               'idlwave-shell-delete-output-overlay)
+               #'idlwave-shell-delete-output-overlay)
 
       ;; Remove empty or comment-only lines
       (while (string-match "\n[ \t]*\\(;.*\\)?\r*\n" expr)
@@ -2881,7 +2870,7 @@ from `idlwave-shell-examine-alist' via mini-buffer 
shortcut key."
 ;;                        "Print")
                        (idlwave-popup-select
                         ev
-                        (mapcar 'car idlwave-shell-examine-alist)
+                        (mapcar #'car idlwave-shell-examine-alist)
                         "Examine with"))
                      idlwave-shell-examine-alist))))
              (setq help (cdr help-cons))
@@ -2916,9 +2905,8 @@ from `idlwave-shell-examine-alist' via mini-buffer 
shortcut key."
   "Variable to hold the win/height pairs for all *Examine* windows.")
 
 (defvar idlwave-shell-examine-map (make-sparse-keymap))
-(define-key idlwave-shell-examine-map "q" 'idlwave-shell-examine-display-quit)
-(define-key idlwave-shell-examine-map "c" 'idlwave-shell-examine-display-clear)
-
+(define-key idlwave-shell-examine-map "q" #'idlwave-shell-examine-display-quit)
+(define-key idlwave-shell-examine-map "c" 
#'idlwave-shell-examine-display-clear)
 
 (defun idlwave-shell-check-compiled-and-display ()
   "Check examine output for warning about undefined procedure/function."
@@ -3347,9 +3335,10 @@ the breakpoint overlays."
                              count nil condition disabled))))))
       (setq idlwave-shell-bp-alist (cdr idlwave-shell-bp-alist))
       ;; Update breakpoint data
-      (if (eq bp-re bp-re54)
-         (mapc 'idlwave-shell-update-bp old-bp-alist)
-       (mapc 'idlwave-shell-update-bp-command-only old-bp-alist))))
+      (mapc (if (eq bp-re bp-re54)
+               #'idlwave-shell-update-bp
+             #'idlwave-shell-update-bp-command-only)
+           old-bp-alist)))
   ;; Update the breakpoint overlays
   (unless no-show (idlwave-shell-update-bp-overlays))
   ;; Return the new list
@@ -3484,7 +3473,7 @@ The actual line number for a breakpoint in IDL may be 
different from
 the line number used with the IDL breakpoint command.
 Looks for a new breakpoint index number in the list.  This is
 considered the new breakpoint if the file name of frame matches."
-  (let ((obp-index (mapcar 'idlwave-shell-bp-get idlwave-shell-old-bp))
+  (let ((obp-index (mapcar #'idlwave-shell-bp-get idlwave-shell-old-bp))
         (bpl idlwave-shell-bp-alist))
     (while (and (member (idlwave-shell-bp-get (car bpl)) obp-index)
                 (setq bpl (cdr bpl))))
@@ -3510,7 +3499,7 @@ considered the new breakpoint if the file name of frame 
matches."
 
 (defvar idlwave-shell-debug-line-map (make-sparse-keymap))
 (define-key idlwave-shell-debug-line-map [mouse-3]
-  'idlwave-shell-mouse-active-bp)
+  #'idlwave-shell-mouse-active-bp)
 
 (defun idlwave-shell-update-bp-overlays ()
   "Update the overlays which mark breakpoints in the source code.
@@ -3532,7 +3521,7 @@ Existing overlays are recycled, in order to minimize 
consumption."
       (setq ov-alist idlwave-shell-bp-overlays
            idlwave-shell-bp-overlays
            (if idlwave-shell-bp-glyph
-               (mapcar 'list (mapcar 'car idlwave-shell-bp-glyph))
+               (mapcar #'list (mapcar #'car idlwave-shell-bp-glyph))
              (list (list 'bp))))
       (while (setq bp (pop bp-list))
        (save-excursion
@@ -3568,7 +3557,7 @@ Existing overlays are recycled, in order to minimize 
consumption."
                             (if help-list
                                 (concat
                                  " - "
-                                 (mapconcat 'identity help-list ", ")))
+                                 (mapconcat #'identity help-list ", ")))
                             (if (and (not count) (not condition))
                                 " (use mouse-3 for breakpoint actions)")))
                 (full-type (if disabled
@@ -3962,73 +3951,73 @@ Otherwise, just expand the file name."
     ;;(define-key map "\M-?" 'comint-dynamic-list-completions)
     ;;(define-key map "\t" 'comint-dynamic-complete)
 
-    (define-key map "\C-w"     'comint-kill-region)
-    (define-key map "\t"       'idlwave-shell-complete)
-    (define-key map "\M-\t"    'idlwave-shell-complete)
-    (define-key map "\C-c\C-s" 'idlwave-shell)
-    (define-key map "\C-c?"    'idlwave-routine-info)
-    (define-key map "\C-g"     'idlwave-keyboard-quit)
-    (define-key map "\M-?"     'idlwave-context-help)
+    (define-key map "\C-w"     #'comint-kill-region)
+    (define-key map "\t"       #'idlwave-shell-complete)
+    (define-key map "\M-\t"    #'idlwave-shell-complete)
+    (define-key map "\C-c\C-s" #'idlwave-shell)
+    (define-key map "\C-c?"    #'idlwave-routine-info)
+    (define-key map "\C-g"     #'idlwave-keyboard-quit)
+    (define-key map "\M-?"     #'idlwave-context-help)
     (define-key map [(control meta ?\?)]
-      'idlwave-help-assistant-help-with-topic)
-    (define-key map "\C-c\C-i" 'idlwave-update-routine-info)
-    (define-key map "\C-c\C-y" 'idlwave-shell-char-mode-loop)
-    (define-key map "\C-c\C-x" 'idlwave-shell-send-char)
-    (define-key map "\C-c="    'idlwave-resolve)
-    (define-key map "\C-c\C-v" 'idlwave-find-module)
-    (define-key map "\C-c\C-k" 'idlwave-kill-autoloaded-buffers)
+      #'idlwave-help-assistant-help-with-topic)
+    (define-key map "\C-c\C-i" #'idlwave-update-routine-info)
+    (define-key map "\C-c\C-y" #'idlwave-shell-char-mode-loop)
+    (define-key map "\C-c\C-x" #'idlwave-shell-send-char)
+    (define-key map "\C-c="    #'idlwave-resolve)
+    (define-key map "\C-c\C-v" #'idlwave-find-module)
+    (define-key map "\C-c\C-k" #'idlwave-kill-autoloaded-buffers)
     (define-key map idlwave-shell-prefix-key
-      'idlwave-shell-debug-map)
-    (define-key map [(up)]  'idlwave-shell-up-or-history)
-    (define-key map [(down)] 'idlwave-shell-down-or-history)
+      #'idlwave-shell-debug-map)
+    (define-key map [(up)]  #'idlwave-shell-up-or-history)
+    (define-key map [(down)] #'idlwave-shell-down-or-history)
     (define-key idlwave-shell-mode-map [(shift mouse-3)]
-      'idlwave-mouse-context-help)
+      #'idlwave-mouse-context-help)
     map)
   "Keymap for `idlwave-mode'.")
 
 (defvar idlwave-shell-electric-debug-mode-map
   (let ((map (make-sparse-keymap)))
     ;; A few extras in the electric debug map
-    (define-key map " " 'idlwave-shell-step)
-    (define-key map "+" 'idlwave-shell-stack-up)
-    (define-key map "=" 'idlwave-shell-stack-up)
-    (define-key map "-" 'idlwave-shell-stack-down)
-    (define-key map "_" 'idlwave-shell-stack-down)
+    (define-key map " " #'idlwave-shell-step)
+    (define-key map "+" #'idlwave-shell-stack-up)
+    (define-key map "=" #'idlwave-shell-stack-up)
+    (define-key map "-" #'idlwave-shell-stack-down)
+    (define-key map "_" #'idlwave-shell-stack-down)
     (define-key map "e" (lambda () (interactive) (idlwave-shell-print '(16))))
-    (define-key map "q" 'idlwave-shell-retall)
+    (define-key map "q" #'idlwave-shell-retall)
     (define-key map "t"
       (lambda () (interactive) (idlwave-shell-send-command "help,/TRACE")))
-    (define-key map [(control ??)]  'idlwave-shell-electric-debug-help)
+    (define-key map [(control ??)]  #'idlwave-shell-electric-debug-help)
     (define-key map "x"
       (lambda (arg) (interactive "P")
         (idlwave-shell-print arg nil nil t)))
     map))
 
 (defvar idlwave-shell-mode-prefix-map (make-sparse-keymap))
-(fset 'idlwave-shell-mode-prefix-map idlwave-shell-mode-prefix-map)
+(defalias 'idlwave-shell-mode-prefix-map idlwave-shell-mode-prefix-map)
 (defvar idlwave-mode-prefix-map (make-sparse-keymap))
-(fset 'idlwave-mode-prefix-map idlwave-mode-prefix-map)
+(defalias 'idlwave-mode-prefix-map idlwave-mode-prefix-map)
 
 (defun idlwave-shell-define-key-both (key hook)
   "Define a key in both the shell and buffer mode maps."
   (define-key idlwave-mode-map key hook)
   (define-key idlwave-shell-mode-map key hook))
-(define-key idlwave-mode-map "\C-c\C-y" 'idlwave-shell-char-mode-loop)
-(define-key idlwave-mode-map "\C-c\C-x" 'idlwave-shell-send-char)
+(define-key idlwave-mode-map "\C-c\C-y" #'idlwave-shell-char-mode-loop)
+(define-key idlwave-mode-map "\C-c\C-x" #'idlwave-shell-send-char)
 
 ;; The mouse bindings for PRINT and HELP
 (idlwave-shell-define-key-both [(shift down-mouse-2)]
-                               'idlwave-shell-mouse-print)
+                               #'idlwave-shell-mouse-print)
 (idlwave-shell-define-key-both [(control meta down-mouse-2)]
-                               'idlwave-shell-mouse-help)
+                               #'idlwave-shell-mouse-help)
 (idlwave-shell-define-key-both [(control shift down-mouse-2)]
-                               'idlwave-shell-examine-select)
+                               #'idlwave-shell-examine-select)
 
 ;; We need to turn off the button release events.
 
-(idlwave-shell-define-key-both [(shift mouse-2)] 'ignore)
-(idlwave-shell-define-key-both [(shift control mouse-2)] 'ignore)
-(idlwave-shell-define-key-both [(control meta mouse-2)] 'ignore)
+(idlwave-shell-define-key-both [(shift mouse-2)] #'ignore)
+(idlwave-shell-define-key-both [(shift control mouse-2)] #'ignore)
+(idlwave-shell-define-key-both [(control meta mouse-2)] #'ignore)
 
 
 ;; The following set of bindings is used to bind the debugging keys.
@@ -4109,8 +4098,8 @@ Otherwise, just expand the file name."
          cmd))))
 
 ; Enter the prefix map in two places.
-(fset 'idlwave-debug-map       idlwave-mode-prefix-map)
-(fset 'idlwave-shell-debug-map idlwave-shell-mode-prefix-map)
+(defalias 'idlwave-debug-map       idlwave-mode-prefix-map)
+(defalias 'idlwave-shell-debug-map idlwave-shell-mode-prefix-map)
 
 ;; The Electric Debug Minor Mode --------------------------------------------
 
@@ -4496,6 +4485,6 @@ static char * file[] = {
   (idlwave-toolbar-toggle))
 
 (if idlwave-shell-use-toolbar
-    (add-hook 'idlwave-shell-mode-hook 'idlwave-toolbar-add-everywhere))
+    (add-hook 'idlwave-shell-mode-hook #'idlwave-toolbar-add-everywhere))
 
 ;;; idlw-shell.el ends here
diff --git a/lisp/progmodes/idlw-toolbar.el b/lisp/progmodes/idlw-toolbar.el
index 4bd0afb..d3f47fc 100644
--- a/lisp/progmodes/idlw-toolbar.el
+++ b/lisp/progmodes/idlw-toolbar.el
@@ -1,4 +1,4 @@
-;;; idlw-toolbar.el --- a debugging toolbar for IDLWAVE
+;;; idlw-toolbar.el --- a debugging toolbar for IDLWAVE  -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 1999-2021 Free Software Foundation, Inc.
 
@@ -24,8 +24,8 @@
 
 ;;; Commentary:
 
-;; This file implements a debugging toolbar for IDLWAVE.  It requires
-;; Emacs or XEmacs with toolbar and xpm support.
+;; This file implements a debugging toolbar for IDLWAVE.
+;; It requires toolbar and xpm support.
 
 ;; New versions of IDLWAVE, documentation, and more information
 ;; available from:
@@ -35,22 +35,16 @@
 ;;; Code:
 
 (defun idlwave-toolbar-make-button (image)
-  (if (featurep 'xemacs)
-      (toolbar-make-button-list image)
-    (list 'image :type 'xpm :data image)))
+  (list 'image :type 'xpm :data image))
 
 (defvar idlwave-toolbar)
 (defvar default-toolbar)
 (defvar idlwave-toolbar-is-possible)
 
-(if (not (or (and (featurep 'xemacs)                ; This is XEmacs
-                 (featurep 'xpm)                   ; need xpm
-                 (featurep 'toolbar))              ; ... and the toolbar
-            (and (not (featurep 'xemacs))          ; This is Emacs
-                 (boundp 'tool-bar-button-margin)   ; need toolbar
-                 (fboundp 'image-type-available-p) ; need image stuff
-                 (image-type-available-p 'xpm))    ; need xpm
-            ))
+(if (not (and (boundp 'tool-bar-button-margin)   ; need toolbar
+             (fboundp 'image-type-available-p) ; need image stuff
+             (image-type-available-p 'xpm))    ; need xpm
+        )
     ;; oops - cannot do the toolbar
     (message "Sorry, IDLWAVE xpm toolbar cannot be used on this version of 
Emacs")
 ;; OK, we can define a toolbar
@@ -873,23 +867,12 @@ static char * file[] = {
 
 ;; When the shell exits, arrange to remove the special toolbar everywhere.
 (add-hook 'idlwave-shell-cleanup-hook
-         'idlwave-toolbar-remove-everywhere)
+         #'idlwave-toolbar-remove-everywhere)
 );; End can define toolbar
 
-(defun idlwave-toolbar-add ()
-  "Add the IDLWAVE toolbar if appropriate."
-  (if (and (featurep 'xemacs)    ; This is a noop on Emacs
-          (boundp 'idlwave-toolbar-is-possible)
-          (derived-mode-p 'idlwave-mode 'idlwave-shell-mode))
-      (set-specifier default-toolbar (cons (current-buffer)
-                                          idlwave-toolbar))))
-
-(defun idlwave-toolbar-remove ()
-  "Add the IDLWAVE toolbar if appropriate."
-  (if (and (featurep 'xemacs)    ; This is a noop on Emacs
-          (boundp 'idlwave-toolbar-is-possible)
-           (derived-mode-p 'idlwave-mode 'idlwave-shell-mode))
-      (remove-specifier default-toolbar (current-buffer))))
+(define-obsolete-function-alias 'idlwave-toolbar-add #'ignore "28.1")
+
+(define-obsolete-function-alias 'idlwave-toolbar-remove #'ignore "28.1")
 
 (defvar idlwave-shell-mode-map)
 (defvar idlwave-mode-map)
@@ -898,57 +881,40 @@ static char * file[] = {
   "Add the toolbar in all appropriate buffers."
   (when (boundp 'idlwave-toolbar-is-possible)
 
-    ;; First make sure new buffers will get the toolbar
-    (add-hook 'idlwave-mode-hook 'idlwave-toolbar-add)
     ;; Then add it to all existing buffers
-    (if (featurep 'xemacs)
-       ;; For XEmacs, map over all buffers to add toolbar
-       (save-excursion
-         (mapcar (lambda (buf)
-                   (set-buffer buf)
-                   (idlwave-toolbar-add))
-                 (buffer-list)))
-      ;; For Emacs, add the key definitions to the mode maps
-      (mapc (lambda (x)
-             (let* ((icon (aref x 0))
-                    (func (aref x 1))
-                    (show (aref x 2))
-                    (help (aref x 3))
-                    (key (vector 'tool-bar func))
-                    (def (list 'menu-item
-                               ""
-                               func
-                               :image (symbol-value icon)
-                               :visible show
-                               :help help)))
-               (define-key idlwave-mode-map key def)
-               (define-key idlwave-shell-mode-map key def)))
-           (reverse idlwave-toolbar)))
+    ;; For Emacs, add the key definitions to the mode maps
+    (mapc (lambda (x)
+           (let* ((icon (aref x 0))
+                  (func (aref x 1))
+                  (show (aref x 2))
+                  (help (aref x 3))
+                  (key (vector 'tool-bar func))
+                  (def (list 'menu-item
+                             ""
+                             func
+                             :image (symbol-value icon)
+                             :visible show
+                             :help help)))
+             (define-key idlwave-mode-map key def)
+             (define-key idlwave-shell-mode-map key def)))
+         (reverse idlwave-toolbar))
     (setq idlwave-toolbar-visible t)))
 
 (defun idlwave-toolbar-remove-everywhere ()
   "Remove the toolbar in all appropriate buffers."
   ;; First make sure new buffers won't get the toolbar
   (when idlwave-toolbar-is-possible
-    (remove-hook 'idlwave-mode-hook 'idlwave-toolbar-add)
     ;; Then remove it in all existing buffers.
-    (if (featurep 'xemacs)
-       ;; For XEmacs, map over all buffers to remove toolbar
-       (save-excursion
-         (mapcar (lambda (buf)
-                   (set-buffer buf)
-                   (idlwave-toolbar-remove))
-                 (buffer-list)))
-      ;; For Emacs, remove the key definitions from the mode maps
-      (mapc (lambda (x)
-             (let* (;;(icon (aref x 0))
-                    (func (aref x 1))
-                    ;;(show (aref x 2))
-                    ;;(help (aref x 3))
-                    (key (vector 'tool-bar func)))
-               (define-key idlwave-mode-map key nil)
-               (define-key idlwave-shell-mode-map key nil)))
-           idlwave-toolbar))
+    ;; For Emacs, remove the key definitions from the mode maps
+    (mapc (lambda (x)
+           (let* (;;(icon (aref x 0))
+                  (func (aref x 1))
+                  ;;(show (aref x 2))
+                  ;;(help (aref x 3))
+                  (key (vector 'tool-bar func)))
+             (define-key idlwave-mode-map key nil)
+             (define-key idlwave-shell-mode-map key nil)))
+         idlwave-toolbar)
     (setq idlwave-toolbar-visible nil)))
 
 (defun idlwave-toolbar-toggle (&optional force-on)
@@ -956,11 +922,8 @@ static char * file[] = {
   (if idlwave-toolbar-visible
       (or force-on (idlwave-toolbar-remove-everywhere))
     (idlwave-toolbar-add-everywhere))
-  ;; Now make sure this
-  (if (featurep 'xemacs)
-      nil ; no action necessary, toolbar gets updated automatically
-    ;; On Emacs, redraw the frame to make sure the Toolbar is updated.
-    (redraw-frame)))
+  ;; On Emacs, redraw the frame to make sure the Toolbar is updated.
+  (redraw-frame))
 
 (provide 'idlw-toolbar)
 (provide 'idlwave-toolbar)
diff --git a/lisp/progmodes/idlwave.el b/lisp/progmodes/idlwave.el
index e8e55ae..75f2016 100644
--- a/lisp/progmodes/idlwave.el
+++ b/lisp/progmodes/idlwave.el
@@ -1,4 +1,4 @@
-;; idlwave.el --- IDL editing mode for GNU Emacs
+;; idlwave.el --- IDL editing mode for GNU Emacs  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1999-2021 Free Software Foundation, Inc.
 
@@ -781,7 +781,7 @@ definitions, use the command `list-abbrevs', for abbrevs 
that move
 point.  Moving point is useful, for example, to place point between
 parentheses of expanded functions.
 
-See `idlwave-check-abbrev'."
+See `idlwave-modify-abbrev'."
   :group 'idlwave-abbrev-and-indent-action
   :type 'boolean)
 
@@ -819,18 +819,19 @@ Has effect only if in abbrev-mode."
 ;; Example actions:
 ;;
 ;;  Capitalize system vars
-;;   (idlwave-action-and-binding idlwave-sysvar '(capitalize-word 1) t)
+;;   (idlwave-action-and-binding idlwave-sysvar
+;;                               (lambda (_) (capitalize-word 1)) t)
 ;;
 ;;  Capitalize procedure name
 ;;   (idlwave-action-and-binding "\\<\\(pro\\|function\\)\\>[ \t]*\\<"
-;;                           '(capitalize-word 1) t)
+;;                               (lambda (_) (capitalize-word 1)) t)
 ;;
 ;;  Capitalize common block name
 ;;   (idlwave-action-and-binding "\\<common\\>[ \t]+\\<"
-;;                           '(capitalize-word 1) t)
+;;                               (lambda (_) (capitalize-word 1)) t)
 ;;  Capitalize label
 ;;   (idlwave-action-and-binding (concat "^[ \t]*" idlwave-label)
-;;                           '(capitalize-word -1) t)
+;;                               (lambda (_) (capitalize-word 1)) t)
 
 (defvar idlwave-indent-action-table nil
   "Associated array containing action lists of search string (car),
@@ -1121,91 +1122,101 @@ As a user, you should not set this to t.")
   
"\\<\\(&&\\|and\\|b\\(egin\\|reak\\)\\|c\\(ase\\|o\\(mpile_opt\\|ntinue\\)\\)\\|do\\|e\\(lse\\|nd\\(case\\|else\\|for\\|if\\|rep\\|switch\\|while\\)?\\|q\\)\\|for\\(ward_function\\)?\\|g\\(oto\\|[et]\\)\\|i\\(f\\|nherits\\)\\|l[et]\\|mod\\|n\\(e\\|ot\\)\\|o\\(n_\\(error\\|ioerror\\)\\|[fr]\\)\\|re\\(peat\\|turn\\)\\|switch\\|then\\|until\\|while\\|xor\\|||\\)\\>")
 
 
-(let* (;; Procedure declarations.  Fontify keyword plus procedure name.
-       ;; Function  declarations.  Fontify keyword plus function  name.
-       (pros-and-functions
-       '("\\<\\(function\\|pro\\)\\>[ \t]+\\(\\sw+\\(::\\sw+\\)?\\)"
-         (1 font-lock-keyword-face)
-         (2 font-lock-function-name-face nil t)))
-
-       ;; Common blocks
-       (common-blocks
-       '("\\<\\(common\\)\\>[ \t]*\\(\\sw+\\)?[ \t]*,?"
-         (1 font-lock-keyword-face)        ; "common"
-         (2 font-lock-constant-face nil t) ; block name
-         ("[ \t]*\\(\\sw+\\)[ ,]*"
-          ;; Start with point after block name and comma
-          nil nil (1 font-lock-variable-name-face))))       ; variable names
-
-       ;; Batch files
-       (batch-files
-       '("^[ \t]*\\(@[^ \t\n]+\\)" (1 font-lock-string-face)))
-
-       ;; Labels
-       (label
-       '("^[ \t]*\\([a-zA-Z]\\sw*:\\)" (1 font-lock-constant-face)))
-
-       ;; The goto statement and its label
-       (goto
-       '("\\(goto\\)[ \t]*,[ \t]*\\([a-zA-Z]\\sw*\\)"
-         (1 font-lock-keyword-face)
-         (2 font-lock-constant-face)))
-
-       ;; Tags in structure definitions.  Note that this definition
-       ;; actually collides with labels, so we have to use the same
-       ;; face.  It also matches named subscript ranges,
-       ;; e.g. vec{bottom:top].  No good way around this.
-       (structtag
-       '("\\<\\([a-zA-Z][a-zA-Z0-9_]*:\\)[^:]" (1 font-lock-constant-face)))
-
-       ;; Structure names
-       (structname
-       '("\\({\\|\\<inherits\\s-\\)\\s-*\\([a-zA-Z][a-zA-Z0-9_]*\\)[},\t \n]"
-         (2 font-lock-function-name-face)))
-
-       ;; Keyword parameters, like /xlog or ,xrange=[]
-       ;; This is anchored to the comma preceding the keyword.
-       ;; Treats continuation lines, works only during whole buffer
-       ;; fontification.  Slow, use it only in fancy fontification.
-       (keyword-parameters
-       '("\\(,\\|[a-zA-Z0-9_](\\)[ \t]*\\(\\$[ \t]*\\(;.*\\)?\n\\([ 
\t]*\\(;.*\\)?\n\\)*[ \t]*\\)?\\(/[a-zA-Z_]\\sw*\\|[a-zA-Z_]\\sw*[ \t]*=\\)"
-         (6 font-lock-constant-face)))
-
-       ;; System variables start with a bang.
-       (system-variables
-       '("\\(![a-zA-Z_0-9]+\\(\\.\\sw+\\)?\\)"
-         (1 font-lock-variable-name-face)))
-
-       ;; Special and unusual operators (not used because too noisy)
-       ;; (special-operators
-       ;;  '("[<>#]" (0 font-lock-keyword-face)))
-
-       ;; All operators (not used because too noisy)
-       ;; (all-operators
-       ;;  '("[-*^#+<>/]" (0 font-lock-keyword-face)))
-
-       ;; Arrows with text property `idlwave-class'
-       (class-arrows
-       '(idlwave-match-class-arrows (0 idlwave-class-arrow-face))))
+(defmacro idlwave--dlet (binders &rest body)
+  "Like `dlet' but without warnings about non-prefixed var names."
+  (declare (indent 1) (debug let))
+  (let ((vars (mapcar (lambda (binder)
+                        (if (consp binder) (car binder) binder))
+                      binders)))
+    `(with-suppressed-warnings ((lexical ,@vars))
+       (dlet ,binders ,@body))))
+
+(idlwave--dlet
+    (;; Procedure declarations.  Fontify keyword plus procedure name.
+     ;; Function  declarations.  Fontify keyword plus function  name.
+     (pros-and-functions
+      '("\\<\\(function\\|pro\\)\\>[ \t]+\\(\\sw+\\(::\\sw+\\)?\\)"
+       (1 font-lock-keyword-face)
+       (2 font-lock-function-name-face nil t)))
+
+     ;; Common blocks
+     (common-blocks
+      '("\\<\\(common\\)\\>[ \t]*\\(\\sw+\\)?[ \t]*,?"
+       (1 font-lock-keyword-face)          ; "common"
+       (2 font-lock-constant-face nil t)   ; block name
+       ("[ \t]*\\(\\sw+\\)[ ,]*"
+        ;; Start with point after block name and comma
+        nil nil (1 font-lock-variable-name-face)))) ; variable names
+
+     ;; Batch files
+     (batch-files
+      '("^[ \t]*\\(@[^ \t\n]+\\)" (1 font-lock-string-face)))
+
+     ;; Labels
+     (label
+      '("^[ \t]*\\([a-zA-Z]\\sw*:\\)" (1 font-lock-constant-face)))
+
+     ;; The goto statement and its label
+     (goto
+      '("\\(goto\\)[ \t]*,[ \t]*\\([a-zA-Z]\\sw*\\)"
+       (1 font-lock-keyword-face)
+       (2 font-lock-constant-face)))
+
+     ;; Tags in structure definitions.  Note that this definition
+     ;; actually collides with labels, so we have to use the same
+     ;; face.  It also matches named subscript ranges,
+     ;; e.g. vec{bottom:top].  No good way around this.
+     (structtag
+      '("\\<\\([a-zA-Z][a-zA-Z0-9_]*:\\)[^:]" (1 font-lock-constant-face)))
+
+     ;; Structure names
+     (structname
+      '("\\({\\|\\<inherits\\s-\\)\\s-*\\([a-zA-Z][a-zA-Z0-9_]*\\)[},\t \n]"
+       (2 font-lock-function-name-face)))
+
+     ;; Keyword parameters, like /xlog or ,xrange=[]
+     ;; This is anchored to the comma preceding the keyword.
+     ;; Treats continuation lines, works only during whole buffer
+     ;; fontification.  Slow, use it only in fancy fontification.
+     (keyword-parameters
+      '("\\(,\\|[a-zA-Z0-9_](\\)[ \t]*\\(\\$[ \t]*\\(;.*\\)?\n\\([ 
\t]*\\(;.*\\)?\n\\)*[ \t]*\\)?\\(/[a-zA-Z_]\\sw*\\|[a-zA-Z_]\\sw*[ \t]*=\\)"
+       (6 font-lock-constant-face)))
+
+     ;; System variables start with a bang.
+     (system-variables
+      '("\\(![a-zA-Z_0-9]+\\(\\.\\sw+\\)?\\)"
+       (1 font-lock-variable-name-face)))
+
+     ;; Special and unusual operators (not used because too noisy)
+     ;; (special-operators
+     ;;  '("[<>#]" (0 font-lock-keyword-face)))
+
+     ;; All operators (not used because too noisy)
+     ;; (all-operators
+     ;;  '("[-*^#+<>/]" (0 font-lock-keyword-face)))
+
+     ;; Arrows with text property `idlwave-class'
+     (class-arrows
+      '(idlwave-match-class-arrows (0 idlwave-class-arrow-face))))
 
   (defconst idlwave-font-lock-keywords-1
     (list pros-and-functions batch-files)
     "Subdued level highlighting for IDLWAVE mode.")
 
   (defconst idlwave-font-lock-keywords-2
-    (mapcar 'symbol-value idlwave-default-font-lock-items)
+    (mapcar #'symbol-value idlwave-default-font-lock-items)
     "Medium level highlighting for IDLWAVE mode.")
 
   (defconst idlwave-font-lock-keywords-3
-       (list pros-and-functions
-             batch-files
-             idlwave-idl-keywords
-             label goto
-             structtag
-             structname
-             common-blocks
-             keyword-parameters
-             system-variables
+    (list pros-and-functions
+         batch-files
+         idlwave-idl-keywords
+         label goto
+         structtag
+         structname
+         common-blocks
+         keyword-parameters
+         system-variables
          class-arrows)
     "Gaudy level highlighting for IDLWAVE mode."))
 
@@ -1312,13 +1323,16 @@ blocks starting with a BEGIN statement.  The matches 
must have associations
    (cons 'call (list (concat "\\(" idlwave-variable "\\) *= *"
                             "\\(" idlwave-method-call "\\s *\\)?"
                             idlwave-identifier
-                            "\\s *(") nil))
+                            "\\s *(")
+                    nil))
    (cons 'call (list (concat
                      "\\(" idlwave-method-call "\\s *\\)?"
                      idlwave-identifier
-                     "\\( *\\($\\|\\$\\)\\|\\s *,\\)") nil))
+                     "\\( *\\($\\|\\$\\)\\|\\s *,\\)")
+                    nil))
    (cons 'assign (list (concat
-                       "\\(" idlwave-variable "\\) *=") nil)))
+                       "\\(" idlwave-variable "\\) *=")
+                      nil)))
 
   "Associated list of statement matching regular expressions.
 Each regular expression matches the start of an IDL statement.
@@ -1333,10 +1347,6 @@ list order matters since matching an assignment 
statement exactly is
 not possible without parsing.  Thus assignment statement become just
 the leftover unidentified statements containing an equal sign.")
 
-;; FIXME: This var seems to only ever be set, but never actually used!
-(defvar idlwave-fill-function 'auto-fill-function
-  "IDL mode auto fill function.")
-
 (defvar idlwave-comment-indent-function 'comment-indent-function
   "IDL mode comment indent function.")
 
@@ -1353,28 +1363,9 @@ Normally a space.")
 
 (defconst idlwave-mode-version "6.1_em22")
 
-(defmacro idlwave-keyword-abbrev (&rest args)
-  "Creates a function for abbrev hooks to call `idlwave-check-abbrev' with 
args."
-  `(lambda ()
-     ,(append '(idlwave-check-abbrev) args)))
-
-;; If I take the time I can replace idlwave-keyword-abbrev with
-;; idlwave-code-abbrev and remove the quoted abbrev check from
-;; idlwave-check-abbrev.  Then, e.g, (idlwave-keyword-abbrev 0 t) becomes
-;; (idlwave-code-abbrev idlwave-check-abbrev 0 t).  In fact I should change
-;; the name of idlwave-check-abbrev to something like idlwave-modify-abbrev.
-
-(defmacro idlwave-code-abbrev (&rest args)
-  "Creates a function for abbrev hooks that ensures abbrevs are not quoted.
-Specifically, if the abbrev is in a comment or string it is unexpanded.
-Otherwise ARGS forms a list that is evaluated."
-  ;; FIXME: it would probably be better to rely on the new :enable-function
-  ;; to enforce the "don't expand in comments or strings".
-  `(lambda ()
-     ,(prin1-to-string args)  ;; Puts the code in the doc string
-     (if (idlwave-quoted)
-         (progn (unexpand-abbrev) nil)
-       ,(append args))))
+(defun idlwave-keyword-abbrev (&rest args)
+  "Create a function for abbrev hooks to call `idlwave-modify-abbrev' with 
args."
+  (lambda () (append #'idlwave-modify-abbrev args)))
 
 (autoload 'idlwave-shell "idlw-shell"
   "Run an inferior IDL, with I/O through buffer `(idlwave-shell-buffer)'." t)
@@ -1388,41 +1379,41 @@ Otherwise ARGS forms a list that is evaluated."
 (autoload 'idlwave-shell-run-region "idlw-shell"
   "Compile and run the region." t)
 
-(fset 'idlwave-debug-map (make-sparse-keymap))
+(defalias 'idlwave-debug-map (make-sparse-keymap))
 
 (defvar idlwave-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "\C-c "    'idlwave-hard-tab)
-    (define-key map [(control tab)] 'idlwave-hard-tab)
-    ;;(define-key map "\C-c\C- " 'idlwave-hard-tab)
-    (define-key map "'"        'idlwave-show-matching-quote)
-    (define-key map "\""       'idlwave-show-matching-quote)
-    (define-key map "\C-g"     'idlwave-keyboard-quit)
-    (define-key map "\C-c;"    'idlwave-toggle-comment-region)
-    (define-key map "\C-\M-a"  'idlwave-beginning-of-subprogram)
-    (define-key map "\C-\M-e"  'idlwave-end-of-subprogram)
-    (define-key map "\C-c{"    'idlwave-beginning-of-block)
-    (define-key map "\C-c}"    'idlwave-end-of-block)
-    (define-key map "\C-c]"    'idlwave-close-block)
-    (define-key map [(meta control h)] 'idlwave-mark-subprogram)
-    (define-key map "\M-\C-n"  'idlwave-forward-block)
-    (define-key map "\M-\C-p"  'idlwave-backward-block)
-    (define-key map "\M-\C-d"  'idlwave-down-block)
-    (define-key map "\M-\C-u"  'idlwave-backward-up-block)
-    (define-key map "\M-\r"    'idlwave-split-line)
-    (define-key map "\M-\C-q"  'idlwave-indent-subprogram)
-    (define-key map "\C-c\C-p" 'idlwave-previous-statement)
-    (define-key map "\C-c\C-n" 'idlwave-next-statement)
-    ;; (define-key map "\r"       'idlwave-newline)
-    ;; (define-key map "\t"       'idlwave-indent-line)
-    (define-key map [(shift iso-lefttab)] 'idlwave-indent-statement)
-    (define-key map "\C-c\C-a" 'idlwave-auto-fill-mode)
-    (define-key map "\M-q"     'idlwave-fill-paragraph)
-    (define-key map "\M-s"     'idlwave-edit-in-idlde)
-    (define-key map "\C-c\C-h" 'idlwave-doc-header)
-    (define-key map "\C-c\C-m" 'idlwave-doc-modification)
-    (define-key map "\C-c\C-c" 'idlwave-case)
-    (define-key map "\C-c\C-d" 'idlwave-debug-map)
+    (define-key map "\C-c "    #'idlwave-hard-tab)
+    (define-key map [(control tab)] #'idlwave-hard-tab)
+    ;;(define-key map "\C-c\C- " #'idlwave-hard-tab)
+    (define-key map "'"        #'idlwave-show-matching-quote)
+    (define-key map "\""       #'idlwave-show-matching-quote)
+    (define-key map "\C-g"     #'idlwave-keyboard-quit)
+    (define-key map "\C-c;"    #'idlwave-toggle-comment-region)
+    (define-key map "\C-\M-a"  #'idlwave-beginning-of-subprogram)
+    (define-key map "\C-\M-e"  #'idlwave-end-of-subprogram)
+    (define-key map "\C-c{"    #'idlwave-beginning-of-block)
+    (define-key map "\C-c}"    #'idlwave-end-of-block)
+    (define-key map "\C-c]"    #'idlwave-close-block)
+    (define-key map [(meta control h)] #'idlwave-mark-subprogram)
+    (define-key map "\M-\C-n"  #'idlwave-forward-block)
+    (define-key map "\M-\C-p"  #'idlwave-backward-block)
+    (define-key map "\M-\C-d"  #'idlwave-down-block)
+    (define-key map "\M-\C-u"  #'idlwave-backward-up-block)
+    (define-key map "\M-\r"    #'idlwave-split-line)
+    (define-key map "\M-\C-q"  #'idlwave-indent-subprogram)
+    (define-key map "\C-c\C-p" #'idlwave-previous-statement)
+    (define-key map "\C-c\C-n" #'idlwave-next-statement)
+    ;; (define-key map "\r"       #'idlwave-newline)
+    ;; (define-key map "\t"       #'idlwave-indent-line)
+    (define-key map [(shift iso-lefttab)] #'idlwave-indent-statement)
+    (define-key map "\C-c\C-a" #'auto-fill-mode)
+    (define-key map "\M-q"     #'idlwave-fill-paragraph)
+    (define-key map "\M-s"     #'idlwave-edit-in-idlde)
+    (define-key map "\C-c\C-h" #'idlwave-doc-header)
+    (define-key map "\C-c\C-m" #'idlwave-doc-modification)
+    (define-key map "\C-c\C-c" #'idlwave-case)
+    (define-key map "\C-c\C-d" #'idlwave-debug-map)
     (when (and (listp idlwave-shell-debug-modifiers)
                (not (equal idlwave-shell-debug-modifiers '())))
       ;; Bind the debug commands also with the special modifiers.
@@ -1431,38 +1422,39 @@ Otherwise ARGS forms a list that is evaluated."
              (delq 'shift (copy-sequence idlwave-shell-debug-modifiers))))
         (define-key map
           (vector (append mods-noshift (list (if shift ?C ?c))))
-          'idlwave-shell-save-and-run)
+          #'idlwave-shell-save-and-run)
         (define-key map
           (vector (append mods-noshift (list (if shift ?B ?b))))
-          'idlwave-shell-break-here)
+          #'idlwave-shell-break-here)
         (define-key map
           (vector (append mods-noshift (list (if shift ?E ?e))))
-          'idlwave-shell-run-region)))
-    (define-key map "\C-c\C-d\C-c" 'idlwave-shell-save-and-run)
-    (define-key map "\C-c\C-d\C-b" 'idlwave-shell-break-here)
-    (define-key map "\C-c\C-d\C-e" 'idlwave-shell-run-region)
-    (define-key map "\C-c\C-f" 'idlwave-for)
-    ;;  (define-key map "\C-c\C-f" 'idlwave-function)
-    ;;  (define-key map "\C-c\C-p" 'idlwave-procedure)
-    (define-key map "\C-c\C-r" 'idlwave-repeat)
-    (define-key map "\C-c\C-w" 'idlwave-while)
-    (define-key map "\C-c\C-k" 'idlwave-kill-autoloaded-buffers)
-    (define-key map "\C-c\C-s" 'idlwave-shell)
-    (define-key map "\C-c\C-l" 'idlwave-shell-recenter-shell-window)
-    (define-key map "\C-c\C-b" 'idlwave-list-buffer-load-path-shadows)
-    (define-key map "\C-c\C-v"   'idlwave-find-module)
-    (define-key map "\C-c\C-t"   'idlwave-find-module-this-file)
-    (define-key map "\C-c?"      'idlwave-routine-info)
-    (define-key map "\M-?"       'idlwave-context-help)
+          #'idlwave-shell-run-region)))
+    (define-key map "\C-c\C-d\C-c" #'idlwave-shell-save-and-run)
+    (define-key map "\C-c\C-d\C-b" #'idlwave-shell-break-here)
+    (define-key map "\C-c\C-d\C-e" #'idlwave-shell-run-region)
+    (define-key map "\C-c\C-f" #'idlwave-for)
+    ;;  (define-key map "\C-c\C-f" #'idlwave-function)
+    ;;  (define-key map "\C-c\C-p" #'idlwave-procedure)
+    (define-key map "\C-c\C-r" #'idlwave-repeat)
+    (define-key map "\C-c\C-w" #'idlwave-while)
+    (define-key map "\C-c\C-k" #'idlwave-kill-autoloaded-buffers)
+    (define-key map "\C-c\C-s" #'idlwave-shell)
+    (define-key map "\C-c\C-l" #'idlwave-shell-recenter-shell-window)
+    (define-key map "\C-c\C-b" #'idlwave-list-buffer-load-path-shadows)
+    (define-key map "\C-c\C-v"   #'idlwave-find-module)
+    (define-key map "\C-c\C-t"   #'idlwave-find-module-this-file)
+    (define-key map "\C-c?"      #'idlwave-routine-info)
+    (define-key map "\M-?"       #'idlwave-context-help)
     (define-key map [(control meta ?\?)]
-      'idlwave-help-assistant-help-with-topic)
+      #'idlwave-help-assistant-help-with-topic)
     ;; Pickup both forms of Esc/Meta binding
-    (define-key map [(meta tab)] 'idlwave-complete)
-    (define-key map [?\e?\t] 'idlwave-complete)
-    (define-key map "\M-\C-i" 'idlwave-complete)
-    (define-key map "\C-c\C-i" 'idlwave-update-routine-info)
-    (define-key map "\C-c="    'idlwave-resolve)
-    (define-key map [(shift mouse-3)] 'idlwave-mouse-context-help)
+    ;; FIXME: Use `completion-at-point'!
+    (define-key map [(meta tab)] #'idlwave-complete)
+    (define-key map [?\e?\t] #'idlwave-complete)
+    (define-key map "\M-\C-i" #'idlwave-complete)
+    (define-key map "\C-c\C-i" #'idlwave-update-routine-info)
+    (define-key map "\C-c="    #'idlwave-resolve)
+    (define-key map [(shift mouse-3)] #'idlwave-mouse-context-help)
     map)
   "Keymap used in IDL mode.")
 
@@ -1501,28 +1493,15 @@ Otherwise ARGS forms a list that is evaluated."
     st)
   "Syntax table that treats symbol characters as word characters.")
 
-(defmacro idlwave-with-special-syntax (&rest body)
-  "Execute BODY with a different syntax table."
-  `(let ((saved-syntax (syntax-table)))
-     (unwind-protect
-        (progn
-          (set-syntax-table idlwave-find-symbol-syntax-table)
-          ,@body)
-       (set-syntax-table saved-syntax))))
-
-;(defmacro idlwave-with-special-syntax1 (&rest body)
-;  "Execute BODY with a different syntax table."
-;  `(let ((saved-syntax (syntax-table)))
-;     (unwind-protect
-;        (progn
-;          (set-syntax-table idlwave-find-symbol-syntax-table)
-;          ,@body)
-;      (set-syntax-table saved-syntax))))
+;;(defmacro idlwave-with-special-syntax (&rest body)
+;;  "Execute BODY with `idlwave-find-symbol-syntax-table'."
+;;  `(with-syntax-table idlwave-find-symbol-syntax-table
+;;     ,@body))
 
 (defun idlwave-action-and-binding (key cmd &optional select)
   "KEY and CMD are made into a key binding and an indent action.
 KEY is a string - same as for the `define-key' function.  CMD is a
-function of no arguments or a list to be evaluated.  CMD is bound to
+function of one argument.  CMD is bound to
 KEY in `idlwave-mode-map' by defining an anonymous function calling
 `self-insert-command' followed by CMD.  If KEY contains more than one
 character a binding will only be set if SELECT is `both'.
@@ -1539,62 +1518,59 @@ Otherwise, if SELECT is non-nil then only an action is 
created.
 
 Some examples:
 No spaces before and 1 after a comma
-   (idlwave-action-and-binding \",\"  \\='(idlwave-surround 0 1))
+   (idlwave-action-and-binding \",\"  (lambda (_) (idlwave-surround 0 1)))
 A minimum of 1 space before and after `=' (see `idlwave-expand-equal').
-   (idlwave-action-and-binding \"=\"  \\='(idlwave-expand-equal -1 -1))
+   (idlwave-action-and-binding \"=\"  (lambda (_) (idlwave-expand-equal -1 
-1)))
 Capitalize system variables - action only
-   (idlwave-action-and-binding idlwave-sysvar \\='(capitalize-word 1) t)"
+   (idlwave-action-and-binding idlwave-sysvar (lambda (_) (capitalize-word 1) 
t))"
   (if (not (equal select 'noaction))
       ;; Add action
       (let* ((table (if select 'idlwave-indent-action-table
                       'idlwave-indent-expand-table))
-            (table-key (regexp-quote key))
-             (cell (assoc table-key (eval table))))
-        (if cell
-            ;; Replace action command
-            (setcdr cell cmd)
-          ;; New action
-          (set table (append (eval table) (list (cons table-key cmd)))))))
+            (table-key (regexp-quote key)))
+        (setf (alist-get table-key (symbol-value table) nil nil #'equal) cmd)))
   ;; Make key binding for action
-  (if (or (and (null select) (= (length key) 1))
-          (equal select 'noaction)
-          (equal select 'both))
+  (if (if (null select) (= (length key) 1)
+        (memq select '(noaction both)))
+      ;; FIXME: Use `post-self-insert-hook'!
       (define-key idlwave-mode-map key
-        `(lambda ()
-           (interactive)
-           (self-insert-command 1)
-           ,(if (listp cmd) cmd (list cmd))))))
+        (lambda ()
+          (interactive)
+          (self-insert-command 1)
+          (if (functionp cmd) (funcall cmd nil) (eval cmd t))))))
 
 ;; Set action and key bindings.
 ;; See description of the function `idlwave-action-and-binding'.
 ;; Automatically add spaces for the following characters
 
 ;; Actions for & are complicated by &&
-(idlwave-action-and-binding "&"  'idlwave-custom-ampersand-surround)
+(idlwave-action-and-binding "&" #'idlwave-custom-ampersand-surround)
 
 ;; Automatically add spaces to equal sign if not keyword.  This needs
 ;; to go ahead of > and <, so >= and <= will be treated correctly
-(idlwave-action-and-binding "="  '(idlwave-expand-equal -1 -1))
+(idlwave-action-and-binding "=" (lambda (_) (idlwave-expand-equal -1 -1)))
 
 ;; Actions for > and < are complicated by >=, <=, and ->...
-(idlwave-action-and-binding "<"  '(idlwave-custom-ltgtr-surround nil))
-(idlwave-action-and-binding ">"  '(idlwave-custom-ltgtr-surround 'gtr))
+(idlwave-action-and-binding "<" (lambda (a) (idlwave-custom-ltgtr-surround nil 
a)))
+(idlwave-action-and-binding ">" (lambda (a) (idlwave-custom-ltgtr-surround t 
a)))
 
-(idlwave-action-and-binding ","  '(idlwave-surround 0 -1 1))
+(idlwave-action-and-binding "," (lambda (a) (idlwave-surround 0 -1 1 a)))
 
 
 ;;;
 ;;; Abbrev Section
 ;;;
-;;; When expanding abbrevs and the abbrev hook moves backward, an extra
-;;; space is inserted (this is the space typed by the user to expanded
-;;; the abbrev).
-;;;
-(defvar idlwave-mode-abbrev-table nil
-  "Abbreviation table used for IDLWAVE mode.")
-(define-abbrev-table 'idlwave-mode-abbrev-table ())
+;; When expanding abbrevs and the abbrev hook moves backward, an extra
+;; space is inserted (this is the space typed by the user to expanded
+;; the abbrev).
+;; FIXME: This can be controlled with `no-self-insert' property.
+;;
+(define-abbrev-table 'idlwave-mode-abbrev-table ()
+  "Abbreviation table used for IDLWAVE mode."
+  :enable-function (lambda () (not (idlwave-quoted))))
 
 (defun idlwave-define-abbrev (name expansion hook &optional noprefix table)
+  ;; FIXME: `table' is never passed.
   "Define-abbrev with backward compatibility.
 
 If NOPREFIX is non-nil, don't prepend prefix character.  Installs into
@@ -1605,8 +1581,8 @@ If NOPREFIX is non-nil, don't prepend prefix character.  
Installs into
                    expansion
                    hook)))
     (condition-case nil
-       (apply 'define-abbrev (append args '(0 t)))
-      (error (apply 'define-abbrev args)))))
+       (apply #'define-abbrev (append args '(0 t)))
+      (error (apply #'define-abbrev args)))))
 
 (condition-case nil
     (modify-syntax-entry (string-to-char idlwave-abbrev-start-char)
@@ -1616,15 +1592,15 @@ If NOPREFIX is non-nil, don't prepend prefix character. 
 Installs into
 ;;
 ;; Templates
 ;;
-(idlwave-define-abbrev "c"   "" (idlwave-code-abbrev idlwave-case))
-(idlwave-define-abbrev "sw"  "" (idlwave-code-abbrev idlwave-switch))
-(idlwave-define-abbrev "f"   "" (idlwave-code-abbrev idlwave-for))
-(idlwave-define-abbrev "fu"  "" (idlwave-code-abbrev idlwave-function))
-(idlwave-define-abbrev "pr"  "" (idlwave-code-abbrev idlwave-procedure))
-(idlwave-define-abbrev "r"   "" (idlwave-code-abbrev idlwave-repeat))
-(idlwave-define-abbrev "w"   "" (idlwave-code-abbrev idlwave-while))
-(idlwave-define-abbrev "i"   "" (idlwave-code-abbrev idlwave-if))
-(idlwave-define-abbrev "elif" "" (idlwave-code-abbrev idlwave-elif))
+(idlwave-define-abbrev "c"    "" #'idlwave-case)
+(idlwave-define-abbrev "sw"   "" #'idlwave-switch)
+(idlwave-define-abbrev "f"    "" #'idlwave-for)
+(idlwave-define-abbrev "fu"   "" #'idlwave-function)
+(idlwave-define-abbrev "pr"   "" #'idlwave-procedure)
+(idlwave-define-abbrev "r"    "" #'idlwave-repeat)
+(idlwave-define-abbrev "w"    "" #'idlwave-while)
+(idlwave-define-abbrev "i"    "" #'idlwave-if)
+(idlwave-define-abbrev "elif" "" #'idlwave-elif)
 ;;
 ;; Keywords, system functions, conversion routines
 ;;
@@ -1639,15 +1615,15 @@ If NOPREFIX is non-nil, don't prepend prefix character. 
 Installs into
 (idlwave-define-abbrev "cc" "complex()"    (idlwave-keyword-abbrev 1))
 (idlwave-define-abbrev "cd" "double()"     (idlwave-keyword-abbrev 1))
 (idlwave-define-abbrev "e"  "else"         (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "ec" "endcase"      'idlwave-show-begin)
-(idlwave-define-abbrev "es" "endswitch"    'idlwave-show-begin)
-(idlwave-define-abbrev "ee" "endelse"      'idlwave-show-begin)
-(idlwave-define-abbrev "ef" "endfor"       'idlwave-show-begin)
-(idlwave-define-abbrev "ei" "endif else if" 'idlwave-show-begin)
-(idlwave-define-abbrev "el" "endif else"   'idlwave-show-begin)
-(idlwave-define-abbrev "en" "endif"        'idlwave-show-begin)
-(idlwave-define-abbrev "er" "endrep"       'idlwave-show-begin)
-(idlwave-define-abbrev "ew" "endwhile"     'idlwave-show-begin)
+(idlwave-define-abbrev "ec" "endcase"      #'idlwave-show-begin)
+(idlwave-define-abbrev "es" "endswitch"    #'idlwave-show-begin)
+(idlwave-define-abbrev "ee" "endelse"      #'idlwave-show-begin)
+(idlwave-define-abbrev "ef" "endfor"       #'idlwave-show-begin)
+(idlwave-define-abbrev "ei" "endif else if" #'idlwave-show-begin)
+(idlwave-define-abbrev "el" "endif else"   #'idlwave-show-begin)
+(idlwave-define-abbrev "en" "endif"        #'idlwave-show-begin)
+(idlwave-define-abbrev "er" "endrep"       #'idlwave-show-begin)
+(idlwave-define-abbrev "ew" "endwhile"     #'idlwave-show-begin)
 (idlwave-define-abbrev "g"  "goto,"        (idlwave-keyword-abbrev 0 t))
 (idlwave-define-abbrev "h"  "help,"        (idlwave-keyword-abbrev 0))
 (idlwave-define-abbrev "k"  "keyword_set()" (idlwave-keyword-abbrev 1))
@@ -1695,15 +1671,15 @@ If NOPREFIX is non-nil, don't prepend prefix character. 
 Installs into
 (idlwave-define-abbrev "continue"   "continue"  (idlwave-keyword-abbrev 0 t) t)
 (idlwave-define-abbrev "do"         "do"        (idlwave-keyword-abbrev 0 t) t)
 (idlwave-define-abbrev "else"       "else"      (idlwave-keyword-abbrev 0 t) t)
-(idlwave-define-abbrev "end"        "end"       'idlwave-show-begin-check t)
-(idlwave-define-abbrev "endcase"    "endcase"   'idlwave-show-begin-check t)
-(idlwave-define-abbrev "endelse"    "endelse"   'idlwave-show-begin-check t)
-(idlwave-define-abbrev "endfor"     "endfor"    'idlwave-show-begin-check t)
-(idlwave-define-abbrev "endif"      "endif"     'idlwave-show-begin-check t)
-(idlwave-define-abbrev "endrep"     "endrep"    'idlwave-show-begin-check t)
-(idlwave-define-abbrev "endswitch"  "endswitch" 'idlwave-show-begin-check t)
-(idlwave-define-abbrev "endwhi"     "endwhi"    'idlwave-show-begin-check t)
-(idlwave-define-abbrev "endwhile"   "endwhile"  'idlwave-show-begin-check t)
+(idlwave-define-abbrev "end"        "end"       #'idlwave-show-begin-check t)
+(idlwave-define-abbrev "endcase"    "endcase"   #'idlwave-show-begin-check t)
+(idlwave-define-abbrev "endelse"    "endelse"   #'idlwave-show-begin-check t)
+(idlwave-define-abbrev "endfor"     "endfor"    #'idlwave-show-begin-check t)
+(idlwave-define-abbrev "endif"      "endif"     #'idlwave-show-begin-check t)
+(idlwave-define-abbrev "endrep"     "endrep"    #'idlwave-show-begin-check t)
+(idlwave-define-abbrev "endswitch"  "endswitch" #'idlwave-show-begin-check t)
+(idlwave-define-abbrev "endwhi"     "endwhi"    #'idlwave-show-begin-check t)
+(idlwave-define-abbrev "endwhile"   "endwhile"  #'idlwave-show-begin-check t)
 (idlwave-define-abbrev "eq"         "eq"        (idlwave-keyword-abbrev 0 t) t)
 (idlwave-define-abbrev "for"        "for"       (idlwave-keyword-abbrev 0 t) t)
 (idlwave-define-abbrev "function"   "function"  (idlwave-keyword-abbrev 0 t) t)
@@ -1763,7 +1739,7 @@ The main features of this mode are
    Use \\[idlwave-fill-paragraph] to refill a paragraph inside a
    comment.  The indentation of the second line of the paragraph
    relative to the first will be retained.  Use
-   \\[idlwave-auto-fill-mode] to toggle auto-fill mode for these
+   \\[auto-fill-mode] to toggle auto-fill mode for these
    comments.  When the variable `idlwave-fill-comment-line-only' is
    nil, code can also be auto-filled and auto-indented.
 
@@ -1861,7 +1837,7 @@ The main features of this mode are
       (message "Emacs IDLWAVE mode version %s." idlwave-mode-version))
   (setq idlwave-startup-message nil)
 
-  (set (make-local-variable 'indent-line-function) 'idlwave-indent-and-action)
+  (set (make-local-variable 'indent-line-function) #'idlwave-indent-and-action)
 
   (set (make-local-variable idlwave-comment-indent-function)
        #'idlwave-comment-hook)
@@ -1875,7 +1851,7 @@ The main features of this mode are
 
   (setq abbrev-mode t)
 
-  (set (make-local-variable idlwave-fill-function) 'idlwave-auto-fill)
+  (set (make-local-variable 'normal-auto-fill-function) #'idlwave-auto-fill)
   (setq comment-end "")
   (set (make-local-variable 'comment-multi-line) nil)
   (set (make-local-variable 'paragraph-separate)
@@ -1886,26 +1862,27 @@ The main features of this mode are
 
   ;; ChangeLog
   (set (make-local-variable 'add-log-current-defun-function)
-       'idlwave-current-routine-fullname)
+       #'idlwave-current-routine-fullname)
 
   ;; Set tag table list to use IDLTAGS as file name.
   (if (boundp 'tag-table-alist)
-      (add-to-list 'tag-table-alist '("\\.pro$" . "IDLTAGS")))
+      (add-to-list 'tag-table-alist '("\\.pro\\'" . "IDLTAGS")))
 
   ;; Font-lock additions
   (set (make-local-variable 'font-lock-defaults) idlwave-font-lock-defaults)
   (set (make-local-variable 'font-lock-mark-block-function)
-       'idlwave-mark-subprogram)
+       #'idlwave-mark-subprogram)
   (set (make-local-variable 'font-lock-fontify-region-function)
-       'idlwave-font-lock-fontify-region)
+       #'idlwave-font-lock-fontify-region)
 
   ;; Imenu setup
-  (set (make-local-variable 'imenu-create-index-function)
-       'imenu-default-create-index-function)
+  ;;(set (make-local-variable 'imenu-create-index-function)
+  ;;     ;; FIXME: Why set it explicitly to the value it already has?
+  ;;     #'imenu-default-create-index-function)
   (set (make-local-variable 'imenu-extract-index-name-function)
-       'idlwave-unit-name)
+       #'idlwave-unit-name)
   (set (make-local-variable 'imenu-prev-index-position-function)
-       'idlwave-prev-index-position)
+       #'idlwave-prev-index-position)
 
   ;; HideShow setup
   (add-to-list 'hs-special-modes-alist
@@ -1916,12 +1893,12 @@ The main features of this mode are
                     'idlwave-forward-block nil))
 
   ;; Make a local post-command-hook and add our hook to it
-  (add-hook 'post-command-hook 'idlwave-command-hook nil 'local)
+  (add-hook 'post-command-hook #'idlwave-command-hook nil 'local)
 
   ;; Make local hooks for buffer updates
-  (add-hook 'kill-buffer-hook 'idlwave-kill-buffer-update nil 'local)
-  (add-hook 'after-save-hook 'idlwave-save-buffer-update nil 'local)
-  (add-hook 'after-save-hook 'idlwave-revoke-license-to-kill nil 'local)
+  (add-hook 'kill-buffer-hook #'idlwave-kill-buffer-update nil 'local)
+  (add-hook 'after-save-hook #'idlwave-save-buffer-update nil 'local)
+  (add-hook 'after-save-hook #'idlwave-revoke-license-to-kill nil 'local)
 
   ;; Setup directories and file, if necessary
   (idlwave-setup)
@@ -1974,29 +1951,27 @@ The main features of this mode are
 
 ;;; This stuff is experimental
 
-(defvar idlwave-command-hook nil
-  "If non-nil, a list that can be evaluated using `eval'.
+(defvar idlwave--command-function nil
+  "If non-nil, a function called from `post-command-hook'.
 It is evaluated in the lisp function `idlwave-command-hook' which is
 placed in `post-command-hook'.")
 
 (defun idlwave-command-hook ()
   "Command run after every command.
-Evaluates a non-nil value of the *variable* `idlwave-command-hook' and
+Evaluates a non-nil value of the *variable* `idlwave--command-function' and
 sets the variable to zero afterwards."
-  (and idlwave-command-hook
-       (listp idlwave-command-hook)
-       (condition-case nil
-          (eval idlwave-command-hook)
-        (error nil)))
-  (setq idlwave-command-hook nil))
+  (and idlwave--command-function
+       (with-demoted-errors "idlwave-command-hook: %S"
+        (funcall (prog1 idlwave--command-function
+                   (setq idlwave--command-function nil))))))
 
 ;;; End experiment
 
 ;; It would be better to use expand.el for better abbrev handling and
 ;; versatility.
 
-(defun idlwave-check-abbrev (arg &optional reserved)
-  "Reverse abbrev expansion if in comment or string.
+(defun idlwave-modify-abbrev (arg &optional reserved)
+  "Tweak the abbrev we just expanded.
 Argument ARG is the number of characters to move point
 backward if `idlwave-abbrev-move' is non-nil.
 If optional argument RESERVED is non-nil then the expansion
@@ -2006,21 +1981,16 @@ Otherwise, the abbrev will be capitalized if 
`idlwave-abbrev-change-case'
 is non-nil, unless its value is `down' in which case the abbrev will be
 made into all lowercase.
 Returns non-nil if abbrev is left expanded."
-  (if (idlwave-quoted)
-      (progn (unexpand-abbrev)
-             nil)
-    (if (and reserved idlwave-reserved-word-upcase)
-        (upcase-region last-abbrev-location (point))
-      (cond
-       ((equal idlwave-abbrev-change-case 'down)
-        (downcase-region last-abbrev-location (point)))
-       (idlwave-abbrev-change-case
-        (upcase-region last-abbrev-location (point)))))
-    (if (and idlwave-abbrev-move (> arg 0))
-        (if (boundp 'post-command-hook)
-            (setq idlwave-command-hook (list 'backward-char (1+ arg)))
-          (backward-char arg)))
-    t))
+  (if (and reserved idlwave-reserved-word-upcase)
+      (upcase-region last-abbrev-location (point))
+    (cond
+     ((equal idlwave-abbrev-change-case 'down)
+      (downcase-region last-abbrev-location (point)))
+     (idlwave-abbrev-change-case
+      (upcase-region last-abbrev-location (point)))))
+  (if (and idlwave-abbrev-move (> arg 0))
+      (setq idlwave--command-function (lambda () (backward-char (1+ arg)))))
+  t)
 
 (defun idlwave-in-comment ()
   "Return t if point is inside a comment, nil otherwise."
@@ -2047,7 +2017,7 @@ Returns point if comment found and nil otherwise."
            (backward-char 1)
            (point)))))
 
-(define-obsolete-function-alias 'idlwave-region-active-p 'use-region-p "28.1")
+(define-obsolete-function-alias 'idlwave-region-active-p #'use-region-p "28.1")
 
 (defun idlwave-show-matching-quote ()
   "Insert quote and show matching quote if this is end of a string."
@@ -2067,13 +2037,12 @@ Returns point if comment found and nil otherwise."
 (defun idlwave-show-begin-check ()
   "Ensure that the previous word was a token before `idlwave-show-begin'.
 An END token must be preceded by whitespace."
-  (if (not (idlwave-quoted))
-      (if
-         (save-excursion
-           (backward-word-strictly 1)
-           (backward-char 1)
-           (looking-at "[ \t\n\f]"))
-         (idlwave-show-begin))))
+  (if
+      (save-excursion
+       (backward-word-strictly 1)
+       (backward-char 1)
+       (looking-at "[ \t\n\f]"))
+      (idlwave-show-begin)))
 
 (defun idlwave-show-begin ()
   "Find the start of current block and blinks to it for a second.
@@ -2088,7 +2057,7 @@ Also checks if the correct END statement has been used."
         begin-pos end-pos end end1 )
     (if idlwave-reindent-end  (idlwave-indent-line))
     (setq last-abbrev-location (marker-position last-abbrev-marker))
-    (when (and (idlwave-check-abbrev 0 t)
+    (when (and (idlwave-modify-abbrev 0 t)
               idlwave-show-block)
       (save-excursion
        ;; Move inside current block
@@ -2178,11 +2147,11 @@ Also checks if the correct END statement has been used."
        (next-char (char-after (point)))
        (method-invoke (and gtr (eq prev-char ?-)))
        (len (if method-invoke 2 1)))
-    (unless  (eq next-char ?=)
+    (unless (eq next-char ?=)
       ;; Key binding: pad only on left, to save for possible >=/<=
       (idlwave-surround -1 (if (or is-action method-invoke) -1) len))))
 
-(defun idlwave-surround (&optional before after length is-action)
+(defun idlwave-surround (&optional before after length _is-action)
   "Surround the LENGTH characters before point with blanks.
 LENGTH defaults to 1.
 Optional arguments BEFORE and AFTER affect the behavior before and
@@ -2641,7 +2610,7 @@ statement."
       (if st
           (append st (match-end 0))))))
 
-(defun idlwave-expand-equal (&optional before after is-action)
+(defun idlwave-expand-equal (&optional before after _is-action)
   "Pad `=' with spaces.
 Two cases: Assignment statement, and keyword assignment.
 Which case is determined using `idlwave-start-of-substatement' and
@@ -2749,10 +2718,10 @@ If the optional argument EXPAND is non-nil then the 
actions in
         ;; Before indenting, run action routines.
         ;;
         (if (and expand idlwave-do-actions)
-            (mapc 'idlwave-do-action idlwave-indent-expand-table))
+            (mapc #'idlwave-do-action idlwave-indent-expand-table))
         ;;
         (if idlwave-do-actions
-            (mapc 'idlwave-do-action idlwave-indent-action-table))
+            (mapc #'idlwave-do-action idlwave-indent-action-table))
         ;;
         ;; No longer expand abbrevs on the line.  The user can do this
         ;; manually using expand-region-abbrevs.
@@ -2781,18 +2750,19 @@ If the optional argument EXPAND is non-nil then the 
actions in
 (defun idlwave-do-action (action)
   "Perform an action repeatedly on a line.
 ACTION is a list (REG . FUNC).  REG is a regular expression.  FUNC is
-either a function name to be called with `funcall' or a list to be
-evaluated with `eval'.  The action performed by FUNC should leave
-point after the match for REG - otherwise an infinite loop may be
-entered.  FUNC is always passed a final argument of `is-action', so it
+either a function which will be called with one argument `is-action' or
+a list to be evaluated with `eval'.
+The action performed by FUNC should leave point after the match for REG
+- otherwise an infinite loop may be entered.
+FUNC is always passed a final argument of `is-action', so it
 can discriminate between being run as an action, or a key binding."
   (let ((action-key (car action))
         (action-routine (cdr action)))
     (beginning-of-line)
     (while (idlwave-look-at action-key)
-      (if (listp action-routine)
-          (eval (append action-routine '('is-action)))
-        (funcall action-routine 'is-action)))))
+      (if (functionp action-routine)
+          (funcall action-routine 'is-action)
+        (eval (append action-routine '('is-action)) t)))))
 
 (defun idlwave-indent-to (col &optional min)
   "Indent from point with spaces until column COL.
@@ -3053,7 +3023,7 @@ Return value is the beginning of the match or (in case of 
failure) nil."
   (let ((case-fold-search t)
        (search-func (if (> dir 0) 're-search-forward 're-search-backward))
        found)
-    (idlwave-with-special-syntax
+    (with-syntax-table idlwave-find-symbol-syntax-table
      (save-excursion
        (catch 'exit
         (while (funcall search-func key-re limit t)
@@ -3181,7 +3151,7 @@ If successful leaves point after the match, otherwise, 
does not move point."
               (if cont (idlwave-end-of-statement) (end-of-line))
               (point)))
         found)
-    (idlwave-with-special-syntax
+    (with-syntax-table idlwave-find-symbol-syntax-table
      (if beg (idlwave-beginning-of-statement))
      (while (and (setq found (re-search-forward regexp eos t))
                 (idlwave-quoted))))
@@ -3465,25 +3435,7 @@ if `idlwave-auto-fill-split-string' is non-nil."
              (idlwave-indent-line))
            )))))
 
-(defun idlwave-auto-fill-mode (arg)
-  "Toggle auto-fill mode for IDL mode.
-With arg, turn auto-fill mode on if arg is positive.
-In auto-fill mode, inserting a space at a column beyond `fill-column'
-automatically breaks the line at a previous space."
-  (interactive "P")
-  (prog1 (set idlwave-fill-function
-              (if (if (null arg)
-                      (not (symbol-value idlwave-fill-function))
-                    (> (prefix-numeric-value arg) 0))
-                  'idlwave-auto-fill
-                nil))
-    ;; update mode-line
-    (set-buffer-modified-p (buffer-modified-p))))
-
-;(defun idlwave-fill-routine-call ()
-;  "Fill a routine definition or statement, indenting appropriately."
-;  (let ((where (idlwave-where)))))
-
+(define-obsolete-function-alias 'idlwave-auto-fill-mode #'auto-fill-mode 
"28.1")
 
 (defun idlwave-doc-header (&optional nomark)
   "Insert a documentation header at the beginning of the unit.
@@ -3578,6 +3530,7 @@ Calling from a program, arguments are START END."
 (defun idlwave-quoted ()
   "Return t if point is in a comment or quoted string.
 Returns nil otherwise."
+  ;; FIXME: Use (nth 8 (synx-ppss))!
   (and (or (idlwave-in-comment) (idlwave-in-quote)) t))
 
 (defun idlwave-in-quote ()
@@ -3858,7 +3811,7 @@ Intended for `after-save-hook'."
        (setq idlwave-outlawed-buffers
              (delq entry idlwave-outlawed-buffers)))
     ;; Remove this function from the hook.
-    (remove-hook 'after-save-hook 'idlwave-revoke-license-to-kill 'local)))
+    (remove-hook 'after-save-hook #'idlwave-revoke-license-to-kill 'local)))
 
 (defvar idlwave-path-alist)
 (defun idlwave-locate-lib-file (file)
@@ -4098,10 +4051,10 @@ blank lines."
        (set (idlwave-sintern-set name 'class idlwave-sint-classes set))
        (name)))
 
-(defun idlwave-sintern-dir (dir &optional set)
+(defun idlwave-sintern-dir (dir &optional _set)
   (car (or (member dir idlwave-sint-dirs)
           (setq idlwave-sint-dirs (cons dir idlwave-sint-dirs)))))
-(defun idlwave-sintern-libname (name &optional set)
+(defun idlwave-sintern-libname (name &optional _set)
   (car (or (member name idlwave-sint-libnames)
           (setq idlwave-sint-libnames (cons name idlwave-sint-libnames)))))
 
@@ -4169,7 +4122,7 @@ the base of the directory."
 
 ;; Creating new sintern tables
 
-(defun idlwave-new-sintern-type (tag)
+(defmacro idlwave-new-sintern-type (tag)
   "Define a variable and a function to sintern the new type TAG.
 This defines the function `idlwave-sintern-TAG' and the variable
 `idlwave-sint-TAGs'."
@@ -4177,15 +4130,15 @@ This defines the function `idlwave-sintern-TAG' and the 
variable
         (names (concat name "s"))
         (var (intern (concat "idlwave-sint-" names)))
         (func (intern (concat "idlwave-sintern-" name))))
-    (set var nil) ; initial value of the association list
-    (fset func    ; set the function
-         `(lambda (name &optional set)
-            (cond ((not (stringp name)) name)
-                  ((cdr (assoc (downcase name) ,var)))
-                  (set
-                   (setq ,var (cons (cons (downcase name) name) ,var))
-                   name)
-                  (name))))))
+    `(progn
+       (defvar ,var nil)        ; initial value of the association list
+       (defun ,func (name &optional set)
+        (cond ((not (stringp name)) name)
+              ((cdr (assoc (downcase name) ,var)))
+              (set
+               (push (cons (downcase name) name) ,var)
+               name)
+              (name))))))
 
 (defun idlwave-reset-sintern-type (tag)
   "Reset the sintern variable associated with TAG."
@@ -4296,12 +4249,12 @@ will re-read the catalog."
                     "-l" (expand-file-name "~/.emacs")
                     "-l" "idlwave"
                     "-f" "idlwave-rescan-catalog-directories"))
-        (process (apply 'start-process "idlcat"
+        (process (apply #'start-process "idlcat"
                         nil emacs args)))
     (setq idlwave-catalog-process process)
     (set-process-sentinel
      process
-     (lambda (pro why)
+     (lambda (_pro why)
        (when (string-match "finished" why)
         (setq idlwave-routines nil
               idlwave-system-routines nil
@@ -4449,7 +4402,7 @@ information updated immediately, leave NO-CONCATENATE 
nil."
            (setq idlwave-load-rinfo-idle-timer
                  (run-with-idle-timer
                   idlwave-init-rinfo-when-idle-after
-                  nil 'idlwave-load-rinfo-next-step)))
+                  nil #'idlwave-load-rinfo-next-step)))
        (error nil))))
 
 ;;------ XML Help routine info system
@@ -4935,7 +4888,7 @@ Cache to disk for quick recovery."
          (setq idlwave-load-rinfo-idle-timer
                (run-with-idle-timer
                 idlwave-init-rinfo-when-idle-after
-                nil 'idlwave-load-rinfo-next-step))))))
+                nil #'idlwave-load-rinfo-next-step))))))
 
 (defvar idlwave-after-load-rinfo-hook nil)
 
@@ -5109,7 +5062,7 @@ Can run from `after-save-hook'."
                               (error nil)))
                   (push res routine-lists)))))
     ;; Concatenate the individual lists and return the result
-    (apply 'nconc routine-lists)))
+    (apply #'nconc routine-lists)))
 
 (defun idlwave-get-buffer-routine-info ()
   "Scan the current buffer for routine info.  Return (PRO-LIST FUNC-LIST)."
@@ -5185,10 +5138,10 @@ Can run from `after-save-hook'."
           (if args
               (concat
                (if (string= type "function") "(" ", ")
-               (mapconcat 'identity args ", ")
+               (mapconcat #'identity args ", ")
                (if (string= type "function") ")" ""))))
          (if keywords
-             (cons nil (mapcar 'list keywords)) ;No help file
+             (cons nil (mapcar #'list keywords)) ;No help file
            nil))))
 
 
@@ -5246,7 +5199,7 @@ as last time - so no widget will pop up."
                         (cons x (cdr path-entry))
                       (list x))))
                 (idlwave-expand-path idlwave-library-path))
-       (mapcar 'list (idlwave-expand-path idlwave-library-path)))))
+       (mapcar #'list (idlwave-expand-path idlwave-library-path)))))
 
    ;; Ask the shell for the path and then run the widget
    (t
@@ -5314,7 +5267,7 @@ directories and save the routine info.
   (widget-insert "  ")
   (widget-create 'push-button
                 :notify
-                (lambda (&rest ignore)
+                (lambda (&rest _ignore)
                    (let ((path-list (widget-get idlwave-widget :path-dirs)))
                      (dolist (x path-list)
                        (unless (memq 'lib (cdr x))
@@ -5324,7 +5277,7 @@ directories and save the routine info.
   (widget-insert "  ")
   (widget-create 'push-button
                 :notify
-                (lambda (&rest ignore)
+                (lambda (&rest _ignore)
                    (let ((path-list (widget-get idlwave-widget :path-dirs)))
                      (dolist (x path-list)
                        (idlwave-path-alist-remove-flag x 'user))
@@ -5332,7 +5285,7 @@ directories and save the routine info.
                 "Deselect All")
   (widget-insert "  ")
   (widget-create 'push-button
-                :notify (lambda (&rest ignore)
+                :notify (lambda (&rest _ignore)
                           (kill-buffer (current-buffer)))
                 "Quit")
   (widget-insert "\n\n")
@@ -5340,7 +5293,7 @@ directories and save the routine info.
   (widget-insert "Select Directories: \n")
 
   (setq idlwave-widget
-       (apply 'widget-create
+       (apply #'widget-create
               'checklist
               :value  (delq nil (mapcar (lambda (x)
                                           (if (memq 'user (cdr x))
@@ -5352,7 +5305,8 @@ directories and save the routine info.
                         (list 'item
                               (if (memq 'lib (cdr x))
                                   (concat "[LIB] " (car x) )
-                                (car x)))) dirs-list)))
+                                (car x))))
+                      dirs-list)))
   (widget-put idlwave-widget :path-dirs dirs-list)
   (widget-insert "\n")
   (use-local-map widget-keymap)
@@ -5360,14 +5314,14 @@ directories and save the routine info.
   (goto-char (point-min))
   (delete-other-windows))
 
-(defun idlwave-delete-user-catalog-file (&rest ignore)
+(defun idlwave-delete-user-catalog-file (&rest _ignore)
   (if (yes-or-no-p
        (format "Delete file %s " idlwave-user-catalog-file))
       (progn
        (delete-file idlwave-user-catalog-file)
        (message "%s has been deleted" idlwave-user-catalog-file))))
 
-(defun idlwave-widget-scan-user-lib-files (&rest ignore)
+(defun idlwave-widget-scan-user-lib-files (&rest _ignore)
   ;; Call `idlwave-scan-user-lib-files' with data taken from the widget.
   (let* ((widget idlwave-widget)
         (selected-dirs (widget-value widget))
@@ -5517,7 +5471,7 @@ be set to nil to disable library catalog scanning."
     (let ((dirs
           (if idlwave-library-path
               (idlwave-expand-path idlwave-library-path)
-            (mapcar 'car idlwave-path-alist)))
+            (mapcar #'car idlwave-path-alist)))
          (old-libname "")
          dir-entry dir catalog all-routines)
       (if message-base (message "%s" message-base))
@@ -5730,11 +5684,10 @@ end
 (defvar idlwave-completion-help-info nil)
 (defvar idlwave-completion-help-links nil)
 (defvar idlwave-current-obj_new-class nil)
-(defvar idlwave-complete-special nil)
-(defvar method-selector)
-(defvar class-selector)
-(defvar type-selector)
-(defvar super-classes)
+(defvar idlwave--method-selector)
+(defvar idlwave--class-selector)
+(defvar idlwave--type-selector)
+(defvar idlwave--super-classes)
 
 (defun idlwave-complete (&optional arg module class)
   "Complete a function, procedure or keyword name at point.
@@ -5815,8 +5768,7 @@ When we force a method or a method keyword, CLASS can 
specify the class."
       (idlwave-complete-filename))
 
      ;; Check for any special completion functions
-     ((and idlwave-complete-special
-          (idlwave-call-special idlwave-complete-special)))
+     ((run-hook-with-args-until-success 'idlwave-complete-functions))
 
      ((null what)
       (error "Nothing to complete here"))
@@ -5829,22 +5781,26 @@ When we force a method or a method keyword, CLASS can 
specify the class."
      ((eq what 'procedure)
       ;; Complete a procedure name
       (let* ((cw-list (nth 3 where-list))
-            (class-selector (idlwave-determine-class cw-list 'pro))
-            (super-classes (unless (idlwave-explicit-class-listed cw-list)
-                             (idlwave-all-class-inherits class-selector)))
-            (isa (concat "procedure" (if class-selector "-method" "")))
-            (type-selector 'pro))
+            (idlwave--class-selector (idlwave-determine-class cw-list 'pro))
+            (idlwave--super-classes
+             (unless (idlwave-explicit-class-listed cw-list)
+               (idlwave-all-class-inherits idlwave--class-selector)))
+            (isa (concat "procedure"
+                         (if idlwave--class-selector "-method" "")))
+            (idlwave--type-selector 'pro))
        (setq idlwave-completion-help-info
-             (list 'routine nil type-selector class-selector nil 
super-classes))
+             (list 'routine nil
+                   idlwave--type-selector idlwave--class-selector
+                   nil idlwave--super-classes))
        (idlwave-complete-in-buffer
-        'procedure (if class-selector 'method 'routine)
+        'procedure (if idlwave--class-selector 'method 'routine)
         (idlwave-routines) 'idlwave-selector
         (format "Select a %s name%s"
                 isa
-                (if class-selector
+                (if idlwave--class-selector
                     (format " (class is %s)"
-                            (if (eq class-selector t)
-                                "unknown" class-selector))
+                            (if (eq idlwave--class-selector t)
+                                "unknown" idlwave--class-selector))
                   ""))
         isa
         'idlwave-attach-method-classes 'idlwave-add-file-link-selector)))
@@ -5852,22 +5808,25 @@ When we force a method or a method keyword, CLASS can 
specify the class."
      ((eq what 'function)
       ;; Complete a function name
       (let* ((cw-list (nth 3 where-list))
-            (class-selector (idlwave-determine-class cw-list 'fun))
-            (super-classes (unless (idlwave-explicit-class-listed cw-list)
-                             (idlwave-all-class-inherits class-selector)))
-            (isa (concat "function" (if class-selector "-method" "")))
-            (type-selector 'fun))
+            (idlwave--class-selector (idlwave-determine-class cw-list 'fun))
+            (idlwave--super-classes
+             (unless (idlwave-explicit-class-listed cw-list)
+               (idlwave-all-class-inherits idlwave--class-selector)))
+            (isa (concat "function" (if idlwave--class-selector "-method" "")))
+            (idlwave--type-selector 'fun))
        (setq idlwave-completion-help-info
-             (list 'routine nil type-selector class-selector nil 
super-classes))
+             (list 'routine nil
+                   idlwave--type-selector idlwave--class-selector
+                   nil idlwave--super-classes))
        (idlwave-complete-in-buffer
-        'function (if class-selector 'method 'routine)
+        'function (if idlwave--class-selector 'method 'routine)
         (idlwave-routines) 'idlwave-selector
         (format "Select a %s name%s"
                 isa
-                (if class-selector
+                (if idlwave--class-selector
                     (format " (class is %s)"
-                            (if (eq class-selector t)
-                                "unknown" class-selector))
+                            (if (eq idlwave--class-selector t)
+                                "unknown" idlwave--class-selector))
                   ""))
         isa
         'idlwave-attach-method-classes 'idlwave-add-file-link-selector)))
@@ -5880,11 +5839,12 @@ When we force a method or a method keyword, CLASS can 
specify the class."
       ;; Complete a procedure keyword
       (let* ((where (nth 3 where-list))
             (name  (car where))
-            (method-selector name)
-            (type-selector 'pro)
+            (idlwave--method-selector name)
+            (idlwave--type-selector 'pro)
             (class (idlwave-determine-class where 'pro))
-            (class-selector class)
-            (super-classes (idlwave-all-class-inherits class-selector))
+            (idlwave--class-selector class)
+            (idlwave--super-classes (idlwave-all-class-inherits
+                                     idlwave--class-selector))
             (isa (format "procedure%s-keyword" (if class "-method" "")))
             (entry (idlwave-best-rinfo-assq
                     name 'pro class (idlwave-routines)))
@@ -5894,11 +5854,13 @@ When we force a method or a method keyword, CLASS can 
specify the class."
          (error "Nothing known about procedure %s"
                 (idlwave-make-full-name class name)))
        (setq list (idlwave-fix-keywords name 'pro class list
-                                        super-classes system))
+                                        idlwave--super-classes system))
        (unless list (error "No keywords available for procedure %s"
                            (idlwave-make-full-name class name)))
        (setq idlwave-completion-help-info
-             (list 'keyword name type-selector class-selector entry 
super-classes))
+             (list 'keyword name
+                   idlwave--type-selector idlwave--class-selector
+                   entry idlwave--super-classes))
        (idlwave-complete-in-buffer
         'keyword 'keyword list nil
         (format "Select keyword for procedure %s%s"
@@ -5913,11 +5875,12 @@ When we force a method or a method keyword, CLASS can 
specify the class."
       ;; Complete a function keyword
       (let* ((where (nth 3 where-list))
             (name  (car where))
-            (method-selector name)
-            (type-selector 'fun)
+            (idlwave--method-selector name)
+            (idlwave--type-selector 'fun)
             (class (idlwave-determine-class where 'fun))
-            (class-selector class)
-            (super-classes (idlwave-all-class-inherits class-selector))
+            (idlwave--class-selector class)
+            (idlwave--super-classes (idlwave-all-class-inherits
+                                     idlwave--class-selector))
             (isa (format "function%s-keyword" (if class "-method" "")))
             (entry (idlwave-best-rinfo-assq
                     name 'fun class (idlwave-routines)))
@@ -5928,7 +5891,7 @@ When we force a method or a method keyword, CLASS can 
specify the class."
          (error "Nothing known about function %s"
                 (idlwave-make-full-name class name)))
        (setq list (idlwave-fix-keywords name 'fun class list
-                                        super-classes system))
+                                        idlwave--super-classes system))
        ;; OBJ_NEW: Messages mention the proper Init method
        (setq msg-name (if (and (null class)
                                (string= (upcase name) "OBJ_NEW"))
@@ -5938,7 +5901,9 @@ When we force a method or a method keyword, CLASS can 
specify the class."
        (unless list (error "No keywords available for function %s"
                            msg-name))
        (setq idlwave-completion-help-info
-             (list 'keyword name type-selector class-selector nil 
super-classes))
+             (list 'keyword name
+                   idlwave--type-selector idlwave--class-selector
+                   nil idlwave--super-classes))
        (idlwave-complete-in-buffer
         'keyword 'keyword list nil
         (format "Select keyword for function %s%s" msg-name
@@ -5950,7 +5915,9 @@ When we force a method or a method keyword, CLASS can 
specify the class."
 
      (t (error "This should not happen (idlwave-complete)")))))
 
-(defvar idlwave-complete-special nil
+(define-obsolete-variable-alias 'idlwave-complete-special
+  'idlwave-complete-functions "28.1")
+(defvar idlwave-complete-functions nil
   "List of special completion functions.
 These functions are called for each completion.  Each function must
 check if its own special completion context is present.  If yes, it
@@ -5960,6 +5927,7 @@ complete other contexts will be done.  If the function 
returns nil,
 other completions will be tried.")
 
 (defun idlwave-call-special (functions &rest args)
+  (declare (obsolete run-hook-with-args-until-success "28.1"))
   (let ((funcs functions)
        fun ret)
     (catch 'exit
@@ -6002,9 +5970,9 @@ other completions will be tried.")
       (list nil-list nil-list 'procedure nil-list nil))
 
      ((eq what 'procedure-keyword)
-      (let* ((class-selector nil)
-            (super-classes nil)
-            (type-selector 'pro)
+      (let* ((idlwave--class-selector nil)
+            (idlwave--super-classes nil)
+            (idlwave--type-selector 'pro)
             (pro (or module
                      (idlwave-completing-read
                       "Procedure: " (idlwave-routines) 'idlwave-selector))))
@@ -6016,9 +5984,9 @@ other completions will be tried.")
       (list nil-list nil-list 'function nil-list nil))
 
      ((eq what 'function-keyword)
-      (let* ((class-selector nil)
-            (super-classes nil)
-            (type-selector 'fun)
+      (let* ((idlwave--class-selector nil)
+            (idlwave--super-classes nil)
+            (idlwave--type-selector 'fun)
             (func (or module
                       (idlwave-completing-read
                        "Function: " (idlwave-routines) 'idlwave-selector))))
@@ -6031,12 +5999,14 @@ other completions will be tried.")
 
      ((eq what 'procedure-method-keyword)
       (let* ((class (idlwave-determine-class class-list 'pro))
-            (class-selector class)
-            (super-classes (idlwave-all-class-inherits class-selector))
-            (type-selector 'pro)
+            (idlwave--class-selector class)
+            (idlwave--super-classes (idlwave-all-class-inherits
+                                     idlwave--class-selector))
+            (idlwave--type-selector 'pro)
             (pro (or module
                      (idlwave-completing-read
-                      (format "Procedure in %s class: " class-selector)
+                      (format "Procedure in %s class: "
+                              idlwave--class-selector)
                       (idlwave-routines) 'idlwave-selector))))
        (setq pro (idlwave-sintern-method pro))
        (list nil-list nil-list 'procedure-keyword
@@ -6047,12 +6017,14 @@ other completions will be tried.")
 
      ((eq what 'function-method-keyword)
       (let* ((class (idlwave-determine-class class-list 'fun))
-            (class-selector class)
-            (super-classes (idlwave-all-class-inherits class-selector))
-            (type-selector 'fun)
+            (idlwave--class-selector class)
+            (idlwave--super-classes (idlwave-all-class-inherits
+                                     idlwave--class-selector))
+            (idlwave--type-selector 'fun)
             (func (or module
                       (idlwave-completing-read
-                       (format "Function in %s class: " class-selector)
+                       (format "Function in %s class: "
+                               idlwave--class-selector)
                        (idlwave-routines) 'idlwave-selector))))
        (setq func (idlwave-sintern-method func))
        (list nil-list nil-list 'function-keyword
@@ -6069,14 +6041,14 @@ other completions will be tried.")
     (unwind-protect
        (progn
          (setq-default completion-ignore-case t)
-         (apply 'completing-read args))
+         (apply #'completing-read args))
       (setq-default completion-ignore-case old-value))))
 
 (defvar idlwave-shell-default-directory)
 (defun idlwave-complete-filename ()
   "Use the comint stuff to complete a file name."
   (require 'comint)
-  (let* ((comint-file-name-chars "~/A-Za-z0-9+@:_.$#%={}\\-")
+  (dlet ((comint-file-name-chars "~/A-Za-z0-9+@:_.$#%={}\\-")
         (comint-completion-addsuffix nil)
         (default-directory
           (if (and (boundp 'idlwave-shell-default-directory)
@@ -6110,7 +6082,7 @@ other completions will be tried.")
 (defun idlwave-rinfo-assq-any-class (name type class list)
   ;; Return the first matching method on the inheritance list
   (let* ((classes (cons class (idlwave-all-class-inherits class)))
-        class rtn)
+        rtn) ;; class
     (while classes
       (if (setq rtn (idlwave-rinfo-assq name type (pop classes) list))
          (setq classes nil)))
@@ -6127,7 +6099,7 @@ syslib files."
                list))
        syslibp)
     (when (> (length twins) 1)
-      (setq twins (sort twins 'idlwave-routine-entry-compare-twins))
+      (setq twins (sort twins #'idlwave-routine-entry-compare-twins))
       (if (and (null keep-system)
               (eq 'system (car (nth 3 (car twins))))
               (setq syslibp (idlwave-any-syslib (cdr twins)))
@@ -6174,7 +6146,7 @@ If yes, return the index (>=1)."
 TYPE is `fun' or `pro'.
 When TYPE is not specified, both procedures and functions will be considered."
   (if (null method)
-      (mapcar 'car (idlwave-class-alist))
+      (mapcar #'car (idlwave-class-alist))
     (let (rtn)
       (mapc (lambda (x)
              (and (nth 2 x)
@@ -6228,9 +6200,11 @@ INFO is as returned by `idlwave-what-function' or 
`-procedure'."
        (save-excursion (goto-char apos)
                        (looking-at "->[a-zA-Z][a-zA-Z0-9$_]*::")))))
 
-(defvar idlwave-determine-class-special nil
-  "List of special functions for determining class.
-Must accept two arguments: `apos' and `info'.")
+(define-obsolete-variable-alias 'idlwave-determine-class-special
+  'idlwave-determine-class-functions "28.1")
+(defvar idlwave-determine-class-functions nil
+  "Special hook to determine a class.
+The functions should accept one argument, APOS.")
 
 (defun idlwave-determine-class (info type)
   ;; Determine the class of a routine call.
@@ -6275,10 +6249,10 @@ Must accept two arguments: `apos' and `info'.")
 
       ;; Before prompting, try any special class determination routines
       (when (and (eq t class)
-                idlwave-determine-class-special
                 (not force-query))
        (setq special-class
-             (idlwave-call-special idlwave-determine-class-special apos))
+             (run-hook-with-args-until-success
+              'idlwave-determine-class-functions apos))
        (if special-class
            (setq class (idlwave-sintern-class special-class)
                  store idlwave-store-inquired-class)))
@@ -6287,7 +6261,7 @@ Must accept two arguments: `apos' and `info'.")
       (when (and (eq class t)
                 (or force-query query))
        (setq class-alist
-             (mapcar 'list (idlwave-all-method-classes (car info) type)))
+             (mapcar #'list (idlwave-all-method-classes (car info) type)))
        (setq class
              (idlwave-sintern-class
               (cond
@@ -6321,10 +6295,10 @@ Must accept two arguments: `apos' and `info'.")
      (t class))))
 
 (defun idlwave-selector (a)
-  (and (eq (nth 1 a) type-selector)
-       (or (and (nth 2 a) (eq class-selector t))
-          (eq (nth 2 a) class-selector)
-          (memq (nth 2 a) super-classes))))
+  (and (eq (nth 1 a) idlwave--type-selector)
+       (or (and (nth 2 a) (eq idlwave--class-selector t))
+          (eq (nth 2 a) idlwave--class-selector)
+          (memq (nth 2 a) idlwave--super-classes))))
 
 (defun idlwave-add-file-link-selector (a)
   ;; Record a file link, if any, for the tested names during selection.
@@ -6442,7 +6416,7 @@ ARROW:  Location of the arrow"
          func-point
          (cnt 0)
          func arrow-start class)
-      (idlwave-with-special-syntax
+      (with-syntax-table idlwave-find-symbol-syntax-table
        (save-restriction
         (save-excursion
           (narrow-to-region (max 1 (or bound 0)) (point-max))
@@ -6472,7 +6446,7 @@ ARROW:  Location of the arrow"
             (goto-char pos))
           (throw 'exit nil)))))))
 
-(defun idlwave-what-procedure (&optional bound)
+(defun idlwave-what-procedure (&optional _bound)
   ;; Find out if point is within the argument list of a procedure.
   ;; The return value is ("procedure-name" class arrow-pos (point)).
 
@@ -6562,10 +6536,10 @@ This function is not general, can only be used for 
completion stuff."
            (throw 'exit nil)))
         (t (throw 'exit (preceding-char))))))))
 
-(defvar idlwave-complete-after-success-form nil
-  "A form to evaluate after successful completion.")
-(defvar idlwave-complete-after-success-form-force nil
-  "A form to evaluate after completion selection in *Completions* buffer.")
+(defvar idlwave--complete-after-success-function #'ignore
+  "A function to evaluate after successful completion.")
+(defvar idlwave--complete-after-success-force-function #'ignore
+  "A function to evaluate after completion selection in *Completions* buffer.")
 (defconst idlwave-completion-mark (make-marker)
   "A mark pointing to the beginning of the completion string.")
 
@@ -6590,12 +6564,12 @@ accumulate information on matching completions."
       (skip-chars-backward "a-zA-Z0-9_$")
       (setq slash (eq (preceding-char) ?/)
            beg (point)
-           idlwave-complete-after-success-form
-           (list 'idlwave-after-successful-completion
-                 (list 'quote type) slash beg)
-           idlwave-complete-after-success-form-force
-           (list 'idlwave-after-successful-completion
-                 (list 'quote type) slash (list 'quote 'force))))
+           idlwave--complete-after-success-function
+           (lambda () (idlwave-after-successful-completion
+                  type slash beg))
+           idlwave--complete-after-success-force-function
+           (lambda () (idlwave-after-successful-completion
+                  type slash 'force))))
 
     ;; Try a completion
     (setq part (buffer-substring beg end)
@@ -6699,19 +6673,20 @@ accumulate information on matching completions."
   ;; 'class-tag, for class tags, and otherwise for methods.
   ;; SHOW-CLASSES is the value of `idlwave-completion-show-classes'.
   (if (or (null show-classes)           ; don't want to see classes
-         (null class-selector)         ; not a method call
+         (null idlwave--class-selector)         ; not a method call
          (and
-          (stringp class-selector) ; the class is already known
-          (not super-classes)))    ; no possibilities for inheritance
+          (stringp idlwave--class-selector) ; the class is already known
+          (not idlwave--super-classes)))    ; no possibilities for inheritance
       ;; In these cases, we do not have to do anything
       list
     (let* ((do-prop (>= show-classes 0))
           (do-buf (not (= show-classes 0)))
-          (do-dots t)
-          (inherit (if (and (not (eq type 'class-tag)) super-classes)
-                       (cons class-selector super-classes)))
+          ;; (do-dots t)
+          (inherit (if (and (not (eq type 'class-tag)) idlwave--super-classes)
+                       (cons idlwave--class-selector idlwave--super-classes)))
           (max (abs show-classes))
-          (lmax (if do-dots (apply 'max (mapcar 'length list))))
+          (lmax ;; (if do-dots
+                    (apply #'max (mapcar #'length list))) ;;)
          classes nclasses class-info space)
       (mapcar
        (lambda (x)
@@ -6720,13 +6695,14 @@ accumulate information on matching completions."
             ;; Just one class for tags
             (setq classes
                   (list
-                   (idlwave-class-or-superclass-with-tag class-selector x)))
+                   (idlwave-class-or-superclass-with-tag
+                    idlwave--class-selector x)))
           ;; Multiple classes for method or method-keyword
           (setq classes
                 (if (eq type 'kwd)
                     (idlwave-all-method-keyword-classes
-                     method-selector x type-selector)
-                  (idlwave-all-method-classes x type-selector)))
+                     idlwave--method-selector x idlwave--type-selector)
+                  (idlwave-all-method-classes x idlwave--type-selector)))
           (if inherit
               (setq classes
                     (delq nil
@@ -6734,22 +6710,22 @@ accumulate information on matching completions."
                                   classes)))))
         (setq nclasses (length classes))
         ;; Make the separator between item and class-info
-        (if do-dots
-            (setq space (concat " " (make-string (- lmax (length x)) ?.)))
-          (setq space " "))
+        ;; (if do-dots
+        (setq space (concat " " (make-string (- lmax (length x)) ?.)))
+        ;; (setq space " "))
         (if  do-buf
             ;; We do want info in the buffer
             (if (<= nclasses max)
                 (setq class-info (concat
                                   space
-                                  "<" (mapconcat 'identity classes ",") ">"))
+                                  "<" (mapconcat #'identity classes ",") ">"))
               (setq class-info (format "%s<%d classes>" space nclasses)))
           (setq class-info nil))
         (when do-prop
           ;; We do want properties
           (setq x (copy-sequence x))
           (put-text-property 0 (length x)
-                              'help-echo (mapconcat 'identity classes " ")
+                              'help-echo (mapconcat #'identity classes " ")
                               x))
         (if class-info
             (list x class-info)
@@ -6839,7 +6815,7 @@ sort the list before displaying."
                            (nth 2 last-command))
                       (progn
                         (select-window win)
-                        (eval idlwave-complete-after-success-form))
+                        (funcall idlwave--complete-after-success-function))
                     (set-window-start cwin (point-min)))))
          (and message (message "%s" message)))
       (select-window win))))
@@ -6882,7 +6858,7 @@ sort the list before displaying."
                   (skip-chars-backward "a-zA-Z0-9_")
                   (point))))
        (remove-text-properties beg (point) '(face nil))))
-  (eval idlwave-complete-after-success-form-force))
+  (funcall idlwave--complete-after-success-force-function))
 
 (defun idlwave-keyboard-quit ()
   (interactive)
@@ -6990,16 +6966,15 @@ If these don't exist, a letter in the string is 
automatically selected."
 
 (defun idlwave-local-value (var &optional buffer)
   "Return the value of VAR in BUFFER, but only if VAR is local to BUFFER."
-  (with-current-buffer (or buffer (current-buffer))
-    (and (local-variable-p var (current-buffer))
-        (symbol-value var))))
+  (when (local-variable-p var buffer)
+    (buffer-local-value var (or buffer (current-buffer)))))
 
 (defvar idlwave-completion-map nil
   "Keymap for `completion-list-mode' with `idlwave-complete'.")
 
-(defun idlwave-default-choose-completion (&rest args)
-  "Execute `default-choose-completion' and then restore the win-conf."
-  (apply 'idlwave-choose 'default-choose-completion args))
+;; (defun idlwave-default-choose-completion (&rest args)
+;;   "Execute `default-choose-completion' and then restore the win-conf."
+;;   (apply #'idlwave-choose #'default-choose-completion args))
 
 (define-obsolete-function-alias 'idlwave-display-completion-list-emacs
   #'idlwave-display-completion-list-1 "28.1")
@@ -7021,14 +6996,14 @@ If these don't exist, a letter in the string is 
automatically selected."
   "Replace `choose-completion' in OLD-MAP."
   (let ((new-map (copy-keymap old-map)))
     (substitute-key-definition
-     'choose-completion 'idlwave-choose-completion new-map)
-    (define-key new-map [mouse-3] 'idlwave-mouse-completion-help)
+     #'choose-completion #'idlwave-choose-completion new-map)
+    (define-key new-map [mouse-3] #'idlwave-mouse-completion-help)
     new-map))
 
 (defun idlwave-choose-completion (&rest args)
   "Choose the completion that point is in or next to."
   (interactive (list last-nonmenu-event))
-  (apply 'idlwave-choose 'choose-completion args))
+  (apply #'idlwave-choose #'choose-completion args))
 
 (define-obsolete-function-alias 'idlwave-mouse-choose-completion
   #'idlwave-choose-completion "28.1")
@@ -7278,8 +7253,8 @@ class/struct definition."
 (defun idlwave-all-class-tags (class)
   "Return a list of native and inherited tags in CLASS."
   (condition-case err
-      (apply 'append (mapcar 'idlwave-class-tags
-                            (cons class (idlwave-all-class-inherits class))))
+      (apply #'append (mapcar #'idlwave-class-tags
+                             (cons class (idlwave-all-class-inherits class))))
     (error
      (idlwave-class-tag-reset)
      (error "%s" (error-message-string err)))))
@@ -7369,10 +7344,9 @@ property indicating the link is added."
 (defvar idlwave-current-class-tags nil)
 (defvar idlwave-current-native-class-tags nil)
 (defvar idlwave-sint-class-tags nil)
-(declare-function idlwave-sintern-class-tag "idlwave" t t)
-(idlwave-new-sintern-type 'class-tag)
-(add-to-list 'idlwave-complete-special 'idlwave-complete-class-structure-tag)
-(add-hook 'idlwave-update-rinfo-hook 'idlwave-class-tag-reset)
+(idlwave-new-sintern-type class-tag)
+(add-hook 'idlwave-complete-functions #'idlwave-complete-class-structure-tag)
+(add-hook 'idlwave-update-rinfo-hook #'idlwave-class-tag-reset)
 
 (defun idlwave-complete-class-structure-tag ()
   "Complete a structure tag on a `self' argument in an object method."
@@ -7384,25 +7358,26 @@ property indicating the link is added."
          (skip-chars-backward "a-zA-Z0-9._$")
          (and (< (point) (- pos 4))
               (looking-at "self\\.")))
-       (let* ((class-selector (nth 2 (idlwave-current-routine)))
-              (super-classes (idlwave-all-class-inherits class-selector)))
+       (let* ((idlwave--class-selector (nth 2 (idlwave-current-routine)))
+              (idlwave--super-classes (idlwave-all-class-inherits
+                                       idlwave--class-selector)))
          ;; Check if we are in a class routine
-         (unless class-selector
+         (unless idlwave--class-selector
            (error "Not in a method procedure or function"))
          ;; Check if we need to update the "current" class
-         (if (not (equal class-selector idlwave-current-tags-class))
-             (idlwave-prepare-class-tag-completion class-selector))
+         (if (not (equal idlwave--class-selector idlwave-current-tags-class))
+             (idlwave-prepare-class-tag-completion idlwave--class-selector))
          (setq idlwave-completion-help-info
                (list 'idlwave-complete-class-structure-tag-help
                      (idlwave-sintern-routine
-                      (concat class-selector "__define"))
+                      (concat idlwave--class-selector "__define"))
                      nil))
           ;; FIXME: idlwave-cpl-bold doesn't seem used anywhere.
-         (let  ((idlwave-cpl-bold idlwave-current-native-class-tags))
+         (let  ((_idlwave-cpl-bold idlwave-current-native-class-tags))
            (idlwave-complete-in-buffer
             'class-tag 'class-tag
             idlwave-current-class-tags nil
-            (format "Select a tag of class %s" class-selector)
+            (format "Select a tag of class %s" idlwave--class-selector)
             "class tag"
             'idlwave-attach-class-tag-classes))
          t) ; return t to skip other completions
@@ -7420,7 +7395,7 @@ property indicating the link is added."
                  (list (idlwave-sintern-class-tag x 'set)))
                (idlwave-all-class-tags class)))
   (setq idlwave-current-native-class-tags
-       (mapcar 'downcase (idlwave-class-tags class))))
+       (mapcar #'downcase (idlwave-class-tags class))))
 
 ;===========================================================================
 ;;
@@ -7429,13 +7404,11 @@ property indicating the link is added."
 
 (defvar idlwave-sint-sysvars nil)
 (defvar idlwave-sint-sysvartags nil)
-(declare-function idlwave-sintern-sysvar    "idlwave" t t)
-(declare-function idlwave-sintern-sysvartag "idlwave" t t)
-(idlwave-new-sintern-type 'sysvar)
-(idlwave-new-sintern-type 'sysvartag)
-(add-to-list 'idlwave-complete-special 'idlwave-complete-sysvar-or-tag)
-(add-hook 'idlwave-update-rinfo-hook 'idlwave-sysvars-reset)
-(add-hook 'idlwave-after-load-rinfo-hook 'idlwave-sintern-sysvar-alist)
+(idlwave-new-sintern-type sysvar)
+(idlwave-new-sintern-type sysvartag)
+(add-hook 'idlwave-complete-functions #'idlwave-complete-sysvar-or-tag)
+(add-hook 'idlwave-update-rinfo-hook #'idlwave-sysvars-reset)
+(add-hook 'idlwave-after-load-rinfo-hook #'idlwave-sintern-sysvar-alist)
 
 
 (defun idlwave-complete-sysvar-or-tag ()
@@ -7591,7 +7564,7 @@ associated TAG, if any."
   (let ((text idlwave-shell-command-output)
        (start 0)
        (old idlwave-system-variables-alist)
-       var tags type name class link old-entry)
+       var tags link old-entry) ;; type name class
     (setq idlwave-system-variables-alist nil)
     (while (string-match "^IDLWAVE-SYSVAR: !\\([a-zA-Z0-9_$]+\\)\\( 
\\(.*\\)\\)?"
                         text start)
@@ -7611,7 +7584,8 @@ associated TAG, if any."
                                         (cdr (assq
                                               (idlwave-sintern-sysvartag x)
                                               (cdr (assq 'tags old-entry))))))
-                                tags)) link)
+                                tags))
+                       link)
                  idlwave-system-variables-alist)))
     ;; Keep the old value if query was not successful
     (setq idlwave-system-variables-alist
@@ -7627,15 +7601,6 @@ associated TAG, if any."
           (put-text-property (match-beginning 0) (match-end 0)
                              'face 'font-lock-string-face))))))
 
-(defun idlwave-uniquify (list)
-  (let ((ht (make-hash-table :size (length list) :test 'equal)))
-    (delq nil
-         (mapcar (lambda (x)
-                   (unless (gethash x ht)
-                     (puthash x t ht)
-                     x))
-                 list))))
-
 (defun idlwave-after-successful-completion (type slash &optional verify)
   "Add `=' or `(' after successful completion of keyword and function.
 Restore the pre-completion window configuration if possible."
@@ -7700,7 +7665,7 @@ itself."
   (setq this-command last-command)
   (idlwave-do-mouse-completion-help ev))
 
-(defun idlwave-routine-info (&optional arg external)
+(defun idlwave-routine-info (&optional arg _external)
   "Display a routines calling sequence and list of keywords.
 When point is on the name a function or procedure, or in the argument
 list of a function or procedure, this command displays a help buffer with
@@ -7737,7 +7702,7 @@ arg, the class property is cleared out."
           (idlwave-force-class-query (equal arg '(4)))
           (module (idlwave-what-module)))
       (if (car module)
-         (apply 'idlwave-display-calling-sequence
+         (apply #'idlwave-display-calling-sequence
                 (idlwave-fix-module-if-obj_new module))
        (error "Don't know which calling sequence to show")))))
 
@@ -7820,7 +7785,7 @@ force class query for object methods."
         (name (idlwave-completing-read
                (if (or (not this-buffer)
                        (assoc default list))
-                   (format "Module (Default %s): " default)
+                   (format-prompt "Module" default)
                  (format "Module in this file: "))
                list))
         type class)
@@ -7954,7 +7919,7 @@ Used by `idlwave-routine-info' and `idlwave-find-module'."
             (stringp class))
        (list (car module)
              (nth 1 module)
-             (apply 'idlwave-find-inherited-class module))
+             (apply #'idlwave-find-inherited-class module))
       module)))
 
 (defun idlwave-find-inherited-class (name type class)
@@ -7979,7 +7944,7 @@ appropriate Init method."
               (setq string (buffer-substring (point) pos))
               (string-match "obj_new([^'\"]*['\"]\\([a-zA-Z0-9_]+\\)"
                             string)))
-       (let ((name "Init")
+       (let (;; (name "Init")
              (class (match-string 1 string)))
          (setq module (list (idlwave-sintern-method "Init")
                             'fun
@@ -7992,7 +7957,8 @@ appropriate Init method."
 Translate OBJ_NEW, adding all super-class keywords, or all keywords
 from all classes if CLASS equals t.  If SYSTEM is non-nil, don't
 demand _EXTRA in the keyword list."
-  (let ((case-fold-search t))
+  (let ((case-fold-search t)
+        (idlwave--super-classes super-classes))
 
     ;; If this is the OBJ_NEW function, try to figure out the class and use
     ;; the keywords from the corresponding INIT method.
@@ -8013,7 +7979,8 @@ demand _EXTRA in the keyword list."
                               (idlwave-sintern-method "INIT")
                               'fun
                               class
-                              (idlwave-routines)) 'do-link))))))
+                              (idlwave-routines))
+                             'do-link))))))
 
     ;; If the class is t, combine all keywords of all methods NAME
     (when (eq class t)
@@ -8030,7 +7997,7 @@ demand _EXTRA in the keyword list."
     ;; If we have inheritance, add all keywords from superclasses, if
     ;; the user indicated that method in `idlwave-keyword-class-inheritance'
     (when (and
-          super-classes
+          idlwave--super-classes
           idlwave-keyword-class-inheritance
           (stringp class)
           (or
@@ -8045,7 +8012,7 @@ demand _EXTRA in the keyword list."
 
       (cl-loop for entry in (idlwave-routines) do
            (and (nth 2 entry)                           ; non-nil class
-                (memq (nth 2 entry) super-classes)      ; an inherited class
+                (memq (nth 2 entry) idlwave--super-classes) ;an inherited class
                 (eq (nth 1 entry) type)                 ; correct type
                 (eq (car entry) name)                   ; correct name
                 (mapc (lambda (k) (add-to-list 'keywords k))
@@ -8095,16 +8062,16 @@ If we do not know about MODULE, just return KEYWORD 
literally."
 
 (defvar idlwave-rinfo-mouse-map
   (let ((map (make-sparse-keymap)))
-    (define-key map [mouse-2] 'idlwave-mouse-active-rinfo)
-    (define-key map [(shift mouse-2)] 'idlwave-mouse-active-rinfo-shift)
-    (define-key map [mouse-3] 'idlwave-mouse-active-rinfo-right)
-    (define-key map " " 'idlwave-active-rinfo-space)
-    (define-key map "q" 'idlwave-quit-help)
+    (define-key map [mouse-2] #'idlwave-mouse-active-rinfo)
+    (define-key map [(shift mouse-2)] #'idlwave-mouse-active-rinfo-shift)
+    (define-key map [mouse-3] #'idlwave-mouse-active-rinfo-right)
+    (define-key map " " #'idlwave-active-rinfo-space)
+    (define-key map "q" #'idlwave-quit-help)
     map))
 
 (defvar idlwave-rinfo-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "q" 'idlwave-quit-help)
+    (define-key map "q" #'idlwave-quit-help)
     map))
 
 (defvar idlwave-popup-source nil)
@@ -8151,7 +8118,7 @@ If we do not know about MODULE, just return KEYWORD 
literally."
         (data (list name type class (current-buffer) nil initial-class))
         (face 'idlwave-help-link)
         beg props win cnt total)
-    ;; Fix keywords, but don't add chained super-classes, since these
+    ;; Fix keywords, but don't add chained idlwave--super-classes, since these
     ;; are shown separately for that super-class
     (setq keywords (idlwave-fix-keywords name type class keywords))
     (cond
@@ -8336,7 +8303,7 @@ to it."
       (add-text-properties beg (point) (list 'face 'bold)))
     (when (and file (not (equal file "")))
       (setq beg (point))
-      (insert (apply 'abbreviate-file-name (list file)))
+      (insert (apply #'abbreviate-file-name (list file)))
       (if file-props
          (add-text-properties beg (point) file-props)))))
 
@@ -8441,9 +8408,9 @@ was pressed."
               idlwave-keyword-completion-adds-equal)
          (insert "=")))))
 
-(defun idlwave-list-buffer-load-path-shadows (&optional arg)
+(defun idlwave-list-buffer-load-path-shadows (&optional _arg)
   "List the load path shadows of all routines defined in current buffer."
-  (interactive "P")
+  (interactive)
   (idlwave-routines)
   (if (derived-mode-p 'idlwave-mode)
       (idlwave-list-load-path-shadows
@@ -8451,13 +8418,13 @@ was pressed."
        "in current buffer")
     (error "Current buffer is not in idlwave-mode")))
 
-(defun idlwave-list-shell-load-path-shadows (&optional arg)
+(defun idlwave-list-shell-load-path-shadows (&optional _arg)
   "List the load path shadows of all routines compiled under the shell.
 This is very useful for checking an IDL application.  Just compile the
 application, do RESOLVE_ALL, and `C-c C-i' to compile all referenced
 routines and update IDLWAVE internal info.  Then check for shadowing
 with this command."
-  (interactive "P")
+  (interactive)
   (cond
    ((or (not (fboundp 'idlwave-shell-is-running))
        (not (idlwave-shell-is-running)))
@@ -8468,15 +8435,15 @@ with this command."
     (idlwave-list-load-path-shadows nil idlwave-compiled-routines
                                    "in the shell"))))
 
-(defun idlwave-list-all-load-path-shadows (&optional arg)
+(defun idlwave-list-all-load-path-shadows (&optional _arg)
   "List the load path shadows of all routines known to IDLWAVE."
-  (interactive "P")
+  (interactive)
   (idlwave-list-load-path-shadows nil nil "globally"))
 
 (defvar idlwave-sort-prefer-buffer-info t
   "Internal variable used to influence `idlwave-routine-twin-compare'.")
 
-(defun idlwave-list-load-path-shadows (arg &optional special-routines loc)
+(defun idlwave-list-load-path-shadows (_arg &optional special-routines loc)
   "List the routines which are defined multiple times.
 Search the information IDLWAVE has about IDL routines for multiple
 definitions.
@@ -8525,12 +8492,12 @@ can be used to detect possible name clashes during this 
process."
       (lambda (ev)
        (interactive "e")
        (mouse-set-point ev)
-       (apply 'idlwave-do-find-module
+       (apply #'idlwave-do-find-module
               (get-text-property (point) 'find-args))))
     (define-key keymap [(return)]
       (lambda ()
        (interactive)
-       (apply 'idlwave-do-find-module
+       (apply #'idlwave-do-find-module
               (get-text-property (point) 'find-args))))
     (message "Compiling list...( 0%%)")
     (with-current-buffer (get-buffer-create "*Shadows*")
@@ -8606,6 +8573,10 @@ ENTRY will also be returned, as the first item of this 
list."
        (push candidate twins))
     (cons entry (nreverse twins))))
 
+;; Bound in idlwave-study-twins,idlwave-routine-entry-compare-twins.
+(defvar idlwave-twin-class)
+(defvar idlwave-twin-name)
+
 (defun idlwave-study-twins (entries)
   "Return dangerous twins of first entry in ENTRIES.
 Dangerous twins are routines with same name, but in different files on
@@ -8618,7 +8589,7 @@ routines, and may have been scanned."
         (type (nth 1 entry))    ; Must be bound for
         (idlwave-twin-class (nth 2 entry)) ;  idlwave-routine-twin-compare
         (cnt 0)
-        source type type-cons file alist syslibp key)
+        source type-cons file alist syslibp key)
     (while (setq entry (pop entries))
       (cl-incf cnt)
       (setq source (nth 3 entry)
@@ -8654,12 +8625,12 @@ routines, and may have been scanned."
     (when (and (idlwave-syslib-scanned-p)
               (setq entry (assoc 'system alist)))
       (setcar entry 'builtin))
-    (sort alist 'idlwave-routine-twin-compare)))
+    (sort alist #'idlwave-routine-twin-compare)))
 
 ;; FIXME: Dynamically scoped vars need to use the `idlwave-' prefix.
 ;; (defvar type)
 
-(define-obsolete-function-alias 'idlwave-xor 'xor "27.1")
+(define-obsolete-function-alias 'idlwave-xor #'xor "27.1")
 
 (defun idlwave-routine-entry-compare (a b)
   "Compare two routine info entries for sorting.
@@ -8690,7 +8661,7 @@ names and path locations."
   "Compare two routine entries, under the assumption that they are twins.
 This basically calls `idlwave-routine-twin-compare' with the correct args."
   (let* ((idlwave-twin-name (car a))
-        (type (nth 1 a))
+        ;; (type (nth 1 a))
         (idlwave-twin-class (nth 2 a)) ; used in idlwave-routine-twin-compare
         (asrc (nth 3 a))
         (atype (car asrc))
@@ -8706,10 +8677,6 @@ This basically calls `idlwave-routine-twin-compare' with 
the correct args."
         (list (file-truename bfile) bfile (list btype))
        (list btype bfile (list btype))))))
 
-;; Bound in idlwave-study-twins,idlwave-routine-entry-compare-twins.
-(defvar idlwave-twin-class)
-(defvar idlwave-twin-name)
-
 (defun idlwave-routine-twin-compare (a b)
   "Compare two routine twin entries for sorting.
 In here, A and B are not normal routine info entries, but special
@@ -8809,9 +8776,7 @@ This expects NAME TYPE IDLWAVE-TWIN-CLASS to be bound to 
the right values."
 
 (defun idlwave-path-alist-add-flag (list-entry flag)
   "Add a flag to the path list entry, if not set."
-  (let ((flags (cdr list-entry)))
-    (add-to-list 'flags flag)
-    (setcdr list-entry flags)))
+  (cl-pushnew flag (cdr list-entry) :test #'equal))
 
 (defun idlwave-path-alist-remove-flag (list-entry flag)
   "Remove a flag to the path list entry, if set."
@@ -8920,8 +8885,8 @@ Assumes that point is at the beginning of the unit as 
found by
      ["(Un)Comment Region" idlwave-toggle-comment-region t]
      ["Continue/Split line" idlwave-split-line t]
      "--"
-     ["Toggle Auto Fill" idlwave-auto-fill-mode :style toggle
-      :selected (symbol-value idlwave-fill-function)])
+     ["Toggle Auto Fill" auto-fill-mode :style toggle
+      :selected auto-fill-function])
     ("Templates"
      ["Procedure" idlwave-procedure t]
      ["Function" idlwave-function t]
@@ -9069,7 +9034,7 @@ With arg, list all abbrevs with the corresponding hook.
 This function was written since `list-abbrevs' looks terrible for IDLWAVE 
mode."
 
   (interactive "P")
-  (let ((table (symbol-value 'idlwave-mode-abbrev-table))
+  (let ((table idlwave-mode-abbrev-table)
        abbrevs
        str rpl func fmt (len-str 0) (len-rpl 0))
     (mapatoms
@@ -9127,6 +9092,9 @@ This function was written since `list-abbrevs' looks 
terrible for IDLWAVE mode."
 ;; Run the hook
 (run-hooks 'idlwave-load-hook)
 
+;; Obsolete.
+(define-obsolete-function-alias 'idlwave-uniquify #'seq-uniq "28.1")
+
 (provide 'idlwave)
 
 ;;; idlwave.el ends here
diff --git a/lisp/progmodes/inf-lisp.el b/lisp/progmodes/inf-lisp.el
index 146ed4d..0a72ae9 100644
--- a/lisp/progmodes/inf-lisp.el
+++ b/lisp/progmodes/inf-lisp.el
@@ -1,7 +1,6 @@
-;;; inf-lisp.el --- an inferior-lisp mode
+;;; inf-lisp.el --- an inferior-lisp mode  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1988, 1993-1994, 2001-2021 Free Software Foundation,
-;; Inc.
+;; Copyright (C) 1988-2021 Free Software Foundation, Inc.
 
 ;; Author: Olin Shivers <shivers@cs.cmu.edu>
 ;; Keywords: processes, lisp
@@ -23,13 +22,13 @@
 
 ;;; Commentary:
 
-;; Hacked from tea.el by Olin Shivers (shivers@cs.cmu.edu). 8/88
+;; Hacked from tea.el by Olin Shivers (shivers@cs.cmu.edu).  8/88
 
 ;; This file defines a lisp-in-a-buffer package (inferior-lisp mode)
 ;; built on top of comint mode.  This version is more featureful,
 ;; robust, and uniform than the Emacs 18 version.  The key bindings are
 ;; also more compatible with the bindings of Hemlock and Zwei (the
-;; Lisp Machine emacs).
+;; Lisp Machine Emacs).
 
 ;; Since this mode is built on top of the general command-interpreter-in-
 ;; a-buffer mode (comint mode), it shares a common base functionality,
@@ -40,19 +39,19 @@
 ;; the hooks available for customizing it, see the file comint.el.
 ;; For further information on inferior-lisp mode, see the comments below.
 
-;; Needs fixin:
+;; Needs fixing:
 ;; The load-file/compile-file default mechanism could be smarter -- it
 ;; doesn't know about the relationship between filename extensions and
-;; whether the file is source or executable. If you compile foo.lisp
+;; whether the file is source or executable.  If you compile foo.lisp
 ;; with compile-file, then the next load-file should use foo.bin for
-;; the default, not foo.lisp. This is tricky to do right, particularly
+;; the default, not foo.lisp.  This is tricky to do right, particularly
 ;; because the extension for executable files varies so much (.o, .bin,
 ;; .lbin, .mo, .vo, .ao, ...).
 ;;
 ;; It would be nice if inferior-lisp (and inferior scheme, T, ...) modes
 ;; had a verbose minor mode wherein sending or compiling defuns, etc.
 ;; would be reflected in the transcript with suitable comments, e.g.
-;; ";;; redefining fact". Several ways to do this. Which is right?
+;; ";;; redefining fact".  Several ways to do this.  Which is right?
 ;;
 ;; When sending text from a source file to a subprocess, the process-mark can
 ;; move off the window, so you can lose sight of the process interactions.
@@ -81,19 +80,19 @@ mode.  Default is whitespace followed by 0 or 1 
single-letter colon-keyword
 (defvar inferior-lisp-mode-map
   (let ((map (copy-keymap comint-mode-map)))
     (set-keymap-parent map lisp-mode-shared-map)
-    (define-key map "\C-x\C-e" 'lisp-eval-last-sexp)
-    (define-key map "\C-c\C-l" 'lisp-load-file)
-    (define-key map "\C-c\C-k" 'lisp-compile-file)
-    (define-key map "\C-c\C-a" 'lisp-show-arglist)
-    (define-key map "\C-c\C-d" 'lisp-describe-sym)
-    (define-key map "\C-c\C-f" 'lisp-show-function-documentation)
-    (define-key map "\C-c\C-v" 'lisp-show-variable-documentation)
+    (define-key map "\C-x\C-e" #'lisp-eval-last-sexp)
+    (define-key map "\C-c\C-l" #'lisp-load-file)
+    (define-key map "\C-c\C-k" #'lisp-compile-file)
+    (define-key map "\C-c\C-a" #'lisp-show-arglist)
+    (define-key map "\C-c\C-d" #'lisp-describe-sym)
+    (define-key map "\C-c\C-f" #'lisp-show-function-documentation)
+    (define-key map "\C-c\C-v" #'lisp-show-variable-documentation)
     map))
 
 (easy-menu-define
   inferior-lisp-menu
   inferior-lisp-mode-map
-  "Inferior Lisp Menu"
+  "Inferior Lisp Menu."
   '("Inf-Lisp"
     ["Eval Last Sexp" lisp-eval-last-sexp t]
     "--"
@@ -107,20 +106,20 @@ mode.  Default is whitespace followed by 0 or 1 
single-letter colon-keyword
 
 ;;; These commands augment Lisp mode, so you can process Lisp code in
 ;;; the source files.
-(define-key lisp-mode-map "\M-\C-x"  'lisp-eval-defun)     ; GNU convention
-(define-key lisp-mode-map "\C-x\C-e" 'lisp-eval-last-sexp) ; GNU convention
-(define-key lisp-mode-map "\C-c\C-e" 'lisp-eval-defun)
-(define-key lisp-mode-map "\C-c\C-r" 'lisp-eval-region)
-(define-key lisp-mode-map "\C-c\C-n" 'lisp-eval-form-and-next)
-(define-key lisp-mode-map "\C-c\C-p" 'lisp-eval-paragraph)
-(define-key lisp-mode-map "\C-c\C-c" 'lisp-compile-defun)
-(define-key lisp-mode-map "\C-c\C-z" 'switch-to-lisp)
-(define-key lisp-mode-map "\C-c\C-l" 'lisp-load-file)
-(define-key lisp-mode-map "\C-c\C-k" 'lisp-compile-file)  ; "kompile" file
-(define-key lisp-mode-map "\C-c\C-a" 'lisp-show-arglist)
-(define-key lisp-mode-map "\C-c\C-d" 'lisp-describe-sym)
-(define-key lisp-mode-map "\C-c\C-f" 'lisp-show-function-documentation)
-(define-key lisp-mode-map "\C-c\C-v" 'lisp-show-variable-documentation)
+(define-key lisp-mode-map "\M-\C-x"  #'lisp-eval-defun)     ; GNU convention
+(define-key lisp-mode-map "\C-x\C-e" #'lisp-eval-last-sexp) ; GNU convention
+(define-key lisp-mode-map "\C-c\C-e" #'lisp-eval-defun)
+(define-key lisp-mode-map "\C-c\C-r" #'lisp-eval-region)
+(define-key lisp-mode-map "\C-c\C-n" #'lisp-eval-form-and-next)
+(define-key lisp-mode-map "\C-c\C-p" #'lisp-eval-paragraph)
+(define-key lisp-mode-map "\C-c\C-c" #'lisp-compile-defun)
+(define-key lisp-mode-map "\C-c\C-z" #'switch-to-lisp)
+(define-key lisp-mode-map "\C-c\C-l" #'lisp-load-file)
+(define-key lisp-mode-map "\C-c\C-k" #'lisp-compile-file)  ; "kompile" file
+(define-key lisp-mode-map "\C-c\C-a" #'lisp-show-arglist)
+(define-key lisp-mode-map "\C-c\C-d" #'lisp-describe-sym)
+(define-key lisp-mode-map "\C-c\C-f" #'lisp-show-function-documentation)
+(define-key lisp-mode-map "\C-c\C-v" #'lisp-show-variable-documentation)
 
 
 ;; This function exists for backwards compatibility.
@@ -133,24 +132,23 @@ mode.  Default is whitespace followed by 0 or 1 
single-letter colon-keyword
 ;;;  (with-eval-after-load 'inf-lisp 'inferior-lisp-install-letter-bindings)
 ;;;You can modify this function to install just the bindings you want."
 (defun inferior-lisp-install-letter-bindings ()
-  (define-key lisp-mode-map "\C-ce" 'lisp-eval-defun-and-go)
-  (define-key lisp-mode-map "\C-cr" 'lisp-eval-region-and-go)
-  (define-key lisp-mode-map "\C-cc" 'lisp-compile-defun-and-go)
-  (define-key lisp-mode-map "\C-cz" 'switch-to-lisp)
-  (define-key lisp-mode-map "\C-cl" 'lisp-load-file)
-  (define-key lisp-mode-map "\C-ck" 'lisp-compile-file)
-  (define-key lisp-mode-map "\C-ca" 'lisp-show-arglist)
-  (define-key lisp-mode-map "\C-cd" 'lisp-describe-sym)
-  (define-key lisp-mode-map "\C-cf" 'lisp-show-function-documentation)
-  (define-key lisp-mode-map "\C-cv" 'lisp-show-variable-documentation)
-
-  (define-key inferior-lisp-mode-map "\C-cl" 'lisp-load-file)
-  (define-key inferior-lisp-mode-map "\C-ck" 'lisp-compile-file)
-  (define-key inferior-lisp-mode-map "\C-ca" 'lisp-show-arglist)
-  (define-key inferior-lisp-mode-map "\C-cd" 'lisp-describe-sym)
-  (define-key inferior-lisp-mode-map "\C-cf" 'lisp-show-function-documentation)
-  (define-key inferior-lisp-mode-map "\C-cv"
-    'lisp-show-variable-documentation))
+  (define-key lisp-mode-map "\C-ce" #'lisp-eval-defun-and-go)
+  (define-key lisp-mode-map "\C-cr" #'lisp-eval-region-and-go)
+  (define-key lisp-mode-map "\C-cc" #'lisp-compile-defun-and-go)
+  (define-key lisp-mode-map "\C-cz" #'switch-to-lisp)
+  (define-key lisp-mode-map "\C-cl" #'lisp-load-file)
+  (define-key lisp-mode-map "\C-ck" #'lisp-compile-file)
+  (define-key lisp-mode-map "\C-ca" #'lisp-show-arglist)
+  (define-key lisp-mode-map "\C-cd" #'lisp-describe-sym)
+  (define-key lisp-mode-map "\C-cf" #'lisp-show-function-documentation)
+  (define-key lisp-mode-map "\C-cv" #'lisp-show-variable-documentation)
+
+  (define-key inferior-lisp-mode-map "\C-cl" #'lisp-load-file)
+  (define-key inferior-lisp-mode-map "\C-ck" #'lisp-compile-file)
+  (define-key inferior-lisp-mode-map "\C-ca" #'lisp-show-arglist)
+  (define-key inferior-lisp-mode-map "\C-cd" #'lisp-describe-sym)
+  (define-key inferior-lisp-mode-map "\C-cf" 
#'lisp-show-function-documentation)
+  (define-key inferior-lisp-mode-map "\C-cv" 
#'lisp-show-variable-documentation))
 
 (defcustom inferior-lisp-program "lisp"
   "Program name for invoking an inferior Lisp in Inferior Lisp mode."
@@ -181,7 +179,7 @@ franz: \"^\\\\(->\\\\|<[0-9]*>:\\\\) *\"
 kcl: \"^>+ *\""
   :type 'regexp)
 
-(defvar inferior-lisp-buffer nil "*The current inferior-lisp process buffer.
+(defvar inferior-lisp-buffer nil "*The current `inferior-lisp' process buffer.
 
 MULTIPLE PROCESS SUPPORT
 ===========================================================================
@@ -326,18 +324,18 @@ Prefix argument means switch to the Lisp buffer 
afterwards."
   (if and-go (switch-to-lisp t)))
 
 (defun lisp-compile-string (string)
-  "Send the string to the inferior Lisp process to be compiled and executed."
+  "Send STRING to the inferior Lisp process to be compiled and executed."
   (comint-send-string
    (inferior-lisp-proc)
    (format "(funcall (compile nil (lambda () %s)))\n" string)))
 
 (defun lisp-eval-string (string)
-  "Send the string to the inferior Lisp process to be executed."
+  "Send STRING to the inferior Lisp process to be executed."
   (comint-send-string (inferior-lisp-proc) (concat string "\n")))
 
 (defun lisp-do-defun (do-string do-region)
   "Send the current defun to the inferior Lisp process.
-The actually processing is done by `do-string' and `do-region'
+The actually processing is done by DO-STRING and DO-REGION
  which determine whether the code is compiled before evaluation.
 DEFVAR forms reset the variables to the init values."
   (save-excursion
@@ -444,7 +442,7 @@ With argument, positions cursor at end of buffer."
 ;;;     (let ((name-start (point)))
 ;;;       (forward-sexp 1)
 ;;;       (process-send-string "inferior-lisp"
-;;;                            (format "(compile '%s #'(lambda "
+;;;                            (format "(compile '%s (lambda "
 ;;;                                    (buffer-substring name-start
 ;;;                                                      (point)))))
 ;;;     (let ((body-start (point)))
@@ -460,7 +458,7 @@ With argument, positions cursor at end of buffer."
 ;;;   (interactive "r")
 ;;;   (save-excursion
 ;;;     (goto-char start) (end-of-defun) (beginning-of-defun) ; error check
-;;;     (if (< (point) start) (error "region begins in middle of defun"))
+;;;     (if (< (point) start) (error "Region begins in middle of defun"))
 ;;;     (goto-char start)
 ;;;     (let ((s start))
 ;;;       (end-of-defun)
@@ -487,7 +485,7 @@ Used by these commands to determine defaults."
 
 (defun lisp-load-file (file-name)
   "Load a Lisp file into the inferior Lisp process."
-  (interactive (comint-get-source "Load Lisp file: " lisp-prev-l/c-dir/file
+  (interactive (comint-get-source "Load Lisp file" lisp-prev-l/c-dir/file
                                  lisp-source-modes nil)) ; nil because LOAD
                                        ; doesn't need an exact name
   (comint-check-source file-name) ; Check to see if buffer needs saved.
@@ -500,7 +498,7 @@ Used by these commands to determine defaults."
 
 (defun lisp-compile-file (file-name)
   "Compile a Lisp file in the inferior Lisp process."
-  (interactive (comint-get-source "Compile Lisp file: " lisp-prev-l/c-dir/file
+  (interactive (comint-get-source "Compile Lisp file" lisp-prev-l/c-dir/file
                                  lisp-source-modes nil)) ; nil = don't need
                                        ; suffix .lisp
   (comint-check-source file-name) ; Check to see if buffer needs saved.
@@ -591,7 +589,7 @@ See variable `lisp-function-doc-command'."
                     (format lisp-function-doc-command fn)))
 
 (defun lisp-show-variable-documentation (var)
-  "Send a command to the inferior Lisp to give documentation for function FN.
+  "Send a command to the inferior Lisp to give documentation for variable VAR.
 See variable `lisp-var-doc-command'."
   (interactive (lisp-symprompt "Variable doc" (lisp-var-at-pt)))
   (comint-proc-query (inferior-lisp-proc) (format lisp-var-doc-command var)))
@@ -620,8 +618,8 @@ See variable `lisp-describe-sym-command'."
        (error "No Lisp subprocess; see variable `inferior-lisp-buffer'"))))
 
 
-;;; Do the user's customization...
-;;;===============================
+;; Obsolete.
+
 (defvar inferior-lisp-load-hook nil
   "This hook is run when the library `inf-lisp' is loaded.")
 (make-obsolete-variable 'inferior-lisp-load-hook
diff --git a/lisp/progmodes/modula2.el b/lisp/progmodes/modula2.el
index 536d3be..2a0374a 100644
--- a/lisp/progmodes/modula2.el
+++ b/lisp/progmodes/modula2.el
@@ -1,4 +1,4 @@
-;;; modula2.el --- Modula-2 editing support package
+;;; modula2.el --- Modula-2 editing support package  -*- lexical-binding: t -*-
 
 ;; Author: Michael Schmidt <michael@pbinfo.UUCP>
 ;;     Tom Perrine <Perrin@LOGICON.ARPA>
@@ -69,33 +69,33 @@
 (defvar m2-mode-map
   (let ((map (make-sparse-keymap)))
     ;; FIXME: Many of those bindings are contrary to coding conventions.
-    (define-key map "\C-cb" 'm2-begin)
-    (define-key map "\C-cc" 'm2-case)
-    (define-key map "\C-cd" 'm2-definition)
-    (define-key map "\C-ce" 'm2-else)
-    (define-key map "\C-cf" 'm2-for)
-    (define-key map "\C-ch" 'm2-header)
-    (define-key map "\C-ci" 'm2-if)
-    (define-key map "\C-cm" 'm2-module)
-    (define-key map "\C-cl" 'm2-loop)
-    (define-key map "\C-co" 'm2-or)
-    (define-key map "\C-cp" 'm2-procedure)
-    (define-key map "\C-c\C-w" 'm2-with)
-    (define-key map "\C-cr" 'm2-record)
-    (define-key map "\C-cs" 'm2-stdio)
-    (define-key map "\C-ct" 'm2-type)
-    (define-key map "\C-cu" 'm2-until)
-    (define-key map "\C-cv" 'm2-var)
-    (define-key map "\C-cw" 'm2-while)
-    (define-key map "\C-cx" 'm2-export)
-    (define-key map "\C-cy" 'm2-import)
-    (define-key map "\C-c{" 'm2-begin-comment)
-    (define-key map "\C-c}" 'm2-end-comment)
-    (define-key map "\C-c\C-z" 'suspend-emacs)
-    (define-key map "\C-c\C-v" 'm2-visit)
-    (define-key map "\C-c\C-t" 'm2-toggle)
-    (define-key map "\C-c\C-l" 'm2-link)
-    (define-key map "\C-c\C-c" 'm2-compile)
+    (define-key map "\C-cb" #'m2-begin)
+    (define-key map "\C-cc" #'m2-case)
+    (define-key map "\C-cd" #'m2-definition)
+    (define-key map "\C-ce" #'m2-else)
+    (define-key map "\C-cf" #'m2-for)
+    (define-key map "\C-ch" #'m2-header)
+    (define-key map "\C-ci" #'m2-if)
+    (define-key map "\C-cm" #'m2-module)
+    (define-key map "\C-cl" #'m2-loop)
+    (define-key map "\C-co" #'m2-or)
+    (define-key map "\C-cp" #'m2-procedure)
+    (define-key map "\C-c\C-w" #'m2-with)
+    (define-key map "\C-cr" #'m2-record)
+    (define-key map "\C-cs" #'m2-stdio)
+    (define-key map "\C-ct" #'m2-type)
+    (define-key map "\C-cu" #'m2-until)
+    (define-key map "\C-cv" #'m2-var)
+    (define-key map "\C-cw" #'m2-while)
+    (define-key map "\C-cx" #'m2-export)
+    (define-key map "\C-cy" #'m2-import)
+    (define-key map "\C-c{" #'m2-begin-comment)
+    (define-key map "\C-c}" #'m2-end-comment)
+    (define-key map "\C-c\C-z" #'suspend-emacs)
+    (define-key map "\C-c\C-v" #'m2-visit)
+    (define-key map "\C-c\C-t" #'m2-toggle)
+    (define-key map "\C-c\C-l" #'m2-link)
+    (define-key map "\C-c\C-c" #'m2-compile)
     map)
   "Keymap used in Modula-2 mode.")
 
diff --git a/lisp/progmodes/octave.el b/lisp/progmodes/octave.el
index a8a8647..a1a5192 100644
--- a/lisp/progmodes/octave.el
+++ b/lisp/progmodes/octave.el
@@ -491,8 +491,8 @@ Non-nil means always go to the next Octave code line after 
sending."
          'font-lock-keyword-face)
    ;; Note: 'end' also serves as the last index in an indexing expression,
    ;; and 'enumerate' is also a function.
-   ;; Ref: http://www.mathworks.com/help/matlab/ref/end.html
-   ;; Ref: http://www.mathworks.com/help/matlab/ref/enumeration.html
+   ;; Ref: https://www.mathworks.com/help/matlab/ref/end.html
+   ;; Ref: https://www.mathworks.com/help/matlab/ref/enumeration.html
    (list (lambda (limit)
            (while (re-search-forward "\\_<en\\(?:d\\|umeratio\\(n\\)\\)\\_>"
                                      limit 'move)
@@ -1769,8 +1769,8 @@ sentence."
           (insert "\nRetry with ")
           (insert-text-button "'-all'"
                               'follow-link t
-                              'action #'(lambda (_b)
-                                          (octave-lookfor str '-all)))
+                              'action (lambda (_b)
+                                        (octave-lookfor str '-all)))
           (insert ".\n"))
         (octave-help-mode)))))
 
diff --git a/lisp/progmodes/perl-mode.el b/lisp/progmodes/perl-mode.el
index c7fa5ab..fd23683 100644
--- a/lisp/progmodes/perl-mode.el
+++ b/lisp/progmodes/perl-mode.el
@@ -170,9 +170,9 @@
     ;;  (1 font-lock-constant-face) (2 font-lock-variable-name-face nil t))
     ;;
     ;; Fontify function and package names in declarations.
-    ("\\<\\(package\\|sub\\)\\>[ \t]*\\(\\sw+\\)?"
+    ("\\<\\(package\\|sub\\)\\>[ \t]*\\(\\(?:\\sw\\|::\\)+\\)?"
      (1 font-lock-keyword-face) (2 font-lock-function-name-face nil t))
-    ("\\(^\\|[^$@%&\\]\\)\\<\\(import\\|no\\|require\\|use\\)\\>[ 
\t]*\\(\\sw+\\)?"
+    ("\\(?:^\\|[^$@%&\\]\\)\\<\\(import\\|no\\|require\\|use\\)\\>[ 
\t]*\\(\\(?:\\sw\\|::\\)+\\)?"
      (1 font-lock-keyword-face) (2 font-lock-constant-face nil t)))
   "Subdued level highlighting for Perl mode.")
 
@@ -187,7 +187,7 @@
               "\\>")
      ;;
      ;; Fontify declarators and prefixes as types.
-     ("\\<\\(has\\|local\\|my\\|our\\|state\\)\\>" . font-lock-type-face) ; 
declarators
+     ("\\<\\(has\\|local\\|my\\|our\\|state\\)\\>" . font-lock-keyword-face) ; 
declarators
           ;;
      ;; Fontify function, variable and file name references.
      ("&\\(\\sw+\\(::\\sw+\\)*\\)" 1 font-lock-function-name-face)
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index bd552c9..3dd1111 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -201,7 +201,8 @@ of the project instance object."
     (when maybe-prompt
       (if pr
           (project-remember-project pr)
-        (project--remove-from-project-list directory)
+        (project--remove-from-project-list
+         directory "Project `%s' not found; removed from list")
         (setq pr (cons 'transient directory))))
     pr))
 
@@ -731,13 +732,14 @@ requires quoting, e.g. `\\[quoted-insert]<space>'."
   (interactive (list (project--read-regexp)))
   (require 'xref)
   (require 'grep)
-  (let* ((pr (project-current t))
+  (let* ((caller-dir default-directory)
+         (pr (project-current t))
          (default-directory (project-root pr))
          (files
           (if (not current-prefix-arg)
               (project-files pr)
             (let ((dir (read-directory-name "Base directory: "
-                                            nil default-directory t)))
+                                            caller-dir nil t)))
               (project--files-in-directory dir
                                            nil
                                            (grep-read-files regexp))))))
@@ -781,9 +783,12 @@ pattern to search for."
       (user-error "No matches for: %s" regexp))
     xrefs))
 
+(defvar project-regexp-history-variable 'grep-regexp-history)
+
 (defun project--read-regexp ()
   (let ((sym (thing-at-point 'symbol t)))
-    (read-regexp "Find regexp" (and sym (regexp-quote sym)))))
+    (read-regexp "Find regexp" (and sym (regexp-quote sym))
+                 project-regexp-history-variable)))
 
 ;;;###autoload
 (defun project-find-file ()
@@ -911,7 +916,7 @@ if one already exists."
                    "-shell*"))
          (shell-buffer (get-buffer default-project-shell-name)))
     (if (and shell-buffer (not current-prefix-arg))
-        (pop-to-buffer shell-buffer)
+        (pop-to-buffer-same-window shell-buffer)
       (shell (generate-new-buffer-name default-project-shell-name)))))
 
 ;;;###autoload
@@ -1217,17 +1222,27 @@ Save the result in `project-list-file' if the list of 
projects has changed."
       (push (list dir) project--list)
       (project--write-project-list))))
 
-(defun project--remove-from-project-list (pr-dir)
-  "Remove directory PR-DIR of a missing project from the project list.
+(defun project--remove-from-project-list (project-root report-message)
+  "Remove directory PROJECT-ROOT of a missing project from the project list.
 If the directory was in the list before the removal, save the
 result in `project-list-file'.  Announce the project's removal
-from the list."
+from the list using REPORT-MESSAGE, which is a format string
+passed to `message' as its first argument."
   (project--ensure-read-project-list)
-  (when-let ((ent (assoc pr-dir project--list)))
+  (when-let ((ent (assoc project-root project--list)))
     (setq project--list (delq ent project--list))
-    (message "Project `%s' not found; removed from list" pr-dir)
+    (message report-message project-root)
     (project--write-project-list)))
 
+;;;###autoload
+(defun project-remove-known-project (project-root)
+  "Remove directory PROJECT-ROOT from the project list.
+PROJECT-ROOT is the root directory of a known project listed in
+the project list."
+  (interactive (list (project-prompt-project-dir)))
+  (project--remove-from-project-list
+   project-root "Project `%s' removed from known projects"))
+
 (defun project-prompt-project-dir ()
   "Prompt the user for a directory that is one of the known project roots.
 The project is chosen among projects known from the project list,
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index afb9697..e5c15d1 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -241,8 +241,8 @@
 ;; 2) Add the following hook in your .emacs:
 
 ;; (add-hook 'python-mode-hook
-;;   #'(lambda ()
-;;       (define-key python-mode-map "\C-m" 'newline-and-indent)))
+;;   (lambda ()
+;;     (define-key python-mode-map "\C-m" 'newline-and-indent)))
 
 ;; I'd recommend the first one since you'll get the same behavior for
 ;; all modes out-of-the-box.
@@ -3976,8 +3976,8 @@ Returns the tracked buffer."
   "Finish tracking."
   (python-pdbtrack-unset-tracked-buffer)
   (when python-pdbtrack-kill-buffers
-      (mapc #'(lambda (buffer)
-                (ignore-errors (kill-buffer buffer)))
+    (mapc (lambda (buffer)
+            (ignore-errors (kill-buffer buffer)))
             python-pdbtrack-buffers-to-kill))
   (setq python-pdbtrack-buffers-to-kill nil))
 
diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el
index 3f8afd9..84ac8fd 100644
--- a/lisp/progmodes/ruby-mode.el
+++ b/lisp/progmodes/ruby-mode.el
@@ -331,7 +331,7 @@ It is used when `ruby-encoding-magic-comment-style' is set 
to `custom'."
 (require 'smie)
 
 ;; Here's a simplified BNF grammar, for reference:
-;; http://www.cse.buffalo.edu/~regan/cse305/RubyBNF.pdf
+;; https://www.cse.buffalo.edu/~regan/cse305/RubyBNF.pdf
 (defconst ruby-smie-grammar
   (smie-prec2->grammar
    (smie-merge-prec2s
diff --git a/lisp/progmodes/scheme.el b/lisp/progmodes/scheme.el
index 72ac2d9..b697284 100644
--- a/lisp/progmodes/scheme.el
+++ b/lisp/progmodes/scheme.el
@@ -28,7 +28,7 @@
 ;; the Lisp mode documented in the Emacs manual.  `dsssl-mode' is a
 ;; variant of scheme-mode for editing DSSSL specifications for SGML
 ;; documents.  [As of Apr 1997, some pointers for DSSSL may be found,
-;; for instance, at <URL:http://www.sil.org/sgml/related.html#dsssl>.]
+;; for instance, at <URL:https://www.sil.org/sgml/related.html#dsssl>.]
 ;; All these Lisp-ish modes vary basically in details of the language
 ;; syntax they highlight/indent/index, but dsssl-mode uses "^;;;" as
 ;; the page-delimiter since ^L isn't normally a valid SGML character.
diff --git a/lisp/progmodes/simula.el b/lisp/progmodes/simula.el
index ef157ce..7c0de9f 100644
--- a/lisp/progmodes/simula.el
+++ b/lisp/progmodes/simula.el
@@ -1,4 +1,4 @@
-;;; simula.el --- SIMULA 87 code editing commands for Emacs
+;;; simula.el --- SIMULA 87 code editing commands for Emacs  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1992, 1994, 1996, 2001-2021 Free Software Foundation,
 ;; Inc.
@@ -52,6 +52,7 @@ the run of whitespace at the beginning of the line.")
 Otherwise TAB indents only when point is within
 the run of whitespace at the beginning of the line."
   :type 'boolean)
+(make-obsolete-variable 'simula-tab-always-indent 'tab-always-indent "28.1")
 
 (defconst simula-indent-level-default 3
   "Indentation of SIMULA statements with respect to containing block.")
@@ -148,7 +149,24 @@ Please note that the standard definitions are required
 for SIMULA mode to function correctly."
   :type '(choice file (const nil)))
 
-(defvar simula-mode-syntax-table nil
+(defvar simula-mode-syntax-table
+  (let ((st (copy-syntax-table (standard-syntax-table))))
+    (modify-syntax-entry ?!  "<"    st)
+    (modify-syntax-entry ?$  "."    st)
+    (modify-syntax-entry ?%  "< b"  st)
+    (modify-syntax-entry ?\n "> b"  st)
+    (modify-syntax-entry ?'  "\""   st)
+    (modify-syntax-entry ?\( "()"   st)
+    (modify-syntax-entry ?\) ")("   st)
+    (modify-syntax-entry ?\; ">"    st)
+    (modify-syntax-entry ?\[ "."    st)
+    (modify-syntax-entry ?\\ "."    st)
+    (modify-syntax-entry ?\] "."    st)
+    (modify-syntax-entry ?_  "_"    st)
+    (modify-syntax-entry ?\| "."    st)
+    (modify-syntax-entry ?\{ "."    st)
+    (modify-syntax-entry ?\} "."    st)
+    st)
   "Syntax table in SIMULA mode buffers.")
 
 (defconst simula-syntax-propertize-function
@@ -237,39 +255,20 @@ for SIMULA mode to function correctly."
     ["Forward Statement"      simula-next-statement t]
     ["Backward Up Level"      simula-backward-up-level t]
     ["Forward Down Statement" simula-forward-down-level t])
-  "Lucid Emacs menu for SIMULA mode.")
-
-(if simula-mode-syntax-table
-    ()
-  (setq simula-mode-syntax-table (copy-syntax-table (standard-syntax-table)))
-  (modify-syntax-entry ?!  "<"    simula-mode-syntax-table)
-  (modify-syntax-entry ?$  "."    simula-mode-syntax-table)
-  (modify-syntax-entry ?%  "< b"  simula-mode-syntax-table)
-  (modify-syntax-entry ?\n "> b"  simula-mode-syntax-table)
-  (modify-syntax-entry ?'  "\""   simula-mode-syntax-table)
-  (modify-syntax-entry ?\( "()"   simula-mode-syntax-table)
-  (modify-syntax-entry ?\) ")("   simula-mode-syntax-table)
-  (modify-syntax-entry ?\; ">"    simula-mode-syntax-table)
-  (modify-syntax-entry ?\[ "."    simula-mode-syntax-table)
-  (modify-syntax-entry ?\\ "."    simula-mode-syntax-table)
-  (modify-syntax-entry ?\] "."    simula-mode-syntax-table)
-  (modify-syntax-entry ?_  "_"    simula-mode-syntax-table)
-  (modify-syntax-entry ?\| "."    simula-mode-syntax-table)
-  (modify-syntax-entry ?\{ "."    simula-mode-syntax-table)
-  (modify-syntax-entry ?\} "."    simula-mode-syntax-table))
+  "Emacs menu for SIMULA mode.")
 
 (defvar simula-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "\C-c\C-u"   'simula-backward-up-level)
-    (define-key map "\C-c\C-p"   'simula-previous-statement)
-    (define-key map "\C-c\C-d"   'simula-forward-down-level)
-    (define-key map "\C-c\C-n"   'simula-next-statement)
-    ;; (define-key map "\C-c\C-g"   'simula-goto-definition)
-    ;; (define-key map "\C-c\C-h"   'simula-standard-help)
-    (define-key map "\177"       'backward-delete-char-untabify)
-    (define-key map ":"          'simula-electric-label)
-    (define-key map "\e\C-q"     'simula-indent-exp)
-    (define-key map "\t"         'simula-indent-command)
+    (define-key map "\C-c\C-u"   #'simula-backward-up-level)
+    (define-key map "\C-c\C-p"   #'simula-previous-statement)
+    (define-key map "\C-c\C-d"   #'simula-forward-down-level)
+    (define-key map "\C-c\C-n"   #'simula-next-statement)
+    ;; (define-key map "\C-c\C-g"   #'simula-goto-definition)
+    ;; (define-key map "\C-c\C-h"   #'simula-standard-help)
+    (define-key map "\177"       #'backward-delete-char-untabify)
+    (define-key map ":"          #'simula-electric-label)
+    (define-key map "\e\C-q"     #'simula-indent-exp)
+    ;; (define-key map "\t"         #'simula-indent-command)
     map)
   "Keymap used in `simula-mode'.")
 
@@ -285,8 +284,8 @@ for SIMULA mode to function correctly."
     ["Previous Statement" simula-previous-statement
      :enable (not (bobp))]
     "---"
-    ["Indent Line" simula-indent-command
-     :enable (not buffer-read-only)]
+    ;; ["Indent Line" simula-indent-command
+    ;;  :enable (not buffer-read-only)]
     ["Indent Expression" simula-indent-exp
      :enable (not buffer-read-only)]))
 
@@ -295,9 +294,6 @@ for SIMULA mode to function correctly."
   "Major mode for editing SIMULA code.
 \\{simula-mode-map}
 Variables controlling indentation style:
- `simula-tab-always-indent'
-    Non-nil means TAB in SIMULA mode should always reindent the current line,
-    regardless of where in the line point is when the TAB command is used.
  `simula-indent-level'
     Indentation of SIMULA statements with respect to containing block.
  `simula-substatement-offset'
@@ -335,7 +331,7 @@ with no arguments, if that value is non-nil."
   ;; (setq-local end-comment-column 75)
   (setq-local paragraph-start "[ \t]*$\\|\f")
   (setq-local paragraph-separate paragraph-start)
-  (setq-local indent-line-function 'simula-indent-line)
+  (setq-local indent-line-function #'simula-indent-line)
   (setq-local comment-start "! ")
   (setq-local comment-end " ;")
   (setq-local comment-start-skip "!+ *")
@@ -415,6 +411,7 @@ A numeric argument, regardless of its value, means indent 
rigidly
 all the lines of the SIMULA statement after point so that this line
 becomes properly indented.
 The relative indentation among the lines of the statement are preserved."
+  (declare (obsolete indent-for-tab-command "28.1"))
   (interactive "P")
   (let ((case-fold-search t))
     (if (or whole-exp simula-tab-always-indent
@@ -1564,18 +1561,6 @@ If not nil and not t, move to limit of search and return 
nil."
   (simula-install-standard-abbrevs))
 
 ;; Hilit mode support.
-(when (fboundp 'hilit-set-mode-patterns)
-  (when (and (boundp 'hilit-patterns-alist)
-            (not (assoc 'simula-mode hilit-patterns-alist)))
-    (hilit-set-mode-patterns
-     'simula-mode
-     '(
-       ("^%\\([ \t\f].*\\)?$" nil comment)
-       ("^%include\\>" nil include)
-       ("\"[^\"\n]*\"\\|'.'\\|'![0-9]+!'" nil string)
-       
("\\<\\(ACTIVATE\\|AFTER\\|AND\\|ARRAY\\|AT\\|BEFORE\\|BEGIN\\|BOOLEAN\\|CHARACTER\\|CLASS\\|DELAY\\|DO\\|ELSE\\|END\\|EQ\\|EQV\\|EXTERNAL\\|FALSE\\|FOR\\|GE\\|GO\\|GOTO\\|GT\\|HIDDEN\\|IF\\|IMP\\|IN\\|INNER\\|INSPECT\\|INTEGER\\|IS\\|LABEL\\|LE\\|LONG\\|LT\\|NAME\\|NE\\|NEW\\|NONE\\|NOT\\|NOTEXT\\|OR\\|OTHERWISE\\|PRIOR\\|PROCEDURE\\|PROTECTED\\|QUA\\|REACTIVATE\\|REAL\\|REF\\|SHORT\\|STEP\\|SWITCH\\|TEXT\\|THEN\\|THIS\\|TO\\|TRUE\\|UNTIL\\|VALUE\\|VIRTUAL\\|WHEN\\|WHILE\\)\\>"
 n [...]
-       ("!\\|\\<COMMENT\\>" ";" comment))
-     nil 'case-insensitive)))
 
 ;; obsolete
 
@@ -1586,7 +1571,7 @@ If not nil and not t, move to limit of search and return 
nil."
                        "24.4")
 
 (define-obsolete-function-alias 'simula-submit-bug-report
-  'report-emacs-bug "24.4")
+  #'report-emacs-bug "24.4")
 
 (defun simula-popup-menu (_e)
   "Pops up the SIMULA menu."
diff --git a/lisp/progmodes/sql.el b/lisp/progmodes/sql.el
index f1f4d61..6224b3b 100644
--- a/lisp/progmodes/sql.el
+++ b/lisp/progmodes/sql.el
@@ -2992,7 +2992,7 @@ displayed."
 ;; (defconst sql-smie-grammar
 ;;   (smie-prec2->grammar
 ;;    (smie-bnf->prec2
-;;     ;; Partly based on http://www.h2database.com/html/grammar.html
+;;     ;; Partly based on https://www.h2database.com/html/grammar.html
 ;;     '((cmd ("SELECT" select-exp "FROM" select-table-exp)
 ;;            )
 ;;       (select-exp ("*") (exp) (exp "AS" column-alias))
diff --git a/lisp/progmodes/tcl.el b/lisp/progmodes/tcl.el
index 82e1343..f6a50bf 100644
--- a/lisp/progmodes/tcl.el
+++ b/lisp/progmodes/tcl.el
@@ -1413,7 +1413,7 @@ Prefix argument means switch to the Tcl buffer 
afterwards."
    (list
     ;; car because comint-get-source returns a list holding the
     ;; filename.
-    (car (comint-get-source "Load Tcl file: "
+    (car (comint-get-source "Load Tcl file"
                            (or (and
                                 (derived-mode-p 'tcl-mode)
                                 (buffer-file-name))
@@ -1433,7 +1433,7 @@ If an inferior Tcl process exists, it is killed first.
 Prefix argument means switch to the Tcl buffer afterwards."
   (interactive
    (list
-    (car (comint-get-source "Restart with Tcl file: "
+    (car (comint-get-source "Restart with Tcl file"
                            (or (and
                                 (derived-mode-p 'tcl-mode)
                                 (buffer-file-name))
diff --git a/lisp/progmodes/vera-mode.el b/lisp/progmodes/vera-mode.el
index 036b2f4..4622256 100644
--- a/lisp/progmodes/vera-mode.el
+++ b/lisp/progmodes/vera-mode.el
@@ -5,7 +5,7 @@
 ;; Author:      Reto Zimmermann <reto@gnu.org>
 ;; Version:     2.28
 ;; Keywords:    languages vera
-;; WWW:         http://www.iis.ee.ethz.ch/~zimmi/emacs/vera-mode.html
+;; WWW:         https://guest.iis.ee.ethz.ch/~zimmi/emacs/vera-mode.html
 
 ;; Yoni Rabkin <yoni@rabkins.net> contacted the maintainer of this
 ;; file on 18/3/2008, and the maintainer agreed that when a bug is
@@ -249,7 +249,7 @@ Add a description of the problem and include a reproducible 
test case.
 Feel free to send questions and enhancement requests to <reto@gnu.org>.
 
 Official distribution is at
-URL `http://www.iis.ee.ethz.ch/~zimmi/emacs/vera-mode.html'
+URL `https://www.iis.ee.ethz.ch/~zimmi/emacs/vera-mode.html'
 
 
                                                   The Vera Mode Maintainer
diff --git a/lisp/progmodes/verilog-mode.el b/lisp/progmodes/verilog-mode.el
index 55c04e1..a7f7295 100644
--- a/lisp/progmodes/verilog-mode.el
+++ b/lisp/progmodes/verilog-mode.el
@@ -9,7 +9,7 @@
 ;; Keywords: languages
 ;; The "Version" is the date followed by the decimal rendition of the Git
 ;;     commit hex.
-;; Version: 2021.02.02.263931197
+;; Version: 2021.03.30.243771231
 
 ;; Yoni Rabkin <yoni@rabkins.net> contacted the maintainer of this
 ;; file on 19/3/2008, and the maintainer agreed that when a bug is
@@ -124,7 +124,7 @@
 ;;
 
 ;; This variable will always hold the version number of the mode
-(defconst verilog-mode-version "2021-02-02-fbb453d-vpo-GNU"
+(defconst verilog-mode-version "2021-03-30-e87a75f-vpo-GNU"
   "Version of this Verilog mode.")
 (defconst verilog-mode-release-emacs t
   "If non-nil, this version of Verilog mode was released with Emacs itself.")
@@ -290,7 +290,7 @@ STRING should be given if the last search was by 
`string-match' on STRING."
             (concat open (mapconcat 'regexp-quote strings "\\|") close)))
         )
     ;; Emacs.
-    (defalias 'verilog-regexp-opt 'regexp-opt)))
+    (defalias 'verilog-regexp-opt #'regexp-opt)))
 
 ;; emacs >=22 has looking-back, but older emacs and xemacs don't.
 ;; This function is lifted directly from emacs's subr.el
@@ -300,7 +300,7 @@ STRING should be given if the last search was by 
`string-match' on STRING."
 (eval-and-compile
   (cond
    ((fboundp 'looking-back)
-    (defalias 'verilog-looking-back 'looking-back))
+    (defalias 'verilog-looking-back #'looking-back))
    (t
     (defun verilog-looking-back (regexp limit &optional greedy)
       "Return non-nil if text before point matches regular expression REGEXP.
@@ -340,14 +340,14 @@ wherever possible, since it is slow."
   (cond
    ((fboundp 'restore-buffer-modified-p)
     ;; Faster, as does not update mode line when nothing changes
-    (defalias 'verilog-restore-buffer-modified-p 'restore-buffer-modified-p))
+    (defalias 'verilog-restore-buffer-modified-p #'restore-buffer-modified-p))
    (t
-    (defalias 'verilog-restore-buffer-modified-p 'set-buffer-modified-p))))
+    (defalias 'verilog-restore-buffer-modified-p #'set-buffer-modified-p))))
 
 (eval-and-compile
   (cond
    ((fboundp 'quit-window)
-    (defalias 'verilog-quit-window 'quit-window))
+    (defalias 'verilog-quit-window #'quit-window))
    (t
     (defun verilog-quit-window (_kill-ignored window)
       "Quit WINDOW and bury its buffer. KILL-IGNORED is ignored."
@@ -379,7 +379,7 @@ wherever possible, since it is slow."
   ;; Added in Emacs 25.1
   (condition-case nil
       (unless (fboundp 'forward-word-strictly)
-        (defalias 'forward-word-strictly 'forward-word))
+        (defalias 'forward-word-strictly #'forward-word))
     (error nil)))
 
 (eval-when-compile
@@ -1483,48 +1483,48 @@ If set will become buffer local.")
 
 (defvar verilog-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map ";"        'electric-verilog-semi)
-    (define-key map [(control 59)]    'electric-verilog-semi-with-comment)
-    (define-key map ":"        'electric-verilog-colon)
+    (define-key map ";"        #'electric-verilog-semi)
+    (define-key map [(control 59)]    #'electric-verilog-semi-with-comment)
+    (define-key map ":"        #'electric-verilog-colon)
     ;;(define-key map "="        'electric-verilog-equal)
-    (define-key map "`"        'electric-verilog-tick)
-    (define-key map "\t"       'electric-verilog-tab)
-    (define-key map "\r"       'electric-verilog-terminate-line)
+    (define-key map "`"        #'electric-verilog-tick)
+    (define-key map "\t"       #'electric-verilog-tab)
+    (define-key map "\r"       #'electric-verilog-terminate-line)
     ;; backspace/delete key bindings
-    (define-key map [backspace]    'backward-delete-char-untabify)
+    (define-key map [backspace]    #'backward-delete-char-untabify)
     (unless (boundp 'delete-key-deletes-forward) ; XEmacs variable
-      (define-key map [delete]       'delete-char)
-      (define-key map [(meta delete)] 'kill-word))
-    (define-key map "\M-\C-b"  'electric-verilog-backward-sexp)
-    (define-key map "\M-\C-f"  'electric-verilog-forward-sexp)
-    (define-key map "\M-\r"    'electric-verilog-terminate-and-indent)
+      (define-key map [delete]       #'delete-char)
+      (define-key map [(meta delete)] #'kill-word))
+    (define-key map "\M-\C-b"  #'electric-verilog-backward-sexp)
+    (define-key map "\M-\C-f"  #'electric-verilog-forward-sexp)
+    (define-key map "\M-\r"    #'electric-verilog-terminate-and-indent)
     (define-key map "\M-\t"    (if (fboundp 'completion-at-point)
-                                   'completion-at-point 
'verilog-complete-word))
+                                   #'completion-at-point 
#'verilog-complete-word))
     (define-key map "\M-?"     (if (fboundp 'completion-help-at-point)
-                                   'completion-help-at-point 
'verilog-show-completions))
+                                   #'completion-help-at-point 
#'verilog-show-completions))
     ;; Note \C-c and letter are reserved for users
-    (define-key map "\C-c`"    'verilog-lint-off)
-    (define-key map "\C-c*"    'verilog-delete-auto-star-implicit)
-    (define-key map "\C-c?"    'verilog-diff-auto)
-    (define-key map "\C-c\C-r" 'verilog-label-be)
-    (define-key map "\C-c\C-i" 'verilog-pretty-declarations)
-    (define-key map "\C-c="    'verilog-pretty-expr)
-    (define-key map "\C-c\C-b" 'verilog-submit-bug-report)
-    (define-key map "\C-c/"    'verilog-star-comment)
-    (define-key map "\C-c\C-c" 'verilog-comment-region)
-    (define-key map "\C-c\C-u" 'verilog-uncomment-region)
+    (define-key map "\C-c`"    #'verilog-lint-off)
+    (define-key map "\C-c*"    #'verilog-delete-auto-star-implicit)
+    (define-key map "\C-c?"    #'verilog-diff-auto)
+    (define-key map "\C-c\C-r" #'verilog-label-be)
+    (define-key map "\C-c\C-i" #'verilog-pretty-declarations)
+    (define-key map "\C-c="    #'verilog-pretty-expr)
+    (define-key map "\C-c\C-b" #'verilog-submit-bug-report)
+    (define-key map "\C-c/"    #'verilog-star-comment)
+    (define-key map "\C-c\C-c" #'verilog-comment-region)
+    (define-key map "\C-c\C-u" #'verilog-uncomment-region)
     (when (featurep 'xemacs)
-      (define-key map [(meta control h)] 'verilog-mark-defun)
-      (define-key map "\M-\C-a"  'verilog-beg-of-defun)
-      (define-key map "\M-\C-e"  'verilog-end-of-defun))
-    (define-key map "\C-c\C-d" 'verilog-goto-defun)
-    (define-key map "\C-c\C-k" 'verilog-delete-auto)
-    (define-key map "\C-c\C-a" 'verilog-auto)
-    (define-key map "\C-c\C-s" 'verilog-auto-save-compile)
-    (define-key map "\C-c\C-p" 'verilog-preprocess)
-    (define-key map "\C-c\C-z" 'verilog-inject-auto)
-    (define-key map "\C-c\C-e" 'verilog-expand-vector)
-    (define-key map "\C-c\C-h" 'verilog-header)
+      (define-key map [(meta control h)] #'verilog-mark-defun)
+      (define-key map "\M-\C-a"  #'verilog-beg-of-defun)
+      (define-key map "\M-\C-e"  #'verilog-end-of-defun))
+    (define-key map "\C-c\C-d" #'verilog-goto-defun)
+    (define-key map "\C-c\C-k" #'verilog-delete-auto)
+    (define-key map "\C-c\C-a" #'verilog-auto)
+    (define-key map "\C-c\C-s" #'verilog-auto-save-compile)
+    (define-key map "\C-c\C-p" #'verilog-preprocess)
+    (define-key map "\C-c\C-z" #'verilog-inject-auto)
+    (define-key map "\C-c\C-e" #'verilog-expand-vector)
+    (define-key map "\C-c\C-h" #'verilog-header)
     map)
   "Keymap used in Verilog mode.")
 
@@ -1969,7 +1969,11 @@ To call on \\[verilog-auto], set 
`verilog-auto-delete-trailing-whitespace'."
     (unless (bolp) (insert "\n"))))
 
 (defvar compile-command)
+;; These are known to be from other packages and may not be defined
+(defvar diff-command)
+;; There are known to be from newer versions of Emacs
 (defvar create-lockfiles)  ; Emacs 24
+(defvar which-func-modes)
 
 ;; compilation program
 (defun verilog-set-compile-command ()
@@ -2009,9 +2013,10 @@ portion, will be substituted."
    (t
     (set (make-local-variable 'compile-command)
         (if verilog-tool
-            (if (string-match "%s" (eval verilog-tool))
-                (format (eval verilog-tool) (or buffer-file-name ""))
-              (concat (eval verilog-tool) " " (or buffer-file-name "")))
+            (let ((cmd (symbol-value verilog-tool)))
+              (if (string-match "%s" cmd)
+                  (format cmd (or buffer-file-name ""))
+                (concat cmd " " (or buffer-file-name ""))))
           ""))))
   (verilog-modify-compile-command))
 
@@ -2098,7 +2103,7 @@ find the errors."
   (interactive)
   (when (boundp 'compilation-error-regexp-alist-alist)
     (when (not (assoc 'verilog-xl-1 compilation-error-regexp-alist-alist))
-      (mapcar
+      (mapc
        (lambda (item)
          (push (car item) compilation-error-regexp-alist)
          (push item compilation-error-regexp-alist-alist))
@@ -5455,8 +5460,7 @@ becomes:
           (let* ((code (match-string 2))
                  (file (match-string 3))
                  (line (match-string 4))
-                 (buffer (get-file-buffer file))
-                 dir filename)
+                 (buffer (get-file-buffer file)))
             (unless buffer
               (progn
                 (setq buffer
@@ -5468,9 +5472,8 @@ becomes:
                                    (read-file-name
                                     (format "Find this error in: (default %s) "
                                             file)
-                                    dir file t))))
-                        (if (file-directory-p name)
-                            (setq name (expand-file-name filename name)))
+                                    nil ;; dir
+                                    file t))))
                         (setq buffer
                               (and (file-exists-p name)
                                    (find-file-noselect name))))))))
@@ -5613,12 +5616,11 @@ Save the result unless optional NO-SAVE is t."
      ;; Process the files
      (mapc (lambda (buf)
              (when (buffer-file-name buf)
-               (save-excursion
-                 (if (not (file-exists-p (buffer-file-name buf)))
-                     (error
-                      "File not found: %s" (buffer-file-name buf)))
-                 (message "Processing %s" (buffer-file-name buf))
-                 (set-buffer buf)
+               (if (not (file-exists-p (buffer-file-name buf)))
+                   (error
+                    "File not found: %s" (buffer-file-name buf)))
+               (message "Processing %s" (buffer-file-name buf))
+               (with-current-buffer buf
                  (funcall funref)
                  (verilog-star-cleanup)
                  (when (and (not no-save)
@@ -6648,14 +6650,9 @@ Return >0 for nested struct."
 
 (defun verilog-at-close-struct-p ()
   "If at the } that closes a struct, return true."
-  (if (and
-       (equal (char-after) ?\})
-       (verilog-in-struct-p))
-      ;; true
-      (save-excursion
-       (if (looking-at "}\\(?:\\s-*\\w+\\s-*\\)?;") 1))
-    ;; false
-    nil))
+  (and (equal (char-after) ?\})
+       (verilog-in-struct-p)
+       (looking-at "}\\(?:\\s-*\\w+\\s-*\\(?:,\\s-*\\w+\\s-*\\)*\\)?;")))
 
 (defun verilog-parenthesis-depth ()
   "Return non zero if in parenthetical-expression."
@@ -6860,16 +6857,19 @@ Only look at a few lines to determine indent level."
            (indent-line-to val)))
         (t
          (goto-char here)
-         (let ((val))
-           (verilog-beg-of-statement-1)
-           (if (and (< (point) here)
-                    (verilog-re-search-forward "=[ \t]*" here 'move)
-                    ;; not at a |=>, #=#, or [=n] operator
-                    (not (string-match "\\[=.\\|#=#\\||=>"
-                                        (or (buffer-substring (- (point) 2) 
(1+ (point)))
-                                            ""))))  ; don't let buffer 
over/under-run spoil the party
-               (setq val (current-column))
-             (setq val (eval (cdr (assoc type verilog-indent-alist)))))
+         (verilog-beg-of-statement-1)
+         (let ((val
+                (if (and (< (point) here)
+                         (verilog-re-search-forward "=[ \t]*" here 'move)
+                         ;; not at a |=>, #=#, or [=n] operator
+                         (not (string-match "\\[=.\\|#=#\\||=>"
+                                             (or (buffer-substring
+                                                  (- (point) 2) (1+ (point)))
+                                                 ;; Don't let buffer over/under
+                                                 ;; run spoil the party.
+                                                 ""))))
+                    (current-column)
+                  (eval (cdr (assoc type verilog-indent-alist))))))
            (goto-char here)
            (indent-line-to val))))))
 
@@ -7305,7 +7305,8 @@ BASEIND is the base indent to offset everything."
        (if (verilog-re-search-backward
             (or (and verilog-indent-declaration-macros
                      verilog-declaration-re-1-macro)
-                verilog-declaration-re-1-no-macro) lim t)
+                verilog-declaration-re-1-no-macro)
+            lim t)
            (progn
              (goto-char (match-end 0))
              (skip-chars-forward " \t")
@@ -7423,9 +7424,7 @@ BEG and END."
 ;;
 (defvar verilog-str nil)
 (defvar verilog-all nil)
-(defvar verilog-pred nil)
 (defvar verilog-buffer-to-use nil)
-(defvar verilog-flag nil)
 (defvar verilog-toggle-completions nil
   "True means \\<verilog-mode-map>\\[verilog-complete-word] should try all 
possible completions one by one.
 Repeated use of \\[verilog-complete-word] will show you all of them.
@@ -7572,9 +7571,7 @@ TYPE is `module', `tf' for task or function, or t if 
unknown."
     (while (verilog-re-search-forward verilog-str (point-max) t)
       (progn (setq match (buffer-substring (match-beginning 2)
                                           (match-end 2)))
-            (if (or (null verilog-pred)
-                    (funcall verilog-pred match))
-                (setq verilog-all (cons match verilog-all)))))
+             (setq verilog-all (cons match verilog-all))))
     (if (match-beginning 0)
        (goto-char (match-beginning 0)))))
 
@@ -7594,9 +7591,7 @@ for matches of `str' and adding the occurrence tp `all' 
through point END."
                  (not (match-end 1)))
        (setq match (buffer-substring (match-beginning 0) (match-end 0)))
        (if (string-match (concat "\\<" verilog-str) match)
-           (if (or (null verilog-pred)
-                   (funcall verilog-pred match))
-               (setq verilog-all (cons match verilog-all)))))
+            (setq verilog-all (cons match verilog-all))))
       (forward-line 1)))
   verilog-all)
 
@@ -7611,28 +7606,25 @@ for matches of `str' and adding the occurrence tp `all' 
through point END."
 
 (defun verilog-keyword-completion (keyword-list)
   "Give list of all possible completions of keywords in KEYWORD-LIST."
-  (mapcar (lambda (s)
-           (if (string-match (concat "\\<" verilog-str) s)
-               (if (or (null verilog-pred)
-                       (funcall verilog-pred s))
-                   (setq verilog-all (cons s verilog-all)))))
-         keyword-list))
-
-
-(defun verilog-completion (verilog-str verilog-pred verilog-flag)
-  "Function passed to `completing-read', `try-completion' or `all-completions'.
-Called to get completion on VERILOG-STR.  If VERILOG-PRED is non-nil, it
-must be a function to be called for every match to check if this should
-really be a match.  If VERILOG-FLAG is t, the function returns a list of
-all possible completions.  If VERILOG-FLAG is nil it returns a string,
-the longest possible completion, or t if VERILOG-STR is an exact match.
-If VERILOG-FLAG is `lambda', the function returns t if VERILOG-STR is an
-exact match, nil otherwise."
-  (save-excursion
-    (let ((verilog-all nil))
-      ;; Set buffer to use for searching labels. This should be set
-      ;; within functions which use verilog-completions
-      (set-buffer verilog-buffer-to-use)
+  (dolist (s keyword-list)
+    (if (string-match (concat "\\<" verilog-str) s)
+        (push s verilog-all))))
+
+
+(defun verilog-completion (str pred flag)
+  "Completion table for Verilog tokens.
+Function passed to `completing-read', `try-completion' or `all-completions'.
+Called to get completion on STR.
+If FLAG is t, the function returns a list of all possible completions.
+If FLAG is nil it returns a string, the longest possible completion,
+or t if STR is an exact match.
+If FLAG is `lambda', the function returns t if STR is an exact match,
+nil otherwise."
+  (let ((verilog-str str)
+        (verilog-all nil))
+    ;; Set buffer to use for searching labels. This should be set
+    ;; within functions which use verilog-completions
+    (with-current-buffer verilog-buffer-to-use
 
       ;; Determine what should be completed
       (let ((state (car (verilog-calculate-indent))))
@@ -7674,43 +7666,47 @@ exact match, nil otherwise."
               (verilog-keyword-completion verilog-separator-keywords))))
 
       ;; Now we have built a list of all matches. Give response to caller
-      (verilog-completion-response))))
-
-(defun verilog-completion-response ()
-  (cond ((or (equal verilog-flag 'lambda) (null verilog-flag))
-        ;; This was not called by all-completions
-        (if (null verilog-all)
-            ;; Return nil if there was no matching label
-            nil
-          ;; Get longest string common in the labels
-           ;; FIXME: Why not use `try-completion'?
-          (let* ((elm (cdr verilog-all))
-                 (match (car verilog-all))
-                 (min (length match))
-                 tmp)
-            (if (string= match verilog-str)
-                ;; Return t if first match was an exact match
-                (setq match t)
-              (while (not (null elm))
-                ;; Find longest common string
-                (if (< (setq tmp (verilog-string-diff match (car elm))) min)
-                    (progn
-                      (setq min tmp)
-                      (setq match (substring match 0 min))))
-                ;; Terminate with match=t if this is an exact match
-                (if (string= (car elm) verilog-str)
-                    (progn
-                      (setq match t)
-                      (setq elm nil))
-                  (setq elm (cdr elm)))))
-            ;; If this is a test just for exact match, return nil ot t
-            (if (and (equal verilog-flag 'lambda) (not (equal match 't)))
-                nil
-              match))))
-       ;; If flag is t, this was called by all-completions. Return
-       ;; list of all possible completions
-       (verilog-flag
-        verilog-all)))
+      (verilog--complete-with-action flag verilog-all verilog-str pred))))
+
+
+(defalias 'verilog--complete-with-action
+  (if (fboundp 'complete-with-action)
+      #'complete-with-action
+    (lambda (flag collection string _predicate)
+      (cond ((or (equal flag 'lambda) (null flag))
+            ;; This was not called by all-completions
+            (if (null collection)
+                ;; Return nil if there was no matching label
+                nil
+              ;; Get longest string common in the labels
+              (let* ((elm (cdr collection))
+                     (match (car collection))
+                     (min (length match))
+                     tmp)
+                (if (string= match string)
+                    ;; Return t if first match was an exact match
+                    (setq match t)
+                  (while (not (null elm))
+                    ;; Find longest common string
+                    (if (< (setq tmp (verilog-string-diff match (car elm)))
+                           min)
+                        (progn
+                          (setq min tmp)
+                          (setq match (substring match 0 min))))
+                    ;; Terminate with match=t if this is an exact match
+                    (if (string= (car elm) string)
+                        (progn
+                          (setq match t)
+                          (setq elm nil))
+                      (setq elm (cdr elm)))))
+                ;; If this is a test just for exact match, return nil ot t
+                (if (and (equal flag 'lambda) (not (equal match 't)))
+                    nil
+                  match))))
+           ;; If flag is t, this was called by all-completions. Return
+           ;; list of all possible completions
+           (flag
+            collection)))))
 
 (defvar verilog-last-word-numb 0)
 (defvar verilog-last-word-shown nil)
@@ -7728,7 +7724,7 @@ exact match, nil otherwise."
          (allcomp (if (and verilog-toggle-completions
                            (string= verilog-last-word-shown verilog-str))
                       verilog-last-completions
-                    (all-completions verilog-str 'verilog-completion))))
+                    (all-completions verilog-str #'verilog-completion))))
     (list b e allcomp)))
 
 (defun verilog-complete-word ()
@@ -7744,9 +7740,7 @@ and `verilog-separator-keywords'.)"
         (verilog-str (buffer-substring b e))
         (allcomp (nth 2 comp-info))
         (match (if verilog-toggle-completions
-                   "" (try-completion
-                       verilog-str (mapcar (lambda (elm)
-                                             (cons elm 0)) allcomp)))))
+                   "" (try-completion verilog-str allcomp))))
     ;; Delete old string
     (delete-region b e)
 
@@ -7818,39 +7812,38 @@ With optional second ARG non-nil, STR is the complete 
name of the instruction."
     (setq str (concat str "[a-zA-Z0-9_]*")))
   (concat "^\\s-*\\(function\\|task\\|module\\)[ 
\t]+\\(?:\\(?:static\\|automatic\\)\\s-+\\)?\\(" str "\\)\\>"))
 
-(defun verilog-comp-defun (verilog-str verilog-pred verilog-flag)
-  "Function passed to `completing-read', `try-completion' or `all-completions'.
-Returns a completion on any function name based on VERILOG-STR prefix.  If
-VERILOG-PRED is non-nil, it must be a function to be called for every match
-to check if this should really be a match.  If VERILOG-FLAG is t, the
-function returns a list of all possible completions.  If it is nil it
-returns a string, the longest possible completion, or t if VERILOG-STR is
-an exact match.  If VERILOG-FLAG is `lambda', the function returns t if
-VERILOG-STR is an exact match, nil otherwise."
-  (save-excursion
-    (let ((verilog-all nil)
-         match)
-
-      ;; Set buffer to use for searching labels. This should be set
-      ;; within functions which use verilog-completions
-      (set-buffer verilog-buffer-to-use)
+(defun verilog-comp-defun (str pred flag)
+  "Completion table for function names.
+Function passed to `completing-read', `try-completion' or `all-completions'.
+Returns a completion on any function name based on STR prefix.
+If FLAG is t, the function returns a list of all possible completions.
+If it is nil it returns a string, the longest possible completion,
+or t if STR is an exact match.
+If FLAG is `lambda', the function returns t if STR is an exact match,
+nil otherwise."
+  (let ((verilog-all nil)
+       (verilog-str str)
+       match)
+
+    ;; Set buffer to use for searching labels. This should be set
+    ;; within functions which use verilog-completions
+    (with-current-buffer verilog-buffer-to-use
 
       (let ((verilog-str verilog-str))
        ;; Build regular expression for functions
-       (if (string= verilog-str "")
-           (setq verilog-str (verilog-build-defun-re "[a-zA-Z_]"))
-         (setq verilog-str (verilog-build-defun-re verilog-str)))
+       (setq verilog-str
+             (verilog-build-defun-re (if (string= verilog-str "")
+                                         "[a-zA-Z_]"
+                                       verilog-str)))
        (goto-char (point-min))
 
        ;; Build a list of all possible completions
        (while (verilog-re-search-forward verilog-str nil t)
          (setq match (buffer-substring (match-beginning 2) (match-end 2)))
-         (if (or (null verilog-pred)
-                 (funcall verilog-pred match))
-             (setq verilog-all (cons match verilog-all)))))
+         (setq verilog-all (cons match verilog-all))))
 
       ;; Now we have built a list of all matches. Give response to caller
-      (verilog-completion-response))))
+      (verilog--complete-with-action flag verilog-all verilog-str pred))))
 
 (defun verilog-goto-defun ()
   "Move to specified Verilog module/interface/task/function.
@@ -7865,10 +7858,10 @@ If search fails, other files are checked based on
                    ;; Do completion with default
                    (completing-read (concat "Goto-Label: (default "
                                             default ") ")
-                                    'verilog-comp-defun nil nil "")
+                                    #'verilog-comp-defun nil nil "")
                  ;; There is no default value. Complete without it
                  (completing-read "Goto-Label: "
-                                  'verilog-comp-defun nil nil "")))
+                                  #'verilog-comp-defun nil nil "")))
         pt)
     ;; Make sure library paths are correct, in case need to resolve module
     (verilog-auto-reeval-locals)
@@ -7927,10 +7920,9 @@ If search fails, other files are checked based on
                 (tag (format "%3d" linenum))
                 (empty (make-string (length tag) ?\ ))
                 tem)
-           (save-excursion
-             (setq tem (make-marker))
-             (set-marker tem (point))
-             (set-buffer standard-output)
+           (setq tem (make-marker))
+           (set-marker tem (point))
+           (with-current-buffer standard-output
              (setq occur-pos-list (cons tem occur-pos-list))
              (or first (zerop nlines)
                  (insert "--------\n"))
@@ -8648,11 +8640,6 @@ Optional NUM-PARAM and MAX-PARAM check for a specific 
number of parameters."
 (defvar sigs-out-i)
 (defvar sigs-out-unk)
 (defvar sigs-temp)
-;; These are known to be from other packages and may not be defined
-(defvar diff-command)
-;; There are known to be from newer versions of Emacs
-(defvar create-lockfiles)
-(defvar which-func-modes)
 
 (defun verilog-read-decls ()
   "Compute signal declaration information for the current module at point.
@@ -10099,7 +10086,7 @@ If undefined, and WING-IT, return just SYMBOL without 
the tick, else nil."
              ;; variable in only one buffer returns t in another.
              ;; This can confuse, so check for nil.
              ;; Namespace intentionally short for AUTOs and compatibility
-             (let ((val (eval (intern (concat "vh-" symbol)))))
+             (let ((val (symbol-value (intern (concat "vh-" symbol)))))
                (if (eq val nil)
                    (if wing-it symbol nil)
                  val))
@@ -10138,7 +10125,7 @@ This function is intended for use in AUTO_TEMPLATE Lisp 
expressions."
              ;; variable in only one buffer returns t in another.
              ;; This can confuse, so check for nil.
              ;; Namespace intentionally short for AUTOs and compatibility
-             (setq val (eval (intern (concat "vh-" symbol)))))
+             (setq val (symbol-value (intern (concat "vh-" symbol)))))
             (setq text (replace-match val nil nil text)))
            (t (setq ok nil)))))
   text)
@@ -10493,7 +10480,7 @@ those clocking block's signals."
     ;; New scheme
     ;; Namespace intentionally short for AUTOs and compatibility
     (let* ((enumvar (intern (concat "venum-" enum))))
-      (dolist (en (and (boundp enumvar) (eval enumvar)))
+      (dolist (en (and (boundp enumvar) (symbol-value enumvar)))
         (let ((sig (list en)))
           (unless (member sig out-list)
             (push sig out-list)))))
@@ -10698,9 +10685,7 @@ When MODI is non-null, also add to modi-cache, for 
tracking."
        (verilog-insert "// " (verilog-sig-comment sig) "\n"))
       (setq sigs (cdr sigs)))))
 
-(defvar indent-pt) ;; Local used by `verilog-insert-indent'.
-
-(defun verilog-insert-indent (&rest stuff)
+(defun verilog--insert-indent (indent-pt &rest stuff)
   "Indent to position stored in local `indent-pt' variable, then insert STUFF.
 Presumes that any newlines end a list element."
   (let ((need-indent t))
@@ -10710,6 +10695,10 @@ Presumes that any newlines end a list element."
       (verilog-insert (car stuff))
       (setq need-indent (string-match "\n$" (car stuff))
            stuff (cdr stuff)))))
+
+(defmacro verilog-insert-indent (&rest stuff)
+  `(verilog--insert-indent indent-pt ,@stuff))
+
 ;;(let ((indent-pt 10)) (verilog-insert-indent "hello\n" "addon" "there\n"))
 
 (defun verilog-forward-or-insert-line ()
@@ -11518,7 +11507,8 @@ See the example in `verilog-auto-inout-modport'."
           (inst-name (nth 2 params))
           (regexp (nth 3 params))
            (prefix (nth 4 params))
-           direction-re submodi)  ; direction argument not supported until 
requested
+           ;; direction-re  ; direction argument not supported until requested
+           submodi)
       ;; Lookup position, etc of co-module
       ;; Note this may raise an error
       (when (setq submodi (verilog-modi-lookup submod t))
@@ -11539,11 +11529,11 @@ See the example in `verilog-auto-inout-modport'."
          (setq sig-list-i  (verilog-signals-edit-wire-reg
                             (verilog-signals-matching-dir-re
                              (verilog-signals-matching-regexp sig-list-i 
regexp)
-                             "input" direction-re))
+                             "input" nil)) ;; direction-re
                sig-list-o  (verilog-signals-edit-wire-reg
                             (verilog-signals-matching-dir-re
                              (verilog-signals-matching-regexp sig-list-o 
regexp)
-                             "output" direction-re)))
+                             "output" nil))) ;; direction-re
          (setq sig-list-i (sort (copy-alist sig-list-i) 
#'verilog-signals-sort-compare))
          (setq sig-list-o (sort (copy-alist sig-list-o) 
#'verilog-signals-sort-compare))
          (when (or sig-list-i sig-list-o)
@@ -11684,7 +11674,7 @@ If PAR-VALUES replace final strings with these 
parameter values."
       (setq tpl-net (verilog-string-replace-matches "\\[\\]" vl-bits nil nil 
tpl-net)))
     ;; Insert it
     (when (or tpl-ass (not verilog-auto-inst-template-required))
-      (verilog-auto-inst-first section)
+      (verilog--auto-inst-first indent-pt section)
       (indent-to indent-pt)
       (insert "." port)
       (unless (and verilog-auto-inst-dot-name
@@ -11723,7 +11713,7 @@ If PAR-VALUES replace final strings with these 
parameter values."
 (defvar verilog-auto-inst-first-any nil
   "Local first-in-any-section for `verilog-auto-inst-first'.")
 
-(defun verilog-auto-inst-first (section)
+(defun verilog--auto-inst-first (indent-pt section)
   "Insert , and SECTION before port, as part of \\[verilog-auto-inst]."
   ;; Do we need a trailing comma?
   ;; There maybe an ifdef or something similar before us.  What a mess.  Thus
@@ -12957,21 +12947,25 @@ that expression are included."
                             (verilog-signals-not-matching-regexp
                              (verilog-signals-matching-dir-re
                               (verilog-signals-matching-regexp sig-list-i 
regexp)
-                              "input" direction-re) not-re))
+                              "input" direction-re)
+                             not-re))
                sig-list-o  (verilog-signals-edit-wire-reg
                             (verilog-signals-not-matching-regexp
                              (verilog-signals-matching-dir-re
                               (verilog-signals-matching-regexp sig-list-o 
regexp)
-                              "output" direction-re) not-re))
+                              "output" direction-re)
+                             not-re))
                sig-list-io (verilog-signals-edit-wire-reg
                             (verilog-signals-not-matching-regexp
                              (verilog-signals-matching-dir-re
                               (verilog-signals-matching-regexp sig-list-io 
regexp)
-                              "inout" direction-re) not-re))
+                              "inout" direction-re)
+                             not-re))
                sig-list-if (verilog-signals-not-matching-regexp
                             (verilog-signals-matching-dir-re
                              (verilog-signals-matching-regexp sig-list-if 
regexp)
-                             "interface" direction-re) not-re))
+                             "interface" direction-re)
+                            not-re))
          (when v2k (verilog-repair-open-comma))
          (when (or sig-list-i sig-list-o sig-list-io sig-list-if)
            (verilog-insert-indent "// Beginning of automatic in/out/inouts 
(from specific module)\n")
@@ -13257,7 +13251,8 @@ driver/monitor using AUTOINST in the testbench."
           (modport-re (nth 1 params))
           (regexp (nth 2 params))
            (prefix (nth 3 params))
-           direction-re submodi)  ; direction argument not supported until 
requested
+           ;; direction-re  ; direction argument not supported until requested
+           submodi)
       ;; Lookup position, etc of co-module
       ;; Note this may raise an error
       (when (setq submodi (verilog-modi-lookup submod t))
@@ -13288,7 +13283,7 @@ driver/monitor using AUTOINST in the testbench."
                               (verilog-signals-add-prefix
                                (verilog-signals-matching-dir-re
                                 (verilog-signals-matching-regexp sig-list-i 
regexp)
-                                "input" direction-re)
+                                "input" nil) ;; direction-re
                                prefix)
                               (verilog-decls-get-ports moddecls)))
                sig-list-o  (verilog-signals-edit-wire-reg
@@ -13296,7 +13291,7 @@ driver/monitor using AUTOINST in the testbench."
                               (verilog-signals-add-prefix
                                (verilog-signals-matching-dir-re
                                 (verilog-signals-matching-regexp sig-list-o 
regexp)
-                                "output" direction-re)
+                                "output" nil) ;; direction-re
                                prefix)
                               (verilog-decls-get-ports moddecls)))
                sig-list-io (verilog-signals-edit-wire-reg
@@ -13304,7 +13299,7 @@ driver/monitor using AUTOINST in the testbench."
                               (verilog-signals-add-prefix
                                (verilog-signals-matching-dir-re
                                 (verilog-signals-matching-regexp sig-list-io 
regexp)
-                                "inout" direction-re)
+                                "inout" nil) ;; direction-re
                                prefix)
                               (verilog-decls-get-ports moddecls))))
          (when v2k (verilog-repair-open-comma))
@@ -14275,37 +14270,37 @@ Wilson Snyder (wsnyder@wsnyder.org)."
 
 (defvar verilog-template-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "a" 'verilog-sk-always)
-    (define-key map "b" 'verilog-sk-begin)
-    (define-key map "c" 'verilog-sk-case)
-    (define-key map "f" 'verilog-sk-for)
-    (define-key map "g" 'verilog-sk-generate)
-    (define-key map "h" 'verilog-sk-header)
-    (define-key map "i" 'verilog-sk-initial)
-    (define-key map "j" 'verilog-sk-fork)
-    (define-key map "m" 'verilog-sk-module)
-    (define-key map "o" 'verilog-sk-ovm-class)
-    (define-key map "p" 'verilog-sk-primitive)
-    (define-key map "r" 'verilog-sk-repeat)
-    (define-key map "s" 'verilog-sk-specify)
-    (define-key map "t" 'verilog-sk-task)
-    (define-key map "u" 'verilog-sk-uvm-object)
-    (define-key map "w" 'verilog-sk-while)
-    (define-key map "x" 'verilog-sk-casex)
-    (define-key map "z" 'verilog-sk-casez)
-    (define-key map "?" 'verilog-sk-if)
-    (define-key map ":" 'verilog-sk-else-if)
-    (define-key map "/" 'verilog-sk-comment)
-    (define-key map "A" 'verilog-sk-assign)
-    (define-key map "F" 'verilog-sk-function)
-    (define-key map "I" 'verilog-sk-input)
-    (define-key map "O" 'verilog-sk-output)
-    (define-key map "S" 'verilog-sk-state-machine)
-    (define-key map "=" 'verilog-sk-inout)
-    (define-key map "U" 'verilog-sk-uvm-component)
-    (define-key map "W" 'verilog-sk-wire)
-    (define-key map "R" 'verilog-sk-reg)
-    (define-key map "D" 'verilog-sk-define-signal)
+    (define-key map "a" #'verilog-sk-always)
+    (define-key map "b" #'verilog-sk-begin)
+    (define-key map "c" #'verilog-sk-case)
+    (define-key map "f" #'verilog-sk-for)
+    (define-key map "g" #'verilog-sk-generate)
+    (define-key map "h" #'verilog-sk-header)
+    (define-key map "i" #'verilog-sk-initial)
+    (define-key map "j" #'verilog-sk-fork)
+    (define-key map "m" #'verilog-sk-module)
+    (define-key map "o" #'verilog-sk-ovm-class)
+    (define-key map "p" #'verilog-sk-primitive)
+    (define-key map "r" #'verilog-sk-repeat)
+    (define-key map "s" #'verilog-sk-specify)
+    (define-key map "t" #'verilog-sk-task)
+    (define-key map "u" #'verilog-sk-uvm-object)
+    (define-key map "w" #'verilog-sk-while)
+    (define-key map "x" #'verilog-sk-casex)
+    (define-key map "z" #'verilog-sk-casez)
+    (define-key map "?" #'verilog-sk-if)
+    (define-key map ":" #'verilog-sk-else-if)
+    (define-key map "/" #'verilog-sk-comment)
+    (define-key map "A" #'verilog-sk-assign)
+    (define-key map "F" #'verilog-sk-function)
+    (define-key map "I" #'verilog-sk-input)
+    (define-key map "O" #'verilog-sk-output)
+    (define-key map "S" #'verilog-sk-state-machine)
+    (define-key map "=" #'verilog-sk-inout)
+    (define-key map "U" #'verilog-sk-uvm-component)
+    (define-key map "W" #'verilog-sk-wire)
+    (define-key map "R" #'verilog-sk-reg)
+    (define-key map "D" #'verilog-sk-define-signal)
     map)
   "Keymap used in Verilog mode for smart template operations.")
 
@@ -14696,13 +14691,13 @@ and the case items."
   (let ((map (make-sparse-keymap))) ; as described in info pages, make a map
     (set-keymap-parent map verilog-mode-map)
     ;; mouse button bindings
-    (define-key map "\r"            'verilog-load-file-at-point)
-    (if (featurep 'xemacs)
-       (define-key map 'button2    'verilog-load-file-at-mouse);ffap-at-mouse ?
-      (define-key map [mouse-2]     'verilog-load-file-at-mouse))
+    (define-key map "\r"            #'verilog-load-file-at-point)
+    (define-key map
+      (if (featurep 'xemacs) 'button2 [mouse-2])
+      #'verilog-load-file-at-mouse)
     (if (featurep 'xemacs)
-       (define-key map 'Sh-button2 'mouse-yank) ; you wanna paste don't you ?
-      (define-key map [S-mouse-2]   'mouse-yank-at-click))
+       (define-key map 'Sh-button2 #'mouse-yank) ; you wanna paste don't you ?
+      (define-key map [S-mouse-2]   #'mouse-yank-at-click))
     map)
   "Map containing mouse bindings for `verilog-mode'.")
 
@@ -14775,7 +14770,7 @@ Clicking on the middle-mouse button loads them in a 
buffer (as in dired)."
   (verilog-highlight-region (point-min) (point-max) nil))
 
 ;; Deprecated, but was interactive, so we'll keep it around
-(defalias 'verilog-colorize-include-files-buffer 'verilog-highlight-buffer)
+(defalias 'verilog-colorize-include-files-buffer #'verilog-highlight-buffer)
 
 ;; ffap-at-mouse isn't useful for Verilog mode. It uses library paths.
 ;; so define this function to do more or less the same as ffap-at-mouse
diff --git a/lisp/progmodes/vhdl-mode.el b/lisp/progmodes/vhdl-mode.el
index c8e55da..856432c 100644
--- a/lisp/progmodes/vhdl-mode.el
+++ b/lisp/progmodes/vhdl-mode.el
@@ -6,7 +6,7 @@
 ;;              Rodney J. Whitby <software.vhdl-mode@rwhitby.net>
 ;; Maintainer:  Reto Zimmermann <reto@gnu.org>
 ;; Keywords:    languages vhdl
-;; WWW:         http://www.iis.ee.ethz.ch/~zimmi/emacs/vhdl-mode.html
+;; WWW:         https://guest.iis.ee.ethz.ch/~zimmi/emacs/vhdl-mode.html
 
 ;; Yoni Rabkin <yoni@rabkins.net> contacted the maintainer of this
 ;; file on 18/3/2008, and the maintainer agreed that when a bug is
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el
index ea52bef..cada1f1 100644
--- a/lisp/progmodes/xref.el
+++ b/lisp/progmodes/xref.el
@@ -103,7 +103,7 @@ This is typically the filename.")
 
 ;;;; Commonly needed location classes are defined here:
 
-(defcustom xref-file-name-display 'abs
+(defcustom xref-file-name-display 'project-relative
   "Style of file name display in *xref* buffers.
 
 If the value is the symbol `abs', the default, show the file names
@@ -521,7 +521,7 @@ If SELECT is non-nil, select the target window."
   "Face for displaying line numbers in the xref buffer."
   :version "27.1")
 
-(defface xref-match '((t :inherit highlight))
+(defface xref-match '((t :inherit match))
   "Face used to highlight matches in the xref buffer."
   :version "27.1")
 
diff --git a/lisp/recentf.el b/lisp/recentf.el
index 48b8e2b..9ae059a 100644
--- a/lisp/recentf.el
+++ b/lisp/recentf.el
@@ -1,4 +1,4 @@
-;;; recentf.el --- setup a menu of recently opened files
+;;; recentf.el --- setup a menu of recently opened files  -*- lexical-binding: 
t -*-
 
 ;; Copyright (C) 1999-2021 Free Software Foundation, Inc.
 
@@ -24,19 +24,21 @@
 ;;; Commentary:
 
 ;; This package maintains a menu for visiting files that were operated
-;; on recently.  When enabled a new "Open Recent" sub menu is
+;; on recently.  When enabled a new "Open Recent" submenu is
 ;; displayed in the "File" menu.  The recent files list is
-;; automatically saved across Emacs sessions.  You can customize the
-;; number of recent files displayed, the location of the menu and
-;; others options (see the source code for details).
+;; automatically saved across Emacs sessions.
 
-;; To enable this package, add the following to your .emacs:
-;; (recentf-mode 1)
+;; You can customize the number of recent files displayed, the
+;; location of the menu and others options.  Type:
+;;
+;;     M-x customize-group RET recentf RET
 
-;;; History:
+;; To enable this package, add this line to your Init file:
 ;;
+;;     (recentf-mode 1)
 
 ;;; Code:
+
 (require 'tree-widget)
 (require 'timer)
 
@@ -76,7 +78,7 @@ See the command `recentf-save-list'."
   :type 'file
   :initialize 'custom-initialize-default
   :set (lambda (symbol value)
-         (let ((oldvalue (eval symbol)))
+         (let ((oldvalue (symbol-value symbol)))
            (custom-set-default symbol value)
            (and (not (equal value oldvalue))
                 recentf-mode
@@ -295,7 +297,7 @@ They are successively passed a file name to transform it."
             (function :tag "Other function")))))
 
 (defcustom recentf-show-file-shortcuts-flag t
-  "Whether to show \"[N]\" for the Nth item up to 10.
+  "Non-nil means to show \"[N]\" for the Nth item up to 10.
 If non-nil, `recentf-open-files' will show labels for keys that can be
 used as shortcuts to open the Nth file."
   :group 'recentf
@@ -330,15 +332,6 @@ Ignore case if `recentf-case-fold-search' is non-nil."
     (setq list (cdr list)))
   list)
 
-(defsubst recentf-trunc-list (l n)
-  "Return from L the list of its first N elements."
-  (let (nl)
-    (while (and l (> n 0))
-      (setq nl (cons (car l) nl)
-            n  (1- n)
-            l  (cdr l)))
-    (nreverse nl)))
-
 (defun recentf-dump-variable (variable &optional limit)
   "Insert a \"(setq VARIABLE value)\" in the current buffer.
 When the value of VARIABLE is a list, optional argument LIMIT
@@ -348,7 +341,7 @@ the full list."
     (if (atom value)
         (insert (format "\n(setq %S '%S)\n" variable value))
       (when (and (integerp limit) (> limit 0))
-        (setq value (recentf-trunc-list value limit)))
+        (setq value (seq-take value limit)))
       (insert (format "\n(setq %S\n      '(" variable))
       (dolist (e value)
         (insert (format "\n        %S" e)))
@@ -519,7 +512,7 @@ filter function this variable is reset to nil.")
 
 (defsubst recentf-elements (n)
   "Return a list of the first N elements of the recent list."
-  (recentf-trunc-list recentf-list n))
+  (seq-take recentf-list n))
 
 (defsubst recentf-make-menu-element (menu-item menu-value)
   "Create a new menu-element.
@@ -559,7 +552,7 @@ This a menu element (FILE . FILE)."
 (defsubst recentf-menu-elements (n)
   "Return a list of the first N default menu elements from the recent list.
 See also `recentf-make-default-menu-element'."
-  (mapcar 'recentf-make-default-menu-element
+  (mapcar #'recentf-make-default-menu-element
           (recentf-elements n)))
 
 (defun recentf-apply-menu-filter (filter l)
@@ -600,7 +593,7 @@ This is a menu filter function which ignores the MENU 
argument."
   (let* ((recentf-menu-shortcuts 0)
          (file-items
           (condition-case err
-              (mapcar 'recentf-make-menu-item
+              (mapcar #'recentf-make-menu-item
                       (recentf-apply-menu-filter
                        recentf-menu-filter
                        (recentf-menu-elements recentf-max-menu-items)))
@@ -642,7 +635,7 @@ Return nil if file NAME is not one of the ten more recent."
   (let ((item  (recentf-menu-element-item  elt))
         (value (recentf-menu-element-value elt)))
     (if (recentf-sub-menu-element-p elt)
-        (cons item (mapcar 'recentf-make-menu-item value))
+        (cons item (mapcar #'recentf-make-menu-item value))
       (let ((k (and (< recentf-menu-shortcuts 10)
                     (recentf-menu-value-shortcut value))))
         (vector item
@@ -767,12 +760,12 @@ This filter combines the 
`recentf-sort-basenames-descending' and
 (defun recentf-relative-filter (l)
   "Filter the list of menu-elements L to show relative filenames.
 Filenames are relative to the `default-directory'."
-  (mapcar #'(lambda (menu-element)
-              (let* ((ful (recentf-menu-element-value menu-element))
-                     (rel (file-relative-name ful default-directory)))
-                (if (string-match "^\\.\\." rel)
-                    menu-element
-                  (recentf-make-menu-element rel ful))))
+  (mapcar (lambda (menu-element)
+            (let* ((ful (recentf-menu-element-value menu-element))
+                   (rel (file-relative-name ful default-directory)))
+              (if (string-match "^\\.\\." rel)
+                  menu-element
+                (recentf-make-menu-element rel ful))))
           l))
 
 ;;; Rule based menu filters
@@ -944,10 +937,10 @@ Rules obey `recentf-arrange-rules' format."
 This simplified version of `recentf-show-basenames' does not handle
 duplicates.  It is used by `recentf-arrange-by-dir' as its
 `recentf-arrange-by-rule-subfilter'."
-  (mapcar #'(lambda (e)
-              (recentf-make-menu-element
-               (file-name-nondirectory (recentf-menu-element-value e))
-               (recentf-menu-element-value e)))
+  (mapcar (lambda (e)
+            (recentf-make-menu-element
+             (file-name-nondirectory (recentf-menu-element-value e))
+             (recentf-menu-element-value e)))
           l))
 
 (defun recentf-dir-rule (file)
@@ -1000,15 +993,15 @@ Filtering of L is delegated to the selected filter in 
the menu."
           (list
            `("Show files"
              ,@(mapcar
-                #'(lambda (f)
-                    `[,(cdr f)
-                      (setq recentf-filter-changer-current ',(car f))
-                      ;;:active t
-                      :style radio ;;radio Don't work with GTK :-(
-                      :selected (eq recentf-filter-changer-current
-                                    ',(car f))
-                      ;;:help ,(cdr f)
-                      ])
+                (lambda (f)
+                  `[,(cdr f)
+                    (setq recentf-filter-changer-current ',(car f))
+                    ;;:active t
+                    :style radio ;;radio Don't work with GTK :-(
+                    :selected (eq recentf-filter-changer-current
+                                  ',(car f))
+                    ;;:help ,(cdr f)
+                    ])
                 recentf-filter-changer-alist))))
     (recentf-apply-menu-filter recentf-filter-changer-current l)))
 
@@ -1065,9 +1058,9 @@ Go to the beginning of buffer if not found."
 (defvar recentf-dialog-mode-map
   (let ((km (copy-keymap recentf--shortcuts-keymap)))
     (set-keymap-parent km widget-keymap)
-    (define-key km "q" 'recentf-cancel-dialog)
-    (define-key km "n" 'next-line)
-    (define-key km "p" 'previous-line)
+    (define-key km "q" #'recentf-cancel-dialog)
+    (define-key km "n" #'next-line)
+    (define-key km "p" #'previous-line)
     km)
   "Keymap used in recentf dialogs.")
 
@@ -1086,8 +1079,8 @@ Go to the beginning of buffer if not found."
     ;; Cleanup buffer
     (let ((inhibit-read-only t)
           (ol (overlay-lists)))
-      (mapc 'delete-overlay (car ol))
-      (mapc 'delete-overlay (cdr ol))
+      (mapc #'delete-overlay (car ol))
+      (mapc #'delete-overlay (cdr ol))
       (erase-buffer))
     (recentf-dialog-mode)
     ,@forms
@@ -1181,7 +1174,7 @@ IGNORE other arguments."
         :node (item :tag ,(car menu-element)
                     :sample-face bold
                     :format "%{%t%}:\n")
-        ,@(mapcar 'recentf-open-files-item
+        ,@(mapcar #'recentf-open-files-item
                   (cdr menu-element)))
     ;; Represent a single file with a link widget
     `(link :tag ,(car menu-element)
@@ -1196,8 +1189,8 @@ IGNORE other arguments."
 (defun recentf-open-files-items (files)
   "Return a list of widgets to display FILES in a dialog buffer."
   (setq-local recentf--files-with-key
-              (recentf-trunc-list files 10))
-  (mapcar 'recentf-open-files-item
+              (seq-take files 10))
+  (mapcar #'recentf-open-files-item
           (append
            ;; When requested group the files with shortcuts together
            ;; at the top of the list.
@@ -1205,12 +1198,12 @@ IGNORE other arguments."
              (setq files (nthcdr 10 files))
              (recentf-apply-menu-filter
               'recentf-show-digit-shortcut-filter
-              (mapcar 'recentf-make-default-menu-element
+              (mapcar #'recentf-make-default-menu-element
                       recentf--files-with-key)))
            ;; Then the other files.
            (recentf-apply-menu-filter
             recentf-menu-filter
-            (mapcar 'recentf-make-default-menu-element
+            (mapcar #'recentf-make-default-menu-element
                     files)))))
 
 (defun recentf-open-files (&optional files buffer-name)
@@ -1231,7 +1224,7 @@ use for the dialog.  It defaults to 
\"*`recentf-menu-title'*\"."
                    (format-message "Click on Cancel or type `q' to cancel.\n"))
     ;; Use a L&F that looks like the recentf menu.
     (tree-widget-set-theme "folder")
-    (apply 'widget-create
+    (apply #'widget-create
            `(group
              :indent 2
              :format "\n%v\n"
@@ -1313,7 +1306,7 @@ empty `file-name-history' with the recent list."
       (load-file file)
       (and recentf-initialize-file-name-history
            (not file-name-history)
-           (setq file-name-history (mapcar 'abbreviate-file-name
+           (setq file-name-history (mapcar #'abbreviate-file-name
                                            recentf-list))))))
 
 (defun recentf-cleanup ()
@@ -1380,6 +1373,10 @@ buffers you switch to a lot, you can say something like 
the following:
   ;; continue standard unloading
   nil)
 
+;; Obsolete.
+
+(define-obsolete-function-alias 'recentf-trunc-list #'seq-take "28.1")
+
 (provide 'recentf)
 
 (run-hooks 'recentf-load-hook)
diff --git a/lisp/repeat.el b/lisp/repeat.el
index 84a613d..a2b04b8 100644
--- a/lisp/repeat.el
+++ b/lisp/repeat.el
@@ -180,7 +180,7 @@ this function is always whether the value of `this-command' 
would've been
   (= repeat-num-input-keys-at-repeat num-input-keys))
 
 ;; An example of the use of (repeat-is-really-this-command) may still be
-;; available in <http://www.eskimo.com/~seldon/dotemacs.el>; search for
+;; available in <https://www.eskimo.com/~seldon/dotemacs.el>; search for
 ;; "defun wm-switch-buffer".
 
 ;;;;; ******************* THE REPEAT COMMAND ITSELF ******************* ;;;;;
diff --git a/lisp/ruler-mode.el b/lisp/ruler-mode.el
index c9d3939..11226fd 100644
--- a/lisp/ruler-mode.el
+++ b/lisp/ruler-mode.el
@@ -1,4 +1,4 @@
-;;; ruler-mode.el --- display a ruler in the header line
+;;; ruler-mode.el --- display a ruler in the header line  -*- lexical-binding: 
t -*-
 
 ;; Copyright (C) 2001-2021 Free Software Foundation, Inc.
 
@@ -100,10 +100,7 @@
 ;; To automatically display the ruler in specific major modes use:
 ;;
 ;;    (add-hook '<major-mode>-hook 'ruler-mode)
-;;
 
-;;; History:
-;;
 
 ;;; Code:
 (eval-when-compile
@@ -122,7 +119,6 @@ Also allowing to visually change `tab-stop-list' setting 
using
 <C-down-mouse-1> and <C-down-mouse-3> on the ruler to respectively add
 or remove a tab stop.  \\[ruler-mode-toggle-show-tab-stops] or
 <C-down-mouse-2> on the ruler toggles showing/editing of tab stops."
-  :group 'ruler-mode
   :type 'boolean)
 
 ;; IMPORTANT: This function must be defined before the following
@@ -140,7 +136,6 @@ or remove a tab stop.  \\[ruler-mode-toggle-show-tab-stops] 
or
                                            ?\¶
                                          ?\|)
   "Character used at the `fill-column' location."
-  :group 'ruler-mode
   :type '(choice
           (character :tag "Character")
           (integer :tag "Integer char value"
@@ -148,7 +143,6 @@ or remove a tab stop.  \\[ruler-mode-toggle-show-tab-stops] 
or
 
 (defcustom ruler-mode-comment-column-char ?\#
   "Character used at the `comment-column' location."
-  :group 'ruler-mode
   :type '(choice
           (character :tag "Character")
           (integer :tag "Integer char value"
@@ -156,7 +150,6 @@ or remove a tab stop.  \\[ruler-mode-toggle-show-tab-stops] 
or
 
 (defcustom ruler-mode-goal-column-char ?G
   "Character used at the `goal-column' location."
-  :group 'ruler-mode
   :type '(choice
           (character :tag "Character")
           (integer :tag "Integer char value"
@@ -166,7 +159,6 @@ or remove a tab stop.  \\[ruler-mode-toggle-show-tab-stops] 
or
                                               ?\¦
                                             ?\@)
   "Character used at the `current-column' location."
-  :group 'ruler-mode
   :type '(choice
           (character :tag "Character")
           (integer :tag "Integer char value"
@@ -174,7 +166,6 @@ or remove a tab stop.  \\[ruler-mode-toggle-show-tab-stops] 
or
 
 (defcustom ruler-mode-tab-stop-char ?\T
   "Character used at `tab-stop-list' locations."
-  :group 'ruler-mode
   :type '(choice
           (character :tag "Character")
           (integer :tag "Integer char value"
@@ -182,7 +173,6 @@ or remove a tab stop.  \\[ruler-mode-toggle-show-tab-stops] 
or
 
 (defcustom ruler-mode-basic-graduation-char ?\.
   "Character used for basic graduations."
-  :group 'ruler-mode
   :type '(choice
           (character :tag "Character")
           (integer :tag "Integer char value"
@@ -190,7 +180,6 @@ or remove a tab stop.  \\[ruler-mode-toggle-show-tab-stops] 
or
 
 (defcustom ruler-mode-inter-graduation-char ?\!
   "Character used for intermediate graduations."
-  :group 'ruler-mode
   :type '(choice
           (character :tag "Character")
           (integer :tag "Integer char value"
@@ -198,7 +187,6 @@ or remove a tab stop.  \\[ruler-mode-toggle-show-tab-stops] 
or
 
 (defcustom ruler-mode-set-goal-column-ding-flag t
   "Non-nil means do `ding' when `goal-column' is set."
-  :group 'ruler-mode
   :type 'boolean)
 
 (defface ruler-mode-default
@@ -215,8 +203,7 @@ or remove a tab stop.  \\[ruler-mode-toggle-show-tab-stops] 
or
                             :line-width 1
                             :style released-button)
                )))
-  "Default face used by the ruler."
-  :group 'ruler-mode)
+  "Default face used by the ruler.")
 
 (defface ruler-mode-pad
   '((((type tty))
@@ -227,64 +214,56 @@ or remove a tab stop.  
\\[ruler-mode-toggle-show-tab-stops] or
      (:inherit ruler-mode-default
                :background "grey64"
                )))
-  "Face used to pad inactive ruler areas."
-  :group 'ruler-mode)
+  "Face used to pad inactive ruler areas.")
 
 (defface ruler-mode-margins
   '((t
      (:inherit ruler-mode-default
                :foreground "white"
                )))
-  "Face used to highlight margin areas."
-  :group 'ruler-mode)
+  "Face used to highlight margin areas.")
 
 (defface ruler-mode-fringes
   '((t
      (:inherit ruler-mode-default
                :foreground "green"
                )))
-  "Face used to highlight fringes areas."
-  :group 'ruler-mode)
+  "Face used to highlight fringes areas.")
 
 (defface ruler-mode-column-number
   '((t
      (:inherit ruler-mode-default
                :foreground "black"
                )))
-  "Face used to highlight number graduations."
-  :group 'ruler-mode)
+  "Face used to highlight number graduations.")
 
 (defface ruler-mode-fill-column
   '((t
      (:inherit ruler-mode-default
                :foreground "red"
                )))
-  "Face used to highlight the fill column character."
-  :group 'ruler-mode)
+  "Face used to highlight the fill column character.")
 
 (defface ruler-mode-comment-column
   '((t
      (:inherit ruler-mode-default
                :foreground "red"
                )))
-  "Face used to highlight the comment column character."
-  :group 'ruler-mode)
+  "Face used to highlight the comment column character.")
 
 (defface ruler-mode-goal-column
   '((t
      (:inherit ruler-mode-default
                :foreground "red"
                )))
-  "Face used to highlight the goal column character."
-  :group 'ruler-mode)
+  "Face used to highlight the goal column character.")
 
 (defface ruler-mode-tab-stop
   '((t
      (:inherit ruler-mode-default
                :foreground "steelblue"
                )))
-  "Face used to highlight tab stop characters."
-  :group 'ruler-mode)
+  "Face used to highlight tab stop characters.")
 
 (defface ruler-mode-current-column
   '((t
@@ -292,8 +271,7 @@ or remove a tab stop.  \\[ruler-mode-toggle-show-tab-stops] 
or
                :weight bold
                :foreground "yellow"
                )))
-  "Face used to highlight the `current-column' character."
-  :group 'ruler-mode)
+  "Face used to highlight the `current-column' character.")
 
 
 (defsubst ruler-mode-full-window-width ()
@@ -547,15 +525,15 @@ START-EVENT is the mouse click event."
     (define-key km [header-line (control down-mouse-2)]
       #'ruler-mode-toggle-show-tab-stops)
     (define-key km [header-line (shift mouse-1)]
-      'ignore)
+      #'ignore)
     (define-key km [header-line (shift mouse-3)]
-      'ignore)
+      #'ignore)
     (define-key km [header-line (control mouse-1)]
-      'ignore)
+      #'ignore)
     (define-key km [header-line (control mouse-3)]
-      'ignore)
+      #'ignore)
     (define-key km [header-line (control mouse-2)]
-      'ignore)
+      #'ignore)
     km)
   "Keymap for ruler minor mode.")
 
diff --git a/lisp/scroll-all.el b/lisp/scroll-all.el
index 25b245e..8ba0cc9 100644
--- a/lisp/scroll-all.el
+++ b/lisp/scroll-all.el
@@ -1,4 +1,4 @@
-;;; scroll-all.el --- scroll all buffers together minor mode
+;;; scroll-all.el --- scroll all buffers together minor mode  -*- 
lexical-binding: t -*-
 
 ;; Copyright (C) 1997, 2001-2021 Free Software Foundation, Inc.
 
@@ -47,38 +47,41 @@
        (condition-case nil
            (funcall func arg)
          ;; Ignore beginning- or end-of-buffer error in other windows.
-         (error nil)
-         )
+          (error nil))
        (other-window 1)
        (setq count (1+ count))))))
 
 (defun scroll-all-scroll-down-all (arg)
-  "Scroll down in all visible windows."
+  "Scroll down ARG lines in all visible windows."
   (interactive "p")
   (scroll-all-function-all 'next-line arg))
 
 (defun scroll-all-scroll-up-all (arg)
-  "Scroll up in all visible windows."
+  "Scroll up ARG lines in all visible windows."
   (interactive "p")
   (scroll-all-function-all 'previous-line arg))
 
 (defun scroll-all-page-down-all (arg)
-  "Page down in all visible windows."
+  "Page down in all visible windows.
+ARG is like in `scroll-up'."
   (interactive "P")
   (scroll-all-function-all 'scroll-up arg))
 
 (defun scroll-all-page-up-all (arg)
-  "Page up in all visible windows."
+  "Page up in all visible windows.
+ARG is like in `scroll-down'."
   (interactive "P")
   (scroll-all-function-all 'scroll-down arg))
 
 (defun scroll-all-beginning-of-buffer-all (arg)
-  "Go to the beginning of the buffer in all visible windows."
+  "Go to the beginning of the buffer in all visible windows.
+ARG is like in `beginning-of-buffer'."
   (interactive "P")
   (scroll-all-function-all 'beginning-of-buffer arg))
 
 (defun scroll-all-end-of-buffer-all (arg)
-  "Go to the end of the buffer in all visible windows."
+  "Go to the end of the buffer in all visible windows.
+ARG is like in `end-of-buffer'."
   (interactive "P")
   (scroll-all-function-all 'end-of-buffer arg))
 
diff --git a/lisp/ses.el b/lisp/ses.el
index a11c754..6058d48 100644
--- a/lisp/ses.el
+++ b/lisp/ses.el
@@ -2653,9 +2653,7 @@ canceled."
   (barf-if-buffer-read-only)
   (if (eq default t)
       (setq default "")
-    (setq prompt (format "%s (default %S): "
-                        (substring prompt 0 -2)
-                        default)))
+    (setq prompt (format-prompt prompt default)))
   (dolist (key ses-completion-keys)
     (define-key ses-mode-edit-map key 'ses-read-printer-complete-symbol))
   ;; make it globally visible, so that it can be visible from the minibuffer.
@@ -2702,7 +2700,7 @@ right-justified) or a list of one string (will be 
left-justified)."
                ;;Range contains differing printer functions
                (setq default t)
                (throw 'ses-read-cell-printer t))))))
-     (list (ses-read-printer (format "Cell %S printer: " ses--curcell)
+     (list (ses-read-printer (format "Cell %S printer" ses--curcell)
                             default))))
   (unless (eq newval t)
     (ses-begin-change)
@@ -2716,7 +2714,7 @@ See `ses-read-cell-printer' for input forms."
   (interactive
    (let ((col (cdr (ses-sym-rowcol ses--curcell))))
      (ses-check-curcell)
-     (list col (ses-read-printer (format "Column %s printer: "
+     (list col (ses-read-printer (format "Column %s printer"
                                         (ses-column-letter col))
                                 (ses-col-printer col)))))
 
@@ -2731,7 +2729,7 @@ See `ses-read-cell-printer' for input forms."
   "Set the default printer function for cells that have no other.
 See `ses-read-cell-printer' for input forms."
   (interactive
-   (list (ses-read-printer "Default printer: " ses--default-printer)))
+   (list (ses-read-printer "Default printer" ses--default-printer)))
   (unless (eq newval t)
     (ses-begin-change)
     (ses-set-parameter 'ses--default-printer newval)
@@ -3773,7 +3771,7 @@ function is redefined."
      (setq name (intern name))
      (let* ((cur-printer (gethash name ses--local-printer-hashmap))
             (default (and cur-printer (ses--locprn-def cur-printer))))
-            (setq def (ses-read-printer (format "Enter definition of printer 
%S: " name)
+            (setq def (ses-read-printer (format "Enter definition of printer 
%S" name)
                                         default)))
             (list name def)))
 
diff --git a/lisp/shadowfile.el b/lisp/shadowfile.el
index a4f0eba..a03965c 100644
--- a/lisp/shadowfile.el
+++ b/lisp/shadowfile.el
@@ -172,20 +172,6 @@ created by `shadow-define-regexp-group'.")
 ;;; Syntactic sugar; General list and string manipulation
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(defun shadow-union (a b)
-  "Add members of list A to list B if not equal to items already in B."
-  (if (null a)
-      b
-    (if (member (car a) b)
-       (shadow-union (cdr a) b)
-      (shadow-union (cdr a) (cons (car a) b)))))
-
-(defun shadow-find (func list)
-  "If FUNC applied to some element of LIST is non-nil, return first such 
element."
-  (while (and list (not (funcall func (car list))))
-    (setq list (cdr list)))
-  (car list))
-
 (defun shadow-regexp-superquote (string)
   "Like `regexp-quote', but includes the \\` and \\'.
 This makes sure regexp matches nothing but STRING."
@@ -226,7 +212,7 @@ information defining the cluster.  For interactive use, call
 
 (defun shadow-get-cluster (name)
   "Return cluster named NAME, or nil."
-  (shadow-find
+  (seq-find
    (lambda (x) (string-equal (shadow-cluster-name x) name))
    shadow-clusters))
 
@@ -252,7 +238,7 @@ information defining the cluster.  For interactive use, call
 (defun shadow-site-cluster (site)
   "Given a SITE, return cluster it is in, or nil."
   (or (shadow-get-cluster (shadow-site-name site))
-      (shadow-find
+      (seq-find
        (lambda (x)
          (string-match (shadow-cluster-regexp x) (shadow-name-site site)))
        shadow-clusters)))
@@ -653,7 +639,7 @@ Consider them as regular expressions if third arg REGEXP is 
true."
        shadows shadow-files-to-copy (with-output-to-string (backtrace))))
     (when shadows
       (setq shadow-files-to-copy
-           (shadow-union shadows shadow-files-to-copy))
+            (cl-union shadows shadow-files-to-copy :test #'equal))
       (when (not shadow-inhibit-message)
        (message "%s" (substitute-command-keys
                       "Use \\[shadow-copy-files] to update shadows."))
@@ -839,6 +825,17 @@ look for files that have been changed and need to be 
copied to other systems."
   ;; continue standard unloading
   nil)
 
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Obsolete
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun shadow-union (a b)
+  "Add members of list A to list B if not equal to items already in B."
+  (declare (obsolete cl-union "28.1"))
+  (cl-union a b :test #'equal))
+
+(define-obsolete-function-alias 'shadow-find #'seq-find "28.1")
+
 (provide 'shadowfile)
 
 ;;; shadowfile.el ends here
diff --git a/lisp/shell.el b/lisp/shell.el
index 53f5d0b..cd99b00 100644
--- a/lisp/shell.el
+++ b/lisp/shell.el
@@ -110,11 +110,6 @@
   "Directory support in shell mode."
   :group 'shell)
 
-;; Unused.
-;;; (defgroup shell-faces nil
-;;;   "Faces in shell buffers."
-;;;   :group 'shell)
-
 ;;;###autoload
 (defcustom shell-dumb-shell-regexp (purecopy "cmd\\(proxy\\)?\\.exe")
   "Regexp to match shells that don't save their command history, and
@@ -743,7 +738,7 @@ Make the shell buffer the current buffer, and return it.
                  (current-buffer)))
   ;; The buffer's window must be correctly set when we call comint
   ;; (so that comint sets the COLUMNS env var properly).
-  (pop-to-buffer buffer)
+  (pop-to-buffer-same-window buffer)
 
   (with-connection-local-variables
    ;; On remote hosts, the local `shell-file-name' might be useless.
diff --git a/lisp/simple.el b/lisp/simple.el
index b097f89..207b434 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -836,7 +836,10 @@ In programming language modes, this is the same as TAB.
 In some text modes, where TAB inserts a tab, this command indents to the
 column specified by the function `current-left-margin'.
 
-With ARG, perform this action that many times."
+With ARG, perform this action that many times.
+
+Also see `open-line' (bound to \\[open-line]) for a command that
+just inserts a newline without doing any indentation."
   (interactive "*p")
   (delete-horizontal-space t)
   (unless arg
@@ -2002,9 +2005,14 @@ This function uses the `read-extended-command-predicate' 
user option."
            (complete-with-action action obarray string pred)))
        (lambda (sym)
          (and (commandp sym)
-              (or (null read-extended-command-predicate)
-                  (and (functionp read-extended-command-predicate)
-                       (funcall read-extended-command-predicate sym buffer)))))
+              (cond ((null read-extended-command-predicate))
+                    ((functionp read-extended-command-predicate)
+                     ;; Don't let bugs break M-x completion; interpret
+                     ;; them as the absence of a predicate.
+                     (condition-case-unless-debug err
+                         (funcall read-extended-command-predicate sym buffer)
+                       (error (message "read-extended-command-predicate: %s: 
%s"
+                                       sym (error-message-string err))))))))
        t nil 'extended-command-history))))
 
 (defun command-completion-using-modes-p (symbol buffer)
diff --git a/lisp/strokes.el b/lisp/strokes.el
index 55f2ae8..4b682e9 100644
--- a/lisp/strokes.el
+++ b/lisp/strokes.el
@@ -1,4 +1,4 @@
-;;; strokes.el --- control Emacs through mouse strokes
+;;; strokes.el --- control Emacs through mouse strokes  -*- lexical-binding: 
t; -*-
 
 ;; Copyright (C) 1997, 2000-2021 Free Software Foundation, Inc.
 
@@ -216,14 +216,12 @@ static char * stroke_xpm[] = {
 
 (defcustom strokes-lighter " Strokes"
   "Mode line identifier for Strokes mode."
-  :type 'string
-  :group 'strokes)
+  :type 'string)
 
 (defcustom strokes-character ?@
   "Character used when drawing strokes in the strokes buffer.
 \(The default is `@', which works well.)"
-  :type 'character
-  :group 'strokes)
+  :type 'character)
 
 (defcustom strokes-minimum-match-score 1000
   "Minimum score for a stroke to be considered a possible match.
@@ -239,8 +237,7 @@ then you can set `strokes-minimum-match-score' to something 
that works
 for you.  The only purpose of this variable is to insure that if you
 do a bogus stroke that really doesn't match any of the predefined
 ones, then strokes should NOT pick the one that came closest."
-  :type 'integer
-  :group 'strokes)
+  :type 'integer)
 
 (defcustom strokes-grid-resolution 9
   "Integer defining dimensions of the stroke grid.
@@ -256,14 +253,12 @@ WARNING: Changing the value of this variable will gravely 
affect the
          figure out what it should be based on your needs and on how
          quick the particular platform(s) you're operating on, and
          only then start programming in your custom strokes."
-  :type 'integer
-  :group 'strokes)
+  :type 'integer)
 
 (defcustom strokes-file (locate-user-emacs-file "strokes" ".strokes")
   "File containing saved strokes for Strokes mode."
   :version "24.4"                       ; added locate-user-emacs-file
-  :type 'file
-  :group 'strokes)
+  :type 'file)
 
 (defvar strokes-buffer-name " *strokes*"
   "The name of the buffer that the strokes take place in.")
@@ -273,8 +268,7 @@ WARNING: Changing the value of this variable will gravely 
affect the
 If nil, strokes will be read the same, however the user will not be
 able to see the strokes.  This be helpful for people who don't like
 the delay in switching to the strokes buffer."
-  :type 'boolean
-  :group 'strokes)
+  :type 'boolean)
 
 ;;; internal variables...
 
@@ -1044,7 +1038,7 @@ o Strokes are a bit computer-dependent in that they 
depend somewhat on
     (help-mode)
     (help-print-return-message)))
 
-(define-obsolete-function-alias 'strokes-report-bug 'report-emacs-bug "24.1")
+(define-obsolete-function-alias 'strokes-report-bug #'report-emacs-bug "24.1")
 
 (defun strokes-window-configuration-changed-p ()
   "Non-nil if the `strokes-window-configuration' frame properties changed.
@@ -1379,8 +1373,8 @@ If STROKES-MAP is not given, `strokes-global-map' will be 
used instead."
 
 (defvar strokes-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map [(shift down-mouse-2)] 'strokes-do-stroke)
-    (define-key map [(meta down-mouse-2)] 'strokes-do-complex-stroke)
+    (define-key map [(shift down-mouse-2)] #'strokes-do-stroke)
+    (define-key map [(meta down-mouse-2)] #'strokes-do-complex-stroke)
     map))
 
 ;;;###autoload
@@ -1399,8 +1393,7 @@ Encode/decode your strokes with \\[strokes-encode-buffer],
 \\[strokes-decode-buffer].
 
 \\{strokes-mode-map}"
-  nil strokes-lighter strokes-mode-map
-  :group 'strokes :global t
+  nil strokes-lighter strokes-mode-map :global t
   (cond ((not (display-mouse-p))
         (error "Can't use Strokes without a mouse"))
        (strokes-mode                   ; turn on strokes
@@ -1408,15 +1401,15 @@ Encode/decode your strokes with 
\\[strokes-encode-buffer],
              (null strokes-global-map)
              (strokes-load-user-strokes))
         (add-hook 'kill-emacs-query-functions
-                  'strokes-prompt-user-save-strokes)
+                  #'strokes-prompt-user-save-strokes)
         (add-hook 'select-frame-hook
-                  'strokes-update-window-configuration)
+                  #'strokes-update-window-configuration)
         (strokes-update-window-configuration))
        (t                              ; turn off strokes
         (if (get-buffer strokes-buffer-name)
             (kill-buffer (get-buffer strokes-buffer-name)))
         (remove-hook 'select-frame-hook
-                     'strokes-update-window-configuration))))
+                     #'strokes-update-window-configuration))))
 
 
 ;;;; strokes-xpm stuff (later may be separate)...
@@ -1426,74 +1419,75 @@ Encode/decode your strokes with 
\\[strokes-encode-buffer],
 
 (defface strokes-char '((t (:background "lightgray")))
   "Face for strokes characters."
-  :version "21.1"
-  :group 'strokes)
+  :version "21.1")
 
 (put 'strokes 'char-table-extra-slots 0)
-(defconst strokes-char-table (make-char-table 'strokes) ;
+(defconst strokes-char-table
+  (let ((ct (make-char-table 'strokes))) ;
+    (aset ct ?0 0)
+    (aset ct ?1 1)
+    (aset ct ?2 2)
+    (aset ct ?3 3)
+    (aset ct ?4 4)
+    (aset ct ?5 5)
+    (aset ct ?6 6)
+    (aset ct ?7 7)
+    (aset ct ?8 8)
+    (aset ct ?9 9)
+    (aset ct ?a 10)
+    (aset ct ?b 11)
+    (aset ct ?c 12)
+    (aset ct ?d 13)
+    (aset ct ?e 14)
+    (aset ct ?f 15)
+    (aset ct ?g 16)
+    (aset ct ?h 17)
+    (aset ct ?i 18)
+    (aset ct ?j 19)
+    (aset ct ?k 20)
+    (aset ct ?l 21)
+    (aset ct ?m 22)
+    (aset ct ?n 23)
+    (aset ct ?o 24)
+    (aset ct ?p 25)
+    (aset ct ?q 26)
+    (aset ct ?r 27)
+    (aset ct ?s 28)
+    (aset ct ?t 29)
+    (aset ct ?u 30)
+    (aset ct ?v 31)
+    (aset ct ?w 32)
+    (aset ct ?x 33)
+    (aset ct ?y 34)
+    (aset ct ?z 35)
+    (aset ct ?A 36)
+    (aset ct ?B 37)
+    (aset ct ?C 38)
+    (aset ct ?D 39)
+    (aset ct ?E 40)
+    (aset ct ?F 41)
+    (aset ct ?G 42)
+    (aset ct ?H 43)
+    (aset ct ?I 44)
+    (aset ct ?J 45)
+    (aset ct ?K 46)
+    (aset ct ?L 47)
+    (aset ct ?M 48)
+    (aset ct ?N 49)
+    (aset ct ?O 50)
+    (aset ct ?P 51)
+    (aset ct ?Q 52)
+    (aset ct ?R 53)
+    (aset ct ?S 54)
+    (aset ct ?T 55)
+    (aset ct ?U 56)
+    (aset ct ?V 57)
+    (aset ct ?W 58)
+    (aset ct ?X 59)
+    (aset ct ?Y 60)
+    (aset ct ?Z 61)
+    ct)
   "The table which stores values for the character keys.")
-(aset strokes-char-table ?0 0)
-(aset strokes-char-table ?1 1)
-(aset strokes-char-table ?2 2)
-(aset strokes-char-table ?3 3)
-(aset strokes-char-table ?4 4)
-(aset strokes-char-table ?5 5)
-(aset strokes-char-table ?6 6)
-(aset strokes-char-table ?7 7)
-(aset strokes-char-table ?8 8)
-(aset strokes-char-table ?9 9)
-(aset strokes-char-table ?a 10)
-(aset strokes-char-table ?b 11)
-(aset strokes-char-table ?c 12)
-(aset strokes-char-table ?d 13)
-(aset strokes-char-table ?e 14)
-(aset strokes-char-table ?f 15)
-(aset strokes-char-table ?g 16)
-(aset strokes-char-table ?h 17)
-(aset strokes-char-table ?i 18)
-(aset strokes-char-table ?j 19)
-(aset strokes-char-table ?k 20)
-(aset strokes-char-table ?l 21)
-(aset strokes-char-table ?m 22)
-(aset strokes-char-table ?n 23)
-(aset strokes-char-table ?o 24)
-(aset strokes-char-table ?p 25)
-(aset strokes-char-table ?q 26)
-(aset strokes-char-table ?r 27)
-(aset strokes-char-table ?s 28)
-(aset strokes-char-table ?t 29)
-(aset strokes-char-table ?u 30)
-(aset strokes-char-table ?v 31)
-(aset strokes-char-table ?w 32)
-(aset strokes-char-table ?x 33)
-(aset strokes-char-table ?y 34)
-(aset strokes-char-table ?z 35)
-(aset strokes-char-table ?A 36)
-(aset strokes-char-table ?B 37)
-(aset strokes-char-table ?C 38)
-(aset strokes-char-table ?D 39)
-(aset strokes-char-table ?E 40)
-(aset strokes-char-table ?F 41)
-(aset strokes-char-table ?G 42)
-(aset strokes-char-table ?H 43)
-(aset strokes-char-table ?I 44)
-(aset strokes-char-table ?J 45)
-(aset strokes-char-table ?K 46)
-(aset strokes-char-table ?L 47)
-(aset strokes-char-table ?M 48)
-(aset strokes-char-table ?N 49)
-(aset strokes-char-table ?O 50)
-(aset strokes-char-table ?P 51)
-(aset strokes-char-table ?Q 52)
-(aset strokes-char-table ?R 53)
-(aset strokes-char-table ?S 54)
-(aset strokes-char-table ?T 55)
-(aset strokes-char-table ?U 56)
-(aset strokes-char-table ?V 57)
-(aset strokes-char-table ?W 58)
-(aset strokes-char-table ?X 59)
-(aset strokes-char-table ?Y 60)
-(aset strokes-char-table ?Z 61)
 
 (defconst strokes-base64-chars
   ;; I wanted to make this a vector of individual like (vector ?0
diff --git a/lisp/subr.el b/lisp/subr.el
index ef0e5e6..c2be26a 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -2806,9 +2806,9 @@ This function is used by the `interactive' code letter 
`n'."
     (when default1
       (setq prompt
            (if (string-match "\\(\\):[ \t]*\\'" prompt)
-               (replace-match (format " (default %s)" default1) t t prompt 1)
+               (replace-match (format minibuffer-default-prompt-format 
default1) t t prompt 1)
              (replace-regexp-in-string "[ \t]*\\'"
-                                       (format " (default %s) " default1)
+                                       (format 
minibuffer-default-prompt-format default1)
                                        prompt t t))))
     (while
        (progn
@@ -6200,6 +6200,28 @@ returned list are in the same order as in TREE.
 ;; for discoverability:
 (defalias 'flatten-list #'flatten-tree)
 
+(defun string-trim-left (string &optional regexp)
+  "Trim STRING of leading string matching REGEXP.
+
+REGEXP defaults to \"[ \\t\\n\\r]+\"."
+  (if (string-match (concat "\\`\\(?:" (or regexp "[ \t\n\r]+") "\\)") string)
+      (substring string (match-end 0))
+    string))
+
+(defun string-trim-right (string &optional regexp)
+  "Trim STRING of trailing string matching REGEXP.
+
+REGEXP defaults to  \"[ \\t\\n\\r]+\"."
+  (let ((i (string-match-p (concat "\\(?:" (or regexp "[ \t\n\r]+") "\\)\\'")
+                           string)))
+    (if i (substring string 0 i) string)))
+
+(defun string-trim (string &optional trim-left trim-right)
+  "Trim STRING of leading and trailing strings matching TRIM-LEFT and 
TRIM-RIGHT.
+
+TRIM-LEFT and TRIM-RIGHT default to \"[ \\t\\n\\r]+\"."
+  (string-trim-left (string-trim-right string trim-right) trim-left))
+
 ;; The initial anchoring is for better performance in searching matches.
 (defconst regexp-unmatchable "\\`a\\`"
   "Standard regexp guaranteed not to match any string at all.")
diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el
index 45ed2a6..2e27b29 100644
--- a/lisp/tab-bar.el
+++ b/lisp/tab-bar.el
@@ -345,7 +345,7 @@ before calling the command that adds a new tab."
   :group 'tab-bar
   :version "27.1")
 
-(defcustom tab-bar-new-tab-group nil
+(defcustom tab-bar-new-tab-group t
   "Defines what group to assign to a new tab.
 If nil, don't set a default group automatically.
 If t, inherit the group name from the previous tab.
@@ -522,7 +522,7 @@ Return its existing value or a new value."
             (setf (cdr current-tab-name)
                   (funcall tab-bar-tab-name-function))))
       ;; Create default tabs
-      (setq tabs (list (tab-bar--current-tab)))
+      (setq tabs (list (tab-bar--current-tab-make)))
       (tab-bar-tabs-set tabs frame))
     tabs))
 
@@ -795,7 +795,7 @@ on the tab bar instead."
 (push '(tabs . frameset-filter-tabs) frameset-filter-alist)
 
 (defun tab-bar--tab (&optional frame)
-  (let* ((tab (tab-bar--current-tab-find))
+  (let* ((tab (tab-bar--current-tab-find nil frame))
          (tab-explicit-name (alist-get 'explicit-name tab))
          (tab-group (alist-get 'group tab))
          (bl  (seq-filter #'buffer-live-p (frame-parameter frame 
'buffer-list)))
@@ -816,7 +816,10 @@ on the tab bar instead."
       (wc-history-back . ,(gethash (or frame (selected-frame)) 
tab-bar-history-back))
       (wc-history-forward . ,(gethash (or frame (selected-frame)) 
tab-bar-history-forward)))))
 
-(defun tab-bar--current-tab (&optional tab)
+(defun tab-bar--current-tab (&optional tab frame)
+  (tab-bar--current-tab-make (or tab (tab-bar--current-tab-find nil frame))))
+
+(defun tab-bar--current-tab-make (&optional tab)
   ;; `tab' here is an argument meaning "use tab as template".  This is
   ;; necessary when switching tabs, otherwise the destination tab
   ;; inherits the current tab's `explicit-name' parameter.
@@ -933,7 +936,7 @@ ARG counts from 1.  Negative ARG counts tabs from the end 
of the tab bar."
 
         (when from-index
           (setf (nth from-index tabs) from-tab))
-        (setf (nth to-index tabs) (tab-bar--current-tab (nth to-index tabs)))
+        (setf (nth to-index tabs) (tab-bar--current-tab-make (nth to-index 
tabs)))
 
         (unless tab-bar-mode
           (message "Selected tab '%s'" (alist-get 'name to-tab))))
@@ -1111,7 +1114,7 @@ After the tab is created, the hooks in
     (when from-index
       (setf (nth from-index tabs) from-tab))
 
-    (let* ((to-tab (tab-bar--current-tab
+    (let* ((to-tab (tab-bar--current-tab-make
                     (when (eq tab-bar-new-tab-group t)
                       `((group . ,(alist-get 'group from-tab))))))
            (to-index (and to-index (prefix-numeric-value to-index)))
@@ -1409,6 +1412,42 @@ function `tab-bar-tab-name-function'."
 
 ;;; Tab groups
 
+(defun tab-bar-move-tab-to-group (&optional tab)
+  "Relocate TAB (or the current tab) closer to its group."
+  (interactive)
+  (let* ((tabs (funcall tab-bar-tabs-function))
+         (tab (or tab (tab-bar--current-tab-find tabs)))
+         (tab-index (tab-bar--tab-index tab))
+         (group (alist-get 'group tab))
+         ;; Beginning position of the same group
+         (beg (seq-position tabs group
+                            (lambda (tb gr)
+                              (and (not (eq tb tab))
+                                   (equal (alist-get 'group tb) gr)))))
+         ;; Size of the same group
+         (len (when beg
+                (seq-position (nthcdr beg tabs) group
+                              (lambda (tb gr)
+                                (not (equal (alist-get 'group tb) gr))))))
+         (pos (when beg
+                (cond
+                 ;; Don't move tab when it's already inside group bounds
+                 ((and len (>= tab-index beg) (<= tab-index (+ beg len))) nil)
+                 ;; Move tab from the right to the group end
+                 ((and len (> tab-index (+ beg len))) (+ beg len 1))
+                 ;; Move tab from the left to the group beginning
+                 ((< tab-index beg) beg)))))
+    (when pos
+      (tab-bar-move-tab-to pos (1+ tab-index)))))
+
+(defcustom tab-bar-tab-post-change-group-functions nil
+  "List of functions to call after changing a tab group.
+The current tab is supplied as an argument."
+  :type 'hook
+  :options '(tab-bar-move-tab-to-group)
+  :group 'tab-bar
+  :version "28.1")
+
 (defun tab-bar-change-tab-group (group-name &optional arg)
   "Add the tab specified by its absolute position ARG to GROUP-NAME.
 If no ARG is specified, then set the GROUP-NAME for the current tab.
@@ -1442,6 +1481,8 @@ While using this command, you might also want to replace
         (setcdr group group-new-name)
       (nconc tab `((group . ,group-new-name))))
 
+    (run-hook-with-args 'tab-bar-tab-post-change-group-functions tab)
+
     (force-mode-line-update)
     (unless tab-bar-mode
       (message "Set tab group to '%s'" group-new-name))))
diff --git a/lisp/talk.el b/lisp/talk.el
index 473f8ac..56d36dd 100644
--- a/lisp/talk.el
+++ b/lisp/talk.el
@@ -1,4 +1,4 @@
-;;; talk.el --- allow several users to talk to each other through Emacs
+;;; talk.el --- allow several users to talk to each other through Emacs  -*- 
lexical-binding: t -*-
 
 ;; Copyright (C) 1995, 2001-2021 Free Software Foundation, Inc.
 
@@ -23,7 +23,7 @@
 ;;; Commentary:
 
 ;; This is a multi-user talk package that runs in Emacs.
-;; Use talk-connect to bring a new person into the conversation.
+;; Use `talk-connect' to bring a new person into the conversation.
 
 ;;; Code:
 
diff --git a/lisp/term.el b/lisp/term.el
index 6beb17f..d41895a 100644
--- a/lisp/term.el
+++ b/lisp/term.el
@@ -2535,7 +2535,7 @@ See `term-prompt-regexp'."
 ;; then the filename reader will only accept a file that exists.
 ;;
 ;; A typical use:
-;; (interactive (term-get-source "Compile file: " prev-lisp-dir/file
+;; (interactive (term-get-source "Compile file" prev-lisp-dir/file
 ;;                                 '(lisp-mode) t))
 
 ;; This is pretty stupid about strings.  It decides we're in a string
@@ -2566,9 +2566,7 @@ See `term-prompt-regexp'."
                       (car def)))
         (deffile (if sfile-p (file-name-nondirectory stringfile)
                       (cdr def)))
-        (ans (read-file-name (if deffile (format "%s(default %s) "
-                                                 prompt    deffile)
-                                 prompt)
+        (ans (read-file-name (format-prompt prompt deffile)
                              defdir
                              (concat defdir deffile)
                              mustmatch-p)))
diff --git a/lisp/term/w32-win.el b/lisp/term/w32-win.el
index e845193..687250f 100644
--- a/lisp/term/w32-win.el
+++ b/lisp/term/w32-win.el
@@ -555,6 +555,9 @@ be found in this alist.
 This alist is used by w32font.c when it looks for fonts that can display
 characters from scripts for which no USBs are defined.")
 
+(declare-function x-list-fonts "xfaces.c"
+                  (pattern &optional face frame maximum width))
+
 (defun w32-find-non-USB-fonts (&optional frame size)
   "Compute the value of `w32-non-USB-fonts' for specified SIZE and FRAME.
 FRAME defaults to the selected frame.
diff --git a/lisp/textmodes/artist.el b/lisp/textmodes/artist.el
index 3d08122..fbb9d21 100644
--- a/lisp/textmodes/artist.el
+++ b/lisp/textmodes/artist.el
@@ -6,7 +6,7 @@
 ;; Keywords:     mouse
 ;; Old-Version:         1.2.6
 ;; Release-date: 6-Aug-2004
-;; Location:     http://www.lysator.liu.se/~tab/artist/
+;; Location:     https://www.lysator.liu.se/~tab/artist/
 
 ;; Yoni Rabkin <yoni@rabkins.net> contacted the maintainer of this
 ;; file on 19/3/2008, and the maintainer agreed that when a bug is filed in
@@ -106,13 +106,6 @@
 ;; If you add a new drawing mode, send it to me, and I would gladly
 ;; include in the next release!
 
-;;; Installation:
-
-;; To use artist, put this in your .emacs:
-;;
-;;    (autoload 'artist-mode "artist" "Enter artist-mode" t)
-
-
 ;;; Requirements:
 
 ;; Artist requires the `rect' package (which comes with Emacs) to be
@@ -1760,13 +1753,6 @@ info-variant-part."
   "Call function FN with ARGS, if FN is not nil."
   `(if ,fn (funcall ,fn ,@args)))
 
-(defun artist-uniq (l)
-  "Remove consecutive duplicates in list L.  Comparison is done with `equal'."
-  (cond ((null l) nil)
-       ((null (cdr l)) l)              ; only one element in list
-       ((equal (car l) (car (cdr l))) (artist-uniq (cdr l))) ; first 2 equal
-       (t (cons (car l) (artist-uniq (cdr l)))))) ; first 2 are different
-
 (defun artist-string-split (str r)
   "Split string STR at occurrences of regexp R, returning a list of strings."
   (let ((res nil)
@@ -2768,7 +2754,7 @@ to append to the end of the list, when doing free-hand 
drawing)."
 Also, the `artist-key-poly-point-list' is reversed."
 
   (setq artist-key-poly-point-list
-       (artist-uniq artist-key-poly-point-list))
+        (seq-uniq artist-key-poly-point-list))
 
   (if (>= (length artist-key-poly-point-list) 2)
 
@@ -5379,10 +5365,7 @@ The event, EV, is the mouse event."
         (concat "Hello Tomas,\n\n"
                 "I have a nice bug report on Artist for you! Here it is:")))))
 
-
-;;
-;; Now provide this minor mode
-;;
+(define-obsolete-function-alias 'artist-uniq #'seq-uniq "28.1")
 
 (provide 'artist)
 
diff --git a/lisp/textmodes/bibtex-style.el b/lisp/textmodes/bibtex-style.el
index 8200334..6d01871 100644
--- a/lisp/textmodes/bibtex-style.el
+++ b/lisp/textmodes/bibtex-style.el
@@ -49,7 +49,7 @@
     "REVERSE" "SORT" "STRINGS"))
 
 (defconst bibtex-style-functions
-  ;; From http://www.eeng.dcu.ie/local-docs/btxdocs/btxhak/btxhak/node4.html.
+  ;; From https://www.eeng.dcu.ie/local-docs/btxdocs/btxhak/btxhak/node4.html.
   '("<" ">" "=" "+" "-" "*" ":="
     "add.period$" "call.type$" "change.case$" "chr.to.int$" "cite$"
     "duplicate$" "empty$" "format.name$" "if$" "int.to.chr$" "int.to.str$"
diff --git a/lisp/textmodes/bibtex.el b/lisp/textmodes/bibtex.el
index 301f701..f01c66b 100644
--- a/lisp/textmodes/bibtex.el
+++ b/lisp/textmodes/bibtex.el
@@ -1431,7 +1431,7 @@ If `bibtex-expand-strings' is non-nil, BibTeX strings are 
expanded
 for generating the URL.
 Set this variable before loading BibTeX mode.
 
-The following is a complex example, see URL `http://link.aps.org/'.
+The following is a complex example, see URL `https://link.aps.org/'.
 
    (((\"journal\" . \"\\\\=<\\(PR[ABCDEL]?\\|RMP\\)\\\\=>\")
      \"http://link.aps.org/abstract/%s/v%s/p%s\";
diff --git a/lisp/textmodes/css-mode.el b/lisp/textmodes/css-mode.el
index 622853d..47b0b51 100644
--- a/lisp/textmodes/css-mode.el
+++ b/lisp/textmodes/css-mode.el
@@ -427,7 +427,7 @@
      "paged-y" "paged-x-controls" "paged-y-controls" "fragments")
 
     ;; CSS Text Decoration Module Level 3
-    ;; (http://dev.w3.org/csswg/css-text-decor-3/#property-index)
+    ;; (https://dev.w3.org/csswg/css-text-decor-3/#property-index)
     ("text-decoration" text-decoration-line text-decoration-style
      text-decoration-color)
     ("text-decoration-color" color)
diff --git a/lisp/textmodes/fill.el b/lisp/textmodes/fill.el
index 81cd2f0..61514d6 100644
--- a/lisp/textmodes/fill.el
+++ b/lisp/textmodes/fill.el
@@ -412,12 +412,12 @@ and `fill-nobreak-invisible'."
   ;; Register `kinsoku' for scripts HAN, KANA, BOPOMOFO, and CJK-MISC.
   ;; Also tell that they don't use space between words.
   (map-char-table
-   #'(lambda (key val)
-       (when (memq val '(han kana bopomofo cjk-misc))
-        (set-char-table-range fill-find-break-point-function-table
-                              key 'kinsoku)
-        (set-char-table-range fill-nospace-between-words-table
-                              key t)))
+   (lambda (key val)
+     (when (memq val '(han kana bopomofo cjk-misc))
+       (set-char-table-range fill-find-break-point-function-table
+                             key 'kinsoku)
+       (set-char-table-range fill-nospace-between-words-table
+                             key t)))
    char-script-table)
   ;; Do the same thing also for full width characters and half
   ;; width kana variants.
@@ -703,7 +703,8 @@ space does not end a sentence, so don't break a line there."
     (or justify (setq justify (current-justification)))
 
     ;; Don't let Adaptive Fill mode alter the fill prefix permanently.
-    (let ((fill-prefix fill-prefix))
+    (let ((actual-fill-prefix fill-prefix)
+          (fill-prefix fill-prefix))
       ;; Figure out how this paragraph is indented, if desired.
       (when (and adaptive-fill-mode
                 (or (null fill-prefix) (string= fill-prefix "")))
@@ -717,7 +718,7 @@ space does not end a sentence, so don't break a line there."
       (goto-char from)
       (beginning-of-line)
 
-      (if (not justify)          ; filling disabled: just check indentation
+      (if (not justify)     ; filling disabled: just check indentation
          (progn
            (goto-char from)
            (while (< (point) to)
@@ -747,12 +748,14 @@ space does not end a sentence, so don't break a line 
there."
               linebeg)
          (while (< (point) to)
             ;; On the first line, there may be text in the fill prefix
-            ;; zone.  In that case, don't consider that area when
-            ;; trying to find a place to put a line break (bug#45720).
+            ;; zone (when `fill-prefix' is specified externally, and
+            ;; not computed).  In that case, don't consider that area
+            ;; when trying to find a place to put a line break
+            ;; (bug#45720).
             (if (not first)
                (setq linebeg (point))
               (setq first nil
-                    linebeg (+ (point) (length fill-prefix))))
+                    linebeg (+ (point) (length actual-fill-prefix))))
            (move-to-column (current-fill-column))
            (if (when (< (point) to)
                  ;; Find the position where we'll break the line.
diff --git a/lisp/textmodes/ispell.el b/lisp/textmodes/ispell.el
index cee578f..eb52113 100644
--- a/lisp/textmodes/ispell.el
+++ b/lisp/textmodes/ispell.el
@@ -1207,9 +1207,9 @@ If LANG is omitted, get the extra word characters for the 
default language."
          (split-string
           (ispell--call-enchant-lsmod "-list-dicts") " ([^)]+)\n" t))
          (found
-          (mapcar #'(lambda (lang)
-                      `(,lang "[[:alpha:]]" "[^[:alpha:]]"
-                              ,(ispell--get-extra-word-characters lang) t nil 
nil utf-8))
+          (mapcar (lambda (lang)
+                    `(,lang "[[:alpha:]]" "[^[:alpha:]]"
+                            ,(ispell--get-extra-word-characters lang) t nil 
nil utf-8))
                   dictionaries)))
     ;; Merge into FOUND any elements from the standard 
ispell-dictionary-base-alist
     ;; which have no element in FOUND at all.
diff --git a/lisp/textmodes/reftex-auc.el b/lisp/textmodes/reftex-auc.el
index 8429fce..977da70 100644
--- a/lisp/textmodes/reftex-auc.el
+++ b/lisp/textmodes/reftex-auc.el
@@ -32,11 +32,12 @@
                  (optional prompt default &optional complete))
 (declare-function TeX-argument-insert "ext:tex"
                  (name optional &optional prefix))
-(declare-function LaTeX-add-labels "ext:tex" (&rest entries) t)
-(declare-function LaTeX-add-index-entries "ext:tex" (&rest entries) t)
-(declare-function LaTeX-bibitem-list "ext:tex" () t)
-(declare-function LaTeX-index-entry-list "ext:tex" () t)
-(declare-function LaTeX-label-list "ext:tex" () t)
+(declare-function LaTeX-add-labels "ext:latex" (&rest labels) t)
+(declare-function LaTeX-add-index-entries "ext:latex" (&rest index-entries) t)
+(declare-function LaTeX-add-bibitems "ext:latex" (&rest bibitems) t)
+(declare-function LaTeX-bibitem-list "ext:latex" () t)
+(declare-function LaTeX-index-entry-list "ext:latex" () t)
+(declare-function LaTeX-label-list "ext:latex" () t)
 (declare-function multi-prompt "ext:multi-prompt"
                  (separator unique prompt table &optional
                             mp-predicate require-match initial history))
@@ -69,8 +70,6 @@ What is being used depends upon `reftex-plug-into-AUCTeX'."
         (LaTeX-add-labels label))
     (TeX-argument-insert label optional)))
 
-(declare-function LaTeX-add-bibitems "latex") ;FIXME: Can't find the definition
-
 ;;;###autoload
 (defun reftex-arg-cite (optional &optional prompt definition)
   "Use `reftex-citation' or AUCTeX's code to insert a cite-key macro argument.
@@ -88,7 +87,6 @@ What is being used depends upon `reftex-plug-into-AUCTeX'."
     (TeX-argument-insert (mapconcat #'identity items reftex-cite-key-separator)
                         optional)))
 
-
 ;;;###autoload
 (defun reftex-arg-index-tag (optional &optional prompt &rest _args)
   "Prompt for an index tag with completion.
diff --git a/lisp/textmodes/reftex-vars.el b/lisp/textmodes/reftex-vars.el
index a65772d..0d6bfb5 100644
--- a/lisp/textmodes/reftex-vars.el
+++ b/lisp/textmodes/reftex-vars.el
@@ -888,50 +888,46 @@ DOWNCASE    t:   Downcase words before using them."
                          (string :tag ""))
                 (option (boolean :tag "Downcase words          "))))
 
-(if (featurep 'xemacs)
-    ;; XEmacs 21.5 doesn't have explicitly numbered matching groups,
-    ;; so this list mustn't get any more items.
-    (defconst reftex-label-regexps '("\\\\label{\\([^}]*\\)}"))
-  (defcustom reftex-label-regexps
-    `(;; Normal \\label{foo} labels
-      "\\\\label{\\(?1:[^}]*\\)}"
-      ;; keyvals [..., label = {foo}, ...] forms used by ctable,
-      ;; listings, breqn, ...
-      ,(concat
-        ;; Make sure we search only for optional arguments of
-        ;; environments/macros and don't match any other [.  ctable
-        ;; provides a macro called \ctable, beamer/breqn/listings have
-        ;; environments.  Start with a backslash and a group for names
-        "\\\\\\(?:"
-        ;; begin, optional spaces and opening brace
-        "begin[[:space:]]*{"
-        ;; Build a regexp for env names
-        (regexp-opt '("lstlisting" "dmath" "dseries" "dgroup"
-                      "darray" "frame"))
-        ;; closing brace, optional spaces
-        "}[[:space:]]*"
-        ;; Now for macros
-        "\\|"
-        ;; Build a regexp for macro names; currently only \ctable
-        (regexp-opt '("ctable"))
-        ;; Close the group for names
-        "\\)"
-        ;; Match the opening [ and the following chars
-        "\\[[^][]*"
-        ;; Allow nested levels of chars enclosed in braces
-        "\\(?:{[^}{]*"
-        "\\(?:{[^}{]*"
-        "\\(?:{[^}{]*}[^}{]*\\)*"
-        "}[^}{]*\\)*"
-        "}[^][]*\\)*"
-        ;; Match the label key
-        "\\<label[[:space:]]*=[[:space:]]*"
-        ;; Match the label value; braces around the value are
-        ;; optional.
-        "{?\\(?1:[^] ,}\r\n\t%]+\\)"
-        ;; We are done.  Just search until the next closing bracket
-        "[^]]*\\]"))
-    "List of regexps matching \\label definitions.
+(defcustom reftex-label-regexps
+  `(;; Normal \\label{foo} labels
+    "\\\\label{\\(?1:[^}]*\\)}"
+    ;; keyvals [..., label = {foo}, ...] forms used by ctable,
+    ;; listings, breqn, ...
+    ,(concat
+      ;; Make sure we search only for optional arguments of
+      ;; environments/macros and don't match any other [.  ctable
+      ;; provides a macro called \ctable, beamer/breqn/listings have
+      ;; environments.  Start with a backslash and a group for names
+      "\\\\\\(?:"
+      ;; begin, optional spaces and opening brace
+      "begin[[:space:]]*{"
+      ;; Build a regexp for env names
+      (regexp-opt '("lstlisting" "dmath" "dseries" "dgroup"
+                    "darray" "frame"))
+      ;; closing brace, optional spaces
+      "}[[:space:]]*"
+      ;; Now for macros
+      "\\|"
+      ;; Build a regexp for macro names; currently only \ctable
+      (regexp-opt '("ctable"))
+      ;; Close the group for names
+      "\\)"
+      ;; Match the opening [ and the following chars
+      "\\[[^][]*"
+      ;; Allow nested levels of chars enclosed in braces
+      "\\(?:{[^}{]*"
+      "\\(?:{[^}{]*"
+      "\\(?:{[^}{]*}[^}{]*\\)*"
+      "}[^}{]*\\)*"
+      "}[^][]*\\)*"
+      ;; Match the label key
+      "\\<label[[:space:]]*=[[:space:]]*"
+      ;; Match the label value; braces around the value are
+      ;; optional.
+      "{?\\(?1:[^] ,}\r\n\t%]+\\)"
+      ;; We are done.  Just search until the next closing bracket
+      "[^]]*\\]"))
+  "List of regexps matching \\label definitions.
 The default value matches usual \\label{...} definitions and
 keyval style [..., label = {...}, ...] label definitions.  The
 regexp for keyval style explicitly looks for environments
@@ -946,13 +942,13 @@ you have to define it using \\(?1:...\\) when adding new 
regexps.
 When changed from Lisp, make sure to call
 `reftex-compile-variables' afterwards to make the change
 effective."
-    :version "28.1"
-    :set (lambda (symbol value)
-          (set symbol value)
-          (when (fboundp 'reftex-compile-variables)
-            (reftex-compile-variables)))
-    :group 'reftex-defining-label-environments
-    :type '(repeat (regexp :tag "Regular Expression"))))
+  :version "28.1"
+  :set (lambda (symbol value)
+        (set symbol value)
+        (when (fboundp 'reftex-compile-variables)
+          (reftex-compile-variables)))
+  :group 'reftex-defining-label-environments
+  :type '(repeat (regexp :tag "Regular Expression")))
 
 (defcustom reftex-label-ignored-macros-and-environments nil
   "List of macros and environments to be ignored when searching for labels.
diff --git a/lisp/textmodes/remember.el b/lisp/textmodes/remember.el
index b731c12..cd76bf8 100644
--- a/lisp/textmodes/remember.el
+++ b/lisp/textmodes/remember.el
@@ -176,14 +176,8 @@
 ;;
 ;;   2003.08.12 Sacha's birthday
 
-;;; History:
-
 ;;; Code:
 
-(defconst remember-version "2.0"
-  "This version of remember.")
-(make-obsolete-variable 'remember-version nil "28.1")
-
 (defgroup remember nil
   "A mode to remember information."
   :group 'data)
@@ -673,6 +667,11 @@ is non-nil, bury it and return nil; otherwise return t."
         nil)
     t))
 
+;; Obsolete
+
+(defconst remember-version "2.0" "This version of remember.")
+(make-obsolete-variable 'remember-version 'emacs-version "28.1")
+
 (provide 'remember)
 
 ;;; remember.el ends here
diff --git a/lisp/textmodes/rst.el b/lisp/textmodes/rst.el
index ce15637..56cca84 100644
--- a/lisp/textmodes/rst.el
+++ b/lisp/textmodes/rst.el
@@ -554,30 +554,30 @@ After interpretation of ARGS the results are concatenated 
as for
 `:seq'."
   (apply #'concat
         (mapcar
-         #'(lambda (re)
-             (cond
-              ((stringp re)
-               re)
-              ((symbolp re)
-               (cadr (assoc re rst-re-alist)))
-              ((characterp re)
-               (regexp-quote (char-to-string re)))
-              ((listp re)
-               (let ((nested
-                      (mapcar #'rst-re (cdr re))))
-                 (cond
-                  ((eq (car re) :seq)
-                   (mapconcat #'identity nested ""))
-                  ((eq (car re) :shy)
-                   (concat "\\(?:" (mapconcat #'identity nested "") "\\)"))
-                  ((eq (car re) :grp)
-                   (concat "\\(" (mapconcat #'identity nested "") "\\)"))
-                  ((eq (car re) :alt)
-                   (concat "\\(?:" (mapconcat #'identity nested "\\|") "\\)"))
-                  (t
-                   (error "Unknown list car: %s" (car re))))))
-              (t
-               (error "Unknown object type for building regex: %s" re))))
+          (lambda (re)
+            (cond
+             ((stringp re)
+              re)
+             ((symbolp re)
+              (cadr (assoc re rst-re-alist)))
+             ((characterp re)
+              (regexp-quote (char-to-string re)))
+             ((listp re)
+              (let ((nested
+                     (mapcar #'rst-re (cdr re))))
+                (cond
+                 ((eq (car re) :seq)
+                  (mapconcat #'identity nested ""))
+                 ((eq (car re) :shy)
+                  (concat "\\(?:" (mapconcat #'identity nested "") "\\)"))
+                 ((eq (car re) :grp)
+                  (concat "\\(" (mapconcat #'identity nested "") "\\)"))
+                 ((eq (car re) :alt)
+                  (concat "\\(?:" (mapconcat #'identity nested "\\|") "\\)"))
+                 (t
+                  (error "Unknown list car: %s" (car re))))))
+             (t
+              (error "Unknown object type for building regex: %s" re))))
          args)))
 
 ;; FIXME: Remove circular dependency between `rst-re' and `rst-re-alist'.
@@ -709,8 +709,8 @@ Return CHAR if so or signal an error otherwise."
   ;; testcover: ok.
   "Return position of SELF in ADOS or nil."
   (cl-check-type self rst-Ado)
-  (cl-position-if #'(lambda (e)
-                     (rst-Ado-equal self e))
+  (cl-position-if (lambda (e)
+                    (rst-Ado-equal self e))
                  ados))
 
 
@@ -814,8 +814,8 @@ Return ADO if so or signal an error otherwise."
   "Return sublist of HDRS whose car's adornment equals that of SELF or nil."
   (cl-check-type self rst-Hdr)
   (let ((ado (rst-Hdr-ado self)))
-    (cl-member-if #'(lambda (hdr)
-                     (rst-Ado-equal ado (rst-Hdr-ado hdr)))
+    (cl-member-if (lambda (hdr)
+                    (rst-Ado-equal ado (rst-Hdr-ado hdr)))
                  hdrs)))
 
 (defun rst-Hdr-ado-map (selves)
@@ -1277,8 +1277,8 @@ This inherits from Text mode.")
 
 ;; Abbrevs.
 (define-abbrev-table 'rst-mode-abbrev-table
-  (mapcar #'(lambda (x)
-             (append x '(nil 0 system)))
+  (mapcar (lambda (x)
+            (append x '(nil 0 system)))
           '(("contents" ".. contents::\n..\n   ")
             ("con" ".. contents::\n..\n   ")
             ("cont" "[...]")
@@ -1501,9 +1501,9 @@ file."
   :type `(repeat
          (group :tag "Adornment specification"
                 (choice :tag "Adornment character"
-                        ,@(mapcar #'(lambda (char)
-                                      (list 'const
-                                            :tag (char-to-string char) char))
+                         ,@(mapcar (lambda (char)
+                                     (list 'const
+                                           :tag (char-to-string char) char))
                                   rst-adornment-chars))
                 (radio :tag "Adornment type"
                        (const :tag "Overline and underline" over-and-under)
@@ -1540,8 +1540,8 @@ search starts after this entry.  Return nil if no new 
preferred
              ;; Start searching after the level of the previous adornment.
              (cdr (rst-Hdr-member-ado prev (rst-Hdr-preferred-adornments))))
          (rst-Hdr-preferred-adornments))))
-    (cl-find-if #'(lambda (cand)
-                   (not (rst-Hdr-member-ado cand seen)))
+    (cl-find-if (lambda (cand)
+                  (not (rst-Hdr-member-ado cand seen)))
                candidates)))
 
 (defun rst-update-section (hdr)
@@ -1620,55 +1620,55 @@ returned."
               (ttl-blw ; Title found below starting here.
                (rst-forward-line-looking-at
                 +1 'ttl-beg-1
-                #'(lambda (mtcd)
-                    (when mtcd
-                      (setq txt-blw (match-string-no-properties 1))
-                      (point)))))
+                 (lambda (mtcd)
+                   (when mtcd
+                     (setq txt-blw (match-string-no-properties 1))
+                     (point)))))
               txt-abv
               (ttl-abv ; Title found above starting here.
                (rst-forward-line-looking-at
                  -1 'ttl-beg-1
-                 #'(lambda (mtcd)
-                     (when mtcd
-                       (setq txt-abv (match-string-no-properties 1))
-                       (point)))))
+                  (lambda (mtcd)
+                    (when mtcd
+                      (setq txt-abv (match-string-no-properties 1))
+                      (point)))))
               (und-fnd ; Matching underline found starting here.
                (and ttl-blw
                     (rst-forward-line-looking-at
                      +2 (list ado-re 'lin-end)
-                     #'(lambda (mtcd)
-                         (when mtcd
-                           (point))))))
+                      (lambda (mtcd)
+                        (when mtcd
+                          (point))))))
               (ovr-fnd ; Matching overline found starting here.
                (and ttl-abv
                     (rst-forward-line-looking-at
                      -2 (list ado-re 'lin-end)
-                     #'(lambda (mtcd)
-                         (when mtcd
-                           (point))))))
+                      (lambda (mtcd)
+                        (when mtcd
+                          (point))))))
               (und-wng ; Wrong underline found starting here.
                (and ttl-blw
                     (not und-fnd)
                     (rst-forward-line-looking-at
                      +2 'ado-beg-2-1
-                     #'(lambda (mtcd)
-                         (when mtcd
-                           (point))))))
+                      (lambda (mtcd)
+                        (when mtcd
+                          (point))))))
               (ovr-wng ; Wrong overline found starting here.
                (and ttl-abv (not ovr-fnd)
                     (rst-forward-line-looking-at
                       -2 'ado-beg-2-1
-                      #'(lambda (mtcd)
-                          (when (and
-                                 mtcd
-                                 ;; An adornment above may be a legal
-                                 ;; adornment for the line above - consider it
-                                 ;; a wrong overline only when it is equally
-                                 ;; long.
-                                 (equal
-                                  (length (match-string-no-properties 1))
-                                  (length adornment)))
-                            (point)))))))
+                       (lambda (mtcd)
+                         (when (and
+                                mtcd
+                                ;; An adornment above may be a legal
+                                ;; adornment for the line above - consider it
+                                ;; a wrong overline only when it is equally
+                                ;; long.
+                                (equal
+                                 (length (match-string-no-properties 1))
+                                 (length adornment)))
+                           (point)))))))
          (cond
           ((and nxt-emp prv-emp)
            ;; A transition.
@@ -1708,11 +1708,11 @@ a section header or nil if no title line is found."
        (rst-forward-line-strict 0))
       (let* (cnd-beg ; Beginning of a title candidate.
             cnd-txt ; Text of a title candidate.
-            (cnd-fun #'(lambda (mtcd) ; Function setting title candidate data.
-                         (when mtcd
-                           (setq cnd-beg (match-beginning 0))
-                           (setq cnd-txt (match-string-no-properties 1))
-                           t)))
+             (cnd-fun (lambda (mtcd) ; Function setting title candidate data.
+                        (when mtcd
+                          (setq cnd-beg (match-beginning 0))
+                          (setq cnd-txt (match-string-no-properties 1))
+                          t)))
             ttl)
        (cond
         ((looking-at (rst-re 'ado-beg-2-1))
@@ -1728,10 +1728,10 @@ a section header or nil if no title line is found."
          ;; Title line found - check for a following underline.
          (setq ttl (rst-forward-line-looking-at
                     1 'ado-beg-2-1
-                    #'(lambda (mtcd)
-                        (when mtcd
-                          (rst-classify-adornment
-                           (match-string-no-properties 0) (match-end 0))))))
+                     (lambda (mtcd)
+                       (when mtcd
+                         (rst-classify-adornment
+                          (match-string-no-properties 0) (match-end 0))))))
          ;; Title candidate found if no valid adornment found.
          (funcall cnd-fun (not ttl))))
        (cond
@@ -1827,15 +1827,15 @@ given."
         (ignore-ttl
          (if ignore-position
              (cl-find-if
-              #'(lambda (ttl)
-                  (equal (rst-Ttl-contains ttl ignore-position) 0))
+               (lambda (ttl)
+                 (equal (rst-Ttl-contains ttl ignore-position) 0))
               all-ttls)))
         (really-ignore
          (if ignore-ttl
              (<= (cl-count-if
-                  #'(lambda (ttl)
-                      (rst-Ado-equal (rst-Ttl-ado ignore-ttl)
-                                     (rst-Ttl-ado ttl)))
+                   (lambda (ttl)
+                     (rst-Ado-equal (rst-Ttl-ado ignore-ttl)
+                                 (rst-Ttl-ado ttl)))
                   all-ttls)
                  1)))
         (real-ttls (delq (if really-ignore ignore-ttl) all-ttls)))
@@ -1859,14 +1859,14 @@ given."
 Return a list of (`rst-Ttl' . LEVEL) with ascending line number."
   (let ((hier (rst-Hdr-ado-map (rst-hdr-hierarchy))))
     (mapcar
-     #'(lambda (ttl)
-        (cons ttl (rst-Ado-position (rst-Ttl-ado ttl) hier)))
+     (lambda (ttl)
+       (cons ttl (rst-Ado-position (rst-Ttl-ado ttl) hier)))
      (rst-all-ttls))))
 
 (defun rst-get-previous-hdr ()
   "Return the `rst-Hdr' before point or nil if none."
-  (let ((prev (cl-find-if #'(lambda (ttl)
-                             (< (rst-Ttl-contains ttl (point)) 0))
+  (let ((prev (cl-find-if (lambda (ttl)
+                            (< (rst-Ttl-contains ttl (point)) 0))
                          (rst-all-ttls)
                          :from-end t)))
     (and prev (rst-Ttl-hdr prev))))
@@ -2169,19 +2169,19 @@ hierarchy is similar to that used by 
`rst-adjust-section'."
   (let* ((beg (region-beginning))
         (end (region-end))
         (ttls-reg (cl-remove-if-not
-                   #'(lambda (ttl)
-                       (and
-                        (>= (rst-Ttl-contains ttl beg) 0)
-                        (< (rst-Ttl-contains ttl end) 0)))
+                    (lambda (ttl)
+                      (and
+                       (>= (rst-Ttl-contains ttl beg) 0)
+                       (< (rst-Ttl-contains ttl end) 0)))
                    (rst-all-ttls))))
     (save-excursion
       ;; Apply modifications.
       (rst-destructuring-dolist
          ((marker &rest hdr
                   &aux (hier (rst-hdr-hierarchy)))
-          (mapcar #'(lambda (ttl)
-                      (cons (copy-marker (rst-Ttl-get-title-beginning ttl))
-                            (rst-Ttl-hdr ttl)))
+           (mapcar (lambda (ttl)
+                     (cons (copy-marker (rst-Ttl-get-title-beginning ttl))
+                           (rst-Ttl-hdr ttl)))
                   ttls-reg))
        (set-marker
         (goto-char marker) nil)
@@ -2391,9 +2391,9 @@ also arranged by `rst-insert-list-new-tag'."
   "List of favorite bullets."
   :group 'rst
   :type `(repeat
-         (choice ,@(mapcar #'(lambda (char)
-                               (list 'const
-                                     :tag (char-to-string char) char))
+          (choice ,@(mapcar (lambda (char)
+                              (list 'const
+                                    :tag (char-to-string char) char))
                            rst-bullets)))
   :package-version '(rst . "1.1.0"))
 
@@ -2517,13 +2517,13 @@ ordered by POINT."
                   (looking-at (rst-re rst-re-beg)) ; Start found
                   (not (rst-forward-line-looking-at
                         -1 'lin-end
-                        #'(lambda (mtcd) ; Previous line exists and is...
-                            (and
-                             (not mtcd) ; non-empty,
-                             (<= (current-indentation) clm) ; less indented
-                             (not (and (= (current-indentation) clm)
+                         (lambda (mtcd) ; Previous line exists and is...
+                           (and
+                            (not mtcd) ; non-empty,
+                            (<= (current-indentation) clm) ; less indented
+                            (not (and (= (current-indentation) clm)
                                        ; not a beg at same level.
-                                       (looking-at (rst-re rst-re-beg)))))))))
+                                      (looking-at (rst-re rst-re-beg)))))))))
              (back-to-indentation)
              (push (cons (point) clm) r)))
          (1value ; At least one line is moved in this loop.
@@ -2553,8 +2553,8 @@ modified."
          ((bullet _clm &rest pnts)
           ;; Zip preferred bullets and sorted columns associating a bullet
           ;; with a column and all the points this column is found.
-          (cl-mapcar #'(lambda (bullet clm2pnt)
-                         (cons bullet clm2pnt))
+           (cl-mapcar (lambda (bullet clm2pnt)
+                        (cons bullet clm2pnt))
                      rst-preferred-bullets
                      (sort clm2pnts #'car-less-than-car)))
        ;; Replace the bullets by the preferred ones.
@@ -2614,8 +2614,8 @@ section headers at all."
     (when (>= point (rst-Stn-get-title-beginning stn))
       ;; Point may be in this section or a child.
       (let ((in-child (cl-find-if
-                      #'(lambda (child)
-                          (>= point (rst-Stn-get-title-beginning child)))
+                       (lambda (child)
+                         (>= point (rst-Stn-get-title-beginning child)))
                       (rst-Stn-children stn)
                       :from-end t)))
        (if in-child
@@ -2829,18 +2829,18 @@ file-write hook to always make it up-to-date 
automatically."
            (and beg
                 (rst-forward-line-looking-at
                  1 'lin-end
-                 #'(lambda (mtcd)
-                     (unless mtcd
-                       (rst-apply-indented-blocks
-                        (point) (point-max) (current-indentation)
-                        #'(lambda (count _in-first _in-sub in-super in-empty
-                                         _relind)
-                            (cond
-                             ((or (> count 1) in-super))
-                             ((not in-empty)
-                              (setq fnd (line-end-position))
-                              nil)))))
-                     t)))
+                  (lambda (mtcd)
+                    (unless mtcd
+                      (rst-apply-indented-blocks
+                       (point) (point-max) (current-indentation)
+                       (lambda (count _in-first _in-sub in-super in-empty
+                                 _relind)
+                         (cond
+                          ((or (> count 1) in-super))
+                          ((not in-empty)
+                           (setq fnd (line-end-position))
+                           nil)))))
+                    t)))
          (when fnd
            (delete-region beg fnd))
          (goto-char beg)
@@ -3024,14 +3024,14 @@ direction."
         (contained nil) ; Title contains point (or is after point otherwise).
          (found (or (cl-position-if
                     ;; Find a title containing or after point.
-                    #'(lambda (ttl)
-                        (let ((cmp (rst-Ttl-contains ttl pnt)))
-                          (cond
-                           ((= cmp 0) ; Title contains point.
-                            (setq contained t)
-                            t)
-                           ((> cmp 0) ; Title after point.
-                            t))))
+                     (lambda (ttl)
+                       (let ((cmp (rst-Ttl-contains ttl pnt)))
+                         (cond
+                          ((= cmp 0) ; Title contains point.
+                           (setq contained t)
+                           t)
+                          ((> cmp 0) ; Title after point.
+                           t))))
                     ttls)
                    ;; Point after all titles.
                    count))
@@ -3290,8 +3290,8 @@ remove all indentation (CNT = 0).  A tab is taken from 
the text
 above.  If no suitable tab is found `rst-indent-width' is used."
   (interactive "r\np")
   (let ((tabs (sort (rst-compute-tabs beg)
-                   #'(lambda (x y)
-                       (<= x y))))
+                    (lambda (x y)
+                      (<= x y))))
        (leftmostcol (rst-find-leftmost-column beg end)))
     (when (or (> leftmostcol 0) (> cnt 0))
       ;; Apply the indent.
@@ -3306,8 +3306,8 @@ above.  If no suitable tab is found `rst-indent-width' is 
used."
                (dir (cl-signum cnt)) ; Direction to take.
                (abs (abs cnt)) ; Absolute number of steps to take.
                ;; Get the position of the first tab beyond leftmostcol.
-               (fnd (cl-position-if #'(lambda (elt)
-                                        (funcall cmp elt leftmostcol))
+                (fnd (cl-position-if (lambda (elt)
+                                       (funcall cmp elt leftmostcol))
                                       tabs))
                ;; Virtual position of tab.
                (pos (+ (or fnd len) (1- abs)))
@@ -3492,20 +3492,20 @@ do all lines instead of just paragraphs."
        (indent ""))
     (rst-apply-indented-blocks
      beg end (rst-find-leftmost-column beg end)
-     #'(lambda (count in-first in-sub in-super in-empty _relind)
-        (cond
-         (in-empty)
-         (in-super)
-         ((zerop count))
-         (in-sub
-          (insert indent))
-         ((or in-first all)
-          (let ((tag (format "%d. " (cl-incf enum))))
-            (setq indent (make-string (length tag) ? ))
-            (insert tag)))
-         (t
-          (insert indent)))
-        nil))))
+     (lambda (count in-first in-sub in-super in-empty _relind)
+       (cond
+        (in-empty)
+        (in-super)
+        ((zerop count))
+        (in-sub
+         (insert indent))
+        ((or in-first all)
+         (let ((tag (format "%d. " (cl-incf enum))))
+           (setq indent (make-string (length tag) ? ))
+           (insert tag)))
+        (t
+         (insert indent)))
+       nil))))
 
 ;; FIXME: Does not deal with deeper indentation - although
 ;;        `rst-apply-indented-blocks' could.
@@ -3520,18 +3520,18 @@ do all lines instead of just paragraphs."
         (indent (make-string (length bul) ? )))
     (rst-apply-indented-blocks
      beg end (rst-find-leftmost-column beg end)
-     #'(lambda (count in-first in-sub in-super in-empty _relind)
-        (cond
-         (in-empty)
-         (in-super)
-         ((zerop count))
-         (in-sub
-          (insert indent))
-         ((or in-first all)
-          (insert bul))
-         (t
-          (insert indent)))
-        nil))))
+     (lambda (count in-first in-sub in-super in-empty _relind)
+       (cond
+        (in-empty)
+        (in-super)
+        ((zerop count))
+        (in-sub
+         (insert indent))
+        ((or in-first all)
+         (insert bul))
+        (t
+         (insert indent)))
+       nil))))
 
 ;; FIXME: Does not deal with a varying number of digits appropriately.
 ;; FIXME: Does not deal with multiple levels independently.
@@ -3561,11 +3561,11 @@ Region is from BEG to END.  With WITH-EMPTY prefix 
empty lines too."
   (let ((ind (rst-find-leftmost-column beg end)))
     (rst-apply-indented-blocks
      beg end ind
-     #'(lambda (_count _in-first _in-sub in-super in-empty _relind)
-        (when (and (not in-super) (or with-empty (not in-empty)))
-          (move-to-column ind t)
-          (insert "| "))
-        nil))))
+     (lambda (_count _in-first _in-sub in-super in-empty _relind)
+       (when (and (not in-super) (or with-empty (not in-empty)))
+         (move-to-column ind t)
+         (insert "| "))
+       nil))))
 
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -4085,16 +4085,16 @@ end of the buffer) return nil and do not move point."
     (setq fnd (rst-apply-indented-blocks
               (line-beginning-position 2) ; Skip the current line
               (or limit (point-max)) (or column (current-column))
-              #'(lambda (_count _in-first _in-sub in-super in-empty _relind)
-                  (cond
-                   (in-empty
-                    (setq candidate (or candidate (line-beginning-position)))
-                    nil)
-                   (in-super
-                    (or candidate (line-beginning-position)))
-                   (t ; Non-empty, same or more indented line.
-                    (setq candidate nil)
-                    nil)))))
+               (lambda (_count _in-first _in-sub in-super in-empty _relind)
+                 (cond
+                  (in-empty
+                   (setq candidate (or candidate (line-beginning-position)))
+                   nil)
+                  (in-super
+                   (or candidate (line-beginning-position)))
+                  (t ; Non-empty, same or more indented line.
+                   (setq candidate nil)
+                   nil)))))
     (when fnd
       (goto-char fnd))))
 
diff --git a/lisp/textmodes/sgml-mode.el b/lisp/textmodes/sgml-mode.el
index 7de5317..6958ab8 100644
--- a/lisp/textmodes/sgml-mode.el
+++ b/lisp/textmodes/sgml-mode.el
@@ -2368,7 +2368,7 @@ or Edit/Text Properties/Face commands.
 Pages can have <a name=\"SOMENAME\">named points</a> and can link other points
 to them with <a href=\"#SOMENAME\">see also somename</a>.  In the same way <a
 href=\"URL\">see also URL</a> where URL is a filename relative to current
-directory, or absolute as in `http://www.cs.indiana.edu/elisp/w3/docs.html'.
+directory, or absolute as in `https://www.cs.indiana.edu/elisp/w3/docs.html'.
 
 Images in many formats can be inlined with <img src=\"URL\">.
 
diff --git a/lisp/textmodes/table.el b/lisp/textmodes/table.el
index a9f066c..13b4a6d 100644
--- a/lisp/textmodes/table.el
+++ b/lisp/textmodes/table.el
@@ -2911,11 +2911,11 @@ HTML:
         URL `https://www.w3.org'
 
 LaTeX:
-        URL `http://www.maths.tcd.ie/~dwilkins/LaTeXPrimer/Tables.html'
+        URL `https://www.maths.tcd.ie/~dwilkins/LaTeXPrimer/Tables.html'
 
 CALS (DocBook DTD):
-        URL `http://www.oasis-open.org/html/a502.htm'
-        URL 
`http://www.oreilly.com/catalog/docbook/chapter/book/table.html#AEN114751'
+        URL `https://www.oasis-open.org/html/a502.htm'
+        URL 
`https://www.oreilly.com/catalog/docbook/chapter/book/table.html#AEN114751'
 "
   (interactive
    (let* ((_ (unless (table--probe-cell) (error "Table not found here")))
diff --git a/lisp/thumbs.el b/lisp/thumbs.el
index e43d13d..5710b8c 100644
--- a/lisp/thumbs.el
+++ b/lisp/thumbs.el
@@ -51,9 +51,6 @@
 ;; In thumbs-mode, pressing <return> on an image will bring you in image view
 ;; mode for that image.  C-h m will give you a list of available keybinding.
 
-;;; History:
-;;
-
 ;;; Code:
 
 (require 'dired)
@@ -93,11 +90,12 @@ When it reaches that size (in bytes), a warning is sent."
 ;; customize this value to the absolute filename.
 (defcustom thumbs-conversion-program
   (if (eq system-type 'windows-nt)
+      ;; FIXME is this necessary, or can a sane PATHEXE be assumed?
+      ;; Eg find-program does not do this.
       "convert.exe"
-    (or (executable-find "convert")
-        "/usr/bin/convert"))
+    "convert")
   "Name of conversion program for thumbnails generation.
-It must be \"convert\"."
+This must be the ImageMagick \"convert\" utility."
   :type 'string
   :version "28.1")
 
diff --git a/lisp/time.el b/lisp/time.el
index 1403c4a..7e1d918 100644
--- a/lisp/time.el
+++ b/lisp/time.el
@@ -614,13 +614,14 @@ point."
         str))))
 
 ;;;###autoload
-(defun emacs-init-time ()
-  "Return a string giving the duration of the Emacs initialization."
+(defun emacs-init-time (&optional format)
+  "Return a string giving the duration of the Emacs initialization.
+FORMAT is a string to format the result, using `format'. If nil,
+the default format \"%f seconds\" is used."
   (interactive)
-  (let ((str
-        (format "%s seconds"
-                (float-time
-                 (time-subtract after-init-time before-init-time)))))
+  (let ((str (format (or format "%f seconds")
+                     (float-time (time-subtract after-init-time
+                                                before-init-time)))))
     (if (called-interactively-p 'interactive)
         (message "%s" str)
       str)))
diff --git a/lisp/tree-widget.el b/lisp/tree-widget.el
index 44b29bf..d40a628 100644
--- a/lisp/tree-widget.el
+++ b/lisp/tree-widget.el
@@ -110,10 +110,8 @@
 ;; `tree-widget-themes-directory', and `tree-widget-theme' options for
 ;; more details.
 
-;;; History:
-;;
-
 ;;; Code:
+
 (require 'wid-edit)
 
 ;;; Customization
diff --git a/lisp/url/ChangeLog.1 b/lisp/url/ChangeLog.1
index 5a3bf3a..cdd37a6 100644
--- a/lisp/url/ChangeLog.1
+++ b/lisp/url/ChangeLog.1
@@ -2337,7 +2337,7 @@
        recurse when retrieving the property lists.  Returns an assoc
        list keyed off of the resource, the cdr of which is a property list.
        (url-dav-datatype-attribute): We support the XML-Data note
-       (http://www.w3.org/TR/1998/NOTE-XML-data) to figure out what the
+       (https://www.w3.org/TR/1998/NOTE-XML-data) to figure out what the
        datatypes of attributes are.  Currently only date, dateTime, int,
        number, float, boolean, and uri are supported.
 
diff --git a/lisp/url/url-cookie.el b/lisp/url/url-cookie.el
index 085159c..60388df 100644
--- a/lisp/url/url-cookie.el
+++ b/lisp/url/url-cookie.el
@@ -60,7 +60,7 @@
 
 (defcustom url-cookie-multiple-line nil
   "If nil, HTTP requests put all cookies for the server on one line.
-Some web servers, such as http://www.hotmail.com/, only accept cookies
+Some web servers, such as https://www.hotmail.com/, only accept cookies
 when they are on one line.  This is broken behavior, but just try
 telling Microsoft that."
   :type 'boolean
@@ -358,10 +358,10 @@ i.e. 1970-1-1) are loaded as expiring one year from now 
instead."
 Default is 1 hour.  Note that if you change this variable outside of
 the `customize' interface after `url-do-setup' has been run, you need
 to run the `url-cookie-setup-save-timer' function manually."
-  :set #'(lambda (var val)
-          (set-default var val)
-          (if (bound-and-true-p url-setup-done)
-              (url-cookie-setup-save-timer)))
+  :set (lambda (var val)
+         (set-default var val)
+         (if (bound-and-true-p url-setup-done)
+             (url-cookie-setup-save-timer)))
   :type 'integer
   :group 'url-cookie)
 
diff --git a/lisp/url/url-dav.el b/lisp/url/url-dav.el
index edb1c1d..192b1ac 100644
--- a/lisp/url/url-dav.el
+++ b/lisp/url/url-dav.el
@@ -43,22 +43,11 @@
 (defvar url-http-response-status)
 (defvar url-http-end-of-headers)
 
-(defun url-intersection (l1 l2)
-  "Return a list of the elements occurring in both of the lists L1 and L2."
-  (if (null l2)
-      l2
-    (let (result)
-      (while l1
-       (if (member (car l1) l2)
-           (setq result (cons (pop l1) result))
-         (pop l1)))
-      (nreverse result))))
-
 ;;;###autoload
 (defun url-dav-supported-p (url)
   "Return WebDAV protocol version supported by URL.
 Returns nil if WebDAV is not supported."
-  (url-intersection url-dav-supported-protocols
+  (seq-intersection url-dav-supported-protocols
                    (plist-get (url-http-options url) 'dav)))
 
 (defun url-dav-node-text (node)
@@ -910,7 +899,9 @@ Returns nil if URL contains no name starting with FILE."
        t)))
 
 
-;;; Miscellaneous stuff.
+;;; Obsolete.
+
+(define-obsolete-function-alias 'url-intersection #'seq-intersection "28.1")
 
 (provide 'url-dav)
 
diff --git a/lisp/url/url-history.el b/lisp/url/url-history.el
index 10238a4..5dd1f09 100644
--- a/lisp/url/url-history.el
+++ b/lisp/url/url-history.el
@@ -38,10 +38,10 @@
 If non-nil, the URL package will keep track of all the URLs visited.
 If set to t, then the list is saved to disk at the end of each Emacs
 session."
-  :set #'(lambda (var val)
-          (set-default var val)
-          (and (bound-and-true-p url-setup-done)
-               (url-history-setup-save-timer)))
+  :set (lambda (var val)
+         (set-default var val)
+         (and (bound-and-true-p url-setup-done)
+              (url-history-setup-save-timer)))
   :type '(choice (const :tag "off" nil)
                 (const :tag "on" t)
                 (other :tag "within session" session))
@@ -59,10 +59,10 @@ is parsed at startup and used to provide URL completion."
 Default is 1 hour.  Note that if you change this variable outside of
 the `customize' interface after `url-do-setup' has been run, you need
 to run the `url-history-setup-save-timer' function manually."
-  :set #'(lambda (var val)
-          (set-default var val)
-          (if (bound-and-true-p url-setup-done)
-              (url-history-setup-save-timer)))
+  :set (lambda (var val)
+         (set-default var val)
+         (if (bound-and-true-p url-setup-done)
+             (url-history-setup-save-timer)))
   :type 'integer
   :group 'url-history)
 
diff --git a/lisp/url/url-mailto.el b/lisp/url/url-mailto.el
index 72884c0..c6901d9 100644
--- a/lisp/url/url-mailto.el
+++ b/lisp/url/url-mailto.el
@@ -104,8 +104,8 @@
            (or (search-forward (concat "\n" mail-header-separator "\n") nil t)
                (goto-char (point-max)))
            (insert (mapconcat
-                    #'(lambda (string)
-                        (replace-regexp-in-string "\r\n" "\n" string))
+                     (lambda (string)
+                       (replace-regexp-in-string "\r\n" "\n" string))
                     (cdar args) "\n")))
        (url-mail-goto-field (caar args))
        ;; (setq func (intern-soft (concat "mail-" (caar args))))
diff --git a/lisp/url/url-news.el b/lisp/url/url-news.el
index 585a282..49cc587 100644
--- a/lisp/url/url-news.el
+++ b/lisp/url/url-news.el
@@ -27,11 +27,6 @@
 (require 'nntp)
 (autoload 'gnus-group-read-ephemeral-group "gnus-group")
 
-;; Unused.
-;;; (defgroup url-news nil
-;;;   "News related options."
-;;;   :group 'url)
-
 (defun url-news-open-host (host port user pass)
   (if (fboundp 'nnheader-init-server-buffer)
       (nnheader-init-server-buffer))
diff --git a/lisp/url/url-vars.el b/lisp/url/url-vars.el
index 8c836f8..2aa2e79 100644
--- a/lisp/url/url-vars.el
+++ b/lisp/url/url-vars.el
@@ -22,10 +22,6 @@
 
 ;;; Code:
 
-(defconst url-version "Emacs"
-  "Version number of URL package.")
-(make-obsolete-variable 'url-version nil "28.1")
-
 (defgroup url nil
   "Uniform Resource Locator tool."
   :version "22.1"
@@ -427,6 +423,11 @@ Should be one of:
 This should be set, e.g. by mail user agents rendering HTML to avoid
 `bugs' which call home.")
 
+;; Obsolete
+
+(defconst url-version "Emacs" "Version number of URL package.")
+(make-obsolete-variable 'url-version 'emacs-version "28.1")
+
 (provide 'url-vars)
 
 ;;; url-vars.el ends here
diff --git a/lisp/userlock.el b/lisp/userlock.el
index 57311ac..4a75815 100644
--- a/lisp/userlock.el
+++ b/lisp/userlock.el
@@ -224,4 +224,14 @@ to get the latest version of the file, then make the 
change again."
           revert-buffer-binding))
         (help-mode)))))
 
+;;;###autoload
+(defun userlock--handle-unlock-error (error)
+  "Report an ERROR that occurred while unlocking a file."
+  (display-warning
+   '(unlock-file)
+   ;; There is no need to explain that this is an unlock error because
+   ;; ERR is a `file-error' condition, which explains this.
+   (message "%s, ignored" (error-message-string error))
+   :warning))
+
 ;;; userlock.el ends here
diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el
index 342b4cc..2c72c45 100644
--- a/lisp/vc/diff-mode.el
+++ b/lisp/vc/diff-mode.el
@@ -2826,7 +2826,7 @@ hunk text is not found in the source file."
 
 ;;; Support for converting a diff to diff3 markers via `wiggle'.
 
-;; Wiggle can be found at http://neil.brown.name/wiggle/ or in your nearest
+;; Wiggle can be found at https://neil.brown.name/wiggle/ or in your nearest
 ;; Debian repository.
 
 (defun diff-wiggle ()
diff --git a/lisp/vc/ediff-mult.el b/lisp/vc/ediff-mult.el
index 49b2890..8e88b60 100644
--- a/lisp/vc/ediff-mult.el
+++ b/lisp/vc/ediff-mult.el
@@ -620,7 +620,7 @@ behavior."
        (setq common (ediff-intersection common lis3 #'string=)))
 
     ;; copying is needed because sort sorts via side effects
-    (setq common (sort (ediff-copy-list common) 'string-lessp))
+    (setq common (sort (copy-sequence common) #'string-lessp))
 
     ;; compute difference list
     (setq difflist (ediff-set-difference
@@ -631,7 +631,7 @@ behavior."
                    #'string=)
          difflist (delete "."  difflist)
          ;; copying is needed because sort sorts via side effects
-         difflist (sort (ediff-copy-list (delete ".." difflist))
+          difflist (sort (copy-sequence (delete ".." difflist))
                         #'string-lessp))
 
     (setq difflist (mapcar (lambda (elt) (cons elt 1)) difflist))
@@ -729,7 +729,7 @@ behavior."
          )
 
     ;; copying is needed because sort sorts via side effects
-    (setq common (sort (ediff-copy-list common) 'string-lessp))
+    (setq common (sort (copy-sequence common) #'string-lessp))
 
     ;; return result
     (cons
diff --git a/lisp/vc/ediff-util.el b/lisp/vc/ediff-util.el
index fc6dcf6..1c78490 100644
--- a/lisp/vc/ediff-util.el
+++ b/lisp/vc/ediff-util.el
@@ -4188,12 +4188,7 @@ Mail anyway? (y or n) ")
     (cdr result)))
 
 (define-obsolete-function-alias 'ediff-add-to-history #'add-to-history "27.1")
-
-(defalias 'ediff-copy-list 'copy-sequence)
-
-
-;; don't report error if version control package wasn't found
-;;(ediff-load-version-control 'silent)
+(define-obsolete-function-alias 'ediff-copy-list #'copy-sequence "28.1")
 
 (run-hooks 'ediff-load-hook)
 
diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el
index 465ed87..e37c09d 100644
--- a/lisp/vc/vc-git.el
+++ b/lisp/vc/vc-git.el
@@ -27,14 +27,6 @@
 ;; system.
 ;;
 
-;;; Installation:
-
-;; To install: put this file on the load-path and add Git to the list
-;; of supported backends in `vc-handled-backends'; the following line,
-;; placed in your init file, will accomplish this:
-;;
-;;     (add-to-list 'vc-handled-backends 'Git)
-
 ;;; Todo:
 ;;  - check if more functions could use vc-git-command instead
 ;;     of start-process.
@@ -252,7 +244,7 @@ included in the completions."
                ;; Do not use the `file-name-directory' here: git-ls-files
                ;; sometimes fails to return the correct status for relative
                ;; path specs.
-               ;; See also: http://marc.info/?l=git&m=125787684318129&w=2
+               ;; See also: https://marc.info/?l=git&m=125787684318129&w=2
                (name (file-relative-name file dir))
                (str (with-demoted-errors "Error: %S"
                       (cd dir)
diff --git a/lisp/vc/vc-hg.el b/lisp/vc/vc-hg.el
index 9faed10..a054a7c 100644
--- a/lisp/vc/vc-hg.el
+++ b/lisp/vc/vc-hg.el
@@ -30,8 +30,6 @@
 
 ;;; Bugs:
 
-;;; Installation:
-
 ;;; Todo:
 
 ;; 1) Implement the rest of the vc interface. See the comment at the
@@ -97,9 +95,6 @@
 ;; without even using `hg' (this way even if you don't have `hg' installed,
 ;; Emacs is able to tell you this file is under mercurial's control).
 
-;;; History:
-;;
-
 ;;; Code:
 
 (require 'cl-lib)
diff --git a/lisp/vcursor.el b/lisp/vcursor.el
index 595a253..e219dc2 100644
--- a/lisp/vcursor.el
+++ b/lisp/vcursor.el
@@ -1,4 +1,4 @@
-;;; vcursor.el --- manipulate an alternative ("virtual") cursor
+;;; vcursor.el --- manipulate an alternative ("virtual") cursor  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 1994, 1996, 1998, 2001-2021 Free Software Foundation,
 ;; Inc.
@@ -27,24 +27,24 @@
 ;; Latest changes
 ;; ==============
 ;;
-;; - *IMPORTANT* vcursor-key-bindings is now nil by default, to avoid
+;; - *IMPORTANT* `vcursor-key-bindings' is now nil by default, to avoid
 ;;   side-effects when the package is loaded.  This means no keys are
 ;;   bound by default.  Use customize to change it to t to restore
 ;;   the old behavior.  (If you do it by hand in .emacs, it
 ;;   must come before vcursor is loaded.)
 ;; - You can alter the main variables and the vcursor face via
 ;;   M-x customize: go to the Editing group and find Vcursor.
-;; - vcursor-auto-disable can now be 'copy (actually any value not nil
+;; - `vcursor-auto-disable' can now be 'copy (actually any value not nil
 ;;   or t), which means that copying from the vcursor will be turned
 ;;   off after any operation not involving the vcursor, but the
 ;;   vcursor itself will be left alone.
 ;; - works on dumb terminals
 ;; - new keymap vcursor-map for binding to a prefix key
-;; - vcursor-compare-windows substantially improved
-;; - vcursor-execute-{key,command} much better about using the
+;; - `vcursor-compare-windows' substantially improved
+;; - `vcursor-execute-{key,command}' much better about using the
 ;;   right keymaps and arranging for the correct windows to be used
-;; - vcursor-window-funcall can call functions interactively
-;; - vcursor-interpret-input for special effects
+;; - `vcursor-window-funcall' can call functions interactively
+;; - `vcursor-interpret-input' for special effects
 ;;
 ;; Introduction
 ;; ============
@@ -326,21 +326,18 @@
 (defface vcursor
   '((((class color)) (:foreground "blue" :background "cyan" :underline t))
     (t (:inverse-video t :underline t)))
-  "Face for the virtual cursor."
-  :group 'vcursor)
+  "Face for the virtual cursor.")
 
 (defcustom vcursor-auto-disable nil
   "If non-nil, disable the virtual cursor after use.
 Any non-vcursor command will force `vcursor-disable' to be called.
 If non-nil but not t, just make sure copying is toggled off, but don't
 disable the vcursor."
-  :type '(choice (const t) (const nil) (const copy))
-  :group 'vcursor)
+  :type '(choice (const t) (const nil) (const copy)))
 
 (defcustom vcursor-modifiers (list 'control 'shift)
   "A list of modifiers that are used to define vcursor key bindings."
-  :type '(repeat symbol)
-  :group 'vcursor)
+  :type '(repeat symbol))
 
 ;; Needed for defcustom, must be up here
 (defun vcursor-cs-binding (base &optional meta)
@@ -349,112 +346,114 @@ disable the vcursor."
                (cons 'meta key)
              key))))
 
+;; (defvar vcursor)
+
 (defun vcursor-bind-keys (var value)
   "Alter the value of the variable VAR to VALUE, binding keys as required.
 VAR is usually `vcursor-key-bindings'.  Normally this function is called
 on loading vcursor and from the customize package."
   (set var value)
   (cond
-   ((not value));; don't set any key bindings
+   ((not value)) ;; Don't set any key bindings.
    ((or (eq value 'oemacs)
        (and (eq value t) (fboundp 'oemacs-version)))
-    (global-set-key [C-f1] 'vcursor-toggle-copy)
-    (global-set-key [C-f2] 'vcursor-copy)
-    (global-set-key [C-f3] 'vcursor-copy-word)
-    (global-set-key [C-f4] 'vcursor-copy-line)
-
-    (global-set-key [S-f1] 'vcursor-disable)
-    (global-set-key [S-f2] 'vcursor-other-window)
-    (global-set-key [S-f3] 'vcursor-goto)
-    (global-set-key [S-f4] 'vcursor-swap-point)
-
-    (global-set-key [C-f5] 'vcursor-backward-char)
-    (global-set-key [C-f6] 'vcursor-previous-line)
-    (global-set-key [C-f7] 'vcursor-next-line)
-    (global-set-key [C-f8] 'vcursor-forward-char)
-
-    (global-set-key [M-f5] 'vcursor-beginning-of-line)
-    (global-set-key [M-f6] 'vcursor-backward-word)
-    (global-set-key [M-f6] 'vcursor-forward-word)
-    (global-set-key [M-f8] 'vcursor-end-of-line)
-
-    (global-set-key [S-f5] 'vcursor-beginning-of-buffer)
-    (global-set-key [S-f6] 'vcursor-scroll-down)
-    (global-set-key [S-f7] 'vcursor-scroll-up)
-    (global-set-key [S-f8] 'vcursor-end-of-buffer)
-
-    (global-set-key [C-f9] 'vcursor-isearch-forward)
-
-    (global-set-key [S-f9] 'vcursor-execute-key)
-    (global-set-key [S-f10] 'vcursor-execute-command)
-
-;;; Partial dictionary of Oemacs key sequences for you to roll your own,
-;;; e.g C-S-up: (global-set-key "\M-[\C-f\M-\C-m" 'vcursor-previous-line)
-;;;    Sequence:         Sends:
-;;; "\M-[\C-f\M-\C-m"   C-S-up
-;;; "\M-[\C-f\M-\C-q"   C-S-down
-;;; "\M-[\C-fs"         C-S-left
-;;; "\M-[\C-ft"         C-S-right
-;;;
-;;; "\M-[\C-fw"         C-S-home
-;;; "\M-[\C-b\C-o"      S-tab
-;;; "\M-[\C-f\M-\C-r"   C-S-insert
-;;; "\M-[\C-fu"         C-S-end
-;;; "\M-[\C-f\M-\C-s"   C-S-delete
-;;; "\M-[\C-f\M-\C-d"   C-S-prior
-;;; "\M-[\C-fv"         C-S-next
-;;;
-;;; "\M-[\C-f^"         C-S-f1
-;;; "\M-[\C-f_"         C-S-f2
-;;; "\M-[\C-f`"         C-S-f3
-;;; "\M-[\C-fa"         C-S-f4
-;;; "\M-[\C-fb"         C-S-f5
-;;; "\M-[\C-fc"         C-S-f6
-;;; "\M-[\C-fd"         C-S-f7
-;;; "\M-[\C-fe"         C-S-f8
-;;; "\M-[\C-ff"         C-S-f9
-;;; "\M-[\C-fg"         C-S-f10
+    (global-set-key [C-f1] #'vcursor-toggle-copy)
+    (global-set-key [C-f2] #'vcursor-copy)
+    (global-set-key [C-f3] #'vcursor-copy-word)
+    (global-set-key [C-f4] #'vcursor-copy-line)
+
+    (global-set-key [S-f1] #'vcursor-disable)
+    (global-set-key [S-f2] #'vcursor-other-window)
+    (global-set-key [S-f3] #'vcursor-goto)
+    (global-set-key [S-f4] #'vcursor-swap-point)
+
+    (global-set-key [C-f5] #'vcursor-backward-char)
+    (global-set-key [C-f6] #'vcursor-previous-line)
+    (global-set-key [C-f7] #'vcursor-next-line)
+    (global-set-key [C-f8] #'vcursor-forward-char)
+
+    (global-set-key [M-f5] #'vcursor-beginning-of-line)
+    (global-set-key [M-f6] #'vcursor-backward-word)
+    (global-set-key [M-f6] #'vcursor-forward-word)
+    (global-set-key [M-f8] #'vcursor-end-of-line)
+
+    (global-set-key [S-f5] #'vcursor-beginning-of-buffer)
+    (global-set-key [S-f6] #'vcursor-scroll-down)
+    (global-set-key [S-f7] #'vcursor-scroll-up)
+    (global-set-key [S-f8] #'vcursor-end-of-buffer)
+
+    (global-set-key [C-f9] #'vcursor-isearch-forward)
+
+    (global-set-key [S-f9] #'vcursor-execute-key)
+    (global-set-key [S-f10] #'vcursor-execute-command)
+
+    ;; Partial dictionary of Oemacs key sequences for you to roll your own,
+    ;; e.g C-S-up: (global-set-key "\M-[\C-f\M-\C-m" 'vcursor-previous-line)
+    ;;    Sequence:         Sends:
+    ;; "\M-[\C-f\M-\C-m"   C-S-up
+    ;; "\M-[\C-f\M-\C-q"   C-S-down
+    ;; "\M-[\C-fs"         C-S-left
+    ;; "\M-[\C-ft"         C-S-right
+    ;;
+    ;; "\M-[\C-fw"         C-S-home
+    ;; "\M-[\C-b\C-o"      S-tab
+    ;; "\M-[\C-f\M-\C-r"   C-S-insert
+    ;; "\M-[\C-fu"         C-S-end
+    ;; "\M-[\C-f\M-\C-s"   C-S-delete
+    ;; "\M-[\C-f\M-\C-d"   C-S-prior
+    ;; "\M-[\C-fv"         C-S-next
+    ;;
+    ;; "\M-[\C-f^"         C-S-f1
+    ;; "\M-[\C-f_"         C-S-f2
+    ;; "\M-[\C-f`"         C-S-f3
+    ;; "\M-[\C-fa"         C-S-f4
+    ;; "\M-[\C-fb"         C-S-f5
+    ;; "\M-[\C-fc"         C-S-f6
+    ;; "\M-[\C-fd"         C-S-f7
+    ;; "\M-[\C-fe"         C-S-f8
+    ;; "\M-[\C-ff"         C-S-f9
+    ;; "\M-[\C-fg"         C-S-f10
     )
    (t
-    (global-set-key (vcursor-cs-binding "up") 'vcursor-previous-line)
-    (global-set-key (vcursor-cs-binding "down") 'vcursor-next-line)
-    (global-set-key (vcursor-cs-binding "left") 'vcursor-backward-char)
-    (global-set-key (vcursor-cs-binding "right") 'vcursor-forward-char)
-
-    (global-set-key (vcursor-cs-binding "return") 'vcursor-disable)
-    (global-set-key (vcursor-cs-binding "insert")  'vcursor-copy)
-    (global-set-key (vcursor-cs-binding "delete") 'vcursor-copy-word)
-    (global-set-key (vcursor-cs-binding "remove") 'vcursor-copy-word)
-    (global-set-key (vcursor-cs-binding "tab") 'vcursor-toggle-copy)
-    (global-set-key (vcursor-cs-binding "backtab") 'vcursor-toggle-copy)
-    (global-set-key (vcursor-cs-binding "home") 'vcursor-beginning-of-buffer)
-    (global-set-key (vcursor-cs-binding "up" t) 'vcursor-beginning-of-buffer)
-    (global-set-key (vcursor-cs-binding "end") 'vcursor-end-of-buffer)
-    (global-set-key (vcursor-cs-binding "down" t) 'vcursor-end-of-buffer)
-    (global-set-key (vcursor-cs-binding "prior") 'vcursor-scroll-down)
-    (global-set-key (vcursor-cs-binding "next") 'vcursor-scroll-up)
-
-    (global-set-key (vcursor-cs-binding "f6") 'vcursor-other-window)
-    (global-set-key (vcursor-cs-binding "f7") 'vcursor-goto)
+    (global-set-key (vcursor-cs-binding "up") #'vcursor-previous-line)
+    (global-set-key (vcursor-cs-binding "down") #'vcursor-next-line)
+    (global-set-key (vcursor-cs-binding "left") #'vcursor-backward-char)
+    (global-set-key (vcursor-cs-binding "right") #'vcursor-forward-char)
+
+    (global-set-key (vcursor-cs-binding "return") #'vcursor-disable)
+    (global-set-key (vcursor-cs-binding "insert")  #'vcursor-copy)
+    (global-set-key (vcursor-cs-binding "delete") #'vcursor-copy-word)
+    (global-set-key (vcursor-cs-binding "remove") #'vcursor-copy-word)
+    (global-set-key (vcursor-cs-binding "tab") #'vcursor-toggle-copy)
+    (global-set-key (vcursor-cs-binding "backtab") #'vcursor-toggle-copy)
+    (global-set-key (vcursor-cs-binding "home") #'vcursor-beginning-of-buffer)
+    (global-set-key (vcursor-cs-binding "up" t) #'vcursor-beginning-of-buffer)
+    (global-set-key (vcursor-cs-binding "end") #'vcursor-end-of-buffer)
+    (global-set-key (vcursor-cs-binding "down" t) #'vcursor-end-of-buffer)
+    (global-set-key (vcursor-cs-binding "prior") #'vcursor-scroll-down)
+    (global-set-key (vcursor-cs-binding "next") #'vcursor-scroll-up)
+
+    (global-set-key (vcursor-cs-binding "f6") #'vcursor-other-window)
+    (global-set-key (vcursor-cs-binding "f7") #'vcursor-goto)
 
     (global-set-key (vcursor-cs-binding "select")
-                   'vcursor-swap-point) ; DEC keyboards
-    (global-set-key (vcursor-cs-binding "tab" t) 'vcursor-swap-point)
+                   #'vcursor-swap-point) ; DEC keyboards
+    (global-set-key (vcursor-cs-binding "tab" t) #'vcursor-swap-point)
 
     (global-set-key (vcursor-cs-binding "find")
-                   'vcursor-isearch-forward) ; DEC keyboards
-    (global-set-key (vcursor-cs-binding "f8") 'vcursor-isearch-forward)
+                   #'vcursor-isearch-forward) ; DEC keyboards
+    (global-set-key (vcursor-cs-binding "f8") #'vcursor-isearch-forward)
 
-    (global-set-key (vcursor-cs-binding "left" t) 'vcursor-beginning-of-line)
-    (global-set-key (vcursor-cs-binding "right" t) 'vcursor-end-of-line)
+    (global-set-key (vcursor-cs-binding "left" t) #'vcursor-beginning-of-line)
+    (global-set-key (vcursor-cs-binding "right" t) #'vcursor-end-of-line)
 
-    (global-set-key (vcursor-cs-binding "prior" t) 'vcursor-backward-word)
-    (global-set-key (vcursor-cs-binding "next" t) 'vcursor-forward-word)
+    (global-set-key (vcursor-cs-binding "prior" t) #'vcursor-backward-word)
+    (global-set-key (vcursor-cs-binding "next" t) #'vcursor-forward-word)
 
-    (global-set-key (vcursor-cs-binding "return" t) 'vcursor-copy-line)
+    (global-set-key (vcursor-cs-binding "return" t) #'vcursor-copy-line)
 
-    (global-set-key (vcursor-cs-binding "f9") 'vcursor-execute-key)
-    (global-set-key (vcursor-cs-binding "f10") 'vcursor-execute-command)
+    (global-set-key (vcursor-cs-binding "f9") #'vcursor-execute-key)
+    (global-set-key (vcursor-cs-binding "f10") #'vcursor-execute-command)
     )))
 
 (defcustom vcursor-key-bindings nil
@@ -465,8 +464,7 @@ define any key bindings.
 
 Default is nil."
   :type '(choice (const t) (const nil) (const xterm) (const oemacs))
-  :group 'vcursor
-  :set 'vcursor-bind-keys
+  :set #'vcursor-bind-keys
   :version "20.3")
 
 (defcustom vcursor-interpret-input nil
@@ -475,13 +473,11 @@ This will cause text insertion to be much slower.  Note 
that no special
 interpretation of strings is done: \"\C-x\" is a string of four
 characters.  The default is simply to copy strings."
   :type 'boolean
-  :group 'vcursor
   :version "20.3")
 
 (defcustom vcursor-string "**>"
   "String used to show the vcursor position on dumb terminals."
   :type 'string
-  :group 'vcursor
   :version "20.3")
 
 (defvar vcursor-overlay nil
@@ -501,42 +497,41 @@ scrolling set this.  It is used by the 
`vcursor-auto-disable' code.")
 
 (defcustom vcursor-copy-flag nil
   "Non-nil means moving vcursor should copy characters moved over to point."
-  :type 'boolean
-  :group 'vcursor)
+  :type 'boolean)
 
 (defvar vcursor-temp-goal-column nil
   "Keeps track of temporary goal columns for the virtual cursor.")
 
 (defvar vcursor-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "t" 'vcursor-use-vcursor-map)
-
-    (define-key map "\C-p" 'vcursor-previous-line)
-    (define-key map "\C-n" 'vcursor-next-line)
-    (define-key map "\C-b" 'vcursor-backward-char)
-    (define-key map "\C-f" 'vcursor-forward-char)
-
-    (define-key map "\r" 'vcursor-disable)
-    (define-key map " " 'vcursor-copy)
-    (define-key map "\C-y" 'vcursor-copy-word)
-    (define-key map "\C-i" 'vcursor-toggle-copy)
-    (define-key map "<" 'vcursor-beginning-of-buffer)
-    (define-key map ">" 'vcursor-end-of-buffer)
-    (define-key map "\M-v" 'vcursor-scroll-down)
-    (define-key map "\C-v" 'vcursor-scroll-up)
-    (define-key map "o" 'vcursor-other-window)
-    (define-key map "g" 'vcursor-goto)
-    (define-key map "x" 'vcursor-swap-point)
-    (define-key map "\C-s" 'vcursor-isearch-forward)
-    (define-key map "\C-r" 'vcursor-isearch-backward)
-    (define-key map "\C-a" 'vcursor-beginning-of-line)
-    (define-key map "\C-e" 'vcursor-end-of-line)
-    (define-key map "\M-w" 'vcursor-forward-word)
-    (define-key map "\M-b" 'vcursor-backward-word)
-    (define-key map "\M-l" 'vcursor-copy-line)
-    (define-key map "c" 'vcursor-compare-windows)
-    (define-key map "k" 'vcursor-execute-key)
-    (define-key map "\M-x" 'vcursor-execute-command)
+    (define-key map "t" #'vcursor-use-vcursor-map)
+
+    (define-key map "\C-p" #'vcursor-previous-line)
+    (define-key map "\C-n" #'vcursor-next-line)
+    (define-key map "\C-b" #'vcursor-backward-char)
+    (define-key map "\C-f" #'vcursor-forward-char)
+
+    (define-key map "\r"   #'vcursor-disable)
+    (define-key map " "    #'vcursor-copy)
+    (define-key map "\C-y" #'vcursor-copy-word)
+    (define-key map "\C-i" #'vcursor-toggle-copy)
+    (define-key map "<"    #'vcursor-beginning-of-buffer)
+    (define-key map ">"    #'vcursor-end-of-buffer)
+    (define-key map "\M-v" #'vcursor-scroll-down)
+    (define-key map "\C-v" #'vcursor-scroll-up)
+    (define-key map "o"    #'vcursor-other-window)
+    (define-key map "g"    #'vcursor-goto)
+    (define-key map "x"    #'vcursor-swap-point)
+    (define-key map "\C-s" #'vcursor-isearch-forward)
+    (define-key map "\C-r" #'vcursor-isearch-backward)
+    (define-key map "\C-a" #'vcursor-beginning-of-line)
+    (define-key map "\C-e" #'vcursor-end-of-line)
+    (define-key map "\M-w" #'vcursor-forward-word)
+    (define-key map "\M-b" #'vcursor-backward-word)
+    (define-key map "\M-l" #'vcursor-copy-line)
+    (define-key map "c"    #'vcursor-compare-windows)
+    (define-key map "k"    #'vcursor-execute-key)
+    (define-key map "\M-x" #'vcursor-execute-command)
     map)
   "Keymap for vcursor command.")
 ;; This seems unused, but it was done as part of define-prefix-command,
@@ -611,7 +606,8 @@ Set `vcursor-window' to the returned value as a side 
effect."
                  (cond
                   (winok)              ; choice 2
                   ((and vcursor-window ; choice 3
-                        (not (eq thiswin vcursor-window))) vcursor-window)
+                        (not (eq thiswin vcursor-window)))
+                   vcursor-window)
                   (winbuf)             ; choice 4
                   (new-win (display-buffer (current-buffer) t)) ; choice 5
                   (t nil)))))))        ; default (choice 6)
@@ -719,16 +715,14 @@ not be visible otherwise, display it in another window."
 The vcursor will always appear in an unselected window."
 
   (interactive "P")
-  (vcursor-window-funcall 'scroll-up n)
-)
+  (vcursor-window-funcall #'scroll-up n))
 
 (defun vcursor-scroll-down (&optional n)
   "Scroll down the vcursor window ARG lines or near full screen if none.
 The vcursor will always appear in an unselected window."
 
   (interactive "P")
-  (vcursor-window-funcall 'scroll-down n)
-  )
+  (vcursor-window-funcall #'scroll-down n))
 
 (defun vcursor-isearch-forward (&optional rep norecurs)
   "Perform forward incremental search in the virtual cursor window.
@@ -736,7 +730,7 @@ The virtual cursor is moved to the resulting point; the 
ordinary
 cursor stays where it was."
 
   (interactive "P")
-  (vcursor-window-funcall 'isearch-forward rep norecurs)
+  (vcursor-window-funcall #'isearch-forward rep norecurs)
   )
 
 (defun vcursor-isearch-backward (&optional rep norecurs)
@@ -745,7 +739,7 @@ The virtual cursor is moved to the resulting point; the 
ordinary
 cursor stays where it was."
 
   (interactive "P")
-  (vcursor-window-funcall 'isearch-backward rep norecurs)
+  (vcursor-window-funcall #'isearch-backward rep norecurs)
   )
 
 (defun vcursor-window-funcall (func &rest args)
@@ -891,7 +885,7 @@ A prefix argument, if any, means ignore changes in 
whitespace.
 The variable `compare-windows-whitespace' controls how whitespace is skipped.
 If `compare-ignore-case' is non-nil, changes in case are also ignored."
   (interactive "P")
-  ;; (vcursor-window-funcall 'compare-windows arg)
+  ;; (vcursor-window-funcall #'compare-windows arg)
   (require 'compare-w)
   (let* (p1 p2 maxp1 maxp2 b1 b2 w2
            success
@@ -1005,32 +999,32 @@ If `compare-ignore-case' is non-nil, changes in case are 
also ignored."
 (defun vcursor-forward-char (arg)
   "Move the virtual cursor forward ARG characters."
   (interactive "p")
-  (vcursor-relative-move 'forward-char arg)
+  (vcursor-relative-move #'forward-char arg)
   )
 
 (defun vcursor-backward-char (arg)
   "Move the virtual cursor backward ARG characters."
   (interactive "p")
-  (vcursor-relative-move 'backward-char arg)
+  (vcursor-relative-move #'backward-char arg)
   )
 
 (defun vcursor-forward-word (arg)
   "Move the virtual cursor forward ARG words."
   (interactive "p")
-  (vcursor-relative-move 'forward-word arg)
+  (vcursor-relative-move #'forward-word arg)
   )
 
 (defun vcursor-backward-word (arg)
   "Move the virtual cursor backward ARG words."
   (interactive "p")
-  (vcursor-relative-move 'backward-word arg)
+  (vcursor-relative-move #'backward-word arg)
   )
 
 (defun vcursor-beginning-of-line (arg)
   "Move the virtual cursor to beginning of its current line.
 ARG is as for `beginning-of-line'."
   (interactive "P")
-  (vcursor-relative-move 'beginning-of-line
+  (vcursor-relative-move #'beginning-of-line
                         (if arg (prefix-numeric-value arg)))
   )
 
@@ -1038,7 +1032,7 @@ ARG is as for `beginning-of-line'."
   "Move the virtual cursor to end of its current line.
 ARG is as for `end-of-line'."
   (interactive "P")
-  (vcursor-relative-move 'end-of-line
+  (vcursor-relative-move #'end-of-line
                         (if arg (prefix-numeric-value arg)))
   )
 
@@ -1110,7 +1104,7 @@ is called interactively, so prefix argument etc. are 
usable."
 (defun vcursor-copy-word (arg)
   "Copy ARG words from the virtual cursor position to point."
   (interactive "p")
-  (vcursor-copy (vcursor-get-char-count 'forward-word arg))
+  (vcursor-copy (vcursor-get-char-count #'forward-word arg))
   )
 
 (defun vcursor-copy-line (arg)
@@ -1123,7 +1117,7 @@ line is treated like ordinary characters."
 
   (interactive "P")
   (let* ((num (prefix-numeric-value arg))
-        (count (vcursor-get-char-count 'end-of-line num)))
+        (count (vcursor-get-char-count #'end-of-line num)))
     (vcursor-copy (if (or (= count 0) arg) (1+ count) count)))
   )
 
@@ -1136,7 +1130,7 @@ line is treated like ordinary characters."
   (setq vcursor-last-command nil)
   )
 
-(add-hook 'post-command-hook 'vcursor-post-command)
+(add-hook 'post-command-hook #'vcursor-post-command)
 
 (provide 'vcursor)
 
diff --git a/lisp/view.el b/lisp/view.el
index 026c1ec..3476ced 100644
--- a/lisp/view.el
+++ b/lisp/view.el
@@ -1,4 +1,4 @@
-;;; view.el --- peruse file or buffer without editing
+;;; view.el --- peruse file or buffer without editing  -*- lexical-binding: t 
-*-
 
 ;; Copyright (C) 1985, 1989, 1994-1995, 1997, 2000-2021 Free Software
 ;; Foundation, Inc.
@@ -26,9 +26,9 @@
 
 ;; This package provides the `view' minor mode documented in the Emacs
 ;; user's manual.
-;; View mode entry and exit is done through the functions view-mode-enter
-;; and view-mode-exit.  Use these functions to enter or exit view-mode from
-;; emacs lisp programs.
+;; View mode entry and exit is done through the functions `view-mode-enter'
+;; and `view-mode-exit'.  Use these functions to enter or exit `view-mode' from
+;; Emacs Lisp programs.
 ;; We use both view- and View- as prefix for symbols.  View- is used as
 ;; prefix for commands that have a key binding.  view- is used for commands
 ;; without key binding.  The purpose of this is to make it easier for a
@@ -36,11 +36,11 @@
 
 ;;; Suggested key bindings:
 ;;
-;; (define-key ctl-x-4-map "v" 'view-file-other-window)  ; ^x4v
-;; (define-key ctl-x-5-map "v" 'view-file-other-frame)  ; ^x5v
+;; (define-key ctl-x-4-map "v" #'view-file-other-window)  ; ^x4v
+;; (define-key ctl-x-5-map "v" #'view-file-other-frame)   ; ^x5v
 ;;
-;; You could also bind view-file, view-buffer, view-buffer-other-window and
-;; view-buffer-other-frame to keys.
+;; You could also bind `view-file', `view-buffer', `view-buffer-other-window' 
and
+;; `view-buffer-other-frame' to keys.
 
 ;;; Code:
 
@@ -51,31 +51,27 @@
   :group 'text)
 
 (defcustom view-highlight-face 'highlight
-   "The face used for highlighting the match found by View mode search."
-   :type 'face
-   :group 'view)
+  "The face used for highlighting the match found by View mode search."
+  :type 'face)
 
 (defcustom view-scroll-auto-exit nil
   "Non-nil means scrolling past the end of buffer exits View mode.
 A value of nil means attempting to scroll past the end of the buffer,
 only rings the bell and gives a message on how to leave."
-  :type 'boolean
-  :group 'view)
+  :type 'boolean)
 
 (defcustom view-try-extend-at-buffer-end nil
  "Non-nil means try to load more of file when reaching end of buffer.
 This variable is mainly intended to be temporarily set to non-nil by
-the F command in view-mode, but you can set it to t if you want the action
+the F command in `view-mode', but you can set it to t if you want the action
 for all scroll commands in view mode."
-  :type 'boolean
-  :group 'view)
+  :type 'boolean)
 
 ;;;###autoload
 (defcustom view-remove-frame-by-deleting t
   "Determine how View mode removes a frame no longer needed.
 If nil, make an icon of the frame.  If non-nil, delete the frame."
   :type 'boolean
-  :group 'view
   :version "23.1")
 
 (defcustom view-exits-all-viewing-windows nil
@@ -84,15 +80,13 @@ Commands that restore windows when finished viewing a 
buffer,
 apply to all windows that display the buffer and have restore
 information.  If `view-exits-all-viewing-windows' is nil, only
 the selected window is considered for restoring."
-  :type 'boolean
-  :group 'view)
+  :type 'boolean)
 
 (defcustom view-inhibit-help-message nil
   "Non-nil inhibits the help message shown upon entering View mode.
 This setting takes effect only when View mode is entered via an
 interactive command; otherwise the help message is not shown."
   :type 'boolean
-  :group 'view
   :version "22.1")
 
 ;;;###autoload
@@ -103,8 +97,7 @@ functions that enable or disable view mode.")
 
 (defcustom view-mode-hook nil
   "Normal hook run when starting to view a buffer or file."
-  :type 'hook
-  :group 'view)
+  :type 'hook)
 
 (defvar-local view-old-buffer-read-only nil)
 
@@ -154,62 +147,62 @@ This is local in each buffer, once it is used.")
 ;; Some redundant "less"-like key bindings below have been commented out.
 (defvar view-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map "C" 'View-kill-and-leave)
-    (define-key map "c" 'View-leave)
-    (define-key map "Q" 'View-quit-all)
-    (define-key map "E" 'View-exit-and-edit)
-    ;; (define-key map "v" 'View-exit)
-    (define-key map "e" 'View-exit)
-    (define-key map "q" 'View-quit)
-    ;; (define-key map "N" 'View-search-last-regexp-backward)
-    (define-key map "p" 'View-search-last-regexp-backward)
-    (define-key map "n" 'View-search-last-regexp-forward)
-    ;; (define-key map "?" 'View-search-regexp-backward) ; Less does this.
-    (define-key map "\\" 'View-search-regexp-backward)
-    (define-key map "/" 'View-search-regexp-forward)
-    (define-key map "r" 'isearch-backward)
-    (define-key map "s" 'isearch-forward)
-    (define-key map "m" 'point-to-register)
-    (define-key map "'" 'register-to-point)
-    (define-key map "x" 'exchange-point-and-mark)
-    (define-key map "@" 'View-back-to-mark)
-    (define-key map "." 'set-mark-command)
-    (define-key map "%" 'View-goto-percent)
-    ;; (define-key map "G" 'View-goto-line-last)
-    (define-key map "g" 'View-goto-line)
-    (define-key map "=" 'what-line)
-    (define-key map "F" 'View-revert-buffer-scroll-page-forward)
-    ;; (define-key map "k" 'View-scroll-line-backward)
-    (define-key map "y" 'View-scroll-line-backward)
-    ;; (define-key map "j" 'View-scroll-line-forward)
-    (define-key map "\n" 'View-scroll-line-forward)
-    (define-key map "\r" 'View-scroll-line-forward)
-    (define-key map "u" 'View-scroll-half-page-backward)
-    (define-key map "d" 'View-scroll-half-page-forward)
-    (define-key map "z" 'View-scroll-page-forward-set-page-size)
-    (define-key map "w" 'View-scroll-page-backward-set-page-size)
-    ;; (define-key map "b" 'View-scroll-page-backward)
-    (define-key map "\C-?" 'View-scroll-page-backward)
-    ;; (define-key map "f" 'View-scroll-page-forward)
-    (define-key map " " 'View-scroll-page-forward)
-    (define-key map [?\S-\ ]  'View-scroll-page-backward)
-    (define-key map "o" 'View-scroll-to-buffer-end)
-    (define-key map ">" 'end-of-buffer)
-    (define-key map "<" 'beginning-of-buffer)
-    (define-key map "-" 'negative-argument)
-    (define-key map "9" 'digit-argument)
-    (define-key map "8" 'digit-argument)
-    (define-key map "7" 'digit-argument)
-    (define-key map "6" 'digit-argument)
-    (define-key map "5" 'digit-argument)
-    (define-key map "4" 'digit-argument)
-    (define-key map "3" 'digit-argument)
-    (define-key map "2" 'digit-argument)
-    (define-key map "1" 'digit-argument)
-    (define-key map "0" 'digit-argument)
-    (define-key map "H" 'describe-mode)
-    (define-key map "?" 'describe-mode)        ; Maybe do as less instead? See 
above.
-    (define-key map "h" 'describe-mode)
+    (define-key map "C" #'View-kill-and-leave)
+    (define-key map "c" #'View-leave)
+    (define-key map "Q" #'View-quit-all)
+    (define-key map "E" #'View-exit-and-edit)
+    ;; (define-key map "v" #'View-exit)
+    (define-key map "e" #'View-exit)
+    (define-key map "q" #'View-quit)
+    ;; (define-key map "N" #'View-search-last-regexp-backward)
+    (define-key map "p" #'View-search-last-regexp-backward)
+    (define-key map "n" #'View-search-last-regexp-forward)
+    ;; (define-key map "?" #'View-search-regexp-backward) ; Less does this.
+    (define-key map "\\" #'View-search-regexp-backward)
+    (define-key map "/" #'View-search-regexp-forward)
+    (define-key map "r" #'isearch-backward)
+    (define-key map "s" #'isearch-forward)
+    (define-key map "m" #'point-to-register)
+    (define-key map "'" #'register-to-point)
+    (define-key map "x" #'exchange-point-and-mark)
+    (define-key map "@" #'View-back-to-mark)
+    (define-key map "." #'set-mark-command)
+    (define-key map "%" #'View-goto-percent)
+    ;; (define-key map "G" #'View-goto-line-last)
+    (define-key map "g" #'View-goto-line)
+    (define-key map "=" #'what-line)
+    (define-key map "F" #'View-revert-buffer-scroll-page-forward)
+    ;; (define-key map "k" #'View-scroll-line-backward)
+    (define-key map "y" #'View-scroll-line-backward)
+    ;; (define-key map "j" #'View-scroll-line-forward)
+    (define-key map "\n" #'View-scroll-line-forward)
+    (define-key map "\r" #'View-scroll-line-forward)
+    (define-key map "u" #'View-scroll-half-page-backward)
+    (define-key map "d" #'View-scroll-half-page-forward)
+    (define-key map "z" #'View-scroll-page-forward-set-page-size)
+    (define-key map "w" #'View-scroll-page-backward-set-page-size)
+    ;; (define-key map "b" #'View-scroll-page-backward)
+    (define-key map "\C-?" #'View-scroll-page-backward)
+    ;; (define-key map "f" #'View-scroll-page-forward)
+    (define-key map " " #'View-scroll-page-forward)
+    (define-key map [?\S-\ ] #'View-scroll-page-backward)
+    (define-key map "o" #'View-scroll-to-buffer-end)
+    (define-key map ">" #'end-of-buffer)
+    (define-key map "<" #'beginning-of-buffer)
+    (define-key map "-" #'negative-argument)
+    (define-key map "9" #'digit-argument)
+    (define-key map "8" #'digit-argument)
+    (define-key map "7" #'digit-argument)
+    (define-key map "6" #'digit-argument)
+    (define-key map "5" #'digit-argument)
+    (define-key map "4" #'digit-argument)
+    (define-key map "3" #'digit-argument)
+    (define-key map "2" #'digit-argument)
+    (define-key map "1" #'digit-argument)
+    (define-key map "0" #'digit-argument)
+    (define-key map "H" #'describe-mode)
+    (define-key map "?" #'describe-mode)       ; Maybe do as less instead? See 
above.
+    (define-key map "h" #'describe-mode)
     map))
 
 ;;; Commands that enter or exit view mode.
@@ -220,7 +213,7 @@ This is local in each buffer, once it is used.")
 ;; types C-x C-q again to return to view mode.
 ;;;###autoload
 (defun kill-buffer-if-not-modified (buf)
-  "Like `kill-buffer', but does nothing if the buffer is modified."
+  "Like `kill-buffer', but does nothing if buffer BUF is modified."
   (let ((buf (get-buffer buf)))
     (and buf (not (buffer-modified-p buf))
         (kill-buffer buf))))
@@ -305,7 +298,7 @@ file: Users may suspend viewing in order to modify the 
buffer.
 Exiting View mode will then discard the user's edits.  Setting
 EXIT-ACTION to `kill-buffer-if-not-modified' avoids this.
 
-This function does not enable View mode if the buffer's major-mode
+This function does not enable View mode if the buffer's major mode
 has a `special' mode-class, because such modes usually have their
 own View-like bindings."
   (interactive "bView buffer: ")
@@ -331,7 +324,7 @@ Optional argument EXIT-ACTION is either nil or a function 
with buffer as
 argument.  This function is called when finished viewing buffer.  Use
 this argument instead of explicitly setting `view-exit-action'.
 
-This function does not enable View mode if the buffer's major-mode
+This function does not enable View mode if the buffer's major mode
 has a `special' mode-class, because such modes usually have their
 own View-like bindings."
   (interactive "bIn other window view buffer:\nP")
@@ -358,7 +351,7 @@ Optional argument EXIT-ACTION is either nil or a function 
with buffer as
 argument.  This function is called when finished viewing buffer.  Use
 this argument instead of explicitly setting `view-exit-action'.
 
-This function does not enable View mode if the buffer's major-mode
+This function does not enable View mode if the buffer's major mode
 has a `special' mode-class, because such modes usually have their
 own View-like bindings."
   (interactive "bView buffer in other frame: \nP")
@@ -662,8 +655,8 @@ previous state and go to previous buffer or window."
   (recenter '(1)))
 
 (defun view-page-size-default (lines)
-  ;; If LINES is nil, 0, or larger than `view-window-size', return nil.
-  ;; Otherwise, return LINES.
+  "If LINES is nil, 0, or larger than `view-window-size', return nil.
+Otherwise, return LINES."
   (and lines
        (not (zerop (setq lines (prefix-numeric-value lines))))
        (<= (abs lines)
@@ -671,7 +664,7 @@ previous state and go to previous buffer or window."
        (abs lines)))
 
 (defun view-set-half-page-size-default (lines)
-  ;; Get and maybe set half page size.
+  "Get and maybe set half page size."
   (if (not lines) (or view-half-page-size
                      (/ (view-window-size) 2))
     (setq view-half-page-size
@@ -749,7 +742,7 @@ invocations return to earlier marks."
           (if (view-really-at-end) (view-end-message)))))
 
 (defun view-really-at-end ()
-  ;; Return true if buffer end visible.  Maybe revert buffer and test.
+  "Return non-nil if buffer end visible.  Maybe revert buffer and test."
   (and (or (null scroll-error-top-bottom) (eobp))
        (pos-visible-in-window-p (point-max))
        (let ((buf (current-buffer))
@@ -772,7 +765,7 @@ invocations return to earlier marks."
               (pos-visible-in-window-p (point-max)))))))
 
 (defun view-end-message ()
-  ;; Tell that we are at end of buffer.
+  "Tell that we are at end of buffer."
   (goto-char (point-max))
   (if (window-parameter nil 'quit-restore)
       (message "End of buffer.  Type %s to quit viewing."
@@ -979,7 +972,7 @@ for highlighting the match that is found."
 ;; https://lists.gnu.org/r/bug-gnu-emacs/2007-09/msg00073.html
 (defun view-search-no-match-lines (times regexp)
   "Search for the TIMESth occurrence of a line with no match for REGEXP.
-If such a line is found, return non-nil and set the match-data to that line.
+If such a line is found, return non-nil and set the match data to that line.
 If TIMES is negative, search backwards."
   (let ((step (if (>= times 0) 1
                 (setq times (- times))
diff --git a/lisp/wdired.el b/lisp/wdired.el
index e040b52..ff42d78 100644
--- a/lisp/wdired.el
+++ b/lisp/wdired.el
@@ -172,6 +172,7 @@ nonexistent directory will fail."
     (define-key map [remap upcase-word] #'wdired-upcase-word)
     (define-key map [remap capitalize-word] #'wdired-capitalize-word)
     (define-key map [remap downcase-word] #'wdired-downcase-word)
+    (define-key map [remap self-insert-command] #'wdired--self-insert)
     map)
   "Keymap used in `wdired-mode'.")
 
@@ -188,10 +189,11 @@ nonexistent directory will fail."
   "Hooks run when changing to WDired mode.")
 
 ;; Local variables (put here to avoid compilation gripes)
-(defvar wdired-col-perm) ;; Column where the permission bits start
-(defvar wdired-old-content)
-(defvar wdired-old-point)
-(defvar wdired-old-marks)
+(defvar wdired--perm-beg) ;; Column where the permission bits start
+(defvar wdired--perm-end) ;; Column where the permission bits stop
+(defvar wdired--old-content)
+(defvar wdired--old-point)
+(defvar wdired--old-marks)
 
 (defun wdired-mode ()
   "Writable Dired (WDired) mode.
@@ -230,11 +232,12 @@ See `wdired-mode'."
   (interactive)
   (unless (derived-mode-p 'dired-mode)
     (error "Not a Dired buffer"))
-  (setq-local wdired-old-content
+  (setq-local wdired--old-content
               (buffer-substring (point-min) (point-max)))
-  (setq-local wdired-old-marks
+  (setq-local wdired--old-marks
               (dired-remember-marks (point-min) (point-max)))
-  (setq-local wdired-old-point (point))
+  (setq-local wdired--old-point (point))
+  (wdired--set-permission-bounds)
   (setq-local query-replace-skip-read-only t)
   (add-function :after-while (local 'isearch-filter-predicate)
                 #'wdired-isearch-filter-read-only)
@@ -243,20 +246,11 @@ See `wdired-mode'."
   (setq buffer-read-only nil)
   (dired-unadvertise default-directory)
   (add-hook 'kill-buffer-hook #'wdired-check-kill-buffer nil t)
+  (add-hook 'before-change-functions #'wdired--before-change-fn nil t)
   (add-hook 'after-change-functions #'wdired--restore-properties nil t)
   (setq major-mode 'wdired-mode)
   (setq mode-name "Editable Dired")
-  (add-function :override (local revert-buffer-function) #'wdired-revert)
-  ;; I temp disable undo for performance: since I'm going to clear the
-  ;; undo list, it can save more than a 9% of time with big
-  ;; directories because setting properties modify the undo-list.
-  (buffer-disable-undo)
-  (wdired-preprocess-files)
-  (if wdired-allow-to-change-permissions
-      (wdired-preprocess-perms))
-  (if (fboundp 'make-symbolic-link)
-      (wdired-preprocess-symlinks))
-  (buffer-enable-undo) ; Performance hack. See above.
+  (add-function :override (local 'revert-buffer-function) #'wdired-revert)
   (set-buffer-modified-p nil)
   (setq buffer-undo-list nil)
   (run-mode-hooks 'wdired-mode-hook)
@@ -264,6 +258,63 @@ See `wdired-mode'."
                 "Press \\[wdired-finish-edit] when finished \
 or \\[wdired-abort-changes] to abort changes")))
 
+(defun wdired--set-permission-bounds ()
+  (save-excursion
+    (goto-char (point-min))
+    (if (not (re-search-forward dired-re-perms nil t 1))
+        (progn
+          (setq-local wdired--perm-beg nil)
+          (setq-local wdired--perm-end nil))
+      (goto-char (match-beginning 0))
+      ;; Add 1 since the first char matched by `dired-re-perms' is the
+      ;; one describing the nature of the entry (dir/symlink/...) rather
+      ;; than its permissions.
+      (setq-local wdired--perm-beg (1+ (wdired--current-column)))
+      (goto-char (match-end 0))
+      (setq-local wdired--perm-end (wdired--current-column)))))
+
+(defun wdired--current-column ()
+  (- (point) (line-beginning-position)))
+
+(defun wdired--point-at-perms-p ()
+  (and wdired--perm-beg
+       (<= wdired--perm-beg (wdired--current-column) wdired--perm-end)))
+
+(defun wdired--line-preprocessed-p ()
+  (get-text-property (line-beginning-position) 'front-sticky))
+
+(defun wdired--self-insert ()
+  (interactive)
+  (if (wdired--line-preprocessed-p)
+      (call-interactively 'self-insert-command)
+    (wdired--before-change-fn (point) (point))
+    (let* ((map (get-text-property (point) 'keymap)))
+      (call-interactively (or (if map (lookup-key map (this-command-keys)))
+                              #'self-insert-command)))))
+
+(defun wdired--before-change-fn (beg end)
+  (save-excursion
+    ;; Make sure to process entire lines.
+    (goto-char end)
+    (setq end (line-end-position))
+    (goto-char beg)
+    (forward-line 0)
+
+    (while (< (point) end)
+      (unless (wdired--line-preprocessed-p)
+        (with-silent-modifications
+          (put-text-property (point) (1+ (point)) 'front-sticky t)
+          (wdired--preprocess-files)
+          (when wdired-allow-to-change-permissions
+            (wdired--preprocess-perms))
+          (when (fboundp 'make-symbolic-link)
+            (wdired--preprocess-symlinks))))
+      (forward-line))
+    (when (eobp)
+      (with-silent-modifications
+        ;; Is this good enough? Assumes no extra white lines from dired.
+        (put-text-property (1- (point-max)) (point-max) 'read-only t)))))
+
 (defun wdired-isearch-filter-read-only (beg end)
   "Skip matches that have a read-only property."
   (not (text-property-not-all (min beg end) (max beg end)
@@ -271,35 +322,28 @@ or \\[wdired-abort-changes] to abort changes")))
 
 ;; Protect the buffer so only the filenames can be changed, and put
 ;; properties so filenames (old and new) can be easily found.
-(defun wdired-preprocess-files ()
-  (put-text-property (point-min) (1+ (point-min))'front-sticky t)
+(defun wdired--preprocess-files ()
   (save-excursion
-    (goto-char (point-min))
-    (let ((b-protection (point))
-          (used-F (dired-check-switches dired-actual-switches "F" "classify"))
-         filename)
-      (while (not (eobp))
-       (setq filename (dired-get-filename nil t))
-        (when (and filename
-                  (not (member (file-name-nondirectory filename) '("." ".."))))
-         (dired-move-to-filename)
-         ;; The rear-nonsticky property below shall ensure that text preceding
-         ;; the filename can't be modified.
-         (add-text-properties
-          (1- (point)) (point) `(old-name ,filename rear-nonsticky 
(read-only)))
-         (put-text-property b-protection (point) 'read-only t)
-          (dired-move-to-end-of-filename t)
-         (put-text-property (point) (1+ (point)) 'end-name t))
-          (when (and used-F (looking-at "[*/@|=>]$")) (forward-char))
-          (when (save-excursion
-                  (and (re-search-backward
-                        dired-permission-flags-regexp nil t)
-                       (looking-at "l")
-                       (search-forward " -> " (line-end-position) t)))
-            (goto-char (line-end-position)))
-         (setq b-protection (point))
-        (forward-line))
-      (put-text-property b-protection (point-max) 'read-only t))))
+    (let ((used-F (dired-check-switches dired-actual-switches "F" "classify"))
+         (beg (point))
+          (filename (dired-get-filename nil t)))
+      (when (and filename
+                (not (member (file-name-nondirectory filename) '("." ".."))))
+       (dired-move-to-filename)
+       ;; The rear-nonsticky property below shall ensure that text preceding
+       ;; the filename can't be modified.
+       (add-text-properties
+        (1- (point)) (point) `(old-name ,filename rear-nonsticky (read-only)))
+       (put-text-property beg (point) 'read-only t)
+        (dired-move-to-end-of-filename t)
+       (put-text-property (point) (1+ (point)) 'end-name t))
+      (when (and used-F (looking-at "[*/@|=>]$")) (forward-char))
+      (when (save-excursion
+              (and (re-search-backward
+                    dired-permission-flags-regexp nil t)
+                   (looking-at "l")
+                   (search-forward " -> " (line-end-position) t)))
+        (goto-char (line-end-position))))))
 
 ;; This code is a copy of some dired-get-filename lines.
 (defsubst wdired-normalize-filename (file unquotep)
@@ -326,6 +370,7 @@ non-nil means return old filename."
   ;; FIXME: Use dired-get-filename's new properties.
   (let ((used-F (dired-check-switches dired-actual-switches "F" "classify"))
         beg end file)
+    (wdired--before-change-fn (point) (point))
     (save-excursion
       (setq end (line-end-position))
       (beginning-of-line)
@@ -362,7 +407,6 @@ non-nil means return old filename."
        (and file (> (length file) 0)
              (concat (dired-current-directory) file))))))
 
-
 (defun wdired-change-to-dired-mode ()
   "Change the mode back to dired."
   (or (eq major-mode 'wdired-mode)
@@ -380,16 +424,18 @@ non-nil means return old filename."
   (setq mode-name "Dired")
   (dired-advertise)
   (remove-hook 'kill-buffer-hook #'wdired-check-kill-buffer t)
+  (remove-hook 'before-change-functions #'wdired--before-change-fn t)
   (remove-hook 'after-change-functions #'wdired--restore-properties t)
-  (remove-function (local revert-buffer-function) #'wdired-revert))
+  (remove-function (local 'revert-buffer-function) #'wdired-revert))
 
 (defun wdired-abort-changes ()
   "Abort changes and return to dired mode."
   (interactive)
+  (remove-hook 'before-change-functions #'wdired--before-change-fn t)
   (let ((inhibit-read-only t))
     (erase-buffer)
-    (insert wdired-old-content)
-    (goto-char wdired-old-point))
+    (insert wdired--old-content)
+    (goto-char wdired--old-point))
   (wdired-change-to-dired-mode)
   (set-buffer-modified-p nil)
   (setq buffer-undo-list nil)
@@ -411,13 +457,14 @@ non-nil means return old filename."
        (setq errors (cdr tmp-value))
        (setq changes (car tmp-value)))
       (when (and wdired-allow-to-change-permissions
-                (boundp 'wdired-col-perm)) ; could have been changed
+                wdired--perm-beg) ; could have been changed
        (setq tmp-value (wdired-do-perm-changes))
        (setq errors (+ errors (cdr tmp-value)))
        (setq changes (or changes (car tmp-value))))
       (goto-char (point-max))
       (while (not (bobp))
-       (setq file-old (wdired-get-filename nil t))
+       (setq file-old (and (wdired--line-preprocessed-p)
+                           (wdired-get-filename nil t)))
        (when file-old
          (setq file-new (wdired-get-filename))
           (if (equal file-new file-old)
@@ -429,11 +476,11 @@ non-nil means return old filename."
                (let ((mark (cond ((integerp wdired-keep-marker-rename)
                                   wdired-keep-marker-rename)
                                  (wdired-keep-marker-rename
-                                  (cdr (assoc file-old wdired-old-marks)))
+                                  (cdr (assoc file-old wdired--old-marks)))
                                  (t nil))))
                  (when mark
                    (push (cons (substitute-in-file-name file-new) mark)
-                         wdired-old-marks))))
+                         wdired--old-marks))))
               (push (cons file-old (substitute-in-file-name file-new))
                     files-renamed))))
        (forward-line -1)))
@@ -458,7 +505,7 @@ non-nil means return old filename."
          ;; Re-sort the buffer.
          (revert-buffer)
          (let ((inhibit-read-only t))
-           (dired-mark-remembered wdired-old-marks)))
+           (dired-mark-remembered wdired--old-marks)))
       (let ((inhibit-read-only t))
        (remove-text-properties (point-min) (point-max)
                                '(old-name nil end-name nil old-link nil
@@ -702,21 +749,17 @@ says how many lines to move; default is one line."
       (dired-move-to-filename)))
 
 ;; Put the needed properties to allow the user to change links' targets
-(defun wdired-preprocess-symlinks ()
-  (let ((inhibit-read-only t))
-    (save-excursion
-      (goto-char (point-min))
-      (while (not (eobp))
-        (when (looking-at dired-re-sym)
-          (re-search-forward " -> \\(.*\\)$")
-         (put-text-property (1- (match-beginning 1))
-                            (match-beginning 1) 'old-link
-                            (match-string-no-properties 1))
-          (put-text-property (match-end 1) (1+ (match-end 1)) 'end-link t)
-          (unless wdired-allow-to-redirect-links
-            (put-text-property (match-beginning 0)
-                              (match-end 1) 'read-only t)))
-        (forward-line)))))
+(defun wdired--preprocess-symlinks ()
+  (save-excursion
+    (when (looking-at dired-re-sym)
+      (re-search-forward " -> \\(.*\\)$")
+      (put-text-property (1- (match-beginning 1))
+                        (match-beginning 1) 'old-link
+                        (match-string-no-properties 1))
+      (put-text-property (match-end 1) (1+ (match-end 1)) 'end-link t)
+      (unless wdired-allow-to-redirect-links
+        (put-text-property (match-beginning 0)
+                          (match-end 1) 'read-only t)))))
 
 (defun wdired-get-previous-link (&optional old move)
   "Return the next symlink target.
@@ -800,7 +843,6 @@ Like original function but it skips read-only words."
   (interactive "p")
   (wdired-xcase-word 'capitalize-word arg))
 
-
 ;; The following code deals with changing the access bits (or
 ;; permissions) of the files.
 
@@ -822,34 +864,28 @@ Like original function but it skips read-only words."
 
 ;; Put a keymap property to the permission bits of the files, and store the
 ;; original name and permissions as a property
-(defun wdired-preprocess-perms ()
-  (let ((inhibit-read-only t))
-    (setq-local wdired-col-perm nil)
-    (save-excursion
-      (goto-char (point-min))
-      (while (not (eobp))
-       (when (and (not (looking-at dired-re-sym))
-                  (wdired-get-filename)
-                  (re-search-forward dired-re-perms (line-end-position) 'eol))
-         (let ((begin (match-beginning 0))
-               (end (match-end 0)))
-           (unless wdired-col-perm
-             (setq wdired-col-perm (- (current-column) 9)))
-           (if (eq wdired-allow-to-change-permissions 'advanced)
-               (progn
-                 (put-text-property begin end 'read-only nil)
-                 ;; make first permission bit writable
-                 (put-text-property
-                  (1- begin) begin 'rear-nonsticky '(read-only)))
-             ;; avoid that keymap applies to text following permissions
-             (add-text-properties
-              (1+ begin) end
-              `(keymap ,wdired-perm-mode-map rear-nonsticky (keymap))))
-           (put-text-property end (1+ end) 'end-perm t)
-           (put-text-property
-            begin (1+ begin) 'old-perm (match-string-no-properties 0))))
-        (forward-line)
-       (beginning-of-line)))))
+(defun wdired--preprocess-perms ()
+  (save-excursion
+    (when (and (not (looking-at dired-re-sym))
+              (wdired-get-filename)
+              (re-search-forward dired-re-perms
+                                  (line-end-position) 'eol))
+      (let ((begin (match-beginning 0))
+           (end (match-end 0)))
+       (if (eq wdired-allow-to-change-permissions 'advanced)
+           (progn
+             (put-text-property begin end 'read-only nil)
+             ;; make first permission bit writable
+             (put-text-property
+              (1- begin) begin 'rear-nonsticky '(read-only)))
+         ;; avoid that keymap applies to text following permissions
+         (add-text-properties
+          (1+ begin) end
+          `(keymap ,wdired-perm-mode-map rear-nonsticky (keymap))))
+       (put-text-property end (1+ end) 'end-perm t)
+       (put-text-property
+        begin (1+ begin)
+         'old-perm (match-string-no-properties 0))))))
 
 (defun wdired-perm-allowed-in-pos (char pos)
   (cond
@@ -861,39 +897,30 @@ Like original function but it skips read-only words."
    ((memq char '(?t ?T)) (= pos 8))
    ((= char ?l)          (= pos 5))))
 
-(defun wdired-set-bit ()
+(defun wdired-set-bit (&optional char)
   "Set a permission bit character."
-  (interactive)
-  (if (wdired-perm-allowed-in-pos last-command-event
-                                  (- (current-column) wdired-col-perm))
-      (let ((new-bit (char-to-string last-command-event))
+  (interactive (list last-command-event))
+  (unless char (setq char last-command-event))
+  (if (wdired-perm-allowed-in-pos char
+                                  (- (wdired--current-column) 
wdired--perm-beg))
+      (let ((new-bit (char-to-string char))
             (inhibit-read-only t)
-           (pos-prop (- (point) (- (current-column) wdired-col-perm))))
-        (put-text-property 0 1 'keymap wdired-perm-mode-map new-bit)
-        (put-text-property 0 1 'read-only t new-bit)
+           (pos-prop (+ (line-beginning-position) wdired--perm-beg)))
+        (set-text-properties 0 1 (text-properties-at (point)) new-bit)
         (insert new-bit)
         (delete-char 1)
-       (put-text-property (1- pos-prop) pos-prop 'perm-changed t)
-       (put-text-property (1- (point)) (point) 'rear-nonsticky '(keymap)))
+       (put-text-property (1- pos-prop) pos-prop 'perm-changed t))
     (forward-char 1)))
 
 (defun wdired-toggle-bit ()
   "Toggle the permission bit at point."
   (interactive)
-  (let ((inhibit-read-only t)
-       (new-bit "-")
-       (pos-prop (- (point) (- (current-column) wdired-col-perm))))
-    (if (eq (char-after (point)) ?-)
-       (setq new-bit
-             (if (= (% (- (current-column) wdired-col-perm) 3) 0) "r"
-               (if (= (% (- (current-column) wdired-col-perm) 3) 1) "w"
-                 "x"))))
-    (put-text-property 0 1 'keymap wdired-perm-mode-map new-bit)
-    (put-text-property 0 1 'read-only t new-bit)
-    (insert new-bit)
-    (delete-char 1)
-    (put-text-property (1- pos-prop) pos-prop 'perm-changed t)
-    (put-text-property (1- (point)) (point) 'rear-nonsticky '(keymap))))
+  (wdired-set-bit
+   (cond
+    ((not (eq (char-after (point)) ?-)) ?-)
+    ((= (% (- (wdired--current-column) wdired--perm-beg) 3) 0) ?r)
+    ((= (% (- (wdired--current-column) wdired--perm-beg) 3) 1) ?w)
+    (t ?x))))
 
 (defun wdired-mouse-toggle-bit (event)
   "Toggle the permission bit that was left clicked."
diff --git a/lisp/wid-browse.el b/lisp/wid-browse.el
index 39b3221..54b71c9 100644
--- a/lisp/wid-browse.el
+++ b/lisp/wid-browse.el
@@ -1,7 +1,7 @@
-;;; wid-browse.el --- functions for browsing widgets
-;;
+;;; wid-browse.el --- functions for browsing widgets  -*- lexical-binding: t 
-*-
+
 ;; Copyright (C) 1997, 2001-2021 Free Software Foundation, Inc.
-;;
+
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Keywords: extensions
 ;; Package: emacs
@@ -22,7 +22,7 @@
 ;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Commentary:
-;;
+
 ;; Widget browser.  See `widget.el'.
 
 ;;; Code:
@@ -38,7 +38,7 @@
 (defvar widget-browse-mode-map
   (let ((map (make-sparse-keymap)))
     (set-keymap-parent map widget-keymap)
-    (define-key map "q" 'bury-buffer)
+    (define-key map "q" #'bury-buffer)
     map)
   "Keymap for `widget-browse-mode'.")
 
diff --git a/lisp/wid-edit.el b/lisp/wid-edit.el
index e71290c..49baab6 100644
--- a/lisp/wid-edit.el
+++ b/lisp/wid-edit.el
@@ -750,7 +750,7 @@ automatically."
   :type 'boolean)
 
 (defcustom widget-image-conversion
-  '((xpm ".xpm") (gif ".gif") (png ".png") (jpeg ".jpg" ".jpeg")
+  '((svg ".svg") (xpm ".xpm") (gif ".gif") (png ".png") (jpeg ".jpg" ".jpeg")
     (xbm ".xbm"))
   "Conversion alist from image formats to file name suffixes."
   :group 'widgets
@@ -1878,20 +1878,9 @@ as the argument to `documentation-property'."
   (let ((value (widget-get widget :value)))
     (and (listp value)
         (<= (length value) (length vals))
-        (let ((head (widget-sublist vals 0 (length value))))
+         (let ((head (seq-subseq vals 0 (length value))))
           (and (equal head value)
-               (cons head (widget-sublist vals (length value))))))))
-
-(defun widget-sublist (list start &optional end)
-  "Return the sublist of LIST from START to END.
-If END is omitted, it defaults to the length of LIST."
-  (if (> start 0) (setq list (nthcdr start list)))
-  (if end
-      (unless (<= end start)
-       (setq list (copy-sequence list))
-       (setcdr (nthcdr (- end start 1) list) nil)
-       list)
-    (copy-sequence list)))
+                (cons head (seq-subseq vals (length value))))))))
 
 (defun widget-item-action (widget &optional event)
   ;; Just notify itself.
@@ -2575,9 +2564,9 @@ Return an alist of (TYPE MATCH)."
   :button-suffix ""
   :button-prefix ""
   :on "(*)"
-  :on-glyph "radio1"
+  :on-glyph "radio-checked"
   :off "( )"
-  :off-glyph "radio0")
+  :off-glyph "radio")
 
 (defun widget-radio-button-notify (widget _child &optional event)
   ;; Tell daddy.
@@ -4117,7 +4106,9 @@ is inline."
        (setq help-echo (funcall help-echo widget)))
     (if help-echo (message "%s" (eval help-echo)))))
 
-;;; The End:
+;;; Obsolete.
+
+(define-obsolete-function-alias 'widget-sublist #'seq-subseq "28.1")
 
 (provide 'wid-edit)
 
diff --git a/lisp/window.el b/lisp/window.el
index cfd9876..f27631b 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -4158,7 +4158,7 @@ returned by `window-start' and `window-point' 
respectively.
 
 This function is called only if `switch-to-buffer-preserve-window-point'
 evaluates non-nil."
-  (dolist (win (window-list))
+  (dolist (win (window-list nil 'no-minibuf))
     (let* ((buf   (window-buffer (or window win)))
            (start (window-start win))
            (pos   (window-point win))
@@ -4416,7 +4416,8 @@ WINDOW must be a live window and defaults to the selected 
one."
        window (assq-delete-all buffer (window-prev-buffers window))))
 
     ;; Don't record insignificant buffers.
-    (unless (eq (aref (buffer-name buffer) 0) ?\s)
+    (when (or (not (eq (aref (buffer-name buffer) 0) ?\s))
+              (minibufferp buffer))
       ;; Add an entry for buffer to WINDOW's previous buffers.
       (with-current-buffer buffer
        (let ((start (window-start window))
diff --git a/lisp/woman.el b/lisp/woman.el
index d4f7e8c..d9aa573 100644
--- a/lisp/woman.el
+++ b/lisp/woman.el
@@ -1,4 +1,4 @@
-;;; woman.el --- browse UN*X manual pages `wo (without) man'
+;;; woman.el --- browse UN*X manual pages `wo (without) man'  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2000-2021 Free Software Foundation, Inc.
 
@@ -388,8 +388,7 @@
 
 ;;; Code:
 
-(defvar woman-version "0.551 (beta)" "WoMan version information.")
-(make-obsolete-variable 'woman-version nil "28.1")
+(eval-when-compile (require 'cl-lib))
 
 (require 'man)
 (define-button-type 'WoMan-xref-man-page
@@ -418,14 +417,14 @@ As a special case, if PATHS is nil then replace it by 
calling
   ;; an empty substring of MANPATH denotes the default list.
   (if (memq system-type '(windows-nt ms-dos))
       (cond ((null paths)
-            (mapcar 'woman-Cyg-to-Win (woman-parse-man.conf)))
+            (mapcar #'woman-Cyg-to-Win (woman-parse-man.conf)))
            ((string-match-p ";" paths)
             ;; Assume DOS-style path-list...
             (mapcan                    ; splice list into list
              (lambda (x)
                (if x
                    (list x)
-                 (mapcar 'woman-Cyg-to-Win (woman-parse-man.conf))))
+                 (mapcar #'woman-Cyg-to-Win (woman-parse-man.conf))))
              (parse-colon-path paths)))
            ((string-match-p "\\`[a-zA-Z]:" paths)
             ;; Assume single DOS-style path...
@@ -434,7 +433,7 @@ As a special case, if PATHS is nil then replace it by 
calling
             ;; Assume UNIX/Cygwin-style path-list...
             (mapcan                    ; splice list into list
              (lambda (x)
-               (mapcar 'woman-Cyg-to-Win
+               (mapcar #'woman-Cyg-to-Win
                        (if x (list x) (woman-parse-man.conf))))
              (let ((path-separator ":"))
                (parse-colon-path paths)))))
@@ -509,7 +508,7 @@ Change only via `Customization' or the function `add-hook'."
 (defcustom woman-man.conf-path
   (let ((path '("/usr/lib" "/etc")))
     (cond ((eq system-type 'windows-nt)
-          (mapcar 'woman-Cyg-to-Win path))
+          (mapcar #'woman-Cyg-to-Win path))
          ((eq system-type 'darwin)
           (cons "/usr/share/misc" path))
          (t path)))
@@ -809,7 +808,7 @@ in the ncurses package include `toe.1m', `form.3x', etc.
 Note: an optional compression regexp will be appended, so this regexp
 MUST NOT end with any kind of string terminator such as $ or \\\\='."
   :type 'regexp
-  :set 'set-woman-file-regexp
+  :set #'set-woman-file-regexp
   :group 'woman-interface)
 
 (defcustom woman-file-compression-regexp
@@ -825,7 +824,7 @@ Should begin with \\. and end with \\\\=' and MUST NOT be 
optional."
   ;; not loaded by default!
   :version "24.1"                       ; added xz
   :type 'regexp
-  :set 'set-woman-file-regexp
+  :set #'set-woman-file-regexp
   :group 'woman-interface)
 
 (defcustom woman-use-own-frame nil
@@ -1186,7 +1185,7 @@ Called both to generate and to check the cache!"
              (setq dir (and (member (car dir) path) (cdr dir))))
            (when dir
               (cl-pushnew (substitute-in-file-name dir) lst :test #'equal))))
-       (mapcar 'substitute-in-file-name woman-path)))
+       (mapcar #'substitute-in-file-name woman-path)))
 
 (defun woman-read-directory-cache ()
   "Load the directory and topic cache.
@@ -1501,14 +1500,14 @@ Also make each path-info component into a list.
        (if (woman-not-member dir path) ; use each directory only once!
            (setq files (nconc files
                               (directory-files dir t topic-regexp))))))
-    (mapcar 'list files)))
+    (mapcar #'list files)))
 
 
 ;;; dired support
 
 (defun woman-dired-define-key (key)
   "Bind the argument KEY to the command `woman-dired-find-file'."
-  (define-key dired-mode-map key 'woman-dired-find-file))
+  (define-key dired-mode-map key #'woman-dired-find-file))
 
 (defsubst woman-dired-define-key-maybe (key)
   "If KEY is undefined in Dired, bind it to command `woman-dired-find-file'."
@@ -1520,7 +1519,7 @@ Also make each path-info component into a list.
   "Define dired keys to run WoMan according to `woman-dired-keys'."
   (if woman-dired-keys
       (if (listp woman-dired-keys)
-         (mapc 'woman-dired-define-key woman-dired-keys)
+         (mapc #'woman-dired-define-key woman-dired-keys)
        (woman-dired-define-key-maybe "w")
        (woman-dired-define-key-maybe "W")))
   (define-key-after (lookup-key dired-mode-map [menu-bar immediate])
@@ -1528,7 +1527,7 @@ Also make each path-info component into a list.
 
 (if (featurep 'dired)
     (woman-dired-define-keys)
-  (add-hook 'dired-mode-hook 'woman-dired-define-keys))
+  (add-hook 'dired-mode-hook #'woman-dired-define-keys))
 
 (declare-function dired-get-filename "dired"
                   (&optional localp no-error-if-not-filep))
@@ -1754,15 +1753,15 @@ Leave point at end of new text.  Return length of 
inserted text."
   (let ((map (make-sparse-keymap)))
     (set-keymap-parent map Man-mode-map)
 
-    (define-key map "R" 'woman-reformat-last-file)
-    (define-key map "w" 'woman)
-    (define-key map "\en" 'WoMan-next-manpage)
-    (define-key map "\ep" 'WoMan-previous-manpage)
-    (define-key map [M-mouse-2] 'woman-follow-word)
+    (define-key map "R" #'woman-reformat-last-file)
+    (define-key map "w" #'woman)
+    (define-key map "\en" #'WoMan-next-manpage)
+    (define-key map "\ep" #'WoMan-previous-manpage)
+    (define-key map [M-mouse-2] #'woman-follow-word)
 
     ;; We don't need to call `man' when we are in `woman-mode'.
-    (define-key map [remap man] 'woman)
-    (define-key map [remap man-follow] 'woman-follow)
+    (define-key map [remap man] #'woman)
+    (define-key map [remap man-follow] #'woman-follow)
     map)
   "Keymap for `woman-mode'.")
 
@@ -1865,23 +1864,13 @@ See `Man-mode' for additional details.
 \\{woman-mode-map}"
   ;; FIXME: Should all this just be re-arranged so that this can just
   ;; inherit `man-common' and be done with it?
-  (let ((Man-build-page-list (symbol-function 'Man-build-page-list))
-       (Man-strip-page-headers (symbol-function 'Man-strip-page-headers))
-       (Man-unindent (symbol-function 'Man-unindent))
-       (Man-goto-page (symbol-function 'Man-goto-page)))
+  (cl-letf (((symbol-function 'Man-build-page-list) #'ignore)
+           ((symbol-function 'Man-strip-page-headers) #'ignore)
+           ((symbol-function 'Man-unindent) #'ignore)
+           ((symbol-function 'Man-goto-page) #'ignore))
     ;; Prevent inappropriate operations:
-    (fset 'Man-build-page-list 'ignore)
-    (fset 'Man-strip-page-headers 'ignore)
-    (fset 'Man-unindent 'ignore)
-    (fset 'Man-goto-page 'ignore)
-    (unwind-protect
-       (delay-mode-hooks (Man-mode))
-      ;; Restore the status quo:
-      (fset 'Man-build-page-list Man-build-page-list)
-      (fset 'Man-strip-page-headers Man-strip-page-headers)
-      (fset 'Man-unindent Man-unindent)
-      (fset 'Man-goto-page Man-goto-page)
-      (setq tab-width woman-tab-width)))
+    (delay-mode-hooks (Man-mode)))
+  (setq tab-width woman-tab-width)
   (setq major-mode 'woman-mode
        mode-name "WoMan")
   ;; Don't show page numbers like Man-mode does.  (Online documents do
@@ -1892,7 +1881,7 @@ See `Man-mode' for additional details.
   (setq imenu-generic-expression woman-imenu-generic-expression)
   (setq-local imenu-space-replacement " ")
   ;; Bookmark support.
-  (setq-local bookmark-make-record-function 'woman-bookmark-make-record)
+  (setq-local bookmark-make-record-function #'woman-bookmark-make-record)
   ;; For reformat ...
   ;; necessary when reformatting a file in its old buffer:
   (setq imenu--last-menubar-index-alist nil)
@@ -2431,6 +2420,10 @@ Preserves location of `point'."
 
 (defvar woman0-rename-alist)           ; bound in woman0-roff-buffer
 
+;; Bound locally by woman[012]-roff-buffer, and woman0-macro.
+;; Use dynamically in woman-unquote and woman-forward-arg.
+(defvar woman-request)
+
 (defun woman0-roff-buffer (from)
   "Process conditional-type requests and user-defined macros.
 Start at FROM and re-scan new text as appropriate."
@@ -2750,15 +2743,16 @@ Optional argument APPEND, if non-nil, means append 
macro."
 
 ;; request may be used dynamically (woman-interpolate-macro calls
 ;; woman-forward-arg).
-(defun woman0-macro (woman-request)
-  "Process the macro call named WOMAN-REQUEST."
+(defun woman0-macro (request)
+  "Process the macro call named REQUEST."
   ;; Leaves point at start of new text.
-  (let ((macro (assoc woman-request woman0-macro-alist)))
+  (let ((woman-request request)
+        (macro (assoc request woman0-macro-alist)))
     (if macro
        (woman-interpolate-macro (cdr macro))
       ;; SHOULD DELETE THE UNINTERPRETED REQUEST!!!!!
       ;; Output this message once only per call (cf. strings)?
-      (WoMan-warn "Undefined macro %s not interpolated!" woman-request))))
+      (WoMan-warn "Undefined macro %s not interpolated!" request))))
 
 (defun woman-interpolate-macro (macro)
   "Interpolate (.de) or append (.am) expansion of MACRO into the buffer."
@@ -2982,11 +2976,6 @@ Useful for constructing the alist variable 
`woman-special-characters'."
 
 ;;; Formatting macros that do not cause a break:
 
-;; Bound locally by woman[012]-roff-buffer, and also, annoyingly and
-;; confusingly, as a function argument.  Use dynamically in
-;; woman-unquote and woman-forward-arg.
-(defvar woman-request)
-
 (defun woman-unquote (to)
   "Delete any double-quote characters between point and TO.
 Leave point at TO (which should be a marker)."
@@ -3067,7 +3056,7 @@ B-OR-I is the appropriate complete control line."
   ".SM -- Set the current line in small font, i.e. IGNORE!"
   nil)
 
-(defalias 'woman1-SB 'woman1-B)
+(defalias 'woman1-SB #'woman1-B)
 ;; .SB -- Set the current line in small bold font, i.e. just embolden!
 ;; (This is what /usr/local/share/groff/tmac/tmac.an does.  The
 ;; Linux man.7 is wrong about this!)
@@ -3197,27 +3186,27 @@ If optional arg CONCAT is non-nil then join arguments."
 ;;; Other non-breaking requests correctly ignored by nroff:
 
 (put 'woman1-ps 'notfont t)
-(defalias 'woman1-ps 'woman-delete-whole-line)
+(defalias 'woman1-ps #'woman-delete-whole-line)
   ;; .ps -- Point size -- IGNORE!
 
 (put 'woman1-ss 'notfont t)
-(defalias 'woman1-ss 'woman-delete-whole-line)
+(defalias 'woman1-ss #'woman-delete-whole-line)
   ;; .ss -- Space-character size -- IGNORE!
 
 (put 'woman1-cs 'notfont t)
-(defalias 'woman1-cs 'woman-delete-whole-line)
+(defalias 'woman1-cs #'woman-delete-whole-line)
   ;; .cs -- Constant character space (width) mode -- IGNORE!
 
 (put 'woman1-ne 'notfont t)
-(defalias 'woman1-ne 'woman-delete-whole-line)
+(defalias 'woman1-ne #'woman-delete-whole-line)
   ;; .ne -- Need vertical space -- IGNORE!
 
 (put 'woman1-vs 'notfont t)
-(defalias 'woman1-vs 'woman-delete-whole-line)
+(defalias 'woman1-vs #'woman-delete-whole-line)
   ;; .vs -- Vertical base line spacing -- IGNORE!
 
 (put 'woman1-bd 'notfont t)
-(defalias 'woman1-bd 'woman-delete-whole-line)
+(defalias 'woman1-bd #'woman-delete-whole-line)
   ;; .bd -- Embolden font -- IGNORE!
 
 ;;; Non-breaking SunOS-specific macros:
@@ -3228,7 +3217,7 @@ If optional arg CONCAT is non-nil then join arguments."
   (woman-forward-arg 'unquote 'concat))
 
 (put 'woman1-IX 'notfont t)
-(defalias 'woman1-IX 'woman-delete-whole-line)
+(defalias 'woman1-IX #'woman-delete-whole-line)
   ;; .IX -- Index macro, for Sun internal use -- IGNORE!
 
 
@@ -3577,7 +3566,7 @@ expression in parentheses.  Leaves point after the value."
                                  inc (cdr value)
                                  ;; eval internal (.X) registers
                                  ;; stored as lisp variable names:
-                                 value (eval (car value)))
+                                 value (eval (car value) t))
                            (if (and pm inc) ; auto-increment
                                (setq value
                                      (funcall (intern-soft pm) value inc)
@@ -3637,64 +3626,55 @@ expression in parentheses.  Leaves point after the 
value."
   "Process breaks.  Format paragraphs and headings."
   (let ((case-fold-search t)
        (to (make-marker))
-       (canonically-space-region
-        (symbol-function 'canonically-space-region))
-       (insert-and-inherit (symbol-function 'insert-and-inherit))
-       (set-text-properties (symbol-function 'set-text-properties))
        (woman-registers woman-registers)
        fn woman-request woman-translations
        tab-stop-list)
     (set-marker-insertion-type to t)
     ;; ?roff does not squeeze multiple spaces, but does fill, so...
-    (fset 'canonically-space-region 'ignore)
-    ;; Try to avoid spaces inheriting underlines from preceding text!
-    (fset 'insert-and-inherit (symbol-function 'insert))
-    (fset 'set-text-properties 'ignore)
-    (unwind-protect
-        (progn
-          (while
-              ;; Find next control line:
-              (re-search-forward woman-request-regexp nil t)
-            (cond
-             ;; Construct woman function to call:
-             ((setq fn (intern-soft
-                        (concat "woman2-"
-                                (setq woman-request (match-string 1)))))
-              ;; Delete request or macro name:
-              (woman-delete-match 0))
-             ;; Unrecognized request:
-             ((prog1 nil
-                ;; (WoMan-warn ".%s request ignored!" woman-request)
-                (WoMan-warn-ignored woman-request "ignored!")
-                ;; (setq fn 'woman2-LP)
-                ;; AVOID LEAVING A BLANK LINE!
-                ;; (setq fn 'woman2-format-paragraphs)
-                ))
-             ;; .LP assumes it is at eol and leaves a (blank) line,
-             ;; so leave point at end of line before paragraph:
-             ((or (looking-at "[ \t]*$") ; no argument
-                  woman-ignore)          ; ignore all
-              ;; (beginning-of-line) (kill-line)
-              ;; AVOID LEAVING A BLANK LINE!
-              (beginning-of-line) (woman-delete-line 1))
-             (t (end-of-line) (insert ?\n)))
-            (if (not (or fn
-                         (and (not (memq (following-char) '(?. ?')))
-                              (setq fn 'woman2-format-paragraphs))))
-                ()
-              ;; Find next control line:
-              (if (equal woman-request "TS")
-                  (set-marker to (woman-find-next-control-line "TE"))
-                (set-marker to (woman-find-next-control-line)))
-              ;; Call the appropriate function:
-              (funcall fn to)))
-          (if (not (eobp))             ; This should not happen, but ...
-              (woman2-format-paragraphs (copy-marker (point-max) t)
-                                        woman-left-margin)))
-      (fset 'canonically-space-region canonically-space-region)
-      (fset 'set-text-properties set-text-properties)
-      (fset 'insert-and-inherit insert-and-inherit)
-      (set-marker to nil))))
+    (cl-letf (((symbol-function 'canonically-space-region) #'ignore)
+              ;; Try to avoid spaces inheriting underlines from preceding text!
+              ((symbol-function 'insert-and-inherit) #'insert)
+              ((symbol-function 'set-text-properties) #'ignore))
+      (while
+          ;; Find next control line:
+          (re-search-forward woman-request-regexp nil t)
+        (cond
+         ;; Construct woman function to call:
+         ((setq fn (intern-soft
+                    (concat "woman2-"
+                            (setq woman-request (match-string 1)))))
+          ;; Delete request or macro name:
+          (woman-delete-match 0))
+         ;; Unrecognized request:
+         ((prog1 nil
+            ;; (WoMan-warn ".%s request ignored!" woman-request)
+            (WoMan-warn-ignored woman-request "ignored!")
+            ;; (setq fn 'woman2-LP)
+            ;; AVOID LEAVING A BLANK LINE!
+            ;; (setq fn 'woman2-format-paragraphs)
+            ))
+         ;; .LP assumes it is at eol and leaves a (blank) line,
+         ;; so leave point at end of line before paragraph:
+         ((or (looking-at "[ \t]*$")    ; no argument
+              woman-ignore)             ; ignore all
+          ;; (beginning-of-line) (kill-line)
+          ;; AVOID LEAVING A BLANK LINE!
+          (beginning-of-line) (woman-delete-line 1))
+         (t (end-of-line) (insert ?\n)))
+        (if (not (or fn
+                     (and (not (memq (following-char) '(?. ?')))
+                          (setq fn 'woman2-format-paragraphs))))
+            ()
+          ;; Find next control line:
+          (if (equal woman-request "TS")
+              (set-marker to (woman-find-next-control-line "TE"))
+            (set-marker to (woman-find-next-control-line)))
+          ;; Call the appropriate function:
+          (funcall fn to)))
+      (if (not (eobp))             ; This should not happen, but ...
+          (woman2-format-paragraphs (copy-marker (point-max) t)
+                                    woman-left-margin)))
+    (set-marker to nil)))
 
 (defun woman-find-next-control-line (&optional pat)
   "Find and return start of next control line.
@@ -3805,8 +3785,8 @@ Leave 1 blank line.  Format paragraphs upto TO."
   (setq woman-prevailing-indent woman-default-indent)
   (woman2-format-paragraphs to woman-left-margin))
 
-(defalias 'woman2-PP 'woman2-LP)
-(defalias 'woman2-P 'woman2-LP)
+(defalias 'woman2-PP #'woman2-LP)
+(defalias 'woman2-P #'woman2-LP)
 
 (defun woman2-ns (to)
   ".ns -- Turn on no-space mode.  Format paragraphs upto TO."
@@ -4277,16 +4257,16 @@ Set prevailing indent to amount of starting .RS."
 If no argument then use value of optional arg PREVIOUS if non-nil,
 otherwise set PREVIOUS.  Delete the whole remaining control line."
   (if (eolp)                           ; space already skipped
-      (set arg (if previous (eval previous) 0))
-    (if previous (set previous (eval arg)))
+      (set arg (if previous (symbol-value previous) 0))
+    (if previous (set previous (symbol-value arg)))
     (woman2-process-escapes-to-eol 'numeric)
     (let ((pm (if (looking-at "[+-]")
                (prog1 (following-char)
                  (forward-char 1))))
        (i (woman-parse-numeric-arg)))
     (cond ((null pm) (set arg i))
-         ((= pm ?+) (set arg (+ (eval arg) i)))
-         ((= pm ?-) (set arg (- (eval arg) i)))
+         ((= pm ?+) (set arg (+ (symbol-value arg) i)))
+         ((= pm ?-) (set arg (- (symbol-value arg) i)))
          ))
     (beginning-of-line))
   (woman-delete-line 1))               ; ignore any remaining arguments
@@ -4483,7 +4463,7 @@ Format paragraphs upto TO."
   (setq woman-nofill t)
   (woman2-format-paragraphs to))
 
-(defalias 'woman2-TE 'woman2-fi)
+(defalias 'woman2-TE #'woman2-fi)
   ;; ".TE -- End of table code for the tbl processor."
   ;; Turn filling and adjusting back on.
 
@@ -4597,6 +4577,11 @@ logging the message."
     (bookmark-default-handler
      `("" (buffer . ,buf) . ,(bookmark-get-bookmark-record bookmark)))))
 
+;; Obsolete.
+
+(defvar woman-version "0.551 (beta)" "WoMan version information.")
+(make-obsolete-variable 'woman-version 'emacs-version "28.1")
+
 (provide 'woman)
 
 ;;; woman.el ends here
diff --git a/lwlib/Makefile.in b/lwlib/Makefile.in
index fb0ae0e..ce77789 100644
--- a/lwlib/Makefile.in
+++ b/lwlib/Makefile.in
@@ -93,9 +93,9 @@ globals_h = ../src/globals.h
 $(globals_h):
        $(MAKE) -C ../src globals.h
 
-.PHONY: mostlyclean clean distclean bootstrap-clean maintainer-clean
+.PHONY: mostlyclean clean distclean bootstrap-clean maintainer-clean extraclean
 
-clean mostlyclean:
+clean mostlyclean extraclean:
        rm -f ./*.o liblw.a \#* $(DEPDIR)/*
 
 distclean: clean
diff --git a/src/coding.c b/src/coding.c
index 739dd6a..46e7fca 100644
--- a/src/coding.c
+++ b/src/coding.c
@@ -7799,7 +7799,13 @@ encode_coding (struct coding_system *coding)
     coding_set_source (coding);
     consume_chars (coding, translation_table, max_lookup);
     coding_set_destination (coding);
+    /* The CODING_MODE_LAST_BLOCK flag should be set only for the last
+       iteration of the encoding.  */
+    unsigned saved_mode = coding->mode;
+    if (coding->consumed_char < coding->src_chars)
+      coding->mode &= ~CODING_MODE_LAST_BLOCK;
     (*(coding->encoder)) (coding);
+    coding->mode = saved_mode;
   } while (coding->consumed_char < coding->src_chars);
 
   if (BUFFERP (coding->dst_object) && coding->produced_char > 0)
diff --git a/src/data.c b/src/data.c
index 0fa491b..3667b03 100644
--- a/src/data.c
+++ b/src/data.c
@@ -1589,6 +1589,7 @@ All writes to aliases of SYMBOL will call WATCH-FUNCTION 
too.  */)
   (Lisp_Object symbol, Lisp_Object watch_function)
 {
   symbol = Findirect_variable (symbol);
+  CHECK_SYMBOL (symbol);
   set_symbol_trapped_write (symbol, SYMBOL_TRAPPED_WRITE);
   map_obarray (Vobarray, harmonize_variable_watchers, symbol);
 
diff --git a/src/dispextern.h b/src/dispextern.h
index 742fac2..8f1d62b 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -3077,6 +3077,11 @@ struct image
      is created.  */
   unsigned long face_foreground, face_background;
 
+  /* Details of the font, only really relevant for types like SVG that
+     allow us to draw text. */
+  int face_font_size;
+  char *face_font_family;
+
   /* True if this image has a `transparent' background -- that is, is
      uses an image mask.  The accessor macro for this is
      `IMAGE_BACKGROUND_TRANSPARENT'.  */
diff --git a/src/filelock.c b/src/filelock.c
index 373fc00..446a262 100644
--- a/src/filelock.c
+++ b/src/filelock.c
@@ -719,8 +719,8 @@ lock_file (Lisp_Object fn)
     }
 }
 
-void
-unlock_file (Lisp_Object fn)
+static Lisp_Object
+unlock_file_body (Lisp_Object fn)
 {
   char *lfname;
   USE_SAFE_ALLOCA;
@@ -737,6 +737,23 @@ unlock_file (Lisp_Object fn)
     report_file_errno ("Unlocking file", filename, err);
 
   SAFE_FREE ();
+  return Qnil;
+}
+
+static Lisp_Object
+unlock_file_handle_error (Lisp_Object err)
+{
+  call1 (intern ("userlock--handle-unlock-error"), err);
+  return Qnil;
+}
+
+void
+unlock_file (Lisp_Object fn)
+{
+  internal_condition_case_1 (unlock_file_body,
+                            fn,
+                            list1(Qfile_error),
+                            unlock_file_handle_error);
 }
 
 #else  /* MSDOS */
@@ -790,7 +807,10 @@ DEFUN ("unlock-buffer", Funlock_buffer, Sunlock_buffer,
        0, 0, 0,
        doc: /* Unlock the file visited in the current buffer.
 If the buffer is not modified, this does nothing because the file
-should not be locked in that case.  */)
+should not be locked in that case.  It also does nothing if the
+current buffer is not visiting a file, or is not locked.  Handles file
+system errors by calling `display-warning' and continuing as if the
+error did not occur.  */)
   (void)
 {
   if (SAVE_MODIFF < MODIFF
diff --git a/src/fns.c b/src/fns.c
index 766e767..1758148 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -2279,6 +2279,52 @@ merge (Lisp_Object org_l1, Lisp_Object org_l2, 
Lisp_Object pred)
     }
 }
 
+Lisp_Object
+merge_c (Lisp_Object org_l1, Lisp_Object org_l2, bool (*less) (Lisp_Object, 
Lisp_Object))
+{
+  Lisp_Object l1 = org_l1;
+  Lisp_Object l2 = org_l2;
+  Lisp_Object tail = Qnil;
+  Lisp_Object value = Qnil;
+
+  while (1)
+    {
+      if (NILP (l1))
+       {
+         if (NILP (tail))
+           return l2;
+         Fsetcdr (tail, l2);
+         return value;
+       }
+      if (NILP (l2))
+       {
+         if (NILP (tail))
+           return l1;
+         Fsetcdr (tail, l1);
+         return value;
+       }
+
+      Lisp_Object tem;
+      if (less (Fcar (l1), Fcar (l2)))
+       {
+         tem = l1;
+         l1 = Fcdr (l1);
+         org_l1 = l1;
+       }
+      else
+       {
+         tem = l2;
+         l2 = Fcdr (l2);
+         org_l2 = l2;
+       }
+      if (NILP (tail))
+       value = tem;
+      else
+       Fsetcdr (tail, tem);
+      tail = tem;
+    }
+}
+
 
 /* This does not check for quits.  That is safe since it must terminate.  */
 
@@ -2323,7 +2369,10 @@ This is the last value stored with `(put SYMBOL PROPNAME 
VALUE)'.  */)
 DEFUN ("plist-put", Fplist_put, Splist_put, 3, 3, 0,
        doc: /* Change value in PLIST of PROP to VAL.
 PLIST is a property list, which is a list of the form
-\(PROP1 VALUE1 PROP2 VALUE2 ...).  PROP is a symbol and VAL is any object.
+\(PROP1 VALUE1 PROP2 VALUE2 ...).
+
+The comparison with PROP is done using `eq'.
+
 If PROP is already a property on the list, its value is set to VAL,
 otherwise the new PROP VAL pair is added.  The new plist is returned;
 use `(setq x (plist-put x prop val))' to be sure to use the new value.
@@ -3165,7 +3214,10 @@ suppressed.  */)
 DEFUN ("plist-member", Fplist_member, Splist_member, 2, 2, 0,
        doc: /* Return non-nil if PLIST has the property PROP.
 PLIST is a property list, which is a list of the form
-\(PROP1 VALUE1 PROP2 VALUE2 ...).  PROP is a symbol.
+\(PROP1 VALUE1 PROP2 VALUE2 ...).
+
+The comparison with PROP is done using `eq'.
+
 Unlike `plist-get', this allows you to distinguish between a missing
 property and a property with the value nil.
 The value is actually the tail of PLIST whose car is PROP.  */)
diff --git a/src/frame.c b/src/frame.c
index 417a45f..17e1b3f 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -1489,7 +1489,7 @@ do_switch_frame (Lisp_Object frame, int track, int 
for_deletion, Lisp_Object nor
 #endif
     internal_last_event_frame = Qnil;
 
-  move_minibuffer_onto_frame ();
+  move_minibuffers_onto_frame (sf, for_deletion);
   return frame;
 }
 
@@ -3747,6 +3747,17 @@ window state change flag is reset.  */)
   return (FRAME_WINDOW_STATE_CHANGE (f) = !NILP (arg)) ? Qt : Qnil;
 }
 
+DEFUN ("frame-scale-factor", Fframe_scale_factor, Sframe_scale_factor,
+       0, 1, 0,
+       doc: /* Return FRAMEs scale factor.
+The scale factor is the amount by which a logical pixel size must be
+multiplied to find the real number of pixels.  */)
+     (Lisp_Object frame)
+{
+  struct frame *f = decode_live_frame (frame);
+
+  return (make_float (f ? FRAME_SCALE_FACTOR (f) : 1));
+}
 
 /***********************************************************************
                                Frame Parameters
@@ -6480,6 +6491,7 @@ iconify the top level frame instead.  */);
   defsubr (&Sframe_pointer_visible_p);
   defsubr (&Sframe_window_state_change);
   defsubr (&Sset_frame_window_state_change);
+  defsubr (&Sframe_scale_factor);
 
 #ifdef HAVE_WINDOW_SYSTEM
   defsubr (&Sx_get_resource);
diff --git a/src/frame.h b/src/frame.h
index bb05448..ab7d3c5 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -916,6 +916,13 @@ default_pixels_per_inch_y (void)
   (WINDOWP (f->minibuffer_window)                              \
    && XFRAME (XWINDOW (f->minibuffer_window)->frame) == f)
 
+/* Scale factor of frame F.  */
+#if defined HAVE_NS
+# define FRAME_SCALE_FACTOR(f) (FRAME_NS_P (f) ? ns_frame_scale_factor (f) : 1)
+#else
+# define FRAME_SCALE_FACTOR(f) 1
+#endif
+
 /* Pixel width of frame F.  */
 #define FRAME_PIXEL_WIDTH(f) ((f)->pixel_width)
 
diff --git a/src/image.c b/src/image.c
index cf360c2..107670d 100644
--- a/src/image.c
+++ b/src/image.c
@@ -150,14 +150,6 @@ typedef struct pgtk_bitmap_record Bitmap_Record;
 # define COLOR_TABLE_SUPPORT 1
 #endif
 
-#ifdef HAVE_RSVG
-#if defined HAVE_NS
-# define FRAME_SCALE_FACTOR(f) ns_frame_scale_factor (f)
-#else
-# define FRAME_SCALE_FACTOR(f) 1;
-#endif
-#endif
-
 static void image_disable_image (struct frame *, struct image *);
 static void image_edge_detection (struct frame *, struct image *, Lisp_Object,
                                   Lisp_Object);
@@ -1329,6 +1321,7 @@ free_image (struct frame *f, struct image *img)
 
       /* Free resources, then free IMG.  */
       img->type->free_img (f, img);
+      xfree (img->face_font_family);
       xfree (img);
     }
 }
@@ -1727,7 +1720,7 @@ make_image_cache (void)
 static struct image *
 search_image_cache (struct frame *f, Lisp_Object spec, EMACS_UINT hash,
                     unsigned long foreground, unsigned long background,
-                    bool ignore_colors)
+                    int font_size, char *font_family, bool ignore_colors)
 {
   struct image *img;
   struct image_cache *c = FRAME_IMAGE_CACHE (f);
@@ -1751,7 +1744,10 @@ search_image_cache (struct frame *f, Lisp_Object spec, 
EMACS_UINT hash,
     if (img->hash == hash
        && !NILP (Fequal (img->spec, spec))
        && (ignore_colors || (img->face_foreground == foreground
-                              && img->face_background == background)))
+                              && img->face_background == background
+                             && img->face_font_size == font_size
+                             && (font_family
+                                 &&!strcmp (font_family, 
img->face_font_family)))))
       break;
   return img;
 }
@@ -1769,7 +1765,7 @@ uncache_image (struct frame *f, Lisp_Object spec)
      can have multiple copies of an image with the same spec. We want
      to remove them all to ensure the user doesn't see an old version
      of the image when the face changes.  */
-  while ((img = search_image_cache (f, spec, hash, 0, 0, true)))
+  while ((img = search_image_cache (f, spec, hash, 0, 0, 0, NULL, true)))
     {
       free_image (f, img);
       /* As display glyphs may still be referring to the image ID, we
@@ -2542,6 +2538,8 @@ lookup_image (struct frame *f, Lisp_Object spec, int 
face_id)
   struct face *face = FACE_FROM_ID (f, face_id);
   unsigned long foreground = FACE_COLOR_TO_PIXEL (face->foreground, f);
   unsigned long background = FACE_COLOR_TO_PIXEL (face->background, f);
+  int font_size = face->font->pixel_size;
+  char *font_family = SSDATA (face->lface[LFACE_FAMILY_INDEX]);
 
   /* F must be a window-system frame, and SPEC must be a valid image
      specification.  */
@@ -2550,7 +2548,8 @@ lookup_image (struct frame *f, Lisp_Object spec, int 
face_id)
 
   /* Look up SPEC in the hash table of the image cache.  */
   hash = sxhash (spec);
-  img = search_image_cache (f, spec, hash, foreground, background, false);
+  img = search_image_cache (f, spec, hash, foreground, background,
+                           font_size, font_family, false);
   if (img && img->load_failed_p)
     {
       free_image (f, img);
@@ -2565,6 +2564,9 @@ lookup_image (struct frame *f, Lisp_Object spec, int 
face_id)
       cache_image (f, img);
       img->face_foreground = foreground;
       img->face_background = background;
+      img->face_font_size = font_size;
+      img->face_font_family = xmalloc (strlen (font_family) + 1);
+      strcpy (img->face_font_family, font_family);
       img->load_failed_p = ! img->type->load_img (f, img);
 
       /* If we can't load the image, and we don't have a width and
@@ -9680,6 +9682,7 @@ enum svg_keyword_index
   SVG_DATA,
   SVG_FILE,
   SVG_BASE_URI,
+  SVG_CSS,
   SVG_ASCENT,
   SVG_MARGIN,
   SVG_RELIEF,
@@ -9700,6 +9703,7 @@ static const struct image_keyword svg_format[SVG_LAST] =
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":file",            IMAGE_STRING_VALUE,                     0},
   {":base-uri",                IMAGE_STRING_VALUE,                     0},
+  {":css",             IMAGE_STRING_VALUE,                     0},
   {":ascent",          IMAGE_ASCENT_VALUE,                     0},
   {":margin",          IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
@@ -9783,6 +9787,11 @@ DEF_DLL_FN (gboolean, rsvg_handle_get_geometry_for_layer,
            (RsvgHandle *, const char *, const RsvgRectangle *,
             RsvgRectangle *, RsvgRectangle *, GError **));
 #  endif
+
+#  if LIBRSVG_CHECK_VERSION (2, 48, 0)
+DEF_DLL_FN (gboolean, rsvg_handle_set_stylesheet,
+           (RsvgHandle *, const guint8 *, gsize, GError **));
+#  endif
 DEF_DLL_FN (void, rsvg_handle_get_dimensions,
            (RsvgHandle *, RsvgDimensionData *));
 DEF_DLL_FN (GdkPixbuf *, rsvg_handle_get_pixbuf, (RsvgHandle *));
@@ -9836,6 +9845,9 @@ init_svg_functions (void)
   LOAD_DLL_FN (library, rsvg_handle_get_intrinsic_dimensions);
   LOAD_DLL_FN (library, rsvg_handle_get_geometry_for_layer);
 #endif
+#if LIBRSVG_CHECK_VERSION (2, 48, 0)
+  LOAD_DLL_FN (library, rsvg_handle_set_stylesheet);
+#endif
   LOAD_DLL_FN (library, rsvg_handle_get_dimensions);
   LOAD_DLL_FN (library, rsvg_handle_get_pixbuf);
 
@@ -9876,6 +9888,9 @@ init_svg_functions (void)
 #   undef rsvg_handle_get_geometry_for_layer
 #  endif
 #  undef rsvg_handle_get_dimensions
+#  if LIBRSVG_CHECK_VERSION (2, 48, 0)
+#   undef rsvg_handle_set_stylesheet
+#  endif
 #  undef rsvg_handle_get_pixbuf
 #  if LIBRSVG_CHECK_VERSION (2, 32, 0)
 #   undef g_file_new_for_path
@@ -9909,6 +9924,9 @@ init_svg_functions (void)
        fn_rsvg_handle_get_geometry_for_layer
 #  endif
 #  define rsvg_handle_get_dimensions fn_rsvg_handle_get_dimensions
+#  if LIBRSVG_CHECK_VERSION (2, 48, 0)
+#   define rsvg_handle_set_stylesheet fn_rsvg_handle_set_stylesheet
+#  endif
 #  define rsvg_handle_get_pixbuf fn_rsvg_handle_get_pixbuf
 #  if LIBRSVG_CHECK_VERSION (2, 32, 0)
 #   define g_file_new_for_path fn_g_file_new_for_path
@@ -9986,7 +10004,7 @@ svg_load (struct frame *f, struct image *img)
 
 #if LIBRSVG_CHECK_VERSION (2, 46, 0)
 static double
-svg_css_length_to_pixels (RsvgLength length, double dpi)
+svg_css_length_to_pixels (RsvgLength length, double dpi, int font_size)
 {
   double value = length.length;
 
@@ -10014,9 +10032,16 @@ svg_css_length_to_pixels (RsvgLength length, double 
dpi)
     case RSVG_UNIT_IN:
       value *= dpi;
       break;
+#if LIBRSVG_CHECK_VERSION (2, 48, 0)
+      /* We don't know exactly what font size is used on older librsvg
+        versions.  */
+    case RSVG_UNIT_EM:
+      value *= font_size;
+      break;
+#endif
     default:
-      /* Probably one of em, ex, or %.  We can't know what the pixel
-         value is without more information.  */
+      /* Probably ex or %.  We can't know what the pixel value is
+         without more information.  */
       value = 0;
     }
 
@@ -10046,6 +10071,10 @@ svg_load_image (struct frame *f, struct image *img, 
char *contents,
   char *wrapped_contents = NULL;
   ptrdiff_t wrapped_size;
 
+#if LIBRSVG_CHECK_VERSION (2, 48, 0)
+  char *css = NULL;
+#endif
+
 #if ! GLIB_CHECK_VERSION (2, 36, 0)
   /* g_type_init is a glib function that must be called prior to
      using gnome type library functions (obsolete since 2.36.0).  */
@@ -10071,6 +10100,26 @@ svg_load_image (struct frame *f, struct image *img, 
char *contents,
 
   rsvg_handle_set_dpi_x_y (rsvg_handle, FRAME_DISPLAY_INFO (f)->resx,
                            FRAME_DISPLAY_INFO (f)->resy);
+
+#if LIBRSVG_CHECK_VERSION (2, 48, 0)
+  Lisp_Object lcss = image_spec_value (img->spec, QCcss, NULL);
+  if (!STRINGP (lcss))
+    {
+      /* Generate the CSS for the SVG image.  */
+      const char *css_spec = "svg{font-family:\"%s\";font-size:%4dpx}";
+      int css_len = strlen (css_spec) + strlen (img->face_font_family);
+      css = xmalloc (css_len);
+      snprintf (css, css_len, css_spec, img->face_font_family, 
img->face_font_size);
+      rsvg_handle_set_stylesheet (rsvg_handle, (guint8 *)css, strlen (css), 
NULL);
+    }
+  else
+    {
+      css = xmalloc (SBYTES (lcss) + 1);
+      strncpy (css, SSDATA (lcss), SBYTES (lcss));
+      *(css + SBYTES (lcss) + 1) = 0;
+    }
+#endif
+
 #else
   /* Make a handle to a new rsvg object.  */
   rsvg_handle = rsvg_handle_new ();
@@ -10113,20 +10162,20 @@ svg_load_image (struct frame *f, struct image *img, 
char *contents,
   if (has_width && has_height)
     {
       /* Success!  We can use these values directly.  */
-      viewbox_width = svg_css_length_to_pixels (iwidth, dpi);
-      viewbox_height = svg_css_length_to_pixels (iheight, dpi);
+      viewbox_width = svg_css_length_to_pixels (iwidth, dpi, 
img->face_font_size);
+      viewbox_height = svg_css_length_to_pixels (iheight, dpi, 
img->face_font_size);
     }
   else if (has_width && has_viewbox)
     {
-      viewbox_width = svg_css_length_to_pixels (iwidth, dpi);
-      viewbox_height = svg_css_length_to_pixels (iwidth, dpi)
-        * viewbox.width / viewbox.height;
+      viewbox_width = svg_css_length_to_pixels (iwidth, dpi, 
img->face_font_size);
+      viewbox_height = svg_css_length_to_pixels (iwidth, dpi, 
img->face_font_size)
+        * viewbox.height / viewbox.width;
     }
   else if (has_height && has_viewbox)
     {
-      viewbox_height = svg_css_length_to_pixels (iheight, dpi);
-      viewbox_width = svg_css_length_to_pixels (iheight, dpi)
-        * viewbox.height / viewbox.width;
+      viewbox_height = svg_css_length_to_pixels (iheight, dpi, 
img->face_font_size);
+      viewbox_width = svg_css_length_to_pixels (iheight, dpi, 
img->face_font_size)
+        * viewbox.width / viewbox.height;
     }
   else if (has_viewbox)
     {
@@ -10247,6 +10296,10 @@ svg_load_image (struct frame *f, struct image *img, 
char *contents,
 
   rsvg_handle_set_dpi_x_y (rsvg_handle, FRAME_DISPLAY_INFO (f)->resx,
                            FRAME_DISPLAY_INFO (f)->resy);
+
+#if LIBRSVG_CHECK_VERSION (2, 48, 0)
+  rsvg_handle_set_stylesheet (rsvg_handle, (guint8 *)css, strlen (css), NULL);
+#endif
 #else
   /* Make a handle to a new rsvg object.  */
   rsvg_handle = rsvg_handle_new ();
@@ -10280,6 +10333,11 @@ svg_load_image (struct frame *f, struct image *img, 
char *contents,
   g_object_unref (rsvg_handle);
   xfree (wrapped_contents);
 
+#if LIBRSVG_CHECK_VERSION (2, 48, 0)
+  if (!STRINGP (lcss))
+    xfree (css);
+#endif
+
   /* Extract some meta data from the svg handle.  */
   width     = gdk_pixbuf_get_width (pixbuf);
   height    = gdk_pixbuf_get_height (pixbuf);
@@ -10350,6 +10408,10 @@ svg_load_image (struct frame *f, struct image *img, 
char *contents,
     g_object_unref (rsvg_handle);
   if (wrapped_contents)
     xfree (wrapped_contents);
+#if LIBRSVG_CHECK_VERSION (2, 48, 0)
+  if (css && !STRINGP (lcss))
+    xfree (css);
+#endif
   /* FIXME: Use error->message so the user knows what is the actual
      problem with the image.  */
   image_error ("Error parsing SVG image `%s'", img->spec);
@@ -10941,6 +11003,7 @@ non-numeric, there is no explicit limit on the size of 
images.  */);
 #if defined (HAVE_RSVG)
   DEFSYM (Qsvg, "svg");
   DEFSYM (QCbase_uri, ":base-uri");
+  DEFSYM (QCcss, ":css");
   add_image_type (Qsvg);
 #ifdef HAVE_NTGUI
   /* Other libraries used directly by svg code.  */
diff --git a/src/lisp.h b/src/lisp.h
index b95f389..c67c8b0 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3610,6 +3610,7 @@ extern void validate_subarray (Lisp_Object, Lisp_Object, 
Lisp_Object,
 extern Lisp_Object substring_both (Lisp_Object, ptrdiff_t, ptrdiff_t,
                                   ptrdiff_t, ptrdiff_t);
 extern Lisp_Object merge (Lisp_Object, Lisp_Object, Lisp_Object);
+extern Lisp_Object merge_c (Lisp_Object, Lisp_Object, bool (*) (Lisp_Object, 
Lisp_Object));
 extern Lisp_Object do_yes_or_no_p (Lisp_Object);
 extern int string_version_cmp (Lisp_Object, Lisp_Object);
 extern Lisp_Object concat2 (Lisp_Object, Lisp_Object);
@@ -4348,7 +4349,7 @@ extern void clear_regexp_cache (void);
 
 extern Lisp_Object Vminibuffer_list;
 extern Lisp_Object last_minibuf_string;
-extern void move_minibuffer_onto_frame (void);
+extern void move_minibuffers_onto_frame (struct frame *, bool);
 extern bool is_minibuffer (EMACS_INT, Lisp_Object);
 extern EMACS_INT this_minibuffer_depth (Lisp_Object);
 extern EMACS_INT minibuf_level;
diff --git a/src/minibuf.c b/src/minibuf.c
index 4b1f4b1..c9831fd 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -59,6 +59,12 @@ Lisp_Object last_minibuf_string;
 
 static Lisp_Object minibuf_prompt;
 
+/* The frame containinug the most recently opened Minibuffer.  This is
+   used only when `minibuffer-follows-selected-frame' is neither nil
+   nor t.  */
+
+static Lisp_Object MB_frame;
+
 /* Width of current mini-buffer prompt.  Only set after display_line
    of the line that contains the prompt.  */
 
@@ -67,6 +73,7 @@ static ptrdiff_t minibuf_prompt_width;
 static Lisp_Object nth_minibuffer (EMACS_INT depth);
 static EMACS_INT minibuf_c_loop_level (EMACS_INT depth);
 static void set_minibuffer_mode (Lisp_Object buf, EMACS_INT depth);
+static bool live_minibuffer_p (Lisp_Object);
 
 
 /* Return TRUE when a frame switch causes a minibuffer on the old
@@ -78,6 +85,7 @@ minibuf_follows_frame (void)
              Qt);
 }
 
+#if 0
 /* Return TRUE when a minibuffer always remains on the frame where it
    was first invoked. */
 static bool
@@ -85,6 +93,7 @@ minibuf_stays_put (void)
 {
   return NILP (Fdefault_toplevel_value (Qminibuffer_follows_selected_frame));
 }
+#endif
 
 /* Return TRUE when opening a (recursive) minibuffer causes
    minibuffers on other frames to move to the selected frame.  */
@@ -112,84 +121,85 @@ choose_minibuf_frame (void)
        emacs_abort ();
 
       minibuf_window = sf->minibuffer_window;
-      /* If we've still got another minibuffer open, use its mini-window
-         instead.  */
-      if (minibuf_level > 1 && minibuf_stays_put ())
-        {
-          Lisp_Object buffer = get_minibuffer (minibuf_level);
-          Lisp_Object tail, frame;
-
-          FOR_EACH_FRAME (tail, frame)
-            if (EQ (XWINDOW (XFRAME (frame)->minibuffer_window)->contents,
-                    buffer))
-              {
-                minibuf_window = XFRAME (frame)->minibuffer_window;
-                break;
-              }
-        }
     }
+}
 
-  if (minibuf_moves_frame_when_opened ()
-      && FRAMEP (selected_frame)
-      && FRAME_LIVE_P (XFRAME (selected_frame)))
-    /* Make sure no other frame has a minibuffer as its selected window,
-       because the text would not be displayed in it, and that would be
-       confusing.  Only allow the selected frame to do this,
-       and that only if the minibuffer is active.  */
-  {
-    Lisp_Object tail, frame;
-    struct frame *of;
-
-    FOR_EACH_FRAME (tail, frame)
-      if (!EQ (frame, selected_frame)
-          && minibuf_level > 1
-         /* The frame's minibuffer can be on a different frame.  */
-         && ! EQ (XWINDOW ((of = XFRAME (frame))->minibuffer_window)->frame,
-                  selected_frame))
-        {
-          if (MINI_WINDOW_P (XWINDOW (FRAME_SELECTED_WINDOW (of))))
-            Fset_frame_selected_window (frame, Fframe_first_window (frame),
-                                        Qnil);
-
-          if (!EQ (XWINDOW (of->minibuffer_window)->contents,
-                   nth_minibuffer (0)))
-            set_window_buffer (of->minibuffer_window,
-                               nth_minibuffer (0), 0, 0);
-        }
-  }
+/* If ENT1 has a higher minibuffer index than ENT2, return true.  More
+precisely, compare the buffer components of each window->prev_buffers
+entry.  */
+static bool
+minibuffer_ent_greater (Lisp_Object ent1, Lisp_Object ent2)
+{
+  return this_minibuffer_depth (Fcar (ent1))
+    > this_minibuffer_depth (Fcar (ent2)) ;
 }
 
-/* If `minibuffer_follows_selected_frame' is t and we have a
-   minibuffer, move it from its current frame to the selected frame.
-   This function is intended to be called from `do_switch_frame' in
-   frame.c.  */
-void move_minibuffer_onto_frame (void)
+/* Move the ordered "stack" of minibuffers from SOURCE_WINDOW to
+   DEST_WINDOW, interleaving those minibuffers with any in DEST_WINDOW
+   to produce an ordered combination.  The ordering is by minibuffer
+   depth.  A stack of minibuffers consists of the minibuffer currently
+   in DEST/SOURCE_WINDOW together with any recorded in the
+   ->prev_buffers field of the struct window.  */
+static void
+zip_minibuffer_stacks (Lisp_Object dest_window, Lisp_Object source_window)
 {
-  if (!minibuf_level)
-    return;
-  if (!minibuf_follows_frame ())
-    return;
-  if (FRAMEP (selected_frame)
-      && FRAME_LIVE_P (XFRAME (selected_frame))
-      && !EQ (minibuf_window, XFRAME (selected_frame)->minibuffer_window))
+  struct window *dw = XWINDOW (dest_window);
+  struct window *sw = XWINDOW (source_window);
+  Lisp_Object acc;
+  Lisp_Object d_ent;   /* Entry from dw->prev_buffers */
+
+  if (!live_minibuffer_p (dw->contents)
+      && NILP (dw->prev_buffers))
     {
-      EMACS_INT i;
-      struct frame *sf = XFRAME (selected_frame);
-      Lisp_Object old_frame = XWINDOW (minibuf_window)->frame;
-      struct frame *of = XFRAME (old_frame);
+      set_window_buffer (dest_window, sw->contents, 0, 0);
+      Fset_window_start (dest_window, Fwindow_start (source_window), Qnil);
+      Fset_window_point (dest_window, Fwindow_point (source_window));
+      dw->prev_buffers = sw->prev_buffers;
+      set_window_buffer (source_window, get_minibuffer (0), 0, 0);
+      sw->prev_buffers = Qnil;
+      return;
+    }
 
-      /* Stack up all the (recursively) open minibuffers on the selected
-         mini_window.  */
-      for (i = 1; i <= minibuf_level; i++)
-       set_window_buffer (sf->minibuffer_window, nth_minibuffer (i), 0, 0);
-      minibuf_window = sf->minibuffer_window;
-      if (of != sf)
-       {
-         Lisp_Object temp = get_minibuffer (0);
+  if (live_minibuffer_p (dw->contents))
+    call1 (Qrecord_window_buffer, dest_window);
+  if (live_minibuffer_p (sw->contents))
+    call1 (Qrecord_window_buffer, source_window);
 
-         set_window_buffer (of->minibuffer_window, temp, 0, 0);
-         set_minibuffer_mode (temp, 0);
-       }
+  acc = merge_c (dw->prev_buffers, sw->prev_buffers, minibuffer_ent_greater);
+
+  if (!NILP (acc))
+    {
+      d_ent = Fcar (acc);
+      acc = Fcdr (acc);
+      set_window_buffer (dest_window, Fcar (d_ent), 0, 0);
+      Fset_window_start (dest_window, Fcar (Fcdr (d_ent)), Qnil);
+      Fset_window_point (dest_window, Fcar (Fcdr (Fcdr (d_ent))));
+    }
+  dw->prev_buffers = acc;
+  sw->prev_buffers = Qnil;
+  set_window_buffer (source_window, get_minibuffer (0), 0, 0);
+}
+
+/* If `minibuffer_follows_selected_frame' is t, or we're about to
+   delete a frame which potentially "contains" minibuffers, move them
+   from the old frame to the selected frame.  This function is
+   intended to be called from `do_switch_frame' in frame.c.  OF is the
+   old frame, FOR_DELETION is true if OF is about to be deleted.  */
+void
+move_minibuffers_onto_frame (struct frame *of, bool for_deletion)
+{
+  struct frame *f = XFRAME (selected_frame);
+
+  minibuf_window = f->minibuffer_window;
+  if (!(minibuf_level
+       && (for_deletion || minibuf_follows_frame () || FRAME_INITIAL_P (of))))
+    return;
+  if (FRAME_LIVE_P (f)
+      && !EQ (f->minibuffer_window, of->minibuffer_window))
+    {
+      zip_minibuffer_stacks (f->minibuffer_window, of->minibuffer_window);
+      if (for_deletion && XFRAME (MB_frame) != of)
+       MB_frame = selected_frame;
     }
 }
 
@@ -221,6 +231,7 @@ without invoking the usual minibuffer commands.  */)
 /* Actual minibuffer invocation.  */
 
 static void read_minibuf_unwind (void);
+static void minibuffer_unwind (void);
 static void run_exit_minibuf_hook (void);
 
 
@@ -544,7 +555,6 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, 
Lisp_Object prompt,
   Lisp_Object histval;
 
   Lisp_Object empty_minibuf;
-  Lisp_Object dummy, frame;
 
   specbind (Qminibuffer_default, defalt);
   specbind (Qinhibit_read_only, Qnil);
@@ -626,17 +636,24 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, 
Lisp_Object prompt,
   mini_frame = WINDOW_FRAME (XWINDOW (minibuf_window));
 
   if (minibuf_level > 1
+      && !EQ (XWINDOW (XFRAME (selected_frame)->minibuffer_window)->frame,
+             MB_frame)
       && minibuf_moves_frame_when_opened ()
-      && (!minibuf_follows_frame ()
-         || (!EQ (mini_frame, selected_frame))))
+      && (!minibuf_follows_frame ()))
     {
-      EMACS_INT i;
+      struct frame *of = XFRAME (MB_frame);
 
-      /* Stack up the existing minibuffers on the current mini-window */
-      for (i = 1; i < minibuf_level; i++)
-       set_window_buffer (minibuf_window, nth_minibuffer (i), 0, 0);
+      zip_minibuffer_stacks (minibuf_window, of->minibuffer_window);
+      /* MB_frame's minibuffer can be on a different frame.  */
+      if (MINI_WINDOW_P (XWINDOW (FRAME_SELECTED_WINDOW (of))))
+       Fset_frame_selected_window (MB_frame,
+                                   Fframe_first_window (MB_frame), Qnil);
     }
+  MB_frame = XWINDOW (XFRAME (selected_frame)->minibuffer_window)->frame;
+  if (live_minibuffer_p (XWINDOW (minibuf_window)->contents))
+    call1 (Qrecord_window_buffer, minibuf_window);
 
+  record_unwind_protect_void (minibuffer_unwind);
   record_unwind_protect (restore_window_configuration,
                          Fcons (Qt, Fcurrent_window_configuration (Qnil)));
 
@@ -771,23 +788,6 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, 
Lisp_Object prompt,
   empty_minibuf = get_minibuffer (0);
   set_minibuffer_mode (empty_minibuf, 0);
 
-  FOR_EACH_FRAME (dummy, frame)
-    {
-      Lisp_Object root_window = Fframe_root_window (frame);
-      Lisp_Object mini_window = XWINDOW (root_window)->next;
-      Lisp_Object buffer;
-
-      if (!NILP (mini_window) && !EQ (mini_window, minibuf_window)
-          && !NILP (Fwindow_minibuffer_p (mini_window)))
-        {
-          buffer = XWINDOW (mini_window)->contents;
-          if (!live_minibuffer_p (buffer))
-            /* Use set_window_buffer instead of Fset_window_buffer (see
-               discussion of bug#11984, bug#12025, bug#12026).  */
-            set_window_buffer (mini_window, empty_minibuf, 0, 0);
-        }
-    }
-
   /* Display this minibuffer in the proper window.  */
   /* Use set_window_buffer instead of Fset_window_buffer (see
      discussion of bug#11984, bug#12025, bug#12026).  */
@@ -908,7 +908,9 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, 
Lisp_Object prompt,
   unbind_to (count, Qnil);
 
   /* Switch the frame back to the calling frame.  */
-  if (!EQ (selected_frame, calling_frame)
+  if ((!EQ (selected_frame, calling_frame)
+       || !EQ (XWINDOW (XFRAME (calling_frame)->minibuffer_window)->frame,
+              calling_frame))
       && FRAMEP (calling_frame)
       && FRAME_LIVE_P (XFRAME (calling_frame)))
     call2 (intern ("select-frame-set-input-focus"), calling_frame, Qnil);
@@ -1026,6 +1028,14 @@ run_exit_minibuf_hook (void)
   safe_run_hooks (Qminibuffer_exit_hook);
 }
 
+/* This variable records the expired minibuffer's frame between the
+   calls of `read_minibuf_unwind' and `minibuffer_unwind'.  It should
+   be used only by these two functions.  Note that the same search
+   method for the MB's frame won't always work in `minibuffer_unwind'
+   because the intervening `restore-window-configuration' will have
+   changed the buffer in the mini-window.  */
+static Lisp_Object exp_MB_frame;
+
 /* This function is called on exiting minibuffer, whether normally or
    not, and it restores the current window, buffer, etc.  */
 
@@ -1036,6 +1046,28 @@ read_minibuf_unwind (void)
   Lisp_Object calling_frame;
   Lisp_Object calling_window;
   Lisp_Object future_mini_window;
+  Lisp_Object saved_selected_frame = selected_frame;
+  Lisp_Object window, frames;
+  struct window *w;
+  struct frame *f;
+
+  /* Locate the expired minibuffer.  */
+  FOR_EACH_FRAME (frames, exp_MB_frame)
+    {
+      f = XFRAME (exp_MB_frame);
+      window = f->minibuffer_window;
+      w = XWINDOW (window);
+      if (EQ (w->frame, exp_MB_frame)
+         && EQ (w->contents, nth_minibuffer (minibuf_level)))
+       goto found;
+    }
+  return; /* expired minibuffer not found.  Maybe we should output an
+            error, here. */
+
+ found:
+  if (!EQ (exp_MB_frame, saved_selected_frame))
+    do_switch_frame (exp_MB_frame, 0, 0, Qt); /* This also sets
+                                            minibuff_window */
 
   /* To keep things predictable, in case it matters, let's be in the
      minibuffer when we reset the relevant variables.  Don't depend on
@@ -1127,20 +1159,61 @@ read_minibuf_unwind (void)
      away from the expired minibuffer window, both in the current
      minibuffer's frame and the original calling frame.  */
   choose_minibuf_frame ();
-  if (!EQ (WINDOW_FRAME (XWINDOW (minibuf_window)), calling_frame))
-  {
-    Lisp_Object prev = Fprevious_window (minibuf_window, Qnil, Qnil);
-    /* PREV can be on a different frame when we have a minibuffer only
-       frame, the other frame's minibuffer window is MINIBUF_WINDOW,
-       and its "focus window" is also MINIBUF_WINDOW.  */
-    if (!EQ (prev, minibuf_window)
-       && EQ (WINDOW_FRAME (XWINDOW (prev)),
-              WINDOW_FRAME (XWINDOW (minibuf_window))))
-      Fset_frame_selected_window (selected_frame, prev, Qnil);
-  }
-  else
-    Fset_frame_selected_window (calling_frame, calling_window, Qnil);
+  if (NILP (XWINDOW (minibuf_window)->prev_buffers))
+    {
+      if (!EQ (WINDOW_FRAME (XWINDOW (minibuf_window)), calling_frame))
+       {
+         Lisp_Object prev = Fprevious_window (minibuf_window, Qnil, Qnil);
+         /* PREV can be on a different frame when we have a minibuffer only
+            frame, the other frame's minibuffer window is MINIBUF_WINDOW,
+            and its "focus window" is also MINIBUF_WINDOW.  */
+         if (!EQ (prev, minibuf_window)
+             && EQ (WINDOW_FRAME (XWINDOW (prev)),
+                    WINDOW_FRAME (XWINDOW (minibuf_window))))
+           Fset_frame_selected_window (selected_frame, prev, Qnil);
+       }
+      else
+       Fset_frame_selected_window (calling_frame, calling_window, Qnil);
+    }
+
+  /* Restore the selected frame. */
+  if (!EQ (exp_MB_frame, saved_selected_frame))
+    do_switch_frame (saved_selected_frame, 0, 0, Qt);
+}
+
+/* Replace the expired minibuffer in frame exp_MB_frame with the next less
+   nested minibuffer in that frame, if any.  Otherwise, replace it
+   with the null minibuffer.  MINIBUF_WINDOW is not changed.  */
+static void
+minibuffer_unwind (void)
+{
+  struct frame *f;
+  struct window *w;
+  Lisp_Object window;
+  Lisp_Object entry;
+
+  f = XFRAME (exp_MB_frame);
+  window = f->minibuffer_window;
+  w = XWINDOW (window);
+  if (FRAME_LIVE_P (f))
+    {
+      /* minibuf_window = sf->minibuffer_window; */
+      if (!NILP (w->prev_buffers))
+       {
+         entry = Fcar (w->prev_buffers);
+         w->prev_buffers = Fcdr (w->prev_buffers);
+         set_window_buffer (window, Fcar (entry), 0, 0);
+         Fset_window_start (window, Fcar (Fcdr (entry)), Qnil);
+         Fset_window_point (window, Fcar (Fcdr (Fcdr (entry))));
+         /* set-window-configuration may/will have unselected the
+            mini-window as the selected window.  Restore it. */
+         Fset_frame_selected_window (exp_MB_frame, window, Qnil);
+       }
+      else
+       set_window_buffer (window, nth_minibuffer (0), 0, 0);
+    }
 }
+
 
 
 void
@@ -1417,8 +1490,8 @@ function, instead of the usual behavior.  */)
                                              STRING_MULTIBYTE (prompt));
            }
 
-         AUTO_STRING (format, "%s (default %s): ");
-         prompt = CALLN (Fformat, format, prompt,
+         prompt = CALLN (Ffuncall, intern("format-prompt"),
+                         prompt,
                          CONSP (def) ? XCAR (def) : def);
        }
 
@@ -2213,6 +2286,9 @@ syms_of_minibuf (void)
 {
   staticpro (&minibuf_prompt);
   staticpro (&minibuf_save_list);
+  staticpro (&MB_frame);
+  MB_frame = Qnil;
+  staticpro (&exp_MB_frame);
 
   DEFSYM (Qminibuffer_follows_selected_frame,
           "minibuffer-follows-selected-frame");
diff --git a/src/nsterm.m b/src/nsterm.m
index bf175bb..a650110 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -9790,7 +9790,7 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c)
   IOSurfaceRef surface = NULL;
 
   NSTRACE ("[EmacsSurface getContextWithSize:]");
-  NSTRACE_MSG (@"IOSurface count: %lu", [cache count] + (lastSurface ? 1 : 0));
+  NSTRACE_MSG ("IOSurface count: %lu", [cache count] + (lastSurface ? 1 : 0));
 
   for (id object in cache)
     {
diff --git a/src/pdumper.c b/src/pdumper.c
index 337742f..d32a147 100644
--- a/src/pdumper.c
+++ b/src/pdumper.c
@@ -162,11 +162,7 @@ ptrdiff_t_to_dump_off (ptrdiff_t value)
 static int
 dump_get_page_size (void)
 {
-#if defined (WINDOWSNT) || defined (CYGWIN)
-  return 64 * 1024;  /* Worst-case allocation granularity.  */
-#else
-  return getpagesize ();
-#endif
+  return 64 * 1024;
 }
 
 #define dump_offsetof(type, member)                             \
@@ -5467,9 +5463,6 @@ Value is nil if this session was not started using a dump 
file.*/)
                Fcons (Qdump_file_name, dump_fn));
 }
 
-#endif /* HAVE_PDUMPER */
-
-
 static void
 thaw_hash_tables (void)
 {
@@ -5478,10 +5471,15 @@ thaw_hash_tables (void)
     hash_table_thaw (AREF (hash_tables, i));
 }
 
+#endif /* HAVE_PDUMPER */
+
+
 void
 init_pdumper_once (void)
 {
+#ifdef HAVE_PDUMPER
   pdumper_do_now_and_after_load (thaw_hash_tables);
+#endif
 }
 
 void
diff --git a/src/window.c b/src/window.c
index eb16e2a..4d5c7e7 100644
--- a/src/window.c
+++ b/src/window.c
@@ -6958,7 +6958,8 @@ the return value is nil.  Otherwise the value is t.  */)
 
          if (BUFFERP (w->contents)
              && !EQ (w->contents, p->buffer)
-             && BUFFER_LIVE_P (XBUFFER (p->buffer)))
+             && BUFFER_LIVE_P (XBUFFER (p->buffer))
+             && (NILP (Fminibufferp (p->buffer, Qnil))))
            /* If a window we restore gets another buffer, record the
               window's old buffer.  */
            call1 (Qrecord_window_buffer, window);
diff --git a/src/xdisp.c b/src/xdisp.c
index dc165c8..82c9dc0 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -12650,9 +12650,8 @@ gui_consider_frame_title (Lisp_Object frame)
         mode_line_noprop_buf; then display the title.  */
       record_unwind_protect (unwind_format_mode_line,
                             format_mode_line_unwind_data
-                              (f, current_buffer, selected_window, false));
+                            (NULL, current_buffer, Qnil, false));
 
-      Fselect_window (f->selected_window, Qt);
       set_buffer_internal_1
        (XBUFFER (XWINDOW (f->selected_window)->contents));
       fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format;
diff --git a/src/xfns.c b/src/xfns.c
index d906448..0507dc8 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -2783,7 +2783,7 @@ xic_set_preeditarea (struct window *w, int x, int y)
   XVaNestedList attr;
   XPoint spot;
 
-  spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x) + WINDOW_LEFT_FRINGE_WIDTH (w);
+  spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x) + WINDOW_LEFT_FRINGE_WIDTH (w) + 
WINDOW_LEFT_MARGIN_WIDTH(w);
   spot.y = WINDOW_TO_FRAME_PIXEL_Y (w, y) + FONT_BASE (FRAME_FONT (f));
   attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL);
   XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
diff --git a/test/infra/Dockerfile.emba b/test/infra/Dockerfile.emba
index cde657a..19c83a8 100644
--- a/test/infra/Dockerfile.emba
+++ b/test/infra/Dockerfile.emba
@@ -47,7 +47,8 @@ RUN make -j4
 FROM emacs-base as emacs-filenotify-gio
 
 RUN apt-get update && \
-    apt-get install -y --no-install-recommends -o=Dpkg::Use-Pty=0 
libglib2.0-dev libglib2.0-bin libglib2.0-0 \
+    apt-get install -y --no-install-recommends -o=Dpkg::Use-Pty=0 \
+      libglib2.0-dev libglib2.0-bin libglib2.0-0 \
     && rm -rf /var/lib/apt/lists/*
 
 COPY . /checkout
@@ -67,5 +68,5 @@ COPY . /checkout
 WORKDIR /checkout
 RUN ./autogen.sh autoconf
 RUN ./configure --with-ns
-RUN make -j4 bootstrap
+RUN make bootstrap
 RUN make -j4
diff --git a/test/infra/gitlab-ci.yml b/test/infra/gitlab-ci.yml
index 5a0ab54..6355513 100644
--- a/test/infra/gitlab-ci.yml
+++ b/test/infra/gitlab-ci.yml
@@ -61,6 +61,8 @@ default:
     - docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} 
${CI_REGISTRY}
 
 .job-template:
+  variables:
+    test_name: ${CI_JOB_NAME}-${CI_COMMIT_SHORT_SHA}
   rules:
     - changes:
         - "**/Makefile.in"
@@ -95,14 +97,18 @@ default:
   artifacts:
     expire_in: 24 hrs
     paths: []
-      # - "test/**/*.log"
-      # - "**/*.log"
   # using the variables for each job
   script:
     - docker pull ${CI_REGISTRY_IMAGE}:${target}-${BUILD_TAG}
     # TODO: with make -j4 several of the tests were failing, for example 
shadowfile-tests, but passed without it
     - 'export PWD=$(pwd)'
-    - 'docker run -i --rm -e EMACS_EMBA_CI=${EMACS_EMBA_CI} --volumes-from 
$(docker ps -q -f "label=com.gitlab.gitlab-runner.job.id=${CI_JOB_ID}"):ro 
${CI_REGISTRY_IMAGE}:${target}-${BUILD_TAG} /bin/bash -c "git fetch ${PWD} HEAD 
&& echo checking out these updated files && git diff --name-only FETCH_HEAD && 
( git diff --name-only FETCH_HEAD | xargs git checkout -f FETCH_HEAD ) && make 
-j4 && make ${make_params}"'
+    - 'docker run -i -e EMACS_EMBA_CI=${EMACS_EMBA_CI} --volumes-from $(docker 
ps -q -f "label=com.gitlab.gitlab-runner.job.id=${CI_JOB_ID}"):ro --name 
${test_name} ${CI_REGISTRY_IMAGE}:${target}-${BUILD_TAG} /bin/bash -c "git 
fetch ${PWD} HEAD && echo checking out these updated files && git diff 
--name-only FETCH_HEAD && ( git diff --name-only FETCH_HEAD | xargs git 
checkout -f FETCH_HEAD ) && make -j4 && make ${make_params}"'
+  after_script:
+    # - docker ps -a
+    # - printenv
+    # - test -n "$(docker ps -aq -f name=${test_name})" && ( docker export 
${test_name} | tar -tvf - )
+    - test -n "$(docker ps -aq -f name=${test_name})" && docker cp 
${test_name}:checkout/test ${test_name}
+    - test -n "$(docker ps -aq -f name=${test_name})" && docker rm ${test_name}
 
 .build-template:
   rules:
@@ -133,6 +139,19 @@ default:
     - docker build --pull --target ${target} -t 
${CI_REGISTRY_IMAGE}:${target}-${BUILD_TAG} -f test/infra/Dockerfile.emba .
     - docker push ${CI_REGISTRY_IMAGE}:${target}-${BUILD_TAG}
 
+.test-template:
+  # Do not run fast and normal test jobs when scheduled
+  rules:
+    - if: '$CI_JOB_STAGE =~ "fast|normal" && $CI_PIPELINE_SOURCE == "schedule"'
+      when: never
+    - when: always
+  artifacts:
+    name: ${test_name}
+    public: true
+    expire_in: 1 week
+    paths:
+      - "${test_name}/**/*.log"
+
 .gnustep-template:
   rules:
     - if: '$CI_PIPELINE_SOURCE == "web"'
@@ -185,7 +204,7 @@ build-image-inotify:
 
 test-fast-inotify:
   stage: fast
-  extends: [.job-template]
+  extends: [.job-template, .test-template]
   variables:
     target: emacs-inotify
     make_params: "-C test check"
@@ -204,14 +223,14 @@ build-image-gnustep:
 
 test-lisp-inotify:
   stage: normal
-  extends: [.job-template]
+  extends: [.job-template, .test-template]
   variables:
     target: emacs-inotify
     make_params: "-C test check-lisp"
 
 test-lisp-net-inotify:
   stage: normal
-  extends: [.job-template]
+  extends: [.job-template, .test-template]
   variables:
     target: emacs-inotify
     make_params: "-C test check-lisp-net"
@@ -219,10 +238,10 @@ test-lisp-net-inotify:
 test-filenotify-gio:
   # This tests file monitor libraries gfilemonitor and gio.
   stage: platforms
-  extends: [.job-template, .filenotify-gio-template]
+  extends: [.job-template, .test-template, .filenotify-gio-template]
   variables:
     target: emacs-filenotify-gio
-    make_params: "-k -C test autorevert-tests filenotify-tests"
+    make_params: "-k -C test autorevert-tests.log filenotify-tests.log"
 
 test-gnustep:
   # This tests the GNUstep build process
@@ -235,7 +254,7 @@ test-gnustep:
 test-all-inotify:
   # This tests also file monitor libraries inotify and inotifywatch.
   stage: slow
-  extends: [.job-template]
+  extends: [.job-template, .test-template]
   rules:
     # note there's no "changes" section, so this always runs on a schedule
     - if: '$CI_PIPELINE_SOURCE == "web"'
diff --git a/test/lisp/autorevert-tests.el b/test/lisp/autorevert-tests.el
index 45cf635..5f27c2e 100644
--- a/test/lisp/autorevert-tests.el
+++ b/test/lisp/autorevert-tests.el
@@ -133,7 +133,9 @@ This expects `auto-revert--messages' to be bound by
                        (format-message
                         "Reverting buffer `%s'\\." (buffer-name buffer))
                        (or auto-revert--messages ""))))
-      (if (with-current-buffer buffer auto-revert-use-notify)
+      (if (and (or file-notify--library
+                   (file-remote-p temporary-file-directory))
+               (with-current-buffer buffer auto-revert-use-notify))
           (read-event nil nil 0.05)
         (sleep-for 0.05)))))
 
diff --git a/test/lisp/electric-tests.el b/test/lisp/electric-tests.el
index 62a42b7..235c02f 100644
--- a/test/lisp/electric-tests.el
+++ b/test/lisp/electric-tests.el
@@ -47,10 +47,11 @@
 
 (defmacro save-electric-modes (&rest body)
   (declare (indent defun) (debug t))
-  `(call-with-saved-electric-modes #'(lambda () ,@body)))
+  `(call-with-saved-electric-modes (lambda () ,@body)))
 
 (defun electric-pair-test-for (fixture where char expected-string
-                                       expected-point mode bindings fixture-fn)
+                                       expected-point mode bindings
+                                       fixture-fn &optional doc-string)
   (with-temp-buffer
     (funcall mode)
     (insert fixture)
@@ -63,6 +64,14 @@
             (mapcar #'car bindings)
             (mapcar #'cdr bindings)
           (call-interactively (key-binding `[,last-command-event])))))
+    (when
+        (and doc-string
+             (not
+              (and
+               (equal (buffer-substring-no-properties (point-min) (point-max))
+                      expected-string)
+               (equal (point) expected-point))))
+      (message "\n%s\n" doc-string))
     (should (equal (buffer-substring-no-properties (point-min) (point-max))
                    expected-string))
     (should (equal (point)
@@ -109,14 +118,9 @@
            (fixture (format "%s%s%s" prefix fixture suffix))
            (expected-string (format "%s%s%s" prefix expected-string suffix))
            (expected-point (+ (length prefix) expected-point))
-           (pos (+ (length prefix) pos)))
-      `(ert-deftest ,(intern (format "electric-pair-%s-at-point-%s-in-%s%s"
-                                     name
-                                     (1+ pos)
-                                     mode
-                                     extra-desc))
-           ()
-         ,(format "Electricity test in a `%s' buffer.\n
+           (pos (+ (length prefix) pos))
+           (doc-string
+            (format "Electricity test in a `%s' buffer.\n
 Start with point at %d in a %d-char-long buffer
 like this one:
 
@@ -143,7 +147,14 @@ The buffer's contents should %s:
                   char
                   (if (string= fixture expected-string) "stay" "become")
                   (replace-regexp-in-string "\n" "\\\\n" expected-string)
-                  expected-point)
+                  expected-point)))
+      `(ert-deftest ,(intern (format "electric-pair-%s-at-point-%s-in-%s%s"
+                                     name
+                                     (1+ pos)
+                                     mode
+                                     extra-desc))
+           ()
+         ,doc-string
          (electric-pair-test-for ,fixture
                                  ,(1+ pos)
                                  ,char
@@ -151,7 +162,8 @@ The buffer's contents should %s:
                                  ,expected-point
                                  ',mode
                                  ,bindings
-                                 ,fixture-fn)))))
+                                 ,fixture-fn
+                                 ,doc-string)))))
 
 (cl-defmacro define-electric-pair-test
     (name fixture
@@ -347,7 +359,7 @@ baz\"\""
 #    \"
 #
 baz\"\""
-  :fixture-fn #'(lambda () (goto-char (point-min)) (search-forward "bar")))
+  :fixture-fn (lambda () (goto-char (point-min)) (search-forward "bar")))
 
 (define-electric-pair-test inhibit-in-mismatched-string-inside-c-comments
   "foo\"\"/*
@@ -366,7 +378,7 @@ baz\"\""
     \"   \"
     \"
 */baz\"\""
-  :fixture-fn #'(lambda () (goto-char (point-min)) (search-forward "bar")))
+  :fixture-fn (lambda () (goto-char (point-min)) (search-forward "bar")))
 
 
 ;;; More quotes, but now don't bind `electric-pair-text-syntax-table'
@@ -508,8 +520,8 @@ baz\"\""
 (define-electric-pair-test js-mode-braces
   "" "{" :expected-string "{}" :expected-point 2
   :modes '(js-mode)
-  :fixture-fn #'(lambda ()
-                  (electric-pair-mode 1)))
+  :fixture-fn (lambda ()
+                (electric-pair-mode 1)))
 
 
 (define-electric-pair-test js-mode-braces-with-layout
@@ -517,29 +529,29 @@ baz\"\""
   :modes '(js-mode)
   :test-in-comments nil
   :test-in-strings nil
-  :fixture-fn #'(lambda ()
-                  (electric-layout-mode 1)
-                  (electric-pair-mode 1)))
+  :fixture-fn (lambda ()
+                (electric-layout-mode 1)
+                (electric-pair-mode 1)))
 
 (define-electric-pair-test js-mode-braces-with-layout-and-indent
   "" "{" :expected-string "{\n    \n}" :expected-point 7
   :modes '(js-mode)
   :test-in-comments nil
   :test-in-strings nil
-  :fixture-fn #'(lambda ()
-                  (electric-pair-mode 1)
-                  (electric-indent-mode 1)
-                  (electric-layout-mode 1)))
+  :fixture-fn (lambda ()
+                (electric-pair-mode 1)
+                (electric-indent-mode 1)
+                (electric-layout-mode 1)))
 
 (define-electric-pair-test js-mode-braces-with-layout-and-indent
   "" "{" :expected-string "{\n    \n}" :expected-point 7
   :modes '(js-mode)
   :test-in-comments nil
   :test-in-strings nil
-  :fixture-fn #'(lambda ()
-                  (electric-pair-mode 1)
-                  (electric-indent-mode 1)
-                  (electric-layout-mode 1)))
+  :fixture-fn (lambda ()
+                (electric-pair-mode 1)
+                (electric-indent-mode 1)
+                (electric-layout-mode 1)))
 
 
 ;;; Backspacing
@@ -594,55 +606,55 @@ baz\"\""
 ;;;
 (define-electric-pair-test autowrapping-1
   "foo" "(" :expected-string "(foo)" :expected-point 2
-  :fixture-fn #'(lambda ()
-                  (electric-pair-mode 1)
-                  (mark-sexp 1)))
+  :fixture-fn (lambda ()
+                (electric-pair-mode 1)
+                (mark-sexp 1)))
 
 (define-electric-pair-test autowrapping-2
   "foo" ")" :expected-string "(foo)" :expected-point 6
-  :fixture-fn #'(lambda ()
-                  (electric-pair-mode 1)
-                  (mark-sexp 1)))
+  :fixture-fn (lambda ()
+                (electric-pair-mode 1)
+                (mark-sexp 1)))
 
 (define-electric-pair-test autowrapping-3
   "foo" ")" :expected-string "(foo)" :expected-point 6
-  :fixture-fn #'(lambda ()
-                  (electric-pair-mode 1)
-                  (goto-char (point-max))
-                  (skip-chars-backward "\"")
-                  (mark-sexp -1)))
+  :fixture-fn (lambda ()
+                (electric-pair-mode 1)
+                (goto-char (point-max))
+                (skip-chars-backward "\"")
+                (mark-sexp -1)))
 
 (define-electric-pair-test autowrapping-4
   "foo" "(" :expected-string "(foo)" :expected-point 2
-  :fixture-fn #'(lambda ()
-                  (electric-pair-mode 1)
-                  (goto-char (point-max))
-                  (skip-chars-backward "\"")
-                  (mark-sexp -1)))
+  :fixture-fn (lambda ()
+                (electric-pair-mode 1)
+                (goto-char (point-max))
+                (skip-chars-backward "\"")
+                (mark-sexp -1)))
 
 (define-electric-pair-test autowrapping-5
   "foo" "\"" :expected-string "\"foo\"" :expected-point 2
-  :fixture-fn #'(lambda ()
-                  (electric-pair-mode 1)
-                  (mark-sexp 1)))
+  :fixture-fn (lambda ()
+                (electric-pair-mode 1)
+                (mark-sexp 1)))
 
 (define-electric-pair-test autowrapping-6
   "foo" "\"" :expected-string "\"foo\"" :expected-point 6
-  :fixture-fn #'(lambda ()
-                  (electric-pair-mode 1)
-                  (goto-char (point-max))
-                  (skip-chars-backward "\"")
-                  (mark-sexp -1)))
+  :fixture-fn (lambda ()
+                (electric-pair-mode 1)
+                (goto-char (point-max))
+                (skip-chars-backward "\"")
+                (mark-sexp -1)))
 
 (define-electric-pair-test autowrapping-7
   "foo" "\"" :expected-string "``foo''" :expected-point 8
   :modes '(tex-mode)
   :test-in-comments nil
-  :fixture-fn #'(lambda ()
-                  (electric-pair-mode 1)
-                  (goto-char (point-max))
-                  (skip-chars-backward "\"")
-                  (mark-sexp -1)))
+  :fixture-fn (lambda ()
+                (electric-pair-mode 1)
+                (goto-char (point-max))
+                (skip-chars-backward "\"")
+                (mark-sexp -1)))
 
 
 ;;; Electric quotes
diff --git a/test/lisp/epg-config-tests.el b/test/lisp/epg-config-tests.el
new file mode 100644
index 0000000..fba61e5
--- /dev/null
+++ b/test/lisp/epg-config-tests.el
@@ -0,0 +1,47 @@
+;;; epg-config-tests.el --- Test suite for epg.el  -*- lexical-binding: t -*-
+
+;; Copyright (C) 2021 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'epg-config)
+
+(ert-deftest epg-config-test-epg-find-configuration ()
+  (skip-unless (executable-find "gpg2"))
+  (should (assq 'version (epg-find-configuration 'OpenPGP))))
+
+(ert-deftest epg-config-test-epg-find-configuration/unknown-protocol ()
+  (should-error (epg-find-configuration 'does-not-exist)))
+
+(ert-deftest epg-config-test-epg-check-configuration ()
+  (should (epg-check-configuration '((version . "1.0")) "0.9"))
+  (should (epg-check-configuration '((version . "1.0")) "1.0"))
+  (should-error (epg-check-configuration '((version . "1.0")) "1.1"))
+  (should-error (epg-check-configuration '((version . "1.0")) 'foo))
+  (should-error (epg-check-configuration '((version . "1.0")) "foo")))
+
+(ert-deftest epg-config-test-epg-required-version-p ()
+  (skip-unless (executable-find "gpg2"))
+  (should (epg-required-version-p 'OpenPGP "1.0")))
+
+(provide 'epg-config-tests)
+
+;;; epg-config-tests.el ends here
diff --git a/test/lisp/filenotify-tests.el b/test/lisp/filenotify-tests.el
index d73b072..13350b2 100644
--- a/test/lisp/filenotify-tests.el
+++ b/test/lisp/filenotify-tests.el
@@ -107,19 +107,20 @@ There are different timeouts for local and remote file 
notification libraries."
    (cond
     ;; gio/gpollfilemonitor.c declares POLL_TIME_SECS 5.  So we must
     ;; wait at least this time in the GPollFileMonitor case.  A
-    ;; similar timeout seems to be needed in the GFamFileMonitor case,
-    ;; at least on cygwin.
-    ((memq (file-notify--test-monitor) '(GFamFileMonitor GPollFileMonitor)) 7)
-    ((string-equal (file-notify--test-library) "gvfs-monitor-dir.exe") 1)
+    ;; similar timeout seems to be needed in the
+    ;; GFam{File,Directory}Monitor case.  So we use a large timeout
+    ;; for any monitor.
+    ((file-notify--test-monitor) 7)
     ((file-remote-p temporary-file-directory) 0.1)
     (t 0.01))))
 
 (defun file-notify--test-timeout ()
   "Timeout to wait for arriving a bunch of events, in seconds."
   (cond
-   ((file-remote-p temporary-file-directory) 6)
+   ((file-remote-p temporary-file-directory) 20)
+   ((eq system-type 'cygwin) 10)
+   ((getenv "EMACS_EMBA_CI") 10)
    ((string-equal (file-notify--test-library) "w32notify") 4)
-   ((eq system-type 'cygwin) 6)
    (t 3)))
 
 (defmacro file-notify--test-wait-for-events (timeout until)
@@ -256,24 +257,37 @@ remote host, or nil."
 
 (defun file-notify--test-monitor ()
   "The used monitor for the test, as a symbol.
-This returns only for the local case and gfilenotify; otherwise it is nil.
-`file-notify--test-desc' must be a valid watch descriptor."
+This returns only for (local) gfilenotify or (remote) gio library;
+otherwise it is nil.  `file-notify--test-desc' must be a valid
+watch descriptor."
   ;; We cache the result, because after `file-notify-rm-watch',
   ;; `gfile-monitor-name' does not return a proper result anymore.
-  ;; But we still need this information.
-  ;; So far, we know the monitors GFamFileMonitor, GFenFileMonitor,
-  ;; GInotifyFileMonitor, GKqueueFileMonitor and GPollFileMonitor.
-  (or (cdr (assq file-notify--test-desc file-notify--test-monitors))
-      (progn
-       (add-to-list
-        'file-notify--test-monitors
-        (cons file-notify--test-desc
-              (if (file-remote-p temporary-file-directory)
-                  (tramp-get-connection-property
-                   file-notify--test-desc "gio-file-monitor" nil)
-                (and (functionp 'gfile-monitor-name)
-                     (gfile-monitor-name file-notify--test-desc)))))
-       (cdr (assq file-notify--test-desc file-notify--test-monitors)))))
+  ;; But we still need this information.  So far, we know the monitors
+  ;; GFamFileMonitor (gfilenotify on cygwin), GFamDirectoryMonitor
+  ;; (gfilenotify on Solaris), GInotifyFileMonitor (gfilenotify and
+  ;; gio on GNU/Linux), GKqueueFileMonitor (gfilenotify and gio on
+  ;; FreeBSD) and GPollFileMonitor (gio on cygwin).
+  (when file-notify--test-desc
+    (or (alist-get file-notify--test-desc file-notify--test-monitors)
+        (when (member (file-notify--test-library) '("gfilenotify" "gio"))
+         (add-to-list
+          'file-notify--test-monitors
+          (cons file-notify--test-desc
+                (if (file-remote-p temporary-file-directory)
+                     ;; `file-notify--test-desc' is the connection process.
+                     (progn
+                       (while (not (tramp-connection-property-p
+                                   file-notify--test-desc "gio-file-monitor"))
+                         (accept-process-output file-notify--test-desc 0))
+                      (tramp-get-connection-property
+                       file-notify--test-desc "gio-file-monitor" nil))
+                  (and (functionp 'gfile-monitor-name)
+                       (gfile-monitor-name file-notify--test-desc)))))
+          ;; If we don't know the monitor, there are good chances the
+          ;; test will fail.  We let it fail already here, in order to
+          ;; know the real reason.
+          (should (alist-get file-notify--test-desc 
file-notify--test-monitors)))
+       (alist-get file-notify--test-desc file-notify--test-monitors))))
 
 (defmacro file-notify--deftest-remote (test docstring &optional unstable)
   "Define ert `TEST-remote' for remote files.
@@ -484,6 +498,9 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'."
                    (file-notify-add-watch
                     file-notify--test-tmpfile
                     '(change) #'second-callback)))
+            ;; `file-notify-rm-watch' confuses `file-notify--test-monitor'.
+            ;; Initialize it in time.
+            (file-notify--test-monitor)
             ;; Remove first watch.
             (file-notify-rm-watch file-notify--test-desc)
             ;; Only the second callback shall run.
@@ -547,6 +564,10 @@ and the event to `file-notify--test-events'."
            file-notify--test-results
            (append file-notify--test-results `(,result))))))
 
+(defun file-notify--test-event-actions ()
+  "Helper function to return retrieved actions, as list."
+  (mapcar #'file-notify--test-event-action file-notify--test-events))
+
 (defun file-notify--test-with-actions-check (actions)
   "Check whether received actions match one of the ACTIONS alternatives."
   (let (result)
@@ -555,22 +576,25 @@ and the event to `file-notify--test-events'."
             (or result
                 (if (eq (car elt) :random)
                     (equal (sort (cdr elt) 'string-lessp)
-                           (sort (mapcar #'file-notify--test-event-action
-                                         file-notify--test-events)
+                           (sort (file-notify--test-event-actions)
                                  'string-lessp))
-                  (equal elt (mapcar #'file-notify--test-event-action
-                                     file-notify--test-events))))))))
+                  (equal elt (file-notify--test-event-actions))))))
+    ;; Do not report result in case we debug.  Write messages instead.
+    (if file-notify-debug
+        (prog1 t
+          (if result
+              (message "Success\n%s" (file-notify--test-event-actions))
+            (message (file-notify--test-with-actions-explainer actions))))
+      result)))
 
 (defun file-notify--test-with-actions-explainer (actions)
   "Explain why `file-notify--test-with-actions-check' fails."
   (if (null (cdr actions))
       (format "Received actions do not match expected actions\n%s\n%s"
-              (mapcar #'file-notify--test-event-action 
file-notify--test-events)
-              (car actions))
+              (file-notify--test-event-actions) (car actions))
     (format
      "Received actions do not match any sequence of expected actions\n%s\n%s"
-     (mapcar #'file-notify--test-event-action file-notify--test-events)
-     actions)))
+     (file-notify--test-event-actions) actions)))
 
 (put 'file-notify--test-with-actions-check 'ert-explainer
      'file-notify--test-with-actions-explainer)
@@ -592,6 +616,9 @@ delivered."
             (mapcar
              (lambda (x) (length (if (eq (car x) :random) (cdr x) x)))
              actions)))
+          ;; Don't stop while debugging.
+          (while-no-input-ignore-events
+           (cons 'file-notify while-no-input-ignore-events))
           create-lockfiles)
      ;; Flush pending actions.
      (file-notify--test-read-event)
@@ -632,16 +659,11 @@ delivered."
                 '(change) #'file-notify--test-event-handler)))
         (file-notify--test-with-actions
             (cond
-             ;; gvfs-monitor-dir on cygwin does not detect the
-             ;; `created' event reliably.
-            ((string-equal (file-notify--test-library) "gvfs-monitor-dir.exe")
-             '((deleted stopped)
-               (created deleted stopped)))
-             ;; cygwin does not raise a `changed' event.
-             ((eq system-type 'cygwin)
-              '(created deleted stopped))
-            ;; GKqueueFileMonitor does not report the `changed' event.
-            ((equal (file-notify--test-monitor) 'GKqueueFileMonitor)
+            ;; GFam{File,Directory}Monitor, GKqueueFileMonitor and
+            ;; GPollFileMonitor do not report the `changed' event.
+            ((memq (file-notify--test-monitor)
+                    '(GFamFileMonitor GFamDirectoryMonitor
+                      GKqueueFileMonitor GPollFileMonitor))
              '(created deleted stopped))
              (t '(created changed deleted stopped)))
           (write-region
@@ -668,13 +690,14 @@ delivered."
                '(change) #'file-notify--test-event-handler)))
         (file-notify--test-with-actions
            (cond
-             ;; gvfs-monitor-dir on cygwin does not detect the
-             ;; `changed' event reliably.
-            ((string-equal (file-notify--test-library) "gvfs-monitor-dir.exe")
+            ;; GFam{File,Directory}Monitor and GPollFileMonitor do
+             ;; not detect the `changed' event reliably.
+            ((memq (file-notify--test-monitor)
+                    '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor))
              '((deleted stopped)
                (changed deleted stopped)))
             ;; GKqueueFileMonitor does not report the `changed' event.
-            ((equal (file-notify--test-monitor) 'GKqueueFileMonitor)
+            ((eq (file-notify--test-monitor) 'GKqueueFileMonitor)
              '(deleted stopped))
             ;; There could be one or two `changed' events.
             (t '((changed deleted stopped)
@@ -709,25 +732,22 @@ delivered."
             ;; events for the watched directory.
             ((string-equal (file-notify--test-library) "w32notify")
              '(created changed deleted))
-             ;; gvfs-monitor-dir on cygwin does not detect the
-             ;; `created' event reliably.
-            ((string-equal
-              (file-notify--test-library) "gvfs-monitor-dir.exe")
-             '((deleted stopped)
-               (created deleted stopped)))
              ;; On emba, `deleted' and `stopped' events of the
              ;; directory are not detected.
              ((getenv "EMACS_EMBA_CI")
               '(created changed deleted))
             ;; There are two `deleted' events, for the file and for
-            ;; the directory.  Except for cygwin and kqueue.  And
-            ;; cygwin does not raise a `changed' event.
-            ((eq system-type 'cygwin)
+            ;; the directory.  Except for
+            ;; GFam{File,Directory}Monitor, GPollFileMonitor and
+            ;; kqueue.  And GFam{File,Directory}Monitor and
+            ;; GPollFileMonitordo not raise a `changed' event.
+            ((memq (file-notify--test-monitor)
+                    '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor))
              '(created deleted stopped))
             ((string-equal (file-notify--test-library) "kqueue")
              '(created changed deleted stopped))
             ;; GKqueueFileMonitor does not report the `changed' event.
-            ((equal (file-notify--test-monitor) 'GKqueueFileMonitor)
+            ((eq (file-notify--test-monitor) 'GKqueueFileMonitor)
              '(created deleted deleted stopped))
             (t '(created changed deleted deleted stopped)))
          (write-region
@@ -762,15 +782,12 @@ delivered."
              '(created changed created changed
                changed changed changed
                deleted deleted))
-             ;; gvfs-monitor-dir on cygwin does not detect the
-             ;; `created' event reliably.
-            ((string-equal
-              (file-notify--test-library) "gvfs-monitor-dir.exe")
-             '((deleted stopped)
-               (created created deleted stopped)))
             ;; There are three `deleted' events, for two files and
-            ;; for the directory.  Except for cygwin and kqueue.
-            ((eq system-type 'cygwin)
+            ;; for the directory.  Except for
+            ;; GFam{File,Directory}Monitor, GPollFileMonitor and
+            ;; kqueue.
+            ((memq (file-notify--test-monitor)
+                    '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor))
              '(created created changed changed deleted stopped))
             ((string-equal (file-notify--test-library) "kqueue")
              '(created changed created changed deleted stopped))
@@ -779,7 +796,7 @@ delivered."
              ((getenv "EMACS_EMBA_CI")
               '(created changed created changed deleted deleted))
             ;; GKqueueFileMonitor does not report the `changed' event.
-            ((equal (file-notify--test-monitor) 'GKqueueFileMonitor)
+            ((eq (file-notify--test-monitor) 'GKqueueFileMonitor)
              '(created created deleted deleted deleted stopped))
             (t '(created changed created changed
                  deleted deleted deleted stopped)))
@@ -819,26 +836,23 @@ delivered."
             ;; events for the watched directory.
             ((string-equal (file-notify--test-library) "w32notify")
              '(created changed renamed deleted))
-             ;; gvfs-monitor-dir on cygwin does not detect the
-             ;; `created' event reliably.
-            ((string-equal
-              (file-notify--test-library) "gvfs-monitor-dir.exe")
-             '((deleted stopped)
-               (created deleted stopped)))
              ;; On emba, `deleted' and `stopped' events of the
              ;; directory are not detected.
              ((getenv "EMACS_EMBA_CI")
               '(created changed renamed deleted))
             ;; There are two `deleted' events, for the file and for
-            ;; the directory.  Except for cygwin and kqueue.  And
-            ;; cygwin raises `created' and `deleted' events instead
-            ;; of a `renamed' event.
-            ((eq system-type 'cygwin)
+            ;; the directory.  Except for
+            ;; GFam{File,Directory}Monitor, GPollfileMonitor and
+            ;; kqueue.  And GFam{File,Directory}Monitor and
+            ;; GPollFileMonitor raise `created' and `deleted' events
+            ;; instead of a `renamed' event.
+            ((memq (file-notify--test-monitor)
+                    '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor))
              '(created created deleted deleted stopped))
             ((string-equal (file-notify--test-library) "kqueue")
              '(created changed renamed deleted stopped))
             ;; GKqueueFileMonitor does not report the `changed' event.
-            ((equal (file-notify--test-monitor) 'GKqueueFileMonitor)
+            ((eq (file-notify--test-monitor) 'GKqueueFileMonitor)
              '(created renamed deleted deleted stopped))
             (t '(created changed renamed deleted deleted stopped)))
          (write-region
@@ -857,8 +871,8 @@ delivered."
     (file-notify--test-cleanup))
 
   (unwind-protect
-      ;; Check attribute change.  Does not work for cygwin.
-      (unless (eq system-type 'cygwin)
+      ;; Check attribute change.
+      (progn
        (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
        (write-region
         "any text" nil file-notify--test-tmpfile nil 'no-message)
@@ -876,12 +890,21 @@ delivered."
             ((string-equal (file-notify--test-library) "w32notify")
              '((changed changed)
                (changed changed changed changed)))
-            ;; GKqueueFileMonitor does not report the `attribute-changed' 
event.
-            ((equal (file-notify--test-monitor) 'GKqueueFileMonitor) nil)
-            ;; For kqueue and in the remote case, `write-region'
-            ;; raises also an `attribute-changed' event.
-            ((or (string-equal (file-notify--test-library) "kqueue")
-                 (file-remote-p temporary-file-directory))
+            ;; GFam{File,Directory}Monitor, GKqueueFileMonitor and
+            ;; GPollFileMonitor do not report the `attribute-changed'
+            ;; event.
+            ((memq (file-notify--test-monitor)
+                    '(GFamFileMonitor GFamDirectoryMonitor
+                      GKqueueFileMonitor GPollFileMonitor))
+              '())
+            ;; For GInotifyFileMonitor,`write-region' raises
+            ;; also an `attribute-changed' event on gio.
+            ((and (string-equal (file-notify--test-library) "gio")
+                   (eq (file-notify--test-monitor) 'GInotifyFileMonitor))
+             '(attribute-changed attribute-changed attribute-changed))
+            ;; For kqueue, `write-region' raises also an
+            ;; `attribute-changed' event.
+             ((string-equal (file-notify--test-library) "kqueue")
              '(attribute-changed attribute-changed attribute-changed))
             (t '(attribute-changed attribute-changed)))
          (write-region
@@ -946,7 +969,7 @@ delivered."
 
            ;; GKqueueFileMonitor does not report the `changed' event.
            (skip-unless
-            (not (equal (file-notify--test-monitor) 'GKqueueFileMonitor)))
+             (not (eq (file-notify--test-monitor) 'GKqueueFileMonitor)))
 
            ;; Check, that file notification has been used.
            (should auto-revert-mode)
@@ -1046,13 +1069,14 @@ delivered."
        (should (file-notify-valid-p file-notify--test-desc))
         (file-notify--test-with-actions
            (cond
-             ;; gvfs-monitor-dir on cygwin does not detect the
-             ;; `changed' event reliably.
-            ((string-equal (file-notify--test-library) "gvfs-monitor-dir.exe")
+            ;; GFam{File,Directory}Monitor do not
+             ;; detect the `changed' event reliably.
+            ((memq (file-notify--test-monitor)
+                    '(GFamFileMonitor GFamDirectoryMonitor))
              '((deleted stopped)
                (changed deleted stopped)))
             ;; GKqueueFileMonitor does not report the `changed' event.
-            ((equal (file-notify--test-monitor) 'GKqueueFileMonitor)
+            ((eq (file-notify--test-monitor) 'GKqueueFileMonitor)
              '(deleted stopped))
             ;; There could be one or two `changed' events.
             (t '((changed deleted stopped)
@@ -1090,21 +1114,18 @@ delivered."
               ;; events for the watched directory.
               ((string-equal (file-notify--test-library) "w32notify")
                '(created changed deleted))
-               ;; gvfs-monitor-dir on cygwin does not detect the
-               ;; `created' event reliably.
-              ((string-equal
-                 (file-notify--test-library) "gvfs-monitor-dir.exe")
-               '((deleted stopped)
-                 (created deleted stopped)))
               ;; There are two `deleted' events, for the file and for
-              ;; the directory.  Except for cygwin and kqueue.  And
-              ;; cygwin does not raise a `changed' event.
-              ((eq system-type 'cygwin)
+              ;; the directory.  Except for
+              ;; GFam{File,Directory}Monitor, GPollFileMonitor and
+              ;; kqueue.  And GFam{File,Directory}Monitor and
+              ;; GPollfileMonitor do not raise a `changed' event.
+              ((memq (file-notify--test-monitor)
+                      '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor))
                '(created deleted stopped))
               ((string-equal (file-notify--test-library) "kqueue")
                '(created changed deleted stopped))
               ;; GKqueueFileMonitor does not report the `changed' event.
-              ((equal (file-notify--test-monitor) 'GKqueueFileMonitor)
+              ((eq (file-notify--test-monitor) 'GKqueueFileMonitor)
                '(created deleted deleted stopped))
               (t '(created changed deleted deleted stopped)))
            (write-region
@@ -1205,7 +1226,7 @@ delivered."
          file-notify--test-tmpfile
          '(change) #'file-notify--test-event-handler)))
   (unwind-protect
-      (let ((n 1000)
+      (let ((n 10);00)
             source-file-list target-file-list
             (default-directory file-notify--test-tmpfile))
         (dotimes (i n)
@@ -1234,9 +1255,11 @@ delivered."
                (dotimes (_i n)
                  (setq r (append '(deleted renamed) r)))
                r))
-            ;; cygwin fires `changed' and `deleted' events, sometimes
-            ;; in random order.
-            ((eq system-type 'cygwin)
+            ;; GFam{File,Directory}Monitor and GPollFileMonitor fire
+            ;; `changed' and `deleted' events, sometimes in random
+            ;; order.
+            ((memq (file-notify--test-monitor)
+                    '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor))
              (let (r)
                (dotimes (_i n)
                  (setq r (append '(changed deleted) r)))
@@ -1285,7 +1308,7 @@ delivered."
         (file-notify--test-with-actions
            (cond
             ;; GKqueueFileMonitor does not report the `changed' event.
-            ((equal (file-notify--test-monitor) 'GKqueueFileMonitor) nil)
+            ((eq (file-notify--test-monitor) 'GKqueueFileMonitor) '())
              ;; There could be one or two `changed' events.
             (t '((changed)
                  (changed changed))))
@@ -1323,11 +1346,13 @@ delivered."
         (should (file-notify-valid-p file-notify--test-desc))
         (file-notify--test-with-actions
             (cond
-             ;; On cygwin we only get the `changed' event.
-             ((eq system-type 'cygwin)
-              '(changed))
+            ;; GFam{File,Directory}Monitor and GPollFileMonitor
+            ;; report only the `changed' event.
+            ((memq (file-notify--test-monitor)
+                    '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor))
+             '(changed))
             ;; GKqueueFileMonitor does not report the `changed' event.
-            ((equal (file-notify--test-monitor) 'GKqueueFileMonitor)
+            ((eq (file-notify--test-monitor) 'GKqueueFileMonitor)
              '(renamed created))
              (t '(renamed created changed)))
           ;; The file is renamed when creating a backup.  It shall
@@ -1398,7 +1423,7 @@ the file watch."
         (should (file-notify-valid-p file-notify--test-desc1))
         (should (file-notify-valid-p file-notify--test-desc2))
         (should-not (equal file-notify--test-desc1 file-notify--test-desc2))
-        (let ((n 100))
+        (let ((n 10));0))
           ;; Run the test.
           (file-notify--test-with-actions
               ;; There could be one or two `changed' events.
@@ -1455,10 +1480,13 @@ the file watch."
         ;; Now we delete the directory.
         (file-notify--test-with-actions
             (cond
-             ;; In kqueue and for cygwin, just one `deleted' event for
-             ;; the directory is received.
-             ((or (eq system-type 'cygwin)
-                 (string-equal (file-notify--test-library) "kqueue"))
+             ;; GFam{File,Directory}Monitor, GPollFileMonitor and
+             ;; kqueue raise just one `deleted' event for the
+             ;; directory.
+            ((memq (file-notify--test-monitor)
+                    '(GFamFileMonitor GFamDirectoryMonitor GPollFileMonitor))
+              '(deleted stopped))
+            ((string-equal (file-notify--test-library) "kqueue")
               '(deleted stopped))
              (t (append
                  ;; The directory monitor raises a `deleted' event for
diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el
index 149cc68..3371657 100644
--- a/test/lisp/files-tests.el
+++ b/test/lisp/files-tests.el
@@ -192,14 +192,37 @@ form.")
 (ert-deftest files-tests-bug-21454 ()
   "Test for https://debbugs.gnu.org/21454 ."
   (let ((input-result
-         '(("/foo/bar//baz/:/bar/foo/baz//" nil ("/foo/bar/baz/" 
"/bar/foo/baz/"))
-           ("/foo/bar/:/bar/qux/:/qux/foo" nil ("/foo/bar/" "/bar/qux/" 
"/qux/foo/"))
-           ("//foo/bar/:/bar/qux/:/qux/foo/" nil ("/foo/bar/" "/bar/qux/" 
"/qux/foo/"))
-           ("/foo/bar/:/bar/qux/:/qux/foo/" nil ("/foo/bar/" "/bar/qux/" 
"/qux/foo/"))
-           ("/foo//bar/:/bar/qux/:/qux/foo/" nil ("/foo/bar/" "/bar/qux/" 
"/qux/foo/"))
-           ("/foo//bar/:/bar/qux/:/qux/foo" nil ("/foo/bar/" "/bar/qux/" 
"/qux/foo/"))
-           ("/foo/bar" "$FOO/baz/:/qux/foo/" ("/foo/bar/baz/" "/qux/foo/"))
-           ("//foo/bar/" "$FOO/baz/:/qux/foo/" ("/foo/bar/baz/" "/qux/foo/"))))
+         (if (memq system-type '(windows-nt ms-dos))
+             '(("x:/foo/bar//baz/;y:/bar/foo/baz//" nil
+                ("x:/foo/bar/baz/" "y:/bar/foo/baz/"))
+               ("x:/foo/bar/;y:/bar/qux/;z:/qux/foo" nil
+                ("x:/foo/bar/" "y:/bar/qux/" "z:/qux/foo/"))
+               ("x://foo/bar/;y:/bar/qux/;z:/qux/foo/" nil
+                ("x:/foo/bar/" "y:/bar/qux/" "z:/qux/foo/"))
+               ("x:/foo/bar/;y:/bar/qux/;z:/qux/foo/" nil
+                ("x:/foo/bar/" "y:/bar/qux/" "z:/qux/foo/"))
+               ("x:/foo//bar/;y:/bar/qux/;z:/qux/foo/" nil
+                ("x:/foo/bar/" "y:/bar/qux/" "z:/qux/foo/"))
+               ("x:/foo//bar/;y:/bar/qux/;z:/qux/foo" nil
+                ("x:/foo/bar/" "y:/bar/qux/" "z:/qux/foo/"))
+               ("x:/foo/bar" "$FOO/baz/;z:/qux/foo/"
+                ("x:/foo/bar/baz/" "z:/qux/foo/"))
+               ("x://foo/bar/" "$FOO/baz/;z:/qux/foo/"
+                ("x:/foo/bar/baz/" "z:/qux/foo/")))
+           '(("/foo/bar//baz/:/bar/foo/baz//" nil
+              ("/foo/bar/baz/" "/bar/foo/baz/"))
+             ("/foo/bar/:/bar/qux/:/qux/foo" nil
+              ("/foo/bar/" "/bar/qux/" "/qux/foo/"))
+             ("//foo/bar/:/bar/qux/:/qux/foo/" nil
+              ("/foo/bar/" "/bar/qux/" "/qux/foo/"))
+             ("/foo/bar/:/bar/qux/:/qux/foo/" nil
+              ("/foo/bar/" "/bar/qux/" "/qux/foo/"))
+             ("/foo//bar/:/bar/qux/:/qux/foo/" nil
+              ("/foo/bar/" "/bar/qux/" "/qux/foo/"))
+             ("/foo//bar/:/bar/qux/:/qux/foo" nil
+              ("/foo/bar/" "/bar/qux/" "/qux/foo/"))
+             ("/foo/bar" "$FOO/baz/:/qux/foo/" ("/foo/bar/baz/" "/qux/foo/"))
+             ("//foo/bar/" "$FOO/baz/:/qux/foo/" ("/foo/bar/baz/" 
"/qux/foo/")))))
         (foo-env (getenv "FOO"))
         (bar-env (getenv "BAR")))
     (unwind-protect
@@ -857,10 +880,15 @@ unquoted file names."
                                  (find-backup-file-name tmpfile)))))))
 
 (ert-deftest files-tests-file-name-non-special-get-file-buffer ()
+  ;; Make sure these buffers don't exist.
   (files-tests--with-temp-non-special (tmpfile nospecial)
-    (should-not (get-file-buffer nospecial)))
+    (let ((fbuf (get-file-buffer nospecial)))
+      (if fbuf (kill-buffer fbuf))
+      (should-not (get-file-buffer nospecial))))
   (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
-    (should-not (get-file-buffer nospecial))))
+    (let ((fbuf (get-file-buffer nospecial)))
+      (if fbuf (kill-buffer fbuf))
+      (should-not (get-file-buffer nospecial)))))
 
 (ert-deftest files-tests-file-name-non-special-insert-directory ()
   (files-tests--with-temp-non-special (tmpdir nospecial-dir t)
@@ -1363,8 +1391,11 @@ See <https://debbugs.gnu.org/36401>."
       (should (not (eq major-mode 'text-mode))))))
 
 (ert-deftest files-colon-path ()
-  (should (equal (parse-colon-path "/foo//bar/baz")
-                 '("/foo/bar/baz/"))))
+  (if (memq system-type '(windows-nt ms-dos))
+      (should (equal (parse-colon-path "x:/foo//bar/baz")
+                     '("x:/foo/bar/baz/")))
+    (should (equal (parse-colon-path "/foo//bar/baz")
+                 '("/foo/bar/baz/")))))
 
 (ert-deftest files-test-magic-mode-alist-doctype ()
   "Test that DOCTYPE and variants put files in mhtml-mode."
diff --git a/test/lisp/lpr-tests.el b/test/lisp/lpr-tests.el
new file mode 100644
index 0000000..bc31982
--- /dev/null
+++ b/test/lisp/lpr-tests.el
@@ -0,0 +1,41 @@
+;;; lpr-tests.el --- Tests for lpr.el  -*- lexical-binding: t -*-
+
+;; Copyright (C) 2021 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'lpr)
+
+(ert-deftest lpr-test-printify-region ()
+  (with-temp-buffer
+    (insert "foo\^@-\^h\^k\^n-\^_\177bar")
+    (printify-region (point-min) (point-max))
+    (should (equal (buffer-string) "foo\\^@-\\^H\\^K\\^N-\\^_\\7fbar"))))
+
+(ert-deftest lpr-test-lpr-eval-switch ()
+  (should (equal (lpr-eval-switch "foo") "foo"))
+  (should (equal (lpr-eval-switch (lambda () "foo")) "foo"))
+  (let ((v "foo"))
+    (should (equal (lpr-eval-switch v) "foo")))
+  (should (equal (lpr-eval-switch (list #'identity "foo")) "foo"))
+  (should (equal (lpr-eval-switch 1) nil)))
+
+;;; lpr-tests.el ends here
diff --git a/test/lisp/progmodes/cperl-mode-tests.el 
b/test/lisp/progmodes/cperl-mode-tests.el
index 8078e9c..14bc48b 100644
--- a/test/lisp/progmodes/cperl-mode-tests.el
+++ b/test/lisp/progmodes/cperl-mode-tests.el
@@ -135,6 +135,25 @@ point in the distant past, and is still broken in 
perl-mode. "
         (should (equal (nth 3 (syntax-ppss)) nil))
         (should (equal (nth 4 (syntax-ppss)) t))))))
 
+(ert-deftest cperl-test-fontify-declarations ()
+  "Test that declarations and package usage use consistent fontification."
+  (with-temp-buffer
+    (funcall cperl-test-mode)
+    (insert "package Foo::Bar;\n")
+    (insert "use Fee::Fie::Foe::Foo\n;")
+    (insert "my $xyzzy = 'PLUGH';\n")
+    (goto-char (point-min))
+    (font-lock-ensure)
+    (search-forward "Bar")
+    (should (equal (get-text-property (match-beginning 0) 'face)
+                   'font-lock-function-name-face))
+    (search-forward "use") ; This was buggy in perl-mode
+    (should (equal (get-text-property (match-beginning 0) 'face)
+                   'font-lock-keyword-face))
+    (search-forward "my")
+    (should (equal (get-text-property (match-beginning 0) 'face)
+                   'font-lock-keyword-face))))
+
 (defvar perl-continued-statement-offset)
 (defvar perl-indent-level)
 
diff --git a/test/lisp/progmodes/executable-tests.el 
b/test/lisp/progmodes/executable-tests.el
new file mode 100644
index 0000000..4f0fa69
--- /dev/null
+++ b/test/lisp/progmodes/executable-tests.el
@@ -0,0 +1,51 @@
+;;; executable-tests.el --- Tests for executable.el  -*- lexical-binding:t -*-
+
+;; Copyright (C) 2021 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'executable)
+
+(ert-deftest executable-tests-set-magic ()
+  (with-temp-buffer
+    (insert "#!/foo/bar")
+    (executable-set-magic "/bin/bash" nil t t)
+    (should (equal (buffer-string) "#!/bin/bash"))))
+
+(ert-deftest executable-tests-set-magic/with-argument ()
+  (with-temp-buffer
+    (insert "#!/foo/bar")
+    (executable-set-magic "/bin/bash" "--norc" t t)
+    (should (equal (buffer-string) "#!/bin/bash --norc"))))
+
+(ert-deftest executable-tests-set-magic/executable-insert-nil ()
+  (let ((executable-insert nil))
+    (with-temp-buffer
+      (insert "#!/foo/bar")
+      (executable-set-magic "/bin/bash" nil t nil)
+      (should (equal (buffer-string) "#!/foo/bar"))))
+  (let ((executable-insert nil))
+    (with-temp-buffer
+      (insert "#!/foo/bar")
+      (executable-set-magic "/bin/bash" nil t t)
+      (should (equal (buffer-string) "#!/bin/bash")))))
+
+;;; executable-tests.el ends here
diff --git a/test/lisp/progmodes/xref-tests.el 
b/test/lisp/progmodes/xref-tests.el
index 9982c32..c25bbd9 100644
--- a/test/lisp/progmodes/xref-tests.el
+++ b/test/lisp/progmodes/xref-tests.el
@@ -143,7 +143,7 @@
   (let* ((data-parent-dir
           (file-name-directory (directory-file-name xref-tests--data-dir)))
          (project-find-functions
-          #'(lambda (_) (cons 'transient data-parent-dir)))
+          (lambda (_) (cons 'transient data-parent-dir)))
          (xref-file-name-display 'project-relative)
          ;; Some older BSD find versions can produce '//' in the output.
          (expected (list
diff --git a/test/src/data-tests.el b/test/src/data-tests.el
index 03d867f..b1e5fa0 100644
--- a/test/src/data-tests.el
+++ b/test/src/data-tests.el
@@ -358,12 +358,35 @@ comparing the subr with a much slower lisp 
implementation."
             (should (equal (symbol-value var) 42))
             (should (equal (default-value var) (symbol-value var)))
             (set var 123)
+            (should (not (local-variable-p var)))
             (should (equal (symbol-value var) 123))
             (should (equal (default-value var) (symbol-value var)))) ;bug#44733
           (should (equal (symbol-value var) def))
           (should (equal (default-value var) (symbol-value var))))
         (should (equal (default-value var) def))))))
 
+(ert-deftest data-tests--let-buffer-local-no-unwind-other-buffers ()
+  "Test that a let-binding for a buffer-local unwinds only current-buffer."
+  (let ((blvar (make-symbol "blvar")))
+    (set-default blvar 0)
+    (make-variable-buffer-local blvar)
+    (dolist (var (list blvar 'left-margin))
+      (let* ((def (default-value var))
+             (newdef (+ def 1))
+             (otherbuf (generate-new-buffer "otherbuf")))
+        (with-temp-buffer
+          (cl-progv (list var) (list newdef)
+            (with-current-buffer otherbuf
+              (set var 123)
+              (should (local-variable-p var))
+              (should (equal (symbol-value var) 123))
+              (should (equal (default-value var) newdef))))
+          (with-current-buffer otherbuf
+            (should (local-variable-p var))
+            (should (equal (symbol-value var) 123))
+            (should (equal (default-value var) def)))
+          )))))
+
 (ert-deftest binding-test-makunbound ()
   "Tests of makunbound, from the manual."
   (with-current-buffer binding-test-buffer-B
diff --git a/test/src/filelock-tests.el b/test/src/filelock-tests.el
new file mode 100644
index 0000000..a96d6d6
--- /dev/null
+++ b/test/src/filelock-tests.el
@@ -0,0 +1,183 @@
+;;; filelock-tests.el --- test file locking -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021  Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This file tests code in src/filelock.c and, to some extent, the
+;; related code in src/fileio.c.
+;;
+;; See also (info "(emacs)Interlocking") and (info "(elisp)File Locks")
+
+;;; Code:
+
+(require 'cl-macs)
+(require 'ert)
+(require 'seq)
+
+(defun filelock-tests--fixture (test-function)
+  "Call TEST-FUNCTION under a test fixture.
+Create a test directory and a buffer whose `buffer-file-name' and
+`buffer-file-truename' are a file within it, then call
+TEST-FUNCTION.  Finally, delete the buffer and the test
+directory."
+  (let* ((temp-dir (make-temp-file "filelock-tests" t))
+         (name (concat (file-name-as-directory temp-dir)
+                       "userfile"))
+         (create-lockfiles t))
+    (unwind-protect
+        (with-temp-buffer
+          (setq buffer-file-name name
+                buffer-file-truename name)
+          (unwind-protect
+              (save-current-buffer
+                (funcall test-function))
+            ;; Set `buffer-file-truename' nil to prevent unlocking,
+            ;; which might prompt the user and/or signal errors.
+            (setq buffer-file-name nil
+                  buffer-file-truename nil)))
+      (delete-directory temp-dir t nil))))
+
+(defun filelock-tests--make-lock-name (file-name)
+  "Return the lock file name for FILE-NAME.
+Equivalent logic in Emacs proper is implemented in C and
+unavailable to Lisp."
+  (concat (file-name-directory (expand-file-name file-name))
+          ".#"
+          (file-name-nondirectory file-name)))
+
+(defun filelock-tests--spoil-lock-file (file-name)
+  "Spoil the lock file for FILE-NAME.
+Cause Emacs to report errors for various file locking operations
+on FILE-NAME going forward.  Create a file that is incompatible
+with Emacs' file locking protocol, but uses the same name as
+FILE-NAME's lock file.  A directory file is used, which is
+portable in practice."
+  (make-directory (filelock-tests--make-lock-name file-name)))
+
+(defun filelock-tests--unspoil-lock-file (file-name)
+  "Remove the lock file spoiler for FILE-NAME.
+See `filelock-tests--spoil-lock-file'."
+  (delete-directory (filelock-tests--make-lock-name file-name) t))
+
+(defun filelock-tests--should-be-locked ()
+  "Abort the current test if the current buffer is not locked.
+Exception: on systems without lock file support, aborts the
+current test if the current file is locked (which should never
+the case)."
+  (if (eq system-type 'ms-dos)
+      (should-not (file-locked-p buffer-file-truename))
+    (should (file-locked-p buffer-file-truename))))
+
+(ert-deftest filelock-tests-lock-unlock-no-errors ()
+  "Check that locking and unlocking works without error."
+  (filelock-tests--fixture
+   (lambda ()
+     (should-not (file-locked-p (buffer-file-name)))
+
+     ;; inserting text should lock the buffer's file.
+     (insert "this locks the buffer's file")
+     (filelock-tests--should-be-locked)
+     (unlock-buffer)
+     (set-buffer-modified-p nil)
+     (should-not (file-locked-p (buffer-file-name)))
+
+     ;; `set-buffer-modified-p' should lock the buffer's file.
+     (set-buffer-modified-p t)
+     (filelock-tests--should-be-locked)
+     (unlock-buffer)
+     (should-not (file-locked-p (buffer-file-name)))
+
+     (should-not (file-locked-p (buffer-file-name))))))
+
+(ert-deftest filelock-tests-lock-spoiled ()
+  "Check `lock-buffer' ."
+  (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support
+  (filelock-tests--fixture
+   (lambda ()
+     (filelock-tests--spoil-lock-file buffer-file-truename)
+     ;; FIXME: errors when locking a file are ignored; should they be?
+     (set-buffer-modified-p t)
+     (filelock-tests--unspoil-lock-file buffer-file-truename)
+     (should-not (file-locked-p buffer-file-truename)))))
+
+(ert-deftest filelock-tests-file-locked-p-spoiled ()
+  "Check that `file-locked-p' fails if the lockfile is \"spoiled\"."
+  (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support
+  (filelock-tests--fixture
+   (lambda ()
+     (filelock-tests--spoil-lock-file buffer-file-truename)
+     (let ((err (should-error (file-locked-p (buffer-file-name)))))
+       (should (equal (seq-subseq err 0 2)
+                      '(file-error "Testing file lock")))))))
+
+(ert-deftest filelock-tests-unlock-spoiled ()
+  "Check that `unlock-buffer' fails if the lockfile is \"spoiled\"."
+  (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support
+  (filelock-tests--fixture
+   (lambda ()
+     ;; Set the buffer modified with file locking temporarily
+     ;; disabled.
+     (let ((create-lockfiles nil))
+       (set-buffer-modified-p t))
+     (should-not (file-locked-p buffer-file-truename))
+     (filelock-tests--spoil-lock-file buffer-file-truename)
+
+     ;; Errors from `unlock-buffer' should call
+     ;; `userlock--handle-unlock-error' (bug#46397).
+     (let (errors)
+       (cl-letf (((symbol-function 'userlock--handle-unlock-error)
+                  (lambda (err) (push err errors))))
+         (unlock-buffer))
+       (should (consp errors))
+       (should (equal '(file-error "Unlocking file")
+                      (seq-subseq (car errors) 0 2)))
+       (should (equal (length errors) 1))))))
+
+(ert-deftest filelock-tests-kill-buffer-spoiled ()
+  "Check that `kill-buffer' fails if a lockfile is \"spoiled\"."
+  (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support
+  (filelock-tests--fixture
+   (lambda ()
+     ;; Set the buffer modified with file locking temporarily
+     ;; disabled.
+     (let ((create-lockfiles nil))
+       (set-buffer-modified-p t))
+     (should-not (file-locked-p buffer-file-truename))
+     (filelock-tests--spoil-lock-file buffer-file-truename)
+
+     ;; Kill the current buffer.  Because the buffer is modified Emacs
+     ;; will attempt to unlock it.  Temporarily bind `yes-or-no-p' to
+     ;; a function that fakes a "yes" answer for the "Buffer modified;
+     ;; kill anyway?" prompt.
+     ;;
+     ;; File errors from unlocking files should call
+     ;; `userlock--handle-unlock-error' (bug#46397).
+     (let (errors)
+       (cl-letf (((symbol-function 'yes-or-no-p)
+                  (lambda (&rest _) t))
+                 ((symbol-function 'userlock--handle-unlock-error)
+                  (lambda (err) (push err errors))))
+         (kill-buffer))
+       (should (consp errors))
+       (should (equal '(file-error "Unlocking file")
+                      (seq-subseq (car errors) 0 2)))
+       (should (equal (length errors) 1))))))
+
+(provide 'filelock-tests)
+;;; filelock-tests.el ends here
diff --git a/test/src/process-tests.el b/test/src/process-tests.el
index 17aef30..b64c82c 100644
--- a/test/src/process-tests.el
+++ b/test/src/process-tests.el
@@ -26,7 +26,6 @@
 (require 'cl-lib)
 (require 'ert)
 (require 'puny)
-(require 'rx)
 (require 'subr-x)
 (require 'dns)
 
diff --git a/test/src/thread-tests.el b/test/src/thread-tests.el
index f14d242..0e1ca76 100644
--- a/test/src/thread-tests.el
+++ b/test/src/thread-tests.el
@@ -315,8 +315,8 @@
   "Test signaling a thread as soon as it is started by the OS."
   (skip-unless (featurep 'threads))
   (let ((thread
-         (make-thread #'(lambda ()
-                          (while t (thread-yield))))))
+         (make-thread (lambda ()
+                        (while t (thread-yield))))))
     (thread-signal thread 'error nil)
     (sit-for 1)
     (should-not (thread-live-p thread))
@@ -331,7 +331,7 @@
     (let (buffer-read-only)
       (erase-buffer))
     (let ((thread
-           (make-thread #'(lambda () (thread-signal main-thread 'error nil)))))
+           (make-thread (lambda () (thread-signal main-thread 'error nil)))))
       (while (thread-live-p thread)
         (thread-yield))
       (read-event nil nil 0.1)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]