emacs-diffs
[Top][All Lists]
Advanced

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

scratch/etags-regen c409977 4/4: Merge branch 'master' into scratch/etag


From: Dmitry Gutov
Subject: scratch/etags-regen c409977 4/4: Merge branch 'master' into scratch/etags-regen
Date: Mon, 6 Sep 2021 11:17:39 -0400 (EDT)

branch: scratch/etags-regen
commit c409977cc2943d8bb6b8bce7d58e9dd989944621
Merge: 8cb5af4 ba6df55
Author: Dmitry Gutov <dgutov@yandex.ru>
Commit: Dmitry Gutov <dgutov@yandex.ru>

    Merge branch 'master' into scratch/etags-regen
---
 ChangeLog.2                                        |    2 +-
 ChangeLog.3                                        |   12 +-
 admin/nt/dist-build/build-zips.sh                  |    2 +-
 configure.ac                                       |   25 +-
 doc/emacs/basic.texi                               |   20 +-
 doc/emacs/calendar.texi                            |   14 +
 doc/emacs/commands.texi                            |    2 +-
 doc/emacs/custom.texi                              |   40 +-
 doc/emacs/dired.texi                               |    8 +-
 doc/emacs/display.texi                             |    8 +
 doc/emacs/files.texi                               |   24 +-
 doc/emacs/fixit.texi                               |    7 +-
 doc/emacs/frames.texi                              |   45 +-
 doc/emacs/maintaining.texi                         |   46 +-
 doc/emacs/misc.texi                                |   13 +
 doc/emacs/mule.texi                                |    6 +
 doc/emacs/programs.texi                            |   12 +-
 doc/emacs/text.texi                                |    5 +-
 doc/lispintro/emacs-lisp-intro.texi                |    4 +-
 doc/lispref/display.texi                           |   11 +-
 doc/lispref/eval.texi                              |   13 +-
 doc/lispref/files.texi                             |   10 +
 doc/lispref/frames.texi                            |   11 +-
 doc/lispref/lists.texi                             |   10 +-
 doc/lispref/modes.texi                             |   21 +
 doc/lispref/nonascii.texi                          |    4 +-
 doc/lispref/searching.texi                         |   18 +
 doc/lispref/tips.texi                              |    8 +
 doc/lispref/variables.texi                         |   18 +-
 doc/misc/cl.texi                                   |   60 +-
 doc/misc/message.texi                              |   17 +-
 doc/misc/mh-e.texi                                 |    4 +-
 doc/misc/tramp.texi                                |   17 +-
 etc/DISTRIB                                        |    3 +-
 etc/NEWS                                           | 4907 ++++++++++----------
 etc/PROBLEMS                                       |   10 +
 etc/TODO                                           |    8 +
 etc/facemenu-removal.txt                           |   20 -
 etc/publicsuffix.txt                               |  749 ++-
 etc/refcards/de-refcard.tex                        |    2 -
 etc/refcards/fr-refcard.tex                        |    2 -
 etc/refcards/pl-refcard.tex                        |    2 +-
 etc/refcards/pt-br-refcard.tex                     |    2 -
 etc/refcards/refcard.tex                           |    2 -
 leim/SKK-DIC/SKK-JISYO.L                           |    5 +
 lib-src/Makefile.in                                |    1 +
 lib-src/emacsclient.c                              |    7 +-
 lib-src/etags.c                                    |    2 +-
 lib-src/seccomp-filter.c                           |    9 +-
 lisp/ChangeLog.7                                   |    2 +-
 lisp/ChangeLog.8                                   |    2 +-
 lisp/abbrev.el                                     |   20 +-
 lisp/bindings.el                                   |   11 +
 lisp/bookmark.el                                   |    2 +-
 lisp/calc/calc-graph.el                            |   21 +-
 lisp/calc/calc.el                                  |    7 +-
 lisp/calendar/appt.el                              |   11 +-
 lisp/calendar/calendar.el                          |    4 +-
 lisp/calendar/diary-lib.el                         |   11 +
 lisp/calendar/timeclock.el                         |   28 +-
 lisp/comint.el                                     |  109 +-
 lisp/cus-start.el                                  |    2 +
 lisp/dired-aux.el                                  |    9 +-
 lisp/dired.el                                      |   31 +-
 lisp/edmacro.el                                    |    2 +-
 lisp/emacs-lisp/bytecomp.el                        |    5 +-
 lisp/emacs-lisp/cl-macs.el                         |   26 +-
 lisp/emacs-lisp/comp-cstr.el                       |    2 +-
 lisp/emacs-lisp/comp.el                            |   10 +-
 lisp/emacs-lisp/debug.el                           |   19 +-
 lisp/emacs-lisp/lisp.el                            |   32 +-
 lisp/emacs-lisp/map-ynp.el                         |    2 +-
 lisp/emacs-lisp/map.el                             |   18 +-
 lisp/emacs-lisp/memory-report.el                   |   15 +-
 lisp/emacs-lisp/nadvice.el                         |   67 +-
 lisp/emacs-lisp/rx.el                              |    3 +-
 lisp/emacs-lisp/tabulated-list.el                  |   60 +-
 lisp/emacs-lisp/timer.el                           |   93 +-
 lisp/epg.el                                        |   34 +-
 lisp/erc/erc.el                                    |    2 +-
 lisp/eshell/em-cmpl.el                             |    9 +-
 lisp/eshell/esh-cmd.el                             |   28 +-
 lisp/faces.el                                      |   27 +-
 lisp/files.el                                      |  127 +-
 lisp/finder.el                                     |    2 +-
 lisp/follow.el                                     |    7 +-
 lisp/frame.el                                      |   23 +-
 lisp/frameset.el                                   |    2 +-
 lisp/gnus/gnus-group.el                            |   32 +-
 lisp/gnus/gnus-start.el                            |    3 +
 lisp/help-mode.el                                  |   58 +-
 lisp/hi-lock.el                                    |    6 +-
 lisp/htmlfontify.el                                |   12 +-
 lisp/ibuf-ext.el                                   |   11 +
 lisp/icomplete.el                                  |  202 +-
 lisp/ielm.el                                       |    3 +-
 lisp/image-dired.el                                |   98 +-
 lisp/indent.el                                     |    2 +-
 lisp/info.el                                       |   58 +-
 lisp/international/mule-cmds.el                    |   66 +-
 lisp/international/mule-diag.el                    |   17 +-
 lisp/international/mule.el                         |    7 +-
 lisp/isearch.el                                    |    6 +-
 lisp/jit-lock.el                                   |   10 +-
 lisp/language/japan-util.el                        |    2 +-
 lisp/ldefs-boot.el                                 |  280 +-
 lisp/mail/footnote.el                              |    4 +-
 lisp/mail/rfc6068.el                               |   83 +
 lisp/mh-e/mh-comp.el                               |    3 +-
 lisp/mh-e/mh-e.el                                  |    5 +-
 lisp/mh-e/mh-junk.el                               |    5 +-
 lisp/mh-e/mh-mime.el                               |    9 +-
 lisp/mh-e/mh-xface.el                              |   17 +-
 lisp/minibuffer.el                                 |   96 +-
 lisp/mouse.el                                      |  222 +
 lisp/net/ange-ftp.el                               |    3 +-
 lisp/net/browse-url.el                             |    5 +-
 lisp/net/dictionary.el                             |    2 +-
 lisp/net/eudc.el                                   |    4 +-
 lisp/net/eww.el                                    |   30 +
 lisp/net/goto-addr.el                              |   23 +-
 lisp/net/rcirc.el                                  |    6 +-
 lisp/net/tramp-adb.el                              |    8 +-
 lisp/net/tramp-compat.el                           |    9 +
 lisp/net/tramp-sh.el                               |   80 +-
 lisp/net/tramp-smb.el                              |  311 +-
 lisp/net/tramp.el                                  |   36 +-
 lisp/newcomment.el                                 |    3 +-
 lisp/{mail => obsolete}/rfc2368.el                 |    1 +
 lisp/obsolete/terminal.el                          |    7 +-
 lisp/play/5x5.el                                   |    8 +-
 lisp/play/decipher.el                              |    4 +-
 lisp/progmodes/bug-reference.el                    |  234 +-
 lisp/progmodes/cc-awk.el                           |    2 +-
 lisp/progmodes/cc-defs.el                          |   66 +-
 lisp/progmodes/cc-engine.el                        |   11 +-
 lisp/progmodes/compile.el                          |    9 +-
 lisp/progmodes/cperl-mode.el                       |  432 +-
 lisp/progmodes/ebnf-abn.el                         |    3 +-
 lisp/progmodes/ebnf2ps.el                          |    8 +-
 lisp/progmodes/elisp-mode.el                       |    2 +-
 lisp/progmodes/flymake.el                          |    2 +
 lisp/progmodes/gud.el                              |   35 +-
 lisp/progmodes/hideif.el                           |    2 +-
 lisp/progmodes/prog-mode.el                        |   28 +
 lisp/progmodes/project.el                          |   56 +-
 lisp/progmodes/python.el                           |  103 +-
 lisp/progmodes/sh-script.el                        |    2 +-
 lisp/progmodes/vhdl-mode.el                        |    2 +-
 lisp/progmodes/xref.el                             |  156 +-
 lisp/repeat.el                                     |    5 +-
 lisp/saveplace.el                                  |    4 +-
 lisp/ses.el                                        |    2 +-
 lisp/shadowfile.el                                 |   72 +-
 lisp/shell.el                                      |    4 +-
 lisp/simple.el                                     |  117 +-
 lisp/subr.el                                       |   45 +-
 lisp/tab-bar.el                                    |    7 +-
 lisp/term.el                                       |    8 +-
 lisp/term/linux.el                                 |    2 +-
 lisp/term/st.el                                    |   10 +-
 lisp/term/xterm.el                                 |   34 +-
 lisp/textmodes/bibtex.el                           |    8 +-
 lisp/textmodes/conf-mode.el                        |   12 +-
 lisp/textmodes/css-mode.el                         |   59 +-
 lisp/textmodes/flyspell.el                         |   47 +-
 lisp/textmodes/ispell.el                           |   32 +-
 lisp/textmodes/tex-mode.el                         |   14 +-
 lisp/thingatpt.el                                  |   38 +-
 lisp/time-stamp.el                                 |  167 +-
 lisp/userlock.el                                   |    3 +-
 lisp/vc/ediff-wind.el                              |   34 +-
 lisp/vc/vc-cvs.el                                  |   10 +-
 lisp/vc/vc-git.el                                  |   24 +-
 lisp/vc/vc-rcs.el                                  |   48 +-
 lisp/vc/vc.el                                      |   30 +-
 lisp/whitespace.el                                 |    5 +-
 lisp/windmove.el                                   |    2 +-
 lisp/window.el                                     |    9 +-
 lisp/xwidget.el                                    |   74 +-
 oldXMenu/Activate.c                                |   20 +-
 oldXMenu/AddPane.c                                 |   20 +-
 oldXMenu/AddSel.c                                  |   20 +-
 oldXMenu/ChgPane.c                                 |   20 +-
 oldXMenu/ChgSel.c                                  |   20 +-
 oldXMenu/Create.c                                  |   20 +-
 oldXMenu/DelPane.c                                 |   20 +-
 oldXMenu/DelSel.c                                  |   20 +-
 oldXMenu/Destroy.c                                 |   20 +-
 oldXMenu/Error.c                                   |   20 +-
 oldXMenu/EvHand.c                                  |   20 +-
 oldXMenu/FindPane.c                                |   20 +-
 oldXMenu/FindSel.c                                 |   20 +-
 oldXMenu/InsPane.c                                 |   20 +-
 oldXMenu/InsSel.c                                  |   20 +-
 oldXMenu/Internal.c                                |   20 +-
 oldXMenu/Locate.c                                  |   20 +-
 oldXMenu/Post.c                                    |   20 +-
 oldXMenu/Recomp.c                                  |   20 +-
 oldXMenu/SetAEQ.c                                  |   20 +-
 oldXMenu/SetFrz.c                                  |   20 +-
 oldXMenu/SetPane.c                                 |   20 +-
 oldXMenu/SetSel.c                                  |   20 +-
 oldXMenu/XCrAssoc.c                                |   20 +-
 oldXMenu/XDelAssoc.c                               |   20 +-
 oldXMenu/XDestAssoc.c                              |   20 +-
 oldXMenu/XLookAssoc.c                              |   20 +-
 oldXMenu/XMakeAssoc.c                              |   20 +-
 oldXMenu/XMenu.h                                   |   20 +-
 oldXMenu/XMenuInt.h                                |   20 +-
 src/buffer.c                                       |   60 +-
 src/callint.c                                      |   10 +-
 src/callproc.c                                     |    2 +
 src/coding.c                                       |   44 +-
 src/comp.c                                         |  225 +-
 src/composite.c                                    |   28 +-
 src/data.c                                         |    2 +
 src/fileio.c                                       |    2 +
 src/fns.c                                          |    5 +-
 src/frame.c                                        |   36 +-
 src/image.c                                        |    4 +-
 src/keyboard.c                                     |   42 +-
 src/lisp.h                                         |    1 +
 src/menu.c                                         |   14 +-
 src/nsfns.m                                        |    5 +
 src/nsmenu.m                                       |    9 +-
 src/nsterm.h                                       |    1 +
 src/nsterm.m                                       |   32 +-
 src/process.c                                      |    5 +-
 src/syntax.c                                       |   10 +-
 src/term.c                                         |   13 +-
 src/xdisp.c                                        |   40 +-
 src/xfaces.c                                       |    4 +-
 src/xfns.c                                         |    1 -
 test/Makefile.in                                   |    2 +-
 test/infra/Dockerfile.emba                         |    2 +-
 test/infra/gitlab-ci.yml                           |    6 +-
 test/lisp/calendar/icalendar-tests.el              |    7 +
 test/lisp/custom-tests.el                          |    1 +
 test/lisp/electric-tests.el                        |    2 +-
 test/lisp/emacs-lisp/cl-lib-tests.el               |   16 -
 test/lisp/emacs-lisp/edebug-tests.el               |    4 +-
 test/lisp/emacs-lisp/map-tests.el                  |    9 +
 test/lisp/emacs-lisp/memory-report-tests.el        |    8 +
 test/lisp/files-tests.el                           |  213 +
 test/lisp/international/ucs-normalize-tests.el     |    1 +
 test/lisp/mail/rfc6068-tests.el                    |   52 +
 test/lisp/mh-e/mh-xface-tests.el                   |   35 +
 test/lisp/net/socks-tests.el                       |    2 +-
 test/lisp/net/tramp-tests.el                       |  186 +-
 test/lisp/newcomment-tests.el                      |   39 +
 test/lisp/{mail => obsolete}/rfc2368-tests.el      |    0
 .../progmodes/cperl-mode-resources/here-docs.pl    |    2 +-
 test/lisp/progmodes/cperl-mode-tests.el            |  162 +-
 test/lisp/progmodes/project-tests.el               |   15 +
 test/lisp/progmodes/sh-script-tests.el             |   51 +
 test/lisp/progmodes/xref-tests.el                  |    8 +
 test/lisp/shadowfile-tests.el                      |   24 +-
 test/lisp/simple-tests.el                          |   11 +
 test/lisp/subr-tests.el                            |   27 +
 test/lisp/textmodes/fill-tests.el                  |    4 +-
 test/lisp/thingatpt-tests.el                       |    8 +
 test/lisp/vc/vc-tests.el                           |  158 +-
 test/src/buffer-tests.el                           |   63 +
 test/src/syntax-tests.el                           |    6 +
 265 files changed, 8785 insertions(+), 4603 deletions(-)

diff --git a/ChangeLog.2 b/ChangeLog.2
index 7b40c54..3e22767 100644
--- a/ChangeLog.2
+++ b/ChangeLog.2
@@ -35670,7 +35670,7 @@
 2015-04-08  Artur Malabarba  <bruce.connor.am@gmail.com>
 
        * lisp/emacs-lisp/package.el (package-menu-mode): Mode-line notification
-       while dowloading information.
+       while downloading information.
 
        * lisp/emacs-lisp/package.el: More conservative `ensure-init-file'
        (package--ensure-init-file): Check file contents before visiting.
diff --git a/ChangeLog.3 b/ChangeLog.3
index 8b872a0..9ec19e9 100644
--- a/ChangeLog.3
+++ b/ChangeLog.3
@@ -33355,9 +33355,9 @@
        Fix the handling of font backend supersedence on MS-Windows
 
        * src/w32font.c (syms_of_w32font): Don't make the Uniscribe
-       font backend "superceded" here, ...
+       font backend "superseded" here, ...
        * src/w32uniscribe.c (syms_of_w32uniscribe_for_pdumper):
-       ... make it "superceded" here, only if the HarfBuzz DLL was
+       ... make it "superseded" here, only if the HarfBuzz DLL was
        successfully loaded.  This is because Emacs compiled with
        HarfBuzz support might run on a system without the DLL.
        * src/w32fns.c (Fx_create_frame, w32_create_tip_frame):
@@ -36933,7 +36933,7 @@
        electric--sort-post-self-insertion-hook.
 
        * lisp/emacs-lisp/syntax.el (syntax-propertize, syntax-ppss):
-       Use new `depth` arg to make sure noone accidentally gets added
+       Use new `depth` arg to make sure no one accidentally gets added
        after syntax-ppss-flush-cache.
 
        * doc/lispref/modes.texi (Setting Hooks): Document new `depth` arg.
@@ -58138,7 +58138,7 @@
 
        Use bignums when Emacs converts to and from system types like
        off_t for file sizes whose values can exceed fixnum range.
-       Formerly, Emacs sometimes generted floats and sometimes ad-hoc
+       Formerly, Emacs sometimes generated floats and sometimes ad-hoc
        conses of integers.  Emacs still accepts floats and conses for
        these system types, in case some stray Lisp code is generating
        them, though this usage is obsolescent.
@@ -133272,7 +133272,7 @@
        (g_b_init_compare_string_w): Move declaration to file scope.
        * src/w32heap.c (dumped_data_commit): Now static.
        (FREEABLE_P): Avoid warnings about pointer comparison with integer.
-       (mmap_realloc): Cast to 'char *' for arithmetics on void pointers.
+       (mmap_realloc): Cast to 'char *' for arithmetic on void pointers.
        * src/w32console.c (ctrl_c_handler, sys_tputs, sys_tgetstr)
        (evalcost, cmputc, cmcheckmagic, cmcostinit, cmgoto, Wcm_clear):
        Provide prototypes.
@@ -144146,7 +144146,7 @@
 
        Move package test files to new directory.
 
-        * test/lisp/emacs-lisp/package-tests.el: Update resoruce file location.
+        * test/lisp/emacs-lisp/package-tests.el: Update resource file location.
         * test/data/package: Moved to test/lisp/emacs-lisp/package-resources
 
 2015-11-24  Phillip Lord  <phillip.lord@russet.org.uk>
diff --git a/admin/nt/dist-build/build-zips.sh 
b/admin/nt/dist-build/build-zips.sh
index 7bc6ea6..4c3a52a 100755
--- a/admin/nt/dist-build/build-zips.sh
+++ b/admin/nt/dist-build/build-zips.sh
@@ -134,7 +134,7 @@ while getopts "gb:hnsiV:" opt; do
         echo "  -g git update and worktree only"
         echo "  -i build installer only"
         echo "  -n do not configure"
-        echo "  -s snaphot build"
+        echo "  -s snapshot build"
         exit 0
         ;;
     \?)
diff --git a/configure.ac b/configure.ac
index eff5591..418a62f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1335,7 +1335,9 @@ if test -n "$BREW"; then
 fi
 
 # Check MacPorts on macOS.
-AC_PATH_PROG(HAVE_MACPORTS, port)
+if test $opsys = darwin; then
+  AC_PATH_PROG(HAVE_MACPORTS, port)
+fi
 
 ## Require makeinfo >= 4.13 (last of the 4.x series) to build the manuals.
 : ${MAKEINFO:=makeinfo}
@@ -3795,7 +3797,7 @@ AC_DEFUN([libgccjit_dev_not_found], [
 not found.
 Please try installing libgccjit-dev or a similar package.
 If you are sure you want Emacs be compiled without ELisp native compiler,
-pass the --without-nativecomp option to configure.])])
+pass the --without-native-compilation option to configure.])])
 
 AC_DEFUN([libgccjit_broken], [
   AC_MSG_ERROR([The installed libgccjit failed to compile and run a test 
program using
@@ -3814,20 +3816,21 @@ LIBGCCJIT_LIBS=
 LIBGCCJIT_CFLAGS=
 if test "${with_native_compilation}" != "no"; then
     if test "${HAVE_PDUMPER}" = no; then
-       AC_MSG_ERROR(['--with-nativecomp' requires '--with-dumping=pdumper'])
+       AC_MSG_ERROR(['--with-native-compilation' requires 
'--with-dumping=pdumper'])
     fi
     if test "${HAVE_ZLIB}" = no; then
-       AC_MSG_ERROR(['--with-nativecomp' requires zlib])
+       AC_MSG_ERROR(['--with-native-compilation' requires zlib])
     fi
 
     # Ensure libgccjit installed by Homebrew can be found.
     if test -n "$BREW"; then
-      BREW_LIBGCCJIT_PREFIX=`$BREW --prefix --installed libgccjit 2>/dev/null`
-      if test "$BREW_LIBGCCJIT_PREFIX"; then
-        brew_libdir=`find ${BREW_LIBGCCJIT_PREFIX}/ -name \*.so \
-                     | sed -e '1!d;s|/[[^/]]*\.so$||'`
-        CFLAGS="$CFLAGS -I${BREW_LIBGCCJIT_PREFIX}/include"
-        LDFLAGS="$LDFLAGS -L${brew_libdir} -I${BREW_LIBGCCJIT_PREFIX}/include"
+      if test -n "`$BREW --prefix --installed libgccjit 2>/dev/null`"; then
+        BREW_LIBGCCJIT_INCLUDE=$(dirname $($BREW ls -v libgccjit | \
+                                              grep libgccjit.h))
+        BREW_LIBGCCJIT_LIB=$(dirname $($BREW ls -v libgccjit| \
+                                          grep libgccjit.so\$))
+        CFLAGS="$CFLAGS -I${BREW_LIBGCCJIT_INCLUDE}"
+        LDFLAGS="$LDFLAGS -L${BREW_LIBGCCJIT_LIB}"
       fi
     fi
 
@@ -5664,7 +5667,7 @@ gl_INIT
 CFLAGS=$SAVE_CFLAGS
 LIBS=$SAVE_LIBS
 
-# timer_getoverrun needs the same libarary as timer_settime
+# timer_getoverrun needs the same library as timer_settime
 OLD_LIBS=$LIBS
 LIBS="$LIB_TIMER_TIME $LIBS"
 AC_CHECK_FUNCS(timer_getoverrun)
diff --git a/doc/emacs/basic.texi b/doc/emacs/basic.texi
index ba8d822..c4fa0d6 100644
--- a/doc/emacs/basic.texi
+++ b/doc/emacs/basic.texi
@@ -887,15 +887,19 @@ z z z}.  The first @kbd{C-x z} repeats the command once, 
and each
 subsequent @kbd{z} repeats it once again.
 
 @findex repeat-mode
-  Also you can activate @code{repeat-mode} that temporarily enables
-a transient mode with short keys after a limited number of commands.
+@vindex repeat-exit-key
+@vindex repeat-exit-timeout
+  Also you can activate @code{repeat-mode} that temporarily enables a
+transient mode with short keys after a limited number of commands.
 Currently supported shorter key sequences are @kbd{C-x u u} instead of
 @kbd{C-x u C-x u} to undo many changes, @kbd{C-x o o} instead of
 @kbd{C-x o C-x o} to switch several windows, @kbd{C-x @{ @{ @} @} ^ ^
 v v} to resize the selected window interactively, @kbd{M-g n n p p} to
-navigate @code{next-error} matches.  Any other key exits transient mode
-and then is executed normally.  The user option @code{repeat-exit-key}
-defines an additional key to exit this transient mode.  Also it's
-possible to break the repetition chain automatically after idle time
-by customizing the user option @code{repeat-exit-timeout} to a number
-of seconds.
+navigate @code{next-error} matches, and @kbd{C-x ] ] [ [} to navigate
+through pages.  Any other key exits transient mode and then is
+executed normally.  The user option @code{repeat-exit-key} defines an
+additional key to exit this transient mode.  Also it's possible to
+break the repetition chain automatically after some idle time by
+customizing the user option @code{repeat-exit-timeout} to specify the
+idle time in seconds after which this transient mode will be turned
+off.
diff --git a/doc/emacs/calendar.texi b/doc/emacs/calendar.texi
index 3750e78..18de721 100644
--- a/doc/emacs/calendar.texi
+++ b/doc/emacs/calendar.texi
@@ -1363,6 +1363,20 @@ the 11 above to @samp{'(1 2 3)} and have the entry apply 
to the last
 Thursday of January, February, and March.  If the month is @code{t}, the
 entry applies to all months of the year.
 
+@findex diary-offset
+@example
+%%(diary-offset '(diary-float t 3 4) 2) Monthly committee meeting
+@end example
+
+@noindent
+This entry applies to the Saturday after the third Thursday of each
+month.  The 2 specifies number of days after when the sexp
+@w{@code{'(diary-float t 3 4)}} would evaluate to @code{t}.  This is
+useful when for example your organization has a committee meeting two
+days after every monthly meeting which takes place on the third
+Thursday, or if you would like to attend a virtual meeting scheduled
+in a different timezone causing a difference in the date.
+
   Each of the standard sexp diary entries takes an optional parameter
 specifying the name of a face or a single-character string to use when
 marking the entry in the calendar.  Most generally, sexp diary entries
diff --git a/doc/emacs/commands.texi b/doc/emacs/commands.texi
index 82a917c..f56f820 100644
--- a/doc/emacs/commands.texi
+++ b/doc/emacs/commands.texi
@@ -121,7 +121,7 @@ C-k} is two key sequences, not one.
   By default, the prefix keys in Emacs are @kbd{C-c}, @kbd{C-h},
 @kbd{C-x}, @kbd{C-x @key{RET}}, @kbd{C-x @@}, @kbd{C-x a}, @kbd{C-x
 n}, @kbd{C-x r}, @kbd{C-x t}, @kbd{C-x v}, @kbd{C-x 4}, @kbd{C-x 5},
-@kbd{C-x 6}, @key{ESC}, @kbd{M-g}, and @kbd{M-o}.  (@key{F1} and
+@kbd{C-x 6}, @key{ESC}, and @kbd{M-g}.  (@key{F1} and
 @key{F2} are aliases for @kbd{C-h} and @kbd{C-x 6}.)  This list is not
 cast in stone; if you customize Emacs, you can make new prefix keys.
 You could even eliminate some of the standard ones, though this is not
diff --git a/doc/emacs/custom.texi b/doc/emacs/custom.texi
index 999234e..9220a20 100644
--- a/doc/emacs/custom.texi
+++ b/doc/emacs/custom.texi
@@ -1721,6 +1721,17 @@ previous ones, but they are specifically for file name 
completion.
 They do not bind @key{SPC}.
 @end itemize
 
+By default, @key{TAB}, @key{SPC} and @key{?} do completion in
+@code{minibuffer-local-completion-map}.  If you commonly complete over
+collections that have elements with space or question mark characters in
+them, it may be convenient to disable completion on those keys by
+putting this in your init file:
+
+@lisp
+(define-key minibuffer-local-completion-map " " 'self-insert-command)
+(define-key minibuffer-local-completion-map "?" 'self-insert-command)
+@end lisp
+
 @node Rebinding
 @subsection Changing Key Bindings Interactively
 @cindex key rebinding, this session
@@ -2355,14 +2366,19 @@ function @code{setq} to set the variable 
@code{fill-column}
 (@pxref{Filling}) to 60.
 
   You can set any Lisp variable with @code{setq}, but with certain
-variables @code{setq} won't do what you probably want in the
-init file.  Some variables automatically become buffer-local
-when set with @code{setq}; what you want in the init file is to set
-the default value, using @code{setq-default}.  Some customizable minor
-mode variables do special things to enable the mode when you set them
-with Customize, but ordinary @code{setq} won't do that; to enable the
-mode in your init file, call the minor mode command.  The
-following section has examples of both of these methods.
+variables @code{setq} won't do what you probably want in the init
+file.  Some variables automatically become buffer-local when set with
+@code{setq}; what you want in the init file is to set the default
+value, using @code{setq-default}.  (The following section has examples
+of both of these methods.)
+
+Some customizable minor mode variables do special things to enable the
+mode when you set them with Customize, but ordinary @code{setq} won't
+do that; to enable the mode in your init file, call the minor mode
+command.  Finally, a few customizable user options are initialized in
+complex ways, and these have to be set either via the customize
+interface (@pxref{Customization}) or by using
+@code{customize-set-variable} (@pxref{Examining}).
 
   The second argument to @code{setq} is an expression for the new
 value of the variable.  This can be a constant, a variable, or a
@@ -2511,6 +2527,14 @@ Turn on Auto Fill mode automatically in Text mode and 
related modes
 @end example
 
 @item
+Change the coding system used when using the clipboard
+(@pxref{Communication Coding}).
+
+@example
+(customize-set-variable 'selection-coding-system 'utf-8)
+@end example
+
+@item
 Load the installed Lisp library named @file{foo} (actually a file
 @file{foo.elc} or @file{foo.el} in a standard Emacs directory).
 
diff --git a/doc/emacs/dired.texi b/doc/emacs/dired.texi
index 680b20c..540abc3 100644
--- a/doc/emacs/dired.texi
+++ b/doc/emacs/dired.texi
@@ -823,7 +823,9 @@ link.
 Change the mode (also called @dfn{permission bits}) of the specified
 files (@code{dired-do-chmod}).  @var{modespec} can be in octal or
 symbolic notation, like arguments handled by the @command{chmod}
-program.
+program.  This command does not follow symbolic links, so it reports
+an error if you try to change the mode of a symbolic link on a
+platform where such modes are immutable.
 
 @findex dired-do-chgrp
 @kindex G @r{(Dired)}
@@ -850,8 +852,8 @@ different systems put @command{chown} in different places).
 @cindex changing file time (in Dired)
 @item T @var{timestamp} @key{RET}
 Touch the specified files (@code{dired-do-touch}).  This means
-updating their modification times to the present time.  This is like
-the shell command @code{touch}.
+updating their modification times to @var{timestamp}, which defaults
+to the present time.  This is like the shell command @command{touch}.
 
 @findex dired-do-print
 @kindex P @r{(Dired)}
diff --git a/doc/emacs/display.texi b/doc/emacs/display.texi
index ae345c1..996c5a6 100644
--- a/doc/emacs/display.texi
+++ b/doc/emacs/display.texi
@@ -1767,6 +1767,10 @@ multiple screen lines.  Setting the variable 
@code{truncate-lines} in
 any way makes it local to the current buffer; until that time, the
 default value, which is normally @code{nil}, is in effect.
 
+  Since line truncation and word wrap (described in the next section)
+are contradictory, @code{toggle-truncate-lines} disables word wrap
+when it turns on line truncation.
+
   If a split window becomes too narrow, Emacs may automatically enable
 line truncation.  @xref{Split Window}, for the variable
 @code{truncate-partial-width-windows} which controls this.
@@ -1797,6 +1801,10 @@ mode is enabled, the mode line shows the string 
@samp{wrap} in the
 mode display.  The command @kbd{M-x global-visual-line-mode} toggles
 Visual Line mode in all buffers.
 
+  Since word wrap and line truncation (described in the previous
+section) are contradictory, turning on @code{visual-line-mode}
+disables line truncation.
+
 @findex beginning-of-visual-line
 @findex end-of-visual-line
 @findex next-logical-line
diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi
index 8304e40..65a57cc 100644
--- a/doc/emacs/files.texi
+++ b/doc/emacs/files.texi
@@ -742,6 +742,17 @@ always supposed to end in newlines.  Such major modes set 
the variable
 setting the latter variable, you can control how these modes handle
 final newlines.
 
+@vindex file-preserve-symlinks-on-save
+If this option is non-@code{nil} and you're visiting a file via a
+symbolic link, Emacs will break the symbolic link upon saving the
+buffer, and will write the buffer to a file with the same name as the
+symbolic link, if the value of @code{file-precious-flag} is
+non-@code{nil} (@pxref{Saving Buffers, file-precious-flag,, elisp, The
+Emacs Lisp Reference Manual}).  If you want Emacs to save the buffer
+to the file the symbolic link points to (thereby preserving the link)
+in these cases, customize the variable
+@code{file-preserve-symlinks-on-save} to @code{t}.
+
 @vindex write-region-inhibit-fsync
   Normally, when a program writes a file, the operating system briefly
 caches the file's data in main memory before committing the data to
@@ -1180,6 +1191,13 @@ visited file.  (You can inhibit this by setting the 
variable
 file name with @kbd{C-x C-w} or @code{set-visited-file-name} renames
 any auto-save file to go with the new visited name.
 
+@vindex kill-buffer-delete-auto-save-files
+  Killing a buffer, by default, doesn't remove the buffer's auto-save
+file.  If @code{kill-buffer-delete-auto-save-files} is non-@code{nil},
+killing a buffer that has an auto-save file will make Emacs prompt the
+user for whether the auto-save file should be deleted.  (This is
+inhibited if @code{delete-auto-save-files} is @code{nil}.)
+
 @node Auto Save Control
 @subsection Controlling Auto-Saving
 
@@ -1728,12 +1746,16 @@ exists.
   @kbd{M-x copy-file} copies the contents of the file @var{old} to the
 file @var{new}.
 
+@vindex copy-directory-create-symlink
 @findex copy-directory
   @kbd{M-x copy-directory} copies directories, similar to the
 @command{cp -r} shell command.  If @var{new} is a directory name, it
 creates a copy of the @var{old} directory and puts it in @var{new}.
 Otherwise it copies all the contents of @var{old} into a new directory
-named @var{new}.
+named @var{new}.  If @code{copy-directory-create-symlink} is
+non-@code{nil} and @var{old} is a symbolic link, this command will
+copy the symbolic link.  If @code{nil}, this command will follow the
+link and copy the contents instead.  (This is the default.)
 
 @cindex renaming files
 @findex rename-file
diff --git a/doc/emacs/fixit.texi b/doc/emacs/fixit.texi
index b558ebc..85cdbff 100644
--- a/doc/emacs/fixit.texi
+++ b/doc/emacs/fixit.texi
@@ -462,10 +462,9 @@ use @code{flyspell-region} or @code{flyspell-buffer} for 
that.
   When Flyspell mode highlights a word as misspelled, you can click on
 it with @kbd{mouse-2} (@code{flyspell-correct-word}) to display a menu
 of possible corrections and actions.  If you want this menu on
-@kbd{mouse-3} instead, customize the variable
-@code{flyspell-use-mouse-3-for-menu}.  In addition, @kbd{C-.} or
-@kbd{@key{ESC}-@key{TAB}} (@code{flyspell-auto-correct-word}) will
-propose various successive corrections for the word at point, and
+@kbd{mouse-3} instead, enable @code{context-menu-mode}.  In addition,
+@kbd{C-.} or @kbd{@key{ESC}-@key{TAB}} (@code{flyspell-auto-correct-word})
+will propose various successive corrections for the word at point, and
 @w{@kbd{C-c $}} (@code{flyspell-correct-word-before-point}) will pop
 up a menu of possible corrections.  Of course, you can always correct
 the misspelled word by editing it manually in any way you like.
diff --git a/doc/emacs/frames.texi b/doc/emacs/frames.texi
index 951e090..a32181e 100644
--- a/doc/emacs/frames.texi
+++ b/doc/emacs/frames.texi
@@ -366,20 +366,24 @@ This menu is for changing the default face within the 
window's buffer.
 @xref{Text Scale}.
 @end table
 
-  Some graphical applications use @kbd{mouse-3} for a mode-specific
-menu.  If you prefer @kbd{mouse-3} in Emacs to bring up such a menu
-instead of running the @code{mouse-save-then-kill} command, rebind
-@kbd{mouse-3} by adding the following line to your init file
-(@pxref{Init Rebinding}):
-
-@smallexample
-(global-set-key [mouse-3]
-  '(menu-item "Menu Bar" ignore
-    :filter (lambda (_)
-              (if (zerop (or (frame-parameter nil 'menu-bar-lines) 0))
-                  (mouse-menu-bar-map)
-                (mouse-menu-major-mode-map)))))
-@end smallexample
+@cindex context menu
+@findex context-menu-mode
+@vindex context-menu-functions
+@kindex Down-mouse-3
+@kindex S-F10
+  Many GUI applications use @kbd{mouse-3} to display @dfn{context
+menus}: menus that provide access to various pertinent settings and
+actions for the location and context of the mouse click.  If you
+prefer this in Emacs over the default function of @kbd{mouse-3}, which
+is bound to the @code{mouse-save-then-kill} command (@pxref{Mouse
+Commands}), you can enable the minor mode @code{context-menu-mode}.
+Then Emacs will show context menus when you click @kbd{mouse-3}.  The
+exact contents of these context menus depends on the current major
+mode and the buffer contents around the place where you click the
+mouse.  To customize the contents of the context menu, you can use the
+variable @code{context-menu-functions} (@pxref{Major Mode
+Conventions,,, elisp, The Emacs Lisp Reference Manual}).
+You can also invoke the context menu by pressing @kbd{S-@key{F10}}.
 
 @node Mode Line Mouse
 @section Mode Line Mouse Commands
@@ -448,7 +452,14 @@ buffer to select:
 @item C-x 5 2
 @kindex C-x 5 2
 @findex make-frame-command
-Create a new frame (@code{make-frame-command}).
+Create a new frame using the default frame parameters
+(@code{make-frame-command}).
+
+@item C-x 5 c
+@kindex C-x 5 c
+@findex clone-frame
+Create a new frame using the parameters of the current frame
+(@code{clone-frame}).
 
 @item C-x 5 b @var{bufname} @key{RET}
 Select buffer @var{bufname} in another frame.  This runs
@@ -1218,7 +1229,9 @@ the use of menu bars at startup, customize the variable
 terminals, where this makes one additional line available for text.
 If the menu bar is off, you can still pop up a menu of its contents
 with @kbd{C-mouse-3} on a display which supports pop-up menus.
-@xref{Menu Mouse Clicks}.
+Or you can enable @code{context-menu-mode} and customize the variable
+@code{context-menu-functions} to pop up a context menu with
+@kbd{mouse-3}.  @xref{Menu Mouse Clicks}.
 
   @xref{Menu Bar}, for information on how to invoke commands with the
 menu bar.  @xref{X Resources}, for how to customize the menu bar
diff --git a/doc/emacs/maintaining.texi b/doc/emacs/maintaining.texi
index 3205e6d..5b33c9b 100644
--- a/doc/emacs/maintaining.texi
+++ b/doc/emacs/maintaining.texi
@@ -1136,13 +1136,17 @@ Revert the work file(s) in the current VC fileset to 
the last revision
 @findex vc-revert
 @vindex vc-revert-show-diff
   If you want to discard all the changes you have made to the current
-VC fileset, type @kbd{C-x v u} (@code{vc-revert}).  This shows
-you a diff between the work file(s) and the revision from which you
-started editing, and asks for confirmation for discarding the changes.
-If you agree, the fileset is reverted.  If you don't want @kbd{C-x v
-u} to show a diff, set the variable @code{vc-revert-show-diff} to
-@code{nil} (you can still view the diff directly with @kbd{C-x v =};
-@pxref{Old Revisions}).
+VC fileset, type @kbd{C-x v u} (@code{vc-revert}).  This will ask you
+for confirmation before discarding the changes.  If you agree, the
+fileset is reverted.
+
+  If @code{vc-revert-show-diff} is non-@code{nil}, this command will
+show you a diff between the work file(s) and the revision from which
+you started editing.  Afterwards, the diff buffer will either be
+killed (if this variable is @code{kill}), or the buffer will be buried
+(any other non-@code{nil} value).  If you don't want @kbd{C-x v u} to
+show a diff, set this variable to @code{nil} (you can still view the
+diff directly with @kbd{C-x v =}; @pxref{Old Revisions}).
 
   On locking-based version control systems, @kbd{C-x v u} leaves files
 unlocked; you must lock again to resume editing.  You can also use
@@ -2141,6 +2145,7 @@ identifier at point, it prompts for the identifier.  (If 
you want it
 to always prompt, customize @code{xref-prompt-for-identifier} to
 @code{t}.)
 
+@vindex xref-auto-jump-to-first-definition
 If the specified identifier has only one definition, the command jumps
 to it.  If the identifier has more than one possible definition (e.g.,
 in an object-oriented language, or if there's a function and a
@@ -2148,7 +2153,22 @@ variable by the same name), the command shows the 
candidate
 definitions in the @file{*xref*} buffer, together with the files in
 which these definitions are found.  Selecting one of these candidates
 by typing @kbd{@key{RET}} or clicking @kbd{mouse-2} will pop a buffer
-showing the corresponding definition.
+showing the corresponding definition.  If the value of the variable
+@code{xref-auto-jump-to-first-definition} is @code{move}, the first
+candidate is automatically selected, and if it's @code{t} or
+@code{show}, the first candidate is automatically shown.  The default
+value is @code{nil}, which just shows the candidates in the
+@file{*xref*} buffer, but doesn't select any of them.
+
+@vindex xref-auto-jump-to-first-xref
+  If the value of the variable @code{xref-auto-jump-to-first-xref} is
+@code{t}, @emph{all} Xref commands automatically jump to the first
+result.  If the value is @code{show}, the first result is shown, but
+the window showing the @file{*xref*} buffer is left selected.  If the
+value is @code{move}, the first result is selected in the
+@file{*xref*} buffer, but is not shown.  The default value is
+@code{nil}, which just shows the results in the @file{*xref*} buffer,
+but doesn't select any of them.
 
   When entering the identifier argument to @kbd{M-.}, the usual
 minibuffer completion commands can be used (@pxref{Completion}), with
@@ -2218,10 +2238,16 @@ the special XREF mode:
 
 @table @kbd
 @item @key{RET}
-@itemx mouse-2
+@itemx mouse-1
 Display the reference on the current line (@code{xref-goto-xref}).
 With prefix argument, also bury the @file{*xref*} buffer.
 
+@item mouse-2
+@findex xref-select-and-show-xref
+The same as @code{mouse-1}, but make the window displaying the
+@file{*xref*} buffer the selected window
+(@code{xref-select-and-show-xref}).
+
 @item n
 @itemx .
 @findex xref-next-line
@@ -2259,8 +2285,8 @@ the match with @var{replacement}.  @xref{Identifier 
Search}.
 Refresh the contents of the @file{*xref*} buffer
 (@code{xref-revert-buffer}.
 
-@findex xref-quit
 @item q
+@findex xref-quit
 Quit the window showing the @file{*xref*} buffer (@code{xref-quit}).
 @end table
 
diff --git a/doc/emacs/misc.texi b/doc/emacs/misc.texi
index 528cfa9..47e3e11 100644
--- a/doc/emacs/misc.texi
+++ b/doc/emacs/misc.texi
@@ -1113,6 +1113,19 @@ subshell:
 @end example
 @end table
 
+By default, Shell mode handles common @acronym{ANSI} escape codes (for
+instance, for changing the color of text).  Emacs also optionally
+supports some extend escape codes, like some of the @acronym{OSC}
+(Operating System Codes) if you put the following in your init file:
+
+@lisp
+(add-hook 'comint-output-filter-functions 'comint-osc-process-output)
+@end lisp
+
+With this enabled, the output from, for instance, @code{ls
+--hyperlink} will be made into clickable buttons in the Shell mode
+buffer.
+
 @cindex Comint mode
 @cindex mode, Comint
   Shell mode is a derivative of Comint mode, a general-purpose mode for
diff --git a/doc/emacs/mule.texi b/doc/emacs/mule.texi
index 22b3677..81aabfb 100644
--- a/doc/emacs/mule.texi
+++ b/doc/emacs/mule.texi
@@ -1330,6 +1330,12 @@ You can do this by putting
 @noindent
 in your init file.
 
+@findex w32-set-console-codepage
+  Setting @code{keyboard-coding-system} has no effect on MS-Windows,
+except on old Windows 9X systems, in which case the encoding must
+match the current codepage of the MS-Windows console, which can be
+changed by calling @code{w32-set-console-codepage}.
+
   There is a similarity between using a coding system translation for
 keyboard input, and using an input method: both define sequences of
 keyboard input that translate into single characters.  However, input
diff --git a/doc/emacs/programs.texi b/doc/emacs/programs.texi
index fe3ee57..09216c2 100644
--- a/doc/emacs/programs.texi
+++ b/doc/emacs/programs.texi
@@ -1098,13 +1098,13 @@ match the last comment before point in the buffer, and 
then does a
 expression that is the value of the variable @code{comment-start-skip}.
 Make sure this regexp does not match the null string.  It may match more
 than the comment starting delimiter in the strictest sense of the word;
-for example, in C mode the value of the variable is
+for example, in C mode the value of the variable could be
 @c This stops M-q from breaking the line inside that @code.
-@code{@w{"\\(//+\\|/\\*+\\)\\s *"}}, which matches extra stars and
-spaces after the @samp{/*} itself, and accepts C++ style comments
-also.  (Note that @samp{\\} is needed in Lisp syntax to include a
-@samp{\} in the string, which is needed to deny the first star its
-special meaning in regexp syntax.  @xref{Regexp Backslash}.)
+@code{@w{"/\\*+[ \t]*\\|//+[ \t]*"}}, which matches extra stars and
+spaces after the @samp{/*} itself, and accepts C++ style (@samp{//})
+comments also.  (Note that @samp{\\} is needed in Lisp syntax to
+include a @samp{\} in the string, which is needed to deny the first
+star its special meaning in regexp syntax.  @xref{Regexp Backslash}.)
 
 @vindex comment-start
 @vindex comment-end
diff --git a/doc/emacs/text.texi b/doc/emacs/text.texi
index 3b9d5c2..dc8ca90 100644
--- a/doc/emacs/text.texi
+++ b/doc/emacs/text.texi
@@ -572,7 +572,7 @@ Set the fill column (@code{set-fill-column}).
 Fill each paragraph in the region (@code{fill-region}).
 @item M-x fill-region-as-paragraph
 Fill the region, considering it as one paragraph.
-@item M-o M-s
+@item M-x center-line
 Center a line.
 @end table
 
@@ -621,10 +621,9 @@ numeric argument, it uses that as the new fill column.  
With just
 @kbd{C-u} as argument, it sets @code{fill-column} to the current
 horizontal position of point.
 
-@kindex M-o M-s @r{(Text mode)}
 @cindex centering
 @findex center-line
-  The command @kbd{M-o M-s} (@code{center-line}) centers the current line
+  The command @kbd{M-x center-line} centers the current line
 within the current fill column.  With an argument @var{n}, it centers
 @var{n} lines individually and moves past them.  This binding is
 made by Text mode and is available only in that and related modes
diff --git a/doc/lispintro/emacs-lisp-intro.texi 
b/doc/lispintro/emacs-lisp-intro.texi
index fade409..7933ebe 100644
--- a/doc/lispintro/emacs-lisp-intro.texi
+++ b/doc/lispintro/emacs-lisp-intro.texi
@@ -14650,7 +14650,9 @@ Let's re-use @kbd{C-c =} as a convenient keybinding:
 
 Now we can try out @code{count-words-defun}: install both
 @code{count-words-in-defun} and @code{count-words-defun}, and set the
-keybinding, and then place the cursor within the following definition:
+keybinding.  Then copy the following to an Emacs Lisp buffer (like,
+for instance, @file{*scratch*}), place the cursor within the
+definition, and use the @kbd{C-c =} command.
 
 @smallexample
 @group
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index 79fb72a..510efaf 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -152,6 +152,9 @@ truncation; a @samp{\} on the rightmost column indicates a 
line that
 wraps.  (The display table can specify alternate characters to use
 for this; @pxref{Display Tables}).
 
+   Since wrapping and truncation of text contradict each other, Emacs
+turns off line truncation when wrapping is requested, and vice versa.
+
 @defopt truncate-lines
 If this buffer-local variable is non-@code{nil}, lines that extend
 beyond the right edge of the window are truncated; otherwise, they are
@@ -646,9 +649,9 @@ If the value is zero, then command input is not echoed.
 
 @defvar message-truncate-lines
 Normally, displaying a long message resizes the echo area to display
-the entire message.  But if the variable @code{message-truncate-lines}
-is non-@code{nil}, the echo area does not resize, and the message is
-truncated to fit it.
+the entire message, wrapping long line as needed.  But if the variable
+@code{message-truncate-lines} is non-@code{nil}, long lines of
+echo-area message are instead truncated to fit the mini-window width.
 @end defvar
 
   The variable @code{max-mini-window-height}, which specifies the
@@ -5970,7 +5973,7 @@ To @var{svg} add an embedded (raster) image placed at
 @code{:base-uri} specifies a (possibly non-existing) file name of the
 svg image to be created, thus all the embedded files are searched
 relatively to the @code{:base-uri} filename's directory.  If
-@code{:base-uri} is ommited, then filename from where svg image is
+@code{:base-uri} is omitted, then filename from where svg image is
 loaded is used.  Using @code{:base-uri} improves the performance of
 embedding large images, comparing to @code{svg-embed}, because all the
 work is done directly by librsvg.
diff --git a/doc/lispref/eval.texi b/doc/lispref/eval.texi
index 7893895..e199884 100644
--- a/doc/lispref/eval.texi
+++ b/doc/lispref/eval.texi
@@ -862,8 +862,13 @@ expressions that were read, evaluated, and printed from 
buffers
 (including the minibuffer) by the standard Emacs commands which do
 this.  (Note that this does @emph{not} include evaluation in
 @file{*ielm*} buffers, nor evaluation using @kbd{C-j}, @kbd{C-x C-e},
-and similar evaluation commands in @code{lisp-interaction-mode}.)  The
-elements are ordered most recent first.
+and similar evaluation commands in @code{lisp-interaction-mode}.)
+
+This variable is obsolete, and will be removed in a future version,
+since it constantly enlarges the memory footprint of the Emacs
+process.  For that reason, we recommend against using it.
+
+The elements of @code{values} are ordered most recent first.
 
 @example
 @group
@@ -880,8 +885,8 @@ values
 @end group
 @end example
 
-This variable is useful for referring back to values of forms recently
-evaluated.  It is generally a bad idea to print the value of
+This variable could be useful for referring back to values of forms
+recently evaluated.  It is generally a bad idea to print the value of
 @code{values} itself, since this may be very long.  Instead, examine
 particular elements, like this:
 
diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi
index 266501d..d104570 100644
--- a/doc/lispref/files.texi
+++ b/doc/lispref/files.texi
@@ -936,6 +936,16 @@ file in @file{/foo/} will give an error:
 @end example
 @end defun
 
+@defmac with-existing-directory body@dots{}
+This macro ensures that @code{default-directory} is bound to an
+existing directory before executing @var{body}.  If
+@code{default-directory} already exists, that's preferred, and
+otherwise some other directory is used.  This macro can be useful, for
+instance, when calling an external command that requires that it's
+running in a directory that exists.  The chosen directory is not
+guaranteed to be writable.
+@end defmac
+
 @defun access-file filename string
 If you can read @var{filename} this function returns @code{nil};
 otherwise it signals an error
diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi
index 25706be..477c105 100644
--- a/doc/lispref/frames.texi
+++ b/doc/lispref/frames.texi
@@ -2692,18 +2692,19 @@ frame and defaults to the selected frame.  It never 
returns a frame
 whose @code{no-other-frame} parameter (@pxref{Frame Interaction
 Parameters}) is non-@code{nil}.
 
-The second argument, @var{minibuf}, says which frames to consider:
+The second argument, @var{minibuf}, says which frames to consider when
+deciding what the next frame should be:
 
 @table @asis
 @item @code{nil}
-Exclude minibuffer-only frames.
+Consider all frames except minibuffer-only frames.
 @item @code{visible}
-Consider all visible frames.
+Consider only visible frames.
 @item 0
-Consider all visible or iconified frames.
+Consider only visible or iconified frames.
 @item a window
 Consider only the frames using that particular window as their
-minibuffer.
+minibuffer window.
 @item anything else
 Consider all frames.
 @end table
diff --git a/doc/lispref/lists.texi b/doc/lispref/lists.texi
index ac99835..bbe1dce 100644
--- a/doc/lispref/lists.texi
+++ b/doc/lispref/lists.texi
@@ -1557,10 +1557,12 @@ of property lists and association lists.
 @defun assoc key alist &optional testfn
 This function returns the first association for @var{key} in
 @var{alist}, comparing @var{key} against the alist elements using
-@var{testfn} if it is non-@code{nil} and @code{equal} otherwise
-(@pxref{Equality Predicates}).  It returns @code{nil} if no
-association in @var{alist} has a @sc{car} equal to @var{key}.  For
-example:
+@var{testfn} if it is a function, and @code{equal} otherwise
+(@pxref{Equality Predicates}).  If @var{testfn} is a function, it is
+called with two arguments: the @sc{car} of an element from @var{alist}
+and @var{key}.  The function returns @code{nil} if no
+association in @var{alist} has a @sc{car} equal to @var{key}, as
+tested by @var{testfn}.  For example:
 
 @smallexample
 (setq trees '((pine . cones) (oak . acorns) (maple . seeds)))
diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi
index d9caeab..ee55f98 100644
--- a/doc/lispref/modes.texi
+++ b/doc/lispref/modes.texi
@@ -471,6 +471,22 @@ Each face that the mode defines should, if possible, 
inherit from an
 existing Emacs face.  @xref{Basic Faces}, and @ref{Faces for Font Lock}.
 
 @item
+Consider adding a mode-specific menu to the menu bar.  This should
+preferably include the most important menu-specific settings and
+commands that will allow users discovering the main features quickly
+and efficiently.
+
+@item
+@cindex context menus, for a major mode
+@vindex context-menu-functions
+Consider adding mode-specific context menus for the mode, to be used
+if and when users activate the @code{context-menu-mode} (@pxref{Menu
+Mouse Clicks,,, emacs, The Emacs Manual}).  To this end, define a
+mode-specific function which builds one or more menus depending on the
+location of the @kbd{mouse-3} click in the buffer, and then add that
+function to the buffer-local value of @code{context-menu-functions}.
+
+@item
 The mode should specify how Imenu should find the definitions or
 sections of a buffer, by setting up a buffer-local value for the
 variable @code{imenu-generic-expression}, for the two variables
@@ -3299,6 +3315,11 @@ This function tells Font Lock mode to run the Lisp 
function
 current buffer.  It calls @var{function} before calling the default
 fontification functions, and gives it two arguments, @var{start} and
 @var{end}, which specify the region to be fontified or refontified.
+If @var{function} performs fontifications, it can return a list of the
+form @w{@code{(jit-lock-bounds @var{beg} . @var{end})}}, to indicate
+the bounds of the region it actually fontified; JIT font-lock will use
+this information to optimize subsequent redisplay cycles and regions
+of buffer text it will pass to future calls to @var{function}.
 
 The optional argument @var{contextual}, if non-@code{nil}, forces Font
 Lock mode to always refontify a syntactically relevant part of the
diff --git a/doc/lispref/nonascii.texi b/doc/lispref/nonascii.texi
index c22930d..0cc2b7e 100644
--- a/doc/lispref/nonascii.texi
+++ b/doc/lispref/nonascii.texi
@@ -1988,7 +1988,9 @@ for decoding keyboard input from @var{terminal}.  If
 @var{coding-system} is @code{nil}, that means not to decode keyboard
 input.  If @var{terminal} is a frame, it means that frame's terminal;
 if it is @code{nil}, that means the currently selected frame's
-terminal.  @xref{Multiple Terminals}.
+terminal.  @xref{Multiple Terminals}.  Note that on modern MS-Windows
+systems Emacs always uses Unicode input when decoding keyboard input,
+so the encoding set by this command has no effect on Windows.
 @end deffn
 
 @defun terminal-coding-system &optional terminal
diff --git a/doc/lispref/searching.texi b/doc/lispref/searching.texi
index 4d5ae3c..68061f0 100644
--- a/doc/lispref/searching.texi
+++ b/doc/lispref/searching.texi
@@ -1649,6 +1649,24 @@ extra actual argument values not matched by any other 
parameter in
 Since the definition is global, it is recommended to give @var{name} a
 package prefix to avoid name clashes with definitions elsewhere, as is
 usual when naming non-local variables and functions.
+
+Forms defined this way only perform simple template substitution.
+For arbitrary computations, use them together with with the @code{rx}
+forms @code{eval}, @code{regexp} or @code{literal}.  Example:
+
+@example
+@group
+(defun n-tuple-rx (n element)
+  `(seq "<"
+        (group-n 1 ,element)
+        ,@@(mapcar (lambda (i) `(seq ?, (group-n ,i ,element)))
+                  (number-sequence 2 n))
+        ">"))
+(rx-define n-tuple (n element) (eval (n-tuple-rx n 'element)))
+(rx (n-tuple 3 (+ (in "0-9"))))
+  @result{} "<\\(?1:[0-9]+\\),\\(?2:[0-9]+\\),\\(?3:[0-9]+\\)>"
+@end group
+@end example
 @end defmac
 
 @defmac rx-let (bindings@dots{}) body@dots{}
diff --git a/doc/lispref/tips.texi b/doc/lispref/tips.texi
index 8aa225a..f0eb107 100644
--- a/doc/lispref/tips.texi
+++ b/doc/lispref/tips.texi
@@ -755,6 +755,14 @@ anchor}.  The Info file name defaults to @samp{emacs}.  
For example,
 See Info node `Font Lock' and Info node `(elisp)Font Lock Basics'.
 @end smallexample
 
+To link to a customization group, write the single-quoted name of the
+group, preceded by @samp{customization group} (the first character in
+each word is case-insensitive).  For example,
+
+@smallexample
+See the customization group `whitespace' for details.
+@end smallexample
+
 Finally, to create a hyperlink to URLs, write the single-quoted URL,
 preceded by @samp{URL}.  For example,
 
diff --git a/doc/lispref/variables.texi b/doc/lispref/variables.texi
index 9356fb9..3b03318 100644
--- a/doc/lispref/variables.texi
+++ b/doc/lispref/variables.texi
@@ -194,7 +194,7 @@ default scoping rule in Emacs Lisp is called @dfn{dynamic 
scoping},
 which simply states that the current binding at any given point in the
 execution of a program is the most recently-created binding for that
 variable that still exists.  For details about dynamic scoping, and an
-alternative scoping rule called @dfn{lexical scoping}, @xref{Variable
+alternative scoping rule called @dfn{lexical scoping}, @pxref{Variable
 Scoping}.
 
   The special forms @code{let} and @code{let*} exist to create local
@@ -286,6 +286,22 @@ being run once:
 @end lisp
 @end defspec
 
+@cindex dynamic binding, temporarily
+@cindex dynamic let-binding
+@defspec dlet (bindings@dots{}) forms@dots{}
+This special form is like @code{let}, but it binds all variables
+dynamically.  This is rarely useful---you usually want to bind normal
+variables lexically, and special variables (i.e., variables that are
+defined with @code{defvar}) dynamically, and this is what @code{let}
+does.
+
+@code{dlet} can be useful when interfacing with old code that assumes
+that certain variables are dynamically bound (@pxref{Dynamic
+Binding}), but it's impractical to @code{defvar} these variables.
+@code{dlet} will temporarily make the bound variables special, execute
+the forms, and then make the variables non-special again.
+@end defspec
+
   Here is a complete list of the other facilities that create local
 bindings:
 
diff --git a/doc/misc/cl.texi b/doc/misc/cl.texi
index c89e0e7..a6c3c32 100644
--- a/doc/misc/cl.texi
+++ b/doc/misc/cl.texi
@@ -3962,22 +3962,22 @@ In the simplest case, @var{name} and each of the 
@var{slots}
 are symbols.  For example,
 
 @example
-(cl-defstruct person name age sex)
+(cl-defstruct person first-name age sex)
 @end example
 
 @noindent
-defines a struct type called @code{person} that contains three
-slots.  Given a @code{person} object @var{p}, you can access those
-slots by calling @code{(person-name @var{p})}, @code{(person-age @var{p})},
-and @code{(person-sex @var{p})}.  You can also change these slots by
-using @code{setf} on any of these place forms, for example:
+defines a struct type called @code{person} that contains three slots.
+Given a @code{person} object @var{p}, you can access those slots by
+calling @code{(person-first-name @var{p})}, @code{(person-age
+@var{p})}, and @code{(person-sex @var{p})}.  You can also change these
+slots by using @code{setf} on any of these place forms, for example:
 
 @example
 (cl-incf (person-age birthday-boy))
 @end example
 
 You can create a new @code{person} by calling @code{make-person},
-which takes keyword arguments @code{:name}, @code{:age}, and
+which takes keyword arguments @code{:first-name}, @code{:age}, and
 @code{:sex} to specify the initial values of these slots in the
 new object.  (Omitting any of these arguments leaves the corresponding
 slot ``undefined'', according to the Common Lisp standard; in Emacs
@@ -3989,7 +3989,7 @@ object of the same type whose slots are @code{eq} to 
those of @var{p}.
 Given any Lisp object @var{x}, @code{(person-p @var{x})} returns
 true if @var{x} is a @code{person}, and false otherwise.
 
-Accessors like @code{person-name} normally check their arguments
+Accessors like @code{person-first-name} normally check their arguments
 (effectively using @code{person-p}) and signal an error if the
 argument is the wrong type.  This check is affected by
 @code{(optimize (safety @dots{}))} declarations.  Safety level 1,
@@ -4002,13 +4002,13 @@ always print a descriptive error message for incorrect 
inputs.
 @xref{Declarations}.
 
 @example
-(setq dave (make-person :name "Dave" :sex 'male))
+(setq dave (make-person :first-name "Dave" :sex 'male))
      @result{} [cl-struct-person "Dave" nil male]
 (setq other (copy-person dave))
      @result{} [cl-struct-person "Dave" nil male]
 (eq dave other)
      @result{} nil
-(eq (person-name dave) (person-name other))
+(eq (person-first-name dave) (person-first-name other))
      @result{} t
 (person-p dave)
      @result{} t
@@ -4021,7 +4021,7 @@ always print a descriptive error message for incorrect 
inputs.
 @end example
 
 In general, @var{name} is either a name symbol or a list of a name
-symbol followed by any number of @dfn{struct options}; each @var{slot}
+symbol followed by any number of @dfn{structure options}; each @var{slot}
 is either a slot symbol or a list of the form @samp{(@var{slot-name}
 @var{default-value} @var{slot-options}@dots{})}.  The @var{default-value}
 is a Lisp form that is evaluated any time an instance of the
@@ -4029,7 +4029,7 @@ structure type is created without specifying that slot's 
value.
 
 @example
 (cl-defstruct person
-     (name nil :read-only t)
+     (first-name nil :read-only t)
      age
      (sex 'unknown))
 @end example
@@ -4062,7 +4062,7 @@ enclosed in lists.)
 (cl-defstruct (person (:constructor create-person)
                       (:type list)
                       :named)
-     name age sex)
+     first-name age sex)
 @end example
 
 The following structure options are recognized.
@@ -4108,12 +4108,12 @@ option.
     (person
      (:constructor nil)   ; no default constructor
      (:constructor new-person
-                   (name sex &optional (age 0)))
-     (:constructor new-hound (&key (name "Rover")
+                   (first-name sex &optional (age 0)))
+     (:constructor new-hound (&key (first-name "Rover")
                                    (dog-years 0)
                               &aux (age (* 7 dog-years))
                                    (sex 'canine))))
-    name age sex)
+    first-name age sex)
 @end example
 
 The first constructor here takes its arguments positionally rather
@@ -4165,16 +4165,16 @@ slot descriptors for slots in the included structure, 
possibly with
 modified default values.  Borrowing an example from Steele:
 
 @example
-(cl-defstruct person name (age 0) sex)
+(cl-defstruct person first-name (age 0) sex)
         @result{} person
 (cl-defstruct (astronaut (:include person (age 45)))
      helmet-size
      (favorite-beverage 'tang))
         @result{} astronaut
 
-(setq joe (make-person :name "Joe"))
+(setq joe (make-person :first-name "Joe"))
      @result{} [cl-struct-person "Joe" 0 nil]
-(setq buzz (make-astronaut :name "Buzz"))
+(setq buzz (make-astronaut :first-name "Buzz"))
      @result{} [cl-struct-astronaut "Buzz" 45 nil nil tang]
 
 (list (person-p joe) (person-p buzz))
@@ -4182,17 +4182,17 @@ modified default values.  Borrowing an example from 
Steele:
 (list (astronaut-p joe) (astronaut-p buzz))
      @result{} (nil t)
 
-(person-name buzz)
+(person-first-name buzz)
      @result{} "Buzz"
-(astronaut-name joe)
-     @result{} error: "astronaut-name accessing a non-astronaut"
+(astronaut-first-name joe)
+     @result{} error: "astronaut-first-name accessing a non-astronaut"
 @end example
 
 Thus, if @code{astronaut} is a specialization of @code{person},
 then every @code{astronaut} is also a @code{person} (but not the
 other way around).  Every @code{astronaut} includes all the slots
 of a @code{person}, plus extra slots that are specific to
-astronauts.  Operations that work on people (like @code{person-name})
+astronauts.  Operations that work on people (like @code{person-first-name})
 work on astronauts just like other people.
 
 @item :noinline
@@ -4230,10 +4230,10 @@ records, which are always tagged.  Therefore, 
@code{:named} is only
 useful in conjunction with @code{:type}.
 
 @example
-(cl-defstruct (person1) name age sex)
-(cl-defstruct (person2 (:type list) :named) name age sex)
-(cl-defstruct (person3 (:type list)) name age sex)
-(cl-defstruct (person4 (:type vector)) name age sex)
+(cl-defstruct (person1) first-name age sex)
+(cl-defstruct (person2 (:type list) :named) first-name age sex)
+(cl-defstruct (person3 (:type list)) first-name age sex)
+(cl-defstruct (person4 (:type vector)) first-name age sex)
 
 (setq p1 (make-person1))
      @result{} #s(person1 nil nil nil)
@@ -4254,10 +4254,10 @@ useful in conjunction with @code{:type}.
 
 Since unnamed structures don't have tags, @code{cl-defstruct} is not
 able to make a useful predicate for recognizing them.  Also,
-accessors like @code{person3-name} will be generated but they
-will not be able to do any type checking.  The @code{person3-name}
+accessors like @code{person3-first-name} will be generated but they
+will not be able to do any type checking.  The @code{person3-first-name}
 function, for example, will simply be a synonym for @code{car} in
-this case.  By contrast, @code{person2-name} is able to verify
+this case.  By contrast, @code{person2-first-name} is able to verify
 that its argument is indeed a @code{person2} object before
 proceeding.
 
diff --git a/doc/misc/message.texi b/doc/misc/message.texi
index c0e3dfa..4136ad8 100644
--- a/doc/misc/message.texi
+++ b/doc/misc/message.texi
@@ -1699,14 +1699,15 @@ result is inserted.
 @cindex Sv
 @cindex Re
 Responses to messages have subjects that start with @samp{Re: }.  This
-is @emph{not} an abbreviation of the English word ``response'', but is
-Latin, and means ``in response to''.  Some illiterate nincompoops have
-failed to grasp this fact, and have ``internationalized'' their software
-to use abominations like @samp{Aw: } (``antwort'') or @samp{Sv: }
-(``svar'') instead, which is meaningless and evil.  However, you may
-have to deal with users that use these evil tools, in which case you may
-set this variable to a regexp that matches these prefixes.  Myself, I
-just throw away non-compliant mail.
+is @emph{not} an abbreviation of the English word ``response'', but it
+comes from the Latin ``res'', and means ``in the matter of''.  Some
+illiterate nincompoops have failed to grasp this fact, and have
+``internationalized'' their software to use abominations like
+@samp{Aw: } (``antwort'') or @samp{Sv: } (``svar'') instead, which is
+meaningless and evil.  However, you may have to deal with users that
+use these evil tools, in which case you may set this variable to a
+regexp that matches these prefixes.  Myself, I just throw away
+non-compliant mail.
 
 Here's an example of a value to deal with these headers when
 responding to a message:
diff --git a/doc/misc/mh-e.texi b/doc/misc/mh-e.texi
index a7c1fed..d2b81a6 100644
--- a/doc/misc/mh-e.texi
+++ b/doc/misc/mh-e.texi
@@ -8816,8 +8816,8 @@ hands several times since then. Jim Larus wanted to do 
something
 similar for GNU Emacs, and ended up completely rewriting it that same
 year. In 1989, Stephen Gildea picked it up and added many
 improvements. Bill Wohler then took over in 2000 and moved its
-development to @uref{https://sourceforge.net/, SourceForge} where it
-lives today.
+development to @uref{https://sourceforge.net/, SourceForge}.
+Since 2016, MH-E development occurs within the Emacs repository.
 
 @menu
 * From Brian Reid::
diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi
index bd9bd99..b2dcddc 100644
--- a/doc/misc/tramp.texi
+++ b/doc/misc/tramp.texi
@@ -3745,19 +3745,20 @@ tty, or not.  This is controlled by the variable
 @value{tramp} is based on running shells on the remote host, which
 require a pseudo tty.  Therefore, it declares the variable
 @code{tramp-process-connection-type}, which carries this information
-for remote processes.  Per default, its value is @code{t}.  The name
-of the remote pseudo tty is returned by the function
-@code{process-tty-name}.
+for remote processes.  Per default, its value is @code{t}, and there's
+no need to change it.  The name of the remote pseudo tty is returned
+by the function @code{process-tty-name}.
 
 If a remote process, started by @code{start-file-process}, shouldn't
-use a pseudo tty, this is emulated by let-binding this variable to
-@code{nil} or @code{pipe}.  There is still a pseudo tty for the
-started process, but some terminal properties are changed, like
-suppressing translation of carriage return characters into newline.
+use a pseudo tty, this can be indicated by setting
+@code{process-connection-type} to @code{nil} or @code{pipe}.  There is
+still a pseudo tty for the started process, but some terminal
+properties are changed, like suppressing translation of carriage
+return characters into newline.
 
 The function @code{make-process} allows an explicit setting by the
 @code{:connection-type} keyword.  If this keyword is not used, the
-value of @code{tramp-process-connection-type} is applied instead.
+value of @code{process-connection-type} is applied instead.
 
 
 @anchor{Improving performance of asynchronous remote processes}
diff --git a/etc/DISTRIB b/etc/DISTRIB
index 610c347..3dd1bf3 100644
--- a/etc/DISTRIB
+++ b/etc/DISTRIB
@@ -73,8 +73,7 @@ you can contribute.
 Your donations will help to support the development of additional GNU
 software.  GNU/Linux systems (variants of GNU, based on the kernel
 Linux) have millions of users, but there is still much to be done.
-For more information on GNU, see the file 'GNU' in this directory (see
-above).
+For more information on GNU, visit https://www.gnu.org/.
 
                        Richard M Stallman
                        Chief GNUisance, Founder of the FSF
diff --git a/etc/NEWS b/etc/NEWS
index aaff30b..f033176 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1,6 +1,6 @@
 GNU Emacs NEWS -- history of user-visible changes.
 
-Copyright (C) 2017-2021 Free Software Foundation, Inc.
+Copyright (C) 2019-2021 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 Please send Emacs bug reports to 'bug-gnu-emacs@gnu.org'.
@@ -31,9 +31,6 @@ and also requires GCC and Binutils to be available when Lisp 
code is
 natively compiled.  See the Info node "(elisp) Native Compilation" for
 more details.
 
----
-** Support for building with Motif has been removed.
-
 ** The Cairo graphics library is now used by default if present.
 '--with-cairo' is now the default, if the appropriate development files
 are found by 'configure'.  Note that building with Cairo means using
@@ -52,11 +49,6 @@ default.  We strongly recommend building with HarBuzz 
support.  'x' is
 still a valid backend.
 
 ---
-** Building without double buffering support.
-'configure --with-xdbe=no' can now be used to disable double buffering
-at build time.
-
----
 ** 'configure' now warns about building with libXft support.
 libXft is unmaintained, and causes a number of problems with modern
 fonts including but not limited to crashes; support for it may be
@@ -70,8 +62,12 @@ available, and this is the Cairo graphics library + HarfBuzz 
for font
 shaping, so 'configure' now recommends that combination.
 
 ---
-** The ftx font backend driver has been removed.
-It was declared obsolete in Emacs 27.1.
+** Building without double buffering support.
+'configure --with-xdbe=no' can now be used to disable double buffering
+at build time.
+
+---
+** Support for building with Motif has been removed.
 
 ---
 ** The configure option '--without-makeinfo' has been removed.
@@ -84,6 +80,10 @@ GCC has withdrawn the '-fcheck-pointer-bounds' option and 
support for
 its implementation has been removed from the Linux kernel.
 
 ---
+** The ftx font backend driver has been removed.
+It was declared obsolete in Emacs 27.1.
+
+---
 ** Emacs no longer supports old OpenBSD systems.
 OpenBSD 5.3 and older releases are no longer supported, as they lack
 proper pty support that Emacs needs.
@@ -92,20 +92,16 @@ proper pty support that Emacs needs.
 * Startup Changes in Emacs 28.1
 
 ---
-** File names given on the command line will now be pushed onto
-'file-name-history'.
-
----
 ** In GTK builds, Emacs now supports startup notification.
 This means that Emacs won't steal keyboard focus upon startup
 (when started via the Desktop) if the user is typing into another
 application.
 
-** Emacs can support 24-bit color TTY without terminfo database.
-If your text-mode terminal supports 24-bit true color, but your system
-lacks the terminfo database, you can instruct Emacs to support 24-bit
-true color by setting 'COLORTERM=truecolor' in the environment.  This is
-useful on systems such as FreeBSD which ships only with "etc/termcap".
+---
+** Errors in 'kill-emacs-hook' no longer prevent Emacs from shutting down.
+If a function in that hook signals an error in an interactive Emacs,
+the user will be prompted on whether to continue.  If the user doesn't
+answer within five seconds, Emacs will continue shutting down anyway.
 
 ** Emacs now supports loading a Secure Computing filter.
 This is supported only on capable GNU/Linux systems.  To activate,
@@ -118,80 +114,56 @@ avoid security issues when executing untrusted code.  See 
the manual
 page for 'seccomp' system call, for details about Secure Computing
 filters.
 
-** Setting 'fill-column' to nil is obsolete.
-This undocumented use of 'fill-column' is now obsolete.  To disable
-auto filling, turn off 'auto-fill-mode' instead.
-
-For instance, you could add something like the following to your init
-file:
+** Emacs can support 24-bit color TTY without terminfo database.
+If your text-mode terminal supports 24-bit true color, but your system
+lacks the terminfo database, you can instruct Emacs to support 24-bit
+true color by setting 'COLORTERM=truecolor' in the environment.  This is
+useful on systems such as FreeBSD which ships only with "etc/termcap".
 
-    (add-hook 'foo-mode-hook (lambda () (auto-fill-mode -1))
+---
+** File names given on the command line are now be pushed onto history.
+The file names will be pushed onto 'file-name-history', like the names
+of files visited via 'C-x C-f' and other commands.
 
 
 * Changes in Emacs 28.1
 
-** 'blink-cursor-mode' is now enabled by default regardless of the UI.
-It used to be enabled when Emacs is started in GUI mode but not when started
-in text mode.  The cursor still only actually blinks in GUI frames.
-
 +++
-** Etags now supports the Mercury programming language.
-See https://mercurylang.org.
-
-+++
-** Etags command line option '--declarations' now has Mercury-specific 
behavior.
-All Mercury declarations are tagged by default.  However, for
-compatibility with 'etags' support for Prolog, predicates and
-functions appearing first in clauses will also be tagged if 'etags' is
-invoked with the '--declarations' command-line option.
-
-+++
-** New command 'font-lock-update', bound to 'C-x x f'.
-This command updates the syntax highlighting in this buffer.
+** New command 'execute-extended-command-for-buffer'.
+This new command, bound to 'M-S-x', works like
+'execute-extended-command', but limits the set of commands to the
+commands that have been determined to be particularly useful with the
+current mode.
 
 +++
-** A new standard face 'font-lock-doc-markup-face'.
-Intended for documentation mark-up syntax and tags inside text that
-uses 'font-lock-doc-face', with which it should harmonise.  It would
-typically be used in structured documentation comments in program
-source code by language-specific modes, for mark-up conventions like
-Haddock, Javadoc or Doxygen.  By default this face inherits from
-'font-lock-constant-face'.
-
-** The new NonGNU ELPA archive is enabled by default alongside GNU ELPA.
+** New user option 'read-extended-command-predicate'.
+This user option controls how 'M-x' performs completion of commands when
+you type 'TAB'.  By default, any command that matches what you have
+typed is considered a completion candidate, but you can customize this
+option to exclude commands that are not applicable to the current
+buffer's major and minor modes, and respect the command's completion
+predicate (if any).
 
 +++
-** New command 'recenter-other-window', bound to 'S-M-C-l'.
-Like 'recenter-top-bottom' acting in the other window.
-
-** Minibuffer scrolling is now conservative by default.
-This is controlled by the new variable 'scroll-minibuffer-conservatively'.
+** Completion on 'M-x' shows key bindings for commands.
+When 'suggest-key-bindings' is non-nil (as it is by default), the
+completion list popped up by 'M-x' shows the key bindings for all the
+commands shown in the list of candidate completions that have a key
+binding.
 
-In addition, there is a new variable
-'redisplay-adhoc-scroll-in-resize-mini-windows' to disable the
-ad-hoc auto-scrolling when resizing minibuffer windows.  It has been
-found that its heuristic can be counter productive in some corner
-cases, tho the cure may be worse than the disease.  This said, the
-effect should be negligible in the vast majority of cases anyway.
+** New user option 'completions-detailed'.
+When non-nil, some commands like 'describe-symbol' show more detailed
+completions with more information in completion prefix and suffix.
+The default is nil.
 
-+++
-** Improved handling of minibuffers on switching frames.
-By default, when you switch to another frame, an active minibuffer now
-moves to the newly selected frame.  Nevertheless, the effect of what
-you type in the minibuffer happens in the frame where the minibuffer
-was first activated.  An alternative behavior is available by
-customizing 'minibuffer-follows-selected-frame' to nil.  Here, the
-minibuffer stays in the frame where you first opened it, and you must
-switch back to this frame to continue or abort its command.  The old
-behavior, which mixed these two, can be approximated by customizing
-'minibuffer-follows-selected-frame' to a value which is neither nil
-nor t.
+---
+** 'C-s' in 'M-x' now once again searches over completions.
+In Emacs 23, typing 'M-x' ('read-extended-command') and then 'C-s' (to
+do an interactive search) would search over possible completions.
+This was lost in Emacs 24, but is now back again.
 
-+++
-** New user option 'read-minibuffer-restore-windows'.
-When customized to nil, it uses 'minibuffer-restore-windows' in
-'minibuffer-exit-hook' to remove only the window showing the
-"*Completions*" buffer.
+---
+** User option 'completions-format' supports a new value 'one-column'.
 
 +++
 ** New system for displaying documentation for groups of functions.
@@ -200,77 +172,125 @@ choosing a group, or clicking a button in the "*Help*" 
buffers when
 looking at the doc string of a function that belongs to one of these
 groups.
 
++++
+** New minor mode 'context-menu-mode' for context menus popped by 'mouse-3'.
+When this mode is enabled, clicking 'down-mouse-3' anywhere in the buffer
+pops up a menu whose contents depends on surrounding context near the
+mouse click.  You can change the order of the default sub-menus in the
+context menu by customizing the user option 'context-menu-functions'.
+You can also invoke the context menu by pressing 'S-<F10>'.
+
++++
+** A new keymap for buffer actions has been added.
+The 'C-x x' keymap now holds keystrokes for various buffer-oriented
+commands.  The new keystrokes are 'C-x x g' ('revert-buffer-quick'),
+'C-x x r' ('rename-buffer'), 'C-x x u' ('rename-uniquely'), 'C-x x n'
+('clone-buffer'), 'C-x x i' ('insert-buffer'), 'C-x x t'
+('toggle-truncate-lines') and 'C-x x f' ('font-lock-update').
+
++++
+** Modifiers now go outside angle brackets in pretty-printed key bindings.
+For example, 'RET' with Control and Meta modifiers is now shown as
+'C-M-<return>' instead of '<C-M-return>'.  Either variant can be used
+as input; functions such as 'kbd' and 'read-kbd-macro' accept both
+styles as equivalent (they have done so for a long time).
+
 ---
-** Improved "find definition" feature of "*Help*" buffers.
-Now clicking on the link to find the definition of functions generated
-by 'cl-defstruct', or variables generated by 'define-derived-mode',
-for example, will go to the exact place where they are defined.
+** 'eval-expression' no longer signals an error on incomplete expressions.
+Previously, typing 'M-: ( RET' would result in Emacs saying "End of
+file during parsing" and dropping out of the minibuffer.  The user
+would have to type 'M-: M-p' to edit and redo the expression.  Now
+Emacs will echo the message and allow the user to continue editing.
 
-** New variable 'redisplay-skip-initial-frame' to enable batch redisplay tests.
-Setting it to nil forces the redisplay to do its job even in the
-initial frame used in batch mode.
++++
+** 'eval-last-sexp' now handles 'defvar'/'defcustom'/'defface' specially.
+This command would previously not redefine values defined by these
+forms, but this command has now been changed to work more like
+'eval-defun', and reset the values as specified.
 
 ---
-** Support for the 'strike-through' face attribute on TTY frames.
-If your terminal's termcap or terminfo database entry has the 'smxx'
-capability defined, Emacs will now emit the prescribed escape
-sequences necessary to render faces with the 'strike-through'
-attribute on TTY frames.
+** New user option 'use-short-answers'.
+When non-nil, the function 'y-or-n-p' is used instead of
+'yes-or-no-p'.  This eliminates the need to define an alias that maps
+one to another in the init file.  The same user option also controls
+whether the function 'read-answer' accepts short answers.
 
 +++
-** Emacs now defaults to UTF-8 instead of ISO-8859-1.
-This is only for the default, where the user has set no 'LANG' (or
-similar) variable or environment.  This change should lead to no
-user-visible changes for normal usage.
+** New user option 'kill-buffer-delete-auto-save-files'.
+If non-nil, killing a buffer that has an auto-save file will prompt
+the user for whether that file should be deleted.  (Note that
+'delete-auto-save-files', if non-nil, was previously documented to
+result in deletion of auto-save files when killing a buffer without
+unsaved changes, but this has apparently not worked for several
+decades, so the documented semantics of this variable has been changed
+to match the behaviour.)
 
 +++
-** New variables that hold default buffer names for shell output.
-The new constants 'shell-command-buffer-name' and
-'shell-command-buffer-name-async' store the default buffer names
-for the output of, respectively, synchronous and async shell
-commands.
+** New user option 'next-error-message-highlight'.
+In addition to a fringe arrow, 'next-error' error may now optionally
+highlight the current error message in the 'next-error' buffer.
+This user option can be also customized to keep highlighting on all
+visited errors, so you can have an overview what errors were already visited.
 
-** Support for '(box . SIZE)' 'cursor-type'.
-By default, 'box' cursor always has a filled box shape.  But if you
-specify 'cursor-type' to be '(box . SIZE)', the cursor becomes a hollow
-box if the point is on an image larger than SIZE pixels in any
-dimension.
+---
+** New choice 'next-error-quit-window' for 'next-error-found-function'.
+When 'next-error-found-function' is customized to 'next-error-quit-window',
+then typing the numeric prefix argument 0 before the command 'next-error'
+will quit the source window after visiting the next occurrence.
 
 +++
-** New user option 'word-wrap-by-category'.
-When word-wrap is enabled, and this option is non-nil, that allows
-Emacs to break lines after more characters than just whitespace
-characters.  In particular, this significantly improves word-wrapping
-for CJK text mixed with Latin text.
+** New user option 'file-preserve-symlinks-on-save'.
+This controls what Emacs does when saving buffers that visit files via
+symbolic links, and 'file-precious-flag' is non-nil.
+
++++
+** New user option 'copy-directory-create-symlink'.
+If non-nil, will make 'copy-directory' (when used on a symbolic
+link) copy the link instead of following the link.  The default is
+nil, so the default behavior is unchanged.
+
++++
+** New user option 'ignored-local-variable-values'.
+This is the opposite of 'safe-local-variable-values' -- it's an alist
+of variable-value pairs that are to be ignored when reading a
+local-variables section of a file.
 
 ---
-** Rudimentary support for the 'st' terminal emulator.
-Emacs now supports 256 color display on the 'st' terminal emulator.
+** Specific warnings can now be disabled from the warning buffer.
+When a warning is displayed to the user, the resulting buffer now has
+buttons which allow making permanent changes to the treatment of that
+warning.  Automatic showing of the warning can be disabled (although
+it is still logged to the "*Messages*" buffer), or the warning can be
+disabled entirely.
+
++++
+** ".dir-locals.el" now supports setting 'auto-mode-alist'.
+The new 'auto-mode-alist' specification in ".dir-locals.el" files can
+now be used to override the global 'auto-mode-alist' in the current
+directory tree.
 
 ---
-** Mouse wheel scrolling now works on more parts of frame's display.
-When using 'mwheel-mode', the mouse wheel will now scroll also when
-the mouse cursor is on the scroll bars, fringes, margins, header line,
-and mode line.  ('mwheel-mode' is enabled by default on most graphical
-displays.)
+** User option 'uniquify-buffer-name-style' can now be a function.
+This user option can be one of the predefined styles or a function to
+personalize the uniquified buffer name.
 
 ---
-** Mouse wheel scrolling now defaults to one line at a time.
+** 'remove-hook' is now an interactive command.
+
+** Frames
 
 +++
-** Mouse wheel scrolling with Shift modifier now scrolls horizontally.
-This works in text buffers and over images.  Typing a numeric prefix arg
-(e.g. 'M-5') before starting horizontal scrolling changes its step value.
-The value is saved in the user option 'mouse-wheel-scroll-amount-horizontal'.
+*** The key prefix 'C-x 5 5' displays next command buffer in a new frame.
+It's bound to the command 'other-frame-prefix' that requests the buffer
+of the next command to be displayed in a new frame.
 
----
-** New choice 'permanent' for 'shift-select-mode'.
-When the mark was activated by shifted motion keys,
-non-shifted motion keys don't deactivate the mark
-after customizing 'shift-select-mode' to 'permanent'.
++++
+*** New command 'clone-frame' (bound to 'C-x 5 c').
+This is like 'C-x 5 2', but uses the frame parameters of the current
+frame instead of 'default-frame-alist'.
 
 ---
-** The default value of 'frame-title-format' and 'icon-title-format' has 
changed.
+*** Default values of 'frame-title-format' and 'icon-title-format' have 
changed.
 These variables are used to display the title bar of visible frames
 and the title bar of an iconified frame.  They now show the name of
 the current buffer and the text "GNU Emacs" instead of the value of
@@ -281,608 +301,715 @@ your init file:
                               ("" invocation-name "@" system-name)))
 
 +++
-** 'nobreak-char-display' now also affects all non-ASCII space characters.
-Previously, this was limited only to NO-BREAK-SPACE and hyphen
-characters.  Now it also covers the rest of the non-ASCII Unicode
-space characters.
+*** New frame parameter 'drag-with-tab-line'.
+This parameter, similar to 'drag-with-header-line', allows moving frames
+by dragging the tab lines of their topmost windows with the mouse.
+
++++
+*** New optional behavior of 'delete-other-frames'.
+When invoked with a prefix argument, 'delete-other-frames' now
+iconifies frames, rather than deleting them.
 
 ---
-** Prefer "chat.freenode.net" to "irc.freenode.net".
-"chat.freenode.net" has been the preferred address for connecting to the
-freenode IRC network for years now.  Occurrences of "irc.freenode.net"
-have been replaced with "chat.freenode.net" throughout Emacs.
+*** Commands 'set-frame-width' and 'set-frame-height' now prompt for values.
+These commands now prompt for the value via the minibuffer, instead of
+requiring the user to specify the value via the prefix argument.
 
-+++
-** New functions 'null-device' and 'path-separator'.
-These functions return the connection local value of the respective
-variables.  This can be used for remote hosts.
+** Windows
 
-** Emacs now prints a backtrace when signaling an error in batch mode.
-This makes debugging Emacs Lisp scripts run in batch mode easier.  To
-get back the old behavior, set the new variable
-'backtrace-on-error-noninteractive' to a nil value.
+*** The key prefix 'C-x 4 1' displays next command buffer in the same window.
+It's bound to the command 'same-window-prefix' that requests the buffer
+of the next command to be displayed in the same window.
 
-** 'redisplay-skip-fontification-on-input' helps Emacs keep up with fast input.
-This is another attempt to solve the problem of handling high key repeat rate
-and other "slow scrolling" situations.  It is hoped it behaves better
-than 'fast-but-imprecise-scrolling' and 'jit-lock-defer-time'.
-It is not enabled by default.
+*** The key prefix 'C-x 4 4' displays next command buffer in a new window.
+It's bound to the command 'other-window-prefix' that requests the buffer
+of the next command to be displayed in a new window.
 
 +++
-** Modifiers now go outside angle brackets in pretty-printed key bindings.
-For example, 'RET' with Control and Meta modifiers is now shown as
-'C-M-<return>' instead of '<C-M-return>'.  Either variant can be used
-as input; functions such as 'kbd' and 'read-kbd-macro' accept both
-styles as equivalent (they have done so for a long time).
+*** New command 'recenter-other-window', bound to 'S-M-C-l'.
+Like 'recenter-top-bottom' acting on the other window.
 
 +++
-** New user option 'lazy-highlight-no-delay-length'.
-Lazy highlighting of matches in Isearch now starts immediately if the
-search string is at least this long.  'lazy-highlight-initial-delay'
-still applies for shorter search strings, which avoids flicker in the
-search buffer due to too many matches being highlighted.
+*** New user option 'delete-window-choose-selected'.
+This allows to choose a window that will be the frame's selected
+window after deleting the currently selected one.
 
 +++
-** A new keymap for buffer actions has been added.
-The 'C-x x' keymap now holds keystrokes for various buffer-oriented
-commands.  The new keystrokes are 'C-x x g' ('revert-buffer-quick'),
-'C-x x r' ('rename-buffer'), 'C-x x u' ('rename-uniquely'), 'C-x x n'
-('clone-buffer'), 'C-x x i' ('insert-buffer'), 'C-x x t'
-('toggle-truncate-lines') and 'C-x x f' ('font-lock-update').
-
----
-** Commands 'set-frame-width' and 'set-frame-height' can now get their
-input using the minibuffer.
-
----
-** New help window when Emacs prompts before opening a large file.
-Commands like 'find-file' or 'visit-tags-table' ask to visit a file
-normally or literally when the file is larger than a certain size (by
-default, 9.5 MiB).  Press '?' or 'C-h' in that prompt to read more
-about the different options to visit a file, how you can disable the
-prompt, and how you can tweak the file size threshold.
+*** New argument NO-OTHER for some window functions.
+'get-lru-window', 'get-mru-window' and 'get-largest-window' now accept a
+new optional argument NO-OTHER which, if non-nil, avoids returning a
+window whose 'no-other-window' parameter is non-nil.
 
 +++
-** New user option 'query-about-changed-file'.
-If non-nil (the default), users are prompted as before when
-re-visiting a file that has changed externally after it was visited
-the first time.  If nil, the user is not prompted, but instead the
-buffer is opened with its contents before the change, and the user is
-given instructions how to revert the buffer.
+*** New 'display-buffer' function 'display-buffer-use-least-recent-window'.
+This is like 'display-buffer-use-some-window', but won't reuse the
+current window, and when called repeatedly will try not to reuse a
+previously selected window.
 
-+++
-** Improved support for terminal emulators that encode the Meta flag.
-Some terminal emulators set the 8th bit of Meta characters, and then
-encode the resulting character code as if it were non-ASCII character
-above codepoint 127.  Previously, the only way of using these in Emacs
-was to set up the terminal emulator to use the 'ESC' characters to send
-Meta characters to Emacs, e.g., send "ESC x" when the user types
-'M-x'.  You can now avoid the need for this setup of such terminal
-emulators by using the new input-meta-mode with the special value
-'encoded' with these terminal emulators.
+*** New function 'window-bump-use-time'.
+This updates the use time of a window.
 
-+++
-** New frame parameter 'drag-with-tab-line'.
-This parameter, similar to 'drag-with-header-line', allows moving frames
-by dragging the tab lines of their topmost windows with the mouse.
+** Minibuffer
 
-
-* Editing Changes in Emacs 28.1
+*** Minibuffer scrolling is now conservative by default.
+This is controlled by the new variable 'scroll-minibuffer-conservatively'.
+It is t by default; setting it to nil will cause scrolling in the
+minibuffer obey the value of 'scroll-conservatively'.
 
-** New value 'save-some-buffers-root' of 'save-some-buffers-default-predicate'.
-It allows to ask about saving only files under the project root
-or in subdirectories of the directory that was default during
-command invocation.
++++
+*** Improved handling of minibuffers on switching frames.
+By default, when you switch to another frame, an active minibuffer now
+moves to the newly selected frame.  Nevertheless, the effect of what
+you type in the minibuffer happens in the frame where the minibuffer
+was first activated.  An alternative behavior is available by
+customizing 'minibuffer-follows-selected-frame' to nil.  Here, the
+minibuffer stays in the frame where you first opened it, and you must
+switch back to this frame to continue or abort its command.  The old
+behavior, which mixed these two, can be approximated by customizing
+'minibuffer-follows-selected-frame' to a value which is neither nil
+nor t.
+
++++
+*** New user option 'read-minibuffer-restore-windows'.
+When customized to nil, it uses 'minibuffer-restore-windows' in
+'minibuffer-exit-hook' to remove only the window showing the
+"*Completions*" buffer.
 
 ---
-** Dragging a file to Emacs will now also push the name of the file
-onto 'file-name-history'.
+*** New variable 'redisplay-adhoc-scroll-in-resize-mini-windows'.
+Customizing it to nil will disable the ad-hoc auto-scrolling of
+minibuffer text shown in mini-windows when resizing those windows.
+The default heuristics of that scrolling can be counter productive in
+some corner cases, though the cure might be worse than the disease.
+This said, the effect should be negligible in the vast majority of
+cases anyway.
 
-+++
-** A prefix arg now causes 'delete-other-frames' to only iconify frames.
+** Mode Line
 
 +++
-** The "Edit => Clear" menu item now obeys a rectangular region.
+*** New user option 'mode-line-compact'.
+If non-nil, repeating spaces are compressed into a single space.  If
+'long', this is only done when the mode line is longer than the
+current window width (in columns).
 
 +++
-** New command 'execute-extended-command-for-buffer'.
-This new command, bound to 'M-S-x', works like
-'execute-extended-command', but limits the set of commands to the
-commands that have been determined to be particularly useful with the
-current mode.
+*** New user options to control format of line/column numbers in the mode line.
+'mode-line-position-line-format' is the line number format (when
+'line-number-mode' is on), 'mode-line-position-column-format' is
+the column number format (when 'column-number-mode' is on), and
+'mode-line-position-column-line-format' is the combined format (when
+both modes are on).
 
-+++
-** New user option 'read-extended-command-predicate'.
-This user option controls how 'M-x' performs completion of commands when
-you type 'TAB'.  By default, any command that matches what you have
-typed is considered a completion candidate, but you can customize this
-option to exclude commands that are not applicable to the current
-buffer's major and minor modes, and respect the command's completion
-predicate (if any).
+** Tab Bars and Tab Lines
 
----
-** 'eval-expression' now no longer signals an error on incomplete expressions.
-Previously, typing 'M-: ( RET' would result in Emacs saying "End of
-file during parsing" and dropping out of the minibuffer.  The user
-would have to type 'M-: M-p' to edit and redo the expression.  Now
-Emacs will echo the message and allow the user to continue editing.
+*** The prefix key 'C-x t t' can be used to display a buffer in a new tab.
+Typing 'C-x t t' before a command will cause the buffer shown by that
+command to be displayed in a new tab.  'C-x t t" is bound to the
+command 'other-tab-prefix'.
 
 +++
-** 'eval-last-sexp' now handles 'defvar'/'defcustom'/'defface' specially.
-This command would previously not redefine values defined by these
-forms, but this command has now been changed to work more like
-'eval-defun', and reset the values as specified.
+*** New command 'C-x t C-r' to open file read-only in the other tab.
 
-+++
-** Standalone 'M-y' allows interactive selection from previous kills.
-'M-y' can now be typed after a command that is not a yank command.
-When invoked like that, it prompts in the minibuffer for one of the
-previous kills, offering completion and minibuffer-history navigation
-through previous kills recorded in the kill ring.  A similar feature
-in Isearch can be invoked if you bind 'C-s M-y' to the command
-'isearch-yank-pop'.  When the user option 'yank-from-kill-ring-rotate'
-is nil the kill ring is not rotated after 'yank-from-kill-ring'.
+---
+*** The tab bar is frame-local when 'tab-bar-show' is a number.
+Show/hide the tab bar independently for each frame, according to the
+value of 'tab-bar-show'.
 
 ---
-** New user options 'copy-region-blink-delay' and 'delete-pair-blink-delay'.
-'copy-region-blink-delay' specifies a delay to indicate the region
-copied by 'kill-ring-save'.  'delete-pair-blink-delay' specifies
-a delay to show a paired character to delete.
+*** New command 'toggle-frame-tab-bar'.
+It can be used to enable/disable the tab bar on the currently selected
+frame regardless of the values of 'tab-bar-mode' and 'tab-bar-show'.
 
-+++
-** New command 'undo-redo'.
-It undoes previous undo commands, but doesn't record itself as an
-undoable command.
+---
+*** New user option 'tab-bar-format' defines a list of tab bar items.
+When it contains 'tab-bar-format-global' (possibly appended after
+'tab-bar-format-align-right'), then after enabling 'display-time-mode'
+(or any other mode that uses 'global-mode-string') it displays time
+aligned to the right on the tab bar instead of on the mode line.
+When 'tab-bar-format-tabs' is replaced with 'tab-bar-format-tabs-groups',
+the tab bar displays tab groups.
 
-+++
-** 'read-number' now has its own history variable.
-Additionally, the function now accepts a HIST argument which can be
-used to specify a custom history variable.
+---
+*** 'Mod-9' bound to 'tab-last' now switches to the last tab.
+It also supports a negative argument.
 
-+++
-** Input history for 'goto-line' can now be made local to every buffer.
-In any event, line numbers used with 'goto-line' are kept in their own
-history list.  This should help make faster the process of finding
-line numbers that were previously jumped to.  By default, all buffers
-share a single history list.  To make every buffer have its own
-history list, customize the user option 'goto-line-history-local'.
+---
+*** New command 'tab-duplicate' bound to 'C-x t n'.
 
-+++
-** New command 'goto-line-relative' to use in a narrowed buffer.
-It moves point to the line relative to the accessible portion of the
-narrowed buffer.  'M-g M-g' in Info is rebound to this command.
-When 'widen-automatically' is non-nil, 'goto-line' widens the narrowed
-buffer to be able to move point to the inaccessible portion.
-'goto-line-relative' is bound to 'C-x n g'.
+---
+*** 'C-x t N' creates a new tab at the specified absolute position.
+The position is provided as prefix arg, and specifies an index that
+starts at 1.  Negative values count from the end of the tab bar.
 
-+++
-** When called interactively, 'goto-char' now offers the number at
-point as default.
+---
+*** 'C-x t M' moves the current tab to the specified absolute position.
+The position is provided as prefix arg, whose interpretation is as in
+'C-x t N'.
 
-+++
-** When 'suggest-key-bindings' is non-nil, the completion list of 'M-x'
-shows equivalent key bindings for all commands that have them.
+---
+*** 'C-x t G' assigns a tab to a named group of tabs.
+'tab-close-group' closes all tabs that belong to the selected group.
+The user option 'tab-bar-new-tab-group' defines the default group of
+new tabs.  After customizing 'tab-bar-tab-post-change-group-functions'
+to 'tab-bar-move-tab-to-group', changing the group of a tab will also
+move it closer to other tabs in the same group.
 
-** Autosaving via 'auto-save-visited-mode' can now be inhibited by
-setting the variable 'auto-save-visited-mode' buffer-locally to nil.
+---
+*** New user option 'tab-bar-tab-name-format-function'.
 
-** New commands to describe buttons and widgets have been added.
-'widget-describe' (on a widget) will pop up a help buffer and give a
-description of the properties.  Likewise 'button-describe' does the
-same for a button.
+---
+*** New user option 'tab-line-tab-name-format-function'.
 
-** Obsolete aliases are no longer hidden from command completion.
-Completion of command names now considers obsolete aliases as
-candidates, if they were marked obsolete in the current major version
-of Emacs.  Invoking a command via an obsolete alias now mentions the
-obsolescence fact and shows the new name of the command.
+---
+*** The tabs in the tab line can now be scrolled using horizontal scroll.
+If your mouse or trackpad supports it, you can now scroll tabs when
+the mouse pointer is in the tab line by scrolling left or right.
 
-+++
-** New command 'revert-buffer-with-fine-grain'.
-Revert a buffer trying to be as non-destructive as possible,
-preserving markers, properties and overlays.  The new variable
-'revert-buffer-with-fine-grain-max-seconds' specifies the maximum
-number of seconds that 'revert-buffer-with-fine-grain' should spend
-trying to be non-destructive.
+---
+*** New tab-line faces and options.
+The face 'tab-line-tab-special' is used for tabs whose buffers are
+special, i.e. buffers that don't visit a file.  The face
+'tab-line-tab-inactive-alternate' is used to display inactive tabs
+with an alternating background color, making them easier to
+distinguish, especially if the face 'tab-line-tab' is configured to
+not display with a box; this alternate face is only applied when the
+option 'tab-line-tab-face-functions' is so configured.  That option
+may also be used to customize tab-line faces in other ways.
 
-+++
-** New command 'memory-report'.
-This command opens a new buffer called "*Memory Report*" and gives a
-summary of where Emacs is using memory currently.
+** Mouse wheel
 
-+++
-** New user option 'isearch-repeat-on-direction-change'.
-When this option is set, direction changes in Isearch move to another
-search match, if there is one, instead of moving point to the other
-end of the current match.
+---
+*** Mouse wheel scrolling now defaults to one line at a time.
 
-** Outline
+---
+*** Mouse wheel scrolling now works on more parts of frame's display.
+When using 'mwheel-mode', the mouse wheel will now scroll also when
+the mouse cursor is on the scroll bars, fringes, margins, header line,
+and mode line.  ('mwheel-mode' is enabled by default on most graphical
+displays.)
 
 +++
-*** New commands to cycle heading visibility.
-Typing 'TAB' on a heading line cycles the current section between
-"hide all", "subheadings", and "show all" states.  Typing 'S-TAB'
-anywhere in the buffer cycles the whole buffer between "only top-level
-headings", "all headings and subheadings", and "show all" states.
+*** Mouse wheel scrolling with Shift modifier now scrolls horizontally.
+This works in text buffers and over images.  Typing a numeric prefix arg
+(e.g. 'M-5') before starting horizontal scrolling changes its step value.
+The value is saved in the user option 'mouse-wheel-scroll-amount-horizontal'.
 
-+++
-*** New user option 'outline-minor-mode-cycle'.
-This user option customizes 'outline-minor-mode', with the difference
-that 'TAB' and 'S-TAB' on heading lines cycle heading visibility.
-Typing 'TAB' on a heading line cycles the current section between
-"hide all", "subheadings", and "show all" states.  Typing 'S-TAB' on a
-heading line cycles the whole buffer between "only top-level
-headings", "all headings and subheadings", and "show all" states.
+** Customize
 
 ---
-*** New user option 'outline-minor-mode-highlight'.
-This user option customizes 'outline-minor-mode'.  It puts
-highlighting on heading lines using standard outline faces.  This
-works well only when there are no conflicts with faces used by the
-major mode.
-
-+++
-** New commands 'copy-matching-lines' and 'kill-matching-lines'.
-These commands are similar to the command 'flush-lines',
-but add the matching lines to the kill ring as a single string,
-including the newlines that separate the lines.
-
-
-* Changes in Specialized Modes and Packages in Emacs 28.1
+*** Customize buffers can now be reverted with 'C-x x g'.
 
-** Completion List Mode
-New key bindings have been added: 'n' and 'p' to navigate completions,
-and 'M-g M-c' to switch to the minibuffer, and you can also switch back
-to the completion list buffer with 'M-g M-c'.
+*** Most customize commands now hide obsolete user options.
+Obsolete user options are no longer shown in the listings produced by
+the commands 'customize', 'customize-group', 'customize-apropos' and
+'customize-changed'.
 
-** Benchmark
-*** New function 'benchmark-call' to measure the execution time of a function.
-Additionally, the number of repetitions can be expressed as a minimal duration
-in seconds.
+To customize obsolete user options, use 'customize-option' or
+'customize-saved'.
 
-** Macroexp
----
-*** New function 'macroexp-file-name' to know the name of the current file.
----
-*** New function 'macroexp-compiling-p' to know if we're compiling.
----
-*** New function 'macroexp-warn-and-return' to help emit warnings.
-This used to be named 'macroexp--warn-and-return' and has proved useful
-and well-behaved enough to lose the "internal" marker.
+*** 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.
 
-** Bindat
+** Help
 
 +++
-*** New 'Bindat type expression' description language.
-This new system is provided by the new macro 'bindat-type' and
-obsoletes the old data layout specifications.  It supports
-arbitrary-size integers, recursive types, and more.  See the Info node
-"(elisp) Byte Packing" in the ELisp manual for more details.
-
-** pcase
+*** New command 'describe-command' shows help for a command.
+This can be used instead of 'describe-function' for interactive
+commands and is globally bound to 'C-h x'.
 
 +++
-*** The 'or' pattern now binds the union of the vars of its sub-patterns.
-If a variable is not bound by the subpattern that matched, it gets bound
-to nil.  This was already sometimes the case, but it is now guaranteed.
+*** New command 'describe-keymap' describes keybindings in a keymap.
 
-+++
-*** The 'pred' pattern can now take the form '(pred (not FUN))'.
-This is like '(pred (lambda (x) (not (FUN x))))' but results
-in better code.
+*** New command 'apropos-function'.
+This works like 'C-u M-x apropos-command' but is more discoverable.
 
 ---
-*** New function 'pcase-compile-patterns' to write other macros.
+*** New keybinding 'C-h R' prompts for an Info manual and displays it.
 
-*** Added 'cl-type' pattern.
-The new 'cl-type' pattern compares types using 'cl-typep', which allows
-comparing simple types like '(cl-type integer)', as well as forms like
-'(cl-type (integer 0 10))'.
+---
+*** Keybindings in 'help-mode' use the new 'help-key-binding' face.
+This face is added by 'substitute-command-keys' to any "\[command]"
+substitution.  The return value of that function should consequently
+be assumed to be a propertized string.
 
-*** New macro 'pcase-setq'
-This macro is the 'setq' equivalent of 'pcase-let', which allows for
-destructuring patterns in a 'setq' form.
-
-+++
-** profiler.el
-The results displayed by 'profiler-report' now have the usage figures
-at the left hand side followed by the function name.  This is intended
-to make better use of the horizontal space, in particular eliminating
-the truncation of function names.  There is no way to get the former
-layout back.
-
-** Loading dunnet.el in batch mode doesn't start the game any more.
-Instead you need to do "emacs -f dun-batch" to start the game in
-batch mode.
+Note that the new face will also be used in tooltips.  When using the
+GTK toolkit, this is only true if 'x-gtk-use-system-tooltips' is t.
 
-** Emacs Server
+---
+*** The 'help-for-help' ('C-h C-h') screen has been redesigned.
 
 +++
-*** New user option 'server-client-instructions'.
-When emacsclient connects, Emacs will (by default) output a message
-about how to exit the client frame.  If 'server-client-instructions'
-is set to nil, this message is inhibited.
+*** New convenience commands with short keys in the Help buffer.
+New command 'help-view-source' ('s') will view the source file (if
+any) of the current help topic.  New command 'help-goto-info' ('i')
+will look up the current symbol (if any) in Info.  New command
+'help-customize' ('c') will customize the variable or the face
+(if any) whose doc string is being shown in the Help buffer.
 
-+++
-*** New command 'server-edit-abort'.
-This command (not bound to any key by default) can be used to abort
-an edit instead of marking it as "Done" (which the 'C-x #' command
-does).  The 'emacsclient' program exits with an abnormal status as
-result of this command.
+---
+*** New user option 'describe-bindings-outline'.
+It enables outlines in the output buffer of 'describe-bindings' that
+can provide a better overview in a long list of available bindings.
 
 +++
-*** New desktop integration for connecting to the server.
-If your operating system’s desktop environment is
-freedesktop.org-compatible (which is true of most GNU/Linux and other
-recent Unix-like GUIs), you may use the new "Emacs (Client)" desktop
-menu entry to open files in an existing Emacs instance rather than
-starting a new one.  The daemon starts if not already running.
+*** New command 'lossage-size'.
+It allows users to change the maximum number of keystrokes and
+commands recorded for the purpose of 'view-lossage'.
 
-** Perl mode
+*** New commands to describe buttons and widgets.
+'widget-describe' (on a widget) will pop up a help buffer and give a
+description of the properties.  Likewise 'button-describe' does the
+same for a button.
 
 ---
-*** New face 'perl-non-scalar-variable'.
-This is used to fontify non-scalar variables.
+*** Improved "find definition" feature of "*Help*" buffers.
+Now clicking on the link to find the definition of functions generated
+by 'cl-defstruct', or variables generated by 'define-derived-mode',
+for example, will go to the exact place where they are defined.
 
-** Python mode
+*** New commands 'apropos-next-symbol' and 'apropos-previous-symbol'.
+These new navigation commands are bound to 'n' and 'p' in
+'apropos-mode'.
 
 ---
-*** New user option 'python-forward-sexp-function'.
-This allows the user to easier customize whether to use block-based
-navigation or not.
+*** The command 'view-lossage' can now be invoked from the menu bar.
+The menu bar "Help" menu now has a "Show Recent Inputs" item under the
+"Describe" sub-menu.
 
 ---
-*** 'python-shell-interpreter' now defaults to python3 on systems with python3.
+*** Closing the "*Help*" buffer from the toolbar now buries the buffer.
+In previous Emacs versions, the "*Help*" buffer was killed instead when
+clicking the "X" icon in the tool bar.
 
 ---
-*** 'C-c C-r' can now be used on arbitrary regions.
-The command previously extended the start of the region to the start
-of the line, but will now actually send the marked region, as
-documented.
-
-** Ruby mode
+*** 'g' ('revert-buffer') in 'help-mode' no longer requires confirmation.
 
----
-*** 'ruby-use-smie' is declared obsolete.
-SMIE is now always enabled and 'ruby-use-smie' only controls whether
-indentation is done using SMIE or with the old ad-hoc code.
+** File Locks
 
-** Icomplete
++++
+*** New user option 'lock-file-name-transforms'.
+This option allows controlling where lock files are written.  It uses
+the same syntax as 'auto-save-file-name-transforms'.
 
----
-*** New user option 'icomplete-matches-format'.
-This allows controlling the current/total number of matches for the
-prompt prefix.
++++
+*** New user option 'remote-file-name-inhibit-locks'.
+When non-nil, this option suppresses lock files for remote files.
 
 +++
-*** New minor modes 'icomplete-vertical-mode' and 'fido-vertical-mode'
-These modes are modify Icomplete ('M-x icomplete-mode') and Fido ('M-x
-fido-mode'), to display completions candidates vertically instead of
-horizontally.  In Icomplete, completions are rotated and selection
-kept at the top.  In Fido, completions scroll like a typical dropdown
-widget.  Both these new minor modes will first turn on their
-respective non-vertical counterparts first, if they are not on
-already.
+*** New minor mode 'lock-file-mode'.
+This command, called interactively, toggles the local value of
+'create-lockfiles' in the current buffer.
 
----
-*** Default value of 'icomplete-compute-delay' has been changed to 0.15 s.
+** Emacs Server
 
----
-*** Default value of 'icomplete-max-delay-chars' has been changed to 2.
++++
+*** New user option 'server-client-instructions'.
+When emacsclient connects, Emacs will (by default) output a message
+about how to exit the client frame.  If 'server-client-instructions'
+is set to nil, this message is inhibited.
 
----
-*** Reduced blinking while completing the next completions set.
-Icomplete doesn't hide the hint with the previously computed
-completions anymore when compute delay is in effect, or the previous
-computation has been aborted by input.  Instead it shows the previous
-completions until the new ones are ready.
++++
+*** New command 'server-edit-abort'.
+This command (not bound to any key by default) can be used to abort
+an edit instead of marking it as "Done" (which the 'C-x #' command
+does).  The 'emacsclient' program exits with an abnormal status as
+result of this command.
 
----
-** Specific warnings can now be disabled from the warning buffer.
-When a warning is displayed to the user, the resulting buffer now has
-buttons which allow making permanent changes to the treatment of that
-warning.  Automatic showing of the warning can be disabled (although
-it is still logged to the "*Messages*" buffer), or the warning can be
-disabled entirely.
++++
+*** New desktop integration for connecting to the server.
+If your operating system’s desktop environment is
+freedesktop.org-compatible (which is true of most GNU/Linux and other
+recent Unix-like desktops), you may use the new "Emacs (Client)"
+desktop menu entry to open files in an existing Emacs instance rather
+than starting a new one.  The daemon starts if it is not already
+running.
 
-** mspool.el
+** Miscellaneous
 
----
-*** Autoload the main entry point 'mspool-show'.
++++
+*** New command 'font-lock-update', bound to 'C-x x f'.
+This command updates the syntax highlighting in this buffer.
 
-** Windmove
++++
+*** New command 'memory-report'.
+This command opens a new buffer called "*Memory Report*" and gives a
+summary of where Emacs is using memory currently.
 
 +++
-*** New user options to customize windmove keybindings.
-These options include 'windmove-default-keybindings',
-'windmove-display-default-keybindings',
-'windmove-delete-default-keybindings',
-'windmove-swap-states-default-keybindings'.
+*** New command 'submit-emacs-patch'.
+This works like 'report-emacs-bug', but is more geared towards sending
+patches to the Emacs issue tracker.
 
-** Windows
+*** New face 'apropos-button'.
+Applies to buttons that indicate a face.
 
 +++
-*** New user option 'delete-window-choose-selected'.
-This allows to choose a frame's selected window after deleting the
-previously selected one.
+*** New face 'font-lock-doc-markup-face'.
+Intended for documentation mark-up syntax and tags inside text that
+uses 'font-lock-doc-face', with which it should harmonise.  It would
+typically be used in structured documentation comments in program
+source code by language-specific modes, for mark-up conventions like
+Haddock, Javadoc or Doxygen.  By default this face inherits from
+'font-lock-constant-face'.
 
 +++
-*** New argument NO-OTHER for some window functions.
-'get-lru-window', ‘get-mru-window’ and 'get-largest-window' now accept a
-new optional argument NO-OTHER which, if non-nil, avoids returning a
-window whose 'no-other-window' parameter is non-nil.
+*** New face 'flat-button'.
+This is a plain 2D button, but uses the background color instead of
+the foreground color.
 
-+++
-*** New 'display-buffer' function 'display-buffer-use-least-recent-window'.
-This is like 'display-buffer-use-some-window', but won't reuse the
-current window, and when called repeatedly will try not to reuse a
-previously selected window.
+---
+*** New face 'shortdoc-heading'.
+Applies to headings of shortdoc sections.
 
-*** New function 'window-bump-use-time'.
-This updates the use time of a window.
+---
+*** New face 'separator-line'.
+This is used by 'make-separator-line' (see below).
 
-*** The key prefix 'C-x 4 1' displays next command buffer in the same window.
-It's bound to the command 'same-window-prefix' that requests the buffer
-of the next command to be displayed in the same window.
+*** 'redisplay-skip-fontification-on-input' helps Emacs keep up with fast 
input.
+This is another attempt to solve the problem of handling high key repeat rate
+and other "slow scrolling" situations.  It is hoped it behaves better
+than 'fast-but-imprecise-scrolling' and 'jit-lock-defer-time'.
+It is not enabled by default.
 
-*** The key prefix 'C-x 4 4' displays next command buffer in a new window.
-It's bound to the command 'other-window-prefix' that requests the buffer
-of the next command to be displayed in a new window.
+*** Obsolete aliases are no longer hidden from command completion.
+Completion of command names now considers obsolete aliases as
+candidates, if they were marked obsolete in the current major version
+of Emacs.  Invoking a command via an obsolete alias now mentions the
+obsolescence fact and shows the new name of the command.
 
-** Frames
+*** Support for '(box . SIZE)' 'cursor-type'.
+By default, 'box' cursor always has a filled box shape.  But if you
+specify 'cursor-type' to be '(box . SIZE)', the cursor becomes a hollow
+box if the point is on an image larger than SIZE pixels in any
+dimension.
 
 +++
-*** The key prefix 'C-x 5 5' displays next command buffer in a new frame.
-It's bound to the command 'other-frame-prefix' that requests the buffer
-of the next command to be displayed in a new frame.
-
-** Tab Bars
+*** The user can now customize how "default" values are prompted for.
+The new utility function 'format-prompt' has been added which uses the
+new 'minibuffer-default-prompt-format' user option to format "default"
+prompts.  This means that prompts that look like "Enter a number
+(default 10)" can be customized to look like, for instance, "Enter a
+number [10]", or not have the default displayed at all, like "Enter a
+number".  (This only affects callers that were altered to use
+'format-prompt'.)
 
-*** The key prefix 'C-x t t' displays next command buffer in a new tab.
-It's bound to the command 'other-tab-prefix' that requests the buffer
-of the next command to be displayed in a new tab.
+---
+*** New help window when Emacs prompts before opening a large file.
+Commands like 'find-file' or 'visit-tags-table' ask to visit a file
+normally or literally when the file is larger than a certain size (by
+default, 9.5 MiB).  Press '?' or 'C-h' in that prompt to read more
+about the different options to visit a file, how you can disable the
+prompt, and how you can tweak the file size threshold.
 
 +++
-*** New command 'C-x t C-r' to open file read-only in other tab.
+*** Emacs now defaults to UTF-8 instead of ISO-8859-1.
+This is only for the default, where the user has set no 'LANG' (or
+similar) variable or environment.  This change should lead to no
+user-visible changes for normal usage.
 
 ---
-*** The tab bar is frame-local when 'tab-bar-show' is a number.
-Show/hide the tab bar independently for each frame, according to the
-value of 'tab-bar-show'.
+*** 'global-display-fill-column-indicator-mode' skips some buffers.
+By default, turning on 'global-display-fill-column-indicator-mode'
+doesn't turn on 'display-fill-column-indicator-mode' in special-mode
+buffers.  This can be controlled by customizing the variable
+'global-display-fill-column-indicator-modes'.
 
----
-*** New command 'toggle-frame-tab-bar'.
-It can be used to enable/disable the tab bar individually on each frame
-independently from the value of 'tab-bar-mode' and 'tab-bar-show'.
++++
+*** 'nobreak-char-display' now also affects all non-ASCII space characters.
+Previously, this was limited only to 'NO-BREAK SPACE' and hyphen
+characters.  Now it also covers the rest of the non-ASCII Unicode
+space characters.
 
----
-*** New user option 'tab-bar-format' defines a list of tab bar items.
-When it contains 'tab-bar-format-global' (possibly appended after
-'tab-bar-format-align-right'), then after enabling 'display-time-mode'
-(or any other mode that uses 'global-mode-string') it displays time
-aligned to the right on the tab bar instead of the mode line.
-When 'tab-bar-format-tabs' is replaced with 'tab-bar-format-tabs-groups',
-then the tab bar displays tab groups.
++++
+*** Improved support for terminal emulators that encode the Meta flag.
+Some terminal emulators set the 8th bit of Meta characters, and then
+encode the resulting character code as if it were non-ASCII character
+above codepoint 127.  Previously, the only way of using these in Emacs
+was to set up the terminal emulator to use the 'ESC' characters to send
+Meta characters to Emacs, e.g., send "ESC x" when the user types
+'M-x'.  You can now avoid the need for this setup of such terminal
+emulators by using the new input-meta-mode with the special value
+'encoded' with these terminal emulators.
 
 ---
-*** 'Mod-9' bound to 'tab-last' now switches to the last tab.
-It also supports a negative argument.
+*** 'auto-composition-mode' can now be selectively disabled on some TTYs.
+Some text-mode terminals produce display glitches trying to compose
+characters.  The 'auto-composition-mode' can now have a string value
+that names a terminal type; if the value returned by the 'tty-type'
+function compares equal with that string, automatic composition will
+be disabled in windows shown on that terminal.  The Linux terminal
+sets this up by default.
 
 ---
-*** New command 'tab-duplicate' bound to 'C-x t n'.
+*** Support for the 'strike-through' face attribute on TTY frames.
+If your terminal's termcap or terminfo database entry has the 'smxx'
+capability defined, Emacs will now emit the prescribed escape
+sequences necessary to render faces with the 'strike-through'
+attribute on TTY frames.
 
 ---
-*** 'C-x t N' creates a new tab at the specified absolute position.
-It also supports a negative argument.
+*** TTY menu navigation is now supported in 'xterm-mouse-mode'.
+TTY menus support mouse navigation and selection when 'xterm-mouse-mode'
+is active.  When run on a terminal, clicking on the menu bar with the
+mouse now pops up a TTY menu by default instead of running the command
+'tmm-menubar'.  To restore the old behavior, set the user option
+'tty-menu-open-use-tmm' to non-nil.
 
 ---
-*** 'C-x t M' moves the current tab to the specified absolute position.
-It also supports a negative argument.
+*** 'M-x report-emacs-bug' will no longer include "Recent messages" section.
+These were taken from the "*Messages*" buffer, and may inadvertently
+leak information from the reporting user.
 
 ---
-*** '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.  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.
+*** 'C-u M-x dig' will now prompt for a query type to use.
 
 ---
-*** New user option 'tab-bar-tab-name-format-function'.
+*** Rudimentary support for the 'st' terminal emulator.
+Emacs now supports 256 color display on the 'st' terminal emulator.
 
 ---
-*** New user option 'tab-line-tab-name-format-function'.
+*** Prefer "chat.freenode.net" to "irc.freenode.net".
+"chat.freenode.net" has been the preferred address for connecting to the
+freenode IRC network for years now.  Occurrences of "irc.freenode.net"
+have been replaced with "chat.freenode.net" throughout Emacs.
+
+
+* Editing Changes in Emacs 28.1
+
+** Input methods
+
++++
+*** Emacs now supports "transient" input methods.
+A transient input method is enabled for inserting a single character,
+and is then automatically disabled.  'C-x \' temporarily enables the
+selected transient input method.  Use 'C-u C-x \' to select a
+transient input method (which can be different from the input method
+enabled by 'C-\').  For example, 'C-u C-x \ compose RET' selects the
+'compose' input method; then typing 'C-x \ 1 2' will insert the
+character '½', and disable the 'compose' input method afterwards.
+You can use 'C-x \' in incremental search to insert a single character
+to the search string.
 
 ---
-*** The tabs in the tab line can now be scrolled using horizontal scroll.
-If your mouse or trackpad supports it, you can now scroll tabs when
-the mouse pointer is in the tab line by scrolling left or right.
+*** New input method 'compose' based on X Multi_key sequences.
 
 ---
-*** New tab-line faces and options.
-The face 'tab-line-tab-special' is used for tabs whose buffers are
-special, i.e. not file-backed.  The face
-'tab-line-tab-inactive-alternate' is used to display inactive tabs
-with an alternating background color, making them easier to
-distinguish between, especially if the face 'tab-line-tab' is
-configured to not display with a box; this alternate face is only
-applied when the option 'tab-line-tab-face-functions' is
-so-configured.  That option may also be used to customize tab-line
-faces in other ways.
+*** New input method 'iso-transl' with the same keys as 'C-x 8'.
+After selecting it as a transient input method with 'C-u C-x \
+iso-transl RET', it supports the same key sequences as 'C-x 8',
+so e.g. like 'C-x 8 [' inserts a left single quotation mark,
+'C-x \ [' does the same.
 
-** Occur mode
+---
+*** New user option 'read-char-by-name-sort'.
+It defines the sorting order of characters for completion of 'C-x 8 RET TAB'
+and can be customized to sort them by codepoints instead of character names.
+Additionally, you can group characters by Unicode blocks after customizing
+'completions-group' and 'completions-group-sort'.
+
+---
+*** Improved language transliteration in Malayalam input methods.
+Added a new Mozhi scheme.  The inapplicable ITRANS scheme is now
+deprecated.  Errors in the Inscript method were corrected.
 
-*** New bindings in occur-mode, 'next-error-no-select' bound to 'n' and
-'previous-error-no-select' bound to 'p'.
+---
+*** New input method 'cham'.
+There's also a Cham greeting in "etc/HELLO".
 
-*** The new command 'recenter-current-error', bound to 'l' in Occur or
-compilation buffers, recenters the current displayed occurrence/error.
+---
+*** New input methods for Lakota language orthographies.
+Two orthographies are represented here, the Suggested Lakota
+Orthography and what is known as the White Hat Orthography.  Input
+methods 'lakota-slo-prefix', 'lakota-slo-postfix', and
+'lakota-white-hat-postfix' have been added.  There is also a Lakota
+greeting in "etc/HELLO".
 
-*** Matches in target buffers are now highlighted as in 'compilation-mode'.
-The method of highlighting is specified by the user options
-'next-error-highlight' and 'next-error-highlight-no-select'.
++++
+** Standalone 'M-y' allows interactive selection from previous kills.
+'M-y' can now be typed after a command that is not a yank command.
+When invoked like that, it prompts in the minibuffer for one of the
+previous kills, offering completion and minibuffer-history navigation
+through previous kills recorded in the kill ring.  A similar feature
+in Isearch can be invoked if you bind 'C-s M-y' to the command
+'isearch-yank-pop'.  When the user option 'yank-from-kill-ring-rotate'
+is nil the kill ring is not rotated after 'yank-from-kill-ring'.
+
++++
+** New user option 'word-wrap-by-category'.
+When word-wrap is enabled, and this option is non-nil, that allows
+Emacs to break lines after more characters than just whitespace
+characters.  In particular, this significantly improves word-wrapping
+for CJK text mixed with Latin text.
+
++++
+** New command 'undo-redo'.
+It undoes previous undo commands, but doesn't record itself as an
+undoable command.
+
++++
+** New commands 'copy-matching-lines' and 'kill-matching-lines'.
+These commands are similar to the command 'flush-lines',
+but add the matching lines to the kill ring as a single string,
+including the newlines that separate the lines.
+
++++
+** New user option 'kill-transform-function'.
+This can be used to transform (and suppress) strings from entering the
+kill ring.
+
++++
+** 'save-interprogram-paste-before-kill' can now be a number.
+In that case, it's interpreted as a limit on the size of the clipboard
+data that will be saved to the 'kill-ring' prior to killing text: if
+the size of the clipboard data is greater than or equal to the limit,
+it will not be saved.
+
++++
+** New user option 'tab-first-completion'.
+If 'tab-always-indent' is 'complete', this new user option can be used to
+further tweak whether to complete or indent.
 
 ---
-*** A fringe arrow in the "*Occur*" buffer indicates the selected match.
+** 'indent-tabs-mode' is now a global minor mode instead of just a variable.
 
 ---
-*** Occur mode may use a different type for 'occur-target' property values.
-The value was previously always a marker set to the start of the first
-match on the line but can now also be a list of '(BEGIN . END)' pairs
-of markers delimiting each match on the line.
-This is a fully compatible change to the internal occur-mode
-implementation, and code creating their own occur-mode buffers will
-work as before.
+** New choice 'permanent' for 'shift-select-mode'.
+When the mark was activated by shifted motion keys, non-shifted motion
+keys don't deactivate the mark after customizing 'shift-select-mode'
+to 'permanent'.
 
-** EIEIO
++++
+** The "Edit => Clear" menu item now obeys a rectangular region.
 
 +++
-*** The macro 'oref-default' can now be used with 'setf'.
-It is now defined as a generalized variable that can be used with
-'setf' to modify the value stored in a given class slot.
+** New command 'revert-buffer-with-fine-grain'.
+Revert a buffer trying to be as non-destructive as possible,
+preserving markers, properties and overlays.  The new variable
+'revert-buffer-with-fine-grain-max-seconds' specifies the maximum
+number of seconds that 'revert-buffer-with-fine-grain' should spend
+trying to be non-destructive.
 
----
-*** 'form' in '(eql form)' specializers in 'cl-defmethod' is now evaluated.
-This corresponds to the behavior of defmethod in Common Lisp Object System.
-For compatibility, '(eql SYMBOL)' does not evaluate SYMBOL, for now.
++++
+** New command 'revert-buffer-quick'.
+This is bound to 'C-x x g' and is like 'revert-buffer', but prompts
+less.
 
-** New minor mode 'cl-font-lock-built-in-mode' for 'lisp-mode'.
-The mode provides refined highlighting of built-in functions, types,
-and variables.
++++
+** New user option 'revert-buffer-quick-short-answers'.
+This controls how the new 'revert-buffer-quick' ('C-x x g') command
+prompts.
 
-** Archive mode
++++
+** New user option 'query-about-changed-file'.
+If non-nil (the default), Emacs prompts as before when re-visiting a
+file that has changed externally after it was visited the first time.
+If nil, Emacs does not prompt, but instead shows the buffer with its
+contents before the change, and provides instructions how to revert
+the buffer.
+
+** New value 'save-some-buffers-root' of 'save-some-buffers-default-predicate'.
+They allow to ask about saving only those files that are under the
+project root or in subdirectories of the directory that was default
+during command invocation.
 
 ---
-*** Archive Mode can now parse ".squashfs" files.
+** New user option 'save-place-abbreviate-file-names'.
+This can simplify sharing the 'save-place-file' file across
+different hosts.
 
-*** Can now modify members of 'ar' archives.
+---
+** New user options 'copy-region-blink-delay' and 'delete-pair-blink-delay'.
+'copy-region-blink-delay' specifies a delay to indicate the region
+copied by 'kill-ring-save'.  'delete-pair-blink-delay' specifies
+a delay to show the paired character to delete.
 
-*** Display of summaries unified between backends.
+---
+** 'zap-up-to-char' now uses 'read-char-from-minibuffer'.
+This allows navigating through the history of characters that have
+been input.  This is mostly useful for characters that have complex
+input methods where inputting the character again may involve many
+keystrokes.
 
-*** New user option 'archive-hidden-columns' and command
-'archive-hideshow-column'.  These let you control which columns are
-displayed and which are kept hidden.
++++
+** Input history for 'goto-line' can now be made local to every buffer.
+In any event, line numbers used with 'goto-line' are kept in their own
+history list.  This should help make faster the process of finding
+line numbers that were previously jumped to.  By default, all buffers
+share a single history list.  To make every buffer have its own
+history list, customize the user option 'goto-line-history-local'.
 
----
-*** New command bound to 'C': 'archive-copy-file'.
-This command extracts the file under point and writes the data to a
-file.
++++
+** New command 'goto-line-relative' for use in a narrowed buffer.
+It moves point to the line relative to the accessible portion of the
+narrowed buffer.  'M-g M-g' in Info is rebound to this command.
+When 'widen-automatically' is non-nil, 'goto-line' widens the narrowed
+buffer to be able to move point to the inaccessible portion.
+'goto-line-relative' is bound to 'C-x n g'.
 
-** Emacs Lisp mode
++++
+** 'got-char' prompts for the character position.
+When called interactively, 'goto-char' now offers the position at
+point as the default.
 
-*** The mode-line now indicates whether we're using lexical or dynamic scoping.
+** Autosaving via 'auto-save-visited-mode' can now be inhibited.
+Set the variable 'auto-save-visited-mode' buffer-locally to nil to
+achieve that.
 
-*** A space between an open paren and a symbol changes the indentation rule.
-The presence of a space between an open paren and a symbol now is
-taken as a statement by the programmer that this should be indented
-as a data list rather than as a piece of code.
++++
+** New command 'C-x C-k Q' to force redisplay in keyboard macros.
 
-** Calendar
+** 'blink-cursor-mode' is now enabled by default regardless of the UI.
+It used to be enabled when Emacs is started in GUI mode but not when started
+in text mode.  The cursor still only actually blinks in GUI frames.
+
+
+* Changes in Specialized Modes and Packages in Emacs 28.1
+
+** Isearch and Replace
 
 +++
-*** New user option 'calendar-time-zone-style'.
-If 'numeric', calendar functions (eg 'calendar-sunrise-sunset') that display
-time zones will use a form like "+0100" instead of "CET".
+*** Interactive regular expression search now uses faces for sub-groups.
+E.g., 'C-M-s foo-\([0-9]+\)' will now use the 'isearch-group-1' face
+on the part of the regexp that matches the sub-expression "[0-9]+".
+By default, there are two faces for sub-group highlighting, but you
+can define more faces whose names are of the form 'isearch-group-N',
+where N are successive numbers above 2.
+
+This is controlled by the 'search-highlight-submatches' user option.
+This feature is available only on terminals that have enough colors to
+distinguish between sub-expression highlighting.
+
++++
+*** Interactive regular expression replace now uses faces for sub-groups.
+Like 'search-highlight-submatches', this is controlled by the new user option
+'query-replace-highlight-submatches'.
+
+*** New user option 'isearch-wrap-pause' defines how to wrap the search.
+There are choices to disable wrapping completely and to wrap immediately.
+When wrapping immediately, it consistently handles the numeric arguments
+of 'C-s' ('isearch-repeat-forward') and 'C-r' ('isearch-repeat-backward'),
+continuing with the remaining count after wrapping.
+
++++
+*** New user option 'isearch-repeat-on-direction-change'.
+When this option is set, direction changes in Isearch move to another
+search match, if there is one, instead of moving point to the other
+end of the current match.
+
+*** New key 'M-s M-.' starts isearch looking for the thing at point.
+This key is bound to the new command 'isearch-forward-thing-at-point'.
+The new user option 'isearch-forward-thing-at-point' defines
+a list of symbols to try to get the "thing" at point.  By default,
+the first element of the list is 'region' that tries to yank
+the currently active region to the search string.
+
++++
+*** New user option 'lazy-highlight-no-delay-length'.
+Lazy highlighting of matches in Isearch now starts immediately if the
+search string is at least this long.  'lazy-highlight-initial-delay'
+still applies for shorter search strings, which avoids flicker in the
+search buffer due to too many matches being highlighted.
 
 ** Dired
 
@@ -891,6 +1018,12 @@ time zones will use a form like "+0100" instead of "CET".
 If non-nil, Dired will kill the current buffer when selecting a new
 directory to display.
 
++++
+*** Behavior change on 'dired-do-chmod'.
+As a security precaution, Dired's M command no longer follows symbolic
+links.  Instead, it changes the symbolic link's own mode; this always
+fails on platforms where such modes are immutable.
+
 ---
 *** Behavior change on 'dired-clean-confirm-killing-deleted-buffers'.
 Previously, if 'dired-clean-up-buffers-too' was non-nil, and
@@ -944,14 +1077,16 @@ Non-nil reverts the destination Dired buffer after 
performing one
 of these operations: 'dired-do-copy', 'dired-do-rename',
 'dired-do-symlink', 'dired-do-hardlink'.
 
-*** New user option 'dired-mark-region' affects all Dired commands
-that mark files.  When non-nil and the region is active in Transient
-Mark mode, then Dired commands operate only on files in the active
-region.  The values 'file' and 'line' of this user option define the
-details of marking the file at the end of the region.
+*** New user option 'dired-mark-region'.
+This option affects all Dired commands that mark files.  When non-nil
+and the region is active in Transient Mark mode, then Dired commands
+operate only on files in the active region.  The values 'file' and
+'line' of this user option define the details of marking the file at
+the end of the region.
 
-*** State changing VC operations are supported in Dired on files and
-directories with the help of new command 'dired-vc-next-action'.
+*** State changing VC operations are supported in Dired.
+These operations are supported on files and directories via the new
+command 'dired-vc-next-action'.
 
 +++
 *** 'dired-jump' and 'dired-jump-other-window' moved from 'dired-x' to 'dired'.
@@ -966,284 +1101,240 @@ keys, add the following to your init file:
 (global-set-key "\C-x\C-j" nil)
 (global-set-key "\C-x4\C-j" nil)
 
-** Change Logs and VC
+---
+*** 'dired-query' now uses 'read-char-from-minibuffer'.
+Using it instead of 'read-char-choice' allows using 'C-x o'
+to switch to the help window displayed after typing 'C-h'.
 
-*** More VC commands can be used from non-file buffers.
-The relevant commands are those that don't change the VC state.
-The non-file buffers which can use VC commands are those that have
-their 'default-directory' under VC.
+** Outline
 
-*** New command 'vc-dir-root' uses the root directory without asking.
++++
+*** New commands to cycle heading visibility.
+Typing 'TAB' on a heading line cycles the current section between
+"hide all", "subheadings", and "show all" states.  Typing 'S-TAB'
+anywhere in the buffer cycles the whole buffer between "only top-level
+headings", "all headings and subheadings", and "show all" states.
 
----
-*** New face 'log-view-commit-body'.
-This is used when expanding commit messages from 'vc-print-root-log'
-and similar commands.
++++
+*** New user option 'outline-minor-mode-cycle'.
+This user option customizes 'outline-minor-mode', with the difference
+that 'TAB' and 'S-TAB' on heading lines cycle heading visibility.
+Typing 'TAB' on a heading line cycles the current section between
+"hide all", "subheadings", and "show all" states.  Typing 'S-TAB' on a
+heading line cycles the whole buffer between "only top-level
+headings", "all headings and subheadings", and "show all" states.
 
 ---
-*** New faces for 'vc-dir' buffers.
-Those are: 'vc-dir-header', 'vc-dir-header-value', 'vc-dir-directory',
-'vc-dir-file', 'vc-dir-mark-indicator', 'vc-dir-status-warning',
-'vc-dir-status-edited', 'vc-dir-status-up-to-date',
-'vc-dir-status-ignored'.
-
----
-*** The responsible VC backend is now the most specific one.
-'vc-responsible-backend' loops over the backends in
-'vc-handled-backends' to determine which backend is responsible for a
-specific (unregistered) file.  Previously the first matching backend
-was chosen, but now the one with the most specific path is chosen (in
-case there's a directory handled by one backend inside another).
+*** New user option 'outline-minor-mode-highlight'.
+This user option customizes 'outline-minor-mode'.  It puts
+highlighting on heading lines using standard outline faces.  This
+works well only when there are no conflicts with faces used by the
+major mode.
 
-*** New commands 'vc-dir-mark-registered-files' (bound to '* r') and
-'vc-dir-mark-unregistered-files'.
+** Ispell
 
-*** Support for bookmark.el.
-Bookmark locations can refer to VC directory buffers.
++++
+*** 'ispell-comments-and-strings' now accepts START and END arguments.
+These arguments default to active region when used interactively.
 
----
-*** New user option 'vc-hg-create-bookmark'.
-It controls whether a bookmark or branch will be created when you
-invoke 'C-u C-x v s' ('vc-create-tag').
++++
+*** New command 'ispell-comment-or-string-at-point'.
 
----
-*** 'vc-hg' now uses 'hg summary' to populate extra 'vc-dir' headers.
+** Flyspell mode
 
----
-*** New user option 'vc-git-revision-complete-only-branches'.
-If non-nil, only branches and remotes are considered when doing
-completion over Git branch names.  The default is nil, which causes
-tags to be considered as well.
++++
+*** Corrections and actions menu can be optionally bound to 'mouse-3'.
+When Flyspell mode highlights a word as misspelled, you can click on
+it to display a menu of possible corrections and actions.  You can now
+easily bind this menu to 'down-mouse-3' (usually the right mouse button)
+instead of 'mouse-2' (the default) by enabling 'context-menu-mode'.
 
 ---
-*** New user option 'vc-git-log-switches'.
-String or list of strings specifying switches for Git log under VC.
+*** The current dictionary is now displayed in the minor mode lighter.
+Clicking the dictionary name changes the current dictionary.
 
-** Gnus
+** Package
 
-+++
-*** New user option 'gnus-topic-display-predicate'.
-This can be used to inhibit the display of some topics completely.
+*** The new NonGNU ELPA archive is enabled by default alongside GNU ELPA.
+Thus, packages on nonGNU ELPA will appear by default in the list shown
+by 'list-packages'.
 
-+++
-*** nnimap now supports the oauth2.el library.
+---
+*** '/ s' ('package-menu-filter-by-status') changes parameter handling.
+The command was documented to take a comma-separated list of statuses
+to filter by, but instead it used the parameter as a regexp.  The
+command has been changed so that it now works as documented, and
+checks statuses not as a regexp, but instead an exact match from the
+comma-separated list.
 
 +++
-*** New Summary buffer sort options for extra headers.
-The extra header sort option ('C-c C-s C-x') prompts for a header
-and fails if no sort function has been defined.  Sorting by
-Newsgroups ('C-c C-s C-u') has been pre-defined.
+*** New command 'package-browse-url' and keystroke 'w'.
 
 +++
-*** The '#' command in the Group and Summary buffer now toggles,
-instead of sets, the process mark.
+*** New commands to filter the package list.
+The filter commands are bound to the following keys:
 
-+++
-*** New user option 'gnus-process-mark-toggle'.
-If non-nil (the default), the '#' command in the Group and Summary
-buffers will toggle, instead of set, the process mark.
+key             binding
+---             -------
+/ a             package-menu-filter-by-archive
+/ d             package-menu-filter-by-description
+/ k             package-menu-filter-by-keyword
+/ N             package-menu-filter-by-name-or-description
+/ n             package-menu-filter-by-name
+/ s             package-menu-filter-by-status
+/ v             package-menu-filter-by-version
+/ m             package-menu-filter-marked
+/ u             package-menu-filter-upgradable
+/ /             package-menu-filter-clear
 
+*** Option to automatically native-compile packages upon installation.
+Customize the user option 'package-native-compile' to enable automatic
+native compilation of packages when they are installed.  That option
+is nil by default; if set non-nil, and if your Emacs was built with
+native-compilation support, each package will be natively compiled
+when it is installed, by invoking an asynchronous Emacs subprocess to
+run the native-compilation of the package files.  (Be sure to leave
+Emacs running until these asynchronous subprocesses exit, or else the
+native-compilation will be aborted when you exit Emacs.)
 
-+++
-*** New user option 'gnus-registry-register-all'.
-If non-nil (the default), create registry entries for all messages.
-If nil, don't automatically create entries, they must be created
-manually.
+---
+*** Column widths in 'list-packages' display can now be customized.
+See the new user options 'package-name-column-width',
+'package-version-column-width', 'package-status-column-width', and
+'package-archive-column-width'.
 
-+++
-*** New user options to customise the summary line specs "%[" and "%]".
-Four new options introduced in customisation group
-'gnus-summary-format'.  These are 'gnus-sum-opening-bracket',
-'gnus-sum-closing-bracket', 'gnus-sum-opening-bracket-adopted', and
-'gnus-sum-closing-bracket-adopted'.  Their default values are "[", "]",
-"<", ">" respectively.  These options control the appearance of "%["
-and "%]" specs in the summary line format.  "%[" will normally display
-the value of 'gnus-sum-opening-bracket', but can also be
-'gnus-sum-opening-bracket-adopted' for the adopted articles.  "%]" will
-normally display the value of 'gnus-sum-closing-bracket', but can also
-be 'gnus-sum-closing-bracket-adopted' for the adopted articles.
+** Info
 
-+++
-*** New user option 'gnus-paging-select-next'.
-This controls what happens when using commands like 'SPC' and 'DEL' to
-page the current article.  If non-nil (the default), go to the
-next/prev article, but if nil, do nothing at the end/start of the article.
+---
+*** New user option 'Info-warn-on-index-alternatives-wrap'.
+This option affects what happens when using the ',' command after
+looking up an entry with 'i' in info buffers.  If non-nil (the
+default), the ',' command will now display a warning when proceeding
+beyond the final index match, and tapping ',' once more will then take
+you to the first match.
 
-+++
-*** New gnus-search library.
-A new unified search syntax which can be used across multiple
-supported search engines.  Set 'gnus-search-use-parsed-queries' to
-non-nil to enable.
+** Abbrev mode
 
 +++
-*** New value for user option 'smiley-style'.
-Smileys can now be rendered with emojis instead of small images when
-using the new 'emoji' value in 'smiley-style'.
+*** Emacs can now suggest to use an abbrev based on text you type.
+A new user option, 'abbrev-suggest', enables the new abbrev suggestion
+feature.  When enabled, if a user manually types a piece of text that
+could have saved enough typing by using an abbrev, a hint will be
+displayed in the echo area, mentioning the abbrev that could have been
+used instead.
 
-+++
-*** New user option 'gnus-agent-eagerly-store-articles'.
-If non-nil (which is the default), the Gnus Agent will store all read
-articles in the Agent cache.
+** Bookmarks
 
-+++
-*** New user option 'gnus-global-groups'.
-Gnus handles private groups differently from public (i.e., NNTP-like)
-groups.  Most importantly, Gnus doesn't download external images from
-mail-like groups.  This can be overridden by putting group names in
-'gnus-global-groups': Any group present in that list will be treated
-like a public group.
+*** Bookmarks can now be targets for new tabs.
+When the bookmark.el library is loaded, a customize choice is added
+to 'tab-bar-new-tab-choice' for new tabs to show the bookmark list.
 
-+++
-*** New scoring types for the Date header.
-You can now score based on the relative age of an article with the new
-'<' and '>' date scoring types.
+---
+*** The 'list-bookmarks' menu is now based on 'tabulated-list-mode'.
+The interactive bookmark list will now benefit from features in
+'tabulated-list-mode' like sorting columns or changing column width.
 
-+++
-*** User-defined scoring is now possible.
-The new type is 'score-fn'.  More information in the Gnus manual node
-"(gnus) Score File Format".
+Support for the optional "inline" header line, allowing for a header
+without using 'header-line-format', has been dropped.  Consequently,
+the variables 'bookmark-bmenu-use-header-line' and
+'bookmark-bmenu-inline-header-height' are now declared obsolete.
 
-+++
-*** New backend 'nnselect'.
-The newly added 'nnselect' backend allows creating groups from an
-arbitrary list of articles that may come from multiple groups and
-servers.  These groups generally behave like any other group: they may
-be ephemeral or persistent, and allow article marking, moving,
-deletion, etc.  'nnselect' groups may be created like any other group,
-but there are three convenience functions for the common case of
-obtaining the list of articles as a result of a search:
-'gnus-group-make-search-group' ('G g') that will prompt for an 'nnir'
-search query and create a persistent group for that search;
-'gnus-group-read-ephemeral-search-group' ('G G') that will prompt for
-an 'nnir' search query and create an ephemeral group for that search;
-and 'gnus-summary-make-group-from-search' ('C-c C-p') that will create
-a persistent group with the search parameters of a current ephemeral
-search group.
+---
+*** New user option 'bookmark-fontify'.
+If non-nil, setting a bookmark will colorize the current line with
+'bookmark-face'.
 
-As part of this addition, the user option 'nnir-summary-line-format'
-has been removed; its functionality is now available directly in the
-'gnus-summary-line-format' specs '%G' and '%g'.  The user option
-'gnus-refer-thread-use-nnir' has been renamed to
-'gnus-refer-thread-use-search'.
+---
+*** New user option 'bookmark-menu-confirm-deletion'.
+In Bookmark Menu mode, Emacs by default does not prompt for
+confirmation when you type 'x' to execute the deletion of bookmarks
+that have been marked for deletion.  However, if this new option is
+non-nil then Emacs will require confirmation with 'yes-or-no-p' before
+deleting.
 
-+++
-*** New user option 'gnus-dbus-close-on-sleep'.
-On systems with D-Bus support, it is now possible to register a signal
-to close all Gnus servers before the system sleeps.
+** Recentf
 
-+++
-*** The key binding of 'gnus-summary-search-article-forward' has changed.
-This command was previously on 'M-s' and shadowed the global 'M-s'
-search prefix.  The command has now been moved to 'M-s M-s'.  (For
-consistency, the 'M-s M-r' key binding has been added for the
-'gnus-summary-search-article-backward' command.)
+---
+*** The recentf files are no longer backed up.
 
 ---
-*** The value of "all" in the 'large-newsgroup-initial' group parameter 
changes.
-It was previously nil, which didn't work, because nil is
-indistinguishable from not being present.  The new value for "all" is
-the symbol 'all'.
+*** 'recentf-auto-cleanup' now repeats daily when set to a time string.
+When 'recentf-auto-cleanup' is set to a time string, it now repeats
+every day, rather than only running once after the mode is turned on.
 
-+++
-*** The name of dependent Gnus sessions has changed from "slave" to "child".
-The names of the commands 'gnus-slave', 'gnus-slave-no-server' and
-'gnus-slave-unplugged' have changed to 'gnus-child',
-'gnus-child-no-server' and 'gnus-child-unplugged' respectively.
+** Calc
 
-+++
-*** The 'W Q' summary mode command now takes a numerical prefix to
-allow adjusting the fill width.
+---
+*** The behavior when doing forward-delete has been changed.
+Previously, using the 'C-d' command would delete the final number in
+the input field, no matter where point was.  This has been changed to
+work more traditionally, with 'C-d' deleting the next character.
+Likewise, point isn't moved to the end of the string before inserting
+digits.
 
 +++
-*** New variable 'mm-inline-font-lock'.
-This variable is supposed to be bound by callers to determine whether
-inline MIME parts (that support it) are supposed to be font-locked or
-not.
+*** Setting the word size to zero disables word clipping.
+The word size normally clips the results of certain bit-oriented
+operations such as shifts and bitwise XOR.  A word size of zero, set
+by 'b w', makes the operation have effect on the whole argument values
+and the result is not truncated in any way.
 
-** Message
+---
+*** The '/' operator now has higher precedence in (La)TeX input mode.
+It no longer has lower precedence than '+' and '-'.
 
 ---
-*** Respect 'message-forward-ignored-headers' more.
-Previously, this user option would not be consulted if
-'message-forward-show-mml' was nil and forwarding as MIME.
+*** Calc now marks its windows dedicated.
+The new user option 'calc-make-windows-dedicated' controls this.  It
+is t by default; set to nil to get back the old behavior.
 
-+++
-*** New user option 'message-forward-included-mime-headers'.
-This is used when forwarding messages as MIME, but not using MML.
+** Calendar
 
 +++
-*** Message now supports the OpenPGP header.
-To generate these headers, add the new function
-'message-add-openpgp-header' to 'message-send-hook'.  The header will
-be generated according to the new 'message-openpgp-header' variable.
-
----
-*** A change to how "Mail-Copies-To: never" is handled.
-If a user has specified "Mail-Copies-To: never", and Message was asked
-to do a "wide reply", some other arbitrary recipient would end up in
-the resulting "To" header, while the remaining recipients would be put
-in the "Cc" header.  This is somewhat misleading, as it looks like
-you're responding to a specific person in particular.  This has been
-changed so that all the recipients are put in the "To" header in these
-instances.
+*** New user option 'calendar-time-zone-style'.
+If 'numeric', calendar functions (eg 'calendar-sunrise-sunset') that display
+time zones will use a form like "+0100" instead of "CET".
 
-+++
-*** New command to start Emacs in Message mode to send an email.
-Emacs can be defined as a handler for the "x-scheme-handler/mailto"
-MIME type with the following command: "emacs -f message-mailto %u".
-An "emacs-mail.desktop" file has been included, suitable for
-installing in desktop directories like "/usr/share/applications" or
-"~/.local/share/applications".
-Clicking on a 'mailto:' link in other applications will then open
-Emacs with headers filled out according to the link, e.g.
-"mailto:larsi@gnus.org?subject=This+is+a+test";.  If you prefer
-emacsclient, use "emacsclient -e '(message-mailto "%u")'"
-or "emacsclient-mail.desktop".
+** ido
 
 ---
-*** Change to default value of 'message-draft-headers' user option.
-The 'Date' symbol has been removed from the default value, meaning that
-draft or delayed messages will get a date reflecting when the message
-was sent.  To restore the original behavior of dating a message
-from when it is first saved or delayed, add the symbol 'Date' back to
-this user option.
-
-+++
-*** New command to take screenshots.
-In Message mode buffers, the 'C-c C-p' ('message-insert-screenshot')
-command has been added.  It depends on using an external program to
-take the actual screenshot, and defaults to "ImageMagick import".
-
-** Smtpmail
+*** Switching on 'ido-mode' now also overrides 'ffap-file-finder'.
 
-+++
-*** smtpmail now supports using the oauth2.el library.
+---
+*** Killing virtual ido buffers interactively will make them go away.
+Previously, killing a virtual ido buffer with 'ido-kill-buffer' didn't
+do anything.  This has now been changed, and killing virtual buffers
+with that command will remove the buffer from recentf.
 
-+++
-*** New user option 'smtpmail-store-queue-variables'.
-If non-nil, SMTP variables will be stored together with the queued
-messages, and will then be used when sending with
-'M-x smtpmail-send-queued-mail'.
+** So Long
 
-+++
-*** Allow direct selection of smtp authentication mechanism.
-A server entry retrieved by auth-source can request a desired smtp
-authentication mechanism by setting a value for the key 'smtp-auth'.
+---
+*** New 'so-long-predicate' function 'so-long-statistics-excessive-p'.
+It efficiently detects the presence of a long line anywhere in the
+buffer using 'buffer-line-statistics' (see above).  This is now the
+default predicate (replacing 'so-long-detected-long-line-p').
 
-** Search and Replace
+---
+*** Default values 'so-long-threshold' and 'so-long-max-lines' increased.
+The values of these variables have been raised to 10000 bytes and 500
+lines respectively, to reduce the likelihood of false-positives when
+'global-so-long-mode' is enabled.  The latter value is now only used
+by the old predicate, as the new predicate knows the longest line in
+the entire buffer.
 
-*** New key 'M-s M-.' starts isearch with the thing found at point.
-This key is bound to the new command 'isearch-forward-thing-at-point'.
-The new user option 'isearch-forward-thing-at-point' defines
-a list of symbols to try to get the "thing" at point.  By default,
-the first element of the list is 'region' that tries to yank
-the currently active region to the search string.
+---
+*** 'so-long-target-modes' now includes 'fundamental-mode' by default.
+This means that 'global-so-long-mode' will also process files which were
+not recognised.  (This only has an effect if 'set-auto-mode' chooses
+'fundamental-mode'; buffers which are simply in 'fundamental-mode' by
+default are unaffected.)
 
-*** New user option 'isearch-wrap-pause' defines how to wrap the search.
-There are choices to disable wrapping completely and to wrap immediately.
-When wrapping immediately, it consistently handles the numeric arguments
-of 'C-s' ('isearch-repeat-forward') and 'C-r' ('isearch-repeat-backward'),
-continuing with the remaining count after wrapping.
+---
+*** New user options to preserve modes and variables.
+The new options 'so-long-mode-preserved-minor-modes' and
+'so-long-mode-preserved-variables' allow specified mode and variable
+states to be maintained if 'so-long-mode' replaces the original major
+mode.  By default, these new options support 'view-mode'.
 
 ** Grep
 
@@ -1274,217 +1365,501 @@ This change is for better compatibility with old 
versions of non-GNU
 This returns the name of the file at point (if any) in 'grep-mode'
 buffers.
 
-** Help
+** Shell
+
+---
+*** New command in 'shell-mode': 'narrow-to-prompt'.
+This is bound to 'C-x n d' in 'shell-mode' buffers, and narrows to the
+command line under point (and any following output).
+
+---
+*** New user option 'shell-has-auto-cd'.
+If non-nil, 'shell-mode' handles implicit "cd" commands, changing the
+directory if the command is a directory.  Useful for shells like "zsh"
+that has this feature.
+
+** term-mode
+
+---
+*** New user option 'term-scroll-snap-to-bottom'.
+By default, 'term' and 'ansi-term' will now recenter the buffer so
+that the prompt is on the final line in the window.  Setting this new
+user option to nil inhibits this behavior.
+
+---
+*** New user option 'term-set-terminal-size'
+If non-nil, the 'LINES' and 'COLUMNS' environment variables will be set
+based on the current window size.  In previous versions of Emacs, this
+was always done (and that could lead to odd displays when resizing the
+window after starting).  This variable defaults to nil.
+
+** Eshell
+
+---
+*** 'eshell-hist-ignoredups' can now also be used to mimic "erasedups" in bash.
+
+---
+*** Environment variable 'INSIDE_EMACS' is now copied to subprocesses.
+Its value contains the result of evaluating '(format "%s,eshell"
+emacs-version)'.  Other package names, like "tramp", could also be included.
+
+---
+*** Eshell no longer re-initializes its keymap every call.
+This allows users to use (define-key eshell-mode-map ...) as usual.
+Some modules have their own minor mode now to account for these
+changes.
+
+** Archive mode
+
+---
+*** Archive Mode can now parse ".squashfs" files.
+
+*** Can now modify members of 'ar' archives.
+
+*** Display of summaries is unified between backends.
+
+*** New user option and command to control displayed columns.
+New user option 'archive-hidden-columns' and new command
+'archive-hideshow-column' let you control which columns are displayed
+and which are kept hidden.
+
+---
+*** New command bound to 'C': 'archive-copy-file'.
+This command extracts the file at point and writes its data to a
+file.
+
+** browse-url
+
+*** Added support for custom URL handlers.
+There is a new variable 'browse-url-default-handlers' and a user
+option 'browse-url-handlers' being alists with '(REGEXP-OR-PREDICATE
+. FUNCTION)' entries allowing to define different browsing FUNCTIONs
+depending on the URL to be browsed.  The variable is for default
+handlers provided by Emacs itself or external packages, the user
+option is for the user (and allows for overriding the default
+handlers).
+
+Formerly, one could do the same by setting
+'browse-url-browser-function' to such an alist.  This usage is still
+supported but deprecated.
+
+*** Categorization of browsing commands into internal vs. external.
+All standard browsing commands such as 'browse-url-firefox',
+'browse-url-mail', or 'eww' have been categorized into internal (URL
+is browsed in Emacs) or external (an external application is spawned
+with the URL).  This is done by adding a 'browse-url-browser-kind'
+symbol property to the browsing commands.  With a new command
+'browse-url-with-browser-kind', an URL can explicitly be browsed with
+either an internal or external browser.
+
+---
+*** Support for browsing of remote files.
+If a remote file is specified, a local temporary copy of that file is
+passed to the browser.
+
+*** Support for the conkeror browser is now obsolete.
+
+*** Support for the Mosaic browser has been removed.
+This support has been obsolete since 25.1.
+
+** Completion List Mode
+New key bindings have been added to 'completion-list-mode': 'n' and
+'p' now navigate completions, and 'M-g M-c' switches to the
+minibuffer and back to the completion list buffer.
 
 +++
-*** New convenience commands with short keys in the Help buffer.
-New command 'help-view-source' ('s') will view the source file (if
-any) of the current help topic.  New command 'help-goto-info' ('i')
-will look up the current symbol (if any) in Info.  New command
-'help-customize' ('c') will customize the variable or the face
-(if any) whose doc string is being shown in the Help buffer.
+** profiler.el
+The results displayed by 'profiler-report' now have the usage figures
+at the left hand side followed by the function name.  This is intended
+to make better use of the horizontal space, in particular eliminating
+the truncation of function names.  There is no way to get the former
+layout back.
+
+** Python mode
+
+---
+*** New user option 'python-forward-sexp-function'.
+This allows the user easier customization of whether to use block-based
+navigation or not.
+
+---
+*** 'python-shell-interpreter' now defaults to python3 on systems with python3.
+
+---
+*** 'C-c C-r' can now be used on arbitrary regions.
+The command previously extended the start of the region to the start
+of the line, but will now actually send the marked region, as
+documented.
+
+** Perl mode
+
+---
+*** New face 'perl-non-scalar-variable'.
+This is used to fontify non-scalar variables.
+
+** Icomplete
+
+---
+*** New user option 'icomplete-matches-format'.
+This allows controlling the current/total number of matches for the
+prompt prefix.
+
++++
+*** New minor modes 'icomplete-vertical-mode' and 'fido-vertical-mode'.
+These modes modify Icomplete ('M-x icomplete-mode') and Fido ('M-x
+fido-mode'), to display completion candidates vertically instead of
+horizontally.  In Icomplete, completions are rotated and selection
+kept at the top.  In Fido, completions scroll like a typical dropdown
+widget.  Both these new minor modes will turn on their non-vertical
+counterparts first, if they are not on already.
+
+---
+*** Default value of 'icomplete-compute-delay' has been changed to 0.15 s.
+
+---
+*** Default value of 'icomplete-max-delay-chars' has been changed to 2.
+
+---
+*** Reduced blinking while completing the next completions set.
+Icomplete doesn't hide the hint with the previously computed
+completions anymore when compute delay is in effect, or the previous
+computation has been aborted by input.  Instead it shows the previous
+completions until the new ones are ready.
+
+---
+*** Change in meaning of 'icomplete-show-matches-on-no-input'.
+Previously, choosing a different completion with commands like 'C-.'
+and then hitting 'RET' would choose the default completion.  Doing this
+will now choose the completion under point instead.  Also when this option
+is nil, completions are not shown when the minibuffer reads a file name
+with initial input as the default directory.
+
+** mspool.el
+
+---
+*** Autoload the main entry point 'mspool-show'.
+
+** Windmove
+
++++
+*** New user options to customize windmove keybindings.
+These options include 'windmove-default-keybindings',
+'windmove-display-default-keybindings',
+'windmove-delete-default-keybindings',
+'windmove-swap-states-default-keybindings'.
+
+** Occur mode
+
+*** New bindings in occur-mode.
+The command 'next-error-no-select' is now bound to 'n' and
+'previous-error-no-select' is bound to 'p'.
+
+*** The new command 'recenter-current-error'.
+It is bound to 'l' in Occur or compilation buffers, and recenters the
+current displayed occurrence/error.
+
+*** Matches in target buffers are now highlighted as in 'compilation-mode'.
+The method of highlighting is specified by the user options
+'next-error-highlight' and 'next-error-highlight-no-select'.
+
+---
+*** A fringe arrow in the "*Occur*" buffer indicates the selected match.
+
+---
+*** Occur mode may use a different type for 'occur-target' property values.
+The value was previously always a marker set to the start of the first
+match on the line but can now also be a list of '(BEGIN . END)' pairs
+of markers delimiting each match on the line.
+This is a fully compatible change to the internal occur-mode
+implementation, and code creating their own occur-mode buffers will
+work as before.
+
+** New minor mode 'cl-font-lock-built-in-mode' for 'lisp-mode'.
+The mode provides refined highlighting of built-in functions, types,
+and variables.
+
+** Emacs Lisp mode
+
+*** The mode-line now indicates whether we're using lexical or dynamic scoping.
+
+*** A space between an open paren and a symbol changes the indentation rule.
+The presence of a space between an open paren and a symbol now is
+taken as a statement by the programmer that this should be indented
+as a data list rather than as a piece of code.
+
+** Change Logs and VC
+
++++
+*** 'vc-revert-show-diff' now has a third possible value: 'kill'.
+If this user option is 'kill', then the diff buffer will be killed
+after the 'vc-revert' action instead of buried.
+
+*** More VC commands can be used from non-file buffers.
+The relevant commands are those that don't change the VC state.
+The non-file buffers which can use VC commands are those that have
+their 'default-directory' under VC.
+
+*** New command 'vc-dir-root' uses the root directory without asking.
 
 ---
-*** The 'help-for-help' ('C-h C-h') screen has been redesigned.
+*** New face 'log-view-commit-body'.
+This is used when expanding commit messages from 'vc-print-root-log'
+and similar commands.
 
 ---
-*** Keybindings in 'help-mode' use the new 'help-key-binding' face.
-This face is added by 'substitute-command-keys' to any "\[command]"
-substitution.  The return value of that function should consequently
-be assumed to be a propertized string.
-
-Note that the new face will also be used in tooltips.  When using the
-GTK toolkit, this is only true if 'x-gtk-use-system-tooltips' is t.
+*** New faces for 'vc-dir' buffers.
+Those are: 'vc-dir-header', 'vc-dir-header-value', 'vc-dir-directory',
+'vc-dir-file', 'vc-dir-mark-indicator', 'vc-dir-status-warning',
+'vc-dir-status-edited', 'vc-dir-status-up-to-date',
+'vc-dir-status-ignored'.
 
 ---
-*** 'g' ('revert-buffer') in 'help-mode' no longer requires confirmation.
+*** The responsible VC backend is now the most specific one.
+'vc-responsible-backend' loops over the backends in
+'vc-handled-backends' to determine which backend is responsible for a
+specific (unregistered) file.  Previously, the first matching backend
+was chosen, but now the one with the most specific path is chosen (in
+case there's a directory handled by one backend inside another).
 
-+++
-*** New command 'describe-command' shows help for a command.
-This can be used instead of 'describe-function' for interactive
-commands and is globally bound to 'C-h x'.
+*** New commands 'vc-dir-mark-registered-files' (bound to '* r') and
+'vc-dir-mark-unregistered-files'.
 
-+++
-*** New command 'describe-keymap' describes keybindings in a keymap.
+*** Support for bookmark.el.
+Bookmark locations can refer to VC directory buffers.
 
 ---
-*** New user option 'describe-bindings-outline'.
-It enables outlines in the output buffer of 'describe-bindings' that
-can provide a better overview in a long list of available bindings.
+*** New user option 'vc-hg-create-bookmark'.
+It controls whether a bookmark or branch will be created when you
+invoke 'C-u C-x v s' ('vc-create-tag').
 
 ---
-*** New keybinding 'C-h R' prompts for a manual to display and displays it.
+*** 'vc-hg' now uses 'hg summary' to populate extra 'vc-dir' headers.
 
 ---
-*** Closing the "*Help*" buffer from the toolbar now buries the buffer.
-In previous Emacs versions, the "*Help*" buffer was killed instead when
-clicking the "X" icon in the tool bar.
-
-** Info
+*** New user option 'vc-git-revision-complete-only-branches'.
+If non-nil, only branches and remotes are considered when doing
+completion over Git branch names.  The default is nil, which causes
+tags to be considered as well.
 
 ---
-*** New user option 'Info-warn-on-index-alternatives-wrap'.
-This option affects what happens when using the ',' command after
-looking up an entry with 'i' in info buffers.  If non-nil (the
-default), the ',' command will now warn you when proceeding beyond the
-final entry, and tapping ',' once more will then take you to the
-first entry.
+*** New user option 'vc-git-log-switches'.
+String or list of strings specifying switches for Git log under VC.
+
+** Gnus
 
 +++
-** New command 'lossage-size'.
-It allows users to set the maximum number of keystrokes and commands
-recorded for the purpose of 'view-lossage'.
+*** New user option 'gnus-topic-display-predicate'.
+This can be used to inhibit the display of some topics completely.
 
----
-*** The command 'view-lossage' can now be invoked from the menu bar.
-The menu bar "Help" menu now has a "Show Recent Inputs" item under the
-"Describe" sub-menu.
++++
+*** nnimap now supports the oauth2.el library.
 
-** Input methods
++++
+*** New Summary buffer sort options for extra headers.
+The extra header sort option ('C-c C-s C-x') prompts for a header
+and fails if no sort function has been defined.  Sorting by
+Newsgroups ('C-c C-s C-u') has been pre-defined.
 
 +++
-*** Emacs now supports "transient" input methods.
-A transient input method is enabled for inserting a single character,
-and is then automatically disabled.  'C-x \' temporarily enables the
-selected transient input method.  Use 'C-u C-x \' to select a
-transient input method (which can be different from the input method
-enabled by 'C-\').  For example, 'C-u C-x \ compose RET' selects the
-'compose' input method; then typing 'C-x \ 1 2' will insert the
-character '½', and disable the 'compose' input method afterwards.
-You can use 'C-x \' in incremental search to insert a single character
-to the search string.
+*** The '#' command in the Group and Summary buffer now toggles,
+instead of sets, the process mark.
 
----
-*** New input method 'compose' based on X Multi_key sequences.
++++
+*** New user option 'gnus-process-mark-toggle'.
+If non-nil (the default), the '#' command in the Group and Summary
+buffers will toggle, instead of set, the process mark.
 
----
-*** New input method 'iso-transl' with the same keys as 'C-x 8'.
-After selecting it as a transient input method with 'C-u C-x \
-iso-transl RET', it supports the same key sequences as 'C-x 8',
-so e.g. like 'C-x 8 [' inserts a left single quotation mark,
-'C-x \ [' does the same.
 
----
-*** New user option 'read-char-by-name-sort'.
-It defines the sorting order of characters for completion of 'C-x 8 RET TAB'
-and can be customized to sort them by codepoints instead of character names.
-Additionally, you can group characters by Unicode blocks after customizing
-'completions-group' and 'completions-group-sort'.
++++
+*** New user option 'gnus-registry-register-all'.
+If non-nil (the default), create registry entries for all messages.
+If nil, don't automatically create entries, they must be created
+manually.
 
----
-*** Improved language transliteration in Malayalam input methods.
-Added a new Mozhi scheme.  The inapplicable ITRANS scheme is now
-deprecated.  Errors in the Inscript method were corrected.
++++
+*** New user options to customise the summary line specs "%[" and "%]".
+Four new options introduced in customisation group
+'gnus-summary-format'.  These are 'gnus-sum-opening-bracket',
+'gnus-sum-closing-bracket', 'gnus-sum-opening-bracket-adopted', and
+'gnus-sum-closing-bracket-adopted'.  Their default values are "[", "]",
+"<", ">" respectively.  These options control the appearance of "%["
+and "%]" specs in the summary line format.  "%[" will normally display
+the value of 'gnus-sum-opening-bracket', but can also be
+'gnus-sum-opening-bracket-adopted' for the adopted articles.  "%]" will
+normally display the value of 'gnus-sum-closing-bracket', but can also
+be 'gnus-sum-closing-bracket-adopted' for the adopted articles.
 
----
-*** New input method 'cham'.
-There's also a Cham greeting in "etc/HELLO".
++++
+*** New user option 'gnus-paging-select-next'.
+This controls what happens when using commands like 'SPC' and 'DEL' to
+page the current article.  If non-nil (the default), go to the
+next/prev article, but if nil, do nothing at the end/start of the article.
 
----
-*** New input methods for Lakota language orthographies.
-Two orthographies are represented here, the Suggested Lakota
-Orthography and what is known as the White Hat Orthography.  Input
-methods 'lakota-slo-prefix', 'lakota-slo-postfix', and
-'lakota-white-hat-postfix' have been added.  There is also a Lakota
-greeting in "etc/HELLO".
++++
+*** New gnus-search library.
+A new unified search syntax which can be used across multiple
+supported search engines.  Set 'gnus-search-use-parsed-queries' to
+non-nil to enable.
 
-** Ispell
++++
+*** New value for user option 'smiley-style'.
+Smileys can now be rendered with emojis instead of small images when
+using the new 'emoji' value in 'smiley-style'.
 
 +++
-*** 'ispell-comments-and-strings' now accepts START and END arguments,
-defaulting to active region when used interactively.
+*** New user option 'gnus-agent-eagerly-store-articles'.
+If non-nil (which is the default), the Gnus Agent will store all read
+articles in the Agent cache.
 
 +++
-*** New command 'ispell-comment-or-string-at-point' is provided.
+*** New user option 'gnus-global-groups'.
+Gnus handles private groups differently from public (i.e., NNTP-like)
+groups.  Most importantly, Gnus doesn't download external images from
+mail-like groups.  This can be overridden by putting group names in
+'gnus-global-groups': Any group present in that list will be treated
+like a public group.
 
----
-** The old non-SMIE indentation of 'sh-mode' has been removed.
++++
+*** New scoring types for the Date header.
+You can now score based on the relative age of an article with the new
+'<' and '>' date scoring types.
 
----
-** The sb-image.el library is now marked obsolete.
-This file was a compatibility kludge which is no longer needed.
++++
+*** User-defined scoring is now possible.
+The new type is 'score-fn'.  More information in the Gnus manual node
+"(gnus) Score File Format".
 
----
-** Lisp mode now uses 'common-lisp-indent-function'.
-To revert to the previous behavior,
-'(setq lisp-indent-function 'lisp-indent-function)' from 'lisp-mode-hook'.
++++
+*** New backend 'nnselect'.
+The newly added 'nnselect' backend allows creating groups from an
+arbitrary list of articles that may come from multiple groups and
+servers.  These groups generally behave like any other group: they may
+be ephemeral or persistent, and allow article marking, moving,
+deletion, etc.  'nnselect' groups may be created like any other group,
+but there are three convenience functions for the common case of
+obtaining the list of articles as a result of a search:
+'gnus-group-make-search-group' ('G g') that will prompt for an 'nnir'
+search query and create a persistent group for that search;
+'gnus-group-read-ephemeral-search-group' ('G G') that will prompt for
+an 'nnir' search query and create an ephemeral group for that search;
+and 'gnus-summary-make-group-from-search' ('C-c C-p') that will create
+a persistent group with the search parameters of a current ephemeral
+search group.
 
-** Customize
+As part of this addition, the user option 'nnir-summary-line-format'
+has been removed; its functionality is now available directly in the
+'gnus-summary-line-format' specs '%G' and '%g'.  The user option
+'gnus-refer-thread-use-nnir' has been renamed to
+'gnus-refer-thread-use-search'.
 
----
-*** Customize buffers can now be reverted with 'C-x x g'.
++++
+*** New user option 'gnus-dbus-close-on-sleep'.
+On systems with D-Bus support, it is now possible to register a signal
+to close all Gnus servers before the system sleeps.
 
-*** Most customize commands now hide obsolete user options.
-Obsolete user options are no longer shown in the listings produced by
-the commands 'customize', 'customize-group', 'customize-apropos' and
-'customize-changed'.
++++
+*** The key binding of 'gnus-summary-search-article-forward' has changed.
+This command was previously on 'M-s' and shadowed the global 'M-s'
+search prefix.  The command has now been moved to 'M-s M-s'.  (For
+consistency, the 'M-s M-r' key binding has been added for the
+'gnus-summary-search-article-backward' command.)
 
-To customize obsolete user options, use 'customize-option' or
-'customize-saved'.
+---
+*** The value of "all" in the 'large-newsgroup-initial' group parameter 
changes.
+It was previously nil, which didn't work, because nil is
+indistinguishable from not being present.  The new value for "all" is
+the symbol 'all'.
 
-*** 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.
++++
+*** The name of dependent Gnus sessions has changed from "slave" to "child".
+The names of the commands 'gnus-slave', 'gnus-slave-no-server' and
+'gnus-slave-unplugged' have changed to 'gnus-child',
+'gnus-child-no-server' and 'gnus-child-unplugged' respectively.
 
-** Bookmarks
++++
+*** The 'W Q' summary mode command now takes a numerical prefix to
+allow adjusting the fill width.
 
-*** Bookmarks can now be targets for new tabs.
-When the bookmark.el library is loaded, a customize choice is added
-to 'tab-bar-new-tab-choice' for new tabs to show the bookmark list.
++++
+*** New variable 'mm-inline-font-lock'.
+This variable is supposed to be bound by callers to determine whether
+inline MIME parts (that support it) are supposed to be font-locked or
+not.
+
+** Message
 
 ---
-*** The 'list-bookmarks' menu is now based on 'tabulated-list-mode'.
-The interactive bookmark list will now benefit from features in
-'tabulated-list-mode' like sorting columns or changing column width.
+*** Respect 'message-forward-ignored-headers' more.
+Previously, this user option would not be consulted if
+'message-forward-show-mml' was nil and forwarding as MIME.
 
-Support for the optional "inline" header line, allowing for a header
-without using 'header-line-format', has been dropped.  Consequently,
-the variables 'bookmark-bmenu-use-header-line' and
-'bookmark-bmenu-inline-header-height' are now declared obsolete.
++++
+*** New user option 'message-forward-included-mime-headers'.
+This is used when forwarding messages as MIME, but not using MML.
 
----
-*** New user option 'bookmark-fontify'.
-If non-nil, setting a bookmark will colorize the current line with
-'bookmark-face'.
++++
+*** Message now supports the OpenPGP header.
+To generate these headers, add the new function
+'message-add-openpgp-header' to 'message-send-hook'.  The header will
+be generated according to the new 'message-openpgp-header' variable.
 
 ---
-*** New user option 'bookmark-menu-confirm-deletion'.
-In Bookmark Menu mode, Emacs by default does not prompt for
-confirmation when you type 'x' to execute the deletion of bookmarks
-that have been marked for deletion.  However, if this new option is
-non-nil then Emacs will require confirmation with 'yes-or-no-p' before
-deleting.
+*** A change to how "Mail-Copies-To: never" is handled.
+If a user has specified "Mail-Copies-To: never", and Message was asked
+to do a "wide reply", some other arbitrary recipient would end up in
+the resulting "To" header, while the remaining recipients would be put
+in the "Cc" header.  This is somewhat misleading, as it looks like
+you're responding to a specific person in particular.  This has been
+changed so that all the recipients are put in the "To" header in these
+instances.
 
-** Edebug
++++
+*** New command to start Emacs in Message mode to send an email.
+Emacs can be defined as a handler for the "x-scheme-handler/mailto"
+MIME type with the following command: "emacs -f message-mailto %u".
+An "emacs-mail.desktop" file has been included, suitable for
+installing in desktop directories like "/usr/share/applications" or
+"~/.local/share/applications".
+Clicking on a 'mailto:' link in other applications will then open
+Emacs with headers filled out according to the link, e.g.
+"mailto:larsi@gnus.org?subject=This+is+a+test";.  If you prefer
+emacsclient, use "emacsclient -e '(message-mailto "%u")'"
+or "emacsclient-mail.desktop".
 
-*** Obsoletions
 ---
-**** 'get-edebug-spec' is obsolete, replaced by 'edebug-get-spec'.
-+++
-**** The spec operator ':name NAME' is obsolete, use '&name' instead.
-+++
-**** The spec element 'function-form' is obsolete, use 'form' instead.
+*** Change to default value of 'message-draft-headers' user option.
+The 'Date' symbol has been removed from the default value, meaning that
+draft or delayed messages will get a date reflecting when the message
+was sent.  To restore the original behavior of dating a message
+from when it is first saved or delayed, add the symbol 'Date' back to
+this user option.
 
 +++
-*** New function 'def-edebug-elem-spec' to define Edebug spec elements.
-These used to be defined with 'def-edebug-spec' thus conflating the
-two name spaces, which lead to name collisions.
-The use of 'def-edebug-spec' to define Edebug spec elements is
-declared obsolete.
+*** New command to take screenshots.
+In Message mode buffers, the 'C-c C-p' ('message-insert-screenshot')
+command has been added.  It depends on using an external program to
+take the actual screenshot, and defaults to "ImageMagick import".
 
-*** Edebug specification lists can use some new keywords:
+** Smtpmail
 
 +++
-**** '&interpose SPEC FUN ARGS..' lets FUN control parsing after SPEC.
-More specifically, FUN is called with 'HEAD PF ARGS..' where
-PF is a parsing function that expects a single argument (the specs to
-use) and HEAD is the code that matched SPEC.
+*** smtpmail now supports using the oauth2.el library.
 
 +++
-**** '&error MSG' unconditionally aborts the current edebug instrumentation.
+*** New user option 'smtpmail-store-queue-variables'.
+If non-nil, SMTP variables will be stored together with the queued
+messages, and will then be used when sending with
+'M-x smtpmail-send-queued-mail'.
 
 +++
-**** '&name SPEC FUN' extracts the current name from the code matching SPEC.
+*** Allow direct selection of smtp authentication mechanism.
+A server entry retrieved by auth-source can request a desired smtp
+authentication mechanism by setting a value for the key 'smtp-auth'.
+
+---
+** Lisp mode now uses 'common-lisp-indent-function'.
+To revert to the previous behavior,
+'(setq lisp-indent-function 'lisp-indent-function)' from 'lisp-mode-hook'.
 
 ** ElDoc
 
@@ -1524,55 +1899,17 @@ by the ElDoc library itself.  Functions in
 'eldoc-documentation-functions' don't need to worry about consulting
 it when producing a doc string.
 
-** Shell
-
----
-*** New command in 'shell-mode': 'narrow-to-prompt'.
-This is bound to 'C-x n d' in 'shell-mode' buffers, and narrows to the
-command line under point (and any following output).
-
----
-*** New user option 'shell-has-auto-cd'.
-If non-nil, 'shell-mode' handles implicit "cd" commands, changing the
-directory if the command is a directory.  Useful for shells like "zsh"
-that has this feature.
-
-+++
-*** 'comint-delete-output' can now save deleted text in the kill-ring.
-Interactively, 'C-u C-c C-o' triggers this new optional behavior.
-
-** Eshell
-
----
-*** 'eshell-hist-ignoredups' can now also be used to mimic "erasedups" in bash.
-
----
-*** Environment variable 'INSIDE_EMACS' is now copied to subprocesses.
-Its value contains the result of evaluating '(format "%s,eshell"
-emacs-version)'.  Other package names, like "tramp", could also be included.
-
----
-*** Eshell no longer re-initializes its keymap every call.
-This allows users to use (define-key eshell-mode-map ...) as usual.
-Some modules have their own minor mode now to account for these
-changes.
-
-** EUDC
-
-+++
-*** New macOS Contacts backend.
-This backend works on newer versions of macOS and is generally
-preferred over the eudcb-mab.el backend.
-
 ** Tramp
 
 +++
-*** New connection method "mtp", which allows accessing media devices
-like cell phones, tablets or cameras.
+*** New connection method "mtp".
+It allows accessing media devices like cell phones, tablets or
+cameras.
 
 +++
-*** New connection method "sshfs", which allows accessing remote files
-via a file system mounted with 'sshfs'.
+*** New connection method "sshfs".
+It allows accessing remote files via a file system mounted with
+'sshfs'.
 
 +++
 *** Tramp supports SSH authentication via a hardware security key now.
@@ -1582,7 +1919,7 @@ security key, like yubikey, solokey, or nitrokey.
 +++
 *** Trashed remote files are moved to the local trash directory.
 All remote files, which are trashed, are moved to the local trash
-directory.  Except remote encrypted files, which are always deleted.
+directory, except remote encrypted files, which are always deleted.
 
 +++
 *** New command 'tramp-crypt-add-directory'.
@@ -1612,10 +1949,10 @@ In order to deactivate this, set user option
 'remote-file-name-inhibit-locks' to t.
 
 +++
-*** Writing sensitive auto-save, backup or lock files to the local
-temporary directory must be confirmed.  In order to suppress this
-confirmation, set user option 'tramp-allow-unsafe-temporary-files' to
-t.
+*** Writing sensitive data locally requires confirmation.
+Writing auto-save, backup or lock files to the local temporary
+directory must be confirmed.  In order to suppress this confirmation,
+set user option 'tramp-allow-unsafe-temporary-files' to t.
 
 ** Tempo
 
@@ -1624,71 +1961,6 @@ t.
 Previously, assigning a new template to an already defined tag had no
 effect.
 
-** map.el
-
-*** Pcase 'map' pattern added keyword symbols abbreviation.
-A pattern like '(map :sym)' binds the map's value for ':sym' to 'sym',
-equivalent to '(map (:sym sym))'.
-
----
-*** The function 'map-copy' now uses 'copy-alist' on alists.
-This is a slightly deeper copy than the previous 'copy-sequence'.
-
----
-*** The function 'map-contains-key' now supports plists.
-
----
-*** More consistent duplicate key handling in 'map-merge-with'.
-Until now, 'map-merge-with' promised to call its function argument
-whenever multiple maps contained 'eql' keys.  However, this did not
-always coincide with the keys that were actually merged, which could
-be 'equal' instead.  The function argument is now called whenever keys
-are merged, for greater consistency with 'map-merge' and 'map-elt'.
-
-** Package
-
----
-*** '/ s' ('package-menu-filter-by-status') changes parameter handling.
-The command was documented to take a comma-separated list of statuses
-to filter by, but instead it used the parameter as a regexp.  The
-command has been changed so that it now works as documented, and
-checks statuses not as a regexp, but instead an exact match from the
-comma-separated list.
-
-+++
-*** New command 'package-browse-url' and keystroke 'w'.
-
-+++
-*** New commands to filter the package list.
-The filter commands are bound to the following keys:
-
-key             binding
----             -------
-/ a             package-menu-filter-by-archive
-/ d             package-menu-filter-by-description
-/ k             package-menu-filter-by-keyword
-/ N             package-menu-filter-by-name-or-description
-/ n             package-menu-filter-by-name
-/ s             package-menu-filter-by-status
-/ v             package-menu-filter-by-version
-/ m             package-menu-filter-marked
-/ u             package-menu-filter-upgradable
-/ /             package-menu-filter-clear
-
-*** Option to automatically native-compile packages upon installation.
-Customize the user option 'package-native-compile' to enable automatic
-native compilation of packages when they are installed.  That option
-is nil by default; if set non-nil, and if your Emacs was built with
-native-compilation support, each package will be natively compiled
-when it is installed, by invoking an asynchronous Emacs subprocess to
-run the native-compilation of the package files.
-
----
-*** Column widths in 'list-packages' display can now be customized.
-See the new user options 'package-name-column-width',
-'package-version-column-width', 'package-status-column-width', and
-'package-archive-column-width'.
-
 ** gdb-mi
 
 *** New user option 'gdb-registers-enable-filter'.
@@ -1696,7 +1968,7 @@ If non-nil, apply a register filter based on
 'gdb-registers-filter-pattern-list'.
 
 +++
-*** gdb-mi can now store and restore window configurations.
+*** gdb-mi can now save and restore window configurations.
 Use 'gdb-save-window-configuration' to save window configuration to a
 file and 'gdb-load-window-configuration' to load from a file.  These
 commands can also be accessed through the menu bar under "Gud =>
@@ -1704,11 +1976,11 @@ GDB-Windows".  'gdb-default-window-configuration-file', 
when non-nil,
 is loaded when GDB starts up.
 
 +++
-*** gdb-mi can now restore window configuration after quit.
+*** gdb-mi can now restore window configuration after quitting.
 Set 'gdb-restore-window-configuration-after-quit' to non-nil and Emacs
 will remember the window configuration before GDB started and restore
 it after GDB quits.  A toggle button is also provided under "Gud =>
-GDB-Windows".
+GDB-Windows" menu item.
 
 +++
 *** gdb-mi now has a better logic for displaying source buffers.
@@ -1721,12 +1993,6 @@ Control source file display by 
'gdb-display-source-buffer-action'.
 This means that the default coding-system is now used to decode strings
 and source file names from GDB.
 
-** Gravatar
-
----
-*** New user option 'gravatar-service' for host to query for gravatars.
-Defaults to 'libravatar', with 'unicornify' and 'gravatar' as options.
-
 ** Compilation mode
 
 ---
@@ -1760,10 +2026,11 @@ be done (and this restores how this previously worked).
 ** Hi Lock mode
 
 ---
-*** Matching in 'hi-lock-mode' is case-sensitive when regexp contains
-upper case characters and 'search-upper-case' is non-nil.
-'highlight-phrase' also uses 'search-whitespace-regexp'
-to substitute spaces in regexp search.
+*** Matching in 'hi-lock-mode' can be case-sensitive.
+The matching is case-sensitive when a regexp contains upper case
+characters and 'search-upper-case' is non-nil.  'highlight-phrase'
+also uses 'search-whitespace-regexp' to substitute spaces in regexp
+search.
 
 ---
 *** The default value of 'hi-lock-highlight-range' was enlarged.
@@ -1814,53 +2081,7 @@ t, which preserves the original behavior.
 ---
 *** New user option 'rmail-show-message-set-modified'.
 If set non-nil, showing an unseen message will set the Rmail buffer's
-modified flag.
-
----
-*** New faces for heading elements.
-Those are 'shr-h1', 'shr-h2', 'shr-h3', 'shr-h4', 'shr-h5', 'shr-h6'.
-
-** MH-E mail handler for Emacs
-
-Functions and variables related to handling junk mail have been
-renamed to not associate color with sender quality.
-
-+++
-*** New names for mh-junk interactive functions.
-Function 'mh-junk-whitelist' is renamed 'mh-junk-allowlist'.
-Function 'mh-junk-blacklist' is renamed 'mh-junk-blocklist'.
-
-+++
-*** New binding for 'mh-junk-allowlist'.
-The key binding for 'mh-junk-allowlist' is changed from 'J w' to 'J a'.
-The old binding is supported but warns that it is obsolete.
-
-+++
-*** New names for some hooks.
-'mh-whitelist-msg-hook' is renamed 'mh-allowlist-msg-hook'.
-'mh-blacklist-msg-hook' is renamed 'mh-blocklist-msg-hook'.
-
-+++
-*** New names for some variables.
-Variable 'mh-whitelist-preserves-sequences-flag' is renamed
-'mh-allowlist-preserves-sequences-flag'.
-
-+++
-*** New names for some faces.
-Face 'mh-folder-blacklisted' is renamed 'mh-folder-blocklisted'.
-Face 'mh-folder-whitelisted' is renamed 'mh-folder-allowlisted'.
-
-** Apropos
-
-*** New commands 'apropos-next-symbol' and 'apropos-previous-symbol'.
-These new navigation commands are bound to 'n' and 'p' in
-'apropos-mode'.
-
-*** New command 'apropos-function'.
-This works like 'C-u M-x apropos-command' but is more discoverable.
-
-*** New face 'apropos-button'.
-Applies to buttons that indicate a face.
+modified flag.  The default is nil, to preserve the old behavior.
 
 ** CC Mode
 
@@ -1886,48 +2107,14 @@ operator ('?:').  For example:
     return arg % 2 == 0 ? arg / 2
                         : (3 * arg + 1);
 
-To enable, add it to appropriate entries in 'c-offsets-alist', e.g.:
-
-    (c-set-offset 'arglist-cont '(c-lineup-ternary-bodies
-                                  c-lineup-gcc-asm-reg))
-    (c-set-offset 'arglist-cont-nonempty '(c-lineup-ternary-bodies
-                                           c-lineup-gcc-asm-reg
-                                           c-lineup-arglist))
-    (c-set-offset 'statement-cont '(c-lineup-ternary-bodies +))
-
-** browse-url
-
-*** Added support for custom URL handlers.
-There is a new variable 'browse-url-default-handlers' and a user
-option 'browse-url-handlers' being alists with '(REGEXP-OR-PREDICATE
-. FUNCTION)' entries allowing to define different browsing FUNCTIONs
-depending on the URL to be browsed.  The variable is for default
-handlers provided by Emacs itself or external packages, the user
-option is for the user (and allows for overriding the default
-handlers).
-
-Formerly, one could do the same by setting
-'browse-url-browser-function' to such an alist.  This usage is still
-supported but deprecated.
-
-*** Categorization of browsing commands in internal vs. external.
-All standard browsing commands such as 'browse-url-firefox',
-'browse-url-mail', or 'eww' have been categorized into internal (URL
-is browsed in Emacs) or external (an external application is spawned
-with the URL).  This is done by adding a 'browse-url-browser-kind'
-symbol property to the browsing commands.  With a new command
-'browse-url-with-browser-kind', an URL can explicitly be browsed with
-either an internal or external browser.
-
----
-*** Support for browsing of remote files.
-If a remote file is taken, a local temporary copy of that file is
-passed to the browser.
-
-*** Support for the conkeror browser is now obsolete.
+To enable, add it to appropriate entries in 'c-offsets-alist', e.g.:
 
-*** Support for the Mosaic browser has been removed.
-This support has been obsolete since 25.1.
+    (c-set-offset 'arglist-cont '(c-lineup-ternary-bodies
+                                  c-lineup-gcc-asm-reg))
+    (c-set-offset 'arglist-cont-nonempty '(c-lineup-ternary-bodies
+                                           c-lineup-gcc-asm-reg
+                                           c-lineup-arglist))
+    (c-set-offset 'statement-cont '(c-lineup-ternary-bodies +))
 
 ** SHR
 
@@ -1949,6 +2136,10 @@ to a more readable text.  Set this user option to nil to 
get the
 previous behavior of rendering as wide as the 'window-width' allows.
 If 'shr-width' is non-nil, it overrides this variable.
 
+---
+*** New faces for heading elements.
+Those are 'shr-h1', 'shr-h2', 'shr-h3', 'shr-h4', 'shr-h5', 'shr-h6'.
+
 ** Images
 
 ---
@@ -2072,7 +2263,7 @@ information, see the related entry about 'shr-browse-url' 
above.
 *** New user option 'project-vc-merge-submodules'.
 
 *** Project commands now have their own history.
-Previously used project directories are now suggested by all commands
+Previously, used project directories are now suggested by all commands
 that prompt for a project directory.
 
 +++
@@ -2102,6 +2293,7 @@ project's root directory, respectively.
 
 +++
 *** New user option 'project-list-file'.
+This specifies the file in which to save the list of known projects.
 
 +++
 *** New command 'project-remove-known-project'.
@@ -2115,13 +2307,24 @@ sub-directory.
 *** 'project-find-file' doesn't use the string at point as default input.
 Now it's only suggested as part of the "future history".
 
-** xref
+** Xref
 
 ---
 *** Prefix arg of 'xref-goto-xref' quits the "*xref*" buffer.
 So typing 'C-u RET' in the "*xref*" buffer quits its window
 before navigating to the selected location.
 
++++
+*** New user options to automatically show the first Xref match.
+The new user option 'xref-auto-jump-to-first-definition' controls the
+behavior of 'xref-find-definitions' and related commands: if it's t or
+'show', the first match is automatically displayed; if it's 'move',
+point in the "*xref*" buffer is automatically moved to the first match
+without displaying it.
+The new user option 'xref-auto-jump-to-first-xref' changes the behavior of
+all Xref commands in the same way as 'xref-auto-jump-to-first-definition'
+affects the "find-definitions" commands.
+
 *** New user options 'xref-search-program' and 'xref-search-program-alist'.
 So far 'grep' and 'ripgrep' are supported.  'ripgrep' seems to offer better
 performance in certain cases, in particular for case-insensitive
@@ -2157,97 +2360,10 @@ supported, but we plan on removing it in a future 
version; at that
 time, the command 'xref-quit-and-goto-xref' will no longer have a key
 binding in 'xref--xref-buffer-mode-map'.
 
-** json.el
-
----
-*** JSON number parsing is now stricter.
-Numbers with a leading plus sign, leading zeros, or a missing integer
-component are now rejected by 'json-read' and friends.  This makes
-them more compliant with the JSON specification and consistent with
-the native JSON parsing functions.
-
----
-*** Some JSON encoding functions are now obsolete.
-The functions 'json-encode-number', 'json-encode-hash-table',
-'json-encode-key', and 'json-encode-list' are now obsolete.
-
-The first two are kept as aliases of 'json-encode', which should be
-used instead.  Uses of 'json-encode-list' should be changed to call
-one of 'json-encode', 'json-encode-alist', 'json-encode-plist', or
-'json-encode-array' instead.
-
-** json.c
-
-+++
-*** New function 'json-available-p'.
-This predicate returns non-nil if Emacs is built with libjansson
-support, and it is available on the current system.
-
-+++
-*** Native JSON functions now signal an error if libjansson is unavailable.
-This affects 'json-serialize', 'json-insert', 'json-parse-string',
-and 'json-parse-buffer'.  This can happen if Emacs was compiled with
-libjansson, but the DLL cannot be found and/or loaded by Emacs at run
-time.  Previously, Emacs would display a message and return nil in
-these cases.
-
-*** The JSON functions 'json-serialize', 'json-insert',
-'json-parse-string', and 'json-parse-buffer' now implement some of the
-semantics of RFC 8259 instead of the earlier RFC 4627.  In particular,
-these functions now accept top-level JSON values that are neither
-arrays nor objects.
-
-** xml.el
-
-*** XML serialization functions now reject invalid characters.
-Previously 'xml-print' would produce invalid XML when given a string
-with characters that are not valid in XML (see
-https://www.w3.org/TR/xml/#charsets).  Now it rejects such strings.
-
-** erc
-
----
-*** erc-services.el now supports NickServ passwords from auth-source.
-The 'erc-use-auth-source-for-nickserv-password' user option enables
-querying auth-source for NickServ passwords.  To enable this, add the
-following to your init file:
-
-    (setq erc-prompt-for-nickserv-password nil
-          erc-use-auth-source-for-nickserv-password t)
-
----
-*** The '/ignore' command will now ask for a timeout to stop ignoring the user.
-Allowed inputs are seconds or ISO8601-like periods like "1h" or "4h30m".
-
----
-*** ERC now recognizes 'C-]' for italic text.
-Italic text is displayed in the new 'erc-italic-face'.
-
----
-*** The erc-compat.el library is now marked obsolete.
-This file contained ERC compatibility code for Emacs 21 and XEmacs
-which is no longer needed.
-
 ---
-*** erc-match.el now supports 'message' highlight type (not including the 
nick).
-The 'erc-current-nick-highlight-type', 'erc-pal-highlight-type',
-'erc-fool-highlight-type', 'erc-keyword-highlight-type', and
-'erc-dangerous-host-highlight-type' variables now support a 'message'
-type for highlighting the entire message but not the sender's nick.
-
-*** erc-status-sidebar.el is now part of ERC.
-The 'erc-status-sidebar' package which provides a HexChat-like
-activity overview sidebar for joined IRC channels is now part of ERC.
-
-+++
-*** erc-tls now supports specifying a TLS client certificate.
-The 'erc-tls' function has been updated to allow specifying a TLS
-client certificate for authentication, as an alternative to NickServ
-password-based authentication.  This is referred to as "CertFP" (short
-for Certificate Fingerprint) by several IRC networks.  See the Info
-node "(erc) Connecting" in the ERC manual for more details and
-examples on how to specify and use TLS client certificates with
-'erc-tls'.
+*** New user option 'etags-xref-prefer-current-file'.
+When non-nil, matches for identifiers in the file visited by the
+current buffer will be shown first in the "*xref*" buffer.
 
 ** Battery
 
@@ -2272,16 +2388,17 @@ truncation, amongst other things.
 ** bug-reference.el
 
 ---
-*** Bug reference mode auto-setup.  If 'bug-reference-mode' or
-'bug-reference-prog-mode' have been activated, their respective hook
-has been run and still 'bug-reference-bug-regexp' and
-'bug-reference-url-format' aren't both set, it tries to guess
-appropriate values for those two variables.  There are three guessing
-mechanisms so far: based on version control information of the current
-buffer's file, based on newsgroup/mail-folder name and several news
-and mail message headers in Gnus buffers, and based on IRC channel and
-network in rcirc and ERC buffers.  All mechanisms are extensible with
-custom rules, see the variables 'bug-reference-setup-from-vc-alist',
+*** Bug reference mode uses auto-setup.
+If 'bug-reference-mode' or 'bug-reference-prog-mode' have been
+activated, their respective hook has been run and still
+'bug-reference-bug-regexp' and 'bug-reference-url-format' aren't both
+set, it tries to guess appropriate values for those two variables.
+There are three guessing mechanisms so far: based on version control
+information of the current buffer's file, based on
+newsgroup/mail-folder name and several news and mail message headers
+in Gnus buffers, and based on IRC channel and network in rcirc and ERC
+buffers.  All the mechanisms are extensible with custom rules, see the
+variables 'bug-reference-setup-from-vc-alist',
 'bug-reference-setup-from-mail-alist', and
 'bug-reference-setup-from-irc-alist'.
 
@@ -2292,111 +2409,238 @@ custom rules, see the variables 
'bug-reference-setup-from-vc-alist',
 It's bound to the 'C-c C-c f' keystroke, and prompts for a local file
 name.
 
-** Recentf
+** Widget
+
++++
+*** 'widget-choose' now supports menus in extended format.
 
 ---
-*** The recentf files are no longer backed up.
+*** The 'editable-list' widget now supports moving items up and down.
+You can now move items up and down by deleting and then reinserting
+them, using the 'DEL' and 'INS' buttons respectively.  This is useful
+in Custom buffers, for example, to change the order of the elements in
+a list.
+
+** Diff
 
 ---
-*** 'recentf-auto-cleanup' time string now repeats.
-When 'recentf-auto-cleanup' is set to a time string, it now repeats
-every day, rather than only running once after the mode is turned on.
+*** New face 'diff-changed-unspecified'.
+This is used to highlight "changed" lines (those marked with '!') in
+context diffs, when 'diff-use-changed-face' is non-nil.
 
-** Calc
+---
+*** New 'diff-mode' font locking face 'diff-error'.
+This face is used for error messages from 'diff'.
+
++++
+*** New command 'diff-refresh-hunk'.
+This new command (bound to 'C-c C-l') regenerates the current hunk.
+
+** Buttons
+
++++
+*** New minor mode 'button-mode'.
+This minor mode does nothing else than install 'button-buffer-map' as
+a minor mode map (which binds the 'TAB' / 'S-TAB' key bindings to navigate
+to buttons), and can be used in any view-mode-like buffer that has
+buttons in it.
+
++++
+*** New utility function 'button-buttonize'.
+This function takes a string and returns a string propertized in a way
+that makes it a valid button.
+
+** thing-at-point
+
++++
+*** New 'thing-at-point' target: 'existing-filename'.
+This is like 'filename', but is a full path, and is nil if the file
+doesn't exist.
+
++++
+*** New variable 'thing-at-point-provider-alist'.
+This allows mode-specific alterations to how 'thing-at-point' works.
 
 ---
-*** The behavior when doing forward-delete has been changed.
-Previously, using the 'C-d' command would delete the final number in
-the input field, no matter where point was.  This has been changed to
-work more traditionally, with 'C-d' deleting the next character.
-Likewise, point isn't moved to the end of the string before inserting
-digits.
+*** thing-at-point now respects fields.
+'thing-at-point' (and all functions that use it, like
+'symbol-at-point') will narrow to the current field (if any) before
+trying to identify the thing at point.
+
+** image-dired
+
+---
+*** 'image-dired-mouse-toggle-mark' now toggles files in the active region.
 
 +++
-*** Setting the word size to zero disables word clipping.
-The word size normally clips the results of certain bit-oriented
-operations such as shifts and bitwise XOR.  A word size of zero, set
-by 'b w', makes the operation have effect on the whole argument values
-and the result is not truncated in any way.
+*** New user option 'image-dired-thumb-visible-marks'.
+If non-nil (the default), use 'image-dired-thumb-mark' to say what
+images are marked.
 
 ---
-*** The '/' operator now has higher precedence in (La)TeX input mode.
-It no longer has lower precedence than '+' and '-'.
+*** New command 'image-dired-delete-marked'.
+
+** Flymake mode
+
++++
+*** New user options to customize Flymake's mode-line.
+The new user option 'flymake-mode-line-format' is a mix of strings and
+symbols like 'flymake-mode-line-title', 'flymake-mode-line-exception'
+and 'flymake-mode-line-counters'.  The new user option
+'flymake-mode-line-counter-format' is a mix of strings and symbols
+like 'flymake-mode-line-error-counter',
+'flymake-mode-line-warning-counter' and 'flymake-mode-line-note-counter'.
+
+** Time
 
 ---
-*** Calc now marks its windows dedicated.
-The new user option 'calc-make-windows-dedicated' controls this.  It
-is t by default; set to nil to get back the old behavior.
+*** 'display-time-world' has been renamed to 'world-clock'.
+'world-clock' creates a buffer with an updating time display using
+several time zones.  It is hoped that the new names are more
+discoverable.
 
-** term-mode
+The following commands have been renamed:
+
+  'display-time-world'         to 'world-clock'
+  'display-time-world-mode'    to 'world-clock-mode'
+  'display-time-world-display' to 'world-clock-display'
+  'display-time-world-timer'   to 'world-clock-update'
+
+The following user options have been renamed:
+
+  'display-time-world-list'         to 'world-clock-list'
+  'display-time-world-time-format'  to 'world-clock-time-format'
+  'display-time-world-buffer-name'  to 'world-clock-buffer-name'
+  'display-time-world-timer-enable' to 'world-clock-timer-enable'
+  'display-time-world-timer-second' to 'world-clock-timer-second'
+
+The old names are now obsolete.
 
 ---
-*** New user option 'term-scroll-snap-to-bottom'.
-By default, 'term' and 'ansi-term' will now recenter the buffer so
-that the prompt is on the final line in the window.  Setting this new
-user option to nil inhibits this behavior.
+*** 'world-clock-mode' can no longer be turned on interactively.
+Use 'world-clock' to turn on that mode.
+
+** CPerl Mode
 
 ---
-*** New user option 'term-set-terminal-size'
-If non-nil, the 'LINES' and 'COLUMNS' environment variables will be set
-based on the current window size.  In previous versions of Emacs, this
-was always done (and that could lead to odd displays when resizing the
-window after starting).  This variable defaults to nil.
+*** New face 'perl-heredoc', used for heredoc elements.
+
+---
+*** The command 'cperl-set-style' offers the new value "PBP".
+This value customizes Emacs to use the style recommended in Damian
+Conway's book "Perl Best Practices" for indentation and formatting
+of conditionals.
+
+** Octave Mode
+
++++
+*** Line continuations in double-quoted strings now use a backslash.
+Typing 'C-M-j' (bound to 'octave-indent-new-comment-line') now follows
+the behavior introduced in Octave 3.8 of using a backslash as a line
+continuation marker within double-quoted strings, and an ellipsis
+everywhere else.
+
++++
+** EasyPG
+GPG key servers can now be queried for keys with the
+'M-x epa-search-keys' command.  Keys can then be added to your
+personal key ring.
+
+** Etags
+
++++
+*** Etags now supports the Mercury programming language.
+See https://mercurylang.org.
+
++++
+*** Etags command line option '--declarations' now has Mercury-specific 
behavior.
+All Mercury declarations are tagged by default.  However, for
+compatibility with 'etags' support for Prolog, predicates and
+functions appearing first in clauses will also be tagged if 'etags' is
+invoked with the '--declarations' command-line option.
+
+** Comint
 
-** Widget
++++
+*** Support for OSC escape sequences.
+Adding the new 'comint-osc-process-output' to
+'comint-output-filter-functions' enables the interpretation of OSC
+("Operating System Command") escape sequences in comint buffers.  By
+default, only OSC 8, for hyperlinks, and OSC 7, for directory
+tracking, are acted upon.  Adding more entries to
+'comint-osc-handlers' allows a customized treatment of further escape
+sequences.
 
 +++
-*** 'widget-choose' now supports menus in extended format.
+*** 'comint-delete-output' can now save deleted text in the kill-ring.
+Interactively, 'C-u C-c C-o' triggers this new optional behavior.
+
+** erc
 
 ---
-*** The 'editable-list' widget now supports moving items up and down.
-You can now move items up and down by deleting and then reinserting
-them, using the 'DEL' and 'INS' buttons respectively.  This is useful
-in Custom buffers, for example, to change the order of the elements in
-a list.
+*** erc-services.el now supports NickServ passwords from auth-source.
+The 'erc-use-auth-source-for-nickserv-password' user option enables
+querying auth-source for NickServ passwords.  To enable this, add the
+following to your init file:
 
-** Diff
+    (setq erc-prompt-for-nickserv-password nil
+          erc-use-auth-source-for-nickserv-password t)
 
 ---
-*** New face 'diff-changed-unspecified'.
-This is used to highlight "changed" lines (those marked with '!') in
-context diffs, when 'diff-use-changed-face' is non-nil.
+*** The '/ignore' command will now ask for a timeout to stop ignoring the user.
+Allowed inputs are seconds or ISO8601-like periods like "1h" or "4h30m".
 
 ---
-*** New 'diff-mode' font locking face 'diff-error'.
-This face is used for error messages from 'diff'.
+*** ERC now recognizes 'C-]' for italic text.
+Italic text is displayed in the new 'erc-italic-face'.
 
-+++
-*** New command 'diff-refresh-hunk'.
-This new command (bound to 'C-c C-l') regenerates the current hunk.
+---
+*** The erc-compat.el library is now marked obsolete.
+This file contained ERC compatibility code for Emacs 21 and XEmacs
+which is no longer needed.
 
-** Buttons
+---
+*** erc-match.el now supports 'message' highlight type (not including the 
nick).
+The 'erc-current-nick-highlight-type', 'erc-pal-highlight-type',
+'erc-fool-highlight-type', 'erc-keyword-highlight-type', and
+'erc-dangerous-host-highlight-type' variables now support a 'message'
+type for highlighting the entire message but not the sender's nick.
 
-+++
-*** New minor mode 'button-mode'.
-This minor mode does nothing else than install 'button-buffer-map' as
-a minor mode map (which binds the 'TAB' / 'S-TAB' key bindings to navigate
-to buttons), and can be used in any view-mode-like buffer that has
-buttons in it.
+*** erc-status-sidebar.el is now part of ERC.
+The 'erc-status-sidebar' package which provides a HexChat-like
+activity overview sidebar for joined IRC channels is now part of ERC.
 
 +++
-*** New utility function 'button-buttonize'.
-This function takes a string and returns a string propertized in a way
-that makes it a valid button.
+*** erc-tls now supports specifying a TLS client certificate.
+The 'erc-tls' function has been updated to allow specifying a TLS
+client certificate for authentication, as an alternative to NickServ
+password-based authentication.  This is referred to as "CertFP" (short
+for Certificate Fingerprint) by several IRC networks.  See the Info
+node "(erc) Connecting" in the ERC manual for more details and
+examples on how to specify and use TLS client certificates with
+'erc-tls'.
 
-** subr-x
-+++
-*** A number of new string manipulation functions have been added.
-'string-clean-whitespace', 'string-fill', 'string-limit',
-'string-lines', 'string-pad' and 'string-chop-newline'.
+** xwidget-webkit mode
 
-*** New macro 'named-let' that provides Scheme's "named let" looping construct.
+*** New xwidget commands.
+'xwidget-webkit-uri' (return the current URL), 'xwidget-webkit-title'
+(return the current title), and 'xwidget-webkit-goto-history' (goto a
+point in history).
 
-** thingatpt
+*** Pixel-based scrolling.
+The 'xwidget-webkit-scroll-up', 'xwidget-webkit-scroll-down' commands
+now supports scrolling arbitrary pixel values.  It now treats the
+optional 2nd argument as the pixel values to scroll.
 
-+++
-*** New variable 'thing-at-point-provider-alist'.
-This allows mode-specific alterations to how 'thing-at-point' works.
+*** New commands for scrolling.
+The new commands 'xwidget-webkit-scroll-up-line',
+'xwidget-webkit-scroll-down-line', 'xwidget-webkit-scroll-forward',
+'xwidget-webkit-scroll-backward' can be used to scroll webkit by the
+height of lines or width of chars.
+
+*** New user option 'xwidget-webkit-bookmark-jump-new-session'.
+When non-nil, use a new xwidget webkit session after bookmark jump.
+Otherwise, it will use 'xwidget-webkit-last-session'.
 
 ** Enriched mode
 
@@ -2405,947 +2649,1017 @@ This allows mode-specific alterations to how 
'thing-at-point' works.
 This is so 'C-a' works as in other modes, and in particular holding
 Shift while typing 'C-a', i.e. 'C-S-a', will now highlight the text.
 
-** ERT
+** Gravatar
+
+---
+*** New user option 'gravatar-service' for host to query for gravatars.
+Defaults to 'libravatar', with 'unicornify' and 'gravatar' as options.
+
+** MH-E mail handler for Emacs
+
+Functions and variables related to handling junk mail have been
+renamed to not associate color with sender quality.
 
 +++
-*** ERT can now output more verbose test failure reports.
-If the 'EMACS_TEST_VERBOSE' environment variable is set, failure
-summaries will include the failing condition.
+*** New names for mh-junk interactive functions.
+Function 'mh-junk-whitelist' is renamed 'mh-junk-allowlist'.
+Function 'mh-junk-blacklist' is renamed 'mh-junk-blocklist'.
 
-** File Locks
++++
+*** New binding for 'mh-junk-allowlist'.
+The key binding for 'mh-junk-allowlist' is changed from 'J w' to 'J a'.
+The old binding is supported but warns that it is obsolete.
 
 +++
-*** New user option 'lock-file-name-transforms'.
-This option allows controlling where lock files are written.  It uses
-the same syntax as 'auto-save-file-name-transforms'.
+*** New names for some hooks.
+'mh-whitelist-msg-hook' is renamed 'mh-allowlist-msg-hook'.
+'mh-blacklist-msg-hook' is renamed 'mh-blocklist-msg-hook'.
 
 +++
-*** New user option 'remote-file-name-inhibit-locks'.
-When non-nil, this option suppresses lock files for remote files.
+*** New names for some variables.
+Variable 'mh-whitelist-preserves-sequences-flag' is renamed
+'mh-allowlist-preserves-sequences-flag'.
 
 +++
-*** New minor mode 'lock-file-mode'.
-This command, called interactively, toggles the local value of
-'create-lockfiles' in the current buffer.
+*** New names for some faces.
+Face 'mh-folder-blacklisted' is renamed 'mh-folder-blocklisted'.
+Face 'mh-folder-whitelisted' is renamed 'mh-folder-allowlisted'.
 
-** image-dired
+** Miscellaneous
 
 ---
-*** 'image-dired-mouse-toggle-mark' now toggles files in the active region.
-
-+++
-*** New user option 'image-dired-thumb-visible-marks'.
-If non-nil (the default), use 'image-dired-thumb-mark' to say what
-images are marked.
+*** 'shell-script-mode' now supports 'outline-minor-mode'.
+The outline headings have lines that start with "###".
 
-*** New command 'image-dired-tag-marked-thumbnails'.
+---
+*** fileloop will now skip missing files instead of signalling an error.
 
-*** New command 'image-dired-delete-marked'.
+---
+*** 'tabulated-list-mode' can now restore original display order.
+Many commands (like 'C-x C-b') are derived from 'tabulated-list-mode',
+and that mode allows the user to sort on any column.  There was
+previously no easy way to get back to the original displayed order
+after sorting, but giving a -1 numerical prefix to the sorting command
+will now restore the original order.
 
-** Miscellaneous
+---
+*** 'M-left' and 'M-right' now move between columns in 'tabulated-list-mode'.
 
 +++
-*** New function 'replace-regexp-in-region'.
+*** rcirc now supports SASL authentication.
+
+---
+*** New variable 'hl-line-overlay-priority'.
+This can be used to change the priority of the hl-line overlays.
 
 +++
-*** New function 'replace-string-in-region'.
+*** New command 'mailcap-view-file'.
+This command will open a viewer based on the file type, as determined
+by "~/.mailcap" and related files and variables.
 
 ---
-*** New function 'mail-header-parse-addresses-lax'.
-This takes a comma-separated string and returns a list of mail/name
-pairs.
+*** New user option 'remember-diary-regexp'.
 
 ---
-*** New function 'mail-header-parse-address-lax'.
-Parse a string as a mail address-like string.
+*** New user option 'remember-text-format-function'.
 
 ---
-*** 'shell-script-mode' now supports 'outline-minor-mode'.
-The outline headings have lines that start with "###".
+*** New user option 'authinfo-hide-elements'.
+This can be set to nil to inhibit hiding passwords in ".authinfo" files.
 
-+++
-*** New command 'revert-buffer-quick'.
-This is bound to 'C-x x g' and is like `revert-buffer', but prompts
-less.
+---
+*** 'hexl-mode' scrolling commands now heed 'next-screen-context-lines'.
+Previously, 'hexl-scroll-down' and 'hexl-scroll-up' would scroll
+up/down an entire window, but they now work more like the standard
+scrolling commands.
 
-+++
-*** New user option 'revert-buffer-quick-short-answers'.  This
-controls how the new 'revert-buffer-quick' (`C-x x g') command
-prompts.
+---
+*** New user option 'bibtex-unify-case-function'.
+This new option allows the user to customize how case is converted
+when unifying entries.
 
 ---
-*** fileloop will now skip missing files instead of signalling an error.
+*** The user option 'bibtex-maintain-sorted-entries' now permits
+user-defined sorting schemes.
 
-+++
-*** ".dir-locals.el" now supports setting 'auto-mode-alist'.
-The new 'auto-mode-alist' specification in ".dir-locals.el" files can
-now be used to override the global 'auto-mode-alist' in the current
-directory tree.
+---
+*** New user option 'reveal-auto-hide'.
+If non-nil (the default), revealed text is automatically hidden when
+point leaves the text.  If nil, the text is not hidden again.  Instead
+'M-x reveal-hide-revealed' can be used to hide all the revealed text.
 
 ---
-*** New utility function 'make-separator-line'.
+*** New variable 'ffap-file-name-with-spaces'.
+If non-nil, 'find-file-at-point' and friends will try to guess more
+expansively to identify a file name with spaces.
 
 ---
-*** New face 'separator-line'.
-This is used by 'make-separator-line'.
+*** Two new commands for centering in 'doc-view-mode'.
+The new commands 'doc-view-center-page-horizontally' (bound to 'c h')
+and 'doc-view-center-page-vertically' (bound to 'c v') center the page
+horizontally and vertically, respectively.
+
+---
+*** The width of the buffer-name column in 'list-buffers' is now dynamic.
+The width now depends of the width of the window, but will never be
+wider than the length of the longest buffer name, except that it will
+never be narrower than 19 characters.
 
 +++
-*** New user option 'ignored-local-variable-values'.
-This is the opposite of 'safe-local-variable-values' -- it's an alist
-of variable-value pairs that are to be ignored when reading a
-local-variables section of a file.
+*** New diary sexp 'diary-offset'.
+It offsets another diary sexp by a number of days.  This is useful
+when for example your organization has a committee meeting two days
+after every monthly meeting which takes place on the third Thursday,
+or if you would like to attend a virtual meeting scheduled in a
+different timezone causing a difference in the date.
+
+---
+*** The old non-SMIE indentation of 'sh-mode' has been removed.
+
+*** Loading dunnet.el in batch mode doesn't start the game any more.
+Instead you need to do "emacs -f dun-batch" to start the game in
+batch mode.
+
+
+* New Modes and Packages in Emacs 28.1
+
++++
+** New transient mode 'repeat-mode' to allow shorter key sequences.
+You can type 'C-x u u' instead of 'C-x u C-x u' to undo many changes,
+'C-x o o' instead of 'C-x o C-x o' to switch several windows,
+'C-x { { } } ^ ^ v v' to resize the selected window interactively,
+'M-g n n p p' to navigate next-error matches.  Any other key exits
+transient mode and then is executed normally.  'repeat-exit-key'
+defines an additional key to exit mode like 'isearch-exit' ('RET').
+The user option 'repeat-exit-timeout' specifies the number of
+seconds of idle time to break the repetition chain automatically.
+With 'repeat-keep-prefix' you can keep the prefix arg of the previous
+command.  For example, this can help to reverse the window navigation
+direction with e.g. 'C-x o M-- o o'.  Also it can help to set a new
+step with e.g. 'C-x { C-5 { { {', which will set the window resizing
+step to 5 columns.
+
+** New themes 'modus-vivendi' and 'modus-operandi'.
+These themes are designed to conform with the highest standard for
+color-contrast accessibility (WCAG AAA).  You can load either of them
+using 'M-x customize-themes' or 'load-theme' from your init file.
+Consult the Modus Themes Info manual for more information on the user
+options they provide.
+
+** Dictionary mode
+This is a mode for searching a RFC 2229 dictionary server.
+'dictionary' opens a buffer for starting operations.
+'dictionary-search' performs a lookup for a word.  It also supports a
+'dictionary-tooltip-mode' which performs a lookup of the word under
+the mouse in 'dictionary-tooltip-dictionary' (which must be customized
+first).
+
+** Lisp Data mode
+The new command 'lisp-data-mode' enables a major mode for buffers
+composed of Lisp symbolic expressions that do not form a computer
+program.  The ".dir-locals.el" file is automatically set to use this
+mode, as are other data files produced by Emacs.
+
++++
+** New global mode 'global-goto-address-mode'.
+This will enable 'goto-address-mode' in all buffers.
+
+** transient.el
+This library implements support for powerful keyboard-driven menus.
+Such menus can be used as simple visual command dispatchers.  More
+complex menus take advantage of infix arguments, which are somewhat
+similar to prefix arguments, but are more flexible and discoverable.
 
----
-*** 'indent-tabs-mode' is now a global minor mode instead of just a variable.
+** hierarchy.el
+It's a library to create, query, navigate and display hierarchical
+structures.
 
----
-*** New user option 'save-place-abbreviate-file-names'.
+
+* Incompatible Editing Changes in Emacs 28.1
 
 ---
-*** 'tabulated-list-mode' can now restore original display order.
-Many commands (like 'C-x C-b') are derived from 'tabulated-list-mode',
-and that mode allows the user to sort on any column.  There was
-previously no easy way to get back to the original displayed order
-after sorting, but giving a -1 numerical prefix to the sorting command
-will now restore the original order.
+** 'toggle-truncate-lines' now disables 'visual-line-mode'.
+This is for symmetry with 'visual-line-mode', which disables
+'truncate-lines'.
 
----
-*** 'M-left' and 'M-right' now move between columns in 'tabulated-list-mode'.
+** 'electric-indent-mode' now also indents inside strings and comments,
+(unless the indentation function doesn't, of course).
+To recover the previous behavior you can use:
 
-+++
-*** New utility function 'insert-into-buffer'.
-This is like 'insert-buffer-substring', but works in the opposite
-direction.
+    (add-hook 'electric-indent-functions
+              (lambda (_) (if (nth 8 (syntax-ppss)) 'no-indent)))
 
-+++
-*** New user option 'kill-transform-function'.
-This can be used to transform (and suppress) strings from entering the
-kill ring.
+** The 'M-o' ('facemenu-keymap') global binding has been removed.
+To restore the old binding, say something like:
 
----
-*** 'C-u M-x dig' will now prompt for a query type to use.
+    (require 'facemenu)
+    (define-key global-map "\M-o" 'facemenu-keymap)
+    (define-key facemenu-keymap "\es" 'center-line)
+    (define-key facemenu-keymap "\eS" 'center-paragraph)
 
-+++
-*** rcirc now supports SASL authentication.
+The last two lines are not strictly necessary if you don't care about
+having those two commands on the 'M-o' keymap; see the next section.
 
-+++
-*** 'save-interprogram-paste-before-kill' can now be a number.
-In that case, it's interpreted as a limit on the size of the clipboard
-data that will be saved to the 'kill-ring' prior to killing text: if
-the size of the clipboard data is greater than or equal to the limit,
-it will not be saved.
+** The 'M-o M-s' and 'M-o M-S' global bindings have been removed.
+Use 'M-x center-line' and 'M-x center-paragraph' instead.  See the
+previous section for how to get back the old bindings.  Alternatively,
+if you only want these two commands to have global bindings they had
+before, you can add the following to your init file:
 
----
-*** New variable 'hl-line-overlay-priority'.
-This can be used to change the priority of the hl-line overlays.
+  (define-key global-map "\M-o\M-s" 'center-line)
+  (define-key global-map "\M-o\M-S" 'center-paragraph)
 
-+++
-*** New command 'mailcap-view-file'.
-This command will open a viewer based on the file type, as determined
-by "~/.mailcap" and related files and variables.
+** The 'M-o M-o' global binding has been removed.
+Use 'M-x font-lock-fontify-block' instead, or the new 'C-x x f'
+command, which updates the syntax highlighting in the current buffer.
 
-+++
-*** New command 'C-x C-k Q' to force redisplay in keyboard macros.
+** The escape sequence '\e[29~' in Xterm is now mapped to 'menu'.
+Xterm sends this sequence for both 'F16' and 'Menu' keys
+It used to be mapped to 'print' but we couldn't find a terminal
+that uses this sequence for any kind of 'Print' key.
+This makes the Menu key (see https://en.wikipedia.org/wiki/Menu_key)
+work for 'context-menu-mode' in Xterm.
 
 ---
-*** New user option 'remember-diary-regexp'.
+** New user option 'xterm-store-paste-on-kill-ring'.
+If non-nil (the default), Emacs pushes pasted text onto the kill ring
+(if using an xterm-like terminal that supports bracketed paste).
+Setting this to nil inhibits that.
+
+** 'vc-print-branch-log' shows the change log for BRANCH from its root
+directory instead of the default directory.
 
 ---
-*** New user option 'remember-text-format-function'.
+** 'project-shell' and 'shell' now use 'pop-to-buffer-same-window'.
+This is to keep the same behavior as Eshell.
 
-*** New function 'buffer-line-statistics'.
-This function returns some statistics about the line lengths in a buffer.
+** In 'nroff-mode', 'center-line' is now bound to 'M-o M-s'.
+The original key binding was 'M-s', which interfered with I-search,
+since the latter uses 'M-s' as a prefix key of the search prefix map.
 
-+++
-*** New variable 'inhibit-interaction' to make user prompts signal an error.
-If this is bound to something non-nil, functions like
-'read-from-minibuffer', 'read-char' (and related) will signal an
-'inhibited-interaction' error.
+** In 'f90-mode', the backslash character ('\') no longer escapes.
+For about a decade, the backslash character has no longer had a
+special escape syntax in Fortran F90.  To get the old behavior back,
+say something like:
 
----
-*** 'process-attributes' now works under OpenBSD, too.
+    (modify-syntax-entry ?\\ "\\" f90-mode-syntax-table)
 
-+++
-*** New button face 'flat-button'.
-This is a plain 2D button, but uses the background color instead of
-the foreground color.
+** Setting 'fill-column' to nil is obsolete.
+This undocumented use of 'fill-column' is now obsolete.  To disable
+auto filling, turn off 'auto-fill-mode' instead.
 
----
-*** New face 'shortdoc-heading'.
-Applies to headings of shortdoc sections.
+For instance, you could add something like the following to your init
+file:
 
-+++
-*** New predicate functions 'length<', 'length>' and 'length='.
-Using these functions may be more efficient than using 'length' (if
-the length of a (long) list is being computed just to compare this
-length to a number).
+    (add-hook 'foo-mode-hook (lambda () (auto-fill-mode -1))
 
----
-*** 'remove-hook' is now an interactive command.
+
+* Incompatible Lisp Changes in Emacs 28.1
+
+** Emacs now prints a backtrace when signaling an error in batch mode.
+This makes debugging Emacs Lisp scripts run in batch mode easier.  To
+get back the old behavior, set the new variable
+'backtrace-on-error-noninteractive' to a nil value.
 
 ---
-*** New user option 'authinfo-hide-elements'.
-This can be set to nil to inhibit hiding passwords in ".authinfo" files.
+** Some floating-point numbers are now handled differently by the Lisp reader.
+In previous versions of Emacs, numbers with a trailing dot and an exponent
+were read as integers and the exponent ignored: 2.e6 was interpreted as the
+integer 2.  Such numerals are now read as floats with the exponent included:
+2.e6 is now read as the floating-point value 2000000.0.
+That is, '(read-from-string "1.e3")' => '(1000.0 . 4)' now.
 
-+++
-*** New variable 'current-minibuffer-command'.
-This is like 'this-command', but it is bound recursively when entering
-the minibuffer.
+** 'equal' no longer examines some contents of window configurations.
+Instead, it considers window configurations to be equal only if they
+are 'eq'.  To compare contents, use 'compare-window-configurations'
+instead.  This change helps fix a bug in 'sxhash-equal', which returned
+incorrect hashes for window configurations and some other objects.
 
 +++
-*** New function 'object-intervals'.
-This function returns a copy of the list of intervals (i.e., text
-properties) in the object in question (which must either be a string
-or a buffer).
-
----
-*** 'hexl-mode' scrolling commands now heed 'next-screen-context-lines'.
-Previously, 'hexl-scroll-down' and 'hexl-scroll-up' would scroll
-up/down an entire window, but they now work more like the standard
-scrolling commands.
-
----
-*** Errors in 'kill-emacs-hook' no longer prevent Emacs from shutting down.
-If a function in that hook signals an error in an interactive Emacs,
-the user will be prompted on whether to continue.  If the user doesn't
-answer within five seconds, Emacs will continue shutting down anyway.
+** The 'lexical-binding' local variable is always enabled.
+Previously, if 'enable-local-variables' was nil, a 'lexical-binding'
+local variable would not be heeded.  This has now changed, and a file
+with a 'lexical-binding' cookie is always heeded.  To revert to the
+old behavior, set 'permanently-enabled-local-variables' to nil.
 
 ---
-*** iso-transl is now preloaded.
-This means that keystrokes like 'Alt-[' are defined by default,
-instead of only becoming available after doing (for instance)
-'C-x 8 <letter>'.
+** 'kill-all-local-variables' has changed how it handles non-symbol hooks.
+The function is documented to eliminate all buffer-local bindings
+except variables with a 'permanent-local' property, or hooks that
+have elements with a 'permanent-local-hook' property.  In addition, it
+would also keep lambda expressions in hooks sometimes.  The latter has
+now been changed: The function will now also remove these.
 
-*** New user option 'completions-detailed'.
-When non-nil, some commands like 'describe-symbol' show more detailed
-completions with more information in completion prefix and suffix.
++++
+** Temporary buffers no longer run certain buffer hooks.
+The macros 'with-temp-buffer' and 'with-temp-file' no longer run the
+hooks 'kill-buffer-hook', 'kill-buffer-query-functions', and
+'buffer-list-update-hook' for the temporary buffers they create.  This
+avoids slowing them down when a lot of these hooks are defined.
 
----
-*** User option 'completions-format' supports a new value 'one-column'.
+** New face 'child-frame-border' and frame parameter 
'child-frame-border-width'.
+The face and width of child frames borders can now be determined
+separately from those of normal frames.  To minimize backward
+incompatibility, child frames without a 'child-frame-border-width'
+parameter will fall back to using 'internal-border-width'.  However,
+the new 'child-frame-border' face does constitute a breaking change
+since child frames' borders no longer use the 'internal-border' face.
 
 ---
-*** New user option 'bibtex-unify-case-function'.
-This new option allows the user to customize how case is converted
-when unifying entries.
+** 'run-at-time' now tries harder to implement the t TIME parameter.
+If TIME is t, the timer runs at an integral multiple of REPEAT.
+(I.e., if given a REPEAT of 60, it'll run at 08:11:00, 08:12:00,
+08:13:00.)  However, when a machine goes to sleep (or otherwise didn't
+get a time slot to run when the timer was scheduled), the timer would
+then fire every 60 seconds after the time the timer was fired.  This
+has now changed, and the timer code now recomputes the integral
+multiple every time it runs, which means that if the laptop wakes at
+08:16:43, it'll fire at that time, but then at 08:17:00, 08:18:00...
 
 ---
-*** The user option 'bibtex-maintain-sorted-entries' now permits
-user-defined sorting schemes.
+** 'parse-partial-sexp' now signals an error if TO is smaller than FROM.
+Previously, this would lead to the function interpreting FROM as TO and
+vice versa, which would be confusing when passing in OLDSTATE, which
+refers to the old state at FROM.
 
 +++
-*** 'format-seconds' can now be used for sub-second times.
-The new optional "," parameter has been added, and
-'(format-seconds "%mm %,1ss" 66.4)' will now result in "1m 6.4s".
-
----
-*** 'global-display-fill-column-indicator-mode' skips some buffers.
-By default, turning on 'global-display-fill-column-indicator-mode'
-doesn't turn on 'display-fill-column-indicator-mode' in special-mode
-buffers.  This can be controlled by customizing the variable
-'global-display-fill-column-indicator-modes'.
+** 'global-mode-string' constructs should end with a space.
+This was previously not formalized, which led to combinations of modes
+displaying data "smushed together" on the mode line.
 
 +++
-*** New user option 'next-error-message-highlight'.
-In addition to a fringe arrow, 'next-error' error may now optionally
-highlight the current error message in the 'next-error' buffer.
-This user option can be also customized to keep highlighting on all
-visited errors, so you can have an overview what errors were already visited.
+** 'overlays-in' now handles zero-length overlays slightly differently.
+Previously, zero-length overlays at the end of the buffer were included
+in the result (if the region queried for stopped at that position).
+The same was not the case if the buffer had been narrowed to exclude
+the real end of the buffer.  This has now been changed, and
+zero-length overlays at 'point-max' are always included in the results.
 
 ---
-*** New choice 'next-error-quit-window' for 'next-error-found-function'.
-When 'next-error-found-function' is customized to 'next-error-quit-window',
-then typing the numeric prefix argument 0 before the command 'next-error'
-will quit the source window after visiting the next occurrence.
+** 'replace-match' now runs modification hooks slightly later.
+The function is documented to leave point after the replacement text,
+but this was not always the case if a modification hook inserted text
+in front of the replaced text -- 'replace-match' would instead leave
+point where the end of the inserted text would have been before the
+hook ran.  'replace-match' now always leaves point after the
+replacement text.
 
 +++
-*** New user option 'tab-first-completion'.
-If 'tab-always-indent' is 'complete', this new user option can be used to
-further tweak whether to complete or indent.
+** 'completing-read-default' sets completion variables buffer-locally.
+'minibuffer-completion-table' and related variables are now set buffer-locally
+in the minibuffer instead of being set via a global let-binding.
 
----
-*** 'dired-query' now uses 'read-char-from-minibuffer'.
-Using it instead of 'read-char-choice' allows using 'C-x o'
-to switch to the help window displayed after typing 'C-h'.
+** XML serialization functions now reject invalid characters.
+Previously, 'xml-print' would produce invalid XML when given a string
+with characters that are not valid in XML (see
+https://www.w3.org/TR/xml/#charsets).  Now it rejects such strings.
 
 ---
-*** 'zap-up-to-char' now uses 'read-char-from-minibuffer'.
-This allows navigating through the history of characters that have
-been input.  This is mostly useful for characters that have complex
-input methods where inputting the character again may involve many
-keystrokes.
-
-+++
-*** Interactive regular expression search now uses faces for sub-groups.
-E.g., 'C-M-s foo-\([0-9]+\)' will now use the 'isearch-group-1' face
-on the part of the regexp that matches the sub-expression "[0-9]+".
-By default, there are two faces for sub-group highlighting, but you
-can define more faces whose names are of the form 'isearch-group-N',
-where N are successive numbers above 2.
+** JSON
 
-This is controlled by the 'search-highlight-submatches' user option.
-This feature is available only on terminals that have enough colors to
-distinguish between sub-expression highlighting.
+*** JSON number parsing is now stricter.
+Numbers with a leading plus sign, leading zeros, or a missing integer
+component are now rejected by 'json-read' and friends.  This makes
+them more compliant with the JSON specification and consistent with
+the native JSON parsing functions.
 
-+++
-*** Interactive regular expression replace now uses faces for sub-groups.
-Like 'search-highlight-submatches', this is controlled by the new user option
-'query-replace-highlight-submatches'.
+*** JSON functions support the semantics of RFC 8259.
+The JSON functions 'json-serialize', 'json-insert',
+'json-parse-string', and 'json-parse-buffer' now implement some of the
+semantics of RFC 8259 instead of the earlier RFC 4627.  In particular,
+these functions now accept top-level JSON values that are neither
+arrays nor objects.
 
 ---
-*** New user option 'reveal-auto-hide'.
-If non-nil (the default), revealed text is automatically hidden when
-point leaves the text.  If nil, the text is not hidden again.  Instead
-'M-x reveal-hide-revealed' can be used to hide all the revealed text.
+*** Some JSON encoding functions are now obsolete.
+The functions 'json-encode-number', 'json-encode-hash-table',
+'json-encode-key', and 'json-encode-list' are now obsolete.
+
+The first two are kept as aliases of 'json-encode', which should be
+used instead.  Uses of 'json-encode-list' should be changed to call
+one of 'json-encode', 'json-encode-alist', 'json-encode-plist', or
+'json-encode-array' instead.
 
 +++
-*** New command 'submit-emacs-patch'.
-This works like 'report-emacs-bug', but is more geared towards sending
-patches to the Emacs issue tracker.
+*** Native JSON functions now signal an error if libjansson is unavailable.
+This affects 'json-serialize', 'json-insert', 'json-parse-string',
+and 'json-parse-buffer'.  This can happen if Emacs was compiled with
+libjansson, but the DLL cannot be found and/or loaded by Emacs at run
+time.  Previously, Emacs would display a message and return nil in
+these cases.
 
 +++
-*** The user can now customize how "default" values are prompted for.
-The new utility function 'format-prompt' has been added which uses the
-new 'minibuffer-default-prompt-format' user option to format "default"
-prompts.  This means that prompts that look like "Enter a number
-(default 10)" can be customized to look like, for instance, "Enter a
-number [10]", or not have the default displayed at all, like "Enter a
-number".  (This requires that all callers are altered to use
-'format-prompt', though.)
+** The use of positional arguments in 'define-minor-mode' is obsolete.
+These were actually rendered obsolete in Emacs 21 but were never
+marked as such.
+
+** 'pcomplete-ignore-case' is now an obsolete alias of 
'completion-ignore-case'.
+
+** 'completions-annotations' face is not used when the caller puts own face.
+This affects the suffix specified by completion 'annotation-function'.
 
 +++
-*** New global mode 'global-goto-address-mode'.
-This will enable 'goto-address-mode' in all buffers.
+** An active minibuffer now has major mode 'minibuffer-mode'.
+This is instead of the erroneous 'minibuffer-inactive-mode' it
+formerly had.
 
----
-*** 'C-s' in 'M-x' now searches over completions again.
-In Emacs 23, typing 'M-x' ('read-extended-command') and then 'C-s' (to
-do an interactive search) would search over possible completions.
-This was lost in Emacs 24, but is now back again.
+** 'make-text-button' no longer text properties of its first argument.
+When its first argument is a string, 'make-text-button' no longer
+modifies the string's text properties; instead, it uses and returns
+a copy of the string.  This helps avoid trouble when strings are
+shared or constants.
 
----
-*** 'M-x report-emacs-bug' will no longer include "Recent messages" section.
-These were taken from the "*Messages*" buffer, and may inadvertently
-leak information from the reporting user.
++++
+** Some properties from completion tables are now preserved.
+If 'minibuffer-allow-text-properties' is non-nil, doing completion
+over a table of strings with properties will no longer remove all the
+properties before returning.  This affects things like 'completing-read'.
 
----
-*** 'count-windows' now takes an optional parameter ALL-FRAMES.
-The semantics are as with 'walk-windows'.
+** 'dns-query' now consistently uses Lisp integers to represent integers.
+Formerly it made an exception for integer components of SOA records,
+because SOA serial numbers can exceed fixnum ranges on 32-bit platforms.
+Emacs now supports bignums so this old glitch is no longer needed.
 
----
-*** New variable 'ffap-file-name-with-spaces'.
-If non-nil, 'find-file-at-point' and friends will try to guess more
-expansively to identify a file name with spaces.
++++
+** The '&define' keyword in an Edebug specification now disables backtracking.
+The implementation was buggy, and multiple '&define' forms in an '&or'
+form should be exceedingly rare.  See the Info node "(elisp) Backtracking" in
+the Emacs Lisp reference manual for background.
 
 +++
-*** New 'thing-at-point' target: 'existing-filename'.
-This is like 'filename', but is a full path, and is nil if the file
-doesn't exist.
+** The error 'ftp-error' belongs also to category 'remote-file-error'.
 
----
-*** Two new commands for centering in 'doc-view-mode'.
-The new commands 'doc-view-center-page-horizontally' (bound to 'c h')
-and 'doc-view-center-page-vertically' (bound to 'c v') center the page
-horizontally and vertically, respectively.
+** The WHEN argument of 'make-obsolete' and related functions is mandatory.
+The use of those functions without a WHEN argument was marked obsolete
+back in Emacs 23.1.  The affected functions are: 'make-obsolete',
+'define-obsolete-function-alias', 'make-obsolete-variable',
+'define-obsolete-variable-alias'.
 
----
-*** Change in meaning of 'icomplete-show-matches-on-no-input'.
-Previously, choosing a different completion with commands like 'C-.'
-and then hitting 'RET' would choose the default completion.  Doing this
-will now choose the completion under point instead.  Also when this option
-is nil, completions are not shown when the minibuffer reads a file name
-with initial input as the default directory.
++++
+** 'inhibit-nul-byte-detection' is renamed to 'inhibit-null-byte-detection'.
 
 ---
-*** The width of the buffer-name column in 'list-buffers' is now dynamic.
-The width now depends of the width of the window, but will never be
-wider than the length of the longest buffer name, except that it will
-never be narrower than 19 characters.
+** Some functions are no longer considered safe by 'unsafep':
+'replace-regexp-in-string', 'catch', 'throw', 'error', 'signal'
+and 'play-sound-file'.
 
 ---
-*** Movement commands in 'gomoku-mode' are fixed.
-'gomoku-move-sw' and 'gomoku-move-ne' now work correctly, and
-horizontal movements now stop at the edge of the board.
-
-** xterm-mouse mode
+** 'ruby-use-smie' is declared obsolete.
+SMIE is now always enabled and 'ruby-use-smie' only controls whether
+indentation is done using SMIE or with the old ad-hoc code.
 
 ---
-*** TTY menu navigation is now supported in 'xterm-mouse-mode'.
-TTY menus support mouse navigation and selection when 'xterm-mouse-mode'
-is active.  When run on a terminal, clicking on the menu bar with the
-mouse now pops up a TTY menu by default instead of running the command
-'tmm-menubar'.  To restore the old behavior, set the user option
-'tty-menu-open-use-tmm' to non-nil.
+** 'sql-*-statement-starters' are no longer user options.
+These variables describe facts about the SQL standard and
+product-specific additions.  There should be no need for users to
+customize them.
 
-** text-scale-mode
+** Some locale-related variables have been removed.
+The Lisp variables 'previous-system-messages-locale' and
+'previous-system-time-locale' have been removed, as they were created
+by mistake and were not useful to Lisp code.
 
 ---
-*** 'text-scale-mode' can now adjust font size of the header line.
-When the new buffer local variable 'text-scale-remap-header-line'
-is non-nil, 'text-scale-adjust' will also scale the text in the header
-line when displaying that buffer.
+** Function 'lm-maintainer' is replaced with 'lm-maintainers'.
+The former is now declared obsolete.
 
-This is useful for major modes that arrange their display in a tabular
-form below the header line.  It is enabled by default in
-'tabulated-list-mode' and its derived modes.
+** 'facemenu.el' is no longer preloaded.
+To use functions/variables from the package, you now have to say
+'(require 'facemenu)' or similar.
 
-** xwidget-webkit mode
+** 'facemenu-color-alist' is now obsolete, and is not used.
 
-*** New xwidget commands.
-'xwidget-webkit-uri' (return the current URL), 'xwidget-webkit-title'
-(return the current title), and 'xwidget-webkit-goto-history' (goto a
-point in history).
+** The variable 'keyboard-type' is obsolete and not dynamically scoped any 
more.
 
-*** Pixel-based scrolling.
-The 'xwidget-webkit-scroll-up', 'xwidget-webkit-scroll-down' commands
-now supports scrolling arbitrary pixel values.  It now treats the
-optional 2nd argument as the pixel values to scroll.
++++
+** The 'values' variable is now obsolete.
+Using it just contributes to the growth of the Emacs memory
+footprint.
 
-*** New commands for scrolling.
-The new commands 'xwidget-webkit-scroll-up-line',
-'xwidget-webkit-scroll-down-line', 'xwidget-webkit-scroll-forward',
-'xwidget-webkit-scroll-backward' can be used to scroll webkit by the
-height of lines or width of chars.
+---
+** The 'load-dangerous-libraries' variable is now obsolete.
+It was used to allow loading Lisp libraries compiled by XEmacs, a
+modified version of Emacs which is no longer actively maintained.
+This is no longer supported, and setting this variable has no effect.
 
-*** New user option 'xwidget-webkit-bookmark-jump-new-session'.
-When non-nil, use a new xwidget webkit session after bookmark jump.
-Otherwise, it will use 'xwidget-webkit-last-session'.
++++
+** The macro 'with-displayed-buffer-window' is now obsolete.
+Use macro 'with-current-buffer-window' with action alist entry 'body-function'.
 
-** ido
+---
+** The rfc2368.el library is now obsolete.
+Use rfc6068.el instead.  The main difference is that
+'rfc2368-parse-mailto-url' and 'rfc2368-unhexify-string' assumed that
+the strings were all-ASCII, while 'rfc6068-parse-mailto-url' and
+'rfc6068-unhexify-string' parse UTF-8 strings.
 
 ---
-*** Switching on 'ido-mode' now also overrides 'ffap-file-finder'.
+** The inversion.el library is now obsolete.
 
 ---
-*** Killing virtual ido buffers interactively will make them go away.
-Previously, killing a virtual ido buffer with 'ido-kill-buffer' didn't
-do anything.  This has now been changed, and killing virtual buffers
-with that command will remove the buffer from recentf.
+** The metamail.el library is now obsolete.
 
-** Flymake mode
+** Edebug changes
+
+---
+*** 'get-edebug-spec' is obsolete, replaced by 'edebug-get-spec'.
 
 +++
-*** New user options to customize Flymake's mode-line.
-The new user option 'flymake-mode-line-format' is a mix of strings and
-symbols like 'flymake-mode-line-title', 'flymake-mode-line-exception'
-and 'flymake-mode-line-counters'.  The new user option
-'flymake-mode-line-counter-format' is a mix of strings and symbols
-like 'flymake-mode-line-error-counter',
-'flymake-mode-line-warning-counter' and 'flymake-mode-line-note-counter'.
+*** The spec operator ':name NAME' is obsolete, use '&name' instead.
 
-** Flyspell mode
++++
+*** The spec element 'function-form' is obsolete, use 'form' instead.
 
 +++
-*** Corrections and actions menu can be optionally bound to 'mouse-3'.
-When Flyspell mode highlights a word as misspelled, you can click on
-it to display a menu of possible corrections and actions.  You can now
-easily bind this menu to 'down-mouse-3' (usually the right mouse button)
-instead of 'mouse-2' (the default) by customizing the new user option
-'flyspell-use-mouse-3-for-menu'.
+*** New function 'def-edebug-elem-spec' to define Edebug spec elements.
+These used to be defined with 'def-edebug-spec' thus conflating the
+two name spaces, which lead to name collisions.
+The use of 'def-edebug-spec' to define Edebug spec elements is
+declared obsolete.
 
 ---
-*** The current dictionary is now displayed in the minor mode lighter.
-Clicking the dictionary name changes the current dictionary.
-
-** Time
+** The sb-image.el library is now obsolete.
+This was a compatibility kludge which is no longer needed.
 
 ---
-*** 'display-time-world' has been renamed to 'world-clock'.
-'world-clock' creates a buffer with an updating time display using
-several time zones.  It is hoped that the new names are more
-discoverable.
-
-The following commands have been renamed:
+** Some libraries obsolete since Emacs 23 have been removed:
+ledit.el, lmenu.el, lucid.el and old-whitespace.el.
 
-  'display-time-world'         to 'world-clock'
-  'display-time-world-mode'    to 'world-clock-mode'
-  'display-time-world-display' to 'world-clock-display'
-  'display-time-world-timer'   to 'world-clock-update'
+---
+** Some functions and variables obsolete since Emacs 23 have been removed:
+'GOLD-map', 'advertised-xscheme-send-previous-expression',
+'allout-init', 'bookmark-jump-noselect',
+'bookmark-read-annotation-text-func', 'buffer-menu-mode-hook',
+'c-forward-into-nomenclature', 'char-coding-system-table',
+'char-valid-p', 'charset-bytes', 'charset-id', 'charset-list',
+'choose-completion-delete-max-match', 'complete-in-turn',
+'completion-base-size', 'completion-common-substring',
+'crm-minibuffer-complete', 'crm-minibuffer-complete-and-exit',
+'crm-minibuffer-completion-help', 'custom-mode', 'custom-mode-hook',
+'define-key-rebound-commands', 'define-mode-overload-implementation',
+'detect-coding-with-priority', 'dirtrack-debug',
+'dirtrack-debug-toggle', 'dynamic-completion-table',
+'easy-menu-precalculate-equivalent-keybindings',
+'epa-display-verify-result', 'epg-passphrase-callback-function',
+'erc-announced-server-name', 'erc-default-coding-system',
+'erc-process', 'erc-send-command', 'eshell-report-bug',
+'eval-next-after-load', 'exchange-dot-and-mark', 'ffap-bug',
+'ffap-submit-bug', 'ffap-version', 'file-cache-mouse-choose-completion',
+'forward-point', 'generic-char-p', 'global-highlight-changes',
+'hi-lock-face-history', 'hi-lock-regexp-history',
+'highlight-changes-active-string', 'highlight-changes-initial-state',
+'highlight-changes-passive-string',
+'icalendar--datetime-to-noneuropean-date', 'image-mode-maybe',
+'imenu-example--name-and-position', 'ispell-aspell-supports-utf8',
+'lisp-mode-auto-fill', 'locate-file-completion', 'make-coding-system',
+'menu-bar-files-menu', 'minibuffer-local-must-match-filename-map',
+'mouse-choose-completion', 'mouse-major-mode-menu',
+'mouse-popup-menubar', 'mouse-popup-menubar-stuff',
+'newsticker-groups-filename', 'nnir-swish-e-index-file',
+'nnmail-fix-eudora-headers', 'non-iso-charset-alist',
+'nonascii-insert-offset', 'nonascii-translation-table',
+'password-read-and-add', 'pre-abbrev-expand-hook', 'princ-list',
+'print-help-return-message', 'process-filter-multibyte-p',
+'read-file-name-predicate', 'remember-buffer', 'rmail-highlight-face',
+'rmail-message-filter', 'semantic-after-idle-scheduler-reparse-hooks',
+'semantic-after-toplevel-bovinate-hook',
+'semantic-before-idle-scheduler-reparse-hooks',
+'semantic-before-toplevel-bovination-hook',
+'semantic-bovinate-from-nonterminal-full',
+'semantic-bovinate-region-until-error', 'semantic-bovinate-toplevel',
+'semantic-bovination-working-type',
+'semantic-decorate-pending-decoration-hooks',
+'semantic-edits-incremental-reparse-failed-hooks',
+'semantic-eldoc-current-symbol-info', 'semantic-expand-nonterminal',
+'semantic-file-token-stream', 'semantic-find-dependency',
+'semantic-find-nonterminal', 'semantic-flex', 'semantic-flex-buffer',
+'semantic-flex-keyword-get', 'semantic-flex-keyword-p',
+'semantic-flex-keyword-put', 'semantic-flex-keywords',
+'semantic-flex-list', 'semantic-flex-make-keyword-table',
+'semantic-flex-map-keywords', 'semantic-flex-token-end',
+'semantic-flex-token-start', 'semantic-flex-token-text',
+'semantic-imenu-bucketize-type-parts',
+'semantic-imenu-expand-type-parts', 'semantic-imenu-expandable-token',
+'semantic-init-db-hooks', 'semantic-init-hooks',
+'semantic-init-mode-hooks', 'semantic-java-prototype-nonterminal',
+'semantic-nonterminal-abstract', 'semantic-nonterminal-full-name',
+'semantic-nonterminal-leaf', 'semantic-nonterminal-protection',
+'semantic-something-to-stream', 'semantic-tag-make-assoc-list',
+'semantic-token-type-parent', 'semantic-toplevel-bovine-cache',
+'semantic-toplevel-bovine-table', 'semanticdb-mode-hooks',
+'set-coding-priority', 'set-process-filter-multibyte',
+'shadows-compare-text-p', 'shell-dirtrack-toggle',
+'speedbar-navigating-speed', 'speedbar-update-speed', 't-mouse-mode',
+'term-dynamic-simple-complete', 'tooltip-hook', 'tpu-have-ispell',
+'url-generate-unique-filename', 'url-temporary-directory',
+'vc-arch-command', 'vc-default-working-revision' (variable),
+'vc-mtn-command', 'vc-revert-buffer', 'vc-workfile-version',
+'vcursor-toggle-vcursor-map', 'w32-focus-frame', 'w32-select-font',
+'wisent-lex-make-token-table'.
 
-The following user options have been renamed:
+---
+** Some functions and variables obsolete since Emacs 22 have been removed:
+'gnus-article-hide-pgp-hook', 'gnus-inews-mark-gcc-as-read',
+'gnus-treat-display-xface', 'gnus-treat-strip-pgp',
+'nnmail-spool-file'.
 
-  'display-time-world-list'         to 'world-clock-list'
-  'display-time-world-time-format'  to 'world-clock-time-format'
-  'display-time-world-buffer-name'  to 'world-clock-buffer-name'
-  'display-time-world-timer-enable' to 'world-clock-timer-enable'
-  'display-time-world-timer-second' to 'world-clock-timer-second'
+---
+** The obsolete function 'thread-alive-p' has been removed.
 
-The old names are now obsolete.
+---
+** The variable 'force-new-style-backquotes' has been removed.
+This removes the final remaining trace of old-style backquotes.
 
 ---
-*** 'world-clock-mode' can no longer be turned on interactively.
-Use 'world-clock' to turn on that mode.
+** Some obsolete variable and function aliases in dbus.el have been removed.
+In Emacs 24.3, the variable 'dbus-event-error-hooks' was renamed to
+'dbus-event-error-functions' and the function
+'dbus-call-method-non-blocking' was renamed to 'dbus-call-method'.
+The old names, which were kept as obsolete aliases of the new names,
+have now been removed.
 
-** D-Bus
+
+* Lisp Changes in Emacs 28.1
 
 +++
-*** Property values can be typed explicitly.
-'dbus-register-property' and 'dbus-set-property' accept now optional
-type symbols.  Both functions propagate D-Bus errors.
+** The 'interactive' syntax has been extended to allow listing applicable 
modes.
+Forms like '(interactive "p" dired-mode)' can be used to annotate the
+commands as being applicable for modes derived from 'dired-mode',
+or if the mode is a minor mode, that the current buffer has that
+minor mode activated.  Note that using this form will create byte code
+that is not compatible with byte code in previous Emacs versions.
 
 +++
-*** Registered properties can have the new access type ':write'.
+** New forms to declare how completion should happen has been added.
+'(declare (completion PREDICATE))' can be used as a general predicate
+to say whether the command should be present when completing with
+'M-x TAB'.  '(declare (modes MODE...))' can be used as a short-hand
+way of saying that the command should be present when completing from
+buffers in major modes derived from MODE..., or, if it's a minor mode,
+whether that minor mode is enabled in the current buffer.
 
 +++
-*** In case of problems, handlers can emit proper D-Bus error messages now.
+** 'define-minor-mode'  now takes an ':interactive' argument.
+This can be used for specifying which modes this minor mode is meant
+for, or to make the new minor mode non-interactive.  The default value
+is t.
 
 +++
-*** D-Bus errors, which have been converted from incoming D-Bus error
-messages, contain the error name of that message now.
+** 'define-derived-mode' now takes an ':interactive' argument.
+This can be used to control whether the defined mode is a command
+or not, and is useful when defining commands that aren't meant to be
+used by users directly.
 
 +++
-*** D-Bus messages can be monitored with the new command 'dbus-monitor'.
+** 'define-globalized-minor-mode' now takes a ':predicate' parameter.
+This can be used to control which major modes the minor mode should be
+used in.
 
 +++
-*** D-Bus events have changed their internal structure.
-They carry now the destination and the error-name of an event.  They
-also keep the type information of their arguments.  Use the
-'dbus-event-*' accessor functions.
-
-** CPerl Mode
+** 'condition-case' now allows for a success handler.
+It is written as '(:success BODY...)' where BODY is executed
+whenever the protected form terminates without error, with the
+specified variable bound to the the value of the protected form.
 
----
-*** New face 'perl-heredoc', used for heredoc elements.
+** New function 'benchmark-call' to measure the execution time of a function.
+Additionally, the number of repetitions can be expressed as a minimal duration
+in seconds.
 
 +++
-** A function can now be thrown to the 'exit' label in addition to t or nil.
-The command loop will call it with zero arguments before returning.
+** The value thrown to the 'exit' label can now be a function.
+This is in addition to values t or nil.  If the value is a function,
+the command loop will call it with zero arguments before returning.
 
 +++
-** New error symbol 'minibuffer-quit'.
-Signaling it has almost the same effect as 'quit' except that it
-doesn't cause keyboard macro termination.
+** The behavior of 'format-spec' is now closer to that of 'format'.
+In order for the two functions to behave more consistently,
+'format-spec' now pads and truncates based on string width rather than
+length, and also supports format specifications that include a
+truncating precision field, such as "%.2a".
 
 ---
-*** The command 'cperl-set-style' offers the new value "PBP".
-This value customizes Emacs to use the style recommended in Damian
-Conway's book "Perl Best Practices" for indentation and formatting
-of conditionals.
-
-** Abbrev mode
+** 'defvar' detects the error of defining a variable currently lexically bound.
+Such mixes are always signs that the outer lexical binding was an
+error and should have used dynamic binding instead.
 
-+++
-*** Emacs can now suggest to use an abbrev based on text you type.
-A new user option, 'abbrev-suggest', enables the new abbrev suggestion
-feature.  When enabled, if a user manually types a piece of text that
-could have saved enough typing by using an abbrev, a hint will be
-displayed in the echo area, mentioning the abbrev that could have been
-used instead.
+---
+** New variable 'inhibit-mouse-event-check'.
+If bound to non-nil, a command with '(interactive "e")' doesn't signal
+an error when invoked by input event that is not a mouse click (e.g.,
+a key sequence).
 
-** Octave Mode
+** New variable 'redisplay-skip-initial-frame' to enable batch redisplay tests.
+Setting it to nil forces the redisplay to do its job even in the
+initial frame used in batch mode.
 
 +++
-*** Line continuations in double-quoted strings now use a backslash.
-Typing 'C-M-j' (bound to 'octave-indent-new-comment-line') now follows
-the behavior introduced in Octave 3.8 of using a backslash as a line
-continuation marker within double-quoted strings, and an ellipsis
-everywhere else.
-
-** Repeat
+** Doc strings can now link to customization groups.
+Text like "customization group `whitespace'" will be made into a
+button.  When clicked, it'll take the user to a Custom buffer
+displaying that customization group.
 
 +++
-*** New transient mode 'repeat-mode' to allow shorter key sequences.
-You can type 'C-x u u' instead of 'C-x u C-x u' to undo many changes,
-'C-x o o' instead of 'C-x o C-x o' to switch several windows,
-'C-x { { } } ^ ^ v v' to resize the selected window interactively,
-'M-g n n p p' to navigate next-error matches.  Any other key exits
-transient mode and then is executed normally.  'repeat-exit-key'
-defines an additional key to exit mode like 'isearch-exit' ('RET').
-The user option 'repeat-exit-timeout' specifies the number of
-seconds of idle time to break the repetition chain automatically.
-With 'repeat-keep-prefix' you can keep the prefix arg of the previous
-command.  For example, this can help to reverse the window navigation
-direction with e.g. 'C-x o M-- o o'.  Also it can help to set a new
-step with e.g. 'C-x { C-5 { { {', which will set the window resizing
-step to 5 columns.
+** Buffers can now be created with certain hooks disabled.
+The functions 'get-buffer-create' and 'generate-new-buffer' accept a
+new optional argument INHIBIT-BUFFER-HOOKS.  If non-nil, the new
+buffer does not run the hooks 'kill-buffer-hook',
+'kill-buffer-query-functions', and 'buffer-list-update-hook'.  This
+avoids slowing down internal or temporary buffers that are never
+presented to users or passed on to other applications.
 
 +++
-** EasyPG
-GPG key servers can now be queried for keys with the
-'M-x epa-search-keys' command.  Keys can then be added to your
-personal key ring.
-
-** So Long
+** New command 'make-directory-autoloads'.
+This does the same as the old command 'update-directory-autoloads',
+but has different semantics: Instead of passing in the output file via
+the dynamically bound 'generated-autoload-file' variable, the output
+file is now a explicit parameter.
 
 ---
-*** New 'so-long-predicate' function 'so-long-statistics-excessive-p'
-efficiently detects the presence of a long line anywhere in the buffer
-using 'buffer-line-statistics' (see above).  This is now the default
-predicate (replacing 'so-long-detected-long-line-p').
+** Dragging a file into Emacs pushes the file name onto 'file-name-history'.
 
 ---
-*** 'so-long-threshold' and 'so-long-max-lines' have been raised to
-10000 bytes and 500 lines respectively, to reduce the likelihood of
-false-positives when 'global-so-long-mode' is enabled.  The latter
-value is now only used by the old predicate, as the new predicate
-knows the longest line in the entire buffer.
+** The 'easymenu' library is now preloaded.
 
 ---
-*** 'so-long-target-modes' now includes 'fundamental-mode' by default,
-meaning that 'global-so-long-mode' will also process files which were
-not recognised.  (This only has an effect if 'set-auto-mode' chooses
-'fundamental-mode'; buffers which are simply in 'fundamental-mode' by
-default are unaffected.)
+** The 'iso-transl' library is now preloaded.
+This means that keystrokes like 'Alt-[' are defined by default,
+instead of only becoming available after doing (for instance)
+'C-x 8 <letter>'.
 
 ---
-*** New user options 'so-long-mode-preserved-minor-modes' and
-'so-long-mode-preserved-variables' allow specified mode and variable
-states to be maintained if 'so-long-mode' replaces the original major
-mode.  By default, these new options support 'view-mode'.
-
-
-* New Modes and Packages in Emacs 28.1
-
-** Lisp Data mode
-The new command 'lisp-data-mode' enables a major mode for buffers
-composed of Lisp symbolic expressions that do not form a computer
-program.  The ".dir-locals.el" file is automatically set to use this
-mode, as are other data files produced by Emacs.
-
-** hierarchy.el
-It's a library to create, query, navigate and display hierarchy structures.
-
-** New themes 'modus-vivendi' and 'modus-operandi'.
-These themes are designed to conform with the highest standard for
-color-contrast accessibility (WCAG AAA).  You can load either of them
-using 'M-x customize-themes' or 'load-theme' from your init file.
-Consult the Modus Themes Info manual for more information on the user
-options they provide.
-
-** Dictionary mode
-This is a mode for searching a RFC 2229 dictionary server.
-'dictionary' opens a buffer for starting operations.
-'dictionary-search' performs a lookup for a word.  It also supports a
-'dictionary-tooltip-mode' which performs a lookup of the word under
-the mouse in 'dictionary-tooltip-dictionary' (which must be customized
-first).
-
-** transient.el
-
-This library implements support for powerful keyboard-driven menus.
-Such menus can be used as simple visual command dispatchers.  More
-complex menus take advantage of infix arguments, which are somewhat
-similar to prefix arguments, but are more flexible and discoverable.
-
-
-* Incompatible Editing Changes in Emacs 28.1
+** ':safe' settings in 'defcustom' are now propagated to the loaddefs files.
 
-** 'electric-indent-mode' now also indents inside strings and comments,
-(unless the indentation function doesn't, of course).
-To recover the previous behavior you can use:
++++
+** ERT can now output more verbose test failure reports.
+If the 'EMACS_TEST_VERBOSE' environment variable is set, failure
+summaries will include the failing condition.
 
-    (add-hook 'electric-indent-functions
-              (lambda (_) (if (nth 8 (syntax-ppss)) 'no-indent)))
+** Byte compiler changes
 
-** The 'M-o' ('facemenu-keymap') global binding has been removed.
-To restore the old binding, say something like:
++++
+*** New byte-compiler check for missing dynamic variable declarations.
+It is meant as an (experimental) aid for converting Emacs Lisp code
+to lexical binding, where dynamic (special) variables bound in one
+file can affect code in another.  For details, see the manual section
+"(elisp) Converting to Lexical Binding".
 
-    (require 'facemenu)
-    (define-key global-map "\M-o" 'facemenu-keymap)
-    (define-key facemenu-keymap "\es" 'center-line)
-    (define-key facemenu-keymap "\eS" 'center-paragraph)
++++
+*** 'byte-recompile-directory' can now compile symlinked ".el" files.
+This is achieved by giving a non-nil FOLLOW-SYMLINKS parameter.
 
-The last two lines are not strictly necessary if you don't care about
-having those two commands on the 'M-o' keymap; see the next section.
+---
+*** The byte-compiler now warns about too wide documentation strings.
+By default, it will warn if a documentation string is wider than the
+largest of 'byte-compile-docstring-max-column' or 'fill-column'
+characters.
 
-** The 'M-o M-s' and 'M-o M-S' global bindings have been removed.
-Use 'M-x center-line' and 'M-x center-paragraph' instead.  See the
-previous section for how to get back the old bindings.  Alternatively,
-if you only want these two commands to have global bindings they had
-before, you can add the following to your init file:
++++
+*** 'byte-compile-file' optional argument LOAD is now obsolete.
+To load the file after byte-compiling, add a call to 'load' from Lisp
+or use 'M-x emacs-lisp-byte-compile-and-load' interactively.
 
-  (define-key global-map "\M-o\M-s" 'center-line)
-  (define-key global-map "\M-o\M-S" 'center-paragraph)
+** Macroexp
+---
+*** New function 'macroexp-file-name' to know the name of the current file.
+---
+*** New function 'macroexp-compiling-p' to know if we're compiling.
+---
+*** New function 'macroexp-warn-and-return' to help emit warnings.
+This used to be named 'macroexp--warn-and-return' and has proved useful
+and well-behaved enough to lose the "internal" marker.
 
-** The 'M-o M-o' global binding has been removed.
-Use 'M-x font-lock-fontify-block' instead, or the new 'C-x x f'
-command, which updates the syntax highlighting in the current buffer.
+** map.el
 
-** In 'f90-mode', the backslash character ('\') no longer escapes.
-For about a decade, the backslash character has no longer had a
-special escape syntax in Fortran F90.  To get the old behavior back,
-say something like:
+*** Pcase 'map' pattern added keyword symbols abbreviation.
+A pattern like '(map :sym)' binds the map's value for ':sym' to 'sym',
+equivalent to '(map (:sym sym))'.
 
-    (modify-syntax-entry ?\\ "\\" f90-mode-syntax-table)
+---
+*** The function 'map-copy' now uses 'copy-alist' on alists.
+This is a slightly deeper copy than the previous 'copy-sequence'.
 
-** In 'nroff-mode', 'center-line' is now bound to 'M-o M-s'.
-The original key binding was 'M-s', which interfered with I-search,
-since the latter uses 'M-s' as a prefix key of the search prefix map.
+---
+*** The function 'map-contains-key' now supports plists.
 
-** 'vc-print-branch-log' shows the change log for BRANCH from its root
-directory instead of the default directory.
+---
+*** More consistent duplicate key handling in 'map-merge-with'.
+Until now, 'map-merge-with' promised to call its function argument
+whenever multiple maps contained 'eql' keys.  However, this did not
+always coincide with the keys that were actually merged, which could
+be 'equal' instead.  The function argument is now called whenever keys
+are merged, for greater consistency with 'map-merge' and 'map-elt'.
 
----
-** 'project-shell' and 'shell' now use 'pop-to-buffer-same-window'.
-This is to keep the same behavior as Eshell.
+** pcase
 
-
-* Incompatible Lisp Changes in Emacs 28.1
++++
+*** The 'or' pattern now binds the union of the vars of its sub-patterns.
+If a variable is not bound by the subpattern that matched, it gets bound
+to nil.  This was already sometimes the case, but it is now guaranteed.
 
 +++
-** 'overlays-in' now handles zero-length overlays slightly differently.
-Previosly, zero-length overlays at the end of the buffer were included
-in the result (if the region queried for stopped at that position).
-The same was not the case if the buffer had been narrowed to exclude
-the real end of the buffer.  This has now been changed, and
-zero-length overlays at `point-max' are always included in the results.
+*** The 'pred' pattern can now take the form '(pred (not FUN))'.
+This is like '(pred (lambda (x) (not (FUN x))))' but results
+in better code.
 
 ---
-** 'replace-match' now runs modification hooks slightly later.
-The function is documented to leave point after the replacement text,
-but this was not always the case if a modification hook inserted text
-in front of the replaced text -- 'replace-match' would instead leave
-point where the end of the inserted text would have been before the
-hook ran.  'replace-match' now always leaves point after the
-replacement text.
+*** New function 'pcase-compile-patterns' to write other macros.
 
----
-** 'kill-all-local-variables' has changed how it handles non-symbol hooks.
-The function is documented to eliminate all buffer-local bindings
-except variables with a 'permanent-local' property, or hooks that
-have elements with a 'permanent-local-hook' property.  In addition, it
-would also keep lambda expressions in hooks sometimes.  The latter has
-now been changed: The function will now also remove these.
+*** Added 'cl-type' pattern.
+The new 'cl-type' pattern compares types using 'cl-typep', which allows
+comparing simple types like '(cl-type integer)', as well as forms like
+'(cl-type (integer 0 10))'.
 
----
-** Some floating-point numbers are now handled differently by the Lisp reader.
-In previous versions of Emacs, numbers with a trailing dot and an exponent
-were read as integers and the exponent ignored: 2.e6 was interpreted as the
-integer 2.  Such numerals are now read as floats with the exponent included:
-2.e6 is now read as the floating-point value 2000000.0.
-That is, '(read-from-string "1.e3")' => '(1000.0 . 4)' now.
+*** New macro 'pcase-setq'.
+This macro is the 'setq' equivalent of 'pcase-let', which allows for
+destructuring patterns in a 'setq' form.
+
+** Edebug
+
+*** Edebug specification lists can use some new keywords:
 
 +++
-** The 'lexical-binding' local variable is always enabled.
-Previously, if 'enable-local-variables' was nil, a 'lexical-binding'
-local variable would not be heeded.  This has now changed, and a file
-with a 'lexical-binding' cookie is always heeded.  To revert to the
-old behavior, set 'permanently-enabled-local-variables' to nil.
+**** '&interpose SPEC FUN ARGS..' lets FUN control parsing after SPEC.
+More specifically, FUN is called with 'HEAD PF ARGS..' where
+PF is a parsing function that expects a single argument (the specs to
+use) and HEAD is the code that matched SPEC.
 
 +++
-** 'completing-read-default' sets completion variables buffer-locally.
-'minibuffer-completion-table' and related variables are now set buffer-locally
-in the minibuffer instead of being set via a global let-binding.
+**** '&error MSG' unconditionally aborts the current edebug instrumentation.
 
 +++
-** The use of positional arguments in 'define-minor-mode' is obsolete.
-These were actually rendered obsolete in Emacs 21 but were never
-marked as such.
+**** '&name SPEC FUN' extracts the current name from the code matching SPEC.
 
-** 'facemenu-color-alist' is now obsolete, and is not used.
+** Dynamic modules changes
 
-** 'facemenu.el' is no longer preloaded.
-To use functions/variables from the package, you now have to say
-'(require 'facemenu)' or similar.
++++
+*** Type aliases for module functions and finalizers.
+The module header 'emacs-module.h' now contains type aliases
+'emacs_function' and 'emacs_finalizer' for module functions and
+finalizers, respectively.
 
-** 'pcomplete-ignore-case' is now an obsolete alias of 
'completion-ignore-case'.
++++
+*** Module functions can now be made interactive.
+Use 'make_interactive' to give a module function an interactive
+specification.
 
-** 'completions-annotations' face is not used when the caller puts own face.
-This affects the suffix specified by completion 'annotation-function'.
++++
+*** Module functions can now install an optional finalizer.
+The finalizer is called when the function object is garbage-collected.
+Use 'set_function_finalizer' to set the finalizer and
+'get_function_finalizer' to retrieve it.
 
-** 'set-process-buffer' now updates the process mark.
-The mark will be set to point to the end of the new buffer.
++++
+*** Modules can now open a channel to an existing pipe process.
+Modules can use the new module function 'open_channel' to do that.
+On capable systems, modules can use this functionality to
+asynchronously send data back to Emacs.
 
 +++
-** An active minibuffer now has major mode 'minibuffer-mode', not the
-erroneous 'minibuffer-inactive-mode' it formerly had.
+*** A new module API 'make_unibyte_string'.
+It can be used to create Lisp strings with arbitrary byte sequences
+(a.k.a. "raw bytes").
 
 +++
-** Some properties from completion tables are now preserved.
-If 'minibuffer-allow-text-properties' is non-nil, doing completion
-over a table of strings with properties will no longer remove all the
-properties before returning.  This affects things like 'completing-read'.
+** New function 'string-search'.
+This function takes two string parameters and returns the position of
+the first instance of the former string in the latter.
 
-** 'equal' no longer examines some contents of window configurations.
-Instead, it considers window configurations to be equal only if they
-are 'eq'.  To compare contents, use 'compare-window-configurations'
-instead.  This change helps fix a bug in 'sxhash-equal', which returned
-incorrect hashes for window configurations and some other objects.
++++
+** New function 'string-replace'.
+This function works along the line of 'replace-regexp-in-string', but
+it matches on fixed strings instead of regexps, and does not change
+the global match state.
 
-** When its first argument is a string, 'make-text-button' no longer
-modifies the string's text properties; instead, it uses and returns
-a copy of the string.  This helps avoid trouble when strings are
-shared or constants.
++++
+** New function 'split-string-shell-command'.
+This splits a shell command string into separate components,
+respecting quoting with single ('like this') and double ("like this")
+quotes, as well as backslash quoting (like\ this).
+
+** New string manipulation functions added to subr-x.el.
+the functions are 'string-clean-whitespace', 'string-fill',
+'string-limit', 'string-lines', 'string-pad' and
+'string-chop-newline'.
 
 +++
-** Temporary buffers no longer run certain buffer hooks.
-The macros 'with-temp-buffer' and 'with-temp-file' no longer run the
-hooks 'kill-buffer-hook', 'kill-buffer-query-functions', and
-'buffer-list-update-hook' for the temporary buffers they create.  This
-avoids slowing them down when a lot of these hooks are defined.
+** New function 'replace-regexp-in-region'.
 
-** New face 'child-frame-border' and frame parameter 
'child-frame-border-width'.
-The face and width of child frames borders can now be determined
-separately from those of normal frames.  To minimize backward
-incompatibility, child frames without a 'child-frame-border-width'
-parameter will fall back to using 'internal-border-width'.  However,
-the new 'child-frame-border' face does constitute a breaking change
-since child frames' borders no longer use the 'internal-border' face.
++++
+** New function 'replace-string-in-region'.
 
----
-** The obsolete function 'thread-alive-p' has been removed.
++++
+** New function 'file-name-with-extension'.
+This function allows a canonical way to set/replace the extension of a
+file name.
 
-** 'dns-query' now consistently uses Lisp integers to represent integers.
-Formerly it made an exception for integer components of SOA records,
-because SOA serial numbers can exceed fixnum ranges on 32-bit platforms.
-Emacs now supports bignums so this old glitch is no longer needed.
++++
+** New function 'file-modes-number-to-symbolic' to convert a numeric
+file mode specification into symbolic form.
 
----
-** The new function 'dns-query-asynchronous' has been added.
-It takes the same parameters as 'dns-query', but adds a callback
-parameter.
++++
+** New function 'file-name-concat'.
+This appends file name components to a directory name and returns the
+result.
 
-** The Lisp variables 'previous-system-messages-locale' and
-'previous-system-time-locale' have been removed, as they were created
-by mistake and were not useful to Lisp code.
++++
+** New function 'file-backup-file-names'.
+This function returns the list of file names of all the backup files
+for the specified file.
 
----
-** The 'load-dangerous-libraries' variable is now obsolete.
-It was used to allow loading Lisp libraries compiled by XEmacs, a
-modified version of Emacs which is no longer actively maintained.
-This is no longer supported, and setting this variable has no effect.
++++
+** New function 'directory-empty-p'.
+This predicate tests whether a given file name is an accessible
+directory and whether it contains no other directories or files.
 
 +++
-** The macro 'with-displayed-buffer-window' is now obsolete.
-Use macro 'with-current-buffer-window' with action alist entry 'body-function'.
+** New function 'buffer-local-boundp'.
+This predicate says whether a symbol is bound in a specific buffer.
 
----
-** The inversion.el library is now obsolete.
++++
+** New function 'always'.
+This is identical to 'ignore', but returns t instead.
 
----
-** The metamail.el library is now obsolete.
++++
+** New function 'sxhash-equal-including-properties'.
+This is identical to 'sxhash-equal' but also accounts for string
+properties.
+
+** New function 'buffer-line-statistics'.
+This function returns some statistics about the line lengths in a buffer.
 
 ---
-** Some obsolete variable and function aliases in dbus.el have been removed.
-In Emacs 24.3, the variable 'dbus-event-error-hooks' was renamed to
-'dbus-event-error-functions' and the function
-'dbus-call-method-non-blocking' was renamed to 'dbus-call-method'.
-The old names, which were kept as obsolete aliases of the new names,
-have now been removed.
+** New function 'color-values-from-color-spec'.
+This can be used to parse RGB color specs in several formats and
+convert them to a list '(R G B)' of primary color values.
 
 ---
-** Some libraries obsolete since Emacs 23 have been removed:
-ledit.el, lmenu.el, lucid.el and old-whitespace.el.
+** New function 'custom-add-choice'.
+This function can be used by modes to add elements to the
+'choice' customization type of a variable.
 
 ---
-** Some functions and variables obsolete since Emacs 23 have been removed:
-'GOLD-map', 'advertised-xscheme-send-previous-expression',
-'allout-init', 'bookmark-jump-noselect',
-'bookmark-read-annotation-text-func', 'buffer-menu-mode-hook',
-'c-forward-into-nomenclature', 'char-coding-system-table',
-'char-valid-p', 'charset-bytes', 'charset-id', 'charset-list',
-'choose-completion-delete-max-match', 'complete-in-turn',
-'completion-base-size', 'completion-common-substring',
-'crm-minibuffer-complete', 'crm-minibuffer-complete-and-exit',
-'crm-minibuffer-completion-help', 'custom-mode', 'custom-mode-hook',
-'define-key-rebound-commands', 'define-mode-overload-implementation',
-'detect-coding-with-priority', 'dirtrack-debug',
-'dirtrack-debug-toggle', 'dynamic-completion-table',
-'easy-menu-precalculate-equivalent-keybindings',
-'epa-display-verify-result', 'epg-passphrase-callback-function',
-'erc-announced-server-name', 'erc-default-coding-system',
-'erc-process', 'erc-send-command', 'eshell-report-bug',
-'eval-next-after-load', 'exchange-dot-and-mark', 'ffap-bug',
-'ffap-submit-bug', 'ffap-version', 'file-cache-mouse-choose-completion',
-'forward-point', 'generic-char-p', 'global-highlight-changes',
-'hi-lock-face-history', 'hi-lock-regexp-history',
-'highlight-changes-active-string', 'highlight-changes-initial-state',
-'highlight-changes-passive-string',
-'icalendar--datetime-to-noneuropean-date', 'image-mode-maybe',
-'imenu-example--name-and-position', 'ispell-aspell-supports-utf8',
-'lisp-mode-auto-fill', 'locate-file-completion', 'make-coding-system',
-'menu-bar-files-menu', 'minibuffer-local-must-match-filename-map',
-'mouse-choose-completion', 'mouse-major-mode-menu',
-'mouse-popup-menubar', 'mouse-popup-menubar-stuff',
-'newsticker-groups-filename', 'nnir-swish-e-index-file',
-'nnmail-fix-eudora-headers', 'non-iso-charset-alist',
-'nonascii-insert-offset', 'nonascii-translation-table',
-'password-read-and-add', 'pre-abbrev-expand-hook', 'princ-list',
-'print-help-return-message', 'process-filter-multibyte-p',
-'read-file-name-predicate', 'remember-buffer', 'rmail-highlight-face',
-'rmail-message-filter', 'semantic-after-idle-scheduler-reparse-hooks',
-'semantic-after-toplevel-bovinate-hook',
-'semantic-before-idle-scheduler-reparse-hooks',
-'semantic-before-toplevel-bovination-hook',
-'semantic-bovinate-from-nonterminal-full',
-'semantic-bovinate-region-until-error', 'semantic-bovinate-toplevel',
-'semantic-bovination-working-type',
-'semantic-decorate-pending-decoration-hooks',
-'semantic-edits-incremental-reparse-failed-hooks',
-'semantic-eldoc-current-symbol-info', 'semantic-expand-nonterminal',
-'semantic-file-token-stream', 'semantic-find-dependency',
-'semantic-find-nonterminal', 'semantic-flex', 'semantic-flex-buffer',
-'semantic-flex-keyword-get', 'semantic-flex-keyword-p',
-'semantic-flex-keyword-put', 'semantic-flex-keywords',
-'semantic-flex-list', 'semantic-flex-make-keyword-table',
-'semantic-flex-map-keywords', 'semantic-flex-token-end',
-'semantic-flex-token-start', 'semantic-flex-token-text',
-'semantic-imenu-bucketize-type-parts',
-'semantic-imenu-expand-type-parts', 'semantic-imenu-expandable-token',
-'semantic-init-db-hooks', 'semantic-init-hooks',
-'semantic-init-mode-hooks', 'semantic-java-prototype-nonterminal',
-'semantic-nonterminal-abstract', 'semantic-nonterminal-full-name',
-'semantic-nonterminal-leaf', 'semantic-nonterminal-protection',
-'semantic-something-to-stream', 'semantic-tag-make-assoc-list',
-'semantic-token-type-parent', 'semantic-toplevel-bovine-cache',
-'semantic-toplevel-bovine-table', 'semanticdb-mode-hooks',
-'set-coding-priority', 'set-process-filter-multibyte',
-'shadows-compare-text-p', 'shell-dirtrack-toggle',
-'speedbar-navigating-speed', 'speedbar-update-speed', 't-mouse-mode',
-'term-dynamic-simple-complete', 'tooltip-hook', 'tpu-have-ispell',
-'url-generate-unique-filename', 'url-temporary-directory',
-'vc-arch-command', 'vc-default-working-revision' (variable),
-'vc-mtn-command', 'vc-revert-buffer', 'vc-workfile-version',
-'vcursor-toggle-vcursor-map', 'w32-focus-frame', 'w32-select-font',
-'wisent-lex-make-token-table'.
+** New function 'decoded-time-period'.
+It interprets a decoded time structure as a period and returns the
+equivalent period in seconds.
+
++++
+** New function 'dom-print'.
+
++++
+** New function 'dom-remove-attribute'.
 
 ---
-** Some functions and variables obsolete since Emacs 22 have been removed:
-'gnus-article-hide-pgp-hook', 'gnus-inews-mark-gcc-as-read',
-'gnus-treat-display-xface', 'gnus-treat-strip-pgp',
-'nnmail-spool-file'.
+** New function 'dns-query-asynchronous'.
+It takes the same parameters as 'dns-query', but adds a callback
+parameter.
 
-** The WHEN argument of 'make-obsolete' and related functions is mandatory.
-The use of those functions without a WHEN argument was marked obsolete
-back in Emacs 23.1.  The affected functions are: 'make-obsolete',
-'define-obsolete-function-alias', 'make-obsolete-variable',
-'define-obsolete-variable-alias'.
+** New function 'garbage-collect-maybe' to trigger GC early.
 
-** The variable 'keyboard-type' is obsolete and not dynamically scoped any 
more.
+---
+** New function 'get-locale-names'.
+This utility function returns a list of names of locales available on
+the current system.
 
-** The 'values' variable is now obsolete.
++++
+** New function 'insert-into-buffer'.
+This is like 'insert-buffer-substring', but works in the opposite
+direction.
 
 +++
-** The '&define' keyword in an Edebug specification now disables backtracking.
-The implementation was buggy, and multiple '&define' forms in an '&or'
-form should be exceedingly rare.  See the Info node "(elisp) Backtracking" in
-the Emacs Lisp reference manual for background.
+** New function 'json-available-p'.
+This predicate returns non-nil if Emacs is built with libjansson
+support, and it is available on the current system.
 
 ---
-** 'sql-*-statement-starters' are no longer user options.
-These variables describe facts about the SQL standard and
-product-specific additions.  There should be no need for users to
-customize them.
+** New function 'mail-header-parse-addresses-lax'.
+This takes a comma-separated string and returns a list of mail/name
+pairs.
 
 ---
-** Function 'lm-maintainer' is replaced with 'lm-maintainers'.
-The former is now declared obsolete.
+** New function 'mail-header-parse-address-lax'.
+Parse a string as a mail address-like string.
 
-
-* Lisp Changes in Emacs 28.1
+---
+** New function 'make-separator-line'.
+Make a string appropriate for usage as a visual separator line.
 
 +++
-*** New function 'file-name-concat'.
-This appends file name components to a directory name and returns the
-result.
+** New function 'object-intervals'.
+This function returns a copy of the list of intervals (i.e., text
+properties) in the object in question (which must either be a string
+or a buffer).
 
 +++
-*** New function 'split-string-shell-command'.
-This splits a shell command string into separate components,
-respecting quoting with single ('like this') and double ("like this")
-quotes, as well as backslash quoting (like\ this).
+** New function 'process-lines-ignore-status'.
+This is like 'process-lines', but does not signal an error if the
+return status is non-zero.  'process-lines-handling-status' has also
+been added, and takes a callback to handle the return status.
 
----
-*** ':safe' settings in 'defcustom' are now propagated to the loaddefs files.
++++
+** New function 'require-theme'.
+This function is like 'require', but searches 'custom-theme-load-path'
+instead of 'load-path'.  It can be used by Custom themes to load
+supporting Lisp files when 'require' is unsuitable.
 
 +++
 ** New function 'syntax-class-to-char'.
@@ -3354,87 +3668,76 @@ syntax descriptor (a character) given a raw syntax 
descriptor (an
 integer).
 
 +++
-** New function 'buffer-local-boundp'.
-This predicate says whether a symbol is bound in a specific buffer.
-
----
-** Emacs now attempts to test for high-rate subprocess output more fairly.
-When several subprocesses produce output simultaneously at high rate,
-Emacs will now by default attempt to service them all in a round-robin
-fashion.  Set the new variable 'process-prioritize-lower-fds' to a
-non-nil value to get back the old behavior, whereby after reading
-from a subprocess, Emacs would check for output of other subprocesses
-in a way that is likely to read from the same process again.
+** New functions 'null-device' and 'path-separator'.
+These functions return the connection local value of the respective
+variables.  This can be used for remote hosts.
 
 +++
-** New function 'sxhash-equal-including-properties'.
-This is identical to 'sxhash-equal' but accounting also for string
-properties.
+** New predicate functions 'length<', 'length>' and 'length='.
+Using these functions may be more efficient than using 'length' (if
+the length of a (long) list is being computed just to compare this
+length to a number).
 
 +++
-** '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 macro 'dlet' to dynamically bind variables.
 
 +++
-** New function 'always'.
-This is identical to 'ignore', but returns t instead.
+** New macro 'with-existing-directory'.
+This macro binds 'default-directory' to some other existing directory
+if 'default-directory' doesn't exist, and then executes the body forms.
 
 +++
-** New forms to declare how completion should happen has been added.
-'(declare (completion PREDICATE))' can be used as a general predicate
-to say whether the command should be present when completing with
-'M-x TAB'.  '(declare (modes MODE...))' can be used as a short-hand
-way of saying that the command should be present when completing from
-buffers in major modes derived from MODE..., or, if it's a minor mode,
-whether that minor mode is enabled in the current buffer.
+** New variable 'current-minibuffer-command'.
+This is like 'this-command', but it is bound recursively when entering
+the minibuffer.
 
 +++
-** The 'interactive' syntax has been extended to allow listing applicable 
modes.
-Forms like '(interactive "p" dired-mode)' can be used to annotate the
-commands as being applicable for modes derived from 'dired-mode',
-or if the mode is a minor mode, that the current buffer has that
-minor mode activated.  Note that using this form will create byte code
-that is not compatible with byte code in previous Emacs versions.
+** New variable 'inhibit-interaction' to make user prompts signal an error.
+If this is bound to something non-nil, functions like
+'read-from-minibuffer', 'read-char' (and related) will signal an
+'inhibited-interaction' error.
 
-+++
-** New buffer-local variable 'local-minor-modes'.
-This permanently buffer-local variable holds a list of currently
-enabled non-global minor modes in the current buffer (as a list of
-symbols).
+---
+** New variable 'indent-line-ignored-functions'.
+This allows modes to cycle through a set of indentation functions
+appropriate for those modes.
 
 +++
-** New variable 'global-minor-modes'.
-This variable holds a list of currently enabled global minor modes (as
-a list of symbols).
+** New variable 'print-integers-as-characters' modifies integer printing.
+If this variable is non-nil, character syntax is used for printing
+numbers when this makes sense, such as '?A' for 65.
 
 +++
-** 'define-minor-mode'  now takes an ':interactive' argument.
-This can be used for specifying which modes this minor mode is meant
-for, or to make the new minor mode non-interactive.  The default value
-is t.
+** New variable 'tty-menu-calls-mouse-position-function'.
+This controls whether 'mouse-position-function' is called by functions
+that retrieve the mouse position when that happens during TTY menu
+handling.  Lisp programs that set 'mouse-position-function' should
+also set this variable non-nil if they are compatible with the tty
+menu handling.
 
 +++
-** 'define-derived-mode' now takes an ':interactive' argument.
-This can be used to control whether the defined mode is a command
-or not, and is useful when defining commands that aren't meant to be
-used by users directly.
-
----
-** The 'easymenu' library is now preloaded.
+** New variables that hold default buffer names for shell output.
+The new constants 'shell-command-buffer-name' and
+'shell-command-buffer-name-async' store the default buffer names
+for the output of, respectively, synchronous and async shell
+commands.
 
 ---
-** New variable 'indent-line-ignored-functions'.
-This allows modes to cycle through a set of indentation functions
-appropriate for those modes.
+** New variables 'read-char-choice-use-read-key' and 'y-or-n-p-use-read-key'.
+When non-nil, then functions 'read-char-choice' and 'y-or-n-p'
+(respectively) use the function 'read-key' to read a character instead
+of using the minibuffer.
 
-** New function 'garbage-collect-maybe' to trigger GC early.
++++
+** New variable 'global-minor-modes'.
+This variable holds a list of currently enabled global minor modes (as
+a list of symbols).
 
----
-** 'defvar' detects the error of defining a variable currently lexically bound.
-Such mixes are always signs that the outer lexical binding was an
-error and should have used dynamic binding instead.
++++
+** New buffer-local variable 'local-minor-modes'.
+This permanently buffer-local variable holds a list of currently
+enabled non-global minor modes in the current buffer (as a list of
+symbols).
 
 +++
 ** New completion function 'affixation-function' to add prefix/suffix.
@@ -3447,22 +3750,54 @@ a prefix string, and a suffix string.
 It takes two arguments: a completion candidate and a 'transform' flag.
 
 +++
+** New error symbol 'minibuffer-quit'.
+Signaling it has almost the same effect as 'quit' except that it
+doesn't cause keyboard macro termination.
+
++++
+** New error 'remote-file-error', a subcategory of 'file-error'.
+It is signaled if a remote file operation fails due to internal
+reasons, and could block Emacs.  It does not replace 'file-error'
+signals for the usual cases.  Timers, process filters and process
+functions, which run remote file operations, shall protect themselves
+against this error.
+
+If such an error occurs, please report this as bug via 'M-x report-emacs-bug'.
+Until it is solved you could ignore such errors by performing
+
+    (setq debug-ignored-errors (cons 'remote-file-error debug-ignored-errors))
+
+** New macro 'named-let' added to subr-x.el.
+It provides Scheme's "named let" looping construct.
+
+---
+** Emacs now attempts to test for high-rate subprocess output more fairly.
+When several subprocesses produce output simultaneously at high rate,
+Emacs will now by default attempt to service them all in a round-robin
+fashion.  Set the new variable 'process-prioritize-lower-fds' to a
+non-nil value to get back the old behavior, whereby after reading
+from a subprocess, Emacs would check for output of other subprocesses
+in a way that is likely to read from the same process again.
+
+** 'set-process-buffer' now updates the process mark.
+The mark will be set to point to the end of the new buffer.
+
++++
+** '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.
+
++++
 ** 'read-char-from-minibuffer' and 'y-or-n-p' support 'help-form'.
 If you bind 'help-form' to a non-nil value while calling these functions,
 then pressing 'C-h' ('help-char') causes the function to evaluate 'help-form'
 and display the result.
 
----
-** New variables 'read-char-choice-use-read-key' and 'y-or-n-p-use-read-key'.
-When non-nil, then functions 'read-char-choice' and 'y-or-n-p' (respectively)
-use the function 'read-key' to read a character instead of using the 
minibuffer.
-
----
-** New user option 'use-short-answers'.
-When non-nil, the function 'y-or-n-p' is used instead of
-'yes-or-no-p'.  This eliminates the need to define an alias that maps
-one to another in the init file.  The same user option also controls
-whether the function 'read-answer' accepts short answers.
++++
+** 'read-number' now has its own history variable.
+Additionally, the function now accepts a HIST argument which can be
+used to specify a custom history variable.
 
 +++
 ** 'set-window-configuration' now takes two optional parameters,
@@ -3471,10 +3806,9 @@ non-nil, instructs the function not to select the frame 
recorded in
 the configuration.  The second prevents the current minibuffer being
 replaced by the one stored in the configuration.
 
-+++
-** 'define-globalized-minor-mode' now takes a ':predicate' parameter.
-This can be used to control which major modes the minor mode should be
-used in.
+---
+** 'count-windows' now takes an optional parameter ALL-FRAMES.
+The semantics are as with 'walk-windows'.
 
 +++
 ** 'truncate-string-ellipsis' now uses '…' by default.
@@ -3483,51 +3817,9 @@ argument ELLIPSIS, will now indicate truncation using 
'…' when
 the selected frame can display it, and using "..." otherwise.
 
 +++
-** 'string-width' now accepts two optional arguments FROM and TO.
-This allows calculating the width of a substring without consing a
-new string.
-
-+++
-** New command 'make-directory-autoloads'.
-This does the same as the old command 'update-directory-autoloads',
-but has different semantics: Instead of passing in the output file via
-the dynamically bound 'generated-autoload-file' variable, the output
-file is now a explicit parameter.
-
-+++
-** New function 'string-search'.
-This function takes two string parameters and returns the position of
-the first instance of the former string in the latter.
-
-+++
-** New function 'string-replace'.
-This function works along the line of 'replace-regexp-in-string', but
-matching on strings instead of regexps, and does not change the global
-match state.
-
-+++
-** New function 'process-lines-ignore-status'.
-This is like 'process-lines', but does not signal an error if the
-return status is non-zero.  'process-lines-handling-status' has also
-been added, and takes a callback to handle the return status.
-
----
-** 'ascii' is now a coding system alias for 'us-ascii'.
-
-+++
-** New function 'file-name-with-extension'.
-This function allows a canonical way to set/replace the extension of a
-file name.
-
-+++
-** New function 'file-backup-file-names'.
-This function returns the list of file names of all the backup files
-of its file argument.
-
-+++
-** New utility function 'directory-empty-p'.
-This predicate tests whether a given file name is an accessible
-directory and whether it contains no other directories or files.
+** 'string-width' now accepts two optional arguments FROM and TO.
+This allows calculating the width of a substring without consing a
+new string.
 
 +++
 ** 'directory-files' now takes an additional COUNT parameter.
@@ -3537,7 +3829,7 @@ first COUNT file names that match the expression.  The 
same COUNT
 parameter has been added to 'directory-files-and-attributes'.
 
 +++
-** The 'count-lines' function now takes an optional parameter to
+** 'count-lines' now takes an optional parameter to
 ignore invisible lines.
 
 ---
@@ -3546,86 +3838,19 @@ Originally, 'count-words' would stop counting at the 
first field
 boundary it encountered; now it keeps counting all the way to the
 region's (or buffer's) end.
 
----
-** New function 'custom-add-choice'.
-This function can be used by modes to add elements to the
-'choice' customization type of a variable.
-
-+++
-** New function 'require-theme'.
-This function is like 'require', but searches 'custom-theme-load-path'
-instead of 'load-path'.  It can be used by Custom themes to load
-supporting Lisp files when 'require' is unsuitable.
-
-+++
-** New function 'file-modes-number-to-symbolic' to convert a numeric
-file mode specification into symbolic form.
-
-** New macro 'dlet' to dynamically bind variables.
-
-** The variable 'force-new-style-backquotes' has been removed.
-This removes the final remaining trace of old-style backquotes.
-
-** Mode Lines
-
-+++
-*** New user options to control the line/column numbers in the mode line.
-'mode-line-position-line-format' is the line number format (when
-'line-number-mode' is on), 'mode-line-position-column-format' is
-the column number format (when 'column-number-mode' is on), and
-'mode-line-position-column-line-format' is the combined format (when
-both modes are on).
-
-+++
-*** New user option 'mode-line-compact'.
-If non-nil, repeating spaces are compressed into a single space.  If
-'long', this is only done when the mode line is longer than the
-current window width (in characters).
-
 +++
-*** 'global-mode-string' constructs should end with a space.
-This was previously not formalized, which led to combinations of modes
-displaying data "smushed together" on the mode line.
-
-** Changes in handling dynamic modules
-
-*** The module header 'emacs-module.h' now contains type aliases
-'emacs_function' and 'emacs_finalizer' for module functions and
-finalizers, respectively.
-
-*** Module functions can now be made interactive.
-Use 'make_interactive' to give a module function an interactive
-specification.
-
-*** Module functions can now install an optional finalizer that is
-called when the function object is garbage-collected.  Use
-'set_function_finalizer' to set the finalizer and
-'get_function_finalizer' to retrieve it.
-
-*** Modules can now open a channel to an existing pipe process using
-the new module function 'open_channel'.  Modules can use this
-functionality to asynchronously send data back to Emacs.
-
-*** A new module API 'make_unibyte_string' is provided.
-It can be used to create Lisp strings with arbitrary byte sequences
-(a.k.a. "raw bytes").
-
-** 'file-modes', 'set-file-modes', and 'set-file-times' now have an
-optional argument specifying whether to follow symbolic links.
-
-** 'parse-time-string' can now parse ISO 8601 format strings,
-such as "2020-01-15T16:12:21-08:00".
-
----
-** The new function 'decoded-time-period' has been added.
-It interprets a decoded time structure as a period and returns the
-equivalent period in seconds.
+** File-related APIs can optionally follow symlinks.
+The functions 'file-modes', 'set-file-modes', and 'set-file-times' now
+have an optional argument specifying whether to follow symbolic links.
 
 +++
-** The new function 'dom-remove-attribute' has been added.
+** 'format-seconds' can now be used for sub-second times.
+The new optional "," parameter has been added, and
+'(format-seconds "%mm %,1ss" 66.4)' will now result in "1m 6.4s".
 
 +++
-** The new function 'dom-print' has been added.
+** 'parse-time-string' can now parse ISO 8601 format strings.
+These have the format like "2020-01-15T16:12:21-08:00".
 
 ---
 ** 'make-network-process', 'make-serial-process' ':coding' behavior change.
@@ -3652,17 +3877,8 @@ server based on that greeting.
 +++
 ** 'open-gnutls-stream' now also accepts a ':coding' argument.
 
-+++
-** New user option 'process-file-return-signal-string'.
-It controls, whether 'process-file' returns a string when a remote
-process is interrupted by a signal.
-
-+++
-** The behavior of 'format-spec' is now closer to that of 'format'.
-In order for the two functions to behave more consistently,
-'format-spec' now pads and truncates based on string width rather than
-length, and also supports format specifications that include a
-truncating precision field, such as "%.2a".
+---
+** 'process-attributes' now works under OpenBSD, too.
 
 +++
 ** 'format-spec' now takes an optional SPLIT parameter.
@@ -3670,94 +3886,85 @@ If non-nil, 'format-spec' will split the resulting 
string into a list
 of strings, based on where the format specs (and expansions) were.
 
 ---
-** New function 'color-values-from-color-spec'.
-This can be used to parse RGB color specs in several formats and
-convert them to a list '(R G B)' of primary color values.
+** 'unload-feature' now also tries to undo additions to buffer-local hooks.
 
 ---
-** User option 'uniquify-buffer-name-style' can now be a function.
-This user option can be one of the predefined styles or a function to
-personalize the uniquified buffer name.
+** 'while-no-input-ignore-events' accepts more special events.
+The special events 'dbus-event' and 'file-notify' are now ignored in
+'while-no-input' when added to this variable.
 
-+++
-** New variable 'tty-menu-calls-mouse-position-function'.
-This controls whether 'mouse-position-function' is called by functions
-that retrieve the mouse position when that happens during TTY menu
-handling.  Lisp programs that set 'mouse-position-function' should
-also set this variable non-nil if they are compatible with the tty
-menu handling.
+---
+** 'start-process-shell-command' and 'start-file-process-shell-command'
+do not support the old calling conventions any longer.
 
 +++
-** 'inhibit-nul-byte-detection' is renamed to 'inhibit-null-byte-detection'.
-
-** Byte compiler
+** The 'uniquify' argument in 'auto-save-file-name-transforms' can be a symbol.
+If this symbol is one of the members of 'secure-hash-algorithms',
+Emacs constructs the nondirectory part of the auto-save file name by
+applying that 'secure-hash' to the buffer file name.  This avoids any
+risk of excessively long file names.
 
-+++
-*** New byte-compiler check for missing dynamic variable declarations.
-It is meant as an (experimental) aid for converting Emacs Lisp code
-to lexical binding, where dynamic (special) variables bound in one
-file can affect code in another.  For details, see the manual section
-"(elisp) Converting to Lexical Binding".
+---
+** File names checked for null bytes.
+Functions operating on local file names now check that the file names
+don't contain any NUL bytes.  This avoids subtle bugs caused by
+silently using only the part of the file name until the first NUL byte.
 
 +++
-*** 'byte-recompile-directory' can now compile symlinked ".el" files.
-This is achieved by giving a non-nil FOLLOW-SYMLINKS parameter.
+** New user option 'process-file-return-signal-string'.
+It controls, whether 'process-file' returns a string when a remote
+process is interrupted by a signal.
 
-*** The byte-compiler now warns about too wide documentation strings.
-By default, it will warn if a documentation string is wider than the
-largest of 80 characters or 'fill-column'.  This is controlled by the
-new user option 'byte-compile-docstring-max-column'.
+** EIEIO Changes
 
 +++
-*** 'byte-compile-file' optional argument LOAD is now obsolete.
-To load the file after byte-compiling, add a call to 'load' from Lisp
-or use 'M-x emacs-lisp-byte-compile-and-load' interactively.
+*** The macro 'oref-default' can now be used with 'setf'.
+It is now defined as a generalized variable that can be used with
+'setf' to modify the value stored in a given class slot.
 
 ---
-** 'unload-feature' now also tries to undo additions to buffer-local hooks.
+*** 'form' in '(eql form)' specializers in 'cl-defmethod' is now evaluated.
+This corresponds to the behavior of defmethod in Common Lisp Object System.
+For compatibility, '(eql SYMBOL)' does not evaluate SYMBOL, for now.
 
----
-** Some functions are no longer considered safe by 'unsafep':
-'replace-regexp-in-string', 'catch', 'throw', 'error', 'signal'
-and 'play-sound-file'.
+** D-Bus
 
 +++
-** New variable 'print-integers-as-characters' modifies integer printing.
-If this variable is non-nil, character syntax is used for printing
-numbers when this makes sense, such as '?A' for 65.
+*** Property values can be typed explicitly.
+'dbus-register-property' and 'dbus-set-property' accept now optional
+type symbols.  Both functions propagate D-Bus errors.
 
 +++
-** New error 'remote-file-error', a subcategory of 'file-error'.
-It is signaled if a remote file operation fails due to internal
-reasons, and could block Emacs.  It does not replace 'file-error'
-signals for the usual cases.  Timers, process filters and process
-functions, which run remote file operations, shall protect themselves
-against this error.
+*** Registered properties can have the new access type ':write'.
 
-If such an error occurs, please report this as bug via 'M-x report-emacs-bug'.
-Until it is solved you could ignore such errors by performing
++++
+*** In case of problems, handlers can emit proper D-Bus error messages now.
 
-    (setq debug-ignored-errors (cons 'remote-file-error debug-ignored-errors))
++++
+*** D-Bus errors, which have been converted from incoming D-Bus error
+messages, contain the error name of that message now.
 
 +++
-** The error 'ftp-error' belongs also to category 'remote-file-error'.
+*** D-Bus messages can be monitored with the new command 'dbus-monitor'.
 
 +++
-** Buffers can now be created with certain hooks disabled.
-The functions 'get-buffer-create' and 'generate-new-buffer' accept a
-new optional argument INHIBIT-BUFFER-HOOKS.  If non-nil, the new
-buffer does not run the hooks 'kill-buffer-hook',
-'kill-buffer-query-functions', and 'buffer-list-update-hook'.  This
-avoids slowing down internal or temporary buffers that are never
-presented to users or passed on to other applications.
+*** D-Bus events have changed their internal structure.
+They carry now the destination and the error-name of an event.  They
+also keep the type information of their arguments.  Use the
+'dbus-event-*' accessor functions.
 
 ---
-** 'start-process-shell-command' and 'start-file-process-shell-command'
-do not support the old calling conventions any longer.
+** 'text-scale-mode' can now adjust font size of the header line.
+When the new buffer local variable 'text-scale-remap-header-line'
+is non-nil, 'text-scale-adjust' will also scale the text in the header
+line when displaying that buffer.
 
-** Functions operating on local file names now check that the file names
-don't contain any NUL bytes.  This avoids subtle bugs caused by
-silently using only the part of the file name until the first NUL byte.
+This is useful for major modes that arrange their display in a tabular
+form below the header line.  It is enabled by default in
+'tabulated-list-mode' and its derived modes.
+
+---
+** 'ascii' is now a coding system alias for 'us-ascii'.
 
 ** New coding-systems for EBCDIC variants.
 New coding-systems 'ibm256', 'ibm273', 'ibm274', 'ibm277', 'ibm278',
@@ -3768,63 +3975,20 @@ locales.  They are also available as aliases 
'ebcdic-cp-*' (e.g.,
 'cp278' for 'ibm278').  There are also new charsets 'ibm2xx' to
 support these coding-systems.
 
----
-** 'while-no-input-ignore-events' accepts more special events.
-The special events 'dbus-event' and 'file-notify' are now ignored in
-'while-no-input' when added to this variable.
-
-+++
-** 'condition-case' now allows for a success handler.
-It is written as '(:success BODY...)' where BODY is executed
-whenever the protected form terminates without error, with the
-specified variable bound to the the value of the protected form.
-
 +++
-** 'The 'uniquify' argument in 'auto-save-file-name-transforms' can be a 
symbol.
-If this symbol is one of the members of 'secure-hash-algorithms',
-Emacs constructs the nondirectory part of the auto-save file name by
-applying that 'secure-hash' to the buffer file name.  This avoids any
-risk of excessively long file names.
-
----
-** New user option 'etags-xref-prefer-current-file'.
-When non-nil, matches for identifiers in the file visited by the
-current buffer will be shown first in the "*xref*" buffer.
+** New 'Bindat type expression' description language.
+This new system is provided by the new macro 'bindat-type' and
+obsoletes the old data layout specifications.  It supports
+arbitrary-size integers, recursive types, and more.  See the Info node
+"(elisp) Byte Packing" in the ELisp manual for more details.
 
 
 * Changes in Emacs 28.1 on Non-Free Operating Systems
 
----
-** On macOS, Xwidget is now supported.
-If Emacs was built with xwidget support, you can access the embedded
-webkit browser with 'M-x xwidget-webkit-browse-url'.  Viewing two
-instances of xwidget webkit is not supported.
-
-*** Downloading files from xwidget-webkit is now supported.
-The new variable 'xwidget-webkit-download-dir' says where to download to.
-
-*** New functions for xwidget-webkit mode
-'xwidget-webkit-clone-and-split-below',
-'xwidget-webkit-clone-and-split-right'.
-
-*** New variable 'xwidget-webkit-enable-plugins'.
-
-+++
-** On macOS, Emacs can now load dynamic modules with a ".dylib" suffix.
-'module-file-suffix' now has the value ".dylib" on macOS, but the
-".so" suffix is supported as well.
-
-+++
-** On MS-Windows, Emacs can now toggle the IME.
-A new function 'w32-set-ime-open-status' can now be used to disable
-and enable the MS-Windows native Input Method Editor (IME) at run
-time.  A companion function 'w32-get-ime-open-status' returns the
-current IME activation status.
-
 +++
 ** On MS-Windows, Emacs can now use the native image API to display images.
 Emacs can now use the MS-Windows GDI+ library to load and display
-images in JPEG, PNG, GIF and TIFF formats.  This support is enabled
+images in JPEG, PNG, GIF and TIFF formats.  This support is available
 unless Emacs was configured '--without-native-image-api'.
 
 This feature is experimental, and needs to be turned on to be used.
@@ -3832,14 +3996,51 @@ To turn this on, set the variable 
'w32-use-native-image-API' to a
 non-nil value.  Please report any bugs you find while using the native
 image API via 'M-x report-emacs-bug'.
 
----
-** The user option 'make-pointer-invisible' is now honored on macOS.
++++
+** On MS-Windows, Emacs can now toggle the IME.
+A new function 'w32-set-ime-open-status' can now be used to disable
+and enable the MS-Windows native Input Method Editor (IME) at run
+time.  A companion function 'w32-get-ime-open-status' returns the
+current IME activation status.
 
 --
 ** On macOS, 's-<left>' and 's-<right>' are now bound to
 'move-beginning-of-line' and 'move-end-of-line' respectively.  The commands
 to select previous/next frame are still bound to 's-~' and 's-`'.
 
++++
+** On macOS, Emacs can now load dynamic modules with a ".dylib" suffix.
+'module-file-suffix' now has the value ".dylib" on macOS, but the
+".so" suffix is supported as well.
+
+---
+** On macOS, the user option 'make-pointer-invisible' is now honored.
+
+---
+** On macOS, Xwidget is now supported.
+If Emacs was built with xwidget support, you can access the embedded
+webkit browser with 'M-x xwidget-webkit-browse-url'.  Viewing two
+instances of xwidget webkit is not supported.
+
+---
+*** Downloading files from xwidget-webkit is now supported.
+The new variable 'xwidget-webkit-download-dir' says where to download to.
+
+---
+*** New command 'xwidget-webkit-clone-and-split-below'.
+*** New command 'xwidget-webkit-clone-and-split-right'.
+These are used in 'xwidget-webkit-mode'.
+
+---
+*** New variable 'xwidget-webkit-enable-plugins'.
+If non-nil, enable plugins in xwidget.  (This is only available on
+macOS.)
+
++++
+** New macOS Contacts back-end for EUDC.
+This backend works on newer versions of macOS and is generally
+preferred over the eudcb-mab.el backend.
+
 
 ----------------------------------------------------------------------
 This file is part of GNU Emacs.
diff --git a/etc/PROBLEMS b/etc/PROBLEMS
index 15e34ea..f904187 100644
--- a/etc/PROBLEMS
+++ b/etc/PROBLEMS
@@ -2660,6 +2660,16 @@ If you do, please send it to bug-gnu-emacs@gnu.org so we 
can list it here.
 
 Libxpm is available for macOS as part of the XQuartz project.
 
+** Synthetic fonts on macOS
+
+Synthetic bold looks thinner if the background is darker than the
+foreground and font smoothing is turned on.  In such cases, you can
+turn off synthetic bold for particular fonts and use overstriking
+instead by customizing the variable 'face-ignored-fonts'.  For
+instance, if the problem is with the Monaco font, you could put
+something like the following in your init file:
+
+(push "\\`-[^-]*-monaco-bold-" face-ignored-fonts)
 
 * Build-time problems
 
diff --git a/etc/TODO b/etc/TODO
index 1d6824c..8fe698b 100644
--- a/etc/TODO
+++ b/etc/TODO
@@ -1538,6 +1538,14 @@ cannot represent in Unicode.
 
 *** Performance
 
+**** Make the implementation of markers more efficient
+Markers are implemented as a non-sorted singly linked list of markers.
+This makes them scale badly when thousands of markers are created in a
+buffer for some purpose, because some low-level primitives in Emacs
+traverse the markers' list (e.g., when converting between character
+and byte positions), and also because searching for a marker (e.g.,
+with 'buffer-has-markers-at') becomes very slow.
+
 **** Explore whether overlay-recenter can cure overlays performance problems
 
 **** Cache schemas.  Need to have list of files and mtimes
diff --git a/etc/facemenu-removal.txt b/etc/facemenu-removal.txt
deleted file mode 100644
index 9a969df..0000000
--- a/etc/facemenu-removal.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-`facemenu-keymap' (normally bound to `M-o') has been disabled.
-==============================================================
-
-We've disabled the normal `M-o' keymap for a month (until March the
-10th, 2021) in the development version of Emacs to see whether anybody
-uses this feature.
-
-If the removal of this key binding doesn't annoy too many people, the
-plan is to then leave the it unbound, for usage by third-party
-packages and users.
-
-If you wish to restore the binding during the trial period, you can
-put the following in your .emacs file:
-
-(facemenu-keymap-restore)
-
-After the trial period is over, the function will be removed.
-
-If you wish to protest the removal of the `M-o' key binding, please
-send your thoughts to the emacs-devel@gnu.org mailing list.
diff --git a/etc/publicsuffix.txt b/etc/publicsuffix.txt
index 1ede2b9..986f110 100644
--- a/etc/publicsuffix.txt
+++ b/etc/publicsuffix.txt
@@ -734,7 +734,6 @@ gouv.ci
 // cl : https://www.nic.cl
 // Confirmed by .CL registry <hsalgado@nic.cl>
 cl
-aprendemas.cl
 co.cl
 gob.cl
 gov.cl
@@ -4594,15 +4593,17 @@ gob.mx
 edu.mx
 net.mx
 
-// my : http://www.mynic.net.my/
+// my : http://www.mynic.my/
+// Available strings: https://mynic.my/resources/domains/buying-a-domain/
 my
+biz.my
 com.my
-net.my
-org.my
-gov.my
 edu.my
+gov.my
 mil.my
 name.my
+net.my
+org.my
 
 // mz : http://www.uem.mz/
 // Submitted by registry <antonio@uem.mz>
@@ -6085,8 +6086,10 @@ biz.ss
 com.ss
 edu.ss
 gov.ss
+me.ss
 net.ss
 org.ss
+sch.ss
 
 // st : http://www.nic.st/html/policyrules/
 st
@@ -6095,7 +6098,6 @@ com.st
 consulado.st
 edu.st
 embaixada.st
-gov.st
 mil.st
 net.st
 org.st
@@ -6712,9 +6714,10 @@ mil.vc
 edu.vc
 
 // ve : https://registro.nic.ve/
-// Submitted by registry
+// Submitted by registry nic@nic.ve and nicve@conatel.gob.ve
 ve
 arts.ve
+bib.ve
 co.ve
 com.ve
 e12.ve
@@ -6726,7 +6729,9 @@ info.ve
 int.ve
 mil.ve
 net.ve
+nom.ve
 org.ve
+rar.ve
 rec.ve
 store.ve
 tec.ve
@@ -6805,6 +6810,9 @@ yt
 // xn--90ae ("bg", Bulgarian) : BG
 бг
 
+// xn--mgbcpq6gpa1a ("albahrain", Arabic) : BH
+البحرين
+
 // xn--90ais ("bel", Belarusian/Russian Cyrillic) : BY
 // Operated by .by registry
 бел
@@ -6937,6 +6945,9 @@ yt
 // xn--80ao21a ("Kaz", Kazakh) : KZ
 қаз
 
+// xn--q7ce6a ("Lao", Lao) : LA
+ລາວ
+
 // xn--fzc2c9e2c ("Lanka", Sinhalese-Sinhala) : LK
 // https://nic.lk
 ලංකා
@@ -7062,7 +7073,13 @@ yt
 xxx
 
 // ye : http://www.y.net.ye/services/domain_name.htm
-*.ye
+ye
+com.ye
+edu.ye
+gov.ye
+net.ye
+mil.ye
+org.ye
 
 // za : https://www.zadna.org.za/content/page/domain-information/
 ac.za
@@ -7111,7 +7128,7 @@ org.zw
 
 // newGTLDs
 
-// List of new gTLDs imported from 
https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 
2020-11-30T20:26:10Z
+// List of new gTLDs imported from 
https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 
2021-08-19T15:13:52Z
 // This list is auto-generated, don't edit it manually.
 // aaa : 2015-02-26 American Automobile Association, Inc.
 aaa
@@ -7137,7 +7154,7 @@ abc
 // able : 2015-06-25 Able Inc.
 able
 
-// abogado : 2014-04-24 Minds + Machines Group Limited
+// abogado : 2014-04-24 Registry Services, LLC
 abogado
 
 // abudhabi : 2015-07-30 Abu Dhabi Systems and Information Centre
@@ -7335,7 +7352,7 @@ autos
 // avianca : 2015-01-08 Avianca Holdings S.A.
 avianca
 
-// aws : 2015-06-25 Amazon Registry Services, Inc.
+// aws : 2015-06-25 AWS Registry LLC
 aws
 
 // axa : 2013-12-19 AXA Group Operations SAS
@@ -7413,7 +7430,7 @@ beats
 // beauty : 2015-12-03 XYZ.COM LLC
 beauty
 
-// beer : 2014-01-09 Minds + Machines Group Limited
+// beer : 2014-01-09 Registry Services, LLC
 beer
 
 // bentley : 2014-12-18 Bentley Motors Limited
@@ -7530,7 +7547,7 @@ bridgestone
 // broadway : 2014-12-22 Celebrate Broadway, Inc.
 broadway
 
-// broker : 2014-12-11 Dotbroker Registry Limited
+// broker : 2014-12-11 Dog Beach, LLC
 broker
 
 // brother : 2015-01-29 Brother Industries, Ltd.
@@ -7623,15 +7640,12 @@ careers
 // cars : 2014-11-13 XYZ.COM LLC
 cars
 
-// casa : 2013-11-21 Minds + Machines Group Limited
+// casa : 2013-11-21 Registry Services, LLC
 casa
 
 // case : 2015-09-03 CNH Industrial N.V.
 case
 
-// caseih : 2015-09-03 CNH Industrial N.V.
-caseih
-
 // cash : 2014-03-06 Binky Moon, LLC
 cash
 
@@ -7656,9 +7670,6 @@ cbre
 // cbs : 2015-08-06 CBS Domains Inc.
 cbs
 
-// ceb : 2015-04-09 The Corporate Executive Board Company
-ceb
-
 // center : 2013-11-07 Binky Moon, LLC
 center
 
@@ -7671,7 +7682,7 @@ cern
 // cfa : 2014-08-28 CFA Institute
 cfa
 
-// cfd : 2014-12-11 DotCFD Registry Limited
+// cfd : 2014-12-11 ShortDot SA
 cfd
 
 // chanel : 2015-04-09 Chanel International B.V.
@@ -7749,7 +7760,7 @@ clothing
 // cloud : 2015-04-16 Aruba PEC S.p.A.
 cloud
 
-// club : 2013-11-08 .CLUB DOMAINS, LLC
+// club : 2013-11-08 Registry Services, LLC
 club
 
 // clubmed : 2015-06-25 Club Méditerranée S.A.
@@ -7806,7 +7817,7 @@ contact
 // contractors : 2013-09-10 Binky Moon, LLC
 contractors
 
-// cooking : 2013-11-21 Minds + Machines Group Limited
+// cooking : 2013-11-21 Registry Services, LLC
 cooking
 
 // cookingchannel : 2015-07-02 Lifestyle Domain Holdings, Inc.
@@ -7839,7 +7850,7 @@ credit
 // creditcard : 2014-03-20 Binky Moon, LLC
 creditcard
 
-// creditunion : 2015-01-22 CUNA Performance Resources, LLC
+// creditunion : 2015-01-22 DotCooperation LLC
 creditunion
 
 // cricket : 2014-10-09 dot Cricket Limited
@@ -7896,7 +7907,7 @@ day
 // dclk : 2014-11-20 Charleston Road Registry Inc.
 dclk
 
-// dds : 2015-05-07 Minds + Machines Group Limited
+// dds : 2015-05-07 Registry Services, LLC
 dds
 
 // deal : 2015-06-25 Amazon Registry Services, Inc.
@@ -7935,7 +7946,7 @@ dentist
 // desi : 2013-11-14 Desi Networks LLC
 desi
 
-// design : 2014-11-07 Top Level Design, LLC
+// design : 2014-11-07 Registry Services, LLC
 design
 
 // dev : 2014-10-16 Charleston Road Registry Inc.
@@ -8124,7 +8135,7 @@ farm
 // farmers : 2015-07-09 Farmers Insurance Exchange
 farmers
 
-// fashion : 2014-07-03 Minds + Machines Group Limited
+// fashion : 2014-07-03 Registry Services, LLC
 fashion
 
 // fast : 2014-12-18 Amazon Registry Services, Inc.
@@ -8175,10 +8186,10 @@ firmdale
 // fish : 2013-12-12 Binky Moon, LLC
 fish
 
-// fishing : 2013-11-21 Minds + Machines Group Limited
+// fishing : 2013-11-21 Registry Services, LLC
 fishing
 
-// fit : 2014-11-07 Minds + Machines Group Limited
+// fit : 2014-11-07 Registry Services, LLC
 fit
 
 // fitness : 2014-03-06 Binky Moon, LLC
@@ -8217,7 +8228,7 @@ football
 // ford : 2014-11-13 Ford Motor Company
 ford
 
-// forex : 2014-12-11 Dotforex Registry Limited
+// forex : 2014-12-11 Dog Beach, LLC
 forex
 
 // forsale : 2014-05-22 Dog Beach, LLC
@@ -8256,10 +8267,7 @@ ftr
 // fujitsu : 2015-07-30 Fujitsu Limited
 fujitsu
 
-// fujixerox : 2015-07-23 Xerox DNHC LLC
-fujixerox
-
-// fun : 2016-01-14 DotSpace Inc.
+// fun : 2016-01-14 Radix FZC
 fun
 
 // fund : 2014-03-20 Binky Moon, LLC
@@ -8295,7 +8303,7 @@ games
 // gap : 2015-07-31 The Gap, Inc.
 gap
 
-// garden : 2014-06-26 Minds + Machines Group Limited
+// garden : 2014-06-26 Registry Services, LLC
 garden
 
 // gay : 2019-05-23 Top Level Design, LLC
@@ -8511,13 +8519,13 @@ homesense
 // honda : 2014-12-18 Honda Motor Co., Ltd.
 honda
 
-// horse : 2013-11-21 Minds + Machines Group Limited
+// horse : 2013-11-21 Registry Services, LLC
 horse
 
 // hospital : 2016-10-20 Binky Moon, LLC
 hospital
 
-// host : 2014-04-17 DotHost Inc.
+// host : 2014-04-17 Radix FZC
 host
 
 // hosting : 2014-05-29 UNR Corp.
@@ -8640,9 +8648,6 @@ itau
 // itv : 2015-07-09 ITV Services Limited
 itv
 
-// iveco : 2015-09-03 CNH Industrial N.V.
-iveco
-
 // jaguar : 2014-11-13 Jaguar Land Rover Ltd
 jaguar
 
@@ -8715,6 +8720,9 @@ kfh
 // kia : 2015-07-09 KIA MOTORS CORPORATION
 kia
 
+// kids : 2021-08-13 DotKids Foundation Limited
+kids
+
 // kim : 2013-09-23 Afilias Limited
 kim
 
@@ -8793,7 +8801,7 @@ latino
 // latrobe : 2014-06-16 La Trobe University
 latrobe
 
-// law : 2015-01-22 LW TLD Limited
+// law : 2015-01-22 Registry Services, LLC
 law
 
 // lawyer : 2014-03-20 Dog Beach, LLC
@@ -8922,10 +8930,7 @@ ltda
 // lundbeck : 2015-08-06 H. Lundbeck A/S
 lundbeck
 
-// lupin : 2014-11-07 LUPIN LIMITED
-lupin
-
-// luxe : 2014-01-09 Minds + Machines Group Limited
+// luxe : 2014-01-09 Registry Services, LLC
 luxe
 
 // luxury : 2013-10-17 Luxury Partners, LLC
@@ -8964,7 +8969,7 @@ market
 // marketing : 2013-11-07 Binky Moon, LLC
 marketing
 
-// markets : 2014-12-11 Dotmarkets Registry Limited
+// markets : 2014-12-11 Dog Beach, LLC
 markets
 
 // marriott : 2014-10-09 Marriott Worldwide Corporation
@@ -9093,6 +9098,9 @@ mtn
 // mtr : 2015-03-12 MTR Corporation Limited
 mtr
 
+// music : 2021-05-04 DotMusic Limited
+music
+
 // mutual : 2015-04-02 Northwestern Mutual MU TLD Registry, LLC
 mutual
 
@@ -9102,9 +9110,6 @@ nab
 // nagoya : 2013-10-24 GMO Registry, Inc.
 nagoya
 
-// nationwide : 2015-07-23 Nationwide Mutual Insurance Company
-nationwide
-
 // natura : 2015-03-12 NATURA COSMÉTICOS S.A.
 natura
 
@@ -9132,9 +9137,6 @@ neustar
 // new : 2014-01-30 Charleston Road Registry Inc.
 new
 
-// newholland : 2015-09-03 CNH Industrial N.V.
-newholland
-
 // news : 2014-12-18 Dog Beach, LLC
 news
 
@@ -9207,7 +9209,7 @@ nyc
 // obi : 2014-09-25 OBI Group Holding SE & Co. KGaA
 obi
 
-// observer : 2015-04-30 Top Level Spectrum, Inc.
+// observer : 2015-04-30 Dog Beach, LLC
 observer
 
 // off : 2015-07-23 Johnson Shareholdings, Inc.
@@ -9243,12 +9245,9 @@ ong
 // onl : 2013-09-16 iRegistry GmbH
 onl
 
-// online : 2015-01-15 DotOnline Inc.
+// online : 2015-01-15 Radix FZC
 online
 
-// onyourside : 2015-07-23 Nationwide Mutual Insurance Company
-onyourside
-
 // ooo : 2014-01-09 INFIBEAM AVENUES LIMITED
 ooo
 
@@ -9402,7 +9401,7 @@ pramerica
 // praxi : 2013-12-05 Praxi S.p.A.
 praxi
 
-// press : 2014-04-03 DotPress Inc.
+// press : 2014-04-03 Radix FZC
 press
 
 // prime : 2015-06-25 Amazon Registry Services, Inc.
@@ -9474,7 +9473,7 @@ realestate
 // realtor : 2014-05-29 Real Estate Domains LLC
 realtor
 
-// realty : 2015-03-19 Fegistry, LLC
+// realty : 2015-03-19 Dog Beach, LLC
 realty
 
 // recipes : 2013-10-17 Binky Moon, LLC
@@ -9564,7 +9563,7 @@ rocher
 // rocks : 2013-11-14 Dog Beach, LLC
 rocks
 
-// rodeo : 2013-12-19 Minds + Machines Group Limited
+// rodeo : 2013-12-19 Registry Services, LLC
 rodeo
 
 // rogers : 2015-08-06 Rogers Communications Canada Inc.
@@ -9642,7 +9641,7 @@ saxo
 // sbi : 2015-03-12 STATE BANK OF INDIA
 sbi
 
-// sbs : 2014-11-07 SPECIAL BROADCASTING SERVICE CORPORATION
+// sbs : 2014-11-07 ShortDot SA
 sbs
 
 // sca : 2014-03-13 SVENSKA CELLULOSA AKTIEBOLAGET SCA (publ)
@@ -9765,7 +9764,7 @@ sina
 // singles : 2013-08-27 Binky Moon, LLC
 singles
 
-// site : 2015-01-15 DotSite Inc.
+// site : 2015-01-15 Radix FZC
 site
 
 // ski : 2015-04-09 Afilias Limited
@@ -9825,7 +9824,7 @@ soy
 // spa : 2019-09-19 Asia Spa and Wellness Promotion Council Limited
 spa
 
-// space : 2014-04-03 DotSpace Inc.
+// space : 2014-04-03 Radix FZC
 space
 
 // sport : 2017-11-16 Global Association of International Sports Federations 
(GAISF)
@@ -9834,9 +9833,6 @@ sport
 // spot : 2015-02-26 Amazon Registry Services, Inc.
 spot
 
-// spreadbetting : 2014-12-11 Dotspreadbetting Registry Limited
-spreadbetting
-
 // srl : 2015-05-07 InterNetX, Corp
 srl
 
@@ -9867,7 +9863,7 @@ stockholm
 // storage : 2014-12-22 XYZ.COM LLC
 storage
 
-// store : 2015-04-09 DotStore Inc.
+// store : 2015-04-09 Radix FZC
 store
 
 // stream : 2016-01-08 dot Stream Limited
@@ -9894,7 +9890,7 @@ supply
 // support : 2013-10-24 Binky Moon, LLC
 support
 
-// surf : 2014-01-09 Minds + Machines Group Limited
+// surf : 2014-01-09 Registry Services, LLC
 surf
 
 // surgery : 2014-03-20 Binky Moon, LLC
@@ -9957,7 +9953,7 @@ tdk
 // team : 2015-03-05 Binky Moon, LLC
 team
 
-// tech : 2015-01-30 Personals TLD Inc.
+// tech : 2015-01-30 Radix FZC
 tech
 
 // technology : 2013-09-13 Binky Moon, LLC
@@ -9984,7 +9980,7 @@ theatre
 // tiaa : 2015-07-23 Teachers Insurance and Annuity Association of America
 tiaa
 
-// tickets : 2015-02-05 Accent Media Limited
+// tickets : 2015-02-05 XYZ.COM LLC
 tickets
 
 // tienda : 2013-11-14 Binky Moon, LLC
@@ -10050,7 +10046,7 @@ toys
 // trade : 2014-01-23 Elite Registry Limited
 trade
 
-// trading : 2014-12-11 Dottrading Registry Limited
+// trading : 2014-12-11 Dog Beach, LLC
 trading
 
 // training : 2013-11-07 Binky Moon, LLC
@@ -10101,7 +10097,7 @@ unicom
 // university : 2014-03-06 Binky Moon, LLC
 university
 
-// uno : 2013-09-11 DotSite Inc.
+// uno : 2013-09-11 Radix FZC
 uno
 
 // uol : 2014-05-01 UBN INTERNET LTDA.
@@ -10152,7 +10148,7 @@ villas
 // vin : 2015-06-18 Binky Moon, LLC
 vin
 
-// vip : 2015-01-22 Minds + Machines Group Limited
+// vip : 2015-01-22 Registry Services, LLC
 vip
 
 // virgin : 2014-09-25 Virgin Enterprises Limited
@@ -10173,7 +10169,7 @@ vivo
 // vlaanderen : 2014-02-06 DNS.be vzw
 vlaanderen
 
-// vodka : 2013-12-19 Minds + Machines Group Limited
+// vodka : 2013-12-19 Registry Services, LLC
 vodka
 
 // volkswagen : 2015-05-14 Volkswagen Group of America Inc.
@@ -10215,7 +10211,7 @@ wanggou
 // watch : 2013-11-14 Binky Moon, LLC
 watch
 
-// watches : 2014-12-22 Richemont DNS Inc.
+// watches : 2014-12-22 Afilias Limited
 watches
 
 // weather : 2015-01-08 International Business Machines Corporation
@@ -10230,10 +10226,10 @@ webcam
 // weber : 2015-06-04 Saint-Gobain Weber SA
 weber
 
-// website : 2014-04-03 DotWebsite Inc.
+// website : 2014-04-03 Radix FZC
 website
 
-// wedding : 2014-04-24 Minds + Machines Group Limited
+// wedding : 2014-04-24 Registry Services, LLC
 wedding
 
 // weibo : 2015-03-05 Sina Corporation
@@ -10275,7 +10271,7 @@ wolterskluwer
 // woodside : 2015-07-09 Woodside Petroleum Limited
 woodside
 
-// work : 2013-12-19 Minds + Machines Group Limited
+// work : 2013-12-19 Registry Services, LLC
 work
 
 // works : 2013-11-14 Binky Moon, LLC
@@ -10593,7 +10589,7 @@ xyz
 // yachts : 2014-01-09 XYZ.COM LLC
 yachts
 
-// yahoo : 2015-04-02 Yahoo! Domain Services Inc.
+// yahoo : 2015-04-02 Oath Inc.
 yahoo
 
 // yamaxun : 2014-12-18 Amazon Registry Services, Inc.
@@ -10605,7 +10601,7 @@ yandex
 // yodobashi : 2014-11-20 YODOBASHI CAMERA CO.,LTD.
 yodobashi
 
-// yoga : 2014-05-29 Minds + Machines Group Limited
+// yoga : 2014-05-29 Registry Services, LLC
 yoga
 
 // yokohama : 2013-12-12 GMO Registry, Inc.
@@ -10652,11 +10648,22 @@ ltd.ua
 // 611coin : https://611project.org/
 611.to
 
+// Aaron Marais' Gitlab pages: https://lab.aaronleem.co.za
+// Submitted by Aaron Marais <its_me@aaronleem.co.za>
+graphox.us
+
+// accesso Technology Group, plc. : https://accesso.com/
+// Submitted by accesso Team <accessoecommerce@accesso.com>
+*.devcdnaccesso.com
+
 // Adobe : https://www.adobe.com/
-// Submitted by Ian Boston <boston@adobe.com>
+// Submitted by Ian Boston <boston@adobe.com> and Lars Trieloff 
<trieloff@adobe.com>
 adobeaemcloud.com
-adobeaemcloud.net
 *.dev.adobeaemcloud.com
+hlx.live
+adobeaemcloud.net
+hlx.page
+hlx3.page
 
 // Agnat sp. z o.o. : https://domena.pl
 // Submitted by Przemyslaw Plewa <it-admin@domena.pl>
@@ -10722,6 +10729,10 @@ us-west-2.elasticbeanstalk.com
 *.elb.amazonaws.com
 *.elb.amazonaws.com.cn
 
+// Amazon Global Accelerator : https://aws.amazon.com/global-accelerator/
+// Submitted by Daniel Massaguer <psl-maintainers@amazon.com>
+awsglobalaccelerator.com
+
 // Amazon S3 : https://aws.amazon.com/s3/
 // Submitted by Luke Wells <psl-maintainers@amazon.com>
 s3.amazonaws.com
@@ -10792,6 +10803,15 @@ tele.amune.org
 // Submitted by Apigee Security Team <security@apigee.com>
 apigee.io
 
+// Appspace : https://www.appspace.com
+// Submitted by Appspace Security Team <security@appspace.com>
+appspacehosted.com
+appspaceusercontent.com
+
+// Appudo UG (haftungsbeschränkt) : https://www.appudo.com
+// Submitted by Alexander Hochbaum <admin@appudo.com>
+appudo.net
+
 // Aptible : https://www.aptible.com/
 // Submitted by Thomas Orozco <thomas@aptible.com>
 on-aptible.com
@@ -10817,15 +10837,27 @@ sweetpepper.org
 // Submitted by Vincent Tseng <vincenttseng@asustor.com>
 myasustor.com
 
+// Atlassian : https://atlassian.com
+// Submitted by Sam Smyth <devloop@atlassian.com>
+cdn.prod.atlassian-dev.net
+
 // AVM : https://avm.de
 // Submitted by Andreas Weise <a.weise@avm.de>
 myfritz.net
 
+// AVStack Pte. Ltd. : https://avstack.io
+// Submitted by Jasper Hugo <jasper@avstack.io>
+onavstack.net
+
 // AW AdvisorWebsites.com Software Inc : https://advisorwebsites.com
 // Submitted by James Kennedy <domains@advisorwebsites.com>
 *.awdev.ca
 *.advisor.ws
 
+// AZ.pl sp. z.o.o: https://az.pl
+// Submited by Krzysztof Wolski <krzysztof.wolski@home.eu>
+ecommerce-shop.pl
+
 // b-data GmbH : https://www.b-data.io
 // Submitted by Olivier Benz <olivier.benz@b-data.ch>
 b-data.io
@@ -10838,6 +10870,11 @@ backplaneapp.io
 // Submitted by Petros Angelatos <petrosagg@balena.io>
 balena-devices.com
 
+// University of Banja Luka : https://unibl.org
+// Domains for Republic of Srpska administrative entity.
+// Submitted by Marko Ivanovic <kormang@hotmail.rs>
+rs.ba
+
 // Banzai Cloud
 // Submitted by Janos Matyas <info@banzaicloud.com>
 *.banzai.cloud
@@ -10853,6 +10890,10 @@ betainabox.com
 // Submitted by Nathan O'Sullivan <nathan@mammoth.com.au>
 bnr.la
 
+// Bitbucket : http://bitbucket.org
+// Submitted by Andy Ortlieb <aortlieb@atlassian.com>
+bitbucket.io
+
 // Blackbaud, Inc. : https://www.blackbaud.com
 // Submitted by Paul Crowder <paul.crowder@blackbaud.com>
 blackbaudcdn.net
@@ -10861,10 +10902,18 @@ blackbaudcdn.net
 // Submitted by Luke Bratch <luke@bratch.co.uk>
 of.je
 
+// Blue Bite, LLC : https://bluebite.com
+// Submitted by Joshua Weiss <admin.engineering@bluebite.com>
+bluebite.io
+
 // Boomla : https://boomla.com
 // Submitted by Tibor Halter <thalter@boomla.com>
 boomla.net
 
+// Boutir : https://www.boutir.com
+// Submitted by Eric Ng Ka Ka <ngkaka@boutir.com>
+boutir.com
+
 // Boxfuse : https://boxfuse.com
 // Submitted by Axel Fontaine <axel@boxfuse.com>
 boxfuse.io
@@ -10878,6 +10927,10 @@ square7.de
 bplaced.net
 square7.net
 
+// Brendly : https://brendly.rs
+// Submitted by Dusan Radovanovic <dusan.radovanovic@brendly.rs>
+shop.brendly.rs
+
 // BrowserSafetyMark
 // Submitted by Dave Tharp <browsersafetymark.io@quicinc.com>
 browsersafetymark.io
@@ -10888,15 +10941,21 @@ uk0.bigv.io
 dh.bytemark.co.uk
 vm.bytemark.co.uk
 
+// Caf.js Labs LLC : https://www.cafjs.com
+// Submitted by Antonio Lain <antlai@cafjs.com>
+cafjs.com
+
 // callidomus : https://www.callidomus.com/
 // Submitted by Marcus Popp <admin@callidomus.com>
 mycd.eu
 
 // Carrd : https://carrd.co
 // Submitted by AJ <aj@carrd.co>
+drr.ac
+uwu.ai
 carrd.co
 crd.co
-uwu.ai
+ju.mp
 
 // CentralNic : http://www.centralnic.com/names/domains
 // Submitted by registry <gavin.brown@centralnic.com>
@@ -10962,11 +11021,6 @@ nz.basketball
 radio.am
 radio.fm
 
-// Globe Hosting SRL : https://www.globehosting.com/
-// Submitted by Gavin Brown <gavin.brown@centralnic.com>
-co.ro
-shop.ro
-
 // c.la : http://www.c.la/
 c.la
 
@@ -10974,6 +11028,10 @@ c.la
 // Submitted by B. Blechschmidt <hostmaster@certmgr.org>
 certmgr.org
 
+// Cityhost LLC  : https://cityhost.ua
+// Submitted by Maksym Rivtin <support@cityhost.net.ua>
+cx.ua
+
 // Civilized Discourse Construction Kit, Inc. : https://www.discourse.org/
 // Submitted by Rishabh Nambiar & Michael Brown <team@discourse.org>
 discourse.group
@@ -10988,14 +11046,22 @@ virtueeldomein.nl
 cleverapps.io
 
 // Clerk : https://www.clerk.dev
-// Submitted by Colin Sidoti <colin@clerk.dev>
+// Submitted by Colin Sidoti <systems@clerk.dev>
+clerk.app
+clerkstage.app
 *.lcl.dev
+*.lclstage.dev
 *.stg.dev
+*.stgstage.dev
 
 // Clic2000 : https://clic2000.fr
 // Submitted by Mathilde Blanchemanche <mathilde@clic2000.fr>
 clic2000.net
 
+// ClickRising : https://clickrising.com/
+// Submitted by Umut Gumeli <infrastructure-publicsuffixlist@clickrising.com>
+clickrising.net
+
 // Cloud66 : https://www.cloud66.com/
 // Submitted by Khash Sajadi <khash@cloud66.com>
 c66.me
@@ -11016,8 +11082,8 @@ cloudcontrolled.com
 cloudcontrolapp.com
 
 // Cloudera, Inc. : https://www.cloudera.com/
-// Submitted by Philip Langdale <security@cloudera.com>
-cloudera.site
+// Submitted by Kedarnath Waikar <security@cloudera.com>
+*.cloudera.site
 
 // Cloudflare, Inc. : https://www.cloudflare.com/
 // Submitted by Cloudflare Team <publicsuffixlist@cloudflare.com>
@@ -11166,18 +11232,37 @@ dyndns.dappnode.io
 // Submitted by Paul Biggar <ops@darklang.com>
 builtwithdark.com
 
+// DataDetect, LLC. : https://datadetect.com
+// Submitted by Andrew Banchich <abanchich@sceven.com>
+demo.datadetect.com
+instance.datadetect.com
+
 // Datawire, Inc : https://www.datawire.io
 // Submitted by Richard Li <secalert@datawire.io>
 edgestack.me
 
+// DDNS5 : https://ddns5.com
+// Submitted by Cameron Elliott <cameron@cameronelliott.com>
+ddns5.com
+
 // Debian : https://www.debian.org/
 // Submitted by Peter Palfrader / Debian Sysadmin Team 
<dsa-publicsuffixlist@debian.org>
 debian.net
 
+// Deno Land Inc : https://deno.com/
+// Submitted by Luca Casonato <hostmaster@deno.com>
+deno.dev
+deno-staging.dev
+
 // deSEC : https://desec.io/
 // Submitted by Peter Thomassen <peter@desec.io>
 dedyn.io
 
+// Diher Solutions : https://diher.solutions
+// Submitted by Didi Hermawan <mail@diher.solutions>
+*.rss.my.id
+*.diher.solutions
+
 // DNS Africa Ltd https://dns.business
 // Submitted by Calvin Browne <calvin@dns.business>
 jozi.biz
@@ -11195,6 +11280,10 @@ shop.th
 // Submitted by Paul Fang <mis@draytek.com>
 drayddns.com
 
+// DreamCommerce : https://shoper.pl/
+// Submitted by Konrad Kotarba <konrad.kotarba@dreamcommerce.com>
+shoparena.pl
+
 // DreamHost : http://www.dreamhost.com/
 // Submitted by Andrew Farmer <andrew.farmer@dreamhost.com>
 dreamhosters.com
@@ -11554,10 +11643,26 @@ blogsite.xyz
 // Submitted by Dominik Menke <dom@digineo.de>
 dynv6.net
 
+// Ellucian : https://ellucian.com
+// Submitted by Josue Colon <CloudOps-Network@ellucian.com>
+elluciancrmadvance.com
+elluciancrmadvise.com
+elluciancrmrecruit.com
+
 // E4YOU spol. s.r.o. : https://e4you.cz/
 // Submitted by Vladimir Dudr <info@e4you.cz>
 e4.cz
 
+// eero : https://eero.com/
+// Submitted by Yue Kang <eero-dynamic-dns@amazon.com>
+eero.online
+eero-stage.online
+
+// Elementor : Elementor Ltd.
+// Submitted by Anton Barkan <antonb@elementor.com>
+elementor.cloud
+elementor.cool
+
 // En root‽ : https://en-root.org
 // Submitted by Emmanuel Raviart <emmanuel@raviart.com>
 en-root.fr
@@ -11565,6 +11670,7 @@ en-root.fr
 // Enalean SAS: https://www.enalean.com
 // Submitted by Thomas Cottier <thomas.cottier@enalean.com>
 mytuleap.com
+tuleap-partners.com
 
 // ECG Robotics, Inc: https://ecgrobotics.org
 // Submitted by <frc1533@ecgrobotics.org>
@@ -11575,11 +11681,6 @@ staging.onred.one
 // Submitted by Jacob Bunk Nielsen <jbn@one.com>
 service.one
 
-// Enonic : http://enonic.com/
-// Submitted by Erik Kaareng-Sunde <esu@enonic.com>
-enonic.io
-customer.enonic.io
-
 // EU.org https://eu.org/
 // Submitted by Pierre Beyssac <hostmaster@eu.org>
 eu.org
@@ -11639,6 +11740,10 @@ tr.eu.org
 uk.eu.org
 us.eu.org
 
+// Eurobyte : https://eurobyte.ru
+// Submitted by Evgeniy Subbotin <e.subbotin@eurobyte.ru>
+eurodir.ru
+
 // Evennode : http://www.evennode.com/
 // Submitted by Michal Kralik <support@evennode.com>
 eu-1.evennode.com
@@ -11749,6 +11854,7 @@ u.channelsdvr.net
 
 // Fastly Inc. : http://www.fastly.com/
 // Submitted by Fastly Security <security@fastly.com>
+edgecompute.app
 fastly-terrarium.com
 fastlylb.net
 map.fastlylb.net
@@ -11768,10 +11874,6 @@ myfast.host
 fastvps.site
 myfast.space
 
-// Featherhead : https://featherhead.xyz/
-// Submitted by Simon Menke <simon@featherhead.xyz>
-fhapp.xyz
-
 // Fedora : https://fedoraproject.org/
 // submitted by Patrick Uiterwijk <puiterwijk@fedoraproject.org>
 fedorainfracloud.org
@@ -11782,10 +11884,11 @@ app.os.stg.fedoraproject.org
 
 // FearWorks Media Ltd. : https://fearworksmedia.co.uk
 // submitted by Keith Fairley <domains@fearworksmedia.co.uk>
-conn.uk
-copro.uk
 couk.me
 ukco.me
+conn.uk
+copro.uk
+hosp.uk
 
 // Fermax : https://fermax.com/
 // submitted by Koen Van Isterdael <k.vanisterdael@fermax.be>
@@ -11809,6 +11912,14 @@ filegear-sg.me
 // Submitted by Chris Raynor <chris@firebase.com>
 firebaseapp.com
 
+// Firewebkit : https://www.firewebkit.com
+// Submitted by Majid Qureshi <mqureshi@amrayn.com>
+fireweb.app
+
+// FLAP : https://www.flap.cloud
+// Submitted by Louis Chemineau <louis@chmn.me>
+flap.id
+
 // fly.io: https://fly.io
 // Submitted by Kurt Mackey <kurt@fly.io>
 fly.dev
@@ -11819,6 +11930,24 @@ shw.io
 // Submitted by Jonathan Rudenberg <jonathan@flynn.io>
 flynnhosting.net
 
+// Forgerock : https://www.forgerock.com
+// Submitted by Roderick Parr <roderick.parr@forgerock.com>
+forgeblocks.com
+id.forgerock.io
+
+// Framer : https://www.framer.com
+// Submitted by Koen Rouwhorst <koenrh@framer.com>
+framer.app
+framercanvas.com
+
+// Frusky MEDIA&PR : https://www.frusky.de
+// Submitted by Victor Pupynin <hallo@frusky.de>
+*.frusky.de
+
+// RavPage : https://www.ravpage.co.il
+// Submitted by Roni Horowitz <roni@responder.co.il>
+ravpage.co.il
+
 // Frederik Braun https://frederik-braun.com
 // Submitted by Frederik Braun <fb@frederik-braun.com>
 0e.vc
@@ -11836,6 +11965,10 @@ freeboxos.fr
 // Submitted by Daniel Stone <daniel@fooishbar.org>
 freedesktop.org
 
+// freemyip.com : https://freemyip.com
+// Submitted by Cadence <contact@freemyip.com>
+freemyip.com
+
 // FunkFeuer - Verein zur Förderung freier Netze : https://www.funkfeuer.at
 // Submitted by Daniel A. Maierhofer <vorstand@funkfeuer.at>
 wien.funkfeuer.at
@@ -11867,10 +12000,19 @@ gentlentapis.com
 lab.ms
 cdn-edges.net
 
+// Ghost Foundation : https://ghost.org
+// Submitted by Matt Hanley <security@ghost.org>
+ghost.io
+
+// GignoSystemJapan: http://gsj.bz
+// Submitted by GignoSystemJapan <kakutou-ec@gsj.bz>
+gsj.bz
+
 // GitHub, Inc.
 // Submitted by Patrick Toomey <security@github.com>
-github.io
 githubusercontent.com
+githubpreview.dev
+github.io
 
 // GitLab, Inc.
 // Submitted by Alex Hanselka <alex@gitlab.com>
@@ -11885,12 +12027,21 @@ gitpage.si
 // Submitted by Mads Hartmann <mads@glitch.com>
 glitch.me
 
+// Global NOG Alliance : https://nogalliance.org/
+// Submitted by Sander Steffann <sander@nogalliance.org>
+nog.community
+
+// Globe Hosting SRL : https://www.globehosting.com/
+// Submitted by Gavin Brown <gavin.brown@centralnic.com>
+co.ro
+shop.ro
+
 // GMO Pepabo, Inc. : https://pepabo.com/
 // Submitted by dojineko <admin@pepabo.com>
 lolipop.io
 
 // GOV.UK Platform as a Service : https://www.cloud.service.gov.uk/
-// Submitted by Tom Whitwell <tom.whitwell@digital.cabinet-office.gov.uk>
+// Submitted by Tom Whitwell 
<gov-uk-paas-support@digital.cabinet-office.gov.uk>
 cloudapps.digital
 london.cloudapps.digital
 
@@ -11929,7 +12080,6 @@ withyoutube.com
 cloud.goog
 translate.goog
 cloudfunctions.net
-
 blogspot.ae
 blogspot.al
 blogspot.am
@@ -12005,14 +12155,19 @@ blogspot.tw
 blogspot.ug
 blogspot.vn
 
-// Aaron Marais' Gitlab pages: https://lab.aaronleem.co.za
-// Submitted by Aaron Marais <its_me@aaronleem.co.za>
-graphox.us
+// Goupile : https://goupile.fr
+// Submitted by Niels Martignene <hello@goupile.fr>
+goupile.fr
 
 // Group 53, LLC : https://www.group53.com
 // Submitted by Tyler Todd <noc@nova53.net>
 awsmppl.com
 
+// GünstigBestellen : https://günstigbestellen.de
+// Submitted by Furkan Akkoc <info@hendelzon.de>
+günstigbestellen.de
+günstigliefern.de
+
 // Hakaran group: http://hakaran.cz
 // Submited by Arseniy Sokolov <security@hakaran.cz>
 fin.ci
@@ -12034,6 +12189,10 @@ hashbang.sh
 hasura.app
 hasura-app.io
 
+// Heilbronn University of Applied Sciences - Faculty Informatics (GitLab 
Pages): https://www.hs-heilbronn.de
+// Submitted by Richard Zowalla <mi-admin@hs-heilbronn.de>
+pages.it.hs-heilbronn.de
+
 // Hepforge : https://www.hepforge.org
 // Submitted by David Grellscheid <admin@hepforge.org>
 hepforge.org
@@ -12051,24 +12210,26 @@ ravendb.me
 development.run
 ravendb.run
 
+// home.pl S.A.: https://home.pl
+// Submited by Krzysztof Wolski <krzysztof.wolski@home.eu>
+homesklep.pl
+
 // Hong Kong Productivity Council: https://www.hkpc.org/
 // Submitted by SECaaS Team <summchan@hkpc.org>
 secaas.hk
 
 // HOSTBIP REGISTRY : https://www.hostbip.com/
 // Submitted by Atanunu Igbunuroghene <publicsuffixlist@hostbip.com>
-bpl.biz
 orx.biz
-ng.city
 biz.gl
-ng.ink
 col.ng
 firm.ng
 gen.ng
 ltd.ng
 ngo.ng
-ng.school
+edu.scot
 sch.so
+org.yt
 
 // HostyHosting (hostyhosting.com)
 hostyhosting.io
@@ -12086,6 +12247,19 @@ moonscale.net
 // Submitted by Hannu Aronsson <haa@iki.fi>
 iki.fi
 
+// Impertrix Solutions : <https://impertrixcdn.com>
+// Submitted by Zhixiang Zhao <csuite@impertrix.com>
+impertrixcdn.com
+impertrix.com
+
+// Incsub, LLC: https://incsub.com/
+// Submitted by Aaron Edwards <sysadmins@incsub.com>
+smushcdn.com
+wphostedmail.com
+wpmucdn.com
+tempurl.host
+wpmudev.host
+
 // Individual Network Berlin e.V. : https://www.in-berlin.de/
 // Submitted by Christian Seitz <chris@in-berlin.de>
 dyn-berlin.de
@@ -12178,7 +12352,8 @@ vip.jelastic.cloud
 jele.cloud
 it1.eur.aruba.jenv-aruba.cloud
 it1.jenv-aruba.cloud
-it1-eur.jenv-arubabiz.cloud
+keliweb.cloud
+cs.keliweb.cloud
 oxa.cloud
 tn.oxa.cloud
 uk.oxa.cloud
@@ -12190,13 +12365,9 @@ us.reclaim.cloud
 ch.trendhosting.cloud
 de.trendhosting.cloud
 jele.club
+amscompute.com
 clicketcloud.com
-ams.cloudswitches.com
-au.cloudswitches.com
-sg.cloudswitches.com
 dopaas.com
-elastyco.com
-nv.elastyco.com
 hidora.com
 paas.hosted-by-previder.com
 rag-cloud.hosteur.com
@@ -12211,29 +12382,26 @@ lon.wafaicloud.com
 ryd.wafaicloud.com
 j.scaleforce.com.cy
 jelastic.dogado.eu
-paas.leviracloud.eu
 fi.cloudplatform.fi
 demo.datacenter.fi
 paas.datacenter.fi
 jele.host
 mircloud.host
+paas.beebyte.io
+sekd1.beebyteapp.io
 jele.io
-ocs.opusinteractive.io
-cloud.unispace.io
-cloud-de.unispace.io
 cloud-fr1.unispace.io
 jc.neen.it
 cloud.jelastic.open.tim.it
 jcloud.kz
 upaas.kazteleport.kz
-jl.serv.net.mx
 cloudjiffy.net
 fra1-de.cloudjiffy.net
 west1-us.cloudjiffy.net
-ams1.jls.docktera.net
 jls-sto1.elastx.net
 jls-sto2.elastx.net
 jls-sto3.elastx.net
+faststacks.net
 fr-1.paas.massivegrid.net
 lon-1.paas.massivegrid.net
 lon-2.paas.massivegrid.net
@@ -12244,8 +12412,7 @@ jelastic.saveincloud.net
 nordeste-idc.saveincloud.net
 j.scaleforce.net
 jelastic.tsukaeru.net
-atl.jelastic.vps-host.net
-njs.jelastic.vps-host.net
+sdscloud.pl
 unicloud.pl
 mircloud.ru
 jelastic.regruhosting.ru
@@ -12265,6 +12432,10 @@ myjino.ru
 *.spectrum.myjino.ru
 *.vps.myjino.ru
 
+// Jotelulu S.L. : https://jotelulu.com
+// Submitted by Daniel Fariña <ingenieria@jotelulu.com>
+jotelulu.cloud
+
 // Joyent : https://www.joyent.com/
 // Submitted by Brian Bennett <brian.bennett@joyent.com>
 *.triton.zone
@@ -12296,10 +12467,20 @@ knightpoint.systems
 // Submitted by DisposaBoy <security@oya.to>
 oya.to
 
+// Katholieke Universiteit Leuven: https://www.kuleuven.be
+// Submitted by Abuse KU Leuven <abuse@kuleuven.be>
+kuleuven.cloud
+ezproxy.kuleuven.be
+
 // .KRD : http://nic.krd/data/krd/Registration%20Policy.pdf
 co.krd
 edu.krd
 
+// Krellian Ltd. : https://krellian.com
+// Submitted by Ben Francis <ben@krellian.com>
+krellian.net
+webthings.io
+
 // LCube - Professional hosting e.K. : https://www.lcube-webhosting.de
 // Submitted by Lars Laehn <info@lcube.de>
 git-repos.de
@@ -12357,6 +12538,14 @@ loginline.io
 loginline.services
 loginline.site
 
+// Lokalized : https://lokalized.nl
+// Submitted by Noah Taheij <noah@lokalized.nl>
+servers.run
+
+// Lõhmus Family, The
+// Submitted by Heiki Lõhmus <hostmaster at lohmus dot me>
+lohmus.me
+
 // LubMAN UMCS Sp. z o.o : https://lubman.pl/
 // Submitted by Ireneusz Maliszewski <ireneusz.maliszewski@lubman.pl>
 krasnik.pl
@@ -12393,6 +12582,7 @@ barsy.online
 barsy.org
 barsy.pro
 barsy.pub
+barsy.ro
 barsy.shop
 barsy.site
 barsy.support
@@ -12411,15 +12601,34 @@ mayfirst.org
 // Submitted by Ilya Zaretskiy <zaretskiy@corp.mail.ru>
 hb.cldmail.ru
 
+// Mail Transfer Platform : https://www.neupeer.com
+// Submitted by Li Hui <lihui@neupeer.com>
+cn.vu
+
+// Maze Play: https://www.mazeplay.com
+// Submitted by Adam Humpherys <adam@mws.dev>
+mazeplay.com
+
 // mcpe.me : https://mcpe.me
 // Submitted by Noa Heyl <hi@noa.dev>
 mcpe.me
 
 // McHost : https://mchost.ru
 // Submitted by Evgeniy Subbotin <e.subbotin@mchost.ru>
+mcdir.me
 mcdir.ru
+mcpre.ru
 vps.mcdir.ru
 
+// Mediatech : https://mediatech.by
+// Submitted by Evgeniy Kozhuhovskiy <ugenk@mediatech.by>
+mediatech.by
+mediatech.dev
+
+// Medicom Health : https://medicomhealth.com
+// Submitted by Michael Olson <molson@medicomhealth.com>
+hra.health
+
 // Memset hosting : https://www.memset.com
 // Submitted by Tom Whitwell <domains@memset.com>
 miniserver.com
@@ -12460,6 +12669,10 @@ westus2.azurestaticapps.net
 // Submitted by Robert Böttinger <r@minion.systems>
 csx.cc
 
+// Mintere : https://mintere.com/
+// Submitted by Ben Aubin <security@mintere.com>
+mintere.site
+
 // MobileEducation, LLC : https://joinforte.com
 // Submitted by Grayson Martin <grayson.martin@mobileeducation.us>
 forte.id
@@ -12482,8 +12695,11 @@ pp.ru
 // Submitted by Paul Cammish <kelduum@mythic-beasts.com>
 hostedpi.com
 customer.mythic-beasts.com
+caracal.mythic-beasts.com
+fentiger.mythic-beasts.com
 lynx.mythic-beasts.com
 ocelot.mythic-beasts.com
+oncilla.mythic-beasts.com
 onza.mythic-beasts.com
 sphinx.mythic-beasts.com
 vs.mythic-beasts.com
@@ -12538,6 +12754,20 @@ nh-serv.co.uk
 // Submitted by Jeff Wheelhouse <support@nearlyfreespeech.net>
 nfshost.com
 
+// Noop : https://noop.app
+// Submitted by Nathaniel Schweinberg <noop@rearc.io>
+*.developer.app
+noop.app
+
+// Northflank Ltd. : https://northflank.com/
+// Submitted by Marco Suter <marco@northflank.com>
+*.northflank.app
+*.code.run
+
+// Noticeable : https://noticeable.io
+// Submitted by Laurent Pellegrino <security@noticeable.io>
+noticeable.news
+
 // Now-DNS : https://now-dns.com
 // Submitted by Steve Russell <steve@now-dns.com>
 dnsking.ch
@@ -12676,60 +12906,6 @@ pcloud.host
 // Submitted by Matthew Brown <mattbrown@nyc.mn>
 nyc.mn
 
-// NymNom : https://nymnom.com/
-// Submitted by NymNom <psl@nymnom.com>
-nom.ae
-nom.af
-nom.ai
-nom.al
-nym.by
-nom.bz
-nym.bz
-nom.cl
-nym.ec
-nom.gd
-nom.ge
-nom.gl
-nym.gr
-nom.gt
-nym.gy
-nym.hk
-nom.hn
-nym.ie
-nom.im
-nom.ke
-nym.kz
-nym.la
-nym.lc
-nom.li
-nym.li
-nym.lt
-nym.lu
-nom.lv
-nym.me
-nom.mk
-nym.mn
-nym.mx
-nom.nu
-nym.nz
-nym.pe
-nym.pt
-nom.pw
-nom.qa
-nym.ro
-nom.rs
-nom.si
-nym.sk
-nom.st
-nym.su
-nym.sx
-nom.tj
-nym.tw
-nom.ug
-nom.uy
-nom.vc
-nom.vg
-
 // Observable, Inc. : https://observablehq.com
 // Submitted by Mike Bostock <dns@observablehq.com>
 static.observableusercontent.com
@@ -12762,18 +12938,29 @@ opensocial.site
 // Submitted by Sven Marnach <sven@opencraft.com>
 opencraft.hosting
 
+// OpenResearch GmbH: https://openresearch.com/
+// Submitted by Philipp Schmid <ops@openresearch.com>
+orsites.com
+
 // Opera Software, A.S.A.
 // Submitted by Yngve Pettersen <yngve@opera.com>
 operaunite.com
 
-// Oursky Limited : https://skygear.io/
-// Submited by Skygear Developer <hello@skygear.io>
+// Oursky Limited : https://authgear.com/, https://skygear.io/
+// Submited by Authgear Team <hello@authgear.com>, Skygear Developer 
<hello@skygear.io>
+authgear-staging.com
+authgearapps.com
 skygearapp.com
 
 // OutSystems
 // Submitted by Duarte Santos <domain-admin@outsystemscloud.com>
 outsystemscloud.com
 
+// OVHcloud: https://ovhcloud.com
+// Submitted by Vincent Cassé <vincent.casse@ovhcloud.com>
+*.webpaas.ovh.net
+*.hosting.ovh.net
+
 // OwnProvider GmbH: http://www.ownprovider.com
 // Submitted by Jan Moennich <jan.moennich@ownprovider.com>
 ownprovider.com
@@ -12803,6 +12990,10 @@ pagefrontapp.com
 // Submitted by Yann Guichard <yann@pagexl.com>
 pagexl.com
 
+// Paywhirl, Inc : https://paywhirl.com/
+// Submitted by Daniel Netzer <dan@paywhirl.com>
+*.paywhirl.com
+
 // pcarrier.ca Software Inc: https://pcarrier.ca/
 // Submitted by Pierre Carrier <pc@rrier.ca>
 bar0.net
@@ -12834,8 +13025,6 @@ perspecta.cloud
 // PE Ulyanov Kirill Sergeevich : https://airy.host
 // Submitted by Kirill Ulyanov <k.ulyanov@airy.host>
 lk3.ru
-ra-ru.ru
-zsew.ru
 
 // Planet-Work : https://www.planet-work.com/
 // Submitted by Frédéric VANNIÈRE <f.vanniere@planet-work.com>
@@ -12848,6 +13037,7 @@ ent.platform.sh
 eu.platform.sh
 us.platform.sh
 *.platformsh.site
+*.tst.site
 
 // Platter: https://platter.dev
 // Submitted by Patrick Flor <patrick@platter.dev>
@@ -12869,6 +13059,13 @@ dyn53.io
 // Submitted by Zulfais <pc@co.bn>
 co.bn
 
+// Postman, Inc : https://postman.com
+// Submitted by Rahul Dhawan <security@postman.com>
+postman-echo.com
+pstmn.io
+mock.pstmn.io
+httpbin.org
+
 // prgmr.com : https://prgmr.com/
 // Submitted by Sarah Newman <owner@prgmr.com>
 xen.prgmr.com
@@ -12898,6 +13095,11 @@ byen.site
 // Submitted by Kor Nielsen <kor@pubtls.org>
 pubtls.org
 
+// PythonAnywhere LLP: https://www.pythonanywhere.com
+// Submitted by Giles Thomas <giles@pythonanywhere.com>
+pythonanywhere.com
+eu.pythonanywhere.com
+
 // QOTO, Org.
 // Submitted by Jeffrey Phillips Freeman <jeffrey.freeman@qoto.org>
 qoto.io
@@ -12910,6 +13112,10 @@ qualifioapp.com
 // Submitted by Dani Biro <dani@pymet.com>
 qbuser.com
 
+// Rad Web Hosting: https://radwebhosting.com
+// Submitted by Scott Claeys <s.claeys@radwebhosting.com>
+cloudsite.builders
+
 // Redstar Consultants : https://www.redstarconsultants.com/
 // Submitted by Jons Slemmer <jons@redstarconsultants.com>
 instantcloud.cn
@@ -12973,6 +13179,7 @@ onrender.com
 // Repl.it : https://repl.it
 // Submitted by Mason Clayton <mason@repl.it>
 repl.co
+id.repl.co
 repl.run
 
 // Resin.io : https://resin.io
@@ -12989,10 +13196,31 @@ hzc.io
 wellbeingzone.eu
 wellbeingzone.co.uk
 
+// Rico Developments Limited : https://adimo.co
+// Submitted by Colin Brown <hello@adimo.co>
+adimo.co.uk
+
+// Riseup Networks : https://riseup.net
+// Submitted by Micah Anderson <micah@riseup.net>
+itcouldbewor.se
+
 // Rochester Institute of Technology : http://www.rit.edu/
 // Submitted by Jennifer Herting <jchits@rit.edu>
 git-pages.rit.edu
 
+// Rusnames Limited: http://rusnames.ru/
+// Submitted by Sergey Zotov <admin@rusnames.ru>
+биз.рус
+ком.рус
+крым.рус
+мир.рус
+мск.рус
+орг.рус
+самара.рус
+сочи.рус
+спб.рус
+я.рус
+
 // Sandstorm Development Group, Inc. : https://sandcats.io/
 // Submitted by Asheesh Laroia <asheesh@sandstorm.io>
 sandcats.io
@@ -13009,6 +13237,7 @@ schokokeks.net
 // Scottish Government: https://www.gov.scot
 // Submitted by Martin Ellis <martin.ellis@gov.scot>
 gov.scot
+service.gov.scot
 
 // Scry Security : http://www.scrysec.com
 // Submitted by Shante Adam <shante@skyhat.io>
@@ -13031,16 +13260,33 @@ spdns.org
 // Submitted by Artem Kondratev <accounts@seidat.com>
 seidat.net
 
+// Sellfy : https://sellfy.com
+// Submitted by Yuriy Romadin <contact@sellfy.com>
+sellfy.store
+
 // Senseering GmbH : https://www.senseering.de
 // Submitted by Felix Mönckemeyer <f.moenckemeyer@senseering.de>
 senseering.net
 
+// Sendmsg: https://www.sendmsg.co.il
+// Submitted by Assaf Stern <domains@comstar.co.il>
+minisite.ms
+
+// Service Magnet : https://myservicemagnet.com
+// Submitted by Dave Sanders <dave@myservicemagnet.com>
+magnet.page
+
 // Service Online LLC : http://drs.ua/
 // Submitted by Serhii Bulakh <support@drs.ua>
 biz.ua
 co.ua
 pp.ua
 
+// Shift Crypto AG : https://shiftcrypto.ch
+// Submitted by alex <alex@shiftcrypto.ch>
+shiftcrypto.dev
+shiftcrypto.io
+
 // ShiftEdit : https://shiftedit.net/
 // Submitted by Adam Jimenez <adam@shiftcreate.com>
 shiftedit.io
@@ -13049,6 +13295,10 @@ shiftedit.io
 // Submitted by Alex Bowers <alex@shopblocks.com>
 myshopblocks.com
 
+// Shopify : https://www.shopify.com
+// Submitted by Alex Richter <alex.richter@shopify.com>
+myshopify.com
+
 // Shopit : https://www.shopitcommerce.com/
 // Submitted by Craig McMahon <craig@shopitcommerce.com>
 shopitsite.com
@@ -13083,16 +13333,43 @@ beta.bounty-full.com
 // Submitted by Aral Balkan <aral@small-tech.org>
 small-web.org
 
+// Smoove.io : https://www.smoove.io/
+// Submitted by Dan Kozak <dan@smoove.io>
+vp4.me
+
+// Snowplow Analytics : https://snowplowanalytics.com/
+// Submitted by Ian Streeter <ian@snowplowanalytics.com>
+try-snowplow.com
+
+// SourceHut : https://sourcehut.org
+// Submitted by Drew DeVault <sir@cmpwn.com>
+srht.site
+
 // Stackhero : https://www.stackhero.io
 // Submitted by Adrien Gillon <adrien+public-suffix-list@stackhero.io>
 stackhero-network.com
 
+// Staclar : https://staclar.com
+// Submitted by Matthias Merkel <matthias.merkel@staclar.com>
+novecore.site
+
 // staticland : https://static.land
 // Submitted by Seth Vincent <sethvincent@gmail.com>
 static.land
 dev.static.land
 sites.static.land
 
+// Storebase : https://www.storebase.io
+// Submitted by Tony Schirmer <tony@storebase.io>
+storebase.store
+
+// Strategic System Consulting (eApps Hosting): https://www.eapps.com/
+// Submitted by Alex Oancea <aoancea@cloudscale365.com>
+vps-host.net
+atl.jelastic.vps-host.net
+njs.jelastic.vps-host.net
+ric.jelastic.vps-host.net
+
 // Sony Interactive Entertainment LLC : https://sie.com/
 // Submitted by David Coles <david.coles@sony.com>
 playstation-cloud.com
@@ -13110,6 +13387,28 @@ spacekit.io
 // Submitted by Stefan Neufeind <info@speedpartner.de>
 customer.speedpartner.de
 
+// Spreadshop (sprd.net AG) : https://www.spreadshop.com/
+// Submitted by Martin Breest <security@spreadshop.com>
+myspreadshop.at
+myspreadshop.com.au
+myspreadshop.be
+myspreadshop.ca
+myspreadshop.ch
+myspreadshop.com
+myspreadshop.de
+myspreadshop.dk
+myspreadshop.es
+myspreadshop.fi
+myspreadshop.fr
+myspreadshop.ie
+myspreadshop.it
+myspreadshop.net
+myspreadshop.nl
+myspreadshop.no
+myspreadshop.pl
+myspreadshop.se
+myspreadshop.co.uk
+
 // Standard Library : https://stdlib.com
 // Submitted by Jacob Lee <jacob@stdlib.com>
 api.stdlib.com
@@ -13131,10 +13430,12 @@ user.srcf.net
 // Submitted by Dan Miller <dm@sub6.com>
 temp-dns.com
 
-// Swisscom Application Cloud: https://developer.swisscom.com
-// Submitted by Matthias.Winzeler <matthias.winzeler@swisscom.com>
-applicationcloud.io
-scapp.io
+// Supabase : https://supabase.io
+// Submitted by Inian Parameshwaran <security@supabase.io>
+supabase.co
+supabase.in
+supabase.net
+su.paba.se
 
 // Symfony, SAS : https://symfony.com/
 // Submitted by Fabien Potencier <fabien@symfony.com>
@@ -13163,6 +13464,10 @@ synology.me
 vpnplus.to
 direct.quickconnect.to
 
+// Tabit Technologies Ltd. : https://tabit.cloud/
+// Submitted by Oren Agiv <oren@tabit.cloud>
+tabitorder.co.il
+
 // TAIFUN Software AG : http://taifun-software.de
 // Submitted by Bjoern Henke <dev-server@taifun-software.de>
 taifun-dns.de
@@ -13190,13 +13495,17 @@ gwiddle.co.uk
 
 // Thingdust AG : https://thingdust.com/
 // Submitted by Adrian Imboden <adi@thingdust.com>
+*.firenet.ch
+*.svc.firenet.ch
+reservd.com
 thingdustdata.com
 cust.dev.thingdust.io
 cust.disrec.thingdust.io
 cust.prod.thingdust.io
 cust.testing.thingdust.io
-*.firenet.ch
-*.svc.firenet.ch
+reservd.dev.thingdust.io
+reservd.disrec.thingdust.io
+reservd.testing.thingdust.io
 
 // Tlon.io : https://tlon.io
 // Submitted by Mark Staarink <mark@tlon.io>
@@ -13204,11 +13513,20 @@ arvo.network
 azimuth.network
 tlon.network
 
+// Tor Project, Inc. : https://torproject.org
+// Submitted by Antoine Beaupré <anarcat@torproject.org
+torproject.net
+pages.torproject.net
+
 // TownNews.com : http://www.townnews.com
 // Submitted by Dustin Ward <dward@townnews.com>
 bloxcms.com
 townnews-staging.com
 
+// TradableBits: https://tradablebits.com
+// Submitted by Dmitry Khrisanov dmitry@tradablebits.com
+tbits.me
+
 // TrafficPlex GmbH : https://www.trafficplex.de/
 // Submitted by Phillipp Röll <phillipp.roell@trafficplex.de>
 12hp.at
@@ -13336,7 +13654,6 @@ at.md
 de.md
 jp.md
 to.md
-uwu.nu
 indie.porn
 vxl.sh
 ch.tc
@@ -13369,6 +13686,13 @@ fastblog.net
 // Submitted by Arnold Hendriks <info@webhare.com>
 *.webhare.dev
 
+// WebHotelier Technologies Ltd: https://www.webhotelier.net/
+// Submitted by Apostolos Tsakpinis <apostolos.tsakpinis@gmail.com>
+reserve-online.net
+reserve-online.com
+bookonline.app
+hotelwithflight.com
+
 // WeDeploy by Liferay, Inc. : https://www.wedeploy.com
 // Submitted by Henrique Vicente <security@wedeploy.com>
 wedeploy.io
@@ -13396,15 +13720,29 @@ daemon.panel.gg
 
 // WoltLab GmbH : https://www.woltlab.com
 // Submitted by Tim Düsterhus <security@woltlab.cloud>
+woltlab-demo.com
 myforum.community
 community-pro.de
 diskussionsbereich.de
 community-pro.net
 meinforum.net
 
-// www.com.vc : http://www.com.vc
-// Submitted by Li Hui <lihui@sinopub.com>
-cn.vu
+// Woods Valldata : https://www.woodsvalldata.co.uk/
+// Submitted by Chris Whittle <chris.whittle@woodsvalldata.co.uk>
+affinitylottery.org.uk
+raffleentry.org.uk
+weeklylottery.org.uk
+
+// WP Engine : https://wpengine.com/
+// Submitted by Michael Smith <michael.smith@wpengine.com>
+// Submitted by Brandon DuRette <brandon.durette@wpengine.com>
+wpenginepowered.com
+js.wpenginepowered.com
+
+// Wix.com, Inc. : https://www.wix.com
+// Submitted by Shahar Talmi <shahart@wix.com>
+wixsite.com
+editorx.io
 
 // XenonCloud GbR: https://xenoncloud.net
 // Submitted by Julian Uphoff <publicsuffixlist@xenoncloud.net>
@@ -13448,6 +13786,7 @@ ybo.trade
 
 // Yunohost : https://yunohost.org
 // Submitted by Valentin Grimaud <security@yunohost.org>
+ynh.fr
 nohost.me
 noho.st
 
@@ -13466,26 +13805,4 @@ basicserver.io
 virtualserver.io
 enterprisecloud.nu
 
-// Mintere : https://mintere.com/
-// Submitted by Ben Aubin <security@mintere.com>
-mintere.site
-
-// Cityhost LLC  : https://cityhost.ua
-// Submitted by Maksym Rivtin <support@cityhost.net.ua>
-cx.ua
-
-// WP Engine : https://wpengine.com/
-// Submitted by Michael Smith <michael.smith@wpengine.com>
-// Submitted by Brandon DuRette <brandon.durette@wpengine.com>
-wpenginepowered.com
-js.wpenginepowered.com
-
-// Impertrix Solutions : <https://impertrixcdn.com>
-// Submitted by Zhixiang Zhao <csuite@impertrix.com>
-impertrixcdn.com
-impertrix.com
-
-// GignoSystemJapan: http://gsj.bz
-// Submitted by GignoSystemJapan <kakutou-ec@gsj.bz>
-gsj.bz
 // ===END PRIVATE DOMAINS===
diff --git a/etc/refcards/de-refcard.tex b/etc/refcards/de-refcard.tex
index c890acb..9cd0df7 100644
--- a/etc/refcards/de-refcard.tex
+++ b/etc/refcards/de-refcard.tex
@@ -443,8 +443,6 @@ einen Rahmen statt eines Fensters.
 \key{Spalte f\"ur Umbruch auf {\it Argument\/} setzen}{C-x f}
 \key{Pr\"afix f\"ur jede Zeile setzen}{C-x .}
 
-\key{Face setzen}{M-o}
-
 \section{Gro\ss{}- und Kleinschreibung}
 
 \key{Wort in Gro\ss{}buchstaben}{M-u}
diff --git a/etc/refcards/fr-refcard.tex b/etc/refcards/fr-refcard.tex
index 34d7ebd..ad6db63 100644
--- a/etc/refcards/fr-refcard.tex
+++ b/etc/refcards/fr-refcard.tex
@@ -446,8 +446,6 @@ pas les fen\^etres mais les cadres.
 \key{Placer la marge droite \`a {\it arg\/} colonnes}{C-u {\it arg\/} C-x f}
 \key{D\'efinir le pr\'efixe des lignes}{C-x .}
 
-\key{D\'efinir la fonte}{M-o}
-
 \section{Modifier la casse}
 
 \key{Mettre le mot en capitales}{M-u}
diff --git a/etc/refcards/pl-refcard.tex b/etc/refcards/pl-refcard.tex
index c9d9678..5c12dbf 100644
--- a/etc/refcards/pl-refcard.tex
+++ b/etc/refcards/pl-refcard.tex
@@ -679,7 +679,7 @@ Napisz \kbd{F10} aby uaktywni/c menu w minibuforze.
 \key{przestaw {\bf linie}}{C-x C-t}
 \key{przestaw {\bf s-wyra/zenia}}{C-M-t}
 
-% Removed -- there is no Polish disctionary for ispell.
+% Removed -- there is no Polish dictionary for ispell.
 %\section{Spelling Check}
 %
 %\key{check spelling of current word}{M-\$}
diff --git a/etc/refcards/pt-br-refcard.tex b/etc/refcards/pt-br-refcard.tex
index 2d6680f..9226a6d 100644
--- a/etc/refcards/pt-br-refcard.tex
+++ b/etc/refcards/pt-br-refcard.tex
@@ -452,8 +452,6 @@ para frame.
 \key{define a coluna limite de preenchimento}{C-x f}
 \key{define um prefixo para cada linha}{C-x .}
 
-\key{formata fonte}{M-o}
-
 \section{Mai{\'u}sculas e Min{\'u}sculas}
 
 \key{Palavra para mai{\'u}sculas}{M-u}
diff --git a/etc/refcards/refcard.tex b/etc/refcards/refcard.tex
index 4cb8f9d..ae39a4e 100644
--- a/etc/refcards/refcard.tex
+++ b/etc/refcards/refcard.tex
@@ -457,8 +457,6 @@ frame instead of a window.
 \key{set fill column to {\it arg}}{C-x f}
 \key{set prefix each line starts with}{C-x .}
 
-\key{set face}{M-o}
-
 \section{Case Change}
 
 \key{uppercase word}{M-u}
diff --git a/leim/SKK-DIC/SKK-JISYO.L b/leim/SKK-DIC/SKK-JISYO.L
index 78d6e08..f1e06cc 100644
--- a/leim/SKK-DIC/SKK-JISYO.L
+++ b/leim/SKK-DIC/SKK-JISYO.L
@@ -46444,7 +46444,9 @@ zyklus /
 ���󤴤� /�Ź�;code/�Ź�;�����ΰ���/
 ���󤴤��� /�Ź沽/
 ���󤴤����� /�Ź渰;[����]encryption key/
+���󤴤������� /�Ź��/
 ���󤴤����礦 /�Ź�Ģ/
+���󤴤��Ĥ��� /�Ź��̲�/
 ���󤴤��Ҥ礦 /�Ź�ɽ/
 ���󤴤��֤� /�Ź�ʸ/
 ���󤵤� /�Ż�/
@@ -61914,6 +61916,7 @@ zyklus /
 ���������� /������/
 �������������礦 /�������/
 ����������ޤ� /����ü��/
+�������Ĥ��� /�����̲�/
 �������Ƥ� /����Ū/����Ũ;imaginary enemy/
 �������Ƥ����� /����Ũ��/
 �������� /�����/
@@ -138362,6 +138365,7 @@ zyklus /
 �ˤ��夦����� /�󽽻���;Make a wish!/
 �ˤ��夦���� /�󽽻ͻ�;�󽽰�ˡܵ����ܵ����ˡ�����/
 �ˤ��夦�����ä� /�󽽻��ᵤ/
+�ˤ��夦���Ϥ餤 /��Ż�ʧ/
 �ˤ��夦���礦 /��ž�/
 �ˤ��夦���󤫤� /��ſͳ�/
 �ˤ��夦���� /�����;dualism/�����;[ŷʸ]double star/
@@ -138476,6 +138480,7 @@ zyklus /
 �ˤ��� /��ê/
 �ˤ��� /����/
 �ˤ��󤫤� /���ʳ�/2�ʳ�/
+�ˤ��󤫤��ˤ󤷤礦 /���ʳ�ǧ��/
 �ˤ��󤫤Ĥ褦 /���ʳ���/
 �ˤ��󤬤��� /���ʽŤ�/
 �ˤ��󤬤ޤ� /���ʹ���;with a fallback/
diff --git a/lib-src/Makefile.in b/lib-src/Makefile.in
index 7af89eb..e6cda73 100644
--- a/lib-src/Makefile.in
+++ b/lib-src/Makefile.in
@@ -52,6 +52,7 @@ top_builddir = @top_builddir@
 # Location to install Emacs.app under GNUstep / macOS.
 # Later values may use this.
 ns_appbindir=@ns_appbindir@
+ns_applibexecdir=@ns_applibexecdir@
 
 # The default location for installation.  Everything is placed in
 # subdirectories of this directory.  The default values for many of
diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c
index 8346524..018e81e 100644
--- a/lib-src/emacsclient.c
+++ b/lib-src/emacsclient.c
@@ -1401,10 +1401,8 @@ local_sockname (int s, char sockname[socknamesize], int 
tmpdirlen,
   /* Put the full address name into the buffer, since the caller might
      need it for diagnostics.  But don't overrun the buffer.  */
   uintmax_t uidmax = uid;
-  int emacsdirlen;
   int suffixlen = snprintf (sockname + tmpdirlen, socknamesize - tmpdirlen,
-                           "/emacs%"PRIuMAX"%n/%s", uidmax, &emacsdirlen,
-                           server_name);
+                           "/emacs%"PRIuMAX"/%s", uidmax, server_name);
   if (! (0 <= suffixlen && suffixlen < socknamesize - tmpdirlen))
     return ENAMETOOLONG;
 
@@ -1412,7 +1410,8 @@ local_sockname (int s, char sockname[socknamesize], int 
tmpdirlen,
      this user's directory and does not let others write to it; this
      fends off some symlink attacks.  To avoid races, keep the parent
      directory open while checking.  */
-  char *emacsdirend = sockname + tmpdirlen + emacsdirlen;
+  char *emacsdirend = sockname + tmpdirlen + suffixlen -
+    strlen(server_name) - 1;
   *emacsdirend = '\0';
   int dir = openat (AT_FDCWD, sockname,
                    O_PATH | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
diff --git a/lib-src/etags.c b/lib-src/etags.c
index ae39fc4..b3883d7 100644
--- a/lib-src/etags.c
+++ b/lib-src/etags.c
@@ -6260,7 +6260,7 @@ test_objc_is_mercury (char *this_file, language **lang)
        }
     }
 
-  /* Fallback heuristic test.  Not failsafe but errless in pratice.  */
+  /* Fallback heuristic test.  Not failsafe but errless in practice.  */
   ratio = ((float) rule_signs + percentage_signs + mercury_dots) / lines;
 
  out:
diff --git a/lib-src/seccomp-filter.c b/lib-src/seccomp-filter.c
index dc568e0..d378e0b 100644
--- a/lib-src/seccomp-filter.c
+++ b/lib-src/seccomp-filter.c
@@ -131,9 +131,12 @@ export_filter (const char *file,
                int (*function) (const scmp_filter_ctx, int),
                const char *name)
 {
-  int fd = TEMP_FAILURE_RETRY (
-    open (file, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_CLOEXEC,
-          0644));
+  int fd;
+  do
+    fd = open (file,
+               O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_CLOEXEC,
+               0644);
+  while (fd < 0 && errno == EINTR);
   if (fd < 0)
     fail (errno, "open %s", file);
   int status = function (ctx, fd);
diff --git a/lisp/ChangeLog.7 b/lisp/ChangeLog.7
index 3de3f2f..3dd8313 100644
--- a/lisp/ChangeLog.7
+++ b/lisp/ChangeLog.7
@@ -15867,7 +15867,7 @@
        the key line of an entry.
 
        * bibtex.el (bibtex-autokey-year-use-crossref-entry): New variable
-       to determine if crossreferenced entry should be used for autokey
+       to determine if cross-referenced entry should be used for autokey
        generation, if year field of current entry is absent.
        (bibtex-generate-autokey): Use this new variable.
 
diff --git a/lisp/ChangeLog.8 b/lisp/ChangeLog.8
index 3027463..39e757b 100644
--- a/lisp/ChangeLog.8
+++ b/lisp/ChangeLog.8
@@ -1147,7 +1147,7 @@
        (bibtex-submit-bug-report): Use bibtex-version and
        bibtex-maintainer-salutation.
        (bibtex-entry-field-alist): Made booktitle field optional for
-       @inproceedings entries when crossreferenced.
+       @inproceedings entries when cross-referenced.
        (bibtex-entry-field-alist): Add booktitle field to proceedings
        entry type (for cross referencing). Thanks to Wagner Toledo Correa
        for the suggestion.
diff --git a/lisp/abbrev.el b/lisp/abbrev.el
index 54783db..f370bd3 100644
--- a/lisp/abbrev.el
+++ b/lisp/abbrev.el
@@ -288,6 +288,10 @@ or zero means the region is the expansion.
 A negative argument means to undefine the specified abbrev.
 Reads the abbreviation in the minibuffer.
 
+See also `inverse-add-mode-abbrev', which performs the opposite task:
+if the abbrev text is already in the buffer, use this command to
+define an abbrev by specifying the expansion in the minibuffer.
+
 Don't use this function in a Lisp program; use `define-abbrev' instead."
   (interactive "p")
   (add-abbrev
@@ -304,6 +308,10 @@ expansion; or zero means the region is the expansion.
 A negative argument means to undefine the specified abbrev.
 This command uses the minibuffer to read the abbreviation.
 
+See also `inverse-add-global-abbrev', which performs the opposite task:
+if the abbrev text is already in the buffer, use this command to
+define an abbrev by specifying the expansion in the minibuffer.
+
 Don't use this function in a Lisp program; use `define-abbrev' instead."
   (interactive "p")
   (add-abbrev global-abbrev-table "Global" arg))
@@ -330,7 +338,11 @@ Don't use this function in a Lisp program; use 
`define-abbrev' instead."
   "Define last word before point as a mode-specific abbrev.
 With prefix argument N, defines the Nth word before point.
 This command uses the minibuffer to read the expansion.
-Expands the abbreviation after defining it."
+Expands the abbreviation after defining it.
+
+See also `add-mode-abbrev', which performs the opposite task:
+if the expansion is already in the buffer, use this command
+to define an abbrev by specifying the abbrev in the minibuffer."
   (interactive "p")
   (inverse-add-abbrev
    (if only-global-abbrevs
@@ -343,7 +355,11 @@ Expands the abbreviation after defining it."
   "Define last word before point as a global (mode-independent) abbrev.
 With prefix argument N, defines the Nth word before point.
 This command uses the minibuffer to read the expansion.
-Expands the abbreviation after defining it."
+Expands the abbreviation after defining it.
+
+See also `add-global-abbrev', which performs the opposite task:
+if the expansion is already in the buffer, use this command
+to define an abbrev by specifying the abbrev in the minibuffer."
   (interactive "p")
   (inverse-add-abbrev global-abbrev-table "Global" n))
 
diff --git a/lisp/bindings.el b/lisp/bindings.el
index 0345944..b8bf0c1 100644
--- a/lisp/bindings.el
+++ b/lisp/bindings.el
@@ -1434,6 +1434,17 @@ if `inhibit-field-text-motion' is non-nil."
 
 (define-key ctl-x-map "[" 'backward-page)
 (define-key ctl-x-map "]" 'forward-page)
+
+(defvar page-navigation-repeat-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map "]" #'forward-page)
+    (define-key map "[" #'backward-page)
+    map)
+  "Keymap to repeat page navigation key sequences.  Used in `repeat-mode'.")
+
+(put 'forward-page 'repeat-map 'page-navigation-repeat-map)
+(put 'backward-page 'repeat-map 'page-navigation-repeat-map)
+
 (define-key ctl-x-map "\C-p" 'mark-page)
 (define-key ctl-x-map "l" 'count-lines-page)
 (define-key ctl-x-map "np" 'narrow-to-page)
diff --git a/lisp/bookmark.el b/lisp/bookmark.el
index ff9b8ab..b340d37 100644
--- a/lisp/bookmark.el
+++ b/lisp/bookmark.el
@@ -27,7 +27,7 @@
 ;; associates a string with a location in a certain file.  Thus, you
 ;; can navigate your way to that location by providing the string.
 ;;
-;; Type `M-x customize-group RET boomark RET' for user options.
+;; Type `M-x customize-group RET bookmark RET' for user options.
 
 
 ;;; Code:
diff --git a/lisp/calc/calc-graph.el b/lisp/calc/calc-graph.el
index 9ac24bf..9dfdba3 100644
--- a/lisp/calc/calc-graph.el
+++ b/lisp/calc/calc-graph.el
@@ -391,6 +391,13 @@
                    ((>= calc-gnuplot-version 3)
                     "dumb")
                    (t "postscript"))))
+        (unless (equal device calc-graph-last-device)
+          (setq calc-graph-last-device device)
+          (unless (calc-gnuplot-command "set terminal" device)
+             ;; If gnuplot doesn't support the terminal, then set it
+             ;; to "dumb".
+             (calc-gnuplot-command "set terminal dumb")
+             (setq device "dumb")))
         (if (equal device "dumb")
             (setq device (format "dumb %d %d"
                                  (1- (frame-width)) (1- (frame-height)))))
@@ -404,10 +411,6 @@
                 (setq tempoutfile (calc-temp-file-name -1)
                       output tempoutfile))
           (setq output (eval output t)))
-        (or (equal device calc-graph-last-device)
-            (progn
-              (setq calc-graph-last-device device)
-              (calc-gnuplot-command "set terminal" device)))
         (or (equal output calc-graph-last-output)
             (progn
               (setq calc-graph-last-output output)
@@ -1411,6 +1414,8 @@ This \"dumb\" driver will be present in Gnuplot 3.0."
       (calc-graph-view-trail)))
 
 (defun calc-gnuplot-command (&rest args)
+  "Send ARGS to Gnuplot.
+Returns nil if Gnuplot signalled an error."
   (calc-graph-init)
   (let ((cmd (concat (mapconcat 'identity args " ") "\n")))
     (or (calc-graph-w32-p)
@@ -1428,9 +1433,11 @@ This \"dumb\" driver will be present in Gnuplot 3.0."
       (or (calc-graph-w32-p)
          (accept-process-output (and (not calc-graph-no-wait)
                                      calc-gnuplot-process)))
-      (calc-gnuplot-check-for-errors)
-      (if (get-buffer-window calc-gnuplot-buffer)
-         (calc-graph-view-trail)))))
+      (prog1
+          ;; Return nil if we got an error.
+          (not (calc-gnuplot-check-for-errors))
+        (if (get-buffer-window calc-gnuplot-buffer)
+           (calc-graph-view-trail))))))
 
 (defun calc-graph-init-buffers ()
   (or (and calc-gnuplot-buffer
diff --git a/lisp/calc/calc.el b/lisp/calc/calc.el
index a10b317..800ec7a 100644
--- a/lisp/calc/calc.el
+++ b/lisp/calc/calc.el
@@ -139,6 +139,7 @@
 ;;; Code:
 
 (require 'calc-macs)
+(require 'rect)
 
 ;; Declare functions which are defined elsewhere.
 (declare-function calc-set-language "calc-lang" (lang &optional option 
no-refresh))
@@ -3388,7 +3389,9 @@ and all digits are kept, regardless of Calc's current 
precision."
   "Parse the region as a vector of numbers and push it on the Calculator 
stack."
   (interactive "r\nP")
   (require 'calc-ext)
-  (calc-do-grab-region top bot arg))
+  (if rectangle-mark-mode
+      (calc-do-grab-rectangle top bot arg)
+    (calc-do-grab-region top bot arg)))
 
 ;;;###autoload
 (defun calc-grab-rectangle (top bot arg)
@@ -3397,12 +3400,14 @@ and all digits are kept, regardless of Calc's current 
precision."
   (require 'calc-ext)
   (calc-do-grab-rectangle top bot arg))
 
+;;;###autoload
 (defun calc-grab-sum-down (top bot arg)
   "Parse a rectangle as a matrix of numbers and sum its columns."
   (interactive "r\nP")
   (require 'calc-ext)
   (calc-do-grab-rectangle top bot arg 'calcFunc-reduced))
 
+;;;###autoload
 (defun calc-grab-sum-across (top bot arg)
   "Parse a rectangle as a matrix of numbers and sum its rows."
   (interactive "r\nP")
diff --git a/lisp/calendar/appt.el b/lisp/calendar/appt.el
index 29bcd6d..f523863 100644
--- a/lisp/calendar/appt.el
+++ b/lisp/calendar/appt.el
@@ -402,11 +402,12 @@ displayed in a window:
              (appt-display-message string-list min-list))
         (when appt-display-mode-line
           (setq appt-mode-string
-                (concat " " (propertize
-                             (appt-mode-line (mapcar #'number-to-string
-                                                     min-list)
-                                             t)
-                             'face 'mode-line-emphasis))))
+                (concat (propertize
+                         (appt-mode-line (mapcar #'number-to-string
+                                                 min-list)
+                                         t)
+                         'face 'mode-line-emphasis)
+                        " ")))
         ;; Reset count to 0 in case we display another appt on the next cycle.
         (setq appt-display-count (if (eq '(0) min-list) 0
                                    (1+ prev-appt-display-count))))
diff --git a/lisp/calendar/calendar.el b/lisp/calendar/calendar.el
index 76d6132..7c929eb 100644
--- a/lisp/calendar/calendar.el
+++ b/lisp/calendar/calendar.el
@@ -1308,7 +1308,9 @@ This function is suitable for execution in an init file."
   ;; Avoid loading cal-x unless it will be used.
   (if (and (memq calendar-setup '(one-frame two-frames calendar-only))
            (display-multi-frame-p))
-      (calendar-frame-setup calendar-setup arg)
+      ;; Calendar does its own frame setup.
+      (let ((pop-up-frames nil))
+        (calendar-frame-setup calendar-setup arg))
     (calendar-basic-setup arg)))
 
 (defun calendar-basic-setup (&optional arg nodisplay)
diff --git a/lisp/calendar/diary-lib.el b/lisp/calendar/diary-lib.el
index f57fe26..9ca7ce3 100644
--- a/lisp/calendar/diary-lib.el
+++ b/lisp/calendar/diary-lib.el
@@ -2014,6 +2014,17 @@ string to use when highlighting the day in the calendar."
     (and (>= diff 0) (zerop (% diff n))
          (cons mark (format entry cycle (diary-ordinal-suffix cycle))))))
 
+;; To be called from diary-sexp-entry, where DATE, ENTRY are bound.
+(defun diary-offset (sexp days)
+  "Offsetted diary entry.  Offsets SEXP by DAYS days.
+Entry applies if the date is DAYS days after another diary-sexp SEXP."
+  (with-no-warnings (defvar date))
+  (unless (integerp days)
+    (user-error "Days must be an integer"))
+  (let ((date (calendar-gregorian-from-absolute
+              (- (calendar-absolute-from-gregorian date) days))))
+    (eval sexp)))
+
 (defun diary-day-of-year ()
   "Day of year and number of days remaining in the year of date diary entry."
   (with-no-warnings (defvar date))
diff --git a/lisp/calendar/timeclock.el b/lisp/calendar/timeclock.el
index 4a4b65d..0b94bcb 100644
--- a/lisp/calendar/timeclock.el
+++ b/lisp/calendar/timeclock.el
@@ -35,14 +35,14 @@
 ;; working day), and `timeclock-when-to-leave' to calculate when you're free.
 
 ;; You'll probably want to bind the timeclock commands to some handy
-;; keystrokes.  At the moment, C-x t is unused:
+;; keystrokes.  Assuming C-c t is unbound, you might use:
 ;;
-;;   (define-key ctl-x-map "ti" 'timeclock-in)
-;;   (define-key ctl-x-map "to" 'timeclock-out)
-;;   (define-key ctl-x-map "tc" 'timeclock-change)
-;;   (define-key ctl-x-map "tr" 'timeclock-reread-log)
-;;   (define-key ctl-x-map "tu" 'timeclock-update-mode-line)
-;;   (define-key ctl-x-map "tw" 'timeclock-when-to-leave-string)
+;;   (define-key (kbd "C-c t i") 'timeclock-in)
+;;   (define-key (kbd "C-c t o") 'timeclock-out)
+;;   (define-key (kbd "C-c t c") 'timeclock-change)
+;;   (define-key (kbd "C-c t r") 'timeclock-reread-log)
+;;   (define-key (kbd "C-c t u") 'timeclock-update-mode-line)
+;;   (define-key (kbd "C-c t w") 'timeclock-when-to-leave-string)
 
 ;; If you want Emacs to display the amount of time "left" to your
 ;; workday in the mode-line, you can either set the value of
@@ -88,6 +88,8 @@
   "The length of a work period in seconds."
   :type 'integer)
 
+(defvar timeclock--previous-workday nil)
+
 (defcustom timeclock-relative t
   "Whether to make reported time relative to `timeclock-workday'.
 For example, if the length of a normal workday is eight hours, and you
@@ -269,7 +271,10 @@ will be updated whenever the time display is updated.  
Otherwise,
 the timeclock will use its own sixty second timer to do its
 updating.  With prefix ARG, turn mode line display on if and only
 if ARG is positive.  Returns the new status of timeclock mode line
-display (non-nil means on)."
+display (non-nil means on).
+
+If using a customized `timeclock-workday' value, this should be
+set before switching this mode on."
   :global t
   ;; cf display-time-mode.
   (setq timeclock-mode-string "")
@@ -1058,7 +1063,9 @@ discrepancy, today's discrepancy, and the time worked 
today."
         (first t) (accum 0) (elapsed 0)
         event beg last-date
         last-date-limited last-date-seconds)
-    (unless timeclock-discrepancy
+    (when (or (not timeclock-discrepancy)
+              ;; The length of the workday has changed, so recompute.
+              (not (equal timeclock-workday timeclock--previous-workday)))
       (when (file-readable-p timeclock-file)
        (setq timeclock-project-list nil
              timeclock-last-project nil
@@ -1114,7 +1121,8 @@ discrepancy, today's discrepancy, and the time worked 
today."
                      last-date-seconds
                    timeclock-workday))
            (forward-line))
-         (setq timeclock-discrepancy accum))))
+         (setq timeclock-discrepancy accum
+                timeclock--previous-workday timeclock-workday))))
     (unless timeclock-last-event-workday
       (setq timeclock-last-event-workday timeclock-workday))
     (setq accum (or timeclock-discrepancy 0)
diff --git a/lisp/comint.el b/lisp/comint.el
index 7af8e8f..e058e6b 100644
--- a/lisp/comint.el
+++ b/lisp/comint.el
@@ -665,7 +665,8 @@ to continue it.
 \\{comint-mode-map}
 
 Entry to this mode runs the hooks on `comint-mode-hook'."
-  (setq mode-line-process '(":%s"))
+  (setq mode-line-process
+        (list (propertize ":%s" 'help-echo "Process status")))
   (setq-local window-point-insertion-type t)
   (setq-local comint-last-input-start (point-min-marker))
   (setq-local comint-last-input-end (point-min-marker))
@@ -3887,6 +3888,112 @@ REGEXP-GROUP is the regular expression group in REGEXP 
to use."
           ;; don't advance, so ensure forward progress.
          (forward-line 1)))
       (nreverse results))))
+
+
+;;; OSC escape sequences (Operating System Commands)
+;;============================================================================
+;; Adding `comint-osc-process-output' to `comint-output-filter-functions'
+;; enables the interpretation of OSC escape sequences.  By default, only
+;; OSC 8, for hyperlinks, is acted upon.  Adding more entries to
+;; `comint-osc-handlers' allows a customized treatment of further sequences.
+
+(defvar-local comint-osc-handlers '(("7" . comint-osc-directory-tracker)
+                                    ("8" . comint-osc-hyperlink-handler))
+  "Alist of handlers for OSC escape sequences.
+See `comint-osc-process-output' for details.")
+
+(defvar-local comint-osc--marker nil)
+
+(defun comint-osc-process-output (_)
+  "Interpret OSC escape sequences in comint output.
+This function is intended to be added to
+`comint-output-filter-functions' in order to interpret escape
+sequences of the forms
+
+    ESC ] command ; text BEL
+    ESC ] command ; text ESC \\
+
+Specifically, every occurrence of such escape sequences is
+removed from the buffer.  Then, if `command' is a key of the
+`comint-osc-handlers' alist, the corresponding value, which
+should be a function, is called with `command' and `text' as
+arguments, with point where the escape sequence was located."
+  (let ((bound (process-mark (get-buffer-process (current-buffer)))))
+    (save-excursion
+      ;; Start one char before last output to catch a possibly stray ESC
+      (goto-char (or comint-osc--marker (1- comint-last-output-start)))
+      (when (eq (char-before) ?\e) (backward-char))
+      (while (re-search-forward "\e]" bound t)
+        (let ((pos0 (match-beginning 0))
+              (code (and (re-search-forward "\\=\\([0-9A-Za-z]*\\);" bound t)
+                         (match-string 1)))
+              (pos1 (point)))
+          (if (re-search-forward "\a\\|\e\\\\" bound t)
+              (let ((text (buffer-substring-no-properties
+                           pos1 (match-beginning 0))))
+                (setq comint-osc--marker nil)
+                (delete-region pos0 (point))
+                (when-let ((fun (cdr (assoc-string code comint-osc-handlers))))
+                  (funcall fun code text)))
+            (put-text-property pos0 bound 'invisible t)
+            (setq comint-osc--marker (copy-marker pos0))))))))
+
+;; Current directory tracking (OSC 7)
+
+(declare-function url-host "url-parse.el")
+(declare-function url-type "url-parse.el")
+(declare-function url-filename "url-parse.el")
+(defun comint-osc-directory-tracker (_ text)
+  "Update `default-directory' from OSC 7 escape sequences.
+
+This function is intended to be included as an entry of
+`comint-osc-handlers'.  You should moreover arrange for your
+shell to print the appropriate escape sequence at each prompt,
+say with the following command:
+
+    printf \"\\e]7;file://%s%s\\e\\\\\" \"$HOSTNAME\" \"$PWD\"
+
+This functionality serves as an alternative to `dirtrack-mode'
+and `shell-dirtrack-mode'."
+  (let ((url (url-generic-parse-url text)))
+    (when (and (string= (url-type url) "file")
+               (or (null (url-host url))
+                   (string= (url-host url) (system-name))))
+      (ignore-errors
+        (cd-absolute (url-unhex-string (url-filename url)))))))
+
+;; Hyperlink handling (OSC 8)
+
+(defvar comint-osc-hyperlink-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map "\C-c\r" 'browse-url-button-open)
+    (define-key map [mouse-2] 'browse-url-button-open)
+    (define-key map [follow-link] 'mouse-face)
+    map)
+  "Keymap used by OSC 8 hyperlink buttons.")
+
+(define-button-type 'comint-osc-hyperlink
+  'keymap comint-osc-hyperlink-map
+  'help-echo (lambda (_ buffer pos)
+               (when-let ((url (get-text-property pos 'browse-url-data 
buffer)))
+                 (format "mouse-2, C-c RET: Open %s" url))))
+
+(defvar-local comint-osc-hyperlink--state nil)
+
+(defun comint-osc-hyperlink-handler (_ text)
+  "Create a hyperlink from an OSC 8 escape sequence.
+This function is intended to be included as an entry of
+`comint-osc-handlers'."
+  (when comint-osc-hyperlink--state
+    (let ((start (car comint-osc-hyperlink--state))
+          (url (cdr comint-osc-hyperlink--state)))
+      (make-text-button start (point)
+                        'type 'comint-osc-hyperlink
+                        'browse-url-data url)))
+  (setq comint-osc-hyperlink--state
+        (and (string-match ";\\(.+\\)" text)
+             (cons (point-marker) (match-string-no-properties 1 text)))))
+
 
 ;;; Converting process modes to use comint mode
 ;;============================================================================
diff --git a/lisp/cus-start.el b/lisp/cus-start.el
index 1997530..1a3e568 100644
--- a/lisp/cus-start.el
+++ b/lisp/cus-start.el
@@ -171,6 +171,8 @@ Leaving \"Default\" unchecked is equivalent with specifying 
a default of
               (const :tag "Right to Left" right-to-left)
               (const :tag "Dynamic, according to paragraph text" nil))
              "24.1")
+             (delete-auto-save-files auto-save boolean)
+             (kill-buffer-delete-auto-save-files auto-save boolean "28.1")
             ;; callint.c
             (mark-even-if-inactive editing-basics boolean)
             ;; callproc.c
diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el
index 0b8c693..c728642 100644
--- a/lisp/dired-aux.el
+++ b/lisp/dired-aux.el
@@ -1137,12 +1137,12 @@ present.  A FMT of \"\" will suppress the messaging."
     ("\\.tar\\.gz\\'" "" "gzip -dc %i | tar -xf -")
     ("\\.tar\\.xz\\'" "" "xz -dc %i | tar -xf -")
     ("\\.tgz\\'" "" "gzip -dc %i | tar -xf -")
-    ("\\.gz\\'" "" "gunzip")
+    ("\\.gz\\'" "" "gzip -d")
     ("\\.lz\\'" "" "lzip -d")
     ("\\.Z\\'" "" "uncompress")
     ;; For .z, try gunzip.  It might be an old gzip file,
     ;; or it might be from compact? pack? (which?) but gunzip handles both.
-    ("\\.z\\'" "" "gunzip")
+    ("\\.z\\'" "" "gzip -d")
     ("\\.dz\\'" "" "dictunzip")
     ("\\.tbz\\'" ".tar" "bunzip2")
     ("\\.bz2\\'" "" "bunzip2")
@@ -3245,10 +3245,13 @@ REGEXP should use constructs supported by your local 
`grep' command."
      (list (nth 0 common) (nth 1 common))))
   (require 'xref)
   (defvar xref-show-xrefs-function)
+  (defvar xref-auto-jump-to-first-xref)
   (with-current-buffer
       (let ((xref-show-xrefs-function
              ;; Some future-proofing (bug#44905).
-             (custom--standard-value 'xref-show-xrefs-function)))
+             (custom--standard-value 'xref-show-xrefs-function))
+            ;; Disable auto-jumping, it will mess up replacement logic.
+            xref-auto-jump-to-first-xref)
         (dired-do-find-regexp from))
     (xref-query-replace-in-results from to)))
 
diff --git a/lisp/dired.el b/lisp/dired.el
index ff82250..958677c 100644
--- a/lisp/dired.el
+++ b/lisp/dired.el
@@ -137,10 +137,9 @@ For more details, see Info node `(emacs)ls in Lisp'."
                  (const :tag "Do not use --dired" nil)
                  (other :tag "Always use --dired" t)))
 
-(defcustom dired-chmod-program "chmod"
-  "Name of chmod command (usually `chmod')."
-  :group 'dired
-  :type 'file)
+(defvar dired-chmod-program "chmod"
+  "Name of chmod command (usually `chmod').")
+(make-obsolete-variable 'dired-chmod-program nil "28.1")
 
 (defcustom dired-touch-program "touch"
   "Name of touch command (usually `touch')."
@@ -2194,6 +2193,21 @@ Do so according to the former subdir alist 
OLD-SUBDIR-ALIST."
     ["Delete Image Tag..." image-dired-delete-tag
      :help "Delete image tag from current or marked files"]))
 
+(defun dired-context-menu (menu)
+  (when (mouse-posn-property (event-start last-input-event) 'dired-filename)
+    (define-key menu [dired-separator] menu-bar-separator)
+    (let ((easy-menu (make-sparse-keymap "Immediate")))
+      (easy-menu-define nil easy-menu nil
+        '("Immediate"
+          ["Find This File" dired-mouse-find-file
+           :help "Edit file at mouse click"]
+          ["Find in Other Window" dired-mouse-find-file-other-window
+           :help "Edit file at mouse click in other window"]))
+      (dolist (item (reverse (lookup-key easy-menu [menu-bar immediate])))
+        (when (consp item)
+          (define-key menu (vector (car item)) (cdr item))))))
+  menu)
+
 
 ;;; Dired mode
 
@@ -2293,6 +2307,7 @@ Keybindings:
                 (append dired-dnd-protocol-alist dnd-protocol-alist)))
   (add-hook 'file-name-at-point-functions #'dired-file-name-at-point nil t)
   (add-hook 'isearch-mode-hook #'dired-isearch-filenames-setup nil t)
+  (add-hook 'context-menu-functions 'dired-context-menu 5 t)
   (run-mode-hooks 'dired-mode-hook))
 
 
@@ -4479,11 +4494,17 @@ Ask means pop up a menu for the user to select one of 
copy, move or link."
 ;;;###autoload
 (defun dired-jump (&optional other-window file-name)
   "Jump to Dired buffer corresponding to current buffer.
-If in a file, Dired the current directory and move to file's line.
+If in a buffer visiting a file, Dired that file's directory and
+move to that file's line in the directory listing.
+
+If the current buffer isn't visiting a file, Dired `default-directory'.
+
 If in Dired already, pop up a level and goto old directory's line.
 In case the proper Dired file line cannot be found, refresh the dired
 buffer and try again.
+
 When OTHER-WINDOW is non-nil, jump to Dired buffer in other window.
+
 When FILE-NAME is non-nil, jump to its line in Dired.
 Interactively with prefix argument, read FILE-NAME."
   (interactive
diff --git a/lisp/edmacro.el b/lisp/edmacro.el
index 9e4a71c..e18aad1 100644
--- a/lisp/edmacro.el
+++ b/lisp/edmacro.el
@@ -612,7 +612,7 @@ This function assumes that the events can be stored in a 
string."
                ((eq (car ev) 'switch-frame))
                ((equal ev '(menu-bar))
                 (push 'menu-bar result))
-               ((equal (cl-cadadr ev) '(menu-bar))
+                ((equal (cadadr ev) '(menu-bar))
                 (push (vector 'menu-bar (car ev)) result))
                ;; It would be nice to do pop-up menus, too, but not enough
                ;; info is recorded in macros to make this possible.
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index 7bd642d..145cdba 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -322,8 +322,9 @@ Elements of the list may be:
   make-local  calls to make-variable-buffer-local that may be incorrect.
   mapcar      mapcar called for effect.
   constants   let-binding of, or assignment to, constants/nonvariables.
-  docstrings  docstrings that are too wide (longer than 80 characters,
-              or `fill-column', whichever is bigger)
+  docstrings  docstrings that are too wide (longer than
+              `byte-compile-docstring-max-column' or
+              `fill-column' characters, whichever is bigger).
   suspicious  constructs that usually don't do what the coder wanted.
 
 If the list begins with `not', then the remaining elements specify warnings to
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el
index 4ef1948..4ea583d 100644
--- a/lisp/emacs-lisp/cl-macs.el
+++ b/lisp/emacs-lisp/cl-macs.el
@@ -2868,16 +2868,21 @@ in SLOTs.  It defines a `make-NAME' constructor, a 
`copy-NAME'
 copier, a `NAME-p' predicate, and slot accessors named `NAME-SLOT'.
 You can use the accessors to set the corresponding slots, via `setf'.
 
-NAME may instead take the form (NAME OPTIONS...), where each
-OPTION is either a single keyword or (KEYWORD VALUE) where
-KEYWORD can be one of `:conc-name', `:constructor', `:copier',
-`:predicate', `:type', `:named', `:initial-offset',
-`:print-function', `:noinline', or `:include'.  See Info
-node `(cl)Structures' for the description of the options.
-
-Each SLOT may instead take the form (SNAME SDEFAULT SOPTIONS...), where
-SDEFAULT is the default value of that slot and SOPTIONS are keyword-value
-pairs for that slot.
+NAME is usually a symbol, but may instead take the form (NAME
+OPTIONS...), where each OPTION is either a single keyword
+or (KEYWORD VALUE) where KEYWORD can be one of `:conc-name',
+`:constructor', `:copier', `:predicate', `:type', `:named',
+`:initial-offset', `:print-function', `:noinline', or `:include'.
+See Info node `(cl)Structures' for the description of the
+options.
+
+The first element in SLOTS can be a doc string.
+
+The rest of the elements in SLOTS is a list of SLOT elements,
+each of which should either be a symbol, or take the form (SNAME
+SDEFAULT SOPTIONS...), where SDEFAULT is the default value of
+that slot and SOPTIONS are keyword-value pairs for that slot.
+
 Supported keywords for slots are:
 - `:read-only': If this has a non-nil value, that slot cannot be set via 
`setf'.
 - `:documentation': this is a docstring describing the slot.
@@ -3283,6 +3288,7 @@ STRUCT-TYPE is a symbol naming a struct type.  Return 
`record',
       (push (cdr x) res))
     (nreverse res)))
 
+;;;###autoload
 (defun cl-struct-slot-info (struct-type)
   "Return a list of slot names of struct STRUCT-TYPE.
 Each entry is a list (SLOT-NAME . OPTS), where SLOT-NAME is a
diff --git a/lisp/emacs-lisp/comp-cstr.el b/lisp/emacs-lisp/comp-cstr.el
index 3c55782..6a3f604 100644
--- a/lisp/emacs-lisp/comp-cstr.el
+++ b/lisp/emacs-lisp/comp-cstr.el
@@ -152,7 +152,7 @@ Integer values are handled in the `range' slot.")
 (defun comp-cstrs-homogeneous (cstrs)
   "Check if constraints CSTRS are all homogeneously negated or non-negated.
 Return `pos' if they are all positive, `neg' if they are all
-negated or nil othewise."
+negated or nil otherwise."
   (cl-loop
    for cstr in cstrs
    unless (comp-cstr-neg cstr)
diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el
index ed75bf2..80a1da5 100644
--- a/lisp/emacs-lisp/comp.el
+++ b/lisp/emacs-lisp/comp.el
@@ -116,9 +116,9 @@ or one if there's just one execution unit."
   :version "28.1")
 
 (defcustom native-comp-async-cu-done-functions nil
-  "List of functions to call after asynchronously compiling one compilation 
unit.
-Called with one argument FILE, the filename used as input to
-compilation."
+  "List of functions to call when asynchronous compilation of a file is done.
+Each function is called with one argument FILE, the filename whose
+compilation has completed."
   :type 'hook
   :version "28.1")
 
@@ -3918,7 +3918,9 @@ display a message."
          do (let* ((expr `((require 'comp)
                            ,(when (boundp 'backtrace-line-length)
                               `(setf backtrace-line-length 
,backtrace-line-length))
-                           (setf native-comp-speed ,native-comp-speed
+                           (setf comp-file-preloaded-p ,comp-file-preloaded-p
+                                 native-compile-target-directory 
,native-compile-target-directory
+                                 native-comp-speed ,native-comp-speed
                                  native-comp-debug ,native-comp-debug
                                  native-comp-verbose ,native-comp-verbose
                                  comp-libgccjit-reproducer 
,comp-libgccjit-reproducer
diff --git a/lisp/emacs-lisp/debug.el b/lisp/emacs-lisp/debug.el
index 2007f79..f76ae3f 100644
--- a/lisp/emacs-lisp/debug.el
+++ b/lisp/emacs-lisp/debug.el
@@ -266,16 +266,15 @@ the debugger will not be entered."
                                    (window-frame debugger-previous-window)))
                          `((previous-window . ,debugger-previous-window))))))
                (setq debugger-window (selected-window))
-               (if (eq debugger-previous-window debugger-window)
-                   (when debugger-jumping-flag
-                     ;; Try to restore previous height of debugger
-                     ;; window.
-                     (condition-case nil
-                         (window-resize
-                          debugger-window
-                          (- debugger-previous-window-height
-                             (window-total-height debugger-window)))
-                       (error nil)))
+               (when debugger-jumping-flag
+                 ;; Try to restore previous height of debugger
+                 ;; window.
+                 (condition-case nil
+                     (window-resize
+                      debugger-window
+                      (- debugger-previous-window-height
+                         (window-total-height debugger-window)))
+                   (error nil))
                  (setq debugger-previous-window debugger-window))
                (message "")
                (let ((standard-output nil)
diff --git a/lisp/emacs-lisp/lisp.el b/lisp/emacs-lisp/lisp.el
index 2495277..9b38d86 100644
--- a/lisp/emacs-lisp/lisp.el
+++ b/lisp/emacs-lisp/lisp.el
@@ -186,12 +186,16 @@ report errors as appropriate for this kind of usage."
 This command will also work on other parentheses-like expressions
 defined by the current language mode.  With ARG, do this that
 many times.  A negative argument means move forward but still to
-a less deep spot.  If ESCAPE-STRINGS is non-nil (as it is
-interactively), move out of enclosing strings as well.  If
-NO-SYNTAX-CROSSING is non-nil (as it is interactively), prefer to
-break out of any enclosing string instead of moving to the start
-of a list broken across multiple strings.  On error, location of
-point is unspecified."
+a less deep spot.
+
+If ESCAPE-STRINGS is non-nil (as it is interactively), move out
+of enclosing strings as well.
+
+If NO-SYNTAX-CROSSING is non-nil (as it is interactively), prefer
+to break out of any enclosing string instead of moving to the
+start of a list broken across multiple strings.
+
+On error, location of point is unspecified."
   (interactive "^p\nd\nd")
   (up-list (- (or arg 1)) escape-strings no-syntax-crossing))
 
@@ -200,12 +204,16 @@ point is unspecified."
 This command will also work on other parentheses-like expressions
 defined by the current language mode.  With ARG, do this that
 many times.  A negative argument means move backward but still to
-a less deep spot.  If ESCAPE-STRINGS is non-nil (as it is
-interactively), move out of enclosing strings as well.  If
-NO-SYNTAX-CROSSING is non-nil (as it is interactively), prefer to
-break out of any enclosing string instead of moving to the start
-of a list broken across multiple strings.  On error, location of
-point is unspecified."
+a less deep spot.
+
+If ESCAPE-STRINGS is non-nil (as it is interactively), move out
+of enclosing strings as well.
+
+If NO-SYNTAX-CROSSING is non-nil (as it is interactively), prefer
+to break out of any enclosing string instead of moving to the
+end of a list broken across multiple strings.
+
+On error, location of point is unspecified."
   (interactive "^p\nd\nd")
   (or arg (setq arg 1))
   (let ((inc (if (> arg 0) 1 -1))
diff --git a/lisp/emacs-lisp/map-ynp.el b/lisp/emacs-lisp/map-ynp.el
index 0522b31..b95f11e 100644
--- a/lisp/emacs-lisp/map-ynp.el
+++ b/lisp/emacs-lisp/map-ynp.el
@@ -79,7 +79,7 @@ of the alist has the form (KEY FUNCTION HELP), where KEY is a 
character;
 FUNCTION is a function of one argument (an object from LIST); and HELP
 is a string.  When the user presses KEY, FUNCTION is called; if it
 returns non-nil, the object is considered to have been \"acted upon\",
-and `map-y-or-n-p' proceeeds to the next object from LIST.  If
+and `map-y-or-n-p' proceeds to the next object from LIST.  If
 FUNCTION returns nil, the prompt is re-issued for the same object: this
 comes in handy if FUNCTION produces some display that will allow the
 user to make an intelligent decision whether the object in question
diff --git a/lisp/emacs-lisp/map.el b/lisp/emacs-lisp/map.el
index 988a62a..77431f0 100644
--- a/lisp/emacs-lisp/map.el
+++ b/lisp/emacs-lisp/map.el
@@ -119,14 +119,16 @@ or array."
             ((key key) (default default) (testfn testfn))
           (funcall do `(map-elt ,mgetter ,key ,default)
                    (lambda (v)
-                     `(condition-case nil
-                          ;; Silence warnings about the hidden 4th arg.
-                          (with-no-warnings (map-put! ,mgetter ,key ,v 
,testfn))
-                        (map-not-inplace
-                         ,(funcall msetter
-                                   `(map-insert ,mgetter ,key ,v))
-                         ;; Always return the value.
-                         ,v))))))))
+                     (macroexp-let2 nil v v
+                       `(condition-case nil
+                            ;; Silence warnings about the hidden 4th arg.
+                            (with-no-warnings
+                              (map-put! ,mgetter ,key ,v ,testfn))
+                          (map-not-inplace
+                           ,(funcall msetter
+                                     `(map-insert ,mgetter ,key ,v))
+                           ;; Always return the value.
+                           ,v)))))))))
    ;; `testfn' is deprecated.
    (advertised-calling-convention (map key &optional default) "27.1"))
   ;; Can't use `cl-defmethod' with `advertised-calling-convention'.
diff --git a/lisp/emacs-lisp/memory-report.el b/lisp/emacs-lisp/memory-report.el
index aee2a00..3166d33 100644
--- a/lisp/emacs-lisp/memory-report.el
+++ b/lisp/emacs-lisp/memory-report.el
@@ -29,7 +29,7 @@
 
 (require 'seq)
 (require 'subr-x)
-(eval-when-compile (require 'cl-lib))
+(require 'cl-lib)
 
 (defvar memory-report--type-size (make-hash-table))
 
@@ -243,6 +243,19 @@ by counted more than once."
      value)
     total))
 
+;; All cl-defstruct types.
+(cl-defmethod memory-report--object-size-1 (counted (value 
cl-structure-object))
+  (let ((struct-type (type-of value)))
+    (apply #'+
+           (memory-report--size 'vector)
+           (mapcar (lambda (slot)
+                     (if (eq (car slot) 'cl-tag-slot)
+                         0
+                       (memory-report--object-size
+                        counted
+                        (cl-struct-slot-value struct-type (car slot) value))))
+                   (cl-struct-slot-info struct-type)))))
+
 (defun memory-report--format (bytes)
   (setq bytes (/ bytes 1024.0))
   (let ((units '("KiB" "MiB" "GiB" "TiB")))
diff --git a/lisp/emacs-lisp/nadvice.el b/lisp/emacs-lisp/nadvice.el
index 4804e85..41a9c72 100644
--- a/lisp/emacs-lisp/nadvice.el
+++ b/lisp/emacs-lisp/nadvice.el
@@ -85,42 +85,50 @@ Each element has the form (WHERE BYTECODE STACK) where:
       (if (eq bytecode (cadr elem)) (setq where (car elem))))
     where))
 
+(defun advice--make-single-doc (flist function macrop)
+  (let ((where (advice--where flist)))
+    (concat
+     (format "This %s has %s advice: "
+             (if macrop "macro" "function")
+             where)
+     (let ((fun (advice--car flist)))
+       (if (symbolp fun) (format-message "`%S'." fun)
+         (let* ((name (cdr (assq 'name (advice--props flist))))
+                (doc (documentation fun t))
+                (usage (help-split-fundoc doc function)))
+           (if usage (setq doc (cdr usage)))
+           (if name
+               (if doc
+                   (format "%s\n%s" name doc)
+                 (format "%s" name))
+             (or doc "No documentation")))))
+     "\n")))
+
 (defun advice--make-docstring (function)
   "Build the raw docstring for FUNCTION, presumably advised."
   (let* ((flist (indirect-function function))
          (docfun nil)
          (macrop (eq 'macro (car-safe flist)))
          (docstring nil))
-    (if macrop (setq flist (cdr flist)))
-    (while (advice--p flist)
-      (let ((doc (aref flist 4))
-            (where (advice--where flist)))
+    (when macrop
+      (setq flist (cdr flist)))
+    (if (and (autoloadp flist)
+             (get function 'advice--pending))
+        (setq docstring
+              (advice--make-single-doc (get function 'advice--pending)
+                                       function macrop))
+      (while (advice--p flist)
         ;; Hack attack!  For advices installed before calling
         ;; Snarf-documentation, the integer offset into the DOC file will not
         ;; be installed in the "core unadvised function" but in the advice
         ;; object instead!  So here we try to undo the damage.
-        (if (integerp doc) (setq docfun flist))
-        (setq docstring
-              (concat
-               docstring
-               (format "This %s has %s advice: "
-                       (if macrop "macro" "function")
-                       where)
-               (let ((fun (advice--car flist)))
-                 (if (symbolp fun) (format-message "`%S'." fun)
-                   (let* ((name (cdr (assq 'name (advice--props flist))))
-                          (doc (documentation fun t))
-                          (usage (help-split-fundoc doc function)))
-                     (if usage (setq doc (cdr usage)))
-                     (if name
-                         (if doc
-                             (format "%s\n%s" name doc)
-                           (format "%s" name))
-                       (or doc "No documentation")))))
-               "\n")))
-      (setq flist (advice--cdr flist)))
-    (if docstring (setq docstring (concat docstring "\n")))
-    (unless docfun (setq docfun flist))
+        (when (integerp (aref flist 4))
+          (setq docfun flist))
+        (setq docstring (concat docstring (advice--make-single-doc
+                                           flist function macrop))
+              flist (advice--cdr flist))))
+    (unless docfun
+      (setq docfun flist))
     (let* ((origdoc (unless (eq function docfun) ;Avoid inf-loops.
                       (documentation docfun t)))
            (usage (help-split-fundoc origdoc function)))
@@ -131,7 +139,12 @@ Each element has the form (WHERE BYTECODE STACK) where:
                         (if (stringp arglist) t
                           (help--make-usage-docstring function arglist)))
                     (setq origdoc (cdr usage)) (car usage)))
-      (help-add-fundoc-usage (concat docstring origdoc) usage))))
+      (help-add-fundoc-usage (concat origdoc
+                                     (if (string-suffix-p "\n" origdoc)
+                                         "\n"
+                                       "\n\n")
+                                     docstring)
+                             usage))))
 
 (defun advice-eval-interactive-spec (spec)
   "Evaluate the interactive spec SPEC."
diff --git a/lisp/emacs-lisp/rx.el b/lisp/emacs-lisp/rx.el
index 071d390..c48052d 100644
--- a/lisp/emacs-lisp/rx.el
+++ b/lisp/emacs-lisp/rx.el
@@ -1266,7 +1266,8 @@ Zero-width assertions: these all match the empty string 
in specific places.
 
 (literal EXPR) Match the literal string from evaluating EXPR at run time.
 (regexp EXPR)  Match the string regexp from evaluating EXPR at run time.
-(eval EXPR)    Match the rx sexp from evaluating EXPR at compile time.
+(eval EXPR)    Match the rx sexp from evaluating EXPR at macro-expansion
+                (compile) time.
 
 Additional constructs can be defined using `rx-define' and `rx-let',
 which see.
diff --git a/lisp/emacs-lisp/tabulated-list.el 
b/lisp/emacs-lisp/tabulated-list.el
index f0ee787..f148bc1 100644
--- a/lisp/emacs-lisp/tabulated-list.el
+++ b/lisp/emacs-lisp/tabulated-list.el
@@ -271,12 +271,15 @@ Populated by `tabulated-list-init-header'.")
 (defun tabulated-list-init-header ()
   "Set up header line for the Tabulated List buffer."
   ;; FIXME: Should share code with tabulated-list-print-col!
-  (let ((x (max tabulated-list-padding 0))
-       (button-props `(help-echo "Click to sort by column"
-                                 mouse-face header-line-highlight
-                                 keymap ,tabulated-list-sort-button-map))
-        (len (length tabulated-list-format))
-       (cols nil))
+  (let* ((x (max tabulated-list-padding 0))
+        (button-props `(help-echo "Click to sort by column"
+                                  mouse-face header-line-highlight
+                                  keymap ,tabulated-list-sort-button-map))
+         (len (length tabulated-list-format))
+         ;; Pre-compute width for available-space compution.
+         (hcols (mapcar #'car tabulated-list-format))
+         (tabulated-list--near-rows (list hcols hcols))
+        (cols nil))
     (if display-line-numbers
         (setq x (+ x (tabulated-list-line-number-width))))
     (push (propertize " " 'display `(space :align-to ,x)) cols)
@@ -290,9 +293,17 @@ Populated by `tabulated-list-init-header'.")
             (props (nthcdr 3 col))
             (pad-right (or (plist-get props :pad-right) 1))
              (right-align (plist-get props :right-align))
-             (next-x (+ x pad-right width)))
-        (when (and (>= lablen 3) (> lablen width) not-last-col)
-          (setq label (truncate-string-to-width label (- lablen 1) nil nil t)))
+             (next-x (+ x pad-right width))
+             (available-space
+              (and not-last-col
+                   (if right-align
+                       width
+                     (tabulated-list--available-space width n)))))
+        (when (and (>= lablen 3)
+                   not-last-col
+                   (> lablen available-space))
+          (setq label (truncate-string-to-width label available-space
+                                                nil nil t)))
        (push
         (cond
          ;; An unsortable column
@@ -481,6 +492,8 @@ changing `tabulated-list-sort-key'."
               (forward-line 1)
               (delete-region old (point))))))
       (setq entries (cdr entries)))
+    (when update
+      (delete-region (point) (point-max)))
     (set-buffer-modified-p nil)
     ;; If REMEMBER-POS was specified, move to the "old" location.
     (if saved-pt
@@ -512,6 +525,17 @@ of column descriptors."
      beg (point)
      `(tabulated-list-id ,id tabulated-list-entry ,cols))))
 
+(defun tabulated-list--available-space (width n)
+  (let* ((next-col-format (aref tabulated-list-format (1+ n)))
+         (next-col-right-align (plist-get (nthcdr 3 next-col-format)
+                                          :right-align))
+         (next-col-width (nth 1 next-col-format)))
+    (if next-col-right-align
+        (- (+ width next-col-width)
+           (min next-col-width
+                (tabulated-list--col-local-max-widths (1+ n))))
+      width)))
+
 (defun tabulated-list-print-col (n col-desc x)
   "Insert a specified Tabulated List entry at point.
 N is the column number, COL-DESC is a column descriptor (see
@@ -528,20 +552,10 @@ Return the column number after insertion."
         (help-echo (concat (car format) ": " label))
         (opoint (point))
         (not-last-col (< (1+ n) (length tabulated-list-format)))
-         available-space)
-    (when not-last-col
-      (let* ((next-col-format (aref tabulated-list-format (1+ n)))
-             (next-col-right-align (plist-get (nthcdr 3 next-col-format)
-                                              :right-align))
-             (next-col-width (nth 1 next-col-format)))
-        (setq available-space
-              (if (and (not right-align)
-                       next-col-right-align)
-                  (-
-                   (+ width next-col-width)
-                   (min next-col-width
-                        (tabulated-list--col-local-max-widths (1+ n))))
-                width))))
+        (available-space (and not-last-col
+                               (if right-align
+                                   width
+                                 (tabulated-list--available-space width n)))))
     ;; Truncate labels if necessary (except last column).
     ;; Don't truncate to `width' if the next column is align-right
     ;; and has some space left, truncate to `available-space' instead.
diff --git a/lisp/emacs-lisp/timer.el b/lisp/emacs-lisp/timer.el
index 36de29a..44d70cd 100644
--- a/lisp/emacs-lisp/timer.el
+++ b/lisp/emacs-lisp/timer.el
@@ -29,10 +29,12 @@
 
 (eval-when-compile (require 'cl-lib))
 
+;; If you change this structure, you also have to change `timerp'
+;; (below) and decode_timer in keyboard.c.
 (cl-defstruct (timer
                (:constructor nil)
                (:copier nil)
-               (:constructor timer-create ())
+               (:constructor timer--create ())
                (:type vector)
                (:conc-name timer--))
   ;; nil if the timer is active (waiting to be triggered),
@@ -46,11 +48,25 @@
   repeat-delay
   function args                         ;What to do when triggered.
   idle-delay                            ;If non-nil, this is an idle-timer.
-  psecs)
+  psecs
+  ;; A timer may be created with `t' as the TIME, which means that we
+  ;; want to run at specific integral multiples of `repeat-delay'.  We
+  ;; then have to recompute this (because the machine may have gone to
+  ;; sleep, etc).
+  integral-multiple)
+
+(defun timer-create ()
+  ;; BEWARE: This is not an eta-redex, because `timer--create' is inlinable
+  ;; whereas `timer-create' should not be because we don't want to
+  ;; hardcode the shape of timers in other .elc files.
+  (timer--create))
 
 (defun timerp (object)
   "Return t if OBJECT is a timer."
-  (and (vectorp object) (= (length object) 9)))
+  (and (vectorp object)
+       ;; Timers are now ten elements, but old .elc code may have
+       ;; shorter versions of `timer-create'.
+       (<= 9 (length object) 10)))
 
 (defsubst timer--check (timer)
   (or (timerp timer) (signal 'wrong-type-argument (list #'timerp timer))))
@@ -284,6 +300,14 @@ This function is called, by name, directly by the C code."
                     (if (> repeats timer-max-repeats)
                         (timer-inc-time timer (* (timer--repeat-delay timer)
                                                  repeats)))))
+              ;; If we want integral multiples, we have to recompute
+              ;; the repetition.
+              (when (and (> (length timer) 9) ; Backwards compatible.
+                         (timer--integral-multiple timer)
+                         (not (timer--idle-delay timer)))
+                (setf (timer--time timer)
+                      (timer-next-integral-multiple-of-time
+                       (current-time) (timer--repeat-delay timer))))
               ;; Place it back on the timer-list before running
               ;; timer--function, so it can cancel-timer itself.
               (timer-activate timer t cell)
@@ -340,45 +364,44 @@ This function returns a timer object which you can use in
 `cancel-timer'."
   (interactive "sRun at time: \nNRepeat interval: \naFunction: ")
 
-  (or (null repeat)
-      (and (numberp repeat) (< 0 repeat))
-      (error "Invalid repetition interval"))
+  (when (and repeat
+             (numberp repeat)
+             (< repeat 0))
+    (error "Invalid repetition interval"))
 
-  ;; Special case: nil means "now" and is useful when repeating.
-  (if (null time)
+  (let ((timer (timer-create)))
+    ;; Special case: nil means "now" and is useful when repeating.
+    (unless time
       (setq time (current-time)))
 
-  ;; Special case: t means the next integral multiple of REPEAT.
-  (if (and (eq time t) repeat)
-      (setq time (timer-next-integral-multiple-of-time (current-time) repeat)))
+    ;; Special case: t means the next integral multiple of REPEAT.
+    (when (and (eq time t) repeat)
+      (setq time (timer-next-integral-multiple-of-time (current-time) repeat))
+      (setf (timer--integral-multiple timer) t))
 
-  ;; Handle numbers as relative times in seconds.
-  (if (numberp time)
+    ;; Handle numbers as relative times in seconds.
+    (when (numberp time)
       (setq time (timer-relative-time nil time)))
 
-  ;; Handle relative times like "2 hours 35 minutes"
-  (if (stringp time)
-      (let ((secs (timer-duration time)))
-       (if secs
-           (setq time (timer-relative-time nil secs)))))
-
-  ;; Handle "11:23pm" and the like.  Interpret it as meaning today
-  ;; which admittedly is rather stupid if we have passed that time
-  ;; already.  (Though only Emacs hackers hack Emacs at that time.)
-  (if (stringp time)
-      (progn
-       (require 'diary-lib)
-       (let ((hhmm (diary-entry-time time))
-             (now (decode-time)))
-         (if (>= hhmm 0)
-             (setq time
-                   (encode-time 0 (% hhmm 100) (/ hhmm 100)
-                                 (decoded-time-day now)
-                                (decoded-time-month now)
-                                 (decoded-time-year now)
-                                 (decoded-time-zone now)))))))
+    ;; Handle relative times like "2 hours 35 minutes".
+    (when (stringp time)
+      (when-let ((secs (timer-duration time)))
+       (setq time (timer-relative-time nil secs))))
+
+    ;; Handle "11:23pm" and the like.  Interpret it as meaning today
+    ;; which admittedly is rather stupid if we have passed that time
+    ;; already.  (Though only Emacs hackers hack Emacs at that time.)
+    (when (stringp time)
+      (require 'diary-lib)
+      (let ((hhmm (diary-entry-time time))
+           (now (decode-time)))
+       (when (>= hhmm 0)
+         (setq time (encode-time 0 (% hhmm 100) (/ hhmm 100)
+                                  (decoded-time-day now)
+                                 (decoded-time-month now)
+                                  (decoded-time-year now)
+                                  (decoded-time-zone now))))))
 
-  (let ((timer (timer-create)))
     (timer-set-time timer time repeat)
     (timer-set-function timer function args)
     (timer-activate timer)
diff --git a/lisp/epg.el b/lisp/epg.el
index 9d62955..a461afa 100644
--- a/lisp/epg.el
+++ b/lisp/epg.el
@@ -25,6 +25,7 @@
 ;;; Prelude
 
 (require 'epg-config)
+(require 'rfc6068)
 (eval-when-compile (require 'cl-lib))
 
 (define-error 'epg-error "GPG error")
@@ -432,7 +433,7 @@ callback data (if any)."
      (and user-id
          (concat " "
                  (if (stringp user-id)
-                     (epg--decode-percent-escape-as-utf-8 user-id)
+                     (rfc6068-unhexify-string user-id)
                    (epg-decode-dn user-id))))
      (and (epg-signature-validity signature)
          (format " (trust %s)"  (epg-signature-validity signature)))
@@ -656,16 +657,17 @@ callback data (if any)."
                             :sentinel #'ignore
                             :noquery t))
     (setf (epg-context-error-buffer context) (process-buffer error-process))
-    (with-file-modes 448
-      (setq process (make-process :name "epg"
-                                 :buffer buffer
-                                 :command (cons (epg-context-program context)
-                                                args)
-                                 :connection-type 'pipe
-                                 :coding 'raw-text
-                                 :filter #'epg--process-filter
-                                 :stderr error-process
-                                 :noquery t)))
+    (with-existing-directory
+      (with-file-modes 448
+        (setq process (make-process :name "epg"
+                                   :buffer buffer
+                                   :command (cons (epg-context-program context)
+                                                  args)
+                                   :connection-type 'pipe
+                                   :coding 'raw-text
+                                   :filter #'epg--process-filter
+                                   :stderr error-process
+                                   :noquery t))))
     (setf (epg-context-process context) process)))
 
 (defun epg--process-filter (process input)
@@ -777,7 +779,7 @@ callback data (if any)."
             (user-id (match-string 2 string))
             (entry (assoc key-id epg-user-id-alist)))
        (condition-case nil
-           (setq user-id (epg--decode-percent-escape-as-utf-8 user-id))
+           (setq user-id (rfc6068-unhexify-string user-id))
          (error))
        (if entry
            (setcdr entry user-id)
@@ -906,7 +908,7 @@ callback data (if any)."
        (condition-case nil
            (if (eq (epg-context-protocol context) 'CMS)
                (setq user-id (epg-dn-from-string user-id))
-             (setq user-id (epg--decode-percent-escape-as-utf-8 user-id)))
+             (setq user-id (rfc6068-unhexify-string user-id)))
          (error))
        (if entry
            (setcdr entry user-id)
@@ -1182,7 +1184,7 @@ callback data (if any)."
             (user-id (match-string 2 string))
             (entry (assoc key-id epg-user-id-alist)))
        (condition-case nil
-           (setq user-id (epg--decode-percent-escape-as-utf-8 user-id))
+           (setq user-id (rfc6068-unhexify-string user-id))
          (error))
        (if entry
            (setcdr entry user-id)
@@ -2061,9 +2063,11 @@ If you are unsure, use synchronous version of this 
function
     string))
 
 (defun epg--decode-percent-escape-as-utf-8 (string)
+  (declare (obsolete rfc6068-unhexify-string "28.1"))
   (decode-coding-string (epg--decode-percent-escape string) 'utf-8))
 
 (defun epg--decode-hexstring (string)
+  (declare (obsolete rfc6068-unhexify-string "28.1"))
   (let ((index 0))
     (while (eq index (string-match "[[:xdigit:]][[:xdigit:]]" string index))
       (setq string (replace-match (string (string-to-number
@@ -2114,7 +2118,7 @@ The return value is an alist mapping from types to 
values."
                value (epg--decode-quotedstring (match-string 0 string)))
        (if (eq index (string-match "#\\([[:xdigit:]]+\\)" string index))
            (setq index (match-end 0)
-                 value (epg--decode-hexstring (match-string 1 string)))
+                 value (rfc6068-unhexify-string (match-string 1 string) t))
          (if (eq index (string-match "\"\\([^\\\"]\\|\\\\.\\)*\""
                                      string index))
              (setq index (match-end 0)
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index 7320201..e0fda41 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -2271,7 +2271,7 @@ first element is the certificate key file name, and the 
second
 element is the certificate file name itself, or t, which means
 that `auth-source' will be queried for the key and the
 certificate.  Authenticating using a TLS client certificate is
-also refered to as \"CertFP\" (Certificate Fingerprint)
+also referred to as \"CertFP\" (Certificate Fingerprint)
 authentication by various IRC networks.
 
 Example usage:
diff --git a/lisp/eshell/em-cmpl.el b/lisp/eshell/em-cmpl.el
index cbfe0b8..4fd0afb 100644
--- a/lisp/eshell/em-cmpl.el
+++ b/lisp/eshell/em-cmpl.el
@@ -72,6 +72,7 @@
 
 (require 'esh-mode)
 (require 'esh-util)
+(require 'em-dirs)
 
 (eval-when-compile
   (require 'cl-lib)
@@ -377,8 +378,12 @@ to writing a completion function."
                           (cl-assert (eq (car result) 'quote))
                           (cadr result))
                       arg)))
-               (if (numberp val)
-                   (setq val (number-to-string val)))
+               (cond ((numberp val)
+                      (setq val (number-to-string val)))
+                     ;; expand .../ etc that only eshell understands to
+                     ;; standard ../../
+                     ((string-match "\\.\\.\\.+/" val)
+                      (setq val (eshell-expand-multiple-dots val))))
                (or val "")))
           args)
          posns)))
diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el
index daca035..90a8f85 100644
--- a/lisp/eshell/esh-cmd.el
+++ b/lisp/eshell/esh-cmd.el
@@ -923,10 +923,10 @@ at the moment are:
 (defun eshell-eval-command (command &optional input)
   "Evaluate the given COMMAND iteratively."
   (if eshell-current-command
-      ;; we can just stick the new command at the end of the current
-      ;; one, and everything will happen as it should
+      ;; We can just stick the new command at the end of the current
+      ;; one, and everything will happen as it should.
       (setcdr (last (cdr eshell-current-command))
-             (list `(let ((here (and (eobp) (point))))
+              (list `(let ((here (and (eobp) (point))))
                        ,(and input
                              `(insert-and-inherit ,(concat input "\n")))
                        (if here
@@ -937,14 +937,20 @@ at the moment are:
            (erase-buffer)
            (insert "command: \"" input "\"\n")))
     (setq eshell-current-command command)
-    (let ((delim (catch 'eshell-incomplete
-                  (eshell-resume-eval))))
-      ;; On systems that don't support async subprocesses, eshell-resume
-      ;; can return t.  Don't treat that as an error.
-      (if (listp delim)
-         (setq delim (car delim)))
-      (if (and delim (not (eq delim t)))
-         (error "Unmatched delimiter: %c" delim)))))
+    (let* ((delim (catch 'eshell-incomplete
+                    (eshell-resume-eval)))
+           (val (car-safe delim)))
+      ;; If the return value of `eshell-resume-eval' is wrapped in a
+      ;; list, it indicates that the command was run asynchronously.
+      ;; In that case, unwrap the value before checking the delimiter
+      ;; value.
+      (if (and val
+               (not (processp val))
+               (not (eq val t)))
+          (error "Unmatched delimiter: %S" val)
+        ;; Eshell-command expect a list like (<process>) to know if the
+        ;; command should be async or not.
+        (or (and (processp val) delim) val)))))
 
 (defun eshell-resume-command (proc status)
   "Resume the current command when a process ends."
diff --git a/lisp/faces.el b/lisp/faces.el
index a3a6f1b..a5aef75 100644
--- a/lisp/faces.el
+++ b/lisp/faces.el
@@ -1795,18 +1795,21 @@ If FRAME is nil, that stands for the selected frame."
     (mapcar 'car (tty-color-alist frame))))
 (defalias 'x-defined-colors 'defined-colors)
 
-(defun defined-colors-with-face-attributes (&optional frame)
+(defun defined-colors-with-face-attributes (&optional frame foreground)
   "Return a list of colors supported for a particular frame.
 See `defined-colors' for arguments and return value. In contrast
 to `defined-colors' the elements of the returned list are color
 strings with text properties, that make the color names render
-with the color they represent as background color."
+with the color they represent as background color (if FOREGROUND
+is nil; otherwise use the foreground color)."
   (mapcar
    (lambda (color-name)
-     (let ((foreground (readable-foreground-color color-name))
-          (color      (copy-sequence color-name)))
-       (propertize color 'face (list :foreground foreground
-                                    :background color))))
+     (let ((color (copy-sequence color-name)))
+       (propertize color 'face
+                  (if foreground
+                      (list :foreground color)
+                    (list :foreground (readable-foreground-color color-name)
+                           :background color)))))
    (defined-colors frame)))
 
 (defun readable-foreground-color (color)
@@ -1915,7 +1918,8 @@ If omitted or nil, that stands for the selected frame's 
display."
       (x-display-grayscale-p display)
     (> (tty-color-gray-shades display) 2)))
 
-(defun read-color (&optional prompt convert-to-RGB allow-empty-name msg)
+(defun read-color (&optional prompt convert-to-RGB allow-empty-name msg
+                            foreground)
   "Read a color name or RGB triplet.
 Completion is available for color names, but not for RGB triplets.
 
@@ -1942,13 +1946,18 @@ If optional arg ALLOW-EMPTY-NAME is non-nil, the user 
is allowed
 to enter an empty color name (the empty string).
 
 Interactively, or with optional arg MSG non-nil, print the
-resulting color name in the echo area."
+resulting color name in the echo area.
+
+Interactively, displays a list of colored completions.  If optional
+argument FOREGROUND is non-nil, shows them as foregrounds, otherwise
+as backgrounds."
   (interactive "i\np\ni\np")    ; Always convert to RGB interactively.
   (let* ((completion-ignore-case t)
         (colors (append '("foreground at point" "background at point")
                         (if allow-empty-name '(""))
                          (if (display-color-p)
-                             (defined-colors-with-face-attributes)
+                             (defined-colors-with-face-attributes
+                               nil foreground)
                            (defined-colors))))
         (color (completing-read
                 (or prompt "Color (name or #RGB triplet): ")
diff --git a/lisp/files.el b/lisp/files.el
index 875ac55..7e4bdab 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -42,15 +42,6 @@
   "Finding files."
   :group 'files)
 
-
-(defcustom delete-auto-save-files t
-  "Non-nil means delete auto-save file when a buffer is saved or killed.
-
-Note that the auto-save file will not be deleted if the buffer is killed
-when it has unsaved changes."
-  :type 'boolean
-  :group 'auto-save)
-
 (defcustom directory-abbrev-alist
   nil
   "Alist of abbreviations for file directories.
@@ -257,7 +248,7 @@ This feature is advisory: for example, if the directory in 
which the
 file is being saved is not writable, Emacs may ignore a non-nil value
 of `file-precious-flag' and write directly into the file.
 
-See also: `break-hardlink-on-save'."
+See also: `break-hardlink-on-save' and `file-preserve-symlinks-on-save'."
   :type 'boolean
   :group 'backup)
 
@@ -2360,7 +2351,7 @@ the various files."
                         ((not query-about-changed-file)
                          (message
                           (substitute-command-keys
-                           "File %s changed on disk.  \\[revert-buffer] to 
load new contents%s")
+                           "File %s changed on disk.  \\[revert-buffer-quick] 
to load new contents%s")
                           (file-name-nondirectory filename)
                           (if (buffer-modified-p buf)
                               " and discard your edits"
@@ -5033,7 +5024,7 @@ FILENAME has the format of a directory.
 See also `file-name-sans-extension'."
   (let ((extn (string-trim-left extension "[.]")))
     (cond ((string-empty-p filename)
-           (error "Empty filename: %s" filename))
+           (error "Empty filename"))
           ((string-empty-p extn)
            (error "Malformed extension: %s" extension))
           ((directory-name-p filename)
@@ -5437,6 +5428,23 @@ Used only by `save-buffer'."
   :type 'hook
   :group 'files)
 
+(defcustom copy-directory-create-symlink nil
+  "This option influences the handling of symbolic links in `copy-directory'.
+If non-nil, `copy-directory' will create a symbolic link if the
+source directory is a symbolic link.  If nil, it'll follow the
+symbolic link and copy the contents instead."
+  :type 'boolean
+  :version "28.1"
+  :group 'files)
+
+(defcustom file-preserve-symlinks-on-save nil
+  "If non-nil, saving a buffer visited via a symlink won't overwrite the 
symlink.
+This is only relevant if `file-precious-flag' is non-nil -- if
+this is nil, Emacs will preserve the symlinks anyway."
+  :type 'boolean
+  :version "28.1"
+  :group 'files)
+
 (defvar-local save-buffer-coding-system nil
   "If non-nil, use this coding system for saving the buffer.
 More precisely, use this coding system in place of the
@@ -5639,7 +5647,14 @@ Before and after saving the buffer, this function runs
                                     buffer-file-name)))
            ;; We succeeded in writing the temp file,
            ;; so rename it.
-           (rename-file tempname buffer-file-name t))
+           (rename-file tempname
+                         (if (and file-preserve-symlinks-on-save
+                                  (file-symlink-p buffer-file-name))
+                             ;; Write to the file that the symlink
+                             ;; points to.
+                             (file-chase-links buffer-file-name)
+                           buffer-file-name)
+                         t))
        ;; If file not writable, see if we can make it writable
        ;; temporarily while we write it.
        ;; But no need to do so if we have just backed it up
@@ -6165,6 +6180,9 @@ Noninteractively, the PARENTS argument says whether to 
create
 parent directories if they don't exist.  Interactively, this
 happens by default.
 
+If DIRECTORY is a symlink and `copy-directory-create-symlink' is
+non-nil, create a symlink with the same target as DIRECTORY.
+
 If NEWNAME is a directory name, copy DIRECTORY as a subdirectory
 there.  However, if called from Lisp with a non-nil optional
 argument COPY-CONTENTS, copy the contents of DIRECTORY directly
@@ -6193,42 +6211,53 @@ into NEWNAME instead."
       (setq directory (directory-file-name (expand-file-name directory))
            newname (expand-file-name newname))
 
-      (cond ((not (directory-name-p newname))
-            ;; If NEWNAME is not a directory name, create it;
-            ;; that is where we will copy the files of DIRECTORY.
-            (make-directory newname parents))
-           ;; NEWNAME is a directory name.  If COPY-CONTENTS is non-nil,
-           ;; create NEWNAME if it is not already a directory;
-           ;; otherwise, create NEWNAME/[DIRECTORY-BASENAME].
-           ((if copy-contents
-                (or parents (not (file-directory-p newname)))
-              (setq newname (concat newname
-                                    (file-name-nondirectory directory))))
-            (make-directory (directory-file-name newname) parents))
-           (t (setq follow t)))
-
-      ;; Copy recursively.
-      (dolist (file
-              ;; We do not want to copy "." and "..".
-              (directory-files directory 'full
-                               directory-files-no-dot-files-regexp))
-       (let ((target (concat (file-name-as-directory newname)
-                             (file-name-nondirectory file)))
-             (filetype (car (file-attributes file))))
-         (cond
-          ((eq filetype t)       ; Directory but not a symlink.
-           (copy-directory file target keep-time parents t))
-          ((stringp filetype)    ; Symbolic link
-           (make-symbolic-link filetype target t))
-          ((copy-file file target t keep-time)))))
-
-      ;; Set directory attributes.
-      (let ((modes (file-modes directory))
-           (times (and keep-time (file-attribute-modification-time
-                                  (file-attributes directory))))
-           (follow-flag (unless follow 'nofollow)))
-       (if modes (set-file-modes newname modes follow-flag))
-       (if times (set-file-times newname times follow-flag))))))
+      ;; If DIRECTORY is a symlink, create a symlink with the same target.
+      (if (and (file-symlink-p directory)
+               copy-directory-create-symlink)
+          (let ((target (car (file-attributes directory))))
+           (if (directory-name-p newname)
+               (make-symbolic-link target
+                                   (concat newname
+                                           (file-name-nondirectory directory))
+                                   t)
+             (make-symbolic-link target newname t)))
+        ;; Else proceed to copy as a regular directory
+        (cond ((not (directory-name-p newname))
+              ;; If NEWNAME is not a directory name, create it;
+              ;; that is where we will copy the files of DIRECTORY.
+              (make-directory newname parents))
+             ;; NEWNAME is a directory name.  If COPY-CONTENTS is non-nil,
+             ;; create NEWNAME if it is not already a directory;
+             ;; otherwise, create NEWNAME/[DIRECTORY-BASENAME].
+             ((if copy-contents
+                  (or parents (not (file-directory-p newname)))
+                (setq newname (concat newname
+                                      (file-name-nondirectory directory))))
+              (make-directory (directory-file-name newname) parents))
+             (t (setq follow t)))
+
+        ;; Copy recursively.
+        (dolist (file
+                ;; We do not want to copy "." and "..".
+                (directory-files directory 'full
+                                 directory-files-no-dot-files-regexp))
+         (let ((target (concat (file-name-as-directory newname)
+                               (file-name-nondirectory file)))
+               (filetype (car (file-attributes file))))
+           (cond
+            ((eq filetype t)           ; Directory but not a symlink.
+             (copy-directory file target keep-time parents t))
+            ((stringp filetype)        ; Symbolic link
+             (make-symbolic-link filetype target t))
+            ((copy-file file target t keep-time)))))
+
+        ;; Set directory attributes.
+        (let ((modes (file-modes directory))
+             (times (and keep-time (file-attribute-modification-time
+                                    (file-attributes directory))))
+             (follow-flag (unless follow 'nofollow)))
+         (if modes (set-file-modes newname modes follow-flag))
+         (if times (set-file-times newname times follow-flag)))))))
 
 
 ;; At time of writing, only info uses this.
diff --git a/lisp/finder.el b/lisp/finder.el
index c2d5806..555506d 100644
--- a/lisp/finder.el
+++ b/lisp/finder.el
@@ -247,7 +247,7 @@ from; the default is `load-path'."
                  ;; The idea here is that eg calc.el gets to define
                  ;; the description of the calc package.
                  ;; This does not work for eg nxml-mode.el.
-                 ((or (eq base-name package) version)
+                 ((eq base-name package)
                   (setq desc (cdr entry))
                   (aset desc 0 version)
                   (aset desc 2 summary)))
diff --git a/lisp/follow.el b/lisp/follow.el
index dde140d..b64f4cb 100644
--- a/lisp/follow.el
+++ b/lisp/follow.el
@@ -858,8 +858,11 @@ from the bottom."
           (windows (follow-all-followers))
           (win (nth (/ (- (length windows) 1) 2) windows)))
       (select-window win)
-      (goto-char dest)
-      (recenter))))
+      (let ((win-s (window-start)))
+        (goto-char dest)
+        (recenter)
+        (when (< dest win-s)
+          (setq follow-internal-force-redisplay t))))))
 
 
 (defun follow-redraw ()
diff --git a/lisp/frame.el b/lisp/frame.el
index 146fe27..60234fc 100644
--- a/lisp/frame.el
+++ b/lisp/frame.el
@@ -787,6 +787,26 @@ When called from Lisp, returns the new frame."
       (make-frame)
     (select-frame (make-frame))))
 
+(defun clone-frame (&optional frame use-default-parameters)
+  "Make a new frame with the same parameters as FRAME.
+With a prefix arg (USE-DEFAULT-PARAMETERS), use
+`default-frame-alist' instead.
+
+FRAME defaults to the selected frame.  The frame is created on the
+same terminal as FRAME.  If the terminal is a text-only terminal then
+also select the new frame."
+  (interactive "i\nP")
+  (if use-default-parameters
+      (make-frame-command)
+    (let* ((default-frame-alist (seq-filter
+                                 (lambda (elem)
+                                   (not (eq (car elem) 'name)))
+                                 (frame-parameters frame)))
+           (new-frame (make-frame)))
+      (unless (display-graphic-p)
+        (select-frame new-frame))
+      new-frame)))
+
 (defvar before-make-frame-hook nil
   "Functions to run before `make-frame' creates a new frame.")
 
@@ -1507,7 +1527,7 @@ To get the frame's current background color, use 
`frame-parameters'."
   "Set the foreground color of the selected frame to COLOR-NAME.
 When called interactively, prompt for the name of the color to use.
 To get the frame's current foreground color, use `frame-parameters'."
-  (interactive (list (read-color "Foreground color: ")))
+  (interactive (list (read-color "Foreground color: " nil nil nil t)))
   (modify-frame-parameters (selected-frame)
                           (list (cons 'foreground-color color-name)))
   (or window-system
@@ -2807,6 +2827,7 @@ See also `toggle-frame-maximized'."
 (define-key ctl-x-5-map "0" #'delete-frame)
 (define-key ctl-x-5-map "o" #'other-frame)
 (define-key ctl-x-5-map "5" #'other-frame-prefix)
+(define-key ctl-x-5-map "c" #'clone-frame)
 (define-key global-map [f11] #'toggle-frame-fullscreen)
 (define-key global-map [(meta f10)] #'toggle-frame-maximized)
 (define-key esc-map    [f10]        #'toggle-frame-maximized)
diff --git a/lisp/frameset.el b/lisp/frameset.el
index 6aa94f8..cdbac0a 100644
--- a/lisp/frameset.el
+++ b/lisp/frameset.el
@@ -882,7 +882,7 @@ For the description of FORCE-ONSCREEN, see 
`frameset-restore'.
 When forced onscreen, frames wider than the monitor's workarea are converted
 to fullwidth, and frames taller than the workarea are converted to fullheight.
 NOTE: This only works for non-iconified frames."
-  (pcase-let* ((`(,left ,top ,width ,height) (cl-cdadr 
(frame-monitor-attributes frame)))
+  (pcase-let* ((`(,left ,top ,width ,height) (cdadr (frame-monitor-attributes 
frame)))
               (right (+ left width -1))
               (bottom (+ top height -1))
               (fr-left (frameset-compute-pos (frame-parameter frame 'left) 
left right))
diff --git a/lisp/gnus/gnus-group.el b/lisp/gnus/gnus-group.el
index b1134397..c1b46d6 100644
--- a/lisp/gnus/gnus-group.el
+++ b/lisp/gnus/gnus-group.el
@@ -118,7 +118,9 @@ If nil, only list groups that have unread articles."
 
 (defcustom gnus-group-default-list-level gnus-level-subscribed
   "Default listing level.
-Ignored if `gnus-group-use-permanent-levels' is non-nil."
+When `gnus-group-use-permanent-levels' is non-nil, this level is
+used as the starting level until the user sets a different level,
+and is ignored afterwards."
   :group 'gnus-group-listing
   :type '(choice (integer :tag "Level")
                  (function :tag "Function returning level")))
@@ -1176,11 +1178,11 @@ The following commands are available:
 (defun gnus-group-default-level (&optional level number-or-nil)
   (cond
    (gnus-group-use-permanent-levels
-    (or (setq gnus-group-use-permanent-levels
-             (or level (if (numberp gnus-group-use-permanent-levels)
-                           gnus-group-use-permanent-levels
-                         (or (gnus-group-default-list-level)
-                             gnus-level-subscribed))))
+    (or level
+        (if (numberp gnus-group-use-permanent-levels)
+           gnus-group-use-permanent-levels
+         (or (gnus-group-default-list-level)
+             gnus-level-subscribed))
        (gnus-group-default-list-level) gnus-level-subscribed))
    (number-or-nil
     level)
@@ -1228,20 +1230,23 @@ The following commands are available:
   (let ((charset (gnus-group-name-charset nil string)))
     (gnus-group-name-decode string charset)))
 
-(defun gnus-group-list-groups (&optional level unread lowest)
+(defun gnus-group-list-groups (&optional level unread lowest update-level)
   "List newsgroups with level LEVEL or lower that have unread articles.
 Default is all subscribed groups.
 If argument UNREAD is non-nil, groups with no unread articles are also
 listed.
 
-Also see the `gnus-group-use-permanent-levels' variable."
+Also see the `gnus-group-use-permanent-levels' variable.  If this
+variable is non-nil, and UPDATE-LEVEL is non-nil (which is the
+case interactively), the level will be updated by this command."
   (interactive
    (list (if current-prefix-arg
             (prefix-numeric-value current-prefix-arg)
           (or
            (gnus-group-default-level nil t)
            (gnus-group-default-list-level)
-           gnus-level-subscribed)))
+           gnus-level-subscribed))
+         nil nil t)
    gnus-group-mode)
   (unless level
     (setq level (car gnus-group-list-mode)
@@ -1288,7 +1293,9 @@ Also see the `gnus-group-use-permanent-levels' variable."
              (goto-char (point-max))
              (forward-line -1)))))))
     ;; Adjust cursor point.
-    (gnus-group-position-point)))
+    (gnus-group-position-point)
+    (when (and update-level gnus-group-use-permanent-levels)
+      (setq gnus-group-use-permanent-levels level))))
 
 (defun gnus-group-list-level (level &optional all)
   "List groups on LEVEL.
@@ -4205,8 +4212,9 @@ otherwise all levels below ARG will be scanned too."
 
     (gnus-check-reasonable-setup)
     (gnus-run-hooks 'gnus-after-getting-new-news-hook)
-    (gnus-group-list-groups (and (numberp arg)
-                                (max (car gnus-group-list-mode) arg)))))
+    (gnus-group-list-groups (and (numberp arg) arg))
+    (when gnus-group-use-permanent-levels
+      (setq gnus-group-use-permanent-levels (gnus-group-default-level arg)))))
 
 (defun gnus-group-get-new-news-this-group (&optional n dont-scan)
   "Check for newly arrived news in the current group (and the N-1 next groups).
diff --git a/lisp/gnus/gnus-start.el b/lisp/gnus/gnus-start.el
index 02bbe19..4bbeb24 100644
--- a/lisp/gnus/gnus-start.el
+++ b/lisp/gnus/gnus-start.el
@@ -715,6 +715,9 @@ the first newsgroup."
        (kill-buffer (get-file-buffer gnus-current-startup-file)))
   ;; Clear the dribble buffer.
   (gnus-dribble-clear)
+  ;; Reset the level when Gnus is restarted.
+  (when (numberp gnus-group-use-permanent-levels)
+    (setq gnus-group-use-permanent-levels t))
   ;; Kill global KILL file buffer.
   (when (get-file-buffer (gnus-newsgroup-kill-file nil))
     (kill-buffer (get-file-buffer (gnus-newsgroup-kill-file nil))))
diff --git a/lisp/help-mode.el b/lisp/help-mode.el
index 2f82d83..08182b7 100644
--- a/lisp/help-mode.el
+++ b/lisp/help-mode.el
@@ -70,6 +70,35 @@
     ["Customize" help-customize
      :help "Customize variable or face"]))
 
+(defun help-mode-context-menu (menu)
+  (define-key menu [help-mode-separator] menu-bar-separator)
+  (let ((easy-menu (make-sparse-keymap "Help-Mode")))
+    (easy-menu-define nil easy-menu nil
+      '("Help-Mode"
+        ["Previous Topic" help-go-back
+         :help "Go back to previous topic in this help buffer"
+         :active help-xref-stack]
+        ["Next Topic" help-go-forward
+         :help "Go back to next topic in this help buffer"
+         :active help-xref-forward-stack]))
+    (dolist (item (reverse (lookup-key easy-menu [menu-bar help-mode])))
+      (when (consp item)
+        (define-key menu (vector (car item)) (cdr item)))))
+
+  (when (and
+         ;; First check if `help-fns--list-local-commands'
+         ;; used `where-is-internal' to call this function
+         ;; with wrong `last-input-event'.
+         (eq (current-buffer) (window-buffer (posn-window (event-start 
last-input-event))))
+         (mouse-posn-property (event-start last-input-event) 'mouse-face))
+    (define-key menu [help-mode-push-button]
+      '(menu-item "Follow Link" (lambda (event)
+                                  (interactive "e")
+                                  (push-button event))
+                  :help "Follow the link at click")))
+
+  menu)
+
 (defvar help-mode-tool-bar-map
   (let ((map (make-sparse-keymap)))
     (tool-bar-local-item "close" 'quit-window 'quit map
@@ -111,6 +140,15 @@ The format is (FUNCTION ARGS...).")
 (setq-default help-xref-stack nil help-xref-stack-item nil)
 (setq-default help-xref-forward-stack nil help-xref-forward-stack-item nil)
 
+(defvar help-mode-syntax-table
+  (let ((table (make-syntax-table emacs-lisp-mode-syntax-table)))
+    ;; Treat single quotes as parens so that forward-sexp does not
+    ;; break when a quoted string contains punctuation.
+    (modify-syntax-entry ?‘ "(’  " table)
+    (modify-syntax-entry ?’ ")‘  " table)
+    table)
+  "Syntax table used in `help-mode'.")
+
 (defcustom help-mode-hook nil
   "Hook run by `help-mode'."
   :type 'hook
@@ -190,6 +228,11 @@ The format is (FUNCTION ARGS...).")
   'help-function #'info
   'help-echo (purecopy "mouse-2, RET: read this Info node"))
 
+(define-button-type 'help-customization-group
+  :supertype 'help-xref
+  'help-function #'customize-group
+  'help-echo (purecopy "mouse-2, RET: display this customization group"))
+
 (define-button-type 'help-url
   :supertype 'help-xref
   'help-function #'browse-url
@@ -340,6 +383,7 @@ Commands:
 \\{help-mode-map}"
   (setq-local revert-buffer-function
               #'help-mode-revert-buffer)
+  (add-hook 'context-menu-functions 'help-mode-context-menu 5 t)
   (setq-local tool-bar-map
               help-mode-tool-bar-map)
   (setq-local help-mode--current-data nil)
@@ -398,6 +442,10 @@ when help commands related to multilingual environment 
(e.g.,
    "\\<[Ii]nfo[ \t\n]+\\(node\\|anchor\\)[ \t\n]+['`‘]\\([^'’]+\\)['’]")
   "Regexp matching doc string references to an Info node.")
 
+(defconst help-xref-customization-group-regexp
+  (purecopy "\\<[Cc]ustomization[ \t\n]+[Gg]roup[ \t\n]+['`‘]\\([^'’]+\\)['’]")
+  "Regexp matching doc string references to a customization group.")
+
 (defconst help-xref-url-regexp
   (purecopy "\\<[Uu][Rr][Ll][ \t\n]+['`‘]\\([^'’]+\\)['’]")
   "Regexp matching doc string references to a URL.")
@@ -490,7 +538,7 @@ that."
         (let ((stab (syntax-table))
               (case-fold-search t)
               (inhibit-read-only t))
-          (set-syntax-table emacs-lisp-mode-syntax-table)
+          (set-syntax-table help-mode-syntax-table)
           ;; The following should probably be abstracted out.
           (unwind-protect
               (progn
@@ -504,6 +552,12 @@ that."
                        (setq data ;; possible newlines if para filled
                              (replace-regexp-in-string "[ \t\n]+" " " data t 
t)))
                       (help-xref-button 2 'help-info data))))
+                ;; Customization groups.
+                (save-excursion
+                  (while (re-search-forward
+                          help-xref-customization-group-regexp nil t)
+                    (help-xref-button 1 'help-customization-group
+                                      (intern (match-string 1)))))
                 ;; URLs
                 (save-excursion
                   (while (re-search-forward help-xref-url-regexp nil t)
@@ -643,7 +697,7 @@ See `help-make-xrefs'."
 (defun help-xref-on-pp (from to)
   "Add xrefs for symbols in `pp's output between FROM and TO."
   (if (> (- to from) 5000) nil
-    (with-syntax-table emacs-lisp-mode-syntax-table
+    (with-syntax-table help-mode-syntax-table
       (save-excursion
        (save-restriction
          (narrow-to-region from to)
diff --git a/lisp/hi-lock.el b/lisp/hi-lock.el
index 37b88b3..4c924e9 100644
--- a/lisp/hi-lock.el
+++ b/lisp/hi-lock.el
@@ -344,9 +344,9 @@ which can be called interactively, are:
 When hi-lock is started and if the mode is not excluded or patterns
 rejected, the beginning of the buffer is searched for lines of the
 form:
-  Hi-lock: FOO
+  Hi-lock: (FOO ...)
 
-where FOO is a list of patterns.  The patterns must start before
+where (FOO ...) is a list of patterns.  The patterns must start before
 position \(number of characters into buffer)
 `hi-lock-file-patterns-range'.  Patterns will be read until
 Hi-lock: end is found.  A mode is excluded if it's in the list
@@ -818,7 +818,7 @@ SPACES-REGEXP is a regexp to substitute spaces in font-lock 
search."
                      (not (looking-at "\\s-*end")))
             (condition-case nil
                 (setq all-patterns (append (read (current-buffer)) 
all-patterns))
-              (error (message "Invalid pattern list expression at %d"
+              (error (message "Invalid pattern list expression at line %d"
                               (line-number-at-pos)))))))
       (when (and all-patterns
                  hi-lock-mode
diff --git a/lisp/htmlfontify.el b/lisp/htmlfontify.el
index 3b96198..e63910d 100644
--- a/lisp/htmlfontify.el
+++ b/lisp/htmlfontify.el
@@ -1238,7 +1238,7 @@ return a `defface' style list of face properties instead 
of a face symbol."
                             (setq fprops (cdr fprops)))
                         ;; ((prop val))
                         (setq p (caar fprops))
-                        (setq v (cl-cadar fprops))
+                        (setq v (cadar fprops))
                         (setq fprops (cdr fprops)))
                     (if (listp (cdr fprops))
                         (progn
@@ -1358,8 +1358,8 @@ Returns a modified copy of FACE-MAP."
     ;;(push (car  tmp-map) reduced-map)
     ;;(push (cadr tmp-map) reduced-map)
     (while tmp-map
-      (setq first-start (cl-cadddr tmp-map)
-            first-stop (cl-caddr tmp-map)
+      (setq first-start (cadddr tmp-map)
+            first-stop (caddr tmp-map)
             last-start  (cadr   tmp-map)
             last-stop   (car    tmp-map)
             map-buf      tmp-map
@@ -1372,8 +1372,8 @@ Returns a modified copy of FACE-MAP."
                     (not (re-search-forward "[^ \t\n\r]" (car last-start) t))))
         (setq map-buf     (cddr map-buf)
               span-start  first-start
-              first-start (cl-cadddr map-buf)
-              first-stop (cl-caddr map-buf)
+              first-start (cadddr map-buf)
+              first-stop (caddr map-buf)
               last-start  (cadr   map-buf)
               last-stop   (car    map-buf)))
       (push span-stop  reduced-map)
@@ -1888,7 +1888,7 @@ property, with a value of \"tag.line-number\"."
             (lambda (TLIST)
               (if (string= file (car TLIST))
                   (let* ((line              (cadr TLIST) )
-                         (chr (cl-caddr TLIST))
+                         (chr (caddr TLIST))
                          (link (format "%s.%d" TAG line) ))
                     (put-text-property (+ 1 chr)
                                        (+ 2 chr)
diff --git a/lisp/ibuf-ext.el b/lisp/ibuf-ext.el
index 1dc8acb..907ee8d 100644
--- a/lisp/ibuf-ext.el
+++ b/lisp/ibuf-ext.el
@@ -332,6 +332,17 @@ where NAME is a unique but arbitrary name and 
FILTER-GROUP-LIST
 is a list of filter groups with the same structure as
 allowed for `ibuffer-filter-groups'.
 
+For instance:
+
+  (setq ibuffer-saved-filter-groups
+        \\='((\"Home\"
+           (\"Modified\" (predicate buffer-modified-p (current-buffer)))
+           (\"Helm\" (name . \"\\\\*helm.+\"))
+           (\"Dev\" (or (filename . \".+\\\\.css\\\\'\")
+                      (filename . \".+\\\\.html?\\\\'\")
+                      (mode . android-mode)
+                      (mode . clojure-mode))))))
+
 See also the functions `ibuffer-save-filter-groups' and
 `ibuffer-switch-to-saved-filter-groups' for saving and switching
 between sets of filter groups, and the variable
diff --git a/lisp/icomplete.el b/lisp/icomplete.el
index e06b33e..0fa5f36 100644
--- a/lisp/icomplete.el
+++ b/lisp/icomplete.el
@@ -109,7 +109,11 @@ Otherwise this should be a list of the completion tables 
(e.g.,
 
 (defface icomplete-selected-match '((t :inherit highlight))
   "Face used by `icomplete-vertical-mode' for the selected candidate."
-  :version "24.4")
+  :version "28.1")
+
+(defface icomplete-section '((t :inherit shadow :slant italic))
+  "Face used by `icomplete-vertical-mode' for the section title."
+  :version "28.1")
 
 ;;;_* User Customization variables
 (defcustom icomplete-prospects-height 2
@@ -249,38 +253,53 @@ the default otherwise."
 (defun icomplete-forward-completions ()
   "Step forward completions by one entry.
 Second entry becomes the first and can be selected with
-`icomplete-force-complete-and-exit'."
+`icomplete-force-complete-and-exit'.
+Return non-nil iff something was stepped."
   (interactive)
   (let* ((beg (icomplete--field-beg))
          (end (icomplete--field-end))
-         (comps (completion-all-sorted-completions beg end))
-         (last (last comps)))
+         (comps (completion-all-sorted-completions beg end)))
     (when (consp (cdr comps))
       (cond (icomplete-scroll
              (push (pop comps) icomplete--scrolled-past)
              (setq icomplete--scrolled-completions comps))
             (t
-             (setcdr (last comps) (cons (pop comps) (cdr last)))))
+             (let ((last (last comps)))
+               (setcdr (last comps) (cons (pop comps) (cdr last))))))
       (completion--cache-all-sorted-completions beg end comps))))
 
 (defun icomplete-backward-completions ()
   "Step backward completions by one entry.
 Last entry becomes the first and can be selected with
-`icomplete-force-complete-and-exit'."
+`icomplete-force-complete-and-exit'.
+Return non-nil iff something was stepped."
   (interactive)
   (let* ((beg (icomplete--field-beg))
          (end (icomplete--field-end))
          (comps (completion-all-sorted-completions beg end))
-        last-but-one)
-    (cond ((and icomplete-scroll icomplete--scrolled-past)
-           (push (pop icomplete--scrolled-past) comps)
-           (setq icomplete--scrolled-completions comps))
-          ((and (not icomplete-scroll)
-                (consp (cdr (setq last-but-one (last comps 2)))))
-           ;; At least two elements in comps
-           (push (car (cdr last-but-one)) comps)
-           (setcdr last-but-one (cdr (cdr last-but-one)))))
-    (completion--cache-all-sorted-completions beg end comps)))
+         last-but-one)
+    (prog1
+        (cond ((and icomplete-scroll icomplete--scrolled-past)
+               (push (pop icomplete--scrolled-past) comps)
+               (setq icomplete--scrolled-completions comps))
+              ((and (not icomplete-scroll)
+                    (consp (cdr (setq last-but-one (last comps 2)))))
+               ;; At least two elements in comps
+               (push (car (cdr last-but-one)) comps)
+               (setcdr last-but-one (cdr (cdr last-but-one)))))
+      (completion--cache-all-sorted-completions beg end comps))))
+
+(defun icomplete-vertical-goto-first ()
+  "Go to first completions entry when `icomplete-scroll' is non-nil."
+  (interactive)
+  (unless icomplete-scroll (error "Only works with `icomplete-scroll'"))
+  (while (icomplete-backward-completions)))
+
+(defun icomplete-vertical-goto-last ()
+  "Go to last completions entry when `icomplete-scroll' is non-nil."
+  (interactive)
+  (unless icomplete-scroll (error "Only works with `icomplete-scroll'"))
+  (while (icomplete-forward-completions)))
 
 ;;;_* Helpers for `fido-mode' (or `ido-mode' emulation)
 
@@ -609,6 +628,10 @@ Usually run by inclusion in `minibuffer-setup-hook'."
   (let ((map (make-sparse-keymap)))
     (define-key map (kbd "C-n") 'icomplete-forward-completions)
     (define-key map (kbd "C-p") 'icomplete-backward-completions)
+    (define-key map (kbd "<down>") 'icomplete-forward-completions)
+    (define-key map (kbd "<up>") 'icomplete-backward-completions)
+    (define-key map (kbd "M-<") 'icomplete-vertical-goto-first)
+    (define-key map (kbd "M->") 'icomplete-vertical-goto-last)
     map)
   "Keymap used by `icomplete-vertical-mode' in the minibuffer.")
 
@@ -616,8 +639,7 @@ Usually run by inclusion in `minibuffer-setup-hook'."
   "Setup the minibuffer for vertical display of completion candidates."
   (use-local-map (make-composed-keymap icomplete-vertical-mode-minibuffer-map
                                        (current-local-map)))
-  (setq-local icomplete-separator "\n"
-              icomplete-hide-common-prefix nil
+  (setq-local icomplete-hide-common-prefix nil
               ;; Ask `icomplete-completions' to return enough completions 
candidates.
               icomplete-prospects-height 25
               redisplay-adhoc-scroll-in-resize-mini-windows nil))
@@ -726,14 +748,22 @@ See `icomplete-mode' and `minibuffer-setup-hook'."
                       (format icomplete-matches-format current total))))
               (overlay-put icomplete-overlay 'after-string text))))))))
 
-(defun icomplete--affixate (md prospects)
-  "Affixate PROSPECTS given completion metadata MD.
-Return a list of (COMP PREFIX SUFFIX)."
-  (let ((aff-fun (or (completion-metadata-get md 'affixation-function)
-                     (plist-get completion-extra-properties 
:affixation-function)))
-        (ann-fun (or (completion-metadata-get md 'annotation-function)
-                     (plist-get completion-extra-properties 
:annotation-function))))
-    (cond (aff-fun
+(defun icomplete--augment (md prospects)
+  "Augment completion strings in PROSPECTS with completion metadata MD.
+Return a list of strings (COMP PREFIX SUFFIX SECTION).  PREFIX
+and SUFFIX, if non-nil, are obtained from `affixation-function' or
+`annotation-function' metadata.  SECTION is obtained from
+`group-function'.  Consecutive `equal' sections are avoided.
+COMP is the element in PROSPECTS or a transformation also given
+by `group-function''s second \"transformation\" protocol."
+  (let* ((aff-fun (or (completion-metadata-get md 'affixation-function)
+                      (plist-get completion-extra-properties 
:affixation-function)))
+         (ann-fun (or (completion-metadata-get md 'annotation-function)
+                      (plist-get completion-extra-properties 
:annotation-function)))
+         (grp-fun (and completions-group
+                       (completion-metadata-get md 'group-function)))
+         (annotated
+          (cond (aff-fun
            (funcall aff-fun prospects))
           (ann-fun
            (mapcar
@@ -747,9 +777,24 @@ Return a list of (COMP PREFIX SUFFIX)."
                           suffix
                         (propertize suffix 'face 'completions-annotations)))))
             prospects))
-          (prospects))))
-
-(cl-defun icomplete--render-vertical (comps md &aux scroll-above scroll-below)
+          (t (mapcar #'list prospects)))))
+    (if grp-fun
+        (cl-loop with section = nil
+                 for (c prefix suffix) in annotated
+                 for selectedp = (get-text-property 0 'icomplete-selected c)
+                 for tr = (propertize (or (funcall grp-fun c t) c)
+                                      'icomplete-selected selectedp)
+                 if (not (equal section (setq section (funcall grp-fun c 
nil))))
+                 collect (list tr prefix suffix section)
+                 else collect (list tr prefix suffix ))
+      annotated)))
+
+(cl-defun icomplete--render-vertical
+    (comps md &aux scroll-above scroll-below
+           (total-space ; number of mini-window lines available
+            (1- (min
+                 icomplete-prospects-height
+                 (truncate (max-mini-window-lines) 1)))))
   ;; Welcome to loopapalooza!
   ;;
   ;; First, be mindful of `icomplete-scroll' and manual scrolls.  If
@@ -757,11 +802,11 @@ Return a list of (COMP PREFIX SUFFIX)."
   ;; are:
   ;;
   ;; - both nil, there is no manual scroll;
-  ;; - both non-nil, there is a healthy manual scroll the doesn't need
+  ;; - both non-nil, there is a healthy manual scroll that doesn't need
   ;;   to be readjusted (user just moved around the minibuffer, for
   ;;   example)l
   ;; - non-nil and nil, respectively, a refiltering took place and we
-  ;;   need attempt to readjust them to the new filtered `comps'.
+  ;;   may need to readjust them to the new filtered `comps'.
   (when (and icomplete-scroll
              icomplete--scrolled-completions
              (null icomplete--scrolled-past))
@@ -783,52 +828,67 @@ Return a list of (COMP PREFIX SUFFIX)."
   ;; positions.
   (cl-loop with preds = icomplete--scrolled-past
            with succs = (cdr comps)
-           with max-lines = (1- (min
-                                 icomplete-prospects-height
-                                 (truncate (max-mini-window-lines) 1)))
-           with max-above = (- max-lines
-                               1
-                               (cl-loop for (_ . r) on comps
-                                        repeat (truncate max-lines 2)
-                                        while (listp r)
-                                        count 1))
-           repeat max-lines
+           with space-above = (- total-space
+                                 1
+                                 (cl-loop for (_ . r) on comps
+                                          repeat (truncate total-space 2)
+                                          while (listp r)
+                                          count 1))
+           repeat total-space
            for neighbour = nil
-           if (and preds (> max-above 0)) do
+           if (and preds (> space-above 0)) do
            (push (setq neighbour (pop preds)) scroll-above)
-           (cl-decf max-above)
+           (cl-decf space-above)
            else if (consp succs) collect
            (setq neighbour (pop succs)) into scroll-below-aux
            while neighbour
            finally (setq scroll-below scroll-below-aux))
-  ;; Now figure out spacing and layout
-  ;;
-  (cl-loop
-   with selected = (substring (car comps))
-   initially (add-face-text-property 0 (length selected)
-                                     'icomplete-selected-match 'append 
selected)
-   with torender = (nconc scroll-above (list selected) scroll-below)
-   with triplets = (icomplete--affixate md torender)
-   initially (when (eq triplets torender)
-               (cl-return-from icomplete--render-vertical
-                 (concat
-                  " \n"
-                  (mapconcat #'identity torender icomplete-separator))))
-   for (comp prefix) in triplets
-   maximizing (length prefix) into max-prefix-len
-   maximizing (length comp) into max-comp-len
-   finally return
-   ;; Finally, render
-   ;;
-   (concat
-    " \n"
-    (cl-loop for (comp prefix suffix) in triplets
-             concat prefix
-             concat (make-string (- max-prefix-len (length prefix)) ? )
-             concat comp
-             concat (make-string (- max-comp-len (length comp)) ? )
-             concat suffix
-             concat icomplete-separator))))
+  ;; Halfway there...
+  (let* ((selected (propertize (car comps) 'icomplete-selected t))
+         (chosen (append scroll-above (list selected) scroll-below))
+         (tuples (icomplete--augment md chosen))
+         max-prefix-len max-comp-len lines nsections)
+    (add-face-text-property 0 (length selected)
+                            'icomplete-selected-match 'append selected)
+    ;; Figure out parameters for horizontal spacing
+    (cl-loop
+     for (comp prefix) in tuples
+     maximizing (length prefix) into max-prefix-len-aux
+     maximizing (length comp) into max-comp-len-aux
+     finally (setq max-prefix-len max-prefix-len-aux
+                   max-comp-len max-comp-len-aux))
+    ;; Serialize completions and section titles into a list
+    ;; of lines to render
+    (cl-loop
+     for (comp prefix suffix section) in tuples
+     when section
+     collect (propertize section 'face 'icomplete-section) into lines-aux
+     and count 1 into nsections-aux
+     when (get-text-property 0 'icomplete-selected comp)
+     do (add-face-text-property 0 (length comp)
+                                'icomplete-selected-match 'append comp)
+     collect (concat prefix
+                     (make-string (- max-prefix-len (length prefix)) ? )
+                     comp
+                     (make-string (- max-comp-len (length comp)) ? )
+                     suffix)
+     into lines-aux
+     finally (setq lines lines-aux
+                   nsections nsections-aux))
+    ;; Kick out some lines from the beginning due to extra sections.
+    ;; This hopes to keep the selected entry more or less in the
+    ;; middle of the dropdown-like widget when `icomplete-scroll' is
+    ;; t.  Funky, but at least I didn't use `cl-loop'
+    (setq lines
+          (nthcdr
+           (cond ((<= (length lines) total-space) 0)
+                 ((> (length scroll-above) (length scroll-below)) nsections)
+                 (t (min (ceiling nsections 2) (length scroll-above))))
+           lines))
+    ;; At long last, render final string return value.  This may still
+    ;; kick out lines at the end.
+    (concat " \n"
+            (cl-loop for l in lines repeat total-space concat l concat "\n"))))
 
 ;;;_ > icomplete-completions (name candidates predicate require-match)
 (defun icomplete-completions (name candidates predicate require-match)
diff --git a/lisp/ielm.el b/lisp/ielm.el
index fd8dac7..39820a8 100644
--- a/lisp/ielm.el
+++ b/lisp/ielm.el
@@ -440,8 +440,7 @@ nonempty, then flushes the buffer."
                                  (concat (buffer-string) aux))))))
           (error
            (setq error-type "IELM Error")
-           (setq result (format "Error during pretty-printing (bug in pp): %S"
-                                err)))
+           (setq result (format "Error during pretty-printing: %S" err)))
           (quit  (setq error-type "IELM Error")
                  (setq result "Quit during pretty-printing"))))
       (if error-type
diff --git a/lisp/image-dired.el b/lisp/image-dired.el
index 7092f75..b92a937 100644
--- a/lisp/image-dired.el
+++ b/lisp/image-dired.el
@@ -652,6 +652,8 @@ Each item has the form (ORIGINAL-FILE TARGET-FILE).")
   "Maximum number of concurrent jobs permitted for generating images.
 Increase at own risk.")
 
+(defvar image-dired-tag-history nil "Variable holding the tag history.")
+
 (defun image-dired-pngnq-thumb (spec)
   "Quantize thumbnail described by format SPEC with pngnq(1)."
   (let ((process
@@ -797,6 +799,22 @@ Queued items live in `image-dired-queue'."
                (list (list original-file thumbnail-file))))
   (run-at-time 0 nil #'image-dired-thumb-queue-run))
 
+(defmacro image-dired--with-marked (&rest body)
+  "Eval BODY with point on each marked thumbnail.
+If no marked file could be found, execute BODY on the current
+thumbnail."
+  `(with-current-buffer image-dired-thumbnail-buffer
+     (let (found)
+       (save-mark-and-excursion
+         (goto-char (point-min))
+         (while (not (eobp))
+           (when (image-dired-thumb-file-marked-p)
+             (setq found t)
+             ,@body)
+           (forward-char)))
+       (unless found
+         ,@body))))
+
 ;;;###autoload
 (defun image-dired-dired-toggle-marked-thumbs (&optional arg)
   "Toggle thumbnails in front of file names in the dired buffer.
@@ -1080,7 +1098,7 @@ FILE-TAGS is an alist in the following form:
               (end-of-line)
               (insert (format ";%s" tag))))
         (goto-char (point-max))
-        (insert (format "\n%s;%s" file tag))))
+        (insert (format "%s;%s\n" file tag))))
      (save-buffer))))
 
 (defun image-dired-remove-tag (files tag)
@@ -1095,11 +1113,12 @@ FILE-TAGS is an alist in the following form:
         (error "Files must be a string or a list of strings!")))
      (dolist (file files)
        (goto-char (point-min))
-       (when (search-forward-regexp (format "^%s" file) nil t)
+       (when (search-forward-regexp (format "^%s;" file) nil t)
         (end-of-line)
         (setq end (point))
         (beginning-of-line)
-        (when (search-forward-regexp (format "\\(;%s\\)" tag) end t)
+        (when (search-forward-regexp
+                (format "\\(;%s\\)\\($\\|;\\)" tag) end t)
           (delete-region (match-beginning 1) (match-end 1))
           ;; Check if file should still be in the database. If
           ;; it has no tags or comments, it will be removed.
@@ -1107,11 +1126,7 @@ FILE-TAGS is an alist in the following form:
           (setq end (point))
           (beginning-of-line)
           (when (not (search-forward ";" end t))
-            (kill-line 1)
-            ;; If on empty line at end of buffer
-            (and (eobp)
-                 (looking-at "^$")
-                 (delete-char -1)))))))
+            (kill-line 1))))))
    (save-buffer)))
 
 (defun image-dired-list-tags (file)
@@ -1134,7 +1149,9 @@ FILE-TAGS is an alist in the following form:
 (defun image-dired-tag-files (arg)
   "Tag marked file(s) in dired.  With prefix ARG, tag file at point."
   (interactive "P")
-  (let ((tag (read-string "Tags to add (separate tags with a semicolon): "))
+  (let ((tag (completing-read
+              "Tags to add (separate tags with a semicolon): "
+              image-dired-tag-history nil nil nil 'image-dired-tag-history))
         files)
     (if arg
         (setq files (list (dired-get-filename)))
@@ -1145,27 +1162,25 @@ FILE-TAGS is an alist in the following form:
         (cons x tag))
       files))))
 
-(defun image-dired-tag-marked-thumbnails ()
-  "Tag marked thumbnails."
-  (interactive)
-  (when-let ((dired-buf (image-dired-associated-dired-buffer)))
-    (with-current-buffer dired-buf
-      (image-dired-tag-files nil))))
-
 (defun image-dired-tag-thumbnail ()
-  "Tag current thumbnail."
+  "Tag current or marked thumbnails."
   (interactive)
-  (let ((tag (read-string "Tags to add (separate tags with a semicolon): ")))
-    (image-dired-write-tags (list (cons (image-dired-original-file-name) 
tag))))
-  (image-dired-update-property
-   'tags (image-dired-list-tags (image-dired-original-file-name))))
+  (let ((tag (completing-read
+              "Tags to add (separate tags with a semicolon): "
+              image-dired-tag-history nil nil nil 'image-dired-tag-history)))
+    (image-dired--with-marked
+     (image-dired-write-tags
+      (list (cons (image-dired-original-file-name) tag)))
+     (image-dired-update-property
+      'tags (image-dired-list-tags (image-dired-original-file-name))))))
 
 ;;;###autoload
 (defun image-dired-delete-tag (arg)
   "Remove tag for selected file(s).
 With prefix argument ARG, remove tag from file at point."
   (interactive "P")
-  (let ((tag (read-string "Tag to remove: "))
+  (let ((tag (completing-read "Tag to remove: " image-dired-tag-history
+                              nil nil nil 'image-dired-tag-history))
         files)
     (if arg
         (setq files (list (dired-get-filename)))
@@ -1173,12 +1188,14 @@ With prefix argument ARG, remove tag from file at 
point."
     (image-dired-remove-tag files tag)))
 
 (defun image-dired-tag-thumbnail-remove ()
-  "Remove tag from thumbnail."
+  "Remove tag from current or marked thumbnails."
   (interactive)
-  (let ((tag (read-string "Tag to remove: ")))
-    (image-dired-remove-tag (image-dired-original-file-name) tag))
-  (image-dired-update-property
-   'tags (image-dired-list-tags (image-dired-original-file-name))))
+  (let ((tag (completing-read "Tag to remove: " image-dired-tag-history
+                              nil nil nil 'image-dired-tag-history)))
+    (image-dired--with-marked
+     (image-dired-remove-tag (image-dired-original-file-name) tag)
+     (image-dired-update-property
+      'tags (image-dired-list-tags (image-dired-original-file-name))))))
 
 (defun image-dired-original-file-name ()
   "Get original file name for thumbnail or display image at point."
@@ -1370,7 +1387,7 @@ comment."
   "Check whether file on current line is marked or not."
   (save-excursion
     (beginning-of-line)
-    (not (looking-at "^ .*$"))))
+    (looking-at-p dired-re-mark)))
 
 (defun image-dired-modify-mark-on-thumb-original-file (command)
   "Modify mark in dired buffer.
@@ -1518,8 +1535,10 @@ You probably want to use this together with
       '("Image-Dired"
         ["Quit" quit-window]
         ["Delete thumbnail from buffer" image-dired-delete-char]
-        ["Remove tag from thumbnail" image-dired-tag-thumbnail-remove]
-        ["Tag thumbnail" image-dired-tag-thumbnail]
+        ["Delete marked images" image-dired-delete-marked]
+        ["Remove tag from current or marked thumbnails"
+         image-dired-tag-thumbnail-remove]
+        ["Tag current or marked thumbnails" image-dired-tag-thumbnail]
         ["Comment thumbnail" image-dired-comment-thumbnail]
         ["Refresh thumb" image-dired-refresh-thumb]
         ["Dynamic line up" image-dired-line-up-dynamic]
@@ -2171,7 +2190,7 @@ FILE-COMMENTS is an alist on the following form:
             (insert (format "comment:%s;" comment)))
         ;; File does not exist in database - add it.
         (goto-char (point-max))
-        (insert (format "\n%s;comment:%s" file comment))))
+        (insert (format "%s;comment:%s\n" file comment))))
      (save-buffer))))
 
 (defun image-dired-update-property (prop value)
@@ -2299,17 +2318,14 @@ non-nil."
           (image-dired-dired-file-marked-p))))))
 
 (defun image-dired-delete-marked ()
-  "Delete marked thumbnails and associated images."
+  "Delete current or marked thumbnails and associated images."
   (interactive)
-  (goto-char (point-min))
-  (let ((dired-buf (image-dired-associated-dired-buffer)))
-    (while (not (eobp))
-      (if (image-dired-thumb-file-marked-p)
-          (image-dired-delete-char)
-        (forward-char)))
-    (image-dired--line-up-with-method)
-    (with-current-buffer dired-buf
-      (dired-do-delete))))
+  (with-current-buffer (image-dired-associated-dired-buffer)
+    (dired-do-delete))
+  (image-dired--with-marked
+   (image-dired-delete-char)
+   (backward-char))
+  (image-dired--line-up-with-method))
 
 (defun image-dired-thumb-update-marks ()
   "Update the marks in the thumbnail buffer."
diff --git a/lisp/indent.el b/lisp/indent.el
index a33d962..aa2bfbc 100644
--- a/lisp/indent.el
+++ b/lisp/indent.el
@@ -81,7 +81,7 @@ This variable has no effect unless `tab-always-indent' is 
`complete'."
           (const :tag "Unless looking at a word" 'word)
           (const :tag "Unless at a word or parenthesis" 'word-or-paren)
           (const :tag "Unless at a word, parenthesis, or punctuation." 
'word-or-paren-or-punct))
-  :version "27.1")
+  :version "28.1")
 
 (defvar indent-line-ignored-functions '(indent-relative
                                         indent-relative-maybe
diff --git a/lisp/info.el b/lisp/info.el
index 3718a1e..5589321 100644
--- a/lisp/info.el
+++ b/lisp/info.el
@@ -1731,22 +1731,24 @@ escaped (\\\",\\\\)."
               (list
                (concat
                 " ("
-                (if (stringp Info-current-file)
-                    (string-replace
-                     "%" "%%"
-                     (file-name-sans-extension
-                      (file-name-nondirectory Info-current-file)))
-                  (format "*%S*" Info-current-file))
-                ") "
-                (if Info-current-node
-                    (propertize (string-replace
-                                 "%" "%%" Info-current-node)
-                                'face 'mode-line-buffer-id
-                                'help-echo
-                                "mouse-1: scroll forward, mouse-3: scroll back"
-                                'mouse-face 'mode-line-highlight
-                                'local-map Info-mode-line-node-keymap)
-                  ""))))))
+                 (propertize
+                 (if (stringp Info-current-file)
+                      (string-replace
+                      "%" "%%"
+                      (file-name-sans-extension
+                       (file-name-nondirectory Info-current-file)))
+                   (format "*%S*" Info-current-file))
+                  'help-echo "Info file name")
+                ") ")
+               (if Info-current-node
+                   (propertize (string-replace
+                                "%" "%%" Info-current-node)
+                               'face 'mode-line-buffer-id
+                               'help-echo
+                               "mouse-1: scroll forward, mouse-3: scroll back"
+                               'mouse-face 'mode-line-highlight
+                               'local-map Info-mode-line-node-keymap)
+                 "")))))
 
 ;; Go to an Info node specified with a filename-and-nodename string
 ;; of the sort that is found in pointers in nodes.
@@ -4117,9 +4119,9 @@ If FORK is non-nil, it is passed to `Info-goto-node'."
     :help "Search for another occurrence of regular expression"]
    "---"
    ("History"
-    ["Back in history" Info-history-back :active Info-history
+    ["Back in History" Info-history-back :active Info-history
      :help "Go back in history to the last node you were at"]
-    ["Forward in history" Info-history-forward :active Info-history-forward
+    ["Forward in History" Info-history-forward :active Info-history-forward
      :help "Go forward in history"]
     ["Show History" Info-history :active Info-history-list
      :help "Go to menu of visited nodes"])
@@ -4146,6 +4148,25 @@ If FORK is non-nil, it is passed to `Info-goto-node'."
    "---"
    ["Exit" quit-window :help "Stop reading Info"]))
 
+(defun Info-context-menu (menu)
+  (define-key menu [Info-separator] menu-bar-separator)
+  (let ((easy-menu (make-sparse-keymap "Info")))
+    (easy-menu-define nil easy-menu nil
+      '("Info"
+        ["Back in History" Info-history-back :visible Info-history
+         :help "Go back in history to the last node you were at"]
+        ["Forward in History" Info-history-forward :visible 
Info-history-forward
+         :help "Go forward in history"]))
+    (dolist (item (reverse (lookup-key easy-menu [menu-bar info])))
+      (when (consp item)
+        (define-key menu (vector (car item)) (cdr item)))))
+
+  (when (mouse-posn-property (event-start last-input-event) 'mouse-face)
+    (define-key menu [Info-mouse-follow-nearest-node]
+      '(menu-item "Follow Link" Info-mouse-follow-nearest-node
+                  :help "Follow a link where you click")))
+
+  menu)
 
 (defvar info-tool-bar-map
   (let ((map (make-sparse-keymap)))
@@ -4446,6 +4467,7 @@ Advanced commands:
   (add-hook 'clone-buffer-hook 'Info-clone-buffer nil t)
   (add-hook 'change-major-mode-hook 'font-lock-defontify nil t)
   (add-hook 'isearch-mode-hook 'Info-isearch-start nil t)
+  (add-hook 'context-menu-functions 'Info-context-menu 5 t)
   (when Info-standalone
     (add-hook 'quit-window-hook 'save-buffers-kill-emacs nil t))
   (setq-local isearch-search-fun-function #'Info-isearch-search)
diff --git a/lisp/international/mule-cmds.el b/lisp/international/mule-cmds.el
index 71e2653..abccc4f 100644
--- a/lisp/international/mule-cmds.el
+++ b/lisp/international/mule-cmds.el
@@ -662,6 +662,26 @@ overrides that argument.")
                   (delq 'no-conversion (copy-sequence codings))))
       codings))
 
+(defun select-safe-coding-system--format-list (list)
+  (let ((spec1 "  %-20s %6s  %-10s %s\n")
+        (spec2 "  %-20s %6s  #x%-8X %c\n")
+        (nmax 5))
+    (insert (format spec1 "Coding System" "Pos" "Codepoint" "Char"))
+    (cl-loop for (coding . pairs) in list
+             do (cl-loop for pair in pairs
+                         ;; If there's a lot, only do the first five.
+                         for i from 1 upto nmax
+                         do (insert
+                             (format spec2
+                                     (if (= i 1) coding "")
+                                     (car pair)
+                                     (cdr pair)
+                                     (cdr pair))))
+             (if (> (length pairs) nmax)
+                 (insert (format spec1 "" "..." "" "")))))
+
+  (insert "\n"))
+
 (defun select-safe-coding-system-interactively (from to codings unsafe
                                                &optional rejected default)
   "Select interactively a coding system for the region FROM ... TO.
@@ -720,21 +740,18 @@ DEFAULT is the coding system to use by default in the 
query."
                 (concat " \"" (if (> (length from) 10)
                                   (concat (substring from 0 10) "...\"")
                                 (concat from "\"")))
-              (format-message " text\nin the buffer `%s'" bufname))
+              (format-message
+                " the following\nproblematic characters in the buffer `%s'"
+                bufname))
             ":\n")
-           (let ((pos (point))
-                 (fill-prefix "  "))
-             (dolist (x (append rejected unsafe))
-               (princ "  ") (princ x))
-             (insert "\n")
-             (fill-region-as-paragraph pos (point)))
+            (select-safe-coding-system--format-list unsafe)
            (when rejected
              (insert "These safely encode the text in the buffer,
 but are not recommended for encoding text in this context,
 e.g., for sending an email message.\n ")
-             (dolist (x rejected)
-               (princ " ") (princ x))
-             (insert "\n"))
+              (dolist (x rejected)
+                (princ " ") (princ x))
+              (insert "\n"))
            (when unsafe
              (insert (if rejected "The other coding systems"
                        "However, each of them")
@@ -2610,6 +2627,31 @@ is returned.  Thus, for instance, if charset 
\"ISO8859-2\",
 (declare-function w32-get-console-codepage "w32proc.c" ())
 (declare-function w32-get-console-output-codepage "w32proc.c" ())
 
+(defun get-locale-names ()
+  "Return a list of locale names."
+  (cond
+   ;; On Windows we have a built-in method to get the names.
+   ((and (fboundp 'w32-get-locale-info)
+         (fboundp 'w32-get-valid-locale-ids))
+    (delete-dups (mapcar #'w32-get-locale-info (w32-get-valid-locale-ids))))
+   ;; Unix-ey hosts should have a command to output locales currently
+   ;; defined by the OS.
+   ((executable-find "locale")
+    (split-string (shell-command-to-string "locale -a")))
+   ;; Fall back on the list of all defined locales.
+   ((and locale-translation-file-name
+         (file-exists-p locale-translation-file-name))
+    (with-temp-buffer
+      (insert-file-contents locale-translation-file-name)
+      (let ((locales nil))
+        (while (not (eobp))
+          (unless (looking-at-p "#")
+            (push (cadr (split-string (buffer-substring
+                                       (point) (line-end-position))))
+                  locales))
+          (forward-line 1))
+        (nreverse locales))))))
+
 (defun locale-translate (locale)
   "Expand LOCALE according to `locale-translation-file-name', if possible.
 For example, translate \"swedish\" into \"sv_SE.ISO8859-1\"."
@@ -2650,8 +2692,8 @@ touch session-global parameters like the language 
environment.
 
 See also `locale-charset-language-names', `locale-language-names',
 `locale-preferred-coding-systems' and `locale-coding-system'."
-  (interactive "sSet environment for locale: ")
-
+  (interactive (list (completing-read "Set environment for locale: "
+                                      (get-locale-names))))
   ;; Do this at runtime for the sake of binaries possibly transported
   ;; to a system without X.
   (setq locale-translation-file-name
diff --git a/lisp/international/mule-diag.el b/lisp/international/mule-diag.el
index 02169ce..864cd3c 100644
--- a/lisp/international/mule-diag.el
+++ b/lisp/international/mule-diag.el
@@ -862,15 +862,28 @@ The IGNORED argument is ignored."
 
 (defvar mule--print-opened)
 
+(defun mule--kbd-at (point)
+  (save-excursion
+    (goto-char point)
+    (elt
+     (kbd (buffer-substring
+           (point)
+           (progn
+             ;; Might be a space, in which case we want it.
+             (if (zerop (skip-chars-forward "^ "))
+                 (1+ (point))
+               (point)))))
+     0)))
+
 (defun print-fontset-element (val)
   ;; VAL has this format:
   ;;  ((REQUESTED-FONT-NAME OPENED-FONT-NAME ...) ...)
   ;; CHAR RANGE is already inserted.  Get character codes from
   ;; the current line.
   (beginning-of-line)
-  (let ((from (following-char))
+  (let ((from (mule--kbd-at (point)))
        (to (if (looking-at "[^.]*[.]* ")
-               (char-after (match-end 0)))))
+               (mule--kbd-at (match-end 0)))))
     (if (re-search-forward "[ \t]*$" nil t)
        (delete-region (match-beginning 0) (match-end 0)))
 
diff --git a/lisp/international/mule.el b/lisp/international/mule.el
index 9cd38af..1a53237 100644
--- a/lisp/international/mule.el
+++ b/lisp/international/mule.el
@@ -1380,8 +1380,11 @@ If CODING-SYSTEM is nil or the coding-type of 
CODING-SYSTEM is
 `raw-text', the decoding of keyboard input is disabled.
 
 TERMINAL may be a terminal object, a frame, or nil for the
-selected frame's terminal.  The setting has no effect on
-graphical terminals."
+selected frame's terminal.
+
+The setting has no effect on graphical terminals.  It also
+has no effect on MS-Windows text-mode terminals, except on
+Windows 9X systems.  For Windows 9X, see also `w32-set-console-codepage'."
   (interactive
    (list (let* ((coding (keyboard-coding-system nil))
                (default (if (eq (coding-system-type coding) 'raw-text)
diff --git a/lisp/isearch.el b/lisp/isearch.el
index 922ab0f..1c776a0 100644
--- a/lisp/isearch.el
+++ b/lisp/isearch.el
@@ -869,7 +869,8 @@ When you enter a space or spaces in ordinary incremental 
search, it
 will match any sequence matched by the regexp defined by the variable
 `search-whitespace-regexp'.  If the value is nil, each space you type
 matches literally, against one space.  You can toggle the value of this
-variable by the command `isearch-toggle-lax-whitespace'.")
+variable by the command `isearch-toggle-lax-whitespace', usually bound to
+`M-s SPC' during isearch.")
 
 (defvar isearch-regexp-lax-whitespace nil
   "If non-nil, a space will match a sequence of whitespace chars.
@@ -877,7 +878,8 @@ When you enter a space or spaces in regexp incremental 
search, it
 will match any sequence matched by the regexp defined by the variable
 `search-whitespace-regexp'.  If the value is nil, each space you type
 matches literally, against one space.  You can toggle the value of this
-variable by the command `isearch-toggle-lax-whitespace'.")
+variable by the command `isearch-toggle-lax-whitespace', usually bound to
+`M-s SPC' during isearch.")
 
 (defvar isearch-cmds nil
   "Stack of search status elements.
diff --git a/lisp/jit-lock.el b/lisp/jit-lock.el
index a128792..a905936 100644
--- a/lisp/jit-lock.el
+++ b/lisp/jit-lock.el
@@ -150,7 +150,10 @@ If 0, then fontification is only deferred while there is 
input pending."
 (defvar jit-lock-functions nil
   "Special hook run to do the actual fontification.
 The functions are called with two arguments:
-the START and END of the region to fontify.")
+the START and END of the region to fontify.
+Each function can return a list of the form (jit-lock-bounds BEG . END),
+to indicate the bounds of the region it actually fontified;
+JIT font-lock will use this information to optimize redisplay cycles.")
 
 (defvar-local jit-lock-context-unfontify-pos nil
   "Consider text after this position as contextually unfontified.
@@ -332,7 +335,10 @@ like `debug-on-error' and Edebug can be used."
   "Register FUN as a fontification function to be called in this buffer.
 FUN will be called with two arguments START and END indicating the region
 that needs to be (re)fontified.
-If non-nil, CONTEXTUAL means that a contextual fontification would be useful."
+If non-nil, CONTEXTUAL means that a contextual fontification would be useful.
+FUN can return a list of the form (jit-lock-bounds BEG . END),
+to indicate the bounds of the region it actually fontified; JIT
+font-lock will use this information to optimize redisplay cycles."
   (add-hook 'jit-lock-functions fun nil t)
   (when (and contextual jit-lock-contextually)
     (setq-local jit-lock-contextually t))
diff --git a/lisp/language/japan-util.el b/lisp/language/japan-util.el
index f3e3590..feb75a1 100644
--- a/lisp/language/japan-util.el
+++ b/lisp/language/japan-util.el
@@ -145,7 +145,7 @@ and HANKAKU belongs to `japanese-jisx0201-kana'.")
     (?p . ?p) (?q . ?q) (?r . ?r) (?s . ?s) (?t . ?t)
     (?u . ?u) (?v . ?v) (?w . ?w) (?x . ?x) (?y . ?y) (?z . ?z))
   "Japanese JISX0208 alpha numeric character table.
-Each element is of the form (ALPHA-NUMERIC . ASCII), where ALPHA-NUMERIC
+Each element is of the form (ALPHANUMERIC . ASCII), where ALPHANUMERIC
 belongs to `japanese-jisx0208', ASCII belongs to `ascii'.")
 
 ;; Put properties 'jisx0208 and 'ascii to each Japanese alpha numeric
diff --git a/lisp/ldefs-boot.el b/lisp/ldefs-boot.el
index e6ac5d5..542cbef 100644
--- a/lisp/ldefs-boot.el
+++ b/lisp/ldefs-boot.el
@@ -2938,6 +2938,13 @@ from `browse-url-elinks-wrapper'.
 
 \(fn URL &optional NEW-WINDOW)" t nil)
 
+(autoload 'browse-url-button-open "browse-url" "\
+Follow the link under point using `browse-url'.
+If EXTERNAL (the prefix if used interactively), open with the
+external browser instead of the default one.
+
+\(fn &optional EXTERNAL MOUSE-EVENT)" t nil)
+
 (autoload 'browse-url-button-open-url "browse-url" "\
 Open URL using `browse-url'.
 If `current-prefix-arg' is non-nil, use
@@ -3394,6 +3401,16 @@ Parse a rectangle as a matrix of numbers and push it on 
the Calculator stack.
 
 \(fn TOP BOT ARG)" t nil)
 
+(autoload 'calc-grab-sum-down "calc" "\
+Parse a rectangle as a matrix of numbers and sum its columns.
+
+\(fn TOP BOT ARG)" t nil)
+
+(autoload 'calc-grab-sum-across "calc" "\
+Parse a rectangle as a matrix of numbers and sum its rows.
+
+\(fn TOP BOT ARG)" t nil)
+
 (autoload 'calc-embedded "calc" "\
 Start Calc Embedded mode on the formula surrounding point.
 
@@ -6852,8 +6869,11 @@ or call the function `global-cwarn-mode'.")
 (autoload 'global-cwarn-mode "cwarn" "\
 Toggle Cwarn mode in all buffers.
 With prefix ARG, enable Global Cwarn mode if ARG is positive;
-otherwise, disable it.  If called from Lisp, enable the mode if ARG is
-omitted or nil.
+otherwise, disable it.
+
+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.
 
 Cwarn mode is enabled in all buffers where
 `turn-on-cwarn-mode-if-enabled' would do it.
@@ -8121,11 +8141,17 @@ Keybindings:
 
 (autoload 'dired-jump "dired" "\
 Jump to Dired buffer corresponding to current buffer.
-If in a file, Dired the current directory and move to file's line.
+If in a buffer visiting a file, Dired that file's directory and
+move to that file's line in the directory listing.
+
+If the current buffer isn't visiting a file, Dired `default-directory'.
+
 If in Dired already, pop up a level and goto old directory's line.
 In case the proper Dired file line cannot be found, refresh the dired
 buffer and try again.
+
 When OTHER-WINDOW is non-nil, jump to Dired buffer in other window.
+
 When FILE-NAME is non-nil, jump to its line in Dired.
 Interactively with prefix argument, read FILE-NAME.
 
@@ -8365,8 +8391,11 @@ or call the function 
`global-display-fill-column-indicator-mode'.")
 (autoload 'global-display-fill-column-indicator-mode 
"display-fill-column-indicator" "\
 Toggle Display-Fill-Column-Indicator mode in all buffers.
 With prefix ARG, enable Global Display-Fill-Column-Indicator mode if
-ARG is positive; otherwise, disable it.  If called from Lisp, enable
-the mode if ARG is omitted or nil.
+ARG is positive; otherwise, disable it.
+
+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.
 
 Display-Fill-Column-Indicator mode is enabled in all buffers where
 `display-fill-column-indicator--turn-on' would do it.
@@ -8442,8 +8471,11 @@ or call the function 
`global-display-line-numbers-mode'.")
 (autoload 'global-display-line-numbers-mode "display-line-numbers" "\
 Toggle Display-Line-Numbers mode in all buffers.
 With prefix ARG, enable Global Display-Line-Numbers mode if ARG is
-positive; otherwise, disable it.  If called from Lisp, enable the mode
-if ARG is omitted or nil.
+positive; otherwise, disable it.
+
+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.
 
 Display-Line-Numbers mode is enabled in all buffers where
 `display-line-numbers--turn-on' would do it.
@@ -8733,9 +8765,9 @@ BODY contains code to execute each time the mode is 
enabled or disabled.
                named variable, or a generalized variable.
                PLACE can also be of the form (GET . SET), where GET is
                an expression that returns the current state, and SET is
-               a function that takes one argument, the new state, and
-               sets it.  If you specify a :variable, this function does
-               not define a MODE variable (nor any of the terms used
+               a function that takes one argument, the new state, which should
+                be assigned to PLACE.  If you specify a :variable, this 
function
+                does not define a MODE variable (nor any of the terms used
                in :variable).
 :after-hook     A single lisp form which is evaluated after the mode hooks
                 have been run.  It should not be quoted.
@@ -15274,8 +15306,11 @@ or call the function `global-goto-address-mode'.")
 (autoload 'global-goto-address-mode "goto-addr" "\
 Toggle Goto-Address mode in all buffers.
 With prefix ARG, enable Global Goto-Address mode if ARG is positive;
-otherwise, disable it.  If called from Lisp, enable the mode if ARG
-is omitted or nil.
+otherwise, disable it.
+
+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.
 
 Goto-Address mode is enabled in all buffers where
 `goto-addr-mode--turn-on' would do it.
@@ -15570,9 +15605,14 @@ directories if your program contains sources from more 
than one directory.
 \(fn COMMAND-LINE)" t nil)
 
 (autoload 'perldb "gud" "\
-Run perldb on program FILE in buffer *gud-FILE*.
-The directory containing FILE becomes the initial working directory
-and source-file directory for your debugger.
+Debug a perl program with gud.
+Interactively, this will prompt you for a command line.
+
+Noninteractively, COMMAND-LINE should be on the form
+\"perl -d perl-file.pl\".
+
+The directory containing the perl program becomes the initial
+working directory and source-file directory for your debugger.
 
 \(fn COMMAND-LINE)" t nil)
 
@@ -16462,8 +16502,11 @@ or call the function `global-hi-lock-mode'.")
 (autoload 'global-hi-lock-mode "hi-lock" "\
 Toggle Hi-Lock mode in all buffers.
 With prefix ARG, enable Global Hi-Lock mode if ARG is positive;
-otherwise, disable it.  If called from Lisp, enable the mode if ARG is
-omitted or nil.
+otherwise, disable it.
+
+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.
 
 Hi-Lock mode is enabled in all buffers where
 `turn-on-hi-lock-if-enabled' would do it.
@@ -16860,8 +16903,11 @@ or call the function `global-highlight-changes-mode'.")
 (autoload 'global-highlight-changes-mode "hilit-chg" "\
 Toggle Highlight-Changes mode in all buffers.
 With prefix ARG, enable Global Highlight-Changes mode if ARG is
-positive; otherwise, disable it.  If called from Lisp, enable the mode if
-ARG is omitted or nil.
+positive; otherwise, disable it.
+
+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.
 
 Highlight-Changes mode is enabled in all buffers where
 `highlight-changes-mode-turn-on' would do it.
@@ -17462,17 +17508,50 @@ evaluate `(default-value 'icomplete-vertical-mode)'.
 The mode's hook is called both when the mode is enabled and when it is
 disabled.
 
+If none of these modes are on, turn on `icomplete-mode'.
+
 As many completion candidates as possible are displayed, depending on
 the value of `max-mini-window-height', and the way the mini-window is
 resized depends on `resize-mini-windows'.
 
 \(fn &optional ARG)" t nil)
+
+(defvar fido-vertical-mode nil "\
+Non-nil if Fido-Vertical mode is enabled.
+See the `fido-vertical-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 `fido-vertical-mode'.")
+
+(custom-autoload 'fido-vertical-mode "icomplete" nil)
+
+(autoload 'fido-vertical-mode "icomplete" "\
+Toggle vertical candidate display in `fido-mode'.
+When turning on, if non-vertical `fido-mode' is off, turn it on.
+If it's on, just add the vertical display.
+
+This is a minor mode.  If called interactively, toggle the
+`Fido-Vertical mode' 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.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `(default-value 'fido-vertical-mode)'.
+
+The mode's hook is called both when the mode is enabled and when it is
+disabled.
+
+\(fn &optional ARG)" t nil)
 (when (locate-library "obsolete/iswitchb")
  (autoload 'iswitchb-mode "iswitchb" "Toggle Iswitchb mode." t)
  (make-obsolete 'iswitchb-mode
    "use `icomplete-mode' or `ido-mode' instead." "24.4"))
 
-(register-definition-prefixes "icomplete" '("fido-vertical-mode" "icomplete-"))
+(register-definition-prefixes "icomplete" '("icomplete-"))
 
 ;;;***
 
@@ -19860,7 +19939,7 @@ Create lambda form for macro bound to symbol or key.
 ;;;;;;  0 0))
 ;;; Generated autoloads from language/korea-util.el
 
-(defvar default-korean-keyboard (purecopy (if (string-match "3" (or (getenv 
"HANGUL_KEYBOARD_TYPE") "")) "3" "")) "\
+(defvar default-korean-keyboard (purecopy (if (string-search "3" (or (getenv 
"HANGUL_KEYBOARD_TYPE") "")) "3" "")) "\
 The kind of Korean keyboard for Korean (Hangul) input method.
 \"\" for 2, \"3\" for 3, and \"3f\" for 3f.")
 
@@ -20139,8 +20218,11 @@ or call the function `global-linum-mode'.")
 (autoload 'global-linum-mode "linum" "\
 Toggle Linum mode in all buffers.
 With prefix ARG, enable Global Linum mode if ARG is positive;
-otherwise, disable it.  If called from Lisp, enable the mode if ARG is
-omitted or nil.
+otherwise, disable it.
+
+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.
 
 Linum mode is enabled in all buffers where `linum-on' would do it.
 
@@ -20534,7 +20616,10 @@ This function is primarily meant for when you're 
displaying the
 result to the user: Many prettifications are applied to the
 result returned.  If you want to decode an address for further
 non-display use, you should probably use
-`mail-header-parse-address' instead.
+`mail-header-parse-address' instead.  Also see
+`mail-header-parse-address-lax' for a function that's less strict
+than `mail-header-parse-address', but does less post-processing
+to the results.
 
 \(fn ADDRESS &optional ALL)" nil nil)
 
@@ -21057,7 +21142,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 3 0)) package--builtin-versions)
+(push (purecopy '(map 3 1)) package--builtin-versions)
 
 (register-definition-prefixes "map" '("map-"))
 
@@ -22479,7 +22564,7 @@ The default is 20.  If LIMIT is negative, do not limit 
the listing.
 
 \(fn &optional LIMIT)" t nil)
 
-(register-definition-prefixes "mule-diag" '("charset-history" 
"describe-font-internal" "insert-section" "list-" "print-" 
"sort-listed-character-sets"))
+(register-definition-prefixes "mule-diag" '("charset-history" 
"describe-font-internal" "insert-section" "list-" "mule--kbd-at" "print-" 
"sort-listed-character-sets"))
 
 ;;;***
 
@@ -22603,7 +22688,9 @@ QUALITY can be:
   `approximate', in which case we may cut some corners to avoid
     excessive work.
   `exact', in which case we may end up re-(en/de)coding a large
-    part of the file/buffer, this can be expensive and slow.
+    part of the file/buffer, this can be expensive and slow.  (It
+    is an error to request the `exact' method when the buffer's
+    EOL format is not yet decided.)
   nil, in which case we may return nil rather than an approximation.
 
 \(fn BYTE &optional QUALITY CODING-SYSTEM)" nil nil)
@@ -22617,7 +22704,9 @@ QUALITY can be:
   `approximate', in which case we may cut some corners to avoid
     excessive work.
   `exact', in which case we may end up re-(en/de)coding a large
-    part of the file/buffer, this can be expensive and slow.
+    part of the file/buffer, this can be expensive and slow.  (It
+    is an error to request the `exact' method when the buffer's
+    EOL format is not yet decided.)
   nil, in which case we may return nil rather than an approximation.
 
 \(fn POSITION &optional QUALITY CODING-SYSTEM)" nil nil)
@@ -22629,13 +22718,13 @@ QUALITY can be:
 ;;;### (autoloads nil "mwheel" "mwheel.el" (0 0 0 0))
 ;;; Generated autoloads from mwheel.el
 
-(defcustom mouse-wheel-mode t "\
+(defvar 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 :type 'boolean :group 'mouse)
+or call the function `mouse-wheel-mode'.")
 
 (custom-autoload 'mouse-wheel-mode "mwheel" nil)
 
@@ -25099,6 +25188,19 @@ of the elements of LIST is performed as if by 
`pcase-let'.
 
 (function-put 'pcase-dolist 'lisp-indent-function '1)
 
+(autoload 'pcase-setq "pcase" "\
+Assign values to variables by destructuring with `pcase'.
+PATTERNS are normal `pcase' patterns, and VALUES are expression.
+
+Evaluation happens sequentially as in `setq' (not in parallel).
+
+An example: (pcase-setq `((,a) [(,b)]) '((1) [(2)]))
+
+VAL is presumed to match PAT.  Failure to match may signal an error or go
+undetected, binding variables to arbitrary values, such as nil.
+
+\(fn PATTERNS VALUE PATTERN VALUES ...)" nil t)
+
 (autoload 'pcase-defmacro "pcase" "\
 Define a new kind of pcase PATTERN, by macro expansion.
 Patterns of the form (NAME ...) will be expanded according
@@ -26303,7 +26405,7 @@ Open profile FILENAME.
 
 ;;;### (autoloads nil "project" "progmodes/project.el" (0 0 0 0))
 ;;; Generated autoloads from progmodes/project.el
-(push (purecopy '(project 0 6 0)) package--builtin-versions)
+(push (purecopy '(project 0 6 1)) package--builtin-versions)
 
 (autoload 'project-current "project" "\
 Return the project instance in DIRECTORY, defaulting to `default-directory'.
@@ -28076,10 +28178,10 @@ disabled.
 
 ;;;***
 
-;;;### (autoloads nil "rfc2368" "mail/rfc2368.el" (0 0 0 0))
-;;; Generated autoloads from mail/rfc2368.el
+;;;### (autoloads nil "rfc6068" "mail/rfc6068.el" (0 0 0 0))
+;;; Generated autoloads from mail/rfc6068.el
 
-(register-definition-prefixes "rfc2368" '("rfc2368-"))
+(register-definition-prefixes "rfc6068" '("rfc6068-"))
 
 ;;;***
 
@@ -28919,7 +29021,8 @@ Zero-width assertions: these all match the empty string 
in specific places.
 
 \(literal EXPR) Match the literal string from evaluating EXPR at run time.
 \(regexp EXPR)  Match the string regexp from evaluating EXPR at run time.
-\(eval EXPR)    Match the rx sexp from evaluating EXPR at compile time.
+\(eval EXPR)    Match the rx sexp from evaluating EXPR at macro-expansion
+                (compile) time.
 
 Additional constructs can be defined using `rx-define' and `rx-let',
 which see.
@@ -30799,7 +30902,7 @@ then `snmpv2-mode-hook'." t nil)
 
 ;;;### (autoloads nil "so-long" "so-long.el" (0 0 0 0))
 ;;; Generated autoloads from so-long.el
-(push (purecopy '(so-long 1 0)) package--builtin-versions)
+(push (purecopy '(so-long 1 1 1)) package--builtin-versions)
 
 (autoload 'so-long-commentary "so-long" "\
 View the so-long documentation in `outline-mode'." t nil)
@@ -32117,6 +32220,14 @@ Truncate STRING to LENGTH, replacing initial surplus 
with \"...\".
 
 \(fn STRING LENGTH)" nil nil)
 
+(autoload 'string-clean-whitespace "subr-x" "\
+Clean up whitespace in STRING.
+All sequences of whitespaces in STRING are collapsed into a
+single space character, and leading/trailing whitespace is
+removed.
+
+\(fn STRING)" nil nil)
+
 (autoload 'string-lines "subr-x" "\
 Split STRING into a list of lines.
 If OMIT-NULLS, empty lines will be removed from the results.
@@ -32184,8 +32295,11 @@ or call the function `global-subword-mode'.")
 (autoload 'global-subword-mode "subword" "\
 Toggle Subword mode in all buffers.
 With prefix ARG, enable Global Subword mode if ARG is positive;
-otherwise, disable it.  If called from Lisp, enable the mode if ARG is
-omitted or nil.
+otherwise, disable it.
+
+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.
 
 Subword mode is enabled in all buffers where `(lambda nil
 \(subword-mode 1))' would do it.
@@ -32235,8 +32349,11 @@ or call the function `global-superword-mode'.")
 (autoload 'global-superword-mode "subword" "\
 Toggle Superword mode in all buffers.
 With prefix ARG, enable Global Superword mode if ARG is positive;
-otherwise, disable it.  If called from Lisp, enable the mode if ARG is
-omitted or nil.
+otherwise, disable it.
+
+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.
 
 Superword mode is enabled in all buffers where `(lambda nil
 \(superword-mode 1))' would do it.
@@ -32372,8 +32489,11 @@ or call the function `global-tab-line-mode'.")
 (autoload 'global-tab-line-mode "tab-line" "\
 Toggle Tab-Line mode in all buffers.
 With prefix ARG, enable Global Tab-Line mode if ARG is positive;
-otherwise, disable it.  If called from Lisp, enable the mode if ARG is
-omitted or nil.
+otherwise, disable it.
+
+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.
 
 Tab-Line mode is enabled in all buffers where
 `tab-line-mode--turn-on' would do it.
@@ -33727,12 +33847,16 @@ positions of the thing found.
 Return the THING at point.
 THING should be a symbol specifying a type of syntactic entity.
 Possibilities include `symbol', `list', `sexp', `defun',
-`filename', `url', `email', `uuid', `word', `sentence', `whitespace',
-`line', `number', and `page'.
+`filename', `existing-filename', `url', `email', `uuid', `word',
+`sentence', `whitespace', `line', `number', and `page'.
 
 When the optional argument NO-PROPERTIES is non-nil,
 strip text properties from the return value.
 
+If the current buffer uses fields (see Info node `(elisp)Fields'),
+this function will narrow to the field before identifying the
+thing at point.
+
 See the file `thingatpt.el' for documentation on how to define
 a symbol as a valid THING.
 
@@ -34165,25 +34289,37 @@ Valid ZONE values are described in the documentation 
of `format-time-string'.
 (put 'time-stamp-pattern 'safe-local-variable 'stringp)
 
 (autoload 'time-stamp "time-stamp" "\
-Update the time stamp string(s) in the buffer.
-A template in a file can be automatically updated with a new time stamp
-every time you save the file.  Add this line to your init file:
-    (add-hook \\='before-save-hook \\='time-stamp)
-or customize option `before-save-hook'.
-Normally the template must appear in the first 8 lines of a file and
-look like one of the following:
+Update any time stamp string(s) in the buffer.
+This function looks for a time stamp template and updates it with
+the current date, time, and/or other info.
+
+The template, which you manually create on one of the first 8 lines
+of the file before running this function, by default can look like
+one of the following (your choice):
       Time-stamp: <>
       Time-stamp: \" \"
-The time stamp is written between the brackets or quotes:
+This function writes the current time between the brackets or quotes,
+by default formatted like this:
       Time-stamp: <2020-08-07 17:10:21 gildea>
 
-The time stamp is updated only if the variable
-`time-stamp-active' is non-nil.
-The format of the time stamp is set by the variable
-`time-stamp-pattern' or `time-stamp-format'.
-The variables `time-stamp-pattern', `time-stamp-line-limit',
-`time-stamp-start', `time-stamp-end', `time-stamp-count', and
-`time-stamp-inserts-lines' control finding the template." t nil)
+Although you can run this function manually to update a time stamp
+once, usually you want automatic time stamp updating.
+
+A time stamp can be automatically updated with current information
+every time you save a file.  To enable time-stamping for all files,
+customize option `before-save-hook' or add this line to your init file:
+    (add-hook \\='before-save-hook \\='time-stamp)
+
+To enable automatic time-stamping for only a specific file, add
+this line to a local variables list near the end of the file:
+    eval: (add-hook \\='before-save-hook \\='time-stamp nil t)
+
+If the file has no time-stamp template, this function does nothing.
+
+You can set `time-stamp-pattern' in a files's local variables list
+to customize the information in the time stamp and where it is written.
+
+The time stamp is updated only if `time-stamp-active' is non-nil." t nil)
 
 (autoload 'time-stamp-toggle-active "time-stamp" "\
 Toggle `time-stamp-active', setting whether \\[time-stamp] updates a buffer.
@@ -34219,6 +34355,9 @@ updating.  With prefix ARG, turn mode line display on 
if and only
 if ARG is positive.  Returns the new status of timeclock mode line
 display (non-nil means on).
 
+If using a customized `timeclock-workday' value, this should be
+set before switching this mode on.
+
 \(fn &optional ARG)" t nil)
 
 (autoload 'timeclock-in "timeclock" "\
@@ -35508,7 +35647,9 @@ or call the function `url-handler-mode'.")
 (custom-autoload 'url-handler-mode "url-handlers" nil)
 
 (autoload 'url-handler-mode "url-handlers" "\
-Toggle using `url' library for URL filenames (URL Handler mode).
+Handle URLs as if they were file names throughout Emacs.
+After switching on this minor mode, Emacs file primitives handle
+URLs.  For instance:
 
 This is a minor mode.  If called interactively, toggle the
 `Url-Handler mode' mode.  If the prefix argument is positive, enable
@@ -35524,6 +35665,12 @@ evaluate `(default-value 'url-handler-mode)'.
 The mode's hook is called both when the mode is enabled and when it is
 disabled.
 
+  (file-exists-p \"https://www.gnu.org/\";)
+  => t
+
+and `C-x C-f https://www.gnu.org/ RET' will give you the HTML at
+that URL in a buffer.
+
 \(fn &optional ARG)" t nil)
 
 (autoload 'url-file-handler "url-handlers" "\
@@ -36483,11 +36630,6 @@ log entries should be gathered.
 
 \(fn &rest ARGS)" t nil)
 
-(autoload 'vc-branch-part "vc" "\
-Return the branch part of a revision number REV.
-
-\(fn REV)" nil nil)
-
 (register-definition-prefixes "vc" '("vc-" "with-vc-properties"))
 
 ;;;***
@@ -38984,6 +39126,8 @@ definition for IDENTIFIER, display it in the selected 
window.
 Otherwise, display the list of the possible definitions in a
 buffer where the user can select from the list.
 
+Use \\[xref-pop-marker-stack] to return back to where you invoked this command.
+
 \(fn IDENTIFIER)" t nil)
 
 (autoload 'xref-find-definitions-other-window "xref" "\
@@ -39012,6 +39156,12 @@ This command is intended to be bound to a mouse event.
 
 \(fn EVENT)" t nil)
 
+(autoload 'xref-find-references-at-mouse "xref" "\
+Find references to the identifier at or around mouse click.
+This command is intended to be bound to a mouse event.
+
+\(fn EVENT)" t nil)
+
 (autoload 'xref-find-apropos "xref" "\
 Find all meaningful symbols that match PATTERN.
 The argument has the same meaning as in `apropos'.
diff --git a/lisp/mail/footnote.el b/lisp/mail/footnote.el
index 995ae5f..b765602 100644
--- a/lisp/mail/footnote.el
+++ b/lisp/mail/footnote.el
@@ -713,7 +713,7 @@ Return the footnote number to use."
   (save-excursion
     (let (rc)
       (dolist (alist-elem footnote--markers-alist)
-       (when (<= (point) (cl-caddr alist-elem))
+        (when (<= (point) (caddr alist-elem))
          (unless rc
            (setq rc (car alist-elem)))
          (save-excursion
@@ -835,7 +835,7 @@ being set it is automatically widened."
     (when note
       (when footnote-narrow-to-footnotes-when-editing
        (widen))
-      (goto-char (cl-caddr (assq note footnote--markers-alist)))
+      (goto-char (caddr (assq note footnote--markers-alist)))
       (when (looking-at (footnote--current-regexp))
         (goto-char (match-end 0))))))
 
diff --git a/lisp/mail/rfc6068.el b/lisp/mail/rfc6068.el
new file mode 100644
index 0000000..34fd7b5
--- /dev/null
+++ b/lisp/mail/rfc6068.el
@@ -0,0 +1,83 @@
+;;; rfc6068.el --- support for rfc6068  -*- lexical-binding: t -*-
+
+;; Copyright (C) 2021 Free Software Foundation, Inc.
+
+;; Keywords: mail
+
+;; 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:
+
+(defun rfc6068-unhexify-string (string &optional inhibit-decode)
+  "Unhexify STRING -- e.g. `hello%20there' -> `hello there'.
+STRING is assumed to be a percentage-encoded utf-8 string.
+
+If INHIBIT-DECODE is non-nil, return the resulting raw byte
+string instead of decoding as utf-8."
+  (let ((string
+         (with-temp-buffer
+           (set-buffer-multibyte nil)
+           (insert string)
+           (goto-char (point-min))
+           (while (re-search-forward "%\\([[:xdigit:]]\\{2\\}\\)" nil t)
+             (replace-match (string (string-to-number (match-string 1) 16))
+                            t t))
+           (buffer-string))))
+    (if inhibit-decode
+        string
+      (decode-coding-string string 'utf-8))))
+
+(defun rfc6068-parse-mailto-url (mailto-url)
+  "Parse MAILTO-URL, and return an alist of header-name, header-value pairs.
+MAILTO-URL should be a RFC 6068 (mailto) compliant url.  A cons cell w/ a
+key of `Body' is a special case and is considered a header for this purpose.
+The returned alist is intended for use w/ the `compose-mail' interface.
+Note: make sure MAILTO-URL has been \"unhtmlized\" (e.g., &amp; -> &), before
+calling this function."
+  (let ((case-fold-search t)
+       headers-alist)
+    (setq mailto-url (string-replace "\n" " " mailto-url))
+    (when (string-match "^\\(mailto:\\)\\([^?]+\\)?\\(\\?\\(.*\\)\\)*"
+                        mailto-url)
+      (let ((address (match-string 2 mailto-url))
+            (query (match-string 4 mailto-url)))
+       ;; Build alist of header name-value pairs.
+       (when query
+         (setq headers-alist
+               (mapcar
+                (lambda (x)
+                  (let* ((pair (split-string x "="))
+                         (name (car pair))
+                         (value (cadr pair)))
+                    ;; Return ("Header-Name" . "header-value").
+                    (cons
+                     (capitalize (rfc6068-unhexify-string name))
+                     (rfc6068-unhexify-string value))))
+                (split-string query "&"))))
+
+       (when address
+         (setq address (rfc6068-unhexify-string address))
+         ;; Deal with multiple 'To' recipients.
+         (if-let ((elem (assoc "To" headers-alist)))
+             (setcdr elem (concat address ", " (cdr elem)))
+            (push (cons "To" address) headers-alist)))
+
+       headers-alist))))
+
+(provide 'rfc6068)
+
+;;; rfc6068.el ends here
diff --git a/lisp/mh-e/mh-comp.el b/lisp/mh-e/mh-comp.el
index 4fae69d..404b6b3 100644
--- a/lisp/mh-e/mh-comp.el
+++ b/lisp/mh-e/mh-comp.el
@@ -38,6 +38,7 @@
 (require 'sendmail)
 
 (autoload 'easy-menu-add "easymenu")
+(autoload 'mail-header-parse-address "mail-parse")
 (autoload 'mml-insert-tag "mml")
 
 
@@ -452,7 +453,7 @@ See also `mh-send'."
              ;; Header field exists and we have a value
              (let (address mailbox (alias (mh-alias-expand value)))
                (and alias
-                    (setq address (ietf-drums-parse-address alias))
+                    (setq address (mail-header-parse-address alias))
                     (setq mailbox (car address)))
                ;; XXX - Need to parse all addresses out of field
                (if (and
diff --git a/lisp/mh-e/mh-e.el b/lisp/mh-e/mh-e.el
index 949787a..375072b 100644
--- a/lisp/mh-e/mh-e.el
+++ b/lisp/mh-e/mh-e.el
@@ -33,7 +33,7 @@
 ;; recommended.
 
 ;; MH (Message Handler) is a powerful mail reader. See
-;; http://rand-mh.sourceforge.net/.
+;; https://rand-mh.sourceforge.io/.
 
 ;; N.B. MH must have been compiled with the MHE compiler flag or several
 ;; features necessary for MH-E will be missing from MH commands, specifically
@@ -82,7 +82,8 @@
 ;; Rewritten for GNU Emacs, James Larus, 1985.
 ;; Modified by Stephen Gildea, 1988.
 ;; Maintenance picked up by Bill Wohler and the
-;; SourceForge Crew <http://mh-e.sourceforge.net/>, 2001.
+;;   SourceForge Crew <https://mh-e.sourceforge.io/>, 2001.
+;; Since 2016, MH-E development occurs within the Emacs repository.
 
 ;;; Code:
 
diff --git a/lisp/mh-e/mh-junk.el b/lisp/mh-e/mh-junk.el
index 6c36748..467667f 100644
--- a/lisp/mh-e/mh-junk.el
+++ b/lisp/mh-e/mh-junk.el
@@ -31,6 +31,8 @@
 (require 'mh-e)
 (require 'mh-scan)
 
+(autoload 'mail-header-parse-address "mail-parse")
+
 ;;;###mh-autoload
 (defun mh-junk-blocklist (range)
   "Blocklist RANGE as spam.
@@ -312,8 +314,7 @@ See `mh-spamassassin-blocklist' for more information."
                         "--ham" "--local" "--no-sync")))
       (message "Allowlisting sender of message %d..." msg)
       (setq from
-            (car (mh-funcall-if-exists
-                  ietf-drums-parse-address (mh-get-header-field "From:"))))
+            (car (mail-header-parse-address (mh-get-header-field "From:"))))
       (kill-buffer nil)
       (if (or (null from) (equal from ""))
           (message "Allowlisting sender of message %d...%s"
diff --git a/lisp/mh-e/mh-mime.el b/lisp/mh-e/mh-mime.el
index ef70252..ad594ae 100644
--- a/lisp/mh-e/mh-mime.el
+++ b/lisp/mh-e/mh-mime.el
@@ -51,6 +51,7 @@
 (autoload 'article-emphasize "gnus-art")
 (autoload 'gnus-eval-format "gnus-spec")
 (autoload 'mail-content-type-get "mail-parse")
+(autoload 'mail-decode-encoded-word-region "mail-parse")
 (autoload 'mail-decode-encoded-word-string "mail-parse")
 (autoload 'mail-header-parse-content-type "mail-parse")
 (autoload 'mail-header-strip-cte "mail-parse")
@@ -61,7 +62,6 @@
 (autoload 'mm-decode-body "mm-bodies")
 (autoload 'mm-uu-dissect "mm-uu")
 (autoload 'mml-unsecure-message "mml-sec")
-(autoload 'rfc2047-decode-region "rfc2047")
 (autoload 'widget-convert-button "wid-edit")
 
 
@@ -496,7 +496,7 @@ decoding the same message multiple times."
   "Decode RFC2047 encoded message header fields."
   (when mh-decode-mime-flag
     (let ((buffer-read-only nil))
-      (rfc2047-decode-region (point-min) (mh-mail-header-end)))))
+      (mail-decode-encoded-word-region (point-min) (mh-mail-header-end)))))
 
 ;;;###mh-autoload
 (defun mh-decode-message-subject ()
@@ -504,8 +504,9 @@ decoding the same message multiple times."
   (when mh-decode-mime-flag
     (save-excursion
       (let ((buffer-read-only nil))
-        (rfc2047-decode-region (progn (mh-goto-header-field "Subject:") 
(point))
-                               (progn (mh-header-field-end) (point)))))))
+        (mail-decode-encoded-word-region
+         (progn (mh-goto-header-field "Subject:") (point))
+         (progn (mh-header-field-end) (point)))))))
 
 ;;;###mh-autoload
 (defun mh-mime-display (&optional pre-dissected-handles)
diff --git a/lisp/mh-e/mh-xface.el b/lisp/mh-e/mh-xface.el
index d4d5c5c..58177c1 100644
--- a/lisp/mh-e/mh-xface.el
+++ b/lisp/mh-e/mh-xface.el
@@ -27,6 +27,7 @@
 
 (require 'mh-e)
 
+(autoload 'mail-header-parse-address "mail-parse")
 (autoload 'message-fetch-field "message")
 
 (defvar mh-show-xface-function
@@ -190,11 +191,7 @@ The directories are searched for in the order they appear 
in the list.")
     (let* ((from-field (ignore-errors (car (message-tokenize-header
                                             (mh-get-header-field "from:")))))
            (from (car (ignore-errors
-                        ;; Don't use mh-funcall-if-exists because
-                        ;; ietf-drums-parse-address might exist at run-time but
-                        ;; not at compile-time.
-                        (when (fboundp 'ietf-drums-parse-address)
-                          (ietf-drums-parse-address from-field)))))
+                        (mail-header-parse-address from-field))))
            (host (and from
                       (string-match "\\([^+]*\\)\\(\\+.*\\)?@\\(.*\\)" from)
                       (downcase (match-string 3 from))))
@@ -391,10 +388,12 @@ filenames.  In addition, replaces * with %2a. See URL
 (defun mh-x-image-url-sane-p (url)
   "Check if URL is something sensible."
   (let ((len (length url)))
-    (cond ((< len 5) nil)
-          ((not (equal (substring url 0 5) "http:")) nil)
-          ((> len 100) nil)
-          (t t))))
+    (cond ((> len 100) nil)
+          ((and (>= len 5)
+                (equal (substring url 0 5) "http:") t))
+          ((and (>= len 6)
+                (equal (substring url 0 6) "https:") t))
+          (t nil))))
 
 (defun mh-x-image-display (image marker)
   "Display IMAGE at MARKER."
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index f335a9e..68e4fa1 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -1496,7 +1496,8 @@ Remove completion BASE prefix string from history 
elements."
                                            base-size md
                                            minibuffer-completion-table
                                            minibuffer-completion-predicate))
-             (sort-fun (completion-metadata-get all-md 'cycle-sort-function)))
+             (sort-fun (completion-metadata-get all-md 'cycle-sort-function))
+             (group-fun (completion-metadata-get all-md 'group-function)))
         (when last
           (setcdr last nil)
 
@@ -1506,17 +1507,25 @@ Remove completion BASE prefix string from history 
elements."
           (setq all (delete-dups all))
           (setq last (last all))
 
-          (if sort-fun
-              (setq all (funcall sort-fun all))
-            ;; Sort first by length and alphabetically.
+          (cond
+           (sort-fun (setq all (funcall sort-fun all)))
+           ((and completions-group group-fun)
+            ;; TODO: experiment with re-grouping here.  Might be slow
+            ;; if the group-fun (given by the table and out of our
+            ;; control) is slow and/or allocates too much.
+            )
+           (t
+            ;; If the table doesn't stipulate a sorting function or a
+            ;; group function, sort first by length and
+            ;; alphabetically.
             (setq all (minibuffer--sort-by-length-alpha all))
-            ;; Sort by history position, put the default, if it
+            ;; Then sort by history position, and put the default, if it
             ;; exists, on top.
             (when (minibufferp)
               (setq all (minibuffer--sort-by-position
                          (minibuffer--sort-preprocess-history
                           (substring string 0 base-size))
-                         all))))
+                         all)))))
 
           ;; Cache the result.  This is not just for speed, but also so that
           ;; repeated calls to minibuffer-force-complete can cycle through
@@ -3520,7 +3529,8 @@ string in COMPLETIONS.  Return a deep copy of COMPLETIONS 
where
 each string is propertized with `completion-score', a number
 between 0 and 1, and with faces `completions-common-part',
 `completions-first-difference' in the relevant segments."
-  (when completions
+  (cond
+   ((and completions (cl-loop for e in pattern thereis (stringp e)))
     (let* ((re (completion-pcm--pattern->regex pattern 'group))
            (point-idx (completion-pcm--pattern-point-idx pattern))
            (case-fold-search completion-ignore-case)
@@ -3611,7 +3621,8 @@ between 0 and 1, and with faces `completions-common-part',
               0 1 'completion-score
               (/ score-numerator (* end (1+ score-denominator)) 1.0) str)))
          str)
-       completions))))
+       completions)))
+   (t completions)))
 
 (defun completion-pcm--find-all-completions (string table pred point
                                                     &optional filter)
@@ -3943,51 +3954,38 @@ that is non-nil."
 (put 'flex 'completion--adjust-metadata 'completion--flex-adjust-metadata)
 
 (defun completion--flex-adjust-metadata (metadata)
-  (cl-flet
-      ((compose-flex-sort-fn
-        (existing-sort-fn) ; wish `cl-flet' had proper indentation...
-        (lambda (completions)
-          (cond
-           (;; Sort by flex score whenever outside the minibuffer or
-            ;; in the minibuffer with some input.  JT@2019-12-23:
-            ;; FIXME: this is still wrong.  What we need to test here
-            ;; is "some input that actually leads to flex filtering",
-            ;; not "something after the minibuffer prompt".  Among
-            ;; other inconsistencies, the latter is always true for
-            ;; file searches, meaning the next clauses in this cond
-            ;; will be ignored.
-            (or (not (window-minibuffer-p))
-                (> (point-max) (minibuffer-prompt-end)))
+  "If `flex' is actually doing filtering, adjust sorting."
+  (let ((flex-is-filtering-p
+         ;; JT@2019-12-23: FIXME: this is kinda wrong.  What we need
+         ;; to test here is "some input that actually leads/led to
+         ;; flex filtering", not "something after the minibuffer
+         ;; prompt".  E.g. The latter is always true for file
+         ;; searches, meaning we'll be doing extra work when we
+         ;; needn't.
+         (or (not (window-minibuffer-p))
+             (> (point-max) (minibuffer-prompt-end))))
+        (existing-dsf
+         (completion-metadata-get metadata 'display-sort-function))
+        (existing-csf
+         (completion-metadata-get metadata 'cycle-sort-function)))
+    (cl-flet
+        ((compose-flex-sort-fn
+          (existing-sort-fn) ; wish `cl-flet' had proper indentation...
+          (lambda (completions)
             (sort
-             (if existing-sort-fn
-                 (funcall existing-sort-fn completions)
-               completions)
+             (funcall existing-sort-fn completions)
              (lambda (c1 c2)
                (let ((s1 (get-text-property 0 'completion-score c1))
                      (s2 (get-text-property 0 'completion-score c2)))
-                 (> (or s1 0) (or s2 0))))))
-           (;; If no existing sort fn and nothing flexy happening, use
-            ;; the customary sorting strategy.
-            ;;
-            ;; JT@2021-08-15: FIXME: ideally this wouldn't repeat
-            ;; logic in `completion-all-sorted-completions', but that
-            ;; logic has other context that is either expensive to
-            ;; compute or not easy to access here.
-            (not existing-sort-fn)
-            (let ((lalpha (minibuffer--sort-by-length-alpha completions))
-                  (hist (and (minibufferp)
-                             (and (not (eq minibuffer-history-variable t))
-                                  (symbol-value 
minibuffer-history-variable)))))
-              (if hist (minibuffer--sort-by-position hist lalpha) lalpha)))
-           (t (funcall existing-sort-fn completions))))))
-    `(metadata
-      (display-sort-function
-       . ,(compose-flex-sort-fn
-           (completion-metadata-get metadata 'display-sort-function)))
-      (cycle-sort-function
-       . ,(compose-flex-sort-fn
-           (completion-metadata-get metadata 'cycle-sort-function)))
-      ,@(cdr metadata))))
+                 (> (or s1 0) (or s2 0))))))))
+      `(metadata
+        ,@(and flex-is-filtering-p
+               `((display-sort-function
+                  . ,(compose-flex-sort-fn (or existing-dsf #'identity)))))
+        ,@(and flex-is-filtering-p
+               `((cycle-sort-function
+                  . ,(compose-flex-sort-fn (or existing-csf #'identity)))))
+        ,@(cdr metadata)))))
 
 (defun completion-flex--make-flex-pattern (pattern)
   "Convert PCM-style PATTERN into PCM-style flex pattern.
diff --git a/lisp/mouse.el b/lisp/mouse.el
index cf7c17b..7d3ed9a 100644
--- a/lisp/mouse.el
+++ b/lisp/mouse.el
@@ -277,6 +277,228 @@ not it is actually displayed."
            minor-mode-menus)))
 
 
+;; Context menus.
+
+(defcustom context-menu-functions '(context-menu-undo
+                                    context-menu-region
+                                    context-menu-local
+                                    context-menu-minor)
+  "List of functions that produce the contents of the context menu.
+Each function receives the menu as its argument and should return
+the same menu with changes such as added new menu items."
+  :type '(repeat
+          (choice (function-item context-menu-undo)
+                  (function-item context-menu-region)
+                  (function-item context-menu-toolbar)
+                  (function-item context-menu-global)
+                  (function-item context-menu-local)
+                  (function-item context-menu-minor)
+                  (function-item context-menu-buffers)
+                  (function-item context-menu-vc)
+                  (function-item context-menu-ffap)
+                  (function :tag "Custom function")))
+  :version "28.1")
+
+(defcustom context-menu-filter-function nil
+  "Function that can filter the list produced by `context-menu-functions'."
+  :type '(choice (const nil) function)
+  :version "28.1")
+
+(defun context-menu-map ()
+  "Return composite menu map."
+  (let ((menu (make-sparse-keymap (propertize "Context Menu" 'hide t))))
+    (let ((fun (mouse-posn-property (event-start last-input-event)
+                                    'context-menu-function)))
+      (if (functionp fun)
+          (setq menu (funcall fun menu))
+        (run-hook-wrapped 'context-menu-functions
+                          (lambda (fun)
+                            (setq menu (funcall fun menu))
+                            nil))))
+    ;; TODO: remove double separators
+    (when (functionp context-menu-filter-function)
+      (setq menu (funcall context-menu-filter-function menu)))
+    menu))
+
+(defun context-menu-toolbar (menu)
+  "Tool bar menu items."
+  (run-hooks 'activate-menubar-hook 'menu-bar-update-hook)
+  (define-key-after menu [separator-toolbar] menu-bar-separator)
+  (map-keymap (lambda (key binding)
+                (when (consp binding)
+                  (define-key-after menu (vector key)
+                    (copy-sequence binding))))
+              (lookup-key global-map [tool-bar]))
+  menu)
+
+(defun context-menu-global (menu)
+  "Global submenus."
+  (run-hooks 'activate-menubar-hook 'menu-bar-update-hook)
+  (define-key-after menu [separator-global] menu-bar-separator)
+  (map-keymap (lambda (key binding)
+                (when (consp binding)
+                  (define-key-after menu (vector key)
+                    (copy-sequence binding))))
+              (lookup-key global-map [menu-bar]))
+  menu)
+
+(defun context-menu-local (menu)
+  "Major mode submenus."
+  (run-hooks 'activate-menubar-hook 'menu-bar-update-hook)
+  (define-key-after menu [separator-local] menu-bar-separator)
+  (let ((keymap (local-key-binding [menu-bar])))
+    (when keymap
+      (map-keymap (lambda (key binding)
+                    (when (consp binding)
+                      (define-key-after menu (vector key)
+                        (copy-sequence binding))))
+                  keymap)))
+  menu)
+
+(defun context-menu-minor (menu)
+  "Minor modes submenus."
+  (run-hooks 'activate-menubar-hook 'menu-bar-update-hook)
+  (define-key-after menu [separator-minor] menu-bar-separator)
+  (dolist (mode (reverse (minor-mode-key-binding [menu-bar])))
+    (when (and (consp mode) (symbol-value (car mode)))
+      (map-keymap (lambda (key binding)
+                    (when (consp binding)
+                      (define-key-after menu (vector key)
+                        (copy-sequence binding))))
+                  (cdr mode))))
+  menu)
+
+(defun context-menu-buffers (menu)
+  "Submenus with buffers."
+  (run-hooks 'activate-menubar-hook 'menu-bar-update-hook)
+  (define-key-after menu [separator-buffers] menu-bar-separator)
+  (map-keymap (lambda (key binding)
+                (when (consp binding)
+                  (define-key-after menu (vector key)
+                    (copy-sequence binding))))
+              (mouse-buffer-menu-keymap))
+  menu)
+
+(defun context-menu-vc (menu)
+  "Version Control menu."
+  (define-key-after menu [separator-vc] menu-bar-separator)
+  (define-key-after menu [vc-menu] vc-menu-entry)
+  menu)
+
+(defun context-menu-undo (menu)
+  "Undo menu."
+  (when (cddr menu)
+    (define-key-after menu [separator-undo] menu-bar-separator))
+  (define-key-after menu [undo]
+    '(menu-item "Undo" undo
+                :visible (and (not buffer-read-only)
+                              (not (eq t buffer-undo-list))
+                              (if (eq last-command 'undo)
+                                  (listp pending-undo-list)
+                                (consp buffer-undo-list)))
+                :help "Undo last edits"))
+  (define-key-after menu [undo-redo]
+    '(menu-item "Redo" undo-redo
+                :visible (and (not buffer-read-only)
+                              (undo--last-change-was-undo-p buffer-undo-list))
+                :help "Redo last undone edits"))
+  menu)
+
+(defun context-menu-region (menu)
+  "Region commands menu."
+  (when (cddr menu)
+    (define-key-after menu [separator-region] menu-bar-separator))
+  (define-key-after menu [cut]
+    '(menu-item "Cut" kill-region
+                :visible (and mark-active (not buffer-read-only))
+                :help
+                "Cut (kill) text in region between mark and current position"))
+  (define-key-after menu [copy]
+    ;; ns-win.el said: Substitute a Copy function that works better
+    ;; under X (for GNUstep).
+    `(menu-item "Copy" ,(if (featurep 'ns)
+                            'ns-copy-including-secondary
+                          'kill-ring-save)
+                :visible mark-active
+                :help "Copy text in region between mark and current position"
+                :keys ,(if (featurep 'ns)
+                           "\\[ns-copy-including-secondary]"
+                         "\\[kill-ring-save]")))
+  (define-key-after menu [paste]
+    `(menu-item "Paste" mouse-yank-at-click
+                :visible (funcall
+                          ',(lambda ()
+                              (and (or
+                                    (gui-backend-selection-exists-p 'CLIPBOARD)
+                                    (if (featurep 'ns) ; like paste-from-menu
+                                        (cdr yank-menu)
+                                      kill-ring))
+                                   (not buffer-read-only))))
+                :help "Paste (yank) text most recently cut/copied"))
+  (define-key-after menu (if (featurep 'ns) [select-paste]
+                           [paste-from-menu])
+    ;; ns-win.el said: Change text to be more consistent with
+    ;; surrounding menu items `paste', etc."
+    `(menu-item ,(if (featurep 'ns) "Select and Paste" "Paste from Kill Menu")
+                yank-menu
+                :visible (and (cdr yank-menu) (not buffer-read-only))
+                :help "Choose a string from the kill ring and paste it"))
+  (define-key-after menu [clear]
+    '(menu-item "Clear" delete-active-region
+                :visible (and mark-active
+                              (not buffer-read-only))
+                :help
+                "Delete the text in region between mark and current position"))
+  (define-key-after menu [mark-whole-buffer]
+    '(menu-item "Select All" mark-whole-buffer
+                :help "Mark the whole buffer for a subsequent cut/copy"))
+  menu)
+
+(defun context-menu-ffap (menu)
+  "File at point menu."
+  (save-excursion
+    (mouse-set-point last-input-event)
+    (when (ffap-guess-file-name-at-point)
+      (define-key menu [ffap-separator] menu-bar-separator)
+      (define-key menu [ffap-at-mouse]
+        '(menu-item "Find File or URL" ffap-at-mouse
+                    :help "Find file or URL guessed from text around mouse 
click"))))
+  menu)
+
+(defvar context-menu-entry
+  `(menu-item ,(purecopy "Context Menu") ignore
+              :filter (lambda (_) (context-menu-map))))
+
+(defvar context-menu-mode-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map [mouse-3] nil)
+    (define-key map [down-mouse-3] context-menu-entry)
+    (define-key map [menu] #'context-menu-open)
+    (if (featurep 'w32)
+        (define-key map [apps] #'context-menu-open))
+    (when (featurep 'ns)
+      (define-key map [C-mouse-1] nil)
+      (define-key map [C-down-mouse-1] context-menu-entry))
+    map)
+  "Context Menu mode map.")
+
+(define-minor-mode context-menu-mode
+  "Toggle Context Menu mode.
+
+When Context Menu mode is enabled, clicking the mouse button down-mouse-3
+activates the menu whose contents depends on its surrounding context."
+  :global t :group 'mouse)
+
+(defun context-menu-open ()
+  "Start key navigation of the context menu.
+This is the keyboard interface to \\[context-menu-map]."
+  (interactive)
+  (let ((inhibit-mouse-event-check t))
+    (popup-menu (context-menu-map) (point))))
+
+(global-set-key [S-f10] 'context-menu-open)
+
+
 ;; Commands that operate on windows.
 
 (defun mouse-minibuffer-check (event)
diff --git a/lisp/net/ange-ftp.el b/lisp/net/ange-ftp.el
index e302aa8..c51766d 100644
--- a/lisp/net/ange-ftp.el
+++ b/lisp/net/ange-ftp.el
@@ -4704,8 +4704,7 @@ NEWNAME should be the name to give the new compressed or 
uncompressed file.")
       ;; Can't use ange-ftp-dired-host-type here because the current
       ;; buffer is *dired-check-process output*
       (condition-case oops
-         (cond ((equal (or (bound-and-true-p dired-chmod-program) "chmod")
-                       program)
+         (cond ((equal "chmod" program)
                 (ange-ftp-call-chmod arguments))
                ;; ((equal "chgrp" program))
                ;; ((equal dired-chown-program program))
diff --git a/lisp/net/browse-url.el b/lisp/net/browse-url.el
index f739cd7..73b8c43 100644
--- a/lisp/net/browse-url.el
+++ b/lisp/net/browse-url.el
@@ -1603,7 +1603,7 @@ used instead of `browse-url-new-window-flag'."
 
 ;; --- mailto ---
 
-(autoload 'rfc2368-parse-mailto-url "rfc2368")
+(autoload 'rfc6068-parse-mailto-url "rfc2368")
 
 ;;;###autoload
 (defun browse-url-mail (url &optional new-window)
@@ -1622,7 +1622,7 @@ When called non-interactively, optional second argument 
NEW-WINDOW is
 used instead of `browse-url-new-window-flag'."
   (interactive (browse-url-interactive-arg "Mailto URL: "))
   (save-excursion
-    (let* ((alist (rfc2368-parse-mailto-url url))
+    (let* ((alist (rfc6068-parse-mailto-url url))
           (to (assoc "To" alist))
           (subject (assoc "Subject" alist))
           (body (assoc "Body" alist))
@@ -1780,6 +1780,7 @@ clickable and will use `browse-url' to open the URLs in 
question."
                                          category browse-url
                                          browse-url-data ,(match-string 
0)))))))
 
+;;;###autoload
 (defun browse-url-button-open (&optional external mouse-event)
   "Follow the link under point using `browse-url'.
 If EXTERNAL (the prefix if used interactively), open with the
diff --git a/lisp/net/dictionary.el b/lisp/net/dictionary.el
index f33cbaf..0f42af0 100644
--- a/lisp/net/dictionary.el
+++ b/lisp/net/dictionary.el
@@ -86,7 +86,7 @@ You can specify here:
 (defcustom dictionary-port
   2628
   "The port of the dictionary server.
-This port is propably always 2628 so there should be no need to modify it."
+This port is probably always 2628 so there should be no need to modify it."
   :group 'dictionary
   :set #'dictionary-set-server-var
   :type 'number
diff --git a/lisp/net/eudc.el b/lisp/net/eudc.el
index 6459c52..517913f 100644
--- a/lisp/net/eudc.el
+++ b/lisp/net/eudc.el
@@ -664,7 +664,7 @@ If ERROR is non-nil, report an error if there is none."
   (let ((result (eudc-query (list (cons 'name name)) '(email)))
        email)
     (if (null (cdr result))
-       (setq email (cl-cdaar result))
+        (setq email (cdaar result))
       (error "Multiple match--use the query form"))
     (if error
        (if email
@@ -682,7 +682,7 @@ If ERROR is non-nil, report an error if there is none."
   (let ((result (eudc-query (list (cons 'name name)) '(phone)))
        phone)
     (if (null (cdr result))
-       (setq phone (cl-cdaar result))
+        (setq phone (cdaar result))
       (error "Multiple match--use the query form"))
     (if error
        (if phone
diff --git a/lisp/net/eww.el b/lisp/net/eww.el
index 2a81d2e..90301e9 100644
--- a/lisp/net/eww.el
+++ b/lisp/net/eww.el
@@ -1021,6 +1021,35 @@ the like."
         ["Toggle Paragraph Direction" eww-toggle-paragraph-direction]))
     map))
 
+(defun eww-context-menu (menu)
+  (define-key menu [eww-separator] menu-bar-separator)
+  (let ((easy-menu (make-sparse-keymap "Eww")))
+    (easy-menu-define nil easy-menu nil
+      '("Eww"
+        ["Back to previous page" eww-back-url
+        :visible (not (zerop (length eww-history)))]
+       ["Forward to next page" eww-forward-url
+        :visible (not (zerop eww-history-position))]
+       ["Reload" eww-reload t]))
+    (dolist (item (reverse (lookup-key easy-menu [menu-bar eww])))
+      (when (consp item)
+        (define-key menu (vector (car item)) (cdr item)))))
+
+  (when (or (mouse-posn-property (event-start last-input-event) 'shr-url)
+            (mouse-posn-property (event-start last-input-event) 'image-url))
+    (define-key menu [shr-mouse-browse-url-new-window]
+      `(menu-item "Follow URL in new window" ,(if browse-url-new-window-flag
+                                                  'shr-mouse-browse-url
+                                                
'shr-mouse-browse-url-new-window)
+                  :help "Browse the URL under the mouse cursor in a new 
window"))
+    (define-key menu [shr-mouse-browse-url]
+      `(menu-item "Follow URL" ,(if browse-url-new-window-flag
+                                    'shr-mouse-browse-url-new-window
+                                  'shr-mouse-browse-url)
+                  :help "Browse the URL under the mouse cursor")))
+
+  menu)
+
 (defvar eww-tool-bar-map
   (let ((map (make-sparse-keymap)))
     (dolist (tool-bar-item
@@ -1044,6 +1073,7 @@ the like."
   (setq-local eww-data (list :title ""))
   (setq-local browse-url-browser-function #'eww-browse-url)
   (add-hook 'after-change-functions #'eww-process-text-input nil t)
+  (add-hook 'context-menu-functions 'eww-context-menu 5 t)
   (setq-local eww-history nil)
   (setq-local eww-history-position 0)
   (when (boundp 'tool-bar-map)
diff --git a/lisp/net/goto-addr.el b/lisp/net/goto-addr.el
index 8992ef7..2c43d0f 100644
--- a/lisp/net/goto-addr.el
+++ b/lisp/net/goto-addr.el
@@ -124,6 +124,14 @@ will have no effect.")
     m)
   "Keymap to hold goto-addr's mouse key defs under highlighted URLs.")
 
+(defun goto-address-context-menu (menu)
+  (when (mouse-posn-property (event-start last-input-event) 'goto-address)
+    (define-key menu [goto-address-separator] menu-bar-separator)
+    (define-key menu [goto-address-at-mouse]
+      '(menu-item "Follow Link" goto-address-at-mouse
+                  :help "Follow a link where you click")))
+  menu)
+
 (defcustom goto-address-url-face 'link
   "Face to use for URLs."
   :type 'face)
@@ -245,6 +253,11 @@ address.  If no e-mail address found, return nil."
               (goto-char (match-beginning 0))))
       (match-string-no-properties 0)))
 
+(defun goto-address-at-mouse (click)
+  "Send to the e-mail address or load the URL at mouse click."
+  (interactive "e")
+  (goto-address-at-point click))
+
 ;;;###autoload
 (defun goto-address ()
   "Sets up goto-address functionality in the current buffer.
@@ -264,12 +277,16 @@ Also fontifies the buffer appropriately (see 
`goto-address-fontify-p' and
 (define-minor-mode goto-address-mode
   "Minor mode to buttonize URLs and e-mail addresses in the current buffer."
   :lighter ""
-  (if goto-address-mode
-      (jit-lock-register #'goto-address-fontify-region)
+  (cond
+   (goto-address-mode
+    (jit-lock-register #'goto-address-fontify-region)
+    (add-hook 'context-menu-functions 'goto-address-context-menu 10 t))
+   (t
     (jit-lock-unregister #'goto-address-fontify-region)
     (save-restriction
       (widen)
-      (goto-address-unfontify (point-min) (point-max)))))
+      (goto-address-unfontify (point-min) (point-max)))
+    (remove-hook 'context-menu-functions 'goto-address-context-menu t))))
 
 (defun goto-addr-mode--turn-on ()
   (when (not goto-address-mode)
diff --git a/lisp/net/rcirc.el b/lisp/net/rcirc.el
index e7aec50..9d242c4 100644
--- a/lisp/net/rcirc.el
+++ b/lisp/net/rcirc.el
@@ -2408,7 +2408,7 @@ prefix with another element in PAIRS."
            (when (and (listp x) (listp (cadr x)))
              (setcdr x (if (> (length (cdr x)) 1)
                            (rcirc-make-trees (cdr x))
-                         (setcdr x (list (cl-cdadr x)))))))
+                          (setcdr x (list (cdadr x)))))))
          alist)))
 
 ;;; /commands these are called with 3 args: PROCESS, TARGET, which is
@@ -3234,7 +3234,7 @@ RFC1459."
     (with-current-buffer buffer
       (let ((setter (nth 2 args))
            (time (current-time-string
-                  (string-to-number (cl-cadddr args)))))
+                   (string-to-number (cadddr args)))))
        (rcirc-print process sender "TOPIC" (cadr args)
                     (format "%s (%s on %s)" rcirc-topic setter time))))))
 
@@ -3344,7 +3344,7 @@ Passwords are stored in `rcirc-authinfo' (which see)."
            (server (car i))
            (nick (nth 2 i))
            (method (cadr i))
-           (args (cl-cdddr i)))
+            (args (cdddr i)))
        (when (and (string-match server rcirc-server))
           (if (and (memq method '(nickserv chanserv bitlbee))
                    (string-match nick rcirc-nick))
diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el
index c16e232..70dbfdb 100644
--- a/lisp/net/tramp-adb.el
+++ b/lisp/net/tramp-adb.el
@@ -925,9 +925,7 @@ implementation will be used."
              (coding (plist-get args :coding))
              (noquery (plist-get args :noquery))
              (connection-type
-              (if (plist-member args :connection-type)
-                  (plist-get args :connection-type)
-                tramp-process-connection-type))
+              (or (plist-get args :connection-type) process-connection-type))
              (filter (plist-get args :filter))
              (sentinel (plist-get args :sentinel))
              (stderr (plist-get args :stderr)))
@@ -943,7 +941,9 @@ implementation will be used."
                           (memq (car coding) coding-system-list)
                           (memq (cdr coding) coding-system-list)))
            (signal 'wrong-type-argument (list #'symbolp coding)))
-         (unless (memq connection-type '(nil pipe t pty))
+         (when (eq connection-type t)
+           (setq connection-type 'pty))
+         (unless (memq connection-type '(nil pipe pty))
            (signal 'wrong-type-argument (list #'symbolp connection-type)))
          (unless (or (null filter) (functionp filter))
            (signal 'wrong-type-argument (list #'functionp filter)))
diff --git a/lisp/net/tramp-compat.el b/lisp/net/tramp-compat.el
index b713d5e..125f825 100644
--- a/lisp/net/tramp-compat.el
+++ b/lisp/net/tramp-compat.el
@@ -295,6 +295,15 @@ A nil value for either argument stands for the current 
time."
     (lambda (reporter &optional value _suffix)
       (progress-reporter-update reporter value))))
 
+;; `ignore-error' is new in Emacs Emacs 27.1.
+(defmacro tramp-compat-ignore-error (condition &rest body)
+  "Execute BODY; if the error CONDITION occurs, return nil.
+Otherwise, return result of last form in BODY.
+
+CONDITION can also be a list of error conditions."
+  (declare (debug t) (indent 1))
+  `(condition-case nil (progn ,@body) (,condition nil)))
+
 ;; `file-modes', `set-file-modes' and `set-file-times' got argument
 ;; FLAG in Emacs 28.1.
 (defalias 'tramp-compat-file-modes
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index f00434c..a2bf0af 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -1857,41 +1857,53 @@ ID-FORMAT valid values are `string' and `integer'."
   (dirname newname &optional keep-date parents copy-contents)
   "Like `copy-directory' for Tramp files."
   (let ((t1 (tramp-tramp-file-p dirname))
-       (t2 (tramp-tramp-file-p newname)))
+       (t2 (tramp-tramp-file-p newname))
+       target)
     (with-parsed-tramp-file-name (if t1 dirname newname) nil
       (unless (file-exists-p dirname)
        (tramp-compat-file-missing v dirname))
-      (if (and (not copy-contents)
-              (tramp-get-method-parameter v 'tramp-copy-recursive)
-              ;; When DIRNAME and NEWNAME are remote, they must have
-              ;; the same method.
-              (or (null t1) (null t2)
-                  (string-equal
-                   (tramp-file-name-method (tramp-dissect-file-name dirname))
-                   (tramp-file-name-method
-                    (tramp-dissect-file-name newname)))))
-         ;; scp or rsync DTRT.
-         (progn
-           (when (and (file-directory-p newname)
-                      (not (directory-name-p newname)))
-             (tramp-error v 'file-already-exists newname))
-           (setq dirname (directory-file-name (expand-file-name dirname))
-                 newname (directory-file-name (expand-file-name newname)))
-           (when (and (file-directory-p newname)
-                      (not (string-equal (file-name-nondirectory dirname)
-                                         (file-name-nondirectory newname))))
-             (setq newname
-                   (expand-file-name
-                    (file-name-nondirectory dirname) newname)))
-           (unless (file-directory-p (file-name-directory newname))
+
+      ;; `copy-directory-create-symlink' exists since Emacs 28.1.
+      (if (and (bound-and-true-p copy-directory-create-symlink)
+              (setq target (file-symlink-p dirname))
+              (tramp-equal-remote dirname newname))
+         (make-symbolic-link
+          target
+          (if (directory-name-p newname)
+              (concat newname (file-name-nondirectory dirname)) newname)
+          t)
+
+       (if (and (not copy-contents)
+                (tramp-get-method-parameter v 'tramp-copy-recursive)
+                ;; When DIRNAME and NEWNAME are remote, they must
+                ;; have the same method.
+                (or (null t1) (null t2)
+                    (string-equal
+                     (tramp-file-name-method (tramp-dissect-file-name dirname))
+                     (tramp-file-name-method
+                      (tramp-dissect-file-name newname)))))
+           ;; scp or rsync DTRT.
+           (progn
+             (when (and (file-directory-p newname)
+                        (not (directory-name-p newname)))
+               (tramp-error v 'file-already-exists newname))
+             (setq dirname (directory-file-name (expand-file-name dirname))
+                   newname (directory-file-name (expand-file-name newname)))
+             (when (and (file-directory-p newname)
+                        (not (string-equal (file-name-nondirectory dirname)
+                                           (file-name-nondirectory newname))))
+               (setq newname
+                     (expand-file-name
+                      (file-name-nondirectory dirname) newname)))
+             (unless (file-directory-p (file-name-directory newname))
                (make-directory (file-name-directory newname) parents))
-           (tramp-do-copy-or-rename-file-out-of-band
-            'copy dirname newname 'ok-if-already-exists keep-date))
+             (tramp-do-copy-or-rename-file-out-of-band
+              'copy dirname newname 'ok-if-already-exists keep-date))
 
-       ;; We must do it file-wise.
-       (tramp-run-real-handler
-        #'copy-directory
-        (list dirname newname keep-date parents copy-contents)))
+         ;; We must do it file-wise.
+         (tramp-run-real-handler
+          #'copy-directory
+          (list dirname newname keep-date parents copy-contents))))
 
       ;; When newname did exist, we have wrong cached values.
       (when t2
@@ -2753,9 +2765,7 @@ implementation will be used."
              (coding (plist-get args :coding))
              (noquery (plist-get args :noquery))
              (connection-type
-              (if (plist-member args :connection-type)
-                  (plist-get args :connection-type)
-                tramp-process-connection-type))
+              (or (plist-get args :connection-type) process-connection-type))
              (filter (plist-get args :filter))
              (sentinel (plist-get args :sentinel))
              (stderr (plist-get args :stderr)))
@@ -2771,7 +2781,9 @@ implementation will be used."
                           (memq (car coding) coding-system-list)
                           (memq (cdr coding) coding-system-list)))
            (signal 'wrong-type-argument (list #'symbolp coding)))
-         (unless (memq connection-type '(nil pipe t pty))
+         (when (eq connection-type t)
+           (setq connection-type 'pty))
+         (unless (memq connection-type '(nil pipe pty))
            (signal 'wrong-type-argument (list #'symbolp connection-type)))
          (unless (or (null filter) (functionp filter))
            (signal 'wrong-type-argument (list #'functionp filter)))
diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el
index 6937244..5cfe874 100644
--- a/lisp/net/tramp-smb.el
+++ b/lisp/net/tramp-smb.el
@@ -414,157 +414,176 @@ arguments to pass to the OPERATION."
 (defun tramp-smb-handle-copy-directory
   (dirname newname &optional keep-date parents copy-contents)
   "Like `copy-directory' for Tramp files."
-  (if copy-contents
-      ;; We must do it file-wise.
-      (tramp-run-real-handler
-       #'copy-directory (list dirname newname keep-date parents copy-contents))
-
-    (setq dirname (expand-file-name dirname)
-         newname (expand-file-name newname))
-    (let ((t1 (tramp-tramp-file-p dirname))
-         (t2 (tramp-tramp-file-p newname)))
-      (with-parsed-tramp-file-name (if t1 dirname newname) nil
-       (with-tramp-progress-reporter
-           v 0 (format "Copying %s to %s" dirname newname)
-         (unless (file-exists-p dirname)
-           (tramp-compat-file-missing v dirname))
-         (when (and (file-directory-p newname)
-                    (not (directory-name-p newname)))
-           (tramp-error v 'file-already-exists newname))
-         (cond
-          ;; We must use a local temporary directory.
-          ((and t1 t2)
-           (let ((tmpdir (tramp-compat-make-temp-name)))
-             (unwind-protect
-                 (progn
-                   (make-directory tmpdir)
-                   (copy-directory
-                    dirname (file-name-as-directory tmpdir) keep-date 'parents)
-                   (copy-directory
-                    (expand-file-name (file-name-nondirectory dirname) tmpdir)
-                    newname keep-date parents))
-               (delete-directory tmpdir 'recursive))))
-
-          ;; We can copy recursively.
-          ;; TODO: Does not work reliably.
-          (nil ;(and (or t1 t2) (tramp-smb-get-cifs-capabilities v))
+  (let ((t1 (tramp-tramp-file-p dirname))
+       (t2 (tramp-tramp-file-p newname))
+       target)
+    (with-parsed-tramp-file-name (if t1 dirname newname) nil
+      (unless (file-exists-p dirname)
+       (tramp-compat-file-missing v dirname))
+
+      ;; `copy-directory-create-symlink' exists since Emacs 28.1.
+      (if (and (bound-and-true-p copy-directory-create-symlink)
+              (setq target (file-symlink-p dirname))
+              (tramp-equal-remote dirname newname))
+         (make-symbolic-link
+          target
+          (if (directory-name-p newname)
+              (concat newname (file-name-nondirectory dirname)) newname)
+          t)
+
+       (if copy-contents
+           ;; We must do it file-wise.
+           (tramp-run-real-handler
+            #'copy-directory
+            (list dirname newname keep-date parents copy-contents))
+
+         (setq dirname (expand-file-name dirname)
+               newname (expand-file-name newname))
+         (with-tramp-progress-reporter
+             v 0 (format "Copying %s to %s" dirname newname)
+           (unless (file-exists-p dirname)
+             (tramp-compat-file-missing v dirname))
            (when (and (file-directory-p newname)
-                      (not (string-equal (file-name-nondirectory dirname)
-                                         (file-name-nondirectory newname))))
-             (setq newname
-                   (expand-file-name
-                    (file-name-nondirectory dirname) newname))
-             (if t2 (setq v (tramp-dissect-file-name newname))))
-           (if (not (file-directory-p newname))
-               (make-directory newname parents))
-
-           (let* ((share (tramp-smb-get-share v))
-                  (localname (file-name-as-directory
-                              (tramp-compat-string-replace
-                               "\\" "/" (tramp-smb-get-localname v))))
-                  (tmpdir    (tramp-compat-make-temp-name))
-                  (args      (list (concat "//" host "/" share) "-E"))
-                  (options   tramp-smb-options))
-
-             (if (not (zerop (length user)))
-                 (setq args (append args (list "-U" user)))
-               (setq args (append args (list "-N"))))
-
-             (when domain (setq args (append args (list "-W" domain))))
-             (when port   (setq args (append args (list "-p" port))))
-             (when tramp-smb-conf
-               (setq args (append args (list "-s" tramp-smb-conf))))
-             (while options
+                      (not (directory-name-p newname)))
+             (tramp-error v 'file-already-exists newname))
+           (cond
+            ;; We must use a local temporary directory.
+            ((and t1 t2)
+             (let ((tmpdir (tramp-compat-make-temp-name)))
+               (unwind-protect
+                   (progn
+                     (make-directory tmpdir)
+                     (copy-directory
+                      dirname (file-name-as-directory tmpdir)
+                      keep-date 'parents)
+                     (copy-directory
+                      (expand-file-name (file-name-nondirectory dirname) 
tmpdir)
+                      newname keep-date parents))
+                 (delete-directory tmpdir 'recursive))))
+
+            ;; We can copy recursively.
+            ;; TODO: Does not work reliably.
+            (nil ;(and (or t1 t2) (tramp-smb-get-cifs-capabilities v))
+             (when (and (file-directory-p newname)
+                        (not (string-equal (file-name-nondirectory dirname)
+                                           (file-name-nondirectory newname))))
+               (setq newname
+                     (expand-file-name
+                      (file-name-nondirectory dirname) newname))
+               (if t2 (setq v (tramp-dissect-file-name newname))))
+             (if (not (file-directory-p newname))
+                 (make-directory newname parents))
+
+             (let* ((share (tramp-smb-get-share v))
+                    (localname (file-name-as-directory
+                                (tramp-compat-string-replace
+                                 "\\" "/" (tramp-smb-get-localname v))))
+                    (tmpdir    (tramp-compat-make-temp-name))
+                    (args      (list (concat "//" host "/" share) "-E"))
+                    (options   tramp-smb-options))
+
+               (if (not (zerop (length user)))
+                   (setq args (append args (list "-U" user)))
+                 (setq args (append args (list "-N"))))
+
+               (when domain (setq args (append args (list "-W" domain))))
+               (when port   (setq args (append args (list "-p" port))))
+               (when tramp-smb-conf
+                 (setq args (append args (list "-s" tramp-smb-conf))))
+               (while options
+                 (setq args
+                       (append args `("--option" ,(format "%s" (car options))))
+                       options (cdr options)))
                (setq args
-                     (append args `("--option" ,(format "%s" (car options))))
-                     options (cdr options)))
-             (setq args
-                   (if t1
-                       ;; Source is remote.
-                       (append args
+                     (if t1
+                         ;; Source is remote.
+                         (append args
+                                 (list "-D" (tramp-unquote-shell-quote-argument
+                                             localname)
+                                       "-c" (tramp-unquote-shell-quote-argument
+                                             "tar qc - *")
+                                       "|" "tar" "xfC" "-"
+                                       (tramp-unquote-shell-quote-argument
+                                        tmpdir)))
+                       ;; Target is remote.
+                       (append (list
+                                "tar" "cfC" "-"
+                                (tramp-unquote-shell-quote-argument dirname)
+                                "." "|")
+                               args
                                (list "-D" (tramp-unquote-shell-quote-argument
                                            localname)
                                      "-c" (tramp-unquote-shell-quote-argument
-                                           "tar qc - *")
-                                     "|" "tar" "xfC" "-"
-                                     (tramp-unquote-shell-quote-argument
-                                      tmpdir)))
-                     ;; Target is remote.
-                     (append (list "tar" "cfC" "-"
-                                   (tramp-unquote-shell-quote-argument dirname)
-                                   "." "|")
-                             args
-                             (list "-D" (tramp-unquote-shell-quote-argument
-                                         localname)
-                                   "-c" (tramp-unquote-shell-quote-argument
-                                         "tar qx -")))))
-
-             (unwind-protect
-                 (with-temp-buffer
-                   ;; Set the transfer process properties.
-                   (tramp-set-connection-property
-                    v "process-name" (buffer-name (current-buffer)))
-                   (tramp-set-connection-property
-                    v "process-buffer" (current-buffer))
-
-                   (when t1
-                     ;; The smbclient tar command creates always
-                     ;; complete paths.  We must emulate the
-                     ;; directory structure, and symlink to the real
-                     ;; target.
-                     (make-directory
-                      (expand-file-name
-                       ".." (concat tmpdir localname))
-                      'parents)
-                     (make-symbolic-link
-                      newname (directory-file-name (concat tmpdir localname))))
-
-                   ;; Use an asynchronous processes.  By this,
-                   ;; password can be handled.
-                   (let* ((default-directory tmpdir)
-                          (p (apply
-                              #'start-process
-                              (tramp-get-connection-name v)
-                              (tramp-get-connection-buffer v)
-                              tramp-smb-program args)))
-
-                     (tramp-message
-                      v 6 "%s" (string-join (process-command p) " "))
-                     (process-put p 'vector v)
-                     (process-put p 'adjust-window-size-function #'ignore)
-                     (set-process-query-on-exit-flag p nil)
-                     (tramp-process-actions p v nil tramp-smb-actions-with-tar)
-
-                     (while (process-live-p p)
-                       (sleep-for 0.1))
-                     (tramp-message v 6 "\n%s" (buffer-string))))
-
-               ;; Reset the transfer process properties.
-               (tramp-flush-connection-property v "process-name")
-               (tramp-flush-connection-property v "process-buffer")
-               (when t1 (delete-directory tmpdir 'recursive))))
-
-           ;; Handle KEEP-DATE argument.
-           (when keep-date
-             (tramp-compat-set-file-times
-              newname
-              (tramp-compat-file-attribute-modification-time
-               (file-attributes dirname))
-              (unless ok-if-already-exists 'nofollow)))
-
-           ;; Set the mode.
-           (unless keep-date
-             (set-file-modes newname (tramp-default-file-modes dirname)))
-
-           ;; When newname did exist, we have wrong cached values.
-           (when t2
-             (with-parsed-tramp-file-name newname nil
-               (tramp-flush-file-properties v localname))))
-
-          ;; We must do it file-wise.
-          (t
-           (tramp-run-real-handler
-            #'copy-directory (list dirname newname keep-date parents)))))))))
+                                           "tar qx -")))))
+
+               (unwind-protect
+                   (with-temp-buffer
+                     ;; Set the transfer process properties.
+                     (tramp-set-connection-property
+                      v "process-name" (buffer-name (current-buffer)))
+                     (tramp-set-connection-property
+                      v "process-buffer" (current-buffer))
+
+                     (when t1
+                       ;; The smbclient tar command creates always
+                       ;; complete paths.  We must emulate the
+                       ;; directory structure, and symlink to the
+                       ;; real target.
+                       (make-directory
+                        (expand-file-name
+                         ".." (concat tmpdir localname))
+                        'parents)
+                       (make-symbolic-link
+                        newname
+                        (directory-file-name (concat tmpdir localname))))
+
+                     ;; Use an asynchronous processes.  By this,
+                     ;; password can be handled.
+                     (let* ((default-directory tmpdir)
+                            (p (apply
+                                #'start-process
+                                (tramp-get-connection-name v)
+                                (tramp-get-connection-buffer v)
+                                tramp-smb-program args)))
+
+                       (tramp-message
+                        v 6 "%s" (string-join (process-command p) " "))
+                       (process-put p 'vector v)
+                       (process-put p 'adjust-window-size-function #'ignore)
+                       (set-process-query-on-exit-flag p nil)
+                       (tramp-process-actions
+                        p v nil tramp-smb-actions-with-tar)
+
+                       (while (process-live-p p)
+                         (sleep-for 0.1))
+                       (tramp-message v 6 "\n%s" (buffer-string))))
+
+                 ;; Reset the transfer process properties.
+                 (tramp-flush-connection-property v "process-name")
+                 (tramp-flush-connection-property v "process-buffer")
+                 (when t1 (delete-directory tmpdir 'recursive))))
+
+             ;; Handle KEEP-DATE argument.
+             (when keep-date
+               (tramp-compat-set-file-times
+                newname
+                (tramp-compat-file-attribute-modification-time
+                 (file-attributes dirname))
+                (unless ok-if-already-exists 'nofollow)))
+
+             ;; Set the mode.
+             (unless keep-date
+               (set-file-modes newname (tramp-default-file-modes dirname)))
+
+             ;; When newname did exist, we have wrong cached values.
+             (when t2
+               (with-parsed-tramp-file-name newname nil
+                 (tramp-flush-file-properties v localname))))
+
+            ;; We must do it file-wise.
+            (t
+             (tramp-run-real-handler
+              #'copy-directory (list dirname newname keep-date 
parents))))))))))
 
 (defun tramp-smb-handle-copy-file
   (filename newname &optional ok-if-already-exists keep-date
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index 83df05c..9ed9da9 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -714,6 +714,13 @@ The regexp should match at end of buffer."
   :version "28.1"
   :type 'regexp)
 
+(defcustom tramp-security-key-timeout-regexp
+  "^\r*sign_and_send_pubkey: signing failed for .*[\r\n]*"
+  "Regular expression matching security key timeout message.
+The regexp should match at end of buffer."
+  :version "28.1"
+  :type 'regexp)
+
 (defcustom tramp-operation-not-permitted-regexp
   (concat "\\(" "preserving times.*" "\\|" "set mode" "\\)" ":\\s-*"
          (regexp-opt '("Operation not permitted") t))
@@ -4094,9 +4101,7 @@ substitution.  SPEC-LIST is a list of char/value pairs 
used for
            (coding (plist-get args :coding))
            (noquery (plist-get args :noquery))
            (connection-type
-            (if (plist-member args :connection-type)
-                (plist-get args :connection-type)
-              tramp-process-connection-type))
+            (or (plist-get args :connection-type) process-connection-type))
            (filter (plist-get args :filter))
            (sentinel (plist-get args :sentinel))
            (stderr (plist-get args :stderr)))
@@ -4112,7 +4117,9 @@ substitution.  SPEC-LIST is a list of char/value pairs 
used for
                         (memq (car coding) coding-system-list)
                         (memq (cdr coding) coding-system-list)))
          (signal 'wrong-type-argument (list #'symbolp coding)))
-       (unless (memq connection-type '(nil pipe t pty))
+       (when (eq connection-type t)
+         (setq connection-type 'pty))
+       (unless (memq connection-type '(nil pipe pty))
          (signal 'wrong-type-argument (list #'symbolp connection-type)))
        (unless (or (null filter) (functionp filter))
          (signal 'wrong-type-argument (list #'functionp filter)))
@@ -4692,16 +4699,23 @@ The terminal type can be configured with 
`tramp-terminal-type'."
   "Show the user a message for confirmation.
 Wait, until the connection buffer changes."
   (with-current-buffer (process-buffer proc)
-    (let ((stimers (with-timeout-suspend)))
+    (let ((stimers (with-timeout-suspend))
+         (cursor-in-echo-area t)
+         set-message-function clear-message-function)
+      ;; Silence byte compiler.
+      (ignore set-message-function clear-message-function)
       (tramp-message vec 6 "\n%s" (buffer-string))
-      (goto-char (point-min))
       (tramp-check-for-regexp proc tramp-process-action-regexp)
       (with-temp-message (replace-regexp-in-string "[\r\n]" "" (match-string 
0))
-       (redisplay 'force)
        ;; Hide message in buffer.
        (narrow-to-region (point-max) (point-max))
        ;; Wait for new output.
-       (tramp-wait-for-regexp proc 30 tramp-security-key-confirmed-regexp))
+       (while (not (tramp-compat-ignore-error 'file-error
+                     (tramp-wait-for-regexp
+                      proc 0.1 tramp-security-key-confirmed-regexp)))
+         (when (tramp-check-for-regexp proc tramp-security-key-timeout-regexp)
+           (throw 'tramp-action 'timeout))
+         (redisplay 'force)))
       ;; Reenable the timers.
       (with-timeout-unsuspend stimers)))
   t)
@@ -5405,7 +5419,8 @@ this file, if that variable is non-nil."
     ;; Create directory.
     (unless (or (null tramp-auto-save-directory)
                (file-exists-p tramp-auto-save-directory))
-      (make-directory tramp-auto-save-directory t))
+      (make-directory tramp-auto-save-directory t)
+      (set-file-modes tramp-auto-save-directory #o0700))
 
     (let ((system-type
           (if (and (stringp tramp-auto-save-directory)
@@ -5576,6 +5591,9 @@ verbosity of 6."
               (string-prefix-p comm process-name)
               (throw 'result t)))))))
 
+;; When calling "emacs -Q", `auth-source-search' won't be called.  If
+;; you want to debug exactly this case, call "emacs -Q --eval '(setq
+;; tramp-cache-read-persistent-data t)'" instead.
 (defun tramp-read-passwd (proc &optional prompt)
   "Read a password from user (compat function).
 Consults the auth-source package.
diff --git a/lisp/newcomment.el b/lisp/newcomment.el
index 57a52ef..b458f03 100644
--- a/lisp/newcomment.el
+++ b/lisp/newcomment.el
@@ -932,7 +932,8 @@ This function is the default value of 
`uncomment-region-function'."
   (setq end (copy-marker end))
   (let* ((numarg (prefix-numeric-value arg))
         (ccs comment-continue)
-        (srei (comment-padright ccs 're))
+        (srei (or (comment-padright ccs 're)
+                  (and (stringp comment-continue) comment-continue)))
         (csre (comment-padright comment-start 're))
         (sre (and srei (concat "^\\s-*?\\(" srei "\\)")))
         spt)
diff --git a/lisp/mail/rfc2368.el b/lisp/obsolete/rfc2368.el
similarity index 99%
rename from lisp/mail/rfc2368.el
rename to lisp/obsolete/rfc2368.el
index b96f15d..8a842b0 100644
--- a/lisp/mail/rfc2368.el
+++ b/lisp/obsolete/rfc2368.el
@@ -4,6 +4,7 @@
 
 ;; Author: Sen Nagata <sen@eccosys.com>
 ;; Keywords: mail
+;; Obsolete-since: 28.1
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/obsolete/terminal.el b/lisp/obsolete/terminal.el
index 0167a00..fa89b58 100644
--- a/lisp/obsolete/terminal.el
+++ b/lisp/obsolete/terminal.el
@@ -112,10 +112,9 @@ performance."
     nil
   (let ((map (make-sparse-keymap)))
     (define-key map [t] #'undefined)
-    (let ((s "0"))
-      (while (<= (aref s 0) ?9)
-       (define-key map s #'digit-argument)
-       (aset s 0 (1+ (aref s 0)))))
+    (dotimes (i 10)
+      (let ((s (make-string 1 (+ ?0 i))))
+       (define-key map s #'digit-argument)))
     (define-key map "b" #'switch-to-buffer)
     (define-key map "o" #'other-window)
     (define-key map "e" #'te-set-escape-char)
diff --git a/lisp/play/5x5.el b/lisp/play/5x5.el
index 3630c19..64d43c3 100644
--- a/lisp/play/5x5.el
+++ b/lisp/play/5x5.el
@@ -315,7 +315,7 @@ Quit current game           \\[5x5-quit-game]"
          (save-excursion
            (goto-char grid-org)
            (beginning-of-line (+ 1 (/ 5x5-y-scale 2)))
-           (let ((solution-grid (cl-cdadr 5x5-solver-output)))
+            (let ((solution-grid (cdadr 5x5-solver-output)))
              (dotimes (y 5x5-grid-size)
                (save-excursion
                  (forward-char  (+ 1 (/ (1+ 5x5-x-scale) 2)))
@@ -746,9 +746,9 @@ Solutions are sorted from least to greatest Hamming weight."
                    ;; The Hamming Weight is computed by matrix reduction
                    ;; with an ad-hoc operator.
                    (math-reduce-vec
-                    ;; (cl-cadadr '(vec (mod x 2))) => x
-                    (lambda (r x) (+ (if (integerp r) r (cl-cadadr r))
-                                     (cl-cadadr x)))
+                     ;; (cadadr '(vec (mod x 2))) => x
+                     (lambda (r x) (+ (if (integerp r) r (cadadr r))
+                                      (cadadr x)))
                     solution); car
                    (5x5-vec-to-grid
                     (calcFunc-arrange solution 5x5-grid-size));cdr
diff --git a/lisp/play/decipher.el b/lisp/play/decipher.el
index 47ed6e2..a80cb21 100644
--- a/lisp/play/decipher.el
+++ b/lisp/play/decipher.el
@@ -769,8 +769,8 @@ TOTAL is the total number of letters in the ciphertext."
       (while temp-list
         (insert (caar temp-list)
                 (format "%4d%3d%%  "
-                        (cl-cadar temp-list)
-                        (floor (* 100.0 (cl-cadar temp-list)) total)))
+                        (cadar temp-list)
+                        (floor (* 100.0 (cadar temp-list)) total)))
         (setq temp-list (nthcdr 4 temp-list)))
       (insert ?\n)
       (setq freq-list (cdr freq-list)
diff --git a/lisp/progmodes/bug-reference.el b/lisp/progmodes/bug-reference.el
index 9b9c58e..c0c9d5e 100644
--- a/lisp/progmodes/bug-reference.el
+++ b/lisp/progmodes/bug-reference.el
@@ -153,95 +153,144 @@ The second subexpression should match the bug reference 
(usually a number)."
                     (push (match-string i url) groups))
                   (funcall bug-url-fmt (nreverse groups))))))
 
-(defvar bug-reference-setup-from-vc-alist
-  `(;;
-    ;; GNU projects on savannah.
-    ;;
-    ;; Not all of them use debbugs but that doesn't really matter
-    ;; because the auto-setup is only performed if
-    ;; `bug-reference-url-format' and `bug-reference-bug-regexp'
-    ;; aren't set already.
-    ("git\\.\\(?:sv\\|savannah\\)\\.gnu\\.org:"
-     "\\<\\([Bb]ug ?#?\\)\\([0-9]+\\(?:#[0-9]+\\)?\\)\\>"
-     ,(lambda (_) "https://debbugs.gnu.org/%s";))
-    ;;
-    ;; GitHub projects.
-    ;;
-    ;; Here #17 may refer to either an issue or a pull request but
-    ;; visiting the issue/17 web page will automatically redirect to
-    ;; the pull/17 page if 17 is a PR.  Explicit user/project#17 links
-    ;; to possibly different projects are also supported.
-    ("[/@]github.com[/:]\\([.A-Za-z0-9_/-]+\\)\\.git"
-     "\\([.A-Za-z0-9_/-]+\\)?\\(?:#\\)\\([0-9]+\\)\\>"
-     ,(lambda (groups)
-        (let ((ns-project (nth 1 groups)))
-          (lambda ()
-            (concat "https://github.com/";
-                    (or
-                     ;; Explicit user/proj#18 link.
-                     (match-string 1)
-                     ns-project)
-                    "/issues/"
-                    (match-string 2))))))
-    ;;
-    ;; Codeberg projects.
-    ;;
-    ;; The systematics is exactly as for Github projects.
-    ("[/@]codeberg.org[/:]\\([.A-Za-z0-9_/-]+\\)\\.git"
-     "\\([.A-Za-z0-9_/-]+\\)?\\(?:#\\)\\([0-9]+\\)\\>"
-     ,(lambda (groups)
-        (let ((ns-project (nth 1 groups)))
-          (lambda ()
-            (concat "https://codeberg.org/";
-                    (or
-                     ;; Explicit user/proj#18 link.
-                     (match-string 1)
-                     ns-project)
-                    "/issues/"
-                    (match-string 2))))))
-    ;;
-    ;; GitLab projects.
-    ;;
-    ;; Here #18 is an issue and !17 is a merge request.  Explicit
-    ;; namespace/project#18 or namespace/project!17 references to
-    ;; possibly different projects are also supported.
-    ("[/@]gitlab.com[/:]\\([.A-Za-z0-9_/-]+\\)\\.git"
-     "\\(?1:[.A-Za-z0-9_/-]+\\)?\\(?3:[#!]\\)\\(?2:[0-9]+\\)\\>"
-     ,(lambda (groups)
-        (let ((ns-project (nth 1 groups)))
-          (lambda ()
-            (concat "https://gitlab.com/";
-                    (or (match-string 1)
-                        ns-project)
-                    "/-/"
-                    (if (string= (match-string 3) "#")
-                        "issues/"
-                      "merge_requests/")
-                    (match-string 2))))))
-    ;;
-    ;; Sourcehut projects.
-    ;;
-    ;; #19 is an issue.  Other project's issues can be referenced as
-    ;; #~user/project#19.
-    ;;
-    ;; Caveat: The code assumes that a project on git.sr.ht or
-    ;; hg.sr.ht has a tracker of the same name on todo.sh.ht.  That's
-    ;; a very common setup but all sr.ht services are loosely coupled,
-    ;; so you can have a repo without tracker, or a repo with a
-    ;; tracker using a different name, etc.  So we can only try to
-    ;; make a good guess.
-    ("[/@]\\(?:git\\|hg\\).sr.ht[/:]\\(~[.A-Za-z0-9_/-]+\\)"
-     "\\(~[.A-Za-z0-9_/-]+\\)?\\(?:#\\)\\([0-9]+\\)\\>"
-     ,(lambda (groups)
-        (let ((ns-project (nth 1 groups)))
-          (lambda ()
-            (concat "https://todo.sr.ht/";
-                    (or
-                     ;; Explicit user/proj#18 link.
-                     (match-string 1)
-                     ns-project)
-                    "/"
-                    (match-string 2)))))))
+(defvar bug-reference-gitea-instances '("gitea.com"
+                                        "codeberg.org")
+  "List of Gitea forge instances.
+When the value is changed after bug-reference has already been
+loaded, and performed an auto-setup, evaluate
+`(bug-reference--setup-from-vc-alist t)' for rebuilding the value
+of `bug-reference--setup-from-vc-alist'.")
+
+(defvar bug-reference-gitlab-instances '("gitlab.com"
+                                         "salsa.debian.org"
+                                         "framagit.org")
+  "List of GitLab forge instances.
+When the value is changed after bug-reference has already been
+loaded, and performed an auto-setup, evaluate
+`(bug-reference--setup-from-vc-alist t)' for rebuilding the value
+of `bug-reference--setup-from-vc-alist'.")
+
+(defvar bug-reference-sourcehut-instances '("sr.ht")
+  "List of SourceHut forge instances.
+When the value is changed after bug-reference has already been
+loaded, and performed an auto-setup, evaluate
+`(bug-reference--setup-from-vc-alist t)' for rebuilding the value
+of `bug-reference--setup-from-vc-alist'.")
+
+(defvar bug-reference--setup-from-vc-alist nil
+  "An alist for setting up ‘bug-reference-mode’ based on VC URL.
+This is like `bug-reference-setup-from-vc-alist' but generated
+for the known free software forges from the variables
+`bug-reference-gitea-instances',
+`bug-reference-gitlab-instances', and
+`bug-reference-sourcehut-instances'.")
+
+(defun bug-reference--setup-from-vc-alist (&optional rebuild)
+  (if (and bug-reference--setup-from-vc-alist
+           (null rebuild))
+      bug-reference--setup-from-vc-alist
+    (setq bug-reference--setup-from-vc-alist
+          `(;;
+            ;; GNU projects on savannah.
+            ;;
+            ;; Not all of them use debbugs but that doesn't really
+            ;; matter because the auto-setup is only performed if
+            ;; `bug-reference-url-format' and
+            ;; `bug-reference-bug-regexp' aren't set already.
+            ("git\\.\\(?:sv\\|savannah\\)\\.gnu\\.org:"
+             "\\<\\([Bb]ug ?#?\\)\\([0-9]+\\(?:#[0-9]+\\)?\\)\\>"
+             ,(lambda (_) "https://debbugs.gnu.org/%s";))
+            ;;
+            ;; GitHub projects.
+            ;;
+            ;; Here #17 may refer to either an issue or a pull request
+            ;; but visiting the issue/17 web page will automatically
+            ;; redirect to the pull/17 page if 17 is a PR.  Explicit
+            ;; user/project#17 links to possibly different projects
+            ;; are also supported.
+            ("[/@]github.com[/:]\\([.A-Za-z0-9_/-]+\\)\\.git"
+             "\\([.A-Za-z0-9_/-]+\\)?\\(?:#\\)\\([0-9]+\\)\\>"
+             ,(lambda (groups)
+                (let ((ns-project (nth 1 groups)))
+                  (lambda ()
+                    (concat "https://github.com/";
+                            (or
+                             ;; Explicit user/proj#18 link.
+                             (match-string 1)
+                             ns-project)
+                            "/issues/"
+                            (match-string 2))))))
+            ;;
+            ;; Gitea instances.
+            ;;
+            ;; The systematics is exactly as for Github projects.
+            (,(concat "[/@]"
+                      (regexp-opt bug-reference-gitea-instances t)
+                      "[/:]\\([.A-Za-z0-9_/-]+\\)\\.git")
+             "\\([.A-Za-z0-9_/-]+\\)?\\(?:#\\)\\([0-9]+\\)\\>"
+             ,(lambda (groups)
+                (let ((host (nth 1 groups))
+                      (ns-project (nth 2 groups)))
+                  (lambda ()
+                    (concat "https://"; host "/"
+                            (or
+                             ;; Explicit user/proj#18 link.
+                             (match-string 1)
+                             ns-project)
+                            "/issues/"
+                            (match-string 2))))))
+            ;;
+            ;; GitLab instances.
+            ;;
+            ;; Here #18 is an issue and !17 is a merge request.
+            ;; Explicit namespace/project#18 or namespace/project!17
+            ;; references to possibly different projects are also
+            ;; supported.
+            (,(concat "[/@]"
+                      (regexp-opt bug-reference-gitlab-instances t)
+                      "[/:]\\([.A-Za-z0-9_/-]+\\)\\.git")
+             "\\(?1:[.A-Za-z0-9_/-]+\\)?\\(?3:[#!]\\)\\(?2:[0-9]+\\)\\>"
+             ,(lambda (groups)
+                (let ((host (nth 1 groups))
+                      (ns-project (nth 2 groups)))
+                  (lambda ()
+                    (concat "https://"; host "/"
+                            (or (match-string 1)
+                                ns-project)
+                            "/-/"
+                            (if (string= (match-string 3) "#")
+                                "issues/"
+                              "merge_requests/")
+                            (match-string 2))))))
+            ;;
+            ;; Sourcehut instances.
+            ;;
+            ;; #19 is an issue.  Other project's issues can be
+            ;; #referenced as ~user/project#19.
+            ;;
+            ;; Caveat: The code assumes that a project on git.sr.ht or
+            ;; hg.sr.ht has a tracker of the same name on todo.sh.ht.
+            ;; That's a very common setup but all sr.ht services are
+            ;; loosely coupled, so you can have a repo without
+            ;; tracker, or a repo with a tracker using a different
+            ;; name, etc.  So we can only try to make a good guess.
+            (,(concat "[/@]\\(?:git\\|hg\\)."
+                      (regexp-opt bug-reference-sourcehut-instances t)
+                      "[/:]\\(~[.A-Za-z0-9_/-]+\\)")
+             "\\(~[.A-Za-z0-9_/-]+\\)?\\(?:#\\)\\([0-9]+\\)\\>"
+             ,(lambda (groups)
+                (let ((host (nth 1 groups))
+                      (ns-project (nth 2 groups)))
+                  (lambda ()
+                    (concat "https://todo."; host "/"
+                            (or
+                             ;; Explicit user/proj#18 link.
+                             (match-string 1)
+                             ns-project)
+                            "/"
+                            (match-string 2))))))))))
+
+(defvar bug-reference-setup-from-vc-alist nil
   "An alist for setting up `bug-reference-mode' based on VC URL.
 
 Each element has the form (URL-REGEXP BUG-REGEXP URL-FORMAT-FN).
@@ -256,7 +305,8 @@ URL-REGEXP against the VCS URL and returns the value to be 
set as
 (defun bug-reference-try-setup-from-vc ()
   "Try setting up `bug-reference-mode' based on VC information.
 Test each configuration in `bug-reference-setup-from-vc-alist'
-and apply it if applicable."
+and `bug-reference--setup-from-vc-alist' and apply it if
+applicable."
   (let ((file-or-dir (or buffer-file-name
                          ;; Catches modes such as vc-dir and Magit.
                          default-directory)))
@@ -269,7 +319,9 @@ and apply it if applicable."
                     (vc-call-backend backend 'repository-url)))))
         (when url
           (catch 'found
-            (dolist (config bug-reference-setup-from-vc-alist)
+            (dolist (config (append
+                             bug-reference-setup-from-vc-alist
+                             (bug-reference--setup-from-vc-alist)))
               (when (apply #'bug-reference-maybe-setup-from-vc
                            url config)
                 (throw 'found t)))))))))
diff --git a/lisp/progmodes/cc-awk.el b/lisp/progmodes/cc-awk.el
index 334e821..f1bc25d 100644
--- a/lisp/progmodes/cc-awk.el
+++ b/lisp/progmodes/cc-awk.el
@@ -658,7 +658,7 @@
   ;; prevent a repeat invocation.  See elisp/lispref page "Search-based
   ;; Fontification".
   ;;
-  ;; This function gives invalid GAWK namepace separators (::)
+  ;; This function gives invalid GAWK namespace separators (::)
   ;; font-lock-warning-face.  "Invalid" here means there are spaces, etc.,
   ;; around a separator, or there are more than one of them in an identifier.
   ;; Invalid separators inside function declaration parentheses are handled
diff --git a/lisp/progmodes/cc-defs.el b/lisp/progmodes/cc-defs.el
index 01bd64c..fe6ff22 100644
--- a/lisp/progmodes/cc-defs.el
+++ b/lisp/progmodes/cc-defs.el
@@ -234,6 +234,14 @@ On XEmacs and older Emacsen, this refontifies that region 
immediately."
       `(font-lock-flush ,beg ,end)
     `(font-lock-fontify-region ,beg ,end)))
 
+(defmacro c-benign-error (format &rest args)
+  ;; Formats an error message for the echo area and dings, i.e. like
+  ;; `error' but doesn't abort.
+  (declare (debug t))
+  `(progn
+     (message ,format ,@args)
+     (ding)))
+
 (defmacro c-point (position &optional point)
   "Return the value of certain commonly referenced POSITIONs relative to POINT.
 The current point is used if POINT isn't specified.  POSITION can be
@@ -660,19 +668,27 @@ even when the buffer is read-only, and without 
interference from
 various buffer change hooks."
   (declare (indent 0) (debug t))
   `(let (-tnt-chng-keep
-        -tnt-chng-state)
+        -tnt-chng-state
+        (old-undo-list buffer-undo-list))
      (unwind-protect
         ;; Insert an undo boundary for use with `undo-more'.  We
         ;; don't use `undo-boundary' since it doesn't insert one
         ;; unconditionally.
-        (setq buffer-undo-list (cons nil buffer-undo-list)
-              -tnt-chng-state (c-tnt-chng-record-state)
+        (setq buffer-undo-list
+              (if (eq old-undo-list t)
+                  nil
+                (cons nil buffer-undo-list))
+              old-undo-list (if (eq old-undo-list t)
+                                t
+                              buffer-undo-list)
+              -tnt-chng-state (c-tnt-chng-record-state
+                               old-undo-list)
               -tnt-chng-keep (progn ,@body))
        (c-tnt-chng-cleanup -tnt-chng-keep -tnt-chng-state))))
 
-(defun c-tnt-chng-record-state ()
+(defun c-tnt-chng-record-state (old-undo-list)
   ;; Used internally in `c-tentative-buffer-changes'.
-  (vector buffer-undo-list             ; 0
+  (vector old-undo-list                        ; 0
          (current-buffer)              ; 1
          ;; No need to use markers for the point and mark; if the
          ;; undo got out of synch we're hosed anyway.
@@ -690,18 +706,26 @@ various buffer change hooks."
        (setq buffer-undo-list (cdr saved-undo-list))
 
       (if keep
-         ;; Find and remove the undo boundary.
-         (let ((p buffer-undo-list))
-           (while (not (eq (cdr p) saved-undo-list))
-             (setq p (cdr p)))
-           (setcdr p (cdr saved-undo-list)))
-
-       ;; `primitive-undo' will remove the boundary.
-       (setq saved-undo-list (cdr saved-undo-list))
-       (let ((undo-in-progress t))
-         (while (not (eq (setq buffer-undo-list
-                               (primitive-undo 1 buffer-undo-list))
-                         saved-undo-list))))
+         (if (eq saved-undo-list t)
+             (progn
+               (c-benign-error
+                "Can't save additional undo list in c-tnt-chng-cleanup")
+               (setq buffer-undo-list t))
+           ;; Find and remove the undo boundary.
+           (let ((p buffer-undo-list))
+             (while (not (eq (cdr p) saved-undo-list))
+               (setq p (cdr p)))
+             (setcdr p (cdr saved-undo-list))))
+
+       (let ((undo-in-progress t)
+             (end-undo-list (if (eq saved-undo-list t)
+                                nil
+                              ;; `primitive-undo' will remove the boundary.
+                              (cdr saved-undo-list))))
+         (while (not (eq buffer-undo-list end-undo-list))
+           (setq buffer-undo-list (primitive-undo 1 buffer-undo-list))))
+       (if (eq saved-undo-list t)
+           (setq buffer-undo-list t))
 
        (when (buffer-live-p (elt saved-state 1))
          (set-buffer (elt saved-state 1))
@@ -1027,14 +1051,6 @@ be after it."
   '(if c-vsemi-status-unknown-p-fn (funcall c-vsemi-status-unknown-p-fn)))
 
 
-(defmacro c-benign-error (format &rest args)
-  ;; Formats an error message for the echo area and dings, i.e. like
-  ;; `error' but doesn't abort.
-  (declare (debug t))
-  `(progn
-     (message ,format ,@args)
-     (ding)))
-
 (defmacro c-with-syntax-table (table &rest code)
   ;; Temporarily switches to the specified syntax table in a failsafe
   ;; way to execute code.
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index 5d2e41a..77da98f 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -7422,7 +7422,7 @@ multi-line strings (but not C++, for example)."
                     t)
                    (save-excursion
                      (goto-char (match-end 1))
-                     (if (c-in-literal) ; a psuedo closer.
+                     (if (c-in-literal) ; a pseudo closer.
                          t
                        (setq saved-match-data (match-data))
                        (setq found t)
@@ -12288,12 +12288,15 @@ comment at the start of cc-engine.el for more info."
          pos2 in-paren parens-before-brace
          paren-state paren-pos)
 
-      (setq res (c-backward-token-2 1 t lim))
+      (setq res
+           (or (progn (c-backward-syntactic-ws)
+                      (c-back-over-compound-identifier))
+               (c-backward-token-2 1 t lim)))
       ;; Checks to do only on the first sexp before the brace.
       ;; Have we a C++ initialization, without an "="?
       (if (and (c-major-mode-is 'c++-mode)
               (cond
-               ((and (or (not (eq res 0))
+               ((and (or (not (memq res '(t 0)))
                          (eq (char-after) ?,))
                      (setq paren-state (c-parse-state))
                      (setq paren-pos (c-pull-open-brace paren-state))
@@ -12317,7 +12320,7 @@ comment at the start of cc-engine.el for more info."
                (t nil))
               (save-excursion
                 (cond
-                 ((or (not (eq res 0))
+                 ((or (not (memq res '(t 0)))
                       (eq (char-after) ?,))
                   (and (setq paren-state (c-parse-state))
                        (setq paren-pos (c-pull-open-brace paren-state))
diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el
index 1fb6124..af7b829 100644
--- a/lisp/progmodes/compile.el
+++ b/lisp/progmodes/compile.el
@@ -2951,7 +2951,8 @@ attempts to find a file whose name is produced by (format 
FMT FILENAME)."
             fmts formats)
       ;; For each directory, try each format string.
       (while (and fmts (null buffer))
-        (setq name (expand-file-name (format (car fmts) filename) thisdir)
+        (setq name (file-truename
+                    (file-name-concat thisdir (format (car fmts) filename)))
               buffer (and (file-exists-p name)
                           (find-file-noselect name))
               fmts (cdr fmts)))
@@ -2973,7 +2974,8 @@ attempts to find a file whose name is produced by (format 
FMT FILENAME)."
         (setq thisdir (car dirs)
               fmts formats)
         (while (and fmts (null buffer))
-          (setq name (expand-file-name (format (car fmts) filename) thisdir)
+          (setq name (file-truename
+                      (file-name-concat thisdir (format (car fmts) filename)))
                 buffer (and (file-exists-p name)
                             (find-file-noselect name))
                 fmts (cdr fmts)))
@@ -3016,7 +3018,8 @@ attempts to find a file whose name is produced by (format 
FMT FILENAME)."
               (ding) (sit-for 2))
              ((and (file-directory-p name)
                    (not (file-exists-p
-                         (setq name (expand-file-name filename name)))))
+                         (setq name (file-truename
+                                     (file-name-concat name filename))))))
               (message "No `%s' in directory %s" filename origname)
               (ding) (sit-for 2))
              (t
diff --git a/lisp/progmodes/cperl-mode.el b/lisp/progmodes/cperl-mode.el
index 3370df6..f518501 100644
--- a/lisp/progmodes/cperl-mode.el
+++ b/lisp/progmodes/cperl-mode.el
@@ -1741,7 +1741,9 @@ or as help on variables `cperl-tips', `cperl-problems',
               '((cperl-load-font-lock-keywords
                  cperl-load-font-lock-keywords-1
                  cperl-load-font-lock-keywords-2)
-                nil nil ((?_ . "w"))))
+                nil nil ((?_ . "w")) nil
+                (font-lock-syntactic-face-function
+                 . cperl-font-lock-syntactic-face-function)))
   ;; Reset syntaxification cache.
   (setq-local cperl-syntax-state nil)
   (when cperl-use-syntax-table-text-property
@@ -3147,26 +3149,29 @@ Returns true if comment is found.  In POD will not move 
the point."
     (while (re-search-forward "^\\s(" e 'to-end)
       (put-text-property (1- (point)) (point) 'syntax-table cperl-st-punct))))
 
-(defun cperl-commentify (bb e string &optional noface)
-  (if cperl-use-syntax-table-text-property
-      (if (eq noface 'n)               ; Only immediate
-         nil
-       ;; We suppose that e is _after_ the end of construction, as after eol.
-       (setq string (if string cperl-st-sfence cperl-st-cfence))
-       (if (> bb (- e 2))
+(defun cperl-commentify (begin end string)
+  "Mark text from BEGIN to END as generic string or comment.
+Mark as generic string if STRING, as generic comment otherwise.
+A single character is marked as punctuation and directly
+fontified.  Do nothing if BEGIN and END are equal.  If
+`cperl-use-syntax-text-property' is nil, just fontify."
+  (if (and cperl-use-syntax-table-text-property
+           (> end begin))
+      (progn
+        (setq string (if string cperl-st-sfence cperl-st-cfence))
+        (if (> begin (- end 2))
            ;; one-char string/comment?!
-           (cperl-modify-syntax-type bb cperl-st-punct)
-         (cperl-modify-syntax-type bb string)
-         (cperl-modify-syntax-type (1- e) string))
-       (if (and (eq string cperl-st-sfence) (> (- e 2) bb))
-           (put-text-property (1+ bb) (1- e)
+           (cperl-modify-syntax-type begin cperl-st-punct)
+          (cperl-modify-syntax-type begin string)
+          (cperl-modify-syntax-type (1- end) string))
+        (if (and (eq string cperl-st-sfence) (> (- end 2) begin))
+           (put-text-property (1+ begin) (1- end)
                               'syntax-table cperl-string-syntax-table))
-       (cperl-protect-defun-start bb e))
+        (cperl-protect-defun-start begin end))
     ;; Fontify
-    (or noface
-       (not cperl-pod-here-fontify)
-       (put-text-property bb e 'face (if string 'font-lock-string-face
-                                       'font-lock-comment-face)))))
+    (when cperl-pod-here-fontify
+      (put-text-property begin end 'face (if string 'font-lock-string-face
+                                          'font-lock-comment-face)))))
 
 (defvar cperl-starters '(( ?\( . ?\) )
                         ( ?\[ . ?\] )
@@ -3333,8 +3338,10 @@ Works before syntax recognition is done."
 ;;             Each non-literal part is marked `syntax-type' ==> `pod'
 ;;             Each literal part is marked `syntax-type' ==> `in-pod'
 ;;     b) HEREs:
+;;              The point before start is marked `here-doc-start'
 ;;             Start-to-end is marked `here-doc-group' ==> t
 ;;             The body is marked `syntax-type' ==> `here-doc'
+;;                and is also marked as style 2 comment
 ;;             The delimiter is marked `syntax-type' ==> `here-doc-delim'
 ;;     c) FORMATs:
 ;;             First line (to =) marked `first-format-line' ==> t
@@ -3351,8 +3358,36 @@ Works before syntax recognition is done."
 ;; (value: 0 in //o, 1 if "interpolated variable" is whole-REx, t otherwise).
 
 (defun cperl-unwind-to-safe (before &optional end)
-  ;; if BEFORE, go to the previous start-of-line on each step of unwinding
-  (let ((pos (point)))
+  "Move point back to a safe place, back up one extra line if BEFORE.
+A place is \"safe\" if it is not within POD, a here-document, a
+format, a quote-like expression, a subroutine attribute list or a
+multiline declaration.  These places all have special syntactical
+rules and need to be parsed as a whole.  If END, return the
+position of the end of the unsafe construct."
+  (let ((pos (point))
+        (state (syntax-ppss)))
+    ;; Check edge cases for here-documents first
+    (when before                        ; we need a safe start for parsing
+      (cond
+       ((or (equal (get-text-property (cperl-1- (point)) 'syntax-type)
+                   'here-doc-start)
+            (equal (syntax-after (cperl-1- (point)))
+                   (string-to-syntax "> c")))
+        ;; point is either immediately after the start of a here-doc
+        ;; (which may consist of nothing but one newline) or
+        ;; immediately after the now-outdated end marker of the
+        ;; here-doc. In both cases we need to back up to the line
+        ;; where the here-doc delimiters are defined.
+        (forward-char -1)
+        (cperl-backward-to-noncomment (point-min))
+        (beginning-of-line))
+       ((eq 2 (nth 7 state))
+        ;; point is somewhere in a here-document.  Back up to the line
+        ;; where the here-doc delimiters are defined.
+        (goto-char (nth 8 state))      ; beginning of this here-doc
+        (cperl-backward-to-noncomment  ; skip back over more
+         (point-min))                  ;     here-documents (if any)
+        (beginning-of-line))))         ; skip back over here-doc starters
     (while (and pos (progn
                      (beginning-of-line)
                      (get-text-property (setq pos (point)) 'syntax-type)))
@@ -3510,19 +3545,194 @@ Should be called with the point before leading colon 
of an attribute."
     (goto-char endbracket)             ; just in case something misbehaves???
     t))
 
+(defvar cperl-here-doc-functions
+  (regexp-opt '("print" "printf" "say"  ; print $handle <<EOF
+                "system" "exec"         ; system $progname <<EOF
+                "sort")                 ; sort $subname <<EOF
+              'symbols)                 ; avoid false positives
+  "List of keywords after which `$var <<bareword' is a here-document.
+After any other token `$var <<bareword' is treated as the variable `$var'
+left-shifted by the return value of the function `bareword'.")
+
+(defun cperl-is-here-doc-p (start)
+  "Find out whether a \"<<\" construct starting at START is a here-document.
+The point is expected to be after the end of the delimiter.
+Quoted delimiters after \"<<\" are unambiguously starting
+here-documents and are not handled here.  This function does not
+move point but does change match data."
+  ;; not a here-doc | here-doc
+  ;; $foo << b;     | $f .= <<B;
+  ;; ($f+1) << b;   | a($f) . <<B;
+  ;; foo 1, <<B;    | $x{a} <<b;
+  ;; Limitations:
+  ;; foo <<bar is statically undecidable.  It could be either
+  ;; foo() << bar # left shifting the return value or
+  ;; foo(<<bar)   # passing a here-doc to foo().
+  ;; We treat it as here-document and kindly ask programmers to
+  ;; disambiguate by adding parens.
+  (null
+   (or (looking-at "[ \t]*(") ; << function_call()
+       (looking-at ">>")      ; <<>> operator
+       (save-excursion ; 1 << func_name, or $foo << 10
+        (condition-case nil
+            (progn
+              (goto-char start)
+              (forward-sexp -1) ;; examine the part before "<<"
+              (save-match-data
+                (cond
+                 ((looking-at "[0-9$({]")
+                  (forward-sexp 1)
+                  (and
+                   (looking-at "[ \t]*<<")
+                   (condition-case nil
+                       ;; print $foo <<EOF
+                       (progn
+                         (forward-sexp -2)
+                         (not
+                          (looking-at cperl-here-doc-functions)))
+                     (error t)))))))
+          (error nil)))))) ; func(<<EOF)
+
+(defun cperl-process-here-doc (min max end overshoot stop-point
+                                   end-of-here-doc err-l
+                                   indented-here-doc-p
+                                   matched-pos todo-pos
+                                   delim-begin delim-end)
+  "Process a here-document's delimiters and body.
+The parameters MIN, MAX, END, OVERSHOOT, STOP-POINT, ERR-L are
+used for recursive calls to `cperl-find-pods-here' to handle the
+rest of the line which contains the delimiter.  MATCHED-POS and
+TODO-POS are initial values for this function's result.
+END-OF-HERE-DOC is the end of a previous here-doc in the same
+line, or nil if this is the first.  DELIM-BEGIN and DELIM-END are
+the positions where the here-document's delimiter has been found.
+This is part of `cperl-find-pods-heres' (below)."
+  (let* ((my-cperl-delimiters-face font-lock-constant-face)
+         (delimiter (buffer-substring-no-properties delim-begin delim-end))
+         (qtag (regexp-quote delimiter))
+         (use-syntax-state (and cperl-syntax-state
+                               (>= min (car cperl-syntax-state))))
+         (state-point (if use-syntax-state
+                         (car cperl-syntax-state)
+                       (point-min)))
+         (state (if use-syntax-state
+                   (cdr cperl-syntax-state)))
+         here-doc-start here-doc-end defs-eol
+         warning-message)
+    (when cperl-pod-here-fontify
+      ;; Highlight the starting delimiter
+      (cperl-postpone-fontification delim-begin delim-end
+                                    'face my-cperl-delimiters-face)
+      (cperl-put-do-not-fontify delim-begin delim-end t))
+    (forward-line)
+    (setq here-doc-start (point) ; first char of (first) here-doc
+          defs-eol (1- here-doc-start)) ; end of definitions line
+    (if end-of-here-doc
+        ;; skip to the end of the previous here-doc
+       (goto-char end-of-here-doc)
+      ;; otherwise treat the first (or only) here-doc: Check for
+      ;; special cases if the line containing the delimiter(s)
+      ;; ends in a regular comment or a solitary ?#
+      (let* ((eol-state (save-excursion (syntax-ppss defs-eol))))
+        (when (nth 4 eol-state) ; EOL is in a comment
+          (if (= (1- defs-eol) (nth 8 eol-state))
+              ;; line ends with a naked comment starter.
+              ;; We let it start the here-doc.
+              (progn
+                (put-text-property (1- defs-eol) defs-eol
+                                   'font-lock-face
+                                   'font-lock-comment-face)
+                (put-text-property (1- defs-eol) defs-eol
+                                   'syntax-type 'here-doc)
+                (put-text-property (1- defs-eol) defs-eol
+                                   'syntax-type 'here-doc)
+                (put-text-property (1- defs-eol) defs-eol
+                                   'syntax-table
+                                   (string-to-syntax "< c"))
+                )
+            ;; line ends with a "regular" comment: make
+            ;; the last character of the comment closing
+            ;; it so that we can use the line feed to
+            ;; start the here-doc
+            (put-text-property (1- defs-eol) defs-eol
+                               'syntax-table
+                               (string-to-syntax ">"))))))
+    (setq here-doc-start (point)) ; now points to current here-doc
+    ;; Find the terminating delimiter.
+    ;; We do not search to max, since we may be called from
+    ;; some hook of fontification, and max is random
+    (or (re-search-forward
+        (concat "^" (when indented-here-doc-p "[ \t]*")
+                qtag "$")
+        stop-point 'toend)
+       (progn          ; Pretend we matched at the end
+         (goto-char (point-max))
+         (re-search-forward "\\'")
+         (setq warning-message
+                (format "End of here-document `%s' not found." delimiter))
+         (or (car err-l) (setcar err-l here-doc-start))))
+    (when cperl-pod-here-fontify
+      ;; Highlight the ending delimiter
+      (cperl-postpone-fontification
+       (match-beginning 0) (match-end 0)
+       'face my-cperl-delimiters-face)
+      (cperl-put-do-not-fontify here-doc-start (match-end 0) t))
+    (setq here-doc-end (cperl-1+ (match-end 0))) ; eol after delim
+    (put-text-property here-doc-start (match-beginning 0)
+                      'syntax-type 'here-doc)
+    (put-text-property (match-beginning 0) here-doc-end
+                      'syntax-type 'here-doc-delim)
+    (put-text-property here-doc-start here-doc-end 'here-doc-group t)
+    ;; This makes insertion at the start of HERE-DOC update
+    ;; the whole construct:
+    (put-text-property here-doc-start (cperl-1+ here-doc-start) 'front-sticky 
'(syntax-type))
+    (cperl-commentify (match-beginning 0) (1- here-doc-end) nil)
+    (put-text-property (1- here-doc-start) here-doc-start
+                       'syntax-type 'here-doc-start)
+    (when (> (match-beginning 0) here-doc-start)
+      ;; here-document has non-zero length
+      (cperl-modify-syntax-type (1- here-doc-start) (string-to-syntax "< c"))
+      (cperl-modify-syntax-type (1- (match-beginning 0))
+                                (string-to-syntax "> c")))
+    (cperl-put-do-not-fontify here-doc-start (match-end 0) t)
+    ;; Cache the syntax info...
+    (setq cperl-syntax-state (cons state-point state))
+    ;; ... and process the rest of the line...
+    (setq overshoot
+         (elt          ; non-inter ignore-max
+          (cperl-find-pods-heres todo-pos defs-eol
+                                  t end t here-doc-end)
+           1))
+    (if (and overshoot (> overshoot (point)))
+       (goto-char overshoot)
+      (setq overshoot here-doc-end))
+    (list (if (> here-doc-end max) matched-pos nil)
+          overshoot
+          warning-message)))
+
 ;; Debugging this may require (setq max-specpdl-size 2000)...
 (defun cperl-find-pods-heres (&optional min max non-inter end ignore-max 
end-of-here-doc)
-  "Scans the buffer for hard-to-parse Perl constructions.
-If `cperl-pod-here-fontify' is not-nil after evaluation, will fontify
-the sections using `cperl-pod-head-face', `cperl-pod-face',
-`cperl-here-face'."
+  "Scan the buffer for hard-to-parse Perl constructions.
+If `cperl-pod-here-fontify' is non-nil after evaluation,
+fontify the sections using `cperl-pod-head-face',
+`cperl-pod-face', `cperl-here-face'.  The optional parameters are
+for internal use: scan from MIN to MAX, or the whole buffer if
+these are nil.  If NON-INTER, don't write progress messages.  If
+IGNORE-MAX, scan to end of buffer.  If END, we are after a
+\"__END__\" or \"__DATA__\" token, so ignore unbalanced
+constructs.  END-OF-HERE-DOC points to the end of a here-document
+which has already been processed.
+Value is a two-element list of the position where an error
+occurred (if any) and the \"overshoot\", which is used for
+recursive calls in starting lines of here-documents."
   (interactive)
   (or min (setq min (point-min)
                cperl-syntax-state nil
                cperl-syntax-done-to min))
   (or max (setq max (point-max)))
-  (let* ((cperl-pod-here-fontify (eval cperl-pod-here-fontify)) go tmpend
-        face head-face here-face b e bb tag qtag b1 e1 argument i c tail tb
+  (font-lock-flush min max)
+  (let* (go tmpend
+        face head-face b e bb tag qtag b1 e1 argument i c tail tb
         is-REx is-x-REx REx-subgr-start REx-subgr-end was-subgr i2 hairy-RE
         (case-fold-search nil) (inhibit-read-only t) (buffer-undo-list t)
         (modified (buffer-modified-p)) overshoot is-o-REx name
@@ -3619,20 +3829,20 @@ the sections using `cperl-pod-head-face', 
`cperl-pod-face',
            (and cperl-pod-here-fontify
                 ;; We had evals here, do not know why...
                 (setq face cperl-pod-face
-                      head-face cperl-pod-head-face
-                      here-face cperl-here-face))
-           (remove-text-properties min max
-                                   '(syntax-type t in-pod t syntax-table t
-                                                 attrib-group t
-                                                 REx-interpolated t
-                                                 cperl-postpone t
-                                                 syntax-subtype t
-                                                 rear-nonsticky t
-                                                 front-sticky t
-                                                 here-doc-group t
-                                                 first-format-line t
-                                                 REx-part2 t
-                                                 indentable t))
+                      head-face cperl-pod-head-face))
+            (unless end-of-here-doc
+             (remove-text-properties min max
+                                     '(syntax-type t in-pod t syntax-table t
+                                                   attrib-group t
+                                                   REx-interpolated t
+                                                   cperl-postpone t
+                                                   syntax-subtype t
+                                                   rear-nonsticky t
+                                                   front-sticky t
+                                                   here-doc-group t
+                                                   first-format-line t
+                                                   REx-part2 t
+                                                   indentable t)))
            ;; Need to remove face as well...
            (goto-char min)
            (while (and
@@ -3751,120 +3961,36 @@ the sections using `cperl-pod-head-face', 
`cperl-pod-face',
               ;; but multiline quote on the same line as <<HERE confuses us...
                ;; ;; One extra () before this:
               ;;"<<"
-              ;;  "\\("                        ; 1 + 1
+              ;;  "<<\\(~?\\)"          ; HERE-DOC, indented-p = capture 2
               ;;  ;; First variant "BLAH" or just ``.
               ;;     "[ \t]*"                  ; Yes, whitespace is allowed!
-              ;;     "\\([\"'`]\\)"    ; 2 + 1
-              ;;     "\\([^\"'`\n]*\\)"        ; 3 + 1
-              ;;     "\\3"
+              ;;     "\\([\"'`]\\)"    ; 3 + 1
+              ;;     "\\([^\"'`\n]*\\)"        ; 4 + 1
+              ;;     "\\4"
               ;;  "\\|"
               ;;  ;; Second variant: Identifier or \ID or empty
-              ;;    "\\\\?\\(\\([a-zA-Z_][a-zA-Z_0-9]*\\)?\\)" ; 4 + 1, 5 + 1
+              ;;    "\\\\?\\(\\([a-zA-Z_][a-zA-Z_0-9]*\\)?\\)" ; 5 + 1, 6 + 1
               ;;    ;; Do not have <<= or << 30 or <<30 or << $blah.
               ;;    ;; "\\([^= \t0-9$@%&]\\|[ \t]+[^ \t\n0-9$@%&]\\)" ; 6 + 1
-              ;;    "\\(\\)"           ; To preserve count of pars :-( 6 + 1
               ;;  "\\)"
-              ((match-beginning 3)     ; 2 + 1: found "<<", detect its type
-               (setq b (point)
-                     tb (match-beginning 0)
-                     c (and            ; not HERE-DOC
-                        (match-beginning 6)
-                        (save-match-data
-                          (or (looking-at "[ \t]*(") ; << function_call()
-                              (looking-at ">>")      ; <<>> operator
-                              (save-excursion ; 1 << func_name, or $foo << 10
-                                (condition-case nil
-                                    (progn
-                                      (goto-char tb)
-              ;;; XXX What to do: foo <<bar ???
-              ;;; XXX Need to support print {a} <<B ???
-                                      (forward-sexp -1)
-                                      (save-match-data
-                                       ; $foo << b; $f .= <<B;
-                                       ; ($f+1) << b; a($f) . <<B;
-                                       ; foo 1, <<B; $x{a} <<b;
-                                        (cond
-                                         ((looking-at "[0-9$({]")
-                                          (forward-sexp 1)
-                                          (and
-                                           (looking-at "[ \t]*<<")
-                                           (condition-case nil
-                                               ;; print $foo <<EOF
-                                               (progn
-                                                 (forward-sexp -2)
-                                                 (not
-                                                  (looking-at 
"\\(printf?\\|say\\|system\\|exec\\|sort\\)\\>")))
-                                               (error t)))))))
-                                  (error nil))) ; func(<<EOF)
-                              (and (not (match-beginning 7)) ; Empty
-                                   (looking-at
-                                    "[ \t]*[=0-9$@%&(]"))))))
-               (if c                   ; Not here-doc
-                   nil                 ; Skip it.
-                 (setq c (match-end 3)) ; 2 + 1
-                 (if (match-beginning 6) ;6 + 1
-                     (setq b1 (match-beginning 6) ; 5 + 1
-                           e1 (match-end 6)) ; 5 + 1
-                   (setq b1 (match-beginning 5) ; 4 + 1
-                         e1 (match-end 5))) ; 4 + 1
-                 (setq tag (buffer-substring b1 e1)
-                       qtag (regexp-quote tag))
-                 (cond (cperl-pod-here-fontify
-                        ;; Highlight the starting delimiter
-                        (cperl-postpone-fontification
-                         b1 e1 'face my-cperl-delimiters-face)
-                        (cperl-put-do-not-fontify b1 e1 t)))
-                 (forward-line)
-                 (setq i (point))
-                 (if end-of-here-doc
-                     (goto-char end-of-here-doc))
-                 (setq b (point))
-                 ;; We do not search to max, since we may be called from
-                 ;; some hook of fontification, and max is random
-                 (or (and (re-search-forward
-                           (concat "^" (when (equal (match-string 2) "~") "[ 
\t]*")
-                                   qtag "$")
-                           stop-point 'toend)
-                          ;;;(eq (following-char) ?\n) ; XXXX WHY???
-                          )
-                   (progn              ; Pretend we matched at the end
-                     (goto-char (point-max))
-                     (re-search-forward "\\'")
-                     (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
-                       ;; Highlight the ending delimiter
-                       (cperl-postpone-fontification
-                        (match-beginning 0) (match-end 0)
-                        'face my-cperl-delimiters-face)
-                       (cperl-put-do-not-fontify b (match-end 0) t)
-                       ;; Highlight the HERE-DOC
-                       (cperl-postpone-fontification b (match-beginning 0)
-                                                     'face here-face)))
-                 (setq e1 (cperl-1+ (match-end 0)))
-                 (put-text-property b (match-beginning 0)
-                                    'syntax-type 'here-doc)
-                 (put-text-property (match-beginning 0) e1
-                                    'syntax-type 'here-doc-delim)
-                 (put-text-property b e1 'here-doc-group t)
-                 ;; This makes insertion at the start of HERE-DOC update
-                 ;; the whole construct:
-                 (put-text-property b (cperl-1+ b) 'front-sticky 
'(syntax-type))
-                 (cperl-commentify b e1 nil)
-                 (cperl-put-do-not-fontify b (match-end 0) t)
-                 ;; Cache the syntax info...
-                 (setq cperl-syntax-state (cons state-point state))
-                 ;; ... and process the rest of the line...
-                 (setq overshoot
-                       (elt            ; non-inter ignore-max
-                        (cperl-find-pods-heres c i t end t e1) 1))
-                 (if (and overshoot (> overshoot (point)))
-                     (goto-char overshoot)
-                   (setq overshoot e1))
-                 (if (> e1 max)
-                     (setq tmpend tb))))
+               ((match-beginning 3)     ; 2 + 1: found "<<", detect its type
+                (let* ((matched-pos (match-beginning 0))
+                       (quoted-delim-p (if (match-beginning 6) nil t))
+                       (delim-capture (if quoted-delim-p 5 6)))
+                  (when (cperl-is-here-doc-p matched-pos)
+                    (let ((here-doc-results
+                           (cperl-process-here-doc
+                            min max end overshoot stop-point ; for recursion
+                            end-of-here-doc err-l            ; for recursion
+                            (equal (match-string 2) "~")     ; indented 
here-doc?
+                            matched-pos                      ; for recovery (?)
+                            (match-end 3)                    ; todo from here
+                            (match-beginning delim-capture)  ; starting 
delimiter
+                            (match-end delim-capture))))     ;   boundaries
+                      (setq tmpend (nth 0 here-doc-results)
+                            overshoot (nth 1 here-doc-results))
+                      (and (nth 2 here-doc-results)
+                           (setq warning-message (nth 2 here-doc-results)))))))
               ;; format
               ((match-beginning 8)
                ;; 1+6=7 extra () before this:
@@ -5458,6 +5584,18 @@ comment, or POD."
   (or cperl-faces-init (cperl-init-faces))
   cperl-font-lock-keywords-2)
 
+(defun cperl-font-lock-syntactic-face-function (state)
+  "Apply faces according to their syntax type.  In CPerl mode, this
+is used for here-documents which have been marked as c-style
+comments.  For everything else, delegate to the default
+function."
+  (cond
+   ;; A c-style comment is a HERE-document.  Fontify if requested.
+   ((and (eq 2 (nth 7 state))
+         cperl-pod-here-fontify)
+    cperl-here-face)
+   (t (funcall (default-value 'font-lock-syntactic-face-function) state))))
+
 (defun cperl-init-faces ()
   (condition-case errs
       (progn
diff --git a/lisp/progmodes/ebnf-abn.el b/lisp/progmodes/ebnf-abn.el
index 2a37110..c3b240a 100644
--- a/lisp/progmodes/ebnf-abn.el
+++ b/lisp/progmodes/ebnf-abn.el
@@ -530,13 +530,14 @@ See documentation for variable `ebnf-abn-lex'."
        (let ((prose-p (= (following-char) ?<)))
          (when prose-p
            (forward-char)
-           (or (looking-at ebnf-abn-non-terminal-letter-chars)
+           (or (looking-at (concat "[" ebnf-abn-non-terminal-letter-chars "]"))
                (error "Invalid prose value")))
          (setq ebnf-abn-lex
                (ebnf-buffer-substring ebnf-abn-non-terminal-chars))
          (when prose-p
            (or (= (following-char) ?>)
                (error "Invalid prose value"))
+            (forward-char)
            (setq ebnf-abn-lex (concat "<" ebnf-abn-lex ">"))))
        'non-terminal)
        ;; equal: =, =/
diff --git a/lisp/progmodes/ebnf2ps.el b/lisp/progmodes/ebnf2ps.el
index 884104a..6ad55fc 100644
--- a/lisp/progmodes/ebnf2ps.el
+++ b/lisp/progmodes/ebnf2ps.el
@@ -2244,8 +2244,12 @@ the PostScript image in a file with that name.  If 
FILENAME is a
 number, prompt the user for the name of the file to save in."
   (interactive (list (ps-print-preprint current-prefix-arg)))
   (ebnf-log-header "(ebnf-print-buffer %S)" filename)
-  (ebnf-print-region (point-min) (point-max) filename))
-
+  (cl-letf (((symbol-function 'ps-output-string)
+             ;; Make non-ASCII work (sort of).
+             (lambda (string)
+               (ps-output t (and string
+                                 (encode-coding-string string 'iso-8859-1))))))
+    (ebnf-print-region (point-min) (point-max) filename)))
 
 ;;;###autoload
 (defun ebnf-print-region (from to &optional filename)
diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el
index 542f8ad..ef36c1f 100644
--- a/lisp/progmodes/elisp-mode.el
+++ b/lisp/progmodes/elisp-mode.el
@@ -1452,7 +1452,7 @@ Elisp eldoc behaviour.  Consider variable docstrings and 
function
 signatures only, in this order.  If none applies, returns nil.
 Changes to `eldoc-documentation-functions' and
 `eldoc-documentation-strategy' are _not_ reflected here.  As such
-it is preferrable to use ElDoc's interfaces directly.")
+it is preferable to use ElDoc's interfaces directly.")
 
 (make-obsolete 'elisp-eldoc-documentation-function
                "use ElDoc's interfaces instead." "28.1")
diff --git a/lisp/progmodes/flymake.el b/lisp/progmodes/flymake.el
index 77a807f..cc12fce 100644
--- a/lisp/progmodes/flymake.el
+++ b/lisp/progmodes/flymake.el
@@ -1256,6 +1256,8 @@ correctly.")
     ,(let ((map (make-sparse-keymap)))
        (define-key map [mode-line down-mouse-1]
          flymake-menu)
+       (define-key map [mode-line down-mouse-3]
+         flymake-menu)
        (define-key map [mode-line mouse-2]
          (lambda ()
            (interactive)
diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el
index 08814eb..d8c77f7 100644
--- a/lisp/progmodes/gud.el
+++ b/lisp/progmodes/gud.el
@@ -1679,9 +1679,14 @@ into one that invokes an Emacs-enabled debugging session.
 
 ;;;###autoload
 (defun perldb (command-line)
-  "Run perldb on program FILE in buffer *gud-FILE*.
-The directory containing FILE becomes the initial working directory
-and source-file directory for your debugger."
+  "Debug a perl program with gud.
+Interactively, this will prompt you for a command line.
+
+Noninteractively, COMMAND-LINE should be on the form
+\"perl -d perl-file.pl\".
+
+The directory containing the perl program becomes the initial
+working directory and source-file directory for your debugger."
   (interactive
    (list (gud-query-cmdline 'perldb
                            (concat (or (buffer-file-name) "-e 0") " "))))
@@ -2775,14 +2780,24 @@ Commands:
                        (expand-file-name file-subst)
                      file-subst)))
         (filepart (and file-word (concat "-" (file-name-nondirectory file))))
-        (existing-buffer (get-buffer (concat "*gud" filepart "*"))))
+         (buffer-name (concat "*gud" filepart "*"))
+        (existing-buffer (get-buffer buffer-name))
+         error)
+    (when (and existing-buffer
+               (get-buffer-process existing-buffer))
+      (if (equal (buffer-local-value 'default-directory existing-buffer)
+                 default-directory)
+          ;; We're already debugging this executable.
+          (setq error t)
+        ;; Open a new window to debug an executable with the same name.
+        (setq buffer-name (generate-new-buffer-name buffer-name))))
     (select-window
      (display-buffer
-      (get-buffer-create (concat "*gud" filepart "*"))
+      (get-buffer-create buffer-name)
       '((display-buffer-reuse-window
          display-buffer-in-previous-window
          display-buffer-same-window display-buffer-pop-up-window))))
-    (when (and existing-buffer (get-buffer-process existing-buffer))
+    (when error
       (error "This program is already being debugged"))
     ;; Set the dir, in case the buffer already existed with a different dir.
     (setq default-directory dir)
@@ -2804,8 +2819,12 @@ Commands:
        (setq w (cdr w)))
       ;; Tramp has already been loaded if we are here.
       (if w (setcar w (setq file (file-local-name file)))))
-    (apply #'make-comint (concat "gud" filepart) program nil
-          (if massage-args (funcall massage-args file args) args))
+    (apply #'make-comint-in-buffer
+           (concat "gud" filepart) (current-buffer)
+           program nil
+          (if massage-args
+               (funcall massage-args file args)
+             args))
     ;; Since comint clobbered the mode, we don't set it until now.
     (gud-mode)
     (setq-local gud-target-name
diff --git a/lisp/progmodes/hideif.el b/lisp/progmodes/hideif.el
index 4a1da62..a2f5d72 100644
--- a/lisp/progmodes/hideif.el
+++ b/lisp/progmodes/hideif.el
@@ -682,7 +682,7 @@ that form should be displayed.")
 (defconst hif-valid-token-list (mapcar 'cdr hif-token-alist))
 
 (defconst hif-token-regexp
-  ;; The ordering of regexp grouping is crutial to `hif-strtok'
+  ;; The ordering of regexp grouping is crucial to `hif-strtok'
   (concat
    ;; hex/binary:
    
"\\([+-]?0[xXbB]\\([[:xdigit:]']+\\)?\\.?\\([[:xdigit:]']+\\)?\\([pP]\\([+-]?[0-9]+\\)\\)?"
diff --git a/lisp/progmodes/prog-mode.el b/lisp/progmodes/prog-mode.el
index 19de754..f75a303 100644
--- a/lisp/progmodes/prog-mode.el
+++ b/lisp/progmodes/prog-mode.el
@@ -43,6 +43,33 @@
                                 display-line-numbers-mode
                                 prettify-symbols-mode))
 
+(defun prog-context-menu (menu)
+  (require 'xref)
+  (define-key-after menu [prog-separator] menu-bar-separator
+    'mark-whole-buffer)
+  (define-key-after menu [xref-find-def]
+    '(menu-item "Find Definition" xref-find-definitions-at-mouse
+                :visible (save-excursion
+                           (mouse-set-point last-input-event)
+                           (xref-backend-identifier-at-point
+                            (xref-find-backend)))
+                :help "Find definition of identifier")
+    'prog-separator)
+  (define-key-after menu [xref-find-ref]
+    '(menu-item "Find References" xref-find-references-at-mouse
+                :visible (save-excursion
+                           (mouse-set-point last-input-event)
+                           (xref-backend-identifier-at-point
+                            (xref-find-backend)))
+                :help "Find references to identifier")
+    'xref-find-def)
+  (define-key-after menu [xref-pop]
+    '(menu-item "Back Definition" xref-pop-marker-stack
+                :visible (not (xref-marker-stack-empty-p))
+                :help "Back to the position of the last search")
+    'xref-find-ref)
+  menu)
+
 (defvar prog-mode-map
   (let ((map (make-sparse-keymap)))
     (define-key map [?\C-\M-q] 'prog-indent-sexp)
@@ -249,6 +276,7 @@ support it."
   "Major mode for editing programming language source code."
   (setq-local require-final-newline mode-require-final-newline)
   (setq-local parse-sexp-ignore-comments t)
+  (add-hook 'context-menu-functions 'prog-context-menu 10 t)
   ;; Any programming language is always written left to right.
   (setq bidi-paragraph-direction 'left-to-right))
 
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index e864deb..30ae82e 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -51,6 +51,11 @@
 ;; files and its relations to external directories.  `project-files'
 ;; should be consistent with `project-ignores'.
 ;;
+;; `project-buffers' can be overridden if the project has some unusual
+;; shape (e.g. it contains files residing outside of its root, or some
+;; files inside the root must not be considered a part of it).  It
+;; should be consistent with `project-files'.
+;;
 ;; This list can change in future versions.
 ;;
 ;; VC project:
@@ -319,11 +324,10 @@ The default implementation uses `find-program'."
          ;; expanded and not left for the shell command
          ;; to interpret.
          (localdir (file-name-unquote (file-local-name (expand-file-name 
dir))))
-         (command (format "%s -H %s %s -type f %s -print0"
+         (dfn (directory-file-name localdir))
+         (command (format "%s -H . %s -type f %s -print0"
                           find-program
-                          (shell-quote-argument
-                           (directory-file-name localdir)) ; Bug#48471
-                          (xref--find-ignores-arguments ignores localdir)
+                          (xref--find-ignores-arguments ignores "./")
                           (if files
                               (concat (shell-quote-argument "(")
                                       " " find-name-arg " "
@@ -341,8 +345,9 @@ The default implementation uses `find-program'."
                        (unless (zerop status)
                          (error "File listing failed: %s" 
(buffer-string))))))))
     (project--remote-file-names
-     (sort (split-string output "\0" t)
-           #'string<))))
+     (mapcar (lambda (s) (concat dfn (substring s 1)))
+             (sort (split-string output "\0" t)
+                   #'string<)))))
 
 (defun project--remote-file-names (local-files)
   "Return LOCAL-FILES as if they were on the system of `default-directory'.
@@ -356,6 +361,16 @@ Also quote LOCAL-FILES if `default-directory' is quoted."
                 (concat remote-id file))
               local-files))))
 
+(cl-defgeneric project-buffers (project)
+  "Return the list of all live buffers that belong to PROJECT."
+  (let ((root (expand-file-name (file-name-as-directory (project-root 
project))))
+        bufs)
+    (dolist (buf (buffer-list))
+      (when (string-prefix-p root (expand-file-name
+                                   (buffer-local-value 'default-directory 
buf)))
+        (push buf bufs)))
+    (nreverse bufs)))
+
 (defgroup project-vc nil
   "Project implementation based on the VC package."
   :version "25.1"
@@ -618,7 +633,9 @@ backend implementation of `project-external-roots'.")
                  (replace-match "./" t t entry 1)
                (concat "./" entry)))
             (t entry)))
-         (vc-call-backend backend 'ignore-completion-table root))))
+         (condition-case nil
+             (vc-call-backend backend 'ignore-completion-table root)
+           (vc-not-supported () nil)))))
      (project--value-in-dir 'project-vc-ignores root)
      (mapcar
       (lambda (dir)
@@ -657,6 +674,23 @@ DIRS must contain directory names."
       (hack-dir-local-variables-non-file-buffer))
     (symbol-value var)))
 
+(cl-defmethod project-buffers ((project (head vc)))
+  (let* ((root (expand-file-name (file-name-as-directory (project-root 
project))))
+         (modules (unless (or (project--vc-merge-submodules-p root)
+                              (project--submodule-p root))
+                    (mapcar
+                     (lambda (m) (format "%s%s/" root m))
+                     (project--git-submodules))))
+         dd
+         bufs)
+    (dolist (buf (buffer-list))
+      (setq dd (expand-file-name (buffer-local-value 'default-directory buf)))
+      (when (and (string-prefix-p root dd)
+                 (not (cl-find-if (lambda (module) (string-prefix-p module dd))
+                                  modules)))
+        (push buf bufs)))
+    (nreverse bufs)))
+
 
 ;;; Project commands
 
@@ -1043,13 +1077,11 @@ If non-nil, it overrides 
`compilation-buffer-name-function' for
          (current-buffer (current-buffer))
          (other-buffer (other-buffer current-buffer))
          (other-name (buffer-name other-buffer))
+         (buffers (project-buffers pr))
          (predicate
           (lambda (buffer)
             ;; BUFFER is an entry (BUF-NAME . BUF-OBJ) of Vbuffer_alist.
-            (and (cdr buffer)
-                 (equal pr
-                        (with-current-buffer (cdr buffer)
-                          (project-current)))))))
+            (memq (cdr buffer) buffers))))
     (read-buffer
      "Switch to buffer: "
      (when (funcall predicate (cons other-name other-buffer))
@@ -1189,7 +1221,7 @@ of CONDITIONS."
 What buffers should or should not be killed is described
 in `project-kill-buffer-conditions'."
   (let (bufs)
-    (dolist (buf (project--buffer-list pr))
+    (dolist (buf (project-buffers pr))
       (when (project--kill-buffer-check buf project-kill-buffer-conditions)
         (push buf bufs)))
     bufs))
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 20299c2..d8ec032 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -2022,7 +2022,12 @@ position, else returns nil."
   (cond ((executable-find "python3") "python3")
         ((executable-find "python") "python")
         (t "python3"))
-  "Default Python interpreter for shell."
+  "Default Python interpreter for shell.
+
+Some Python interpreters also require changes to
+`python-shell-interpreter-args'.  In particular, setting
+`python-shell-interpreter' to \"ipython3\" requires setting
+`python-shell-interpreter-args' to \"--simple-prompt\"."
   :version "28.1"
   :type 'string
   :group 'python)
@@ -3076,6 +3081,45 @@ there for compatibility with CEDET.")
       (delete-trailing-whitespace))
     temp-file-name))
 
+(defconst python-shell-eval-setup-code
+  "\
+def __PYTHON_EL_eval(source, filename):
+    import ast, sys
+    if sys.version_info[0] == 2:
+        from __builtin__ import compile, eval, globals
+    else:
+        from builtins import compile, eval, globals
+    sys.stdout.write('\\n')
+    try:
+        p, e = ast.parse(source, filename), None
+    except SyntaxError:
+        t, v, tb = sys.exc_info()
+        sys.excepthook(t, v, tb.tb_next)
+        return
+    if p.body and isinstance(p.body[-1], ast.Expr):
+        e = p.body.pop()
+    try:
+        g = globals()
+        exec(compile(p, filename, 'exec'), g, g)
+        if e:
+            return eval(compile(ast.Expression(e.value), filename, 'eval'), g, 
g)
+    except Exception:
+        t, v, tb = sys.exc_info()
+        sys.excepthook(t, v, tb.tb_next)"
+  "Code used to evaluate statements in inferior Python processes.")
+
+(defalias 'python-shell--encode-string
+  (let ((fun (if (and (fboundp 'json-serialize)
+                      (>= emacs-major-version 28))
+                 'json-serialize
+               (require 'json)
+               'json-encode-string)))
+    (lambda (text)
+      (if (stringp text)
+          (funcall fun text)
+        (signal 'wrong-type-argument (list 'stringp text)))))
+  "Encode TEXT as a valid Python string.")
+
 (defun python-shell-send-string (string &optional process msg)
   "Send STRING to inferior Python PROCESS.
 When optional argument MSG is non-nil, forces display of a
@@ -3083,16 +3127,18 @@ user-friendly message if there's no process running; 
defaults to
 t when called interactively."
   (interactive
    (list (read-string "Python command: ") nil t))
-  (let ((process (or process (python-shell-get-process-or-error msg))))
-    (if (string-match ".\n+." string)   ;Multiline.
-        (let* ((temp-file-name (with-current-buffer (process-buffer process)
-                                 (python-shell--save-temp-file string)))
-               (file-name (or (buffer-file-name) temp-file-name)))
-          (python-shell-send-file file-name process temp-file-name t))
-      (comint-send-string process string)
-      (when (or (not (string-match "\n\\'" string))
-                (string-match "\n[ \t].*\n?\\'" string))
-        (comint-send-string process "\n")))))
+  (let ((process (or process (python-shell-get-process-or-error msg)))
+        (code (format "exec(%s);__PYTHON_EL_eval(%s, %s)\n"
+                      (python-shell--encode-string 
python-shell-eval-setup-code)
+                      (python-shell--encode-string string)
+                      (python-shell--encode-string (or (buffer-file-name)
+                                                       "<string>")))))
+    (if (<= (string-bytes code) 4096)
+        (comint-send-string process code)
+      (let* ((temp-file-name (with-current-buffer (process-buffer process)
+                               (python-shell--save-temp-file string)))
+             (file-name (or (buffer-file-name) temp-file-name)))
+        (python-shell-send-file file-name process temp-file-name t)))))
 
 (defvar python-shell-output-filter-in-progress nil)
 (defvar python-shell-output-filter-buffer nil)
@@ -3134,7 +3180,8 @@ Return the output."
         (inhibit-quit t))
     (or
      (with-local-quit
-       (python-shell-send-string string process)
+       (comint-send-string
+        process (format "exec(%s)\n" (python-shell--encode-string string)))
        (while python-shell-output-filter-in-progress
          ;; `python-shell-output-filter' takes care of setting
          ;; `python-shell-output-filter-in-progress' to NIL after it
@@ -3331,6 +3378,18 @@ t when called interactively."
        nil ;; noop
        msg))))
 
+
+(defconst python-shell-eval-file-setup-code
+  "\
+def __PYTHON_EL_eval_file(filename, tempname, encoding, delete):
+    import codecs, os
+    with codecs.open(tempname or filename, encoding=encoding) as file:
+        source = file.read().encode(encoding)
+    if delete and tempname:
+        os.remove(tempname)
+    return __PYTHON_EL_eval(source, filename)"
+  "Code used to evaluate files in inferior Python processes.")
+
 (defun python-shell-send-file (file-name &optional process temp-file-name
                                          delete msg)
   "Send FILE-NAME to inferior Python PROCESS.
@@ -3357,18 +3416,16 @@ t when called interactively."
          (temp-file-name (when temp-file-name
                            (file-local-name (expand-file-name
                                              temp-file-name)))))
-    (python-shell-send-string
+    (comint-send-string
+     process
      (format
-      (concat
-       "import codecs, os;"
-       "__pyfile = codecs.open('''%s''', encoding='''%s''');"
-       "__code = __pyfile.read().encode('''%s''');"
-       "__pyfile.close();"
-       (when (and delete temp-file-name)
-         (format "os.remove('''%s''');" temp-file-name))
-       "exec(compile(__code, '''%s''', 'exec'));")
-      (or temp-file-name file-name) encoding encoding file-name)
-     process)))
+      "exec(%s);exec(%s);__PYTHON_EL_eval_file(%s, %s, %s, %s)\n"
+      (python-shell--encode-string python-shell-eval-setup-code)
+      (python-shell--encode-string python-shell-eval-file-setup-code)
+      (python-shell--encode-string file-name)
+      (python-shell--encode-string (or temp-file-name ""))
+      (python-shell--encode-string (symbol-name encoding))
+      (if delete "True" "False")))))
 
 (defun python-shell-switch-to-shell (&optional msg)
   "Switch to inferior Python process buffer.
diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el
index b667473..201d1fd 100644
--- a/lisp/progmodes/sh-script.el
+++ b/lisp/progmodes/sh-script.el
@@ -1775,7 +1775,7 @@ Does not preserve point."
                      (goto-char p)
                      nil))))
         (while
-            (progn (skip-syntax-backward "w_'")
+            (progn (skip-syntax-backward ".w_'")
                    (or (not (zerop (skip-syntax-backward "\\")))
                        (when (eq ?\\ (char-before (1- (point))))
                          (let ((p (point)))
diff --git a/lisp/progmodes/vhdl-mode.el b/lisp/progmodes/vhdl-mode.el
index 5eeac8a..3fe67fa 100644
--- a/lisp/progmodes/vhdl-mode.el
+++ b/lisp/progmodes/vhdl-mode.el
@@ -4700,7 +4700,7 @@ Usage:
     `vhdl-project-alist'.
 
 
-  SPECIAL MENUES:
+  SPECIAL MENUS:
     As an alternative to the speedbar, an index menu can be added (set
     option `vhdl-index-menu' to non-nil) or made accessible as a mouse menu
     (e.g. add \"(global-set-key [S-down-mouse-3] \\='imenu)\" to your start-up
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el
index 69378a5..d022baaf 100644
--- a/lisp/progmodes/xref.el
+++ b/lisp/progmodes/xref.el
@@ -1,7 +1,7 @@
 ;;; xref.el --- Cross-referencing commands              -*-lexical-binding:t-*-
 
 ;; Copyright (C) 2014-2021 Free Software Foundation, Inc.
-;; Version: 1.1.0
+;; Version: 1.2.2
 ;; Package-Requires: ((emacs "26.1"))
 
 ;; This is a GNU ELPA :core package.  Avoid functionality that is not
@@ -233,7 +233,7 @@ LOCATION is an `xref-location'."
   ((summary :type string :initarg :summary
             :reader xref-item-summary)
    (location :initarg :location
-             :type xref-file-location
+             :type xref-location
              :reader xref-item-location)
    (length :initarg :length :reader xref-match-length))
   :comment "A match xref item describes a search result.")
@@ -290,7 +290,11 @@ find a search tool; by default, this uses \"find | grep\" 
in the
 current project's main and external roots."
   (mapcan
    (lambda (dir)
-     (xref-references-in-directory identifier dir))
+     (message "Searching %s..." dir)
+     (redisplay)
+     (prog1
+         (xref-references-in-directory identifier dir)
+       (message "Searching %s... done" dir)))
    (let ((pr (project-current t)))
      (cons
       (xref--project-root pr)
@@ -412,6 +416,33 @@ elements is negated: these commands will NOT prompt."
   :version "28.1"
   :package-version '(xref . "1.0.4"))
 
+(defcustom xref-auto-jump-to-first-definition nil
+  "If t, `xref-find-definitions' always jumps to the first result.
+`show' means to show the first result's location, but keep the
+focus on the Xref buffer's window.
+`move' means to only move point to the first result."
+  :type '(choice (const :tag "Jump" t)
+                 (const :tag "Show" show)
+                 (const :tag "Move point only" move)
+                 (const :tag "No auto-jump" nil))
+  :version "28.1"
+  :package-version '(xref . "1.2.0"))
+
+(defcustom xref-auto-jump-to-first-xref nil
+  "If t, xref commands always jump to the first result.
+`show' means to show the first result's location, but keep the
+focus on the Xref buffer's window.
+`move' means to only move point to the first result.
+
+Please be careful changing this value if you are using Emacs 27
+or earlier: it can break dired-do-find-regexp-and-replace."
+  :type '(choice (const :tag "Jump" t)
+                 (const :tag "Show" show)
+                 (const :tag "Move point only" move)
+                 (const :tag "No auto-jump" nil))
+  :version "28.1"
+  :package-version '(xref . "1.2.0"))
+
 (defvar xref--marker-ring (make-ring xref-marker-ring-length)
   "Ring of markers to implement the marker stack.")
 
@@ -596,12 +627,19 @@ SELECT is `quit', also quit the *xref* window."
                   (xref--show-pos-in-buf marker buf))))))
     (user-error (message (error-message-string err)))))
 
+(defun xref--set-arrow ()
+  "Set the overlay arrow at the line at point."
+  (setq overlay-arrow-position
+        (set-marker (or overlay-arrow-position (make-marker))
+                    (line-beginning-position))))
+
 (defun xref-show-location-at-point ()
   "Display the source of xref at point in the appropriate window, if any."
   (interactive)
   (let* ((xref (xref--item-at-point))
          (xref--current-item xref))
     (when xref
+      (xref--set-arrow)
       (xref--show-location (xref-item-location xref)))))
 
 (defun xref-next-line-no-show ()
@@ -659,6 +697,7 @@ quit the *xref* buffer."
          (xref (or (xref--item-at-point)
                    (user-error "Choose a reference to visit")))
          (xref--current-item xref))
+    (xref--set-arrow)
     (xref--show-location (xref-item-location xref) (if quit 'quit t))
     (if (fboundp 'next-error-found)
         (next-error-found buffer (current-buffer))
@@ -877,18 +916,21 @@ beginning of the line."
            ;; it gets reset to that window's point from time to time).
            (let ((win (get-buffer-window (current-buffer))))
              (and win (set-window-point win (point))))
-           (xref--show-location (xref-item-location xref) t))
+           (xref--set-arrow)
+           (let ((xref--current-item xref))
+             (xref--show-location (xref-item-location xref) t)))
           (t
            (error "No %s xref" (if backward "previous" "next"))))))
 
 (defvar xref--button-map
   (let ((map (make-sparse-keymap)))
     (define-key map [mouse-1] #'xref-goto-xref)
-    (define-key map [mouse-2] #'xref--mouse-2)
+    (define-key map [mouse-2] #'xref-select-and-show-xref)
     map))
 
-(defun xref--mouse-2 (event)
-  "Move point to the button and show the xref definition."
+(defun xref-select-and-show-xref (event)
+  "Move point to the button and show the xref definition.
+The window showing the xref buffer will be selected."
   (interactive "e")
   (mouse-set-point event)
   (forward-line 0)
@@ -896,6 +938,9 @@ beginning of the line."
       (xref--search-property 'xref-item))
   (xref-show-location-at-point))
 
+(define-obsolete-function-alias
+  'xref--mouse-2 #'xref-select-and-show-xref "28.1")
+
 (defcustom xref-truncation-width 400
   "The column to visually \"truncate\" each Xref buffer line to."
   :type '(choice
@@ -1002,13 +1047,16 @@ Return an alist of the form ((FILENAME . (XREF ...)) 
...)."
            (assoc-default 'fetched-xrefs alist)
            (funcall fetcher)))
          (xref-alist (xref--analyze xrefs))
-         (dd default-directory))
+         (dd default-directory)
+         buf)
     (with-current-buffer (get-buffer-create xref-buffer-name)
       (setq default-directory dd)
       (xref--xref-buffer-mode)
       (xref--show-common-initialize xref-alist fetcher alist)
       (pop-to-buffer (current-buffer))
-      (current-buffer))))
+      (setq buf (current-buffer)))
+    (xref--auto-jump-first buf (assoc-default 'auto-jump alist))
+    buf))
 
 (defun xref--project-root (project)
   (if (fboundp 'project-root)
@@ -1021,6 +1069,7 @@ Return an alist of the form ((FILENAME . (XREF ...)) 
...)."
   (let ((inhibit-read-only t)
         (buffer-undo-list t))
     (erase-buffer)
+    (setq overlay-arrow-position nil)
     (xref--insert-xrefs xref-alist)
     (add-hook 'post-command-hook 'xref--apply-truncation nil t)
     (goto-char (point-min))
@@ -1045,19 +1094,36 @@ Return an alist of the form ((FILENAME . (XREF ...)) 
...)."
            (error-message-string err)
            'face 'error)))))))
 
+(defun xref--auto-jump-first (buf value)
+  (when value
+    (select-window (get-buffer-window buf))
+    (goto-char (point-min)))
+  (cond
+   ((eq value t)
+    (xref-next-line-no-show)
+    (xref-goto-xref))
+   ((eq value 'show)
+    (xref-next-line))
+   ((eq value 'move)
+    (forward-line 1))))
+
 (defun xref-show-definitions-buffer (fetcher alist)
   "Show the definitions list in a regular window.
 
 When only one definition found, jump to it right away instead."
-  (let ((xrefs (funcall fetcher)))
+  (let ((xrefs (funcall fetcher))
+        buf)
     (cond
      ((not (cdr xrefs))
       (xref-pop-to-location (car xrefs)
                             (assoc-default 'display-action alist)))
      (t
-      (xref--show-xref-buffer fetcher
-                              (cons (cons 'fetched-xrefs xrefs)
-                                    alist))))))
+      (setq buf
+            (xref--show-xref-buffer fetcher
+                                    (cons (cons 'fetched-xrefs xrefs)
+                                          alist)))
+      (xref--auto-jump-first buf (assoc-default 'auto-jump alist))
+      buf))))
 
 (define-obsolete-function-alias
   'xref--show-defs-buffer #'xref-show-definitions-buffer "28.1")
@@ -1073,7 +1139,8 @@ local keymap that binds `RET' to 
`xref-quit-and-goto-xref'."
          ;; XXX: Make percentage customizable maybe?
          (max-height (/ (window-height) 2))
          (size-fun (lambda (window)
-                     (fit-window-to-buffer window max-height))))
+                     (fit-window-to-buffer window max-height)))
+         buf)
     (cond
      ((not (cdr xrefs))
       (xref-pop-to-location (car xrefs)
@@ -1086,7 +1153,9 @@ local keymap that binds `RET' to 
`xref-quit-and-goto-xref'."
         (pop-to-buffer (current-buffer)
                        `(display-buffer-in-direction . ((direction . below)
                                                         (window-height . 
,size-fun))))
-        (current-buffer))))))
+        (setq buf (current-buffer)))
+      (xref--auto-jump-first buf (assoc-default 'auto-jump alist))
+      buf))))
 
 (define-obsolete-function-alias 'xref--show-defs-buffer-at-bottom
   #'xref-show-definitions-buffer-at-bottom "28.1")
@@ -1215,13 +1284,15 @@ definitions."
                   (setq xrefs 'called-already)))))))
   (funcall xref-show-xrefs-function fetcher
            `((window . ,(selected-window))
-             (display-action . ,display-action))))
+             (display-action . ,display-action)
+             (auto-jump . ,xref-auto-jump-to-first-xref))))
 
 (defun xref--show-defs (xrefs display-action)
   (xref--push-markers)
   (funcall xref-show-definitions-function xrefs
            `((window . ,(selected-window))
-             (display-action . ,display-action))))
+             (display-action . ,display-action)
+             (auto-jump . ,xref-auto-jump-to-first-definition))))
 
 (defun xref--push-markers ()
   (unless (region-active-p) (push-mark nil t))
@@ -1308,7 +1379,9 @@ prompt for it.
 If sufficient information is available to determine a unique
 definition for IDENTIFIER, display it in the selected window.
 Otherwise, display the list of the possible definitions in a
-buffer where the user can select from the list."
+buffer where the user can select from the list.
+
+Use \\[xref-pop-marker-stack] to return back to where you invoked this 
command."
   (interactive (list (xref--read-identifier "Find definitions of: ")))
   (xref--find-definitions identifier nil))
 
@@ -1348,6 +1421,20 @@ This command is intended to be bound to a mouse event."
         (xref-find-definitions identifier)
       (user-error "No identifier here"))))
 
+;;;###autoload
+(defun xref-find-references-at-mouse (event)
+  "Find references to the identifier at or around mouse click.
+This command is intended to be bound to a mouse event."
+  (interactive "e")
+  (let ((identifier
+         (save-excursion
+           (mouse-set-point event)
+           (xref-backend-identifier-at-point (xref-find-backend)))))
+    (if identifier
+        (let ((xref-prompt-for-identifier nil))
+          (xref-find-references identifier))
+      (user-error "No identifier here"))))
+
 (declare-function apropos-parse-pattern "apropos" (pattern))
 
 ;;;###autoload
@@ -1469,18 +1556,18 @@ IGNORES is a list of glob patterns for files to ignore."
        ;; do that reliably enough, without creating false negatives?
        (command (xref--rgrep-command (xref--regexp-to-extended regexp)
                                      files
-                                     (directory-file-name
-                                      (file-name-unquote
-                                       (file-local-name (expand-file-name 
dir))))
+                                     "."
                                      ignores))
-       (def default-directory)
+       (local-dir (directory-file-name
+                   (file-name-unquote
+                    (file-local-name (expand-file-name dir)))))
        (buf (get-buffer-create " *xref-grep*"))
        (`(,grep-re ,file-group ,line-group . ,_) (car grep-regexp-alist))
        (status nil)
        (hits nil))
     (with-current-buffer buf
       (erase-buffer)
-      (setq default-directory def)
+      (setq default-directory dir)
       (setq status
             (process-file-shell-command command nil t))
       (goto-char (point-min))
@@ -1493,7 +1580,7 @@ IGNORES is a list of glob patterns for files to ignore."
         (user-error "Search failed with status %d: %s" status (buffer-string)))
       (while (re-search-forward grep-re nil t)
         (push (list (string-to-number (match-string line-group))
-                    (match-string file-group)
+                    (concat local-dir (substring (match-string file-group) 1))
                     (buffer-substring-no-properties (point) 
(line-end-position)))
               hits)))
     (xref--convert-hits (nreverse hits) regexp)))
@@ -1546,7 +1633,7 @@ The template should have the following fields:
   "The program to use for regexp search inside files.
 
 This must reference a corresponding entry in `xref-search-program-alist'."
-  :type `(choice
+  :type '(choice
           (const :tag "Use Grep" grep)
           (const :tag "Use ripgrep" ripgrep)
           (symbol :tag "User defined"))
@@ -1662,6 +1749,11 @@ directory, used as the root of the ignore globs."
   (cl-assert (not (string-match-p "\\`~" dir)))
   (if (not ignores)
       ""
+    ;; TODO: All in-tree callers are passing in just "." or "./".
+    ;; We can simplify.
+    ;; And, if we ever end up deleting xref-matches-in-directory, move
+    ;; this function to the project package.
+    (setq dir (file-name-as-directory dir))
     (concat
      (shell-quote-argument "(")
      " -path "
@@ -1729,12 +1821,14 @@ Such as the current syntax table and the applied syntax 
properties."
     (if buf
         (with-current-buffer buf
           (save-excursion
-            (goto-char (point-min))
-            (forward-line (1- line))
-            (xref--collect-matches-1 regexp file line
-                                     (line-beginning-position)
-                                     (line-end-position)
-                                     syntax-needed)))
+            (save-restriction
+              (widen)
+              (goto-char (point-min))
+              (forward-line (1- line))
+              (xref--collect-matches-1 regexp file line
+                                       (line-beginning-position)
+                                       (line-end-position)
+                                       syntax-needed))))
       ;; Using the temporary buffer is both a performance and a buffer
       ;; management optimization.
       (with-current-buffer tmp-buffer
diff --git a/lisp/repeat.el b/lisp/repeat.el
index cec3cb6..6c3ffec 100644
--- a/lisp/repeat.el
+++ b/lisp/repeat.el
@@ -474,8 +474,9 @@ When Repeat mode is enabled, and the command symbol has the 
property named
         (if (current-message)
             (message "%s [%s]" (current-message) mess)
           (message mess)))
-    (when (string-prefix-p "Repeat with " (current-message))
-      (message nil))))
+    (and (current-message)
+         (string-search "Repeat with " (current-message))
+         (message nil))))
 
 (defvar repeat-echo-mode-line-string
   (propertize "[Repeating...] " 'face 'mode-line-emphasis)
diff --git a/lisp/saveplace.el b/lisp/saveplace.el
index 2a95b39..8225588 100644
--- a/lisp/saveplace.el
+++ b/lisp/saveplace.el
@@ -88,7 +88,9 @@ this happens automatically before saving `save-place-alist' to
   :type 'boolean)
 
 (defcustom save-place-abbreviate-file-names nil
-  "If non-nil, abbreviate file names before saving them."
+  "If non-nil, abbreviate file names before saving them.
+This can simplify sharing the `save-place-file' file across
+different hosts."
   :type 'boolean
   :version "28.1")
 
diff --git a/lisp/ses.el b/lisp/ses.el
index 81c2714..cc8c35d 100644
--- a/lisp/ses.el
+++ b/lisp/ses.el
@@ -1677,7 +1677,7 @@ if the range was altered."
                 (funcall field (ses-sym-rowcol min))))
          ;; This range has changed size.
          (setq ses-relocate-return 'range))
-      `(ses-range ,min ,max ,@(cl-cdddr range)))))
+      `(ses-range ,min ,max ,@(cdddr range)))))
 
 (defun ses-relocate-all (minrow mincol rowincr colincr)
   "Alter all cell values, symbols, formulas, and reference-lists to relocate
diff --git a/lisp/shadowfile.el b/lisp/shadowfile.el
index f67b0b9..63e9bd6 100644
--- a/lisp/shadowfile.el
+++ b/lisp/shadowfile.el
@@ -213,6 +213,14 @@ information defining the cluster.  For interactive use, 
call
 
 ;;; SITES
 
+;; This simplifies it a little bit.  "system-name" is also accepted.
+;; But we don't want to make the help echo too long.
+(defconst shadow-site-help "\
+A cluster identification \"/name:\", a remote identification
+\"/method:user@host:\", or \"/system-name:\" (the value of
+`shadow-system-name')"
+  "The help string describing a valid site.")
+
 (defun shadow-site-name (site)
   "Return name if SITE has the form \"/name:\", otherwise SITE."
   (if (string-match "\\`/\\([-.[:word:]]+\\):\\'" site)
@@ -239,9 +247,10 @@ information defining the cluster.  For interactive use, 
call
        shadow-clusters)))
 
 (defun shadow-read-site ()
-  "Read a cluster name or host identification from the minibuffer."
-  (let ((ans (completing-read "Host identification or cluster name: "
-                             shadow-clusters)))
+  "Read a site name from the minibuffer."
+  (let ((ans (completing-read
+              (propertize "Site name: " 'help-echo shadow-site-help)
+             shadow-clusters)))
     (when (or (shadow-get-cluster (shadow-site-name ans))
              (string-equal ans shadow-system-name)
              (string-equal ans (shadow-site-name shadow-system-name))
@@ -285,7 +294,7 @@ Argument can be a simple name, remote file name, or already 
a
 (defsubst shadow-make-fullname (hup &optional host name)
   "Make a Tramp style fullname out of HUP, a `tramp-file-name' structure.
 Replace HOST, and NAME when non-nil.  HOST can also be a remote file name."
-  (let ((hup (copy-tramp-file-name hup)))
+  (when-let ((hup (copy-tramp-file-name hup)))
     (when host
       (if (file-remote-p host)
           (setq name (or name (and hup (tramp-file-name-localname hup)))
@@ -355,23 +364,23 @@ Will return the name bare if it is a local file."
 Do so by replacing (when possible) home directory with ~/, and
 hostname with cluster name that includes it.  Filename should be
 absolute and true."
-  (let* ((hup (shadow-parse-name file))
-        (homedir (if (shadow-local-file hup)
-                     shadow-homedir
-                   (file-name-as-directory
-                    (file-local-name
-                      (expand-file-name
-                       (shadow-make-fullname hup nil shadow-homedir))))))
-        (suffix (shadow-suffix homedir (tramp-file-name-localname hup)))
-        (cluster (shadow-site-cluster (shadow-make-fullname hup nil ""))))
-    (when cluster
-      (setf (tramp-file-name-method hup) nil
-           (tramp-file-name-host hup) (shadow-cluster-name cluster)))
-    (shadow-make-fullname
-     hup nil
-     (if suffix
-         (concat shadow-homedir suffix)
-       (tramp-file-name-localname hup)))))
+  (when-let ((hup (shadow-parse-name file)))
+    (let* ((homedir (if (shadow-local-file hup)
+                       shadow-homedir
+                     (file-name-as-directory
+                      (file-local-name
+                        (expand-file-name
+                         (shadow-make-fullname hup nil shadow-homedir))))))
+          (suffix (shadow-suffix homedir (tramp-file-name-localname hup)))
+          (cluster (shadow-site-cluster (shadow-make-fullname hup nil ""))))
+      (when cluster
+        (setf (tramp-file-name-method hup) nil
+             (tramp-file-name-host hup) (shadow-cluster-name cluster)))
+      (shadow-make-fullname
+       hup nil
+       (if suffix
+           (concat shadow-homedir suffix)
+         (tramp-file-name-localname hup))))))
 
 (defun shadow-same-site (pattern file)
   "True if the site of PATTERN and of FILE are on the same site.
@@ -455,16 +464,17 @@ It may have different filenames on each site.  When this 
file is edited, the
 new version will be copied to each of the other locations.  Sites can be
 specific hostnames, or names of clusters (see `shadow-define-cluster')."
   (interactive)
-  (let* ((hup (shadow-parse-name
-              (shadow-contract-file-name (buffer-file-name))))
-        (name (tramp-file-name-localname hup))
-        site group)
-    (while (setq site (shadow-read-site))
-      (setq name (read-string "Filename: " name)
-            hup (shadow-parse-name (shadow-contract-file-name name))
-           group (cons (shadow-make-fullname hup site) group)))
-    (setq shadow-literal-groups (cons group shadow-literal-groups)))
-  (shadow-write-info-file))
+  (when-let ((hup (shadow-parse-name
+                  (shadow-contract-file-name (buffer-file-name)))))
+    (let* ((name (tramp-file-name-localname hup))
+          site group)
+      (while (setq site (shadow-read-site))
+        (setq name (read-string "Filename: " name)
+              hup (shadow-parse-name (shadow-contract-file-name name))
+             group (cons (shadow-make-fullname hup site) group)))
+      (when group
+        (setq shadow-literal-groups (cons group shadow-literal-groups))))
+    (shadow-write-info-file)))
 
 ;;;###autoload
 (defun shadow-define-regexp-group ()
diff --git a/lisp/shell.el b/lisp/shell.el
index 292f267..5cdc038 100644
--- a/lisp/shell.el
+++ b/lisp/shell.el
@@ -1199,7 +1199,7 @@ Returns t if successful."
     (if data
        (prog2 (unless (window-minibuffer-p)
                 (message "Completing command name..."))
-           (apply #'completion-in-region data)))))
+            (completion-in-region (nth 0 data) (nth 1 data) (nth 2 data))))))
 
 (defun shell-command-completion ()
   "Return the completion data for the command at point, if any."
@@ -1314,7 +1314,7 @@ Returns non-nil if successful."
     (if data
        (prog2 (unless (window-minibuffer-p)
                 (message "Completing variable name..."))
-           (apply #'completion-in-region data)))))
+           (completion-in-region (nth 0 data) (nth 1 data) (nth 2 data))))))
 
 
 (defun shell-environment-variable-completion ()
diff --git a/lisp/simple.el b/lisp/simple.el
index 7da315e..800a927 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -2070,7 +2070,7 @@ This function uses the `read-extended-command-predicate' 
user option."
   "Say whether SYMBOL has been marked as a mode-specific command in BUFFER."
   ;; Check the modes.
   (let ((modes (command-modes symbol)))
-    ;; Common case: Just a single mode.
+    ;; Common fast case: Just a single mode.
     (if (null (cdr modes))
         (or (provided-mode-derived-p
              (buffer-local-value 'major-mode buffer) (car modes))
@@ -2078,13 +2078,7 @@ This function uses the `read-extended-command-predicate' 
user option."
                   (buffer-local-value 'local-minor-modes buffer))
             (memq (car modes) global-minor-modes))
       ;; Uncommon case: Multiple modes.
-      (apply #'provided-mode-derived-p
-             (buffer-local-value 'major-mode buffer)
-             modes)
-      (seq-intersection modes
-                        (buffer-local-value 'local-minor-modes buffer)
-                        #'eq)
-      (seq-intersection modes global-minor-modes #'eq))))
+      (command-completion-with-modes-p modes buffer))))
 
 (defun command-completion-default-include-p (symbol buffer)
   "Say whether SYMBOL should be offered as a completion.
@@ -2219,7 +2213,9 @@ invoking, give a prefix argument to 
`execute-extended-command'."
   (let* ((function (and (stringp command-name) (intern-soft command-name)))
          (binding (and suggest-key-bindings
                       (not executing-kbd-macro)
-                      (where-is-internal function overriding-local-map t))))
+                      (where-is-internal function overriding-local-map t)))
+         (delay-before-suggest 0)
+         (find-shorter nil))
     (unless (commandp function)
       (error "`%s' is not a valid command name" command-name))
     ;; Some features, such as novice.el, rely on this-command-keys
@@ -2234,50 +2230,52 @@ invoking, give a prefix argument to 
`execute-extended-command'."
     (setq real-this-command function)
     (let ((prefix-arg prefixarg))
       (command-execute function 'record))
-    ;; If enabled, show which key runs this command.
-    ;; But first wait, and skip the message if there is input.
-    (let* ((waited
-            ;; If this command displayed something in the echo area;
-            ;; wait a few seconds, then display our suggestion message.
-            ;; FIXME: Wait *after* running post-command-hook!
-            ;; FIXME: If execute-extended-command--shorter were
-            ;; faster, we could compute the result here first too.
-            (when (and suggest-key-bindings
-                       (or binding
-                           (and extended-command-suggest-shorter typed)))
-              (sit-for (cond
-                        ((zerop (length (current-message))) 0)
-                        ((numberp suggest-key-bindings) suggest-key-bindings)
-                        (t 2))))))
-      (when (and waited (not (consp unread-command-events)))
-        (unless (or (not extended-command-suggest-shorter)
-                    binding executing-kbd-macro (not (symbolp function))
-                    (<= (length (symbol-name function)) 2))
-          ;; There's no binding for CMD.  Let's try and find the shortest
-          ;; string to use in M-x.
-          ;; FIXME: Can be slow.  Cache it maybe?
-          (while-no-input
-            (setq binding (execute-extended-command--shorter
-                           (symbol-name function) typed))))
-        (when binding
-          ;; This is normally not necessary -- the timer should run
-          ;; immediately, but be defensive and ensure that we never
-          ;; have two of these timers in flight.
-          (when execute-extended-command--binding-timer
-            (cancel-timer execute-extended-command--binding-timer))
-          (setq execute-extended-command--binding-timer
-                (run-at-time
-                 0 nil
-                 (lambda ()
-                   (with-temp-message
-                       (format-message "You can run the command `%s' with %s"
-                                       function
-                                       (if (stringp binding)
-                                           (concat "M-x " binding " RET")
-                                         (key-description binding)))
-                     (sit-for (if (numberp suggest-key-bindings)
-                                  suggest-key-bindings
-                                2)))))))))))
+    ;; Ensure that we never have two of the suggest-binding timers in
+    ;; flight.
+    (when execute-extended-command--binding-timer
+      (cancel-timer execute-extended-command--binding-timer))
+    ;; If this command displayed something in the echo area, then
+    ;; postpone the display of our suggestion message a bit.
+    (when (and suggest-key-bindings
+               (or binding
+                   (and extended-command-suggest-shorter typed)))
+      (setq delay-before-suggest
+            (cond
+             ((zerop (length (current-message))) 0)
+             ((numberp suggest-key-bindings) suggest-key-bindings)
+             (t 2)))
+      (when (and extended-command-suggest-shorter
+                 (not binding)
+                 (not executing-kbd-macro)
+                 (symbolp function)
+                 (> (length (symbol-name function)) 2))
+        ;; There's no binding for CMD.  Let's try and find the shortest
+        ;; string to use in M-x.
+        (setq find-shorter t))
+      (when (or binding find-shorter)
+        (setq execute-extended-command--binding-timer
+              (run-at-time
+               delay-before-suggest nil
+               (lambda ()
+                 ;; If the user has typed any other commands in the
+                 ;; meantime, then don't display anything.
+                 (when (eq function real-last-command)
+                   ;; Find shorter string.
+                   (when find-shorter
+                     (while-no-input
+                       ;; FIXME: Can be slow.  Cache it maybe?
+                       (setq binding (execute-extended-command--shorter
+                                      (symbol-name function) typed))))
+                   (when binding
+                     (with-temp-message
+                         (format-message "You can run the command `%s' with %s"
+                                         function
+                                         (if (stringp binding)
+                                             (concat "M-x " binding " RET")
+                                           (key-description binding)))
+                       (sit-for (if (numberp suggest-key-bindings)
+                                    suggest-key-bindings
+                                  2))))))))))))
 
 (defun execute-extended-command-for-buffer (prefixarg &optional
                                                       command-name typed)
@@ -7779,7 +7777,9 @@ other purposes."
 When Visual Line mode is enabled, `word-wrap' is turned on in
 this buffer, and simple editing commands are redefined to act on
 visual lines, not logical lines.  See Info node `Visual Line
-Mode' for details."
+Mode' for details.
+Turning on this mode disables line truncation set up by
+variables `truncate-lines' and `truncate-partial-width-windows'."
   :keymap visual-line-mode-map
   :group 'visual-line
   :lighter " Wrap"
@@ -8308,8 +8308,13 @@ non-nil."
                      (if (eq buffer (window-buffer window))
                          (set-window-hscroll window 0)))
                    nil t)))
-  (message "Truncate long lines %s"
-          (if truncate-lines "enabled" "disabled")))
+  (message "Truncate long lines %s%s"
+          (if truncate-lines "enabled" "disabled")
+           (if (and truncate-lines visual-line-mode)
+               (progn
+                 (visual-line-mode -1)
+                 (format-message " and `visual-line-mode' disabled"))
+             "")))
 
 (defun toggle-word-wrap (&optional arg)
   "Toggle whether to use word-wrapping for continuation lines.
diff --git a/lisp/subr.el b/lisp/subr.el
index 0a31ef2..6ae6d24 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -2872,9 +2872,23 @@ This function is used by the `interactive' code letter 
`n'."
 
 (defvar read-char-choice-use-read-key nil
   "Prefer `read-key' when reading a character by `read-char-choice'.
-Otherwise, use the minibuffer.")
+Otherwise, use the minibuffer.
+
+When using the minibuffer, the user is less constrained, and can
+use the normal commands available in the minibuffer, and can, for
+instance, switch to another buffer, do things there, and then
+switch back again to the minibuffer before entering the
+character.  This is not possible when using `read-key', but using
+`read-key' may be less confusing to some users.")
 
 (defun read-char-choice (prompt chars &optional inhibit-keyboard-quit)
+  "Read and return one of CHARS, prompting for PROMPT.
+Any input that is not one of CHARS is ignored.
+
+By default, the minibuffer is used to read the key
+non-modally (see `read-char-from-minibuffer').  If
+`read-char-choice-use-read-key' is non-nil, the modal `read-key'
+function is used instead (see `read-char-choice-with-read-key')."
   (if (not read-char-choice-use-read-key)
       (read-char-from-minibuffer prompt chars)
     (read-char-choice-with-read-key prompt chars inhibit-keyboard-quit)))
@@ -3174,7 +3188,14 @@ Also discard all previous input in the minibuffer."
 
 (defvar y-or-n-p-use-read-key nil
   "Prefer `read-key' when answering a \"y or n\" question by `y-or-n-p'.
-Otherwise, use the minibuffer.")
+Otherwise, use the minibuffer.
+
+When using the minibuffer, the user is less constrained, and can
+use the normal commands available in the minibuffer, and can, for
+instance, switch to another buffer, do things there, and then
+switch back again to the minibuffer before entering the
+character.  This is not possible when using `read-key', but using
+`read-key' may be less confusing to some users.")
 
 (defun y-or-n-p (prompt)
   "Ask user a \"y or n\" question.
@@ -3203,7 +3224,12 @@ responses, perform the requested window recentering or 
scrolling
 and ask again.
 
 Under a windowing system a dialog box will be used if `last-nonmenu-event'
-is nil and `use-dialog-box' is non-nil."
+is nil and `use-dialog-box' is non-nil.
+
+By default, this function uses the minibuffer to read the key.
+If `y-or-n-p-use-read-key' is non-nil, `read-key' is used
+instead (which means that the user can't change buffers (and the
+like) while `y-or-n-p' is running)."
   (let ((answer 'recenter)
        (padded (lambda (prompt &optional dialog)
                  (let ((l (length prompt)))
@@ -4593,6 +4619,19 @@ MODES is as for `set-default-file-modes'."
              ,@body)
          (set-default-file-modes ,umask)))))
 
+(defmacro with-existing-directory (&rest body)
+  "Execute BODY with `default-directory' bound to an existing directory.
+If `default-directory' is already an existing directory, it's not changed."
+  (declare (indent 0) (debug t))
+  `(let ((default-directory (seq-find (lambda (dir)
+                                        (and dir
+                                             (file-exists-p dir)))
+                                      (list default-directory
+                                            (expand-file-name "~/")
+                                            (getenv "TMPDIR")
+                                            "/tmp/")
+                                      "/")))
+     ,@body))
 
 ;;; Matching and match data.
 
diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el
index 4ec1143..7f6afd7 100644
--- a/lisp/tab-bar.el
+++ b/lisp/tab-bar.el
@@ -260,7 +260,9 @@ See `tab-bar-mode' for more information."
     (tab-bar-mode arg)))
 
 (defun toggle-frame-tab-bar (&optional frame)
-  "Toggle tab bar of FRAME.
+  "Toggle tab bar of the selected frame.
+When calling from Lisp, use the optional argument FRAME to toggle
+the tab bar on that frame.
 This is useful when you want to enable the tab bar individually
 on each new frame when the global `tab-bar-mode' is disabled,
 or when you want to disable the tab bar individually on each
@@ -1074,7 +1076,8 @@ to the tab argument will be applied after all functions 
are called."
   "Add a new tab at the absolute position TO-INDEX.
 TO-INDEX counts from 1.  If no TO-INDEX is specified, then add
 a new tab at the position specified by `tab-bar-new-tab-to'.
-Negative TO-INDEX counts tabs from the end of the tab bar.
+Negative TO-INDEX counts tabs from the end of the tab bar,
+and -1 means the new tab will become the last one.
 Argument addressing is absolute in contrast to `tab-bar-new-tab'
 where argument addressing is relative.
 After the tab is created, the hooks in
diff --git a/lisp/term.el b/lisp/term.el
index b3870a8..0bcd095 100644
--- a/lisp/term.el
+++ b/lisp/term.el
@@ -1429,10 +1429,10 @@ The buffer is in Term mode; see `term-mode' for the
 commands to use in that buffer.
 
 \\<term-raw-map>Type \\[switch-to-buffer] to switch to another buffer."
-  (interactive (list (read-from-minibuffer "Run program: "
-                                          (or explicit-shell-file-name
-                                              (getenv "ESHELL")
-                                              shell-file-name))))
+  (interactive (list (read-shell-command "Run program: "
+                                        (or explicit-shell-file-name
+                                            (getenv "ESHELL")
+                                            shell-file-name))))
   (set-buffer (make-term "terminal" program))
   (term-mode)
   (term-char-mode)
diff --git a/lisp/term/linux.el b/lisp/term/linux.el
index bc61a3a..6d43e47 100644
--- a/lisp/term/linux.el
+++ b/lisp/term/linux.el
@@ -13,7 +13,7 @@
   (tty-no-underline)
 
   ;; Compositions confuse cursor movement.
-  (global-auto-composition-mode -1)
+  (setq-default auto-composition-mode "linux")
 
   (ignore-errors (when gpm-mouse-mode (require 't-mouse) (gpm-mouse-enable)))
 
diff --git a/lisp/term/st.el b/lisp/term/st.el
index 9a1c064..26478ca 100644
--- a/lisp/term/st.el
+++ b/lisp/term/st.el
@@ -11,9 +11,17 @@
 
 (require 'term/xterm)
 
+(defcustom xterm-st-extra-capabilities '(modifyOtherKeys)
+  "Extra capabilities supported under \"stterm\"."
+  :version "28.1"
+  :type xterm--extra-capabilities-type
+  :group 'xterm)
+
 (defun terminal-init-st ()
   "Terminal initialization function for st."
-  (tty-run-terminal-initialization (selected-frame) "xterm"))
+  ;; Using `check' leads to a two-second timeout.
+  (let ((xterm-extra-capabilities xterm-st-extra-capabilities))
+    (tty-run-terminal-initialization (selected-frame) "xterm")))
 
 (provide 'term/st)
 
diff --git a/lisp/term/xterm.el b/lisp/term/xterm.el
index e63bf36..de5f000 100644
--- a/lisp/term/xterm.el
+++ b/lisp/term/xterm.el
@@ -73,6 +73,13 @@ string bytes that can be copied is 3/4 of this value."
   :version "27.1"
   :type 'boolean)
 
+(defcustom xterm-store-paste-on-kill-ring t
+  "If non-nil, pasting text into Emacs will put the text onto the kill ring.
+This user option is only heeded when using a terminal using xterm
+capabilities, and only when that terminal understands bracketed paste."
+  :version "28.1"
+  :type 'boolean)
+
 (defconst xterm-paste-ending-sequence "\e[201~"
   "Characters sent by the terminal to end a bracketed paste.")
 
@@ -100,9 +107,15 @@ Return the pasted text as a string."
   (interactive "e")
   (unless (eq (car-safe event) 'xterm-paste)
     (error "xterm-paste must be found to xterm-paste event"))
-  (let* ((pasted-text (nth 1 event))
-         (interprogram-paste-function (lambda () pasted-text)))
-    (yank)))
+  (let ((pasted-text (nth 1 event)))
+    (if xterm-store-paste-on-kill-ring
+        ;; Put the text onto the kill ring and then insert it into the
+        ;; buffer.
+        (let ((interprogram-paste-function (lambda () pasted-text)))
+          (yank))
+      ;; Insert the text without putting it onto the kill ring.
+      (push-mark)
+      (insert-for-yank pasted-text))))
 
 ;; Put xterm-paste itself in global-map because, after translation,
 ;; it's just a normal input event.
@@ -350,7 +363,20 @@ Return the pasted text as a string."
     (define-key map "\e[5;3~" [M-prior])
     (define-key map "\e[6;3~" [M-next])
 
-    (define-key map "\e[29~" [print])
+    ;; This escape sequence has a controversial story.
+    ;; It was initially mapped to [print] (initial commit by Karl Heuer),
+    ;; but we can't find any justification for it.
+    ;; Xterm uses this escape sequence for both `F16' and `Menu' keys,
+    ;; and the reason for it is that in the VT220 keyboard the key
+    ;; placed logically at position where `F16' would be (and sending
+    ;; the escape sequence that naturally belongs to `F16') was
+    ;; labeled `Menu'.  [ The story gets even more interesting if you
+    ;; want to dig deeper, e.g. some terminals would send that same
+    ;; escape sequence in response to `S-F4' (because they (ab)used
+    ;; the escape sequence of `F<n+12>' for `S-F<n>').  ]
+    ;; The current binding was chosen because current keyboards almost never
+    ;; have an `F16' key, whereas many do have a `Menu' key.
+    (define-key map "\e[29~" [menu])
 
     (define-key map "\eOj" [kp-multiply])
     (define-key map "\eOk" [kp-add])
diff --git a/lisp/textmodes/bibtex.el b/lisp/textmodes/bibtex.el
index 5cece1a..d5671ce 100644
--- a/lisp/textmodes/bibtex.el
+++ b/lisp/textmodes/bibtex.el
@@ -113,7 +113,7 @@ page-dashes         Change double dashes in page field to 
single dash
 whitespace          Delete whitespace at the beginning and end of fields.
 inherit-booktitle   If entry contains a crossref field and the booktitle
                       field is empty, set the booktitle field to the content
-                      of the title field of the crossreferenced entry.
+                      of the title field of the cross-referenced entry.
 realign             Realign entries, so that field texts and perhaps equal
                       signs (depending on the value of
                       `bibtex-align-at-equal-sign') begin in the same column.
@@ -1228,9 +1228,9 @@ See `bibtex-generate-autokey' for details."
   :type 'integer)
 
 (defcustom bibtex-autokey-use-crossref t
-  "If non-nil use fields from crossreferenced entry if necessary.
+  "If non-nil use fields from cross-referenced entry if necessary.
 If this variable is non-nil and some field has no entry, but a
-valid crossref entry, the field from the crossreferenced entry is used.
+valid crossref entry, the field from the cross-referenced entry is used.
 See `bibtex-generate-autokey' for details."
   :group 'bibtex-autokey
   :type 'boolean)
@@ -2975,7 +2975,7 @@ The year part:
     `bibtex-autokey-year-length' digits (useful values are 2 and 4).
  2. If both the year and date fields are absent, but the entry has a
     valid crossref field and `bibtex-autokey-use-crossref' is
-    non-nil, use the date or year field of the crossreferenced entry
+    non-nil, use the date or year field of the cross-referenced entry
     instead.
 
 The title part
diff --git a/lisp/textmodes/conf-mode.el b/lisp/textmodes/conf-mode.el
index 5f34ae1..57ec8a0 100644
--- a/lisp/textmodes/conf-mode.el
+++ b/lisp/textmodes/conf-mode.el
@@ -417,12 +417,18 @@ See also `conf-space-mode', `conf-colon-mode', 
`conf-javaprop-mode',
 ;; To tell the difference between those two cases where the function
 ;; might be called, we check `delay-mode-hooks'.
 ;; (inspired from tex-mode.el)
+(defvar conf-mode--recursing nil)
 (advice-add 'conf-mode :around
             (lambda (orig-fun)
               "Redirect to one of the submodes when called directly."
-              (funcall (if delay-mode-hooks orig-fun (conf--guess-mode)))))
-
-
+              ;; The file may have "mode: conf" in the local variable
+              ;; block, in which case we'll be called recursively
+              ;; infinitely.  Inhibit that.
+              (let ((conf-mode--recursing conf-mode--recursing))
+                (funcall (if (or delay-mode-hooks conf-mode--recursing)
+                             orig-fun
+                           (setq conf-mode--recursing t)
+                           (conf--guess-mode))))))
 
 (defun conf-mode-initialize (comment &optional font-lock)
   "Initializations for sub-modes of `conf-mode'.
diff --git a/lisp/textmodes/css-mode.el b/lisp/textmodes/css-mode.el
index 61a2f6b..d57f2d5 100644
--- a/lisp/textmodes/css-mode.el
+++ b/lisp/textmodes/css-mode.el
@@ -57,7 +57,7 @@
   "Identifiers for pseudo-classes.")
 
 (defconst css-pseudo-element-ids
-  '("after" "before" "first-letter" "first-line")
+  '("after" "before" "first-letter" "first-line" "selection")
   "Identifiers for pseudo-elements.")
 
 (defconst css-at-ids
@@ -274,12 +274,13 @@
     ("color" color)
     ("opacity" alphavalue)
 
-    ;; CSS Containment Module Level 1
-    ;; (https://www.w3.org/TR/css-contain-1/#property-index)
-    ("contain" "none" "strict" "content" "size" "layout" "paint")
+    ;; CSS Containment Module Level 2
+    ;; (https://www.w3.org/TR/css-contain-2/#property-index)
+    ("contain" "none" "strict" "content" "size" "layout" "style" "paint")
+    ("content-visibility" "visible" "auto" "hidden")
 
-    ;; CSS Grid Layout Module Level 1
-    ;; (https://www.w3.org/TR/css-grid-1/#property-index)
+    ;; CSS Grid Layout Module Level 2
+    ;; (https://www.w3.org/TR/css-grid-2/#property-index)
     ("grid" grid-template grid-template-rows "auto-flow" "dense"
      grid-auto-columns grid-auto-rows grid-template-columns)
     ("grid-area" grid-line)
@@ -298,17 +299,32 @@
     ("grid-template" "none" grid-template-rows grid-template-columns
      line-names string track-size line-names explicit-track-list)
     ("grid-template-areas" "none" string)
-    ("grid-template-columns" "none" track-list auto-track-list)
-    ("grid-template-rows" "none" track-list auto-track-list)
-
-    ;; CSS Flexible Box Layout Module Level 1
-    ;; (https://www.w3.org/TR/css-flexbox-1/#property-index)
-    ("align-content" "flex-start" "flex-end" "center" "space-between"
-     "space-around" "stretch")
-    ("align-items" "flex-start" "flex-end" "center" "baseline"
-     "stretch")
-    ("align-self" "auto" "flex-start" "flex-end" "center" "baseline"
-     "stretch")
+    ("grid-template-columns" "none" track-list auto-track-list "subgrid")
+    ("grid-template-rows" "none" track-list auto-track-list "subgrid")
+
+    ;; CSS Box Alignment Module Level 3
+    ;; (https://www.w3.org/TR/css-align-3/#property-index)
+    ("align-content"
+     baseline-position content-distibution overflow-position content-position)
+    ("align-items"
+     "normal" "stretch" baseline-position overflow-position self-position)
+    ("align-self"
+     "auto" "normal" "stretch"
+     baseline-position overflow-position self-position)
+    ("justify-content" "normal"
+     content-distibution overflow-position content-position "left" "right")
+    ("justify-items"
+     "normal" "stretch" baseline-position overflow-position self-position
+     "left" "right" "legacy")
+    ("justify-self"
+     "auto" "normal" "stretch" baseline-position overflow-position 
self-position
+     "left" "right")
+    ("place-content" align-content justify-content)
+    ("place-items" align-items justify-items)
+    ("place-self" justify-self align-self)
+
+    ;; CSS Flexible Box Layout Module Level 2
+    ;; (https://www.w3.org/TR/css-flexbox-2/#property-index)
     ("flex" "none" flex-grow flex-shrink flex-basis)
     ("flex-basis" "auto" "content" width)
     ("flex-direction" "row" "row-reverse" "column" "column-reverse")
@@ -316,8 +332,6 @@
     ("flex-grow" number)
     ("flex-shrink" number)
     ("flex-wrap" "nowrap" "wrap" "wrap-reverse")
-    ("justify-content" "flex-start" "flex-end" "center"
-     "space-between" "space-around")
     ("order" integer)
 
     ;; CSS Fonts Module Level 3
@@ -757,6 +771,13 @@ further value candidates, since that list would be 
infinite.")
     (padding-width length percentage)
     (position
      "left" "center" "right" "top" "bottom" percentage length)
+    (baseline-position "left" "right" "baseline")
+    (content-distribution
+     "space-between" "space-around" "space-evenly" "stretch")
+    (overflow-position "unsafe" "safe")
+    (content-position "center" "start" "end" "flex-start" "flex-end")
+    (self-position
+     "center" "start" "end" "self-start" "self-end" "flex-start" "flex-end")
     (radial-gradient "radial-gradient()")
     (relative-size "larger" "smaller")
     (repeat-style
diff --git a/lisp/textmodes/flyspell.el b/lisp/textmodes/flyspell.el
index 836d889..975f540 100644
--- a/lisp/textmodes/flyspell.el
+++ b/lisp/textmodes/flyspell.el
@@ -442,22 +442,6 @@ like <img alt=\"Some thing.\">."
     map)
   "Minor mode keymap for Flyspell mode--for the whole buffer.")
 
-;; correct on mouse 3
-(defun flyspell--set-use-mouse-3-for-menu (var value)
-  (set-default var value)
-  (if value
-      (progn (define-key flyspell-mouse-map [mouse-2] nil)
-             (define-key flyspell-mouse-map [down-mouse-3] 
'flyspell-correct-word))
-    (define-key flyspell-mouse-map [mouse-2] 'flyspell-correct-word)
-    (define-key flyspell-mouse-map [down-mouse-3] nil)))
-
-(defcustom flyspell-use-mouse-3-for-menu nil
-  "Non-nil means to bind `mouse-3' to `flyspell-correct-word'.
-If this is set, also unbind `mouse-2'."
-  :type 'boolean
-  :set 'flyspell--set-use-mouse-3-for-menu
-  :version "28.1")
-
 ;; dash character machinery
 (defvar-local flyspell-consider-dash-as-word-delimiter-flag nil
   "Non-nil means that the `-' char is considered as a word delimiter.")
@@ -486,6 +470,13 @@ See also `flyspell-duplicate-distance'."
 
 (defvar flyspell-overlay nil)
 
+(defun flyspell-context-menu (_menu)
+  "Context menu for `context-menu-mode'."
+  ;; TODO: refactor `flyspell-correct-word' and related functions to return
+  ;; a keymap menu where every menu item is bound to a lambda that calls
+  ;; `flyspell-do-correct' with an argument that is a correct word.
+  'flyspell-correct-word)
+
 ;;*---------------------------------------------------------------------*/
 ;;*    flyspell-mode ...                                                */
 ;;*---------------------------------------------------------------------*/
@@ -537,10 +528,7 @@ in your init file.
   :group 'flyspell
   (if flyspell-mode
       (condition-case err
-          (progn
-            (when flyspell-use-mouse-3-for-menu
-              (flyspell--set-use-mouse-3-for-menu 
'flyspell-use-mouse-3-for-menu t))
-            (flyspell-mode-on (called-interactively-p 'interactive)))
+         (flyspell-mode-on (called-interactively-p 'interactive))
        (error (message "Error enabling Flyspell mode:\n%s" (cdr err))
               (flyspell-mode -1)))
     (flyspell-mode-off)))
@@ -656,8 +644,7 @@ are both non-nil."
            show-msg)
       (let* ((binding (where-is-internal 'flyspell-auto-correct-word
                                          nil 'non-ascii))
-             (mouse-button (if flyspell-use-mouse-3-for-menu
-                               "Mouse-3" "Mouse-2")))
+             (mouse-button (if context-menu-mode "Mouse-3" "Mouse-2")))
         (message (format-message
                   "Welcome to Flyspell. Use %s to correct words."
                   (if binding
@@ -1820,13 +1807,15 @@ for the overlay."
     (overlay-put overlay 'mouse-face mouse-face)
     (overlay-put overlay 'flyspell-overlay t)
     (overlay-put overlay 'evaporate t)
-    (overlay-put overlay 'help-echo (concat (if flyspell-use-mouse-3-for-menu
-                                                "mouse-3"
-                                              "mouse-2") ": correct word at 
point"))
-    ;; If misspelled text has a 'keymap' property, let that remain in
-    ;; effect for the bindings that flyspell-mouse-map doesn't override.
-    (set-keymap-parent flyspell-mouse-map (get-char-property beg 'keymap))
-    (overlay-put overlay 'keymap flyspell-mouse-map)
+    (overlay-put overlay 'help-echo
+                 (concat (if context-menu-mode "mouse-3" "mouse-2")
+                         ": correct word at point"))
+    (if context-menu-mode
+        (overlay-put overlay 'context-menu-function 'flyspell-context-menu)
+      ;; If misspelled text has a 'keymap' property, let that remain in
+      ;; effect for the bindings that flyspell-mouse-map doesn't override.
+      (set-keymap-parent flyspell-mouse-map (get-char-property beg 'keymap))
+      (overlay-put overlay 'keymap flyspell-mouse-map))
     (when (eq face 'flyspell-incorrect)
       (and (stringp flyspell-before-incorrect-word-string)
            (overlay-put overlay 'before-string
diff --git a/lisp/textmodes/ispell.el b/lisp/textmodes/ispell.el
index 6785299..3b9f1d3 100644
--- a/lisp/textmodes/ispell.el
+++ b/lisp/textmodes/ispell.el
@@ -1039,7 +1039,11 @@ did."
 
 Invoke this command before you want to start Hunspell for the first time
 with a particular combination of dictionaries.  The first dictionary
-in the list must have an affix file where Hunspell affix files are kept."
+in the list must have an affix file where Hunspell affix files are kept.
+
+If you invoke this from Lisp, make sure to precede it with
+a call to `ispell-set-spellchecker-params', as `ispell-change-dictionary'
+calls it only when invoked interactively."
   (interactive "sMulti-dictionary combination: ")
   ;; Make sure the first dictionary in the list is known to us.
   (let ((first-dict (car (split-string dict "," t))))
@@ -2919,7 +2923,14 @@ Keeps argument list for future Ispell invocations for no 
async support."
             ;; But first wait to see if some more output is going to arrive.
             ;; Otherwise we get cool errors like "Can't open ".
             (sleep-for 1)
-            (ispell-accept-output 3)
+             ;; Only call `ispell-accept-output' if the Ispell process
+             ;; is alive, to avoid showing an unhelpful error message
+             ;; about a missing process, instead of the error which
+             ;; reports why the Ispell process died.
+            (when (if ispell-async-processp
+                         (process-live-p ispell-process)
+                       ispell-process)
+               (ispell-accept-output 3))
             (error "%s" (mapconcat #'identity ispell-filter "\n"))))
       (setq ispell-filter nil)         ; Discard version ID line
       (let ((extended-char-mode (ispell-get-extended-character-mode)))
@@ -3632,8 +3643,7 @@ sequence inside of a word.
 Standard ispell choices are then available."
   ;; FIXME: completion-at-point-function.
   (interactive "P")
-  (let ((cursor-location (point))
-       (case-fold-search-val case-fold-search)
+  (let ((case-fold-search-val case-fold-search)
        (word (ispell-get-word nil "\\*")) ; force "previous-word" processing.
        start end possibilities replacement)
     (setq start (car (cdr word))
@@ -3670,18 +3680,12 @@ Standard ispell choices are then available."
             (ispell-add-per-file-word-list word))
            (replacement                ; REPLACEMENT WORD
             (delete-region start end)
-            (setq word (if (atom replacement) replacement (car replacement))
-                  cursor-location (+ (- (length word) (- end start))
-                                     cursor-location))
-            (insert word)
-            (if (not (atom replacement)) ; recheck spelling of replacement.
-                (progn
-                  (goto-char cursor-location)
-                  (ispell-word nil t)))))
+            (insert (if (atom replacement) replacement (car replacement)))
+            (unless (atom replacement) ; recheck spelling of replacement.
+              (ispell-word nil t))))
           (if (get-buffer ispell-choices-buffer)
               (kill-buffer ispell-choices-buffer))))
-    (ispell-pdict-save ispell-silently-savep)
-    (goto-char cursor-location)))
+    (ispell-pdict-save ispell-silently-savep)))
 
 
 ;;;###autoload
diff --git a/lisp/textmodes/tex-mode.el b/lisp/textmodes/tex-mode.el
index c53acf5..d7cd0ac 100644
--- a/lisp/textmodes/tex-mode.el
+++ b/lisp/textmodes/tex-mode.el
@@ -1014,12 +1014,18 @@ says which mode to use."
   (tex-common-initialization))
 
 (advice-add 'tex-mode :around #'tex--redirect-to-submode)
+(defvar tex-mode--recursing nil)
 (defun tex--redirect-to-submode (orig-fun)
   "Redirect to one of the submodes when called directly."
-  (funcall (if delay-mode-hooks
-               ;; We're called from one of the children already.
-               orig-fun
-             (tex--guess-mode))))
+  ;; The file may have "mode: tex" in the local variable
+  ;; block, in which case we'll be called recursively
+  ;; infinitely.  Inhibit that.
+  (let ((tex-mode--recursing tex-mode--recursing))
+    (funcall (if (or delay-mode-hooks tex-mode--recursing)
+                 ;; We're called from one of the children already.
+                 orig-fun
+               (setq tex-mode--recursing t)
+               (tex--guess-mode)))))
 
 ;; The following three autoloaded aliases appear to conflict with
 ;; AUCTeX.  However, even though AUCTeX uses the mixed case variants
diff --git a/lisp/thingatpt.el b/lisp/thingatpt.el
index 66bbfb0..ab17748 100644
--- a/lisp/thingatpt.el
+++ b/lisp/thingatpt.el
@@ -162,24 +162,30 @@ Possibilities include `symbol', `list', `sexp', `defun',
 When the optional argument NO-PROPERTIES is non-nil,
 strip text properties from the return value.
 
+If the current buffer uses fields (see Info node `(elisp)Fields'),
+this function will narrow to the field before identifying the
+thing at point.
+
 See the file `thingatpt.el' for documentation on how to define
 a symbol as a valid THING."
-  (let ((text
-         (cond
-          ((cl-loop for (pthing . function) in thing-at-point-provider-alist
-                    when (eq pthing thing)
-                    for result = (funcall function)
-                    when result
-                    return result))
-          ((get thing 'thing-at-point)
-           (funcall (get thing 'thing-at-point)))
-          (t
-           (let ((bounds (bounds-of-thing-at-point thing)))
-             (when bounds
-               (buffer-substring (car bounds) (cdr bounds))))))))
-    (when (and text no-properties (sequencep text))
-      (set-text-properties 0 (length text) nil text))
-    text))
+  (save-restriction
+    (narrow-to-region (field-beginning) (field-end))
+    (let ((text
+           (cond
+            ((cl-loop for (pthing . function) in thing-at-point-provider-alist
+                      when (eq pthing thing)
+                      for result = (funcall function)
+                      when result
+                      return result))
+            ((get thing 'thing-at-point)
+             (funcall (get thing 'thing-at-point)))
+            (t
+             (let ((bounds (bounds-of-thing-at-point thing)))
+               (when bounds
+                 (buffer-substring (car bounds) (cdr bounds))))))))
+      (when (and text no-properties (sequencep text))
+        (set-text-properties 0 (length text) nil text))
+      text)))
 
 ;; Go to beginning/end
 
diff --git a/lisp/time-stamp.el b/lisp/time-stamp.el
index ae91171..5258742 100644
--- a/lisp/time-stamp.el
+++ b/lisp/time-stamp.el
@@ -44,10 +44,7 @@
 (defcustom time-stamp-format "%Y-%02m-%02d %02H:%02M:%02S %l"
   "Format of the string inserted by \\[time-stamp].
 This is a string, used verbatim except for character sequences beginning
-with %, as follows.  The values of non-numeric formatted items depend
-on the locale setting recorded in `system-time-locale' and
-`locale-coding-system'.  The examples here are for the default
-\(`C') locale.
+with %, as follows.
 
 %:A  weekday name: `Monday'             %#A gives uppercase: `MONDAY'
 %3a  abbreviated weekday: `Mon'         %#a gives uppercase: `MON'
@@ -79,6 +76,11 @@ A leading zero in the field width zero-fills a number.
 For example, to get the format used by the `date' command,
 use \"%3a %3b %2d %02H:%02M:%02S %Z %Y\".
 
+The values of non-numeric formatted items depend on the locale
+setting recorded in `system-time-locale' and `locale-coding-system'.
+The examples here are for the default (`C') locale.
+`time-stamp-time-zone' controls the time zone used.
+
 The default padding of some formats has changed to be more compatible
 with format-time-string.  To be compatible with older versions of Emacs,
 specify a padding width (as shown) or use the : modifier to request the
@@ -100,6 +102,10 @@ when they are saved, either add this line to your init 
file:
     (add-hook \\='before-save-hook \\='time-stamp)
 or customize option `before-save-hook'.
 
+To enable automatic time-stamping for only a specific file, add this
+line to a local variables list near the end of the file:
+    eval: (add-hook \\='before-save-hook \\='time-stamp nil t)
+
 See also the variable `time-stamp-warn-inactive'."
   :type 'boolean)
 
@@ -151,26 +157,27 @@ the first (last) `time-stamp-line-limit' lines of the 
file for the
 file to be time-stamped by \\[time-stamp].  A value of 0 searches the
 entire buffer (use with care).
 
-This value can also be set with the variable `time-stamp-pattern'.
+It may be more convenient to use `time-stamp-pattern' if you set more
+than one of `time-stamp-line-limit', `time-stamp-start', `time-stamp-end',
+or `time-stamp-format'.
 
-Do not change `time-stamp-line-limit', `time-stamp-start',
-`time-stamp-end', or `time-stamp-pattern' for yourself or you will be
-incompatible with other people's files!  If you must change them for some
-application, do so in the local variables section of the time-stamped file
-itself.")
+These variables are best changed with file-local variables.
+If you were to change `time-stamp-line-limit', `time-stamp-start',
+`time-stamp-end', or `time-stamp-pattern' in your init file, you
+would be incompatible with other people's files.")
 ;;;###autoload(put 'time-stamp-line-limit 'safe-local-variable 'integerp)
 
 (defvar time-stamp-start "Time-stamp:[ \t]+\\\\?[\"<]+"    ;Do not change!
   "Regexp after which the time stamp is written by \\[time-stamp].
-See also the variables `time-stamp-end' and `time-stamp-line-limit'.
 
-This value can also be set with the variable `time-stamp-pattern'.
+It may be more convenient to use `time-stamp-pattern' if you set more
+than one of `time-stamp-line-limit', `time-stamp-start', `time-stamp-end',
+or `time-stamp-format'.
 
-Do not change `time-stamp-line-limit', `time-stamp-start',
-`time-stamp-end', or `time-stamp-pattern' for yourself or you will be
-incompatible with other people's files!  If you must change them for some
-application, do so in the local variables section of the time-stamped file
-itself.")
+These variables are best changed with file-local variables.
+If you were to change `time-stamp-line-limit', `time-stamp-start',
+`time-stamp-end', or `time-stamp-pattern' in your init file, you
+would be incompatible with other people's files.")
 ;;;###autoload(put 'time-stamp-start 'safe-local-variable 'stringp)
 
 (defvar time-stamp-end "\\\\?[\">]"    ;Do not change!
@@ -179,7 +186,9 @@ itself.")
 and the following match of `time-stamp-end', then writes the
 time stamp specified by `time-stamp-format' between them.
 
-This value can also be set with the variable `time-stamp-pattern'.
+It may be more convenient to use `time-stamp-pattern' if you set more
+than one of `time-stamp-line-limit', `time-stamp-start', `time-stamp-end',
+or `time-stamp-format'.
 
 The end text normally starts on the same line as the start text ends,
 but if there are any newlines in `time-stamp-format', the same number
@@ -187,10 +196,10 @@ of newlines must separate the start and end.  
\\[time-stamp] tries
 to not change the number of lines in the buffer.  `time-stamp-inserts-lines'
 controls this behavior.
 
-Do not change `time-stamp-start', `time-stamp-end', `time-stamp-pattern',
-or `time-stamp-inserts-lines' for yourself or you will be incompatible
-with other people's files!  If you must change them for some application,
-do so in the local variables section of the time-stamped file itself.")
+These variables are best changed with file-local variables.
+If you were to change `time-stamp-line-limit', `time-stamp-start',
+`time-stamp-end', `time-stamp-pattern', or `time-stamp-inserts-lines' in
+your init file, you would be incompatible with other people's files.")
 ;;;###autoload(put 'time-stamp-end 'safe-local-variable 'stringp)
 
 
@@ -204,10 +213,9 @@ immediately after the start pattern.  This behavior can 
cause
 unexpected changes in the buffer if used carelessly, but it is useful
 for generating repeated time stamps.
 
-Do not change `time-stamp-end' or `time-stamp-inserts-lines' for
-yourself or you will be incompatible with other people's files!
-If you must change them for some application, do so in the local
-variables section of the time-stamped file itself.")
+These variables are best changed with file-local variables.
+If you were to change `time-stamp-end' or `time-stamp-inserts-lines' in
+your init file, you would be incompatible with other people's files.")
 ;;;###autoload(put 'time-stamp-inserts-lines 'safe-local-variable 'symbolp)
 
 
@@ -215,10 +223,9 @@ variables section of the time-stamped file itself.")
   "How many templates \\[time-stamp] will look for in a buffer.
 The same time stamp will be written in each case.
 
-Do not change `time-stamp-count' for yourself or you will be
-incompatible with other people's files!  If you must change it for
-some application, do so in the local variables section of the
-time-stamped file itself.")
+`time-stamp-count' is best changed with a file-local variable.
+If you were to change it in your init file, you would be incompatible
+with other people's files.")
 ;;;###autoload(put 'time-stamp-count 'safe-local-variable 'integerp)
 
 
@@ -244,6 +251,15 @@ part as \"%%\" to use the normal format.
 The fourth part is a regexp identifying the pattern following the time stamp.
 This part may be omitted to use the normal pattern.
 
+The pattern does not need to match the entire line of the time stamp.
+
+These variables are best changed with file-local variables.
+If you were to change `time-stamp-pattern', `time-stamp-line-limit',
+`time-stamp-start', or `time-stamp-end' in your init file, you
+would be incompatible with other people's files.
+
+See also `time-stamp-count' and `time-stamp-inserts-lines'.
+
 Examples:
 
 \"-10/\" (sets only `time-stamp-line-limit')
@@ -255,38 +271,44 @@ Examples:
 `time-stamp-format' and `time-stamp-end')
 
 \"newcommand{\\\\\\\\timestamp}{%%}\" (sets `time-stamp-start'
-and `time-stamp-end')
-
-Do not change `time-stamp-pattern' `time-stamp-line-limit',
-`time-stamp-start', or `time-stamp-end' for yourself or you will be
-incompatible with other people's files!  If you must change them for
-some application, do so only in the local variables section of the
-time-stamped file itself.")
+and `time-stamp-end')")
 ;;;###autoload(put 'time-stamp-pattern 'safe-local-variable 'stringp)
 
 
 
 ;;;###autoload
 (defun time-stamp ()
-  "Update the time stamp string(s) in the buffer.
-A template in a file can be automatically updated with a new time stamp
-every time you save the file.  Add this line to your init file:
-    (add-hook \\='before-save-hook \\='time-stamp)
-or customize option `before-save-hook'.
-Normally the template must appear in the first 8 lines of a file and
-look like one of the following:
+  "Update any time stamp string(s) in the buffer.
+This function looks for a time stamp template and updates it with
+the current date, time, and/or other info.
+
+The template, which you manually create on one of the first 8 lines
+of the file before running this function, by default can look like
+one of the following (your choice):
       Time-stamp: <>
       Time-stamp: \" \"
-The time stamp is written between the brackets or quotes:
+This function writes the current time between the brackets or quotes,
+by default formatted like this:
       Time-stamp: <2020-08-07 17:10:21 gildea>
 
-The time stamp is updated only if the variable
-`time-stamp-active' is non-nil.
-The format of the time stamp is set by the variable
-`time-stamp-pattern' or `time-stamp-format'.
-The variables `time-stamp-pattern', `time-stamp-line-limit',
-`time-stamp-start', `time-stamp-end', `time-stamp-count', and
-`time-stamp-inserts-lines' control finding the template."
+Although you can run this function manually to update a time stamp
+once, usually you want automatic time stamp updating.
+
+A time stamp can be automatically updated with current information
+every time you save a file.  To enable time-stamping for all files,
+customize option `before-save-hook' or add this line to your init file:
+    (add-hook \\='before-save-hook \\='time-stamp)
+
+To enable automatic time-stamping for only a specific file, add
+this line to a local variables list near the end of the file:
+    eval: (add-hook \\='before-save-hook \\='time-stamp nil t)
+
+If the file has no time-stamp template, this function does nothing.
+
+You can set `time-stamp-pattern' in a files's local variables list
+to customize the information in the time stamp and where it is written.
+
+The time stamp is updated only if `time-stamp-active' is non-nil."
   (interactive)
   (let ((line-limit time-stamp-line-limit)
        (ts-start time-stamp-start)
@@ -431,6 +453,8 @@ With ARG, turn time stamping on if and only if ARG is 
positive."
   (message "time-stamp is now %s." (if time-stamp-active "active" "off")))
 
 (defun time-stamp--format (format time)
+  "FORMAT a TIME in zone `time-stamp-time-zone'.
+Internal helper used by `time-stamp-string-preprocess'."
   (format-time-string format time time-stamp-time-zone))
 
 (defun time-stamp-string (&optional ts-format time)
@@ -457,7 +481,7 @@ normally the current time is used."
 (defun time-stamp-string-preprocess (format &optional time)
   "Use a FORMAT to format date, time, file, and user information.
 Optional second argument TIME is only for testing.
-Implements extensions to `format-time-string'
+This is an internal routine implementing extensions to `format-time-string'
 and all `time-stamp-format' compatibility."
   (let ((fmt-len (length format))
        (ind 0)
@@ -682,14 +706,15 @@ and all `time-stamp-format' compatibility."
 (defun time-stamp-do-number (format-char alt-form field-width time)
   "Handle compatible FORMAT-CHAR where only default width/padding will change.
 ALT-FORM is whether `#' specified.  FIELD-WIDTH is the string
-width specification or \"\".  TIME is the time to convert."
+width specification or \"\".  TIME is the time to convert.
+This is an internal helper for `time-stamp-string-preprocess'."
   (let ((format-string (concat "%" (char-to-string format-char))))
     (if (and (> alt-form 0) (not (string-equal field-width "")))
        ""                              ;discourage "%:2d" and the like
       (string-to-number (time-stamp--format format-string time)))))
 
 (defvar time-stamp-conversion-warn t
-  "Warn about soon-to-be-unsupported forms in `time-stamp-format'.
+  "Enable warnings about soon-to-be-unsupported forms in `time-stamp-format'.
 If nil, these warnings are disabled, which would be a bad idea!
 You really need to update your files instead.
 
@@ -755,7 +780,7 @@ Suggests replacing OLD-FORM with NEW-FORM."
 ;; Principles guiding our choices:
 ;;
 ;; - The syntax should be easy to remember and the effect predictable.
-;; - It should be possible to produces as many useful effects as possible.
+;; - The syntax should enable as many useful effects as possible.
 ;;
 ;; Padding choices:
 ;;
@@ -789,21 +814,21 @@ Suggests replacing OLD-FORM with NEW-FORM."
 ;; %07:z  "+99:00:00" "+100:00"
 ;; %7::z  "+99:00:00" "+100:00:00"
 
-;;; * BNF syntax of the offset string produced by %z
-
-;; <offset> ::= <sign><hours>[<minutes>[<seconds>]]<padding> |
-;;              <sign><hours>[<colonminutes>[<colonseconds>]]<padding> |
-;;              <sign><bighours><colonminutes>[<colonseconds>]<padding>
-;; <sign> ::= "+"|"-"
-;; <hours> ::= <2digits>
-;; <minutes> ::= <2digits>
-;; <seconds> ::= <2digits>
-;; <colonminutes> ::= ":"<minutes>
-;; <colonseconds> ::= ":"<seconds>
-;; <2digits> ::= <digit><digit>
-;; <digit> ::= "0"|"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9"
-;; <bighours> ::= <digit>*<digit><2digits>
-;; <padding> ::= " "*
+;;; * ABNF syntax of the offset string produced by %z
+
+;; offset = sign hours [minutes [seconds]] padding /
+;;          sign hours [colonminutes [colonseconds]] padding /
+;;          sign bighours colonminutes [colonseconds] padding
+;; sign = "+" / "-"
+;; hours = digitpair
+;; minutes = digitpair
+;; seconds = digitpair
+;; colonminutes = ":" minutes
+;; colonseconds = ":" seconds
+;; digitpair = digit digit
+;; digit = "0" / "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9"
+;; bighours = 1*digit digitpair
+;; padding = *" "
 
 (defun time-stamp-formatz-from-parsed-options (flag-minimize
                                                flag-pad-spaces-only
diff --git a/lisp/userlock.el b/lisp/userlock.el
index 38aaf6a..a38f6ac 100644
--- a/lisp/userlock.el
+++ b/lisp/userlock.el
@@ -125,7 +125,8 @@ You can <%s>uit; don't modify this file."
   (with-demoted-errors "Unchanged content check: %S"
     ;; Even tho we receive `filename', we know that `filename' refers to the 
current
     ;; buffer's file.
-    (cl-assert (equal filename (expand-file-name buffer-file-truename)))
+    (cl-assert (equal (expand-file-name filename)
+                      (expand-file-name buffer-file-truename)))
     ;; Note: rather than read the file and compare to the buffer, we could save
     ;; the buffer and compare to the file, but for encrypted data this
     ;; wouldn't work well (and would risk exposing the data).
diff --git a/lisp/vc/ediff-wind.el b/lisp/vc/ediff-wind.el
index fc6ea94..7c90348 100644
--- a/lisp/vc/ediff-wind.el
+++ b/lisp/vc/ediff-wind.el
@@ -400,7 +400,8 @@ keyboard input to go into icons."
   ;; skip dedicated and unsplittable frames
   (ediff-destroy-control-frame control-buffer)
   (let ((window-min-height 1)
-       split-window-function wind-width-or-height
+        (window-combination-resize t)
+       split-window-function
        three-way-comparison
        wind-A-start wind-B-start wind-A wind-B wind-C)
     (with-current-buffer control-buffer
@@ -419,22 +420,12 @@ keyboard input to go into icons."
        (select-window (next-window nil 'ignore-minibuf)))
     (delete-other-windows)
     (set-window-dedicated-p (selected-window) nil)
-    (split-window-vertically)
-    (ediff-select-lowest-window)
-    (ediff-setup-control-buffer control-buffer)
 
     ;; go to the upper window and split it betw A, B, and possibly C
     (other-window 1)
     (switch-to-buffer buf-A)
     (setq wind-A (selected-window))
-    (if three-way-comparison
-       (setq wind-width-or-height
-             (/ (if (eq split-window-function #'split-window-vertically)
-                    (window-height wind-A)
-                  (window-width wind-A))
-                3)))
-
-    (funcall split-window-function wind-width-or-height)
+    (funcall split-window-function)
 
     (if (eq (selected-window) wind-A)
        (other-window 1))
@@ -443,7 +434,7 @@ keyboard input to go into icons."
 
     (if three-way-comparison
        (progn
-         (funcall split-window-function) ; equally
+         (funcall split-window-function)
          (if (eq (selected-window) wind-B)
              (other-window 1))
          (switch-to-buffer buf-C)
@@ -461,7 +452,9 @@ keyboard input to go into icons."
          (set-window-start wind-A wind-A-start)
          (set-window-start wind-B wind-B-start)))
 
-    (ediff-select-lowest-window)
+    (select-window (display-buffer-in-direction
+                    control-buffer
+                    '((direction . bottom))))
     (ediff-setup-control-buffer control-buffer)
     ))
 
@@ -746,6 +739,7 @@ keyboard input to go into icons."
                             (and (not (frame-live-p frame-A))
                                  (or ctl-frame-exists-p
                                      (eq frame-B (selected-frame))))))
+         (window-combination-resize t)
         wind-A-start wind-B-start
         designated-minibuffer-frame)
 
@@ -758,7 +752,7 @@ keyboard input to go into icons."
                           'B ediff-narrow-bounds))))
 
     (if use-same-frame
-       (let (wind-width-or-height) ; this affects 3way setups only
+        (progn
          (if (and (eq frame-A frame-B) (frame-live-p frame-A))
              (select-frame frame-A)
            ;; avoid dedicated and non-splittable windows
@@ -767,15 +761,7 @@ keyboard input to go into icons."
          (switch-to-buffer buf-A)
          (setq wind-A (selected-window))
 
-         (if three-way-comparison
-             (setq wind-width-or-height
-                   (/
-                    (if (eq split-window-function #'split-window-vertically)
-                        (window-height wind-A)
-                      (window-width wind-A))
-                    3)))
-
-         (funcall split-window-function wind-width-or-height)
+          (funcall split-window-function)
          (if (eq (selected-window) wind-A)
              (other-window 1))
          (switch-to-buffer buf-B)
diff --git a/lisp/vc/vc-cvs.el b/lisp/vc/vc-cvs.el
index c8f36fb..ec6dc28 100644
--- a/lisp/vc/vc-cvs.el
+++ b/lisp/vc/vc-cvs.el
@@ -24,9 +24,9 @@
 
 ;;; Code:
 
+(require 'vc-rcs)
 (eval-when-compile (require 'vc))
 
-(declare-function vc-branch-p "vc" (rev))
 (declare-function vc-checkout "vc" (file &optional rev))
 (declare-function vc-expand-dirs "vc" (file-or-dir-list backend))
 (declare-function vc-read-revision "vc"
@@ -451,17 +451,17 @@ REV is the revision to check out."
      ((string= first-revision "")
       (setq status (vc-cvs-merge-news file)))
      (t
-      (if (not (vc-branch-p first-revision))
+      (if (not (vc-rcs-branch-p first-revision))
          (setq second-revision
                (vc-read-revision
                 "Second revision: "
                 (list file) 'CVS nil
-                (concat (vc-branch-part first-revision) ".")))
+                (concat (vc-rcs-branch-part first-revision) ".")))
        ;; We want to merge an entire branch.  Set revisions
        ;; accordingly, so that vc-cvs-merge understands us.
        (setq second-revision first-revision)
        ;; first-revision must be the starting point of the branch
-       (setq first-revision (vc-branch-part first-revision)))
+       (setq first-revision (vc-rcs-branch-part first-revision)))
       (setq status (vc-cvs-merge file first-revision second-revision))))
     status))
 
@@ -542,14 +542,12 @@ Will fail unless you have administrative privileges on 
the repo."
 ;;; History functions
 ;;;
 
-(declare-function vc-rcs-print-log-cleanup "vc-rcs" ())
 ;; Follows vc-cvs-command, which uses vc-do-command from vc-dispatcher.
 (declare-function vc-exec-after "vc-dispatcher" (code))
 
 (defun vc-cvs-print-log (files buffer &optional _shortlog _start-revision 
limit)
   "Print commit log associated with FILES into specified BUFFER.
 Remaining arguments are ignored."
-  (require 'vc-rcs)
   ;; It's just the catenation of the individual logs.
   (vc-cvs-command
    buffer
diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el
index 935dc8b..037fbcb 100644
--- a/lisp/vc/vc-git.el
+++ b/lisp/vc/vc-git.el
@@ -242,14 +242,18 @@ included in the completions."
 ;;;###autoload         (load "vc-git" nil t)
 ;;;###autoload         (vc-git-registered file))))
 
-(defun vc-git--literal-pathspec (pathspec)
-  "Prepend :(literal) path magic to PATHSPEC."
-  ;; Good example of PATHSPEC that needs this: "test[56].xx".
-  (and pathspec (concat ":(literal)" pathspec)))
-
-(defun vc-git--literal-pathspecs (pathspecs)
-  "Prepend :(literal) path magic to PATHSPECS."
-  (mapcar #'vc-git--literal-pathspec pathspecs))
+(defun vc-git--literal-pathspec (file)
+  "Prepend :(literal) path magic to FILE."
+  ;; Good example of file name that needs this: "test[56].xx".
+  (let ((lname (file-local-name file)))
+    ;; Expand abbreviated file names.
+    (when (file-name-absolute-p lname)
+      (setq lname (expand-file-name lname)))
+    (and file (concat ":(literal)" lname))))
+
+(defun vc-git--literal-pathspecs (files)
+  "Prepend :(literal) path magic to FILES."
+  (mapcar #'vc-git--literal-pathspec files))
 
 (defun vc-git-registered (file)
   "Check whether FILE is registered with git."
@@ -1552,10 +1556,10 @@ This requires git 1.8.4 or later, for the \"-L\" option 
of \"git log\"."
     (or (vc-git-symbolic-commit next-rev) next-rev)))
 
 (defun vc-git-delete-file (file)
-  (vc-git-command nil 0 (vc-git--literal-pathspecs file) "rm" "-f" "--"))
+  (vc-git-command nil 0 (vc-git--literal-pathspec file) "rm" "-f" "--"))
 
 (defun vc-git-rename-file (old new)
-  (vc-git-command nil 0 (vc-git--literal-pathspecs (list old new)) "mv" "-f" 
"--"))
+  (vc-git-command nil 0 (list old new) "mv" "-f" "--"))
 
 (defun vc-git-mark-resolved (files)
   (vc-git-command nil 0 (vc-git--literal-pathspecs files) "add"))
diff --git a/lisp/vc/vc-rcs.el b/lisp/vc/vc-rcs.el
index 6ffc1a8..0b0c71b 100644
--- a/lisp/vc/vc-rcs.el
+++ b/lisp/vc/vc-rcs.el
@@ -41,7 +41,6 @@
   (require 'cl-lib)
   (require 'vc))
 
-(declare-function vc-branch-p "vc" (rev))
 (declare-function vc-read-revision "vc"
                   (prompt &optional files backend default initial-input))
 (declare-function vc-buffer-context "vc-dispatcher" ())
@@ -173,6 +172,19 @@ For a description of possible values, see 
`vc-check-master-templates'."
 
 (defun vc-rcs-dir-extra-headers (&rest _ignore))
 
+;; functions that operate on RCS revision numbers.
+(defun vc-rcs-branch-p (rev)
+  "Return t if REV is a branch revision."
+  (not (eq nil (string-match "\\`[0-9]+\\(\\.[0-9]+\\.[0-9]+\\)*\\'" rev))))
+(define-obsolete-function-alias 'vc-branch-p #'vc-rcs-branch-p "28.1")
+
+(defun vc-rcs-branch-part (rev)
+  "Return the branch part of a revision number REV."
+  (let ((index (string-match "\\.[0-9]+\\'" rev)))
+    (when index
+      (substring rev 0 index))))
+(define-obsolete-function-alias 'vc-branch-part #'vc-rcs-branch-part "28.1")
+
 (defun vc-rcs-working-revision (file)
   "RCS-specific version of `vc-working-revision'."
   (or (and vc-consult-headers
@@ -198,7 +210,7 @@ When VERSION is given, perform check for that version."
               ;; If we are not on the trunk, we need to examine the
               ;; whole current branch.
               (vc-insert-file (vc-master-name file) "^desc")
-              (vc-rcs-find-most-recent-rev (vc-branch-part version))))))
+              (vc-rcs-find-most-recent-rev (vc-rcs-branch-part version))))))
 
 (defun vc-rcs-workfile-unchanged-p (file)
   "Has FILE remained unchanged since last checkout?"
@@ -326,7 +338,7 @@ whether to remove it."
             (setq rev default-branch)
             (setq switches (cons "-f" switches)))
        (if (and (not rev) old-version)
-           (setq rev (vc-branch-part old-version)))
+           (setq rev (vc-rcs-branch-part old-version)))
        (apply #'vc-do-command "*vc*" 0 "ci" (vc-master-name file)
               ;; if available, use the secure check-in option
               (and (vc-rcs-release-p "5.6.4") "-j")
@@ -349,11 +361,11 @@ whether to remove it."
        ;; branch accordingly
        (cond
         ((and old-version new-version
-              (not (string= (vc-branch-part old-version)
-                            (vc-branch-part new-version))))
+              (not (string= (vc-rcs-branch-part old-version)
+                            (vc-rcs-branch-part new-version))))
          (vc-rcs-set-default-branch file
                                     (if (vc-rcs-trunk-p new-version) nil
-                                      (vc-branch-part new-version)))
+                                      (vc-rcs-branch-part new-version)))
          ;; If this is an old (pre-1992!) RCS release, we might have
          ;; to remove a remaining lock.
          (if (not (vc-rcs-release-p "5.6.2"))
@@ -414,7 +426,7 @@ attempt the checkout for all registered files beneath it."
                                       ;; REV is t ...
                                       (if (not (vc-rcs-trunk-p workrev))
                                           ;; ... go to head of current branch
-                                          (vc-branch-part workrev)
+                                          (vc-rcs-branch-part workrev)
                                         ;; ... go to head of trunk
                                         (vc-rcs-set-default-branch file
                                                                   nil)
@@ -431,7 +443,7 @@ attempt the checkout for all registered files beneath it."
                  file
                  (if (vc-rcs-latest-on-branch-p file new-version)
                      (if (vc-rcs-trunk-p new-version) nil
-                       (vc-branch-part new-version))
+                       (vc-rcs-branch-part new-version))
                    new-version)))))
        (message "Checking out %s...done" file))))))
 
@@ -456,17 +468,17 @@ revert all registered files beneath it."
      ((string= first-revision "")
       (error "A starting RCS revision is required"))
      (t
-      (if (not (vc-branch-p first-revision))
+      (if (not (vc-rcs-branch-p first-revision))
          (setq second-revision
                (vc-read-revision
                 "Second RCS revision: "
                 (list file) 'RCS nil
-                (concat (vc-branch-part first-revision) ".")))
+                (concat (vc-rcs-branch-part first-revision) ".")))
        ;; We want to merge an entire branch.  Set revisions
        ;; accordingly, so that vc-rcs-merge understands us.
        (setq second-revision first-revision)
        ;; first-revision must be the starting point of the branch
-       (setq first-revision (vc-branch-part first-revision)))))
+       (setq first-revision (vc-rcs-branch-part first-revision)))))
     (vc-rcs-merge file first-revision second-revision)))
 
 (defun vc-rcs-merge (file first-version &optional second-version)
@@ -637,11 +649,11 @@ Optional arg REVISION is a revision to annotate from."
     ;; Find which branches (if any) must be included in the edits.
     (let ((par revision)
           bpt kids)
-      (while (setq bpt (vc-branch-part par)
-                   par (vc-branch-part bpt))
+      (while (setq bpt (vc-rcs-branch-part par)
+                   par (vc-rcs-branch-part bpt))
         (setq kids (cdr (assq 'branches (cdr (assoc par revisions)))))
         ;; A branchpoint may have multiple children.  Find the right one.
-        (while (not (string= bpt (vc-branch-part (car kids))))
+        (while (not (string= bpt (vc-rcs-branch-part (car kids))))
           (setq kids (cdr kids)))
         (push (cons par (car kids)) nbls)))
     ;; Start with the full text.
@@ -818,7 +830,7 @@ systime, or nil if there is none.  Also, reposition point."
 or nil if there is no previous revision.  This default
 implementation works for MAJOR.MINOR-style revision numbers as
 used by RCS and CVS."
-  (let ((branch (vc-branch-part rev))
+  (let ((branch (vc-rcs-branch-part rev))
         (minor-num (string-to-number (vc-rcs-minor-part rev))))
     (when branch
       (if (> minor-num 1)
@@ -830,7 +842,7 @@ used by RCS and CVS."
             nil
           ;; we are at the beginning of a branch --
           ;; return revision of starting point
-          (vc-branch-part branch))))))
+          (vc-rcs-branch-part branch))))))
 
 (defun vc-rcs-next-revision (file rev)
   "Return the revision number immediately following REV for FILE,
@@ -838,7 +850,7 @@ or nil if there is no next revision.  This default 
implementation
 works for MAJOR.MINOR-style revision numbers as used by RCS
 and CVS."
   (when (not (string= rev (vc-working-revision file)))
-    (let ((branch (vc-branch-part rev))
+    (let ((branch (vc-rcs-branch-part rev))
          (minor-num (string-to-number (vc-rcs-minor-part rev))))
       (concat branch "." (number-to-string (1+ minor-num))))))
 
@@ -965,7 +977,7 @@ to its master version."
          (setq latest-rev rev)
          (setq value (match-string 1)))))
     (or value
-       (vc-branch-part branch))))
+       (vc-rcs-branch-part branch))))
 
 (defun vc-rcs-fetch-master-state (file &optional working-revision)
   "Compute the master file's idea of the state of FILE.
diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el
index e2b12c6..f6ae270 100644
--- a/lisp/vc/vc.el
+++ b/lisp/vc/vc.el
@@ -860,7 +860,9 @@ See `run-hooks'."
 
 (defcustom vc-revert-show-diff t
   "If non-nil, `vc-revert' shows a `vc-diff' buffer before querying."
-  :type 'boolean
+  :type '(choice (const :tag "Show and bury afterwards" t)
+                 (const :tag "Show and kill afterwards" kill)
+                 (const :tag "Don't show" nil))
   :version "24.1")
 
 ;; Header-insertion hair
@@ -2055,9 +2057,9 @@ saving the buffer."
       ;; here, this way the *vc-diff* buffer is setup correctly, so
       ;; relative file names work.
       (let ((default-directory rootdir))
-       (vc-diff-internal
-        t (list backend (list rootdir) working-revision) nil nil
-        (called-interactively-p 'interactive))))))
+        (vc-diff-internal
+         t (list backend (list rootdir) working-revision) nil nil
+         (called-interactively-p 'interactive))))))
 
 ;;;###autoload
 (defun vc-root-dir ()
@@ -2603,8 +2605,8 @@ with its diffs (if the underlying VCS supports that)."
       (setq backend (vc-responsible-backend rootdir))
       (unless backend
         (error "Directory is not version controlled")))
-    (setq default-directory (expand-file-name rootdir))
-    (vc-print-log-internal backend (list default-directory) revision revision 
limit
+    (setq default-directory rootdir)
+    (vc-print-log-internal backend (list rootdir) revision revision limit
                            (when with-diff 'with-diff))))
 
 ;;;###autoload
@@ -2757,7 +2759,7 @@ to the working revision (except for keyword expansion)."
                                       (if (= nfiles 1) "" "s"))))))
            (error "Revert canceled")))
       (when diff-buffer
-       (quit-windows-on diff-buffer)))
+       (quit-windows-on diff-buffer (eq vc-revert-show-diff 'kill))))
     (dolist (file files)
       (message "Reverting %s..." (vc-delistify files))
       (vc-revert-file file)
@@ -3072,20 +3074,6 @@ log entries should be gathered."
   (vc-call-backend (vc-responsible-backend default-directory)
                    'update-changelog args))
 
-;; functions that operate on RCS revision numbers.  This code should
-;; also be moved into the backends.  It stays for now, however, since
-;; it is used in code below.
-(defun vc-branch-p (rev)
-  "Return t if REV is a branch revision."
-  (not (eq nil (string-match "\\`[0-9]+\\(\\.[0-9]+\\.[0-9]+\\)*\\'" rev))))
-
-;;;###autoload
-(defun vc-branch-part (rev)
-  "Return the branch part of a revision number REV."
-  (let ((index (string-match "\\.[0-9]+\\'" rev)))
-    (when index
-      (substring rev 0 index))))
-
 (defun vc-default-responsible-p (_backend _file)
   "Indicate whether BACKEND is responsible for FILE.
 The default is to return nil always."
diff --git a/lisp/whitespace.el b/lisp/whitespace.el
index a2dc6ab..a3a1274 100644
--- a/lisp/whitespace.el
+++ b/lisp/whitespace.el
@@ -924,7 +924,10 @@ Any other value is treated as nil."
   "Toggle whitespace visualization (Whitespace mode).
 
 See also `whitespace-style', `whitespace-newline' and
-`whitespace-display-mappings'."
+`whitespace-display-mappings'.
+
+This mode uses a number of faces to visualize the whitespace; see
+the customization group `whitespace' for details."
   :lighter    " ws"
   :init-value nil
   :global     nil
diff --git a/lisp/windmove.el b/lisp/windmove.el
index f747c40..ef970bb 100644
--- a/lisp/windmove.el
+++ b/lisp/windmove.el
@@ -170,7 +170,7 @@ placement bugs in old versions of Emacs."
 
 (defcustom windmove-allow-all-windows nil
   "Whether the windmove commands are allowed to target all type of windows.
-If this variable is set to non-nil, all windmove commmands will
+If this variable is set to non-nil, all windmove commands will
 ignore the `no-other-window' parameter applied by `display-buffer-alist'
 or `set-window-parameter'."
   :type 'boolean
diff --git a/lisp/window.el b/lisp/window.el
index 0346397..e14d472 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -4721,8 +4721,8 @@ This function is called by `prev-buffer'."
               window new-buffer (nth 1 entry) (nth 2 entry))
              (throw 'found t)))))
 
-      (when skipped
-        ;; Show first skipped buffer.
+      (when (and skipped (not (functionp switch-to-prev-buffer-skip)))
+        ;; Show first skipped buffer, unless skip was a function.
        (setq new-buffer skipped)
        (set-window-buffer-start-and-point window new-buffer)))
 
@@ -4831,6 +4831,7 @@ This function is called by `next-buffer'."
       ;; nreverse here!)
       (dolist (entry (reverse (window-prev-buffers window)))
        (when (and (not (eq new-buffer (car entry)))
+                   (not (eq old-buffer (car entry)))
                    (setq new-buffer (car entry))
                   (or (buffer-live-p new-buffer)
                       (not (setq killed-buffers
@@ -4842,8 +4843,8 @@ This function is called by `next-buffer'."
             window new-buffer (nth 1 entry) (nth 2 entry))
            (throw 'found t))))
 
-      (when skipped
-        ;; Show first skipped buffer.
+      (when (and skipped (not (functionp switch-to-prev-buffer-skip)))
+        ;; Show first skipped buffer, unless skip was a function.
        (setq new-buffer skipped)
        (set-window-buffer-start-and-point window new-buffer)))
 
diff --git a/lisp/xwidget.el b/lisp/xwidget.el
index b8df550..f8cb7a7 100644
--- a/lisp/xwidget.el
+++ b/lisp/xwidget.el
@@ -95,9 +95,7 @@ NEW-SESSION specifies whether to create a new xwidget-webkit 
session.
 Interactively, URL defaults to the string looking like a url around point."
   (interactive (progn
                  (require 'browse-url)
-                 (browse-url-interactive-arg "xwidget-webkit URL: "
-                                             ;;(xwidget-webkit-current-url)
-                                             )))
+                 (browse-url-interactive-arg "xwidget-webkit URL: ")))
   (or (featurep 'xwidget-internal)
       (user-error "Your Emacs was not compiled with xwidgets support"))
   (when (stringp url)
@@ -112,7 +110,7 @@ Interactively, URL defaults to the string looking like a 
url around point."
   "Clone current URL into a new widget place in new window below.
 Get the URL of current session, then browse to the URL
 in `split-window-below' with a new xwidget webkit session."
-  (interactive)
+  (interactive nil xwidget-webkit-mode)
   (let ((url (xwidget-webkit-current-url)))
     (with-selected-window (split-window-below)
       (xwidget-webkit-new-session url))))
@@ -121,7 +119,7 @@ in `split-window-below' with a new xwidget webkit session."
   "Clone current URL into a new widget place in new window right.
 Get the URL of current session, then browse to the URL
 in `split-window-right' with a new xwidget webkit session."
-  (interactive)
+  (interactive nil xwidget-webkit-mode)
   (let ((url (xwidget-webkit-current-url)))
     (with-selected-window (split-window-right)
       (xwidget-webkit-new-session url))))
@@ -168,12 +166,12 @@ in `split-window-right' with a new xwidget webkit 
session."
 
 (defun xwidget-webkit-zoom-in ()
   "Increase webkit view zoom factor."
-  (interactive)
+  (interactive nil xwidget-webkit-mode)
   (xwidget-webkit-zoom (xwidget-webkit-current-session) 0.1))
 
 (defun xwidget-webkit-zoom-out ()
   "Decrease webkit view zoom factor."
-  (interactive)
+  (interactive nil xwidget-webkit-mode)
   (xwidget-webkit-zoom (xwidget-webkit-current-session) -0.1))
 
 (defun xwidget-webkit-scroll-up (&optional arg)
@@ -181,7 +179,7 @@ in `split-window-right' with a new xwidget webkit session."
 Stop if bottom of page is reached.
 Interactively, ARG is the prefix numeric argument.
 Negative ARG scrolls down."
-  (interactive "P")
+  (interactive "P" xwidget-webkit-mode)
   (xwidget-webkit-execute-script
    (xwidget-webkit-current-session)
    (format "window.scrollBy(0, %d);"
@@ -192,7 +190,7 @@ Negative ARG scrolls down."
 Stop if top of page is reached.
 Interactively, ARG is the prefix numeric argument.
 Negative ARG scrolls up."
-  (interactive "P")
+  (interactive "P" xwidget-webkit-mode)
   (xwidget-webkit-execute-script
    (xwidget-webkit-current-session)
    (format "window.scrollBy(0, -%d);"
@@ -203,7 +201,7 @@ Negative ARG scrolls up."
 The height of line is calculated with `window-font-height'.
 Stop if the bottom edge of the page is reached.
 If N is omitted or nil, scroll up by one line."
-  (interactive "p")
+  (interactive "p" xwidget-webkit-mode)
   (xwidget-webkit-scroll-up (* n (window-font-height))))
 
 (defun xwidget-webkit-scroll-down-line (&optional n)
@@ -211,14 +209,14 @@ If N is omitted or nil, scroll up by one line."
 The height of line is calculated with `window-font-height'.
 Stop if the top edge of the page is reached.
 If N is omitted or nil, scroll down by one line."
-  (interactive "p")
+  (interactive "p" xwidget-webkit-mode)
   (xwidget-webkit-scroll-down (* n (window-font-height))))
 
 (defun xwidget-webkit-scroll-forward (&optional n)
   "Scroll webkit horizontally by N chars.
 The width of char is calculated with `window-font-width'.
 If N is omitted or nil, scroll forwards by one char."
-  (interactive "p")
+  (interactive "p" xwidget-webkit-mode)
   (xwidget-webkit-execute-script
    (xwidget-webkit-current-session)
    (format "window.scrollBy(%d, 0);"
@@ -228,7 +226,7 @@ If N is omitted or nil, scroll forwards by one char."
   "Scroll webkit back by N chars.
 The width of char is calculated with `window-font-width'.
 If N is omitted or nil, scroll backwards by one char."
-  (interactive "p")
+  (interactive "p" xwidget-webkit-mode)
   (xwidget-webkit-execute-script
    (xwidget-webkit-current-session)
    (format "window.scrollBy(-%d, 0);"
@@ -236,14 +234,14 @@ If N is omitted or nil, scroll backwards by one char."
 
 (defun xwidget-webkit-scroll-top ()
   "Scroll webkit to the very top."
-  (interactive)
+  (interactive nil xwidget-webkit-mode)
   (xwidget-webkit-execute-script
    (xwidget-webkit-current-session)
    "window.scrollTo(pageXOffset, 0);"))
 
 (defun xwidget-webkit-scroll-bottom ()
   "Scroll webkit to the very bottom."
-  (interactive)
+  (interactive nil xwidget-webkit-mode)
   (xwidget-webkit-execute-script
    (xwidget-webkit-current-session)
    "window.scrollTo(pageXOffset, window.document.body.scrollHeight);"))
@@ -261,7 +259,7 @@ If N is omitted or nil, scroll backwards by one char."
 
 (defun xwidget-event-handler ()
   "Receive xwidget event."
-  (interactive)
+  (interactive nil xwidget-webkit-mode)
   (xwidget-log "stuff happened to xwidget %S" last-input-event)
   (let*
       ((xwidget-event-type (nth 1 last-input-event))
@@ -302,12 +300,14 @@ XWIDGET instance, XWIDGET-EVENT-TYPE depends on the 
originating xwidget."
 
 (defvar bookmark-make-record-function)
 (when (memq window-system '(mac ns))
-  (defvar xwidget-webkit-enable-plugins nil
+  (defcustom xwidget-webkit-enable-plugins nil
     "Enable plugins for xwidget webkit.
-If non-nil, plugins are enabled.  Otherwise, disabled."))
+If non-nil, plugins are enabled.  Otherwise, disabled."
+    :type 'boolean
+    :version "28.1"))
 
-(define-derived-mode xwidget-webkit-mode
-  special-mode "xwidget-webkit" "Xwidget webkit view mode."
+(define-derived-mode xwidget-webkit-mode special-mode "xwidget-webkit"
+  "Xwidget webkit view mode."
   (setq buffer-read-only t)
   (setq-local bookmark-make-record-function
               #'xwidget-webkit-bookmark-make-record)
@@ -420,7 +420,7 @@ function findactiveelement(doc){
 (defun xwidget-webkit-insert-string ()
   "Insert string into the active field in the current webkit widget."
   ;; Read out the string in the field first and provide for edit.
-  (interactive)
+  (interactive nil xwidget-webkit-mode)
   ;; As the prompt differs on JavaScript execution results,
   ;; the function must handle the prompt itself.
   (let ((xww (xwidget-webkit-current-session)))
@@ -456,7 +456,7 @@ XW is the xwidget identifier, TEXT is retrieved from the 
webkit."
 
 (defun xwidget-webkit-end-edit-textarea ()
   "End editing of a webkit text area."
-  (interactive)
+  (interactive nil xwidget-webkit-mode)
   (goto-char (point-min))
   (while (search-forward "\n" nil t)
     (replace-match "\\n" nil t))
@@ -472,7 +472,8 @@ XW is the xwidget identifier, TEXT is retrieved from the 
webkit."
 The ELEMENT-SELECTOR must be a valid CSS selector.  For example,
 use this to display an anchor."
   (interactive (list (xwidget-webkit-current-session)
-                     (read-string "Element selector: ")))
+                     (read-string "Element selector: "))
+               xwidget-webkit-mode)
   (xwidget-webkit-execute-script
    xw
    (format "
@@ -488,7 +489,8 @@ use this to display an anchor."
   "Make webkit xwidget XW show a named element ELEMENT-NAME.
 For example, use this to display an anchor."
   (interactive (list (xwidget-webkit-current-session)
-                     (read-string "Element name: ")))
+                     (read-string "Element name: "))
+               xwidget-webkit-mode)
   ;; TODO: This needs to be interfaced into browse-url somehow.  The
   ;; tricky part is that we need to do this in two steps: A: load the
   ;; base url, wait for load signal to arrive B: navigate to the
@@ -508,7 +510,8 @@ For example, use this to display an anchor."
   "Make webkit xwidget XW show an id-element ELEMENT-ID.
 For example, use this to display an anchor."
   (interactive (list (xwidget-webkit-current-session)
-                     (read-string "Element id: ")))
+                     (read-string "Element id: "))
+               xwidget-webkit-mode)
   (xwidget-webkit-execute-script
    xw
    (format "
@@ -524,7 +527,8 @@ For example, use this to display an anchor."
    "Make webkit xwidget XW show a name or element id ELEMENT-ID.
 For example, use this to display an anchor."
   (interactive (list (xwidget-webkit-current-session)
-                     (read-string "Name or element id: ")))
+                     (read-string "Name or element id: "))
+               xwidget-webkit-mode)
   (xwidget-webkit-execute-script
    xw
    (format "
@@ -539,12 +543,12 @@ For example, use this to display an anchor."
 
 (defun xwidget-webkit-adjust-size-to-content ()
   "Adjust webkit to content size."
-  (interactive)
+  (interactive nil xwidget-webkit-mode)
   (xwidget-adjust-size-to-content (xwidget-webkit-current-session)))
 
 (defun xwidget-webkit-adjust-size-dispatch ()
   "Adjust size according to mode."
-  (interactive)
+  (interactive nil xwidget-webkit-mode)
   (xwidget-webkit-adjust-size-to-window (xwidget-webkit-current-session))
   ;; The recenter is intended to correct a visual glitch.
   ;; It errors out if the buffer isn't visible, but then we don't get
@@ -573,12 +577,12 @@ For example, use this to display an anchor."
 (defun xwidget-webkit-adjust-size (w h)
   "Manually set webkit size to width W, height H."
   ;; TODO shouldn't be tied to the webkit xwidget
-  (interactive "nWidth:\nnHeight:\n")
+  (interactive "nWidth:\nnHeight:\n" xwidget-webkit-mode)
   (xwidget-resize (xwidget-webkit-current-session) w h))
 
 (defun xwidget-webkit-fit-width ()
   "Adjust width of webkit to window width."
-  (interactive)
+  (interactive nil xwidget-webkit-mode)
   (xwidget-webkit-adjust-size (- (nth 2 (window-inside-pixel-edges))
                                  (car (window-inside-pixel-edges)))
                               1000))
@@ -630,22 +634,22 @@ For example, use this to display an anchor."
 
 (defun xwidget-webkit-back ()
   "Go back to previous URL in xwidget webkit buffer."
-  (interactive)
+  (interactive nil xwidget-webkit-mode)
   (xwidget-webkit-goto-history (xwidget-webkit-current-session) -1))
 
 (defun xwidget-webkit-forward ()
   "Go forward in history."
-  (interactive)
+  (interactive nil xwidget-webkit-mode)
   (xwidget-webkit-goto-history (xwidget-webkit-current-session) 1))
 
 (defun xwidget-webkit-reload ()
   "Reload current URL."
-  (interactive)
+  (interactive nil xwidget-webkit-mode)
   (xwidget-webkit-goto-history (xwidget-webkit-current-session) 0))
 
 (defun xwidget-webkit-current-url ()
   "Display the current xwidget webkit URL and place it on the `kill-ring'."
-  (interactive)
+  (interactive nil xwidget-webkit-mode)
   (let ((url (xwidget-webkit-uri (xwidget-webkit-current-session))))
     (message "URL: %s" (kill-new (or url "")))))
 
@@ -659,7 +663,7 @@ For example, use this to display an anchor."
 
 (defun xwidget-webkit-copy-selection-as-kill ()
   "Get the webkit selection and put it on the `kill-ring'."
-  (interactive)
+  (interactive nil xwidget-webkit-mode)
   (xwidget-webkit-get-selection #'kill-new))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/oldXMenu/Activate.c b/oldXMenu/Activate.c
index 91439ea..8ffa817 100644
--- a/oldXMenu/Activate.c
+++ b/oldXMenu/Activate.c
@@ -1,6 +1,24 @@
 /* Copyright    Massachusetts Institute of Technology    1985  */
 
-#include "copyright.h"
+/*
+
+Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+M.I.T. makes no representations about the suitability of
+this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+*/
+
+
 
 /*
 Copyright (C) 2001-2021 Free Software Foundation, Inc.
diff --git a/oldXMenu/AddPane.c b/oldXMenu/AddPane.c
index e7246f2..b14b3e8 100644
--- a/oldXMenu/AddPane.c
+++ b/oldXMenu/AddPane.c
@@ -1,6 +1,24 @@
 /* Copyright    Massachusetts Institute of Technology    1985  */
 
-#include "copyright.h"
+/*
+
+Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+M.I.T. makes no representations about the suitability of
+this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+*/
+
+
 
 /*
  * XMenu:      MIT Project Athena, X Window system menu package
diff --git a/oldXMenu/AddSel.c b/oldXMenu/AddSel.c
index 2a52a6a..9596cae 100644
--- a/oldXMenu/AddSel.c
+++ b/oldXMenu/AddSel.c
@@ -1,6 +1,24 @@
 /* Copyright    Massachusetts Institute of Technology    1985  */
 
-#include "copyright.h"
+/*
+
+Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+M.I.T. makes no representations about the suitability of
+this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+*/
+
+
 
 
 /*
diff --git a/oldXMenu/ChgPane.c b/oldXMenu/ChgPane.c
index 733f659..c9c4a5e 100644
--- a/oldXMenu/ChgPane.c
+++ b/oldXMenu/ChgPane.c
@@ -1,6 +1,24 @@
 /* Copyright    Massachusetts Institute of Technology    1985  */
 
-#include "copyright.h"
+/*
+
+Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+M.I.T. makes no representations about the suitability of
+this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+*/
+
+
 
 
 /*
diff --git a/oldXMenu/ChgSel.c b/oldXMenu/ChgSel.c
index 5a46b5c..c26781b 100644
--- a/oldXMenu/ChgSel.c
+++ b/oldXMenu/ChgSel.c
@@ -1,6 +1,24 @@
 /* Copyright    Massachusetts Institute of Technology    1985  */
 
-#include "copyright.h"
+/*
+
+Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+M.I.T. makes no representations about the suitability of
+this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+*/
+
+
 
 
 /*
diff --git a/oldXMenu/Create.c b/oldXMenu/Create.c
index e209bbe..2077a71 100644
--- a/oldXMenu/Create.c
+++ b/oldXMenu/Create.c
@@ -1,6 +1,24 @@
 /* Copyright    Massachusetts Institute of Technology    1985  */
 
-#include "copyright.h"
+/*
+
+Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+M.I.T. makes no representations about the suitability of
+this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+*/
+
+
 
 /*
 Copyright (C) 1993-1994, 2001-2021 Free Software Foundation, Inc.
diff --git a/oldXMenu/DelPane.c b/oldXMenu/DelPane.c
index 10234e0..37a2095 100644
--- a/oldXMenu/DelPane.c
+++ b/oldXMenu/DelPane.c
@@ -1,6 +1,24 @@
 /* Copyright    Massachusetts Institute of Technology    1985  */
 
-#include "copyright.h"
+/*
+
+Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+M.I.T. makes no representations about the suitability of
+this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+*/
+
+
 
 
 /*
diff --git a/oldXMenu/DelSel.c b/oldXMenu/DelSel.c
index ca2ea28..47cc168 100644
--- a/oldXMenu/DelSel.c
+++ b/oldXMenu/DelSel.c
@@ -1,6 +1,24 @@
 /* Copyright    Massachusetts Institute of Technology    1985  */
 
-#include "copyright.h"
+/*
+
+Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+M.I.T. makes no representations about the suitability of
+this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+*/
+
+
 
 
 /*
diff --git a/oldXMenu/Destroy.c b/oldXMenu/Destroy.c
index 7f0f614..fdaa69b 100644
--- a/oldXMenu/Destroy.c
+++ b/oldXMenu/Destroy.c
@@ -1,6 +1,24 @@
 /* Copyright    Massachusetts Institute of Technology    1985  */
 
-#include "copyright.h"
+/*
+
+Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+M.I.T. makes no representations about the suitability of
+this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+*/
+
+
 
 
 /*
diff --git a/oldXMenu/Error.c b/oldXMenu/Error.c
index 0173845..b49e172 100644
--- a/oldXMenu/Error.c
+++ b/oldXMenu/Error.c
@@ -1,6 +1,24 @@
 /* Copyright    Massachusetts Institute of Technology    1985  */
 
-#include "copyright.h"
+/*
+
+Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+M.I.T. makes no representations about the suitability of
+this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+*/
+
+
 
 
 /*
diff --git a/oldXMenu/EvHand.c b/oldXMenu/EvHand.c
index bd15359..94789c2 100644
--- a/oldXMenu/EvHand.c
+++ b/oldXMenu/EvHand.c
@@ -1,6 +1,24 @@
 /* Copyright    Massachusetts Institute of Technology    1985  */
 
-#include "copyright.h"
+/*
+
+Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+M.I.T. makes no representations about the suitability of
+this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+*/
+
+
 
 
 /*
diff --git a/oldXMenu/FindPane.c b/oldXMenu/FindPane.c
index 8101d00..3e76321 100644
--- a/oldXMenu/FindPane.c
+++ b/oldXMenu/FindPane.c
@@ -1,6 +1,24 @@
 /* Copyright    Massachusetts Institute of Technology    1985  */
 
-#include "copyright.h"
+/*
+
+Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+M.I.T. makes no representations about the suitability of
+this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+*/
+
+
 
 
 /*
diff --git a/oldXMenu/FindSel.c b/oldXMenu/FindSel.c
index e2a5dbb..53d1405 100644
--- a/oldXMenu/FindSel.c
+++ b/oldXMenu/FindSel.c
@@ -1,6 +1,24 @@
 /* Copyright    Massachusetts Institute of Technology    1985  */
 
-#include "copyright.h"
+/*
+
+Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+M.I.T. makes no representations about the suitability of
+this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+*/
+
+
 
 /*
 Copyright (C) 2001-2021 Free Software Foundation, Inc.
diff --git a/oldXMenu/InsPane.c b/oldXMenu/InsPane.c
index da92f49..89253e1 100644
--- a/oldXMenu/InsPane.c
+++ b/oldXMenu/InsPane.c
@@ -1,6 +1,24 @@
 /* Copyright    Massachusetts Institute of Technology    1985  */
 
-#include "copyright.h"
+/*
+
+Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+M.I.T. makes no representations about the suitability of
+this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+*/
+
+
 
 
 /*
diff --git a/oldXMenu/InsSel.c b/oldXMenu/InsSel.c
index f538043..527a7a0 100644
--- a/oldXMenu/InsSel.c
+++ b/oldXMenu/InsSel.c
@@ -1,6 +1,24 @@
 /* Copyright    Massachusetts Institute of Technology    1985  */
 
-#include "copyright.h"
+/*
+
+Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+M.I.T. makes no representations about the suitability of
+this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+*/
+
+
 
 
 /*
diff --git a/oldXMenu/Internal.c b/oldXMenu/Internal.c
index 3e97f9a..476336c 100644
--- a/oldXMenu/Internal.c
+++ b/oldXMenu/Internal.c
@@ -1,6 +1,24 @@
 /* Copyright    Massachusetts Institute of Technology    1985  */
 
-#include "copyright.h"
+/*
+
+Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+M.I.T. makes no representations about the suitability of
+this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+*/
+
+
 
 /*
 Copyright (C) 1993, 1996, 2001-2021 Free Software Foundation, Inc.
diff --git a/oldXMenu/Locate.c b/oldXMenu/Locate.c
index 1605b4b..bd12666 100644
--- a/oldXMenu/Locate.c
+++ b/oldXMenu/Locate.c
@@ -1,6 +1,24 @@
 /* Copyright    Massachusetts Institute of Technology    1985  */
 
-#include "copyright.h"
+/*
+
+Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+M.I.T. makes no representations about the suitability of
+this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+*/
+
+
 
 
 /*
diff --git a/oldXMenu/Post.c b/oldXMenu/Post.c
index e78fedc..5247736 100644
--- a/oldXMenu/Post.c
+++ b/oldXMenu/Post.c
@@ -1,6 +1,24 @@
 /* Copyright    Massachusetts Institute of Technology    1985  */
 
-#include "copyright.h"
+/*
+
+Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+M.I.T. makes no representations about the suitability of
+this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+*/
+
+
 
 
 /*
diff --git a/oldXMenu/Recomp.c b/oldXMenu/Recomp.c
index 2aec87a..5c129fc 100644
--- a/oldXMenu/Recomp.c
+++ b/oldXMenu/Recomp.c
@@ -1,6 +1,24 @@
 /* Copyright    Massachusetts Institute of Technology    1985  */
 
-#include "copyright.h"
+/*
+
+Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+M.I.T. makes no representations about the suitability of
+this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+*/
+
+
 
 
 /*
diff --git a/oldXMenu/SetAEQ.c b/oldXMenu/SetAEQ.c
index ee2d64b..57debf0 100644
--- a/oldXMenu/SetAEQ.c
+++ b/oldXMenu/SetAEQ.c
@@ -1,6 +1,24 @@
 /* Copyright    Massachusetts Institute of Technology    1985  */
 
-#include "copyright.h"
+/*
+
+Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+M.I.T. makes no representations about the suitability of
+this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+*/
+
+
 
 
 /*
diff --git a/oldXMenu/SetFrz.c b/oldXMenu/SetFrz.c
index c8998ee..eb54dd6 100644
--- a/oldXMenu/SetFrz.c
+++ b/oldXMenu/SetFrz.c
@@ -1,6 +1,24 @@
 /* Copyright    Massachusetts Institute of Technology    1985  */
 
-#include "copyright.h"
+/*
+
+Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+M.I.T. makes no representations about the suitability of
+this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+*/
+
+
 
 
 /*
diff --git a/oldXMenu/SetPane.c b/oldXMenu/SetPane.c
index f29a81c..b43c777 100644
--- a/oldXMenu/SetPane.c
+++ b/oldXMenu/SetPane.c
@@ -1,6 +1,24 @@
 /* Copyright    Massachusetts Institute of Technology    1985  */
 
-#include "copyright.h"
+/*
+
+Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+M.I.T. makes no representations about the suitability of
+this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+*/
+
+
 
 
 /*
diff --git a/oldXMenu/SetSel.c b/oldXMenu/SetSel.c
index 2f950d4..251b5f9 100644
--- a/oldXMenu/SetSel.c
+++ b/oldXMenu/SetSel.c
@@ -1,6 +1,24 @@
 /* Copyright    Massachusetts Institute of Technology    1985  */
 
-#include "copyright.h"
+/*
+
+Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+M.I.T. makes no representations about the suitability of
+this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+*/
+
+
 
 
 /*
diff --git a/oldXMenu/XCrAssoc.c b/oldXMenu/XCrAssoc.c
index 7150cbc..e017cbb 100644
--- a/oldXMenu/XCrAssoc.c
+++ b/oldXMenu/XCrAssoc.c
@@ -1,5 +1,23 @@
 /* Copyright    Massachusetts Institute of Technology    1985  */
-#include "copyright.h"
+/*
+
+Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+M.I.T. makes no representations about the suitability of
+this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+*/
+
+
 
 
 #include <config.h>
diff --git a/oldXMenu/XDelAssoc.c b/oldXMenu/XDelAssoc.c
index ec1d09d..26a635e 100644
--- a/oldXMenu/XDelAssoc.c
+++ b/oldXMenu/XDelAssoc.c
@@ -1,6 +1,24 @@
 /* Copyright    Massachusetts Institute of Technology    1985  */
 
-#include "copyright.h"
+/*
+
+Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+M.I.T. makes no representations about the suitability of
+this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+*/
+
+
 
 #include "XMenuInt.h"
 
diff --git a/oldXMenu/XDestAssoc.c b/oldXMenu/XDestAssoc.c
index 94c0454..7306944 100644
--- a/oldXMenu/XDestAssoc.c
+++ b/oldXMenu/XDestAssoc.c
@@ -1,6 +1,24 @@
 /* Copyright    Massachusetts Institute of Technology    1985  */
 
-#include "copyright.h"
+/*
+
+Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+M.I.T. makes no representations about the suitability of
+this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+*/
+
+
 
 #include "XMenuInt.h"
 
diff --git a/oldXMenu/XLookAssoc.c b/oldXMenu/XLookAssoc.c
index fad960d..577e63f 100644
--- a/oldXMenu/XLookAssoc.c
+++ b/oldXMenu/XLookAssoc.c
@@ -1,6 +1,24 @@
 /* Copyright    Massachusetts Institute of Technology    1985  */
 
-#include "copyright.h"
+/*
+
+Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+M.I.T. makes no representations about the suitability of
+this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+*/
+
+
 
 #include <config.h>
 #include <X11/Xlib.h>
diff --git a/oldXMenu/XMakeAssoc.c b/oldXMenu/XMakeAssoc.c
index 2530e8e..256d4eb 100644
--- a/oldXMenu/XMakeAssoc.c
+++ b/oldXMenu/XMakeAssoc.c
@@ -1,6 +1,24 @@
 /* Copyright    Massachusetts Institute of Technology    1985  */
 
-#include "copyright.h"
+/*
+
+Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+M.I.T. makes no representations about the suitability of
+this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+*/
+
+
 
 
 #include "XMenuInt.h"
diff --git a/oldXMenu/XMenu.h b/oldXMenu/XMenu.h
index 8e4292f..50ea683 100644
--- a/oldXMenu/XMenu.h
+++ b/oldXMenu/XMenu.h
@@ -1,6 +1,24 @@
 /* Copyright    Massachusetts Institute of Technology    1985  */
 
-#include "copyright.h"
+/*
+
+Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+M.I.T. makes no representations about the suitability of
+this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+*/
+
+
 
 
 /*
diff --git a/oldXMenu/XMenuInt.h b/oldXMenu/XMenuInt.h
index 369b8c1..86b8e05 100644
--- a/oldXMenu/XMenuInt.h
+++ b/oldXMenu/XMenuInt.h
@@ -1,6 +1,24 @@
 /* Copyright    Massachusetts Institute of Technology    1985  */
 
-#include "copyright.h"
+/*
+
+Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+M.I.T. makes no representations about the suitability of
+this software for any purpose.  It is provided "as is"
+without express or implied warranty.
+
+*/
+
+
 
 
 /*
diff --git a/src/buffer.c b/src/buffer.c
index 7e4c849..4eb7ab6 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -1768,6 +1768,7 @@ cleaning up all windows currently displaying the buffer 
to be killed. */)
   /* Run hooks with the buffer to be killed as the current buffer.  */
   {
     ptrdiff_t count = SPECPDL_INDEX ();
+    bool modified;
 
     record_unwind_protect_excursion ();
     set_buffer_internal (b);
@@ -1782,9 +1783,12 @@ cleaning up all windows currently displaying the buffer 
to be killed. */)
          return unbind_to (count, Qnil);
       }
 
+    /* Is this a modified buffer that's visiting a file? */
+    modified = !NILP (BVAR (b, filename))
+      && BUF_MODIFF (b) > BUF_SAVE_MODIFF (b);
+
     /* Query if the buffer is still modified.  */
-    if (INTERACTIVE && !NILP (BVAR (b, filename))
-       && BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
+    if (INTERACTIVE && modified)
       {
        AUTO_STRING (format, "Buffer %s modified; kill anyway? ");
        tem = do_yes_or_no_p (CALLN (Fformat, format, BVAR (b, name)));
@@ -1792,6 +1796,23 @@ cleaning up all windows currently displaying the buffer 
to be killed. */)
          return unbind_to (count, Qnil);
       }
 
+    /* Delete the autosave file, if requested. */
+    if (modified
+       && kill_buffer_delete_auto_save_files
+       && delete_auto_save_files
+       && !NILP (Frecent_auto_save_p ())
+       && STRINGP (BVAR (b, auto_save_file_name))
+       && !NILP (Ffile_exists_p (BVAR (b, auto_save_file_name)))
+       /* If `auto-save-visited-mode' is on, then we're auto-saving
+          to the visited file -- don't delete it.. */
+       && NILP (Fstring_equal (BVAR (b, auto_save_file_name),
+                               BVAR (b, filename))))
+      {
+       tem = do_yes_or_no_p (build_string ("Delete auto-save file? "));
+       if (!NILP (tem))
+         call0 (intern ("delete-auto-save-file-if-necessary"));
+      }
+
     /* If the hooks have killed the buffer, exit now.  */
     if (!BUFFER_LIVE_P (b))
       return unbind_to (count, Qt);
@@ -1888,24 +1909,6 @@ cleaning up all windows currently displaying the buffer 
to be killed. */)
   replace_buffer_in_windows_safely (buffer);
   Vinhibit_quit = tem;
 
-  /* Delete any auto-save file, if we saved it in this session.
-     But not if the buffer is modified.  */
-  if (STRINGP (BVAR (b, auto_save_file_name))
-      && BUF_AUTOSAVE_MODIFF (b) != 0
-      && BUF_SAVE_MODIFF (b) < BUF_AUTOSAVE_MODIFF (b)
-      && BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)
-      && NILP (Fsymbol_value (intern ("auto-save-visited-file-name"))))
-    {
-      Lisp_Object delete;
-      delete = Fsymbol_value (intern ("delete-auto-save-files"));
-      if (! NILP (delete))
-       internal_delete_file (BVAR (b, auto_save_file_name));
-    }
-
-  /* Deleting an auto-save file could have killed our buffer.  */
-  if (!BUFFER_LIVE_P (b))
-    return Qt;
-
   if (b->base_buffer)
     {
       INTERVAL i;
@@ -5802,7 +5805,10 @@ Note that this is overridden by the variable
 `truncate-partial-width-windows' if that variable is non-nil
 and this buffer is not full-frame width.
 
-Minibuffers set this variable to nil.  */);
+Minibuffers set this variable to nil.
+
+Don't set this to a non-nil value when `visual-line-mode' is
+turned on, as it could produce confusing results.   */);
 
   DEFVAR_PER_BUFFER ("word-wrap", &BVAR (current_buffer, word_wrap), Qnil,
                     doc: /* Non-nil means to use word-wrapping for 
continuation lines.
@@ -6366,6 +6372,18 @@ nil NORECORD argument since it may lead to infinite 
recursion.  */);
   Vbuffer_list_update_hook = Qnil;
   DEFSYM (Qbuffer_list_update_hook, "buffer-list-update-hook");
 
+  DEFVAR_BOOL ("kill-buffer-delete-auto-save-files",
+              kill_buffer_delete_auto_save_files,
+              doc: /* If non-nil, offer to delete any autosave file when 
killing a buffer.
+
+If `delete-auto-save-files' is nil, any autosave deletion is inhibited.  */);
+  kill_buffer_delete_auto_save_files = 0;
+
+  DEFVAR_BOOL ("delete-auto-save-files", delete_auto_save_files,
+              doc: /* Non-nil means delete auto-save file when a buffer is 
saved.
+This is the default.  If nil, auto-save file deletion is inhibited.  */);
+  delete_auto_save_files = 1;
+
   defsubr (&Sbuffer_live_p);
   defsubr (&Sbuffer_list);
   defsubr (&Sget_buffer);
diff --git a/src/callint.c b/src/callint.c
index 6f8a7f1..44dae36 100644
--- a/src/callint.c
+++ b/src/callint.c
@@ -606,7 +606,7 @@ invoke it (via an `interactive' spec that contains, for 
instance, an
          break;
 
        case 'e':               /* The invoking event.  */
-         if (next_event >= key_count)
+         if (!inhibit_mouse_event_check && next_event >= key_count)
            error ("%s must be bound to an event with parameters",
                   (SYMBOLP (function)
                    ? SSDATA (SYMBOL_NAME (function))
@@ -900,6 +900,14 @@ Its purpose is to give temporary modes such as Isearch mode
 a way to turn themselves off when a mouse command switches windows.  */);
   Vmouse_leave_buffer_hook = Qnil;
 
+  DEFVAR_BOOL ("inhibit-mouse-event-check", inhibit_mouse_event_check,
+    doc: /* Whether the interactive spec "e" requires a mouse gesture event.
+If non-nil, `(interactive "e")' doesn't signal an error when the command
+was invoked by an input event that is not a mouse gesture: a click, a drag,
+etc.  To create the event data when the input was some other event,
+use `event-start', `event-end', and `event-click-count'.  */);
+  inhibit_mouse_event_check = false;
+
   defsubr (&Sinteractive);
   defsubr (&Scall_interactively);
   defsubr (&Sfuncall_interactively);
diff --git a/src/callproc.c b/src/callproc.c
index 675b78d..fa43f97 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -232,6 +232,8 @@ directory where the process is run (see below).  If you 
want to make the
 input come from an Emacs buffer, use `call-process-region' instead.
 
 Third argument DESTINATION specifies how to handle program's output.
+(\"Output\" here means both standard output and standard error
+output.)
 If DESTINATION is a buffer, or t that stands for the current buffer,
  it means insert output in that buffer before point.
 If DESTINATION is nil, it means discard output; 0 means discard
diff --git a/src/coding.c b/src/coding.c
index 87b55ae..d027c7d 100644
--- a/src/coding.c
+++ b/src/coding.c
@@ -8250,6 +8250,39 @@ decode_coding_object (struct coding_system *coding,
 }
 
 
+/* Encode the text in the range FROM/FROM_BYTE and TO/TO_BYTE in
+   SRC_OBJECT into DST_OBJECT by coding context CODING.
+
+   SRC_OBJECT is a buffer, a string, or Qnil.
+
+   If it is a buffer, the text is at point of the buffer.  FROM and TO
+   are positions in the buffer.
+
+   If it is a string, the text is at the beginning of the string.
+   FROM and TO are indices into the string.
+
+   If it is nil, the text is at coding->source.  FROM and TO are
+   indices into coding->source.
+
+   DST_OBJECT is a buffer, Qt, or Qnil.
+
+   If it is a buffer, the encoded text is inserted at point of the
+   buffer.  If the buffer is the same as SRC_OBJECT, the source text
+   is replaced with the encoded text.
+
+   If it is Qt, a string is made from the encoded text, and set in
+   CODING->dst_object.  However, if CODING->raw_destination is non-zero,
+   the encoded text is instead returned in CODING->destination as a C string,
+   and the caller is responsible for freeing CODING->destination.  This
+   feature is meant to be used when the caller doesn't need the result as
+   a Lisp string, and wants to avoid unnecessary consing of large strings.
+
+   If it is Qnil, the encoded text is stored at CODING->destination.
+   The caller must allocate CODING->dst_bytes bytes at
+   CODING->destination by xmalloc.  If the encoded text is longer than
+   CODING->dst_bytes, CODING->destination is reallocated by xrealloc
+   (and CODING->dst_bytes is enlarged accordingly).  */
+
 void
 encode_coding_object (struct coding_system *coding,
                      Lisp_Object src_object,
@@ -8275,11 +8308,14 @@ encode_coding_object (struct coding_system *coding,
 
   attrs = CODING_ID_ATTRS (coding->id);
 
-  if (EQ (src_object, dst_object))
+  bool same_buffer = false;
+  if (EQ (src_object, dst_object) && BUFFERP (src_object))
     {
       struct Lisp_Marker *tail;
 
-      for (tail = BUF_MARKERS (current_buffer); tail; tail = tail->next)
+      same_buffer = true;
+
+      for (tail = BUF_MARKERS (XBUFFER (src_object)); tail; tail = tail->next)
        {
          tail->need_adjustment
            = tail->charpos == (tail->insertion_type ? from : to);
@@ -8298,7 +8334,7 @@ encode_coding_object (struct coding_system *coding,
       else
        insert_1_both ((char *) coding->source + from, chars, bytes, 0, 0, 0);
 
-      if (EQ (src_object, dst_object))
+      if (same_buffer)
        {
          set_buffer_internal (XBUFFER (src_object));
          saved_pt = PT, saved_pt_byte = PT_BYTE;
@@ -8329,7 +8365,7 @@ encode_coding_object (struct coding_system *coding,
     {
       code_conversion_save (0, 0);
       set_buffer_internal (XBUFFER (src_object));
-      if (EQ (src_object, dst_object))
+      if (same_buffer)
        {
          saved_pt = PT, saved_pt_byte = PT_BYTE;
          coding->src_object = del_range_1 (from, to, 1, 1);
diff --git a/src/comp.c b/src/comp.c
index c380346..7e21331 100644
--- a/src/comp.c
+++ b/src/comp.c
@@ -71,6 +71,7 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 #undef gcc_jit_context_new_binary_op
 #undef gcc_jit_context_new_call
 #undef gcc_jit_context_new_call_through_ptr
+#undef gcc_jit_context_new_cast
 #undef gcc_jit_context_new_comparison
 #undef gcc_jit_context_new_field
 #undef gcc_jit_context_new_function
@@ -176,6 +177,9 @@ DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_call,
 DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_call_through_ptr,
             (gcc_jit_context *ctxt, gcc_jit_location *loc,
              gcc_jit_rvalue *fn_ptr, int numargs, gcc_jit_rvalue **args));
+DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_cast,
+            (gcc_jit_context *ctxt, gcc_jit_location *loc,
+             gcc_jit_rvalue *rvalue, gcc_jit_type *type));
 DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_comparison,
             (gcc_jit_context *ctxt, gcc_jit_location *loc,
              enum gcc_jit_comparison op, gcc_jit_rvalue *a, gcc_jit_rvalue 
*b));
@@ -288,6 +292,7 @@ init_gccjit_functions (void)
   LOAD_DLL_FN (library, gcc_jit_context_new_binary_op);
   LOAD_DLL_FN (library, gcc_jit_context_new_call);
   LOAD_DLL_FN (library, gcc_jit_context_new_call_through_ptr);
+  LOAD_DLL_FN (library, gcc_jit_context_new_cast);
   LOAD_DLL_FN (library, gcc_jit_context_new_comparison);
   LOAD_DLL_FN (library, gcc_jit_context_new_field);
   LOAD_DLL_FN (library, gcc_jit_context_new_function);
@@ -358,6 +363,7 @@ init_gccjit_functions (void)
 #define gcc_jit_context_new_binary_op fn_gcc_jit_context_new_binary_op
 #define gcc_jit_context_new_call fn_gcc_jit_context_new_call
 #define gcc_jit_context_new_call_through_ptr 
fn_gcc_jit_context_new_call_through_ptr
+#define gcc_jit_context_new_cast fn_gcc_jit_context_new_cast
 #define gcc_jit_context_new_comparison fn_gcc_jit_context_new_comparison
 #define gcc_jit_context_new_field fn_gcc_jit_context_new_field
 #define gcc_jit_context_new_function fn_gcc_jit_context_new_function
@@ -499,13 +505,6 @@ static f_reloc_t freloc;
 
 #define NUM_CAST_TYPES 15
 
-enum cast_kind_of_type
-  {
-    kind_unsigned,
-    kind_signed,
-    kind_pointer
-  };
-
 typedef struct {
   EMACS_INT len;
   gcc_jit_rvalue *r_val;
@@ -571,14 +570,9 @@ typedef struct {
      be used for the scope.  */
   gcc_jit_type *cast_union_type;
   gcc_jit_function *cast_functions_from_to[NUM_CAST_TYPES][NUM_CAST_TYPES];
-  /*  We add one to make space for the last member which is the "biggest_type"
-      member.  */
-  gcc_jit_type *cast_types[NUM_CAST_TYPES + 1];
-  size_t cast_type_sizes[NUM_CAST_TYPES + 1];
-  enum cast_kind_of_type cast_type_kind[NUM_CAST_TYPES + 1];
-  const char *cast_type_names[NUM_CAST_TYPES + 1];
-  gcc_jit_field *cast_union_fields[NUM_CAST_TYPES + 1];
-  size_t cast_union_field_biggest_type;
+  gcc_jit_function *cast_ptr_to_int;
+  gcc_jit_function *cast_int_to_ptr;
+  gcc_jit_type *cast_types[NUM_CAST_TYPES];
   gcc_jit_function *func; /* Current function being compiled.  */
   bool func_has_non_local; /* From comp-func has-non-local slot.  */
   EMACS_INT func_speed; /* From comp-func speed slot.  */
@@ -1113,13 +1107,6 @@ emit_coerce (gcc_jit_type *new_type, gcc_jit_rvalue *obj)
   int old_index = type_to_cast_index (old_type);
   int new_index = type_to_cast_index (new_type);
 
-  if (comp.cast_type_sizes[old_index] < comp.cast_type_sizes[new_index]
-      && comp.cast_type_kind[new_index] == kind_signed)
-    xsignal3 (Qnative_ice,
-              build_string ("FIXME: sign extension not implemented"),
-              build_string (comp.cast_type_names[old_index]),
-              build_string (comp.cast_type_names[new_index]));
-
   /* Lookup the appropriate cast function in the cast matrix.  */
   return gcc_jit_context_new_call (comp.ctxt,
            NULL,
@@ -3111,30 +3098,17 @@ define_thread_state_struct (void)
     gcc_jit_type_get_pointer (gcc_jit_struct_as_type (comp.thread_state_s));
 }
 
-struct cast_type
-{
-  gcc_jit_type *type;
-  const char *name;
-  size_t bytes_size;
-  enum cast_kind_of_type kind;
-};
-
 static gcc_jit_function *
-define_cast_from_to (struct cast_type from, int from_index, struct cast_type 
to,
-                    int to_index)
+define_type_punning (const char *name,
+                    gcc_jit_type *from, gcc_jit_field *from_field,
+                    gcc_jit_type *to, gcc_jit_field *to_field)
 {
-  /*  FIXME: sign extension not implemented.  */
-  if (comp.cast_type_sizes[from_index] < comp.cast_type_sizes[to_index]
-      && comp.cast_type_kind[to_index] == kind_signed)
-    return NULL;
-
-  char *name = format_string ("cast_from_%s_to_%s", from.name, to.name);
   gcc_jit_param *param = gcc_jit_context_new_param (comp.ctxt, NULL,
-                                                    from.type, "arg");
+                                                    from, "arg");
   gcc_jit_function *result = gcc_jit_context_new_function (comp.ctxt,
                                NULL,
                                GCC_JIT_FUNCTION_INTERNAL,
-                               to.type,
+                               to,
                                name,
                                1,
                                &param,
@@ -3148,26 +3122,63 @@ define_cast_from_to (struct cast_type from, int 
from_index, struct cast_type to,
                                   comp.cast_union_type,
                                   "union_cast");
 
-  /*  Zero the union first.  */
   gcc_jit_block_add_assignment (entry_block, NULL,
                                 gcc_jit_lvalue_access_field (tmp_union, NULL,
-                                  comp.cast_union_fields[NUM_CAST_TYPES]),
-                                  gcc_jit_context_new_rvalue_from_int (
-                                   comp.ctxt,
-                                   comp.cast_types[NUM_CAST_TYPES],
-                                    0));
-
-  gcc_jit_block_add_assignment (entry_block, NULL,
-                                gcc_jit_lvalue_access_field (tmp_union, NULL,
-                                  comp.cast_union_fields[from_index]),
+                                                            from_field),
                                 gcc_jit_param_as_rvalue (param));
 
   gcc_jit_block_end_with_return (entry_block,
                                  NULL,
                                  gcc_jit_rvalue_access_field (
                                    gcc_jit_lvalue_as_rvalue (tmp_union),
-                                   NULL,
-                                   comp.cast_union_fields[to_index]));
+                                   NULL, to_field));
+
+  return result;
+}
+
+struct cast_type
+{
+  gcc_jit_type *type;
+  const char *name;
+  bool is_ptr;
+};
+
+static gcc_jit_function *
+define_cast_from_to (struct cast_type from, struct cast_type to)
+{
+  char *name = format_string ("cast_from_%s_to_%s", from.name, to.name);
+  gcc_jit_param *param = gcc_jit_context_new_param (comp.ctxt, NULL,
+                                                   from.type, "arg");
+  gcc_jit_function *result
+    = gcc_jit_context_new_function (comp.ctxt,
+                                   NULL,
+                                   GCC_JIT_FUNCTION_INTERNAL,
+                                   to.type, name,
+                                   1, &param, 0);
+  DECL_BLOCK (entry_block, result);
+
+  gcc_jit_rvalue *tmp = gcc_jit_param_as_rvalue (param);
+  if (from.is_ptr != to.is_ptr)
+    {
+      if (from.is_ptr)
+       {
+         tmp = gcc_jit_context_new_cast (comp.ctxt, NULL,
+                                         tmp, comp.void_ptr_type);
+         tmp = gcc_jit_context_new_call (comp.ctxt, NULL,
+                                         comp.cast_ptr_to_int, 1, &tmp);
+       }
+      else
+       {
+         tmp = gcc_jit_context_new_cast (comp.ctxt, NULL,
+                                         tmp, comp.uintptr_type);
+         tmp = gcc_jit_context_new_call (comp.ctxt, NULL,
+                                         comp.cast_int_to_ptr, 1, &tmp);
+       }
+    }
+
+  tmp = gcc_jit_context_new_cast (comp.ctxt, NULL, tmp, to.type);
+
+  gcc_jit_block_end_with_return (entry_block, NULL, tmp);
 
   return result;
 }
@@ -3176,69 +3187,58 @@ static void
 define_cast_functions (void)
 {
   struct cast_type cast_types[NUM_CAST_TYPES]
-    = { { comp.bool_type, "bool", sizeof (bool), kind_unsigned },
-        { comp.char_ptr_type, "char_ptr", sizeof (char *), kind_pointer },
-        { comp.int_type, "int", sizeof (int), kind_signed },
-        { comp.lisp_cons_ptr_type, "cons_ptr", sizeof (struct Lisp_Cons *),
-          kind_pointer },
-        { comp.lisp_obj_ptr_type, "lisp_obj_ptr", sizeof (Lisp_Object *),
-          kind_pointer },
-        { comp.lisp_word_tag_type, "lisp_word_tag", sizeof (Lisp_Word_tag),
-          kind_unsigned },
-        { comp.lisp_word_type, "lisp_word", sizeof (Lisp_Word),
-          LISP_WORDS_ARE_POINTERS ? kind_pointer : kind_signed },
-        { comp.long_long_type, "long_long", sizeof (long long), kind_signed },
-        { comp.long_type, "long", sizeof (long), kind_signed },
-        { comp.ptrdiff_type, "ptrdiff", sizeof (ptrdiff_t), kind_signed },
-        { comp.uintptr_type, "uintptr", sizeof (uintptr_t), kind_unsigned },
-        { comp.unsigned_long_long_type, "unsigned_long_long",
-          sizeof (unsigned long long), kind_unsigned },
-        { comp.unsigned_long_type, "unsigned_long", sizeof (unsigned long),
-          kind_unsigned },
-        { comp.unsigned_type, "unsigned", sizeof (unsigned), kind_unsigned },
-        { comp.void_ptr_type, "void_ptr", sizeof (void*), kind_pointer } };
-
-  /* Find the biggest size.  It should be unsigned long long, but to be
-     sure we find it programmatically.  */
-  size_t biggest_size = 0;
-  for (int i = 0; i < NUM_CAST_TYPES; ++i)
-    biggest_size = max (biggest_size, cast_types[i].bytes_size);
+    = { { comp.bool_type, "bool", false },
+        { comp.char_ptr_type, "char_ptr", true },
+        { comp.int_type, "int", false },
+        { comp.lisp_cons_ptr_type, "lisp_cons_ptr", true },
+        { comp.lisp_obj_ptr_type, "lisp_obj_ptr", true },
+        { comp.lisp_word_tag_type, "lisp_word_tag", false },
+        { comp.lisp_word_type, "lisp_word", LISP_WORDS_ARE_POINTERS },
+        { comp.long_long_type, "long_long", false },
+        { comp.long_type, "long", false },
+        { comp.ptrdiff_type, "ptrdiff", false },
+        { comp.uintptr_type, "uintptr", false },
+        { comp.unsigned_long_long_type, "unsigned_long_long", false },
+        { comp.unsigned_long_type, "unsigned_long", false },
+        { comp.unsigned_type, "unsigned", false },
+        { comp.void_ptr_type, "void_ptr", true } };
+  gcc_jit_field *cast_union_fields[2];
+
+  /* Define the union used for type punning.  */
+  cast_union_fields[0] = gcc_jit_context_new_field (comp.ctxt,
+                                                   NULL,
+                                                   comp.void_ptr_type,
+                                                   "void_ptr");
+  cast_union_fields[1] = gcc_jit_context_new_field (comp.ctxt,
+                                                   NULL,
+                                                   comp.uintptr_type,
+                                                   "uintptr");
 
-  /* Define the union used for casting.  */
-  for (int i = 0; i < NUM_CAST_TYPES; ++i)
-    {
-      comp.cast_types[i] = cast_types[i].type;
-      comp.cast_union_fields[i] = gcc_jit_context_new_field (comp.ctxt,
-                                    NULL,
-                                    cast_types[i].type,
-                                    cast_types[i].name);
-      comp.cast_type_names[i] = cast_types[i].name;
-      comp.cast_type_sizes[i] = cast_types[i].bytes_size;
-      comp.cast_type_kind[i] = cast_types[i].kind;
-    }
+  comp.cast_union_type
+    = gcc_jit_context_new_union_type (comp.ctxt,
+                                     NULL,
+                                     "cast_union",
+                                     2, cast_union_fields);
+
+  comp.cast_ptr_to_int = define_type_punning ("cast_pointer_to_uintptr_t",
+                                             comp.void_ptr_type,
+                                             cast_union_fields[0],
+                                             comp.uintptr_type,
+                                             cast_union_fields[1]);
+  comp.cast_int_to_ptr = define_type_punning ("cast_uintptr_t_to_pointer",
+                                             comp.uintptr_type,
+                                             cast_union_fields[1],
+                                             comp.void_ptr_type,
+                                             cast_union_fields[0]);
 
-  gcc_jit_type *biggest_type = gcc_jit_context_get_int_type (comp.ctxt,
-                                                             biggest_size,
-                                                             false);
-  comp.cast_types[NUM_CAST_TYPES] = biggest_type;
-  comp.cast_union_fields[NUM_CAST_TYPES] =
-    gcc_jit_context_new_field (comp.ctxt, NULL, biggest_type, "biggest_type");
-  comp.cast_type_names[NUM_CAST_TYPES] = "biggest_type";
-  comp.cast_type_sizes[NUM_CAST_TYPES] = biggest_size;
-  comp.cast_type_kind[NUM_CAST_TYPES] = kind_unsigned;
-
-  comp.cast_union_type =
-    gcc_jit_context_new_union_type (comp.ctxt,
-                                   NULL,
-                                   "cast_union",
-                                   NUM_CAST_TYPES + 1,
-                                   comp.cast_union_fields);
+  for (int i = 0; i < NUM_CAST_TYPES; ++i)
+    comp.cast_types[i] = cast_types[i].type;
 
   /* Define the cast functions using a matrix.  */
   for (int i = 0; i < NUM_CAST_TYPES; ++i)
     for (int j = 0; j < NUM_CAST_TYPES; ++j)
         comp.cast_functions_from_to[i][j] =
-          define_cast_from_to (cast_types[i], i, cast_types[j], j);
+          define_cast_from_to (cast_types[i], cast_types[j]);
 }
 
 static void
@@ -4490,6 +4490,15 @@ DEFUN ("comp--compile-ctxt-to-file", 
Fcomp__compile_ctxt_to_file,
                                  GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL,
                                  comp.speed < 0 ? 0
                                  : (comp.speed > 3 ? 3 : comp.speed));
+
+  /* On MacOS set a unique dylib ID.  */
+#if defined (LIBGCCJIT_HAVE_gcc_jit_context_add_driver_option) \
+  && defined (DARWIN_OS)
+  gcc_jit_context_add_driver_option (comp.ctxt, "-install_name");
+  gcc_jit_context_add_driver_option (
+         comp.ctxt, SSDATA (Ffile_name_nondirectory (filename)));
+#endif
+
   comp.d_default_idx =
     CALL1I (comp-data-container-idx, CALL1I (comp-ctxt-d-default, Vcomp_ctxt));
   comp.d_impure_idx =
diff --git a/src/composite.c b/src/composite.c
index 129e9d6..e97f8e2 100644
--- a/src/composite.c
+++ b/src/composite.c
@@ -961,6 +961,23 @@ char_composable_p (int c)
                       && (XFIXNUM (val) <= UNICODE_CATEGORY_Zs))))));
 }
 
+static inline bool
+inhibit_auto_composition (void)
+{
+  if (NILP (Vauto_composition_mode))
+    return true;
+
+  if (STRINGP (Vauto_composition_mode))
+    {
+      char *name = tty_type_name (Qnil);
+
+      if (name && ! strcmp (SSDATA (Vauto_composition_mode), name))
+       return true;
+    }
+
+  return false;
+}
+
 /* Update cmp_it->stop_pos to the next position after CHARPOS (and
    BYTEPOS) where character composition may happen.  If BYTEPOS is
    negative, compute it.  ENDPOS is a limit of searching.  If it is
@@ -1015,7 +1032,7 @@ composition_compute_stop_pos (struct composition_it 
*cmp_it, ptrdiff_t charpos,
       cmp_it->ch = -1;
     }
   if (NILP (BVAR (current_buffer, enable_multibyte_characters))
-      || NILP (Vauto_composition_mode))
+      || inhibit_auto_composition ())
     return;
   if (bytepos < 0)
     {
@@ -1741,7 +1758,7 @@ composition_adjust_point (ptrdiff_t last_pt, ptrdiff_t 
new_pt)
     }
 
   if (NILP (BVAR (current_buffer, enable_multibyte_characters))
-      || NILP (Vauto_composition_mode))
+      || inhibit_auto_composition ())
     return new_pt;
 
   /* Next check the automatic composition.  */
@@ -1941,7 +1958,7 @@ See `find-composition' for more details.  */)
   if (!find_composition (from, to, &start, &end, &prop, string))
     {
       if (!NILP (BVAR (current_buffer, enable_multibyte_characters))
-         && ! NILP (Vauto_composition_mode)
+         && ! inhibit_auto_composition ()
          && find_automatic_composition (from, to, (ptrdiff_t) -1,
                                         &start, &end, &gstring, string))
        return list3 (make_fixnum (start), make_fixnum (end), gstring);
@@ -2040,7 +2057,10 @@ The default value is the function `compose-chars-after'. 
 */);
 
   DEFVAR_LISP ("auto-composition-mode", Vauto_composition_mode,
               doc: /* Non-nil if Auto-Composition mode is enabled.
-Use the command `auto-composition-mode' to change this variable. */);
+Use the command `auto-composition-mode' to change this variable.
+
+If this variable is a string, `auto-composition-mode' will be disabled in
+buffers displayed on a terminal whose type compares equal to this string.  */);
   Vauto_composition_mode = Qt;
 
   DEFVAR_LISP ("auto-composition-function", Vauto_composition_function,
diff --git a/src/data.c b/src/data.c
index ffca7e7..27b642d 100644
--- a/src/data.c
+++ b/src/data.c
@@ -1045,6 +1045,8 @@ The value, if non-nil, is a list of mode name symbols.  
*/)
 
   if (COMPILEDP (fun))
     {
+      if (PVSIZE (fun) <= COMPILED_INTERACTIVE)
+       return Qnil;
       Lisp_Object form = AREF (fun, COMPILED_INTERACTIVE);
       if (VECTORP (form))
        /* New form -- the second element is the command modes. */
diff --git a/src/fileio.c b/src/fileio.c
index 13c99be..0db8ed7 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -1307,6 +1307,8 @@ the root directory.  */)
              newdir = SSDATA (hdir);
              newdirlim = newdir + SBYTES (hdir);
            }
+         else if (!multibyte && STRING_MULTIBYTE (tem))
+           multibyte = 1;
 #ifdef DOS_NT
          collapse_newdir = false;
 #endif
diff --git a/src/fns.c b/src/fns.c
index 932800a..c39fce2 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -1174,7 +1174,7 @@ string_make_multibyte (Lisp_Object string)
 
 
 /* Convert STRING (if unibyte) to a multibyte string without changing
-   the number of characters.  Characters 0200 trough 0237 are
+   the number of characters.  Characters 0200 through 0237 are
    converted to eight-bit characters. */
 
 Lisp_Object
@@ -1755,7 +1755,8 @@ DEFUN ("assoc", Fassoc, Sassoc, 2, 3, 0,
        doc: /* Return non-nil if KEY is equal to the car of an element of 
ALIST.
 The value is actually the first element of ALIST whose car equals KEY.
 
-Equality is defined by TESTFN if non-nil or by `equal' if nil.  */)
+Equality is defined by the function TESTFN, defaulting to `equal'.
+TESTFN is called with 2 arguments: a car of an alist element and KEY.  */)
      (Lisp_Object key, Lisp_Object alist, Lisp_Object testfn)
 {
   if (eq_comparable_value (key) && NILP (testfn))
diff --git a/src/frame.c b/src/frame.c
index b105268..f955668 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -729,7 +729,7 @@ adjust_frame_size (struct frame *f, int new_text_width, int 
new_text_height,
          && (f->new_width >= 0 || f->new_height >= 0))
        /* For implied resizes with inhibit 2 (external menu and tool
           bar) pick up any new sizes the display engine has not
-          processed yet.  Otherwsie, we would request the old sizes
+          processed yet.  Otherwise, we would request the old sizes
           which will make this request appear as a request to set new
           sizes and have the WM react accordingly which is not TRT.
 
@@ -1406,11 +1406,6 @@ affects all frames on the same terminal device.  */)
                  (t->display_info.tty->name
                   ? build_string (t->display_info.tty->name)
                   : Qnil));
-  /* On terminal frames the `minibuffer' frame parameter is always
-     virtually t.  Avoid that a different value in parms causes
-     complaints, see Bug#24758.  */
-  store_in_alist (&parms, Qminibuffer, Qt);
-  Fmodify_frame_parameters (frame, parms);
 
   /* Make the frame face hash be frame-specific, so that each
      frame could change its face definitions independently.  */
@@ -1423,6 +1418,12 @@ affects all frames on the same terminal device.  */)
   for (idx = 0; idx < table->count; ++idx)
     set_hash_value_slot (table, idx, Fcopy_sequence (HASH_VALUE (table, idx)));
 
+  /* On terminal frames the `minibuffer' frame parameter is always
+     virtually t.  Avoid that a different value in parms causes
+     complaints, see Bug#24758.  */
+  store_in_alist (&parms, Qminibuffer, Qt);
+  Fmodify_frame_parameters (frame, parms);
+
   f->can_set_window_size = true;
   f->after_make_frame = true;
 
@@ -1837,15 +1838,20 @@ prev_frame (Lisp_Object frame, Lisp_Object minibuf)
 
 DEFUN ("next-frame", Fnext_frame, Snext_frame, 0, 2, 0,
        doc: /* Return the next frame in the frame list after FRAME.
-It considers only frames on the same terminal as FRAME.
-By default, skip minibuffer-only frames.
-If omitted, FRAME defaults to the selected frame.
-If optional argument MINIFRAME is nil, exclude minibuffer-only frames.
-If MINIFRAME is a window, include only its own frame
-and any frame now using that window as the minibuffer.
-If MINIFRAME is `visible', include all visible frames.
-If MINIFRAME is 0, include all visible and iconified frames.
-Otherwise, include all frames.  */)
+Only frames on the same terminal as FRAME are included in the list
+of candidate frames.  If omitted, FRAME defaults to the selected frame.
+
+If MINIFRAME is nil (the default), include all frames except
+minibuffer-only frames.
+
+If MINIFRAME is a window, include only its own frame and any frame now
+using that window as the minibuffer.
+
+If MINIFRAME is `visible', include only visible frames.
+
+If MINIFRAME is 0, include only visible and iconified frames.
+
+If MINIFRAME is any other value, include all frames.  */)
   (Lisp_Object frame, Lisp_Object miniframe)
 {
   if (NILP (frame))
diff --git a/src/image.c b/src/image.c
index bcd45eb..206c7ba 100644
--- a/src/image.c
+++ b/src/image.c
@@ -10039,7 +10039,7 @@ svg_load_image (struct frame *f, struct image *img, 
char *contents,
 #if LIBRSVG_CHECK_VERSION (2, 46, 0)
   RsvgRectangle zero_rect, viewbox, out_logical_rect;
 
-  /* Try the instrinsic dimensions first.  */
+  /* Try the intrinsic dimensions first.  */
   gboolean has_width, has_height, has_viewbox;
   RsvgLength iwidth, iheight;
   double dpi = FRAME_DISPLAY_INFO (f)->resx;
@@ -10074,7 +10074,7 @@ svg_load_image (struct frame *f, struct image *img, 
char *contents,
     }
   else
     {
-      /* We haven't found a useable set of sizes, so try working out
+      /* We haven't found a usable set of sizes, so try working out
          the visible area.  */
       rsvg_handle_get_geometry_for_layer (rsvg_handle, NULL,
                                           &zero_rect, &viewbox,
diff --git a/src/keyboard.c b/src/keyboard.c
index 2e4c4e6..f6139b3 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -1009,25 +1009,28 @@ Default value of `command-error-function'.  */)
   (Lisp_Object data, Lisp_Object context, Lisp_Object signal)
 {
   struct frame *sf = SELECTED_FRAME ();
-  Lisp_Object conditions;
+  Lisp_Object conditions = Fget (XCAR (data), Qerror_conditions);
+  int is_minibuffer_quit = !NILP (Fmemq (Qminibuffer_quit, conditions));
 
   CHECK_STRING (context);
 
   /* If the window system or terminal frame hasn't been initialized
-     yet, or we're not interactive, write the message to stderr and exit.  */
-  if (!sf->glyphs_initialized_p
-          /* The initial frame is a special non-displaying frame. It
-             will be current in daemon mode when there are no frames
-             to display, and in non-daemon mode before the real frame
-             has finished initializing.  If an error is thrown in the
-             latter case while creating the frame, then the frame
-             will never be displayed, so the safest thing to do is
-             write to stderr and quit.  In daemon mode, there are
-             many other potential errors that do not prevent frames
-             from being created, so continuing as normal is better in
-             that case.  */
-          || (!IS_DAEMON && FRAME_INITIAL_P (sf))
-          || noninteractive)
+     yet, or we're not interactive, write the message to stderr and exit.
+     Don't do this for the minibuffer-quit condition.  */
+  if (!is_minibuffer_quit
+      && (!sf->glyphs_initialized_p
+         /* The initial frame is a special non-displaying frame. It
+            will be current in daemon mode when there are no frames
+            to display, and in non-daemon mode before the real frame
+            has finished initializing.  If an error is thrown in the
+            latter case while creating the frame, then the frame
+            will never be displayed, so the safest thing to do is
+            write to stderr and quit.  In daemon mode, there are
+            many other potential errors that do not prevent frames
+            from being created, so continuing as normal is better in
+            that case.  */
+         || (!IS_DAEMON && FRAME_INITIAL_P (sf))
+         || noninteractive))
     {
       print_error_message (data, Qexternal_debugging_output,
                           SSDATA (context), signal);
@@ -1036,12 +1039,10 @@ Default value of `command-error-function'.  */)
     }
   else
     {
-      conditions = Fget (XCAR (data), Qerror_conditions);
-
       clear_message (1, 0);
       message_log_maybe_newline ();
 
-      if (!NILP (Fmemq (Qminibuffer_quit, conditions)))
+      if (is_minibuffer_quit)
        {
          Fding (Qt);
        }
@@ -4234,7 +4235,7 @@ decode_timer (Lisp_Object timer, struct timespec *result)
 {
   Lisp_Object *vec;
 
-  if (! (VECTORP (timer) && ASIZE (timer) == 9))
+  if (! (VECTORP (timer) && ASIZE (timer) == 10))
     return false;
   vec = XVECTOR (timer)->contents;
   if (! NILP (vec[0]))
@@ -9187,8 +9188,7 @@ access_keymap_keyremap (Lisp_Object map, Lisp_Object key, 
Lisp_Object prompt,
       /* If the function returned something invalid,
         barf--don't ignore it.  */
       if (! (NILP (next) || VECTORP (next) || STRINGP (next)))
-       error ("Function %s returns invalid key sequence",
-              SSDATA (SYMBOL_NAME (tem)));
+       signal_error ("Function returns invalid key sequence", tem);
     }
   return next;
 }
diff --git a/src/lisp.h b/src/lisp.h
index 1206a0d..7bfc69b 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4652,6 +4652,7 @@ extern AVOID fatal (const char *msgid, ...) 
ATTRIBUTE_FORMAT_PRINTF (1, 2);
 
 /* Defined in terminal.c.  */
 extern void syms_of_terminal (void);
+extern char * tty_type_name (Lisp_Object);
 
 /* Defined in font.c.  */
 extern void syms_of_font (void);
diff --git a/src/menu.c b/src/menu.c
index 3b1d740..d43360e 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -1284,12 +1284,16 @@ x_popup_menu_1 (Lisp_Object position, Lisp_Object menu)
       /* Search for a string appearing directly as an element of the keymap.
         That string is the title of the menu.  */
       prompt = Fkeymap_prompt (keymap);
-      if (!NILP (prompt))
-       title = prompt;
-#ifdef HAVE_NS         /* Is that needed and NS-specific?  --Stef  */
+
+#if defined (USE_GTK) || defined (HAVE_NS)
+      if (STRINGP (prompt)
+         && SCHARS (prompt) > 0
+         && !NILP (Fget_text_property (make_fixnum (0), Qhide, prompt)))
+       title = Qnil;
       else
-       title = build_string ("Select");
 #endif
+      if (!NILP (prompt))
+       title = prompt;
 
       /* Make that be the pane title of the first pane.  */
       if (!NILP (prompt) && menu_items_n_panes >= 0)
@@ -1575,6 +1579,8 @@ syms_of_menu (void)
   menu_items = Qnil;
   staticpro (&menu_items);
 
+  DEFSYM (Qhide, "hide");
+
   defsubr (&Sx_popup_menu);
   defsubr (&Sx_popup_dialog);
   defsubr (&Smenu_bar_menu_at_x_y);
diff --git a/src/nsfns.m b/src/nsfns.m
index c403677..07bcab1 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -1343,6 +1343,11 @@ DEFUN ("x-create-frame", Fx_create_frame, 
Sx_create_frame,
 
   f->output_data.ns->in_animation = NO;
 
+#ifdef NS_IMPL_COCOA
+  /* If the app has previously been disabled, start it up again.  */
+  [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
+#endif
+
   [[EmacsView alloc] initFrameFromEmacs: f];
 
   ns_icon (f, parms);
diff --git a/src/nsmenu.m b/src/nsmenu.m
index bb0dd26..3493e4e 100644
--- a/src/nsmenu.m
+++ b/src/nsmenu.m
@@ -959,7 +959,7 @@ ns_menu_show (struct frame *f, int x, int y, int menuflags,
     }
 
   pmenu = [[EmacsMenu alloc] initWithTitle:
-                               [NSString stringWithLispString: title]];
+                   NILP (title) ? @"" : [NSString stringWithLispString: 
title]];
   [pmenu fillWithWidgetValue: first_wv->contents];
   free_menubar_widget_value_tree (first_wv);
   unbind_to (specpdl_count, Qnil);
@@ -1033,6 +1033,8 @@ update_frame_tool_bar (struct frame *f)
       ptrdiff_t img_id;
       struct image *img;
       Lisp_Object image;
+      Lisp_Object labelObj;
+      const char *labelText;
       Lisp_Object helpObj;
       const char *helpText;
 
@@ -1059,6 +1061,8 @@ update_frame_tool_bar (struct frame *f)
         {
           idx = -1;
         }
+      labelObj = TOOLPROP (TOOL_BAR_ITEM_LABEL);
+      labelText = NILP (labelObj) ? "" : SSDATA (labelObj);
       helpObj = TOOLPROP (TOOL_BAR_ITEM_HELP);
       if (NILP (helpObj))
         helpObj = TOOLPROP (TOOL_BAR_ITEM_CAPTION);
@@ -1084,6 +1088,7 @@ update_frame_tool_bar (struct frame *f)
       [toolbar addDisplayItemWithImage: img->pixmap
                                    idx: k++
                                    tag: i
+                             labelText: labelText
                               helpText: helpText
                                enabled: enabled_p];
 #undef TOOLPROP
@@ -1188,6 +1193,7 @@ update_frame_tool_bar (struct frame *f)
 - (void) addDisplayItemWithImage: (EmacsImage *)img
                              idx: (int)idx
                              tag: (int)tag
+                       labelText: (const char *)label
                         helpText: (const char *)help
                          enabled: (BOOL)enabled
 {
@@ -1205,6 +1211,7 @@ update_frame_tool_bar (struct frame *f)
       item = [[[NSToolbarItem alloc] initWithItemIdentifier: identifier]
                autorelease];
       [item setImage: img];
+      [item setLabel: [NSString stringWithUTF8String: label]];
       [item setToolTip: [NSString stringWithUTF8String: help]];
       [item setTarget: emacsView];
       [item setAction: @selector (toolbarClicked:)];
diff --git a/src/nsterm.h b/src/nsterm.h
index 404c714..6d4ea77 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -548,6 +548,7 @@ typedef id instancetype;
 - (void) addDisplayItemWithImage: (EmacsImage *)img
                              idx: (int)idx
                              tag: (int)tag
+                       labelText: (const char *)label
                         helpText: (const char *)help
                          enabled: (BOOL)enabled;
 
diff --git a/src/nsterm.m b/src/nsterm.m
index ba5d81f..8d88f7b 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -5014,6 +5014,12 @@ ns_delete_terminal (struct terminal *terminal)
 
   block_input ();
 
+#ifdef NS_IMPL_COCOA
+  /* Rather than try to clean up the NS environment we can just
+     disable the app and leave it waiting for any new frames.  */
+  [NSApp setActivationPolicy:NSApplicationActivationPolicyProhibited];
+#endif
+
   image_destroy_all_bitmaps (dpyinfo);
   ns_delete_display (dpyinfo);
   unblock_input ();
@@ -8363,14 +8369,14 @@ not_in_argv (NSString *arg)
 
 
 #ifdef NS_IMPL_COCOA
-  /* We have to set the accesibility subroles and/or the collection
+  /* We have to set the accessibility subroles and/or the collection
      behaviors early otherwise child windows may not go fullscreen as
      expected later.  */
 
 #if MAC_OS_X_VERSION_MIN_REQUIRED < 101000
   if ([child respondsToSelector:@selector(setAccessibilitySubrole:)])
 #endif
-    /* Set the accessibilty subroles.  */
+    /* Set the accessibility subroles.  */
     if (parentFrame)
       [self setAccessibilitySubrole:NSAccessibilityFloatingWindowSubrole];
     else
@@ -9394,7 +9400,7 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c)
   if (self)
     {
       cache = [[NSMutableArray arrayWithCapacity:CACHE_MAX_SIZE] retain];
-      colorSpace = cs;
+      [self setColorSpace:cs];
     }
   else
     {
@@ -9409,7 +9415,10 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c)
 {
   /* We don't need to clear the cache because the new colorspace will
      be used next time we create a new context.  */
-  colorSpace = cs;
+  if (cs)
+    colorSpace = cs;
+  else
+    colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
 }
 
 
@@ -9505,6 +9514,12 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c)
                 (id)kIOSurfacePixelFormat:[NSNumber 
numberWithUnsignedInt:'BGRA']});
         }
 
+      if (!surface)
+        {
+          NSLog (@"Failed to create IOSurface for frame %@", [self delegate]);
+          return nil;
+        }
+
       IOReturn lockStatus = IOSurfaceLock (surface, 0, nil);
       if (lockStatus != kIOReturnSuccess)
         NSLog (@"Failed to lock surface: %x", lockStatus);
@@ -9522,6 +9537,15 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c)
                                        (kCGImageAlphaPremultipliedFirst
                                         | kCGBitmapByteOrder32Host));
 
+      if (!context)
+        {
+          NSLog (@"Failed to create context for frame %@", [self delegate]);
+          IOSurfaceUnlock (currentSurface, 0, nil);
+          CFRelease (currentSurface);
+          currentSurface = nil;
+          return nil;
+        }
+
       CGContextTranslateCTM(context, 0, IOSurfaceGetHeight (currentSurface));
       CGContextScaleCTM(context, scale, -scale);
     }
diff --git a/src/process.c b/src/process.c
index c3186ee..bfca165 100644
--- a/src/process.c
+++ b/src/process.c
@@ -1718,7 +1718,10 @@ to use a pty, or nil to use the default specified through
 :stderr STDERR -- STDERR is either a buffer or a pipe process attached
 to the standard error of subprocess.  Specifying this implies
 `:connection-type' is set to `pipe'.  If STDERR is nil, standard error
-is mixed with standard output and sent to BUFFER or FILTER.
+is mixed with standard output and sent to BUFFER or FILTER.  (Note
+that specifying :stderr will create a new, separate (but associated)
+process, with its own filter and sentinel.  See
+Info node `(elisp) Asynchronous Processes' for more details.)
 
 :file-handler FILE-HANDLER -- If FILE-HANDLER is non-nil, then look
 for a file name handler for the current buffer's `default-directory'
diff --git a/src/syntax.c b/src/syntax.c
index 7bba336..057a4c3 100644
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -17,7 +17,6 @@ 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/>.  */
 
-
 #include <config.h>
 
 #include "lisp.h"
@@ -3547,8 +3546,10 @@ DEFUN ("parse-partial-sexp", Fparse_partial_sexp, 
Sparse_partial_sexp, 2, 6, 0,
        doc: /* Parse Lisp syntax starting at FROM until TO; return status of 
parse at TO.
 Parsing stops at TO or when certain criteria are met;
  point is set to where parsing stops.
-If fifth arg OLDSTATE is omitted or nil,
- parsing assumes that FROM is the beginning of a function.
+
+If OLDSTATE is omitted or nil, parsing assumes that FROM is the
+ beginning of a function.  If not, OLDSTATE should be the state at
+ FROM.
 
 Value is a list of elements describing final state of parsing:
  0. depth in parens.
@@ -3594,6 +3595,9 @@ Sixth arg COMMENTSTOP non-nil means stop after the start 
of a comment.
   else
     target = TYPE_MINIMUM (EMACS_INT); /* We won't reach this depth.  */
 
+  if (fix_position (to) < fix_position (from))
+    error ("End position is smaller than start position");
+
   validate_region (&from, &to);
   internalize_parse_state (oldstate, &state);
   scan_sexps_forward (&state, XFIXNUM (from), CHAR_TO_BYTE (XFIXNUM (from)),
diff --git a/src/term.c b/src/term.c
index c995a44..6651b96 100644
--- a/src/term.c
+++ b/src/term.c
@@ -2169,6 +2169,14 @@ set_tty_color_mode (struct tty_display_info *tty, struct 
frame *f)
 
 #endif /* !DOS_NT */
 
+char *
+tty_type_name (Lisp_Object terminal)
+{
+  struct terminal *t = decode_tty_terminal (terminal);
+
+  return t? t->display_info.tty->type: NULL;
+}
+
 DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0,
        doc: /* Return the type of the tty device that TERMINAL uses.
 Returns nil if TERMINAL is not on a tty device.
@@ -2177,10 +2185,9 @@ TERMINAL can be a terminal object, a frame, or nil 
(meaning the
 selected frame's terminal).  */)
   (Lisp_Object terminal)
 {
-  struct terminal *t = decode_tty_terminal (terminal);
+  char *name = tty_type_name (terminal);
 
-  return (t && t->display_info.tty->type
-         ? build_string (t->display_info.tty->type) : Qnil);
+  return (name? build_string (name) : Qnil);
 }
 
 DEFUN ("controlling-tty-p", Fcontrolling_tty_p, Scontrolling_tty_p, 0, 1, 0,
diff --git a/src/xdisp.c b/src/xdisp.c
index 972b901..b2fcc16 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -4472,7 +4472,13 @@ face_at_pos (const struct it *it, enum 
lface_attribute_index attr_filter)
 static enum prop_handled
 handle_face_prop (struct it *it)
 {
+  ptrdiff_t count = SPECPDL_INDEX ();
+  /* Don't allow the user to quit out of face-merging code, in case
+     this is called when redisplaying a non-selected window, with
+     point temporarily moved to window-point.  */
+  specbind (Qinhibit_quit, Qt);
   const int new_face_id = face_at_pos (it, 0);
+  unbind_to (count, Qnil);
 
 
   /* Is this a start of a run of characters with box face?
@@ -4595,6 +4601,7 @@ face_before_or_after_it_pos (struct it *it, bool before_p)
          SAVE_IT (it_copy, *it, it_copy_data);
          IT_STRING_CHARPOS (it_copy) = 0;
          bidi_init_it (0, 0, FRAME_WINDOW_P (it_copy.f), &it_copy.bidi_it);
+         it_copy.bidi_it.scan_dir = 0;
 
          do
            {
@@ -5781,8 +5788,15 @@ handle_single_display_spec (struct it *it, Lisp_Object 
spec, Lisp_Object object,
 #ifdef HAVE_WINDOW_SYSTEM
       else
        {
+         ptrdiff_t count = SPECPDL_INDEX ();
+
          it->what = IT_IMAGE;
+         /* Don't allow quitting from lookup_image, for when we are
+            displaying a non-selected window, and the buffer's point
+            was temporarily moved to the window-point.  */
+         specbind (Qinhibit_quit, Qt);
          it->image_id = lookup_image (it->f, value, it->face_id);
+         unbind_to (count, Qnil);
          it->position = start_pos;
          it->object = NILP (object) ? it->w->contents : object;
          it->method = GET_FROM_IMAGE;
@@ -11757,7 +11771,7 @@ display_echo_area (struct window *w)
   /* If there is no message, we must call display_echo_area_1
      nevertheless because it resizes the window.  But we will have to
      reset the echo_area_buffer in question to nil at the end because
-     with_echo_area_buffer will sets it to an empty buffer.  */
+     with_echo_area_buffer will set it to an empty buffer.  */
   bool i = display_last_displayed_message_p;
   /* According to the C99, C11 and C++11 standards, the integral value
      of a "bool" is always 0 or 1, so this array access is safe here,
@@ -14884,7 +14898,15 @@ hscroll_window_tree (Lisp_Object window)
 
       if (WINDOWP (w->contents))
        hscrolled_p |= hscroll_window_tree (w->contents);
-      else if (w->cursor.vpos >= 0)
+      else if (w->cursor.vpos >= 0
+              /* Don't allow hscroll in mini-windows that display
+                 echo-area messages.  This is because desired_matrix
+                 of such windows was prepared while momentarily
+                 switched to an echo-area buffer, which is different
+                 from w->contents, and we simply cannot hscroll such
+                 windows safely.  */
+              && !(w == XWINDOW (echo_area_window)
+                   && !NILP (echo_area_buffer[0])))
        {
          int h_margin;
          int text_area_width;
@@ -22111,10 +22133,17 @@ extend_face_to_end_of_line (struct it *it)
           || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0))
     return;
 
+  ptrdiff_t count = SPECPDL_INDEX ();
+
+  /* Don't allow the user to quit out of face-merging code, in case
+     this is called when redisplaying a non-selected window, with
+     point temporarily moved to window-point.  */
+  specbind (Qinhibit_quit, Qt);
   const int extend_face_id = (it->face_id == DEFAULT_FACE_ID
                               || it->s != NULL)
     ? DEFAULT_FACE_ID
     : face_at_pos (it, LFACE_EXTEND_INDEX);
+  unbind_to (count, Qnil);
 
   /* Face extension extends the background and box of IT->extend_face_id
      to the end of the line.  If the background equals the background
@@ -35107,7 +35136,10 @@ not span the full frame width.
 
 A value of nil means to respect the value of `truncate-lines'.
 
-If `word-wrap' is enabled, you might want to reduce this.  */);
+If `word-wrap' is enabled, you might want to reduce the value of this.
+
+Don't set this to a non-nil value when `visual-line-mode' is
+turned on, as it could produce confusing results.  */);
   Vtruncate_partial_width_windows = make_fixnum (50);
 
   DEFVAR_BOOL("word-wrap-by-category", word_wrap_by_category, doc: /*
@@ -35416,7 +35448,7 @@ and `scroll-right' overrides this variable's effect.  
*/);
   Vhscroll_step = make_fixnum (0);
 
   DEFVAR_BOOL ("message-truncate-lines", message_truncate_lines,
-    doc: /* If non-nil, messages are truncated instead of resizing the echo 
area.
+    doc: /* If non-nil, messages are truncated when displaying the echo area.
 Bind this around calls to `message' to let it take effect.  */);
   message_truncate_lines = false;
 
diff --git a/src/xfaces.c b/src/xfaces.c
index 207f0d6..2273fb4 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -5092,8 +5092,8 @@ gui_supports_face_attributes_p (struct frame *f,
 {
   Lisp_Object *def_attrs = def_face->lface;
 
-  /* Check that other specified attributes are different that the default
-     face.  */
+  /* Check that other specified attributes are different from the
+     default face.  */
   if ((!UNSPECIFIEDP (attrs[LFACE_UNDERLINE_INDEX])
        && face_attr_equal_p (attrs[LFACE_UNDERLINE_INDEX],
                             def_attrs[LFACE_UNDERLINE_INDEX]))
diff --git a/src/xfns.c b/src/xfns.c
index 81349d0..0d0335c 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -7836,7 +7836,6 @@ syms_of_xfns (void)
   DEFSYM (Qfont_parameter, "font-parameter");
   DEFSYM (Qmono, "mono");
   DEFSYM (Qassq_delete_all, "assq-delete-all");
-  DEFSYM (Qhide, "hide");
   DEFSYM (Qresize_mode, "resize-mode");
 
 #ifdef USE_CAIRO
diff --git a/test/Makefile.in b/test/Makefile.in
index a3412d6..7047c24 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -163,7 +163,7 @@ endif
 WRITE_LOG = > $@ 2>&1 || { STAT=$$?; cat $@; exit $$STAT; }
 ## On Hydra or Emba, always show logs for certain problematic tests.
 ifdef EMACS_HYDRA_CI
-lisp/net/tramp-tests.log lisp/electric-tests.log \
+lisp/net/tramp-tests.log \
 : WRITE_LOG = 2>&1 | tee $@
 endif
 ifdef EMACS_EMBA_CI
diff --git a/test/infra/Dockerfile.emba b/test/infra/Dockerfile.emba
index 9f03482..0b61c74 100644
--- a/test/infra/Dockerfile.emba
+++ b/test/infra/Dockerfile.emba
@@ -82,6 +82,6 @@ ARG make_bootstrap_params=""
 COPY . /checkout
 WORKDIR /checkout
 RUN ./autogen.sh autoconf
-RUN ./configure --with-nativecomp
+RUN ./configure --with-native-compilation
 RUN make bootstrap -j2 NATIVE_FULL_AOT=1 BYTE_COMPILE_EXTRA_FLAGS='--eval 
"(setq comp-speed 0)"'
 RUN make -j4
diff --git a/test/infra/gitlab-ci.yml b/test/infra/gitlab-ci.yml
index 6876a8b..5082b08 100644
--- a/test/infra/gitlab-ci.yml
+++ b/test/infra/gitlab-ci.yml
@@ -291,7 +291,7 @@ build-native-bootstrap-speed0:
 #   script:
 #     - DEBIAN_FRONTEND=noninteractive apt install --no-install-recommends -y 
-qq -o=Dpkg::Use-Pty=0 libgccjit-6-dev
 #     - ./autogen.sh autoconf
-#     - ./configure --with-nativecomp
+#     - ./configure --with-native-compilation
 #     - make bootstrap NATIVE_FULL_AOT=1 BYTE_COMPILE_EXTRA_FLAGS='--eval 
"(setq comp-speed 0)"' -j2
 #   timeout: 8 hours
 
@@ -300,7 +300,7 @@ build-native-bootstrap-speed0:
 #   script:
 #     - DEBIAN_FRONTEND=noninteractive apt install --no-install-recommends -y 
-qq -o=Dpkg::Use-Pty=0 libgccjit-6-dev
 #     - ./autogen.sh autoconf
-#     - ./configure --with-nativecomp
+#     - ./configure --with-native-compilation
 #     - make bootstrap BYTE_COMPILE_EXTRA_FLAGS='--eval "(setq comp-speed 1)"'
 #   timeout: 8 hours
 
@@ -309,7 +309,7 @@ build-native-bootstrap-speed0:
 #   script:
 #     - DEBIAN_FRONTEND=noninteractive apt install --no-install-recommends -y 
-qq -o=Dpkg::Use-Pty=0 libgccjit-6-dev
 #     - ./autogen.sh autoconf
-#     - ./configure --with-nativecomp
+#     - ./configure --with-native-compilation
 #     - make bootstrap
 #   timeout: 8 hours
 
diff --git a/test/lisp/calendar/icalendar-tests.el 
b/test/lisp/calendar/icalendar-tests.el
index 6973f7e..de2a891 100644
--- a/test/lisp/calendar/icalendar-tests.el
+++ b/test/lisp/calendar/icalendar-tests.el
@@ -1442,6 +1442,13 @@ RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=09;BYMONTHDAY=21
 SUMMARY:ff birthday (%d years old)")
 
 
+  (icalendar-tests--test-export
+   nil
+   nil
+   "%%(diary-offset '(diary-float t 3 4) 1) asdf"
+   nil)
+
+
   ;; FIXME!
 
   ;; export 2004-10-28 monthly, weekly entries
diff --git a/test/lisp/custom-tests.el b/test/lisp/custom-tests.el
index e93c96e..f4c43b0 100644
--- a/test/lisp/custom-tests.el
+++ b/test/lisp/custom-tests.el
@@ -96,6 +96,7 @@ Ensure the directory is recursively deleted after the fact."
 
 (ert-deftest custom-tests-require-theme ()
   "Test `require-theme'."
+  (require 'warnings)
   (custom-tests--with-temp-dir
     (let* ((default-directory temporary-file-directory)
            (custom-theme-load-path (list default-directory))
diff --git a/test/lisp/electric-tests.el b/test/lisp/electric-tests.el
index ea856ab..666de89 100644
--- a/test/lisp/electric-tests.el
+++ b/test/lisp/electric-tests.el
@@ -871,7 +871,7 @@ baz\"\""
 
 (defun electric-layout-for-c-style-du-jour (inserted)
   "A function to use in `electric-layout-rules'"
-  (when (memq inserted '(?{ ?}))
+  (when (memq inserted '(?\{ ?\}))
     (save-excursion
       (backward-char 2) (c-point-syntax) (forward-char) ; silly, but needed
       (c-brace-newlines (c-point-syntax)))))
diff --git a/test/lisp/emacs-lisp/cl-lib-tests.el 
b/test/lisp/emacs-lisp/cl-lib-tests.el
index a5ec62b..a132d73 100644
--- a/test/lisp/emacs-lisp/cl-lib-tests.el
+++ b/test/lisp/emacs-lisp/cl-lib-tests.el
@@ -417,22 +417,6 @@
   (should-error (cl-nth-value -1 (cl-values 2 3)) :type 'args-out-of-range)
   (should (string= (cl-nth-value 0 "only lists") "only lists")))
 
-(ert-deftest cl-test-caaar ()
-  (should (null (cl-caaar '())))
-  (should (null (cl-caaar '(() (2)))))
-  (should (null (cl-caaar '((() (2)) (a b)))))
-  (should-error (cl-caaar '(1 2)) :type 'wrong-type-argument)
-  (should-error (cl-caaar '((1 2))) :type 'wrong-type-argument)
-  (should (=  1 (cl-caaar '(((1 2) (3 4))))))
-  (should (null (cl-caaar '((() (3 4)))))))
-
-(ert-deftest cl-test-caadr ()
-  (should (null (cl-caadr '())))
-  (should (null (cl-caadr '(1))))
-  (should-error (cl-caadr '(1 2)) :type 'wrong-type-argument)
-  (should (= 2 (cl-caadr '(1 (2 3)))))
-  (should (equal '((2) (3)) (cl-caadr '((1) (((2) (3))) (4))))))
-
 (ert-deftest cl-test-ldiff ()
   (let ((l '(1 2 3)))
     (should (null (cl-ldiff '() '())))
diff --git a/test/lisp/emacs-lisp/edebug-tests.el 
b/test/lisp/emacs-lisp/edebug-tests.el
index 2f45050..f8fa223 100644
--- a/test/lisp/emacs-lisp/edebug-tests.el
+++ b/test/lisp/emacs-lisp/edebug-tests.el
@@ -723,7 +723,7 @@ test and possibly others should be updated."
           (edebug-on-error nil)
           error-message
           (command-error-function (lambda (&rest args)
-                                    (setq error-message (cl-cadar args)))))
+                                    (setq error-message (cadar args)))))
      (edebug-tests-run-kbd-macro
       "@"    (edebug-tests-should-be-at "format-node" "start")
       "SPC"  (edebug-tests-should-be-at "format-node" "vectorp")
@@ -744,7 +744,7 @@ test and possibly others should be updated."
           (edebug-on-error nil)
           (error-message "")
           (command-error-function (lambda (&rest args)
-                                    (setq error-message (cl-cadar args)))))
+                                    (setq error-message (cadar args)))))
      (edebug-tests-run-kbd-macro
       "@ SPC SPC SPC SPC SPC"
       (edebug-tests-should-be-at "try-flavors" "macro")
diff --git a/test/lisp/emacs-lisp/map-tests.el 
b/test/lisp/emacs-lisp/map-tests.el
index 658ed2e..c0f0dbc 100644
--- a/test/lisp/emacs-lisp/map-tests.el
+++ b/test/lisp/emacs-lisp/map-tests.el
@@ -521,5 +521,14 @@ Evaluate BODY for each created map."
                   'value2))
     (should (equal (map-elt ht 'key) 'value2))))
 
+(ert-deftest test-setf-map-with-function ()
+  (let ((num 0)
+        (map nil))
+    (setf (map-elt map 'foo)
+          (funcall (lambda ()
+                     (cl-incf num))))
+    ;; Check that the function is only called once.
+    (should (= num 1))))
+
 (provide 'map-tests)
 ;;; map-tests.el ends here
diff --git a/test/lisp/emacs-lisp/memory-report-tests.el 
b/test/lisp/emacs-lisp/memory-report-tests.el
index 0c0297b..e352dd1 100644
--- a/test/lisp/emacs-lisp/memory-report-tests.el
+++ b/test/lisp/emacs-lisp/memory-report-tests.el
@@ -68,6 +68,14 @@
                 (vector string string))
                124))))
 
+(ert-deftest memory-report-sizes-structs ()
+  (cl-defstruct memory-report-test-struct
+    (item0 nil)
+    (item1 nil))
+  (let ((s (make-memory-report-test-struct :item0 "hello" :item1 "world")))
+    (should (= (memory-report-object-size s)
+               90))))
+
 (provide 'memory-report-tests)
 
 ;;; memory-report-tests.el ends here
diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el
index fb24b98..aa5150b 100644
--- a/test/lisp/files-tests.el
+++ b/test/lisp/files-tests.el
@@ -1560,5 +1560,218 @@ The door of all subtleties!
   (find-file (ert-resource-file "auto-test.zot3"))
   (should (eq major-mode 'fundamental-mode)))
 
+(defun files-tests--save-some-buffers (pred def-pred-bind exp-1 exp-2)
+  "Helper function to test `save-some-buffers'.
+
+This function creates two file-visiting buffers, BUF-1, BUF-2 in
+different directories at the same level, i.e., none of them is a
+subdir of the other; then it modifies both buffers; finally, it
+calls `save-some-buffers' from BUF-1 with first arg t, second
+arg PRED and `save-some-buffers-default-predicate' let-bound to
+DEF-PRED-BIND.
+
+EXP-1 and EXP-2 are the expected values of calling `buffer-modified-p'
+on BUF-1 and BUF-2 after the `save-some-buffers' call.
+
+The test is repeated with `save-some-buffers-default-predicate'
+let-bound to PRED and passing nil as second arg of
+`save-some-buffers'."
+  (let* ((dir (make-temp-file "testdir" 'dir))
+         (file-1 (expand-file-name "subdir-1/file.foo" dir))
+         (file-2 (expand-file-name "subdir-2/file.bar" dir))
+         (inhibit-message t)
+         buf-1 buf-2)
+    (unwind-protect
+        (progn
+          (make-empty-file file-1 'parens)
+          (make-empty-file file-2 'parens)
+          (setq buf-1 (find-file file-1)
+                buf-2 (find-file file-2))
+          (dolist (buf (list buf-1 buf-2))
+            (with-current-buffer buf (insert "foobar\n")))
+          ;; Run the test.
+          (with-current-buffer buf-1
+            (let ((save-some-buffers-default-predicate def-pred-bind))
+              (save-some-buffers t pred))
+            (should (eq exp-1 (buffer-modified-p buf-1)))
+            (should (eq exp-2 (buffer-modified-p buf-2))))
+          ;; Set both buffers as modified to run another test.
+          (dolist (buf (list buf-1 buf-2))
+            (with-current-buffer buf (set-buffer-modified-p t)))
+          ;; The result of this test must be identical as the previous one.
+          (with-current-buffer buf-1
+            (let ((save-some-buffers-default-predicate (or pred 
def-pred-bind)))
+              (save-some-buffers t nil))
+            (should (eq exp-1 (buffer-modified-p buf-1)))
+            (should (eq exp-2 (buffer-modified-p buf-2)))))
+      ;; Clean up.
+      (dolist (buf (list buf-1 buf-2))
+        (with-current-buffer buf
+          (set-buffer-modified-p nil)
+          (kill-buffer buf)))
+      (delete-directory dir 'recursive))))
+
+(ert-deftest files-tests-save-some-buffers ()
+  "Test `save-some-buffers'.
+Test the 3 cases for the second argument PRED, i.e., nil, t, or
+predicate.
+The value of `save-some-buffers-default-predicate' is ignored unless
+PRED is nil."
+  (let* ((foo-file-p (lambda () (string-suffix-p ".foo" buffer-file-name)))
+         (bar-file-p (lambda () (string-suffix-p ".bar" buffer-file-name)))
+         (args-results `((nil         nil                      nil nil)
+                         (nil         ,foo-file-p              nil t)
+                         (nil         ,bar-file-p              t nil)
+                         (,foo-file-p nil                      nil t)
+                         (,bar-file-p nil                      t nil)
+
+                         (buffer-modified-p nil                nil nil)
+                         (t           nil                      nil nil)
+                         (t           ,foo-file-p              nil nil)
+
+                         (,foo-file-p save-some-buffers-root   nil t)
+                         (nil         save-some-buffers-root   nil t)
+                         (,bar-file-p save-some-buffers-root   t   nil)
+                         (t           save-some-buffers-root   nil nil))))
+    (pcase-dolist (`(,pred ,def-pred-bind ,exp-1 ,exp-2) args-results)
+      (files-tests--save-some-buffers pred def-pred-bind exp-1 exp-2))))
+
+(defmacro files-tests--with-buffer-offer-save (buffers-offer fn-test 
fn-binders args-results)
+  "Helper macro to test `save-some-buffers' and `save-buffers-kill-emacs'.
+
+This macro creates several non-file-visiting buffers in different
+directories at the same level, i.e., none of them is a subdir of the
+other.  Then it modifies the buffers and sets their `buffer-offer-save'
+as specified by BUFFERS-OFFER, a list of elements (BUFFER OFFER-SAVE).
+Finally, it calls FN-TEST from the first buffer.
+
+FN-TEST is the function to test: either `save-some-buffers' or
+`save-buffers-kill-emacs'.  This function is called with
+`save-some-buffers-default-predicate' let-bound to a value
+specified inside ARGS-RESULTS.
+
+FN-BINDERS is a list of elements (FUNCTION . BINDING), where FUNCTION
+is a function symbol that this macro temporary binds to BINDING during
+the FN-TEST call.
+
+ARGS-RESULTS is a list of elements (FN-ARGS CALLERS-DIR EXPECTED), where
+FN-ARGS are the arguments for FN-TEST;
+CALLERS-DIR specifies the value to let-bind
+\`save-some-buffers-default-predicate';
+ EXPECTED is the expected result of the test."
+  (declare (debug (form symbol form form)))
+  (let ((dir (gensym "dir"))
+        (buffers (gensym "buffers")))
+    `(let* ((,dir (make-temp-file "testdir" 'dir))
+            (inhibit-message t)
+            (use-dialog-box nil)
+            ,buffers)
+       (pcase-dolist (`(,bufsym ,offer-save) ,buffers-offer)
+         (let* ((buf (generate-new-buffer (symbol-name bufsym)))
+                (subdir (expand-file-name
+                         (format "subdir-%s" (buffer-name buf))
+                         ,dir)))
+           (make-directory subdir 'parens)
+           (push buf ,buffers)
+           (with-current-buffer buf
+             (cd subdir)
+             (setq buffer-offer-save offer-save)
+             (insert "foobar\n"))))
+       (setq ,buffers (nreverse ,buffers))
+       (let ((nb-saved-buffers 0))
+         (unwind-protect
+             (pcase-dolist (`(,fn-test-args ,callers-dir ,expected)
+                            ,args-results)
+               (setq nb-saved-buffers 0)
+               (with-current-buffer (car ,buffers)
+                 (cl-letf
+                     (,@(mapcar (lambda (pair) `((symbol-function ,(car pair)) 
,(cdr pair)))
+                                fn-binders)
+                      (save-some-buffers-default-predicate callers-dir))
+                   (apply #',fn-test fn-test-args)
+                   (should (equal nb-saved-buffers expected)))))
+           ;; Clean up.
+           (dolist (buf ,buffers)
+             (with-current-buffer buf
+               (set-buffer-modified-p nil)
+               (kill-buffer buf)))
+           (delete-directory ,dir 'recursive))))))
+
+(defmacro files-tests-with-all-permutations (permutation list &rest body)
+  "Execute BODY forms for all permutations of LIST.
+Execute the forms with the symbol PERMUTATION bound to the current
+permutation."
+  (declare (indent 2) (debug (symbol form body)))
+  (let ((vec (gensym "vec")))
+    `(let ((,vec (vconcat ,list)))
+       (cl-labels ((swap (,vec i j)
+                         (let ((tmp (aref ,vec j)))
+                           (aset ,vec j (aref ,vec i))
+                           (aset ,vec i tmp)))
+                   (permute (,vec l r)
+                            (if (= l r)
+                                (let ((,permutation (append ,vec nil)))
+                                  ,@body)
+                              (cl-loop for idx from l below (1+ r) do
+                                       (swap ,vec idx l)
+                                       (permute ,vec (1+ l) r)
+                                       (swap ,vec idx l)))))
+         (permute ,vec 0 (1- (length ,vec)))))))
+
+(ert-deftest files-tests-buffer-offer-save ()
+  "Test `save-some-buffers' for non-file-visiting buffers.
+Check the behavior of `save-some-buffers' for non-file-visiting
+buffers under several values of `buffer-offer-save'.
+The value of `save-some-buffers-default-predicate' is ignored unless
+PRED is nil."
+  (let* ((buffers-offer-init '((buf-1 t) (buf-2 always) (buf-3 nil)))
+         (nb-might-save
+          (length
+           (cl-remove-if (lambda (l) (null (cadr l))) buffers-offer-init)))
+         (nb-always-save
+          (length
+           (cl-remove-if-not (lambda (l) (eq 'always (cadr l))) 
buffers-offer-init))))
+    (files-tests-with-all-permutations
+        buffers-offer
+        buffers-offer-init
+      (dolist (pred `(nil t save-some-buffers-root))
+        (dolist (callers-dir `(nil save-some-buffers-root))
+          (let* ((head-offer (cadar buffers-offer))
+                 (res (cond ((null pred)
+                             (if (null callers-dir) nb-always-save (or (and 
head-offer 1) 0)))
+                            (t
+                             ;; Save any buffer with `buffer-offer-save' 
non-nil.
+                             (if (eq pred t) nb-might-save
+                               ;; Restrict to caller's dir.
+                               (or (and head-offer 1) 0)))))
+                 (args-res `(((nil ,pred) ,callers-dir ,res))))
+            (files-tests--with-buffer-offer-save
+             buffers-offer
+             save-some-buffers
+             ;; Increase counter and answer 'n' when prompted to save a buffer.
+             (('read-event . (lambda (&rest _) (cl-incf nb-saved-buffers) ?n)))
+             args-res)))))))
+
+(ert-deftest files-tests-save-buffers-kill-emacs--asks-to-save-buffers ()
+  "Test that `save-buffers-kill-emacs' asks to save buffers as expected.
+Prompt users for any modified buffer with `buffer-offer-save' non-nil."
+  (let* ((buffers-offer-init '((buf-1 t) (buf-2 always) (buf-3 nil)))
+         (nb-might-save
+          (length
+           (cl-remove-if (lambda (l) (null (cadr l))) buffers-offer-init))))
+    (files-tests-with-all-permutations
+        buffers-offer
+        buffers-offer-init
+      (files-tests--with-buffer-offer-save
+       buffers-offer
+       save-buffers-kill-emacs
+       ;; Increase counter and answer 'n' when prompted to save a buffer.
+       (('read-event . (lambda (&rest _) (cl-incf nb-saved-buffers) ?n))
+        ('kill-emacs . #'ignore)) ; Do not kill Emacs.
+       `((nil nil ,nb-might-save)
+         ;; `save-some-buffers-default-predicate' (i.e. the 2nd element) is 
ignored.
+         (nil save-some-buffers-root ,nb-might-save))))))
+
+
 (provide 'files-tests)
 ;;; files-tests.el ends here
diff --git a/test/lisp/international/ucs-normalize-tests.el 
b/test/lisp/international/ucs-normalize-tests.el
index 51f4ed3..2b489dc 100644
--- a/test/lisp/international/ucs-normalize-tests.el
+++ b/test/lisp/international/ucs-normalize-tests.el
@@ -233,6 +233,7 @@ implementations:
 
 (ert-deftest ucs-normalize-part1 ()
   :tags '(:expensive-test)
+  (skip-unless (not (getenv "EMACS_HYDRA_CI"))) ; SLOW ~ 1800s
   ;; This takes a long time, so make sure we're compiled.
   (dolist (fun '(ucs-normalize-tests--part1-rule2
                  ucs-normalize-tests--rule1-failing-for-partX
diff --git a/test/lisp/mail/rfc6068-tests.el b/test/lisp/mail/rfc6068-tests.el
new file mode 100644
index 0000000..caf8230
--- /dev/null
+++ b/test/lisp/mail/rfc6068-tests.el
@@ -0,0 +1,52 @@
+;;; rfc6068-tests.el --- Tests for rfc6068.el  -*- lexical-binding:t -*-
+
+;; Copyright (C) 2020-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 'rfc6068)
+
+(ert-deftest rfc6068-unhexify-string ()
+  (should (equal (rfc6068-unhexify-string "hello%20there") "hello there"))
+  (should (equal (rfc6068-unhexify-string "caf%C3%A9") "café")))
+
+(ert-deftest rfc6068-parse-mailto-url ()
+  (should
+   (equal
+    (rfc6068-parse-mailto-url "mailto:foo@example.org?subject=Foo&bar=baz";)
+    '(("To" . "foo@example.org") ("Subject" . "Foo") ("Bar" . "baz"))))
+  (should
+   (equal
+    (rfc6068-parse-mailto-url "mailto:foo@bar.com?to=bar@example.org";)
+    '(("To" . "foo@bar.com, bar@example.org"))))
+  (should
+   (equal (rfc6068-parse-mailto-url "mailto:foo@bar.com?subject=bar%20baz";)
+          '(("To" . "foo@bar.com") ("Subject" . "bar baz"))))
+  (should
+   (equal (rfc6068-parse-mailto-url 
"mailto:foo@bar.com?subject=bar%20baz&to=other@bar.com";)
+          '(("Subject" . "bar baz") ("To" . "foo@bar.com, other@bar.com"))))
+  (should
+   (equal (rfc6068-parse-mailto-url 
"mailto:user@example.org?subject=caf%C3%A9&body=caf%C3%A9";)
+          '(("To" . "user@example.org") ("Subject" . "café") ("Body" . 
"café")))))
+
+(provide 'rfc6068-tests)
+
+;;; rfc6068-tests.el ends here
diff --git a/test/lisp/mh-e/mh-xface-tests.el b/test/lisp/mh-e/mh-xface-tests.el
new file mode 100644
index 0000000..65e3c82
--- /dev/null
+++ b/test/lisp/mh-e/mh-xface-tests.el
@@ -0,0 +1,35 @@
+;;; mh-xface-tests.el --- tests for mh-xface.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/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'mh-xface)
+
+(ert-deftest mh-x-image-url-sane-p ()
+  "Test that `mh-x-image-url-sane-p' accepts a URL exactly if it is sane."
+  (should (equal (mh-x-image-url-sane-p (concat "http://";
+                                                (make-string 101 ?a)))
+                 nil))                  ;too long
+  (should (equal (mh-x-image-url-sane-p "http") nil)) ;too short
+  (should (equal (mh-x-image-url-sane-p "http:") t))
+  (should (equal (mh-x-image-url-sane-p "https") nil)) ;too short
+  (should (equal (mh-x-image-url-sane-p "https:") t))
+  (should (equal (mh-x-image-url-sane-p "https://www.example.com/me.png";) t))
+  (should (equal (mh-x-image-url-sane-p "abcde:") nil)))
diff --git a/test/lisp/net/socks-tests.el b/test/lisp/net/socks-tests.el
index 71bdd74..c0f90bc 100644
--- a/test/lisp/net/socks-tests.el
+++ b/test/lisp/net/socks-tests.el
@@ -95,7 +95,7 @@
       ;; From fedora.org: 2605:bc80:3010:600:dead:beef:cafe:fed9
       ;; 5004 ~~> Version Status (OK) NOOP Addr-Type (4 -> IPv6)
       (socks-filter proc "\5\0\0\4\x26\x05\xbc\x80\x30\x10\x00\x60")
-      (ert-info ("State still waiting and response emtpy")
+      (ert-info ("State still waiting and response empty")
         (should (eq (process-get proc 'socks-state) socks-state-waiting))
         (should-not (process-get proc 'socks-response)))
       (ert-info ("Scratch field holds partial payload of pending msg")
diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el
index 3008861..27b37d4 100644
--- a/test/lisp/net/tramp-tests.el
+++ b/test/lisp/net/tramp-tests.el
@@ -177,6 +177,19 @@ The temporary file is not created."
     (make-temp-name "tramp-test")
     (if local temporary-file-directory tramp-test-temporary-file-directory))))
 
+;; Method "smb" supports `make-symbolic-link' only if the remote host
+;; has CIFS capabilities.  tramp-adb.el, tramp-gvfs.el, tramp-rclone.el
+;; and tramp-sshfs.el do not support symbolic links at all.
+(defmacro tramp--test-ignore-make-symbolic-link-error (&rest body)
+  "Run BODY, ignoring \"make-symbolic-link not supported\" file error."
+  (declare (indent defun) (debug (body)))
+  `(condition-case err
+       (progn ,@body)
+     (file-error
+      (unless (string-equal (error-message-string err)
+                           "make-symbolic-link not supported")
+       (signal (car err) (cdr err))))))
+
 ;; Don't print messages in nested `tramp--test-instrument-test-case' calls.
 (defvar tramp--test-instrument-test-case-p nil
   "Whether `tramp--test-instrument-test-case' run.
@@ -2866,7 +2879,8 @@ This tests also `file-directory-p' and 
`file-accessible-directory-p'."
                       (file-name-nondirectory tmp-name1) tmp-name2))
           (tmp-name4 (expand-file-name "foo" tmp-name1))
           (tmp-name5 (expand-file-name "foo" tmp-name2))
-          (tmp-name6 (expand-file-name "foo" tmp-name3)))
+          (tmp-name6 (expand-file-name "foo" tmp-name3))
+          (tmp-name7 (tramp--test-make-temp-name nil quoted)))
 
       ;; Copy complete directory.
       (unwind-protect
@@ -2922,7 +2936,48 @@ This tests also `file-directory-p' and 
`file-accessible-directory-p'."
        ;; Cleanup.
        (ignore-errors
          (delete-directory tmp-name1 'recursive)
-         (delete-directory tmp-name2 'recursive))))))
+         (delete-directory tmp-name2 'recursive)))
+
+      ;; Copy symlink to directory.  Implemented since Emacs 28.1.
+      (when (boundp 'copy-directory-create-symlink)
+       (dolist (copy-directory-create-symlink '(nil t))
+         (unwind-protect
+             (tramp--test-ignore-make-symbolic-link-error
+               ;; Copy to file name.
+               (make-directory tmp-name1)
+               (write-region "foo" nil tmp-name4)
+               (make-symbolic-link tmp-name1 tmp-name7)
+               (should (file-directory-p tmp-name1))
+               (should (file-exists-p tmp-name4))
+               (should (file-symlink-p tmp-name7))
+               (copy-directory tmp-name7 tmp-name2)
+               (if copy-directory-create-symlink
+                   (should
+                    (string-equal
+                     (file-symlink-p tmp-name2) (file-symlink-p tmp-name7)))
+                 (should (file-directory-p tmp-name2)))
+               ;; Copy to directory name.
+               (delete-directory tmp-name2 'recursive)
+               (make-directory tmp-name2)
+               (should (file-directory-p tmp-name2))
+               (copy-directory tmp-name7 (file-name-as-directory tmp-name2))
+               (if copy-directory-create-symlink
+                   (should
+                    (string-equal
+                     (file-symlink-p
+                      (expand-file-name
+                       (file-name-nondirectory tmp-name7) tmp-name2))
+                     (file-symlink-p tmp-name7)))
+                 (should
+                  (file-directory-p
+                   (expand-file-name
+                    (file-name-nondirectory tmp-name7) tmp-name2)))))
+
+           ;; Cleanup.
+           (ignore-errors
+             (delete-directory tmp-name1 'recursive)
+             (delete-directory tmp-name2 'recursive)
+             (delete-directory tmp-name7 'recursive))))))))
 
 (ert-deftest tramp-test16-directory-files ()
   "Check `directory-files'."
@@ -3266,19 +3321,6 @@ This tests also `file-directory-p' and 
`file-accessible-directory-p'."
        (ignore-errors (kill-buffer buffer))
        (ignore-errors (delete-directory tmp-name1 'recursive))))))
 
-;; Method "smb" supports `make-symbolic-link' only if the remote host
-;; has CIFS capabilities.  tramp-adb.el, tramp-gvfs.el, tramp-rclone.el
-;; and tramp-sshfs.el do not support symbolic links at all.
-(defmacro tramp--test-ignore-make-symbolic-link-error (&rest body)
-  "Run BODY, ignoring \"make-symbolic-link not supported\" file error."
-  (declare (indent defun) (debug (body)))
-  `(condition-case err
-       (progn ,@body)
-     (file-error
-      (unless (string-equal (error-message-string err)
-                           "make-symbolic-link not supported")
-       (signal (car err) (cdr err))))))
-
 (ert-deftest tramp-test18-file-attributes ()
   "Check `file-attributes'.
 This tests also `access-file', `file-readable-p',
@@ -4535,16 +4577,51 @@ This tests also `make-symbolic-link', `file-truename' 
and `add-name-to-file'."
        ;; Cleanup.
        (ignore-errors (delete-process proc)))
 
+      ;; Process connection type.
+      (when (and (tramp--test-sh-p)
+                (not (tramp-direct-async-process-p))
+                ;; `executable-find' has changed the number of
+                ;; parameters in Emacs 27.1, so we use `apply' for
+                ;; older Emacsen.
+                (ignore-errors
+                  (with-no-warnings
+                    (apply #'executable-find '("hexdump" remote)))))
+       (dolist (process-connection-type '(nil pipe t pty))
+         (unwind-protect
+             (with-temp-buffer
+               (setq proc
+                     (start-file-process
+                      (format "test4-%s" process-connection-type)
+                      (current-buffer) "hexdump" "-v" "-e" "/1 \"%02X\n\""))
+               (should (processp proc))
+               (should (equal (process-status proc) 'run))
+               (process-send-string proc "foo\r\n")
+               (process-send-eof proc)
+               ;; Read output.
+               (with-timeout (10 (tramp--test-timeout-handler))
+                 (while (< (- (point-max) (point-min))
+                           (length "66\n6F\n6F\n0D\n0A\n"))
+                   (while (accept-process-output proc 0 nil t))))
+               (should
+                (string-match-p
+                 (if (memq process-connection-type '(nil pipe))
+                     "66\n6F\n6F\n0D\n0A\n"
+                   "66\n6F\n6F\n0A\n0A\n")
+                 (buffer-string))))
+
+           ;; Cleanup.
+           (ignore-errors (delete-process proc)))))
+
       ;; PTY.
       (unwind-protect
          (with-temp-buffer
            ;; It works only for tramp-sh.el, and not direct async processes.
            (if (or (not (tramp--test-sh-p)) (tramp-direct-async-process-p))
                (should-error
-                (start-file-process "test4" (current-buffer) nil)
+                (start-file-process "test5" (current-buffer) nil)
                 :type 'wrong-type-argument)
 
-             (setq proc (start-file-process "test4" (current-buffer) nil))
+             (setq proc (start-file-process "test5" (current-buffer) nil))
              (should (processp proc))
              (should (equal (process-status proc) 'run))
              ;; On MS Windows, `process-tty-name' returns nil.
@@ -4559,8 +4636,9 @@ This tests also `make-symbolic-link', `file-truename' and 
`add-name-to-file'."
   "Define ert test `TEST-direct-async' for direct async processes.
 If UNSTABLE is non-nil, the test is tagged as `:unstable'."
   (declare (indent 1))
-  ;; `make-process' supports file name handlers since Emacs 27.
-  (when (let ((file-name-handler-alist '(("" . #'tramp--test-always))))
+  ;; `make-process' supports file name handlers since Emacs 27.  We
+  ;; cannot use `tramp--test-always' during compilation of the macro.
+  (when (let ((file-name-handler-alist '(("" . (lambda (&rest _) t)))))
          (ignore-errors (make-process :file-handler t)))
     `(ert-deftest ,(intern (concat (symbol-name test) "-direct-async")) ()
        ,docstring
@@ -4753,6 +4831,7 @@ If UNSTABLE is non-nil, the test is tagged as 
`:unstable'."
 
       ;; Process connection type.
       (when (and (tramp--test-sh-p)
+                (not (tramp-direct-async-process-p))
                 ;; `executable-find' has changed the number of
                 ;; parameters in Emacs 27.1, so we use `apply' for
                 ;; older Emacsen.
@@ -4760,34 +4839,41 @@ If UNSTABLE is non-nil, the test is tagged as 
`:unstable'."
                   (with-no-warnings
                     (apply #'executable-find '("hexdump" remote)))))
        (dolist (connection-type '(nil pipe t pty))
-         (unwind-protect
-             (with-temp-buffer
-               (setq proc
-                     (with-no-warnings
-                       (make-process
-                        :name (format "test7-%s" connection-type)
-                        :buffer (current-buffer)
-                        :connection-type connection-type
-                        :command '("hexdump" "-v" "-e" "/1 \"%02X\n\"")
-                        :file-handler t)))
-               (should (processp proc))
-               (should (equal (process-status proc) 'run))
-               (process-send-string proc "foo\r\n")
-               (process-send-eof proc)
-               ;; Read output.
-               (with-timeout (10 (tramp--test-timeout-handler))
-                 (while (< (- (point-max) (point-min))
-                           (length "66\n6F\n6F\n0D\n0A\n"))
-                   (while (accept-process-output proc 0 nil t))))
-               (should
-                (string-match-p
-                 (if (memq connection-type '(nil pipe))
-                     "66\n6F\n6F\n0D\n0A\n"
-                   "66\n6F\n6F\n0A\n0A\n")
-                 (buffer-string))))
+         ;; `process-connection-type' is taken when
+         ;; `:connection-type' is nil.
+         (dolist (process-connection-type
+                  (unless connection-type '(nil pipe t pty)))
+           (unwind-protect
+               (with-temp-buffer
+                 (setq proc
+                       (with-no-warnings
+                         (make-process
+                          :name
+                          (format "test7-%s-%s"
+                                  connection-type process-connection-type)
+                          :buffer (current-buffer)
+                          :connection-type connection-type
+                          :command '("hexdump" "-v" "-e" "/1 \"%02X\n\"")
+                          :file-handler t)))
+                 (should (processp proc))
+                 (should (equal (process-status proc) 'run))
+                 (process-send-string proc "foo\r\n")
+                 (process-send-eof proc)
+                 ;; Read output.
+                 (with-timeout (10 (tramp--test-timeout-handler))
+                   (while (< (- (point-max) (point-min))
+                             (length "66\n6F\n6F\n0D\n0A\n"))
+                     (while (accept-process-output proc 0 nil t))))
+                 (should
+                  (string-match-p
+                   (if (memq (or connection-type process-connection-type)
+                             '(nil pipe))
+                       "66\n6F\n6F\n0D\n0A\n"
+                     "66\n6F\n6F\n0A\n0A\n")
+                   (buffer-string))))
 
-           ;; Cleanup.
-           (ignore-errors (delete-process proc))))))))
+             ;; Cleanup.
+             (ignore-errors (delete-process proc)))))))))
 
 (tramp--test--deftest-direct-async-process tramp-test30-make-process
   "Check direct async `make-process'.")
@@ -6358,6 +6444,7 @@ This requires restrictions of file name syntax."
 ;; These tests are inspired by Bug#17238.
 (ert-deftest tramp-test41-special-characters ()
   "Check special characters in file names."
+  (skip-unless (not (getenv "EMACS_HYDRA_CI"))) ; SLOW ~ 245s
   (skip-unless (tramp--test-enabled))
   (skip-unless (not (tramp--test-rsync-p)))
   (skip-unless (or (tramp--test-emacs26-p) (not (tramp--test-rclone-p))))
@@ -6368,6 +6455,7 @@ This requires restrictions of file name syntax."
   "Check special characters in file names.
 Use the `stat' command."
   :tags '(:expensive-test)
+  (skip-unless (not (getenv "EMACS_HYDRA_CI"))) ; SLOW ~ 287s
   (skip-unless (tramp--test-enabled))
   (skip-unless (tramp--test-sh-p))
   (skip-unless (not (tramp--test-rsync-p)))
@@ -6386,6 +6474,7 @@ Use the `stat' command."
   "Check special characters in file names.
 Use the `perl' command."
   :tags '(:expensive-test)
+  (skip-unless (not (getenv "EMACS_HYDRA_CI"))) ; SLOW ~ 266s
   (skip-unless (tramp--test-enabled))
   (skip-unless (tramp--test-sh-p))
   (skip-unless (not (tramp--test-rsync-p)))
@@ -6407,6 +6496,7 @@ Use the `perl' command."
   "Check special characters in file names.
 Use the `ls' command."
   :tags '(:expensive-test)
+  (skip-unless (not (getenv "EMACS_HYDRA_CI"))) ; SLOW ~ 287s
   (skip-unless (tramp--test-enabled))
   (skip-unless (tramp--test-sh-p))
   (skip-unless (not (tramp--test-rsync-p)))
@@ -6472,6 +6562,7 @@ Use the `ls' command."
 
 (ert-deftest tramp-test42-utf8 ()
   "Check UTF8 encoding in file names and file contents."
+  (skip-unless (not (getenv "EMACS_HYDRA_CI"))) ; SLOW ~ 620s
   (skip-unless (tramp--test-enabled))
   (skip-unless (not (tramp--test-docker-p)))
   (skip-unless (not (tramp--test-rsync-p)))
@@ -6487,6 +6578,7 @@ Use the `ls' command."
   "Check UTF8 encoding in file names and file contents.
 Use the `stat' command."
   :tags '(:expensive-test)
+  (skip-unless (not (getenv "EMACS_HYDRA_CI"))) ; SLOW ~ 595s
   (skip-unless (tramp--test-enabled))
   (skip-unless (tramp--test-sh-p))
   (skip-unless (not (tramp--test-docker-p)))
@@ -6509,6 +6601,7 @@ Use the `stat' command."
   "Check UTF8 encoding in file names and file contents.
 Use the `perl' command."
   :tags '(:expensive-test)
+  (skip-unless (not (getenv "EMACS_HYDRA_CI"))) ; SLOW ~ 620s
   (skip-unless (tramp--test-enabled))
   (skip-unless (tramp--test-sh-p))
   (skip-unless (not (tramp--test-docker-p)))
@@ -6534,6 +6627,7 @@ Use the `perl' command."
   "Check UTF8 encoding in file names and file contents.
 Use the `ls' command."
   :tags '(:expensive-test)
+  (skip-unless (not (getenv "EMACS_HYDRA_CI"))) ; SLOW ~ 690s
   (skip-unless (tramp--test-enabled))
   (skip-unless (tramp--test-sh-p))
   (skip-unless (not (tramp--test-docker-p)))
diff --git a/test/lisp/newcomment-tests.el b/test/lisp/newcomment-tests.el
new file mode 100644
index 0000000..5485673
--- /dev/null
+++ b/test/lisp/newcomment-tests.el
@@ -0,0 +1,39 @@
+;;; newcomment-tests.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)
+
+(ert-deftest test-uncomment-space-comment-continue ()
+  (let ((comment-style 'multi-line)
+        (comment-continue "   ")
+        (text "  a\n  b"))
+    (should
+     (equal text
+            (with-temp-buffer
+              (c-mode)
+              (insert text)
+              (comment-region (point-min) (point-max))
+              (uncomment-region (point-min) (point-max))
+              (buffer-string))))))
+
+;;; newcomment-testsuite.el ends here
diff --git a/test/lisp/mail/rfc2368-tests.el 
b/test/lisp/obsolete/rfc2368-tests.el
similarity index 100%
rename from test/lisp/mail/rfc2368-tests.el
rename to test/lisp/obsolete/rfc2368-tests.el
diff --git a/test/lisp/progmodes/cperl-mode-resources/here-docs.pl 
b/test/lisp/progmodes/cperl-mode-resources/here-docs.pl
index 8af4625..bb3d487 100644
--- a/test/lisp/progmodes/cperl-mode-resources/here-docs.pl
+++ b/test/lisp/progmodes/cperl-mode-resources/here-docs.pl
@@ -17,7 +17,7 @@ For each of the HERE documents, the following checks will 
done:
 
 =item *
 
-All occurrences of the string "look-here" are fontified correcty.
+All occurrences of the string "look-here" are fontified correctly.
 Note that we deliberately test the face, not the syntax property:
 Users won't care for the syntax property, but they see the face.
 Different implementations with different syntax properties have been
diff --git a/test/lisp/progmodes/cperl-mode-tests.el 
b/test/lisp/progmodes/cperl-mode-tests.el
index 4d2bac6..5f3ba4d 100644
--- a/test/lisp/progmodes/cperl-mode-tests.el
+++ b/test/lisp/progmodes/cperl-mode-tests.el
@@ -154,16 +154,106 @@ point in the distant past, and is still broken in 
perl-mode. "
     (should (equal (get-text-property (match-beginning 0) 'face)
                    'font-lock-keyword-face))))
 
+(ert-deftest cperl-test-identify-heredoc ()
+  "Test whether a construct containing \"<<\" followed by a
+  bareword is properly identified for a here-document if
+  appropriate."
+  (let ((here-docs
+         '("$text .= <<DELIM;"          ; mutator concatenating a here-doc
+           "func($arg) . <<DELIM;"      ; concatenating a return value
+           "func 1, <<DELIM;"           ; a function taking two arguments
+           ))
+        ;; There forms are currently mishandled in `perl-mode' :-(
+        (here-docs-cperl
+         '("print {a} <<DELIM;"         ; printing to a file handle
+           "system $prog <<DELIM;"      ; lie about the program's name
+           ))
+        (_undecidable
+         '("foo <<bar")                 ; could be either "foo() <<bar"
+                                        ; or "foo(<<bar)"
+         ))
+    (dolist (code (append here-docs (if (eq cperl-test-mode #'cperl-mode)
+                                        here-docs-cperl)))
+      (with-temp-buffer
+        (insert code "\n\nDELIM\n")
+        (funcall cperl-test-mode)
+        (goto-char (point-min))
+        (forward-line 1)
+        ;; We should now be within a here-doc.
+        (let ((ppss (syntax-ppss)))
+          (should (and (nth 8 ppss) (nth 4 ppss))))
+        ))))
+
+(ert-deftest cperl-test-identify-no-heredoc ()
+  "Test whether a construct containing \"<<\" which is not a
+  here-document is properly rejected."
+  (let (
+        (not-here-docs
+         '("while (<<>>) {"             ; double angle bracket operator
+           "expr <<func();"             ; left shift by a return value
+           "$var <<func;"               ; left shift by a return value
+           "($var+1) <<func;"           ; same for an expression
+           "$hash{key} <<func;"         ; same for a hash element
+           "or $var <<func;"            ; same for an expression
+           "sorted $by <<func"          ; _not_ a call to sort
+           ))
+        (_undecidable
+         '("foo <<bar"                  ; could be either "foo() <<bar"
+                                        ; or "foo(<<bar)"
+           "$foo = <<;")                ; empty delim forbidden since 5.28
+         ))
+    (dolist (code not-here-docs)
+      (with-temp-buffer
+        (insert code "\n\n")
+        (funcall cperl-test-mode)
+        (goto-char (point-min))
+        (forward-line 1)
+        ;; Point is not within a here-doc (nor string nor comment).
+        (let ((ppss (syntax-ppss)))
+          (should-not (nth 8 ppss)))
+        ))))
+
+(ert-deftest cperl-test-here-doc-missing-end ()
+  "Verify that a missing here-document terminator gives a message.
+This message prints the terminator which wasn't found and is only
+issued by CPerl mode."
+  (skip-unless (eq cperl-test-mode #'cperl-mode))
+  (ert-with-message-capture collected-messages
+    (with-temp-buffer
+      (insert "my $foo = <<HERE\n")
+      (insert "some text here\n")
+      (goto-char (point-min))
+      (funcall cperl-test-mode)
+      (cperl-find-pods-heres)
+      (should (string-match "End of here-document [‘'`]HERE[’']"
+                            collected-messages))))
+  (ert-with-message-capture collected-messages
+    (with-temp-buffer
+      (insert "my $foo = <<HERE . <<'THERE'\n")
+      (insert "some text here\n")
+      (insert "HERE\n")
+      (insert "more text here\n")
+      (goto-char (point-min))
+      (funcall cperl-test-mode)
+      (cperl-find-pods-heres)
+      (should (string-match "End of here-document [‘'`]THERE[’']"
+                            collected-messages)))))
+
 (defvar perl-continued-statement-offset)
 (defvar perl-indent-level)
 
+(defconst cperl--tests-heredoc-face
+  (if (equal cperl-test-mode 'perl-mode) 'perl-heredoc
+    'font-lock-string-face))
+(defconst cperl--tests-heredoc-delim-face
+  (if (equal cperl-test-mode 'perl-mode) 'perl-heredoc
+    'font-lock-constant-face))
+
 (ert-deftest cperl-test-heredocs ()
   "Test that HERE-docs are fontified with the appropriate face."
   (require 'perl-mode)
   (let ((file (ert-resource-file "here-docs.pl"))
         (cperl-continued-statement-offset perl-continued-statement-offset)
-        (target-font (if (equal cperl-test-mode 'perl-mode) 'perl-heredoc
-                       'font-lock-string-face))
         (case-fold-search nil))
     (with-temp-buffer
       (insert-file-contents file)
@@ -176,7 +266,7 @@ point in the distant past, and is still broken in 
perl-mode. "
           (while (search-forward "look-here" nil t)
             (should (equal
                      (get-text-property (match-beginning 0) 'face)
-                     target-font))
+                     cperl--tests-heredoc-face))
             (beginning-of-line)
             (should (null (looking-at "[ \t]")))
             (forward-line 1)))
@@ -339,6 +429,72 @@ under timeout control."
       (should (string-match
                "poop ('foo', \n      'bar')" (buffer-string))))))
 
+(ert-deftest cperl-test-bug-14343 ()
+  "Verify that inserting text into a HERE-doc string with Elisp
+does not break fontification."
+  (with-temp-buffer
+    (insert "my $string = <<HERE;\n"
+            "One line of text.\n"
+            "Last line of this string.\n"
+            "HERE\n")
+    (funcall cperl-test-mode)
+    (font-lock-ensure)
+    (goto-char (point-min))
+    (search-forward "One line")
+    (should (equal (get-text-property (point) 'face)
+                   cperl--tests-heredoc-face))
+    (beginning-of-line)
+    (insert "Another line if text.\n")
+    (font-lock-ensure)
+    (forward-line -1)
+    (should (equal (get-text-property (point) 'face)
+                   cperl--tests-heredoc-face))
+    (search-forward "HERE")
+    (beginning-of-line)
+    (should (equal (get-text-property (point) 'face)
+                   cperl--tests-heredoc-delim-face)))
+  ;; insert into an empty here-document
+  (with-temp-buffer
+    (insert "print <<HERE;\n"
+            "HERE\n")
+    (funcall cperl-test-mode)
+    (font-lock-ensure)
+    (goto-char (point-min))
+    (forward-line)
+    (should (equal (get-text-property (point) 'face)
+                   cperl--tests-heredoc-delim-face))
+    ;; Insert a newline into the empty here-document
+    (goto-char (point-min))
+    (forward-line)
+    (insert "\n")
+    (search-forward "HERE")
+    (beginning-of-line)
+    (should (equal (get-text-property (point) 'face)
+                   cperl--tests-heredoc-delim-face))
+    ;; Insert text at the beginning of the here-doc
+    (goto-char (point-min))
+    (forward-line)
+    (insert "text")
+    (font-lock-ensure)
+    (search-backward "text")
+    (should (equal (get-text-property (point) 'face)
+                   cperl--tests-heredoc-face))
+    (search-forward "HERE")
+    (beginning-of-line)
+    (should (equal (get-text-property (point) 'face)
+                   cperl--tests-heredoc-delim-face))
+    ;; Insert a new line immediately before the delimiter
+    ;; (That's where the point is anyway)
+    (insert "A new line\n")
+    (font-lock-ensure)
+    ;; The delimiter is still the delimiter
+    (should (equal (get-text-property (point) 'face)
+                   cperl--tests-heredoc-delim-face))
+    (forward-line -1)
+    ;; The new line has been "added" to the here-document
+    (should (equal (get-text-property (point) 'face)
+                   cperl--tests-heredoc-face))))
+
 (ert-deftest cperl-test-bug-16368 ()
   "Verify that `cperl-forward-group-in-re' doesn't hide errors."
   (skip-unless (eq cperl-test-mode #'cperl-mode))
diff --git a/test/lisp/progmodes/project-tests.el 
b/test/lisp/progmodes/project-tests.el
index 68460a9..1e3f258 100644
--- a/test/lisp/progmodes/project-tests.el
+++ b/test/lisp/progmodes/project-tests.el
@@ -107,4 +107,19 @@ directory name (Bug#48471)."
                      collect (file-relative-name file dir))))
       (should (equal relative-files '("some-file"))))))
 
+(ert-deftest project-ignores-bug-50240 ()
+  "Check that `project-files' does not ignore all files.
+When `project-ignores' includes a name matching project dir."
+  (skip-unless (executable-find find-program))
+  (project-tests--with-temporary-directory dir
+    (make-empty-file (expand-file-name "some-file" dir))
+    (let* ((project (make-project-tests--trivial
+                     :root (file-name-as-directory dir)
+                     :ignores (list (file-name-nondirectory
+                                     (directory-file-name dir)))))
+           (files (project-files project)))
+      (should (equal files
+                     (list
+                      (expand-file-name "some-file" dir)))))))
+
 ;;; project-tests.el ends here
diff --git a/test/lisp/progmodes/sh-script-tests.el 
b/test/lisp/progmodes/sh-script-tests.el
new file mode 100644
index 0000000..c21010c
--- /dev/null
+++ b/test/lisp/progmodes/sh-script-tests.el
@@ -0,0 +1,51 @@
+;;; sh-script-tests.el --- Tests for sh-script.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 'sh-script)
+(require 'ert)
+
+(ert-deftest test-sh-script-indentation ()
+  (with-temp-buffer
+    (insert "relative-path/to/configure --prefix=$prefix\\
+             --with-x")
+    (shell-script-mode)
+    (goto-char (point-min))
+    (forward-line 1)
+    (indent-for-tab-command)
+    (should (equal
+             (buffer-substring-no-properties (point-min) (point-max))
+             "relative-path/to/configure --prefix=$prefix\\
+                          --with-x"))))
+
+(ert-deftest test-basic-sh-indentation ()
+  (with-temp-buffer
+    (insert "myecho () {\necho foo\n}\n")
+    (shell-script-mode)
+    (indent-region (point-min) (point-max))
+    (should (equal (buffer-string)
+  "myecho () {
+    echo foo
+}
+"))))
+
+;;; sh-script-tests.el ends here
diff --git a/test/lisp/progmodes/xref-tests.el 
b/test/lisp/progmodes/xref-tests.el
index d294522..ff4b647 100644
--- a/test/lisp/progmodes/xref-tests.el
+++ b/test/lisp/progmodes/xref-tests.el
@@ -52,6 +52,14 @@
     (should (string-match-p "file1\\.txt\\'" (xref-location-group (nth 0 
locs))))
     (should (string-match-p "file2\\.txt\\'" (xref-location-group (nth 1 
locs))))))
 
+(ert-deftest xref-matches-in-directory-filters-with-ignores ()
+  (let ((locs (xref-matches-in-directory "bar" "*" xref-tests--data-dir
+                                         '("./file1.*"))))
+    (should (= 1 (length locs)))
+    (should (string-match-p "file2\\.txt\\'" (xref-location-group
+                                              (xref-item-location
+                                               (nth 0 locs)))))))
+
 (ert-deftest xref-matches-in-directory-finds-two-matches-on-the-same-line ()
   (let ((locs (xref-tests--locations-in-data-dir "foo")))
     (should (= 2 (length locs)))
diff --git a/test/lisp/shadowfile-tests.el b/test/lisp/shadowfile-tests.el
index c571dc3..1ab539f 100644
--- a/test/lisp/shadowfile-tests.el
+++ b/test/lisp/shadowfile-tests.el
@@ -664,7 +664,29 @@ guaranteed by the originator of a cluster definition."
          (should (member (format "/%s:%s" cluster2 (file-local-name file2))
                           (car shadow-literal-groups)))
           ;; Bug#49596.
-         (should (member (concat primary file1) (car shadow-literal-groups))))
+         (should (member (concat primary file1) (car shadow-literal-groups)))
+
+          ;; Error handling.
+          (setq shadow-literal-groups nil)
+          ;; There's no `buffer-file-name'.
+          (with-temp-buffer
+            (call-interactively #'shadow-define-literal-group)
+            (set-buffer-modified-p nil))
+          (should-not shadow-literal-groups)
+         ;; Define an empty literal group.
+         (setq mocked-input `(,(kbd "RET")))
+         (with-temp-buffer
+            (set-visited-file-name file1)
+           (call-interactively #'shadow-define-literal-group)
+            (set-buffer-modified-p nil))
+          (should-not shadow-literal-groups)
+          ;; Use a non-existing site name.
+         (setq mocked-input `("foo" ,(kbd "RET")))
+         (with-temp-buffer
+            (set-visited-file-name file1)
+           (call-interactively #'shadow-define-literal-group)
+            (set-buffer-modified-p nil))
+          (should-not shadow-literal-groups))
 
       ;; Cleanup.
       (shadow--tests-cleanup))))
diff --git a/test/lisp/simple-tests.el b/test/lisp/simple-tests.el
index 4b153d1..3ece612 100644
--- a/test/lisp/simple-tests.el
+++ b/test/lisp/simple-tests.el
@@ -959,6 +959,17 @@ See Bug#21722."
       (with-shell-command-dont-erase-buffer str output-buffer-is-current
         (should (= (point) (alist-get shell-command-dont-erase-buffer 
expected-point)))))))
 
+(ert-deftest test-undo-region ()
+  (with-temp-buffer
+    (insert "This is a test\n")
+    (goto-char (point-min))
+    (setq buffer-undo-list nil)
+    (downcase-word 1)
+    (should (= (length (delq nil (undo-make-selective-list 1 9))) 2))
+    (should (= (length (delq nil (undo-make-selective-list 4 9))) 1))
+    ;; FIXME this is the off-by-one error case.
+    ;;(should (= (length (delq nil (undo-make-selective-list 5 9))) 0))
+    (should (= (length (delq nil (undo-make-selective-list 6 9))) 0))))
 
 (provide 'simple-test)
 ;;; simple-test.el ends here
diff --git a/test/lisp/subr-tests.el b/test/lisp/subr-tests.el
index 21b8a27..54bee7b 100644
--- a/test/lisp/subr-tests.el
+++ b/test/lisp/subr-tests.el
@@ -62,6 +62,25 @@
                       (0 font-lock-keyword-face))))))))
 
 
+;;;; List functions.
+
+(ert-deftest subr-test-caaar ()
+  (should (null (caaar '())))
+  (should (null (caaar '(() (2)))))
+  (should (null (caaar '((() (2)) (a b)))))
+  (should-error (caaar '(1 2)) :type 'wrong-type-argument)
+  (should-error (caaar '((1 2))) :type 'wrong-type-argument)
+  (should (=  1 (caaar '(((1 2) (3 4))))))
+  (should (null (caaar '((() (3 4)))))))
+
+(ert-deftest subr-test-caadr ()
+  (should (null (caadr '())))
+  (should (null (caadr '(1))))
+  (should-error (caadr '(1 2)) :type 'wrong-type-argument)
+  (should (= 2 (caadr '(1 (2 3)))))
+  (should (equal '((2) (3)) (caadr '((1) (((2) (3))) (4))))))
+
+
 ;;;; Keymap support.
 
 (ert-deftest subr-test-kbd ()
@@ -740,5 +759,13 @@ See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=19350.";
                1))
     (should (equal (buffer-string) "new bar zot foobar"))))
 
+(ert-deftest test-with-existing-directory ()
+  (let ((dir (make-temp-name "/tmp/not-exist-")))
+    (let ((default-directory dir))
+      (should-not (file-exists-p default-directory)))
+    (with-existing-directory
+      (should-not (equal dir default-directory))
+      (should (file-exists-p default-directory)))))
+
 (provide 'subr-tests)
 ;;; subr-tests.el ends here
diff --git a/test/lisp/textmodes/fill-tests.el 
b/test/lisp/textmodes/fill-tests.el
index a4c7f44..fcc2c75 100644
--- a/test/lisp/textmodes/fill-tests.el
+++ b/test/lisp/textmodes/fill-tests.el
@@ -54,7 +54,7 @@
              (beg (line-beginning-position))
              (end (line-end-position))
              (fill-prefix (make-string (- pos beg) ?\s))
-             ;; `fill-column' is too small to accomodate the current line
+             ;; `fill-column' is too small to accommodate the current line
              (fill-column (- end beg 10)))
         (fill-region-as-paragraph beg end nil nil pos))
       (should (equal (buffer-string) string)))))
@@ -69,7 +69,7 @@
              (beg (line-beginning-position))
              (end (line-end-position))
              (fill-prefix (make-string (- pos beg) ?\s))
-             ;; `fill-column' is too small to accomodate the current line
+             ;; `fill-column' is too small to accommodate the current line
              (fill-column (- end beg 10)))
         (fill-region-as-paragraph beg end nil nil pos))
       (should (equal
diff --git a/test/lisp/thingatpt-tests.el b/test/lisp/thingatpt-tests.el
index fba6f21..1849480 100644
--- a/test/lisp/thingatpt-tests.el
+++ b/test/lisp/thingatpt-tests.el
@@ -223,4 +223,12 @@ position to retrieve THING.")
   (should (equal (test--number "0xf00" 2) 3840))
   (should (equal (test--number "0xf00" 3) 3840)))
 
+(ert-deftest test-fields ()
+  (with-temp-buffer
+    (insert (propertize "foo" 'field 1) "bar" (propertize "zot" 'field 2))
+    (goto-char 1)
+    (should (eq (symbol-at-point) 'foo))
+    (goto-char 5)
+    (should (eq (symbol-at-point) 'bar))))
+
 ;;; thingatpt.el ends here
diff --git a/test/lisp/vc/vc-tests.el b/test/lisp/vc/vc-tests.el
index 5430535..4169a96 100644
--- a/test/lisp/vc/vc-tests.el
+++ b/test/lisp/vc/vc-tests.el
@@ -52,7 +52,7 @@
 ;; - responsible-p (file)
 ;; - receive-file (file rev)
 ;; - unregister (file)                                          DONE
-;; * checkin (files comment)
+;; * checkin (files comment)                                    DONE
 ;; * find-revision (file rev buffer)
 ;; * checkout (file &optional rev)
 ;; * revert (file &optional contents-done)
@@ -75,7 +75,7 @@
 ;; - show-log-entry (revision)
 ;; - comment-history (file)
 ;; - update-changelog (files)
-;; * diff (files &optional async rev1 rev2 buffer)
+;; * diff (files &optional async rev1 rev2 buffer)              DONE
 ;; - revision-completion-table (files)
 ;; - annotate-command (file buf &optional rev)
 ;; - annotate-time ()
@@ -100,7 +100,7 @@
 ;; - log-edit-mode ()
 ;; - check-headers ()
 ;; - delete-file (file)
-;; - rename-file (old new)
+;; - rename-file (old new)                                      DONE
 ;; - find-file-hook ()
 ;; - extra-menu ()
 ;; - extra-dir-menu ()
@@ -110,6 +110,7 @@
 
 (require 'ert)
 (require 'vc)
+(require 'log-edit)
 
 (declare-function w32-application-type "w32proc.c")
 
@@ -547,6 +548,127 @@ This checks also `vc-backend' and 
`vc-responsible-backend'."
         (if tempdir (delete-directory tempdir t))
         (run-hooks 'vc-test--cleanup-hook)))))
 
+(defun vc-test--rename-file (backend)
+  "Check the rename-file action."
+
+  (let ((vc-handled-backends `(,backend))
+        (default-directory
+          (file-name-as-directory
+           (expand-file-name
+            (make-temp-name "vc-test") temporary-file-directory)))
+        (process-environment process-environment)
+        tempdir
+        vc-test--cleanup-hook)
+    (when (eq backend 'Bzr)
+      (setq tempdir (make-temp-file "vc-test--rename-file" t)
+            process-environment (cons (format "BZR_HOME=%s" tempdir)
+                                      process-environment)))
+
+    (unwind-protect
+        (progn
+          ;; Cleanup.
+          (add-hook
+           'vc-test--cleanup-hook
+           `(lambda () (delete-directory ,default-directory 'recursive)))
+
+          ;; Create empty repository.
+          (make-directory default-directory)
+          (vc-test--create-repo-function backend)
+
+          (let ((tmp-name (expand-file-name "foo" default-directory))
+                (new-name (expand-file-name "bar" default-directory)))
+            ;; Write a new file.
+            (write-region "foo" nil tmp-name nil 'nomessage)
+
+            ;; Register it.  Renaming can fail otherwise.
+            (vc-register
+             (list backend (list (file-name-nondirectory tmp-name))))
+
+            (vc-rename-file tmp-name new-name)
+
+            (should (not (file-exists-p tmp-name)))
+            (should (file-exists-p new-name))
+
+            (should (equal (vc-state new-name)
+                           (if (memq backend '(RCS SCCS))
+                               'up-to-date
+                             'added)))))
+
+      ;; Save exit.
+      (ignore-errors
+        (if tempdir (delete-directory tempdir t))
+        (run-hooks 'vc-test--cleanup-hook)))))
+
+(declare-function log-edit-done "vc/log-edit")
+
+(defun vc-test--version-diff (backend)
+  "Check the diff version of a repository."
+
+  (let ((vc-handled-backends `(,backend))
+        (default-directory
+          (file-name-as-directory
+           (expand-file-name
+            (make-temp-name "vc-test") temporary-file-directory)))
+        (process-environment process-environment)
+        tempdir
+        vc-test--cleanup-hook)
+    (when (eq backend 'Bzr)
+      (setq tempdir (make-temp-file "vc-test--version-diff" t)
+            process-environment (cons (format "BZR_HOME=%s" tempdir)
+                                      process-environment)))
+    (when (memq backend '(Bzr Git))
+      (setq process-environment (cons "EMAIL=john@doe.ee"
+                                      process-environment)))
+    (unwind-protect
+        (progn
+          ;; Cleanup.
+          (add-hook
+           'vc-test--cleanup-hook
+           `(lambda () (delete-directory ,default-directory 'recursive)))
+
+          ;; Create empty repository.  Check repository checkout model.
+          (make-directory default-directory)
+          (vc-test--create-repo-function backend)
+
+          (let* ((tmp-name (expand-file-name "foo" default-directory))
+                 (files (list (file-name-nondirectory tmp-name))))
+            ;; Write and register a new file.
+            (write-region "originaltext" nil tmp-name nil 'nomessage)
+            (vc-register (list backend files))
+
+            (let ((buff (find-file tmp-name)))
+              (with-current-buffer buff
+                (progn
+                  ;; Optionally checkout file.
+                  (when (memq backend '(RCS CVS SCCS))
+                    (vc-checkout tmp-name))
+
+                  ;; Checkin file.
+                  (vc-checkin files backend)
+                  (insert "Testing vc-version-diff")
+                  (log-edit-done))))
+
+            ;; Modify file content.
+            (when (memq backend '(RCS CVS SCCS))
+              (vc-checkout tmp-name))
+            (write-region "updatedtext" nil tmp-name nil 'nomessage)
+
+            ;; Check version diff.
+            (vc-version-diff files nil nil)
+            (should (bufferp (get-buffer "*vc-diff*")))
+
+            (with-current-buffer "*vc-diff*"
+              (progn
+                (let ((rawtext (buffer-substring-no-properties (point-min)
+                                                               (point-max))))
+                  (should (string-search "-originaltext" rawtext))
+                  (should (string-search "+updatedtext" rawtext)))))))
+
+      ;; Save exit.
+      (ignore-errors
+        (if tempdir (delete-directory tempdir t))
+        (run-hooks 'vc-test--cleanup-hook)))))
+
 ;; Create the test cases.
 
 (defun vc-test--rcs-enabled ()
@@ -648,7 +770,35 @@ This checks also `vc-backend' and 
`vc-responsible-backend'."
             (ert-get-test
              ',(intern
                 (format "vc-test-%s01-register" backend-string))))))
-         (vc-test--checkout-model ',backend))))))
+         (vc-test--checkout-model ',backend))
+
+        (ert-deftest
+            ,(intern (format "vc-test-%s05-rename-file" backend-string)) ()
+          ,(format "Check `vc-rename-file' for the %s backend."
+                   backend-string)
+          (skip-unless
+           (ert-test-passed-p
+            (ert-test-most-recent-result
+             (ert-get-test
+              ',(intern
+                 (format "vc-test-%s01-register" backend-string))))))
+          ;; CVS calls vc-delete-file, which insists on prompting
+          ;; "Really want to delete ...?"
+          (skip-unless (not (eq 'CVS ',backend)))
+          (vc-test--rename-file ',backend))
+
+        (ert-deftest
+            ,(intern (format "vc-test-%s06-version-diff" backend-string)) ()
+          ,(format "Check `vc-version-diff' for the %s backend."
+                   backend-string)
+          (skip-unless
+           (ert-test-passed-p
+            (ert-test-most-recent-result
+             (ert-get-test
+              ',(intern
+                 (format "vc-test-%s01-register" backend-string))))))
+          (vc-test--version-diff ',backend))
+        ))))
 
 (provide 'vc-tests)
 ;;; vc-tests.el ends here
diff --git a/test/src/buffer-tests.el b/test/src/buffer-tests.el
index 118311c..059926f 100644
--- a/test/src/buffer-tests.el
+++ b/test/src/buffer-tests.el
@@ -1420,4 +1420,67 @@ with parameters from the *Messages* buffer modification."
     (remove-overlays)
     (should (= (length (overlays-in (point-min) (point-max))) 0))))
 
+(ert-deftest test-kill-buffer-auto-save-default ()
+  (let ((file (make-temp-file "ert"))
+        auto-save)
+    (should (file-exists-p file))
+    ;; Always answer yes.
+    (cl-letf (((symbol-function #'yes-or-no-p) (lambda (_) t)))
+      (unwind-protect
+          (progn
+            (find-file file)
+            (auto-save-mode t)
+            (insert "foo\n")
+            (should buffer-auto-save-file-name)
+            (setq auto-save buffer-auto-save-file-name)
+            (do-auto-save)
+            (should (file-exists-p auto-save))
+            (kill-buffer (current-buffer))
+            (should (file-exists-p auto-save)))
+        (ignore-errors (delete-file file))
+        (when auto-save
+          (ignore-errors (delete-file auto-save)))))))
+
+(ert-deftest test-kill-buffer-auto-save-delete ()
+  (let ((file (make-temp-file "ert"))
+        auto-save)
+    (should (file-exists-p file))
+    (setq kill-buffer-delete-auto-save-files t)
+    ;; Always answer yes.
+    (cl-letf (((symbol-function #'yes-or-no-p) (lambda (_) t)))
+      (unwind-protect
+          (progn
+            (find-file file)
+            (auto-save-mode t)
+            (insert "foo\n")
+            (should buffer-auto-save-file-name)
+            (setq auto-save buffer-auto-save-file-name)
+            (do-auto-save)
+            (should (file-exists-p auto-save))
+            ;; This should delete the auto-save file.
+            (kill-buffer (current-buffer))
+            (should-not (file-exists-p auto-save)))
+        (ignore-errors (delete-file file))
+        (when auto-save
+          (ignore-errors (delete-file auto-save)))))
+    ;; Answer no to deletion.
+    (cl-letf (((symbol-function #'yes-or-no-p)
+               (lambda (prompt)
+                 (not (string-search "Delete auto-save file" prompt)))))
+      (unwind-protect
+          (progn
+            (find-file file)
+            (auto-save-mode t)
+            (insert "foo\n")
+            (should buffer-auto-save-file-name)
+            (setq auto-save buffer-auto-save-file-name)
+            (do-auto-save)
+            (should (file-exists-p auto-save))
+            ;; This should not delete the auto-save file.
+            (kill-buffer (current-buffer))
+            (should (file-exists-p auto-save)))
+        (ignore-errors (delete-file file))
+        (when auto-save
+          (ignore-errors (delete-file auto-save)))))))
+
 ;;; buffer-tests.el ends here
diff --git a/test/src/syntax-tests.el b/test/src/syntax-tests.el
index e4e3054..bd89283 100644
--- a/test/src/syntax-tests.el
+++ b/test/src/syntax-tests.el
@@ -500,4 +500,10 @@ the `parse-partial-sexp's are expected to stop.  See
 (syntax-pps-comments /* 56 76 77 58)
 (syntax-pps-comments /* 60 78 79)
 
+(ert-deftest test-from-to-parse-partial-sexp ()
+  (with-temp-buffer
+    (insert "foo")
+    (should (parse-partial-sexp 1 1))
+    (should-error (parse-partial-sexp 2 1))))
+
 ;;; syntax-tests.el ends here



reply via email to

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