diff options
| author | Gerd Moellmann | 2000-08-10 19:17:01 +0000 |
|---|---|---|
| committer | Gerd Moellmann | 2000-08-10 19:17:01 +0000 |
| commit | 47589c8c98edf2a457e97df8e55063fd36ac881d (patch) | |
| tree | 0061e4bdb2257c867d061bd71890b0d87494063e /src | |
| parent | cbc099e58429f712b1f88c1ee9b85457ce6e6c0e (diff) | |
| download | emacs-47589c8c98edf2a457e97df8e55063fd36ac881d.tar.gz emacs-47589c8c98edf2a457e97df8e55063fd36ac881d.zip | |
(trace_move) [GLYPH_DEBUG]: New variable.
(TRACE_MOVE) [GLYPH_DEBUG]: New macro.
(move_it_in_display_line_to): Record iterator's ascent and descent
before producing glyphs, and restore them when we know the glyph
doesn't fit on the line.
(move_it_to): Restructured so that it's easier to debug. If
moving to a vpos, and not moving to an x or character position,
stop as soon as the specified vpos is reached; don't move further
into that line because that might change the computed line height.
(try_cursor_movement): New function, extracted from the cursor
movement branch of redisplay_window. If ending on a partially
visible line, don't try to scroll if the cursor line is taller
than the window.
(redisplay_window): Use try_cursor_movement.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 23 | ||||
| -rw-r--r-- | src/xdisp.c | 469 |
2 files changed, 311 insertions, 181 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index a5a7118d4d0..2600b3a73c9 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,26 @@ | |||
| 1 | 2000-08-10 Gerd Moellmann <gerd@gnu.org> | ||
| 2 | |||
| 3 | * xdisp.c (trace_move) [GLYPH_DEBUG]: New variable. | ||
| 4 | (TRACE_MOVE) [GLYPH_DEBUG]: New macro. | ||
| 5 | (move_it_in_display_line_to): Record iterator's ascent and descent | ||
| 6 | before producing glyphs, and restore them when we know the glyph | ||
| 7 | doesn't fit on the line. | ||
| 8 | (move_it_to): Restructured so that it's easier to debug. If | ||
| 9 | moving to a vpos, and not moving to an x or character position, | ||
| 10 | stop as soon as the specified vpos is reached; don't move further | ||
| 11 | into that line because that might change the computed line height. | ||
| 12 | (try_cursor_movement): New function, extracted from the cursor | ||
| 13 | movement branch of redisplay_window. If ending on a partially | ||
| 14 | visible line, don't try to scroll if the cursor line is taller | ||
| 15 | than the window. | ||
| 16 | (redisplay_window): Use try_cursor_movement. | ||
| 17 | |||
| 18 | * window.c (Fwindow_end): Rewritten to not use Fvertical_motion, | ||
| 19 | because that function doesn't cope with variable-height lines. | ||
| 20 | |||
| 21 | * xterm.c (x_draw_bar_cursor): If cursor is on an image, draw a | ||
| 22 | box cursor because that's better visible for large images. | ||
| 23 | |||
| 1 | 2000-08-10 Miles Bader <miles@gnu.org> | 24 | 2000-08-10 Miles Bader <miles@gnu.org> |
| 2 | 25 | ||
| 3 | * w32term.c (note_mouse_highlight): Update calls to overlays_at. | 26 | * w32term.c (note_mouse_highlight): Update calls to overlays_at. |
diff --git a/src/xdisp.c b/src/xdisp.c index 28067a7ee51..1a3a5ab3fa4 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -516,13 +516,25 @@ static int last_max_ascent, last_height; | |||
| 516 | 516 | ||
| 517 | #define TEXT_PROP_DISTANCE_LIMIT 100 | 517 | #define TEXT_PROP_DISTANCE_LIMIT 100 |
| 518 | 518 | ||
| 519 | #if GLYPH_DEBUG | ||
| 520 | |||
| 519 | /* Non-zero means print traces of redisplay if compiled with | 521 | /* Non-zero means print traces of redisplay if compiled with |
| 520 | GLYPH_DEBUG != 0. */ | 522 | GLYPH_DEBUG != 0. */ |
| 521 | 523 | ||
| 522 | #if GLYPH_DEBUG | ||
| 523 | int trace_redisplay_p; | 524 | int trace_redisplay_p; |
| 525 | |||
| 526 | /* Non-zero means trace with TRACE_MOVE to stderr. */ | ||
| 527 | |||
| 528 | int trace_move; | ||
| 529 | |||
| 530 | #ifdef DEBUG_TRACE_MOVE | ||
| 531 | #define TRACE_MOVE(x) if (trace_move) fprintf x; else (void) 0 | ||
| 532 | #else | ||
| 533 | #define TRACE_MOVE(x) (void) 0; | ||
| 524 | #endif | 534 | #endif |
| 525 | 535 | ||
| 536 | #endif /* GLYPH_DEBUG */ | ||
| 537 | |||
| 526 | /* Non-zero means automatically scroll windows horizontally to make | 538 | /* Non-zero means automatically scroll windows horizontally to make |
| 527 | point visible. */ | 539 | point visible. */ |
| 528 | 540 | ||
| @@ -655,6 +667,7 @@ static void extend_face_to_end_of_line P_ ((struct it *)); | |||
| 655 | static int append_space P_ ((struct it *, int)); | 667 | static int append_space P_ ((struct it *, int)); |
| 656 | static void make_cursor_line_fully_visible P_ ((struct window *)); | 668 | static void make_cursor_line_fully_visible P_ ((struct window *)); |
| 657 | static int try_scrolling P_ ((Lisp_Object, int, int, int, int)); | 669 | static int try_scrolling P_ ((Lisp_Object, int, int, int, int)); |
| 670 | static int try_cursor_movement P_ ((Lisp_Object, struct text_pos, int *)); | ||
| 658 | static int trailing_whitespace_p P_ ((int)); | 671 | static int trailing_whitespace_p P_ ((int)); |
| 659 | static int message_log_check_duplicate P_ ((int, int, int, int)); | 672 | static int message_log_check_duplicate P_ ((int, int, int, int)); |
| 660 | int invisible_p P_ ((Lisp_Object, Lisp_Object)); | 673 | int invisible_p P_ ((Lisp_Object, Lisp_Object)); |
| @@ -4265,7 +4278,7 @@ move_it_in_display_line_to (it, to_charpos, to_x, op) | |||
| 4265 | 4278 | ||
| 4266 | while (1) | 4279 | while (1) |
| 4267 | { | 4280 | { |
| 4268 | int x, i; | 4281 | int x, i, ascent, descent; |
| 4269 | 4282 | ||
| 4270 | /* Stop when ZV or TO_CHARPOS reached. */ | 4283 | /* Stop when ZV or TO_CHARPOS reached. */ |
| 4271 | if (!get_next_display_element (it) | 4284 | if (!get_next_display_element (it) |
| @@ -4282,6 +4295,15 @@ move_it_in_display_line_to (it, to_charpos, to_x, op) | |||
| 4282 | x-position before this display element in case it does not | 4295 | x-position before this display element in case it does not |
| 4283 | fit on the line. */ | 4296 | fit on the line. */ |
| 4284 | x = it->current_x; | 4297 | x = it->current_x; |
| 4298 | |||
| 4299 | /* Remember the line height so far in case the next element doesn't | ||
| 4300 | fit on the line. */ | ||
| 4301 | if (!it->truncate_lines_p) | ||
| 4302 | { | ||
| 4303 | ascent = it->max_ascent; | ||
| 4304 | descent = it->max_descent; | ||
| 4305 | } | ||
| 4306 | |||
| 4285 | PRODUCE_GLYPHS (it); | 4307 | PRODUCE_GLYPHS (it); |
| 4286 | 4308 | ||
| 4287 | if (it->area != TEXT_AREA) | 4309 | if (it->area != TEXT_AREA) |
| @@ -4347,8 +4369,14 @@ move_it_in_display_line_to (it, to_charpos, to_x, op) | |||
| 4347 | set_iterator_to_next (it); | 4369 | set_iterator_to_next (it); |
| 4348 | } | 4370 | } |
| 4349 | else | 4371 | else |
| 4350 | it->current_x = x; | 4372 | { |
| 4351 | 4373 | it->current_x = x; | |
| 4374 | it->max_ascent = ascent; | ||
| 4375 | it->max_descent = descent; | ||
| 4376 | } | ||
| 4377 | |||
| 4378 | TRACE_MOVE ((stderr, "move_it_in: continued at %d\n", | ||
| 4379 | IT_CHARPOS (*it))); | ||
| 4352 | result = MOVE_LINE_CONTINUED; | 4380 | result = MOVE_LINE_CONTINUED; |
| 4353 | break; | 4381 | break; |
| 4354 | } | 4382 | } |
| @@ -4423,8 +4451,9 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op) | |||
| 4423 | { | 4451 | { |
| 4424 | enum move_it_result skip, skip2 = MOVE_X_REACHED; | 4452 | enum move_it_result skip, skip2 = MOVE_X_REACHED; |
| 4425 | int line_height; | 4453 | int line_height; |
| 4454 | int reached = 0; | ||
| 4426 | 4455 | ||
| 4427 | while (1) | 4456 | for (;;) |
| 4428 | { | 4457 | { |
| 4429 | if (op & MOVE_TO_VPOS) | 4458 | if (op & MOVE_TO_VPOS) |
| 4430 | { | 4459 | { |
| @@ -4433,31 +4462,46 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op) | |||
| 4433 | if ((op & (MOVE_TO_X | MOVE_TO_POS)) == 0) | 4462 | if ((op & (MOVE_TO_X | MOVE_TO_POS)) == 0) |
| 4434 | { | 4463 | { |
| 4435 | if (it->vpos == to_vpos) | 4464 | if (it->vpos == to_vpos) |
| 4436 | break; | 4465 | { |
| 4437 | skip = move_it_in_display_line_to (it, -1, -1, 0); | 4466 | reached = 1; |
| 4467 | break; | ||
| 4468 | } | ||
| 4469 | else | ||
| 4470 | skip = move_it_in_display_line_to (it, -1, -1, 0); | ||
| 4438 | } | 4471 | } |
| 4439 | else | 4472 | else |
| 4440 | { | 4473 | { |
| 4441 | /* TO_VPOS >= 0 means stop at TO_X in the line at | 4474 | /* TO_VPOS >= 0 means stop at TO_X in the line at |
| 4442 | TO_VPOS, or at TO_POS, whichever comes first. */ | 4475 | TO_VPOS, or at TO_POS, whichever comes first. */ |
| 4476 | if (it->vpos == to_vpos) | ||
| 4477 | { | ||
| 4478 | reached = 2; | ||
| 4479 | break; | ||
| 4480 | } | ||
| 4481 | |||
| 4443 | skip = move_it_in_display_line_to (it, to_charpos, to_x, op); | 4482 | skip = move_it_in_display_line_to (it, to_charpos, to_x, op); |
| 4444 | 4483 | ||
| 4445 | if (skip == MOVE_POS_MATCH_OR_ZV || it->vpos == to_vpos) | 4484 | if (skip == MOVE_POS_MATCH_OR_ZV || it->vpos == to_vpos) |
| 4446 | break; | 4485 | { |
| 4486 | reached = 3; | ||
| 4487 | break; | ||
| 4488 | } | ||
| 4447 | else if (skip == MOVE_X_REACHED && it->vpos != to_vpos) | 4489 | else if (skip == MOVE_X_REACHED && it->vpos != to_vpos) |
| 4448 | { | 4490 | { |
| 4449 | /* We have reached TO_X but not in the line we want. */ | 4491 | /* We have reached TO_X but not in the line we want. */ |
| 4450 | skip = move_it_in_display_line_to (it, to_charpos, | 4492 | skip = move_it_in_display_line_to (it, to_charpos, |
| 4451 | -1, MOVE_TO_POS); | 4493 | -1, MOVE_TO_POS); |
| 4452 | if (skip == MOVE_POS_MATCH_OR_ZV) | 4494 | if (skip == MOVE_POS_MATCH_OR_ZV) |
| 4453 | break; | 4495 | { |
| 4496 | reached = 4; | ||
| 4497 | break; | ||
| 4498 | } | ||
| 4454 | } | 4499 | } |
| 4455 | } | 4500 | } |
| 4456 | } | 4501 | } |
| 4457 | else if (op & MOVE_TO_Y) | 4502 | else if (op & MOVE_TO_Y) |
| 4458 | { | 4503 | { |
| 4459 | struct it it_backup; | 4504 | struct it it_backup; |
| 4460 | int done_p; | ||
| 4461 | 4505 | ||
| 4462 | /* TO_Y specified means stop at TO_X in the line containing | 4506 | /* TO_Y specified means stop at TO_X in the line containing |
| 4463 | TO_Y---or at TO_CHARPOS if this is reached first. The | 4507 | TO_Y---or at TO_CHARPOS if this is reached first. The |
| @@ -4479,22 +4523,27 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op) | |||
| 4479 | 4523 | ||
| 4480 | /* If TO_CHARPOS is reached or ZV, we don't have to do more. */ | 4524 | /* If TO_CHARPOS is reached or ZV, we don't have to do more. */ |
| 4481 | if (skip == MOVE_POS_MATCH_OR_ZV) | 4525 | if (skip == MOVE_POS_MATCH_OR_ZV) |
| 4482 | break; | 4526 | { |
| 4527 | reached = 5; | ||
| 4528 | break; | ||
| 4529 | } | ||
| 4483 | 4530 | ||
| 4484 | /* If TO_X was reached, we would like to know whether TO_Y | 4531 | /* If TO_X was reached, we would like to know whether TO_Y |
| 4485 | is in the line. This can only be said if we know the | 4532 | is in the line. This can only be said if we know the |
| 4486 | total line height which requires us to scan the rest of | 4533 | total line height which requires us to scan the rest of |
| 4487 | the line. */ | 4534 | the line. */ |
| 4488 | done_p = 0; | ||
| 4489 | if (skip == MOVE_X_REACHED) | 4535 | if (skip == MOVE_X_REACHED) |
| 4490 | { | 4536 | { |
| 4491 | it_backup = *it; | 4537 | it_backup = *it; |
| 4538 | TRACE_MOVE ((stderr, "move_it: from %d\n", IT_CHARPOS (*it))); | ||
| 4492 | skip2 = move_it_in_display_line_to (it, to_charpos, -1, | 4539 | skip2 = move_it_in_display_line_to (it, to_charpos, -1, |
| 4493 | op & MOVE_TO_POS); | 4540 | op & MOVE_TO_POS); |
| 4541 | TRACE_MOVE ((stderr, "move_it: to %d\n", IT_CHARPOS (*it))); | ||
| 4494 | } | 4542 | } |
| 4495 | 4543 | ||
| 4496 | /* Now, decide whether TO_Y is in this line. */ | 4544 | /* Now, decide whether TO_Y is in this line. */ |
| 4497 | line_height = it->max_ascent + it->max_descent; | 4545 | line_height = it->max_ascent + it->max_descent; |
| 4546 | TRACE_MOVE ((stderr, "move_it: line_height = %d\n", line_height)); | ||
| 4498 | 4547 | ||
| 4499 | if (to_y >= it->current_y | 4548 | if (to_y >= it->current_y |
| 4500 | && to_y < it->current_y + line_height) | 4549 | && to_y < it->current_y + line_height) |
| @@ -4504,16 +4553,16 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op) | |||
| 4504 | we scanned too far. We have to restore IT's settings | 4553 | we scanned too far. We have to restore IT's settings |
| 4505 | to the ones before skipping. */ | 4554 | to the ones before skipping. */ |
| 4506 | *it = it_backup; | 4555 | *it = it_backup; |
| 4507 | done_p = 1; | 4556 | reached = 6; |
| 4508 | } | 4557 | } |
| 4509 | else if (skip == MOVE_X_REACHED) | 4558 | else if (skip == MOVE_X_REACHED) |
| 4510 | { | 4559 | { |
| 4511 | skip = skip2; | 4560 | skip = skip2; |
| 4512 | if (skip == MOVE_POS_MATCH_OR_ZV) | 4561 | if (skip == MOVE_POS_MATCH_OR_ZV) |
| 4513 | done_p = 1; | 4562 | reached = 7; |
| 4514 | } | 4563 | } |
| 4515 | 4564 | ||
| 4516 | if (done_p) | 4565 | if (reached) |
| 4517 | break; | 4566 | break; |
| 4518 | } | 4567 | } |
| 4519 | else | 4568 | else |
| @@ -4522,7 +4571,8 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op) | |||
| 4522 | switch (skip) | 4571 | switch (skip) |
| 4523 | { | 4572 | { |
| 4524 | case MOVE_POS_MATCH_OR_ZV: | 4573 | case MOVE_POS_MATCH_OR_ZV: |
| 4525 | return; | 4574 | reached = 8; |
| 4575 | goto out; | ||
| 4526 | 4576 | ||
| 4527 | case MOVE_NEWLINE_OR_CR: | 4577 | case MOVE_NEWLINE_OR_CR: |
| 4528 | set_iterator_to_next (it); | 4578 | set_iterator_to_next (it); |
| @@ -4534,7 +4584,10 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op) | |||
| 4534 | reseat_at_next_visible_line_start (it, 0); | 4584 | reseat_at_next_visible_line_start (it, 0); |
| 4535 | if ((op & MOVE_TO_POS) != 0 | 4585 | if ((op & MOVE_TO_POS) != 0 |
| 4536 | && IT_CHARPOS (*it) > to_charpos) | 4586 | && IT_CHARPOS (*it) > to_charpos) |
| 4537 | goto out; | 4587 | { |
| 4588 | reached = 9; | ||
| 4589 | goto out; | ||
| 4590 | } | ||
| 4538 | break; | 4591 | break; |
| 4539 | 4592 | ||
| 4540 | case MOVE_LINE_CONTINUED: | 4593 | case MOVE_LINE_CONTINUED: |
| @@ -4554,7 +4607,10 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op) | |||
| 4554 | last_max_ascent = it->max_ascent; | 4607 | last_max_ascent = it->max_ascent; |
| 4555 | it->max_ascent = it->max_descent = 0; | 4608 | it->max_ascent = it->max_descent = 0; |
| 4556 | } | 4609 | } |
| 4557 | out:; | 4610 | |
| 4611 | out: | ||
| 4612 | |||
| 4613 | TRACE_MOVE ((stderr, "move_it_to: reached %d\n", reached)); | ||
| 4558 | } | 4614 | } |
| 4559 | 4615 | ||
| 4560 | 4616 | ||
| @@ -4603,6 +4659,7 @@ move_it_vertically_backward (it, dy) | |||
| 4603 | MOVE_TO_POS | MOVE_TO_VPOS); | 4659 | MOVE_TO_POS | MOVE_TO_VPOS); |
| 4604 | xassert (IT_CHARPOS (*it) >= BEGV); | 4660 | xassert (IT_CHARPOS (*it) >= BEGV); |
| 4605 | line_height = it2.max_ascent + it2.max_descent; | 4661 | line_height = it2.max_ascent + it2.max_descent; |
| 4662 | |||
| 4606 | move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS); | 4663 | move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS); |
| 4607 | xassert (IT_CHARPOS (*it) >= BEGV); | 4664 | xassert (IT_CHARPOS (*it) >= BEGV); |
| 4608 | h = it2.current_y - it->current_y; | 4665 | h = it2.current_y - it->current_y; |
| @@ -4657,8 +4714,10 @@ move_it_vertically (it, dy) | |||
| 4657 | move_it_vertically_backward (it, -dy); | 4714 | move_it_vertically_backward (it, -dy); |
| 4658 | else if (dy > 0) | 4715 | else if (dy > 0) |
| 4659 | { | 4716 | { |
| 4717 | TRACE_MOVE ((stderr, "move_it_v: from %d, %d\n", IT_CHARPOS (*it), dy)); | ||
| 4660 | move_it_to (it, ZV, -1, it->current_y + dy, -1, | 4718 | move_it_to (it, ZV, -1, it->current_y + dy, -1, |
| 4661 | MOVE_TO_POS | MOVE_TO_Y); | 4719 | MOVE_TO_POS | MOVE_TO_Y); |
| 4720 | TRACE_MOVE ((stderr, "move_it_v: to %d\n", IT_CHARPOS (*it))); | ||
| 4662 | 4721 | ||
| 4663 | /* If buffer ends in ZV without a newline, move to the start of | 4722 | /* If buffer ends in ZV without a newline, move to the start of |
| 4664 | the line to satisfy the post-condition. */ | 4723 | the line to satisfy the post-condition. */ |
| @@ -8511,7 +8570,7 @@ try_scrolling (window, just_this_one_p, scroll_conservatively, | |||
| 8511 | 8570 | ||
| 8512 | /* Point is in the scroll margin at the bottom of the window, or | 8571 | /* Point is in the scroll margin at the bottom of the window, or |
| 8513 | below. Compute a new window start that makes point visible. */ | 8572 | below. Compute a new window start that makes point visible. */ |
| 8514 | 8573 | ||
| 8515 | /* Compute the distance from the scroll margin to PT. | 8574 | /* Compute the distance from the scroll margin to PT. |
| 8516 | Give up if the distance is greater than scroll_max. */ | 8575 | Give up if the distance is greater than scroll_max. */ |
| 8517 | start_display (&it, w, scroll_margin_pos); | 8576 | start_display (&it, w, scroll_margin_pos); |
| @@ -8522,6 +8581,7 @@ try_scrolling (window, just_this_one_p, scroll_conservatively, | |||
| 8522 | ? it.max_ascent + it.max_descent | 8581 | ? it.max_ascent + it.max_descent |
| 8523 | : last_height); | 8582 | : last_height); |
| 8524 | dy = it.current_y + line_height - y0; | 8583 | dy = it.current_y + line_height - y0; |
| 8584 | |||
| 8525 | if (dy > scroll_max) | 8585 | if (dy > scroll_max) |
| 8526 | return 0; | 8586 | return 0; |
| 8527 | 8587 | ||
| @@ -8706,6 +8766,209 @@ compute_window_start_on_continuation_line (w) | |||
| 8706 | } | 8766 | } |
| 8707 | 8767 | ||
| 8708 | 8768 | ||
| 8769 | /* Try cursor movement in case text has not changes in window WINDOW, | ||
| 8770 | with window start STARTP. Value is | ||
| 8771 | |||
| 8772 | 1 if successful | ||
| 8773 | |||
| 8774 | 0 if this method cannot be used | ||
| 8775 | |||
| 8776 | -1 if we know we have to scroll the display. *SCROLL_STEP is | ||
| 8777 | set to 1, under certain circumstances, if we want to scroll as | ||
| 8778 | if scroll-step were set to 1. See the code. */ | ||
| 8779 | |||
| 8780 | static int | ||
| 8781 | try_cursor_movement (window, startp, scroll_step) | ||
| 8782 | Lisp_Object window; | ||
| 8783 | struct text_pos startp; | ||
| 8784 | int *scroll_step; | ||
| 8785 | { | ||
| 8786 | struct window *w = XWINDOW (window); | ||
| 8787 | struct frame *f = XFRAME (w->frame); | ||
| 8788 | int rc = 0; | ||
| 8789 | |||
| 8790 | /* Handle case where text has not changed, only point, and it has | ||
| 8791 | not moved off the frame. */ | ||
| 8792 | if (/* Point may be in this window. */ | ||
| 8793 | PT >= CHARPOS (startp) | ||
| 8794 | /* If we don't check this, we are called to move the cursor in a | ||
| 8795 | horizontally split window with a current matrix that doesn't | ||
| 8796 | fit the display. */ | ||
| 8797 | && !windows_or_buffers_changed | ||
| 8798 | /* Selective display hasn't changed. */ | ||
| 8799 | && !current_buffer->clip_changed | ||
| 8800 | /* If force-mode-line-update was called, really redisplay; | ||
| 8801 | that's how redisplay is forced after e.g. changing | ||
| 8802 | buffer-invisibility-spec. */ | ||
| 8803 | && NILP (w->update_mode_line) | ||
| 8804 | /* Can't use this case if highlighting a region. When a | ||
| 8805 | region exists, cursor movement has to do more than just | ||
| 8806 | set the cursor. */ | ||
| 8807 | && !(!NILP (Vtransient_mark_mode) | ||
| 8808 | && !NILP (current_buffer->mark_active)) | ||
| 8809 | && NILP (w->region_showing) | ||
| 8810 | && NILP (Vshow_trailing_whitespace) | ||
| 8811 | /* Right after splitting windows, last_point may be nil. */ | ||
| 8812 | && INTEGERP (w->last_point) | ||
| 8813 | /* This code is not used for mini-buffer for the sake of the case | ||
| 8814 | of redisplaying to replace an echo area message; since in | ||
| 8815 | that case the mini-buffer contents per se are usually | ||
| 8816 | unchanged. This code is of no real use in the mini-buffer | ||
| 8817 | since the handling of this_line_start_pos, etc., in redisplay | ||
| 8818 | handles the same cases. */ | ||
| 8819 | && !EQ (window, minibuf_window) | ||
| 8820 | /* When splitting windows or for new windows, it happens that | ||
| 8821 | redisplay is called with a nil window_end_vpos or one being | ||
| 8822 | larger than the window. This should really be fixed in | ||
| 8823 | window.c. I don't have this on my list, now, so we do | ||
| 8824 | approximately the same as the old redisplay code. --gerd. */ | ||
| 8825 | && INTEGERP (w->window_end_vpos) | ||
| 8826 | && XFASTINT (w->window_end_vpos) < w->current_matrix->nrows | ||
| 8827 | && (FRAME_WINDOW_P (f) | ||
| 8828 | || !MARKERP (Voverlay_arrow_position) | ||
| 8829 | || current_buffer != XMARKER (Voverlay_arrow_position)->buffer)) | ||
| 8830 | { | ||
| 8831 | int this_scroll_margin; | ||
| 8832 | struct glyph_row *row; | ||
| 8833 | |||
| 8834 | #if GLYPH_DEBUG | ||
| 8835 | debug_method_add (w, "cursor movement"); | ||
| 8836 | #endif | ||
| 8837 | |||
| 8838 | /* Scroll if point within this distance from the top or bottom | ||
| 8839 | of the window. This is a pixel value. */ | ||
| 8840 | this_scroll_margin = max (0, scroll_margin); | ||
| 8841 | this_scroll_margin = min (this_scroll_margin, XFASTINT (w->height) / 4); | ||
| 8842 | this_scroll_margin *= CANON_Y_UNIT (f); | ||
| 8843 | |||
| 8844 | /* Start with the row the cursor was displayed during the last | ||
| 8845 | not paused redisplay. Give up if that row is not valid. */ | ||
| 8846 | if (w->last_cursor.vpos >= w->current_matrix->nrows) | ||
| 8847 | rc = -1; | ||
| 8848 | else | ||
| 8849 | { | ||
| 8850 | row = MATRIX_ROW (w->current_matrix, w->last_cursor.vpos); | ||
| 8851 | if (row->mode_line_p) | ||
| 8852 | ++row; | ||
| 8853 | if (!row->enabled_p) | ||
| 8854 | rc = -1; | ||
| 8855 | } | ||
| 8856 | |||
| 8857 | if (rc == 0) | ||
| 8858 | { | ||
| 8859 | int scroll_p = 0; | ||
| 8860 | |||
| 8861 | if (PT > XFASTINT (w->last_point)) | ||
| 8862 | { | ||
| 8863 | /* Point has moved forward. */ | ||
| 8864 | int last_y = window_text_bottom_y (w) - this_scroll_margin; | ||
| 8865 | |||
| 8866 | while (MATRIX_ROW_END_CHARPOS (row) < PT | ||
| 8867 | && MATRIX_ROW_BOTTOM_Y (row) < last_y) | ||
| 8868 | { | ||
| 8869 | xassert (row->enabled_p); | ||
| 8870 | ++row; | ||
| 8871 | } | ||
| 8872 | |||
| 8873 | /* The end position of a row equals the start position | ||
| 8874 | of the next row. If PT is there, we would rather | ||
| 8875 | display it in the next line. Exceptions are when the | ||
| 8876 | row ends in the middle of a character, or ends in | ||
| 8877 | ZV. */ | ||
| 8878 | if (MATRIX_ROW_BOTTOM_Y (row) < last_y | ||
| 8879 | && MATRIX_ROW_END_CHARPOS (row) == PT | ||
| 8880 | && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row) | ||
| 8881 | && !row->ends_at_zv_p) | ||
| 8882 | { | ||
| 8883 | xassert (row->enabled_p); | ||
| 8884 | ++row; | ||
| 8885 | } | ||
| 8886 | |||
| 8887 | /* If within the scroll margin, scroll. Note that | ||
| 8888 | MATRIX_ROW_BOTTOM_Y gives the pixel position at which | ||
| 8889 | the next line would be drawn, and that | ||
| 8890 | this_scroll_margin can be zero. */ | ||
| 8891 | if (MATRIX_ROW_BOTTOM_Y (row) > last_y | ||
| 8892 | || PT > MATRIX_ROW_END_CHARPOS (row) | ||
| 8893 | /* Line is completely visible last line in window | ||
| 8894 | and PT is to be set in the next line. */ | ||
| 8895 | || (MATRIX_ROW_BOTTOM_Y (row) == last_y | ||
| 8896 | && PT == MATRIX_ROW_END_CHARPOS (row) | ||
| 8897 | && !row->ends_at_zv_p | ||
| 8898 | && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))) | ||
| 8899 | scroll_p = 1; | ||
| 8900 | } | ||
| 8901 | else if (PT < XFASTINT (w->last_point)) | ||
| 8902 | { | ||
| 8903 | /* Cursor has to be moved backward. Note that PT >= | ||
| 8904 | CHARPOS (startp) because of the outer | ||
| 8905 | if-statement. */ | ||
| 8906 | while (!row->mode_line_p | ||
| 8907 | && (MATRIX_ROW_START_CHARPOS (row) > PT | ||
| 8908 | || (MATRIX_ROW_START_CHARPOS (row) == PT | ||
| 8909 | && MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P (row))) | ||
| 8910 | && (row->y > this_scroll_margin | ||
| 8911 | || CHARPOS (startp) == BEGV)) | ||
| 8912 | { | ||
| 8913 | xassert (row->enabled_p); | ||
| 8914 | --row; | ||
| 8915 | } | ||
| 8916 | |||
| 8917 | /* Consider the following case: Window starts at BEGV, | ||
| 8918 | there is invisible, intangible text at BEGV, so that | ||
| 8919 | display starts at some point START > BEGV. It can | ||
| 8920 | happen that we are called with PT somewhere between | ||
| 8921 | BEGV and START. Try to handle that case. */ | ||
| 8922 | if (row < w->current_matrix->rows | ||
| 8923 | || row->mode_line_p) | ||
| 8924 | { | ||
| 8925 | row = w->current_matrix->rows; | ||
| 8926 | if (row->mode_line_p) | ||
| 8927 | ++row; | ||
| 8928 | } | ||
| 8929 | |||
| 8930 | /* Due to newlines in overlay strings, we may have to | ||
| 8931 | skip forward over overlay strings. */ | ||
| 8932 | while (MATRIX_ROW_END_CHARPOS (row) == PT | ||
| 8933 | && MATRIX_ROW_ENDS_IN_OVERLAY_STRING_P (row) | ||
| 8934 | && !row->ends_at_zv_p) | ||
| 8935 | ++row; | ||
| 8936 | |||
| 8937 | /* If within the scroll margin, scroll. */ | ||
| 8938 | if (row->y < this_scroll_margin | ||
| 8939 | && CHARPOS (startp) != BEGV) | ||
| 8940 | scroll_p = 1; | ||
| 8941 | } | ||
| 8942 | |||
| 8943 | if (PT < MATRIX_ROW_START_CHARPOS (row) | ||
| 8944 | || PT > MATRIX_ROW_END_CHARPOS (row)) | ||
| 8945 | { | ||
| 8946 | /* if PT is not in the glyph row, give up. */ | ||
| 8947 | rc = -1; | ||
| 8948 | } | ||
| 8949 | else if (MATRIX_ROW_PARTIALLY_VISIBLE_P (row) | ||
| 8950 | && window_box_height (w) > row->height) | ||
| 8951 | { | ||
| 8952 | /* If we end up in a partially visible line, let's make it | ||
| 8953 | fully visible, except when it's taller than the window, | ||
| 8954 | in which case we can't do much about it. */ | ||
| 8955 | *scroll_step = 1; | ||
| 8956 | rc = -1; | ||
| 8957 | } | ||
| 8958 | else if (scroll_p) | ||
| 8959 | rc = -1; | ||
| 8960 | else | ||
| 8961 | { | ||
| 8962 | set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0); | ||
| 8963 | rc = 1; | ||
| 8964 | } | ||
| 8965 | } | ||
| 8966 | } | ||
| 8967 | |||
| 8968 | return rc; | ||
| 8969 | } | ||
| 8970 | |||
| 8971 | |||
| 8709 | /* Redisplay leaf window WINDOW. JUST_THIS_ONE_P non-zero means only | 8972 | /* Redisplay leaf window WINDOW. JUST_THIS_ONE_P non-zero means only |
| 8710 | selected_window is redisplayed. */ | 8973 | selected_window is redisplayed. */ |
| 8711 | 8974 | ||
| @@ -8726,6 +8989,7 @@ redisplay_window (window, just_this_one_p) | |||
| 8726 | int current_matrix_up_to_date_p = 0; | 8989 | int current_matrix_up_to_date_p = 0; |
| 8727 | int temp_scroll_step = 0; | 8990 | int temp_scroll_step = 0; |
| 8728 | int count = specpdl_ptr - specpdl; | 8991 | int count = specpdl_ptr - specpdl; |
| 8992 | int rc; | ||
| 8729 | 8993 | ||
| 8730 | SET_TEXT_POS (lpoint, PT, PT_BYTE); | 8994 | SET_TEXT_POS (lpoint, PT, PT_BYTE); |
| 8731 | opoint = lpoint; | 8995 | opoint = lpoint; |
| @@ -8886,7 +9150,6 @@ redisplay_window (window, just_this_one_p) | |||
| 8886 | && CHARPOS (startp) <= ZV) | 9150 | && CHARPOS (startp) <= ZV) |
| 8887 | { | 9151 | { |
| 8888 | w->optional_new_start = Qnil; | 9152 | w->optional_new_start = Qnil; |
| 8889 | /* This takes a mini-buffer prompt into account. */ | ||
| 8890 | start_display (&it, w, startp); | 9153 | start_display (&it, w, startp); |
| 8891 | move_it_to (&it, PT, 0, it.last_visible_y, -1, | 9154 | move_it_to (&it, PT, 0, it.last_visible_y, -1, |
| 8892 | MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y); | 9155 | MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y); |
| @@ -8983,170 +9246,14 @@ redisplay_window (window, just_this_one_p) | |||
| 8983 | /* Handle case where text has not changed, only point, and it has | 9246 | /* Handle case where text has not changed, only point, and it has |
| 8984 | not moved off the frame. */ | 9247 | not moved off the frame. */ |
| 8985 | if (current_matrix_up_to_date_p | 9248 | if (current_matrix_up_to_date_p |
| 8986 | /* Point may be in this window. */ | 9249 | && (rc = try_cursor_movement (window, startp, &temp_scroll_step), |
| 8987 | && PT >= CHARPOS (startp) | 9250 | rc != 0)) |
| 8988 | /* If we don't check this, we are called to move the cursor in a | ||
| 8989 | horizontally split window with a current matrix that doesn't | ||
| 8990 | fit the display. */ | ||
| 8991 | && !windows_or_buffers_changed | ||
| 8992 | /* Selective display hasn't changed. */ | ||
| 8993 | && !current_buffer->clip_changed | ||
| 8994 | /* If force-mode-line-update was called, really redisplay; | ||
| 8995 | that's how redisplay is forced after e.g. changing | ||
| 8996 | buffer-invisibility-spec. */ | ||
| 8997 | && NILP (w->update_mode_line) | ||
| 8998 | /* Can't use this case if highlighting a region. When a | ||
| 8999 | region exists, cursor movement has to do more than just | ||
| 9000 | set the cursor. */ | ||
| 9001 | && !(!NILP (Vtransient_mark_mode) | ||
| 9002 | && !NILP (current_buffer->mark_active)) | ||
| 9003 | && NILP (w->region_showing) | ||
| 9004 | && NILP (Vshow_trailing_whitespace) | ||
| 9005 | /* Right after splitting windows, last_point may be nil. */ | ||
| 9006 | && INTEGERP (w->last_point) | ||
| 9007 | /* This code is not used for mini-buffer for the sake of the case | ||
| 9008 | of redisplaying to replace an echo area message; since in | ||
| 9009 | that case the mini-buffer contents per se are usually | ||
| 9010 | unchanged. This code is of no real use in the mini-buffer | ||
| 9011 | since the handling of this_line_start_pos, etc., in redisplay | ||
| 9012 | handles the same cases. */ | ||
| 9013 | && !EQ (window, minibuf_window) | ||
| 9014 | /* When splitting windows or for new windows, it happens that | ||
| 9015 | redisplay is called with a nil window_end_vpos or one being | ||
| 9016 | larger than the window. This should really be fixed in | ||
| 9017 | window.c. I don't have this on my list, now, so we do | ||
| 9018 | approximately the same as the old redisplay code. --gerd. */ | ||
| 9019 | && INTEGERP (w->window_end_vpos) | ||
| 9020 | && XFASTINT (w->window_end_vpos) < w->current_matrix->nrows | ||
| 9021 | && (FRAME_WINDOW_P (f) | ||
| 9022 | || !MARKERP (Voverlay_arrow_position) | ||
| 9023 | || current_buffer != XMARKER (Voverlay_arrow_position)->buffer)) | ||
| 9024 | { | 9251 | { |
| 9025 | int this_scroll_margin; | 9252 | if (rc == -1) |
| 9026 | struct glyph_row *row; | ||
| 9027 | int scroll_p; | ||
| 9028 | |||
| 9029 | #if GLYPH_DEBUG | ||
| 9030 | debug_method_add (w, "cursor movement"); | ||
| 9031 | #endif | ||
| 9032 | |||
| 9033 | /* Scroll if point within this distance from the top or bottom | ||
| 9034 | of the window. This is a pixel value. */ | ||
| 9035 | this_scroll_margin = max (0, scroll_margin); | ||
| 9036 | this_scroll_margin = min (this_scroll_margin, XFASTINT (w->height) / 4); | ||
| 9037 | this_scroll_margin *= CANON_Y_UNIT (f); | ||
| 9038 | |||
| 9039 | /* Start with the row the cursor was displayed during the last | ||
| 9040 | not paused redisplay. Give up if that row is not valid. */ | ||
| 9041 | if (w->last_cursor.vpos >= w->current_matrix->nrows) | ||
| 9042 | goto try_to_scroll; | ||
| 9043 | row = MATRIX_ROW (w->current_matrix, w->last_cursor.vpos); | ||
| 9044 | if (row->mode_line_p) | ||
| 9045 | ++row; | ||
| 9046 | if (!row->enabled_p) | ||
| 9047 | goto try_to_scroll; | ||
| 9048 | |||
| 9049 | scroll_p = 0; | ||
| 9050 | if (PT > XFASTINT (w->last_point)) | ||
| 9051 | { | ||
| 9052 | /* Point has moved forward. */ | ||
| 9053 | int last_y = window_text_bottom_y (w) - this_scroll_margin; | ||
| 9054 | |||
| 9055 | while (MATRIX_ROW_END_CHARPOS (row) < PT | ||
| 9056 | && MATRIX_ROW_BOTTOM_Y (row) < last_y) | ||
| 9057 | { | ||
| 9058 | xassert (row->enabled_p); | ||
| 9059 | ++row; | ||
| 9060 | } | ||
| 9061 | |||
| 9062 | /* The end position of a row equals the start position of | ||
| 9063 | the next row. If PT is there, we would rather display it | ||
| 9064 | in the next line. Exceptions are when the row ends in | ||
| 9065 | the middle of a character, or ends in ZV. */ | ||
| 9066 | if (MATRIX_ROW_BOTTOM_Y (row) < last_y | ||
| 9067 | && MATRIX_ROW_END_CHARPOS (row) == PT | ||
| 9068 | && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row) | ||
| 9069 | && !row->ends_at_zv_p) | ||
| 9070 | { | ||
| 9071 | xassert (row->enabled_p); | ||
| 9072 | ++row; | ||
| 9073 | } | ||
| 9074 | |||
| 9075 | /* If within the scroll margin, scroll. Note that | ||
| 9076 | MATRIX_ROW_BOTTOM_Y gives the pixel position at which the | ||
| 9077 | next line would be drawn, and that this_scroll_margin can | ||
| 9078 | be zero. */ | ||
| 9079 | if (MATRIX_ROW_BOTTOM_Y (row) > last_y | ||
| 9080 | || PT > MATRIX_ROW_END_CHARPOS (row) | ||
| 9081 | /* Line is completely visible last line in window and PT | ||
| 9082 | is to be set in the next line. */ | ||
| 9083 | || (MATRIX_ROW_BOTTOM_Y (row) == last_y | ||
| 9084 | && PT == MATRIX_ROW_END_CHARPOS (row) | ||
| 9085 | && !row->ends_at_zv_p | ||
| 9086 | && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))) | ||
| 9087 | scroll_p = 1; | ||
| 9088 | } | ||
| 9089 | else if (PT < XFASTINT (w->last_point)) | ||
| 9090 | { | ||
| 9091 | /* Cursor has to be moved backward. Note that PT >= | ||
| 9092 | CHARPOS (startp) because of the outer if-statement. */ | ||
| 9093 | while (!row->mode_line_p | ||
| 9094 | && (MATRIX_ROW_START_CHARPOS (row) > PT | ||
| 9095 | || (MATRIX_ROW_START_CHARPOS (row) == PT | ||
| 9096 | && MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P (row))) | ||
| 9097 | && (row->y > this_scroll_margin | ||
| 9098 | || CHARPOS (startp) == BEGV)) | ||
| 9099 | { | ||
| 9100 | xassert (row->enabled_p); | ||
| 9101 | --row; | ||
| 9102 | } | ||
| 9103 | |||
| 9104 | /* Consider the following case: Window starts at BEGV, there | ||
| 9105 | is invisible, intangible text at BEGV, so that display | ||
| 9106 | starts at some point START > BEGV. It can happen that | ||
| 9107 | we are called with PT somewhere between BEGV and START. | ||
| 9108 | Try to handle that case. */ | ||
| 9109 | if (row < w->current_matrix->rows | ||
| 9110 | || row->mode_line_p) | ||
| 9111 | { | ||
| 9112 | row = w->current_matrix->rows; | ||
| 9113 | if (row->mode_line_p) | ||
| 9114 | ++row; | ||
| 9115 | } | ||
| 9116 | |||
| 9117 | /* Due to newlines in overlay strings, we may have to skip | ||
| 9118 | forward over overlay strings. */ | ||
| 9119 | while (MATRIX_ROW_END_CHARPOS (row) == PT | ||
| 9120 | && MATRIX_ROW_ENDS_IN_OVERLAY_STRING_P (row) | ||
| 9121 | && !row->ends_at_zv_p) | ||
| 9122 | ++row; | ||
| 9123 | |||
| 9124 | /* If within the scroll margin, scroll. */ | ||
| 9125 | if (row->y < this_scroll_margin | ||
| 9126 | && CHARPOS (startp) != BEGV) | ||
| 9127 | scroll_p = 1; | ||
| 9128 | } | ||
| 9129 | |||
| 9130 | /* if PT is not in the glyph row, give up. */ | ||
| 9131 | if (PT < MATRIX_ROW_START_CHARPOS (row) | ||
| 9132 | || PT > MATRIX_ROW_END_CHARPOS (row)) | ||
| 9133 | goto try_to_scroll; | ||
| 9134 | |||
| 9135 | /* If we end up in a partially visible line, let's make it fully | ||
| 9136 | visible. This can be done most easily by using the existing | ||
| 9137 | scrolling code. */ | ||
| 9138 | if (MATRIX_ROW_PARTIALLY_VISIBLE_P (row)) | ||
| 9139 | { | ||
| 9140 | temp_scroll_step = 1; | ||
| 9141 | goto try_to_scroll; | ||
| 9142 | } | ||
| 9143 | else if (scroll_p) | ||
| 9144 | goto try_to_scroll; | 9253 | goto try_to_scroll; |
| 9145 | 9254 | else | |
| 9146 | set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0); | 9255 | goto done; |
| 9147 | goto done; | ||
| 9148 | } | 9256 | } |
| 9149 | |||
| 9150 | /* If current starting point was originally the beginning of a line | 9257 | /* If current starting point was originally the beginning of a line |
| 9151 | but no longer is, find a new starting point. */ | 9258 | but no longer is, find a new starting point. */ |
| 9152 | else if (!NILP (w->start_at_line_beg) | 9259 | else if (!NILP (w->start_at_line_beg) |