emacs-diffs
[Top][All Lists]
Advanced

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

feature/native-comp 99e7cc0: Merge remote-tracking branch 'savannah/mast


From: Andrea Corallo
Subject: feature/native-comp 99e7cc0: Merge remote-tracking branch 'savannah/master' into HEAD
Date: Fri, 23 Oct 2020 16:50:32 -0400 (EDT)

branch: feature/native-comp
commit 99e7cc0da652bf0f19f691d5de3b3ce7c15e8c39
Merge: 3be9339 46f5d28
Author: Andrea Corallo <akrl@sdf.org>
Commit: Andrea Corallo <akrl@sdf.org>

    Merge remote-tracking branch 'savannah/master' into HEAD
---
 admin/MAINTAINERS                                  |    1 +
 doc/emacs/package.texi                             |    6 +
 doc/lispref/commands.texi                          |   48 +-
 doc/lispref/compile.texi                           |    5 +-
 doc/lispref/files.texi                             |   21 +-
 doc/lispref/loading.texi                           |    4 +-
 doc/lispref/nonascii.texi                          |    5 +-
 doc/lispref/sequences.texi                         |    9 +-
 doc/lispref/variables.texi                         |   47 +
 doc/man/emacsclient.1                              |   24 +-
 doc/misc/efaq.texi                                 |   34 +-
 doc/misc/gnus.texi                                 |    8 +-
 doc/misc/info.texi                                 |   42 +-
 doc/misc/modus-themes.texi                         |   53 +-
 doc/misc/tramp.texi                                |   16 -
 etc/HELLO                                          |  115 +-
 etc/NEWS                                           |   99 +-
 etc/NEWS.27                                        |    6 +-
 etc/PROBLEMS                                       |    4 +
 etc/tutorials/TUTORIAL.de                          |  156 ++-
 etc/tutorials/TUTORIAL.fr                          |    2 +-
 lisp/Makefile.in                                   |    6 +
 lisp/ansi-color.el                                 |   10 +-
 lisp/arc-mode.el                                   |  120 +-
 lisp/bookmark.el                                   |  292 ++---
 lisp/calc/calc-ext.el                              |    2 +
 lisp/calendar/time-date.el                         |    2 +-
 lisp/calendar/timeclock.el                         |    2 +-
 lisp/cus-edit.el                                   |   59 +-
 lisp/delim-col.el                                  |    2 +-
 lisp/edmacro.el                                    |    1 -
 lisp/emacs-lisp/bindat.el                          |  180 ++-
 lisp/emacs-lisp/byte-run.el                        |   14 +-
 lisp/emacs-lisp/bytecomp.el                        |   70 +-
 lisp/emacs-lisp/chart.el                           |    2 +-
 lisp/emacs-lisp/cl-extra.el                        |    2 +
 lisp/emacs-lisp/cl-macs.el                         |    2 +
 lisp/emacs-lisp/cl-seq.el                          |    2 +
 lisp/emacs-lisp/package.el                         |   10 +
 lisp/emacs-lisp/pcase.el                           |    2 +-
 lisp/emacs-lisp/regi.el                            |    2 +-
 lisp/emacs-lisp/seq.el                             |    9 +-
 lisp/emacs-lisp/shortdoc.el                        |   11 +-
 lisp/erc/erc-ibuffer.el                            |   12 +-
 lisp/ffap.el                                       |   36 +-
 lisp/files.el                                      |   28 +-
 lisp/gnus/message.el                               |    2 +
 lisp/gnus/nnheader.el                              |    2 +
 lisp/gnus/nnmail.el                                |    2 +
 lisp/gnus/smiley.el                                |   80 +-
 lisp/help.el                                       |  470 ++++++++
 lisp/hfy-cmap.el                                   |   45 +-
 lisp/image-file.el                                 |    4 +-
 lisp/info.el                                       |   88 +-
 lisp/international/iso-ascii.el                    |    5 +-
 lisp/international/mule.el                         |    4 +-
 lisp/language/misc-lang.el                         |   14 +
 lisp/language/utf-8-lang.el                        |    2 +-
 lisp/loadhist.el                                   |   51 +-
 lisp/mail/binhex.el                                |   16 +-
 lisp/mail/footnote.el                              |    2 +-
 lisp/mail/mail-extr.el                             |   79 ++
 lisp/mail/rfc2231.el                               |   36 +-
 lisp/mail/uudecode.el                              |   11 +-
 lisp/md4.el                                        |    2 +-
 lisp/minibuffer.el                                 |   82 +-
 lisp/mpc.el                                        |   11 +-
 lisp/net/browse-url.el                             |   16 +-
 lisp/net/eww.el                                    |   11 +-
 lisp/net/sasl-ntlm.el                              |    2 +-
 lisp/net/tramp-sh.el                               |    4 +-
 lisp/net/tramp.el                                  |    2 +
 lisp/nxml/nxml-mode.el                             |    2 +-
 lisp/org/org.el                                    |    3 +-
 lisp/outline.el                                    |  161 ++-
 lisp/play/dunnet.el                                |    4 +-
 lisp/play/gamegrid.el                              |    2 +-
 lisp/progmodes/compile.el                          |  219 ++--
 lisp/progmodes/cperl-mode.el                       |    7 -
 lisp/progmodes/cpp.el                              |    2 +-
 lisp/progmodes/dcl-mode.el                         |    5 +-
 lisp/progmodes/elisp-mode.el                       |    3 +-
 lisp/progmodes/f90.el                              |   41 +-
 lisp/progmodes/fortran.el                          |    9 +-
 lisp/progmodes/gdb-mi.el                           |    5 +-
 lisp/progmodes/idlw-complete-structtag.el          |    7 +-
 lisp/progmodes/js.el                               |   11 +
 lisp/progmodes/ld-script.el                        |    2 +-
 lisp/progmodes/m4-mode.el                          |   15 +-
 lisp/progmodes/mixal-mode.el                       |   50 +-
 lisp/progmodes/python.el                           |    2 +-
 lisp/progmodes/sh-script.el                        |    2 +-
 lisp/progmodes/tcl.el                              |   24 +-
 lisp/savehist.el                                   |    2 +-
 lisp/shell.el                                      |   43 +
 lisp/simple.el                                     |   15 +-
 lisp/speedbar.el                                   |    2 +-
 lisp/textmodes/artist.el                           |   64 +-
 lisp/textmodes/picture.el                          |    2 +-
 lisp/textmodes/tex-mode.el                         |    2 +
 lisp/time.el                                       |  110 +-
 lisp/url/url-vars.el                               |    2 +-
 lisp/vc/diff-mode.el                               |    5 +-
 lisp/whitespace.el                                 |    3 +-
 lisp/wid-edit.el                                   |   35 +-
 lisp/woman.el                                      |    6 +
 src/dired.c                                        |    8 +-
 src/doc.c                                          |  321 +----
 src/eval.c                                         |    5 +-
 src/ftcrfont.c                                     |   16 +-
 src/image.c                                        |   46 +-
 src/keyboard.c                                     |   11 +-
 src/keymap.c                                       |  540 ++-------
 src/keymap.h                                       |    2 -
 src/lread.c                                        |    7 +
 src/nsterm.m                                       |    6 +
 src/print.c                                        |    2 +-
 src/search.c                                       |    2 +-
 src/syntax.c                                       |    2 +-
 src/xterm.c                                        |   13 +-
 test/Makefile.in                                   |    2 +-
 test/lisp/autorevert-tests.el                      |  656 ++++++-----
 test/lisp/bookmark-tests.el                        |    6 +-
 .../import-bug-11473.diary-european                |   10 +
 .../icalendar-resources/import-bug-11473.ics       |   54 +
 .../import-bug-22092.diary-american                |    6 +
 .../import-bug-22092.diary-european                |    6 +
 .../icalendar-resources/import-bug-22092.diary-iso |    6 +
 .../icalendar-resources/import-bug-22092.ics       |   30 +
 .../import-bug-24199.diary-american                |    5 +
 .../import-bug-24199.diary-european                |    5 +
 .../icalendar-resources/import-bug-24199.diary-iso |    5 +
 .../icalendar-resources/import-bug-24199.ics       |   25 +
 .../import-bug-33277.diary-american                |    1 +
 .../import-bug-33277.diary-european                |    1 +
 .../icalendar-resources/import-bug-33277.diary-iso |    1 +
 .../icalendar-resources/import-bug-33277.ics       |   15 +
 .../import-bug-6766.diary-american                 |    7 +
 .../import-bug-6766.diary-european                 |    7 +
 .../icalendar-resources/import-bug-6766.diary-iso  |    7 +
 .../icalendar-resources/import-bug-6766.ics        |   28 +
 .../import-duration-2.diary-american               |    3 +
 .../import-duration-2.diary-european               |    3 +
 .../import-duration-2.diary-iso                    |    3 +
 .../icalendar-resources/import-duration-2.ics      |   17 +
 .../import-duration.diary-american                 |    1 +
 .../import-duration.diary-european                 |    1 +
 .../icalendar-resources/import-duration.diary-iso  |    1 +
 .../icalendar-resources/import-duration.ics        |   10 +
 .../import-multiple-vcalendars.diary-american      |    4 +
 .../import-multiple-vcalendars.diary-european      |    4 +
 .../import-multiple-vcalendars.diary-iso           |    4 +
 .../import-multiple-vcalendars.ics                 |   21 +
 .../import-non-recurring-1.diary-american          |    1 +
 .../import-non-recurring-1.diary-european          |    1 +
 .../import-non-recurring-1.diary-iso               |    1 +
 .../icalendar-resources/import-non-recurring-1.ics |   10 +
 .../import-non-recurring-all-day.diary-american    |    1 +
 .../import-non-recurring-all-day.diary-european    |    1 +
 .../import-non-recurring-all-day.diary-iso         |    1 +
 .../import-non-recurring-all-day.ics               |    9 +
 ...rt-non-recurring-another-example.diary-american |    4 +
 ...rt-non-recurring-another-example.diary-european |    4 +
 .../import-non-recurring-another-example.diary-iso |    4 +
 .../import-non-recurring-another-example.ics       |   23 +
 .../import-non-recurring-block.diary-american      |    4 +
 .../import-non-recurring-block.diary-european      |    4 +
 .../import-non-recurring-block.diary-iso           |    4 +
 .../import-non-recurring-block.ics                 |   16 +
 ...ort-non-recurring-folded-summary.diary-american |    4 +
 ...ort-non-recurring-folded-summary.diary-european |    4 +
 .../import-non-recurring-folded-summary.diary-iso  |    4 +
 .../import-non-recurring-folded-summary.ics        |   25 +
 ...mport-non-recurring-long-summary.diary-american |    1 +
 ...mport-non-recurring-long-summary.diary-european |    1 +
 .../import-non-recurring-long-summary.diary-iso    |    1 +
 .../import-non-recurring-long-summary.ics          |   10 +
 .../import-real-world-2003-05-29.diary-american    |    6 +
 .../import-real-world-2003-05-29.diary-european    |    6 +
 .../import-real-world-2003-05-29.ics               |   54 +
 .../import-real-world-2003-06-18a.diary-american   |    6 +
 .../import-real-world-2003-06-18a.diary-european   |    6 +
 .../import-real-world-2003-06-18a.ics              |   36 +
 .../import-real-world-2003-06-18b.diary-american   |    6 +
 .../import-real-world-2003-06-18b.diary-european   |    6 +
 .../import-real-world-2003-06-18b.ics              |   55 +
 .../import-real-world-2004-11-19.diary-american    |   19 +
 .../import-real-world-2004-11-19.diary-european    |   19 +
 .../import-real-world-2004-11-19.ics               |  120 ++
 .../import-real-world-2005-02-07.diary-american    |    5 +
 .../import-real-world-2005-02-07.diary-european    |    5 +
 .../import-real-world-2005-02-07.ics               |   26 +
 .../import-real-world-2005-03-01.diary-american    |    2 +
 .../import-real-world-2005-03-01.diary-european    |    2 +
 .../import-real-world-2005-03-01.ics               |   11 +
 .../import-real-world-no-dst.diary-american        |    4 +
 .../import-real-world-no-dst.diary-european        |    4 +
 .../import-real-world-no-dst.ics                   |   26 +
 .../import-rrule-anniversary.diary-american        |    1 +
 .../import-rrule-anniversary.diary-european        |    1 +
 .../import-rrule-anniversary.diary-iso             |    1 +
 .../import-rrule-anniversary.ics                   |   11 +
 .../import-rrule-count-bi-weekly.diary-american    |    1 +
 .../import-rrule-count-bi-weekly.diary-european    |    1 +
 .../import-rrule-count-bi-weekly.diary-iso         |    1 +
 .../import-rrule-count-bi-weekly.ics               |   11 +
 .../import-rrule-count-daily-long.diary-american   |    1 +
 .../import-rrule-count-daily-long.diary-european   |    1 +
 .../import-rrule-count-daily-long.diary-iso        |    1 +
 .../import-rrule-count-daily-long.ics              |   11 +
 .../import-rrule-count-daily-short.diary-american  |    1 +
 .../import-rrule-count-daily-short.diary-european  |    1 +
 .../import-rrule-count-daily-short.diary-iso       |    1 +
 .../import-rrule-count-daily-short.ics             |   11 +
 ...t-rrule-count-every-second-month.diary-american |    1 +
 ...t-rrule-count-every-second-month.diary-european |    1 +
 ...import-rrule-count-every-second-month.diary-iso |    1 +
 .../import-rrule-count-every-second-month.ics      |   11 +
 ...rt-rrule-count-every-second-year.diary-american |    1 +
 ...rt-rrule-count-every-second-year.diary-european |    1 +
 .../import-rrule-count-every-second-year.diary-iso |    1 +
 .../import-rrule-count-every-second-year.ics       |   10 +
 .../import-rrule-count-monthly.diary-american      |    1 +
 .../import-rrule-count-monthly.diary-european      |    1 +
 .../import-rrule-count-monthly.diary-iso           |    1 +
 .../import-rrule-count-monthly.ics                 |   11 +
 .../import-rrule-count-yearly.diary-american       |    1 +
 .../import-rrule-count-yearly.diary-european       |    1 +
 .../import-rrule-count-yearly.diary-iso            |    1 +
 .../import-rrule-count-yearly.ics                  |   11 +
 .../import-rrule-daily-two-day.diary-american      |    1 +
 .../import-rrule-daily-two-day.diary-european      |    1 +
 .../import-rrule-daily-two-day.diary-iso           |    1 +
 .../import-rrule-daily-two-day.ics                 |   10 +
 ...port-rrule-daily-with-exceptions.diary-american |    1 +
 ...port-rrule-daily-with-exceptions.diary-european |    1 +
 .../import-rrule-daily-with-exceptions.diary-iso   |    1 +
 .../import-rrule-daily-with-exceptions.ics         |   12 +
 .../import-rrule-daily.diary-american              |    1 +
 .../import-rrule-daily.diary-european              |    1 +
 .../import-rrule-daily.diary-iso                   |    1 +
 .../icalendar-resources/import-rrule-daily.ics     |   11 +
 .../import-rrule-monthly-no-end.diary-american     |    1 +
 .../import-rrule-monthly-no-end.diary-european     |    1 +
 .../import-rrule-monthly-no-end.diary-iso          |    1 +
 .../import-rrule-monthly-no-end.ics                |   11 +
 .../import-rrule-monthly-with-end.diary-american   |    1 +
 .../import-rrule-monthly-with-end.diary-european   |    1 +
 .../import-rrule-monthly-with-end.diary-iso        |    1 +
 .../import-rrule-monthly-with-end.ics              |   11 +
 .../import-rrule-weekly.diary-american             |    1 +
 .../import-rrule-weekly.diary-european             |    1 +
 .../import-rrule-weekly.diary-iso                  |    1 +
 .../icalendar-resources/import-rrule-weekly.ics    |   11 +
 .../import-rrule-yearly.diary-american             |    1 +
 .../import-rrule-yearly.diary-european             |    1 +
 .../import-rrule-yearly.diary-iso                  |    1 +
 .../icalendar-resources/import-rrule-yearly.ics    |   11 +
 .../import-with-timezone.diary-iso                 |    2 +
 .../icalendar-resources/import-with-timezone.ics   |   27 +
 .../import-with-uid.diary-american                 |    2 +
 .../import-with-uid.diary-european                 |    2 +
 .../icalendar-resources/import-with-uid.diary-iso  |    2 +
 .../icalendar-resources/import-with-uid.ics        |   10 +
 test/lisp/calendar/icalendar-tests.el              | 1223 +++-----------------
 test/lisp/calendar/time-date-tests.el              |   52 +-
 test/lisp/emacs-lisp/bindat-tests.el               |   10 +-
 test/lisp/emacs-lisp/bytecomp-tests.el             |    7 +-
 test/lisp/emacs-lisp/package-resources/key.pub     |   32 +-
 test/lisp/emacs-lisp/package-resources/key.sec     |   62 +-
 .../package-resources/signed/archive-contents.sig  |  Bin 287 -> 181 bytes
 .../package-resources/signed/signed-bad-1.0.el     |    2 +-
 .../package-resources/signed/signed-good-1.0.el    |    2 +-
 .../signed/signed-good-1.0.el.sig                  |  Bin 287 -> 181 bytes
 .../package-resources/signed/update-signatures.sh  |   32 +
 test/lisp/emacs-lisp/package-tests.el              |    9 +
 test/lisp/ffap-tests.el                            |    6 +
 .../files-resources}/files-bug18141.el.gz          |  Bin
 test/lisp/files-tests.el                           |    3 +-
 test/lisp/files-x-tests.el                         |    3 +-
 test/lisp/help-tests.el                            |  310 +++++
 test/lisp/hfy-cmap-resources/rgb.txt               |    3 +
 test/lisp/hfy-cmap-tests.el                        |   55 +
 test/lisp/mail/rfc822-tests.el                     |   83 ++
 .../net/mailcap-resources}/mime.types              |    0
 test/lisp/net/mailcap-tests.el                     |    7 +-
 test/lisp/progmodes/compile-tests.el               |  453 ++++----
 .../fontify-punctuation-vars.pl                    |   20 +
 test/lisp/progmodes/cperl-mode-tests.el            |   22 +
 .../progmodes/js-resources}/js-chain.js            |    0
 .../js-indent-align-list-continuation-nil.js       |    0
 .../js-resources}/js-indent-init-dynamic.js        |    0
 .../progmodes/js-resources}/js-indent-init-t.js    |    0
 .../indent => lisp/progmodes/js-resources}/js.js   |    0
 .../js-resources}/jsx-align-gt-with-lt.jsx         |    0
 .../progmodes/js-resources}/jsx-comment-string.jsx |    0
 .../progmodes/js-resources}/jsx-indent-level.jsx   |    0
 .../progmodes/js-resources}/jsx-quote.jsx          |    0
 .../progmodes/js-resources}/jsx-self-closing.jsx   |    0
 .../progmodes/js-resources}/jsx-unclosed-1.jsx     |    0
 .../progmodes/js-resources}/jsx-unclosed-2.jsx     |    0
 .../indent => lisp/progmodes/js-resources}/jsx.jsx |    0
 test/lisp/progmodes/js-tests.el                    |   41 +
 test/lisp/progmodes/perl-mode-tests.el             |   33 +
 .../progmodes/xref-resources}/file1.txt            |    0
 .../progmodes/xref-resources}/file2.txt            |    0
 test/lisp/progmodes/xref-tests.el                  |    7 +-
 test/lisp/time-resources/non-empty                 |    1 +
 test/lisp/time-tests.el                            |   78 ++
 test/lisp/vc/vc-bzr-tests.el                       |    2 +-
 test/lisp/wid-edit-tests.el                        |   19 +
 test/src/doc-tests.el                              |   98 --
 .../emacs-module-resources}/mod-test.c             |    0
 test/src/emacs-module-tests.el                     |   12 +-
 test/{data => src/lread-resources}/somelib.el      |    0
 test/{data => src/lread-resources}/somelib2.el     |    0
 test/src/lread-tests.el                            |    8 +-
 .../syntax-resources}/syntax-comments.txt          |    0
 test/src/syntax-tests.el                           |   12 +-
 319 files changed, 5203 insertions(+), 3749 deletions(-)

diff --git a/admin/MAINTAINERS b/admin/MAINTAINERS
index f7ec181..53afe87 100644
--- a/admin/MAINTAINERS
+++ b/admin/MAINTAINERS
@@ -213,6 +213,7 @@ Paul Eggert
        src/* (except for *.m, *w32*, bitmaps, files others want to maintain)
 
 Michael Albinus
+        .gitlab-ci.yml
        src/inotify.c
         lisp/autorevert.el
        lisp/eshell/em-tramp.el
diff --git a/doc/emacs/package.texi b/doc/emacs/package.texi
index 453d9eb..56e8ee1 100644
--- a/doc/emacs/package.texi
+++ b/doc/emacs/package.texi
@@ -222,6 +222,12 @@ lower, equal or higher version than the one specified.
 Filter package list by non-empty mark (@code{package-menu-filter-marked}).
 This shows only the packages that have been marked to be installed or deleted.
 
+@item / u
+@kindex / u @r{(Package Menu)}
+@findex package-menu-filter-upgradable
+Filter package list to show only packages for which there are
+available upgrades (@code{package-menu-filter-upgradable}).
+
 @item / /
 @kindex / / @r{(Package Menu)}
 @findex package-menu-filter-clear
diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi
index 1467854..8959175 100644
--- a/doc/lispref/commands.texi
+++ b/doc/lispref/commands.texi
@@ -1345,10 +1345,11 @@ button.  @xref{Repeat Events}.
 
   To access the contents of a mouse position list in the
 @var{position} slot of a click event, you should typically use the
-functions documented in @ref{Accessing Mouse}.  The explicit format of
-the list depends on where the click occurred.  For clicks in the text
-area, mode line, header line, tab line, or in the fringe or marginal
-areas, the mouse position list has the form
+functions documented in @ref{Accessing Mouse}.
+
+The explicit format of the list depends on where the click occurred.
+For clicks in the text area, mode line, header line, tab line, or in
+the fringe or marginal areas, the mouse position list has the form
 
 @example
 (@var{window} @var{pos-or-area} (@var{x} . @var{y}) @var{timestamp}
@@ -1478,6 +1479,45 @@ handle), @code{up} (the up arrow at one end of the 
scroll bar), or
 @c The 'top', 'bottom', and 'end-scroll' codes don't seem to be used.
 @end table
 
+For clicks on the frame's internal border (@pxref{Frame Layout}),
+@var{position} has this form:
+
+@example
+ (@var{frame} @var{part} (@var{X} . @var{Y}) @var{timestamp})
+@end example
+
+@table @asis
+@item @var{frame}
+The frame whose internal border was clicked on.
+
+@item @var{part}
+The part of the internal border which was clicked on.  This can be one
+of the following:
+
+@table @code
+@item nil
+The frame does not have an internal border.  This usually happens on
+text-mode frames.  This can also happen on GUI frames with internal
+border if the frame doesn't have its @code{drag-internal-border}
+parameter (@pxref{Mouse Dragging Parameters}) set to a non-@code{nil}
+value.
+
+@item left-edge
+@itemx top-edge
+@itemx right-edge
+@itemx bottom-edge
+The click was on the corresponding border at an offset of at least one
+canonical character from the border's nearest corner.
+
+@item top-left-corner
+@itemx top-right-corner
+@itemx bottom-right-corner
+@itemx bottom-left-corner
+The click was on the corresponding corner of the internal border.
+@end table
+
+@end table
+
 
 @node Drag Events
 @subsection Drag Events
diff --git a/doc/lispref/compile.texi b/doc/lispref/compile.texi
index e979fda..ad8afaa 100644
--- a/doc/lispref/compile.texi
+++ b/doc/lispref/compile.texi
@@ -164,7 +164,7 @@ echo area, but if @var{arg} is non-@code{nil}, it inserts 
the result
 in the current buffer after the form it has compiled.
 @end deffn
 
-@deffn Command byte-compile-file filename &optional load
+@deffn Command byte-compile-file filename
 This function compiles a file of Lisp code named @var{filename} into a
 file of byte-code.  The output file's name is made by changing the
 @samp{.el} suffix into @samp{.elc}; if @var{filename} does not end in
@@ -180,9 +180,6 @@ input file is read.
 This command returns @code{t} if there were no errors and @code{nil}
 otherwise.  When called interactively, it prompts for the file name.
 
-If @var{load} is non-@code{nil}, this command loads the compiled file
-after compiling it.  Interactively, @var{load} is the prefix argument.
-
 @example
 @group
 $ ls -l push*
diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi
index 3b8b4fb..fc66d1c 100644
--- a/doc/lispref/files.texi
+++ b/doc/lispref/files.texi
@@ -2926,11 +2926,11 @@ absolute file names.  Otherwise, it returns the names 
relative to
 the specified directory.
 
 If @var{match-regexp} is non-@code{nil}, this function returns only
-those file names that contain a match for that regular expression---the
-other file names are excluded from the list.  On case-insensitive
-filesystems, the regular expression matching is case-insensitive.
+those file names whose non-directory part contain a match for that
+regular expression---the other file names are excluded from the list.
+On case-insensitive filesystems, the regular expression matching is
+case-insensitive.
 
-@c Emacs 19 feature
 If @var{nosort} is non-@code{nil}, @code{directory-files} does not sort
 the list, so you get the file names in no particular order.  Use this if
 you want the utmost possible speed and don't care what order the files
@@ -3007,6 +3007,19 @@ corresponding argument to @code{file-attributes} 
(@pxref{Definition
 of file-attributes}).
 @end defun
 
+@defvr Constant directory-files-no-dot-files-regexp
+This regular expression matches any file name except @samp{.} and
+@samp{..}.  More precisely, it matches parts of any nonempty string
+except those two.  It is useful as the @var{match-regexp} argument to
+@code{directory-files} and @code{directory-files-and-attributes}:
+
+@example
+(directory-files "/foo" nil directory-files-no-dot-files-regexp)
+@end example
+
+returns @code{nil}, if directory @samp{/foo} is empty.
+@end defvr
+
 @defun file-expand-wildcards pattern &optional full
 This function expands the wildcard pattern @var{pattern}, returning
 a list of file names that match it.
diff --git a/doc/lispref/loading.texi b/doc/lispref/loading.texi
index aa6ef30..e536415 100644
--- a/doc/lispref/loading.texi
+++ b/doc/lispref/loading.texi
@@ -1063,7 +1063,7 @@ It then restores any autoloads formerly associated with 
those symbols.
 (Loading saves these in the @code{autoload} property of the symbol.)
 
 Before restoring the previous definitions, @code{unload-feature} runs
-@code{remove-hook} to remove functions in the library from certain
+@code{remove-hook} to remove functions defined by the library from certain
 hooks.  These hooks include variables whose names end in @samp{-hook}
 (or the deprecated suffix @samp{-hooks}), plus those listed in
 @code{unload-feature-special-hooks}, as well as
@@ -1071,7 +1071,7 @@ hooks.  These hooks include variables whose names end in 
@samp{-hook}
 function because important hooks refer to functions that are no longer
 defined.
 
-Standard unloading activities also undoes ELP profiling of functions
+Standard unloading activities also undo ELP profiling of functions
 in that library, unprovides any features provided by the library, and
 cancels timers held in variables defined by the library.
 
diff --git a/doc/lispref/nonascii.texi b/doc/lispref/nonascii.texi
index 8e9d624..97bc85f 100644
--- a/doc/lispref/nonascii.texi
+++ b/doc/lispref/nonascii.texi
@@ -722,7 +722,10 @@ The value of this variable is a char-table that specifies, 
for each
 character, a symbol whose name is the script to which the character
 belongs, according to the Unicode Standard classification of the
 Unicode code space into script-specific blocks.  This char-table has a
-single extra slot whose value is the list of all script symbols.
+single extra slot whose value is the list of all script symbols.  Note
+that Emacs' classification of characters into scripts is not a 1-for-1
+reflection of the Unicode standard, e.g. there is no @samp{symbol}
+script in Unicode.
 @end defvar
 
 @defvar char-width-table
diff --git a/doc/lispref/sequences.texi b/doc/lispref/sequences.texi
index ca52369..952834b 100644
--- a/doc/lispref/sequences.texi
+++ b/doc/lispref/sequences.texi
@@ -658,8 +658,13 @@ for which @var{predicate} returns @code{nil}.
 @var{initial-value} and the first element of @var{sequence}, then calling
 @var{function} with that result and the second element of @var{sequence},
 then with that result and the third element of @var{sequence}, etc.
-@var{function} should be a function of two arguments.  If
-@var{sequence} is empty, this returns @var{initial-value} without
+@var{function} should be a function of two arguments.
+
+@var{function} is called with two arguments.  @var{intial-value}
+(and then the accumulated value) is used as the first argument, and
+the elements in @var{sequence} are used for the second argument.
+
+If @var{sequence} is empty, this returns @var{initial-value} without
 calling @var{function}.
 
 @example
diff --git a/doc/lispref/variables.texi b/doc/lispref/variables.texi
index acbc8df..394fb96 100644
--- a/doc/lispref/variables.texi
+++ b/doc/lispref/variables.texi
@@ -1283,6 +1283,45 @@ you can also add a leading underscore to the variable's 
name to
 indicate to the compiler that this is a variable known not to
 be used.)
 
+@subsubheading Cross-file variable checking
+
+@strong{Note:} This is an experimental feature that may change or
+disappear without prior notice.
+
+The byte-compiler can also warn about lexical variables that are
+special in other Emacs Lisp files, often indicating a missing
+@code{defvar} declaration.  This useful but somewhat specialised check
+requires three steps:
+
+@enumerate
+@item
+Byte-compile all files whose special variable declarations may be of
+interest, with the environment variable @env{EMACS_GENERATE_DYNVARS}
+set to a nonempty string.  These are typically all the files in the
+same package or related packages or Emacs subsystems.  The process
+will generate a file whose name ends in @file{.dynvars} for each
+compiled Emacs Lisp file.
+
+@item
+Concatenate the @file{.dynvars} files into a single file.
+
+@item
+Byte-compile the files that need to be checked, this time with
+the environment variable @env{EMACS_DYNVARS_FILE} set to the name
+of the aggregated file created in step 2.
+@end enumerate
+
+Here is an example illustrating how this could be done, assuming that
+a Unix shell and @command{make} are used for byte-compilation:
+
+@example
+$ rm *.elc                                # force recompilation
+$ EMACS_GENERATE_DYNVARS=1 make           # generate .dynvars
+$ cat *.dynvars > ~/my.dynvars            # combine .dynvars
+$ rm *.elc                                # force recompilation
+$ EMACS_DYNVARS_FILE=~/my.dynvars make    # perform checks
+@end example
+
 @node Buffer-Local Variables
 @section Buffer-Local Variables
 @cindex variable, buffer-local
@@ -2346,6 +2385,14 @@ equivalent to the following:
 (defvaralias @var{obsolete-name} @var{current-name} @var{docstring})
 (make-obsolete-variable @var{obsolete-name} @var{current-name} @var{when})
 @end example
+
+This macro evaluates all its parameters, and both @var{obsolete-name}
+and @var{current-name} should be symbols, so a typical usage would
+look like:
+
+@lisp
+(define-obsolete-variable-alias 'foo-thing 'bar-thing "27.1")
+@end lisp
 @end defmac
 
 @defun indirect-variable variable
diff --git a/doc/man/emacsclient.1 b/doc/man/emacsclient.1
index 62f5489..ba64efa 100644
--- a/doc/man/emacsclient.1
+++ b/doc/man/emacsclient.1
@@ -1,5 +1,5 @@
 .\" See section COPYING for conditions for redistribution.
-.TH EMACSCLIENT 1 "2020-10-15" "GNU Emacs" "GNU"
+.TH EMACSCLIENT 1 "2020-10-18" "GNU Emacs" "GNU"
 .\" NAME should be all caps, SECTION should be 1-8, maybe w/ subsection
 .\" other params are allowed: see man(7), man(1)
 .SH NAME
@@ -61,45 +61,45 @@ is treated as column 1.
 This option applies only to the next file specified.
 .TP
 .B \-a, \-\-alternate-editor=COMMAND
-if the Emacs server is not running, run the specified shell command instead.
+If the Emacs server is not running, run the specified shell command instead.
 This can also be specified via the ALTERNATE_EDITOR environment variable.
 If the value of ALTERNATE_EDITOR is the empty string, run "emacs \-\-daemon" to
 start Emacs in daemon mode, and try to connect to it.
 .TP
 .B -c, \-\-create-frame
-create a new frame instead of trying to use the current Emacs frame
+Create a new frame instead of trying to use the current Emacs frame.
 .TP
 .B \-F, \-\-frame-parameters=ALIST
-set the parameters of a newly-created frame.
+Set the parameters of a newly-created frame.
 .TP
 .B \-d, \-\-display=DISPLAY
-tell the server to display the files on the given display.
+Tell the server to display the files on the given display.
 .TP
 .B \-e, \-\-eval
-do not visit files but instead evaluate the arguments as Emacs
+Do not visit files but instead evaluate the arguments as Emacs
 Lisp expressions.
 .TP
 .B \-f, \-\-server-file=FILENAME
-use TCP configuration file FILENAME for communication.
+Use TCP configuration file FILENAME for communication.
 This can also be specified via the EMACS_SERVER_FILE environment variable.
 .TP
 .B \-n, \-\-no-wait
-returns
+Return
 immediately without waiting for you to "finish" the buffer in Emacs.
 If combined with --eval, this option is ignored.
 .TP
 .B \-nw, \-t, \-\-tty
-open a new Emacs frame on the current terminal
+Open a new Emacs frame on the current terminal.
 .TP
 .B \-s, \-\-socket-name=FILENAME
-use socket named FILENAME for communication.
+Use socket named FILENAME for communication.
 This can also be specified via the EMACS_SOCKET_NAME environment variable.
 .TP
 .B \-V, \-\-version
-print version information and exit
+Print version information and exit.
 .TP
 .B \-H, \-\-help
-print this usage information message and exit
+Print this usage information message and exit.
 .SH "EXIT STATUS"
 Normally, the exit status is 0.  If emacsclient shuts down due to
 Emacs signaling an error, the exit status is 1.
diff --git a/doc/misc/efaq.texi b/doc/misc/efaq.texi
index 115dd8a..e1b099e 100644
--- a/doc/misc/efaq.texi
+++ b/doc/misc/efaq.texi
@@ -2718,8 +2718,7 @@ menus}), use:
 @cindex FAQ, @code{font-lock-mode}
 
 @code{font-lock-mode} is the standard way to have Emacs perform syntax
-highlighting in the current buffer.  It is enabled by default in Emacs
-22.1 and later.
+highlighting in the current buffer.  It is enabled by default.
 
 With @code{font-lock-mode} turned on, different types of text will
 appear in different colors.  For instance, in a programming mode,
@@ -2729,13 +2728,6 @@ a third.
 To turn @code{font-lock-mode} off within an existing buffer, use
 @kbd{M-x font-lock-mode @key{RET}}.
 
-In Emacs 21 and earlier versions, you could use the following code in
-your @file{.emacs} file to turn on @code{font-lock-mode} globally:
-
-@lisp
-(global-font-lock-mode 1)
-@end lisp
-
 Highlighting a buffer with @code{font-lock-mode} can take quite a while,
 and cause an annoying delay in display, so several features exist to
 work around this.
@@ -3672,7 +3664,6 @@ See the file @file{nextstep/INSTALL} in the distribution.
 * Compose Character::
 * Binding combinations of modifiers and function keys::
 * Meta key does not work in xterm::
-* ExtendChar key does not work as Meta::
 * SPC no longer completes file names::
 @end menu
 
@@ -4147,29 +4138,6 @@ You might have to replace @samp{Meta} with @samp{Alt}.
 
 @end itemize
 
-@node ExtendChar key does not work as Meta
-@section Why doesn't my @key{ExtendChar} key work as a @key{Meta} key under 
HP-UX 8.0 and 9.x?
-@cindex @key{ExtendChar} key as @key{Meta}
-@cindex @key{Meta}, using @key{ExtendChar} for
-@cindex HP-UX, the @key{ExtendChar} key
-
-This is a result of an internationalization extension in X11R4 and the
-fact that HP is now using this extension.  Emacs assumes that the
-@code{XLookupString} function returns the same result regardless of the
-@key{Meta} key state which is no longer necessarily true.  Until Emacs
-is fixed, the temporary kludge is to run this command after each time
-the X server is started but preferably before any xterm clients are:
-
-@example
-xmodmap -e 'remove mod1 = Mode_switch'
-@end example
-
-@c FIXME: Emacs 21 supports I18N in X11; does that mean that this bug is
-@c solved?
-
-This will disable the use of the extra keysyms systemwide, which may be
-undesirable if you actually intend to use them.
-
 @node SPC no longer completes file names
 @section Why doesn't @key{SPC} complete file names anymore?
 @cindex @kbd{SPC} file name completion
diff --git a/doc/misc/gnus.texi b/doc/misc/gnus.texi
index 3f893e9..69ac05d 100644
--- a/doc/misc/gnus.texi
+++ b/doc/misc/gnus.texi
@@ -23919,10 +23919,10 @@ The following variables customize the appearance of 
the smileys:
 @item smiley-style
 @vindex smiley-style
 Specifies the smiley style.  Predefined smiley styles include
-@code{low-color} (small 13x14 pixel, three-color images), @code{medium}
-(more colorful images, 16x16 pixel), and @code{grayscale} (grayscale
-images, 14x14 pixel).  The default depends on the height of the default
-face.
+@code{emoji} (use emoji characters), @code{low-color} (small 13x14
+pixel, three-color images), @code{medium} (more colorful images, 16x16
+pixel), and @code{grayscale} (grayscale images, 14x14 pixel).  The
+default depends on the height of the default face.
 
 @item smiley-data-directory
 @vindex smiley-data-directory
diff --git a/doc/misc/info.texi b/doc/misc/info.texi
index f3ab305..85e04a9 100644
--- a/doc/misc/info.texi
+++ b/doc/misc/info.texi
@@ -798,17 +798,17 @@ in cross references and node names if it differs from the 
current
 file, so you can always know that you are going to be switching to
 another manual and which one.
 
-However, Emacs normally hides some other text in cross-references.
-If you put your mouse over the cross reference, then the information
-appearing in a separate box (tool tip) or in the echo area will show
-the full cross-reference including the file name and the node name of
-the cross reference.  If you have a mouse, just leave it over the
-cross reference @xref{Top,, Overview of Texinfo, texinfo, Texinfo:
-The GNU Documentation Format}, and watch what happens.  If you
-always like to have that information visible without having to move
-your mouse over the cross reference, use @kbd{M-x visible-mode}, or
-set @code{Info-hide-note-references} to a value other than @code{t}
-(@pxref{Emacs Info Variables}).
+Emacs normally hides some text in cross references.  If you put your
+mouse over the cross reference, then the information appearing in a
+separate box (tool tip) or in the echo area will show the full
+cross reference, including the file name and the node name of the
+cross reference if it leads to another file.  If you have a mouse,
+just leave it over the next cross reference: @xref{Top,, Overview of
+Texinfo, texinfo, Texinfo: The GNU Documentation Format}, and watch
+what happens.  If you always like to have that information visible
+without having to move your mouse over the cross reference, use
+@kbd{M-x visible-mode}, or set @code{Info-hide-note-references} to a
+value other than @code{t} (@pxref{Emacs Info Variables}).
 
 @format
 >> Now type @kbd{n} to learn more commands.
@@ -1227,12 +1227,20 @@ not scroll with the rest of the buffer, making these 
links always
 visible.
 
 @item Info-hide-note-references
-As explained in earlier nodes, the Emacs version of Info normally
-hides some text in menus and cross-references.  You can completely
-disable this feature, by setting this option to @code{nil}.  Setting
-it to a value that is neither @code{nil} nor @code{t} produces an
-intermediate behavior, hiding a limited amount of text, but showing
-all text that could potentially be useful.
+As explained in earlier sections, the Emacs version of Info normally
+hides some text in menus and cross references.  It also replaces the
+@samp{*note} prefix of each cross reference with a more grammatically
+correct @samp{see}.  This is the effect of the default value of this
+option, @code{t}.  Setting this option to @code{nil} disables both
+hiding and replacing of the original cross reference text, and Emacs
+will then display them as they are in the Info file.  If you set it to
+the value @code{hide}, Emacs will do the same as with @code{t}, but
+will also remove @samp{*note} without replacing it with anything.
+Setting it to any other non-@code{nil} value produces an intermediate
+behavior, hiding a limited amount of text, but showing all text that
+could potentially be useful, including the name of the node that is
+the target of the cross reference and its file if it is different from
+the current file.
 
 @item Info-scroll-prefer-subnodes
 If set to a non-@code{nil} value, @key{SPC} and @key{BACKSPACE} (or
diff --git a/doc/misc/modus-themes.texi b/doc/misc/modus-themes.texi
index c34ee15..de3ccd2 100644
--- a/doc/misc/modus-themes.texi
+++ b/doc/misc/modus-themes.texi
@@ -50,8 +50,8 @@ and with no Back-Cover Texts.
 * Overview::
 * Installation::
 * Enable and load::
-* Customisation Options::
-* Advanced customisation (do-it-yourself)::
+* Customization Options::
+* Advanced customization (do-it-yourself)::
 * Face coverage::
 * Notes for individual packages::
 * Contributing::
@@ -85,7 +85,7 @@ Enable and load
 * Toggle between the themes on demand::
 * Configure options prior to loading::
 
-Customisation Options
+Customization Options
 
 * Bold constructs::              Toggle bold constructs in code
 * Slanted constructs::           Toggle slanted constructs (italics) in code
@@ -108,7 +108,7 @@ Scaled headings
 
 * Scaled heading sizes::         Specify rate of increase for scaled headings
 
-Advanced customisation (do-it-yourself)
+Advanced customization (do-it-yourself)
 
 * Tweak colors (DIY)::           Declare your own palette overrides
 * Font configs (DIY)::           Optimise for mixed typeface buffers
@@ -177,7 +177,7 @@ display that draw attention to details and important 
aspects in the
 design of the themes.  They also showcase the numerous customization
 options.
 
-@xref{Customisation Options, , Customisation options}.
+@xref{Customization Options}.
 
 @node Learn about the latest changes
 @section Learn about the latest changes
@@ -193,9 +193,8 @@ On older versions of Emacs, they can be installed using 
Emacs' package
 manager or manually from their code repository.
 
 Modus Operandi (light theme) and Modus Vivendi (dark) are normally
-distributed as standalone packages in Emacs-specific archives: GNU ELPA,
-MELPA, and MELPA Stable.  There also exist packages for GNU/Linux
-distributions.
+distributed as standalone packages in Emacs-specific archives.  There
+also exist packages for GNU/Linux distributions.
 
 @menu
 * Install from the archives::
@@ -206,14 +205,12 @@ distributions.
 @section Install from the archives
 
 @samp{modus-operandi-theme} and @samp{modus-vivendi-theme} are
-available from GNU ELPA.
+available from the GNU ELPA archive, which is configured by default.
 
 Prior to querying any package archive, make sure to have updated the
 index, with @samp{M-x package-refresh-contents}.  Then all you need to do is
 type @samp{M-x package-install} and specify the theme of your choice.
 
-GNU ELPA contains the last tagged release.
-
 @node Install on GNU/Linux
 @section Install on GNU/Linux
 
@@ -247,22 +244,22 @@ Users of either the Guix System (the distro) or just Guix 
(the package
 manager) can get each theme as a standalone package.
 
 @example
-guix package -i modus-operandi-theme
+guix package -i emacs-modus-operandi-theme
 @end example
 
 And/or:
 
 @example
-guix package -i modus-vivendi-theme
+guix package -i emacs-modus-vivendi-theme
 @end example
 
 @node Enable and load
 @chapter Enable and load
 
-This section documents how to load the theme of your
-choice and how to further control its initialization.  It also includes
-some sample code snippets that could help you in the task, especially if
-you intend to use both Modus Operandi and Modus Vivendi.
+This section documents how to load the theme of your choice and how to
+further control its initialization.  It also includes some sample code
+snippets that could help you in the task, especially if you intend to
+use both Modus Operandi and Modus Vivendi.
 
 @menu
 * Load automatically::
@@ -298,7 +295,7 @@ evaluate the expression:
 @section Load at a given time or at sunset/sunrise
 
 It is possible to schedule a time during the day at or after which a
-given theme will be loaded.@footnote{Contributed on Reddit by user b3n
+given theme will be loaded.@footnote{Contributed on Reddit by user @samp{b3n}
 
@uref{https://www.reddit.com/r/emacs/comments/gdtqov/weekly_tipstricketc_thread/fq9186h/}.}
 
 @lisp
@@ -373,7 +370,7 @@ disabling a single target, but you get the idea.
 @section Configure options prior to loading
 
 If you plan to use both themes and wish to apply styles consistently
-(see @ref{Customisation Options}), you could define wrapper functions around
+(see @ref{Customization Options}), you could define wrapper functions around
 the standard @samp{load-theme} command.  These extend the simple function we
 presented in @ref{Toggle between the themes on demand}.
 
@@ -427,8 +424,8 @@ method were contributed on Reddit by user @samp{b3n},
     (modus-operandi-theme-load)))
 @end lisp
 
-@node Customisation Options
-@chapter Customisation Options
+@node Customization Options
+@chapter Customization Options
 
 The Modus themes are highly configurable, though they should work well
 without any further tweaks.
@@ -639,7 +636,7 @@ background and foreground to the minibuffer and other REPL 
prompts (like
 @samp{M-x shell} and @samp{M-x eshell}).  The difference between the two is 
that the
 latter has a more pronounced/noticeable effect than the former.
 
-The default is not to use any background for such prompts, while relying
+The default does not use any background for such prompts, while relying
 exclusively on an accented foreground color.
 
 @node Mode line
@@ -1182,13 +1179,13 @@ main font family.
 
 @ref{Font configs (DIY), , Font configurations for Org (and others)}.
 
-@node Advanced customisation (do-it-yourself)
-@chapter Advanced customisation (do-it-yourself)
+@node Advanced customization (do-it-yourself)
+@chapter Advanced customization (do-it-yourself)
 
 Unlike the predefined customization options which follow a
 straightforward pattern of allowing the user to quickly specify their
 preference, the themes also provide a more flexible, albeit difficult,
-mechanism to control things with precision (see @ref{Customisation Options}).
+mechanism to control things with precision (see @ref{Customization Options}).
 
 This section is of interest only to users who are prepared to maintain
 their own local tweaks and who are willing to deal with any possible
@@ -2043,7 +2040,7 @@ that secondary elements like sidebars can have the 
default (pure
 white/black) background.
 
 I will only cover this package if it ever supports the inverse effect:
-less intense colors (but still accessible) for supportive interfaces
+less intense colors (but still accessible) for ancillary interfaces
 and the intended styles for the content you are actually working on.
 
 @node Notes for individual packages
@@ -2302,13 +2299,13 @@ The Modus themes are a collective effort.  Every 
contribution counts.
 Protesilaos Stavrou.
 
 @item Code contributions
-Anders Johansson, Basil L@. Contovounisios,
+Anders Johansson, Basil L@. Contovounesios,
 Markus Beppler, Matthew Stevenson.
 
 @item Ideas and user feedback
 Aaron Jensen, Adam Spiers, Alex Griffin,
 Alex Peitsinis, Alexey Shmalko, Anders Johansson, André Alexandre
-Gomes, Arif Rezai, Basil L@. Contovounisios, Damien Cassou, Dario
+Gomes, Arif Rezai, Basil L@. Contovounesios, Damien Cassou, Dario
 Gjorgjevski, David Edmondson, Davor Rotim, Divan Santana, Gerry
 Agbobada, Gianluca Recchia, Iris Garcia, Len Trigg, Manuel Uberti,
 Mark Burton, Markus Beppler, Michael Goldenberg, Murilo Pereira,
diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi
index 0e397f4..a7339bf 100644
--- a/doc/misc/tramp.texi
+++ b/doc/misc/tramp.texi
@@ -3089,19 +3089,6 @@ Example:
 @end group
 @end example
 
-During file name completion, remote directory contents are re-read
-regularly to account for any changes in the file system that may
-affect the completion candidates.  Such re-reads can account for
-changes to the file system by applications outside Emacs
-(@pxref{Connection caching}).
-
-@defopt tramp-completion-reread-directory-timeout
-The timeout is number of seconds since last remote command for
-rereading remote directory contents.  A value of 0 re-reads
-immediately during file name completion, @code{nil} uses cached
-directory contents.
-@end defopt
-
 
 @node Ad-hoc multi-hops
 @section Declaring multiple hops in the file name
@@ -4126,9 +4113,6 @@ files are not independently updated outside 
@value{tramp}'s control.
 That cache cleanup will be necessary if the remote directories or
 files are updated independent of @value{tramp}.
 
-Set @code{tramp-completion-reread-directory-timeout} to @code{nil} to
-speed up completions, @ref{File name completion}.
-
 Disable version control to avoid delays:
 
 @lisp
diff --git a/etc/HELLO b/etc/HELLO
index e0345cb..fcc9075 100644
--- a/etc/HELLO
+++ b/etc/HELLO
@@ -7,88 +7,89 @@ some of the character sets that Emacs supports.
 
 
 Non-ASCII examples:
-  Europe: <x-charset><param>latin-iso8859-1</param>¡Hola!, Grüß Gott, Hyvää 
päivää,</x-charset><x-charset><param>latin-iso8859-15</param> Tere 
õhtust,</x-charset><x-charset><param>latin-iso8859-3</param> Bonġu
-          Cześć!,</x-charset><x-charset><param>latin-iso8859-2</param> Dobrý 
den,</x-charset><x-charset><param>cyrillic-iso8859-5</param> 
Здравствуйте!,</x-charset><x-charset><param>greek-iso8859-7</param> Γειά 
σας,</x-charset><x-charset><param>mule-unicode-0100-24ff</param> 
გამარჯობა</x-charset>
-  Africa:<x-charset><param>mule-unicode-0100-24ff</param> 
</x-charset><x-charset><param>ethiopic</param>ሠላም</x-charset>
-  Middle/Near East:<x-charset><param>hebrew-iso8859-8</param> 
שָׁלוֹם,</x-charset><x-charset><param>mule-unicode-0100-24ff</param> السّلام 
عليكم</x-charset>
-  South Asia:<x-charset><param>mule-unicode-0100-24ff</param> નમસ્તે, नमस्ते, 
ನಮಸ್ಕಾರ, നമസ്കാരം, ଶୁଣିବେ,
-              ආයුබෝවන්, வணக்கம், 
నమస్కారం,</x-charset><x-charset><param>tibetan</param> 
བཀྲ་ཤིས་བདེ་ལེགས༎</x-charset>
-  South East Asia:<x-charset><param>mule-unicode-0100-24ff</param> 
ជំរាបសួរ,</x-charset><x-charset><param>lao</param> 
ສະບາຍດີ,</x-charset><x-charset><param>mule-unicode-0100-24ff</param> 
မင်္ဂလာပါ,</x-charset><x-charset><param>thai-tis620</param> 
สวัสดีครับ,</x-charset><x-charset><param>vietnamese-viscii-lower</param> 
</x-charset><x-charset><param>vietnamese-viscii-upper</param>C</x-charset><x-charset><param>vietnamese-viscii-lower</param>hào
 bạn</x-charset>
+  Europe: <x-charset><param>latin-iso8859-1</param>¡Hola!, Grüß Gott, Hyvää 
päivää,</x-charset> Tere õhtust,<x-charset><param>latin-iso8859-3</param> Bonġu
+          Cześć!,</x-charset><x-charset><param>latin-iso8859-2</param> Dobrý 
den,</x-charset><x-charset><param>cyrillic-iso8859-5</param> 
Здравствуйте!,</x-charset><x-charset><param>greek-iso8859-7</param> Γειά 
σας,</x-charset> გამარჯობა
+  Africa: <x-charset><param>ethiopic</param>ሠላም</x-charset>
+  Middle/Near East:<x-charset><param>hebrew-iso8859-8</param> 
שָׁלוֹם,</x-charset> السّلام عليكم
+  South Asia: નમસ્તે, नमस्ते, ನಮಸ್ಕಾರ, നമസ്കാരം, ଶୁଣିବେ,
+              ආයුබෝවන්, வணக்கம், నమస్కారం,<x-charset><param>tibetan</param> 
བཀྲ་ཤིས་བདེ་ལེགས༎</x-charset>
+  South East Asia: ជំរាបសួរ,<x-charset><param>lao</param> ສະບາຍດີ,</x-charset> 
မင်္ဂလာပါ,<x-charset><param>thai-tis620</param> 
สวัสดีครับ,</x-charset><x-charset><param>vietnamese-viscii-lower</param> 
</x-charset><x-charset><param>vietnamese-viscii-upper</param>C</x-charset><x-charset><param>vietnamese-viscii-lower</param>hào
 bạn</x-charset>
   East Asia:<x-charset><param>chinese-gb2312</param> 
你好,</x-charset><x-charset><param>chinese-big5-1</param> 
早晨,</x-charset><x-charset><param>japanese-jisx0208</param> 
こんにちは,</x-charset><x-charset><param>korean-ksc5601</param> 안녕하세요</x-charset>
-  Misc:<x-charset><param>latin-iso8859-3</param> Eĥoŝanĝo 
ĉiuĵaŭde,</x-charset><x-charset><param>mule-unicode-2500-33ff</param> 
⠓⠑⠇⠇⠕,</x-charset><x-charset><param>mule-unicode-0100-24ff</param> ∀ p ∈ world 
• hello p  
</x-charset><x-charset><param>mule-unicode-2500-33ff</param>□</x-charset>
+  Misc:<x-charset><param>latin-iso8859-3</param> Eĥoŝanĝo 
ĉiuĵaŭde,</x-charset> ⠓⠑⠇⠇⠕, ∀ p ∈ world • hello p  □
   CJK variety:<x-charset><param>chinese-gb2312</param> 
GB(元气,开发),</x-charset><x-charset><param>chinese-big5-1</param> 
BIG5(元氣,開發),</x-charset><x-charset><param>japanese-jisx0208</param> 
JIS(元気,開発),</x-charset><x-charset><param>korean-ksc5601</param> 
KSC(元氣,開發)</x-charset>
   Unicode charset:<x-charset><param>unicode</param> Eĥoŝanĝo ĉiuĵaŭde, Γειά 
σας, שלום, Здравствуйте!</x-charset>
 
 
 LANGUAGE (NATIVE NAME) HELLO
 ---------------------- -----
-<x-charset><param>mule-unicode-0100-24ff</param>Amharic (አማርኛ) ሠላም
+Amharic (አማርኛ) ሠላም
 Arabic (العربيّة)      السّلام عليكم
 Armenian (հայերեն)     Բարև ձեզ
+Belarusian (беларуская)        Прывітанне
 Bengali (বাংলা)        নমস্কার
-</x-charset><x-charset><param>mule-unicode-2500-33ff</param>Braille    ⠓⠑⠇⠇⠕
-</x-charset><x-charset><param>mule-unicode-0100-24ff</param>Burmese (မြန်မာ)   
မင်္ဂလာပါ
-</x-charset>C  printf ("Hello, world!\n");
-<x-charset><param>unicode</param>Cherokee (ᏣᎳᎩ ᎦᏬᏂᎯᏍᏗ) ᎣᏏᏲ / ᏏᏲ
+Braille        ⠓⠑⠇⠇⠕
+Burmese (မြန်မာ)       မင်္ဂလာပါ
+C      printf ("Hello, world!\n");
+Cherokee (ᏣᎳᎩ ᎦᏬᏂᎯᏍᏗ)  ᎣᏏᏲ / ᏏᏲ
 Comanche /kəˈmæntʃiː/  Haa marʉ́awe
 
 Cree (ᓀᐦᐃᔭᐍᐏᐣ) ᑕᓂᓯ / ᐙᒋᔮ
 
-</x-charset><x-charset><param>latin-iso8859-2</param>Czech (čeština)   Dobrý 
den
-</x-charset><x-charset><param>latin-iso8859-1</param>Danish (dansk)    Hej / 
Goddag / Halløj
+Czech (čeština)        Dobrý den
+Danish (dansk) Hej / Goddag / Halløj
 Dutch (Nederlands)     Hallo / Dag
-</x-charset><x-charset><param>unicode</param>Efik  /ˈɛfɪk/     Mɔkɔm
+Efik  /ˈɛfɪk/  Mɔkɔm
 
 Emacs  emacs --no-splash -f view-hello-file
 
 Emoji  👋
-</x-charset>English <x-charset><param>ipa</param>/ˈɪŋɡlɪʃ/</x-charset> Hello
-<x-charset><param>latin-iso8859-3</param>Esperanto     Saluton (Eĥoŝanĝo 
ĉiuĵaŭde)
-</x-charset><x-charset><param>latin-iso8859-15</param>Estonian (eesti keel)    
Tere päevast / Tere õhtust
-</x-charset><x-charset><param>latin-iso8859-1</param>Finnish (suomi)   Hei / 
Hyvää päivää
+English /ˈɪŋɡlɪʃ/      Hello
+Esperanto      Saluton (Eĥoŝanĝo ĉiuĵaŭde)
+Estonian (eesti keel)  Tere päevast / Tere õhtust
+Finnish (suomi)        Hei / Hyvää päivää
 French (français)      Bonjour / Salut
-</x-charset><x-charset><param>mule-unicode-0100-24ff</param>Georgian (ქართული) 
გამარჯობა
-</x-charset><x-charset><param>latin-iso8859-1</param>German (Deutsch)  Guten 
Tag / Grüß Gott
-</x-charset><x-charset><param>greek-iso8859-7</param>Greek (ελληνικά)  Γειά σας
-</x-charset><x-charset><param>mule-unicode-0100-24ff</param>Greek, ancient 
(ἑλληνική)  Οὖλέ τε καὶ μέγα χαῖρε
+Georgian (ქართული)     გამარჯობა
+German (Deutsch)       Guten Tag / Grüß Gott
+Greek (ελληνικά)       Γειά σας
+Greek, ancient (ἑλληνική)      Οὖλέ τε καὶ μέγα χαῖρε
 Gujarati (ગુજરાતી)     નમસ્તે
-</x-charset><x-charset><param>hebrew-iso8859-8</param>Hebrew (עִבְרִית)        
שָׁלוֹם
-</x-charset><x-charset><param>latin-iso8859-2</param>Hungarian (magyar)        
Szép jó napot!
-</x-charset><x-charset><param>mule-unicode-0100-24ff</param>Hindi (हिंदी)      
नमस्ते / नमस्कार ।
-</x-charset><x-charset><param>unicode</param>Inuktitut (ᐃᓄᒃᑎᑐᑦ)        ᐊᐃ
-
-</x-charset><x-charset><param>latin-iso8859-1</param>Italian (italiano)        
Ciao / Buon giorno
-</x-charset>Javanese (Jawa)    System.out.println("Sugeng siang!");
-<x-charset><param>mule-unicode-0100-24ff</param>Kannada (ಕನ್ನಡ)        ನಮಸ್ಕಾರ
+Hebrew (עִבְרִית)      שָׁלוֹם
+Hungarian (magyar)     Szép jó napot!
+Hindi (हिंदी)  नमस्ते / नमस्कार ।
+Inuktitut (ᐃᓄᒃᑎᑐᑦ)     ᐊᐃ
+
+Italian (italiano)     Ciao / Buon giorno
+Javanese (ꦧꦱꦗꦮ)        console.log("ꦱꦸꦒꦼꦁꦱꦶꦪꦁ");
+Kannada (ಕನ್ನಡ)        ನಮಸ್ಕಾರ
 Khmer (ភាសាខ្មែរ)      ជំរាបសួរ
-</x-charset><x-charset><param>lao</param>Lao (ພາສາລາວ) ສະບາຍດີ / ຂໍໃຫ້ໂຊກດີ
-</x-charset><x-charset><param>mule-unicode-0100-24ff</param>Malayalam (മലയാളം) 
നമസ്കാരം
-</x-charset><x-charset><param>unicode</param>Maldivian (ދިވެހި)        
އައްސަލާމު ޢަލައިކުމް / ކިހިނެހް؟
-
-</x-charset><x-charset><param>latin-iso8859-3</param>Maltese (il-Malti)        
Bonġu / Saħħa
-</x-charset><x-charset><param>unicode</param>Mathematics       ∀ p ∈ world • 
hello p  □
-</x-charset><x-charset><param>cyrillic-iso8859-5</param>Mongolian (монгол хэл) 
Сайн байна уу?
-</x-charset><x-charset><param>latin-iso8859-1</param>Norwegian (norsk) Hei / 
God dag
-</x-charset><x-charset><param>mule-unicode-0100-24ff</param>Oriya (ଓଡ଼ିଆ)       
ଶୁଣିବେ
-</x-charset><x-charset><param>latin-iso8859-2</param>Polish  (język polski)    
Dzień dobry! / Cześć!
-</x-charset><x-charset><param>cyrillic-iso8859-5</param>Russian (русский)      
Здра́вствуйте!
-</x-charset><x-charset><param>mule-unicode-0100-24ff</param>Sinhala (සිංහල)    
ආයුබෝවන්
-</x-charset><x-charset><param>latin-iso8859-2</param>Slovak (slovenčina)       
Dobrý deň
+Lao (ພາສາລາວ)  ສະບາຍດີ / ຂໍໃຫ້ໂຊກດີ
+Malayalam (മലയാളം)     നമസ്കാരം
+Maldivian (ދިވެހި)     އައްސަލާމު ޢަލައިކުމް / ކިހިނެހް؟
+
+Maltese (il-Malti)     Bonġu / Saħħa
+Mathematics    ∀ p ∈ world • hello p  □
+Mongolian (монгол хэл) Сайн байна уу?
+Norwegian (norsk)      Hei / God dag
+Oriya (ଓଡ଼ିଆ)   ଶୁଣିବେ
+Polish  (język polski) Dzień dobry! / Cześć!
+Russian (русский)      Здра́вствуйте!
+Sinhala (සිංහල)        ආයුබෝවන්
+Slovak (slovenčina)    Dobrý deň
 Slovenian (slovenščina)        Pozdravljeni!
-Spanish (espa</x-charset><x-charset><param>latin-iso8859-1</param>ñol) ¡Hola!
+Spanish (español)      ¡Hola!
 Swedish (svenska)      Hej / Goddag / Hallå
-</x-charset><x-charset><param>mule-unicode-0100-24ff</param>Tamil (தமிழ்)      
வணக்கம்
+Tamil (தமிழ்)  வணக்கம்
 Telugu (తెలుగు)        నమస్కారం
-</x-charset>TaiViet (ꪁꪫꪱꪣ ꪼꪕ)  ꪅꪰꪙꫂ ꪨꪮꫂ ꪁꪫꪱ / ꪅꪽ ꪨꪷ ꪁꪫꪱ
+TaiViet (ꪁꪫꪱꪣ ꪼꪕ)      ꪅꪰꪙꫂ ꪨꪮꫂ ꪁꪫꪱ / ꪅꪽ ꪨꪷ ꪁꪫꪱ
+
+Thai (ภาษาไทย) สวัสดีครับ / สวัสดีค่ะ
+Tibetan (བོད་སྐད་)     བཀྲ་ཤིས་བདེ་ལེགས༎
+Tigrigna (ትግርኛ)        ሰላማት
+Turkish (Türkçe)       Merhaba
+Ukrainian (українська) Вітаю
+Vietnamese (tiếng Việt)        Chào bạn
 
-<x-charset><param>thai-tis620</param>Thai (ภาษาไทย)    สวัสดีครับ / สวัสดีค่ะ
-</x-charset><x-charset><param>tibetan</param>Tibetan (བོད་སྐད་)        
བཀྲ་ཤིས་བདེ་ལེགས༎
-</x-charset><x-charset><param>mule-unicode-0100-24ff</param>Tigrigna (ትግርኛ)    
ሰላማት
-</x-charset><x-charset><param>latin-iso8859-9</param>Turkish (Türkçe)  Merhaba
-</x-charset><x-charset><param>cyrillic-iso8859-5</param>Ukrainian (українська) 
Вітаю
-</x-charset><x-charset><param>vietnamese-viscii-lower</param>Vietnamese (tiếng 
</x-charset><x-charset><param>vietnamese-viscii-upper</param>V</x-charset><x-charset><param>vietnamese-viscii-lower</param>iệt)
 </x-charset><x-charset><param>vietnamese-viscii-upper</param>Chào bạn
 
-</x-charset>
 
 <x-charset><param>japanese-jisx0208</param>Japanese (日本語)      
こんにちは</x-charset> <x-charset><param>katakana-jisx0201</param>/ コンニチハ
 </x-charset><x-charset><param>chinese-gb2312</param>Chinese (中文,普通话,汉语)        
你好
@@ -97,7 +98,7 @@ Telugu (తెలుగు)       నమస్కారం
 
 </x-charset>
 
-<x-charset><param>unicode</param>
+
 
 
 Copyright (C) 2001-2020 Free Software Foundation, Inc.
@@ -127,4 +128,4 @@ along with GNU Emacs.  If not, see 
<<https://www.gnu.org/licenses/>.
 ;;; bidi-display-reordering: t
 ;;; coding: utf-8
 ;;; inhibit-compacting-font-caches: t
-;;; End:</x-charset>
+;;; End:
diff --git a/etc/NEWS b/etc/NEWS
index 1838b6b..11c19b3 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -86,13 +86,13 @@ useful on systems such as FreeBSD which ships only with 
"etc/termcap".
 * Changes in Emacs 28.1
 
 +++
-*** A new system for displaying documentation for groups of function is added.
+** New system for displaying documentation for groups of function.
 This can either be used by saying 'M-x shortdoc-display-group' and
 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 var 'redisplay-skip-initial-frame' to enable batch redisplay tests.
+** New var '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.
 
@@ -104,7 +104,7 @@ sequences necessary to render faces with the 
'strike-through'
 attribute on TTY frames.
 
 +++
-*** Emacs now defaults to UTF-8 instead of ISO-8859-1.
+** 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.
@@ -163,13 +163,6 @@ your init file:
     (setq frame-title-format '(multiple-frames "%b"
                               ("" invocation-name "@" system-name)))
 
-** recentf
-
----
-*** '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.
-
 
 * Editing Changes in Emacs 28.1
 
@@ -213,11 +206,6 @@ buffer to be able to move point to the inaccessible 
portion.
 ** When 'suggest-key-bindings' is non-nil, the completion list of 'M-x'
 shows equivalent key bindings for all commands that have them.
 
----
-** 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.
-
 ** Autosaving via 'auto-save-visited-mode' can now be inhibited by
 setting the variable 'auto-save-visited-mode' buffer-locally to nil.
 
@@ -320,6 +308,9 @@ and variables.
 
 ** Archive mode
 
+---
+*** Archive Mode can now parse .squashfs files.
+
 *** Can now modify members of 'ar' archives.
 
 *** Display of summaries unified between backends.
@@ -435,6 +426,11 @@ tags to be considered as well.
 ** Gnus
 
 +++
+*** 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'.
+
++++
 *** 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.
@@ -608,6 +604,16 @@ defaulting to active region when used interactively.
 ** The old non-SMIE indentation of 'sh-mode' has been removed.
 
 ---
+** The 'list-bookmark' 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.
+
+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.
+
+---
 ** The sb-image.el library is now marked obsolete.
 This file was a compatibility kludge which is no longer needed.
 
@@ -658,6 +664,13 @@ 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).
+
 ** Eshell
 
 ---
@@ -726,6 +739,7 @@ key             binding
 / 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
 
 ---
@@ -818,6 +832,14 @@ current environment.
 Its default value matches localized abbreviations of the "reply"
 prefix on the Subject line in various languages.
 
+---
+*** New user option 'shr-offer-extend-specpdl'.
+If this is nil, rendering of HTML in the email message body that
+requires to enlarge 'max-specpdl-size', the number of Lisp variable
+bindings, will be aborted, and Emacs will not ask you whether to
+enlarge 'max-specpdl-size' to complete the rendering.  The default is
+t, which preserves the original behavior.
+
 ** Apropos
 
 *** New commands 'apropos-next-symbol' and 'apropos-previous-symbol'.
@@ -1096,9 +1118,15 @@ 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
-The recentf files are no longer backed up.
+
+---
+*** The recentf files are no longer backed up.
+
+---
+*** '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.
 
 ** Calc
 
@@ -1141,6 +1169,13 @@ window after starting).  This variable defaults to nil.
 +++
 *** 'widget-choose' now supports menus in extended format.
 
+---
+*** 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.
+
 ** Miscellaneous
 
 ---
@@ -1155,6 +1190,8 @@ be done (and this restores how this previously worked).
 *** 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.
 
 +++
 *** New user option 'tab-first-completion'.
@@ -1283,6 +1320,11 @@ never be narrower than 19 characters.
 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.
 
+---
+*** 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.
+
 ** xwidget-webkit mode
 
 *** New xwidget commands.
@@ -1403,9 +1445,11 @@ mode, as are other data files produced by Emacs.
 It's a library to create, query, navigate and display hierarchy structures.
 
 ** New themes 'modus-vivendi' and 'modus-operandi'.
-These themes are designed for colour-contrast accessibility.  You can
-load the new themes using 'M-x customize-themes' or 'load-theme' from
-your init file.
+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.
 
 
 * Incompatible Editing Changes in Emacs 28.1
@@ -1466,6 +1510,11 @@ This is no longer supported, and setting this variable 
has no effect.
 ** The macro 'with-displayed-buffer-window' is now obsolete.
 Use macro 'with-current-buffer-window' with action alist entry 'body-function'.
 
++++
+** `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 metamail.el library is now marked obsolete.
 
 ---
@@ -1702,6 +1751,16 @@ personalize the uniquified buffer name.
 +++
 ** 'inhibit-nul-byte-detection' is renamed to 'inhibit-null-byte-detection'.
 
++++
+** 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'.
+
+---
+** 'unload-feature' now also tries to undo additions to buffer-local hooks.
+
 
 * Changes in Emacs 28.1 on Non-Free Operating Systems
 
diff --git a/etc/NEWS.27 b/etc/NEWS.27
index 149bd32..e793133 100644
--- a/etc/NEWS.27
+++ b/etc/NEWS.27
@@ -21,6 +21,10 @@ Temporary note:
 When you add a new item, use the appropriate mark if you are sure it
 applies, and please also update docstrings as needed.
 
+** Tramp
+
+*** The user option 'tramp-completion-reread-directory-timeout' is made 
obsolete.
+
 
 * Installation Changes in Emacs 27.1
 
@@ -202,7 +206,7 @@ it won't work right without some adjustment:
 Units that are ordered after 'emacs.service' will only be started
 after Emacs has finished initialization and is ready for use, and
 Emacs needs to be built with systemd support.  (If your Emacs is
-installed in a non-standard location and you copied the emacs.service
+installed in a non-standard location and you copied the "emacs.service"
 file to e.g. "~/.config/systemd/user/", you will need to copy the new
 version of the file again.)
 
diff --git a/etc/PROBLEMS b/etc/PROBLEMS
index 41d5ea1..8ed92ab 100644
--- a/etc/PROBLEMS
+++ b/etc/PROBLEMS
@@ -181,6 +181,10 @@ Configure checks for the correct version, but this problem 
could occur
 if a binary built against a shared libungif is run on a system with an
 older version.
 
+** SVG images may be cropped incorrectly with librsvg 2.45 and below.
+Librsvg 2.46 and above have improved geometry code which Emacs is able
+to take advantage of.
+
 ** Emacs aborts inside the function 'tparam1'.
 
 This can happen if Emacs was built without terminfo support, but the
diff --git a/etc/tutorials/TUTORIAL.de b/etc/tutorials/TUTORIAL.de
index 75c03a1..f146156 100644
--- a/etc/tutorials/TUTORIAL.de
+++ b/etc/tutorials/TUTORIAL.de
@@ -19,15 +19,22 @@ EDIT oder ALT genannt).  Folgende Abkürzungen werden 
verwendet:
 <<Blank lines inserted here by startup of help-with-tutorial>>
 [Leerzeilen befinden sich hier aus didaktischen Gründen.  Fortsetzung unten.]
 >> Drücken Sie C-v, um zur nächsten Bildschirmseite vorzublättern.
-        Ab jetzt sollten Sie das stets tun, wenn Sie eine Seite fertig
-        gelesen haben.
+        Ab jetzt sollten Sie das stets tun, wenn Sie das untere
+        Bildschirmende erreicht haben.
 
 Beachten Sie bitte, dass beim Blättern die untersten zwei Zeilen der
 vorigen Bildschirmseite als die zwei obersten Zeilen der neuen Seite
 erscheinen, um eine gewisse Kontinuität während des Lesens zu
 ermöglichen.
 
+Was Sie gerade lesen, ist eine leicht angepasste Kopie der deutschen
+Einführung.  Später werden Sie aufgefordert, verschiedene Befehle
+auszuführen, um den Text der Einführung zu ändern.  Es spielt keine
+Rolle, wenn Sie den Text schon vorher ändern sollten – man nennt das
+»editieren«, und genau dafür ist ein Editor wie Emacs da.
+
 Wichtig: Sie können Emacs mit der Befehlsfolge C-x C-c beenden.
+Diese Einführung beenden Sie mit C-x k, gefolgt von der Eingabetaste.
 
 Im weiteren wird die ESC-Taste mit <ESC> bezeichnet.
 
@@ -41,7 +48,7 @@ Sie schon (C-v).  Mit M-v blättern Sie eine Bildschirmseite 
zurück
 (halten Sie die META-Taste gedrückt und geben Sie v ein, oder drücken
 Sie zuerst <ESC> und anschließend v).
 
->>  Probieren Sie einige Male M-v und C-v aus.
+>> Probieren Sie einige Male M-v und C-v aus.
 
 [Auf den meisten Tastaturen bewirkt die PgUp-Taste (»page up«, auch
 mit »Bild« und einem Aufwärtspfeil beschriftet) dasselbe wie M-v bzw.
@@ -277,14 +284,14 @@ Wert, signalisiert dem Befehl, etwas anderes zu tun.
 
 C-v und M-v sind weitere Ausnahmen.  Gibt man diesen Befehlen einen
 Parameter n, dann verschieben sie den Bildschirminhalt nicht um eine
-ganze Bildschirmseite, sondern um n Zeilen.  Beispiel: C-u 4 C-v
-verschiebt den Bildschirminhalt um vier Zeilen.
+ganze Bildschirmseite, sondern um n Zeilen.  Beispiel: C-u 8 C-v
+verschiebt den dargestellten Text um acht Zeilen.
 
 >> Versuchen Sie jetzt C-u 8 C-v auszuführen.
 
-Der Bildschirminhalt sollte jetzt um acht Zeilen nach oben verschoben
-sein.  Wollen Sie ihn nach unten verschieben, dann geben Sie M-v mit
-einem numerischen Argument ein.
+Der Text sollte jetzt um acht Zeilen nach oben verschoben sein.
+Wollen Sie ihn nach unten verschieben, dann geben Sie M-v mit einem
+numerischen Argument ein.
 
 Wenn Sie eine graphische Oberfläche wie X oder MS-Windows verwenden,
 dann befindet sich ein schmaler, langgezogener rechteckiger Bereich
@@ -411,12 +418,12 @@ Fortsetzungszeile.
 >> Geben Sie <Return> ein, um wieder ein Zeilenvorschubzeichen
    einzufügen.
 
-Die <Return>-Taste ist insofern besonders, als dass sie mehr bewirken
-kann, als einfach ein Zeilenvorschubszeichen einzufügen.  Abhängig vom
-umgebenden Text können zusätzliche Leerzeichen eingefügt werden, damit
-der neue Zeilenanfang bündig zur vorherigen Zeile ist.  Wir nennen
-dieses Verhalten (wenn das Drücken einer Taste mehr bewirkt, als nur
-das entsprechende Zeichen einzufügen) »electric«.
+Die <Return>-Taste ist besonders, da sie mehr bewirken kann als
+einfach ein Zeilenvorschubzeichen einfügen.  Abhängig vom umgebenden
+Text können zusätzliche Leerzeichen eingefügt werden, damit der neue
+Zeilenanfang bündig zur vorherigen Zeile ist.  Wir nennen dieses
+Verhalten (wenn das Drücken einer Taste mehr bewirkt, als nur das
+entsprechende Zeichen einzufügen) »electric«.
 
 >> Ein Beispiel für dieses Verhalten von <Return>.
    Drücken Sie <Return> am Ende dieser Zeile.
@@ -468,7 +475,7 @@ gelöschten Text, damit Sie ihn bei Bedarf wieder 
zurückholen können.
 Einfügen von bereits gelöschtem Text wird im englischen Dokumentation
 von Emacs als »yanking« (wörtlich »herausreißen«) bezeichnet.  Sie
 können den gelöschten Text an einer beliebigen Stelle wieder
-einzufügen.  Solange Sie nichts neues löschen, steht Ihnen dieser
+einfügen.  Solange Sie nichts neues löschen, steht Ihnen dieser
 gelöschte Textteil immer wieder zu Verfügung.  Der Befehl dazu ist C-y
 (das Ypsilon steht für »yank«).
 
@@ -584,9 +591,11 @@ Anzahl der notwendigen C-/-Befehle zu reduzieren.
 >> Löschen Sie diese Zeilen mit C-k und drücken Sie anschließend
    mehrmals C-/, und die Zeilen erscheinen wieder.
 
-Alternative Tastenkombinationen für C-/ sind C-_ und C-x u.  Ein
-numerisches Argument für C-/, C-_ oder C-x u wird als
-Wiederholungszähler interpretiert.
+Alternative Tastenkombinationen für C-/ sind C-_ und C-x u (in manchen
+Terminals funktioniert C-_ auch ohne SHIFT-Taste).  Wählen Sie das
+aus, was am bequemsten für Sie zu tippen ist.  Ein numerisches
+Argument für C-/, C-_ oder C-x u wird als Wiederholungszähler
+interpretiert.
 
 Der Unterschied zwischen der Undo-Funktion und dem oben erklärten C-y
 ist, dass erstere gelöschten Text an exakt der gleichen Position wie
@@ -668,10 +677,7 @@ Name besteht aus dem Originalnamen plus einer angehängten 
Tilde »~«
 Namenserweiterung durch ».bak« ersetzt].
 
 Emacs schreibt den Namen der gesicherten Datei in die unterste Zeile,
-sobald C-x C-s fertig ausgeführt ist.  Sie sollten den editierten Text
-oft speichern, damit nicht allzuviel bei einem etwaigen Systemabsturz
-verloren geht (siehe auch den Abschnitt »AUTOMATISCHES SPEICHERN«
-weiter unten).
+sobald C-x C-s fertig ausgeführt ist.
 
 >> Geben Sie
 
@@ -715,12 +721,11 @@ ein.
 
 >> Probieren Sie jetzt C-x C-b.
 
-Beachten Sie, dass jeder Puffer einen Namen hat und manche auch mit
-dem Namen einer Datei assoziiert sind, dessen Inhalt sie enthalten.
-Manche Puffer aber haben keinen zugehörige Datei, z.B. der mit dem
-Namen »*Buffer List*«.  Er wurde von dem Befehl C-x C-b erzeugt, um
-die Pufferliste darzustellen.  JEDER Text, den Sie innerhalb Emacs in
-einem Fenster sehen, ist immer ein Ausschnitt eines Puffers.
+Beachten Sie, dass manche Puffer keine zugehörige Datei haben,
+z.B. der mit dem Namen »*Buffer List*«.  Er wurde von dem Befehl C-x
+C-b erzeugt, um die Pufferliste darzustellen.  JEDER Text, den Sie
+innerhalb Emacs in einem Fenster sehen, ist immer ein Ausschnitt eines
+Puffers.
 
 >> Geben Sie jetzt C-x 1 ein, um die Pufferliste wieder verschwinden
    zu lassen.
@@ -748,13 +753,11 @@ den Verzeichnispräfix), jedoch nicht immer.  Die von C-x 
C-b erzeugte
 Pufferliste zeigt stets die Namen aller Puffer mit den
 korrespondierenden Dateinamen.
 
-JEDER Text in Emacs ist Teil eines Puffers, aber nicht jeder Puffer
-entspricht einer Datei.  So ist z.B. der Puffer »*Buffer List*« mit
-keiner Datei assoziiert -- er wurde direkt von dem Befehl C-x C-b
-erzeugt.  Auch dieser »TUTORIAL.de«-Puffer war anfangs keiner Datei
-zugeordnet, jetzt allerdings schon, denn Sie haben im letzten
-Abschnitt den Befehl C-x C-s eingegeben und so den Pufferinhalt als
-Datei gespeichert.
+Wie schon erwähnt, ist JEDER Text in Emacs Teil eines Puffers, aber
+nicht jeder Puffer entspricht einer Datei.  Auch dieser
+»TUTORIAL.de«-Puffer war anfangs keiner Datei zugeordnet, jetzt
+allerdings schon, denn Sie haben im letzten Abschnitt den Befehl C-x
+C-s eingegeben und so den Pufferinhalt als Datei gespeichert.
 
 Der Puffer »*Messages*« hat ebenfalls keine Entsprechung als Datei; er
 enthält alle Mitteilungen, die in der untersten Zeile während des
@@ -774,10 +777,10 @@ Datei permanent abzuspeichern.  Es wäre äußerst 
umständlich, müsste
 man jedesmal C-x C-f eingeben, um den Puffer dann mit C-x C-s
 abzuspeichern.  Daher gibt es den Befehl
 
-        C-x s                     (sichere mehrere Puffer)
+        C-x s                     (sichere mehrere Puffer in Dateien)
 
-Dieser Befehl fragt Sie bei jedem Puffer, der Änderungen enthält, ob
-Sie ihn speichern wollen.
+Dieser Befehl fragt Sie bei jedem einer Datei zugeordneten Puffer, der
+Änderungen enthält, ob Sie ihn in der Datei speichern wollen.
 
 >> Fügen Sie eine Textzeile ein und drücken Sie dann C-x s.
    Emacs fragt Sie jetzt, ob Sie einen Puffer mit dem Namen
@@ -824,15 +827,15 @@ zu Emacs zurückzukehren.
 
 Der beste Zeitpunkt für C-x C-c ist, wenn Sie sich ausloggen
 (bzw. Ihren Computer ausschalten); Sie sollten Emacs ebenfalls
-beenden, wenn Sie Emacs von einem anderen Programm aus aufgerufen
-haben (z.B. einem Programm, das E-mails liest).
+beenden, wenn Sie Emacs von einem anderen Programm aus kurzzeitig
+aufgerufen haben (z.B. einem Programm, das E-Mails liest).
 
 Hier ist eine Liste aller C-x-Befehle, die Sie bereits kennengelernt
 haben:
 
         C-x C-f         lade Datei
-        C-x C-s         sichere Datei
-        C-x s           sichere einige Puffer
+        C-x C-s         sichere Puffer in Datei
+        C-x s           sichere einige Puffer in zugehörige Dateien
         C-x C-b         zeige Pufferliste an
         C-x b           wechsle zu Puffer
         C-x C-c         beende Emacs
@@ -840,10 +843,10 @@ haben:
         C-x u           widerrufen
 
 Ein Beispiel für einen Befehl mit langen Namen ist replace-string, der
-global (also in der ganzen Datei bzw. Puffer) eine Zeichenkette durch
-eine andere ersetzt.  Wenn Sie M-x drücken, dann fragt Sie Emacs in
-der untersten Bildschirmzeile nach dem Namen des Befehls (in diesem
-Fall »replace-string«).  Geben Sie jetzt »repl s<TAB>« ein und Emacs
+in der ganzen Datei bzw. Puffer eine Zeichenkette durch eine andere
+ersetzt.  Wenn Sie M-x drücken, dann fragt Sie Emacs in der untersten
+Bildschirmzeile nach dem Namen des Befehls (in diesem Fall
+»replace-string«).  Geben Sie jetzt »repl s<TAB>« ein und Emacs
 vervollständigt den Namen.  Schließen Sie die Eingabe mit <Return> ab.
 [<TAB> bezeichnet die Tabulatortaste.]
 
@@ -855,7 +858,7 @@ vervollständigt den Namen.  Schließen Sie die Eingabe mit 
<Return> ab.
    ein und kehren Sie mit C-u C-SPC an diese Position zurück.
 
    Beachten Sie wie diese Bildschirmzeile jetzt aussieht: Sie haben
-   den Wortteil B-i-l-d-s-c-h-i-r-m durch »Text« ersetzt (und zwar im
+   den Wortteil »Bildschirm« durch »Text« ersetzt (und zwar im
    ganzen Dokument beginnend von der Cursorposition).
 
 >> Drücken Sie jetzt C-x u, um diese Änderungen auf einmal rückgängig
@@ -878,8 +881,8 @@ Stürzt der Rechner einmal wirklich ab, können Sie die 
Änderungen, die
 beim letzten Auto-Save gespeichert worden sind, folgendermaßen
 wiederherstellen: Laden Sie die Datei auf normalem Wege (die Datei,
 die Sie bearbeitet haben, nicht die Auto-Save-Datei) und geben Sie
-dann »M-x recover-file <Return>« ein.  Wenn Emacs Sie um Bestätigung
-fragt, antworten Sie mit »yes <Return>«, um den Inhalt der
+dann »M-x recover-this-file <Return>« ein.  Wenn Emacs Sie um
+Bestätigung fragt, antworten Sie mit »yes <Return>«, um den Inhalt der
 Auto-Save-Datei zu übernehmen.
 
 
@@ -979,6 +982,7 @@ jeweils ein bisschen anders.
 
 Dokumentation zum derzeit aktuellen Hauptmodus bekommen Sie mit C-h m.
 
+>> Bewegen Sie den Cursor zur nächsten Zeile.
 >> Drücken Sie C-l C-l, um diese Zeile an den oberen Bildschirmrand zu
    bringen.
 >> Lesen Sie nun mittels C-h m die englische Dokumentation zum
@@ -1129,13 +1133,13 @@ Rechteck dargestellt).  Alle normalen Editierbefehle 
betreffen das
 Fenster, in dem sich der Cursor befindet.  Wir nennen dieses Fenster
 »ausgewählt« (»selected window«).
 
-Der Befehl M-C-v ist sehr nützlich, wenn man Text in einem Fenster
+Der Befehl C-M-v ist sehr nützlich, wenn man Text in einem Fenster
 editiert und das andere Fenster als Referenz verwendet.  Ohne das
-momentante Arbeitsfenster verlassen zu müssen, kann man mit M-C-v im
+momentante Arbeitsfenster verlassen zu müssen, kann man mit C-M-v im
 anderen Fenster bequem vorwärtsblättern.
 
-M-C-v ist ein Beispiel eines CONTROL-META-Zeichens.  Haben Sie eine
-META-Taste, dann kann man M-C-v erzeugen, indem man CTRL und META
+C-M-v ist ein Beispiel eines CONTROL-META-Zeichens.  Haben Sie eine
+META-Taste, dann kann man C-M-v erzeugen, indem man CTRL und META
 gleichzeitig niedergedrückt hält, während man v eintippt.  Es ist
 egal, ob zuerst CTRL oder META niedergedrückt wird, da beide Tasten
 gleichberechtigt das jeweils einzugebende Zeichen modifizieren.
@@ -1146,10 +1150,10 @@ gefolgt von CTRL-v.  CTRL-ESC v funktioniert nicht!  
Der Grund dafür
 ist, dass ESC ein eigenes Zeichen ist und keine Modifizier-Taste wie
 META oder CTRL.
 
-Der umgekehrte Befehl zu M-C-v ist M-C-S-v, um im anderen Fenster
-rückwärts zu blättern (d.h., Sie müssen die META-Taste sowie die
-CONTROL- und SHIFT-Taste zusammen mit »v« betätigen) -- jetzt werden
-Sie wahrscheinlich verstehen, warum manche Kritiker das Wort Emacs als
+Der umgekehrte Befehl zu C-M-v ist C-M-S-v, um im anderen Fenster
+rückwärts zu blättern (d.h., Sie müssen die CONTROL-Taste sowie die
+META- und SHIFT-Taste zusammen mit »v« betätigen) -- jetzt werden Sie
+wahrscheinlich verstehen, warum manche Kritiker das Wort Emacs als
 Abkürzung von Escape-Meta-Alt-Control-Shift betrachten.  Leider
 funktioniert diese Befehlsfolge normalerweise nur mit graphischen
 Oberflächen, da C-v von C-S-v auf den meisten Textterminals nicht
@@ -1196,7 +1200,7 @@ Textterminal kann genau ein Rahmen dargestellt werden.
 
 >> Geben Sie
 
-     M-x make-frame <Return>
+     C-x 5 2
 
    ein, um einen neuen Rahmen zu erzeugen.
 
@@ -1206,7 +1210,7 @@ gleichwertig.
 
 >> Geben Sie
 
-     M-x delete-frame <Return>
+     C-x 5 0
 
    ein, um den ausgewählten Rahmen zu entfernen.
 
@@ -1343,7 +1347,7 @@ zwar für die Tastatur- und Bildschirmkodierung.]
 Wir haben uns bemüht, in dieser Einführung genau soviel Information zu
 geben, dass Sie beginnen können, mit Emacs zu arbeiten.  Emacs ist
 jedoch so mächtig und umfangreich, dass es den Rahmen einer Einführung
-spränge, an dieser Stelle mehr zu erklären.  Um Sie im weiteren
+sprengte, an dieser Stelle mehr zu erklären.  Um Sie im weiteren
 Lernverlauf zu unterstützen, stellt Emacs eine Reihe von
 Hilfe-Funktionen zu Verfügung, die alle mit dem Präfix C-h (dem
 Hilfe-Zeichen, »Help character«) beginnen.
@@ -1424,18 +1428,44 @@ zugehörigen langen Namen, find-file.
 
 >> Schließen Sie das Hilfefenster mit C-x 1.
 
-   C-h i        Dieser Befehl öffnet einen speziellen Puffer, um
-                Handbücher zu lesen (im »Info«-Format), die auf dem
+   C-h i        Dieser Befehl öffnet einen speziellen Puffer »*info*«,
+                um Handbücher zu lesen (im »Info«-Format), die auf dem
                 verwendeten Computersystem installiert sind.  Geben
                 Sie z.B. m emacs <Return> ein, um das Emacs-Handbuch
                 zu lesen.  Haben Sie »Info« noch nie benutzt, tippen
-                Sie ?, und Emacs führt Sie Schritt für Schritt durch
+                Sie h, und Emacs führt Sie Schritt für Schritt durch
                 die Möglichkeiten des Info-Modus.  Wenn Sie diese
                 Einführung fertiggelesen haben, sollten Sie das
                 Info-Handbuch für Emacs als primäre Dokumentation
                 benutzen.
 
 
+* MEHR FEATURES
+---------------
+
+Sie können mehr über Emacs lernen, in dem Sie das Handbuch lesen,
+entweder in der gedruckten Form oder innerhalb von Emacs (benützen Sie
+dazu das Hilfe-Menu oder tippen Sie C-h r).  Zwei besonders nützliche
+Features sind Vervollständigung, um weniger tippen zu müssen, und
+Dired, um das Laden von Dateien zu vereinfachen.
+
+Das Vervollständigungs-Feature ist eine Methode, um unnötiges Eingeben
+von Zeichen zu vermeiden.  Wenn Sie beispielsweise zum
+»*Messages*«-Puffer umschalten wollen, genügt C-x b *M<TAB>, und Emacs
+ergänzt automatisch den Namen des Puffers, soweit das anhand der
+bisherigen Eingabe möglich ist.  Vervollständigung funktioniert auch
+für Befehls- und Dateinamen.  Eine genaue Beschreibung finden Sie im
+Abschnitt »Completion« des Emacs-Handbuchs.
+
+Dired ermöglicht es, Dateien eines Verzeichnisses (auf Wunsch
+inklusive seiner Unterverzeichnisse) aufzulisten, sich innerhalb der
+Liste zu bewegen, Dateien zu besuchen, umzubenennen, zu löschen u.a.
+Eine genaue Beschreibung finden Sie im Abschnitt »Dired« des
+Emacs-Handbuchs.
+
+Viele weitere Features sind ebenfalls im Handbuch beschrieben.
+
+
 * SCHLUSSBEMERKUNG
 ------------------
 
diff --git a/etc/tutorials/TUTORIAL.fr b/etc/tutorials/TUTORIAL.fr
index bc94f9a..3148c3f 100644
--- a/etc/tutorials/TUTORIAL.fr
+++ b/etc/tutorials/TUTORIAL.fr
@@ -917,7 +917,7 @@ que vous recherchez. <Entrée> termine une recherche.
 
 Avez-vous vu ce qui se passait ?  Emacs, dans une recherche
 incrémentale, essaie d'aller sur l'occurrence de la chaîne que vous
-avec tapée jusqu'à cet instant. Pour aller sur l'occurrence suivante de
+avez tapée jusqu'à cet instant. Pour aller sur l'occurrence suivante de
 « curseur », il suffit de refaire C-s : s'il ne trouve rien, Emacs
 bippe et vous indique que la recherche a échoué. C-g permet également
 de mettre fin à la recherche.
diff --git a/lisp/Makefile.in b/lisp/Makefile.in
index 75563ad..9187308 100644
--- a/lisp/Makefile.in
+++ b/lisp/Makefile.in
@@ -556,4 +556,10 @@ $(lisp)/progmodes/cc-mode.elc: 
$(lisp)/progmodes/cc-langs.elc \
 $(lisp)/progmodes/cc-styles.elc: $(lisp)/progmodes/cc-vars.elc \
    $(lisp)/progmodes/cc-align.elc
 
+# https://debbugs.gnu.org/43037
+# js.elc (like all modes using CC Mode's compile time macros) needs to
+# be compiled under the same version of CC Mode it will run with.
+$(lisp)/progmodes/js.elc: $(lisp)/progmodes/cc-defs.elc \
+   $(lisp)/progmodes/cc-engine.elc $(lisp)/progmodes/cc-mode.elc
+
 # Makefile ends here.
diff --git a/lisp/ansi-color.el b/lisp/ansi-color.el
index 141ad23..c3b2d98 100644
--- a/lisp/ansi-color.el
+++ b/lisp/ansi-color.el
@@ -414,11 +414,17 @@ this."
        ;; if the rest of the region should have a face, put it there
        (funcall ansi-color-apply-face-function
                 start-marker end-marker (ansi-color--find-face codes))
-       (setq ansi-color-context-region (if codes (list codes)))))
+        ;; Save a restart position when there are codes active. It's
+        ;; convenient for man.el's process filter to pass `begin'
+        ;; positions that overlap regions previously colored; these
+        ;; `codes' should not be applied to that overlap, so we need
+        ;; to know where they should really start.
+       (setq ansi-color-context-region (if codes (list codes end-marker)))))
     ;; Clean up our temporary markers.
     (unless (eq start-marker (cadr ansi-color-context-region))
       (set-marker start-marker nil))
-    (set-marker end-marker nil)))
+    (unless (eq end-marker (cadr ansi-color-context-region))
+      (set-marker end-marker nil))))
 
 (defun ansi-color-apply-overlay-face (beg end face)
   "Make an overlay from BEG to END, and apply face FACE.
diff --git a/lisp/arc-mode.el b/lisp/arc-mode.el
index eb62a85..ce0c061 100644
--- a/lisp/arc-mode.el
+++ b/lisp/arc-mode.el
@@ -51,17 +51,17 @@
 ;; ARCHIVE TYPES: Currently only the archives below are handled, but the
 ;; structure for handling just about anything is in place.
 ;;
-;;                     Arc     Lzh     Zip     Zoo     Rar     7z      Ar
-;;                     --------------------------------------------------
-;; View listing                Intern  Intern  Intern  Intern  Y       Y       
Y
-;; Extract member      Y       Y       Y       Y       Y       Y       Y
-;; Save changed member Y       Y       Y       Y       N       Y       Y
-;; Add new member      N       N       N       N       N       N       N
-;; Delete member       Y       Y       Y       Y       N       Y       N
-;; Rename member       Y       Y       N       N       N       N       N
-;; Chmod               -       Y       Y       -       N       N       N
-;; Chown               -       Y       -       -       N       N       N
-;; Chgrp               -       Y       -       -       N       N       N
+;;                     Arc     Lzh     Zip     Zoo     Rar     7z      Ar      
Squashfs
+;;                     
---------------------------------------------------------------
+;; View listing                Intern  Intern  Intern  Intern  Y       Y       
Y       Y
+;; Extract member      Y       Y       Y       Y       Y       Y       Y       
Y
+;; Save changed member Y       Y       Y       Y       N       Y       Y       
N
+;; Add new member      N       N       N       N       N       N       N       
N
+;; Delete member       Y       Y       Y       Y       N       Y       N       
N
+;; Rename member       Y       Y       N       N       N       N       N       
N
+;; Chmod               -       Y       Y       -       N       N       N       
N
+;; Chown               -       Y       -       -       N       N       N       
N
+;; Chgrp               -       Y       -       -       N       N       N       
N
 ;;
 ;; Special thanks to Bill Brodie <wbrodie@panix.com> for very useful tips
 ;; on the first released version of this package.
@@ -370,6 +370,24 @@ file.  Archive and member name will be added."
                       :inline t
                       (string :format "%v"))))
 
+;; ------------------------------
+;; Squashfs archive configuration
+
+(defgroup archive-squashfs nil
+  "Squashfs-specific options to archive."
+  :group 'archive)
+
+(defcustom archive-squashfs-extract '("rdsquashfs" "-c")
+  "Program and its options to run in order to extract a squashsfs file member.
+Extraction should happen to standard output.  Archive and member name will
+be added."
+  :type '(list (string :tag "Program")
+              (repeat :tag "Options"
+                      :inline t
+                      (string :format "%v")))
+  :version "28.1"
+  :group 'archive-squashfs)
+
 ;; -------------------------------------------------------------------------
 ;;; Section: Variables
 
@@ -741,6 +759,7 @@ archive.
                 (re-search-forward "Rar!" (+ (point) 100000) t))
            'rar-exe)
          ((looking-at "7z\274\257\047\034") '7z)
+          ((looking-at "hsqs") 'squashfs)
          (t (error "Buffer format not recognized")))))
 ;; -------------------------------------------------------------------------
 
@@ -2280,6 +2299,85 @@ NAME is expected to be the 16-bytes part of an ar 
record."
    descr
    '("ar" "r")))
 
+;; -------------------------------------------------------------------------
+;;; Section Squashfs archives.
+
+(defun archive-squashfs-summarize (&optional file)
+  (unless file
+    (setq file buffer-file-name))
+  (let ((copy (file-local-copy file))
+        (files ()))
+    (with-temp-buffer
+      (call-process "unsquashfs" nil t nil "-ll" (or file copy))
+      (when copy
+        (delete-file copy))
+      (goto-char (point-min))
+      (search-forward-regexp "[drwxl\\-]\\{10\\}")
+      (beginning-of-line)
+      (while (looking-at (concat
+                          "^\\(.[rwx\\-]\\{9\\}\\) " ;Mode
+                          "\\(.+\\)/\\(.+\\) "       ;user/group
+                          "\\(.+\\) "                ;size
+                          "\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}\\) " ;date
+                          "\\([0-9]\\{2\\}:[0-9]\\{2\\}\\) " ;time
+                          "\\(.+\\)\n"))                     ;Filename
+        (let* ((name (match-string 7))
+               (flags (match-string 1))
+               (uid (match-string 2))
+               (gid (match-string 3))
+               (size (string-to-number (match-string 4)))
+               (date (match-string 5))
+               (time (match-string 6))
+               (date-time)
+               (mode))
+          ;; Only list directory and regular files
+          (when (or (eq (aref flags 0) ?d)
+                    (eq (aref flags 0) ?-))
+            (when (equal name "squashfs-root")
+              (setf name "/"))
+            ;; Remove 'squashfs-root/' from filenames.
+            (setq name (string-replace "squashfs-root/" "" name))
+            (setq date-time (concat date " " time))
+            (setq mode (logior
+                        (cond
+                         ((eq (aref flags 0) ?d) #o40000)
+                         (t 0))
+                        ;; Convert symbolic to octal representation.
+                        (file-modes-symbolic-to-number
+                         (concat
+                          "u=" (string-replace "-" "" (substring flags 1 4))
+                          ",g=" (string-replace "-" "" (substring flags 4 7))
+                          ",o=" (string-replace "-" ""
+                                                (substring flags 7 10))))))
+            (push (archive--file-desc name name mode size
+                                      date-time :uid uid :gid gid)
+                  files)))
+        (goto-char (match-end 0))))
+    (archive--summarize-descs (nreverse files))))
+
+(defun archive-squashfs-extract-by-stdout (archive name command
+                                                   &optional stderr-test)
+  (let ((stderr-file (make-temp-file "arc-stderr")))
+    (unwind-protect
+       (prog1
+           (apply #'call-process
+                  (car command)
+                  nil
+                  (if stderr-file (list t stderr-file) t)
+                  nil
+                  (append (cdr command) (list name archive)))
+         (with-temp-buffer
+           (insert-file-contents stderr-file)
+           (goto-char (point-min))
+           (when (if (stringp stderr-test)
+                     (not (re-search-forward stderr-test nil t))
+                   (> (buffer-size) 0))
+             (message "%s" (buffer-string)))))
+      (if (file-exists-p stderr-file)
+          (delete-file stderr-file)))))
+
+(defun archive-squashfs-extract (archive name)
+  (archive-squashfs-extract-by-stdout archive name archive-squashfs-extract))
 
 ;; -------------------------------------------------------------------------
 ;; This line was a mistake; it is kept now for compatibility.
diff --git a/lisp/bookmark.el b/lisp/bookmark.el
index dcb03ad..ab7b04d 100644
--- a/lisp/bookmark.el
+++ b/lisp/bookmark.el
@@ -32,6 +32,7 @@
 ;;; Code:
 
 (require 'pp)
+(require 'tabulated-list)
 (require 'text-property-search)
 (eval-when-compile (require 'cl-lib))
 
@@ -126,16 +127,16 @@ recently set ones come first, oldest ones come last)."
 (defconst bookmark-bmenu-buffer "*Bookmark List*"
   "Name of buffer used for Bookmark List.")
 
-(defcustom bookmark-bmenu-use-header-line t
+(defvar bookmark-bmenu-use-header-line t
   "Non-nil means to use an immovable header line.
-This is as opposed to inline text at the top of the buffer."
-  :version "24.4"
-  :type 'boolean)
+This is as opposed to inline text at the top of the buffer.")
+(make-obsolete-variable 'bookmark-bmenu-use-header-line "no longer used." 
"28.1")
 
 (defconst bookmark-bmenu-inline-header-height 2
   "Number of lines used for the *Bookmark List* header.
 \(This is only significant when `bookmark-bmenu-use-header-line'
 is nil.)")
+(make-obsolete-variable 'bookmark-bmenu-inline-header-height "no longer used." 
"28.1")
 
 (defconst bookmark-bmenu-marks-width 2
   "Number of columns (chars) used for the *Bookmark List* marks column.
@@ -165,6 +166,7 @@ A non-nil value may result in truncated bookmark names."
   "Time before `bookmark-bmenu-search' updates the display."
   :type  'number)
 
+;; FIXME: No longer used.  Should be declared obsolete or removed.
 (defface bookmark-menu-heading
   '((t (:inherit font-lock-type-face)))
   "Face used to highlight the heading in bookmark menu buffers."
@@ -976,7 +978,7 @@ Lines beginning with `#' are ignored."
     (when from-bookmark-list
       (pop-to-buffer (get-buffer bookmark-bmenu-buffer))
       (goto-char (point-min))
-      (text-property-search-forward 'bookmark-name-prop bookmark-name))
+      (bookmark-bmenu-bookmark))
     (kill-buffer old-buffer)))
 
 
@@ -1587,7 +1589,7 @@ unique numeric suffixes \"<2>\", \"<3>\", etc."
 
 (defvar bookmark-bmenu-mode-map
   (let ((map (make-keymap)))
-    (set-keymap-parent map special-mode-map)
+    (set-keymap-parent map tabulated-list-mode-map)
     (define-key map "v" 'bookmark-bmenu-select)
     (define-key map "w" 'bookmark-bmenu-locate)
     (define-key map "5" 'bookmark-bmenu-other-frame)
@@ -1607,8 +1609,6 @@ unique numeric suffixes \"<2>\", \"<3>\", etc."
     (define-key map "d" 'bookmark-bmenu-delete)
     (define-key map "D" 'bookmark-bmenu-delete-all)
     (define-key map " " 'next-line)
-    (define-key map "n" 'next-line)
-    (define-key map "p" 'previous-line)
     (define-key map "\177" 'bookmark-bmenu-backup-unmark)
     (define-key map "u" 'bookmark-bmenu-unmark)
     (define-key map "U" 'bookmark-bmenu-unmark-all)
@@ -1676,6 +1676,30 @@ Don't affect the buffer ring order."
         (save-window-excursion
           (bookmark-bmenu-list)))))
 
+(defun bookmark-bmenu--revert ()
+  "Re-populate `tabulated-list-entries'."
+  (let (entries)
+    (dolist (full-record (bookmark-maybe-sort-alist))
+      (let* ((name       (bookmark-name-from-full-record full-record))
+             (annotation (bookmark-get-annotation full-record))
+             (location   (bookmark-location full-record)))
+        (push (list
+               full-record
+               `[,(if (and annotation (not (string-equal annotation "")))
+                      "*" "")
+                 ,(if (display-mouse-p)
+                      (propertize name
+                                  'font-lock-face 'bookmark-menu-bookmark
+                                  'mouse-face 'highlight
+                                  'follow-link t
+                                  'help-echo "mouse-2: go to this bookmark in 
other window")
+                    name)
+                 ,@(if bookmark-bmenu-toggle-filenames
+                       (list location))])
+              entries)))
+    (tabulated-list-init-header)
+    (setq tabulated-list-entries entries))
+  (tabulated-list-print t))
 
 ;;;###autoload
 (defun bookmark-bmenu-get-buffer ()
@@ -1702,70 +1726,18 @@ deletion, or > if it is flagged for displaying."
     (if (called-interactively-p 'interactive)
         (switch-to-buffer buf)
       (set-buffer buf)))
-  (let ((inhibit-read-only t))
-    (erase-buffer)
-    (if (not bookmark-bmenu-use-header-line)
-      (insert "% Bookmark\n- --------\n"))
-    (add-text-properties (point-min) (point)
-                        '(font-lock-face bookmark-menu-heading))
-    (dolist (full-record (bookmark-maybe-sort-alist))
-      (let ((name        (bookmark-name-from-full-record full-record))
-            (annotation  (bookmark-get-annotation full-record))
-            (start       (point))
-            end)
-        ;; if a bookmark has an annotation, prepend a "*"
-        ;; in the list of bookmarks.
-        (insert (if (and annotation (not (string-equal annotation "")))
-                    " *" "  ")
-                name)
-        (setq end (point))
-        (put-text-property
-         (+ bookmark-bmenu-marks-width start) end 'bookmark-name-prop name)
-        (when (display-mouse-p)
-          (add-text-properties
-           (+ bookmark-bmenu-marks-width start) end
-           '(font-lock-face bookmark-menu-bookmark
-            mouse-face highlight
-             follow-link t
-             help-echo "mouse-2: go to this bookmark in other window")))
-        (insert "\n")))
-    (set-buffer-modified-p (not (= bookmark-alist-modification-count 0)))
-    (goto-char (point-min))
-    (bookmark-bmenu-mode)
-    (if bookmark-bmenu-use-header-line
-       (bookmark-bmenu-set-header)
-      (forward-line bookmark-bmenu-inline-header-height))
-    (when (and bookmark-alist bookmark-bmenu-toggle-filenames)
-      (bookmark-bmenu-toggle-filenames t))))
+  (bookmark-bmenu-mode)
+  (bookmark-bmenu--revert))
 
 ;;;###autoload
 (defalias 'list-bookmarks 'bookmark-bmenu-list)
 ;;;###autoload
 (defalias 'edit-bookmarks 'bookmark-bmenu-list)
 
-;; FIXME: This could also display the current default bookmark file
-;; according to `bookmark-bookmarks-timestamp'.
-(defun bookmark-bmenu-set-header ()
-  "Set the immutable header line."
-  (let ((header (copy-sequence "%% Bookmark")))
-    (when bookmark-bmenu-toggle-filenames
-      (setq header (concat header
-                          (make-string (- bookmark-bmenu-file-column
-                                          (- (length header) 3))  ?\s)
-                          "File")))
-    (let ((pos 0))
-      (while (string-match "[ \t\n]+" header pos)
-       (setq pos (match-end 0))
-       (put-text-property (match-beginning 0) pos 'display
-                          (list 'space :align-to (- pos 1))
-                          header)))
-    (put-text-property 0 2 'face 'fixed-pitch header)
-    (setq header (concat (propertize " " 'display '(space :align-to 0))
-                        header))
-    ;; Code derived from `buff-menu.el'.
-    (setq header-line-format header)))
-
-(define-derived-mode bookmark-bmenu-mode special-mode "Bookmark Menu"
+(define-obsolete-function-alias 'bookmark-bmenu-set-header
+  #'tabulated-list-init-header "28.1")
+
+(define-derived-mode bookmark-bmenu-mode tabulated-list-mode "Bookmark Menu"
   "Major mode for editing a list of bookmarks.
 Each line describes one of the bookmarks in Emacs.
 Letters do not insert themselves; instead, they are commands.
@@ -1804,7 +1776,31 @@ Bookmark names preceded by a \"*\" have annotations.
 \\[bookmark-bmenu-edit-annotation] -- edit the annotation for the current 
bookmark.
 \\[bookmark-bmenu-search] -- incrementally search for bookmarks."
   (setq truncate-lines t)
-  (setq buffer-read-only t))
+  (setq buffer-read-only t)
+  ;; FIXME: The header could also display the current default bookmark file
+  ;; according to `bookmark-bookmarks-timestamp'.
+  (setq tabulated-list-format
+        `[("" 1) ;; Space to add "*" for bookmark with annotation
+          ("Bookmark" ,bookmark-bmenu-file-column 
bookmark-bmenu--name-predicate)
+          ,@(if bookmark-bmenu-toggle-filenames
+                '(("File" 0 bookmark-bmenu--file-predicate)))])
+  (setq tabulated-list-padding bookmark-bmenu-marks-width)
+  (setq tabulated-list-sort-key '("Bookmark" . nil))
+  (add-hook 'tabulated-list-revert-hook #'bookmark-bmenu--revert nil t)'
+  (setq revert-buffer-function 'bookmark-bmenu--revert)
+  (tabulated-list-init-header))
+
+
+(defun bookmark-bmenu--name-predicate (a b)
+  "Predicate to sort \"*Bookmark List*\" buffer by the name column.
+This is used for `tabulated-list-format' in `bookmark-bmenu-mode'."
+  (string< (caar a) (caar b)))
+
+
+(defun bookmark-bmenu--file-predicate (a b)
+  "Predicate to sort \"*Bookmark List*\" buffer by the file column.
+This is used for `tabulated-list-format' in `bookmark-bmenu-mode'."
+  (string< (bookmark-location (car a)) (bookmark-location (car b))))
 
 
 (defun bookmark-bmenu-toggle-filenames (&optional show)
@@ -1813,100 +1809,42 @@ Optional argument SHOW means show them 
unconditionally."
   (interactive)
   (cond
    (show
-    (setq bookmark-bmenu-toggle-filenames nil)
-    (bookmark-bmenu-show-filenames)
     (setq bookmark-bmenu-toggle-filenames t))
    (bookmark-bmenu-toggle-filenames
-    (bookmark-bmenu-hide-filenames)
     (setq bookmark-bmenu-toggle-filenames nil))
    (t
-    (bookmark-bmenu-show-filenames)
     (setq bookmark-bmenu-toggle-filenames t)))
-  (when bookmark-bmenu-use-header-line
-    (bookmark-bmenu-set-header)))
-
-
-(defun bookmark-bmenu-show-filenames (&optional force)
-  "In an interactive bookmark list, show filenames along with bookmarks.
-Non-nil FORCE forces a redisplay showing the filenames.  FORCE is used
-mainly for debugging, and should not be necessary in normal use."
-  (if (and (not force) bookmark-bmenu-toggle-filenames)
-      nil ;already shown, so do nothing
-    (with-buffer-modified-unmodified
-     (save-excursion
-       (save-window-excursion
-         (goto-char (point-min))
-        (if (not bookmark-bmenu-use-header-line)
-            (forward-line bookmark-bmenu-inline-header-height))
-         (setq bookmark-bmenu-hidden-bookmarks ())
-         (let ((inhibit-read-only t))
-           (while (< (point) (point-max))
-             (let ((bmrk (bookmark-bmenu-bookmark)))
-               (push bmrk bookmark-bmenu-hidden-bookmarks)
-               (let ((start (line-end-position)))
-                 (move-to-column bookmark-bmenu-file-column t)
-                 ;; Strip off `mouse-face' from the white spaces region.
-                 (if (display-mouse-p)
-                     (remove-text-properties start (point)
-                                             '(mouse-face nil help-echo nil))))
-               (delete-region (point) (progn (end-of-line) (point)))
-               (insert "  ")
-               ;; Pass the NO-HISTORY arg:
-               (bookmark-insert-location bmrk t)
-               (forward-line 1)))))))))
-
-
-(defun bookmark-bmenu-hide-filenames (&optional force)
-  "In an interactive bookmark list, hide the filenames of the bookmarks.
-Non-nil FORCE forces a redisplay showing the filenames.  FORCE is used
-mainly for debugging, and should not be necessary in normal use."
-  (when (and (not force) bookmark-bmenu-toggle-filenames)
-    ;; nothing to hide if above is nil
-    (with-buffer-modified-unmodified
-     (save-excursion
-       (goto-char (point-min))
-       (if (not bookmark-bmenu-use-header-line)
-          (forward-line bookmark-bmenu-inline-header-height))
-       (setq bookmark-bmenu-hidden-bookmarks
-             (nreverse bookmark-bmenu-hidden-bookmarks))
-       (let ((inhibit-read-only t))
-         (while bookmark-bmenu-hidden-bookmarks
-           (move-to-column bookmark-bmenu-marks-width t)
-           (bookmark-kill-line)
-           (let ((name  (pop bookmark-bmenu-hidden-bookmarks))
-                 (start (point)))
-             (insert name)
-             (put-text-property start (point) 'bookmark-name-prop name)
-             (if (display-mouse-p)
-                 (add-text-properties
-                  start (point)
-                  '(font-lock-face bookmark-menu-bookmark
-                   mouse-face highlight
-                   follow-link t help-echo
-                    "mouse-2: go to this bookmark in other window"))))
-           (forward-line 1)))))))
+  (bookmark-bmenu-surreptitiously-rebuild-list))
+
+
+(defun bookmark-bmenu-show-filenames (&optional _)
+  "In an interactive bookmark list, show filenames along with bookmarks."
+  (setq bookmark-bmenu-toggle-filenames t)
+  (bookmark-bmenu-surreptitiously-rebuild-list))
+
+
+(defun bookmark-bmenu-hide-filenames (&optional _)
+  "In an interactive bookmark list, hide the filenames of the bookmarks."
+  (setq bookmark-bmenu-toggle-filenames nil)
+  (bookmark-bmenu-surreptitiously-rebuild-list))
 
 
 (defun bookmark-bmenu-ensure-position ()
   "If point is not on a bookmark line, move it to one.
-If before the first bookmark line, move to the first; if after the
-last full line, move to the last full line.  The return value is undefined."
-  (cond ((and (not bookmark-bmenu-use-header-line)
-             (< (count-lines (point-min) (point))
-                bookmark-bmenu-inline-header-height))
-         (goto-char (point-min))
-         (forward-line bookmark-bmenu-inline-header-height))
-        ((and (bolp) (eobp))
+If after the last full line, move to the last full line.  The
+return value is undefined."
+  (cond ((and (bolp) (eobp))
          (beginning-of-line 0))))
 
 
 (defun bookmark-bmenu-bookmark ()
   "Return the bookmark for this line in an interactive bookmark list buffer."
   (bookmark-bmenu-ensure-position)
-  (save-excursion
-    (beginning-of-line)
-    (forward-char bookmark-bmenu-marks-width)
-    (get-text-property (point) 'bookmark-name-prop)))
+  (let* ((id (tabulated-list-get-id))
+         (entry (and id (assoc id tabulated-list-entries))))
+    (if entry
+        (caar entry)
+      "")))
 
 
 (defun bookmark-show-annotation (bookmark-name-or-record)
@@ -1954,14 +1892,8 @@ If the annotation does not exist, do nothing."
 (defun bookmark-bmenu-mark ()
   "Mark bookmark on this line to be displayed by 
\\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-select]."
   (interactive)
-  (beginning-of-line)
   (bookmark-bmenu-ensure-position)
-  (with-buffer-modified-unmodified
-   (let ((inhibit-read-only t))
-     (delete-char 1)
-     (insert ?>)
-     (forward-line 1)
-     (bookmark-bmenu-ensure-position))))
+  (tabulated-list-put-tag ">" t))
 
 
 (defun bookmark-bmenu-mark-all ()
@@ -1970,12 +1902,8 @@ If the annotation does not exist, do nothing."
   (save-excursion
     (goto-char (point-min))
     (bookmark-bmenu-ensure-position)
-    (with-buffer-modified-unmodified
-     (let ((inhibit-read-only t))
-       (while (not (eobp))
-         (delete-char 1)
-         (insert ?>)
-         (forward-line 1))))))
+    (while (not (eobp))
+      (tabulated-list-put-tag ">" t))))
 
 
 (defun bookmark-bmenu-select ()
@@ -2126,17 +2054,12 @@ bookmark menu visible."
   "Cancel all requested operations on bookmark on this line and move down.
 Optional BACKUP means move up."
   (interactive "P")
-  (beginning-of-line)
+  ;; any flags to reset according to circumstances?  How about a
+  ;; flag indicating whether this bookmark is being visited?
+  ;; well, we don't have this now, so maybe later.
   (bookmark-bmenu-ensure-position)
-  (with-buffer-modified-unmodified
-   (let ((inhibit-read-only t))
-     (delete-char 1)
-     ;; any flags to reset according to circumstances?  How about a
-     ;; flag indicating whether this bookmark is being visited?
-     ;; well, we don't have this now, so maybe later.
-     (insert " "))
-   (forward-line (if backup -1 1))
-   (bookmark-bmenu-ensure-position)))
+  (tabulated-list-put-tag " ")
+  (forward-line (if backup -1 1)))
 
 
 (defun bookmark-bmenu-backup-unmark ()
@@ -2155,26 +2078,16 @@ Optional BACKUP means move up."
   (save-excursion
     (goto-char (point-min))
     (bookmark-bmenu-ensure-position)
-    (with-buffer-modified-unmodified
-     (let ((inhibit-read-only t))
-       (while (not (eobp))
-         (delete-char 1)
-         (insert " ")
-         (forward-line 1))))))
+    (while (not (eobp))
+      (tabulated-list-put-tag " " t))))
 
 
 (defun bookmark-bmenu-delete ()
   "Mark bookmark on this line to be deleted.
 To carry out the deletions that you've marked, use 
\\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-execute-deletions]."
   (interactive)
-  (beginning-of-line)
   (bookmark-bmenu-ensure-position)
-  (with-buffer-modified-unmodified
-   (let ((inhibit-read-only t))
-     (delete-char 1)
-     (insert ?D)
-     (forward-line 1)
-     (bookmark-bmenu-ensure-position))))
+  (tabulated-list-put-tag "D" t))
 
 
 (defun bookmark-bmenu-delete-backwards ()
@@ -2182,10 +2095,7 @@ To carry out the deletions that you've marked, use 
\\<bookmark-bmenu-mode-map>\\
 To carry out the deletions that you've marked, use 
\\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-execute-deletions]."
   (interactive)
   (bookmark-bmenu-delete)
-  (forward-line -2)
-  (bookmark-bmenu-ensure-position)
-  (forward-line 1)
-  (bookmark-bmenu-ensure-position))
+  (forward-line -2))
 
 
 (defun bookmark-bmenu-delete-all ()
@@ -2196,12 +2106,8 @@ To carry out the deletions that you've marked, use 
\\<bookmark-bmenu-mode-map>\\
   (save-excursion
     (goto-char (point-min))
     (bookmark-bmenu-ensure-position)
-    (with-buffer-modified-unmodified
-     (let ((inhibit-read-only t))
-       (while (not (eobp))
-         (delete-char 1)
-         (insert ?D)
-         (forward-line 1))))))
+    (while (not (eobp))
+      (tabulated-list-put-tag "D" t))))
 
 
 (defun bookmark-bmenu-execute-deletions ()
@@ -2217,8 +2123,6 @@ To carry out the deletions that you've marked, use 
\\<bookmark-bmenu-mode-map>\\
                        (progn (end-of-line) (point))))))
         (o-col     (current-column)))
     (goto-char (point-min))
-    (unless bookmark-bmenu-use-header-line
-      (forward-line 1))
     (while (re-search-forward "^D" (point-max) t)
       (bookmark-delete (bookmark-bmenu-bookmark) t)) ; pass BATCH arg
     (bookmark-bmenu-list)
diff --git a/lisp/calc/calc-ext.el b/lisp/calc/calc-ext.el
index c48d159..23248ce 100644
--- a/lisp/calc/calc-ext.el
+++ b/lisp/calc/calc-ext.el
@@ -3458,6 +3458,8 @@ A command spec is a command name symbol, a keyboard macro 
string, a
 list containing a numeric entry string, or nil.
 A key may contain additional specs for Inverse, Hyperbolic, and Inv+Hyp.")
 
+(make-obsolete-variable 'calc-ext-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 (run-hooks 'calc-ext-load-hook)
 
 (provide 'calc-ext)
diff --git a/lisp/calendar/time-date.el b/lisp/calendar/time-date.el
index 638d8c1..f60c9c2 100644
--- a/lisp/calendar/time-date.el
+++ b/lisp/calendar/time-date.el
@@ -1,4 +1,4 @@
-;;; time-date.el --- Date and time handling functions
+;;; time-date.el --- Date and time handling functions  -*- lexical-binding: t 
-*-
 
 ;; Copyright (C) 1998-2020 Free Software Foundation, Inc.
 
diff --git a/lisp/calendar/timeclock.el b/lisp/calendar/timeclock.el
index 18ca05a..a26da26 100644
--- a/lisp/calendar/timeclock.el
+++ b/lisp/calendar/timeclock.el
@@ -4,7 +4,7 @@
 
 ;; Author: John Wiegley <johnw@gnu.org>
 ;; Created: 25 Mar 1999
-;; Version: 2.6.1
+;; Old-Version: 2.6.1
 ;; Keywords: calendar data
 
 ;; This file is part of GNU Emacs.
diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el
index 510c6e3..85c197b 100644
--- a/lisp/cus-edit.el
+++ b/lisp/cus-edit.el
@@ -2789,7 +2789,9 @@ Possible return values are `standard', `saved', `set', 
`themed',
                   (and (equal value (eval (car tmp)))
                        (equal comment temp))
                 (error nil))
-              'set
+               (if (equal value (eval (car (get symbol 'standard-value))))
+                   'standard
+                'set)
             'changed))
          ((progn (setq tmp (get symbol 'theme-value))
                  (setq temp (get symbol 'saved-variable-comment))
@@ -2859,6 +2861,18 @@ otherwise."
 (defun custom-variable-standard-value (widget)
   (get (widget-value widget) 'standard-value))
 
+(defun custom-variable-current-value (widget)
+  "Return the current value of the variable edited by WIDGET.
+
+WIDGET should be a custom-variable widget."
+  (let* ((symbol (widget-value widget))
+         (get (or (get symbol 'custom-get) 'default-value))
+         (type (custom-variable-type symbol))
+         (conv (widget-convert type)))
+    (if (default-boundp symbol)
+        (funcall get symbol)
+      (widget-get conv :value))))
+
 (defvar custom-variable-menu nil
   "If non-nil, an alist of actions for the `custom-variable' widget.
 
@@ -2989,10 +3003,12 @@ Optional EVENT is the location for the menu."
             (setq comment nil)
             ;; Make the comment invisible by hand if it's empty
             (custom-comment-hide comment-widget))
-          (custom-variable-backup-value widget)
+           (setq val (widget-value child))
+           (unless (equal (eval val) (custom-variable-current-value widget))
+            (custom-variable-backup-value widget))
           (custom-push-theme 'theme-value symbol 'user
-                             'set (custom-quote (widget-value child)))
-          (funcall set symbol (eval (setq val (widget-value child))))
+                              'set (custom-quote val))
+          (funcall set symbol (eval val))
           (put symbol 'customized-value (list val))
           (put symbol 'variable-comment comment)
           (put symbol 'customized-variable-comment comment))
@@ -3001,10 +3017,12 @@ Optional EVENT is the location for the menu."
             (setq comment nil)
             ;; Make the comment invisible by hand if it's empty
             (custom-comment-hide comment-widget))
-          (custom-variable-backup-value widget)
+           (setq val (widget-value child))
+           (unless (equal val (custom-variable-current-value widget))
+            (custom-variable-backup-value widget))
           (custom-push-theme 'theme-value symbol 'user
-                             'set (custom-quote (widget-value child)))
-          (funcall set symbol (setq val (widget-value child)))
+                             'set (custom-quote val))
+          (funcall set symbol val)
           (put symbol 'customized-value (list (custom-quote val)))
           (put symbol 'variable-comment comment)
           (put symbol 'customized-variable-comment comment)))
@@ -3073,17 +3091,23 @@ before this operation becomes the backup value."
   (let* ((symbol (widget-value widget))
         (saved-value (get symbol 'saved-value))
         (comment (get symbol 'saved-variable-comment))
+         (old-value (custom-variable-current-value widget))
          value)
-    (custom-variable-backup-value widget)
     (if (not (or saved-value comment))
-        ;; If there is no saved value, remove the setting.
-        (custom-push-theme 'theme-value symbol 'user 'reset)
+        (progn
+          (setq value (car (get symbol 'standard-value)))
+          ;; If there is no saved value, remove the setting.
+          (custom-push-theme 'theme-value symbol 'user 'reset)
+          ;; And reset this property too.
+          (put symbol 'variable-comment nil))
       (setq value (car-safe saved-value))
       (custom-push-theme 'theme-value symbol 'user 'set value)
       (put symbol 'variable-comment comment))
+    (unless (equal (eval value) old-value)
+      (custom-variable-backup-value widget))
     (ignore-errors
       (funcall (or (get symbol 'custom-set) #'set-default) symbol
-               (eval (or value (car (get symbol 'standard-value))))))
+               (eval value)))
     (put symbol 'customized-value nil)
     (put symbol 'customized-variable-comment nil)
     (widget-put widget :custom-state 'unknown)
@@ -3096,7 +3120,9 @@ If `custom-reset-standard-variables-list' is nil, save, 
reset and
 redraw the widget immediately."
   (let* ((symbol (widget-value widget)))
     (if (get symbol 'standard-value)
-       (custom-variable-backup-value widget)
+       (unless (equal (custom-variable-current-value widget)
+                       (eval (car (get symbol 'standard-value))))
+          (custom-variable-backup-value widget))
       (user-error "No standard setting known for %S" symbol))
     (put symbol 'variable-comment nil)
     (put symbol 'customized-value nil)
@@ -3133,13 +3159,8 @@ becomes the backup value, so you can get it again."
 (defun custom-variable-backup-value (widget)
   "Back up the current value for WIDGET's variable.
 The backup value is kept in the car of the `backup-value' property."
-  (let* ((symbol (widget-value widget))
-        (get (or (get symbol 'custom-get) 'default-value))
-        (type (custom-variable-type symbol))
-        (conv (widget-convert type))
-        (value (if (default-boundp symbol)
-                   (funcall get symbol)
-                 (widget-get conv :value))))
+  (let ((symbol (widget-value widget))
+       (value (custom-variable-current-value widget)))
     (put symbol 'backup-value (list value))))
 
 (defun custom-variable-reset-backup (widget)
diff --git a/lisp/delim-col.el b/lisp/delim-col.el
index 9d52027..1d4358d 100644
--- a/lisp/delim-col.el
+++ b/lisp/delim-col.el
@@ -3,7 +3,7 @@
 ;; Copyright (C) 1999-2020 Free Software Foundation, Inc.
 
 ;; Author: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
-;; Version: 2.1
+;; Old-Version: 2.1
 ;; Keywords: convenience text
 ;; X-URL: https://www.emacswiki.org/emacs/ViniciusJoseLatorre
 
diff --git a/lisp/edmacro.el b/lisp/edmacro.el
index 71474c0..1d9b472 100644
--- a/lisp/edmacro.el
+++ b/lisp/edmacro.el
@@ -3,7 +3,6 @@
 ;; Copyright (C) 1993-1994, 2001-2020 Free Software Foundation, Inc.
 
 ;; Author: Dave Gillespie <daveg@synaptics.com>
-;; Version: 2.01
 ;; Keywords: abbrev
 
 ;; This file is part of GNU Emacs.
diff --git a/lisp/emacs-lisp/bindat.el b/lisp/emacs-lisp/bindat.el
index d168c25..95581c4 100644
--- a/lisp/emacs-lisp/bindat.el
+++ b/lisp/emacs-lisp/bindat.el
@@ -1,4 +1,4 @@
-;;; bindat.el --- binary data structure packing and unpacking.
+;;; bindat.el --- binary data structure packing and unpacking.  -*- 
lexical-binding: t -*-
 
 ;; Copyright (C) 2002-2020 Free Software Foundation, Inc.
 
@@ -193,8 +193,8 @@
 ;; Helper functions for structure unpacking.
 ;; Relies on dynamic binding of BINDAT-RAW and BINDAT-IDX
 
-(defvar bindat-raw)
-(defvar bindat-idx)
+(defvar bindat-raw nil)
+(defvar bindat-idx nil)
 
 (defun bindat--unpack-u8 ()
   (prog1
@@ -276,7 +276,7 @@
    (t nil)))
 
 (defun bindat--unpack-group (spec)
-  (let (struct last)
+  (let (struct)
     (while spec
       (let* ((item (car spec))
             (field (car item))
@@ -298,7 +298,7 @@
                  type field
                  field nil))
        (if (and (consp len) (not (eq type 'eval)))
-           (setq len (apply 'bindat-get-field struct len)))
+            (setq len (apply #'bindat-get-field struct len)))
        (if (not len)
            (setq len 1))
        (cond
@@ -330,21 +330,21 @@
                  (setq data (bindat--unpack-group (cdr case))
                        cases nil)))))
         (t
-         (setq data (bindat--unpack-item type len vectype)
-               last data)))
+          (setq data (bindat--unpack-item type len vectype))))
        (if data
            (if field
                (setq struct (cons (cons field data) struct))
              (setq struct (append data struct))))))
     struct))
 
-(defun bindat-unpack (spec bindat-raw &optional bindat-idx)
-  "Return structured data according to SPEC for binary data in BINDAT-RAW.
-BINDAT-RAW is a unibyte string or vector.
-Optional third arg BINDAT-IDX specifies the starting offset in BINDAT-RAW."
-  (when (multibyte-string-p bindat-raw)
+(defun bindat-unpack (spec raw &optional idx)
+  "Return structured data according to SPEC for binary data in RAW.
+RAW is a unibyte string or vector.
+Optional third arg IDX specifies the starting offset in RAW."
+  (when (multibyte-string-p raw)
     (error "String is multibyte"))
-  (unless bindat-idx (setq bindat-idx 0))
+  (setq bindat-raw raw)
+  (setq bindat-idx (or idx 0))
   (bindat--unpack-group spec))
 
 (defun bindat-get-field (struct &rest field)
@@ -373,74 +373,70 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
     (ip . 4)))
 
 (defun bindat--length-group (struct spec)
-  (let (last)
-    (while spec
-      (let* ((item (car spec))
-            (field (car item))
-            (type (nth 1 item))
-            (len (nth 2 item))
-            (vectype (and (eq type 'vec) (nth 3 item)))
-            (tail 3))
-       (setq spec (cdr spec))
-       (if (and (consp field) (eq (car field) 'eval))
-           (setq field (eval (car (cdr field)))))
-       (if (and type (consp type) (eq (car type) 'eval))
-           (setq type (eval (car (cdr type)))))
-       (if (and len (consp len) (eq (car len) 'eval))
-           (setq len (eval (car (cdr len)))))
-       (if (memq field '(eval fill align struct union))
-           (setq tail 2
-                 len type
-                 type field
-                 field nil))
-       (if (and (consp len) (not (eq type 'eval)))
-           (setq len (apply 'bindat-get-field struct len)))
-       (if (not len)
-           (setq len 1))
-       (while (eq type 'vec)
-         (let ((vlen 1))
-           (if (consp vectype)
-               (setq len (* len (nth 1 vectype))
-                     type (nth 2 vectype))
-             (setq type (or vectype 'u8)
-                   vectype nil))))
-       (cond
-        ((eq type 'eval)
-         (if field
-             (setq struct (cons (cons field (eval len)) struct))
-           (eval len)))
-        ((eq type 'fill)
-         (setq bindat-idx (+ bindat-idx len)))
-        ((eq type 'align)
-         (while (/= (% bindat-idx len) 0)
-           (setq bindat-idx (1+ bindat-idx))))
-        ((eq type 'struct)
-         (bindat--length-group
-          (if field (bindat-get-field struct field) struct) (eval len)))
-        ((eq type 'repeat)
-         (let ((index 0) (count len))
-           (while (< index count)
-             (bindat--length-group
-               (nth index (bindat-get-field struct field))
-               (nthcdr tail item))
-             (setq index (1+ index)))))
-        ((eq type 'union)
-         (let ((tag len) (cases (nthcdr tail item)) case cc)
-           (while cases
-             (setq case (car cases)
-                   cases (cdr cases)
-                   cc (car case))
-             (if (or (equal cc tag) (equal cc t)
-                     (and (consp cc) (eval cc)))
-                 (progn
-                   (bindat--length-group struct (cdr case))
-                   (setq cases nil))))))
-        (t
-         (if (setq type (assq type bindat--fixed-length-alist))
-             (setq len (* len (cdr type))))
-         (if field
-             (setq last (bindat-get-field struct field)))
-         (setq bindat-idx (+ bindat-idx len))))))))
+  (while spec
+    (let* ((item (car spec))
+           (field (car item))
+           (type (nth 1 item))
+           (len (nth 2 item))
+           (vectype (and (eq type 'vec) (nth 3 item)))
+           (tail 3))
+      (setq spec (cdr spec))
+      (if (and (consp field) (eq (car field) 'eval))
+          (setq field (eval (car (cdr field)))))
+      (if (and type (consp type) (eq (car type) 'eval))
+          (setq type (eval (car (cdr type)))))
+      (if (and len (consp len) (eq (car len) 'eval))
+          (setq len (eval (car (cdr len)))))
+      (if (memq field '(eval fill align struct union))
+          (setq tail 2
+                len type
+                type field
+                field nil))
+      (if (and (consp len) (not (eq type 'eval)))
+          (setq len (apply #'bindat-get-field struct len)))
+      (if (not len)
+          (setq len 1))
+      (while (eq type 'vec)
+        (if (consp vectype)
+            (setq len (* len (nth 1 vectype))
+                  type (nth 2 vectype))
+          (setq type (or vectype 'u8)
+                vectype nil)))
+      (cond
+       ((eq type 'eval)
+        (if field
+            (setq struct (cons (cons field (eval len)) struct))
+          (eval len)))
+       ((eq type 'fill)
+        (setq bindat-idx (+ bindat-idx len)))
+       ((eq type 'align)
+        (while (/= (% bindat-idx len) 0)
+          (setq bindat-idx (1+ bindat-idx))))
+       ((eq type 'struct)
+        (bindat--length-group
+         (if field (bindat-get-field struct field) struct) (eval len)))
+       ((eq type 'repeat)
+        (let ((index 0) (count len))
+          (while (< index count)
+            (bindat--length-group
+             (nth index (bindat-get-field struct field))
+             (nthcdr tail item))
+            (setq index (1+ index)))))
+       ((eq type 'union)
+        (let ((tag len) (cases (nthcdr tail item)) case cc)
+          (while cases
+            (setq case (car cases)
+                  cases (cdr cases)
+                  cc (car case))
+            (if (or (equal cc tag) (equal cc t)
+                    (and (consp cc) (eval cc)))
+                (progn
+                  (bindat--length-group struct (cdr case))
+                  (setq cases nil))))))
+       (t
+        (if (setq type (assq type bindat--fixed-length-alist))
+            (setq len (* len (cdr type))))
+        (setq bindat-idx (+ bindat-idx len)))))))
 
 (defun bindat-length (spec struct)
   "Calculate bindat-raw length for STRUCT according to bindat SPEC."
@@ -557,7 +553,7 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
                  type field
                  field nil))
        (if (and (consp len) (not (eq type 'eval)))
-           (setq len (apply 'bindat-get-field struct len)))
+            (setq len (apply #'bindat-get-field struct len)))
        (if (not len)
            (setq len 1))
        (cond
@@ -596,17 +592,17 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
          (bindat--pack-item last type len vectype)
          ))))))
 
-(defun bindat-pack (spec struct &optional bindat-raw bindat-idx)
+(defun bindat-pack (spec struct &optional raw idx)
   "Return binary data packed according to SPEC for structured data STRUCT.
-Optional third arg BINDAT-RAW is a pre-allocated unibyte string or vector to
-pack into.
-Optional fourth arg BINDAT-IDX is the starting offset into BINDAT-RAW."
-  (when (multibyte-string-p bindat-raw)
+Optional third arg RAW is a pre-allocated unibyte string or
+vector to pack into.
+Optional fourth arg IDX is the starting offset into BINDAT-RAW."
+  (when (multibyte-string-p raw)
     (error "Pre-allocated string is multibyte"))
-  (let ((no-return bindat-raw))
-    (unless bindat-idx (setq bindat-idx 0))
-    (unless bindat-raw
-      (setq bindat-raw (make-string (+ bindat-idx (bindat-length spec struct)) 
0)))
+  (let ((no-return raw))
+    (setq bindat-idx (or idx 0))
+    (setq bindat-raw (or raw
+                   (make-string (+ bindat-idx (bindat-length spec struct)) 0)))
     (bindat--pack-group struct spec)
     (if no-return nil bindat-raw)))
 
@@ -624,7 +620,7 @@ only that many elements from VECT."
     (while (> i 0)
       (setq i (1- i)
            s (cons (format (if (= i 0) fmt fmt2) (aref vect i)) s)))
-    (apply 'concat s)))
+    (apply #'concat s)))
 
 (defun bindat-vector-to-dec (vect &optional sep)
   "Format vector VECT in decimal format separated by dots.
diff --git a/lisp/emacs-lisp/byte-run.el b/lisp/emacs-lisp/byte-run.el
index df693ab..042a26a 100644
--- a/lisp/emacs-lisp/byte-run.el
+++ b/lisp/emacs-lisp/byte-run.el
@@ -442,7 +442,16 @@ ACCESS-TYPE if non-nil should specify the kind of access 
that will trigger
 (defmacro define-obsolete-variable-alias (obsolete-name current-name
                                                 &optional when docstring)
   "Make OBSOLETE-NAME a variable alias for CURRENT-NAME and mark it obsolete.
-This uses `defvaralias' and `make-obsolete-variable' (which see).
+
+WHEN should be a string indicating when the variable was first
+made obsolete, for example a date or a release number.
+
+This macro evaluates all its parameters, and both OBSOLETE-NAME
+and CURRENT-NAME should be symbols, so a typical usage would look like:
+
+  (define-obsolete-variable-alias 'foo-thing 'bar-thing \"27.1\")
+
+This macro uses `defvaralias' and `make-obsolete-variable' (which see).
 See the Info node `(elisp)Variable Aliases' for more details.
 
 If CURRENT-NAME is a defcustom or a defvar (more generally, any variable
@@ -456,9 +465,6 @@ dumped with Emacs).  This is so that any user 
customizations are
 applied before the defcustom tries to initialize the
 variable (this is due to the way `defvaralias' works).
 
-WHEN should be a string indicating when the variable was first
-made obsolete, for example a date or a release number.
-
 For the benefit of Customize, if OBSOLETE-NAME has
 any of the following properties, they are copied to
 CURRENT-NAME, if it does not already have them:
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index 1320501..1e2ce8c 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -268,6 +268,13 @@ This option is enabled by default because it reduces Emacs 
memory usage."
 (defconst byte-compile-log-buffer "*Compile-Log*"
   "Name of the byte-compiler's log buffer.")
 
+(defvar byte-compile--known-dynamic-vars nil
+  "Variables known to be declared as dynamic, for warning purposes.
+Each element is (VAR . FILE), indicating that VAR is declared in FILE.")
+
+(defvar byte-compile--seen-defvars nil
+  "All dynamic variable declarations seen so far.")
+
 (defcustom byte-optimize-log nil
   "If non-nil, the byte-compiler will log its optimizations.
 If this is `source', then only source-level optimizations will be logged.
@@ -290,7 +297,7 @@ The information is logged to `byte-compile-log-buffer'."
 (defconst byte-compile-warning-types
   '(redefine callargs free-vars unresolved
             obsolete noruntime cl-functions interactive-only
-            make-local mapcar constants suspicious lexical)
+            make-local mapcar constants suspicious lexical lexical-dynamic)
   "The list of warning types used when `byte-compile-warnings' is t.")
 (defcustom byte-compile-warnings t
   "List of warnings that the byte-compiler should issue (t for all).
@@ -310,6 +317,8 @@ Elements of the list may be:
   interactive-only
              commands that normally shouldn't be called from Lisp code.
   lexical     global/dynamic variables lacking a prefix.
+  lexical-dynamic
+              lexically bound variable declared dynamic elsewhere
   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.
@@ -1887,10 +1896,9 @@ compile FILENAME.  If optional argument ARG is 0, it 
compiles
 the input file even if the `.elc' file does not exist.
 Any other non-nil value of ARG means to ask the user.
 
-If optional argument LOAD is non-nil, loads the file after compiling.
-
 If compilation is needed, this functions returns the result of
 `byte-compile-file'; otherwise it returns `no-byte-compile'."
+  (declare (advertised-calling-convention (filename &optional force arg) 
"28.1"))
   (interactive
    (let ((file buffer-file-name)
         (file-name nil)
@@ -1919,11 +1927,24 @@ If compilation is needed, this functions returns the 
result of
         (progn
           (if (and noninteractive (not byte-compile-verbose))
               (message "Compiling %s..." filename))
-          (byte-compile-file filename load))
+          (byte-compile-file filename)
+          (when load
+            (load (if (file-exists-p dest) dest filename))))
       (when load
        (load (if (file-exists-p dest) dest filename)))
       'no-byte-compile)))
 
+(defun byte-compile--load-dynvars (file)
+  (and file (not (equal file ""))
+       (with-temp-buffer
+         (insert-file-contents file)
+         (goto-char (point-min))
+         (let ((vars nil)
+               var)
+           (while (ignore-errors (setq var (read (current-buffer))))
+             (push var vars))
+           vars))))
+
 (defvar byte-compile-level 0           ; bug#13787
   "Depth of a recursive byte compilation.")
 
@@ -1932,8 +1953,10 @@ If compilation is needed, this functions returns the 
result of
   "Compile a file of Lisp code named FILENAME into a file of byte code.
 The output file's name is generated by passing FILENAME to the
 function `byte-compile-dest-file' (which see).
-With prefix arg (noninteractively: 2nd arg), LOAD the file after compiling.
-The value is non-nil if there were no errors, nil if errors."
+The value is non-nil if there were no errors, nil if errors.
+
+See also `emacs-lisp-byte-compile-and-load'."
+  (declare (advertised-calling-convention (filename) "28.1"))
 ;;  (interactive "fByte compile file: \nP")
   (interactive
    (let ((file buffer-file-name)
@@ -1962,6 +1985,9 @@ The value is non-nil if there were no errors, nil if 
errors."
   (let ((byte-compile-current-file filename)
         (byte-compile-current-group nil)
        (set-auto-coding-for-load t)
+        (byte-compile--seen-defvars nil)
+        (byte-compile--known-dynamic-vars
+         (byte-compile--load-dynvars (getenv "EMACS_DYNVARS_FILE")))
        target-file input-buffer output-buffer
        byte-compile-dest-file)
     (setq target-file (byte-compile-dest-file filename))
@@ -2096,8 +2122,17 @@ The value is non-nil if there were no errors, nil if 
errors."
                                        filename))))
            (save-excursion
              (display-call-tree filename)))
+        (let ((gen-dynvars (getenv "EMACS_GENERATE_DYNVARS")))
+          (when (and gen-dynvars (not (equal gen-dynvars ""))
+                     byte-compile--seen-defvars)
+            (let ((dynvar-file (concat target-file ".dynvars")))
+              (message "Generating %s" dynvar-file)
+              (with-temp-buffer
+                (dolist (var (delete-dups byte-compile--seen-defvars))
+                  (insert (format "%S\n" (cons var filename))))
+               (write-region (point-min) (point-max) dynvar-file)))))
        (if load
-           (load target-file))
+            (load target-file))
        t))))
 
 ;;; compiling a single function
@@ -2490,7 +2525,8 @@ list that represents a doc string reference.
     (setq byte-compile-lexical-variables
           (delq sym byte-compile-lexical-variables))
     (byte-compile-warn "Variable `%S' declared after its first use" sym))
-  (push sym byte-compile-bound-variables))
+  (push sym byte-compile-bound-variables)
+  (push sym byte-compile--seen-defvars))
 
 (defun byte-compile-file-form-defvar (form)
   (let ((sym (nth 1 form)))
@@ -2905,6 +2941,16 @@ If FORM is a lambda or a macro, byte-compile it as a 
function."
               (ash nonrest 8)
               (ash rest 7)))))
 
+(defun byte-compile--warn-lexical-dynamic (var context)
+  (when (byte-compile-warning-enabled-p 'lexical-dynamic var)
+    (byte-compile-warn
+     "`%s' lexically bound in %s here but declared dynamic in: %s"
+     var context
+     (mapconcat #'identity
+                (mapcan (lambda (v) (and (eq var (car v))
+                                         (list (cdr v))))
+                        byte-compile--known-dynamic-vars)
+                ", "))))
 
 (defun byte-compile-lambda (fun &optional add-lambda reserved-csts)
   "Byte-compile a lambda-expression and return a valid function.
@@ -2933,6 +2979,10 @@ for symbols generated by the byte compiler itself."
                     (if (cdr body)
                         (setq body (cdr body))))))
         (int (assq 'interactive body)))
+    (when lexical-binding
+      (dolist (var arglistvars)
+        (when (assq var byte-compile--known-dynamic-vars)
+          (byte-compile--warn-lexical-dynamic var 'lambda))))
     ;; Process the interactive spec.
     (when int
       (byte-compile-set-symbol-position 'interactive)
@@ -4460,6 +4510,8 @@ Return non-nil if the TOS value was popped."
       ;; VAR is a simple stack-allocated lexical variable.
       (progn (push (assq var init-lexenv)
                    byte-compile--lexical-environment)
+             (when (assq var byte-compile--known-dynamic-vars)
+               (byte-compile--warn-lexical-dynamic var 'let))
              nil)
     ;; VAR should be dynamically bound.
     (while (assq var byte-compile--lexical-environment)
@@ -5289,6 +5341,8 @@ and corresponding effects."
                byte-compile-variable-ref))))
   nil)
 
+(make-obsolete-variable 'bytecomp-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 (run-hooks 'bytecomp-load-hook)
 
 ;;; bytecomp.el ends here
diff --git a/lisp/emacs-lisp/chart.el b/lisp/emacs-lisp/chart.el
index 964836a..1777100 100644
--- a/lisp/emacs-lisp/chart.el
+++ b/lisp/emacs-lisp/chart.el
@@ -4,7 +4,7 @@
 ;; Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
-;; Version: 0.2
+;; Old-Version: 0.2
 ;; Keywords: OO, chart, graph
 
 ;; This file is part of GNU Emacs.
diff --git a/lisp/emacs-lisp/cl-extra.el b/lisp/emacs-lisp/cl-extra.el
index 5bf7479..23c784f 100644
--- a/lisp/emacs-lisp/cl-extra.el
+++ b/lisp/emacs-lisp/cl-extra.el
@@ -910,6 +910,8 @@ Outputs to the current buffer."
       (mapc #'cl--describe-class-slot cslots))))
 
 
+(make-obsolete-variable 'cl-extra-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 (run-hooks 'cl-extra-load-hook)
 
 ;; Local variables:
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el
index 86d99a9..6f98e0f 100644
--- a/lisp/emacs-lisp/cl-macs.el
+++ b/lisp/emacs-lisp/cl-macs.el
@@ -3464,6 +3464,8 @@ STRUCT and SLOT-NAME are symbols.  INST is a structure 
instance."
            (nth (cl-struct-slot-offset ,struct-type ,slot-name) ,inst)
          (aref ,inst (cl-struct-slot-offset ,struct-type ,slot-name)))))))
 
+(make-obsolete-variable 'cl-macs-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 (run-hooks 'cl-macs-load-hook)
 
 ;; Local variables:
diff --git a/lisp/emacs-lisp/cl-seq.el b/lisp/emacs-lisp/cl-seq.el
index f90cce9..d34d501 100644
--- a/lisp/emacs-lisp/cl-seq.el
+++ b/lisp/emacs-lisp/cl-seq.el
@@ -1042,6 +1042,8 @@ Atoms are compared by `eql'; cons cells are compared 
recursively.
   (and (not (consp cl-x)) (not (consp cl-y)) (cl--check-match cl-x cl-y)))
 
 
+(make-obsolete-variable 'cl-seq-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 (run-hooks 'cl-seq-load-hook)
 
 ;; Local variables:
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index 56f000b..d58216b 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -2718,6 +2718,7 @@ either a full name or nil, and EMAIL is a valid email 
address."
     (define-key map (kbd "/ s") 'package-menu-filter-by-status)
     (define-key map (kbd "/ v") 'package-menu-filter-by-version)
     (define-key map (kbd "/ m") 'package-menu-filter-marked)
+    (define-key map (kbd "/ u") 'package-menu-filter-upgradable)
     map)
   "Local keymap for `package-menu-mode' buffers.")
 
@@ -3914,6 +3915,15 @@ Unlike other filters, this leaves the marks intact."
              (tabulated-list-put-tag (char-to-string mark) t)))
        (user-error "No packages found")))))
 
+(defun package-menu-filter-upgradable ()
+  "Filter \"*Packages*\" buffer to show only upgradable packages."
+  (interactive)
+  (let ((pkgs (mapcar #'car (package-menu--find-upgrades))))
+    (package-menu--filter-by
+     (lambda (pkg)
+       (memql (package-desc-name pkg) pkgs))
+     "upgradable")))
+
 (defun package-menu-clear-filter ()
   "Clear any filter currently applied to the \"*Packages*\" buffer."
   (interactive)
diff --git a/lisp/emacs-lisp/pcase.el b/lisp/emacs-lisp/pcase.el
index 09c48d0..e603900 100644
--- a/lisp/emacs-lisp/pcase.el
+++ b/lisp/emacs-lisp/pcase.el
@@ -3,7 +3,7 @@
 ;; Copyright (C) 2010-2020 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
-;; Keywords:
+;; Keywords: extensions
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/emacs-lisp/regi.el b/lisp/emacs-lisp/regi.el
index 61af5e5..11b28b7 100644
--- a/lisp/emacs-lisp/regi.el
+++ b/lisp/emacs-lisp/regi.el
@@ -4,7 +4,7 @@
 
 ;; Author: 1993 Barry A. Warsaw, Century Computing, Inc. <bwarsaw@cen.com>
 ;; Created:       24-Feb-1993
-;; Version:       1.8
+;; Old-Version:   1.8
 ;; Last Modified: 1993/06/01 21:33:00
 ;; Keywords:      extensions, matching
 
diff --git a/lisp/emacs-lisp/seq.el b/lisp/emacs-lisp/seq.el
index d60f974..4656277 100644
--- a/lisp/emacs-lisp/seq.el
+++ b/lisp/emacs-lisp/seq.el
@@ -336,9 +336,11 @@ list."
   "Reduce the function FUNCTION across SEQUENCE, starting with INITIAL-VALUE.
 
 Return the result of calling FUNCTION with INITIAL-VALUE and the
-first element of SEQUENCE, then calling FUNCTION with that result and
-the second element of SEQUENCE, then with that result and the third
-element of SEQUENCE, etc.
+first element of SEQUENCE, then calling FUNCTION with that result
+and the second element of SEQUENCE, then with that result and the
+third element of SEQUENCE, etc.  FUNCTION will be called with
+INITIAL-VALUE (and then the accumulated value) as the first
+argument, and the elements from SEQUENCE as the second argument.
 
 If SEQUENCE is empty, return INITIAL-VALUE and FUNCTION is not called."
   (if (seq-empty-p sequence)
@@ -472,6 +474,7 @@ Equality is defined by TESTFN if non-nil or by `equal' if 
nil."
               (seq-reverse sequence1)
               '()))
 
+;;;###autoload
 (cl-defgeneric seq-group-by (function sequence)
   "Apply FUNCTION to each element of SEQUENCE.
 Separate the elements of SEQUENCE into an alist using the results as
diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el
index f6309c7..7ae6d53 100644
--- a/lisp/emacs-lisp/shortdoc.el
+++ b/lisp/emacs-lisp/shortdoc.el
@@ -24,7 +24,6 @@
 
 ;;; Code:
 
-(require 'macroexp)
 (require 'seq)
 (eval-when-compile (require 'cl-lib))
 
@@ -34,18 +33,16 @@
 
 (defface shortdoc-section
   '((((class color) (background dark))
-     (:inherit variable-pitch
-               :background "#303030" :extend t))
+     :inherit variable-pitch :background "#303030" :extend t)
     (((class color) (background light))
-     (:inherit variable-pitch
-               :background "#f0f0f0" :extend t)))
+     :inherit variable-pitch :background "#f0f0f0" :extend t))
   "Face used for a section.")
 
 (defface shortdoc-example
   '((((class color) (background dark))
-     (:background "#202020" :extend t))
+     :background "#202020" :extend t)
     (((class color) (background light))
-     (:background "#e8e8e8" :extend t)))
+     :background "#e8e8e8" :extend t))
   "Face used for examples.")
 
 (defvar shortdoc--groups nil)
diff --git a/lisp/erc/erc-ibuffer.el b/lisp/erc/erc-ibuffer.el
index 7aee770..556a25e 100644
--- a/lisp/erc/erc-ibuffer.el
+++ b/lisp/erc/erc-ibuffer.el
@@ -92,10 +92,14 @@
     " "))
 
 (define-ibuffer-column erc-server-name (:name "Server")
-  (if (and erc-server-process (processp erc-server-process))
-      (with-current-buffer (process-buffer erc-server-process)
-       (or erc-server-announced-name erc-session-server))
-    ""))
+  (or
+   (when (and erc-server-process (processp erc-server-process))
+     (let ((buffer (process-buffer erc-server-process)))
+       (if (buffer-live-p buffer)
+         (with-current-buffer buffer
+           (or erc-server-announced-name erc-session-server))
+         "(closed)")))
+   ""))
 
 (define-ibuffer-column erc-target (:name "Target")
   (if (eq major-mode 'erc-mode)
diff --git a/lisp/ffap.el b/lisp/ffap.el
index ccba291..bf03588 100644
--- a/lisp/ffap.el
+++ b/lisp/ffap.el
@@ -1,4 +1,4 @@
-;;; ffap.el --- find file (or url) at point
+;;; ffap.el --- find file (or url) at point  -*- lexical-binding: t -*-
 
 ;; Copyright (C) 1995-1997, 2000-2020 Free Software Foundation, Inc.
 
@@ -1049,22 +1049,19 @@ out of NAME."
                         "/pub/gnu/emacs/elisp-archive/"))
     (substring name 2))))
 
-(defcustom ffap-rfc-path
-  (concat (ffap-host-to-filename "ftp.rfc-editor.org") "/in-notes/rfc%s.txt")
+(defcustom ffap-rfc-path "https://www.rfc-editor.org/in-notes/rfc%s.txt";
   "A `format' string making a filename for RFC documents.
-This can be an ange-ftp or Tramp remote filename to download, or
-a local filename if you have full set of RFCs locally.  See also
-`ffap-rfc-directories'."
+This can be an URL, an ange-ftp or Tramp remote filename to
+download, or a local filename if you have the full set of RFCs
+locally.  See also `ffap-rfc-directories'."
   :type 'string
-  :version "23.1"
-  :group 'ffap)
+  :version "28.1")
 
 (defcustom ffap-rfc-directories nil
   "A list of directories to look for RFC files.
 If a given RFC isn't in these then `ffap-rfc-path' is offered."
   :type '(repeat directory)
-  :version "23.1"
-  :group 'ffap)
+  :version "23.1")
 
 (defun ffap-rfc (name)
   (let ((num (match-string 1 name)))
@@ -1142,7 +1139,7 @@ Move point and return point if an adjustment was done."
   (unless dir-separator
     (setq dir-separator "/"))
   (let ((opoint (point))
-       point punct end whitespace-p)
+       point punct whitespace-p)
     (when (re-search-backward
           (regexp-quote dir-separator) (line-beginning-position) t)
       ;; Move to the beginning of the match..
@@ -1363,12 +1360,14 @@ Set to nil to disable matching gopher bookmarks.")
 (defun ffap--gopher-var-on-line ()
   "Return (KEY . VALUE) of gopher bookmark on current line."
   (save-excursion
-    (let ((eol (progn (end-of-line) (skip-chars-backward " ") (point)))
-          (bol (progn (beginning-of-line) (point))))
-     (when (re-search-forward ffap-gopher-regexp eol t)
-       (let ((key (match-string 1))
-             (val (buffer-substring-no-properties (match-end 0) eol)))
-         (cons (intern (downcase key)) val))))))
+    (end-of-line)
+    (skip-chars-backward " ")
+    (let ((eol (point)))
+      (beginning-of-line)
+      (when (re-search-forward ffap-gopher-regexp eol t)
+        (let ((key (match-string 1))
+              (val (buffer-substring-no-properties (match-end 0) eol)))
+          (cons (intern (downcase key)) val))))))
 
 (defun ffap-gopher-at-point ()
   "If point is inside a gopher bookmark block, return its URL.
@@ -1383,7 +1382,8 @@ Sets the variable `ffap-string-at-point-region' to the 
bounds of URL, if any."
                          (point)))
              (bookmark (cl-loop for keyval = (ffap--gopher-var-on-line)
                                 while keyval collect keyval
-                                do (forward-line 1))))
+                                do (forward-line 1)
+                                until (eobp))))
         (when bookmark
           (setq ffap-string-at-point-region (list beg (point)))
           (let-alist (nconc bookmark '((type . "1") (port . "70")))
diff --git a/lisp/files.el b/lisp/files.el
index 1d330ce..e72f829 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -2763,8 +2763,8 @@ since only a single case-insensitive search through the 
alist is made."
      ;; The list of archive file extensions should be in sync with
      ;; `auto-coding-alist' with `no-conversion' coding system.
      ("\\.\\(\
-arc\\|zip\\|lzh\\|lha\\|zoo\\|[jew]ar\\|xpi\\|rar\\|cbr\\|7z\\|\
-ARC\\|ZIP\\|LZH\\|LHA\\|ZOO\\|[JEW]AR\\|XPI\\|RAR\\|CBR\\|7Z\\)\\'" . 
archive-mode)
+arc\\|zip\\|lzh\\|lha\\|zoo\\|[jew]ar\\|xpi\\|rar\\|cbr\\|7z\\|squashfs\\|\
+ARC\\|ZIP\\|LZH\\|LHA\\|ZOO\\|[JEW]AR\\|XPI\\|RAR\\|CBR\\|7Z\\|SQUASHFS\\)\\'" 
. archive-mode)
      ("\\.oxt\\'" . archive-mode) ;(Open|Libre)Office extensions.
      ("\\.\\(deb\\|[oi]pk\\)\\'" . archive-mode) ; Debian/Opkg packages.
      ;; Mailer puts message to be edited in
@@ -4306,9 +4306,27 @@ Return the new class name, which is a symbol named DIR."
                   (if (not (and newvars variables))
                       (or newvars variables)
                     (require 'map)
-                    (map-merge-with 'list (lambda (a b) (map-merge 'list a b))
-                                    variables
-                                    newvars))))))
+                    ;; We want to make the variable setting from
+                    ;; newvars (the second .dir-locals file) take
+                    ;; presedence over the old variables, but we also
+                    ;; want to preserve all `eval' elements as is from
+                    ;; both lists.
+                    (map-merge-with
+                     'list
+                     (lambda (a b)
+                       (let ((ag
+                              (seq-group-by
+                               (lambda (e) (eq (car e) 'eval)) a))
+                             (bg
+                              (seq-group-by
+                               (lambda (e) (eq (car e) 'eval)) b)))
+                         (append (map-merge 'list
+                                            (assoc-default nil ag)
+                                            (assoc-default nil bg))
+                                 (assoc-default t ag)
+                                 (assoc-default t bg))))
+                     variables
+                     newvars))))))
       (setq success latest))
     (setq variables (dir-locals--sort-variables variables))
     (dir-locals-set-class-variables class-name variables)
diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el
index 7d89739..150f70e 100644
--- a/lisp/gnus/message.el
+++ b/lisp/gnus/message.el
@@ -8863,6 +8863,8 @@ will then start up Emacs ready to compose mail."
 
 (provide 'message)
 
+(make-obsolete-variable 'message-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 (run-hooks 'message-load-hook)
 
 ;; Local Variables:
diff --git a/lisp/gnus/nnheader.el b/lisp/gnus/nnheader.el
index 67dc379..2952e20 100644
--- a/lisp/gnus/nnheader.el
+++ b/lisp/gnus/nnheader.el
@@ -1067,6 +1067,8 @@ See `find-file-noselect' for the arguments."
       (setq nnheader-last-message-time now)
       (apply 'nnheader-message args))))
 
+(make-obsolete-variable 'nnheader-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 (run-hooks 'nnheader-load-hook)
 
 (provide 'nnheader)
diff --git a/lisp/gnus/nnmail.el b/lisp/gnus/nnmail.el
index b630814..57801d6 100644
--- a/lisp/gnus/nnmail.el
+++ b/lisp/gnus/nnmail.el
@@ -2082,6 +2082,8 @@ Doesn't change point."
              (format "%S" split)
              "\n"))))
 
+(make-obsolete-variable 'nnmail-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 (run-hooks 'nnmail-load-hook)
 
 (provide 'nnmail)
diff --git a/lisp/gnus/smiley.el b/lisp/gnus/smiley.el
index 5504a52..3edae04 100644
--- a/lisp/gnus/smiley.el
+++ b/lisp/gnus/smiley.el
@@ -44,6 +44,7 @@
 ;; cry               ;-(
 ;; dead              X-)
 ;; grin              :-D
+;; halo              O:-)
 
 ;;; Code:
 
@@ -64,7 +65,8 @@
   "Smiley style."
   :type '(choice (const :tag "small, 3 colors" low-color)  ;; 13x14
                 (const :tag "medium, ~10 colors" medium)  ;; 16x16
-                (const :tag "dull, grayscale" grayscale)) ;; 14x14
+                (const :tag "dull, grayscale" grayscale)  ;; 14x14
+                 (const :tag "emoji, full color" emoji))
   :set (lambda (symbol value)
         (set-default symbol value)
         (setq smiley-data-directory (smiley-directory))
@@ -96,6 +98,35 @@ is nil, use `smiley-style'."
   :type 'directory
   :group 'smiley)
 
+(defcustom smiley-emoji-regexp-alist
+  '(("\\(;-)\\)\\W" 1 "😉")
+    ("[^;]\\(;)\\)\\W" 1 "😉")
+    ("\\(:-]\\)\\W" 1 "😬")
+    ("\\(8-)\\)\\W" 1 "🥴")
+    ("\\(:-|\\)\\W" 1 "😐")
+    ("\\(:-[/\\]\\)\\W" 1 "😕")
+    ("\\(:-(\\)\\W" 1 "😠")
+    ("\\(X-)\\)\\W" 1 "😵") ; 💀
+    ("\\(:-{\\)\\W" 1 "😦")
+    ("\\(>:-)\\)\\W" 1 "😈")
+    ("\\(;-(\\)\\W" 1 "😢")
+    ("\\(:-D\\)\\W" 1 "😀")
+    ("\\(O:-)\\)\\W" 1 "😇")
+    ;; "smile" must be come after "evil"
+    ("\\(\\^?:-?)\\)\\W" 1 "🙂"))
+  "A list of regexps to map smilies to emoji.
+The elements are (REGEXP MATCH EMOJI), where MATCH is the submatch in
+regexp to replace with EMOJI."
+  :version "28.1"
+  :type '(repeat (list regexp
+                      (integer :tag "Regexp match number")
+                      (string :tag "Emoji")))
+  :set (lambda (symbol value)
+        (set-default symbol value)
+        (smiley-update-cache))
+  :initialize 'custom-initialize-default
+  :group 'smiley)
+
 ;; The XEmacs version has a baroque, if not rococo, set of these.
 (defcustom smiley-regexp-alist
   '(("\\(;-)\\)\\W" 1 "blink")
@@ -142,23 +173,25 @@ regexp to replace with IMAGE.  IMAGE is the name of an 
image file in
 
 (defun smiley-update-cache ()
   (setq smiley-cached-regexp-alist nil)
-  (dolist (elt (if (symbolp smiley-regexp-alist)
-                  (symbol-value smiley-regexp-alist)
-                smiley-regexp-alist))
-    (let ((types gnus-smiley-file-types)
-         file type)
-      (while (and (not file)
-                 (setq type (pop types)))
-       (unless (file-exists-p
-                (setq file (expand-file-name (concat (nth 2 elt) "." type)
-                                             smiley-data-directory)))
-         (setq file nil)))
-      (when type
-       (let ((image (gnus-create-image file (intern type) nil
-                                       :ascent 'center)))
-         (when image
-           (push (list (car elt) (cadr elt) image)
-                 smiley-cached-regexp-alist)))))))
+  (if (eq smiley-style 'emoji)
+      (setq smiley-cached-regexp-alist smiley-emoji-regexp-alist)
+    (dolist (elt (if (symbolp smiley-regexp-alist)
+                    (symbol-value smiley-regexp-alist)
+                  smiley-regexp-alist))
+      (let ((types gnus-smiley-file-types)
+           file type)
+        (while (and (not file)
+                   (setq type (pop types)))
+         (unless (file-exists-p
+                  (setq file (expand-file-name (concat (nth 2 elt) "." type)
+                                               smiley-data-directory)))
+           (setq file nil)))
+        (when type
+         (let ((image (gnus-create-image file (intern type) nil
+                                         :ascent 'center)))
+           (when image
+             (push (list (car elt) (cadr elt) image)
+                   smiley-cached-regexp-alist))))))))
 
 ;; Not implemented:
 ;; (defvar smiley-mouse-map
@@ -190,8 +223,15 @@ A list of images is returned."
            (when image
              (push image images)
              (gnus-add-wash-type 'smiley)
-             (gnus-add-image 'smiley image)
-             (gnus-put-image image string 'smiley))))
+              (if (symbolp image)
+                  (progn
+                   (gnus-add-image 'smiley image)
+                   (gnus-put-image image string 'smiley))
+               ;; This is a string, but mark the property for
+               ;; deletion if the washing method is switched off.
+                (insert (propertize string
+                                   'display image
+                                   'gnus-image-category 'smiley))))))
        images))))
 
 ;;;###autoload
diff --git a/lisp/help.el b/lisp/help.el
index d7a53f5..c42e4b4 100644
--- a/lisp/help.el
+++ b/lisp/help.el
@@ -973,6 +973,476 @@ is currently activated with completion."
                  minor-modes nil)
          (setq minor-modes (cdr minor-modes)))))
     result))
+
+
+(defun substitute-command-keys (string)
+  "Substitute key descriptions for command names in STRING.
+Each substring of the form \\\\=[COMMAND] is replaced by either a
+keystroke sequence that invokes COMMAND, or \"M-x COMMAND\" if COMMAND
+is not on any keys.
+
+Each substring of the form \\\\={MAPVAR} is replaced by a summary of
+the value of MAPVAR as a keymap.  This summary is similar to the one
+produced by ‘describe-bindings’.  The summary ends in two newlines
+(used by the helper function ‘help-make-xrefs’ to find the end of the
+summary).
+
+Each substring of the form \\\\=<MAPVAR> specifies the use of MAPVAR
+as the keymap for future \\\\=[COMMAND] substrings.
+
+Each grave accent \\=` is replaced by left quote, and each apostrophe \\='
+is replaced by right quote.  Left and right quote characters are
+specified by ‘text-quoting-style’.
+
+\\\\== quotes the following character and is discarded; thus, \\\\==\\\\== 
puts \\\\==
+into the output, \\\\==\\[ puts \\[ into the output, and \\\\==\\=` puts \\=` 
into the
+output.
+
+Return the original STRING if no substitutions are made.
+Otherwise, return a new string (without any text properties)."
+  (when (not (null string))
+    ;; KEYMAP is either nil (which means search all the active
+    ;; keymaps) or a specified local map (which means search just that
+    ;; and the global map).  If non-nil, it might come from
+    ;; overriding-local-map, or from a \\<mapname> construct in STRING
+    ;; itself.
+    (let ((keymap overriding-local-map)
+          (inhibit-modification-hooks t)
+          (orig-buf (current-buffer)))
+      (with-temp-buffer
+        (insert string)
+        (goto-char (point-min))
+        (while (< (point) (point-max))
+          (let ((standard-output (current-buffer))
+                (orig-point (point))
+                end-point active-maps
+                close generate-summary)
+            (cond
+             ;; 1. Handle all sequences starting with "\"
+             ((= (following-char) ?\\)
+              (ignore-errors
+                (forward-char 1))
+              (cond
+               ;; 1A. Ignore \= at end of string.
+               ((and (= (+ (point) 1) (point-max))
+                     (= (following-char) ?=))
+                (forward-char 1))
+               ;; 1B. \= quotes the next character; thus, to put in \[
+               ;;     without its special meaning, use \=\[.
+               ((= (following-char) ?=)
+                (goto-char orig-point)
+                (delete-char 2)
+                (ignore-errors
+                  (forward-char 1)))
+               ;; 1C. \[foo] is replaced with the keybinding.
+               ((and (= (following-char) ?\[)
+                     (save-excursion
+                       (prog1 (search-forward "]" nil t)
+                         (setq end-point (- (point) 2)))))
+                (goto-char orig-point)
+                (delete-char 2)
+                (let* ((fun (intern (buffer-substring (point) (1- end-point))))
+                       (key (with-current-buffer orig-buf
+                              (where-is-internal fun keymap t))))
+                  ;; If this a command remap, we need to follow it.
+                  (when (and (vectorp key)
+                             (> (length key) 1)
+                             (eq (aref key 0) 'remap)
+                             (symbolp (aref key 1)))
+                    (setq fun (aref key 1))
+                    (setq key (with-current-buffer orig-buf
+                                (where-is-internal fun keymap t))))
+                  (if (not key)
+                      ;; Function is not on any key.
+                      (progn (insert "M-x ")
+                             (goto-char (+ end-point 3))
+                             (delete-char 1))
+                    ;; Function is on a key.
+                    (delete-char (- end-point (point)))
+                    (insert (key-description key)))))
+               ;; 1D. \{foo} is replaced with a summary of the keymap
+               ;;            (symbol-value foo).
+               ;;     \<foo> just sets the keymap used for \[cmd].
+               ((and (or (and (= (following-char) ?{)
+                              (setq close "}")
+                              (setq generate-summary t))
+                         (and (= (following-char) ?<)
+                              (setq close ">")))
+                     (or (save-excursion
+                           (prog1 (search-forward close nil t)
+                             (setq end-point (- (point) 2))))))
+                (goto-char orig-point)
+                (delete-char 2)
+                (let* ((name (intern (buffer-substring (point) (1- 
end-point))))
+                       this-keymap)
+                  (delete-char (- end-point (point)))
+                  ;; Get the value of the keymap in TEM, or nil if
+                  ;; undefined. Do this in the user's current buffer
+                  ;; in case it is a local variable.
+                  (with-current-buffer orig-buf
+                    ;; This is for computing the SHADOWS arg for
+                    ;; describe-map-tree.
+                    (setq active-maps (current-active-maps))
+                    (when (boundp name)
+                      (setq this-keymap (and (keymapp (symbol-value name))
+                                             (symbol-value name)))))
+                  (cond
+                   ((null this-keymap)
+                    (insert "\nUses keymap "
+                            (substitute-command-keys "`")
+                            (symbol-name name)
+                            (substitute-command-keys "'")
+                            ", which is not currently defined.\n")
+                    (unless generate-summary
+                      (setq keymap nil)))
+                   ((not generate-summary)
+                    (setq keymap this-keymap))
+                   (t
+                    ;; Get the list of active keymaps that precede this one.
+                    ;; If this one's not active, get nil.
+                    (let ((earlier-maps (cdr (memq this-keymap (reverse 
active-maps)))))
+                      (describe-map-tree this-keymap t (nreverse earlier-maps)
+                                         nil nil t nil nil t))))))))
+             ;; 2. Handle quotes.
+             ((and (eq (get-quoting-style) 'curve)
+                   (or (and (= (following-char) ?\`)
+                            (prog1 t (insert "‘")))
+                       (and (= (following-char) ?')
+                            (prog1 t (insert "’")))))
+              (delete-char 1))
+             ((and (eq (get-quoting-style) 'straight)
+                   (= (following-char) ?\`))
+              (insert "'")
+              (delete-char 1))
+             ;; 3. Nothing to do -- next character.
+             (t (forward-char 1)))))
+        (buffer-string)))))
+
+(defvar help--keymaps-seen nil)
+(defun describe-map-tree (startmap partial shadow prefix title no-menu
+                                   transl always-title mention-shadow)
+  "Insert a description of the key bindings in STARTMAP.
+This is followed by the key bindings of all maps reachable
+through STARTMAP.
+
+If PARTIAL is non-nil, omit certain uninteresting commands
+\(such as `undefined').
+
+If SHADOW is non-nil, it is a list of maps; don't mention keys
+which would be shadowed by any of them.
+
+If PREFIX is non-nil, mention only keys that start with PREFIX.
+
+If TITLE is non-nil, is a string to insert at the beginning.
+TITLE should not end with a colon or a newline; we supply that.
+
+If NOMENU is non-nil, then omit menu-bar commands.
+
+If TRANSL is non-nil, the definitions are actually key
+translations so print strings and vectors differently.
+
+If ALWAYS_TITLE is non-nil, print the title even if there are no
+maps to look through.
+
+If MENTION_SHADOW is non-nil, then when something is shadowed by
+SHADOW, don't omit it; instead, mention it but say it is
+shadowed.
+
+Any inserted text ends in two newlines (used by
+`help-make-xrefs')."
+  (let* ((amaps (accessible-keymaps startmap prefix))
+         (orig-maps (if no-menu
+                        (progn
+                          ;; Delete from MAPS each element that is for
+                          ;; the menu bar.
+                          (let* ((tail amaps)
+                                 result)
+                            (while tail
+                              (let ((elem (car tail)))
+                                (when (not (and (>= (length (car elem)) 1)
+                                                (eq (elt (car elem) 0) 
'menu-bar)))
+                                  (setq result (append result (list elem)))))
+                              (setq tail (cdr tail)))
+                            result))
+                      amaps))
+         (maps orig-maps)
+         (print-title (or maps always-title)))
+    ;; Print title.
+    (when print-title
+      (princ (concat (if title
+                         (concat title
+                                 (if prefix
+                                     (concat " Starting With "
+                                             (key-description prefix)))
+                                 ":\n"))
+                     "key             binding\n"
+                     "---             -------\n")))
+    ;; Describe key bindings.
+    (setq help--keymaps-seen nil)
+    (while (consp maps)
+      (let* ((elt (car maps))
+             (elt-prefix (car elt))
+             (sub-shadows (lookup-key shadow elt-prefix t)))
+        (when (if (natnump sub-shadows)
+                  (prog1 t (setq sub-shadows nil))
+                ;; Describe this map iff elt_prefix is bound to a
+                ;; keymap, since otherwise it completely shadows this
+                ;; map.
+                (or (keymapp sub-shadows)
+                    (null sub-shadows)
+                    (consp sub-shadows)
+                    (not (keymapp (car sub-shadows)))))
+          ;; Maps we have already listed in this loop shadow this map.
+          (let ((tail orig-maps))
+            (while (not (equal tail maps))
+              (when (equal (car (car tail)) elt-prefix)
+                (setq sub-shadows (cons (cdr (car tail)) sub-shadows)))
+              (setq tail (cdr tail))))
+          (describe-map (cdr elt) elt-prefix transl partial
+                        sub-shadows no-menu mention-shadow)))
+      (setq maps (cdr maps)))
+    (when print-title
+      (princ "\n"))))
+
+(defun help--shadow-lookup (keymap key accept-default remap)
+  "Like `lookup-key', but with command remapping.
+Return nil if the key sequence is too long."
+  ;; Converted from shadow_lookup in keymap.c.
+  (let ((value (lookup-key keymap key accept-default)))
+    (cond ((and (fixnump value) (<= 0 value)))
+          ((and value remap (symbolp value))
+           (or (command-remapping value nil keymap)
+               value))
+          (t value))))
+
+(defvar help--previous-description-column 0)
+(defun help--describe-command (definition)
+  ;; Converted from describe_command in keymap.c.
+  ;; If column 16 is no good, go to col 32;
+  ;; but don't push beyond that--go to next line instead.
+  (let* ((column (current-column))
+         (description-column (cond ((> column 30)
+                                    (insert "\n")
+                                    32)
+                                   ((or (> column 14)
+                                        (and (> column 10)
+                                             (= 
help--previous-description-column 32)))
+                                    32)
+                                   (t 16))))
+    (indent-to description-column 1)
+    (setq help--previous-description-column description-column)
+    (cond ((symbolp definition)
+           (insert (symbol-name definition) "\n"))
+          ((or (stringp definition) (vectorp definition))
+           (insert "Keyboard Macro\n"))
+          ((keymapp definition)
+           (insert "Prefix Command\n"))
+          (t (insert "??\n")))))
+
+(defun help--describe-translation (definition)
+  ;; Converted from describe_translation in keymap.c.
+  (indent-to 16 1)
+  (cond ((symbolp definition)
+         (insert (symbol-name definition) "\n"))
+        ((or (stringp definition) (vectorp definition))
+         (insert (key-description definition nil) "\n"))
+        ((keymapp definition)
+         (insert "Prefix Command\n"))
+        (t (insert "??\n"))))
+
+(defun help--describe-map-compare (a b)
+  (let ((a (car a))
+        (b (car b)))
+    (cond ((and (fixnump a) (fixnump b)) (< a b))
+          ;; ((and (not (fixnump a)) (fixnump b)) nil) ; not needed
+          ((and (fixnump a) (not (fixnump b))) t)
+          ((and (symbolp a) (symbolp b))
+           ;; Sort the keystroke names in the "natural" way, with (for
+           ;; instance) "<f2>" coming between "<f1>" and "<f11>".
+           (string-version-lessp (symbol-name a) (symbol-name b)))
+          (t nil))))
+
+(defun describe-map (map prefix transl partial shadow nomenu mention-shadow)
+  "Describe the contents of keymap MAP.
+Assume that this keymap itself is reached by the sequence of
+prefix keys PREFIX (a string or vector).
+
+TRANSL, PARTIAL, SHADOW, NOMENU, MENTION-SHADOW are as in
+`describe-map-tree'."
+  ;; Converted from describe_map in keymap.c.
+  (let* ((suppress (and partial 'suppress-keymap))
+         (map (keymap-canonicalize map))
+         (tail map)
+         (first t)
+         (describer (if transl
+                        #'help--describe-translation
+                      #'help--describe-command))
+         done vect)
+    (while (and (consp tail) (not done))
+      (cond ((or (vectorp (car tail)) (char-table-p (car tail)))
+             (help--describe-vector (car tail) prefix describer partial
+                                shadow map mention-shadow))
+            ((consp (car tail))
+             (let ((event (caar tail))
+                   definition this-shadowed)
+               ;; Ignore bindings whose "prefix" are not really
+               ;; valid events. (We get these in the frames and
+               ;; buffers menu.)
+               (and (or (symbolp event) (fixnump event))
+                    (not (and nomenu (eq event 'menu-bar)))
+                    ;; Don't show undefined commands or suppressed
+                    ;; commands.
+                    (setq definition (keymap--get-keyelt (cdr (car tail)) nil))
+                    (or (not (symbolp definition))
+                        (null (get definition suppress)))
+                    ;; Don't show a command that isn't really
+                    ;; visible because a local definition of the
+                    ;; same key shadows it.
+                    (or (not shadow)
+                        (let ((tem (help--shadow-lookup shadow (vector event) 
t nil)))
+                          (cond ((null tem) t)
+                                ;; If both bindings are keymaps,
+                                ;; this key is a prefix key, so
+                                ;; don't say it is shadowed.
+                                ((and (keymapp definition) (keymapp tem)) t)
+                                ;; Avoid generating duplicate
+                                ;; entries if the shadowed binding
+                                ;; has the same definition.
+                                ((and mention-shadow (not (eq tem definition)))
+                                 (setq this-shadowed t))
+                                (t nil))))
+                    (push (list event definition this-shadowed) vect))))
+            ((eq (car tail) 'keymap)
+             ;; The same keymap might be in the structure twice, if
+             ;; we're using an inherited keymap.  So skip anything
+             ;; we've already encountered.
+             (let ((tem (assq tail help--keymaps-seen)))
+               (if (and (consp tem)
+                        (equal (car tem) prefix))
+                   (setq done t)
+                 (push (cons tail prefix) help--keymaps-seen)))))
+      (setq tail (cdr tail)))
+    ;; If we found some sparse map events, sort them.
+    (let ((vect (sort vect 'help--describe-map-compare)))
+      ;; Now output them in sorted order.
+      (while vect
+        (let* ((elem (car vect))
+               (start (car elem))
+               (definition (cadr elem))
+               (shadowed (caddr elem))
+               (end start))
+          (when first
+            (setq help--previous-description-column 0)
+            (insert "\n")
+            (setq first nil))
+          ;; Find consecutive chars that are identically defined.
+          (when (fixnump start)
+            (while (and (cdr vect)
+                        (let ((this-event (caar vect))
+                              (this-definition (cadar vect))
+                              (this-shadowed (caddar vect))
+                              (next-event (caar (cdr vect)))
+                              (next-definition (cadar (cdr vect)))
+                              (next-shadowed (caddar (cdr vect))))
+                          (and (eq next-event (1+ this-event))
+                               (equal next-definition this-definition)
+                               (eq this-shadowed next-shadowed))))
+              (setq vect (cdr vect))
+              (setq end (caar vect))))
+          ;; Now START .. END is the range to describe next.
+          ;; Insert the string to describe the event START.
+          (insert (key-description (vector start) prefix))
+          (when (not (eq start end))
+            (insert " .. " (key-description (vector end) prefix)))
+          ;; Print a description of the definition of this character.
+          ;; Called function will take care of spacing out far enough
+          ;; for alignment purposes.
+          (if transl
+              (help--describe-translation definition)
+            (help--describe-command definition))
+          ;; Print a description of the definition of this character.
+          ;; elt_describer will take care of spacing out far enough for
+          ;; alignment purposes.
+          (when shadowed
+            (goto-char (max (1- (point)) (point-min)))
+            (insert "\n  (this binding is currently shadowed)")
+            (goto-char (min (1+ (point)) (point-max)))))
+        ;; Next item in list.
+        (setq vect (cdr vect))))))
+
+;;;; This Lisp version is 100 times slower than its C equivalent:
+;;
+;; (defun help--describe-vector
+;;     (vector prefix transl partial shadow entire-map mention-shadow)
+;;   "Insert in the current buffer a description of the contents of VECTOR.
+;;
+;; PREFIX a prefix key which leads to the keymap that this vector is
+;; in.
+;;
+;; If PARTIAL, it means do not mention suppressed commands
+;; (that assumes the vector is in a keymap).
+;;
+;; SHADOW is a list of keymaps that shadow this map.  If it is
+;; non-nil, look up the key in those maps and don't mention it if it
+;; is defined by any of them.
+;;
+;; ENTIRE-MAP is the vector in which this vector appears.
+;; If the definition in effect in the whole map does not match
+;; the one in this vector, we ignore this one."
+;;   ;; Converted from describe_vector in keymap.c.
+;;   (let* ((first t)
+;;          (idx 0))
+;;     (while (< idx (length vector))
+;;       (let* ((val (aref vector idx))
+;;              (definition (keymap--get-keyelt val nil))
+;;              (start-idx idx)
+;;              this-shadowed
+;;              found-range)
+;;         (when (and definition
+;;                    ;; Don't mention suppressed commands.
+;;                    (not (and partial
+;;                              (symbolp definition)
+;;                              (get definition 'suppress-keymap)))
+;;                    ;; If this binding is shadowed by some other map,
+;;                    ;; ignore it.
+;;                    (not (and shadow
+;;                              (help--shadow-lookup shadow (vector start-idx) 
t nil)
+;;                              (if mention-shadow
+;;                                  (prog1 nil (setq this-shadowed t))
+;;                                t)))
+;;                    ;; Ignore this definition if it is shadowed by an earlier
+;;                    ;; one in the same keymap.
+;;                    (not (and entire-map
+;;                              (not (eq (lookup-key entire-map (vector 
start-idx) t)
+;;                                       definition)))))
+;;           (when first
+;;             (insert "\n")
+;;             (setq first nil))
+;;           (when (and prefix (> (length prefix) 0))
+;;             (insert (format "%s" prefix)))
+;;           (insert (key-description (vector start-idx) prefix))
+;;           ;; Find all consecutive characters or rows that have the
+;;           ;; same definition.
+;;           (while (equal (keymap--get-keyelt (aref vector (1+ idx)) nil)
+;;                         definition)
+;;             (setq found-range t)
+;;             (setq idx (1+ idx)))
+;;           ;; If we have a range of more than one character,
+;;           ;; print where the range reaches to.
+;;           (when found-range
+;;             (insert " .. ")
+;;             (when (and prefix (> (length prefix) 0))
+;;               (insert (format "%s" prefix)))
+;;             (insert (key-description (vector idx) prefix)))
+;;           (if transl
+;;               (help--describe-translation definition)
+;;             (help--describe-command definition))
+;;           (when this-shadowed
+;;             (goto-char (1- (point)))
+;;             (insert "  (binding currently shadowed)")
+;;             (goto-char (1+ (point))))))
+;;       (setq idx (1+ idx)))))
+
 
 (declare-function x-display-pixel-height "xfns.c" (&optional terminal))
 (declare-function x-display-pixel-width "xfns.c" (&optional terminal))
diff --git a/lisp/hfy-cmap.el b/lisp/hfy-cmap.el
index 4cff2a4..a3398f6 100644
--- a/lisp/hfy-cmap.el
+++ b/lisp/hfy-cmap.el
@@ -1,4 +1,4 @@
-;;; hfy-cmap.el --- Fallback color name -> rgb mapping for `htmlfontify'
+;;; hfy-cmap.el --- Fallback color name -> rgb mapping for `htmlfontify'  -*- 
lexical-binding:t -*-
 
 ;; Copyright (C) 2002-2003, 2009-2020 Free Software Foundation, Inc.
 
@@ -809,6 +809,22 @@
 (defconst hfy-rgb-regex
   "^\\s-*\\([0-9]+\\)\\s-+\\([0-9]+\\)\\s-+\\([0-9]+\\)\\s-+\\(.+\\)\\s-*$")
 
+(defun hfy-cmap--parse-buffer (buffer)
+  (with-current-buffer buffer
+    (let ((end-of-rgb 0)
+          result)
+      (goto-char (point-min))
+      (htmlfontify-unload-rgb-file)
+      (while (/= end-of-rgb 1)
+        (if (looking-at hfy-rgb-regex)
+            (push (list (match-string 4)
+                        (string-to-number (match-string 1))
+                        (string-to-number (match-string 2))
+                        (string-to-number (match-string 3)))
+                  result))
+        (setq end-of-rgb (forward-line)))
+      result)))
+
 ;;;###autoload
 (defun htmlfontify-load-rgb-file (&optional file)
   "Load an X11 style rgb.txt FILE.
@@ -818,25 +834,14 @@ Loads the variable `hfy-rgb-txt-color-map', which is used 
by
   (interactive
    (list
     (read-file-name "rgb.txt (equivalent) file: " "" nil t (hfy-rgb-file))))
-  (let ((rgb-buffer   nil)
-       (end-of-rgb     0)
-       (rgb-txt      nil))
-    (if (and (setq rgb-txt (or file (hfy-rgb-file)))
-            (file-readable-p rgb-txt))
-       (with-current-buffer
-            (setq rgb-buffer (find-file-noselect rgb-txt 'nowarn))
-          (goto-char (point-min))
-         (htmlfontify-unload-rgb-file)
-         (while (/= end-of-rgb 1)
-           (if (looking-at hfy-rgb-regex)
-               (setq hfy-rgb-txt-color-map
-                     (cons (list (match-string 4)
-                                 (string-to-number (match-string 1))
-                                 (string-to-number (match-string 2))
-                                 (string-to-number (match-string 3)))
-                           hfy-rgb-txt-color-map)) )
-           (setq end-of-rgb (forward-line)))
-         (kill-buffer rgb-buffer)))))
+  (let ((rgb-buffer nil)
+        (rgb-txt (or file (hfy-rgb-file))))
+    (when (and rgb-txt
+               (file-readable-p rgb-txt))
+      (setq rgb-buffer (find-file-noselect rgb-txt 'nowarn))
+      (when-let ((result (hfy-cmap--parse-buffer rgb-buffer)))
+        (setq hfy-rgb-txt-color-map result))
+      (kill-buffer rgb-buffer))))
 
 (defun htmlfontify-unload-rgb-file ()
   "Unload the current color name -> rgb translation map."
diff --git a/lisp/image-file.el b/lisp/image-file.el
index 22366c8..3b4f572 100644
--- a/lisp/image-file.el
+++ b/lisp/image-file.el
@@ -1,4 +1,4 @@
-;;; image-file.el --- support for visiting image files
+;;; image-file.el --- support for visiting image files  -*- lexical-binding:t 
-*-
 ;;
 ;; Copyright (C) 2000-2020 Free Software Foundation, Inc.
 ;;
@@ -90,7 +90,7 @@ the variable is set using \\[customize]."
                       t)
                      "\\'"))))
     (mapconcat
-     'identity
+     #'identity
      (delq nil (list exts-regexp
                     image-file-name-regexps
                     (car (rassq 'imagemagick image-type-file-name-regexps))))
diff --git a/lisp/info.el b/lisp/info.el
index 6dffb39..c3684de 100644
--- a/lisp/info.el
+++ b/lisp/info.el
@@ -67,7 +67,6 @@ Intermediate Info nodes are nodes visited by Info internally 
in the process of
 searching the node to display.  Intermediate nodes are not presented
 to the user."
   :type 'boolean
-  :group 'info
   :version "24.1")
 
 (defvar Info-enable-active-nodes nil
@@ -79,8 +78,7 @@ The Lisp code is executed when the node is selected.")
   '((((class color) (background light)) :foreground "brown" :weight bold 
:slant italic)
     (((class color) (background dark)) :foreground "white" :weight bold :slant 
italic)
     (t :weight bold :slant italic))
-  "Face for Info node names."
-  :group 'info)
+  "Face for Info node names.")
 
 (defface info-title-1
   '((((type tty pc) (class color) (background light))
@@ -88,26 +86,22 @@ The Lisp code is executed when the node is selected.")
     (((type tty pc) (class color) (background dark))
      :foreground "yellow" :weight bold)
     (t :height 1.2 :inherit info-title-2))
-  "Face for info titles at level 1."
-  :group 'info)
+  "Face for info titles at level 1.")
 
 (defface info-title-2
   '((((type tty pc) (class color)) :foreground "lightblue" :weight bold)
     (t :height 1.2 :inherit info-title-3))
-  "Face for info titles at level 2."
-  :group 'info)
+  "Face for info titles at level 2.")
 
 (defface info-title-3
   '((((type tty pc) (class color)) :weight bold)
     (t :height 1.2 :inherit info-title-4))
-  "Face for info titles at level 3."
-  :group 'info)
+  "Face for info titles at level 3.")
 
 (defface info-title-4
   '((((type tty pc) (class color)) :weight bold)
     (t :weight bold :inherit variable-pitch))
-  "Face for info titles at level 4."
-  :group 'info)
+  "Face for info titles at level 4.")
 
 (defface info-menu-header
   '((((type tty pc))
@@ -116,31 +110,26 @@ The Lisp code is executed when the node is selected.")
     (t
      :inherit variable-pitch
      :weight bold))
-  "Face for headers in Info menus."
-  :group 'info)
+  "Face for headers in Info menus.")
 
 (defface info-menu-star
   '((((class color)) :foreground "red1")
     (t :underline t))
-  "Face for every third `*' in an Info menu."
-  :group 'info)
+  "Face for every third `*' in an Info menu.")
 
 (defface info-xref
   '((t :inherit link))
-  "Face for unvisited Info cross-references."
-  :group 'info)
+  "Face for unvisited Info cross-references.")
 
 (defface info-xref-visited
   '((t :inherit (link-visited info-xref)))
   "Face for visited Info cross-references."
-  :version "22.1"
-  :group 'info)
+  :version "22.1")
 
 (defcustom Info-fontify-visited-nodes t
   "Non-nil to fontify references to visited nodes in `info-xref-visited' face."
   :version "22.1"
-  :type 'boolean
-  :group 'info)
+  :type 'boolean)
 
 ;; It's unfortunate that nil means no fontification, as opposed to no limit,
 ;; since that differs from font-lock-maximum-size.
@@ -150,29 +139,24 @@ Set to nil to disable node fontification; set to t for no 
limit."
   :type '(choice (const :tag "No fontification" nil)
                 (const :tag "No size limit" t)
                 (integer :tag "Up to this many characters"))
-  :version "25.1"                      ; 100k -> 400k
-  :group 'info)
+  :version "25.1")             ; 100k -> 400k
 
 (defcustom Info-use-header-line t
   "Non-nil means to put the beginning-of-node links in an Emacs header-line.
 A header-line does not scroll with the rest of the buffer."
-  :type 'boolean
-  :group 'info)
+  :type 'boolean)
 
 (defface info-header-xref
   '((t :inherit info-xref))
-  "Face for Info cross-references in a node header."
-  :group 'info)
+  "Face for Info cross-references in a node header.")
 
 (defface info-header-node
   '((t :inherit info-node))
-  "Face for Info nodes in a node header."
-  :group 'info)
+  "Face for Info nodes in a node header.")
 
 (defface info-index-match
   '((t :inherit match))
   "Face used to highlight matches in an index entry."
-  :group 'info
   :version "24.4")
 
 ;; This is a defcustom largely so that we can get the benefit
@@ -249,8 +233,7 @@ Although this is a customizable variable, that is mainly 
for technical
 reasons.  Normally, you should either set INFOPATH or customize
 `Info-additional-directory-list', rather than changing this variable."
   :initialize 'custom-initialize-delay
-  :type '(repeat directory)
-  :group 'info))
+  :type '(repeat directory)))
 
 (defvar Info-directory-list nil
   "List of directories to search for Info documentation files.
@@ -285,8 +268,7 @@ a version of Emacs without installing it.")
 (defcustom Info-additional-directory-list nil
   "List of additional directories to search for Info documentation files.
 These directories are searched after those in `Info-directory-list'."
-  :type '(repeat directory)
-  :group 'info)
+  :type '(repeat directory))
 
 (defcustom Info-scroll-prefer-subnodes nil
   "If non-nil, \\<Info-mode-map>\\[Info-scroll-up] in a menu visits subnodes.
@@ -300,15 +282,15 @@ Setting this option to nil results in behavior similar to 
the stand-alone
 Info reader program, which visits the first subnode from the menu only
 when you hit the end of the current node."
   :version "22.1"
-  :type 'boolean
-  :group 'info)
+  :type 'boolean)
 
 (defcustom Info-hide-note-references t
   "If non-nil, hide the tag and section reference in *note and * menu items.
-If value is non-nil but not `hide', also replaces the \"*note\" with \"see\".
-If value is non-nil but not t or `hide', the reference section is still shown.
-nil completely disables this feature.  If this is non-nil, you might
-want to set `Info-refill-paragraphs'."
+If the value is t, the default, replace \"*note\" with \"see\".
+If the value is `hide', remove \"*note\" without replacing it with anything.
+If value is non-nil, but not t or `hide', the reference section is still shown.
+nil completely disables this feature, leaving the original \"*note\" visible.
+If this is non-nil, you may wish setting `Info-refill-paragraphs' non-nil."
   :version "22.1"
   :type '(choice (const :tag "No hiding" nil)
                 (const :tag "Replace tag and hide reference" t)
@@ -319,8 +301,7 @@ want to set `Info-refill-paragraphs'."
         (dolist (buffer (buffer-list))
           (with-current-buffer buffer
              (when (derived-mode-p 'Info-mode)
-              (revert-buffer t t)))))
-  :group 'info)
+               (revert-buffer t t))))))
 
 (defcustom Info-refill-paragraphs nil
   "If non-nil, attempt to refill paragraphs with hidden references.
@@ -328,15 +309,13 @@ This refilling may accidentally remove explicit line 
breaks in the Info
 file, so be prepared for a few surprises if you enable this feature.
 This only has an effect if `Info-hide-note-references' is non-nil."
   :version "22.1"
-  :type 'boolean
-  :group 'info)
+  :type 'boolean)
 
 (defcustom Info-breadcrumbs-depth 4
   "Depth of breadcrumbs to display.
 0 means do not display breadcrumbs."
   :version "23.1"
-  :type 'integer
-  :group 'info)
+  :type 'integer)
 
 (defcustom Info-search-whitespace-regexp "\\s-+"
   "If non-nil, regular expression to match a sequence of whitespace chars.
@@ -346,8 +325,7 @@ In the Customization buffer, that is `[' followed by a 
space,
 a tab, a carriage return (control-M), a newline, and `]+'.  Don't
 add any capturing groups into this value; that can change the
 numbering of existing capture groups in unexpected ways."
-  :type 'regexp
-  :group 'info)
+  :type 'regexp)
 
 (defcustom Info-isearch-search t
   "If non-nil, isearch in Info searches through multiple nodes.
@@ -362,8 +340,7 @@ node depending on search direction.
 Setting this option to nil restores the default isearch behavior
 with wrapping around the current Info node."
   :version "22.1"
-  :type 'boolean
-  :group 'info)
+  :type 'boolean)
 
 (defvar Info-isearch-initial-node nil)
 (defvar Info-isearch-initial-history nil)
@@ -374,13 +351,11 @@ with wrapping around the current Info node."
   (unless (and (boundp 'Info-fontify) (null Info-fontify))
     '(turn-on-font-lock))
   "Hook run when activating Info Mode."
-  :type 'hook
-  :group 'info)
+  :type 'hook)
 
 (defcustom Info-selection-hook nil
   "Hook run when an Info node is selected as the current node."
-  :type 'hook
-  :group 'info)
+  :type 'hook)
 
 (defvar-local Info-current-file nil
   "Info file that Info is now looking at, or nil.
@@ -1473,9 +1448,10 @@ is non-nil)."
 
 (defvar Info-streamline-headings
   '(("Emacs" . "Emacs")
-    ("Programming" . "Programming")
+    ("Software development\\|Programming" . "Software development")
     ("Libraries" . "Libraries")
-    ("World Wide Web\\|Net Utilities" . "Net Utilities"))
+    ("Network applications\\|World Wide Web\\|Net Utilities"
+     . "Network applications"))
   "List of elements (RE . NAME) to merge headings matching RE to NAME.")
 
 (defun Info-dir-remove-duplicates ()
diff --git a/lisp/international/iso-ascii.el b/lisp/international/iso-ascii.el
index e86efe5..0df07d6 100644
--- a/lisp/international/iso-ascii.el
+++ b/lisp/international/iso-ascii.el
@@ -1,4 +1,4 @@
-;;; iso-ascii.el --- set up char tables for ISO 8859/1 on ASCII terminals
+;;; iso-ascii.el --- set up char tables for ISO 8859/1 on ASCII terminals  -*- 
lexical-binding: t -*-
 
 ;; Copyright (C) 1987, 1995, 1998, 2001-2020 Free Software Foundation,
 ;; Inc.
@@ -41,8 +41,7 @@
 
 (defcustom iso-ascii-convenient nil
   "Non-nil means `iso-ascii' should aim for convenience, not precision."
-  :type 'boolean
-  :group 'iso-ascii)
+  :type 'boolean)
 
 (defvar iso-ascii-display-table (make-display-table)
   "Display table used for ISO-ASCII mode.")
diff --git a/lisp/international/mule.el b/lisp/international/mule.el
index 607287f..5292abf 100644
--- a/lisp/international/mule.el
+++ b/lisp/international/mule.el
@@ -1711,8 +1711,8 @@ in-place."
   ;; self-extracting exe archives.
   (mapcar (lambda (arg) (cons (purecopy (car arg)) (cdr arg)))
          '(("\\.\\(\
-arc\\|zip\\|lzh\\|lha\\|zoo\\|[jew]ar\\|xpi\\|rar\\|7z\\|\
-ARC\\|ZIP\\|LZH\\|LHA\\|ZOO\\|[JEW]AR\\|XPI\\|RAR\\|7Z\\)\\'"
+arc\\|zip\\|lzh\\|lha\\|zoo\\|[jew]ar\\|xpi\\|rar\\|7z\\|squashfs\\|\
+ARC\\|ZIP\\|LZH\\|LHA\\|ZOO\\|[JEW]AR\\|XPI\\|RAR\\|7Z\\|SQUASHFS\\)\\'"
      . no-conversion-multibyte)
     ("\\.\\(exe\\|EXE\\)\\'" . no-conversion)
     ("\\.\\(sx[dmicw]\\|odt\\|tar\\|t[bg]z\\)\\'" . no-conversion)
diff --git a/lisp/language/misc-lang.el b/lisp/language/misc-lang.el
index e3a24c4..3f45f70 100644
--- a/lisp/language/misc-lang.el
+++ b/lisp/language/misc-lang.el
@@ -141,6 +141,20 @@ thin (i.e. 1-dot width) space."
        (vector "[\u0600-\u074F\u200C\u200D]+"
                0 'arabic-shape-gstring)))
 
+;; The Egyptian Hieroglyph Format Controls were introduced in Unicode
+;; Standard v12.0.  Apparently, they are not yet well supported in
+;; existing fonts, as of late 2020.  But there's no reason for us not
+;; to be ready for when they will be!
+;; The below is needed to support the arrangement of the Egyptian
+;; Hieroglyphs in "quadrats", as directed by the format controls,
+;; which specify how the hieroglyphs should be joined horizontally and
+;; vertically.
+(set-char-table-range
+ composition-function-table
+ '(#x13000 . #x1343F)
+ (list (vector "[\U00013000-\U0001343F]+"
+               0 'compose-gstring-for-graphic)))
+
 (provide 'misc-lang)
 
 ;;; misc-lang.el ends here
diff --git a/lisp/language/utf-8-lang.el b/lisp/language/utf-8-lang.el
index 78fbae3..9e59f61 100644
--- a/lisp/language/utf-8-lang.el
+++ b/lisp/language/utf-8-lang.el
@@ -1,4 +1,4 @@
-;;; utf-8-lang.el --- generic UTF-8 language environment
+;;; utf-8-lang.el --- generic UTF-8 language environment  -*- lexical-binding: 
t -*-
 
 ;; Copyright (C) 2001-2020 Free Software Foundation, Inc.
 
diff --git a/lisp/loadhist.el b/lisp/loadhist.el
index a1ff2f6..8ac575e 100644
--- a/lisp/loadhist.el
+++ b/lisp/loadhist.el
@@ -234,11 +234,10 @@ If the feature is required by any other loaded code, and 
prefix arg FORCE
 is nil, raise an error.
 
 Standard unloading activities include restoring old autoloads for
-functions defined by the library, undoing any additions that the
-library has made to hook variables or to `auto-mode-alist', undoing
-ELP profiling of functions in that library, unproviding any features
-provided by the library, and canceling timers held in variables
-defined by the library.
+functions defined by the library, removing such functions from
+hooks and `auto-mode-alist', undoing their ELP profiling,
+unproviding any features provided by the library, and canceling
+timers held in variables defined by the library.
 
 If a function `FEATURE-unload-function' is defined, this function
 calls it with no arguments, before doing anything else.  That function
@@ -287,22 +286,32 @@ something strange, such as redefining an Emacs function."
        ;; functions which the package might just have installed, and
        ;; there might be other important state, but this tactic
        ;; normally works.
-       (mapatoms
-        (lambda (x)
-          (when (and (boundp x)
-                     (or (and (consp (symbol-value x)) ; Random hooks.
-                              (string-match "-hooks?\\'" (symbol-name x)))
-                         (memq x unload-feature-special-hooks)))       ; Known 
abnormal hooks etc.
-            (dolist (y unload-function-defs-list)
-              (when (and (eq (car-safe y) 'defun)
-                         (not (get (cdr y) 'autoload)))
-                (remove-hook x (cdr y)))))))
-       ;; Remove any feature-symbols from auto-mode-alist as well.
-       (dolist (y unload-function-defs-list)
-         (when (and (eq (car-safe y) 'defun)
-                    (not (get (cdr y) 'autoload)))
-           (setq auto-mode-alist
-                 (rassq-delete-all (cdr y) auto-mode-alist)))))
+        (let ((removables (cl-loop for def in unload-function-defs-list
+                                   when (and (eq (car-safe def) 'defun)
+                                             (not (get (cdr def) 'autoload)))
+                                   collect (cdr def))))
+          (mapatoms
+          (lambda (x)
+            (when (and (boundp x)
+                       (or (and (consp (symbol-value x)) ; Random hooks.
+                                (string-match "-hooks?\\'" (symbol-name x)))
+                            ;; Known abnormal hooks etc.
+                           (memq x unload-feature-special-hooks)))
+              (dolist (func removables)
+                (remove-hook x func)))))
+          (save-current-buffer
+            (dolist (buffer (buffer-list))
+              (pcase-dolist (`(,sym . ,val) (buffer-local-variables buffer))
+                (when (or (and (consp val)
+                               (string-match "-hooks?\\'" (symbol-name sym)))
+                          (memq sym unload-feature-special-hooks))
+                  (set-buffer buffer)
+                  (dolist (func removables)
+                    (remove-hook sym func t))))))
+          ;; Remove any feature-symbols from auto-mode-alist as well.
+          (dolist (func removables)
+            (setq auto-mode-alist
+                  (rassq-delete-all func auto-mode-alist)))))
 
       ;; Change major mode in all buffers using one defined in the feature 
being unloaded.
       (unload--set-major-mode)
diff --git a/lisp/mail/binhex.el b/lisp/mail/binhex.el
index 2c77f88..431c681 100644
--- a/lisp/mail/binhex.el
+++ b/lisp/mail/binhex.el
@@ -29,12 +29,6 @@
 
 ;;; Code:
 
-(eval-and-compile
-  (defalias 'binhex-char-int
-    (if (fboundp 'char-int)
-       'char-int
-      'identity)))
-
 (defgroup binhex nil
   "Decoding of BinHex (binary-to-hexadecimal) data."
   :group 'mail
@@ -150,14 +144,14 @@ input and write the converted data to its standard 
output."
 (defun binhex-string-big-endian (string)
   (let ((ret 0) (i 0) (len (length string)))
     (while (< i len)
-      (setq ret (+ (ash ret 8) (binhex-char-int (aref string i)))
+      (setq ret (+ (ash ret 8) (aref string i))
            i (1+ i)))
     ret))
 
 (defun binhex-string-little-endian (string)
   (let ((ret 0) (i 0) (shift 0) (len (length string)))
     (while (< i len)
-      (setq ret (+ ret (ash (binhex-char-int (aref string i)) shift))
+      (setq ret (+ ret (ash (aref string i) shift))
            i (1+ i)
            shift (+ shift 8)))
     ret))
@@ -167,11 +161,11 @@ input and write the converted data to its standard 
output."
     (let ((pos (point-min)) len)
       (vector
        (prog1
-          (setq len (binhex-char-int (char-after pos)))
+           (setq len (char-after pos))
         (setq pos (1+ pos)))
        (buffer-substring pos (setq pos (+ pos len)))
        (prog1
-          (setq len (binhex-char-int (char-after pos)))
+           (setq len (char-after pos))
         (setq pos (1+ pos)))
        (buffer-substring pos (setq pos (+ pos 4)))
        (buffer-substring pos (setq pos (+ pos 4)))
@@ -323,6 +317,8 @@ If HEADER-ONLY is non-nil only decode header and return 
filename."
       (binhex-decode-region-external start end)
     (binhex-decode-region-internal start end)))
 
+(define-obsolete-function-alias 'binhex-char-int #'identity)
+
 (provide 'binhex)
 
 ;;; binhex.el ends here
diff --git a/lisp/mail/footnote.el b/lisp/mail/footnote.el
index 61f7cbf..67bfbf7 100644
--- a/lisp/mail/footnote.el
+++ b/lisp/mail/footnote.el
@@ -5,7 +5,7 @@
 ;; Author: Steven L Baur <steve@xemacs.org> (1997-2011)
 ;;         Boruch Baum <boruch_baum@gmx.com> (2017-)
 ;; Keywords: mail, news
-;; Version: 0.19
+;; Old-Version: 0.19
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/mail/mail-extr.el b/lisp/mail/mail-extr.el
index bd9aef1..c296f29 100644
--- a/lisp/mail/mail-extr.el
+++ b/lisp/mail/mail-extr.el
@@ -1856,6 +1856,11 @@ place.  It affects how `mail-extract-address-components' 
works."
 ;; https://www.iana.org/cctld/cctld-whois.htm
 ;; Latest change: 2007/11/15
 
+;; FIXME: There are over 1500 top level domains, the vast majority of
+;; which are not in the below list.  Should they be?
+;; https://data.iana.org/TLD/tlds-alpha-by-domain.txt
+;; https://en.wikipedia.org/wiki/List_of_Internet_top-level_domains
+
 (defconst mail-extr-all-top-level-domains
   (let ((ob (make-vector 739 0)))
     (mapc
@@ -2145,6 +2150,80 @@ place.  It affects how `mail-extract-address-components' 
works."
        ("uucp" t               "Unix to Unix CoPy")
        ;; Infrastructure Domains:
        ("arpa" t               "Advanced Research Projects Agency (U.S. DoD)")
+       ;; Geographic Domains:
+       ("abudhabi"        "Abu Dhabi")
+       ("africa"          "Africa")
+       ("alsace"          "Alsace, France")
+       ("amsterdam"       "Amsterdam, The Netherlands")
+       ("arab"            "League of Arab States")
+       ("asia"            "Asia-Pacific region")
+       ("bar"             "Bar, Montenegro")
+       ("barcelona"       "Barcelona, Spain")
+       ("bayern"          "Bavaria, Germany")
+       ("bcn"             "Barcelona, Spain")
+       ("berlin"          "Berlin, Germany")
+       ("boston"          "Boston, Massachusetts")
+       ("brussels"        "Brussels, Belgium")
+       ("budapest"        "Budapest, Hungary")
+       ("bzh"             "Brittany, France")
+       ("capetown"        "Cape Town, South Africa")
+       ("cat"             "Catalonia, Spain")
+       ("cologne"         "Cologne, Germany")
+       ("corsica"         "Corsica, France")
+       ("cymru"           "Wales, United Kingdom")
+       ("doha"            "Doha")
+       ("dubai"           "Dubai")
+       ("durban"          "Durban, South Africa")
+       ("eus"             "Basque, Spain and France")
+       ("frl"             "Friesland, Netherlands")
+       ("gal"             "Galicia, Spain")
+       ("gent"            "Ghent, Belgium")
+       ("hamburg"         "Hamburg, Germany")
+       ("helsinki"        "Helsinki, Finland")
+       ("irish"           "Ireland")
+       ("ist"             "İstanbul, Turkey")
+       ("istanbul"        "İstanbul, Turkey")
+       ("joburg"          "Johannesburg, South Africa")
+       ("kiwi"            "New Zealanders")
+       ("koeln"           "Cologne, Germany")
+       ("krd"             "Kurdistan")
+       ("kyoto"           "Kyoto, Japan")
+       ("lat"             "Latin America")
+       ("london"          "London, United Kingdom")
+       ("madrid"          "Madrid, Spain")
+       ("melbourne"       "Melbourne, Australia")
+       ("miami"           "Miami, Florida")
+       ("nagoya"          "Nagoya, Japan")
+       ("nrw"             "North Rhine-Westphalia, Germany")
+       ("nyc"             "New York City, New York")
+       ("okinawa"         "Okinawa, Japan")
+       ("osaka"           "Osaka, Japan")
+       ("paris"           "Paris, France")
+       ("quebec"          "Québec, Canada")
+       ("rio"             "Rio de Janeiro, Brazil")
+       ("ruhr"            "Ruhr, Germany")
+       ("ryukyu"          "Ryukyu Islands, Japan")
+       ("saarland"        "Saarland, Germany")
+       ("scot"            "Scotland, United Kingdom")
+       ("stockholm"       "Stockholm, Sweden")
+       ("swiss"           "Switzerland")
+       ("sydney"          "Sydney, Australia")
+       ("taipei"          "Taipei, Taiwan")
+       ("tatar"           "Tatars")
+       ("tirol"           "Tyrol, Austria")
+       ("tokyo"           "Tokyo, Japan")
+       ("vegas"           "Las Vegas, Nevada")
+       ("wales"           "Wales, United Kingdom")
+       ("wien"            "Vienna, Austria")
+       ("yokohama"        "Yokohama, Japan")
+       ("zuerich"         "Zurich, Switzerland")
+       ;; Internationalized Geographic Domains:
+       ("xn--1qqw23a"     "Foshan, China")
+       ("xn--xhq521b"     "Guangdong, China")
+       ("xn--80adxhks"    "Moscow, Russia")
+       ("xn--p1acf"       "Russia")
+       ("xn--mgbca7dzdo"  "Abu Dhabi")
+       ("xn--ngbrx"       "Arab")
        ))
     ob))
 
diff --git a/lisp/mail/rfc2231.el b/lisp/mail/rfc2231.el
index add0997..17da60e 100644
--- a/lisp/mail/rfc2231.el
+++ b/lisp/mail/rfc2231.el
@@ -215,23 +215,25 @@ These look like:
  \"\\='en-us\\='This%20is%20%2A%2A%2Afun%2A%2A%2A\",
  \"\\='\\='This%20is%20%2A%2A%2Afun%2A%2A%2A\", or
  \"This is ***fun***\"."
-  (string-match "\\`\\(?:\\([^']+\\)?'\\([^']+\\)?'\\)?\\(.+\\)" string)
-  (let ((coding-system (mm-charset-to-coding-system
-                       (match-string 1 string) nil t))
-       ;;(language (match-string 2 string))
-       (value (match-string 3 string)))
-    (mm-with-unibyte-buffer
-      (insert value)
-      (goto-char (point-min))
-      (while (re-search-forward "%\\([[:xdigit:]][[:xdigit:]]\\)" nil t)
-       (insert
-        (prog1
-            (string-to-number (match-string 1) 16)
-          (delete-region (match-beginning 0) (match-end 0)))))
-      ;; Decode using the charset, if any.
-      (if (memq coding-system '(nil ascii))
-         (buffer-string)
-       (decode-coding-string (buffer-string) coding-system)))))
+  (if (not (string-match "\\`\\(?:\\([^']+\\)?'\\([^']+\\)?'\\)?\\(.+\\)\\'"
+                         string))
+      (error "Unrecognized RFC2231 format: %S" string)
+    (let ((value (match-string 3 string))
+         ;;(language (match-string 2 string))
+         (coding-system (mm-charset-to-coding-system
+                         (match-string 1 string) nil t)))
+      (mm-with-unibyte-buffer
+        (insert value)
+        (goto-char (point-min))
+        (while (re-search-forward "%\\([[:xdigit:]][[:xdigit:]]\\)" nil t)
+         (insert
+          (prog1
+              (string-to-number (match-string 1) 16)
+            (delete-region (match-beginning 0) (match-end 0)))))
+       ;; Decode using the charset, if any.
+       (if (memq coding-system '(nil ascii))
+           (buffer-string)
+         (decode-coding-string (buffer-string) coding-system))))))
 
 (defun rfc2231-encode-string (param value)
   "Return a PARAM=VALUE string encoded according to RFC2231.
diff --git a/lisp/mail/uudecode.el b/lisp/mail/uudecode.el
index 945bff3..bcbd571 100644
--- a/lisp/mail/uudecode.el
+++ b/lisp/mail/uudecode.el
@@ -24,11 +24,6 @@
 
 ;;; Code:
 
-(defalias 'uudecode-char-int
-  (if (fboundp 'char-int)
-      'char-int
-    'identity))
-
 (defgroup uudecode nil
   "Decoding of uuencoded data."
   :group 'mail
@@ -140,7 +135,7 @@ If FILE-NAME is non-nil, save the result to FILE-NAME."
           ((> (skip-chars-forward uudecode-alphabet end) 0)
            (setq lim (point))
            (setq remain
-                 (logand (- (uudecode-char-int (char-after inputpos)) 32)
+                  (logand (- (char-after inputpos) 32)
                          63))
            (setq inputpos (1+ inputpos))
            (if (= remain 0) (setq done t))
@@ -148,7 +143,7 @@ If FILE-NAME is non-nil, save the result to FILE-NAME."
              (setq bits (+ bits
                            (logand
                             (-
-                             (uudecode-char-int (char-after inputpos)) 32)
+                              (char-after inputpos) 32)
                             63)))
              (if (/= counter 0) (setq remain (1- remain)))
              (setq counter (1+ counter)
@@ -201,6 +196,8 @@ If FILE-NAME is non-nil, save the result to FILE-NAME."
       (uudecode-decode-region-external start end file-name)
     (uudecode-decode-region-internal start end file-name)))
 
+(define-obsolete-function-alias 'uudecode-char-int #'identity "28.1")
+
 (provide 'uudecode)
 
 ;;; uudecode.el ends here
diff --git a/lisp/md4.el b/lisp/md4.el
index 925686a..029a125 100644
--- a/lisp/md4.el
+++ b/lisp/md4.el
@@ -4,7 +4,7 @@
 
 ;; Author: Taro Kawagishi <tarok@transpulse.org>
 ;; Keywords: MD4
-;; Version: 1.00
+;; Old-Version: 1.00
 ;; Created: February 2001
 
 ;; This file is part of GNU Emacs.
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 427636e..5a41e2f 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -776,44 +776,50 @@ The text is displayed for 
`minibuffer-message-clear-timeout' seconds
 whichever comes first.
 Unlike `minibuffer-message', this function is called automatically
 via `set-message-function'."
-  (when (and (not noninteractive)
-             (window-live-p (active-minibuffer-window)))
-    (with-current-buffer (window-buffer (active-minibuffer-window))
-      (setq message (if (string-match-p "\\` *\\[.+\\]\\'" message)
-                        ;; Make sure we can put-text-property.
-                        (copy-sequence message)
-                      (concat " [" message "]")))
-      (unless (or (null minibuffer-message-properties)
-                  ;; Don't overwrite the face properties the caller has set
-                  (text-properties-at 0 message))
-        (setq message (apply #'propertize message 
minibuffer-message-properties)))
-
-      (clear-minibuffer-message)
-
-      (let ((ovpos (minibuffer--message-overlay-pos)))
-        (setq minibuffer-message-overlay
-              (make-overlay ovpos ovpos nil t t)))
-      (unless (zerop (length message))
-        ;; The current C cursor code doesn't know to use the overlay's
-        ;; marker's stickiness to figure out whether to place the cursor
-        ;; before or after the string, so let's spoon-feed it the pos.
-        (put-text-property 0 1 'cursor 1 message))
-      (overlay-put minibuffer-message-overlay 'after-string message)
-      ;; Make sure the overlay with the message is displayed before
-      ;; any other overlays in that position, in case they have
-      ;; resize-mini-windows set to nil and the other overlay strings
-      ;; are too long for the mini-window width.  This makes sure the
-      ;; temporary message will always be visible.
-      (overlay-put minibuffer-message-overlay 'priority 1100)
-
-      (when (numberp minibuffer-message-clear-timeout)
-        (setq minibuffer-message-timer
-              (run-with-timer minibuffer-message-clear-timeout nil
-                              #'clear-minibuffer-message)))
-
-      ;; Return `t' telling the caller that the message
-      ;; was handled specially by this function.
-      t)))
+  (let* ((minibuf-window (active-minibuffer-window))
+         (minibuf-frame (and (window-live-p minibuf-window)
+                             (window-frame minibuf-window))))
+    (when (and (not noninteractive)
+               (window-live-p minibuf-window)
+               (or (eq (window-frame) minibuf-frame)
+                   (eq (frame-parameter minibuf-frame 'minibuffer) 'only)))
+      (with-current-buffer (window-buffer minibuf-window)
+        (setq message (if (string-match-p "\\` *\\[.+\\]\\'" message)
+                          ;; Make sure we can put-text-property.
+                          (copy-sequence message)
+                        (concat " [" message "]")))
+        (unless (or (null minibuffer-message-properties)
+                    ;; Don't overwrite the face properties the caller has set
+                    (text-properties-at 0 message))
+          (setq message
+                (apply #'propertize message minibuffer-message-properties)))
+
+        (clear-minibuffer-message)
+
+        (let ((ovpos (minibuffer--message-overlay-pos)))
+          (setq minibuffer-message-overlay
+                (make-overlay ovpos ovpos nil t t)))
+        (unless (zerop (length message))
+          ;; The current C cursor code doesn't know to use the overlay's
+          ;; marker's stickiness to figure out whether to place the cursor
+          ;; before or after the string, so let's spoon-feed it the pos.
+          (put-text-property 0 1 'cursor 1 message))
+        (overlay-put minibuffer-message-overlay 'after-string message)
+        ;; Make sure the overlay with the message is displayed before
+        ;; any other overlays in that position, in case they have
+        ;; resize-mini-windows set to nil and the other overlay strings
+        ;; are too long for the mini-window width.  This makes sure the
+        ;; temporary message will always be visible.
+        (overlay-put minibuffer-message-overlay 'priority 1100)
+
+        (when (numberp minibuffer-message-clear-timeout)
+          (setq minibuffer-message-timer
+                (run-with-timer minibuffer-message-clear-timeout nil
+                                #'clear-minibuffer-message)))
+
+        ;; Return `t' telling the caller that the message
+        ;; was handled specially by this function.
+        t))))
 
 (setq set-message-function 'set-minibuffer-message)
 
diff --git a/lisp/mpc.el b/lisp/mpc.el
index d22b7ab..fade23e 100644
--- a/lisp/mpc.el
+++ b/lisp/mpc.el
@@ -819,8 +819,8 @@ The songs are returned as alists."
 (defun mpc-cmd-status ()
   (mpc-proc-cmd-to-alist "status"))
 
-(defun mpc-cmd-play ()
-  (mpc-proc-cmd "play")
+(defun mpc-cmd-play (&optional sn)
+  (mpc-proc-cmd (if sn (list "play" sn) "play"))
   (mpc-status-refresh))
 
 (defun mpc-cmd-seekcur (time)
@@ -849,7 +849,7 @@ If PLAYLIST is t or nil or missing, use the main playlist."
                          ;; Sort them from last to first, so the renumbering
                          ;; caused by the earlier deletions don't affect
                          ;; later ones.
-                         (sort song-poss '>))))
+                         (sort (copy-sequence song-poss) '>))))
     (if (stringp playlist)
         (puthash (cons 'Playlist playlist) nil mpc--find-memoize)))
 
@@ -873,7 +873,7 @@ If PLAYLIST is t or nil or missing, use the main playlist."
               ;; Sort them from last to first, so the renumbering
               ;; caused by the earlier deletions affect
               ;; later ones a bit less.
-              (sort song-poss '>))))
+              (sort (copy-sequence song-poss) '>))))
     (if (stringp playlist)
         (puthash (cons 'Playlist playlist) nil mpc--find-memoize))))
 
@@ -2089,7 +2089,7 @@ This is used so that they can be compared with `eq', 
which is needed for
      ((null (with-current-buffer plbuf (re-search-forward re nil t)))
       ;; song-file only appears once in the playlist: no ambiguity,
       ;; we're good to go!
-      (mpc-proc-cmd (list "play" sn)))
+      (mpc-cmd-play sn))
      (t
       ;; The song appears multiple times in the playlist.  If the current
       ;; buffer holds not only the destination song but also the current
@@ -2391,6 +2391,7 @@ This is used so that they can be compared with `eq', 
which is needed for
   (interactive)
   (mpc-cmd-stop)
   (mpc-cmd-clear)
+  (mpc-songs-refresh)
   (mpc-status-refresh))
 
 (defun mpc-pause ()
diff --git a/lisp/net/browse-url.el b/lisp/net/browse-url.el
index e7dad48..8b245b0 100644
--- a/lisp/net/browse-url.el
+++ b/lisp/net/browse-url.el
@@ -134,6 +134,8 @@
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; Code:
 
+(require 'url)
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Variables
 
@@ -1374,10 +1376,16 @@ Optional argument SAME-WINDOW non-nil means show the 
URL in the
 currently selected window instead."
   (interactive (browse-url-interactive-arg "URL: "))
   (require 'url-handlers)
-  (let ((file-name-handler-alist
-         (cons (cons url-handler-regexp 'url-file-handler)
-               file-name-handler-alist)))
-    (if same-window (find-file url) (find-file-other-window url))))
+  (let ((parsed (url-generic-parse-url url))
+        (func (if same-window 'find-file 'find-file-other-window)))
+    (if (and (equal (url-type parsed) "file")
+             (file-directory-p (url-filename parsed)))
+        ;; It's a directory; just open it.
+        (funcall func (url-filename parsed))
+      (let ((file-name-handler-alist
+             (cons (cons url-handler-regexp 'url-file-handler)
+                   file-name-handler-alist)))
+        (funcall func url)))))
 
 (function-put 'browse-url-emacs 'browse-url-browser-kind 'internal)
 
diff --git a/lisp/net/eww.el b/lisp/net/eww.el
index fd9fe98..53835bb 100644
--- a/lisp/net/eww.el
+++ b/lisp/net/eww.el
@@ -695,11 +695,12 @@ Currently this means either text/html or 
application/xhtml+xml."
   (eww-handle-link dom)
   (let ((start (point)))
     (shr-tag-a dom)
-    (put-text-property start (point)
-                       'keymap
-                       (if (mm-images-in-region-p start (point))
-                           eww-image-link-keymap
-                         eww-link-keymap))))
+    (if (dom-attr dom 'href)
+        (put-text-property start (point)
+                           'keymap
+                           (if (mm-images-in-region-p start (point))
+                               eww-image-link-keymap
+                             eww-link-keymap)))))
 
 (defun eww--limit-string-pixelwise (string pixels)
   (if (not pixels)
diff --git a/lisp/net/sasl-ntlm.el b/lisp/net/sasl-ntlm.el
index ec5b53e..6882c23 100644
--- a/lisp/net/sasl-ntlm.el
+++ b/lisp/net/sasl-ntlm.el
@@ -4,7 +4,7 @@
 
 ;; Author: Taro Kawagishi <tarok@transpulse.org>
 ;; Keywords: SASL, NTLM
-;; Version: 1.00
+;; Old-Version: 1.00
 ;; Created: February 2001
 ;; Package: sasl
 
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index 15eab0a..2c7c6da 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -2850,8 +2850,10 @@ implementation will be used."
                 ;; command.
                 (heredoc (and (stringp program)
                               (string-match-p "sh$" program)
+                              (= (length args) 2)
                               (string-equal "-c" (car args))
-                              (= (length args) 2)))
+                              ;; Don't if there is a string.
+                              (not (string-match-p "'\\|\"" (cadr args)))))
                 ;; When PROGRAM is nil, we just provide a tty.
                 (args (if (not heredoc) args
                         (let ((i 250))
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index 6d44ad2..0c85025 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -1235,6 +1235,8 @@ have been gone since last remote command execution.  A 
value of t
 would require an immediate reread during filename completion, nil
 means to use always cached values for the directory contents."
   :type '(choice (const nil) (const t) integer))
+(make-obsolete-variable
+ 'tramp-completion-reread-directory-timeout 'remote-file-name-inhibit-cache 
"27.2")
 
 ;;; Internal Variables:
 
diff --git a/lisp/nxml/nxml-mode.el b/lisp/nxml/nxml-mode.el
index 644de03..5bb904e 100644
--- a/lisp/nxml/nxml-mode.el
+++ b/lisp/nxml/nxml-mode.el
@@ -2230,7 +2230,7 @@ ENDP is t in the former case, nil in the latter."
     (skip-line-prefix fill-prefix)
     fill-prefix))
 
-(defun nxml-newline-and-indent (soft)
+(defun nxml-newline-and-indent (&optional soft)
   (delete-horizontal-space)
   (if soft (insert-and-inherit ?\n) (newline 1))
   (nxml-indent-line))
diff --git a/lisp/org/org.el b/lisp/org/org.el
index 7733198..1ab8ab6 100644
--- a/lisp/org/org.el
+++ b/lisp/org/org.el
@@ -223,7 +223,8 @@ byte-compiled before it is loaded."
       (org-babel-tangle-file file tangled-file "emacs-lisp"))
     (if compile
        (progn
-         (byte-compile-file tangled-file 'load)
+          (byte-compile-file tangled-file)
+          (load tangled-file)
          (message "Compiled and loaded %s" tangled-file))
       (load-file tangled-file)
       (message "Loaded %s" tangled-file))))
diff --git a/lisp/outline.el b/lisp/outline.el
index a4ce9af..47e6528 100644
--- a/lisp/outline.el
+++ b/lisp/outline.el
@@ -1,4 +1,4 @@
-;;; outline.el --- outline mode commands for Emacs
+;;; outline.el --- outline mode commands for Emacs  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1986, 1993-1995, 1997, 2000-2020 Free Software
 ;; Foundation, Inc.
@@ -166,7 +166,7 @@ in the file it applies to.")
                   ;; Remove extra separator
                   (cdr
                    ;; Flatten the major mode's menus into a single menu.
-                   (apply 'append
+                   (apply #'append
                           (mapcar (lambda (x)
                                     (if (consp x)
                                         ;; Add a separator between each
@@ -196,47 +196,45 @@ in the file it applies to.")
 
 (defface outline-1
   '((t :inherit font-lock-function-name-face))
-  "Level 1."
-  :group 'outlines)
+  "Level 1.")
 
 (defface outline-2
   '((t :inherit font-lock-variable-name-face))
-  "Level 2."
-  :group 'outlines)
+  "Level 2.")
 
 (defface outline-3
   '((t :inherit font-lock-keyword-face))
-  "Level 3."
-  :group 'outlines)
+  "Level 3.")
 
 (defface outline-4
   '((t :inherit font-lock-comment-face))
-  "Level 4."
-  :group 'outlines)
+  "Level 4.")
 
 (defface outline-5
   '((t :inherit font-lock-type-face))
-  "Level 5."
-  :group 'outlines)
+  "Level 5.")
 
 (defface outline-6
   '((t :inherit font-lock-constant-face))
-  "Level 6."
-  :group 'outlines)
+  "Level 6.")
 
 (defface outline-7
   '((t :inherit font-lock-builtin-face))
-  "Level 7."
-  :group 'outlines)
+  "Level 7.")
 
 (defface outline-8
   '((t :inherit font-lock-string-face))
-  "Level 8."
-  :group 'outlines)
+  "Level 8.")
 
 (defvar outline-font-lock-faces
   [outline-1 outline-2 outline-3 outline-4
    outline-5 outline-6 outline-7 outline-8])
+
+(defvar outline-level #'outline-level
+  "Function of no args to compute a header's nesting level in an outline.
+It can assume point is at the beginning of a header line and that the match
+data reflects the `outline-regexp'.")
+;;;###autoload(put 'outline-level 'risky-local-variable t)
 
 (defun outline-font-lock-face ()
   "Return one of `outline-font-lock-faces' for current level."
@@ -279,21 +277,20 @@ beginning of the line.  The longer the match, the deeper 
the level.
 
 Turning on outline mode calls the value of `text-mode-hook' and then of
 `outline-mode-hook', if they are non-nil."
-  (make-local-variable 'line-move-ignore-invisible)
-  (setq line-move-ignore-invisible t)
+  (setq-local line-move-ignore-invisible t)
   ;; Cause use of ellipses for invisible text.
   (add-to-invisibility-spec '(outline . t))
-  (set (make-local-variable 'paragraph-start)
-       (concat paragraph-start "\\|\\(?:" outline-regexp "\\)"))
+  (setq-local paragraph-start
+              (concat paragraph-start "\\|\\(?:" outline-regexp "\\)"))
   ;; Inhibit auto-filling of header lines.
-  (set (make-local-variable 'auto-fill-inhibit-regexp) outline-regexp)
-  (set (make-local-variable 'paragraph-separate)
-       (concat paragraph-separate "\\|\\(?:" outline-regexp "\\)"))
-  (set (make-local-variable 'font-lock-defaults)
-       '(outline-font-lock-keywords t nil nil backward-paragraph))
-  (setq imenu-generic-expression
-       (list (list nil (concat "^\\(?:" outline-regexp "\\).*$") 0)))
-  (add-hook 'change-major-mode-hook 'outline-show-all nil t))
+  (setq-local auto-fill-inhibit-regexp outline-regexp)
+  (setq-local paragraph-separate
+              (concat paragraph-separate "\\|\\(?:" outline-regexp "\\)"))
+  (setq-local font-lock-defaults
+              '(outline-font-lock-keywords t nil nil backward-paragraph))
+  (setq-local imenu-generic-expression
+             (list (list nil (concat "^\\(?:" outline-regexp "\\).*$") 0)))
+  (add-hook 'change-major-mode-hook #'outline-show-all nil t))
 
 (defvar outline-minor-mode-map)
 
@@ -302,7 +299,6 @@ Turning on outline mode calls the value of `text-mode-hook' 
and then of
 The value of this variable is checked as part of loading Outline mode.
 After that, changing the prefix key requires manipulating keymaps."
   :type 'key-sequence
-  :group 'outlines
   :initialize 'custom-initialize-default
   :set (lambda (sym val)
          (define-key outline-minor-mode-map outline-minor-mode-prefix nil)
@@ -316,7 +312,6 @@ After that, changing the prefix key requires manipulating 
keymaps."
 See the command `outline-mode' for more information on this mode."
   nil " Outl" (list (cons [menu-bar] outline-minor-mode-menu-bar-map)
                    (cons outline-minor-mode-prefix outline-mode-prefix-map))
-  :group 'outlines
   (if outline-minor-mode
       (progn
        ;; Turn off this mode if we change major modes.
@@ -331,14 +326,8 @@ See the command `outline-mode' for more information on 
this mode."
     (remove-from-invisibility-spec '(outline . t))
     ;; When turning off outline mode, get rid of any outline hiding.
     (outline-show-all)))
-
-(defvar outline-level 'outline-level
-  "Function of no args to compute a header's nesting level in an outline.
-It can assume point is at the beginning of a header line and that the match
-data reflects the `outline-regexp'.")
-;;;###autoload(put 'outline-level 'risky-local-variable t)
 
-(defvar outline-heading-alist ()
+(defvar-local outline-heading-alist ()
   "Alist associating a heading for every possible level.
 Each entry is of the form (HEADING . LEVEL).
 This alist is used two ways: to find the heading corresponding to
@@ -357,7 +346,6 @@ within each set.  For example in texinfo mode:
 
 Instead of sorting the entries in each set, you can also separate the
 sets with nil.")
-(make-variable-buffer-local 'outline-heading-alist)
 
 ;; This used to count columns rather than characters, but that made ^L
 ;; appear to be at level 2 instead of 1.  Columns would be better for
@@ -402,6 +390,8 @@ at the end of the buffer."
 If POS is nil, use `point' instead."
   (eq (get-char-property (or pos (point)) 'invisible) 'outline))
 
+(define-error 'outline-before-first-heading "Before first heading")
+
 (defun outline-back-to-heading (&optional invisible-ok)
   "Move to previous heading line, or beg of this line if it's a heading.
 Only visible heading lines are considered, unless INVISIBLE-OK is non-nil."
@@ -412,7 +402,7 @@ Only visible heading lines are considered, unless 
INVISIBLE-OK is non-nil."
          (while (not found)
            (or (re-search-backward (concat "^\\(?:" outline-regexp "\\)")
                                    nil t)
-                (error "Before first heading"))
+                (signal 'outline-before-first-heading nil))
            (setq found (and (or invisible-ok (not (outline-invisible-p)))
                             (point)))))
        (goto-char found)
@@ -477,9 +467,9 @@ nil for WHICH, or do not pass any argument)."
           (if current-prefix-arg nil 'subtree))))
   (cond
    ((eq which 'region)
-    (outline-map-region 'outline-promote (region-beginning) (region-end)))
+    (outline-map-region #'outline-promote (region-beginning) (region-end)))
    (which
-    (outline-map-region 'outline-promote
+    (outline-map-region #'outline-promote
                        (point)
                        (save-excursion (outline-get-next-sibling) (point))))
    (t
@@ -516,9 +506,9 @@ nil for WHICH, or do not pass any argument)."
           (if current-prefix-arg nil 'subtree))))
   (cond
    ((eq which 'region)
-    (outline-map-region 'outline-demote (region-beginning) (region-end)))
+    (outline-map-region #'outline-demote (region-beginning) (region-end)))
    (which
-    (outline-map-region 'outline-demote
+    (outline-map-region #'outline-demote
                        (point)
                        (save-excursion (outline-get-next-sibling) (point))))
    (t
@@ -698,12 +688,12 @@ This puts point at the start of the current subtree, and 
mark at the end."
     (goto-char beg)))
 
 
-(defvar outline-isearch-open-invisible-function nil
+(defvar outline-isearch-open-invisible-function
+  #'outline-isearch-open-invisible
   "Function called if `isearch' finishes in an invisible overlay.
-The function is called with the overlay as its only argument.
-If nil, `outline-show-entry' is called to reveal the invisible text.")
+The function is called with the overlay as its only argument.")
 
-(put 'outline 'reveal-toggle-invisible 'outline-reveal-toggle-invisible)
+(put 'outline 'reveal-toggle-invisible #'outline-reveal-toggle-invisible)
 (defun outline-flag-region (from to flag)
   "Hide or show lines from FROM to TO, according to FLAG.
 If FLAG is nil then text is shown, while if FLAG is t the text is hidden."
@@ -717,7 +707,7 @@ If FLAG is nil then text is shown, while if FLAG is t the 
text is hidden."
       (overlay-put o 'invisible 'outline)
       (overlay-put o 'isearch-open-invisible
                   (or outline-isearch-open-invisible-function
-                      'outline-isearch-open-invisible))))
+                      #'outline-isearch-open-invisible))))
   ;; Seems only used by lazy-lock.  I.e. obsolete.
   (run-hooks 'outline-view-change-hook))
 
@@ -777,8 +767,7 @@ If FLAG is nil then text is shown, while if FLAG is t the 
text is hidden."
     (outline-end-of-heading)
     (outline-flag-region (point) (progn (outline-next-preface) (point)) t)))
 
-(define-obsolete-function-alias
-    'hide-entry 'outline-hide-entry "25.1")
+(define-obsolete-function-alias 'hide-entry #'outline-hide-entry "25.1")
 
 (defun outline-show-entry ()
   "Show the body directly following this heading.
@@ -794,8 +783,7 @@ Show the heading too, if it is currently invisible."
                              (point)))
                          nil)))
 
-(define-obsolete-function-alias
-    'show-entry 'outline-show-entry "25.1")
+(define-obsolete-function-alias 'show-entry #'outline-show-entry "25.1")
 
 (defun outline-hide-body ()
   "Hide all body lines in buffer, leaving all headings visible.
@@ -803,8 +791,7 @@ Note that this does not hide the lines preceding the first 
heading line."
   (interactive)
   (outline-hide-region-body (point-min) (point-max)))
 
-(define-obsolete-function-alias
-    'hide-body 'outline-hide-body "25.1")
+(define-obsolete-function-alias 'hide-body #'outline-hide-body "25.1")
 
 (defun outline-hide-region-body (start end)
   "Hide all body lines between START and END, but not headings."
@@ -828,23 +815,21 @@ Note that this does not hide the lines preceding the 
first heading line."
   (run-hooks 'outline-view-change-hook))
 
 (define-obsolete-function-alias
-    'hide-region-body 'outline-hide-region-body "25.1")
+    'hide-region-body #'outline-hide-region-body "25.1")
 
 (defun outline-show-all ()
   "Show all of the text in the buffer."
   (interactive)
   (outline-flag-region (point-min) (point-max) nil))
 
-(define-obsolete-function-alias
-    'show-all 'outline-show-all "25.1")
+(define-obsolete-function-alias 'show-all #'outline-show-all "25.1")
 
 (defun outline-hide-subtree ()
   "Hide everything after this heading at deeper levels."
   (interactive)
   (outline-flag-subtree t))
 
-(define-obsolete-function-alias
-    'hide-subtree 'outline-hide-subtree "25.1")
+(define-obsolete-function-alias 'hide-subtree #'outline-hide-subtree "25.1")
 
 (defun outline-hide-leaves ()
   "Hide the body after this heading and at deeper levels."
@@ -857,16 +842,14 @@ Note that this does not hide the lines preceding the 
first heading line."
      (point)
      (progn (outline-end-of-subtree) (point)))))
 
-(define-obsolete-function-alias
-    'hide-leaves 'outline-hide-leaves "25.1")
+(define-obsolete-function-alias 'hide-leaves #'outline-hide-leaves "25.1")
 
 (defun outline-show-subtree ()
   "Show everything after this heading at deeper levels."
   (interactive)
   (outline-flag-subtree nil))
 
-(define-obsolete-function-alias
-    'show-subtree 'outline-show-subtree "25.1")
+(define-obsolete-function-alias 'show-subtree #'outline-show-subtree "25.1")
 
 (defun outline-show-heading ()
   "Show the current heading and move to its end."
@@ -921,8 +904,7 @@ of the current heading, or to 1 if the current line is not 
a heading."
           (outline-flag-region (1- (point)) (point) nil))))
   (run-hooks 'outline-view-change-hook))
 
-(define-obsolete-function-alias
-    'hide-sublevels 'outline-hide-sublevels "25.1")
+(define-obsolete-function-alias 'hide-sublevels #'outline-hide-sublevels 
"25.1")
 
 (defun outline-hide-other ()
   "Hide everything except current body and parent and top-level headings.
@@ -940,8 +922,7 @@ This also unhides the top heading-less body, if any."
                             nil))))
   (run-hooks 'outline-view-change-hook))
 
-(define-obsolete-function-alias
-    'hide-other 'outline-hide-other "25.1")
+(define-obsolete-function-alias 'hide-other #'outline-hide-other "25.1")
 
 (defun outline-toggle-children ()
   "Show or hide the current subtree depending on its current state."
@@ -985,8 +966,7 @@ This also unhides the top heading-less body, if any."
   (interactive)
   (outline-show-children 1000))
 
-(define-obsolete-function-alias
-    'show-branches 'outline-show-branches "25.1")
+(define-obsolete-function-alias 'show-branches #'outline-show-branches "25.1")
 
 (defun outline-show-children (&optional level)
   "Show all direct subheadings of this heading.
@@ -1015,8 +995,7 @@ Default is enough to cause the following heading to 
appear."
              (if (eobp) (point-max) (1+ (point)))))))
   (run-hooks 'outline-view-change-hook))
 
-(define-obsolete-function-alias
-    'show-children 'outline-show-children "25.1")
+(define-obsolete-function-alias 'show-children #'outline-show-children "25.1")
 
 
 
@@ -1167,19 +1146,21 @@ Return either 'hide-all, 'headings-only, or 'show-all."
 `Headings only' means show sub headings but not their bodies.
 `Show all' means show all subheadings and their bodies."
   (interactive)
-  (pcase (outline--cycle-state)
-    ('hide-all
-     (if (outline-has-subheading-p)
-         (progn (outline-show-children)
-                (message "Only headings"))
-       (outline-show-subtree)
-       (message "Show all")))
-    ('headings-only
-     (outline-show-subtree)
-     (message "Show all"))
-    ('show-all
-     (outline-hide-subtree)
-     (message "Hide all"))))
+  (condition-case nil
+      (pcase (outline--cycle-state)
+        ('hide-all
+         (if (outline-has-subheading-p)
+             (progn (outline-show-children)
+                    (message "Only headings"))
+           (outline-show-subtree)
+           (message "Show all")))
+        ('headings-only
+         (outline-show-subtree)
+         (message "Show all"))
+        ('show-all
+         (outline-hide-subtree)
+         (message "Hide all")))
+    (outline-before-first-heading nil)))
 
 (defvar-local outline--cycle-buffer-state 'show-all
   "Internal variable used for tracking buffer cycle state.")
@@ -1189,13 +1170,7 @@ Return either 'hide-all, 'headings-only, or 'show-all."
   (interactive)
   (pcase outline--cycle-buffer-state
     ('show-all
-     (save-excursion
-       (let ((start-point (point)))
-         (while (not (eq (point) start-point))
-           (outline-up-heading 1))
-         (outline-hide-sublevels
-          (progn (outline-back-to-heading)
-                 (funcall 'outline-level)))))
+     (outline-hide-sublevels 1)
      (setq outline--cycle-buffer-state 'top-level)
      (message "Top level headings"))
     ('top-level
diff --git a/lisp/play/dunnet.el b/lisp/play/dunnet.el
index a03d0a9..8a69f9d 100644
--- a/lisp/play/dunnet.el
+++ b/lisp/play/dunnet.el
@@ -4,7 +4,7 @@
 
 ;; Author: Ron Schnell <ronnie@driver-aces.com>
 ;; Created: 25 Jul 1992
-;; Version: 2.02
+;; Old-Version: 2.02
 ;; Keywords: games
 
 ;; This file is part of GNU Emacs.
@@ -1957,7 +1957,7 @@ to swim.")
 
 (defun dun-help (_args)
   (dun-mprincl
-"Welcome to dunnet (2.02), by Ron Schnell (ronnie@driver-aces.com - 
@RonnieSchnell).
+"Welcome to dunnet by Ron Schnell (ronnie@driver-aces.com - @RonnieSchnell).
 Here is some useful information (read carefully because there are one
 or more clues in here):
 - If you have a key that can open a door, you do not need to explicitly
diff --git a/lisp/play/gamegrid.el b/lisp/play/gamegrid.el
index 74e6c2d..bb8ae56 100644
--- a/lisp/play/gamegrid.el
+++ b/lisp/play/gamegrid.el
@@ -3,7 +3,7 @@
 ;; Copyright (C) 1997-1998, 2001-2020 Free Software Foundation, Inc.
 
 ;; Author: Glynn Clements <glynn@sensei.co.uk>
-;; Version: 1.02
+;; Old-Version: 1.02
 ;; Created: 1997-08-13
 ;; Keywords: games
 
diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el
index bc0fe6d..9188a08 100644
--- a/lisp/progmodes/compile.el
+++ b/lisp/progmodes/compile.el
@@ -1063,9 +1063,9 @@ from a different message."
             (:constructor nil)
             (:copier nil)
             ;; (:type list)                ;Old representation.
-            (:constructor compilation--make-message (loc type end-loc))
+            (:constructor compilation--make-message (loc type end-loc rule))
             (:conc-name compilation--message->))
-  loc type end-loc)
+  loc type end-loc rule)
 
 (defvar compilation--previous-directory-cache nil
   "A pair (POS . RES) caching the result of previous directory search.
@@ -1138,7 +1138,7 @@ POS and RES.")
                                (cons (match-string-no-properties idx) dir))
       ;; Place a `compilation-message' everywhere we change text-properties
       ;; so compilation--remove-properties can know what to remove.
-      compilation-message ,(compilation--make-message nil 0 nil)
+      compilation-message ,(compilation--make-message nil 0 nil nil)
       mouse-face highlight
       keymap compilation-button-map
       help-echo "mouse-2: visit destination directory")))
@@ -1177,7 +1177,8 @@ POS and RES.")
 ;; all information needed to later jump to corresponding source code.
 ;; Return a property list with all meta information on this error location.
 
-(defun compilation-error-properties (file line end-line col end-col type fmt)
+(defun compilation-error-properties (file line end-line col end-col type fmt
+                                     rule)
   (unless (text-property-not-all (match-beginning 0) (point)
                                  'compilation-message nil)
     (if file
@@ -1265,7 +1266,7 @@ POS and RES.")
                         (current-buffer) (match-beginning 0)))
 
       (compilation-internal-error-properties
-       file line end-line col end-col type fmt))))
+       file line end-line col end-col type fmt rule))))
 
 (defun compilation-beginning-of-line (&optional n)
   "Like `beginning-of-line', but accounts for lines hidden by 
`selective-display'."
@@ -1288,13 +1289,15 @@ just char-counts."
       (let ((tab-width 8)) (move-to-column (max col 0)))
     (goto-char (min (+ (line-beginning-position) col) (line-end-position)))))
 
-(defun compilation-internal-error-properties (file line end-line col end-col 
type fmts)
+(defun compilation-internal-error-properties (file line end-line col end-col
+                                              type fmts rule)
   "Get the meta-info that will be added as text-properties.
 LINE, END-LINE, COL, END-COL are integers or nil.
 TYPE can be 0, 1, or 2, meaning error, warning, or just info.
 FILE should be (FILENAME) or (RELATIVE-FILENAME . DIRNAME) or (BUFFER) or
 nil.
 FMTS is a list of format specs for transforming the file name.
+RULE is the name (symbol) of the rule used or nil if anonymous.
  (See `compilation-error-regexp-alist'.)"
   (unless file (setq file '("*unknown*")))
   (let* ((file-struct (compilation-get-file-structure file fmts))
@@ -1381,7 +1384,7 @@ FMTS is a list of format specs for transforming the file 
name.
 
     ;; Must start with face
     `(font-lock-face ,compilation-message-face
-      compilation-message ,(compilation--make-message loc type end-loc)
+      compilation-message ,(compilation--make-message loc type end-loc rule)
       help-echo ,(if col
                      "mouse-2: visit this file, line and column"
                    (if line
@@ -1473,105 +1476,109 @@ This updates the appropriate variable used by the 
mode-line."
   "Parse errors between START and END.
 The errors recognized are the ones specified in RULES which default
 to `compilation-error-regexp-alist' if RULES is nil."
-  (dolist (item (or rules compilation-error-regexp-alist))
-    (if (symbolp item)
-        (setq item (cdr (assq item
-                              compilation-error-regexp-alist-alist))))
-    (let ((case-fold-search compilation-error-case-fold-search)
-          (file (nth 1 item))
-          (line (nth 2 item))
-          (col (nth 3 item))
-          (type (nth 4 item))
-          (pat (car item))
-          end-line end-col fmt
-          props)
-
-      ;; omake reports some error indented, so skip the indentation.
-      ;; another solution is to modify (some?) regexps in
-      ;; `compilation-error-regexp-alist'.
-      ;; note that omake usage is not limited to ocaml and C (for stubs).
-      ;; FIXME-omake: Doing it here seems wrong, at least it should depend on
-      ;; whether or not omake's own error messages are recognized.
-      (cond
-       ((not (memq 'omake compilation-error-regexp-alist)) nil)
-       ((string-match "\\`\\([^^]\\|\\^\\( \\*\\|\\[\\)\\)" pat)
-        nil) ;; Not anchored or anchored but already allows empty spaces.
-       (t (setq pat (concat "^\\(?:      \\)?" (substring pat 1)))))
-
-      (if (and (consp file) (not (functionp file)))
-         (setq fmt (cdr file)
-                file (car file)))
-      (if (and (consp line) (not (functionp line)))
-          (setq end-line (cdr line)
-                line (car line)))
-      (if (and (consp col) (not (functionp col)))
-          (setq end-col (cdr col)
-                col (car col)))
-
-      (unless (or (null (nth 5 item)) (integerp (nth 5 item)))
-        (error "HYPERLINK should be an integer: %s" (nth 5 item)))
-
-      (goto-char start)
-      (while (re-search-forward pat end t)
-        (when (setq props (compilation-error-properties
-                           file line end-line col end-col (or type 2) fmt))
-
-          (when (integerp file)
-            (let ((this-type (if (consp type)
-                                 (compilation-type type)
-                               (or type 2))))
-              (compilation--note-type this-type)
-
-              (compilation--put-prop
-               file 'font-lock-face
-               (symbol-value (aref [compilation-info-face
-                                    compilation-warning-face
-                                    compilation-error-face]
-                                   this-type)))))
-
-          (compilation--put-prop
-           line 'font-lock-face compilation-line-face)
-          (compilation--put-prop
-           end-line 'font-lock-face compilation-line-face)
-
-          (compilation--put-prop
-           col 'font-lock-face compilation-column-face)
-          (compilation--put-prop
-           end-col 'font-lock-face compilation-column-face)
-
-         ;; Obey HIGHLIGHT.
-          (dolist (extra-item (nthcdr 6 item))
-            (let ((mn (pop extra-item)))
-              (when (match-beginning mn)
-                (let ((face (eval (car extra-item))))
-                  (cond
-                   ((null face))
-                   ((or (symbolp face) (stringp face))
-                    (put-text-property
-                     (match-beginning mn) (match-end mn)
-                     'font-lock-face face))
-                  ((and (listp face)
-                        (eq (car face) 'face)
-                        (or (symbolp (cadr face))
-                            (stringp (cadr face))))
-                    (compilation--put-prop mn 'font-lock-face (cadr face))
-                    (add-text-properties
-                     (match-beginning mn) (match-end mn)
-                     (nthcdr 2 face)))
-                   (t
-                    (error "Don't know how to handle face %S"
-                           face)))))))
-          (let ((mn (or (nth 5 item) 0)))
-            (when compilation-debug
+  (let ((case-fold-search compilation-error-case-fold-search)
+        (omake-included (memq 'omake compilation-error-regexp-alist)))
+    (dolist (rule-item (or rules compilation-error-regexp-alist))
+      (let* ((item
+              (if (symbolp rule-item)
+                  (cdr (assq rule-item compilation-error-regexp-alist-alist))
+                rule-item))
+             (pat (car item))
+             (file (nth 1 item))
+             (line (nth 2 item))
+             (col (nth 3 item))
+             (type (nth 4 item))
+             (rule (and (symbolp rule-item) rule-item))
+             end-line end-col fmt
+             props)
+
+        ;; omake reports some error indented, so skip the indentation.
+        ;; another solution is to modify (some?) regexps in
+        ;; `compilation-error-regexp-alist'.
+        ;; note that omake usage is not limited to ocaml and C (for stubs).
+        ;; FIXME-omake: Doing it here seems wrong, at least it should depend on
+        ;; whether or not omake's own error messages are recognized.
+        (cond
+         ((not omake-included) nil)
+         ((string-match "\\`\\([^^]\\|\\^\\( \\*\\|\\[\\)\\)" pat)
+          nil) ;; Not anchored or anchored but already allows empty spaces.
+         (t (setq pat (concat "^\\(?:      \\)?" (substring pat 1)))))
+
+        (if (and (consp file) (not (functionp file)))
+            (setq fmt (cdr file)
+                  file (car file)))
+        (if (and (consp line) (not (functionp line)))
+            (setq end-line (cdr line)
+                  line (car line)))
+        (if (and (consp col) (not (functionp col)))
+            (setq end-col (cdr col)
+                  col (car col)))
+
+        (unless (or (null (nth 5 item)) (integerp (nth 5 item)))
+          (error "HYPERLINK should be an integer: %s" (nth 5 item)))
+
+        (goto-char start)
+        (while (re-search-forward pat end t)
+          (when (setq props (compilation-error-properties
+                             file line end-line col end-col
+                             (or type 2) fmt rule))
+
+            (when (integerp file)
+              (let ((this-type (if (consp type)
+                                   (compilation-type type)
+                                 (or type 2))))
+                (compilation--note-type this-type)
+
+                (compilation--put-prop
+                 file 'font-lock-face
+                 (symbol-value (aref [compilation-info-face
+                                      compilation-warning-face
+                                      compilation-error-face]
+                                     this-type)))))
+
+            (compilation--put-prop
+             line 'font-lock-face compilation-line-face)
+            (compilation--put-prop
+             end-line 'font-lock-face compilation-line-face)
+
+            (compilation--put-prop
+             col 'font-lock-face compilation-column-face)
+            (compilation--put-prop
+             end-col 'font-lock-face compilation-column-face)
+
+            ;; Obey HIGHLIGHT.
+            (dolist (extra-item (nthcdr 6 item))
+              (let ((mn (pop extra-item)))
+                (when (match-beginning mn)
+                  (let ((face (eval (car extra-item))))
+                    (cond
+                     ((null face))
+                     ((or (symbolp face) (stringp face))
+                      (put-text-property
+                       (match-beginning mn) (match-end mn)
+                       'font-lock-face face))
+                    ((and (listp face)
+                          (eq (car face) 'face)
+                          (or (symbolp (cadr face))
+                              (stringp (cadr face))))
+                      (compilation--put-prop mn 'font-lock-face (cadr face))
+                      (add-text-properties
+                       (match-beginning mn) (match-end mn)
+                       (nthcdr 2 face)))
+                     (t
+                      (error "Don't know how to handle face %S"
+                             face)))))))
+            (let ((mn (or (nth 5 item) 0)))
+              (when compilation-debug
+                (font-lock-append-text-property
+                 (match-beginning 0) (match-end 0)
+                 'compilation-debug (vector 'std item props)))
+              (add-text-properties
+               (match-beginning mn) (match-end mn)
+               (cddr props))
               (font-lock-append-text-property
-               (match-beginning 0) (match-end 0)
-               'compilation-debug (vector 'std item props)))
-            (add-text-properties
-             (match-beginning mn) (match-end mn)
-             (cddr props))
-            (font-lock-append-text-property
-             (match-beginning mn) (match-end mn)
-             'font-lock-face (cadr props))))))))
+               (match-beginning mn) (match-end mn)
+               'font-lock-face (cadr props)))))))))
 
 (defvar compilation--parsed -1)
 (make-variable-buffer-local 'compilation--parsed)
@@ -3113,7 +3120,7 @@ TRUE-DIRNAME is the `file-truename' of DIRNAME, if given."
             ;;                    'font-lock-face 'font-lock-warning-face)
            (put-text-property src (line-end-position)
                               'compilation-message
-                               (compilation--make-message loc 2 nil)))))))
+                               (compilation--make-message loc 2 nil nil)))))))
   (goto-char limit)
   nil)
 
diff --git a/lisp/progmodes/cperl-mode.el b/lisp/progmodes/cperl-mode.el
index 5b6e50c..ebbea6b 100644
--- a/lisp/progmodes/cperl-mode.el
+++ b/lisp/progmodes/cperl-mode.el
@@ -71,13 +71,6 @@
 
 ;; (define-key global-map [M-S-down-mouse-3] 'imenu)
 
-;;;; Font lock bugs as of v4.32:
-
-;; The following kinds of Perl code erroneously start strings:
-;; \$`  \$'  \$"
-;; $opt::s  $opt_s  $opt{s}  (s => ...)  /\s+.../
-;; likewise with m, tr, y, q, qX instead of s
-
 ;;; Code:
 
 ;;; Compatibility with older versions (for publishing on ELPA)
diff --git a/lisp/progmodes/cpp.el b/lisp/progmodes/cpp.el
index bcbe669..65ef83f 100644
--- a/lisp/progmodes/cpp.el
+++ b/lisp/progmodes/cpp.el
@@ -1,4 +1,4 @@
-;;; cpp.el --- highlight or hide text according to cpp conditionals
+;;; cpp.el --- highlight or hide text according to cpp conditionals -*- 
lexical-binding: t -*-
 
 ;; Copyright (C) 1994-1995, 2001-2020 Free Software Foundation, Inc.
 
diff --git a/lisp/progmodes/dcl-mode.el b/lisp/progmodes/dcl-mode.el
index ab3321f..ca45795 100644
--- a/lisp/progmodes/dcl-mode.el
+++ b/lisp/progmodes/dcl-mode.el
@@ -557,8 +557,7 @@ Variables controlling indentation style and extra features:
  dcl-imenu-label-call
     Change the text that is used as sub-listing labels in imenu.
 
-Loading this package calls the value of the variable
-`dcl-mode-load-hook' with no args, if that value is non-nil.
+To run code after DCL mode has loaded, use `with-eval-after-load'.
 Turning on DCL mode calls the value of the variable `dcl-mode-hook'
 with no args, if that value is non-nil.
 
@@ -2192,6 +2191,8 @@ otherwise return nil."
 
 (provide 'dcl-mode)
 
+(make-obsolete-variable 'dcl-mode-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 (run-hooks 'dcl-mode-load-hook)                ; for your customizations
 
 ;;; dcl-mode.el ends here
diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el
index dbbb127..eed73f5 100644
--- a/lisp/progmodes/elisp-mode.el
+++ b/lisp/progmodes/elisp-mode.el
@@ -196,7 +196,8 @@ All commands in `lisp-mode-shared-map' are inherited by 
this map.")
   (if (and (buffer-modified-p)
           (y-or-n-p (format "Save buffer %s first? " (buffer-name))))
       (save-buffer))
-  (byte-recompile-file buffer-file-name nil 0 t))
+  (byte-recompile-file buffer-file-name nil 0)
+  (load buffer-file-name))
 
 (defun emacs-lisp-macroexpand ()
   "Macroexpand the form after point.
diff --git a/lisp/progmodes/f90.el b/lisp/progmodes/f90.el
index 22f1cfd..1fbbc89 100644
--- a/lisp/progmodes/f90.el
+++ b/lisp/progmodes/f90.el
@@ -1649,25 +1649,28 @@ Return (TYPE NAME), or nil if not found."
   (interactive)
   (let ((count 1) (case-fold-search t) matching-beg)
     (beginning-of-line)
-    (while (and (> count 0)
-                (re-search-backward f90-program-block-re nil 'move))
-      (beginning-of-line)
-      (skip-chars-forward " \t0-9")
-      ;; Check if in string in case using non-standard feature where
-      ;; continued strings do not need "&" at start of continuations.
-      (cond ((f90-in-string))
-            ((setq matching-beg (f90-looking-at-program-block-start))
-             (setq count (1- count)))
-            ((f90-looking-at-program-block-end)
-             (setq count (1+ count)))))
-    (beginning-of-line)
-    (if (zerop count)
-        matching-beg
-      ;; Note this includes the case of an un-named main program,
-      ;; in which case we go to (point-min).
-      (if (called-interactively-p 'interactive)
-         (message "No beginning found"))
-      nil)))
+    ;; Check whether we're already at the start of a subprogram.
+    (or (f90-looking-at-program-block-start)
+        ;; We're not; search backwards.
+        (while (and (> count 0)
+                    (re-search-backward f90-program-block-re nil 'move))
+          (beginning-of-line)
+          (skip-chars-forward " \t0-9")
+          ;; Check if in string in case using non-standard feature where
+          ;; continued strings do not need "&" at start of continuations.
+          (cond ((f90-in-string))
+                ((setq matching-beg (f90-looking-at-program-block-start))
+                 (setq count (1- count)))
+                ((f90-looking-at-program-block-end)
+                 (setq count (1+ count)))))
+        (beginning-of-line)
+        (if (zerop count)
+            matching-beg
+          ;; Note this includes the case of an un-named main program,
+          ;; in which case we go to (point-min).
+          (if (called-interactively-p 'interactive)
+             (message "No beginning found"))
+          nil))))
 
 (defun f90-end-of-subprogram ()
   "Move point to the end of the current subprogram.
diff --git a/lisp/progmodes/fortran.el b/lisp/progmodes/fortran.el
index abc860b..d84c379 100644
--- a/lisp/progmodes/fortran.el
+++ b/lisp/progmodes/fortran.el
@@ -1,4 +1,4 @@
-;;; fortran.el --- Fortran mode for GNU Emacs
+;;; fortran.el --- Fortran mode for GNU Emacs -*- lexical-binding: t -*-
 
 ;; Copyright (C) 1986, 1993-1995, 1997-2020 Free Software Foundation,
 ;; Inc.
@@ -495,14 +495,15 @@ This is used to fontify fixed-format Fortran comments."
   ;; `byte-compile', but simple benchmarks indicate that it's probably not
   ;; worth the trouble (about 0.5% of slow down).
   (eval                         ;I hate `eval', but it's hard to avoid it here.
-   '(syntax-propertize-rules
+   `(syntax-propertize-rules
      ("^[CcDd\\*]" (0 "<"))
      ;; We mark all chars after line-length as "comment-start", rather than
      ;; just the first one.  This is so that a closing ' that's past the
      ;; line-length will indeed be ignored (and will result in a string that
      ;; leaks into subsequent lines).
-     ((format "^[^CcDd\\*\t\n].\\{%d\\}\\(.+\\)" (1- line-length))
-      (1 "<")))))
+     (,(format "^[^CcDd\\*\t\n].\\{%d\\}\\(.+\\)" (1- line-length))
+      (1 "<")))
+   t))
 
 (defvar fortran-font-lock-keywords fortran-font-lock-keywords-1
   "Default expressions to highlight in Fortran mode.")
diff --git a/lisp/progmodes/gdb-mi.el b/lisp/progmodes/gdb-mi.el
index 79df970..9e8af84 100644
--- a/lisp/progmodes/gdb-mi.el
+++ b/lisp/progmodes/gdb-mi.el
@@ -1317,7 +1317,7 @@ With arg, enter name of variable to be watched in the 
minibuffer."
 
 (defun gdb-var-list-children-handler (varnum)
   (let* ((var-list nil)
-        (output (bindat-get-field (gdb-json-partial-output "child")))
+        (output (gdb-json-partial-output "child"))
         (children (bindat-get-field output 'children)))
     (catch 'child-already-watched
       (dolist (var gdb-var-list)
@@ -4395,8 +4395,7 @@ member."
   (save-excursion
     (if event (posn-set-point (event-end event)))
     (beginning-of-line)
-    (let* ((var (bindat-get-field
-                 (get-text-property (point) 'gdb-register-name)))
+    (let* ((var (get-text-property (point) 'gdb-register-name))
           (value (read-string (format "New value (%s): " var))))
       (gud-basic-call
        (concat  "-gdb-set variable $" var " = " value)))))
diff --git a/lisp/progmodes/idlw-complete-structtag.el 
b/lisp/progmodes/idlw-complete-structtag.el
index 3bc3971..4cb8278 100644
--- a/lisp/progmodes/idlw-complete-structtag.el
+++ b/lisp/progmodes/idlw-complete-structtag.el
@@ -53,11 +53,10 @@
 ;;
 ;; INSTALLATION
 ;; ============
-;; Put this file on the emacs load path and load it with the following
-;; line in your init file:
+;; Load it with the following line in your init file:
 ;;
-;;   (add-hook 'idlwave-load-hook
-;;             (lambda () (require 'idlw-complete-structtag)))
+;;   (with-eval-after-load 'idlwave
+;;     (require 'idlw-complete-structtag))
 ;;
 ;; DESCRIPTION
 ;; ===========
diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el
index 5c50e2a..f3cfbbb 100644
--- a/lisp/progmodes/js.el
+++ b/lisp/progmodes/js.el
@@ -4656,8 +4656,19 @@ could set `js-jsx-syntax' to t in your init file, or in a
 one of the aforementioned options instead of using this mode."
   :group 'js
   (js-jsx-enable)
+  (setq-local comment-region-function #'js-jsx--comment-region)
   (js-use-syntactic-mode-name))
 
+(defun js-jsx--comment-region (beg end &optional arg)
+  (if (or (js-jsx--context)
+          (save-excursion
+            (skip-chars-forward " \t")
+            (js-jsx--looking-at-start-tag-p)))
+      (let ((comment-start "{/* ")
+            (comment-end " */}"))
+        (comment-region-default beg end arg))
+    (comment-region-default beg end arg)))
+
 ;;;###autoload (defalias 'javascript-mode 'js-mode)
 
 (eval-after-load 'folding
diff --git a/lisp/progmodes/ld-script.el b/lisp/progmodes/ld-script.el
index 442c230..b17f255 100644
--- a/lisp/progmodes/ld-script.el
+++ b/lisp/progmodes/ld-script.el
@@ -1,4 +1,4 @@
-;;; ld-script.el --- GNU linker script editing mode for Emacs
+;;; ld-script.el --- GNU linker script editing mode for Emacs  -*- 
lexical-binding:t -*-
 
 ;; Copyright (C) 2001-2020 Free Software Foundation, Inc.
 
diff --git a/lisp/progmodes/m4-mode.el b/lisp/progmodes/m4-mode.el
index 95fead9..ec0f425 100644
--- a/lisp/progmodes/m4-mode.el
+++ b/lisp/progmodes/m4-mode.el
@@ -1,4 +1,4 @@
-;;; m4-mode.el --- m4 code editing commands for Emacs
+;;; m4-mode.el --- m4 code editing commands for Emacs  -*- lexical-binding:t 
-*-
 
 ;; Copyright (C) 1996-1997, 2001-2020 Free Software Foundation, Inc.
 
@@ -48,14 +48,12 @@
   "File name of the m4 executable.
 If m4 is not in your PATH, set this to an absolute file name."
   :version "24.4"
-  :type 'file
-  :group 'm4)
+  :type 'file)
 
 ;;options to m4
 (defcustom m4-program-options nil
   "Options to pass to `m4-program'."
-  :type '(repeat string)
-  :group 'm4)
+  :type '(repeat string))
 
 ;;to use --prefix-builtins, you can use
 ;;(defconst m4-program-options '("-P"))
@@ -72,8 +70,7 @@ If m4 is not in your PATH, set this to an absolute file name."
 
 (defcustom m4-mode-hook nil
   "Hook called by `m4-mode'."
-  :type 'hook
-  :group 'm4)
+  :type 'hook)
 
 ;;this may still need some work
 (defvar m4-mode-syntax-table
@@ -125,7 +122,7 @@ If m4 is not in your PATH, set this to an absolute file 
name."
   (interactive)
   (shell-command-on-region
    (point-min) (point-max)
-   (mapconcat 'identity (cons m4-program m4-program-options) "\s")
+   (mapconcat #'identity (cons m4-program m4-program-options) "\s")
    "*m4-output*" nil)
   (switch-to-buffer-other-window "*m4-output*"))
 
@@ -134,7 +131,7 @@ If m4 is not in your PATH, set this to an absolute file 
name."
   (interactive)
   (shell-command-on-region
    (point) (mark)
-   (mapconcat 'identity (cons m4-program m4-program-options) "\s")
+   (mapconcat #'identity (cons m4-program m4-program-options) "\s")
    "*m4-output*" nil)
   (switch-to-buffer-other-window "*m4-output*"))
 
diff --git a/lisp/progmodes/mixal-mode.el b/lisp/progmodes/mixal-mode.el
index 468c116..b9f6059 100644
--- a/lisp/progmodes/mixal-mode.el
+++ b/lisp/progmodes/mixal-mode.el
@@ -1,11 +1,11 @@
-;;; mixal-mode.el --- Major mode for the mix asm language.
+;;; mixal-mode.el --- Major mode for the mix asm language.  -*- 
lexical-binding:t -*-
 
 ;; Copyright (C) 2003-2020 Free Software Foundation, Inc.
 
 ;; Author: Pieter E.J. Pareit <pieter.pareit@gmail.com>
-;; Maintainer: emacs-devel@gnu.org
+;; Maintainer: Jose A Ortega Ruiz <jao@gnu.org>
 ;; Created: 09 Nov 2002
-;; Version: 0.1
+;; Version: 0.4
 ;; Keywords: languages, Knuth, mix, mixal, asm, mixvm, The Art Of Computer 
Programming
 
 ;; This file is part of GNU Emacs.
@@ -24,6 +24,7 @@
 ;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Commentary:
+
 ;; Major mode for the mix asm language.
 ;; The mix asm language is described in "The Art Of Computer Programming".
 ;;
@@ -34,8 +35,9 @@
 ;;
 ;; To use this mode, place the following in your init file:
 ;; `(load-file "/PATH-TO-FILE/mixal-mode.el")'.
+;;
 ;; When you load a file with the extension .mixal the mode will be started
-;; automatic.  If you want to start the mode manual, use `M-x mixal-mode'.
+;; automatically.  If you want to start the mode manually, use `M-x 
mixal-mode'.
 ;; Font locking will work, the behavior of tabs is the same as Emacs's
 ;; default behavior.  You can compile a source file with `C-c c' you can
 ;; run a compiled file with `C-c r' or run it in debug mode with `C-c d'.
@@ -45,6 +47,9 @@
 ;; Have fun.
 
 ;;; History:
+;; Version 0.4:
+;; 16/10/20: Jose A Ortega Ruiz <jao@gnu.org>
+;;           Add missed instructions: SLB,SRB,JAE,JAO,JXE,JXO
 ;; Version 0.3:
 ;; 12/10/05: Stefan Monnier <monnier@iro.umontreal.ca>
 ;;           Use font-lock-syntactic-keywords to detect/mark comments.
@@ -683,6 +688,18 @@ Register J is set to the value of the next instruction 
that would have
 been executed when there was no jump."
           1)
 
+    (JAE jump "jump A even" 40
+          "Jump if the content of rA is even.
+Register J is set to the value of the next instruction that would have
+been executed when there was no jump."
+          1)
+
+    (JAO jump "jump A odd" 40
+         "Jump if the content of rA is odd.
+Register J is set to the value of the next instruction that would have
+been executed when there was no jump."
+         1)
+
     (JXN jump "jump X negative" 47
          "Jump if the content of rX is negative.
 Register J is set to the value of the next instruction that would have
@@ -719,12 +736,24 @@ Register J is set to the value of the next instruction 
that would have
 been executed when there was no jump."
           1)
 
-    (J1N jump "jump I1 negative" 41
-         "Jump if the content of rI1 is negative.
+    (JXE jump "jump X even" 47
+         "Jump if the content of rX is even.
+Register J is set to the value of the next instruction that would have
+been executed when there was no jump."
+         1)
+
+    (JXO jump "jump X odd" 47
+         "Jump if the content of rX is odd.
 Register J is set to the value of the next instruction that would have
 been executed when there was no jump."
          1)
 
+    (J1N jump "jump I1 negative" 41
+     "Jump if the content of rI1 is negative.
+Register J is set to the value of the next instruction that would have
+been executed when there was no jump."
+     1)
+
     (J1Z jump "jump I1 zero" 41
          "Jump if the content of rI1 is zero.
 Register J is set to the value of the next instruction that would have
@@ -950,7 +979,6 @@ Zeros will be added to the left."
 Zeros will be added to the right."
           2)
 
-
     (SRAX miscellaneous "shift right AX" 6
           "Shift AX, M bytes right.
 Zeros will be added to the left."
@@ -966,6 +994,14 @@ The bytes that fall off to the left will be added to the 
right."
 The bytes that fall off to the right will be added to the left."
          2)
 
+    (SLB miscellaneous "shift left AX binary" 6
+         "Shift AX, M binary places left."
+         2)
+
+    (SRB miscellaneous "shift right AX binary" 6
+         "Shift AX, M binary places right."
+         2)
+
     (MOVE miscellaneous "move" 7 number
           "Move MOD words from M to the location stored in rI1."
           (+ 1 (* 2 number)))
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index d1871c9..7f4d225 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -4,7 +4,7 @@
 
 ;; Author: Fabián E. Gallina <fgallina@gnu.org>
 ;; URL: https://github.com/fgallina/python.el
-;; Version: 0.26.1
+;; Version: 0.27
 ;; Package-Requires: ((emacs "24.1") (cl-lib "1.0"))
 ;; Maintainer: emacs-devel@gnu.org
 ;; Created: Jul 2010
diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el
index a8c0e04..3b24cab 100644
--- a/lisp/progmodes/sh-script.el
+++ b/lisp/progmodes/sh-script.el
@@ -4,7 +4,7 @@
 ;; Inc.
 
 ;; Author: Daniel Pfeiffer <occitan@esperanto.org>
-;; Version: 2.0f
+;; Old-Version: 2.0f
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: languages, unix
 
diff --git a/lisp/progmodes/tcl.el b/lisp/progmodes/tcl.el
index 33aad2d..717008a 100644
--- a/lisp/progmodes/tcl.el
+++ b/lisp/progmodes/tcl.el
@@ -1555,21 +1555,21 @@ The first line is assumed to look like \"#!.../program 
...\"."
                 (char-to-string char)))
             string ""))
 
+
+
 ;;
-;; Bug reporting.
+;; Obsolete.
 ;;
-
 
-;; These are relics kept "just in case".
-(defalias 'tcl-uncomment-region 'uncomment-region)
-(defalias 'tcl-indent-for-comment 'comment-indent)
-(defalias 'add-log-tcl-defun 'tcl-add-log-defun)
-(defalias 'indent-tcl-exp 'tcl-indent-exp)
-(defalias 'calculate-tcl-indent 'tcl-calculate-indent)
-(defalias 'tcl-beginning-of-defun 'beginning-of-defun)
-(defalias 'tcl-end-of-defun 'end-of-defun)
-(defalias 'tcl-mark-defun 'mark-defun)
-(defun tcl-mark () (mark t))
+(define-obsolete-function-alias 'tcl-uncomment-region #'uncomment-region 
"28.1")
+(define-obsolete-function-alias 'tcl-indent-for-comment #'comment-indent 
"28.1")
+(define-obsolete-function-alias 'add-log-tcl-defun #'tcl-add-log-defun "28.1")
+(define-obsolete-function-alias 'indent-tcl-exp #'tcl-indent-exp "28.1")
+(define-obsolete-function-alias 'calculate-tcl-indent #'tcl-calculate-indent 
"28.1")
+(define-obsolete-function-alias 'tcl-beginning-of-defun #'beginning-of-defun 
"28.1")
+(define-obsolete-function-alias 'tcl-end-of-defun #'end-of-defun "28.1")
+(define-obsolete-function-alias 'tcl-mark-defun #'mark-defun "28.1")
+(defun tcl-mark () (declare (obsolete nil "28.1")) (mark t))
 
 (provide 'tcl)
 
diff --git a/lisp/savehist.el b/lisp/savehist.el
index 4e52efe..5d20239 100644
--- a/lisp/savehist.el
+++ b/lisp/savehist.el
@@ -5,7 +5,7 @@
 ;; Author: Hrvoje Nikšić <hrvoje.niksic@avl.com>
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: convenience, minibuffer
-;; Version: 24
+;; Old-Version: 24
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/shell.el b/lisp/shell.el
index 226bdf4..43ad587 100644
--- a/lisp/shell.el
+++ b/lisp/shell.el
@@ -334,6 +334,7 @@ Thus, this does not include the shell's current directory.")
     (define-key map "\t" 'completion-at-point)
     (define-key map (kbd "M-RET") 'shell-resync-dirs)
     (define-key map "\M-?" 'comint-dynamic-list-filename-completions)
+    (define-key map (kbd "C-x n d") 'shell-narrow-to-prompt)
     (define-key map [menu-bar completion]
       (cons "Complete"
            (copy-keymap (lookup-key comint-mode-map [menu-bar completion]))))
@@ -1366,6 +1367,48 @@ Returns t if successful."
   (let ((f (shell-c-a-p-replace-by-expanded-directory)))
     (if f (funcall f))))
 
+(defun shell--prompt-begin-position ()
+  ;; We need this convoluted function because `looking-at-p' does not work on
+  ;; multiline regexps _and_ `re-search-backward' skips the current line.
+  (save-excursion
+    (let ((old-point (point)))
+      (max
+       (save-excursion
+         ;; Right result if not on prompt.
+         (call-interactively #'comint-previous-prompt)
+         (re-search-backward comint-prompt-regexp)
+         (point))
+       (save-excursion
+         ;; Right result if on first char after prompt.
+         (re-search-backward comint-prompt-regexp)
+         (point))
+       (save-excursion
+         ;; Right result if on prompt.
+         (call-interactively #'comint-next-prompt)
+         (re-search-backward comint-prompt-regexp)
+         (if (<= (point) old-point)
+             (point)
+           (point-min)))))))
+
+(defun shell--prompt-end-position ()
+  (save-excursion
+    (goto-char (shell--prompt-begin-position))
+    (comint-next-prompt 1)
+    (point)))
+
+(defun shell-narrow-to-prompt ()
+  "Narrow buffer to the command line (and any following command output) at 
point."
+  (interactive)
+  (let ((begin (shell--prompt-begin-position)))
+    (narrow-to-region
+     begin
+     (save-excursion
+       (goto-char (shell--prompt-end-position))
+       (call-interactively #'comint-next-prompt)
+       (if (= begin (shell--prompt-begin-position))
+           (point-max)
+         (shell--prompt-begin-position))))))
+
 (provide 'shell)
 
 ;;; shell.el ends here
diff --git a/lisp/simple.el b/lisp/simple.el
index bd19969..a29f85b 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -119,13 +119,17 @@ If non-nil, the value is passed directly to `recenter'."
   :version "23.1")
 
 (defcustom next-error-message-highlight nil
-  "If non-nil, highlight the current error message in the `next-error' buffer."
-  :type 'boolean
+  "If non-nil, highlight the current error message in the `next-error' buffer.
+If the value is `keep', highlighting is permanent, so all visited error
+messages are highlighted; this helps to see what messages were visited."
+  :type '(choice (const :tag "Highlight the current error" t)
+                 (const :tag "Highlight all visited errors" keep)
+                 (const :tag "No highlighting" nil))
   :group 'next-error
   :version "28.1")
 
 (defface next-error-message
-  '((t (:inherit highlight)))
+  '((t (:inherit highlight :extend t)))
   "Face used to highlight the current error message in the `next-error' 
buffer."
   :group 'next-error
   :version "28.1")
@@ -482,9 +486,10 @@ buffer causes automatic display of the corresponding 
source code location."
   "Highlight the current error message in the ‘next-error’ buffer."
   (when next-error-message-highlight
     (with-current-buffer error-buffer
-      (when next-error--message-highlight-overlay
+      (when (and next-error--message-highlight-overlay
+                 (not (eq next-error-message-highlight 'keep)))
         (delete-overlay next-error--message-highlight-overlay))
-      (let ((ol (make-overlay (line-beginning-position) (line-end-position))))
+      (let ((ol (make-overlay (line-beginning-position) (1+ 
(line-end-position)))))
         ;; do not override region highlighting
         (overlay-put ol 'priority -50)
         (overlay-put ol 'face 'next-error-message)
diff --git a/lisp/speedbar.el b/lisp/speedbar.el
index aab6a3a..9c5f028 100644
--- a/lisp/speedbar.el
+++ b/lisp/speedbar.el
@@ -1392,7 +1392,7 @@ Argument ARG represents to force a refresh past any 
caches that may exist."
     (if (and (file-exists-p f) (string-match "\\.el\\'" f))
        (progn
          (dframe-select-attached-frame speedbar-frame)
-         (byte-compile-file f nil)
+          (byte-compile-file f)
          (select-frame sf)
          (speedbar-reset-scanners)))
     ))
diff --git a/lisp/textmodes/artist.el b/lisp/textmodes/artist.el
index 7196692..5ce9a90 100644
--- a/lisp/textmodes/artist.el
+++ b/lisp/textmodes/artist.el
@@ -1,10 +1,10 @@
-;;; artist.el --- draw ascii graphics with your mouse
+;;; artist.el --- draw ascii graphics with your mouse -*- lexical-binding: t 
-*-
 
 ;; Copyright (C) 2000-2020 Free Software Foundation, Inc.
 
 ;; Author:       Tomas Abrahamsson <tab@lysator.liu.se>
 ;; Keywords:     mouse
-;; Version:     1.2.6
+;; Old-Version:         1.2.6
 ;; Release-date: 6-Aug-2004
 ;; Location:     http://www.lysator.liu.se/~tab/artist/
 
@@ -1844,9 +1844,7 @@ Return a list (RETURN-CODE STDOUT STDERR)."
                                  nil))
           (tmp-stdout-buffer (get-buffer-create
                               (concat "*artist-" program "*")))
-          (tmp-stderr-file-name (make-temp-file "artist-stdout."))
-          (binary-process-input nil)   ; for msdos
-          (binary-process-output nil))
+          (tmp-stderr-file-name (make-temp-file "artist-stdout.")))
 
       ;; Prepare stdin
       (if stdin (artist-string-to-file stdin tmp-stdin-file-name))
@@ -2721,7 +2719,7 @@ SHAPE-INFO is a list of four straight lines."
 ;; Filling rectangles and squares
 ;;
 
-(defun artist-fill-rect (rect x1 y1 x2 y2)
+(defun artist-fill-rect (_rect x1 y1 x2 y2)
   "Fill rectangle RECT from X1,Y1 to X2,Y2."
   (let ((x (1+ (min x1 x2)))
        (y (1+ (min y1 y2)))
@@ -2733,7 +2731,7 @@ SHAPE-INFO is a list of four straight lines."
        (artist-replace-chars artist-fill-char w)
        (setq y (1+ y))))))
 
-(defun artist-fill-square (square x1 y1 x2 y2)
+(defun artist-fill-square (_square x1 y1 x2 y2)
   "Fill a SQUARE from X1,Y1 to X2,Y2."
   (let* ((square-corners (artist-rect-corners-squarify x1 y1 x2 y2))
         (new-x1 (elt square-corners 0))
@@ -2795,7 +2793,7 @@ to append to the end of the list, when doing free-hand 
drawing)."
   (setq artist-key-poly-point-list (list (cons x1 y1))))
 
 
-(defun artist-pen-set-arrow-points (x1 y1)
+(defun artist-pen-set-arrow-points (_x1 _y1)
   "Set arrow points for pen drawing using X1, Y1.
 Also, the `artist-key-poly-point-list' is reversed."
 
@@ -2996,11 +2994,11 @@ Returns a list of points.  Each point is on the form 
(X1 . Y1)."
       ;; Step to next spray point
       (setq spray-points (cdr spray-points)))))
 
-(defun artist-spray-clear-circle (circle x1 y1 x2 y2)
+(defun artist-spray-clear-circle (circle _x1 _y1 _x2 _y2)
   "Clear circle CIRCLE at X1, Y1 through X2, Y2."
   (artist-undraw-circle circle))
 
-(defun artist-spray-set-radius (circle x1 y1 x2 y2)
+(defun artist-spray-set-radius (_circle x1 y1 x2 y2)
   "Set spray radius from CIRCLE at X1, Y1 through X2, Y2."
   (let ((dx (- x2 x1))
        (dy (- y2 y1)))
@@ -3493,8 +3491,7 @@ POINT-LIST is a list of vectors on the form [X Y 
SAVED-CHAR NEW-CHAR].
 FILL-INFO is a list of vectors on the form [X Y ELLIPSE-WIDTH-ON-THIS-LINE].
 
 The Y-RADIUS must be 0, but the X-RADIUS must not be 0."
-  (let ((point-list nil)
-       (width      (max (- (abs (* 2 x-radius)) 1)))
+  (let ((width      (max (- (abs (* 2 x-radius)) 1)))
        (left-edge  (1+ (- x1 (abs x-radius))))
        (line-char  (if artist-line-char-set artist-line-char ?-))
        (i          0)
@@ -3602,7 +3599,7 @@ FILL-INFO is a list of vectors on the form [X Y 
ELLIPSE-WIDTH-ON-THIS-LINE]."
 ;
 ; Filling ellipses
 ;
-(defun artist-fill-ellipse (ellipse x y x-radius y-radius)
+(defun artist-fill-ellipse (ellipse _x _y _x-radius _y-radius)
   "Fill an ELLIPSE centered at X,Y with radius X-RADIUS and Y-RADIUS."
   (let ((fill-info (aref (artist-2point-get-shapeinfo ellipse) 1)))
     (mapcar
@@ -3722,11 +3719,11 @@ original contents of that area in the buffer."
        (setq x (1+ x)))
       last-x)))
 
-(defun artist-ff-is-topmost-line (x y)
+(defun artist-ff-is-topmost-line (_x y)
   "Determine whether the position X,Y is on the topmost line or not."
   (= y 0))
 
-(defun artist-ff-is-bottommost-line (x y)
+(defun artist-ff-is-bottommost-line (_x y)
   "Determine whether the position X,Y is on the bottommost line or not."
   (save-excursion
     (goto-char (point-max))
@@ -3742,7 +3739,6 @@ original contents of that area in the buffer."
 (defun artist-flood-fill (x1 y1)
   "Flood-fill starting at X1, Y1.  Fill with the char in `artist-fill-char'."
   (let ((stack nil)
-       (input-queue nil)
        ;; We are flood-filling the area that has this character.
        (c     (artist-get-char-at-xy-conv x1 y1))
         (artist-fill-char (if artist-fill-char-set
@@ -3884,7 +3880,7 @@ Optional argument STATE can be used to set state (default 
is nil)."
     (setq artist-arrow-point-2 (artist-make-arrow-point xn yn dirn))))
 
 
-(defun artist-set-arrow-points-for-2points (shape x1 y1 x2 y2)
+(defun artist-set-arrow-points-for-2points (shape _x1 _y1 _x2 _y2)
   "Generic function for setting arrow-points for 2-point shapes.
 The 2-point shape SHAPE is drawn from X1, Y1 to X2, Y2."
   (let* ((endpoint1 (artist-2point-get-endpoint1 shape))
@@ -3906,28 +3902,24 @@ The 2-point shape SHAPE is drawn from X1, Y1 to X2, Y2."
 ;; on the draw-how
 ;;
 
-(defun artist-key-undraw-continously (x y)
+(defun artist-key-undraw-continously (_x _y)
   "Undraw current continuous shape with point at X, Y."
   ;; No undraw-info for continuous shapes
   nil)
 
-(defun artist-key-undraw-poly (x y)
+(defun artist-key-undraw-poly (_x _y)
   "Undraw current poly shape with point at X, Y."
-  (let ((undraw-fn (artist-go-get-undraw-fn-from-symbol artist-curr-go))
-       (x1        (artist-endpoint-get-x artist-key-endpoint1))
-       (y1        (artist-endpoint-get-y artist-key-endpoint1)))
+  (let ((undraw-fn (artist-go-get-undraw-fn-from-symbol artist-curr-go)))
     (artist-funcall undraw-fn artist-key-shape)))
 
-(defun artist-key-undraw-1point (x y)
+(defun artist-key-undraw-1point (_x _y)
   "Undraw current 1-point shape at X, Y."
   ;; No undraw-info for 1-point shapes
   nil)
 
-(defun artist-key-undraw-2points (x y)
+(defun artist-key-undraw-2points (_x _y)
   "Undraw current 2-point shape at X, Y."
-  (let ((undraw-fn (artist-go-get-undraw-fn-from-symbol artist-curr-go))
-       (x1        (artist-endpoint-get-x artist-key-endpoint1))
-       (y1        (artist-endpoint-get-y artist-key-endpoint1)))
+  (let ((undraw-fn (artist-go-get-undraw-fn-from-symbol artist-curr-go)))
     (artist-funcall undraw-fn artist-key-shape)))
 
 (defun artist-key-undraw-common ()
@@ -4071,7 +4063,7 @@ Trimming here means removing white space at end of a 
line."
        (setq artist-key-shape (artist-funcall draw-fn x1 y1 x2 y2))))))
 
 
-(defun artist-key-do-continously-1point (x y)
+(defun artist-key-do-continously-1point (_x _y)
   "Update current 1-point shape at X,Y."
   ;; Nothing to do continuously for operations
   ;; where we have only one input point
@@ -4271,8 +4263,7 @@ If optional argument THIS-IS-LAST-POINT is non-nil, this 
point is the last."
 
 (defun artist-key-set-point-1point (x y)
   "Set point for current 1-point shape at X,Y."
-  (let ((draw-fn      (artist-go-get-draw-fn-from-symbol artist-curr-go))
-       (init-fn      (artist-go-get-init-fn-from-symbol artist-curr-go))
+  (let ((init-fn      (artist-go-get-init-fn-from-symbol artist-curr-go))
        (prep-fill-fn (artist-go-get-prep-fill-fn-from-symbol artist-curr-go))
        (exit-fn      (artist-go-get-exit-fn-from-symbol artist-curr-go))
        (draw-fn      (artist-go-get-draw-fn-from-symbol artist-curr-go))
@@ -4802,7 +4793,7 @@ If optional argument STATE is positive, turn borders on."
         (orig-draw-region-min-y artist-draw-region-min-y)
         (orig-draw-region-max-y artist-draw-region-max-y)
         (orig-pointer-shape (if (eq window-system 'x) x-pointer-shape nil))
-        (echoq-keystrokes 10000)       ; a lot of seconds
+        (echo-keystrokes 0)    ; Don't echo unfinished commands.
         ;; Remember original binding for the button-up event to this
         ;; button-down event.
         (key (artist-compute-up-event-key ev))
@@ -4918,7 +4909,7 @@ If optional argument STATE is positive, turn borders on."
 ;; Mouse routines
 ;;
 
-(defsubst artist-shift-has-changed (shift-state ev)
+(defsubst artist-shift-has-changed (_shift-state _ev)
   "From the last SHIFT-STATE and EV, determine if the shift-state has changed."
   ;; This one simply doesn't work.
   ;;
@@ -4972,8 +4963,7 @@ The event, EV, is the mouse event."
         (ev-start-pos (artist-coord-win-to-buf (posn-col-row ev-start)))
         (x1           (artist--adjust-x (car ev-start-pos)))
         (y1           (cdr ev-start-pos))
-        (shape)
-        (timer))
+        (timer nil))
     (select-window (posn-window ev-start))
     (artist-funcall init-fn x1 y1)
     (if (not artist-rubber-banding)
@@ -5017,7 +5007,7 @@ The event, EV, is the mouse event."
                     (setq draw-fn     (artist-go-get-draw-fn-from-symbol op))))
 
               ;; Draw the new shape
-              (setq shape (artist-funcall draw-fn x1 y1))
+              (artist-funcall draw-fn x1 y1)
               (artist-move-to-xy x1 y1)
 
               ;; Start the timer to call `draw-fn' repeatedly every
@@ -5262,7 +5252,6 @@ Operation is done once.  The event, EV, is the mouse 
event."
         (shifted      (artist-go-get-symbol-shift artist-curr-go t))
         (shift-state  (artist-event-is-shifted ev))
         (op           (if shift-state shifted unshifted))
-        (draw-how     (artist-go-get-draw-how-from-symbol op))
         (init-fn      (artist-go-get-init-fn-from-symbol op))
         (prep-fill-fn (artist-go-get-prep-fill-fn-from-symbol op))
         (exit-fn      (artist-go-get-exit-fn-from-symbol op))
@@ -5394,8 +5383,7 @@ The event, EV, is the mouse event."
   (interactive)
   (require 'reporter)
   (if (y-or-n-p "Do you want to submit a bug report on Artist? ")
-      (let ((to   artist-maintainer-address)
-           (vars '(window-system
+      (let ((vars '(window-system
                    window-system-version
                    ;;
                    artist-rubber-banding
diff --git a/lisp/textmodes/picture.el b/lisp/textmodes/picture.el
index 7a82f8f..5216812 100644
--- a/lisp/textmodes/picture.el
+++ b/lisp/textmodes/picture.el
@@ -1,4 +1,4 @@
-;;; picture.el --- "Picture mode" -- editing using quarter-plane screen model
+;;; picture.el --- "Picture mode" -- editing using quarter-plane screen model 
-*- lexical-binding: t -*-
 
 ;; Copyright (C) 1985, 1994, 2001-2020 Free Software Foundation, Inc.
 
diff --git a/lisp/textmodes/tex-mode.el b/lisp/textmodes/tex-mode.el
index 11db25c..37ab11a 100644
--- a/lisp/textmodes/tex-mode.el
+++ b/lisp/textmodes/tex-mode.el
@@ -3541,6 +3541,8 @@ There might be text before point."
       (process-send-region tex-chktex--process (point-min) (point-max))
       (process-send-eof tex-chktex--process))))
 
+(make-obsolete-variable 'tex-mode-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 (run-hooks 'tex-mode-load-hook)
 
 (provide 'tex-mode)
diff --git a/lisp/time.el b/lisp/time.el
index cb3a847..63773d4 100644
--- a/lisp/time.el
+++ b/lisp/time.el
@@ -1,4 +1,4 @@
-;;; time.el --- display time, load and mail indicator in mode line of Emacs
+;;; time.el --- display time, load and mail indicator in mode line of Emacs  
-*- lexical-binding: t -*-
 
 ;; Copyright (C) 1985-1987, 1993-1994, 1996, 2000-2020 Free Software
 ;; Foundation, Inc.
@@ -284,6 +284,60 @@ Switches from the 1 to 5 to 15 minute load average, and 
then back to 1."
   (defvar month)
   (defvar dayname))
 
+(defun display-time-update--load ()
+  (if (null display-time-load-average)
+      ""
+    (condition-case ()
+        ;; Do not show values less than
+        ;; `display-time-load-average-threshold'.
+        (if (> (* display-time-load-average-threshold 100)
+               (nth display-time-load-average (load-average)))
+            ""
+          ;; The load average number is mysterious, so
+          ;; provide some help.
+          (let ((str (format " %03d"
+                             (nth display-time-load-average
+                                  (load-average)))))
+            (propertize
+             (concat (substring str 0 -2) "." (substring str -2))
+             'local-map (make-mode-line-mouse-map
+                         'mouse-2 'display-time-next-load-average)
+             'mouse-face 'mode-line-highlight
+             'help-echo (concat
+                         "System load average for past "
+                         (if (= 0 display-time-load-average)
+                             "1 minute"
+                           (if (= 1 display-time-load-average)
+                               "5 minutes"
+                             "15 minutes"))
+                         "; mouse-2: next"))))
+      (error ""))))
+
+(defun display-time-update--mail ()
+  (let ((mail-spool-file (or display-time-mail-file
+                             (getenv "MAIL")
+                             (concat rmail-spool-directory
+                                     (user-login-name)))))
+    (cond
+     (display-time-mail-function
+      (funcall display-time-mail-function))
+     (display-time-mail-directory
+      (display-time-mail-check-directory))
+     ((and (stringp mail-spool-file)
+           (or (null display-time-server-down-time)
+               ;; If have been down for 20 min, try again.
+               (time-less-p 1200 (time-since
+                              display-time-server-down-time))))
+      (let ((start-time (current-time)))
+        (prog1
+            (display-time-file-nonempty-p mail-spool-file)
+          ;; Record whether mail file is accessible.
+          (setq display-time-server-down-time
+                (let ((end-time (current-time)))
+                  (and (time-less-p 20 (time-subtract
+                                    end-time start-time))
+                       (float-time end-time))))))))))
+
 (defun display-time-update ()
   "Update the display-time info for the mode line.
 However, don't redisplay right now.
@@ -291,57 +345,9 @@ However, don't redisplay right now.
 This is used for things like Rmail `g' that want to force an
 update which can wait for the next redisplay."
   (let* ((now (current-time))
-        (time (current-time-string now))
-         (load (if (null display-time-load-average)
-                  ""
-                (condition-case ()
-                    ;; Do not show values less than
-                    ;; `display-time-load-average-threshold'.
-                    (if (> (* display-time-load-average-threshold 100)
-                           (nth display-time-load-average (load-average)))
-                        ""
-                      ;; The load average number is mysterious, so
-                      ;; provide some help.
-                      (let ((str (format " %03d"
-                                         (nth display-time-load-average
-                                              (load-average)))))
-                        (propertize
-                         (concat (substring str 0 -2) "." (substring str -2))
-                         'local-map (make-mode-line-mouse-map
-                                     'mouse-2 'display-time-next-load-average)
-                         'mouse-face 'mode-line-highlight
-                         'help-echo (concat
-                                     "System load average for past "
-                                     (if (= 0 display-time-load-average)
-                                         "1 minute"
-                                       (if (= 1 display-time-load-average)
-                                           "5 minutes"
-                                         "15 minutes"))
-                                     "; mouse-2: next"))))
-                  (error ""))))
-         (mail-spool-file (or display-time-mail-file
-                              (getenv "MAIL")
-                              (concat rmail-spool-directory
-                                      (user-login-name))))
-        (mail (cond
-               (display-time-mail-function
-                (funcall display-time-mail-function))
-               (display-time-mail-directory
-                (display-time-mail-check-directory))
-               ((and (stringp mail-spool-file)
-                     (or (null display-time-server-down-time)
-                         ;; If have been down for 20 min, try again.
-                         (time-less-p 1200 (time-since
-                                            display-time-server-down-time))))
-                (let ((start-time (current-time)))
-                  (prog1
-                      (display-time-file-nonempty-p mail-spool-file)
-                    ;; Record whether mail file is accessible.
-                    (setq display-time-server-down-time
-                          (let ((end-time (current-time)))
-                            (and (time-less-p 20 (time-subtract
-                                                  end-time start-time))
-                                 (float-time end-time)))))))))
+         (time (current-time-string now))
+         (load (display-time-update--load))
+         (mail (display-time-update--mail))
          (24-hours (substring time 11 13))
          (hour (string-to-number 24-hours))
          (12-hours (int-to-string (1+ (% (+ hour 11) 12))))
diff --git a/lisp/url/url-vars.el b/lisp/url/url-vars.el
index e35823a..f9dce24 100644
--- a/lisp/url/url-vars.el
+++ b/lisp/url/url-vars.el
@@ -1,4 +1,4 @@
-;;; url-vars.el --- Variables for Uniform Resource Locator tool
+;;; url-vars.el --- Variables for Uniform Resource Locator tool  -*- 
lexical-binding:t -*-
 
 ;; Copyright (C) 1996-1999, 2001, 2004-2020 Free Software Foundation,
 ;; Inc.
diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el
index d586afb..7c9ad25 100644
--- a/lisp/vc/diff-mode.el
+++ b/lisp/vc/diff-mode.el
@@ -1860,7 +1860,10 @@ SWITCHED is non-nil if the patch is already applied."
           (buf (if revision
                     (let ((vc-find-revision-no-save t))
                       (vc-find-revision (expand-file-name file) revision 
diff-vc-backend))
-                  (find-file-noselect file))))
+                  ;; NOPROMPT is only non-nil when called from
+                  ;; `which-function-mode', so avoid "File x changed
+                  ;; on disk. Reread from disk?" warnings.
+                  (find-file-noselect file noprompt))))
       ;; Update the user preference if he so wished.
       (when (> (prefix-numeric-value other-file) 8)
        (setq diff-jump-to-old-file other))
diff --git a/lisp/whitespace.el b/lisp/whitespace.el
index 6690578..94ed6dc 100644
--- a/lisp/whitespace.el
+++ b/lisp/whitespace.el
@@ -2473,7 +2473,8 @@ It should be added buffer-locally to 
`write-file-functions'."
 
 (provide 'whitespace)
 
-
+(make-obsolete-variable 'whitespace-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 (run-hooks 'whitespace-load-hook)
 
 
diff --git a/lisp/wid-edit.el b/lisp/wid-edit.el
index 6568cd2..009c6b4 100644
--- a/lisp/wid-edit.el
+++ b/lisp/wid-edit.el
@@ -2721,7 +2721,10 @@ Return an alist of (TYPE MATCH)."
 (define-widget 'insert-button 'push-button
   "An insert button for the `editable-list' widget."
   :tag "INS"
-  :help-echo "Insert a new item into the list at this position."
+  :help-echo (lambda (widget)
+               (if (widget-get (widget-get widget :parent) :last-deleted)
+                   "Insert back the last deleted item from this list, at this 
position."
+                 "Insert a new item into the list at this position."))
   :action 'widget-insert-button-action)
 
 (defun widget-insert-button-action (widget &optional _event)
@@ -2734,7 +2737,7 @@ Return an alist of (TYPE MATCH)."
 (define-widget 'delete-button 'push-button
   "A delete button for the `editable-list' widget."
   :tag "DEL"
-  :help-echo "Delete this item from the list."
+  :help-echo "Delete this item from the list, saving it for later reinsertion."
   :action 'widget-delete-button-action)
 
 (defun widget-delete-button-action (widget &optional _event)
@@ -2824,9 +2827,18 @@ Return an alist of (TYPE MATCH)."
     (cons found value)))
 
 (defun widget-editable-list-insert-before (widget before)
-  ;; Insert a new child in the list of children.
+  "Insert a new widget as a child of WIDGET.
+
+If there is a recently deleted child, the new widget is that deleted child.
+Otherwise, the new widget is the default child of WIDGET.
+
+The new widget gets inserted at the position of the BEFORE child."
   (save-excursion
     (let ((children (widget-get widget :children))
+          (last-deleted (when-let ((lst (widget-get widget :last-deleted)))
+                          (prog1
+                              (pop lst)
+                            (widget-put widget :last-deleted lst))))
          (inhibit-read-only t)
          (inhibit-modification-hooks t))
       (cond (before
@@ -2834,7 +2846,11 @@ Return an alist of (TYPE MATCH)."
            (t
             (goto-char (widget-get widget :value-pos))))
       (let ((child (widget-editable-list-entry-create
-                   widget nil nil)))
+                    widget (and last-deleted
+                                (widget-apply last-deleted
+                                              :value-to-external
+                                              (widget-get last-deleted 
:value)))
+                    last-deleted)))
        (when (< (widget-get child :entry-from) (widget-get widget :from))
          (set-marker (widget-get widget :from)
                      (widget-get child :entry-from)))
@@ -2847,6 +2863,15 @@ Return an alist of (TYPE MATCH)."
   (widget-apply widget :notify widget))
 
 (defun widget-editable-list-delete-at (widget child)
+  "Delete the widget CHILD from the known children of widget WIDGET.
+
+Save CHILD into the :last-deleted list, so it can be inserted later."
+  ;; Save the current value of CHILD, to use if the user later inserts the
+  ;; widget.
+  (widget-put child :value (widget-apply child :value-get))
+  (let ((lst (widget-get widget :last-deleted)))
+    (push child lst)
+    (widget-put widget :last-deleted lst))
   ;; Delete child from list of children.
   (save-excursion
     (let ((buttons (copy-sequence (widget-get widget :buttons)))
@@ -3559,7 +3584,7 @@ To use this type, you must define :match or 
:match-alternatives."
   :match 'widget-restricted-sexp-match
   :value-to-internal (lambda (widget value)
                       (if (widget-apply widget :match value)
-                          (prin1-to-string value)
+                           (widget-sexp-value-to-internal widget value)
                         value)))
 
 (defun widget-restricted-sexp-match (widget value)
diff --git a/lisp/woman.el b/lisp/woman.el
index eeaccea..96ae7fe 100644
--- a/lisp/woman.el
+++ b/lisp/woman.el
@@ -2289,6 +2289,12 @@ Currently set only from \\='\\\" t in the first line of 
the source file.")
     (setq fill-column woman-fill-column
          tab-width woman-tab-width)
 
+    ;; Ignore the \, and \/ kerning operators.  See
+    ;; 
https://www.gnu.org/software/groff/manual/groff.html#Ligatures-and-Kerning
+    (goto-char (point-min))
+    (while (re-search-forward "\\\\[,/]" nil t)
+      (replace-match "" t t))
+
     ;; Hide unpaddable and digit-width spaces \(space) and \0:
     (goto-char from)
     (while (re-search-forward "\\\\[ 0]" nil t)
diff --git a/src/dired.c b/src/dired.c
index 1584b6a..8256f26 100644
--- a/src/dired.c
+++ b/src/dired.c
@@ -293,7 +293,8 @@ DEFUN ("directory-files", Fdirectory_files, 
Sdirectory_files, 1, 4, 0,
 There are three optional arguments:
 If FULL is non-nil, return absolute file names.  Otherwise return names
  that are relative to the specified directory.
-If MATCH is non-nil, mention only file names that match the regexp MATCH.
+If MATCH is non-nil, mention only file names whose non-directory part
+ matches the regexp MATCH.
 If NOSORT is non-nil, the list is not sorted--its order is unpredictable.
  Otherwise, the list returned is sorted with `string-lessp'.
  NOSORT is useful if you plan to sort the result yourself.  */)
@@ -325,11 +326,12 @@ by `file-attributes'.
 This function accepts four optional arguments:
 If FULL is non-nil, return absolute file names.  Otherwise return names
  that are relative to the specified directory.
-If MATCH is non-nil, mention only file names that match the regexp MATCH.
+If MATCH is non-nil, mention only file names whose non-directory part
+ matches the regexp MATCH.
 If NOSORT is non-nil, the list is not sorted--its order is unpredictable.
  NOSORT is useful if you plan to sort the result yourself.
 ID-FORMAT specifies the preferred format of attributes uid and gid, see
-`file-attributes' for further documentation.
+ `file-attributes' for further documentation.
 On MS-Windows, performance depends on `w32-get-true-file-attributes',
 which see.  */)
   (Lisp_Object directory, Lisp_Object full, Lisp_Object match,
diff --git a/src/doc.c b/src/doc.c
index 8a4f885..d4e3ce2 100644
--- a/src/doc.c
+++ b/src/doc.c
@@ -420,7 +420,7 @@ string is passed through `substitute-command-keys'.  */)
     }
 
   if (NILP (raw))
-    doc = Fsubstitute_command_keys (doc);
+    doc = call1 (Qsubstitute_command_keys, doc);
   return doc;
 }
 
@@ -477,7 +477,7 @@ aren't strings.  */)
     tem = Feval (tem, Qnil);
 
   if (NILP (raw) && STRINGP (tem))
-    tem = Fsubstitute_command_keys (tem);
+    tem = call1 (Qsubstitute_command_keys, tem);
   return tem;
 }
 
@@ -702,315 +702,34 @@ text_quoting_style (void)
     return CURVE_QUOTING_STYLE;
 }
 
-DEFUN ("substitute-command-keys", Fsubstitute_command_keys,
-       Ssubstitute_command_keys, 1, 1, 0,
-       doc: /* Substitute key descriptions for command names in STRING.
-Each substring of the form \\=\\[COMMAND] is replaced by either a
-keystroke sequence that invokes COMMAND, or "M-x COMMAND" if COMMAND
-is not on any keys.
-
-Each substring of the form \\=\\{MAPVAR} is replaced by a summary of
-the value of MAPVAR as a keymap.  This summary is similar to the one
-produced by `describe-bindings'.  The summary ends in two newlines
-\(used by the helper function `help-make-xrefs' to find the end of the
-summary).
-
-Each substring of the form \\=\\<MAPVAR> specifies the use of MAPVAR
-as the keymap for future \\=\\[COMMAND] substrings.
-
-Each grave accent \\=` is replaced by left quote, and each apostrophe \\='
-is replaced by right quote.  Left and right quote characters are
-specified by `text-quoting-style'.
-
-\\=\\= quotes the following character and is discarded; thus, \\=\\=\\=\\= 
puts \\=\\=
-into the output, \\=\\=\\=\\[ puts \\=\\[ into the output, and \\=\\=\\=` puts 
\\=` into the
-output.
-
-Return the original STRING if no substitutions are made.
-Otherwise, return a new string (without any text properties).  */)
-  (Lisp_Object string)
+/* This is just a Lisp wrapper for text_quoting_style above.  */
+DEFUN ("get-quoting-style", Fget_quoting_style,
+       Sget_quoting_style, 0, 0, 0,
+       doc: /* Return the current effective text quoting style.
+See variable `text-quoting-style'.  */)
+  (void)
 {
-  char *buf;
-  bool changed = false;
-  bool nonquotes_changed = false;
-  unsigned char *strp;
-  char *bufp;
-  ptrdiff_t idx;
-  ptrdiff_t bsize;
-  Lisp_Object tem;
-  Lisp_Object keymap;
-  unsigned char const *start;
-  ptrdiff_t length, length_byte;
-  Lisp_Object name;
-  ptrdiff_t nchars;
-
-  if (NILP (string))
-    return Qnil;
-
-  /* If STRING contains non-ASCII unibyte data, process its
-     properly-encoded multibyte equivalent instead.  This simplifies
-     the implementation and is OK since substitute-command-keys is
-     intended for use only on text strings.  Keep STRING around, since
-     it will be returned if no changes occur.  */
-  Lisp_Object str = Fstring_make_multibyte (string);
-
-  enum text_quoting_style quoting_style = text_quoting_style ();
-
-  nchars = 0;
-
-  /* KEYMAP is either nil (which means search all the active keymaps)
-     or a specified local map (which means search just that and the
-     global map).  If non-nil, it might come from Voverriding_local_map,
-     or from a \\<mapname> construct in STRING itself..  */
-  keymap = Voverriding_local_map;
-
-  ptrdiff_t strbytes = SBYTES (str);
-  bsize = strbytes;
-
-  /* Fixed-size stack buffer.  */
-  char sbuf[MAX_ALLOCA];
-
-  /* Heap-allocated buffer, if any.  */
-  char *abuf;
-
-  /* Extra room for expansion due to replacing ‘\[]’ with ‘M-x ’.  */
-  enum { EXTRA_ROOM = sizeof "M-x " - sizeof "\\[]" };
-
-  ptrdiff_t count = SPECPDL_INDEX ();
-
-  if (bsize <= sizeof sbuf - EXTRA_ROOM)
-    {
-      abuf = NULL;
-      buf = sbuf;
-      bsize = sizeof sbuf;
-    }
-  else
-    {
-      buf = abuf = xpalloc (NULL, &bsize, EXTRA_ROOM, STRING_BYTES_BOUND, 1);
-      record_unwind_protect_ptr (xfree, abuf);
-    }
-  bufp = buf;
-
-  strp = SDATA (str);
-  while (strp < SDATA (str) + strbytes)
-    {
-      unsigned char *close_bracket;
-
-      if (strp[0] == '\\' && strp[1] == '='
-         && strp + 2 < SDATA (str) + strbytes)
-       {
-         /* \= quotes the next character;
-            thus, to put in \[ without its special meaning, use \=\[.  */
-         changed = nonquotes_changed = true;
-         strp += 2;
-         /* Fall through to copy one char.  */
-       }
-      else if (strp[0] == '\\' && strp[1] == '['
-              && (close_bracket
-                  = memchr (strp + 2, ']',
-                            SDATA (str) + strbytes - (strp + 2))))
-       {
-         bool follow_remap = 1;
-
-         start = strp + 2;
-         length_byte = close_bracket - start;
-         idx = close_bracket + 1 - SDATA (str);
-
-         name = Fintern (make_string ((char *) start, length_byte), Qnil);
-
-       do_remap:
-         tem = Fwhere_is_internal (name, keymap, Qt, Qnil, Qnil);
-
-         if (VECTORP (tem) && ASIZE (tem) > 1
-             && EQ (AREF (tem, 0), Qremap) && SYMBOLP (AREF (tem, 1))
-             && follow_remap)
-           {
-             name = AREF (tem, 1);
-             follow_remap = 0;
-             goto do_remap;
-           }
-
-         /* Fwhere_is_internal can GC, so take relocation of string
-            contents into account.  */
-         strp = SDATA (str) + idx;
-         start = strp - length_byte - 1;
-
-         if (NILP (tem))       /* but not on any keys */
-           {
-             memcpy (bufp, "M-x ", 4);
-             bufp += 4;
-             nchars += 4;
-             length = multibyte_chars_in_text (start, length_byte);
-             goto subst;
-           }
-         else
-           {                   /* function is on a key */
-             tem = Fkey_description (tem, Qnil);
-             goto subst_string;
-           }
-       }
-      /* \{foo} is replaced with a summary of the keymap (symbol-value foo).
-        \<foo> just sets the keymap used for \[cmd].  */
-      else if (strp[0] == '\\' && (strp[1] == '{' || strp[1] == '<')
-              && (close_bracket
-                  = memchr (strp + 2, strp[1] == '{' ? '}' : '>',
-                            SDATA (str) + strbytes - (strp + 2))))
-       {
-        {
-         bool generate_summary = strp[1] == '{';
-         /* This is for computing the SHADOWS arg for describe_map_tree.  */
-         Lisp_Object active_maps = Fcurrent_active_maps (Qnil, Qnil);
-         ptrdiff_t count = SPECPDL_INDEX ();
-
-         start = strp + 2;
-         length_byte = close_bracket - start;
-         idx = close_bracket + 1 - SDATA (str);
-
-         /* Get the value of the keymap in TEM, or nil if undefined.
-            Do this while still in the user's current buffer
-            in case it is a local variable.  */
-         name = Fintern (make_string ((char *) start, length_byte), Qnil);
-         tem = Fboundp (name);
-         if (! NILP (tem))
-           {
-             tem = Fsymbol_value (name);
-             if (! NILP (tem))
-               tem = get_keymap (tem, 0, 1);
-           }
-
-         /* Now switch to a temp buffer.  */
-         struct buffer *oldbuf = current_buffer;
-         set_buffer_internal (XBUFFER (Vprin1_to_string_buffer));
-         /* This is for an unusual case where some after-change
-            function uses 'format' or 'prin1' or something else that
-            will thrash Vprin1_to_string_buffer we are using.  */
-         specbind (Qinhibit_modification_hooks, Qt);
-
-         if (NILP (tem))
-           {
-             name = Fsymbol_name (name);
-             AUTO_STRING (msg_prefix, "\nUses keymap `");
-             insert1 (Fsubstitute_command_keys (msg_prefix));
-             insert_from_string (name, 0, 0,
-                                 SCHARS (name),
-                                 SBYTES (name), 1);
-             AUTO_STRING (msg_suffix, "', which is not currently defined.\n");
-             insert1 (Fsubstitute_command_keys (msg_suffix));
-             if (!generate_summary)
-               keymap = Qnil;
-           }
-         else if (!generate_summary)
-           keymap = tem;
-         else
-           {
-             /* Get the list of active keymaps that precede this one.
-                If this one's not active, get nil.  */
-             Lisp_Object earlier_maps
-               = Fcdr (Fmemq (tem, Freverse (active_maps)));
-             describe_map_tree (tem, 1, Fnreverse (earlier_maps),
-                                Qnil, 0, 1, 0, 0, 1);
-           }
-         tem = Fbuffer_string ();
-         Ferase_buffer ();
-         set_buffer_internal (oldbuf);
-         unbind_to (count, Qnil);
-        }
-
-       subst_string:
-         /* Convert non-ASCII unibyte data to properly-encoded multibyte,
-            for the same reason STRING was converted to STR.  */
-         tem = Fstring_make_multibyte (tem);
-         start = SDATA (tem);
-         length = SCHARS (tem);
-         length_byte = SBYTES (tem);
-       subst:
-         nonquotes_changed = true;
-       subst_quote:
-         changed = true;
-         {
-           ptrdiff_t offset = bufp - buf;
-           ptrdiff_t avail = bsize - offset;
-           ptrdiff_t need = strbytes - idx;
-           if (INT_ADD_WRAPV (need, length_byte + EXTRA_ROOM, &need))
-             string_overflow ();
-           if (avail < need)
-             {
-               abuf = xpalloc (abuf, &bsize, need - avail,
-                               STRING_BYTES_BOUND, 1);
-               if (buf == sbuf)
-                 {
-                   record_unwind_protect_ptr (xfree, abuf);
-                   memcpy (abuf, sbuf, offset);
-                 }
-               else
-                 set_unwind_protect_ptr (count, xfree, abuf);
-               buf = abuf;
-               bufp = buf + offset;
-             }
-           memcpy (bufp, start, length_byte);
-           bufp += length_byte;
-           nchars += length;
-
-           /* Some of the previous code can GC, so take relocation of
-              string contents into account.  */
-           strp = SDATA (str) + idx;
-
-           continue;
-         }
-       }
-      else if ((strp[0] == '`' || strp[0] == '\'')
-              && quoting_style == CURVE_QUOTING_STYLE)
-       {
-         start = (unsigned char const *) (strp[0] == '`' ? uLSQM : uRSQM);
-         length = 1;
-         length_byte = sizeof uLSQM - 1;
-         idx = strp - SDATA (str) + 1;
-         goto subst_quote;
-       }
-      else if (strp[0] == '`' && quoting_style == STRAIGHT_QUOTING_STYLE)
-       {
-         *bufp++ = '\'';
-         strp++;
-         nchars++;
-         changed = true;
-         continue;
-       }
-
-      /* Copy one char.  */
-      do
-       *bufp++ = *strp++;
-      while (! CHAR_HEAD_P (*strp));
-      nchars++;
-    }
-
-  if (changed)                 /* don't bother if nothing substituted */
+  switch (text_quoting_style ())
     {
-      tem = make_string_from_bytes (buf, nchars, bufp - buf);
-      if (!nonquotes_changed)
-       {
-         /* Nothing has changed other than quoting, so copy the string’s
-            text properties.  FIXME: Text properties should survive other
-            changes too; see bug#17052.  */
-         INTERVAL interval_copy = copy_intervals (string_intervals (string),
-                                                  0, SCHARS (string));
-         if (interval_copy)
-           {
-             set_interval_object (interval_copy, tem);
-             set_string_intervals (tem, interval_copy);
-           }
-       }
+    case STRAIGHT_QUOTING_STYLE:
+      return Qstraight;
+    case CURVE_QUOTING_STYLE:
+      return Qcurve;
+    case GRAVE_QUOTING_STYLE:
+    default:
+      return Qgrave;
     }
-  else
-    tem = string;
-  return unbind_to (count, tem);
 }
+
 
 void
 syms_of_doc (void)
 {
+  DEFSYM (Qsubstitute_command_keys, "substitute-command-keys");
   DEFSYM (Qfunction_documentation, "function-documentation");
   DEFSYM (Qgrave, "grave");
   DEFSYM (Qstraight, "straight");
+  DEFSYM (Qcurve, "curve");
 
   DEFVAR_LISP ("internal-doc-file-name", Vdoc_file_name,
               doc: /* Name of file containing documentation strings of 
built-in symbols.  */);
@@ -1042,5 +761,5 @@ otherwise.  */);
   defsubr (&Sdocumentation);
   defsubr (&Sdocumentation_property);
   defsubr (&Ssnarf_documentation);
-  defsubr (&Ssubstitute_command_keys);
+  defsubr (&Sget_quoting_style);
 }
diff --git a/src/eval.c b/src/eval.c
index 84631f4..09e12bd 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -553,7 +553,10 @@ usage: (quote ARG)  */)
 DEFUN ("function", Ffunction, Sfunction, 1, UNEVALLED, 0,
        doc: /* Like `quote', but preferred for objects which are functions.
 In byte compilation, `function' causes its argument to be handled by
-the byte compiler.  `quote' cannot do that.
+the byte compiler.  Similarly, when expanding macros and expressions,
+ARG can be examined and possibly expanded.  If `quote' is used
+instead, this doesn't happen.
+
 usage: (function ARG)  */)
   (Lisp_Object args)
 {
diff --git a/src/ftcrfont.c b/src/ftcrfont.c
index 4892a34..a10308c 100644
--- a/src/ftcrfont.c
+++ b/src/ftcrfont.c
@@ -139,7 +139,8 @@ ftcrfont_open (struct frame *f, Lisp_Object entity, int 
pixel_size)
 
   FcPatternDestroy (pat);
   font_face = cairo_ft_font_face_create_for_pattern (match);
-  if (!font_face)
+  if (!font_face
+      || cairo_font_face_status (font_face) != CAIRO_STATUS_SUCCESS)
     {
       unblock_input ();
       FcPatternDestroy (match);
@@ -154,6 +155,18 @@ ftcrfont_open (struct frame *f, Lisp_Object entity, int 
pixel_size)
   cairo_font_face_destroy (font_face);
   cairo_font_options_destroy (options);
   unblock_input ();
+  if (!scaled_font
+      || cairo_scaled_font_status (scaled_font) != CAIRO_STATUS_SUCCESS)
+    {
+      FcPatternDestroy (match);
+      return Qnil;
+    }
+  ft_face = cairo_ft_scaled_font_lock_face (scaled_font);
+  if (!ft_face)
+    {
+      FcPatternDestroy (match);
+      return Qnil;
+    }
 
   font_object = font_build_object (VECSIZE (struct font_info),
                                   AREF (entity, FONT_TYPE_INDEX),
@@ -234,7 +247,6 @@ ftcrfont_open (struct frame *f, Lisp_Object entity, int 
pixel_size)
       font->descent = font->height - font->ascent;
     }
 
-  ft_face = cairo_ft_scaled_font_lock_face (scaled_font);
   if (XFIXNUM (AREF (entity, FONT_SIZE_INDEX)) == 0)
     {
       int upEM = ft_face->units_per_EM;
diff --git a/src/image.c b/src/image.c
index 25d5af8..5f6d9f4 100644
--- a/src/image.c
+++ b/src/image.c
@@ -9736,7 +9736,7 @@ svg_load_image (struct frame *f, struct image *img, char 
*contents,
                ptrdiff_t size, char *filename)
 {
   RsvgHandle *rsvg_handle;
-  RsvgDimensionData dimension_data;
+  double viewbox_width, viewbox_height;
   GError *err = NULL;
   GdkPixbuf *pixbuf;
   int width;
@@ -9789,15 +9789,38 @@ svg_load_image (struct frame *f, struct image *img, 
char *contents,
 #endif
 
   /* Get the image dimensions.  */
+#if LIBRSVG_CHECK_VERSION (2, 46, 0)
+  RsvgRectangle zero_rect, viewbox;
+
+  rsvg_handle_get_geometry_for_layer (rsvg_handle, NULL,
+                                      &zero_rect, &viewbox,
+                                      NULL, NULL);
+  viewbox_width = viewbox.x + viewbox.width;
+  viewbox_height = viewbox.y + viewbox.height;
+#else
+  /* The function used above to get the geometry of the visible area
+     of the SVG are only available in librsvg 2.46 and above, so in
+     certain circumstances this code path can result in some parts of
+     the SVG being cropped.  */
+  RsvgDimensionData dimension_data;
+
   rsvg_handle_get_dimensions (rsvg_handle, &dimension_data);
 
+  viewbox_width = dimension_data.width;
+  viewbox_height = dimension_data.height;
+#endif
+  compute_image_size (viewbox_width, viewbox_height, img->spec,
+                      &width, &height);
+
+  if (! check_image_size (f, width, height))
+    {
+      image_size_error ();
+      goto rsvg_error;
+    }
+
   /* We are now done with the unmodified data.  */
   g_object_unref (rsvg_handle);
 
-  /* Calculate the final image size.  */
-  compute_image_size (dimension_data.width, dimension_data.height,
-                      img->spec, &width, &height);
-
   /* Wrap the SVG data in another SVG.  This allows us to set the
      width and height, as well as modify the foreground and background
      colors.  */
@@ -9820,7 +9843,7 @@ svg_load_image (struct frame *f, struct image *img, char 
*contents,
       "xmlns:xi=\"http://www.w3.org/2001/XInclude\"; "
       "style=\"color: #%06X; fill: currentColor;\" "
       "width=\"%d\" height=\"%d\" preserveAspectRatio=\"none\" "
-      "viewBox=\"0 0 %d %d\">"
+      "viewBox=\"0 0 %f %f\">"
       "<rect width=\"100%%\" height=\"100%%\" fill=\"#%06X\"/>"
       "<xi:include href=\"data:image/svg+xml;base64,%s\"></xi:include>"
       "</svg>";
@@ -9845,8 +9868,9 @@ svg_load_image (struct frame *f, struct image *img, char 
*contents,
     if (!wrapped_contents
         || buffer_size <= snprintf (wrapped_contents, buffer_size, wrapper,
                                     foreground & 0xFFFFFF, width, height,
-                                    dimension_data.width, 
dimension_data.height,
-                                    background & 0xFFFFFF, SSDATA 
(encoded_contents)))
+                                    viewbox_width, viewbox_height,
+                                    background & 0xFFFFFF,
+                                    SSDATA (encoded_contents)))
       goto rsvg_error;
 
     wrapped_size = strlen (wrapped_contents);
@@ -9887,12 +9911,6 @@ svg_load_image (struct frame *f, struct image *img, char 
*contents,
   if (err) goto rsvg_error;
 #endif
 
-  rsvg_handle_get_dimensions (rsvg_handle, &dimension_data);
-  if (! check_image_size (f, dimension_data.width, dimension_data.height))
-    {
-      image_size_error ();
-      goto rsvg_error;
-    }
 
   /* We can now get a valid pixel buffer from the svg file, if all
      went ok.  */
diff --git a/src/keyboard.c b/src/keyboard.c
index 4d22c44..2e01433 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -2040,7 +2040,7 @@ help_echo_substitute_command_keys (Lisp_Object help)
                                     help)))
     return help;
 
-  return Fsubstitute_command_keys (help);
+  return call1 (Qsubstitute_command_keys, help);
 }
 
 /* Display the help-echo property of the character after the mouse pointer.
@@ -5254,7 +5254,6 @@ make_lispy_position (struct frame *f, Lisp_Object x, 
Lisp_Object y,
                                        extra_info)));
     }
 
-#ifdef HAVE_WINDOW_SYSTEM
   else if (f)
     {
       /* Return mouse pixel coordinates here.  */
@@ -5262,7 +5261,9 @@ make_lispy_position (struct frame *f, Lisp_Object x, 
Lisp_Object y,
       xret = XFIXNUM (x);
       yret = XFIXNUM (y);
 
-      if (FRAME_LIVE_P (f)
+#ifdef HAVE_WINDOW_SYSTEM
+      if (FRAME_WINDOW_P (f)
+         && FRAME_LIVE_P (f)
          && FRAME_INTERNAL_BORDER_WIDTH (f) > 0
          && !NILP (get_frame_param (f, Qdrag_internal_border)))
        {
@@ -5271,8 +5272,8 @@ make_lispy_position (struct frame *f, Lisp_Object x, 
Lisp_Object y,
 
          posn = builtin_lisp_symbol (internal_border_parts[part]);
        }
-    }
 #endif
+    }
 
   else
     window_or_frame = Qnil;
@@ -7855,7 +7856,7 @@ parse_menu_item (Lisp_Object item, int inmenubar)
     /* The previous code preferred :key-sequence to :keys, so we
        preserve this behavior.  */
     if (STRINGP (keyeq) && !CONSP (keyhint))
-      keyeq = concat2 (space_space, Fsubstitute_command_keys (keyeq));
+      keyeq = concat2 (space_space, call1 (Qsubstitute_command_keys, keyeq));
     else
       {
        Lisp_Object prefix = keyeq;
diff --git a/src/keymap.c b/src/keymap.c
index 0608bdd..e5b4781 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -89,11 +89,6 @@ static Lisp_Object where_is_cache_keymaps;
 static Lisp_Object store_in_keymap (Lisp_Object, Lisp_Object, Lisp_Object);
 
 static Lisp_Object define_as_prefix (Lisp_Object, Lisp_Object);
-static void describe_command (Lisp_Object, Lisp_Object);
-static void describe_translation (Lisp_Object, Lisp_Object);
-static void describe_map (Lisp_Object, Lisp_Object,
-                          void (*) (Lisp_Object, Lisp_Object),
-                         bool, Lisp_Object, Lisp_Object *, bool, bool);
 static void describe_vector (Lisp_Object, Lisp_Object, Lisp_Object,
                              void (*) (Lisp_Object, Lisp_Object), bool,
                              Lisp_Object, Lisp_Object, bool, bool);
@@ -679,6 +674,23 @@ usage: (map-keymap FUNCTION KEYMAP)  */)
   return Qnil;
 }
 
+DEFUN ("keymap--get-keyelt", Fkeymap__get_keyelt, Skeymap__get_keyelt, 2, 2, 0,
+       doc: /* Given OBJECT which was found in a slot in a keymap,
+trace indirect definitions to get the actual definition of that slot.
+An indirect definition is a list of the form
+(KEYMAP . INDEX), where KEYMAP is a keymap or a symbol defined as one
+and INDEX is the object to look up in KEYMAP to yield the definition.
+
+Also if OBJECT has a menu string as the first element,
+remove that.  Also remove a menu help string as second element.
+
+If AUTOLOAD, load autoloadable keymaps
+that are referred to with indirection.  */)
+  (Lisp_Object object, Lisp_Object autoload)
+{
+  return get_keyelt (object, NILP (autoload) ? false : true);
+}
+
 /* Given OBJECT which was found in a slot in a keymap,
    trace indirect definitions to get the actual definition of that slot.
    An indirect definition is a list of the form
@@ -2733,7 +2745,7 @@ The optional argument MENUS, if non-nil, says to mention 
menu bindings.
   (Lisp_Object buffer, Lisp_Object prefix, Lisp_Object menus)
 {
   Lisp_Object outbuf, shadow;
-  bool nomenu = NILP (menus);
+  Lisp_Object nomenu = NILP (menus) ? Qt : Qnil;
   Lisp_Object start1;
 
   const char *alternate_heading
@@ -2782,9 +2794,13 @@ You type        Translation\n\
     }
 
   if (!NILP (Vkey_translation_map))
-    describe_map_tree (Vkey_translation_map, 0, Qnil, prefix,
-                      "Key translations", nomenu, 1, 0, 0);
-
+    {
+      Lisp_Object msg = build_unibyte_string ("Key translations");
+      CALLN (Ffuncall,
+            Qdescribe_map_tree,
+            Vkey_translation_map, Qnil, Qnil, prefix,
+            msg, nomenu, Qt, Qnil, Qnil);
+    }
 
   /* Print the (major mode) local map.  */
   start1 = Qnil;
@@ -2793,8 +2809,11 @@ You type        Translation\n\
 
   if (!NILP (start1))
     {
-      describe_map_tree (start1, 1, shadow, prefix,
-                        "\f\nOverriding Bindings", nomenu, 0, 0, 0);
+      Lisp_Object msg = build_unibyte_string ("\f\nOverriding Bindings");
+      CALLN (Ffuncall,
+            Qdescribe_map_tree,
+            start1, Qt, shadow, prefix,
+            msg, nomenu, Qnil, Qnil, Qnil);
       shadow = Fcons (start1, shadow);
       start1 = Qnil;
     }
@@ -2803,8 +2822,11 @@ You type        Translation\n\
 
   if (!NILP (start1))
     {
-      describe_map_tree (start1, 1, shadow, prefix,
-                        "\f\nOverriding Bindings", nomenu, 0, 0, 0);
+      Lisp_Object msg = build_unibyte_string ("\f\nOverriding Bindings");
+      CALLN (Ffuncall,
+            Qdescribe_map_tree,
+            start1, Qt, shadow, prefix,
+            msg, nomenu, Qnil, Qnil, Qnil);
       shadow = Fcons (start1, shadow);
     }
   else
@@ -2824,9 +2846,11 @@ You type        Translation\n\
                              XBUFFER (buffer), Qkeymap);
       if (!NILP (start1))
        {
-         describe_map_tree (start1, 1, shadow, prefix,
-                            "\f\n`keymap' Property Bindings", nomenu,
-                            0, 0, 0);
+         Lisp_Object msg = build_unibyte_string ("\f\n`keymap' Property 
Bindings");
+         CALLN (Ffuncall,
+                Qdescribe_map_tree,
+                start1, Qt, shadow, prefix,
+                msg, nomenu, Qnil, Qnil, Qnil);
          shadow = Fcons (start1, shadow);
        }
 
@@ -2835,7 +2859,7 @@ You type        Translation\n\
        {
          /* The title for a minor mode keymap
             is constructed at run time.
-            We let describe_map_tree do the actual insertion
+            We let describe-map-tree do the actual insertion
             because it takes care of other features when doing so.  */
          char *title, *p;
 
@@ -2855,8 +2879,11 @@ You type        Translation\n\
          p += strlen (" Minor Mode Bindings");
          *p = 0;
 
-         describe_map_tree (maps[i], 1, shadow, prefix,
-                            title, nomenu, 0, 0, 0);
+         Lisp_Object msg = build_unibyte_string (title);
+         CALLN (Ffuncall,
+                Qdescribe_map_tree,
+                maps[i], Qt, shadow, prefix,
+                msg, nomenu, Qnil, Qnil, Qnil);
          shadow = Fcons (maps[i], shadow);
          SAFE_FREE ();
        }
@@ -2866,432 +2893,66 @@ You type        Translation\n\
       if (!NILP (start1))
        {
          if (EQ (start1, BVAR (XBUFFER (buffer), keymap)))
-           describe_map_tree (start1, 1, shadow, prefix,
-                              "\f\nMajor Mode Bindings", nomenu, 0, 0, 0);
-         else
-           describe_map_tree (start1, 1, shadow, prefix,
-                              "\f\n`local-map' Property Bindings",
-                              nomenu, 0, 0, 0);
-
-         shadow = Fcons (start1, shadow);
-       }
-    }
-
-  describe_map_tree (current_global_map, 1, shadow, prefix,
-                    "\f\nGlobal Bindings", nomenu, 0, 1, 0);
-
-  /* Print the function-key-map translations under this prefix.  */
-  if (!NILP (KVAR (current_kboard, Vlocal_function_key_map)))
-    describe_map_tree (KVAR (current_kboard, Vlocal_function_key_map), 0, 
Qnil, prefix,
-                      "\f\nFunction key map translations", nomenu, 1, 0, 0);
-
-  /* Print the input-decode-map translations under this prefix.  */
-  if (!NILP (KVAR (current_kboard, Vinput_decode_map)))
-    describe_map_tree (KVAR (current_kboard, Vinput_decode_map), 0, Qnil, 
prefix,
-                      "\f\nInput decoding map translations", nomenu, 1, 0, 0);
-
-  return Qnil;
-}
-
-/* Insert a description of the key bindings in STARTMAP,
-    followed by those of all maps reachable through STARTMAP.
-   If PARTIAL, omit certain "uninteresting" commands
-    (such as `undefined').
-   If SHADOW is non-nil, it is a list of maps;
-    don't mention keys which would be shadowed by any of them.
-   PREFIX, if non-nil, says mention only keys that start with PREFIX.
-   TITLE, if not 0, is a string to insert at the beginning.
-   TITLE should not end with a colon or a newline; we supply that.
-   If NOMENU, then omit menu-bar commands.
-
-   If TRANSL, the definitions are actually key translations
-   so print strings and vectors differently.
-
-   If ALWAYS_TITLE, print the title even if there are no maps
-   to look through.
-
-   If MENTION_SHADOW, then when something is shadowed by SHADOW,
-   don't omit it; instead, mention it but say it is shadowed.
-
-   Any inserted text ends in two newlines (used by `help-make-xrefs').  */
-
-void
-describe_map_tree (Lisp_Object startmap, bool partial, Lisp_Object shadow,
-                  Lisp_Object prefix, const char *title, bool nomenu,
-                  bool transl, bool always_title, bool mention_shadow)
-{
-  Lisp_Object maps, orig_maps, seen, sub_shadows;
-  bool something = 0;
-  const char *key_heading
-    = "\
-key             binding\n\
----             -------\n";
-
-  orig_maps = maps = Faccessible_keymaps (startmap, prefix);
-  seen = Qnil;
-  sub_shadows = Qnil;
-
-  if (nomenu)
-    {
-      Lisp_Object list;
-
-      /* Delete from MAPS each element that is for the menu bar.  */
-      for (list = maps; CONSP (list); list = XCDR (list))
-       {
-         Lisp_Object elt, elt_prefix, tem;
-
-         elt = XCAR (list);
-         elt_prefix = Fcar (elt);
-         if (ASIZE (elt_prefix) >= 1)
            {
-             tem = Faref (elt_prefix, make_fixnum (0));
-             if (EQ (tem, Qmenu_bar))
-               maps = Fdelq (elt, maps);
+             Lisp_Object msg = build_unibyte_string ("\f\nMajor Mode 
Bindings");
+             CALLN (Ffuncall,
+                    Qdescribe_map_tree,
+                    start1, Qt, shadow, prefix,
+                    msg, nomenu, Qnil, Qnil, Qnil);
            }
-       }
-    }
-
-  if (!NILP (maps) || always_title)
-    {
-      if (title)
-       {
-         insert_string (title);
-         if (!NILP (prefix))
+         else
            {
-             insert_string (" Starting With ");
-             insert1 (Fkey_description (prefix, Qnil));
+             Lisp_Object msg = build_unibyte_string ("\f\n`local-map' Property 
Bindings");
+             CALLN (Ffuncall,
+                    Qdescribe_map_tree,
+                    start1, Qt, shadow, prefix,
+                    msg, nomenu, Qnil, Qnil, Qnil);
            }
-         insert_string (":\n");
-       }
-      insert_string (key_heading);
-      something = 1;
-    }
 
-  for (; CONSP (maps); maps = XCDR (maps))
-    {
-      register Lisp_Object elt, elt_prefix, tail;
-
-      elt = XCAR (maps);
-      elt_prefix = Fcar (elt);
-
-      sub_shadows = Flookup_key (shadow, elt_prefix, Qt);
-      if (FIXNATP (sub_shadows))
-        sub_shadows = Qnil;
-      else if (!KEYMAPP (sub_shadows)
-               && !NILP (sub_shadows)
-               && !(CONSP (sub_shadows)
-                    && KEYMAPP (XCAR (sub_shadows))))
-         /* If elt_prefix is bound to something that's not a keymap,
-            it completely shadows this map, so don't
-            describe this map at all.  */
-        goto skip;
-
-      /* Maps we have already listed in this loop shadow this map.  */
-      for (tail = orig_maps; !EQ (tail, maps); tail = XCDR (tail))
-       {
-         Lisp_Object tem;
-         tem = Fequal (Fcar (XCAR (tail)), elt_prefix);
-         if (!NILP (tem))
-           sub_shadows = Fcons (XCDR (XCAR (tail)), sub_shadows);
+         shadow = Fcons (start1, shadow);
        }
-
-      describe_map (Fcdr (elt), elt_prefix,
-                   transl ? describe_translation : describe_command,
-                   partial, sub_shadows, &seen, nomenu, mention_shadow);
-
-    skip: ;
     }
 
-  if (something)
-    insert_string ("\n");
-}
-
-static int previous_description_column;
-
-static void
-describe_command (Lisp_Object definition, Lisp_Object args)
-{
-  register Lisp_Object tem1;
-  ptrdiff_t column = current_column ();
-  int description_column;
+  Lisp_Object msg = build_unibyte_string ("\f\nGlobal Bindings");
+  CALLN (Ffuncall,
+        Qdescribe_map_tree,
+        current_global_map, Qt, shadow, prefix,
+        msg, nomenu, Qnil, Qt, Qnil);
 
-  /* If column 16 is no good, go to col 32;
-     but don't push beyond that--go to next line instead.  */
-  if (column > 30)
+  /* Print the function-key-map translations under this prefix.  */
+  if (!NILP (KVAR (current_kboard, Vlocal_function_key_map)))
     {
-      insert_char ('\n');
-      description_column = 32;
+      Lisp_Object msg = build_unibyte_string ("\f\nFunction key map 
translations");
+      CALLN (Ffuncall,
+            Qdescribe_map_tree,
+            KVAR (current_kboard, Vlocal_function_key_map), Qnil, Qnil, prefix,
+            msg, nomenu, Qt, Qt, Qt);
     }
-  else if (column > 14 || (column > 10 && previous_description_column == 32))
-    description_column = 32;
-  else
-    description_column = 16;
-
-  Findent_to (make_fixnum (description_column), make_fixnum (1));
-  previous_description_column = description_column;
 
-  if (SYMBOLP (definition))
+  /* Print the input-decode-map translations under this prefix.  */
+  if (!NILP (KVAR (current_kboard, Vinput_decode_map)))
     {
-      tem1 = SYMBOL_NAME (definition);
-      insert1 (tem1);
-      insert_string ("\n");
+      Lisp_Object msg = build_unibyte_string ("\f\nInput decoding map 
translations");
+      CALLN (Ffuncall,
+            Qdescribe_map_tree,
+            KVAR (current_kboard, Vinput_decode_map), Qnil, Qnil, prefix,
+            msg, nomenu, Qt, Qnil, Qnil);
     }
-  else if (STRINGP (definition) || VECTORP (definition))
-    insert_string ("Keyboard Macro\n");
-  else if (KEYMAPP (definition))
-    insert_string ("Prefix Command\n");
-  else
-    insert_string ("??\n");
+  return Qnil;
 }
 
 static void
-describe_translation (Lisp_Object definition, Lisp_Object args)
+describe_vector_princ (Lisp_Object elt, Lisp_Object fun)
 {
-  register Lisp_Object tem1;
-
   Findent_to (make_fixnum (16), make_fixnum (1));
-
-  if (SYMBOLP (definition))
-    {
-      tem1 = SYMBOL_NAME (definition);
-      insert1 (tem1);
-      insert_string ("\n");
-    }
-  else if (STRINGP (definition) || VECTORP (definition))
-    {
-      insert1 (Fkey_description (definition, Qnil));
-      insert_string ("\n");
-    }
-  else if (KEYMAPP (definition))
-    insert_string ("Prefix Command\n");
-  else
-    insert_string ("??\n");
-}
-
-/* describe_map puts all the usable elements of a sparse keymap
-   into an array of `struct describe_map_elt',
-   then sorts them by the events.  */
-
-struct describe_map_elt
-{
-  Lisp_Object event;
-  Lisp_Object definition;
-  bool shadowed;
-};
-
-/* qsort comparison function for sorting `struct describe_map_elt' by
-   the event field.  */
-
-static int
-describe_map_compare (const void *aa, const void *bb)
-{
-  const struct describe_map_elt *a = aa, *b = bb;
-  if (FIXNUMP (a->event) && FIXNUMP (b->event))
-    return ((XFIXNUM (a->event) > XFIXNUM (b->event))
-           - (XFIXNUM (a->event) < XFIXNUM (b->event)));
-  if (!FIXNUMP (a->event) && FIXNUMP (b->event))
-    return 1;
-  if (FIXNUMP (a->event) && !FIXNUMP (b->event))
-    return -1;
-  if (SYMBOLP (a->event) && SYMBOLP (b->event))
-    /* Sort the keystroke names in the "natural" way, with (for
-       instance) "<f2>" coming between "<f1>" and "<f11>".  */
-    return string_version_cmp (SYMBOL_NAME (a->event), SYMBOL_NAME (b->event));
-  return 0;
-}
-
-/* Describe the contents of map MAP, assuming that this map itself is
-   reached by the sequence of prefix keys PREFIX (a string or vector).
-   PARTIAL, SHADOW, NOMENU are as in `describe_map_tree' above.  */
-
-static void
-describe_map (Lisp_Object map, Lisp_Object prefix,
-             void (*elt_describer) (Lisp_Object, Lisp_Object),
-             bool partial, Lisp_Object shadow,
-             Lisp_Object *seen, bool nomenu, bool mention_shadow)
-{
-  Lisp_Object tail, definition, event;
-  Lisp_Object tem;
-  Lisp_Object suppress;
-  Lisp_Object kludge;
-  bool first = 1;
-
-  /* These accumulate the values from sparse keymap bindings,
-     so we can sort them and handle them in order.  */
-  ptrdiff_t length_needed = 0;
-  struct describe_map_elt *vect;
-  ptrdiff_t slots_used = 0;
-  ptrdiff_t i;
-
-  suppress = Qnil;
-
-  if (partial)
-    suppress = intern ("suppress-keymap");
-
-  /* This vector gets used to present single keys to Flookup_key.  Since
-     that is done once per keymap element, we don't want to cons up a
-     fresh vector every time.  */
-  kludge = make_nil_vector (1);
-  definition = Qnil;
-
-  map = call1 (Qkeymap_canonicalize, map);
-
-  for (tail = map; CONSP (tail); tail = XCDR (tail))
-    length_needed++;
-
-  USE_SAFE_ALLOCA;
-  SAFE_NALLOCA (vect, 1, length_needed);
-
-  for (tail = map; CONSP (tail); tail = XCDR (tail))
-    {
-      maybe_quit ();
-
-      if (VECTORP (XCAR (tail))
-         || CHAR_TABLE_P (XCAR (tail)))
-       describe_vector (XCAR (tail),
-                        prefix, Qnil, elt_describer, partial, shadow, map,
-                        1, mention_shadow);
-      else if (CONSP (XCAR (tail)))
-       {
-         bool this_shadowed = 0;
-
-         event = XCAR (XCAR (tail));
-
-         /* Ignore bindings whose "prefix" are not really valid events.
-            (We get these in the frames and buffers menu.)  */
-         if (!(SYMBOLP (event) || FIXNUMP (event)))
-           continue;
-
-         if (nomenu && EQ (event, Qmenu_bar))
-           continue;
-
-         definition = get_keyelt (XCDR (XCAR (tail)), 0);
-
-         /* Don't show undefined commands or suppressed commands.  */
-         if (NILP (definition)) continue;
-         if (SYMBOLP (definition) && partial)
-           {
-             tem = Fget (definition, suppress);
-             if (!NILP (tem))
-               continue;
-           }
-
-         /* Don't show a command that isn't really visible
-            because a local definition of the same key shadows it.  */
-
-         ASET (kludge, 0, event);
-         if (!NILP (shadow))
-           {
-             tem = shadow_lookup (shadow, kludge, Qt, 0);
-             if (!NILP (tem))
-               {
-                 /* If both bindings are keymaps, this key is a prefix key,
-                    so don't say it is shadowed.  */
-                 if (KEYMAPP (definition) && KEYMAPP (tem))
-                   ;
-                 /* Avoid generating duplicate entries if the
-                    shadowed binding has the same definition.  */
-                 else if (mention_shadow && !EQ (tem, definition))
-                   this_shadowed = 1;
-                 else
-                   continue;
-               }
-           }
-
-         tem = Flookup_key (map, kludge, Qt);
-         if (!EQ (tem, definition)) continue;
-
-         vect[slots_used].event = event;
-         vect[slots_used].definition = definition;
-         vect[slots_used].shadowed = this_shadowed;
-         slots_used++;
-       }
-      else if (EQ (XCAR (tail), Qkeymap))
-       {
-         /* The same keymap might be in the structure twice, if we're
-            using an inherited keymap.  So skip anything we've already
-            encountered.  */
-         tem = Fassq (tail, *seen);
-         if (CONSP (tem) && !NILP (Fequal (XCAR (tem), prefix)))
-           break;
-         *seen = Fcons (Fcons (tail, prefix), *seen);
-       }
-    }
-
-  /* If we found some sparse map events, sort them.  */
-
-  qsort (vect, slots_used, sizeof (struct describe_map_elt),
-        describe_map_compare);
-
-  /* Now output them in sorted order.  */
-
-  for (i = 0; i < slots_used; i++)
-    {
-      Lisp_Object start, end;
-
-      if (first)
-       {
-         previous_description_column = 0;
-         insert ("\n", 1);
-         first = 0;
-       }
-
-      ASET (kludge, 0, vect[i].event);
-      start = vect[i].event;
-      end = start;
-
-      definition = vect[i].definition;
-
-      /* Find consecutive chars that are identically defined.  */
-      if (FIXNUMP (vect[i].event))
-       {
-         while (i + 1 < slots_used
-                && EQ (vect[i+1].event, make_fixnum (XFIXNUM (vect[i].event) + 
1))
-                && !NILP (Fequal (vect[i + 1].definition, definition))
-                && vect[i].shadowed == vect[i + 1].shadowed)
-           i++;
-         end = vect[i].event;
-       }
-
-      /* Now START .. END is the range to describe next.  */
-
-      /* Insert the string to describe the event START.  */
-      insert1 (Fkey_description (kludge, prefix));
-
-      if (!EQ (start, end))
-       {
-         insert (" .. ", 4);
-
-         ASET (kludge, 0, end);
-         /* Insert the string to describe the character END.  */
-         insert1 (Fkey_description (kludge, prefix));
-       }
-
-      /* Print a description of the definition of this character.
-        elt_describer will take care of spacing out far enough
-        for alignment purposes.  */
-      (*elt_describer) (vect[i].definition, Qnil);
-
-      if (vect[i].shadowed)
-       {
-         ptrdiff_t pt = max (PT - 1, BEG);
-
-         SET_PT (pt);
-         insert_string ("\n  (this binding is currently shadowed)");
-         pt = min (PT + 1, Z);
-         SET_PT (pt);
-       }
-    }
-
-  SAFE_FREE ();
+  call1 (fun, elt);
+  Fterpri (Qnil, Qnil);
 }
 
 static void
-describe_vector_princ (Lisp_Object elt, Lisp_Object fun)
+describe_vector_basic (Lisp_Object elt, Lisp_Object fun)
 {
-  Findent_to (make_fixnum (16), make_fixnum (1));
   call1 (fun, elt);
-  Fterpri (Qnil, Qnil);
 }
 
 DEFUN ("describe-vector", Fdescribe_vector, Sdescribe_vector, 1, 2, 0,
@@ -3311,8 +2972,40 @@ DESCRIBER is the output function used; nil means use 
`princ'.  */)
   return unbind_to (count, Qnil);
 }
 
+DEFUN ("help--describe-vector", Fhelp__describe_vector, 
Shelp__describe_vector, 7, 7, 0,
+       doc: /* Insert in the current buffer a description of the contents of 
VECTOR.
+Call DESCRIBER to insert the description of one value found in VECTOR.
+
+PREFIX is a string describing the key which leads to the keymap that
+this vector is in.
+
+If PARTIAL, it means do not mention suppressed commands.
+
+SHADOW is a list of keymaps that shadow this map.
+If it is non-nil, look up the key in those maps and don't mention it
+if it is defined by any of them.
+
+ENTIRE-MAP is the keymap in which this vector appears.
+If the definition in effect in the whole map does not match
+the one in this keymap, we ignore this one.  */)
+  (Lisp_Object vector, Lisp_Object prefix, Lisp_Object describer,
+   Lisp_Object partial, Lisp_Object shadow, Lisp_Object entire_map,
+   Lisp_Object mention_shadow)
+{
+  ptrdiff_t count = SPECPDL_INDEX ();
+  specbind (Qstandard_output, Fcurrent_buffer ());
+  CHECK_VECTOR_OR_CHAR_TABLE (vector);
+
+  bool b_partial = NILP (partial) ? false : true;
+  bool b_mention_shadow = NILP (mention_shadow) ? false : true;
+
+  describe_vector (vector, prefix, describer, describe_vector_basic, b_partial,
+                  shadow, entire_map, true, b_mention_shadow);
+  return unbind_to (count, Qnil);
+}
+
 /* Insert in the current buffer a description of the contents of VECTOR.
-   We call ELT_DESCRIBER to insert the description of one value found
+   Call ELT_DESCRIBER to insert the description of one value found
    in VECTOR.
 
    ELT_PREFIX describes what "comes before" the keys or indices defined
@@ -3568,6 +3261,7 @@ void
 syms_of_keymap (void)
 {
   DEFSYM (Qkeymap, "keymap");
+  DEFSYM (Qdescribe_map_tree, "describe-map-tree");
   staticpro (&apropos_predicate);
   staticpro (&apropos_accumulate);
   apropos_predicate = Qnil;
@@ -3708,6 +3402,8 @@ be preferred.  */);
   defsubr (&Scurrent_active_maps);
   defsubr (&Saccessible_keymaps);
   defsubr (&Skey_description);
+  defsubr (&Skeymap__get_keyelt);
+  defsubr (&Shelp__describe_vector);
   defsubr (&Sdescribe_vector);
   defsubr (&Ssingle_key_description);
   defsubr (&Stext_char_description);
diff --git a/src/keymap.h b/src/keymap.h
index 3ef48fb..2f7df2b 100644
--- a/src/keymap.h
+++ b/src/keymap.h
@@ -36,8 +36,6 @@ extern Lisp_Object current_global_map;
 extern char *push_key_description (EMACS_INT, char *);
 extern Lisp_Object access_keymap (Lisp_Object, Lisp_Object, bool, bool, bool);
 extern Lisp_Object get_keymap (Lisp_Object, bool, bool);
-extern void describe_map_tree (Lisp_Object, bool, Lisp_Object, Lisp_Object,
-                              const char *, bool, bool, bool, bool);
 extern ptrdiff_t current_minor_maps (Lisp_Object **, Lisp_Object **);
 extern void initial_define_key (Lisp_Object, int, const char *);
 extern void initial_define_lispy_key (Lisp_Object, const char *, const char *);
diff --git a/src/lread.c b/src/lread.c
index 6aab470..015bcc2 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -2667,6 +2667,13 @@ read_escape (Lisp_Object readcharfun, bool stringp)
        while (++count <= unicode_hex_count)
          {
            c = READCHAR;
+           if (c < 0)
+             {
+               if (unicode_hex_count > 4)
+                 error ("Malformed Unicode escape: \\U%x", i);
+               else
+                 error ("Malformed Unicode escape: \\u%x", i);
+             }
            /* `isdigit' and `isalpha' may be locale-specific, which we don't
               want.  */
            int digit = char_hexdigit (c);
diff --git a/src/nsterm.m b/src/nsterm.m
index a702a05..fa38350 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -3048,6 +3048,12 @@ ns_clear_under_internal_border (struct frame *f)
       if (!face)
         face = FRAME_DEFAULT_FACE (f);
 
+      /* Sometimes with new frames we reach this point and have no
+         face.  I'm not sure why we have a live frame but no face, so
+         just give up.  */
+      if (!face)
+        return;
+
       ns_focus (f, &frame_rect, 1);
       [ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f) set];
       for (int i = 0; i < 4 ; i++)
diff --git a/src/print.c b/src/print.c
index 23d0625..9d839d6 100644
--- a/src/print.c
+++ b/src/print.c
@@ -941,7 +941,7 @@ print_error_message (Lisp_Object data, Lisp_Object stream, 
const char *context,
   else
     {
       Lisp_Object error_conditions = Fget (errname, Qerror_conditions);
-      errmsg = Fsubstitute_command_keys (Fget (errname, Qerror_message));
+      errmsg = call1 (Qsubstitute_command_keys, Fget (errname, 
Qerror_message));
       file_error = Fmemq (Qfile_error, error_conditions);
     }
 
diff --git a/src/search.c b/src/search.c
index 6fb3716..e7f9094 100644
--- a/src/search.c
+++ b/src/search.c
@@ -2748,7 +2748,7 @@ since only regular expressions have distinguished 
subexpressions.  */)
 
   /* Put point back where it was in the text, if possible.  */
   TEMP_SET_PT (clip_to_bounds (BEGV, opoint + (opoint <= 0 ? ZV : 0), ZV));
-  /* Now move point "officially" to the start of the inserted replacement.  */
+  /* Now move point "officially" to the end of the inserted replacement.  */
   move_if_not_intangible (newpoint);
 
   return Qnil;
diff --git a/src/syntax.c b/src/syntax.c
index 066972e..df07809 100644
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -1421,7 +1421,7 @@ DEFUN ("internal-describe-syntax-value", 
Finternal_describe_syntax_value,
     {
       AUTO_STRING (prefixdoc,
                   ",\n\t  is a prefix character for `backward-prefix-chars'");
-      insert1 (Fsubstitute_command_keys (prefixdoc));
+      insert1 (call1 (Qsubstitute_command_keys, prefixdoc));
     }
 
   return syntax;
diff --git a/src/xterm.c b/src/xterm.c
index 2e0407a..98bb0ea 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -8949,8 +8949,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 #endif
 #ifdef USE_GTK
       if (!f
-          && (f = any)
-          && configureEvent.xconfigure.window == FRAME_X_WINDOW (f))
+         && (f = any)
+         && configureEvent.xconfigure.window == FRAME_X_WINDOW (f)
+         && FRAME_VISIBLE_P(f))
         {
           block_input ();
           if (FRAME_X_DOUBLE_BUFFERED_P (f))
@@ -8963,10 +8964,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                                            configureEvent.xconfigure.height);
 #endif
           f = 0;
-        }
+       }
 #endif
-      if (f)
-        {
+      if (f && FRAME_VISIBLE_P(f))
+       {
 #ifdef USE_GTK
          /* For GTK+ don't call x_net_wm_state for the scroll bar
             window.  (Bug#24963, Bug#25887) */
@@ -9056,7 +9057,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
             xic_set_statusarea (f);
 #endif
 
-        }
+       }
       goto OTHER;
 
     case ButtonRelease:
diff --git a/test/Makefile.in b/test/Makefile.in
index 4a5cbee..a11bf96 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -133,7 +133,7 @@ emacs = EMACSLOADPATH= \
 # exists, or writing to ~/.bzr.log when running bzr commands).
 TEST_HOME = /nonexistent
 
-test_module_dir := data/emacs-module
+test_module_dir := src/emacs-module-resources
 
 .PHONY: all check
 
diff --git a/test/lisp/autorevert-tests.el b/test/lisp/autorevert-tests.el
index 3243a80..1b26a3d 100644
--- a/test/lisp/autorevert-tests.el
+++ b/test/lisp/autorevert-tests.el
@@ -61,8 +61,9 @@
       file-notify-debug nil
       tramp-verbose 0)
 
-(defconst auto-revert--timeout (1+ auto-revert-interval)
-  "Time to wait for a message.")
+(defun auto-revert--timeout ()
+  "Time to wait for a message."
+  (+ auto-revert-interval 0.1))
 
 (defvar auto-revert--messages nil
   "Used to collect messages issued during a section of a test.")
@@ -125,14 +126,14 @@ This expects `auto-revert--messages' to be bound by
   ;; Remote files do not cooperate well with timers.  So we count ourselves.
   (let ((ct (current-time)))
     (while (and (< (float-time (time-subtract (current-time) ct))
-                   auto-revert--timeout)
+                   (auto-revert--timeout))
                 (null (string-match
                        (format-message
                         "Reverting buffer `%s'\\." (buffer-name buffer))
                        auto-revert--messages)))
       (if (with-current-buffer buffer auto-revert-use-notify)
-          (read-event nil nil 0.1)
-        (sleep-for 0.1)))))
+          (read-event nil nil 0.05)
+        (sleep-for 0.05)))))
 
 (defmacro auto-revert--deftest-remote (test docstring)
   "Define ert `TEST-remote' for remote files."
@@ -152,51 +153,59 @@ This expects `auto-revert--messages' to be bound by
            (funcall (ert-test-body ert-test))
          (error (message "%s" err) (signal (car err) (cdr err)))))))
 
+(defmacro with-auto-revert-test (&rest body)
+  `(let ((auto-revert-interval-orig auto-revert-interval))
+     (unwind-protect
+         (progn
+           (customize-set-variable 'auto-revert-interval 0.1)
+           ,@body)
+       (customize-set-variable 'auto-revert-interval 
auto-revert-interval-orig))))
+
+(defun auto-revert-tests--write-file (text file time-delta &optional append)
+  (write-region text nil file append 'no-message)
+  (set-file-times file (time-subtract (current-time) time-delta)))
+
 (ert-deftest auto-revert-test00-auto-revert-mode ()
   "Check autorevert for a file."
   ;; `auto-revert-buffers' runs every 5".  And we must wait, until the
   ;; file has been reverted.
-  :tags '(:expensive-test)
-  (let ((tmpfile (make-temp-file "auto-revert-test"))
-        buf)
-    (unwind-protect
-       (progn
-          (write-region "any text" nil tmpfile nil 'no-message)
-         (setq buf (find-file-noselect tmpfile))
-          (with-current-buffer buf
-            (ert-with-message-capture auto-revert--messages
-              (should (string-equal (buffer-string) "any text"))
-              ;; `buffer-stale--default-function' checks for
-              ;; `verify-visited-file-modtime'.  We must ensure that it
-              ;; returns nil.
-              (sleep-for 1)
-              (auto-revert-mode 1)
-              (should auto-revert-mode)
-
-              ;; Modify file.  We wait for a second, in order to have
-              ;; another timestamp.
-              (sleep-for 1)
-              (write-region "another text" nil tmpfile nil 'no-message)
-
-              ;; Check, that the buffer has been reverted.
-              (auto-revert--wait-for-revert buf))
-            (should (string-match "another text" (buffer-string)))
-
-            ;; When the buffer is modified, it shall not be reverted.
-            (ert-with-message-capture auto-revert--messages
-              (set-buffer-modified-p t)
-              (sleep-for 1)
-              (write-region "any text" nil tmpfile nil 'no-message)
-
-              ;; Check, that the buffer hasn't been reverted.
-              (auto-revert--wait-for-revert buf))
-            (should-not (string-match "any text" (buffer-string)))))
-
-      ;; Exit.
-      (ignore-errors
-        (with-current-buffer buf (set-buffer-modified-p nil))
-        (kill-buffer buf))
-      (ignore-errors (delete-file tmpfile)))))
+  (with-auto-revert-test
+   (let ((tmpfile (make-temp-file "auto-revert-test"))
+         (times '(60 30 15))
+         buf)
+     (unwind-protect
+         (progn
+           (auto-revert-tests--write-file "any text" tmpfile (pop times))
+           (setq buf (find-file-noselect tmpfile))
+           (with-current-buffer buf
+             (ert-with-message-capture auto-revert--messages
+               (should (string-equal (buffer-string) "any text"))
+               ;; `buffer-stale--default-function' checks for
+               ;; `verify-visited-file-modtime'.  We must ensure that it
+               ;; returns nil.
+               (auto-revert-mode 1)
+               (should auto-revert-mode)
+
+               (auto-revert-tests--write-file "another text" tmpfile (pop 
times))
+
+               ;; Check, that the buffer has been reverted.
+               (auto-revert--wait-for-revert buf))
+             (should (string-match "another text" (buffer-string)))
+
+             ;; When the buffer is modified, it shall not be reverted.
+             (ert-with-message-capture auto-revert--messages
+               (set-buffer-modified-p t)
+               (auto-revert-tests--write-file "any text" tmpfile (pop times))
+
+               ;; Check, that the buffer hasn't been reverted.
+               (auto-revert--wait-for-revert buf))
+             (should-not (string-match "any text" (buffer-string)))))
+
+       ;; Exit.
+       (ignore-errors
+         (with-current-buffer buf (set-buffer-modified-p nil))
+         (kill-buffer buf))
+       (ignore-errors (delete-file tmpfile))))))
 
 (auto-revert--deftest-remote auto-revert-test00-auto-revert-mode
   "Check autorevert for a remote file.")
@@ -204,66 +213,65 @@ This expects `auto-revert--messages' to be bound by
 ;; This is inspired by Bug#21841.
 (ert-deftest auto-revert-test01-auto-revert-several-files ()
   "Check autorevert for several files at once."
-  :tags '(:expensive-test)
   (skip-unless (executable-find "cp" (file-remote-p temporary-file-directory)))
 
-  (let* ((cp (executable-find "cp" (file-remote-p temporary-file-directory)))
-         (tmpdir1 (make-temp-file "auto-revert-test" 'dir))
-         (tmpdir2 (make-temp-file "auto-revert-test" 'dir))
-         (tmpfile1
-          (make-temp-file (expand-file-name "auto-revert-test" tmpdir1)))
-         (tmpfile2
-          (make-temp-file (expand-file-name "auto-revert-test" tmpdir1)))
-         buf1 buf2)
-    (unwind-protect
-        (ert-with-message-capture auto-revert--messages
-          (write-region "any text" nil tmpfile1 nil 'no-message)
-          (setq buf1 (find-file-noselect tmpfile1))
-          (write-region "any text" nil tmpfile2 nil 'no-message)
-          (setq buf2 (find-file-noselect tmpfile2))
-
-          (dolist (buf (list buf1 buf2))
-            (with-current-buffer buf
-              (should (string-equal (buffer-string) "any text"))
-              ;; `buffer-stale--default-function' checks for
-              ;; `verify-visited-file-modtime'.  We must ensure that
-              ;; it returns nil.
-              (sleep-for 1)
-              (auto-revert-mode 1)
-              (should auto-revert-mode)))
-
-          ;; Modify files.  We wait for a second, in order to have
-          ;; another timestamp.
-          (sleep-for 1)
-          (write-region
-           "another text" nil
-           (expand-file-name (file-name-nondirectory tmpfile1) tmpdir2)
-           nil 'no-message)
-          (write-region
-           "another text" nil
-           (expand-file-name (file-name-nondirectory tmpfile2) tmpdir2)
-           nil 'no-message)
-          ;;(copy-directory tmpdir2 tmpdir1 nil 'copy-contents)
-          ;; Strange, that `copy-directory' does not work as expected.
-          ;; The following shell command is not portable on all
-          ;; platforms, unfortunately.
-          (shell-command
-           (format "%s -f %s/* %s"
-                   cp (file-local-name tmpdir2) (file-local-name tmpdir1)))
-
-          ;; Check, that the buffers have been reverted.
-          (dolist (buf (list buf1 buf2))
-            (with-current-buffer buf
-              (auto-revert--wait-for-revert buf)
-              (should (string-match "another text" (buffer-string))))))
-
-      ;; Exit.
-      (ignore-errors
-        (dolist (buf (list buf1 buf2))
-          (with-current-buffer buf (set-buffer-modified-p nil))
-          (kill-buffer buf)))
-      (ignore-errors (delete-directory tmpdir1 'recursive))
-      (ignore-errors (delete-directory tmpdir2 'recursive)))))
+  (with-auto-revert-test
+   (let* ((cp (executable-find "cp" (file-remote-p temporary-file-directory)))
+          (tmpdir1 (make-temp-file "auto-revert-test" 'dir))
+          (tmpdir2 (make-temp-file "auto-revert-test" 'dir))
+          (tmpfile1
+           (make-temp-file (expand-file-name "auto-revert-test" tmpdir1)))
+          (tmpfile2
+           (make-temp-file (expand-file-name "auto-revert-test" tmpdir1)))
+          (times '(120 60 30 15))
+          buf1 buf2)
+     (unwind-protect
+         (ert-with-message-capture auto-revert--messages
+           (auto-revert-tests--write-file "any text" tmpfile1 (pop times))
+           (setq buf1 (find-file-noselect tmpfile1))
+           (auto-revert-tests--write-file "any text" tmpfile2 (pop times))
+           (setq buf2 (find-file-noselect tmpfile2))
+
+           (dolist (buf (list buf1 buf2))
+             (with-current-buffer buf
+               (should (string-equal (buffer-string) "any text"))
+               ;; `buffer-stale--default-function' checks for
+               ;; `verify-visited-file-modtime'.  We must ensure that
+               ;; it returns nil.
+               (auto-revert-mode 1)
+               (should auto-revert-mode)))
+
+           ;; Modify files.  We wait for a second, in order to have
+           ;; another timestamp.
+           (auto-revert-tests--write-file
+            "another text"
+            (expand-file-name (file-name-nondirectory tmpfile1) tmpdir2)
+            (pop times))
+           (auto-revert-tests--write-file
+            "another text"
+            (expand-file-name (file-name-nondirectory tmpfile2) tmpdir2)
+            (pop times))
+           ;;(copy-directory tmpdir2 tmpdir1 nil 'copy-contents)
+           ;; Strange, that `copy-directory' does not work as expected.
+           ;; The following shell command is not portable on all
+           ;; platforms, unfortunately.
+           (shell-command
+            (format "%s -f %s/* %s"
+                    cp (file-local-name tmpdir2) (file-local-name tmpdir1)))
+
+           ;; Check, that the buffers have been reverted.
+           (dolist (buf (list buf1 buf2))
+             (with-current-buffer buf
+               (auto-revert--wait-for-revert buf)
+               (should (string-match "another text" (buffer-string))))))
+
+       ;; Exit.
+       (ignore-errors
+         (dolist (buf (list buf1 buf2))
+           (with-current-buffer buf (set-buffer-modified-p nil))
+           (kill-buffer buf)))
+       (ignore-errors (delete-directory tmpdir1 'recursive))
+       (ignore-errors (delete-directory tmpdir2 'recursive))))))
 
 (auto-revert--deftest-remote auto-revert-test01-auto-revert-several-files
   "Check autorevert for several remote files at once.")
@@ -271,84 +279,81 @@ This expects `auto-revert--messages' to be bound by
 ;; This is inspired by Bug#23276.
 (ert-deftest auto-revert-test02-auto-revert-deleted-file ()
   "Check autorevert for a deleted file."
-  :tags '(:expensive-test)
   ;; Repeated unpredictable failures, bug#32645.
   ;; Unlikely to be hydra-specific?
 ;  (skip-unless (not (getenv "EMACS_HYDRA_CI")))
 
-  (let ((tmpfile (make-temp-file "auto-revert-test"))
-        ;; Try to catch bug#32645.
-        (auto-revert-debug (getenv "EMACS_HYDRA_CI"))
-        (file-notify-debug (getenv "EMACS_HYDRA_CI"))
-        buf desc)
-    (unwind-protect
-       (progn
-          (write-region "any text" nil tmpfile nil 'no-message)
-         (setq buf (find-file-noselect tmpfile))
-         (with-current-buffer buf
-            (should-not
-             (file-notify-valid-p auto-revert-notify-watch-descriptor))
-            (should (string-equal (buffer-string) "any text"))
-            ;; `buffer-stale--default-function' checks for
-            ;; `verify-visited-file-modtime'.  We must ensure that
-            ;; it returns nil.
-            (sleep-for 1)
-            (auto-revert-mode 1)
-            (should auto-revert-mode)
-            (setq desc auto-revert-notify-watch-descriptor)
-
-            ;; Remove file while reverting.  We simulate this by
-            ;; modifying `before-revert-hook'.
-            (add-hook
-             'before-revert-hook
-             (lambda ()
-               (when auto-revert-debug
-                 (message "%s deleted" buffer-file-name))
-               (delete-file buffer-file-name))
-             nil t)
-
-            (ert-with-message-capture auto-revert--messages
-              (sleep-for 1)
-              (write-region "another text" nil tmpfile nil 'no-message)
-              (auto-revert--wait-for-revert buf))
-            ;; Check, that the buffer hasn't been reverted.  File
-            ;; notification should be disabled, falling back to
-            ;; polling.
-            (should (string-match "any text" (buffer-string)))
-            ;; With w32notify, and on emba, the `stopped' events are not sent.
-            (or (eq file-notify--library 'w32notify)
-                (getenv "EMACS_EMBA_CI")
-                (should-not
-                 (file-notify-valid-p auto-revert-notify-watch-descriptor)))
-
-            ;; Once the file has been recreated, the buffer shall be
-            ;; reverted.
-            (kill-local-variable 'before-revert-hook)
-            (ert-with-message-capture auto-revert--messages
-              (sleep-for 1)
-              (write-region "another text" nil tmpfile nil 'no-message)
-              (auto-revert--wait-for-revert buf))
-            ;; Check, that the buffer has been reverted.
-            (should (string-match "another text" (buffer-string)))
-            ;; When file notification is used, it must be reenabled
-            ;; after recreation of the file.  We cannot expect that
-            ;; the descriptor is the same, so we just check the
-            ;; existence.
-            (should (eq (null desc) (null 
auto-revert-notify-watch-descriptor)))
-
-            ;; An empty file shall still be reverted.
-            (ert-with-message-capture auto-revert--messages
-              (sleep-for 1)
-              (write-region "" nil tmpfile nil 'no-message)
-              (auto-revert--wait-for-revert buf))
-            ;; Check, that the buffer has been reverted.
-            (should (string-equal "" (buffer-string)))))
-
-      ;; Exit.
-      (ignore-errors
-        (with-current-buffer buf (set-buffer-modified-p nil))
-        (kill-buffer buf))
-      (ignore-errors (delete-file tmpfile)))))
+  (with-auto-revert-test
+   (let ((tmpfile (make-temp-file "auto-revert-test"))
+         ;; Try to catch bug#32645.
+         (auto-revert-debug (getenv "EMACS_HYDRA_CI"))
+         (file-notify-debug (getenv "EMACS_HYDRA_CI"))
+         (times '(120 60 30 15))
+         buf desc)
+     (unwind-protect
+         (progn
+           (auto-revert-tests--write-file "any text" tmpfile (pop times))
+           (setq buf (find-file-noselect tmpfile))
+           (with-current-buffer buf
+             (should-not
+              (file-notify-valid-p auto-revert-notify-watch-descriptor))
+             (should (string-equal (buffer-string) "any text"))
+             ;; `buffer-stale--default-function' checks for
+             ;; `verify-visited-file-modtime'.  We must ensure that
+             ;; it returns nil.
+             (auto-revert-mode 1)
+             (should auto-revert-mode)
+             (setq desc auto-revert-notify-watch-descriptor)
+
+             ;; Remove file while reverting.  We simulate this by
+             ;; modifying `before-revert-hook'.
+             (add-hook
+              'before-revert-hook
+              (lambda ()
+                (when auto-revert-debug
+                  (message "%s deleted" buffer-file-name))
+                (delete-file buffer-file-name))
+              nil t)
+
+             (ert-with-message-capture auto-revert--messages
+               (auto-revert-tests--write-file "another text" tmpfile (pop 
times))
+               (auto-revert--wait-for-revert buf))
+             ;; Check, that the buffer hasn't been reverted.  File
+             ;; notification should be disabled, falling back to
+             ;; polling.
+             (should (string-match "any text" (buffer-string)))
+             ;; With w32notify, and on emba, the `stopped' events are not sent.
+             (or (eq file-notify--library 'w32notify)
+                 (getenv "EMACS_EMBA_CI")
+                 (should-not
+                  (file-notify-valid-p auto-revert-notify-watch-descriptor)))
+
+             ;; Once the file has been recreated, the buffer shall be
+             ;; reverted.
+             (kill-local-variable 'before-revert-hook)
+             (ert-with-message-capture auto-revert--messages
+               (auto-revert-tests--write-file "another text" tmpfile (pop 
times))
+               (auto-revert--wait-for-revert buf))
+             ;; Check, that the buffer has been reverted.
+             (should (string-match "another text" (buffer-string)))
+             ;; When file notification is used, it must be reenabled
+             ;; after recreation of the file.  We cannot expect that
+             ;; the descriptor is the same, so we just check the
+             ;; existence.
+             (should (eq (null desc) (null 
auto-revert-notify-watch-descriptor)))
+
+             ;; An empty file shall still be reverted.
+             (ert-with-message-capture auto-revert--messages
+               (auto-revert-tests--write-file "" tmpfile (pop times))
+               (auto-revert--wait-for-revert buf))
+             ;; Check, that the buffer has been reverted.
+             (should (string-equal "" (buffer-string)))))
+
+       ;; Exit.
+       (ignore-errors
+         (with-current-buffer buf (set-buffer-modified-p nil))
+         (kill-buffer buf))
+       (ignore-errors (delete-file tmpfile))))))
 
 (auto-revert--deftest-remote auto-revert-test02-auto-revert-deleted-file
   "Check autorevert for a deleted remote file.")
@@ -357,28 +362,25 @@ This expects `auto-revert--messages' to be bound by
   "Check autorevert tail mode."
   ;; `auto-revert-buffers' runs every 5".  And we must wait, until the
   ;; file has been reverted.
-  :tags '(:expensive-test)
   (let ((tmpfile (make-temp-file "auto-revert-test"))
+        (times '(30 15))
         buf)
     (unwind-protect
         (ert-with-message-capture auto-revert--messages
-          (write-region "any text" nil tmpfile nil 'no-message)
+          (auto-revert-tests--write-file "any text" tmpfile (pop times))
          (setq buf (find-file-noselect tmpfile))
          (with-current-buffer buf
             ;; `buffer-stale--default-function' checks for
             ;; `verify-visited-file-modtime'.  We must ensure that it
             ;; returns nil.
-            (sleep-for 1)
            (auto-revert-tail-mode 1)
            (should auto-revert-tail-mode)
             (erase-buffer)
             (insert "modified text\n")
             (set-buffer-modified-p nil)
 
-           ;; Modify file.  We wait for a second, in order to have
-           ;; another timestamp.
-           (sleep-for 1)
-            (write-region "another text" nil tmpfile 'append 'no-message)
+            ;; Modify file.
+            (auto-revert-tests--write-file "another text" tmpfile (pop times) 
'append)
 
            ;; Check, that the buffer has been reverted.
             (auto-revert--wait-for-revert buf)
@@ -396,50 +398,47 @@ This expects `auto-revert--messages' to be bound by
   "Check autorevert for dired."
   ;; `auto-revert-buffers' runs every 5".  And we must wait, until the
   ;; file has been reverted.
-  :tags '(:expensive-test)
-  (let* ((tmpfile (make-temp-file "auto-revert-test"))
-         (name (file-name-nondirectory tmpfile))
-         buf)
-    (unwind-protect
-       (progn
-         (setq buf (dired-noselect temporary-file-directory))
-         (with-current-buffer buf
-            ;; `buffer-stale--default-function' checks for
-            ;; `verify-visited-file-modtime'.  We must ensure that it
-            ;; returns nil.
-            (sleep-for 1)
-            (auto-revert-mode 1)
-            (should auto-revert-mode)
-           (should
-             (string-match name (substring-no-properties (buffer-string))))
-
-            (ert-with-message-capture auto-revert--messages
-              ;; Delete file.  We wait for a second, in order to have
-              ;; another timestamp.
-              (sleep-for 1)
-              (delete-file tmpfile)
-              (auto-revert--wait-for-revert buf))
-            ;; Check, that the buffer has been reverted.
-            (should-not
-             (string-match name (substring-no-properties (buffer-string))))
-
-            (ert-with-message-capture auto-revert--messages
-              ;; Make dired buffer modified.  Check, that the buffer has
-              ;; been still reverted.
-              (set-buffer-modified-p t)
-              (sleep-for 1)
-              (write-region "any text" nil tmpfile nil 'no-message)
-
-              (auto-revert--wait-for-revert buf))
-            ;; Check, that the buffer has been reverted.
-            (should
-             (string-match name (substring-no-properties (buffer-string))))))
-
-      ;; Exit.
-      (ignore-errors
-        (with-current-buffer buf (set-buffer-modified-p nil))
-        (kill-buffer buf))
-      (ignore-errors (delete-file tmpfile)))))
+  (with-auto-revert-test
+   (let* ((tmpfile (make-temp-file "auto-revert-test"))
+          (name (file-name-nondirectory tmpfile))
+          (times '(30))
+          buf)
+     (unwind-protect
+         (progn
+           (setq buf (dired-noselect temporary-file-directory))
+           (with-current-buffer buf
+             ;; `buffer-stale--default-function' checks for
+             ;; `verify-visited-file-modtime'.  We must ensure that it
+             ;; returns nil.
+             (auto-revert-mode 1)
+             (should auto-revert-mode)
+             (should
+              (string-match name (substring-no-properties (buffer-string))))
+
+             (ert-with-message-capture auto-revert--messages
+               ;; Delete file.
+               (delete-file tmpfile)
+               (auto-revert--wait-for-revert buf))
+             ;; Check, that the buffer has been reverted.
+             (should-not
+              (string-match name (substring-no-properties (buffer-string))))
+
+             (ert-with-message-capture auto-revert--messages
+               ;; Make dired buffer modified.  Check, that the buffer has
+               ;; been still reverted.
+               (set-buffer-modified-p t)
+               (auto-revert-tests--write-file "any text" tmpfile (pop times))
+
+               (auto-revert--wait-for-revert buf))
+             ;; Check, that the buffer has been reverted.
+             (should
+              (string-match name (substring-no-properties (buffer-string))))))
+
+       ;; Exit.
+       (ignore-errors
+         (with-current-buffer buf (set-buffer-modified-p nil))
+         (kill-buffer buf))
+       (ignore-errors (delete-file tmpfile))))))
 
 (auto-revert--deftest-remote auto-revert-test04-auto-revert-mode-dired
   "Check remote autorevert for dired.")
@@ -468,117 +467,116 @@ This expects `auto-revert--messages' to be bound by
 
 (ert-deftest auto-revert-test05-global-notify ()
   "Test `global-auto-revert-mode' without polling."
-  :tags '(:expensive-test)
   (skip-unless (or file-notify--library
                    (file-remote-p temporary-file-directory)))
-  (let* ((auto-revert-use-notify t)
-         (auto-revert-avoid-polling t)
-         (was-in-global-auto-revert-mode global-auto-revert-mode)
-         (file-1 (make-temp-file "global-auto-revert-test-1"))
-         (file-2 (make-temp-file "global-auto-revert-test-2"))
-         (file-3 (make-temp-file "global-auto-revert-test-3"))
-         (file-2b (concat file-2 "-b"))
-         require-final-newline buf-1 buf-2 buf-3)
-    (unwind-protect
-        (progn
-          (setq buf-1 (find-file-noselect file-1))
-          (setq buf-2 (find-file-noselect file-2))
-          (auto-revert-test--write-file "1-a" file-1)
-          (should (equal (auto-revert-test--buffer-string buf-1) ""))
-
-          (global-auto-revert-mode 1)   ; Turn it on.
-
-          (should (buffer-local-value
-                   'auto-revert-notify-watch-descriptor buf-1))
-          (should (buffer-local-value
-                   'auto-revert-notify-watch-descriptor buf-2))
-
-          ;; buf-1 should have been reverted immediately when the mode
-          ;; was enabled.
-          (should (equal (auto-revert-test--buffer-string buf-1) "1-a"))
-
-          ;; Alter a file.
-          (auto-revert-test--write-file "2-a" file-2)
-          ;; Allow for some time to handle notification events.
-          (auto-revert-test--wait-for-buffer-text buf-2 "2-a" 1)
-          (should (equal (auto-revert-test--buffer-string buf-2) "2-a"))
-
-          ;; Visit a file, and modify it on disk.
-          (setq buf-3 (find-file-noselect file-3))
-          ;; Newly opened buffers won't be use notification until the
-          ;; first poll cycle; wait for it.
-          (auto-revert-test--wait-for
-           (lambda () (buffer-local-value
-                       'auto-revert-notify-watch-descriptor buf-3))
-           auto-revert--timeout)
-          (should (buffer-local-value
+  (with-auto-revert-test
+   (let* ((auto-revert-use-notify t)
+          (auto-revert-avoid-polling t)
+          (was-in-global-auto-revert-mode global-auto-revert-mode)
+          (file-1 (make-temp-file "global-auto-revert-test-1"))
+          (file-2 (make-temp-file "global-auto-revert-test-2"))
+          (file-3 (make-temp-file "global-auto-revert-test-3"))
+          (file-2b (concat file-2 "-b"))
+          require-final-newline buf-1 buf-2 buf-3)
+     (unwind-protect
+         (progn
+           (setq buf-1 (find-file-noselect file-1))
+           (setq buf-2 (find-file-noselect file-2))
+           (auto-revert-test--write-file "1-a" file-1)
+           (should (equal (auto-revert-test--buffer-string buf-1) ""))
+
+           (global-auto-revert-mode 1)   ; Turn it on.
+
+           (should (buffer-local-value
+                    'auto-revert-notify-watch-descriptor buf-1))
+           (should (buffer-local-value
+                    'auto-revert-notify-watch-descriptor buf-2))
+
+           ;; buf-1 should have been reverted immediately when the mode
+           ;; was enabled.
+           (should (equal (auto-revert-test--buffer-string buf-1) "1-a"))
+
+           ;; Alter a file.
+           (auto-revert-test--write-file "2-a" file-2)
+           ;; Allow for some time to handle notification events.
+           (auto-revert-test--wait-for-buffer-text buf-2 "2-a" 1)
+           (should (equal (auto-revert-test--buffer-string buf-2) "2-a"))
+
+           ;; Visit a file, and modify it on disk.
+           (setq buf-3 (find-file-noselect file-3))
+           ;; Newly opened buffers won't be use notification until the
+           ;; first poll cycle; wait for it.
+           (auto-revert-test--wait-for
+            (lambda () (buffer-local-value
                    'auto-revert-notify-watch-descriptor buf-3))
-          (auto-revert-test--write-file "3-a" file-3)
-          (auto-revert-test--wait-for-buffer-text buf-3 "3-a" 1)
-          (should (equal (auto-revert-test--buffer-string buf-3) "3-a"))
-
-          ;; Delete a visited file, and re-create it with new contents.
-          (delete-file file-1)
-          (sleep-for 0.5)
-          (should (equal (auto-revert-test--buffer-string buf-1) "1-a"))
-          (auto-revert-test--write-file "1-b" file-1)
-          (auto-revert-test--wait-for-buffer-text
-           buf-1 "1-b" auto-revert--timeout)
-          (should (buffer-local-value
-                   'auto-revert-notify-watch-descriptor buf-1))
-
-          ;; Write a buffer to a new file, then modify the new file on disk.
-          (with-current-buffer buf-2
-            (write-file file-2b))
-          (should (equal (auto-revert-test--buffer-string buf-2) "2-a"))
-          (auto-revert-test--write-file "2-b" file-2b)
-          (auto-revert-test--wait-for-buffer-text
-           buf-2 "2-b" auto-revert--timeout)
-          (should (buffer-local-value
-                   'auto-revert-notify-watch-descriptor buf-2)))
-
-      ;; Clean up.
-      (unless was-in-global-auto-revert-mode
-        (global-auto-revert-mode 0))    ; Turn it off.
-      (dolist (buf (list buf-1 buf-2 buf-3))
-        (ignore-errors (kill-buffer buf)))
-      (dolist (file (list file-1 file-2 file-2b file-3))
-        (ignore-errors (delete-file file)))
-      )))
+            (auto-revert--timeout))
+           (should (buffer-local-value
+                    'auto-revert-notify-watch-descriptor buf-3))
+           (auto-revert-test--write-file "3-a" file-3)
+           (auto-revert-test--wait-for-buffer-text buf-3 "3-a" 1)
+           (should (equal (auto-revert-test--buffer-string buf-3) "3-a"))
+
+           ;; Delete a visited file, and re-create it with new contents.
+           (delete-file file-1)
+           (should (equal (auto-revert-test--buffer-string buf-1) "1-a"))
+           (auto-revert-test--write-file "1-b" file-1)
+           (auto-revert-test--wait-for-buffer-text
+            buf-1 "1-b" (auto-revert--timeout))
+           (should (buffer-local-value
+                    'auto-revert-notify-watch-descriptor buf-1))
+
+           ;; Write a buffer to a new file, then modify the new file on disk.
+           (with-current-buffer buf-2
+             (write-file file-2b))
+           (should (equal (auto-revert-test--buffer-string buf-2) "2-a"))
+           (auto-revert-test--write-file "2-b" file-2b)
+           (auto-revert-test--wait-for-buffer-text
+            buf-2 "2-b" (auto-revert--timeout))
+           (should (buffer-local-value
+                    'auto-revert-notify-watch-descriptor buf-2)))
+
+       ;; Clean up.
+       (unless was-in-global-auto-revert-mode
+         (global-auto-revert-mode 0))    ; Turn it off.
+       (dolist (buf (list buf-1 buf-2 buf-3))
+         (ignore-errors (kill-buffer buf)))
+       (dolist (file (list file-1 file-2 file-2b file-3))
+         (ignore-errors (delete-file file)))
+       ))))
 
 (auto-revert--deftest-remote auto-revert-test05-global-notify
   "Test `global-auto-revert-mode' without polling for remote buffers.")
 
 (ert-deftest auto-revert-test06-write-file ()
   "Verify that notification follows `write-file' correctly."
-  :tags '(:expensive-test)
   (skip-unless (or file-notify--library
                    (file-remote-p temporary-file-directory)))
-  (let* ((auto-revert-use-notify t)
-         (file-1 (make-temp-file "auto-revert-test"))
-         (file-2 (concat file-1 "-2"))
-         require-final-newline buf)
-    (unwind-protect
-        (progn
-          (setq buf (find-file-noselect file-1))
-          (with-current-buffer buf
-            (insert "A")
-            (save-buffer)
-
-            (auto-revert-mode 1)
-
-            (insert "B")
-            (write-file file-2)
-
-            (auto-revert-test--write-file "C" file-2)
-            (auto-revert-test--wait-for-buffer-text
-             buf "C" auto-revert--timeout)
-            (should (equal (buffer-string) "C"))))
-
-      ;; Clean up.
-      (ignore-errors (kill-buffer buf))
-      (ignore-errors (delete-file file-1))
-      (ignore-errors (delete-file file-2)))))
+  (with-auto-revert-test
+   (let* ((auto-revert-use-notify t)
+          (file-1 (make-temp-file "auto-revert-test"))
+          (file-2 (concat file-1 "-2"))
+          require-final-newline buf)
+     (unwind-protect
+         (progn
+           (setq buf (find-file-noselect file-1))
+           (with-current-buffer buf
+             (insert "A")
+             (save-buffer)
+
+             (auto-revert-mode 1)
+
+             (insert "B")
+             (write-file file-2)
+
+             (auto-revert-test--write-file "C" file-2)
+             (auto-revert-test--wait-for-buffer-text
+              buf "C" (auto-revert--timeout))
+             (should (equal (buffer-string) "C"))))
+
+       ;; Clean up.
+       (ignore-errors (kill-buffer buf))
+       (ignore-errors (delete-file file-1))
+       (ignore-errors (delete-file file-2))))))
 
 (auto-revert--deftest-remote auto-revert-test06-write-file
   "Test `write-file' in `auto-revert-mode' for remote buffers.")
diff --git a/test/lisp/bookmark-tests.el b/test/lisp/bookmark-tests.el
index 7cfd4ac..6745e4c 100644
--- a/test/lisp/bookmark-tests.el
+++ b/test/lisp/bookmark-tests.el
@@ -312,7 +312,7 @@ the lexically-bound variable `buffer'."
   (with-bookmark-test
    (should-error (bookmark-insert-annotation "a missing bookmark"))
    (bookmark-insert-annotation "name")
-   (should (equal (buffer-string) (bookmark-default-annotation-text "name"))))
+   (should (string-match "Type the annotation" (buffer-string))))
   (with-bookmark-test
    (bookmark-set-annotation "name" "some stuff")
    (bookmark-insert-annotation "name")
@@ -471,6 +471,8 @@ testing `bookmark-bmenu-list'."
    (insert "foo")
    (bookmark-send-edited-annotation)
    (should (equal (buffer-name (current-buffer)) bookmark-bmenu-buffer))
+   (beginning-of-line)
+   (forward-char 4)
    (should (looking-at "name"))))
 
 (ert-deftest bookmark-test-bmenu-toggle-filenames ()
@@ -503,6 +505,7 @@ testing `bookmark-bmenu-list'."
 (ert-deftest bookmark-test-bmenu-mark ()
   (with-bookmark-bmenu-test
    (bookmark-bmenu-mark)
+   (forward-line -1)
    (beginning-of-line)
    (should (looking-at "^>"))))
 
@@ -563,6 +566,7 @@ testing `bookmark-bmenu-list'."
    (bookmark-bmenu-mark)
    (goto-char (point-min))
    (bookmark-bmenu-unmark)
+   (forward-line -1)
    (beginning-of-line)
    (should (looking-at "^  "))))
 
diff --git 
a/test/lisp/calendar/icalendar-resources/import-bug-11473.diary-european 
b/test/lisp/calendar/icalendar-resources/import-bug-11473.diary-european
new file mode 100644
index 0000000..97348ae
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-11473.diary-european
@@ -0,0 +1,10 @@
+&15/5/2012 15:00-15:30 Query
+ Desc: 
+ Whassup?
+ 
+ 
+ Location: phone
+ Organizer: MAILTO:a.luser@foo.com
+ Status: CONFIRMED
+ Class: PUBLIC
+ UID: 
040000008200E00074C5B7101A82E0080000000020FFAED0CFEFCC01000000000000000010000000575268034ECDB649A15349B1BF240F15
diff --git a/test/lisp/calendar/icalendar-resources/import-bug-11473.ics 
b/test/lisp/calendar/icalendar-resources/import-bug-11473.ics
new file mode 100644
index 0000000..bc3a6c6
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-11473.ics
@@ -0,0 +1,54 @@
+BEGIN:VCALENDAR
+METHOD:REQUEST
+PRODID:Microsoft Exchange Server 2007
+VERSION:2.0
+BEGIN:VTIMEZONE
+TZID:(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna
+BEGIN:STANDARD
+DTSTART:16010101T030000
+TZOFFSETFROM:+0200
+TZOFFSETTO:+0100
+RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=10
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:16010101T020000
+TZOFFSETFROM:+0100
+TZOFFSETTO:+0200
+RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=3
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+ORGANIZER;CN="A. Luser":MAILTO:a.luser@foo.com
+ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN="Luser, Oth
+ er":MAILTO:other.luser@foo.com
+DESCRIPTION;LANGUAGE=en-US:\nWhassup?\n\n
+SUMMARY;LANGUAGE=en-US:Query
+DTSTART;TZID="(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna"
+ :20120515T150000
+DTEND;TZID="(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna":2
+ 0120515T153000
+UID:040000008200E00074C5B7101A82E0080000000020FFAED0CFEFCC01000000000000000
+ 010000000575268034ECDB649A15349B1BF240F15
+RECURRENCE-ID;TZID="(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, V
+ ienna":20120515T170000
+CLASS:PUBLIC
+PRIORITY:5
+DTSTAMP:20120514T153645Z
+TRANSP:OPAQUE
+STATUS:CONFIRMED
+SEQUENCE:15
+LOCATION;LANGUAGE=en-US:phone
+X-MICROSOFT-CDO-APPT-SEQUENCE:15
+X-MICROSOFT-CDO-OWNERAPPTID:1907632092
+X-MICROSOFT-CDO-BUSYSTATUS:TENTATIVE
+X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY
+X-MICROSOFT-CDO-ALLDAYEVENT:FALSE
+X-MICROSOFT-CDO-IMPORTANCE:1
+X-MICROSOFT-CDO-INSTTYPE:3
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:REMINDER
+TRIGGER;RELATED=START:-PT15M
+END:VALARM
+END:VEVENT
+END:VCALENDAR
\ No newline at end of file
diff --git 
a/test/lisp/calendar/icalendar-resources/import-bug-22092.diary-american 
b/test/lisp/calendar/icalendar-resources/import-bug-22092.diary-american
new file mode 100644
index 0000000..392345f
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-22092.diary-american
@@ -0,0 +1,6 @@
+&12/8/2014 18:30-22:55 Norwegian til Tromsoe-Langnes - 
+ Desc: Fly med Norwegian, reservasjon. Fra Stavanger til Troms&#248; 8. des 
2014 18:30, DY545Fly med Norwegian, reservasjon . Fra Stavanger til Troms&#248; 
8. des 2014 21:00, DY390
+ Location: Stavanger-Sola
+ Organizer: noreply@norwegian.no
+ Class: PUBLIC
+ UID: RFCALITEM1
diff --git 
a/test/lisp/calendar/icalendar-resources/import-bug-22092.diary-european 
b/test/lisp/calendar/icalendar-resources/import-bug-22092.diary-european
new file mode 100644
index 0000000..6a64cf6
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-22092.diary-european
@@ -0,0 +1,6 @@
+&8/12/2014 18:30-22:55 Norwegian til Tromsoe-Langnes - 
+ Desc: Fly med Norwegian, reservasjon. Fra Stavanger til Troms&#248; 8. des 
2014 18:30, DY545Fly med Norwegian, reservasjon . Fra Stavanger til Troms&#248; 
8. des 2014 21:00, DY390
+ Location: Stavanger-Sola
+ Organizer: noreply@norwegian.no
+ Class: PUBLIC
+ UID: RFCALITEM1
diff --git a/test/lisp/calendar/icalendar-resources/import-bug-22092.diary-iso 
b/test/lisp/calendar/icalendar-resources/import-bug-22092.diary-iso
new file mode 100644
index 0000000..e0fadbf
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-22092.diary-iso
@@ -0,0 +1,6 @@
+&2014/12/8 18:30-22:55 Norwegian til Tromsoe-Langnes - 
+ Desc: Fly med Norwegian, reservasjon. Fra Stavanger til Troms&#248; 8. des 
2014 18:30, DY545Fly med Norwegian, reservasjon . Fra Stavanger til Troms&#248; 
8. des 2014 21:00, DY390
+ Location: Stavanger-Sola
+ Organizer: noreply@norwegian.no
+ Class: PUBLIC
+ UID: RFCALITEM1
diff --git a/test/lisp/calendar/icalendar-resources/import-bug-22092.ics 
b/test/lisp/calendar/icalendar-resources/import-bug-22092.ics
new file mode 100644
index 0000000..4a4c679
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-22092.ics
@@ -0,0 +1,30 @@
+BEGIN:VCALENDAR
+PRODID:-//www.norwegian.no//iCalendar MIMEDIR//EN
+VERSION:2.0
+METHOD:REQUEST
+BEGIN:VEVENT
+UID:RFCALITEM1
+SEQUENCE:1512040950
+DTSTAMP:20141204T095043Z
+ORGANIZER:noreply@norwegian.no
+DTSTART:20141208T173000Z
+
+DTEND:20141208T215500Z
+
+LOCATION:Stavanger-Sola
+
+DESCRIPTION:Fly med Norwegian, reservasjon. Fra Stavanger til Troms&#248; 8. 
des 2014 18:30, DY545Fly med Norwegian, reservasjon . Fra Stavanger til 
Troms&#248; 8. des 2014 21:00, DY390
+
+X-ALT-DESC;FMTTYPE=text/html:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 
3.2//EN"><html><head><META NAME="Generator" CONTENT="MS Exchange Server version 
08.00.0681.000"><title></title></head><body><b><font face="Calibri" 
size="3">Reisereferanse</p></body></html>
+SUMMARY:Norwegian til Tromsoe-Langnes - 
+
+CATEGORIES:Appointment
+
+
+PRIORITY:5
+
+CLASS:PUBLIC
+
+TRANSP:OPAQUE
+END:VEVENT
+END:VCALENDAR
diff --git 
a/test/lisp/calendar/icalendar-resources/import-bug-24199.diary-american 
b/test/lisp/calendar/icalendar-resources/import-bug-24199.diary-american
new file mode 100644
index 0000000..b3308f1
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-24199.diary-american
@@ -0,0 +1,5 @@
+&%%(and (not (diary-date 1 6 2016)) (not (diary-date 2 3 2016)) (not 
(diary-date 3 2 2016)) (not (diary-date 5 4 2016)) (not (diary-date 6 1 2016)) 
(diary-float t 3 1) (diary-block 12 2 2015 1 1 9999)) 12:46-16:00 Summary
+ Desc: Desc
+ Location: Loc
+ Class: DEFAULT
+ UID: 9188710a-08a7-4061-bae3-d4cf4972599a
diff --git 
a/test/lisp/calendar/icalendar-resources/import-bug-24199.diary-european 
b/test/lisp/calendar/icalendar-resources/import-bug-24199.diary-european
new file mode 100644
index 0000000..acba714
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-24199.diary-european
@@ -0,0 +1,5 @@
+&%%(and (not (diary-date 6 1 2016)) (not (diary-date 3 2 2016)) (not 
(diary-date 2 3 2016)) (not (diary-date 4 5 2016)) (not (diary-date 1 6 2016)) 
(diary-float t 3 1) (diary-block 2 12 2015 1 1 9999)) 12:46-16:00 Summary
+ Desc: Desc
+ Location: Loc
+ Class: DEFAULT
+ UID: 9188710a-08a7-4061-bae3-d4cf4972599a
diff --git a/test/lisp/calendar/icalendar-resources/import-bug-24199.diary-iso 
b/test/lisp/calendar/icalendar-resources/import-bug-24199.diary-iso
new file mode 100644
index 0000000..2c18395
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-24199.diary-iso
@@ -0,0 +1,5 @@
+&%%(and (not (diary-date 2016 1 6)) (not (diary-date 2016 2 3)) (not 
(diary-date 2016 3 2)) (not (diary-date 2016 5 4)) (not (diary-date 2016 6 1)) 
(diary-float t 3 1) (diary-block 2015 12 2 9999 1 1)) 12:46-16:00 Summary
+ Desc: Desc
+ Location: Loc
+ Class: DEFAULT
+ UID: 9188710a-08a7-4061-bae3-d4cf4972599a
diff --git a/test/lisp/calendar/icalendar-resources/import-bug-24199.ics 
b/test/lisp/calendar/icalendar-resources/import-bug-24199.ics
new file mode 100644
index 0000000..a307c2d
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-24199.ics
@@ -0,0 +1,25 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:Summary
+DESCRIPTION:Desc
+LOCATION:Loc
+DTSTART:20151202T124600
+DTEND:20151202T160000
+RRULE:FREQ=MONTHLY;BYDAY=1WE;INTERVAL=1
+EXDATE:20160106T114600Z
+EXDATE:20160203T114600Z
+EXDATE:20160302T114600Z
+EXDATE:20160504T104600Z
+EXDATE:20160601T104600Z
+CLASS:DEFAULT
+TRANSP:OPAQUE
+BEGIN:VALARM
+ACTION:DISPLAY
+TRIGGER;VALUE=DURATION:-PT3H
+END:VALARM
+LAST-MODIFIED:20160805T191040Z
+UID:9188710a-08a7-4061-bae3-d4cf4972599a
+END:VEVENT
+END:VCALENDAR
diff --git 
a/test/lisp/calendar/icalendar-resources/import-bug-33277.diary-american 
b/test/lisp/calendar/icalendar-resources/import-bug-33277.diary-american
new file mode 100644
index 0000000..c546fa9
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-33277.diary-american
@@ -0,0 +1 @@
+&11/5/2018 21:00 event with same start/end time
diff --git 
a/test/lisp/calendar/icalendar-resources/import-bug-33277.diary-european 
b/test/lisp/calendar/icalendar-resources/import-bug-33277.diary-european
new file mode 100644
index 0000000..28e5396
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-33277.diary-european
@@ -0,0 +1 @@
+&5/11/2018 21:00 event with same start/end time
diff --git a/test/lisp/calendar/icalendar-resources/import-bug-33277.diary-iso 
b/test/lisp/calendar/icalendar-resources/import-bug-33277.diary-iso
new file mode 100644
index 0000000..faa7aea
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-33277.diary-iso
@@ -0,0 +1 @@
+&2018/11/5 21:00 event with same start/end time
diff --git a/test/lisp/calendar/icalendar-resources/import-bug-33277.ics 
b/test/lisp/calendar/icalendar-resources/import-bug-33277.ics
new file mode 100644
index 0000000..a4122a2
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-33277.ics
@@ -0,0 +1,15 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+DTSTART:20181105T200000Z
+DTSTAMP:20181105T181652Z
+DESCRIPTION:
+LAST-MODIFIED:20181105T181646Z
+LOCATION:
+SEQUENCE:0
+SUMMARY:event with same start/end time
+TRANSP:OPAQUE
+END:VEVENT
+END:VCALENDAR
+
diff --git 
a/test/lisp/calendar/icalendar-resources/import-bug-6766.diary-american 
b/test/lisp/calendar/icalendar-resources/import-bug-6766.diary-american
new file mode 100644
index 0000000..30deea9
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-6766.diary-american
@@ -0,0 +1,7 @@
+&%%(and (memq (calendar-day-of-week date) '(1 3 4 5)) (diary-cyclic 1 4 21 
2010)) 11:30-12:00 Scrum
+ Status: CONFIRMED
+ Class: PUBLIC
+ UID: 8814e3f9-7482-408f-996c-3bfe486a1262
+&%%(and (memq (calendar-day-of-week date) '(2 4)) (diary-cyclic 1 4 22 2010)) 
Tues + Thurs thinking
+ Class: PUBLIC
+ UID: 8814e3f9-7482-408f-996c-3bfe486a1263
diff --git 
a/test/lisp/calendar/icalendar-resources/import-bug-6766.diary-european 
b/test/lisp/calendar/icalendar-resources/import-bug-6766.diary-european
new file mode 100644
index 0000000..ba16c02
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-6766.diary-european
@@ -0,0 +1,7 @@
+&%%(and (memq (calendar-day-of-week date) '(1 3 4 5)) (diary-cyclic 1 21 4 
2010)) 11:30-12:00 Scrum
+ Status: CONFIRMED
+ Class: PUBLIC
+ UID: 8814e3f9-7482-408f-996c-3bfe486a1262
+&%%(and (memq (calendar-day-of-week date) '(2 4)) (diary-cyclic 1 22 4 2010)) 
Tues + Thurs thinking
+ Class: PUBLIC
+ UID: 8814e3f9-7482-408f-996c-3bfe486a1263
diff --git a/test/lisp/calendar/icalendar-resources/import-bug-6766.diary-iso 
b/test/lisp/calendar/icalendar-resources/import-bug-6766.diary-iso
new file mode 100644
index 0000000..7794e58
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-6766.diary-iso
@@ -0,0 +1,7 @@
+&%%(and (memq (calendar-day-of-week date) '(1 3 4 5)) (diary-cyclic 1 2010 4 
21)) 11:30-12:00 Scrum
+ Status: CONFIRMED
+ Class: PUBLIC
+ UID: 8814e3f9-7482-408f-996c-3bfe486a1262
+&%%(and (memq (calendar-day-of-week date) '(2 4)) (diary-cyclic 1 2010 4 22)) 
Tues + Thurs thinking
+ Class: PUBLIC
+ UID: 8814e3f9-7482-408f-996c-3bfe486a1263
diff --git a/test/lisp/calendar/icalendar-resources/import-bug-6766.ics 
b/test/lisp/calendar/icalendar-resources/import-bug-6766.ics
new file mode 100644
index 0000000..451391b
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-bug-6766.ics
@@ -0,0 +1,28 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+CLASS:PUBLIC
+DTEND;TZID=America/New_York:20100421T120000
+DTSTAMP:20100525T141214Z
+DTSTART;TZID=America/New_York:20100421T113000
+RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,WE,TH,FR
+SEQUENCE:1
+STATUS:CONFIRMED
+SUMMARY:Scrum
+TRANSP:OPAQUE
+UID:8814e3f9-7482-408f-996c-3bfe486a1262
+END:VEVENT
+BEGIN:VEVENT
+CLASS:PUBLIC
+DTSTAMP:20100525T141214Z
+DTSTART;VALUE=DATE:20100422
+DTEND;VALUE=DATE:20100423
+RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=TU,TH
+SEQUENCE:1
+SUMMARY:Tues + Thurs thinking
+TRANSP:OPAQUE
+UID:8814e3f9-7482-408f-996c-3bfe486a1263
+END:VEVENT
+END:VCALENDAR
+
diff --git 
a/test/lisp/calendar/icalendar-resources/import-duration-2.diary-american 
b/test/lisp/calendar/icalendar-resources/import-duration-2.diary-american
new file mode 100644
index 0000000..56f41d6
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-duration-2.diary-american
@@ -0,0 +1,3 @@
+&%%(and (diary-cyclic 1 12 21 2001) (diary-block 12 21 2001 12 29 2001))  
Urlaub
+ Class: PUBLIC
+ UID: 20041127T183329Z-18215-1001-4536-49109@andromeda
diff --git 
a/test/lisp/calendar/icalendar-resources/import-duration-2.diary-european 
b/test/lisp/calendar/icalendar-resources/import-duration-2.diary-european
new file mode 100644
index 0000000..999102a
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-duration-2.diary-european
@@ -0,0 +1,3 @@
+&%%(and (diary-cyclic 1 21 12 2001) (diary-block 21 12 2001 29 12 2001))  
Urlaub
+ Class: PUBLIC
+ UID: 20041127T183329Z-18215-1001-4536-49109@andromeda
diff --git a/test/lisp/calendar/icalendar-resources/import-duration-2.diary-iso 
b/test/lisp/calendar/icalendar-resources/import-duration-2.diary-iso
new file mode 100644
index 0000000..393937e
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-duration-2.diary-iso
@@ -0,0 +1,3 @@
+&%%(and (diary-cyclic 1 2001 12 21) (diary-block 2001 12 21 2001 12 29))  
Urlaub
+ Class: PUBLIC
+ UID: 20041127T183329Z-18215-1001-4536-49109@andromeda
diff --git a/test/lisp/calendar/icalendar-resources/import-duration-2.ics 
b/test/lisp/calendar/icalendar-resources/import-duration-2.ics
new file mode 100644
index 0000000..eb8a03b
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-duration-2.ics
@@ -0,0 +1,17 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+UID:20041127T183329Z-18215-1001-4536-49109@andromeda
+DTSTAMP:20041127T183315Z
+LAST-MODIFIED:20041127T183329
+SUMMARY:Urlaub
+DTSTART;VALUE=DATE:20011221
+DTEND;VALUE=DATE:20011221
+RRULE:FREQ=DAILY;UNTIL=20011229;INTERVAL=1;WKST=SU
+CLASS:PUBLIC
+SEQUENCE:1
+CREATED:20041127T183329
+END:VEVENT
+END:VCALENDAR
+
diff --git 
a/test/lisp/calendar/icalendar-resources/import-duration.diary-american 
b/test/lisp/calendar/icalendar-resources/import-duration.diary-american
new file mode 100644
index 0000000..268736a
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-duration.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-block 2 17 2005 2 23 2005)) duration
diff --git 
a/test/lisp/calendar/icalendar-resources/import-duration.diary-european 
b/test/lisp/calendar/icalendar-resources/import-duration.diary-european
new file mode 100644
index 0000000..7d852dd
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-duration.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-block 17 2 2005 23 2 2005)) duration
diff --git a/test/lisp/calendar/icalendar-resources/import-duration.diary-iso 
b/test/lisp/calendar/icalendar-resources/import-duration.diary-iso
new file mode 100644
index 0000000..5d3a714
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-duration.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-block 2005 2 17 2005 2 23)) duration
diff --git a/test/lisp/calendar/icalendar-resources/import-duration.ics 
b/test/lisp/calendar/icalendar-resources/import-duration.ics
new file mode 100644
index 0000000..67f5c73
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-duration.ics
@@ -0,0 +1,10 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20050217
+SUMMARY:duration
+DURATION:P7D
+END:VEVENT
+END:VCALENDAR
+
diff --git 
a/test/lisp/calendar/icalendar-resources/import-multiple-vcalendars.diary-american
 
b/test/lisp/calendar/icalendar-resources/import-multiple-vcalendars.diary-american
new file mode 100644
index 0000000..d1b1992
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-multiple-vcalendars.diary-american
@@ -0,0 +1,4 @@
+&7/23/2011 event-1
+&7/24/2011 event-2
+&7/25/2011 event-3a
+&7/25/2011 event-3b
diff --git 
a/test/lisp/calendar/icalendar-resources/import-multiple-vcalendars.diary-european
 
b/test/lisp/calendar/icalendar-resources/import-multiple-vcalendars.diary-european
new file mode 100644
index 0000000..f068354
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-multiple-vcalendars.diary-european
@@ -0,0 +1,4 @@
+&23/7/2011 event-1
+&24/7/2011 event-2
+&25/7/2011 event-3a
+&25/7/2011 event-3b
diff --git 
a/test/lisp/calendar/icalendar-resources/import-multiple-vcalendars.diary-iso 
b/test/lisp/calendar/icalendar-resources/import-multiple-vcalendars.diary-iso
new file mode 100644
index 0000000..5685e47
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-multiple-vcalendars.diary-iso
@@ -0,0 +1,4 @@
+&2011/7/23 event-1
+&2011/7/24 event-2
+&2011/7/25 event-3a
+&2011/7/25 event-3b
diff --git 
a/test/lisp/calendar/icalendar-resources/import-multiple-vcalendars.ics 
b/test/lisp/calendar/icalendar-resources/import-multiple-vcalendars.ics
new file mode 100644
index 0000000..69a02c0
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-multiple-vcalendars.ics
@@ -0,0 +1,21 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20110723
+SUMMARY:event-1
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20110724
+SUMMARY:event-2
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20110725
+SUMMARY:event-3a
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20110725
+SUMMARY:event-3b
+END:VEVENT
+END:VCALENDAR
+
diff --git 
a/test/lisp/calendar/icalendar-resources/import-non-recurring-1.diary-american 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-1.diary-american
new file mode 100644
index 0000000..780e3a8
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-1.diary-american
@@ -0,0 +1 @@
+&9/19/2003 09:00-11:30 non-recurring
diff --git 
a/test/lisp/calendar/icalendar-resources/import-non-recurring-1.diary-european 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-1.diary-european
new file mode 100644
index 0000000..7e0cd21
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-1.diary-european
@@ -0,0 +1 @@
+&19/9/2003 09:00-11:30 non-recurring
diff --git 
a/test/lisp/calendar/icalendar-resources/import-non-recurring-1.diary-iso 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-1.diary-iso
new file mode 100644
index 0000000..c731128
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-non-recurring-1.diary-iso
@@ -0,0 +1 @@
+&2003/9/19 09:00-11:30 non-recurring
diff --git a/test/lisp/calendar/icalendar-resources/import-non-recurring-1.ics 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-1.ics
new file mode 100644
index 0000000..cd471ef
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-non-recurring-1.ics
@@ -0,0 +1,10 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:non-recurring
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+END:VEVENT
+END:VCALENDAR
+
diff --git 
a/test/lisp/calendar/icalendar-resources/import-non-recurring-all-day.diary-american
 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-all-day.diary-american
new file mode 100644
index 0000000..1d4bb6a
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-all-day.diary-american
@@ -0,0 +1 @@
+&9/19/2003 non-recurring allday
diff --git 
a/test/lisp/calendar/icalendar-resources/import-non-recurring-all-day.diary-european
 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-all-day.diary-european
new file mode 100644
index 0000000..b56c7f4
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-all-day.diary-european
@@ -0,0 +1 @@
+&19/9/2003 non-recurring allday
diff --git 
a/test/lisp/calendar/icalendar-resources/import-non-recurring-all-day.diary-iso 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-all-day.diary-iso
new file mode 100644
index 0000000..f1c70ab
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-all-day.diary-iso
@@ -0,0 +1 @@
+&2003/9/19 non-recurring allday
diff --git 
a/test/lisp/calendar/icalendar-resources/import-non-recurring-all-day.ics 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-all-day.ics
new file mode 100644
index 0000000..4efa8ff
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-non-recurring-all-day.ics
@@ -0,0 +1,9 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:non-recurring allday
+DTSTART;VALUE=DATE-TIME:20030919
+END:VEVENT
+END:VCALENDAR
+
diff --git 
a/test/lisp/calendar/icalendar-resources/import-non-recurring-another-example.diary-american
 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-another-example.diary-american
new file mode 100644
index 0000000..2eb8c0a
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-another-example.diary-american
@@ -0,0 +1,4 @@
+&11/23/2004 14:45-15:45 another example
+ Status: TENTATIVE
+ Class: PRIVATE
+ UID: 6161a312-3902-11d9-b512-f764153bb28b
diff --git 
a/test/lisp/calendar/icalendar-resources/import-non-recurring-another-example.diary-european
 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-another-example.diary-european
new file mode 100644
index 0000000..394eae8
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-another-example.diary-european
@@ -0,0 +1,4 @@
+&23/11/2004 14:45-15:45 another example
+ Status: TENTATIVE
+ Class: PRIVATE
+ UID: 6161a312-3902-11d9-b512-f764153bb28b
diff --git 
a/test/lisp/calendar/icalendar-resources/import-non-recurring-another-example.diary-iso
 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-another-example.diary-iso
new file mode 100644
index 0000000..5e8bdf4
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-another-example.diary-iso
@@ -0,0 +1,4 @@
+&2004/11/23 14:45-15:45 another example
+ Status: TENTATIVE
+ Class: PRIVATE
+ UID: 6161a312-3902-11d9-b512-f764153bb28b
diff --git 
a/test/lisp/calendar/icalendar-resources/import-non-recurring-another-example.ics
 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-another-example.ics
new file mode 100644
index 0000000..b145e41
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-another-example.ics
@@ -0,0 +1,23 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+UID
+ :6161a312-3902-11d9-b512-f764153bb28b
+SUMMARY
+ :another example
+STATUS
+ :TENTATIVE
+CLASS
+ :PRIVATE
+X-MOZILLA-ALARM-DEFAULT-LENGTH
+ :0
+DTSTART
+ :20041123T144500
+DTEND
+ :20041123T154500
+DTSTAMP
+ :20041118T013641Z
+END:VEVENT
+END:VCALENDAR
+
diff --git 
a/test/lisp/calendar/icalendar-resources/import-non-recurring-block.diary-american
 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-block.diary-american
new file mode 100644
index 0000000..b222342
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-block.diary-american
@@ -0,0 +1,4 @@
+&%%(and (diary-block 7 19 2004 8 27 2004)) Sommerferien
+ Status: TENTATIVE
+ Class: PRIVATE
+ UID: 748f2da0-0d9b-11d8-97af-b4ec8686ea61
diff --git 
a/test/lisp/calendar/icalendar-resources/import-non-recurring-block.diary-european
 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-block.diary-european
new file mode 100644
index 0000000..8043482
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-block.diary-european
@@ -0,0 +1,4 @@
+&%%(and (diary-block 19 7 2004 27 8 2004)) Sommerferien
+ Status: TENTATIVE
+ Class: PRIVATE
+ UID: 748f2da0-0d9b-11d8-97af-b4ec8686ea61
diff --git 
a/test/lisp/calendar/icalendar-resources/import-non-recurring-block.diary-iso 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-block.diary-iso
new file mode 100644
index 0000000..e0f1896
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-block.diary-iso
@@ -0,0 +1,4 @@
+&%%(and (diary-block 2004 7 19 2004 8 27)) Sommerferien
+ Status: TENTATIVE
+ Class: PRIVATE
+ UID: 748f2da0-0d9b-11d8-97af-b4ec8686ea61
diff --git 
a/test/lisp/calendar/icalendar-resources/import-non-recurring-block.ics 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-block.ics
new file mode 100644
index 0000000..0c52ba3
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-non-recurring-block.ics
@@ -0,0 +1,16 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+UID:748f2da0-0d9b-11d8-97af-b4ec8686ea61
+SUMMARY:Sommerferien
+STATUS:TENTATIVE
+CLASS:PRIVATE
+X-MOZILLA-ALARM-DEFAULT-UNITS:Minuten
+X-MOZILLA-RECUR-DEFAULT-INTERVAL:0
+DTSTART;VALUE=DATE:20040719
+DTEND;VALUE=DATE:20040828
+DTSTAMP:20031103T011641Z
+END:VEVENT
+END:VCALENDAR
+
diff --git 
a/test/lisp/calendar/icalendar-resources/import-non-recurring-folded-summary.diary-american
 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-folded-summary.diary-american
new file mode 100644
index 0000000..2954d0c
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-folded-summary.diary-american
@@ -0,0 +1,4 @@
+&11/23/2004 14:00-14:30 folded summary
+ Status: TENTATIVE
+ Class: PRIVATE
+ UID: 04979712-3902-11d9-93dd-8f9f4afe08da
diff --git 
a/test/lisp/calendar/icalendar-resources/import-non-recurring-folded-summary.diary-european
 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-folded-summary.diary-european
new file mode 100644
index 0000000..7745fc8
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-folded-summary.diary-european
@@ -0,0 +1,4 @@
+&23/11/2004 14:00-14:30 folded summary
+ Status: TENTATIVE
+ Class: PRIVATE
+ UID: 04979712-3902-11d9-93dd-8f9f4afe08da
diff --git 
a/test/lisp/calendar/icalendar-resources/import-non-recurring-folded-summary.diary-iso
 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-folded-summary.diary-iso
new file mode 100644
index 0000000..8c19a95
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-folded-summary.diary-iso
@@ -0,0 +1,4 @@
+&2004/11/23 14:00-14:30 folded summary
+ Status: TENTATIVE
+ Class: PRIVATE
+ UID: 04979712-3902-11d9-93dd-8f9f4afe08da
diff --git 
a/test/lisp/calendar/icalendar-resources/import-non-recurring-folded-summary.ics
 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-folded-summary.ics
new file mode 100644
index 0000000..e3ecee9
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-folded-summary.ics
@@ -0,0 +1,25 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+UID
+ :04979712-3902-11d9-93dd-8f9f4afe08da
+SUMMARY
+ :folded summary
+STATUS
+ :TENTATIVE
+CLASS
+ :PRIVATE
+X-MOZILLA-ALARM-DEFAULT-LENGTH
+ :0
+DTSTART
+ :20041123T140000
+DTEND
+ :20041123T143000
+DTSTAMP
+ :20041118T013430Z
+LAST-MODIFIED
+ :20041118T013640Z
+END:VEVENT
+END:VCALENDAR
+
diff --git 
a/test/lisp/calendar/icalendar-resources/import-non-recurring-long-summary.diary-american
 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-long-summary.diary-american
new file mode 100644
index 0000000..84cd464
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-long-summary.diary-american
@@ -0,0 +1 @@
+&9/19/2003 long summary
diff --git 
a/test/lisp/calendar/icalendar-resources/import-non-recurring-long-summary.diary-european
 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-long-summary.diary-european
new file mode 100644
index 0000000..5d65242
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-long-summary.diary-european
@@ -0,0 +1 @@
+&19/9/2003 long summary
diff --git 
a/test/lisp/calendar/icalendar-resources/import-non-recurring-long-summary.diary-iso
 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-long-summary.diary-iso
new file mode 100644
index 0000000..d230052
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-long-summary.diary-iso
@@ -0,0 +1 @@
+&2003/9/19 long summary
diff --git 
a/test/lisp/calendar/icalendar-resources/import-non-recurring-long-summary.ics 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-long-summary.ics
new file mode 100644
index 0000000..39ae02f
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-non-recurring-long-summary.ics
@@ -0,0 +1,10 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:long 
+ summary
+DTSTART;VALUE=DATE:20030919
+END:VEVENT
+END:VCALENDAR
+
diff --git 
a/test/lisp/calendar/icalendar-resources/import-real-world-2003-05-29.diary-american
 
b/test/lisp/calendar/icalendar-resources/import-real-world-2003-05-29.diary-american
new file mode 100644
index 0000000..e6c8712
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-real-world-2003-05-29.diary-american
@@ -0,0 +1,6 @@
+&5/9/2003 07:00-12:00 On-Site Interview
+ Desc: 10:30am - Blah
+ Location: Cccc
+ Organizer: MAILTO:aaaaaaa@aaaaaaa.com
+ Status: CONFIRMED
+ UID: 
040000008200E00074C5B7101A82E0080000000080B6DE661216C301000000000000000010000000DB823520692542408ED02D7023F9DFF9
diff --git 
a/test/lisp/calendar/icalendar-resources/import-real-world-2003-05-29.diary-european
 
b/test/lisp/calendar/icalendar-resources/import-real-world-2003-05-29.diary-european
new file mode 100644
index 0000000..cecca07
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-real-world-2003-05-29.diary-european
@@ -0,0 +1,6 @@
+&9/5/2003 07:00-12:00 On-Site Interview
+ Desc: 10:30am - Blah
+ Location: Cccc
+ Organizer: MAILTO:aaaaaaa@aaaaaaa.com
+ Status: CONFIRMED
+ UID: 
040000008200E00074C5B7101A82E0080000000080B6DE661216C301000000000000000010000000DB823520692542408ED02D7023F9DFF9
diff --git 
a/test/lisp/calendar/icalendar-resources/import-real-world-2003-05-29.ics 
b/test/lisp/calendar/icalendar-resources/import-real-world-2003-05-29.ics
new file mode 100644
index 0000000..decc8df
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-real-world-2003-05-29.ics
@@ -0,0 +1,54 @@
+BEGIN:VCALENDAR
+METHOD:REQUEST
+PRODID:Microsoft CDO for Microsoft Exchange
+VERSION:2.0
+BEGIN:VTIMEZONE
+TZID:Kolkata, Chennai, Mumbai, New Delhi
+X-MICROSOFT-CDO-TZID:23
+BEGIN:STANDARD
+DTSTART:16010101T000000
+TZOFFSETFROM:+0530
+TZOFFSETTO:+0530
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:16010101T000000
+TZOFFSETFROM:+0530
+TZOFFSETTO:+0530
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20030509T043439Z
+DTSTART;TZID="Kolkata, Chennai, Mumbai, New Delhi":20030509T103000
+SUMMARY:On-Site Interview
+UID:040000008200E00074C5B7101A82E0080000000080B6DE661216C301000000000000000
+ 010000000DB823520692542408ED02D7023F9DFF9
+ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN="Xxxxx
+ xxx Xxxxxxxxxxxx":MAILTO:xxxxxxxx@xxxxxxx.com
+ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN="Yyyyyyy Y
+ yyyy":MAILTO:yyyyyyy@yyyyyyy.com
+ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN="Zzzz Zzzz
+ zz":MAILTO:zzzzzz@zzzzzzz.com
+ORGANIZER;CN="Aaaaaa Aaaaa":MAILTO:aaaaaaa@aaaaaaa.com
+LOCATION:Cccc
+DTEND;TZID="Kolkata, Chennai, Mumbai, New Delhi":20030509T153000
+DESCRIPTION:10:30am - Blah
+SEQUENCE:0
+PRIORITY:5
+CLASS:
+CREATED:20030509T043439Z
+LAST-MODIFIED:20030509T043459Z
+STATUS:CONFIRMED
+TRANSP:OPAQUE
+X-MICROSOFT-CDO-BUSYSTATUS:BUSY
+X-MICROSOFT-CDO-INSTTYPE:0
+X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY
+X-MICROSOFT-CDO-ALLDAYEVENT:FALSE
+X-MICROSOFT-CDO-IMPORTANCE:1
+X-MICROSOFT-CDO-OWNERAPPTID:126441427
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:REMINDER
+TRIGGER;RELATED=START:-PT00H15M00S
+END:VALARM
+END:VEVENT
+END:VCALENDAR
diff --git 
a/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18a.diary-american
 
b/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18a.diary-american
new file mode 100644
index 0000000..f2c9141
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18a.diary-american
@@ -0,0 +1,6 @@
+&6/23/2003 11:00-12:00 Dress Rehearsal for XXXX-XXXX
+ Desc: 753 Zeichen hier radiert
+ Location: 555 or TN 555-5555 ID 5555 & NochWas (see below)
+ Organizer: MAILTO:xxx@xxxxx.com
+ Status: CONFIRMED
+ UID: 
040000008200E00074C5B7101A82E00800000000608AA7DA9835C3010000000000000000100000007C3A6D65EE726E40B7F3D69A23BD567E
diff --git 
a/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18a.diary-european
 
b/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18a.diary-european
new file mode 100644
index 0000000..89cff58
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18a.diary-european
@@ -0,0 +1,6 @@
+&23/6/2003 11:00-12:00 Dress Rehearsal for XXXX-XXXX
+ Desc: 753 Zeichen hier radiert
+ Location: 555 or TN 555-5555 ID 5555 & NochWas (see below)
+ Organizer: MAILTO:xxx@xxxxx.com
+ Status: CONFIRMED
+ UID: 
040000008200E00074C5B7101A82E00800000000608AA7DA9835C3010000000000000000100000007C3A6D65EE726E40B7F3D69A23BD567E
diff --git 
a/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18a.ics 
b/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18a.ics
new file mode 100644
index 0000000..6bb5b05
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18a.ics
@@ -0,0 +1,36 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+DTSTAMP:20030618T195512Z
+DTSTART;TZID="Mountain Time (US & Canada)":20030623T110000
+SUMMARY:Dress Rehearsal for XXXX-XXXX
+UID:040000008200E00074C5B7101A82E00800000000608AA7DA9835C301000000000000000
+ 0100000007C3A6D65EE726E40B7F3D69A23BD567E
+ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN="AAAAA,AAA
+ AA (A-AAAAAAA,ex1)":MAILTO:aaaaa_aaaaa@aaaaa.com
+ORGANIZER;CN="ABCD,TECHTRAINING
+ (A-Americas,exgen1)":MAILTO:xxx@xxxxx.com
+LOCATION:555 or TN 555-5555 ID 5555 & NochWas (see below)
+DTEND;TZID="Mountain Time (US & Canada)":20030623T120000
+DESCRIPTION:753 Zeichen hier radiert
+SEQUENCE:0
+PRIORITY:5
+CLASS:
+CREATED:20030618T195518Z
+LAST-MODIFIED:20030618T195527Z
+STATUS:CONFIRMED
+TRANSP:OPAQUE
+X-MICROSOFT-CDO-BUSYSTATUS:BUSY
+X-MICROSOFT-CDO-INSTTYPE:0
+X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY
+X-MICROSOFT-CDO-ALLDAYEVENT:FALSE
+X-MICROSOFT-CDO-IMPORTANCE:1
+X-MICROSOFT-CDO-OWNERAPPTID:1022519251
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:REMINDER
+TRIGGER;RELATED=START:-PT00H15M00S
+END:VALARM
+END:VEVENT
+END:VCALENDAR
diff --git 
a/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18b.diary-american
 
b/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18b.diary-american
new file mode 100644
index 0000000..2c0774c
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18b.diary-american
@@ -0,0 +1,6 @@
+&6/23/2003 17:00-18:00 Updated: Dress Rehearsal for ABC01-15
+ Desc: Viele Zeichen standen hier früher
+ Location: 123 or TN 123-1234 ID abcd & SonstWo (see below)
+ Organizer: MAILTO:bbb@bbbbb.com
+ Status: CONFIRMED
+ UID: 
040000008200E00074C5B7101A82E00800000000608AA7DA9835C3010000000000000000100000007C3A6D65EE726E40B7F3D69A23BD567E
diff --git 
a/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18b.diary-european
 
b/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18b.diary-european
new file mode 100644
index 0000000..95aac16
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18b.diary-european
@@ -0,0 +1,6 @@
+&23/6/2003 17:00-18:00 Updated: Dress Rehearsal for ABC01-15
+ Desc: Viele Zeichen standen hier früher
+ Location: 123 or TN 123-1234 ID abcd & SonstWo (see below)
+ Organizer: MAILTO:bbb@bbbbb.com
+ Status: CONFIRMED
+ UID: 
040000008200E00074C5B7101A82E00800000000608AA7DA9835C3010000000000000000100000007C3A6D65EE726E40B7F3D69A23BD567E
diff --git 
a/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18b.ics 
b/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18b.ics
new file mode 100644
index 0000000..1523135
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-real-world-2003-06-18b.ics
@@ -0,0 +1,55 @@
+BEGIN:VCALENDAR
+METHOD:REQUEST
+PRODID:Microsoft CDO for Microsoft Exchange
+VERSION:2.0
+BEGIN:VTIMEZONE
+TZID:Mountain Time (US & Canada)
+X-MICROSOFT-CDO-TZID:12
+BEGIN:STANDARD
+DTSTART:16010101T020000
+TZOFFSETFROM:-0600
+TZOFFSETTO:-0700
+RRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=10;BYDAY=-1SU
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:16010101T020000
+TZOFFSETFROM:-0700
+TZOFFSETTO:-0600
+RRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=4;BYDAY=1SU
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20030618T230323Z
+DTSTART;TZID="Mountain Time (US & Canada)":20030623T090000
+SUMMARY:Updated: Dress Rehearsal for ABC01-15
+UID:040000008200E00074C5B7101A82E00800000000608AA7DA9835C301000000000000000
+ 0100000007C3A6D65EE726E40B7F3D69A23BD567E
+ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;X-REPLYTIME=20030618T20
+ 0700Z;RSVP=TRUE;CN="AAAAA,AAAAAA
+\(A-AAAAAAA,ex1)":MAILTO:aaaaaa_aaaaa@aaaaa
+ .com
+ORGANIZER;CN="ABCD,TECHTRAINING
+\(A-Americas,exgen1)":MAILTO:bbb@bbbbb.com
+LOCATION:123 or TN 123-1234 ID abcd & SonstWo (see below)
+DTEND;TZID="Mountain Time (US & Canada)":20030623T100000
+DESCRIPTION:Viele Zeichen standen hier früher
+SEQUENCE:0
+PRIORITY:5
+CLASS:
+CREATED:20030618T230326Z
+LAST-MODIFIED:20030618T230335Z
+STATUS:CONFIRMED
+TRANSP:OPAQUE
+X-MICROSOFT-CDO-BUSYSTATUS:BUSY
+X-MICROSOFT-CDO-INSTTYPE:0
+X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY
+X-MICROSOFT-CDO-ALLDAYEVENT:FALSE
+X-MICROSOFT-CDO-IMPORTANCE:1
+X-MICROSOFT-CDO-OWNERAPPTID:1022519251
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:REMINDER
+TRIGGER;RELATED=START:-PT00H15M00S
+END:VALARM
+END:VEVENT
+END:VCALENDAR
\ No newline at end of file
diff --git 
a/test/lisp/calendar/icalendar-resources/import-real-world-2004-11-19.diary-american
 
b/test/lisp/calendar/icalendar-resources/import-real-world-2004-11-19.diary-american
new file mode 100644
index 0000000..a986f70
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-real-world-2004-11-19.diary-american
@@ -0,0 +1,19 @@
+&11/23/2004 14:00-14:30 Jjjjj & Wwwww
+ Status: TENTATIVE
+ Class: PRIVATE
+&11/23/2004 14:45-15:45 BB Aaaaaaaa Bbbbb
+ Status: TENTATIVE
+ Class: PRIVATE
+&11/23/2004 11:00-12:00 Hhhhhhhh
+ Status: TENTATIVE
+ Class: PRIVATE
+&%%(and (diary-cyclic 14 11 12 2004)) 14:00-18:30 MMM Aaaaaaaaa
+ Status: TENTATIVE
+ Class: PRIVATE
+&%%(and (diary-block 11 19 2004 11 19 2004)) Rrrr/Cccccc ii Aaaaaaaa
+ Desc: Vvvvv Rrrr aaa Cccccc
+ Status: TENTATIVE
+ Class: PRIVATE
+&%%(and (diary-cyclic 7 11 1 2004)) Wwww aa hhhh
+ Status: TENTATIVE
+ Class: PRIVATE
diff --git 
a/test/lisp/calendar/icalendar-resources/import-real-world-2004-11-19.diary-european
 
b/test/lisp/calendar/icalendar-resources/import-real-world-2004-11-19.diary-european
new file mode 100644
index 0000000..cbfe99e
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-real-world-2004-11-19.diary-european
@@ -0,0 +1,19 @@
+&23/11/2004 14:00-14:30 Jjjjj & Wwwww
+ Status: TENTATIVE
+ Class: PRIVATE
+&23/11/2004 14:45-15:45 BB Aaaaaaaa Bbbbb
+ Status: TENTATIVE
+ Class: PRIVATE
+&23/11/2004 11:00-12:00 Hhhhhhhh
+ Status: TENTATIVE
+ Class: PRIVATE
+&%%(and (diary-cyclic 14 12 11 2004)) 14:00-18:30 MMM Aaaaaaaaa
+ Status: TENTATIVE
+ Class: PRIVATE
+&%%(and (diary-block 19 11 2004 19 11 2004)) Rrrr/Cccccc ii Aaaaaaaa
+ Desc: Vvvvv Rrrr aaa Cccccc
+ Status: TENTATIVE
+ Class: PRIVATE
+&%%(and (diary-cyclic 7 1 11 2004)) Wwww aa hhhh
+ Status: TENTATIVE
+ Class: PRIVATE
diff --git 
a/test/lisp/calendar/icalendar-resources/import-real-world-2004-11-19.ics 
b/test/lisp/calendar/icalendar-resources/import-real-world-2004-11-19.ics
new file mode 100644
index 0000000..9edb682
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-real-world-2004-11-19.ics
@@ -0,0 +1,120 @@
+BEGIN:VCALENDAR
+VERSION
+ :2.0
+PRODID
+ :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN
+BEGIN:VEVENT
+SUMMARY
+ :Jjjjj & Wwwww
+STATUS
+ :TENTATIVE
+CLASS
+ :PRIVATE
+X-MOZILLA-ALARM-DEFAULT-LENGTH
+ :0
+DTSTART
+ :20041123T140000
+DTEND
+ :20041123T143000
+DTSTAMP
+ :20041118T013430Z
+LAST-MODIFIED
+ :20041118T013640Z
+END:VEVENT
+BEGIN:VEVENT
+SUMMARY
+ :BB Aaaaaaaa Bbbbb
+STATUS
+ :TENTATIVE
+CLASS
+ :PRIVATE
+X-MOZILLA-ALARM-DEFAULT-LENGTH
+ :0
+DTSTART
+ :20041123T144500
+DTEND
+ :20041123T154500
+DTSTAMP
+ :20041118T013641Z
+END:VEVENT
+BEGIN:VEVENT
+SUMMARY
+ :Hhhhhhhh
+STATUS
+ :TENTATIVE
+CLASS
+ :PRIVATE
+X-MOZILLA-ALARM-DEFAULT-LENGTH
+ :0
+DTSTART
+ :20041123T110000
+DTEND
+ :20041123T120000
+DTSTAMP
+ :20041118T013831Z
+END:VEVENT
+BEGIN:VEVENT
+SUMMARY
+ :MMM Aaaaaaaaa
+STATUS
+ :TENTATIVE
+CLASS
+ :PRIVATE
+X-MOZILLA-ALARM-DEFAULT-LENGTH
+ :0
+X-MOZILLA-RECUR-DEFAULT-INTERVAL
+ :2
+RRULE
+ :FREQ=WEEKLY;INTERVAL=2;BYDAY=FR
+DTSTART
+ :20041112T140000
+DTEND
+ :20041112T183000
+DTSTAMP
+ :20041118T014117Z
+END:VEVENT
+BEGIN:VEVENT
+SUMMARY
+ :Rrrr/Cccccc ii Aaaaaaaa
+DESCRIPTION
+ :Vvvvv Rrrr aaa Cccccc
+STATUS
+ :TENTATIVE
+CLASS
+ :PRIVATE
+X-MOZILLA-ALARM-DEFAULT-LENGTH
+ :0
+DTSTART
+ ;VALUE=DATE
+ :20041119
+DTEND
+ ;VALUE=DATE
+ :20041120
+DTSTAMP
+ :20041118T013107Z
+LAST-MODIFIED
+ :20041118T014203Z
+END:VEVENT
+BEGIN:VEVENT
+SUMMARY
+ :Wwww aa hhhh
+STATUS
+ :TENTATIVE
+CLASS
+ :PRIVATE
+X-MOZILLA-ALARM-DEFAULT-LENGTH
+ :0
+RRULE
+ :FREQ=WEEKLY;INTERVAL=1;BYDAY=MO
+DTSTART
+ ;VALUE=DATE
+ :20041101
+DTEND
+ ;VALUE=DATE
+ :20041102
+DTSTAMP
+ :20041118T014045Z
+LAST-MODIFIED
+ :20041118T023846Z
+END:VEVENT
+END:VCALENDAR
diff --git 
a/test/lisp/calendar/icalendar-resources/import-real-world-2005-02-07.diary-american
 
b/test/lisp/calendar/icalendar-resources/import-real-world-2005-02-07.diary-american
new file mode 100644
index 0000000..ce7d835
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-real-world-2005-02-07.diary-american
@@ -0,0 +1,5 @@
+&%%(and (diary-block 2 6 2005 2 6 2005)) Waitangi Day
+ Desc: abcdef
+ Status: CONFIRMED
+ Class: PRIVATE
+ UID: b60d398e-1dd1-11b2-a159-cf8cb05139f4
diff --git 
a/test/lisp/calendar/icalendar-resources/import-real-world-2005-02-07.diary-european
 
b/test/lisp/calendar/icalendar-resources/import-real-world-2005-02-07.diary-european
new file mode 100644
index 0000000..3a52b0a
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-real-world-2005-02-07.diary-european
@@ -0,0 +1,5 @@
+&%%(and (diary-block 6 2 2005 6 2 2005)) Waitangi Day
+ Desc: abcdef
+ Status: CONFIRMED
+ Class: PRIVATE
+ UID: b60d398e-1dd1-11b2-a159-cf8cb05139f4
diff --git 
a/test/lisp/calendar/icalendar-resources/import-real-world-2005-02-07.ics 
b/test/lisp/calendar/icalendar-resources/import-real-world-2005-02-07.ics
new file mode 100644
index 0000000..9eec71f
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-real-world-2005-02-07.ics
@@ -0,0 +1,26 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+UID
+ :b60d398e-1dd1-11b2-a159-cf8cb05139f4
+SUMMARY
+ :Waitangi Day
+DESCRIPTION
+ :abcdef
+CATEGORIES
+ :Public Holiday
+STATUS
+ :CONFIRMED
+CLASS
+ :PRIVATE
+DTSTART
+ ;VALUE=DATE
+ :20050206
+DTEND
+ ;VALUE=DATE
+ :20050207
+DTSTAMP
+ :20050128T011209Z
+END:VEVENT
+END:VCALENDAR
diff --git 
a/test/lisp/calendar/icalendar-resources/import-real-world-2005-03-01.diary-american
 
b/test/lisp/calendar/icalendar-resources/import-real-world-2005-03-01.diary-american
new file mode 100644
index 0000000..23c93d4
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-real-world-2005-03-01.diary-american
@@ -0,0 +1,2 @@
+&%%(and (diary-block 2 17 2005 2 23 2005)) Hhhhhh Aaaaa ii Aaaaaaaa
+ UID: 6AFA7558-6994-11D9-8A3A-000A95A0E830-RID
diff --git 
a/test/lisp/calendar/icalendar-resources/import-real-world-2005-03-01.diary-european
 
b/test/lisp/calendar/icalendar-resources/import-real-world-2005-03-01.diary-european
new file mode 100644
index 0000000..106e9f3
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-real-world-2005-03-01.diary-european
@@ -0,0 +1,2 @@
+&%%(and (diary-block 17 2 2005 23 2 2005)) Hhhhhh Aaaaa ii Aaaaaaaa
+ UID: 6AFA7558-6994-11D9-8A3A-000A95A0E830-RID
diff --git 
a/test/lisp/calendar/icalendar-resources/import-real-world-2005-03-01.ics 
b/test/lisp/calendar/icalendar-resources/import-real-world-2005-03-01.ics
new file mode 100644
index 0000000..ed9faa9
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-real-world-2005-03-01.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20050217
+SUMMARY:Hhhhhh Aaaaa ii Aaaaaaaa
+UID:6AFA7558-6994-11D9-8A3A-000A95A0E830-RID
+DTSTAMP:20050118T210335Z
+DURATION:P7D
+END:VEVENT
+END:VCALENDAR
diff --git 
a/test/lisp/calendar/icalendar-resources/import-real-world-no-dst.diary-american
 
b/test/lisp/calendar/icalendar-resources/import-real-world-no-dst.diary-american
new file mode 100644
index 0000000..290edb8
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-real-world-no-dst.diary-american
@@ -0,0 +1,4 @@
+&11/16/2014 04:30-05:30 NoDST
+ Desc: Test event from timezone without DST
+ Location: Everywhere
+ UID: 20141116T171439Z-678877132@marudot.com
diff --git 
a/test/lisp/calendar/icalendar-resources/import-real-world-no-dst.diary-european
 
b/test/lisp/calendar/icalendar-resources/import-real-world-no-dst.diary-european
new file mode 100644
index 0000000..c56b7a6
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-real-world-no-dst.diary-european
@@ -0,0 +1,4 @@
+&16/11/2014 04:30-05:30 NoDST
+ Desc: Test event from timezone without DST
+ Location: Everywhere
+ UID: 20141116T171439Z-678877132@marudot.com
diff --git 
a/test/lisp/calendar/icalendar-resources/import-real-world-no-dst.ics 
b/test/lisp/calendar/icalendar-resources/import-real-world-no-dst.ics
new file mode 100644
index 0000000..5f147af
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-real-world-no-dst.ics
@@ -0,0 +1,26 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//www.marudot.com//iCal Event Maker
+X-WR-CALNAME:Test
+CALSCALE:GREGORIAN
+BEGIN:VTIMEZONE
+TZID:Asia/Tehran
+TZURL:http://tzurl.org/zoneinfo-outlook/Asia/Tehran
+X-LIC-LOCATION:Asia/Tehran
+BEGIN:STANDARD
+TZOFFSETFROM:+0330
+TZOFFSETTO:+0330
+TZNAME:IRST
+DTSTART:19700101T000000
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20141116T171439Z
+UID:20141116T171439Z-678877132@marudot.com
+DTSTART;TZID="Asia/Tehran":20141116T070000
+DTEND;TZID="Asia/Tehran":20141116T080000
+SUMMARY:NoDST
+DESCRIPTION:Test event from timezone without DST
+LOCATION:Everywhere
+END:VEVENT
+END:VCALENDAR
\ No newline at end of file
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-american
 
b/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-american
new file mode 100644
index 0000000..7b86b55
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-anniversary 8 15 2004))  Maria Himmelfahrt
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-european
 
b/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-european
new file mode 100644
index 0000000..3b82ec0
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-anniversary 15 8 2004))  Maria Himmelfahrt
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-iso 
b/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-iso
new file mode 100644
index 0000000..7fc9947
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-anniversary 2004 8 15))  Maria Himmelfahrt
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.ics 
b/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.ics
new file mode 100644
index 0000000..2996f49
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20040815
+DTEND;VALUE=DATE:20040816
+SUMMARY:Maria Himmelfahrt
+RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=8
+END:VEVENT
+END:VCALENDAR
+
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-count-bi-weekly.diary-american
 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-bi-weekly.diary-american
new file mode 100644
index 0000000..84b6d10
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-bi-weekly.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 14 9 19 2003) (diary-block 9 19 2003 10 31 2003)) 
09:00-11:30 rrule count bi-weekly 3 times
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-count-bi-weekly.diary-european
 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-bi-weekly.diary-european
new file mode 100644
index 0000000..0bebdf8
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-bi-weekly.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 14 19 9 2003) (diary-block 19 9 2003 31 10 2003)) 
09:00-11:30 rrule count bi-weekly 3 times
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-count-bi-weekly.diary-iso 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-bi-weekly.diary-iso
new file mode 100644
index 0000000..1142908
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-bi-weekly.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 14 2003 9 19) (diary-block 2003 9 19 2003 10 31)) 
09:00-11:30 rrule count bi-weekly 3 times
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-count-bi-weekly.ics 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-bi-weekly.ics
new file mode 100644
index 0000000..888b85b
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-bi-weekly.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule count bi-weekly 3 times
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=WEEKLY;COUNT=3;INTERVAL=2
+END:VEVENT
+END:VCALENDAR
+
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-long.diary-american
 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-long.diary-american
new file mode 100644
index 0000000..23fe9fc
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-long.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 1 9 19 2003) (diary-block 9 19 2003 10 2 2003)) 
09:00-11:30 rrule count daily long
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-long.diary-european
 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-long.diary-european
new file mode 100644
index 0000000..0d4ab66
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-long.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 1 19 9 2003) (diary-block 19 9 2003 2 10 2003)) 
09:00-11:30 rrule count daily long
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-long.diary-iso
 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-long.diary-iso
new file mode 100644
index 0000000..8cecda5
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-long.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 1 2003 9 19) (diary-block 2003 9 19 2003 10 2)) 
09:00-11:30 rrule count daily long
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-long.ics 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-long.ics
new file mode 100644
index 0000000..73df19a
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-long.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule count daily long
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=DAILY;COUNT=14;INTERVAL=1
+END:VEVENT
+END:VCALENDAR
+
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-short.diary-american
 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-short.diary-american
new file mode 100644
index 0000000..d69bb08
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-short.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 1 9 19 2003) (diary-block 9 19 2003 9 19 2003)) 
09:00-11:30 rrule count daily short
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-short.diary-european
 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-short.diary-european
new file mode 100644
index 0000000..33a1ce4
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-short.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 1 19 9 2003) (diary-block 19 9 2003 19 9 2003)) 
09:00-11:30 rrule count daily short
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-short.diary-iso
 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-short.diary-iso
new file mode 100644
index 0000000..a06bcba
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-short.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 1 2003 9 19) (diary-block 2003 9 19 2003 9 19)) 
09:00-11:30 rrule count daily short
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-short.ics 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-short.ics
new file mode 100644
index 0000000..92ffe8b
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-daily-short.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule count daily short
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=DAILY;COUNT=1;INTERVAL=1
+END:VEVENT
+END:VCALENDAR
+
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-month.diary-american
 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-month.diary-american
new file mode 100644
index 0000000..4ce8ef8
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-month.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-date t 19 t) (diary-block 9 19 2003 5 19 2004)) 09:00-11:30 
rrule count every second month
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-month.diary-european
 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-month.diary-european
new file mode 100644
index 0000000..09ec375
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-month.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-date 19 t t) (diary-block 19 9 2003 19 5 2004)) 09:00-11:30 
rrule count every second month
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-month.diary-iso
 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-month.diary-iso
new file mode 100644
index 0000000..ae6feb7
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-month.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-date t t 19) (diary-block 2003 9 19 2004 5 19)) 09:00-11:30 
rrule count every second month
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-month.ics
 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-month.ics
new file mode 100644
index 0000000..3b27b66
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-month.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule count every second month
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=5
+END:VEVENT
+END:VCALENDAR
+
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-year.diary-american
 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-year.diary-american
new file mode 100644
index 0000000..99543aa
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-year.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-date 9 19 t) (diary-block 9 19 2003 9 19 2011)) 09:00-11:30 
rrule count every second year
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-year.diary-european
 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-year.diary-european
new file mode 100644
index 0000000..3b33088
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-year.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-date 19 9 t) (diary-block 19 9 2003 19 9 2011)) 09:00-11:30 
rrule count every second year
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-year.diary-iso
 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-year.diary-iso
new file mode 100644
index 0000000..16af52e
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-year.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-date t 9 19) (diary-block 2003 9 19 2011 9 19)) 09:00-11:30 
rrule count every second year
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-year.ics
 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-year.ics
new file mode 100644
index 0000000..ce21c34
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-every-second-year.ics
@@ -0,0 +1,10 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule count every second year
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=5
+END:VEVENT
+END:VCALENDAR
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-count-monthly.diary-american
 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-monthly.diary-american
new file mode 100644
index 0000000..ad5ca0b
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-monthly.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-date t 19 t) (diary-block 9 19 2003 1 19 2004)) 09:00-11:30 
rrule count monthly
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-count-monthly.diary-european
 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-monthly.diary-european
new file mode 100644
index 0000000..709de3a
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-monthly.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-date 19 t t) (diary-block 19 9 2003 19 1 2004)) 09:00-11:30 
rrule count monthly
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-count-monthly.diary-iso 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-monthly.diary-iso
new file mode 100644
index 0000000..9fc2a2d
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-monthly.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-date t t 19) (diary-block 2003 9 19 2004 1 19)) 09:00-11:30 
rrule count monthly
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-count-monthly.ics 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-monthly.ics
new file mode 100644
index 0000000..3391ca2
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-monthly.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule count monthly
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=MONTHLY;INTERVAL=1;COUNT=5
+END:VEVENT
+END:VCALENDAR
+
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-count-yearly.diary-american
 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-yearly.diary-american
new file mode 100644
index 0000000..8c1f95b
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-yearly.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-date 9 19 t) (diary-block 9 19 2003 9 19 2007)) 09:00-11:30 
rrule count yearly
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-count-yearly.diary-european
 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-yearly.diary-european
new file mode 100644
index 0000000..e216e22
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-yearly.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-date 19 9 t) (diary-block 19 9 2003 19 9 2007)) 09:00-11:30 
rrule count yearly
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-count-yearly.diary-iso 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-yearly.diary-iso
new file mode 100644
index 0000000..3801192
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-yearly.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-date t 9 19) (diary-block 2003 9 19 2007 9 19)) 09:00-11:30 
rrule count yearly
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-count-yearly.ics 
b/test/lisp/calendar/icalendar-resources/import-rrule-count-yearly.ics
new file mode 100644
index 0000000..d856993
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-count-yearly.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule count yearly
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=YEARLY;INTERVAL=1;COUNT=5
+END:VEVENT
+END:VCALENDAR
+
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-daily-two-day.diary-american
 
b/test/lisp/calendar/icalendar-resources/import-rrule-daily-two-day.diary-american
new file mode 100644
index 0000000..495fca5
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-daily-two-day.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 2 9 19 2003)) 09:00-11:30 rrule daily
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-daily-two-day.diary-european
 
b/test/lisp/calendar/icalendar-resources/import-rrule-daily-two-day.diary-european
new file mode 100644
index 0000000..61db14a
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-daily-two-day.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 2 19 9 2003)) 09:00-11:30 rrule daily
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-daily-two-day.diary-iso 
b/test/lisp/calendar/icalendar-resources/import-rrule-daily-two-day.diary-iso
new file mode 100644
index 0000000..0e0a4b1
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-daily-two-day.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 2 2003 9 19)) 09:00-11:30 rrule daily
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-daily-two-day.ics 
b/test/lisp/calendar/icalendar-resources/import-rrule-daily-two-day.ics
new file mode 100644
index 0000000..8c9cb3b
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-daily-two-day.ics
@@ -0,0 +1,10 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule daily
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=DAILY;INTERVAL=2
+END:VEVENT
+END:VCALENDAR
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-daily-with-exceptions.diary-american
 
b/test/lisp/calendar/icalendar-resources/import-rrule-daily-with-exceptions.diary-american
new file mode 100644
index 0000000..83e5f58
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-daily-with-exceptions.diary-american
@@ -0,0 +1 @@
+&%%(and (not (diary-date 9 25 2003)) (not (diary-date 9 21 2003)) 
(diary-cyclic 2 9 19 2003)) 09:00-11:30 rrule daily with exceptions
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-daily-with-exceptions.diary-european
 
b/test/lisp/calendar/icalendar-resources/import-rrule-daily-with-exceptions.diary-european
new file mode 100644
index 0000000..a3c7fdd
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-daily-with-exceptions.diary-european
@@ -0,0 +1 @@
+&%%(and (not (diary-date 25 9 2003)) (not (diary-date 21 9 2003)) 
(diary-cyclic 2 19 9 2003)) 09:00-11:30 rrule daily with exceptions
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-daily-with-exceptions.diary-iso
 
b/test/lisp/calendar/icalendar-resources/import-rrule-daily-with-exceptions.diary-iso
new file mode 100644
index 0000000..88b4c89
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-daily-with-exceptions.diary-iso
@@ -0,0 +1 @@
+&%%(and (not (diary-date 2003 9 25)) (not (diary-date 2003 9 21)) 
(diary-cyclic 2 2003 9 19)) 09:00-11:30 rrule daily with exceptions
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-daily-with-exceptions.ics 
b/test/lisp/calendar/icalendar-resources/import-rrule-daily-with-exceptions.ics
new file mode 100644
index 0000000..5284bf4
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-daily-with-exceptions.ics
@@ -0,0 +1,12 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule daily with exceptions
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=DAILY;INTERVAL=2
+EXDATE:20030921,20030925
+END:VEVENT
+END:VCALENDAR
+
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-daily.diary-american 
b/test/lisp/calendar/icalendar-resources/import-rrule-daily.diary-american
new file mode 100644
index 0000000..9213270
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-daily.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 1 9 19 2003)) 09:00-11:30 rrule daily
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-daily.diary-european 
b/test/lisp/calendar/icalendar-resources/import-rrule-daily.diary-european
new file mode 100644
index 0000000..2c70cd7
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-daily.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 1 19 9 2003)) 09:00-11:30 rrule daily
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-daily.diary-iso 
b/test/lisp/calendar/icalendar-resources/import-rrule-daily.diary-iso
new file mode 100644
index 0000000..b201cb4
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-daily.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 1 2003 9 19)) 09:00-11:30 rrule daily
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-daily.ics 
b/test/lisp/calendar/icalendar-resources/import-rrule-daily.ics
new file mode 100644
index 0000000..6d013b0
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-daily.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule daily
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=DAILY;
+END:VEVENT
+END:VCALENDAR
+
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-monthly-no-end.diary-american
 
b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-no-end.diary-american
new file mode 100644
index 0000000..bc5453f
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-no-end.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-date t 19 t) (diary-block 9 19 2003 1 1 9999)) 09:00-11:30 
rrule monthly no end
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-monthly-no-end.diary-european
 
b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-no-end.diary-european
new file mode 100644
index 0000000..f071519
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-no-end.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-date 19 t t) (diary-block 19 9 2003 1 1 9999)) 09:00-11:30 
rrule monthly no end
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-monthly-no-end.diary-iso 
b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-no-end.diary-iso
new file mode 100644
index 0000000..3709e93
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-no-end.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-date t t 19) (diary-block 2003 9 19 9999 1 1)) 09:00-11:30 
rrule monthly no end
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-monthly-no-end.ics 
b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-no-end.ics
new file mode 100644
index 0000000..b871658
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-no-end.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule monthly no end
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=MONTHLY;
+END:VEVENT
+END:VCALENDAR
+
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-monthly-with-end.diary-american
 
b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-with-end.diary-american
new file mode 100644
index 0000000..638ab8b
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-with-end.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-date t 19 t) (diary-block 9 19 2003 8 19 2005)) 09:00-11:30 
rrule monthly with end
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-monthly-with-end.diary-european
 
b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-with-end.diary-european
new file mode 100644
index 0000000..c70cde2
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-with-end.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-date 19 t t) (diary-block 19 9 2003 19 8 2005)) 09:00-11:30 
rrule monthly with end
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-monthly-with-end.diary-iso
 
b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-with-end.diary-iso
new file mode 100644
index 0000000..ee51a21
--- /dev/null
+++ 
b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-with-end.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-date t t 19) (diary-block 2003 9 19 2005 8 19)) 09:00-11:30 
rrule monthly with end
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-monthly-with-end.ics 
b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-with-end.ics
new file mode 100644
index 0000000..d8a1fe2
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-monthly-with-end.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule monthly with end
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=MONTHLY;UNTIL=20050819;
+END:VEVENT
+END:VCALENDAR
+
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-weekly.diary-american 
b/test/lisp/calendar/icalendar-resources/import-rrule-weekly.diary-american
new file mode 100644
index 0000000..d8bf2eb
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-weekly.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 7 9 19 2003)) 09:00-11:30 rrule weekly
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-weekly.diary-european 
b/test/lisp/calendar/icalendar-resources/import-rrule-weekly.diary-european
new file mode 100644
index 0000000..e368fde
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-weekly.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 7 19 9 2003)) 09:00-11:30 rrule weekly
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-weekly.diary-iso 
b/test/lisp/calendar/icalendar-resources/import-rrule-weekly.diary-iso
new file mode 100644
index 0000000..49cd9d8
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-weekly.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 7 2003 9 19)) 09:00-11:30 rrule weekly
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-weekly.ics 
b/test/lisp/calendar/icalendar-resources/import-rrule-weekly.ics
new file mode 100644
index 0000000..c3f0b8a
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-weekly.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule weekly
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=WEEKLY;
+END:VEVENT
+END:VCALENDAR
+
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-american 
b/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-american
new file mode 100644
index 0000000..a54780b
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-anniversary 9 19 2003)) 09:00-11:30 rrule yearly
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-european 
b/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-european
new file mode 100644
index 0000000..a4bd81d
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-anniversary 19 9 2003)) 09:00-11:30 rrule yearly
diff --git 
a/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-iso 
b/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-iso
new file mode 100644
index 0000000..65a7abe
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-anniversary 2003 9 19)) 09:00-11:30 rrule yearly
diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-yearly.ics 
b/test/lisp/calendar/icalendar-resources/import-rrule-yearly.ics
new file mode 100644
index 0000000..21cca09
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-rrule-yearly.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule yearly
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=YEARLY;INTERVAL=2
+END:VEVENT
+END:VCALENDAR
+
diff --git 
a/test/lisp/calendar/icalendar-resources/import-with-timezone.diary-iso 
b/test/lisp/calendar/icalendar-resources/import-with-timezone.diary-iso
new file mode 100644
index 0000000..f99b592
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-with-timezone.diary-iso
@@ -0,0 +1,2 @@
+&2012/1/15 15:00-15:30 standardtime
+&2012/12/15 11:00-11:30 daylightsavingtime
diff --git a/test/lisp/calendar/icalendar-resources/import-with-timezone.ics 
b/test/lisp/calendar/icalendar-resources/import-with-timezone.ics
new file mode 100644
index 0000000..110a983
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-with-timezone.ics
@@ -0,0 +1,27 @@
+BEGIN:VCALENDAR
+BEGIN:VTIMEZONE
+TZID:fictional, nonexistent, arbitrary
+BEGIN:STANDARD
+DTSTART:20100101T000000
+TZOFFSETFROM:+0200
+TZOFFSETTO:-0200
+RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=01
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:20101201T000000
+TZOFFSETFROM:-0200
+TZOFFSETTO:+0200
+RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=11
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+SUMMARY:standardtime
+DTSTART;TZID="fictional, nonexistent, arbitrary":20120115T120000
+DTEND;TZID="fictional, nonexistent, arbitrary":20120115T123000
+END:VEVENT
+BEGIN:VEVENT
+SUMMARY:daylightsavingtime
+DTSTART;TZID="fictional, nonexistent, arbitrary":20121215T120000
+DTEND;TZID="fictional, nonexistent, arbitrary":20121215T123000
+END:VEVENT
+END:VCALENDAR
diff --git 
a/test/lisp/calendar/icalendar-resources/import-with-uid.diary-american 
b/test/lisp/calendar/icalendar-resources/import-with-uid.diary-american
new file mode 100644
index 0000000..9b2f06a
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-with-uid.diary-american
@@ -0,0 +1,2 @@
+&9/19/2003 09:00-11:30 non-recurring
+ UID: 1234567890uid
diff --git 
a/test/lisp/calendar/icalendar-resources/import-with-uid.diary-european 
b/test/lisp/calendar/icalendar-resources/import-with-uid.diary-european
new file mode 100644
index 0000000..95db4d4
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-with-uid.diary-european
@@ -0,0 +1,2 @@
+&19/9/2003 09:00-11:30 non-recurring
+ UID: 1234567890uid
diff --git a/test/lisp/calendar/icalendar-resources/import-with-uid.diary-iso 
b/test/lisp/calendar/icalendar-resources/import-with-uid.diary-iso
new file mode 100644
index 0000000..d372e5a
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-with-uid.diary-iso
@@ -0,0 +1,2 @@
+&2003/9/19 09:00-11:30 non-recurring
+ UID: 1234567890uid
diff --git a/test/lisp/calendar/icalendar-resources/import-with-uid.ics 
b/test/lisp/calendar/icalendar-resources/import-with-uid.ics
new file mode 100644
index 0000000..db412d9
--- /dev/null
+++ b/test/lisp/calendar/icalendar-resources/import-with-uid.ics
@@ -0,0 +1,10 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+UID:1234567890uid
+SUMMARY:non-recurring
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+END:VEVENT
+END:VCALENDAR
diff --git a/test/lisp/calendar/icalendar-tests.el 
b/test/lisp/calendar/icalendar-tests.el
index bce7de7..8b44f63 100644
--- a/test/lisp/calendar/icalendar-tests.el
+++ b/test/lisp/calendar/icalendar-tests.el
@@ -32,6 +32,7 @@
 ;;; Code:
 
 (require 'ert)
+(require 'ert-x)
 (require 'icalendar)
 
 ;; ======================================================================
@@ -51,6 +52,15 @@
   (replace-regexp-in-string "[ \t\n]+\\'" ""
                             (replace-regexp-in-string "\\`[ \t\n]+" "" 
string)))
 
+(defun icalendar-tests--get-file-contents (filename)
+  "Return contents of file in test data directory named FILENAME."
+  (with-temp-buffer
+    (let ((coding-system-for-read 'raw-text)
+          (inhibit-eol-conversion t))
+      (insert-file-contents-literally
+       (ert-resource-file filename))
+      (buffer-string))))
+
 ;; ======================================================================
 ;; Tests of functions
 ;; ======================================================================
@@ -963,13 +973,16 @@ END:VALARM
 ;; Import tests
 ;; ======================================================================
 
-(defun icalendar-tests--test-import (input expected-iso expected-european
-                                          expected-american)
+(defun icalendar-tests--test-import (filename expected-iso expected-european
+                                             expected-american)
   "Perform import test.
-Argument INPUT icalendar event string.
-Argument EXPECTED-ISO expected iso style diary string.
-Argument EXPECTED-EUROPEAN expected european style diary string.
-Argument EXPECTED-AMERICAN expected american style diary string.
+Argument FILENAME ics file to import.
+Argument EXPECTED-ISO diary-file containing expected
+iso-calendar-style result.
+Argument EXPECTED-EUROPEAN diary-file containing expected
+european-calendar-style result.
+Argument EXPECTED-AMERICAN diary-file containing expected
+american-calendar-style result.
 During import test the timezone is set to Central European Time."
   (let ((timezone (getenv "TZ")))
     (unwind-protect
@@ -978,14 +991,7 @@ During import test the timezone is set to Central European 
Time."
          ;; Eg hydra.nixos.org.
          (setenv "TZ" "CET-1CEST,M3.5.0/2,M10.5.0/3")
          (with-temp-buffer
-           (if (string-match "^BEGIN:VCALENDAR" input)
-               (insert input)
-             (insert "BEGIN:VCALENDAR\nPRODID:-//Emacs//NONSGML 
icalendar.el//EN\n")
-             (insert "VERSION:2.0\nBEGIN:VEVENT\n")
-             (insert input)
-             (unless (eq (char-before) ?\n)
-               (insert "\n"))
-             (insert "END:VEVENT\nEND:VCALENDAR\n"))
+           (insert (icalendar-tests--get-file-contents filename))
            (let ((icalendar-import-format "%s%d%l%o%t%u%c%U")
                  (icalendar-import-format-summary "%s")
                  (icalendar-import-format-location "\n Location: %s")
@@ -998,26 +1004,29 @@ During import test the timezone is set to Central 
European Time."
                  calendar-date-style)
              (when expected-iso
                (setq calendar-date-style 'iso)
-               (icalendar-tests--do-test-import input expected-iso))
+               (icalendar-tests--do-test-import
+                 (icalendar-tests--get-file-contents expected-iso)))
              (when expected-european
                (setq calendar-date-style 'european)
-               (icalendar-tests--do-test-import input expected-european))
+               (icalendar-tests--do-test-import
+                 (icalendar-tests--get-file-contents expected-european)))
              (when expected-american
                (setq calendar-date-style 'american)
-               (icalendar-tests--do-test-import input expected-american)))))
+               (icalendar-tests--do-test-import
+                 (icalendar-tests--get-file-contents expected-american))))))
       (setenv "TZ" timezone))))
 
-(defun icalendar-tests--do-test-import (_input expected-output)
+(defun icalendar-tests--do-test-import (expected-output)
   "Actually perform import test.
-Argument INPUT input icalendar string.
-Argument EXPECTED-OUTPUT expected diary string."
+Argument EXPECTED-OUTPUT file containing expected diary string."
   (let ((temp-file (make-temp-file "icalendar-test-diary")))
     ;; Test the Catch-the-mysterious-coding-header logic below.
     ;; Ruby-mode adds an after-save-hook which inserts the header!
     ;; (save-excursion
     ;;   (find-file temp-file)
     ;;   (ruby-mode))
-    (icalendar-import-buffer temp-file t t)
+    (let ((coding-system-for-write 'raw-text))
+      (icalendar-import-buffer temp-file t t))
     (save-excursion
       (find-file temp-file)
       ;; Check for the mysterious "# coding: ..." header, remove it
@@ -1045,452 +1054,135 @@ Argument EXPECTED-OUTPUT expected diary string."
 
 (ert-deftest icalendar-import-non-recurring ()
   "Perform standard import tests."
-  (icalendar-tests--test-import
-   "SUMMARY:non-recurring
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000"
-   "&2003/9/19 09:00-11:30 non-recurring\n"
-   "&19/9/2003 09:00-11:30 non-recurring\n"
-   "&9/19/2003 09:00-11:30 non-recurring\n")
-  (icalendar-tests--test-import
-   "SUMMARY:non-recurring allday
-DTSTART;VALUE=DATE-TIME:20030919"
-   "&2003/9/19 non-recurring allday\n"
-   "&19/9/2003 non-recurring allday\n"
-   "&9/19/2003 non-recurring allday\n")
-  (icalendar-tests--test-import
-   ;; Checkdoc removes trailing blanks.  Therefore: format!
-   (format "%s\n%s\n%s" "SUMMARY:long " " summary"
-           "DTSTART;VALUE=DATE:20030919")
-   "&2003/9/19 long summary\n"
-   "&19/9/2003 long summary\n"
-   "&9/19/2003 long summary\n")
-  (icalendar-tests--test-import
-   "UID:748f2da0-0d9b-11d8-97af-b4ec8686ea61
-SUMMARY:Sommerferien
-STATUS:TENTATIVE
-CLASS:PRIVATE
-X-MOZILLA-ALARM-DEFAULT-UNITS:Minuten
-X-MOZILLA-RECUR-DEFAULT-INTERVAL:0
-DTSTART;VALUE=DATE:20040719
-DTEND;VALUE=DATE:20040828
-DTSTAMP:20031103T011641Z
-"
-   "&%%(and (diary-block 2004 7 19 2004 8 27)) Sommerferien
- Status: TENTATIVE
- Class: PRIVATE
- UID: 748f2da0-0d9b-11d8-97af-b4ec8686ea61
-"
-   "&%%(and (diary-block 19 7 2004 27 8 2004)) Sommerferien
- Status: TENTATIVE
- Class: PRIVATE
- UID: 748f2da0-0d9b-11d8-97af-b4ec8686ea61
-"
-   "&%%(and (diary-block 7 19 2004 8 27 2004)) Sommerferien
- Status: TENTATIVE
- Class: PRIVATE
- UID: 748f2da0-0d9b-11d8-97af-b4ec8686ea61
-")
-  (icalendar-tests--test-import
-   "UID
- :04979712-3902-11d9-93dd-8f9f4afe08da
-SUMMARY
- :folded summary
-STATUS
- :TENTATIVE
-CLASS
- :PRIVATE
-X-MOZILLA-ALARM-DEFAULT-LENGTH
- :0
-DTSTART
- :20041123T140000
-DTEND
- :20041123T143000
-DTSTAMP
- :20041118T013430Z
-LAST-MODIFIED
- :20041118T013640Z
-"
-   "&2004/11/23 14:00-14:30 folded summary
- Status: TENTATIVE
- Class: PRIVATE
- UID: 04979712-3902-11d9-93dd-8f9f4afe08da\n"
-   "&23/11/2004 14:00-14:30 folded summary
- Status: TENTATIVE
- Class: PRIVATE
- UID: 04979712-3902-11d9-93dd-8f9f4afe08da\n"
-   "&11/23/2004 14:00-14:30 folded summary
- Status: TENTATIVE
- Class: PRIVATE
- UID: 04979712-3902-11d9-93dd-8f9f4afe08da\n")
-
-  (icalendar-tests--test-import
-   "UID
- :6161a312-3902-11d9-b512-f764153bb28b
-SUMMARY
- :another example
-STATUS
- :TENTATIVE
-CLASS
- :PRIVATE
-X-MOZILLA-ALARM-DEFAULT-LENGTH
- :0
-DTSTART
- :20041123T144500
-DTEND
- :20041123T154500
-DTSTAMP
- :20041118T013641Z
-"
-   "&2004/11/23 14:45-15:45 another example
- Status: TENTATIVE
- Class: PRIVATE
- UID: 6161a312-3902-11d9-b512-f764153bb28b\n"
-   "&23/11/2004 14:45-15:45 another example
- Status: TENTATIVE
- Class: PRIVATE
- UID: 6161a312-3902-11d9-b512-f764153bb28b\n"
-   "&11/23/2004 14:45-15:45 another example
- Status: TENTATIVE
- Class: PRIVATE
- UID: 6161a312-3902-11d9-b512-f764153bb28b\n"))
+  (icalendar-tests--test-import "import-non-recurring-1.ics"
+                                "import-non-recurring-1.diary-iso"
+                                "import-non-recurring-1.diary-european"
+                                "import-non-recurring-1.diary-american")
+  (icalendar-tests--test-import "import-non-recurring-all-day.ics"
+                                "import-non-recurring-all-day.diary-iso"
+                                "import-non-recurring-all-day.diary-european"
+                                "import-non-recurring-all-day.diary-american")
+  (icalendar-tests--test-import "import-non-recurring-long-summary.ics"
+                                "import-non-recurring-long-summary.diary-iso"
+                                
"import-non-recurring-long-summary.diary-european"
+                                
"import-non-recurring-long-summary.diary-american")
+  (icalendar-tests--test-import "import-non-recurring-block.ics"
+                                "import-non-recurring-block.diary-iso"
+                                "import-non-recurring-block.diary-european"
+                                "import-non-recurring-block.diary-american")
+  (icalendar-tests--test-import "import-non-recurring-folded-summary.ics"
+                                "import-non-recurring-folded-summary.diary-iso"
+                                
"import-non-recurring-folded-summary.diary-european"
+                                
"import-non-recurring-folded-summary.diary-american")
+  (icalendar-tests--test-import "import-non-recurring-another-example.ics"
+                                
"import-non-recurring-another-example.diary-iso"
+                                
"import-non-recurring-another-example.diary-european"
+                                
"import-non-recurring-another-example.diary-american"))
+
 
 (ert-deftest icalendar-import-rrule ()
-  (icalendar-tests--test-import
-   "SUMMARY:rrule daily
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=DAILY;
-"
-   "&%%(and (diary-cyclic 1 2003 9 19)) 09:00-11:30 rrule daily\n"
-   "&%%(and (diary-cyclic 1 19 9 2003)) 09:00-11:30 rrule daily\n"
-   "&%%(and (diary-cyclic 1 9 19 2003)) 09:00-11:30 rrule daily\n")
-  ;; RRULE examples
-  (icalendar-tests--test-import
-   "SUMMARY:rrule daily
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=DAILY;INTERVAL=2
-"
-   "&%%(and (diary-cyclic 2 2003 9 19)) 09:00-11:30 rrule daily\n"
-   "&%%(and (diary-cyclic 2 19 9 2003)) 09:00-11:30 rrule daily\n"
-   "&%%(and (diary-cyclic 2 9 19 2003)) 09:00-11:30 rrule daily\n")
-  (icalendar-tests--test-import
-   "SUMMARY:rrule daily with exceptions
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=DAILY;INTERVAL=2
-EXDATE:20030921,20030925
-"
-   "&%%(and (not (diary-date 2003 9 25)) (not (diary-date 2003 9 21)) 
(diary-cyclic 2 2003 9 19)) 09:00-11:30 rrule daily with exceptions\n"
-   "&%%(and (not (diary-date 25 9 2003)) (not (diary-date 21 9 2003)) 
(diary-cyclic 2 19 9 2003)) 09:00-11:30 rrule daily with exceptions\n"
-   "&%%(and (not (diary-date 9 25 2003)) (not (diary-date 9 21 2003)) 
(diary-cyclic 2 9 19 2003)) 09:00-11:30 rrule daily with exceptions\n")
-  (icalendar-tests--test-import
-   "SUMMARY:rrule weekly
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=WEEKLY;
-"
-   "&%%(and (diary-cyclic 7 2003 9 19)) 09:00-11:30 rrule weekly\n"
-   "&%%(and (diary-cyclic 7 19 9 2003)) 09:00-11:30 rrule weekly\n"
-   "&%%(and (diary-cyclic 7 9 19 2003)) 09:00-11:30 rrule weekly\n")
-  (icalendar-tests--test-import
-   "SUMMARY:rrule monthly no end
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=MONTHLY;
-"
-   "&%%(and (diary-date t t 19) (diary-block 2003 9 19 9999 1 1)) 09:00-11:30 
rrule monthly no end\n"
-   "&%%(and (diary-date 19 t t) (diary-block 19 9 2003 1 1 9999)) 09:00-11:30 
rrule monthly no end\n"
-   "&%%(and (diary-date t 19 t) (diary-block 9 19 2003 1 1 9999)) 09:00-11:30 
rrule monthly no end\n")
-  (icalendar-tests--test-import
-   "SUMMARY:rrule monthly with end
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=MONTHLY;UNTIL=20050819;
-"
-   "&%%(and (diary-date t t 19) (diary-block 2003 9 19 2005 8 19)) 09:00-11:30 
rrule monthly with end\n"
-   "&%%(and (diary-date 19 t t) (diary-block 19 9 2003 19 8 2005)) 09:00-11:30 
rrule monthly with end\n"
-   "&%%(and (diary-date t 19 t) (diary-block 9 19 2003 8 19 2005)) 09:00-11:30 
rrule monthly with end\n")
-  (icalendar-tests--test-import
-   "DTSTART;VALUE=DATE:20040815
-DTEND;VALUE=DATE:20040816
-SUMMARY:Maria Himmelfahrt
-RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=8
-"
-   "&%%(and (diary-anniversary 2004 8 15))  Maria Himmelfahrt\n"
-   "&%%(and (diary-anniversary 15 8 2004))  Maria Himmelfahrt\n"
-   "&%%(and (diary-anniversary 8 15 2004))  Maria Himmelfahrt\n")
-  (icalendar-tests--test-import
-   "SUMMARY:rrule yearly
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=YEARLY;INTERVAL=2
-"
-   "&%%(and (diary-anniversary 2003 9 19)) 09:00-11:30 rrule yearly\n" ;FIXME
-   "&%%(and (diary-anniversary 19 9 2003)) 09:00-11:30 rrule yearly\n" ;FIXME
-   "&%%(and (diary-anniversary 9 19 2003)) 09:00-11:30 rrule yearly\n") ;FIXME
-  (icalendar-tests--test-import
-   "SUMMARY:rrule count daily short
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=DAILY;COUNT=1;INTERVAL=1
-"
-   "&%%(and (diary-cyclic 1 2003 9 19) (diary-block 2003 9 19 2003 9 19)) 
09:00-11:30 rrule count daily short\n"
-   "&%%(and (diary-cyclic 1 19 9 2003) (diary-block 19 9 2003 19 9 2003)) 
09:00-11:30 rrule count daily short\n"
-   "&%%(and (diary-cyclic 1 9 19 2003) (diary-block 9 19 2003 9 19 2003)) 
09:00-11:30 rrule count daily short\n")
-  (icalendar-tests--test-import
-   "SUMMARY:rrule count daily long
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=DAILY;COUNT=14;INTERVAL=1
-"
-   "&%%(and (diary-cyclic 1 2003 9 19) (diary-block 2003 9 19 2003 10 2)) 
09:00-11:30 rrule count daily long\n"
-   "&%%(and (diary-cyclic 1 19 9 2003) (diary-block 19 9 2003 2 10 2003)) 
09:00-11:30 rrule count daily long\n"
-   "&%%(and (diary-cyclic 1 9 19 2003) (diary-block 9 19 2003 10 2 2003)) 
09:00-11:30 rrule count daily long\n")
-  (icalendar-tests--test-import
-   "SUMMARY:rrule count bi-weekly 3 times
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=WEEKLY;COUNT=3;INTERVAL=2
-"
-   "&%%(and (diary-cyclic 14 2003 9 19) (diary-block 2003 9 19 2003 10 31)) 
09:00-11:30 rrule count bi-weekly 3 times\n"
-   "&%%(and (diary-cyclic 14 19 9 2003) (diary-block 19 9 2003 31 10 2003)) 
09:00-11:30 rrule count bi-weekly 3 times\n"
-   "&%%(and (diary-cyclic 14 9 19 2003) (diary-block 9 19 2003 10 31 2003)) 
09:00-11:30 rrule count bi-weekly 3 times\n")
-  (icalendar-tests--test-import
-   "SUMMARY:rrule count monthly
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=MONTHLY;INTERVAL=1;COUNT=5
-"
-   "&%%(and (diary-date t t 19) (diary-block 2003 9 19 2004 1 19)) 09:00-11:30 
rrule count monthly\n"
-   "&%%(and (diary-date 19 t t) (diary-block 19 9 2003 19 1 2004)) 09:00-11:30 
rrule count monthly\n"
-   "&%%(and (diary-date t 19 t) (diary-block 9 19 2003 1 19 2004)) 09:00-11:30 
rrule count monthly\n")
-  (icalendar-tests--test-import
-   "SUMMARY:rrule count every second month
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=5
-"
-   "&%%(and (diary-date t t 19) (diary-block 2003 9 19 2004 5 19)) 09:00-11:30 
rrule count every second month\n" ;FIXME
-   "&%%(and (diary-date 19 t t) (diary-block 19 9 2003 19 5 2004)) 09:00-11:30 
rrule count every second month\n" ;FIXME
-   "&%%(and (diary-date t 19 t) (diary-block 9 19 2003 5 19 2004)) 09:00-11:30 
rrule count every second month\n") ;FIXME
-  (icalendar-tests--test-import
-   "SUMMARY:rrule count yearly
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=YEARLY;INTERVAL=1;COUNT=5
-"
-   "&%%(and (diary-date t 9 19) (diary-block 2003 9 19 2007 9 19)) 09:00-11:30 
rrule count yearly\n"
-   "&%%(and (diary-date 19 9 t) (diary-block 19 9 2003 19 9 2007)) 09:00-11:30 
rrule count yearly\n"
-   "&%%(and (diary-date 9 19 t) (diary-block 9 19 2003 9 19 2007)) 09:00-11:30 
rrule count yearly\n")
-  (icalendar-tests--test-import
-   "SUMMARY:rrule count every second year
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=5
-"
-   "&%%(and (diary-date t 9 19) (diary-block 2003 9 19 2011 9 19)) 09:00-11:30 
rrule count every second year\n" ;FIXME!!!
-   "&%%(and (diary-date 19 9 t) (diary-block 19 9 2003 19 9 2011)) 09:00-11:30 
rrule count every second year\n" ;FIXME!!!
-   "&%%(and (diary-date 9 19 t) (diary-block 9 19 2003 9 19 2011)) 09:00-11:30 
rrule count every second year\n") ;FIXME!!!
-)
+  (icalendar-tests--test-import "import-rrule-daily.ics"
+                                "import-rrule-daily.diary-iso"
+                                "import-rrule-daily.diary-european"
+                                "import-rrule-daily.diary-american")
+  (icalendar-tests--test-import "import-rrule-daily-two-day.ics"
+                                "import-rrule-daily-two-day.diary-iso"
+                                "import-rrule-daily-two-day.diary-european"
+                                "import-rrule-daily-two-day.diary-american")
+  (icalendar-tests--test-import "import-rrule-daily-with-exceptions.ics"
+                                "import-rrule-daily-with-exceptions.diary-iso"
+                                
"import-rrule-daily-with-exceptions.diary-european"
+                                
"import-rrule-daily-with-exceptions.diary-american")
+  (icalendar-tests--test-import "import-rrule-weekly.ics"
+                                "import-rrule-weekly.diary-iso"
+                                "import-rrule-weekly.diary-european"
+                                "import-rrule-weekly.diary-american")
+  (icalendar-tests--test-import "import-rrule-monthly-no-end.ics"
+                                "import-rrule-monthly-no-end.diary-iso"
+                                "import-rrule-monthly-no-end.diary-european"
+                                "import-rrule-monthly-no-end.diary-american")
+  (icalendar-tests--test-import "import-rrule-monthly-with-end.ics"
+                                "import-rrule-monthly-with-end.diary-iso"
+                                "import-rrule-monthly-with-end.diary-european"
+                                "import-rrule-monthly-with-end.diary-american")
+  (icalendar-tests--test-import "import-rrule-anniversary.ics"
+                                "import-rrule-anniversary.diary-iso"
+                                "import-rrule-anniversary.diary-european"
+                                "import-rrule-anniversary.diary-american")
+  (icalendar-tests--test-import "import-rrule-yearly.ics"
+                                "import-rrule-yearly.diary-iso"
+                                "import-rrule-yearly.diary-european"
+                                "import-rrule-yearly.diary-american")
+  (icalendar-tests--test-import "import-rrule-count-daily-short.ics"
+                                "import-rrule-count-daily-short.diary-iso"
+                                "import-rrule-count-daily-short.diary-european"
+                                
"import-rrule-count-daily-short.diary-american")
+  (icalendar-tests--test-import "import-rrule-count-daily-long.ics"
+                                "import-rrule-count-daily-long.diary-iso"
+                                "import-rrule-count-daily-long.diary-european"
+                                "import-rrule-count-daily-long.diary-american")
+  (icalendar-tests--test-import "import-rrule-count-monthly.ics"
+                                "import-rrule-count-monthly.diary-iso"
+                                "import-rrule-count-monthly.diary-european"
+                                "import-rrule-count-monthly.diary-american")
+  (icalendar-tests--test-import "import-rrule-count-every-second-month.ics"
+                                
"import-rrule-count-every-second-month.diary-iso"
+                                
"import-rrule-count-every-second-month.diary-european"
+                                
"import-rrule-count-every-second-month.diary-american")
+  (icalendar-tests--test-import "import-rrule-count-yearly.ics"
+                                "import-rrule-count-yearly.diary-iso"
+                                "import-rrule-count-yearly.diary-european"
+                                "import-rrule-count-yearly.diary-american")
+  (icalendar-tests--test-import "import-rrule-count-every-second-year.ics"
+                                
"import-rrule-count-every-second-year.diary-iso"
+                                
"import-rrule-count-every-second-year.diary-european"
+                                
"import-rrule-count-every-second-year.diary-american")
+  )
 
 (ert-deftest icalendar-import-duration ()
-  ;; duration
-  (icalendar-tests--test-import
-   "DTSTART;VALUE=DATE:20050217
-SUMMARY:duration
-DURATION:P7D
-"
-   "&%%(and (diary-block 2005 2 17 2005 2 23)) duration\n"
-   "&%%(and (diary-block 17 2 2005 23 2 2005)) duration\n"
-   "&%%(and (diary-block 2 17 2005 2 23 2005)) duration\n")
-  (icalendar-tests--test-import
-   "UID:20041127T183329Z-18215-1001-4536-49109@andromeda
-DTSTAMP:20041127T183315Z
-LAST-MODIFIED:20041127T183329
-SUMMARY:Urlaub
-DTSTART;VALUE=DATE:20011221
-DTEND;VALUE=DATE:20011221
-RRULE:FREQ=DAILY;UNTIL=20011229;INTERVAL=1;WKST=SU
-CLASS:PUBLIC
-SEQUENCE:1
-CREATED:20041127T183329
-"
-   "&%%(and (diary-cyclic 1 2001 12 21) (diary-block 2001 12 21 2001 12 29))  
Urlaub
- Class: PUBLIC
- UID: 20041127T183329Z-18215-1001-4536-49109@andromeda\n"
-   "&%%(and (diary-cyclic 1 21 12 2001) (diary-block 21 12 2001 29 12 2001))  
Urlaub
- Class: PUBLIC
- UID: 20041127T183329Z-18215-1001-4536-49109@andromeda\n"
-   "&%%(and (diary-cyclic 1 12 21 2001) (diary-block 12 21 2001 12 29 2001))  
Urlaub
- Class: PUBLIC
- UID: 20041127T183329Z-18215-1001-4536-49109@andromeda\n"))
+  (icalendar-tests--test-import "import-duration.ics"
+                                "import-duration.diary-iso"
+                                "import-duration.diary-european"
+                                "import-duration.diary-american")
+  ;; duration-2: this is actually an rrule test
+  (icalendar-tests--test-import "import-duration-2.ics"
+                                "import-duration-2.diary-iso"
+                                "import-duration-2.diary-european"
+                                "import-duration-2.diary-american"))
 
 (ert-deftest icalendar-import-bug-6766 ()
   ;;bug#6766 -- multiple byday values in a weekly rrule
-  (icalendar-tests--test-import
-"CLASS:PUBLIC
-DTEND;TZID=America/New_York:20100421T120000
-DTSTAMP:20100525T141214Z
-DTSTART;TZID=America/New_York:20100421T113000
-RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,WE,TH,FR
-SEQUENCE:1
-STATUS:CONFIRMED
-SUMMARY:Scrum
-TRANSP:OPAQUE
-UID:8814e3f9-7482-408f-996c-3bfe486a1262
-END:VEVENT
-BEGIN:VEVENT
-CLASS:PUBLIC
-DTSTAMP:20100525T141214Z
-DTSTART;VALUE=DATE:20100422
-DTEND;VALUE=DATE:20100423
-RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=TU,TH
-SEQUENCE:1
-SUMMARY:Tues + Thurs thinking
-TRANSP:OPAQUE
-UID:8814e3f9-7482-408f-996c-3bfe486a1263
-"
-"&%%(and (memq (calendar-day-of-week date) '(1 3 4 5)) (diary-cyclic 1 2010 4 
21)) 11:30-12:00 Scrum
- Status: CONFIRMED
- Class: PUBLIC
- UID: 8814e3f9-7482-408f-996c-3bfe486a1262
-&%%(and (memq (calendar-day-of-week date) '(2 4)) (diary-cyclic 1 2010 4 22)) 
Tues + Thurs thinking
- Class: PUBLIC
- UID: 8814e3f9-7482-408f-996c-3bfe486a1263
-"
-"&%%(and (memq (calendar-day-of-week date) '(1 3 4 5)) (diary-cyclic 1 21 4 
2010)) 11:30-12:00 Scrum
- Status: CONFIRMED
- Class: PUBLIC
- UID: 8814e3f9-7482-408f-996c-3bfe486a1262
-&%%(and (memq (calendar-day-of-week date) '(2 4)) (diary-cyclic 1 22 4 2010)) 
Tues + Thurs thinking
- Class: PUBLIC
- UID: 8814e3f9-7482-408f-996c-3bfe486a1263
-"
-"&%%(and (memq (calendar-day-of-week date) '(1 3 4 5)) (diary-cyclic 1 4 21 
2010)) 11:30-12:00 Scrum
- Status: CONFIRMED
- Class: PUBLIC
- UID: 8814e3f9-7482-408f-996c-3bfe486a1262
-&%%(and (memq (calendar-day-of-week date) '(2 4)) (diary-cyclic 1 4 22 2010)) 
Tues + Thurs thinking
- Class: PUBLIC
- UID: 8814e3f9-7482-408f-996c-3bfe486a1263
-"))
+  (icalendar-tests--test-import "import-bug-6766.ics"
+                                "import-bug-6766.diary-iso"
+                                "import-bug-6766.diary-european"
+                                "import-bug-6766.diary-american"))
 
 (ert-deftest icalendar-import-bug-24199 ()
   ;;bug#24199 -- monthly rule with byday-clause
-  (icalendar-tests--test-import
-"
-SUMMARY:Summary
-DESCRIPTION:Desc
-LOCATION:Loc
-DTSTART:20151202T124600
-DTEND:20151202T160000
-RRULE:FREQ=MONTHLY;BYDAY=1WE;INTERVAL=1
-EXDATE:20160106T114600Z
-EXDATE:20160203T114600Z
-EXDATE:20160302T114600Z
-EXDATE:20160504T104600Z
-EXDATE:20160601T104600Z
-CLASS:DEFAULT
-TRANSP:OPAQUE
-BEGIN:VALARM
-ACTION:DISPLAY
-TRIGGER;VALUE=DURATION:-PT3H
-END:VALARM
-LAST-MODIFIED:20160805T191040Z
-UID:9188710a-08a7-4061-bae3-d4cf4972599a
-"
-"&%%(and (not (diary-date 2016 1 6)) (not (diary-date 2016 2 3)) (not 
(diary-date 2016 3 2)) (not (diary-date 2016 5 4)) (not (diary-date 2016 6 1)) 
(diary-float t 3 1) (diary-block 2015 12 2 9999 1 1)) 12:46-16:00 Summary
- Desc: Desc
- Location: Loc
- Class: DEFAULT
- UID: 9188710a-08a7-4061-bae3-d4cf4972599a
-"
-"&%%(and (not (diary-date 6 1 2016)) (not (diary-date 3 2 2016)) (not 
(diary-date 2 3 2016)) (not (diary-date 4 5 2016)) (not (diary-date 1 6 2016)) 
(diary-float t 3 1) (diary-block 2 12 2015 1 1 9999)) 12:46-16:00 Summary
- Desc: Desc
- Location: Loc
- Class: DEFAULT
- UID: 9188710a-08a7-4061-bae3-d4cf4972599a
-"
-"&%%(and (not (diary-date 1 6 2016)) (not (diary-date 2 3 2016)) (not 
(diary-date 3 2 2016)) (not (diary-date 5 4 2016)) (not (diary-date 6 1 2016)) 
(diary-float t 3 1) (diary-block 12 2 2015 1 1 9999)) 12:46-16:00 Summary
- Desc: Desc
- Location: Loc
- Class: DEFAULT
- UID: 9188710a-08a7-4061-bae3-d4cf4972599a
-"
-))
+  (icalendar-tests--test-import "import-bug-24199.ics"
+                                "import-bug-24199.diary-iso"
+                                "import-bug-24199.diary-european"
+                                "import-bug-24199.diary-american"))
 
 (ert-deftest icalendar-import-bug-33277 ()
   ;;bug#33277 -- start time equals end time
-  (icalendar-tests--test-import
-   "DTSTART:20181105T200000Z
-DTSTAMP:20181105T181652Z
-DESCRIPTION:
-LAST-MODIFIED:20181105T181646Z
-LOCATION:
-SEQUENCE:0
-SUMMARY:event with same start/end time
-TRANSP:OPAQUE
-"
-
-   "&2018/11/5 21:00 event with same start/end time\n"
-   "&5/11/2018 21:00 event with same start/end time\n"
-   "&11/5/2018 21:00 event with same start/end time\n"
-   ))
+  (icalendar-tests--test-import "import-bug-33277.ics"
+                                "import-bug-33277.diary-iso"
+                                "import-bug-33277.diary-european"
+                                "import-bug-33277.diary-american"))
 
 (ert-deftest icalendar-import-multiple-vcalendars ()
-  (icalendar-tests--test-import
-   "DTSTART;VALUE=DATE:20110723
-SUMMARY:event-1
-"
-   "&2011/7/23 event-1\n"
-   "&23/7/2011 event-1\n"
-   "&7/23/2011 event-1\n")
-
-  (icalendar-tests--test-import
-   "BEGIN:VCALENDAR
-PRODID:-//Emacs//NONSGML icalendar.el//EN
-VERSION:2.0\nBEGIN:VEVENT
-DTSTART;VALUE=DATE:20110723
-SUMMARY:event-1
-END:VEVENT
-END:VCALENDAR
-BEGIN:VCALENDAR
-PRODID:-//Emacs//NONSGML icalendar.el//EN
-VERSION:2.0
-BEGIN:VEVENT
-DTSTART;VALUE=DATE:20110724
-SUMMARY:event-2
-END:VEVENT
-END:VCALENDAR
-BEGIN:VCALENDAR
-PRODID:-//Emacs//NONSGML icalendar.el//EN
-VERSION:2.0
-BEGIN:VEVENT
-DTSTART;VALUE=DATE:20110725
-SUMMARY:event-3a
-END:VEVENT
-BEGIN:VEVENT
-DTSTART;VALUE=DATE:20110725
-SUMMARY:event-3b
-END:VEVENT
-END:VCALENDAR
-"
-   "&2011/7/23 event-1\n&2011/7/24 event-2\n&2011/7/25 event-3a\n&2011/7/25 
event-3b\n"
-   "&23/7/2011 event-1\n&24/7/2011 event-2\n&25/7/2011 event-3a\n&25/7/2011 
event-3b\n"
-   "&7/23/2011 event-1\n&7/24/2011 event-2\n&7/25/2011 event-3a\n&7/25/2011 
event-3b\n"))
+  (icalendar-tests--test-import "import-multiple-vcalendars.ics"
+                                "import-multiple-vcalendars.diary-iso"
+                                "import-multiple-vcalendars.diary-european"
+                                "import-multiple-vcalendars.diary-american"))
 
 (ert-deftest icalendar-import-with-uid ()
   "Perform import test with uid."
-  (icalendar-tests--test-import
-   "UID:1234567890uid
-SUMMARY:non-recurring
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000"
-   "&2003/9/19 09:00-11:30 non-recurring\n UID: 1234567890uid\n"
-   "&19/9/2003 09:00-11:30 non-recurring\n UID: 1234567890uid\n"
-   "&9/19/2003 09:00-11:30 non-recurring\n UID: 1234567890uid\n"))
+  (icalendar-tests--test-import "import-with-uid.ics"
+                                "import-with-uid.diary-iso"
+                                "import-with-uid.diary-european"
+                                "import-with-uid.diary-american"))
 
 (ert-deftest icalendar-import-with-timezone ()
   ;; This is known to fail on MS-Windows, because the test assumes
@@ -1499,42 +1191,13 @@ DTEND;VALUE=DATE-TIME:20030919T113000"
                        :failed
                      :passed)
   ;; bug#11473
-  (icalendar-tests--test-import
-   "BEGIN:VCALENDAR
-BEGIN:VTIMEZONE
-TZID:fictional, nonexistent, arbitrary
-BEGIN:STANDARD
-DTSTART:20100101T000000
-TZOFFSETFROM:+0200
-TZOFFSETTO:-0200
-RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=01
-END:STANDARD
-BEGIN:DAYLIGHT
-DTSTART:20101201T000000
-TZOFFSETFROM:-0200
-TZOFFSETTO:+0200
-RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=11
-END:DAYLIGHT
-END:VTIMEZONE
-BEGIN:VEVENT
-SUMMARY:standardtime
-DTSTART;TZID=\"fictional, nonexistent, arbitrary\":20120115T120000
-DTEND;TZID=\"fictional, nonexistent, arbitrary\":20120115T123000
-END:VEVENT
-BEGIN:VEVENT
-SUMMARY:daylightsavingtime
-DTSTART;TZID=\"fictional, nonexistent, arbitrary\":20121215T120000
-DTEND;TZID=\"fictional, nonexistent, arbitrary\":20121215T123000
-END:VEVENT
-END:VCALENDAR"
-   ;; "standardtime" begins first sunday in january and is 4 hours behind CET
-   ;; "daylightsavingtime" begins first sunday in november and is 1 hour 
before CET
-   "&2012/1/15 15:00-15:30 standardtime
-&2012/12/15 11:00-11:30 daylightsavingtime
-"
-   nil
-   nil)
-  )
+  ;; "standardtime" begins first sunday in january and is 4 hours behind CET
+  ;; "daylightsavingtime" begins first sunday in november and is 1 hour before 
CET
+  (icalendar-tests--test-import "import-with-timezone.ics"
+                                "import-with-timezone.diary-iso"
+                                nil
+                                nil))
+
 ;; ======================================================================
 ;; Cycle
 ;; ======================================================================
@@ -1632,237 +1295,27 @@ SUMMARY:and diary-anniversary
                        :failed
                      :passed)
   ;; 2003-05-29
-  (icalendar-tests--test-import
-   "BEGIN:VCALENDAR
-METHOD:REQUEST
-PRODID:Microsoft CDO for Microsoft Exchange
-VERSION:2.0
-BEGIN:VTIMEZONE
-TZID:Kolkata, Chennai, Mumbai, New Delhi
-X-MICROSOFT-CDO-TZID:23
-BEGIN:STANDARD
-DTSTART:16010101T000000
-TZOFFSETFROM:+0530
-TZOFFSETTO:+0530
-END:STANDARD
-BEGIN:DAYLIGHT
-DTSTART:16010101T000000
-TZOFFSETFROM:+0530
-TZOFFSETTO:+0530
-END:DAYLIGHT
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20030509T043439Z
-DTSTART;TZID=\"Kolkata, Chennai, Mumbai, New Delhi\":20030509T103000
-SUMMARY:On-Site Interview
-UID:040000008200E00074C5B7101A82E0080000000080B6DE661216C301000000000000000
- 010000000DB823520692542408ED02D7023F9DFF9
-ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=\"Xxxxx
- xxx Xxxxxxxxxxxx\":MAILTO:xxxxxxxx@xxxxxxx.com
-ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=\"Yyyyyyy Y
- yyyy\":MAILTO:yyyyyyy@yyyyyyy.com
-ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=\"Zzzz Zzzz
- zz\":MAILTO:zzzzzz@zzzzzzz.com
-ORGANIZER;CN=\"Aaaaaa Aaaaa\":MAILTO:aaaaaaa@aaaaaaa.com
-LOCATION:Cccc
-DTEND;TZID=\"Kolkata, Chennai, Mumbai, New Delhi\":20030509T153000
-DESCRIPTION:10:30am - Blah
-SEQUENCE:0
-PRIORITY:5
-CLASS:
-CREATED:20030509T043439Z
-LAST-MODIFIED:20030509T043459Z
-STATUS:CONFIRMED
-TRANSP:OPAQUE
-X-MICROSOFT-CDO-BUSYSTATUS:BUSY
-X-MICROSOFT-CDO-INSTTYPE:0
-X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY
-X-MICROSOFT-CDO-ALLDAYEVENT:FALSE
-X-MICROSOFT-CDO-IMPORTANCE:1
-X-MICROSOFT-CDO-OWNERAPPTID:126441427
-BEGIN:VALARM
-ACTION:DISPLAY
-DESCRIPTION:REMINDER
-TRIGGER;RELATED=START:-PT00H15M00S
-END:VALARM
-END:VEVENT
-END:VCALENDAR"
-   nil
-   "&9/5/2003 07:00-12:00 On-Site Interview
- Desc: 10:30am - Blah
- Location: Cccc
- Organizer: MAILTO:aaaaaaa@aaaaaaa.com
- Status: CONFIRMED
- UID: 
040000008200E00074C5B7101A82E0080000000080B6DE661216C301000000000000000010000000DB823520692542408ED02D7023F9DFF9
-"
-   "&5/9/2003 07:00-12:00 On-Site Interview
- Desc: 10:30am - Blah
- Location: Cccc
- Organizer: MAILTO:aaaaaaa@aaaaaaa.com
- Status: CONFIRMED
- UID: 
040000008200E00074C5B7101A82E0080000000080B6DE661216C301000000000000000010000000DB823520692542408ED02D7023F9DFF9
-")
+  (icalendar-tests--test-import "import-real-world-2003-05-29.ics"
+                                nil
+                                "import-real-world-2003-05-29.diary-european"
+                                "import-real-world-2003-05-29.diary-american")
 
   ;; created with http://apps.marudot.com/ical/
-  (icalendar-tests--test-import
-   "BEGIN:VCALENDAR
-VERSION:2.0
-PRODID:-//www.marudot.com//iCal Event Maker
-X-WR-CALNAME:Test
-CALSCALE:GREGORIAN
-BEGIN:VTIMEZONE
-TZID:Asia/Tehran
-TZURL:http://tzurl.org/zoneinfo-outlook/Asia/Tehran
-X-LIC-LOCATION:Asia/Tehran
-BEGIN:STANDARD
-TZOFFSETFROM:+0330
-TZOFFSETTO:+0330
-TZNAME:IRST
-DTSTART:19700101T000000
-END:STANDARD
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20141116T171439Z
-UID:20141116T171439Z-678877132@marudot.com
-DTSTART;TZID=\"Asia/Tehran\":20141116T070000
-DTEND;TZID=\"Asia/Tehran\":20141116T080000
-SUMMARY:NoDST
-DESCRIPTION:Test event from timezone without DST
-LOCATION:Everywhere
-END:VEVENT
-END:VCALENDAR"
-   nil
-   "&16/11/2014 04:30-05:30 NoDST
- Desc: Test event from timezone without DST
- Location: Everywhere
- UID: 20141116T171439Z-678877132@marudot.com
-"
-   "&11/16/2014 04:30-05:30 NoDST
- Desc: Test event from timezone without DST
- Location: Everywhere
- UID: 20141116T171439Z-678877132@marudot.com
-")
-
+  (icalendar-tests--test-import "import-real-world-no-dst.ics"
+                                nil
+                                "import-real-world-no-dst.diary-european"
+                                "import-real-world-no-dst.diary-american")
 
   ;; 2003-06-18 a
-  (icalendar-tests--test-import
-   "DTSTAMP:20030618T195512Z
-DTSTART;TZID=\"Mountain Time (US & Canada)\":20030623T110000
-SUMMARY:Dress Rehearsal for XXXX-XXXX
-UID:040000008200E00074C5B7101A82E00800000000608AA7DA9835C301000000000000000
- 0100000007C3A6D65EE726E40B7F3D69A23BD567E
-ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=\"AAAAA,AAA
- AA (A-AAAAAAA,ex1)\":MAILTO:aaaaa_aaaaa@aaaaa.com
-ORGANIZER;CN=\"ABCD,TECHTRAINING
- (A-Americas,exgen1)\":MAILTO:xxx@xxxxx.com
-LOCATION:555 or TN 555-5555 ID 5555 & NochWas (see below)
-DTEND;TZID=\"Mountain Time (US & Canada)\":20030623T120000
-DESCRIPTION:753 Zeichen hier radiert
-SEQUENCE:0
-PRIORITY:5
-CLASS:
-CREATED:20030618T195518Z
-LAST-MODIFIED:20030618T195527Z
-STATUS:CONFIRMED
-TRANSP:OPAQUE
-X-MICROSOFT-CDO-BUSYSTATUS:BUSY
-X-MICROSOFT-CDO-INSTTYPE:0
-X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY
-X-MICROSOFT-CDO-ALLDAYEVENT:FALSE
-X-MICROSOFT-CDO-IMPORTANCE:1
-X-MICROSOFT-CDO-OWNERAPPTID:1022519251
-BEGIN:VALARM
-ACTION:DISPLAY
-DESCRIPTION:REMINDER
-TRIGGER;RELATED=START:-PT00H15M00S
-END:VALARM"
-   nil
-   "&23/6/2003 11:00-12:00 Dress Rehearsal for XXXX-XXXX
- Desc: 753 Zeichen hier radiert
- Location: 555 or TN 555-5555 ID 5555 & NochWas (see below)
- Organizer: MAILTO:xxx@xxxxx.com
- Status: CONFIRMED
- UID: 
040000008200E00074C5B7101A82E00800000000608AA7DA9835C3010000000000000000100000007C3A6D65EE726E40B7F3D69A23BD567E
-"
-   "&6/23/2003 11:00-12:00 Dress Rehearsal for XXXX-XXXX
- Desc: 753 Zeichen hier radiert
- Location: 555 or TN 555-5555 ID 5555 & NochWas (see below)
- Organizer: MAILTO:xxx@xxxxx.com
- Status: CONFIRMED
- UID: 
040000008200E00074C5B7101A82E00800000000608AA7DA9835C3010000000000000000100000007C3A6D65EE726E40B7F3D69A23BD567E
-")
+  (icalendar-tests--test-import "import-real-world-2003-06-18a.ics"
+                                nil
+                                "import-real-world-2003-06-18a.diary-european"
+                                "import-real-world-2003-06-18a.diary-american")
   ;; 2003-06-18 b -- uses timezone
-  (icalendar-tests--test-import
-   "BEGIN:VCALENDAR
-METHOD:REQUEST
-PRODID:Microsoft CDO for Microsoft Exchange
-VERSION:2.0
-BEGIN:VTIMEZONE
-TZID:Mountain Time (US & Canada)
-X-MICROSOFT-CDO-TZID:12
-BEGIN:STANDARD
-DTSTART:16010101T020000
-TZOFFSETFROM:-0600
-TZOFFSETTO:-0700
-RRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=10;BYDAY=-1SU
-END:STANDARD
-BEGIN:DAYLIGHT
-DTSTART:16010101T020000
-TZOFFSETFROM:-0700
-TZOFFSETTO:-0600
-RRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=4;BYDAY=1SU
-END:DAYLIGHT
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20030618T230323Z
-DTSTART;TZID=\"Mountain Time (US & Canada)\":20030623T090000
-SUMMARY:Updated: Dress Rehearsal for ABC01-15
-UID:040000008200E00074C5B7101A82E00800000000608AA7DA9835C301000000000000000
- 0100000007C3A6D65EE726E40B7F3D69A23BD567E
-ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;X-REPLYTIME=20030618T20
- 0700Z;RSVP=TRUE;CN=\"AAAAA,AAAAAA
-\(A-AAAAAAA,ex1)\":MAILTO:aaaaaa_aaaaa@aaaaa
- .com
-ORGANIZER;CN=\"ABCD,TECHTRAINING
-\(A-Americas,exgen1)\":MAILTO:bbb@bbbbb.com
-LOCATION:123 or TN 123-1234 ID abcd & SonstWo (see below)
-DTEND;TZID=\"Mountain Time (US & Canada)\":20030623T100000
-DESCRIPTION:Viele Zeichen standen hier früher
-SEQUENCE:0
-PRIORITY:5
-CLASS:
-CREATED:20030618T230326Z
-LAST-MODIFIED:20030618T230335Z
-STATUS:CONFIRMED
-TRANSP:OPAQUE
-X-MICROSOFT-CDO-BUSYSTATUS:BUSY
-X-MICROSOFT-CDO-INSTTYPE:0
-X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY
-X-MICROSOFT-CDO-ALLDAYEVENT:FALSE
-X-MICROSOFT-CDO-IMPORTANCE:1
-X-MICROSOFT-CDO-OWNERAPPTID:1022519251
-BEGIN:VALARM
-ACTION:DISPLAY
-DESCRIPTION:REMINDER
-TRIGGER;RELATED=START:-PT00H15M00S
-END:VALARM
-END:VEVENT
-END:VCALENDAR"
-   nil
-   "&23/6/2003 17:00-18:00 Updated: Dress Rehearsal for ABC01-15
- Desc: Viele Zeichen standen hier früher
- Location: 123 or TN 123-1234 ID abcd & SonstWo (see below)
- Organizer: MAILTO:bbb@bbbbb.com
- Status: CONFIRMED
- UID: 
040000008200E00074C5B7101A82E00800000000608AA7DA9835C3010000000000000000100000007C3A6D65EE726E40B7F3D69A23BD567E
-"
-   "&6/23/2003 17:00-18:00 Updated: Dress Rehearsal for ABC01-15
- Desc: Viele Zeichen standen hier früher
- Location: 123 or TN 123-1234 ID abcd & SonstWo (see below)
- Organizer: MAILTO:bbb@bbbbb.com
- Status: CONFIRMED
- UID: 
040000008200E00074C5B7101A82E00800000000608AA7DA9835C3010000000000000000100000007C3A6D65EE726E40B7F3D69A23BD567E
-")
+  (icalendar-tests--test-import "import-real-world-2003-06-18b.ics"
+                                nil
+                                "import-real-world-2003-06-18b.diary-european"
+                                "import-real-world-2003-06-18b.diary-american")
   ;; export 2004-10-28 block entries
   (icalendar-tests--test-export
    nil
@@ -2078,169 +1531,10 @@ DTEND;VALUE=DATE-TIME:20041012T150000
 SUMMARY:Tue: [2004-10-12] q1")
 
   ;; 2004-11-19
-  (icalendar-tests--test-import
-   "BEGIN:VCALENDAR
-VERSION
- :2.0
-PRODID
- :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN
-BEGIN:VEVENT
-SUMMARY
- :Jjjjj & Wwwww
-STATUS
- :TENTATIVE
-CLASS
- :PRIVATE
-X-MOZILLA-ALARM-DEFAULT-LENGTH
- :0
-DTSTART
- :20041123T140000
-DTEND
- :20041123T143000
-DTSTAMP
- :20041118T013430Z
-LAST-MODIFIED
- :20041118T013640Z
-END:VEVENT
-BEGIN:VEVENT
-SUMMARY
- :BB Aaaaaaaa Bbbbb
-STATUS
- :TENTATIVE
-CLASS
- :PRIVATE
-X-MOZILLA-ALARM-DEFAULT-LENGTH
- :0
-DTSTART
- :20041123T144500
-DTEND
- :20041123T154500
-DTSTAMP
- :20041118T013641Z
-END:VEVENT
-BEGIN:VEVENT
-SUMMARY
- :Hhhhhhhh
-STATUS
- :TENTATIVE
-CLASS
- :PRIVATE
-X-MOZILLA-ALARM-DEFAULT-LENGTH
- :0
-DTSTART
- :20041123T110000
-DTEND
- :20041123T120000
-DTSTAMP
- :20041118T013831Z
-END:VEVENT
-BEGIN:VEVENT
-SUMMARY
- :MMM Aaaaaaaaa
-STATUS
- :TENTATIVE
-CLASS
- :PRIVATE
-X-MOZILLA-ALARM-DEFAULT-LENGTH
- :0
-X-MOZILLA-RECUR-DEFAULT-INTERVAL
- :2
-RRULE
- :FREQ=WEEKLY;INTERVAL=2;BYDAY=FR
-DTSTART
- :20041112T140000
-DTEND
- :20041112T183000
-DTSTAMP
- :20041118T014117Z
-END:VEVENT
-BEGIN:VEVENT
-SUMMARY
- :Rrrr/Cccccc ii Aaaaaaaa
-DESCRIPTION
- :Vvvvv Rrrr aaa Cccccc
-STATUS
- :TENTATIVE
-CLASS
- :PRIVATE
-X-MOZILLA-ALARM-DEFAULT-LENGTH
- :0
-DTSTART
- ;VALUE=DATE
- :20041119
-DTEND
- ;VALUE=DATE
- :20041120
-DTSTAMP
- :20041118T013107Z
-LAST-MODIFIED
- :20041118T014203Z
-END:VEVENT
-BEGIN:VEVENT
-SUMMARY
- :Wwww aa hhhh
-STATUS
- :TENTATIVE
-CLASS
- :PRIVATE
-X-MOZILLA-ALARM-DEFAULT-LENGTH
- :0
-RRULE
- :FREQ=WEEKLY;INTERVAL=1;BYDAY=MO
-DTSTART
- ;VALUE=DATE
- :20041101
-DTEND
- ;VALUE=DATE
- :20041102
-DTSTAMP
- :20041118T014045Z
-LAST-MODIFIED
- :20041118T023846Z
-END:VEVENT
-END:VCALENDAR
-"
-   nil
-   "&23/11/2004 14:00-14:30 Jjjjj & Wwwww
- Status: TENTATIVE
- Class: PRIVATE
-&23/11/2004 14:45-15:45 BB Aaaaaaaa Bbbbb
- Status: TENTATIVE
- Class: PRIVATE
-&23/11/2004 11:00-12:00 Hhhhhhhh
- Status: TENTATIVE
- Class: PRIVATE
-&%%(and (diary-cyclic 14 12 11 2004)) 14:00-18:30 MMM Aaaaaaaaa
- Status: TENTATIVE
- Class: PRIVATE
-&%%(and (diary-block 19 11 2004 19 11 2004)) Rrrr/Cccccc ii Aaaaaaaa
- Desc: Vvvvv Rrrr aaa Cccccc
- Status: TENTATIVE
- Class: PRIVATE
-&%%(and (diary-cyclic 7 1 11 2004)) Wwww aa hhhh
- Status: TENTATIVE
- Class: PRIVATE
-"
-   "&11/23/2004 14:00-14:30 Jjjjj & Wwwww
- Status: TENTATIVE
- Class: PRIVATE
-&11/23/2004 14:45-15:45 BB Aaaaaaaa Bbbbb
- Status: TENTATIVE
- Class: PRIVATE
-&11/23/2004 11:00-12:00 Hhhhhhhh
- Status: TENTATIVE
- Class: PRIVATE
-&%%(and (diary-cyclic 14 11 12 2004)) 14:00-18:30 MMM Aaaaaaaaa
- Status: TENTATIVE
- Class: PRIVATE
-&%%(and (diary-block 11 19 2004 11 19 2004)) Rrrr/Cccccc ii Aaaaaaaa
- Desc: Vvvvv Rrrr aaa Cccccc
- Status: TENTATIVE
- Class: PRIVATE
-&%%(and (diary-cyclic 7 11 1 2004)) Wwww aa hhhh
- Status: TENTATIVE
- Class: PRIVATE
-")
+  (icalendar-tests--test-import "import-real-world-2004-11-19.ics"
+                                nil
+                                "import-real-world-2004-11-19.diary-european"
+                                "import-real-world-2004-11-19.diary-american")
 
   ;; 2004-09-09 pg
   (icalendar-tests--test-export
@@ -2270,53 +1564,16 @@ DTEND;VALUE=DATE-TIME:20041102T163000
 SUMMARY:Zahnarzt")
 
   ;; 2005-02-07 lt
-  (icalendar-tests--test-import
-   "UID
- :b60d398e-1dd1-11b2-a159-cf8cb05139f4
-SUMMARY
- :Waitangi Day
-DESCRIPTION
- :abcdef
-CATEGORIES
- :Public Holiday
-STATUS
- :CONFIRMED
-CLASS
- :PRIVATE
-DTSTART
- ;VALUE=DATE
- :20050206
-DTEND
- ;VALUE=DATE
- :20050207
-DTSTAMP
- :20050128T011209Z"
-   nil
-   "&%%(and (diary-block 6 2 2005 6 2 2005)) Waitangi Day
- Desc: abcdef
- Status: CONFIRMED
- Class: PRIVATE
- UID: b60d398e-1dd1-11b2-a159-cf8cb05139f4
-"
-   "&%%(and (diary-block 2 6 2005 2 6 2005)) Waitangi Day
- Desc: abcdef
- Status: CONFIRMED
- Class: PRIVATE
- UID: b60d398e-1dd1-11b2-a159-cf8cb05139f4
-")
+  (icalendar-tests--test-import "import-real-world-2005-02-07.ics"
+                                nil
+                                "import-real-world-2005-02-07.diary-european"
+                                "import-real-world-2005-02-07.diary-american")
 
   ;; 2005-03-01 lt
-  (icalendar-tests--test-import
-   "DTSTART;VALUE=DATE:20050217
-SUMMARY:Hhhhhh Aaaaa ii Aaaaaaaa
-UID:6AFA7558-6994-11D9-8A3A-000A95A0E830-RID
-DTSTAMP:20050118T210335Z
-DURATION:P7D"
-   nil
-   "&%%(and (diary-block 17 2 2005 23 2 2005)) Hhhhhh Aaaaa ii Aaaaaaaa
- UID: 6AFA7558-6994-11D9-8A3A-000A95A0E830-RID\n"
-   "&%%(and (diary-block 2 17 2005 2 23 2005)) Hhhhhh Aaaaa ii Aaaaaaaa
- UID: 6AFA7558-6994-11D9-8A3A-000A95A0E830-RID\n")
+  (icalendar-tests--test-import "import-real-world-2005-03-01.ics"
+                                nil
+                                "import-real-world-2005-03-01.diary-european"
+                                "import-real-world-2005-03-01.diary-american")
 
   ;; 2005-03-23 lt
   (icalendar-tests--test-export
@@ -2343,132 +1600,24 @@ SUMMARY:NNN Wwwwwwww Wwwww - Aaaaaa Pppppppp rrrrrr 
ddd oo Nnnnnnnn 30
 ")
 
   ;; bug#11473
-  (icalendar-tests--test-import
-   "BEGIN:VCALENDAR
-METHOD:REQUEST
-PRODID:Microsoft Exchange Server 2007
-VERSION:2.0
-BEGIN:VTIMEZONE
-TZID:(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna
-BEGIN:STANDARD
-DTSTART:16010101T030000
-TZOFFSETFROM:+0200
-TZOFFSETTO:+0100
-RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=10
-END:STANDARD
-BEGIN:DAYLIGHT
-DTSTART:16010101T020000
-TZOFFSETFROM:+0100
-TZOFFSETTO:+0200
-RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=3
-END:DAYLIGHT
-END:VTIMEZONE
-BEGIN:VEVENT
-ORGANIZER;CN=\"A. Luser\":MAILTO:a.luser@foo.com
-ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=\"Luser, Oth
- er\":MAILTO:other.luser@foo.com
-DESCRIPTION;LANGUAGE=en-US:\nWhassup?\n\n
-SUMMARY;LANGUAGE=en-US:Query
-DTSTART;TZID=\"(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna\"
- :20120515T150000
-DTEND;TZID=\"(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna\":2
- 0120515T153000
-UID:040000008200E00074C5B7101A82E0080000000020FFAED0CFEFCC01000000000000000
- 010000000575268034ECDB649A15349B1BF240F15
-RECURRENCE-ID;TZID=\"(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, V
- ienna\":20120515T170000
-CLASS:PUBLIC
-PRIORITY:5
-DTSTAMP:20120514T153645Z
-TRANSP:OPAQUE
-STATUS:CONFIRMED
-SEQUENCE:15
-LOCATION;LANGUAGE=en-US:phone
-X-MICROSOFT-CDO-APPT-SEQUENCE:15
-X-MICROSOFT-CDO-OWNERAPPTID:1907632092
-X-MICROSOFT-CDO-BUSYSTATUS:TENTATIVE
-X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY
-X-MICROSOFT-CDO-ALLDAYEVENT:FALSE
-X-MICROSOFT-CDO-IMPORTANCE:1
-X-MICROSOFT-CDO-INSTTYPE:3
-BEGIN:VALARM
-ACTION:DISPLAY
-DESCRIPTION:REMINDER
-TRIGGER;RELATED=START:-PT15M
-END:VALARM
-END:VEVENT
-END:VCALENDAR"
-   nil
-   "&15/5/2012 15:00-15:30 Query
- Location: phone
- Organizer: MAILTO:a.luser@foo.com
- Status: CONFIRMED
- Class: PUBLIC
- UID: 
040000008200E00074C5B7101A82E0080000000020FFAED0CFEFCC01000000000000000010000000575268034ECDB649A15349B1BF240F15
-"     nil)
+  (icalendar-tests--test-import "import-bug-11473.ics"
+                                nil
+                                "import-bug-11473.diary-european"
+                                nil)
 
   ;; 2015-12-05, mixed line endings and empty lines, see Bug#22092.
-  (icalendar-tests--test-import
-   "BEGIN:VCALENDAR\r
-PRODID:-//www.norwegian.no//iCalendar MIMEDIR//EN\r
-VERSION:2.0\r
-METHOD:REQUEST\r
-BEGIN:VEVENT\r
-UID:RFCALITEM1\r
-SEQUENCE:1512040950\r
-DTSTAMP:20141204T095043Z\r
-ORGANIZER:noreply@norwegian.no\r
-DTSTART:20141208T173000Z\r
-
-DTEND:20141208T215500Z\r
-
-LOCATION:Stavanger-Sola\r
-
-DESCRIPTION:Fly med Norwegian, reservasjon. Fra Stavanger til Troms&#248; 8. 
des 2014 18:30, DY545Fly med Norwegian, reservasjon . Fra Stavanger til 
Troms&#248; 8. des 2014 21:00, DY390\r
-
-X-ALT-DESC;FMTTYPE=text/html:<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 
3.2//EN\"><html><head><META NAME=\"Generator\" CONTENT=\"MS Exchange Server 
version 08.00.0681.000\"><title></title></head><body><b><font face=\"Calibri\" 
size=\"3\">Reisereferanse</p></body></html>
-SUMMARY:Norwegian til Tromsoe-Langnes -\r
-
-CATEGORIES:Appointment\r
-
-
-PRIORITY:5\r
-
-CLASS:PUBLIC\r
-
-TRANSP:OPAQUE\r
-END:VEVENT\r
-END:VCALENDAR
-"
-"&2014/12/8 18:30-22:55 Norwegian til Tromsoe-Langnes -
- Desc: Fly med Norwegian, reservasjon. Fra Stavanger til Troms&#248; 8. des 
2014 18:30, DY545Fly med Norwegian, reservasjon . Fra Stavanger til Troms&#248; 
8. des 2014 21:00, DY390
- Location: Stavanger-Sola
- Organizer: noreply@norwegian.no
- Class: PUBLIC
- UID: RFCALITEM1
-"
-"&8/12/2014 18:30-22:55 Norwegian til Tromsoe-Langnes -
- Desc: Fly med Norwegian, reservasjon. Fra Stavanger til Troms&#248; 8. des 
2014 18:30, DY545Fly med Norwegian, reservasjon . Fra Stavanger til Troms&#248; 
8. des 2014 21:00, DY390
- Location: Stavanger-Sola
- Organizer: noreply@norwegian.no
- Class: PUBLIC
- UID: RFCALITEM1
-"
-"&12/8/2014 18:30-22:55 Norwegian til Tromsoe-Langnes -
- Desc: Fly med Norwegian, reservasjon. Fra Stavanger til Troms&#248; 8. des 
2014 18:30, DY545Fly med Norwegian, reservasjon . Fra Stavanger til Troms&#248; 
8. des 2014 21:00, DY390
- Location: Stavanger-Sola
- Organizer: noreply@norwegian.no
- Class: PUBLIC
- UID: RFCALITEM1
-"
-)
-  )
+  (icalendar-tests--test-import "import-bug-22092.ics"
+                                "import-bug-22092.diary-iso"
+                                "import-bug-22092.diary-european"
+                                "import-bug-22092.diary-american"))
 
 (defun icalendar-test--format (string &optional day zone)
+  "Decode and format STRING with DAY and ZONE."
   (let ((time (icalendar--decode-isodatetime string day zone)))
     (format-time-string "%FT%T%z" (encode-time time) 0)))
 
 (defun icalendar-tests--decode-isodatetime (_ical-string)
+  "Test icalendar--decode-isodatetime."
   (should (equal (icalendar-test--format "20040917T050910-0200")
                  "2004-09-17T03:09:10+0000"))
   (should (equal (icalendar-test--format "20040917T050910")
diff --git a/test/lisp/calendar/time-date-tests.el 
b/test/lisp/calendar/time-date-tests.el
index 233d43c..3f8954a 100644
--- a/test/lisp/calendar/time-date-tests.el
+++ b/test/lisp/calendar/time-date-tests.el
@@ -22,19 +22,67 @@
 (require 'ert)
 (require 'time-date)
 
+(ert-deftest test-obsolete-with-decoded-time-value ()
+  (with-suppressed-warnings ((obsolete with-decoded-time-value))
+    (with-decoded-time-value ((high low micro pico type '(1 2 3 4 5 6 8 8)))
+      (should (equal (list high low micro pico type) '(1 2 3 4 3))))))
+
+(ert-deftest test-obsolete-encode-time-value ()
+  (should (equal (with-suppressed-warnings ((obsolete encode-time-value))
+                   (encode-time-value 1 2 3 4 0))
+                 '(1 . 2)))
+  (should (equal (with-suppressed-warnings ((obsolete encode-time-value))
+                   (encode-time-value 1 2 3 4 1))
+                 '(1 2)))
+  (should (equal (with-suppressed-warnings ((obsolete encode-time-value))
+                   (encode-time-value 1 2 3 4 2))
+                 '(1 2 3)))
+  (should (equal (with-suppressed-warnings ((obsolete encode-time-value))
+                   (encode-time-value 1 2 3 4 3))
+                 '(1 2 3 4))))
+
 (ert-deftest test-leap-year ()
   (should-not (date-leap-year-p 1999))
   (should-not (date-leap-year-p 1900))
   (should (date-leap-year-p 2000))
   (should (date-leap-year-p 2004)))
 
+(ert-deftest test-days-to-time ()
+  (should (equal (days-to-time 0) '(0 0)))
+  (should (equal (days-to-time 1) '(1 20864)))
+  (should (equal (days-to-time 999) '(1317 2688)))
+  (should (equal (days-to-time 0.0) '(0 0 0 0)))
+  (should (equal (days-to-time 0.5) '(0 43200 0 0)))
+  (should (equal (days-to-time 1.0) '(1 20864 0 0)))
+  (should (equal (days-to-time 999.0) '(1317 2688 0 0))))
+
+(ert-deftest test-seconds-to-string ()
+  (should (equal (seconds-to-string 0) "0s"))
+  (should (equal (seconds-to-string 9) "9.00s"))
+  (should (equal (seconds-to-string 99) "99.00s"))
+  (should (equal (seconds-to-string 999) "16.65m"))
+  (should (equal (seconds-to-string 9999) "2.78h"))
+  (should (equal (seconds-to-string 99999) "27.78h"))
+  (should (equal (seconds-to-string 999999) "11.57d"))
+  (should (equal (seconds-to-string 9999999) "115.74d"))
+  (should (equal (seconds-to-string 99999999) "3.17y"))
+  (should (equal (seconds-to-string 999999999) "31.69y")))
+
 (ert-deftest test-days-in-month ()
   (should (= (date-days-in-month 2004 2) 29))
   (should (= (date-days-in-month 2004 3) 31))
+  (should (= (date-days-in-month 2019 2) 28))
+  (should (= (date-days-in-month 2020 12) 31))
   (should-not (= (date-days-in-month 1900 3) 28))
+  (should-error (date-days-in-month 2020 0))
   (should-error (date-days-in-month 2020 15))
   (should-error (date-days-in-month 2020 'foo)))
 
+(ert-deftest test-format-seconds ()
+  (should (equal (format-seconds "%y %d %h %m %s %%" 0) "0 0 0 0 0 %"))
+  (should (equal (format-seconds "%y %d %h %m %s %%" 9999999) "0 115 17 46 39 
%"))
+  (should (equal (format-seconds "%y %d %h %m %z %s %%" 1) " 1 %")))
+
 (ert-deftest test-ordinal ()
   (should (equal (date-ordinal-to-time 2008 271)
                  '(nil nil nil 27 9 2008 nil nil nil)))
@@ -107,7 +155,8 @@
                    '(12 15 14 8 7 2019 1 t 7200)))))
 
 (ert-deftest test-time-since ()
-  (should (time-equal-p 0 (time-since nil))))
+  (should (time-equal-p 0 (time-since nil)))
+  (should (= (cadr (time-since (time-subtract (current-time) 1))) 1)))
 
 (ert-deftest test-time-decoded-period ()
   (should (equal (decoded-time-period '(nil nil 1 nil nil nil nil nil nil))
@@ -119,6 +168,7 @@
   (should (equal (decoded-time-period '(0 0 0 1 0 0 nil nil nil)) 86400))
   (should (equal (decoded-time-period '(0 0 0 0 1 0 nil nil nil)) 2592000))
   (should (equal (decoded-time-period '(0 0 0 0 0 1 nil nil nil)) 31536000))
+  (should (equal (decoded-time-period '(1 2 3 4 5 6 nil nil nil)) 202532521))
 
   (should (equal (decoded-time-period '((135 . 10) 0 0 0 0 0 nil nil nil))
                  13.5)))
diff --git a/test/lisp/emacs-lisp/bindat-tests.el 
b/test/lisp/emacs-lisp/bindat-tests.el
index 14f95a8..842ef10 100644
--- a/test/lisp/emacs-lisp/bindat-tests.el
+++ b/test/lisp/emacs-lisp/bindat-tests.el
@@ -1,4 +1,4 @@
-;;; bindat-tests.el --- tests for bindat.el  -*- lexical-binding: t; -*-
+;;; bindat-tests.el --- tests for bindat.el  -*- lexical-binding: t; coding: 
utf-8; -*-
 
 ;; Copyright (C) 2019-2020 Free Software Foundation, Inc.
 
@@ -94,7 +94,13 @@
               (src-ip .
                      [192 168 1 101])
               (dest-ip .
-                      [192 168 1 100]))))))
+                       [192 168 1 100]))))))
+
+(ert-deftest bindat-test-pack/multibyte-string-fails ()
+  (should-error (bindat-pack nil nil "ö")))
+
+(ert-deftest bindat-test-unpack/multibyte-string-fails ()
+  (should-error (bindat-unpack nil "ö")))
 
 (ert-deftest bindat-test-format-vector ()
   (should (equal (bindat-format-vector [1 2 3] "%d" "x" 2) "1x2"))
diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el 
b/test/lisp/emacs-lisp/bytecomp-tests.el
index a9dcf15..ea5aacd 100644
--- a/test/lisp/emacs-lisp/bytecomp-tests.el
+++ b/test/lisp/emacs-lisp/bytecomp-tests.el
@@ -444,8 +444,8 @@ Subtests signal errors if something goes wrong."
            (if compile
                (let ((byte-compile-dest-file-function
                       (lambda (e) elcfile)))
-                 (byte-compile-file elfile t))
-             (load elfile nil 'nomessage)))
+                 (byte-compile-file elfile)))
+           (load elfile nil 'nomessage))
       (when elfile (delete-file elfile))
       (when elcfile (delete-file elcfile)))))
 (put 'test-byte-comp-compile-and-load 'lisp-indent-function 1)
@@ -646,7 +646,8 @@ literals (Bug#20852)."
                     (setq bytecomp-tests--foobar (bytecomp-tests--foobar))))
       (print form (current-buffer)))
     (write-region (point-min) (point-max) source nil 'silent)
-    (byte-compile-file source t)
+    (byte-compile-file source)
+    (load source)
     (should (equal bytecomp-tests--foobar (cons 1 2)))))
 
 (ert-deftest bytecomp-tests--test-no-warnings-with-advice ()
diff --git a/test/lisp/emacs-lisp/package-resources/key.pub 
b/test/lisp/emacs-lisp/package-resources/key.pub
index a326d34..5e2ebc5 100644
--- a/test/lisp/emacs-lisp/package-resources/key.pub
+++ b/test/lisp/emacs-lisp/package-resources/key.pub
@@ -1,18 +1,20 @@
 -----BEGIN PGP PUBLIC KEY BLOCK-----
-Version: GnuPG v1.4.14 (GNU/Linux)
 
-mQENBFJNB8gBCACfbtpvYrM8V1HM0KFlIwatcEJugHqwOHpr/Z9mrCW0fxyQAW/d
-2L+3QVNsN9Tz/K9lLcBUgeR7rhVEzHNqhmhNj/HnikwGqXbIofhp+QbZmBKnAlCz
-d77kg8K9lozHtfTkm1gX/7DdPzQKmgi7WOzzi2395wGubeqJLvYaEcqVbI0Eob+E
-3CzRjNy/e/Tf3TJRW5etTcdZN6LVuIY7tNCHqlQZTwyycON/hfLTX6cLCnzDsqm/
-NxCuwn9aqP9aGRGfIu7Y+If3zTymvrXEPUN98OEID814bOKdx0uVTZRiSMbvuTGI
-8uMa/kpGX/78rqI61gbZV51RFoU7pT2tzwY/ABEBAAG0HkouIFIuIEhhY2tlciA8
-anJoQGV4YW1wbGUuY29tPokBOAQTAQIAIgUCUk0HyAIbAwYLCQgHAwIGFQgCCQoL
-BBYCAwECHgECF4AACgkQtpVAhgkYletuhQf+JAyHYhTZNxjq0UYlikuLX8EtYbXX
-PB+03J0B73SMzEai5XsiTU2ADxqxwr7pveVK1INf+IGLiiXBlQq+4DSOvQY4xLfp
-58jTOYRV1ECvlXK/JtvVOwufXREADaydf9l/MUxA5G2PPBWIuQknh3ysPSsx68OJ
-SzNHFwklLn0DKc4WloE/GLDpTzimnCg7QGzuUo3Iilpjdy8EvTdI5d3jx/mGJIwI
-goB+YZgyxSPM+GjDwh5DEwD7OexNqqa7RynnmU0epmlYyi9UufCHLwgiiEIzjpWi
-6+iF+CQ45ZAKncovByenIUv73J3ImOudrsskeAHBmahljv1he6uV9Egj2Q==
-=b5Kg
+mI0EX48EbAEEANrsWXyZ4MRZRjVbLAh5jX/+1+31oB/aJ/q/5DkH1qUHJf0La9LC
+sykUSM3H2u5VWLytX/ozrxIRYX13GR2xBxyJlUkDWB209AAVLFrjSp1yUX/Sb5SU
+Kb7p421ZAeHiOxfnLRuErFZkTfzY19mUCyw4cdamw430V3mUC9uns/d9ABEBAAG0
+LUouIFJhbmRvbSBIYWNrZXIgKFRFU1QgS0VZKSA8anJoQGV4YW1wbGUub3JnPojO
+BBMBCgA4FiEEHP310DrP36xrZ1kSMKdkJgeTYhoFAl+PBGwCGwMFCwkIBwIGFQoJ
+CAsCBBYCAwECHgECF4AACgkQMKdkJgeTYhq9MQP7BYkCk8r5G777Ilp8kWjsEIo3
+aDX9jORiNfMAGys/aLjjEajHFAlTQKfSLm/VXLDYtK28c8ACjThQagaDF46MRWqQ
+rFFiH4IAZRgj2ELj+/j1ljQZjGjKR2Yx4BCDhbumz8zeMSPL6yFT5+8LOMUAtdv4
+lEPWXW0AycylbdbE7024jQRfjwRsAQQApjTw9kONmSVouCi8ZIQwwYiA9tLzbSZv
+CYxbJ6KH0icRhBLfdb1hL/Kn8x3k+xll9A0c/ABVkMxRcbQkY98xsFck7E2GcvnC
+sY+w/NdcUUZJYMB3l2MH5ojCbOk5jSAZzxzeFcJhNAhmLqomMHg2LI6KDVey6iYU
+FxyIpIQ3SlkAEQEAAYi2BBgBCgAgFiEEHP310DrP36xrZ1kSMKdkJgeTYhoFAl+P
+BGwCGwwACgkQMKdkJgeTYhrtywQAhoCR/skBSQWWBI10N0qhtdlNxbpvK8ErSPKw
+wS74Pq407Zv0VD9ual/HC3Uet2z8LeG9ZwU4Jd23g96fmJt7AM9CQWrOhC242JYr
+YSqWxANyek8otsvppJNHtt2Stmknv7XbJFFB1JDC8WKo8lVo9/MkmzROxuEFEvOU
+Yn923VI=
+=NRtx
 -----END PGP PUBLIC KEY BLOCK-----
diff --git a/test/lisp/emacs-lisp/package-resources/key.sec 
b/test/lisp/emacs-lisp/package-resources/key.sec
index d21e6ae..dbc80f4 100644
--- a/test/lisp/emacs-lisp/package-resources/key.sec
+++ b/test/lisp/emacs-lisp/package-resources/key.sec
@@ -1,33 +1,35 @@
 -----BEGIN PGP PRIVATE KEY BLOCK-----
-Version: GnuPG v1.4.14 (GNU/Linux)
 
-lQO+BFJNB8gBCACfbtpvYrM8V1HM0KFlIwatcEJugHqwOHpr/Z9mrCW0fxyQAW/d
-2L+3QVNsN9Tz/K9lLcBUgeR7rhVEzHNqhmhNj/HnikwGqXbIofhp+QbZmBKnAlCz
-d77kg8K9lozHtfTkm1gX/7DdPzQKmgi7WOzzi2395wGubeqJLvYaEcqVbI0Eob+E
-3CzRjNy/e/Tf3TJRW5etTcdZN6LVuIY7tNCHqlQZTwyycON/hfLTX6cLCnzDsqm/
-NxCuwn9aqP9aGRGfIu7Y+If3zTymvrXEPUN98OEID814bOKdx0uVTZRiSMbvuTGI
-8uMa/kpGX/78rqI61gbZV51RFoU7pT2tzwY/ABEBAAH+AwMCKCCpPNXkXuVgF7cz
-eByuvgIO7wImDYGOdJqsASSzV4q0u1acnGtlxg7WphKDF9RnC5+1ZZ1ZcrBcv2uJ
-xZm2jHdjqM3FmgQTN70GVzO1nKEur2wxlKotG4Q+8BtaRDwHdKpQFk+QW9aInH3C
-BkNWTK97iFwZaoUGxKuRJb35qjMe3SsDE7kdbtOqO+tOeppRVeOOZCn7F33ir/6i
-j2gmIME6LFDzvBi6YAyMBSh90Ak70HJINt0QfXlZf5MtX1NaxaEcnsRmwwcNqxh9
-JvcC9q4WrR92NhHCHI+lOsAe7hbwo/VkwRjSSx0HdKkx6kvdcNj/9LeX/jykzLvg
-kEqvAqT4Jmk57W2seqvpNcAO+eUVrJ5D1OR6khsUtikPp2pQH5MDXJDGcie+ZAFb
-w6BwoWBDBjooKtfuP0LKqrdtJG2JLe6yhBhWvfqHPBlUU1SsA7a5aTCLo8FiqgEI
-Kyy60zMx/2Mi48oN1a/mAoV1MTWLhOVUWJlIHM7nVLj1OaX0316LcLX/uTLTq40p
-apHKwERanzY7f8ROiv/Fa/J+9cCsfOLKfjFAjpBVUVoOb39HsyS/vvkGMY4kgaD6
-K6r9JPdsaoYvsLkxk5HyHF7Mk2uS1z1EIArD2/3lRiX6ag+IU1Nl3XDkgfZj06K3
-juS84dGF8CmN49uOEjzAJAQZH9jTs5OKzUuZhGJF+gt0L78vLOoKRr8bu1N1GPqU
-wnS908HWruXzjJl1CAhnuCa8FnDaU+tmEKjYpWuelx85kolpMW7LT5gOFZr84MIj
-Kq3Rt2hU6qQ7Cdy1ep531YKkmyh9Y4l/Tgir1OtnQQqtNuwHI497l7qAUnKZBBHZ
-guApjS9BoHsRXkw2mgDssZ+khOwj/xJm876nFSiQeCD0aIbU/4zJ9e2HUOJAZI1r
-d7QeSi4gUi4gSGFja2VyIDxqcmhAZXhhbXBsZS5jb20+iQE4BBMBAgAiBQJSTQfI
-AhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRC2lUCGCRiV626FB/4kDIdi
-FNk3GOrRRiWKS4tfwS1htdc8H7TcnQHvdIzMRqLleyJNTYAPGrHCvum95UrUg1/4
-gYuKJcGVCr7gNI69BjjEt+nnyNM5hFXUQK+Vcr8m29U7C59dEQANrJ1/2X8xTEDk
-bY88FYi5CSeHfKw9KzHrw4lLM0cXCSUufQMpzhaWgT8YsOlPOKacKDtAbO5SjciK
-WmN3LwS9N0jl3ePH+YYkjAiCgH5hmDLFI8z4aMPCHkMTAPs57E2qprtHKeeZTR6m
-aVjKL1S58IcvCCKIQjOOlaLr6IX4JDjlkAqdyi8HJ6chS/vcnciY652uyyR4AcGZ
-qGWO/WF7q5X0SCPZ
-=5FZK
+lQIGBF+PBGwBBADa7Fl8meDEWUY1WywIeY1//tft9aAf2if6v+Q5B9alByX9C2vS
+wrMpFEjNx9ruVVi8rV/6M68SEWF9dxkdsQcciZVJA1gdtPQAFSxa40qdclF/0m+U
+lCm+6eNtWQHh4jsX5y0bhKxWZE382NfZlAssOHHWpsON9Fd5lAvbp7P3fQARAQAB
+/gcDAngNw4ppSPBe/w734cz++xNEv0TDgwxGBWp2wGSwWao04Nl1U4LkjiIy+dkc
+uUPwEZMvxXwMcq10PPH26ifP8Xfi/zANXUoLJ0DsG6rtE3BcSC9MPFe3EJENtcIP
+a0jFLsbi72aBzolNEDCZCv93znXFPekaXw/RAeeFLJz8GR2Sx6bHbTJKklXgWPHw
+C5Dw6xr/kEZktgjlhjkx280STpLGaFO4jiiGZ4Obp5ePp7kyOzDUzaimdZgJwClT
+VbZDNQMTzgQrBOP8doXlo9euW4Wo1IYBIOwgeYieM3ZA9YjJAmp4lFnk/KFYt0Ak
+0H9IWzDU8VERcU4B04PSXahzvB1Ii7C7bbHxPyuu6sAfMK8DRkrGjwgAlrhuWNLX
+M07acT/E9Pm+mBlDcdkyKB2LfwgaVb9F3C25sfcFSvc5p+sqgZp1Zx7Qg9pOhQjw
+U7Ln+96c0bUl+iQKdm3TGjOXAFUHYXbRkx2cJ4gxnMVNj0D68xBtBSm0LUouIFJh
+bmRvbSBIYWNrZXIgKFRFU1QgS0VZKSA8anJoQGV4YW1wbGUub3JnPojOBBMBCgA4
+FiEEHP310DrP36xrZ1kSMKdkJgeTYhoFAl+PBGwCGwMFCwkIBwIGFQoJCAsCBBYC
+AwECHgECF4AACgkQMKdkJgeTYhq9MQP7BYkCk8r5G777Ilp8kWjsEIo3aDX9jORi
+NfMAGys/aLjjEajHFAlTQKfSLm/VXLDYtK28c8ACjThQagaDF46MRWqQrFFiH4IA
+ZRgj2ELj+/j1ljQZjGjKR2Yx4BCDhbumz8zeMSPL6yFT5+8LOMUAtdv4lEPWXW0A
+ycylbdbE702dAgYEX48EbAEEAKY08PZDjZklaLgovGSEMMGIgPbS820mbwmMWyei
+h9InEYQS33W9YS/yp/Md5PsZZfQNHPwAVZDMUXG0JGPfMbBXJOxNhnL5wrGPsPzX
+XFFGSWDAd5djB+aIwmzpOY0gGc8c3hXCYTQIZi6qJjB4NiyOig1XsuomFBcciKSE
+N0pZABEBAAH+BwMCXeUOBwcOsxb/AY6rnHmgACNTGwIa5vgelw0qfET0ms/YzVrN
+ufikyV9dEWVxJyuTKav978wanPu7VcCh0pTjL2nTm2nZWyRJN4gb3UIC0MA1xfB2
+yPLTCmsGeJhVOqi4Af/r06mk+NOQ96ivOA2CJuw1LSpcUtuYxB5t/grGyEojYjRP
+s0Htvf2bfN9KbFJ26DGsfYzC8bCxm9szPFHBQjw4NboCigUSAHmkoTW01aWZU9Vq
+brY4cWhdmCqHgfmsQgzP3LfaAQ6kJ/bkuKef7z57lz5XmlyjMQGWcZWp5xf2n81p
+BV6unaIPyavzkKVAXizVfNiHNJgK9PoVoEOJkPLjRfMxVmFSGN/oF7lVTRWfOIwo
+68rtNPhr6UzE4ArGHYv/pK3kijUp5daWmfrySWPcwoVAaR3mIIVs/1rhd9aZrwn6
+Q07Yo5u11rH9b8anZQF3BdTcrnU9pUzLYlFPnfhtyGqhikQILtPTf0iwr8hpG9b2
+Zoi2BBgBCgAgFiEEHP310DrP36xrZ1kSMKdkJgeTYhoFAl+PBGwCGwwACgkQMKdk
+JgeTYhrtywQAhoCR/skBSQWWBI10N0qhtdlNxbpvK8ErSPKwwS74Pq407Zv0VD9u
+al/HC3Uet2z8LeG9ZwU4Jd23g96fmJt7AM9CQWrOhC242JYrYSqWxANyek8otsvp
+pJNHtt2Stmknv7XbJFFB1JDC8WKo8lVo9/MkmzROxuEFEvOUYn923VI=
+=2DW8
 -----END PGP PRIVATE KEY BLOCK-----
diff --git a/test/lisp/emacs-lisp/package-resources/signed/archive-contents.sig 
b/test/lisp/emacs-lisp/package-resources/signed/archive-contents.sig
index 658edd3..dac168b 100644
Binary files 
a/test/lisp/emacs-lisp/package-resources/signed/archive-contents.sig and 
b/test/lisp/emacs-lisp/package-resources/signed/archive-contents.sig differ
diff --git a/test/lisp/emacs-lisp/package-resources/signed/signed-bad-1.0.el 
b/test/lisp/emacs-lisp/package-resources/signed/signed-bad-1.0.el
index 3734823..ff070c6 100644
--- a/test/lisp/emacs-lisp/package-resources/signed/signed-bad-1.0.el
+++ b/test/lisp/emacs-lisp/package-resources/signed/signed-bad-1.0.el
@@ -1,4 +1,4 @@
-;;; signed-bad.el --- A single-file package with bad signature
+;;; signed-bad.el --- A single-file package with bad signature  -*- 
lexical-binding: t -*-
 
 ;; Author: J. R. Hacker <jrh@example.com>
 ;; Version: 1.0
diff --git a/test/lisp/emacs-lisp/package-resources/signed/signed-good-1.0.el 
b/test/lisp/emacs-lisp/package-resources/signed/signed-good-1.0.el
index 22718df..60b1b86 100644
--- a/test/lisp/emacs-lisp/package-resources/signed/signed-good-1.0.el
+++ b/test/lisp/emacs-lisp/package-resources/signed/signed-good-1.0.el
@@ -1,4 +1,4 @@
-;;; signed-good.el --- A single-file package with good signature
+;;; signed-good.el --- A single-file package with good signature  -*- 
lexical-binding: t -*-
 
 ;; Author: J. R. Hacker <jrh@example.com>
 ;; Version: 1.0
diff --git 
a/test/lisp/emacs-lisp/package-resources/signed/signed-good-1.0.el.sig 
b/test/lisp/emacs-lisp/package-resources/signed/signed-good-1.0.el.sig
index 7479187..5b1c721 100644
Binary files 
a/test/lisp/emacs-lisp/package-resources/signed/signed-good-1.0.el.sig and 
b/test/lisp/emacs-lisp/package-resources/signed/signed-good-1.0.el.sig differ
diff --git a/test/lisp/emacs-lisp/package-resources/signed/update-signatures.sh 
b/test/lisp/emacs-lisp/package-resources/signed/update-signatures.sh
new file mode 100755
index 0000000..a48c9bb
--- /dev/null
+++ b/test/lisp/emacs-lisp/package-resources/signed/update-signatures.sh
@@ -0,0 +1,32 @@
+#! /bin/sh
+
+# Generate a new key and update the signatures for tests.
+
+# Copyright (C) 2020 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/>.
+
+export GPG_AGENT=""
+KEYRING="./key.ring"
+TRUSTDB="./trust.db"
+GPG="gpg --no-default-keyring --trustdb-name $TRUSTDB --keyring $KEYRING --yes"
+
+rm $KEYRING
+$GPG --full-generate-key
+$GPG --export --armor > "../key.pub"
+$GPG --export-secret-keys -armor > "../key.sec"
+$GPG --detach-sign --sign "./archive-contents"
+$GPG --detach-sign --sign "./signed-good-1.0.el"
diff --git a/test/lisp/emacs-lisp/package-tests.el 
b/test/lisp/emacs-lisp/package-tests.el
index 155a8e6..2326754 100644
--- a/test/lisp/emacs-lisp/package-tests.el
+++ b/test/lisp/emacs-lisp/package-tests.el
@@ -151,6 +151,15 @@
                     `(insert-file-contents ,file))
                ,@body)))
 
+       (when ,upload-base
+         (dolist (f '("archive-contents"
+                      "simple-single-1.3.el"
+                      "simple-single-1.4.el"
+                      "simple-single-readme.txt"))
+           (ignore-errors
+             (delete-file
+              (expand-file-name f package-test-archive-upload-base))))
+         (delete-directory package-test-archive-upload-base))
        (when (file-directory-p package-test-user-dir)
          (delete-directory package-test-user-dir t))
 
diff --git a/test/lisp/ffap-tests.el b/test/lisp/ffap-tests.el
index e8c1266..ca8c108 100644
--- a/test/lisp/ffap-tests.el
+++ b/test/lisp/ffap-tests.el
@@ -117,6 +117,12 @@ left alone when opening a URL in an external browser."
      t "C:\\temp\\program.log on Windows or /var/log/program.log on Unix.")
     "\\temp\\program.log")))
 
+(ert-deftest ffap-test-no-newlines ()
+  (should-not
+   (with-temp-buffer
+     (save-excursion (insert "type="))
+     (ffap-guess-file-name-at-point))))
+
 (provide 'ffap-tests)
 
 ;;; ffap-tests.el ends here
diff --git a/test/data/files-bug18141.el.gz 
b/test/lisp/files-resources/files-bug18141.el.gz
similarity index 100%
rename from test/data/files-bug18141.el.gz
rename to test/lisp/files-resources/files-bug18141.el.gz
diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el
index 1b964af..8818099 100644
--- a/test/lisp/files-tests.el
+++ b/test/lisp/files-tests.el
@@ -20,6 +20,7 @@
 ;;; Code:
 
 (require 'ert)
+(require 'ert-x)
 (require 'nadvice)
 (eval-when-compile (require 'cl-lib))
 (require 'bytecomp) ; `byte-compiler-base-file-name'.
@@ -151,7 +152,7 @@ form.")
           (should (file-test--do-local-variables-test str subtest)))))))
 
 (defvar files-test-bug-18141-file
-  (expand-file-name "data/files-bug18141.el.gz" (getenv 
"EMACS_TEST_DIRECTORY"))
+  (ert-resource-file "files-bug18141.el.gz")
   "Test file for bug#18141.")
 
 (ert-deftest files-tests-bug-18141 ()
diff --git a/test/lisp/files-x-tests.el b/test/lisp/files-x-tests.el
index d3ed4b5..9db1983 100644
--- a/test/lisp/files-x-tests.el
+++ b/test/lisp/files-x-tests.el
@@ -1,4 +1,4 @@
-;;; files-x-tests.el --- tests for files-x.el.
+;;; files-x-tests.el --- tests for files-x.el.  -*- lexical-binding: t -*-
 
 ;; Copyright (C) 2016-2020 Free Software Foundation, Inc.
 
@@ -35,6 +35,7 @@
   '((remote-null-device . "/dev/null")))
 (defconst files-x-test--variables4
   '((remote-null-device . "null")))
+(defvar remote-null-device)
 (put 'remote-shell-file-name 'safe-local-variable #'identity)
 (put 'remote-shell-command-switch 'safe-local-variable #'identity)
 (put 'remote-shell-interactive-switch 'safe-local-variable #'identity)
diff --git a/test/lisp/help-tests.el b/test/lisp/help-tests.el
index 0862d12..079b111 100644
--- a/test/lisp/help-tests.el
+++ b/test/lisp/help-tests.el
@@ -3,6 +3,8 @@
 ;; Copyright (C) 2019-2020 Free Software Foundation, Inc.
 
 ;; Author: Juanma Barranquero <lekktu@gmail.com>
+;;         Eli Zaretskii <eliz@gnu.org>
+;;         Stefan Kangas <stefankangas@gmail.com>
 ;; Keywords: help, internal
 
 ;; This file is part of GNU Emacs.
@@ -23,6 +25,7 @@
 ;;; Code:
 
 (require 'ert)
+(eval-when-compile (require 'cl-lib))
 
 (ert-deftest help-split-fundoc-SECTION ()
   "Test new optional arg SECTION."
@@ -51,6 +54,313 @@
     (should (equal (help-split-fundoc nil t 'usage)  nil))
     (should (equal (help-split-fundoc nil t 'doc)    nil))))
 
+
+;;; substitute-command-keys
+
+(defmacro with-substitute-command-keys-test (&rest body)
+  `(cl-flet* ((test
+               (lambda (orig result)
+                 (should (equal-including-properties
+                          (substitute-command-keys orig)
+                          result))))
+              (test-re
+               (lambda (orig regexp)
+                 (should (string-match (concat "^" regexp "$")
+                                       (substitute-command-keys orig))))))
+     ,@body))
+
+(ert-deftest help-tests-substitute-command-keys/no-change ()
+  (with-substitute-command-keys-test
+   (test "foo" "foo")
+   (test "\\invalid-escape" "\\invalid-escape")))
+
+(ert-deftest help-tests-substitute-command-keys/commands ()
+  (with-substitute-command-keys-test
+   (test "foo \\[goto-char]" "foo M-g c")
+   (test "\\[next-line]" "C-n")
+   (test "\\[next-line]\n\\[next-line]" "C-n\nC-n")
+   (test "\\[next-line]\\[previous-line]" "C-nC-p")
+   (test "\\[next-line]\\=\\[previous-line]" "C-n\\[previous-line]")
+   ;; Allow any style of quotes, since the terminal might not support
+   ;; UTF-8.  Same thing is done below.
+   (test-re "\\[next-line]`foo'" "C-n[`'‘]foo['’]")
+   (test "\\[emacs-version]" "M-x emacs-version")
+   (test "\\[emacs-version]\\[next-line]" "M-x emacs-versionC-n")
+   (test-re "\\[emacs-version]`foo'" "M-x emacs-version[`'‘]foo['’]")))
+
+(ert-deftest help-tests-substitute-command-keys/keymaps ()
+  (with-substitute-command-keys-test
+   (test "\\{minibuffer-local-must-match-map}"
+               "\
+key             binding
+---             -------
+
+C-g            abort-recursive-edit
+TAB            minibuffer-complete
+C-j            minibuffer-complete-and-exit
+RET            minibuffer-complete-and-exit
+ESC            Prefix Command
+SPC            minibuffer-complete-word
+?              minibuffer-completion-help
+<C-tab>                file-cache-minibuffer-complete
+<XF86Back>     previous-history-element
+<XF86Forward>  next-history-element
+<down>         next-line-or-history-element
+<next>         next-history-element
+<prior>                switch-to-completions
+<up>           previous-line-or-history-element
+
+M-v            switch-to-completions
+
+M-<            minibuffer-beginning-of-buffer
+M-n            next-history-element
+M-p            previous-history-element
+M-r            previous-matching-history-element
+M-s            next-matching-history-element
+
+")))
+
+(ert-deftest help-tests-substitute-command-keys/keymap-change ()
+  (with-substitute-command-keys-test
+   (test "\\<minibuffer-local-must-match-map>\\[abort-recursive-edit]" "C-g")
+   (test "\\<emacs-lisp-mode-map>\\[eval-defun]" "C-M-x")))
+
+(ert-deftest help-tests-substitute-command-keys/undefined-map ()
+  (with-substitute-command-keys-test
+   (test-re "\\{foobar-map}"
+                  "\nUses keymap [`'‘]foobar-map['’], which is not currently 
defined.\n")))
+
+(ert-deftest help-tests-substitute-command-keys/quotes ()
+ (with-substitute-command-keys-test
+  (let ((text-quoting-style 'curve))
+    (test "quotes ‘like this’" "quotes ‘like this’")
+    (test "`x'" "‘x’")
+    (test "`" "‘")
+    (test "'" "’")
+    (test "\\`" "\\‘"))
+  (let ((text-quoting-style 'straight))
+    (test "quotes `like this'" "quotes 'like this'")
+    (test "`x'" "'x'")
+    (test "`" "'")
+    (test "'" "'")
+    (test "\\`" "\\'"))
+  (let ((text-quoting-style 'grave))
+    (test "quotes `like this'" "quotes `like this'")
+    (test "`x'" "`x'")
+    (test "`" "`")
+    (test "'" "'")
+    (test "\\`" "\\`"))))
+
+(ert-deftest help-tests-substitute-command-keys/literals ()
+  (with-substitute-command-keys-test
+   (test "foo \\=\\[goto-char]" "foo \\[goto-char]")
+   (test "foo \\=\\=" "foo \\=")
+   (test "\\=\\=" "\\=")
+   (test "\\=\\[" "\\[")
+   (let ((text-quoting-style 'curve))
+     (test "\\=`x\\='" "`x'"))
+   (let ((text-quoting-style 'straight))
+     (test "\\=`x\\='" "`x'"))
+   (let ((text-quoting-style 'grave))
+     (test "\\=`x\\='" "`x'"))))
+
+(ert-deftest help-tests-substitute-command-keys/no-change ()
+  (with-substitute-command-keys-test
+   (test "\\[foobar" "\\[foobar")
+   (test "\\=" "\\=")))
+
+(ert-deftest help-tests-substitute-command-keys/multibyte ()
+  ;; Cannot use string= here, as that compares unibyte and multibyte
+  ;; strings not equal.
+  (should (compare-strings
+           (substitute-command-keys "\200 \\[goto-char]") nil nil
+           "\200 M-g c" nil nil)))
+
+(ert-deftest help-tests-substitute-command-keys/apropos ()
+  (save-window-excursion
+    (apropos "foo")
+    (switch-to-buffer "*Apropos*")
+    (goto-char (point-min))
+    (should (looking-at "Type RET on"))))
+
+(defvar help-tests-major-mode-map
+  (let ((map (make-keymap)))
+    (define-key map "x" 'foo-original)
+    (define-key map "1" 'foo-range)
+    (define-key map "2" 'foo-range)
+    (define-key map "3" 'foo-range)
+    (define-key map "4" 'foo-range)
+    (define-key map (kbd "C-e") 'foo-something)
+    (define-key map '[F1] 'foo-function-key1)
+    (define-key map "(" 'short-range)
+    (define-key map ")" 'short-range)
+    (define-key map "a" 'foo-other-range)
+    (define-key map "b" 'foo-other-range)
+    (define-key map "c" 'foo-other-range)
+    map))
+
+(define-derived-mode help-tests-major-mode nil
+  "Major mode for testing shadowing.")
+
+(defvar help-tests-minor-mode-map
+  (let ((map (make-keymap)))
+    (define-key map "x" 'foo-shadow)
+    (define-key map (kbd "C-e") 'foo-shadow)
+    map))
+
+(define-minor-mode help-tests-minor-mode
+  "Minor mode for testing shadowing.")
+
+(ert-deftest help-tests-substitute-command-keys/test-mode ()
+  (with-substitute-command-keys-test
+   (with-temp-buffer
+     (help-tests-major-mode)
+     (test "\\{help-tests-major-mode-map}"
+           "\
+key             binding
+---             -------
+
+( .. )         short-range
+1 .. 4         foo-range
+a .. c         foo-other-range
+
+C-e            foo-something
+x              foo-original
+<F1>           foo-function-key1
+
+"))))
+
+(ert-deftest help-tests-substitute-command-keys/shadow ()
+  (with-substitute-command-keys-test
+   (with-temp-buffer
+     (help-tests-major-mode)
+     (help-tests-minor-mode)
+     (test "\\{help-tests-major-mode-map}"
+           "\
+key             binding
+---             -------
+
+( .. )         short-range
+1 .. 4         foo-range
+a .. c         foo-other-range
+
+C-e            foo-something
+  (this binding is currently shadowed)
+x              foo-original
+  (this binding is currently shadowed)
+<F1>           foo-function-key1
+
+"))))
+
+(ert-deftest help-tests-substitute-command-keys/command-remap ()
+  (with-substitute-command-keys-test
+   (let ((help-tests-major-mode-map (make-keymap))) ; Protect from changes.
+    (with-temp-buffer
+      (help-tests-major-mode)
+      (define-key help-tests-major-mode-map [remap foo] 'bar)
+      (test "\\{help-tests-major-mode-map}"
+            "\
+key             binding
+---             -------
+
+<remap>                Prefix Command
+
+<remap> <foo>  bar
+
+")))))
+
+(ert-deftest help-tests-describe-map-tree/no-menu-t ()
+  (with-temp-buffer
+    (let ((standard-output (current-buffer))
+          (map '(keymap . ((1 . foo)
+                           (menu-bar keymap
+                                     (foo menu-item "Foo" foo
+                                          :enable mark-active
+                                          :help "Help text"))))))
+      (describe-map-tree map nil nil nil nil t nil nil nil)
+      (should (equal (buffer-string) "key             binding
+---             -------
+
+C-a            foo
+
+")))))
+
+(ert-deftest help-tests-describe-map-tree/no-menu-nil ()
+  (with-temp-buffer
+    (let ((standard-output (current-buffer))
+          (map '(keymap . ((1 . foo)
+                           (menu-bar keymap
+                                     (foo menu-item "Foo" foo
+                                          :enable mark-active
+                                          :help "Help text"))))))
+      (describe-map-tree map nil nil nil nil nil nil nil nil)
+      (should (equal (buffer-string) "key             binding
+---             -------
+
+C-a            foo
+<menu-bar>     Prefix Command
+
+<menu-bar> <foo>               foo
+
+")))))
+
+(ert-deftest help-tests-describe-map-tree/mention-shadow-t ()
+  (with-temp-buffer
+    (let ((standard-output (current-buffer))
+          (map '(keymap . ((1 . foo)
+                           (2 . bar))))
+          (shadow-maps '((keymap . ((1 . baz))))))
+      (describe-map-tree map t shadow-maps nil nil t nil nil t)
+      (should (equal (buffer-string) "key             binding
+---             -------
+
+C-a            foo
+  (this binding is currently shadowed)
+C-b            bar
+
+")))))
+
+(ert-deftest help-tests-describe-map-tree/mention-shadow-nil ()
+  (with-temp-buffer
+    (let ((standard-output (current-buffer))
+          (map '(keymap . ((1 . foo)
+                           (2 . bar))))
+          (shadow-maps '((keymap . ((1 . baz))))))
+      (describe-map-tree map t shadow-maps nil nil t nil nil nil)
+      (should (equal (buffer-string) "key             binding
+---             -------
+
+C-b            bar
+
+")))))
+
+(ert-deftest help-tests-describe-map-tree/partial-t ()
+  (with-temp-buffer
+    (let ((standard-output (current-buffer))
+          (map '(keymap . ((1 . foo)
+                           (2 . undefined)))))
+      (describe-map-tree map t nil nil nil nil nil nil nil)
+      (should (equal (buffer-string) "key             binding
+---             -------
+
+C-a            foo
+
+")))))
+
+(ert-deftest help-tests-describe-map-tree/partial-nil ()
+  (with-temp-buffer
+    (let ((standard-output (current-buffer))
+          (map '(keymap . ((1 . foo)
+                           (2 . undefined)))))
+      (describe-map-tree map nil nil nil nil nil nil nil nil)
+      (should (equal (buffer-string) "key             binding
+---             -------
+
+C-a            foo
+C-b            undefined
+
+")))))
+
 (provide 'help-tests)
 
 ;;; help-tests.el ends here
diff --git a/test/lisp/hfy-cmap-resources/rgb.txt 
b/test/lisp/hfy-cmap-resources/rgb.txt
new file mode 100644
index 0000000..86a0053
--- /dev/null
+++ b/test/lisp/hfy-cmap-resources/rgb.txt
@@ -0,0 +1,3 @@
+255 250 250            snow
+248 248 255            ghost white
+248 248 255            GhostWhite
diff --git a/test/lisp/hfy-cmap-tests.el b/test/lisp/hfy-cmap-tests.el
new file mode 100644
index 0000000..4cdc6ff
--- /dev/null
+++ b/test/lisp/hfy-cmap-tests.el
@@ -0,0 +1,55 @@
+;;; hfy-cmap-tests.el --- tests for hfy-cmap.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020 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 'ert-x)
+(require 'hfy-cmap)
+
+(defconst hfy-cmap-tests--data
+  (concat "255 250 250         snow\n"
+          "248 248 255         ghost white\n"
+          "248 248 255         GhostWhite\n"))
+
+(defconst hfy-cmap-tests--parsed
+  '(("GhostWhite" 248 248 255)
+    ("ghost white" 248 248 255)
+    ("snow" 255 250 250)))
+
+(ert-deftest test-hfy-cmap--parse-buffer ()
+  (with-temp-buffer
+    (insert hfy-cmap-tests--data)
+    (should (equal (hfy-cmap--parse-buffer (current-buffer))
+                   hfy-cmap-tests--parsed))))
+
+(ert-deftest test-htmlfontify-load-rgb-file ()
+  :tags '(:expensive-test)
+  (let (hfy-rgb-txt-color-map)
+    (htmlfontify-load-rgb-file (ert-resource-file "rgb.txt"))
+    (should (equal hfy-rgb-txt-color-map
+                   hfy-cmap-tests--parsed))))
+
+(ert-deftest test-htmlfontify-load-rgb-file/non-existent-file ()
+  (let (hfy-rgb-txt-color-map)
+    (htmlfontify-load-rgb-file "/non/existent/file")
+    (should-not hfy-rgb-txt-color-map)))
+
+(provide 'hfy-cmap-tests)
+;;; hfy-cmap-tests.el ends here
diff --git a/test/lisp/mail/rfc822-tests.el b/test/lisp/mail/rfc822-tests.el
new file mode 100644
index 0000000..d13966c
--- /dev/null
+++ b/test/lisp/mail/rfc822-tests.el
@@ -0,0 +1,83 @@
+;;; rfc822-tests.el --- Tests for rfc822.el  -*- lexical-binding:t -*-
+
+;; Copyright (C) 2020 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 'rfc822)
+
+(defmacro rfc822-tests-deftest (email desc &optional valid)
+  `(ert-deftest ,(intern (format "rfc822-email-%s-%s"
+                                 (if valid "valid" "invalid")
+                                 desc)) ()
+     (if ,valid
+         (should (equal (rfc822-addresses ,email) (list ,email)))
+       (let ((addresses (rfc822-addresses ,email)))
+         ;; `rfc822-addresses' returns a string if parsing fails.
+         (while (and (consp addresses)
+                     (not (eq (string-to-char (car addresses)) ?\()))
+           (setq addresses (cdr addresses)))
+         ;; Found saved error.
+         (should (= (length addresses) 1))))))
+
+;;;; Valid emails
+
+(rfc822-tests-deftest "email@example.org" "email" t)
+(rfc822-tests-deftest "firstname.lastname@example.org" "dot-in-address" t)
+(rfc822-tests-deftest "email@subdomain.example.org" "dot-in-subdomain" t)
+(rfc822-tests-deftest "firstname+lastname@example.org" "contains-plus-sign" t)
+(rfc822-tests-deftest "email@123.123.123.123" "domain-valid-ip" t)
+(rfc822-tests-deftest "email@[123.123.123.123]" 
"domain-valid-ip-square-bracket" t)
+(rfc822-tests-deftest "\"email\"@example.org" "quotes-around-email" t)
+(rfc822-tests-deftest "1234567890@example.org" "digits-in-address" t)
+(rfc822-tests-deftest "email@example-one.com" "dash-in-domain-name" t)
+(rfc822-tests-deftest "_______@example.org" "underscore-in-address" t)
+(rfc822-tests-deftest "email@example.name" "dotname-tld" t)
+(rfc822-tests-deftest "email@example.co.jp" "dot-in-tld" t)
+(rfc822-tests-deftest "firstname-lastname@example.org" "dash-in-address" t)
+(rfc822-tests-deftest 
"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghiklm@example.org" 
"address-long" t)
+
+;;;; Invalid emails
+
+(rfc822-tests-deftest "#@%^%#$@#$@#.com" "garbage")
+(rfc822-tests-deftest "@example.org" "missing-username")
+(rfc822-tests-deftest "email@example@example.org" "two-at-signs")
+(rfc822-tests-deftest ".email@example.org" "address-leading-dot")
+(rfc822-tests-deftest "email.@example.org" "address-trailing-dot")
+(rfc822-tests-deftest "email..email@example.org" "address-multiple-dots")
+(rfc822-tests-deftest "email@example..org" "domain-multiple-dots")
+(rfc822-tests-deftest "email@example.org." "domain-trailing-dot")
+(rfc822-tests-deftest "email@.example.org" "domain-leading-dot")
+(rfc822-tests-deftest "test\\@test@example.org" "address-escaped-at-sign")
+
+;; FIXME: Should these fail?
+;; (rfc822-tests-deftest "plainaddress" "missing-at-sign-and-domain")
+;; (rfc822-tests-deftest "email@example.org (J. Random Hacker)" 
"text-following-email")
+;; (rfc822-tests-deftest "email@-example.org" 
"leading-dash-in-domain-is-invalid")
+;; (rfc822-tests-deftest "email@example-.org" 
"trailing-dash-in-domain-is-invalid")
+;; (rfc822-tests-deftest "あいうえお@example.org" "address-unicode-chars")
+;; (rfc822-tests-deftest "email.example.org" "missing-at")
+;; (rfc822-tests-deftest "email@111.222.333.44444" "invalid-IP-format")
+;; (rfc822-tests-deftest "email@domain" "missing-top-level-domain")
+;; (rfc822-tests-deftest "email@domain.web" 
".web-is-not-a-valid-top-level-domain")
+
+(provide 'rfc822-tests)
+;;; rfc822-tests.el ends here
diff --git a/test/data/mailcap/mime.types 
b/test/lisp/net/mailcap-resources/mime.types
similarity index 100%
rename from test/data/mailcap/mime.types
rename to test/lisp/net/mailcap-resources/mime.types
diff --git a/test/lisp/net/mailcap-tests.el b/test/lisp/net/mailcap-tests.el
index 8354d8e..0ebbec6 100644
--- a/test/lisp/net/mailcap-tests.el
+++ b/test/lisp/net/mailcap-tests.el
@@ -24,13 +24,10 @@
 ;;; Code:
 
 (require 'ert)
+(require 'ert-x)
 (require 'mailcap)
 
-(defconst mailcap-tests-data-dir
-  (expand-file-name "test/data/mailcap" source-directory))
-
-(defconst mailcap-tests-path
-  (expand-file-name "mime.types" mailcap-tests-data-dir)
+(defconst mailcap-tests-path (ert-resource-file "mime.types")
   "String used as PATH argument of `mailcap-parse-mimetypes'.")
 
 (defconst mailcap-tests-mime-extensions (copy-alist mailcap-mime-extensions))
diff --git a/test/lisp/progmodes/compile-tests.el 
b/test/lisp/progmodes/compile-tests.el
index 45eebac..b8ed6e0 100644
--- a/test/lisp/progmodes/compile-tests.el
+++ b/test/lisp/progmodes/compile-tests.el
@@ -35,319 +35,358 @@
   ;; what's reported in the string.  The end column numbers are for
   ;; the character after, so it matches what's reported in the string.
   '(;; absoft
-    ("Error on line 3 of t.f: Execution error unclassifiable statement"
+    (absoft
+     "Error on line 3 of t.f: Execution error unclassifiable statement"
      1 nil 3 "t.f")
-    ("Line 45 of \"foo.c\": bloofle undefined"
+    (absoft "Line 45 of \"foo.c\": bloofle undefined"
      1 nil 45 "foo.c")
-    ("error on line 19 of fplot.f: spelling error?"
+    (absoft "error on line 19 of fplot.f: spelling error?"
      1 nil 19 "fplot.f")
-    ("warning on line 17 of fplot.f: data type is undefined for variable d"
+    (absoft
+     "warning on line 17 of fplot.f: data type is undefined for variable d"
      1 nil 17 "fplot.f")
     ;; Ada & Mpatrol
-    ("foo.adb:61:11:  [...] in call to size declared at foo.ads:11"
+    (gnu "foo.adb:61:11:  [...] in call to size declared at foo.ads:11"
      1 11 61 "foo.adb")
-    ("foo.adb:61:11:  [...] in call to size declared at foo.ads:11"
+    (ada "foo.adb:61:11:  [...] in call to size declared at foo.ads:11"
      52 nil 11 "foo.ads")
-    ("     0x8008621 main+16 at error.c:17"
+    (ada "     0x8008621 main+16 at error.c:17"
      23 nil 17 "error.c")
     ;; aix
-    ("****** Error number 140 in line 8 of file errors.c ******"
+    (aix "****** Error number 140 in line 8 of file errors.c ******"
      25 nil 8 "errors.c")
     ;; ant
-    ("[javac] /src/DataBaseTestCase.java:27: unreported exception ..."
+    (ant "[javac] /src/DataBaseTestCase.java:27: unreported exception ..."
      13 nil 27 "/src/DataBaseTestCase.java" 2)
-    ("[javac] /src/DataBaseTestCase.java:49: warning: finally clause cannot 
complete normally"
+    (ant "[javac] /src/DataBaseTestCase.java:49: warning: finally clause 
cannot complete normally"
      13 nil 49 "/src/DataBaseTestCase.java" 1)
-    ("[jikes]  foo.java:3:5:7:9: blah blah"
+    (ant "[jikes]  foo.java:3:5:7:9: blah blah"
      14 (5 . 10) (3 . 7) "foo.java" 2)
-    ("[javac] c:/cygwin/Test.java:12: error: foo: bar"
+    (ant "[javac] c:/cygwin/Test.java:12: error: foo: bar"
      9 nil 12 "c:/cygwin/Test.java" 2)
-    ("[javac] c:\\cygwin\\Test.java:87: error: foo: bar"
+    (ant "[javac] c:\\cygwin\\Test.java:87: error: foo: bar"
      9 nil 87 "c:\\cygwin\\Test.java" 2)
     ;; Checkstyle error, but ant reports a warning (note additional
     ;; severity level after task name)
-    ("[checkstyle] [ERROR] /src/Test.java:38: warning: foo"
+    (ant "[checkstyle] [ERROR] /src/Test.java:38: warning: foo"
      22 nil 38 "/src/Test.java" 1)
     ;; bash
-    ("a.sh: line 1: ls-l: command not found"
+    (bash "a.sh: line 1: ls-l: command not found"
      1 nil 1 "a.sh")
     ;; borland
-    ("Error ping.c 15: Unable to open include file 'sys/types.h'"
+    (borland "Error ping.c 15: Unable to open include file 'sys/types.h'"
      1 nil 15 "ping.c")
-    ("Warning pong.c 68: Call to function 'func' with no prototype"
+    (borland "Warning pong.c 68: Call to function 'func' with no prototype"
      1 nil 68 "pong.c")
-    ("Error E2010 ping.c 15: Unable to open include file 'sys/types.h'"
+    (borland "Error E2010 ping.c 15: Unable to open include file 'sys/types.h'"
      1 nil 15 "ping.c")
-    ("Warning W1022 pong.c 68: Call to function 'func' with no prototype"
+    (borland
+     "Warning W1022 pong.c 68: Call to function 'func' with no prototype"
      1 nil 68 "pong.c")
     ;; caml
-    ("File \"foobar.ml\", lines 5-8, characters 20-155: blah blah"
+    (python-tracebacks-and-caml
+     "File \"foobar.ml\", lines 5-8, characters 20-155: blah blah"
      1 (20 . 156) (5 . 8) "foobar.ml")
-    ("File \"F:\\ocaml\\sorting.ml\", line 65, characters 2-145:\nWarning 26: 
unused variable equ."
+    (python-tracebacks-and-caml
+     "File \"F:\\ocaml\\sorting.ml\", line 65, characters 2-145:\nWarning 26: 
unused variable equ."
      1 (2 . 146) 65 "F:\\ocaml\\sorting.ml")
-    ("File \"/usr/share/gdesklets/display/TargetGauge.py\", line 41, in 
add_children"
+    (python-tracebacks-and-caml
+     "File \"/usr/share/gdesklets/display/TargetGauge.py\", line 41, in 
add_children"
      1 nil 41 "/usr/share/gdesklets/display/TargetGauge.py")
-    ("File \\lib\\python\\Products\\PythonScripts\\PythonScript.py, line 302, 
in _exec"
+    (python-tracebacks-and-caml
+     "File \\lib\\python\\Products\\PythonScripts\\PythonScript.py, line 302, 
in _exec"
      1 nil 302 "\\lib\\python\\Products\\PythonScripts\\PythonScript.py")
-    ("File \"/tmp/foo.py\", line 10"
+    (python-tracebacks-and-caml
+     "File \"/tmp/foo.py\", line 10"
      1 nil 10 "/tmp/foo.py")
     ;; clang-include
-    ("In file included from foo.cpp:2:"
+    (clang-include "In file included from foo.cpp:2:"
      1 nil 2 "foo.cpp" 0)
     ;; cmake cmake-info
-    ("CMake Error at CMakeLists.txt:23 (hurz):"
+    (cmake "CMake Error at CMakeLists.txt:23 (hurz):"
      1 nil 23 "CMakeLists.txt")
-    ("CMake Warning at cmake/modules/UseUG.cmake:73 (find_package):"
+    (cmake "CMake Warning at cmake/modules/UseUG.cmake:73 (find_package):"
      1 nil 73 "cmake/modules/UseUG.cmake")
-    ("  cmake/modules/DuneGridMacros.cmake:19 (include)"
+    (cmake-info "  cmake/modules/DuneGridMacros.cmake:19 (include)"
      1 nil 19 "cmake/modules/DuneGridMacros.cmake")
     ;; comma
-    ("\"foo.f\", line 3: Error: syntax error near end of statement"
+    (comma "\"foo.f\", line 3: Error: syntax error near end of statement"
      1 nil 3 "foo.f")
-    ("\"vvouch.c\", line 19.5: 1506-046 (S) Syntax error."
+    (comma "\"vvouch.c\", line 19.5: 1506-046 (S) Syntax error."
      1 5 19 "vvouch.c")
-    ("\"foo.c\", line 32 pos 1; (E) syntax error; unexpected symbol: 
\"lossage\""
+    (comma "\"foo.c\", line 32 pos 1; (E) syntax error; unexpected symbol: 
\"lossage\""
      1 1 32 "foo.c")
-    ("\"foo.adb\", line 2(11): warning: file name does not match ..."
+    (comma "\"foo.adb\", line 2(11): warning: file name does not match ..."
      1 11 2 "foo.adb")
-    ("\"src/swapping.c\", line 30.34: 1506-342 (W) \"/*\" detected in comment."
+    (comma
+     "\"src/swapping.c\", line 30.34: 1506-342 (W) \"/*\" detected in comment."
      1 34 30 "src/swapping.c")
     ;; cucumber
-    ("Scenario: undefined step  # features/cucumber.feature:3"
+    (cucumber "Scenario: undefined step  # features/cucumber.feature:3"
      29 nil 3 "features/cucumber.feature")
-    ("      /home/gusev/.rvm/foo/bar.rb:500:in `_wrap_assertion'"
+    (gnu "      /home/gusev/.rvm/foo/bar.rb:500:in `_wrap_assertion'"
      1 nil 500 "/home/gusev/.rvm/foo/bar.rb")
     ;; edg-1 edg-2
-    ("build/intel/debug/../../../struct.cpp(42): error: identifier \"foo\" is 
undefined"
+    (edg-1 "build/intel/debug/../../../struct.cpp(42): error: identifier 
\"foo\" is undefined"
      1 nil 42 "build/intel/debug/../../../struct.cpp")
-    ("build/intel/debug/struct.cpp(44): warning #1011: missing return 
statement at end of"
+    (edg-1 "build/intel/debug/struct.cpp(44): warning #1011: missing return 
statement at end of"
      1 nil 44 "build/intel/debug/struct.cpp")
-    ("build/intel/debug/iptr.h(302): remark #981: operands are evaluated in 
unspecified order"
+    (edg-1 "build/intel/debug/iptr.h(302): remark #981: operands are evaluated 
in unspecified order"
      1 nil 302 "build/intel/debug/iptr.h")
-    ("   detected during ... at line 62 of 
\"build/intel/debug/../../../trace.h\""
+    (edg-2 "   detected during ... at line 62 of 
\"build/intel/debug/../../../trace.h\""
      31 nil 62 "build/intel/debug/../../../trace.h")
     ;; epc
-    ("Error 24 at (2:progran.f90) : syntax error"
+    (epc "Error 24 at (2:progran.f90) : syntax error"
      1 nil 2 "progran.f90")
     ;; ftnchek
-    ("    Dummy arg W in module SUBA line 8 file arrayclash.f is array"
+    (ftnchek "    Dummy arg W in module SUBA line 8 file arrayclash.f is array"
      32 nil 8 "arrayclash.f")
-    ("    L4 used at line 55 file test/assign.f; never set"
+    (ftnchek "    L4 used at line 55 file test/assign.f; never set"
      16 nil 55 "test/assign.f")
-    ("Warning near line 10 file arrayclash.f: Module contains no executable"
+    (ftnchek
+     "Warning near line 10 file arrayclash.f: Module contains no executable"
      1 nil 10 "arrayclash.f")
-    ("Nonportable usage near line 31 col 9 file assign.f: mixed default and 
explicit"
+    (ftnchek "Nonportable usage near line 31 col 9 file assign.f: mixed 
default and explicit"
      24 9 31 "assign.f")
     ;; iar
-    ("\"foo.c\",3  Error[32]: Error message"
+    (iar "\"foo.c\",3  Error[32]: Error message"
      1 nil 3 "foo.c")
-    ("\"foo.c\",3  Warning[32]: Error message"
+    (iar "\"foo.c\",3  Warning[32]: Error message"
      1 nil 3 "foo.c")
     ;; ibm
-    ("foo.c(2:0) : informational EDC0804: Function foo is not referenced."
+    (ibm "foo.c(2:0) : informational EDC0804: Function foo is not referenced."
      1 0 2 "foo.c")
-    ("foo.c(3:8) : warning EDC0833: Implicit return statement encountered."
+    (ibm "foo.c(3:8) : warning EDC0833: Implicit return statement encountered."
      1 8 3 "foo.c")
-    ("foo.c(5:5) : error EDC0350: Syntax error."
+    (ibm "foo.c(5:5) : error EDC0350: Syntax error."
      1 5 5 "foo.c")
     ;; irix
-    ("ccom: Error: foo.c, line 2: syntax error"
+    (irix "ccom: Error: foo.c, line 2: syntax error"
      1 nil 2 "foo.c")
-    ("cc: Severe: /src/Python-2.3.3/Modules/_curses_panel.c, line 17: Cannot 
find file <panel.h> ..."
+    (irix "cc: Severe: /src/Python-2.3.3/Modules/_curses_panel.c, line 17: 
Cannot find file <panel.h> ..."
      1 nil 17 "/src/Python-2.3.3/Modules/_curses_panel.c")
-    ("cc: Info: foo.c, line 27: ..."
+    (irix "cc: Info: foo.c, line 27: ..."
      1 nil 27 "foo.c")
-    ("cfe: Warning 712: foo.c, line 2: illegal combination of pointer and ..."
+    (irix
+     "cfe: Warning 712: foo.c, line 2: illegal combination of pointer and ..."
      1 nil 2 "foo.c")
-    ("cfe: Warning 600: xfe.c: 170: Not in a conditional directive while ..."
+    (irix
+     "cfe: Warning 600: xfe.c: 170: Not in a conditional directive while ..."
      1 nil 170 "xfe.c")
-    ("/usr/lib/cmplrs/cc/cfe: Error: foo.c: 1: blah blah"
+    (irix "/usr/lib/cmplrs/cc/cfe: Error: foo.c: 1: blah blah"
      1 nil 1 "foo.c")
-    ("/usr/lib/cmplrs/cc/cfe: warning: foo.c: 1: blah blah"
+    (irix "/usr/lib/cmplrs/cc/cfe: warning: foo.c: 1: blah blah"
      1 nil 1 "foo.c")
-    ("foo bar: baz.f, line 27: ..."
+    (irix "foo bar: baz.f, line 27: ..."
      1 nil 27 "baz.f")
     ;; java
-    ("\tat org.foo.ComponentGateway.doGet(ComponentGateway.java:172)"
+    (java "\tat org.foo.ComponentGateway.doGet(ComponentGateway.java:172)"
      5 nil 172 "ComponentGateway.java")
-    ("\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:740)"
+    (java "\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:740)"
      5 nil 740 "HttpServlet.java")
-    ("==1332==    at 0x4040743C: System::getErrorString() 
(../src/Lib/System.cpp:217)"
+    (java "==1332==    at 0x4040743C: System::getErrorString() 
(../src/Lib/System.cpp:217)"
      13 nil 217 "../src/Lib/System.cpp")
-    ("==1332==    by 0x8008621: main (vtest.c:180)"
+    (java "==1332==    by 0x8008621: main (vtest.c:180)"
      13 nil 180 "vtest.c")
     ;; javac
-    ("/src/Test.java:5: ';' expected\n        foo foo\n               ^\n" 1 
15 5 "/src/Test.java" 2)
-    ("e:\\src\\Test.java:7: warning: ';' expected\n   foo foo\n          ^\n" 
1 10 7 "e:\\src\\Test.java" 1)
+    (javac
+     "/src/Test.java:5: ';' expected\n        foo foo\n               ^\n"
+     1 15 5 "/src/Test.java" 2)
+    (javac
+     "e:\\src\\Test.java:7: warning: ';' expected\n   foo foo\n          ^\n"
+     1 10 7 "e:\\src\\Test.java" 1)
     ;; jikes-file jikes-line
-    ("Found 2 semantic errors compiling \"../javax/swing/BorderFactory.java\":"
+    (jikes-file
+     "Found 2 semantic errors compiling \"../javax/swing/BorderFactory.java\":"
      1 nil nil "../javax/swing/BorderFactory.java")
-    ("Issued 1 semantic warning compiling \"java/awt/Toolkit.java\":"
+    (jikes-file "Issued 1 semantic warning compiling 
\"java/awt/Toolkit.java\":"
      1 nil nil "java/awt/Toolkit.java")
     ;; gcc-include
-    ("In file included from /usr/include/c++/3.3/backward/warn.h:4,"
+    (gcc-include "In file included from 
/usr/include/c++/3.3/backward/warn.h:4,"
      1 nil 4 "/usr/include/c++/3.3/backward/warn.h")
-    ("                 from /usr/include/c++/3.3/backward/iostream.h:31:0,"
+    (gcc-include
+     "                 from /usr/include/c++/3.3/backward/iostream.h:31:0,"
      1 0 31 "/usr/include/c++/3.3/backward/iostream.h")
-    ("                 from test_clt.cc:1:"
+    (gcc-include "                 from test_clt.cc:1:"
      1 nil 1 "test_clt.cc")
     ;; gmake
-    ("make: *** [Makefile:20: all] Error 2" 12 nil 20 "Makefile" 0)
-    ("make[4]: *** [sub/make.mk:19: all] Error 127" 15 nil 19 "sub/make.mk" 0)
-    ("gmake[4]: *** [sub/make.mk:19: all] Error 2" 16 nil 19 "sub/make.mk" 0)
-    ("gmake-4.3[4]: *** [make.mk:1119: all] Error 2" 20 nil 1119 "make.mk" 0)
-    ("Make-4.3: *** [make.INC:1119: dir/all] Error 2" 16 nil 1119 "make.INC" 0)
+    (gmake "make: *** [Makefile:20: all] Error 2" 12 nil 20 "Makefile" 0)
+    (gmake "make[4]: *** [sub/make.mk:19: all] Error 127" 15 nil 19
+           "sub/make.mk" 0)
+    (gmake "gmake[4]: *** [sub/make.mk:19: all] Error 2" 16 nil 19
+           "sub/make.mk" 0)
+    (gmake "gmake-4.3[4]: *** [make.mk:1119: all] Error 2" 20 nil 1119
+           "make.mk" 0)
+    (gmake "Make-4.3: *** [make.INC:1119: dir/all] Error 2" 16 nil 1119
+           "make.INC" 0)
     ;; gnu
-    ("foo.c:8: message" 1 nil 8 "foo.c")
-    ("../foo.c:8: W: message" 1 nil 8 "../foo.c")
-    ("/tmp/foo.c:8:warning message" 1 nil 8 "/tmp/foo.c")
-    ("foo/bar.py:8: FutureWarning message" 1 nil 8 "foo/bar.py")
-    ("foo.py:8: RuntimeWarning message" 1 nil 8 "foo.py")
-    ("foo.c:8:I: message" 1 nil 8 "foo.c")
-    ("foo.c:8.23: note: message" 1 23 8 "foo.c")
-    ("foo.c:8.23: info: message" 1 23 8 "foo.c")
-    ("foo.c:8:23:information: message" 1 23 8 "foo.c")
-    ("foo.c:8.23-45: Informational: message" 1 (23 . 46) (8 . nil) "foo.c")
-    ("foo.c:8-23: message" 1 nil (8 . 23) "foo.c")
+    (gnu "foo.c:8: message" 1 nil 8 "foo.c")
+    (gnu "../foo.c:8: W: message" 1 nil 8 "../foo.c")
+    (gnu "/tmp/foo.c:8:warning message" 1 nil 8 "/tmp/foo.c")
+    (gnu "foo/bar.py:8: FutureWarning message" 1 nil 8 "foo/bar.py")
+    (gnu "foo.py:8: RuntimeWarning message" 1 nil 8 "foo.py")
+    (gnu "foo.c:8:I: message" 1 nil 8 "foo.c")
+    (gnu "foo.c:8.23: note: message" 1 23 8 "foo.c")
+    (gnu "foo.c:8.23: info: message" 1 23 8 "foo.c")
+    (gnu "foo.c:8:23:information: message" 1 23 8 "foo.c")
+    (gnu "foo.c:8.23-45: Informational: message" 1 (23 . 46) (8 . nil) "foo.c")
+    (gnu "foo.c:8-23: message" 1 nil (8 . 23) "foo.c")
     ;; The next one is not in the GNU standards AFAICS.
     ;; Here we seem to interpret it as LINE1-LINE2.COL2.
-    ("foo.c:8-45.3: message" 1 (nil . 4) (8 . 45) "foo.c")
-    ("foo.c:8.23-9.1: message" 1 (23 . 2) (8 . 9) "foo.c")
-    ("jade:dbcommon.dsl:133:17:E: missing argument for function call"
+    (gnu "foo.c:8-45.3: message" 1 (nil . 4) (8 . 45) "foo.c")
+    (gnu "foo.c:8.23-9.1: message" 1 (23 . 2) (8 . 9) "foo.c")
+    (gnu "jade:dbcommon.dsl:133:17:E: missing argument for function call"
      1 17 133 "dbcommon.dsl")
-    ("G:/cygwin/dev/build-myproj.xml:54: Compiler Adapter 'javac' can't be 
found."
+    (gnu "G:/cygwin/dev/build-myproj.xml:54: Compiler Adapter 'javac' can't be 
found."
      1 nil 54 "G:/cygwin/dev/build-myproj.xml")
-    ("file:G:/cygwin/dev/build-myproj.xml:54: Compiler Adapter 'javac' can't 
be found."
+    (gnu "file:G:/cygwin/dev/build-myproj.xml:54: Compiler Adapter 'javac' 
can't be found."
      1 nil 54 "G:/cygwin/dev/build-myproj.xml")
-    ("{standard input}:27041: Warning: end of file not at end of a line; 
newline inserted"
+    (gnu "{standard input}:27041: Warning: end of file not at end of a line; 
newline inserted"
      1 nil 27041 "{standard input}")
-    ("boost/container/detail/flat_tree.hpp:589:25:   [ skipping 5 
instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]"
+    (gnu "boost/container/detail/flat_tree.hpp:589:25:   [ skipping 5 
instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]"
      1 25 589 "boost/container/detail/flat_tree.hpp" 0)
     ;; gradle-kotlin
-    ("e: /src/Test.kt: (34, 15): foo: bar" 4 15 34 "/src/Test.kt" 2)
-    ("w: /src/Test.kt: (11, 98): foo: bar" 4 98 11 "/src/Test.kt" 1)
-    ("e: e:/cygwin/src/Test.kt: (34, 15): foo: bar" 4 15 34 
"e:/cygwin/src/Test.kt" 2)
-    ("w: e:/cygwin/src/Test.kt: (11, 98): foo: bar" 4 98 11 
"e:/cygwin/src/Test.kt" 1)
-    ("e: e:\\src\\Test.kt: (34, 15): foo: bar" 4 15 34 "e:\\src\\Test.kt" 2)
-    ("w: e:\\src\\Test.kt: (11, 98): foo: bar" 4 98 11 "e:\\src\\Test.kt" 1)
+    (gradle-kotlin
+     "e: /src/Test.kt: (34, 15): foo: bar" 4 15 34 "/src/Test.kt" 2)
+    (gradle-kotlin
+     "w: /src/Test.kt: (11, 98): foo: bar" 4 98 11 "/src/Test.kt" 1)
+    (gradle-kotlin
+     "e: e:/cygwin/src/Test.kt: (34, 15): foo: bar"
+     4 15 34 "e:/cygwin/src/Test.kt" 2)
+    (gradle-kotlin
+     "w: e:/cygwin/src/Test.kt: (11, 98): foo: bar"
+     4 98 11 "e:/cygwin/src/Test.kt" 1)
+    (gradle-kotlin
+     "e: e:\\src\\Test.kt: (34, 15): foo: bar" 4 15 34 "e:\\src\\Test.kt" 2)
+    (gradle-kotlin
+     "w: e:\\src\\Test.kt: (11, 98): foo: bar" 4 98 11 "e:\\src\\Test.kt" 1)
     ;; Guile
-    ("In foo.scm:\n" 1 nil nil "foo.scm")
-    ("  63:4 [call-with-prompt prompt0 ...]" 1 4 63 nil)
-    ("1038: 1 [main (\"gud-break.scm\")]" 1 1 1038 nil)
+    (guile-file "In foo.scm:\n" 1 nil nil "foo.scm")
+    (guile-line "  63:4 [call-with-prompt prompt0 ...]" 1 4 63 nil)
+    (guile-line "1038: 1 [main (\"gud-break.scm\")]" 1 1 1038 nil)
     ;; lcc
-    ("E, file.cc(35,52) Illegal operation on pointers" 1 52 35 "file.cc")
-    ("W, file.cc(36,52) blah blah" 1 52 36 "file.cc")
+    (lcc "E, file.cc(35,52) Illegal operation on pointers" 1 52 35 "file.cc")
+    (lcc "W, file.cc(36,52) blah blah" 1 52 36 "file.cc")
     ;; makepp
-    ("makepp: Scanning `/foo/bar.c'" 19 nil nil "/foo/bar.c")
-    ("makepp: warning: bla bla `/foo/bar.c' and `/foo/bar.h'" 27 nil nil 
"/foo/bar.c")
-    ("makepp: bla bla `/foo/Makeppfile:12' bla" 18 nil 12 "/foo/Makeppfile")
-    ("makepp: bla bla `/foo/bar.c' and `/foo/bar.h'" 35 nil nil "/foo/bar.h")
+    (makepp "makepp: Scanning `/foo/bar.c'" 19 nil nil "/foo/bar.c")
+    (makepp "makepp: warning: bla bla `/foo/bar.c' and `/foo/bar.h'"
+            27 nil nil "/foo/bar.c")
+    (makepp "makepp: bla bla `/foo/Makeppfile:12' bla"
+            18 nil 12 "/foo/Makeppfile")
+    (nil "makepp: bla bla `/foo/bar.c' and `/foo/bar.h'"
+         35 nil nil "/foo/bar.h")
     ;; maven
-    ("FooBar.java:[111,53] no interface expected here"
+    (maven "FooBar.java:[111,53] no interface expected here"
      1 53 111 "FooBar.java" 2)
-    ("[ERROR] /Users/cinsk/hello.java:[651,96] ';' expected"
+    (maven "[ERROR] /Users/cinsk/hello.java:[651,96] ';' expected"
      15 96 651 "/Users/cinsk/hello.java" 2) ;Bug#11517.
-    ("[WARNING] /foo/bar/Test.java:[27,43] unchecked conversion"
+    (maven "[WARNING] /foo/bar/Test.java:[27,43] unchecked conversion"
      11 43 27 "/foo/bar/Test.java" 1) ;Bug#20556
     ;; mips-1 mips-2
-    ("TrimMask (255) in solomon.c may be indistinguishable from TrimMasks (93) 
in solomo.c due to truncation"
+    (mips-1 "TrimMask (255) in solomon.c may be indistinguishable from 
TrimMasks (93) in solomo.c due to truncation"
      11 nil 255 "solomon.c")
-    ("TrimMask (255) in solomon.c may be indistinguishable from TrimMasks (93) 
in solomo.c due to truncation"
+    (mips-1 "TrimMask (255) in solomon.c may be indistinguishable from 
TrimMasks (93) in solomo.c due to truncation"
      70 nil 93 "solomo.c")
-    ("name defined but never used: LinInt in cmap_calc.c(199)"
+    (mips-2 "name defined but never used: LinInt in cmap_calc.c(199)"
      40 nil 199 "cmap_calc.c")
     ;; msft
-    ("keyboard handler.c(537) : warning C4005: 'min' : macro redefinition"
+    (msft "keyboard handler.c(537) : warning C4005: 'min' : macro redefinition"
      1 nil 537 "keyboard handler.c")
-    ("d:\\tmp\\test.c(23) : error C2143: syntax error : missing ';' before 
'if'"
+    (msft
+     "d:\\tmp\\test.c(23) : error C2143: syntax error : missing ';' before 
'if'"
      1 nil 23 "d:\\tmp\\test.c")
-    ("d:\\tmp\\test.c(1145) : see declaration of 'nsRefPtr'"
+    (msft "d:\\tmp\\test.c(1145) : see declaration of 'nsRefPtr'"
      1 nil 1145 "d:\\tmp\\test.c")
-    ("1>test_main.cpp(29): error C2144: syntax error : 'int' should be 
preceded by ';'"
+    (msft "1>test_main.cpp(29): error C2144: syntax error : 'int' should be 
preceded by ';'"
      3 nil 29 "test_main.cpp")
-    ("1>test_main.cpp(29): error C4430: missing type specifier - int assumed. 
Note: C++ does not support default-int"
+    (msft "1>test_main.cpp(29): error C4430: missing type specifier - int 
assumed. Note: C++ does not support default-int"
      3 nil 29 "test_main.cpp")
-    ("C:\\tmp\\test.cpp(101,11): error C4101: 'bias0123': unreferenced local 
variable [C:\\tmp\\project.vcxproj]"
+    (msft "C:\\tmp\\test.cpp(101,11): error C4101: 'bias0123': unreferenced 
local variable [C:\\tmp\\project.vcxproj]"
      1 11 101 "C:\\tmp\\test.cpp")
     ;; watcom
-    ("..\\src\\ctrl\\lister.c(109): Error! E1009: Expecting ';' but found '{'"
+    (watcom
+     "..\\src\\ctrl\\lister.c(109): Error! E1009: Expecting ';' but found '{'"
      1 nil 109 "..\\src\\ctrl\\lister.c")
-    ("..\\src\\ctrl\\lister.c(120): Warning! W201: Unreachable code"
+    (watcom "..\\src\\ctrl\\lister.c(120): Warning! W201: Unreachable code"
      1 nil 120 "..\\src\\ctrl\\lister.c")
     ;; omake
-    ("      alpha.c:5:15: error: expected ';' after expression"
+    ;; FIXME: This doesn't actually test the omake rule.
+    (gnu "      alpha.c:5:15: error: expected ';' after expression"
      1 15 5 "alpha.c")
     ;; oracle
-    ("Semantic error at line 528, column 5, file erosacqdb.pc:"
+    (oracle "Semantic error at line 528, column 5, file erosacqdb.pc:"
      1 5 528 "erosacqdb.pc")
-    ("Error at line 41, column 10 in file /usr/src/sb/ODBI_BHP.hpp"
+    (oracle "Error at line 41, column 10 in file /usr/src/sb/ODBI_BHP.hpp"
      1 10 41 "/usr/src/sb/ODBI_BHP.hpp")
-    ("PCC-02150: error at line 49, column 27 in file /usr/src/sb/ODBI_dxfgh.pc"
+    (oracle
+     "PCC-02150: error at line 49, column 27 in file /usr/src/sb/ODBI_dxfgh.pc"
      1 27 49 "/usr/src/sb/ODBI_dxfgh.pc")
-    ("PCC-00003: invalid SQL Identifier at column name in line 12 of file 
/usr/src/sb/ODBI_BHP.hpp"
+    (oracle "PCC-00003: invalid SQL Identifier at column name in line 12 of 
file /usr/src/sb/ODBI_BHP.hpp"
      1 nil 12 "/usr/src/sb/ODBI_BHP.hpp")
-    ("PCC-00004: mismatched IF/ELSE/ENDIF block at line 27 in file 
/usr/src/sb/ODBI_BHP.hpp"
+    (oracle "PCC-00004: mismatched IF/ELSE/ENDIF block at line 27 in file 
/usr/src/sb/ODBI_BHP.hpp"
      1 nil 27 "/usr/src/sb/ODBI_BHP.hpp")
-    ("PCC-02151: line 21 column 40 file /usr/src/sb/ODBI_BHP.hpp:"
+    (oracle "PCC-02151: line 21 column 40 file /usr/src/sb/ODBI_BHP.hpp:"
      1 40 21 "/usr/src/sb/ODBI_BHP.hpp")
     ;; perl
-    ("syntax error at automake line 922, near \"':'\""
+    (perl "syntax error at automake line 922, near \"':'\""
      14 nil 922 "automake")
-    ("Died at test.pl line 27."
+    (perl "Died at test.pl line 27."
      6 nil 27 "test.pl")
-    ("store::odrecall('File_A', 'x2') called at store.pm line 90"
+    (perl "store::odrecall('File_A', 'x2') called at store.pm line 90"
      40 nil 90 "store.pm")
-    ("\t(in cleanup) something bad at foo.pl line 3 during global destruction."
+    (perl
+     "\t(in cleanup) something bad at foo.pl line 3 during global destruction."
      29 nil 3 "foo.pl")
-    ("GLib-GObject-WARNING **: 
/build/buildd/glib2.0-2.14.5/gobject/gsignal.c:1741: instance `0x8206790' has 
no handler with id `1234' at t-compilation-perl-gtk.pl line 3."
+    (perl "GLib-GObject-WARNING **: 
/build/buildd/glib2.0-2.14.5/gobject/gsignal.c:1741: instance `0x8206790' has 
no handler with id `1234' at t-compilation-perl-gtk.pl line 3."
      130 nil 3 "t-compilation-perl-gtk.pl")
     ;; php
-    ("Parse error: parse error, unexpected $ in main.php on line 59"
+    (php "Parse error: parse error, unexpected $ in main.php on line 59"
      1 nil 59 "main.php")
-    ("Fatal error: Call to undefined function: mysql_pconnect() in db.inc on 
line 66"
+    (php "Fatal error: Call to undefined function: mysql_pconnect() in db.inc 
on line 66"
      1 nil 66 "db.inc")
-    ;; ruby
-    ("plain-exception.rb:7:in `fun': unhandled exception"
+    ;; ruby (uses gnu)
+    (gnu "plain-exception.rb:7:in `fun': unhandled exception"
      1 nil 7 "plain-exception.rb")
-    ("\tfrom plain-exception.rb:3:in `proxy'" 2 nil 3 "plain-exception.rb")
-    ("\tfrom plain-exception.rb:12" 2 nil 12 "plain-exception.rb")
+    (gcc-include
+     "\tfrom plain-exception.rb:3:in `proxy'" 2 nil 3 "plain-exception.rb")
+    (gcc-include "\tfrom plain-exception.rb:12" 2 nil 12 "plain-exception.rb")
     ;; ruby-Test::Unit
     ;; FIXME
-    ("    [examples/test-unit.rb:28:in `here_is_a_deep_assert'"
+    (ruby-Test::Unit "    [examples/test-unit.rb:28:in `here_is_a_deep_assert'"
      5 nil 28 "examples/test-unit.rb")
-    ("     examples/test-unit.rb:19:in `test_a_deep_assert']:"
+    (ruby-Test::Unit "     examples/test-unit.rb:19:in `test_a_deep_assert']:"
      6 nil 19 "examples/test-unit.rb")
-    ("examples/test-unit.rb:10:in `test_assert_raise'"
+    (gnu "examples/test-unit.rb:10:in `test_assert_raise'"
      1 nil 10 "examples/test-unit.rb")
     ;; rxp
-    ("Error: Mismatched end tag: expected </geroup>, got </group>\nin unnamed 
entity at line 71 char 8 of file:///home/reto/test/group.xml"
+    (rxp "Error: Mismatched end tag: expected </geroup>, got </group>\nin 
unnamed entity at line 71 char 8 of file:///home/reto/test/group.xml"
      1 8 71 "/home/reto/test/group.xml")
-    ("Warning: Start tag for undeclared element geroup\nin unnamed entity at 
line 4 char 8 of file:///home/reto/test/group.xml"
+    (rxp "Warning: Start tag for undeclared element geroup\nin unnamed entity 
at line 4 char 8 of file:///home/reto/test/group.xml"
      1 8 4 "/home/reto/test/group.xml")
     ;; shellcheck
-    ("In autogen.sh line 48:"
+    (shellcheck "In autogen.sh line 48:"
      1 nil 48 "autogen.sh")
     ;; sparc-pascal-file sparc-pascal-line sparc-pascal-example
-    ("Thu May 14 10:46:12 1992  mom3.p:"
+    (sparc-pascal-file "Thu May 14 10:46:12 1992  mom3.p:"
      1 nil nil "mom3.p")
     ;; sun
-    ("cc-1020 CC: REMARK File = CUI_App.h, Line = 735"
+    (sun "cc-1020 CC: REMARK File = CUI_App.h, Line = 735"
      13 nil 735 "CUI_App.h")
-    ("cc-1070 cc: WARNING File = linkl.c, Line = 38"
+    (sun "cc-1070 cc: WARNING File = linkl.c, Line = 38"
      13 nil 38 "linkl.c")
-    ("cf90-113 f90comp: ERROR NSE, File = Hoved.f90, Line = 16, Column = 3"
+    (sun "cf90-113 f90comp: ERROR NSE, File = Hoved.f90, Line = 16, Column = 3"
      18 3 16 "Hoved.f90")
     ;; sun-ada
-    ("/home3/xdhar/rcds_rc/main.a, line 361, char 6:syntax error: \",\" 
inserted"
+    (sun-ada "/home3/xdhar/rcds_rc/main.a, line 361, char 6:syntax error: 
\",\" inserted"
      1 6 361 "/home3/xdhar/rcds_rc/main.a")
     ;; 4bsd
-    ("/usr/src/foo/foo.c(8): warning: w may be used before set"
+    (edg-1 "/usr/src/foo/foo.c(8): warning: w may be used before set"
      1 nil 8 "/usr/src/foo/foo.c")
-    ("/usr/src/foo/foo.c(9): error: w is used before set"
+    (edg-1 "/usr/src/foo/foo.c(9): error: w is used before set"
      1 nil 9 "/usr/src/foo/foo.c")
-    ("strcmp: variable # of args. llib-lc(359)  ::  /usr/src/foo/foo.c(8)"
+    (4bsd "strcmp: variable # of args. llib-lc(359)  ::  /usr/src/foo/foo.c(8)"
      44 nil 8 "/usr/src/foo/foo.c")
-    ("bloofle defined( /users/wolfgang/foo.c(4) ), but never used"
+    (4bsd "bloofle defined( /users/wolfgang/foo.c(4) ), but never used"
      18 nil 4 "/users/wolfgang/foo.c")
     ;; perl--Pod::Checker
     ;; FIXME
@@ -355,21 +394,21 @@
     ;; *** ERROR: =over on line 37 without closing =back at line EOF in file 
bar.pm
     ;; *** ERROR: =over on line 1 without closing =back (at head1) at line 3 
in file x.pod
     ;; perl--Test
-    ("# Failed test 1 in foo.t at line 6"
+    (perl--Test "# Failed test 1 in foo.t at line 6"
      1 nil 6 "foo.t")
     ;; perl--Test::Harness
-    ("NOK 1# Test 1 got: \"1234\" (t/foo.t at line 46)"
+    (perl--Test2 "NOK 1# Test 1 got: \"1234\" (t/foo.t at line 46)"
      1 nil 46 "t/foo.t")
     ;; weblint
-    ("index.html (13:1) Unknown element <fdjsk>"
+    (weblint "index.html (13:1) Unknown element <fdjsk>"
      1 1 13 "index.html"))
   "List of tests for `compilation-error-regexp-alist'.
-Each element has the form (STR POS COLUMN LINE FILENAME [TYPE]),
-where STR is an error string, POS is the position of the error in
-STR, COLUMN and LINE are the reported column and line numbers (or
-nil) for that error, FILENAME is the reported filename, and TYPE
-is 0 for an information message, 1 for a warning, and 2 for an
-error.
+Each element has the form (RULE STR POS COLUMN LINE FILENAME
+[TYPE]), where RULE is the rule (as a symbol), STR is an error
+string, POS is the position of the error in STR, COLUMN and LINE
+are the reported column and line numbers (or nil) for that error,
+FILENAME is the reported filename, and TYPE is 0 for an
+information message, 1 for a warning, and 2 for an error.
 
 LINE can also be of the form (LINE . END-LINE) meaning a range of
 lines.  COLUMN can also be of the form (COLUMN . END-COLUMN)
@@ -379,11 +418,14 @@ any message type is accepted.")
 
 (defconst compile-tests--grep-regexp-testcases
   ;; Bug#32051.
-  '(("c:/Users/my.name/src/project\\src\\kbhit.hpp\0\ 29:#include <termios.h>"
+  '((nil
+     "c:/Users/my.name/src/project\\src\\kbhit.hpp\0\ 29:#include <termios.h>"
      1 nil 29 "c:/Users/my.name/src/project\\src\\kbhit.hpp")
-    ("d:/gnu/emacs/branch/src/callproc.c\0\ 214:#ifdef DOS_NT"
+    (nil
+     "d:/gnu/emacs/branch/src/callproc.c\0\ 214:#ifdef DOS_NT"
      1 nil 214 "d:/gnu/emacs/branch/src/callproc.c")
-    ("/gnu/emacs/branch/src/callproc.c\0\ 214:#ifdef DOS_NT"
+    (nil
+     "/gnu/emacs/branch/src/callproc.c\0\ 214:#ifdef DOS_NT"
      1 nil 214 "/gnu/emacs/branch/src/callproc.c"))
   "List of tests for `grep-regexp-list'.
 The format is the same as `compile-tests--test-regexps-data', but
@@ -392,43 +434,51 @@ with colon.")
 
 (defconst compile-tests--grep-regexp-tricky-testcases
   ;; Bug#7378.
-  
'(("./x11-libs---nx/3.4.0:0:C.30253.1289557929.792611.C/nx-3.4.0.exheres-0\0\ 
42:some text"
+  '((nil
+     
"./x11-libs---nx/3.4.0:0:C.30253.1289557929.792611.C/nx-3.4.0.exheres-0\0\ 
42:some text"
      1 nil 42 
"./x11-libs---nx/3.4.0:0:C.30253.1289557929.792611.C/nx-3.4.0.exheres-0")
-    ("2011-08-31_11:57:03_1\0\ 7:Date: Wed, 31 Aug 2011 11:57:03 +0000"
+    (nil
+     "2011-08-31_11:57:03_1\0\ 7:Date: Wed, 31 Aug 2011 11:57:03 +0000"
      1 nil 7 "2011-08-31_11:57:03_1"))
   "List of tricky tests for `grep-regexp-list'.
 Same as `compile-tests--grep-regexp-testcases', but these cases
 can only work with the NUL byte to disambiguate colons.")
 
 (defun compile--test-error-line (test)
-  (erase-buffer)
-  (setq compilation-locs (make-hash-table))
-  (insert (car test))
-  (compilation-parse-errors (point-min) (point-max))
-  (let ((msg (get-text-property (nth 1 test) 'compilation-message)))
-    (should msg)
-    (let ((loc (compilation--message->loc msg))
-          (col  (nth 2 test))
-          (line (nth 3 test))
-          (file (nth 4 test))
-          (type (nth 5 test))
-          end-col end-line)
-      (if (consp col)
-          (setq end-col (cdr col) col (car col)))
-      (if (consp line)
-          (setq end-line (cdr line) line (car line)))
-      (should (equal (compilation--loc->col loc) col))
-      (should (equal (compilation--loc->line loc) line))
-      (when file
-        (should (equal (caar (compilation--loc->file-struct loc)) file)))
-      (when end-col
-        (should (equal (car (cadr (nth 2 (compilation--loc->file-struct loc))))
-                       end-col)))
-      (should (equal (car (nth 2 (compilation--loc->file-struct loc)))
-                     (or end-line line)))
-      (when type
-        (should (equal type (compilation--message->type msg)))))
-    msg))
+  (ert-info ((format "%S" test) :prefix "testcase: ")
+    (erase-buffer)
+    (setq compilation-locs (make-hash-table))
+    (let ((rule (nth 0 test))
+          (str (nth 1 test))
+          (pos (nth 2 test))
+          (col  (nth 3 test))
+          (line (nth 4 test))
+          (file (nth 5 test))
+          (type (nth 6 test)))
+      (insert str)
+      (compilation-parse-errors (point-min) (point-max))
+      (let ((msg (get-text-property pos 'compilation-message)))
+        (should msg)
+        (let ((loc (compilation--message->loc msg))
+              end-col end-line)
+          (if (consp col)
+              (setq end-col (cdr col) col (car col)))
+          (if (consp line)
+              (setq end-line (cdr line) line (car line)))
+          (should (equal (compilation--loc->col loc) col))
+          (should (equal (compilation--loc->line loc) line))
+          (when file
+            (should (equal (caar (compilation--loc->file-struct loc)) file)))
+          (when end-col
+            (should (equal
+                     (car (cadr (nth 2 (compilation--loc->file-struct loc))))
+                     end-col)))
+          (should (equal (car (nth 2 (compilation--loc->file-struct loc)))
+                         (or end-line line)))
+          (when type
+            (should (equal type (compilation--message->type msg))))
+          (should (equal rule (compilation--message->rule msg))))
+        msg))))
 
 (ert-deftest compile-test-error-regexps ()
   "Test the `compilation-error-regexp-alist' regexps.
@@ -452,16 +502,15 @@ The test data is in 
`compile-tests--grep-regexp-testcases'."
     (font-lock-mode -1)
     (dolist (testcase compile-tests--grep-regexp-testcases)
       (let (msg1 msg2)
-        (setq msg1 (ert-info ((format "%S" testcase) :prefix "testcase: ")
-                     (compile--test-error-line testcase)))
+        (setq msg1 (compile--test-error-line testcase))
         ;; Make sure replacing the NUL character with a colon still matches.
-        (setf (car testcase) (replace-regexp-in-string "\0" ":" (car 
testcase)))
-        (setq msg2 (ert-info ((format "%S" testcase) :prefix "testcase: ")
-                     (compile--test-error-line testcase)))
+        (let ((testcase2 (copy-sequence testcase)))
+          (setf (nth 1 testcase2)
+                (string-replace "\0" ":" (nth 1 testcase2)))
+          (setq msg2 (compile--test-error-line testcase2)))
         (should (equal msg1 msg2))))
     (dolist (testcase compile-tests--grep-regexp-tricky-testcases)
-      (ert-info ((format "%S" testcase) :prefix "testcase: ")
-        (compile--test-error-line testcase)))
+      (compile--test-error-line testcase))
     (should (eq compilation-num-errors-found 8))))
 
 ;;; compile-tests.el ends here
diff --git 
a/test/lisp/progmodes/cperl-mode-resources/fontify-punctuation-vars.pl 
b/test/lisp/progmodes/cperl-mode-resources/fontify-punctuation-vars.pl
new file mode 100644
index 0000000..fa32843
--- /dev/null
+++ b/test/lisp/progmodes/cperl-mode-resources/fontify-punctuation-vars.pl
@@ -0,0 +1,20 @@
+# The following Perl punctiation variables contain characters which
+# are classified as string delimiters in the syntax table.  The mode
+# should not be confused by these.
+# The corresponding tests check that two consecutive '#' characters
+# are seen as comments, not as strings.
+my $pre = $`;  ##  $PREMATCH,      use another ` # to balance out
+my $pos = $';  ##  $POSTMATCH,     use another ' # to balance out
+my $lsp = $";  ##  $LIST_SEPARATOR use another " # to balance out
+
+# In the second level, we use the reference constructor \ on these
+# variables.  The backslash is an escape character *only* in strings.
+my $ref = \$`; ## \$PREMATCH,      use another ` # to balance out
+my $rif = \$'; ## \$POSTMATCH,     use another ' # to balance out
+my $raf = \$"; ## \$LIST_SEPARATOR use another " # to balance out
+
+my $opt::s = 0;       ## s is no substitution here
+my $opt_s  = 0;       ## s is no substitution here
+my %opt = (s => 0);   ## s is no substitution here
+$opt{s} = 0;          ## s is no substitution here
+$opt_s =~ /\s+.../    ## s is no substitution here
diff --git a/test/lisp/progmodes/cperl-mode-tests.el 
b/test/lisp/progmodes/cperl-mode-tests.el
index e2af2b5..e67678c 100644
--- a/test/lisp/progmodes/cperl-mode-tests.el
+++ b/test/lisp/progmodes/cperl-mode-tests.el
@@ -196,4 +196,26 @@ Perl Best Practices sets some indentation values different 
from
             (should (equal got expected)))))
       (cperl-set-style "CPerl"))))
 
+(ert-deftest cperl-mode-fontify-punct-vars ()
+  "Test fontification of Perl's punctiation variables.
+Perl has variable names containing unbalanced quotes for the list
+separator $\" and pre- and postmatch $` and $'.  A reference to
+these variables, for example \\$\", should not cause the dollar
+to be escaped, which would then start a string beginning with the
+quote character.  This used to be broken in cperl-mode at some
+point in the distant past, and is still broken in perl-mode. "
+  (skip-unless (eq cperl-test-mode #'cperl-mode))
+  (let ((file (ert-resource-file "fontify-punctuation-vars.pl")))
+    (with-temp-buffer
+      (insert-file-contents file)
+      (goto-char (point-min))
+      (funcall cperl-test-mode)
+      (while (search-forward "##" nil t)
+        ;; The third element of syntax-ppss is true if in a string,
+        ;; which would indicate bad interpretation of the quote.  The
+        ;; fourth element is true if in a comment, which should be the
+        ;; case.
+        (should (equal (nth 3 (syntax-ppss)) nil))
+        (should (equal (nth 4 (syntax-ppss)) t))))))
+
 ;;; cperl-mode-tests.el ends here
diff --git a/test/manual/indent/js-chain.js 
b/test/lisp/progmodes/js-resources/js-chain.js
similarity index 100%
rename from test/manual/indent/js-chain.js
rename to test/lisp/progmodes/js-resources/js-chain.js
diff --git a/test/manual/indent/js-indent-align-list-continuation-nil.js 
b/test/lisp/progmodes/js-resources/js-indent-align-list-continuation-nil.js
similarity index 100%
rename from test/manual/indent/js-indent-align-list-continuation-nil.js
rename to 
test/lisp/progmodes/js-resources/js-indent-align-list-continuation-nil.js
diff --git a/test/manual/indent/js-indent-init-dynamic.js 
b/test/lisp/progmodes/js-resources/js-indent-init-dynamic.js
similarity index 100%
rename from test/manual/indent/js-indent-init-dynamic.js
rename to test/lisp/progmodes/js-resources/js-indent-init-dynamic.js
diff --git a/test/manual/indent/js-indent-init-t.js 
b/test/lisp/progmodes/js-resources/js-indent-init-t.js
similarity index 100%
rename from test/manual/indent/js-indent-init-t.js
rename to test/lisp/progmodes/js-resources/js-indent-init-t.js
diff --git a/test/manual/indent/js.js b/test/lisp/progmodes/js-resources/js.js
similarity index 100%
rename from test/manual/indent/js.js
rename to test/lisp/progmodes/js-resources/js.js
diff --git a/test/manual/indent/jsx-align-gt-with-lt.jsx 
b/test/lisp/progmodes/js-resources/jsx-align-gt-with-lt.jsx
similarity index 100%
rename from test/manual/indent/jsx-align-gt-with-lt.jsx
rename to test/lisp/progmodes/js-resources/jsx-align-gt-with-lt.jsx
diff --git a/test/manual/indent/jsx-comment-string.jsx 
b/test/lisp/progmodes/js-resources/jsx-comment-string.jsx
similarity index 100%
rename from test/manual/indent/jsx-comment-string.jsx
rename to test/lisp/progmodes/js-resources/jsx-comment-string.jsx
diff --git a/test/manual/indent/jsx-indent-level.jsx 
b/test/lisp/progmodes/js-resources/jsx-indent-level.jsx
similarity index 100%
rename from test/manual/indent/jsx-indent-level.jsx
rename to test/lisp/progmodes/js-resources/jsx-indent-level.jsx
diff --git a/test/manual/indent/jsx-quote.jsx 
b/test/lisp/progmodes/js-resources/jsx-quote.jsx
similarity index 100%
rename from test/manual/indent/jsx-quote.jsx
rename to test/lisp/progmodes/js-resources/jsx-quote.jsx
diff --git a/test/manual/indent/jsx-self-closing.jsx 
b/test/lisp/progmodes/js-resources/jsx-self-closing.jsx
similarity index 100%
rename from test/manual/indent/jsx-self-closing.jsx
rename to test/lisp/progmodes/js-resources/jsx-self-closing.jsx
diff --git a/test/manual/indent/jsx-unclosed-1.jsx 
b/test/lisp/progmodes/js-resources/jsx-unclosed-1.jsx
similarity index 100%
rename from test/manual/indent/jsx-unclosed-1.jsx
rename to test/lisp/progmodes/js-resources/jsx-unclosed-1.jsx
diff --git a/test/manual/indent/jsx-unclosed-2.jsx 
b/test/lisp/progmodes/js-resources/jsx-unclosed-2.jsx
similarity index 100%
rename from test/manual/indent/jsx-unclosed-2.jsx
rename to test/lisp/progmodes/js-resources/jsx-unclosed-2.jsx
diff --git a/test/manual/indent/jsx.jsx 
b/test/lisp/progmodes/js-resources/jsx.jsx
similarity index 100%
rename from test/manual/indent/jsx.jsx
rename to test/lisp/progmodes/js-resources/jsx.jsx
diff --git a/test/lisp/progmodes/js-tests.el b/test/lisp/progmodes/js-tests.el
index 681e51d..6c3a618 100644
--- a/test/lisp/progmodes/js-tests.el
+++ b/test/lisp/progmodes/js-tests.el
@@ -22,6 +22,7 @@
 ;;; Code:
 
 (require 'ert)
+(require 'ert-x)
 (require 'js)
 (require 'syntax)
 
@@ -196,6 +197,46 @@ if (!/[ (:,='\"]/.test(value)) {
     ;; The bug was a hang.
     (should t)))
 
+;;;; Indentation tests.
+
+(defun js-tests--remove-indentation ()
+  "Remove all indentation in the current buffer."
+  (goto-char (point-min))
+  (while (re-search-forward (rx bol (+ (in " \t"))) nil t)
+    (let ((syntax (save-match-data (syntax-ppss))))
+      (unless (nth 3 syntax)       ; Avoid multiline string literals.
+        (replace-match "")))))
+
+(defmacro js-deftest-indent (file)
+  `(ert-deftest ,(intern (format "js-indent-test/%s" file)) ()
+     :tags '(:expensive-test)
+     (let ((buf (find-file-noselect (ert-resource-file ,file))))
+       (unwind-protect
+           (with-current-buffer buf
+             (let ((orig (buffer-string)))
+               (js-tests--remove-indentation)
+               ;; Indent and check that we get the original text.
+               (indent-region (point-min) (point-max))
+               (should (equal (buffer-string) orig))
+               ;; Verify idempotency.
+               (indent-region (point-min) (point-max))
+               (should (equal (buffer-string) orig))))
+         (kill-buffer buf)))))
+
+(js-deftest-indent "js-chain.js")
+(js-deftest-indent "js-indent-align-list-continuation-nil.js")
+(js-deftest-indent "js-indent-init-dynamic.js")
+(js-deftest-indent "js-indent-init-t.js")
+(js-deftest-indent "js.js")
+(js-deftest-indent "jsx-align-gt-with-lt.jsx")
+(js-deftest-indent "jsx-comment-string.jsx")
+(js-deftest-indent "jsx-indent-level.jsx")
+(js-deftest-indent "jsx-quote.jsx")
+(js-deftest-indent "jsx-self-closing.jsx")
+(js-deftest-indent "jsx-unclosed-1.jsx")
+(js-deftest-indent "jsx-unclosed-2.jsx")
+(js-deftest-indent "jsx.jsx")
+
 (provide 'js-tests)
 
 ;;; js-tests.el ends here
diff --git a/test/lisp/progmodes/perl-mode-tests.el 
b/test/lisp/progmodes/perl-mode-tests.el
new file mode 100644
index 0000000..a2ea972
--- /dev/null
+++ b/test/lisp/progmodes/perl-mode-tests.el
@@ -0,0 +1,33 @@
+;;; perl-mode-tests --- Test for perl-mode  -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020 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 'perl-mode)
+
+;;;; Re-use cperl-mode tests
+
+(defvar cperl-test-mode)
+(setq cperl-test-mode #'perl-mode)
+(load-file (expand-file-name "cperl-mode-tests.el"
+                             (file-truename
+                              (file-name-directory (or load-file-name
+                                                       buffer-file-name)))))
+
+;;; perl-mode-tests.el ends here
diff --git a/test/data/xref/file1.txt 
b/test/lisp/progmodes/xref-resources/file1.txt
similarity index 100%
rename from test/data/xref/file1.txt
rename to test/lisp/progmodes/xref-resources/file1.txt
diff --git a/test/data/xref/file2.txt 
b/test/lisp/progmodes/xref-resources/file2.txt
similarity index 100%
rename from test/data/xref/file2.txt
rename to test/lisp/progmodes/xref-resources/file2.txt
diff --git a/test/lisp/progmodes/xref-tests.el 
b/test/lisp/progmodes/xref-tests.el
index a4980b2..060c9cb 100644
--- a/test/lisp/progmodes/xref-tests.el
+++ b/test/lisp/progmodes/xref-tests.el
@@ -23,13 +23,12 @@
 
 ;;; Code:
 
+(require 'ert)
+(require 'ert-x)
 (require 'xref)
 (require 'cl-lib)
 
-(defvar xref-tests-data-dir
-  (expand-file-name "../../../data/xref/"
-                    (or load-file-name
-                        buffer-file-name)))
+(defvar xref-tests-data-dir (ert-resource-directory))
 
 (ert-deftest xref-matches-in-directory-finds-none-for-some-regexp ()
   (should (null (xref-matches-in-directory "zzz" "*" xref-tests-data-dir 
nil))))
diff --git a/test/lisp/time-resources/non-empty 
b/test/lisp/time-resources/non-empty
new file mode 100644
index 0000000..86f5704
--- /dev/null
+++ b/test/lisp/time-resources/non-empty
@@ -0,0 +1 @@
+This file should be non-empty.
diff --git a/test/lisp/time-tests.el b/test/lisp/time-tests.el
new file mode 100644
index 0000000..1a62450
--- /dev/null
+++ b/test/lisp/time-tests.el
@@ -0,0 +1,78 @@
+;;; time-tests.el --- Tests for time.el  -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 Free Software Foundation, Inc.
+
+;; Author: Stefan Kangas <stefankangas@gmail.com>
+
+;; 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:
+
+(require 'ert)
+(require 'ert-x)
+(require 'time)
+
+(ert-deftest time-tests-display-time-mail-check-directory ()
+  (let ((display-time-mail-directory (ert-resource-directory)))
+    (should (display-time-mail-check-directory))))
+
+(ert-deftest time-tests-display-time-update--load ()
+  (let ((display-time-load-average 1)
+        (display-time-load-average-threshold 0))
+    (display-time-next-load-average)
+    (should (string-match (rx string-start " "
+                              (+ (| digit "."))
+                              string-end)
+                          (display-time-update--load))))
+  (let (display-time-load-average)
+    (should (equal (display-time-update--load) ""))))
+
+(ert-deftest time-tests-display-time-update ()
+  (let ((display-time-load-average 1)
+        (display-time-load-average-threshold 0)
+        display-time-string)
+    (display-time-update)
+    (should (string-match (rx string-start
+                              (? digit) digit ":" digit digit
+                              (? (| "AM" "PM"))
+                              " " (+ (| digit "."))
+                              string-end)
+                          display-time-string))))
+
+(ert-deftest time-tests-display-time-file-nonempty-p ()
+  (should (display-time-file-nonempty-p (ert-resource-file "non-empty")))
+  (should-not (display-time-file-nonempty-p "/non/existent")))
+
+(ert-deftest time-tests-world-clock ()
+  (save-window-excursion
+    (world-clock)
+    (should (equal (buffer-name) world-clock-buffer-name))
+    (should (string-match "New York" (buffer-string)))))
+
+(ert-deftest time-tests-world-clock/revert-buffer-works ()
+  (save-window-excursion
+    (world-clock)
+    (revert-buffer)
+    (should (string-match "New York" (buffer-string)))))
+
+(ert-deftest time-tests-emacs-uptime ()
+  (should (string-match "^[0-9.]+ seconds?$" (emacs-uptime "%S"))))
+
+(ert-deftest time-tests-emacs-init-time ()
+  (should (string-match "^[0-9.]+ seconds?$" (emacs-init-time))))
+
+(provide 'time-tests)
+;;; time-tests.el ends here
diff --git a/test/lisp/vc/vc-bzr-tests.el b/test/lisp/vc/vc-bzr-tests.el
index 408d6e8..d922e98 100644
--- a/test/lisp/vc/vc-bzr-tests.el
+++ b/test/lisp/vc/vc-bzr-tests.el
@@ -1,4 +1,4 @@
-;;; vc-bzr.el --- tests for vc/vc-bzr.el
+;;; vc-bzr.el --- tests for vc/vc-bzr.el  -*- lexical-binding: t -*-
 
 ;; Copyright (C) 2011-2020 Free Software Foundation, Inc.
 
diff --git a/test/lisp/wid-edit-tests.el b/test/lisp/wid-edit-tests.el
index df49ffc..4508b68 100644
--- a/test/lisp/wid-edit-tests.el
+++ b/test/lisp/wid-edit-tests.el
@@ -129,4 +129,23 @@
       (widget-insert "And some non-widget text.")
       (should (string= (widget-apply wid :value-get) "")))))
 
+(ert-deftest widget-test-moving-editable-list-item ()
+  "Check that we can move an editable list item up or down, via delete+insert."
+  (with-temp-buffer
+    (widget-insert "Testing editable-list.\n\n")
+    (let ((lst (widget-create 'editable-list
+                              :value '("beg" "end" "middle")
+                              '(editable-field :value "unknown"))))
+      (use-local-map widget-keymap)
+      (widget-setup)
+      ;; Go to the DEL button for the 2nd element and action it.
+      (goto-char (widget-get (nth 2 (widget-get lst :buttons)) :from))
+      (widget-apply-action (widget-at))
+      ;; Go to the INS button and action it.
+      (goto-char (widget-get lst :to))
+      (widget-backward 1)
+      (widget-apply-action (widget-at))
+      ;; Check that we effectively moved the item to the last position.
+      (should (equal (widget-value lst) '("beg" "middle" "end"))))))
+
 ;;; wid-edit-tests.el ends here
diff --git a/test/src/doc-tests.el b/test/src/doc-tests.el
deleted file mode 100644
index 797b9ba..0000000
--- a/test/src/doc-tests.el
+++ /dev/null
@@ -1,98 +0,0 @@
-;;; doc-tests.el --- Tests for doc.c -*- lexical-binding: t -*-
-
-;; Copyright (C) 2016-2020 Free Software Foundation, Inc.
-
-;; Author: Eli Zaretskii <eliz@gnu.org>
-
-;; 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)
-
-(ert-deftest doc-test-substitute-command-keys ()
-  ;; Bindings.
-  (should (string= (substitute-command-keys "foo \\[goto-char]") "foo M-g c"))
-  ;; Cannot use string= here, as that compares unibyte and multibyte
-  ;; strings not equal.
-  (should (compare-strings
-           (substitute-command-keys "\200 \\[goto-char]") nil nil
-           "\200 M-g c" nil nil))
-  ;; Literals.
-  (should (string= (substitute-command-keys "foo \\=\\[goto-char]")
-                   "foo \\[goto-char]"))
-  (should (string= (substitute-command-keys "foo \\=\\=")
-                   "foo \\="))
-  ;; Keymaps.
-  ;; I don't see that this is testing anything useful.
-  ;; AFAICS all it does it fail whenever someone modifies the
-  ;; minibuffer map.
-;;;   (should (string= (substitute-command-keys
-;;;                     "\\{minibuffer-local-must-match-map}")
-;;;                    "\
-;;; key             binding
-;;; ---             -------
-;;;
-;;; C-g                abort-recursive-edit
-;;; TAB                minibuffer-complete
-;;; C-j                minibuffer-complete-and-exit
-;;; RET                minibuffer-complete-and-exit
-;;; ESC                Prefix Command
-;;; SPC                minibuffer-complete-word
-;;; ?          minibuffer-completion-help
-;;; <C-tab>            file-cache-minibuffer-complete
-;;; <XF86Back> previous-history-element
-;;; <XF86Forward>      next-history-element
-;;; <down>             next-line-or-history-element
-;;; <next>             next-history-element
-;;; <prior>            switch-to-completions
-;;; <up>               previous-line-or-history-element
-;;;
-;;; M-v                switch-to-completions
-;;;
-;;; M-<                minibuffer-beginning-of-buffer
-;;; M-n                next-history-element
-;;; M-p                previous-history-element
-;;; M-r                previous-matching-history-element
-;;; M-s                next-matching-history-element
-;;;
-;;; "))
-  (should (string=
-           (substitute-command-keys
-            "\\<minibuffer-local-must-match-map>\\[abort-recursive-edit]")
-           "C-g"))
-  ;; Allow any style of quotes, since the terminal might not support
-  ;; UTF-8.
-  (should (string-match
-           "\nUses keymap [`‘']foobar-map['’], which is not currently 
defined.\n"
-            (substitute-command-keys "\\{foobar-map}")))
-  ;; Quotes.
-  (should (let ((text-quoting-style 'grave))
-            (string= (substitute-command-keys "quotes `like this'")
-                      "quotes `like this'")))
-  (should (let ((text-quoting-style 'grave))
-            (string= (substitute-command-keys "quotes ‘like this’")
-                      "quotes ‘like this’")))
-  (should (let ((text-quoting-style 'straight))
-            (string= (substitute-command-keys "quotes `like this'")
-                     "quotes 'like this'")))
-  ;; Bugs.
-  (should (string= (substitute-command-keys "\\[foobar") "\\[foobar"))
-  (should (string= (substitute-command-keys "\\=") "\\="))
-  )
-
-(provide 'doc-tests)
-;;; doc-tests.el ends here
diff --git a/test/data/emacs-module/mod-test.c 
b/test/src/emacs-module-resources/mod-test.c
similarity index 100%
rename from test/data/emacs-module/mod-test.c
rename to test/src/emacs-module-resources/mod-test.c
diff --git a/test/src/emacs-module-tests.el b/test/src/emacs-module-tests.el
index 621229c..fb4ed4a 100644
--- a/test/src/emacs-module-tests.el
+++ b/test/src/emacs-module-tests.el
@@ -21,13 +21,14 @@
 
 ;; Unit tests for the dynamic module facility.  See Info node `(elisp)
 ;; Writing Dynamic Modules'.  These tests make use of a small test
-;; module in test/data/emacs-module.
+;; module in the "emacs-module-resources" directory.
 
 ;;; Code:
 ;;; Prelude
 
 (require 'cl-lib)
 (require 'ert)
+(require 'ert-x)
 (require 'help-fns)
 
 (defconst mod-test-emacs
@@ -35,8 +36,7 @@
   "File name of the Emacs binary currently running.")
 
 (eval-and-compile
-  (defconst mod-test-file
-    (expand-file-name "../test/data/emacs-module/mod-test" 
invocation-directory)
+  (defconst mod-test-file (ert-resource-file "mod-test")
     "File name of the module test file."))
 
 (require 'mod-test mod-test-file)
@@ -313,11 +313,11 @@ local reference."
           (text-quoting-style 'grave))
       (describe-function-1 #'mod-test-sum)
       (goto-char (point-min))
-      (while (re-search-forward "`[^']*/data/emacs-module/" nil t)
-        (replace-match "`data/emacs-module/"))
+      (while (re-search-forward "`[^']*/src/emacs-module-resources/" nil t)
+        (replace-match "`src/emacs-module-resources/"))
       (should (equal
                (buffer-substring-no-properties 1 (point-max))
-               (format "a module function in `data/emacs-module/mod-test%s'.
+               (format "a module function in 
`src/emacs-module-resources/mod-test%s'.
 
 (mod-test-sum a b)
 
diff --git a/test/data/somelib.el b/test/src/lread-resources/somelib.el
similarity index 100%
rename from test/data/somelib.el
rename to test/src/lread-resources/somelib.el
diff --git a/test/data/somelib2.el b/test/src/lread-resources/somelib2.el
similarity index 100%
rename from test/data/somelib2.el
rename to test/src/lread-resources/somelib2.el
diff --git a/test/src/lread-tests.el b/test/src/lread-tests.el
index 26fd6aa..825b74e 100644
--- a/test/src/lread-tests.el
+++ b/test/src/lread-tests.el
@@ -25,6 +25,9 @@
 
 ;;; Code:
 
+(require 'ert)
+(require 'ert-x)
+
 (ert-deftest lread-char-number ()
   (should (equal (read "?\\N{U+A817}") #xA817)))
 
@@ -146,10 +149,7 @@ literals (Bug#20852)."
 
 (ert-deftest lread-test-bug26837 ()
   "Test for https://debbugs.gnu.org/26837 ."
-  (let ((load-path (cons
-                    (file-name-as-directory
-                     (expand-file-name "data" (getenv "EMACS_TEST_DIRECTORY")))
-                    load-path)))
+  (let ((load-path (cons (ert-resource-directory) load-path)))
     (load "somelib" nil t)
     (should (string-suffix-p "/somelib.el" (caar load-history)))
     (load "somelib2" nil t)
diff --git a/test/data/syntax-comments.txt 
b/test/src/syntax-resources/syntax-comments.txt
similarity index 100%
rename from test/data/syntax-comments.txt
rename to test/src/syntax-resources/syntax-comments.txt
diff --git a/test/src/syntax-tests.el b/test/src/syntax-tests.el
index 56e0338..4b9c3f2 100644
--- a/test/src/syntax-tests.el
+++ b/test/src/syntax-tests.el
@@ -20,6 +20,7 @@
 ;;; Code:
 
 (require 'ert)
+(require 'ert-x)
 
 (ert-deftest parse-partial-sexp-continue-over-comment-marker ()
   "Continue a parse that stopped in the middle of a comment marker."
@@ -91,7 +92,7 @@ also has open paren syntax (see Bug#24870)."
 ;; It is intended to enhance this bit to test nested comments
 ;; (2020-10-01).
 
-;; This bit uses the data file test/data/syntax-comments.txt.
+;; This bit uses the data file syntax-resources/syntax-comments.txt.
 
 (defun syntax-comments-point (n forw)
   "Return the buffer offset corresponding to the \"label\" N.
@@ -182,8 +183,7 @@ missing or nil, the value of START is assumed for it."
         ()
        (with-current-buffer
           (find-file
-           ,(expand-file-name "data/syntax-comments.txt"
-                              (getenv "EMACS_TEST_DIRECTORY")))
+            ,(ert-resource-file "syntax-comments.txt"))
         (,(intern (concat (symbol-name type) "-in")))
         (goto-char (syntax-comments-point ,start ,forw))
         (let ((stop (syntax-comments-point ,(or stop start) ,(not forw))))
@@ -230,8 +230,7 @@ missing or nil, the value of -START- is assumed for it."
         ()
        (with-current-buffer
           (find-file
-           ,(expand-file-name "data/syntax-comments.txt"
-                              (getenv "EMACS_TEST_DIRECTORY")))
+            ,(ert-resource-file "syntax-comments.txt"))
         (,(intern (concat (symbol-name type) "-in")))
          (let ((start-pos (syntax-comments-point ,start ,forw))
                ,@(if res
@@ -285,8 +284,7 @@ the `parse-partial-sexp's are expected to stop.  See
          ()
        (with-current-buffer
            (find-file
-            ,(expand-file-name "data/syntax-comments.txt"
-                               (getenv "EMACS_TEST_DIRECTORY")))
+            ,(ert-resource-file "syntax-comments.txt"))
          (,(intern (concat (symbol-name type) "-in")))
          (let ((start-pos (syntax-comments-point ,start t))
                (open-pos (syntax-comments-midpoint ,open))



reply via email to

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