diff options
| author | Eli Zaretskii | 2011-09-20 20:13:45 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2011-09-20 20:13:45 +0300 |
| commit | 8c203dbf33f77e12b6833d26bb2b86e836ceef8e (patch) | |
| tree | 87a86bbab1745289ede2dc58cb8dc91aa00a1e7c /src | |
| parent | 5147931d624ce62d2382398859a06fa1f334fd56 (diff) | |
| download | emacs-8c203dbf33f77e12b6833d26bb2b86e836ceef8e.tar.gz emacs-8c203dbf33f77e12b6833d26bb2b86e836ceef8e.zip | |
Fix bug #9549 with longlines-show-hard-newlines.
src/xdisp.c (set_cursor_from_row): If the row ends in a newline from
a display string, extend search for cursor position to end of row.
(find_row_edges): If the row ends in a newline from a display
string, increment its MATRIX_ROW_END_CHARPOS by one.
Handle the case of a display string with multiple newlines.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 8 | ||||
| -rw-r--r-- | src/xdisp.c | 86 |
2 files changed, 91 insertions, 3 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 12a45918e87..f0b1ecc3caa 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,11 @@ | |||
| 1 | 2011-09-20 Eli Zaretskii <eliz@gnu.org> | ||
| 2 | |||
| 3 | * xdisp.c (set_cursor_from_row): If the row ends in a newline from | ||
| 4 | a display string, extend search for cursor position to end of row. | ||
| 5 | (find_row_edges): If the row ends in a newline from a display | ||
| 6 | string, increment its MATRIX_ROW_END_CHARPOS by one. (Bug#9549) | ||
| 7 | Handle the case of a display string with multiple newlines. | ||
| 8 | |||
| 1 | 2011-09-19 Lars Magne Ingebrigtsen <larsi@gnus.org> | 9 | 2011-09-19 Lars Magne Ingebrigtsen <larsi@gnus.org> |
| 2 | 10 | ||
| 3 | * lread.c (Fread_from_string): Document what FINAL-STRING-INDEX is | 11 | * lread.c (Fread_from_string): Document what FINAL-STRING-INDEX is |
diff --git a/src/xdisp.c b/src/xdisp.c index d58eea538f5..81cba29206a 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -13666,6 +13666,17 @@ set_cursor_from_row (struct window *w, struct glyph_row *row, | |||
| 13666 | 13666 | ||
| 13667 | x = -1; | 13667 | x = -1; |
| 13668 | 13668 | ||
| 13669 | /* If the row ends in a newline from a display string, | ||
| 13670 | reordering could have moved the glyphs belonging to the | ||
| 13671 | string out of the [GLYPH_BEFORE..GLYPH_AFTER] range. So | ||
| 13672 | in this case we extend the search to the last glyph in | ||
| 13673 | the row that was not inserted by redisplay. */ | ||
| 13674 | if (row->ends_in_newline_from_string_p) | ||
| 13675 | { | ||
| 13676 | glyph_after = end; | ||
| 13677 | pos_after = MATRIX_ROW_END_CHARPOS (row) + delta; | ||
| 13678 | } | ||
| 13679 | |||
| 13669 | /* GLYPH_BEFORE and GLYPH_AFTER are the glyphs that | 13680 | /* GLYPH_BEFORE and GLYPH_AFTER are the glyphs that |
| 13670 | correspond to POS_BEFORE and POS_AFTER, respectively. We | 13681 | correspond to POS_BEFORE and POS_AFTER, respectively. We |
| 13671 | need START and STOP in the order that corresponds to the | 13682 | need START and STOP in the order that corresponds to the |
| @@ -18341,7 +18352,8 @@ find_row_edges (struct it *it, struct glyph_row *row, | |||
| 18341 | Line ends in a newline from buffer eol_pos + 1 | 18352 | Line ends in a newline from buffer eol_pos + 1 |
| 18342 | Line is continued from buffer max_pos + 1 | 18353 | Line is continued from buffer max_pos + 1 |
| 18343 | Line is truncated on right it->current.pos | 18354 | Line is truncated on right it->current.pos |
| 18344 | Line ends in a newline from string max_pos | 18355 | Line ends in a newline from string max_pos + 1(*) |
| 18356 | (*) + 1 only when line ends in a forward scan | ||
| 18345 | Line is continued from string max_pos | 18357 | Line is continued from string max_pos |
| 18346 | Line is continued from display vector max_pos | 18358 | Line is continued from display vector max_pos |
| 18347 | Line is entirely from a string min_pos == max_pos | 18359 | Line is entirely from a string min_pos == max_pos |
| @@ -18354,8 +18366,76 @@ find_row_edges (struct it *it, struct glyph_row *row, | |||
| 18354 | row->maxpos = it->current.pos; | 18366 | row->maxpos = it->current.pos; |
| 18355 | else if (row->used[TEXT_AREA]) | 18367 | else if (row->used[TEXT_AREA]) |
| 18356 | { | 18368 | { |
| 18357 | if (row->ends_in_newline_from_string_p) | 18369 | int seen_this_string = 0; |
| 18358 | SET_TEXT_POS (row->maxpos, max_pos, max_bpos); | 18370 | struct glyph_row *r1 = row - 1; |
| 18371 | |||
| 18372 | /* Did we see the same display string on the previous row? */ | ||
| 18373 | if (STRINGP (it->object) | ||
| 18374 | /* this is not the first row */ | ||
| 18375 | && row > it->w->desired_matrix->rows | ||
| 18376 | /* previous row is not the header line */ | ||
| 18377 | && !r1->mode_line_p | ||
| 18378 | /* previous row also ends in a newline from a string */ | ||
| 18379 | && r1->ends_in_newline_from_string_p) | ||
| 18380 | { | ||
| 18381 | struct glyph *start, *end; | ||
| 18382 | |||
| 18383 | /* Search for the last glyph of the previous row that came | ||
| 18384 | from buffer or string. Depending on whether the row is | ||
| 18385 | L2R or R2L, we need to process it front to back or the | ||
| 18386 | other way round. */ | ||
| 18387 | if (!r1->reversed_p) | ||
| 18388 | { | ||
| 18389 | start = r1->glyphs[TEXT_AREA]; | ||
| 18390 | end = start + r1->used[TEXT_AREA]; | ||
| 18391 | /* Glyphs inserted by redisplay have an integer (zero) | ||
| 18392 | as their object. */ | ||
| 18393 | while (end > start | ||
| 18394 | && INTEGERP ((end - 1)->object) | ||
| 18395 | && (end - 1)->charpos <= 0) | ||
| 18396 | --end; | ||
| 18397 | if (end > start) | ||
| 18398 | { | ||
| 18399 | if (EQ ((end - 1)->object, it->object)) | ||
| 18400 | seen_this_string = 1; | ||
| 18401 | } | ||
| 18402 | else | ||
| 18403 | abort (); | ||
| 18404 | } | ||
| 18405 | else | ||
| 18406 | { | ||
| 18407 | end = r1->glyphs[TEXT_AREA] - 1; | ||
| 18408 | start = end + r1->used[TEXT_AREA]; | ||
| 18409 | while (end < start | ||
| 18410 | && INTEGERP ((end + 1)->object) | ||
| 18411 | && (end + 1)->charpos <= 0) | ||
| 18412 | ++end; | ||
| 18413 | if (end < start) | ||
| 18414 | { | ||
| 18415 | if (EQ ((end + 1)->object, it->object)) | ||
| 18416 | seen_this_string = 1; | ||
| 18417 | } | ||
| 18418 | else | ||
| 18419 | abort (); | ||
| 18420 | } | ||
| 18421 | } | ||
| 18422 | /* Take note of each display string that covers a newline only | ||
| 18423 | once, the first time we see it. This is for when a display | ||
| 18424 | string includes more than one newline in it. */ | ||
| 18425 | if (row->ends_in_newline_from_string_p && !seen_this_string) | ||
| 18426 | { | ||
| 18427 | /* If we were scanning the buffer forward when we displayed | ||
| 18428 | the string, we want to account for at least one buffer | ||
| 18429 | position that belongs to this row (position covered by | ||
| 18430 | the display string), so that cursor positioning will | ||
| 18431 | consider this row as a candidate when point is at the end | ||
| 18432 | of the visual line represented by this row. This is not | ||
| 18433 | required when scanning back, because max_pos will already | ||
| 18434 | have a much larger value. */ | ||
| 18435 | if (CHARPOS (row->end.pos) > max_pos) | ||
| 18436 | INC_BOTH (max_pos, max_bpos); | ||
| 18437 | SET_TEXT_POS (row->maxpos, max_pos, max_bpos); | ||
| 18438 | } | ||
| 18359 | else if (CHARPOS (it->eol_pos) > 0) | 18439 | else if (CHARPOS (it->eol_pos) > 0) |
| 18360 | SET_TEXT_POS (row->maxpos, | 18440 | SET_TEXT_POS (row->maxpos, |
| 18361 | CHARPOS (it->eol_pos) + 1, BYTEPOS (it->eol_pos) + 1); | 18441 | CHARPOS (it->eol_pos) + 1, BYTEPOS (it->eol_pos) + 1); |