comparison src/xdisp.c @ 30744:6181f12f7f51

(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.
author Gerd Moellmann <gerd@gnu.org>
date Thu, 10 Aug 2000 19:15:37 +0000
parents a87e28789082
children 6c7afd50ec6a
comparison
equal deleted inserted replaced
30743:51d0f4273e89 30744:6181f12f7f51
514 let us call compute_char_face and alike too often because we 514 let us call compute_char_face and alike too often because we
515 might not be interested in text properties that far away. */ 515 might not be interested in text properties that far away. */
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
535
536 #endif /* GLYPH_DEBUG */
525 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
529 int automatic_hscrolling_p; 541 int automatic_hscrolling_p;
653 static struct glyph_row *get_overlay_arrow_glyph_row P_ ((struct window *)); 665 static struct glyph_row *get_overlay_arrow_glyph_row P_ ((struct window *));
654 static void extend_face_to_end_of_line P_ ((struct it *)); 666 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));
661 int invisible_ellipsis_p P_ ((Lisp_Object, Lisp_Object)); 674 int invisible_ellipsis_p P_ ((Lisp_Object, Lisp_Object));
662 static void push_it P_ ((struct it *)); 675 static void push_it P_ ((struct it *));
4263 saved_glyph_row = it->glyph_row; 4276 saved_glyph_row = it->glyph_row;
4264 it->glyph_row = NULL; 4277 it->glyph_row = NULL;
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)
4272 || ((op & MOVE_TO_POS) != 0 4285 || ((op & MOVE_TO_POS) != 0
4273 && BUFFERP (it->object) 4286 && BUFFERP (it->object)
4280 /* The call to produce_glyphs will get the metrics of the 4293 /* The call to produce_glyphs will get the metrics of the
4281 display element IT is loaded with. We record in x the 4294 display element IT is loaded with. We record in x the
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)
4288 { 4310 {
4289 set_iterator_to_next (it); 4311 set_iterator_to_next (it);
4345 it->current_x = new_x; 4367 it->current_x = new_x;
4346 if (i == it->nglyphs - 1) 4368 if (i == it->nglyphs - 1)
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 }
4355 else if (new_x > it->first_visible_x) 4383 else if (new_x > it->first_visible_x)
4356 { 4384 {
4421 int to_charpos, to_x, to_y, to_vpos; 4449 int to_charpos, to_x, to_y, to_vpos;
4422 int op; 4450 int 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;
4426 4454 int reached = 0;
4427 while (1) 4455
4456 for (;;)
4428 { 4457 {
4429 if (op & MOVE_TO_VPOS) 4458 if (op & MOVE_TO_VPOS)
4430 { 4459 {
4431 /* If no TO_CHARPOS and no TO_X specified, stop at the 4460 /* If no TO_CHARPOS and no TO_X specified, stop at the
4432 start of the line TO_VPOS. */ 4461 start of the line TO_VPOS. */
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
4464 problem is that we can't really tell whether the line 4508 problem is that we can't really tell whether the line
4465 contains TO_Y before we have completely scanned it, and 4509 contains TO_Y before we have completely scanned it, and
4477 (MOVE_TO_X 4521 (MOVE_TO_X
4478 | (op & MOVE_TO_POS))); 4522 | (op & MOVE_TO_POS)));
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)
4501 { 4550 {
4502 if (skip == MOVE_X_REACHED) 4551 if (skip == MOVE_X_REACHED)
4503 /* If TO_Y is in this line and TO_X was reached above, 4552 /* If TO_Y is in this line and TO_X was reached above,
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
4520 skip = move_it_in_display_line_to (it, to_charpos, -1, MOVE_TO_POS); 4569 skip = move_it_in_display_line_to (it, to_charpos, -1, MOVE_TO_POS);
4521 4570
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);
4529 it->continuation_lines_width = 0; 4579 it->continuation_lines_width = 0;
4530 break; 4580 break;
4532 case MOVE_LINE_TRUNCATED: 4582 case MOVE_LINE_TRUNCATED:
4533 it->continuation_lines_width = 0; 4583 it->continuation_lines_width = 0;
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:
4541 it->continuation_lines_width += it->current_x; 4594 it->continuation_lines_width += it->current_x;
4542 break; 4595 break;
4552 ++it->vpos; 4605 ++it->vpos;
4553 last_height = it->max_ascent + it->max_descent; 4606 last_height = it->max_ascent + it->max_descent;
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
4561 /* Move iterator IT backward by a specified y-distance DY, DY >= 0. 4617 /* Move iterator IT backward by a specified y-distance DY, DY >= 0.
4562 4618
4601 it2.max_ascent = it2.max_descent = 0; 4657 it2.max_ascent = it2.max_descent = 0;
4602 move_it_to (&it2, start_pos, -1, -1, it2.vpos + 1, 4658 move_it_to (&it2, start_pos, -1, -1, it2.vpos + 1,
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;
4609 nlines = it2.vpos - it->vpos; 4666 nlines = it2.vpos - it->vpos;
4610 4667
4655 { 4712 {
4656 if (dy <= 0) 4713 if (dy <= 0)
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. */
4665 if (IT_CHARPOS (*it) == ZV 4724 if (IT_CHARPOS (*it) == ZV
4666 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n') 4725 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
8509 { 8568 {
8510 int y0; 8569 int y0;
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);
8518 y0 = it.current_y; 8577 y0 = it.current_y;
8519 move_it_to (&it, PT, 0, it.last_visible_y, -1, 8578 move_it_to (&it, PT, 0, it.last_visible_y, -1,
8520 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y); 8579 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
8521 line_height = (it.max_ascent + it.max_descent 8580 line_height = (it.max_ascent + it.max_descent
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
8528 /* Move the window start down. If scrolling conservatively, 8588 /* Move the window start down. If scrolling conservatively,
8529 move it just enough down to make point visible. If 8589 move it just enough down to make point visible. If
8704 8764
8705 return window_start_changed_p; 8765 return window_start_changed_p;
8706 } 8766 }
8707 8767
8708 8768
8709 /* Redisplay leaf window WINDOW. JUST_THIS_ONE_P non-zero means only 8769 /* Try cursor movement in case text has not changes in window WINDOW,
8710 selected_window is redisplayed. */ 8770 with window start STARTP. Value is
8711 8771
8712 static void 8772 1 if successful
8713 redisplay_window (window, just_this_one_p) 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)
8714 Lisp_Object window; 8782 Lisp_Object window;
8715 int just_this_one_p; 8783 struct text_pos startp;
8784 int *scroll_step;
8716 { 8785 {
8717 struct window *w = XWINDOW (window); 8786 struct window *w = XWINDOW (window);
8718 struct frame *f = XFRAME (w->frame); 8787 struct frame *f = XFRAME (w->frame);
8719 struct buffer *buffer = XBUFFER (w->buffer); 8788 int rc = 0;
8720 struct buffer *old = current_buffer; 8789
8721 struct text_pos lpoint, opoint, startp;
8722 int update_mode_line;
8723 int tem;
8724 struct it it;
8725 /* Record it now because it's overwritten. */
8726 int current_matrix_up_to_date_p = 0;
8727 int temp_scroll_step = 0;
8728 int count = specpdl_ptr - specpdl;
8729
8730 SET_TEXT_POS (lpoint, PT, PT_BYTE);
8731 opoint = lpoint;
8732
8733 /* W must be a leaf window here. */
8734 xassert (!NILP (w->buffer));
8735 #if GLYPH_DEBUG
8736 *w->desired_matrix->method = 0;
8737 #endif
8738
8739 specbind (Qinhibit_point_motion_hooks, Qt);
8740
8741 reconsider_clip_changes (w, buffer);
8742
8743 /* Has the mode line to be updated? */
8744 update_mode_line = (!NILP (w->update_mode_line)
8745 || update_mode_lines
8746 || buffer->clip_changed);
8747
8748 if (MINI_WINDOW_P (w))
8749 {
8750 if (w == XWINDOW (echo_area_window)
8751 && !NILP (echo_area_buffer[0]))
8752 {
8753 if (update_mode_line)
8754 /* We may have to update a tty frame's menu bar or a
8755 tool-bar. Example `M-x C-h C-h C-g'. */
8756 goto finish_menu_bars;
8757 else
8758 /* We've already displayed the echo area glyphs in this window. */
8759 goto finish_scroll_bars;
8760 }
8761 else if (w != XWINDOW (minibuf_window))
8762 {
8763 /* W is a mini-buffer window, but it's not the currently
8764 active one, so clear it. */
8765 int yb = window_text_bottom_y (w);
8766 struct glyph_row *row;
8767 int y;
8768
8769 for (y = 0, row = w->desired_matrix->rows;
8770 y < yb;
8771 y += row->height, ++row)
8772 blank_row (w, row, y);
8773 goto finish_scroll_bars;
8774 }
8775 }
8776
8777 /* Otherwise set up data on this window; select its buffer and point
8778 value. */
8779 /* Really select the buffer, for the sake of buffer-local
8780 variables. */
8781 set_buffer_internal_1 (XBUFFER (w->buffer));
8782 SET_TEXT_POS (opoint, PT, PT_BYTE);
8783
8784 current_matrix_up_to_date_p
8785 = (!NILP (w->window_end_valid)
8786 && !current_buffer->clip_changed
8787 && XFASTINT (w->last_modified) >= MODIFF
8788 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF);
8789
8790 /* When windows_or_buffers_changed is non-zero, we can't rely on
8791 the window end being valid, so set it to nil there. */
8792 if (windows_or_buffers_changed)
8793 {
8794 /* If window starts on a continuation line, maybe adjust the
8795 window start in case the window's width changed. */
8796 if (XMARKER (w->start)->buffer == current_buffer)
8797 compute_window_start_on_continuation_line (w);
8798
8799 w->window_end_valid = Qnil;
8800 }
8801
8802 /* Some sanity checks. */
8803 CHECK_WINDOW_END (w);
8804 if (Z == Z_BYTE && CHARPOS (opoint) != BYTEPOS (opoint))
8805 abort ();
8806 if (BYTEPOS (opoint) < CHARPOS (opoint))
8807 abort ();
8808
8809 /* If %c is in mode line, update it if needed. */
8810 if (!NILP (w->column_number_displayed)
8811 /* This alternative quickly identifies a common case
8812 where no change is needed. */
8813 && !(PT == XFASTINT (w->last_point)
8814 && XFASTINT (w->last_modified) >= MODIFF
8815 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
8816 && XFASTINT (w->column_number_displayed) != current_column ())
8817 update_mode_line = 1;
8818
8819 /* Count number of windows showing the selected buffer. An indirect
8820 buffer counts as its base buffer. */
8821 if (!just_this_one_p)
8822 {
8823 struct buffer *current_base, *window_base;
8824 current_base = current_buffer;
8825 window_base = XBUFFER (XWINDOW (selected_window)->buffer);
8826 if (current_base->base_buffer)
8827 current_base = current_base->base_buffer;
8828 if (window_base->base_buffer)
8829 window_base = window_base->base_buffer;
8830 if (current_base == window_base)
8831 buffer_shared++;
8832 }
8833
8834 /* Point refers normally to the selected window. For any other
8835 window, set up appropriate value. */
8836 if (!EQ (window, selected_window))
8837 {
8838 int new_pt = XMARKER (w->pointm)->charpos;
8839 int new_pt_byte = marker_byte_position (w->pointm);
8840 if (new_pt < BEGV)
8841 {
8842 new_pt = BEGV;
8843 new_pt_byte = BEGV_BYTE;
8844 set_marker_both (w->pointm, Qnil, BEGV, BEGV_BYTE);
8845 }
8846 else if (new_pt > (ZV - 1))
8847 {
8848 new_pt = ZV;
8849 new_pt_byte = ZV_BYTE;
8850 set_marker_both (w->pointm, Qnil, ZV, ZV_BYTE);
8851 }
8852
8853 /* We don't use SET_PT so that the point-motion hooks don't run. */
8854 TEMP_SET_PT_BOTH (new_pt, new_pt_byte);
8855 }
8856
8857 /* If any of the character widths specified in the display table
8858 have changed, invalidate the width run cache. It's true that
8859 this may be a bit late to catch such changes, but the rest of
8860 redisplay goes (non-fatally) haywire when the display table is
8861 changed, so why should we worry about doing any better? */
8862 if (current_buffer->width_run_cache)
8863 {
8864 struct Lisp_Char_Table *disptab = buffer_display_table ();
8865
8866 if (! disptab_matches_widthtab (disptab,
8867 XVECTOR (current_buffer->width_table)))
8868 {
8869 invalidate_region_cache (current_buffer,
8870 current_buffer->width_run_cache,
8871 BEG, Z);
8872 recompute_width_table (current_buffer, disptab);
8873 }
8874 }
8875
8876 /* If window-start is screwed up, choose a new one. */
8877 if (XMARKER (w->start)->buffer != current_buffer)
8878 goto recenter;
8879
8880 SET_TEXT_POS_FROM_MARKER (startp, w->start);
8881
8882 /* If someone specified a new starting point but did not insist,
8883 check whether it can be used. */
8884 if (!NILP (w->optional_new_start)
8885 && CHARPOS (startp) >= BEGV
8886 && CHARPOS (startp) <= ZV)
8887 {
8888 w->optional_new_start = Qnil;
8889 /* This takes a mini-buffer prompt into account. */
8890 start_display (&it, w, startp);
8891 move_it_to (&it, PT, 0, it.last_visible_y, -1,
8892 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
8893 if (IT_CHARPOS (it) == PT)
8894 w->force_start = Qt;
8895 }
8896
8897 /* Handle case where place to start displaying has been specified,
8898 unless the specified location is outside the accessible range. */
8899 if (!NILP (w->force_start)
8900 || w->frozen_window_start_p)
8901 {
8902 w->force_start = Qnil;
8903 w->vscroll = 0;
8904 w->window_end_valid = Qnil;
8905
8906 /* Forget any recorded base line for line number display. */
8907 if (!current_matrix_up_to_date_p
8908 || current_buffer->clip_changed)
8909 w->base_line_number = Qnil;
8910
8911 /* Redisplay the mode line. Select the buffer properly for that.
8912 Also, run the hook window-scroll-functions
8913 because we have scrolled. */
8914 /* Note, we do this after clearing force_start because
8915 if there's an error, it is better to forget about force_start
8916 than to get into an infinite loop calling the hook functions
8917 and having them get more errors. */
8918 if (!update_mode_line
8919 || ! NILP (Vwindow_scroll_functions))
8920 {
8921 update_mode_line = 1;
8922 w->update_mode_line = Qt;
8923 startp = run_window_scroll_functions (window, startp);
8924 }
8925
8926 XSETFASTINT (w->last_modified, 0);
8927 XSETFASTINT (w->last_overlay_modified, 0);
8928 if (CHARPOS (startp) < BEGV)
8929 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
8930 else if (CHARPOS (startp) > ZV)
8931 SET_TEXT_POS (startp, ZV, ZV_BYTE);
8932
8933 /* Redisplay, then check if cursor has been set during the
8934 redisplay. Give up if new fonts were loaded. */
8935 if (!try_window (window, startp))
8936 {
8937 w->force_start = Qt;
8938 clear_glyph_matrix (w->desired_matrix);
8939 goto restore_buffers;
8940 }
8941
8942 if (w->cursor.vpos < 0 && !w->frozen_window_start_p)
8943 {
8944 /* If point does not appear, try to move point so it does
8945 appear. The desired matrix has been built above, so we
8946 can use it here. */
8947 int window_height;
8948 struct glyph_row *row;
8949
8950 window_height = window_box_height (w) / 2;
8951 row = MATRIX_FIRST_TEXT_ROW (w->desired_matrix);
8952 while (MATRIX_ROW_BOTTOM_Y (row) < window_height)
8953 ++row;
8954
8955 TEMP_SET_PT_BOTH (MATRIX_ROW_START_CHARPOS (row),
8956 MATRIX_ROW_START_BYTEPOS (row));
8957
8958 if (w != XWINDOW (selected_window))
8959 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
8960 else if (current_buffer == old)
8961 SET_TEXT_POS (lpoint, PT, PT_BYTE);
8962
8963 set_cursor_from_row (w, row, w->desired_matrix, 0, 0, 0, 0);
8964
8965 /* If we are highlighting the region, then we just changed
8966 the region, so redisplay to show it. */
8967 if (!NILP (Vtransient_mark_mode)
8968 && !NILP (current_buffer->mark_active))
8969 {
8970 clear_glyph_matrix (w->desired_matrix);
8971 if (!try_window (window, startp))
8972 goto restore_buffers;
8973 }
8974 }
8975
8976 make_cursor_line_fully_visible (w);
8977 #if GLYPH_DEBUG
8978 debug_method_add (w, "forced window start");
8979 #endif
8980 goto done;
8981 }
8982
8983 /* Handle case where text has not changed, only point, and it has 8790 /* Handle case where text has not changed, only point, and it has
8984 not moved off the frame. */ 8791 not moved off the frame. */
8985 if (current_matrix_up_to_date_p 8792 if (/* Point may be in this window. */
8986 /* Point may be in this window. */ 8793 PT >= CHARPOS (startp)
8987 && PT >= CHARPOS (startp)
8988 /* If we don't check this, we are called to move the cursor in a 8794 /* 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 8795 horizontally split window with a current matrix that doesn't
8990 fit the display. */ 8796 fit the display. */
8991 && !windows_or_buffers_changed 8797 && !windows_or_buffers_changed
8992 /* Selective display hasn't changed. */ 8798 /* Selective display hasn't changed. */
9022 || !MARKERP (Voverlay_arrow_position) 8828 || !MARKERP (Voverlay_arrow_position)
9023 || current_buffer != XMARKER (Voverlay_arrow_position)->buffer)) 8829 || current_buffer != XMARKER (Voverlay_arrow_position)->buffer))
9024 { 8830 {
9025 int this_scroll_margin; 8831 int this_scroll_margin;
9026 struct glyph_row *row; 8832 struct glyph_row *row;
9027 int scroll_p;
9028 8833
9029 #if GLYPH_DEBUG 8834 #if GLYPH_DEBUG
9030 debug_method_add (w, "cursor movement"); 8835 debug_method_add (w, "cursor movement");
9031 #endif 8836 #endif
9032 8837
9037 this_scroll_margin *= CANON_Y_UNIT (f); 8842 this_scroll_margin *= CANON_Y_UNIT (f);
9038 8843
9039 /* Start with the row the cursor was displayed during the last 8844 /* Start with the row the cursor was displayed during the last
9040 not paused redisplay. Give up if that row is not valid. */ 8845 not paused redisplay. Give up if that row is not valid. */
9041 if (w->last_cursor.vpos >= w->current_matrix->nrows) 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
8972 /* Redisplay leaf window WINDOW. JUST_THIS_ONE_P non-zero means only
8973 selected_window is redisplayed. */
8974
8975 static void
8976 redisplay_window (window, just_this_one_p)
8977 Lisp_Object window;
8978 int just_this_one_p;
8979 {
8980 struct window *w = XWINDOW (window);
8981 struct frame *f = XFRAME (w->frame);
8982 struct buffer *buffer = XBUFFER (w->buffer);
8983 struct buffer *old = current_buffer;
8984 struct text_pos lpoint, opoint, startp;
8985 int update_mode_line;
8986 int tem;
8987 struct it it;
8988 /* Record it now because it's overwritten. */
8989 int current_matrix_up_to_date_p = 0;
8990 int temp_scroll_step = 0;
8991 int count = specpdl_ptr - specpdl;
8992 int rc;
8993
8994 SET_TEXT_POS (lpoint, PT, PT_BYTE);
8995 opoint = lpoint;
8996
8997 /* W must be a leaf window here. */
8998 xassert (!NILP (w->buffer));
8999 #if GLYPH_DEBUG
9000 *w->desired_matrix->method = 0;
9001 #endif
9002
9003 specbind (Qinhibit_point_motion_hooks, Qt);
9004
9005 reconsider_clip_changes (w, buffer);
9006
9007 /* Has the mode line to be updated? */
9008 update_mode_line = (!NILP (w->update_mode_line)
9009 || update_mode_lines
9010 || buffer->clip_changed);
9011
9012 if (MINI_WINDOW_P (w))
9013 {
9014 if (w == XWINDOW (echo_area_window)
9015 && !NILP (echo_area_buffer[0]))
9016 {
9017 if (update_mode_line)
9018 /* We may have to update a tty frame's menu bar or a
9019 tool-bar. Example `M-x C-h C-h C-g'. */
9020 goto finish_menu_bars;
9021 else
9022 /* We've already displayed the echo area glyphs in this window. */
9023 goto finish_scroll_bars;
9024 }
9025 else if (w != XWINDOW (minibuf_window))
9026 {
9027 /* W is a mini-buffer window, but it's not the currently
9028 active one, so clear it. */
9029 int yb = window_text_bottom_y (w);
9030 struct glyph_row *row;
9031 int y;
9032
9033 for (y = 0, row = w->desired_matrix->rows;
9034 y < yb;
9035 y += row->height, ++row)
9036 blank_row (w, row, y);
9037 goto finish_scroll_bars;
9038 }
9039 }
9040
9041 /* Otherwise set up data on this window; select its buffer and point
9042 value. */
9043 /* Really select the buffer, for the sake of buffer-local
9044 variables. */
9045 set_buffer_internal_1 (XBUFFER (w->buffer));
9046 SET_TEXT_POS (opoint, PT, PT_BYTE);
9047
9048 current_matrix_up_to_date_p
9049 = (!NILP (w->window_end_valid)
9050 && !current_buffer->clip_changed
9051 && XFASTINT (w->last_modified) >= MODIFF
9052 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF);
9053
9054 /* When windows_or_buffers_changed is non-zero, we can't rely on
9055 the window end being valid, so set it to nil there. */
9056 if (windows_or_buffers_changed)
9057 {
9058 /* If window starts on a continuation line, maybe adjust the
9059 window start in case the window's width changed. */
9060 if (XMARKER (w->start)->buffer == current_buffer)
9061 compute_window_start_on_continuation_line (w);
9062
9063 w->window_end_valid = Qnil;
9064 }
9065
9066 /* Some sanity checks. */
9067 CHECK_WINDOW_END (w);
9068 if (Z == Z_BYTE && CHARPOS (opoint) != BYTEPOS (opoint))
9069 abort ();
9070 if (BYTEPOS (opoint) < CHARPOS (opoint))
9071 abort ();
9072
9073 /* If %c is in mode line, update it if needed. */
9074 if (!NILP (w->column_number_displayed)
9075 /* This alternative quickly identifies a common case
9076 where no change is needed. */
9077 && !(PT == XFASTINT (w->last_point)
9078 && XFASTINT (w->last_modified) >= MODIFF
9079 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
9080 && XFASTINT (w->column_number_displayed) != current_column ())
9081 update_mode_line = 1;
9082
9083 /* Count number of windows showing the selected buffer. An indirect
9084 buffer counts as its base buffer. */
9085 if (!just_this_one_p)
9086 {
9087 struct buffer *current_base, *window_base;
9088 current_base = current_buffer;
9089 window_base = XBUFFER (XWINDOW (selected_window)->buffer);
9090 if (current_base->base_buffer)
9091 current_base = current_base->base_buffer;
9092 if (window_base->base_buffer)
9093 window_base = window_base->base_buffer;
9094 if (current_base == window_base)
9095 buffer_shared++;
9096 }
9097
9098 /* Point refers normally to the selected window. For any other
9099 window, set up appropriate value. */
9100 if (!EQ (window, selected_window))
9101 {
9102 int new_pt = XMARKER (w->pointm)->charpos;
9103 int new_pt_byte = marker_byte_position (w->pointm);
9104 if (new_pt < BEGV)
9105 {
9106 new_pt = BEGV;
9107 new_pt_byte = BEGV_BYTE;
9108 set_marker_both (w->pointm, Qnil, BEGV, BEGV_BYTE);
9109 }
9110 else if (new_pt > (ZV - 1))
9111 {
9112 new_pt = ZV;
9113 new_pt_byte = ZV_BYTE;
9114 set_marker_both (w->pointm, Qnil, ZV, ZV_BYTE);
9115 }
9116
9117 /* We don't use SET_PT so that the point-motion hooks don't run. */
9118 TEMP_SET_PT_BOTH (new_pt, new_pt_byte);
9119 }
9120
9121 /* If any of the character widths specified in the display table
9122 have changed, invalidate the width run cache. It's true that
9123 this may be a bit late to catch such changes, but the rest of
9124 redisplay goes (non-fatally) haywire when the display table is
9125 changed, so why should we worry about doing any better? */
9126 if (current_buffer->width_run_cache)
9127 {
9128 struct Lisp_Char_Table *disptab = buffer_display_table ();
9129
9130 if (! disptab_matches_widthtab (disptab,
9131 XVECTOR (current_buffer->width_table)))
9132 {
9133 invalidate_region_cache (current_buffer,
9134 current_buffer->width_run_cache,
9135 BEG, Z);
9136 recompute_width_table (current_buffer, disptab);
9137 }
9138 }
9139
9140 /* If window-start is screwed up, choose a new one. */
9141 if (XMARKER (w->start)->buffer != current_buffer)
9142 goto recenter;
9143
9144 SET_TEXT_POS_FROM_MARKER (startp, w->start);
9145
9146 /* If someone specified a new starting point but did not insist,
9147 check whether it can be used. */
9148 if (!NILP (w->optional_new_start)
9149 && CHARPOS (startp) >= BEGV
9150 && CHARPOS (startp) <= ZV)
9151 {
9152 w->optional_new_start = Qnil;
9153 start_display (&it, w, startp);
9154 move_it_to (&it, PT, 0, it.last_visible_y, -1,
9155 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
9156 if (IT_CHARPOS (it) == PT)
9157 w->force_start = Qt;
9158 }
9159
9160 /* Handle case where place to start displaying has been specified,
9161 unless the specified location is outside the accessible range. */
9162 if (!NILP (w->force_start)
9163 || w->frozen_window_start_p)
9164 {
9165 w->force_start = Qnil;
9166 w->vscroll = 0;
9167 w->window_end_valid = Qnil;
9168
9169 /* Forget any recorded base line for line number display. */
9170 if (!current_matrix_up_to_date_p
9171 || current_buffer->clip_changed)
9172 w->base_line_number = Qnil;
9173
9174 /* Redisplay the mode line. Select the buffer properly for that.
9175 Also, run the hook window-scroll-functions
9176 because we have scrolled. */
9177 /* Note, we do this after clearing force_start because
9178 if there's an error, it is better to forget about force_start
9179 than to get into an infinite loop calling the hook functions
9180 and having them get more errors. */
9181 if (!update_mode_line
9182 || ! NILP (Vwindow_scroll_functions))
9183 {
9184 update_mode_line = 1;
9185 w->update_mode_line = Qt;
9186 startp = run_window_scroll_functions (window, startp);
9187 }
9188
9189 XSETFASTINT (w->last_modified, 0);
9190 XSETFASTINT (w->last_overlay_modified, 0);
9191 if (CHARPOS (startp) < BEGV)
9192 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
9193 else if (CHARPOS (startp) > ZV)
9194 SET_TEXT_POS (startp, ZV, ZV_BYTE);
9195
9196 /* Redisplay, then check if cursor has been set during the
9197 redisplay. Give up if new fonts were loaded. */
9198 if (!try_window (window, startp))
9199 {
9200 w->force_start = Qt;
9201 clear_glyph_matrix (w->desired_matrix);
9202 goto restore_buffers;
9203 }
9204
9205 if (w->cursor.vpos < 0 && !w->frozen_window_start_p)
9206 {
9207 /* If point does not appear, try to move point so it does
9208 appear. The desired matrix has been built above, so we
9209 can use it here. */
9210 int window_height;
9211 struct glyph_row *row;
9212
9213 window_height = window_box_height (w) / 2;
9214 row = MATRIX_FIRST_TEXT_ROW (w->desired_matrix);
9215 while (MATRIX_ROW_BOTTOM_Y (row) < window_height)
9216 ++row;
9217
9218 TEMP_SET_PT_BOTH (MATRIX_ROW_START_CHARPOS (row),
9219 MATRIX_ROW_START_BYTEPOS (row));
9220
9221 if (w != XWINDOW (selected_window))
9222 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
9223 else if (current_buffer == old)
9224 SET_TEXT_POS (lpoint, PT, PT_BYTE);
9225
9226 set_cursor_from_row (w, row, w->desired_matrix, 0, 0, 0, 0);
9227
9228 /* If we are highlighting the region, then we just changed
9229 the region, so redisplay to show it. */
9230 if (!NILP (Vtransient_mark_mode)
9231 && !NILP (current_buffer->mark_active))
9232 {
9233 clear_glyph_matrix (w->desired_matrix);
9234 if (!try_window (window, startp))
9235 goto restore_buffers;
9236 }
9237 }
9238
9239 make_cursor_line_fully_visible (w);
9240 #if GLYPH_DEBUG
9241 debug_method_add (w, "forced window start");
9242 #endif
9243 goto done;
9244 }
9245
9246 /* Handle case where text has not changed, only point, and it has
9247 not moved off the frame. */
9248 if (current_matrix_up_to_date_p
9249 && (rc = try_cursor_movement (window, startp, &temp_scroll_step),
9250 rc != 0))
9251 {
9252 if (rc == -1)
9042 goto try_to_scroll; 9253 goto try_to_scroll;
9043 row = MATRIX_ROW (w->current_matrix, w->last_cursor.vpos); 9254 else
9044 if (row->mode_line_p) 9255 goto done;
9045 ++row; 9256 }
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;
9145
9146 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
9147 goto done;
9148 }
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)
9153 && !(CHARPOS (startp) <= BEGV 9260 && !(CHARPOS (startp) <= BEGV
9154 || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n')) 9261 || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n'))