Mercurial > emacs
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')) |