diff options
| author | Gerd Moellmann | 2001-05-03 16:19:16 +0000 |
|---|---|---|
| committer | Gerd Moellmann | 2001-05-03 16:19:16 +0000 |
| commit | 27d16f056bc557edcbdcc0ba8736ca63bf7331c6 (patch) | |
| tree | 89d78602085b4469ba23d012b0aed775ca27a180 /src | |
| parent | 768e4b745dab9219c125de258f793ca31fa61b72 (diff) | |
| download | emacs-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.c | 244 |
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 | ||