aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2017-05-20 10:32:58 +0300
committerEli Zaretskii2017-05-20 10:32:58 +0300
commit1cbbecee66617a232d6ed361f842128564599e70 (patch)
tree5aad7c7c353ab174d40cf218cd2fe9d98bef3303 /src
parent7d00410af69b3cbbf0e8fc9765f3bf9f5616286d (diff)
downloademacs-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.c70
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;