aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2010-05-22 22:32:21 +0300
committerEli Zaretskii2010-05-22 22:32:21 +0300
commit1111783029f1d7f50c348d1836ec56c62fb344c2 (patch)
tree82dfbad243f61c19044985c98639ada8815bc47a /src
parent6e83d8007b844f1d0d68ad235015a154da8050c4 (diff)
parenta9f86045d9966fd1090951731050bd51e4cc6a8e (diff)
downloademacs-1111783029f1d7f50c348d1836ec56c62fb344c2.tar.gz
emacs-1111783029f1d7f50c348d1836ec56c62fb344c2.zip
Redesign bidi-aware edge positions of glyph rows, fix bug #6036.
dispextern.h (struct glyph_row): New members minpos and maxpos. (MATRIX_ROW_START_CHARPOS, MATRIX_ROW_START_BYTEPOS) (MATRIX_ROW_END_CHARPOS, MATRIX_ROW_END_BYTEPOS): Reference minpos and maxpos members instead of start.pos and end.pos, respectively. xdisp.c (display_line): Compare IT_CHARPOS with the position in row->start.pos, rather than with MATRIX_ROW_START_CHARPOS. (cursor_row_p): Use row->end.pos rather than MATRIX_ROW_END_CHARPOS. (try_window_reusing_current_matrix, try_window_id): Use ROW->minpos rather than ROW->start.pos. (init_from_display_pos, init_iterator): Use EMACS_INT for character and byte positions. (find_row_edges): Renamed from find_row_end. Accept additional arguments for minimum and maximum buffer positions seen by display_line for this row. Don't use iterator to find the position following the maximum one; instead, increment the position found by display_line directly. Fix logic; eol_pos should be tested before the rest. Handle the case of characters delivered from display vector (bug#6036). Fix tests related to it->method. Handle the truncated_on_right_p rows. (RECORD_MAX_MIN_POS): New macro. (display_line): Use it to record the minimum and maximum buffer positions for glyphs in the row being assembled. Record the position of the newline that terminates the line. If word wrap is in effect, restore minimum and maximum positions seen up to the wrap point, when iterator returns to it. (try_window_reusing_current_matrix): Give up if in bidi-reordered row and cursor not already at point. Restore original pre-bidi code for unidirectional buffers. dispnew.c (increment_row_positions, check_matrix_invariants): Increment and check row->start.pos and row->end.pos, in addition to MATRIX_ROW_START_CHARPOS and MATRIX_ROW_END_CHARPOS. .gdbinit (prowlims): Display row->minpos and row->maxpos. Display truncated_on_left_p and truncated_on_right_p flags. Formatting fixes. (pmtxrows): Display the ordinal number of each row. Don't display rows beyond the last one. bidi.c (bidi_cache_iterator_state): Don't zero out new_paragraph: it is not copied by bidi_copy_it.
Diffstat (limited to 'src')
-rw-r--r--src/.gdbinit7
-rw-r--r--src/ChangeLog51
-rw-r--r--src/bidi.c1
-rw-r--r--src/dispextern.h36
-rw-r--r--src/dispnew.c16
-rw-r--r--src/xdisp.c307
6 files changed, 249 insertions, 169 deletions
diff --git a/src/.gdbinit b/src/.gdbinit
index 5ecdaa4a572..1fd7e288736 100644
--- a/src/.gdbinit
+++ b/src/.gdbinit
@@ -616,7 +616,7 @@ Pretty print all glyphs in it->glyph_row.
616end 616end
617 617
618define prowlims 618define prowlims
619 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 619 printf "edges=(%d,%d),r2l=%d,cont=%d,trunc=(%d,%d),at_zv=%d\n", $arg0->minpos.charpos, $arg0->maxpos.charpos, $arg0->reversed_p, $arg0->continued_p, $arg0->truncated_on_left_p, $arg0->truncated_on_right_p, $arg0->ends_at_zv_p
620end 620end
621document prowlims 621document prowlims
622Print important attributes of a glyph_row structure. 622Print important attributes of a glyph_row structure.
@@ -626,10 +626,13 @@ end
626define pmtxrows 626define pmtxrows
627 set $mtx = $arg0 627 set $mtx = $arg0
628 set $gl = $mtx->rows 628 set $gl = $mtx->rows
629 set $glend = $mtx->rows + $mtx->nrows 629 set $glend = $mtx->rows + $mtx->nrows - 1
630 set $i = 0
630 while ($gl < $glend) 631 while ($gl < $glend)
632 printf "%d: ", $i
631 prowlims $gl 633 prowlims $gl
632 set $gl = $gl + 1 634 set $gl = $gl + 1
635 set $i = $i + 1
633 end 636 end
634end 637end
635document pmtxrows 638document pmtxrows
diff --git a/src/ChangeLog b/src/ChangeLog
index 540a85a6b1d..eb71ddf9377 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,50 @@
12010-05-19 Eli Zaretskii <eliz@gnu.org>
2
3 Redesign and reimplement bidi-aware edge positions of glyph rows.
4
5 * dispextern.h (struct glyph_row): New members minpos and maxpos.
6 (MATRIX_ROW_START_CHARPOS, MATRIX_ROW_START_BYTEPOS)
7 (MATRIX_ROW_END_CHARPOS, MATRIX_ROW_END_BYTEPOS): Reference minpos
8 and maxpos members instead of start.pos and end.pos, respectively.
9
10 * xdisp.c (display_line): Compare IT_CHARPOS with the position in
11 row->start.pos, rather than with MATRIX_ROW_START_CHARPOS.
12 (cursor_row_p): Use row->end.pos rather than MATRIX_ROW_END_CHARPOS.
13 (try_window_reusing_current_matrix, try_window_id): Use
14 ROW->minpos rather than ROW->start.pos.
15 (init_from_display_pos, init_iterator): Use EMACS_INT for
16 character and byte positions.
17 (find_row_edges): Renamed from find_row_end. Accept additional
18 arguments for minimum and maximum buffer positions seen by
19 display_line for this row. Don't use iterator to find the
20 position following the maximum one; instead, increment the
21 position found by display_line directly. Fix logic; eol_pos
22 should be tested before the rest. Handle the case of characters
23 delivered from display vector (bug#6036). Fix tests related to
24 it->method. Handle the truncated_on_right_p rows.
25 (RECORD_MAX_MIN_POS): New macro.
26 (display_line): Use it to record the minimum and maximum buffer
27 positions for glyphs in the row being assembled. Record the
28 position of the newline that terminates the line. If word wrap is
29 in effect, restore minimum and maximum positions seen up to the
30 wrap point, when iterator returns to it.
31 (try_window_reusing_current_matrix): Give up if in bidi-reordered
32 row and cursor not already at point. Restore original pre-bidi
33 code for unidirectional buffers.
34
35 * dispnew.c (increment_row_positions, check_matrix_invariants):
36 Increment and check row->start.pos and row->end.pos, in addition
37 to MATRIX_ROW_START_CHARPOS and MATRIX_ROW_END_CHARPOS.
38
39 * .gdbinit (prowlims): Display row->minpos and row->maxpos.
40 Display truncated_on_left_p and truncated_on_right_p flags.
41 Formatting fixes.
42 (pmtxrows): Display the ordinal number of each row. Don't display
43 rows beyond the last one.
44
45 * bidi.c (bidi_cache_iterator_state): Don't zero out new_paragraph:
46 it is not copied by bidi_copy_it.
47
12010-05-22 Eli Zaretskii <eliz@gnu.org> 482010-05-22 Eli Zaretskii <eliz@gnu.org>
2 49
3 * w32.c (sys_write): Break writes into chunks smaller than 32MB. 50 * w32.c (sys_write): Break writes into chunks smaller than 32MB.
@@ -51,8 +98,6 @@
51 Move static/dynamic dependency stuff to deps.mk/autodeps.mk. 98 Move static/dynamic dependency stuff to deps.mk/autodeps.mk.
52 * deps.mk, autodeps.mk: New files, extracted from Makefile.in. 99 * deps.mk, autodeps.mk: New files, extracted from Makefile.in.
53 100
542010-05-19 Eli Zaretskii <eliz@gnu.org>
55
56 * bidi.c (bidi_cache_shrink, bidi_cache_iterator_state): Fix 101 * bidi.c (bidi_cache_shrink, bidi_cache_iterator_state): Fix
57 reallocation of the cache. (Bug#6210) 102 reallocation of the cache. (Bug#6210)
58 103
@@ -175,6 +220,8 @@
175 * xdisp.c (Fcurrent_bidi_paragraph_direction): New function. 220 * xdisp.c (Fcurrent_bidi_paragraph_direction): New function.
176 (syms_of_xdisp): Defsubr it. 221 (syms_of_xdisp): Defsubr it.
177 222
223 * cmds.c (Fforward_char, Fbackward_char): Doc fix.
224
178 * Makefile.in: Fix MSDOS-related comments. 225 * Makefile.in: Fix MSDOS-related comments.
179 226
1802010-05-15 Glenn Morris <rgm@gnu.org> 2272010-05-15 Glenn Morris <rgm@gnu.org>
diff --git a/src/bidi.c b/src/bidi.c
index 6bcbf6f6aea..bdeccfee97c 100644
--- a/src/bidi.c
+++ b/src/bidi.c
@@ -707,7 +707,6 @@ bidi_cache_iterator_state (struct bidi_it *bidi_it, int resolved)
707 bidi_copy_it (&bidi_cache[idx], bidi_it); 707 bidi_copy_it (&bidi_cache[idx], bidi_it);
708 if (!resolved) 708 if (!resolved)
709 bidi_cache[idx].resolved_level = -1; 709 bidi_cache[idx].resolved_level = -1;
710 bidi_cache[idx].new_paragraph = 0;
711 } 710 }
712 else 711 else
713 { 712 {
diff --git a/src/dispextern.h b/src/dispextern.h
index 8e8da36daea..ce8527b92de 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -748,21 +748,29 @@ struct glyph_row
748 748
749 /* First position in this row. This is the text position, including 749 /* First position in this row. This is the text position, including
750 overlay position information etc, where the display of this row 750 overlay position information etc, where the display of this row
751 started, and can thus be less the position of the first glyph 751 started, and can thus be less than the position of the first
752 (e.g. due to invisible text or horizontal scrolling). BIDI Note: 752 glyph (e.g. due to invisible text or horizontal scrolling).
753 This is the smallest character position in the row, but not 753 BIDI Note: In R2L rows, that have its reversed_p flag set, this
754 necessarily the character that is the leftmost on the display. */ 754 position is at or beyond the right edge of the row. */
755 struct display_pos start; 755 struct display_pos start;
756 756
757 /* Text position at the end of this row. This is the position after 757 /* Text position at the end of this row. This is the position after
758 the last glyph on this row. It can be greater than the last 758 the last glyph on this row. It can be greater than the last
759 glyph position + 1, due to truncation, invisible text etc. In an 759 glyph position + 1, due to a newline that ends the line,
760 up-to-date display, this should always be equal to the start 760 truncation, invisible text etc. In an up-to-date display, this
761 position of the next row. BIDI Note: this is the character whose 761 should always be equal to the start position of the next row.
762 buffer position is the largest, but not necessarily the rightmost 762 BIDI Note: In R2L rows, this position is at or beyond the left
763 one on the display. */ 763 edge of the row. */
764 struct display_pos end; 764 struct display_pos end;
765 765
766 /* The smallest and the largest buffer positions that contributed to
767 glyphs in this row. Note that due to bidi reordering, these are
768 in general different from the text positions stored in `start'
769 and `end' members above, and also different from the buffer
770 positions recorded in the glyphs displayed the leftmost and
771 rightmost on the screen. */
772 struct text_pos minpos, maxpos;
773
766 /* Non-zero means the overlay arrow bitmap is on this line. 774 /* Non-zero means the overlay arrow bitmap is on this line.
767 -1 means use default overlay arrow bitmap, else 775 -1 means use default overlay arrow bitmap, else
768 it specifies actual fringe bitmap number. */ 776 it specifies actual fringe bitmap number. */
@@ -947,16 +955,16 @@ struct glyph_row *matrix_row P_ ((struct glyph_matrix *, int));
947 displayed by ROW, which is not necessarily the smallest horizontal 955 displayed by ROW, which is not necessarily the smallest horizontal
948 position. */ 956 position. */
949 957
950#define MATRIX_ROW_START_CHARPOS(ROW) ((ROW)->start.pos.charpos) 958#define MATRIX_ROW_START_CHARPOS(ROW) ((ROW)->minpos.charpos)
951#define MATRIX_ROW_START_BYTEPOS(ROW) ((ROW)->start.pos.bytepos) 959#define MATRIX_ROW_START_BYTEPOS(ROW) ((ROW)->minpos.bytepos)
952 960
953/* Return the character/ byte position at which ROW ends. BIDI Note: 961/* Return the character/ byte position at which ROW ends. BIDI Note:
954 this is the largest character/byte position among characters in 962 this is the largest character/byte position among characters in
955 ROW, i.e. the last logical-order character displayed by ROW, which 963 ROW, i.e. the last logical-order character displayed by ROW, which
956 is not necessarily the largest horizontal position. */ 964 is not necessarily the largest horizontal position. */
957 965
958#define MATRIX_ROW_END_CHARPOS(ROW) ((ROW)->end.pos.charpos) 966#define MATRIX_ROW_END_CHARPOS(ROW) ((ROW)->maxpos.charpos)
959#define MATRIX_ROW_END_BYTEPOS(ROW) ((ROW)->end.pos.bytepos) 967#define MATRIX_ROW_END_BYTEPOS(ROW) ((ROW)->maxpos.bytepos)
960 968
961/* Return the vertical position of ROW in MATRIX. */ 969/* Return the vertical position of ROW in MATRIX. */
962 970
@@ -1789,7 +1797,7 @@ struct bidi_it {
1789 EMACS_INT next_en_pos; /* position of next EN char for ET */ 1797 EMACS_INT next_en_pos; /* position of next EN char for ET */
1790 EMACS_INT ignore_bn_limit; /* position until which to ignore BNs */ 1798 EMACS_INT ignore_bn_limit; /* position until which to ignore BNs */
1791 bidi_dir_t sor; /* direction of start-of-run in effect */ 1799 bidi_dir_t sor; /* direction of start-of-run in effect */
1792 int scan_dir; /* direction of text scan */ 1800 int scan_dir; /* direction of text scan, 1: forw, -1: back */
1793 int stack_idx; /* index of current data on the stack */ 1801 int stack_idx; /* index of current data on the stack */
1794 /* Note: Everything from here on is not copied/saved when the bidi 1802 /* Note: Everything from here on is not copied/saved when the bidi
1795 iterator state is saved, pushed, or popped. So only put here 1803 iterator state is saved, pushed, or popped. So only put here
diff --git a/src/dispnew.c b/src/dispnew.c
index 7ab2bf35811..476b58ae7e3 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -1188,6 +1188,10 @@ increment_row_positions (row, delta, delta_bytes)
1188 MATRIX_ROW_START_BYTEPOS (row) += delta_bytes; 1188 MATRIX_ROW_START_BYTEPOS (row) += delta_bytes;
1189 MATRIX_ROW_END_CHARPOS (row) += delta; 1189 MATRIX_ROW_END_CHARPOS (row) += delta;
1190 MATRIX_ROW_END_BYTEPOS (row) += delta_bytes; 1190 MATRIX_ROW_END_BYTEPOS (row) += delta_bytes;
1191 CHARPOS (row->start.pos) += delta;
1192 BYTEPOS (row->start.pos) += delta_bytes;
1193 CHARPOS (row->end.pos) += delta;
1194 BYTEPOS (row->end.pos) += delta_bytes;
1191 1195
1192 if (!row->enabled_p) 1196 if (!row->enabled_p)
1193 return; 1197 return;
@@ -1748,13 +1752,19 @@ check_matrix_invariants (w)
1748 /* Check that character and byte positions are in sync. */ 1752 /* Check that character and byte positions are in sync. */
1749 xassert (MATRIX_ROW_START_BYTEPOS (row) 1753 xassert (MATRIX_ROW_START_BYTEPOS (row)
1750 == CHAR_TO_BYTE (MATRIX_ROW_START_CHARPOS (row))); 1754 == CHAR_TO_BYTE (MATRIX_ROW_START_CHARPOS (row)));
1755 xassert (BYTEPOS (row->start.pos)
1756 == CHAR_TO_BYTE (CHARPOS (row->start.pos)));
1751 1757
1752 /* CHAR_TO_BYTE aborts when invoked for a position > Z. We can 1758 /* CHAR_TO_BYTE aborts when invoked for a position > Z. We can
1753 have such a position temporarily in case of a minibuffer 1759 have such a position temporarily in case of a minibuffer
1754 displaying something like `[Sole completion]' at its end. */ 1760 displaying something like `[Sole completion]' at its end. */
1755 if (MATRIX_ROW_END_CHARPOS (row) < BUF_ZV (current_buffer)) 1761 if (MATRIX_ROW_END_CHARPOS (row) < BUF_ZV (current_buffer))
1756 xassert (MATRIX_ROW_END_BYTEPOS (row) 1762 {
1757 == CHAR_TO_BYTE (MATRIX_ROW_END_CHARPOS (row))); 1763 xassert (MATRIX_ROW_END_BYTEPOS (row)
1764 == CHAR_TO_BYTE (MATRIX_ROW_END_CHARPOS (row)));
1765 xassert (BYTEPOS (row->end.pos)
1766 == CHAR_TO_BYTE (CHARPOS (row->end.pos)));
1767 }
1758 1768
1759 /* Check that end position of `row' is equal to start position 1769 /* Check that end position of `row' is equal to start position
1760 of next row. */ 1770 of next row. */
@@ -1764,6 +1774,8 @@ check_matrix_invariants (w)
1764 == MATRIX_ROW_START_CHARPOS (next)); 1774 == MATRIX_ROW_START_CHARPOS (next));
1765 xassert (MATRIX_ROW_END_BYTEPOS (row) 1775 xassert (MATRIX_ROW_END_BYTEPOS (row)
1766 == MATRIX_ROW_START_BYTEPOS (next)); 1776 == MATRIX_ROW_START_BYTEPOS (next));
1777 xassert (CHARPOS (row->end.pos) == CHARPOS (next->start.pos));
1778 xassert (BYTEPOS (row->end.pos) == BYTEPOS (next->start.pos));
1767 } 1779 }
1768 row = next; 1780 row = next;
1769 } 1781 }
diff --git a/src/xdisp.c b/src/xdisp.c
index 2ff12730b8a..56e09f54842 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -2598,7 +2598,7 @@ void
2598init_iterator (it, w, charpos, bytepos, row, base_face_id) 2598init_iterator (it, w, charpos, bytepos, row, base_face_id)
2599 struct it *it; 2599 struct it *it;
2600 struct window *w; 2600 struct window *w;
2601 int charpos, bytepos; 2601 EMACS_INT charpos, bytepos;
2602 struct glyph_row *row; 2602 struct glyph_row *row;
2603 enum face_id base_face_id; 2603 enum face_id base_face_id;
2604{ 2604{
@@ -3012,7 +3012,7 @@ init_from_display_pos (it, w, pos)
3012 struct window *w; 3012 struct window *w;
3013 struct display_pos *pos; 3013 struct display_pos *pos;
3014{ 3014{
3015 int charpos = CHARPOS (pos->pos), bytepos = BYTEPOS (pos->pos); 3015 EMACS_INT charpos = CHARPOS (pos->pos), bytepos = BYTEPOS (pos->pos);
3016 int i, overlay_strings_with_newlines = 0; 3016 int i, overlay_strings_with_newlines = 0;
3017 3017
3018 /* If POS specifies a position in a display vector, this might 3018 /* If POS specifies a position in a display vector, this might
@@ -14975,7 +14975,7 @@ try_window_reusing_current_matrix (w)
14975 /* The variable new_start now holds the new window start. The old 14975 /* The variable new_start now holds the new window start. The old
14976 start `start' can be determined from the current matrix. */ 14976 start `start' can be determined from the current matrix. */
14977 SET_TEXT_POS_FROM_MARKER (new_start, w->start); 14977 SET_TEXT_POS_FROM_MARKER (new_start, w->start);
14978 start = start_row->start.pos; 14978 start = start_row->minpos;
14979 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix); 14979 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
14980 14980
14981 /* Clear the desired matrix for the display below. */ 14981 /* Clear the desired matrix for the display below. */
@@ -15014,7 +15014,7 @@ try_window_reusing_current_matrix (w)
15014 { 15014 {
15015 /* Advance to the next row as the "start". */ 15015 /* Advance to the next row as the "start". */
15016 start_row++; 15016 start_row++;
15017 start = start_row->start.pos; 15017 start = start_row->minpos;
15018 /* If there are no more rows to try, or just one, give up. */ 15018 /* If there are no more rows to try, or just one, give up. */
15019 if (start_row == MATRIX_MODE_LINE_ROW (w->current_matrix) - 1 15019 if (start_row == MATRIX_MODE_LINE_ROW (w->current_matrix) - 1
15020 || w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row) 15020 || w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row)
@@ -15296,39 +15296,26 @@ try_window_reusing_current_matrix (w)
15296 { 15296 {
15297 struct glyph *glyph = row->glyphs[TEXT_AREA] + w->cursor.hpos; 15297 struct glyph *glyph = row->glyphs[TEXT_AREA] + w->cursor.hpos;
15298 struct glyph *end = glyph + row->used[TEXT_AREA]; 15298 struct glyph *end = glyph + row->used[TEXT_AREA];
15299 struct glyph *orig_glyph = glyph;
15300 struct cursor_pos orig_cursor = w->cursor;
15301 15299
15302 for (; glyph < end 15300 /* Can't use this optimization with bidi-reordered glyph
15303 && (!BUFFERP (glyph->object) 15301 rows, unless cursor is already at point. */
15304 || glyph->charpos != PT); 15302 if (!NILP (XBUFFER (w->buffer)->bidi_display_reordering))
15305 glyph++)
15306 { 15303 {
15307 w->cursor.hpos++; 15304 if (!(w->cursor.hpos >= 0
15308 w->cursor.x += glyph->pixel_width; 15305 && w->cursor.hpos < row->used[TEXT_AREA]
15309 } 15306 && BUFFERP (glyph->object)
15310 /* With bidi reordering, charpos changes non-linearly 15307 && glyph->charpos == PT))
15311 with hpos, so the right glyph could be to the 15308 return 0;
15312 left. */
15313 if (!NILP (XBUFFER (w->buffer)->bidi_display_reordering)
15314 && (!BUFFERP (glyph->object) || glyph->charpos != PT))
15315 {
15316 struct glyph *start_glyph = row->glyphs[TEXT_AREA];
15317
15318 glyph = orig_glyph - 1;
15319 orig_cursor.hpos--;
15320 orig_cursor.x -= glyph->pixel_width;
15321 for (; glyph >= start_glyph
15322 && (!BUFFERP (glyph->object)
15323 || glyph->charpos != PT);
15324 glyph--)
15325 {
15326 w->cursor.hpos--;
15327 w->cursor.x -= glyph->pixel_width;
15328 }
15329 if (BUFFERP (glyph->object) && glyph->charpos == PT)
15330 w->cursor = orig_cursor;
15331 } 15309 }
15310 else
15311 for (; glyph < end
15312 && (!BUFFERP (glyph->object)
15313 || glyph->charpos < PT);
15314 glyph++)
15315 {
15316 w->cursor.hpos++;
15317 w->cursor.x += glyph->pixel_width;
15318 }
15332 } 15319 }
15333 } 15320 }
15334 15321
@@ -15908,13 +15895,13 @@ try_window_id (w)
15908 as is, without changing glyph positions since no text has 15895 as is, without changing glyph positions since no text has
15909 been added/removed in front of the window end. */ 15896 been added/removed in front of the window end. */
15910 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix); 15897 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
15911 if (TEXT_POS_EQUAL_P (start, r0->start.pos) 15898 if (TEXT_POS_EQUAL_P (start, r0->minpos)
15912 /* PT must not be in a partially visible line. */ 15899 /* PT must not be in a partially visible line. */
15913 && !(PT >= MATRIX_ROW_START_CHARPOS (row) 15900 && !(PT >= MATRIX_ROW_START_CHARPOS (row)
15914 && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w))) 15901 && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
15915 { 15902 {
15916 /* We have to compute the window end anew since text 15903 /* We have to compute the window end anew since text
15917 can have been added/removed after it. */ 15904 could have been added/removed after it. */
15918 w->window_end_pos 15905 w->window_end_pos
15919 = make_number (Z - MATRIX_ROW_END_CHARPOS (row)); 15906 = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
15920 w->window_end_bytepos 15907 w->window_end_bytepos
@@ -15946,7 +15933,7 @@ try_window_id (w)
15946 start is not in changed text, otherwise positions would not be 15933 start is not in changed text, otherwise positions would not be
15947 comparable. */ 15934 comparable. */
15948 row = MATRIX_FIRST_TEXT_ROW (current_matrix); 15935 row = MATRIX_FIRST_TEXT_ROW (current_matrix);
15949 if (!TEXT_POS_EQUAL_P (start, row->start.pos)) 15936 if (!TEXT_POS_EQUAL_P (start, row->minpos))
15950 GIVE_UP (16); 15937 GIVE_UP (16);
15951 15938
15952 /* Give up if the window ends in strings. Overlay strings 15939 /* Give up if the window ends in strings. Overlay strings
@@ -17338,7 +17325,7 @@ cursor_row_p (w, row)
17338{ 17325{
17339 int cursor_row_p = 1; 17326 int cursor_row_p = 1;
17340 17327
17341 if (PT == MATRIX_ROW_END_CHARPOS (row)) 17328 if (PT == CHARPOS (row->end.pos))
17342 { 17329 {
17343 /* Suppose the row ends on a string. 17330 /* Suppose the row ends on a string.
17344 Unless the row is continued, that means it ends on a newline 17331 Unless the row is continued, that means it ends on a newline
@@ -17375,14 +17362,15 @@ cursor_row_p (w, row)
17375 { 17362 {
17376 /* If the row ends in middle of a real character, 17363 /* If the row ends in middle of a real character,
17377 and the line is continued, we want the cursor here. 17364 and the line is continued, we want the cursor here.
17378 That's because MATRIX_ROW_END_CHARPOS would equal 17365 That's because CHARPOS (ROW->end.pos) would equal
17379 PT if PT is before the character. */ 17366 PT if PT is before the character. */
17380 if (!row->ends_in_ellipsis_p) 17367 if (!row->ends_in_ellipsis_p)
17381 cursor_row_p = row->continued_p; 17368 cursor_row_p = row->continued_p;
17382 else 17369 else
17383 /* If the row ends in an ellipsis, then 17370 /* If the row ends in an ellipsis, then
17384 MATRIX_ROW_END_CHARPOS will equal point after the invisible text. 17371 CHARPOS (ROW->end.pos) will equal point after the
17385 We want that position to be displayed after the ellipsis. */ 17372 invisible text. We want that position to be displayed
17373 after the ellipsis. */
17386 cursor_row_p = 0; 17374 cursor_row_p = 0;
17387 } 17375 }
17388 /* If the row ends at ZV, display the cursor at the end of that 17376 /* If the row ends at ZV, display the cursor at the end of that
@@ -17518,122 +17506,87 @@ unproduce_glyphs (it, n)
17518 glyph[-n] = *glyph; 17506 glyph[-n] = *glyph;
17519} 17507}
17520 17508
17521/* Find the positions in a bidi-reordered ROW to serve as ROW->start 17509/* Find the positions in a bidi-reordered ROW to serve as ROW->minpos
17522 and ROW->end. */ 17510 and ROW->maxpos. */
17523static struct display_pos 17511static void
17524find_row_end (it, row) 17512find_row_edges (it, row, min_pos, min_bpos, max_pos, max_bpos)
17525 struct it *it; 17513 struct it *it;
17526 struct glyph_row *row; 17514 struct glyph_row *row;
17515 EMACS_INT min_pos, min_bpos, max_pos, max_bpos;
17527{ 17516{
17528 /* FIXME: Revisit this when glyph ``spilling'' in continuation 17517 /* FIXME: Revisit this when glyph ``spilling'' in continuation
17529 lines' rows is implemented for bidi-reordered rows. */ 17518 lines' rows is implemented for bidi-reordered rows. */
17530 EMACS_INT min_pos = ZV + 1, max_pos = 0;
17531 struct glyph *g;
17532 struct it save_it;
17533 struct text_pos tpos;
17534 struct display_pos row_end = it->current;
17535 17519
17536 for (g = row->glyphs[TEXT_AREA]; 17520 /* ROW->minpos is the value of min_pos, the minimal buffer position
17537 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
17538 g++)
17539 {
17540 if (BUFFERP (g->object))
17541 {
17542 if (g->charpos > 0 && g->charpos < min_pos)
17543 min_pos = g->charpos;
17544 if (g->charpos > max_pos)
17545 max_pos = g->charpos;
17546 }
17547 }
17548 /* Empty lines have a valid buffer position at their first
17549 glyph, but that glyph's OBJECT is zero, as if it didn't come
17550 from a buffer. If we didn't find any valid buffer positions
17551 in this row, maybe we have such an empty line. */
17552 if (max_pos == 0 && row->used[TEXT_AREA])
17553 {
17554 for (g = row->glyphs[TEXT_AREA];
17555 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
17556 g++)
17557 {
17558 if (INTEGERP (g->object))
17559 {
17560 if (g->charpos > 0 && g->charpos < min_pos)
17561 min_pos = g->charpos;
17562 if (g->charpos > max_pos)
17563 max_pos = g->charpos;
17564 }
17565 }
17566 }
17567
17568 /* ROW->start is the value of min_pos, the minimal buffer position
17569 we have in ROW. */ 17521 we have in ROW. */
17570 if (min_pos <= ZV) 17522 if (min_pos <= ZV)
17523 SET_TEXT_POS (row->minpos, min_pos, min_bpos);
17524 else
17571 { 17525 {
17572 /* Avoid calling the costly CHAR_TO_BYTE if possible. */ 17526 /* We didn't find _any_ valid buffer positions in any of the
17573 if (min_pos != row->start.pos.charpos) 17527 glyphs, so we must trust the iterator's computed
17574 SET_TEXT_POS (row->start.pos, min_pos, CHAR_TO_BYTE (min_pos)); 17528 positions. */
17575 if (max_pos == 0) 17529 row->minpos = row->start.pos;
17576 max_pos = min_pos; 17530 max_pos = CHARPOS (it->current.pos);
17531 max_bpos = BYTEPOS (it->current.pos);
17577 } 17532 }
17578 17533
17579 /* For ROW->end, we need the position that is _after_ max_pos, in 17534 if (!max_pos)
17580 the logical order, unless we are at ZV. */ 17535 abort ();
17581 if (row->ends_at_zv_p)
17582 {
17583 if (!row->used[TEXT_AREA])
17584 row->start.pos = row_end.pos;
17585 }
17586 else if (row->used[TEXT_AREA] && max_pos)
17587 {
17588 int at_eol_p;
17589 17536
17590 SET_TEXT_POS (tpos, max_pos, CHAR_TO_BYTE (max_pos)); 17537 /* Here are the various use-cases for ending the row, and the
17591 save_it = *it; 17538 corresponding values for ROW->maxpos:
17592 it->bidi_p = 0; 17539
17593 reseat (it, tpos, 0); 17540 Line ends in a newline from buffer eol_pos + 1
17594 if (!get_next_display_element (it)) 17541 Line is continued from buffer max_pos + 1
17595 abort (); /* this row cannot be at ZV, see above */ 17542 Line is truncated on right it->current.pos
17596 at_eol_p = ITERATOR_AT_END_OF_LINE_P (it); 17543 Line ends in a newline from string max_pos
17597 set_iterator_to_next (it, 1); 17544 Line is continued from string max_pos
17598 row_end = it->current; 17545 Line is continued from display vector max_pos
17599 /* If the character at max_pos is not a newline and the 17546 Line is entirely from a string min_pos == max_pos
17600 characters at max_pos+1 is a newline, skip that newline as 17547 Line is entirely from a display vector min_pos == max_pos
17601 well. Note that this may skip some invisible text. */ 17548 Line that ends at ZV ZV
17602 if (!at_eol_p 17549
17603 && get_next_display_element (it) 17550 If you discover other use-cases, please add them here as
17604 && ITERATOR_AT_END_OF_LINE_P (it)) 17551 appropriate. */
17605 { 17552 if (row->ends_at_zv_p)
17606 set_iterator_to_next (it, 1); 17553 row->maxpos = it->current.pos;
17607 /* Record the position after the newline of a continued row. 17554 else if (row->used[TEXT_AREA])
17608 We will need that to set ROW->end of the last row 17555 {
17609 produced for a continued line. */ 17556 if (row->ends_in_newline_from_string_p)
17610 if (row->continued_p) 17557 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
17611 save_it.eol_pos = it->current.pos; 17558 else if (CHARPOS (it->eol_pos) > 0)
17559 SET_TEXT_POS (row->maxpos,
17560 CHARPOS (it->eol_pos) + 1, BYTEPOS (it->eol_pos) + 1);
17561 else if (row->continued_p)
17562 {
17563 /* If max_pos is different from IT's current position, it
17564 means IT->method does not belong to the display element
17565 at max_pos. However, it also means that the display
17566 element at max_pos was displayed in its entirety on this
17567 line, which is equivalent to saying that the next line
17568 starts at the next buffer position. */
17569 if (IT_CHARPOS (*it) == max_pos && it->method != GET_FROM_BUFFER)
17570 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
17612 else 17571 else
17613 { 17572 {
17614 row_end = it->current; 17573 INC_BOTH (max_pos, max_bpos);
17615 save_it.eol_pos.charpos = save_it.eol_pos.bytepos = 0; 17574 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
17616 } 17575 }
17617 } 17576 }
17618 else if (!row->continued_p 17577 else if (row->truncated_on_right_p)
17619 && MATRIX_ROW_CONTINUATION_LINE_P (row) 17578 /* display_line already called reseat_at_next_visible_line_start,
17620 && it->eol_pos.charpos > 0) 17579 which puts the iterator at the beginning of the next line, in
17621 { 17580 the logical order. */
17622 /* Last row of a continued line. Use the position recorded 17581 row->maxpos = it->current.pos;
17623 in IT->eol_pos, to the effect that the newline belongs to 17582 else if (max_pos == min_pos && it->method != GET_FROM_BUFFER)
17624 this row, not to the row which displays the character 17583 /* A line that is entirely from a string/image/stretch... */
17625 with the largest buffer position before the newline. */ 17584 row->maxpos = row->minpos;
17626 row_end.pos = it->eol_pos; 17585 else
17627 it->eol_pos.charpos = it->eol_pos.bytepos = 0; 17586 abort ();
17628 }
17629 *it = save_it;
17630 /* The members of ROW->end that are not taken from buffer
17631 positions are copied from IT->current. */
17632 row_end.string_pos = it->current.string_pos;
17633 row_end.overlay_string_index = it->current.overlay_string_index;
17634 row_end.dpvec_index = it->current.dpvec_index;
17635 } 17587 }
17636 return row_end; 17588 else
17589 row->maxpos = it->current.pos;
17637} 17590}
17638 17591
17639/* Construct the glyph row IT->glyph_row in the desired matrix of 17592/* Construct the glyph row IT->glyph_row in the desired matrix of
@@ -17653,7 +17606,10 @@ display_line (it)
17653 int wrap_row_used = -1, wrap_row_ascent, wrap_row_height; 17606 int wrap_row_used = -1, wrap_row_ascent, wrap_row_height;
17654 int wrap_row_phys_ascent, wrap_row_phys_height; 17607 int wrap_row_phys_ascent, wrap_row_phys_height;
17655 int wrap_row_extra_line_spacing; 17608 int wrap_row_extra_line_spacing;
17609 EMACS_INT wrap_row_min_pos, wrap_row_min_bpos;
17610 EMACS_INT wrap_row_max_pos, wrap_row_max_bpos;
17656 int cvpos; 17611 int cvpos;
17612 EMACS_INT min_pos = ZV + 1, min_bpos, max_pos = 0, max_bpos;
17657 17613
17658 /* We always start displaying at hpos zero even if hscrolled. */ 17614 /* We always start displaying at hpos zero even if hscrolled. */
17659 xassert (it->hpos == 0 && it->current_x == 0); 17615 xassert (it->hpos == 0 && it->current_x == 0);
@@ -17710,6 +17666,23 @@ display_line (it)
17710 row->phys_height = it->max_phys_ascent + it->max_phys_descent; 17666 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
17711 row->extra_line_spacing = it->max_extra_line_spacing; 17667 row->extra_line_spacing = it->max_extra_line_spacing;
17712 17668
17669/* Utility macro to record max and min buffer positions seen until now. */
17670#define RECORD_MAX_MIN_POS(IT) \
17671 do \
17672 { \
17673 if (IT_CHARPOS (*(IT)) < min_pos) \
17674 { \
17675 min_pos = IT_CHARPOS (*(IT)); \
17676 min_bpos = IT_BYTEPOS (*(IT)); \
17677 } \
17678 if (IT_CHARPOS (*(IT)) > max_pos) \
17679 { \
17680 max_pos = IT_CHARPOS (*(IT)); \
17681 max_bpos = IT_BYTEPOS (*(IT)); \
17682 } \
17683 } \
17684 while (0)
17685
17713 /* Loop generating characters. The loop is left with IT on the next 17686 /* Loop generating characters. The loop is left with IT on the next
17714 character to display. */ 17687 character to display. */
17715 while (1) 17688 while (1)
@@ -17744,7 +17717,8 @@ display_line (it)
17744 row->ends_at_zv_p = 1; 17717 row->ends_at_zv_p = 1;
17745 /* A row that displays right-to-left text must always have 17718 /* A row that displays right-to-left text must always have
17746 its last face extended all the way to the end of line, 17719 its last face extended all the way to the end of line,
17747 even if this row ends in ZV. */ 17720 even if this row ends in ZV, because we still write to th
17721 screen left to right. */
17748 if (row->reversed_p) 17722 if (row->reversed_p)
17749 extend_face_to_end_of_line (it); 17723 extend_face_to_end_of_line (it);
17750 break; 17724 break;
@@ -17778,6 +17752,10 @@ display_line (it)
17778 wrap_row_phys_ascent = row->phys_ascent; 17752 wrap_row_phys_ascent = row->phys_ascent;
17779 wrap_row_phys_height = row->phys_height; 17753 wrap_row_phys_height = row->phys_height;
17780 wrap_row_extra_line_spacing = row->extra_line_spacing; 17754 wrap_row_extra_line_spacing = row->extra_line_spacing;
17755 wrap_row_min_pos = min_pos;
17756 wrap_row_min_bpos = min_bpos;
17757 wrap_row_max_pos = max_pos;
17758 wrap_row_max_bpos = max_bpos;
17781 may_wrap = 0; 17759 may_wrap = 0;
17782 } 17760 }
17783 } 17761 }
@@ -17828,6 +17806,10 @@ display_line (it)
17828 it->max_extra_line_spacing); 17806 it->max_extra_line_spacing);
17829 if (it->current_x - it->pixel_width < it->first_visible_x) 17807 if (it->current_x - it->pixel_width < it->first_visible_x)
17830 row->x = x - it->first_visible_x; 17808 row->x = x - it->first_visible_x;
17809 /* Record the maximum and minimum buffer positions seen so
17810 far in glyphs that will be displayed by this row. */
17811 if (it->bidi_p)
17812 RECORD_MAX_MIN_POS (it);
17831 } 17813 }
17832 else 17814 else
17833 { 17815 {
@@ -17861,6 +17843,11 @@ display_line (it)
17861 it->current_x = new_x; 17843 it->current_x = new_x;
17862 it->continuation_lines_width += new_x; 17844 it->continuation_lines_width += new_x;
17863 ++it->hpos; 17845 ++it->hpos;
17846 /* Record the maximum and minimum buffer
17847 positions seen so far in glyphs that will be
17848 displayed by this row. */
17849 if (it->bidi_p)
17850 RECORD_MAX_MIN_POS (it);
17864 if (i == nglyphs - 1) 17851 if (i == nglyphs - 1)
17865 { 17852 {
17866 /* If line-wrap is on, check if a previous 17853 /* If line-wrap is on, check if a previous
@@ -17935,6 +17922,10 @@ display_line (it)
17935 row->phys_ascent = wrap_row_phys_ascent; 17922 row->phys_ascent = wrap_row_phys_ascent;
17936 row->phys_height = wrap_row_phys_height; 17923 row->phys_height = wrap_row_phys_height;
17937 row->extra_line_spacing = wrap_row_extra_line_spacing; 17924 row->extra_line_spacing = wrap_row_extra_line_spacing;
17925 min_pos = wrap_row_min_pos;
17926 min_bpos = wrap_row_min_bpos;
17927 max_pos = wrap_row_max_pos;
17928 max_bpos = wrap_row_max_bpos;
17938 row->continued_p = 1; 17929 row->continued_p = 1;
17939 row->ends_at_zv_p = 0; 17930 row->ends_at_zv_p = 0;
17940 row->exact_window_width_line_p = 0; 17931 row->exact_window_width_line_p = 0;
@@ -17997,6 +17988,12 @@ display_line (it)
17997 /* Increment number of glyphs actually displayed. */ 17988 /* Increment number of glyphs actually displayed. */
17998 ++it->hpos; 17989 ++it->hpos;
17999 17990
17991 /* Record the maximum and minimum buffer positions
17992 seen so far in glyphs that will be displayed by
17993 this row. */
17994 if (it->bidi_p)
17995 RECORD_MAX_MIN_POS (it);
17996
18000 if (x < it->first_visible_x) 17997 if (x < it->first_visible_x)
18001 /* Glyph is partially visible, i.e. row starts at 17998 /* Glyph is partially visible, i.e. row starts at
18002 negative X position. */ 17999 negative X position. */
@@ -18048,6 +18045,10 @@ display_line (it)
18048 if (used_before == 0) 18045 if (used_before == 0)
18049 row->glyphs[TEXT_AREA]->charpos = CHARPOS (it->position); 18046 row->glyphs[TEXT_AREA]->charpos = CHARPOS (it->position);
18050 18047
18048 /* Record the position of the newline, for use in
18049 find_row_edges. */
18050 it->eol_pos = it->current.pos;
18051
18051 /* Consume the line end. This skips over invisible lines. */ 18052 /* Consume the line end. This skips over invisible lines. */
18052 set_iterator_to_next (it, 1); 18053 set_iterator_to_next (it, 1);
18053 it->continuation_lines_width = 0; 18054 it->continuation_lines_width = 0;
@@ -18127,7 +18128,7 @@ display_line (it)
18127 /* If line is not empty and hscrolled, maybe insert truncation glyphs 18128 /* If line is not empty and hscrolled, maybe insert truncation glyphs
18128 at the left window margin. */ 18129 at the left window margin. */
18129 if (it->first_visible_x 18130 if (it->first_visible_x
18130 && IT_CHARPOS (*it) != MATRIX_ROW_START_CHARPOS (row)) 18131 && IT_CHARPOS (*it) != CHARPOS (row->start.pos))
18131 { 18132 {
18132 if (!FRAME_WINDOW_P (it->f)) 18133 if (!FRAME_WINDOW_P (it->f))
18133 insert_left_trunc_glyphs (it); 18134 insert_left_trunc_glyphs (it);
@@ -18181,12 +18182,19 @@ display_line (it)
18181 18182
18182 /* Remember the position at which this line ends. */ 18183 /* Remember the position at which this line ends. */
18183 row->end = it->current; 18184 row->end = it->current;
18184 /* ROW->start and ROW->end must be the smallest and the largest 18185 if (!it->bidi_p)
18185 buffer positions in ROW. But if ROW was bidi-reordered, these 18186 {
18186 two positions can be anywhere in the row, so we must rescan all 18187 row->minpos = row->start.pos;
18187 of the ROW's glyphs to find them. */ 18188 row->maxpos = row->end.pos;
18188 if (it->bidi_p) 18189 }
18189 row->end = find_row_end (it, row); 18190 else
18191 {
18192 /* ROW->minpos and ROW->maxpos must be the smallest and
18193 `1 + the largest' buffer positions in ROW. But if ROW was
18194 bidi-reordered, these two positions can be anywhere in the
18195 row, so we must determine them now. */
18196 find_row_edges (it, row, min_pos, min_bpos, max_pos, max_bpos);
18197 }
18190 18198
18191 /* Record whether this row ends inside an ellipsis. */ 18199 /* Record whether this row ends inside an ellipsis. */
18192 row->ends_in_ellipsis_p 18200 row->ends_in_ellipsis_p
@@ -18232,6 +18240,7 @@ display_line (it)
18232 row to be used. */ 18240 row to be used. */
18233 it->current_x = it->hpos = 0; 18241 it->current_x = it->hpos = 0;
18234 it->current_y += row->height; 18242 it->current_y += row->height;
18243 SET_TEXT_POS (it->eol_pos, 0, 0);
18235 ++it->vpos; 18244 ++it->vpos;
18236 ++it->glyph_row; 18245 ++it->glyph_row;
18237 /* The next row should by default use the same value of the 18246 /* The next row should by default use the same value of the
@@ -18242,6 +18251,8 @@ display_line (it)
18242 it->glyph_row->reversed_p = row->reversed_p; 18251 it->glyph_row->reversed_p = row->reversed_p;
18243 it->start = row->end; 18252 it->start = row->end;
18244 return row->displays_text_p; 18253 return row->displays_text_p;
18254
18255#undef RECORD_MAX_MIN_POS
18245} 18256}
18246 18257
18247DEFUN ("current-bidi-paragraph-direction", Fcurrent_bidi_paragraph_direction, 18258DEFUN ("current-bidi-paragraph-direction", Fcurrent_bidi_paragraph_direction,