From: Po Lu Date: Thu, 1 Feb 2024 08:16:09 +0000 (+0800) Subject: Prevent continuation from affecting tab width in/after line prefix X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=7aa46f52d6f508076907e45213f8284f72d01856;p=emacs.git Prevent continuation from affecting tab width in/after line prefix * src/dispextern.h (struct it) : New field, synchronized with current_x when producing glyphs for wrap prefixes, and subtracted from it->current_x when computing tab widths. * src/term.c (produce_glyphs): Set wrap_prefix_width. * src/xdisp.c (start_display, display_min_width, move_it_to) (move_it_vertically_backward, move_it_by_lines) (window_text_pixel_size, display_tab_bar_line) (display_tool_bar_line, redisplay_internal, redisplay_window) (try_window_id, insert_left_trunc_glyphs) (extend_face_to_end_of_line, display_line) (Fmove_point_visually): Set or clear wrap_prefix_width as appropriate. (gui_produce_glyphs): Set or clear it->wrap_prefix_width. When computing the base position of a tab character, do not subtract the continuation line width if a line prefix is the current iterator method. Subtract the wrap_prefix_width otherwise, in order that the width of the tab is computed free of influence from the wrap prefix. (cherry picked from commit 881a1ade30d2efacf9fcbd136b8fea722760f36e) --- diff --git a/src/dispextern.h b/src/dispextern.h index 84b9dadc184..5387cb45603 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -2752,6 +2752,16 @@ struct it pixel_width with each call to produce_glyphs. */ int current_x; + /* Pixel position within a display line with a wrap prefix. Updated + to reflect current_x in produce_glyphs when producing glyphs from + a prefix string and continuation_lines_width > 0, which is to + say, from a wrap prefix. + + Such updates are unnecessary where it is impossible for a wrap + prefix to be active, e.g. when continuation lines are being + produced. */ + int wrap_prefix_width; + /* Accumulated width of continuation lines. If > 0, this means we are currently in a continuation line. This is initially zero and incremented/reset by display_line, move_it_to etc. */ diff --git a/src/term.c b/src/term.c index 447876d288a..b3793088fac 100644 --- a/src/term.c +++ b/src/term.c @@ -1704,7 +1704,13 @@ produce_glyphs (struct it *it) /* Advance current_x by the pixel width as a convenience for the caller. */ if (it->area == TEXT_AREA) - it->current_x += it->pixel_width; + { + it->current_x += it->pixel_width; + + if (it->continuation_lines_width + && it->string_from_prefix_prop_p) + it->wrap_prefix_width = it->current_x; + } it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0; it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1; #endif diff --git a/src/xdisp.c b/src/xdisp.c index 066217a2f0f..4ff689b2df7 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -3821,7 +3821,7 @@ start_display (struct it *it, struct window *w, struct text_pos pos) it->current_y = first_y; it->vpos = 0; - it->current_x = it->hpos = 0; + it->current_x = it->hpos = it->wrap_prefix_width = 0; } } } @@ -5532,7 +5532,13 @@ display_min_width (struct it *it, ptrdiff_t bufpos, it->object = list3 (Qspace, QCwidth, w); produce_stretch_glyph (it); if (it->area == TEXT_AREA) - it->current_x += it->pixel_width; + { + it->current_x += it->pixel_width; + + if (it->continuation_lines_width + && it->string_from_prefix_prop_p) + it->wrap_prefix_width = it->current_x; + } it->min_width_property = Qnil; } } @@ -10797,6 +10803,7 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos /* Reset/increment for the next run. */ it->current_x = line_start_x; + it->wrap_prefix_width = 0; line_start_x = 0; it->hpos = 0; it->line_number_produced_p = false; @@ -10827,6 +10834,7 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos { it->continuation_lines_width += it->current_x; it->current_x = it->hpos = it->max_ascent = it->max_descent = 0; + it->wrap_prefix_width = 0; it->current_y += it->max_ascent + it->max_descent; ++it->vpos; last_height = it->max_ascent + it->max_descent; @@ -10886,6 +10894,7 @@ move_it_vertically_backward (struct it *it, int dy) reseat_1 (it, it->current.pos, true); /* We are now surely at a line start. */ + it->wrap_prefix_width = 0; it->current_x = it->hpos = 0; /* FIXME: this is incorrect when bidi reordering is in effect. */ it->continuation_lines_width = 0; @@ -11164,7 +11173,7 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos) dvpos--; } - it->current_x = it->hpos = 0; + it->current_x = it->hpos = it->wrap_prefix_width = 0; /* Above call may have moved too far if continuation lines are involved. Scan forward and see if it did. */ @@ -11173,7 +11182,7 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos) move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS); it->vpos -= it2.vpos; it->current_y -= it2.current_y; - it->current_x = it->hpos = 0; + it->current_x = it->hpos = it->wrap_prefix_width = 0; /* If we moved too far back, move IT some lines forward. */ if (it2.vpos > -dvpos) @@ -11452,7 +11461,7 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to, IT.current_x will be incorrectly set to zero at some arbitrary non-zero X coordinate. */ move_it_by_lines (&it, 0); - it.current_x = it.hpos = 0; + it.current_x = it.hpos = it.wrap_prefix_width = 0; if (IT_CHARPOS (it) != start) { void *it1data = NULL; @@ -11505,7 +11514,7 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to, /* If FROM is on a newline, pretend that we start at the beginning of the next line, because the newline takes no place on display. */ if (FETCH_BYTE (start) == '\n') - it.current_x = 0; + it.current_x = 0, it.wrap_prefix_width = 0; if (!NILP (x_limit)) { it.last_visible_x = max_x; @@ -14417,7 +14426,7 @@ display_tab_bar_line (struct it *it, int height) row->truncated_on_left_p = false; row->truncated_on_right_p = false; - it->current_x = it->hpos = 0; + it->current_x = it->hpos = it->wrap_prefix_width = 0; it->current_y += row->height; ++it->vpos; ++it->glyph_row; @@ -15441,7 +15450,7 @@ display_tool_bar_line (struct it *it, int height) row->truncated_on_left_p = false; row->truncated_on_right_p = false; - it->current_x = it->hpos = 0; + it->current_x = it->hpos = it->wrap_prefix_width = 0; it->current_y += row->height; ++it->vpos; ++it->glyph_row; @@ -17141,6 +17150,7 @@ redisplay_internal (void) NULL, DEFAULT_FACE_ID); it.current_x = this_line_start_x; it.current_y = this_line_y; + it.wrap_prefix_width = 0; it.vpos = this_line_vpos; if (current_buffer->long_line_optimizations_p @@ -20587,7 +20597,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) it.current_y = 0; } - it.current_x = it.hpos = 0; + it.current_x = it.wrap_prefix_width = it.hpos = 0; /* Set the window start position here explicitly, to avoid an infinite loop in case the functions in window-scroll-functions @@ -22555,7 +22565,7 @@ try_window_id (struct window *w) /* We may start in a continuation line. If so, we have to get the right continuation_lines_width and current_x. */ it.continuation_lines_width = last_row->continuation_lines_width; - it.hpos = it.current_x = 0; + it.hpos = it.current_x = it.wrap_prefix_width = 0; /* Display the rest of the lines at the window end. */ it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos); @@ -23160,6 +23170,7 @@ insert_left_trunc_glyphs (struct it *it) /* Get the truncation glyphs. */ truncate_it = *it; truncate_it.current_x = 0; + truncate_it.wrap_prefix_width = 0; truncate_it.face_id = DEFAULT_FACE_ID; truncate_it.glyph_row = &scratch_glyph_row; truncate_it.area = TEXT_AREA; @@ -23922,6 +23933,10 @@ extend_face_to_end_of_line (struct it *it) for (it->current_x = 0; g < e; g++) it->current_x += g->pixel_width; + if (it->continuation_lines_width + && it->string_from_prefix_prop_p) + it->wrap_prefix_width = it->current_x; + it->area = LEFT_MARGIN_AREA; it->face_id = default_face->id; while (it->glyph_row->used[LEFT_MARGIN_AREA] @@ -25064,7 +25079,10 @@ display_line (struct it *it, int cursor_vpos) if (it->current_x < it->first_visible_x && (move_result == MOVE_NEWLINE_OR_CR || move_result == MOVE_POS_MATCH_OR_ZV)) - it->current_x = it->first_visible_x; + { + it->current_x = it->first_visible_x; + it->wrap_prefix_width = 0; + } /* In case move_it_in_display_line_to above "produced" the line number. */ @@ -25921,7 +25939,7 @@ display_line (struct it *it, int cursor_vpos) HPOS) = (0 0). Vertical positions are incremented. As a convenience for the caller, IT->glyph_row is set to the next row to be used. */ - it->current_x = it->hpos = 0; + it->wrap_prefix_width = it->current_x = it->hpos = 0; it->current_y += row->height; /* Restore the first and last visible X if we adjusted them for current-line hscrolling. */ @@ -26400,7 +26418,7 @@ Value is the new character position of point. */) { struct text_pos pt; struct it it; - int pt_x, target_x, pixel_width, pt_vpos; + int pt_x, pt_wrap_prefix_x, target_x, pixel_width, pt_vpos; bool at_eol_p; bool overshoot_expected = false; bool target_is_eol_p = false; @@ -26432,6 +26450,7 @@ Value is the new character position of point. */) reseat: reseat_at_previous_visible_line_start (&it); it.current_x = it.hpos = it.current_y = it.vpos = 0; + it.wrap_prefix_width = 0; if (IT_CHARPOS (it) != PT) { move_it_to (&it, overshoot_expected ? PT - 1 : PT, @@ -26450,6 +26469,7 @@ Value is the new character position of point. */) move_it_in_display_line (&it, PT, -1, MOVE_TO_POS); } pt_x = it.current_x; + pt_wrap_prefix_x = it.wrap_prefix_width; pt_vpos = it.vpos; if (dir > 0 || overshoot_expected) { @@ -26464,10 +26484,11 @@ Value is the new character position of point. */) it.glyph_row = NULL; PRODUCE_GLYPHS (&it); /* compute it.pixel_width */ it.glyph_row = row; - /* PRODUCE_GLYPHS advances it.current_x, so we must restore - it, lest it will become out of sync with it's buffer + /* PRODUCE_GLYPHS advances it.current_x, so it must be + restored, lest it become out of sync with its buffer position. */ it.current_x = pt_x; + it.wrap_prefix_width = pt_wrap_prefix_x; } else at_eol_p = ITERATOR_AT_END_OF_LINE_P (&it); @@ -26512,6 +26533,7 @@ Value is the new character position of point. */) it.last_visible_x = DISP_INFINITY; reseat_at_previous_visible_line_start (&it); it.current_x = it.current_y = it.hpos = 0; + it.wrap_prefix_width = 0; if (pt_vpos != 0) move_it_by_lines (&it, pt_vpos); } @@ -32659,7 +32681,19 @@ gui_produce_glyphs (struct it *it) if (font->space_width > 0) { int tab_width = it->tab_width * font->space_width; - int x = it->current_x + it->continuation_lines_width; + /* wrap-prefix strings are prepended to continuation + lines, so the width of tab characters inside should + be computed from the start of this screen line rather + than as a product of the total width of the physical + line being wrapped. */ + int x = it->current_x + (it->string_from_prefix_prop_p + /* Subtract the width of the + prefix from it->current_x if + it exists. */ + ? 0 : (it->continuation_lines_width + ? (it->continuation_lines_width + - it->wrap_prefix_width) + : 0)); int x0 = x; /* Adjust for line numbers, if needed. */ if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p) @@ -33130,7 +33164,13 @@ gui_produce_glyphs (struct it *it) because this isn't true for images with `:ascent 100'. */ eassert (it->ascent >= 0 && it->descent >= 0); if (it->area == TEXT_AREA) - it->current_x += it->pixel_width; + { + it->current_x += it->pixel_width; + + if (it->continuation_lines_width + && it->string_from_prefix_prop_p) + it->wrap_prefix_width = it->current_x; + } if (extra_line_spacing > 0) {