aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGerd Moellmann2000-08-10 19:17:01 +0000
committerGerd Moellmann2000-08-10 19:17:01 +0000
commit47589c8c98edf2a457e97df8e55063fd36ac881d (patch)
tree0061e4bdb2257c867d061bd71890b0d87494063e /src
parentcbc099e58429f712b1f88c1ee9b85457ce6e6c0e (diff)
downloademacs-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/ChangeLog23
-rw-r--r--src/xdisp.c469
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 @@
12000-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
12000-08-10 Miles Bader <miles@gnu.org> 242000-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
523int trace_redisplay_p; 524int trace_redisplay_p;
525
526/* Non-zero means trace with TRACE_MOVE to stderr. */
527
528int 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 *));
655static int append_space P_ ((struct it *, int)); 667static int append_space P_ ((struct it *, int));
656static void make_cursor_line_fully_visible P_ ((struct window *)); 668static void make_cursor_line_fully_visible P_ ((struct window *));
657static int try_scrolling P_ ((Lisp_Object, int, int, int, int)); 669static int try_scrolling P_ ((Lisp_Object, int, int, int, int));
670static int try_cursor_movement P_ ((Lisp_Object, struct text_pos, int *));
658static int trailing_whitespace_p P_ ((int)); 671static int trailing_whitespace_p P_ ((int));
659static int message_log_check_duplicate P_ ((int, int, int, int)); 672static int message_log_check_duplicate P_ ((int, int, int, int));
660int invisible_p P_ ((Lisp_Object, Lisp_Object)); 673int 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
8780static int
8781try_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)