diff options
| author | Gregory Heytings | 2023-02-13 11:44:37 +0100 |
|---|---|---|
| committer | Gregory Heytings | 2023-02-13 11:44:37 +0100 |
| commit | b948d0d7efe4c73a34485238d6a4e1bb5f0cac9e (patch) | |
| tree | 3c1fc837f7094c21d1d35f1e66c657020908ea7f | |
| parent | cc30422825a5acf460d026bfe912b327b70dedcf (diff) | |
| parent | dcb2379a463678bdadd05ee39d61e7da84c71c5e (diff) | |
| download | emacs-b948d0d7efe4c73a34485238d6a4e1bb5f0cac9e.tar.gz emacs-b948d0d7efe4c73a34485238d6a4e1bb5f0cac9e.zip | |
Merge branch 'scratch/fix-locked-narrowing'
| -rw-r--r-- | doc/lispref/commands.texi | 6 | ||||
| -rw-r--r-- | doc/lispref/display.texi | 10 | ||||
| -rw-r--r-- | doc/lispref/positions.texi | 82 | ||||
| -rw-r--r-- | etc/NEWS | 17 | ||||
| -rw-r--r-- | lisp/emacs-lisp/bytecomp.el | 2 | ||||
| -rw-r--r-- | lisp/subr.el | 47 | ||||
| -rw-r--r-- | src/buffer.c | 47 | ||||
| -rw-r--r-- | src/bytecode.c | 2 | ||||
| -rw-r--r-- | src/comp.c | 2 | ||||
| -rw-r--r-- | src/editfns.c | 98 | ||||
| -rw-r--r-- | src/keyboard.c | 31 | ||||
| -rw-r--r-- | src/lisp.h | 2 | ||||
| -rw-r--r-- | src/xdisp.c | 27 | ||||
| -rw-r--r-- | test/src/buffer-tests.el | 106 |
14 files changed, 341 insertions, 138 deletions
diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi index dc78adc4520..9723c279a45 100644 --- a/doc/lispref/commands.texi +++ b/doc/lispref/commands.texi | |||
| @@ -99,6 +99,12 @@ is removed from the hook. | |||
| 99 | emacs, The GNU Emacs Manual}) runs these two hooks just as a keyboard | 99 | emacs, The GNU Emacs Manual}) runs these two hooks just as a keyboard |
| 100 | command does. | 100 | command does. |
| 101 | 101 | ||
| 102 | Note that, when the buffer text includes very long lines, these two | ||
| 103 | hooks are called as if they were in a @code{with-narrowing} form | ||
| 104 | (@pxref{Narrowing}), with a | ||
| 105 | @code{long-line-optimizations-in-command-hooks} label and with the | ||
| 106 | buffer narrowed to a portion around point. | ||
| 107 | |||
| 102 | @node Defining Commands | 108 | @node Defining Commands |
| 103 | @section Defining Commands | 109 | @section Defining Commands |
| 104 | @cindex defining commands | 110 | @cindex defining commands |
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index c5374e1481a..f0ca7440c60 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi | |||
| @@ -3501,11 +3501,11 @@ function finishes are the ones that really matter. | |||
| 3501 | For efficiency, we recommend writing these functions so that they | 3501 | For efficiency, we recommend writing these functions so that they |
| 3502 | usually assign faces to around 400 to 600 characters at each call. | 3502 | usually assign faces to around 400 to 600 characters at each call. |
| 3503 | 3503 | ||
| 3504 | When the buffer text includes very long lines, these functions are | 3504 | Note that, when the buffer text includes very long lines, these |
| 3505 | called with the buffer narrowed to a relatively small region around | 3505 | functions are called as if they were in a @code{with-narrowing} form |
| 3506 | @var{pos}, and with narrowing locked, so the functions cannot use | 3506 | (@pxref{Narrowing}), with a |
| 3507 | @code{widen} to gain access to the rest of the buffer. | 3507 | @code{long-line-optimizations-in-fontification-functions} label and |
| 3508 | @xref{Narrowing}. | 3508 | with the buffer narrowed to a portion around @var{pos}. |
| 3509 | @end defvar | 3509 | @end defvar |
| 3510 | 3510 | ||
| 3511 | @node Basic Faces | 3511 | @node Basic Faces |
diff --git a/doc/lispref/positions.texi b/doc/lispref/positions.texi index f3824436246..bad83e1be2d 100644 --- a/doc/lispref/positions.texi +++ b/doc/lispref/positions.texi | |||
| @@ -1037,11 +1037,13 @@ positions. | |||
| 1037 | In an interactive call, @var{start} and @var{end} are set to the bounds | 1037 | In an interactive call, @var{start} and @var{end} are set to the bounds |
| 1038 | of the current region (point and the mark, with the smallest first). | 1038 | of the current region (point and the mark, with the smallest first). |
| 1039 | 1039 | ||
| 1040 | Note that, in rare circumstances, Emacs may decide to leave, for | 1040 | However, when the narrowing has been set by @code{with-narrowing} with |
| 1041 | performance reasons, the accessible portion of the buffer unchanged | 1041 | a label argument (see below), @code{narrow-to-region} can be used only |
| 1042 | after a call to @code{narrow-to-region}. This can happen when a Lisp | 1042 | within the limits of that narrowing. If @var{start} or @var{end} are |
| 1043 | program is called via low-level hooks, such as | 1043 | outside these limits, the corresponding limit set by |
| 1044 | @code{jit-lock-functions}, @code{post-command-hook}, etc. | 1044 | @code{with-narrowing} is used instead. To gain access to other |
| 1045 | portions of the buffer, use @code{without-narrowing} with the same | ||
| 1046 | label. | ||
| 1045 | @end deffn | 1047 | @end deffn |
| 1046 | 1048 | ||
| 1047 | @deffn Command narrow-to-page &optional move-count | 1049 | @deffn Command narrow-to-page &optional move-count |
| @@ -1065,13 +1067,13 @@ It is equivalent to the following expression: | |||
| 1065 | @example | 1067 | @example |
| 1066 | (narrow-to-region 1 (1+ (buffer-size))) | 1068 | (narrow-to-region 1 (1+ (buffer-size))) |
| 1067 | @end example | 1069 | @end example |
| 1068 | @end deffn | ||
| 1069 | 1070 | ||
| 1070 | Note that, in rare circumstances, Emacs may decide to leave, for | 1071 | However, when a narrowing has been set by @code{with-narrowing} with a |
| 1071 | performance reasons, the accessible portion of the buffer unchanged | 1072 | label argument (see below), the limits set by @code{with-narrowing} |
| 1072 | after a call to @code{widen}. This can happen when a Lisp program is | 1073 | are restored, instead of canceling the narrowing. To gain access to |
| 1073 | called via low-level hooks, such as @code{jit-lock-functions}, | 1074 | other portions of the buffer, use @code{without-narrowing} with the |
| 1074 | @code{post-command-hook}, etc. | 1075 | same label. |
| 1076 | @end deffn | ||
| 1075 | 1077 | ||
| 1076 | @defun buffer-narrowed-p | 1078 | @defun buffer-narrowed-p |
| 1077 | This function returns non-@code{nil} if the buffer is narrowed, and | 1079 | This function returns non-@code{nil} if the buffer is narrowed, and |
| @@ -1086,6 +1088,9 @@ in effect. The state of narrowing is restored even in the event of an | |||
| 1086 | abnormal exit via @code{throw} or error (@pxref{Nonlocal Exits}). | 1088 | abnormal exit via @code{throw} or error (@pxref{Nonlocal Exits}). |
| 1087 | Therefore, this construct is a clean way to narrow a buffer temporarily. | 1089 | Therefore, this construct is a clean way to narrow a buffer temporarily. |
| 1088 | 1090 | ||
| 1091 | This construct also saves and restores the narrowings that were set by | ||
| 1092 | @code{with-narrowing} with a label argument (see below). | ||
| 1093 | |||
| 1089 | The value returned by @code{save-restriction} is that returned by the | 1094 | The value returned by @code{save-restriction} is that returned by the |
| 1090 | last form in @var{body}, or @code{nil} if no body forms were given. | 1095 | last form in @var{body}, or @code{nil} if no body forms were given. |
| 1091 | 1096 | ||
| @@ -1135,3 +1140,58 @@ This is the contents of foo@point{} | |||
| 1135 | @end group | 1140 | @end group |
| 1136 | @end example | 1141 | @end example |
| 1137 | @end defspec | 1142 | @end defspec |
| 1143 | |||
| 1144 | @defspec with-narrowing start end [:label label] body | ||
| 1145 | This special form saves the current bounds of the accessible portion | ||
| 1146 | of the buffer, sets the accessible portion to start at @var{start} and | ||
| 1147 | end at @var{end}, evaluates the @var{body} forms, and restores the | ||
| 1148 | saved bounds. In that case it is equivalent to | ||
| 1149 | |||
| 1150 | @example | ||
| 1151 | (save-restriction | ||
| 1152 | (narrow-to-region start end) | ||
| 1153 | body) | ||
| 1154 | @end example | ||
| 1155 | |||
| 1156 | When the optional @var{label} symbol argument is present however, the | ||
| 1157 | narrowing is labeled. A labeled narrowing differs from a non-labeled | ||
| 1158 | one in several ways: | ||
| 1159 | |||
| 1160 | @itemize @bullet | ||
| 1161 | @item | ||
| 1162 | During the evaluation of the @var{body} form, @code{narrow-to-region} | ||
| 1163 | and @code{widen} can be used only within the @var{start} and @var{end} | ||
| 1164 | limits. | ||
| 1165 | |||
| 1166 | @item | ||
| 1167 | To lift the restriction introduced by @code{with-narrowing} and gain | ||
| 1168 | access to other portions of the buffer, use @code{without-narrowing} | ||
| 1169 | with the same @var{label} argument. (Another way to gain access to | ||
| 1170 | other portions of the buffer is to use an indirect buffer | ||
| 1171 | (@pxref{Indirect Buffers}).) | ||
| 1172 | |||
| 1173 | @item | ||
| 1174 | Labeled narrowings can be nested. | ||
| 1175 | |||
| 1176 | @item | ||
| 1177 | Labeled narrowings can only be used in Lisp programs: they are never | ||
| 1178 | visible on display, and never interfere with narrowings set by the | ||
| 1179 | user. | ||
| 1180 | @end itemize | ||
| 1181 | @end defspec | ||
| 1182 | |||
| 1183 | @defspec without-narrowing [:label label] body | ||
| 1184 | This special form saves the current bounds of the accessible portion | ||
| 1185 | of the buffer, widens the buffer, evaluates the @var{body} forms, and | ||
| 1186 | restores the saved bounds. In that case it is equivalent to | ||
| 1187 | |||
| 1188 | @example | ||
| 1189 | (save-restriction | ||
| 1190 | (widen) | ||
| 1191 | body) | ||
| 1192 | @end example | ||
| 1193 | |||
| 1194 | When the optional @var{label} argument is present however, the | ||
| 1195 | narrowing set by @code{with-narrowing} with the same @var{label} | ||
| 1196 | argument is lifted. | ||
| 1197 | @end defspec | ||
| @@ -615,8 +615,13 @@ with 'C-x x t', or try disabling all known slow minor modes with | |||
| 615 | and the major mode with 'M-x so-long-mode', or visit the file with | 615 | and the major mode with 'M-x so-long-mode', or visit the file with |
| 616 | 'M-x find-file-literally' instead of the usual 'C-x C-f'. | 616 | 'M-x find-file-literally' instead of the usual 'C-x C-f'. |
| 617 | 617 | ||
| 618 | Note that the display optimizations in these cases may cause the | 618 | In buffers in which these display optimizations are in effect, the |
| 619 | buffer to be occasionally mis-fontified. | 619 | 'fontification-functions', 'pre-command-hook' and 'post-command-hook' |
| 620 | hooks are executed on a narrowed portion of the buffer, whose size is | ||
| 621 | controlled by the options 'long-line-optimizations-region-size' and | ||
| 622 | 'long-line-optimizations-bol-search-limit', as if they were in a | ||
| 623 | 'with-narrowing' form. This may, in particular, cause occasional | ||
| 624 | mis-fontifications in these buffers. | ||
| 620 | 625 | ||
| 621 | The new function 'long-line-optimizations-p' returns non-nil when | 626 | The new function 'long-line-optimizations-p' returns non-nil when |
| 622 | these optimizations are in effect in the current buffer. | 627 | these optimizations are in effect in the current buffer. |
| @@ -3814,6 +3819,14 @@ TIMEOUT is the idle time after which to deactivate the transient map. | |||
| 3814 | The default timeout value can be defined by the new variable | 3819 | The default timeout value can be defined by the new variable |
| 3815 | 'set-transient-map-timeout'. | 3820 | 'set-transient-map-timeout'. |
| 3816 | 3821 | ||
| 3822 | +++ | ||
| 3823 | ** New forms 'with-narrowing' and 'without-narrowing'. | ||
| 3824 | These forms can be used as enhanced alternatives to the | ||
| 3825 | 'save-restriction' form combined with, respectively, | ||
| 3826 | 'narrow-to-region' and 'widen'. They also accept an optional label | ||
| 3827 | argument, with which labeled narrowings can be created and lifted. | ||
| 3828 | See the "(elisp) Narrowing" node for details. | ||
| 3829 | |||
| 3817 | ** Connection Local Variables | 3830 | ** Connection Local Variables |
| 3818 | 3831 | ||
| 3819 | +++ | 3832 | +++ |
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 5df1205869c..c6cda6b588a 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el | |||
| @@ -4900,7 +4900,7 @@ binding slots have been popped." | |||
| 4900 | (defun byte-compile-save-restriction (form) | 4900 | (defun byte-compile-save-restriction (form) |
| 4901 | (byte-compile-out 'byte-save-restriction 0) | 4901 | (byte-compile-out 'byte-save-restriction 0) |
| 4902 | (byte-compile-body-do-effect (cdr form)) | 4902 | (byte-compile-body-do-effect (cdr form)) |
| 4903 | (byte-compile-out 'byte-unbind 1)) | 4903 | (byte-compile-out 'byte-unbind 2)) |
| 4904 | 4904 | ||
| 4905 | (defun byte-compile-save-current-buffer (form) | 4905 | (defun byte-compile-save-current-buffer (form) |
| 4906 | (byte-compile-out 'byte-save-current-buffer 0) | 4906 | (byte-compile-out 'byte-save-current-buffer 0) |
diff --git a/lisp/subr.el b/lisp/subr.el index 9e6388987df..58a8e85b61d 100644 --- a/lisp/subr.el +++ b/lisp/subr.el | |||
| @@ -3946,25 +3946,46 @@ See also `locate-user-emacs-file'.") | |||
| 3946 | 3946 | ||
| 3947 | The current restrictions, if any, are restored upon return. | 3947 | The current restrictions, if any, are restored upon return. |
| 3948 | 3948 | ||
| 3949 | With the optional :locked TAG argument, inside BODY, | 3949 | When the optional :label LABEL argument is present, in which |
| 3950 | `narrow-to-region' and `widen' can be used only within the START | 3950 | LABEL is a symbol, inside BODY, `narrow-to-region' and `widen' |
| 3951 | and END limits, unless the restrictions are unlocked by calling | 3951 | can be used only within the START and END limits. To gain access |
| 3952 | `narrowing-unlock' with TAG. See `narrowing-lock' for a more | 3952 | to other portions of the buffer, use `without-narrowing' with the |
| 3953 | detailed description. | 3953 | same LABEL argument. |
| 3954 | 3954 | ||
| 3955 | \(fn START END [:locked TAG] BODY)" | 3955 | \(fn START END [:label LABEL] BODY)" |
| 3956 | (if (eq (car rest) :locked) | 3956 | (if (eq (car rest) :label) |
| 3957 | `(internal--with-narrowing ,start ,end (lambda () ,@(cddr rest)) | 3957 | `(internal--with-narrowing ,start ,end (lambda () ,@(cddr rest)) |
| 3958 | ,(cadr rest)) | 3958 | ,(cadr rest)) |
| 3959 | `(internal--with-narrowing ,start ,end (lambda () ,@rest)))) | 3959 | `(internal--with-narrowing ,start ,end (lambda () ,@rest)))) |
| 3960 | 3960 | ||
| 3961 | (defun internal--with-narrowing (start end body &optional tag) | 3961 | (defun internal--with-narrowing (start end body &optional label) |
| 3962 | "Helper function for `with-narrowing', which see." | 3962 | "Helper function for `with-narrowing', which see." |
| 3963 | (save-restriction | 3963 | (save-restriction |
| 3964 | (progn | 3964 | (narrow-to-region start end) |
| 3965 | (narrow-to-region start end) | 3965 | (if label (internal--lock-narrowing label)) |
| 3966 | (if tag (narrowing-lock tag)) | 3966 | (funcall body))) |
| 3967 | (funcall body)))) | 3967 | |
| 3968 | (defmacro without-narrowing (&rest rest) | ||
| 3969 | "Execute BODY without restrictions. | ||
| 3970 | |||
| 3971 | The current restrictions, if any, are restored upon return. | ||
| 3972 | |||
| 3973 | When the optional :label LABEL argument is present, the | ||
| 3974 | restrictions set by `with-narrowing' with the same LABEL argument | ||
| 3975 | are lifted. | ||
| 3976 | |||
| 3977 | \(fn [:label LABEL] BODY)" | ||
| 3978 | (if (eq (car rest) :label) | ||
| 3979 | `(internal--without-narrowing (lambda () ,@(cddr rest)) | ||
| 3980 | ,(cadr rest)) | ||
| 3981 | `(internal--without-narrowing (lambda () ,@rest)))) | ||
| 3982 | |||
| 3983 | (defun internal--without-narrowing (body &optional label) | ||
| 3984 | "Helper function for `without-narrowing', which see." | ||
| 3985 | (save-restriction | ||
| 3986 | (if label (internal--unlock-narrowing label)) | ||
| 3987 | (widen) | ||
| 3988 | (funcall body))) | ||
| 3968 | 3989 | ||
| 3969 | (defun find-tag-default-bounds () | 3990 | (defun find-tag-default-bounds () |
| 3970 | "Determine the boundaries of the default tag, based on text at point. | 3991 | "Determine the boundaries of the default tag, based on text at point. |
diff --git a/src/buffer.c b/src/buffer.c index 38648519ba0..755061d0dee 100644 --- a/src/buffer.c +++ b/src/buffer.c | |||
| @@ -5916,40 +5916,41 @@ If nil, these display shortcuts will always remain disabled. | |||
| 5916 | There is no reason to change that value except for debugging purposes. */); | 5916 | There is no reason to change that value except for debugging purposes. */); |
| 5917 | XSETFASTINT (Vlong_line_threshold, 50000); | 5917 | XSETFASTINT (Vlong_line_threshold, 50000); |
| 5918 | 5918 | ||
| 5919 | DEFVAR_INT ("long-line-locked-narrowing-region-size", | 5919 | DEFVAR_INT ("long-line-optimizations-region-size", |
| 5920 | long_line_locked_narrowing_region_size, | 5920 | long_line_optimizations_region_size, |
| 5921 | doc: /* Region size for locked narrowing in buffers with long lines. | 5921 | doc: /* Region size for narrowing in buffers with long lines. |
| 5922 | 5922 | ||
| 5923 | This variable has effect only in buffers which contain one or more | 5923 | This variable has effect only in buffers in which |
| 5924 | lines whose length is above `long-line-threshold', which see. For | 5924 | `long-line-optimizations-p' is non-nil. For performance reasons, in |
| 5925 | performance reasons, in such buffers, low-level hooks such as | 5925 | such buffers, the `fontification-functions', `pre-command-hook' and |
| 5926 | `fontification-functions' or `post-command-hook' are executed on a | 5926 | `post-command-hook' hooks are executed on a narrowed buffer around |
| 5927 | narrowed buffer, with a narrowing locked with `narrowing-lock'. This | 5927 | point, as if they were called in a `with-narrowing' form with a label. |
| 5928 | variable specifies the size of the narrowed region around point. | 5928 | This variable specifies the size of the narrowed region around point. |
| 5929 | 5929 | ||
| 5930 | To disable that narrowing, set this variable to 0. | 5930 | To disable that narrowing, set this variable to 0. |
| 5931 | 5931 | ||
| 5932 | See also `long-line-locked-narrowing-bol-search-limit'. | 5932 | See also `long-line-optimizations-bol-search-limit'. |
| 5933 | 5933 | ||
| 5934 | There is no reason to change that value except for debugging purposes. */); | 5934 | There is no reason to change that value except for debugging purposes. */); |
| 5935 | long_line_locked_narrowing_region_size = 500000; | 5935 | long_line_optimizations_region_size = 500000; |
| 5936 | 5936 | ||
| 5937 | DEFVAR_INT ("long-line-locked-narrowing-bol-search-limit", | 5937 | DEFVAR_INT ("long-line-optimizations-bol-search-limit", |
| 5938 | long_line_locked_narrowing_bol_search_limit, | 5938 | long_line_optimizations_bol_search_limit, |
| 5939 | doc: /* Limit for beginning of line search in buffers with long lines. | 5939 | doc: /* Limit for beginning of line search in buffers with long lines. |
| 5940 | 5940 | ||
| 5941 | This variable has effect only in buffers which contain one or more | 5941 | This variable has effect only in buffers in which |
| 5942 | lines whose length is above `long-line-threshold', which see. For | 5942 | `long-line-optimizations-p' is non-nil. For performance reasons, in |
| 5943 | performance reasons, in such buffers, low-level hooks such as | 5943 | such buffers, the `fontification-functions', `pre-command-hook' and |
| 5944 | `fontification-functions' or `post-command-hook' are executed on a | 5944 | `post-command-hook' hooks are executed on a narrowed buffer around |
| 5945 | narrowed buffer, with a narrowing locked with `narrowing-lock'. The | 5945 | point, as if they were called in a `with-narrowing' form with a label. |
| 5946 | variable `long-line-locked-narrowing-region-size' specifies the size | 5946 | The variable `long-line-optimizations-region-size' specifies the |
| 5947 | of the narrowed region around point. This variable, which should be a | 5947 | size of the narrowed region around point. This variable, which should |
| 5948 | small integer, specifies the number of characters by which that region | 5948 | be a small integer, specifies the number of characters by which that |
| 5949 | can be extended backwards to make it start at the beginning of a line. | 5949 | region can be extended backwards to make it start at the beginning of |
| 5950 | a line. | ||
| 5950 | 5951 | ||
| 5951 | There is no reason to change that value except for debugging purposes. */); | 5952 | There is no reason to change that value except for debugging purposes. */); |
| 5952 | long_line_locked_narrowing_bol_search_limit = 128; | 5953 | long_line_optimizations_bol_search_limit = 128; |
| 5953 | 5954 | ||
| 5954 | DEFVAR_INT ("large-hscroll-threshold", large_hscroll_threshold, | 5955 | DEFVAR_INT ("large-hscroll-threshold", large_hscroll_threshold, |
| 5955 | doc: /* Horizontal scroll of truncated lines above which to use redisplay shortcuts. | 5956 | doc: /* Horizontal scroll of truncated lines above which to use redisplay shortcuts. |
diff --git a/src/bytecode.c b/src/bytecode.c index 124348e5b35..8e214560f30 100644 --- a/src/bytecode.c +++ b/src/bytecode.c | |||
| @@ -942,6 +942,8 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, | |||
| 942 | CASE (Bsave_restriction): | 942 | CASE (Bsave_restriction): |
| 943 | record_unwind_protect (save_restriction_restore, | 943 | record_unwind_protect (save_restriction_restore, |
| 944 | save_restriction_save ()); | 944 | save_restriction_save ()); |
| 945 | record_unwind_protect (narrowing_locks_restore, | ||
| 946 | narrowing_locks_save ()); | ||
| 945 | NEXT; | 947 | NEXT; |
| 946 | 948 | ||
| 947 | CASE (Bcatch): /* Obsolete since 25. */ | 949 | CASE (Bcatch): /* Obsolete since 25. */ |
diff --git a/src/comp.c b/src/comp.c index 10cf7962ba1..0e2dfd3913b 100644 --- a/src/comp.c +++ b/src/comp.c | |||
| @@ -5063,6 +5063,8 @@ helper_save_restriction (void) | |||
| 5063 | { | 5063 | { |
| 5064 | record_unwind_protect (save_restriction_restore, | 5064 | record_unwind_protect (save_restriction_restore, |
| 5065 | save_restriction_save ()); | 5065 | save_restriction_save ()); |
| 5066 | record_unwind_protect (narrowing_locks_restore, | ||
| 5067 | narrowing_locks_save ()); | ||
| 5066 | } | 5068 | } |
| 5067 | 5069 | ||
| 5068 | static bool | 5070 | static bool |
diff --git a/src/editfns.c b/src/editfns.c index 78d2c73ecbf..f9879662168 100644 --- a/src/editfns.c +++ b/src/editfns.c | |||
| @@ -2659,7 +2659,11 @@ DEFUN ("delete-and-extract-region", Fdelete_and_extract_region, | |||
| 2659 | the (uninterned) Qoutermost_narrowing tag and records the narrowing | 2659 | the (uninterned) Qoutermost_narrowing tag and records the narrowing |
| 2660 | bounds that were set by the user and that are visible on display. | 2660 | bounds that were set by the user and that are visible on display. |
| 2661 | This alist is used internally by narrow-to-region, widen, | 2661 | This alist is used internally by narrow-to-region, widen, |
| 2662 | narrowing-lock, narrowing-unlock and save-restriction. */ | 2662 | internal--lock-narrowing, internal--unlock-narrowing and |
| 2663 | save-restriction. For efficiency reasons, an alist is used instead | ||
| 2664 | of a buffer-local variable: otherwise reset_outermost_narrowings, | ||
| 2665 | which is called during each redisplay cycle, would have to loop | ||
| 2666 | through all live buffers. */ | ||
| 2663 | static Lisp_Object narrowing_locks; | 2667 | static Lisp_Object narrowing_locks; |
| 2664 | 2668 | ||
| 2665 | /* Add BUF with its LOCKS in the narrowing_locks alist. */ | 2669 | /* Add BUF with its LOCKS in the narrowing_locks alist. */ |
| @@ -2763,7 +2767,10 @@ unwind_reset_outermost_narrowing (Lisp_Object buf) | |||
| 2763 | In particular, this function is called when redisplay starts, so | 2767 | In particular, this function is called when redisplay starts, so |
| 2764 | that if a Lisp function executed during redisplay calls (redisplay) | 2768 | that if a Lisp function executed during redisplay calls (redisplay) |
| 2765 | while a locked narrowing is in effect, the locked narrowing will | 2769 | while a locked narrowing is in effect, the locked narrowing will |
| 2766 | not be visible on display. */ | 2770 | not be visible on display. |
| 2771 | See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=57207#140 and | ||
| 2772 | https://debbugs.gnu.org/cgi/bugreport.cgi?bug=57207#254 for example | ||
| 2773 | recipes that demonstrate why this is necessary. */ | ||
| 2767 | void | 2774 | void |
| 2768 | reset_outermost_narrowings (void) | 2775 | reset_outermost_narrowings (void) |
| 2769 | { | 2776 | { |
| @@ -2787,32 +2794,30 @@ reset_outermost_narrowings (void) | |||
| 2787 | 2794 | ||
| 2788 | /* Helper functions to save and restore the narrowing locks of the | 2795 | /* Helper functions to save and restore the narrowing locks of the |
| 2789 | current buffer in Fsave_restriction. */ | 2796 | current buffer in Fsave_restriction. */ |
| 2790 | static Lisp_Object | 2797 | Lisp_Object |
| 2791 | narrowing_locks_save (void) | 2798 | narrowing_locks_save (void) |
| 2792 | { | 2799 | { |
| 2793 | Lisp_Object buf = Fcurrent_buffer (); | 2800 | Lisp_Object buf = Fcurrent_buffer (); |
| 2794 | Lisp_Object locks = assq_no_quit (buf, narrowing_locks); | 2801 | Lisp_Object locks = assq_no_quit (buf, narrowing_locks); |
| 2795 | if (NILP (locks)) | 2802 | if (!NILP (locks)) |
| 2796 | return Qnil; | 2803 | locks = XCAR (XCDR (locks)); |
| 2797 | locks = XCAR (XCDR (locks)); | ||
| 2798 | return Fcons (buf, Fcopy_sequence (locks)); | 2804 | return Fcons (buf, Fcopy_sequence (locks)); |
| 2799 | } | 2805 | } |
| 2800 | 2806 | ||
| 2801 | static void | 2807 | void |
| 2802 | narrowing_locks_restore (Lisp_Object buf_and_saved_locks) | 2808 | narrowing_locks_restore (Lisp_Object buf_and_saved_locks) |
| 2803 | { | 2809 | { |
| 2804 | if (NILP (buf_and_saved_locks)) | ||
| 2805 | return; | ||
| 2806 | Lisp_Object buf = XCAR (buf_and_saved_locks); | 2810 | Lisp_Object buf = XCAR (buf_and_saved_locks); |
| 2807 | Lisp_Object saved_locks = XCDR (buf_and_saved_locks); | 2811 | Lisp_Object saved_locks = XCDR (buf_and_saved_locks); |
| 2808 | narrowing_locks_remove (buf); | 2812 | narrowing_locks_remove (buf); |
| 2809 | narrowing_locks_add (buf, saved_locks); | 2813 | if (!NILP (saved_locks)) |
| 2814 | narrowing_locks_add (buf, saved_locks); | ||
| 2810 | } | 2815 | } |
| 2811 | 2816 | ||
| 2812 | static void | 2817 | static void |
| 2813 | unwind_narrow_to_region_locked (Lisp_Object tag) | 2818 | unwind_narrow_to_region_locked (Lisp_Object tag) |
| 2814 | { | 2819 | { |
| 2815 | Fnarrowing_unlock (tag); | 2820 | Finternal__unlock_narrowing (tag); |
| 2816 | Fwiden (); | 2821 | Fwiden (); |
| 2817 | } | 2822 | } |
| 2818 | 2823 | ||
| @@ -2821,7 +2826,7 @@ void | |||
| 2821 | narrow_to_region_locked (Lisp_Object begv, Lisp_Object zv, Lisp_Object tag) | 2826 | narrow_to_region_locked (Lisp_Object begv, Lisp_Object zv, Lisp_Object tag) |
| 2822 | { | 2827 | { |
| 2823 | Fnarrow_to_region (begv, zv); | 2828 | Fnarrow_to_region (begv, zv); |
| 2824 | Fnarrowing_lock (tag); | 2829 | Finternal__lock_narrowing (tag); |
| 2825 | record_unwind_protect (restore_point_unwind, Fpoint_marker ()); | 2830 | record_unwind_protect (restore_point_unwind, Fpoint_marker ()); |
| 2826 | record_unwind_protect (unwind_narrow_to_region_locked, tag); | 2831 | record_unwind_protect (unwind_narrow_to_region_locked, tag); |
| 2827 | } | 2832 | } |
| @@ -2829,10 +2834,12 @@ narrow_to_region_locked (Lisp_Object begv, Lisp_Object zv, Lisp_Object tag) | |||
| 2829 | DEFUN ("widen", Fwiden, Swiden, 0, 0, "", | 2834 | DEFUN ("widen", Fwiden, Swiden, 0, 0, "", |
| 2830 | doc: /* Remove restrictions (narrowing) from current buffer. | 2835 | doc: /* Remove restrictions (narrowing) from current buffer. |
| 2831 | 2836 | ||
| 2832 | This allows the buffer's full text to be seen and edited, unless | 2837 | This allows the buffer's full text to be seen and edited. |
| 2833 | restrictions have been locked with `narrowing-lock', which see, in | 2838 | |
| 2834 | which case the narrowing that was current when `narrowing-lock' was | 2839 | However, when restrictions have been set by `with-narrowing' with a |
| 2835 | called is restored. */) | 2840 | label, `widen' restores the narrowing limits set by `with-narrowing'. |
| 2841 | To gain access to other portions of the buffer, use | ||
| 2842 | `without-narrowing' with the same label. */) | ||
| 2836 | (void) | 2843 | (void) |
| 2837 | { | 2844 | { |
| 2838 | Fset (Qoutermost_narrowing, Qnil); | 2845 | Fset (Qoutermost_narrowing, Qnil); |
| @@ -2879,11 +2886,12 @@ When calling from Lisp, pass two arguments START and END: | |||
| 2879 | positions (integers or markers) bounding the text that should | 2886 | positions (integers or markers) bounding the text that should |
| 2880 | remain visible. | 2887 | remain visible. |
| 2881 | 2888 | ||
| 2882 | When restrictions have been locked with `narrowing-lock', which see, | 2889 | However, when restrictions have been set by `with-narrowing' with a |
| 2883 | `narrow-to-region' can be used only within the limits of the | 2890 | label, `narrow-to-region' can be used only within the limits of these |
| 2884 | restrictions that were current when `narrowing-lock' was called. If | 2891 | restrictions. If the START or END arguments are outside these limits, |
| 2885 | the START or END arguments are outside these limits, the corresponding | 2892 | the corresponding limit set by `with-narrowing' is used instead of the |
| 2886 | limit of the locked restriction is used instead of the argument. */) | 2893 | argument. To gain access to other portions of the buffer, use |
| 2894 | `without-narrowing' with the same label. */) | ||
| 2887 | (Lisp_Object start, Lisp_Object end) | 2895 | (Lisp_Object start, Lisp_Object end) |
| 2888 | { | 2896 | { |
| 2889 | EMACS_INT s = fix_position (start), e = fix_position (end); | 2897 | EMACS_INT s = fix_position (start), e = fix_position (end); |
| @@ -2912,7 +2920,7 @@ limit of the locked restriction is used instead of the argument. */) | |||
| 2912 | 2920 | ||
| 2913 | /* Record the accessible range of the buffer when narrow-to-region | 2921 | /* Record the accessible range of the buffer when narrow-to-region |
| 2914 | is called, that is, before applying the narrowing. It is used | 2922 | is called, that is, before applying the narrowing. It is used |
| 2915 | only by narrowing-lock. */ | 2923 | only by internal--lock-narrowing. */ |
| 2916 | Fset (Qoutermost_narrowing, list3 (Qoutermost_narrowing, | 2924 | Fset (Qoutermost_narrowing, list3 (Qoutermost_narrowing, |
| 2917 | Fpoint_min_marker (), | 2925 | Fpoint_min_marker (), |
| 2918 | Fpoint_max_marker ())); | 2926 | Fpoint_max_marker ())); |
| @@ -2932,31 +2940,18 @@ limit of the locked restriction is used instead of the argument. */) | |||
| 2932 | return Qnil; | 2940 | return Qnil; |
| 2933 | } | 2941 | } |
| 2934 | 2942 | ||
| 2935 | DEFUN ("narrowing-lock", Fnarrowing_lock, Snarrowing_lock, 1, 1, 0, | 2943 | DEFUN ("internal--lock-narrowing", Finternal__lock_narrowing, |
| 2936 | doc: /* Lock the current narrowing with TAG. | 2944 | Sinternal__lock_narrowing, 1, 1, 0, |
| 2937 | 2945 | doc: /* Lock the current narrowing with LABEL. | |
| 2938 | When restrictions are locked, `narrow-to-region' and `widen' can be | ||
| 2939 | used only within the limits of the restrictions that were current when | ||
| 2940 | `narrowing-lock' was called, unless the lock is removed by calling | ||
| 2941 | `narrowing-unlock' with TAG. | ||
| 2942 | |||
| 2943 | Locking restrictions should be used sparingly, after carefully | ||
| 2944 | considering the potential adverse effects on the code that will be | ||
| 2945 | executed within locked restrictions. It is typically meant to be used | ||
| 2946 | around portions of code that would become too slow, and make Emacs | ||
| 2947 | unresponsive, if they were executed in a large buffer. For example, | ||
| 2948 | restrictions are locked by Emacs around low-level hooks such as | ||
| 2949 | `fontification-functions' or `post-command-hook'. | ||
| 2950 | 2946 | ||
| 2951 | Locked restrictions are never visible on display, and can therefore | 2947 | This is an internal function used by `with-narrowing'. */) |
| 2952 | not be used as a stronger variant of normal restrictions. */) | ||
| 2953 | (Lisp_Object tag) | 2948 | (Lisp_Object tag) |
| 2954 | { | 2949 | { |
| 2955 | Lisp_Object buf = Fcurrent_buffer (); | 2950 | Lisp_Object buf = Fcurrent_buffer (); |
| 2956 | Lisp_Object outermost_narrowing | 2951 | Lisp_Object outermost_narrowing |
| 2957 | = buffer_local_value (Qoutermost_narrowing, buf); | 2952 | = buffer_local_value (Qoutermost_narrowing, buf); |
| 2958 | /* If narrowing-lock is called without being preceded by | 2953 | /* If internal--lock-narrowing is ever called without being preceded |
| 2959 | narrow-to-region, do nothing. */ | 2954 | by narrow-to-region, do nothing. */ |
| 2960 | if (NILP (outermost_narrowing)) | 2955 | if (NILP (outermost_narrowing)) |
| 2961 | return Qnil; | 2956 | return Qnil; |
| 2962 | if (NILP (narrowing_lock_peek_tag (buf))) | 2957 | if (NILP (narrowing_lock_peek_tag (buf))) |
| @@ -2967,16 +2962,11 @@ not be used as a stronger variant of normal restrictions. */) | |||
| 2967 | return Qnil; | 2962 | return Qnil; |
| 2968 | } | 2963 | } |
| 2969 | 2964 | ||
| 2970 | DEFUN ("narrowing-unlock", Fnarrowing_unlock, Snarrowing_unlock, 1, 1, 0, | 2965 | DEFUN ("internal--unlock-narrowing", Finternal__unlock_narrowing, |
| 2971 | doc: /* Unlock a narrowing locked with (narrowing-lock TAG). | 2966 | Sinternal__unlock_narrowing, 1, 1, 0, |
| 2967 | doc: /* Unlock a narrowing locked with LABEL. | ||
| 2972 | 2968 | ||
| 2973 | Unlocking restrictions locked with `narrowing-lock' should be used | 2969 | This is an internal function used by `without-narrowing'. */) |
| 2974 | sparingly, after carefully considering the reasons why restrictions | ||
| 2975 | were locked. Restrictions are typically locked around portions of | ||
| 2976 | code that would become too slow, and make Emacs unresponsive, if they | ||
| 2977 | were executed in a large buffer. For example, restrictions are locked | ||
| 2978 | by Emacs around low-level hooks such as `fontification-functions' or | ||
| 2979 | `post-command-hook'. */) | ||
| 2980 | (Lisp_Object tag) | 2970 | (Lisp_Object tag) |
| 2981 | { | 2971 | { |
| 2982 | Lisp_Object buf = Fcurrent_buffer (); | 2972 | Lisp_Object buf = Fcurrent_buffer (); |
| @@ -3083,8 +3073,8 @@ DEFUN ("save-restriction", Fsave_restriction, Ssave_restriction, 0, UNEVALLED, 0 | |||
| 3083 | The buffer's restrictions make parts of the beginning and end invisible. | 3073 | The buffer's restrictions make parts of the beginning and end invisible. |
| 3084 | \(They are set up with `narrow-to-region' and eliminated with `widen'.) | 3074 | \(They are set up with `narrow-to-region' and eliminated with `widen'.) |
| 3085 | This special form, `save-restriction', saves the current buffer's | 3075 | This special form, `save-restriction', saves the current buffer's |
| 3086 | restrictions, as well as their locks if they have been locked with | 3076 | restrictions, including those that were set by `with-narrowing' with a |
| 3087 | `narrowing-lock', when it is entered, and restores them when it is exited. | 3077 | label argument, when it is entered, and restores them when it is exited. |
| 3088 | So any `narrow-to-region' within BODY lasts only until the end of the form. | 3078 | So any `narrow-to-region' within BODY lasts only until the end of the form. |
| 3089 | The old restrictions settings are restored even in case of abnormal exit | 3079 | The old restrictions settings are restored even in case of abnormal exit |
| 3090 | \(throw or error). | 3080 | \(throw or error). |
| @@ -4903,8 +4893,8 @@ it to be non-nil. */); | |||
| 4903 | defsubr (&Sdelete_and_extract_region); | 4893 | defsubr (&Sdelete_and_extract_region); |
| 4904 | defsubr (&Swiden); | 4894 | defsubr (&Swiden); |
| 4905 | defsubr (&Snarrow_to_region); | 4895 | defsubr (&Snarrow_to_region); |
| 4906 | defsubr (&Snarrowing_lock); | 4896 | defsubr (&Sinternal__lock_narrowing); |
| 4907 | defsubr (&Snarrowing_unlock); | 4897 | defsubr (&Sinternal__unlock_narrowing); |
| 4908 | defsubr (&Ssave_restriction); | 4898 | defsubr (&Ssave_restriction); |
| 4909 | defsubr (&Stranspose_regions); | 4899 | defsubr (&Stranspose_regions); |
| 4910 | } | 4900 | } |
diff --git a/src/keyboard.c b/src/keyboard.c index 6f0f075e54e..1d0b907bd8e 100644 --- a/src/keyboard.c +++ b/src/keyboard.c | |||
| @@ -1910,12 +1910,13 @@ safe_run_hooks_maybe_narrowed (Lisp_Object hook, struct window *w) | |||
| 1910 | specbind (Qinhibit_quit, Qt); | 1910 | specbind (Qinhibit_quit, Qt); |
| 1911 | 1911 | ||
| 1912 | if (current_buffer->long_line_optimizations_p | 1912 | if (current_buffer->long_line_optimizations_p |
| 1913 | && long_line_locked_narrowing_region_size > 0) | 1913 | && long_line_optimizations_region_size > 0) |
| 1914 | { | 1914 | { |
| 1915 | ptrdiff_t begv = get_locked_narrowing_begv (PT); | 1915 | ptrdiff_t begv = get_locked_narrowing_begv (PT); |
| 1916 | ptrdiff_t zv = get_locked_narrowing_zv (PT); | 1916 | ptrdiff_t zv = get_locked_narrowing_zv (PT); |
| 1917 | if (begv != BEG || zv != Z) | 1917 | if (begv != BEG || zv != Z) |
| 1918 | narrow_to_region_locked (make_fixnum (begv), make_fixnum (zv), hook); | 1918 | narrow_to_region_locked (make_fixnum (begv), make_fixnum (zv), |
| 1919 | Qlong_line_optimizations_in_command_hooks); | ||
| 1919 | } | 1920 | } |
| 1920 | 1921 | ||
| 1921 | run_hook_with_args (2, ((Lisp_Object []) {hook, hook}), | 1922 | run_hook_with_args (2, ((Lisp_Object []) {hook, hook}), |
| @@ -12168,6 +12169,8 @@ syms_of_keyboard (void) | |||
| 12168 | /* Hooks to run before and after each command. */ | 12169 | /* Hooks to run before and after each command. */ |
| 12169 | DEFSYM (Qpre_command_hook, "pre-command-hook"); | 12170 | DEFSYM (Qpre_command_hook, "pre-command-hook"); |
| 12170 | DEFSYM (Qpost_command_hook, "post-command-hook"); | 12171 | DEFSYM (Qpost_command_hook, "post-command-hook"); |
| 12172 | DEFSYM (Qlong_line_optimizations_in_command_hooks, | ||
| 12173 | "long-line-optimizations-in-command-hooks"); | ||
| 12171 | 12174 | ||
| 12172 | /* Hook run after the region is selected. */ | 12175 | /* Hook run after the region is selected. */ |
| 12173 | DEFSYM (Qpost_select_region_hook, "post-select-region-hook"); | 12176 | DEFSYM (Qpost_select_region_hook, "post-select-region-hook"); |
| @@ -12728,13 +12731,11 @@ If an unhandled error happens in running this hook, the function in | |||
| 12728 | which the error occurred is unconditionally removed, since otherwise | 12731 | which the error occurred is unconditionally removed, since otherwise |
| 12729 | the error might happen repeatedly and make Emacs nonfunctional. | 12732 | the error might happen repeatedly and make Emacs nonfunctional. |
| 12730 | 12733 | ||
| 12731 | Note that, when the current buffer contains one or more lines whose | 12734 | Note that, when `long-line-optimizations-p' is non-nil in the buffer, |
| 12732 | length is above `long-line-threshold', these hook functions are called | 12735 | these functions are called as if they were in a `with-narrowing' form, |
| 12733 | with the buffer narrowed to a small portion around point (whose size | 12736 | with a `long-line-optimizations-in-command-hooks' label and with the |
| 12734 | is specified by `long-line-locked-narrowing-region-size'), and the | 12737 | buffer narrowed to a portion around point whose size is specified by |
| 12735 | narrowing is locked (see `narrowing-lock'), so that these hook | 12738 | `long-line-optimizations-region-size'. |
| 12736 | functions cannot use `widen' to gain access to other portions of | ||
| 12737 | buffer text. | ||
| 12738 | 12739 | ||
| 12739 | See also `post-command-hook'. */); | 12740 | See also `post-command-hook'. */); |
| 12740 | Vpre_command_hook = Qnil; | 12741 | Vpre_command_hook = Qnil; |
| @@ -12750,13 +12751,11 @@ It is a bad idea to use this hook for expensive processing. If | |||
| 12750 | unavoidable, wrap your code in `(while-no-input (redisplay) CODE)' to | 12751 | unavoidable, wrap your code in `(while-no-input (redisplay) CODE)' to |
| 12751 | avoid making Emacs unresponsive while the user types. | 12752 | avoid making Emacs unresponsive while the user types. |
| 12752 | 12753 | ||
| 12753 | Note that, when the current buffer contains one or more lines whose | 12754 | Note that, when `long-line-optimizations-p' is non-nil in the buffer, |
| 12754 | length is above `long-line-threshold', these hook functions are called | 12755 | these functions are called as if they were in a `with-narrowing' form, |
| 12755 | with the buffer narrowed to a small portion around point (whose size | 12756 | with a `long-line-optimizations-in-command-hooks' label and with the |
| 12756 | is specified by `long-line-locked-narrowing-region-size'), and the | 12757 | buffer narrowed to a portion around point whose size is specified by |
| 12757 | narrowing is locked (see `narrowing-lock'), so that these hook | 12758 | `long-line-optimizations-region-size'. |
| 12758 | functions cannot use `widen' to gain access to other portions of | ||
| 12759 | buffer text. | ||
| 12760 | 12759 | ||
| 12761 | See also `pre-command-hook'. */); | 12760 | See also `pre-command-hook'. */); |
| 12762 | Vpost_command_hook = Qnil; | 12761 | Vpost_command_hook = Qnil; |
diff --git a/src/lisp.h b/src/lisp.h index 1276285e2f2..93197d38176 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -4684,6 +4684,8 @@ extern void save_excursion_save (union specbinding *); | |||
| 4684 | extern void save_excursion_restore (Lisp_Object, Lisp_Object); | 4684 | extern void save_excursion_restore (Lisp_Object, Lisp_Object); |
| 4685 | extern Lisp_Object save_restriction_save (void); | 4685 | extern Lisp_Object save_restriction_save (void); |
| 4686 | extern void save_restriction_restore (Lisp_Object); | 4686 | extern void save_restriction_restore (Lisp_Object); |
| 4687 | extern Lisp_Object narrowing_locks_save (void); | ||
| 4688 | extern void narrowing_locks_restore (Lisp_Object); | ||
| 4687 | extern Lisp_Object make_buffer_string (ptrdiff_t, ptrdiff_t, bool); | 4689 | extern Lisp_Object make_buffer_string (ptrdiff_t, ptrdiff_t, bool); |
| 4688 | extern Lisp_Object make_buffer_string_both (ptrdiff_t, ptrdiff_t, ptrdiff_t, | 4690 | extern Lisp_Object make_buffer_string_both (ptrdiff_t, ptrdiff_t, ptrdiff_t, |
| 4689 | ptrdiff_t, bool); | 4691 | ptrdiff_t, bool); |
diff --git a/src/xdisp.c b/src/xdisp.c index a19c9908616..1450b869d20 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -3536,11 +3536,11 @@ get_closer_narrowed_begv (struct window *w, ptrdiff_t pos) | |||
| 3536 | ptrdiff_t | 3536 | ptrdiff_t |
| 3537 | get_locked_narrowing_begv (ptrdiff_t pos) | 3537 | get_locked_narrowing_begv (ptrdiff_t pos) |
| 3538 | { | 3538 | { |
| 3539 | if (long_line_locked_narrowing_region_size <= 0) | 3539 | if (long_line_optimizations_region_size <= 0) |
| 3540 | return BEGV; | 3540 | return BEGV; |
| 3541 | int len = long_line_locked_narrowing_region_size / 2; | 3541 | int len = long_line_optimizations_region_size / 2; |
| 3542 | int begv = max (pos - len, BEGV); | 3542 | int begv = max (pos - len, BEGV); |
| 3543 | int limit = long_line_locked_narrowing_bol_search_limit; | 3543 | int limit = long_line_optimizations_bol_search_limit; |
| 3544 | while (limit > 0) | 3544 | while (limit > 0) |
| 3545 | { | 3545 | { |
| 3546 | if (begv == BEGV || FETCH_BYTE (CHAR_TO_BYTE (begv) - 1) == '\n') | 3546 | if (begv == BEGV || FETCH_BYTE (CHAR_TO_BYTE (begv) - 1) == '\n') |
| @@ -3554,9 +3554,9 @@ get_locked_narrowing_begv (ptrdiff_t pos) | |||
| 3554 | ptrdiff_t | 3554 | ptrdiff_t |
| 3555 | get_locked_narrowing_zv (ptrdiff_t pos) | 3555 | get_locked_narrowing_zv (ptrdiff_t pos) |
| 3556 | { | 3556 | { |
| 3557 | if (long_line_locked_narrowing_region_size <= 0) | 3557 | if (long_line_optimizations_region_size <= 0) |
| 3558 | return ZV; | 3558 | return ZV; |
| 3559 | int len = long_line_locked_narrowing_region_size / 2; | 3559 | int len = long_line_optimizations_region_size / 2; |
| 3560 | return min (pos + len, ZV); | 3560 | return min (pos + len, ZV); |
| 3561 | } | 3561 | } |
| 3562 | 3562 | ||
| @@ -4394,7 +4394,7 @@ handle_fontified_prop (struct it *it) | |||
| 4394 | eassert (it->end_charpos == ZV); | 4394 | eassert (it->end_charpos == ZV); |
| 4395 | 4395 | ||
| 4396 | if (current_buffer->long_line_optimizations_p | 4396 | if (current_buffer->long_line_optimizations_p |
| 4397 | && long_line_locked_narrowing_region_size > 0) | 4397 | && long_line_optimizations_region_size > 0) |
| 4398 | { | 4398 | { |
| 4399 | ptrdiff_t begv = it->locked_narrowing_begv; | 4399 | ptrdiff_t begv = it->locked_narrowing_begv; |
| 4400 | ptrdiff_t zv = it->locked_narrowing_zv; | 4400 | ptrdiff_t zv = it->locked_narrowing_zv; |
| @@ -4406,7 +4406,7 @@ handle_fontified_prop (struct it *it) | |||
| 4406 | } | 4406 | } |
| 4407 | if (begv != BEG || zv != Z) | 4407 | if (begv != BEG || zv != Z) |
| 4408 | narrow_to_region_locked (make_fixnum (begv), make_fixnum (zv), | 4408 | narrow_to_region_locked (make_fixnum (begv), make_fixnum (zv), |
| 4409 | Qfontification_functions); | 4409 | Qlong_line_optimizations_in_fontification_functions); |
| 4410 | } | 4410 | } |
| 4411 | 4411 | ||
| 4412 | /* Don't allow Lisp that runs from 'fontification-functions' | 4412 | /* Don't allow Lisp that runs from 'fontification-functions' |
| @@ -36266,6 +36266,8 @@ be let-bound around code that needs to disable messages temporarily. */); | |||
| 36266 | DEFSYM (QCfile, ":file"); | 36266 | DEFSYM (QCfile, ":file"); |
| 36267 | DEFSYM (Qfontified, "fontified"); | 36267 | DEFSYM (Qfontified, "fontified"); |
| 36268 | DEFSYM (Qfontification_functions, "fontification-functions"); | 36268 | DEFSYM (Qfontification_functions, "fontification-functions"); |
| 36269 | DEFSYM (Qlong_line_optimizations_in_fontification_functions, | ||
| 36270 | "long-line-optimizations-in-fontification-functions"); | ||
| 36269 | 36271 | ||
| 36270 | /* Name of the symbol which disables Lisp evaluation in 'display' | 36272 | /* Name of the symbol which disables Lisp evaluation in 'display' |
| 36271 | properties. This is used by enriched.el. */ | 36273 | properties. This is used by enriched.el. */ |
| @@ -36775,12 +36777,11 @@ Each function is called with one argument POS. Functions must | |||
| 36775 | fontify a region starting at POS in the current buffer, and give | 36777 | fontify a region starting at POS in the current buffer, and give |
| 36776 | fontified regions the property `fontified' with a non-nil value. | 36778 | fontified regions the property `fontified' with a non-nil value. |
| 36777 | 36779 | ||
| 36778 | Note that, when the buffer contains one or more lines whose length is | 36780 | Note that, when `long-line-optimizations-p' is non-nil in the buffer, |
| 36779 | above `long-line-threshold', these functions are called with the | 36781 | these functions are called as if they were in a `with-narrowing' form, |
| 36780 | buffer narrowed to a small portion around POS (whose size is specified | 36782 | with a `long-line-optimizations-in-fontification-functions' label and |
| 36781 | by `long-line-locked-narrowing-region-size'), and the narrowing is | 36783 | with the buffer narrowed to a portion around POS whose size is |
| 36782 | locked (see `narrowing-lock'), so that these functions cannot use | 36784 | specified by `long-line-optimizations-region-size'. */); |
| 36783 | `widen' to gain access to other portions of buffer text. */); | ||
| 36784 | Vfontification_functions = Qnil; | 36785 | Vfontification_functions = Qnil; |
| 36785 | Fmake_variable_buffer_local (Qfontification_functions); | 36786 | Fmake_variable_buffer_local (Qfontification_functions); |
| 36786 | 36787 | ||
diff --git a/test/src/buffer-tests.el b/test/src/buffer-tests.el index 9d4bbf3e040..0ae78c8d9d9 100644 --- a/test/src/buffer-tests.el +++ b/test/src/buffer-tests.el | |||
| @@ -8539,4 +8539,110 @@ Finally, kill the buffer and its temporary file." | |||
| 8539 | (if f2 (delete-file f2)) | 8539 | (if f2 (delete-file f2)) |
| 8540 | ))) | 8540 | ))) |
| 8541 | 8541 | ||
| 8542 | (ert-deftest test-labeled-narrowing () | ||
| 8543 | "Test `with-narrowing' and `without-narrowing'." | ||
| 8544 | (with-current-buffer (generate-new-buffer " foo" t) | ||
| 8545 | (insert (make-string 5000 ?a)) | ||
| 8546 | (should (= (point-min) 1)) | ||
| 8547 | (should (= (point-max) 5001)) | ||
| 8548 | (with-narrowing | ||
| 8549 | 100 500 :label 'foo | ||
| 8550 | (should (= (point-min) 100)) | ||
| 8551 | (should (= (point-max) 500)) | ||
| 8552 | (widen) | ||
| 8553 | (should (= (point-min) 100)) | ||
| 8554 | (should (= (point-max) 500)) | ||
| 8555 | (narrow-to-region 1 5000) | ||
| 8556 | (should (= (point-min) 100)) | ||
| 8557 | (should (= (point-max) 500)) | ||
| 8558 | (narrow-to-region 50 150) | ||
| 8559 | (should (= (point-min) 100)) | ||
| 8560 | (should (= (point-max) 150)) | ||
| 8561 | (widen) | ||
| 8562 | (should (= (point-min) 100)) | ||
| 8563 | (should (= (point-max) 500)) | ||
| 8564 | (narrow-to-region 400 1000) | ||
| 8565 | (should (= (point-min) 400)) | ||
| 8566 | (should (= (point-max) 500)) | ||
| 8567 | (without-narrowing | ||
| 8568 | :label 'bar | ||
| 8569 | (should (= (point-min) 100)) | ||
| 8570 | (should (= (point-max) 500))) | ||
| 8571 | (without-narrowing | ||
| 8572 | :label 'foo | ||
| 8573 | (should (= (point-min) 1)) | ||
| 8574 | (should (= (point-max) 5001))) | ||
| 8575 | (should (= (point-min) 400)) | ||
| 8576 | (should (= (point-max) 500)) | ||
| 8577 | (widen) | ||
| 8578 | (should (= (point-min) 100)) | ||
| 8579 | (should (= (point-max) 500)) | ||
| 8580 | (with-narrowing | ||
| 8581 | 50 250 :label 'bar | ||
| 8582 | (should (= (point-min) 100)) | ||
| 8583 | (should (= (point-max) 250)) | ||
| 8584 | (widen) | ||
| 8585 | (should (= (point-min) 100)) | ||
| 8586 | (should (= (point-max) 250)) | ||
| 8587 | (without-narrowing | ||
| 8588 | :label 'bar | ||
| 8589 | (should (= (point-min) 100)) | ||
| 8590 | (should (= (point-max) 500)) | ||
| 8591 | (without-narrowing | ||
| 8592 | :label 'foo | ||
| 8593 | (should (= (point-min) 1)) | ||
| 8594 | (should (= (point-max) 5001))) | ||
| 8595 | (should (= (point-min) 100)) | ||
| 8596 | (should (= (point-max) 500))) | ||
| 8597 | (should (= (point-min) 100)) | ||
| 8598 | (should (= (point-max) 250))) | ||
| 8599 | (should (= (point-min) 100)) | ||
| 8600 | (should (= (point-max) 500)) | ||
| 8601 | (with-narrowing | ||
| 8602 | 50 250 :label 'bar | ||
| 8603 | (should (= (point-min) 100)) | ||
| 8604 | (should (= (point-max) 250)) | ||
| 8605 | (with-narrowing | ||
| 8606 | 150 500 :label 'baz | ||
| 8607 | (should (= (point-min) 150)) | ||
| 8608 | (should (= (point-max) 250)) | ||
| 8609 | (without-narrowing | ||
| 8610 | :label 'bar | ||
| 8611 | (should (= (point-min) 150)) | ||
| 8612 | (should (= (point-max) 250))) | ||
| 8613 | (without-narrowing | ||
| 8614 | :label 'foo | ||
| 8615 | (should (= (point-min) 150)) | ||
| 8616 | (should (= (point-max) 250))) | ||
| 8617 | (without-narrowing | ||
| 8618 | :label 'baz | ||
| 8619 | (should (= (point-min) 100)) | ||
| 8620 | (should (= (point-max) 250)) | ||
| 8621 | (without-narrowing | ||
| 8622 | :label 'foo | ||
| 8623 | (should (= (point-min) 100)) | ||
| 8624 | (should (= (point-max) 250))) | ||
| 8625 | (without-narrowing | ||
| 8626 | :label 'bar | ||
| 8627 | (should (= (point-min) 100)) | ||
| 8628 | (should (= (point-max) 500)) | ||
| 8629 | (without-narrowing | ||
| 8630 | :label 'foobar | ||
| 8631 | (should (= (point-min) 100)) | ||
| 8632 | (should (= (point-max) 500))) | ||
| 8633 | (without-narrowing | ||
| 8634 | :label 'foo | ||
| 8635 | (should (= (point-min) 1)) | ||
| 8636 | (should (= (point-max) 5001))) | ||
| 8637 | (should (= (point-min) 100)) | ||
| 8638 | (should (= (point-max) 500))) | ||
| 8639 | (should (= (point-min) 100)) | ||
| 8640 | (should (= (point-max) 250))) | ||
| 8641 | (should (= (point-min) 150)) | ||
| 8642 | (should (= (point-max) 250))) | ||
| 8643 | (should (= (point-min) 100)) | ||
| 8644 | (should (= (point-max) 250)))) | ||
| 8645 | (should (= (point-min) 1)) | ||
| 8646 | (should (= (point-max) 5001)))) | ||
| 8647 | |||
| 8542 | ;;; buffer-tests.el ends here | 8648 | ;;; buffer-tests.el ends here |