Mercurial > emacs
comparison src/xdisp.c @ 107641:d65c199e8bdd
Continue work on cursor movement in continued lines.
xdisp.c (try_cursor_movement): Give up if rows are
bidi-reordered and point moved backwards. Examine all the
candidate rows that occlude point, to return the best match.
(row_containing_pos): With bidi-reordered rows, don't return the
first one that occludes point; rather, examine all candidates and
return the best match, with he glyph that's closest to point.
(display_line): When looking for min position, don't consider
negative values of glyph->charpos. (Fixes a crash with "C-x 3" at
ZV.) Record the position after EOL in it->eol_pos, and use it to
set end_pos of the last row produced for a continued line. Fix
the condition for passing candidate rows to set_cursor_from_row:
check ends_at_zv_p flag of the best candidate row, not of the
current row.
dispextern.h (struct it): New member eol_pos.
.gdbinit (prowlims): Display the ends_at_zv_p flag.
author | Eli Zaretskii <eliz@gnu.org> |
---|---|
date | Sat, 13 Mar 2010 11:38:01 -0500 |
parents | 844012bdb5dd |
children | a5c1ccd17b3c |
comparison
equal
deleted
inserted
replaced
107640:a744b1df50bd | 107641:d65c199e8bdd |
---|---|
13539 && !NILP (current_buffer->mark_active)) | 13539 && !NILP (current_buffer->mark_active)) |
13540 && NILP (w->region_showing) | 13540 && NILP (w->region_showing) |
13541 && NILP (Vshow_trailing_whitespace) | 13541 && NILP (Vshow_trailing_whitespace) |
13542 /* Right after splitting windows, last_point may be nil. */ | 13542 /* Right after splitting windows, last_point may be nil. */ |
13543 && INTEGERP (w->last_point) | 13543 && INTEGERP (w->last_point) |
13544 /* Can't use this optimization if rows were bidi-reordered and | |
13545 point moved backwards, because that would mean we would need | |
13546 to examine previous rows that came from the same continued | |
13547 line. */ | |
13548 && (PT > XFASTINT (w->last_point) | |
13549 || NILP (XBUFFER (w->buffer)->bidi_display_reordering)) | |
13544 /* This code is not used for mini-buffer for the sake of the case | 13550 /* This code is not used for mini-buffer for the sake of the case |
13545 of redisplaying to replace an echo area message; since in | 13551 of redisplaying to replace an echo area message; since in |
13546 that case the mini-buffer contents per se are usually | 13552 that case the mini-buffer contents per se are usually |
13547 unchanged. This code is of no real use in the mini-buffer | 13553 unchanged. This code is of no real use in the mini-buffer |
13548 since the handling of this_line_start_pos, etc., in redisplay | 13554 since the handling of this_line_start_pos, etc., in redisplay |
13712 rc = CURSOR_MOVEMENT_SUCCESS; | 13718 rc = CURSOR_MOVEMENT_SUCCESS; |
13713 } | 13719 } |
13714 } | 13720 } |
13715 else if (scroll_p) | 13721 else if (scroll_p) |
13716 rc = CURSOR_MOVEMENT_MUST_SCROLL; | 13722 rc = CURSOR_MOVEMENT_MUST_SCROLL; |
13723 else if (!NILP (XBUFFER (w->buffer)->bidi_display_reordering)) | |
13724 { | |
13725 /* With bidi-reordered rows, there could be more than | |
13726 one candidate row whose start and end positions | |
13727 occlude point. We need to find the best | |
13728 candidate. */ | |
13729 int rv = 0; | |
13730 | |
13731 do | |
13732 { | |
13733 rv |= set_cursor_from_row (w, row, w->current_matrix, | |
13734 0, 0, 0, 0); | |
13735 /* As soon as we've found the first suitable row | |
13736 whose ends_at_zv_p flag is set, we are done. */ | |
13737 if (rv | |
13738 && MATRIX_ROW (w->current_matrix, w->cursor.vpos)->ends_at_zv_p) | |
13739 { | |
13740 rc = CURSOR_MOVEMENT_SUCCESS; | |
13741 break; | |
13742 } | |
13743 ++row; | |
13744 } | |
13745 while (MATRIX_ROW_BOTTOM_Y (row) < last_y | |
13746 && MATRIX_ROW_START_CHARPOS (row) <= PT | |
13747 && PT <= MATRIX_ROW_END_CHARPOS (row) | |
13748 && cursor_row_p (w, row)); | |
13749 /* If we didn't find any candidate rows, or exited the | |
13750 loop before all the candidates were examined, signal | |
13751 to the caller that this method failed. */ | |
13752 if (rc != CURSOR_MOVEMENT_SUCCESS | |
13753 && (!rv | |
13754 || (MATRIX_ROW_START_CHARPOS (row) <= PT | |
13755 && PT <= MATRIX_ROW_END_CHARPOS (row)))) | |
13756 rc = CURSOR_MOVEMENT_CANNOT_BE_USED; | |
13757 else | |
13758 rc = CURSOR_MOVEMENT_SUCCESS; | |
13759 } | |
13717 else | 13760 else |
13718 { | 13761 { |
13719 do | 13762 do |
13720 { | 13763 { |
13721 if (set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0)) | 13764 if (set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0)) |
15337 int charpos; | 15380 int charpos; |
15338 struct glyph_row *start, *end; | 15381 struct glyph_row *start, *end; |
15339 int dy; | 15382 int dy; |
15340 { | 15383 { |
15341 struct glyph_row *row = start; | 15384 struct glyph_row *row = start; |
15385 struct glyph_row *best_row = NULL; | |
15386 EMACS_INT mindif = BUF_ZV (XBUFFER (w->buffer)) + 1; | |
15342 int last_y; | 15387 int last_y; |
15343 | 15388 |
15344 /* If we happen to start on a header-line, skip that. */ | 15389 /* If we happen to start on a header-line, skip that. */ |
15345 if (row->mode_line_p) | 15390 if (row->mode_line_p) |
15346 ++row; | 15391 ++row; |
15369 would rather display it in the next line, except | 15414 would rather display it in the next line, except |
15370 when this line ends in ZV. */ | 15415 when this line ends in ZV. */ |
15371 && !row->ends_at_zv_p | 15416 && !row->ends_at_zv_p |
15372 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))) | 15417 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))) |
15373 && charpos >= MATRIX_ROW_START_CHARPOS (row)) | 15418 && charpos >= MATRIX_ROW_START_CHARPOS (row)) |
15374 return row; | 15419 { |
15420 struct glyph *g; | |
15421 | |
15422 if (NILP (XBUFFER (w->buffer)->bidi_display_reordering)) | |
15423 return row; | |
15424 /* In bidi-reordered rows, there could be several rows | |
15425 occluding point. We need to find the one which fits | |
15426 CHARPOS the best. */ | |
15427 for (g = row->glyphs[TEXT_AREA]; | |
15428 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]; | |
15429 g++) | |
15430 { | |
15431 if (!STRINGP (g->object)) | |
15432 { | |
15433 if (g->charpos > 0 && eabs (g->charpos - charpos) < mindif) | |
15434 { | |
15435 mindif = eabs (g->charpos - charpos); | |
15436 best_row = row; | |
15437 } | |
15438 } | |
15439 } | |
15440 } | |
15441 else if (best_row) | |
15442 return best_row; | |
15375 ++row; | 15443 ++row; |
15376 } | 15444 } |
15377 } | 15445 } |
15378 | 15446 |
15379 | 15447 |
17102 int may_wrap = 0, wrap_x; | 17170 int may_wrap = 0, wrap_x; |
17103 int wrap_row_used = -1, wrap_row_ascent, wrap_row_height; | 17171 int wrap_row_used = -1, wrap_row_ascent, wrap_row_height; |
17104 int wrap_row_phys_ascent, wrap_row_phys_height; | 17172 int wrap_row_phys_ascent, wrap_row_phys_height; |
17105 int wrap_row_extra_line_spacing; | 17173 int wrap_row_extra_line_spacing; |
17106 struct display_pos row_end; | 17174 struct display_pos row_end; |
17175 int cvpos; | |
17107 | 17176 |
17108 /* We always start displaying at hpos zero even if hscrolled. */ | 17177 /* We always start displaying at hpos zero even if hscrolled. */ |
17109 xassert (it->hpos == 0 && it->current_x == 0); | 17178 xassert (it->hpos == 0 && it->current_x == 0); |
17110 | 17179 |
17111 if (MATRIX_ROW_VPOS (row, it->w->desired_matrix) | 17180 if (MATRIX_ROW_VPOS (row, it->w->desired_matrix) |
17620 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]; | 17689 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]; |
17621 g++) | 17690 g++) |
17622 { | 17691 { |
17623 if (BUFFERP (g->object)) | 17692 if (BUFFERP (g->object)) |
17624 { | 17693 { |
17625 if (g->charpos && g->charpos < min_pos) | 17694 if (g->charpos > 0 && g->charpos < min_pos) |
17626 min_pos = g->charpos; | 17695 min_pos = g->charpos; |
17627 if (g->charpos > max_pos) | 17696 if (g->charpos > max_pos) |
17628 max_pos = g->charpos; | 17697 max_pos = g->charpos; |
17629 } | 17698 } |
17630 } | 17699 } |
17638 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]; | 17707 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]; |
17639 g++) | 17708 g++) |
17640 { | 17709 { |
17641 if (INTEGERP (g->object)) | 17710 if (INTEGERP (g->object)) |
17642 { | 17711 { |
17643 if (g->charpos && g->charpos < min_pos) | 17712 if (g->charpos > 0 && g->charpos < min_pos) |
17644 min_pos = g->charpos; | 17713 min_pos = g->charpos; |
17645 if (g->charpos > max_pos) | 17714 if (g->charpos > max_pos) |
17646 max_pos = g->charpos; | 17715 max_pos = g->charpos; |
17647 } | 17716 } |
17648 } | 17717 } |
17669 } | 17738 } |
17670 } | 17739 } |
17671 else if (row->used[TEXT_AREA] && max_pos) | 17740 else if (row->used[TEXT_AREA] && max_pos) |
17672 { | 17741 { |
17673 SET_TEXT_POS (tpos, max_pos + 1, CHAR_TO_BYTE (max_pos + 1)); | 17742 SET_TEXT_POS (tpos, max_pos + 1, CHAR_TO_BYTE (max_pos + 1)); |
17743 row_end = it->current; | |
17744 row_end.pos = tpos; | |
17674 /* If the character at max_pos+1 is a newline, skip that as | 17745 /* If the character at max_pos+1 is a newline, skip that as |
17675 well. Note that this may skip some invisible text. */ | 17746 well. Note that this may skip some invisible text. */ |
17676 if (FETCH_CHAR (tpos.bytepos) == '\n' | 17747 if (FETCH_CHAR (tpos.bytepos) == '\n' |
17677 || (FETCH_CHAR (tpos.bytepos) == '\r' && it->selective)) | 17748 || (FETCH_CHAR (tpos.bytepos) == '\r' && it->selective)) |
17678 { | 17749 { |
17679 save_it = *it; | 17750 save_it = *it; |
17680 it->bidi_p = 0; | 17751 it->bidi_p = 0; |
17681 reseat_1 (it, tpos, 0); | 17752 reseat_1 (it, tpos, 0); |
17682 set_iterator_to_next (it, 1); | 17753 set_iterator_to_next (it, 1); |
17683 row_end = it->current; | 17754 /* Record the position after the newline of a continued |
17755 row. We will need that to set ROW->end of the last | |
17756 row produced for a continued line. */ | |
17757 if (row->continued_p) | |
17758 { | |
17759 save_it.eol_pos.charpos = IT_CHARPOS (*it); | |
17760 save_it.eol_pos.bytepos = IT_BYTEPOS (*it); | |
17761 } | |
17762 else | |
17763 { | |
17764 row_end = it->current; | |
17765 save_it.eol_pos.charpos = save_it.eol_pos.bytepos = 0; | |
17766 } | |
17684 *it = save_it; | 17767 *it = save_it; |
17685 } | 17768 } |
17686 else | 17769 else if (!row->continued_p |
17770 && row->continuation_lines_width | |
17771 && it->eol_pos.charpos > 0) | |
17687 { | 17772 { |
17688 row_end = it->current; | 17773 /* Last row of a continued line. Use the position |
17689 row_end.pos = tpos; | 17774 recorded in ROW->eol_pos, to the effect that the |
17775 newline belongs to this row, not to the row which | |
17776 displays the character with the largest buffer | |
17777 position. */ | |
17778 row_end.pos = it->eol_pos; | |
17779 it->eol_pos.charpos = it->eol_pos.bytepos = 0; | |
17690 } | 17780 } |
17691 row->end = row_end; | 17781 row->end = row_end; |
17692 } | 17782 } |
17693 } | 17783 } |
17694 | 17784 |
17707 it->left_user_fringe_face_id = 0; | 17797 it->left_user_fringe_face_id = 0; |
17708 it->right_user_fringe_bitmap = 0; | 17798 it->right_user_fringe_bitmap = 0; |
17709 it->right_user_fringe_face_id = 0; | 17799 it->right_user_fringe_face_id = 0; |
17710 | 17800 |
17711 /* Maybe set the cursor. */ | 17801 /* Maybe set the cursor. */ |
17712 if ((it->w->cursor.vpos < 0 | 17802 cvpos = it->w->cursor.vpos; |
17803 if ((cvpos < 0 | |
17713 /* In bidi-reordered rows, keep checking for proper cursor | 17804 /* In bidi-reordered rows, keep checking for proper cursor |
17714 position even if one has been found already, because buffer | 17805 position even if one has been found already, because buffer |
17715 positions in such rows change non-linearly with ROW->VPOS, | 17806 positions in such rows change non-linearly with ROW->VPOS, |
17716 when a line is continued. One exception: when we are at ZV, | 17807 when a line is continued. One exception: when we are at ZV, |
17717 display cursor on the first suitable glyph row, since all | 17808 display cursor on the first suitable glyph row, since all |
17718 the empty rows after that also have their ends_at_zv_p flag | 17809 the empty rows after that also have their position set to ZV. */ |
17719 set. */ | 17810 || (it->bidi_p |
17720 || (it->bidi_p && !row->ends_at_zv_p)) | 17811 && !MATRIX_ROW (it->w->desired_matrix, cvpos)->ends_at_zv_p)) |
17721 && PT >= MATRIX_ROW_START_CHARPOS (row) | 17812 && PT >= MATRIX_ROW_START_CHARPOS (row) |
17722 && PT <= MATRIX_ROW_END_CHARPOS (row) | 17813 && PT <= MATRIX_ROW_END_CHARPOS (row) |
17723 && cursor_row_p (it->w, row)) | 17814 && cursor_row_p (it->w, row)) |
17724 set_cursor_from_row (it->w, row, it->w->desired_matrix, 0, 0, 0, 0); | 17815 set_cursor_from_row (it->w, row, it->w->desired_matrix, 0, 0, 0, 0); |
17725 | 17816 |