/* First position in this row. This is the text position, including
overlay position information etc, where the display of this row
- started, and can thus be less the position of the first glyph
- (e.g. due to invisible text or horizontal scrolling). BIDI Note:
- This is the smallest character position in the row, but not
- necessarily the character that is the leftmost on the display. */
+ started, and can thus be less than the position of the first
+ glyph (e.g. due to invisible text or horizontal scrolling).
+ BIDI Note: In R2L rows, that have its reversed_p flag set, this
+ position is at or beyond the right edge of the row. */
struct display_pos start;
/* Text position at the end of this row. This is the position after
the last glyph on this row. It can be greater than the last
- glyph position + 1, due to truncation, invisible text etc. In an
- up-to-date display, this should always be equal to the start
- position of the next row. BIDI Note: this is the character whose
- buffer position is the largest, but not necessarily the rightmost
- one on the display. */
+ glyph position + 1, due to a newline that ends the line,
+ truncation, invisible text etc. In an up-to-date display, this
+ should always be equal to the start position of the next row.
+ BIDI Note: In R2L rows, this position is at or beyond the left
+ edge of the row. */
struct display_pos end;
+ /* The smallest and the largest buffer positions that contributed to
+ glyphs in this row. Note that due to bidi reordering, these are
+ in general different from the text positions stored in `start'
+ and `end' members above, and also different from the buffer
+ positions recorded in the glyphs displayed the leftmost and
+ rightmost on the screen. */
+ struct text_pos minpos, maxpos;
+
/* Non-zero means the overlay arrow bitmap is on this line.
-1 means use default overlay arrow bitmap, else
it specifies actual fringe bitmap number. */
displayed by ROW, which is not necessarily the smallest horizontal
position. */
-#define MATRIX_ROW_START_CHARPOS(ROW) ((ROW)->start.pos.charpos)
-#define MATRIX_ROW_START_BYTEPOS(ROW) ((ROW)->start.pos.bytepos)
+#define MATRIX_ROW_START_CHARPOS(ROW) ((ROW)->minpos.charpos)
+#define MATRIX_ROW_START_BYTEPOS(ROW) ((ROW)->minpos.bytepos)
/* Return the character/ byte position at which ROW ends. BIDI Note:
this is the largest character/byte position among characters in
ROW, i.e. the last logical-order character displayed by ROW, which
is not necessarily the largest horizontal position. */
-#define MATRIX_ROW_END_CHARPOS(ROW) ((ROW)->end.pos.charpos)
-#define MATRIX_ROW_END_BYTEPOS(ROW) ((ROW)->end.pos.bytepos)
+#define MATRIX_ROW_END_CHARPOS(ROW) ((ROW)->maxpos.charpos)
+#define MATRIX_ROW_END_BYTEPOS(ROW) ((ROW)->maxpos.bytepos)
/* Return the vertical position of ROW in MATRIX. */
EMACS_INT next_en_pos; /* position of next EN char for ET */
EMACS_INT ignore_bn_limit; /* position until which to ignore BNs */
bidi_dir_t sor; /* direction of start-of-run in effect */
- int scan_dir; /* direction of text scan */
+ int scan_dir; /* direction of text scan, 1: forw, -1: back */
int stack_idx; /* index of current data on the stack */
/* Note: Everything from here on is not copied/saved when the bidi
iterator state is saved, pushed, or popped. So only put here
init_iterator (it, w, charpos, bytepos, row, base_face_id)
struct it *it;
struct window *w;
- int charpos, bytepos;
+ EMACS_INT charpos, bytepos;
struct glyph_row *row;
enum face_id base_face_id;
{
struct window *w;
struct display_pos *pos;
{
- int charpos = CHARPOS (pos->pos), bytepos = BYTEPOS (pos->pos);
+ EMACS_INT charpos = CHARPOS (pos->pos), bytepos = BYTEPOS (pos->pos);
int i, overlay_strings_with_newlines = 0;
/* If POS specifies a position in a display vector, this might
/* The variable new_start now holds the new window start. The old
start `start' can be determined from the current matrix. */
SET_TEXT_POS_FROM_MARKER (new_start, w->start);
- start = start_row->start.pos;
+ start = start_row->minpos;
start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
/* Clear the desired matrix for the display below. */
{
/* Advance to the next row as the "start". */
start_row++;
- start = start_row->start.pos;
+ start = start_row->minpos;
/* If there are no more rows to try, or just one, give up. */
if (start_row == MATRIX_MODE_LINE_ROW (w->current_matrix) - 1
|| w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row)
as is, without changing glyph positions since no text has
been added/removed in front of the window end. */
r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
- if (TEXT_POS_EQUAL_P (start, r0->start.pos)
+ if (TEXT_POS_EQUAL_P (start, r0->minpos)
/* PT must not be in a partially visible line. */
&& !(PT >= MATRIX_ROW_START_CHARPOS (row)
&& MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
{
/* We have to compute the window end anew since text
- can have been added/removed after it. */
+ could have been added/removed after it. */
w->window_end_pos
= make_number (Z - MATRIX_ROW_END_CHARPOS (row));
w->window_end_bytepos
start is not in changed text, otherwise positions would not be
comparable. */
row = MATRIX_FIRST_TEXT_ROW (current_matrix);
- if (!TEXT_POS_EQUAL_P (start, row->start.pos))
+ if (!TEXT_POS_EQUAL_P (start, row->minpos))
GIVE_UP (16);
/* Give up if the window ends in strings. Overlay strings
{
int cursor_row_p = 1;
- if (PT == MATRIX_ROW_END_CHARPOS (row))
+ if (PT == CHARPOS (row->end.pos))
{
/* Suppose the row ends on a string.
Unless the row is continued, that means it ends on a newline
{
/* If the row ends in middle of a real character,
and the line is continued, we want the cursor here.
- That's because MATRIX_ROW_END_CHARPOS would equal
+ That's because CHARPOS (ROW->end.pos) would equal
PT if PT is before the character. */
if (!row->ends_in_ellipsis_p)
cursor_row_p = row->continued_p;
else
/* If the row ends in an ellipsis, then
- MATRIX_ROW_END_CHARPOS will equal point after the invisible text.
- We want that position to be displayed after the ellipsis. */
+ CHARPOS (ROW->end.pos) will equal point after the
+ invisible text. We want that position to be displayed
+ after the ellipsis. */
cursor_row_p = 0;
}
/* If the row ends at ZV, display the cursor at the end of that
glyph[-n] = *glyph;
}
-/* Find the positions in a bidi-reordered ROW to serve as ROW->start
- and ROW->end. */
-static struct display_pos
-find_row_end (it, row)
+/* Find the positions in a bidi-reordered ROW to serve as ROW->minpos
+ and ROW->maxpos. */
+static void
+find_row_edges (it, row, min_pos, min_bpos, max_pos, max_bpos)
struct it *it;
struct glyph_row *row;
+ EMACS_INT min_pos, min_bpos, max_pos, max_bpos;
{
/* FIXME: Revisit this when glyph ``spilling'' in continuation
lines' rows is implemented for bidi-reordered rows. */
- EMACS_INT min_pos = ZV + 1, max_pos = 0;
- struct glyph *g;
- struct it save_it;
- struct text_pos tpos;
- struct display_pos row_end = it->current;
- for (g = row->glyphs[TEXT_AREA];
- g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
- g++)
+ /* ROW->minpos is the value of min_pos, the minimal buffer position
+ we have in ROW. */
+ if (min_pos <= ZV)
{
- if (BUFFERP (g->object))
+ SET_TEXT_POS (row->minpos, min_pos, min_bpos);
+ if (max_pos == 0)
{
- if (g->charpos > 0 && g->charpos < min_pos)
- min_pos = g->charpos;
- if (g->charpos > max_pos)
- max_pos = g->charpos;
+ max_pos = min_pos;
+ max_bpos = min_bpos;
}
}
- /* Empty lines have a valid buffer position at their first
- glyph, but that glyph's OBJECT is zero, as if it didn't come
- from a buffer. If we didn't find any valid buffer positions
- in this row, maybe we have such an empty line. */
- if (max_pos == 0 && row->used[TEXT_AREA])
+ else
{
- for (g = row->glyphs[TEXT_AREA];
- g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
- g++)
- {
- if (INTEGERP (g->object))
- {
- if (g->charpos > 0 && g->charpos < min_pos)
- min_pos = g->charpos;
- if (g->charpos > max_pos)
- max_pos = g->charpos;
- }
- }
+ /* We didn't find _any_ valid buffer positions in any of the
+ glyphs, so we must trust the iterator's computed
+ positions. */
+ row->minpos = row->start.pos;
+ max_pos = CHARPOS (it->current.pos);
+ max_bpos = BYTEPOS (it->current.pos);
}
- /* ROW->start is the value of min_pos, the minimal buffer position
- we have in ROW. */
- if (min_pos <= ZV)
- {
- /* Avoid calling the costly CHAR_TO_BYTE if possible. */
- if (min_pos != row->start.pos.charpos)
- SET_TEXT_POS (row->start.pos, min_pos, CHAR_TO_BYTE (min_pos));
- if (max_pos == 0)
- max_pos = min_pos;
- }
+ if (!max_pos)
+ abort ();
- /* For ROW->end, we need the position that is _after_ max_pos, in
- the logical order, unless we are at ZV. */
+ /* Here are the various use-cases for ending the row, and the
+ corresponding values for ROW->maxpos:
+
+ Empty line min_pos + 1
+ Line ends in a newline from buffer eol_pos + 1
+ Line is continued from buffer max_pos + 1
+ Line ends in a newline from string max_pos
+ Line is continued from string max_pos
+ Line is entirely from a string min_pos
+ Line that ends at ZV ZV
+
+ If you discover other use-cases, please add them here as
+ appropriate. */
if (row->ends_at_zv_p)
+ row->maxpos = it->current.pos;
+ else if (row->used[TEXT_AREA])
{
- if (!row->used[TEXT_AREA])
- row->start.pos = row_end.pos;
- }
- else if (row->used[TEXT_AREA] && max_pos)
- {
- int at_eol_p;
-
- SET_TEXT_POS (tpos, max_pos, CHAR_TO_BYTE (max_pos));
- save_it = *it;
- it->bidi_p = 0;
- reseat (it, tpos, 0);
- if (!get_next_display_element (it))
- abort (); /* this row cannot be at ZV, see above */
- at_eol_p = ITERATOR_AT_END_OF_LINE_P (it);
- set_iterator_to_next (it, 1);
- row_end = it->current;
- /* If the character at max_pos is not a newline and the
- characters at max_pos+1 is a newline, skip that newline as
- well. Note that this may skip some invisible text. */
- if (!at_eol_p
- && get_next_display_element (it)
- && ITERATOR_AT_END_OF_LINE_P (it))
+ if (max_pos == min_pos)
{
- set_iterator_to_next (it, 1);
- /* Record the position after the newline of a continued row.
- We will need that to set ROW->end of the last row
- produced for a continued line. */
- if (row->continued_p)
- save_it.eol_pos = it->current.pos;
+ if (it->method == GET_FROM_BUFFER)
+ /* Empty line, which stands for a newline. */
+ SET_TEXT_POS (row->maxpos, min_pos + 1, min_bpos + 1);
else
- {
- row_end = it->current;
- save_it.eol_pos.charpos = save_it.eol_pos.bytepos = 0;
- }
+ /* A line that is entirely from a string. */
+ row->maxpos = row->minpos;
}
- else if (!row->continued_p
- && MATRIX_ROW_CONTINUATION_LINE_P (row)
- && it->eol_pos.charpos > 0)
+ else if (CHARPOS (it->eol_pos) > 0)
+ SET_TEXT_POS (row->maxpos,
+ CHARPOS (it->eol_pos) + 1, BYTEPOS (it->eol_pos) + 1);
+ else if (row->continued_p)
{
- /* Last row of a continued line. Use the position recorded
- in IT->eol_pos, to the effect that the newline belongs to
- this row, not to the row which displays the character
- with the largest buffer position before the newline. */
- row_end.pos = it->eol_pos;
- it->eol_pos.charpos = it->eol_pos.bytepos = 0;
+ if (it->method == GET_FROM_BUFFER)
+ {
+ INC_BOTH (max_pos, max_bpos);
+ SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
+ }
+ else
+ SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
}
- *it = save_it;
- /* The members of ROW->end that are not taken from buffer
- positions are copied from IT->current. */
- row_end.string_pos = it->current.string_pos;
- row_end.overlay_string_index = it->current.overlay_string_index;
- row_end.dpvec_index = it->current.dpvec_index;
+ else if (row->ends_in_newline_from_string_p)
+ SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
+ else
+ abort ();
}
- return row_end;
+ else
+ row->maxpos = it->current.pos;
}
/* Construct the glyph row IT->glyph_row in the desired matrix of
int wrap_row_phys_ascent, wrap_row_phys_height;
int wrap_row_extra_line_spacing;
int cvpos;
+ EMACS_INT min_pos = ZV + 1, min_bpos, max_pos = 0, max_bpos;
/* We always start displaying at hpos zero even if hscrolled. */
xassert (it->hpos == 0 && it->current_x == 0);
row->ends_at_zv_p = 1;
/* A row that displays right-to-left text must always have
its last face extended all the way to the end of line,
- even if this row ends in ZV. */
+ even if this row ends in ZV, because we still write to th
+ screen left to right. */
if (row->reversed_p)
extend_face_to_end_of_line (it);
break;
}
}
}
+
+ /* Record the maximum and minimum buffer
+ positions seen so far in glyphs that will be
+ displayed by this row. */
+ if (it->bidi_p)
+ {
+ if (BUFFERP (glyph->object)
+ || INTEGERP (glyph->object))
+ {
+ if (IT_CHARPOS (*it) < min_pos)
+ {
+ min_pos = IT_CHARPOS (*it);
+ min_bpos = IT_BYTEPOS (*it);
+ }
+ if (IT_CHARPOS (*it) > max_pos)
+ {
+ max_pos = IT_CHARPOS (*it);
+ max_bpos = IT_BYTEPOS (*it);
+ }
+ }
+ }
}
else if (CHAR_GLYPH_PADDING_P (*glyph)
&& !FRAME_WINDOW_P (it->f))
/* Increment number of glyphs actually displayed. */
++it->hpos;
+ /* Record the maximum and minimum buffer positions
+ seen so far in glyphs that will be displayed by
+ this row. */
+ if (it->bidi_p)
+ {
+ if (BUFFERP (glyph->object)
+ || INTEGERP (glyph->object))
+ {
+ if (IT_CHARPOS (*it) < min_pos)
+ {
+ min_pos = IT_CHARPOS (*it);
+ min_bpos = IT_BYTEPOS (*it);
+ }
+ if (IT_CHARPOS (*it) > max_pos)
+ {
+ max_pos = IT_CHARPOS (*it);
+ max_bpos = IT_BYTEPOS (*it);
+ }
+ }
+ }
+
if (x < it->first_visible_x)
/* Glyph is partially visible, i.e. row starts at
negative X position. */
if (used_before == 0)
row->glyphs[TEXT_AREA]->charpos = CHARPOS (it->position);
+ /* Record the position of the newline, for use in
+ find_row_edges. */
+ it->eol_pos = it->current.pos;
+
/* Consume the line end. This skips over invisible lines. */
set_iterator_to_next (it, 1);
it->continuation_lines_width = 0;
/* If line is not empty and hscrolled, maybe insert truncation glyphs
at the left window margin. */
if (it->first_visible_x
- && IT_CHARPOS (*it) != MATRIX_ROW_START_CHARPOS (row))
+ && IT_CHARPOS (*it) != CHARPOS (row->start.pos))
{
if (!FRAME_WINDOW_P (it->f))
insert_left_trunc_glyphs (it);
/* Remember the position at which this line ends. */
row->end = it->current;
- /* ROW->start and ROW->end must be the smallest and the largest
- buffer positions in ROW. But if ROW was bidi-reordered, these
- two positions can be anywhere in the row, so we must rescan all
- of the ROW's glyphs to find them. */
- if (it->bidi_p)
- row->end = find_row_end (it, row);
+ if (!it->bidi_p)
+ {
+ row->minpos = row->start.pos;
+ row->maxpos = row->end.pos;
+ }
+ else
+ {
+ /* ROW->minpos and ROW->maxpos must be the smallest and
+ `1 + the largest' buffer positions in ROW. But if ROW was
+ bidi-reordered, these two positions can be anywhere in the
+ row, so we must determine them now. */
+ find_row_edges (it, row, min_pos, min_bpos, max_pos, max_bpos);
+ }
/* Record whether this row ends inside an ellipsis. */
row->ends_in_ellipsis_p
row to be used. */
it->current_x = it->hpos = 0;
it->current_y += row->height;
+ SET_TEXT_POS (it->eol_pos, 0, 0);
++it->vpos;
++it->glyph_row;
/* The next row should by default use the same value of the