Commit 8b2b4b58 authored by Eli Zaretskii's avatar Eli Zaretskii

Fix display of TABs in hscrolled windows with line numbers

* src/dispextern.h (struct it): New members tab_offset and
line_number_produced_p.
* src/xdisp.c (display_line): Don't set row->x to a negative value
if line numbers are being displayed.  (Bug#30582)
Reset the line_number_produced_p flag before laying out the glyph
row.
(x_produce_glyphs): Use the line_number_produced_p flag to decide
whether to offset the X coordinate due to line-number display.
Use the tab_offset member to restore the original TAB width for
alignment purposes.
(move_it_in_display_line_to): Don't produce line numbers when moving
in hscrolled window to the left of first_visible_x.
(maybe_produce_line_number): Set the line_number_produced_p flag.
(Bug#30584)
* src/term.c (produce_glyphs): Correct TAB width only when
line_number_produced_p flag is set.

(cherry picked from commit 1ac19055)
parent de69d284
......@@ -2462,6 +2462,10 @@ struct it
descent/ascent (line-height property). Reset after this glyph. */
bool_bf constrain_row_ascent_descent_p : 1;
/* If true, glyphs for line number display were already produced for
the current row. */
bool_bf line_number_produced_p : 1;
enum line_wrap_method line_wrap;
/* The ID of the default face to use. One of DEFAULT_FACE_ID,
......@@ -2641,6 +2645,12 @@ struct it
/* The line number of point's line, or zero if not computed yet. */
ptrdiff_t pt_lnum;
/* Number of pixels to offset tab stops due to width fixup of the
first glyph that crosses first_visible_x. This is only needed on
GUI frames, only when display-line-numbers is in effect, and only
in hscrolled windows. */
int tab_offset;
/* Left fringe bitmap number (enum fringe_bitmap_type). */
unsigned left_user_fringe_bitmap : FRINGE_ID_BITS;
......
......@@ -1591,13 +1591,13 @@ produce_glyphs (struct it *it)
+ it->continuation_lines_width);
int x0 = absolute_x;
/* Adjust for line numbers. */
if (!NILP (Vdisplay_line_numbers))
if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
absolute_x -= it->lnum_pixel_width;
int next_tab_x
= (((1 + absolute_x + it->tab_width - 1)
/ it->tab_width)
* it->tab_width);
if (!NILP (Vdisplay_line_numbers))
if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
next_tab_x += it->lnum_pixel_width;
int nspaces;
......
......@@ -8718,8 +8718,12 @@ move_it_in_display_line_to (struct it *it,
if (it->hpos == 0)
{
/* If line numbers are being displayed, produce a line number. */
if (should_produce_line_number (it))
/* If line numbers are being displayed, produce a line number.
But don't do that if we are to reach first_visible_x, because
line numbers are not relevant to stuff that is not visible on
display. */
if (!((op && MOVE_TO_X) && to_x == it->first_visible_x)
&& should_produce_line_number (it))
{
if (it->current_x == it->first_visible_x)
maybe_produce_line_number (it);
......@@ -21169,6 +21173,8 @@ maybe_produce_line_number (struct it *it)
it->max_phys_descent = max (it->max_phys_descent, tem_it.max_phys_descent);
}
it->line_number_produced_p = true;
bidi_unshelve_cache (itdata, false);
}
......@@ -21292,6 +21298,8 @@ display_line (struct it *it, int cursor_vpos)
row->displays_text_p = true;
row->starts_in_middle_of_char_p = it->starts_in_middle_of_char_p;
it->starts_in_middle_of_char_p = false;
it->tab_offset = 0;
it->line_number_produced_p = false;
/* Arrange the overlays nicely for our purposes. Usually, we call
display_line on only one line at a time, in which case this
......@@ -21336,6 +21344,10 @@ display_line (struct it *it, int cursor_vpos)
|| move_result == MOVE_POS_MATCH_OR_ZV))
it->current_x = it->first_visible_x;
/* In case move_it_in_display_line_to above "produced" the line
number. */
it->line_number_produced_p = false;
/* Record the smallest positions seen while we moved over
display elements that are not visible. This is needed by
redisplay_internal for optimizing the case where the cursor
......@@ -21555,6 +21567,10 @@ display_line (struct it *it, int cursor_vpos)
row->extra_line_spacing = max (row->extra_line_spacing,
it->max_extra_line_spacing);
if (it->current_x - it->pixel_width < it->first_visible_x
/* When line numbers are displayed, row->x should not be
offset, as the first glyph after the line number can
never be partially visible. */
&& !line_number_needed
/* In R2L rows, we arrange in extend_face_to_end_of_line
to add a right offset to the line, by a suitable
change to the stretch glyph that is the leftmost
......@@ -21796,7 +21812,8 @@ display_line (struct it *it, int cursor_vpos)
if (it->bidi_p)
RECORD_MAX_MIN_POS (it);
if (x < it->first_visible_x && !row->reversed_p)
if (x < it->first_visible_x && !row->reversed_p
&& !line_number_needed)
/* Glyph is partially visible, i.e. row starts at
negative X position. Don't do that in R2L
rows, where we arrange to add a right offset to
......@@ -21812,6 +21829,7 @@ display_line (struct it *it, int cursor_vpos)
be taken care of in produce_special_glyphs. */
if (row->reversed_p
&& new_x > it->last_visible_x
&& !line_number_needed
&& !(it->line_wrap == TRUNCATE
&& WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0))
{
......@@ -28264,8 +28282,14 @@ x_produce_glyphs (struct it *it)
int x = it->current_x + it->continuation_lines_width;
int x0 = x;
/* Adjust for line numbers, if needed. */
if (!NILP (Vdisplay_line_numbers) && x0 >= it->lnum_pixel_width)
x -= it->lnum_pixel_width;
if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
{
x -= it->lnum_pixel_width;
/* Restore the original TAB width, if required. */
if (x + it->tab_offset >= it->first_visible_x)
x += it->tab_offset;
}
int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
/* If the distance from the current position to the next tab
......@@ -28273,10 +28297,19 @@ x_produce_glyphs (struct it *it)
tab stop after that. */
if (next_tab_x - x < font->space_width)
next_tab_x += tab_width;
if (!NILP (Vdisplay_line_numbers) && x0 >= it->lnum_pixel_width)
next_tab_x += (it->lnum_pixel_width
- ((it->w->hscroll * font->space_width)
% tab_width));
if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
{
next_tab_x += it->lnum_pixel_width;
/* If the line is hscrolled, and the TAB starts before
the first visible pixel, simulate negative row->x. */
if (x < it->first_visible_x)
{
next_tab_x -= it->first_visible_x - x;
it->tab_offset = it->first_visible_x - x;
}
else
next_tab_x -= it->tab_offset;
}
it->pixel_width = next_tab_x - x0;
it->nglyphs = 1;
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment