aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGerd Moellmann2001-05-03 16:19:16 +0000
committerGerd Moellmann2001-05-03 16:19:16 +0000
commit27d16f056bc557edcbdcc0ba8736ca63bf7331c6 (patch)
tree89d78602085b4469ba23d012b0aed775ca27a180 /src
parent768e4b745dab9219c125de258f793ca31fa61b72 (diff)
downloademacs-27d16f056bc557edcbdcc0ba8736ca63bf7331c6.tar.gz
emacs-27d16f056bc557edcbdcc0ba8736ca63bf7331c6.zip
(try_window_id): Cases of changes all in front of
the window start or all below the window end mostly rewritten. (redisplay_window): Move the tests if try_window_id is applicable to try_window_id. (GIVE_UP): New macro.
Diffstat (limited to 'src')
-rw-r--r--src/xdisp.c244
1 files changed, 159 insertions, 85 deletions
diff --git a/src/xdisp.c b/src/xdisp.c
index 5fc7c5de47c..0f7adb3d0e7 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -9986,36 +9986,10 @@ redisplay_window (window, just_this_one_p)
9986 goto recenter; 9986 goto recenter;
9987 } 9987 }
9988 9988
9989 /* Try scrolling with try_window_id. */ 9989 /* Try scrolling with try_window_id. Value is > 0 if update has
9990 else if (/* Windows and buffers haven't changed. */ 9990 been done, it is -1 if we know that the same window start will
9991 !windows_or_buffers_changed 9991 not work. It is 0 if unsuccessful for some other reason. */
9992 /* Window must be either use window-based redisplay or 9992 else if ((tem = try_window_id (w)) != 0)
9993 be full width. */
9994 && (FRAME_WINDOW_P (f)
9995 || (line_ins_del_ok && WINDOW_FULL_WIDTH_P (w)))
9996 && !MINI_WINDOW_P (w)
9997 /* Point is not known NOT to appear in window. */
9998 && PT >= CHARPOS (startp)
9999 && XFASTINT (w->last_modified)
10000 /* Window is not hscrolled. */
10001 && XFASTINT (w->hscroll) == 0
10002 /* Selective display has not changed. */
10003 && !current_buffer->clip_changed
10004 /* Current matrix is up to date. */
10005 && !NILP (w->window_end_valid)
10006 /* Can't use this case if highlighting a region because
10007 a cursor movement will do more than just set the cursor. */
10008 && !(!NILP (Vtransient_mark_mode)
10009 && !NILP (current_buffer->mark_active))
10010 && NILP (w->region_showing)
10011 && NILP (Vshow_trailing_whitespace)
10012 /* Overlay arrow position and string not changed. */
10013 && EQ (last_arrow_position, COERCE_MARKER (Voverlay_arrow_position))
10014 && EQ (last_arrow_string, Voverlay_arrow_string)
10015 /* Value is > 0 if update has been done, it is -1 if we
10016 know that the same window start will not work. It is 0
10017 if unsuccessful for some other reason. */
10018 && (tem = try_window_id (w)) != 0)
10019 { 9993 {
10020#if GLYPH_DEBUG 9994#if GLYPH_DEBUG
10021 debug_method_add (w, "try_window_id %d", tem); 9995 debug_method_add (w, "try_window_id %d", tem);
@@ -11108,15 +11082,78 @@ try_window_id (w)
11108 int first_unchanged_at_end_vpos = 0; 11082 int first_unchanged_at_end_vpos = 0;
11109 struct glyph_row *last_text_row, *last_text_row_at_end; 11083 struct glyph_row *last_text_row, *last_text_row_at_end;
11110 struct text_pos start; 11084 struct text_pos start;
11085 int first_changed_charpos, last_changed_charpos;
11111 11086
11087 /* This is handy for debugging. */
11088#if 0
11089#define GIVE_UP(X) \
11090 do { \
11091 fprintf (stderr, "try_window_id give up %d\n", (X)); \
11092 return 0; \
11093 } while (0)
11094#else
11095 #define GIVE_UP(X) return 0
11096#endif
11097
11112 SET_TEXT_POS_FROM_MARKER (start, w->start); 11098 SET_TEXT_POS_FROM_MARKER (start, w->start);
11113 11099
11114 /* Check pre-conditions. Window end must be valid, otherwise 11100 /* Don't use this for mini-windows because these can show
11115 the current matrix would not be up to date. */ 11101 messages and mini-buffers, and we don't handle that here. */
11116 xassert (!NILP (w->window_end_valid)); 11102 if (MINI_WINDOW_P (w))
11117 xassert (FRAME_WINDOW_P (XFRAME (w->frame)) 11103 GIVE_UP (1);
11118 || (line_ins_del_ok && WINDOW_FULL_WIDTH_P (w))); 11104
11105 /* This flag is used to prevent redisplay optimizations. */
11106 if (windows_or_buffers_changed)
11107 GIVE_UP (2);
11108
11109 /* Narrowing has not changed. This flag is also set to prevent
11110 redisplay optimizations. It would be nice to further
11111 reduce the number of cases where this prevents try_window_id. */
11112 if (current_buffer->clip_changed)
11113 GIVE_UP (3);
11114
11115 /* Window must either use window-based redisplay or be full width. */
11116 if (!FRAME_WINDOW_P (f)
11117 && (!line_ins_del_ok
11118 || !WINDOW_FULL_WIDTH_P (w)))
11119 GIVE_UP (4);
11120
11121 /* Point is not known NOT to appear in W. */
11122 if (PT < CHARPOS (start))
11123 GIVE_UP (5);
11124
11125 /* Another way to prevent redisplay optimizations. */
11126 if (XFASTINT (w->last_modified) == 0)
11127 GIVE_UP (6);
11128
11129 /* Window is not hscrolled. */
11130 if (XFASTINT (w->hscroll) != 0)
11131 GIVE_UP (7);
11132
11133 /* Display wasn't paused. */
11134 if (NILP (w->window_end_valid))
11135 GIVE_UP (8);
11136
11137 /* Can't use this if highlighting a region because a cursor movement
11138 will do more than just set the cursor. */
11139 if (!NILP (Vtransient_mark_mode)
11140 && !NILP (current_buffer->mark_active))
11141 GIVE_UP (9);
11142
11143 /* Likewise if highlighting trailing whitespace. */
11144 if (!NILP (Vshow_trailing_whitespace))
11145 GIVE_UP (11);
11146
11147 /* Likewise if showing a region. */
11148 if (!NILP (w->region_showing))
11149 GIVE_UP (10);
11150
11151 /* Can use this if overlay arrow position and or string have changed. */
11152 if (!EQ (last_arrow_position, COERCE_MARKER (Voverlay_arrow_position))
11153 || !EQ (last_arrow_string, Voverlay_arrow_string))
11154 GIVE_UP (12);
11119 11155
11156
11120 /* Make sure beg_unchanged and end_unchanged are up to date. Do it 11157 /* Make sure beg_unchanged and end_unchanged are up to date. Do it
11121 only if buffer has really changed. The reason is that the gap is 11158 only if buffer has really changed. The reason is that the gap is
11122 initially at Z for freshly visited files. The code below would 11159 initially at Z for freshly visited files. The code below would
@@ -11131,72 +11168,107 @@ try_window_id (w)
11131 END_UNCHANGED = Z - GPT; 11168 END_UNCHANGED = Z - GPT;
11132 } 11169 }
11133 11170
11171 /* The position of the first and last character that has been changed. */
11172 first_changed_charpos = BEG + BEG_UNCHANGED;
11173 last_changed_charpos = Z - END_UNCHANGED;
11174
11134 /* If window starts after a line end, and the last change is in 11175 /* If window starts after a line end, and the last change is in
11135 front of that newline, then changes don't affect the display. 11176 front of that newline, then changes don't affect the display.
11136 This case happens with stealth-fontification. Note that although 11177 This case happens with stealth-fontification. Note that although
11137 the display is unchanged, glyph positions in the matrix have to 11178 the display is unchanged, glyph positions in the matrix have to
11138 be adjusted, of course. */ 11179 be adjusted, of course. */
11139 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); 11180 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
11140 if (CHARPOS (start) > BEGV 11181 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
11141 && Z - END_UNCHANGED < CHARPOS (start) - 1 11182 && ((first_changed_charpos < CHARPOS (start)
11142 && FETCH_BYTE (BYTEPOS (start) - 1) == '\n' 11183 && CHARPOS (start) == BEGV)
11143 && PT < MATRIX_ROW_END_CHARPOS (row)) 11184 || (first_changed_charpos < CHARPOS (start) - 1
11144 { 11185 && FETCH_BYTE (BYTEPOS (start) - 1) == '\n')))
11145 struct glyph_row *r0 = MATRIX_FIRST_TEXT_ROW (current_matrix); 11186 {
11146 int delta = CHARPOS (start) - MATRIX_ROW_START_CHARPOS (r0); 11187 int Z_old, delta, Z_BYTE_old, delta_bytes;
11147 int delta_bytes = BYTEPOS (start) - MATRIX_ROW_START_BYTEPOS (r0); 11188 struct glyph_row *r0;
11148 11189
11149 if (delta || delta_bytes) 11190 /* Compute how many chars/bytes have been added to or removed
11150 { 11191 from the buffer. */
11151 struct glyph_row *r1 = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w); 11192 Z_old = MATRIX_ROW_END_CHARPOS (row) + XFASTINT (w->window_end_pos);
11152 increment_matrix_positions (w->current_matrix, 11193 Z_BYTE_old = MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
11153 MATRIX_ROW_VPOS (r0, current_matrix), 11194 delta = Z - Z_old;
11154 MATRIX_ROW_VPOS (r1, current_matrix), 11195 delta_bytes = Z_BYTE - Z_BYTE_old;
11155 delta, delta_bytes); 11196
11156 } 11197 /* Give up if PT is not in the window. Note that it already has
11157 11198 been checked at the start of try_window_id that PT is not in
11158#if 0 /* If changes are all in front of the window start, the 11199 front of the window start. */
11159 distance of the last displayed glyph from Z hasn't 11200 if (PT >= MATRIX_ROW_END_CHARPOS (row) + delta)
11160 changed. */ 11201 GIVE_UP (13);
11161 w->window_end_pos 11202
11162 = make_number (Z - MATRIX_ROW_END_CHARPOS (row)); 11203 /* If window start is unchanged, we can reuse the whole matrix
11163 w->window_end_bytepos 11204 as is, after adjusting glyph positions. No need to compute
11164 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row); 11205 the window end again, since its offset from Z hasn't changed. */
11165#endif 11206 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
11166 11207 if (CHARPOS (start) == MATRIX_ROW_START_CHARPOS (r0) + delta
11167 row = row_containing_pos (w, PT, r0, NULL); 11208 && BYTEPOS (start) == MATRIX_ROW_START_BYTEPOS (r0) + delta_bytes)
11168 if (row == NULL) 11209 {
11169 return 0; 11210 /* Adjust positions in the glyph matrix. */
11211 if (delta || delta_bytes)
11212 {
11213 struct glyph_row *r1
11214 = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
11215 increment_matrix_positions (w->current_matrix,
11216 MATRIX_ROW_VPOS (r0, current_matrix),
11217 MATRIX_ROW_VPOS (r1, current_matrix),
11218 delta, delta_bytes);
11219 }
11170 11220
11171 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0); 11221 /* Set the cursor. */
11172 return 1; 11222 row = row_containing_pos (w, PT, r0, NULL);
11223 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
11224 return 1;
11225 }
11173 } 11226 }
11174 11227
11175 /* Return quickly if changes are all below what is displayed in the 11228 /* Handle the case that changes are all below what is displayed in
11176 window, and if PT is in the window. */ 11229 the window, and that PT is in the window. */
11177 if (BEG_UNCHANGED > MATRIX_ROW_END_CHARPOS (row) 11230 if (first_changed_charpos >= MATRIX_ROW_END_CHARPOS (row))
11178 && PT < MATRIX_ROW_END_CHARPOS (row))
11179 { 11231 {
11180 /* We have to update window end positions because the buffer's 11232 struct glyph_row *r0;
11181 size has changed. */
11182 w->window_end_pos
11183 = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
11184 w->window_end_bytepos
11185 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
11186 11233
11187 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix); 11234 /* Give up if PT is not in the window. Note that it already has
11188 row = row_containing_pos (w, PT, row, NULL); 11235 been checked at the start of try_window_id that PT is not in
11189 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0); 11236 front of the window start. */
11190 return 2; 11237 if (PT >= MATRIX_ROW_END_CHARPOS (row))
11238 GIVE_UP (14);
11239
11240 /* If window start is unchanged, we can reuse the whole matrix
11241 as is, without changing glyph positions since no text has
11242 been added/removed in front of the window end. */
11243 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
11244 if (TEXT_POS_EQUAL_P (start, r0->start.pos))
11245 {
11246 /* We have to compute the window end anew since text
11247 can have been added/removed after it. */
11248 w->window_end_pos
11249 = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
11250 w->window_end_bytepos
11251 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
11252
11253 /* Set the cursor. */
11254 row = row_containing_pos (w, PT, r0, NULL);
11255 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
11256 return 2;
11257 }
11191 } 11258 }
11192 11259
11193 /* Check that window start agrees with the start of the first glyph 11260 /* Check that window start agrees with the start of the first glyph
11194 row in its current matrix. Check this after we know the window 11261 row in its current matrix. Check this after we know the window
11195 start is not in changed text, otherwise positions would not be 11262 start is not in changed text, otherwise positions would not be
11196 comparable. */ 11263 comparable. */
11197 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix); 11264 if (BEG_UNCHANGED + END_UNCHANGED != Z - BEG
11265 && CHARPOS (start) >= first_changed_charpos
11266 && CHARPOS (start) <= last_changed_charpos)
11267 GIVE_UP (15);
11268
11269 row = MATRIX_FIRST_TEXT_ROW (current_matrix);
11198 if (!TEXT_POS_EQUAL_P (start, row->start.pos)) 11270 if (!TEXT_POS_EQUAL_P (start, row->start.pos))
11199 return 0; 11271 GIVE_UP (16);
11200 11272
11201 /* Compute the position at which we have to start displaying new 11273 /* Compute the position at which we have to start displaying new
11202 lines. Some of the lines at the top of the window might be 11274 lines. Some of the lines at the top of the window might be
@@ -11216,7 +11288,7 @@ try_window_id (w)
11216 --last_unchanged_at_beg_row; 11288 --last_unchanged_at_beg_row;
11217 11289
11218 if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row)) 11290 if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row))
11219 return 0; 11291 GIVE_UP (17);
11220 11292
11221 init_to_row_end (&it, w, last_unchanged_at_beg_row); 11293 init_to_row_end (&it, w, last_unchanged_at_beg_row);
11222 start_pos = it.current.pos; 11294 start_pos = it.current.pos;
@@ -11285,7 +11357,7 @@ try_window_id (w)
11285 } 11357 }
11286 } 11358 }
11287 else if (last_unchanged_at_beg_row == NULL) 11359 else if (last_unchanged_at_beg_row == NULL)
11288 return 0; 11360 GIVE_UP (18);
11289 11361
11290 11362
11291#if GLYPH_DEBUG 11363#if GLYPH_DEBUG
@@ -11645,6 +11717,8 @@ try_window_id (w)
11645 w->window_end_valid = Qnil; 11717 w->window_end_valid = Qnil;
11646 w->desired_matrix->no_scrolling_p = 1; 11718 w->desired_matrix->no_scrolling_p = 1;
11647 return 3; 11719 return 3;
11720
11721#undef GIVE_UP
11648} 11722}
11649 11723
11650 11724