emacs-diffs
[Top][All Lists]
Advanced

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

master ea986a64b23: Merge from origin/emacs-29


From: Eli Zaretskii
Subject: master ea986a64b23: Merge from origin/emacs-29
Date: Sat, 13 May 2023 06:37:44 -0400 (EDT)

branch: master
commit ea986a64b234c3e946d4577dc2ccfd261855c60b
Merge: bfc07100d28 7acae22f42f
Author: Eli Zaretskii <eliz@gnu.org>
Commit: Eli Zaretskii <eliz@gnu.org>

    Merge from origin/emacs-29
    
    7acae22f42f Fix auto-filling in Texinfo mode
    4bda9627349 ; * admin/git-bisect-start: Update failing commits
    dcf8c011028 Merge branch 'scratch/long-lines-cleanup' into 'emacs-29'
    1e3a66df459 Add an assertion in, and a commentary for, 'get_nearby_bo...
    f0f08eeb05c Fix the return type of 'labeled_restrictions_get_bound'
    acf4763417e Fix mouse highlight with some fonts in Cairo builds
    32b42b333ca ; * etc/NEWS: Fix wording in last change.
    09d6070e56e ; Improve and update documentation of built-in package up...
    ba2c76fa2bc Ensure that package menu respects 'package-install-upgrad...
    6fa9332e7cd Ensure that EXTRA-DATA are always written when generating...
    60d5a015d1f Update to Transient v0.4.0
    b8bcd42cabc Revert "Don't have nntp-report signal an error"
    ef1f4068f6f ; * lisp/wid-edit.el (widget-specify-insert): Fix debug s...
    09bf4768360 Make c-emacs-features use the proper binding of parse-sex...
    c9e2a5ec26c ; * lisp/obsolete/autoload.el (make-directory-autoloads):...
    346f4ac3bf5 ; Fix example in ELisp manual
    91fff05ae35 ; Fix wording in Emacs manual
    2438fa2e6cc ; Fix minor documentation issue ion replace.el
    93005cd9dc2 with-display-message: Workaround for bug#63253
    6924c81a6d2 ; Don't use literal non-ASCII characters in Texinfo
    f1675df3d0c Fido-mode: never shadow 'external' completion style
    56d2949d44c ; * lisp/leim/quail/persian.el: Fix a typo in last commit.
    d94ea9efca6 Avoid crashes in --without-all build trying to scale non-...
    387ddc0ccc1 Improve instructions for dealing with Emacs crashes
    e6b4784a37f Improved transliterations + improved bidi insertion suppo...
    c1363a04bb2 Fix crash when creating a child frame in NS (bug#63107)
    7d6855c9ab6 Fix outgoing mime type regression (Bug#62815)
    e920dd2b6f9 define-minor-mode: sanitize mode function messages
    910a7b30dfd Fix beginning/end-of-defun with tree-sitter
    e205f68717e Fix indent for enums in csharp-mode
    dfde902f3b9 ; Expand 'package-vc-install' documentation
    71337843036 Teach c-ts-mode about the 'restrict' keyword
    15e06260ae8 * lisp/x-dnd.el (x-dnd-after-move-frame): Skip dead frame...
    a081b6625bd ; Updated Elispref-Manual: `nil' cannot be defun'ed
    97b818a4fb9 Fix doc strings of 'mark-sexp' and 'mark-word'
    6f910ad9322 ; * etc/EGLOT-NEWS: Fix misspellings.
    9b775ddc057 ; * etc/EGLOT-NEWS: Fix wording of last change.
    79a886ba368 (package-upgrade): Don't remove the package from 'package...
    c0ab4e9ca93 Eglot: re-rename eglot-upgrade to eglot-upgrade-eglot
    b4e90070f96 Fix arguments of xml.c functions as displayed in Help buf...
    b1bda8228e5 More fixes for NetBSD/vax
    a2d4cd06f45 Improve VHDL mode highlighting
    2f3a514b6db Clarify documentation wrt floating point division by zero...
    94e984e6700 Make loaddefs-generate slightly more tolerant
    aba41d2c4bb ; Minor doc cleanups in go-ts-mode.el
    b42ccb2e5c1 ; Minor grammar fix in treesit manual.
    ab44c8a6f9d Fix order of rcirc-connect arguments
    8eb6e33691d Fix rcirc messages printing in the wrong place
    2901a3443c7 Prevent unnecessary modifications of 'package-vc-selected...
    eaad302bd6f Rename eglot-update to eglot-upgrade
    eaf25b9c6ae go-ts-mode: Use iota query only if supported (Bug#63086)
    cc090294d77 (rng-complete-tag): Add the (ignored) argument to the :co...
    21ec6c1d5cc Update to Transient v0.3.7-219-g3ded15b
    8d5aa8df4ad Fix inserting selection data into Mozilla programs
    57562c3fd0a Recognize defstruct slot names in various eieio functions
    b93eb68cc30 Use 'calendar-buffer' instead of fixed string
    e338a8ac41d Handle point not at EOB in minibuffer-choose-completion
    fceaf230b06 Note that Emacs pauses when handling sentinel errors
    46392c1623b Fix vertical-motion when tab-line is displayed in a window
    0e52beeacea Update to Org 9.6.5-3-g2993f4
    dd21003878d Prevent generating empty autoload files
    2bcf11d0efe * lisp/org/org-macs.el (org--inhibit-version-check): Fix ...
    ca43435816b Fix redisplay of mode line after its format changes from nil
    610a7657e0a Fix c-ts-mode--emacs-c-range-query
    7f94558b775 Improve documentation of warnings
    5a3f0e2c558 ; Doc fix in c-ts-mode.el
    21361d05635 Fix FOR_EACH_TAIL fontification (bug#62951)
    d0df3404fde ; * etc/EGLOT-NEWS:  chsharp-le -> csharp-ls
    c229e83c3ce ; * etc/EGLOT-NEWS (https): Elglot -> Eglot.
    b4f2f499783 Fix documentation of libxml-parse-* functions
    5dd784961d1 ; * src/treesit.c (syms_of_treesit): Fix error messages.
    ddfa0d8da9a ; Remove some leftover text
    212e30f6789 ; Fix byte-compilation warnings in c-ts-mode.el
    1f2214dabd0 Skip over whitespace in annotation-top-cont check (bug#63...
    7e136c51f6f Update zh-CN tutorial translation
    d3ca0b3aa2e ; * lisp/progmodes/c-ts-mode.el: Fix comments and doc str...
    c6f15c24862 ; Fix last change.
    b9e06330f75 ; * etc/NEWS: Followup to bug#62720.
    b33d25f5967 ; Minor improvements in doc strings of package-upgrade co...
    c3a61870b94 Fix eglot.texi
    a40f1816237 Fix two crashes upon startup
    44ebd9cbd56 Eglot: explain how to update Eglot in manual (bug#62720)
    941ef044f2e Eglot: fix edge case when deleting inlay hint overlays
    a365984d9e1 package-upgrade[-all]: Expand docstrings to note the curr...
    f965f35b33b Rename all functions called package-*-update-* to package...
    31b58161bb5 Fix FOR_EACH_TAIL in c-ts-mode (bug#62951)
    0cf6e0998ba * Makefile.in (distclean): Remove the 'native-lisp' direc...
    933705d61e5 Improve greek-ibycus4 input method
    c46e93b1f50 Explain ERC 5.5 regressions in new version 5.5.0.29.1
    af43f0a2954 * doc/misc/erc.texi: Elaborate on upgrading via ELPA.
    10948948c12 Improve outline-default-state docstring
    b5ace2eed80 Document problems with /bin/sh on Solaris 10
    7b2ad8f199e ; Add missing <<inserted by help-with-tutorial>> line to ...
    524e161a536 Followup to addition of TUTORIAL.fa
    76f50df1539 Add Farsi/Persian translation of the tutorial
    8eacfaea6d8 Add Mongolian language environments
    fe8efbb8f75 Document the 'end-session' event on MS-Windows
    d80f959bede Update to Org 9.6.4-9-g8eb209
    98c6cfcbe4a Don't support versioned grammar libraries on MS-Windows
    8f71c1546df Accept versioned tree-sitter language grammar files
    99add09d5e1 tab-bar-new-tab: inhibit side-window checks
    087e8181947 * etc/NEWS: Fix outline level.  (Bug#63042)
    d7f38558c4c ; Improve font selection for Traditional Mongolian
    965c5e0231c Fix rendering of Traditional Mongolian script
    9a0f10b5f88 Fix line-number-at-pos when POSITION is out of narrowing
    4e0f4292aaf ; * etc/tutorials/TUTORIAL: Fix punctuation.
    dec2ac0c657 Fix exiting Emacs after saving a tutorial
    44145bf07e2 Add indentation style setting for c-ts-mode in .dir-local...
    e7db6c59cc6 ; * .dir-locals.el (c-ts-mode): Add settings.
    d041f01b02f ; Minor fix in Emacs Lisp Intro manual
    3899acbb336 ; * src/fringe.c: Fix description of large circle.  (Bug#...
    2b10e1827d3 sql: add missing postgresql types
    9ac12592781 Fix display of menu-bar bindings of commands in *Help* bu...
    ecdd3a9efac Improve Completion Example section in the Emacs manual
    626e1ac62b2 Improve 'message-server-alist' docstring
    327986936c3 Add index entry for fallback modes
    1c4783c3300 ; * etc/NEWS: Copyedits and grammar fixes.
    3d6f7553319 xref-search-program-alist: Fix searching larger file list...
    1b8b2cf61bd Fix typo and inaccuracy in the ELisp Reference manual
    df17682ebf1 ; Support 'dart-ts-mode' in Eglot
    e0dc60e0780 ; Fix typos in gdb-mi.el
    60560cc7adf Fix description of lexical environment's internals
    1456adf4248 ; Eglot: fix a typo in a customization type
    2f59595f5f4 ; * etc/NEWS: Grammar fixes.
    596b780ab71 Update to Org 9.6.4-2-g0f6ae7
    a0b04a22479 Documentation copyedits for 'package-install-upgrade-buil...
    580d8278c5f Allow upgrading built-in packages with 'package-install'
    329304c23fa ; * src/term.c (init_tty): Fix last change.  (Bug#62877)
    200dbf7d302 Minor changes in c-ts-mode.el's support of DEFUNs
    9686b015a0d Fix strike-through attribute support on TTY frames
    39035fbfc5f Avoid crashes in 'describe-keymap' due to shadowing
    b7023da6627 Make image-map bindings available on image links
    d9e96c029bb * CONTRIBUTE: Fix a typo
    3f71a2a0cf6 ; * lisp/progmodes/c-ts-mode.el (treesit-node-next-siblin...
    adf9c956c28 Add to Eglot support for additional language-servers.
    b3603b84bd9 Partial support for DEFUN in c-ts-mode (bug#62825)
    14e809ddff1 Fix style and unwinding code in treesit.c
    759cdf1e510 Catch signals produced by PRED in tree-sitter search func...
    864a4dc2363 Fix compilation of w32.c with old MinGW system headers
    a22eb9ae0f9 ruby-add-log-current-method: Reduce the use of 'nreverse'
    17d803d0a75 Fix detection of WebP images by their signature
    43290391ce2 ; Eglot: make version parseable by version-to-list
    6e6e8b5c974 Add more documentation for the keys of `package-vc-select...
    7972b76c2c7 ; vc-checkout: Wrap var lookup in 'bound-and-true-p'
    e9fef1d70ff vc-checkout: Try to use the vc-dir's backend first
    372e024accd ; Fix wallpaper-tests on XFCE
    7055fd8e43e Improve documentation related to 'ispell-complete-word'
    61fd017abde * configure.ac: Add -lbsd on Haiku.
    05971c4d9a4 Add menu to 'c-ts-mode' and 'c++-ts-mode'
    954e2d96a92 Update manual about `sort`
    c62afb10cf0 Fix wallpaper-tests on MS-Windows
    f2d212c6966 Fix a couple of eglot-tests
    338b3718b6c Fix visiting RPM files
    b4afee03193 Fix ff-quiet-mode doc
    2445100d7d6 ; Improve documentation of 'match-buffers'
    d4d0da96f0b ; Update make-tarball.txt for Emacs 29.
    9b0bf694da4 ; Fix ldefs-boot.el.
    0cb86a348c7 ; Update ChangeLog.4.
    5e039d5a6e9 * lisp/ldefs-boot.el: Regenerate.
    671abd0cc40 Merge branch 'emacs-29' of git.sv.gnu.org:/srv/git/emacs ...
    4bc678ec9f4 Bump Emacs version to 29.0.90
    db8f207e52f Fix some cases of incomplete code's indentation [c/c++-ts...
    589959fb09d project-search: Pipe the list of files through 'file-regu...
    2b91567bf61 Update ChangeLog and AUTHORS for Emacs 29
    d6af1f14982 ; doc/lispref/windows.texi: Fix @pxref paren.
    57490fff6ec ; Backport: Eglot: fix misplaced parenthesis in last comm...
    2a62273f3bf Backport: Eglot: no more tests based on Pylsp (bug#62694)
    5ef7ff05736 ; Start a new ChangeLog.4 file.
    11126c6d30a Fix 'C-h k' for "Paste from Kill Menu" in context menus
    74ddfe811f9 ; * doc/misc/calc.texi (Rewrites Tutorial): Fix a typo (b...
    08cda286c3f Improve the documentation of the XDS support
    14d1c00e806 Allow reindentation of images inserted by 'mm-inline-image'
    b63a9eda01c Fix "C-h k" and "C-h c" with Paste from Kill Menu
    b36c21e27dc Change cursor color on NS port when it matches the face b...
    96714c106b7 Improve documentation of image-related commands
    6a2863ca016 Fix handling of sliced images
    5be79fd05a5 ; * etc/NEWS: Announce 'cyrillic-mongolian' IM.
    ca1a0fda98a ; Fix last change.
    ce63462dbda Add cyrillic-mongolian input method
    58801792706 ; Minor addition to the Emacs FAQ
    88847dee125 Jsonrpc: don't bind inhibit-read-only to t so early
    cb8c87a423a Allow active region when IM is used
    305246d9726 Add emoji-zoom-reset
    470d269ec1f Make emoji-zoom-{increase,decrease} set text properties c...
    63d4a86f8d1 Fix transforming sliced images
    5e1953a8f85 ; * etc/NEWS: Minor copyedits of entry for 'keymap-*' fun...
    6b9f9df9454 ; Improve documentation of 'declare-function'
    81d1f46d0fe ; Avoid compiler warning in eglot.el.
    38cdfcb2128 ; Fix description of new 'keymap-*' functions
    257090b8728 Adapt EMBA scripts.
    90c07d3fdd2 Another terminology fix in ELisp reference manual
    a832bc7090c Correct terminology in Elisp Reference Manual
    db308233cb3 Comment out GNUSTEP jobs on EMBA (again)
    8c1b1022439 ; * lisp/image.el (put-image): Doc fix.
    eda88c63adf ; * doc/emacs/trouble.texi (Checklist): Minor grammar fix.
    728bc09cf3c Fix regexp string escaping mistake in vhdl-mode.el (bug#6...
    479626dbac9 Update to Org 9.6.3-2-gf2949d
    5a1c9aace70 ; Add a bit more docstring to tsx-ts-mode (bug#62429)
    86cf9fd932c Eglot: don't watch directories that don't exist
    82d0b6c64ea ; * lisp/subr.el (use-dialog-box-p): Fix last change.
    3619663f982 Preserve peer information for web page in eww-readable
    cb8d6ab648f * lisp/subr.el (use-dialog-box-p): Fix conditions for GUI...
    fb2c4409207 ; * lisp/progmodes/c-ts-mode.el (c++-ts-mode): Add some n...
    c0b9530862c Another final fix to last changes
    0cc8d6826ad Three final fixes to last changes
    89e337c3fc9 ; Make sure 'eshell-command' tests don't prompt the user
    097c5ee8f55 Two further fixes to last changes
    b39c3cd1125 ; * etc/NEWS: Fix typos.
    dce08cf05cc Improve and fix last changes
    89ac5ba11c7 Fix ModelSim error regexp in vhdl-mode
    24ed9c7ae78 ; * doc/emacs/trouble.texi (Checklist): Minor copyedits (...
    d1d39a0f09c Document enhancements in handling of echo-area messages
    46209b2453b ; Fix last change
    21a4ee209c1 Fix new Eshell tests on MS-Windows
    e2ebf3995d0 ; Auto-commit of loaddefs files.
    6419d78fa6f Fix using background commands in 'eshell-command'
    3bdbb66efb9 ; CONTRIBUTE: Minor stylistic changes.
    d0eb12e8d3c Fix typo in section 14.1 of Emacs Manual
    b2fbec37f39 ; * etc/EGLOT-NEWS: Clarify scope of topmost section
    131ec049db0 Eglot: unbreak eglot-extend-to-xref on w32
    0622e1f29f6 Eglot: ensure server shutdown turns off eglot-inlay-hints...
    59f66ea3027 ; * lisp/emacs-lisp/package-vc.el: Remove completed item ...
    d23dc3dd7e3 ; * lisp/emacs-lisp/package-vc.el (package-vc): Fix manua...
    4508a024e81 ; Clarify documentation of 'cursor' text property
    d2e82817a3f Add two typescript-ts-mode faces (bug#62429)
    10918fc9d24 Fix scrolling window when point moves up
    9b32bc134c4 Improve documentation of 'defcustom's :set keyword
    ab4273056e0 Comp fix calls to redefined primtives with op-bytecode (b...
    c98929c7e18 ; Fix last change
    a14c3f62a67 ; Fix last change
    09fece5722f Fix duplicate defcustom in eww.el
    2093e010dc1 Fix cursor motion in character-only terminals
    e45bd10a3d9 Fix indentation regression in 'C-h l'
    46fd10a7600 * doc/misc/tramp.texi (Remote shell setup): Clarify use o...
    974e4f33333 Make get_medium_narrowing_begv/zv static
    afc2c6c13cb Improve accuracy of cursor motion commands in long lines
    7e26a5c774e Remove labeled restrictions before calling Fwiden
    85ed1c9ca6b Code cleanup for long line optimizations
    
    # Conflicts:
    #       etc/NEWS
---
 admin/git-bisect-start          |   5 +-
 doc/emacs/package.texi          |  50 +++++-
 doc/lispref/positions.texi      |   1 +
 doc/misc/transient.texi         |   4 +-
 etc/NEWS.29                     |   7 +
 lisp/emacs-lisp/loaddefs-gen.el |  15 +-
 lisp/emacs-lisp/package.el      |   4 +-
 lisp/gnus/nntp.el               |   4 +-
 lisp/subr.el                    |   4 +-
 lisp/textmodes/texinfo.el       |  14 +-
 lisp/transient.el               |  11 +-
 lisp/wid-edit.el                |   2 +-
 src/buffer.c                    |   1 +
 src/callproc.c                  |   1 +
 src/composite.c                 |   4 +-
 src/dispextern.h                |  37 ++---
 src/editfns.c                   | 347 ++++++++++++++++++++++------------------
 src/fileio.c                    |   1 +
 src/ftcrfont.c                  |   1 -
 src/indent.c                    |   1 +
 src/keyboard.c                  |  12 +-
 src/lisp.h                      |   6 +-
 src/lread.c                     |   1 +
 src/xdisp.c                     | 209 +++++++++++++++++++-----
 24 files changed, 494 insertions(+), 248 deletions(-)

diff --git a/admin/git-bisect-start b/admin/git-bisect-start
index 511111c7f65..cae9c7918a8 100755
--- a/admin/git-bisect-start
+++ b/admin/git-bisect-start
@@ -82,7 +82,7 @@ done
 # SKIP-BRANCH 58cc931e92ece70c3e64131ee12a799d65409100
 
 ## The list below is the exhaustive list of all commits between Dec 1
-## 2016 and Feb 28 2023 on which building Emacs with the default
+## 2016 and Apr 30 2023 on which building Emacs with the default
 ## options, on a GNU/Linux computer and with GCC, fails.  It is
 ## possible (though unlikely) that building Emacs with non-default
 ## options, with other compilers, or on other platforms, would succeed
@@ -1720,3 +1720,6 @@ $REAL_GIT bisect skip $(cat $0 | grep '^# SKIP-SINGLE ' | 
sed 's/^# SKIP-SINGLE
 # SKIP-SINGLE 95692f6754c3a8f55a90df2d6f7ce62be55cdcfc
 # SKIP-SINGLE a3edacd3f547195740304139cb68aaa94d7b18ee
 # SKIP-SINGLE ae4ff4f25fbf704446f8f38d8e818f223b79042b
+# SKIP-SINGLE 9686b015a0d71d08828afb0cfe6e477bbc4909ae
+# SKIP-SINGLE 621e732ade0f3dc165498ebde4d55d5aacb05b56
+# SKIP-SINGLE 200dbf7d302e659e618f74bde81c7b3ccd795639
diff --git a/doc/emacs/package.texi b/doc/emacs/package.texi
index d1766026db2..6722185cb20 100644
--- a/doc/emacs/package.texi
+++ b/doc/emacs/package.texi
@@ -160,7 +160,13 @@ current line by an @kbd{i} or @kbd{d} command
 Mark all package with a newer available version for upgrading
 (@code{package-menu-mark-upgrades}).  This places an installation mark
 on the new available versions, and a deletion mark on the old
-installed versions (marked with status @samp{obsolete}).
+installed versions (marked with status @samp{obsolete}).  By default,
+this won't mark built-in packages for which a newer version is
+available, but customizing @code{package-install-upgrade-built-in} can
+change that.  @xref{Package Installation}.  If you customize
+@code{package-install-upgrade-built-in} to a non-@code{nil} value, be
+sure to review all the built-in packages the @kbd{U} command marks, to
+avoid updating built-in packages you don't want to overwrite.
 
 @item x
 @kindex x @r{(Package Menu)}
@@ -258,7 +264,11 @@ This shows only the packages that have been marked to be 
installed or deleted.
 @kindex / u @r{(Package Menu)}
 @findex package-menu-filter-upgradable
 Filter package list to show only packages for which there are
-available upgrades (@code{package-menu-filter-upgradable}).
+available upgrades (@code{package-menu-filter-upgradable}).  By
+default, this filter excludes the built-in packages for which a newer
+version is available, but customizing
+@code{package-install-upgrade-built-in} can change that.
+@xref{Package Installation}.
 
 @item / /
 @kindex / / @r{(Package Menu)}
@@ -286,9 +296,12 @@ the package archive.
 The package is available for installation, but a newer version is also
 available.  Packages with this status are hidden by default.
 
+@cindex built-in package
 @item built-in
 The package is included in Emacs by default.  It cannot be deleted
-through the package menu, and is not considered for upgrading.
+through the package menu, and by default is not considered for
+upgrading (but you can change that by customizing
+@code{package-install-upgrade-built-in}, @pxref{Package Installation}).
 
 @item dependency
 The package was installed automatically to satisfy a dependency of
@@ -339,6 +352,37 @@ if you want to upgrade a package, you can use the @kbd{M-x
 package-upgrade} command, and if you want to upgrade all the packages,
 you can use the @kbd{M-x package-upgrade-all} command.
 
+@vindex package-install-upgrade-built-in
+  By default, @code{package-install} doesn't consider built-in
+packages for which new versions are available from the archives.  (A
+package is built-in if it is included in the Emacs distribution.)  In
+particular, it will not show built-in packages in the list of
+completion candidates when you type at its prompt.  But if you invoke
+@code{package-install} with a prefix argument, it will also consider
+built-in packages that can be upgraded.  You can make this behavior
+the default by customizing the variable
+@code{package-install-upgrade-built-in}: if its value is
+non-@code{nil}, @code{package-install} will consider built-in packages
+even when invoked without a prefix argument.  Note that the
+package-menu commands (@pxref{Package Menu}) are also affected by
+@code{package-install-upgrade-built-in}.
+
+  By contrast, @code{package-upgrade} and @code{package-upgrade-all}
+never consider built-in packages.  If you want to use these commands
+for upgrading some built-in packages, you need to upgrade each of
+those packages, once, either via @kbd{C-u M-x package-install
+@key{RET}}, or by customizing @code{package-install-upgrade-built-in}
+to a non-@code{nil} value, and then upgrading the package once via the
+package menu or by @code{package-install}.
+
+  If you customize @code{package-install-upgrade-built-in} to a
+non-@code{nil} value, be very careful when using commands that update
+many packages at once, like @code{package-upgrade-all} and @kbd{U} in
+the package menu: those might overwrite built-in packages that you
+didn't intent to replace with newer versions from the archives.  Don't
+use these bulk commands if you want to update only a small number of
+built-in packages.
+
 @cindex package requirements
   A package may @dfn{require} certain other packages to be installed,
 because it relies on functionality provided by them.  When Emacs
diff --git a/doc/lispref/positions.texi b/doc/lispref/positions.texi
index edc7c86533c..1305daa7a2e 100644
--- a/doc/lispref/positions.texi
+++ b/doc/lispref/positions.texi
@@ -1188,6 +1188,7 @@ saved bounds.  In that case it is equivalent to
 @end example
 
 @cindex labeled narrowing
+@cindex labeled restriction
 When the optional argument @var{label}, a symbol, is present, the
 narrowing is @dfn{labeled}.  A labeled narrowing differs from a
 non-labeled one in several ways:
diff --git a/doc/misc/transient.texi b/doc/misc/transient.texi
index 33d689cc01b..330fdd1e3a2 100644
--- a/doc/misc/transient.texi
+++ b/doc/misc/transient.texi
@@ -31,7 +31,7 @@ General Public License for more details.
 @finalout
 @titlepage
 @title Transient User and Developer Manual
-@subtitle for version 0.3.7.50
+@subtitle for version 0.4.0
 @author Jonas Bernoulli
 @page
 @vskip 0pt plus 1filll
@@ -74,7 +74,7 @@ that hurdle is Psionic K's interactive tutorial, available at
 @end quotation
 
 @noindent
-This manual is for Transient version 0.3.7.50.
+This manual is for Transient version 0.4.0.
 
 @insertcopying
 @end ifnottex
diff --git a/etc/NEWS.29 b/etc/NEWS.29
index 5f5ae1c75a1..fa428d9c790 100644
--- a/etc/NEWS.29
+++ b/etc/NEWS.29
@@ -1906,6 +1906,13 @@ 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 'M-x 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.
 
diff --git a/lisp/emacs-lisp/loaddefs-gen.el b/lisp/emacs-lisp/loaddefs-gen.el
index 2a46fb7a022..5db9af21508 100644
--- a/lisp/emacs-lisp/loaddefs-gen.el
+++ b/lisp/emacs-lisp/loaddefs-gen.el
@@ -656,7 +656,20 @@ instead of just updating them with the new/changed 
autoloads."
             (write-region (point-min) (point-max) loaddefs-file nil 'silent)
             (byte-compile-info
              (file-relative-name loaddefs-file (car (ensure-list dir)))
-             t "GEN")))))))
+             t "GEN")))))
+
+    ;; If processing files without any autoloads, the above loop will
+    ;; not generate any files.  If the function was invoked with
+    ;; EXTRA-DATA, we want to ensure that even if no autoloads were
+    ;; found, that at least a file will have been generated containing
+    ;; the contents of EXTRA-DATA:
+    (when (and extra-data (not (file-exists-p output-file)))
+      (with-temp-buffer
+        (insert (loaddefs-generate--rubric output-file nil t))
+        (search-backward "\f")
+        (insert extra-data)
+        (ensure-empty-lines 1)
+        (write-region (point-min) (point-max) output-file nil 'silent)))))
 
 (defun loaddefs-generate--print-form (def)
   "Print DEF in a format that makes sense for version control."
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index 2892728ebd9..325c7b4e0a6 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -3740,7 +3740,7 @@ corresponding to the newer version."
       ;; ENTRY is (PKG-DESC [NAME VERSION STATUS DOC])
       (let ((pkg-desc (car entry))
             (status (aref (cadr entry) 2)))
-        (cond ((member status '("installed" "dependency" "unsigned" 
"external"))
+        (cond ((member status '("installed" "dependency" "unsigned" "external" 
"built-in"))
                (push pkg-desc installed))
               ((member status '("available" "new"))
                (setq available (package--append-to-alist pkg-desc 
available))))))
@@ -3751,6 +3751,8 @@ corresponding to the newer version."
         (and avail-pkg
              (version-list-< (package-desc-priority-version pkg-desc)
                              (package-desc-priority-version avail-pkg))
+             (xor (not package-install-upgrade-built-in)
+                  (package--active-built-in-p pkg-desc))
              (push (cons name avail-pkg) upgrades))))
     upgrades))
 
