diff options
| author | Eli Zaretskii | 2010-03-13 11:38:01 -0500 |
|---|---|---|
| committer | Eli Zaretskii | 2010-03-13 11:38:01 -0500 |
| commit | 8eef7665fa98baae93da5151c27ca0db4d1d6f5b (patch) | |
| tree | 889cf0c172a1ff24484c8f65d8babae7b003fff1 | |
| parent | 9565d1e6f3d09d5cd5afebd1b30a7571a27199cc (diff) | |
| download | emacs-8eef7665fa98baae93da5151c27ca0db4d1d6f5b.tar.gz emacs-8eef7665fa98baae93da5151c27ca0db4d1d6f5b.zip | |
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.
| -rw-r--r-- | src/.gdbinit | 2 | ||||
| -rw-r--r-- | src/ChangeLog.bidi | 20 | ||||
| -rw-r--r-- | src/dispextern.h | 12 | ||||
| -rw-r--r-- | src/xdisp.c | 113 |
4 files changed, 133 insertions, 14 deletions
diff --git a/src/.gdbinit b/src/.gdbinit index 659bc870710..b959baae8f3 100644 --- a/src/.gdbinit +++ b/src/.gdbinit | |||
| @@ -614,7 +614,7 @@ Pretty print all glyphs in it->glyph_row. | |||
| 614 | end | 614 | end |
| 615 | 615 | ||
| 616 | define prowlims | 616 | define prowlims |
| 617 | printf "start=%d,end=%d,reversed=%d,cont=%d\n", $arg0->start.pos.charpos, $arg0->end.pos.charpos, $arg0->reversed_p, $arg0->continued_p | 617 | printf "start=%d,end=%d,reversed=%d,cont=%d,at_zv=%d\n", $arg0->start.pos.charpos, $arg0->end.pos.charpos, $arg0->reversed_p, $arg0->continued_p, $arg0->ends_at_zv_p |
| 618 | end | 618 | end |
| 619 | document prowlims | 619 | document prowlims |
| 620 | Print important attributes of a glyph_row structure. | 620 | Print important attributes of a glyph_row structure. |
diff --git a/src/ChangeLog.bidi b/src/ChangeLog.bidi index 7f7eb0808d2..8f96779196d 100644 --- a/src/ChangeLog.bidi +++ b/src/ChangeLog.bidi | |||
| @@ -1,3 +1,23 @@ | |||
| 1 | 2010-03-13 Eli Zaretskii <eliz@gnu.org> | ||
| 2 | |||
| 3 | * xdisp.c (try_cursor_movement): Give up if rows are | ||
| 4 | bidi-reordered and point moved backwards. Examine all the | ||
| 5 | candidate rows that occlude point, to return the best match. | ||
| 6 | (row_containing_pos): With bidi-reordered rows, don't return the | ||
| 7 | first one that occludes point; rather, examine all candidates and | ||
| 8 | return the best match, with he glyph that's closest to point. | ||
| 9 | (display_line): When looking for min position, don't consider | ||
| 10 | negative values of glyph->charpos. (Fixes a crash with "C-x 3" at | ||
| 11 | ZV.) Record the position after EOL in it->eol_pos, and use it to | ||
| 12 | set end_pos of the last row produced for a continued line. Fix | ||
| 13 | the condition for passing candidate rows to set_cursor_from_row: | ||
| 14 | check ends_at_zv_p flag of the best candidate row, not of the | ||
| 15 | current row. | ||
| 16 | |||
| 17 | * dispextern.h (struct it): New member eol_pos. | ||
| 18 | |||
| 19 | * .gdbinit (prowlims): Display the ends_at_zv_p flag. | ||
| 20 | |||
| 1 | 2010-03-06 Eli Zaretskii <eliz@gnu.org> | 21 | 2010-03-06 Eli Zaretskii <eliz@gnu.org> |
| 2 | 22 | ||
| 3 | * .gdbinit (prowlims, pmtxrows): New commands. | 23 | * .gdbinit (prowlims, pmtxrows): New commands. |
diff --git a/src/dispextern.h b/src/dispextern.h index 2b581fd0eaa..3202385e541 100644 --- a/src/dispextern.h +++ b/src/dispextern.h | |||
| @@ -2016,8 +2016,8 @@ struct it | |||
| 2016 | iterator position in `current'. */ | 2016 | iterator position in `current'. */ |
| 2017 | EMACS_INT prev_stop; | 2017 | EMACS_INT prev_stop; |
| 2018 | 2018 | ||
| 2019 | /* Last stop position iterated across whose embedding level is equal | 2019 | /* Last stop position iterated across whose bidi embedding level is |
| 2020 | to the current paragraph's embedding level. */ | 2020 | equal to the current paragraph's base embedding level. */ |
| 2021 | EMACS_INT base_level_stop; | 2021 | EMACS_INT base_level_stop; |
| 2022 | 2022 | ||
| 2023 | /* Maximum string or buffer position + 1. ZV when iterating over | 2023 | /* Maximum string or buffer position + 1. ZV when iterating over |
| @@ -2327,6 +2327,14 @@ struct it | |||
| 2327 | incremented/reset by display_line, move_it_to etc. */ | 2327 | incremented/reset by display_line, move_it_to etc. */ |
| 2328 | int continuation_lines_width; | 2328 | int continuation_lines_width; |
| 2329 | 2329 | ||
| 2330 | /* Buffer position that ends the buffer text line being iterated. | ||
| 2331 | This is normally the position after the newline at EOL. If this | ||
| 2332 | is the last line of the buffer and it doesn't have a newline, | ||
| 2333 | value is ZV/ZV_BYTE. Set and used only if IT->bidi_p, for | ||
| 2334 | setting the end position of glyph rows produced for continuation | ||
| 2335 | lines, see display_line. */ | ||
| 2336 | struct text_pos eol_pos; | ||
| 2337 | |||
| 2330 | /* Current y-position. Automatically incremented by the height of | 2338 | /* Current y-position. Automatically incremented by the height of |
| 2331 | glyph_row in move_it_to and display_line. */ | 2339 | glyph_row in move_it_to and display_line. */ |
| 2332 | int current_y; | 2340 | int current_y; |
diff --git a/src/xdisp.c b/src/xdisp.c index e481809164d..7fcb5243162 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -13541,6 +13541,12 @@ try_cursor_movement (window, startp, scroll_step) | |||
| 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 |
| @@ -13714,6 +13720,43 @@ try_cursor_movement (window, startp, scroll_step) | |||
| 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 |
| @@ -15339,6 +15382,8 @@ row_containing_pos (w, charpos, start, end, dy) | |||
| 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. */ |
| @@ -15371,7 +15416,30 @@ row_containing_pos (w, charpos, start, end, dy) | |||
| 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 | } |
| @@ -17104,6 +17172,7 @@ display_line (it) | |||
| 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); |
| @@ -17622,7 +17691,7 @@ display_line (it) | |||
| 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; |
| @@ -17640,7 +17709,7 @@ display_line (it) | |||
| 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; |
| @@ -17671,6 +17740,8 @@ display_line (it) | |||
| 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' |
| @@ -17680,13 +17751,32 @@ display_line (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 | } |
| @@ -17709,15 +17799,16 @@ display_line (it) | |||
| 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)) |