Fix C-n/C-p inside bidirectional text
* src/xdisp.c (move_it_by_lines, try_cursor_movement): Handle glyph rows whose direction of increasing buffer positions is reverse of the normal: going down in the window makes buffer positions higher. * src/indent.c (Fvertical_motion): When looking for the last glyph row occupied by point, take into account the bidi iteration direction.
This commit is contained in:
parent
d8abff398b
commit
55c25e73d4
2 changed files with 46 additions and 5 deletions
10
src/indent.c
10
src/indent.c
|
@ -2345,7 +2345,15 @@ whether or not it is currently displayed in some window. */)
|
|||
last line that it occupies. */
|
||||
if (it_start < ZV)
|
||||
{
|
||||
while (IT_CHARPOS (it) <= it_start)
|
||||
if ((it.bidi_it.scan_dir > 0)
|
||||
? IT_CHARPOS (it) < it_start
|
||||
: IT_CHARPOS (it) > it_start)
|
||||
{
|
||||
it.vpos = 0;
|
||||
it.current_y = 0;
|
||||
move_it_by_lines (&it, 1);
|
||||
}
|
||||
while (IT_CHARPOS (it) == it_start)
|
||||
{
|
||||
it.vpos = 0;
|
||||
it.current_y = 0;
|
||||
|
|
41
src/xdisp.c
41
src/xdisp.c
|
@ -10956,15 +10956,21 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
|
|||
int nchars_per_row
|
||||
= (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
|
||||
bool hit_pos_limit = false;
|
||||
bool reverse_rows = false;
|
||||
ptrdiff_t pos_limit;
|
||||
|
||||
/* Start at the beginning of the screen line containing IT's
|
||||
position. This may actually move vertically backwards,
|
||||
in case of overlays, so adjust dvpos accordingly. */
|
||||
dvpos += it->vpos;
|
||||
start_charpos = IT_CHARPOS (*it);
|
||||
move_it_vertically_backward (it, 0);
|
||||
dvpos -= it->vpos;
|
||||
|
||||
/* Do we have glyph rows whose positions _increase_ as we go up? */
|
||||
if (IT_CHARPOS (*it) > start_charpos)
|
||||
reverse_rows = true;
|
||||
|
||||
/* Go back -DVPOS buffer lines, but no farther than -DVPOS full
|
||||
screen lines, and reseat the iterator there. */
|
||||
start_charpos = IT_CHARPOS (*it);
|
||||
|
@ -11015,7 +11021,8 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
|
|||
SAVE_IT (it2, *it, it2data);
|
||||
move_it_to (it, -1, -1, -1, it->vpos + delta, MOVE_TO_VPOS);
|
||||
/* Move back again if we got too far ahead. */
|
||||
if (IT_CHARPOS (*it) >= start_charpos)
|
||||
if ((IT_CHARPOS (*it) >= start_charpos && !reverse_rows)
|
||||
|| (IT_CHARPOS (*it) <= start_charpos && reverse_rows))
|
||||
RESTORE_IT (it, &it2, it2data);
|
||||
else
|
||||
bidi_unshelve_cache (it2data, true);
|
||||
|
@ -18837,6 +18844,8 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp,
|
|||
{
|
||||
/* Cursor has to be moved backward. Note that PT >=
|
||||
CHARPOS (startp) because of the outer if-statement. */
|
||||
struct glyph_row *row0 = row;
|
||||
|
||||
while (!row->mode_line_p
|
||||
&& (MATRIX_ROW_START_CHARPOS (row) > PT
|
||||
|| (MATRIX_ROW_START_CHARPOS (row) == PT
|
||||
|
@ -18851,6 +18860,23 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp,
|
|||
--row;
|
||||
}
|
||||
|
||||
/* With bidi-reordered rows we can have buffer positions
|
||||
_decrease_ when going down by rows. If we haven't
|
||||
found our row in the loop above, give it another try
|
||||
now going in the other direction from the original row. */
|
||||
if (!(MATRIX_ROW_START_CHARPOS (row) <= PT
|
||||
&& PT <= MATRIX_ROW_END_CHARPOS (row))
|
||||
&& row0->continued_p)
|
||||
{
|
||||
row = row0;
|
||||
while (MATRIX_ROW_START_CHARPOS (row) > PT
|
||||
&& MATRIX_ROW_BOTTOM_Y (row) < last_y)
|
||||
{
|
||||
eassert (row->enabled_p);
|
||||
++row;
|
||||
}
|
||||
}
|
||||
|
||||
/* Consider the following case: Window starts at BEGV,
|
||||
there is invisible, intangible text at BEGV, so that
|
||||
display starts at some point START > BEGV. It can
|
||||
|
@ -18874,9 +18900,16 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp,
|
|||
&& !cursor_row_p (row))
|
||||
++row;
|
||||
|
||||
/* If within the scroll margin, scroll. */
|
||||
if (row->y < top_scroll_margin
|
||||
&& CHARPOS (startp) != BEGV)
|
||||
/* If within the scroll margin, either the top one or
|
||||
the bottom one, scroll. */
|
||||
if ((row->y < top_scroll_margin
|
||||
&& CHARPOS (startp) != BEGV)
|
||||
|| MATRIX_ROW_BOTTOM_Y (row) > last_y
|
||||
|| PT > MATRIX_ROW_END_CHARPOS (row)
|
||||
|| (MATRIX_ROW_BOTTOM_Y (row) == last_y
|
||||
&& PT == MATRIX_ROW_END_CHARPOS (row)
|
||||
&& !row->ends_at_zv_p
|
||||
&& !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
|
||||
scroll_p = true;
|
||||
}
|
||||
else
|
||||
|
|
Loading…
Add table
Reference in a new issue