diff options
| author | Eli Zaretskii | 2018-03-07 20:40:44 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2018-03-07 20:40:44 +0200 |
| commit | 1ac190553886ff20817d3dd218464e2fc6f9e42a (patch) | |
| tree | ce84ae0c548359086f5762d150eaa9673c7fe2ba /src | |
| parent | 4ad214f36c2b1eab4446f9f698ce2588941a7356 (diff) | |
| download | emacs-1ac190553886ff20817d3dd218464e2fc6f9e42a.tar.gz emacs-1ac190553886ff20817d3dd218464e2fc6f9e42a.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/dispextern.h | 10 | ||||
| -rw-r--r-- | src/term.c | 4 | ||||
| -rw-r--r-- | src/xdisp.c | 51 |
3 files changed, 54 insertions, 11 deletions
diff --git a/src/dispextern.h b/src/dispextern.h index 441361b4083..25d51cdd638 100644 --- a/src/dispextern.h +++ b/src/dispextern.h | |||
| @@ -2462,6 +2462,10 @@ struct it | |||
| 2462 | descent/ascent (line-height property). Reset after this glyph. */ | 2462 | descent/ascent (line-height property). Reset after this glyph. */ |
| 2463 | bool_bf constrain_row_ascent_descent_p : 1; | 2463 | bool_bf constrain_row_ascent_descent_p : 1; |
| 2464 | 2464 | ||
| 2465 | /* If true, glyphs for line number display were already produced for | ||
| 2466 | the current row. */ | ||
| 2467 | bool_bf line_number_produced_p : 1; | ||
| 2468 | |||
| 2465 | enum line_wrap_method line_wrap; | 2469 | enum line_wrap_method line_wrap; |
| 2466 | 2470 | ||
| 2467 | /* The ID of the default face to use. One of DEFAULT_FACE_ID, | 2471 | /* The ID of the default face to use. One of DEFAULT_FACE_ID, |
| @@ -2641,6 +2645,12 @@ struct it | |||
| 2641 | /* The line number of point's line, or zero if not computed yet. */ | 2645 | /* The line number of point's line, or zero if not computed yet. */ |
| 2642 | ptrdiff_t pt_lnum; | 2646 | ptrdiff_t pt_lnum; |
| 2643 | 2647 | ||
| 2648 | /* Number of pixels to offset tab stops due to width fixup of the | ||
| 2649 | first glyph that crosses first_visible_x. This is only needed on | ||
| 2650 | GUI frames, only when display-line-numbers is in effect, and only | ||
| 2651 | in hscrolled windows. */ | ||
| 2652 | int tab_offset; | ||
| 2653 | |||
| 2644 | /* Left fringe bitmap number (enum fringe_bitmap_type). */ | 2654 | /* Left fringe bitmap number (enum fringe_bitmap_type). */ |
| 2645 | unsigned left_user_fringe_bitmap : FRINGE_ID_BITS; | 2655 | unsigned left_user_fringe_bitmap : FRINGE_ID_BITS; |
| 2646 | 2656 | ||
diff --git a/src/term.c b/src/term.c index 64a2b7e5519..8be5fb319b0 100644 --- a/src/term.c +++ b/src/term.c | |||
| @@ -1591,13 +1591,13 @@ produce_glyphs (struct it *it) | |||
| 1591 | + it->continuation_lines_width); | 1591 | + it->continuation_lines_width); |
| 1592 | int x0 = absolute_x; | 1592 | int x0 = absolute_x; |
| 1593 | /* Adjust for line numbers. */ | 1593 | /* Adjust for line numbers. */ |
| 1594 | if (!NILP (Vdisplay_line_numbers)) | 1594 | if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p) |
| 1595 | absolute_x -= it->lnum_pixel_width; | 1595 | absolute_x -= it->lnum_pixel_width; |
| 1596 | int next_tab_x | 1596 | int next_tab_x |
| 1597 | = (((1 + absolute_x + it->tab_width - 1) | 1597 | = (((1 + absolute_x + it->tab_width - 1) |
| 1598 | / it->tab_width) | 1598 | / it->tab_width) |
| 1599 | * it->tab_width); | 1599 | * it->tab_width); |
| 1600 | if (!NILP (Vdisplay_line_numbers)) | 1600 | if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p) |
| 1601 | next_tab_x += it->lnum_pixel_width; | 1601 | next_tab_x += it->lnum_pixel_width; |
| 1602 | int nspaces; | 1602 | int nspaces; |
| 1603 | 1603 | ||
diff --git a/src/xdisp.c b/src/xdisp.c index 9170d6b777f..23a10659b04 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -8716,8 +8716,12 @@ move_it_in_display_line_to (struct it *it, | |||
| 8716 | 8716 | ||
| 8717 | if (it->hpos == 0) | 8717 | if (it->hpos == 0) |
| 8718 | { | 8718 | { |
| 8719 | /* If line numbers are being displayed, produce a line number. */ | 8719 | /* If line numbers are being displayed, produce a line number. |
| 8720 | if (should_produce_line_number (it)) | 8720 | But don't do that if we are to reach first_visible_x, because |
| 8721 | line numbers are not relevant to stuff that is not visible on | ||
| 8722 | display. */ | ||
| 8723 | if (!((op && MOVE_TO_X) && to_x == it->first_visible_x) | ||
| 8724 | && should_produce_line_number (it)) | ||
| 8721 | { | 8725 | { |
| 8722 | if (it->current_x == it->first_visible_x) | 8726 | if (it->current_x == it->first_visible_x) |
| 8723 | maybe_produce_line_number (it); | 8727 | maybe_produce_line_number (it); |
| @@ -21173,6 +21177,8 @@ maybe_produce_line_number (struct it *it) | |||
| 21173 | it->max_phys_descent = max (it->max_phys_descent, tem_it.max_phys_descent); | 21177 | it->max_phys_descent = max (it->max_phys_descent, tem_it.max_phys_descent); |
| 21174 | } | 21178 | } |
| 21175 | 21179 | ||
| 21180 | it->line_number_produced_p = true; | ||
| 21181 | |||
| 21176 | bidi_unshelve_cache (itdata, false); | 21182 | bidi_unshelve_cache (itdata, false); |
| 21177 | } | 21183 | } |
| 21178 | 21184 | ||
| @@ -21290,6 +21296,8 @@ display_line (struct it *it, int cursor_vpos) | |||
| 21290 | row->displays_text_p = true; | 21296 | row->displays_text_p = true; |
| 21291 | row->starts_in_middle_of_char_p = it->starts_in_middle_of_char_p; | 21297 | row->starts_in_middle_of_char_p = it->starts_in_middle_of_char_p; |
| 21292 | it->starts_in_middle_of_char_p = false; | 21298 | it->starts_in_middle_of_char_p = false; |
| 21299 | it->tab_offset = 0; | ||
| 21300 | it->line_number_produced_p = false; | ||
| 21293 | 21301 | ||
| 21294 | /* Arrange the overlays nicely for our purposes. Usually, we call | 21302 | /* Arrange the overlays nicely for our purposes. Usually, we call |
| 21295 | display_line on only one line at a time, in which case this | 21303 | display_line on only one line at a time, in which case this |
| @@ -21334,6 +21342,10 @@ display_line (struct it *it, int cursor_vpos) | |||
| 21334 | || move_result == MOVE_POS_MATCH_OR_ZV)) | 21342 | || move_result == MOVE_POS_MATCH_OR_ZV)) |
| 21335 | it->current_x = it->first_visible_x; | 21343 | it->current_x = it->first_visible_x; |
| 21336 | 21344 | ||
| 21345 | /* In case move_it_in_display_line_to above "produced" the line | ||
| 21346 | number. */ | ||
| 21347 | it->line_number_produced_p = false; | ||
| 21348 | |||
| 21337 | /* Record the smallest positions seen while we moved over | 21349 | /* Record the smallest positions seen while we moved over |
| 21338 | display elements that are not visible. This is needed by | 21350 | display elements that are not visible. This is needed by |
| 21339 | redisplay_internal for optimizing the case where the cursor | 21351 | redisplay_internal for optimizing the case where the cursor |
| @@ -21553,6 +21565,10 @@ display_line (struct it *it, int cursor_vpos) | |||
| 21553 | row->extra_line_spacing = max (row->extra_line_spacing, | 21565 | row->extra_line_spacing = max (row->extra_line_spacing, |
| 21554 | it->max_extra_line_spacing); | 21566 | it->max_extra_line_spacing); |
| 21555 | if (it->current_x - it->pixel_width < it->first_visible_x | 21567 | if (it->current_x - it->pixel_width < it->first_visible_x |
| 21568 | /* When line numbers are displayed, row->x should not be | ||
| 21569 | offset, as the first glyph after the line number can | ||
| 21570 | never be partially visible. */ | ||
| 21571 | && !line_number_needed | ||
| 21556 | /* In R2L rows, we arrange in extend_face_to_end_of_line | 21572 | /* In R2L rows, we arrange in extend_face_to_end_of_line |
| 21557 | to add a right offset to the line, by a suitable | 21573 | to add a right offset to the line, by a suitable |
| 21558 | change to the stretch glyph that is the leftmost | 21574 | change to the stretch glyph that is the leftmost |
| @@ -21794,7 +21810,8 @@ display_line (struct it *it, int cursor_vpos) | |||
| 21794 | if (it->bidi_p) | 21810 | if (it->bidi_p) |
| 21795 | RECORD_MAX_MIN_POS (it); | 21811 | RECORD_MAX_MIN_POS (it); |
| 21796 | 21812 | ||
| 21797 | if (x < it->first_visible_x && !row->reversed_p) | 21813 | if (x < it->first_visible_x && !row->reversed_p |
| 21814 | && !line_number_needed) | ||
| 21798 | /* Glyph is partially visible, i.e. row starts at | 21815 | /* Glyph is partially visible, i.e. row starts at |
| 21799 | negative X position. Don't do that in R2L | 21816 | negative X position. Don't do that in R2L |
| 21800 | rows, where we arrange to add a right offset to | 21817 | rows, where we arrange to add a right offset to |
| @@ -21810,6 +21827,7 @@ display_line (struct it *it, int cursor_vpos) | |||
| 21810 | be taken care of in produce_special_glyphs. */ | 21827 | be taken care of in produce_special_glyphs. */ |
| 21811 | if (row->reversed_p | 21828 | if (row->reversed_p |
| 21812 | && new_x > it->last_visible_x | 21829 | && new_x > it->last_visible_x |
| 21830 | && !line_number_needed | ||
| 21813 | && !(it->line_wrap == TRUNCATE | 21831 | && !(it->line_wrap == TRUNCATE |
| 21814 | && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0)) | 21832 | && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0)) |
| 21815 | { | 21833 | { |
| @@ -28274,8 +28292,14 @@ x_produce_glyphs (struct it *it) | |||
| 28274 | int x = it->current_x + it->continuation_lines_width; | 28292 | int x = it->current_x + it->continuation_lines_width; |
| 28275 | int x0 = x; | 28293 | int x0 = x; |
| 28276 | /* Adjust for line numbers, if needed. */ | 28294 | /* Adjust for line numbers, if needed. */ |
| 28277 | if (!NILP (Vdisplay_line_numbers) && x0 >= it->lnum_pixel_width) | 28295 | if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p) |
| 28278 | x -= it->lnum_pixel_width; | 28296 | { |
| 28297 | x -= it->lnum_pixel_width; | ||
| 28298 | /* Restore the original TAB width, if required. */ | ||
| 28299 | if (x + it->tab_offset >= it->first_visible_x) | ||
| 28300 | x += it->tab_offset; | ||
| 28301 | } | ||
| 28302 | |||
| 28279 | int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width; | 28303 | int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width; |
| 28280 | 28304 | ||
| 28281 | /* If the distance from the current position to the next tab | 28305 | /* If the distance from the current position to the next tab |
| @@ -28283,10 +28307,19 @@ x_produce_glyphs (struct it *it) | |||
| 28283 | tab stop after that. */ | 28307 | tab stop after that. */ |
| 28284 | if (next_tab_x - x < font->space_width) | 28308 | if (next_tab_x - x < font->space_width) |
| 28285 | next_tab_x += tab_width; | 28309 | next_tab_x += tab_width; |
| 28286 | if (!NILP (Vdisplay_line_numbers) && x0 >= it->lnum_pixel_width) | 28310 | if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p) |
| 28287 | next_tab_x += (it->lnum_pixel_width | 28311 | { |
| 28288 | - ((it->w->hscroll * font->space_width) | 28312 | next_tab_x += it->lnum_pixel_width; |
| 28289 | % tab_width)); | 28313 | /* If the line is hscrolled, and the TAB starts before |
| 28314 | the first visible pixel, simulate negative row->x. */ | ||
| 28315 | if (x < it->first_visible_x) | ||
| 28316 | { | ||
| 28317 | next_tab_x -= it->first_visible_x - x; | ||
| 28318 | it->tab_offset = it->first_visible_x - x; | ||
| 28319 | } | ||
| 28320 | else | ||
| 28321 | next_tab_x -= it->tab_offset; | ||
| 28322 | } | ||
| 28290 | 28323 | ||
| 28291 | it->pixel_width = next_tab_x - x0; | 28324 | it->pixel_width = next_tab_x - x0; |
| 28292 | it->nglyphs = 1; | 28325 | it->nglyphs = 1; |