]> git.eshelyaron.com Git - emacs.git/commitdiff
Improvements to long lines handling.
authorGregory Heytings <gregory@heytings.org>
Sat, 16 Jul 2022 19:06:38 +0000 (19:06 +0000)
committerGregory Heytings <gregory@heytings.org>
Sat, 16 Jul 2022 19:13:33 +0000 (21:13 +0200)
* src/buffer.h (struct buffer): New field 'long_line_optimizations_p'.

* src/buffer.c (syms_of_buffer): New variable 'long-line-threshold'.
(reset_buffer): Initialize the 'long_line_optimizations_p' field.
(Fbuffer_swap_text): Handle it.

* src/xdisp.c (redisplay_window): Set 'long_line_optimizations_p' when
a buffer contains long lines.
(init_iterator): Use 'long_line_optimizations_p'.
(get_narrowed_begv): Update.
(SET_WITH_NARROWED_BEGV): New macro.
(unwind_narrowed_begv): New internal function used by the new macro.
(back_to_previous_line_start, get_visually_first_element,
move_it_vertically_backward): Use the new macro.

* src/search.c (find_newline1): Make it externally visible.

* src/lisp.h: Make 'find_newline1' externally visible.

* src/dispextern.h (struct it): Update comment.  Remove the
'WITH_NARROWED_BEGV' macro.

* etc/NEWS: Mention the 'long-line-threshold' variable.

etc/NEWS
src/buffer.c
src/buffer.h
src/dispextern.h
src/lisp.h
src/search.c
src/xdisp.c

index 223e6dd7616ee38cb805e506d10392eb323ef066..6050a8ae1aed752757ea530fbaaadd57887722ab 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -332,7 +332,9 @@ experience slowdowns while editing files with long lines, this is
 either due to font locking, which you can turn off with M-x
 font-lock-mode, or to the current major mode or one of the enabled
 minor modes, in which case you should open the the file with M-x
-find-file-literally instead of C-x C-f.
+find-file-literally instead of C-x C-f.  The variable
+'long-line-threshold' controls whether and when these display
+optimizations are used.
 
 +++
 ** New command to change the font size globally.
index 509ce51b55ea34e14d28156956235ba61f2cd448..a777668e44b0225178679363031ecda677ec9332 100644 (file)
@@ -984,6 +984,7 @@ reset_buffer (register struct buffer *b)
   /* It is more conservative to start out "changed" than "unchanged".  */
   b->clip_changed = 0;
   b->prevent_redisplay_optimizations_p = 1;
+  b->long_line_optimizations_p = 0;
   bset_backed_up (b, Qnil);
   bset_local_minor_modes (b, Qnil);
   BUF_AUTOSAVE_MODIFF (b) = 0;
