diff options
| author | Eli Zaretskii | 2017-05-20 10:32:58 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2017-05-20 10:32:58 +0300 |
| commit | 1cbbecee66617a232d6ed361f842128564599e70 (patch) | |
| tree | 5aad7c7c353ab174d40cf218cd2fe9d98bef3303 /src | |
| parent | 7d00410af69b3cbbf0e8fc9765f3bf9f5616286d (diff) | |
| download | emacs-1cbbecee66617a232d6ed361f842128564599e70.tar.gz emacs-1cbbecee66617a232d6ed361f842128564599e70.zip | |
Fix automatic hscrolling of only the current line
* src/xdisp.c (display_line): When hscrolling only the current
line, increment iterator's first_visible_x and last_visible_x
values to account for the hscroll. This propagates the hscroll
effect on the iterator geometry all the way down to the
subroutines called by display_line, and avoids scrolling bugs
under large hscroll values. (Bug#26994)
Diffstat (limited to 'src')
| -rw-r--r-- | src/xdisp.c | 70 |
1 files changed, 39 insertions, 31 deletions
diff --git a/src/xdisp.c b/src/xdisp.c index 96bc1a5e032..c0e821a934c 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -20671,8 +20671,11 @@ display_line (struct it *it, int cursor_vpos) | |||
| 20671 | ptrdiff_t min_pos = ZV + 1, max_pos = 0; | 20671 | ptrdiff_t min_pos = ZV + 1, max_pos = 0; |
| 20672 | ptrdiff_t min_bpos UNINIT, max_bpos UNINIT; | 20672 | ptrdiff_t min_bpos UNINIT, max_bpos UNINIT; |
| 20673 | bool pending_handle_line_prefix = false; | 20673 | bool pending_handle_line_prefix = false; |
| 20674 | bool hscroll_this_line = (cursor_vpos >= 0 && it->vpos == cursor_vpos | ||
| 20675 | && hscrolling_current_line_p (it->w)); | ||
| 20674 | int first_visible_x = it->first_visible_x; | 20676 | int first_visible_x = it->first_visible_x; |
| 20675 | int last_visible_x = it->last_visible_x; | 20677 | int last_visible_x = it->last_visible_x; |
| 20678 | int x_incr = 0; | ||
| 20676 | 20679 | ||
| 20677 | /* We always start displaying at hpos zero even if hscrolled. */ | 20680 | /* We always start displaying at hpos zero even if hscrolled. */ |
| 20678 | eassert (it->hpos == 0 && it->current_x == 0); | 20681 | eassert (it->hpos == 0 && it->current_x == 0); |
| @@ -20704,25 +20707,23 @@ display_line (struct it *it, int cursor_vpos) | |||
| 20704 | 20707 | ||
| 20705 | /* If we are going to display the cursor's line, account for the | 20708 | /* If we are going to display the cursor's line, account for the |
| 20706 | hscroll of that line. */ | 20709 | hscroll of that line. */ |
| 20707 | if (cursor_vpos >= 0 && it->vpos == cursor_vpos | 20710 | if (hscroll_this_line) |
| 20708 | && hscrolling_current_line_p (it->w)) | 20711 | x_incr = window_hscroll_limited (it->w, it->f) * FRAME_COLUMN_WIDTH (it->f); |
| 20709 | { | ||
| 20710 | int x_incr = | ||
| 20711 | window_hscroll_limited (it->w, it->f) * FRAME_COLUMN_WIDTH (it->f); | ||
| 20712 | |||
| 20713 | first_visible_x += x_incr; | ||
| 20714 | last_visible_x += x_incr; | ||
| 20715 | } | ||
| 20716 | 20712 | ||
| 20717 | /* Move over display elements that are not visible because we are | 20713 | /* Move over display elements that are not visible because we are |
| 20718 | hscrolled. This may stop at an x-position < first_visible_x | 20714 | hscrolled. This may stop at an x-position < first_visible_x |
| 20719 | if the first glyph is partially visible or if we hit a line end. */ | 20715 | if the first glyph is partially visible or if we hit a line end. */ |
| 20720 | if (it->current_x < first_visible_x) | 20716 | if (it->current_x < it->first_visible_x + x_incr) |
| 20721 | { | 20717 | { |
| 20722 | enum move_it_result move_result; | 20718 | enum move_it_result move_result; |
| 20723 | 20719 | ||
| 20724 | this_line_min_pos = row->start.pos; | 20720 | this_line_min_pos = row->start.pos; |
| 20725 | move_result = move_it_in_display_line_to (it, ZV, first_visible_x, | 20721 | if (hscroll_this_line) |
| 20722 | { | ||
| 20723 | it->first_visible_x += x_incr; | ||
| 20724 | it->last_visible_x += x_incr; | ||
| 20725 | } | ||
| 20726 | move_result = move_it_in_display_line_to (it, ZV, it->first_visible_x, | ||
| 20726 | MOVE_TO_POS | MOVE_TO_X); | 20727 | MOVE_TO_POS | MOVE_TO_X); |
| 20727 | /* If we are under a large hscroll, move_it_in_display_line_to | 20728 | /* If we are under a large hscroll, move_it_in_display_line_to |
| 20728 | could hit the end of the line without reaching | 20729 | could hit the end of the line without reaching |
| @@ -20730,10 +20731,10 @@ display_line (struct it *it, int cursor_vpos) | |||
| 20730 | especially important on a TTY, where we will call | 20731 | especially important on a TTY, where we will call |
| 20731 | extend_face_to_end_of_line, which needs to know how many | 20732 | extend_face_to_end_of_line, which needs to know how many |
| 20732 | blank glyphs to produce. */ | 20733 | blank glyphs to produce. */ |
| 20733 | if (it->current_x < first_visible_x | 20734 | if (it->current_x < it->first_visible_x |
| 20734 | && (move_result == MOVE_NEWLINE_OR_CR | 20735 | && (move_result == MOVE_NEWLINE_OR_CR |
| 20735 | || move_result == MOVE_POS_MATCH_OR_ZV)) | 20736 | || move_result == MOVE_POS_MATCH_OR_ZV)) |
| 20736 | it->current_x = first_visible_x; | 20737 | it->current_x = it->first_visible_x; |
| 20737 | 20738 | ||
| 20738 | /* Record the smallest positions seen while we moved over | 20739 | /* Record the smallest positions seen while we moved over |
| 20739 | display elements that are not visible. This is needed by | 20740 | display elements that are not visible. This is needed by |
| @@ -20927,7 +20928,7 @@ display_line (struct it *it, int cursor_vpos) | |||
| 20927 | if (/* Not a newline. */ | 20928 | if (/* Not a newline. */ |
| 20928 | nglyphs > 0 | 20929 | nglyphs > 0 |
| 20929 | /* Glyphs produced fit entirely in the line. */ | 20930 | /* Glyphs produced fit entirely in the line. */ |
| 20930 | && it->current_x < last_visible_x) | 20931 | && it->current_x < it->last_visible_x) |
| 20931 | { | 20932 | { |
| 20932 | it->hpos += nglyphs; | 20933 | it->hpos += nglyphs; |
| 20933 | row->ascent = max (row->ascent, it->max_ascent); | 20934 | row->ascent = max (row->ascent, it->max_ascent); |
| @@ -20937,13 +20938,13 @@ display_line (struct it *it, int cursor_vpos) | |||
| 20937 | it->max_phys_ascent + it->max_phys_descent); | 20938 | it->max_phys_ascent + it->max_phys_descent); |
| 20938 | row->extra_line_spacing = max (row->extra_line_spacing, | 20939 | row->extra_line_spacing = max (row->extra_line_spacing, |
| 20939 | it->max_extra_line_spacing); | 20940 | it->max_extra_line_spacing); |
| 20940 | if (it->current_x - it->pixel_width < first_visible_x | 20941 | if (it->current_x - it->pixel_width < it->first_visible_x |
| 20941 | /* In R2L rows, we arrange in extend_face_to_end_of_line | 20942 | /* In R2L rows, we arrange in extend_face_to_end_of_line |
| 20942 | to add a right offset to the line, by a suitable | 20943 | to add a right offset to the line, by a suitable |
| 20943 | change to the stretch glyph that is the leftmost | 20944 | change to the stretch glyph that is the leftmost |
| 20944 | glyph of the line. */ | 20945 | glyph of the line. */ |
| 20945 | && !row->reversed_p) | 20946 | && !row->reversed_p) |
| 20946 | row->x = x - first_visible_x; | 20947 | row->x = x - it->first_visible_x; |
| 20947 | /* Record the maximum and minimum buffer positions seen so | 20948 | /* Record the maximum and minimum buffer positions seen so |
| 20948 | far in glyphs that will be displayed by this row. */ | 20949 | far in glyphs that will be displayed by this row. */ |
| 20949 | if (it->bidi_p) | 20950 | if (it->bidi_p) |
| @@ -20968,9 +20969,9 @@ display_line (struct it *it, int cursor_vpos) | |||
| 20968 | if (/* Lines are continued. */ | 20969 | if (/* Lines are continued. */ |
| 20969 | it->line_wrap != TRUNCATE | 20970 | it->line_wrap != TRUNCATE |
| 20970 | && (/* Glyph doesn't fit on the line. */ | 20971 | && (/* Glyph doesn't fit on the line. */ |
| 20971 | new_x > last_visible_x | 20972 | new_x > it->last_visible_x |
| 20972 | /* Or it fits exactly on a window system frame. */ | 20973 | /* Or it fits exactly on a window system frame. */ |
| 20973 | || (new_x == last_visible_x | 20974 | || (new_x == it->last_visible_x |
| 20974 | && FRAME_WINDOW_P (it->f) | 20975 | && FRAME_WINDOW_P (it->f) |
| 20975 | && (row->reversed_p | 20976 | && (row->reversed_p |
| 20976 | ? WINDOW_LEFT_FRINGE_WIDTH (it->w) | 20977 | ? WINDOW_LEFT_FRINGE_WIDTH (it->w) |
| @@ -20979,7 +20980,7 @@ display_line (struct it *it, int cursor_vpos) | |||
| 20979 | /* End of a continued line. */ | 20980 | /* End of a continued line. */ |
| 20980 | 20981 | ||
| 20981 | if (it->hpos == 0 | 20982 | if (it->hpos == 0 |
| 20982 | || (new_x == last_visible_x | 20983 | || (new_x == it->last_visible_x |
| 20983 | && FRAME_WINDOW_P (it->f) | 20984 | && FRAME_WINDOW_P (it->f) |
| 20984 | && (row->reversed_p | 20985 | && (row->reversed_p |
| 20985 | ? WINDOW_LEFT_FRINGE_WIDTH (it->w) | 20986 | ? WINDOW_LEFT_FRINGE_WIDTH (it->w) |
| @@ -21122,10 +21123,10 @@ display_line (struct it *it, int cursor_vpos) | |||
| 21122 | ? WINDOW_LEFT_FRINGE_WIDTH (it->w) | 21123 | ? WINDOW_LEFT_FRINGE_WIDTH (it->w) |
| 21123 | : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0) | 21124 | : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0) |
| 21124 | produce_special_glyphs (it, IT_CONTINUATION); | 21125 | produce_special_glyphs (it, IT_CONTINUATION); |
| 21125 | it->continuation_lines_width += last_visible_x; | 21126 | it->continuation_lines_width += it->last_visible_x; |
| 21126 | row->ends_in_middle_of_char_p = true; | 21127 | row->ends_in_middle_of_char_p = true; |
| 21127 | row->continued_p = true; | 21128 | row->continued_p = true; |
| 21128 | glyph->pixel_width = last_visible_x - x; | 21129 | glyph->pixel_width = it->last_visible_x - x; |
| 21129 | it->starts_in_middle_of_char_p = true; | 21130 | it->starts_in_middle_of_char_p = true; |
| 21130 | if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0 | 21131 | if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0 |
| 21131 | || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0) | 21132 | || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0) |
| @@ -21169,7 +21170,7 @@ display_line (struct it *it, int cursor_vpos) | |||
| 21169 | 21170 | ||
| 21170 | break; | 21171 | break; |
| 21171 | } | 21172 | } |
| 21172 | else if (new_x > first_visible_x) | 21173 | else if (new_x > it->first_visible_x) |
| 21173 | { | 21174 | { |
| 21174 | /* Increment number of glyphs actually displayed. */ | 21175 | /* Increment number of glyphs actually displayed. */ |
| 21175 | ++it->hpos; | 21176 | ++it->hpos; |
| @@ -21180,14 +21181,14 @@ display_line (struct it *it, int cursor_vpos) | |||
| 21180 | if (it->bidi_p) | 21181 | if (it->bidi_p) |
| 21181 | RECORD_MAX_MIN_POS (it); | 21182 | RECORD_MAX_MIN_POS (it); |
| 21182 | 21183 | ||
| 21183 | if (x < first_visible_x && !row->reversed_p) | 21184 | if (x < it->first_visible_x && !row->reversed_p) |
| 21184 | /* Glyph is partially visible, i.e. row starts at | 21185 | /* Glyph is partially visible, i.e. row starts at |
| 21185 | negative X position. Don't do that in R2L | 21186 | negative X position. Don't do that in R2L |
| 21186 | rows, where we arrange to add a right offset to | 21187 | rows, where we arrange to add a right offset to |
| 21187 | the line in extend_face_to_end_of_line, by a | 21188 | the line in extend_face_to_end_of_line, by a |
| 21188 | suitable change to the stretch glyph that is | 21189 | suitable change to the stretch glyph that is |
| 21189 | the leftmost glyph of the line. */ | 21190 | the leftmost glyph of the line. */ |
| 21190 | row->x = x - first_visible_x; | 21191 | row->x = x - it->first_visible_x; |
| 21191 | /* When the last glyph of an R2L row only fits | 21192 | /* When the last glyph of an R2L row only fits |
| 21192 | partially on the line, we need to set row->x to a | 21193 | partially on the line, we need to set row->x to a |
| 21193 | negative offset, so that the leftmost glyph is | 21194 | negative offset, so that the leftmost glyph is |
| @@ -21195,12 +21196,12 @@ display_line (struct it *it, int cursor_vpos) | |||
| 21195 | going to produce the truncation glyph, this will | 21196 | going to produce the truncation glyph, this will |
| 21196 | be taken care of in produce_special_glyphs. */ | 21197 | be taken care of in produce_special_glyphs. */ |
| 21197 | if (row->reversed_p | 21198 | if (row->reversed_p |
| 21198 | && new_x > last_visible_x | 21199 | && new_x > it->last_visible_x |
| 21199 | && !(it->line_wrap == TRUNCATE | 21200 | && !(it->line_wrap == TRUNCATE |
| 21200 | && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0)) | 21201 | && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0)) |
| 21201 | { | 21202 | { |
| 21202 | eassert (FRAME_WINDOW_P (it->f)); | 21203 | eassert (FRAME_WINDOW_P (it->f)); |
| 21203 | row->x = last_visible_x - new_x; | 21204 | row->x = it->last_visible_x - new_x; |
| 21204 | } | 21205 | } |
| 21205 | } | 21206 | } |
| 21206 | else | 21207 | else |
| @@ -21210,7 +21211,7 @@ display_line (struct it *it, int cursor_vpos) | |||
| 21210 | move_it_in_display_line at the start of this | 21211 | move_it_in_display_line at the start of this |
| 21211 | function, unless the text display area of the | 21212 | function, unless the text display area of the |
| 21212 | window is empty. */ | 21213 | window is empty. */ |
| 21213 | eassert (first_visible_x <= last_visible_x); | 21214 | eassert (it->first_visible_x <= it->last_visible_x); |
| 21214 | } | 21215 | } |
| 21215 | } | 21216 | } |
| 21216 | /* Even if this display element produced no glyphs at all, | 21217 | /* Even if this display element produced no glyphs at all, |
| @@ -21279,8 +21280,8 @@ display_line (struct it *it, int cursor_vpos) | |||
| 21279 | ? WINDOW_LEFT_FRINGE_WIDTH (it->w) | 21280 | ? WINDOW_LEFT_FRINGE_WIDTH (it->w) |
| 21280 | : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) | 21281 | : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) |
| 21281 | || it->what == IT_IMAGE)) | 21282 | || it->what == IT_IMAGE)) |
| 21282 | ? (it->current_x >= last_visible_x) | 21283 | ? (it->current_x >= it->last_visible_x) |
| 21283 | : (it->current_x > last_visible_x))) | 21284 | : (it->current_x > it->last_visible_x))) |
| 21284 | { | 21285 | { |
| 21285 | /* Maybe add truncation glyphs. */ | 21286 | /* Maybe add truncation glyphs. */ |
| 21286 | if (!FRAME_WINDOW_P (it->f) | 21287 | if (!FRAME_WINDOW_P (it->f) |
| @@ -21314,7 +21315,7 @@ display_line (struct it *it, int cursor_vpos) | |||
| 21314 | /* produce_special_glyphs overwrites the last glyph, so | 21315 | /* produce_special_glyphs overwrites the last glyph, so |
| 21315 | we don't want that if we want to keep that last | 21316 | we don't want that if we want to keep that last |
| 21316 | glyph, which means it's an image. */ | 21317 | glyph, which means it's an image. */ |
| 21317 | if (it->current_x > last_visible_x) | 21318 | if (it->current_x > it->last_visible_x) |
| 21318 | { | 21319 | { |
| 21319 | it->current_x = x_before; | 21320 | it->current_x = x_before; |
| 21320 | if (!FRAME_WINDOW_P (it->f)) | 21321 | if (!FRAME_WINDOW_P (it->f)) |
| @@ -21375,7 +21376,7 @@ display_line (struct it *it, int cursor_vpos) | |||
| 21375 | 21376 | ||
| 21376 | /* If line is not empty and hscrolled, maybe insert truncation glyphs | 21377 | /* If line is not empty and hscrolled, maybe insert truncation glyphs |
| 21377 | at the left window margin. */ | 21378 | at the left window margin. */ |
| 21378 | if (first_visible_x | 21379 | if (it->first_visible_x |
| 21379 | && IT_CHARPOS (*it) != CHARPOS (row->start.pos)) | 21380 | && IT_CHARPOS (*it) != CHARPOS (row->start.pos)) |
| 21380 | { | 21381 | { |
| 21381 | if (!FRAME_WINDOW_P (it->f) | 21382 | if (!FRAME_WINDOW_P (it->f) |
| @@ -21503,6 +21504,13 @@ display_line (struct it *it, int cursor_vpos) | |||
| 21503 | row to be used. */ | 21504 | row to be used. */ |
| 21504 | it->current_x = it->hpos = 0; | 21505 | it->current_x = it->hpos = 0; |
| 21505 | it->current_y += row->height; | 21506 | it->current_y += row->height; |
| 21507 | /* Restore the first and last visible X if we adjusted them for | ||
| 21508 | current-line hscrolling. */ | ||
| 21509 | if (hscroll_this_line) | ||
| 21510 | { | ||
| 21511 | it->first_visible_x = first_visible_x; | ||
| 21512 | it->last_visible_x = last_visible_x; | ||
| 21513 | } | ||
| 21506 | SET_TEXT_POS (it->eol_pos, 0, 0); | 21514 | SET_TEXT_POS (it->eol_pos, 0, 0); |
| 21507 | ++it->vpos; | 21515 | ++it->vpos; |
| 21508 | ++it->glyph_row; | 21516 | ++it->glyph_row; |