Mercurial > emacs
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 /*********************************************************************** |