emacs-diffs
[Top][All Lists]
Advanced

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

feature/native-comp 46e7613 2/3: Merge remote-tracking branch 'savannah/


From: Andrea Corallo
Subject: feature/native-comp 46e7613 2/3: Merge remote-tracking branch 'savannah/master' into HEAD
Date: Thu, 13 Aug 2020 06:49:38 -0400 (EDT)

branch: feature/native-comp
commit 46e7613ad3b88807d25cfab3d78bf46c9e2fe13e
Merge: f6502f9 e9eafd2
Author: Andrea Corallo <akrl@sdf.org>
Commit: Andrea Corallo <akrl@sdf.org>

    Merge remote-tracking branch 'savannah/master' into HEAD
---
 Makefile.in                                |   7 +
 configure.ac                               |  34 +-
 doc/emacs/calendar.texi                    |   5 +-
 doc/emacs/dired.texi                       |   8 +
 doc/emacs/misc.texi                        |  18 +-
 doc/lispref/positions.texi                 |   5 +-
 doc/lispref/tips.texi                      |  65 +++-
 doc/misc/tramp.texi                        |  23 +-
 etc/NEWS                                   | 106 ++++-
 etc/emacs.service                          |   2 +-
 etc/emacsclient.desktop                    |  12 +
 lib-src/emacsclient.c                      |  16 +-
 lib/alloca.in.h                            |   2 +-
 lib/arg-nonnull.h                          |   2 +-
 lib/binary-io.h                            |   2 +-
 lib/c++defs.h                              |   2 +-
 lib/cdefs.h                                | 103 +++--
 lib/count-one-bits.h                       |   3 +-
 lib/dirent.in.h                            |   2 +-
 lib/fcntl.c                                |   4 +-
 lib/ignore-value.h                         |   5 +-
 lib/intprops.h                             |   3 +-
 lib/malloca.h                              |   2 +-
 lib/regex.h                                |  17 +-
 lib/regex_internal.h                       |   6 +-
 lib/stdalign.in.h                          |  19 +-
 lib/stddef.in.h                            |   2 +-
 lib/stdint.in.h                            |   5 +-
 lib/stdio.in.h                             |   2 +-
 lib/stdlib.in.h                            |   2 +-
 lib/string.in.h                            |  14 +-
 lib/verify.h                               |  11 +-
 lib/warn-on-use.h                          |  31 +-
 lisp/allout-widgets.el                     |  19 +-
 lisp/allout.el                             |  46 +--
 lisp/apropos.el                            |  14 +
 lisp/bookmark.el                           |  78 +++-
 lisp/calc/calc-yank.el                     |  56 ++-
 lisp/calc/calc.el                          |  50 ++-
 lisp/calendar/cal-dst.el                   |   6 +-
 lisp/calendar/calendar.el                  |  10 +-
 lisp/calendar/solar.el                     |   6 +-
 lisp/cedet/semantic/fw.el                  |  10 +-
 lisp/cedet/semantic/grammar.el             |   1 +
 lisp/comint.el                             |  22 +-
 lisp/dired-aux.el                          |  43 ++-
 lisp/dired.el                              |   6 +
 lisp/emacs-lisp/autoload.el                |   7 +-
 lisp/emacs-lisp/checkdoc.el                |  13 +-
 lisp/emacs-lisp/eldoc.el                   |   8 +-
 lisp/emacs-lisp/lisp.el                    |   3 +-
 lisp/emulation/viper-cmd.el                |  33 +-
 lisp/emulation/viper.el                    |  35 +-
 lisp/epa-dired.el                          |   1 +
 lisp/epa-file.el                           |  10 +
 lisp/epa-hook.el                           |   1 +
 lisp/epa-mail.el                           |  10 +
 lisp/epa.el                                |  37 +-
 lisp/epg-config.el                         |   7 +
 lisp/epg.el                                |  80 ++--
 lisp/erc/erc-goodies.el                    |  27 +-
 lisp/erc/erc-join.el                       |  22 +-
 lisp/erc/erc.el                            |  85 ++--
 lisp/eshell/esh-proc.el                    |   2 +-
 lisp/files.el                              |  14 +-
 lisp/font-lock.el                          |  30 +-
 lisp/gnus/gnus-util.el                     |   4 +-
 lisp/gnus/gnus.el                          |   3 +-
 lisp/gnus/mm-util.el                       |  77 +---
 lisp/help-fns.el                           |   1 +
 lisp/language/burmese.el                   |   1 -
 lisp/language/cyril-util.el                |   2 +-
 lisp/language/hanja-util.el                |   4 +-
 lisp/language/indian.el                    |   2 +-
 lisp/leim/quail/latin-ltx.el               |   7 +-
 lisp/mail/smtpmail.el                      |  10 +-
 lisp/man.el                                |   5 +-
 lisp/net/dns.el                            |   5 +-
 lisp/net/eudc-bob.el                       |  10 +-
 lisp/net/eudcb-macos-contacts.el           |  16 +-
 lisp/net/imap.el                           |  32 +-
 lisp/net/mailcap.el                        |   5 -
 lisp/net/tramp-adb.el                      |   3 +-
 lisp/net/tramp-sh.el                       |   3 +-
 lisp/net/tramp.el                          |  40 +-
 lisp/obsolete/longlines.el                 |  17 +-
 lisp/play/bubbles.el                       |  10 +-
 lisp/progmodes/compile.el                  |   2 -
 lisp/progmodes/idlw-shell.el               |   4 +-
 lisp/progmodes/idlwave.el                  |  21 +-
 lisp/progmodes/prolog.el                   |  18 -
 lisp/progmodes/sql.el                      |  34 +-
 lisp/ps-def.el                             |   2 +-
 lisp/ps-print.el                           |   4 +-
 lisp/server.el                             |   9 +-
 lisp/shell.el                              |   7 +-
 lisp/simple.el                             | 147 +++++--
 lisp/term/st.el                            |  20 +
 lisp/textmodes/paragraphs.el               |  63 +--
 lisp/textmodes/tex-mode.el                 |   2 +-
 lisp/textmodes/texinfo.el                  |  71 ++++
 lisp/url/url-handlers.el                   |   3 +-
 lisp/vc/ediff-init.el                      |  15 -
 lisp/vc/vc-git.el                          |   2 +-
 lisp/vc/vc-src.el                          |  67 ++--
 lisp/vt100-led.el                          |   2 +-
 lisp/whitespace.el                         |   2 +-
 lisp/xwidget.el                            | 275 +++++++++----
 m4/gnulib-common.m4                        |   8 +-
 m4/stddef_h.m4                             |   4 +-
 m4/stdint.m4                               |   4 +-
 nextstep/templates/Info.plist.in           |  12 +-
 src/Makefile.in                            |   1 +
 src/bytecode.c                             |   1 -
 src/composite.c                            |   1 -
 src/emacs.c                                |   3 +-
 src/fns.c                                  |  67 +---
 src/json.c                                 |   4 +-
 src/lisp.h                                 |  24 +-
 src/macfont.m                              |  88 ++++-
 src/minibuf.c                              |   3 -
 src/nsterm.m                               |  21 +-
 src/nsxwidget.h                            |  80 ++++
 src/nsxwidget.m                            | 601 +++++++++++++++++++++++++++++
 src/pdumper.c                              | 320 +++++++--------
 src/pdumper.h                              |   1 +
 src/timefns.c                              |   2 +-
 src/xfaces.c                               |  20 +-
 src/xwidget.c                              | 253 +++++++++++-
 src/xwidget.h                              |  48 ++-
 test/lisp/bookmark-resources/test-list.bmk |  20 +
 test/lisp/bookmark-tests.el                | 215 +++++++++++
 test/lisp/emacs-lisp/lisp-tests.el         |  55 +++
 test/lisp/files-tests.el                   |   5 +-
 test/lisp/gnus/mml-sec-tests.el            |   3 +
 test/lisp/help-fns-tests.el                |  11 +
 test/src/emacs-module-tests.el             |  21 +-
 137 files changed, 3075 insertions(+), 1180 deletions(-)

diff --git a/Makefile.in b/Makefile.in
index 2f6a68f..f28623e 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -715,6 +715,13 @@ install-etc:
          ${srcdir}/etc/emacs.desktop > $${tmp}; \
        ${INSTALL_DATA} $${tmp} 
"$(DESTDIR)${desktopdir}/${EMACS_NAME}.desktop"; \
        rm -f $${tmp}
+       tmp=etc/emacsclient.tmpdesktop; rm -f $${tmp}; \
+       client_name=`echo emacsclient | sed '$(TRANSFORM)'`${EXEEXT}; \
+       sed -e "/^Exec=emacsclient/ s|emacsclient|${bindir}/$${client_name}|" \
+         -e "/^Icon=emacs/ s/emacs/${EMACS_NAME}/" \
+         ${srcdir}/etc/emacsclient.desktop > $${tmp}; \
+       ${INSTALL_DATA} $${tmp} 
"$(DESTDIR)${desktopdir}/$${client_name}.desktop"; \
+       rm -f $${tmp}
        umask 022; ${MKDIR_P} "$(DESTDIR)${appdatadir}"
        tmp=etc/emacs.tmpappdata; rm -f $${tmp}; \
        sed -e "s/emacs\.desktop/${EMACS_NAME}.desktop/" \
diff --git a/configure.ac b/configure.ac
index 76a3e6b..4b8497b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -490,7 +490,7 @@ otherwise for the first of 'inotify', 'kqueue' or 'gfile' 
that is usable.])
  [with_file_notification=$with_features])
 
 OPTION_DEFAULT_OFF([xwidgets],
-  [enable use of some gtk widgets in Emacs buffers (requires gtk3)])
+  [enable use of xwidgets in Emacs buffers (requires gtk3 or macOS Cocoa)])
 
 ## For the times when you want to build Emacs but don't have
 ## a suitable makeinfo, and can live without the manuals.
@@ -2755,20 +2755,34 @@ fi
 
 
 dnl Enable xwidgets if GTK3 and WebKitGTK+ are available.
+dnl Enable xwidgets if macOS Cocoa and WebKit framework are available.
 HAVE_XWIDGETS=no
 XWIDGETS_OBJ=
 if test "$with_xwidgets" != "no"; then
-  test "$USE_GTK_TOOLKIT" = "GTK3" && test "$window_system" != "none" ||
-    AC_MSG_ERROR([xwidgets requested but gtk3 not used.])
+  if test "$USE_GTK_TOOLKIT" = "GTK3" && test "$window_system" != "none"; then
+    WEBKIT_REQUIRED=2.12
+    WEBKIT_MODULES="webkit2gtk-4.0 >= $WEBKIT_REQUIRED"
+    EMACS_CHECK_MODULES([WEBKIT], [$WEBKIT_MODULES])
+    HAVE_XWIDGETS=$HAVE_WEBKIT
+    XWIDGETS_OBJ="xwidget.o"
+  elif test "${NS_IMPL_COCOA}" = "yes"; then
+    dnl FIXME: Check framework WebKit2
+    dnl WEBKIT_REQUIRED=M.m.p
+    WEBKIT_LIBS="-Wl,-framework -Wl,WebKit"
+    WEBKIT_CFLAGS="-I/System/Library/Frameworks/WebKit.framework/Headers"
+    HAVE_WEBKIT="yes"
+    HAVE_XWIDGETS=$HAVE_WEBKIT
+    XWIDGETS_OBJ="xwidget.o"
+    NS_OBJC_OBJ="$NS_OBJC_OBJ nsxwidget.o"
+    dnl Update NS_OBJC_OBJ with added nsxwidget.o
+    AC_SUBST(NS_OBJC_OBJ)
+  else
+    AC_MSG_ERROR([xwidgets requested, it requires GTK3 as X window toolkit or 
macOS Cocoa as window system.])
+  fi
 
-  WEBKIT_REQUIRED=2.12
-  WEBKIT_MODULES="webkit2gtk-4.0 >= $WEBKIT_REQUIRED"
-  EMACS_CHECK_MODULES([WEBKIT], [$WEBKIT_MODULES])
-  HAVE_XWIDGETS=$HAVE_WEBKIT
   test $HAVE_XWIDGETS = yes ||
-    AC_MSG_ERROR([xwidgets requested but WebKitGTK+ not found.])
+    AC_MSG_ERROR([xwidgets requested but WebKitGTK+ or WebKit framework not 
found.])
 
-  XWIDGETS_OBJ=xwidget.o
   AC_DEFINE([HAVE_XWIDGETS], 1, [Define to 1 if you have xwidgets support.])
 fi
 AC_SUBST(XWIDGETS_OBJ)
@@ -5776,7 +5790,7 @@ AS_ECHO(["  Does Emacs use -lXaw3d?                       
          ${HAVE_XAW3D
   Does Emacs directly use zlib?                           ${HAVE_ZLIB}
   Does Emacs have dynamic modules support?                ${HAVE_MODULES}
   Does Emacs use toolkit scroll bars?                     
${USE_TOOLKIT_SCROLL_BARS}
-  Does Emacs support Xwidgets (requires gtk3)?            ${HAVE_XWIDGETS}
+  Does Emacs support Xwidgets?                            ${HAVE_XWIDGETS}
   Does Emacs have threading support in lisp?              ${threads_enabled}
   Does Emacs support the portable dumper?                 ${with_pdumper}
   Does Emacs support legacy unexec dumping?               ${with_unexec}
diff --git a/doc/emacs/calendar.texi b/doc/emacs/calendar.texi
index 31db815..e5ee7e9 100644
--- a/doc/emacs/calendar.texi
+++ b/doc/emacs/calendar.texi
@@ -625,10 +625,9 @@ your time zone.  Emacs displays the times of sunrise and 
sunset
 @emph{corrected for daylight saving time}.  @xref{Daylight Saving},
 for how daylight saving time is determined.
 
-@vindex calendar-use-numeric-time-zones
+@vindex calendar-time-zone-style
   If you want to display numerical time zones (like @samp{"+0100"})
-instead of symbolic time zones (like @samp{"CET"}), set the
-@code{calendar-use-numeric-time-zones} variable to non-@code{nil}.
+instead of symbolic ones (like @samp{"CET"}), set this to @code{numeric}.
 
   As a user, you might find it convenient to set the calendar location
 variables for your usual physical location in your @file{.emacs} file.
diff --git a/doc/emacs/dired.texi b/doc/emacs/dired.texi
index 4ff1dc1..de449e3 100644
--- a/doc/emacs/dired.texi
+++ b/doc/emacs/dired.texi
@@ -694,6 +694,14 @@ The variable @code{dired-recursive-copies} controls 
whether to copy
 directories recursively (like @samp{cp -r}).  The default is
 @code{top}, which means to ask before recursively copying a directory.
 
+@vindex dired-copy-dereference
+@cindex follow symbolic links
+@cindex dereference symbolic links
+The variable @code{dired-copy-dereference} controls whether to copy
+symbolic links as links or after dereferencing (like @samp{cp -L}).
+The default is @code{nil}, which means that the symbolic links are
+copied by creating new ones.
+
 @item D
 @findex dired-do-delete
 @kindex D @r{(Dired)}
diff --git a/doc/emacs/misc.texi b/doc/emacs/misc.texi
index cb9fc61..f3c9d76 100644
--- a/doc/emacs/misc.texi
+++ b/doc/emacs/misc.texi
@@ -729,10 +729,9 @@ See the Eshell Info manual, which is distributed with 
Emacs.
 minibuffer and executes it as a shell command, in a subshell made just
 for that command.  Standard input for the command comes from the null
 device.  If the shell command produces any output, the output appears
-either in the echo area (if it is short), or in an Emacs buffer,
-displayed in another window (if the output is long).  The name of
-this buffer is taken from the constant @code{shell-command-buffer-name}.
-The variables @code{resize-mini-windows} and
+either in the echo area (if it is short), or in the @samp{"*Shell
+Command Output*"} (@code{shell-command-buffer-name}) buffer (if the
+output is long).  The variables @code{resize-mini-windows} and
 @code{max-mini-window-height} (@pxref{Minibuffer Edit}) control when
 Emacs should consider the output to be too long for the echo area.
 
@@ -766,10 +765,11 @@ which is impossible to ignore.
 You can also type @kbd{M-&} (@code{async-shell-command}) to execute a
 shell command asynchronously; this is exactly like calling @kbd{M-!}
 with a trailing @samp{&}, except that you do not need the @samp{&}.
-The constant @code{shell-command-buffer-name-async} stores the name
-of the default output buffer for asynchronous shell commands.
-Emacs inserts the output into this buffer as it comes in,
-whether or not the buffer is visible in a window.
+The output from asynchronous shell commands, by default, goes into the
+@samp{"*Async Shell Command*"} buffer
+(@code{shell-command-buffer-name-async}).  Emacs inserts the output
+into this buffer as it comes in, whether or not the buffer is visible
+in a window.
 
 @vindex async-shell-command-buffer
   If you want to run more than one asynchronous shell command at the
@@ -807,7 +807,7 @@ old region and replaces it with the output from the shell 
command.
 see what keys are in the buffer.  If the buffer contains a GnuPG key,
 type @kbd{C-x h M-| gpg @key{RET}} to feed the entire buffer contents
 to @command{gpg}.  This will output the list of keys to the
-buffer named @code{shell-command-buffer-name}.
+buffer whose name is the value of @code{shell-command-buffer-name}.
 
 @vindex shell-file-name
   The above commands use the shell specified by the variable
diff --git a/doc/lispref/positions.texi b/doc/lispref/positions.texi
index d7856ce..9141970 100644
--- a/doc/lispref/positions.texi
+++ b/doc/lispref/positions.texi
@@ -411,7 +411,7 @@ function counts that line as one line successfully moved.
 In an interactive call, @var{count} is the numeric prefix argument.
 @end deffn
 
-@defun count-lines start end
+@defun count-lines start end &optional ignore-invisible-lines
 @cindex lines in region
 @anchor{Definition of count-lines}
 This function returns the number of lines between the positions
@@ -420,6 +420,9 @@ This function returns the number of lines between the 
positions
 1, even if @var{start} and @var{end} are on the same line.  This is
 because the text between them, considered in isolation, must contain at
 least one line unless it is empty.
+
+If the optional @var{ignore-invisible-lines} is non-@code{nil},
+invisible lines will not be included in the count.
 @end defun
 
 @deffn Command count-words start end
diff --git a/doc/lispref/tips.texi b/doc/lispref/tips.texi
index 5b09b2c..6292054 100644
--- a/doc/lispref/tips.texi
+++ b/doc/lispref/tips.texi
@@ -918,29 +918,56 @@ values.  It is much better to convert such comments to 
documentation
 strings, though.
 
 @item ;;;
-Comments that start with three semicolons, @samp{;;;}, should start at
-the left margin.  We use them
-for comments which should be considered a
-heading by Outline minor mode.  By default, comments starting with
-at least three semicolons (followed by a single space and a
-non-whitespace character) are considered headings, comments starting
-with two or fewer are not.  Historically, triple-semicolon comments have
-also been used for commenting out lines within a function, but this use
-is discouraged.
-
-When commenting out entire functions, use two semicolons.
-
-@item ;;;;
-Comments that start with four (or more) semicolons, @samp{;;;;},
-should be aligned to the left margin and are used for headings of
-major sections of a program.  For example:
+
+Comments that start with three (or more) semicolons, @samp{;;;},
+should start at the left margin.  We use them for comments that should
+be considered a heading by Outline minor mode.  By default, comments
+starting with at least three semicolons (followed by a single space
+and a non-whitespace character) are considered section headings,
+comments starting with two or fewer are not.
+
+(Historically, triple-semicolon comments have also been used for
+commenting out lines within a function, but this use is discouraged in
+favor of using just two semicolons.  This also applies when commenting
+out entire functions; when doing that use two semicolons as well.)
+
+Three semicolons are used for top-level sections, four for
+sub-sections, five for sub-sub-sections and so on.
+
+Typically libraries have at least four top-level sections.  For
+example when the bodies of all of these sections are hidden:
 
 @smallexample
-;;;; The kill ring
+@group
+;;; backquote.el --- implement the ` Lisp construct...
+;;; Commentary:...
+;;; Code:...
+;;; backquote.el ends here
+@end group
 @end smallexample
 
-If you wish to have sub-headings under these heading, use more
-semicolons to nest these sub-headings.
+(In a sense the last line is not a section heading as it must
+never be followed by any text; after all it marks the end of the
+file.)
+
+For longer libraries it is advisable to split the code into multiple
+sections.  This can be done by splitting the @samp{Code:} section into
+multiple sub-sections.  Even though that was the only recommended
+approach for a long time, many people have chosen to use multiple
+top-level code sections instead.  You may chose either style.
+
+Using multiple top-level code sections has the advanatage that it
+avoids introducing an additional nesting level but it also means that
+the section named @samp{Code} does not contain all the code, which is
+awkward.  To avoid that, you should put no code at all inside that
+section; that way it can be considered a seperator instead of a
+section heading.
+
+Finally, we recommend that you don't end headings with a colon or any
+other punctuation for that matter.  For historic reasons the
+@samp{Code:} and @samp{Commentary:} headings end with a colon, but we
+recommend that you don't do the same for other headings anyway.
+
 @end table
 
 @noindent
diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi
index ae6fe3d..c1a66d0 100644
--- a/doc/misc/tramp.texi
+++ b/doc/misc/tramp.texi
@@ -3378,8 +3378,8 @@ host.  Example:
 @end group
 @end example
 
-@command{tail} command outputs continuously to the local buffer,
-named @code{shell-command-buffer-name-async}
+@command{tail} command outputs continuously to the local buffer whose
+name is the value of the variable @code{shell-command-buffer-name-async}.
 
 @kbd{M-x auto-revert-tail-mode @key{RET}} runs similarly showing
 continuous output.
@@ -3561,7 +3561,13 @@ which must be set to a non-@code{nil} value.  Example:
 @end group
 @end lisp
 
-However, this approach has different limitations:
+Using direct asynchronous processes in @value{tramp} is not possible,
+if the remote host is connected via multiple hops
+(@pxref{Multi-hops}), or the @code{make-process} /
+@code{start-file-process} call uses a stderr stream.  In this case,
+@value{tramp} falls back to its classical implementation.
+
+Furthermore, this approach has the following limitations:
 
 @itemize
 @item
@@ -3569,16 +3575,10 @@ It works only for connection methods defined in 
@file{tramp-sh.el} and
 @file{tramp-adb.el}.
 
 @item
-It does not support multi-hop methods.
-
-@item
 It does not support interactive user authentication, like password
 handling.
 
 @item
-It does not support a separated error stream.
-
-@item
 It cannot be killed via @code{interrupt-process}.
 
 @item
@@ -3594,7 +3594,10 @@ It does not set environment variable @env{INSIDE_EMACS}.
 
 In order to gain even more performance, it is recommended to bind
 @code{tramp-verbose} to 0 when running @code{make-process} or
-@code{start-file-process}.
+@code{start-file-process}.  Furthermore, you might set
+@code{tramp-use-ssh-controlmaster-options} to @code{nil} in order to
+bypass @value{tramp}'s handling of the @code{ControlMaster} options,
+and use your own settings in @file{~/.ssh/config}.
 
 
 @node Cleanup remote connections
diff --git a/etc/NEWS b/etc/NEWS
index 8118272..2be9743 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -81,9 +81,11 @@ useful on systems such as FreeBSD which ships only with 
"etc/termcap".
 * Changes in Emacs 28.1
 
 +++
-** The new constants 'shell-command-buffer-name' and
+** New variables that hold default buffer names for shell output.
+The new constants 'shell-command-buffer-name' and
 'shell-command-buffer-name-async' store the default buffer names
-for the output of shell commands.
+for the output of, respectively, synchronous and async shell
+commands.
 
 ** Support for '(box . SIZE)' 'cursor-type'.
 By default, 'box' cursor always has a filled box shape.  But if you
@@ -96,9 +98,20 @@ dimension.
 Added a new Mozhi scheme.  The inapplicable ITRANS scheme is now
 deprecated.  Errors in the Inscript method were corrected.
 
+---
+** Rudimentary support for the 'st' terminal emulator.
+Emacs now supports 256 color display on the 'st' terminal emulator.
+
 
 * Editing Changes in Emacs 28.1
 
+---
+** 'eval-expression' now no longer signals an error on incomplete expressions.
+Previously, typing 'M-: ( RET' would result in Emacs saying "End of
+file during parsing" and dropping out of the minibuffer.  The user
+would have to type 'M-: M-p' to edit and redo the expression.  Now
+Emacs will echo the message and allow the user to continue editing.
+
 +++
 ** New command 'undo-redo'.
 It undoes previous undo commands, but doesn't record itself as an
@@ -201,13 +214,19 @@ as a data list rather than as a piece of code.
 
 ** Calendar
 
-*** New variable 'calendar-use-numeric-time-zones' to use numeric time zones.
-If non-nil, functions that display time zones (like the 'S' command in
-calendar mode that displays the sunrise time) will display time zones
-like "+0100" instead of "CET".
++++
+*** New user option 'calendar-time-zone-style'.
+If 'numeric, calendar functions (eg calendar-sunrise-sunset) that display
+time zones will use a form like "+0100" instead of "CET".
 
 ** Dired
 
++++
+*** New user option 'dired-copy-dereference'.
+If set, Dired will dereferences symbolic links when copying.  This can
+be switched off on a per-usage basis by providing 'dired-do-copy' with
+a 'C-u' prefix.
+
 *** New user option 'dired-mark-region' affects all Dired commands
 that mark files.  When non-nil and the region is active in Transient
 Mark mode, then Dired commands operate only on files in the active
@@ -233,12 +252,12 @@ their 'default-directory' under VC.
 Bookmark locations can refer to VC directory buffers.
 
 ---
-*** New user option 'vc-hg-create-bookmark' controls whether a bookmark
-or branch will be created when you invoke 'C-u C-x v s' ('vc-create-tag').
+*** New user option 'vc-hg-create-bookmark'.
+It controls whether a bookmark or branch will be created when you
+invoke 'C-u C-x v s' ('vc-create-tag').
 
 ---
-*** 'vc-hg' now uses 'hg summary' command to populate extra 'vc-dir'
-headers.
+*** 'vc-hg' now uses 'hg summary' to populate extra 'vc-dir' headers.
 
 
 ** Gnus
@@ -502,6 +521,14 @@ with a newline.
 *** New user option 'texinfo-texi2dvi-options'.
 This is used when invoking 'texi2dvi' from 'texinfo-tex-buffer'.
 
+---
+*** New commands for moving in and between environments.
+An "environment" is something that ends with @end.  The commands are
+'C-c C-c C-f' (next end), 'C-c C-c C-b' (previous end),
+'C-c C-c C-n' (next start) and 'C-c C-c C-p' (previous start), as well
+as 'C-c .', which will alternate between the start end the end of the
+current environment.
+
 ** Rmail
 
 ---
@@ -515,6 +542,9 @@ prefix on the Subject line in various languages.
 These new navigation commands are bound to 'n' and 'p' in
 'apropos-mode'.
 
+*** New command 'apropos-function'.
+This works like 'C-u M-x apropos-command' but is more discoverable.
+
 ** CC Mode
 
 *** Added support for Doxygen documentation style.
@@ -687,6 +717,10 @@ https://www.w3.org/TR/xml/#charsets).  Now it rejects such 
strings.
 *** The /ignore command will now ask for a timeout to stop ignoring the user.
 Allowed inputs are seconds or ISO8601-like periods like "1h" or "4h30m".
 
+---
+*** ERC now recognizes C-] for italic text.
+Italic text is displayed in the new 'erc-italic-face'.
+
 ** Battery
 
 ---
@@ -734,6 +768,15 @@ name.
 ** Recentf
 The recentf files are no longer backed up.
 
+** Calc
+
+---
+*** The behaviour when doing forward-delete has been changed.
+Previously, using the 'C-d' command would delete the final number in
+the input field, no matter where point was.  This has been changed to
+work more traditionally, with 'C-d' deleting the next character.
+Likewise, point isn't moved to the end of the string before inserting
+digits.
 
 ** Miscellaneous
 
@@ -751,6 +794,29 @@ 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.
 
+
+** xwidget-webkit mode
+
+*** New xwidget functions
+'xwidget-webkit-uri' (return the current URL), 'xwidget-webkit-title'
+(return the current title), and 'xwidget-webkit-goto-history' (goto a
+point in history).
+
+*** Pixel-based scrolling
+The 'xwidget-webkit-scroll-up', 'xwidget-webkit-scroll-down' commands
+now supports scrolling arbitrary pixel values.  It now treats the
+optional 2nd argument as the pixel values to scroll.
+
+*** New commands for scrolling
+The new commands 'xwidget-webkit-scroll-up-line',
+'xwidget-webkit-scroll-down-line', 'xwidget-webkit-scroll-forward',
+'xwidget-webkit-scroll-backward' can be used to scroll webkit by the
+height of lines or width of chars.
+
+*** New user option 'xwidget-webkit-bookmark-jump-new-session'.
+When non-nil, use a new xwidget webkit session after bookmark jump.
+Otherwise, it will use 'xwidget-webkit-last-session'.
+
 
 * New Modes and Packages in Emacs 28.1
 
@@ -828,6 +894,10 @@ have now been removed.
 
 * Lisp Changes in Emacs 28.1
 
++++
+** The 'count-lines' function now takes an optional parameter to
+ignore invisible lines.
+
 ---
 ** New function 'custom-add-choice'.
 This function can be used by modes to add elements to the
@@ -914,6 +984,21 @@ convert them to a list '(R G B)' of primary color values.
 
 * Changes in Emacs 28.1 on Non-Free Operating Systems
 
+---
+** On macOS, Xwidget is now supported.
+If Emacs was built with xwidget support, you can access the embedded
+webkit browser with 'M-x xwidget-webkit-browse-url'.  Viewing two
+instances of xwidget webkit is not supported.
+
+*** Downloading files from xwidget-webkit is now supported.
+The new variable 'xwidget-webkit-download-dir' says where to download to.
+
+*** New functions for xwidget-webkit mode
+'xwidget-webkit-clone-and-split-below',
+'xwidget-webkit-clone-and-split-right'.
+
+*** New variable 'xwidget-webkit-enable-plugins'.
+
 +++
 ** On macOS, Emacs can now load dynamic modules with a ".dylib" suffix.
 'module-file-suffix' now has the value ".dylib" on macOS, but the
@@ -954,6 +1039,7 @@ 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/>.
 
+
 
 Local variables:
 coding: utf-8
diff --git a/etc/emacs.service b/etc/emacs.service
index c99c677..0dc2418 100644
--- a/etc/emacs.service
+++ b/etc/emacs.service
@@ -8,7 +8,7 @@ Documentation=info:emacs man:emacs(1) 
https://gnu.org/software/emacs/
 
 [Service]
 Type=notify
-ExecStart=emacs --fg-daemon
+ExecStart=@emacs emacsd --fg-daemon
 ExecStop=emacsclient --eval "(kill-emacs)"
 # The location of the SSH auth socket varies by distribution, and some
 # set it from PAM, so don't override by default.
diff --git a/etc/emacsclient.desktop b/etc/emacsclient.desktop
new file mode 100644
index 0000000..3feb83c
--- /dev/null
+++ b/etc/emacsclient.desktop
@@ -0,0 +1,12 @@
+[Desktop Entry]
+Name=Emacs (Client)
+GenericName=Text Editor
+Comment=Edit text
+MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++;
+Exec=emacsclient -c %F
+Icon=emacs
+Type=Application
+Terminal=false
+Categories=Development;TextEditor;
+StartupWMClass=Emacsd
+Keywords=Text;Editor;
diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c
index 380be95..871fa7a 100644
--- a/lib-src/emacsclient.c
+++ b/lib-src/emacsclient.c
@@ -1504,11 +1504,17 @@ set_local_socket (char const *server_name)
                "%s: (Be careful: XDG_RUNTIME_DIR is security-related.)\n"),
               progname, sockdirname, progname);
        }
-      message (true,
-              ("%s: can't find socket; have you started the server?\n"
-               "%s: To start the server in Emacs,"
-               " type \"M-x server-start\".\n"),
-              progname, progname);
+
+      /* If there's an alternate editor and the user has requested
+        --quiet, don't output the warning. */
+      if (!quiet || !alternate_editor)
+       {
+         message (true,
+                  ("%s: can't find socket; have you started the server?\n"
+                   "%s: To start the server in Emacs,"
+                   " type \"M-x server-start\".\n"),
+                  progname, progname);
+       }
     }
   else
     message (true, "%s: can't stat %s: %s\n",
diff --git a/lib/alloca.in.h b/lib/alloca.in.h
index 5686b08..c71e9bf 100644
--- a/lib/alloca.in.h
+++ b/lib/alloca.in.h
@@ -44,7 +44,7 @@
 # endif
 #endif
 #ifndef alloca
-# ifdef __GNUC__
+# if defined __GNUC__ || (__clang_major__ >= 4)
 #  define alloca __builtin_alloca
 # elif defined _AIX
 #  define alloca __alloca
diff --git a/lib/arg-nonnull.h b/lib/arg-nonnull.h
index ac26ca8..db9d9ae 100644
--- a/lib/arg-nonnull.h
+++ b/lib/arg-nonnull.h
@@ -18,7 +18,7 @@
    that the values passed as arguments n, ..., m must be non-NULL pointers.
    n = 1 stands for the first argument, n = 2 for the second argument etc.  */
 #ifndef _GL_ARG_NONNULL
-# if (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || __GNUC__ > 3
+# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || defined 
__clang__
 #  define _GL_ARG_NONNULL(params) __attribute__ ((__nonnull__ params))
 # else
 #  define _GL_ARG_NONNULL(params)
diff --git a/lib/binary-io.h b/lib/binary-io.h
index 477b4bf..d17af7c 100644
--- a/lib/binary-io.h
+++ b/lib/binary-io.h
@@ -56,7 +56,7 @@ __gl_setmode (int fd _GL_UNUSED, int mode _GL_UNUSED)
 /* Set FD's mode to MODE, which should be either O_TEXT or O_BINARY.
    Return the old mode if successful, -1 (setting errno) on failure.
    Ordinarily this function would be called 'setmode', since that is
-   its name on MS-Windows, but it is called 'set_binary_mode' here
+   its old name on MS-Windows, but it is called 'set_binary_mode' here
    to avoid colliding with a BSD function of another name.  */
 
 #if defined __DJGPP__ || defined __EMX__
diff --git a/lib/c++defs.h b/lib/c++defs.h
index 182c2b3..90e6fd6 100644
--- a/lib/c++defs.h
+++ b/lib/c++defs.h
@@ -298,7 +298,7 @@
    we enable the warning only when not optimizing.  */
 # if !(defined __GNUC__ && !defined __clang__ && __OPTIMIZE__)
 #  define 
_GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \
-    _GL_WARN_ON_USE_CXX (func, rettype, parameters_and_attributes, \
+    _GL_WARN_ON_USE_CXX (func, rettype, rettype, parameters_and_attributes, \
                          "The symbol ::" #func " refers to the system 
function. " \
                          "Use " #namespace "::" #func " instead.")
 # else
diff --git a/lib/cdefs.h b/lib/cdefs.h
index f6c447a..4f89f4e 100644
--- a/lib/cdefs.h
+++ b/lib/cdefs.h
@@ -34,7 +34,34 @@
 #undef __P
 #undef __PMT
 
-#ifdef __GNUC__
+/* Compilers that are not clang may object to
+       #if defined __clang__ && __has_attribute(...)
+   even though they do not need to evaluate the right-hand side of the &&.  */
+#if defined __clang__ && defined __has_attribute
+# define __glibc_clang_has_attribute(name) __has_attribute (name)
+#else
+# define __glibc_clang_has_attribute(name) 0
+#endif
+
+/* Compilers that are not clang may object to
+       #if defined __clang__ && __has_builtin(...)
+   even though they do not need to evaluate the right-hand side of the &&.  */
+#if defined __clang__ && defined __has_builtin
+# define __glibc_clang_has_builtin(name) __has_builtin (name)
+#else
+# define __glibc_clang_has_builtin(name) 0
+#endif
+
+/* Compilers that are not clang may object to
+       #if defined __clang__ && __has_extension(...)
+   even though they do not need to evaluate the right-hand side of the &&.  */
+#if defined __clang__ && defined __has_extension
+# define __glibc_clang_has_extension(ext) __has_extension (ext)
+#else
+# define __glibc_clang_has_extension(ext) 0
+#endif
+
+#if defined __GNUC__ || defined __clang__
 
 /* All functions, except those with callbacks or those that
    synchronize memory, are leaf functions.  */
@@ -51,7 +78,8 @@
    gcc 2.8.x and egcs.  For gcc 3.2 and up we even mark C functions
    as non-throwing using a function attribute since programs can use
    the -fexceptions options for C code as well.  */
-# if !defined __cplusplus && __GNUC_PREREQ (3, 3)
+# if !defined __cplusplus \
+     && (__GNUC_PREREQ (3, 3) || __glibc_clang_has_attribute (__nothrow__))
 #  define __THROW      __attribute__ ((__nothrow__ __LEAF))
 #  define __THROWNL    __attribute__ ((__nothrow__))
 #  define __NTH(fct)   __attribute__ ((__nothrow__ __LEAF)) fct
@@ -70,7 +98,7 @@
 #  endif
 # endif
 
-#else  /* Not GCC.  */
+#else  /* Not GCC or clang.  */
 
 # if (defined __cplusplus                                              \
       || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L))
@@ -83,16 +111,7 @@
 # define __THROWNL
 # define __NTH(fct)    fct
 
-#endif /* GCC.  */
-
-/* Compilers that are not clang may object to
-       #if defined __clang__ && __has_extension(...)
-   even though they do not need to evaluate the right-hand side of the &&.  */
-#if defined __clang__ && defined __has_extension
-# define __glibc_clang_has_extension(ext) __has_extension (ext)
-#else
-# define __glibc_clang_has_extension(ext) 0
-#endif
+#endif /* GCC || clang.  */
 
 /* These two macros are not used in glibc anymore.  They are kept here
    only because some other projects expect the macros to be defined.  */
@@ -129,6 +148,12 @@
 # define __warnattr(msg) __attribute__((__warning__ (msg)))
 # define __errordecl(name, msg) \
   extern void name (void) __attribute__((__error__ (msg)))
+#elif __glibc_clang_has_attribute (__diagnose_if__)
+# define __warndecl(name, msg) \
+  extern void name (void) __attribute__((__diagnose_if__ (1, msg, "warning")))
+# define __warnattr(msg) __attribute__((__diagnose_if__ (1, msg, "warning")))
+# define __errordecl(name, msg) \
+  extern void name (void) __attribute__((__diagnose_if__ (1, msg, "error")))
 #else
 # define __warndecl(name, msg) extern void name (void)
 # define __warnattr(msg)
@@ -142,8 +167,8 @@
 #if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L && !defined __HP_cc
 # define __flexarr     []
 # define __glibc_c99_flexarr_available 1
-#elif __GNUC_PREREQ (2,97)
-/* GCC 2.97 supports C99 flexible array members as an extension,
+#elif __GNUC_PREREQ (2,97) || defined __clang__
+/* GCC 2.97 and clang support C99 flexible array members as an extension,
    even when in C89 mode or compiling C++ (any version).  */
 # define __flexarr     []
 # define __glibc_c99_flexarr_available 1
@@ -194,17 +219,17 @@
 */
 #endif
 
-/* GCC has various useful declarations that can be made with the
-   `__attribute__' syntax.  All of the ways we use this do fine if
-   they are omitted for compilers that don't understand it. */
-#if !defined __GNUC__ || __GNUC__ < 2
+/* GCC and clang have various useful declarations that can be made with
+   the '__attribute__' syntax.  All of the ways we use this do fine if
+   they are omitted for compilers that don't understand it.  */
+#if !(defined __GNUC__ || defined __clang__)
 # define __attribute__(xyz)    /* Ignore */
 #endif
 
 /* At some point during the gcc 2.96 development the `malloc' attribute
    for functions was introduced.  We don't want to use it unconditionally
    (although this would be possible) since it generates warnings.  */
-#if __GNUC_PREREQ (2,96)
+#if __GNUC_PREREQ (2,96) || __glibc_clang_has_attribute (__malloc__)
 # define __attribute_malloc__ __attribute__ ((__malloc__))
 #else
 # define __attribute_malloc__ /* Ignore */
@@ -222,14 +247,14 @@
 /* At some point during the gcc 2.96 development the `pure' attribute
    for functions was introduced.  We don't want to use it unconditionally
    (although this would be possible) since it generates warnings.  */
-#if __GNUC_PREREQ (2,96)
+#if __GNUC_PREREQ (2,96) || __glibc_clang_has_attribute (__pure__)
 # define __attribute_pure__ __attribute__ ((__pure__))
 #else
 # define __attribute_pure__ /* Ignore */
 #endif
 
 /* This declaration tells the compiler that the value is constant.  */
-#if __GNUC_PREREQ (2,5)
+#if __GNUC_PREREQ (2,5) || __glibc_clang_has_attribute (__const__)
 # define __attribute_const__ __attribute__ ((__const__))
 #else
 # define __attribute_const__ /* Ignore */
@@ -238,7 +263,7 @@
 /* At some point during the gcc 3.1 development the `used' attribute
    for functions was introduced.  We don't want to use it unconditionally
    (although this would be possible) since it generates warnings.  */
-#if __GNUC_PREREQ (3,1)
+#if __GNUC_PREREQ (3,1) || __glibc_clang_has_attribute (__used__)
 # define __attribute_used__ __attribute__ ((__used__))
 # define __attribute_noinline__ __attribute__ ((__noinline__))
 #else
@@ -247,7 +272,7 @@
 #endif
 
 /* Since version 3.2, gcc allows marking deprecated functions.  */
-#if __GNUC_PREREQ (3,2)
+#if __GNUC_PREREQ (3,2) || __glibc_clang_has_attribute (__deprecated__)
 # define __attribute_deprecated__ __attribute__ ((__deprecated__))
 #else
 # define __attribute_deprecated__ /* Ignore */
@@ -270,7 +295,7 @@
    If several `format_arg' attributes are given for the same function, in
    gcc-3.0 and older, all but the last one are ignored.  In newer gccs,
    all designated arguments are considered.  */
-#if __GNUC_PREREQ (2,8)
+#if __GNUC_PREREQ (2,8) || __glibc_clang_has_attribute (__format_arg__)
 # define __attribute_format_arg__(x) __attribute__ ((__format_arg__ (x)))
 #else
 # define __attribute_format_arg__(x) /* Ignore */
@@ -280,7 +305,7 @@
    attribute for functions was introduced.  We don't want to use it
    unconditionally (although this would be possible) since it
    generates warnings.  */
-#if __GNUC_PREREQ (2,97)
+#if __GNUC_PREREQ (2,97) || __glibc_clang_has_attribute (__format__)
 # define __attribute_format_strfmon__(a,b) \
   __attribute__ ((__format__ (__strfmon__, a, b)))
 #else
@@ -291,7 +316,7 @@
    must not be NULL.  Do not define __nonnull if it is already defined,
    for portability when this file is used in Gnulib.  */
 #ifndef __nonnull
-# if __GNUC_PREREQ (3,3)
+# if __GNUC_PREREQ (3,3) || __glibc_clang_has_attribute (__nonnull__)
 #  define __nonnull(params) __attribute__ ((__nonnull__ params))
 # else
 #  define __nonnull(params)
@@ -300,7 +325,7 @@
 
 /* If fortification mode, we warn about unused results of certain
    function calls which can lead to problems.  */
-#if __GNUC_PREREQ (3,4)
+#if __GNUC_PREREQ (3,4) || __glibc_clang_has_attribute (__warn_unused_result__)
 # define __attribute_warn_unused_result__ \
    __attribute__ ((__warn_unused_result__))
 # if defined __USE_FORTIFY_LEVEL && __USE_FORTIFY_LEVEL > 0
@@ -314,7 +339,7 @@
 #endif
 
 /* Forces a function to be always inlined.  */
-#if __GNUC_PREREQ (3,2)
+#if __GNUC_PREREQ (3,2) || __glibc_clang_has_attribute (__always_inline__)
 /* The Linux kernel defines __always_inline in stddef.h (283d7573), and
    it conflicts with this definition.  Therefore undefine it first to
    allow either header to be included first.  */
@@ -327,7 +352,7 @@
 
 /* Associate error messages with the source location of the call site rather
    than with the source location inside the function.  */
-#if __GNUC_PREREQ (4,3)
+#if __GNUC_PREREQ (4,3) || __glibc_clang_has_attribute (__artificial__)
 # define __attribute_artificial__ __attribute__ ((__artificial__))
 #else
 # define __attribute_artificial__ /* Ignore */
@@ -370,12 +395,14 @@
    run in pedantic mode if the uses are carefully marked using the
    `__extension__' keyword.  But this is not generally available before
    version 2.8.  */
-#if !__GNUC_PREREQ (2,8)
+#if !(__GNUC_PREREQ (2,8) || defined __clang__)
 # define __extension__         /* Ignore */
 #endif
 
-/* __restrict is known in EGCS 1.2 and above. */
-#if !__GNUC_PREREQ (2,92)
+/* __restrict is known in EGCS 1.2 and above, and in clang.
+   It works also in C++ mode (outside of arrays), but only when spelled
+   as '__restrict', not 'restrict'.  */
+#if !(__GNUC_PREREQ (2,92) || __clang_major__ >= 3)
 # if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
 #  define __restrict   restrict
 # else
@@ -385,8 +412,9 @@
 
 /* ISO C99 also allows to declare arrays as non-overlapping.  The syntax is
      array_name[restrict]
-   GCC 3.1 supports this.  */
-#if __GNUC_PREREQ (3,1) && !defined __GNUG__
+   GCC 3.1 and clang support this.
+   This syntax is not usable in C++ mode.  */
+#if (__GNUC_PREREQ (3,1) || __clang_major__ >= 3) && !defined __cplusplus
 # define __restrict_arr        __restrict
 #else
 # ifdef __GNUC__
@@ -401,7 +429,7 @@
 # endif
 #endif
 
-#if (__GNUC__ >= 3) || (__clang_major__ >= 4)
+#if (__GNUC__ >= 3) || __glibc_clang_has_builtin (__builtin_expect)
 # define __glibc_unlikely(cond)        __builtin_expect ((cond), 0)
 # define __glibc_likely(cond)  __builtin_expect ((cond), 1)
 #else
@@ -417,7 +445,8 @@
 
 #if (!defined _Noreturn \
      && (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) < 201112 \
-     &&  !__GNUC_PREREQ (4,7))
+     &&  !(__GNUC_PREREQ (4,7) \
+           || (3 < __clang_major__ + (5 <= __clang_minor__))))
 # if __GNUC_PREREQ (2,8)
 #  define _Noreturn __attribute__ ((__noreturn__))
 # else
diff --git a/lib/count-one-bits.h b/lib/count-one-bits.h
index 6c5b757..a9e166a 100644
--- a/lib/count-one-bits.h
+++ b/lib/count-one-bits.h
@@ -38,7 +38,8 @@ extern "C" {
    expand to code that computes the number of 1-bits of the local
    variable 'x' of type TYPE (an unsigned integer type) and return it
    from the current function.  */
-#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) \
+    || (__clang_major__ >= 4)
 # define COUNT_ONE_BITS(GCC_BUILTIN, MSC_BUILTIN, TYPE) \
     return GCC_BUILTIN (x)
 #else
diff --git a/lib/dirent.in.h b/lib/dirent.in.h
index 6fa44f0..23c4e05 100644
--- a/lib/dirent.in.h
+++ b/lib/dirent.in.h
@@ -58,7 +58,7 @@ typedef struct gl_directory DIR;
 /* The __attribute__ feature is available in gcc versions 2.5 and later.
    The attribute __pure__ was added in gcc 2.96.  */
 #ifndef _GL_ATTRIBUTE_PURE
-# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
+# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) || defined 
__clang__
 #  define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__))
 # else
 #  define _GL_ATTRIBUTE_PURE /* empty */
diff --git a/lib/fcntl.c b/lib/fcntl.c
index 6b9927e..8cd1531 100644
--- a/lib/fcntl.c
+++ b/lib/fcntl.c
@@ -70,14 +70,14 @@ dupfd (int oldfd, int newfd, int flags)
       return -1;
     }
   if (old_handle == INVALID_HANDLE_VALUE
-      || (mode = setmode (oldfd, O_BINARY)) == -1)
+      || (mode = _setmode (oldfd, O_BINARY)) == -1)
     {
       /* oldfd is not open, or is an unassigned standard file
          descriptor.  */
       errno = EBADF;
       return -1;
     }
-  setmode (oldfd, mode);
+  _setmode (oldfd, mode);
   flags |= mode;
 
   for (;;)
diff --git a/lib/ignore-value.h b/lib/ignore-value.h
index 7a92226..ec3288f 100644
--- a/lib/ignore-value.h
+++ b/lib/ignore-value.h
@@ -39,8 +39,9 @@
    versions 3.4 and newer have __attribute__ ((__warn_unused_result__))
    which may cause unwanted diagnostics in that case.  Use __typeof__
    and __extension__ to work around the problem, if the workaround is
-   known to be needed.  */
-#if 3 < __GNUC__ + (4 <= __GNUC_MINOR__)
+   known to be needed.
+   The workaround is not needed with clang.  */
+#if (3 < __GNUC__ + (4 <= __GNUC_MINOR__)) && !defined __clang__
 # define ignore_value(x) \
     (__extension__ ({ __typeof__ (x) __x = (x); (void) __x; }))
 #else
diff --git a/lib/intprops.h b/lib/intprops.h
index dfbcaae..220f532 100644
--- a/lib/intprops.h
+++ b/lib/intprops.h
@@ -86,6 +86,7 @@
 /* Does the __typeof__ keyword work?  This could be done by
    'configure', but for now it's easier to do it by hand.  */
 #if (2 <= __GNUC__ \
+     || (4 <= __clang_major__) \
      || (1210 <= __IBMC__ && defined __IBM__TYPEOF__) \
      || (0x5110 <= __SUNPRO_C && !__STDC__))
 # define _GL_HAVE___TYPEOF__ 1
@@ -239,7 +240,7 @@
 #endif
 
 /* True if __builtin_add_overflow_p (A, B, C) works, and similarly for
-   __builtin_mul_overflow_p and __builtin_mul_overflow_p.  */
+   __builtin_sub_overflow_p and __builtin_mul_overflow_p.  */
 #define _GL_HAS_BUILTIN_OVERFLOW_P (7 <= __GNUC__)
 
 /* The _GL*_OVERFLOW macros have the same restrictions as the
diff --git a/lib/malloca.h b/lib/malloca.h
index cfcd4de..ccc485a 100644
--- a/lib/malloca.h
+++ b/lib/malloca.h
@@ -89,7 +89,7 @@ extern void freea (void *p);
 /* ------------------- Auxiliary, non-public definitions ------------------- */
 
 /* Determine the alignment of a type at compile time.  */
-#if defined __GNUC__ || defined __IBM__ALIGNOF__
+#if defined __GNUC__ || defined __clang__ || defined __IBM__ALIGNOF__
 # define sa_alignof __alignof__
 #elif defined __cplusplus
   template <class type> struct sa_alignof_helper { char __slot1; type __slot2; 
};
diff --git a/lib/regex.h b/lib/regex.h
index 610f139..306521a 100644
--- a/lib/regex.h
+++ b/lib/regex.h
@@ -612,7 +612,9 @@ extern int re_exec (const char *);
    'configure' might #define 'restrict' to those words, so pick a
    different name.  */
 #ifndef _Restrict_
-# if defined __restrict || 2 < __GNUC__ + (95 <= __GNUC_MINOR__)
+# if defined __restrict \
+     || 2 < __GNUC__ + (95 <= __GNUC_MINOR__) \
+     || __clang_major__ >= 3
 #  define _Restrict_ __restrict
 # elif 199901L <= __STDC_VERSION__ || defined restrict
 #  define _Restrict_ restrict
@@ -620,13 +622,18 @@ extern int re_exec (const char *);
 #  define _Restrict_
 # endif
 #endif
-/* For [restrict], use glibc's __restrict_arr if available.
-   Otherwise, GCC 3.1 (not in C++ mode) and C99 support [restrict].  */
+/* For the ISO C99 syntax
+     array_name[restrict]
+   use glibc's __restrict_arr if available.
+   Otherwise, GCC 3.1 and clang support this syntax (but not in C++ mode).
+   Other ISO C99 compilers support it as well.  */
 #ifndef _Restrict_arr_
 # ifdef __restrict_arr
 #  define _Restrict_arr_ __restrict_arr
-# elif ((199901L <= __STDC_VERSION__ || 3 < __GNUC__ + (1 <= __GNUC_MINOR__)) \
-        && !defined __GNUG__)
+# elif ((199901L <= __STDC_VERSION__ \
+         || 3 < __GNUC__ + (1 <= __GNUC_MINOR__) \
+         || __clang_major__ >= 3) \
+        && !defined __cplusplus)
 #  define _Restrict_arr_ _Restrict_
 # else
 #  define _Restrict_arr_
diff --git a/lib/regex_internal.h b/lib/regex_internal.h
index f6ebfb0..9a0c2ed 100644
--- a/lib/regex_internal.h
+++ b/lib/regex_internal.h
@@ -841,10 +841,10 @@ re_string_elem_size_at (const re_string_t *pstr, Idx idx)
 #endif /* RE_ENABLE_I18N */
 
 #ifndef FALLTHROUGH
-# if __GNUC__ < 7
-#  define FALLTHROUGH ((void) 0)
-# else
+# if (__GNUC__ >= 7) || (__clang_major__ >= 10)
 #  define FALLTHROUGH __attribute__ ((__fallthrough__))
+# else
+#  define FALLTHROUGH ((void) 0)
 # endif
 #endif
 
diff --git a/lib/stdalign.in.h b/lib/stdalign.in.h
index cd786be..e4809b4 100644
--- a/lib/stdalign.in.h
+++ b/lib/stdalign.in.h
@@ -34,11 +34,12 @@
    requirement of a structure member (i.e., slot or field) that is of
    type TYPE, as an integer constant expression.
 
-   This differs from GCC's __alignof__ operator, which can yield a
-   better-performing alignment for an object of that type.  For
-   example, on x86 with GCC, __alignof__ (double) and __alignof__
-   (long long) are 8, whereas alignof (double) and alignof (long long)
-   are 4 unless the option '-malign-double' is used.
+   This differs from GCC's and clang's __alignof__ operator, which can
+   yield a better-performing alignment for an object of that type.  For
+   example, on x86 with GCC and on Linux/x86 with clang,
+   __alignof__ (double) and __alignof__ (long long) are 8, whereas
+   alignof (double) and alignof (long long) are 4 unless the option
+   '-malign-double' is used.
 
    The result cannot be used as a value for an 'enum' constant, if you
    want to be portable to HP-UX 10.20 cc and AIX 3.2.5 xlc.
@@ -55,7 +56,8 @@
 /* GCC releases before GCC 4.9 had a bug in _Alignof.  See GCC bug 52023
    <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52023>.  */
 #if (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112 \
-     || (defined __GNUC__ && __GNUC__ < 4 + (__GNUC_MINOR__ < 9)))
+     || (defined __GNUC__ && __GNUC__ < 4 + (__GNUC_MINOR__ < 9) \
+         && !defined __clang__))
 # ifdef __cplusplus
 #  if 201103 <= __cplusplus
 #   define _Alignof(type) alignof (type)
@@ -102,8 +104,9 @@
 #  define _Alignas(a) alignas (a)
 # elif ((defined __APPLE__ && defined __MACH__                  \
          ? 4 < __GNUC__ + (1 <= __GNUC_MINOR__)                 \
-         : __GNUC__ && !defined __ibmxl__) \
-        || (__ia64 && (61200 <= __HP_cc || 61200 <= __HP_aCC)) \
+         : __GNUC__ && !defined __ibmxl__)                      \
+        || (4 <= __clang_major__)                               \
+        || (__ia64 && (61200 <= __HP_cc || 61200 <= __HP_aCC))  \
         || __ICC || 0x590 <= __SUNPRO_C || 0x0600 <= __xlC__)
 #  define _Alignas(a) __attribute__ ((__aligned__ (a)))
 # elif 1300 <= _MSC_VER
diff --git a/lib/stddef.in.h b/lib/stddef.in.h
index 2e50a1f..87b46d5 100644
--- a/lib/stddef.in.h
+++ b/lib/stddef.in.h
@@ -97,7 +97,7 @@
    and the C11 standard allows this.  Work around this problem by
    using __alignof__ (which returns 8 for double) rather than _Alignof
    (which returns 4), and align each union member accordingly.  */
-#   ifdef __GNUC__
+#   if defined __GNUC__ || (__clang_major__ >= 4)
 #    define _GL_STDDEF_ALIGNAS(type) \
        __attribute__ ((__aligned__ (__alignof__ (type))))
 #   else
diff --git a/lib/stdint.in.h b/lib/stdint.in.h
index 994c0c7..63fa1aa 100644
--- a/lib/stdint.in.h
+++ b/lib/stdint.in.h
@@ -302,12 +302,11 @@ typedef gl_uint_fast32_t gl_uint_fast16_t;
 /* kLIBC's <stdint.h> defines _INTPTR_T_DECLARED and needs its own
    definitions of intptr_t and uintptr_t (which use int and unsigned)
    to avoid clashes with declarations of system functions like sbrk.
-   Similarly, mingw 5.22 <crtdefs.h> defines _INTPTR_T_DEFINED and
-   _UINTPTR_T_DEFINED and needs its own definitions of intptr_t and
+   Similarly, MinGW WSL-5.4.1 <stdint.h> needs its own intptr_t and
    uintptr_t to avoid conflicting declarations of system functions like
    _findclose in <io.h>.  */
 # if !((defined __KLIBC__ && defined _INTPTR_T_DECLARED) \
-       || (defined __MINGW32__ && defined _INTPTR_T_DEFINED && defined 
_UINTPTR_T_DEFINED))
+       || defined __MINGW32__)
 #  undef intptr_t
 #  undef uintptr_t
 #  ifdef _WIN64
diff --git a/lib/stdio.in.h b/lib/stdio.in.h
index 6c338dd..cbebc84 100644
--- a/lib/stdio.in.h
+++ b/lib/stdio.in.h
@@ -63,7 +63,7 @@
    gnulib and libintl do '#define printf __printf__' when they override
    the 'printf' function.  */
 #ifndef _GL_ATTRIBUTE_FORMAT
-# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
+# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) || defined 
__clang__
 #  define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec))
 # else
 #  define _GL_ATTRIBUTE_FORMAT(spec) /* empty */
diff --git a/lib/stdlib.in.h b/lib/stdlib.in.h
index 59f9e6c..5c598a2 100644
--- a/lib/stdlib.in.h
+++ b/lib/stdlib.in.h
@@ -102,7 +102,7 @@ struct random_data
 /* The __attribute__ feature is available in gcc versions 2.5 and later.
    The attribute __pure__ was added in gcc 2.96.  */
 #ifndef _GL_ATTRIBUTE_PURE
-# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
+# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) || defined 
__clang__
 #  define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__))
 # else
 #  define _GL_ATTRIBUTE_PURE /* empty */
diff --git a/lib/string.in.h b/lib/string.in.h
index aa98027..c0c1a54 100644
--- a/lib/string.in.h
+++ b/lib/string.in.h
@@ -55,7 +55,7 @@
 /* The __attribute__ feature is available in gcc versions 2.5 and later.
    The attribute __pure__ was added in gcc 2.96.  */
 #ifndef _GL_ATTRIBUTE_PURE
-# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
+# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) || defined 
__clang__
 #  define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__))
 # else
 #  define _GL_ATTRIBUTE_PURE /* empty */
@@ -329,7 +329,8 @@ _GL_WARN_ON_USE (stpncpy, "stpncpy is unportable - "
    GB18030 and the character to be searched is a digit.  */
 # undef strchr
 /* Assume strchr is always declared.  */
-_GL_WARN_ON_USE_CXX (strchr, const char *, (const char *, int),
+_GL_WARN_ON_USE_CXX (strchr,
+                     const char *, char *, (const char *, int),
                      "strchr cannot work correctly on character strings "
                      "in some multibyte locales - "
                      "use mbschr if you care about internationalization");
@@ -524,7 +525,8 @@ _GL_CXXALIASWARN (strpbrk);
    locale encoding is GB18030 and one of the characters to be searched is a
    digit.  */
 #  undef strpbrk
-_GL_WARN_ON_USE_CXX (strpbrk, const char *, (const char *, const char *),
+_GL_WARN_ON_USE_CXX (strpbrk,
+                     const char *, char *, (const char *, const char *),
                      "strpbrk cannot work correctly on character strings "
                      "in multibyte locales - "
                      "use mbspbrk if you care about internationalization");
@@ -532,7 +534,8 @@ _GL_WARN_ON_USE_CXX (strpbrk, const char *, (const char *, 
const char *),
 #elif defined GNULIB_POSIXCHECK
 # undef strpbrk
 # if HAVE_RAW_DECL_STRPBRK
-_GL_WARN_ON_USE_CXX (strpbrk, const char *, (const char *, const char *),
+_GL_WARN_ON_USE_CXX (strpbrk,
+                     const char *, char *, (const char *, const char *),
                      "strpbrk is unportable - "
                      "use gnulib module strpbrk for portability");
 # endif
@@ -553,7 +556,8 @@ _GL_WARN_ON_USE (strspn, "strspn cannot work correctly on 
character strings "
    GB18030 and the character to be searched is a digit.  */
 # undef strrchr
 /* Assume strrchr is always declared.  */
-_GL_WARN_ON_USE_CXX (strrchr, const char *, (const char *, int),
+_GL_WARN_ON_USE_CXX (strrchr,
+                     const char *, char *, (const char *, int),
                      "strrchr cannot work correctly on character strings "
                      "in some multibyte locales - "
                      "use mbsrchr if you care about internationalization");
diff --git a/lib/verify.h b/lib/verify.h
index f109761..58172f3 100644
--- a/lib/verify.h
+++ b/lib/verify.h
@@ -233,6 +233,13 @@ template <int w>
 
 /* @assert.h omit start@  */
 
+#if defined __has_builtin
+/* <https://clang.llvm.org/docs/LanguageExtensions.html#builtin-functions> */
+# define _GL_HAS_BUILTIN_ASSUME __has_builtin (__builtin_assume)
+#else
+# define _GL_HAS_BUILTIN_ASSUME 0
+#endif
+
 #if 3 < __GNUC__ + (3 < __GNUC_MINOR__ + (4 <= __GNUC_PATCHLEVEL__))
 # define _GL_HAS_BUILTIN_TRAP 1
 #elif defined __has_builtin
@@ -294,7 +301,9 @@ template <int w>
    diagnostics, performance can suffer if R uses hard-to-optimize
    features such as function calls not inlined by the compiler.  */
 
-#if _GL_HAS_BUILTIN_UNREACHABLE
+#if _GL_HAS_BUILTIN_ASSUME
+# define assume(R) __builtin_assume (R)
+#elif _GL_HAS_BUILTIN_UNREACHABLE
 # define assume(R) ((R) ? (void) 0 : __builtin_unreachable ())
 #elif 1200 <= _MSC_VER
 # define assume(R) __assume (R)
diff --git a/lib/warn-on-use.h b/lib/warn-on-use.h
index 23c10fd..3f728d1 100644
--- a/lib/warn-on-use.h
+++ b/lib/warn-on-use.h
@@ -87,6 +87,13 @@
 extern __typeof__ (function) function __attribute__ ((__warning__ (message)))
 #  define _GL_WARN_ON_USE_ATTRIBUTE(message) \
   __attribute__ ((__warning__ (message)))
+# elif __clang_major__ >= 4
+/* Another compiler attribute is available in clang.  */
+#  define _GL_WARN_ON_USE(function, message) \
+extern __typeof__ (function) function \
+  __attribute__ ((__diagnose_if__ (1, message, "warning")))
+#  define _GL_WARN_ON_USE_ATTRIBUTE(message) \
+  __attribute__ ((__diagnose_if__ (1, message, "warning")))
 # elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING
 /* Verify the existence of the function.  */
 #  define _GL_WARN_ON_USE(function, message) \
@@ -99,27 +106,33 @@ _GL_WARN_EXTERN_C int _gl_warn_on_use
 # endif
 #endif
 
-/* _GL_WARN_ON_USE_CXX (function, rettype, parameters_and_attributes, "string")
-   is like _GL_WARN_ON_USE (function, "string"), except that in C++ mode the
+/* _GL_WARN_ON_USE_CXX (function, rettype_gcc, rettype_clang, 
parameters_and_attributes, "message")
+   is like _GL_WARN_ON_USE (function, "message"), except that in C++ mode the
    function is declared with the given prototype, consisting of return type,
    parameters, and attributes.
    This variant is useful for overloaded functions in C++. _GL_WARN_ON_USE does
    not work in this case.  */
 #ifndef _GL_WARN_ON_USE_CXX
 # if !defined __cplusplus
-#  define _GL_WARN_ON_USE_CXX(function,rettype,parameters_and_attributes,msg) \
+#  define 
_GL_WARN_ON_USE_CXX(function,rettype_gcc,rettype_clang,parameters_and_attributes,msg)
 \
      _GL_WARN_ON_USE (function, msg)
 # else
 #  if 4 < __GNUC__ || (__GNUC__ == 4 && 3 <= __GNUC_MINOR__)
-#   define _GL_WARN_ON_USE_CXX(function,rettype,parameters_and_attributes,msg) 
\
-extern rettype function parameters_and_attributes \
-     __attribute__ ((__warning__ (msg)))
+/* A compiler attribute is available in gcc versions 4.3.0 and later.  */
+#   define 
_GL_WARN_ON_USE_CXX(function,rettype_gcc,rettype_clang,parameters_and_attributes,msg)
 \
+extern rettype_gcc function parameters_and_attributes \
+  __attribute__ ((__warning__ (msg)))
+#  elif __clang_major__ >= 4
+/* Another compiler attribute is available in clang.  */
+#   define 
_GL_WARN_ON_USE_CXX(function,rettype_gcc,rettype_clang,parameters_and_attributes,msg)
 \
+extern rettype_clang function parameters_and_attributes \
+  __attribute__ ((__diagnose_if__ (1, msg, "warning")))
 #  elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING
 /* Verify the existence of the function.  */
-#   define _GL_WARN_ON_USE_CXX(function,rettype,parameters_and_attributes,msg) 
\
-extern rettype function parameters_and_attributes
+#   define 
_GL_WARN_ON_USE_CXX(function,rettype_gcc,rettype_clang,parameters_and_attributes,msg)
 \
+extern rettype_gcc function parameters_and_attributes
 #  else /* Unsupported.  */
-#   define _GL_WARN_ON_USE_CXX(function,rettype,parameters_and_attributes,msg) 
\
+#   define 
_GL_WARN_ON_USE_CXX(function,rettype_gcc,rettype_clang,parameters_and_attributes,msg)
 \
 _GL_WARN_EXTERN_C int _gl_warn_on_use
 #  endif
 # endif
diff --git a/lisp/allout-widgets.el b/lisp/allout-widgets.el
index 2a8dced..03fc3e2 100644
--- a/lisp/allout-widgets.el
+++ b/lisp/allout-widgets.el
@@ -207,6 +207,7 @@ See `allout-widgets-mode' for allout widgets mode features."
   :version "24.1"
   :type 'plist
   :group 'allout-widgets)
+(make-obsolete-variable 'allout-widgets-item-image-properties-xemacs nil 
"28.1")
 ;;;_  . Developer
 ;;;_   = allout-widgets-run-unit-tests-on-load
 (defcustom allout-widgets-run-unit-tests-on-load nil
@@ -323,8 +324,7 @@ In addition, you can invoked `allout-widgets-mode' 
allout-mode
 buffers where this is set to enable and disable widget
 enhancements, directly.")
 ;;;###autoload
-(put 'allout-widgets-mode-inhibit 'safe-local-variable
-     (if (fboundp 'booleanp) 'booleanp (lambda (x) (member x '(t nil)))))
+(put 'allout-widgets-mode-inhibit 'safe-local-variable 'booleanp)
 (make-variable-buffer-local 'allout-widgets-mode-inhibit)
 ;;;_    = allout-inhibit-body-modification-hook
 (defvar allout-inhibit-body-modification-hook nil
@@ -1510,8 +1510,7 @@ recursive operation."
   ;; the actual location of the item text:
   :location       'allout-item-location
 
-  :button-keymap  allout-item-icon-keymap ; XEmacs
-  :keymap         allout-item-icon-keymap        ; Emacs
+  :keymap         allout-item-icon-keymap
 
   ;; Element regions:
   :guides-span         nil
@@ -2329,15 +2328,13 @@ We use a caching strategy, so the caller doesn't need 
to do so."
         (allout-widgets-copy-list (cadr got))
       (while (and types (not got))
         (setq got
-              (allout-find-image
+              (find-image
                (list (append (list :type (car types)
                                    :file (concat use-dir
                                                  (symbol-name name)
                                                  "." (symbol-name
                                                       (car types))))
-                             (if (featurep 'xemacs)
-                                 allout-widgets-item-image-properties-xemacs
-                               allout-widgets-item-image-properties-emacs)
+                             allout-widgets-item-image-properties-emacs
                              ))))
         (setq types (cdr types)))
       (if got
@@ -2358,11 +2355,7 @@ We use a caching strategy, so the caller doesn't need to 
do so."
          'frame-property)
         (t nil)))
 ;;;_  > allout-find-image (specs)
-(defalias 'allout-find-image
-  (if (fboundp 'find-image)
-      'find-image
-    nil)                                ; aka, not-yet-implemented for xemacs.
-)
+(define-obsolete-function-alias 'allout-find-image #'find-image "28.1")
 ;;;_  > allout-widgets-copy-list (list)
 (defun allout-widgets-copy-list (list)
   ;; duplicated from cl.el 'copy-list' as of 2008-08-17
diff --git a/lisp/allout.el b/lisp/allout.el
index dedad45..05d9153 100644
--- a/lisp/allout.el
+++ b/lisp/allout.el
@@ -410,8 +410,7 @@ where auto-fill occurs."
   :group 'allout)
 (make-variable-buffer-local 'allout-use-hanging-indents)
 ;;;###autoload
-(put 'allout-use-hanging-indents 'safe-local-variable
-     (if (fboundp 'booleanp) 'booleanp (lambda (x) (member x '(t nil)))))
+(put 'allout-use-hanging-indents 'safe-local-variable 'booleanp)
 ;;;_  = allout-reindent-bodies
 (defcustom allout-reindent-bodies (if allout-use-hanging-indents
                                    'text)
@@ -440,8 +439,7 @@ just the header."
   :group 'allout)
 (make-variable-buffer-local 'allout-show-bodies)
 ;;;###autoload
-(put 'allout-show-bodies 'safe-local-variable
-     (if (fboundp 'booleanp) 'booleanp (lambda (x) (member x '(t nil)))))
+(put 'allout-show-bodies 'safe-local-variable 'booleanp)
 
 ;;;_  = allout-beginning-of-line-cycles
 (defcustom allout-beginning-of-line-cycles t
@@ -662,8 +660,7 @@ are always respected by the topic maneuvering functions."
   :group 'allout)
 (make-variable-buffer-local 'allout-old-style-prefixes)
 ;;;###autoload
-(put 'allout-old-style-prefixes 'safe-local-variable
-     (if (fboundp 'booleanp) 'booleanp (lambda (x) (member x '(t nil)))))
+(put 'allout-old-style-prefixes 'safe-local-variable 'booleanp)
 ;;;_  = allout-stylish-prefixes -- alternating bullets
 (defcustom allout-stylish-prefixes t
   "Do fancy stuff with topic prefix bullets according to level, etc.
@@ -711,8 +708,7 @@ is non-nil."
   :group 'allout)
 (make-variable-buffer-local 'allout-stylish-prefixes)
 ;;;###autoload
-(put 'allout-stylish-prefixes 'safe-local-variable
-     (if (fboundp 'booleanp) 'booleanp (lambda (x) (member x '(t nil)))))
+(put 'allout-stylish-prefixes 'safe-local-variable 'booleanp)
 
 ;;;_  = allout-numbered-bullet
 (defcustom allout-numbered-bullet "#"
@@ -726,10 +722,7 @@ disables numbering maintenance."
   :group 'allout)
 (make-variable-buffer-local 'allout-numbered-bullet)
 ;;;###autoload
-(put 'allout-numbered-bullet 'safe-local-variable
-     (if (fboundp 'string-or-null-p)
-         'string-or-null-p
-       (lambda (x) (or (stringp x) (null x)))))
+(put 'allout-numbered-bullet 'safe-local-variable 'string-or-null-p)
 ;;;_  = allout-file-xref-bullet
 (defcustom allout-file-xref-bullet "@"
   "Bullet signifying file cross-references, for `allout-resolve-xref'.
@@ -738,10 +731,7 @@ Set this var to the bullet you want to use for file 
cross-references."
   :type '(choice (const nil) string)
   :group 'allout)
 ;;;###autoload
-(put 'allout-file-xref-bullet 'safe-local-variable
-     (if (fboundp 'string-or-null-p)
-         'string-or-null-p
-       (lambda (x) (or (stringp x) (null x)))))
+(put 'allout-file-xref-bullet 'safe-local-variable 'string-or-null-p)
 ;;;_  = allout-presentation-padding
 (defcustom allout-presentation-padding 2
   "Presentation-format white-space padding factor, for greater indent."
@@ -2484,20 +2474,16 @@ Outermost is first."
              (allout-back-to-current-heading)
              (allout-end-of-current-line))
             (t
-             (if (not (allout-mark-active-p))
+             (if (not mark-active)
                  (push-mark))
              (allout-end-of-entry))))))
+
 ;;;_   > allout-mark-active-p ()
 (defun allout-mark-active-p ()
   "True if the mark is currently or always active."
-  ;; `(cond (boundp...))' (or `(if ...)') invokes special byte-compiler
-  ;; provisions, at least in GNU Emacs to prevent warnings about lack of,
-  ;; eg, region-active-p.
-  (cond ((boundp 'mark-active)
-         mark-active)
-        ((fboundp 'region-active-p)
-         (region-active-p))
-        (t)))
+  (declare (obsolete nil "28.1"))
+  mark-active)
+
 ;;;_   > allout-next-heading ()
 (defsubst allout-next-heading ()
   "Move to the heading for the topic (possibly invisible) after this one.
@@ -5452,11 +5438,9 @@ header and body.  The elements of that list are:
                                 (cdr format)))))))
       ;; Put the list with first at front, to last at back:
       (nreverse result))))
-;;;_   > allout-region-active-p ()
-(defmacro allout-region-active-p ()
-  (cond ((fboundp 'use-region-p) '(use-region-p))
-        ((fboundp 'region-active-p) '(region-active-p))
-        (t 'mark-active)))
+
+(define-obsolete-function-alias 'allout-region-active-p 'region-active-p 
"28.1")
+
 ;;_   > allout-process-exposed (&optional func from to frombuf
 ;;;                                        tobuf format)
 (defun allout-process-exposed (&optional func from to frombuf tobuf
@@ -5489,7 +5473,7 @@ Defaults:
                                        ; defaulting if necessary:
   (if (not func) (setq func 'allout-insert-listified))
   (if (not (and from to))
-      (if (allout-region-active-p)
+      (if (region-active-p)
          (setq from (region-beginning) to (region-end))
        (setq from (point-min) to (point-max))))
   (if frombuf
diff --git a/lisp/apropos.el b/lisp/apropos.el
index 2566d44..6d8c784 100644
--- a/lisp/apropos.el
+++ b/lisp/apropos.el
@@ -543,6 +543,20 @@ will be buffer-local when set."
                                  (and (local-variable-if-set-p symbol)
                                       (get symbol 'variable-documentation)))))
 
+;;;###autoload
+(defun apropos-function (pattern)
+  "Show functions that match PATTERN.
+
+PATTERN can be a word, a list of words (separated by spaces),
+or a regexp (using some regexp special characters).  If it is a word,
+search for matches for that word as a substring.  If it is a list of words,
+search for matches for any two (or more) of those words.
+
+This is the same as running `apropos-command' with a \\[universal-argument] 
prefix,
+or a non-nil `apropos-do-all' argument."
+  (interactive (list (apropos-read-pattern "function")))
+  (apropos-command pattern t))
+
 ;; For auld lang syne:
 ;;;###autoload
 (defalias 'command-apropos 'apropos-command)
diff --git a/lisp/bookmark.el b/lisp/bookmark.el
index fb293ad..36a361c 100644
--- a/lisp/bookmark.el
+++ b/lisp/bookmark.el
@@ -200,6 +200,7 @@ A non-nil value may result in truncated bookmark names."
     (define-key map "f" 'bookmark-insert-location) ;"f"ind
     (define-key map "r" 'bookmark-rename)
     (define-key map "d" 'bookmark-delete)
+    (define-key map "D" 'bookmark-delete-all)
     (define-key map "l" 'bookmark-load)
     (define-key map "w" 'bookmark-write)
     (define-key map "s" 'bookmark-save)
@@ -1374,6 +1375,23 @@ probably because we were called from there."
     (bookmark-save)))
 
 
+;;;###autoload
+(defun bookmark-delete-all (&optional no-confirm)
+  "Permanently delete all bookmarks.
+If optional argument NO-CONFIRM is non-nil, don't ask for
+confirmation."
+  (interactive "P")
+  (when (or no-confirm
+            (yes-or-no-p "Permanently delete all bookmarks? "))
+    (bookmark-maybe-load-default-file)
+    (setq bookmark-alist-modification-count
+          (+ bookmark-alist-modification-count (length bookmark-alist)))
+    (setq bookmark-alist nil)
+    (bookmark-bmenu-surreptitiously-rebuild-list)
+    (when (bookmark-time-to-save-p)
+      (bookmark-save))))
+
+
 (defun bookmark-time-to-save-p (&optional final-time)
   "Return t if it is time to save bookmarks to disk, nil otherwise.
 Optional argument FINAL-TIME means this is being called when Emacs
@@ -1600,12 +1618,15 @@ unique numeric suffixes \"<2>\", \"<3>\", etc."
     (define-key map "\C-d" 'bookmark-bmenu-delete-backwards)
     (define-key map "x" 'bookmark-bmenu-execute-deletions)
     (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)
     (define-key map "m" 'bookmark-bmenu-mark)
+    (define-key map "M" 'bookmark-bmenu-mark-all)
     (define-key map "l" 'bookmark-bmenu-load)
     (define-key map "r" 'bookmark-bmenu-rename)
     (define-key map "R" 'bookmark-bmenu-relocate)
@@ -1627,8 +1648,10 @@ unique numeric suffixes \"<2>\", \"<3>\", etc."
     ["Select Marked Bookmarks" bookmark-bmenu-select t]
     "---"
     ["Mark Bookmark" bookmark-bmenu-mark t]
+    ["Mark all Bookmarks" bookmark-bmenu-mark-all t]
     ["Unmark Bookmark" bookmark-bmenu-unmark  t]
     ["Unmark Backwards" bookmark-bmenu-backup-unmark  t]
+    ["Unmark all Bookmarks" bookmark-bmenu-unmark-all  t]
     ["Toggle Display of Filenames" bookmark-bmenu-toggle-filenames  t]
     ["Display Location of Bookmark" bookmark-bmenu-locate  t]
     "---"
@@ -1636,6 +1659,7 @@ unique numeric suffixes \"<2>\", \"<3>\", etc."
      ["Rename Bookmark" bookmark-bmenu-rename  t]
      ["Relocate Bookmark's File" bookmark-bmenu-relocate  t]
      ["Mark Bookmark for Deletion" bookmark-bmenu-delete  t]
+     ["Mark all Bookmarks for Deletion" bookmark-bmenu-delete-all  t]
      ["Delete Marked Bookmarks" bookmark-bmenu-execute-deletions  t])
     ("Annotations"
      ["Show Annotation for Current Bookmark" bookmark-bmenu-show-annotation  t]
@@ -1761,6 +1785,7 @@ Letters do not insert themselves; instead, they are 
commands.
 Bookmark names preceded by a \"*\" have annotations.
 \\<bookmark-bmenu-mode-map>
 \\[bookmark-bmenu-mark] -- mark bookmark to be displayed.
+\\[bookmark-bmenu-mark-all] -- mark all listed bookmarks to be displayed.
 \\[bookmark-bmenu-select] -- select bookmark of line point is on.
   Also show bookmarks marked using m in other windows.
 \\[bookmark-bmenu-toggle-filenames] -- toggle displaying of filenames (they 
may obscure long bookmark names).
@@ -1777,13 +1802,15 @@ Bookmark names preceded by a \"*\" have annotations.
 \\[bookmark-bmenu-relocate] -- relocate this bookmark's file (prompts for new 
file).
 \\[bookmark-bmenu-delete] -- mark this bookmark to be deleted, and move down.
 \\[bookmark-bmenu-delete-backwards] -- mark this bookmark to be deleted, and 
move up.
-\\[bookmark-bmenu-execute-deletions] -- delete bookmarks marked with 
`\\[bookmark-bmenu-delete]'.
+\\[bookmark-bmenu-delete-all] -- mark all listed bookmarks as to be deleted.
+\\[bookmark-bmenu-execute-deletions] -- delete bookmarks marked with 
`\\[bookmark-bmenu-delete]' or `\\[bookmark-bmenu-delete-all]'.
 \\[bookmark-bmenu-save] -- save the current bookmark list in the default file.
   With a prefix arg, prompts for a file to save in.
 \\[bookmark-bmenu-load] -- load in a file of bookmarks (prompts for file.)
 \\[bookmark-bmenu-unmark] -- remove all kinds of marks from current line.
   With prefix argument, also move up one line.
 \\[bookmark-bmenu-backup-unmark] -- back up a line and remove marks.
+\\[bookmark-bmenu-unmark-all] -- remove all kinds of marks from all listed 
bookmarks.
 \\[bookmark-bmenu-show-annotation] -- show the annotation, if it exists, for 
the current bookmark
   in another buffer.
 \\[bookmark-bmenu-show-all-annotations] -- show the annotations of all 
bookmarks in another buffer.
@@ -1950,9 +1977,23 @@ If the annotation does not exist, do nothing."
      (bookmark-bmenu-ensure-position))))
 
 
+(defun bookmark-bmenu-mark-all ()
+  "Mark all listed bookmarks to be displayed by 
\\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-select]."
+  (interactive)
+  (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))))))
+
+
 (defun bookmark-bmenu-select ()
   "Select this line's bookmark; also display bookmarks marked with `>'.
-You can mark bookmarks with the 
\\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-mark] command."
+You can mark bookmarks with the 
\\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-mark] or 
\\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-mark-all] commands."
   (interactive)
   (let ((bmrk (bookmark-bmenu-bookmark))
         (menu (current-buffer))
@@ -2121,6 +2162,20 @@ Optional BACKUP means move up."
   (bookmark-bmenu-ensure-position))
 
 
+(defun bookmark-bmenu-unmark-all ()
+  "Cancel all requested operations on all listed bookmarks."
+  (interactive)
+  (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))))))
+
+
 (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]."
@@ -2146,6 +2201,22 @@ To carry out the deletions that you've marked, use 
\\<bookmark-bmenu-mode-map>\\
   (bookmark-bmenu-ensure-position))
 
 
+(defun bookmark-bmenu-delete-all ()
+  "Mark all listed bookmarks as to be deleted.
+To remove all deletion marks, use 
\\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-unmark-all].
+To carry out the deletions that you've marked, use 
\\<bookmark-bmenu-mode-map>\\[bookmark-bmenu-execute-deletions]."
+  (interactive)
+  (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))))))
+
+
 (defun bookmark-bmenu-execute-deletions ()
   "Delete bookmarks flagged `D'."
   (interactive)
@@ -2305,6 +2376,9 @@ strings returned are not."
     (bindings--define-key map [delete]
       '(menu-item "Delete Bookmark..." bookmark-delete
                  :help "Delete a bookmark from the bookmark list"))
+    (bindings--define-key map [delete-all]
+      '(menu-item "Delete all Bookmarks..." bookmark-delete-all
+                 :help "Delete all bookmarks from the bookmark list"))
     (bindings--define-key map [rename]
       '(menu-item "Rename Bookmark..." bookmark-rename
                  :help "Change the name of a bookmark"))
diff --git a/lisp/calc/calc-yank.el b/lisp/calc/calc-yank.el
index f5150ca..690aaf2 100644
--- a/lisp/calc/calc-yank.el
+++ b/lisp/calc/calc-yank.el
@@ -150,34 +150,16 @@
 ;; otherwise it just parses the yanked string.
 ;; Modified to use Emacs 19 extended concept of kill-ring. -- daveg 12/15/96
 ;;;###autoload
-(defun calc-yank (radix)
-  "Yank a value into the Calculator buffer.
-
-Valid numeric prefixes for RADIX: 0, 2, 6, 8
-No radix notation is prepended for any other numeric prefix.
-
-If RADIX is 2, prepend \"2#\"  - Binary.
-If RADIX is 8, prepend \"8#\"  - Octal.
-If RADIX is 0, prepend \"10#\" - Decimal.
-If RADIX is 6, prepend \"16#\" - Hexadecimal.
+(defun calc-yank-internal (radix thing-raw)
+  "Internal common implementation for yank functions.
 
-If RADIX is a non-nil list (created using \\[universal-argument]), the user
-will be prompted to enter the radix in the minibuffer.
-
-If RADIX is nil or if the yanked string already has a calc radix prefix, the
-yanked string will be passed on directly to the Calculator buffer without any
-alteration."
-  (interactive "P")
+This function is used by both `calc-yank' and `calc-yank-mouse-primary'."
   (calc-wrapper
    (calc-pop-push-record-list
     0 "yank"
     (let* (radix-num
            radix-notation
            valid-num-regexp
-           (thing-raw
-            (if (fboundp 'current-kill)
-                (current-kill 0 t)
-              (car kill-ring-yank-pointer)))
            (thing
             (if (or (null radix)
                     ;; Match examples: -2#10, 10\n(10#10,01)
@@ -232,6 +214,38 @@ alteration."
                       val))
                 val))))))))
 
+;;;###autoload
+(defun calc-yank-mouse-primary (radix)
+  "Yank the current primary selection into the Calculator buffer.
+See `calc-yank' for details about RADIX."
+  (interactive "P")
+  (if (or select-enable-primary
+          select-enable-clipboard)
+      (calc-yank-internal radix (gui-get-primary-selection))
+    ;; Yank from the kill ring.
+    (calc-yank radix)))
+
+;;;###autoload
+(defun calc-yank (radix)
+  "Yank a value into the Calculator buffer.
+
+Valid numeric prefixes for RADIX: 0, 2, 6, 8
+No radix notation is prepended for any other numeric prefix.
+
+If RADIX is 2, prepend \"2#\"  - Binary.
+If RADIX is 8, prepend \"8#\"  - Octal.
+If RADIX is 0, prepend \"10#\" - Decimal.
+If RADIX is 6, prepend \"16#\" - Hexadecimal.
+
+If RADIX is a non-nil list (created using \\[universal-argument]), the user
+will be prompted to enter the radix in the minibuffer.
+
+If RADIX is nil or if the yanked string already has a calc radix prefix, the
+yanked string will be passed on directly to the Calculator buffer without any
+alteration."
+  (interactive "P")
+  (calc-yank-internal radix (current-kill 0 t)))
+
 ;;; The Calc set- and get-register commands are modified versions of functions
 ;;; in register.el
 
diff --git a/lisp/calc/calc.el b/lisp/calc/calc.el
index 09b4962..fb1287b 100644
--- a/lisp/calc/calc.el
+++ b/lisp/calc/calc.el
@@ -1087,8 +1087,26 @@ Used by `calc-user-invocation'.")
          (append (where-is-internal 'delete-backward-char global-map)
                  (where-is-internal 'backward-delete-char global-map)
                  (where-is-internal 'backward-delete-char-untabify global-map)
-                 '("\C-d"))
-       '("\177" "\C-d")))
+                 '("\177"))
+       '("\177")))
+
+(mapc (lambda (x)
+        (ignore-errors
+          (define-key calc-digit-map x 'calcDigit-delchar)
+          (define-key calc-mode-map x 'calc-pop)
+          (define-key calc-mode-map
+            (if (and (vectorp x) (featurep 'xemacs))
+                (if (= (length x) 1)
+                    (vector (if (consp (aref x 0))
+                                (cons 'meta (aref x 0))
+                              (list 'meta (aref x 0))))
+                  "\e\C-d")
+              (vconcat "\e" x))
+            'calc-pop-above)))
+      (if calc-scan-for-dels
+          (append (where-is-internal 'delete-forward-char global-map)
+                  '("\C-d"))
+        '("\C-d")))
 
 (defvar calc-dispatch-map
   (let ((map (make-keymap)))
@@ -2343,7 +2361,6 @@ the United States."
 
 (defun calcDigit-key ()
   (interactive)
-  (goto-char (point-max))
   (if (or (and (memq last-command-event '(?+ ?-))
               (> (buffer-size) 0)
               (/= (preceding-char) ?e))
@@ -2386,8 +2403,7 @@ the United States."
            (delete-char 1))
        (if (looking-at "-")
            (delete-char 1)
-         (insert "-")))
-      (goto-char (point-max)))
+         (insert "-"))))
      ((eq last-command-event ?p)
       (if (or (calc-minibuffer-contains ".*\\+/-.*")
              (calc-minibuffer-contains ".*mod.*")
@@ -2440,17 +2456,9 @@ the United States."
   (setq calc-prev-prev-char calc-prev-char
        calc-prev-char last-command-event))
 
-
 (defun calcDigit-backspace ()
   (interactive)
-  (goto-char (point-max))
-  (cond ((calc-minibuffer-contains ".* \\+/- \\'")
-        (backward-delete-char 5))
-       ((calc-minibuffer-contains ".* mod \\'")
-        (backward-delete-char 5))
-       ((calc-minibuffer-contains ".* \\'")
-        (backward-delete-char 2))
-       ((eq last-command 'calcDigit-start)
+  (cond ((eq last-command 'calcDigit-start)
         (erase-buffer))
        (t (backward-delete-char 1)))
   (if (= (calc-minibuffer-size) 0)
@@ -2925,6 +2933,20 @@ the United States."
                     (- (- (nth 2 a) (nth 2 b)) ldiff))))
 
 
+(defun calcDigit-delchar ()
+  (interactive)
+  (cond ((looking-at-p " \\+/- \\'")
+         (delete-char 5))
+       ((looking-at-p " mod \\'")
+        (delete-char 5))
+       ((looking-at-p " \\'")
+        (delete-char 2))
+       ((eq last-command 'calcDigit-start)
+        (erase-buffer))
+       (t (unless (eobp) (delete-char 1))))
+  (when (= (calc-minibuffer-size) 0)
+    (setq last-command-event 13)
+    (calcDigit-nondigit)))
 
 
 (defvar math-comp-selected)
diff --git a/lisp/calendar/cal-dst.el b/lisp/calendar/cal-dst.el
index af6acaf..05768e1 100644
--- a/lisp/calendar/cal-dst.el
+++ b/lisp/calendar/cal-dst.el
@@ -350,7 +350,7 @@ If the locale never uses daylight saving time, set this to 
0."
   :group 'calendar-dst)
 
 (defcustom calendar-standard-time-zone-name
-  (if calendar-use-numeric-time-zones
+  (if (eq calendar-time-zone-style 'numeric)
       (if calendar-current-time-zone-cache
           (format-time-string
            "%z" 0 (* 60 (car calendar-current-time-zone-cache)))
@@ -360,10 +360,11 @@ If the locale never uses daylight saving time, set this 
to 0."
 For example, \"EST\" in New York City, \"PST\" for Los Angeles."
   :type 'string
   :version "28.1"
+  :set-after '(calendar-time-zone-style)
   :group 'calendar-dst)
 
 (defcustom calendar-daylight-time-zone-name
-  (if calendar-use-numeric-time-zones
+  (if (eq calendar-time-zone-style 'numeric)
       (if calendar-current-time-zone-cache
           (format-time-string
            "%z" 0 (* 60 (cadr calendar-current-time-zone-cache)))
@@ -373,6 +374,7 @@ For example, \"EST\" in New York City, \"PST\" for Los 
Angeles."
 For example, \"EDT\" in New York City, \"PDT\" for Los Angeles."
   :type 'string
   :version "28.1"
+  :set-after '(calendar-time-zone-style)
   :group 'calendar-dst)
 
 (defcustom calendar-daylight-savings-starts-time
diff --git a/lisp/calendar/calendar.el b/lisp/calendar/calendar.el
index 0efb2bc..5742614 100644
--- a/lisp/calendar/calendar.el
+++ b/lisp/calendar/calendar.el
@@ -1061,10 +1061,12 @@ calendar."
   :type 'boolean
   :group 'holidays)
 
-(defcustom calendar-use-numeric-time-zones nil
-  "If nil, use symbolic time zones like \"CET\" when displaying dates.
-If non-nil, use numeric time zones like \"+0100\"."
-  :type 'boolean
+;; fixme should have a :set that changes calendar-standard-time-zone-name etc.
+(defcustom calendar-time-zone-style 'symbolic
+  "Your preferred style for time zones.
+If 'numeric, use numeric time zones like \"+0100\".
+Otherwise, use symbolic time zones like \"CET\"."
+  :type '(choice (const numeric) (other symbolic))
   :version "28.1"
   :group 'calendar)
 
diff --git a/lisp/calendar/solar.el b/lisp/calendar/solar.el
index 635bdd8..05bb316 100644
--- a/lisp/calendar/solar.el
+++ b/lisp/calendar/solar.el
@@ -840,8 +840,8 @@ This function is suitable for execution in an init file."
          (calendar-standard-time-zone-name
           (if (< arg 16) calendar-standard-time-zone-name
             (cond ((zerop calendar-time-zone)
-                   (if calendar-use-numeric-time-zones
-                       "+0100" "UTC"))
+                   (if (eq calendar-time-zone-style 'numeric)
+                       "+0000" "UTC"))
                   ((< calendar-time-zone 0)
                    (format "UTC%dmin" calendar-time-zone))
                   (t  (format "UTC+%dmin" calendar-time-zone)))))
@@ -1016,7 +1016,7 @@ Requires floating point."
          (calendar-standard-time-zone-name
           (cond
            (calendar-time-zone calendar-standard-time-zone-name)
-           (calendar-use-numeric-time-zones "+0100")
+           ((eq calendar-time-zone-style 'numeric) "+0000")
            (t "UTC")))
          (calendar-daylight-savings-starts
           (if calendar-time-zone calendar-daylight-savings-starts))
diff --git a/lisp/cedet/semantic/fw.el b/lisp/cedet/semantic/fw.el
index 7a1273d..e347c99 100644
--- a/lisp/cedet/semantic/fw.el
+++ b/lisp/cedet/semantic/fw.el
@@ -68,13 +68,11 @@
 
 ;; Since Emacs 22 major mode functions should use `run-mode-hooks' to
 ;; run major mode hooks.
-(defalias 'semantic-run-mode-hooks
-  (if (fboundp 'run-mode-hooks)
-      'run-mode-hooks
-    'run-hooks))
+(define-obsolete-function-alias 'semantic-run-mode-hooks 'run-mode-hooks 
"28.1")
 
-  ;; Fancy compat usage now handled in cedet-compat
-(defalias 'semantic-subst-char-in-string 'subst-char-in-string)
+;; Fancy compat usage now handled in cedet-compat
+(define-obsolete-function-alias 'semantic-subst-char-in-string
+  'subst-char-in-string "28.1")
 
 (defun semantic-delete-overlay-maybe (overlay)
   "Delete OVERLAY if it is a semantic token overlay."
diff --git a/lisp/cedet/semantic/grammar.el b/lisp/cedet/semantic/grammar.el
index 1ed1833..6cd4832 100644
--- a/lisp/cedet/semantic/grammar.el
+++ b/lisp/cedet/semantic/grammar.el
@@ -1251,6 +1251,7 @@ common grammar menu."
   "Setup an XEmacs grammar menu in variable SYMBOL.
 MODE-MENU is an optional specific menu whose items are appended to the
 common grammar menu."
+  (declare (obsolete nil "28.1"))
   (let ((items (make-symbol "items"))
         (path (make-symbol "path")))
     `(progn
diff --git a/lisp/comint.el b/lisp/comint.el
index 4b3b583..c3cb439 100644
--- a/lisp/comint.el
+++ b/lisp/comint.el
@@ -249,6 +249,10 @@ to set this in a mode hook, rather than customize the 
default value."
                 file)
   :group 'comint)
 
+(defvar comint-input-ring-file-prefix nil
+  "The prefix to skip when parsing the input ring file.
+This is useful in Zsh when the extended_history option is on.")
+
 (defcustom comint-scroll-to-bottom-on-input nil
   "Controls whether input to interpreter causes window to scroll.
 If nil, then do not scroll.  If t or `all', scroll all windows showing buffer.
@@ -731,7 +735,7 @@ contents are sent to the process as its initial input.
 If PROGRAM is a string, any more args are arguments to PROGRAM.
 
 Return the (possibly newly created) process buffer."
-  (or (fboundp 'start-file-process)
+  (or (fboundp 'make-process)
       (error "Multi-processing is not supported for this system"))
   (setq buffer (get-buffer-create (or buffer (concat "*" name "*"))))
   ;; If no process, or nuked process, crank up a new one and put buffer in
@@ -987,8 +991,20 @@ See also `comint-input-ignoredups' and 
`comint-write-input-ring'."
                            (setq end (match-beginning 0)))
                  (setq start
                        (if (re-search-backward ring-separator nil t)
-                           (match-end 0)
-                         (point-min)))
+                           (progn
+                             (when (and comint-input-ring-file-prefix
+                                        (looking-at
+                                         comint-input-ring-file-prefix))
+                               ;; Skip zsh extended_history stamps
+                               (goto-char (match-end 0)))
+                             (match-end 0))
+                         (progn
+                           (goto-char (point-min))
+                           (when (and comint-input-ring-file-prefix
+                                      (looking-at
+                                       comint-input-ring-file-prefix))
+                             (goto-char (match-end 0)))
+                           (point))))
                  (setq history (buffer-substring start end))
                  (goto-char start)
                  (when (and (not (string-match history-ignore history))
diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el
index 84d8c36..c197ed0 100644
--- a/lisp/dired-aux.el
+++ b/lisp/dired-aux.el
@@ -688,7 +688,7 @@ are executed in the background on each file sequentially 
waiting
 for each command to terminate before running the next command.
 In shell syntax this means separating the individual commands with `;'.
 
-The output appears in the buffer `shell-command-buffer-name-async'."
+The output appears in the buffer named by `shell-command-buffer-name-async'."
   (interactive
    (let ((files (dired-get-marked-files t current-prefix-arg nil nil t)))
      (list
@@ -726,16 +726,16 @@ it, write `*\"\"' in place of just `*'.  This is 
equivalent to just
 `*' in the shell, but avoids Dired's special handling.
 
 If COMMAND ends in `&', `;', or `;&', it is executed in the
-background asynchronously, and the output appears in the buffer
-`shell-command-buffer-name-async'.  When operating on multiple files and 
COMMAND
-ends in `&', the shell command is executed on each file in parallel.
-However, when COMMAND ends in `;' or `;&' then commands are executed
-in the background on each file sequentially waiting for each command
-to terminate before running the next command.  You can also use
-`dired-do-async-shell-command' that automatically adds `&'.
+background asynchronously, and the output appears in the buffer named
+by `shell-command-buffer-name-async'.  When operating on multiple files
+and COMMAND ends in `&', the shell command is executed on each file
+in parallel.  However, when COMMAND ends in `;' or `;&', then commands
+are executed in the background on each file sequentially waiting for
+each command to terminate before running the next command.  You can
+also use `dired-do-async-shell-command' that automatically adds `&'.
 
 Otherwise, COMMAND is executed synchronously, and the output
-appears in the buffer `shell-command-buffer-name'.
+appears in the buffer named by `shell-command-buffer-name'.
 
 This feature does not try to redisplay Dired buffers afterward, as
 there's no telling what files COMMAND may have changed.
@@ -1604,7 +1604,7 @@ Special value `always' suppresses confirmation."
 (defun dired-copy-file (from to ok-flag)
   (dired-handle-overwrite to)
   (dired-copy-file-recursive from to ok-flag dired-copy-preserve-time t
-                            dired-recursive-copies))
+                             dired-recursive-copies dired-copy-dereference))
 
 (declare-function make-symbolic-link "fileio.c")
 
@@ -1627,7 +1627,8 @@ If `ask', ask for user confirmation."
         (dired-create-directory dir))))
 
 (defun dired-copy-file-recursive (from to ok-flag &optional
-                                      preserve-time top recursive)
+                                       preserve-time top recursive
+                                       dereference)
   (when (and (eq t (file-attribute-type (file-attributes from)))
             (file-in-directory-p to from))
     (error "Cannot copy `%s' into its subdirectory `%s'" from to))
@@ -1639,7 +1640,8 @@ If `ask', ask for user confirmation."
        (copy-directory from to preserve-time)
       (or top (dired-handle-overwrite to))
       (condition-case err
-         (if (stringp (file-attribute-type attrs))
+         (if (and (not dereference)
+                   (stringp (file-attribute-type attrs)))
              ;; It is a symlink
              (make-symbolic-link (file-attribute-type attrs) to ok-flag)
             (dired-maybe-create-dirs (file-name-directory to))
@@ -2165,6 +2167,9 @@ See HOW-TO argument for `dired-do-create-files'.")
 ;;;###autoload
 (defun dired-do-copy (&optional arg)
   "Copy all marked (or next ARG) files, or copy the current file.
+ARG has to be numeric for above functionality.  See
+`dired-get-marked-files' for more details.
+
 When operating on just the current file, prompt for the new name.
 
 When operating on multiple or marked files, prompt for a target
@@ -2178,10 +2183,18 @@ If `dired-copy-preserve-time' is non-nil, this command 
preserves
 the modification time of each old file in the copy, similar to
 the \"-p\" option for the \"cp\" shell command.
 
-This command copies symbolic links by creating new ones, similar
-to the \"-d\" option for the \"cp\" shell command."
+This command copies symbolic links by creating new ones,
+similar to the \"-d\" option for the \"cp\" shell command.
+But if `dired-copy-dereference' is non-nil, the symbolic
+links are dereferenced and then copied, similar to the \"-L\"
+option for the \"cp\" shell command.  If ARG is a cons with
+element 4 (`\\[universal-argument]'), the inverted value of
+`dired-copy-dereference' will be used."
   (interactive "P")
-  (let ((dired-recursive-copies dired-recursive-copies))
+  (let ((dired-recursive-copies dired-recursive-copies)
+        (dired-copy-dereference (if (equal arg '(4))
+                                    (not dired-copy-dereference)
+                                  dired-copy-dereference)))
     (dired-do-create-files 'copy #'dired-copy-file
                           "Copy"
                           arg dired-keep-marker-copy
diff --git a/lisp/dired.el b/lisp/dired.el
index d19d6d1..77bb6cf 100644
--- a/lisp/dired.el
+++ b/lisp/dired.el
@@ -216,6 +216,12 @@ The target is used in the prompt for file copy, rename 
etc."
   :type 'boolean
   :group 'dired)
 
+(defcustom dired-copy-dereference nil
+  "If non-nil, Dired dereferences symlinks when copying them.
+This is similar to the \"-L\" option for the \"cp\" shell command."
+  :type 'boolean
+  :group 'dired)
+                                        ;
 ; These variables were deleted and the replacements are on files.el.
 ; We leave aliases behind for back-compatibility.
 (define-obsolete-variable-alias 'dired-free-space-program
diff --git a/lisp/emacs-lisp/autoload.el b/lisp/emacs-lisp/autoload.el
index 05eb0ac..592f1b6 100644
--- a/lisp/emacs-lisp/autoload.el
+++ b/lisp/emacs-lisp/autoload.el
@@ -1,4 +1,4 @@
-;; autoload.el --- maintain autoloads in loaddefs.el  -*- lexical-binding: t 
-*-
+;;; autoload.el --- maintain autoloads in loaddefs.el  -*- lexical-binding: t 
-*-
 
 ;; Copyright (C) 1991-1997, 2001-2020 Free Software Foundation, Inc.
 
@@ -606,9 +606,8 @@ Don't try to split prefixes that are already longer than 
that.")
                                prefix file dropped)
                       nil))))
               prefixes)))
-        `(if (fboundp 'register-definition-prefixes)
-             (register-definition-prefixes ,file ',(sort (delq nil strings)
-                                                        'string<)))))))
+        `(register-definition-prefixes ,file ',(sort (delq nil strings)
+                                                    'string<))))))
 
 (defun autoload--setup-output (otherbuf outbuf absfile load-name)
   (let ((outbuf
diff --git a/lisp/emacs-lisp/checkdoc.el b/lisp/emacs-lisp/checkdoc.el
index e4b8007..1029b52 100644
--- a/lisp/emacs-lisp/checkdoc.el
+++ b/lisp/emacs-lisp/checkdoc.el
@@ -1249,13 +1249,8 @@ checking of documentation strings.
 
 ;;; Subst utils
 ;;
-(defsubst checkdoc-run-hooks (hookvar &rest args)
-  "Run hooks in HOOKVAR with ARGS."
-  (if (fboundp 'run-hook-with-args-until-success)
-      (apply #'run-hook-with-args-until-success hookvar args)
-    ;; This method was similar to above.  We ignore the warning
-    ;; since we will use the above for future Emacs versions
-    (apply #'run-hook-with-args hookvar args)))
+(define-obsolete-function-alias 'checkdoc-run-hooks
+  #'run-hook-with-args-until-success "28.1")
 
 (defsubst checkdoc-create-common-verbs-regexp ()
   "Rebuild the contents of `checkdoc-common-verbs-regexp'."
@@ -1873,7 +1868,7 @@ Replace with \"%s\"? " original replace)
      ;; and reliance on the Ispell program.
      (checkdoc-ispell-docstring-engine e take-notes)
      ;; User supplied checks
-     (save-excursion (checkdoc-run-hooks 'checkdoc-style-functions fp e))
+     (save-excursion (run-hook-with-args-until-success 
'checkdoc-style-functions fp e))
      ;; Done!
      )))
 
@@ -2384,7 +2379,7 @@ Code:, and others referenced in the style guide."
        err
        (or
        ;; Generic Full-file checks (should be comment related)
-       (checkdoc-run-hooks 'checkdoc-comment-style-functions)
+       (run-hook-with-args-until-success 'checkdoc-comment-style-functions)
        err))
       ;; Done with full file comment checks
       err)))
diff --git a/lisp/emacs-lisp/eldoc.el b/lisp/emacs-lisp/eldoc.el
index 19b3bd7..4825b5c 100644
--- a/lisp/emacs-lisp/eldoc.el
+++ b/lisp/emacs-lisp/eldoc.el
@@ -289,13 +289,13 @@ Otherwise work like `message'."
             (or (window-in-direction 'above (minibuffer-window))
                 (minibuffer-selected-window)
                 (get-largest-window)))
-    (when mode-line-format
-         (unless (and (listp mode-line-format)
-                      (assq 'eldoc-mode-line-string mode-line-format))
+          (when (and mode-line-format
+                     (not (and (listp mode-line-format)
+                               (assq 'eldoc-mode-line-string 
mode-line-format))))
            (setq mode-line-format
                  (list "" '(eldoc-mode-line-string
                             (" " eldoc-mode-line-string " "))
-                       mode-line-format))))
+                       mode-line-format)))
           (setq eldoc-mode-line-string
                 (when (stringp format-string)
                   (apply #'format-message format-string args)))
diff --git a/lisp/emacs-lisp/lisp.el b/lisp/emacs-lisp/lisp.el
index 043cf01..8c18557 100644
--- a/lisp/emacs-lisp/lisp.el
+++ b/lisp/emacs-lisp/lisp.el
@@ -482,7 +482,8 @@ is called as a function to find the defun's end."
                  (if (looking-at "\\s<\\|\n")
                      (forward-line 1))))))
     (funcall end-of-defun-function)
-    (funcall skip)
+    (when (<= arg 1)
+      (funcall skip))
     (cond
      ((> arg 0)
       ;; Moving forward.
diff --git a/lisp/emulation/viper-cmd.el b/lisp/emulation/viper-cmd.el
index ca7fcaf..77f1b29 100644
--- a/lisp/emulation/viper-cmd.el
+++ b/lisp/emulation/viper-cmd.el
@@ -466,24 +466,7 @@
                           (assoc major-mode viper-emacs-state-modifier-alist)))
                         (cdr
                          (assoc major-mode viper-emacs-state-modifier-alist))
-                      viper-empty-keymap))
-              ))
-
-  ;; This var is not local in Emacs, so we make it local.  It must be local
-  ;; because although the stack of minor modes can be the same for all buffers,
-  ;; the associated *keymaps* can be different.  In Viper,
-  ;; viper-vi-local-user-map, viper-insert-local-user-map, and others can have
-  ;; different keymaps for different buffers.  Also, the keymaps associated
-  ;; with viper-vi/insert-state-modifier-minor-mode can be different.
-  ;; ***This is needed only in case emulation-mode-map-alists is not defined.
-  ;; In emacs with emulation-mode-map-alists, nothing needs to be done
-  (unless
-      (and (fboundp 'add-to-ordered-list) (boundp 'emulation-mode-map-alists))
-    (set (make-local-variable 'minor-mode-map-alist)
-         (viper-append-filter-alist
-          (append viper--intercept-key-maps viper--key-maps)
-          minor-mode-map-alist)))
-  )
+                      viper-empty-keymap)))))
 
 
 
@@ -893,16 +876,7 @@ LOAD-FILE is the name of the file where the specific minor 
mode is defined.
 Suffixes such as .el or .elc should be stripped."
 
   (interactive "sEnter name of the load file: ")
-
-  (eval-after-load load-file '(viper-normalize-minor-mode-map-alist))
-
-  ;; Change the default for minor-mode-map-alist each time a harnessed minor
-  ;; mode adds its own keymap to the a-list.
-  (unless
-      (and (fboundp 'add-to-ordered-list) (boundp 'emulation-mode-map-alists))
-    (eval-after-load
-       load-file '(setq-default minor-mode-map-alist minor-mode-map-alist)))
-  )
+  (eval-after-load load-file '(viper-normalize-minor-mode-map-alist)))
 
 
 (defun viper-ESC (arg)
@@ -4721,8 +4695,7 @@ Please, specify your level now: "))
   (interactive "cViper register to point: ")
   (let ((val (get-register char)))
     (cond
-     ((and (fboundp 'frame-configuration-p)
-          (frame-configuration-p val))
+     ((frame-configuration-p val)
       (set-frame-configuration val))
      ((window-configuration-p val)
       (set-window-configuration val))
diff --git a/lisp/emulation/viper.el b/lisp/emulation/viper.el
index 8e7a34f..59ca629 100644
--- a/lisp/emulation/viper.el
+++ b/lisp/emulation/viper.el
@@ -695,9 +695,6 @@ It also can't undo some Viper settings."
     'mark-even-if-inactive viper-saved-non-viper-variables))
 
   ;; Ideally, we would like to be able to de-localize local variables
-  (unless
-      (and (fboundp 'add-to-ordered-list) (boundp 'emulation-mode-map-alists))
-    (viper-delocalize-var 'minor-mode-map-alist))
   (viper-delocalize-var 'require-final-newline)
 
   ;; deactivate all advices done by Viper.
@@ -705,11 +702,9 @@ It also can't undo some Viper settings."
 
   (setq viper-mode nil)
 
-  (when (and (fboundp 'add-to-ordered-list) (boundp 
'emulation-mode-map-alists))
-    (setq emulation-mode-map-alists
-         (delq 'viper--intercept-key-maps
-               (delq 'viper--key-maps emulation-mode-map-alists))
-         ))
+  (setq emulation-mode-map-alists
+       (delq 'viper--intercept-key-maps
+             (delq 'viper--key-maps emulation-mode-map-alists)))
 
   (viper-delocalize-var 'viper-vi-minibuffer-minor-mode)
   (viper-delocalize-var 'viper-insert-minibuffer-minor-mode)
@@ -943,13 +938,11 @@ Two differences:
     (setq viper-vi-state-cursor-color color-name)))
 
 
-  (when (and (fboundp 'add-to-ordered-list) (boundp 
'emulation-mode-map-alists))
-    ;; needs to be as early as possible
-    (add-to-ordered-list
-     'emulation-mode-map-alists 'viper--intercept-key-maps 100)
-    ;; needs to be after cua-mode
-    (add-to-ordered-list 'emulation-mode-map-alists 'viper--key-maps 500)
-    )
+  ;; needs to be as early as possible
+  (add-to-ordered-list
+   'emulation-mode-map-alists 'viper--intercept-key-maps 100)
+  ;; needs to be after cua-mode
+  (add-to-ordered-list 'emulation-mode-map-alists 'viper--key-maps 500)
 
   ;; Emacs shell, ange-ftp, and comint-based modes
   (add-hook 'comint-mode-hook #'viper-comint-mode-hook) ; comint
@@ -1062,10 +1055,7 @@ This may be needed if the previous `:map' command 
terminated abnormally."
   (viper--advice-add 'add-minor-mode :after
    (lambda (&rest _)
     "Run viper-normalize-minor-mode-map-alist after adding a minor mode."
-    (viper-normalize-minor-mode-map-alist)
-    (unless
-       (and (fboundp 'add-to-ordered-list) (boundp 'emulation-mode-map-alists))
-      (setq-default minor-mode-map-alist minor-mode-map-alist))))
+    (viper-normalize-minor-mode-map-alist)))
 
   ;; catch frame switching event
   (if (viper-window-display-p)
@@ -1253,12 +1243,7 @@ These two lines must come in the order given."))
   ;; Without setting the default, new buffers that come up in emacs mode have
   ;; minor-mode-map-alist = nil, unless we call viper-change-state-*
   (when (eq viper-current-state 'emacs-state)
-    (viper-change-state-to-emacs)
-    (unless
-        (and (fboundp 'add-to-ordered-list)
-             (boundp 'emulation-mode-map-alists))
-      (setq-default minor-mode-map-alist minor-mode-map-alist))
-    )
+    (viper-change-state-to-emacs))
 
   (if (this-major-mode-requires-vi-state major-mode)
       (viper-mode))
diff --git a/lisp/epa-dired.el b/lisp/epa-dired.el
index 9269ea9..4ff1ba3 100644
--- a/lisp/epa-dired.el
+++ b/lisp/epa-dired.el
@@ -1,4 +1,5 @@
 ;;; epa-dired.el --- the EasyPG Assistant, dired extension -*- 
lexical-binding: t -*-
+
 ;; Copyright (C) 2006-2020 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
diff --git a/lisp/epa-file.el b/lisp/epa-file.el
index bbd9279..3b0cc84 100644
--- a/lisp/epa-file.el
+++ b/lisp/epa-file.el
@@ -1,4 +1,5 @@
 ;;; epa-file.el --- the EasyPG Assistant, transparent file encryption -*- 
lexical-binding: t -*-
+
 ;; Copyright (C) 2006-2020 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
@@ -21,10 +22,13 @@
 ;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
+;;; Dependencies
 
 (require 'epa)
 (require 'epa-hook)
 
+;;; Options
+
 (defcustom epa-file-cache-passphrase-for-symmetric-encryption nil
   "If non-nil, cache passphrase for symmetric encryption.
 
@@ -49,6 +53,8 @@ encryption is used."
                 (const :tag "Don't ask" silent))
   :group 'epa-file)
 
+;;; Other
+
 (defvar epa-file-passphrase-alist nil)
 
 (defun epa-file-passphrase-callback-function (context key-id file)
@@ -72,6 +78,8 @@ encryption is used."
                passphrase))))
     (epa-passphrase-callback-function context key-id file)))
 
+;;; File Handler
+
 (defvar epa-inhibit nil
   "Non-nil means don't try to decrypt .gpg files when operating on them.")
 
@@ -311,6 +319,8 @@ If no one is selected, symmetric encryption will be 
performed.  "
        (message "Wrote %s" buffer-file-name))))
 (put 'write-region 'epa-file 'epa-file-write-region)
 
+;;; Commands
+
 (defun epa-file-select-keys ()
   "Select recipients for encryption."
   (interactive)
diff --git a/lisp/epa-hook.el b/lisp/epa-hook.el
index a86f23e..6f12f8a 100644
--- a/lisp/epa-hook.el
+++ b/lisp/epa-hook.el
@@ -1,4 +1,5 @@
 ;;; epa-hook.el --- preloaded code to enable epa-file.el -*- lexical-binding: 
t -*-
+
 ;; Copyright (C) 2006-2020 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
diff --git a/lisp/epa-mail.el b/lisp/epa-mail.el
index 6347525..6e6c0a4 100644
--- a/lisp/epa-mail.el
+++ b/lisp/epa-mail.el
@@ -1,4 +1,5 @@
 ;;; epa-mail.el --- the EasyPG Assistant, minor-mode for mail composer -*- 
lexical-binding: t -*-
+
 ;; Copyright (C) 2006-2020 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
@@ -21,10 +22,13 @@
 ;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
+;;; Dependencies
 
 (require 'epa)
 (require 'mail-utils)
 
+;;; Local Mode
+
 (defvar epa-mail-mode-map
   (let ((keymap (make-sparse-keymap)))
     (define-key keymap "\C-c\C-ed" 'epa-mail-decrypt)
@@ -50,6 +54,8 @@
   "A minor-mode for composing encrypted/clearsigned mails."
   nil " epa-mail" epa-mail-mode-map)
 
+;;; Utilities
+
 (defun epa-mail--find-usable-key (keys usage)
   "Find a usable key from KEYS for USAGE.
 USAGE would be `sign' or `encrypt'."
@@ -64,6 +70,8 @@ USAGE would be `sign' or `encrypt'."
          (setq pointer (cdr pointer))))
       (setq keys (cdr keys)))))
 
+;;; Commands
+
 ;;;###autoload
 (defun epa-mail-decrypt ()
   "Decrypt OpenPGP armors in the current buffer.
@@ -241,6 +249,8 @@ The buffer is expected to contain a mail message."
   (interactive)
   (epa-import-armor-in-region (point-min) (point-max)))
 
+;;; Global Mode
+
 ;;;###autoload
 (define-minor-mode epa-global-mail-mode
   "Minor mode to hook EasyPG into Mail mode."
diff --git a/lisp/epa.el b/lisp/epa.el
index 3c7dd83..d190824 100644
--- a/lisp/epa.el
+++ b/lisp/epa.el
@@ -21,6 +21,7 @@
 ;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
+;;; Dependencies
 
 (require 'epg)
 (require 'font-lock)
@@ -30,6 +31,8 @@
   (require 'wid-edit))
 (require 'derived)
 
+;;; Options
+
 (defgroup epa nil
   "The EasyPG Assistant"
   :version "23.1"
@@ -73,6 +76,8 @@ The command `epa-mail-encrypt' uses this."
   :group 'epa
   :version "24.4")
 
+;;; Faces
+
 (defgroup epa-faces nil
   "Faces for epa-mode."
   :version "23.1"
@@ -146,6 +151,8 @@ The command `epa-mail-encrypt' uses this."
   :type '(repeat (cons symbol face))
   :group 'epa-faces)
 
+;;; Variables
+
 (defvar epa-font-lock-keywords
   '(("^\\*"
      (0 'epa-mark))
@@ -252,6 +259,8 @@ You should bind this variable with `let', but do not set it 
globally.")
 
 (defvar epa-exit-buffer-function #'quit-window)
 
+;;; Key Widget
+
 (define-widget 'epa-key 'push-button
   "Button for representing an epg-key object."
   :format "%[%v%]"
@@ -293,6 +302,8 @@ You should bind this variable with `let', but do not set it 
globally.")
          (epg-sub-key-id (car (epg-key-sub-key-list
                                (widget-get widget :value))))))
 
+;;; Modes
+
 (define-derived-mode epa-key-list-mode special-mode "EPA Keys"
   "Major mode for `epa-list-keys'."
   (buffer-disable-undo)
@@ -316,6 +327,9 @@ You should bind this variable with `let', but do not set it 
globally.")
   (setq truncate-lines t
        buffer-read-only t))
 
+;;; Commands
+;;;; Marking
+
 (defun epa-mark-key (&optional arg)
   "Mark a key on the current line.
 If ARG is non-nil, unmark the key."
@@ -338,11 +352,15 @@ If ARG is non-nil, mark the key."
   (interactive "P")
   (epa-mark-key (not arg)))
 
+;;;; Quitting
+
 (defun epa-exit-buffer ()
   "Exit the current buffer using `epa-exit-buffer-function'."
   (interactive)
   (funcall epa-exit-buffer-function))
 
+;;;; Listing and Selecting
+
 (defun epa--insert-keys (keys)
   (save-excursion
     (save-restriction
@@ -505,6 +523,8 @@ If SECRET is non-nil, list secret keys instead of public 
keys."
   (let ((keys (epg-list-keys context names secret)))
     (epa--select-keys prompt keys)))
 
+;;;; Key Details
+
 (defun epa-show-key ()
   "Show a key on the current line."
   (interactive)
@@ -591,6 +611,8 @@ If SECRET is non-nil, list secret keys instead of public 
keys."
     (goto-char (point-min))
     (pop-to-buffer (current-buffer))))
 
+;;;; Encryption and Signatures
+
 (defun epa-display-info (info)
   (if epa-popup-info-window
       (save-selected-window
@@ -1105,16 +1127,7 @@ If no one is selected, default secret key is used.  "
                                 'start-open t
                                 'end-open t)))))
 
-(defalias 'epa--derived-mode-p
-  (if (fboundp 'derived-mode-p)
-      #'derived-mode-p
-    (lambda (&rest modes)
-      "Non-nil if the current major mode is derived from one of MODES.
-Uses the `derived-mode-parent' property of the symbol to trace backwards."
-      (let ((parent major-mode))
-        (while (and (not (memq parent modes))
-                    (setq parent (get parent 'derived-mode-parent))))
-        parent))))
+(define-obsolete-function-alias 'epa--derived-mode-p 'derived-mode-p "28.1")
 
 ;;;###autoload
 (defun epa-encrypt-region (start end recipients sign signers)
@@ -1191,6 +1204,8 @@ If no one is selected, symmetric encryption will be 
performed.  ")
                                 'start-open t
                                 'end-open t)))))
 
+;;;; Key Management
+
 ;;;###autoload
 (defun epa-delete-keys (keys &optional allow-secret)
   "Delete selected KEYS."
@@ -1227,7 +1242,7 @@ If no one is selected, symmetric encryption will be 
performed.  ")
     (if (epg-context-result-for context 'import)
        (epa-display-info (epg-import-result-to-string
                           (epg-context-result-for context 'import))))
-    ;; FIXME: Why not use the (otherwise unused) epa--derived-mode-p?
+    ;; FIXME: Why not use the derived-mode-p?
     (if (eq major-mode 'epa-key-list-mode)
        (apply #'epa--list-keys epa-list-keys-arguments))))
 
diff --git a/lisp/epg-config.el b/lisp/epg-config.el
index 1c42924..9f0c7e4 100644
--- a/lisp/epg-config.el
+++ b/lisp/epg-config.el
@@ -22,6 +22,7 @@
 ;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
+;;; Prelude
 
 (eval-when-compile (require 'cl-lib))
 
@@ -34,6 +35,8 @@
 (define-obsolete-variable-alias 'epg-bug-report-address
   'report-emacs-bug-address "27.1")
 
+;;; Options
+
 (defgroup epg ()
   "Interface to the GNU Privacy Guard (GnuPG)."
   :tag "EasyPG"
@@ -106,6 +109,8 @@ through the minibuffer, instead of external Pinentry 
program."
 Note that the buffer name starts with a space."
   :type 'boolean)
 
+;;; Constants
+
 (defconst epg-gpg-minimum-version "1.4.3")
 (defconst epg-gpg2-minimum-version "2.1.6")
 
@@ -133,6 +138,8 @@ The first element of each entry is protocol symbol, which is
 either `OpenPGP' or `CMS'.  The second element is a function
 which constructs a configuration object (actually a plist).")
 
+;;; "Configuration"
+
 (defvar epg--configurations nil)
 
 ;;;###autoload
diff --git a/lisp/epg.el b/lisp/epg.el
index 5b90bc2..96af3ad 100644
--- a/lisp/epg.el
+++ b/lisp/epg.el
@@ -1,4 +1,5 @@
 ;;; epg.el --- the EasyPG Library -*- lexical-binding: t -*-
+
 ;; Copyright (C) 1999-2000, 2002-2020 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
@@ -21,10 +22,15 @@
 ;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
+;;; Prelude
 
 (require 'epg-config)
 (eval-when-compile (require 'cl-lib))
 
+(define-error 'epg-error "GPG error")
+
+;;; Variables
+
 (defvar epg-user-id nil
   "GnuPG ID of your default identity.")
 
@@ -41,6 +47,8 @@
 (defvar epg-agent-file nil)
 (defvar epg-agent-mtime nil)
 
+;;; Enums
+
 ;; from gnupg/common/openpgpdefs.h
 (defconst epg-cipher-algorithm-alist
   '((0 . "NONE")
@@ -123,7 +131,7 @@
 
 (defconst epg-no-data-reason-alist
   '((1 . "No armored data")
-    (2 . "Expected a packet but did not found one")
+    (2 . "Expected a packet but did not find one")
     (3 . "Invalid packet found, this may indicate a non OpenPGP message")
     (4 . "Signature expected but not found")))
 
@@ -169,7 +177,8 @@
 
 (defvar epg-prompt-alist nil)
 
-(define-error 'epg-error "GPG error")
+;;; Structs
+;;;; Data Struct
 
 (cl-defstruct (epg-data
                (:constructor nil)
@@ -180,6 +189,8 @@
   (file nil :read-only t)
   (string nil :read-only t))
 
+;;;; Context Struct
+
 (cl-defstruct (epg-context
                (:constructor nil)
                (:constructor epg-context--make
@@ -218,6 +229,8 @@
   (error-output "")
   error-buffer)
 
+;;;; Context Methods
+
 ;; This is not an alias, just so we can mark it as autoloaded.
 ;;;###autoload
 (defun epg-make-context (&optional protocol armor textmode include-certs
@@ -281,6 +294,8 @@ callback data (if any)."
   (declare (obsolete setf "25.1"))
   (setf (epg-context-signers context) signers))
 
+;;;; Other Structs
+
 (cl-defstruct (epg-signature
                (:constructor nil)
                (:constructor epg-make-signature
@@ -385,6 +400,8 @@ callback data (if any)."
   secret-unchanged not-imported
   imports)
 
+;;; Functions
+
 (defun epg-context-result-for (context name)
   "Return the result of CONTEXT associated with NAME."
   (cdr (assq name (epg-context-result context))))
@@ -404,37 +421,28 @@ callback data (if any)."
         (pubkey-algorithm (epg-signature-pubkey-algorithm signature))
         (key-id (epg-signature-key-id signature)))
     (concat
-     (cond ((eq (epg-signature-status signature) 'good)
-           "Good signature from ")
-          ((eq (epg-signature-status signature) 'bad)
-           "Bad signature from ")
-          ((eq (epg-signature-status signature) 'expired)
-           "Expired signature from ")
-          ((eq (epg-signature-status signature) 'expired-key)
-           "Signature made by expired key ")
-          ((eq (epg-signature-status signature) 'revoked-key)
-           "Signature made by revoked key ")
-          ((eq (epg-signature-status signature) 'no-pubkey)
-           "No public key for "))
+     (cl-case (epg-signature-status signature)
+       (good "Good signature from ")
+       (bad "Bad signature from ")
+       (expired "Expired signature from ")
+       (expired-key "Signature made by expired key ")
+       (revoked-key "Signature made by revoked key ")
+       (no-pubkey "No public key for "))
      key-id
-     (if user-id
-        (concat " "
-                (if (stringp user-id)
-                    (epg--decode-percent-escape-as-utf-8 user-id)
-                  (epg-decode-dn user-id)))
-       "")
-     (if (epg-signature-validity signature)
-        (format " (trust %s)"  (epg-signature-validity signature))
-       "")
-     (if (epg-signature-creation-time signature)
-        (format-time-string " created at %Y-%m-%dT%T%z"
-                            (epg-signature-creation-time signature))
-       "")
-     (if pubkey-algorithm
-        (concat " using "
-                (or (cdr (assq pubkey-algorithm epg-pubkey-algorithm-alist))
-                    (format "(unknown algorithm %d)" pubkey-algorithm)))
-       ""))))
+     (and user-id
+         (concat " "
+                 (if (stringp user-id)
+                     (epg--decode-percent-escape-as-utf-8 user-id)
+                   (epg-decode-dn user-id))))
+     (and (epg-signature-validity signature)
+         (format " (trust %s)"  (epg-signature-validity signature)))
+     (and (epg-signature-creation-time signature)
+         (format-time-string " created at %Y-%m-%dT%T%z"
+                             (epg-signature-creation-time signature)))
+     (and pubkey-algorithm
+         (concat " using "
+                 (or (cdr (assq pubkey-algorithm epg-pubkey-algorithm-alist))
+                     (format "(unknown algorithm %d)" pubkey-algorithm)))))))
 
 (defun epg-verify-result-to-string (verify-result)
   "Convert VERIFY-RESULT to a human readable string."
@@ -859,6 +867,8 @@ callback data (if any)."
                  (format "Untrusted key %s %s.  Use anyway? " key-id user-id))
              "Use untrusted key anyway? ")))
 
+;;; Status Functions
+
 (defun epg--status-GET_BOOL (context string)
   (let (inhibit-quit)
     (condition-case nil
@@ -1234,6 +1244,8 @@ callback data (if any)."
                             (epg-context-result-for context 'import-status)))
     (epg-context-set-result-for context 'import-status nil)))
 
+;;; Functions
+
 (defun epg-passphrase-callback-function (context key-id _handback)
   (declare (obsolete epa-passphrase-callback-function "23.1"))
   (if (eq key-id 'SYM)
@@ -1303,6 +1315,8 @@ callback data (if any)."
    (if (aref line 6)
        (epg--time-from-seconds (aref line 6)))))
 
+;;; Public Functions
+
 (defun epg-list-keys (context &optional name mode)
   "Return a list of epg-key objects matched with NAME.
 If MODE is nil or `public', only public keyring should be searched.
@@ -2032,6 +2046,8 @@ If you are unsure, use synchronous version of this 
function
                            (epg-errors-to-string errors))))))
     (epg-reset context)))
 
+;;; Decode Functions
+
 (defun epg--decode-percent-escape (string)
   (setq string (encode-coding-string string 'raw-text))
   (let ((index 0))
diff --git a/lisp/erc/erc-goodies.el b/lisp/erc/erc-goodies.el
index 94d5de2..ff7a77f 100644
--- a/lisp/erc/erc-goodies.el
+++ b/lisp/erc/erc-goodies.el
@@ -232,6 +232,10 @@ The value `erc-interpret-controls-p' must also be t for 
this to work."
   "ERC bold face."
   :group 'erc-faces)
 
+(defface erc-italic-face '((t :slant italic))
+  "ERC italic face."
+  :group 'erc-faces)
+
 (defface erc-inverse-face
   '((t :foreground "White" :background "Black"))
   "ERC inverse face."
@@ -383,6 +387,7 @@ See `erc-interpret-controls-p' and 
`erc-interpret-mirc-color' for options."
               (erc-controls-strip s))
              (erc-interpret-controls-p
               (let ((boldp nil)
+                    (italicp nil)
                     (inversep nil)
                     (underlinep nil)
                     (fg nil)
@@ -401,6 +406,8 @@ See `erc-interpret-controls-p' and 
`erc-interpret-mirc-color' for options."
                            (setq bg bg-color))
                           ((string= control "\C-b")
                            (setq boldp (not boldp)))
+                          ((string= control "\C-]")
+                           (setq italicp (not italicp)))
                           ((string= control "\C-v")
                            (setq inversep (not inversep)))
                           ((string= control "\C-_")
@@ -413,13 +420,14 @@ See `erc-interpret-controls-p' and 
`erc-interpret-mirc-color' for options."
                              (ding)))
                           ((string= control "\C-o")
                            (setq boldp nil
+                                 italicp nil
                                  inversep nil
                                  underlinep nil
                                  fg nil
                                  bg nil))
                           (t nil))
                     (erc-controls-propertize
-                     start end boldp inversep underlinep fg bg s)))
+                     start end boldp italicp inversep underlinep fg bg s)))
                 s))
              (t s)))))
 
@@ -432,13 +440,13 @@ See `erc-interpret-controls-p' and 
`erc-interpret-mirc-color' for options."
       s)))
 
 (defvar erc-controls-remove-regexp
-  "\C-b\\|\C-_\\|\C-v\\|\C-g\\|\C-o\\|\C-c[0-9]?[0-9]?\\(,[0-9][0-9]?\\)?"
+  
"\C-b\\|\C-]\\|\C-_\\|\C-v\\|\C-g\\|\C-o\\|\C-c[0-9]?[0-9]?\\(,[0-9][0-9]?\\)?"
   "Regular expression which matches control characters to remove.")
 
 (defvar erc-controls-highlight-regexp
-  (concat "\\(\C-b\\|\C-v\\|\C-_\\|\C-g\\|\C-o\\|"
+  (concat "\\(\C-b\\|\C-]\\|\C-v\\|\C-_\\|\C-g\\|\C-o\\|"
           "\C-c\\([0-9][0-9]?\\)?\\(,\\([0-9][0-9]?\\)\\)?\\)"
-          "\\([^\C-b\C-v\C-_\C-c\C-g\C-o\n]*\\)")
+          "\\([^\C-b\C-]\C-v\C-_\C-c\C-g\C-o\n]*\\)")
   "Regular expression which matches control chars and the text to highlight.")
 
 (defun erc-controls-highlight ()
@@ -451,6 +459,7 @@ Also see `erc-interpret-controls-p' and 
`erc-interpret-mirc-color'."
            (replace-match "")))
         (erc-interpret-controls-p
          (let ((boldp nil)
+               (italicp nil)
                (inversep nil)
                (underlinep nil)
                (fg nil)
@@ -467,6 +476,8 @@ Also see `erc-interpret-controls-p' and 
`erc-interpret-mirc-color'."
                       (setq bg bg-color))
                      ((string= control "\C-b")
                       (setq boldp (not boldp)))
+                     ((string= control "\C-]")
+                      (setq italicp (not italicp)))
                      ((string= control "\C-v")
                       (setq inversep (not inversep)))
                      ((string= control "\C-_")
@@ -479,16 +490,17 @@ Also see `erc-interpret-controls-p' and 
`erc-interpret-mirc-color'."
                         (ding)))
                      ((string= control "\C-o")
                       (setq boldp nil
+                            italicp nil
                             inversep nil
                             underlinep nil
                             fg nil
                             bg nil))
                      (t nil))
                (erc-controls-propertize start end
-                                        boldp inversep underlinep fg bg)))))
+                                        boldp italicp inversep underlinep fg 
bg)))))
         (t nil)))
 
-(defun erc-controls-propertize (from to boldp inversep underlinep fg bg
+(defun erc-controls-propertize (from to boldp italicp inversep underlinep fg bg
                                      &optional str)
   "Prepend properties from IRC control characters between FROM and TO.
 If optional argument STR is provided, apply to STR, otherwise prepend 
properties
@@ -500,6 +512,9 @@ to a region in the current buffer."
    (append (if boldp
                '(erc-bold-face)
              nil)
+           (if italicp
+               '(erc-italic-face)
+             nil)
            (if inversep
                '(erc-inverse-face)
              nil)
diff --git a/lisp/erc/erc-join.el b/lisp/erc/erc-join.el
index e4faf6b..79c1110 100644
--- a/lisp/erc/erc-join.el
+++ b/lisp/erc/erc-join.el
@@ -153,18 +153,20 @@ This function is run from `erc-nickserv-identified-hook'."
                              'erc-autojoin-channels-delayed
                              server nick (current-buffer))))
     ;; `erc-autojoin-timing' is `connect':
-    (dolist (l erc-autojoin-channels-alist)
-      (when (string-match (car l) server)
-       (let ((server (or erc-session-server erc-server-announced-name)))
+    (let ((server (or erc-session-server erc-server-announced-name)))
+      (dolist (l erc-autojoin-channels-alist)
+        (when (string-match-p (car l) server)
          (dolist (chan (cdr l))
-           (let ((buffer (erc-get-buffer chan)))
-             ;; Only auto-join the channels that we aren't already in
-             ;; using a different nick.
+           (let ((buffer
+                   (car (erc-buffer-filter
+                         (lambda ()
+                           (let ((current (erc-default-target)))
+                             (and (stringp current)
+                                  (string-match-p (car l)
+                                                  (or erc-session-server 
erc-server-announced-name))
+                                  (string-equal (erc-downcase chan)
+                                                (erc-downcase current)))))))))
              (when (or (not buffer)
-                       ;; If the same channel is joined on another
-                       ;; server the best-effort is to just join
-                       (not (string-match (car l)
-                                          (process-name erc-server-process)))
                        (not (with-current-buffer buffer
                               (erc-server-process-alive))))
                (erc-server-join-channel server chan))))))))
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index 404a4c0..41d7516 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -1608,36 +1608,47 @@ symbol, it may have these values:
 (defun erc-generate-new-buffer-name (server port target)
   "Create a new buffer name based on the arguments."
   (when (numberp port) (setq port (number-to-string port)))
-  (let ((buf-name (or target
-                      (or (let ((name (concat server ":" port)))
-                            (when (> (length name) 1)
-                              name))
-                          ;; This fallback should in fact never happen
-                          "*erc-server-buffer*")))
-        buffer-name)
+  (let* ((buf-name (or target
+                       (let ((name (concat server ":" port)))
+                         (when (> (length name) 1)
+                           name))
+                       ;; This fallback should in fact never happen.
+                       "*erc-server-buffer*"))
+         (full-buf-name (concat buf-name "/" server))
+         (dup-buf-name (buffer-name (car (erc-channel-list nil))))
+         buffer-name)
     ;; Reuse existing buffers, but not if the buffer is a connected server
     ;; buffer and not if its associated with a different server than the
     ;; current ERC buffer.
-    ;; if buf-name is taken by a different connection (or by something !erc)
-    ;; then see if "buf-name/server" meets the same criteria
-    (dolist (candidate (list buf-name (concat buf-name "/" server)))
-      (if (and (not buffer-name)
-               erc-reuse-buffers
-               (or (not (get-buffer candidate))
-                   ;; Looking for a server buffer, so there's no target.
-                   (and (not target)
-                        (with-current-buffer (get-buffer candidate)
-                          (and (erc-server-buffer-p)
-                               (not (erc-server-process-alive)))))
-                   ;; Channel buffer; check that it's from the right server.
-                   (and target
-                        (with-current-buffer (get-buffer candidate)
-                          (and (string= erc-session-server server)
-                               (erc-port-equal erc-session-port port))))))
-          (setq buffer-name candidate)))
-    ;; if buffer-name is unset, neither candidate worked out for us,
+    ;; If buf-name is taken by a different connection (or by something !erc)
+    ;; then see if "buf-name/server" meets the same criteria.
+    (if (and dup-buf-name (string-match-p (concat buf-name "/") dup-buf-name))
+        (setq buffer-name full-buf-name) ; ERC buffer with full name already 
exists.
+      (dolist (candidate (list buf-name full-buf-name))
+        (if (and (not buffer-name)
+                 erc-reuse-buffers
+                 (or (not (get-buffer candidate))
+                     ;; Looking for a server buffer, so there's no target.
+                     (and (not target)
+                          (with-current-buffer (get-buffer candidate)
+                            (and (erc-server-buffer-p)
+                                 (not (erc-server-process-alive)))))
+                     ;; Channel buffer; check that it's from the right server.
+                     (and target
+                          (with-current-buffer (get-buffer candidate)
+                            (and (string= erc-session-server server)
+                                 (erc-port-equal erc-session-port port))))))
+            (setq buffer-name candidate)
+          (when (and (not buffer-name) (get-buffer buf-name) erc-reuse-buffers)
+            ;; A new buffer will be created with the name buf-name/server, 
rename
+            ;; the existing name-duplicated buffer with the same format as 
well.
+            (with-current-buffer (get-buffer buf-name)
+              (when (derived-mode-p 'erc-mode) ; ensure it's an erc buffer
+                (rename-buffer
+                 (concat buf-name "/" (or erc-session-server 
erc-server-announced-name)))))))))
+    ;; If buffer-name is unset, neither candidate worked out for us,
     ;; fallback to the old <N> uniquification method:
-    (or buffer-name (generate-new-buffer-name (concat buf-name "/" server)))))
+    (or buffer-name (generate-new-buffer-name full-buf-name))))
 
 (defun erc-get-buffer-create (server port target)
   "Create a new buffer based on the arguments."
@@ -3153,16 +3164,18 @@ were most recently invited.  See also `invitation'."
       (setq chnl (erc-ensure-channel-name channel)))
     (when chnl
       ;; Prevent double joining of same channel on same server.
-      (let ((joined-channels
-             (mapcar #'(lambda (chanbuf)
-                         (with-current-buffer chanbuf (erc-default-target)))
-                     (erc-channel-list erc-server-process))))
-        (if (erc-member-ignore-case chnl joined-channels)
-            (switch-to-buffer (car (erc-member-ignore-case chnl
-                                                           joined-channels)))
-         (let ((server (with-current-buffer (process-buffer erc-server-process)
-                         (or erc-session-server erc-server-announced-name))))
-           (erc-server-join-channel server chnl key))))))
+      (let* ((joined-channels
+              (mapcar #'(lambda (chanbuf)
+                          (with-current-buffer chanbuf (erc-default-target)))
+                      (erc-channel-list erc-server-process)))
+             (server (with-current-buffer (process-buffer erc-server-process)
+                      (or erc-session-server erc-server-announced-name)))
+             (chnl-name (car (erc-member-ignore-case chnl joined-channels))))
+        (if chnl-name
+            (switch-to-buffer (if (get-buffer chnl-name)
+                                  chnl-name
+                                (concat chnl-name "/" server)))
+         (erc-server-join-channel server chnl key)))))
   t)
 
 (defalias 'erc-cmd-CHANNEL 'erc-cmd-JOIN)
diff --git a/lisp/eshell/esh-proc.el b/lisp/eshell/esh-proc.el
index d2c17fe..db1b258 100644
--- a/lisp/eshell/esh-proc.el
+++ b/lisp/eshell/esh-proc.el
@@ -295,7 +295,7 @@ See `eshell-needs-pipe'."
         (process-environment (eshell-environment-variables))
         proc decoding encoding changed)
     (cond
-     ((fboundp 'start-file-process)
+     ((fboundp 'make-process)
       (setq proc
            (let ((process-connection-type
                   (unless (eshell-needs-pipe-p command)
diff --git a/lisp/files.el b/lisp/files.el
index 1909669..9270f33 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -752,10 +752,16 @@ resulting list of directory names.  For an empty path 
element (i.e.,
 a leading or trailing separator, or two adjacent separators), return
 nil (meaning `default-directory') as the associated list element."
   (when (stringp search-path)
-    (mapcar (lambda (f)
-             (if (equal "" f) nil
-               (substitute-in-file-name (file-name-as-directory f))))
-           (split-string search-path path-separator))))
+    (let ((spath (substitute-env-vars search-path)))
+      (mapcar (lambda (f)
+                (if (equal "" f) nil
+                  (let ((dir (expand-file-name (file-name-as-directory f))))
+                    ;; Previous implementation used `substitute-in-file-name'
+                    ;; which collapse multiple "/" in front.  Do the same for
+                    ;; backward compatibility.
+                    (if (string-match "\\`/+" dir)
+                        (substring dir (1- (match-end 0))) dir))))
+              (split-string spath path-separator)))))
 
 (defun cd-absolute (dir)
   "Change current directory to given absolute file name DIR."
diff --git a/lisp/font-lock.el b/lisp/font-lock.el
index 5cda4a6..c633877 100644
--- a/lisp/font-lock.el
+++ b/lisp/font-lock.el
@@ -51,7 +51,7 @@
 ;; also the variable `font-lock-maximum-size'.  Support modes for Font Lock
 ;; mode can be used to speed up Font Lock mode.  See `font-lock-support-mode'.
 
-;;; How Font Lock mode fontifies:
+;;;; How Font Lock mode fontifies:
 
 ;; When Font Lock mode is turned on in a buffer, it (a) fontifies the entire
 ;; buffer and (b) installs one of its fontification functions on one of the
@@ -96,7 +96,7 @@
 ;; some syntactic parsers for common languages and a son-of-font-lock.el could
 ;; use them rather then relying so heavily on the keyword (regexp) pass.
 
-;;; How Font Lock mode supports modes or is supported by modes:
+;;;; How Font Lock mode supports modes or is supported by modes:
 
 ;; Modes that support Font Lock mode do so by defining one or more variables
 ;; whose values specify the fontification.  Font Lock mode knows of these
@@ -112,7 +112,7 @@
 ;; Font Lock mode fontification behavior can be modified in a number of ways.
 ;; See the below comments and the comments distributed throughout this file.
 
-;;; Constructing patterns:
+;;;; Constructing patterns:
 
 ;; See the documentation for the variable `font-lock-keywords'.
 ;;
@@ -120,7 +120,7 @@
 ;; `font-lock-syntactic-keywords' can be generated via the function
 ;; `regexp-opt'.
 
-;;; Adding patterns for modes that already support Font Lock:
+;;;; Adding patterns for modes that already support Font Lock:
 
 ;; Though Font Lock highlighting patterns already exist for many modes, it's
 ;; likely there's something that you want fontified that currently isn't, even
@@ -135,7 +135,7 @@
 ;; other variables.  For example, additional C types can be specified via the
 ;; variable `c-font-lock-extra-types'.
 
-;;; Adding patterns for modes that do not support Font Lock:
+;;;; Adding patterns for modes that do not support Font Lock:
 
 ;; Not all modes support Font Lock mode.  If you (as a user of the mode) add
 ;; patterns for a new mode, you must define in your ~/.emacs a variable or
@@ -155,7 +155,7 @@
 ;;     (set (make-local-variable 'font-lock-defaults)
 ;;          '(foo-font-lock-keywords t))))
 
-;;; Adding Font Lock support for modes:
+;;;; Adding Font Lock support for modes:
 
 ;; Of course, it would be better that the mode already supports Font Lock mode.
 ;; The package author would do something similar to above.  The mode must
@@ -986,7 +986,7 @@ The value of this variable is used when Font Lock mode is 
turned on."
        ((bound-and-true-p lazy-lock-mode)
         (lazy-lock-after-unfontify-buffer))))
 
-;;; End of Font Lock Support mode.
+;; End of Font Lock Support mode.
 
 ;;; Fontification functions.
 
@@ -1393,7 +1393,7 @@ delimit the region to fontify."
              (font-lock-fontify-region (point) (mark)))
          ((error quit) (message "Fontifying block...%s" error-data)))))))
 
-;;; End of Fontification functions.
+;; End of Fontification functions.
 
 ;;; Additional text property functions.
 
@@ -1485,7 +1485,7 @@ Optional argument OBJECT is the string or buffer 
containing the text."
                      (put-text-property start next prop new object))))))
       (setq start (text-property-not-all next end prop nil object)))))
 
-;;; End of Additional text property functions.
+;; End of Additional text property functions.
 
 ;;; Syntactic regexp fontification functions.
 
@@ -1591,7 +1591,7 @@ START should be at the beginning of a line."
          (setq highlights (cdr highlights))))
       (setq keywords (cdr keywords)))))
 
-;;; End of Syntactic regexp fontification functions.
+;; End of Syntactic regexp fontification functions.
 
 ;;; Syntactic fontification functions.
 
@@ -1650,7 +1650,7 @@ START should be at the beginning of a line."
         (setq state (parse-partial-sexp (point) end nil nil state
                                        'syntax-table))))))
 
-;;; End of Syntactic fontification functions.
+;; End of Syntactic fontification functions.
 
 ;;; Keyword regexp fontification functions.
 
@@ -1784,9 +1784,9 @@ LOUDLY, if non-nil, allows progress-meter bar."
       (setq keywords (cdr keywords)))
     (set-marker pos nil)))
 
-;;; End of Keyword regexp fontification functions.
+;; End of Keyword regexp fontification functions.
 
-;; Various functions.
+;;; Various functions.
 
 (defun font-lock-compile-keywords (keywords &optional syntactic-keywords)
   "Compile KEYWORDS into the form (t KEYWORDS COMPILED...)
@@ -2102,7 +2102,7 @@ Sets various variables using `font-lock-defaults' and
   "Font Lock mode face used to highlight grouping constructs in Lisp regexps."
   :group 'font-lock-faces)
 
-;;; End of Color etc. support.
+;; End of Color etc. support.
 
 ;;; Menu support.
 
@@ -2204,7 +2204,7 @@ Sets various variables using `font-lock-defaults' and
 ;;  ;; Deactivate less/more fontification entries.
 ;;  (setq font-lock-fontify-level nil))
 
-;;; End of Menu support.
+;; End of Menu support.
 
 ;;; Various regexp information shared by several modes.
 ;; ;; Information specific to a single mode should go in its load library.
diff --git a/lisp/gnus/gnus-util.el b/lisp/gnus/gnus-util.el
index abe546b..4876715 100644
--- a/lisp/gnus/gnus-util.el
+++ b/lisp/gnus/gnus-util.el
@@ -455,9 +455,7 @@ displayed in the echo area."
                           (> message-log-max 0)
                           (/= (length str) 0))
                  (setq time (current-time))
-                 (with-current-buffer (if (fboundp 'messages-buffer)
-                                          (messages-buffer)
-                                        (get-buffer-create "*Messages*"))
+                 (with-current-buffer (messages-buffer)
                    (goto-char (point-max))
                    (let ((inhibit-read-only t))
                      (insert ,timestamp str "\n")
diff --git a/lisp/gnus/gnus.el b/lisp/gnus/gnus.el
index ae4517e..b416094 100644
--- a/lisp/gnus/gnus.el
+++ b/lisp/gnus/gnus.el
@@ -1029,8 +1029,7 @@ Check the NNTPSERVER environment variable and the
 
 ;; `M-x customize-variable RET gnus-select-method RET' should work without
 ;; starting or even loading Gnus.
-;;;###autoload(when (fboundp 'custom-autoload)
-;;;###autoload  (custom-autoload 'gnus-select-method "gnus"))
+;;;###autoload(custom-autoload 'gnus-select-method "gnus")
 
 (defcustom gnus-select-method
   (list 'nntp (or (gnus-getenv-nntpserver)
diff --git a/lisp/gnus/mm-util.el b/lisp/gnus/mm-util.el
index 7629d5c..2824657 100644
--- a/lisp/gnus/mm-util.el
+++ b/lisp/gnus/mm-util.el
@@ -131,10 +131,6 @@ is not available."
   (cond
    ((null charset)
     charset)
-   ;; Running in a non-MULE environment.
-   ((or (null (mm-get-coding-system-list))
-       (not (fboundp 'coding-system-get)))
-    charset)
    ;; Check override list quite early.  Should only used for decoding, not for
    ;; encoding!
    ((and allow-override
@@ -295,77 +291,16 @@ superset of iso-8859-1."
 (defvar mm-universal-coding-system mm-auto-save-coding-system
   "The universal coding system.")
 
-;; Fixme: some of the cars here aren't valid MIME charsets.  That
-;; should only matter with XEmacs, though.
 (defvar mm-mime-mule-charset-alist
-  '((us-ascii ascii)
-    (iso-8859-1 latin-iso8859-1)
-    (iso-8859-2 latin-iso8859-2)
-    (iso-8859-3 latin-iso8859-3)
-    (iso-8859-4 latin-iso8859-4)
-    (iso-8859-5 cyrillic-iso8859-5)
-    ;; Non-mule (X)Emacs uses the last mule-charset for 8bit characters.
-    ;; The fake mule-charset, gnus-koi8-r, tells Gnus that the default
-    ;; charset is koi8-r, not iso-8859-5.
-    (koi8-r cyrillic-iso8859-5 gnus-koi8-r)
-    (iso-8859-6 arabic-iso8859-6)
-    (iso-8859-7 greek-iso8859-7)
-    (iso-8859-8 hebrew-iso8859-8)
-    (iso-8859-9 latin-iso8859-9)
-    (iso-8859-14 latin-iso8859-14)
-    (iso-8859-15 latin-iso8859-15)
-    (viscii vietnamese-viscii-lower)
-    (iso-2022-jp latin-jisx0201 japanese-jisx0208 japanese-jisx0208-1978)
-    (euc-kr korean-ksc5601)
-    (gb2312 chinese-gb2312)
-    (gbk chinese-gbk)
-    (gb18030 gb18030-2-byte
-            gb18030-4-byte-bmp gb18030-4-byte-smp
-            gb18030-4-byte-ext-1 gb18030-4-byte-ext-2)
-    (big5 chinese-big5-1 chinese-big5-2)
-    (tibetan tibetan)
-    (thai-tis620 thai-tis620)
-    (windows-1251 cyrillic-iso8859-5)
-    (iso-2022-7bit ethiopic arabic-1-column arabic-2-column)
-    (iso-2022-jp-2 latin-iso8859-1 greek-iso8859-7
-                  latin-jisx0201 japanese-jisx0208-1978
-                  chinese-gb2312 japanese-jisx0208
-                  korean-ksc5601 japanese-jisx0212)
-    (iso-2022-int-1 latin-iso8859-1 greek-iso8859-7
-                   latin-jisx0201 japanese-jisx0208-1978
-                   chinese-gb2312 japanese-jisx0208
-                   korean-ksc5601 japanese-jisx0212
-                   chinese-cns11643-1 chinese-cns11643-2)
-    (iso-2022-int-1 latin-iso8859-1 latin-iso8859-2
-                   cyrillic-iso8859-5 greek-iso8859-7
-                   latin-jisx0201 japanese-jisx0208-1978
-                   chinese-gb2312 japanese-jisx0208
-                   korean-ksc5601 japanese-jisx0212
-                   chinese-cns11643-1 chinese-cns11643-2
-                   chinese-cns11643-3 chinese-cns11643-4
-                   chinese-cns11643-5 chinese-cns11643-6
-                   chinese-cns11643-7)
-    (iso-2022-jp-3 latin-jisx0201 japanese-jisx0208-1978 japanese-jisx0208
-                  japanese-jisx0213-1 japanese-jisx0213-2)
-    (shift_jis latin-jisx0201 katakana-jisx0201 japanese-jisx0208)
-    (utf-8))
-  "Alist of MIME-charset/MULE-charsets.")
-
-;; Correct by construction, but should be unnecessary for Emacs:
-(when (and (fboundp 'coding-system-list)
-          (fboundp 'sort-coding-systems))
-  (let ((css (sort-coding-systems (coding-system-list 'base-only)))
-       cs mime mule alist)
-    (while css
-      (setq cs (pop css)
-           mime (or (coding-system-get cs :mime-charset) ; Emacs 23 (unicode)
-                    (coding-system-get cs 'mime-charset)))
+  (let (mime mule alist)
+    (dolist (cs (sort-coding-systems (coding-system-list 'base-only)))
+      (setq mime (coding-system-get cs 'mime-charset))
       (when (and mime
-                (not (eq t (setq mule
-                                 (coding-system-get cs 'safe-charsets))))
+                (not (eq t (setq mule (coding-system-get cs 'safe-charsets))))
                 (not (assq mime alist)))
        (push (cons mime (delq 'ascii mule)) alist)))
-    (setq mm-mime-mule-charset-alist (nreverse alist))))
+    (nreverse alist))
+  "Alist of MIME-charset/MULE-charsets.")
 
 (defvar mm-hack-charsets '(iso-8859-15 iso-2022-jp-2)
   "A list of special charsets.
diff --git a/lisp/help-fns.el b/lisp/help-fns.el
index d40b928..afca2cd 100644
--- a/lisp/help-fns.el
+++ b/lisp/help-fns.el
@@ -371,6 +371,7 @@ suitable file is found, return nil."
          (help-C-file-name type 'subr)
        'C-source))
      ((and (not file-name) (symbolp object)
+           (eq type 'defvar)
           (integerp (get object 'variable-documentation)))
       ;; A variable defined in C.  The form is from `describe-variable'.
       (if (get-buffer " *DOC*")
diff --git a/lisp/language/burmese.el b/lisp/language/burmese.el
index 7f2a99a..1888c8f 100644
--- a/lisp/language/burmese.el
+++ b/lisp/language/burmese.el
@@ -23,7 +23,6 @@
 
 ;;; Commentary:
 
-;; Aung San Suu Kyi says to call her country "Burma".
 ;; The murderous generals say to call it "Myanmar".
 ;; We will call it "Burma". -- rms, Chief GNUisance.
 
diff --git a/lisp/language/cyril-util.el b/lisp/language/cyril-util.el
index a3a6f3f..ce60d1a 100644
--- a/lisp/language/cyril-util.el
+++ b/lisp/language/cyril-util.el
@@ -47,7 +47,7 @@
 
 ;;;###autoload
 (defun standard-display-cyrillic-translit (&optional cyrillic-language)
-  "Display a cyrillic buffer using a transliteration.
+  "Display a Cyrillic buffer using a transliteration.
 For readability, the table is slightly
 different from the one used for the input method `cyrillic-translit'.
 
diff --git a/lisp/language/hanja-util.el b/lisp/language/hanja-util.el
index 19cba91..f38dead 100644
--- a/lisp/language/hanja-util.el
+++ b/lisp/language/hanja-util.el
@@ -22,7 +22,7 @@
 
 ;;; Commentary:
 
-;; This file defines korean hanja table and symbol table.
+;; This file defines the Korean Hanja table and symbol table.
 
 ;;; Code:
 
@@ -31,7 +31,7 @@
 
 (defvar hanja-table nil
   "A char table for Hanja characters.
-It maps a hangul character to a list of the corresponding Hanja characters.
+It maps a Hangul character to a list of the corresponding Hanja characters.
 Each element of the list has the form CHAR or (CHAR . STRING)
 where CHAR is a Hanja character and STRING is the meaning of that
 character.  This variable is initialized by `hanja-init-load'.")
diff --git a/lisp/language/indian.el b/lisp/language/indian.el
index eb882c8..657ad69 100644
--- a/lisp/language/indian.el
+++ b/lisp/language/indian.el
@@ -25,7 +25,7 @@
 ;;; Commentary:
 
 ;; This file contains definitions of Indian language environments, and
-;; setups for displaying the scrtipts used there.
+;; setups for displaying the scripts used there.
 
 ;;; Code:
 
diff --git a/lisp/leim/quail/latin-ltx.el b/lisp/leim/quail/latin-ltx.el
index 78ffca9..6a2508b 100644
--- a/lisp/leim/quail/latin-ltx.el
+++ b/lisp/leim/quail/latin-ltx.el
@@ -242,12 +242,14 @@ system, including many technical ones.  Examples:
  ((lambda (name char)
     ;; "GREEK SMALL LETTER PHI" (which is \phi) and "GREEK PHI SYMBOL"
     ;; (which is \varphi) are reversed in `ucs-names', so we define
-    ;; them manually.
-    (unless (string-match-p "\\<PHI\\>" name)
+    ;; them manually.  Also ignore "GREEK SMALL LETTER EPSILON" and
+    ;; add the correct value for \epsilon manually.
+    (unless (string-match-p "\\<\\(?:PHI\\|GREEK SMALL LETTER EPSILON\\)\\>" 
name)
       (concat "\\" (funcall (if (match-end 1) #' capitalize #'downcase)
                             (match-string 2 name)))))
   "\\`GREEK \\(?:SMALL\\|CAPITA\\(L\\)\\) LETTER \\([^- ]+\\)\\'")
 
+ ("\\epsilon" ?ϵ)
  ("\\phi" ?ϕ)
  ("\\Box" ?□)
  ("\\Bumpeq" ?≎)
@@ -641,6 +643,7 @@ system, including many technical ones.  Examples:
       (concat "\\var" (downcase (match-string 1 name)))))
   "\\`GREEK \\([^- ]+\\) SYMBOL\\'")
 
+ ("\\varepsilon" ?ε)
  ("\\varphi" ?φ)
  ("\\varprime" ?′)
  ("\\varpropto" ?∝)
diff --git a/lisp/mail/smtpmail.el b/lisp/mail/smtpmail.el
index f5c9432..666395e 100644
--- a/lisp/mail/smtpmail.el
+++ b/lisp/mail/smtpmail.el
@@ -53,6 +53,7 @@
 ;; See http://www.ietf.org/rfc/rfc2554.txt
 
 ;;; Code:
+;;; Dependencies
 
 (require 'sendmail)
 (require 'auth-source)
@@ -61,12 +62,12 @@
 (autoload 'message-make-message-id "message")
 (autoload 'rfc2104-hash "rfc2104")
 
-;;;
+;;; Options
+
 (defgroup smtpmail nil
   "SMTP protocol for sending mail."
   :group 'mail)
 
-
 (defcustom smtpmail-default-smtp-server nil
   "Specify default SMTP server.
 This only has effect if you specify it before loading the smtpmail library."
@@ -172,8 +173,7 @@ mean \"try again\"."
   :type 'integer
   :version "27.1")
 
-;; End of customizable variables.
-
+;;; Variables
 
 (defvar smtpmail-address-buffer)
 (defvar smtpmail-recipient-address-list)
@@ -192,6 +192,8 @@ for `smtpmail-try-auth-method'.")
 (defvar smtpmail-mail-address nil
   "Value to use for envelope-from address for mail from ambient buffer.")
 
+;;; Functions
+
 ;;;###autoload
 (defun smtpmail-send-it ()
   (let ((errbuf (if mail-interactive
diff --git a/lisp/man.el b/lisp/man.el
index e1dd503..da8a15f 100644
--- a/lisp/man.el
+++ b/lisp/man.el
@@ -836,9 +836,10 @@ POS defaults to `point'."
 ;; ======================================================================
 ;; Top level command and background process sentinel
 
-;; For compatibility with older versions.
+;; This alias was originally for compatibility with older versions.
+;; Some users got used to having it, so we will not remove it.
 ;;;###autoload
-(define-obsolete-function-alias 'manual-entry 'man "28.1")
+(defalias 'manual-entry 'man)
 
 (defvar Man-completion-cache nil
   ;; On my machine, "man -k" is so fast that a cache makes no sense,
diff --git a/lisp/net/dns.el b/lisp/net/dns.el
index c3c2943..c368cd7 100644
--- a/lisp/net/dns.el
+++ b/lisp/net/dns.el
@@ -316,8 +316,6 @@ If TCP-P, the first two bytes of the packet will be the 
length field."
   "Return false if we need to recheck the list of DNS servers."
   (and dns-servers
        (or (eq dns-servers-valid-for-interfaces t)
-          ;; `network-interface-list' was introduced in Emacs 22.1.
-          (not (fboundp 'network-interface-list))
           (equal dns-servers-valid-for-interfaces
                  (network-interface-list)))))
 
@@ -339,8 +337,7 @@ Parses \"/etc/resolv.conf\" or calls \"nslookup\"."
           (when (re-search-forward
           "^Address:[ 
\t]*\\([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+\\|[[:xdigit:]:]*\\)" nil t)
              (setq dns-servers (list (match-string 1)))))))
-  (when (fboundp 'network-interface-list)
-    (setq dns-servers-valid-for-interfaces (network-interface-list))))
+  (setq dns-servers-valid-for-interfaces (network-interface-list)))
 
 (defun dns-read-txt (string)
   (if (> (length string) 1)
diff --git a/lisp/net/eudc-bob.el b/lisp/net/eudc-bob.el
index 20a5c5f..56ea033 100644
--- a/lisp/net/eudc-bob.el
+++ b/lisp/net/eudc-bob.el
@@ -71,7 +71,7 @@
   `("EUDC Sound Menu"
     ["---" nil nil]
     ["Play sound" eudc-bob-play-sound-at-point
-     (fboundp 'play-sound)]
+     (fboundp 'play-sound-internal)]
     ,@(cdr (cdr eudc-bob-generic-menu))))
 
 (defun eudc-jump-to-event (event)
@@ -197,7 +197,7 @@ display a button."
   (let (sound)
     (if (null (setq sound (eudc-bob-get-overlay-prop 'object-data)))
        (error "No sound data available here")
-      (unless (fboundp 'play-sound)
+      (unless (fboundp 'play-sound-internal)
        (error "Playing sounds not supported on this system"))
       (play-sound (list 'sound :data sound)))))
 
@@ -214,8 +214,7 @@ display a button."
   (let ((data (eudc-bob-get-overlay-prop 'object-data))
        (buffer (generate-new-buffer "*eudc-tmp*")))
     (save-excursion
-      (if (fboundp 'set-buffer-file-coding-system)
-         (set-buffer-file-coding-system 'binary))
+      (set-buffer-file-coding-system 'binary)
       (set-buffer buffer)
       (set-buffer-multibyte nil)
       (insert data)
@@ -231,8 +230,7 @@ display a button."
        viewer)
     (condition-case nil
        (save-excursion
-         (if (fboundp 'set-buffer-file-coding-system)
-             (set-buffer-file-coding-system 'binary))
+         (set-buffer-file-coding-system 'binary)
          (set-buffer buffer)
          (insert data)
          (setq program (completing-read "Viewer: " eudc-external-viewers))
diff --git a/lisp/net/eudcb-macos-contacts.el b/lisp/net/eudcb-macos-contacts.el
index f258d5c..e2d10e3 100644
--- a/lisp/net/eudcb-macos-contacts.el
+++ b/lisp/net/eudcb-macos-contacts.el
@@ -1,19 +1,23 @@
 ;;; eudcb-macos-contacts.el --- EUDC - macOS Contacts backend
 
-;; Copyright (C) 2020 condition-alpha.com
+;; Copyright (C) 2020 Free Software Foundation, Inc.
 
-;; This program is free software: you can redistribute it and/or modify
+;; Author: Alexander Adolf
+
+;; 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.
-;;
-;; This program is distributed in the hope that it will be useful,
+
+;; GNU Emacs is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ;; GNU General Public License for more details.
-;;
+
 ;; You should have received a copy of the GNU General Public License
-;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
+;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 ;;    This library provides an interface to the macOS Contacts app as
diff --git a/lisp/net/imap.el b/lisp/net/imap.el
index a492dc8..22b5908 100644
--- a/lisp/net/imap.el
+++ b/lisp/net/imap.el
@@ -134,6 +134,7 @@
 ;;
 
 ;;; Code:
+;;; Dependencies
 
 (eval-when-compile (require 'cl-lib))
 (require 'utf7)
@@ -145,7 +146,7 @@
 (declare-function digest-md5-digest-uri "ext:digest-md5")
 (declare-function digest-md5-challenge "ext:digest-md5")
 
-;; User variables.
+;;; User variables
 
 (defgroup imap nil
   "Low-level IMAP issues."
@@ -257,7 +258,7 @@ Shorter values mean quicker response, but is more CPU 
intensive."
   :group 'imap
   :type 'boolean)
 
-;; Various variables.
+;;; Various variables
 
 (defvar imap-fetch-data-hook nil
   "Hooks called after receiving each FETCH response.")
@@ -316,7 +317,9 @@ the value of this variable will be bound to a certain value 
to which
 an application program that uses this module specifies on a per-server
 basis.")
 
-;; Internal constants.  Change these and die.
+;;; Internal constants
+
+;; Change these and die.
 
 (defconst imap-default-port 143)
 (defconst imap-default-ssl-port 993)
@@ -348,7 +351,7 @@ basis.")
 (defconst imap-log-buffer "*imap-log*")
 (defconst imap-debug-buffer "*imap-debug*")
 
-;; Internal variables.
+;;; Internal variables
 
 (defvar imap-stream nil)
 (defvar imap-auth nil)
@@ -437,7 +440,7 @@ This variable is set to t automatically per server if the
 canonical form fails.")
 
 
-;; Utility functions:
+;;; Utility functions
 
 (defun imap-remassoc (key alist)
   "Delete by side effect any elements of ALIST whose car is `equal' to KEY.
@@ -489,7 +492,8 @@ sure of changing the value of `foo'."
     (nth 3 (car imap-failed-tags))))
 
 
-;; Server functions; stream stuff:
+;;; Server functions
+;;;; Stream functions
 
 (defun imap-log (string-or-buffer)
   (when imap-log
@@ -747,7 +751,7 @@ sure of changing the value of `foo'."
     (message "imap: Connecting with STARTTLS...%s" (if done "done" "failed"))
     done))
 
-;; Server functions; authenticator stuff:
+;;;; Authenticator functions
 
 (defun imap-interactive-login (buffer loginfunc)
   "Login to server in BUFFER.
@@ -871,7 +875,7 @@ t if it successfully authenticates, nil otherwise."
                (concat "LOGIN anonymous \"" (concat (user-login-name) "@"
                                                     (system-name)) "\"")))))
 
-;;; Compiler directives.
+;;; Compiler directives
 
 (defvar imap-sasl-client)
 (defvar imap-sasl-step)
@@ -969,7 +973,7 @@ t if it successfully authenticates, nil otherwise."
         (imap-send-command-1 "")
         (imap-ok-p (imap-wait-for-tag tag)))))))
 
-;; Server functions:
+;;; Server functions
 
 (defun imap-open-1 (buffer)
   (with-current-buffer buffer
@@ -1228,7 +1232,7 @@ If BUFFER is nil, the current buffer is assumed."
     (imap-send-command-wait "LOGOUT" buffer)))
 
 
-;; Mailbox functions:
+;;; Mailbox functions
 
 (defun imap-mailbox-put (propname value &optional mailbox buffer)
   (with-current-buffer (or buffer (current-buffer))
@@ -1520,7 +1524,7 @@ or `unseen'.  The IMAP command tag is returned."
                                     identifier))))))
 
 
-;; Message functions:
+;;; Message functions
 
 (defun imap-current-message (&optional buffer)
   (with-current-buffer (or buffer (current-buffer))
@@ -1832,7 +1836,7 @@ on failure."
               (if (aref from 0) ">"))))
 
 
-;; Internal functions.
+;;; Internal functions
 
 (defun imap-add-callback (tag func)
   (setq imap-callbacks (append (list (cons tag func)) imap-callbacks)))
@@ -1969,7 +1973,7 @@ Return nil if no complete line has arrived."
              (delete-region (point-min) (point-max)))))))))
 
 
-;; Imap parser.
+;;; Imap parser
 
 (defsubst imap-forward ()
   (or (eobp) (forward-char)))
@@ -2850,6 +2854,8 @@ Return nil if no complete line has arrived."
        (imap-forward)
        (nreverse body)))))
 
+;;; Debug
+
 (when imap-debug                       ; (untrace-all)
   (require 'trace)
   (buffer-disable-undo (get-buffer-create imap-debug-buffer))
diff --git a/lisp/net/mailcap.el b/lisp/net/mailcap.el
index 86f9d2b..f01a5de 100644
--- a/lisp/net/mailcap.el
+++ b/lisp/net/mailcap.el
@@ -269,11 +269,6 @@ is consulted."
       (viewer . "display %s")
       (type . "image/*")
       (test   . (eq window-system 'x))
-      ("needsx11"))
-     (".*"
-      (viewer . "ee %s")
-      (type . "image/*")
-      (test   . (eq window-system 'x))
       ("needsx11")))
     ("text"
      ("plain"
diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el
index 88f5c29..49ecaa5 100644
--- a/lisp/net/tramp-adb.el
+++ b/lisp/net/tramp-adb.el
@@ -890,8 +890,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are 
completely ignored."
   "Like `make-process' for Tramp files.
 If connection property \"direct-async-process\" is non-nil, an
 alternative implementation will be used."
-  (if (tramp-get-connection-property
-       (tramp-dissect-file-name default-directory) "direct-async-process" nil)
+  (if (tramp-direct-async-process-p args)
       (apply #'tramp-handle-make-process args)
     (when args
       (with-parsed-tramp-file-name (expand-file-name default-directory) nil
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index 3e2eb02..ca43475 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -2790,8 +2790,7 @@ the result will be a local, non-Tramp, file name."
 STDERR can also be a file name.  If connection property
 \"direct-async-process\" is non-nil, an alternative
 implementation will be used."
-  (if (tramp-get-connection-property
-       (tramp-dissect-file-name default-directory) "direct-async-process" nil)
+  (if (tramp-direct-async-process-p args)
       (apply #'tramp-handle-make-process args)
     (when args
       (with-parsed-tramp-file-name (expand-file-name default-directory) nil
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index fdf26f6..ab52bec 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -3633,18 +3633,29 @@ User is always nil."
                (load local-copy noerror t nosuffix must-suffix)
              (delete-file local-copy)))))
       t)))
+
+(defun tramp-direct-async-process-p (&rest args)
+  "Whether direct async `make-process' can be called."
+  (let ((v (tramp-dissect-file-name default-directory)))
+    (and (tramp-get-connection-property v"direct-async-process" nil)
+          (not (tramp-multi-hop-p v))
+          (not (plist-get args :stderr)))))
+
 ;; We use BUFFER also as connection buffer during setup. Because of
 ;; this, its original contents must be saved, and restored once
 ;; connection has been setup.
 (defun tramp-handle-make-process (&rest args)
-  "An alternative `make-process' implementation for Tramp files."
+  "An alternative `make-process' implementation for Tramp files.
+It does not support `:stderr'."
   (when args
     (with-parsed-tramp-file-name (expand-file-name default-directory) nil
       (let ((name (plist-get args :name))
            (buffer (plist-get args :buffer))
            (command (plist-get args :command))
+           ;; FIXME: `:coding' shall be used.
            (coding (plist-get args :coding))
            (noquery (plist-get args :noquery))
+           ;; FIXME: `:connection-type' shall be used.
            (connection-type (plist-get args :connection-type))
            (filter (plist-get args :filter))
            (sentinel (plist-get args :sentinel))
@@ -3667,11 +3678,12 @@ User is always nil."
          (signal 'wrong-type-argument (list #'functionp filter)))
        (unless (or (null sentinel) (functionp sentinel))
          (signal 'wrong-type-argument (list #'functionp sentinel)))
-       (unless (or (null stderr) (bufferp stderr) (stringp stderr))
-         (signal 'wrong-type-argument (list #'stringp stderr)))
-       (when (and (stringp stderr) (tramp-tramp-file-p stderr)
-                  (not (tramp-equal-remote default-directory stderr)))
-         (signal 'file-error (list "Wrong stderr" stderr)))
+       (when stderr
+         (signal
+          'user-error
+          (list
+           "Stderr not supported for direct remote asynchronous processes"
+           stderr)))
 
        (let* ((buffer
                (if buffer
@@ -3698,9 +3710,12 @@ User is always nil."
          (tramp-set-connection-property v "process-name" name)
          (tramp-set-connection-property v "process-buffer" buffer)
 
+         ;; Check for `tramp-sh-file-name-handler', because something
+         ;; is different between tramp-adb.el and tramp-sh.el.
          (with-current-buffer (tramp-get-connection-buffer v)
            (unwind-protect
-               (let* ((login-program
+               (let* ((sh-file-name-handler-p (tramp-sh-file-name-handler-p v))
+                      (login-program
                        (tramp-get-method-parameter v 'tramp-login-program))
                       (login-args
                        (tramp-get-method-parameter v 'tramp-login-args))
@@ -3716,12 +3731,12 @@ User is always nil."
                       ;; in the main connection process, therefore
                       ;; we cannot use `tramp-get-connection-process'.
                       (tmpfile
-                       (when (tramp-sh-file-name-handler-p v)
+                       (when sh-file-name-handler-p
                          (with-tramp-connection-property
                              (tramp-get-process v) "temp-file"
                            (tramp-compat-make-temp-name))))
                       (options
-                       (when (tramp-sh-file-name-handler-p v)
+                       (when sh-file-name-handler-p
                          (tramp-compat-funcall
                           'tramp-ssh-controlmaster-options v)))
                       spec)
@@ -3814,9 +3829,12 @@ support symbolic links."
            (setq current-buffer-p t)
            (current-buffer))
           (t (get-buffer-create
+              ;; These variables have been introduced with Emacs 28.1.
               (if asynchronous
-                  shell-command-buffer-name-async
-                shell-command-buffer-name)))))
+                  (or (bound-and-true-p shell-command-buffer-name-async)
+                      "*Async Shell Command*")
+                (or (bound-and-true-p shell-command-buffer-name)
+                    "*Shell Command Output*"))))))
         (error-buffer
          (cond
           ((bufferp error-buffer) error-buffer)
diff --git a/lisp/obsolete/longlines.el b/lisp/obsolete/longlines.el
index 2fba49f..cbe453a 100644
--- a/lisp/obsolete/longlines.el
+++ b/lisp/obsolete/longlines.el
@@ -37,6 +37,7 @@
 ;; Special thanks to Rod Smith for many useful bug reports.
 
 ;;; Code:
+;;; Options
 
 (defgroup longlines nil
   "Automatic wrapping of long lines when loading files."
@@ -76,7 +77,7 @@ This is used when `longlines-show-hard-newlines' is on."
   :group 'longlines
   :type 'string)
 
-;; Internal variables
+;;; Internal variables
 
 (defvar longlines-wrap-beg nil)
 (defvar longlines-wrap-end nil)
@@ -90,7 +91,7 @@ This is used when `longlines-show-hard-newlines' is on."
 (make-variable-buffer-local 'longlines-showing)
 (make-variable-buffer-local 'longlines-decoded)
 
-;; Mode
+;;; Mode
 
 (defvar message-indent-citation-function)
 
@@ -210,7 +211,7 @@ This function exists to be called by 
`change-major-mode-hook' when the
 major mode changes."
   (longlines-mode 0))
 
-;; Showing the effect of hard newlines in the buffer
+;;; Showing the effect of hard newlines in the buffer
 
 (defun longlines-show-hard-newlines (&optional arg)
   "Make hard newlines visible by adding a face.
@@ -252,7 +253,7 @@ With optional argument ARG, make the hard newlines 
invisible again."
       (setq pos (text-property-not-all (1+ pos) (point-max) 'hard nil)))
     (restore-buffer-modified-p mod)))
 
-;; Wrapping the paragraphs.
+;;; Wrapping the paragraphs
 
 (defun longlines-wrap-region (beg end)
   "Wrap each successive line, starting with the line before BEG.
@@ -402,7 +403,7 @@ Hard newlines are left intact."
       (setq pos (string-match "\n" str (1+ pos))))
     str))
 
-;; Auto wrap
+;;; Auto wrap
 
 (defun longlines-auto-wrap (&optional arg)
   "Toggle automatic line wrapping.
@@ -457,7 +458,7 @@ This is called by `window-configuration-change-hook'."
       (setq fill-column (- (window-width) dw))
       (longlines-wrap-region (point-min) (point-max)))))
 
-;; Isearch
+;;; Isearch
 
 (defun longlines-search-function ()
   (cond
@@ -477,7 +478,7 @@ This is called by `window-configuration-change-hook'."
   (let ((search-spaces-regexp " *[ \n]"))
     (re-search-forward string bound noerror count)))
 
-;; Loading and saving
+;;; Loading and saving
 
 (defun longlines-before-revert-hook ()
   (add-hook 'after-revert-hook 'longlines-after-revert-hook nil t)
@@ -492,7 +493,7 @@ This is called by `window-configuration-change-hook'."
  (list 'longlines "Automatically wrap long lines." nil nil
        'longlines-encode-region t nil))
 
-;; Unloading
+;;; Unloading
 
 (defun longlines-unload-function ()
   "Unload the longlines library."
diff --git a/lisp/play/bubbles.el b/lisp/play/bubbles.el
index e598257..903c068 100644
--- a/lisp/play/bubbles.el
+++ b/lisp/play/bubbles.el
@@ -976,16 +976,14 @@ Set `bubbles--col-offset' and `bubbles--row-offset'."
                        (* image-vert-size (bubbles--grid-height)))
                     2)))))
 
-(defun bubbles--remove-overlays ()
-  "Remove all overlays."
-  (if (fboundp 'remove-overlays)
-      (remove-overlays)))
+(define-obsolete-function-alias 'bubbles--remove-overlays
+  'remove-overlays "28.1")
 
 (defun bubbles--initialize ()
   "Initialize Bubbles game."
   (bubbles--initialize-faces)
   (bubbles--initialize-images)
-  (bubbles--remove-overlays)
+  (remove-overlays)
 
   (switch-to-buffer (get-buffer-create "*bubbles*"))
   (bubbles--compute-offsets)
@@ -1409,7 +1407,7 @@ Return t if new char is non-empty."
 
 (defun bubbles--show-images ()
   "Update images in the bubbles buffer."
-  (bubbles--remove-overlays)
+  (remove-overlays)
   (if (and (display-images-p)
            bubbles--images-ok
            (not (eq bubbles-graphics-theme 'ascii)))
diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el
index a76a3c4..0b9f417 100644
--- a/lisp/progmodes/compile.el
+++ b/lisp/progmodes/compile.el
@@ -2373,12 +2373,10 @@ and runs `compilation-filter-hook'."
          (set-marker min nil)
          (set-marker max nil))))))
 
-;;; test if a buffer is a compilation buffer, assuming we're in the buffer
 (defsubst compilation-buffer-internal-p ()
   "Test if inside a compilation buffer."
   (local-variable-p 'compilation-locs))
 
-;;; test if a buffer is a compilation buffer, using 
compilation-buffer-internal-p
 (defsubst compilation-buffer-p (buffer)
   "Test if BUFFER is a compilation buffer."
   (with-current-buffer buffer
diff --git a/lisp/progmodes/idlw-shell.el b/lisp/progmodes/idlw-shell.el
index 6770fbe..f875915 100644
--- a/lisp/progmodes/idlw-shell.el
+++ b/lisp/progmodes/idlw-shell.el
@@ -2745,7 +2745,7 @@ Runs to the last statement and then steps 1 statement.  
Use the .out command."
             ;; event.  mouse-drag-track does so.
             (if drag-track 'mouse-drag-track 'mouse-drag-region)))
        (funcall tracker event)
-       (idlwave-shell-print (if (idlwave-region-active-p) '(4) nil)
+       (idlwave-shell-print (if (region-active-p) '(4) nil)
                            ,help ,ev))))
 
 ;; Begin terrible hack section -- XEmacs tests for button2 explicitly
@@ -2830,7 +2830,7 @@ from `idlwave-shell-examine-alist' via mini-buffer 
shortcut key."
       (cond
        ((equal arg '(16))
        (setq expr (read-string "Expression: ")))
-       ((and (or arg (idlwave-region-active-p))
+       ((and (or arg (region-active-p))
             (< (- (region-end) (region-beginning)) 2000))
        (setq beg (region-beginning)
              end (region-end)))
diff --git a/lisp/progmodes/idlwave.el b/lisp/progmodes/idlwave.el
index 3092d4c..f7e53ec 100644
--- a/lisp/progmodes/idlwave.el
+++ b/lisp/progmodes/idlwave.el
@@ -154,21 +154,6 @@
 (eval-when-compile (require 'cl-lib))
 (require 'idlw-help)
 
-;; For XEmacs
-(unless (fboundp 'line-beginning-position)
-  (defalias 'line-beginning-position 'point-at-bol))
-(unless (fboundp 'line-end-position)
-  (defalias 'line-end-position 'point-at-eol))
-(unless (fboundp 'char-valid-p)
-  (defalias 'char-valid-p 'characterp))
-(unless (fboundp 'match-string-no-properties)
-  (defalias 'match-string-no-properties 'match-string))
-
-(if (not (fboundp 'cancel-timer))
-    (condition-case nil
-       (require 'timer)
-      (error nil)))
-
 (declare-function idlwave-shell-get-path-info "idlw-shell")
 (declare-function idlwave-shell-temp-file "idlw-shell")
 (declare-function idlwave-shell-is-running "idlw-shell")
@@ -2092,11 +2077,7 @@ Returns point if comment found and nil otherwise."
            (backward-char 1)
            (point)))))
 
-(defun idlwave-region-active-p ()
-  "Should we operate on an active region?"
-  (if (fboundp 'use-region-p)
-      (use-region-p)
-    (region-active-p)))
+(define-obsolete-function-alias 'idlwave-region-active-p 'use-region-p "28.1")
 
 (defun idlwave-show-matching-quote ()
   "Insert quote and show matching quote if this is end of a string."
diff --git a/lisp/progmodes/prolog.el b/lisp/progmodes/prolog.el
index 99b5735..a209d21 100644
--- a/lisp/progmodes/prolog.el
+++ b/lisp/progmodes/prolog.el
@@ -271,10 +271,6 @@
 (require 'easymenu)
 (require 'align)
 
-(eval-when-compile
-  (or (fboundp 'use-region-p)
-      (defsubst use-region-p () (region-exists-p))))
-
 (defgroup prolog nil
   "Editing and running Prolog and Mercury files."
   :group 'languages)
@@ -2752,20 +2748,6 @@ When called with prefix argument ARG, disable zipping 
instead."
                   (nth 1 state)))
         ))))
 
-;; For backward compatibility. Stolen from custom.el.
-(or (fboundp 'match-string)
-    ;; Introduced in Emacs 19.29.
-    (defun match-string (num &optional string)
-  "Return string of text matched by last search.
-NUM specifies which parenthesized expression in the last regexp.
- Value is nil if NUMth pair didn't match, or there were less than NUM pairs.
-Zero means the entire text matched by the whole regexp or whole string.
-STRING should be given if the last search was by `string-match' on STRING."
-  (if (match-beginning num)
-      (if string
-          (substring string (match-beginning num) (match-end num))
-        (buffer-substring (match-beginning num) (match-end num))))))
-
 (defun prolog-pred-start ()
   "Return the starting point of the first clause of the current predicate."
   ;; FIXME: Use SMIE.
diff --git a/lisp/progmodes/sql.el b/lisp/progmodes/sql.el
index a70b5ed..e554b2b 100644
--- a/lisp/progmodes/sql.el
+++ b/lisp/progmodes/sql.el
@@ -455,7 +455,7 @@ file.  Since that is a plaintext file, this could be 
dangerous."
      :prompt-regexp "^mysql> "
      :prompt-length 6
      :prompt-cont-regexp "^    -> "
-     :syntax-alist ((?# . "< b"))
+     :syntax-alist ((?# . "< b") (?\\ . "\\"))
      :input-filter sql-remove-tabs-filter)
 
     (oracle
@@ -1508,22 +1508,6 @@ Based on `comint-mode-map'.")
     table)
   "Syntax table used in `sql-mode' and `sql-interactive-mode'.")
 
-;;; Syntax Properties
-
-;; `sql--syntax-propertize-escaped-apostrophe', as follows, was
-;; (analysed and) adapted from `pascal--syntax-propertize' in
-;; pascal.el because basic syntax parsing cannot handle the SQL ''
-;; construct within strings.
-
-(defconst sql--syntax-propertize-escaped-apostrophe
-  (syntax-propertize-rules
-   ("''"
-    (0
-     (if (save-excursion (nth 3 (syntax-ppss (match-beginning 0))))
-        (string-to-syntax ".")
-       (forward-char -1)
-       nil)))))
-
 ;; Font lock support
 
 (defvar sql-mode-font-lock-object-name
@@ -4203,7 +4187,7 @@ must tell Emacs.  Here's how to do that in your init file:
 
 \(add-hook \\='sql-mode-hook
           (lambda ()
-           (modify-syntax-entry ?\\\\ \".\" sql-mode-syntax-table)))"
+           (modify-syntax-entry ?\\\\ \"\\\\\" sql-mode-syntax-table)))"
   :abbrev-table sql-mode-abbrev-table
 
   (if sql-mode-menu
@@ -4226,10 +4210,18 @@ must tell Emacs.  Here's how to do that in your init 
file:
   (setq-local abbrev-all-caps 1)
   ;; Contains the name of database objects
   (set (make-local-variable 'sql-contains-names) t)
-  ;; Activate punctuation syntax table property for
-  ;; escaped apostrophes within strings:
   (setq-local syntax-propertize-function
-              sql--syntax-propertize-escaped-apostrophe)
+              (syntax-propertize-rules
+               ;; Handle escaped apostrophes within strings.
+               ("''"
+                (0
+                 (if (save-excursion (nth 3 (syntax-ppss (match-beginning 0))))
+                    (string-to-syntax ".")
+                   (forward-char -1)
+                   nil)))
+               ;; Propertize rules to not have /- and -* start comments.
+               ("\\(/-\\)" (1 "."))
+               ("\\(-\\*\\)" (1 "."))))
   ;; Set syntax and font-face highlighting
   ;; Catch changes to sql-product and highlight accordingly
   (sql-set-product (or sql-product 'ansi)) ; Fixes bug#13591
diff --git a/lisp/ps-def.el b/lisp/ps-def.el
index 49d72d3..f532511 100644
--- a/lisp/ps-def.el
+++ b/lisp/ps-def.el
@@ -55,7 +55,7 @@
   (face-background face nil t))
 
 
-(defalias 'ps-frame-parameter 'frame-parameter)
+(define-obsolete-function-alias 'ps-frame-parameter #'frame-parameter "28.1")
 
 ;; Return t if the device (which can be changed during an emacs session) can
 ;; handle colors.  This function is not yet implemented for GNU emacs.
diff --git a/lisp/ps-print.el b/lisp/ps-print.el
index ace3001..17b486b 100644
--- a/lisp/ps-print.el
+++ b/lisp/ps-print.el
@@ -5761,7 +5761,7 @@ XSTART YSTART are the relative position for the first 
page in a sheet.")
                                     (eq genfunc 'ps-generate-postscript))
                                 nil)
                                ((eq ps-default-bg 'frame-parameter)
-                                (ps-frame-parameter nil 'background-color))
+                                (frame-parameter nil 'background-color))
                                ((eq ps-default-bg t)
                                 (ps-face-background-name 'default))
                                (t
@@ -5775,7 +5775,7 @@ XSTART YSTART are the relative position for the first 
page in a sheet.")
                                     (eq genfunc 'ps-generate-postscript))
                                 nil)
                                ((eq ps-default-fg 'frame-parameter)
-                                (ps-frame-parameter nil 'foreground-color))
+                                (frame-parameter nil 'foreground-color))
                                ((eq ps-default-fg t)
                                 (ps-face-foreground-name 'default))
                                (t
diff --git a/lisp/server.el b/lisp/server.el
index 1861218..9934e1c 100644
--- a/lisp/server.el
+++ b/lisp/server.el
@@ -274,10 +274,11 @@ the \"-f\" switch otherwise."
   (if internal--daemon-sockname
       (file-name-directory internal--daemon-sockname)
     (and (featurep 'make-network-process '(:family local))
-        (let ((xdg_runtime_dir (getenv "XDG_RUNTIME_DIR")))
-          (if xdg_runtime_dir
-              (format "%s/emacs" xdg_runtime_dir)
-            (format "%s/emacs%d" (or (getenv "TMPDIR") "/tmp") (user-uid))))))
+        (let ((runtime-dir (getenv "XDG_RUNTIME_DIR")))
+          (if runtime-dir
+              (expand-file-name "emacs" runtime-dir)
+            (expand-file-name (format "emacs%d" (user-uid))
+                               (or (getenv "TMPDIR") "/tmp"))))))
   "The directory in which to place the server socket.
 If local sockets are not supported, this is nil.")
 
diff --git a/lisp/shell.el b/lisp/shell.el
index dc52841..f5e18bb 100644
--- a/lisp/shell.el
+++ b/lisp/shell.el
@@ -619,7 +619,12 @@ buffer."
       ;; Bypass a bug in certain versions of bash.
       (when (string-equal shell "bash")
         (add-hook 'comint-preoutput-filter-functions
-                  #'shell-filter-ctrl-a-ctrl-b nil t)))
+                  #'shell-filter-ctrl-a-ctrl-b nil t))
+
+      ;; Skip extended history for zsh.
+      (when (string-equal shell "zsh")
+        (setq-local comint-input-ring-file-prefix
+                    ": [[:digit:]]+:[[:digit:]]+;")))
     (comint-read-input-ring t)))
 
 (defun shell-apply-ansi-color (beg end face)
diff --git a/lisp/simple.el b/lisp/simple.el
index 6c9584a..6f72c3b 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -1366,28 +1366,47 @@ END, without printing any message."
          (message "line %d (narrowed line %d)"
                   (+ n (line-number-at-pos start) -1) n))))))
 
-(defun count-lines (start end)
+(defun count-lines (start end &optional ignore-invisible-lines)
   "Return number of lines between START and END.
-This is usually the number of newlines between them,
-but can be one more if START is not equal to END
-and the greater of them is not at the start of a line."
+This is usually the number of newlines between them, but can be
+one more if START is not equal to END and the greater of them is
+not at the start of a line.
+
+When IGNORE-INVISIBLE-LINES is non-nil, invisible lines are not
+included in the count."
   (save-excursion
     (save-restriction
       (narrow-to-region start end)
       (goto-char (point-min))
-      (if (eq selective-display t)
-         (save-match-data
-           (let ((done 0))
-                     (while (re-search-forward "[\n\C-m]" nil t 40)
-                       (setq done (+ 40 done)))
-                     (while (re-search-forward "[\n\C-m]" nil t 1)
-                       (setq done (+ 1 done)))
-                     (goto-char (point-max))
-                     (if (and (/= start end)
-                      (not (bolp)))
-                 (1+ done)
-               done)))
-       (- (buffer-size) (forward-line (buffer-size)))))))
+      (cond ((and (not ignore-invisible-lines)
+                  (eq selective-display t))
+            (save-match-data
+              (let ((done 0))
+                (while (re-search-forward "\n\\|\r[^\n]" nil t 40)
+                  (setq done (+ 40 done)))
+                (while (re-search-forward "\n\\|\r[^\n]" nil t 1)
+                  (setq done (+ 1 done)))
+                (goto-char (point-max))
+                (if (and (/= start end)
+                         (not (bolp)))
+                    (1+ done)
+                  done))))
+           (ignore-invisible-lines
+            (save-match-data
+              (- (buffer-size)
+                  (forward-line (buffer-size))
+                 (let ((invisible-count 0)
+                       prop)
+                   (goto-char (point-min))
+                   (while (re-search-forward "\n\\|\r[^\n]" nil t)
+                     (setq prop (get-char-property (1- (point)) 'invisible))
+                     (if (if (eq buffer-invisibility-spec t)
+                             prop
+                           (or (memq prop buffer-invisibility-spec)
+                               (assq prop buffer-invisibility-spec)))
+                         (setq invisible-count (1+ invisible-count))))
+                   invisible-count))))
+           (t (- (buffer-size) (forward-line (buffer-size))))))))
 
 (defun line-number-at-pos (&optional pos absolute)
   "Return buffer line number at position POS.
@@ -1619,6 +1638,10 @@ display the result of expression evaluation."
   "Hook run by `eval-expression' when entering the minibuffer.")
 
 (defun read--expression (prompt &optional initial-contents)
+  "Read an Emacs Lisp expression from the minibuffer.
+
+PROMPT and optional argument INITIAL-CONTENTS do the same as in
+function `read-from-minibuffer'."
   (let ((minibuffer-completing-symbol t))
     (minibuffer-with-setup-hook
         (lambda ()
@@ -1629,11 +1652,52 @@ display the result of expression evaluation."
           (set-syntax-table emacs-lisp-mode-syntax-table)
           (add-hook 'completion-at-point-functions
                     #'elisp-completion-at-point nil t)
+          (local-set-key "\r" 'read--expression-try-read)
+          (local-set-key "\n" 'read--expression-try-read)
           (run-hooks 'eval-expression-minibuffer-setup-hook))
       (read-from-minibuffer prompt initial-contents
                             read-expression-map t
                             'read-expression-history))))
 
+(defun read--expression-try-read ()
+  "Try to read an Emacs Lisp expression in the minibuffer.
+
+Exit the minibuffer if successful, else report the error to the
+user and move point to the location of the error.  If point is
+not already at the location of the error, push a mark before
+moving point."
+  (interactive)
+  (unless (> (minibuffer-depth) 0)
+    (error "Minibuffer must be active"))
+  (if (let* ((contents (minibuffer-contents))
+             (error-point nil))
+        (with-temp-buffer
+          (condition-case err
+              (progn
+                (insert contents)
+                (goto-char (point-min))
+                ;; `read' will signal errors like "End of file during
+                ;; parsing" and "Invalid read syntax".
+                (read (current-buffer))
+                ;; Since `read' does not signal the "Trailing garbage
+                ;; following expression" error, we check for trailing
+                ;; garbage ourselves.
+                (or (progn
+                      ;; This check is similar to what `string_to_object'
+                      ;; does in minibuf.c.
+                      (skip-chars-forward " \t\n")
+                      (= (point) (point-max)))
+                    (error "Trailing garbage following expression")))
+            (error
+             (setq error-point (+ (length (minibuffer-prompt)) (point)))
+             (with-current-buffer (window-buffer (minibuffer-window))
+               (unless (= (point) error-point)
+                 (push-mark))
+               (goto-char error-point)
+               (minibuffer-message (error-message-string err)))
+             nil))))
+      (exit-minibuffer)))
+
 (defun eval-expression-get-print-arguments (prefix-argument)
   "Get arguments for commands that print an expression result.
 Returns a list (INSERT-VALUE NO-TRUNCATE CHAR-PRINT-LIMIT)
@@ -3441,8 +3505,9 @@ to `shell-command-history'."
 (defcustom async-shell-command-buffer 'confirm-new-buffer
   "What to do when the output buffer is used by another shell command.
 This option specifies how to resolve the conflict where a new command
-wants to direct its output to the buffer `shell-command-buffer-name-async',
-but this buffer is already taken by another running shell command.
+wants to direct its output to the buffer whose name is stored
+in `shell-command-buffer-name-async', but that buffer is already
+taken by another running shell command.
 
 The value `confirm-kill-process' is used to ask for confirmation before
 killing the already running process and running a new process
@@ -3593,14 +3658,18 @@ whose `car' is BUFFER."
 Like `shell-command', but adds `&' at the end of COMMAND
 to execute it asynchronously.
 
-The output appears in the buffer `shell-command-buffer-name-async'.
-That buffer is in shell mode.
+The output appears in the buffer whose name is stored in the
+variable `shell-command-buffer-name-async'.  That buffer is in
+shell mode.
 
 You can configure `async-shell-command-buffer' to specify what to do
-when the `shell-command-buffer-name-async' buffer is already taken by another
-running shell command.  To run COMMAND without displaying the output
-in a window you can configure `display-buffer-alist' to use the action
-`display-buffer-no-window' for the buffer `shell-command-buffer-name-async'.
+when the buffer specified by `shell-command-buffer-name-async' is
+already taken by another running shell command.
+
+To run COMMAND without displaying the output in a window you can
+configure `display-buffer-alist' to use the action
+`display-buffer-no-window' for the buffer given by
+`shell-command-buffer-name-async'.
 
 In Elisp, you will often be better served by calling `start-process'
 directly, since it offers more control and does not impose the use of
@@ -3636,16 +3705,18 @@ If `shell-command-prompt-show-cwd' is non-nil, show the 
current
 directory in the prompt.
 
 If COMMAND ends in `&', execute it asynchronously.
-The output appears in the buffer `shell-command-buffer-name-async'.
-That buffer is in shell mode.  You can also use
-`async-shell-command' that automatically adds `&'.
+The output appears in the buffer whose name is specified
+by `shell-command-buffer-name-async'.  That buffer is in shell
+mode.  You can also use `async-shell-command' that automatically
+adds `&'.
 
 Otherwise, COMMAND is executed synchronously.  The output appears in
-the buffer `shell-command-buffer-name'.  If the output is short enough to
-display in the echo area (which is determined by the variables
-`resize-mini-windows' and `max-mini-window-height'), it is shown
-there, but it is nonetheless available in buffer `*Shell Command
-Output*' even though that buffer is not automatically displayed.
+the buffer named by `shell-command-buffer-name'.  If the output is
+short enough to display in the echo area (which is determined by the
+variables `resize-mini-windows' and `max-mini-window-height'), it is
+shown there, but it is nonetheless available in buffer named by
+`shell-command-buffer-name' even though that buffer is not
+automatically displayed.
 
 To specify a coding system for converting non-ASCII characters
 in the shell command output, use \\[universal-coding-system-argument] \
@@ -3916,9 +3987,9 @@ and are used only if a pop-up buffer is displayed."
                                      error-buffer display-error-buffer
                                      region-noncontiguous-p)
   "Execute string COMMAND in inferior shell with region as input.
-Normally display output (if any) in temp buffer `shell-command-buffer-name';
-Prefix arg means replace the region with it.  Return the exit code of
-COMMAND.
+Normally display output (if any) in temp buffer specified
+by `shell-command-buffer-name'; prefix arg means replace the region
+with it.  Return the exit code of COMMAND.
 
 To specify a coding system for converting non-ASCII characters
 in the input and output to the shell command, use 
\\[universal-coding-system-argument]
@@ -3935,7 +4006,7 @@ in the echo area or in a buffer.
 If the output is short enough to display in the echo area
 \(determined by the variable `max-mini-window-height' if
 `resize-mini-windows' is non-nil), it is shown there.
-Otherwise it is displayed in the buffer `shell-command-buffer-name'.
+Otherwise it is displayed in the buffer named by `shell-command-buffer-name'.
 The output is available in that buffer in both cases.
 
 If there is output and an error, a message about the error
@@ -3945,7 +4016,7 @@ Optional fourth arg OUTPUT-BUFFER specifies where to put 
the
 command's output.  If the value is a buffer or buffer name,
 erase that buffer and insert the output there; a non-nil value of
 `shell-command-dont-erase-buffer' prevent to erase the buffer.
-If the value is nil, use the buffer `shell-command-buffer-name'.
+If the value is nil, use the buffer specified by `shell-command-buffer-name'.
 Any other non-nil value means to insert the output in the
 current buffer after START.
 
diff --git a/lisp/term/st.el b/lisp/term/st.el
new file mode 100644
index 0000000..617664b
--- /dev/null
+++ b/lisp/term/st.el
@@ -0,0 +1,20 @@
+;;; st.el --- terminal initialization for st  -*- lexical-binding:t -*-
+
+;; Copyright (C) 2020 Free Software Foundation, Inc.
+
+;;; Commentary:
+
+;; Support for the st terminal emulator.
+;; https://st.suckless.org/
+
+;;; Code:
+
+(require 'term/xterm)
+
+(defun terminal-init-st ()
+  "Terminal initialization function for st."
+  (tty-run-terminal-initialization (selected-frame) "xterm"))
+
+(provide 'term/st)
+
+;; st.el ends here
diff --git a/lisp/textmodes/paragraphs.el b/lisp/textmodes/paragraphs.el
index e22e3f4..b097529 100644
--- a/lisp/textmodes/paragraphs.el
+++ b/lisp/textmodes/paragraphs.el
@@ -371,33 +371,50 @@ See `forward-paragraph' for more information."
 
 (defun mark-paragraph (&optional arg allow-extend)
   "Put point at beginning of this paragraph, mark at end.
-The paragraph marked is the one that contains point or follows point.
+The paragraph marked is the one that contains point or follows
+point.
 
-With argument ARG, puts mark at end of a following paragraph, so that
-the number of paragraphs marked equals ARG.
+With argument ARG, puts mark at the end of this or a following
+paragraph, so that the number of paragraphs marked equals ARG.
 
-If ARG is negative, point is put at end of this paragraph, mark is put
-at beginning of this or a previous paragraph.
+If ARG is negative, point is put at the end of this paragraph,
+mark is put at the beginning of this or a previous paragraph.
 
 Interactively (or if ALLOW-EXTEND is non-nil), if this command is
-repeated or (in Transient Mark mode) if the mark is active,
-it marks the next ARG paragraphs after the ones already marked."
-  (interactive "p\np")
-  (unless arg (setq arg 1))
-  (when (zerop arg)
-    (error "Cannot mark zero paragraphs"))
-  (cond ((and allow-extend
-             (or (and (eq last-command this-command) (mark t))
-                 (and transient-mark-mode mark-active)))
-        (set-mark
-         (save-excursion
-           (goto-char (mark))
-           (forward-paragraph arg)
-           (point))))
-       (t
-        (forward-paragraph arg)
-        (push-mark nil t t)
-        (backward-paragraph arg))))
+repeated or (in Transient Mark mode) if the mark is active, it
+marks the next ARG paragraphs after the region already marked.
+This also means when activating the mark immediately before using
+this command, the current paragraph is only marked from point."
+  (interactive "P\np")
+  (let ((numeric-arg (prefix-numeric-value arg)))
+    (cond ((zerop numeric-arg))
+         ((and allow-extend
+               (or (and (eq last-command this-command) mark-active)
+                   (region-active-p)))
+          (if arg
+              (setq arg numeric-arg)
+            (if (< (mark) (point))
+                (setq arg -1)
+              (setq arg 1)))
+          (set-mark
+           (save-excursion
+             (goto-char (mark))
+             (forward-paragraph arg)
+             (point))))
+         ;; don't activate the mark when at eob
+         ((and (eobp) (> numeric-arg 0)))
+         (t
+          (unless (save-excursion
+                    (forward-line 0)
+                    (looking-at  paragraph-start))
+            (backward-paragraph (cond ((> numeric-arg 0) 1)
+                                       ((< numeric-arg 0) -1)
+                                       (t 0))))
+          (push-mark
+           (save-excursion
+             (forward-paragraph numeric-arg)
+             (point))
+            t t)))))
 
 (defun kill-paragraph (arg)
   "Kill forward to end of paragraph.
diff --git a/lisp/textmodes/tex-mode.el b/lisp/textmodes/tex-mode.el
index e3d5759..a905d14 100644
--- a/lisp/textmodes/tex-mode.el
+++ b/lisp/textmodes/tex-mode.el
@@ -593,7 +593,7 @@ An alternative value is \" . \", if you use a font with a 
narrow period."
            ;; Miscellany.
            (slash "\\\\")
            (opt " *\\(\\[[^]]*\\] *\\)*")
-           (args "\\(\\(?:[^{}&\\]+\\|\\\\.\\|{[^}]*}\\)+\\)")
+           (args "\\(\\(?:[^${}&\\]+\\|\\\\.\\|{[^}]*}\\)+\\)")
            (arg "{\\(\\(?:[^{}\\]+\\|\\\\.\\|{[^}]*}\\)+\\)"))
        (list
        ;;
diff --git a/lisp/textmodes/texinfo.el b/lisp/textmodes/texinfo.el
index 66378cb..b3bc634 100644
--- a/lisp/textmodes/texinfo.el
+++ b/lisp/textmodes/texinfo.el
@@ -482,6 +482,13 @@ Subexpression 1 is what goes into the corresponding `@end' 
statement.")
     (define-key map "\C-c\C-ce"    'texinfo-insert-@end)
     (define-key map "\C-c\C-cd"    'texinfo-insert-@dfn)
     (define-key map "\C-c\C-cc"    'texinfo-insert-@code)
+
+    ;; bindings for environment movement
+    (define-key map "\C-c."        'texinfo-to-environment-bounds)
+    (define-key map "\C-c\C-c\C-f" 'texinfo-next-environment-end)
+    (define-key map "\C-c\C-c\C-b" 'texinfo-previous-environment-end)
+    (define-key map "\C-c\C-c\C-n" 'texinfo-next-environment-start)
+    (define-key map "\C-c\C-c\C-p" 'texinfo-previous-environment-start)
     map))
 
 (easy-menu-define texinfo-mode-menu
@@ -1072,6 +1079,70 @@ You are prompted for the job number (use a number shown 
by a previous
   ;;               job-number"\n"))
   (tex-recenter-output-buffer nil))
 
+(defun texinfo-to-environment-bounds ()
+  "Move point alternately to the start and end of a Texinfo environment.
+Do nothing when outside of an environment.  This command does not
+handle nested environments."
+  (interactive)
+  (cond ((save-excursion
+          (forward-line 0)
+          (looking-at texinfo-environment-regexp))
+        (if (save-excursion
+              (forward-line 0)
+              (looking-at "^@end"))
+            (texinfo-previous-environment-start)
+          (texinfo-next-environment-end)))
+       ((save-excursion
+          (and (re-search-backward texinfo-environment-regexp nil t)
+               (not (looking-at "^@end"))))
+        (texinfo-previous-environment-start))
+       ;; Otherwise, point is outside of an environment, so do nothing.
+       ))
+
+(defun texinfo-next-environment-start ()
+  "Move forward to the beginning of a Texinfo environment."
+  (interactive)
+  (if (looking-at texinfo-environment-regexp)
+      (forward-line 1))
+  (while (and (re-search-forward texinfo-environment-regexp nil t)
+             (save-excursion
+               (goto-char (match-beginning 0))
+               (looking-at "@end"))))
+  (if (save-excursion
+       (forward-line 0)
+       (looking-at texinfo-environment-regexp))
+      (forward-line 0)))
+
+(defun texinfo-previous-environment-start ()
+  "Move back to the beginning of the previous Texinfo environment."
+  (interactive)
+  (while (and (re-search-backward texinfo-environment-regexp nil t)
+             (save-excursion
+               (goto-char (match-beginning 0))
+               (looking-at "@end")))))
+
+(defun texinfo-next-environment-end ()
+  "Move forward to the beginning of the next @end line of an environment."
+  (interactive)
+  (if (looking-at "^@end")
+      (forward-line 1))
+  (while (and (re-search-forward texinfo-environment-regexp nil t)
+             (save-excursion
+               (goto-char (match-beginning 0))
+               (not (looking-at "^@end")))))
+  (if (save-excursion
+       (forward-line 0)
+       (looking-at "^@end"))
+      (forward-line 0)))
+
+(defun texinfo-previous-environment-end ()
+  "Move backward to the beginning of the next @end line of an environment."
+  (interactive)
+  (while (and (re-search-backward texinfo-environment-regexp nil t)
+             (save-excursion
+               (goto-char (match-beginning 0))
+               (not (looking-at "@end"))))))
+
 (provide 'texinfo)
 
 ;;; texinfo.el ends here
diff --git a/lisp/url/url-handlers.el b/lisp/url/url-handlers.el
index 3311528..1c3607b 100644
--- a/lisp/url/url-handlers.el
+++ b/lisp/url/url-handlers.el
@@ -339,8 +339,7 @@ if it had been inserted from a file named URL."
         (decode-coding-inserted-region (point-min) (point) url
                                        visit beg end replace))
       (let ((inserted (car size-and-charset)))
-        (list url (or (and (fboundp 'after-insert-file-set-coding)
-                           (after-insert-file-set-coding inserted visit))
+        (list url (or (after-insert-file-set-coding inserted visit)
                       inserted))))))
 
 ;;;###autoload
diff --git a/lisp/vc/ediff-init.el b/lisp/vc/ediff-init.el
index da6509b..f5177bc 100644
--- a/lisp/vc/ediff-init.el
+++ b/lisp/vc/ediff-init.el
@@ -1513,21 +1513,6 @@ This default should work without changes."
 (defsubst ediff-nonempty-string-p (string)
   (and (stringp string) (not (string= string ""))))
 
-(unless (fboundp 'subst-char-in-string)
-  (defun subst-char-in-string (fromchar tochar string &optional inplace)
-    "Replace FROMCHAR with TOCHAR in STRING each time it occurs.
-Unless optional argument INPLACE is non-nil, return a new string."
-    (let ((i (length string))
-         (newstr (if inplace string (copy-sequence string))))
-      (while (> i 0)
-       (setq i (1- i))
-       (if (eq (aref newstr i) fromchar)
-           (aset newstr i tochar)))
-      newstr)))
-
-(unless (fboundp 'format-message)
-  (defalias 'format-message 'format))
-
 (defun ediff-abbrev-jobname (jobname)
   (cond ((eq jobname 'ediff-directories)
         "Compare two directories")
diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el
index e0cf9e7..78a2fa0 100644
--- a/lisp/vc/vc-git.el
+++ b/lisp/vc/vc-git.el
@@ -243,7 +243,7 @@ toggle display of the entire list."
                ;; path specs.
                ;; See also: http://marc.info/?l=git&m=125787684318129&w=2
                (name (file-relative-name file dir))
-               (str (ignore-errors
+               (str (with-demoted-errors "Error: %S"
                       (cd dir)
                       (vc-git--out-ok "ls-files" "-c" "-z" "--" name)
                       ;; If result is empty, use ls-tree to check for deleted
diff --git a/lisp/vc/vc-src.el b/lisp/vc/vc-src.el
index db127ee..4eb6389 100644
--- a/lisp/vc/vc-src.el
+++ b/lisp/vc/vc-src.el
@@ -146,6 +146,20 @@ For a description of possible values, see 
`vc-check-master-templates'."
 (progn
 (defun vc-src-registered (f) (vc-default-registered 'src f)))
 
+(defun vc-src--parse-state (out)
+  (when (null (string-match "does not exist or is unreadable" out))
+    (let ((state (aref out 0)))
+      (cond
+       ;; FIXME: What to do about L code?
+       ((eq state ?.) 'up-to-date)
+       ((eq state ?A) 'added)
+       ((eq state ?M) 'edited)
+       ((eq state ?I) 'ignored)
+       ((eq state ?R) 'removed)
+       ((eq state ?!) 'missing)
+       ((eq state ??) 'unregistered)
+       (t 'up-to-date)))))
+
 (defun vc-src-state (file)
   "SRC-specific version of `vc-state'."
   (let*
@@ -163,32 +177,41 @@ For a description of possible values, see 
`vc-check-master-templates'."
                       "status" "-a" (file-relative-name file))
                    (error nil)))))))
     (when (eq 0 status)
-      (when (null (string-match "does not exist or is unreadable" out))
-       (let ((state (aref out 0)))
-         (cond
-          ;; FIXME: What to do about A and L codes?
-          ((eq state ?.) 'up-to-date)
-          ((eq state ?A) 'added)
-          ((eq state ?M) 'edited)
-          ((eq state ?I) 'ignored)
-          ((eq state ?R) 'removed)
-          ((eq state ?!) 'missing)
-          ((eq state ??) 'unregistered)
-          (t 'up-to-date)))))))
+      (vc-src--parse-state out))))
 
 (autoload 'vc-expand-dirs "vc")
 
 (defun vc-src-dir-status-files (dir files update-function)
-  ;; FIXME: Use one src status -a call for this
-  (if (not files) (setq files (vc-expand-dirs (list dir) 'SRC)))
-  (let ((result nil))
-    (dolist (file files)
-      (let ((state (vc-state file))
-           (frel (file-relative-name file)))
-       (when (and (eq (vc-backend file) 'SRC)
-                  (not (eq state 'up-to-date)))
-         (push (list frel state) result))))
-    (funcall update-function result)))
+  (let* ((result nil)
+         (status nil)
+         (default-directory (or dir default-directory))
+         (out
+          (with-output-to-string
+            (with-current-buffer standard-output
+              (setq status
+                    (ignore-errors
+                      (apply
+                       #'process-file vc-src-program nil t nil
+                       "status" "-a"
+                       (mapcar #'file-relative-name files)))))))
+         dlist)
+    (when (eq 0 status)
+      (dolist (line (split-string out "[\n\r]" t))
+        (let* ((pair (split-string line "[\t]" t))
+               (state (vc-src--parse-state (car pair)))
+               (frel (cadr pair)))
+          (if (file-directory-p frel)
+              (push frel dlist)
+            (when (not (eq state 'up-to-date))
+              (push (list frel state) result)))))
+      (dolist (drel dlist)
+        (let ((dresult (vc-src-dir-status-files
+                        (expand-file-name drel) nil #'identity)))
+          (dolist (dres dresult)
+            (push (list (concat (file-name-as-directory drel) (car dres))
+                        (cadr dres))
+                  result))))
+      (funcall update-function result))))
 
 (defun vc-src-command (buffer file-or-list &rest flags)
   "A wrapper around `vc-do-command' for use in vc-src.el.
diff --git a/lisp/vt100-led.el b/lisp/vt100-led.el
index 7552fbb..1e81dd2 100644
--- a/lisp/vt100-led.el
+++ b/lisp/vt100-led.el
@@ -1,4 +1,4 @@
-;;; vt100-led.el --- functions for LED control on VT-100 terminals & clones
+;;; vt100-led.el --- functions for LED control on VT-100 terminals & clones  
-*- lexical-binding:t -*-
 
 ;; Copyright (C) 1988, 2001-2020 Free Software Foundation, Inc.
 
diff --git a/lisp/whitespace.el b/lisp/whitespace.el
index 42c4b61..8a1bb8a 100644
--- a/lisp/whitespace.el
+++ b/lisp/whitespace.el
@@ -262,7 +262,7 @@
 ;;
 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-;;; code:
+;;; Code:
 
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/lisp/xwidget.el b/lisp/xwidget.el
index aed6c09..0743208 100644
--- a/lisp/xwidget.el
+++ b/lisp/xwidget.el
@@ -41,7 +41,10 @@
 (declare-function xwidget-resize "xwidget.c" (xwidget new-width new-height))
 (declare-function xwidget-webkit-execute-script "xwidget.c"
                   (xwidget script &optional callback))
+(declare-function xwidget-webkit-uri "xwidget.c" (xwidget))
+(declare-function xwidget-webkit-title "xwidget.c" (xwidget))
 (declare-function xwidget-webkit-goto-uri "xwidget.c" (xwidget uri))
+(declare-function xwidget-webkit-goto-history "xwidget.c" (xwidget rel-pos))
 (declare-function xwidget-webkit-zoom "xwidget.c" (xwidget factor))
 (declare-function xwidget-plist "xwidget.c" (xwidget))
 (declare-function set-xwidget-plist "xwidget.c" (xwidget plist))
@@ -51,6 +54,10 @@
 (declare-function get-buffer-xwidgets "xwidget.c" (buffer))
 (declare-function xwidget-query-on-exit-flag "xwidget.c" (xwidget))
 
+(defgroup xwidget nil
+  "Displaying native widgets in Emacs buffers."
+  :group 'widgets)
+
 (defun xwidget-insert (pos type title width height &optional args)
   "Insert an xwidget at position POS.
 Supply the xwidget's TYPE, TITLE, WIDTH, and HEIGHT.
@@ -78,6 +85,8 @@ This returns the result of `make-xwidget'."
 ;;; webkit support
 (require 'browse-url)
 (require 'image-mode);;for some image-mode alike functionality
+(require 'seq)
+(require 'url-handlers)
 
 ;;;###autoload
 (defun xwidget-webkit-browse-url (url &optional new-session)
@@ -99,6 +108,24 @@ Interactively, URL defaults to the string looking like a 
url around point."
         (xwidget-webkit-new-session url)
       (xwidget-webkit-goto-url url))))
 
+(defun xwidget-webkit-clone-and-split-below ()
+  "Clone current URL into a new widget place in new window below.
+Get the URL of current session, then browse to the URL
+in `split-window-below' with a new xwidget webkit session."
+  (interactive)
+  (let ((url (xwidget-webkit-current-url)))
+    (with-selected-window (split-window-below)
+      (xwidget-webkit-new-session url))))
+
+(defun xwidget-webkit-clone-and-split-right ()
+  "Clone current URL into a new widget place in new window right.
+Get the URL of current session, then browse to the URL
+in `split-window-right' with a new xwidget webkit session."
+  (interactive)
+  (let ((url (xwidget-webkit-current-url)))
+    (with-selected-window (split-window-right)
+      (xwidget-webkit-new-session url))))
+
 ;;todo.
 ;; - check that the webkit support is compiled in
 (defvar xwidget-webkit-mode-map
@@ -106,6 +133,7 @@ Interactively, URL defaults to the string looking like a 
url around point."
     (define-key map "g" 'xwidget-webkit-browse-url)
     (define-key map "a" 'xwidget-webkit-adjust-size-dispatch)
     (define-key map "b" 'xwidget-webkit-back)
+    (define-key map "f" 'xwidget-webkit-forward)
     (define-key map "r" 'xwidget-webkit-reload)
     (define-key map "t" (lambda () (interactive) (message "o"))) ;FIXME: ?!?
     (define-key map "\C-m" 'xwidget-webkit-insert-string)
@@ -115,20 +143,21 @@ Interactively, URL defaults to the string looking like a 
url around point."
 
     ;;similar to image mode bindings
     (define-key map (kbd "SPC")                 'xwidget-webkit-scroll-up)
+    (define-key map (kbd "S-SPC")               'xwidget-webkit-scroll-down)
     (define-key map (kbd "DEL")                 'xwidget-webkit-scroll-down)
 
-    (define-key map [remap scroll-up]           'xwidget-webkit-scroll-up)
+    (define-key map [remap scroll-up]           'xwidget-webkit-scroll-up-line)
     (define-key map [remap scroll-up-command]   'xwidget-webkit-scroll-up)
 
-    (define-key map [remap scroll-down]         'xwidget-webkit-scroll-down)
+    (define-key map [remap scroll-down]         
'xwidget-webkit-scroll-down-line)
     (define-key map [remap scroll-down-command] 'xwidget-webkit-scroll-down)
 
     (define-key map [remap forward-char]        'xwidget-webkit-scroll-forward)
     (define-key map [remap backward-char]       
'xwidget-webkit-scroll-backward)
     (define-key map [remap right-char]          'xwidget-webkit-scroll-forward)
     (define-key map [remap left-char]           
'xwidget-webkit-scroll-backward)
-    (define-key map [remap previous-line]       'xwidget-webkit-scroll-down)
-    (define-key map [remap next-line]           'xwidget-webkit-scroll-up)
+    (define-key map [remap previous-line]       
'xwidget-webkit-scroll-down-line)
+    (define-key map [remap next-line]           'xwidget-webkit-scroll-up-line)
 
     ;; (define-key map [remap move-beginning-of-line] 'image-bol)
     ;; (define-key map [remap move-end-of-line]       'image-eol)
@@ -147,33 +176,63 @@ Interactively, URL defaults to the string looking like a 
url around point."
   (interactive)
   (xwidget-webkit-zoom (xwidget-webkit-current-session) -0.1))
 
-(defun xwidget-webkit-scroll-up ()
-  "Scroll webkit up."
-  (interactive)
+(defun xwidget-webkit-scroll-up (&optional arg)
+  "Scroll webkit up by ARG pixels; or full window height if no ARG.
+Stop if bottom of page is reached.
+Interactively, ARG is the prefix numeric argument.
+Negative ARG scrolls down."
+  (interactive "P")
   (xwidget-webkit-execute-script
    (xwidget-webkit-current-session)
-   "window.scrollBy(0, 50);"))
-
-(defun xwidget-webkit-scroll-down ()
-  "Scroll webkit down."
-  (interactive)
+   (format "window.scrollBy(0, %d);"
+           (or arg (xwidget-window-inside-pixel-height (selected-window))))))
+
+(defun xwidget-webkit-scroll-down (&optional arg)
+  "Scroll webkit down by ARG pixels; or full window height if no ARG.
+Stop if top of page is reached.
+Interactively, ARG is the prefix numeric argument.
+Negative ARG scrolls up."
+  (interactive "P")
   (xwidget-webkit-execute-script
    (xwidget-webkit-current-session)
-   "window.scrollBy(0, -50);"))
-
-(defun xwidget-webkit-scroll-forward ()
-  "Scroll webkit forwards."
-  (interactive)
+   (format "window.scrollBy(0, -%d);"
+           (or arg (xwidget-window-inside-pixel-height (selected-window))))))
+
+(defun xwidget-webkit-scroll-up-line (&optional n)
+  "Scroll webkit up by N lines.
+The height of line is calculated with `window-font-height'.
+Stop if the bottom edge of the page is reached.
+If N is omitted or nil, scroll up by one line."
+  (interactive "p")
+  (xwidget-webkit-scroll-up (* n (window-font-height))))
+
+(defun xwidget-webkit-scroll-down-line (&optional n)
+  "Scroll webkit down by N lines.
+The height of line is calculated with `window-font-height'.
+Stop if the top edge of the page is reached.
+If N is omitted or nil, scroll down by one line."
+  (interactive "p")
+  (xwidget-webkit-scroll-down (* n (window-font-height))))
+
+(defun xwidget-webkit-scroll-forward (&optional n)
+  "Scroll webkit horizontally by N chars.
+The width of char is calculated with `window-font-width'.
+If N is ommited or nil, scroll forwards by one char."
+  (interactive "p")
   (xwidget-webkit-execute-script
    (xwidget-webkit-current-session)
-   "window.scrollBy(50, 0);"))
-
-(defun xwidget-webkit-scroll-backward ()
-  "Scroll webkit backwards."
-  (interactive)
+   (format "window.scrollBy(%d, 0);"
+           (* n (window-font-width)))))
+
+(defun xwidget-webkit-scroll-backward (&optional n)
+  "Scroll webkit back by N chars.
+The width of char is calculated with `window-font-width'.
+If N is ommited or nil, scroll backwards by one char."
+  (interactive "p")
   (xwidget-webkit-execute-script
    (xwidget-webkit-current-session)
-   "window.scrollBy(-50, 0);"))
+   (format "window.scrollBy(-%d, 0);"
+           (* n (window-font-width)))))
 
 (defun xwidget-webkit-scroll-top ()
   "Scroll webkit to the very top."
@@ -187,7 +246,7 @@ Interactively, URL defaults to the string looking like a 
url around point."
   (interactive)
   (xwidget-webkit-execute-script
    (xwidget-webkit-current-session)
-   "window.scrollTo(pageXOffset, window.document.body.clientHeight);"))
+   "window.scrollTo(pageXOffset, window.document.body.scrollHeight);"))
 
 ;; The xwidget event needs to go into a higher level handler
 ;; since the xwidget can generate an event even if it's offscreen.
@@ -207,12 +266,8 @@ Interactively, URL defaults to the string looking like a 
url around point."
   (let*
       ((xwidget-event-type (nth 1 last-input-event))
        (xwidget (nth 2 last-input-event))
-       ;;(xwidget-callback (xwidget-get xwidget 'callback))
-       ;;TODO stopped working for some reason
-       )
-    ;;(funcall  xwidget-callback xwidget xwidget-event-type)
-    (message "xw callback %s" xwidget)
-    (funcall  'xwidget-webkit-callback xwidget xwidget-event-type)))
+       (xwidget-callback (xwidget-get xwidget 'callback)))
+    (funcall xwidget-callback xwidget xwidget-event-type)))
 
 (defun xwidget-webkit-callback (xwidget xwidget-event-type)
   "Callback for xwidgets.
@@ -222,21 +277,23 @@ XWIDGET instance, XWIDGET-EVENT-TYPE depends on the 
originating xwidget."
        "error: callback called for xwidget with dead buffer")
     (with-current-buffer (xwidget-buffer xwidget)
       (cond ((eq xwidget-event-type 'load-changed)
-             (xwidget-webkit-execute-script
-              xwidget "document.title"
-              (lambda (title)
-                (xwidget-log "webkit finished loading: '%s'" title)
-                ;;TODO - check the native/internal scroll
-                ;;(xwidget-adjust-size-to-content xwidget)
-                (xwidget-webkit-adjust-size-to-window xwidget)
-                (rename-buffer (format "*xwidget webkit: %s *" title))))
-             (pop-to-buffer (current-buffer)))
+             (let ((title (xwidget-webkit-title xwidget)))
+               (xwidget-log "webkit finished loading: %s" title)
+               ;; Do not adjust webkit size to window here, the selected window
+               ;; can be the mini-buffer window unwantedly.
+               (rename-buffer (format "*xwidget webkit: %s *" title) t)))
             ((eq xwidget-event-type 'decide-policy)
              (let ((strarg  (nth 3 last-input-event)))
                (if (string-match ".*#\\(.*\\)" strarg)
                    (xwidget-webkit-show-id-or-named-element
                     xwidget
                     (match-string 1 strarg)))))
+            ;; TODO: Response handling other than download.
+            ((eq xwidget-event-type 'download-callback)
+             (let ((url  (nth 3 last-input-event))
+                   (mime-type (nth 4 last-input-event))
+                   (file-name (nth 5 last-input-event)))
+               (xwidget-webkit-save-as-file url mime-type file-name)))
             ((eq xwidget-event-type 'javascript-callback)
              (let ((proc (nth 3 last-input-event))
                    (arg  (nth 4 last-input-event)))
@@ -244,21 +301,66 @@ XWIDGET instance, XWIDGET-EVENT-TYPE depends on the 
originating xwidget."
             (t (xwidget-log "unhandled event:%s" xwidget-event-type))))))
 
 (defvar bookmark-make-record-function)
+(when (memq window-system '(mac ns))
+  (defvar xwidget-webkit-enable-plugins nil
+    "Enable plugins for xwidget webkit.
+If non-nil, plugins are enabled.  Otherwise, disabled."))
+
 (define-derived-mode xwidget-webkit-mode
-    special-mode "xwidget-webkit" "Xwidget webkit view mode."
-    (setq buffer-read-only t)
-    (setq-local bookmark-make-record-function
-                #'xwidget-webkit-bookmark-make-record)
-    ;; Keep track of [vh]scroll when switching buffers
-    (image-mode-setup-winprops))
+  special-mode "xwidget-webkit" "Xwidget webkit view mode."
+  (setq buffer-read-only t)
+  (setq-local bookmark-make-record-function
+              #'xwidget-webkit-bookmark-make-record)
+  ;; Keep track of [vh]scroll when switching buffers
+  (image-mode-setup-winprops))
+
+;;; Download, save as file.
+
+(defcustom xwidget-webkit-download-dir "~/Downloads/"
+  "Directory where download file saved."
+  :version "27.1"
+  :type 'file)
+
+(defun xwidget-webkit-save-as-file (url mime-type file-name)
+  "For XWIDGET webkit, save URL of MIME-TYPE to location specified by user.
+FILE-NAME combined with `xwidget-webkit-download-dir' is the default file name
+of the prompt when reading.  When the file name the user specified is a
+directory, URL is saved at the specified directory as FILE-NAME."
+  (let ((save-name (read-file-name
+                    (format "Save URL `%s' of type `%s' in file/directory: "
+                            url mime-type)
+                    xwidget-webkit-download-dir
+                    (when file-name
+                      (expand-file-name
+                       file-name
+                       xwidget-webkit-download-dir)))))
+    (if (file-directory-p save-name)
+        (setq save-name
+              (expand-file-name (file-name-nondirectory file-name) save-name)))
+    (setq xwidget-webkit-download-dir (file-name-directory save-name))
+    (url-copy-file url save-name t)))
+
+;;; Bookmarks integration
+
+(defcustom xwidget-webkit-bookmark-jump-new-session nil
+  "Control bookmark jump to use new session or not.
+If non-nil, use a new xwidget webkit session after bookmark jump.
+Otherwise, it will use `xwidget-webkit-last-session'.
+When you set this variable to nil, consider further customization with
+`xwidget-webkit-last-session-buffer'."
+  :version "27.1"
+  :type 'boolean)
 
 (defun xwidget-webkit-bookmark-make-record ()
-  "Integrate Emacs bookmarks with the webkit xwidget."
+  "Create bookmark record in webkit xwidget."
   (nconc (bookmark-make-record-default t t)
-         `((page     . ,(xwidget-webkit-current-url))
-           (handler  . (lambda (bmk) (browse-url
-                                 (bookmark-prop-get bmk 'page)))))))
+         `((page . ,(xwidget-webkit-uri (xwidget-webkit-current-session)))
+           (handler  . (lambda (bmk)
+                         (xwidget-webkit-browse-url
+                          (bookmark-prop-get bmk 'page)
+                          xwidget-webkit-bookmark-jump-new-session))))))
 
+;;; xwidget webkit session
 
 (defvar xwidget-webkit-last-session-buffer nil)
 
@@ -306,7 +408,7 @@ function findactiveelement(doc){
 
 "
 
-  "javascript that finds the active element."
+  "Javascript that finds the active element."
   ;; Yes it's ugly, because:
   ;; - there is apparently no way to find the active frame other than recursion
   ;; - the js "for each" construct misbehaved on the "frames" collection
@@ -316,19 +418,22 @@ function findactiveelement(doc){
   )
 
 (defun xwidget-webkit-insert-string ()
-  "Prompt for a string and insert it in the active field in the
-current webkit widget."
+  "Insert string into the active field in the current webkit widget."
   ;; Read out the string in the field first and provide for edit.
   (interactive)
+  ;; As the prompt differs on JavaScript execution results,
+  ;; the function must handle the prompt itself.
   (let ((xww (xwidget-webkit-current-session)))
     (xwidget-webkit-execute-script
      xww
      (concat xwidget-webkit-activeelement-js "
 (function () {
   var res = findactiveelement(document);
-  return [res.value, res.type];
+  if (res)
+    return [res.value, res.type];
 })();")
      (lambda (field)
+       "Prompt a string for the FIELD and insert in the active input."
        (let ((str (pcase field
                     (`[,val "text"]
                      (read-string "Text: " val))
@@ -447,11 +552,23 @@ For example, use this to display an anchor."
   (ignore-errors
     (recenter-top-bottom)))
 
+;; Utility functions
+
+(defun xwidget-window-inside-pixel-width (window)
+  "Return Emacs WINDOW body width in pixel."
+  (let ((edges (window-inside-pixel-edges window)))
+    (- (nth 2 edges) (nth 0 edges))))
+
+(defun xwidget-window-inside-pixel-height (window)
+  "Return Emacs WINDOW body height in pixel."
+  (let ((edges (window-inside-pixel-edges window)))
+    (- (nth 3 edges) (nth 1 edges))))
+
 (defun xwidget-webkit-adjust-size-to-window (xwidget &optional window)
   "Adjust the size of the webkit XWIDGET to fit the WINDOW."
   (xwidget-resize xwidget
-                  (window-pixel-width window)
-                  (window-pixel-height window)))
+                  (xwidget-window-inside-pixel-width window)
+                  (xwidget-window-inside-pixel-height window)))
 
 (defun xwidget-webkit-adjust-size (w h)
   "Manually set webkit size to width W, height H."
@@ -481,51 +598,56 @@ For example, use this to display an anchor."
   (add-to-list 'window-size-change-functions
                'xwidget-webkit-adjust-size-in-frame))
 
-(defun xwidget-webkit-new-session (url)
+(defun xwidget-webkit-new-session (url &optional callback)
   "Create a new webkit session buffer with URL."
   (let*
       ((bufname (generate-new-buffer-name "*xwidget-webkit*"))
+       (callback (or callback #'xwidget-webkit-callback))
        xw)
     (setq xwidget-webkit-last-session-buffer (switch-to-buffer
                                               (get-buffer-create bufname)))
     ;; The xwidget id is stored in a text property, so we need to have
     ;; at least character in this buffer.
-    (insert " ")
-    (setq xw (xwidget-insert 1 'webkit bufname
-                             (window-pixel-width)
-                             (window-pixel-height)))
-    (xwidget-put xw 'callback 'xwidget-webkit-callback)
+    ;; Insert invisible url, good default for next `g' to browse url.
+    (let ((start (point)))
+      (insert url)
+      (put-text-property start (+ start (length url)) 'invisible t)
+      (setq xw (xwidget-insert
+                start 'webkit bufname
+                (xwidget-window-inside-pixel-width (selected-window))
+                (xwidget-window-inside-pixel-height (selected-window)))))
+    (xwidget-put xw 'callback callback)
     (xwidget-webkit-mode)
     (xwidget-webkit-goto-uri (xwidget-webkit-last-session) url)))
 
 
 (defun xwidget-webkit-goto-url (url)
-  "Goto URL."
+  "Goto URL with xwidget webkit."
   (if (xwidget-webkit-current-session)
       (progn
         (xwidget-webkit-goto-uri (xwidget-webkit-current-session) url))
     (xwidget-webkit-new-session url)))
 
 (defun xwidget-webkit-back ()
-  "Go back in history."
+  "Go back to previous URL in xwidget webkit buffer."
   (interactive)
-  (xwidget-webkit-execute-script (xwidget-webkit-current-session)
-                                 "history.go(-1);"))
+  (xwidget-webkit-goto-history (xwidget-webkit-current-session) -1))
+
+(defun xwidget-webkit-forward ()
+  "Go forward in history."
+  (interactive)
+  (xwidget-webkit-goto-history (xwidget-webkit-current-session) 1))
 
 (defun xwidget-webkit-reload ()
-  "Reload current url."
+  "Reload current URL."
   (interactive)
-  (xwidget-webkit-execute-script (xwidget-webkit-current-session)
-                                 "history.go(0);"))
+  (xwidget-webkit-goto-history (xwidget-webkit-current-session) 0))
 
 (defun xwidget-webkit-current-url ()
-  "Get the webkit url and place it on the kill-ring."
+  "Display the current xwidget webkit URL and place it on the `kill-ring'."
   (interactive)
-  (xwidget-webkit-execute-script
-   (xwidget-webkit-current-session)
-   "document.URL" (lambda (rv)
-                    (let ((url (kill-new (or rv ""))))
-                      (message "url: %s" url)))))
+  (let ((url (xwidget-webkit-uri (xwidget-webkit-current-session))))
+    (message "URL: %s" (kill-new (or url "")))))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 (defun xwidget-webkit-get-selection (proc)
@@ -536,10 +658,9 @@ For example, use this to display an anchor."
    proc))
 
 (defun xwidget-webkit-copy-selection-as-kill ()
-  "Get the webkit selection and put it on the kill-ring."
+  "Get the webkit selection and put it on the `kill-ring'."
   (interactive)
-  (xwidget-webkit-get-selection (lambda (selection) (kill-new selection))))
-
+  (xwidget-webkit-get-selection #'kill-new))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Xwidget plist management (similar to the process plist functions)
diff --git a/m4/gnulib-common.m4 b/m4/gnulib-common.m4
index 50acc0a..03da228 100644
--- a/m4/gnulib-common.m4
+++ b/m4/gnulib-common.m4
@@ -1,4 +1,4 @@
-# gnulib-common.m4 serial 53
+# gnulib-common.m4 serial 55
 dnl Copyright (C) 2007-2020 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -45,7 +45,7 @@ AC_DEFUN([gl_COMMON_BODY], [
                 ? 6000000 <= __apple_build_version__ \
                 : 3 < __clang_major__ + (5 <= __clang_minor__))))
    /* _Noreturn works as-is.  */
-# elif _GL_GNUC_PREREQ (2, 8) || 0x5110 <= __SUNPRO_C
+# elif _GL_GNUC_PREREQ (2, 8) || defined __clang__ || 0x5110 <= __SUNPRO_C
 #  define _Noreturn __attribute__ ((__noreturn__))
 # elif 1200 <= (defined _MSC_VER ? _MSC_VER : 0)
 #  define _Noreturn __declspec (noreturn)
@@ -76,6 +76,7 @@ AC_DEFUN([gl_COMMON_BODY], [
 # define _GL_ATTR_cold _GL_GNUC_PREREQ (4, 3)
 # define _GL_ATTR_const _GL_GNUC_PREREQ (2, 95)
 # define _GL_ATTR_deprecated _GL_GNUC_PREREQ (3, 1)
+# define _GL_ATTR_diagnose_if 0
 # define _GL_ATTR_error _GL_GNUC_PREREQ (4, 3)
 # define _GL_ATTR_externally_visible _GL_GNUC_PREREQ (4, 1)
 # define _GL_ATTR_fallthrough _GL_GNUC_PREREQ (7, 0)
@@ -149,6 +150,9 @@ AC_DEFUN([gl_COMMON_BODY], [
 #if _GL_HAS_ATTRIBUTE (error)
 # define _GL_ATTRIBUTE_ERROR(msg) __attribute__ ((__error__ (msg)))
 # define _GL_ATTRIBUTE_WARNING(msg) __attribute__ ((__warning__ (msg)))
+#elif _GL_HAS_ATTRIBUTE (diagnose_if)
+# define _GL_ATTRIBUTE_ERROR(msg) __attribute__ ((__diagnose_if__ (1, msg, 
"error")))
+# define _GL_ATTRIBUTE_WARNING(msg) __attribute__ ((__diagnose_if__ (1, msg, 
"warning")))
 #else
 # define _GL_ATTRIBUTE_ERROR(msg)
 # define _GL_ATTRIBUTE_WARNING(msg)
diff --git a/m4/stddef_h.m4 b/m4/stddef_h.m4
index 6bcfadb..d8bc8ff 100644
--- a/m4/stddef_h.m4
+++ b/m4/stddef_h.m4
@@ -1,5 +1,5 @@
 dnl A placeholder for <stddef.h>, for platforms that have issues.
-# stddef_h.m4 serial 6
+# stddef_h.m4 serial 7
 dnl Copyright (C) 2009-2020 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -19,7 +19,7 @@ AC_DEFUN([gl_STDDEF_H],
        [AC_LANG_PROGRAM(
           [[#include <stddef.h>
             unsigned int s = sizeof (max_align_t);
-            #if defined __GNUC__ || defined __IBM__ALIGNOF__
+            #if defined __GNUC__ || defined __clang__ || defined 
__IBM__ALIGNOF__
             int check1[2 * (__alignof__ (double) <= __alignof__ (max_align_t)) 
- 1];
             int check2[2 * (__alignof__ (long double) <= __alignof__ 
(max_align_t)) - 1];
             #endif
diff --git a/m4/stdint.m4 b/m4/stdint.m4
index 29ad826..e0fa8a5 100644
--- a/m4/stdint.m4
+++ b/m4/stdint.m4
@@ -1,4 +1,4 @@
-# stdint.m4 serial 54
+# stdint.m4 serial 55
 dnl Copyright (C) 2001-2020 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -152,7 +152,7 @@ uintmax_t j = UINTMAX_MAX;
 /* Check that SIZE_MAX has the correct type, if possible.  */
 #if 201112 <= __STDC_VERSION__
 int k = _Generic (SIZE_MAX, size_t: 0);
-#elif (2 <= __GNUC__ || defined __IBM__TYPEOF__ \
+#elif (2 <= __GNUC__ || 4 <= __clang_major__ || defined __IBM__TYPEOF__ \
        || (0x5110 <= __SUNPRO_C && !__STDC__))
 extern size_t k;
 extern __typeof__ (SIZE_MAX) k;
diff --git a/nextstep/templates/Info.plist.in b/nextstep/templates/Info.plist.in
index f791ade..1f074b0 100644
--- a/nextstep/templates/Info.plist.in
+++ b/nextstep/templates/Info.plist.in
@@ -675,8 +675,16 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.
        </array>
        <key>NSAppleScriptEnabled</key>
        <string>YES</string>
-        <key>NSAppleEventsUsageDescription</key>
-        <string>Emacs requires permission to send AppleEvents to other 
applications.</string>
+       <key>NSAppleEventsUsageDescription</key>
+       <string>Emacs requires permission to send AppleEvents to other 
applications.</string>
+       <!-- For xwidget webkit to browse remote url,
+            but this set no restriction at all.  Consult apple's documentation
+            for detail information about `NSApplicationDefinedMask'. -->
+       <key>NSAppTransportSecurity</key>
+       <dict>
+               <key>NSAllowsArbitraryLoads</key>
+               <true/>
+       </dict>
         <key>NSDesktopFolderUsageDescription</key>
         <string>Emacs requires permission to access the Desktop 
folder.</string>
         <key>NSDocumentsFolderUsageDescription</key>
diff --git a/src/Makefile.in b/src/Makefile.in
index 3cc9d59..63a4aa8 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -438,6 +438,7 @@ SOME_MACHINE_OBJECTS = dosfns.o msdos.o \
   xterm.o xfns.o xmenu.o xselect.o xrdb.o xsmfns.o fringe.o image.o \
   fontset.o dbusbind.o cygw32.o \
   nsterm.o nsfns.o nsmenu.o nsselect.o nsimage.o nsfont.o macfont.o \
+  nsxwidget.o \
   w32.o w32console.o w32cygwinx.o w32fns.o w32heap.o w32inevt.o w32notify.o \
   w32menu.o w32proc.o w32reg.o w32select.o w32term.o w32xfns.o \
   w16select.o widget.o xfont.o ftfont.o xftfont.o gtkutil.o \
diff --git a/src/bytecode.c b/src/bytecode.c
index 1913a48..1c3b6ea 100644
--- a/src/bytecode.c
+++ b/src/bytecode.c
@@ -1401,7 +1401,6 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, 
Lisp_Object maxdepth,
             Lisp_Object v1 = POP;
             ptrdiff_t i;
             struct Lisp_Hash_Table *h = XHASH_TABLE (jmp_table);
-            hash_rehash_if_needed (h);
 
             /* h->count is a faster approximation for HASH_TABLE_SIZE (h)
                here. */
diff --git a/src/composite.c b/src/composite.c
index f96f0b7..ec2b832 100644
--- a/src/composite.c
+++ b/src/composite.c
@@ -652,7 +652,6 @@ Lisp_Object
 composition_gstring_put_cache (Lisp_Object gstring, ptrdiff_t len)
 {
   struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table);
-  hash_rehash_if_needed (h);
   Lisp_Object header = LGSTRING_HEADER (gstring);
   Lisp_Object hash = h->test.hashfn (header, h);
   if (len < 0)
diff --git a/src/emacs.c b/src/emacs.c
index 8c25227..288ddb4 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -1551,6 +1551,7 @@ Using an Emacs configured with --with-x-toolkit=lucid 
does not have this problem
   if (!initialized)
     {
       init_alloc_once ();
+      init_pdumper_once ();
       init_obarray_once ();
       init_eval_once ();
       init_charset_once ();
@@ -1877,7 +1878,6 @@ Using an Emacs configured with --with-x-toolkit=lucid 
does not have this problem
       syms_of_xfns ();
       syms_of_xmenu ();
       syms_of_fontset ();
-      syms_of_xwidget ();
       syms_of_xsettings ();
 #ifdef HAVE_X_SM
       syms_of_xsmfns ();
@@ -1954,6 +1954,7 @@ Using an Emacs configured with --with-x-toolkit=lucid 
does not have this problem
 #endif /* HAVE_W32NOTIFY */
 #endif /* WINDOWSNT */
 
+      syms_of_xwidget ();
       syms_of_threads ();
       syms_of_profiler ();
       syms_of_pdumper ();
diff --git a/src/fns.c b/src/fns.c
index 811d6e8..9199178 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -4248,50 +4248,31 @@ maybe_resize_hash_table (struct Lisp_Hash_Table *h)
 
 /* Recompute the hashes (and hence also the "next" pointers).
    Normally there's never a need to recompute hashes.
-   This is done only on first-access to a hash-table loaded from
-   the "pdump", because the object's addresses may have changed, thus
-   affecting their hash.  */
+   This is done only on first access to a hash-table loaded from
+   the "pdump", because the objects' addresses may have changed, thus
+   affecting their hashes.  */
 void
-hash_table_rehash (struct Lisp_Hash_Table *h)
+hash_table_rehash (Lisp_Object hash)
 {
-  ptrdiff_t size = HASH_TABLE_SIZE (h);
-
-  /* These structures may have been purecopied and shared
-     (bug#36447).  */
-  Lisp_Object hash = make_nil_vector (size);
-  h->next = Fcopy_sequence (h->next);
-  h->index = Fcopy_sequence (h->index);
+  struct Lisp_Hash_Table *h = XHASH_TABLE (hash);
+  ptrdiff_t i, count = h->count;
 
   /* Recompute the actual hash codes for each entry in the table.
      Order is still invalid.  */
-  for (ptrdiff_t i = 0; i < size; ++i)
+  for (i = 0; i < count; i++)
     {
       Lisp_Object key = HASH_KEY (h, i);
-      if (!EQ (key, Qunbound))
-        ASET (hash, i, h->test.hashfn (key, h));
+      Lisp_Object hash_code = h->test.hashfn (key, h);
+      ptrdiff_t start_of_bucket = XUFIXNUM (hash_code) % ASIZE (h->index);
+      set_hash_hash_slot (h, i, hash_code);
+      set_hash_next_slot (h, i, HASH_INDEX (h, start_of_bucket));
+      set_hash_index_slot (h, start_of_bucket, i);
+      eassert (HASH_NEXT (h, i) != i); /* Stop loops.  */
     }
 
-  /* Reset the index so that any slot we don't fill below is marked
-     invalid.  */
-  Ffillarray (h->index, make_fixnum (-1));
-
-  /* Rebuild the collision chains.  */
-  for (ptrdiff_t i = 0; i < size; ++i)
-    if (!NILP (AREF (hash, i)))
-      {
-        EMACS_UINT hash_code = XUFIXNUM (AREF (hash, i));
-        ptrdiff_t start_of_bucket = hash_code % ASIZE (h->index);
-        set_hash_next_slot (h, i, HASH_INDEX (h, start_of_bucket));
-        set_hash_index_slot (h, start_of_bucket, i);
-        eassert (HASH_NEXT (h, i) != i); /* Stop loops.  */
-      }
-
-  /* Finally, mark the hash table as having a valid hash order.
-     Do this last so that if we're interrupted, we retry on next
-     access. */
-  eassert (hash_rehash_needed_p (h));
-  h->hash = hash;
-  eassert (!hash_rehash_needed_p (h));
+  ptrdiff_t size = ASIZE (h->next);
+  for (; i + 1 < size; i++)
+    set_hash_next_slot (h, i, i + 1);
 }
 
 /* Lookup KEY in hash table H.  If HASH is non-null, return in *HASH
@@ -4303,8 +4284,6 @@ hash_lookup (struct Lisp_Hash_Table *h, Lisp_Object key, 
Lisp_Object *hash)
 {
   ptrdiff_t start_of_bucket, i;
 
-  hash_rehash_if_needed (h);
-
   Lisp_Object hash_code = h->test.hashfn (key, h);
   if (hash)
     *hash = hash_code;
@@ -4339,8 +4318,6 @@ hash_put (struct Lisp_Hash_Table *h, Lisp_Object key, 
Lisp_Object value,
 {
   ptrdiff_t start_of_bucket, i;
 
-  hash_rehash_if_needed (h);
-
   /* Increment count after resizing because resizing may fail.  */
   maybe_resize_hash_table (h);
   h->count++;
@@ -4373,8 +4350,6 @@ hash_remove_from_table (struct Lisp_Hash_Table *h, 
Lisp_Object key)
   ptrdiff_t start_of_bucket = XUFIXNUM (hash_code) % ASIZE (h->index);
   ptrdiff_t prev = -1;
 
-  hash_rehash_if_needed (h);
-
   for (ptrdiff_t i = HASH_INDEX (h, start_of_bucket);
        0 <= i;
        i = HASH_NEXT (h, i))
@@ -4415,8 +4390,7 @@ hash_clear (struct Lisp_Hash_Table *h)
   if (h->count > 0)
     {
       ptrdiff_t size = HASH_TABLE_SIZE (h);
-      if (!hash_rehash_needed_p (h))
-       memclear (xvector_contents (h->hash), size * word_size);
+      memclear (xvector_contents (h->hash), size * word_size);
       for (ptrdiff_t i = 0; i < size; i++)
        {
          set_hash_next_slot (h, i, i < size - 1 ? i + 1 : -1);
@@ -4452,9 +4426,7 @@ sweep_weak_table (struct Lisp_Hash_Table *h, bool 
remove_entries_p)
   for (ptrdiff_t bucket = 0; bucket < n; ++bucket)
     {
       /* Follow collision chain, removing entries that don't survive
-         this garbage collection.  It's okay if hash_rehash_needed_p
-         (h) is true, since we're operating entirely on the cached
-         hash values. */
+         this garbage collection.  */
       ptrdiff_t prev = -1;
       ptrdiff_t next;
       for (ptrdiff_t i = HASH_INDEX (h, bucket); 0 <= i; i = next)
@@ -4499,7 +4471,7 @@ sweep_weak_table (struct Lisp_Hash_Table *h, bool 
remove_entries_p)
                     set_hash_hash_slot (h, i, Qnil);
 
                   eassert (h->count != 0);
-                  h->count += h->count > 0 ? -1 : 1;
+                  h->count--;
                 }
              else
                {
@@ -4923,7 +4895,6 @@ DEFUN ("hash-table-count", Fhash_table_count, 
Shash_table_count, 1, 1, 0,
   (Lisp_Object table)
 {
   struct Lisp_Hash_Table *h = check_hash_table (table);
-  eassert (h->count >= 0);
   return make_fixnum (h->count);
 }
 
diff --git a/src/json.c b/src/json.c
index 814afc6..8c95836 100644
--- a/src/json.c
+++ b/src/json.c
@@ -479,9 +479,7 @@ lisp_to_json (Lisp_Object lisp, struct json_configuration 
*conf)
     {
       intmax_t low = TYPE_MINIMUM (json_int_t);
       intmax_t high = TYPE_MAXIMUM (json_int_t);
-      intmax_t value;
-      if (! (integer_to_intmax (lisp, &value) && low <= value && value <= 
high))
-        args_out_of_range_3 (lisp, make_int (low), make_int (high));
+      intmax_t value = check_integer_range (lisp, low, high);
       return json_check (json_integer (value));
     }
   else if (FLOATP (lisp))
diff --git a/src/lisp.h b/src/lisp.h
index 75ef6d3..5f913b7 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -2286,11 +2286,7 @@ struct hash_table_test
 
 struct Lisp_Hash_Table
 {
-  /* Change pdumper.c if you change the fields here.
-
-     IMPORTANT!!!!!!!
-
-     Call hash_rehash_if_needed() before accessing.  */
+  /* Change pdumper.c if you change the fields here.  */
 
   /* This is for Lisp; the hash table code does not refer to it.  */
   union vectorlike_header header;
@@ -2409,20 +2405,7 @@ HASH_TABLE_SIZE (const struct Lisp_Hash_Table *h)
   return size;
 }
 
-void hash_table_rehash (struct Lisp_Hash_Table *h);
-
-INLINE bool
-hash_rehash_needed_p (const struct Lisp_Hash_Table *h)
-{
-  return NILP (h->hash);
-}
-
-INLINE void
-hash_rehash_if_needed (struct Lisp_Hash_Table *h)
-{
-  if (hash_rehash_needed_p (h))
-    hash_table_rehash (h);
-}
+void hash_table_rehash (Lisp_Object);
 
 /* Default size for hash tables if not specified.  */
 
@@ -3975,7 +3958,8 @@ make_uninit_sub_char_table (int depth, int min_char)
   return v;
 }
 
-/* Make a vector of SIZE nils.  */
+/* Make a vector of SIZE nils - faster than make_vector (size, Qnil)
+   if the OS already cleared the new memory.  */
 
 INLINE Lisp_Object
 make_nil_vector (ptrdiff_t size)
diff --git a/src/macfont.m b/src/macfont.m
index 21bc7dd..c7430d3 100644
--- a/src/macfont.m
+++ b/src/macfont.m
@@ -1120,7 +1120,10 @@ struct macfont_metrics
      glyph width.  The `width_int' member is an integer that is
      closest to the width.  The `width_frac' member is the fractional
      adjustment representing a value in [-.5, .5], multiplied by
-     WIDTH_FRAC_SCALE.  For synthetic monospace fonts, they represent
+     WIDTH_FRAC_SCALE.  For monospace fonts, non-zero `width_frac'
+     means `width_int' is further adjusted to a multiple of the
+     (rounded) font width, and `width_frac' represents adjustment per
+     unit character.  For synthetic monospace fonts, they represent
      the advance delta for centering instead of the glyph width.  */
   signed width_frac : WIDTH_FRAC_BITS, width_int : 16 - WIDTH_FRAC_BITS;
 };
@@ -1148,6 +1151,27 @@ enum metrics_status
 #define LCD_FONT_SMOOTHING_LEFT_MARGIN (0.396f)
 #define LCD_FONT_SMOOTHING_RIGHT_MARGIN        (0.396f)
 
+/* If FONT is monospace and WIDTH can be regarded as a multiple of its
+   width where the multiplier is greater than 1, then return the
+   multiplier.  Otherwise return 0.  */
+static int
+macfont_monospace_width_multiplier (struct font *font, CGFloat width)
+{
+  struct macfont_info *macfont_info = (struct macfont_info *) font;
+  int multiplier = 0;
+
+  if (macfont_info->spacing == MACFONT_SPACING_MONO
+      && font->space_width != 0)
+    {
+      multiplier = lround (width / font->space_width);
+      if (multiplier == 1
+         || lround (width / multiplier) != font->space_width)
+       multiplier = 0;
+    }
+
+  return multiplier;
+}
+
 static int
 macfont_glyph_extents (struct font *font, CGGlyph glyph,
                        struct font_metrics *metrics, CGFloat *advance_delta,
@@ -1192,13 +1216,38 @@ macfont_glyph_extents (struct font *font, CGGlyph glyph,
       else
         fwidth = mac_font_get_advance_width_for_glyph (macfont, glyph);
 
-      /* For synthetic mono fonts, cache->width_{int,frac} holds the
-         advance delta value.  */
-      if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
-        fwidth = (font->pixel_size - fwidth) / 2;
-      cache->width_int = lround (fwidth);
-      cache->width_frac = lround ((fwidth - cache->width_int)
-                                  * WIDTH_FRAC_SCALE);
+      if (macfont_info->spacing == MACFONT_SPACING_MONO)
+       {
+         /* Some monospace fonts for programming languages contain
+            wider ligature glyphs consisting of multiple characters.
+            For such glyphs, simply rounding the combined fractional
+            width to an integer can result in a value that is not a
+            multiple of the (rounded) font width.  */
+         int multiplier = macfont_monospace_width_multiplier (font, fwidth);
+
+         if (multiplier)
+           {
+             cache->width_int = font->space_width * multiplier;
+             cache->width_frac = lround ((fwidth / multiplier
+                                          - font->space_width)
+                                         * WIDTH_FRAC_SCALE);
+           }
+         else
+           {
+             cache->width_int = lround (fwidth);
+             cache->width_frac = 0;
+           }
+       }
+      else
+       {
+         /* For synthetic mono fonts, cache->width_{int,frac} holds
+            the advance delta value.  */
+         if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
+           fwidth = (font->pixel_size - fwidth) / 2;
+         cache->width_int = lround (fwidth);
+         cache->width_frac = lround ((fwidth - cache->width_int)
+                                     * WIDTH_FRAC_SCALE);
+       }
       METRICS_SET_STATUS (cache, METRICS_WIDTH_VALID);
     }
   if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
@@ -1235,6 +1284,10 @@ macfont_glyph_extents (struct font *font, CGGlyph glyph,
                                     / (CGFloat) (WIDTH_FRAC_SCALE * 2));
               break;
             case MACFONT_SPACING_MONO:
+             if (cache->width_frac)
+               bounds.origin.x += - ((cache->width_frac
+                                      / (CGFloat) (WIDTH_FRAC_SCALE * 2))
+                                     * (cache->width_int / font->space_width));
               break;
             case MACFONT_SPACING_SYNTHETIC_MONO:
               bounds.origin.x += (cache->width_int
@@ -1271,7 +1324,16 @@ macfont_glyph_extents (struct font *font, CGGlyph glyph,
                                  / (CGFloat) (WIDTH_FRAC_SCALE * 2)));
           break;
         case MACFONT_SPACING_MONO:
-          *advance_delta = 0;
+         if (cache->width_frac)
+           *advance_delta = 0;
+         else
+           {
+             CGFloat delta = - ((cache->width_frac
+                                 / (CGFloat) (WIDTH_FRAC_SCALE * 2))
+                                * (cache->width_int / font->space_width));
+
+             *advance_delta = (force_integral_p ? round (delta) : delta);
+           }
           break;
         case MACFONT_SPACING_SYNTHETIC_MONO:
           *advance_delta = (force_integral_p ? cache->width_int
@@ -3015,7 +3077,7 @@ macfont_shape (Lisp_Object lgstring, Lisp_Object 
direction)
       struct mac_glyph_layout *gl = glyph_layouts + i;
       EMACS_INT from, to;
       struct font_metrics metrics;
-      int xoff, yoff, wadjust;
+      int xoff, yoff, wadjust, multiplier;
 
       if (NILP (lglyph))
         {
@@ -3068,7 +3130,11 @@ macfont_shape (Lisp_Object lgstring, Lisp_Object 
direction)
 
       xoff = lround (gl->advance_delta);
       yoff = lround (- gl->baseline_delta);
-      wadjust = lround (gl->advance);
+      multiplier = macfont_monospace_width_multiplier (font, gl->advance);
+      if (multiplier)
+       wadjust = font->space_width * multiplier;
+      else
+       wadjust = lround (gl->advance);
       if (xoff != 0 || yoff != 0 || wadjust != metrics.width)
         {
           Lisp_Object vec = make_uninit_vector (3);
diff --git a/src/minibuf.c b/src/minibuf.c
index 9d870ce..cb302c5 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -1212,9 +1212,6 @@ is used to further constrain the set of candidates.  */)
       bucket = AREF (collection, idx);
     }
 
-  if (HASH_TABLE_P (collection))
-    hash_rehash_if_needed (XHASH_TABLE (collection));
-
   while (1)
     {
       /* Get the next element of the alist, obarray, or hash-table.  */
diff --git a/src/nsterm.m b/src/nsterm.m
index 572b859..9f5916d 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -49,6 +49,7 @@ GNUstep port and post-20 update by Adrian Robert 
(arobert@cogsci.ucsd.edu)
 #include "nsterm.h"
 #include "systime.h"
 #include "character.h"
+#include "xwidget.h"
 #include "fontset.h"
 #include "composite.h"
 #include "ccl.h"
@@ -2600,7 +2601,8 @@ frame_set_mouse_pixel_position (struct frame *f, int 
pix_x, int pix_y)
 }
 
 static int
-ns_note_mouse_movement (struct frame *frame, CGFloat x, CGFloat y)
+ns_note_mouse_movement (struct frame *frame, CGFloat x, CGFloat y,
+                       BOOL dragging)
 /*   ------------------------------------------------------------------------
      Called by EmacsView on mouseMovement events.  Passes on
      to emacs mainstream code if we moved off of a rect of interest
@@ -2609,17 +2611,24 @@ ns_note_mouse_movement (struct frame *frame, CGFloat x, 
CGFloat y)
 {
   struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame);
   NSRect *r;
+  BOOL force_update = NO;
 
   // NSTRACE ("note_mouse_movement");
 
   dpyinfo->last_mouse_motion_frame = frame;
   r = &dpyinfo->last_mouse_glyph;
 
+  /* If the last rect is too large (ex, xwidget webkit), update at
+     every move, or resizing by dragging modeline or vertical split is
+     very hard to make its way.  */
+  if (dragging && (r->size.width > 32 || r->size.height > 32))
+    force_update = YES;
+
   /* Note, this doesn't get called for enter/leave, since we don't have a
      position.  Those are taken care of in the corresponding NSView methods.  
*/
 
   /* Has movement gone beyond last rect we were tracking?  */
-  if (x < r->origin.x || x >= r->origin.x + r->size.width
+  if (force_update || x < r->origin.x || x >= r->origin.x + r->size.width
       || y < r->origin.y || y >= r->origin.y + r->size.height)
     {
       ns_update_begin (frame);
@@ -4368,6 +4377,10 @@ ns_draw_glyph_string (struct glyph_string *s)
       ns_unfocus (s->f);
       break;
 
+    case XWIDGET_GLYPH:
+      x_draw_xwidget_glyph_string (s);
+      break;
+
     case STRETCH_GLYPH:
       ns_dumpglyphs_stretch (s);
       break;
@@ -7065,6 +7078,7 @@ not_in_argv (NSString *arg)
   struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (emacsframe);
   Lisp_Object frame;
   NSPoint pt;
+  BOOL dragging;
 
   NSTRACE_WHEN (NSTRACE_GROUP_EVENTS, "[EmacsView mouseMoved:]");
 
@@ -7107,7 +7121,8 @@ not_in_argv (NSString *arg)
       last_mouse_window = window;
     }
 
-  if (!ns_note_mouse_movement (emacsframe, pt.x, pt.y))
+  dragging = (e.type == NSEventTypeLeftMouseDragged);
+  if (!ns_note_mouse_movement (emacsframe, pt.x, pt.y, dragging))
     help_echo_string = previous_help_echo_string;
 
   XSETFRAME (frame, emacsframe);
diff --git a/src/nsxwidget.h b/src/nsxwidget.h
new file mode 100644
index 0000000..3d91594
--- /dev/null
+++ b/src/nsxwidget.h
@@ -0,0 +1,80 @@
+/* Header for NS Cocoa part of xwidget and webkit widget.
+
+Copyright (C) 2019-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 <http://www.gnu.org/licenses/>.  */
+
+#ifndef NSXWIDGET_H_INCLUDED
+#define NSXWIDGET_H_INCLUDED
+
+/* This file can be included from non-objc files through 'xwidget.h'.  */
+#ifdef __OBJC__
+#import <AppKit/NSView.h>
+#endif
+
+#include "dispextern.h"
+#include "lisp.h"
+#include "xwidget.h"
+
+/* Functions for xwidget webkit.  */
+
+bool nsxwidget_is_web_view (struct xwidget *xw);
+Lisp_Object nsxwidget_webkit_uri (struct xwidget *xw);
+Lisp_Object nsxwidget_webkit_title (struct xwidget *xw);
+void nsxwidget_webkit_goto_uri (struct xwidget *xw, const char *uri);
+void nsxwidget_webkit_goto_history (struct xwidget *xw, int rel_pos);
+void nsxwidget_webkit_zoom (struct xwidget *xw, double zoom_change);
+void nsxwidget_webkit_execute_script (struct xwidget *xw, const char *script,
+                                      Lisp_Object fun);
+
+/* Functions for xwidget model.  */
+
+#ifdef __OBJC__
+@interface XwWindow : NSView
+@property struct xwidget *xw;
+@end
+#endif
+
+void nsxwidget_init (struct xwidget *xw);
+void nsxwidget_kill (struct xwidget *xw);
+void nsxwidget_resize (struct xwidget *xw);
+Lisp_Object nsxwidget_get_size (struct xwidget *xw);
+
+/* Functions for xwidget view.  */
+
+#ifdef __OBJC__
+@interface XvWindow : NSView
+@property struct xwidget *xw;
+@property struct xwidget_view *xv;
+@end
+#endif
+
+void nsxwidget_init_view (struct xwidget_view *xv,
+                          struct xwidget *xww,
+                          struct glyph_string *s,
+                          int x, int y);
+void nsxwidget_delete_view (struct xwidget_view *xv);
+
+void nsxwidget_show_view (struct xwidget_view *xv);
+void nsxwidget_hide_view (struct xwidget_view *xv);
+void nsxwidget_resize_view (struct xwidget_view *xv,
+                            int widget, int height);
+
+void nsxwidget_move_view (struct xwidget_view *xv, int x, int y);
+void nsxwidget_move_widget_in_view (struct xwidget_view *xv, int x, int y);
+void nsxwidget_set_needsdisplay (struct xwidget_view *xv);
+
+#endif /* NSXWIDGET_H_INCLUDED */
diff --git a/src/nsxwidget.m b/src/nsxwidget.m
new file mode 100644
index 0000000..370abee
--- /dev/null
+++ b/src/nsxwidget.m
@@ -0,0 +1,601 @@
+/* NS Cocoa part implementation of xwidget and webkit widget.
+
+Copyright (C) 2019-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 <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include "lisp.h"
+#include "blockinput.h"
+#include "dispextern.h"
+#include "buffer.h"
+#include "frame.h"
+#include "nsterm.h"
+#include "xwidget.h"
+
+#import <AppKit/AppKit.h>
+#import <WebKit/WebKit.h>
+
+/* Thoughts on NS Cocoa xwidget and webkit2:
+
+   Webkit2 process architecture seems to be very hostile for offscreen
+   rendering techniques, which is used by GTK xwiget implementation;
+   Specifically NSView level view sharing / copying is not working.
+
+   *** So only one view can be associcated with a model. ***
+
+   With this decision, implementation is plain and can expect best out
+   of webkit2's rationale.  But process and session structures will
+   diverge from GTK xwiget.  Though, cosmetically similar usages can
+   be presented and will be preferred, if agreeable.
+
+   For other widget types, OSR seems possible, but will not care for a
+   while.  */
+
+/* Xwidget webkit.  */
+
+@interface XwWebView : WKWebView
+<WKNavigationDelegate, WKUIDelegate, WKScriptMessageHandler>
+@property struct xwidget *xw;
+/* Map url to whether javascript is blocked by
+   'Content-Security-Policy' sandbox without allow-scripts.  */
+@property(retain) NSMutableDictionary *urlScriptBlocked;
+@end
+@implementation XwWebView : WKWebView
+
+- (id)initWithFrame:(CGRect)frame
+      configuration:(WKWebViewConfiguration *)configuration
+            xwidget:(struct xwidget *)xw
+{
+  /* Script controller to add script message handler and user script.  */
+  WKUserContentController *scriptor = [[WKUserContentController alloc] init];
+  configuration.userContentController = scriptor;
+
+  /* Enable inspect element context menu item for debugging.  */
+  [configuration.preferences setValue:@YES
+                               forKey:@"developerExtrasEnabled"];
+
+  Lisp_Object enablePlugins =
+    Fintern (build_string ("xwidget-webkit-enable-plugins"), Qnil);
+  if (!EQ (Fsymbol_value (enablePlugins), Qnil))
+    configuration.preferences.plugInsEnabled = YES;
+
+  self = [super initWithFrame:frame configuration:configuration];
+  if (self)
+    {
+      self.xw = xw;
+      self.urlScriptBlocked = [[NSMutableDictionary alloc] init];
+      self.navigationDelegate = self;
+      self.UIDelegate = self;
+      self.customUserAgent =
+        @"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)"
+        @" AppleWebKit/603.3.8 (KHTML, like Gecko)"
+        @" Version/11.0.1 Safari/603.3.8";
+      [scriptor addScriptMessageHandler:self name:@"keyDown"];
+      [scriptor addUserScript:[[WKUserScript alloc]
+                                initWithSource:xwScript
+                                 injectionTime:
+                                  WKUserScriptInjectionTimeAtDocumentStart
+                                forMainFrameOnly:NO]];
+    }
+  return self;
+}
+
+- (void)webView:(WKWebView *)webView
+didFinishNavigation:(WKNavigation *)navigation
+{
+  if (EQ (Fbuffer_live_p (self.xw->buffer), Qt))
+    store_xwidget_event_string (self.xw, "load-changed", "");
+}
+
+- (void)webView:(WKWebView *)webView
+decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction
+decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
+{
+  switch (navigationAction.navigationType) {
+  case WKNavigationTypeLinkActivated:
+    decisionHandler (WKNavigationActionPolicyAllow);
+    break;
+  default:
+    // decisionHandler (WKNavigationActionPolicyCancel);
+    decisionHandler (WKNavigationActionPolicyAllow);
+    break;
+  }
+}
+
+- (void)webView:(WKWebView *)webView
+decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse
+decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
+{
+  if (!navigationResponse.canShowMIMEType)
+    {
+      NSString *url = navigationResponse.response.URL.absoluteString;
+      NSString *mimetype = navigationResponse.response.MIMEType;
+      NSString *filename = navigationResponse.response.suggestedFilename;
+      decisionHandler (WKNavigationResponsePolicyCancel);
+      store_xwidget_download_callback_event (self.xw,
+                                             url.UTF8String,
+                                             mimetype.UTF8String,
+                                             filename.UTF8String);
+      return;
+    }
+  decisionHandler (WKNavigationResponsePolicyAllow);
+
+  self.urlScriptBlocked[navigationResponse.response.URL] =
+    [NSNumber numberWithBool:NO];
+  if ([navigationResponse.response isKindOfClass:[NSHTTPURLResponse class]])
+    {
+      NSDictionary *headers =
+        ((NSHTTPURLResponse *) navigationResponse.response).allHeaderFields;
+      NSString *value = headers[@"Content-Security-Policy"];
+      if (value)
+        {
+          /* TODO: Sloppy parsing of 'Content-Security-Policy' value.  */
+          NSRange sandbox = [value rangeOfString:@"sandbox"];
+          if (sandbox.location != NSNotFound
+              && (sandbox.location == 0
+                  || [value characterAtIndex:(sandbox.location - 1)] == ' '
+                  || [value characterAtIndex:(sandbox.location - 1)] == ';'))
+            {
+              NSRange allowScripts = [value rangeOfString:@"allow-scripts"];
+              if (allowScripts.location == NSNotFound
+                  || allowScripts.location < sandbox.location)
+                self.urlScriptBlocked[navigationResponse.response.URL] =
+                  [NSNumber numberWithBool:YES];
+            }
+        }
+    }
+}
+
+/* No additional new webview or emacs window will be created
+   for <a ... target="_blank">.  */
+- (WKWebView *)webView:(WKWebView *)webView
+createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration
+   forNavigationAction:(WKNavigationAction *)navigationAction
+        windowFeatures:(WKWindowFeatures *)windowFeatures
+{
+  if (!navigationAction.targetFrame.isMainFrame)
+    [webView loadRequest:navigationAction.request];
+  return nil;
+}
+
+/* Open panel for file upload.  */
+- (void)webView:(WKWebView *)webView
+runOpenPanelWithParameters:(WKOpenPanelParameters *)parameters
+initiatedByFrame:(WKFrameInfo *)frame
+completionHandler:(void (^)(NSArray<NSURL *> *URLs))completionHandler
+{
+  NSOpenPanel *openPanel = [NSOpenPanel openPanel];
+  openPanel.canChooseFiles = YES;
+  openPanel.canChooseDirectories = NO;
+  openPanel.allowsMultipleSelection = parameters.allowsMultipleSelection;
+  if ([openPanel runModal] == NSModalResponseOK)
+    completionHandler (openPanel.URLs);
+  else
+    completionHandler (nil);
+}
+
+/* By forwarding mouse events to emacs view (frame)
+   - Mouse click in webview selects the window contains the webview.
+   - Correct mouse hand/arrow/I-beam is displayed (TODO: not perfect yet).
+*/
+
+- (void)mouseDown:(NSEvent *)event
+{
+  [self.xw->xv->emacswindow mouseDown:event];
+  [super mouseDown:event];
+}
+
+- (void)mouseUp:(NSEvent *)event
+{
+  [self.xw->xv->emacswindow mouseUp:event];
+  [super mouseUp:event];
+}
+
+/* Basically we want keyboard events handled by emacs unless an input
+   element has focus.  Especially, while incremental search, we set
+   emacs as first responder to avoid focus held in an input element
+   with matching text.  */
+
+- (void)keyDown:(NSEvent *)event
+{
+  Lisp_Object var = Fintern (build_string ("isearch-mode"), Qnil);
+  Lisp_Object val = buffer_local_value (var, Fcurrent_buffer ());
+  if (!EQ (val, Qunbound) && !EQ (val, Qnil))
+    {
+      [self.window makeFirstResponder:self.xw->xv->emacswindow];
+      [self.xw->xv->emacswindow keyDown:event];
+      return;
+    }
+
+  /* Emacs handles keyboard events when javascript is blocked.  */
+  if ([self.urlScriptBlocked[self.URL] boolValue])
+    {
+      [self.xw->xv->emacswindow keyDown:event];
+      return;
+    }
+
+  [self evaluateJavaScript:@"xwHasFocus()"
+         completionHandler:^(id result, NSError *error) {
+      if (error)
+        {
+          NSLog (@"xwHasFocus: %@", error);
+          [self.xw->xv->emacswindow keyDown:event];
+        }
+      else if (result)
+        {
+          NSNumber *hasFocus = result; /* __NSCFBoolean */
+          if (!hasFocus.boolValue)
+            [self.xw->xv->emacswindow keyDown:event];
+          else
+            [super keyDown:event];
+        }
+    }];
+}
+
+- (void)interpretKeyEvents:(NSArray<NSEvent *> *)eventArray
+{
+  /* We should do nothing and do not forward (default implementation
+     if we not override here) to let emacs collect key events and ask
+     interpretKeyEvents to its superclass.  */
+}
+
+static NSString *xwScript;
++ (void)initialize
+{
+  /* Find out if an input element has focus.
+     Message to script message handler when 'C-g' key down.  */
+  if (!xwScript)
+    xwScript =
+      @"function xwHasFocus() {"
+      @"  var ae = document.activeElement;"
+      @"  if (ae) {"
+      @"    var name = ae.nodeName;"
+      @"    return name == 'INPUT' || name == 'TEXTAREA';"
+      @"  } else {"
+      @"    return false;"
+      @"  }"
+      @"}"
+      @"function xwKeyDown(event) {"
+      @"  if (event.ctrlKey && event.key == 'g') {"
+      @"    window.webkit.messageHandlers.keyDown.postMessage('C-g');"
+      @"  }"
+      @"}"
+      @"document.addEventListener('keydown', xwKeyDown);"
+      ;
+}
+
+/* Confirming to WKScriptMessageHandler, listens concerning keyDown in
+   webkit. Currently 'C-g'.  */
+- (void)userContentController:(WKUserContentController *)userContentController
+      didReceiveScriptMessage:(WKScriptMessage *)message
+{
+  if ([message.body isEqualToString:@"C-g"])
+    {
+      /* Just give up focus, no relay "C-g" to emacs, another "C-g"
+         follows will be handled by emacs.  */
+      [self.window makeFirstResponder:self.xw->xv->emacswindow];
+    }
+}
+
+@end
+
+/* Xwidget webkit commands.  */
+
+static Lisp_Object build_string_with_nsstr (NSString *nsstr);
+
+bool
+nsxwidget_is_web_view (struct xwidget *xw)
+{
+  return xw->xwWidget != NULL &&
+    [xw->xwWidget isKindOfClass:WKWebView.class];
+}
+
+Lisp_Object
+nsxwidget_webkit_uri (struct xwidget *xw)
+{
+  XwWebView *xwWebView = (XwWebView *) xw->xwWidget;
+  return build_string_with_nsstr (xwWebView.URL.absoluteString);
+}
+
+Lisp_Object
+nsxwidget_webkit_title (struct xwidget *xw)
+{
+  XwWebView *xwWebView = (XwWebView *) xw->xwWidget;
+  return build_string_with_nsstr (xwWebView.title);
+}
+
+/* @Note ATS - Need application transport security in 'Info.plist' or
+   remote pages will not loaded.  */
+void
+nsxwidget_webkit_goto_uri (struct xwidget *xw, const char *uri)
+{
+  XwWebView *xwWebView = (XwWebView *) xw->xwWidget;
+  NSString *urlString = [NSString stringWithUTF8String:uri];
+  NSURL *url = [NSURL URLWithString:urlString];
+  NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
+  [xwWebView loadRequest:urlRequest];
+}
+
+void
+nsxwidget_webkit_goto_history (struct xwidget *xw, int rel_pos)
+{
+  XwWebView *xwWebView = (XwWebView *) xw->xwWidget;
+  switch (rel_pos) {
+  case -1: [xwWebView goBack]; break;
+  case 0: [xwWebView reload]; break;
+  case 1: [xwWebView goForward]; break;
+  }
+}
+
+void
+nsxwidget_webkit_zoom (struct xwidget *xw, double zoom_change)
+{
+  XwWebView *xwWebView = (XwWebView *) xw->xwWidget;
+  xwWebView.magnification += zoom_change;
+  /* TODO: setMagnification:centeredAtPoint.  */
+}
+
+/* Build lisp string */
+static Lisp_Object
+build_string_with_nsstr (NSString *nsstr)
+{
+  const char *utfstr = [nsstr UTF8String];
+  NSUInteger bytes = [nsstr lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
+  return make_string (utfstr, bytes);
+}
+
+/* Recursively convert an objc native type JavaScript value to a Lisp
+   value.  Mostly copied from GTK xwidget 'webkit_js_to_lisp'.  */
+static Lisp_Object
+js_to_lisp (id value)
+{
+  if (value == nil || [value isKindOfClass:NSNull.class])
+    return Qnil;
+  else if ([value isKindOfClass:NSString.class])
+    return build_string_with_nsstr ((NSString *) value);
+  else if ([value isKindOfClass:NSNumber.class])
+    {
+      NSNumber *nsnum = (NSNumber *) value;
+      char type = nsnum.objCType[0];
+      if (type == 'c') /* __NSCFBoolean has type character 'c'.  */
+        return nsnum.boolValue? Qt : Qnil;
+      else
+        {
+          if (type == 'i' || type == 'l')
+            return make_int (nsnum.longValue);
+          else if (type == 'f' || type == 'd')
+            return make_float (nsnum.doubleValue);
+          /* else fall through.  */
+        }
+    }
+  else if ([value isKindOfClass:NSArray.class])
+    {
+      NSArray *nsarr = (NSArray *) value;
+      EMACS_INT n = nsarr.count;
+      Lisp_Object obj;
+      struct Lisp_Vector *p = allocate_vector (n);
+
+      for (ptrdiff_t i = 0; i < n; ++i)
+        p->contents[i] = js_to_lisp ([nsarr objectAtIndex:i]);
+      XSETVECTOR (obj, p);
+      return obj;
+    }
+  else if ([value isKindOfClass:NSDictionary.class])
+    {
+      NSDictionary *nsdict = (NSDictionary *) value;
+      NSArray *keys = nsdict.allKeys;
+      ptrdiff_t n = keys.count;
+      Lisp_Object obj;
+      struct Lisp_Vector *p = allocate_vector (n);
+
+      for (ptrdiff_t i = 0; i < n; ++i)
+        {
+          NSString *prop_key = (NSString *) [keys objectAtIndex:i];
+          id prop_value = [nsdict valueForKey:prop_key];
+          p->contents[i] = Fcons (build_string_with_nsstr (prop_key),
+                                  js_to_lisp (prop_value));
+        }
+      XSETVECTOR (obj, p);
+      return obj;
+    }
+  NSLog (@"Unhandled type in javascript result");
+  return Qnil;
+}
+
+void
+nsxwidget_webkit_execute_script (struct xwidget *xw, const char *script,
+                                 Lisp_Object fun)
+{
+  XwWebView *xwWebView = (XwWebView *) xw->xwWidget;
+  if ([xwWebView.urlScriptBlocked[xwWebView.URL] boolValue])
+    {
+      message ("Javascript is blocked by 'CSP: sandbox'.");
+      return;
+    }
+
+  NSString *javascriptString = [NSString stringWithUTF8String:script];
+  [xwWebView evaluateJavaScript:javascriptString
+              completionHandler:^(id result, NSError *error) {
+      if (error)
+        {
+          NSLog (@"evaluateJavaScript error : %@", error.localizedDescription);
+          NSLog (@"error script=%@", javascriptString);
+        }
+      else if (result && FUNCTIONP (fun))
+        {
+          // NSLog (@"result=%@, type=%@", result, [result class]);
+          Lisp_Object lisp_value = js_to_lisp (result);
+          store_xwidget_js_callback_event (xw, fun, lisp_value);
+        }
+    }];
+}
+
+/* Window containing an xwidget.  */
+
+@implementation XwWindow
+- (BOOL)isFlipped { return YES; }
+@end
+
+/* Xwidget model, macOS Cocoa part.  */
+
+void
+nsxwidget_init(struct xwidget *xw)
+{
+  block_input ();
+  NSRect rect = NSMakeRect (0, 0, xw->width, xw->height);
+  xw->xwWidget = [[XwWebView alloc]
+                   initWithFrame:rect
+                   configuration:[[WKWebViewConfiguration alloc] init]
+                         xwidget:xw];
+  xw->xwWindow = [[XwWindow alloc]
+                   initWithFrame:rect];
+  [xw->xwWindow addSubview:xw->xwWidget];
+  xw->xv = NULL; /* for 1 to 1 relationship of webkit2.  */
+  unblock_input ();
+}
+
+void
+nsxwidget_kill (struct xwidget *xw)
+{
+  if (xw)
+    {
+      WKUserContentController *scriptor =
+        ((XwWebView *) xw->xwWidget).configuration.userContentController;
+      [scriptor removeAllUserScripts];
+      [scriptor removeScriptMessageHandlerForName:@"keyDown"];
+      [scriptor release];
+      if (xw->xv)
+        xw->xv->model = Qnil; /* Make sure related view stale.  */
+
+      /* This stops playing audio when a xwidget-webkit buffer is
+         killed.  I could not find other solution.  */
+      nsxwidget_webkit_goto_uri (xw, "about:blank");
+
+      [((XwWebView *) xw->xwWidget).urlScriptBlocked release];
+      [xw->xwWidget removeFromSuperviewWithoutNeedingDisplay];
+      [xw->xwWidget release];
+      [xw->xwWindow removeFromSuperviewWithoutNeedingDisplay];
+      [xw->xwWindow release];
+      xw->xwWidget = nil;
+    }
+}
+
+void
+nsxwidget_resize (struct xwidget *xw)
+{
+  if (xw->xwWidget)
+    {
+      [xw->xwWindow setFrameSize:NSMakeSize(xw->width, xw->height)];
+      [xw->xwWidget setFrameSize:NSMakeSize(xw->width, xw->height)];
+    }
+}
+
+Lisp_Object
+nsxwidget_get_size (struct xwidget *xw)
+{
+  return list2i (xw->xwWidget.frame.size.width,
+                 xw->xwWidget.frame.size.height);
+}
+
+/* Xwidget view, macOS Cocoa part.  */
+
+@implementation XvWindow : NSView
+- (BOOL)isFlipped { return YES; }
+@end
+
+void
+nsxwidget_init_view (struct xwidget_view *xv,
+                     struct xwidget *xw,
+                     struct glyph_string *s,
+                     int x, int y)
+{
+  /* 'x_draw_xwidget_glyph_string' will calculate correct position and
+     size of clip to draw in emacs buffer window.  Thus, just begin at
+     origin with no crop.  */
+  xv->x = x;
+  xv->y = y;
+  xv->clip_left = 0;
+  xv->clip_right = xw->width;
+  xv->clip_top = 0;
+  xv->clip_bottom = xw->height;
+
+  xv->xvWindow = [[XvWindow alloc]
+                   initWithFrame:NSMakeRect (x, y, xw->width, xw->height)];
+  xv->xvWindow.xw = xw;
+  xv->xvWindow.xv = xv;
+
+  xw->xv = xv; /* For 1 to 1 relationship of webkit2.  */
+  [xv->xvWindow addSubview:xw->xwWindow];
+
+  xv->emacswindow = FRAME_NS_VIEW (s->f);
+  [xv->emacswindow addSubview:xv->xvWindow];
+}
+
+void
+nsxwidget_delete_view (struct xwidget_view *xv)
+{
+  if (!EQ (xv->model, Qnil))
+    {
+      struct xwidget *xw = XXWIDGET (xv->model);
+      [xw->xwWindow removeFromSuperviewWithoutNeedingDisplay];
+      xw->xv = NULL; /* Now model has no view.  */
+    }
+  [xv->xvWindow removeFromSuperviewWithoutNeedingDisplay];
+  [xv->xvWindow release];
+}
+
+void
+nsxwidget_show_view (struct xwidget_view *xv)
+{
+  xv->hidden = NO;
+  [xv->xvWindow setFrameOrigin:NSMakePoint(xv->x + xv->clip_left,
+                                           xv->y + xv->clip_top)];
+}
+
+void
+nsxwidget_hide_view (struct xwidget_view *xv)
+{
+  xv->hidden = YES;
+  [xv->xvWindow setFrameOrigin:NSMakePoint(10000, 10000)];
+}
+
+void
+nsxwidget_resize_view (struct xwidget_view *xv, int width, int height)
+{
+  [xv->xvWindow setFrameSize:NSMakeSize(width, height)];
+}
+
+void
+nsxwidget_move_view (struct xwidget_view *xv, int x, int y)
+{
+  [xv->xvWindow setFrameOrigin:NSMakePoint (x, y)];
+}
+
+/* Move model window in container (view window).  */
+void
+nsxwidget_move_widget_in_view (struct xwidget_view *xv, int x, int y)
+{
+  struct xwidget *xww = xv->xvWindow.xw;
+  [xww->xwWindow setFrameOrigin:NSMakePoint (x, y)];
+}
+
+void
+nsxwidget_set_needsdisplay (struct xwidget_view *xv)
+{
+  xv->xvWindow.needsDisplay = YES;
+}
diff --git a/src/pdumper.c b/src/pdumper.c
index de9c06c..c55b6f7 100644
--- a/src/pdumper.c
+++ b/src/pdumper.c
@@ -71,17 +71,7 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 #ifdef HAVE_PDUMPER
 
 #if GNUC_PREREQ (4, 7, 0)
-# pragma GCC diagnostic error "-Wconversion"
-# pragma GCC diagnostic ignored "-Wsign-conversion"
 # pragma GCC diagnostic error "-Wshadow"
-# define ALLOW_IMPLICIT_CONVERSION                       \
-  _Pragma ("GCC diagnostic push")                        \
-  _Pragma ("GCC diagnostic ignored \"-Wconversion\"")
-# define DISALLOW_IMPLICIT_CONVERSION \
-  _Pragma ("GCC diagnostic pop")
-#else
-# define ALLOW_IMPLICIT_CONVERSION ((void) 0)
-# define DISALLOW_IMPLICIT_CONVERSION ((void) 0)
 #endif
 
 #define VM_POSIX 1
@@ -105,17 +95,6 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 # define VM_SUPPORTED 0
 #endif
 
-/* PDUMPER_CHECK_REHASHING being true causes the portable dumper to
-   check, for each hash table it dumps, that the hash table means the
-   same thing after rehashing.  */
-#ifndef PDUMPER_CHECK_REHASHING
-# if ENABLE_CHECKING
-#  define PDUMPER_CHECK_REHASHING 1
-# else
-#  define PDUMPER_CHECK_REHASHING 0
-# endif
-#endif
-
 /* Require an architecture in which pointers, ptrdiff_t and intptr_t
    are the same size and have the same layout, and where bytes have
    eight bits --- that is, a general-purpose computer made after 1990.
@@ -152,8 +131,11 @@ static int nr_remembered_data = 0;
 typedef int_least32_t dump_off;
 #define DUMP_OFF_MIN INT_LEAST32_MIN
 #define DUMP_OFF_MAX INT_LEAST32_MAX
+#define PRIdDUMP_OFF PRIdLEAST32
+
+enum { EMACS_INT_XDIGITS = (EMACS_INT_WIDTH + 3) / 4 };
 
-static void ATTRIBUTE_FORMAT ((printf, 1, 2))
+static void ATTRIBUTE_FORMAT_PRINTF (1, 2)
 dump_trace (const char *fmt, ...)
 {
   if (0)
@@ -326,9 +308,7 @@ static void
 dump_reloc_set_offset (struct dump_reloc *reloc, dump_off offset)
 {
   eassert (offset >= 0);
-  ALLOW_IMPLICIT_CONVERSION;
   reloc->raw_offset = offset >> DUMP_RELOC_ALIGNMENT_BITS;
-  DISALLOW_IMPLICIT_CONVERSION;
   if (dump_reloc_get_offset (*reloc) != offset)
     error ("dump relocation out of range");
 }
@@ -417,6 +397,9 @@ struct dump_header
      The start of the cold region is always aligned on a page
      boundary.  */
   dump_off cold_start;
+
+  /* Offset of a vector of the dumped hash tables.  */
+  dump_off hash_list;
 };
 
 /* Double-ended singly linked list.  */
@@ -575,8 +558,11 @@ struct dump_context
      heap objects.  */
   Lisp_Object bignum_data;
 
-  unsigned number_hot_relocations;
-  unsigned number_discardable_relocations;
+  /* List of hash tables that have been dumped.  */
+  Lisp_Object hash_tables;
+
+  dump_off number_hot_relocations;
+  dump_off number_discardable_relocations;
 };
 
 /* These special values for use as offsets in dump_remember_object and
@@ -763,10 +749,7 @@ dump_off_from_lisp (Lisp_Object value)
 {
   intmax_t n = intmax_t_from_lisp (value);
   eassert (DUMP_OFF_MIN <= n && n <= DUMP_OFF_MAX);
-  ALLOW_IMPLICIT_CONVERSION;
-  dump_off converted = n;
-  DISALLOW_IMPLICIT_CONVERSION;
-  return converted;
+  return n;
 }
 
 static Lisp_Object
@@ -983,11 +966,9 @@ dump_queue_init (struct dump_queue *dump_queue)
 static bool
 dump_queue_empty_p (struct dump_queue *dump_queue)
 {
-  bool is_empty =
-    EQ (Fhash_table_count (dump_queue->sequence_numbers),
-        make_fixnum (0));
-  eassert (EQ (Fhash_table_count (dump_queue->sequence_numbers),
-               Fhash_table_count (dump_queue->link_weights)));
+  ptrdiff_t count = XHASH_TABLE (dump_queue->sequence_numbers)->count;
+  bool is_empty = count == 0;
+  eassert (count == XFIXNAT (Fhash_table_count (dump_queue->link_weights)));
   if (!is_empty)
     {
       eassert (!dump_tailq_empty_p (&dump_queue->zero_weight_objects)
@@ -1029,9 +1010,9 @@ dump_queue_enqueue (struct dump_queue *dump_queue,
   if (NILP (weights))
     {
       /* Object is new.  */
-      dump_trace ("new object %016x weight=%u\n",
-                  (unsigned) XLI (object),
-                  (unsigned) weight.value);
+      EMACS_UINT uobj = XLI (object);
+      dump_trace ("new object %0*"pI"x weight=%d\n", EMACS_INT_XDIGITS, uobj,
+                 weight.value);
 
       if (weight.value == WEIGHT_NONE.value)
         {
@@ -1246,17 +1227,15 @@ dump_queue_dequeue (struct dump_queue *dump_queue, 
dump_off basis)
               + dump_tailq_length (&dump_queue->one_weight_normal_objects)
               + dump_tailq_length (&dump_queue->one_weight_strong_objects)));
 
-  bool dump_object_counts = true;
-  if (dump_object_counts)
-    dump_trace
-      ("dump_queue_dequeue basis=%d fancy=%u zero=%u "
-       "normal=%u strong=%u hash=%u\n",
-       basis,
-       (unsigned) dump_tailq_length (&dump_queue->fancy_weight_objects),
-       (unsigned) dump_tailq_length (&dump_queue->zero_weight_objects),
-       (unsigned) dump_tailq_length (&dump_queue->one_weight_normal_objects),
-       (unsigned) dump_tailq_length (&dump_queue->one_weight_strong_objects),
-       (unsigned) XFIXNUM (Fhash_table_count (dump_queue->link_weights)));
+  dump_trace
+    (("dump_queue_dequeue basis=%"PRIdDUMP_OFF" fancy=%"PRIdPTR
+      " zero=%"PRIdPTR" normal=%"PRIdPTR" strong=%"PRIdPTR" hash=%td\n"),
+     basis,
+     dump_tailq_length (&dump_queue->fancy_weight_objects),
+     dump_tailq_length (&dump_queue->zero_weight_objects),
+     dump_tailq_length (&dump_queue->one_weight_normal_objects),
+     dump_tailq_length (&dump_queue->one_weight_strong_objects),
+     XHASH_TABLE (dump_queue->link_weights)->count);
 
   static const int nr_candidates = 3;
   struct candidate
@@ -1329,10 +1308,10 @@ dump_queue_dequeue (struct dump_queue *dump_queue, 
dump_off basis)
   else
     emacs_abort ();
 
-  dump_trace ("  result score=%f src=%s object=%016x\n",
+  EMACS_UINT uresult = XLI (result);
+  dump_trace ("  result score=%f src=%s object=%0*"pI"x\n",
               best < 0 ? -1.0 : (double) candidates[best].score,
-              src,
-              (unsigned) XLI (result));
+             src, EMACS_INT_XDIGITS, uresult);
 
   {
     Lisp_Object weights = Fgethash (result, dump_queue->link_weights, Qnil);
@@ -2017,11 +1996,7 @@ static dump_off
 finish_dump_pvec (struct dump_context *ctx,
                   union vectorlike_header *out_hdr)
 {
-  ALLOW_IMPLICIT_CONVERSION;
-  dump_off result = dump_object_finish (ctx, out_hdr,
-                                       vectorlike_nbytes (out_hdr));
-  DISALLOW_IMPLICIT_CONVERSION;
-  return result;
+  return dump_object_finish (ctx, out_hdr, vectorlike_nbytes (out_hdr));
 }
 
 static void
@@ -2633,78 +2608,65 @@ dump_vectorlike_generic (struct dump_context *ctx,
   return offset;
 }
 
-/* Determine whether the hash table's hash order is stable
-   across dump and load.  If it is, we don't have to trigger
-   a rehash on access.  */
-static bool
-dump_hash_table_stable_p (const struct Lisp_Hash_Table *hash)
+/* Return a vector of KEY, VALUE pairs in the given hash table H.  The
+   first H->count pairs are valid, and the rest are unbound.  */
+static Lisp_Object
+hash_table_contents (struct Lisp_Hash_Table *h)
 {
-  if (hash->test.hashfn == hashfn_user_defined)
+  if (h->test.hashfn == hashfn_user_defined)
     error ("cannot dump hash tables with user-defined tests");  /* Bug#36769 */
-  bool is_eql = hash->test.hashfn == hashfn_eql;
-  bool is_equal = hash->test.hashfn == hashfn_equal;
-  ptrdiff_t size = HASH_TABLE_SIZE (hash);
-  for (ptrdiff_t i = 0; i < size; ++i)
+
+  ptrdiff_t size = HASH_TABLE_SIZE (h);
+  Lisp_Object key_and_value = make_uninit_vector (2 * size);
+  ptrdiff_t n = 0;
+
+  /* Make sure key_and_value ends up in the same order; charset.c
+     relies on it by expecting hash table indices to stay constant
+     across the dump.  */
+  for (ptrdiff_t i = 0; i < size; i++)
+    if (!NILP (HASH_HASH (h, i)))
+      {
+       ASET (key_and_value, n++, HASH_KEY (h, i));
+       ASET (key_and_value, n++, HASH_VALUE (h, i));
+      }
+
+  while (n < 2 * size)
     {
-      Lisp_Object key =  HASH_KEY (hash, i);
-      if (!EQ (key, Qunbound))
-        {
-         bool key_stable = (dump_builtin_symbol_p (key)
-                            || FIXNUMP (key)
-                            || (is_equal
-                                && (STRINGP (key) || BOOL_VECTOR_P (key)))
-                            || ((is_equal || is_eql)
-                                && (FLOATP (key) || BIGNUMP (key))));
-          if (!key_stable)
-            return false;
-        }
+      ASET (key_and_value, n++, Qunbound);
+      ASET (key_and_value, n++, Qnil);
     }
 
-  return true;
+  return key_and_value;
 }
 
-/* Return a list of (KEY . VALUE) pairs in the given hash table.  */
-static Lisp_Object
-hash_table_contents (Lisp_Object table)
+static dump_off
+dump_hash_table_list (struct dump_context *ctx)
 {
-  Lisp_Object contents = Qnil;
-  struct Lisp_Hash_Table *h = XHASH_TABLE (table);
-  for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i)
-    {
-      Lisp_Object key =  HASH_KEY (h, i);
-      if (!EQ (key, Qunbound))
-        dump_push (&contents, Fcons (key, HASH_VALUE (h, i)));
-    }
-  return Fnreverse (contents);
+  if (!NILP (ctx->hash_tables))
+    return dump_object (ctx, CALLN (Fapply, Qvector, ctx->hash_tables));
+  else
+    return 0;
 }
 
-/* Copy the given hash table, rehash it, and make sure that we can
-   look up all the values in the original.  */
 static void
-check_hash_table_rehash (Lisp_Object table_orig)
-{
-  ptrdiff_t count = XHASH_TABLE (table_orig)->count;
-  hash_rehash_if_needed (XHASH_TABLE (table_orig));
-  Lisp_Object table_rehashed = Fcopy_hash_table (table_orig);
-  eassert (!hash_rehash_needed_p (XHASH_TABLE (table_rehashed)));
-  XHASH_TABLE (table_rehashed)->hash = Qnil;
-  eassert (count == 0 || hash_rehash_needed_p (XHASH_TABLE (table_rehashed)));
-  hash_rehash_if_needed (XHASH_TABLE (table_rehashed));
-  eassert (!hash_rehash_needed_p (XHASH_TABLE (table_rehashed)));
-  Lisp_Object expected_contents = hash_table_contents (table_orig);
-  while (!NILP (expected_contents))
-    {
-      Lisp_Object key_value_pair = dump_pop (&expected_contents);
-      Lisp_Object key = XCAR (key_value_pair);
-      Lisp_Object expected_value = XCDR (key_value_pair);
-      Lisp_Object arbitrary = Qdump_emacs_portable__sort_predicate_copied;
-      Lisp_Object found_value = Fgethash (key, table_rehashed, arbitrary);
-      eassert (EQ (expected_value, found_value));
-      Fremhash (key, table_rehashed);
-    }
+hash_table_freeze (struct Lisp_Hash_Table *h)
+{
+  ptrdiff_t npairs = ASIZE (h->key_and_value) / 2;
+  h->key_and_value = hash_table_contents (h);
+  h->next = h->hash = make_fixnum (npairs);
+  h->index = make_fixnum (ASIZE (h->index));
+  h->next_free = (npairs == h->count ? -1 : h->count);
+}
 
-  eassert (EQ (Fhash_table_count (table_rehashed),
-               make_fixnum (0)));
+static void
+hash_table_thaw (Lisp_Object hash)
+{
+  struct Lisp_Hash_Table *h = XHASH_TABLE (hash);
+  h->hash = make_nil_vector (XFIXNUM (h->hash));
+  h->next = Fmake_vector (h->next, make_fixnum (-1));
+  h->index = Fmake_vector (h->index, make_fixnum (-1));
+
+  hash_table_rehash (hash);
 }
 
 static dump_off
@@ -2712,55 +2674,15 @@ dump_hash_table (struct dump_context *ctx,
                  Lisp_Object object,
                  dump_off offset)
 {
-#if CHECK_STRUCTS && !defined HASH_Lisp_Hash_Table_12AFBF47AF
+#if CHECK_STRUCTS && !defined HASH_Lisp_Hash_Table_6D63EDB618
 # error "Lisp_Hash_Table changed. See CHECK_STRUCTS comment in config.h."
 #endif
   const struct Lisp_Hash_Table *hash_in = XHASH_TABLE (object);
-  bool is_stable = dump_hash_table_stable_p (hash_in);
-  /* If the hash table is likely to be modified in memory (either
-     because we need to rehash, and thus toggle hash->count, or
-     because we need to assemble a list of weak tables) punt the hash
-     table to the end of the dump, where we can lump all such hash
-     tables together.  */
-  if (!(is_stable || !NILP (hash_in->weak))
-      && ctx->flags.defer_hash_tables)
-    {
-      if (offset != DUMP_OBJECT_ON_HASH_TABLE_QUEUE)
-        {
-         eassert (offset == DUMP_OBJECT_ON_NORMAL_QUEUE
-                  || offset == DUMP_OBJECT_NOT_SEEN);
-          /* We still want to dump the actual keys and values now.  */
-          dump_enqueue_object (ctx, hash_in->key_and_value, WEIGHT_NONE);
-          /* We'll get to the rest later.  */
-          offset = DUMP_OBJECT_ON_HASH_TABLE_QUEUE;
-          dump_remember_object (ctx, object, offset);
-          dump_push (&ctx->deferred_hash_tables, object);
-        }
-      return offset;
-    }
-
-  if (PDUMPER_CHECK_REHASHING)
-    check_hash_table_rehash (make_lisp_ptr ((void *) hash_in, 
Lisp_Vectorlike));
-
   struct Lisp_Hash_Table hash_munged = *hash_in;
   struct Lisp_Hash_Table *hash = &hash_munged;
 
-  /* Remember to rehash this hash table on first access.  After a
-     dump reload, the hash table values will have changed, so we'll
-     need to rebuild the index.
-
-     TODO: for EQ and EQL hash tables, it should be possible to rehash
-     here using the preferred load address of the dump, eliminating
-     the need to rehash-on-access if we can load the dump where we
-     want.  */
-  if (hash->count > 0 && !is_stable)
-    /* Hash codes will have to be recomputed anyway, so let's not dump them.
-       Also set `hash` to nil for hash_rehash_needed_p.
-       We could also refrain from dumping the `next' and `index' vectors,
-       except that `next' is currently used for HASH_TABLE_SIZE and
-       we'd have to rebuild the next_free list as well as adjust
-       sweep_weak_hash_table for the case where there's no `index'.  */
-    hash->hash = Qnil;
+  hash_table_freeze (hash);
+  dump_push (&ctx->hash_tables, object);
 
   START_DUMP_PVEC (ctx, &hash->header, struct Lisp_Hash_Table, out);
   dump_pseudovector_lisp_fields (ctx, &out->header, &hash->header);
@@ -3429,9 +3351,7 @@ static void
 dump_cold_charset (struct dump_context *ctx, Lisp_Object data)
 {
   /* Dump charset lookup tables.  */
-  ALLOW_IMPLICIT_CONVERSION;
   int cs_i = XFIXNUM (XCAR (data));
-  DISALLOW_IMPLICIT_CONVERSION;
   dump_off cs_dump_offset = dump_off_from_lisp (XCDR (data));
   dump_remember_fixup_ptr_raw
     (ctx,
@@ -3767,9 +3687,7 @@ static struct emacs_reloc
 decode_emacs_reloc (struct dump_context *ctx, Lisp_Object lreloc)
 {
   struct emacs_reloc reloc = {0};
-  ALLOW_IMPLICIT_CONVERSION;
   int type = XFIXNUM (dump_pop (&lreloc));
-  DISALLOW_IMPLICIT_CONVERSION;
   reloc.emacs_offset = dump_off_from_lisp (dump_pop (&lreloc));
   dump_check_emacs_off (reloc.emacs_offset);
   switch (type)
@@ -3780,9 +3698,7 @@ decode_emacs_reloc (struct dump_context *ctx, Lisp_Object 
lreloc)
         reloc.u.dump_offset = dump_off_from_lisp (dump_pop (&lreloc));
         dump_check_dump_off (ctx, reloc.u.dump_offset);
         dump_off length = dump_off_from_lisp (dump_pop (&lreloc));
-        ALLOW_IMPLICIT_CONVERSION;
         reloc.length = length;
-        DISALLOW_IMPLICIT_CONVERSION;
         if (reloc.length != length)
           error ("relocation copy length too large");
       }
@@ -3793,9 +3709,7 @@ decode_emacs_reloc (struct dump_context *ctx, Lisp_Object 
lreloc)
         intmax_t value = intmax_t_from_lisp (dump_pop (&lreloc));
         dump_off size = dump_off_from_lisp (dump_pop (&lreloc));
         reloc.u.immediate = value;
-        ALLOW_IMPLICIT_CONVERSION;
         reloc.length = size;
-        DISALLOW_IMPLICIT_CONVERSION;
         eassert (reloc.length == size);
       }
       break;
@@ -3820,9 +3734,7 @@ decode_emacs_reloc (struct dump_context *ctx, Lisp_Object 
lreloc)
            RELOC_EMACS_IMMEDIATE relocation instead.  */
         eassert (!dump_object_self_representing_p (target_value));
         int tag_type = XTYPE (target_value);
-        ALLOW_IMPLICIT_CONVERSION;
         reloc.length = tag_type;
-        DISALLOW_IMPLICIT_CONVERSION;
         eassert (reloc.length == tag_type);
 
         if (type == RELOC_EMACS_EMACS_LV)
@@ -3897,9 +3809,7 @@ dump_merge_emacs_relocs (Lisp_Object lreloc_a, 
Lisp_Object lreloc_b)
     return Qnil;
 
   dump_off new_length = reloc_a.length + reloc_b.length;
-  ALLOW_IMPLICIT_CONVERSION;
   reloc_a.length = new_length;
-  DISALLOW_IMPLICIT_CONVERSION;
   if (reloc_a.length != new_length)
     return Qnil; /* Overflow */
 
@@ -4254,6 +4164,19 @@ types.  */)
         || !NILP (ctx->deferred_hash_tables)
         || !NILP (ctx->deferred_symbols));
 
+  ctx->header.hash_list = ctx->offset;
+  dump_hash_table_list (ctx);
+
+  do
+    {
+      dump_drain_deferred_hash_tables (ctx);
+      dump_drain_deferred_symbols (ctx);
+      dump_drain_normal_queue (ctx);
+    }
+  while (!dump_queue_empty_p (&ctx->dump_queue)
+        || !NILP (ctx->deferred_hash_tables)
+        || !NILP (ctx->deferred_symbols));
+
   dump_sort_copied_objects (ctx);
 
   /* While we copy built-in symbols into the Emacs image, these
@@ -4314,9 +4237,9 @@ types.  */)
   for (int i = 0; i < RELOC_NUM_PHASES; ++i)
     drain_reloc_list (ctx, dump_emit_dump_reloc, emacs_reloc_merger,
                      &ctx->dump_relocs[i], &ctx->header.dump_relocs[i]);
-  unsigned number_hot_relocations = ctx->number_hot_relocations;
+  dump_off number_hot_relocations = ctx->number_hot_relocations;
   ctx->number_hot_relocations = 0;
-  unsigned number_discardable_relocations = 
ctx->number_discardable_relocations;
+  dump_off number_discardable_relocations = 
ctx->number_discardable_relocations;
   ctx->number_discardable_relocations = 0;
   drain_reloc_list (ctx, dump_emit_dump_reloc, emacs_reloc_merger,
                    &ctx->object_starts, &ctx->header.object_starts);
@@ -4341,14 +4264,17 @@ types.  */)
   dump_seek (ctx, 0);
   dump_write (ctx, &ctx->header, sizeof (ctx->header));
 
+  dump_off
+    header_bytes = header_end - header_start,
+    hot_bytes = hot_end - hot_start,
+    discardable_bytes = discardable_end - ctx->header.discardable_start,
+    cold_bytes = cold_end - ctx->header.cold_start;
   fprintf (stderr,
           ("Dump complete\n"
-           "Byte counts: header=%lu hot=%lu discardable=%lu cold=%lu\n"
-           "Reloc counts: hot=%u discardable=%u\n"),
-           (unsigned long) (header_end - header_start),
-           (unsigned long) (hot_end - hot_start),
-           (unsigned long) (discardable_end - ctx->header.discardable_start),
-           (unsigned long) (cold_end - ctx->header.cold_start),
+           "Byte counts: header=%"PRIdDUMP_OFF" hot=%"PRIdDUMP_OFF
+           " discardable=%"PRIdDUMP_OFF" cold=%"PRIdDUMP_OFF"\n"
+           "Reloc counts: hot=%"PRIdDUMP_OFF" discardable=%"PRIdDUMP_OFF"\n"),
+          header_bytes, hot_bytes, discardable_bytes, cold_bytes,
            number_hot_relocations,
            number_discardable_relocations);
 
@@ -5214,14 +5140,13 @@ dump_read_all (int fd, void *buf, size_t bytes_to_read)
 {
   /* We don't want to use emacs_read, since that relies on the lisp
      world, and we're not in the lisp world yet.  */
-  eassert (bytes_to_read <= SSIZE_MAX);
   size_t bytes_read = 0;
   while (bytes_read < bytes_to_read)
     {
-      /* Some platforms accept only int-sized values to read.  */
-      unsigned chunk_to_read = INT_MAX;
-      if (bytes_to_read - bytes_read < chunk_to_read)
-       chunk_to_read = (unsigned) (bytes_to_read - bytes_read);
+      /* Some platforms accept only int-sized values to read.
+         Round this down to a page size (see MAX_RW_COUNT in sysdep.c).  */
+      int max_rw_count = INT_MAX >> 18 << 18;
+      int chunk_to_read = min (bytes_to_read - bytes_read, max_rw_count);
       ssize_t chunk = read (fd, (char *) buf + bytes_read, chunk_to_read);
       if (chunk < 0)
         return chunk;
@@ -5485,6 +5410,9 @@ enum dump_section
    NUMBER_DUMP_SECTIONS,
   };
 
+/* Pointer to a stack variable to avoid having to staticpro it.  */
+static Lisp_Object *pdumper_hashes = &zero_vector;
+
 /* Load a dump from DUMP_FILENAME.  Return an error code.
 
    N.B. We run very early in initialization, so we can't use lisp,
@@ -5631,6 +5559,15 @@ pdumper_load (const char *dump_filename, char *argv0, 
char const *original_pwd)
   for (int i = 0; i < ARRAYELTS (sections); ++i)
     dump_mmap_reset (&sections[i]);
 
+  Lisp_Object hashes = zero_vector;
+  if (header->hash_list)
+    {
+      struct Lisp_Vector *hash_tables =
+       (struct Lisp_Vector *) (dump_base + header->hash_list);
+      hashes = make_lisp_ptr (hash_tables, Lisp_Vectorlike);
+    }
+
+  pdumper_hashes = &hashes;
   /* Run the functions Emacs registered for doing post-dump-load
      initialization.  */
   for (int i = 0; i < nr_dump_hooks; ++i)
@@ -5707,6 +5644,19 @@ Value is nil if this session was not started using a 
dump file.*/)
 #endif /* HAVE_PDUMPER */
 
 
+static void
+thaw_hash_tables (void)
+{
+  Lisp_Object hash_tables = *pdumper_hashes;
+  for (ptrdiff_t i = 0; i < ASIZE (hash_tables); i++)
+    hash_table_thaw (AREF (hash_tables, i));
+}
+
+void
+init_pdumper_once (void)
+{
+  pdumper_do_now_and_after_load (thaw_hash_tables);
+}
 
 void
 syms_of_pdumper (void)
diff --git a/src/pdumper.h b/src/pdumper.h
index b92958e..c4baeaf 100644
--- a/src/pdumper.h
+++ b/src/pdumper.h
@@ -257,6 +257,7 @@ pdumper_clear_marks (void)
    file was loaded.  */
 extern void pdumper_record_wd (const char *);
 
+void init_pdumper_once (void);
 void syms_of_pdumper (void);
 
 INLINE_HEADER_END
diff --git a/src/timefns.c b/src/timefns.c
index 7bcc37d..94cfddf 100644
--- a/src/timefns.c
+++ b/src/timefns.c
@@ -2048,7 +2048,7 @@ syms_of_timefns (void)
   defsubr (&Scurrent_time_zone);
   defsubr (&Sset_time_zone_rule);
 
-  flt_radix_power = make_vector (flt_radix_power_size, Qnil);
+  flt_radix_power = make_nil_vector (flt_radix_power_size);
   staticpro (&flt_radix_power);
 
 #ifdef NEED_ZTRILLION_INIT
diff --git a/src/xfaces.c b/src/xfaces.c
index 585cfa1..2c6e593 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -2517,6 +2517,7 @@ merge_face_ref (struct window *w,
 {
   bool ok = true;              /* Succeed without an error? */
   Lisp_Object filtered_face_ref;
+  bool attr_filter_passed = false;
 
   filtered_face_ref = face_ref;
   do
@@ -2613,6 +2614,7 @@ merge_face_ref (struct window *w,
                      || UNSPECIFIEDP (scratch_attrs[attr_filter]))
                    return true;
                }
+             attr_filter_passed = true;
            }
          while (CONSP (face_ref) && CONSP (XCDR (face_ref)))
            {
@@ -2776,9 +2778,21 @@ merge_face_ref (struct window *w,
                {
                  /* This is not really very useful; it's just like a
                     normal face reference.  */
-                 if (! merge_face_ref (w, f, value, to,
-                                       err_msgs, named_merge_points,
-                                       attr_filter))
+                 if (attr_filter_passed)
+                   {
+                     /* We already know that this face was tested
+                        against attr_filter and was found applicable,
+                        so don't pass attr_filter to merge_face_ref.
+                        This is for when a face is specified like
+                        (:inherit FACE :extend t), but the parent
+                        FACE itself doesn't specify :extend.  */
+                     if (! merge_face_ref (w, f, value, to,
+                                           err_msgs, named_merge_points, 0))
+                       err = true;
+                   }
+                 else if (! merge_face_ref (w, f, value, to,
+                                            err_msgs, named_merge_points,
+                                            attr_filter))
                    err = true;
                }
              else if (EQ (keyword, QCextend))
diff --git a/src/xwidget.c b/src/xwidget.c
index 0347f1e..c61f5be 100644
--- a/src/xwidget.c
+++ b/src/xwidget.c
@@ -23,13 +23,21 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 
 #include "lisp.h"
 #include "blockinput.h"
+#include "dispextern.h"
 #include "frame.h"
 #include "keyboard.h"
 #include "gtkutil.h"
 #include "sysstdio.h"
+#include "termhooks.h"
+#include "window.h"
 
+/* Include xwidget bottom end headers.  */
+#ifdef USE_GTK
 #include <webkit2/webkit2.h>
 #include <JavaScriptCore/JavaScript.h>
+#elif defined NS_IMPL_COCOA
+#include "nsxwidget.h"
+#endif
 
 static struct xwidget *
 allocate_xwidget (void)
@@ -48,6 +56,7 @@ allocate_xwidget_view (void)
 
 static struct xwidget_view *xwidget_view_lookup (struct xwidget *,
                                                 struct window *);
+#ifdef USE_GTK
 static void webkit_view_load_changed_cb (WebKitWebView *,
                                          WebKitLoadEvent,
                                          gpointer);
@@ -61,6 +70,7 @@ webkit_decide_policy_cb (WebKitWebView *,
                          WebKitPolicyDecision *,
                          WebKitPolicyDecisionType,
                          gpointer);
+#endif
 
 
 DEFUN ("make-xwidget",
@@ -78,8 +88,10 @@ Returns the newly constructed xwidget, or nil if 
construction fails.  */)
    Lisp_Object title, Lisp_Object width, Lisp_Object height,
    Lisp_Object arguments, Lisp_Object buffer)
 {
+#ifdef USE_GTK
   if (!xg_gtk_initialized)
     error ("make-xwidget: GTK has not been initialized");
+#endif
   CHECK_SYMBOL (type);
   CHECK_FIXNAT (width);
   CHECK_FIXNAT (height);
@@ -94,10 +106,11 @@ Returns the newly constructed xwidget, or nil if 
construction fails.  */)
   xw->kill_without_query = false;
   XSETXWIDGET (val, xw);
   Vxwidget_list = Fcons (val, Vxwidget_list);
-  xw->widgetwindow_osr = NULL;
-  xw->widget_osr = NULL;
   xw->plist = Qnil;
 
+#ifdef USE_GTK
+  xw->widgetwindow_osr = NULL;
+  xw->widget_osr = NULL;
   if (EQ (xw->type, Qwebkit))
     {
       block_input ();
@@ -152,6 +165,9 @@ Returns the newly constructed xwidget, or nil if 
construction fails.  */)
 
       unblock_input ();
     }
+#elif defined NS_IMPL_COCOA
+  nsxwidget_init (xw);
+#endif
 
   return val;
 }
@@ -187,6 +203,7 @@ xwidget_hidden (struct xwidget_view *xv)
   return xv->hidden;
 }
 
+#ifdef USE_GTK
 static void
 xwidget_show_view (struct xwidget_view *xv)
 {
@@ -220,13 +237,14 @@ offscreen_damage_event (GtkWidget *widget, GdkEvent 
*event,
   if (GTK_IS_WIDGET (xv_widget))
     gtk_widget_queue_draw (GTK_WIDGET (xv_widget));
   else
-    printf ("Warning, offscreen_damage_event received invalid xv pointer:%p\n",
-            xv_widget);
+    message ("Warning, offscreen_damage_event received invalid xv 
pointer:%p\n",
+             xv_widget);
 
   return FALSE;
 }
+#endif /* USE_GTK */
 
-static void
+void
 store_xwidget_event_string (struct xwidget *xw, const char *eventname,
                             const char *eventstr)
 {
@@ -240,7 +258,27 @@ store_xwidget_event_string (struct xwidget *xw, const char 
*eventname,
   kbd_buffer_store_event (&event);
 }
 
-static void
+void
+store_xwidget_download_callback_event (struct xwidget *xw,
+                                       const char *url,
+                                       const char *mimetype,
+                                       const char *filename)
+{
+  struct input_event event;
+  Lisp_Object xwl;
+  XSETXWIDGET (xwl, xw);
+  EVENT_INIT (event);
+  event.kind = XWIDGET_EVENT;
+  event.frame_or_window = Qnil;
+  event.arg = list5 (intern ("download-callback"),
+                     xwl,
+                     build_string (url),
+                     build_string (mimetype),
+                     build_string (filename));
+  kbd_buffer_store_event (&event);
+}
+
+void
 store_xwidget_js_callback_event (struct xwidget *xw,
                                  Lisp_Object proc,
                                  Lisp_Object argument)
@@ -256,6 +294,7 @@ store_xwidget_js_callback_event (struct xwidget *xw,
 }
 
 
+#ifdef USE_GTK
 void
 webkit_view_load_changed_cb (WebKitWebView *webkitwebview,
                              WebKitLoadEvent load_event,
@@ -486,6 +525,7 @@ xwidget_osr_event_set_embedder (GtkWidget *widget, GdkEvent 
*event,
                                      gtk_widget_get_window (xv->widget));
   return FALSE;
 }
+#endif /* USE_GTK */
 
 
 /* Initializes and does initial placement of an xwidget view on screen.  */
@@ -495,8 +535,10 @@ xwidget_init_view (struct xwidget *xww,
                    int x, int y)
 {
 
+#ifdef USE_GTK
   if (!xg_gtk_initialized)
     error ("xwidget_init_view: GTK has not been initialized");
+#endif
 
   struct xwidget_view *xv = allocate_xwidget_view ();
   Lisp_Object val;
@@ -507,6 +549,7 @@ xwidget_init_view (struct xwidget *xww,
   XSETWINDOW (xv->w, s->w);
   XSETXWIDGET (xv->model, xww);
 
+#ifdef USE_GTK
   if (EQ (xww->type, Qwebkit))
     {
       xv->widget = gtk_drawing_area_new ();
@@ -564,6 +607,10 @@ xwidget_init_view (struct xwidget *xww,
   xv->x = x;
   xv->y = y;
   gtk_widget_show_all (xv->widgetwindow);
+#elif defined NS_IMPL_COCOA
+  nsxwidget_init_view (xv, xww, s, x, y);
+  nsxwidget_resize_view(xv, xww->width, xww->height);
+#endif
 
   return xv;
 }
@@ -576,6 +623,7 @@ x_draw_xwidget_glyph_string (struct glyph_string *s)
      initialization.  */
   struct xwidget *xww = s->xwidget;
   struct xwidget_view *xv = xwidget_view_lookup (xww, s->w);
+  int text_area_x, text_area_y, text_area_width, text_area_height;
   int clip_right;
   int clip_bottom;
   int clip_top;
@@ -587,13 +635,47 @@ x_draw_xwidget_glyph_string (struct glyph_string *s)
   /* Do initialization here in the display loop because there is no
      other time to know things like window placement etc.  Do not
      create a new view if we have found one that is usable.  */
+#ifdef USE_GTK
   if (!xv)
     xv = xwidget_init_view (xww, s, x, y);
-
-  int text_area_x, text_area_y, text_area_width, text_area_height;
+#elif defined NS_IMPL_COCOA
+  if (!xv)
+    {
+      /* Enforce 1 to 1, model and view for macOS Cocoa webkit2.  */
+      if (xww->xv)
+        {
+          if (xwidget_hidden (xww->xv))
+            {
+              Lisp_Object xvl;
+              XSETXWIDGET_VIEW (xvl, xww->xv);
+              Fdelete_xwidget_view (xvl);
+            }
+          else
+            {
+              message ("You can't share an xwidget (webkit2) among windows.");
+              return;
+            }
+        }
+      xv = xwidget_init_view (xww, s, x, y);
+    }
+#endif
 
   window_box (s->w, TEXT_AREA, &text_area_x, &text_area_y,
               &text_area_width, &text_area_height);
+
+  /* Resize xwidget webkit if its container window size is changed in
+     some ways, for example, a buffer became hidden in small split
+     window, then it can appear front in merged whole window.  */
+  if (EQ (xww->type, Qwebkit)
+      && (xww->width != text_area_width || xww->height != text_area_height))
+    {
+      Lisp_Object xwl;
+      XSETXWIDGET (xwl, xww);
+      Fxwidget_resize (xwl,
+                       make_int (text_area_width),
+                       make_int (text_area_height));
+    }
+
   clip_left = max (0, text_area_x - x);
   clip_right = max (clip_left,
                    min (xww->width, text_area_x + text_area_width - x));
@@ -616,8 +698,14 @@ x_draw_xwidget_glyph_string (struct glyph_string *s)
 
   /* Has it moved?  */
   if (moved)
-    gtk_fixed_move (GTK_FIXED (FRAME_GTK_WIDGET (s->f)),
-                   xv->widgetwindow, x + clip_left, y + clip_top);
+    {
+#ifdef USE_GTK
+      gtk_fixed_move (GTK_FIXED (FRAME_GTK_WIDGET (s->f)),
+                      xv->widgetwindow, x + clip_left, y + clip_top);
+#elif defined NS_IMPL_COCOA
+      nsxwidget_move_view (xv, x + clip_left, y + clip_top);
+#endif
+    }
 
   /* Clip the widget window if some parts happen to be outside
      drawable area.  An Emacs window is not a gtk window.  A gtk window
@@ -628,10 +716,16 @@ x_draw_xwidget_glyph_string (struct glyph_string *s)
       || xv->clip_bottom != clip_bottom
       || xv->clip_top != clip_top || xv->clip_left != clip_left)
     {
+#ifdef USE_GTK
       gtk_widget_set_size_request (xv->widgetwindow, clip_right - clip_left,
                                    clip_bottom - clip_top);
       gtk_fixed_move (GTK_FIXED (xv->widgetwindow), xv->widget, -clip_left,
                       -clip_top);
+#elif defined NS_IMPL_COCOA
+      nsxwidget_resize_view (xv, clip_right - clip_left,
+                             clip_bottom - clip_top);
+      nsxwidget_move_widget_in_view (xv, -clip_left, -clip_top);
+#endif
 
       xv->clip_right = clip_right;
       xv->clip_bottom = clip_bottom;
@@ -645,22 +739,66 @@ x_draw_xwidget_glyph_string (struct glyph_string *s)
      xwidgets background.  It's just a visual glitch though.  */
   if (!xwidget_hidden (xv))
     {
+#ifdef USE_GTK
       gtk_widget_queue_draw (xv->widgetwindow);
       gtk_widget_queue_draw (xv->widget);
+#elif defined NS_IMPL_COCOA
+      nsxwidget_set_needsdisplay (xv);
+#endif
     }
 }
 
-/* Macro that checks WEBKIT_IS_WEB_VIEW (xw->widget_osr) first.  */
+static bool
+xwidget_is_web_view (struct xwidget *xw)
+{
+#ifdef USE_GTK
+  return xw->widget_osr != NULL && WEBKIT_IS_WEB_VIEW (xw->widget_osr);
+#elif defined NS_IMPL_COCOA
+  return nsxwidget_is_web_view (xw);
+#endif
+}
+
+/* Macro that checks xwidget hold webkit web view first.  */
 #define WEBKIT_FN_INIT()                                               \
   CHECK_XWIDGET (xwidget);                                             \
   struct xwidget *xw = XXWIDGET (xwidget);                             \
-  if (!xw->widget_osr || !WEBKIT_IS_WEB_VIEW (xw->widget_osr))         \
+  if (!xwidget_is_web_view (xw))                                       \
     {                                                                  \
       fputs ("ERROR xw->widget_osr does not hold a webkit instance\n", \
             stdout);                                                   \
       return Qnil;                                                     \
     }
 
+DEFUN ("xwidget-webkit-uri",
+       Fxwidget_webkit_uri, Sxwidget_webkit_uri,
+       1, 1, 0,
+       doc: /* Get the current URL of XWIDGET webkit.  */)
+  (Lisp_Object xwidget)
+{
+  WEBKIT_FN_INIT ();
+#ifdef USE_GTK
+  WebKitWebView *wkwv = WEBKIT_WEB_VIEW (xw->widget_osr);
+  return build_string (webkit_web_view_get_uri (wkwv));
+#elif defined NS_IMPL_COCOA
+  return nsxwidget_webkit_uri (xw);
+#endif
+}
+
+DEFUN ("xwidget-webkit-title",
+       Fxwidget_webkit_title, Sxwidget_webkit_title,
+       1, 1, 0,
+       doc: /* Get the current title of XWIDGET webkit.  */)
+  (Lisp_Object xwidget)
+{
+  WEBKIT_FN_INIT ();
+#ifdef USE_GTK
+  WebKitWebView *wkwv = WEBKIT_WEB_VIEW (xw->widget_osr);
+  return build_string (webkit_web_view_get_title (wkwv));
+#elif defined NS_IMPL_COCOA
+  return nsxwidget_webkit_title (xw);
+#endif
+}
+
 DEFUN ("xwidget-webkit-goto-uri",
        Fxwidget_webkit_goto_uri, Sxwidget_webkit_goto_uri,
        2, 2, 0,
@@ -670,7 +808,36 @@ DEFUN ("xwidget-webkit-goto-uri",
   WEBKIT_FN_INIT ();
   CHECK_STRING (uri);
   uri = ENCODE_FILE (uri);
+#ifdef USE_GTK
   webkit_web_view_load_uri (WEBKIT_WEB_VIEW (xw->widget_osr), SSDATA (uri));
+#elif defined NS_IMPL_COCOA
+  nsxwidget_webkit_goto_uri (xw, SSDATA (uri));
+#endif
+  return Qnil;
+}
+
+DEFUN ("xwidget-webkit-goto-history",
+       Fxwidget_webkit_goto_history, Sxwidget_webkit_goto_history,
+       2, 2, 0,
+       doc: /* Make the XWIDGET webkit load REL-POS (-1, 0, 1) page in browse 
history.  */)
+  (Lisp_Object xwidget, Lisp_Object rel_pos)
+{
+  WEBKIT_FN_INIT ();
+  /* Should be one of -1, 0, 1 */
+  if (XFIXNUM (rel_pos) < -1 || XFIXNUM (rel_pos) > 1)
+    args_out_of_range_3 (rel_pos, make_fixnum (-1), make_fixnum (1));
+
+#ifdef USE_GTK
+  WebKitWebView *wkwv = WEBKIT_WEB_VIEW (xw->widget_osr);
+  switch (XFIXNAT (rel_pos))
+    {
+    case -1: webkit_web_view_go_back (wkwv); break;
+    case 0: webkit_web_view_reload (wkwv); break;
+    case 1: webkit_web_view_go_forward (wkwv); break;
+    }
+#elif defined NS_IMPL_COCOA
+  nsxwidget_webkit_goto_history (xw, XFIXNAT (rel_pos));
+#endif
   return Qnil;
 }
 
@@ -684,14 +851,19 @@ DEFUN ("xwidget-webkit-zoom",
   if (FLOATP (factor))
     {
       double zoom_change = XFLOAT_DATA (factor);
+#ifdef USE_GTK
       webkit_web_view_set_zoom_level
         (WEBKIT_WEB_VIEW (xw->widget_osr),
          webkit_web_view_get_zoom_level
          (WEBKIT_WEB_VIEW (xw->widget_osr)) + zoom_change);
+#elif defined NS_IMPL_COCOA
+      nsxwidget_webkit_zoom (xw, zoom_change);
+#endif
     }
   return Qnil;
 }
 
+#ifdef USE_GTK
 /* Save script and fun in the script/callback save vector and return
    its index.  */
 static ptrdiff_t
@@ -713,6 +885,7 @@ save_script_callback (struct xwidget *xw, Lisp_Object 
script, Lisp_Object fun)
   ASET (cbs, idx, Fcons (make_mint_ptr (xlispstrdup (script)), fun));
   return idx;
 }
+#endif
 
 DEFUN ("xwidget-webkit-execute-script",
        Fxwidget_webkit_execute_script, Sxwidget_webkit_execute_script,
@@ -729,6 +902,7 @@ argument procedure FUN.*/)
 
   script = ENCODE_SYSTEM (script);
 
+#ifdef USE_GTK
   /* Protect script and fun during GC.  */
   intptr_t idx = save_script_callback (xw, script, fun);
 
@@ -742,6 +916,9 @@ argument procedure FUN.*/)
                                   NULL, /* cancelable */
                                   webkit_javascript_finished_cb,
                                  (gpointer) idx);
+#elif defined NS_IMPL_COCOA
+  nsxwidget_webkit_execute_script (xw, SSDATA (script), fun);
+#endif
   return Qnil;
 }
 
@@ -758,6 +935,7 @@ DEFUN ("xwidget-resize", Fxwidget_resize, Sxwidget_resize, 
3, 3, 0,
   xw->height = h;
 
   /* If there is an offscreen widget resize it first.  */
+#ifdef USE_GTK
   if (xw->widget_osr)
     {
       gtk_window_resize (GTK_WINDOW (xw->widgetwindow_osr), xw->width,
@@ -766,6 +944,9 @@ DEFUN ("xwidget-resize", Fxwidget_resize, Sxwidget_resize, 
3, 3, 0,
       gtk_widget_set_size_request (GTK_WIDGET (xw->widget_osr), xw->width,
                                    xw->height);
     }
+#elif defined NS_IMPL_COCOA
+  nsxwidget_resize (xw);
+#endif
 
   for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail); tail = XCDR (tail))
     {
@@ -773,8 +954,14 @@ DEFUN ("xwidget-resize", Fxwidget_resize, Sxwidget_resize, 
3, 3, 0,
         {
           struct xwidget_view *xv = XXWIDGET_VIEW (XCAR (tail));
           if (XXWIDGET (xv->model) == xw)
+            {
+#ifdef USE_GTK
               gtk_widget_set_size_request (GTK_WIDGET (xv->widget), xw->width,
                                            xw->height);
+#elif defined NS_IMPL_COCOA
+              nsxwidget_resize_view(xv, xw->width, xw->height);
+#endif
+            }
         }
     }
 
@@ -793,9 +980,13 @@ Emacs allocated area accordingly.  */)
   (Lisp_Object xwidget)
 {
   CHECK_XWIDGET (xwidget);
+#ifdef USE_GTK
   GtkRequisition requisition;
   gtk_widget_size_request (XXWIDGET (xwidget)->widget_osr, &requisition);
   return list2i (requisition.width, requisition.height);
+#elif defined NS_IMPL_COCOA
+  return nsxwidget_get_size (XXWIDGET (xwidget));
+#endif
 }
 
 DEFUN ("xwidgetp",
@@ -872,14 +1063,19 @@ DEFUN ("delete-xwidget-view",
 {
   CHECK_XWIDGET_VIEW (xwidget_view);
   struct xwidget_view *xv = XXWIDGET_VIEW (xwidget_view);
+#ifdef USE_GTK
   gtk_widget_destroy (xv->widgetwindow);
-  Vxwidget_view_list = Fdelq (xwidget_view, Vxwidget_view_list);
   /* xv->model still has signals pointing to the view.  There can be
      several views.  Find the matching signals and delete them all.  */
   g_signal_handlers_disconnect_matched  (XXWIDGET 
(xv->model)->widgetwindow_osr,
                                          G_SIGNAL_MATCH_DATA,
                                          0, 0, 0, 0,
                                          xv->widget);
+#elif defined NS_IMPL_COCOA
+  nsxwidget_delete_view (xv);
+#endif
+
+  Vxwidget_view_list = Fdelq (xwidget_view, Vxwidget_view_list);
   return Qnil;
 }
 
@@ -985,7 +1181,10 @@ syms_of_xwidget (void)
   defsubr (&Sxwidget_query_on_exit_flag);
   defsubr (&Sset_xwidget_query_on_exit_flag);
 
+  defsubr (&Sxwidget_webkit_uri);
+  defsubr (&Sxwidget_webkit_title);
   defsubr (&Sxwidget_webkit_goto_uri);
+  defsubr (&Sxwidget_webkit_goto_history);
   defsubr (&Sxwidget_webkit_zoom);
   defsubr (&Sxwidget_webkit_execute_script);
   DEFSYM (Qwebkit, "webkit");
@@ -1156,11 +1355,19 @@ xwidget_end_redisplay (struct window *w, struct 
glyph_matrix *matrix)
                     xwidget_end_redisplay (w->current_matrix);  */
                  struct xwidget_view *xv
                    = xwidget_view_lookup (glyph->u.xwidget, w);
+#ifdef USE_GTK
                  /* FIXME: Is it safe to assume xwidget_view_lookup
                     always succeeds here?  If so, this comment can be removed.
                     If not, the code probably needs fixing.  */
                  eassume (xv);
                  xwidget_touch (xv);
+#elif defined NS_IMPL_COCOA
+                  /* In NS xwidget, xv can be NULL for the second or
+                     later views for a model, the result of 1 to 1
+                     model view relation enforcement.  */
+                  if (xv)
+                    xwidget_touch (xv);
+#endif
                }
          }
     }
@@ -1177,9 +1384,21 @@ xwidget_end_redisplay (struct window *w, struct 
glyph_matrix *matrix)
           if (XWINDOW (xv->w) == w)
             {
               if (xwidget_touched (xv))
-                xwidget_show_view (xv);
+                {
+#ifdef USE_GTK
+                  xwidget_show_view (xv);
+#elif defined NS_IMPL_COCOA
+                  nsxwidget_show_view (xv);
+#endif
+                }
               else
-                xwidget_hide_view (xv);
+                {
+#ifdef USE_GTK
+                  xwidget_hide_view (xv);
+#elif defined NS_IMPL_COCOA
+                  nsxwidget_hide_view (xv);
+#endif
+                }
             }
         }
     }
@@ -1198,6 +1417,7 @@ kill_buffer_xwidgets (Lisp_Object buffer)
       {
         CHECK_XWIDGET (xwidget);
         struct xwidget *xw = XXWIDGET (xwidget);
+#ifdef USE_GTK
         if (xw->widget_osr && xw->widgetwindow_osr)
           {
             gtk_widget_destroy (xw->widget_osr);
@@ -1211,6 +1431,9 @@ kill_buffer_xwidgets (Lisp_Object buffer)
                xfree (xmint_pointer (XCAR (cb)));
              ASET (xw->script_callbacks, idx, Qnil);
            }
+#elif defined NS_IMPL_COCOA
+        nsxwidget_kill (xw);
+#endif
       }
     }
 }
diff --git a/src/xwidget.h b/src/xwidget.h
index 99fa8bb..40ad8ae 100644
--- a/src/xwidget.h
+++ b/src/xwidget.h
@@ -29,7 +29,13 @@ struct xwidget_view;
 struct window;
 
 #ifdef HAVE_XWIDGETS
-# include <gtk/gtk.h>
+
+#if defined (USE_GTK)
+#include <gtk/gtk.h>
+#elif defined (NS_IMPL_COCOA) && defined (__OBJC__)
+#import <AppKit/NSView.h>
+#import "nsxwidget.h"
+#endif
 
 struct xwidget
 {
@@ -54,9 +60,25 @@ struct xwidget
   int height;
   int width;
 
+#if defined (USE_GTK)
   /* For offscreen widgets, unused if not osr.  */
   GtkWidget *widget_osr;
   GtkWidget *widgetwindow_osr;
+#elif defined (NS_IMPL_COCOA)
+# ifdef __OBJC__
+  /* For offscreen widgets, unused if not osr.  */
+  NSView *xwWidget;
+  XwWindow *xwWindow;
+
+  /* Used only for xwidget types (such as webkit2) enforcing 1 to 1
+     relationship between model and view.  */
+  struct xwidget_view *xv;
+# else
+  void *xwWidget;
+  void *xwWindow;
+  struct xwidget_view *xv;
+# endif
+#endif
 
   /* Kill silently if Emacs is exited.  */
   bool_bf kill_without_query : 1;
@@ -75,9 +97,20 @@ struct xwidget_view
   /* The "live" instance isn't drawn.  */
   bool hidden;
 
+#if defined (USE_GTK)
   GtkWidget *widget;
   GtkWidget *widgetwindow;
   GtkWidget *emacswindow;
+#elif defined (NS_IMPL_COCOA)
+# ifdef __OBJC__
+  XvWindow *xvWindow;
+  NSView *emacswindow;
+# else
+  void *xvWindow;
+  void *emacswindow;
+# endif
+#endif
+
   int x;
   int y;
   int clip_right;
@@ -116,6 +149,19 @@ void x_draw_xwidget_glyph_string (struct glyph_string *);
 struct xwidget *lookup_xwidget (Lisp_Object spec);
 void xwidget_end_redisplay (struct window *, struct glyph_matrix *);
 void kill_buffer_xwidgets (Lisp_Object);
+/* Defined in 'xwidget.c'.  */
+void store_xwidget_event_string (struct xwidget *xw,
+                                 const char *eventname,
+                                 const char *eventstr);
+
+void store_xwidget_download_callback_event (struct xwidget *xw,
+                                            const char *url,
+                                            const char *mimetype,
+                                            const char *filename);
+
+void store_xwidget_js_callback_event (struct xwidget *xw,
+                                      Lisp_Object proc,
+                                      Lisp_Object argument);
 #else
 INLINE_HEADER_BEGIN
 INLINE void syms_of_xwidget (void) {}
diff --git a/test/lisp/bookmark-resources/test-list.bmk 
b/test/lisp/bookmark-resources/test-list.bmk
new file mode 100644
index 0000000..696d649
--- /dev/null
+++ b/test/lisp/bookmark-resources/test-list.bmk
@@ -0,0 +1,20 @@
+;;;; Emacs Bookmark Format Version 1 ;;;; -*- coding: utf-8-emacs -*-
+;;; This format is meant to be slightly human-readable;
+;;; nevertheless, you probably don't want to edit it.
+;;; -*- End Of Bookmark File Format Version Stamp -*-
+(("name-0"
+ (filename . "/some/file-0")
+ (front-context-string . "abc")
+ (rear-context-string . "def")
+ (position . 3))
+("name-1"
+ (filename . "/some/file-1")
+ (front-context-string . "abc")
+ (rear-context-string . "def")
+ (position . 3))
+("name-2"
+ (filename . "/some/file-2")
+ (front-context-string . "abc")
+ (rear-context-string . "def")
+ (position . 3))
+)
diff --git a/test/lisp/bookmark-tests.el b/test/lisp/bookmark-tests.el
index b9c6ff9..c5959e4 100644
--- a/test/lisp/bookmark-tests.el
+++ b/test/lisp/bookmark-tests.el
@@ -83,6 +83,70 @@ the lexically-bound variable `buffer'."
           ,@body)
        (kill-buffer buffer))))
 
+(defvar bookmark-tests-bookmark-file-list
+  (expand-file-name "test-list.bmk" bookmark-tests-data-dir)
+  "Bookmark file used for testing a list of bookmarks.")
+
+;; The values below should match `bookmark-tests-bookmark-file-list'
+;; content.  We cache these values to speed up tests.
+(eval-and-compile  ; needed by `with-bookmark-test-list' macro
+  (defvar bookmark-tests-bookmark-list-0 '("name-0"
+                            (filename . "/some/file-0")
+                            (front-context-string . "ghi")
+                            (rear-context-string . "jkl")
+                            (position . 4))
+    "Cached value used in bookmark-tests.el."))
+
+;; The values below should match `bookmark-tests-bookmark-file-list'
+;; content.  We cache these values to speed up tests.
+(eval-and-compile  ; needed by `with-bookmark-test-list' macro
+  (defvar bookmark-tests-bookmark-list-1 '("name-1"
+                            (filename . "/some/file-1")
+                            (front-context-string . "mno")
+                            (rear-context-string . "pqr")
+                            (position . 5))
+    "Cached value used in bookmark-tests.el."))
+
+;; The values below should match `bookmark-tests-bookmark-file-list'
+;; content.  We cache these values to speed up tests.
+(eval-and-compile  ; needed by `with-bookmark-test-list' macro
+  (defvar bookmark-tests-bookmark-list-2 '("name-2"
+                            (filename . "/some/file-2")
+                            (front-context-string . "stu")
+                            (rear-context-string . "vwx")
+                            (position . 6))
+    "Cached value used in bookmark-tests.el."))
+
+(defvar bookmark-tests-cache-timestamp-list
+  (cons bookmark-tests-bookmark-file-list
+        (nth 5 (file-attributes
+                bookmark-tests-bookmark-file-list)))
+  "Cached value used in bookmark-tests.el.")
+
+(defmacro with-bookmark-test-list (&rest body)
+  "Create environment for testing bookmark.el and evaluate BODY.
+Ensure a clean environment for testing, and do not change user
+data when running tests interactively."
+  `(with-temp-buffer
+     (let ((bookmark-alist (quote (,(copy-sequence 
bookmark-tests-bookmark-list-0)
+                                   ,(copy-sequence 
bookmark-tests-bookmark-list-1)
+                                   ,(copy-sequence 
bookmark-tests-bookmark-list-2))))
+           (bookmark-default-file bookmark-tests-bookmark-file-list)
+           (bookmark-bookmarks-timestamp bookmark-tests-cache-timestamp-list)
+           bookmark-save-flag)
+       ,@body)))
+
+(defmacro with-bookmark-test-file-list (&rest body)
+  "Create environment for testing bookmark.el and evaluate BODY.
+Same as `with-bookmark-test-list' but also opens the resource file
+example.txt in a buffer, which can be accessed by callers through
+the lexically-bound variable `buffer'."
+  `(let ((buffer (find-file-noselect bookmark-tests-example-file)))
+     (unwind-protect
+         (with-bookmark-test-list
+          ,@body)
+       (kill-buffer buffer))))
+
 (ert-deftest bookmark-tests-all-names ()
   (with-bookmark-test
    (should (equal (bookmark-all-names) '("name")))))
@@ -95,6 +159,30 @@ the lexically-bound variable `buffer'."
   (with-bookmark-test
    (should (equal (bookmark-get-bookmark-record "name") (cdr 
bookmark-tests-bookmark)))))
 
+(ert-deftest bookmark-tests-all-names-list ()
+  (with-bookmark-test-list
+   (should (equal (bookmark-all-names) '("name-0"
+                                         "name-1"
+                                         "name-2")))))
+
+(ert-deftest bookmark-tests-get-bookmark-list ()
+  (with-bookmark-test-list
+   (should (equal (bookmark-get-bookmark "name-0")
+                  bookmark-tests-bookmark-list-0))
+   (should (equal (bookmark-get-bookmark "name-1")
+                  bookmark-tests-bookmark-list-1))
+   (should (equal (bookmark-get-bookmark "name-2")
+                  bookmark-tests-bookmark-list-2))))
+
+(ert-deftest bookmark-tests-get-bookmark-record-list ()
+  (with-bookmark-test-list
+   (should (equal (bookmark-get-bookmark-record "name-0")
+                  (cdr bookmark-tests-bookmark-list-0)))
+   (should (equal (bookmark-get-bookmark-record "name-1")
+                  (cdr bookmark-tests-bookmark-list-1)))
+   (should (equal (bookmark-get-bookmark-record "name-2")
+                  (cdr bookmark-tests-bookmark-list-2)))))
+
 (ert-deftest bookmark-tests-record-getters-and-setters-new ()
   (with-temp-buffer
     (let* ((buffer-file-name "test")
@@ -130,6 +218,19 @@ the lexically-bound variable `buffer'."
        ;; calling twice gives same record
        (should (equal (bookmark-make-record) record))))))
 
+(ert-deftest bookmark-tests-make-record-list ()
+  (with-bookmark-test-file-list
+   (let* ((record `("example.txt" (filename . ,bookmark-tests-example-file)
+                    (front-context-string . "is text file is ")
+                    (rear-context-string)
+                    (position . 3)
+                    (defaults "example.txt"))))
+     (with-current-buffer buffer
+       (goto-char 3)
+       (should (equal (bookmark-make-record) record))
+       ;; calling twice gives same record
+       (should (equal (bookmark-make-record) record))))))
+
 (ert-deftest bookmark-tests-make-record-function ()
   (with-bookmark-test
    (let ((buffer-file-name "test"))
@@ -267,6 +368,11 @@ the lexically-bound variable `buffer'."
    (bookmark-delete "name")
    (should (equal bookmark-alist nil))))
 
+(ert-deftest bookmark-tests-delete-all ()
+  (with-bookmark-test-list
+   (bookmark-delete-all t)
+   (should (equal bookmark-alist nil))))
+
 (defmacro with-bookmark-test-save-load (&rest body)
   "Create environment for testing bookmark.el and evaluate BODY.
 Same as `with-bookmark-test' but also sets a temporary
@@ -340,6 +446,18 @@ testing `bookmark-bmenu-list'."
             ,@body)
         (kill-buffer bookmark-bmenu-buffer)))))
 
+(defmacro with-bookmark-bmenu-test-list (&rest body)
+  "Create environment for testing `bookmark-bmenu-list' and evaluate BODY.
+Same as `with-bookmark-test-list' but with additions suitable for
+testing `bookmark-bmenu-list'."
+  `(with-bookmark-test-list
+    (let ((bookmark-bmenu-buffer "*Bookmark List - Testing*"))
+      (unwind-protect
+          (save-window-excursion
+            (bookmark-bmenu-list)
+            ,@body)
+        (kill-buffer bookmark-bmenu-buffer)))))
+
 (ert-deftest bookmark-test-bmenu-edit-annotation/show-annotation ()
   (with-bookmark-bmenu-test
    (bookmark-set-annotation "name" "foo")
@@ -402,6 +520,52 @@ testing `bookmark-bmenu-list'."
    (beginning-of-line)
    (should (bookmark-bmenu-any-marks))))
 
+(ert-deftest bookmark-test-bmenu-mark-all ()
+  (with-bookmark-bmenu-test-list
+   (let ((here (point-max)))
+     ;; Expect to not move the point
+     (goto-char here)
+     (bookmark-bmenu-mark-all)
+     (should (equal here (point)))
+     ;; Verify that all bookmarks are marked
+     (goto-char (point-min))
+     (bookmark-bmenu-ensure-position)
+     (should (looking-at "^> "))
+     (should (equal bookmark-tests-bookmark-list-0
+                    (bookmark-get-bookmark (bookmark-bmenu-bookmark))))
+     (forward-line 1)
+     (should (looking-at "^> "))
+     (should (equal bookmark-tests-bookmark-list-1
+                    (bookmark-get-bookmark (bookmark-bmenu-bookmark))))
+     (forward-line 1)
+     (should (looking-at "^> "))
+     (should (equal bookmark-tests-bookmark-list-2
+                    (bookmark-get-bookmark (bookmark-bmenu-bookmark)))))))
+
+(ert-deftest bookmark-test-bmenu-any-marks-list ()
+  (with-bookmark-bmenu-test-list
+   ;; Mark just the second item
+   (goto-char (point-min))
+   (bookmark-bmenu-ensure-position)
+   (forward-line 1)
+   (bookmark-bmenu-mark)
+   ;; Verify that only the second item is marked
+   (goto-char (point-min))
+   (bookmark-bmenu-ensure-position)
+   (should (looking-at "^  "))
+   (should (equal bookmark-tests-bookmark-list-0
+                  (bookmark-get-bookmark (bookmark-bmenu-bookmark))))
+   (forward-line 1)
+   (should (looking-at "^> "))
+   (should (equal bookmark-tests-bookmark-list-1
+                  (bookmark-get-bookmark (bookmark-bmenu-bookmark))))
+   (forward-line 1)
+   (should (looking-at "^  "))
+   (should (equal bookmark-tests-bookmark-list-2
+                  (bookmark-get-bookmark (bookmark-bmenu-bookmark))))
+   ;; There should be at least one mark
+   (should (bookmark-bmenu-any-marks))))
+
 (ert-deftest bookmark-test-bmenu-unmark ()
   (with-bookmark-bmenu-test
    (bookmark-bmenu-mark)
@@ -410,12 +574,63 @@ testing `bookmark-bmenu-list'."
    (beginning-of-line)
    (should (looking-at "^  "))))
 
+(ert-deftest bookmark-test-bmenu-unmark-all ()
+  (with-bookmark-bmenu-test-list
+   (bookmark-bmenu-mark-all)
+   (let ((here (point-max)))
+     ;; Expect to not move the point
+     (goto-char here)
+     (bookmark-bmenu-unmark-all)
+     (should (equal here (point)))
+     ;; Verify that all bookmarks are unmarked
+     (goto-char (point-min))
+     (bookmark-bmenu-ensure-position)
+     (should (looking-at "^  "))
+     (should (equal bookmark-tests-bookmark-list-0
+                    (bookmark-get-bookmark (bookmark-bmenu-bookmark))))
+     (forward-line 1)
+     (should (looking-at "^  "))
+     (should (equal bookmark-tests-bookmark-list-1
+                    (bookmark-get-bookmark (bookmark-bmenu-bookmark))))
+     (forward-line 1)
+     (should (looking-at "^  "))
+     (should (equal bookmark-tests-bookmark-list-2
+                    (bookmark-get-bookmark (bookmark-bmenu-bookmark)))))))
+
 (ert-deftest bookmark-test-bmenu-delete ()
   (with-bookmark-bmenu-test
    (bookmark-bmenu-delete)
    (bookmark-bmenu-execute-deletions)
    (should (equal (length bookmark-alist) 0))))
 
+(ert-deftest bookmark-test-bmenu-delete-all ()
+  (with-bookmark-bmenu-test-list
+   ;; Verify that unmarked bookmarks aren't deleted
+   (bookmark-bmenu-execute-deletions)
+   (should-not (eq bookmark-alist nil))
+   (let ((here (point-max)))
+     ;; Expect to not move the point
+     (goto-char here)
+     (bookmark-bmenu-delete-all)
+     (should (equal here (point)))
+     ;; Verify that all bookmarks are marked for deletion
+     (goto-char (point-min))
+     (bookmark-bmenu-ensure-position)
+     (should (looking-at "^D "))
+     (should (equal bookmark-tests-bookmark-list-0
+                    (bookmark-get-bookmark (bookmark-bmenu-bookmark))))
+     (forward-line 1)
+     (should (looking-at "^D "))
+     (should (equal bookmark-tests-bookmark-list-1
+                    (bookmark-get-bookmark (bookmark-bmenu-bookmark))))
+     (forward-line 1)
+     (should (looking-at "^D "))
+     (should (equal bookmark-tests-bookmark-list-2
+                    (bookmark-get-bookmark (bookmark-bmenu-bookmark))))
+     ;; Verify that all bookmarks are deleted
+     (bookmark-bmenu-execute-deletions)
+     (should (eq bookmark-alist nil)))))
+
 (ert-deftest bookmark-test-bmenu-locate ()
   (let (msg)
     (cl-letf (((symbol-function 'message)
diff --git a/test/lisp/emacs-lisp/lisp-tests.el 
b/test/lisp/emacs-lisp/lisp-tests.el
index 8736ac7..a2b8304 100644
--- a/test/lisp/emacs-lisp/lisp-tests.el
+++ b/test/lisp/emacs-lisp/lisp-tests.el
@@ -367,6 +367,61 @@ start."
 "
     "Test buffer for `mark-defun'."))
 
+;;; end-of-defun
+
+(ert-deftest end-of-defun-twice ()
+  "Test behavior of prefix arg for `end-of-defun' (Bug#24427).
+Calling `end-of-defun' twice should be the same as a prefix arg
+of two."
+  (setq last-command nil)
+  (cl-flet ((eod2 (lambda ()
+                    (goto-char (point-min))
+                    (end-of-defun)
+                    (end-of-defun)
+                    (let ((pt-eod2 (point)))
+                      (goto-char (point-min))
+                      (end-of-defun 2)
+                      (should (= (point) pt-eod2))))))
+    (with-temp-buffer
+      (insert "\
+\(defun a ())
+
+\(defun b ())
+
+\(defun c ())")
+      (eod2))
+    (with-temp-buffer
+      (insert "\
+\(defun a ())
+\(defun b ())
+\(defun c ())")
+      (eod2)))
+  (elisp-tests-with-temp-buffer ";; Comment header
+
+\(defun func-1 (arg)
+  \"docstring\"
+  body)
+=!p1=
+;; Comment before a defun
+\(defun func-2 (arg)
+  \"docstring\"
+  body)
+
+\(defun func-3 (arg)
+  \"docstring\"
+  body)
+=!p2=(defun func-4 (arg)
+  \"docstring\"
+  body)
+
+;; end
+"
+    (goto-char p1)
+    (end-of-defun 2)
+    (should (= (point) p2))))
+
+;;; mark-defun
+
 (ert-deftest mark-defun-no-arg-region-inactive ()
   "Test `mark-defun' with no prefix argument and inactive
 region."
diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el
index 4b902fd..5b2f5fd 100644
--- a/test/lisp/files-tests.el
+++ b/test/lisp/files-tests.el
@@ -190,7 +190,6 @@ form.")
 
 (ert-deftest files-tests-bug-21454 ()
   "Test for https://debbugs.gnu.org/21454 ."
-  :expected-result :failed
   (let ((input-result
          '(("/foo/bar//baz/:/bar/foo/baz//" nil ("/foo/bar/baz/" 
"/bar/foo/baz/"))
            ("/foo/bar/:/bar/qux/:/qux/foo" nil ("/foo/bar/" "/bar/qux/" 
"/qux/foo/"))
@@ -1362,5 +1361,9 @@ See <https://debbugs.gnu.org/36401>."
       (normal-mode)
       (should (not (eq major-mode 'text-mode))))))
 
+(ert-deftest files-colon-path ()
+  (should (equal (parse-colon-path "/foo//bar/baz")
+                 '("/foo/bar/baz/"))))
+
 (provide 'files-tests)
 ;;; files-tests.el ends here
diff --git a/test/lisp/gnus/mml-sec-tests.el b/test/lisp/gnus/mml-sec-tests.el
index 8f78a66..07da4bf 100644
--- a/test/lisp/gnus/mml-sec-tests.el
+++ b/test/lisp/gnus/mml-sec-tests.el
@@ -663,6 +663,7 @@ In this test, just multiple encryption and signing keys may 
be available."
 (ert-deftest mml-secure-en-decrypt-sign-1-3-double ()
   "Sign and encrypt message; then decrypt and test for expected result.
 In this test, just multiple encryption and signing keys may be available."
+  :tags '(:unstable)
   (skip-unless (test-conf))
   (mml-secure-test-key-fixture
    (lambda ()
@@ -680,6 +681,7 @@ In this test, just multiple encryption and signing keys may 
be available."
 (ert-deftest mml-secure-en-decrypt-sign-2 ()
   "Sign and encrypt message; then decrypt and test for expected result.
 In this test, lists of encryption and signing keys are customized."
+  :tags '(:unstable)
   (skip-unless (test-conf))
   (mml-secure-test-key-fixture
    (lambda ()
@@ -714,6 +716,7 @@ In this test, lists of encryption and signing keys are 
customized."
 (ert-deftest mml-secure-en-decrypt-sign-3 ()
   "Sign and encrypt message; then decrypt and test for expected result.
 Use sign-with-sender and encrypt-to-self."
+  :tags '(:unstable)
   (skip-unless (test-conf))
   (mml-secure-test-key-fixture
    (lambda ()
diff --git a/test/lisp/help-fns-tests.el b/test/lisp/help-fns-tests.el
index d2dc3d2..da2b49e 100644
--- a/test/lisp/help-fns-tests.el
+++ b/test/lisp/help-fns-tests.el
@@ -160,4 +160,15 @@ Return first line of the output of (describe-function-1 
FUNC)."
   (with-current-buffer "*Help*"
     (should (looking-at "^help-fns-test--describe-keymap-foo is"))))
 
+;;; Tests for find-lisp-object-file-name
+(ert-deftest help-fns-test-bug24697-function-search ()
+  (should-not (find-lisp-object-file-name 'tab-width 1)))
+
+(ert-deftest help-fns-test-bug24697-non-internal-variable ()
+  (let ((help-fns--test-var (make-symbol "help-fns--test-var")))
+    ;; simulate an internal variable
+    (put help-fns--test-var 'variable-documentation 1)
+    (should-not (find-lisp-object-file-name help-fns--test-var 'defface))
+    (should-not (find-lisp-object-file-name help-fns--test-var 1))))
+
 ;;; help-fns-tests.el ends here
diff --git a/test/src/emacs-module-tests.el b/test/src/emacs-module-tests.el
index 51b2ca0..0fd8e1d 100644
--- a/test/src/emacs-module-tests.el
+++ b/test/src/emacs-module-tests.el
@@ -24,6 +24,7 @@
 ;; module in test/data/emacs-module.
 
 ;;; Code:
+;;; Prelude
 
 (require 'cl-lib)
 (require 'ert)
@@ -48,9 +49,7 @@
 (cl-defmethod emacs-module-tests--generic ((_ user-ptr))
   'user-ptr)
 
-;;
-;; Basic tests.
-;;
+;;; Basic tests
 
 (ert-deftest mod-test-sum-test ()
   (should (= (mod-test-sum 1 2) 3))
@@ -103,9 +102,7 @@ changes."
                  ">" eos)
              (prin1-to-string func)))))
 
-;;
-;; Non-local exists (throw, signal).
-;;
+;;; Non-local exists (throw, signal)
 
 (ert-deftest mod-test-non-local-exit-signal-test ()
   (should-error (mod-test-signal))
@@ -142,9 +139,7 @@ changes."
   (should (equal (mod-test-non-local-exit-funcall (lambda () (throw 'tag 32)))
                  '(throw tag 32))))
 
-;;
-;; String tests.
-;;
+;;; String tests
 
 (defun multiply-string (s n)
   "Return N copies of S concatenated together."
@@ -168,9 +163,7 @@ changes."
 (ert-deftest mod-test-string-a-to-b-test ()
   (should (string= (mod-test-string-a-to-b "aaa") "bbb")))
 
-;;
-;; User-pointer tests.
-;;
+;;; User-pointer tests
 
 (ert-deftest mod-test-userptr-fun-test ()
   (let* ((n 42)
@@ -184,9 +177,7 @@ changes."
 
 ;; TODO: try to test finalizer
 
-;;
-;; Vector tests.
-;;
+;;; Vector tests
 
 (ert-deftest mod-test-vector-test ()
   (dolist (s '(2 10 100 1000))



reply via email to

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