diff options
| author | Eli Zaretskii | 2010-05-01 21:11:20 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2010-05-01 21:11:20 +0300 |
| commit | af7c7572ce8d87f51817d0f518d1b0aced074a41 (patch) | |
| tree | ff962558f8c48781e6a76883bd429b5ea6be73ba /src | |
| parent | 502269d6e71e78eaafe2da520d9b14ecf732914d (diff) | |
| parent | b47e0dcf2db5d0f754342f0eb13e53974bfbefbe (diff) | |
| download | emacs-af7c7572ce8d87f51817d0f518d1b0aced074a41.tar.gz emacs-af7c7572ce8d87f51817d0f518d1b0aced074a41.zip | |
Fix display of R2L lines and cursor motion in bidi buffers.
xdisp.c (find_row_end): New function, refactored from display_line.
(display_line): Use it.
(extend_face_to_end_of_line): In almost-filled rows, extend only
if the row is R2L and not continued.
(display_line): Fix prepending of truncation glyphs to R2L rows.
Preserve overlay and string info in row->end.
(insert_left_trunc_glyphs): Support addition of left truncation
glyphs to R2L rows.
(set_cursor_from_row): Don't place cursor on the vertical border
glyph between adjacent windows. Fix a crash when a display string
is continued to the next line. Don't return zero if cursor was
found by `cursor' property of a display string.
(try_cursor_movement): Don't assume that row->end == (row+1)->start,
test for that explicitly.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 20 | ||||
| -rw-r--r-- | src/xdisp.c | 341 |
2 files changed, 225 insertions, 136 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index e5c6a0b23b7..0b4baf64cf4 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,23 @@ | |||
| 1 | 2010-05-01 Eli Zaretskii <eliz@gnu.org> | ||
| 2 | |||
| 3 | Miscellaneous fixes of bidi display. | ||
| 4 | |||
| 5 | * xdisp.c (find_row_end): New function, refactored from | ||
| 6 | display_line. | ||
| 7 | (display_line): Use it. | ||
| 8 | (extend_face_to_end_of_line): In almost-filled rows, extend only | ||
| 9 | if the row is R2L and not continued. | ||
| 10 | (display_line): Fix prepending of truncation glyphs to R2L rows. | ||
| 11 | Preserve overlay and string info in row->end. | ||
| 12 | (insert_left_trunc_glyphs): Support addition of left truncation | ||
| 13 | glyphs to R2L rows. | ||
| 14 | (set_cursor_from_row): Don't place cursor on the vertical border | ||
| 15 | glyph between adjacent windows. Fix a crash when a display string | ||
| 16 | is continued to the next line. Don't return zero if cursor was | ||
| 17 | found by `cursor' property of a display string. | ||
| 18 | (try_cursor_movement): Don't assume that row->end == (row+1)->start, | ||
| 19 | test for that explicitly. | ||
| 20 | |||
| 1 | 2010-05-01 Glenn Morris <rgm@gnu.org> | 21 | 2010-05-01 Glenn Morris <rgm@gnu.org> |
| 2 | 22 | ||
| 3 | * Makefile.in (gmallocobj, rallocobj, vmlimitobj): Initialize to null, | 23 | * Makefile.in (gmallocobj, rallocobj, vmlimitobj): Initialize to null, |
diff --git a/src/xdisp.c b/src/xdisp.c index 4834b61a626..6d906825d1e 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -12776,6 +12776,13 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos) | |||
| 12776 | rightmost glyph. Case in point: an empty last line that is | 12776 | rightmost glyph. Case in point: an empty last line that is |
| 12777 | part of an R2L paragraph. */ | 12777 | part of an R2L paragraph. */ |
| 12778 | cursor = end - 1; | 12778 | cursor = end - 1; |
| 12779 | /* Avoid placing the cursor on the last glyph of the row, where | ||
| 12780 | on terminal frames we hold the vertical border between | ||
| 12781 | adjacent windows. */ | ||
| 12782 | if (!FRAME_WINDOW_P (WINDOW_XFRAME (w)) | ||
| 12783 | && !WINDOW_RIGHTMOST_P (w) | ||
| 12784 | && cursor == row->glyphs[LAST_AREA] - 1) | ||
| 12785 | cursor--; | ||
| 12779 | x = -1; /* will be computed below, at label compute_x */ | 12786 | x = -1; /* will be computed below, at label compute_x */ |
| 12780 | } | 12787 | } |
| 12781 | 12788 | ||
| @@ -13015,7 +13022,8 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos) | |||
| 13015 | 13022 | ||
| 13016 | cursor = glyph; | 13023 | cursor = glyph; |
| 13017 | for (glyph += incr; | 13024 | for (glyph += incr; |
| 13018 | EQ (glyph->object, str); | 13025 | (row->reversed_p ? glyph > stop : glyph < stop) |
| 13026 | && EQ (glyph->object, str); | ||
| 13019 | glyph += incr) | 13027 | glyph += incr) |
| 13020 | { | 13028 | { |
| 13021 | Lisp_Object cprop; | 13029 | Lisp_Object cprop; |
| @@ -13055,8 +13063,9 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos) | |||
| 13055 | 13063 | ||
| 13056 | /* If we reached the end of the line, and END was from a string, | 13064 | /* If we reached the end of the line, and END was from a string, |
| 13057 | the cursor is not on this line. */ | 13065 | the cursor is not on this line. */ |
| 13058 | if (glyph == end | 13066 | if (cursor == NULL |
| 13059 | && STRINGP ((glyph - incr)->object) | 13067 | && (row->reversed_p ? glyph <= end : glyph >= end) |
| 13068 | && STRINGP (end->object) | ||
| 13060 | && row->continued_p) | 13069 | && row->continued_p) |
| 13061 | return 0; | 13070 | return 0; |
| 13062 | } | 13071 | } |
| @@ -13714,11 +13723,14 @@ try_cursor_movement (window, startp, scroll_step) | |||
| 13714 | ++row; | 13723 | ++row; |
| 13715 | } | 13724 | } |
| 13716 | 13725 | ||
| 13717 | /* The end position of a row equals the start position | 13726 | /* If the end position of a row equals the start |
| 13718 | of the next row. If PT is there, we would rather | 13727 | position of the next row, and PT is at that position, |
| 13719 | display it in the next line. */ | 13728 | we would rather display cursor in the next line. */ |
| 13720 | while (MATRIX_ROW_BOTTOM_Y (row) < last_y | 13729 | while (MATRIX_ROW_BOTTOM_Y (row) < last_y |
| 13721 | && MATRIX_ROW_END_CHARPOS (row) == PT | 13730 | && MATRIX_ROW_END_CHARPOS (row) == PT |
| 13731 | && row < w->current_matrix->rows | ||
| 13732 | + w->current_matrix->nrows - 1 | ||
| 13733 | && MATRIX_ROW_START_CHARPOS (row+1) == PT | ||
| 13722 | && !cursor_row_p (w, row)) | 13734 | && !cursor_row_p (w, row)) |
| 13723 | ++row; | 13735 | ++row; |
| 13724 | 13736 | ||
| @@ -16737,24 +16749,61 @@ insert_left_trunc_glyphs (it) | |||
| 16737 | produce_special_glyphs (&truncate_it, IT_TRUNCATION); | 16749 | produce_special_glyphs (&truncate_it, IT_TRUNCATION); |
| 16738 | 16750 | ||
| 16739 | /* Overwrite glyphs from IT with truncation glyphs. */ | 16751 | /* Overwrite glyphs from IT with truncation glyphs. */ |
| 16740 | from = truncate_it.glyph_row->glyphs[TEXT_AREA]; | 16752 | if (!it->glyph_row->reversed_p) |
| 16741 | end = from + truncate_it.glyph_row->used[TEXT_AREA]; | ||
| 16742 | to = it->glyph_row->glyphs[TEXT_AREA]; | ||
| 16743 | toend = to + it->glyph_row->used[TEXT_AREA]; | ||
| 16744 | |||
| 16745 | while (from < end) | ||
| 16746 | *to++ = *from++; | ||
| 16747 | |||
| 16748 | /* There may be padding glyphs left over. Overwrite them too. */ | ||
| 16749 | while (to < toend && CHAR_GLYPH_PADDING_P (*to)) | ||
| 16750 | { | 16753 | { |
| 16751 | from = truncate_it.glyph_row->glyphs[TEXT_AREA]; | 16754 | from = truncate_it.glyph_row->glyphs[TEXT_AREA]; |
| 16755 | end = from + truncate_it.glyph_row->used[TEXT_AREA]; | ||
| 16756 | to = it->glyph_row->glyphs[TEXT_AREA]; | ||
| 16757 | toend = to + it->glyph_row->used[TEXT_AREA]; | ||
| 16758 | |||
| 16752 | while (from < end) | 16759 | while (from < end) |
| 16753 | *to++ = *from++; | 16760 | *to++ = *from++; |
| 16761 | |||
| 16762 | /* There may be padding glyphs left over. Overwrite them too. */ | ||
| 16763 | while (to < toend && CHAR_GLYPH_PADDING_P (*to)) | ||
| 16764 | { | ||
| 16765 | from = truncate_it.glyph_row->glyphs[TEXT_AREA]; | ||
| 16766 | while (from < end) | ||
| 16767 | *to++ = *from++; | ||
| 16768 | } | ||
| 16769 | |||
| 16770 | if (to > toend) | ||
| 16771 | it->glyph_row->used[TEXT_AREA] = to - it->glyph_row->glyphs[TEXT_AREA]; | ||
| 16754 | } | 16772 | } |
| 16773 | else | ||
| 16774 | { | ||
| 16775 | /* In R2L rows, overwrite the last (rightmost) glyphs, and do | ||
| 16776 | that back to front. */ | ||
| 16777 | end = truncate_it.glyph_row->glyphs[TEXT_AREA]; | ||
| 16778 | from = end + truncate_it.glyph_row->used[TEXT_AREA] - 1; | ||
| 16779 | toend = it->glyph_row->glyphs[TEXT_AREA]; | ||
| 16780 | to = toend + it->glyph_row->used[TEXT_AREA] - 1; | ||
| 16781 | |||
| 16782 | while (from >= end && to >= toend) | ||
| 16783 | *to-- = *from--; | ||
| 16784 | while (to >= toend && CHAR_GLYPH_PADDING_P (*to)) | ||
| 16785 | { | ||
| 16786 | from = | ||
| 16787 | truncate_it.glyph_row->glyphs[TEXT_AREA] | ||
| 16788 | + truncate_it.glyph_row->used[TEXT_AREA] - 1; | ||
| 16789 | while (from >= end && to >= toend) | ||
| 16790 | *to-- = *from--; | ||
| 16791 | } | ||
| 16792 | if (from >= end) | ||
| 16793 | { | ||
| 16794 | /* Need to free some room before prepending additional | ||
| 16795 | glyphs. */ | ||
| 16796 | int move_by = from - end + 1; | ||
| 16797 | struct glyph *g0 = it->glyph_row->glyphs[TEXT_AREA]; | ||
| 16798 | struct glyph *g = g0 + it->glyph_row->used[TEXT_AREA] - 1; | ||
| 16755 | 16799 | ||
| 16756 | if (to > toend) | 16800 | for ( ; g >= g0; g--) |
| 16757 | it->glyph_row->used[TEXT_AREA] = to - it->glyph_row->glyphs[TEXT_AREA]; | 16801 | g[move_by] = *g; |
| 16802 | while (from >= end) | ||
| 16803 | *to-- = *from--; | ||
| 16804 | it->glyph_row->used[TEXT_AREA] += move_by; | ||
| 16805 | } | ||
| 16806 | } | ||
| 16758 | } | 16807 | } |
| 16759 | 16808 | ||
| 16760 | 16809 | ||
| @@ -16946,8 +16995,13 @@ extend_face_to_end_of_line (it) | |||
| 16946 | 16995 | ||
| 16947 | /* If line is already filled, do nothing. Non window-system frames | 16996 | /* If line is already filled, do nothing. Non window-system frames |
| 16948 | get a grace of one more ``pixel'' because their characters are | 16997 | get a grace of one more ``pixel'' because their characters are |
| 16949 | 1-``pixel'' wide, so they hit the equality too early. */ | 16998 | 1-``pixel'' wide, so they hit the equality too early. This grace |
| 16950 | if (it->current_x >= it->last_visible_x + !FRAME_WINDOW_P (f)) | 16999 | is needed only for R2L rows that are not continued, to produce |
| 17000 | one extra blank where we could display the cursor. */ | ||
| 17001 | if (it->current_x >= it->last_visible_x | ||
| 17002 | + (!FRAME_WINDOW_P (f) | ||
| 17003 | && it->glyph_row->reversed_p | ||
| 17004 | && !it->glyph_row->continued_p)) | ||
| 16951 | return; | 17005 | return; |
| 16952 | 17006 | ||
| 16953 | /* Face extension extends the background and box of IT->face_id | 17007 | /* Face extension extends the background and box of IT->face_id |
| @@ -17368,6 +17422,123 @@ unproduce_glyphs (it, n) | |||
| 17368 | glyph[-n] = *glyph; | 17422 | glyph[-n] = *glyph; |
| 17369 | } | 17423 | } |
| 17370 | 17424 | ||
| 17425 | /* Find the positions in a bidi-reordered ROW to serve as ROW->start | ||
| 17426 | and ROW->end. */ | ||
| 17427 | static struct display_pos | ||
| 17428 | find_row_end (it, row) | ||
| 17429 | struct it *it; | ||
| 17430 | struct glyph_row *row; | ||
| 17431 | { | ||
| 17432 | /* FIXME: Revisit this when glyph ``spilling'' in continuation | ||
| 17433 | lines' rows is implemented for bidi-reordered rows. */ | ||
| 17434 | EMACS_INT min_pos = ZV + 1, max_pos = 0; | ||
| 17435 | struct glyph *g; | ||
| 17436 | struct it save_it; | ||
| 17437 | struct text_pos tpos; | ||
| 17438 | struct display_pos row_end = it->current; | ||
| 17439 | |||
| 17440 | for (g = row->glyphs[TEXT_AREA]; | ||
| 17441 | g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]; | ||
| 17442 | g++) | ||
| 17443 | { | ||
| 17444 | if (BUFFERP (g->object)) | ||
| 17445 | { | ||
| 17446 | if (g->charpos > 0 && g->charpos < min_pos) | ||
| 17447 | min_pos = g->charpos; | ||
| 17448 | if (g->charpos > max_pos) | ||
| 17449 | max_pos = g->charpos; | ||
| 17450 | } | ||
| 17451 | } | ||
| 17452 | /* Empty lines have a valid buffer position at their first | ||
| 17453 | glyph, but that glyph's OBJECT is zero, as if it didn't come | ||
| 17454 | from a buffer. If we didn't find any valid buffer positions | ||
| 17455 | in this row, maybe we have such an empty line. */ | ||
| 17456 | if (max_pos == 0 && row->used[TEXT_AREA]) | ||
| 17457 | { | ||
| 17458 | for (g = row->glyphs[TEXT_AREA]; | ||
| 17459 | g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]; | ||
| 17460 | g++) | ||
| 17461 | { | ||
| 17462 | if (INTEGERP (g->object)) | ||
| 17463 | { | ||
| 17464 | if (g->charpos > 0 && g->charpos < min_pos) | ||
| 17465 | min_pos = g->charpos; | ||
| 17466 | if (g->charpos > max_pos) | ||
| 17467 | max_pos = g->charpos; | ||
| 17468 | } | ||
| 17469 | } | ||
| 17470 | } | ||
| 17471 | |||
| 17472 | /* ROW->start is the value of min_pos, the minimal buffer position | ||
| 17473 | we have in ROW. */ | ||
| 17474 | if (min_pos <= ZV) | ||
| 17475 | { | ||
| 17476 | /* Avoid calling the costly CHAR_TO_BYTE if possible. */ | ||
| 17477 | if (min_pos != row->start.pos.charpos) | ||
| 17478 | SET_TEXT_POS (row->start.pos, min_pos, CHAR_TO_BYTE (min_pos)); | ||
| 17479 | if (max_pos == 0) | ||
| 17480 | max_pos = min_pos; | ||
| 17481 | } | ||
| 17482 | |||
| 17483 | /* For ROW->end, we need the position that is _after_ max_pos, in | ||
| 17484 | the logical order, unless we are at ZV. */ | ||
| 17485 | if (row->ends_at_zv_p) | ||
| 17486 | { | ||
| 17487 | if (!row->used[TEXT_AREA]) | ||
| 17488 | row->start.pos = row_end.pos; | ||
| 17489 | } | ||
| 17490 | else if (row->used[TEXT_AREA] && max_pos) | ||
| 17491 | { | ||
| 17492 | int at_eol_p; | ||
| 17493 | |||
| 17494 | SET_TEXT_POS (tpos, max_pos, CHAR_TO_BYTE (max_pos)); | ||
| 17495 | save_it = *it; | ||
| 17496 | it->bidi_p = 0; | ||
| 17497 | reseat (it, tpos, 0); | ||
| 17498 | if (!get_next_display_element (it)) | ||
| 17499 | abort (); /* this row cannot be at ZV, see above */ | ||
| 17500 | at_eol_p = ITERATOR_AT_END_OF_LINE_P (it); | ||
| 17501 | set_iterator_to_next (it, 1); | ||
| 17502 | row_end = it->current; | ||
| 17503 | /* If the character at max_pos is not a newline and the | ||
| 17504 | characters at max_pos+1 is a newline, skip that newline as | ||
| 17505 | well. Note that this may skip some invisible text. */ | ||
| 17506 | if (!at_eol_p | ||
| 17507 | && get_next_display_element (it) | ||
| 17508 | && ITERATOR_AT_END_OF_LINE_P (it)) | ||
| 17509 | { | ||
| 17510 | set_iterator_to_next (it, 1); | ||
| 17511 | /* Record the position after the newline of a continued row. | ||
| 17512 | We will need that to set ROW->end of the last row | ||
| 17513 | produced for a continued line. */ | ||
| 17514 | if (row->continued_p) | ||
| 17515 | save_it.eol_pos = it->current.pos; | ||
| 17516 | else | ||
| 17517 | { | ||
| 17518 | row_end = it->current; | ||
| 17519 | save_it.eol_pos.charpos = save_it.eol_pos.bytepos = 0; | ||
| 17520 | } | ||
| 17521 | } | ||
| 17522 | else if (!row->continued_p | ||
| 17523 | && MATRIX_ROW_CONTINUATION_LINE_P (row) | ||
| 17524 | && it->eol_pos.charpos > 0) | ||
| 17525 | { | ||
| 17526 | /* Last row of a continued line. Use the position recorded | ||
| 17527 | in IT->eol_pos, to the effect that the newline belongs to | ||
| 17528 | this row, not to the row which displays the character | ||
| 17529 | with the largest buffer position before the newline. */ | ||
| 17530 | row_end.pos = it->eol_pos; | ||
| 17531 | it->eol_pos.charpos = it->eol_pos.bytepos = 0; | ||
| 17532 | } | ||
| 17533 | *it = save_it; | ||
| 17534 | /* The members of ROW->end that are not taken from buffer | ||
| 17535 | positions are copied from IT->current. */ | ||
| 17536 | row_end.string_pos = it->current.string_pos; | ||
| 17537 | row_end.overlay_string_index = it->current.overlay_string_index; | ||
| 17538 | row_end.dpvec_index = it->current.dpvec_index; | ||
| 17539 | } | ||
| 17540 | return row_end; | ||
| 17541 | } | ||
| 17371 | 17542 | ||
| 17372 | /* Construct the glyph row IT->glyph_row in the desired matrix of | 17543 | /* Construct the glyph row IT->glyph_row in the desired matrix of |
| 17373 | IT->w from text at the current position of IT. See dispextern.h | 17544 | IT->w from text at the current position of IT. See dispextern.h |
| @@ -17386,7 +17557,6 @@ display_line (it) | |||
| 17386 | int wrap_row_used = -1, wrap_row_ascent, wrap_row_height; | 17557 | int wrap_row_used = -1, wrap_row_ascent, wrap_row_height; |
| 17387 | int wrap_row_phys_ascent, wrap_row_phys_height; | 17558 | int wrap_row_phys_ascent, wrap_row_phys_height; |
| 17388 | int wrap_row_extra_line_spacing; | 17559 | int wrap_row_extra_line_spacing; |
| 17389 | struct display_pos row_end; | ||
| 17390 | int cvpos; | 17560 | int cvpos; |
| 17391 | 17561 | ||
| 17392 | /* We always start displaying at hpos zero even if hscrolled. */ | 17562 | /* We always start displaying at hpos zero even if hscrolled. */ |
| @@ -17815,10 +17985,14 @@ display_line (it) | |||
| 17815 | for (i = 0; i < row->used[TEXT_AREA]; i++) | 17985 | for (i = 0; i < row->used[TEXT_AREA]; i++) |
| 17816 | if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i])) | 17986 | if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i])) |
| 17817 | break; | 17987 | break; |
| 17818 | /* Remove padding glyphs at the front of ROW, to | 17988 | /* Remove any padding glyphs at the front of ROW, to |
| 17819 | make room for the truncation glyphs we will be | 17989 | make room for the truncation glyphs we will be |
| 17820 | adding below. */ | 17990 | adding below. The loop below always inserts at |
| 17821 | unproduce_glyphs (it, i); | 17991 | least one truncation glyph, so also remove the |
| 17992 | last glyph added to ROW. */ | ||
| 17993 | unproduce_glyphs (it, i + 1); | ||
| 17994 | /* Adjust i for the loop below. */ | ||
| 17995 | i = row->used[TEXT_AREA] - (i + 1); | ||
| 17822 | } | 17996 | } |
| 17823 | 17997 | ||
| 17824 | for (n = row->used[TEXT_AREA]; i < n; ++i) | 17998 | for (n = row->used[TEXT_AREA]; i < n; ++i) |
| @@ -17910,118 +18084,13 @@ display_line (it) | |||
| 17910 | compute_line_metrics (it); | 18084 | compute_line_metrics (it); |
| 17911 | 18085 | ||
| 17912 | /* Remember the position at which this line ends. */ | 18086 | /* Remember the position at which this line ends. */ |
| 17913 | row->end = row_end = it->current; | 18087 | row->end = it->current; |
| 18088 | /* ROW->start and ROW->end must be the smallest and the largest | ||
| 18089 | buffer positions in ROW. But if ROW was bidi-reordered, these | ||
| 18090 | two positions can be anywhere in the row, so we must rescan all | ||
| 18091 | of the ROW's glyphs to find them. */ | ||
| 17914 | if (it->bidi_p) | 18092 | if (it->bidi_p) |
| 17915 | { | 18093 | row->end = find_row_end (it, row); |
| 17916 | /* ROW->start and ROW->end must be the smallest and largest | ||
| 17917 | buffer positions in ROW. But if ROW was bidi-reordered, | ||
| 17918 | these two positions can be anywhere in the row, so we must | ||
| 17919 | rescan all of the ROW's glyphs to find them. */ | ||
| 17920 | /* FIXME: Revisit this when glyph ``spilling'' in continuation | ||
| 17921 | lines' rows is implemented for bidi-reordered rows. */ | ||
| 17922 | EMACS_INT min_pos = ZV + 1, max_pos = 0; | ||
| 17923 | struct glyph *g; | ||
| 17924 | struct it save_it; | ||
| 17925 | struct text_pos tpos; | ||
| 17926 | |||
| 17927 | for (g = row->glyphs[TEXT_AREA]; | ||
| 17928 | g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]; | ||
| 17929 | g++) | ||
| 17930 | { | ||
| 17931 | if (BUFFERP (g->object)) | ||
| 17932 | { | ||
| 17933 | if (g->charpos > 0 && g->charpos < min_pos) | ||
| 17934 | min_pos = g->charpos; | ||
| 17935 | if (g->charpos > max_pos) | ||
| 17936 | max_pos = g->charpos; | ||
| 17937 | } | ||
| 17938 | } | ||
| 17939 | /* Empty lines have a valid buffer position at their first | ||
| 17940 | glyph, but that glyph's OBJECT is zero, as if it didn't come | ||
| 17941 | from a buffer. If we didn't find any valid buffer positions | ||
| 17942 | in this row, maybe we have such an empty line. */ | ||
| 17943 | if (min_pos == ZV + 1 && row->used[TEXT_AREA]) | ||
| 17944 | { | ||
| 17945 | for (g = row->glyphs[TEXT_AREA]; | ||
| 17946 | g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]; | ||
| 17947 | g++) | ||
| 17948 | { | ||
| 17949 | if (INTEGERP (g->object)) | ||
| 17950 | { | ||
| 17951 | if (g->charpos > 0 && g->charpos < min_pos) | ||
| 17952 | min_pos = g->charpos; | ||
| 17953 | if (g->charpos > max_pos) | ||
| 17954 | max_pos = g->charpos; | ||
| 17955 | } | ||
| 17956 | } | ||
| 17957 | } | ||
| 17958 | if (min_pos <= ZV) | ||
| 17959 | { | ||
| 17960 | if (min_pos != row->start.pos.charpos) | ||
| 17961 | { | ||
| 17962 | row->start.pos.charpos = min_pos; | ||
| 17963 | row->start.pos.bytepos = CHAR_TO_BYTE (min_pos); | ||
| 17964 | } | ||
| 17965 | if (max_pos == 0) | ||
| 17966 | max_pos = min_pos; | ||
| 17967 | } | ||
| 17968 | /* For ROW->end, we need the position that is _after_ max_pos, | ||
| 17969 | in the logical order, unless we are at ZV. */ | ||
| 17970 | if (row->ends_at_zv_p) | ||
| 17971 | { | ||
| 17972 | row_end = row->end = it->current; | ||
| 17973 | if (!row->used[TEXT_AREA]) | ||
| 17974 | { | ||
| 17975 | row->start.pos.charpos = row_end.pos.charpos; | ||
| 17976 | row->start.pos.bytepos = row_end.pos.bytepos; | ||
| 17977 | } | ||
| 17978 | } | ||
| 17979 | else if (row->used[TEXT_AREA] && max_pos) | ||
| 17980 | { | ||
| 17981 | SET_TEXT_POS (tpos, max_pos, CHAR_TO_BYTE (max_pos)); | ||
| 17982 | save_it = *it; | ||
| 17983 | it->bidi_p = 0; | ||
| 17984 | reseat (it, tpos, 0); | ||
| 17985 | if (!get_next_display_element (it)) | ||
| 17986 | abort (); /* row at ZV was already handled above */ | ||
| 17987 | set_iterator_to_next (it, 1); | ||
| 17988 | row_end = it->current; | ||
| 17989 | /* If the character at max_pos+1 is a newline, skip that as | ||
| 17990 | well. Note that this may skip some invisible text. */ | ||
| 17991 | if (get_next_display_element (it) | ||
| 17992 | && ITERATOR_AT_END_OF_LINE_P (it)) | ||
| 17993 | { | ||
| 17994 | set_iterator_to_next (it, 1); | ||
| 17995 | /* Record the position after the newline of a continued | ||
| 17996 | row. We will need that to set ROW->end of the last | ||
| 17997 | row produced for a continued line. */ | ||
| 17998 | if (row->continued_p) | ||
| 17999 | { | ||
| 18000 | save_it.eol_pos.charpos = IT_CHARPOS (*it); | ||
| 18001 | save_it.eol_pos.bytepos = IT_BYTEPOS (*it); | ||
| 18002 | } | ||
| 18003 | else | ||
| 18004 | { | ||
| 18005 | row_end = it->current; | ||
| 18006 | save_it.eol_pos.charpos = save_it.eol_pos.bytepos = 0; | ||
| 18007 | } | ||
| 18008 | } | ||
| 18009 | else if (!row->continued_p | ||
| 18010 | && MATRIX_ROW_CONTINUATION_LINE_P (row) | ||
| 18011 | && it->eol_pos.charpos > 0) | ||
| 18012 | { | ||
| 18013 | /* Last row of a continued line. Use the position | ||
| 18014 | recorded in ROW->eol_pos, to the effect that the | ||
| 18015 | newline belongs to this row, not to the row which | ||
| 18016 | displays the character with the largest buffer | ||
| 18017 | position. */ | ||
| 18018 | row_end.pos = it->eol_pos; | ||
| 18019 | it->eol_pos.charpos = it->eol_pos.bytepos = 0; | ||
| 18020 | } | ||
| 18021 | *it = save_it; | ||
| 18022 | row->end = row_end; | ||
| 18023 | } | ||
| 18024 | } | ||
| 18025 | 18094 | ||
| 18026 | /* Record whether this row ends inside an ellipsis. */ | 18095 | /* Record whether this row ends inside an ellipsis. */ |
| 18027 | row->ends_in_ellipsis_p | 18096 | row->ends_in_ellipsis_p |
| @@ -18075,7 +18144,7 @@ display_line (it) | |||
| 18075 | the flag accordingly. */ | 18144 | the flag accordingly. */ |
| 18076 | if (it->glyph_row < MATRIX_BOTTOM_TEXT_ROW (it->w->desired_matrix, it->w)) | 18145 | if (it->glyph_row < MATRIX_BOTTOM_TEXT_ROW (it->w->desired_matrix, it->w)) |
| 18077 | it->glyph_row->reversed_p = row->reversed_p; | 18146 | it->glyph_row->reversed_p = row->reversed_p; |
| 18078 | it->start = row_end; | 18147 | it->start = row->end; |
| 18079 | return row->displays_text_p; | 18148 | return row->displays_text_p; |
| 18080 | } | 18149 | } |
| 18081 | 18150 | ||