]> git.eshelyaron.com Git - emacs.git/commitdiff
Improve font locking in buffers with long lines (bug#56682).
authorGregory Heytings <gregory@heytings.org>
Fri, 22 Jul 2022 10:03:13 +0000 (10:03 +0000)
committerGregory Heytings <gregory@heytings.org>
Fri, 22 Jul 2022 10:06:31 +0000 (12:06 +0200)
* src/dispextern.h (struct it): New 'narrowed_zv' field.

* src/xdisp.c (init_iterator): Set the field.
(get_narrowed_zv): New function to set the field.
(handle_fontified_prop): Use the field, together with 'narrowed_begv',
to narrow the portion of the buffer that 'Vfontification_functions'
will see.  Also bind 'inhibit-widen'.
(get_narrowed_len): New function, factored out of 'get_narrowed_begv'.
(unwind_narrowed_zv): New function.

* src/editfns.c (syms_of_editfns): New variable and symbol 'inhibit-widen'.
(Fwiden): Do nothing when 'inhibit-widen' is non-nil.

src/dispextern.h
src/editfns.c
src/xdisp.c

index 1cdfdca74c08facfe51cb3f8cd10c081639ce14e..bafa98161d05554211f2955de8f7ea1442f69c19 100644 (file)
@@ -2336,6 +2336,10 @@ struct it
      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;
+
   /* C string to iterate over.  Non-null means get characters from
      this string, otherwise characters are read from current_buffer
      or it->string.  */
@@ -3401,6 +3405,7 @@ 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 *w);
+ptrdiff_t get_narrowed_zv (struct window *w);
 void init_iterator_to_row_start (struct it *, struct window *,
                                  struct glyph_row *);
 void start_display (struct it *, struct window *, struct text_pos);
index 4587b1132b1664e8e53c3df20c7b902a3c3a9c76..6dec2d468c05d1300e31db74902733e73a2c2ca1 100644 (file)
@@ -2661,6 +2661,8 @@ DEFUN ("widen", Fwiden, Swiden, 0, 0, "",
 This allows the buffer's full text to be seen and edited.  */)
   (void)
 {
+  if (!NILP (Vinhibit_widen))
+    return Qnil;
   if (BEG != BEGV || Z != ZV)
     current_buffer->clip_changed = 1;
   BEGV = BEG;
@@ -4457,6 +4459,7 @@ syms_of_editfns (void)
   DEFSYM (Qbuffer_access_fontify_functions, "buffer-access-fontify-functions");
   DEFSYM (Qwall, "wall");
   DEFSYM (Qpropertize, "propertize");
+  DEFSYM (Qinhibit_widen, "inhibit-widen");
 
   DEFVAR_LISP ("inhibit-field-text-motion", Vinhibit_field_text_motion,
               doc: /* Non-nil means text motion commands don't notice fields.  */);
@@ -4517,6 +4520,15 @@ This variable is experimental; email 32252@debbugs.gnu.org if you need
 it to be non-nil.  */);
   binary_as_unsigned = false;
 
+  DEFVAR_LISP ("inhibit-widen", Vinhibit_widen,
+              doc: /* Non-nil inhibits the `widen' function.
+
+Do NOT set this globally to a non-nil value, as doing that will
+disable the `widen' function everywhere, including the \\[widen\]
+command.  This variable is intended to be let-bound around code
+that needs to disable `widen' temporarily.  */);
+  Vinhibit_widen = Qnil;
+
   defsubr (&Spropertize);
   defsubr (&Schar_equal);
   defsubr (&Sgoto_char);
index ebeaf2a3dab563d591257cc8ca678224083af222..caa421c28185637dafea22907fb87a41acc74c66 100644 (file)
@@ -3426,7 +3426,10 @@ init_iterator (struct it *it, struct window *w,
     }
 
   if (current_buffer->long_line_optimizations_p)
-    it->narrowed_begv = get_narrowed_begv (w);
+    {
+      it->narrowed_begv = get_narrowed_begv (w);
+      it->narrowed_zv = get_narrowed_zv (w);
+    }
 
   /* If a buffer position was specified, set the iterator there,
      getting overlays and face properties from that position.  */
@@ -3494,29 +3497,49 @@ init_iterator (struct it *it, struct window *w,
   CHECK_IT (it);
 }
 
-/* Compute a suitable alternate value for BEGV that may be used
+/* 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.  */
 
-ptrdiff_t
-get_narrowed_begv (struct window *w)
+static int
+get_narrowed_len (struct window *w)
 {
-  int len, fact; ptrdiff_t begv;
+  int fact;
   /* In a character-only terminal, only one font size is used, so we
      can use a smaller factor.  */
   fact = EQ (Fterminal_live_p (Qnil), Qt) ? 2 : 3;
-  len = fact * (window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS) *
-               window_body_height (w, WINDOW_BODY_IN_CANONICAL_CHARS));
+  return fact * (window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS) *
+                window_body_height (w, WINDOW_BODY_IN_CANONICAL_CHARS));
+}
+
+ptrdiff_t
+get_narrowed_begv (struct window *w)
+{
+  int len = get_narrowed_len (w);
+  ptrdiff_t begv;
   begv = max ((window_point (w) / len - 1) * len, BEGV);
   return begv == BEGV ? 0 : begv;
 }
 
+ptrdiff_t
+get_narrowed_zv (struct window *w)
+{
+  int len = get_narrowed_len (w);
+  return min ((window_point (w) / len + 1) * len, ZV);
+}
+
 static void
 unwind_narrowed_begv (Lisp_Object point_min)
 {
   SET_BUF_BEGV (current_buffer, XFIXNUM (point_min));
 }
 
+static void
+unwind_narrowed_zv (Lisp_Object point_max)
+{
+  SET_BUF_ZV (current_buffer, XFIXNUM (point_max));
+}
+
 /* Set DST to EXPR.  When IT indicates that BEGV should temporarily be
    updated to optimize display, evaluate EXPR with an updated BEGV.  */
 
@@ -4372,6 +4395,15 @@ handle_fontified_prop (struct it *it)
       bool old_clip_changed = current_buffer->clip_changed;
       bool saved_inhibit_flag = it->f->inhibit_clear_image_cache;
 
+      if (it->narrowed_begv)
+       {
+         record_unwind_protect (unwind_narrowed_begv, Fpoint_min ());
+         record_unwind_protect (unwind_narrowed_zv, Fpoint_max ());
+         SET_BUF_BEGV (current_buffer, it->narrowed_begv);
+         SET_BUF_ZV (current_buffer, it->narrowed_zv);
+         specbind (Qinhibit_widen, Qt);
+       }
+
       val = Vfontification_functions;
       specbind (Qfontification_functions, Qnil);