summaryrefslogtreecommitdiff
path: root/src/indent.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/indent.c')
-rw-r--r--src/indent.c60
1 files changed, 53 insertions, 7 deletions
diff --git a/src/indent.c b/src/indent.c
index d2dfaee254e..cb368024d97 100644
--- a/src/indent.c
+++ b/src/indent.c
@@ -306,8 +306,8 @@ and point (e.g., control characters will have a width of 2 or 4, tabs
will have a variable width).
Ignores finite width of frame, which means that this function may return
values greater than (frame-width).
-In a buffer with very long lines, the value can be zero, because calculating
-the exact number is very expensive.
+In a buffer with very long lines, the value will be an approximation,
+because calculating the exact number is very expensive.
Whether the line is visible (if `selective-display' is t) has no effect;
however, ^M is treated as end of line when `selective-display' is t.
Text that has an invisible property is considered as having width 0, unless
@@ -316,8 +316,6 @@ Text that has an invisible property is considered as having width 0, unless
{
Lisp_Object temp;
- if (current_buffer->long_line_optimizations_p)
- return make_fixnum (0);
XSETFASTINT (temp, current_column ());
return temp;
}
@@ -346,6 +344,14 @@ current_column (void)
&& MODIFF == last_known_column_modified)
return last_known_column;
+ ptrdiff_t line_beg = find_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, -1,
+ NULL, NULL, 1);
+
+ /* Avoid becoming abysmally slow for very long lines. */
+ if (current_buffer->long_line_optimizations_p
+ && !NILP (Vlong_line_threshold)
+ && PT - line_beg > XFIXNUM (Vlong_line_threshold))
+ return PT - line_beg; /* this is an approximation! */
/* If the buffer has overlays, text properties,
or multibyte characters, use a more general algorithm. */
if (buffer_intervals (current_buffer)
@@ -561,13 +567,53 @@ scan_for_column (ptrdiff_t *endpos, EMACS_INT *goalcol,
ptrdiff_t scan, scan_byte, next_boundary, prev_pos, prev_bpos;
scan = find_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, -1, NULL, &scan_byte, 1);
- next_boundary = scan;
- prev_pos = scan;
- prev_bpos = scan_byte;
window = Fget_buffer_window (Fcurrent_buffer (), Qnil);
w = ! NILP (window) ? XWINDOW (window) : NULL;
+ if (current_buffer->long_line_optimizations_p)
+ {
+ bool lines_truncated = false;
+
+ if (!NILP (BVAR (current_buffer, truncate_lines)))
+ lines_truncated = true;
+ else if (w && FIXNUMP (Vtruncate_partial_width_windows))
+ lines_truncated =
+ w->total_cols < XFIXNAT (Vtruncate_partial_width_windows);
+ else if (w && !NILP (Vtruncate_partial_width_windows))
+ lines_truncated =
+ w->total_cols < FRAME_COLS (XFRAME (WINDOW_FRAME (w)));
+ /* Special optimization for buffers with long and truncated
+ lines: assumes that each character is a single column. */
+ if (lines_truncated)
+ {
+ ptrdiff_t bolpos = scan;
+ /* The newline which ends this line or ZV. */
+ ptrdiff_t eolpos =
+ find_newline (PT, PT_BYTE, ZV, ZV_BYTE, 1, NULL, NULL, 1);
+
+ scan = bolpos + goal;
+ if (scan > end)
+ scan = end;
+ if (scan > eolpos)
+ scan = (eolpos == ZV ? ZV : eolpos - 1);
+ col = scan - bolpos;
+ if (col > large_hscroll_threshold)
+ {
+ prev_col = col - 1;
+ prev_pos = scan - 1;
+ prev_bpos = CHAR_TO_BYTE (scan);
+ goto endloop;
+ }
+ /* Restore the values we've overwritten above. */
+ scan = bolpos;
+ col = 0;
+ }
+ }
+ next_boundary = scan;
+ prev_pos = scan;
+ prev_bpos = scan_byte;
+
memset (&cmp_it, 0, sizeof cmp_it);
cmp_it.id = -1;
composition_compute_stop_pos (&cmp_it, scan, scan_byte, end, Qnil);