@@ -2445,6 +2446,7 @@ results, see Info node `(elisp)Swapping Text'.  */)
   swapfield (bidi_paragraph_cache, struct region_cache *);
   current_buffer->prevent_redisplay_optimizations_p = 1;
   other_buffer->prevent_redisplay_optimizations_p = 1;
+  swapfield (long_line_optimizations_p, bool_bf);
   swapfield (overlays_before, struct Lisp_Overlay *);
   swapfield (overlays_after, struct Lisp_Overlay *);
   swapfield (overlay_center, ptrdiff_t);
@@ -6423,6 +6425,14 @@ Since `clone-indirect-buffer' calls `make-indirect-buffer', this hook
 will run for `clone-indirect-buffer' calls as well.  */);
   Vclone_indirect_buffer_hook = Qnil;
 
+  DEFVAR_LISP ("long-line-threshold", Vlong_line_threshold,
+              doc: /* Line length above which specific display optimizations are used.
+Display optimizations for long lines will automatically be enabled in
+buffers which contain one or more lines whose length is above that
+threshold.
+When nil, these display optimizations are disabled.  */);
+  XSETFASTINT (Vlong_line_threshold, 10000);
+
   defsubr (&Sbuffer_live_p);
   defsubr (&Sbuffer_list);
   defsubr (&Sget_buffer);
index 135eaf72d30ceafec82bd26e77c0d0385ca83ac7..09daa29992adc7e4ee82491807ac29b98926b11c 100644 (file)
@@ -681,6 +681,10 @@ struct buffer
      defined, as well as by with-temp-buffer, for example.  */
   bool_bf inhibit_buffer_hooks : 1;
 
+  /* Non-zero when the buffer contains long lines and specific
+     display optimizations must be used.  */
+  bool_bf long_line_optimizations_p : 1;
+
   /* List of overlays that end at or before the current center,
      in order of end-position.  */
   struct Lisp_Overlay *overlays_before;
index 2edf4b73f811cbd79d131c75f862a429033a7849..c57949949503e80ae62a346cc376b82d294e5b50 100644 (file)
@@ -2332,8 +2332,8 @@ struct it
      with which display_string was called.  */
   ptrdiff_t end_charpos;
 
-  /* Alternate begin position of the buffer, which is used to optimize
-     display (see the WITH_NARROWED_BEGV macro below).  */
+  /* Alternate begin position of the buffer that may be used to
+     optimize display (see the WITH_NARROWED_BEGV macro below).  */
   ptrdiff_t narrowed_begv;
 
   /* C string to iterate over.  Non-null means get characters from
@@ -2817,18 +2817,6 @@ struct it
     reset_box_start_end_flags ((IT));                  \
   } while (false)
 
-/* Execute STATEMENT with a temporarily narrowed buffer.  */
-
-#define WITH_NARROWED_BEGV(STATEMENT)                              \
-  do {                                                             \
-    ptrdiff_t obegv = BEGV;                                        \
-    if (it->narrowed_begv)                                         \
-      SET_BUF_BEGV (current_buffer, it->narrowed_begv);                    \
-    STATEMENT;                                                     \
-    if (it->narrowed_begv)                                         \
-      SET_BUF_BEGV (current_buffer, obegv);                        \
-  } while (0)
-
 /* Bit-flags indicating what operation move_it_to should perform.  */
 
 enum move_operation_enum
index e4a49b8ef945983a160440fee1f7545c70ebe214..5045d49e1b66d326d547d6e5221cd434700ca30b 100644 (file)
@@ -4761,6 +4761,8 @@ extern ptrdiff_t fast_c_string_match_ignore_case (Lisp_Object, const char *,
                                                  ptrdiff_t);
 extern ptrdiff_t fast_looking_at (Lisp_Object, ptrdiff_t, ptrdiff_t,
                                   ptrdiff_t, ptrdiff_t, Lisp_Object);
+extern ptrdiff_t find_newline1 (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t,
+                               ptrdiff_t, ptrdiff_t *, ptrdiff_t *, bool);
 extern ptrdiff_t find_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t,
                               ptrdiff_t, ptrdiff_t *, ptrdiff_t *, bool);
 extern void scan_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t,
index 9d6bd074e1b453571a2271ab9e8070c29e559352..b5d6a442c0ffcf225aa8e56a6701f6d973b90f26 100644 (file)
@@ -3192,7 +3192,7 @@ DEFUN ("regexp-quote", Fregexp_quote, Sregexp_quote, 1, 1, 0,
 }
 
 /* Like find_newline, but doesn't use the cache, and only searches forward.  */
-static ptrdiff_t
+ptrdiff_t
 find_newline1 (ptrdiff_t start, ptrdiff_t start_byte, ptrdiff_t end,
               ptrdiff_t end_byte, ptrdiff_t count, ptrdiff_t *counted,
               ptrdiff_t *bytepos, bool allow_quit)
index ac76917eb3fceb0ef780c86f9bb38491b8a794af..98bf15a85943d5116ea3ee0af59bae9821a604f0 100644 (file)
@@ -3425,7 +3425,8 @@ init_iterator (struct it *it, struct window *w,
        }
     }
 
-  it->narrowed_begv = get_narrowed_begv (w);
+  if (current_buffer->long_line_optimizations_p)
+    it->narrowed_begv = get_narrowed_begv (w);
 
   /* If a buffer position was specified, set the iterator there,
      getting overlays and face properties from that position.  */
@@ -3493,20 +3494,43 @@ init_iterator (struct it *it, struct window *w,
   CHECK_IT (it);
 }
 
-/* Compute a suitable value for BEGV that can be used temporarily, to
-   optimize display, for the buffer in window W.  */
+/* Compute a suitable alternate value for BEGV 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)
 {
   int len; ptrdiff_t begv;
-  len = (1 + ((window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS) *
-              window_body_height (w, WINDOW_BODY_IN_CANONICAL_CHARS)) /
-             10000)) * 10000;
-  begv = max ((PT / len - 2) * len, BEGV);
+  len = 3 * (window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS) *
+            window_body_height (w, WINDOW_BODY_IN_CANONICAL_CHARS));
+  begv = max ((window_point (w) / len - 1) * len, BEGV);
   return begv == BEGV ? 0 : begv;
 }
 
+static void
+unwind_narrowed_begv (Lisp_Object point_min)
+{
+  SET_BUF_BEGV (current_buffer, XFIXNUM (point_min));
+}
+
+/* Set DST to EXPR.  When IT indicates that BEGV should temporarily be
+   updated to optimize display, evaluate EXPR with an updated BEGV.  */
+
+#define SET_WITH_NARROWED_BEGV(IT,DST,EXPR)                            \
+  do {                                                                 \
+    if (IT->narrowed_begv)                                             \
+      {                                                                        \
+       specpdl_ref count = SPECPDL_INDEX ();                           \
+       record_unwind_protect (unwind_narrowed_begv, Fpoint_min ());    \
+       SET_BUF_BEGV (current_buffer, IT->narrowed_begv);               \
+       DST = EXPR;                                                     \
+       unbind_to (count, Qnil);                                        \
+      }                                                                        \
+    else                                                               \
+      DST = EXPR;                                                      \
+  } while (0)
+
 /* Initialize IT for the display of window W with window start POS.  */
 
 void
@@ -7007,8 +7031,8 @@ back_to_previous_line_start (struct it *it)
   ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
 
   dec_both (&cp, &bp);
-  WITH_NARROWED_BEGV (IT_CHARPOS (*it) =
-                     find_newline_no_quit (cp, bp, -1, &IT_BYTEPOS (*it)));
+  SET_WITH_NARROWED_BEGV (it, IT_CHARPOS (*it),
+                         find_newline_no_quit (cp, bp, -1, &IT_BYTEPOS (*it)));
 }
 
 
@@ -8642,7 +8666,7 @@ get_visually_first_element (struct it *it)
   ptrdiff_t eob = (string_p ? it->bidi_it.string.schars : ZV);
   ptrdiff_t bob;
 
-  WITH_NARROWED_BEGV (bob = (string_p ? 0 : BEGV));
+  SET_WITH_NARROWED_BEGV (it, bob, string_p ? 0 : BEGV);
 
   if (STRINGP (it->string))
     {
@@ -8682,10 +8706,10 @@ get_visually_first_element (struct it *it)
       if (string_p)
        it->bidi_it.charpos = it->bidi_it.bytepos = 0;
       else
-       WITH_NARROWED_BEGV (it->bidi_it.charpos =
-                           find_newline_no_quit (IT_CHARPOS (*it),
-                                                 IT_BYTEPOS (*it), -1,
-                                                 &it->bidi_it.bytepos));
+       SET_WITH_NARROWED_BEGV (it, it->bidi_it.charpos,
+                               find_newline_no_quit (IT_CHARPOS (*it),
+                                                     IT_BYTEPOS (*it), -1,
+                                                     &it->bidi_it.bytepos));
       bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
       do
        {
@@ -10603,7 +10627,8 @@ move_it_vertically_backward (struct it *it, int dy)
          ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
 
          dec_both (&cp, &bp);
-         WITH_NARROWED_BEGV (cp = find_newline_no_quit (cp, bp, -1, NULL));
+         SET_WITH_NARROWED_BEGV (it, cp,
+                                 find_newline_no_quit (cp, bp, -1, NULL));
          move_it_to (it, cp, -1, -1, -1, MOVE_TO_POS);
        }
       bidi_unshelve_cache (it3data, true);
@@ -19245,6 +19270,23 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
         }
     }
 
+  /* Check whether the buffer to be displayed contains long lines.  */
+  if (!NILP (Vlong_line_threshold)
+      && !current_buffer->long_line_optimizations_p
+      && MODIFF != UNCHANGED_MODIFIED)
+    {
+      ptrdiff_t cur, next, found, max = 0;
+      for (cur = 1; cur < Z; cur = next)
+       {
+         next = find_newline1 (cur, CHAR_TO_BYTE (cur), 0, -1, 1,
+                               &found, NULL, true);
+         if (next - cur > max) max = next - cur;
+         if (!found || max > XFIXNUM (Vlong_line_threshold)) break;
+       }
+      if (max > XFIXNUM (Vlong_line_threshold))
+       current_buffer->long_line_optimizations_p = true;
+    }
+
   /* If window-start is screwed up, choose a new one.  */
   if (XMARKER (w->start)->buffer != current_buffer)
     goto recenter;