diff options
| author | Eli Zaretskii | 2010-05-18 18:22:15 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2010-05-18 18:22:15 +0300 |
| commit | d36fe2375ad338a799038a5afee82d00e6b6b7ac (patch) | |
| tree | c556ef3bd494e8c858a285b1f408137b1266dab1 /src | |
| parent | 560bb7ae8eb9873e1a6be40ff7f26e08228e1d1a (diff) | |
| download | emacs-d36fe2375ad338a799038a5afee82d00e6b6b7ac.tar.gz emacs-d36fe2375ad338a799038a5afee82d00e6b6b7ac.zip | |
Initial reimplementation of calculating line edge positions in bidi lines.
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.
(display_line): Record minimum and maximum buffer positions for
glyphs in this row. Record the position of the newline that
terminates the line.
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 29 | ||||
| -rw-r--r-- | src/dispextern.h | 36 | ||||
| -rw-r--r-- | src/dispnew.c | 16 | ||||
| -rw-r--r-- | src/xdisp.c | 248 |
4 files changed, 200 insertions, 129 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index b0965f8e514..fe30d07692a 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,30 @@ | |||
| 1 | 2010-05-18 Eli Zaretskii <eliz@gnu.org> | ||
| 2 | |||
| 3 | * dispextern.h (struct glyph_row): New members minpos and maxpos. | ||
| 4 | (MATRIX_ROW_START_CHARPOS, MATRIX_ROW_START_BYTEPOS) | ||
| 5 | (MATRIX_ROW_END_CHARPOS, MATRIX_ROW_END_BYTEPOS): Reference minpos | ||
| 6 | and maxpos members instead of start.pos and end.pos, respectively. | ||
| 7 | |||
| 8 | * xdisp.c (display_line): Compare IT_CHARPOS with the position in | ||
| 9 | row->start.pos, rather than with MATRIX_ROW_START_CHARPOS. | ||
| 10 | (cursor_row_p): Use row->end.pos rather than MATRIX_ROW_END_CHARPOS. | ||
| 11 | (try_window_reusing_current_matrix, try_window_id): Use | ||
| 12 | ROW->minpos rather than ROW->start.pos. | ||
| 13 | (init_from_display_pos, init_iterator): Use EMACS_INT for | ||
| 14 | character and byte positions. | ||
| 15 | (find_row_edges): Renamed from find_row_end. Accept additional | ||
| 16 | arguments for minimum and maximum buffer positions seen by | ||
| 17 | display_line for this row. Don't use iterator to find the | ||
| 18 | position following the maximum one; instead, increment the | ||
| 19 | position found by display_line directly. | ||
| 20 | (display_line): Record minimum and maximum buffer positions for | ||
| 21 | glyphs in this row. Record the position of the newline that | ||
| 22 | terminates the line. | ||
| 23 | |||
| 24 | * dispnew.c (increment_row_positions, check_matrix_invariants): | ||
| 25 | Increment and check row->start.pos and row->end.pos, in addition | ||
| 26 | to MATRIX_ROW_START_CHARPOS and MATRIX_ROW_END_CHARPOS. | ||
| 27 | |||
| 1 | 2010-05-18 Juanma Barranquero <lekktu@gmail.com> | 28 | 2010-05-18 Juanma Barranquero <lekktu@gmail.com> |
| 2 | 29 | ||
| 3 | * charset.c (load_charset_map_from_file): Don't call close after fclose. | 30 | * charset.c (load_charset_map_from_file): Don't call close after fclose. |
| @@ -91,6 +118,8 @@ | |||
| 91 | * xdisp.c (Fcurrent_bidi_paragraph_direction): New function. | 118 | * xdisp.c (Fcurrent_bidi_paragraph_direction): New function. |
| 92 | (syms_of_xdisp): Defsubr it. | 119 | (syms_of_xdisp): Defsubr it. |
| 93 | 120 | ||
| 121 | * cmds.c (Fforward_char, Fbackward_char): Doc fix. | ||
| 122 | |||
| 94 | * Makefile.in: Fix MSDOS-related comments. | 123 | * Makefile.in: Fix MSDOS-related comments. |
| 95 | 124 | ||
| 96 | 2010-05-15 Glenn Morris <rgm@gnu.org> | 125 | 2010-05-15 Glenn Morris <rgm@gnu.org> |
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 6b3097c9a1a..9cd562e8e3d 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -2598,7 +2598,7 @@ void | |||
| 2598 | init_iterator (it, w, charpos, bytepos, row, base_face_id) | 2598 | init_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 |
| @@ -14972,7 +14972,7 @@ try_window_reusing_current_matrix (w) | |||
| 14972 | /* The variable new_start now holds the new window start. The old | 14972 | /* The variable new_start now holds the new window start. The old |
| 14973 | start `start' can be determined from the current matrix. */ | 14973 | start `start' can be determined from the current matrix. */ |
| 14974 | SET_TEXT_POS_FROM_MARKER (new_start, w->start); | 14974 | SET_TEXT_POS_FROM_MARKER (new_start, w->start); |
| 14975 | start = start_row->start.pos; | 14975 | start = start_row->minpos; |
| 14976 | start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix); | 14976 | start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix); |
| 14977 | 14977 | ||
| 14978 | /* Clear the desired matrix for the display below. */ | 14978 | /* Clear the desired matrix for the display below. */ |
| @@ -15011,7 +15011,7 @@ try_window_reusing_current_matrix (w) | |||
| 15011 | { | 15011 | { |
| 15012 | /* Advance to the next row as the "start". */ | 15012 | /* Advance to the next row as the "start". */ |
| 15013 | start_row++; | 15013 | start_row++; |
| 15014 | start = start_row->start.pos; | 15014 | start = start_row->minpos; |
| 15015 | /* If there are no more rows to try, or just one, give up. */ | 15015 | /* If there are no more rows to try, or just one, give up. */ |
| 15016 | if (start_row == MATRIX_MODE_LINE_ROW (w->current_matrix) - 1 | 15016 | if (start_row == MATRIX_MODE_LINE_ROW (w->current_matrix) - 1 |
| 15017 | || w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row) | 15017 | || w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row) |
| @@ -15905,13 +15905,13 @@ try_window_id (w) | |||
| 15905 | as is, without changing glyph positions since no text has | 15905 | as is, without changing glyph positions since no text has |
| 15906 | been added/removed in front of the window end. */ | 15906 | been added/removed in front of the window end. */ |
| 15907 | r0 = MATRIX_FIRST_TEXT_ROW (current_matrix); | 15907 | r0 = MATRIX_FIRST_TEXT_ROW (current_matrix); |
| 15908 | if (TEXT_POS_EQUAL_P (start, r0->start.pos) | 15908 | if (TEXT_POS_EQUAL_P (start, r0->minpos) |
| 15909 | /* PT must not be in a partially visible line. */ | 15909 | /* PT must not be in a partially visible line. */ |
| 15910 | && !(PT >= MATRIX_ROW_START_CHARPOS (row) | 15910 | && !(PT >= MATRIX_ROW_START_CHARPOS (row) |
| 15911 | && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w))) | 15911 | && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w))) |
| 15912 | { | 15912 | { |
| 15913 | /* We have to compute the window end anew since text | 15913 | /* We have to compute the window end anew since text |
| 15914 | can have been added/removed after it. */ | 15914 | could have been added/removed after it. */ |
| 15915 | w->window_end_pos | 15915 | w->window_end_pos |
| 15916 | = make_number (Z - MATRIX_ROW_END_CHARPOS (row)); | 15916 | = make_number (Z - MATRIX_ROW_END_CHARPOS (row)); |
| 15917 | w->window_end_bytepos | 15917 | w->window_end_bytepos |
| @@ -15943,7 +15943,7 @@ try_window_id (w) | |||
| 15943 | start is not in changed text, otherwise positions would not be | 15943 | start is not in changed text, otherwise positions would not be |
| 15944 | comparable. */ | 15944 | comparable. */ |
| 15945 | row = MATRIX_FIRST_TEXT_ROW (current_matrix); | 15945 | row = MATRIX_FIRST_TEXT_ROW (current_matrix); |
| 15946 | if (!TEXT_POS_EQUAL_P (start, row->start.pos)) | 15946 | if (!TEXT_POS_EQUAL_P (start, row->minpos)) |
| 15947 | GIVE_UP (16); | 15947 | GIVE_UP (16); |
| 15948 | 15948 | ||
| 15949 | /* Give up if the window ends in strings. Overlay strings | 15949 | /* Give up if the window ends in strings. Overlay strings |
| @@ -17335,7 +17335,7 @@ cursor_row_p (w, row) | |||
| 17335 | { | 17335 | { |
| 17336 | int cursor_row_p = 1; | 17336 | int cursor_row_p = 1; |
| 17337 | 17337 | ||
| 17338 | if (PT == MATRIX_ROW_END_CHARPOS (row)) | 17338 | if (PT == CHARPOS (row->end.pos)) |
| 17339 | { | 17339 | { |
| 17340 | /* Suppose the row ends on a string. | 17340 | /* Suppose the row ends on a string. |
| 17341 | Unless the row is continued, that means it ends on a newline | 17341 | Unless the row is continued, that means it ends on a newline |
| @@ -17372,14 +17372,15 @@ cursor_row_p (w, row) | |||
| 17372 | { | 17372 | { |
| 17373 | /* If the row ends in middle of a real character, | 17373 | /* If the row ends in middle of a real character, |
| 17374 | and the line is continued, we want the cursor here. | 17374 | and the line is continued, we want the cursor here. |
| 17375 | That's because MATRIX_ROW_END_CHARPOS would equal | 17375 | That's because CHARPOS (ROW->end.pos) would equal |
| 17376 | PT if PT is before the character. */ | 17376 | PT if PT is before the character. */ |
| 17377 | if (!row->ends_in_ellipsis_p) | 17377 | if (!row->ends_in_ellipsis_p) |
| 17378 | cursor_row_p = row->continued_p; | 17378 | cursor_row_p = row->continued_p; |
| 17379 | else | 17379 | else |
| 17380 | /* If the row ends in an ellipsis, then | 17380 | /* If the row ends in an ellipsis, then |
| 17381 | MATRIX_ROW_END_CHARPOS will equal point after the invisible text. | 17381 | CHARPOS (ROW->end.pos) will equal point after the |
| 17382 | We want that position to be displayed after the ellipsis. */ | 17382 | invisible text. We want that position to be displayed |
| 17383 | after the ellipsis. */ | ||
| 17383 | cursor_row_p = 0; | 17384 | cursor_row_p = 0; |
| 17384 | } | 17385 | } |
| 17385 | /* If the row ends at ZV, display the cursor at the end of that | 17386 | /* If the row ends at ZV, display the cursor at the end of that |
| @@ -17515,122 +17516,87 @@ unproduce_glyphs (it, n) | |||
| 17515 | glyph[-n] = *glyph; | 17516 | glyph[-n] = *glyph; |
| 17516 | } | 17517 | } |
| 17517 | 17518 | ||
| 17518 | /* Find the positions in a bidi-reordered ROW to serve as ROW->start | 17519 | /* Find the positions in a bidi-reordered ROW to serve as ROW->minpos |
| 17519 | and ROW->end. */ | 17520 | and ROW->maxpos. */ |
| 17520 | static struct display_pos | 17521 | static void |
| 17521 | find_row_end (it, row) | 17522 | find_row_edges (it, row, min_pos, min_bpos, max_pos, max_bpos) |
| 17522 | struct it *it; | 17523 | struct it *it; |
| 17523 | struct glyph_row *row; | 17524 | struct glyph_row *row; |
| 17525 | EMACS_INT min_pos, min_bpos, max_pos, max_bpos; | ||
| 17524 | { | 17526 | { |
| 17525 | /* FIXME: Revisit this when glyph ``spilling'' in continuation | 17527 | /* FIXME: Revisit this when glyph ``spilling'' in continuation |
| 17526 | lines' rows is implemented for bidi-reordered rows. */ | 17528 | lines' rows is implemented for bidi-reordered rows. */ |
| 17527 | EMACS_INT min_pos = ZV + 1, max_pos = 0; | ||
| 17528 | struct glyph *g; | ||
| 17529 | struct it save_it; | ||
| 17530 | struct text_pos tpos; | ||
| 17531 | struct display_pos row_end = it->current; | ||
| 17532 | 17529 | ||
| 17533 | for (g = row->glyphs[TEXT_AREA]; | 17530 | /* ROW->minpos is the value of min_pos, the minimal buffer position |
| 17534 | g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]; | 17531 | we have in ROW. */ |
| 17535 | g++) | 17532 | if (min_pos <= ZV) |
| 17536 | { | 17533 | { |
| 17537 | if (BUFFERP (g->object)) | 17534 | SET_TEXT_POS (row->minpos, min_pos, min_bpos); |
| 17535 | if (max_pos == 0) | ||
| 17538 | { | 17536 | { |
| 17539 | if (g->charpos > 0 && g->charpos < min_pos) | 17537 | max_pos = min_pos; |
| 17540 | min_pos = g->charpos; | 17538 | max_bpos = min_bpos; |
| 17541 | if (g->charpos > max_pos) | ||
| 17542 | max_pos = g->charpos; | ||
| 17543 | } | 17539 | } |
| 17544 | } | 17540 | } |
| 17545 | /* Empty lines have a valid buffer position at their first | 17541 | else |
| 17546 | glyph, but that glyph's OBJECT is zero, as if it didn't come | ||
| 17547 | from a buffer. If we didn't find any valid buffer positions | ||
| 17548 | in this row, maybe we have such an empty line. */ | ||
| 17549 | if (max_pos == 0 && row->used[TEXT_AREA]) | ||
| 17550 | { | 17542 | { |
| 17551 | for (g = row->glyphs[TEXT_AREA]; | 17543 | /* We didn't find _any_ valid buffer positions in any of the |
| 17552 | g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]; | 17544 | glyphs, so we must trust the iterator's computed |
| 17553 | g++) | 17545 | positions. */ |
| 17554 | { | 17546 | row->minpos = row->start.pos; |
| 17555 | if (INTEGERP (g->object)) | 17547 | max_pos = CHARPOS (it->current.pos); |
| 17556 | { | 17548 | max_bpos = BYTEPOS (it->current.pos); |
| 17557 | if (g->charpos > 0 && g->charpos < min_pos) | ||
| 17558 | min_pos = g->charpos; | ||
| 17559 | if (g->charpos > max_pos) | ||
| 17560 | max_pos = g->charpos; | ||
| 17561 | } | ||
| 17562 | } | ||
| 17563 | } | 17549 | } |
| 17564 | 17550 | ||
| 17565 | /* ROW->start is the value of min_pos, the minimal buffer position | 17551 | if (!max_pos) |
| 17566 | we have in ROW. */ | 17552 | abort (); |
| 17567 | if (min_pos <= ZV) | ||
| 17568 | { | ||
| 17569 | /* Avoid calling the costly CHAR_TO_BYTE if possible. */ | ||
| 17570 | if (min_pos != row->start.pos.charpos) | ||
| 17571 | SET_TEXT_POS (row->start.pos, min_pos, CHAR_TO_BYTE (min_pos)); | ||
| 17572 | if (max_pos == 0) | ||
| 17573 | max_pos = min_pos; | ||
| 17574 | } | ||
| 17575 | 17553 | ||
| 17576 | /* For ROW->end, we need the position that is _after_ max_pos, in | 17554 | /* Here are the various use-cases for ending the row, and the |
| 17577 | the logical order, unless we are at ZV. */ | 17555 | corresponding values for ROW->maxpos: |
| 17556 | |||
| 17557 | Empty line min_pos + 1 | ||
| 17558 | Line ends in a newline from buffer eol_pos + 1 | ||
| 17559 | Line is continued from buffer max_pos + 1 | ||
| 17560 | Line ends in a newline from string max_pos | ||
| 17561 | Line is continued from string max_pos | ||
| 17562 | Line is entirely from a string min_pos | ||
| 17563 | Line that ends at ZV ZV | ||
| 17564 | |||
| 17565 | If you discover other use-cases, please add them here as | ||
| 17566 | appropriate. */ | ||
| 17578 | if (row->ends_at_zv_p) | 17567 | if (row->ends_at_zv_p) |
| 17568 | row->maxpos = it->current.pos; | ||
| 17569 | else if (row->used[TEXT_AREA]) | ||
| 17579 | { | 17570 | { |
| 17580 | if (!row->used[TEXT_AREA]) | 17571 | if (max_pos == min_pos) |
| 17581 | row->start.pos = row_end.pos; | ||
| 17582 | } | ||
| 17583 | else if (row->used[TEXT_AREA] && max_pos) | ||
| 17584 | { | ||
| 17585 | int at_eol_p; | ||
| 17586 | |||
| 17587 | SET_TEXT_POS (tpos, max_pos, CHAR_TO_BYTE (max_pos)); | ||
| 17588 | save_it = *it; | ||
| 17589 | it->bidi_p = 0; | ||
| 17590 | reseat (it, tpos, 0); | ||
| 17591 | if (!get_next_display_element (it)) | ||
| 17592 | abort (); /* this row cannot be at ZV, see above */ | ||
| 17593 | at_eol_p = ITERATOR_AT_END_OF_LINE_P (it); | ||
| 17594 | set_iterator_to_next (it, 1); | ||
| 17595 | row_end = it->current; | ||
| 17596 | /* If the character at max_pos is not a newline and the | ||
| 17597 | characters at max_pos+1 is a newline, skip that newline as | ||
| 17598 | well. Note that this may skip some invisible text. */ | ||
| 17599 | if (!at_eol_p | ||
| 17600 | && get_next_display_element (it) | ||
| 17601 | && ITERATOR_AT_END_OF_LINE_P (it)) | ||
| 17602 | { | 17572 | { |
| 17603 | set_iterator_to_next (it, 1); | 17573 | if (it->method == GET_FROM_BUFFER) |
| 17604 | /* Record the position after the newline of a continued row. | 17574 | /* Empty line, which stands for a newline. */ |
| 17605 | We will need that to set ROW->end of the last row | 17575 | SET_TEXT_POS (row->maxpos, min_pos + 1, min_bpos + 1); |
| 17606 | produced for a continued line. */ | ||
| 17607 | if (row->continued_p) | ||
| 17608 | save_it.eol_pos = it->current.pos; | ||
| 17609 | else | 17576 | else |
| 17610 | { | 17577 | /* A line that is entirely from a string. */ |
| 17611 | row_end = it->current; | 17578 | row->maxpos = row->minpos; |
| 17612 | save_it.eol_pos.charpos = save_it.eol_pos.bytepos = 0; | ||
| 17613 | } | ||
| 17614 | } | 17579 | } |
| 17615 | else if (!row->continued_p | 17580 | else if (CHARPOS (it->eol_pos) > 0) |
| 17616 | && MATRIX_ROW_CONTINUATION_LINE_P (row) | 17581 | SET_TEXT_POS (row->maxpos, |
| 17617 | && it->eol_pos.charpos > 0) | 17582 | CHARPOS (it->eol_pos) + 1, BYTEPOS (it->eol_pos) + 1); |
| 17583 | else if (row->continued_p) | ||
| 17618 | { | 17584 | { |
| 17619 | /* Last row of a continued line. Use the position recorded | 17585 | if (it->method == GET_FROM_BUFFER) |
| 17620 | in IT->eol_pos, to the effect that the newline belongs to | 17586 | { |
| 17621 | this row, not to the row which displays the character | 17587 | INC_BOTH (max_pos, max_bpos); |
| 17622 | with the largest buffer position before the newline. */ | 17588 | SET_TEXT_POS (row->maxpos, max_pos, max_bpos); |
| 17623 | row_end.pos = it->eol_pos; | 17589 | } |
| 17624 | it->eol_pos.charpos = it->eol_pos.bytepos = 0; | 17590 | else |
| 17591 | SET_TEXT_POS (row->maxpos, max_pos, max_bpos); | ||
| 17625 | } | 17592 | } |
| 17626 | *it = save_it; | 17593 | else if (row->ends_in_newline_from_string_p) |
| 17627 | /* The members of ROW->end that are not taken from buffer | 17594 | SET_TEXT_POS (row->maxpos, max_pos, max_bpos); |
| 17628 | positions are copied from IT->current. */ | 17595 | else |
| 17629 | row_end.string_pos = it->current.string_pos; | 17596 | abort (); |
| 17630 | row_end.overlay_string_index = it->current.overlay_string_index; | ||
| 17631 | row_end.dpvec_index = it->current.dpvec_index; | ||
| 17632 | } | 17597 | } |
| 17633 | return row_end; | 17598 | else |
| 17599 | row->maxpos = it->current.pos; | ||
| 17634 | } | 17600 | } |
| 17635 | 17601 | ||
| 17636 | /* Construct the glyph row IT->glyph_row in the desired matrix of | 17602 | /* Construct the glyph row IT->glyph_row in the desired matrix of |
| @@ -17651,6 +17617,7 @@ display_line (it) | |||
| 17651 | int wrap_row_phys_ascent, wrap_row_phys_height; | 17617 | int wrap_row_phys_ascent, wrap_row_phys_height; |
| 17652 | int wrap_row_extra_line_spacing; | 17618 | int wrap_row_extra_line_spacing; |
| 17653 | int cvpos; | 17619 | int cvpos; |
| 17620 | EMACS_INT min_pos = ZV + 1, min_bpos, max_pos = 0, max_bpos; | ||
| 17654 | 17621 | ||
| 17655 | /* We always start displaying at hpos zero even if hscrolled. */ | 17622 | /* We always start displaying at hpos zero even if hscrolled. */ |
| 17656 | xassert (it->hpos == 0 && it->current_x == 0); | 17623 | xassert (it->hpos == 0 && it->current_x == 0); |
| @@ -17741,7 +17708,8 @@ display_line (it) | |||
| 17741 | row->ends_at_zv_p = 1; | 17708 | row->ends_at_zv_p = 1; |
| 17742 | /* A row that displays right-to-left text must always have | 17709 | /* A row that displays right-to-left text must always have |
| 17743 | its last face extended all the way to the end of line, | 17710 | its last face extended all the way to the end of line, |
| 17744 | even if this row ends in ZV. */ | 17711 | even if this row ends in ZV, because we still write to th |
| 17712 | screen left to right. */ | ||
| 17745 | if (row->reversed_p) | 17713 | if (row->reversed_p) |
| 17746 | extend_face_to_end_of_line (it); | 17714 | extend_face_to_end_of_line (it); |
| 17747 | break; | 17715 | break; |
| @@ -17889,6 +17857,27 @@ display_line (it) | |||
| 17889 | } | 17857 | } |
| 17890 | } | 17858 | } |
| 17891 | } | 17859 | } |
| 17860 | |||
| 17861 | /* Record the maximum and minimum buffer | ||
| 17862 | positions seen so far in glyphs that will be | ||
| 17863 | displayed by this row. */ | ||
| 17864 | if (it->bidi_p) | ||
| 17865 | { | ||
| 17866 | if (BUFFERP (glyph->object) | ||
| 17867 | || INTEGERP (glyph->object)) | ||
| 17868 | { | ||
| 17869 | if (IT_CHARPOS (*it) < min_pos) | ||
| 17870 | { | ||
| 17871 | min_pos = IT_CHARPOS (*it); | ||
| 17872 | min_bpos = IT_BYTEPOS (*it); | ||
| 17873 | } | ||
| 17874 | if (IT_CHARPOS (*it) > max_pos) | ||
| 17875 | { | ||
| 17876 | max_pos = IT_CHARPOS (*it); | ||
| 17877 | max_bpos = IT_BYTEPOS (*it); | ||
| 17878 | } | ||
| 17879 | } | ||
| 17880 | } | ||
| 17892 | } | 17881 | } |
| 17893 | else if (CHAR_GLYPH_PADDING_P (*glyph) | 17882 | else if (CHAR_GLYPH_PADDING_P (*glyph) |
| 17894 | && !FRAME_WINDOW_P (it->f)) | 17883 | && !FRAME_WINDOW_P (it->f)) |
| @@ -17994,6 +17983,27 @@ display_line (it) | |||
| 17994 | /* Increment number of glyphs actually displayed. */ | 17983 | /* Increment number of glyphs actually displayed. */ |
| 17995 | ++it->hpos; | 17984 | ++it->hpos; |
| 17996 | 17985 | ||
| 17986 | /* Record the maximum and minimum buffer positions | ||
| 17987 | seen so far in glyphs that will be displayed by | ||
| 17988 | this row. */ | ||
| 17989 | if (it->bidi_p) | ||
| 17990 | { | ||
| 17991 | if (BUFFERP (glyph->object) | ||
| 17992 | || INTEGERP (glyph->object)) | ||
| 17993 | { | ||
| 17994 | if (IT_CHARPOS (*it) < min_pos) | ||
| 17995 | { | ||
| 17996 | min_pos = IT_CHARPOS (*it); | ||
| 17997 | min_bpos = IT_BYTEPOS (*it); | ||
| 17998 | } | ||
| 17999 | if (IT_CHARPOS (*it) > max_pos) | ||
| 18000 | { | ||
| 18001 | max_pos = IT_CHARPOS (*it); | ||
| 18002 | max_bpos = IT_BYTEPOS (*it); | ||
| 18003 | } | ||
| 18004 | } | ||
| 18005 | } | ||
| 18006 | |||
| 17997 | if (x < it->first_visible_x) | 18007 | if (x < it->first_visible_x) |
| 17998 | /* Glyph is partially visible, i.e. row starts at | 18008 | /* Glyph is partially visible, i.e. row starts at |
| 17999 | negative X position. */ | 18009 | negative X position. */ |
| @@ -18045,6 +18055,10 @@ display_line (it) | |||
| 18045 | if (used_before == 0) | 18055 | if (used_before == 0) |
| 18046 | row->glyphs[TEXT_AREA]->charpos = CHARPOS (it->position); | 18056 | row->glyphs[TEXT_AREA]->charpos = CHARPOS (it->position); |
| 18047 | 18057 | ||
| 18058 | /* Record the position of the newline, for use in | ||
| 18059 | find_row_edges. */ | ||
| 18060 | it->eol_pos = it->current.pos; | ||
| 18061 | |||
| 18048 | /* Consume the line end. This skips over invisible lines. */ | 18062 | /* Consume the line end. This skips over invisible lines. */ |
| 18049 | set_iterator_to_next (it, 1); | 18063 | set_iterator_to_next (it, 1); |
| 18050 | it->continuation_lines_width = 0; | 18064 | it->continuation_lines_width = 0; |
| @@ -18124,7 +18138,7 @@ display_line (it) | |||
| 18124 | /* If line is not empty and hscrolled, maybe insert truncation glyphs | 18138 | /* If line is not empty and hscrolled, maybe insert truncation glyphs |
| 18125 | at the left window margin. */ | 18139 | at the left window margin. */ |
| 18126 | if (it->first_visible_x | 18140 | if (it->first_visible_x |
| 18127 | && IT_CHARPOS (*it) != MATRIX_ROW_START_CHARPOS (row)) | 18141 | && IT_CHARPOS (*it) != CHARPOS (row->start.pos)) |
| 18128 | { | 18142 | { |
| 18129 | if (!FRAME_WINDOW_P (it->f)) | 18143 | if (!FRAME_WINDOW_P (it->f)) |
| 18130 | insert_left_trunc_glyphs (it); | 18144 | insert_left_trunc_glyphs (it); |
| @@ -18178,12 +18192,19 @@ display_line (it) | |||
| 18178 | 18192 | ||
| 18179 | /* Remember the position at which this line ends. */ | 18193 | /* Remember the position at which this line ends. */ |
| 18180 | row->end = it->current; | 18194 | row->end = it->current; |
| 18181 | /* ROW->start and ROW->end must be the smallest and the largest | 18195 | if (!it->bidi_p) |
| 18182 | buffer positions in ROW. But if ROW was bidi-reordered, these | 18196 | { |
| 18183 | two positions can be anywhere in the row, so we must rescan all | 18197 | row->minpos = row->start.pos; |
| 18184 | of the ROW's glyphs to find them. */ | 18198 | row->maxpos = row->end.pos; |
| 18185 | if (it->bidi_p) | 18199 | } |
| 18186 | row->end = find_row_end (it, row); | 18200 | else |
| 18201 | { | ||
| 18202 | /* ROW->minpos and ROW->maxpos must be the smallest and | ||
| 18203 | `1 + the largest' buffer positions in ROW. But if ROW was | ||
| 18204 | bidi-reordered, these two positions can be anywhere in the | ||
| 18205 | row, so we must determine them now. */ | ||
| 18206 | find_row_edges (it, row, min_pos, min_bpos, max_pos, max_bpos); | ||
| 18207 | } | ||
| 18187 | 18208 | ||
| 18188 | /* Record whether this row ends inside an ellipsis. */ | 18209 | /* Record whether this row ends inside an ellipsis. */ |
| 18189 | row->ends_in_ellipsis_p | 18210 | row->ends_in_ellipsis_p |
| @@ -18229,6 +18250,7 @@ display_line (it) | |||
| 18229 | row to be used. */ | 18250 | row to be used. */ |
| 18230 | it->current_x = it->hpos = 0; | 18251 | it->current_x = it->hpos = 0; |
| 18231 | it->current_y += row->height; | 18252 | it->current_y += row->height; |
| 18253 | SET_TEXT_POS (it->eol_pos, 0, 0); | ||
| 18232 | ++it->vpos; | 18254 | ++it->vpos; |
| 18233 | ++it->glyph_row; | 18255 | ++it->glyph_row; |
| 18234 | /* The next row should by default use the same value of the | 18256 | /* The next row should by default use the same value of the |