]> git.eshelyaron.com Git - emacs.git/commitdiff
Merge from origin/emacs-29
authorEli Zaretskii <eliz@gnu.org>
Sat, 12 Aug 2023 17:42:14 +0000 (13:42 -0400)
committerEli Zaretskii <eliz@gnu.org>
Sat, 12 Aug 2023 17:42:14 +0000 (13:42 -0400)
4767f5eaeed Better fix for bug#65156
dd1d8414b33 Fix insert-file-contents with pipes and /dev/stdin
50649a6d1a2 ; * etc/PROBLEMS: Fix wording.
f0dda682ffb ; * etc/NEWS.28: Add deletion of levents.el.
f4acae842c0 Fix bug#65042
e1874c4e8bf * configure.ac (HAVE_TREE_SITTER): Set NEED_DYNLIB=yes (b...
ef8838c3a5f * etc/NEWS: Mention tramp-show-ad-hoc-proxies.
495bee253fc * test/lisp/net/tramp-tests.el (tramp-test42-utf8): Skip ...
de1effd73b4 ; Fix last change
7c7966862bc * test/lisp/net/tramp-tests.el (tramp-test10-write-region...
16205e8db65 ; Improve help-echo in package.el
a95e7006989 ; Filter packages available for upgrade via menu bar
adff72dd1d2 Fix reverting Rmail buffers

12 files changed:
1  2 
configure.ac
etc/NEWS.29
etc/PROBLEMS
exec/exec.c
exec/mipsel-user.h
java/org/gnu/emacs/EmacsWindow.java
lisp/emacs-lisp/package.el
lisp/files.el
src/pgtkterm.c
src/sfntfont.c
src/xdisp.c
test/lisp/net/tramp-tests.el

diff --cc configure.ac
Simple merge
diff --cc etc/NEWS.29
index 9e6f0c16bcd6533f320c742e7c5f7dadc2a9358c,0000000000000000000000000000000000000000..e74cbee4a532abdda2e0391f426a3870b56a1e71
mode 100644,000000..100644
--- /dev/null
@@@ -1,5033 -1,0 +1,4359 @@@
- ---
 +GNU Emacs NEWS -- history of user-visible changes.
 +
 +Copyright (C) 2021-2023 Free Software Foundation, Inc.
 +See the end of the file for license conditions.
 +
 +Please send Emacs bug reports to 'bug-gnu-emacs@gnu.org'.
 +If possible, use 'M-x report-emacs-bug'.
 +
 +This file is about changes in Emacs version 29.
 +
 +See file HISTORY for a list of GNU Emacs versions and release dates.
 +See files NEWS.28, NEWS.27, ..., NEWS.18, and NEWS.1-17 for changes
 +in older Emacs versions.
 +
 +You can narrow news to a specific version by calling 'view-emacs-news'
 +with a prefix argument or by typing 'C-u C-h C-n'.
 +
 +Temporary note:
 ++++ indicates that all relevant manuals in doc/ have been updated.
 +--- means no change in the manuals is needed.
 +When you add a new item, use the appropriate mark if you are sure it
 +applies, and please also update docstrings as needed.
 +
++\f
++* Installation Changes in Emacs 29.2
++
++\f
++* Startup Changes in Emacs 29.2
++
++\f
++* Changes in Emacs 29.2
++
++\f
++* Editing Changes in Emacs 29.2
++
++\f
++* Changes in Specialized Modes and Packages in Emacs 29.2
++
++** Tramp
++
+++++
++*** New user option 'tramp-show-ad-hoc-proxies'.
++When non-nil, ad-hoc definitions are kept in remote file names instead
++of showing the shortcuts.
++
++\f
++* New Modes and Packages in Emacs 29.2
++
++\f
++* Incompatible Lisp Changes in Emacs 29.2
++
++\f
++* Lisp Changes in Emacs 29.2
++
++\f
++* Changes in Emacs 29.2 on Non-Free Operating Systems
++
 +\f
 +* Installation Changes in Emacs 29.1
 +
- +++
 +** Ahead-of-time native compilation can now be requested via configure.
 +Use '--with-native-compilation=aot' to request that all the Lisp files
 +in the Emacs tree should be natively compiled ahead of time.  (This is
 +slow on most machines.)
 +
 +This feature existed in Emacs 28.1, but was less easy to request.
 +
- +++
 +** Emacs can be built with the tree-sitter parsing library.
 +This library, together with separate grammar libraries for each
 +language, provides incremental parsing capabilities for several
 +popular programming languages and other formatted files.  Emacs built
 +with this library offers major modes, described elsewhere in this
 +file, that are based on the tree-sitter's parsers.  If you have the
 +tree-sitter library installed, the configure script will automatically
 +include it in the build; use '--without-tree-sitter' at configure time
 +to disable that.
 +
 +Emacs modes based on the tree-sitter library require an additional
 +grammar library for each mode.  These grammar libraries provide the
 +tree-sitter library with language-specific lexical analysis and
 +parsing capabilities, and are developed separately from the
 +tree-sitter library itself.  If you don't have a grammar library
 +required by some Emacs major mode, and your distro doesn't provide it
 +as an installable package, you can compile and install such a library
 +yourself.  Many libraries can be downloaded from the tree-sitter site:
 +
 +    https://github.com/tree-sitter
 +
 +Emacs provides a user command, 'treesit-install-language-grammar',
 +that automates the download and build process of a grammar library.
 +It prompts for the language, the URL of the language grammar's VCS
 +repository, and then uses the installed C/C++ compiler to build the
 +library and install it.
 +
 +You can also do this manually.  To compile such a library after
 +cloning its Git repository, compile the files "scanner.c" and
 +"parser.c" (sometimes named "scanner.cc" and "parser.cc") in the "src"
 +subdirectory of the library's source tree using the C or C++ compiler,
 +then link these two files into a shared library named
 +"libtree-sitter-LANG.so" ("libtree-sitter-LANG.dll" on MS-Windows,
 +"libtree-sitter-LANG.dylib" on macOS), where LANG is the name of the
 +language supported by the grammar as it is expected by the Emacs major
 +mode (for example, "c" for 'c-ts-mode', "cpp" for 'c++-ts-mode',
 +"python" for 'python-ts-mode', etc.).  Then place the shared library
 +you've built in the same directory where you keep the other shared
 +libraries used by Emacs, or in the "tree-sitter" subdirectory of your
 +'user-emacs-directory', or in a directory mentioned in the variable
 +'treesit-extra-load-path'.
 +
 +You only need to install language grammar libraries required by the
 +Emacs modes you will use, as Emacs loads these libraries only when the
 +corresponding mode is turned on in some buffer for the first time in
 +an Emacs session.
 +
 +We generally recommend to use the latest versions of grammar libraries
 +available from their sites, as these libraries are in constant
 +development and occasionally add features and fix important bugs to
 +follow the advances in the programming languages they support.
 +
- +++
 +** Emacs can be built with built-in support for accessing SQLite databases.
 +This uses the popular sqlite3 library, and can be disabled by using
 +the '--without-sqlite3' option to the 'configure' script.
 +
- ---
 +** Support for the WebP image format.
 +This support is built by default when the libwebp library is
 +available, and includes support for animated WebP images.  To disable
 +WebP support, use the '--without-webp' configure flag.  Image
 +specifiers can now use ':type webp'.
 +
- ---
 +** Emacs now installs the ".pdmp" file using a unique fingerprint in the name.
 +The file is typically installed using a file name akin to
 +"...dir/libexec/emacs/29.1/x86_64-pc-linux-gnu/emacs-<fingerprint>.pdmp".
 +If a constant file name is required, the file can be renamed to
 +"emacs.pdmp", and Emacs will find it during startup anyway.
 +
- ---
 +** Emacs on X now uses XInput 2 for input events.
 +If your X server has support and you have the XInput 2 development
 +headers installed, Emacs will use the X Input Extension for handling
 +input.  If this causes problems, you can configure Emacs with the
 +option '--without-xinput2' to disable this support.
 +
 +'(featurep 'xinput2)' can be used to test for the presence of XInput 2
 +support from Lisp programs.
 +
- +++
 +** Emacs can now be optionally built with the Cairo XCB backend.
 +Configure Emacs with the '--with-cairo-xcb' option to use the Cairo
 +XCB backend; the default is not to use it.  This backend makes Emacs
 +moderately faster when running over X connections with high latency,
 +but is currently known to crash when Emacs repeatedly closes and opens
 +a display connection to the same terminal; this could happen, for
 +example, if you repeatedly visit files via emacsclient in a single
 +client frame, each time deleting the frame with 'C-x C-c'.
 +
- +++
 +** Emacs now supports being built with pure GTK.
 +To use this option, make sure the GTK 3 (version 3.22.23 or later) and
 +Cairo development files are installed, and configure Emacs with the
 +option '--with-pgtk'.  Unlike the default X and GTK build, the
 +resulting Emacs binary will work on any underlying window system
 +supported by GDK, such as Wayland and Broadway.  We recommend that you
 +use this configuration only if you are running a window system other
 +than X that's supported by GDK.  Running this configuration on X is
 +known to have problems, such as undesirable frame positioning and
 +various issues with keyboard input of sequences such as 'C-;' and
 +'C-S-u'.  Running this on WSL is also known to have problems.
 +
 +Note that, unlike the X build of Emacs, the PGTK build cannot
 +automatically switch to text-mode interface (thus emulating '-nw') if
 +it cannot determine the default display; it will instead complain and
 +ask you to invoke it with the explicit '-nw' option.
 +
- ---
 +** Emacs has been ported to the Haiku operating system.
 +The configuration process should automatically detect and build for
 +Haiku.  There is also an optional window-system port to Haiku, which
 +can be enabled by configuring Emacs with the option '--with-be-app',
 +which will require the Haiku Application Kit development headers and a
 +C++ compiler to be present on your system.  If Emacs is not built with
 +the option '--with-be-app', the resulting Emacs will only run in
 +text-mode terminals.
 +
 +To enable Cairo support, ensure that the Cairo and FreeType
 +development files are present on your system, and configure Emacs with
 +'--with-be-cairo'.
 +
 +Unlike X, there is no compile-time option to enable or disable
 +double-buffering; it is always enabled.  To disable it, change the
 +frame parameter 'inhibit-double-buffering' instead.
 +
- ---
 +** Emacs no longer reduces the size of the Japanese dictionary.
 +Building Emacs includes generation of a Japanese dictionary, which is
 +used by Japanese input methods.  Previously, the build included a step
 +of reducing the size of this dictionary's vocabulary.  This vocabulary
 +reduction is now optional, by default off.  If you need the Emacs
 +build to include the vocabulary reduction, configure Emacs with the
 +option '--with-small-ja-dic'.  In an Emacs source tree already
 +configured without that option, you can force the vocabulary reduction
 +by saying
 +
 +    make -C leim generate-ja-dic JA_DIC_NO_REDUCTION_OPTION=''
 +
 +after deleting "lisp/leim/ja-dic/ja-dic.el".
 +
- +++
 +** The docstrings of preloaded files are not in "etc/DOC" any more.
 +Instead, they're fetched as needed from the corresponding ".elc"
 +files, as was already the case for all the non-preloaded files.
 +
 +\f
 +* Startup Changes in Emacs 29.1
 +
- +++
 +** '--batch' and '--script' now adjust the garbage collection levels.
 +These switches now set 'gc-cons-percentage' to 1.0 (up from the
 +default of 0.1).  This means that batch processes will typically use
 +more memory than before, but use less time doing garbage collection.
 +Batch jobs that are supposed to run for a long time should adjust the
 +limit back down again.
 +
- +++
 +** Emacs can now be used more easily in an executable script.
 +If you start an executable script with
 +
 +    #!/usr/bin/emacs -x
 +
 +Emacs will start without reading any init files (like with '--quick'),
 +and then execute the rest of the script file as Emacs Lisp.  When it
 +reaches the end of the script, Emacs will exit with an exit code from
 +the value of the final form.
 +
- +++
 +** Emacs now supports setting 'user-emacs-directory' via '--init-directory'.
 +Use the '--init-directory' command-line option to set
 +'user-emacs-directory'.
 +
- +++
 +** Emacs now has a '--fingerprint' option.
 +This will output a string identifying the current Emacs build, and exit.
 +
- +++
 +** New hook 'after-pdump-load-hook'.
 +This is run at the end of the Emacs startup process, and is meant to
 +be used to reinitialize data structures that would normally be done at
 +load time.
 +
 +** Native Compilation
 +
- +++
 +*** New command 'native-compile-prune-cache'.
 +This command deletes old subdirectories of the eln cache (but not the
 +ones for the current Emacs version).  Note that subdirectories of the
 +system directory where the "*.eln" files are installed (usually, the
 +last entry in 'native-comp-eln-load-path') are not deleted.
 +
- +++
 +*** New function 'startup-redirect-eln-cache'.
 +This function can be called in your init files to change the
 +user-specific directory where Emacs stores the "*.eln" files produced
 +by native compilation of Lisp packages Emacs loads.  The default
 +eln cache directory is unchanged: it is the "eln-cache" subdirectory
 +of 'user-emacs-directory'.
 +
 +\f
 +* Incompatible changes in Emacs 29.1
 +
- +++
 +** The image commands have changed key bindings.
 +In previous Emacs versions, the '+', '-' and 'r' keys were bound when
 +point was over an image.  In Emacs 29.1, additional commands have been
 +added, and this made it more likely that users would trigger the image
 +commands by mistake.  To avoid this, all image commands have been
 +moved to the 'i' prefix keymap, so '+' is now 'i +', '-' is now 'i -',
 +and 'r' is now 'i r'.  In addition, these commands are now repeating,
 +so you can rotate an image twice by saying 'i r r', for instance.
 +
- +++
 +** Emacs now picks the correct coding-system for X input methods.
 +Previously, Emacs would use 'locale-coding-system' for input
 +methods, which could in some circumstances be incorrect, especially
 +when the input method chose to fall back to some other coding system.
 +
 +Emacs now automatically detects the coding-system used by input
 +methods, and uses that to decode input in preference to the value of
 +'locale-coding-system'.  This unfortunately means that users who have
 +changed the coding system used to decode X keyboard input must adjust
 +their customizations to 'locale-coding-system' to the variable
 +'x-input-coding-system' instead.
 +
- ---
 +** Bookmarks no longer include context for encrypted files.
 +If you're visiting an encrypted file, setting a bookmark no longer
 +includes excerpts from that buffer in the bookmarks file.  This is
 +implemented by the new hook 'bookmark-inhibit-context-functions',
 +where packages can register a function which returns non-nil for file
 +names to be excluded from adding such excerpts.
 +
- +++
 +** 'show-paren-mode' is now disabled in 'special-mode' buffers.
 +In Emacs versions previous to Emacs 28.1, 'show-paren-mode' defaulted
 +off.  In Emacs 28.1, the mode was switched on in all buffers.  In
 +Emacs 29.1, this was changed to be switched on in all editing-related
 +buffers, but not in buffers that inherit from 'special-mode'.  To go
 +back to how things worked in Emacs 28.1, put the following in your
 +init file:
 +
 +    (setopt show-paren-predicate t)
 +
- ---
 +** Explicitly-set read-only state is preserved when reverting a buffer.
 +If you use the 'C-x C-q' command to change the read-only state of the
 +buffer and then revert it, Emacs would previously use the file
 +permission bits to determine whether the buffer should be read-only
 +after reverting the buffer.  Emacs now remembers the decision made in
 +'C-x C-q'.
 +
- ---
 +** The Gtk selection face is no longer used for the region.
 +The combination of a Gtk-controlled background and a foreground color
 +controlled by the internal Emacs machinery led to low-contrast faces
 +in common default setups.  Emacs now uses the same 'region' face on
 +Gtk and non-Gtk setups.
 +
- ---
 +** 'C-h f' and 'C-h x' may now require confirmation when you press 'RET'.
 +If the text in the minibuffer cannot be completed to a single function
 +or command, typing 'RET' will not automatically complete to the shortest
 +candidate, but will instead ask for confirmation.  Typing 'TAB' will
 +complete as much as possible, and another 'TAB' will show all the
 +possible completions.  This allows you to insist on the functions name
 +even if Help doesn't appear to know about it, by confirming with a
 +second 'RET'.
 +
 +** Dired
 +
- ---
 +*** 'w' ('dired-copy-filename-as-kill') has changed behavior.
 +If there are several files marked, file names containing space and
 +quote characters will be quoted "like this".
 +
- +++
 +*** The 'd' command now more consistently skips dot files.
 +In previous Emacs versions, commands like 'C-u 10 d' would put the "D"
 +mark on the next ten files, no matter whether they were dot files
 +(i.e., "." and "..") or not, while marking the next ten lines with the
 +mouse (in 'transient-mark-mode') and then hitting 'd' would skip dot
 +files.  These now work equivalently.
 +
- ---
 +** Warning about "eager macro-expansion failure" is now an error.
 +
- +++
 +** Previously, the X "reverseVideo" value at startup was heeded for all frames.
 +This meant that if you had a "reverseVideo" resource on the initial
 +display, and then opened up a new frame on a display without any
 +explicit "reverseVideo" setting, it would get heeded there, too.  (This
 +included terminal frames.)  In Emacs 29, the "reverseVideo" X resource
 +is handled like all the other X resources, and set on a per-frame basis.
 +
- ---
 +** 'E' in 'query-replace' now edits the replacement with exact case.
 +Previously, this command did the same as 'e'.
 +
- +++
 +** '/ a' in "*Packages*" buffer now limits by archive name(s) instead of regexp.
 +
- ---
 +** Setting the goal columns now also affects '<prior>' and '<next>'.
 +Previously, 'C-x C-n' only affected 'next-line' and 'previous-line',
 +but it now also affects 'scroll-up-command' and 'scroll-down-command'.
 +
- ---
 +** Isearch in "*Help*" and "*info*" now char-folds quote characters by default.
 +This means that you can say 'C-s `foo' (GRAVE ACCENT) if the buffer
 +contains "‘foo" (LEFT SINGLE QUOTATION MARK) and the like.  These
 +quotation characters look somewhat similar in some fonts.  To switch
 +this off, disable the new 'isearch-fold-quotes-mode' minor mode.
 +
- ---
 +** Sorting commands no longer necessarily change modification status.
 +In earlier Emacs versions, commands like 'sort-lines' would always
 +change buffer modification status to "modified", whether they changed
 +something in the buffer or not.  This has been changed: the buffer is
 +marked as modified only if the sorting ended up actually changing the
 +contents of the buffer.
 +
- ---
 +** 'string-lines' handles trailing newlines differently.
 +It no longer returns an empty final string if the string ends with a
 +newline.
 +
- ---
 +** 'TAB' and '<backtab>' are now bound in 'button-map'.
 +This means that if point is on a button, 'TAB' will take you to the
 +next button, even if the mode has bound it to something else.  This
 +also means that 'TAB' on a button in an 'outline-minor-mode' heading
 +will move point instead of collapsing the outline.
 +
- ---
 +** 'outline-minor-mode-cycle-map' is now parent of 'outline-minor-mode'.
 +Instead of adding text property 'keymap' with 'outline-minor-mode-cycle'
 +on outline headings in 'outline-minor-mode', the keymap
 +'outline-minor-mode-cycle' is now active in the whole buffer.
 +But keybindings in 'outline-minor-mode-cycle' still take effect
 +only on outline headings because they are bound with the help of
 +'outline-minor-mode-cycle--bind' that checks if point is on a heading.
 +
- ---
 +** 'Info-default-directory-list' is no longer populated at Emacs startup.
 +If you have code in your init file that removes directories from
 +'Info-default-directory-list', this will no longer work.
 +
- ---
 +** 'C-k' no longer deletes files in 'ido-mode'.
 +To get the previous action back, put something like the following in
 +your Init file:
 +
 +    (require 'ido)
 +    (keymap-set ido-file-completion-map "C-k" #'ido-delete-file-at-head)
 +
- ---
 +** New user option 'term-clear-full-screen-programs'.
 +By default, term.el will now work like most terminals when displaying
 +full-screen programs: When they exit, the output is cleared, leaving
 +what was displayed in the window before the programs started.  Set
 +this user option to nil to revert back to the old behavior.
 +
- ---
 +** Support for old EIEIO functions is not autoloaded any more.
 +You need an explicit '(require 'eieio-compat)' to use 'defmethod'
 +and 'defgeneric' (which were made obsolete in Emacs 25.1 by
 +'cl-defmethod' and 'cl-defgeneric').
 +Similarly you might need to '(require 'eieio-compat)' before loading
 +files that were compiled with an old EIEIO (Emacs<25).
 +
- ---
 +** 'C-x 8 .' has been moved to 'C-x 8 . .'.
 +This is to open up the 'C-x 8 .' map to bind further characters there.
 +
- ---
 +** 'C-x 8 =' has been moved to 'C-x 8 = ='.
 +You can now use 'C-x 8 =' to insert several characters with macron;
 +for example, 'C-x 8 = a' will insert U+0101 LATIN SMALL LETTER A WITH
 +MACRON.  To insert a lone macron, type 'C-x 8 = =' instead of the
 +previous 'C-x ='.
 +
 +** Eshell
 +
 +*** Eshell's PATH is now derived from 'exec-path'.
 +For consistency with remote connections, Eshell now uses 'exec-path'
 +to determine the execution path on the local or remote system, instead
 +of using the PATH environment variable directly.
 +
- +++
 +*** 'source' and '.' no longer accept the '--help' option.
 +This is for compatibility with the shell versions of these commands,
 +which don't handle options like '--help' in any special way.
 +
- +++
 +*** String delimiters in argument predicates/modifiers are more restricted.
 +Previously, some argument predicates/modifiers allowed arbitrary
 +characters as string delimiters.  To provide more unified behavior
 +across all predicates/modifiers, the list of allowed delimiters has
 +been restricted to "...", '...', /.../, |...|, (...), [...], <...>,
 +and {...}.  See the "(eshell) Argument Predication and Modification"
 +node in the Eshell manual for more details.
 +
- ---
 +*** Eshell pipelines now only pipe stdout by default.
 +To pipe both stdout and stderr, use the '|&' operator instead of '|'.
 +
- +++
 +** The 'delete-forward-char' command now deletes by grapheme clusters.
 +This command is by default bound to the '<Delete>' function key
 +(a.k.a. '<deletechar>').  When invoked without a prefix argument or
 +with a positive prefix numeric argument, the command will now delete
 +complete grapheme clusters produced by character composition.  For
 +example, if point is before an Emoji sequence, pressing '<Delete>'
 +will delete the entire sequence, not just a single character at its
 +beginning.
 +
- ---
 +** 'load-history' does not treat autoloads specially any more.
 +An autoload definition appears just as a '(defun . NAME)' and the
 +'(t . NAME)' entries are not generated any more.
 +
- +++
 +** The Tamil input methods no longer insert Tamil digits.
 +The input methods 'tamil-itrans' and 'tamil-inscript' no longer insert
 +the Tamil digits, as those digit characters are not used nowadays by
 +speakers of the Tamil language.  To get back the previous behavior,
 +use the new 'tamil-itrans-digits' and 'tamil-inscript-digits' input
 +methods instead.
 +
- +++
 +** New variable 'current-time-list' governing default timestamp form.
 +Functions like 'current-time' now yield '(TICKS . HZ)' timestamps if
 +this new variable is nil.  The variable defaults to t, which means
 +these functions default to timestamps of the forms '(HI LO US PS)',
 +'(HI LO US)' or '(HI LO)', which are less regular and less efficient.
 +This is part of a long-planned change first documented in Emacs 27.
 +Developers are encouraged to test timestamp-related code with this
 +variable set to nil, as it will default to nil in a future Emacs
 +version and will be removed some time after that.
 +
- ---
 +** Functions that recreate the "*scratch*" buffer now also initialize it.
 +When functions like 'other-buffer' and 'server-execute' recreate
 +"*scratch*", they now also insert 'initial-scratch-message' and set
 +the major mode according to 'initial-major-mode', like at Emacs
 +startup.  Previously, these functions ignored
 +'initial-scratch-message' and left "*scratch*" in 'fundamental-mode'.
 +
- ---
 +** Naming of Image-Dired thumbnail files has changed.
 +Names of thumbnail files generated when 'image-dired-thumbnail-storage'
 +is 'image-dired' now always end in ".jpg".  This fixes various issues
 +on different platforms, but means that thumbnails generated in Emacs 28
 +will not be used in Emacs 29, and vice-versa.  If disk space is an
 +issue, consider deleting the 'image-dired-dir' directory (usually
 +"~/.emacs.d/image-dired/") after upgrading to Emacs 29.
 +
- ---
 +** The 'rlogin' method in the URL library is now obsolete.
 +Emacs will now display a warning if you request a URL like
 +"rlogin://foo@example.org".
 +
- ---
 +** Setting 'url-gateway-method' to 'rlogin' is now obsolete.
 +Emacs will now display a warning when setting it to that value.
 +The user options 'url-gateway-rlogin-host',
 +'url-gateway-rlogin-parameters', and 'url-gateway-rlogin-user-name'
 +are also obsolete.
 +
- ---
 +** The user function 'url-irc-function' now takes a SCHEME argument.
 +The user option 'url-irc-function' is now called with a sixth argument
 +corresponding to the scheme portion of the target URL.  For example,
 +this would be "ircs" for a URL like "ircs://irc.libera.chat".
 +
- ---
 +** The linum.el library is now obsolete.
 +We recommend using either the built-in 'display-line-numbers-mode', or
 +the 'nlinum' package from GNU ELPA instead.  The former has better
 +performance, but the latter is closer to a drop-in replacement.
 +
 +1. To use 'display-line-numbers-mode', add something like this to your
 +   init file:
 +
 +    (global-display-line-numbers-mode 1)
 +    ;; Alternatively, to use it only in programming modes:
 +    (add-hook 'prog-mode-hook #'display-line-numbers-mode)
 +
 +2. To use 'nlinum', add this to your Init file:
 +
 +    (package-install 'nlinum)
 +    (global-nlinum-mode 1)
 +    ;; Alternatively, to use it only in programming modes:
 +    (add-hook 'prog-mode-hook #'nlinum-mode)
 +
 +3. To continue using the obsolete package 'linum', add this line to
 +   your Init file, in addition to any existing customizations:
 +
 +    (require 'linum)
 +
- ---
 +** The thumbs.el library is now obsolete.
 +We recommend using the 'image-dired' command instead.
 +
- ---
 +** The autoarg.el library is now marked obsolete.
 +This library provides the 'autoarg-mode' and 'autoarg-kp-mode' minor
 +modes to emulate the behavior of the historical editor Twenex Emacs.
 +We believe it is no longer useful.
 +
- ---
 +** The quickurl.el library is now obsolete.
 +Use 'abbrev', 'skeleton' or 'tempo' instead.
 +
- ---
 +** The rlogin.el library, and the 'rsh' command are now obsolete.
 +Use something like 'M-x shell RET ssh <host> RET' instead.
 +
- ---
 +** The url-about.el library is now obsolete.
 +
- ---
 +** The autoload.el library is now obsolete.
 +It is superseded by the new loaddefs-gen.el library.
 +
- ---
 +** The netrc.el library is now obsolete.
 +Use the 'auth-source-netrc-parse-all' function in auth-source.el
 +instead.
 +
- ---
 +** The url-dired.el library is now obsolete.
 +
- +++
 +** The fast-lock.el and lazy-lock.el libraries have been removed.
 +They have been obsolete since Emacs 22.1.
 +
 +The variable 'font-lock-support-mode' is occasionally useful for
 +debugging purposes.  It is now a regular variable (instead of a user
 +option) and can be set to nil to disable Just-in-time Lock mode.
 +
- +++
 +** The 'utf-8-auto' coding-system now produces BOM on encoding.
 +This is actually a bugfix, since this is how 'utf-8-auto' was
 +documented from day one; it just didn't behave according to
 +documentation.  It turns out some Lisp programs were using this
 +coding-system on the wrong assumption that the "auto" part means some
 +automagic handling of the end-of-line (EOL) format conversion; those
 +programs will now start to fail, because BOM signature in UTF-8 encoded
 +text is rarely expected.  That is the reason we mention this bugfix
 +here.
 +
 +In general, this coding-system should probably never be used for
 +encoding, only for decoding.
 +
 +\f
 +* Changes in Emacs 29.1
 +
- ---
 +** New user option 'major-mode-remap-alist' to specify favorite major modes.
 +This user option lets you remap the default modes (e.g. 'perl-mode' or
 +'latex-mode') to your favorite ones (e.g. 'cperl-mode' or
 +'LaTeX-mode') instead of having to use 'defalias', which can have
 +undesirable side effects.
 +This applies to all modes specified via 'auto-mode-alist', file-local
 +variables, etc.
 +
- ---
 +** Emacs now supports Unicode Standard version 15.0.
 +
- ---
 +** New user option 'electric-quote-replace-consecutive'.
 +This allows you to disable the default behavior of consecutive single
 +quotes being replaced with a double quote.
 +
- +++
 +** Emacs is now capable of editing files with very long lines.
 +The display of long lines has been optimized, and Emacs should no
 +longer choke when a buffer on display contains long lines.  The
 +variable 'long-line-threshold' controls whether and when these display
 +optimizations are in effect.
 +
 +A companion variable 'large-hscroll-threshold' controls when another
 +set of display optimizations are in effect, which are aimed
 +specifically at speeding up display of long lines that are truncated
 +on display.
 +
 +If you still experience slowdowns while editing files with long lines,
 +this may be due to line truncation, or to one of the enabled minor
 +modes, or to the current major mode.  Try turning off line truncation
 +with 'C-x x t', or try disabling all known slow minor modes with
 +'M-x so-long-minor-mode', or try disabling both known slow minor modes
 +and the major mode with 'M-x so-long-mode', or visit the file with
 +'M-x find-file-literally' instead of the usual 'C-x C-f'.
 +
 +In buffers in which these display optimizations are in effect, the
 +'fontification-functions', 'pre-command-hook' and 'post-command-hook'
 +hooks are executed on a narrowed portion of the buffer, whose size is
 +controlled by the variables 'long-line-optimizations-region-size' and
 +'long-line-optimizations-bol-search-limit', as if they were in a
 +'with-restriction' form.  This may, in particular, cause occasional
 +mis-fontifications in these buffers.  Modes which are affected by
 +these optimizations and by the fact that the buffer is narrowed,
 +should adapt and either modify their algorithm so as not to expect the
 +entire buffer to be accessible, or, if accessing outside of the
 +narrowed region doesn't hurt performance, use the
 +'without-restriction' form to temporarily lift the restriction and
 +access portions of the buffer outside of the narrowed region.
 +
 +The new function 'long-line-optimizations-p' returns non-nil when
 +these optimizations are in effect in the current buffer.
 +
- ---
 +** New command to change the font size globally.
 +To increase the font size, type 'C-x C-M-+' or 'C-x C-M-='; to
 +decrease it, type 'C-x C-M--'; to restore the font size, type 'C-x
 +C-M-0'.  The final key in these commands may be repeated without the
 +leading 'C-x' and without the modifiers, e.g. 'C-x C-M-+ C-M-+ C-M-+'
 +and 'C-x C-M-+ + +' increase the font size by three steps.  When
 +'mouse-wheel-mode' is enabled, 'C-M-wheel-up' and 'C-M-wheel-down' also
 +increase and decrease the font size globally.  Additionally, the
 +user option 'global-text-scale-adjust-resizes-frames' controls whether
 +the frames are resized when the font size is changed.
 +
- ---
 +** New config variable 'syntax-wholeline-max' to reduce the cost of long lines.
 +This variable is used by some operations (mostly syntax-propertization
 +and font-locking) to treat lines longer than this variable as if they
 +were made up of various smaller lines.  This can help reduce the
 +slowdowns seen in buffers made of a single long line, but can also
 +cause misbehavior in the presence of such long lines (though most of
 +that misbehavior should usually be limited to mis-highlighting).  You
 +can recover the previous behavior with:
 +
 +    (setq syntax-wholeline-max most-positive-fixnum)
 +
- +++
 +** New bindings in 'find-function-setup-keys' for 'find-library'.
 +When 'find-function-setup-keys' is enabled, 'C-x L' is now bound to
 +'find-library', 'C-x 4 L' is now bound to 'find-library-other-window'
 +and 'C-x 5 L' is now bound to 'find-library-other-frame'.
 +
- ---
 +** New key binding after 'M-x' or 'M-X': 'M-X'.
 +Emacs allows different completion predicates to be used with 'M-x'
 +(i.e., 'execute-extended-command') via the
 +'read-extended-command-predicate' user option.  Emacs also has the
 +'M-X' (note upper case X) command, which only displays commands
 +especially relevant to the current buffer.  Emacs now allows toggling
 +between these modes while the user is inputting a command by hitting
 +'M-X' while in the minibuffer.
 +
- ---
 +** Interactively, 'kill-buffer' will now offer to save the buffer if unsaved.
 +
- ---
 +** New commands 'duplicate-line' and 'duplicate-dwim'.
 +'duplicate-line' duplicates the current line the specified number of times.
 +'duplicate-dwim' duplicates the region if it is active.  If not, it
 +works like 'duplicate-line'.  An active rectangular region is
 +duplicated on its right-hand side.  The new user option
 +'duplicate-line-final-position' specifies where to move point
 +after duplicating a line.
 +
- +++
 +** Files with the ".eld" extension are now visited in 'lisp-data-mode'.
 +
- +++
 +** 'network-lookup-address-info' can now check numeric IP address validity.
 +Specifying 'numeric' as the new optional HINTS argument makes it
 +check if the passed address is a valid IPv4/IPv6 address (without DNS
 +traffic).
 +
 +    (network-lookup-address-info "127.1" 'ipv4 'numeric)
 +    => ([127 0 0 1 0])
 +
- +++
 +** New command 'find-sibling-file'.
 +This command jumps to a file considered a "sibling file", which is
 +determined according to the new user option 'find-sibling-rules'.
 +
- +++
 +** New user option 'delete-selection-temporary-region'.
 +When non-nil, 'delete-selection-mode' will only delete the temporary
 +regions (usually set by mouse-dragging or shift-selection).
 +
- +++
 +** New user option 'switch-to-prev-buffer-skip-regexp'.
 +This should be a regexp or a list of regexps; buffers whose names
 +match those regexps will be ignored by 'switch-to-prev-buffer' and
 +'switch-to-next-buffer'.
 +
- ---
 +** New command 'rename-visited-file'.
 +This command renames the file visited by the current buffer by moving
 +it to a new name or location, and also makes the buffer visit this new
 +file.
 +
 +** Menus
 +
- ---
 +*** The entries following the buffers in the "Buffers" menu can now be altered.
 +Change the 'menu-bar-buffers-menu-command-entries' variable to alter
 +the entries that follow the buffer list.
 +
- +++
 +** 'delete-process' is now a command.
 +When called interactively, it will kill the process running in the
 +current buffer (if any).  This can be useful if you have runaway
 +output in the current buffer (from a process or a network connection),
 +and want to stop it.
 +
- +++
 +** New command 'restart-emacs'.
 +This is like 'save-buffers-kill-emacs', but instead of just killing
 +the current Emacs process at the end, it starts a new Emacs process
 +(using the same command line arguments as the running Emacs process).
 +'kill-emacs' and 'save-buffers-kill-emacs' have also gained new
 +optional arguments to restart instead of just killing the current
 +process.
 +
 +** Drag and Drop
 +
- +++
 +*** New user option 'mouse-drag-mode-line-buffer'.
 +If non-nil, dragging on the buffer name part of the mode-line will
 +drag the buffer's associated file to other programs.  This option is
 +currently only available on X, Haiku and Nextstep (GNUstep or macOS).
 +
- ---
 +*** New user option 'mouse-drag-and-drop-region-cross-program'.
 +If non-nil, this option allows dragging text in the region from Emacs
 +to another program.
 +
- +++
 +*** New user option 'mouse-drag-and-drop-region-scroll-margin'.
 +If non-nil, this option allows scrolling a window while dragging text
 +around without a scroll wheel.
 +
- +++
 +*** The value of 'mouse-drag-copy-region' can now be the symbol 'non-empty'.
 +This prevents mouse drag gestures from putting empty strings onto the
 +kill ring.
 +
- +++
 +*** New user options 'dnd-indicate-insertion-point' and 'dnd-scroll-margin'.
 +These options allow adjusting point and scrolling a window when
 +dragging items from another program.
 +
- +++
 +*** The X Direct Save (XDS) protocol is now supported.
 +This means dropping an image or file link from programs such as
 +Firefox will no longer create a temporary file in a random directory,
 +instead asking you where to save the file first.
 +
- +++
 +** New user option 'record-all-keys'.
 +If non-nil, this option will force recording of all input keys,
 +including those typed in response to passwords prompt (this was the
 +previous behavior).  The default is nil, which inhibits recording of
 +passwords.
 +
- +++
 +** New function 'command-query'.
 +This function makes its argument command prompt the user for
 +confirmation before executing.
 +
- ---
 +** The 'disabled' property of a command's symbol can now be a list.
 +The first element of the list should be the symbol 'query', which will
 +cause the command disabled this way prompt the user with a y/n or a
 +yes/no question before executing.  The new function 'command-query' is
 +a convenient method of making commands disabled in this way.
 +
- +++
 +** 'count-words' will now report buffer totals if given a prefix.
 +Without a prefix, it will only report the word count for the narrowed
 +part of the buffer.
 +
- +++
 +** 'count-words' will now report sentence count when used interactively.
 +
- ---
 +** New user option 'set-message-functions'.
 +It allows more flexible control of how echo-area messages are displayed
 +by adding functions to this list.  The default value is a list of one
 +element: 'set-minibuffer-message', which displays echo-area messages
 +at the end of the minibuffer text when the minibuffer is active.
 +Other useful functions include 'inhibit-message', which allows
 +specifying, via 'inhibit-message-regexps', the list of messages whose
 +display should be inhibited; and 'set-multi-message' that accumulates
 +recent messages and displays them stacked together.
 +
- +++
 +** New user option 'find-library-include-other-files'.
 +If set to nil, commands like 'find-library' will only include library
 +files in the completion candidates.  The default is t, which preserves
 +previous behavior, whereby non-library files could also be included.
 +
- ---
 +** New command 'sqlite-mode-open-file' for examining an sqlite3 file.
 +This uses the new 'sqlite-mode' which allows listing the tables in a
 +DB file, and examining and modifying the columns and the contents of
 +those tables.
 +
- +++
 +** 'write-file' will now copy some file mode bits.
 +If the current buffer is visiting a file that is executable, the
 +'C-x C-w' command will now make the new file executable, too.
 +
- +++
 +** New user option 'process-error-pause-time'.
 +This determines how long to pause Emacs after a process
 +filter/sentinel error has been handled.
 +
- +++
 +** New faces for font-lock.
 +These faces are primarily meant for use with tree-sitter.  They are:
 +'font-lock-bracket-face', 'font-lock-delimiter-face',
 +'font-lock-escape-face', 'font-lock-function-call-face',
 +'font-lock-misc-punctuation-face', 'font-lock-number-face',
 +'font-lock-operator-face', 'font-lock-property-name-face',
 +'font-lock-property-use-face', 'font-lock-punctuation-face',
 +'font-lock-regexp-face', and 'font-lock-variable-use-face'.
 +
- +++
 +** New face 'variable-pitch-text'.
 +This face is like 'variable-pitch' (from which it inherits), but is
 +slightly larger, which should help with the visual size differences
 +between the default, non-proportional font and proportional fonts when
 +mixed.
 +
- +++
 +** New face 'mode-line-active'.
 +This inherits from the 'mode-line' face, but is the face actually used
 +on the mode lines (along with 'mode-line-inactive').
 +
- +++
 +** New face attribute pseudo-value 'reset'.
 +This value stands for the value of the corresponding attribute of the
 +'default' face.  It can be used to reset attribute values produced by
 +inheriting from other faces.
 +
- +++
 +** New X resource "borderThickness".
 +This controls the thickness of the external borders of the menu bars
 +and pop-up menus.
 +
- +++
 +** New X resource "inputStyle".
 +This controls the style of the pre-edit and status areas of X input
 +methods.
 +
- +++
 +** New X resources "highlightForeground" and "highlightBackground".
 +Only in the Lucid build, this controls colors used for highlighted
 +menu item widgets.
 +
- +++
 +** On X, Emacs now tries to synchronize window resize with the window manager.
 +This leads to less flicker and empty areas of a frame being displayed
 +when a frame is being resized.  Unfortunately, it does not work on
 +some ancient buggy window managers, so if Emacs appears to freeze, but
 +is still responsive to input, you can turn it off by setting the X
 +resource "synchronizeResize" to "off".
 +
- +++
 +** On X, Emacs can optionally synchronize display with the graphics hardware.
 +When this is enabled by setting the X resource "synchronizeResize" to
 +"extended", frame content "tearing" is drastically reduced.  This is
 +only supported on the Motif, Lucid, and no-toolkit builds, and
 +requires an X compositing manager supporting the extended frame
 +synchronization protocol (see
 +https://fishsoup.net/misc/wm-spec-synchronization.html).
 +
 +This behavior can be toggled on and off via the frame parameter
 +'use-frame-synchronization'.
 +
- +++
 +** New frame parameter 'alpha-background' and X resource "alphaBackground".
 +This controls the opacity of the text background when running on a
 +composited display.
 +
- ---
 +** New frame parameter 'shaded'.
 +With window managers which support this, it controls whether or not a
 +frame's contents will be hidden, leaving only the title bar on display.
 +
- +++
 +** New user option 'x-gtk-use-native-input'.
 +This controls whether or not GTK input methods are used by Emacs,
 +instead of XIM input methods.  Defaults to nil.
 +
- +++
 +** New user option 'use-system-tooltips'.
 +This controls whether to use the toolkit tooltips, or Emacs's own
 +native implementation of tooltips as small frames.  This option is
 +only meaningful if Emacs was built with GTK+, Nextstep, or Haiku
 +support, and defaults to t, which makes Emacs use the toolkit
 +tooltips.  The existing GTK-specific option
 +'x-gtk-use-system-tooltips' is now an alias of this new option.
 +
- ---
 +** Non-native tooltips are now supported on Nextstep.
 +This means Emacs built with GNUstep or built on macOS is now able to
 +display different faces and images inside tooltips when the
 +'use-system-tooltips' user option is nil.
 +
- ---
 +** New minor mode 'pixel-scroll-precision-mode'.
 +When enabled, and if your mouse supports it, you can scroll the
 +display up or down at pixel resolution, according to what your mouse
 +wheel reports.  Unlike 'pixel-scroll-mode', this mode scrolls the
 +display pixel-by-pixel, as opposed to only animating line-by-line
 +scrolls.
 +
 +** Terminal Emacs
 +
- ---
 +*** Emacs will now use 24-bit colors on terminals that support "Tc" capability.
 +This is in addition to previously-supported ways of discovering 24-bit
 +color support: either via the "RGB" or "setf24" capabilities, or if
 +the 'COLORTERM' environment variable is set to the value "truecolor".
 +
- ---
 +*** Select active regions with xterm selection support.
 +On terminals with xterm "setSelection" support, the active region may be
 +saved to the X primary selection, following the
 +'select-active-regions' variable.  This support is enabled when
 +'tty-select-active-regions' is non-nil.
 +
- ---
 +*** New command to set up display of unsupported characters.
 +The new command 'standard-display-by-replacement-char' produces Lisp
 +code that sets up the 'standard-display-table' to use a replacement
 +character for display of characters that the text-mode terminal
 +doesn't support.  This code is intended to be used in your init files.
 +This feature is most useful with the Linux console and similar
 +terminals, where Emacs has a reliable way of determining which
 +characters have glyphs in the font loaded into the terminal's memory.
 +
- +++
 +*** New functions to set terminal output buffer size.
 +The new functions 'tty--set-output-buffer-size' and
 +'tty--output-buffer-size' allow setting and retrieving the output
 +buffer size of a terminal device.  The default buffer size is and has
 +always been BUFSIZ, which is defined in your system's stdio.h.  When
 +you set a buffer size with 'tty--set-output-buffer-size', this also
 +prevents Emacs from explicitly flushing the tty output stream, except
 +at the end of display update.
 +
 +** ERT
 +
- ---
 +*** New ERT variables 'ert-batch-print-length' and 'ert-batch-print-level'.
 +These variables will override 'print-length' and 'print-level' when
 +printing Lisp values in ERT batch test results.
 +
- +++
 +*** Redefining an ERT test in batch mode now signals an error.
 +Executing 'ert-deftest' with the same name as an existing test causes
 +the previous definition to be discarded, which was probably not
 +intended when this occurs in batch mode.  To remedy the error, rename
 +tests so that they all have unique names.
 +
- ---
 +*** ERT can generate JUnit test reports.
 +When environment variable 'EMACS_TEST_JUNIT_REPORT' is set, ERT
 +generates a JUnit test report under this file name.  This is useful
 +for Emacs integration into CI/CD test environments.
 +
- +++
 +*** Unbound test symbols now signal an 'ert-test-unbound' error.
 +This affects the 'ert-select-tests' function and its callers.
 +
 +** Emoji
 +
- +++
 +*** Emacs now has several new methods for inserting Emoji.
 +The Emoji commands are under the new 'C-x 8 e' prefix.
 +
- +++
 +*** New command 'emoji-insert' (bound to 'C-x 8 e e' and 'C-x 8 e i').
 +This command guides you through various Emoji categories and
 +combinations in a graphical menu system.
 +
- +++
 +*** New command 'emoji-search' (bound to 'C-x 8 e s').
 +This command lets you search for and insert an Emoji based on names.
 +
- ---
 +*** New command 'emoji-list' (bound to 'C-x 8 e l').
 +This command lists all Emoji (categorized by themes) in a special
 +buffer and lets you choose one of them to insert.
 +
- +++
 +*** New command 'emoji-recent' (bound to 'C-x 8 e r').
 +This command lets you choose among the Emoji you have recently
 +inserted and insert it.
 +
- ---
 +*** New command 'emoji-describe' (bound to 'C-x 8 e d').
 +This command will tell you the name of the Emoji at point.  (It also
 +works for non-Emoji characters.)
 +
- ---
 +*** New commands 'emoji-zoom-increase' and 'emoji-zoom-decrease'.
 +These are bound to 'C-x 8 e +' and 'C-x 8 e -', respectively.  They
 +can be used on any character, but are mainly useful for Emoji.
 +
- ---
 +*** New command 'emoji-zoom-reset'.
 +This is bound to 'C-x 8 e 0', and undoes any size changes performed by
 +'emoji-zoom-increase' and 'emoji-zoom-decrease'.
 +
- ---
 +*** New input method 'emoji'.
 +This allows you to enter Emoji using short strings, eg ':face_palm:'
 +or ':scream:'.
 +
 +** Help
 +
- +++
 +*** Variable values displayed by 'C-h v' in "*Help*" are now fontified.
 +
- ---
 +*** New user option 'help-clean-buttons'.
 +If non-nil, link buttons in "*Help*" buffers will have any surrounding
 +quotes removed.
 +
- +++
 +*** 'M-x apropos-variable' output now includes values of variables.
 +Such an apropos buffer is more easily viewed with outlining after
 +enabling 'outline-minor-mode' in 'apropos-mode'.
 +
- +++
 +*** New docstring syntax to indicate that symbols shouldn't be links.
 +When displaying docstrings in "*Help*" buffers, strings that are
 +"`like-this'" are made into links (if they point to a bound
 +function/variable).  This can lead to false positives when talking
 +about values that are symbols that happen to have the same names as
 +functions/variables.  To inhibit this buttonification, use the new
 +"\\+`like-this'" syntax.
 +
- ---
 +*** New user option 'help-window-keep-selected'.
 +If non-nil, commands to show the info manual and the source will reuse
 +the same window in which the "*Help*" buffer is shown.
 +
- +++
 +*** Commands like 'C-h f' have changed how they describe menu bindings.
 +For instance, previously a command might be described as having the
 +following bindings:
 +
 +    It is bound to <open>, C-x C-f, <menu-bar> <file> <new-file>.
 +
 +This has been changed to:
 +
 +    It is bound to <open> and C-x C-f.
 +    It can also be invoked from the menu: File → Visit New File...
 +
- ---
 +*** The 'C-h .' command now accepts a prefix argument.
 +'C-u C-h .' would previously inhibit displaying a warning message if
 +there was no local help at point.  This has been changed to call
 +'button-describe'/'widget-describe' and display button/widget help
 +instead.
 +
- ---
 +*** New user option 'help-enable-variable-value-editing'.
 +If enabled, 'e' on a value in "*Help*" will pop you to a new buffer
 +where you can edit the value.  This is not enabled by default, because
 +it is easy to make an edit that yields an invalid result.
 +
- ---
 +*** 'C-h b' uses outlining by default.
 +Set 'describe-bindings-outline' to nil to get back the old behavior.
 +
- +++
 +*** Jumping to function/variable source now saves mark before moving point.
 +Jumping to source from a "*Help*" buffer moves point when the source
 +buffer is already open.  Now, the old point is pushed onto mark ring.
 +
- ---
 +*** New key bindings in "*Help*" buffers: 'n' and 'p'.
 +These will take you (respectively) to the next and previous "page".
 +
- +++
 +*** 'describe-char' now also outputs the name of Emoji sequences.
 +
- ---
 +*** New key binding in "*Help*" buffer: 'I'.
 +This will take you to the Emacs Lisp manual entry for the item
 +displayed, if any.
 +
- +++
 +*** The 'C-h m' ('describe-mode') "*Help*" buffer has been reformatted.
 +It now only includes local minor modes at the start, and the global
 +minor modes are listed after the major mode.
 +
- ---
 +*** The user option 'help-window-select' now affects apropos commands.
 +The apropos commands will now select the apropos window if
 +'help-window-select' is non-nil.
 +
- ---
 +*** 'describe-keymap' now considers the symbol at point.
 +If the symbol at point is a keymap, 'describe-keymap' suggests it as
 +the default candidate.
 +
- +++
 +*** New command 'help-quick' displays an overview of common commands.
 +The command pops up a buffer at the bottom of the screen with a few
 +helpful commands for various tasks.  You can toggle the display using
 +'C-h C-q'.
 +
 +** Emacs now comes with Org v9.6.
 +See the file "etc/ORG-NEWS" for user-visible changes in Org.
 +
 +** Outline Mode
 +
- +++
 +*** Support for customizing the default visibility state of headings.
 +Customize the user option 'outline-default-state' to define what
 +headings will be visible initially, after Outline mode is turned on.
 +When the value is a number, the user option 'outline-default-rules'
 +determines the visibility of the subtree starting at the corresponding
 +level.  Values are provided to control showing a heading subtree
 +depending on whether the heading matches a regexp, or on whether its
 +subtree has long lines or is itself too long.
 +
 +** Outline Minor Mode
 +
- +++
 +*** New user option 'outline-minor-mode-use-buttons'.
 +If non-nil, Outline Minor Mode will use buttons to hide/show outlines
 +in addition to the ellipsis.  The default is nil, but in 'help-mode'
 +it has the value 'insert' that inserts the buttons directly into the
 +buffer, and you can use 'RET' to cycle outline visibility.  When
 +the value is 'in-margins', Outline Minor Mode uses the window margins
 +for buttons that hide/show outlines.
 +
- +++
 +*** Buttons and headings now have their own keymaps.
 +'outline-button-icon-map', 'outline-overlay-button-map', and
 +'outline-inserted-button-map' are now available as defined keymaps
 +instead of being anonymous keymaps.
 +
 +** Windows
 +
- +++
 +*** New commands 'split-root-window-below' and 'split-root-window-right'.
 +These commands split the root window in two, and are bound to 'C-x w 2'
 +and 'C-x w 3', respectively.  A number of other useful window-related
 +commands are now available with key sequences that start with the
 +'C-x w' prefix.
 +
- +++
 +*** New display action 'display-buffer-full-frame'.
 +This action removes other windows from the frame when displaying a
 +buffer on that frame.
 +
- +++
 +*** 'display-buffer' now can set up the body size of the chosen window.
 +For example, a 'display-buffer-alist' entry of
 +
 +    (window-width . (body-columns . 40))
 +
 +will make the body of the chosen window 40 columns wide.  For the
 +height use 'window-height' and 'body-lines', respectively.
 +
- +++
 +*** 'display-buffer' provides more options for using an existing window.
 +The display buffer action functions 'display-buffer-use-some-window' and
 +'display-buffer-use-least-recent-window' now honor the action alist
 +entry 'window-min-height' as well as the entries listed below to make
 +the display of several buffers in a row more amenable.
 +
- +++
 +*** New buffer display action alist entry 'lru-frames'.
 +This allows specifying which frames 'display-buffer' should consider
 +when using a window that shows another buffer.  It is interpreted as
 +per the ALL-FRAMES argument of 'get-lru-window'.
 +
- +++
 +*** New buffer display action alist entry 'lru-time'.
 +'display-buffer' will ignore windows with a use time higher than this
 +when using a window that shows another buffer.
 +
- +++
 +*** New buffer display action alist entry 'bump-use-time'.
 +This has 'display-buffer' bump the use time of any window it returns,
 +making it a less likely candidate for displaying another buffer.
 +
- ---
 +*** New buffer display action alist entry 'window-min-width'.
 +This allows specifying a preferred minimum width of the window used to
 +display a buffer.
 +
- +++
 +*** You can specify on which window 'scroll-other-window' operates.
 +This is controlled by the new 'other-window-scroll-default' variable,
 +which should be set to a function that returns a window.  When this
 +variable is nil, 'next-window' is used.
 +
 +** Frames
 +
- +++
 +*** Deleted frames can now be undeleted.
 +The 16 most recently deleted frames can be undeleted with 'C-x 5 u' when
 +'undelete-frame-mode' is enabled.  Without a prefix argument, undelete
 +the most recently deleted frame.  With a numerical prefix argument
 +between 1 and 16, where 1 is the most recently deleted frame, undelete
 +the corresponding deleted frame.
 +
- ---
 +*** The variable 'icon-title-format' can now have the value t.
 +That value means to use 'frame-title-format' for iconified frames.
 +This is useful with some window managers and desktop environments
 +which treat changes in frame's title as requests to raise the frame
 +and/or give it input focus, or if you want the frame's title to be the
 +same no matter if the frame is iconified or not.
 +
 +** Tab Bars and Tab Lines
 +
- ---
 +*** New user option 'tab-bar-auto-width' to automatically determine tab width.
 +This option is non-nil by default, which resizes tab-bar tabs so that
 +their width is evenly distributed across the tab bar.  A companion
 +option 'tab-bar-auto-width-max' controls the maximum width of a tab
 +before its name on display is truncated.
 +
- ---
 +*** 'C-x t RET' creates a new tab when the provided tab name doesn't exist.
 +It prompts for the name of a tab and switches to it, creating a new
 +tab if no tab exists by that name.
 +
- ---
 +*** New keymap 'tab-bar-history-mode-map'.
 +By default, it contains 'C-c <left>' and 'C-c <right>' to browse
 +the history of tab window configurations back and forward.
 +
- +++
 +** Better detection of text suspiciously reordered on display.
 +The function 'bidi-find-overridden-directionality' has been extended
 +to detect reordering effects produced by embeddings and isolates
 +(started by directional formatting control characters such as RLO and
 +LRI).  The new command 'highlight-confusing-reorderings' finds and
 +highlights segments of buffer text whose reordering for display is
 +suspicious and could be malicious.
 +
 +** Emacs Server and Client
 +
- +++
 +*** New command-line option '-r'/'--reuse-frame' for emacsclient.
 +With this command-line option, Emacs reuses an existing graphical client
 +frame if one exists; otherwise it creates a new frame.
 +
- +++
 +*** New command-line option '-w N'/'--timeout=N' for emacsclient.
 +With this command-line option, emacsclient will exit if Emacs does not
 +respond within N seconds.  The default is to wait forever.
 +
- +++
 +*** 'server-stop-automatically' can be used to automatically stop the server.
 +The Emacs server will be automatically stopped when certain conditions
 +are met.  The conditions are determined by the argument to
 +'server-stop-automatically', which can be 'empty', 'delete-frame' or
 +'kill-terminal'.
 +
 +** Rcirc
 +
- +++
 +*** New command 'rcirc-when'.
 +This shows the reception time of the message at point (if available).
 +
- +++
 +*** New user option 'rcirc-cycle-completion-flag'.
 +Rcirc now uses the default 'completion-at-point' mechanism.  The
 +conventional IRC behavior of completing by cycling through the
 +available options can be restored by enabling this option.
 +
- ---
 +*** New user option 'rcirc-bridge-bot-alist'.
 +If you are in a channel where a bot is responsible for bridging
 +between networks, you can use this variable to make these messages
 +appear more native.  For example, you might set the option to:
 +
 +    (setopt rcirc-bridge-bot-alist '(("bridge" . "{\\(.+?\\)}[[:space:]]+")))
 +
 +for messages like
 +
 +    09:47 <bridge> {john} I am not on IRC
 +
 +to be reformatted into
 +
 +    09:47 <john> I am not on IRC
 +
- +++
 +*** New formatting commands.
 +Most IRC clients (including rcirc) support basic formatting using
 +control codes.  Under the 'C-c C-f' prefix a few commands have been
 +added to insert these automatically.  For example, if a region is
 +active and 'C-c C-f C-b' is invoked, markup is inserted for the region
 +to be highlighted in bold.
 +
 +** Imenu
 +
- ---
 +*** 'imenu' is now bound to 'M-g i' globally.
 +
- ---
 +*** New function 'imenu-flush-cache'.
 +Use it if you want Imenu to forget the buffer's index alist and
 +recreate it anew next time 'imenu' is invoked.
 +
- +++
 +** Emacs is now capable of abandoning a window's redisplay that takes too long.
 +This is controlled by the new variable 'max-redisplay-ticks'.  If that
 +variable is set to a non-zero value, display of a window will be
 +aborted after that many low-level redisplay operations, thus
 +preventing Emacs from becoming wedged when visiting files with very
 +long lines.  The default is zero, which disables the feature: Emacs
 +will wait forever for redisplay to finish.  (We believe you won't need
 +this feature, given the ability to display buffers with very long
 +lines.)
 +
 +\f
 +* Editing Changes in Emacs 29.1
 +
- ---
 +** 'M-SPC' is now bound to 'cycle-spacing'.
 +Formerly it invoked 'just-one-space'.  The actions performed by
 +'cycle-spacing' and their order can now be customized via the user
 +option 'cycle-spacing-actions'.
 +
- ---
 +** 'zap-to-char' and 'zap-up-to-char' are case-sensitive for upper-case chars.
 +These commands now behave as case-sensitive for interactive calls when
 +they are invoked with an uppercase character, regardless of the value
 +of 'case-fold-search'.
 +
- ---
 +** 'scroll-other-window' and 'scroll-other-window-down' now respect remapping.
 +These commands (bound to 'C-M-v' and 'C-M-V') used to scroll the other
 +windows without looking at customizations in that other window.  These
 +functions now check whether they have been rebound in the buffer shown
 +in that other window, and then call the remapped function instead.  In
 +addition, these commands now also respect the
 +'scroll-error-top-bottom' user option.
 +
- +++
 +** Indentation of 'cl-flet' and 'cl-labels' has changed.
 +These forms now indent like this:
 +
 +    (cl-flet ((bla (x)
 +                (* x x)))
 +      (bla 42))
 +
 +This change also affects 'cl-macrolet', 'cl-flet*' and
 +'cl-symbol-macrolet'.
 +
- +++
 +** New user option 'translate-upper-case-key-bindings'.
 +Set this option to nil to inhibit the default translation of upper
 +case keys to their lower case variants.
 +
- ---
 +** New command 'ensure-empty-lines'.
 +This command increases (or decreases) the number of empty lines before
 +point.
 +
- +++
 +** Improved mouse behavior with auto-scrolling modes.
 +When clicking inside the 'scroll-margin' or 'hscroll-margin' region,
 +point is now moved only when releasing the mouse button.  This no
 +longer results in a bogus selection, unless the mouse has also been
 +dragged.
 +
- ---
 +** 'kill-ring-max' now defaults to 120.
 +
- ---
 +** New user option 'yank-menu-max-items'.
 +Customize this option to limit the number of entries in the menu
 +"Edit → Paste from Kill Menu".  The default is 60.
 +
- +++
 +** New user option 'copy-region-blink-predicate'.
 +By default, when copying a region with 'kill-ring-save', Emacs only
 +blinks point and mark when the region is not denoted visually, that
 +is, when either the region is inactive, or the 'region' face is
 +indistinguishable from the 'default' face.
 +
 +Users who would rather enable blinking unconditionally can now set
 +this user option to 'always'.  To disable blinking unconditionally,
 +either set this option to 'ignore', or set 'copy-region-blink-delay'
 +to 0.
 +
- +++
 +** Performing a pinch gesture on a touchpad now increases the text scale.
 +
 +** Show Paren Mode
 +
- +++
 +*** New user option 'show-paren-context-when-offscreen'.
 +When non-nil, if the point is in a closing delimiter and the opening
 +delimiter is offscreen, shows some context around the opening
 +delimiter in the echo area.  The default is nil.
 +
 +This option can also be set to the symbols 'overlay' or 'child-frame',
 +in which case the context is shown in an overlay or child-frame at the
 +top-left of the current window.  The latter option requires a
 +graphical frame.  On non-graphical frames, the context is shown in the
 +echo area.
 +
 +** Comint
 +
- ---
 +*** 'comint-term-environment' is now aware of connection-local variables.
 +The user option 'comint-terminfo-terminal' and the variable
 +'system-uses-terminfo' can now be set as connection-local variables to
 +change the terminal used on a remote host.
 +
- ---
 +*** New user option 'comint-delete-old-input'.
 +When nil, this prevents comint from deleting the current input when
 +inserting previous input using '<mouse-2>'.  The default is t, to
 +preserve previous behavior.
 +
- ---
 +*** New minor mode 'comint-fontify-input-mode'.
 +This minor mode is enabled by default in "*shell*" and "*ielm*"
 +buffers.  It fontifies input text according to 'shell-mode' or
 +'emacs-lisp-mode' font-lock rules.  Customize the user options
 +'shell-fontify-input-enable' and 'ielm-fontify-input-enable' to nil if
 +you don't want to enable input fontification by default.
 +
 +** Mwheel
 +
- ---
 +*** New user options for alternate wheel events.
 +The user options 'mouse-wheel-down-alternate-event' and
 +'mouse-wheel-up-alternate-event' as well as the variables
 +'mouse-wheel-left-alternate-event' and
 +'mouse-wheel-right-alternate-event' have been added to better support
 +systems where two kinds of wheel events can be received.
 +
 +** Internationalization
 +
- ---
 +*** The '<Delete>' function key now allows deleting the entire composed sequence.
 +For the details, see the item about the 'delete-forward-char' command
 +above.
 +
- ---
 +*** New user option 'composition-break-at-point'.
 +Setting it to a non-nil value temporarily disables automatic
 +composition of character sequences at point, and thus makes it easier
 +to edit such sequences by allowing point to "enter" the composed
 +sequence.
 +
- ---
 +*** Support for many old scripts and writing systems.
 +Emacs now supports, and has language-environments and input methods,
 +for several dozens of old scripts that were used in the past for
 +various languages.  For each such script Emacs now has font-selection
 +and character composition rules, a language environment, and an input
 +method.  The newly-added scripts and the corresponding language
 +environments are:
 +
 + Tai Tham script and the Northern Thai language environment
 +
 + Brahmi script and language environment
 +
 + Kaithi script and language environment
 +
 + Tirhuta script and language environment
 +
 + Sharada script and language environment
 +
 + Siddham script and language environment
 +
 + Syloti Nagri script and language environment
 +
 + Modi script and language environment
 +
 + Baybayin script and Tagalog language environment
 +
 + Hanunoo script and language environment
 +
 + Buhid script and language environment
 +
 + Tagbanwa script and language environment
 +
 + Limbu script and language environment
 +
 + Balinese script and language environment
 +
 + Javanese script and language environment
 +
 + Sundanese script and language environment
 +
 + Batak script and language environment
 +
 + Rejang script and language environment
 +
 + Makasar script and language environment
 +
 + Lontara script and language environment
 +
 + Hanifi Rohingya script and language environment
 +
 + Grantha script and language environment
 +
 + Kharoshthi script and language environment
 +
 + Lepcha script and language environment
 +
 + Meetei Mayek script and language environment
 +
 + Adlam script and language environment
 +
 + Mende Kikakui script and language environment
 +
 + Wancho script and language environment
 +
 + Toto script and language environment
 +
 + Gothic script and language environment
 +
 + Coptic script and language environment
 +
 + Mongolian-traditional script and language environment
 +
 + Mongolian-cyrillic language environment
 +
- ---
 +*** The "Oriya" language environment was renamed to "Odia".
 +This is to follow the change in the official name of the script.  The
 +'oriya' input method was also renamed to 'odia'.  However, the old
 +name of the language environment and the input method are still
 +supported.
 +
- ---
 +*** New Greek translation of the Emacs tutorial.
 +Type 'C-u C-h t' to select it in case your language setup does not do
 +so automatically.
 +
- ---
 +*** New Ukrainian translation of the Emacs tutorial.
 +
- ---
 +*** New Farsi/Persian translation of the Emacs tutorial.
 +
- ---
 +*** New default phonetic input method for the Tamil language environment.
 +The default input method for the Tamil language environment is now
 +"tamil-phonetic" which is a customizable phonetic input method.  To
 +change the input method's translation rules, customize the user option
 +'tamil-translation-rules'.
 +
- ---
 +*** New 'tamil99' input method for the Tamil language.
 +This supports the keyboard layout specifically designed for the Tamil
 +language.
 +
- ---
 +*** New input method 'slovak-qwerty'.
 +This is a variant of the 'slovak' input method, which corresponds to
 +the QWERTY Slovak keyboards.
 +
- ---
 +*** New input method 'cyrillic-chuvash'.
 +This input method is based on the russian-computer input method, and
 +is intended for typing in the Chuvash language written in the Cyrillic
 +script.
 +
- ---
 +*** New input method 'cyrillic-mongolian'.
 +This input method is for typing in the Mongolian language using the
 +Cyrillic script.  It is the default input method for the new
 +Mongolian-cyrillic language environment, see above.
 +
 +\f
 +* Changes in Specialized Modes and Packages in Emacs 29.1
 +
 +** Ecomplete
 +
- ---
 +*** New commands 'ecomplete-edit' and 'ecomplete-remove'.
 +These allow you to (respectively) edit and bulk-remove entries from
 +the ecomplete database.
 +
- ---
 +*** New user option 'ecomplete-auto-select'.
 +If non-nil and there's only one matching option, auto-select that.
 +
- +++
 +*** New user option 'ecomplete-filter-regexp'.
 +If non-nil, this user option describes what entries not to add to the
 +database stored on disk.
 +
 +** Auth Source
 +
- +++
 +*** New user option 'auth-source-pass-extra-query-keywords'.
 +Whether to recognize additional keyword params, like ':max' and
 +':require', as well as accept lists of query terms paired with
 +applicable keywords.  This disables most known behavioral quirks
 +unique to auth-source-pass, such as wildcard subdomain matching.
 +
 +** Dired
 +
- ---
 +*** 'dired-guess-shell-command' moved from dired-x to dired.
 +This means that 'dired-do-shell-command' will now provide smarter
 +defaults without first having to require 'dired-x'.  See the node
 +"(emacs) Shell Command Guessing" in the Emacs manual for more details.
 +
- +++
 +*** 'dired-clean-up-buffers-too' moved from dired-x to dired.
 +This means that Dired now offers to kill buffers visiting files and
 +dirs when they are deleted in Dired.  Before, you had to require
 +'dired-x' to enable this behavior.  To disable this behavior,
 +customize the user option 'dired-clean-up-buffers-too' to nil.  The
 +related user option 'dired-clean-confirm-killing-deleted-buffers'
 +(which see) has also been moved to 'dired'.
 +
- +++
 +*** 'dired-do-relsymlink' moved from dired-x to dired.
 +The corresponding key 'Y' is now bound by default in Dired.
 +
- ---
 +*** 'dired-do-relsymlink-regexp' moved from dired-x to dired.
 +The corresponding key sequence '% Y' is now bound by default in Dired.
 +
- +++
 +*** 'M-G' is now bound to 'dired-goto-subdir'.
 +Before, that binding was only available if the dired-x package was
 +loaded.
 +
- ---
 +*** 'dired-info' and 'dired-man' moved from dired-x to dired.
 +The 'dired-info' and 'dired-man' commands have been moved from the
 +dired-x package to dired.  They have also been renamed to
 +'dired-do-info' and 'dired-do-man'; the old command names are obsolete
 +aliases.
 +
 +The keys 'I' ('dired-do-info') and 'N' ('dired-do-man') are now bound
 +in Dired mode by default.  The user options 'dired-bind-man' and
 +'dired-bind-info' no longer have any effect and are obsolete.
 +
 +To get the old behavior back and unbind these keys in Dired mode, add
 +the following to your Init file:
 +
 +    (with-eval-after-load 'dired
 +      (keymap-set dired-mode-map "N" nil)
 +      (keymap-set dired-mode-map "I" nil))
 +
- ---
 +*** New command 'dired-do-eww'.
 +This command visits the file on the current line with EWW.
 +
- ---
 +*** 'browse-url-of-dired-file' can now call the secondary browser.
 +When invoked with a prefix arg, this will now call
 +'browse-url-secondary-browser-function' instead of the default
 +browser.  'browse-url-of-dired-file' is bound to 'W' by default in
 +dired mode.
 +
- +++
 +*** New user option 'dired-omit-lines'.
 +This is used by 'dired-omit-mode', and now allows you to hide based on
 +other things than just the file names.
 +
- +++
 +*** New user option 'dired-mouse-drag-files'.
 +If non-nil, dragging file names with the mouse in a Dired buffer will
 +initiate a drag-and-drop session allowing them to be opened in other
 +programs.
 +
- ---
 +*** New user option 'dired-free-space'.
 +Dired will now, by default, include the free space in the first line
 +instead of having it on a separate line.  To get the previous behavior
 +back, say:
 +
 +    (setopt dired-free-space 'separate)
 +
- ---
 +*** New user option 'dired-make-directory-clickable'.
 +If non-nil (which is the default), hitting 'RET' or 'mouse-1' on
 +the directory components at the directory displayed at the start of
 +the buffer will take you to that directory.
 +
- ---
 +*** Search and replace in Dired/Wdired supports more regexps.
 +For example, the regexp ".*" will match only characters that are part
 +of the file name.  Also "^.*$" can be used to match at the beginning
 +of the file name and at the end of the file name.  This is used only
 +when searching on file names.  In Wdired this can be used when the new
 +user option 'wdired-search-replace-filenames' is non-nil (which is the
 +default).
 +
 +** Elisp
 +
- ---
 +*** New command 'elisp-eval-region-or-buffer' (bound to 'C-c C-e').
 +This command evals the forms in the active region or in the whole buffer.
 +
- ---
 +*** New commands 'elisp-byte-compile-file' and 'elisp-byte-compile-buffer'.
 +These commands (bound to 'C-c C-f' and 'C-c C-b', respectively)
 +byte-compile the visited file and the current buffer, respectively.
 +
 +** Games
 +
- +++
 +*** New user option 'tetris-allow-repetitions'.
 +This controls how randomness is implemented (whether to use pure
 +randomness as before, or to use a bag).
 +
 +** Battery
 +
- ---
 +*** New user option 'battery-update-functions'.
 +This can be used to trigger actions based on the battery status.
 +
 +** DocView
 +
- +++
 +*** doc-view can now generate SVG images when viewing PDF files.
 +If Emacs is built with SVG support, doc-view can generate SVG files
 +when using MuPDF as the converter for PDF files, which generally leads
 +to sharper images (especially when zooming), and allows customization
 +of background and foreground color of the page via the new user
 +options 'doc-view-svg-background' and 'doc-view-svg-foreground'.  To
 +activate this behavior, set 'doc-view-mupdf-use-svg' to non-nil if
 +your Emacs has SVG support.  Note that, with some versions of MuPDF,
 +SVG generation is known to sometimes produce SVG files that are buggy
 +or can take a long time to render.
 +
 +** Enriched Mode
 +
- ---
 +*** New command 'enriched-toggle-markup'.
 +This allows you to see the markup in 'enriched-mode' buffers (e.g.,
 +the "HELLO" file).  Bound to 'M-o m' by default.
 +
 +** Shell Script Mode
 +
- ---
 +*** New user option 'sh-indent-statement-after-and'.
 +This controls how statements like the following are indented:
 +
 +    foo &&
 +        bar
 +
 +*** New Flymake backend using the ShellCheck program.
 +It is enabled by default, but requires that the external "shellcheck"
 +command is installed.
 +
 +** CC Mode
 +
- ---
 +*** C++ Mode now supports most of the new features in the C++20 Standard.
 +
- ---
 +*** In Objective-C Mode, no extra types are recognized by default.
 +The default value of 'objc-font-lock-extra-types' has been changed to
 +nil, since too many identifiers were getting misfontified as types.
 +This may cause some actual types not to get fontified.  To get the old
 +behavior back, customize the user option to the value suggested in its
 +doc string.
 +
 +** Cperl Mode
 +
- ---
 +*** New user option 'cperl-file-style'.
 +This option determines the indentation style to be used.  It can also
 +be used as a file-local variable.
 +
 +** Gud
 +
- ---
 +*** 'gud-go' is now bound to 'C-c C-v'.
 +If given a prefix, it will prompt for an argument to use for the
 +run/continue command.
 +
- ---
 +*** 'perldb' now recognizes '-E'.
 +As of Perl 5.10, 'perl -E 0' behaves like 'perl -e 0' but also activates
 +all optional features of the Perl version in use.  'perldb' now uses
 +this invocation as its default.
 +
 +** Customize
 +
- ---
 +*** New command 'custom-toggle-hide-all-widgets'.
 +This is bound to 'H' and toggles whether to hide or show the widget
 +contents.
 +
 +** Diff Mode
 +
- +++
 +*** New user option 'diff-whitespace-style'.
 +Sets the value of the buffer-local variable 'whitespace-style' in
 +'diff-mode' buffers.  By default, this variable is '(face trailing)',
 +which preserves behavior of previous Emacs versions.
 +
- ---
 +*** New user option 'diff-add-log-use-relative-names'.
 +If non-nil insert file names in ChangeLog skeletons relative to the
 +VC root directory.
 +
 +** Ispell
 +
- ---
 +*** 'ispell-region' and 'ispell-buffer' now push the mark.
 +These commands push onto the mark ring the location of the last
 +misspelled word where corrections were offered, so that you can then
 +skip back to that location with 'C-x C-x'.
 +
 +** Dabbrev
 +
- +++
 +*** New function 'dabbrev-capf' for use on 'completion-at-point-functions'.
 +
- +++
 +*** New user option 'dabbrev-ignored-buffer-modes'.
 +Buffers with major modes in this list will be ignored.  By default,
 +this includes "binary" buffers like 'archive-mode' and 'image-mode'.
 +
 +** Package
 +
- +++
 +*** New command 'package-upgrade'.
 +This command allows you to upgrade packages without using 'list-packages'.
 +A package that comes with the Emacs distribution can only be upgraded
 +after you install, once, a newer version from ELPA via the
 +package-menu displayed by 'list-packages'.
 +
- +++
 +*** New command 'package-upgrade-all'.
 +This command allows upgrading all packages without any queries.
 +A package that comes with the Emacs distribution will only be upgraded
 +by this command after you install, once, a newer version of that
 +package from ELPA via the package-menu displayed by 'list-packages'.
 +
- +++
 +*** New commands 'package-recompile' and 'package-recompile-all'.
 +These commands can be useful if the ".elc" files are out of date
 +(invalid byte code and macros).
 +
- +++
 +*** New DWIM action on 'x' in "*Packages*" buffer.
 +If no packages are marked, 'x' will install the package under point if
 +it isn't already, and remove it if it is installed.  Customize the new
 +option 'package-menu-use-current-if-no-marks' to the nil value to get
 +back the old behavior of signaling an error in that case.
 +
- +++
 +*** New command 'package-vc-install'.
 +Packages can now be installed directly from source by cloning from
 +their repository.
 +
- +++
 +*** New command 'package-vc-install-from-checkout'.
 +An existing checkout can now be loaded via package.el, by creating a
 +symbolic link from the usual package directory to the checkout.
 +
- +++
 +*** New command 'package-vc-checkout'.
 +Used to fetch the source of a package by cloning a repository without
 +activating the package.
 +
- +++
 +*** New command 'package-vc-prepare-patch'.
 +This command allows you to send patches to package maintainers, for
 +packages checked out using 'package-vc-install'.
 +
- +++
 +*** New command 'package-report-bug'.
 +This command helps you compose an email for sending bug reports to
 +package maintainers, and is bound to 'b' in the "*Packages*" buffer.
 +
- ---
 +*** New user option 'package-vc-selected-packages'.
 +By customizing this user option you can specify specific packages to
 +install.
 +
- +++
 +*** New user option 'package-install-upgrade-built-in'.
 +When enabled, 'package-install' will include in the list of
 +upgradeable packages those built-in packages (like Eglot and
 +use-package, for example) for which a newer version is available in
 +package archives, and will allow installing those newer versions.  By
 +default, this is disabled; however, if 'package-install' is invoked
 +with a prefix argument, it will act as if this new option were
 +enabled.
 +
 +In addition, when this option is non-nil, built-in packages for which
 +a new version is available in archives can be upgraded via the package
 +menu produced by 'list-packages'.  If you do set this option non-nil,
 +we recommend not to use the 'U' command, but instead to use '/ u' to
 +show the packages which can be upgraded, and then decide which ones of
 +them you actually want to update from the archives.
 +
 +If you customize this option, we recommend you place its non-default
 +setting in your early-init file.
 +
 +** Emacs Sessions (Desktop)
 +
- +++
 +*** New user option to load a locked desktop if locking Emacs is not running.
 +The option 'desktop-load-locked-desktop' can now be set to the value
 +'check-pid', which means to allow loading a locked ".emacs.desktop"
 +file if the Emacs process which locked it is no longer running on the
 +local machine.  This allows avoiding questions about locked desktop
 +files when the Emacs session which locked it crashes, or was otherwise
 +interrupted and didn't exit gracefully.  See the "(emacs) Saving
 +Emacs Sessions" node in the Emacs manual for more details.
 +
 +** Miscellaneous
 +
- ---
 +*** New command 'scratch-buffer'.
 +This command switches to the "*scratch*" buffer.  If "*scratch*" doesn't
 +exist, the command creates it first.  You can use this command if you
 +inadvertently delete the "*scratch*" buffer.
 +
 +** Debugging
 +
- +++
 +*** 'q' in a "*Backtrace*" buffer no longer clears the buffer.
 +Instead it just buries the buffer and switches the mode from
 +'debugger-mode' to 'backtrace-mode', since commands like 'e' are no
 +longer available after exiting the recursive edit.
 +
- +++
 +*** New user option 'debug-allow-recursive-debug'.
 +This user option controls whether the 'e' (in a "*Backtrace*"
 +buffer or while edebugging) and 'C-x C-e' (while edebugging) commands
 +lead to a (further) backtrace.  By default, this variable is nil,
 +which is a change in behavior from previous Emacs versions.
 +
- +++
 +*** 'e' in edebug can now take a prefix arg to pretty-print the results.
 +When invoked with a prefix argument, as in 'C-u e', this command will
 +pop up a new buffer and show the full pretty-printed value there.
 +
- +++
 +*** 'C-x C-e' now interprets a non-zero prefix arg to pretty-print the results.
 +When invoked with a non-zero prefix argument, as in 'C-u C-x C-e',
 +this command will pop up a new buffer and show the full pretty-printed
 +value there.
 +
- +++
 +*** You can now generate a backtrace from Lisp errors in redisplay.
 +To do this, set the new variable 'backtrace-on-redisplay-error' to a
 +non-nil value.  The backtrace will be written to a special buffer
 +named "*Redisplay-trace*".  This buffer will not be automatically
 +displayed in a window.
 +
 +** Compile
 +
- +++
 +*** New user option 'compilation-hidden-output'.
 +This regular expression can be used to make specific parts of
 +compilation output invisible.
 +
- +++
 +*** The 'compilation-auto-jump-to-first-error' user option has been extended.
 +It can now have the additional values 'if-location-known' (which will
 +only jump if the location of the first error is known), and
 +'first-known' (which will jump to the first known error location).
 +
- +++
 +*** New user option 'compilation-max-output-line-length'.
 +Lines longer than the value of this option will have their ends
 +hidden, with a button to reveal the hidden text.  This speeds up
 +operations like grepping on files that have few newlines.  The default
 +value is 400; set to nil to disable hiding.
 +
 +** Flymake
 +
- +++
 +*** New user option 'flymake-mode-line-lighter'.
 +
- ---
 +** New minor mode 'word-wrap-whitespace-mode' for extending 'word-wrap'.
 +This mode switches 'word-wrap' on, and breaks on all the whitespace
 +characters instead of just 'SPC' and 'TAB'.
 +
- ---
 +** New mode, 'emacs-news-mode', for editing the NEWS file.
 +This mode adds some highlighting, makes the 'M-q' command aware of the
 +format of NEWS entries, and has special commands for doing maintenance
 +of the Emacs NEWS files.  In addition, this mode turns on
 +'outline-minor-mode', and thus displays customizable icons (see
 +'icon-preference') in the margins.  To disable these icons, set
 +'outline-minor-mode-use-buttons' to a nil value.
 +
- ---
 +** Kmacro
 +Kmacros are now OClosures and have a new constructor 'kmacro' which
 +uses the 'key-parse' syntax.  It replaces the old 'kmacro-lambda-form'
 +(which is now declared obsolete).
 +
- +++
 +** savehist.el can now truncate variables that are too long.
 +An element of user option 'savehist-additional-variables' can now be
 +of the form '(VARIABLE . MAX-ELTS)', which means to truncate the
 +VARIABLE's value to at most MAX-ELTS elements (if the value is a list)
 +before saving the value.
 +
 +** Minibuffer and Completions
 +
- +++
 +*** New commands for navigating completions from the minibuffer.
 +When the minibuffer is the current buffer, typing 'M-<up>' or
 +'M-<down>' selects a previous/next completion candidate from the
 +"*Completions*" buffer and inserts it to the minibuffer.
 +When the user option 'minibuffer-completion-auto-choose' is nil,
 +'M-<up>' and 'M-<down>' do the same, but without inserting
 +a completion candidate to the minibuffer, then 'M-RET' can be used
 +to choose the currently active candidate from the "*Completions*"
 +buffer and exit the minibuffer.  With a prefix argument, 'C-u M-RET'
 +inserts the currently active candidate to the minibuffer, but doesn't
 +exit the minibuffer.  These keys are also available for in-buffer
 +completion, but they don't insert candidates automatically, you need
 +to type 'M-RET' to insert the selected candidate to the buffer.
 +
- +++
 +*** Choosing a completion with a prefix argument doesn't exit the minibuffer.
 +This means that typing 'C-u RET' on a completion candidate in the
 +"*Completions*" buffer inserts the completion into the minibuffer,
 +but doesn't exit the minibuffer.
 +
- ---
 +*** The "*Completions*" buffer can now be automatically selected.
 +To enable this behavior, customize the user option
 +'completion-auto-select' to t, then pressing 'TAB' will switch to the
 +"*Completions*" buffer when it pops up that buffer.  If the value is
 +'second-tab', then the first 'TAB' will display "*Completions*", and
 +the second one will switch to the "*Completions*" buffer.
 +
- +++
 +*** New user option 'completion-auto-wrap'.
 +When non-nil, the commands 'next-completion' and 'previous-completion'
 +automatically wrap around on reaching the beginning or the end of
 +the "*Completions*" buffer.
 +
- ---
 +*** New values for the 'completion-auto-help' user option.
 +There are two new values to control the way the "*Completions*" buffer
 +behaves after pressing a 'TAB' if completion is not unique.  The value
 +'always' updates or shows the "*Completions*" buffer after any attempt
 +to complete.  The value 'visual' is like 'always', but only updates
 +the completions if they are already visible.  The default value t
 +always hides the completion buffer after some completion is made.
 +
- +++
 +*** New commands to complete the minibuffer history.
 +'minibuffer-complete-history' ('C-x <up>') is like 'minibuffer-complete'
 +but completes on the history items instead of the default completion
 +table.  'minibuffer-complete-defaults' ('C-x <down>') completes
 +on the list of default items.
 +
- +++
 +*** User option 'minibuffer-eldef-shorten-default' is now obsolete.
 +Customize the user option 'minibuffer-default-prompt-format' instead.
 +
- +++
 +*** New user option 'completions-sort'.
 +This option controls the sorting of the completion candidates in
 +the "*Completions*" buffer.  Available styles are no sorting,
 +alphabetical (the default), or a custom sort function.
 +
- +++
 +*** New user option 'completions-max-height'.
 +This option limits the height of the "*Completions*" buffer.
 +
- +++
 +*** New user option 'completions-header-format'.
 +This is a string to control the header line to show in the
 +"*Completions*" buffer before the list of completions.
 +If it contains "%s", that is replaced with the number of completions.
 +If nil, the header line is not shown.
 +
- +++
 +*** New user option 'completions-highlight-face'.
 +When this user option names a face, the current
 +candidate in the "*Completions*" buffer is highlighted with that face.
 +The nil value disables this highlighting.  The default is to highlight
 +using the 'completions-highlight' face.
 +
- +++
 +*** You can now define abbrevs for the minibuffer modes.
 +'minibuffer-mode-abbrev-table' and
 +'minibuffer-inactive-mode-abbrev-table' are now defined.
 +
 +** Isearch and Replace
 +
- +++
 +*** Changes in how Isearch responds to 'mouse-yank-at-point'.
 +If a user does 'C-s' and then uses '<mouse-2>' ('mouse-yank-primary')
 +outside the echo area, Emacs will, by default, end the Isearch and
 +yank the text at mouse cursor.  But if 'mouse-yank-at-point' is
 +non-nil, the text will now be added to the Isearch instead.
 +
- +++
 +*** Changes for values 'no' and 'no-ding' of 'isearch-wrap-pause'.
 +Now with these values the search will wrap around not only on repeating
 +with 'C-s C-s', but also after typing a character.
 +
- +++
 +*** New user option 'char-fold-override'.
 +Non-nil means that the default definitions of equivalent characters
 +are overridden.
 +
 +*** New command 'describe-char-fold-equivalences'.
 +It displays character equivalences used by 'char-fold-to-regexp'.
 +
- ---
 +*** New command 'isearch-emoji-by-name'.
 +It is bound to 'C-x 8 e RET' during an incremental search.  The
 +command accepts the Unicode name of an Emoji (for example, "smiling
 +face" or "heart with arrow"), like 'C-x 8 e e', with minibuffer
 +completion, and adds the Emoji into the search string.
 +
 +** GDB/MI
 +
- +++
 +*** New user option 'gdb-debuginfod-enable-setting'.
 +On capable platforms, GDB 10.1 and later can download missing source
 +and debug info files from special-purpose servers, called "debuginfod
 +servers".  Use this new option to control whether 'M-x gdb' instructs
 +GDB to download missing files from debuginfod servers when you debug
 +the corresponding programs.  The default is to ask you at the
 +beginning of each debugging session whether to download the files for
 +that session.
 +
 +** Glyphless Characters
 +
- ---
 +*** New minor mode 'glyphless-display-mode'.
 +This allows an easy way to toggle seeing all glyphless characters in
 +the current buffer.
 +
- +++
 +*** The extra slot of 'glyphless-char-display' can now have cons values.
 +The extra slot of the 'glyphless-char-display' char-table can now have
 +values that are cons cells, specifying separate values for text-mode
 +and GUI terminals.
 +
- +++
 +*** "Replacement character" feature for undisplayable characters on TTYs.
 +The 'acronym' method of displaying glyphless characters on text-mode
 +frames treats single-character acronyms specially: they are displayed
 +without the surrounding '[..]' "box", thus in effect treating such
 +"acronyms" as replacement characters.
 +
 +** Registers
 +
- +++
 +*** Buffer names can now be stored in registers.
 +For instance, to enable jumping to the "*Messages*" buffer with
 +'C-x r j m':
 +
 +    (set-register ?m '(buffer . "*Messages*"))
 +
 +** Pixel Fill
 +
- +++
 +*** This is a new package that deals with filling variable-pitch text.
 +
- +++
 +*** New function 'pixel-fill-region'.
 +This fills the region to be no wider than a specified pixel width.
 +
 +** Info
 +
- ---
 +*** Command 'info-apropos' now takes a prefix argument to search for regexps.
 +
- ---
 +*** New command 'Info-goto-node-web' and key binding 'G'.
 +This will take you to the "gnu.org" web server's version of the current
 +info node.  This command only works for the Emacs and Emacs Lisp manuals.
 +
 +** Shortdoc
 +
- ---
 +*** New command 'shortdoc-copy-function-as-kill' bound to 'w'.
 +It copies the name of the function near point into the kill ring.
 +
- ---
 +*** 'N' and 'P' are now bound to 'shortdoc-{next,previous}-section'.
 +This is in addition to the old keybindings 'C-c C-n' and 'C-c C-p'.
 +
 +** VC
 +
- +++
 +*** New command 'vc-pull-and-push'.
 +This commands first does a "pull" command, and if that is successful,
 +does a "push" command afterwards.  Currently supported in Git and Bzr.
 +
- +++
 +*** 'C-x v b' prefix key is used now for branch commands.
 +'vc-print-branch-log' is bound to 'C-x v b l', and new commands are
 +'vc-create-branch' ('C-x v b c') and 'vc-switch-branch' ('C-x v b s').
 +The VC Directory buffer now uses the prefix 'b' for these branch-related
 +commands.
 +
- +++
 +*** New command 'vc-dir-mark-by-regexp' bound to '% m' and '* %'.
 +This command marks files based on a regexp.  If given a prefix
 +argument, unmark instead.
 +
- ---
 +*** New command 'C-x v !' ('vc-edit-next-command').
 +This prefix command requests editing of the next VC shell command
 +before execution.  For example, in a Git repository, you can produce a
 +log of more than one branch by typing 'C-x v ! C-x v b l' and then
 +appending additional branch names to the 'git log' command.
 +
 +The intention is that this command can be used to access a wide
 +variety of version control system-specific functionality from VC
 +without complexifying either the VC command set or the backend API.
 +
- ---
 +*** 'C-x v v' in a diffs buffer allows to commit only some of the changes.
 +This command is intended to allow you to commit only some of the
 +changes you have in your working tree.  Begin by creating a buffer
 +with the changes against the last commit, e.g. with 'C-x v D'
 +('vc-root-diff').  Then edit the diffs to remove the hunks you don't
 +want to commit.  Finally, type 'C-x v v' in that diff buffer to commit
 +only part of your changes, those whose hunks were left in the buffer.
 +
- ---
 +*** 'C-x v v' on an unregistered file will now use the most specific backend.
 +Previously, if you had an SVN-covered "~/" directory, and a Git-covered
 +directory in "~/foo/bar", using 'C-x v v' on a new, unregistered file
 +"~/foo/bar/zot" would register it in the SVN repository in "~/" instead of
 +in the Git repository in "~/foo/bar".  This makes this command
 +consistent with 'vc-responsible-backend'.
 +
- ---
 +*** Log Edit now fontifies long Git commit summary lines.
 +Writing shorter summary lines avoids truncation in contexts in which
 +Git commands display summary lines.  See the two new user options
 +'vc-git-log-edit-summary-target-len' and 'vc-git-log-edit-summary-max-len'.
 +
- ---
 +*** New 'log-edit-headers-separator' face.
 +It is used to style the line that separates the 'log-edit' headers
 +from the 'log-edit' summary.
 +
- ---
 +*** The function 'vc-read-revision' accepts a new MULTIPLE argument.
 +If non-nil, multiple revisions can be queried.  This is done using
 +'completing-read-multiple'.
 +
- +++
 +*** New function 'vc-read-multiple-revisions'.
 +This function invokes 'vc-read-revision' with a non-nil value for
 +MULTIPLE.
 +
- ---
 +*** New command 'vc-prepare-patch'.
 +Patches for any version control system can be prepared using VC.  The
 +command will query what commits to send and will compose messages for
 +your mail user agent.  The behavior of 'vc-prepare-patch' can be
 +modified by the user options 'vc-prepare-patches-separately' and
 +'vc-default-patch-addressee'.
 +
 +** Message
 +
- ---
 +*** New user option 'mml-attach-file-at-the-end'.
 +If non-nil, 'C-c C-a' will put attached files at the end of the message.
 +
- +++
 +*** Message Mode now supports image yanking.
 +
- ---
 +*** New user option 'message-server-alist'.
 +This controls automatic insertion of the "X-Message-SMTP-Method"
 +header before sending a message.
 +
 +** HTML Mode
 +
- ---
 +*** HTML Mode now supports "text/html" and "image/*" yanking.
 +
 +** Texinfo Mode
 +
- +++
 +*** 'texinfo-mode' now has a specialized 'narrow-to-defun' definition.
 +It narrows to the current node.
 +
 +** EUDC
 +
- +++
 +*** Deprecations planned for next release.
 +After Emacs 29.1, some aspects of EUDC will be deprecated.  The goal
 +of these deprecations is to simplify EUDC server configuration by
 +making 'eudc-server-hotlist' the only place to add servers.  There
 +will not be a need to set the server using the 'eudc-set-server'
 +command.  Instead, the 'eudc-server-hotlist' user option should be
 +customized to have an entry for the server.  The plan is to obsolete
 +the 'eudc-hotlist' package since Customize is sufficient for changing
 +'eudc-server-hotlist'.  How the 'eudc-server' user option works in this
 +context is to-be-determined; it can't be removed, because that would
 +break compatibility, but it may become synchronized with
 +'eudc-server-hotlist' so that 'eudc-server' is always equal to '(car
 +eudc-server-hotlist)'.  The first entry in 'eudc-server-hotlist' is the
 +first server tried by 'eudc-expand-try-all'.  The hotlist
 +simplification will allow 'eudc-query-form' to show a drop down of
 +possible servers, instead of requiring a call to 'eudc-set-server'
 +like it does in this release.  The default value of
 +'eudc-ignore-options-file' will be changed from nil to t.
 +
- +++
 +*** New user option 'eudc-ignore-options-file' that defaults to nil.
 +The 'eudc-ignore-options-file' user option can be configured to ignore
 +the 'eudc-options-file' (typically "~/.emacs.d/eudc-options").  Most
 +users should configure this to t and put EUDC configuration in the
 +main Emacs initialization file ("~/.emacs" or "~/.emacs.d/init.el").
 +
- +++
 +*** 'eudc-expansion-overwrites-query' to 'eudc-expansion-save-query-as-kill'.
 +The user option 'eudc-expansion-overwrites-query' is renamed to
 +'eudc-expansion-save-query-as-kill' to reflect the actual behavior of
 +the user option.  The former is kept as alias.
 +
- +++
 +*** New command 'eudc-expand-try-all'.
 +This command can be used in place of 'eudc-expand-inline'.  It takes a
 +prefix argument that causes 'eudc-expand-try-all' to return matches
 +from all servers instead of just the matches from the first server to
 +return any.  This is useful for example, if one wants to search LDAP
 +for a name that happens to match a contact in one's BBDB.
 +
- +++
 +*** New behavior and default for user option 'eudc-inline-expansion-format'.
 +EUDC inline expansion result formatting defaulted to
 +
 +    ("%s %s <%s>" firstname name email)
 +
 +Since email address specifications need to comply with RFC 5322 in
 +order to be useful in messages, there was a risk of producing syntax
 +which was standard with RFC 822, but is marked as obsolete syntax by
 +its successor RFC 5322.  Also, the first and last name part was never
 +enclosed in double quotes, potentially producing invalid address
 +specifications, which may be rejected by a receiving MTA.  Thus, this
 +variable can now additionally be set to nil (the new default), or a
 +function.  In both cases, the formatted result will be in compliance
 +with RFC 5322.  When set to nil, a default format very similar to the
 +old default will be produced.  When set to a function, that function
 +is called, and the returned values are used to populate the phrase and
 +comment parts (see RFC 5322 for definitions).  In both cases, the
 +phrase part will be automatically quoted if necessary.
 +
- +++
 +*** New function 'eudc-capf-complete' with 'message-mode' integration.
 +EUDC can now contribute email addresses to 'completion-at-point' by
 +adding the new function 'eudc-capf-complete' to
 +'completion-at-point-functions' in 'message-mode'.
 +
- +++
 +*** Additional attributes of query and results in eudcb-macos-contacts.el.
 +The EUDC back-end for the macOS Contacts app now provides a wider set
 +of attributes to use for queries, and delivers more attributes in
 +query results.
 +
- +++
 +*** New back-end for ecomplete.
 +A new back-end for ecomplete allows information from that database to
 +be queried by EUDC, too.  The attributes present in the EUDC query are
 +used to select the entry type in the ecomplete database.
 +
- +++
 +*** New back-end for mailabbrev.
 +A new back-end for mailabbrev allows information from that database to
 +be queried by EUDC, too.  Only the attributes 'email', 'name', and
 +'firstname' are supported.
 +
 +** EWW/SHR
 +
- +++
 +*** New user option to automatically rename EWW buffers.
 +The 'eww-auto-rename-buffer' user option can be configured to rename
 +rendered web pages by using their title, URL, or a user-defined
 +function which returns a string.  For the first two cases, the length
 +of the resulting name is controlled by the user option
 +'eww-buffer-name-length'.  By default, no automatic renaming is
 +performed.
 +
- +++
 +*** New user option 'shr-allowed-images'.
 +This complements 'shr-blocked-images', but allows specifying just the
 +allowed images.
 +
- +++
 +*** New user option 'shr-use-xwidgets-for-media'.
 +If non-nil (and Emacs has been built with support for xwidgets),
 +display <video> elements with an xwidget.  Note that this is
 +experimental; it is known to crash Emacs on some systems, and just
 +doesn't work on other systems.  Also see etc/PROBLEMS.
 +
- ---
 +*** New user option 'eww-url-transformers'.
 +These are used to alter an URL before using it.  By default it removes
 +the common "utm_" trackers from URLs.
 +
 +** Find Dired
 +
- +++
 +*** New command 'find-dired-with-command'.
 +This enables users to run 'find-dired' with an arbitrary command,
 +enabling running commands previously unsupported and also enabling new
 +commands to be built on top.
 +
 +** Gnus
 +
- ---
 +*** Tool bar changes in Gnus/Message.
 +There were previously two styles of tool bars available in Gnus and
 +Message, referred to as 'gnus-summary-tool-bar-retro',
 +'gnus-group-tool-bar-retro' and 'message-tool-bar-retro', and
 +'gnus-summary-tool-bar-gnome', 'gnus-group-tool-bar-gnome' and
 +'message-tool-bar-gnome'.  The "retro" tool bars have been removed (as
 +well as the icons used), and the "gnome" tool bars are now the only
 +pre-defined toolbars.
 +
- ---
 +*** 'gnus-summary-up-thread' and 'gnus-summary-down-thread' bindings removed.
 +The 'gnus-summary-down-thread' binding to 'M-C-d' was shadowed by
 +'gnus-summary-read-document', and these commands are also available on
 +'T u' and 'T d' respectively.
 +
- ---
 +*** Gnus now uses a variable-pitch font in the headers by default.
 +To get the monospace font back, you can put something like the
 +following in your ".gnus" file:
 +
 +    (set-face-attribute 'gnus-header nil :inherit 'unspecified)
 +
- ---
 +*** The default value of 'gnus-treat-fold-headers' is now 'head'.
 +
- +++
 +*** New face 'gnus-header'.
 +All other 'gnus-header-*' faces inherit from this face now.
 +
- +++
 +*** New user option 'gnus-treat-emojize-symbols'.
 +If non-nil, symbols that have an Emoji representation will be
 +displayed as emojis.  The default is nil.
 +
- +++
 +*** New command 'gnus-article-emojize-symbols'.
 +This is bound to 'W D e' and will display symbols that have Emoji
 +representation as Emoji.
 +
- ---
 +*** New mu backend for gnus-search.
 +Configuration is very similar to the notmuch and namazu backends.  It
 +supports the unified search syntax.
 +
- ---
 +*** 'gnus-html-image-cache-ttl' is now a seconds count.
 +Formerly it was a pair of numbers '(A B)' that represented 65536*A + B,
 +to cater to older Emacs implementations that lacked bignums.
 +The older form still works but is undocumented.
 +
 +** Rmail
 +
- ---
 +*** Rmail partial summaries can now be applied one on top of the other.
 +You can now narrow the set of messages selected by Rmail summary's
 +criteria (recipients, topic, senders, etc.) by making a summary of the
 +already summarized messages.  For example, invoking
 +'rmail-summary-by-senders', followed by 'rmail-summary-by-topic' will
 +produce a summary where both the senders and the topic are according
 +to your selection.  The new user option
 +'rmail-summary-progressively-narrow' controls whether the stacking of
 +the filters is in effect; customize it to a non-nil value to enable
 +this feature.
 +
- +++
 +*** New Rmail summary: by thread.
 +The new command 'rmail-summary-by-thread' produces a summary of
 +messages that belong to a single thread of discussion.
 +
 +** EIEIO
 +
- ---
 +*** 'slot-value' can now be used to access slots of 'cl-defstruct' objects.
 +
 +** Align
 +
- ---
 +*** Alignment in 'text-mode' has changed.
 +Previously, 'M-x align' didn't do anything, and you had to say 'C-u
 +M-x align' for it to work.  This has now been changed.  The default
 +regexp for 'C-u M-x align-regexp' has also been changed to be easier
 +for inexperienced users to use.
 +
 +** Help
 +
- ---
 +*** New mode, 'emacs-news-view-mode', for viewing the NEWS file.
 +This mode is used by the 'C-h N' command, and adds buttons to manual
 +entries and symbol references.
 +
- ---
 +*** New user option 'help-link-key-to-documentation'.
 +When this option is non-nil (which is the default), key bindings
 +displayed in the "*Help*" buffer will be linked to the documentation
 +for the command they are bound to.  This does not affect listings of
 +key bindings and functions (such as 'C-h b').
 +
 +** Info Look
 +
- ---
 +*** info-look specs can now be expanded at run time instead of a load time.
 +The new ':doc-spec-function' element can be used to compute the
 +':doc-spec' element when the user asks for info on that particular
 +mode (instead of at load time).
 +
 +** Ansi Color
 +
- ---
 +*** Support for ANSI 256-color and 24-bit colors.
 +256-color and 24-bit color codes are now handled by ANSI color
 +filters and displayed with the specified color.
 +
 +** Term Mode
 +
- ---
 +*** New user option 'term-bind-function-keys'.
 +If non-nil, 'term-mode' will pass the function keys on to the
 +underlying shell instead of using the normal Emacs bindings.
 +
- +++
 +*** Support for ANSI 256-color and 24-bit colors, italic and other fonts.
 +'term-mode' can now display 256-color and 24-bit color codes.  It can
 +also handle ANSI codes for faint, italic and blinking text, displaying
 +it with new 'term-{faint,italic,slow-blink,fast-blink}' faces.
 +
 +** Project
 +
- +++
 +*** 'project-find-file' and 'project-or-external-find-file' can include all.
 +The commands 'project-find-file' and 'project-or-external-find-file'
 +now accept a prefix argument, which is interpreted to mean "include
 +all files".
 +
- +++
 +*** New command 'project-list-buffers' bound to 'C-x p C-b'.
 +This command displays a list of buffers from the current project.
 +
- +++
 +*** 'project-kill-buffers' can display the list of buffers to kill.
 +Customize the user option 'project-kill-buffers-display-buffer-list'
 +to enable the display of the buffer list.
 +
 +*** New user option 'project-vc-extra-root-markers'.
 +Use it to add detection of nested projects (inside a VCS repository),
 +or projects outside of VCS repositories.
 +
 +As a consequence, the 'VC project backend' is formally renamed to
 +'VC-aware project backend'.
 +
- +++
 +*** New user option 'project-vc-include-untracked'.
 +If non-nil, files untracked by a VCS are considered to be part of
 +the project by a VC project based on that VCS.
 +
 +** Xref
 +
- +++
 +*** New command 'xref-go-forward'.
 +It is bound to 'C-M-,' and jumps to the location where you previously
 +invoked 'xref-go-back' ('M-,', also known as 'xref-pop-marker-stack').
 +
- +++
 +*** The depth of the Xref marker stack is now infinite.
 +The implementation of the Xref marker stack was changed in a way that
 +allows as many places to be saved on the stack as needed, limited only
 +by the available memory.  Therefore, the variables
 +'find-tag-marker-ring-length' and 'xref-marker-ring-length' are now
 +obsolete and unused; setting them has no effect.
 +
- +++
 +*** 'xref-query-replace-in-results' prompting change.
 +This command no longer prompts for FROM when called without prefix
 +argument.  This makes the most common case faster: replacing entire
 +matches.
 +
- ---
 +*** New command 'xref-find-references-and-replace' to rename one identifier.
 +
- ---
 +*** New variable 'xref-current-item' (renamed from a private version).
 +
- +++
 +*** New function 'xref-show-xrefs'.
 +
 +*** 'outline-minor-mode' is supported in Xref buffers.
 +You can enable outlining by adding 'outline-minor-mode' to
 +'xref-after-update-hook'.
 +
 +** File Notifications
 +
- ---
 +*** The new command 'file-notify-rm-all-watches' removes all file notifications.
 +
 +** Sql
 +
- +++
 +*** Sql now supports sending of passwords in-process.
 +To improve security, if an sql product has ':password-in-comint' set
 +to t, a password supplied via the minibuffer will be sent in-process,
 +as opposed to via the command-line.
 +
 +** Image Mode
 +
- ---
 +*** New command 'image-transform-fit-to-window'.
 +This command fits the image to the current window by scaling down or
 +up as necessary.  Unlike 'image-transform-fit-both', this can scale
 +the image up as well as down.  It is bound to 's w' in Image Mode by
 +default.
 +
- +++
 +*** New command 'image-mode-wallpaper-set'.
 +This command sets the desktop background to the current image.  It is
 +bound to 'W' in Image Mode by default.
 +
- ---
 +*** 'image-transform-fit-to-{height,width}' are now obsolete.
 +Use the new command 'image-transform-fit-to-window' instead.
 +The keybinding for 'image-transform-fit-to-width' is now 's i'.
 +
- ---
 +*** User option 'image-auto-resize' can now be set to 'fit-window'.
 +This works like 'image-transform-fit-to-window'.
 +
- ---
 +*** New user option 'image-auto-resize-max-scale-percent'.
 +The new 'fit-window' option will never scale an image more than this
 +much (in percent).  It is nil by default, which means no limit.
 +
- +++
 +*** New user option 'image-text-based-formats'.
 +This controls whether or not to show a message, when opening certain
 +image formats, explaining how to edit it as text.  The default is to
 +show this message for SVG and XPM.
 +
- +++
 +*** New command 'image-transform-set-percent'.
 +It allows resizing the image to a percentage of its original size, and
 +is bound to 's p' in Image mode.
 +
- +++
 +*** 'image-transform-original' renamed to 'image-transform-reset-to-original'.
 +The old name was confusing, and is now an obsolete function alias.
 +
- +++
 +*** 'image-transform-reset' renamed to 'image-transform-reset-to-initial'.
 +The old name was confusing, and is now an obsolete function alias.
 +
 +** Images
 +
- +++
 +*** New commands 'image-crop' and 'image-cut'.
 +These commands allow interactively cropping/cutting the image at
 +point.  The commands are bound to keys 'i c' and 'i x' (respectively)
 +in the local keymap over images.  They rely on external programs, by
 +default "convert" from ImageMagick, to do the actual cropping/eliding
 +of the image file.
 +
- +++
 +*** New commands 'image-flip-horizontally' and 'image-flip-vertically'.
 +These commands horizontally and vertically flip the image under point,
 +and are bound to 'i h' and 'i v', respectively.
 +
- +++
 +*** Users can now add special image conversion functions.
 +This is done via 'image-converter-add-handler'.
 +
 +** Image Dired
 +
- ---
 +*** 'image-dired-image-mode' is now based on 'image-mode'.
 +This avoids converting images in the background, and makes Image-Dired
 +noticeably faster.  New keybindings from 'image-mode' are now
 +available in the "*image-dired-display-image*" buffer; press '?' or
 +'h' in that buffer to see the full list.
 +
- ---
 +*** Navigation and marking commands now work in image display buffer.
 +The following new bindings have been added:
 +- 'n', 'SPC' => 'image-dired-display-next'
 +- 'p', 'DEL' => 'image-dired-display-previous'
 +- 'm'        => 'image-dired-mark-thumb-original-file'
 +- 'd'        => 'image-dired-flag-thumb-original-file'
 +- 'u'        => 'image-dired-unmark-thumb-original-file'
 +
- ---
 +*** New command 'image-dired-unmark-all-marks'.
 +It removes all marks from all files in the thumbnail and the
 +associated Dired buffer, and is bound to 'U' in the thumbnail and
 +display buffer.
 +
- ---
 +*** New command 'image-dired-do-flagged-delete'.
 +It deletes all flagged files, and is bound to 'x' in the thumbnail
 +buffer.  It replaces the command 'image-dired-delete-marked', which is
 +now an obsolete alias.
 +
- ---
 +*** New command 'image-dired-copy-filename-as-kill'.
 +It copies the name of the marked or current image to the kill ring,
 +and is bound to 'w' in the thumbnail buffer.
 +
- ---
 +*** New command 'image-dired-wallpaper-set'.
 +This command sets the desktop background to the image at point in the
 +thumbnail buffer.  It is bound to 'W' by default.
 +
- ---
 +*** 'image-dired-slideshow-start' is now bound to 'S'.
 +It is bound in both the thumbnail and display buffer, and no longer
 +prompts for a timeout; use a numerical prefix (e.g. 'C-u 8 S') to set
 +the timeout.
 +
- ---
 +*** New user option 'image-dired-marking-shows-next'.
 +If this option is non-nil (the default), marking, unmarking or
 +flagging an image in either the thumbnail or display buffer shows the
 +next image.
 +
- ---
 +*** New face 'image-dired-thumb-flagged'.
 +If 'image-dired-thumb-mark' is non-nil (the default), this face is
 +used for images that are flagged for deletion in the Dired buffer
 +associated with Image-Dired.
 +
- ---
 +*** Image information is now shown in the header line of the thumbnail buffer.
 +This replaces the message that most navigation commands in the
 +thumbnail buffer used to show at the bottom of the screen.
 +
- ---
 +*** New specifiers for 'image-dired-display-properties-format'.
 +This is used to format the new header line.  The new specifiers are:
 +"%d" for the name of the directory that the file is in, "%n" for
 +file's number in the thumbnail buffer, and "%s" for the file size.
 +
 +The default format has been updated to use this.  If you prefer the
 +old format, add this to your Init file:
 +
 +    (setopt image-dired-display-properties-format "%b: %f (%t): %c")
 +
- ---
 +*** New faces for the header line of the thumbnail buffer.
 +These faces correspond to different parts of the header line, as
 +specified in 'image-dired-display-properties-format':
 +- 'image-dired-thumb-header-directory-name'
 +- 'image-dired-thumb-header-file-name'
 +- 'image-dired-thumb-header-file-size'
 +- 'image-dired-thumb-header-image-count'
 +
- ---
 +*** PDF support.
 +Image-Dired now displays thumbnails for PDF files.  Type 'RET' on a
 +PDF file in the thumbnail buffer to visit the corresponding PDF.
 +
- ---
 +*** Support GraphicsMagick command line tools.
 +Support for the GraphicsMagick command line tool ("gm") has been
 +added, and is used when it is available instead of ImageMagick.
 +
- ---
 +*** Support Thumbnail Managing Standard v0.9.0 (Dec 2020).
 +This standard allows sharing generated thumbnails across different
 +programs.  Version 0.9.0 adds two larger thumbnail sizes: 512x512 and
 +1024x1024 pixels.  See the user option 'image-dired-thumbnail-storage'
 +to use it; it is not enabled by default.
 +
- ---
 +*** Reduce dependency on external "exiftool" program.
 +The 'image-dired-copy-with-exif-file-name' command no longer requires
 +an external "exiftool" program to be available.  The user options
 +'image-dired-cmd-read-exif-data-program' and
 +'image-dired-cmd-read-exif-data-options' are now obsolete.
 +
- ---
 +*** Support for bookmark.el.
 +The command 'bookmark-set' (bound to 'C-x r m') is now supported in
 +the thumbnail view, and will create a bookmark that opens the current
 +directory in Image-Dired.
 +
- +++
 +*** The 'image-dired-slideshow-start' command no longer prompts.
 +It no longer inconveniently prompts for a number of images and a
 +delay: it runs indefinitely, but stops automatically on any command.
 +You can set the delay with a prefix argument, or a negative prefix
 +argument to prompt for a delay.  Customize the user option
 +'image-dired-slideshow-delay' to change the default from 5 seconds.
 +
- ---
 +*** 'image-dired-show-all-from-dir-max-files' increased to 1000.
 +This user option controls asking for confirmation when starting
 +Image-Dired in a directory with many files.  Since Image-Dired creates
 +thumbnails in the background in recent versions, this is not as
 +important as it used to be.  You can now also customize this option to
 +nil to disable this confirmation completely.
 +
- +++
 +*** 'image-dired-thumb-size' increased to 128.
 +
- ---
 +*** 'image-dired-db-file' renamed to 'image-dired-tags-db-file'.
 +
- +++
 +*** 'image-dired-display-image-mode' renamed to 'image-dired-image-mode'.
 +The corresponding keymap is now named 'image-dired-image-mode-map'.
 +
- ---
 +*** Some commands have been renamed to be shorter.
 +- 'image-dired-display-thumbnail-original-image' has been renamed to
 +  'image-dired-display-this'.
 +- 'image-dired-display-next-thumbnail-original' has been renamed to
 +  'image-dired-display-next'.
 +- 'image-dired-display-previous-thumbnail-original' has been renamed
 +  to 'image-dired-display-previous'.
 +The old names are now obsolete aliases.
 +
- ---
 +*** 'image-dired-thumb-{height,width}' are now obsolete.
 +Customize 'image-dired-thumb-size' instead, which will set both the
 +height and width.
 +
- ---
 +*** HTML image gallery generation is now obsolete.
 +The 'image-dired-gallery-generate' command and these user options are
 +now obsolete: 'image-dired-gallery-thumb-image-root-url',
 +'image-dired-gallery-hidden-tags', 'image-dired-gallery-dir',
 +'image-dired-gallery-image-root-url'.
 +
- +++
 +*** 'image-dired-rotate-thumbnail-{left,right}' are now obsolete.
 +Instead, use commands 'image-dired-refresh-thumb' to generate a new
 +thumbnail, or 'image-rotate' to rotate the thumbnail without updating
 +the thumbnail file.
 +
- ---
 +*** Some commands and user options are now obsolete.
 +Since 'image-dired-display-image-mode' is now based on 'image-mode',
 +some commands and user options are no longer needed and are now obsolete:
 +'image-dired-cmd-create-temp-image-options',
 +'image-dired-cmd-create-temp-image-program',
 +'image-dired-display-current-image-full',
 +'image-dired-display-current-image-sized',
 +'image-dired-display-window-height-correction',
 +'image-dired-display-window-width-correction',
 +'image-dired-temp-image-file'.
 +
 +** Exif
 +
- ---
 +*** New function 'exif-field'.
 +This is a convenience function to extract the field data from
 +'exif-parse-file' and 'exif-parse-buffer'.
 +
 +** Bookmarks
 +
- +++
 +*** 'list-bookmarks' now includes a type column.
 +Types are registered via a 'bookmark-handler-type' symbol property on
 +the jumping function.
 +
- ---
 +*** 'bookmark-sort-flag' can now be set to 'last-modified'.
 +This will display bookmark list from most recently set to least
 +recently set.
 +
- ---
 +*** When editing a bookmark annotation, 'C-c C-k' will now cancel.
 +It is bound to the new command 'bookmark-edit-annotation-cancel'.
 +
- ---
 +*** New user option 'bookmark-fringe-mark'.
 +This option controls the bitmap used to indicate bookmarks in the
 +fringe (or nil to disable showing this marker).
 +
 +** Xwidget
 +
- ---
 +*** New user option 'xwidget-webkit-buffer-name-format'.
 +This option controls how xwidget-webkit buffers are named.
 +
- +++
 +*** New user option 'xwidget-webkit-cookie-file'.
 +This option controls whether the xwidget-webkit buffers save cookies
 +set by web pages, and if so, in which file to save them.
 +
- +++
 +*** New minor mode 'xwidget-webkit-edit-mode'.
 +When this mode is enabled, self-inserting characters and other common
 +web browser shortcut keys are redefined to send themselves to the
 +WebKit widget.
 +
- +++
 +*** New minor mode 'xwidget-webkit-isearch-mode'.
 +This mode acts similarly to incremental search, and allows searching
 +the contents of a WebKit widget.  In xwidget-webkit mode, it is bound
 +to 'C-s' and 'C-r'.
 +
- ---
 +*** New command 'xwidget-webkit-browse-history'.
 +This command displays a buffer containing the page load history of
 +the current WebKit widget, and allows you to navigate it.
 +
- ---
 +*** On X, the WebKit inspector is now available inside xwidgets.
 +To access the inspector, right click on the widget and select "Inspect
 +Element".
 +
- +++
 +*** "Open in New Window" in a WebKit widget's context menu now works.
 +The newly created buffer will be displayed via 'display-buffer', which
 +can be customized through the usual mechanism of 'display-buffer-alist'
 +and friends.
 +
 +** Tramp
 +
- ---
 +*** New connection methods "docker", "podman" and "kubernetes".
 +They allow accessing containers provided by Docker and similar
 +programs.
 +
- +++
 +*** Tramp supports abbreviating remote home directories now.
 +When calling 'abbreviate-file-name' on a Tramp file name, the result
 +will abbreviate the user's home directory, for example by abbreviating
 +"/ssh:user@host:/home/user" to "/ssh:user@host:~".
 +
- +++
 +*** New user option 'tramp-use-scp-direct-remote-copying'.
 +When set to non-nil, Tramp does not copy files between two remote
 +hosts via a local copy in its temporary directory, but lets the 'scp'
 +command do this job.
 +
- +++
 +*** Proper password prompts for methods "doas", "sudo" and "sudoedit".
 +The password prompts for these methods reflect now the credentials of
 +the user requesting such a connection, and not of the user who is the
 +target.  This has always been needed, just the password prompt and the
 +related 'auth-sources' entry were wrong.
 +
- ---
 +*** New user option 'tramp-completion-use-cache'.
 +During user and host name completion in the minibuffer, results from
 +Tramp's connection cache are taken into account.  This can be disabled
 +by setting the user option 'tramp-completion-use-cache' to nil.
 +
 +** Browse URL
 +
- ---
 +*** New user option 'browse-url-default-scheme'.
 +This user option decides which URL scheme that 'browse-url' and
 +related functions will use by default.  For example, you could
 +customize this to "https" to always prefer HTTPS URLs.
 +
- ---
 +*** New user option 'browse-url-irc-function'.
 +This option specifies a function for opening "irc://" links.  It
 +defaults to the new function 'browse-url-irc'.
 +
- ---
 +*** New function 'browse-url-irc'.
 +This multipurpose autoloaded function can be used for opening "irc://"
 +and "ircs://" URLS by any caller that passes a URL string as an initial
 +arg.
 +
- ---
 +*** Support for the Netscape web browser has been removed.
 +This support has been obsolete since Emacs 25.1.  The final version of
 +the Netscape web browser was released in February, 2008.
 +
- ---
 +*** Support for the Galeon web browser has been removed.
 +This support has been obsolete since Emacs 25.1.  The final version of
 +the Galeon web browser was released in September, 2008.
 +
- +++
 +*** Support for the Mozilla web browser is now obsolete.
 +Note that this historical web browser is different from Mozilla
 +Firefox; it is its predecessor.
 +
 +** Python Mode
 +
- ---
 +*** Project shells and a new user option 'python-shell-dedicated'.
 +When called with a prefix argument, 'run-python' now offers the choice
 +of creating a shell dedicated to the current project.  This shell runs
 +in the project root directory and is shared among all project buffers.
 +
 +Without a prefix argument, the kind of shell (buffer-dedicated,
 +project-dedicated or global) is specified by the new
 +'python-shell-dedicated' user option.
 +
 +** Ruby Mode
 +
- ---
 +*** New user option 'ruby-toggle-block-space-before-parameters'.
 +
- ---
 +*** Support for endless methods.
 +
- +++
 +*** New user options that determine indentation logic.
 +'ruby-method-params-indent', 'ruby-block-indent',
 +'ruby-after-operator-indent', 'ruby-method-call-indent',
 +'ruby-parenless-call-arguments-indent'.  See the docstrings for
 +explanations and examples.
 +
 +** Eshell
 +
- +++
 +*** New feature to easily bypass Eshell's own pipelining.
 +Prefixing '|', '<' or '>' with an asterisk, i.e. '*|', '*<' or '*>',
 +will cause the whole command to be passed to the operating system
 +shell.  This is particularly useful to bypass Eshell's own pipelining
 +support for pipelines which will move a lot of data.  See section
 +"Running Shell Pipelines Natively" in the Eshell manual, node
 +"(eshell) Pipelines".
 +
- +++
 +*** New module to help supplying absolute file names to remote commands.
 +After enabling the new 'eshell-elecslash' module, typing a forward
 +slash as the first character of a command line argument will
 +automatically insert the Tramp prefix.  The automatic insertion
 +applies only when 'default-directory' is remote and the command is a
 +Lisp function.  This frees you from having to keep track of whether
 +commands are Lisp function or external when supplying absolute file
 +name arguments.  See the "(eshell) Electric forward slash" node in the
 +Eshell manual for details.
 +
- +++
 +*** Improved support for redirection operators in Eshell.
 +Eshell now supports a wider variety of redirection operators.  For
 +example, you can now redirect both stdout and stderr via '&>' or
 +duplicate one output handle to another via 'NEW-FD>&OLD-FD'.  For more
 +information, see the "(eshell) Redirection" node in the Eshell manual.
 +
- +++
 +*** New eshell built-in command 'doas'.
 +The privilege-escalation program 'doas' has been added to the existing
 +'su' and 'sudo' commands from the 'eshell-tramp' module.  The external
 +command may still be accessed by using '*doas'.
 +
- +++
 +*** Double-quoting an Eshell expansion now treats the result as a single string.
 +If an Eshell expansion like '$FOO' is surrounded by double quotes, the
 +result will always be a single string, no matter the type that would
 +otherwise be returned.
 +
- +++
 +*** Concatenating Eshell expansions now works more similarly to other shells.
 +When concatenating an Eshell expansion that returns a list, "adjacent"
 +elements of each operand are now concatenated together,
 +e.g. '$(list "a" "b")c' returns '("a" "bc")'.  See the "(eshell)
 +Expansion" node in the Eshell manual for more details.
 +
- ---
 +*** Eshell subcommands with multiline numeric output return lists of numbers.
 +If every line of the output of an Eshell subcommand like '${COMMAND}'
 +is numeric, the result will be a list of numbers (or a single number
 +if only one line of output).  Previously, this only converted numbers
 +when there was a single line of output.
 +
- ---
 +*** Built-in Eshell commands now follow Posix/GNU argument syntax conventions.
 +Built-in commands in Eshell now accept command-line options with
 +values passed as a single token, such as '-oVALUE' or
 +'--option=VALUE'.  New commands can take advantage of this with the
 +'eshell-eval-using-options' macro.  See "Defining new built-in
 +commands" in the "(eshell) Built-ins" node of the Eshell manual.
 +
- +++
 +*** Eshell globs ending with "/" now match only directories.
 +Additionally, globs ending with "**/" or "***/" no longer raise an
 +error, and now expand to all directories recursively (following
 +symlinks in the latter case).
 +
- ---
 +*** Lisp forms in Eshell now treat a nil result as a failed exit status.
 +When executing a command that looks like '(lisp form)' and returns
 +nil, Eshell will set the exit status (available in the '$?'
 +variable) to 2.  This allows commands like that to be used in
 +conditionals.  To change this behavior, customize the new
 +'eshell-lisp-form-nil-is-failure' user option.
 +
 +** Shell
 +
- ---
 +*** New user option 'shell-kill-buffer-on-exit'.
 +Enabling this will automatically kill a "*shell*" buffer as soon as
 +the shell session terminates.
 +
- +++
 +*** New minor mode 'shell-highlight-undef-mode'.
 +Customize 'shell-highlight-undef-enable' to t if you want to enable
 +this minor mode in "*shell*" buffers.  It will highlight undefined
 +commands with a warning face as you type.
 +
 +** Calc
 +
- +++
 +*** New user option 'calc-kill-line-numbering'.
 +Set it to nil to exclude line numbering from kills and copies.
 +
 +** Hierarchy
 +
- ---
 +*** Tree Display can delay computation of children.
 +'hierarchy-add-tree' and 'hierarchy-add-trees' have an optional
 +argument which allows tree-widget display to be activated and computed
 +only when the user expands the node.
 +
 +** Proced
 +
- ---
 +*** proced.el shows system processes of remote hosts.
 +When 'default-directory' is remote, and 'proced' is invoked with a
 +negative argument like 'C-u - proced', the system processes of that
 +remote host are shown.  Alternatively, the user option
 +'proced-show-remote-processes' can be set to non-nil.
 +'proced-signal-function' has been marked obsolete.
 +
- ---
 +*** Proced can now optionally show process details in color.
 +New user option 'proced-enable-color-flag' enables coloring of Proced
 +buffers.  This option is disabled by default; customize it to a
 +non-nil value to enable colors.
 +
 +** Miscellaneous
 +
- +++
 +*** New user option 'webjump-use-internal-browser'.
 +When non-nil, WebJump will use an internal browser to open web pages,
 +instead of the default external browser.
 +
- ---
 +*** New user option 'font-lock-ignore'.
 +This option provides a mechanism to selectively disable font-lock
 +keyword-driven fontifications.
 +
- ---
 +*** New user option 'auto-save-visited-predicate'.
 +This user option is a predicate function which is called by
 +'auto-save-visited-mode' to decide whether or not to save a buffer.
 +You can use it to automatically save only specific buffers, for
 +example buffers using a particular mode or in some directory.
 +
- +++
 +*** New user option 'remote-file-name-inhibit-auto-save-visited'.
 +If this user option is non-nil, 'auto-save-visited-mode' will not
 +auto-save remote buffers.  The default is nil.
 +
- ---
 +*** New package vtable.el for formatting tabular data.
 +This package allows formatting data using variable-pitch fonts.
 +The resulting tables can display text in variable pitch fonts, text
 +using fonts of different sizes, and images.  See the "(vtable) Top"
 +manual for more details.
 +
- ---
 +*** New minor mode 'elide-head-mode'.
 +Enabling this minor mode turns on hiding header material, like
 +'elide-head' does; disabling it shows the header.  The commands
 +'elide-head' and 'elide-head-show' are now obsolete.
 +
 +*** New package ansi-osc.el.
 +Support for OSC ("Operating System Command") escape sequences has been
 +extracted from comint.el in order to provide interpretation of OSC
 +sequences in compilation buffers.
 +
 +Adding the new function 'ansi-osc-compilation-filter' to
 +'compilation-filter-hook' enables interpretation of OSC escape
 +sequences in compilation buffers.  By default, all sequences are
 +filtered out.
 +
 +The list of handlers (already covering OSC 7 and 8) has been extended
 +with a handler for OSC 2, the command to set a window title.
 +
- ---
 +*** 'recentf-mode' now uses abbreviated file names by default.
 +This means that e.g. "/home/foo/bar" is now displayed as "~/bar".
 +Customize the user option 'recentf-filename-handlers' to nil to get
 +back the old behavior.
 +
- ---
 +*** New command 'recentf-open'.
 +This command prompts for a recently opened file in the minibuffer, and
 +visits it.
 +
- ---
 +*** 'ffap-machine-at-point' no longer pings hosts by default.
 +It will now simply look at a hostname to determine if it is valid,
 +instead of also trying to ping it.  Customize the user option
 +'ffap-machine-p-known' to 'ping' to get the old behavior back.
 +
- ---
 +*** The 'run-dig' command is now obsolete; use 'dig' instead.
 +
- ---
 +*** Some 'bib-mode' commands and variables have been renamed.
 +To respect Emacs naming conventions, the variable 'unread-bib-file'
 +has been renamed to 'bib-unread-file'.  The following commands have
 +also been renamed:
 +    'addbib'           to  'bib-add'
 +    'return-key-bib'   to  'bib-return-key'
 +    'mark-bib'         to  'bib-mark'
 +    'unread-bib'       to  'bib-unread'
 +
- ---
 +*** 'outlineify-sticky' command is renamed to 'allout-outlinify-sticky'.
 +The old name is still available as an obsolete function alias.
 +
- ---
 +*** The url-irc library now understands "ircs://" links.
 +
- ---
 +*** New command 'world-clock-copy-time-as-kill' for 'world-clock-mode'.
 +It copies the current line into the kill ring.
 +
- ---
 +*** 'edit-abbrevs' now uses font-locking.
 +The new face 'abbrev-table-name' is used to display the abbrev table
 +name.
 +
- ---
 +*** New key binding 'O' in "*Buffer List*".
 +This key is now bound to 'Buffer-menu-view-other-window', which will
 +view this line's buffer in View mode in another window.
 +
 +** Scheme Mode
 +
- ---
 +*** Auto-detection of Scheme library files.
 +Emacs now automatically enables the Scheme mode when opening R6RS
 +Scheme Library Source (".sls") files and R7RS Scheme Library
 +Definition (".sld") files.
 +
- +++
 +*** Imenu members for R6RS and R7RS library members.
 +Imenu now lists the members directly nested in R6RS Scheme libraries
 +('library') and R7RS libraries ('define-library').
 +
 +\f
 +* New Modes and Packages in Emacs 29.1
 +
- +++
 +** Eglot: Emacs Client for the Language Server Protocol.
 +Emacs now comes with the Eglot package, which enhances various Emacs
 +features, such as completion, documentation, error detection, etc.,
 +based on data provided by language servers using the Language Server
 +Protocol (LSP).  See the new Info manual "(eglot) Top" for more.  Also
 +see "etc/EGLOT-NEWS".
 +
 +If you want to be able to use 'package-install' to upgrade Eglot to
 +newer versions released on GNU ELPA, customize the new option
 +'package-install-upgrade-built-in' to a non-nil value.
 +
- ---
 +** use-package: Declarative package configuration.
 +use-package is now shipped with Emacs.  It provides the 'use-package'
 +macro, which allows you to isolate package configuration in your init
 +file in a way that is declarative, tidy, and performance-oriented.
 +See the new Info manual "(use-package) Top" for more.
 +
 +If you want to be able to use 'package-install' to upgrade use-package
 +to newer versions released on GNU ELPA, customize the new option
 +'package-install-upgrade-built-in' to a non-nil value.
 +
- +++
 +** New package 'wallpaper'.
 +This package provides the command 'wallpaper-set', which sets the
 +desktop background image.  Depending on the system and the desktop,
 +this may require an external program (such as "swaybg", "gm",
 +"display" or "xloadimage").  If so, a suitable command should be
 +detected automatically in most cases.  It can also be customized
 +manually if needed, using the new user options 'wallpaper-command' and
 +'wallpaper-command-args'.
 +
- +++
 +** New package 'oclosure'.
 +This allows the creation of OClosures, which are "functions with
 +slots" or "function objects" that expose additional information about
 +themselves.  Use the new macros 'oclosure-define' and
 +'oclosure-lambda' to create OClosures.  See the "(elisp) OClosures"
 +node for more information.
 +
- ---
 +*** New generic function 'oclosure-interactive-form'.
 +Used by 'interactive-form' when called on an OClosure.
 +This allows specific OClosure types to compute their interactive specs
 +on demand rather than precompute them when created.
 +
- +++
 +** New theme 'leuven-dark'.
 +This is a dark version of the 'leuven' theme.
 +
- ---
 +** New mode 'erts-mode'.
 +This mode is used to edit files geared towards testing actions in
 +Emacs buffers, like indentation and the like.  The new ert function
 +'ert-test-erts-file' is used to parse these files.
 +
- +++
 +** New major mode 'js-json-mode'.
 +This is a lightweight variant of 'js-mode' that is used by default
 +when visiting JSON files.
 +
- +++
 +** New major mode 'csharp-mode'.
 +A major mode based on CC Mode for editing programs in the C# language.
 +This mode is auto-enabled for files with the ".cs" extension.
 +
- +++
 +** New major modes based on the tree-sitter library.
 +These new major modes are available if Emacs was built with the
 +tree-sitter library.  They provide support for font-locking,
 +indentation, and navigation by defuns based on parsing the buffer text
 +by a tree-sitter parser.  Some major modes also offer support for
 +Imenu and 'which-func'.
 +
 +The new modes based on tree-sitter are for now entirely optional, and
 +you must turn them on manually, or load them in your init file, or
 +customize 'auto-mode-alist' to turn them on automatically for certain
 +files.  You can also customize 'major-mode-remap-alist' to
 +automatically turn on some tree-sitter based modes for the same files
 +for which a "built-in" mode would be turned on.  For example:
 +
 +    (add-to-list 'major-mode-remap-alist '(ruby-mode . ruby-ts-mode))
 +
 +If you try these modes and don't like them, you can go back to the
 +"built-in" modes by restarting Emacs.  (If you use desktop.el to save
 +and restore Emacs sessions, make sure no buffer under these modes is
 +recorded in the desktop file, before restarting.)  But please tell us
 +why you didn't like the tree-sitter based modes, so that we could try
 +improving them.
 +
 +Each major mode based on tree-sitter needs a language grammar library,
 +usually named "libtree-sitter-LANG.so" ("libtree-sitter-LANG.dll" on
 +MS-Windows), where LANG is the corresponding language name.  Emacs
 +looks for these libraries in the following places:
 +
 + . in the directories mentioned in the list 'treesit-extra-load-path'
 + . in the "tree-sitter" subdirectory of your 'user-emacs-directory'
 +   (by default, "~/.emacs.d/tree-sitter")
 + . in the standard system directories where other shared libraries are
 +   usually installed
 +
 +We recommend to install these libraries in one of the standard system
 +locations (the last place in the above list).
 +
 +If a language grammar library required by a mode is not found in any
 +of the above places, the mode will display a warning when you try to
 +turn it on.
 +
- +++
 +*** New major mode 'typescript-ts-mode'.
 +A major mode based on the tree-sitter library for editing programs
 +in the TypeScript language.
 +
- +++
 +*** New major mode 'tsx-ts-mode'.
 +A major mode based on the tree-sitter library for editing programs
 +in the TypeScript language, with support for TSX.
 +
- +++
 +*** New major mode 'c-ts-mode'.
 +An optional major mode based on the tree-sitter library for editing
 +programs in the C language.
 +
- +++
 +*** New major mode 'c++-ts-mode'.
 +An optional major mode based on the tree-sitter library for editing
 +programs in the C++ language.
 +
- +++
 +*** New command 'c-or-c++-ts-mode'.
 +A command that automatically guesses the language of a header file,
 +and enables either 'c-ts-mode' or 'c++-ts-mode' accordingly.
 +
- +++
 +*** New major mode 'java-ts-mode'.
 +An optional major mode based on the tree-sitter library for editing
 +programs in the Java language.
 +
- +++
 +*** New major mode 'python-ts-mode'.
 +An optional major mode based on the tree-sitter library for editing
 +programs in the Python language.
 +
- +++
 +*** New major mode 'css-ts-mode'.
 +An optional major mode based on the tree-sitter library for editing
 +CSS (Cascading Style Sheets).
 +
- +++
 +*** New major mode 'json-ts-mode'.
 +An optional major mode based on the tree-sitter library for editing
 +programs in the JSON language.
 +
- +++
 +*** New major mode 'csharp-ts-mode'.
 +An optional major mode based on the tree-sitter library for editing
 +programs in the C# language.
 +
- +++
 +*** New major mode 'bash-ts-mode'.
 +Am optional major mode based on the tree-sitter library for editing
 +Bash shell scripts.
 +
- +++
 +*** New major mode 'dockerfile-ts-mode'.
 +A major mode based on the tree-sitter library for editing
 +Dockerfiles.
 +
- +++
 +*** New major mode 'cmake-ts-mode'.
 +A major mode based on the tree-sitter library for editing CMake files.
 +
- +++
 +*** New major mode 'toml-ts-mode'.
 +An optional major mode based on the tree-sitter library for editing
 +files written in TOML, a format for writing configuration files.
 +
- +++
 +*** New major mode 'go-ts-mode'.
 +A major mode based on the tree-sitter library for editing programs in
 +the Go language.
 +
- +++
 +*** New major mode 'go-mod-ts-mode'.
 +A major mode based on the tree-sitter library for editing "go.mod"
 +files.
 +
- +++
 +*** New major mode 'yaml-ts-mode'.
 +A major mode based on the tree-sitter library for editing files
 +written in YAML.
 +
- ---
 +*** New major mode 'rust-ts-mode'.
 +A major mode based on the tree-sitter library for editing programs in
 +the Rust language.
 +
- +++
 +*** New major mode 'ruby-ts-mode'.
 +An optional major mode based on the tree-sitter library for editing
 +programs in the Ruby language.
 +
 +\f
 +* Incompatible Lisp Changes in Emacs 29.1
 +
- ---
 +** The implementation of overlays has changed.
 +Emacs now uses an implementation of overlays that is much more
 +efficient than the original one, and should speed up all the
 +operations that involve overlays, especially when there are lots of
 +them in a buffer.
 +
 +As result of this, some minor incompatibilities in behavior could be
 +observed, as described below.  Except those minor incompatibilities,
 +no other changes in behavior of overlays should be visible on the Lisp
 +or user level, with the exception of better performance and the order
 +of overlays returned by functions that don't promise any particular
 +order.
 +
- ---
 +*** The function 'overlay-recenter' is now a no-op.
 +This function does nothing, and in particular has no effect on the
 +value returned by 'overlay-lists'.  The purpose of 'overlay-recenter'
 +was to allow more efficient lookup of overlays around a certain buffer
 +position; however with the new implementation the lookup of overlays
 +is efficient regardless of their position, and there's no longer any
 +need to "optimize" the lookup, nor any notion of a "center" of the
 +overlays.
 +
- +++
 +*** The function 'overlay-lists' returns one unified list of overlays.
 +This function used to return a cons of two lists, one with overlays
 +before the "center" position, the other after that "center".  It now
 +returns a list whose 'car' is the list of all the buffer overlays, and
 +whose 'cdr' is always nil.
 +
- +++
 +** 'format-prompt' now uses 'substitute-command-keys'.
 +This means that both the prompt and 'minibuffer-default-prompt-format'
 +will have key definitions and single quotes handled specially.
 +
- ---
 +** New function 'substitute-quotes'.
 +This function works like 'substitute-command-keys' but only
 +substitutes quote characters.
 +
- +++
 +** 'find-image' now uses 'create-image'.
 +This means that images found through 'find-image' also have
 +auto-scaling applied.  (This only makes a difference on HiDPI
 +displays.)
 +
- +++
 +** Changes in how "raw" in-memory XBM images are specified.
 +Some years back Emacs gained the ability to scale images, and you
 +could then specify ':width' and ':height' when using 'create-image' on all
 +image types -- except XBM images, because this format already used the
 +':width' and ':height' arguments to specify the width/height of the "raw"
 +in-memory format.  This meant that if you used these specifications
 +on, for instance, XBM files, Emacs would refuse to display them.  This
 +has been changed, and ':width'/':height' now works as with all other image
 +formats, and the way to specify the width/height of the "raw"
 +in-memory format is now by using ':data-width' and ':data-height'.
 +
- ---
 +** "loaddefs.el" generation has been reimplemented.
 +The various "loaddefs.el" files in the Emacs tree (which contain
 +information about autoloads, built-in packages and package prefixes)
 +used to be generated by functions in autoloads.el.  These are now
 +generated by loaddefs-gen.el instead.  This leads to functionally
 +equivalent "loaddefs.el" files, but they do not use exactly the same
 +syntax, so using 'M-x update-file-autoloads' no longer works.  (This
 +didn't work well in most files in the past, either, but it will now
 +signal an error in any file.)
 +
 +In addition, files are scanned in a slightly different way.
 +Previously, ';;;###' specs inside a top-level form (i.e., something
 +like '(when ... ;;;### ...)' would be ignored.  They are now parsed as
 +usual.
 +
- +++
 +** Themes have special autoload cookies.
 +All built-in themes are scraped for ';;;###theme-autoload' cookies
 +that are loaded along with the regular auto-loaded code.
 +
- ---
 +** 'buffer-modified-p' has been extended.
 +This function was previously documented to return only nil or t.  This
 +has been changed to nil/'autosaved'/non-nil.  The new 'autosaved'
 +value means that the buffer is modified, but that it hasn't been
 +modified since the time of last auto-save.
 +
- ---
 +** 'with-silent-modifications' also restores buffer autosave status.
 +'with-silent-modifications' is a macro meant to be used by the font
 +locking machinery to allow applying text properties without changing
 +the modification status of the buffer.  However, it didn't restore the
 +buffer autosave status, so applying font locking to a modified buffer
 +that had already been auto-saved would trigger another auto-saving.
 +This is no longer the case.
 +
- +++
 +** 'prin1' doesn't always escape "." and "?" in symbols any more.
 +Previously, symbols like 'foo.bar' would be printed by 'prin1' as
 +"foo\.bar".  This now prints as "foo.bar" instead.  The Emacs Lisp
 +reader interprets these strings as referring to the same symbol, so
 +this is virtually always backwards-compatible, but there may
 +theoretically be code out there that expects a specific printed
 +representation.
 +
 +The same is the case with the "?" character: The 'foo?' symbol is now
 +printed as "foo?" instead of "foo\?".
 +
 +If the "." and "?" characters are the first character in the symbol,
 +they will still be escaped, so the '.foo' symbol is still printed as
 +"\.foo" and the '?bar' symbol is still printed as "\?bar".
 +
- +++
 +** Remapping 'mode-line' face no longer works as expected.
 +'mode-line' is now the parent face of the new 'mode-line-active' face,
 +and remapping parent of basic faces does not work reliably.
 +Instead of remapping 'mode-line', you have to remap 'mode-line-active'.
 +
- ---
 +** 'make-process' has been extended to support ptys when ':stderr' is set.
 +Previously, setting ':stderr' to a non-nil value would force the
 +process's connection to use pipes.  Now, Emacs will use a pty for
 +stdin and stdout if requested no matter the value of ':stderr'.
 +
- ---
 +** User option 'mail-source-ignore-errors' is now obsolete.
 +The whole mechanism for prompting users to continue in case of
 +mail-source errors has been removed, so this option is no longer
 +needed.
 +
 +** Fonts
 +
- ---
 +*** Emacs now supports 'medium' fonts.
 +Emacs previously didn't distinguish between the 'regular'/'normal'
 +weight and the 'medium' weight, but it now also supports the (heavier)
 +'medium' weight.  However, this means that if you specify a weight of
 +'normal' and the font doesn't have this weight, Emacs won't find the
 +font spec.  In these cases, replacing ":weight 'normal" with ":weight
 +'medium" should fix the issue.
 +
- ---
 +** Keymap descriptions by Help commands have changed.
 +'help--describe-command', 'C-h b' and associated functions that output
 +keymap descriptions have changed.  In particular, prefix commands are
 +not output at all, and instead of "??" for closures/functions, these
 +functions output "[closure]"/"[lambda]".  You can get back the old
 +behavior of including prefix commands by customizing the new option
 +'describe-bindings-show-prefix-commands' to a non-nil value.
 +
- ---
 +** 'downcase' details have changed slightly.
 +In certain locales, changing the case of an ASCII-range character may
 +turn it into a multibyte character, most notably with "I" in Turkish
 +(the lowercase is "ı", 0x0131).  Previously, 'downcase' on a unibyte
 +string was buggy, and would mistakenly just return the lower byte of
 +this, 0x31 (the digit "1").  'downcase' on a unibyte string has now
 +been changed to downcase such characters as if they were ASCII.  To
 +get proper locale-dependent downcasing, the string has to be converted
 +to multibyte first.  (This goes for the other case-changing functions,
 +too.)
 +
- ---
 +** Functions in 'tramp-foreign-file-name-handler-alist' have changed.
 +Functions to determine which Tramp file name handler to use are now
 +passed a file name in dissected form (via 'tramp-dissect-file-name')
 +instead of in string form.
 +
- ---
 +** 'def' indentation changes.
 +In 'emacs-lisp-mode', forms with a symbol with a name that start with
 +"def" have been automatically indented as if they were 'defun'-like
 +forms, for instance:
 +
 +    (defzot 1
 +      2 3)
 +
 +This heuristic has now been removed, and all functions/macros that
 +want to be indented this way have to be marked with
 +
 +    (declare (indent defun))
 +
 +or the like.  If the function/macro definition itself can't be
 +changed, the indentation can also be adjusted by saying something
 +like:
 +
 +    (put 'defzot 'lisp-indent-function 'defun)
 +
- ---
 +** The 'inhibit-changing-match-data' variable is now obsolete.
 +Instead, functions like 'string-match' and 'looking-at' now take an
 +optional INHIBIT-MODIFY argument.
 +
- ---
 +** 'gnus-define-keys' is now obsolete.
 +Use 'define-keymap' instead.
 +
- ---
 +** MozRepl has been removed from js.el.
 +MozRepl was removed from Firefox in 2017, so this code doesn't work
 +with recent versions of Firefox.
 +
- ---
 +** The function 'image-dired-get-exif-data' is now obsolete.
 +Use 'exif-parse-file' and 'exif-field' instead.
 +
- ---
 +** 'insert-directory' alternatives should not change the free disk space line.
 +This change is now applied in 'dired-insert-directory'.
 +
- ---
 +** 'compilation-last-buffer' is (finally) declared obsolete.
 +It has been obsolete since Emacs 22.1, actually.
 +
- ---
 +** Calling 'lsh' now elicits a byte-compiler warning.
 +'lsh' behaves in somewhat surprising and platform-dependent ways for
 +negative arguments, and is generally slower than 'ash', which should be
 +used instead.  This warning can be suppressed by surrounding calls to
 +'lsh' with the construct '(with-suppressed-warnings ((suspicious lsh)) ...)',
 +but switching to 'ash' is generally much preferable.
 +
- ---
 +** Some functions and variables obsolete since Emacs 24 have been removed:
 +'Buffer-menu-buffer+size-width', 'Electric-buffer-menu-mode',
 +'Info-edit-map', 'allout-abbreviate-flattened-numbering',
 +'allout-exposure-change-hook', 'allout-mode-deactivate-hook',
 +'allout-structure-added-hook', 'allout-structure-deleted-hook',
 +'allout-structure-shifted-hook', 'ansi-color-unfontify-region',
 +'archive-extract-hooks', 'auth-source-forget-user-or-password',
 +'auth-source-hide-passwords', 'auth-source-user-or-password',
 +'automatic-hscrolling', 'automount-dir-prefix', 'bibtex-complete',
 +'bibtex-entry-field-alist', 'buffer-has-markers-at',
 +'buffer-substring-filters', 'byte-compile-disable-print-circle',
 +'c-prepare-bug-report-hooks', 'cfengine-mode-abbrevs',
 +'change-log-acknowledgement', 'chart-map',
 +'checkdoc-comment-style-hooks', 'comint--unquote&expand-filename',
 +'comint-dynamic-complete', 'comint-dynamic-complete-as-filename',
 +'comint-dynamic-simple-complete', 'comint-unquote-filename',
 +'command-history-map', 'compilation-parse-errors-function',
 +'completion-annotate-function', 'condition-case-no-debug',
 +'count-lines-region', 'crisp-mode-modeline-string',
 +'custom-print-functions', 'cvs-string-prefix-p', 'data-debug-map',
 +'deferred-action-function', 'deferred-action-list',
 +'dired-pop-to-buffer', 'dired-shrink-to-fit',
 +'dired-sort-set-modeline', 'dired-x-submit-report',
 +'display-buffer-function',
 +'ediff-choose-window-setup-function-automatically',
 +'eieio-defgeneric', 'eieio-defmethod', 'emacs-lock-from-exiting',
 +'erc-complete-word', 'erc-dcc-chat-filter-hook',
 +'eshell-add-to-window-buffer-names', 'eshell-cmpl-suffix-list',
 +'eshell-for', 'eshell-remove-from-window-buffer-names',
 +'eshell-status-in-modeline', 'filesets-cache-fill-content-hooks',
 +'font-list-limit', 'font-lock-maximum-size',
 +'font-lock-reference-face', 'gnus-carpal',
 +'gnus-debug-exclude-variables', 'gnus-debug-files',
 +'gnus-local-domain', 'gnus-outgoing-message-group',
 +'gnus-registry-user-format-function-M', 'gnus-secondary-servers',
 +'gnus-subscribe-newsgroup-hooks', 'gud-inhibit-global-bindings',
 +'hangul-input-method-inactivate', 'hfy-post-html-hooks',
 +'image-extension-data', 'image-library-alist',
 +'inactivate-current-input-method-function', 'inactivate-input-method',
 +'inhibit-first-line-modes-regexps',
 +'inhibit-first-line-modes-suffixes', 'input-method-inactivate-hook',
 +'intdos', 'javascript-generic-mode', 'javascript-generic-mode-hook',
 +'latex-string-prefix-p', 'macro-declaration-function' (function),
 +'macro-declaration-function' (variable), 'mail-complete',
 +'mail-complete-function', 'mail-mailer-swallows-blank-line',
 +'mail-sent-via', 'make-register', 'makefile-complete',
 +'menu-bar-kill-ring-save', 'meta-complete-symbol', 'meta-mode-map',
 +'mh-kill-folder-suppress-prompt-hooks',
 +'minibuffer-completing-symbol',
 +'minibuffer-local-filename-must-match-map', 'mode25', 'mode4350',
 +'mpc-string-prefix-p', 'msb-after-load-hooks',
 +'nndiary-request-accept-article-hooks',
 +'nndiary-request-create-group-hooks',
 +'nndiary-request-update-info-hooks', 'nnimap-split-rule',
 +'nntp-authinfo-file', 'ns-alternatives-map',
 +'ns-store-cut-buffer-internal', 'package-menu-view-commentary',
 +'pascal-last-completions', 'pascal-show-completions',
 +'pascal-toggle-completions', 'pcomplete-arg-quote-list',
 +'pcomplete-quote-argument', 'prolog-char-quote-workaround',
 +'python-buffer', 'python-guess-indent', 'python-indent',
 +'python-info-ppss-comment-or-string-p', 'python-info-ppss-context',
 +'python-info-ppss-context-type', 'python-preoutput-result',
 +'python-proc', 'python-send-receive', 'python-send-string',
 +'python-use-skeletons', 'quail-inactivate', 'quail-inactivate-hook',
 +'query-replace-interactive', 'rcirc-activity-hooks',
 +'rcirc-print-hooks', 'rcirc-receive-message-hooks',
 +'rcirc-sentinel-hooks', 'read-filename-at-point', 'redraw-modeline',
 +'reftex-index-map', 'reftex-index-phrases-map',
 +'reftex-select-bib-map', 'reftex-select-label-map', 'reftex-toc-map',
 +'register-name-alist', 'register-value', 'report-emacs-bug-info',
 +'report-emacs-bug-pretest-address',
 +'rmail-default-dont-reply-to-names', 'rmail-dont-reply-to',
 +'rmail-dont-reply-to-names', 'robin-inactivate',
 +'robin-inactivate-hook', 'rst-block-face', 'rst-comment-face',
 +'rst-definition-face', 'rst-directive-face', 'rst-emphasis1-face',
 +'rst-emphasis2-face', 'rst-external-face', 'rst-literal-face',
 +'rst-reference-face', 'semantic-change-hooks',
 +'semantic-edits-delete-change-hooks',
 +'semantic-edits-new-change-hooks',
 +'semantic-edits-reparse-change-hooks', 'semantic-grammar-map',
 +'semantic-grammar-syntax-table', 'semantic-lex-reset-hooks',
 +'semanticdb-elisp-sym-function-arglist',
 +'semanticdb-save-database-hooks', 'set-face-underline-p',
 +'set-register-value', 'sh-maybe-here-document', 'speedbar-key-map',
 +'speedbar-syntax-table', 'starttls-any-program-available',
 +'strokes-modeline-string', 'strokes-report-bug',
 +'term-default-bg-color', 'term-default-fg-color',
 +'tex-string-prefix-p', 'timeclock-modeline-display',
 +'timeclock-modeline-display', 'timeclock-update-modeline',
 +'toggle-emacs-lock', 'tooltip-use-echo-area', 'turn-on-cwarn-mode',
 +'turn-on-iimage-mode', 'ucs-input-inactivate', 'ucs-insert',
 +'url-recreate-url-attributes', 'user-variable-p',
 +'vc-string-prefix-p', 'vc-toggle-read-only', 'view-return-to-alist',
 +'view-return-to-alist-update', 'w32-default-color-map' (function),
 +'which-func-mode' (function), 'window-system-version',
 +'winner-mode-leave-hook', 'x-cut-buffer-or-selection-value'.
 +
- ---
 +** Some functions and variables obsolete since Emacs 23 have been removed:
 +'find-emacs-lisp-shadows', 'newsticker-cache-filename',
 +'process-filter-multibyte-p', 'redisplay-end-trigger-functions',
 +'set-process-filter-multibyte', 'set-window-redisplay-end-trigger',
 +'unify-8859-on-decoding-mode', 'unify-8859-on-encoding-mode',
 +'vc-arch-command', 'window-redisplay-end-trigger', 'x-selection'.
 +
- +++
 +** Some functions and variables obsolete since Emacs 21 or 22 have been removed:
 +'c-toggle-auto-state', 'find-file-not-found-hooks',
 +'ls-lisp-dired-ignore-case', 'query-replace-regexp-eval'.
 +
- +++
 +** New generic function 'function-documentation'.
 +It can dynamically generate a raw docstring depending on the type of a
 +function.  Used mainly for docstrings of OClosures.
 +
- +++
 +** Base64 encoding no longer tolerates latin-1 input.
 +The functions 'base64-encode-string', 'base64url-encode-string',
 +'base64-encode-region' and 'base64url-encode-region' no longer accept
 +characters in the range U+0080..U+00FF as substitutes for single bytes
 +in the range 128..255, but signal an error for all multibyte characters.
 +The input must be unibyte encoded text.
 +
- ---
 +** The 'clone-indirect-buffer-hook' is now run by 'make-indirect-buffer'.
 +It was previously only run by 'clone-indirect-buffer' and
 +'clone-indirect-buffer-other-window'.  Since 'make-indirect-buffer' is
 +called by both of these, the hook is now run by all 3 of these
 +functions.
 +
- ---
 +** '?\' at the end of a line now signals an error.
 +Previously, it produced a nonsense value, -1, that was never intended.
 +
- +++
 +** Some libraries obsolete since Emacs 24.1 and 24.3 have been removed:
 +abbrevlist.el, assoc.el, complete.el, cust-print.el,
 +erc-hecomplete.el, mailpost.el, mouse-sel.el, old-emacs-lock.el,
 +patcomp.el, pc-mode.el, pc-select.el, s-region.el, and sregex.el.
 +
- ---
 +** Many seldom-used generalized variables have been made obsolete.
 +Emacs has a number of rather obscure generalized variables defined,
 +that, for instance, allowed you to say things like:
 +
 +    (setf (point-min) 4)
 +
 +These never caught on and have been made obsolete.  The form above,
 +for instance, is the same as saying
 +
 +    (narrow-to-region 4 (point-max))
 +
 +The following generalized variables have been made obsolete:
 +'buffer-file-name', 'buffer-local-value', 'buffer-modified-p',
 +'buffer-name', 'buffer-string', 'buffer-substring', 'current-buffer',
 +'current-column', 'current-global-map', 'current-input-mode',
 +'current-local-map', 'current-window-configuration',
 +'default-file-modes', 'documentation-property', 'eq', 'frame-height',
 +'frame-width', 'frame-visible-p', 'global-key-binding',
 +'local-key-binding', 'mark', 'mark-marker', 'marker-position',
 +'mouse-position', 'point', 'point-marker', 'point-max', 'point-min',
 +'read-mouse-position', 'screen-height', 'screen-width',
 +'selected-frame', 'selected-screen', 'selected-window',
 +'standard-case-table', 'syntax-table', 'visited-file-modtime',
 +'window-height', 'window-width', and 'x-get-secondary-selection'.
 +
- +++
 +** The 'dotimes' loop variable can no longer be manipulated in the loop body.
 +Previously, the 'dotimes' loop counter could be modified inside the
 +loop body, but only in code using dynamic binding.  Now the behavior
 +is the same as when using lexical binding: changes to the loop
 +variable have no effect on subsequent iterations.  That is,
 +
 +    (dotimes (i 10)
 +      (print i)
 +      (setq i (+ i 6)))
 +
 +now always prints the numbers 0 .. 9.
 +
 +\f
 +* Lisp Changes in Emacs 29.1
 +
- +++
 +** Interpreted closures are "safe for space".
 +As was already the case for byte-compiled closures, instead of capturing
 +the whole current lexical environment, interpreted closures now only
 +capture the part of the environment that they need.
 +The previous behavior could occasionally lead to memory leaks or
 +to problems where a printed closure would not be 'read'able because
 +of an un'read'able value in an unrelated lexical variable.
 +
- +++
 +** New accessor function 'file-attribute-file-identifier'.
 +It returns the list of the inode number and device identifier
 +retrieved by 'file-attributes'.  This value can be used to identify a
 +file uniquely.  The device identifier can be a single number or (for
 +remote files) a cons of 2 numbers.
 +
- +++
 +** New macro 'while-let'.
 +This is like 'when-let', but repeats until a binding form is nil.
 +
- +++
 +** New function 'make-obsolete-generalized-variable'.
 +This can be used to mark setters used by 'setf' as obsolete, and the
 +byte-compiler will then warn about using them.
 +
- +++
 +** New functions 'pos-eol' and 'pos-bol'.
 +These are like 'line-end-position' and 'line-beginning-position'
 +(respectively), but ignore fields (and are more efficient).
 +
- ---
 +** New function 'compiled-function-p'.
 +This returns non-nil if its argument is either a built-in, or a
 +byte-compiled, or a natively-compiled function object, or a function
 +loaded from a dynamic module.
 +
- +++
 +** 'deactivate-mark' can have new value 'dont-save'.
 +This value means that Emacs should deactivate the mark as usual, but
 +without setting the primary selection, if 'select-active-regions' is
 +enabled.
 +
- +++
 +** New 'declare' form 'interactive-args'.
 +This can be used to specify what forms to put into 'command-history'
 +when executing commands interactively.
 +
- +++
 +** The FORM argument of 'time-convert' is mandatory.
 +'time-convert' can still be called without it, as before, but the
 +compiler now emits a warning about this deprecated usage.
 +
- +++
 +** Emacs now supports user-customizable and themable icons.
 +These can be used for buttons in buffers and the like.  See the
 +"(elisp) Icons" and "(emacs) Icons" nodes in the manuals for details.
 +
- +++
 +** New arguments MESSAGE and TIMEOUT of 'set-transient-map'.
 +MESSAGE specifies a message to display after activating the transient
 +map, including a special formatting spec to list available keys.
 +TIMEOUT is the idle time after which to deactivate the transient map.
 +The default timeout value can be defined by the new variable
 +'set-transient-map-timeout'.
 +
- +++
 +** New forms 'with-restriction' and 'without-restriction'.
 +These forms can be used as enhanced alternatives to the
 +'save-restriction' form combined with, respectively,
 +'narrow-to-region' and 'widen'.  They also accept an optional label
 +argument, with which labeled narrowings can be created and lifted.
 +See the "(elisp) Narrowing" node for details.
 +
 +** Connection Local Variables
 +
- +++
 +*** Some connection-local variables are now user options.
 +The variables 'connection-local-profile-alist' and
 +'connection-local-criteria-alist' are now user options, in order to
 +make it more convenient to inspect and modify them.
 +
- +++
 +*** New function 'connection-local-update-profile-variables'.
 +This function allows to modify the settings of an existing
 +connection-local profile.
 +
- +++
 +*** New macro 'with-connection-local-application-variables'.
 +This macro works like 'with-connection-local-variables', but it allows
 +using another application instead of 'tramp'.  This is useful when
 +running code in a buffer where Tramp has already set some
 +connection-local variables.
 +
- +++
 +*** New macro 'setq-connection-local'.
 +This allows dynamically setting variable values for a particular
 +connection within the body of 'with-connection-local-{application-}variables'.
 +See the "(elisp) Connection Local Variables" node in the Lisp
 +Reference manual for more information.
 +
- +++
 +** 'plist-get', 'plist-put' and 'plist-member' are no longer limited to 'eq'.
 +These function now take an optional comparison PREDICATE argument.
 +
- +++
 +** 'read-multiple-choice' can now use long-form answers.
 +
- +++
 +** 'M-s c' in 'read-regexp' now toggles case folding.
 +
- +++
 +** 'completing-read' now allows a function as its REQUIRE-MATCH argument.
 +This function is called to see whether what the user has typed is a
 +match.  This is also available from functions that call
 +'completing-read', like 'read-file-name'.
 +
- +++
 +** 'posn-col-row' can now give position data based on windows.
 +Previously, it reported data only based on the frame.
 +
- ---
 +** 'file-expand-wildcards' can now also take a regexp as PATTERN argument.
 +
- +++
 +** vc-mtn (the VC backend for Monotone) has been made obsolete.
 +
- ---
 +** 'gui-set-selection' can specify different values for different data types.
 +If DATA is a string, then its text properties are searched for values
 +for each specific data type while the selection is being converted.
 +
- +++
 +** New eldoc function 'elisp-eldoc-var-docstring-with-value'.
 +This function includes the current value of the variable in eldoc display
 +and can be used as a more detailed alternative to 'elisp-eldoc-var-docstring'.
 +
- +++
 +** 'save-some-buffers' can now be extended to save other things.
 +Traditionally, 'save-some-buffers' saved buffers, and also saved
 +abbrevs.  This has been generalized via the
 +'save-some-buffers-functions' variable, and packages can now register
 +things to be saved.
 +
- +++
 +** New function 'string-equal-ignore-case'.
 +This compares strings ignoring case differences.
 +
- +++
 +** 'symbol-file' can now report natively-compiled ".eln" files.
 +If Emacs was built with native-compilation enabled, Lisp programs can
 +now call 'symbol-file' with the new optional 3rd argument non-nil to
 +request the name of the ".eln" file which defined a given symbol.
 +
- +++
 +** New macro 'with-memoization' provides a very primitive form of memoization.
 +
- +++
 +** 'max-char' can now report the maximum codepoint according to Unicode.
 +When called with a new optional argument UNICODE non-nil, 'max-char'
 +will now report the maximum valid codepoint defined by the Unicode
 +Standard.
 +
 +** Seq
 +
- +++
 +*** New function 'seq-split'.
 +This returns a list of sub-sequences of the specified sequence.
 +
- +++
 +*** New function 'seq-remove-at-position'.
 +This function returns a copy of the specified sequence with the
 +element at a given (zero-based) index removed.
 +
- +++
 +*** New function 'seq-positions'.
 +This returns a list of the (zero-based) indices of elements matching a
 +given predicate in the specified sequence.
 +
- ---
 +*** New function 'seq-keep'.
 +This is like 'seq-map', but removes all nil results from the returned
 +list.
 +
 +** Themes
 +
- ---
 +*** New hooks 'enable-theme-functions' and 'disable-theme-functions'.
 +These are run after enabling and disabling a theme, respectively.
 +
- +++
 +*** Themes can now be made obsolete.
 +Using 'make-obsolete' on a theme is now supported.  This will make
 +'load-theme' issue a warning when loading the theme.
 +
- +++
 +** New hook 'display-monitors-changed-functions'.
 +It is called whenever the configuration of different monitors on a
 +display changes.
 +
- +++
 +** 'prin1' and 'prin1-to-string' now take an optional OVERRIDES argument.
 +This argument can be used to override values of print-related settings.
 +
- +++
 +** New minor mode 'header-line-indent-mode'.
 +This is meant to be used by Lisp programs that show a header line
 +which should be kept aligned with the buffer contents when the user
 +switches 'display-line-numbers-mode' on or off, and when the width of
 +line-number display changes.  See the "(elisp) Header Lines" node in
 +the Emacs Lisp Reference manual for more information.
 +
- ---
 +** New global minor mode 'lost-selection-mode'.
 +This global minor mode makes Emacs deactivate the mark in all buffers
 +when the primary selection is obtained by another program.
 +
- +++
 +** On X, Emacs will try to preserve selection ownership when a frame is deleted.
 +This means that if you make Emacs the owner of a selection, such as by
 +selecting some text into the clipboard or primary selection, and then
 +delete the current frame, you will still be able to insert the
 +contents of that selection into other programs as long as another
 +frame is open on the same display.  This behavior can be disabled by
 +setting the user option 'x-auto-preserve-selections' to nil.
 +
- ---
 +** New predicate 'char-uppercase-p'.
 +This returns non-nil if its argument its an uppercase character.
 +
 +** Byte Compilation
 +
- ---
 +*** Byte compilation will now warn about some quoting mistakes in docstrings.
 +When writing code snippets that contains the "'" character (APOSTROPHE),
 +that quote character has to be escaped to avoid Emacs displaying it as
 +"’" (LEFT SINGLE QUOTATION MARK), which would make code examples like
 +
 +    (setq foo '(1 2 3))
 +
 +invalid.  Emacs will now warn during byte compilation if it sees
 +something like that, and also warn about when using RIGHT/LEFT SINGLE
 +QUOTATION MARK directly.  In both these cases, if these characters
 +should really be present in the docstring, they should be quoted with
 +"\=".
 +
- +++
 +*** Byte compilation will now warn about some malformed 'defcustom' types.
 +It is very common to write 'defcustom' types on the form:
 +
 +    :type '(choice (const :tag "foo" 'bar))
 +
 +I.e., double-quoting the 'bar', which is almost never the correct
 +value.  The byte compiler will now issue a warning if it encounters
 +these forms.
 +
- ---
 +** 'restore-buffer-modified-p' can now alter buffer auto-save state.
 +With a FLAG value of 'autosaved', it will mark the buffer as having
 +been auto-saved since the time of last modification.
 +
- +++
 +** New minor mode 'isearch-fold-quotes-mode'.
 +This sets up 'search-default-mode' so that quote characters are
 +char-folded into each other.  It is used, by default, in "*Help*" and
 +"*info*" buffers.
 +
- ---
 +** New macro 'buffer-local-set-state'.
 +This is a helper macro to be used by minor modes that wish to restore
 +buffer-local variables back to their original states when the mode is
 +switched off.
 +
- ---
 +** New macro 'with-buffer-unmodified-if-unchanged'.
 +If the buffer is marked as unmodified, and code does modifications
 +that, in total, means that the buffer is identical to the buffer
 +before, mark the buffer as unmodified again.
 +
- ---
 +** New function 'malloc-trim'.
 +This function allows returning unused memory back to the operating
 +system, and is mainly meant as a debugging tool.  It is currently
 +available only when Emacs was built with glibc as the C library.
 +
- ---
 +** 'x-show-tip' no longer hard-codes a timeout default.
 +The new variable 'x-show-tooltip-timeout' allows the user to alter
 +this for packages that don't use 'tooltip-show', but instead call the
 +lower level function directly.
 +
- ---
 +** New function 'current-cpu-time'.
 +It gives access to the CPU time used by the Emacs process, for
 +example for benchmarking purposes.
 +
- +++
 +** New function 'string-edit'.
 +This is meant to be used when the user has to edit a (potentially)
 +long string.  It pops up a new buffer where you can edit the string,
 +and the provided callback is called when the user types 'C-c C-c'.
 +
- +++
 +** New function 'read-string-from-buffer'.
 +This is a modal version of 'string-edit', and can be used as an
 +alternative to 'read-string'.
 +
- +++
 +** The return value of 'clear-message-function' is not ignored anymore.
 +If the function returns 'dont-clear-message', then the message is not
 +cleared, with the assumption that the function cleared it itself.
 +
- +++
 +** The local variables section now supports defining fallback modes.
 +This was previously only available when using a property line (i.e.,
 +putting the modes on the first line of a file).
 +
- +++
 +** New function 'flush-standard-output'.
 +This enables display of lines that don't end in a newline from
 +batch-based Emacs scripts.
 +
- +++
 +** New convenience function 'buttonize-region'.
 +This works like 'buttonize', but for a region instead of a string.
 +
- +++
 +** 'macroexp-let2*' can omit TEST argument and use single-var bindings.
 +
- +++
 +** New macro-writing macros, 'cl-with-gensyms' and 'cl-once-only'.
 +See the "(cl) Macro-Writing Macros" manual section for descriptions.
 +
- +++
 +** New variable 'last-event-device' and new function 'device-class'.
 +On X Windows, 'last-event-device' specifies the input extension device
 +from which the last input event originated, and 'device-class' can be
 +used to determine the type of an input device.
 +
- +++
 +** Variable 'track-mouse' can have a new value 'drag-source'.
 +This means the same as 'dropping', but modifies the mouse position
 +list in reported motion events if there is no frame underneath the
 +mouse pointer.
 +
- ---
 +** New functions for dragging items from Emacs to other programs.
 +The new functions 'x-begin-drag', 'dnd-begin-file-drag',
 +'dnd-begin-drag-files', and 'dnd-direct-save' allow dragging contents
 +(such as files and text) from Emacs to other programs.
 +
- +++
 +** New function 'ietf-drums-parse-date-string'.
 +This function parses RFC5322 (and RFC822) date strings, and should be
 +used instead of 'parse-time-string' when parsing data that's standards
 +compliant.
 +
- +++
 +** New macro 'setopt'.
 +This is like 'setq', but is meant to be used for user options instead
 +of plain variables, and uses 'custom-set'/'set-default' to set them.
 +
- +++
 +** New utility predicate 'mode-line-window-selected-p'.
 +This is meant to be used from ':eval' mode line constructs to create
 +different mode line looks for selected and unselected windows.
 +
- +++
 +** New variable 'messages-buffer-name'.
 +This variable (defaulting to "*Messages*") allows packages to override
 +where messages are logged.
 +
- +++
 +** New function 'readablep'.
 +This function says whether an object can be written out and then
 +read back by the Emacs Lisp reader.
 +
- ---
 +** New variable 'print-unreadable-function'.
 +This variable allows changing how Emacs prints unreadable objects.
 +
- ---
 +** The user option 'polling-period' now accepts floating point values.
 +This means Emacs can now poll for input during Lisp execution more
 +frequently than once in a second.
 +
- ---
 +** New function 'bidi-string-strip-control-characters'.
 +This utility function is meant for displaying strings when it is
 +essential that there's no bidirectional context.  It removes all the
 +bidirectional formatting control characters (such as RLM, LRO, PDF,
 +etc.) from its argument string.  The characters it removes are listed
 +in the value of 'bidi-control-characters'.
 +
- +++
 +** The Gnus range functions have been moved to a new library, range.el.
 +All the old names have been made obsolete.
 +
- +++
 +** New function 'function-alias-p'.
 +This predicate says whether an object is a function alias, and if it
 +is, the alias chain is returned.
 +
- +++
 +** New variable 'lisp-directory' holds the directory of Emacs's own Lisp files.
 +
- +++
 +** New facility for handling session state: 'multisession-value'.
 +This can be used as a convenient way to store (simple) application
 +state, and the command 'list-multisession-values' allows users to list
 +(and edit) this data.
 +
- +++
 +** New function 'get-display-property'.
 +This is like 'get-text-property', but works on the 'display' text
 +property.
 +
- +++
 +** New function 'add-display-text-property'.
 +This is like 'put-text-property', but works on the 'display' text
 +property.
 +
- +++
 +** New 'min-width' 'display' property.
 +This allows setting a minimum display width for a region of text.
 +
- +++
 +** New 'cursor-face' text property.
 +This uses 'cursor-face' instead of the default face when cursor is on or
 +near the character and 'cursor-face-highlight-mode' is enabled.  The
 +user option 'cursor-face-highlight-nonselected-window' is similar to
 +'highlight-nonselected-windows', but for this property.
 +
- +++
 +** New event type 'touch-end'.
 +This event is sent whenever the user's finger moves off the mouse
 +wheel on some mice, or when the user's finger moves off the touchpad.
 +
- +++
 +** New event type 'pinch'.
 +This event is sent when a user performs a pinch gesture on a touchpad,
 +which is comprised of placing two fingers on the touchpad and moving
 +them towards or away from each other.
 +
- ---
 +** New hook 'x-pre-popup-menu-hook'.
 +This hook is run before 'x-popup-menu' is about to display a
 +deck-of-cards menu on screen.
 +
- +++
 +** New hook 'post-select-region-hook'.
 +This hook is run immediately after 'select-active-regions'.  It causes
 +the region to be set as the primary selection.
 +
- +++
 +** New function 'buffer-match-p'.
 +Check if a buffer satisfies some condition.  Some examples for
 +conditions can be regular expressions that match a buffer name, a
 +cons-cell like '(major-mode . shell-mode)' that matches any buffer
 +where 'major-mode' is 'shell-mode' or a combination with a condition
 +like '(and "\\`\\*.+\\*\\'" (major-mode . special-mode))'.
 +
- ---
 +** New function 'match-buffers'.
 +It uses 'buffer-match-p' to gather a list of buffers that match a
 +condition.
 +
- +++
 +** New optional arguments TEXT-FACE and DEFAULT-FACE for 'tooltip-show'.
 +They allow changing the faces used for the tooltip text and frame
 +colors of the resulting tooltip frame from the default 'tooltip' face.
 +
 +** Text Security and Suspiciousness
 +
- +++
 +*** New library textsec.el.
 +This library contains a number of checks for whether a string is
 +"suspicious".  This usually means that the string contains characters
 +that have glyphs that can be confused with other, more commonly used
 +glyphs, or contains bidirectional (or other) formatting characters
 +that may be used to confuse a user.
 +
- +++
 +*** New user option 'textsec-check'.
 +If non-nil (which is the default), Emacs packages that are vulnerable
 +to attackers trying to confuse the users will use the textsec library
 +to mark suspicious text.  For instance shr/eww will mark suspicious
 +URLs and links, Gnus will mark suspicious From addresses, and
 +Message mode will query the user if the user is sending mail to a
 +suspicious address.  If this variable is nil, these checks are
 +disabled.
 +
- +++
 +*** New function 'textsec-suspicious-p'.
 +This is the main function Emacs applications should be using to check
 +whether a string is suspicious.  It heeds the 'textsec-check' user
 +option.
 +
 +** Keymaps and Key Definitions
 +
- +++
 +*** 'where-is-internal' can now filter events marked as non key events.
 +If a command maps to a key binding like '[some-event]', and 'some-event'
 +has a symbol plist containing a non-nil 'non-key-event' property, then
 +that binding is ignored by 'where-is-internal'.
 +
- +++
 +*** New functions for defining and manipulating keystrokes.
 +These all take the syntax defined by 'key-valid-p', which is basically
 +the same syntax as the one accepted by the 'kbd' macro.  None of the
 +older functions have been deprecated or altered, but they are now
 +de-emphasized in the documentation, and we encourage Lisp programs to
 +switch to these new functions.
 +
- +++
 +*** Use 'keymap-set' instead of 'define-key'.
 +
- +++
 +*** Use 'keymap-global-set' instead of 'global-set-key'.
 +
- +++
 +*** Use 'keymap-local-set' instead of 'local-set-key'.
 +
- +++
 +*** Use 'keymap-global-unset' instead of 'global-unset-key'.
 +
- +++
 +*** Use 'keymap-local-unset' instead of 'local-unset-key'.
 +
- +++
 +*** Use 'keymap-substitute' instead of 'substitute-key-definition'.
 +
- +++
 +*** Use 'keymap-set-after' instead of 'define-key-after'.
 +
- +++
 +*** Use 'keymap-lookup' instead of 'lookup-key' and 'key-binding'.
 +
- +++
 +*** Use 'keymap-local-lookup' instead of 'local-key-binding'.
 +
- +++
 +*** Use 'keymap-global-lookup' instead of 'global-key-binding'.
 +
- +++
 +*** 'define-key' now takes an optional REMOVE argument.
 +If non-nil, remove the definition from the keymap.  This is subtly
 +different from setting a definition to nil: when the keymap has a
 +parent such a definition will shadow the parent's definition.
 +
- +++
 +*** 'read-multiple-choice' now takes an optional SHOW-HELP argument.
 +If non-nil, show the help buffer immediately, before any user input.
 +
- ---
 +*** New function 'key-valid-p'.
 +The 'kbd' function is quite permissive, and will try to return
 +something usable even if the syntax of the argument isn't completely
 +correct.  The 'key-valid-p' predicate does a stricter check of the
 +syntax.
 +
- +++
 +*** New function 'key-parse'.
 +This is like 'kbd', but only returns vectors instead of a mix of
 +vectors and strings.
 +
- +++
 +*** New ':type' for 'defcustom' for keys.
 +The new 'key' type can be used for options that should be a valid key
 +according to 'key-valid-p'.  The type 'key-sequence' is now obsolete.
 +
- +++
 +** New function 'define-keymap'.
 +This function allows defining a number of keystrokes with one form.
 +
- ---
 +** New macro 'defvar-keymap'.
 +This macro allows defining keymap variables more conveniently.
 +
 +** 'defvar-keymap' can specify 'repeat-mode' behavior for the keymap.
 +Use ':repeat t' to have all bindings be repeatable or for more
 +advanced usage:
 +
 +    :repeat (:enter (commands ...) :exit (commands ...))
 +
- +++
 +** 'kbd' can now be used in built-in, preloaded libraries.
 +It no longer depends on edmacro.el and cl-lib.el.
 +
- ---
 +** New substitution in docstrings and 'substitute-command-keys'.
 +Use \\`KEYSEQ' to insert a literal key sequence "KEYSEQ" (for example
 +\\`C-k') in a docstring or when calling 'substitute-command-keys',
 +which will use the same face as a command substitution.  This should
 +be used only when a key sequence has no corresponding command, for
 +example when it is read directly with 'read-key-sequence'.  It must be
 +a valid key sequence according to 'key-valid-p'.
 +
- +++
 +** 'lookup-key' is more permissive when searching for extended menu items.
 +In Emacs 28.1, the behavior of 'lookup-key' was changed: when looking
 +for a menu item '[menu-bar Foo-Bar]', first try to find an exact
 +match, then look for the lowercased '[menu-bar foo-bar]'.
 +
 +This has been extended, so that when looking for a menu item with a
 +symbol containing spaces, as in '[menu-bar Foo\ Bar]', first look for
 +an exact match, then the lowercased '[menu-bar foo\ bar]' and finally
 +'[menu-bar foo-bar]'.  This further improves backwards-compatibility
 +when converting menus to use 'easy-menu-define'.
 +
- +++
 +** New function 'file-name-split'.
 +This returns a list of all the components of a file name.
 +
- +++
 +** New function 'file-name-parent-directory'.
 +This returns the parent directory of a file name.
 +
- +++
 +** New macro 'with-undo-amalgamate'.
 +It records a particular sequence of operations as a single undo step.
 +
- +++
 +** New command 'yank-media'.
 +This command supports yanking non-plain-text media like images and
 +HTML from other applications into Emacs.  It is only supported in
 +modes that have registered support for it, and only on capable
 +platforms.
 +
- +++
 +** New command 'yank-media-types'.
 +This command lets you examine all data in the current selection and
 +the clipboard, and insert it into the buffer.
 +
- ---
 +** New variable 'yank-transform-functions'.
 +This variable allows the user to alter the string to be inserted.
 +
- ---
 +** New command 'yank-in-context'.
 +This command tries to preserve string/comment syntax when yanking.
 +
- +++
 +** New function 'minibuffer-lazy-highlight-setup'.
 +This function allows setting up the minibuffer so that lazy
 +highlighting of its content is applied in the original window.
 +
- +++
 +** New text property 'inhibit-isearch'.
 +If set, 'isearch' will skip these areas, which can be useful (for
 +instance) when covering huge amounts of data (that has no meaningful
 +searchable data, like image data) with a 'display' text property.
 +
- ---
 +** 'insert-image' now takes an INHIBIT-ISEARCH optional argument.
 +It marks the image with the 'inhibit-isearch' text property, which
 +inhibits 'isearch' matching the STRING argument.
 +
- ---
 +** New variable 'replace-regexp-function'.
 +Function to call to convert the entered FROM string to an Emacs
 +regexp in 'query-replace' and similar commands.  It can be used to
 +implement a different regexp syntax for search/replace.
 +
- ---
 +** New variables to customize defaults of FROM for 'query-replace*' commands.
 +The new variable 'query-replace-read-from-default' can be set to a
 +function that returns the default value of FROM when 'query-replace'
 +prompts for a string to be replaced.  An example of such a function is
 +'find-tag-default'.
 +
 +The new variable 'query-replace-read-from-regexp-default' can be set
 +to a function (such as 'find-tag-default-as-regexp') that returns the
 +default value of FROM when 'query-replace-regexp' prompts for a regexp
 +whose matches are to be replaced.  If these variables are nil (which
 +is the default), 'query-replace' and 'query-replace-regexp' take the
 +default value from the previous FROM-TO pair.
 +
 +** Lisp pretty-printer ('pp')
 +
- ---
 +*** New function 'pp-emacs-lisp-code'.
 +'pp' formats general Lisp sexps.  This function does much the same,
 +but applies formatting rules appropriate for Emacs Lisp code.  Note
 +that this could currently be quite slow, and is thus appropriate only
 +for relatively small code fragments.
 +
- +++
 +*** New user option 'pp-use-max-width'.
 +If non-nil, 'pp' and all 'pp-*' commands that format the results, will
 +attempt to limit the line length when formatting long lists and
 +vectors.  This uses 'pp-emacs-lisp-code', and thus could be slow for
 +large lists.
 +
- +++
 +** New function 'file-has-changed-p'.
 +This convenience function is useful when writing code that parses
 +files at run-time, and allows Lisp programs to re-parse files only
 +when they have changed.
 +
- ---
 +** 'abbreviate-file-name' now respects magic file name handlers.
 +
- +++
 +** New function 'font-has-char-p'.
 +This can be used to check whether a specific font has a glyph for a
 +character.
 +
- +++
 +** 'window-text-pixel-size' now accepts a new argument IGNORE-LINE-AT-END.
 +This controls whether or not the last screen line of the text being
 +measured will be counted for the purpose of calculating the text
 +dimensions.
 +
- +++
 +** 'window-text-pixel-size' understands a new meaning of FROM.
 +Specifying a cons as the FROM argument allows to start measuring text
 +from a specified amount of pixels above or below a position.
 +
- +++
 +** 'window-body-width' and 'window-body-height' can use remapped faces.
 +Specifying 'remap' as the PIXELWISE argument now checks if the default
 +face was remapped, and if so, uses the remapped face to determine the
 +character width/height.
 +
- ---
 +** 'set-window-vscroll' now accepts a new argument PRESERVE-VSCROLL-P.
 +This means the vscroll will not be reset when set on a window that is
 +"frozen" due to a mini-window being resized.
 +
 +** XDG Support
 +
- ---
 +*** New function 'xdg-state-home'.
 +It returns the new 'XDG_STATE_HOME' environment variable.  It should
 +point to a file name that "contains state data that should persist
 +between (application) restarts, but that is not important or portable
 +enough to the user that it should be stored in $XDG_DATA_HOME".
 +(This variable was introduced in the XDG Base Directory Specification
 +version 0.8 released on May 8, 2021.)
 +
- ---
 +*** New function 'xdg-current-desktop'.
 +It returns a list of strings, corresponding to the colon-separated
 +list of names in the 'XDG_CURRENT_DESKTOP' environment variable, which
 +identify the current desktop environment.
 +(This variable was introduced in XDG Desktop Entry Specification
 +version 1.2.)
 +
- +++
 +*** New function 'xdg-session-type'.
 +It returns the 'XDG_SESSION_TYPE' environment variable.  (This is not
 +part of any official standard; see the man page pam_systemd(8) for
 +more information.)
 +
- ---
 +** New macro 'with-delayed-message'.
 +This macro is like 'progn', but will output the specified message if
 +the body takes longer to execute than the specified timeout.
 +
- ---
 +** New function 'funcall-with-delayed-message'.
 +This function is like 'funcall', but will output the specified message
 +if the function takes longer to execute than the specified timeout.
 +
 +** Locale
 +
- ---
 +*** New variable 'current-locale-environment'.
 +This holds the value of the previous call to 'set-locale-environment'.
 +
- ---
 +*** New macro 'with-locale-environment'.
 +This macro can be used to change the locale temporarily while
 +executing code.
 +
 +** Table
 +
- +++
 +*** New user option 'table-latex-environment'.
 +This allows switching between "table" and "tabular".
 +
 +** Tabulated List Mode
 +
- +++
 +*** A column can now be set to an image descriptor.
 +The 'tabulated-list-entries' variable now supports using an image
 +descriptor, which means to insert an image in that column instead of
 +text.  See the documentation string of that variable for details.
 +
- +++
 +** ':keys' in 'menu-item' can now be a function.
 +If so, it is called whenever the menu is computed, and can be used to
 +calculate the keys dynamically.
 +
- +++
 +** New major mode 'clean-mode'.
 +This is a new major mode meant for debugging.  It kills absolutely all
 +local variables and removes overlays and text properties.
 +
- +++
 +** 'kill-all-local-variables' can now kill all local variables.
 +If given the new optional KILL-PERMANENT argument, it also kills
 +permanent local variables.
 +
- +++
 +** Third 'mapconcat' argument SEPARATOR is now optional.
 +An explicit nil always meant the empty string, now it can be left out.
 +
- +++
 +** New function 'image-at-point-p'.
 +This function returns t if point is on a valid image, and nil
 +otherwise.
 +
- +++
 +** New function 'buffer-text-pixel-size'.
 +This is similar to 'window-text-pixel-size', but can be used when the
 +buffer isn't displayed.
 +
- +++
 +** New function 'string-pixel-width'.
 +This returns the width of a string in pixels.  This can be useful when
 +dealing with variable pitch fonts and glyphs that have widths that
 +aren't integer multiples of the default font.
 +
- +++
 +** New function 'string-glyph-split'.
 +This function splits a string into a list of strings representing
 +separate glyphs.  This takes into account combining characters and
 +grapheme clusters, by treating each sequence of characters composed on
 +display as a single unit.
 +
 +** Xwidget
 +
- +++
 +*** The function 'make-xwidget' now accepts an optional RELATED argument.
 +This argument is used as another widget for the newly created WebKit
 +widget to share settings and subprocesses with.  It must be another
 +WebKit widget.
 +
- +++
 +*** New function 'xwidget-perform-lispy-event'.
 +This function allows you to send events to xwidgets.  Usually, some
 +equivalent of the event will be sent, but there is no guarantee of
 +what the widget will actually receive.
 +
 +On GTK+, only key and function key events are implemented.
 +
- +++
 +*** New function 'xwidget-webkit-load-html'.
 +This function is used to load HTML text into WebKit xwidgets
 +directly, in contrast to creating a temporary file to hold the
 +markup, and passing the URI of the file as an argument to
 +'xwidget-webkit-goto-uri'.
 +
- +++
 +*** New functions for performing searches on WebKit xwidgets.
 +Some new functions, such as 'xwidget-webkit-search', have been added
 +for performing searches on WebKit xwidgets.
 +
- +++
 +*** New function 'xwidget-webkit-back-forward-list'.
 +This function returns the history of page-loads in a WebKit xwidget.
 +
- +++
 +*** New function 'xwidget-webkit-estimated-load-progress'.
 +This function returns the estimated progress of page loading in a
 +WebKit xwidget.
 +
- +++
 +*** New function 'xwidget-webkit-stop-loading'.
 +This function terminates all data transfer during page loads in a
 +WebKit xwidget.
 +
- +++
 +*** 'load-changed' xwidget events are now more detailed.
 +In particular, they can now have different arguments based on the
 +state of the WebKit widget.  'load-finished' is sent when a load has
 +completed, 'load-started' when a load first starts, 'load-redirected'
 +after a redirect, and 'load-committed' when the WebKit widget first
 +commits to the load.
 +
- +++
 +*** New event type 'xwidget-display-event'.
 +These events are sent whenever an xwidget requests that Emacs displays
 +another xwidget.  The only arguments to this event are the xwidget
 +that should be displayed, and the xwidget that asked to display it.
 +
- ---
 +*** New function 'xwidget-webkit-set-cookie-storage-file'.
 +This function is used to control where and if an xwidget stores
 +cookies set by web pages on disk.
 +
- +++
 +** New variable 'help-buffer-under-preparation'.
 +This variable is bound to t during the preparation of a "*Help*" buffer.
 +
- +++
 +** Timestamps like '(1 . 1000)' now work without warnings being generated.
 +For example, '(time-add nil '(1 . 1000))' no longer warns that the
 +'(1 . 1000)' acts like '(1000 . 1000000)'.  This warning, which was a
 +temporary transition aid for Emacs 27, has served its purpose.
 +
- +++
 +** 'encode-time' now also accepts a 6-element list with just time and date.
 +'(encode-time (list SECOND MINUTE HOUR DAY MONTH YEAR))' is now short for
 +'(encode-time (list SECOND MINUTE HOUR DAY MONTH YEAR nil -1 nil))'.
 +
- +++
 +** 'date-to-time' now accepts arguments that lack month, day, or time.
 +The function now assumes the earliest possible values if its argument
 +lacks month, day, or time.  For example, (date-to-time "2021-12-04")
 +now assumes a time of "00:00" instead of signaling an error.
 +
- +++
 +** 'format-seconds' now allows suppressing zero-value trailing elements.
 +The new "%x" non-printing control character will suppress zero-value
 +elements that appear after "%x".
 +
- +++
 +** New events for taking advantage of touchscreen devices.
 +The events 'touchscreen-begin', 'touchscreen-update', and
 +'touchscreen-end' have been added to take better advantage of
 +touch-capable display panels.
 +
- +++
 +** New error symbol 'permission-denied'.
 +This is a subcategory of 'file-error', and is signaled when some file
 +operation fails because the OS doesn't allow Emacs to access a file or
 +a directory.
 +
- +++
 +** The ':underline' face attribute now accepts a new property.
 +The property ':position' now specifies the position of the underline
 +when used as part of a property list specification for the
 +':underline' attribute.
 +
- ---
 +** 'defalias' records a more precise history of definitions.
 +This is recorded in the 'function-history' symbol property.
 +
- ---
 +** New hook 'save-place-after-find-file-hook'.
 +This is called at the end of 'save-place-find-file-hook'.
 +
- ---
 +** 'indian-tml-base-table' no longer translates digits.
 +Use 'indian-tml-base-digits-table' if you want digits translation.
 +
- +++
 +** 'indian-tml-itrans-v5-hash' no longer translates digits.
 +Use 'indian-tml-itrans-digits-v5-hash' if you want digits
 +translation.
 +
- +++
 +** 'shell-quote-argument' has a new optional argument POSIX.
 +This is useful when quoting shell arguments for a remote shell
 +invocation.  Such shells are POSIX conformant by default.
 +
- +++
 +** 'make-process' can set connection type independently for input and output.
 +When calling 'make-process', communication via pty can be enabled
 +selectively for just input or output by passing a cons cell for
 +':connection-type', e.g. '(pipe . pty)'.  When examining a process
 +later, you can determine whether a particular stream for a process
 +uses a pty by passing one of 'stdin', 'stdout', or 'stderr' as the
 +second argument to 'process-tty-name'.
 +
- +++
 +** 'signal-process' now consults the list 'signal-process-functions'.
 +This is to determine which function has to be called in order to
 +deliver the signal.  This allows Tramp to send the signal to remote
 +asynchronous processes.  The hitherto existing implementation has been
 +moved to 'internal-default-signal-process'.
 +
- +++
 +** Some system information functions honor remote systems now.
 +'list-system-processes' returns remote process IDs.
 +'memory-info' returns memory information of remote systems.
 +'process-attributes' expects a remote process ID.
 +This happens only when the current buffer's 'default-directory' is
 +remote.  In order to preserve the old behavior, bind
 +'default-directory' to a local directory, like
 +
 +    (let ((default-directory temporary-file-directory))
 +      (list-system-processes))
 +
- ---
 +** New functions 'take' and 'ntake'.
 +'(take N LIST)' returns the first N elements of LIST; 'ntake' does
 +the same but works by modifying LIST destructively.
 +
- +++
 +** 'string-split' is now an alias for 'split-string'.
 +
- +++
 +** 'format-spec' now accepts functions in the replacement.
 +The function is called only when used in the format string.  This is
 +useful to avoid side-effects such as prompting, when the value is not
 +actually being used for anything.
 +
- +++
 +** The variable 'max-specpdl-size' has been made obsolete.
 +Now 'max-lisp-eval-depth' alone is used for limiting Lisp recursion
 +and stack usage.  'max-specpdl-size' is still present as a plain
 +variable for compatibility but its limiting powers have been taken away.
 +
 +** New function 'external-completion-table'.
 +This function returns a completion table designed to ease
 +communication between Emacs's completion facilities and external tools
 +offering completion services, particularly tools whose full working
 +set is too big to transfer to Emacs every time a completion is
 +needed.  The table uses new 'external' completion style exclusively
 +and cannot work with regular styles such as 'basic' or 'flex'.
 +
- +++
 +** Magic file name handlers for 'make-directory-internal' are no longer needed.
 +Instead, Emacs uses the already-existing 'make-directory' handlers.
 +
- ---
 +** '(make-directory DIR t)' returns non-nil if DIR already exists.
 +This can let a caller know whether it created DIR.  Formerly,
 +'make-directory's return value was unspecified.
 +
 +\f
 +* Changes in Emacs 29.1 on Non-Free Operating Systems
 +
 +** MS-Windows
 +
- +++
 +*** Emacs now supports double-buffering on MS-Windows to reduce display flicker.
 +(This was supported on Free systems since Emacs 26.1.)
 +
 +To disable double-buffering (e.g., if it causes display problems), set
 +the frame parameter 'inhibit-double-buffering' to a non-nil value.
 +You can do that either by adding
 +
 +    '(inhibit-double-buffering . t)
 +
 +to 'default-frame-alist', or by modifying the frame parameters of the
 +selected frame by evaluating
 +
 +    (modify-frame-parameters nil '((inhibit-double-buffering . t)))
 +
- ---
 +*** Emacs now supports system dark mode.
 +On Windows 10 (version 1809 and higher) and Windows 11, Emacs will now
 +follow the system's dark mode: GUI frames use the appropriate light or
 +dark title bar and scroll bars, based on the user's Windows-wide color
 +settings.
 +
- +++
 +*** Emacs now uses native image APIs to display some image formats.
 +On Windows 2000 and later, Emacs now defaults to using the native
 +image APIs for displaying the BMP, GIF, JPEG, PNG, and TIFF images.
 +This means Emacs on MS-Windows needs no longer use external image
 +support libraries to display those images.  Other image types -- XPM,
 +SVG, and WEBP -- still need support libraries for Emacs to be able to
 +display them.
 +
 +The use of native image APIs is controlled by the variable
 +'w32-use-native-image-API', whose value now defaults to t on systems
 +where those APIs are available.
 +
- ---
 +*** Emacs now supports display of BMP images using native image APIs.
 +When 'w32-use-native-image-API' is non-nil, Emacs on MS-Windows now
 +has built-in support for displaying BMP images.
 +
- ---
 +*** GUI Yes/No dialogs now include a "Cancel" button.
 +The "Cancel" button is in addition to "Yes" and "No", and is intended
 +to allow users to quit the dialog, as an equivalent of 'C-g' when Emacs
 +asks a yes/no question via the echo area.  This is controlled by the
 +new variable 'w32-yes-no-dialog-show-cancel', by default t.  Set it to
 +nil to get back the old behavior of showing a modal dialog with only
 +two buttons: "Yes" and "No".
 +
 +** Cygwin
 +
- +++
 +*** 'process-attributes' is now implemented.
 +
 +** macOS
 +
 +*** The 'ns-popup-font-panel' command has been removed.
 +Use the general command 'M-x menu-set-font' instead.
 +
 +\f
 +----------------------------------------------------------------------
 +This file is part of GNU Emacs.
 +
 +GNU Emacs is free software: you can redistribute it and/or modify
 +it under the terms of the GNU General Public License as published by
 +the Free Software Foundation, either version 3 of the License, or
 +(at your option) any later version.
 +
 +GNU Emacs is distributed in the hope that it will be useful,
 +but WITHOUT ANY WARRANTY; without even the implied warranty of
 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +GNU General Public License for more details.
 +
 +You should have received a copy of the GNU General Public License
 +along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
 +
 +\f
 +Local variables:
 +coding: utf-8
 +mode: outline
 +mode: emacs-news
 +paragraph-separate: "[         \f]"
 +end:
diff --cc etc/PROBLEMS
Simple merge
diff --cc exec/exec.c
index 0d9187cabfadedae1253869f98eeeaed4e307612,0000000000000000000000000000000000000000..935c94a59af55ba431decadfecb7ac92feb8482c
mode 100644,000000..100644
--- /dev/null
@@@ -1,1235 -1,0 +1,1235 @@@
-       
 +/* Program execution for Emacs.
 +
 +Copyright (C) 2023 Free Software Foundation, Inc.
 +
 +This file is part of GNU Emacs.
 +
 +GNU Emacs is free software: you can redistribute it and/or modify
 +it under the terms of the GNU General Public License as published by
 +the Free Software Foundation, either version 3 of the License, or (at
 +your option) any later version.
 +
 +GNU Emacs is distributed in the hope that it will be useful,
 +but WITHOUT ANY WARRANTY; without even the implied warranty of
 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +GNU General Public License for more details.
 +
 +You should have received a copy of the GNU General Public License
 +along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 +
 +#include <config.h>
 +
 +#include <errno.h>
 +#include <unistd.h>
 +#include <fcntl.h>
 +#include <assert.h>
 +#include <string.h>
 +#include <ctype.h>
 +#include <stdlib.h>
 +
 +#include <sys/ptrace.h>
 +#include <sys/param.h>
 +#include <sys/mman.h>
 +
 +#include "exec.h"
 +
 +#if defined __mips__ && !defined MIPS_NABI
 +#include "mipsfpu.h"
 +#endif /* defined __mips__ && !defined MIPS_NABI */
 +
 +\f
 +
 +
 +/* Define replacements for required string functions.  */
 +
 +#if !defined HAVE_STPCPY || !defined HAVE_DECL_STPCPY
 +
 +/* Copy SRC to DEST, returning the address of the terminating '\0' in
 +   DEST.  */
 +
 +static char *
 +rpl_stpcpy (char *dest, const char *src)
 +{
 +  register char *d;
 +  register const char *s;
 +
 +  d = dest;
 +  s = src;
 +
 +  do
 +    *d++ = *s;
 +  while (*s++ != '\0');
 +
 +  return d - 1;
 +}
 +
 +#define stpcpy rpl_stpcpy
 +#endif /* !defined HAVE_STPCPY || !defined HAVE_DECL_STPCPY */
 +
 +#if !defined HAVE_STPNCPY || !defined HAVE_DECL_STPNCPY
 +
 +/* Copy no more than N bytes of SRC to DST, returning a pointer past
 +   the last non-NUL byte written into DST.  */
 +
 +static char *
 +rpl_stpncpy (char *dest, const char *src, size_t n)
 +{
 +  char c, *s;
 +  size_t n4;
 +
 +  s = dest;
 +
 +  if (n >= 4)
 +    {
 +      n4 = n >> 2;
 +
 +      for (;;)
 +      {
 +        c = *src++;
 +        *dest++ = c;
 +        if (c == '\0')
 +          break;
 +        c = *src++;
 +        *dest++ = c;
 +        if (c == '\0')
 +          break;
 +        c = *src++;
 +        *dest++ = c;
 +        if (c == '\0')
 +          break;
 +        c = *src++;
 +        *dest++ = c;
 +        if (c == '\0')
 +          break;
 +        if (--n4 == 0)
 +          goto last_chars;
 +      }
 +      n -= dest - s;
 +      goto zero_fill;
 +    }
 +
 + last_chars:
 +  n &= 3;
 +  if (n == 0)
 +    return dest;
 +
 +  for (;;)
 +    {
 +      c = *src++;
 +      --n;
 +      *dest++ = c;
 +      if (c == '\0')
 +      break;
 +      if (n == 0)
 +      return dest;
 +    }
 +
 + zero_fill:
 +  while (n-- > 0)
 +    dest[n] = '\0';
 +
 +  return dest - 1;
 +}
 +
 +#define stpncpy rpl_stpncpy
 +#endif /* !defined HAVE_STPNCPY || !defined HAVE_DECL_STPNCPY */
 +
 +\f
 +
 +/* Executable reading functions.
 +   These functions extract information from an executable that is
 +   about to be loaded.
 +
 +   `exec_0' takes the name of the program, determines whether or not
 +   its format is correct, and if so, returns the list of actions that
 +   the loader should perform.
 +
 +   The actions include:
 +
 +     - Making the stack executable, if PT_GNU_STACK.
 +     - Mapping PT_LOAD sections into the executable with the correct
 +       memory protection.
 +     - On MIPS, setting the floating point register size.
 +     - Transferring control to the interpreter or executable.  */
 +\f
 +
 +/* Check whether or not FD starts with a #!, and return the executable
 +   to load if it does.  Value is NAME if no interpreter character was
 +   found, or the interpreter otherwise.  Value is NULL upon an IO
 +   error.
 +
 +   If an additional command line argument is specified, place it in
 +   *EXTRA.  */
 +
 +static const char *
 +check_interpreter (const char *name, int fd, const char **extra)
 +{
 +  static char buffer[PATH_MAX], *start;
 +  char first[2], *end, *ws;
 +  ssize_t rc;
 +
 +  /* Read the first character.  */
 +  rc = read (fd, &first, 2);
 +
 +  if (rc != 2)
 +    goto fail;
 +
 +  if (first[0] != '#' || first[1] != '!')
 +    goto nomatch;
 +
 +  rc = read (fd, buffer, PATH_MAX);
 +
 +  if (rc < 0)
 +    goto fail;
 +
 +  /* Strip leading whitespace.  */
 +  start = buffer;
 +  while (*start && ((unsigned char) *start) < 128 && isspace (*start))
 +    ++start;
 +
 +  /* Look for a newline character.  */
 +  end = memchr (start, '\n', rc);
 +
 +  if (!end)
 +    goto fail;
 +
 +  /* The string containing the interpreter is now in start.  NULL
 +     terminate it.  */
 +  *end = '\0';
 +
 +  /* Now look for any whitespace characters.  */
 +  ws = strchr (start, ' ');
 +
 +  /* If there's no whitespace, return the entire start.  */
 +
 +  if (!ws)
 +    {
 +      if (lseek (fd, 0, SEEK_SET))
 +      goto fail;
 +
 +      return start;
 +    }
 +
 +  /* Otherwise, split the string at the whitespace and return the
 +     additional argument.  */
 +  *ws = '\0';
 +
 +  if (lseek (fd, 0, SEEK_SET))
 +    goto fail;
 +
 +  *extra = ws + 1;
 +  return start;
 +
 + nomatch:
 +  /* There's no interpreter.  */
 +  if (lseek (fd, 0, SEEK_SET))
 +    goto fail;
 +
 +  return name;
 +
 + fail:
 +  errno = ENOEXEC;
 +  return NULL;
 +}
 +
 +/* Static area used to store data placed on the loader's stack.  */
 +static char loader_area[65536];
 +
 +/* Number of bytes used in that area.  */
 +static int loader_area_used;
 +
 +\f
 +
 +/* Structure definitions for commands placed in the loader area.
 +   Arrange these so that each member is naturally aligned.  */
 +
 +struct exec_open_command
 +{
 +  /* Word identifying the type of this command.  */
 +  USER_WORD command;
 +
 +  /* NULL-terminated file name follows, padded to the size of a user
 +     word.  */
 +};
 +
 +struct exec_map_command
 +{
 +  /* Word identifying the type of this command.  */
 +  USER_WORD command;
 +
 +  /* Where the file will be mapped.  */
 +  USER_WORD vm_address;
 +
 +  /* Offset into the file to map from.  */
 +  USER_WORD file_offset;
 +
 +  /* Memory protection for mprotect.  */
 +  USER_WORD protection;
 +
 +  /* Number of bytes to be mapped.  */
 +  USER_WORD length;
 +
 +  /* Flags for mmap.  */
 +  USER_WORD flags;
 +
 +  /* Number of bytes to clear at the end of this mapping.  */
 +  USER_WORD clear;
 +};
 +
 +struct exec_jump_command
 +{
 +  /* Word identifying the type of this command.  */
 +  USER_WORD command;
 +
 +  /* Address to jump to.  */
 +  USER_WORD entry;
 +
 +  /* The value of AT_ENTRY inside the aux vector.  */
 +  USER_WORD at_entry;
 +
 +  /* The value of AT_PHENT inside the aux vector.  */
 +  USER_WORD at_phent;
 +
 +  /* The value of AT_PHNUM inside the aux vector.  */
 +  USER_WORD at_phnum;
 +
 +  /* The value of AT_PHDR inside the aux vector.  */
 +  USER_WORD at_phdr;
 +
 +  /* The value of AT_BASE inside the aux vector.  */
 +  USER_WORD at_base;
 +
 +#if defined __mips__ && !defined MIPS_NABI
 +  /* The FPU mode to apply.  */
 +  USER_WORD fpu_mode;
 +#endif /* defined __mips__ && !defined MIPS_NABI */
 +};
 +
 +\f
 +
 +/* Write a command to open the file NAME to the loader area.
 +   If ALTERNATE is true, then use the command code 16 instead
 +   of 0.  Value is 1 upon failure, else 0.  */
 +
 +static int
 +write_open_command (const char *name, bool alternate)
 +{
 +  struct exec_open_command command;
 +  size_t size;
 +
 +  /* First, write the command to open NAME.  This is followed by NAME
 +     itself, padded to sizeof (USER_WORD) bytes.  */
 +
 +  command.command = alternate ? 16 : 0;
 +  if (sizeof loader_area - loader_area_used < sizeof command)
 +    return 1;
 +  memcpy (loader_area + loader_area_used, &command, sizeof command);
 +  loader_area_used += sizeof command;
 +
 +  /* Calculate the length of NAME.  */
 +  size = strlen (name) + 1;
 +
 +  /* Round it up.  */
 +  size = ((size + (sizeof (USER_WORD) - 1))
 +        & ~(sizeof (USER_WORD) - 1));
 +
 +  if (sizeof loader_area - loader_area_used < size)
 +    return 1;
 +
 +  /* Now copy name to the loader area, filling the padding with NULL
 +     bytes.  */
 +  strncpy (loader_area + loader_area_used, name, size);
 +
 +  /* Increase loader_area_used.  */
 +  loader_area_used += size;
 +  return 0;
 +}
 +
 +/* Write the commands necessary to map the executable file into memory
 +   for the given PT_LOAD program HEADER.  Value is 1 upon failure,
 +   else 0.  If USE_ALTERNATE, use the command code 17 instead of
 +   1.
 +
 +   Apply the given OFFSET to virtual addresses that will be mapped.  */
 +
 +static int
 +write_load_command (program_header *header, bool use_alternate,
 +                  USER_WORD offset)
 +{
 +  struct exec_map_command command;
 +  struct exec_map_command command1;
 +  USER_WORD start, end;
 +  bool need_command1;
 +  static long pagesize;
 +
 +  /* First, write the commands necessary to map the specified segment
 +     itself.
 +
 +     This is the area between header->p_vaddr and header->p_filesz,
 +     rounded up to the page size.  */
 +
 +#ifndef PAGE_MASK
 +  /* This system doesn't define a fixed page size.  */
 +
 +#ifdef HAVE_GETPAGESIZE
 +  if (!pagesize)
 +    pagesize = getpagesize ();
 +#else /* HAVE_GETPAGESIZE */
 +  if (!pagesize)
 +    pagesize = sysconf (_SC_PAGESIZE);
 +
 +#define PAGE_MASK (~(pagesize - 1))
 +#define PAGE_SIZE (pagesize)
 +#endif /* HAVE_GETPAGESIZE */
 +#endif /* PAGE_MASK */
 +
 +  start = header->p_vaddr & PAGE_MASK;
 +  end = ((header->p_vaddr + header->p_filesz
 +        + PAGE_SIZE)
 +       & PAGE_MASK);
 +
 +  command.command = use_alternate ? 17 : 1;
 +  command.vm_address = start;
 +  command.file_offset = header->p_offset & PAGE_MASK;
 +  command.protection = 0;
 +  command.length = end - start;
 +  command.clear = 0;
 +  command.flags = MAP_PRIVATE | MAP_FIXED;
 +
 +  /* Apply the memory protection specified in the header.  */
 +
 +  if (header->p_flags & 4) /* PF_R */
 +    command.protection |= PROT_READ;
 +
 +  if (header->p_flags & 2) /* PF_W */
 +    command.protection |= PROT_WRITE;
 +
 +  if (header->p_flags & 1) /* PF_X */
 +    command.protection |= PROT_EXEC;
 +
 +  /* Next, write any command necessary to map pages in the area
 +     between p_filesz and p_memsz.  */
 +  need_command1 = false;
 +
 +  if (header->p_memsz > header->p_filesz)
 +    {
 +      /* If there are bytes after end which need to be initialized, do
 +       that now.  */
 +      command.clear = end - header->p_vaddr - header->p_filesz;
 +      start = end;
 +      end = header->p_vaddr + header->p_memsz + PAGE_SIZE;
 +      end &= PAGE_MASK;
 +
 +      if (end > start)
 +      {
 +        command1.command = 4;
 +        command1.vm_address = start;
 +        command1.file_offset = 0;
 +        command1.length = end - start;
 +        command1.clear = 0;
 +        command1.protection = command.protection;
 +        command1.flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED;
 +        need_command1 = true;
 +      }
 +    }
 +
 +  /* Apply the offset to both commands if necessary.  */
 +
 +  if (offset)
 +    {
 +      if (need_command1)
 +      command1.vm_address += offset;
 +
 +      command.vm_address += offset;
 +    }
 +
 +  /* Write both commands.  */
 +
 +  if (sizeof loader_area - loader_area_used < sizeof command)
 +    return 1;
 +
 +  memcpy (loader_area + loader_area_used, &command,
 +        sizeof command);
 +  loader_area_used += sizeof command;
 +
 +  if (!need_command1)
 +    return 0;
 +
 +  if (sizeof loader_area - loader_area_used < sizeof command1)
 +    return 1;
 +
 +  memcpy (loader_area + loader_area_used, &command1,
 +        sizeof command1);
 +  loader_area_used += sizeof command1;
 +
 +  return 0;
 +}
 +
 +#if defined __mips__ && !defined MIPS_NABI
 +
 +/* Static storage used for MIPS ABI flags.  */
 +static struct mips_elf_abi_flags exec_abi, interpreter_abi;
 +
 +/* Static storage for interpreter headers.  */
 +static elf_header exec_interpreter_header;
 +
 +/* Pointer to the ELF header of this executable's interpreter.  */
 +static elf_header *interpreter_header;
 +
 +/* Pointer to any PT_MIPS_ABIFLAGS program header found in the
 +   executable itself.  */
 +static struct mips_elf_abi_flags *exec_abiflags;
 +
 +/* Pointer to any PT_MIPS_ABIFLAGS program header found in the
 +   executable's ELF interpreter.  */
 +static struct mips_elf_abi_flags *interpreter_abiflags;
 +
 +#endif /* defined __mips__ && !defined MIPS_NABI */
 +
 +/* Process the specified program HEADER; HEADER is from the ELF
 +   interpreter of another executable.  FD is the executable file from
 +   which it is being read, NAME is its file name, and ELF_HEADER is
 +   its header.
 +
 +   If ELF_HEADER->e_type is ET_DYN, add the base address for position
 +   independent interpreter code to virtual addresses.
 +
 +   Value is 1 upon failure, else 0.  */
 +
 +static int
 +process_interpreter_1 (const char *name, int fd,
 +                     program_header *header,
 +                     elf_header *elf_header)
 +{
 +  int rc;
 +#if defined __mips__ && !defined MIPS_NABI
 +  ssize_t rc1;
 +#endif /* defined __mips__ && !defined MIPS_NABI */
 +
 +  switch (header->p_type)
 +    {
 +    default: /* PT_NULL, PT_NOTE, PT_DYNAMIC, PT_INTERP, et cetera */
 +      rc = 0;
 +      break;
 +
 +    case 1: /* PT_LOAD */
 +      /* This describes a segment in the file that must be loaded.
 +       Write the appropriate load command.  */
 +
 +      if (elf_header->e_type == 3) /* ET_DYN */
 +      rc = write_load_command (header, true,
 +                               INTERPRETER_BASE);
 +      else
 +      rc = write_load_command (header, true, 0);
 +
 +      break;
 +
 +#if defined __mips__ && !defined MIPS_NABI
 +    case 0x70000003: /* PT_MIPS_ABIFLAGS */
 +      /* Record this header for later use.  */
 +      rc1 = pread (fd, &interpreter_abi, sizeof interpreter_abi,
 +                 header->p_offset);
 +
 +      if (rc1 != sizeof interpreter_abi)
 +      return 1;
 +
 +      interpreter_abiflags = &interpreter_abi;
 +      rc = 0;
 +#endif /* defined __mips__ && !defined MIPS_NABI */
 +    }
 +
 +  return rc;
 +}
 +
 +/* Read the ELF interpreter specified in the given program header from
 +   FD, and append the commands necessary to load it to the load area.
 +   Then, return the interpreter entry point in *ENTRY.
 +
 +   Value is 1 upon failure, else 0.  */
 +
 +static int
 +process_interpreter (int fd, program_header *prog_header,
 +                   USER_WORD *entry)
 +{
 +  char buffer[PATH_MAX + 1];
 +  int rc, size, i;
 +  elf_header header;
 +  program_header program;
 +
 +  /* Read the interpreter name.  */
 +  size = MIN (prog_header->p_filesz, PATH_MAX);
 +  rc = pread (fd, buffer, size, prog_header->p_offset);
 +  if (rc < size)
 +    return 1;
 +
 +  /* Make sure the name is NULL terminated.  */
 +  buffer[size] = '\0';
 +
 +  /* Check if the file is executable.  This is unfortunately not
 +     atomic.  */
 +
 +  if (access (buffer, X_OK))
 +    return 1;
 +
 +  /* Read the interpreter's header much like exec_0.
 +
 +     However, use special command codes in `process_program_header' if
 +     it is position independent.  That way, the loader knows it should
 +     use the open interpreter instead.  */
 +
 +  fd = open (buffer, O_RDONLY);
 +
 +  if (fd < 0)
 +    return 1;
 +
 +  rc = read (fd, &header, sizeof header);
 +
 +  if (rc < sizeof header)
 +    goto fail;
 +
 +#if defined __mips__ && !defined MIPS_NABI
 +  /* Record this interpreter's header for later use determining the
 +     floating point ABI.  */
 +  exec_interpreter_header = header;
 +  interpreter_header = &exec_interpreter_header;
 +#endif /* defined __mips__ && !defined MIPS_NABI */
 +
 +  /* Verify that this is indeed an ELF file.  */
 +
 +  if (header.e_ident[0] != 0x7f
 +      || header.e_ident[1] != 'E'
 +      || header.e_ident[2] != 'L'
 +      || header.e_ident[3] != 'F')
 +    goto fail;
 +
 +  /* Now check that the class is correct.  */
 +#ifdef EXEC_64
 +  if (header.e_ident[4] != 2)
 +    goto fail;
 +#else /* !EXEC_64 */
 +  if (header.e_ident[4] != 1)
 +    goto fail;
 +#endif /* EXEC_64 */
 +
 +  /* And the endianness.  */
 +#ifndef WORDS_BIGENDIAN
 +  if (header.e_ident[5] != 1)
 +    goto fail;
 +#else /* WORDS_BIGENDIAN */
 +  if (header.e_ident[5] != 2)
 +    goto fail;
 +#endif /* EXEC_64 */
 +
 +  /* Check that this is an executable.  */
 +  if (header.e_type != 2 && header.e_type != 3)
 +    goto fail;
 +
 +  /* Now check that the ELF program header makes sense.  */
 +  if (header.e_phnum > 0xffff
 +      || (header.e_phentsize
 +        != sizeof (program_header)))
 +    goto fail;
 +
 +  if (write_open_command (buffer, true))
 +    goto fail;
 +
 +  for (i = 0; i < header.e_phnum; ++i)
 +    {
 +      rc = read (fd, &program, sizeof program);
 +      if (rc < sizeof program)
 +      goto fail;
 +
 +      if (process_interpreter_1 (buffer, fd, &program,
 +                               &header))
 +      goto fail;
 +    }
 +
 +  if (header.e_type == 3) /* ET_DYN */
 +    *entry = header.e_entry + INTERPRETER_BASE;
 +  else
 +    *entry = header.e_entry;
 +
 +  close (fd);
 +  return 0;
 +
 + fail:
 +  close (fd);
 +  return 1;
 +}
 +
 +/* Process the specified program HEADER.  FD is the executable file
 +   from which it is being read, NAME is its file name, and ELF_HEADER
 +   is its header.
 +
 +   If ELF_HEADER->e_type is ET_DYN, add the base address for position
 +   independent code to virtual addresses.
 +
 +   If OFFSET is non-NULL, and *OFFSET is -1, write the virtual address
 +   of HEADER if it describes a PT_LOAD segment.
 +
 +   If an interpreter is found, set *ENTRY to its entry point.
 +
 +   Value is 1 upon failure, else 0.  */
 +
 +static int
 +process_program_header (const char *name, int fd,
 +                      program_header *header,
 +                      elf_header *elf_header,
 +                      USER_WORD *entry,
 +                      USER_WORD *offset)
 +{
 +  int rc;
 +#if defined __mips__ && !defined MIPS_NABI
 +  ssize_t rc1;
 +#endif /* defined __mips__ && !defined MIPS_NABI */
 +
 +  switch (header->p_type)
 +    {
 +    default: /* PT_NULL, PT_NOTE, PT_DYNAMIC, et cetera */
 +      rc = 0;
 +      break;
 +
 +    case 1: /* PT_LOAD */
 +      /* This describes a segment in the file that must be loaded.
 +       Write the appropriate load command.  */
 +
 +      if (elf_header->e_type == 3) /* ET_DYN */
 +      {
 +        rc = write_load_command (header, false,
 +                                 EXECUTABLE_BASE);
 +
 +        if (!rc && offset && *offset == (USER_WORD) -1)
 +          *offset = EXECUTABLE_BASE + header->p_vaddr;
 +      }
 +      else
 +      {
 +        rc = write_load_command (header, false, 0);
 +
 +        if (!rc && offset && *offset == (USER_WORD) -1)
 +          *offset = header->p_vaddr;
 +      }
 +
 +      break;
 +
 +    case 3: /* PT_INTERP */
 +      /* This describes another executable that must be loaded.  Open
 +       the interpreter and process each of its headers as well.  */
 +      rc = process_interpreter (fd, header, entry);
 +      break;
 +
 +    case 1685382481: /* PT_GNU_STACK */
 +      /* TODO */
 +      rc = 0;
 +      break;
 +
 +#if defined __mips__ && !defined MIPS_NABI
 +    case 0x70000003: /* PT_MIPS_ABIFLAGS */
 +      /* Record this header for later use.  */
 +      rc1 = pread (fd, &exec_abi, sizeof exec_abi,
 +                 header->p_offset);
 +
 +      if (rc1 != sizeof exec_abi)
 +      return 1;
 +
 +      exec_abiflags = &exec_abi;
 +      rc = 0;
 +#endif /* defined __mips__ && !defined MIPS_NABI */
 +    }
 +
 +  return rc;
 +}
 +
 +/* Prepend one or two extra arguments ARG1 and ARG2 to a pending
 +   execve system call.  Replace the argument immediately after
 +   with ARG3.
 +
 +   TRACEE is the tracee performing the system call, and REGS are its
 +   current user registers.  Value is 1 upon failure, else 0.  */
 +
 +static int
 +insert_args (struct exec_tracee *tracee, USER_REGS_STRUCT *regs,
 +           const char *arg1, const char *arg2, const char *arg3)
 +{
 +  USER_WORD argv, argc, word, new;
 +  USER_WORD new1, new2, new3, i;
 +  size_t text_size, effective_size;
 +  USER_REGS_STRUCT original;
 +
 +  /* First, get a pointer to the current argument vector.  */
 +  argv = regs->SYSCALL_ARG1_REG;
 +
 +  /* Now figure out how many arguments there are.  */
 +  argc = 0;
 +  while (true)
 +    {
 +      /* Clear errno.  PTRACE_PEEKDATA returns the word read the same
 +       way failure indications are returned, so the only way to
 +       catch IO errors is by clearing errno before the call to
 +       ptrace and checking it afterwards.  */
 +
 +      errno = 0;
 +      word = ptrace (PTRACE_PEEKDATA, tracee->pid,
 +                   (void *) argv, NULL);
 +      argv += sizeof (USER_WORD);
 +
 +      if (errno)
 +      return 1;
 +
 +      if (!word)
 +      break;
 +
 +      ++argc;
 +    };
 +
 +  /* Allocate enough to hold that many arguments, alongside the argc
 +     text.  */
 +
 +  text_size = (strlen (arg1) + 1
 +             + (arg2 ? strlen (arg2) + 1 : 0)
 +             + strlen (arg3) + 1);
 +
 +  /* Round it up to the user word size.  */
 +  text_size += sizeof (USER_WORD) - 1;
 +  text_size &= ~(sizeof (USER_WORD) - 1);
 +
 +  /* Now allocate the new argv.  Make sure argc is at least 1; it
 +     needs to hold ARG3.  */
 +
 +  effective_size = sizeof word * (MAX (1, argc) + 2) + text_size;
 +
 +  if (arg2)
 +    effective_size += sizeof word;
 +
 +  /* Copy regs to original so that user_alloca knows it should append
 +     the ABI red zone.  */
 +
 +  memcpy (&original, regs, sizeof *regs);
 +  new = user_alloca (tracee, &original, regs,
 +                   effective_size);
 +
 +  if (!new)
 +    goto fail;
 +
 +  /* Figure out where argv starts.  */
 +
 +  new3 = new + text_size;
 +
 +  /* Now write the first two strings.  */
 +
 +  new1 = new + strlen (arg1) + 1;
 +  new2 = new1 + (arg2 ? strlen (arg2) + 1 : 0);
 +
 +  if (user_copy (tracee, (const unsigned char *) arg1,
 +               new, new1 - new))
 +    goto fail;
 +
 +  if (arg2 && user_copy (tracee, (const unsigned char *) arg2,
 +                       new1, new2 - new1))
 +    goto fail;
 +
 +  /* Write the replacement arg3, the file name of the executable.  */
 +
 +  if (user_copy (tracee, (const unsigned char *) arg3,
 +               new2, new3 - new2))
 +    goto fail;
 +
 +  /* Start copying argv back to new2.  First, write the one or two new
 +     arguments.  */
 +
 +  if (ptrace (PTRACE_POKETEXT, tracee->pid,
 +            (void *) new3, (void *) new))
 +    goto fail;
 +
 +  new3 += sizeof new3;
 +
 +  if (arg2 && ptrace (PTRACE_POKETEXT, tracee->pid,
 +                    (void *) new3, (void *) new1))
 +    goto fail;
 +  else if (arg2)
 +    new3 += sizeof new3;
 +
 +  /* Next, write the third argument.  */
 +
 +  if (ptrace (PTRACE_POKETEXT, tracee->pid, (void *) new3,
 +            (void *) new2))
 +    goto fail;
 +
 +  new3 += sizeof new3;
 +
 +  /* Copy the remaining arguments back.  */
 +
 +  argv = regs->SYSCALL_ARG1_REG;
 +
 +  if (argc)
 +    {
 +      /* Make sure the trailing NULL is included.  */
 +      argc += 1;
 +
 +      /* Now copy each argument in argv, starting from argv[1].  */
 +
 +      for (i = 1; i < argc; ++i)
 +      {
 +        /* Read one argument.  */
 +        word = ptrace (PTRACE_PEEKDATA, tracee->pid,
 +                       (void *) (argv + i * sizeof argv), NULL);
 +
 +        /* Write one argument, then increment new3.  */
 +
 +        if (ptrace (PTRACE_POKETEXT, tracee->pid,
 +                    (void *) new3, (void *) word))
 +          goto fail;
 +
 +        new3 += sizeof new3;
 +      }
 +    }
 +  else
 +    {
 +      /* Just write the trailing NULL.  */
 +
 +      if (ptrace (PTRACE_POKETEXT, tracee->pid,
 +                (void *) new3, (void *) 0))
 +      goto fail;
 +
 +      new3 += sizeof new3;
 +    }
 +
 +  /* Assert that new3 is not out of bounds.  */
 +  assert (new3 == new + effective_size);
 +
 +  /* And that it is properly aligned.  */
 +  assert (!(new3 & (sizeof new3 - 2)));
 +
 +  /* Now modify the system call argument to point to new +
 +     text_size.  */
 +
 +  regs->SYSCALL_ARG1_REG = new + text_size;
 +
 +#ifdef __aarch64__
 +  if (aarch64_set_regs (tracee->pid, regs, false))
 +    goto fail;
 +#else /* !__aarch64__ */
 +  if (ptrace (PTRACE_SETREGS, tracee->pid, NULL, regs))
 +    goto fail;
 +#endif /* __aarch64__ */
 +
 +  /* Success.  */
 +
 +  return 0;
 +
 + fail:
 +  /* Restore the original stack pointer.  */
 +#ifdef __aarch64__
 +  aarch64_set_regs (tracee->pid, &original, false);
 +#else /* !__aarch64__ */
 +  ptrace (PTRACE_SETREGS, tracee->pid, NULL, &original);
 +#endif /* __aarch64__ */
 +  errno = ENOMEM;
 +  return 1;
 +}
 +
 +\f
 +
 +/* Format PID, an unsigned process identifier, in base 10.  Place the
 +   result in *IN, and return a pointer to the byte after the
 +   result.  REM should be NULL.  */
 +
 +static char *
 +format_pid (char *in, unsigned int pid)
 +{
 +  unsigned int digits[32], *fill;
 +
 +  fill = digits;
 +
 +  for (; pid != 0; pid = pid / 10)
 +    *fill++ = pid % 10;
 +
 +  /* Insert 0 if the number would otherwise be empty.  */
 +
 +  if (fill == digits)
 +    *fill++ = 0;
 +
 +  while (fill != digits)
 +    {
 +      --fill;
 +      *in++ = '0' + *fill;
 +    }
 +
 +  *in = '\0';
 +  return in;
 +}
 +
 +/* Return a sequence of actions required to load the executable under
 +   the file NAME for the given TRACEE.  First, see if the file starts
 +   with #!; in that case, find the program to open and use that
 +   instead.
 +
 +   If REENTRANT is not defined, NAME is actually a buffer of size
 +   PATH_MAX + 80.  In that case, copy over the file name actually
 +   opened.
 +
 +   Next, read the executable header, and add the necessary memory
 +   mappings for each file.  Finally, return the action data and its
 +   size in *SIZE.
 +
 +   Finally, use REGS to add the required interpreter arguments to the
 +   caller's argv.
 +
 +   Value is NULL upon failure, with errno set accordingly.  */
 +
 +char *
 +exec_0 (char *name, struct exec_tracee *tracee,
 +      size_t *size, USER_REGS_STRUCT *regs)
 +{
 +  int fd, rc, i;
 +  elf_header header;
 +  const char *interpreter_name, *extra;
 +  program_header program;
 +  USER_WORD entry, program_entry, offset;
 +  USER_WORD header_offset;
 +  struct exec_jump_command jump;
 +#if defined __mips__ && !defined MIPS_NABI
 +  int fpu_mode;
 +#endif /* defined __mips__ && !defined MIPS_NABI */
 +  char buffer[80], buffer1[PATH_MAX + 80], *rewrite;
 +  ssize_t link_size;
 +  size_t remaining;
 +
 +  /* If the process is trying to run /proc/self/exe, make it run
 +     itself instead.  */
 +
 +  if (!strcmp (name, "/proc/self/exe") && tracee->exec_file)
 +    {
 +      strncpy (name, tracee->exec_file, PATH_MAX - 1);
 +      name[PATH_MAX] = '\0';
 +    }
 +  else
 +    {
 +      /* If name is not absolute, then make it relative to TRACEE's
 +       cwd.  Use stpcpy, as sprintf is not reentrant.  */
 +
 +      if (name[0] && name[0] != '/')
 +      {
 +        /* Clear `buffer'.  */
 +        memset (buffer, 0, sizeof buffer);
 +        memset (buffer1, 0, sizeof buffer);
 +
 +        /* Copy over /proc, the PID, and /cwd/.  */
 +        rewrite = stpcpy (buffer, "/proc/");
 +        rewrite = format_pid (rewrite, tracee->pid);
 +        strcpy (rewrite, "/cwd");
 +
 +        /* Resolve this symbolic link.  */
 +
 +        link_size = readlink (buffer, buffer1,
 +                              PATH_MAX + 1);
 +
 +        if (link_size < 0)
 +          return NULL;
 +
 +        /* Check that the name is a reasonable size.  */
 +
 +        if (link_size > PATH_MAX)
 +          {
 +            /* The name is too long.  */
 +            errno = ENAMETOOLONG;
 +            return NULL;
 +          }
 +
 +        /* Add a directory separator if necessary.  */
++
 +        if (!link_size || buffer1[link_size - 1] != '/')
 +          buffer1[link_size] = '/', link_size++;
 +
 +        rewrite = buffer1 + link_size;
 +        remaining = buffer1 + sizeof buffer1 - rewrite - 1;
 +        rewrite = stpncpy (rewrite, name, remaining);
 +
 +        /* Replace name with buffer1.  */
 +#ifndef REENTRANT
 +        strcpy (name, buffer1);
 +#endif /* REENTRANT */
 +      }
 +    }
 +
 +  /* Check that the file is accessible and executable.  */
 +
 +  if (access (name, X_OK))
 +    return NULL;
 +
 +  fd = open (name, O_RDONLY);
 +  if (fd < 0)
 +    return NULL;
 +
 +  /* Now read the header.  */
 +
 +  extra = NULL;
 +  interpreter_name = check_interpreter (name, fd, &extra);
 +  if (!interpreter_name)
 +    goto fail;
 +
 +  /* Open the interpreter instead, if necessary.  */
 +  if (interpreter_name != name)
 +    {
 +      close (fd);
 +      fd = open (interpreter_name, O_RDONLY);
 +      if (fd < 0)
 +      return NULL;
 +
 +      /* Now, rewrite the argument list to include `interpreter_name'
 +       and perhaps `extra'.  */
 +
 +      if (insert_args (tracee, regs, interpreter_name,
 +                     extra, name))
 +      goto fail1;
 +    }
 +
 +  rc = read (fd, &header, sizeof header);
 +
 +  if (rc < sizeof header)
 +    goto fail1;
 +
 +  /* Verify that this is indeed an ELF file.  */
 +
 +  if (header.e_ident[0] != 0x7f
 +      || header.e_ident[1] != 'E'
 +      || header.e_ident[2] != 'L'
 +      || header.e_ident[3] != 'F')
 +    goto fail1;
 +
 +  /* Now check that the class is correct.  */
 +#ifdef EXEC_64
 +  if (header.e_ident[4] != 2)
 +    goto fail1;
 +#else /* !EXEC_64 */
 +  if (header.e_ident[4] != 1)
 +    goto fail1;
 +#endif /* EXEC_64 */
 +
 +  /* And the endianness.  */
 +#ifndef WORDS_BIGENDIAN
 +  if (header.e_ident[5] != 1)
 +    goto fail1;
 +#else /* WORDS_BIGENDIAN */
 +  if (header.e_ident[5] != 2)
 +    goto fail1;
 +#endif /* EXEC_64 */
 +
 +  /* Check that this is an executable.  */
 +  if (header.e_type != 2 && header.e_type != 3)
 +    goto fail1;
 +
 +  /* Now check that the ELF program header makes sense.  */
 +  if (header.e_phnum > 0xffff
 +      || (header.e_phentsize
 +        != sizeof (program_header)))
 +    goto fail1;
 +
 +  /* Seek to the first program header and read each one.  */
 +  rc = lseek (fd, header.e_phoff, SEEK_SET);
 +  if (rc < 0)
 +    goto fail1;
 +  loader_area_used = 0;
 +
 +  /* Write the command used to open the executable.  */
 +  if (write_open_command (interpreter_name, false))
 +    goto fail1;
 +
 +  /* Apply base addresses for PIC code.  */
 +
 +  if (header.e_type == 3) /* ET_DYN */
 +    offset = EXECUTABLE_BASE;
 +  else
 +    offset = 0;
 +
 +  /* entry and program_entry are initially the same, but entry may be
 +     set to that of the interpreter if one is present.  */
 +
 +  entry = header.e_entry + offset;
 +  program_entry = header.e_entry;
 +
 +#if defined __mips__ && !defined MIPS_NABI
 +  /* Clear MIPS ABI flags.  */
 +  exec_abiflags = NULL;
 +  interpreter_abiflags = NULL;
 +  interpreter_header = NULL;
 +#endif /* defined __mips__ && !defined MIPS_NABI */
 +
 +  /* Set header_offset to -1; `process_program_header' then updates it
 +     to that of the first mapping.  */
 +  header_offset = -1;
 +
 +  for (i = 0; i < header.e_phnum; ++i)
 +    {
 +      rc = read (fd, &program, sizeof program);
 +      if (rc < sizeof program)
 +      goto fail1;
 +
 +      if (process_program_header (interpreter_name, fd,
 +                                &program, &header,
 +                                &entry, &header_offset))
 +      goto fail1;
 +    }
 +
 +  /* Write the entry point and program entry.  */
 +
 +  jump.command = 3;
 +  jump.entry = entry;
 +
 +  /* Now calculate values for the aux vector.  */
 +
 +  jump.at_entry = program_entry + offset;
 +  jump.at_phent = header.e_phentsize;
 +  jump.at_phnum = header.e_phnum;
 +  jump.at_base = (entry == header.e_entry + offset
 +                ? EXECUTABLE_BASE
 +                : INTERPRETER_BASE);
 +
 +#if defined __mips__ && !defined MIPS_NABI
 +  /* Finally, calculate the FPU mode wanted by the executable.  */
 +
 +  if (determine_fpu_mode (&header, interpreter_header,
 +                        &fpu_mode, exec_abiflags,
 +                        interpreter_abiflags))
 +    /* N.B. that `determine_fpu_mode' sets errno.  */
 +    goto fail;
 +
 +  /* If the processor is too new to support FR0 operation, place the
 +     executable in floating point emulation mode.  */
 +
 +  if (fpu_mode == FP_FR0 && !cpu_supports_fr0_p ())
 +    fpu_mode = FP_FRE;
 +
 +  jump.fpu_mode = fpu_mode;
 +#endif /* defined __mips__ && !defined MIPS_NABI */
 +
 +  /* The offset used for at_phdr should be that of the first
 +     mapping.  */
 +
 +  if (header_offset == (USER_WORD) -1)
 +    header_offset = 0;
 +
 +  jump.at_phdr = header.e_phoff + header_offset;
 +
 +  if (sizeof loader_area - loader_area_used < sizeof jump)
 +    goto fail1;
 +
 +  memcpy (loader_area + loader_area_used, &jump,
 +        sizeof jump);
 +  loader_area_used += sizeof jump;
 +
 +  /* Close the file descriptor and return the number of bytes
 +     used.  */
 +
 +  close (fd);
 +  *size = loader_area_used;
 +
 +  /* Make sure the loader area is properly aligned.  */
 +  assert (!(loader_area_used & (sizeof (USER_WORD) - 1)));
 +  return loader_area;
 +
 + fail1:
 +  errno = ENOEXEC;
 + fail:
 +  close (fd);
 +  return NULL;
 +}
index dc3f98eb4e7491f542940912745996323680c7d8,0000000000000000000000000000000000000000..9c5a445c9aa209a1253cfabf475ce5b7473fde0e
mode 100644,000000..100644
--- /dev/null
@@@ -1,43 -1,0 +1,42 @@@
 +/* Program execution for Emacs.
 +
 +Copyright (C) 2023 Free Software Foundation, Inc.
 +
 +This file is part of GNU Emacs.
 +
 +GNU Emacs is free software: you can redistribute it and/or modify
 +it under the terms of the GNU General Public License as published by
 +the Free Software Foundation, either version 3 of the License, or (at
 +your option) any later version.
 +
 +GNU Emacs is distributed in the hope that it will be useful,
 +but WITHOUT ANY WARRANTY; without even the implied warranty of
 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +GNU General Public License for more details.
 +
 +You should have received a copy of the GNU General Public License
 +along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 +
 +\f
 +
 +#ifndef _MIPSEL_USER_H_
 +#define _MIPSEL_USER_H_
 +
 +#include <sys/user.h>
 +
 +#ifndef ELF_NGREG
 +#define ELF_NGREG       45
 +#endif /* ELF_NGREG */
 +
 +\f
 +
 +/* This file defines a structure containing user mode general purpose
 +   registers on 32-bit mipsel systems.  */
 +
 +struct mipsel_regs
 +{
 +  /* General purpose registers.  */
 +  uint64_t gregs[ELF_NGREG];
 +};
 +
 +#endif /* _MIPSEL_USER_H_ */
index a1f70644e16a4d91dcdbac67d29411e678438aea,0000000000000000000000000000000000000000..aff5046b22e7b31160e09231c367278f5f73c6be
mode 100644,000000..100644
--- /dev/null
@@@ -1,1445 -1,0 +1,1445 @@@
-           view.hideOnScreenKeyboard ();         
 +/* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 +
 +Copyright (C) 2023 Free Software Foundation, Inc.
 +
 +This file is part of GNU Emacs.
 +
 +GNU Emacs is free software: you can redistribute it and/or modify
 +it under the terms of the GNU General Public License as published by
 +the Free Software Foundation, either version 3 of the License, or (at
 +your option) any later version.
 +
 +GNU Emacs is distributed in the hope that it will be useful,
 +but WITHOUT ANY WARRANTY; without even the implied warranty of
 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +GNU General Public License for more details.
 +
 +You should have received a copy of the GNU General Public License
 +along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 +
 +package org.gnu.emacs;
 +
 +import java.lang.IllegalStateException;
 +import java.util.ArrayList;
 +import java.util.List;
 +import java.util.HashMap;
 +import java.util.LinkedHashMap;
 +import java.util.Map;
 +
 +import android.content.Context;
 +
 +import android.graphics.Rect;
 +import android.graphics.Canvas;
 +import android.graphics.Bitmap;
 +import android.graphics.PixelFormat;
 +
 +import android.view.View;
 +import android.view.ViewManager;
 +import android.view.Gravity;
 +import android.view.KeyEvent;
 +import android.view.MotionEvent;
 +import android.view.InputDevice;
 +import android.view.WindowManager;
 +
 +import android.util.Log;
 +
 +import android.os.Build;
 +
 +/* This defines a window, which is a handle.  Windows represent a
 +   rectangular subset of the screen with their own contents.
 +
 +   Windows either have a parent window, in which case their views are
 +   attached to the parent's view, or are "floating", in which case
 +   their views are attached to the parent activity (if any), else
 +   nothing.
 +
 +   Views are also drawables, meaning they can accept drawing
 +   requests.  */
 +
 +public final class EmacsWindow extends EmacsHandleObject
 +  implements EmacsDrawable
 +{
 +  private static final String TAG = "EmacsWindow";
 +
 +  private static class Coordinate
 +  {
 +    /* Integral coordinate.  */
 +    int x, y;
 +
 +    /* Button associated with the coordinate, or 0 if it is a touch
 +       event.  */
 +    int button;
 +
 +    /* Pointer ID associated with the coordinate.  */
 +    int id;
 +
 +    public
 +    Coordinate (int x, int y, int button, int id)
 +    {
 +      this.x = x;
 +      this.y = y;
 +      this.button = button;
 +      this.id = id;
 +    }
 +  };
 +
 +  /* The view associated with the window.  */
 +  public EmacsView view;
 +
 +  /* The geometry of the window.  */
 +  private Rect rect;
 +
 +  /* The parent window, or null if it is the root window.  */
 +  public EmacsWindow parent;
 +
 +  /* List of all children in stacking order.  This must be kept
 +     consistent with their Z order!  */
 +  public ArrayList<EmacsWindow> children;
 +
 +  /* Map between pointer identifiers and last known position.  Used to
 +     compute which pointer changed upon a touch event.  */
 +  private HashMap<Integer, Coordinate> pointerMap;
 +
 +  /* The window consumer currently attached, if it exists.  */
 +  private EmacsWindowAttachmentManager.WindowConsumer attached;
 +
 +  /* The window background scratch GC.  foreground is always the
 +     window background.  */
 +  private EmacsGC scratchGC;
 +
 +  /* The button state and keyboard modifier mask at the time of the
 +     last button press or release event.  */
 +  public int lastButtonState;
 +
 +  /* Whether or not the window is mapped.  */
 +  private volatile boolean isMapped;
 +
 +  /* Whether or not to ask for focus upon being mapped.  */
 +  private boolean dontFocusOnMap;
 +
 +  /* Whether or not the window is override-redirect.  An
 +     override-redirect window always has its own system window.  */
 +  private boolean overrideRedirect;
 +
 +  /* The window manager that is the parent of this window.  NULL if
 +     there is no such window manager.  */
 +  private WindowManager windowManager;
 +
 +  /* The time of the last KEYCODE_VOLUME_DOWN release.  This is used
 +     to quit Emacs upon two rapid clicks of the volume down
 +     button.  */
 +  private long lastVolumeButtonRelease;
 +
 +  /* Linked list of character strings which were recently sent as
 +     events.  */
 +  public LinkedHashMap<Integer, String> eventStrings;
 +
 +  /* Whether or not this window is fullscreen.  */
 +  public boolean fullscreen;
 +
 +  /* The window background pixel.  This is used by EmacsView when
 +     creating new bitmaps.  */
 +  public volatile int background;
 +
 +  /* The position of this window relative to the root window.  */
 +  public int xPosition, yPosition;
 +
 +  public
 +  EmacsWindow (short handle, final EmacsWindow parent, int x, int y,
 +             int width, int height, boolean overrideRedirect)
 +  {
 +    super (handle);
 +
 +    rect = new Rect (x, y, x + width, y + height);
 +    pointerMap = new HashMap<Integer, Coordinate> ();
 +
 +    /* Create the view from the context's UI thread.  The window is
 +       unmapped, so the view is GONE.  */
 +    view = EmacsService.SERVICE.getEmacsView (this, View.GONE,
 +                                            parent == null);
 +    this.parent = parent;
 +    this.overrideRedirect = overrideRedirect;
 +
 +    /* Create the list of children.  */
 +    children = new ArrayList<EmacsWindow> ();
 +
 +    if (parent != null)
 +      {
 +      parent.children.add (this);
 +        EmacsService.SERVICE.runOnUiThread (new Runnable () {
 +          @Override
 +          public void
 +          run ()
 +          {
 +            parent.view.addView (view);
 +          }
 +        });
 +      }
 +
 +    scratchGC = new EmacsGC ((short) 0);
 +
 +    /* Create the map of input method-committed strings.  Keep at most
 +       ten strings in the map.  */
 +
 +    eventStrings
 +      = new LinkedHashMap<Integer, String> () {
 +        @Override
 +        protected boolean
 +        removeEldestEntry (Map.Entry<Integer, String> entry)
 +        {
 +          return size () > 10;
 +        }
 +      };
 +  }
 +
 +  public void
 +  changeWindowBackground (int pixel)
 +  {
 +    /* scratchGC is used as the argument to a FillRectangles req.  */
 +    scratchGC.foreground = pixel;
 +    scratchGC.markDirty (false);
 +
 +    /* Make the background known to the view as well.  */
 +    background = pixel;
 +  }
 +
 +  public synchronized Rect
 +  getGeometry ()
 +  {
 +    return new Rect (rect);
 +  }
 +
 +  @Override
 +  public synchronized void
 +  destroyHandle () throws IllegalStateException
 +  {
 +    if (parent != null)
 +      parent.children.remove (this);
 +
 +    EmacsActivity.invalidateFocus ();
 +
 +    if (!children.isEmpty ())
 +      throw new IllegalStateException ("Trying to destroy window with "
 +                                     + "children!");
 +
 +    /* Remove the view from its parent and make it invisible.  */
 +    EmacsService.SERVICE.runOnUiThread (new Runnable () {
 +      public void
 +      run ()
 +      {
 +        ViewManager parent;
 +        EmacsWindowAttachmentManager manager;
 +
 +        if (EmacsActivity.focusedWindow == EmacsWindow.this)
 +          EmacsActivity.focusedWindow = null;
 +
 +        manager = EmacsWindowAttachmentManager.MANAGER;
 +        view.setVisibility (View.GONE);
 +
 +        /* If the window manager is set, use that instead.  */
 +        if (windowManager != null)
 +          parent = windowManager;
 +        else
 +          parent = (ViewManager) view.getParent ();
 +        windowManager = null;
 +
 +        if (parent != null)
 +          parent.removeView (view);
 +
 +        manager.detachWindow (EmacsWindow.this);
 +      }
 +      });
 +
 +    super.destroyHandle ();
 +  }
 +
 +  public void
 +  setConsumer (EmacsWindowAttachmentManager.WindowConsumer consumer)
 +  {
 +    attached = consumer;
 +  }
 +
 +  public EmacsWindowAttachmentManager.WindowConsumer
 +  getAttachedConsumer ()
 +  {
 +    return attached;
 +  }
 +
 +  public synchronized long
 +  viewLayout (int left, int top, int right, int bottom)
 +  {
 +    int rectWidth, rectHeight;
 +
 +    rect.left = left;
 +    rect.top = top;
 +    rect.right = right;
 +    rect.bottom = bottom;
 +
 +    rectWidth = right - left;
 +    rectHeight = bottom - top;
 +
 +    /* If parent is null, use xPosition and yPosition instead of the
 +       geometry rectangle positions.  */
 +
 +    if (parent == null)
 +      {
 +      left = xPosition;
 +      top = yPosition;
 +      }
 +
 +    return EmacsNative.sendConfigureNotify (this.handle,
 +                                          System.currentTimeMillis (),
 +                                          left, top, rectWidth,
 +                                          rectHeight);
 +  }
 +
 +  public void
 +  requestViewLayout ()
 +  {
 +    view.explicitlyDirtyBitmap ();
 +
 +    EmacsService.SERVICE.runOnUiThread (new Runnable () {
 +      @Override
 +      public void
 +      run ()
 +      {
 +        if (overrideRedirect)
 +          /* Set the layout parameters again.  */
 +          view.setLayoutParams (getWindowLayoutParams ());
 +
 +        view.mustReportLayout = true;
 +        view.requestLayout ();
 +      }
 +      });
 +  }
 +
 +  public synchronized void
 +  resizeWindow (int width, int height)
 +  {
 +    rect.right = rect.left + width;
 +    rect.bottom = rect.top + height;
 +
 +    requestViewLayout ();
 +  }
 +
 +  public synchronized void
 +  moveWindow (int x, int y)
 +  {
 +    int width, height;
 +
 +    width = rect.width ();
 +    height = rect.height ();
 +
 +    rect.left = x;
 +    rect.top = y;
 +    rect.right = x + width;
 +    rect.bottom = y + height;
 +
 +    requestViewLayout ();
 +  }
 +
 +  private WindowManager.LayoutParams
 +  getWindowLayoutParams ()
 +  {
 +    WindowManager.LayoutParams params;
 +    int flags, type;
 +    Rect rect;
 +
 +    flags = 0;
 +    rect = getGeometry ();
 +    flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 +    flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
 +    type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
 +
 +    params
 +      = new WindowManager.LayoutParams (rect.width (), rect.height (),
 +                                      rect.left, rect.top,
 +                                      type, flags,
 +                                      PixelFormat.RGBA_8888);
 +    params.gravity = Gravity.TOP | Gravity.LEFT;
 +    return params;
 +  }
 +
 +  private Context
 +  findSuitableActivityContext ()
 +  {
 +    /* Find a recently focused activity.  */
 +    if (!EmacsActivity.focusedActivities.isEmpty ())
 +      return EmacsActivity.focusedActivities.get (0);
 +
 +    /* Return the service context, which probably won't work.  */
 +    return EmacsService.SERVICE;
 +  }
 +
 +  public synchronized void
 +  mapWindow ()
 +  {
 +    final int width, height;
 +
 +    if (isMapped)
 +      return;
 +
 +    isMapped = true;
 +    width = rect.width ();
 +    height = rect.height ();
 +
 +    if (parent == null)
 +      {
 +        EmacsService.SERVICE.runOnUiThread (new Runnable () {
 +          @Override
 +          public void
 +          run ()
 +          {
 +            EmacsWindowAttachmentManager manager;
 +            WindowManager windowManager;
 +            Context ctx;
 +            Object tem;
 +            WindowManager.LayoutParams params;
 +
 +            /* Make the view visible, first of all.  */
 +            view.setVisibility (View.VISIBLE);
 +
 +            if (!overrideRedirect)
 +              {
 +                manager = EmacsWindowAttachmentManager.MANAGER;
 +
 +                /* If parent is the root window, notice that there are new
 +                   children available for interested activites to pick
 +                   up.  */
 +                manager.registerWindow (EmacsWindow.this);
 +
 +                if (!getDontFocusOnMap ())
 +                  /* Eventually this should check no-focus-on-map.  */
 +                  view.requestFocus ();
 +              }
 +            else
 +              {
 +                /* But if the window is an override-redirect window,
 +                   then:
 +
 +                   - Find an activity that is currently active.
 +
 +                   - Map the window as a panel on top of that
 +                       activity using the system window manager.  */
 +
 +                ctx = findSuitableActivityContext ();
 +                tem = ctx.getSystemService (Context.WINDOW_SERVICE);
 +                windowManager = (WindowManager) tem;
 +
 +                /* Calculate layout parameters.  */
 +                params = getWindowLayoutParams ();
 +                view.setLayoutParams (params);
 +
 +                /* Attach the view.  */
 +                try
 +                  {
 +                    view.prepareForLayout (width, height);
 +                    windowManager.addView (view, params);
 +
 +                    /* Record the window manager being used in the
 +                       EmacsWindow object.  */
 +                    EmacsWindow.this.windowManager = windowManager;
 +                  }
 +                catch (Exception e)
 +                  {
 +                    Log.w (TAG,
 +                           "failed to attach override-redirect window, " + e);
 +                  }
 +              }
 +          }
 +        });
 +      }
 +    else
 +      {
 +      /* Do the same thing as above, but don't register this
 +         window.  */
 +        EmacsService.SERVICE.runOnUiThread (new Runnable () {
 +          @Override
 +          public void
 +          run ()
 +          {
 +            /* Prior to mapping the view, set its measuredWidth and
 +               measuredHeight to some reasonable value, in order to
 +               avoid excessive bitmap dirtying.  */
 +
 +            view.prepareForLayout (width, height);
 +            view.setVisibility (View.VISIBLE);
 +
 +            if (!getDontFocusOnMap ())
 +              view.requestFocus ();
 +          }
 +        });
 +      }
 +  }
 +
 +  public synchronized void
 +  unmapWindow ()
 +  {
 +    if (!isMapped)
 +      return;
 +
 +    isMapped = false;
 +
 +    view.post (new Runnable () {
 +      @Override
 +      public void
 +      run ()
 +      {
 +        EmacsWindowAttachmentManager manager;
 +
 +        manager = EmacsWindowAttachmentManager.MANAGER;
 +
 +        view.setVisibility (View.GONE);
 +
 +        /* Detach the view from the window manager if possible.  */
 +        if (windowManager != null)
 +          windowManager.removeView (view);
 +        windowManager = null;
 +
 +        /* Now that the window is unmapped, unregister it as
 +           well.  */
 +        manager.detachWindow (EmacsWindow.this);
 +      }
 +      });
 +  }
 +
 +  @Override
 +  public Canvas
 +  lockCanvas (EmacsGC gc)
 +  {
 +    return view.getCanvas (gc);
 +  }
 +
 +  @Override
 +  public void
 +  damageRect (Rect damageRect)
 +  {
 +    view.damageRect (damageRect);
 +  }
 +
 +  public void
 +  swapBuffers ()
 +  {
 +    view.swapBuffers ();
 +  }
 +
 +  public void
 +  clearWindow ()
 +  {
 +    EmacsService.SERVICE.fillRectangle (this, scratchGC,
 +                                      0, 0, rect.width (),
 +                                      rect.height ());
 +  }
 +
 +  public void
 +  clearArea (int x, int y, int width, int height)
 +  {
 +    EmacsService.SERVICE.fillRectangle (this, scratchGC,
 +                                      x, y, width, height);
 +  }
 +
 +  @Override
 +  public Bitmap
 +  getBitmap ()
 +  {
 +    return view.getBitmap ();
 +  }
 +
 +  /* event.getCharacters is used because older input methods still
 +     require it.  */
 +  @SuppressWarnings ("deprecation")
 +  public int
 +  getEventUnicodeChar (KeyEvent event, int state)
 +  {
 +    String characters;
 +
 +    if (event.getUnicodeChar (state) != 0)
 +      return event.getUnicodeChar (state);
 +
 +    characters = event.getCharacters ();
 +
 +    if (characters != null && characters.length () == 1)
 +      return characters.charAt (0);
 +
 +    return characters == null ? 0 : -1;
 +  }
 +
 +  public void
 +  saveUnicodeString (int serial, String string)
 +  {
 +    eventStrings.put (serial, string);
 +  }
 +
 +\f
 +
 +  /* Return the modifier mask associated with the specified keyboard
 +     input EVENT.  Replace bits corresponding to Left or Right keys
 +     with their corresponding general modifier bits.  */
 +
 +  private int
 +  eventModifiers (KeyEvent event)
 +  {
 +    int state;
 +
 +    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2)
 +      state = event.getModifiers ();
 +    else
 +      {
 +      /* Replace this with getMetaState and manual
 +         normalization.  */
 +      state = event.getMetaState ();
 +
 +      /* Normalize the state by setting the generic modifier bit if
 +         either a left or right modifier is pressed.  */
 +
 +      if ((state & KeyEvent.META_ALT_LEFT_ON) != 0
 +          || (state & KeyEvent.META_ALT_RIGHT_ON) != 0)
 +        state |= KeyEvent.META_ALT_MASK;
 +
 +      if ((state & KeyEvent.META_CTRL_LEFT_ON) != 0
 +          || (state & KeyEvent.META_CTRL_RIGHT_ON) != 0)
 +        state |= KeyEvent.META_CTRL_MASK;
 +      }
 +
 +    return state;
 +  }
 +
 +  /* event.getCharacters is used because older input methods still
 +     require it.  */
 +  @SuppressWarnings ("deprecation")
 +  public void
 +  onKeyDown (int keyCode, KeyEvent event)
 +  {
 +    int state, state_1;
 +    long serial;
 +    String characters;
 +
 +    state = eventModifiers (event);
 +
 +    /* Ignore meta-state understood by Emacs for now, or key presses
 +       such as Ctrl+C and Meta+C will not be recognized as an ASCII
 +       key press event.  */
 +
 +    state_1
 +      = state & ~(KeyEvent.META_ALT_MASK | KeyEvent.META_CTRL_MASK
 +                | KeyEvent.META_SYM_ON | KeyEvent.META_META_MASK);
 +
 +    synchronized (eventStrings)
 +      {
 +      serial
 +        = EmacsNative.sendKeyPress (this.handle,
 +                                    event.getEventTime (),
 +                                    state, keyCode,
 +                                    getEventUnicodeChar (event,
 +                                                         state_1));
 +
 +      characters = event.getCharacters ();
 +
 +      if (characters != null && characters.length () > 1)
 +        saveUnicodeString ((int) serial, characters);
 +      }
 +  }
 +
 +  public void
 +  onKeyUp (int keyCode, KeyEvent event)
 +  {
 +    int state, state_1;
 +    long time;
 +
 +    /* Compute the event's modifier mask.  */
 +    state = eventModifiers (event);
 +
 +    /* Ignore meta-state understood by Emacs for now, or key presses
 +       such as Ctrl+C and Meta+C will not be recognized as an ASCII
 +       key press event.  */
 +
 +    state_1
 +      = state & ~(KeyEvent.META_ALT_MASK | KeyEvent.META_CTRL_MASK
 +                | KeyEvent.META_SYM_ON | KeyEvent.META_META_MASK);
 +
 +    EmacsNative.sendKeyRelease (this.handle,
 +                              event.getEventTime (),
 +                              state, keyCode,
 +                              getEventUnicodeChar (event,
 +                                                   state_1));
 +
 +    if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)
 +      {
 +      /* Check if this volume down press should quit Emacs.
 +         Most Android devices have no physical keyboard, so it
 +         is unreasonably hard to press C-g.  */
 +
 +      time = event.getEventTime ();
 +
 +      if (time - lastVolumeButtonRelease < 350)
 +        EmacsNative.quit ();
 +
 +      lastVolumeButtonRelease = time;
 +      }
 +  }
 +
 +  public void
 +  onFocusChanged (boolean gainFocus)
 +  {
 +    EmacsActivity.invalidateFocus ();
 +  }
 +
 +  /* Notice that the activity has been detached or destroyed.
 +
 +     ISFINISHING is set if the activity is not the main activity, or
 +     if the activity was not destroyed in response to explicit user
 +     action.  */
 +
 +  public void
 +  onActivityDetached (boolean isFinishing)
 +  {
 +    /* Destroy the associated frame when the activity is detached in
 +       response to explicit user action.  */
 +
 +    if (isFinishing)
 +      EmacsNative.sendWindowAction (this.handle, 0);
 +  }
 +
 +\f
 +
 +  /* Mouse and touch event handling.
 +
 +     Android does not conceptually distinguish between mouse events
 +     (those coming from a device whose movement affects the on-screen
 +     pointer image) and touch screen events.  Each click or touch
 +     starts a single pointer gesture sequence, and subsequent motion
 +     of the device will result in updates being reported relative to
 +     that sequence until the mouse button or touch is released.
 +
 +     When a touch, click, or pointer motion takes place, several kinds
 +     of event can be sent:
 +
 +     ACTION_DOWN or ACTION_POINTER_DOWN is sent with a new coordinate
 +     and an associated ``pointer ID'' identifying the event and its
 +     gesture sequence when a click or touch takes place.  Emacs is
 +     responsible for recording both the position and pointer ID of
 +     this click for the purpose of determining future changes to its
 +     position.
 +
 +     ACTION_UP or ACTION_POINTER_UP is sent with a pointer ID when the
 +     click associated with a previous ACTION_DOWN event is released.
 +
 +     ACTION_CANCEL (or ACTION_POINTER_UP with FLAG_CANCELED) is sent
 +     if a similar situation transpires: the window system has chosen
 +     to grab the click, and future changes to its position will no
 +     longer be reported to Emacs.
 +
 +     ACTION_MOVE is sent if a coordinate tied to a click that has not
 +     been released changes.  Emacs processes this event by comparing
 +     each of the coordinates within the event with its recollection of
 +     those contained within prior ACTION_DOWN and ACTION_MOVE events;
 +     the pointer ID of the differing coordinate is then reported
 +     within a touch or pointer motion event along with its new
 +     position.
 +
 +     The events described above are all sent for both touch and mouse
 +     click events.  Determining whether an ACTION_DOWN event is
 +     associated with a button event is performed by inspecting the
 +     mouse button state associated with that event.  If it contains
 +     any mouse buttons that were not contained in the button state at
 +     the time of the last ACTION_DOWN or ACTION_UP event, the
 +     coordinate contained within is assumed to be a mouse click,
 +     leading to it and associated motion or ACTION_UP events being
 +     reported as mouse button or motion events.  Otherwise, those
 +     events are reported as touch screen events, with the touch ID set
 +     to the pointer ID.
 +
 +     In addition to the events illustrated above, Android also sends
 +     several other types of event upon select types of activity from a
 +     mouse device:
 +
 +     ACTION_HOVER_MOVE is sent with the coordinate of the mouse
 +     pointer if it moves above a frame prior to any click taking
 +     place.  Emacs sends a mouse motion event containing the
 +     coordinate.
 +
 +     ACTION_HOVER_ENTER and ACTION_HOVER_LEAVE are respectively sent
 +     when the mouse pointer enters and leaves a frame.  Moreover,
 +     ACTION_HOVER_LEAVE events are sent immediately before an
 +     ACTION_DOWN event associated with a mouse click.  These
 +     extraneous events are distinct in that their button states always
 +     contain an additional button compared to the button state
 +     recorded at the time of the last ACTION_UP event.
 +
 +     On Android 6.0 and later, ACTION_BUTTON_PRESS is sent with the
 +     coordinate of the mouse pointer if a mouse click occurs,
 +     alongside a ACTION_DOWN event.  ACTION_BUTTON_RELEASE is sent
 +     with the same information upon a mouse click being released, also
 +     accompanying an ACTION_UP event.
 +
 +     However, both types of button events are implemented in a buggy
 +     fashion and cannot be used to report button events.  */
 +
 +  /* Look through the button state to determine what button EVENT was
 +     generated from.  DOWN is true if EVENT is a button press event,
 +     false otherwise.  Value is the X number of the button.  */
 +
 +  private int
 +  whatButtonWasIt (MotionEvent event, boolean down)
 +  {
 +    int eventState, notIn;
 +
 +    /* Obtain the new button state.  */
 +    eventState = event.getButtonState ();
 +
 +    /* Compute which button is now set or no longer set.  */
 +
 +    notIn = (down ? eventState & ~lastButtonState
 +           : lastButtonState & ~eventState);
 +
 +    if ((notIn & (MotionEvent.BUTTON_PRIMARY
 +                | MotionEvent.BUTTON_SECONDARY
 +                | MotionEvent.BUTTON_TERTIARY)) == 0)
 +      /* No buttons have been pressed, so this is a touch event.  */
 +      return 0;
 +
 +    if ((notIn & MotionEvent.BUTTON_PRIMARY) != 0)
 +      return 1;
 +
 +    if ((notIn & MotionEvent.BUTTON_SECONDARY) != 0)
 +      return 3;
 +
 +    if ((notIn & MotionEvent.BUTTON_TERTIARY) != 0)
 +      return 2;
 +
 +    /* Buttons 4, 5, 6 and 7 are actually scroll wheels under X.
 +       Thus, report additional buttons starting at 8.  */
 +
 +    if ((notIn & MotionEvent.BUTTON_BACK) != 0)
 +      return 8;
 +
 +    if ((notIn & MotionEvent.BUTTON_FORWARD) != 0)
 +      return 9;
 +
 +    /* Report stylus events as touch screen events.  */
 +
 +    if ((notIn & MotionEvent.BUTTON_STYLUS_PRIMARY) != 0)
 +      return 0;
 +
 +    if ((notIn & MotionEvent.BUTTON_STYLUS_SECONDARY) != 0)
 +      return 0;
 +
 +    /* Not a real value.  */
 +    return 11;
 +  }
 +
 +  /* Return the mouse button associated with the specified ACTION_DOWN
 +     or ACTION_POINTER_DOWN EVENT.
 +
 +     Value is 0 if no mouse button was pressed, or the X number of
 +     that mouse button.  */
 +
 +  private int
 +  buttonForEvent (MotionEvent event)
 +  {
 +    /* ICS and earlier don't support true mouse button events, so
 +       treat all down events as touch screen events.  */
 +
 +    if (Build.VERSION.SDK_INT
 +      < Build.VERSION_CODES.ICE_CREAM_SANDWICH)
 +      return 0;
 +
 +    return whatButtonWasIt (event, true);
 +  }
 +
 +  /* Return the coordinate object associated with the specified
 +     EVENT, or null if it is not known.  */
 +
 +  private Coordinate
 +  figureChange (MotionEvent event)
 +  {
 +    int i, truncatedX, truncatedY, pointerIndex, pointerID, count;
 +    Coordinate coordinate;
 +
 +    /* Initialize this variable now.  */
 +    coordinate = null;
 +
 +    switch (event.getActionMasked ())
 +      {
 +      case MotionEvent.ACTION_DOWN:
 +      /* Primary pointer pressed with index 0.  */
 +
 +      pointerID = event.getPointerId (0);
 +      coordinate = new Coordinate ((int) event.getX (0),
 +                                   (int) event.getY (0),
 +                                   buttonForEvent (event),
 +                                   pointerID);
 +      pointerMap.put (pointerID, coordinate);
 +      break;
 +
 +      case MotionEvent.ACTION_UP:
 +      case MotionEvent.ACTION_CANCEL:
 +      /* Primary pointer released with index 0.  */
 +      pointerID = event.getPointerId (0);
 +      coordinate = pointerMap.remove (pointerID);
 +      break;
 +
 +      case MotionEvent.ACTION_POINTER_DOWN:
 +      /* New pointer.  Find the pointer ID from the index and place
 +         it in the map.  */
 +      pointerIndex = event.getActionIndex ();
 +      pointerID = event.getPointerId (pointerIndex);
 +      coordinate = new Coordinate ((int) event.getX (0),
 +                                   (int) event.getY (0),
 +                                   buttonForEvent (event),
 +                                   pointerID);
 +      pointerMap.put (pointerID, coordinate);
 +      break;
 +
 +      case MotionEvent.ACTION_POINTER_UP:
 +      /* Pointer removed.  Remove it from the map.  */
 +      pointerIndex = event.getActionIndex ();
 +      pointerID = event.getPointerId (pointerIndex);
 +      coordinate = pointerMap.remove (pointerID);
 +      break;
 +
 +      default:
 +
 +      /* Loop through each pointer in the event.  */
 +
 +      count = event.getPointerCount ();
 +      for (i = 0; i < count; ++i)
 +        {
 +          pointerID = event.getPointerId (i);
 +
 +          /* Look up that pointer in the map.  */
 +          coordinate = pointerMap.get (pointerID);
 +
 +          if (coordinate != null)
 +            {
 +              /* See if coordinates have changed.  */
 +              truncatedX = (int) event.getX (i);
 +              truncatedY = (int) event.getY (i);
 +
 +              if (truncatedX != coordinate.x
 +                  || truncatedY != coordinate.y)
 +                {
 +                  /* The pointer changed.  Update the coordinate and
 +                     break out of the loop.  */
 +                  coordinate.x = truncatedX;
 +                  coordinate.y = truncatedY;
 +
 +                  break;
 +                }
 +            }
 +        }
 +
 +      /* Set coordinate to NULL if the loop failed to find any
 +         matching pointer.  */
 +
 +      if (i == count)
 +        coordinate = null;
 +      }
 +
 +    /* Return the pointer ID.  */
 +    return coordinate;
 +  }
 +
 +  /* Return the modifier mask associated with the specified motion
 +     EVENT.  Replace bits corresponding to Left or Right keys with
 +     their corresponding general modifier bits.  */
 +
 +  private int
 +  motionEventModifiers (MotionEvent event)
 +  {
 +    int state;
 +
 +    state = event.getMetaState ();
 +
 +    /* Normalize the state by setting the generic modifier bit if
 +       either a left or right modifier is pressed.  */
 +
 +    if ((state & KeyEvent.META_ALT_LEFT_ON) != 0
 +      || (state & KeyEvent.META_ALT_RIGHT_ON) != 0)
 +      state |= KeyEvent.META_ALT_MASK;
 +
 +    if ((state & KeyEvent.META_CTRL_LEFT_ON) != 0
 +      || (state & KeyEvent.META_CTRL_RIGHT_ON) != 0)
 +      state |= KeyEvent.META_CTRL_MASK;
 +
 +    return state;
 +  }
 +
 +  /* Process a single ACTION_DOWN, ACTION_POINTER_DOWN, ACTION_UP,
 +     ACTION_POINTER_UP, ACTION_CANCEL, or ACTION_MOVE event.
 +
 +     Ascertain which coordinate changed and send an appropriate mouse
 +     or touch screen event.  */
 +
 +  private void
 +  motionEvent (MotionEvent event)
 +  {
 +    Coordinate coordinate;
 +    int modifiers;
 +    long time;
 +
 +    /* Find data associated with this event's pointer.  Namely, its
 +       current location, whether or not a change has taken place, and
 +       whether or not it is a button event.  */
 +
 +    coordinate = figureChange (event);
 +
 +    if (coordinate == null)
 +      return;
 +
 +    time = event.getEventTime ();
 +
 +    if (coordinate.button != 0)
 +      {
 +      /* This event is tied to a mouse click, so report mouse motion
 +         and button events.  */
 +
 +      modifiers = motionEventModifiers (event);
 +
 +      switch (event.getAction ())
 +        {
 +        case MotionEvent.ACTION_POINTER_DOWN:
 +        case MotionEvent.ACTION_DOWN:
 +          EmacsNative.sendButtonPress (this.handle, coordinate.x,
 +                                       coordinate.y, time, modifiers,
 +                                       coordinate.button);
 +          break;
 +
 +        case MotionEvent.ACTION_POINTER_UP:
 +        case MotionEvent.ACTION_UP:
 +        case MotionEvent.ACTION_CANCEL:
 +          EmacsNative.sendButtonRelease (this.handle, coordinate.x,
 +                                         coordinate.y, time, modifiers,
 +                                         coordinate.button);
 +          break;
 +
 +        case MotionEvent.ACTION_MOVE:
 +          EmacsNative.sendMotionNotify (this.handle, coordinate.x,
 +                                        coordinate.y, time);
 +          break;
 +        }
 +      }
 +    else
 +      {
 +      /* This event is a touch event, and the touch ID is the
 +         pointer ID.  */
 +
 +      switch (event.getActionMasked ())
 +        {
 +        case MotionEvent.ACTION_DOWN:
 +        case MotionEvent.ACTION_POINTER_DOWN:
 +          /* Touch down event.  */
 +          EmacsNative.sendTouchDown (this.handle, coordinate.x,
 +                                     coordinate.y, time,
 +                                     coordinate.id, 0);
 +          break;
 +
 +        case MotionEvent.ACTION_UP:
 +        case MotionEvent.ACTION_POINTER_UP:
 +          /* Touch up event.  */
 +          EmacsNative.sendTouchUp (this.handle, coordinate.x,
 +                                   coordinate.y, time,
 +                                   coordinate.id, 0);
 +          break;
 +
 +        case MotionEvent.ACTION_CANCEL:
 +          /* Touch sequence cancellation event.  */
 +          EmacsNative.sendTouchUp (this.handle, coordinate.x,
 +                                   coordinate.y, time,
 +                                   coordinate.id,
 +                                   1 /* ANDROID_TOUCH_SEQUENCE_CANCELED */);
 +          break;
 +
 +        case MotionEvent.ACTION_MOVE:
 +          /* Pointer motion event.  */
 +          EmacsNative.sendTouchMove (this.handle, coordinate.x,
 +                                     coordinate.y, time,
 +                                     coordinate.id, 0);
 +          break;
 +        }
 +      }
 +
 +    if (Build.VERSION.SDK_INT
 +      < Build.VERSION_CODES.ICE_CREAM_SANDWICH)
 +      return;
 +
 +    /* Now update the button state.  */
 +    lastButtonState = event.getButtonState ();
 +    return;
 +  }
 +
 +  public boolean
 +  onTouchEvent (MotionEvent event)
 +  {
 +    switch (event.getActionMasked ())
 +      {
 +      case MotionEvent.ACTION_DOWN:
 +      case MotionEvent.ACTION_POINTER_DOWN:
 +      case MotionEvent.ACTION_UP:
 +      case MotionEvent.ACTION_POINTER_UP:
 +      case MotionEvent.ACTION_CANCEL:
 +      case MotionEvent.ACTION_MOVE:
 +      motionEvent (event);
 +      return true;
 +      }
 +
 +    return false;
 +  }
 +
 +  public boolean
 +  onGenericMotionEvent (MotionEvent event)
 +  {
 +    switch (event.getAction ())
 +      {
 +      case MotionEvent.ACTION_HOVER_ENTER:
 +      EmacsNative.sendEnterNotify (this.handle, (int) event.getX (),
 +                                   (int) event.getY (),
 +                                   event.getEventTime ());
 +      return true;
 +
 +      case MotionEvent.ACTION_HOVER_MOVE:
 +      EmacsNative.sendMotionNotify (this.handle, (int) event.getX (),
 +                                    (int) event.getY (),
 +                                    event.getEventTime ());
 +      return true;
 +
 +      case MotionEvent.ACTION_HOVER_EXIT:
 +
 +      /* If the exit event comes from a button press, its button
 +         state will have extra bits compared to the last known
 +         button state.  Since the exit event will interfere with
 +         tool bar button presses, ignore such splurious events.  */
 +
 +      if ((event.getButtonState () & ~lastButtonState) == 0)
 +        EmacsNative.sendLeaveNotify (this.handle, (int) event.getX (),
 +                                     (int) event.getY (),
 +                                     event.getEventTime ());
 +
 +      return true;
 +
 +      case MotionEvent.ACTION_DOWN:
 +      case MotionEvent.ACTION_POINTER_DOWN:
 +      case MotionEvent.ACTION_UP:
 +      case MotionEvent.ACTION_POINTER_UP:
 +      case MotionEvent.ACTION_CANCEL:
 +      case MotionEvent.ACTION_MOVE:
 +      /* MotionEvents may either be sent to onGenericMotionEvent or
 +         onTouchEvent depending on if Android thinks it is a mouse
 +         event or not, but we detect them ourselves.  */
 +      motionEvent (event);
 +      return true;
 +
 +      case MotionEvent.ACTION_SCROLL:
 +      /* Send a scroll event with the specified deltas.  */
 +      EmacsNative.sendWheel (this.handle, (int) event.getX (),
 +                             (int) event.getY (),
 +                             event.getEventTime (),
 +                             motionEventModifiers (event),
 +                             event.getAxisValue (MotionEvent.AXIS_HSCROLL),
 +                             event.getAxisValue (MotionEvent.AXIS_VSCROLL));
 +      return true;
 +      }
 +
 +    return false;
 +  }
 +
 +\f
 +
 +  public synchronized void
 +  reparentTo (final EmacsWindow otherWindow, int x, int y)
 +  {
 +    int width, height;
 +
 +    /* Reparent this window to the other window.  */
 +
 +    if (parent != null)
 +      parent.children.remove (this);
 +
 +    if (otherWindow != null)
 +      otherWindow.children.add (this);
 +
 +    parent = otherWindow;
 +
 +    /* Move this window to the new location.  */
 +    width = rect.width ();
 +    height = rect.height ();
 +    rect.left = x;
 +    rect.top = y;
 +    rect.right = x + width;
 +    rect.bottom = y + height;
 +
 +    /* Now do the work necessary on the UI thread to reparent the
 +       window.  */
 +    EmacsService.SERVICE.runOnUiThread (new Runnable () {
 +      @Override
 +      public void
 +      run ()
 +      {
 +        EmacsWindowAttachmentManager manager;
 +        ViewManager parent;
 +
 +        /* First, detach this window if necessary.  */
 +        manager = EmacsWindowAttachmentManager.MANAGER;
 +        manager.detachWindow (EmacsWindow.this);
 +
 +        /* Also unparent this view.  */
 +
 +        /* If the window manager is set, use that instead.  */
 +        if (windowManager != null)
 +          parent = windowManager;
 +        else
 +          parent = (ViewManager) view.getParent ();
 +        windowManager = null;
 +
 +        if (parent != null)
 +          parent.removeView (view);
 +
 +        /* Next, either add this window as a child of the new
 +           parent's view, or make it available again.  */
 +        if (otherWindow != null)
 +          otherWindow.view.addView (view);
 +        else if (EmacsWindow.this.isMapped)
 +          manager.registerWindow (EmacsWindow.this);
 +
 +        /* Request relayout.  */
 +        view.requestLayout ();
 +      }
 +      });
 +  }
 +
 +  public void
 +  makeInputFocus (long time)
 +  {
 +    /* TIME is currently ignored.  Request the input focus now.  */
 +
 +    EmacsService.SERVICE.runOnUiThread (new Runnable () {
 +      @Override
 +      public void
 +      run ()
 +      {
 +        view.requestFocus ();
 +      }
 +      });
 +  }
 +
 +  public synchronized void
 +  raise ()
 +  {
 +    /* This does nothing here.  */
 +    if (parent == null)
 +      return;
 +
 +    /* Remove and add this view again.  */
 +    parent.children.remove (this);
 +    parent.children.add (this);
 +
 +    /* Request a relayout.  */
 +    EmacsService.SERVICE.runOnUiThread (new Runnable () {
 +      @Override
 +      public void
 +      run ()
 +      {
 +        view.raise ();
 +      }
 +      });
 +  }
 +
 +  public synchronized void
 +  lower ()
 +  {
 +    /* This does nothing here.  */
 +    if (parent == null)
 +      return;
 +
 +    /* Remove and add this view again.  */
 +    parent.children.remove (this);
 +    parent.children.add (this);
 +
 +    /* Request a relayout.  */
 +    EmacsService.SERVICE.runOnUiThread (new Runnable () {
 +      @Override
 +      public void
 +      run ()
 +      {
 +        view.lower ();
 +      }
 +      });
 +  }
 +
 +  public synchronized int[]
 +  getWindowGeometry ()
 +  {
 +    int[] array;
 +
 +    array = new int[4];
 +
 +    array[0] = parent != null ? rect.left : xPosition;
 +    array[1] = parent != null ? rect.top : yPosition;
 +    array[2] = rect.width ();
 +    array[3] = rect.height ();
 +
 +    return array;
 +  }
 +
 +  public void
 +  noticeIconified ()
 +  {
 +    EmacsNative.sendIconified (this.handle);
 +  }
 +
 +  public void
 +  noticeDeiconified ()
 +  {
 +    EmacsNative.sendDeiconified (this.handle);
 +  }
 +
 +  public synchronized void
 +  setDontAcceptFocus (final boolean dontAcceptFocus)
 +  {
 +    /* Update the view's focus state.  */
 +    EmacsService.SERVICE.runOnUiThread (new Runnable () {
 +      @Override
 +      public void
 +      run ()
 +      {
 +        view.setFocusable (!dontAcceptFocus);
 +        view.setFocusableInTouchMode (!dontAcceptFocus);
 +      }
 +      });
 +  }
 +
 +  public synchronized void
 +  setDontFocusOnMap (final boolean dontFocusOnMap)
 +  {
 +    this.dontFocusOnMap = dontFocusOnMap;
 +  }
 +
 +  public synchronized boolean
 +  getDontFocusOnMap ()
 +  {
 +    return dontFocusOnMap;
 +  }
 +
 +  public int[]
 +  translateCoordinates (int x, int y)
 +  {
 +    int[] array;
 +
 +    /* This is supposed to translate coordinates to the root
 +       window.  */
 +    array = new int[2];
 +    EmacsService.SERVICE.getLocationOnScreen (view, array);
 +
 +    /* Now, the coordinates of the view should be in array.  Offset X
 +       and Y by them.  */
 +    array[0] += x;
 +    array[1] += y;
 +
 +    /* Return the resulting coordinates.  */
 +    return array;
 +  }
 +
 +  public void
 +  toggleOnScreenKeyboard (final boolean on)
 +  {
 +    /* Even though InputMethodManager functions are thread safe,
 +       `showOnScreenKeyboard' etc must be called from the UI thread in
 +       order to avoid deadlocks if the calls happen in tandem with a
 +       call to a synchronizing function within
 +       `onCreateInputConnection'.  */
 +
 +    EmacsService.SERVICE.runOnUiThread (new Runnable () {
 +      @Override
 +      public void
 +      run ()
 +      {
 +        if (on)
 +          view.showOnScreenKeyboard ();
 +        else
++          view.hideOnScreenKeyboard ();
 +      }
 +      });
 +  }
 +
 +  public String
 +  lookupString (int eventSerial)
 +  {
 +    String any;
 +
 +    synchronized (eventStrings)
 +      {
 +      any = eventStrings.remove (eventSerial);
 +      }
 +
 +    return any;
 +  }
 +
 +  public void
 +  setFullscreen (final boolean isFullscreen)
 +  {
 +    EmacsService.SERVICE.runOnUiThread (new Runnable () {
 +      @Override
 +      public void
 +      run ()
 +      {
 +        EmacsActivity activity;
 +        Object tem;
 +
 +        fullscreen = isFullscreen;
 +        tem = getAttachedConsumer ();
 +
 +        if (tem != null)
 +          {
 +            activity = (EmacsActivity) tem;
 +            activity.syncFullscreenWith (EmacsWindow.this);
 +          }
 +      }
 +      });
 +  }
 +
 +  public void
 +  defineCursor (final EmacsCursor cursor)
 +  {
 +    /* Don't post this message if pointer icons aren't supported.  */
 +
 +    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
 +      view.post (new Runnable () {
 +        @Override
 +        public void
 +        run ()
 +        {
 +          if (cursor != null)
 +            view.setPointerIcon (cursor.icon);
 +          else
 +            view.setPointerIcon (null);
 +        }
 +      });
 +  }
 +
 +  public synchronized void
 +  notifyContentRectPosition (int xPosition, int yPosition)
 +  {
 +    Rect geometry;
 +
 +    /* Ignore these notifications if not a child of the root
 +       window.  */
 +    if (parent != null)
 +      return;
 +
 +    /* xPosition and yPosition are the position of this window
 +       relative to the screen.  Set them and request a ConfigureNotify
 +       event.  */
 +
 +    if (this.xPosition != xPosition
 +      || this.yPosition != yPosition)
 +      {
 +      this.xPosition = xPosition;
 +      this.yPosition = yPosition;
 +
 +      EmacsNative.sendConfigureNotify (this.handle,
 +                                       System.currentTimeMillis (),
 +                                       xPosition, yPosition,
 +                                       rect.width (), rect.height ());
 +      }
 +  }
 +};
Simple merge
diff --cc lisp/files.el
Simple merge
diff --cc src/pgtkterm.c
Simple merge
diff --cc src/sfntfont.c
index 600eac811d59980c2d5aa2228581c7046a4bbdb3,0000000000000000000000000000000000000000..dbd244e772cf79679f47cd5f34e3a7f657bb4705
mode 100644,000000..100644
--- /dev/null
@@@ -1,3896 -1,0 +1,3896 @@@
-       ASET (entity, FONT_ADSTYLE_INDEX, AREF (vector, 1));      
 +/* sfnt format font driver for GNU Emacs.
 +
 +Copyright (C) 2023 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, write to the Free Software Foundation,
 +Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 +
 +#include <config.h>
 +
 +#include <fcntl.h>
 +#include <ctype.h>
 +
 +#include "lisp.h"
 +
 +#include "blockinput.h"
 +#include "charset.h"
 +#include "coding.h"
 +#include "font.h"
 +#include "frame.h"
 +#include "math.h"
 +#include "sfnt.h"
 +#include "sfntfont.h"
 +
 +#ifdef HAVE_HARFBUZZ
 +#include <hb.h>
 +#include <hb-ot.h>
 +#endif /* HAVE_HARFBUZZ */
 +
 +/* For FRAME_FONT.  */
 +#include TERM_HEADER
 +
 +/* Generic font driver for sfnt-based fonts (currently TrueType, but
 +   it would be easy to add CFF support in the future with a PostScript
 +   renderer.)
 +
 +   This is not a complete font driver.  Hooks must be supplied by the
 +   platform implementer to draw glyphs.  */
 +
 +\f
 +
 +/* Tables associated with each font, be it distortable or not.  This
 +   allows different font objects sharing the same underlying font file
 +   to share tables.  */
 +
 +struct sfnt_font_tables
 +{
 +  /* Various tables required to use the font.  */
 +  struct sfnt_cmap_table *cmap;
 +  struct sfnt_hhea_table *hhea;
 +  struct sfnt_maxp_table *maxp;
 +  struct sfnt_head_table *head;
 +  struct sfnt_hmtx_table *hmtx;
 +  struct sfnt_glyf_table *glyf;
 +  struct sfnt_loca_table_short *loca_short;
 +  struct sfnt_loca_table_long *loca_long;
 +  struct sfnt_prep_table *prep;
 +  struct sfnt_fpgm_table *fpgm;
 +  struct sfnt_cvt_table *cvt;
 +  struct sfnt_fvar_table *fvar;
 +  struct sfnt_avar_table *avar;
 +  struct sfnt_gvar_table *gvar;
 +  struct sfnt_cvar_table *cvar;
 +
 +  /* The selected character map.  */
 +  struct sfnt_cmap_encoding_subtable_data *cmap_data;
 +
 +  /* Data identifying that character map.  */
 +  struct sfnt_cmap_encoding_subtable cmap_subtable;
 +
 +  /* The UVS context.  */
 +  struct sfnt_uvs_context *uvs;
 +
 +#ifdef HAVE_MMAP
 +  /* Whether or not the glyph table has been mmapped.  */
 +  bool glyf_table_mapped;
 +#endif /* HAVE_MMAP */
 +
 +#ifdef HAVE_HARFBUZZ
 +  /* File descriptor associated with this font.  */
 +  int fd;
 +
 +  /* The table directory of the font file.  */
 +  struct sfnt_offset_subtable *directory;
 +#endif /* HAVE_HARFBUZZ */
 +};
 +
 +/* Description of a font that hasn't been opened.  */
 +
 +struct sfnt_font_desc
 +{
 +  /* Next font in this list.  */
 +  struct sfnt_font_desc *next;
 +
 +  /* Family name of the font.  */
 +  Lisp_Object family;
 +
 +  /* Style name of the font.  */
 +  Lisp_Object style;
 +
 +  /* Designer (foundry) of the font.  */
 +  Lisp_Object designer;
 +
 +  /* Style tokens that could not be parsed.  */
 +  Lisp_Object adstyle;
 +
 +  /* List of design languages.  */
 +  Lisp_Object languages;
 +
 +  /* Font registry that this font supports.  */
 +  Lisp_Object registry;
 +
 +  /* Vector of instances.  Each element is another of the instance's
 +     `style', `adstyle', and numeric width, weight, and slant.  May be
 +     nil.  */
 +  Lisp_Object instances;
 +
 +  /* Numeric width, weight, slant and spacing.  */
 +  int width, weight, slant, spacing;
 +
 +  /* Path to the font file.  */
 +  char *path;
 +
 +  /* char table consisting of characters already known to be
 +     present in the font.  */
 +  Lisp_Object char_cache;
 +
 +  /* Whether or not the character map can't be used by Emacs.  */
 +  bool cmap_invalid;
 +
 +  /* The header of the cmap being used.  May be invalid, in which case
 +     platform_id will be 500.  */
 +  struct sfnt_cmap_encoding_subtable subtable;
 +
 +  /* The offset of the table directory within PATH.  */
 +  off_t offset;
 +
 +  /* The number of glyphs in this font.  Used to catch invalid cmap
 +     tables.  This is actually the number of glyphs - 1.  */
 +  int num_glyphs;
 +
 +  /* The number of references to the font tables below.  */
 +  int refcount;
 +
 +  /* List of font tables.  */
 +  struct sfnt_font_tables *tables;
 +};
 +
 +/* List of fonts.  */
 +
 +static struct sfnt_font_desc *system_fonts;
 +
 +/* Font enumeration and matching.  The sfnt driver assumes it can read
 +   data from each font at startup.  It then reads the head, meta and
 +   name tables to determine font data, and records the font in a list
 +   of system fonts that is then matched against.  */
 +
 +/* Set up the coding system CODING to decode string data from the
 +   given platform id ID and platform specific id PLATFORM_SPECIFIC_ID.
 +   Value is 0 upon success, 1 upon failure.  */
 +
 +static int
 +sfnt_setup_coding_system (enum sfnt_platform_id id, int platform_specific_id,
 +                        struct coding_system *coding)
 +{
 +  Lisp_Object system;
 +
 +  system = Qnil;
 +
 +  /* Figure out what coding system to use.  */
 +
 +  switch (id)
 +    {
 +    case SFNT_PLATFORM_UNICODE:
 +      system = Qutf_16be;
 +      break;
 +
 +    case SFNT_PLATFORM_MACINTOSH:
 +
 +      if (platform_specific_id == SFNT_MACINTOSH_ROMAN)
 +      system = Qmac_roman;
 +      else
 +      /* MULE doesn't support the rest... */
 +      system = Qnil;
 +
 +      break;
 +
 +    case SFNT_PLATFORM_MICROSOFT:
 +      system = Qutf_16be;
 +
 +      /* Not sure if this is right.  */
 +      if (platform_specific_id == SFNT_MICROSOFT_BIG_FIVE)
 +      system = Qchinese_big5;
 +
 +      break;
 +
 +    default:
 +      system = Qnil;
 +    }
 +
 +  if (NILP (system))
 +    return 1;
 +
 +  setup_coding_system (system, coding);
 +  return 0;
 +}
 +
 +/* Globals used to communicate inside the condition-case wrapper.  */
 +static struct coding_system *sfnt_font_coding;
 +
 +/* The src_object being encoded from.  This should be on the stack as
 +   well, or it will get garbage collected.  */
 +static Lisp_Object sfnt_font_src_object;
 +
 +/* From-position.  */
 +static ptrdiff_t sfnt_font_from, sfnt_font_from_byte;
 +
 +/* To-position.  */
 +static ptrdiff_t sfnt_font_to, sfnt_font_to_byte;
 +
 +/* Destination object.  Once again, this should also be on the
 +   stack.  */
 +static Lisp_Object sfnt_font_dst_object;
 +
 +/* Error flag.  Set to true if a signal was caught.  */
 +static bool sfnt_font_signal;
 +
 +static Lisp_Object
 +sfnt_safe_decode_coding_object_1 (void)
 +{
 +  decode_coding_object (sfnt_font_coding,
 +                      sfnt_font_src_object,
 +                      sfnt_font_from,
 +                      sfnt_font_from_byte,
 +                      sfnt_font_to,
 +                      sfnt_font_to_byte,
 +                      sfnt_font_dst_object);
 +  return Qnil;
 +}
 +
 +static Lisp_Object
 +sfnt_safe_decode_coding_object_2 (Lisp_Object error)
 +{
 +  sfnt_font_signal = true;
 +
 +  return Qnil;
 +}
 +
 +/* Like decode_coding_object, but return 1 if a signal happens.  Value
 +   is otherwise 0.  */
 +
 +static int
 +sfnt_safe_decode_coding_object (struct coding_system *coding,
 +                              Lisp_Object src_object,
 +                              ptrdiff_t from, ptrdiff_t from_byte,
 +                              ptrdiff_t to, ptrdiff_t to_byte,
 +                              Lisp_Object dst_object)
 +{
 +  sfnt_font_coding = coding;
 +  sfnt_font_src_object = src_object;
 +  sfnt_font_from = from;
 +  sfnt_font_from_byte = from_byte;
 +  sfnt_font_to = to;
 +  sfnt_font_to_byte = to_byte;
 +  sfnt_font_dst_object = dst_object;
 +  sfnt_font_signal = false;
 +
 +  internal_condition_case (sfnt_safe_decode_coding_object_1,
 +                         Qt,
 +                         sfnt_safe_decode_coding_object_2);
 +
 +  return (int) sfnt_font_signal;
 +}
 +
 +/* Decode the specified string DATA.  The encoding is determined based
 +   on PLATFORM_ID, PLATFORM_SPECIFIC_ID and LANGUAGE_ID.  Consult
 +   sfnt.h and the TrueType Reference Manual for more details.  LENGTH
 +   is the length of DATA in bytes.
 +
 +   Value is nil upon failure, else the decoded string.  */
 +
 +static Lisp_Object
 +sfnt_decode_font_string (unsigned char *data, enum sfnt_platform_id id,
 +                       int platform_specific_id, int language_id,
 +                       size_t length)
 +{
 +  struct coding_system coding;
 +
 +  memset (&coding, 0, sizeof coding);
 +  sfnt_setup_coding_system (id, platform_specific_id, &coding);
 +  coding.mode |= CODING_MODE_SAFE_ENCODING;
 +  coding.mode |= CODING_MODE_LAST_BLOCK;
 +  /* Suppress producing escape sequences for composition.  */
 +  coding.common_flags &= ~CODING_ANNOTATION_MASK;
 +  coding.source = data;
 +
 +  if (sfnt_safe_decode_coding_object (&coding, Qnil, 0, 0,
 +                                    length, length, Qt))
 +    return Qnil;
 +
 +  return coding.dst_object;
 +}
 +
 +/* Decode the family and style names from the name table NAME.  Return
 +   0 and the family and style names upon success, else 1.  */
 +
 +static int
 +sfnt_decode_family_style (struct sfnt_name_table *name,
 +                        Lisp_Object *family, Lisp_Object *style)
 +{
 +  struct sfnt_name_record family_rec, style_rec;
 +  unsigned char *family_data, *style_data;
 +
 +  family_data = sfnt_find_name (name, SFNT_NAME_FONT_FAMILY,
 +                              &family_rec);
 +  style_data = sfnt_find_name (name, SFNT_NAME_FONT_SUBFAMILY,
 +                             &style_rec);
 +
 +  if (!family_data || !style_data)
 +    return 1;
 +
 +  /* Now decode the data.  */
 +  *family = sfnt_decode_font_string (family_data,
 +                                   family_rec.platform_id,
 +                                   family_rec.platform_specific_id,
 +                                   family_rec.language_id,
 +                                   family_rec.length);
 +  *style = sfnt_decode_font_string (style_data,
 +                                  style_rec.platform_id,
 +                                  style_rec.platform_specific_id,
 +                                  style_rec.language_id,
 +                                  style_rec.length);
 +
 +  /* Return whether or not it was successful.  */
 +  return (!NILP (*family) && !NILP (*style)) ? 0 : 1;
 +}
 +
 +/* Decode the foundry names from the name table NAME.  Return the
 +   foundry name, or nil upon failure.  */
 +
 +static Lisp_Object
 +sfnt_decode_foundry_name (struct sfnt_name_table *name)
 +{
 +  struct sfnt_name_record designer_rec;
 +  unsigned char *designer_data;
 +
 +  designer_data = sfnt_find_name (name, SFNT_NAME_DESIGNER,
 +                                &designer_rec);
 +
 +  if (!designer_data)
 +    return Qnil;
 +
 +  return sfnt_decode_font_string (designer_data,
 +                                designer_rec.platform_id,
 +                                designer_rec.platform_specific_id,
 +                                designer_rec.language_id,
 +                                designer_rec.length);
 +}
 +
 +/* Decode the name of the specified font INSTANCE using the given NAME
 +   table.  Return the name of that instance, or nil upon failure.  */
 +
 +static Lisp_Object
 +sfnt_decode_instance_name (struct sfnt_instance *instance,
 +                         struct sfnt_name_table *name)
 +{
 +  struct sfnt_name_record name_rec;
 +  unsigned char *name_data;
 +
 +  name_data = sfnt_find_name (name, instance->name_id,
 +                            &name_rec);
 +
 +  if (!name_data)
 +    return Qnil;
 +
 +  return sfnt_decode_font_string (name_data,
 +                                name_rec.platform_id,
 +                                name_rec.platform_specific_id,
 +                                name_rec.language_id,
 +                                name_rec.length);
 +}
 +
 +struct sfnt_style_desc
 +{
 +  /* The C string to match against.  */
 +  const char *c_string;
 +
 +  /* The value of the style field.  */
 +  int value;
 +};
 +
 +/* Array of style descriptions describing weight.  */
 +static struct sfnt_style_desc sfnt_weight_descriptions[] =
 +  {
 +    { "thin", 0,              },
 +    { "extralight", 40,               },
 +    { "ultralight", 40,               },
 +    { "light", 50,            },
 +    { "demilight", 55,                },
 +    { "semilight", 55,                },
 +    { "book", 75,             },
 +    { "medium", 100,          },
 +    { "demibold", 180,                },
 +    { "semibold", 180,                },
 +    { "bold", 200,            },
 +    { "extrabold", 205,               },
 +    { "ultrabold", 205,               },
 +    { "black", 210,           },
 +    { "heavy", 210,           },
 +    { "extrablack", 215,      },
 +    { "ultrablack", 215,      },
 +  };
 +
 +/* Array of style descriptions describing slant.  */
 +static struct sfnt_style_desc sfnt_slant_descriptions[] =
 +  {
 +    { "italic", 200,  },
 +    { "oblique", 210, },
 +  };
 +
 +/* Array of style descriptions describing width.  */
 +static struct sfnt_style_desc sfnt_width_descriptions[] =
 +  {
 +    { "ultracondensed", 50,   },
 +    { "extracondensed", 63,   },
 +    { "condensed", 75,                },
 +    { "semicondensed", 87,    },
 +    { "semiexpanded", 113,    },
 +    { "expanded", 125,                },
 +    { "extraexpanded", 150,   },
 +    { "ultraexpanded", 200,   },
 +  };
 +
 +/* Figure out DESC->width, DESC->weight, DESC->slant and DESC->spacing
 +   based on the style name passed as STYLE_NAME.
 +
 +   Also append any unknown tokens to DESC->adstyle.  */
 +
 +static void
 +sfnt_parse_style (Lisp_Object style_name, struct sfnt_font_desc *desc)
 +{
 +  char *style, *single, *saveptr;
 +  int i;
 +  USE_SAFE_ALLOCA;
 +
 +  /* Fill in default values.  slant seems to not be consistent with
 +     Fontconfig.  */
 +  desc->weight = 80;
 +  desc->slant = 100;
 +  desc->width = 100;
 +
 +  /* Split the style into tokens delimited by spaces.  Attempt to find
 +     a token specifying each of the weight, slant, or width attributes
 +     using their respective descriptions arrays as a reference.  */
 +
 +  SAFE_ALLOCA_STRING (style, Fdowncase (style_name));
 +  saveptr = NULL;
 +
 +  while ((single = strtok_r (style, " ", &saveptr)))
 +    {
 +      style = NULL;
 +
 +      if (desc->weight == 80)
 +      {
 +        /* Weight hasn't been found yet.  Scan through the weight
 +           table.  */
 +        for (i = 0; i < ARRAYELTS (sfnt_weight_descriptions); ++i)
 +          {
 +            if (!strcmp (sfnt_weight_descriptions[i].c_string,
 +                         single))
 +              {
 +                /* Weight found.  Continue on reading the slant and
 +                   width.  */
 +                desc->weight = sfnt_weight_descriptions[i].value;
 +                goto next;
 +              }
 +          }
 +      }
 +
 +      if (desc->slant == 100)
 +      {
 +        /* Slant hasn't been found yet.  Scan through the slant
 +           table.  */
 +        for (i = 0; i < ARRAYELTS (sfnt_slant_descriptions); ++i)
 +          {
 +            if (!strcmp (sfnt_slant_descriptions[i].c_string,
 +                         single))
 +              {
 +                /* Slant found.  Continue on reading the weight and
 +                   width.  */
 +                desc->slant = sfnt_slant_descriptions[i].value;
 +                goto next;
 +              }
 +          }
 +      }
 +
 +      if (desc->width == 100)
 +      {
 +        /* Width hasn't been found yet.  Scan through the width
 +           table.  */
 +        for (i = 0; i < ARRAYELTS (sfnt_width_descriptions); ++i)
 +          {
 +            if (!strcmp (sfnt_width_descriptions[i].c_string,
 +                         single))
 +              {
 +                /* Width found.  Continue on reading the slant and
 +                   weight.  */
 +                desc->width = sfnt_width_descriptions[i].value;
 +                goto next;
 +              }
 +          }
 +      }
 +
 +      /* This token is extraneous or was not recognized.  Capitalize
 +       the first letter and set it as the adstyle.  */
 +
 +      if (strlen (single))
 +      {
 +        if (islower (single[0]))
 +          single[0] = toupper (single[0]);
 +
 +        if (NILP (desc->adstyle))
 +          desc->adstyle = build_string (single);
 +        else
 +          desc->adstyle = CALLN (Fconcat, desc->adstyle,
 +                                 build_string (" "),
 +                                 build_string (single));
 +      }
 +
 +    next:
 +      continue;
 +    }
 +
 +  SAFE_FREE ();
 +}
 +
 +/* Parse the list of design languages in META, a font metadata table,
 +   and place the results in DESC->languages.  Do nothing if there is
 +   no such metadata.  */
 +
 +static void
 +sfnt_parse_languages (struct sfnt_meta_table *meta,
 +                    struct sfnt_font_desc *desc)
 +{
 +  char *data, *metadata, *tag;
 +  struct sfnt_meta_data_map map;
 +  char *saveptr;
 +
 +  /* Look up the ``design languages'' metadata.  This is a comma (and
 +     possibly space) separated list of scripts that the font was
 +     designed for.  Here is an example of one such tag:
 +
 +       zh-Hans,Jpan,Kore
 +
 +     for a font that covers Simplified Chinese, along with Japanese
 +     and Korean text.  */
 +
 +  saveptr = NULL;
 +  data = sfnt_find_metadata (meta, SFNT_META_DATA_TAG_DLNG,
 +                           &map);
 +
 +  if (!data)
 +    {
 +      /* Fall back to the supported languages metadata.  */
 +      data = sfnt_find_metadata (meta, SFNT_META_DATA_TAG_SLNG,
 +                               &map);
 +
 +      if (!data)
 +      return;
 +    }
 +
 +  USE_SAFE_ALLOCA;
 +
 +  /* Now copy metadata and add a trailing NULL byte.  */
 +
 +  if (map.data_length >= SIZE_MAX)
 +    memory_full (SIZE_MAX);
 +
 +  metadata = SAFE_ALLOCA ((size_t) map.data_length + 1);
 +  memcpy (metadata, data, map.data_length);
 +  metadata[map.data_length] = '\0';
 +
 +  /* Loop through each script-language tag.  Note that there may be
 +     extra leading spaces.  */
 +  while ((tag = strtok_r (metadata, ",", &saveptr)))
 +    {
 +      metadata = NULL;
 +
 +      if (strstr (tag, "Hans") || strstr (tag, "Hant"))
 +      desc->languages = Fcons (Qzh, desc->languages);
 +
 +      if (strstr (tag, "Japn"))
 +      desc->languages = Fcons (Qja, desc->languages);
 +
 +      if (strstr (tag, "Kore"))
 +      desc->languages = Fcons (Qko, desc->languages);
 +    }
 +
 +  SAFE_FREE ();
 +}
 +
 +/* Return the font registry corresponding to the encoding subtable
 +   SUBTABLE.
 +
 +   Under X, the font registry is an atom registered with the Open
 +   Group uniquely identifying the organization which defines the
 +   font's character set.
 +
 +   In practice, the registry overlaps with the character set itself.
 +   So Emacs just uses the ``registry'' field of each font object and
 +   entity to represent both instead.  */
 +
 +static Lisp_Object
 +sfnt_registry_for_subtable (struct sfnt_cmap_encoding_subtable *subtable)
 +{
 +  switch (subtable->platform_id)
 +    {
 +    case SFNT_PLATFORM_UNICODE:
 +      /* Reject variation selector and last resort tables.  */
 +      if ((subtable->platform_specific_id
 +         == SFNT_UNICODE_VARIATION_SEQUENCES)
 +        || (subtable->platform_specific_id
 +            == SFNT_UNICODE_LAST_RESORT))
 +      return Qnil;
 +
 +      return Qiso10646_1;
 +
 +    case SFNT_PLATFORM_MACINTOSH:
 +
 +      switch (subtable->platform_specific_id)
 +      {
 +      case SFNT_MACINTOSH_ROMAN:
 +        /* X calls mac-roman ``apple-roman''.  */
 +        return Qapple_roman;
 +
 +      default:
 +        /* Some other Macintosh charset not supported by Emacs.  */
 +        return Qnil;
 +      }
 +
 +    case SFNT_PLATFORM_MICROSOFT:
 +
 +      /* Microsoft specific encodings.  */
 +
 +      switch (subtable->platform_specific_id)
 +      {
 +      case SFNT_MICROSOFT_SYMBOL:
 +      case SFNT_MICROSOFT_UNICODE_BMP:
 +        /* Symbols in the Unicode PUA are still Unicode.  */
 +        return Qiso10646_1;
 +
 +      case SFNT_MICROSOFT_SHIFT_JIS:
 +        return Qjisx0208_1983_0;
 +
 +      case SFNT_MICROSOFT_PRC:
 +        return Qgbk;
 +
 +      case SFNT_MICROSOFT_JOHAB:
 +        return Qksc5601_1987_0;
 +
 +      case SFNT_MICROSOFT_UNICODE_UCS_4:
 +        return Qiso10646_1;
 +      }
 +
 +    default:
 +      return Qnil;
 +    }
 +}
 +
 +/* Return the type of characters that the cmap subtable SUBTABLE maps
 +   from.  Value is:
 +
 +   2 if SUBTABLE maps from Unicode characters, including those outside
 +   the Unicode Basic Multilingual Plane (BMP).
 +
 +   1 if SUBTABLE maps from Unicode characters within the BMP.
 +
 +   0 if SUBTABLE maps from some other character set that Emacs knows
 +   about.
 +
 +   3 if SUBTABLE cannot be used by Emacs.  */
 +
 +static int
 +sfntfont_identify_cmap (struct sfnt_cmap_encoding_subtable subtable)
 +{
 +  switch (subtable.platform_id)
 +    {
 +    case SFNT_PLATFORM_UNICODE:
 +
 +      /* Reject variation selector and last resort tables.  */
 +      if ((subtable.platform_specific_id
 +         == SFNT_UNICODE_VARIATION_SEQUENCES)
 +        || (subtable.platform_specific_id
 +            == SFNT_UNICODE_LAST_RESORT))
 +      return 3;
 +
 +      /* 1.0, 1.1, ISO-10646-1993, and 2.0_BMP tables are all within
 +       the BMP.  */
 +      if (subtable.platform_specific_id < SFNT_UNICODE_2_0)
 +      return 1;
 +
 +      return 2;
 +
 +    case SFNT_PLATFORM_MACINTOSH:
 +
 +      switch (subtable.platform_specific_id)
 +      {
 +      case SFNT_MACINTOSH_ROMAN:
 +        /* mac-roman */
 +        return 0;
 +
 +      default:
 +        /* Some other Macintosh charset not supported by Emacs.  */
 +        return 3;
 +      }
 +
 +    case SFNT_PLATFORM_MICROSOFT:
 +
 +      /* Microsoft specific encodings.  */
 +
 +      switch (subtable.platform_specific_id)
 +      {
 +      case SFNT_MICROSOFT_SYMBOL:
 +        /* Symbols in the Unicode PUA are still Unicode.  */
 +        return 1;
 +
 +      case SFNT_MICROSOFT_UNICODE_BMP:
 +        return 1;
 +
 +      case SFNT_MICROSOFT_SHIFT_JIS:
 +        /* PCK aka japanese-jisx0208.  */
 +        return 0;
 +
 +      case SFNT_MICROSOFT_PRC:
 +        /* GBK, GB2312 or GB18030.  */
 +        return 0;
 +
 +      case SFNT_MICROSOFT_JOHAB:
 +        /* KS C 5601-1992, aka korean-ksc5601.  */
 +        return 0;
 +
 +      case SFNT_MICROSOFT_UNICODE_UCS_4:
 +        /* Unicode past the BMP.  */
 +        return 2;
 +      }
 +
 +    default:
 +      return 3;
 +    }
 +}
 +
 +/* Figure out which registry DESC, backed by FD, whose table directory
 +   is SUBTABLE, is likely to support.
 +
 +   Read the header of each subtable in the character map and compute
 +   the registry to use; then, set DESC->registry to that value.  */
 +
 +static void
 +sfnt_grok_registry (int fd, struct sfnt_font_desc *desc,
 +                  struct sfnt_offset_subtable *subtable)
 +{
 +  struct sfnt_cmap_table *cmap;
 +  struct sfnt_cmap_encoding_subtable *subtables;
 +  int i;
 +
 +  cmap = sfnt_read_cmap_table (fd, subtable, &subtables, NULL);
 +
 +  if (!cmap)
 +    return;
 +
 +  /* Now pick the ``best'' character map the same way as sfntfont_open
 +     does.  The caveat is that since the subtable data has not been
 +     read, Emacs cannot determine whether or not the encoding subtable
 +     is valid.
 +
 +     Once platform_id is set, that value becomes much more
 +     reliable.  */
 +
 +  /* First look for a non-BMP Unicode cmap.  */
 +
 +  for (i = 0; i < cmap->num_subtables; ++i)
 +    {
 +      if (sfntfont_identify_cmap (subtables[i]) == 2)
 +      {
 +        desc->registry
 +          = sfnt_registry_for_subtable (&subtables[i]);
 +        goto done;
 +      }
 +    }
 +
 +  /* Next, look for a BMP only Unicode cmap.  */
 +
 +  for (i = 0; i < cmap->num_subtables; ++i)
 +    {
 +      if (sfntfont_identify_cmap (subtables[i]) == 1)
 +        {
 +        desc->registry
 +          = sfnt_registry_for_subtable (&subtables[i]);
 +        goto done;
 +      }
 +    }
 +
 +  /* Finally, use the first cmap that appears and can be
 +     identified.  */
 +
 +  for (i = 0; i < cmap->num_subtables; ++i)
 +    {
 +      if (sfntfont_identify_cmap (subtables[i]) == 0)
 +        {
 +        desc->registry
 +          = sfnt_registry_for_subtable (&subtables[i]);
 +        goto done;
 +      }
 +    }
 +
 +  /* There are no cmaps available to Emacs.  */
 + done:
 +  xfree (cmap);
 +  xfree (subtables);
 +}
 +
 +/* Return whether or not the font description PREV conflicts with the
 +   newer font description DESC, and should be removed from the list of
 +   system fonts.
 +
 +   If PREV is a variable font, potentially adjust its list of
 +   instances.  */
 +
 +static bool
 +sfnt_replace_fonts_p (struct sfnt_font_desc *prev,
 +                    struct sfnt_font_desc *desc)
 +{
 +  int i, width, weight, slant, count_instance;
 +  Lisp_Object tem;
 +  bool family_equal_p;
 +
 +  family_equal_p = !NILP (Fstring_equal (prev->family,
 +                                       desc->family));
 +
 +  if ((!NILP (desc->instances)
 +       || !NILP (Fstring_equal (prev->style, desc->style)))
 +      && family_equal_p)
 +    return true;
 +
 +  if (NILP (prev->instances) || !family_equal_p)
 +    return false;
 +
 +  /* Look through instances in PREV to see if DESC provides the same
 +     thing.  */
 +
 +  count_instance = 0;
 +  for (i = 0; i < ASIZE (prev->instances); ++i)
 +    {
 +      tem = AREF (prev->instances, i);
 +
 +      if (NILP (tem))
 +      continue;
 +
 +      width = XFIXNUM (AREF (tem, 2));
 +      weight = XFIXNUM (AREF (tem, 3));
 +      slant = XFIXNUM (AREF (tem, 4));
 +
 +      if (desc->width == width
 +        && desc->weight == weight
 +        && desc->slant == slant)
 +      {
 +        /* Remove this instance.  */
 +        ASET (prev->instances, i, Qnil);
 +        continue;
 +      }
 +
 +      count_instance++;
 +    }
 +
 +  /* Remove this desc if there are no more instances.  */
 +  return count_instance < 1;
 +}
 +
 +/* Enumerate the offset subtable SUBTABLES in the file FD, whose file
 +   name is FILE.  OFFSET should be the offset of the subtable within
 +   the font file, and is recorded for future use.  Value is 1 upon
 +   failure, else 0.  */
 +
 +static int
 +sfnt_enum_font_1 (int fd, const char *file,
 +                struct sfnt_offset_subtable *subtables,
 +                off_t offset)
 +{
 +  struct sfnt_font_desc *desc, **next, *prev;
 +  struct sfnt_head_table *head;
 +  struct sfnt_name_table *name;
 +  struct sfnt_meta_table *meta;
 +  struct sfnt_maxp_table *maxp;
 +  struct sfnt_fvar_table *fvar;
 +  struct sfnt_font_desc temp;
 +  Lisp_Object family, style, instance, style1;
 +  int i;
 +
 +  /* Create the font desc and copy in the file name.  */
 +  desc = xzalloc (sizeof *desc + strlen (file) + 1);
 +  desc->path = (char *) (desc + 1);
 +  memcpy (desc->path, file, strlen (file) + 1);
 +  desc->offset = offset;
 +
 +  /* Check that this is a TrueType font.  */
 +  if (subtables->scaler_type != SFNT_SCALER_TRUE
 +      && subtables->scaler_type != SFNT_SCALER_VER1)
 +    goto bail1;
 +
 +  /* Read required tables.  */
 +  head = sfnt_read_head_table (fd, subtables);
 +  if (!head)
 +    goto bail1;
 +
 +  name = sfnt_read_name_table (fd, subtables);
 +  if (!name)
 +    goto bail2;
 +
 +  maxp = sfnt_read_maxp_table (fd, subtables);
 +  if (!maxp)
 +    goto bail3;
 +
 +  /* meta is not required, nor present on many non-Apple fonts.  */
 +  meta = sfnt_read_meta_table (fd, subtables);
 +
 +  /* Decode the family and style from the name table.  */
 +  if (sfnt_decode_family_style (name, &family, &style))
 +    goto bail4;
 +
 +  /* See if this is a distortable/variable/multiple master font (all
 +     three terms mean the same time.)  */
 +  fvar = sfnt_read_fvar_table (fd, subtables);
 +
 +  /* Set the family.  */
 +  desc->family = family;
 +  desc->designer = sfnt_decode_foundry_name (name);
 +  desc->char_cache = Qnil;
 +  desc->subtable.platform_id = 500;
 +
 +  /* Set the largest glyph identifier.  */
 +  desc->num_glyphs = maxp->num_glyphs;
 +
 +  /* Parse the style.  */
 +  sfnt_parse_style (style, desc);
 +
 +  /* If the meta table exists, parse the list of design languages.  */
 +  if (meta)
 +    sfnt_parse_languages (meta, desc);
 +
 +  /* Figure out the spacing.  Some fancy test like what Fontconfig
 +     does is probably in order but not really necessary.  */
 +  if (!NILP (Fstring_search (Fdowncase (family),
 +                           build_string ("mono"),
 +                           Qnil)))
 +    desc->spacing = 100; /* FC_MONO */
 +
 +  /* Finally add mac-style flags.  Allow them to override styles that
 +     have not been found.  */
 +
 +  if (head->mac_style & 01 && desc->weight == 80) /* Bold */
 +    desc->weight = 200;
 +
 +  if (head->mac_style & 02 && desc->slant == 0) /* Italic */
 +    desc->slant = 100;
 +
 +  /* Figure out what registry this font is likely to support.  */
 +  sfnt_grok_registry (fd, desc, subtables);
 +
 +  if (fvar && fvar->instance_count)
 +    {
 +      /* If there is an fvar table with instances, then this is a font
 +       which defines different axes along which the points in each
 +       glyph can be changed.
 +
 +         Instead of enumerating the font itself, enumerate each
 +         instance within, which specifies how to configure each axis
 +         to achieve a specified style.  */
 +
 +      desc->instances = make_vector (fvar->instance_count, Qnil);
 +
 +      for (i = 0; i < fvar->instance_count; ++i)
 +      {
 +        style1 = sfnt_decode_instance_name (&fvar->instance[i],
 +                                            name);
 +
 +        if (NILP (style1))
 +          continue;
 +
 +        /* Now parse the style.  */
 +        temp.adstyle = Qnil;
 +        sfnt_parse_style (style1, &temp);
 +
 +        /* Set each field of the vector.  */
 +        instance = make_vector (5, Qnil);
 +        ASET (instance, 0, style1);
 +        ASET (instance, 1, temp.adstyle);
 +        ASET (instance, 2, make_fixnum (temp.width));
 +        ASET (instance, 3, make_fixnum (temp.weight));
 +        ASET (instance, 4, make_fixnum (temp.slant));
 +
 +        /* Place the vector in desc->instances.  */
 +        ASET (desc->instances, i, instance);
 +      }
 +    }
 +
 +  /* Set the style, link the desc onto system_fonts and return.  */
 +  desc->style = style;
 +  desc->next = system_fonts;
 +  system_fonts = desc;
 +
 +  /* Remove any fonts which have the same style as this one.  For
 +     distortable fonts, only remove overlapping styles, unless this is
 +     also a distortable font.  */
 +
 +  next = &system_fonts->next;
 +  prev = *next;
 +  for (; *next; prev = *next)
 +    {
 +      if (sfnt_replace_fonts_p (prev, desc))
 +      {
 +        *next = prev->next;
 +        xfree (prev);
 +      }
 +      else
 +      next = &prev->next;
 +    }
 +
 +  xfree (fvar);
 +  xfree (meta);
 +  xfree (maxp);
 +  xfree (name);
 +  xfree (head);
 +  return 0;
 +
 + bail4:
 +  xfree (meta);
 +  xfree (maxp);
 + bail3:
 +  xfree (name);
 + bail2:
 +  xfree (head);
 + bail1:
 +  xfree (desc);
 +  return 1;
 +}
 +
 +/* Enumerate the font FILE into the list of system fonts.  Return 1 if
 +   it could not be enumerated, 0 otherwise.
 +
 +   Remove any font whose family and style is a duplicate of this one.
 +
 +   FILE can either be a TrueType collection file containing TrueType
 +   fonts, or a TrueType font itself.  */
 +
 +int
 +sfnt_enum_font (const char *file)
 +{
 +  int fd, rc;
 +  struct sfnt_offset_subtable *subtables;
 +  struct sfnt_ttc_header *ttc;
 +  size_t i;
 +
 +  /* Now open the font for reading.  */
 +  fd = emacs_open (file, O_RDONLY, 0);
 +
 +  if (fd == -1)
 +    goto bail;
 +
 +  /* Read the table directory.  */
 +  subtables = sfnt_read_table_directory (fd);
 +
 +  if (subtables == (struct sfnt_offset_subtable *) -1)
 +    {
 +      /* This is actually a TrueType container file.  Go back to the
 +       beginning and read the TTC header.  */
 +
 +      if (lseek (fd, 0, SEEK_SET))
 +      goto bail0;
 +
 +      ttc = sfnt_read_ttc_header (fd);
 +
 +      if (!ttc)
 +      goto bail0;
 +
 +      /* Enumerate each of the fonts in the collection.  */
 +
 +      for (i = 0; i < ttc->num_fonts; ++i)
 +      {
 +        if (lseek (fd, ttc->offset_table[i], SEEK_SET)
 +            != ttc->offset_table[i])
 +          continue;
 +
 +        subtables = sfnt_read_table_directory (fd);
 +
 +        if (!subtables
 +            /* This value means that FD was pointing at a TTC
 +               header.  Since FD should already have been moved to
 +               the beginning of the TrueType header above, it
 +               follows that the font format is invalid.  */
 +            || (subtables == (struct sfnt_offset_subtable *) -1))
 +          continue;
 +
 +        sfnt_enum_font_1 (fd, file, subtables,
 +                          ttc->offset_table[i]);
 +        xfree (subtables);
 +      }
 +
 +      /* Always treat reading containers as having been
 +       successful.  */
 +
 +      emacs_close (fd);
 +      xfree (ttc);
 +      return 0;
 +    }
 +
 +  if (!subtables)
 +    goto bail0;
 +
 +  /* Now actually enumerate this font.  */
 +  rc = sfnt_enum_font_1 (fd, file, subtables, 0);
 +  xfree (subtables);
 +  emacs_close (fd);
 +  return rc;
 +
 + bail0:
 +  emacs_close (fd);
 + bail:
 +  return 1;
 +}
 +
 +\f
 +
 +/* Font discovery and matching.  */
 +
 +static struct charset *
 +sfntfont_charset_for_name (Lisp_Object symbol)
 +{
 +  ptrdiff_t idx;
 +  int id;
 +
 +  idx = CHARSET_SYMBOL_HASH_INDEX (symbol);
 +
 +  if (idx == -1)
 +    return NULL;
 +
 +  /* Vcharset_hash_table is not a real variable, so Lisp programs
 +     can't clobber it.  */
 +  id = XFIXNUM (AREF (HASH_VALUE (XHASH_TABLE (Vcharset_hash_table),
 +                                idx),
 +                    charset_id));
 +
 +  return CHARSET_FROM_ID (id);
 +}
 +
 +/* Return the character set corresponding to a cmap subtable SUBTABLE.
 +   Value is NULL if the subtable is not supported.  */
 +
 +static struct charset *
 +sfntfont_charset_for_cmap (struct sfnt_cmap_encoding_subtable subtable)
 +{
 +  switch (subtable.platform_id)
 +    {
 +    case SFNT_PLATFORM_UNICODE:
 +      /* Reject variation selector and last resort tables.  */
 +      if ((subtable.platform_specific_id
 +         == SFNT_UNICODE_VARIATION_SEQUENCES)
 +        || (subtable.platform_specific_id
 +            == SFNT_UNICODE_LAST_RESORT))
 +      return NULL;
 +
 +      /* 1.0, 1.1, ISO-10646-1993, and 2.0_BMP tables are all within
 +       the BMP.  */
 +      if (subtable.platform_specific_id < SFNT_UNICODE_2_0)
 +      return sfntfont_charset_for_name (Qunicode_bmp);
 +
 +      return sfntfont_charset_for_name (Qunicode);
 +
 +    case SFNT_PLATFORM_MACINTOSH:
 +
 +      switch (subtable.platform_specific_id)
 +      {
 +      case SFNT_MACINTOSH_ROMAN:
 +        return sfntfont_charset_for_name (Qmac_roman);
 +
 +      default:
 +        /* Some other Macintosh charset not supported by Emacs.  */
 +        return NULL;
 +      }
 +
 +    case SFNT_PLATFORM_MICROSOFT:
 +
 +      /* Microsoft specific encodings.  */
 +
 +      switch (subtable.platform_specific_id)
 +      {
 +      case SFNT_MICROSOFT_SYMBOL:
 +        /* Symbols in the Unicode PUA are still Unicode.  */
 +        return sfntfont_charset_for_name (Qunicode);
 +
 +      case SFNT_MICROSOFT_UNICODE_BMP:
 +        return sfntfont_charset_for_name (Qunicode_bmp);
 +
 +      case SFNT_MICROSOFT_SHIFT_JIS:
 +        /* PCK aka japanese-jisx0208.  */
 +        return sfntfont_charset_for_name (Qjapanese_jisx0208);
 +
 +      case SFNT_MICROSOFT_PRC:
 +        /* GBK, GB2312 or GB18030.  */
 +        return sfntfont_charset_for_name (Qgbk);
 +
 +      case SFNT_MICROSOFT_JOHAB:
 +        /* KS C 5601-1992, aka korean-ksc5601.  */
 +        return sfntfont_charset_for_name (Qkorean_ksc5601);
 +
 +      case SFNT_MICROSOFT_UNICODE_UCS_4:
 +        /* Unicode past the BMP.  */
 +        return sfntfont_charset_for_name (Qucs);
 +      }
 +
 +    default:
 +      return NULL;
 +    }
 +}
 +
 +/* Pick the best character map in the cmap table CMAP.  Use the
 +   subtables in SUBTABLES and DATA.  Return the subtable data and the
 +   subtable in *SUBTABLE upon success, NULL otherwise.
 +
 +   If FORMAT14 is non-NULL, return any associated format 14 variation
 +   selection context in *FORMAT14 should the selected charcter map be
 +   a Unicode character map.  */
 +
 +static struct sfnt_cmap_encoding_subtable_data *
 +sfntfont_select_cmap (struct sfnt_cmap_table *cmap,
 +                    struct sfnt_cmap_encoding_subtable *subtables,
 +                    struct sfnt_cmap_encoding_subtable_data **data,
 +                    struct sfnt_cmap_encoding_subtable *subtable,
 +                    struct sfnt_cmap_format_14 **format14)
 +{
 +  int i, j;
 +
 +  /* First look for a non-BMP Unicode cmap.  */
 +
 +  for (i = 0; i < cmap->num_subtables; ++i)
 +    {
 +      if (data[i] && sfntfont_identify_cmap (subtables[i]) == 2)
 +      {
 +        *subtable = subtables[i];
 +
 +        if (!format14)
 +          return data[i];
 +
 +        /* Search for a correspoinding format 14 character map.
 +           This is used in conjunction with the selected character
 +           map to map variation sequences.  */
 +
 +        for (j = 0; j < cmap->num_subtables; ++j)
 +          {
 +            if (data[j]
 +                && subtables[j].platform_id == SFNT_PLATFORM_UNICODE
 +                && (subtables[j].platform_specific_id
 +                    == SFNT_UNICODE_VARIATION_SEQUENCES)
 +                && data[j]->format == 14)
 +              *format14 = (struct sfnt_cmap_format_14 *) data[j];
 +          }
 +
 +        return data[i];
 +      }
 +    }
 +
 +  /* Next, look for a BMP only Unicode cmap.  */
 +
 +  for (i = 0; i < cmap->num_subtables; ++i)
 +    {
 +      if (data[i] && sfntfont_identify_cmap (subtables[i]) == 1)
 +      {
 +        *subtable = subtables[i];
 +
 +        if (!format14)
 +          return data[i];
 +
 +        /* Search for a correspoinding format 14 character map.
 +           This is used in conjunction with the selected character
 +           map to map variation sequences.  */
 +
 +        for (j = 0; j < cmap->num_subtables; ++j)
 +          {
 +            if (data[j]
 +                && subtables[j].platform_id == SFNT_PLATFORM_UNICODE
 +                && (subtables[j].platform_specific_id
 +                    == SFNT_UNICODE_VARIATION_SEQUENCES)
 +                && data[j]->format == 14)
 +              *format14 = (struct sfnt_cmap_format_14 *) data[j];
 +          }
 +
 +        return data[i];
 +      }
 +    }
 +
 +  /* Finally, use the first cmap that appears and can be
 +     identified.  */
 +
 +  for (i = 0; i < cmap->num_subtables; ++i)
 +    {
 +      if (data[i] && sfntfont_identify_cmap (subtables[i]) == 0)
 +      {
 +        *subtable = subtables[i];
 +        return data[i];
 +      }
 +    }
 +
 +  /* There are no cmaps available to Emacs.  */
 +  return NULL;
 +}
 +
 +/* Read the cmap from the font descriptor DESC, and place it in CMAP.
 +   Keep *CMAP untouched if opening the cmap fails.  Set SUBTABLE to
 +   the cmap's header upon success.  */
 +
 +static void
 +sfntfont_read_cmap (struct sfnt_font_desc *desc,
 +                  struct sfnt_cmap_encoding_subtable_data **cmap,
 +                  struct sfnt_cmap_encoding_subtable *subtable)
 +{
 +  struct sfnt_offset_subtable *font;
 +  struct sfnt_cmap_encoding_subtable *subtables;
 +  struct sfnt_cmap_encoding_subtable_data **data;
 +  struct sfnt_cmap_table *table;
 +  int fd, i;
 +
 +  /* Pick a character map and place it in *CMAP.  */
 +  fd = emacs_open (desc->path, O_RDONLY, 0);
 +
 +  if (fd < 0)
 +    return;
 +
 +  /* Seek to the start of the font itself within its collection.  */
 +
 +  if (desc->offset
 +      && lseek (fd, desc->offset, SEEK_SET) != desc->offset)
 +    {
 +      emacs_close (fd);
 +      return;
 +    }
 +
 +  font = sfnt_read_table_directory (fd);
 +
 +  /* Return if FONT is a TrueType collection: the file pointer should
 +     already have been moved to the start of the table directory if
 +     so.  */
 +
 +  if (!font || (font == (struct sfnt_offset_subtable *) -1))
 +    {
 +      emacs_close (fd);
 +      return;
 +    }
 +
 +  table = sfnt_read_cmap_table (fd, font, &subtables,
 +                              &data);
 +  xfree (font);
 +
 +  if (!table)
 +    {
 +      emacs_close (fd);
 +      return;
 +    }
 +
 +  /* Now pick the best character map.  */
 +
 +  *cmap = sfntfont_select_cmap (table, subtables, data,
 +                              subtable, NULL);
 +
 +  /* Free the cmap data.  */
 +
 +  for (i = 0; i < table->num_subtables; ++i)
 +    {
 +      if (data[i] != *cmap)
 +      xfree (data[i]);
 +    }
 +
 +  xfree (data);
 +  xfree (subtables);
 +  xfree (table);
 +  emacs_close (fd);
 +}
 +
 +/* Return whether or not CHARACTER has an associated mapping in CMAP,
 +   and the mapping points to a valid glyph.  DESC is the font
 +   descriptor associated with the font.  */
 +
 +static bool
 +sfntfont_glyph_valid (struct sfnt_font_desc *desc,
 +                    sfnt_char font_character,
 +                    struct sfnt_cmap_encoding_subtable_data *cmap)
 +{
 +  sfnt_glyph glyph;
 +
 +  glyph = sfnt_lookup_glyph (font_character, cmap);
 +
 +  if (!glyph)
 +    return false;
 +
 +  return glyph <= desc->num_glyphs;
 +}
 +
 +/* Look up a character CHARACTER in the font description DESC.  Cache
 +   the results.  Return true if the character exists, false otherwise.
 +
 +   If *CMAP is NULL, select a character map for the font and save it
 +   there.  Otherwise, use the character map in *CMAP.  Save data
 +   associated with the character map in *SUBTABLE.  */
 +
 +static bool
 +sfntfont_lookup_char (struct sfnt_font_desc *desc, Lisp_Object character,
 +                    struct sfnt_cmap_encoding_subtable_data **cmap,
 +                    struct sfnt_cmap_encoding_subtable *subtable)
 +{
 +  Lisp_Object cached;
 +  sfnt_char font_character;
 +  struct charset *charset;
 +  bool present;
 +
 +  /* Return false for characters that don't fit in a char table.  */
 +  if (XFIXNUM (character) > INT_MAX || XFIXNUM (character) < 0)
 +    return false;
 +
 +  if (!NILP (desc->char_cache))
 +    {
 +      cached = char_table_ref (desc->char_cache,
 +                             XFIXNUM (character));
 +      if (!NILP (cached))
 +      return (EQ (cached, Qlambda) ? false : true);
 +    }
 +
 +  if (!*cmap && !desc->cmap_invalid)
 +    sfntfont_read_cmap (desc, cmap, subtable);
 +
 +  /* Check that a cmap is now present.  */
 +  if (!*cmap)
 +    {
 +      /* Opening the cmap failed.  Set desc->cmap_invalid to avoid
 +       opening it again.  */
 +      desc->cmap_invalid = true;
 +      return false;
 +    }
 +
 +  /* Otherwise, encode the character.  */
 +
 +  charset = sfntfont_charset_for_cmap (*subtable);
 +  if (!charset)
 +    /* Emacs missing charsets? */
 +    return false;
 +
 +  font_character = ENCODE_CHAR (charset, (int) XFIXNUM (character));
 +
 +  if (font_character == CHARSET_INVALID_CODE (charset))
 +    return false;
 +
 +  /* Now return whether or not the glyph is present.  Noto Sans
 +     Georgian comes with a corrupt format 4 cmap table that somehow
 +     tries to express glyphs greater than 65565.  */
 +  present = sfntfont_glyph_valid (desc, font_character, *cmap);
 +
 +  /* Cache the result.  Store Qlambda when not present, Qt
 +     otherwise.  */
 +
 +  if (NILP (desc->char_cache))
 +    desc->char_cache = Fmake_char_table (Qfont_lookup_cache,
 +                                       Qnil);
 +
 +  Fset_char_table_range (desc->char_cache, character,
 +                       present ? Qt : Qlambda);
 +  return present;
 +}
 +
 +/* Return whether or not the specified registry A is ``compatible''
 +   with registry B.
 +
 +   Compatibility does not refer to whether or not the font registries
 +   have an identical character set or repertory of characters.
 +
 +   Instead, it refers to whether or not Emacs expects looking for A to
 +   result in fonts used with B.  */
 +
 +static bool
 +sfntfont_registries_compatible_p (Lisp_Object a, Lisp_Object b)
 +{
 +  if (EQ (a, Qiso8859_1) && EQ (b, Qiso10646_1))
 +    return true;
 +
 +  return EQ (a, b);
 +}
 +
 +/* Return whether or not the font description DESC satisfactorily
 +   matches the font specification FONT_SPEC.
 +
 +   Value is 0 if there is no match, -1 if there is a match against
 +   DESC itself, and the number of matching instances if the style
 +   matches one or more instances defined in in DESC.  Return the index
 +   of each matching instance in INSTANCES; it should be SIZE big.  */
 +
 +static int
 +sfntfont_list_1 (struct sfnt_font_desc *desc, Lisp_Object spec,
 +               int *instances, int size)
 +{
 +  Lisp_Object tem, extra, tail;
 +  struct sfnt_cmap_encoding_subtable_data *cmap;
 +  size_t i;
 +  struct sfnt_cmap_encoding_subtable subtable;
 +  int instance, num_instance;
 +  Lisp_Object item;
 +
 +  /* cmap and subtable are caches for sfntfont_lookup_char.  */
 +
 +  /* Check that the family name in SPEC matches DESC->family if it is
 +     specified.  */
 +
 +  tem = AREF (spec, FONT_FAMILY_INDEX);
 +
 +  /* If TEM is a family listed in Vsfnt_default_family_alist,
 +     then use that instead.  */
 +
 +  if (SYMBOLP (tem) && CONSP (Vsfnt_default_family_alist))
 +    {
 +      tail = Vsfnt_default_family_alist;
 +      FOR_EACH_TAIL_SAFE (tail)
 +      {
 +        if (!CONSP (XCAR (tail)))
 +          continue;
 +
 +        if (STRINGP (XCAR (XCAR (tail)))
 +            && STRINGP (XCDR (XCAR (tail)))
 +            && !NILP (Fstring_equal (SYMBOL_NAME (tem),
 +                                     XCAR (XCAR (tail)))))
 +          {
 +            /* Special family found.  */
 +            tem = Fintern (XCDR (XCAR (tail)), Qnil);
 +            break;
 +          }
 +      }
 +    }
 +
 +  if (!NILP (tem) && NILP (Fstring_equal (SYMBOL_NAME (tem),
 +                                        desc->family)))
 +    return 0;
 +
 +  instance = -1;
 +
 +  /* If a registry is set and wrong, then reject the font desc
 +     immediately.  This detects 50% of mismatches from fontset.c.
 +
 +     If DESC->registry is nil, then the registry couldn't be
 +     determined beforehand.  */
 +
 +  tem = AREF (spec, FONT_REGISTRY_INDEX);
 +  if (!NILP (tem) && !NILP (desc->registry)
 +      && !sfntfont_registries_compatible_p (tem, desc->registry))
 +    return 0;
 +
 +  /* Check the style.  If DESC is a fixed font, just check once.
 +     Otherwise, check each instance.  */
 +
 +  if (NILP (desc->instances))
 +    {
 +      tem = AREF (spec, FONT_ADSTYLE_INDEX);
 +      if (!NILP (tem) && NILP (Fequal (tem, desc->adstyle)))
 +      return 0;
 +
 +      if (FONT_WIDTH_NUMERIC (spec) != -1
 +        && FONT_WIDTH_NUMERIC (spec) != desc->width)
 +      return 0;
 +
 +      if (FONT_WEIGHT_NUMERIC (spec) != -1
 +        && FONT_WEIGHT_NUMERIC (spec) != desc->weight)
 +      return 0;
 +
 +      if (FONT_SLANT_NUMERIC (spec) != -1
 +        && FONT_SLANT_NUMERIC (spec) != desc->slant)
 +      return 0;
 +    }
 +  else
 +    {
 +      num_instance = 0;
 +
 +      /* Find the indices of instances in this distortable font which
 +       match the given font spec.  */
 +
 +      for (i = 0; i < ASIZE (desc->instances); ++i)
 +      {
 +        item = AREF (desc->instances, i);
 +
 +        if (NILP (item))
 +          continue;
 +
 +        /* Check that the adstyle specified matches.  */
 +
 +        tem = AREF (spec, FONT_ADSTYLE_INDEX);
 +        if (!NILP (tem) && NILP (Fequal (tem, AREF (item, 1))))
 +          continue;
 +
 +        /* Check the style.  */
 +
 +        if (FONT_WIDTH_NUMERIC (spec) != -1
 +            && (FONT_WIDTH_NUMERIC (spec)
 +                != XFIXNUM (AREF (item, 2))))
 +          continue;
 +
 +        if (FONT_WEIGHT_NUMERIC (spec) != -1
 +            && (FONT_WEIGHT_NUMERIC (spec)
 +                != XFIXNUM (AREF (item, 3))))
 +          continue;
 +
 +        if (FONT_SLANT_NUMERIC (spec) != -1
 +            && (FONT_SLANT_NUMERIC (spec)
 +                != XFIXNUM (AREF (item, 4))))
 +          continue;
 +
 +        if (num_instance == size)
 +          break;
 +
 +        /* A matching instance has been found.  Set its index, then
 +           go back to the rest of the font matching.  */
 +        instances[num_instance++] = i;
 +      }
 +
 +      instance = num_instance;
 +    }
 +
 +  /* Handle extras.  */
 +  extra = AREF (spec, FONT_EXTRA_INDEX);
 +
 +  if (NILP (extra))
 +    return instance;
 +
 +  tem = assq_no_quit (QCscript, extra);
 +  cmap = NULL;
 +
 +  if (!NILP (tem))
 +    {
 +      /* If a script has been specified, look up its representative
 +       characters and see if they are present in the font.  This
 +       requires reading the cmap.  */
 +      tem = assq_no_quit (XCDR (tem), Vscript_representative_chars);
 +
 +      if (CONSP (tem) && VECTORP (XCDR (tem)))
 +      {
 +        tem = XCDR (tem);
 +
 +        /* The vector contains characters, of which one must be
 +           present in the font.  */
 +        for (i = 0; i < ASIZE (tem); ++i)
 +          {
 +            if (FIXNUMP (AREF (tem, i)))
 +              {
 +                if (!sfntfont_lookup_char (desc, AREF (tem, i),
 +                                           &cmap, &subtable))
 +                  goto fail;
 +
 +                /* One character is enough to pass a font.  Don't
 +                   look at too many.  */
 +                break;
 +              }
 +          }
 +      }
 +      else if (CONSP (tem) && CONSP (XCDR (tem)))
 +      {
 +        tem = XCDR (tem);
 +
 +        /* tem is a list of each characters, all of which must be
 +           present in the font.  */
 +        FOR_EACH_TAIL_SAFE (tem)
 +          {
 +            if (FIXNUMP (XCAR (tem))
 +                && !sfntfont_lookup_char (desc, XCAR (tem), &cmap,
 +                                          &subtable))
 +              goto fail;
 +          }
 +
 +        /* One or more characters are missing.  */
 +        if (!NILP (tem))
 +          goto fail;
 +      }
 +      /* Fail if there are no matching fonts at all.  */
 +      else if (NILP (tem))
 +      goto fail;
 +    }
 +
 +  /* Now check that the language is supported.  */
 +  tem = assq_no_quit (QClang, extra);
 +  if (!NILP (tem) && NILP (Fmemq (tem, desc->languages)))
 +    goto fail;
 +
 +  /* Set desc->subtable if cmap was specified.  */
 +  if (cmap)
 +    desc->subtable = subtable;
 +
 +  xfree (cmap);
 +  return instance;
 +
 + fail:
 +  /* The cmap might've been read in and require deallocation.  */
 +  xfree (cmap);
 +  return 0;
 +}
 +
 +/* Type of font entities and font objects created.  */
 +static Lisp_Object sfnt_vendor_name;
 +
 +/* Font driver used in font objects created.  */
 +static const struct font_driver *sfnt_font_driver;
 +
 +/* Return the font registry corresponding to the font descriptor DESC.
 +   Under X, the font registry is an atom registered with the Open
 +   Group uniquely identifying the organization which defines the
 +   font's character set.
 +
 +   In practice, the registry overlaps with the character set itself.
 +   So Emacs just uses the ``registry'' field to represent both
 +   instead.  */
 +
 +static Lisp_Object
 +sfntfont_registry_for_desc (struct sfnt_font_desc *desc)
 +{
 +  struct sfnt_cmap_encoding_subtable_data *cmap;
 +
 +  cmap = NULL;
 +
 +  if (desc->cmap_invalid)
 +    return Qnil;
 +
 +  if (desc->subtable.platform_id == 500)
 +    {
 +      /* Read in the cmap to determine the registry.  */
 +      sfntfont_read_cmap (desc, &cmap, &desc->subtable);
 +
 +      if (!cmap)
 +      {
 +        desc->cmap_invalid = true;
 +        return Qnil;
 +      }
 +    }
 +
 +  xfree (cmap);
 +
 +  if (desc->subtable.platform_id != 500)
 +    /* desc->subtable.platform_id is now set.  CMAP is already free,
 +       because it is not actually used.  */
 +    return sfnt_registry_for_subtable (&desc->subtable);
 +
 +  return Qnil;
 +}
 +
 +/* Return a font-entity that represents the font descriptor (unopened
 +   font) DESC.  If INSTANCE is more than or equal to 1, then it is the
 +   index of the instance in DESC that should be opened plus 1; in that
 +   case, DESC must be a distortable font.  */
 +
 +static Lisp_Object
 +sfntfont_desc_to_entity (struct sfnt_font_desc *desc, int instance)
 +{
 +  Lisp_Object entity, vector;
 +
 +  entity = font_make_entity ();
 +
 +  ASET (entity, FONT_TYPE_INDEX, sfnt_vendor_name);
 +
 +  if (!NILP (desc->designer))
 +    ASET (entity, FONT_FOUNDRY_INDEX,
 +        Fintern (desc->designer, Qnil));
 +
 +  ASET (entity, FONT_FAMILY_INDEX, Fintern (desc->family, Qnil));
 +  ASET (entity, FONT_ADSTYLE_INDEX, Qnil);
 +  ASET (entity, FONT_REGISTRY_INDEX,
 +      sfntfont_registry_for_desc (desc));
 +
 +  /* Size of 0 means the font is scalable.  */
 +  ASET (entity, FONT_SIZE_INDEX, make_fixnum (0));
 +  ASET (entity, FONT_AVGWIDTH_INDEX, make_fixnum (0));
 +  ASET (entity, FONT_SPACING_INDEX,
 +      make_fixnum (desc->spacing));
 +
 +  if (instance >= 1)
 +    {
 +      if (NILP (desc->instances)
 +        || instance > ASIZE (desc->instances))
 +      emacs_abort ();
 +
 +      vector = AREF (desc->instances, instance - 1);
 +      FONT_SET_STYLE (entity, FONT_WIDTH_INDEX,
 +                    AREF (vector, 2));
 +      FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
 +                    AREF (vector, 3));
 +      FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
 +                    AREF (vector, 4));
-         ASET (font_object, FONT_ADSTYLE_INDEX, Qnil);   
++      ASET (entity, FONT_ADSTYLE_INDEX, AREF (vector, 1));
 +    }
 +  else
 +    {
 +      FONT_SET_STYLE (entity, FONT_WIDTH_INDEX,
 +                    make_fixnum (desc->width));
 +      FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX,
 +                    make_fixnum (desc->weight));
 +      FONT_SET_STYLE (entity, FONT_SLANT_INDEX,
 +                    make_fixnum (desc->slant));
 +      ASET (entity, FONT_ADSTYLE_INDEX, desc->adstyle);
 +    }
 +
 +  /* Set FONT_EXTRA_INDEX to a pointer to the font description.  Font
 +     descriptions are never supposed to be freed.  */
 +
 +  ASET (entity, FONT_EXTRA_INDEX,
 +      (instance >= 1
 +       ? list2 (Fcons (Qfont_entity, make_mint_ptr (desc)),
 +                Fcons (Qfont_instance, make_fixnum (instance - 1)))
 +       : list1 (Fcons (Qfont_entity, make_mint_ptr (desc)))));
 +
 +  return entity;
 +}
 +
 +/* Return a list of font-entities matching the specified
 +   FONT_SPEC.  */
 +
 +Lisp_Object
 +sfntfont_list (struct frame *f, Lisp_Object font_spec)
 +{
 +  Lisp_Object matching, tem;
 +  struct sfnt_font_desc *desc;
 +  int i, rc, instances[100];
 +
 +  matching = Qnil;
 +
 +  block_input ();
 +  /* Returning irrelevant results on receiving an OTF form will cause
 +     fontset.c to loop over and over, making displaying some
 +     characters very slow.  */
 +  tem = assq_no_quit (QCotf, AREF (font_spec, FONT_EXTRA_INDEX));
 +  if (CONSP (tem) && !NILP (XCDR (tem)))
 +    {
 +      unblock_input ();
 +      return Qnil;
 +    }
 +
 +  /* Loop through known system fonts and add them one-by-one.  */
 +
 +  for (desc = system_fonts; desc; desc = desc->next)
 +    {
 +      rc = sfntfont_list_1 (desc, font_spec, instances,
 +                          ARRAYELTS (instances));
 +
 +      if (rc < 0)
 +      matching = Fcons (sfntfont_desc_to_entity (desc, 0),
 +                        matching);
 +      else if (rc)
 +      {
 +        /* Add each matching instance.  */
 +
 +        for (i = 0; i < rc; ++i)
 +          matching = Fcons (sfntfont_desc_to_entity (desc,
 +                                                     instances[i] + 1),
 +                            matching);
 +      }
 +    }
 +
 +  unblock_input ();
 +
 +  return matching;
 +}
 +
 +/* Return the first font-entity matching the specified FONT_SPEC.  */
 +
 +Lisp_Object
 +sfntfont_match (struct frame *f, Lisp_Object font_spec)
 +{
 +  Lisp_Object matches;
 +
 +  matches = sfntfont_list (f, font_spec);
 +
 +  if (!NILP (matches))
 +    return XCAR (matches);
 +
 +  return Qnil;
 +}
 +
 +\f
 +
 +enum
 +  {
 +    SFNT_OUTLINE_CACHE_SIZE = 256,
 +    SFNT_RASTER_CACHE_SIZE  = 128,
 +  };
 +
 +/* Caching subsystem.  Generating outlines from glyphs is expensive,
 +   and so is rasterizing them, so two caches are maintained for both
 +   glyph outlines and rasters.
 +
 +   Computing metrics also requires some expensive processing if the
 +   glyph has instructions or distortions.  */
 +
 +struct sfnt_outline_cache
 +{
 +  /* Next and last cache buckets.  */
 +  struct sfnt_outline_cache *next, *last;
 +
 +  /* Pointer to outline.  */
 +  struct sfnt_glyph_outline *outline;
 +
 +  /* Reference to glyph metrics.  */
 +  struct sfnt_glyph_metrics metrics;
 +
 +  /* What glyph this caches.  */
 +  sfnt_glyph glyph;
 +};
 +
 +struct sfnt_raster_cache
 +{
 +  /* Next and last cache buckets.  */
 +  struct sfnt_raster_cache *next, *last;
 +
 +  /* Pointer to raster.  */
 +  struct sfnt_raster *raster;
 +
 +  /* What glyph this caches.  */
 +  sfnt_glyph glyph;
 +};
 +
 +struct sfntfont_get_glyph_outline_dcontext
 +{
 +  /* Long and short loca tables.  */
 +  struct sfnt_loca_table_long *loca_long;
 +  struct sfnt_loca_table_short *loca_short;
 +
 +  /* glyf table.  */
 +  struct sfnt_glyf_table *glyf;
 +
 +  /* Variation settings, or NULL.  */
 +  struct sfnt_blend *blend;
 +};
 +
 +/* Return the glyph identified by GLYPH_ID from the glyf and loca
 +   table specified in DCONTEXT.  Set *NEED_FREE to true.  */
 +
 +static struct sfnt_glyph *
 +sfntfont_get_glyph (sfnt_glyph glyph_id, void *dcontext,
 +                  bool *need_free)
 +{
 +  struct sfntfont_get_glyph_outline_dcontext *tables;
 +  struct sfnt_glyph *glyph;
 +  struct sfnt_metrics_distortion distortion;
 +
 +  tables = dcontext;
 +  *need_free = true;
 +
 +  glyph = sfnt_read_glyph (glyph_id, tables->glyf,
 +                         tables->loca_short,
 +                         tables->loca_long);
 +
 +  if (tables->blend && glyph)
 +    {
 +      if (glyph->simple)
 +      sfnt_vary_simple_glyph (tables->blend, glyph_id, glyph,
 +                              &distortion);
 +      else
 +      sfnt_vary_compound_glyph (tables->blend, glyph_id, glyph,
 +                                &distortion);
 +    }
 +
 +  /* Note that the distortion is not relevant for compound glyphs.  */
 +  return glyph;
 +}
 +
 +/* Free the glyph identified by GLYPH.  */
 +
 +static void
 +sfntfont_free_glyph (struct sfnt_glyph *glyph, void *dcontext)
 +{
 +  sfnt_free_glyph (glyph);
 +}
 +
 +/* Dereference the outline OUTLINE.  Free it once refcount reaches
 +   0.  */
 +
 +static void
 +sfntfont_dereference_outline (struct sfnt_glyph_outline *outline)
 +{
 +  eassert (outline->refcount > 0);
 +
 +  if (--outline->refcount)
 +    return;
 +
 +  xfree (outline);
 +}
 +
 +/* Get the outline corresponding to the specified GLYPH_CODE in CACHE.
 +   Use the scale factor SCALE, the glyf table GLYF, and the head table
 +   HEAD.  Keep *CACHE_SIZE updated with the number of elements in the
 +   cache.
 +
 +   Distort the glyph using BLEND if INDEX is not -1.
 +
 +   Use the offset information in the long or short loca tables
 +   LOCA_LONG and LOCA_SHORT, whichever is set.
 +
 +   Use the specified HMTX, HEAD, HHEA and MAXP tables when instructing
 +   compound glyphs.
 +
 +   If INTERPRETER is non-NULL, then possibly use it and the
 +   interpreter graphics STATE to instruct the glyph.
 +
 +   If METRICS is non-NULL, return the scaled glyph metrics after
 +   variation and instructing.
 +
 +   Return the outline with an incremented reference count and enter
 +   the generated outline into CACHE upon success, possibly discarding
 +   any older outlines, or NULL on failure.  */
 +
 +static struct sfnt_glyph_outline *
 +sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
 +                          struct sfnt_outline_cache *cache,
 +                          sfnt_fixed scale, int *cache_size,
 +                          struct sfnt_blend *blend,
 +                          int index,
 +                          struct sfnt_glyf_table *glyf,
 +                          struct sfnt_head_table *head,
 +                          struct sfnt_hmtx_table *hmtx,
 +                          struct sfnt_hhea_table *hhea,
 +                          struct sfnt_maxp_table *maxp,
 +                          struct sfnt_loca_table_short *loca_short,
 +                          struct sfnt_loca_table_long *loca_long,
 +                          struct sfnt_interpreter *interpreter,
 +                          struct sfnt_glyph_metrics *metrics,
 +                          struct sfnt_graphics_state *state)
 +{
 +  struct sfnt_outline_cache *start;
 +  struct sfnt_glyph_outline *outline;
 +  struct sfnt_glyph *glyph;
 +  struct sfntfont_get_glyph_outline_dcontext dcontext;
 +  struct sfnt_instructed_outline *value;
 +  const char *error;
 +  struct sfnt_glyph_metrics temp;
 +  struct sfnt_metrics_distortion distortion;
 +
 +  start = cache->next;
 +  distortion.advance = 0;
 +
 +  /* See if the outline is already cached.  */
 +  for (; start != cache; start = start->next)
 +    {
 +      if (start->glyph == glyph_code)
 +      {
 +        /* Move start to the start of the ring.  Then increase
 +           start->outline->refcount and return it.  */
 +
 +        start->last->next = start->next;
 +        start->next->last = start->last;
 +
 +        start->next = cache->next;
 +        start->last = cache;
 +        start->next->last = start;
 +        start->last->next = start;
 +        start->outline->refcount++;
 +
 +        if (metrics)
 +          *metrics = start->metrics;
 +
 +        return start->outline;
 +      }
 +    }
 +
 +  /* Not already cached.  Get the glyph.  */
 +  glyph = sfnt_read_glyph (glyph_code, glyf,
 +                         loca_short, loca_long);
 +
 +  if (!glyph)
 +    return NULL;
 +
 +  /* Distort the glyph if necessary.  */
 +
 +  if (index != -1)
 +    {
 +      if (glyph->simple)
 +      {
 +        if (sfnt_vary_simple_glyph (blend, glyph_code,
 +                                    glyph, &distortion))
 +          {
 +            sfnt_free_glyph (glyph);
 +            return NULL;
 +          }
 +      }
 +      else if (sfnt_vary_compound_glyph (blend, glyph_code,
 +                                       glyph, &distortion))
 +      {
 +        sfnt_free_glyph (glyph);
 +        return NULL;
 +      }
 +    }
 +
 +  /* Try to instruct the glyph if INTERPRETER is specified.  */
 +
 +  outline = NULL;
 +
 +  dcontext.loca_long = loca_long;
 +  dcontext.loca_short = loca_short;
 +  dcontext.glyf = glyf;
 +  dcontext.blend = (index != -1 ? blend : NULL);
 +
 +  /* Now load the glyph's unscaled metrics into TEMP.  */
 +
 +  if (sfnt_lookup_glyph_metrics (glyph_code, -1, &temp, hmtx, hhea,
 +                               head, maxp))
 +    goto fail;
 +
 +  /* Add the advance width distortion.  */
 +  temp.advance += distortion.advance;
 +
 +  if (interpreter)
 +    {
 +      if (glyph->simple)
 +      {
 +        /* Restore the interpreter state from the snapshot taken
 +           after loading the preprogram.  */
 +        interpreter->state = *state;
 +
 +        error = sfnt_interpret_simple_glyph (glyph, interpreter,
 +                                             &temp, &value);
 +      }
 +      else
 +      /* Restoring the interpreter state is done by
 +         sfnt_interpret_compound_glyph; all that must be done here
 +         is to give the graphics state to that function.  */
 +      error = sfnt_interpret_compound_glyph (glyph, interpreter,
 +                                             state,
 +                                             sfntfont_get_glyph,
 +                                             sfntfont_free_glyph,
 +                                             hmtx, hhea, maxp,
 +                                             &temp, &dcontext,
 +                                             &value);
 +
 +      if (!error)
 +      {
 +        outline = sfnt_build_instructed_outline (value);
 +        xfree (value);
 +      }
 +    }
 +
 +  if (!outline)
 +    {
 +      if (!interpreter)
 +      outline = sfnt_build_glyph_outline (glyph, scale,
 +                                          &temp,
 +                                          sfntfont_get_glyph,
 +                                          sfntfont_free_glyph,
 +                                          &dcontext);
 +      else
 +      outline = sfnt_build_glyph_outline (glyph, scale,
 +                                          &temp,
 +                                          sfntfont_get_glyph,
 +                                          sfntfont_free_glyph,
 +                                          &dcontext);
 +    }
 +
 +  /* At this point, the glyph metrics are unscaled.  Scale them up.
 +     If INTERPRETER is set, use the scale placed within.  */
 +
 +  sfnt_scale_metrics (&temp, scale);
 +
 + fail:
 +
 +  xfree (glyph);
 +
 +  if (!outline)
 +    return NULL;
 +
 +  if (index != -1)
 +    /* Finally, adjust the left side bearing of the glyph metrics by
 +       the origin point of the outline, should a distortion have been
 +       applied.  The left side bearing is the distance from the origin
 +       point to the left most point on the X axis.  */
 +    temp.lbearing = outline->xmin - outline->origin;
 +
 +  start = xmalloc (sizeof *start);
 +  start->glyph = glyph_code;
 +  start->outline = outline;
 +  start->metrics = temp;
 +
 +  /* One reference goes to the cache.  The second reference goes to
 +     the caller.  */
 +  outline->refcount = 2;
 +
 +  /* Link start onto the cache.  */
 +  start->next = cache->next;
 +  start->last = cache;
 +  start->next->last = start;
 +  start->last->next = start;
 +
 +  /* Update the cache size.  */
 +  (*cache_size)++;
 +
 +  /* Figure out if the least recently used element has to be
 +     evicted.  */
 +  if (*cache_size > SFNT_OUTLINE_CACHE_SIZE)
 +    {
 +      start = cache->last;
 +      eassert (start != cache);
 +
 +      /* Free the least recently used entry in the cache.  */
 +      start->last->next = start->next;
 +      start->next->last = start->last;
 +      sfntfont_dereference_outline (start->outline);
 +      xfree (start);
 +
 +      (*cache_size)--;
 +    }
 +
 +  /* Return the cached outline and metrics.  */
 +
 +  if (metrics)
 +    *metrics = temp;
 +
 +  return outline;
 +}
 +
 +/* Free the outline cache referred to by CACHE.  Dereference each
 +   outline contained therein.  */
 +
 +static void
 +sfntfont_free_outline_cache (struct sfnt_outline_cache *cache)
 +{
 +  struct sfnt_outline_cache *next, *last;
 +
 +  /* Handle partly initialized fonts.  */
 +  if (!cache->next)
 +    return;
 +
 +  for (next = cache->next; next != cache;)
 +    {
 +      last = next;
 +      next = next->next;
 +
 +      sfntfont_dereference_outline (last->outline);
 +      xfree (last);
 +    }
 +
 +  cache->next = cache;
 +  cache->last = cache;
 +}
 +
 +/* Dereference the raster RASTER.  Free it once refcount reaches
 +   0.  */
 +
 +static void
 +sfntfont_dereference_raster (struct sfnt_raster *raster)
 +{
 +  eassert (raster->refcount > 0);
 +
 +  if (--raster->refcount)
 +    return;
 +
 +  xfree (raster);
 +}
 +
 +/* Get the raster corresponding to the specified GLYPH_CODE in CACHE.
 +   Use the outline named OUTLINE.  Keep *CACHE_SIZE updated with the
 +   number of elements in the cache.  */
 +
 +static struct sfnt_raster *
 +sfntfont_get_glyph_raster (sfnt_glyph glyph_code,
 +                         struct sfnt_raster_cache *cache,
 +                         struct sfnt_glyph_outline *outline,
 +                         int *cache_size)
 +{
 +  struct sfnt_raster_cache *start;
 +  struct sfnt_raster *raster;
 +
 +  /* See if the raster is already cached.  */
 +  start = cache->next;
 +
 +  for (; start != cache; start = start->next)
 +    {
 +      if (start->glyph == glyph_code)
 +      {
 +        /* Move start to the start of the ring.  Them, increase
 +           start->raster->refcount and return it.  */
 +
 +        start->last->next = start->next;
 +        start->next->last = start->last;
 +
 +        start->next = cache->next;
 +        start->last = cache;
 +        start->next->last = start;
 +        start->last->next = start;
 +        start->raster->refcount++;
 +
 +        return start->raster;
 +      }
 +    }
 +
 +  /* Not already cached.  Raster the outline.  */
 +  raster = sfnt_raster_glyph_outline (outline);
 +
 +  if (!raster)
 +    return NULL;
 +
 +  start = xmalloc (sizeof *start);
 +  start->glyph = glyph_code;
 +  start->raster = raster;
 +
 +  /* One reference goes to the cache.  The second reference goes to
 +     the caller.  */
 +  raster->refcount = 2;
 +
 +  /* Link start onto the cache.  */
 +  start->next = cache->next;
 +  start->last = cache;
 +  start->next->last = start;
 +  start->last->next = start;
 +
 +  /* Update the cache size.  */
 +  (*cache_size)++;
 +
 +  /* Figure out if the least recently used element has to be
 +     evicted.  */
 +  if (*cache_size > SFNT_OUTLINE_CACHE_SIZE)
 +    {
 +      start = cache->last;
 +      eassert (start != cache);
 +
 +      /* Free the least recently used entry in the cache.  */
 +      start->last->next = start->next;
 +      start->next->last = start->last;
 +      sfntfont_dereference_raster (start->raster);
 +      xfree (start);
 +
 +      (*cache_size)--;
 +    }
 +
 +  /* Return the cached raster.  */
 +  return raster;
 +}
 +
 +/* Free the raster cache referred to by CACHE.  Dereference each
 +   raster contained therein.  */
 +
 +static void
 +sfntfont_free_raster_cache (struct sfnt_raster_cache *cache)
 +{
 +  struct sfnt_raster_cache *next, *last;
 +
 +  /* Handle partly initialized fonts.  */
 +  if (!cache->next)
 +    return;
 +
 +  for (next = cache->next; next != cache;)
 +    {
 +      last = next;
 +      next = next->next;
 +
 +      sfntfont_dereference_raster (last->raster);
 +      xfree (last);
 +    }
 +
 +  cache->next = cache;
 +  cache->last = cache;
 +}
 +
 +\f
 +
 +/* Opening fonts.  */
 +
 +struct sfnt_font_info
 +{
 +  /* Parent font structure.  */
 +  struct font font;
 +
 +#ifdef HAVE_MMAP
 +  /* The next font in this chain.  */
 +  struct sfnt_font_info *next;
 +#endif /* HAVE_MMAP */
 +
 +  /* The font description used to create this font.  Used to
 +     dereference tables associated with this font.  */
 +  struct sfnt_font_desc *desc;
 +
 +  /* Various tables required to use the font.  */
 +  struct sfnt_cmap_table *cmap;
 +  struct sfnt_hhea_table *hhea;
 +  struct sfnt_maxp_table *maxp;
 +  struct sfnt_head_table *head;
 +  struct sfnt_hmtx_table *hmtx;
 +  struct sfnt_glyf_table *glyf;
 +  struct sfnt_loca_table_short *loca_short;
 +  struct sfnt_loca_table_long *loca_long;
 +  struct sfnt_prep_table *prep;
 +  struct sfnt_fpgm_table *fpgm;
 +  struct sfnt_cvt_table *cvt;
 +
 +  /* The selected character map.  */
 +  struct sfnt_cmap_encoding_subtable_data *cmap_data;
 +
 +  /* Data identifying that character map.  */
 +  struct sfnt_cmap_encoding_subtable cmap_subtable;
 +
 +  /* The UVS context.  */
 +  struct sfnt_uvs_context *uvs;
 +
 +  /* Outline cache.  */
 +  struct sfnt_outline_cache outline_cache;
 +
 +  /* Number of elements in the outline cache.  */
 +  int outline_cache_size;
 +
 +  /* Raster cache.  */
 +  struct sfnt_raster_cache raster_cache;
 +
 +  /* Number of elements in the raster cache.  */
 +  int raster_cache_size;
 +
 +  /* Interpreter for grid fitting (if enabled).  */
 +  struct sfnt_interpreter *interpreter;
 +
 +  /* Graphics state after the execution of the font and control value
 +     programs.  */
 +  struct sfnt_graphics_state state;
 +
 +  /* Factor used to convert from em space to pixel space.  */
 +  sfnt_fixed scale;
 +
 +  /* The blend (configuration of this multiple master font).  */
 +  struct sfnt_blend blend;
 +
 +  /* The index of the named instance used to initialize BLEND.
 +     -1 if BLEND is not initialized.  */
 +  int instance;
 +
 +#ifdef HAVE_MMAP
 +  /* Whether or not the glyph table has been mmapped.  */
 +  bool glyf_table_mapped;
 +#endif /* HAVE_MMAP */
 +
 +#ifdef HAVE_HARFBUZZ
 +  /* HarfBuzz font object.  */
 +  hb_font_t *hb_font;
 +
 +  /* File descriptor associated with this font.  */
 +  int fd;
 +
 +  /* The table directory of the font file.  */
 +  struct sfnt_offset_subtable *directory;
 +#endif /* HAVE_HARFBUZZ */
 +};
 +
 +#ifdef HAVE_MMAP
 +
 +/* List of all open fonts.  */
 +
 +static struct sfnt_font_info *open_fonts;
 +
 +#endif /* HAVE_MMAP */
 +
 +/* Look up the glyph corresponding to the character C in FONT.  Return
 +   0 upon failure, and the glyph otherwise.  */
 +
 +static sfnt_glyph
 +sfntfont_lookup_glyph (struct sfnt_font_info *font_info, int c)
 +{
 +  struct charset *charset;
 +  sfnt_char character;
 +  sfnt_glyph glyph;
 +
 +  charset = CHARSET_FROM_ID (font_info->font.encoding_charset);
 +
 +  if (!charset)
 +    return 0;
 +
 +  character = ENCODE_CHAR (charset, c);
 +
 +  if (character == CHARSET_INVALID_CODE (charset))
 +    return 0;
 +
 +  /* Do the actual lookup with the encoded character.  */
 +  glyph = sfnt_lookup_glyph (character, font_info->cmap_data);
 +
 +  return glyph;
 +}
 +
 +/* Probe and set FONT_INFO->font.average_width,
 +   FONT_INFO->font.space_width, and FONT_INFO->font.min_width
 +   according to the tables contained therein.  */
 +
 +static void
 +sfntfont_probe_widths (struct sfnt_font_info *font_info)
 +{
 +  int i, num_characters, total_width;
 +  sfnt_glyph glyph;
 +  struct sfnt_glyph_metrics metrics;
 +
 +  num_characters = 0;
 +  total_width = 0;
 +
 +  /* First set some reasonable default values.  */
 +  font_info->font.average_width = font_info->font.pixel_size;
 +  font_info->font.space_width = font_info->font.pixel_size;
 +  font_info->font.min_width = 1;
 +
 +  /* Next, loop through the common ASCII characters.  Tally up their
 +     advance widths and set space_width if necessary.  */
 +  for (i = 0; i < 127; ++i)
 +    {
 +      glyph = sfntfont_lookup_glyph (font_info, i);
 +
 +      if (!glyph)
 +      continue;
 +
 +      /* Now look up the metrics of this glyph.  */
 +      if (sfnt_lookup_glyph_metrics (glyph, font_info->font.pixel_size,
 +                                   &metrics, font_info->hmtx,
 +                                   font_info->hhea, font_info->head,
 +                                   font_info->maxp))
 +      continue;
 +
 +      /* Increase the number of characters.  */
 +      num_characters++;
 +
 +      /* Add the advance to total_width.  */
 +      total_width += SFNT_CEIL_FIXED (metrics.advance) / 65536;
 +
 +      /* Update min_width if it hasn't been set yet or is wider.  */
 +      if (font_info->font.min_width == 1
 +        || font_info->font.min_width > metrics.advance / 65536)
 +      font_info->font.min_width = metrics.advance / 65536;
 +
 +      /* If i is the space character, set the space width.  Make sure
 +       to round this up.  */
 +      if (i == 32)
 +      font_info->font.space_width
 +        = SFNT_CEIL_FIXED (metrics.advance) / 65536;
 +    }
 +
 +  /* Now, if characters were found, set average_width.  */
 +  if (num_characters)
 +    font_info->font.average_width = total_width / num_characters;
 +}
 +
 +/* Initialize the instruction interpreter for INFO.  Load the font and
 +   preprogram for the pixel size in INFO and its corresponding point
 +   size POINT_SIZE.  Use the FVAR table in DESC.
 +
 +   The font tables in INFO must already have been initialized.
 +
 +   Set INFO->interpreter upon success, and leave that field intact
 +   otherwise.  */
 +
 +static void
 +sfntfont_setup_interpreter (struct sfnt_font_info *info,
 +                          struct sfnt_font_desc *desc,
 +                          int point_size)
 +{
 +  struct sfnt_cvt_table *cvt;
 +  struct sfnt_fpgm_table *fpgm;
 +  struct sfnt_prep_table *prep;
 +  struct sfnt_interpreter *interpreter;
 +  const char *error;
 +  struct sfnt_graphics_state state;
 +
 +  /* Load the cvt, fpgm and prep already read.  */
 +
 +  cvt  = info->cvt ;
 +  fpgm = info->fpgm;
 +  prep = info->prep;
 +
 +  /* If both fpgm and prep are NULL, this font likely has no
 +     instructions, so don't bother setting up the interpreter.  */
 +
 +  if (!fpgm && !prep)
 +    goto bail;
 +
 +  /* If the interpreter does not use the operand stack at all, it is
 +     useless.  In addition, some broken fonts specify some unnecessary
 +     instructions in prep and set head->max_stack_elements to 0.
 +
 +     Don't create the interpreter in that case.  */
 +
 +  if (!info->maxp->max_stack_elements)
 +    goto bail;
 +
 +  /* Now, create the interpreter using the limits in info->maxp and
 +     info->head.  CVT can be NULL.  */
 +
 +  interpreter = sfnt_make_interpreter (info->maxp, cvt, info->head,
 +                                     desc->tables->fvar,
 +                                     info->font.pixel_size,
 +                                     point_size);
 +
 +  /* Bail if the interpreter couldn't be created.  */
 +  if (!interpreter)
 +    goto bail;
 +
 +  if (fpgm)
 +    {
 +      /* Otherwise, evaluate the font and cvt programs.
 +
 +       FIXME: make sure infinite loops inside these programs
 +       cannot lock up Emacs.  */
 +
 +      error = sfnt_interpret_font_program (interpreter, fpgm);
 +
 +      if (error)
 +      {
 +        /* If an error occurs, log it to the *Messages* buffer.  */
 +        message_with_string ("While interpreting font program: %s",
 +                             build_string (error), true);
 +        goto bail1;
 +      }
 +
 +      /* Save the graphics state.  */
 +      state = interpreter->state;
 +    }
 +
 +  if (prep)
 +    {
 +      /* This will overwrite state if the instruction control is set
 +       appropriately.  */
 +      error = sfnt_interpret_control_value_program (interpreter, prep,
 +                                                  &state);
 +
 +      if (error)
 +      {
 +        /* If an error occurs, log it to the *Messages* buffer.  */
 +        message_with_string ("While interpreting preprogram: %s",
 +                             build_string (error), true);
 +        goto bail1;
 +      }
 +    }
 +
 +  /* The interpreter has been properly set up.  */
 +  info->fpgm = fpgm;
 +  info->prep = prep;
 +  info->cvt = cvt;
 +  info->state = state;
 +  info->interpreter = interpreter;
 +
 +  return;
 +
 + bail1:
 +  xfree (interpreter);
 + bail:
 +  return;
 +}
 +
 +/* Free each of the tables opened by `sfnt_open_tables', and possibly
 +   file descriptors as well.  Then, free TABLES itself.  */
 +
 +static void
 +sfnt_close_tables (struct sfnt_font_tables *tables)
 +{
 +  int rc;
 +
 +  xfree (tables->cmap);
 +  xfree (tables->hhea);
 +  xfree (tables->maxp);
 +  xfree (tables->head);
 +  xfree (tables->hmtx);
 +#ifdef HAVE_MMAP
 +  if (tables->glyf_table_mapped)
 +    {
 +      rc = sfnt_unmap_glyf_table (tables->glyf);
 +
 +      if (rc)
 +      emacs_abort ();
 +    }
 +  else
 +#endif /* HAVE_MMAP */
 +    xfree (tables->glyf);
 +  xfree (tables->loca_short);
 +  xfree (tables->loca_long);
 +  xfree (tables->prep);
 +  xfree (tables->fpgm);
 +  xfree (tables->cvt);
 +  xfree (tables->fvar);
 +  xfree (tables->avar);
 +  xfree (tables->gvar);
 +  xfree (tables->cvar);
 +  xfree (tables->cmap_data);
 +
 +  if (tables->uvs)
 +    sfnt_free_uvs_context (tables->uvs);
 +
 +#ifdef HAVE_HARFBUZZ
 +  /* Close the font file.  */
 +
 +  if (tables->fd != -1)
 +    {
 +      emacs_close (tables->fd);
 +      tables->fd = -1;
 +    }
 +
 +  /* Free its table directory.  */
 +  xfree (tables->directory);
 +  tables->directory = NULL;
 +#endif
 +}
 +
 +/* Open font tables associated with the specified font description
 +   DESC.  Return the font tables, or NULL upon failure.  */
 +
 +static struct sfnt_font_tables *
 +sfnt_open_tables (struct sfnt_font_desc *desc)
 +{
 +  struct sfnt_font_tables *tables;
 +  struct sfnt_offset_subtable *subtable;
 +  int fd, i, rc;
 +  struct sfnt_cmap_encoding_subtable *subtables;
 +  struct sfnt_cmap_encoding_subtable_data **data;
 +  struct sfnt_cmap_format_14 *format14;
 +
 +  tables = xzalloc (sizeof *tables);
 +
 +  /* Open the font.  */
 +  fd = emacs_open (desc->path, O_RDONLY, 0);
 +
 +  if (fd == -1)
 +    goto bail;
 +
 +  /* Seek to the offset specified to the table directory.  */
 +
 +  if (desc->offset
 +      && lseek (fd, desc->offset, SEEK_SET) != desc->offset)
 +    goto bail;
 +
 +  /* Read the offset subtable.  */
 +  subtable = sfnt_read_table_directory (fd);
 +
 +  if (!subtable || (subtable == (struct sfnt_offset_subtable *) -1))
 +    goto bail1;
 +
 +  /* Read required tables.  This font backend is supposed to be used
 +     mostly on devices with flash memory, so the order in which they
 +     are read is insignificant.  */
 +
 +  tables->cmap = sfnt_read_cmap_table (fd, subtable, &subtables,
 +                                     &data);
 +  if (!tables->cmap)
 +    goto bail2;
 +
 +  format14 = NULL;
 +  tables->cmap_data
 +    = sfntfont_select_cmap (tables->cmap,
 +                          subtables, data,
 +                          &tables->cmap_subtable,
 +                          &format14);
 +
 +  if (format14)
 +    {
 +      /* Build a UVS context from this format 14 mapping table.  A UVS
 +         context contains each variation selector supported by the
 +         font, and a list of ``non-default'' mappings between base
 +         characters and variation glyph IDs.  */
 +
 +      tables->uvs = sfnt_create_uvs_context (format14, fd);
 +      xfree (format14);
 +    }
 +
 +  for (i = 0; i < tables->cmap->num_subtables; ++i)
 +    {
 +      if (data[i] != tables->cmap_data
 +        /* format14 has already been freed.  */
 +        && data[i] != (struct sfnt_cmap_encoding_subtable_data *) format14)
 +      xfree (data[i]);
 +    }
 +
 +  xfree (subtables);
 +  xfree (data);
 +
 +  if (!tables->cmap_data)
 +    goto bail3;
 +
 +  /* Read the hhea, maxp, glyf, and head tables.  */
 +  tables->hhea = sfnt_read_hhea_table (fd, subtable);
 +  tables->maxp = sfnt_read_maxp_table (fd, subtable);
 +
 +#ifdef HAVE_MMAP
 +
 +  /* First try to map the glyf table.  If that fails, then read the
 +     glyf table.  */
 +
 +  tables->glyf = sfnt_map_glyf_table (fd, subtable);
 +
 +  /* Next, if this fails, read the glyf table.  */
 +
 +  if (!tables->glyf)
 +#endif /* HAVE_MMAP */
 +    tables->glyf = sfnt_read_glyf_table (fd, subtable);
 +#ifdef HAVE_MMAP
 +  else
 +    tables->glyf_table_mapped = true;
 +#endif /* HAVE_MMAP */
 +
 +  tables->head = sfnt_read_head_table (fd, subtable);
 +
 +  /* If any of those tables couldn't be read, bail.  */
 +  if (!tables->hhea || !tables->maxp || !tables->glyf
 +      || !tables->head)
 +    goto bail4;
 +
 +  /* Now figure out which kind of loca table must be read based on
 +     head->index_to_loc_format.  */
 +
 +  if (tables->head->index_to_loc_format)
 +    {
 +      tables->loca_long
 +      = sfnt_read_loca_table_long (fd, subtable);
 +
 +      if (!tables->loca_long)
 +      goto bail4;
 +    }
 +  else
 +    {
 +      tables->loca_short
 +      = sfnt_read_loca_table_short (fd, subtable);
 +
 +      if (!tables->loca_short)
 +      goto bail4;
 +    }
 +
 +  /* Read the horizontal metrics table.  */
 +  tables->hmtx = sfnt_read_hmtx_table (fd, subtable,
 +                                     tables->hhea,
 +                                     tables->maxp);
 +  if (!tables->hmtx)
 +    goto bail5;
 +
 +  /* Read instruction related font tables.  These might not be
 +     present, which is OK, since instructing fonts is optional.  */
 +  tables->prep = sfnt_read_prep_table (fd, subtable);
 +  tables->fpgm = sfnt_read_fpgm_table (fd, subtable);
 +  tables->cvt  = sfnt_read_cvt_table (fd, subtable);
 +
 +  /* Read distortion related tables.  These might not be present.  */
 +  tables->fvar = sfnt_read_fvar_table (fd, subtable);
 +  tables->avar = sfnt_read_avar_table (fd, subtable);
 +  tables->gvar = sfnt_read_gvar_table (fd, subtable);
 +
 +  if (tables->cvt && tables->fvar)
 +    tables->cvar = sfnt_read_cvar_table (fd, subtable, tables->fvar,
 +                                       tables->cvt);
 +
 +#ifdef HAVE_HARFBUZZ
 +  /* Now copy over the subtable if necessary, as it is needed to read
 +     extra font tables required by HarfBuzz.  */
 +  tables->directory = subtable;
 +  tables->fd = fd;
 +#else /* !HAVE_HARFBUZZ */
 +  /* Otherwise, close the fd and free the table directory.  */
 +  xfree (subtable);
 +  emacs_close (fd);
 +#endif /* HAVE_HARFBUZZ */
 +
 +  return tables;
 +
 + bail5:
 +  xfree (tables->loca_long);
 +  xfree (tables->loca_short);
 + bail4:
 +  xfree (tables->hhea);
 +  xfree (tables->maxp);
 +
 +#ifdef HAVE_MMAP
 +  if (tables->glyf_table_mapped)
 +    {
 +      rc = sfnt_unmap_glyf_table (tables->glyf);
 +
 +      if (rc)
 +      emacs_abort ();
 +    }
 +  else
 +#endif /* HAVE_MMAP */
 +    xfree (tables->glyf);
 +
 +  xfree (tables->head);
 +
 +  /* This comes under bail4 due to a peculiarity of how the four
 +     tables above are validated.  */
 +  xfree (tables->cmap_data);
 + bail3:
 +  if (tables->uvs)
 +    sfnt_free_uvs_context (tables->uvs);
 +
 +  xfree (tables->cmap);
 + bail2:
 +  xfree (subtable);
 + bail1:
 +  emacs_close (fd);
 + bail:
 +  xfree (tables);
 +  return NULL;
 +}
 +
 +/* Open or reference font tables corresponding to the specified font
 +   DESC.  Return NULL upon failure.  */
 +
 +static struct sfnt_font_tables *
 +sfnt_reference_font_tables (struct sfnt_font_desc *desc)
 +{
 +  if (desc->refcount)
 +    {
 +      desc->refcount++;
 +      return desc->tables;
 +    }
 +
 +  desc->tables = sfnt_open_tables (desc);
 +
 +  if (!desc->tables)
 +    return NULL;
 +
 +  desc->refcount++;
 +  return desc->tables;
 +}
 +
 +/* Dereference font tables corresponding to the specified font
 +   DESC.  */
 +
 +static void
 +sfnt_dereference_font_tables (struct sfnt_font_desc *desc)
 +{
 +  if (!desc->refcount)
 +    emacs_abort ();
 +
 +  if (--desc->refcount)
 +    return;
 +
 +  sfnt_close_tables (desc->tables);
 +  desc->tables = NULL;
 +  return;
 +}
 +
 +/* Open the font corresponding to the font-entity FONT_ENTITY.  Return
 +   nil upon failure, else the opened font-object.  */
 +
 +Lisp_Object
 +sfntfont_open (struct frame *f, Lisp_Object font_entity,
 +             int pixel_size)
 +{
 +  struct sfnt_font_info *font_info;
 +  struct font *font;
 +  struct sfnt_font_desc *desc;
 +  Lisp_Object font_object;
 +  struct charset *charset;
 +  int point_size, instance, i;
 +  Display_Info *dpyinfo;
 +  struct sfnt_font_tables *tables;
 +  Lisp_Object tem;
 +
 +  if (XFIXNUM (AREF (font_entity, FONT_SIZE_INDEX)) != 0)
 +    pixel_size = XFIXNUM (AREF (font_entity, FONT_SIZE_INDEX));
 +  else if (pixel_size == 0)
 +    {
 +      /* This bit was copied from xfont.c.  The values might need
 +       adjustment.  */
 +
 +      if (FRAME_FONT (f))
 +      pixel_size = FRAME_FONT (f)->pixel_size;
 +      else
 +      pixel_size = 12;
 +    }
 +
 +  /* Now find the font description corresponding to FONT_ENTITY.  */
 +
 +  tem = AREF (font_entity, FONT_EXTRA_INDEX);
 +  if (NILP (tem))
 +    return Qnil;
 +
 +  desc = xmint_pointer (XCDR (XCAR (tem)));
 +
 +  /* Finally, see if a specific instance is associated with
 +     FONT_ENTITY.  */
 +
 +  instance = -1;
 +  if (!NILP (XCDR (tem)))
 +    instance = XFIXNUM (XCDR (XCAR (XCDR (tem))));
 +
 +  /* Build the font object.  */
 +  font_object = font_make_object (VECSIZE (struct sfnt_font_info),
 +                                font_entity, pixel_size);
 +  font_info = (struct sfnt_font_info *) XFONT_OBJECT (font_object);
 +
 +  block_input ();
 +
 +  /* Initialize all the font driver specific data.  */
 +
 +  font_info->cmap = NULL;
 +  font_info->hhea = NULL;
 +  font_info->maxp = NULL;
 +  font_info->head = NULL;
 +  font_info->glyf = NULL;
 +  font_info->hmtx = NULL;
 +  font_info->loca_short = NULL;
 +  font_info->loca_long = NULL;
 +  font_info->cmap_data = NULL;
 +  font_info->prep = NULL;
 +  font_info->fpgm = NULL;
 +  font_info->cvt = NULL;
 +  font_info->uvs = NULL;
 +
 +  font_info->outline_cache.next = &font_info->outline_cache;
 +  font_info->outline_cache.last = &font_info->outline_cache;
 +  font_info->outline_cache_size = 0;
 +  font_info->raster_cache.next = &font_info->raster_cache;
 +  font_info->raster_cache.last = &font_info->raster_cache;
 +  font_info->raster_cache_size = 0;
 +  font_info->interpreter = NULL;
 +  font_info->scale = 0;
 +  font_info->instance = -1;
 +  font_info->blend.coords = NULL;
 +#ifdef HAVE_MMAP
 +  font_info->glyf_table_mapped = false;
 +#endif /* HAVE_MMAP */
 +#ifdef HAVE_HARFBUZZ
 +  font_info->hb_font = NULL;
 +  font_info->fd = -1;
 +  font_info->directory = NULL;
 +#endif /* HAVE_HARFBUZZ */
 +
 +  /* Read required tables.  This font backend is supposed to be used
 +     mostly on devices with flash memory, so the order in which they
 +     are read is insignificant.  */
 +
 +  tables = sfnt_reference_font_tables (desc);
 +
 +  if (!tables)
 +    goto bail;
 +
 +  /* Copy fields from the table structure to the font for fast
 +     access.  */
 +  font_info->cmap = tables->cmap;
 +  font_info->hhea = tables->hhea;
 +  font_info->maxp = tables->maxp;
 +  font_info->head = tables->head;
 +  font_info->hmtx = tables->hmtx;
 +  font_info->glyf = tables->glyf;
 +  font_info->loca_short = tables->loca_short;
 +  font_info->loca_long = tables->loca_long;
 +  font_info->prep = tables->prep;
 +  font_info->fpgm = tables->fpgm;
 +  font_info->cvt  = tables->cvt ;
 +  font_info->cmap_data = tables->cmap_data;
 +  font_info->cmap_subtable = tables->cmap_subtable;
 +  font_info->uvs = tables->uvs;
 +
 +  /* Calculate the font's scaling factor.  */
 +  font_info->scale = sfnt_get_scale (font_info->head, pixel_size);
 +
 +  /* Fill in font data.  */
 +  font = &font_info->font;
 +  font->pixel_size = pixel_size;
 +  font->driver = sfnt_font_driver;
 +  font->encoding_charset = font->repertory_charset = -1;
 +
 +  /* Figure out which character set to use.  */
 +  charset = sfntfont_charset_for_cmap (font_info->cmap_subtable);
 +
 +  if (!charset)
 +    goto bail6;
 +
 +  /* Set the character set IDs.  */
 +  font->encoding_charset = charset->id;
 +  font->repertory_charset = charset->id;
 +
 +  /* Figure out the font ascent and descent.  */
 +  font->ascent
 +    = ceil (font_info->hhea->ascent
 +          * pixel_size * 1.0 / font_info->head->units_per_em);
 +  font->descent
 +    = -floor (font_info->hhea->descent
 +            * pixel_size * 1.0 / font_info->head->units_per_em);
 +  font->height = font->ascent + font->descent;
 +
 +  /* Set font->max_width to the maximum advance width.  */
 +  font->max_width = (font_info->hhea->advance_width_max
 +                   * pixel_size * 1.0 / font_info->head->units_per_em);
 +
 +  /* Set generic attributes such as type and style.  */
 +  ASET (font_object, FONT_TYPE_INDEX, sfnt_vendor_name);
 +
 +  if (!NILP (desc->designer))
 +    ASET (font_object, FONT_FOUNDRY_INDEX,
 +        Fintern (desc->designer, Qnil));
 +
 +  ASET (font_object, FONT_FAMILY_INDEX, Fintern (desc->family, Qnil));
 +  ASET (font_object, FONT_ADSTYLE_INDEX, Qnil);
 +  ASET (font_object, FONT_REGISTRY_INDEX,
 +      sfntfont_registry_for_desc (desc));
 +
 +  /* Size of 0 means the font is scalable.  */
 +  ASET (font_object, FONT_SIZE_INDEX, make_fixnum (0));
 +  ASET (font_object, FONT_AVGWIDTH_INDEX, make_fixnum (0));
 +  ASET (font_object, FONT_SPACING_INDEX,
 +      make_fixnum (desc->spacing));
 +
 +  /* Set the font style.  */
 +
 +  FONT_SET_STYLE (font_object, FONT_WIDTH_INDEX,
 +                make_fixnum (desc->width));
 +  FONT_SET_STYLE (font_object, FONT_WEIGHT_INDEX,
 +                make_fixnum (desc->weight));
 +  FONT_SET_STYLE (font_object, FONT_SLANT_INDEX,
 +                make_fixnum (desc->slant));
 +
 +  ASET (font_object, FONT_ADSTYLE_INDEX, Qnil);
 +
 +  /* Find out the minimum, maximum and average widths.  */
 +  sfntfont_probe_widths (font_info);
 +
 +  /* Clear various offsets.  */
 +  font_info->font.baseline_offset = 0;
 +  font_info->font.relative_compose = 0;
 +  font_info->font.default_ascent = 0;
 +  font_info->font.vertical_centering = 0;
 +  font_info->font.underline_position = -1;
 +  font_info->font.underline_thickness = 0;
 +
 +  /* Now try to set up grid fitting for this font.  */
 +  dpyinfo = FRAME_DISPLAY_INFO (f);
 +  point_size = PIXEL_TO_POINT (pixel_size, (dpyinfo->resx
 +                                          * dpyinfo->resy
 +                                          / 2));
 +  sfntfont_setup_interpreter (font_info, desc, point_size);
 +
 +  /* If an instance was specified and the font is distortable, set up
 +     the blend.  */
 +
 +  if (instance != -1
 +      && desc->tables->fvar && desc->tables->gvar
 +      /* Make sure the instance is within range.  */
 +      && instance < desc->tables->fvar->instance_count)
 +    {
 +      tem = AREF (desc->instances, instance);
 +
 +      if (!NILP (tem))
 +      {
 +        sfnt_init_blend (&font_info->blend, desc->tables->fvar,
 +                         desc->tables->gvar, desc->tables->avar,
 +                         desc->tables->cvar);
 +
 +        /* Copy over the coordinates.  */
 +        for (i = 0; i < desc->tables->fvar->axis_count; ++i)
 +          font_info->blend.coords[i]
 +            = desc->tables->fvar->instance[instance].coords[i];
 +
 +        sfnt_normalize_blend (&font_info->blend);
 +
 +        /* Test whether or not the instance is actually redundant,
 +           as all of its axis are at their default values.  If so,
 +           free the instance.  */
 +
 +        for (i = 0; i < desc->tables->fvar->axis_count; ++i)
 +          {
 +            if (font_info->blend.norm_coords[i])
 +              break;
 +          }
 +
 +        if (i == desc->tables->fvar->axis_count)
 +          {
 +            sfnt_free_blend (&font_info->blend);
 +            goto cancel_blend;
 +          }
 +
 +        /* If an interpreter was specified, distort it now.  */
 +
 +        if (font_info->interpreter)
 +          sfnt_vary_interpreter (font_info->interpreter,
 +                                 &font_info->blend);
 +
 +        font_info->instance = instance;
 +
 +        /* Replace the style information with that of the
 +           instance.  */
 +
 +        FONT_SET_STYLE (font_object, FONT_WIDTH_INDEX,
 +                        AREF (tem, 2));
 +        FONT_SET_STYLE (font_object, FONT_WEIGHT_INDEX,
 +                        AREF (tem, 3));
 +        FONT_SET_STYLE (font_object, FONT_SLANT_INDEX,
 +                        AREF (tem, 4));
++        ASET (font_object, FONT_ADSTYLE_INDEX, Qnil);
 +      }
 +    }
 +
 + cancel_blend:
 +  /* Calculate the xfld name.  */
 +  font->props[FONT_NAME_INDEX] = Ffont_xlfd_name (font_object, Qnil);
 +
 +#ifdef HAVE_HARFBUZZ
 +  /* HarfBuzz will potentially read font tables after the font has
 +     been opened by Emacs.  Keep the font open, and record its offset
 +     subtable.  */
 +  font_info->fd = tables->fd;
 +  font_info->directory = tables->directory;
 +#endif /* HAVE_HARFBUZZ */
 +
 +  /* Set font->desc so that font tables can be dereferenced if
 +     anything goes wrong.  */
 +  font_info->desc = desc;
 +
 +#ifdef HAVE_MMAP
 +  /* Link the font onto the font table.  */
 +  font_info->next = open_fonts;
 +  open_fonts = font_info;
 +#endif /* HAVE_MMAP */
 +
 +  /* All done.  */
 +  unblock_input ();
 +  return font_object;
 +
 + bail6:
 +  sfnt_dereference_font_tables (desc);
 +  font_info->desc = NULL;
 + bail:
 +  unblock_input ();
 +  return Qnil;
 +}
 +
 +\f
 +
 +/* Metrics computation and other similar font backend functions.  */
 +
 +/* Return the glyph code corresponding to C inside the font-object
 +   FONT.  Value is the glyph code upon success, else
 +   FONT_INVALID_CODE.  */
 +
 +unsigned int
 +sfntfont_encode_char (struct font *font, int c)
 +{
 +  sfnt_glyph glyph;
 +
 +  /* Now look up the glyph.  */
 +  glyph = sfntfont_lookup_glyph ((struct sfnt_font_info *) font, c);
 +
 +  if (!glyph)
 +    return FONT_INVALID_CODE;
 +
 +  return glyph;
 +}
 +
 +/* Measure the single glyph GLYPH in the font FONT and return its
 +   metrics in *PCM.
 +
 +   Instruct the glyph if possible.
 +
 +   Value is 0 upon success, 1 otherwise.  */
 +
 +static int
 +sfntfont_measure_pcm (struct sfnt_font_info *font, sfnt_glyph glyph,
 +                    struct font_metrics *pcm)
 +{
 +  struct sfnt_glyph_metrics metrics;
 +  struct sfnt_glyph_outline *outline;
 +
 +  /* Now get the glyph outline, which is required to obtain the rsb,
 +     ascent and descent.  */
 +  outline = sfntfont_get_glyph_outline (glyph, &font->outline_cache,
 +                                      font->scale,
 +                                      &font->outline_cache_size,
 +                                      &font->blend,
 +                                      font->instance,
 +                                      font->glyf, font->head,
 +                                      font->hmtx, font->hhea,
 +                                      font->maxp,
 +                                      font->loca_short,
 +                                      font->loca_long,
 +                                      font->interpreter, &metrics,
 +                                      &font->state);
 +
 +  if (!outline)
 +    return 1;
 +
 +  /* Round the left side bearing downwards.  */
 +  pcm->lbearing = SFNT_FLOOR_FIXED (metrics.lbearing) / 65536;
 +  pcm->rbearing = SFNT_CEIL_FIXED (outline->xmax) / 65536;
 +
 +  /* Round the advance, ascent and descent upwards.  */
 +  pcm->width = SFNT_CEIL_FIXED (metrics.advance) / 65536;
 +  pcm->ascent = SFNT_CEIL_FIXED (outline->ymax) / 65536;
 +  pcm->descent = SFNT_CEIL_FIXED (-outline->ymin) / 65536;
 +
 +  sfntfont_dereference_outline (outline);
 +  return 0;
 +}
 +
 +/* Return the total text extents of NGLYPHS glyphs given as CODE in
 +   the single font metrics array METRICS.  */
 +
 +void
 +sfntfont_text_extents (struct font *font, const unsigned int *code,
 +                     int nglyphs, struct font_metrics *metrics)
 +{
 +  int i, total_width;
 +  struct font_metrics pcm;
 +
 +  total_width = 0;
 +
 +  /* First clear the metrics array.  */
 +  memset (metrics, 0, sizeof *metrics);
 +
 +  /* Get the metrcs one by one, then sum them up.  */
 +  for (i = 0; i < nglyphs; ++i)
 +    {
 +      if (!sfntfont_measure_pcm ((struct sfnt_font_info *) font,
 +                               code[i], &pcm))
 +      {
 +        /* Add the per-char metric (PCM) to the metrics in
 +           METRICS.  */
 +
 +        if (total_width + pcm.lbearing < metrics->lbearing)
 +          metrics->lbearing = total_width + pcm.lbearing;
 +
 +        if (total_width + pcm.rbearing > metrics->rbearing)
 +          metrics->rbearing = total_width + pcm.rbearing;
 +
 +        if (pcm.ascent > metrics->ascent)
 +          metrics->ascent = pcm.ascent;
 +
 +        if (pcm.descent > metrics->descent)
 +          metrics->descent = pcm.descent;
 +
 +        total_width += pcm.width;
 +      }
 +    }
 +
 +  metrics->width = total_width;
 +}
 +
 +/* Close the font FONT, discarding all tables inside it and
 +   dereferencing all cached outlines and rasters.  */
 +
 +void
 +sfntfont_close (struct font *font)
 +{
 +  struct sfnt_font_info *info;
 +#ifdef HAVE_MMAP
 +  struct sfnt_font_info **next;
 +#endif /* HAVE_MMAP */
 +
 +  info = (struct sfnt_font_info *) font;
 +
 +  /* If info->desc is still set, dereference the font tables.  */
 +  if (info->desc)
 +    sfnt_dereference_font_tables (info->desc);
 +  info->desc = NULL;
 +
 +  /* Free the interpreter, which is created on a per font basis.  */
 +  xfree (info->interpreter);
 +
 +  /* Clear these fields.  It seems that close can be called twice,
 +     once during font driver destruction, and once during GC.  */
 +
 +  info->cmap = NULL;
 +  info->hhea = NULL;
 +  info->maxp = NULL;
 +  info->head = NULL;
 +  info->hhea = NULL;
 +  info->glyf = NULL;
 +  info->loca_short = NULL;
 +  info->loca_long = NULL;
 +  info->cmap_data = NULL;
 +  info->prep = NULL;
 +  info->fpgm = NULL;
 +  info->cvt = NULL;
 +  info->interpreter = NULL;
 +  info->uvs = NULL;
 +
 +  /* Deinitialize the blend.  */
 +  if (info->instance != -1 && info->blend.coords)
 +    sfnt_free_blend (&info->blend);
 +  info->instance = -1;
 +
 +#ifdef HAVE_MMAP
 +
 +  /* Unlink INFO.  */
 +
 +  next = &open_fonts;
 +  while (*next && (*next) != info)
 +    next = &(*next)->next;
 +
 +  if (*next)
 +    *next = info->next;
 +  info->next = NULL;
 +
 +#endif /* HAVE_MMAP */
 +
 +#ifdef HAVE_HARFBUZZ
 +  /* These fields will be freed or closed by
 +     sfnt_dereference_font_tables, but clear them here for good
 +     measure.  */
 +  info->directory = NULL;
 +  info->fd = -1;
 +
 +  /* Free any hb_font created.  */
 +
 +  if (info->hb_font)
 +    {
 +      hb_font_destroy (info->hb_font);
 +      info->hb_font = NULL;
 +    }
 +#endif
 +
 +  sfntfont_free_outline_cache (&info->outline_cache);
 +  sfntfont_free_raster_cache (&info->raster_cache);
 +}
 +
 +\f
 +
 +/* Glyph display.  */
 +
 +/* Function called to actually draw rasters to the glass.  */
 +static sfntfont_put_glyph_proc sfnt_put_glyphs;
 +
 +/* Draw glyphs in S->char2b starting from FROM to TO, with the origin
 +   at X and baseline at Y.  Fill the background from X, Y +
 +   FONT_DESCENT to X + S->background_width, Y - FONT_ASCENT with the
 +   background color if necessary.  Use the foreground and background
 +   colors in S->gc.  */
 +
 +int
 +sfntfont_draw (struct glyph_string *s, int from, int to,
 +             int x, int y, bool with_background)
 +{
 +  int length;
 +  struct sfnt_raster **rasters;
 +  int *x_coords, current_x, i;
 +  struct sfnt_glyph_outline *outline;
 +  struct font *font;
 +  struct sfnt_font_info *info;
 +  struct sfnt_glyph_metrics metrics;
 +
 +  length = to - from;
 +  font = s->font;
 +  info = (struct sfnt_font_info *) font;
 +
 +  rasters = alloca (length * sizeof *rasters);
 +  x_coords = alloca (length * sizeof *x_coords);
 +  current_x = x;
 +
 +  /* Get rasters and outlines for them.  */
 +  for (i = from; i < to; ++i)
 +    {
 +      /* Look up the outline.  */
 +      outline = sfntfont_get_glyph_outline (s->char2b[i],
 +                                          &info->outline_cache,
 +                                          info->scale,
 +                                          &info->outline_cache_size,
 +                                          &info->blend,
 +                                          info->instance,
 +                                          info->glyf, info->head,
 +                                          info->hmtx, info->hhea,
 +                                          info->maxp,
 +                                          info->loca_short,
 +                                          info->loca_long,
 +                                          info->interpreter,
 +                                          &metrics,
 +                                          &info->state);
 +      x_coords[i - from] = 0;
 +
 +      if (!outline)
 +      {
 +        rasters[i - from] = NULL;
 +        continue;
 +      }
 +
 +      /* Rasterize the outline.  */
 +      rasters[i - from] = sfntfont_get_glyph_raster (s->char2b[i],
 +                                                   &info->raster_cache,
 +                                                   outline,
 +                                                   &info->raster_cache_size);
 +      sfntfont_dereference_outline (outline);
 +
 +      if (!rasters[i - from])
 +      continue;
 +
 +      /* Now work out where to put the outline.  */
 +      x_coords[i - from] = current_x;
 +
 +      if (s->padding_p)
 +      current_x += 1;
 +      else
 +      current_x += SFNT_CEIL_FIXED (metrics.advance) / 65536;
 +    }
 +
 +  /* Call the window system function to put the glyphs to the
 +     frame.  */
 +  sfnt_put_glyphs (s, from, to, x, y, with_background,
 +                 rasters, x_coords);
 +
 +  /* Dereference all the rasters.  */
 +  for (i = 0; i < from - to; ++i)
 +    {
 +      if (rasters[i])
 +      sfntfont_dereference_raster (rasters[i]);
 +    }
 +
 +  return 1;
 +}
 +
 +\f
 +
 +/* Other callbacks.  */
 +
 +/* Return a list of each font family known to Emacs.  F is supposed to
 +   be a frame but is ignored.  */
 +
 +Lisp_Object
 +sfntfont_list_family (struct frame *f)
 +{
 +  Lisp_Object families;
 +  struct sfnt_font_desc *desc;
 +
 +  families = Qnil;
 +
 +  for (desc = system_fonts; desc; desc = desc->next)
 +    /* Add desc->family to the list.  */
 +    families = Fcons (desc->family, families);
 +
 +  /* Not sure if deleting duplicates is worth it.  Is this ever
 +     called? */
 +  return families;
 +}
 +
 +\f
 +
 +/* Unicode Variation Selector (UVS) support.  This is typically
 +   required for Harfbuzz.  */
 +
 +/* Given a FONT object, a character C, and VARIATIONS, return the
 +   number of non-default variation glyphs, and their glyph ids in
 +   VARIATIONS.
 +
 +   For each variation selector character K with a non-default glyph in
 +   the variation selector range 0xFE00 to 0xFE0F, set variations[K -
 +   0xFE0] to its ID.
 +
 +   For each variation selector character K with a non-default glyph in
 +   the variation selector range 0xE0100 to 0xE01EF, set variations[K -
 +   0xE0100 + 16] to its ID.
 +
 +   If value is more than 0, set all other members of VARIATIONS to 0.
 +   Else, the contents of VARIATIONS are undefined.  */
 +
 +int
 +sfntfont_get_variation_glyphs (struct font *font, int c,
 +                             unsigned variations[256])
 +{
 +  struct sfnt_font_info *info;
 +  size_t i;
 +  int n;
 +  struct sfnt_mapped_variation_selector_record *record;
 +
 +  info = (struct sfnt_font_info *) font;
 +  n = 0;
 +
 +  /* Return 0 if there is no UVS mapping table.  */
 +
 +  if (!info->uvs)
 +    return 0;
 +
 +  /* Clear the variations array.  */
 +
 +  memset (variations, 0, sizeof *variations * 256);
 +
 +  /* Find the first 0xFExx selector.  */
 +
 +  i = 0;
 +  while (i < info->uvs->num_records
 +       && info->uvs->records[i].selector < 0xfe00)
 +    ++i;
 +
 +  /* Fill in selectors 0 to 15.  */
 +
 +  while (i < info->uvs->num_records
 +       && info->uvs->records[i].selector <= 0xfe0f)
 +    {
 +      record = &info->uvs->records[i];
 +
 +      /* If record has no non-default mappings, continue on to the
 +       next selector.  */
 +
 +      if (!record->nondefault_uvs)
 +      goto next_selector;
 +
 +      /* Handle invalid unsorted tables.  */
 +
 +      if (record->selector < 0xfe00)
 +      return 0;
 +
 +      /* Find the glyph ID associated with C and put it in
 +       VARIATIONS.  */
 +
 +      variations[info->uvs->records[i].selector - 0xfe00]
 +      = sfnt_variation_glyph_for_char (record->nondefault_uvs, c);
 +
 +      if (variations[info->uvs->records[i].selector - 0xfe00])
 +      ++n;
 +
 +    next_selector:
 +      ++i;
 +    }
 +
 +  /* Find the first 0xE0100 selector.  */
 +
 +  i = 0;
 +  while (i < info->uvs->num_records
 +       && info->uvs->records[i].selector < 0xe0100)
 +    ++i;
 +
 +  /* Fill in selectors 16 to 255.  */
 +
 +  while (i < info->uvs->num_records
 +       && info->uvs->records[i].selector <= 0xe01ef)
 +    {
 +      record = &info->uvs->records[i];
 +
 +      /* If record has no non-default mappings, continue on to the
 +       next selector.  */
 +
 +      if (!record->nondefault_uvs)
 +      goto next_selector_1;
 +
 +      /* Handle invalid unsorted tables.  */
 +
 +      if (record->selector < 0xe0100)
 +      return 0;
 +
 +      /* Find the glyph ID associated with C and put it in
 +       VARIATIONS.  */
 +
 +      variations[info->uvs->records[i].selector - 0xe0100 + 16]
 +      = sfnt_variation_glyph_for_char (record->nondefault_uvs, c);
 +
 +      if (variations[info->uvs->records[i].selector - 0xe0100 + 16])
 +      ++n;
 +
 +    next_selector_1:
 +      ++i;
 +    }
 +
 +  return n;
 +}
 +
 +\f
 +
 +/* mmap specific stuff.  */
 +
 +#ifdef HAVE_MMAP
 +
 +/* Return whether or not ADDR lies in a mapped glyph, and bus faults
 +   should be ignored.  */
 +
 +bool
 +sfntfont_detect_sigbus (void *addr)
 +{
 +  struct sfnt_font_info *info;
 +
 +  for (info = open_fonts; info; info = info->next)
 +    {
 +      if (info->glyf_table_mapped
 +        && (unsigned char *) addr >= info->glyf->glyphs
 +        && (unsigned char *) addr < (info->glyf->glyphs
 +                                     + info->glyf->size))
 +      return true;
 +    }
 +
 +  return false;
 +}
 +
 +#endif
 +
 +\f
 +
 +/* Harfbuzz font support.  */
 +
 +#ifdef HAVE_HARFBUZZ
 +
 +#ifdef HAVE_MMAP
 +
 +/* Unmap the specified table.  */
 +
 +static void
 +sfntfont_unmap_blob (void *ptr)
 +{
 +  if (sfnt_unmap_table (ptr))
 +    emacs_abort ();
 +
 +  xfree (ptr);
 +}
 +
 +#endif /* HAVE_MMAP */
 +
 +/* Given a font DATA and a tag TAG, return the data of the
 +   corresponding font table as a HarfBuzz blob.  */
 +
 +static hb_blob_t *
 +sfntfont_get_font_table (hb_face_t *face, hb_tag_t tag, void *data)
 +{
 +  size_t size;
 +  struct sfnt_font_info *info;
 +#ifdef HAVE_MMAP
 +  struct sfnt_mapped_table *table;
 +  hb_blob_t *blob;
 +
 +  info = data;
 +  table = xmalloc (sizeof *table);
 +
 +  if (!sfnt_map_table (info->fd, info->directory, tag,
 +                     table))
 +    {
 +      /* Create an hb_blob_t and return it.
 +         TODO: record this mapping properly so that SIGBUS can
 +       be handled.  */
 +
 +      blob = hb_blob_create (table->data, table->length,
 +                           HB_MEMORY_MODE_READONLY,
 +                           table, sfntfont_unmap_blob);
 +
 +      /* Note that sfntfont_unmap_blob will be called if the empty
 +       blob is returned.  */
 +      return blob;
 +    }
 +
 +  xfree (table);
 +#else /* !HAVE_MMAP */
 +
 +  /* Try to read the table conventionally.  */
 +  info = data;
 +#endif /* HAVE_MMAP */
 +
 +  data = sfnt_read_table (info->fd, info->directory, tag,
 +                        &size);
 +
 +  if (!data)
 +    return NULL;
 +
 +  return hb_blob_create (data, size, HB_MEMORY_MODE_WRITABLE,
 +                       data, xfree);
 +}
 +
 +/* Create or return a HarfBuzz font object corresponding to the
 +   specified FONT.  Return the scale to convert between fwords and
 +   pixels in POSITION_UNIT.  */
 +
 +hb_font_t *
 +sfntfont_begin_hb_font (struct font *font, double *position_unit)
 +{
 +  struct sfnt_font_info *info;
 +  hb_face_t *face;
 +  int factor;
 +
 +  info = (struct sfnt_font_info *) font;
 +
 +  if (info->hb_font)
 +    {
 +      /* Calculate the scale factor.  */
 +      *position_unit = 1.0 / 64.0;
 +      return info->hb_font;
 +    }
 +
 +  /* Create a face and then a font.  */
 +  face = hb_face_create_for_tables (sfntfont_get_font_table, font,
 +                                  NULL);
 +
 +  if (hb_face_get_glyph_count (face) > 0)
 +    {
 +      info->hb_font = hb_font_create (face);
 +      if (!info->hb_font)
 +      goto bail;
 +
 +      factor = font->pixel_size;
 +
 +      /* Set the scale and PPEM values.  */
 +      hb_font_set_scale (info->hb_font, factor * 64, factor * 64);
 +      hb_font_set_ppem (info->hb_font, factor, factor);
 +
 +#ifdef HAVE_HB_FONT_SET_VAR_NAMED_INSTANCE
 +      /* Set the instance if this is a distortable font.  */
 +      if (info->instance != -1)
 +      hb_font_set_var_named_instance (info->hb_font,
 +                                      info->instance);
 +#endif /* HAVE_HB_FONT_SET_VAR_NAMED_INSTANCE */
 +
 +      /* This is needed for HarfBuzz before 2.0.0; it is the default
 +       in later versions.  */
 +      hb_ot_font_set_funcs (info->hb_font);
 +    }
 +
 + bail:
 +  hb_face_destroy (face);
 +
 +  /* Calculate the scale factor.  */
 +  *position_unit = 1.0 / 64.0;
 +  return info->hb_font;
 +}
 +
 +#endif /* HAVE_HARFBUZZ */
 +
 +\f
 +
 +void
 +syms_of_sfntfont (void)
 +{
 +  DEFSYM (Qutf_16be, "utf-16be");
 +  DEFSYM (Qmac_roman, "mac-roman");
 +  DEFSYM (Qchinese_big5, "chinese-big5");
 +  DEFSYM (Qunicode_bmp, "unicode-bmp");
 +  DEFSYM (Qucs, "ucs");
 +  DEFSYM (Qjapanese_jisx0208, "japanese-jisx0208");
 +  DEFSYM (Qgbk, "gbk");
 +  DEFSYM (Qkorean_ksc5601, "korean-ksc5601");
 +  DEFSYM (Qapple_roman, "apple-roman");
 +  DEFSYM (Qjisx0208_1983_0, "jisx0208.1983-0");
 +  DEFSYM (Qksc5601_1987_0, "ksc5601.1987-0");
 +  DEFSYM (Qzh, "zh");
 +  DEFSYM (Qja, "ja");
 +  DEFSYM (Qko, "ko");
 +  DEFSYM (Qfont_instance, "font-instance");
 +
 +  /* Char-table purpose.  */
 +  DEFSYM (Qfont_lookup_cache, "font-lookup-cache");
 +
 +  /* Set up staticpros.  */
 +  sfnt_vendor_name = Qnil;
 +  staticpro (&sfnt_vendor_name);
 +
 +  /* This variable is supposed to be set by the platform specific part
 +     of the font backend.  */
 +  DEFVAR_LISP ("sfnt-default-family-alist", Vsfnt_default_family_alist,
 +    doc: /* Alist between "emulated" and actual font family names.
 +
 +Much Emacs code assumes that font families named "Monospace" and "Sans
 +Serif" exist, and map to the default monospace and Sans Serif fonts on
 +a system.  When the `sfnt' font driver is asked to look for a font
 +with one of the families in this alist, it uses its value instead.  */);
 +  Vsfnt_default_family_alist = Qnil;
 +}
 +
 +void
 +mark_sfntfont (void)
 +{
 +  struct sfnt_font_desc *desc;
 +
 +  /* Mark each font desc.  */
 +  for (desc = system_fonts; desc; desc = desc->next)
 +    {
 +      mark_object (desc->family);
 +      mark_object (desc->style);
 +      mark_object (desc->adstyle);
 +      mark_object (desc->instances);
 +      mark_object (desc->languages);
 +      mark_object (desc->registry);
 +      mark_object (desc->char_cache);
 +      mark_object (desc->designer);
 +    }
 +}
 +
 +void
 +init_sfntfont (void)
 +{
 +
 +}
 +
 +\f
 +
 +/* Initialize the sfntfont font driver.  VENDOR_TYPE is the type of
 +   all font entities created.  DRIVER is the font driver that is saved
 +   in font objects.  PUT_GLYPHS is a function that is called with 8
 +   arguments, S, FROM, TO, X, Y, WITH_BACKGROUND, RASTERS, and
 +   X_COORDS, and should draw all the rasters in RASTERS to S->f,
 +   originating at X_COORDS[i], Y, along with filling the background if
 +   WITH_BACKGROUND is specified.  */
 +
 +void
 +init_sfntfont_vendor (Lisp_Object vendor_name,
 +                    const struct font_driver *driver,
 +                    sfntfont_put_glyph_proc put_glyphs)
 +{
 +  sfnt_vendor_name = vendor_name;
 +  sfnt_font_driver = driver;
 +  sfnt_put_glyphs = put_glyphs;
 +}
diff --cc src/xdisp.c
index 69aa9bb9c336792d80ade1f958eed0e0db34d47f,9cddcfeda2759189c80dc1f05b15f06197557cf4..d62a8d983173c3efc1931740edd15928510c3351
@@@ -15558,39 -15422,18 +15558,39 @@@ redisplay_tool_bar (struct frame *f
        border = 0;
  
        rows = f->n_tool_bar_rows;
 -      height = max (1, (it.last_visible_y - border) / rows);
 -      extra = it.last_visible_y - border - height * rows;
  
 -      while (it.current_y < it.last_visible_y)
 +      if (f->tool_bar_wraps_p)
        {
 -        int h = 0;
 -        if (extra > 0 && rows-- > 0)
 +        /* If the tool bar contains explicit line wrapping items,
 +           don't force each row to have a fixed height.  */
 +
 +        while (!ITERATOR_AT_END_P (&it))
 +          display_tool_bar_line (&it, -1);
 +
 +        /* Because changes to individual tool bar items may now
 +           change the height of the tool bar, adjust the height of
 +           the tool bar window if it is different from the tool bar
 +           height in any way.  */
 +
 +        if (it.current_y != it.last_visible_y)
 +          change_height_p = true;
 +      }
 +      else
 +      {
 +        height = max (1, (it.last_visible_y - border) / rows);
 +        extra = it.last_visible_y - border - height * rows;
 +
 +        while (it.current_y < it.last_visible_y)
            {
 -            h = (extra + rows - 1) / rows;
 -            extra -= h;
 +            int h = 0;
 +            if (extra > 0 && rows-- > 0)
 +              {
 +                h = (extra + rows - 1) / rows;
 +                extra -= h;
 +              }
-         
++
 +            display_tool_bar_line (&it, height + h);
            }
 -        display_tool_bar_line (&it, height + h);
        }
      }
    else
Simple merge