emacs-diffs
[Top][All Lists]
Advanced

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

feature/improved-locked-narrowing 01efdbd336 2/2: Better way to protect


From: Gregory Heytings
Subject: feature/improved-locked-narrowing 01efdbd336 2/2: Better way to protect redisplay routines from locked narrowings.
Date: Sun, 21 Aug 2022 15:35:57 -0400 (EDT)

branch: feature/improved-locked-narrowing
commit 01efdbd33664d45818f0686589d38e2bfad0ab69
Author: Gregory Heytings <gregory@heytings.org>
Commit: Gregory Heytings <gregory@heytings.org>

    Better way to protect redisplay routines from locked narrowings.
    
    * src/xdisp.c (reset_outermost_narrowing,
    unwind_reset_outermost_narrowing): New functions.
    (redisplay_internal): Use the new functions.
    
    * src/editfns.c (Fnarrow_to_region): Use the limits of the
    locked restriction instead of the position arguments if necessary.
    Update docstring.
    (Fnarrowing_lock): Update docstring.
---
 src/editfns.c | 36 ++++++++++++++++++++++++------------
 src/xdisp.c   | 35 +++++++++++++++++++++++++++++++++++
 2 files changed, 59 insertions(+), 12 deletions(-)

diff --git a/src/editfns.c b/src/editfns.c
index f52db223e4..c672783292 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -2731,7 +2731,9 @@ remain visible.
 
 When restrictions have been locked with `narrowing-lock', which see,
 `narrow-to-region' can be used only within the limits of the
-restrictions that were current when `narrowing-lock' was called.  */)
+restrictions that were current when `narrowing-lock' was called.  If
+the START or END arguments are outside these limits, the corresponding
+limit of the locked restriction is used instead of the argument.  */)
   (Lisp_Object start, Lisp_Object end)
 {
   EMACS_INT s = fix_position (start), e = fix_position (end);
@@ -2741,17 +2743,15 @@ restrictions that were current when `narrowing-lock' 
was called.  */)
       EMACS_INT tem = s; s = e; e = tem;
     }
 
-  if (NILP (Vnarrowing_locks))
-    {
-      if (!(BEG <= s && s <= e && e <= Z))
-       args_out_of_range (start, end);
-    }
-  else
+  if (!(BEG <= s && s <= e && e <= Z))
+    args_out_of_range (start, end);
+
+  if (! NILP (Vnarrowing_locks))
     {
       ptrdiff_t begv = XFIXNUM (Fcar (Fcdr (Fcar (Vnarrowing_locks))));
       ptrdiff_t zv = XFIXNUM (Fcdr (Fcdr (Fcar (Vnarrowing_locks))));
-      if (!(begv <= s && s <= e && e <= zv))
-       args_out_of_range (start, end);
+      if (s < begv) s = begv;
+      if (e > zv) e = zv;
     }
 
   Fset (Qoutermost_narrowing,
@@ -2774,12 +2774,24 @@ restrictions that were current when `narrowing-lock' 
was called.  */)
   return Qnil;
 }
 
-DEFUN ("narrowing-lock", Fnarrowing_lock, Snarrowing_lock, 1, 1, "",
+DEFUN ("narrowing-lock", Fnarrowing_lock, Snarrowing_lock, 1, 1, 0,
        doc: /* Lock the current narrowing with TAG.
 
 When restrictions are locked, `narrow-to-region' and `widen' can be
 used only within the limits of the restrictions that were current when
-`narrowing-lock' was called.  */)
+`narrowing-lock' was called, unless the lock is removed with
+\(narrowing-unlock TAG).
+
+Locking restrictions should be used sparingly, after carefully
+considering the potential adverse effects on the code that will be
+executed with locked restrictions.  It is meant to be used around
+portions of code that would become too slow, and make Emacs
+unresponsive, if they were executed in a large buffer.  For example,
+restrictions are locked by Emacs around low-level hooks such as
+`fontification-functions' or `post-command-hook'.
+
+Locked restrictions are never visible on display, and can therefore
+not be used as a stronger variant of normal restrictions.  */)
   (Lisp_Object tag)
 {
   if (NILP (Vnarrowing_locks))
@@ -2790,7 +2802,7 @@ used only within the limits of the restrictions that were 
current when
   return Qnil;
 }
 
-DEFUN ("narrowing-unlock", Fnarrowing_unlock, Snarrowing_unlock, 1, 1, "",
+DEFUN ("narrowing-unlock", Fnarrowing_unlock, Snarrowing_unlock, 1, 1, 0,
        doc: /* Unlock a narrowing locked with (narrowing-lock TAG).
 
 Unlocking restrictions locked with `narrowing-lock' should be used
diff --git a/src/xdisp.c b/src/xdisp.c
index 8f63b029c1..2ee02684dc 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -16363,6 +16363,39 @@ do { if (! polling_stopped_here) stop_polling ();      
\
 do { if (polling_stopped_here) start_polling ();       \
        polling_stopped_here = false; } while (false)
 
+static void
+unwind_reset_outermost_narrowing (Lisp_Object buf)
+{
+  Lisp_Object innermost_narrowing =
+    Fcar (buffer_local_value (Qnarrowing_locks, buf));
+  if (! NILP (innermost_narrowing))
+    {
+      SET_BUF_BEGV (XBUFFER (buf),
+                   XFIXNUM (Fcar (Fcdr (innermost_narrowing))));
+      SET_BUF_ZV (XBUFFER (buf),
+                 XFIXNUM (Fcdr (Fcdr (innermost_narrowing))));
+    }
+}
+
+static void
+reset_outermost_narrowings (void)
+{
+  Lisp_Object tail, buf, outermost_narrowing;
+  FOR_EACH_LIVE_BUFFER (tail, buf)
+    {
+      outermost_narrowing =
+       Fassq (Qoutermost_narrowing,
+              buffer_local_value (Qnarrowing_locks, buf));
+      if (!NILP (outermost_narrowing))
+       {
+         SET_BUF_BEGV (XBUFFER (buf),
+                       XFIXNUM (Fcar (Fcdr (outermost_narrowing))));
+         SET_BUF_ZV (XBUFFER (buf),
+                     XFIXNUM (Fcdr (Fcdr (outermost_narrowing))));
+         record_unwind_protect (unwind_reset_outermost_narrowing, buf);
+       }
+    }
+}
 
 /* Perhaps in the future avoid recentering windows if it
    is not necessary; currently that causes some problems.  */
@@ -16449,6 +16482,8 @@ redisplay_internal (void)
   FOR_EACH_FRAME (tail, frame)
     XFRAME (frame)->already_hscrolled_p = false;
 
+  reset_outermost_narrowings ();
+
  retry:
   /* Remember the currently selected window.  */
   sw = w;



reply via email to

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