--- /dev/null
- ---
+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:
--- /dev/null
- 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;
+}