aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEli Zaretskii2010-03-13 11:38:01 -0500
committerEli Zaretskii2010-03-13 11:38:01 -0500
commit8eef7665fa98baae93da5151c27ca0db4d1d6f5b (patch)
tree889cf0c172a1ff24484c8f65d8babae7b003fff1
parent9565d1e6f3d09d5cd5afebd1b30a7571a27199cc (diff)
downloademacs-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/.gdbinit2
-rw-r--r--src/ChangeLog.bidi20
-rw-r--r--src/dispextern.h12
-rw-r--r--src/xdisp.c113
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.
614end 614end
615 615
616define prowlims 616define 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
618end 618end
619document prowlims 619document prowlims
620Print important attributes of a glyph_row structure. 620Print 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 @@
12010-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
12010-03-06 Eli Zaretskii <eliz@gnu.org> 212010-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))