comparison src/xdisp.c @ 37553:d8b96c1b61ea

(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.
author Gerd Moellmann <gerd@gnu.org>
date Thu, 03 May 2001 16:19:16 +0000
parents f56d9b9b3fac
children a1501be81cc0
comparison
equal deleted inserted replaced
37552:7615043715cd 37553:d8b96c1b61ea
9984 debug_method_add (w, "recenter 1"); 9984 debug_method_add (w, "recenter 1");
9985 #endif 9985 #endif
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);
10022 #endif 9996 #endif
10023 9997
11106 struct text_pos start_pos; 11080 struct text_pos start_pos;
11107 struct run run; 11081 struct run run;
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;
11111 11085 int first_changed_charpos, last_changed_charpos;
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
11119 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);
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
11123 set end_unchanged to 0 in that case. */ 11160 set end_unchanged to 0 in that case. */
11124 if (MODIFF > SAVE_MODIFF 11161 if (MODIFF > SAVE_MODIFF
11129 BEG_UNCHANGED = GPT - BEG; 11166 BEG_UNCHANGED = GPT - BEG;
11130 if (Z - GPT < END_UNCHANGED) 11167 if (Z - GPT < END_UNCHANGED)
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
11198 been checked at the start of try_window_id that PT is not in
11199 front of the window start. */
11200 if (PT >= MATRIX_ROW_END_CHARPOS (row) + delta)
11201 GIVE_UP (13);
11202
11203 /* If window start is unchanged, we can reuse the whole matrix
11204 as is, after adjusting glyph positions. No need to compute
11205 the window end again, since its offset from Z hasn't changed. */
11206 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
11207 if (CHARPOS (start) == MATRIX_ROW_START_CHARPOS (r0) + delta
11208 && BYTEPOS (start) == MATRIX_ROW_START_BYTEPOS (r0) + delta_bytes)
11209 {
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 }
11157 11220
11158 #if 0 /* If changes are all in front of the window start, the 11221 /* Set the cursor. */
11159 distance of the last displayed glyph from Z hasn't 11222 row = row_containing_pos (w, PT, r0, NULL);
11160 changed. */ 11223 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
11161 w->window_end_pos 11224 return 1;
11162 = make_number (Z - MATRIX_ROW_END_CHARPOS (row)); 11225 }
11163 w->window_end_bytepos 11226 }
11164 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row); 11227
11165 #endif 11228 /* Handle the case that changes are all below what is displayed in
11166 11229 the window, and that PT is in the window. */
11167 row = row_containing_pos (w, PT, r0, NULL); 11230 if (first_changed_charpos >= MATRIX_ROW_END_CHARPOS (row))
11168 if (row == NULL) 11231 {
11169 return 0; 11232 struct glyph_row *r0;
11170 11233
11171 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0); 11234 /* Give up if PT is not in the window. Note that it already has
11172 return 1; 11235 been checked at the start of try_window_id that PT is not in
11173 } 11236 front of the window start. */
11174 11237 if (PT >= MATRIX_ROW_END_CHARPOS (row))
11175 /* Return quickly if changes are all below what is displayed in the 11238 GIVE_UP (14);
11176 window, and if PT is in the window. */ 11239
11177 if (BEG_UNCHANGED > MATRIX_ROW_END_CHARPOS (row) 11240 /* If window start is unchanged, we can reuse the whole matrix
11178 && PT < MATRIX_ROW_END_CHARPOS (row)) 11241 as is, without changing glyph positions since no text has
11179 { 11242 been added/removed in front of the window end. */
11180 /* We have to update window end positions because the buffer's 11243 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
11181 size has changed. */ 11244 if (TEXT_POS_EQUAL_P (start, r0->start.pos))
11182 w->window_end_pos 11245 {
11183 = make_number (Z - MATRIX_ROW_END_CHARPOS (row)); 11246 /* We have to compute the window end anew since text
11184 w->window_end_bytepos 11247 can have been added/removed after it. */
11185 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row); 11248 w->window_end_pos
11186 11249 = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
11187 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix); 11250 w->window_end_bytepos
11188 row = row_containing_pos (w, PT, row, NULL); 11251 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
11189 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0); 11252
11190 return 2; 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
11203 reusable because they are not displaying changed text. Find the 11275 reusable because they are not displaying changed text. Find the
11204 last row in W's current matrix not affected by changes at the 11276 last row in W's current matrix not affected by changes at the
11214 while (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row) 11286 while (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row)
11215 && last_unchanged_at_beg_row > w->current_matrix->rows) 11287 && last_unchanged_at_beg_row > w->current_matrix->rows)
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;
11223 11295
11224 /* Start displaying new lines in the desired matrix at the same 11296 /* Start displaying new lines in the desired matrix at the same
11283 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, current_matrix); 11355 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, current_matrix);
11284 xassert (stop_pos >= Z - END_UNCHANGED); 11356 xassert (stop_pos >= Z - END_UNCHANGED);
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
11292 11364
11293 /* Either there is no unchanged row at the end, or the one we have 11365 /* Either there is no unchanged row at the end, or the one we have
11643 11715
11644 /* Record that display has not been completed. */ 11716 /* Record that display has not been completed. */
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
11651 11725
11652 /*********************************************************************** 11726 /***********************************************************************