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