diff --git a/lisp/gnus/nntp.el b/lisp/gnus/nntp.el
index a36bce2dbfa..fb9d8fa53bf 100644
--- a/lisp/gnus/nntp.el
+++ b/lisp/gnus/nntp.el
@@ -314,7 +314,9 @@ retried once before actually displaying the error report."
     (when nntp-record-commands
       (nntp-record-command "*** CALLED nntp-report ***"))
 
-    (nnheader-report 'nntp args)))
+    (nnheader-report 'nntp args)
+
+    (apply #'error args)))
 
 (defsubst nntp-copy-to-buffer (buffer start end)
   "Copy string from unibyte current buffer to multibyte buffer."
diff --git a/lisp/subr.el b/lisp/subr.el
index a52abb38772..03d3324f3d8 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -4018,7 +4018,7 @@ same LABEL argument.
   "Helper function for `with-restriction', which see."
   (save-restriction
     (narrow-to-region start end)
-    (if label (internal--lock-narrowing label))
+    (if label (internal--label-restriction label))
     (funcall body)))
 
 (defmacro without-restriction (&rest rest)
@@ -4040,7 +4040,7 @@ are lifted.
 (defun internal--without-restriction (body &optional label)
   "Helper function for `without-restriction', which see."
   (save-restriction
-    (if label (internal--unlock-narrowing label))
+    (if label (internal--unlabel-restriction label))
     (widen)
     (funcall body)))
 
diff --git a/lisp/textmodes/texinfo.el b/lisp/textmodes/texinfo.el
index 7416c631c9f..bedf9ec92a5 100644
--- a/lisp/textmodes/texinfo.el
+++ b/lisp/textmodes/texinfo.el
@@ -409,6 +409,8 @@ REPORT-FN is the callback function."
 
 ;;; Texinfo mode
 
+(defvar fill-paragraph-separate nil)
+
 ;;;###autoload
 (define-derived-mode texinfo-mode text-mode "Texinfo"
   "Major mode for editing Texinfo files.
@@ -482,6 +484,10 @@ value of `texinfo-mode-hook'."
                      "\\)\\>"))
   (setq-local require-final-newline mode-require-final-newline)
   (setq-local indent-tabs-mode nil)
+  ;; This is used in 'texinfo--fill-paragraph'.
+  (setq-local fill-paragraph-separate (default-value 'paragraph-separate))
+  (setq-local paragraph-separate
+              (concat "@[a-zA-Z]*[ \n]\\|" paragraph-separate))
   (setq-local paragraph-start (concat "@[a-zA-Z]*[ \n]\\|"
                                      paragraph-start))
   (setq-local fill-paragraph-function 'texinfo--fill-paragraph)
@@ -536,7 +542,13 @@ value of `texinfo-mode-hook'."
 
 (defun texinfo--fill-paragraph (justify)
   "Function to fill a paragraph in `texinfo-mode'."
-  (let ((command-re "\\(@[a-zA-Z]+\\)[ \t\n]"))
+  (let ((command-re "\\(@[a-zA-Z]+\\)[ \t\n]")
+        ;; Kludge alert: we override paragraph-separate here because
+        ;; that is needed for filling @noindent and similar lines.
+        ;; The default Texinfo-specific paragraph-separate value,
+        ;; OTOH, is needed for auto-fill-mode, which doesn't call
+        ;; mode-specific functions.
+        (paragraph-separate fill-paragraph-separate))
     (catch 'no-fill
       (save-restriction
         ;; First check whether we're on a command line that can be
diff --git a/lisp/transient.el b/lisp/transient.el
index 9785e218b19..1d763c4ddeb 100644
--- a/lisp/transient.el
+++ b/lisp/transient.el
@@ -6,7 +6,7 @@
 ;; URL: https://github.com/magit/transient
 ;; Keywords: extensions
 
-;; Package-Version: 0.3.7.50
+;; Package-Version: 0.4.0
 ;; Package-Requires: ((emacs "26.1"))
 
 ;; SPDX-License-Identifier: GPL-3.0-or-later
@@ -3934,8 +3934,13 @@ search instead."
 (defun transient-isearch-abort ()
   "Like `isearch-abort' but adapted for `transient'."
   (interactive)
-  (condition-case nil (isearch-abort) (quit))
-  (transient--isearch-exit))
+  (let ((around (lambda (fn)
+                  (condition-case nil (funcall fn) (quit))
+                  (transient--isearch-exit))))
+    (advice-add 'isearch-cancel :around around)
+    (unwind-protect
+        (isearch-abort)
+      (advice-remove 'isearch-cancel around))))
 
 (defun transient--isearch-setup ()
   (select-window transient--window)
diff --git a/lisp/wid-edit.el b/lisp/wid-edit.el
index 8b035224c9b..cafd0ad0a4d 100644
--- a/lisp/wid-edit.el
+++ b/lisp/wid-edit.el
@@ -499,7 +499,7 @@ With CHECK-AFTER non-nil, considers also the content after 
point, if needed."
 
 (defmacro widget-specify-insert (&rest form)
   "Execute FORM without inheriting any text properties."
-   (declare (debug body))
+   (declare (debug (body)))
   `(save-restriction
     (let ((inhibit-read-only t)
          (inhibit-modification-hooks t))
diff --git a/src/buffer.c b/src/buffer.c
index 3e3be805a6d..399460c47da 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -2386,6 +2386,7 @@ Any narrowing restriction in effect (see 
`narrow-to-region') is removed,
 so the buffer is truly empty after this.  */)
   (void)
 {
+  labeled_restrictions_remove_in_current_buffer ();
   Fwiden ();
 
   del_range (BEG, Z);
diff --git a/src/callproc.c b/src/callproc.c
index 5e1e1a8cc0a..6f3d4fad9be 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -1113,6 +1113,7 @@ usage: (call-process-region START END PROGRAM &optional 
DELETE BUFFER DISPLAY &r
         {
           /* No need to save restrictions since we delete everything
              anyway.  */
+          labeled_restrictions_remove_in_current_buffer ();
           Fwiden ();
           del_range (BEG, Z);
         }
diff --git a/src/composite.c b/src/composite.c
index 34f369d167a..9332c1cb9a3 100644
--- a/src/composite.c
+++ b/src/composite.c
@@ -1077,7 +1077,7 @@ composition_compute_stop_pos (struct composition_it 
*cmp_it, ptrdiff_t charpos,
             with long lines, however, NL might be far away, so
             pretend that the buffer is smaller.  */
          if (current_buffer->long_line_optimizations_p)
-           endpos = get_closer_narrowed_begv (cmp_it->parent_it->w, charpos);
+           endpos = get_small_narrowing_begv (cmp_it->parent_it->w, charpos);
        }
     }
   cmp_it->id = -1;
@@ -1660,7 +1660,7 @@ find_automatic_composition (ptrdiff_t pos, ptrdiff_t 
limit, ptrdiff_t backlim,
        {
          /* In buffers with very long lines, this function becomes very
             slow.  Pretend that the buffer is narrowed to make it fast.  */
-         ptrdiff_t begv = get_closer_narrowed_begv (w, window_point (w));
+         ptrdiff_t begv = get_small_narrowing_begv (w, window_point (w));
          if (pos > begv)
            head = begv;
        }
diff --git a/src/dispextern.h b/src/dispextern.h
index 4dcab113ea2..ece128949f5 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -2334,21 +2334,20 @@ struct it
      with which display_string was called.  */
   ptrdiff_t end_charpos;
 
-  /* Alternate begin position of the buffer that may be used to
-     optimize display (see the SET_WITH_NARROWED_BEGV macro).  */
-  ptrdiff_t narrowed_begv;
-
-  /* Alternate end position of the buffer that may be used to
-     optimize display.  */
-  ptrdiff_t narrowed_zv;
-
-  /* Begin position of the buffer for the locked narrowing around
-     low-level hooks.  */
-  ptrdiff_t locked_narrowing_begv;
-
-  /* End position of the buffer for the locked narrowing around
-     low-level hooks.  */
-  ptrdiff_t locked_narrowing_zv;
+  /* Alternate begin and end positions of the buffer that are used to
+     optimize display of buffers with long lines.  These two fields
+     hold the return value of the 'get_medium_narrowing_begv' and
+     'get_medium_narrowing_zv' functions.  */
+  ptrdiff_t medium_narrowing_begv;
+  ptrdiff_t medium_narrowing_zv;
+
+  /* Alternate begin and end positions of the buffer that are used for
+     labeled narrowings around low-level hooks in buffers with long
+     lines.  These two fields hold the return value of the
+     'get_large_narrowing_begv' and 'get_large_narrowing_zv'
+     functions.  */
+  ptrdiff_t large_narrowing_begv;
+  ptrdiff_t large_narrowing_zv;
 
   /* C string to iterate over.  Non-null means get characters from
      this string, otherwise characters are read from current_buffer
@@ -3410,11 +3409,9 @@ void mark_window_display_accurate (Lisp_Object, bool);
 void redisplay_preserve_echo_area (int);
 void init_iterator (struct it *, struct window *, ptrdiff_t,
                     ptrdiff_t, struct glyph_row *, enum face_id);
-ptrdiff_t get_narrowed_begv (struct window *, ptrdiff_t);
-ptrdiff_t get_narrowed_zv (struct window *, ptrdiff_t);
-ptrdiff_t get_closer_narrowed_begv (struct window *, ptrdiff_t);
-ptrdiff_t get_locked_narrowing_begv (ptrdiff_t);
-ptrdiff_t get_locked_narrowing_zv (ptrdiff_t);
+ptrdiff_t get_small_narrowing_begv (struct window *, ptrdiff_t);
+ptrdiff_t get_large_narrowing_begv (ptrdiff_t);
+ptrdiff_t get_large_narrowing_zv (ptrdiff_t);
 void init_iterator_to_row_start (struct it *, struct window *,
                                  struct glyph_row *);
 void start_display (struct it *, struct window *, struct text_pos);
diff --git a/src/editfns.c b/src/editfns.c
index f83c5c7259b..d02cce4aef3 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -2653,182 +2653,203 @@ DEFUN ("delete-and-extract-region", 
Fdelete_and_extract_region,
   return del_range_1 (XFIXNUM (start), XFIXNUM (end), 1, 1);
 }
 
-/* Alist of buffers in which locked narrowing is used.  The car of
-   each list element is a buffer, the cdr is a list of triplets (tag
-   begv-marker zv-marker).  The last element of that list always uses
-   the (uninterned) Qoutermost_narrowing tag and records the narrowing
-   bounds that were set by the user and that are visible on display.
-   This alist is used internally by narrow-to-region, widen,
-   internal--lock-narrowing, internal--unlock-narrowing and
-   save-restriction.  For efficiency reasons, an alist is used instead
-   of a buffer-local variable: otherwise reset_outermost_narrowings,
-   which is called during each redisplay cycle, would have to loop
-   through all live buffers.  */
-static Lisp_Object narrowing_locks;
-
-/* Add BUF with its LOCKS in the narrowing_locks alist.  */
+/* Alist of buffers in which labeled restrictions are used.  The car
+   of each list element is a buffer, the cdr is a list of triplets
+   (label begv-marker zv-marker).  The last triplet of that list
+   always uses the (uninterned) Qoutermost_restriction label, and
+   records the restriction bounds that were current when the first
+   labeled restriction was entered (which may be a narrowing that was
+   set by the user and is visible on display).  This alist is used
+   internally by narrow-to-region, widen, internal--label-restriction,
+   internal--unlabel-restriction and save-restriction.  For efficiency
+   reasons, an alist is used instead of a buffer-local variable:
+   otherwise reset_outermost_restrictions, which is called during each
+   redisplay cycle, would have to loop through all live buffers.  */
+static Lisp_Object labeled_restrictions;
+
+/* Add BUF with its list of labeled RESTRICTIONS in the
+   labeled_restrictions alist.  */
 static void
-narrowing_locks_add (Lisp_Object buf, Lisp_Object locks)
+labeled_restrictions_add (Lisp_Object buf, Lisp_Object restrictions)
 {
-  narrowing_locks = nconc2 (list1 (list2 (buf, locks)), narrowing_locks);
+  labeled_restrictions = nconc2 (list1 (list2 (buf, restrictions)),
+                                labeled_restrictions);
 }
 
-/* Remove BUF and its locks from the narrowing_locks alist.  Do
-   nothing if BUF is not present in narrowing_locks.  */
+/* Remove BUF and its list of labeled restrictions from the
+   labeled_restrictions alist.  Do nothing if BUF is not present in
+   labeled_restrictions.  */
 static void
-narrowing_locks_remove (Lisp_Object buf)
+labeled_restrictions_remove (Lisp_Object buf)
 {
-  narrowing_locks = Fdelq (Fassoc (buf, narrowing_locks, Qnil),
-                          narrowing_locks);
+  labeled_restrictions = Fdelq (Fassoc (buf, labeled_restrictions, Qnil),
+                               labeled_restrictions);
 }
 
-/* Retrieve one of the BEGV/ZV bounds of a narrowing in BUF from the
-   narrowing_locks alist, as a pointer to a struct Lisp_Marker, or
-   NULL if BUF is not in narrowing_locks or is a killed buffer.  When
-   OUTERMOST is true, the bounds that were set by the user and that
-   are visible on display are returned.  Otherwise the innermost
-   locked narrowing bounds are returned.  */
-static struct Lisp_Marker *
-narrowing_lock_get_bound (Lisp_Object buf, bool begv, bool outermost)
+/* Retrieve one of the labeled restriction bounds in BUF from the
+   labeled_restrictions alist, as a marker, or return nil if BUF is
+   not in labeled_restrictions or is a killed buffer.  When OUTERMOST
+   is true, the restriction bounds that were current when the first
+   labeled restriction was entered are returned.  Otherwise the bounds
+   of the innermost labeled restriction are returned.  */
+static Lisp_Object
+labeled_restrictions_get_bound (Lisp_Object buf, bool begv, bool outermost)
 {
   if (NILP (Fbuffer_live_p (buf)))
-    return NULL;
-  Lisp_Object buffer_locks = assq_no_quit (buf, narrowing_locks);
-  if (NILP (buffer_locks))
-    return NULL;
-  buffer_locks = XCAR (XCDR (buffer_locks));
+    return Qnil;
+  Lisp_Object restrictions = assq_no_quit (buf, labeled_restrictions);
+  if (NILP (restrictions))
+    return Qnil;
+  restrictions = XCAR (XCDR (restrictions));
   Lisp_Object bounds
     = outermost
-      ? XCDR (assq_no_quit (Qoutermost_narrowing, buffer_locks))
-      : XCDR (XCAR (buffer_locks));
+      ? XCDR (assq_no_quit (Qoutermost_restriction, restrictions))
+      : XCDR (XCAR (restrictions));
   eassert (! NILP (bounds));
   Lisp_Object marker = begv ? XCAR (bounds) : XCAR (XCDR (bounds));
   eassert (EQ (Fmarker_buffer (marker), buf));
-  return XMARKER (marker);
+  return marker;
 }
 
-/* Retrieve the tag of the innermost narrowing in BUF.  Return nil if
-   BUF is not in narrowing_locks or is a killed buffer.  */
+/* Retrieve the label of the innermost labeled restriction in BUF.
+   Return nil if BUF is not in labeled_restrictions or is a killed
+   buffer.  */
 static Lisp_Object
-narrowing_lock_peek_tag (Lisp_Object buf)
+labeled_restrictions_peek_label (Lisp_Object buf)
 {
   if (NILP (Fbuffer_live_p (buf)))
     return Qnil;
-  Lisp_Object buffer_locks = assq_no_quit (buf, narrowing_locks);
-  if (NILP (buffer_locks))
+  Lisp_Object restrictions = assq_no_quit (buf, labeled_restrictions);
+  if (NILP (restrictions))
     return Qnil;
-  Lisp_Object tag = XCAR (XCAR (XCAR (XCDR (buffer_locks))));
-  eassert (! NILP (tag));
-  return tag;
+  Lisp_Object label = XCAR (XCAR (XCAR (XCDR (restrictions))));
+  eassert (! NILP (label));
+  return label;
 }
 
-/* Add a LOCK for BUF in the narrowing_locks alist.  */
+/* Add a labeled RESTRICTION for BUF in the labeled_restrictions
+   alist.  */
 static void
-narrowing_lock_push (Lisp_Object buf, Lisp_Object lock)
+labeled_restrictions_push (Lisp_Object buf, Lisp_Object restriction)
 {
-  Lisp_Object buffer_locks = assq_no_quit (buf, narrowing_locks);
-  if (NILP (buffer_locks))
-    narrowing_locks_add (buf, list1 (lock));
+  Lisp_Object restrictions = assq_no_quit (buf, labeled_restrictions);
+  if (NILP (restrictions))
+    labeled_restrictions_add (buf, list1 (restriction));
   else
-    XSETCDR (buffer_locks, list1 (nconc2 (list1 (lock),
-                                         XCAR (XCDR (buffer_locks)))));
+    XSETCDR (restrictions, list1 (nconc2 (list1 (restriction),
+                                         XCAR (XCDR (restrictions)))));
 }
 
-/* Remove the innermost lock in BUF from the narrowing_locks alist.
-   Do nothing if BUF is not present in narrowing_locks.  */
+/* Remove the innermost labeled restriction in BUF from the
+   labeled_restrictions alist.  Do nothing if BUF is not present in
+   labeled_restrictions.  */
 static void
-narrowing_lock_pop (Lisp_Object buf)
+labeled_restrictions_pop (Lisp_Object buf)
 {
-  Lisp_Object buffer_locks = assq_no_quit (buf, narrowing_locks);
-  if (NILP (buffer_locks))
+  Lisp_Object restrictions = assq_no_quit (buf, labeled_restrictions);
+  if (NILP (restrictions))
     return;
-  if (EQ (narrowing_lock_peek_tag (buf), Qoutermost_narrowing))
-    narrowing_locks_remove (buf);
+  if (EQ (labeled_restrictions_peek_label (buf), Qoutermost_restriction))
+    labeled_restrictions_remove (buf);
   else
-    XSETCDR (buffer_locks, list1 (XCDR (XCAR (XCDR (buffer_locks)))));
+    XSETCDR (restrictions, list1 (XCDR (XCAR (XCDR (restrictions)))));
+}
+
+/* Unconditionally remove all labeled restrictions in current_buffer.  */
+void
+labeled_restrictions_remove_in_current_buffer (void)
+{
+  labeled_restrictions_remove (Fcurrent_buffer ());
 }
 
 static void
-unwind_reset_outermost_narrowing (Lisp_Object buf)
+unwind_reset_outermost_restriction (Lisp_Object buf)
 {
-  struct Lisp_Marker *begv = narrowing_lock_get_bound (buf, true, false);
-  struct Lisp_Marker *zv = narrowing_lock_get_bound (buf, false, false);
-  if (begv != NULL && zv != NULL)
+  Lisp_Object begv = labeled_restrictions_get_bound (buf, true, false);
+  Lisp_Object zv = labeled_restrictions_get_bound (buf, false, false);
+  if (! NILP (begv) && ! NILP (zv))
     {
-      SET_BUF_BEGV_BOTH (XBUFFER (buf), begv->charpos, begv->bytepos);
-      SET_BUF_ZV_BOTH (XBUFFER (buf), zv->charpos, zv->bytepos);
+      SET_BUF_BEGV_BOTH (XBUFFER (buf),
+                        marker_position (begv), marker_byte_position (begv));
+      SET_BUF_ZV_BOTH (XBUFFER (buf),
+                      marker_position (zv), marker_byte_position (zv));
     }
   else
-    narrowing_locks_remove (buf);
+    labeled_restrictions_remove (buf);
 }
 
-/* Restore the narrowing bounds that were set by the user, and restore
-   the bounds of the locked narrowing upon return.
+/* Restore the restriction bounds that were current when the first
+   labeled restriction was entered, and restore the bounds of the
+   innermost labeled restriction upon return.
    In particular, this function is called when redisplay starts, so
    that if a Lisp function executed during redisplay calls (redisplay)
-   while a locked narrowing is in effect, the locked narrowing will
-   not be visible on display.
+   while labeled restrictions are in effect, these restrictions will
+   not become visible on display.
    See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=57207#140 and
    https://debbugs.gnu.org/cgi/bugreport.cgi?bug=57207#254 for example
    recipes that demonstrate why this is necessary.  */
 void
-reset_outermost_narrowings (void)
+reset_outermost_restrictions (void)
 {
   Lisp_Object val, buf;
-  for (val = narrowing_locks; CONSP (val); val = XCDR (val))
+  for (val = labeled_restrictions; CONSP (val); val = XCDR (val))
     {
       buf = XCAR (XCAR (val));
       eassert (BUFFERP (buf));
-      struct Lisp_Marker *begv = narrowing_lock_get_bound (buf, true, true);
-      struct Lisp_Marker *zv = narrowing_lock_get_bound (buf, false, true);
-      if (begv != NULL && zv != NULL)
+      Lisp_Object begv = labeled_restrictions_get_bound (buf, true, true);
+      Lisp_Object zv = labeled_restrictions_get_bound (buf, false, true);
+      if (! NILP (begv) && ! NILP (zv))
        {
-         SET_BUF_BEGV_BOTH (XBUFFER (buf), begv->charpos, begv->bytepos);
-         SET_BUF_ZV_BOTH (XBUFFER (buf), zv->charpos, zv->bytepos);
-         record_unwind_protect (unwind_reset_outermost_narrowing, buf);
+         SET_BUF_BEGV_BOTH (XBUFFER (buf),
+                            marker_position (begv), marker_byte_position 
(begv));
+         SET_BUF_ZV_BOTH (XBUFFER (buf),
+                          marker_position (zv), marker_byte_position (zv));
+         record_unwind_protect (unwind_reset_outermost_restriction, buf);
        }
       else
-       narrowing_locks_remove (buf);
+       labeled_restrictions_remove (buf);
     }
 }
 
-/* Helper functions to save and restore the narrowing locks of the
-   current buffer in Fsave_restriction.  */
+/* Helper functions to save and restore the labeled restrictions of
+   the current buffer in Fsave_restriction.  */
 static Lisp_Object
-narrowing_locks_save (void)
+labeled_restrictions_save (void)
 {
   Lisp_Object buf = Fcurrent_buffer ();
-  Lisp_Object locks = assq_no_quit (buf, narrowing_locks);
-  if (!NILP (locks))
-    locks = XCAR (XCDR (locks));
-  return Fcons (buf, Fcopy_sequence (locks));
+  Lisp_Object restrictions = assq_no_quit (buf, labeled_restrictions);
+  if (! NILP (restrictions))
+    restrictions = XCAR (XCDR (restrictions));
+  return Fcons (buf, Fcopy_sequence (restrictions));
 }
 
 static void
-narrowing_locks_restore (Lisp_Object buf_and_saved_locks)
+labeled_restrictions_restore (Lisp_Object buf_and_restrictions)
 {
-  Lisp_Object buf = XCAR (buf_and_saved_locks);
-  Lisp_Object saved_locks = XCDR (buf_and_saved_locks);
-  narrowing_locks_remove (buf);
-  if (!NILP (saved_locks))
-    narrowing_locks_add (buf, saved_locks);
+  Lisp_Object buf = XCAR (buf_and_restrictions);
+  Lisp_Object restrictions = XCDR (buf_and_restrictions);
+  labeled_restrictions_remove (buf);
+  if (! NILP (restrictions))
+    labeled_restrictions_add (buf, restrictions);
 }
 
 static void
-unwind_narrow_to_region_locked (Lisp_Object tag)
+unwind_labeled_narrow_to_region (Lisp_Object label)
 {
-  Finternal__unlock_narrowing (tag);
+  Finternal__unlabel_restriction (label);
   Fwiden ();
 }
 
-/* Narrow current_buffer to BEGV-ZV with a narrowing locked with TAG.  */
+/* Narrow current_buffer to BEGV-ZV with a restriction labeled with
+   LABEL.  */
 void
-narrow_to_region_locked (Lisp_Object begv, Lisp_Object zv, Lisp_Object tag)
+labeled_narrow_to_region (Lisp_Object begv, Lisp_Object zv,
+                         Lisp_Object label)
 {
   Fnarrow_to_region (begv, zv);
-  Finternal__lock_narrowing (tag);
+  Finternal__label_restriction (label);
   record_unwind_protect (restore_point_unwind, Fpoint_marker ());
-  record_unwind_protect (unwind_narrow_to_region_locked, tag);
+  record_unwind_protect (unwind_labeled_narrow_to_region, label);
 }
 
 DEFUN ("widen", Fwiden, Swiden, 0, 0, "",
@@ -2842,11 +2863,11 @@ To gain access to other portions of the buffer, use
 `without-restriction' with the same label.  */)
   (void)
 {
-  Fset (Qoutermost_narrowing, Qnil);
+  Fset (Qoutermost_restriction, Qnil);
   Lisp_Object buf = Fcurrent_buffer ();
-  Lisp_Object tag = narrowing_lock_peek_tag (buf);
+  Lisp_Object label = labeled_restrictions_peek_label (buf);
 
-  if (NILP (tag))
+  if (NILP (label))
     {
       if (BEG != BEGV || Z != ZV)
        current_buffer->clip_changed = 1;
@@ -2856,19 +2877,23 @@ To gain access to other portions of the buffer, use
     }
   else
     {
-      struct Lisp_Marker *begv = narrowing_lock_get_bound (buf, true, false);
-      struct Lisp_Marker *zv = narrowing_lock_get_bound (buf, false, false);
-      eassert (begv != NULL && zv != NULL);
-      if (begv->charpos != BEGV || zv->charpos != ZV)
+      Lisp_Object begv = labeled_restrictions_get_bound (buf, true, false);
+      Lisp_Object zv = labeled_restrictions_get_bound (buf, false, false);
+      eassert (! NILP (begv) && ! NILP (zv));
+      ptrdiff_t begv_charpos = marker_position (begv);
+      ptrdiff_t zv_charpos = marker_position (zv);
+      if (begv_charpos != BEGV || zv_charpos != ZV)
        current_buffer->clip_changed = 1;
-      SET_BUF_BEGV_BOTH (current_buffer, begv->charpos, begv->bytepos);
-      SET_BUF_ZV_BOTH (current_buffer, zv->charpos, zv->bytepos);
-      /* If the only remaining bounds in narrowing_locks for
+      SET_BUF_BEGV_BOTH (current_buffer,
+                        begv_charpos, marker_byte_position (begv));
+      SET_BUF_ZV_BOTH (current_buffer,
+                      zv_charpos, marker_byte_position (zv));
+      /* If the only remaining bounds in labeled_restrictions for
         current_buffer are the bounds that were set by the user, no
-        locked narrowing is in effect in current_buffer anymore:
-        remove it from the narrowing_locks alist.  */
-      if (EQ (tag, Qoutermost_narrowing))
-       narrowing_lock_pop (buf);
+        labeled restriction is in effect in current_buffer anymore:
+        remove it from the labeled_restrictions alist.  */
+      if (EQ (label, Qoutermost_restriction))
+       labeled_restrictions_pop (buf);
     }
   /* Changing the buffer bounds invalidates any recorded current column.  */
   invalidate_current_column ();
@@ -2905,25 +2930,27 @@ argument.  To gain access to other portions of the 
buffer, use
     args_out_of_range (start, end);
 
   Lisp_Object buf = Fcurrent_buffer ();
-  if (! NILP (narrowing_lock_peek_tag (buf)))
+  if (! NILP (labeled_restrictions_peek_label (buf)))
     {
-      struct Lisp_Marker *begv = narrowing_lock_get_bound (buf, true, false);
-      struct Lisp_Marker *zv = narrowing_lock_get_bound (buf, false, false);
-      eassert (begv != NULL && zv != NULL);
-      /* Limit the start and end positions to those of the locked
-        narrowing.  */
-      if (s < begv->charpos) s = begv->charpos;
-      if (s > zv->charpos) s = zv->charpos;
-      if (e < begv->charpos) e = begv->charpos;
-      if (e > zv->charpos) e = zv->charpos;
+      /* Limit the start and end positions to those of the innermost
+        labeled restriction.  */
+      Lisp_Object begv = labeled_restrictions_get_bound (buf, true, false);
+      Lisp_Object zv = labeled_restrictions_get_bound (buf, false, false);
+      eassert (! NILP (begv) && ! NILP (zv));
+      ptrdiff_t begv_charpos = marker_position (begv);
+      ptrdiff_t zv_charpos = marker_position (zv);
+      if (s < begv_charpos) s = begv_charpos;
+      if (s > zv_charpos) s = zv_charpos;
+      if (e < begv_charpos) e = begv_charpos;
+      if (e > zv_charpos) e = zv_charpos;
     }
 
   /* Record the accessible range of the buffer when narrow-to-region
-     is called, that is, before applying the narrowing.  It is used
-     only by internal--lock-narrowing.  */
-  Fset (Qoutermost_narrowing, list3 (Qoutermost_narrowing,
-                                    Fpoint_min_marker (),
-                                    Fpoint_max_marker ()));
+     is called, that is, before applying the narrowing.  That
+     information is used only by internal--label-restriction.  */
+  Fset (Qoutermost_restriction, list3 (Qoutermost_restriction,
+                                      Fpoint_min_marker (),
+                                      Fpoint_max_marker ()));
 
   if (BEGV != s || ZV != e)
     current_buffer->clip_changed = 1;
@@ -2940,38 +2967,38 @@ argument.  To gain access to other portions of the 
buffer, use
   return Qnil;
 }
 
-DEFUN ("internal--lock-narrowing", Finternal__lock_narrowing,
-       Sinternal__lock_narrowing, 1, 1, 0,
-       doc: /* Lock the current narrowing with LABEL.
+DEFUN ("internal--label-restriction", Finternal__label_restriction,
+       Sinternal__label_restriction, 1, 1, 0,
+       doc: /* Label the current restriction with LABEL.
 
 This is an internal function used by `with-restriction'.  */)
-  (Lisp_Object tag)
+  (Lisp_Object label)
 {
   Lisp_Object buf = Fcurrent_buffer ();
-  Lisp_Object outermost_narrowing
-    = buffer_local_value (Qoutermost_narrowing, buf);
-  /* If internal--lock-narrowing is ever called without being preceded
-     by narrow-to-region, do nothing.  */
-  if (NILP (outermost_narrowing))
+  Lisp_Object outermost_restriction
+    = buffer_local_value (Qoutermost_restriction, buf);
+  /* If internal--label-restriction is ever called without being
+     preceded by narrow-to-region, do nothing.  */
+  if (NILP (outermost_restriction))
     return Qnil;
-  if (NILP (narrowing_lock_peek_tag (buf)))
-    narrowing_lock_push (buf, outermost_narrowing);
-  narrowing_lock_push (buf, list3 (tag,
-                                  Fpoint_min_marker (),
-                                  Fpoint_max_marker ()));
+  if (NILP (labeled_restrictions_peek_label (buf)))
+    labeled_restrictions_push (buf, outermost_restriction);
+  labeled_restrictions_push (buf, list3 (label,
+                                        Fpoint_min_marker (),
+                                        Fpoint_max_marker ()));
   return Qnil;
 }
 
-DEFUN ("internal--unlock-narrowing", Finternal__unlock_narrowing,
-       Sinternal__unlock_narrowing, 1, 1, 0,
-       doc: /* Unlock a narrowing locked with LABEL.
+DEFUN ("internal--unlabel-restriction", Finternal__unlabel_restriction,
+       Sinternal__unlabel_restriction, 1, 1, 0,
+       doc: /* If the current restriction is labeled with LABEL, remove its 
label.
 
 This is an internal function used by `without-restriction'.  */)
-  (Lisp_Object tag)
+  (Lisp_Object label)
 {
   Lisp_Object buf = Fcurrent_buffer ();
-  if (EQ (narrowing_lock_peek_tag (buf), tag))
-    narrowing_lock_pop (buf);
+  if (EQ (labeled_restrictions_peek_label (buf), label))
+    labeled_restrictions_pop (buf);
   return Qnil;
 }
 
@@ -3071,15 +3098,15 @@ save_restriction_restore_1 (Lisp_Object data)
 Lisp_Object
 save_restriction_save (void)
 {
-  Lisp_Object restr = save_restriction_save_1 ();
-  Lisp_Object locks = narrowing_locks_save ();
-  return Fcons (restr, locks);
+  Lisp_Object restriction = save_restriction_save_1 ();
+  Lisp_Object labeled_restrictions = labeled_restrictions_save ();
+  return Fcons (restriction, labeled_restrictions);
 }
 
 void
 save_restriction_restore (Lisp_Object data)
 {
-  narrowing_locks_restore (XCDR (data));
+  labeled_restrictions_restore (XCDR (data));
   save_restriction_restore_1 (XCAR (data));
 }
 
@@ -4748,7 +4775,7 @@ syms_of_editfns (void)
   DEFSYM (Qwall, "wall");
   DEFSYM (Qpropertize, "propertize");
 
-  staticpro (&narrowing_locks);
+  staticpro (&labeled_restrictions);
 
   DEFVAR_LISP ("inhibit-field-text-motion", Vinhibit_field_text_motion,
               doc: /* Non-nil means text motion commands don't notice fields.  
*/);
@@ -4809,12 +4836,12 @@ This variable is experimental; email 
32252@debbugs.gnu.org if you need
 it to be non-nil.  */);
   binary_as_unsigned = false;
 
-  DEFVAR_LISP ("outermost-narrowing", Voutermost_narrowing,
+  DEFVAR_LISP ("outermost-restriction", Voutermost_restriction,
               doc: /* Outermost narrowing bounds, if any.  Internal use only.  
*/);
-  Voutermost_narrowing = Qnil;
-  Fmake_variable_buffer_local (Qoutermost_narrowing);
-  DEFSYM (Qoutermost_narrowing, "outermost-narrowing");
-  Funintern (Qoutermost_narrowing, Qnil);
+  Voutermost_restriction = Qnil;
+  Fmake_variable_buffer_local (Qoutermost_restriction);
+  DEFSYM (Qoutermost_restriction, "outermost-restriction");
+  Funintern (Qoutermost_restriction, Qnil);
 
   defsubr (&Spropertize);
   defsubr (&Schar_equal);
@@ -4907,8 +4934,8 @@ it to be non-nil.  */);
   defsubr (&Sdelete_and_extract_region);
   defsubr (&Swiden);
   defsubr (&Snarrow_to_region);
-  defsubr (&Sinternal__lock_narrowing);
-  defsubr (&Sinternal__unlock_narrowing);
+  defsubr (&Sinternal__label_restriction);
+  defsubr (&Sinternal__unlabel_restriction);
   defsubr (&Ssave_restriction);
   defsubr (&Stranspose_regions);
 }
diff --git a/src/fileio.c b/src/fileio.c
index b80f8d61de4..a364aa2ea33 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -5246,6 +5246,7 @@ write_region (Lisp_Object start, Lisp_Object end, 
Lisp_Object filename,
     }
 
   record_unwind_protect (save_restriction_restore, save_restriction_save ());
+  labeled_restrictions_remove_in_current_buffer ();
 
   /* Special kludge to simplify auto-saving.  */
   if (NILP (start))
diff --git a/src/ftcrfont.c b/src/ftcrfont.c
index c9a4de8137b..49564692b75 100644
--- a/src/ftcrfont.c
+++ b/src/ftcrfont.c
@@ -590,7 +590,6 @@ ftcrfont_draw (struct glyph_string *s,
                            GREEN_FROM_ULONG (col) / 255.0,
                            BLUE_FROM_ULONG (col) / 255.0);
 #endif
-      s->background_filled_p = 1;
       cairo_rectangle (cr, x, y - FONT_BASE (s->font),
                       s->width, FONT_HEIGHT (s->font));
       cairo_fill (cr);
diff --git a/src/indent.c b/src/indent.c
index 16285ce84e2..c3cbc49c81b 100644
--- a/src/indent.c
+++ b/src/indent.c
@@ -2065,6 +2065,7 @@ line_number_display_width (struct window *w, int *width, 
int *pixel_width)
        {
          record_unwind_protect (save_restriction_restore,
                                 save_restriction_save ());
+         labeled_restrictions_remove_in_current_buffer ();
          Fwiden ();
          saved_restriction = true;
        }
diff --git a/src/keyboard.c b/src/keyboard.c
index f7aa496bb81..b1ccf4acde4 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -318,6 +318,8 @@ static Lisp_Object command_loop (void);
 static void echo_now (void);
 static ptrdiff_t echo_length (void);
 
+static void safe_run_hooks_maybe_narrowed (Lisp_Object, struct window *);
+
 /* Incremented whenever a timer is run.  */
 unsigned timers_run;
 
@@ -1909,7 +1911,7 @@ safe_run_hooks (Lisp_Object hook)
   unbind_to (count, Qnil);
 }
 
-void
+static void
 safe_run_hooks_maybe_narrowed (Lisp_Object hook, struct window *w)
 {
   specpdl_ref count = SPECPDL_INDEX ();
@@ -1919,11 +1921,11 @@ safe_run_hooks_maybe_narrowed (Lisp_Object hook, struct 
window *w)
   if (current_buffer->long_line_optimizations_p
       && long_line_optimizations_region_size > 0)
     {
-      ptrdiff_t begv = get_locked_narrowing_begv (PT);
-      ptrdiff_t zv = get_locked_narrowing_zv (PT);
+      ptrdiff_t begv = get_large_narrowing_begv (PT);
+      ptrdiff_t zv = get_large_narrowing_zv (PT);
       if (begv != BEG || zv != Z)
-       narrow_to_region_locked (make_fixnum (begv), make_fixnum (zv),
-                                Qlong_line_optimizations_in_command_hooks);
+       labeled_narrow_to_region (make_fixnum (begv), make_fixnum (zv),
+                                 Qlong_line_optimizations_in_command_hooks);
     }
 
   run_hook_with_args (2, ((Lisp_Object []) {hook, hook}),
diff --git a/src/lisp.h b/src/lisp.h
index ab66109d5df..72d2c1a8f91 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4680,8 +4680,9 @@ extern void save_restriction_restore (Lisp_Object);
 extern Lisp_Object make_buffer_string (ptrdiff_t, ptrdiff_t, bool);
 extern Lisp_Object make_buffer_string_both (ptrdiff_t, ptrdiff_t, ptrdiff_t,
                                            ptrdiff_t, bool);
-extern void narrow_to_region_locked (Lisp_Object, Lisp_Object, Lisp_Object);
-extern void reset_outermost_narrowings (void);
+extern void labeled_narrow_to_region (Lisp_Object, Lisp_Object, Lisp_Object);
+extern void reset_outermost_restrictions (void);
+extern void labeled_restrictions_remove_in_current_buffer (void);
 extern void init_editfns (void);
 extern void syms_of_editfns (void);
 
@@ -4850,7 +4851,6 @@ extern bool detect_input_pending (void);
 extern bool detect_input_pending_ignore_squeezables (void);
 extern bool detect_input_pending_run_timers (bool);
 extern void safe_run_hooks (Lisp_Object);
-extern void safe_run_hooks_maybe_narrowed (Lisp_Object, struct window *);
 extern void safe_run_hooks_2 (Lisp_Object, Lisp_Object, Lisp_Object);
 extern void cmd_error_internal (Lisp_Object, const char *);
 extern Lisp_Object command_loop_2 (Lisp_Object);
diff --git a/src/lread.c b/src/lread.c
index 67cd7185d04..4f1d29d80b2 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -2255,6 +2255,7 @@ readevalloop (Lisp_Object readcharfun,
          record_unwind_protect_excursion ();
          /* Save ZV in it.  */
          record_unwind_protect (save_restriction_restore, 
save_restriction_save ());
+         labeled_restrictions_remove_in_current_buffer ();
          /* Those get unbound after we read one expression.  */
 
          /* Set point and ZV around stuff to be read.  */
diff --git a/src/xdisp.c b/src/xdisp.c
index 28f8e8128c5..982e1b3c103 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -3482,7 +3482,7 @@ init_iterator (struct it *it, struct window *w,
 
       /* This is set only when long_line_optimizations_p is non-zero
         for the current buffer.  */
-      it->narrowed_begv = 0;
+      it->medium_narrowing_begv = 0;
 
       /* Compute faces etc.  */
       reseat (it, it->current.pos, true);
@@ -3491,17 +3491,104 @@ init_iterator (struct it *it, struct window *w,
   CHECK_IT (it);
 }
 
-/* Compute a suitable alternate value for BEGV and ZV that may be used
-   temporarily to optimize display if the buffer in window W contains
-   long lines.  */
+/* How Emacs deals with long lines.
+
+   (1) When a buffer is about to be (re)displayed, 'redisplay_window'
+   detects, with a heuristic, whether it contains long lines.
+
+   This happens in 'redisplay_window' because it is only displaying
+   buffers with long lines that is problematic.  In other words, none
+   of the optimizations described below is ever used in buffers that
+   are never displayed.
+
+   This happens with a heuristic, which checks whether a buffer
+   contains long lines, each time its contents have changed "enough"
+   between two redisplay cycles, because a buffer without long lines
+   can become a buffer with long lines at any time, for example after
+   a yank command, or after a replace command, or while the output of
+   an external process is inserted in a buffer.
+
+   When Emacs has detected that a buffer contains long lines, the
+   buffer-local variable 'long_line_optimizations_p' (in 'struct
+   buffer') is set, and Emacs does not try to detect whether the
+   buffer does or does not contain long lines anymore.
+
+   What a long line is depends on the variable 'long-line-threshold',
+   whose default value is 50000 (characters).
+
+   (2) When a buffer with long lines is (re)displayed, the amount of
+   data that the display routines consider is, in a few well-chosen
+   places, limited with a temporary restriction, whose bounds are
+   calculated with the functions below.
+
+   (2.1) 'get_small_narrowing_begv' is used to create a restriction
+   which starts a few hundred characters before point.  The exact
+   number of characters depends on the width of the window in which
+   the buffer is displayed.
+
+   There is no corresponding 'get_small_narrowing_zv' function,
+   because it is not necessary to set the end limit of that
+   restriction.
+
+   This restriction is used in four places, namely:
+   'back_to_previous_line_start' and 'move_it_vertically_backward'
+   (with the 'SET_WITH_NARROWED_BEGV' macro), and in
+   'composition_compute_stop_pos' and 'find_automatic_composition' (in
+   a conditional statement depending on 'long_line_optimizations_p').
+
+   (2.2) 'get_medium_narrowing_begv' is used to create a restriction
+   which starts a few thousand characters before point.  The exact
+   number of characters depends on the size (width and height) of the
+   window in which the buffer is displayed.  For performance reasons,
+   the return value of that function is cached in 'struct it', in the
+   'medium_narrowing_begv' field.
+
+   The corresponding function 'get_medium_narrowing_zv' (and
+   'medium_narrowing_zv' field in 'struct it') is not used to set the
+   end limit of the restriction, which is again unnecessary, but to
+   determine, in 'reseat', whether the iterator has moved far enough
+   from its original position, and whether the start position of the
+   restriction must be computed anew.
+
+   This restriction is used in a single place:
+   'get_visually_first_element', with the 'SET_WITH_NARROWED_BEGV'
+   macro.
+
+   (2.3) 'get_large_narrowing_begv' and 'get_large_narrowing_zv' are
+   used to create a restriction which starts a few hundred thousand
+   characters before point and ends a few hundred thousand characters
+   after point.  The size of that restriction depends on the variable
+   'long-line-optimizations-region-size', whose default value is
+   500000 (characters); it can be adjusted by a few hundred characters
+   depending on 'long-line-optimizations-bol-search-limit', whose
+   default value is 128 (characters).
+
+   For performance reasons again, the return values of these functions
+   are stored in the 'large_narrowing_begv' and 'large_narrowing_zv'
+   fields in 'struct it'.
+
+   The restriction defined by these values is used around three
+   low-level hooks: around 'fontification-functions', in
+   'handle_fontified_prop', and around 'pre-command-hook' and
+   'post-command-hook', in 'safe_run_hooks_maybe_narrowed', which is
+   called in 'command_loop_1'.  These restrictions are set around
+   these hooks with 'labeled_narrow_to_region'; the restrictions are
+   labeled, and cannot be removed with a call to 'widen', but can be
+   removed with 'without-restriction' with a :label argument.
+*/
 
 static int
 get_narrowed_width (struct window *w)
 {
   /* In a character-only terminal, only one font size is used, so we
      can use a smaller factor.  */
-  int fact = EQ (Fterminal_live_p (Qnil), Qt) ? 2 : 3;
-  int width = window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS);
+  int fact = FRAME_WINDOW_P (XFRAME (w->frame)) ? 3 : 2;
+  /* If the window has no fringes (in a character-only terminal or in
+     a GUI frame without fringes), subtract 1 from the width for the
+     '\' line wrapping character.  */
+  int width = window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS)
+    - ((WINDOW_RIGHT_FRINGE_WIDTH (w) == 0
+       || WINDOW_LEFT_FRINGE_WIDTH (w) == 0) ? 1 : 0);
   return fact * max (1, width);
 }
 
@@ -3512,29 +3599,63 @@ get_narrowed_len (struct window *w)
   return get_narrowed_width (w) * max (1, height);
 }
 
-ptrdiff_t
-get_narrowed_begv (struct window *w, ptrdiff_t pos)
+static ptrdiff_t
+get_medium_narrowing_begv (struct window *w, ptrdiff_t pos)
 {
   int len = get_narrowed_len (w);
   return max ((pos / len - 1) * len, BEGV);
 }
 
-ptrdiff_t
-get_narrowed_zv (struct window *w, ptrdiff_t pos)
+static ptrdiff_t
+get_medium_narrowing_zv (struct window *w, ptrdiff_t pos)
 {
   int len = get_narrowed_len (w);
   return min ((pos / len + 1) * len, ZV);
 }
 
+/* Find the position of the last BOL before POS, unless it is too far
+   away.  The buffer portion in which the search occurs is gradually
+   enlarged: [POS-500..POS], [POS-5500..POS-500],
+   [POS-55500..POS-5500], and finally [POS-555500..POS-55500].  Return
+   BEGV-1 if no BOL was found in [POS-555500..POS].  */
+static ptrdiff_t
+get_nearby_bol_pos (ptrdiff_t pos)
+{
+  ptrdiff_t start, pos_bytepos, cur, next, found, bol = BEGV - 1, init_pos = 
pos;
+  int dist;
+  for (dist = 500; dist <= 500000; dist *= 10)
+    {
+      pos_bytepos = pos == BEGV ? BEGV_BYTE : CHAR_TO_BYTE (pos);
+      start = pos - dist < BEGV ? BEGV : pos - dist;
+      for (cur = start; cur < pos; cur = next)
+       {
+         next = find_newline1 (cur, CHAR_TO_BYTE (cur),
+                               pos, pos_bytepos,
+                               1, &found, NULL, false);
+         if (found)
+           bol = next;
+         else
+           break;
+       }
+      if (bol >= BEGV || start == BEGV)
+       break;
+      else
+       pos = pos - dist < BEGV ? BEGV : pos - dist;
+    }
+  eassert (bol <= init_pos);
+  return bol;
+}
+
 ptrdiff_t
-get_closer_narrowed_begv (struct window *w, ptrdiff_t pos)
+get_small_narrowing_begv (struct window *w, ptrdiff_t pos)
 {
   int len = get_narrowed_width (w);
-  return max ((pos / len - 1) * len, BEGV);
+  ptrdiff_t bol_pos = max (get_nearby_bol_pos (pos), BEGV);
+  return max (bol_pos + ((pos - bol_pos) / len - 1) * len, BEGV);
 }
 
 ptrdiff_t
-get_locked_narrowing_begv (ptrdiff_t pos)
+get_large_narrowing_begv (ptrdiff_t pos)
 {
   if (long_line_optimizations_region_size <= 0)
     return BEGV;
@@ -3552,7 +3673,7 @@ get_locked_narrowing_begv (ptrdiff_t pos)
 }
 
 ptrdiff_t
-get_locked_narrowing_zv (ptrdiff_t pos)
+get_large_narrowing_zv (ptrdiff_t pos)
 {
   if (long_line_optimizations_region_size <= 0)
     return ZV;
@@ -3571,7 +3692,7 @@ unwind_narrowed_begv (Lisp_Object point_min)
 
 #define SET_WITH_NARROWED_BEGV(IT,DST,EXPR,BV)                         \
   do {                                                                 \
-    if (IT->narrowed_begv)                                             \
+    if (IT->medium_narrowing_begv)                                     \
       {                                                                        
\
        specpdl_ref count = SPECPDL_INDEX ();                           \
        record_unwind_protect (unwind_narrowed_begv, Fpoint_min ());    \
@@ -4410,17 +4531,17 @@ handle_fontified_prop (struct it *it)
       if (current_buffer->long_line_optimizations_p
          && long_line_optimizations_region_size > 0)
        {
-         ptrdiff_t begv = it->locked_narrowing_begv;
-         ptrdiff_t zv = it->locked_narrowing_zv;
+         ptrdiff_t begv = it->large_narrowing_begv;
+         ptrdiff_t zv = it->large_narrowing_zv;
          ptrdiff_t charpos = IT_CHARPOS (*it);
          if (charpos < begv || charpos > zv)
            {
-             begv = get_locked_narrowing_begv (charpos);
-             zv = get_locked_narrowing_zv (charpos);
+             begv = get_large_narrowing_begv (charpos);
+             zv = get_large_narrowing_zv (charpos);
            }
          if (begv != BEG || zv != Z)
-           narrow_to_region_locked (make_fixnum (begv), make_fixnum (zv),
-                                    
Qlong_line_optimizations_in_fontification_functions);
+           labeled_narrow_to_region (make_fixnum (begv), make_fixnum (zv),
+                                     
Qlong_line_optimizations_in_fontification_functions);
        }
 
       /* Don't allow Lisp that runs from 'fontification-functions'
@@ -7055,7 +7176,7 @@ back_to_previous_line_start (struct it *it)
   dec_both (&cp, &bp);
   SET_WITH_NARROWED_BEGV (it, IT_CHARPOS (*it),
                          find_newline_no_quit (cp, bp, -1, &IT_BYTEPOS (*it)),
-                         get_closer_narrowed_begv (it->w, IT_CHARPOS (*it)));
+                         get_small_narrowing_begv (it->w, IT_CHARPOS (*it)));
 }
 
 /* Find in the current buffer the first display or overlay string
@@ -7359,7 +7480,7 @@ back_to_previous_visible_line_start (struct it *it)
   it->continuation_lines_width = 0;
 
   eassert (IT_CHARPOS (*it) >= BEGV);
-  eassert (it->narrowed_begv > 0 /* long-line optimizations: all bets off */
+  eassert (it->medium_narrowing_begv > 0 /* long-line optimizations: all bets 
off */
           || IT_CHARPOS (*it) == BEGV
           || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
   CHECK_IT (it);
@@ -7477,24 +7598,29 @@ reseat (struct it *it, struct text_pos pos, bool 
force_p)
 
   if (current_buffer->long_line_optimizations_p)
     {
-      if (!it->narrowed_begv)
+      if (!it->medium_narrowing_begv)
        {
-         it->narrowed_begv = get_narrowed_begv (it->w, window_point (it->w));
-         it->narrowed_zv = get_narrowed_zv (it->w, window_point (it->w));
-         it->locked_narrowing_begv
-           = get_locked_narrowing_begv (window_point (it->w));
-         it->locked_narrowing_zv
-           = get_locked_narrowing_zv (window_point (it->w));
+         it->medium_narrowing_begv
+           = get_medium_narrowing_begv (it->w, window_point (it->w));
+         it->medium_narrowing_zv
+           = get_medium_narrowing_zv (it->w, window_point (it->w));
+         it->large_narrowing_begv
+           = get_large_narrowing_begv (window_point (it->w));
+         it->large_narrowing_zv
+           = get_large_narrowing_zv (window_point (it->w));
        }
-      else if ((pos.charpos < it->narrowed_begv || pos.charpos > 
it->narrowed_zv)
+      else if ((pos.charpos < it->medium_narrowing_begv
+               || pos.charpos > it->medium_narrowing_zv)
                && (!redisplaying_p || it->line_wrap == TRUNCATE))
        {
-         it->narrowed_begv = get_narrowed_begv (it->w, pos.charpos);
-         it->narrowed_zv = get_narrowed_zv (it->w, pos.charpos);
-         it->locked_narrowing_begv
-           = get_locked_narrowing_begv (window_point (it->w));
-         it->locked_narrowing_zv
-           = get_locked_narrowing_zv (window_point (it->w));
+         it->medium_narrowing_begv
+           = get_medium_narrowing_begv (it->w, pos.charpos);
+         it->medium_narrowing_zv
+           = get_medium_narrowing_zv (it->w, pos.charpos);
+         it->large_narrowing_begv
+           = get_large_narrowing_begv (window_point (it->w));
+         it->large_narrowing_zv
+           = get_large_narrowing_zv (window_point (it->w));
        }
     }
 
@@ -8804,7 +8930,7 @@ get_visually_first_element (struct it *it)
   SET_WITH_NARROWED_BEGV (it, bob,
                          string_p ? 0 :
                          IT_CHARPOS (*it) < BEGV ? obegv : BEGV,
-                         it->narrowed_begv);
+                         it->medium_narrowing_begv);
 
   if (STRINGP (it->string))
     {
@@ -8848,7 +8974,7 @@ get_visually_first_element (struct it *it)
                                find_newline_no_quit (IT_CHARPOS (*it),
                                                      IT_BYTEPOS (*it), -1,
                                                      &it->bidi_it.bytepos),
-                               it->narrowed_begv);
+                               it->medium_narrowing_begv);
       bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
       do
        {
@@ -10737,7 +10863,7 @@ move_it_vertically_backward (struct it *it, int dy)
          dec_both (&cp, &bp);
          SET_WITH_NARROWED_BEGV (it, cp,
                                  find_newline_no_quit (cp, bp, -1, NULL),
-                                 get_closer_narrowed_begv (it->w, IT_CHARPOS 
(*it)));
+                                 get_small_narrowing_begv (it->w, IT_CHARPOS 
(*it)));
          move_it_to (it, cp, -1, -1, -1, MOVE_TO_POS);
        }
       bidi_unshelve_cache (it3data, true);
@@ -16417,7 +16543,7 @@ redisplay_internal (void)
   FOR_EACH_FRAME (tail, frame)
     XFRAME (frame)->already_hscrolled_p = false;
 
-  reset_outermost_narrowings ();
+  reset_outermost_restrictions ();
 
  retry:
   /* Remember the currently selected window.  */
@@ -24144,6 +24270,7 @@ display_count_lines_logically (ptrdiff_t start_byte, 
ptrdiff_t limit_byte,
   ptrdiff_t val;
   specpdl_ref pdl_count = SPECPDL_INDEX ();
   record_unwind_protect (save_restriction_restore, save_restriction_save ());
+  labeled_restrictions_remove_in_current_buffer ();
   Fwiden ();
   val = display_count_lines (start_byte, limit_byte, count, byte_pos_ptr);
   unbind_to (pdl_count, Qnil);



reply via email to

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