diff options
| author | Eli Zaretskii | 2010-05-01 11:50:01 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2010-05-01 11:50:01 +0300 |
| commit | 59ca28de83fdc18a1d0c06aec7173ef2de3aabac (patch) | |
| tree | 32c1874ba8f99d0c34cd8c9323acef518eaf5739 | |
| parent | 4fc85283057936715d48842ec8f89ae146b1e8d7 (diff) | |
| download | emacs-59ca28de83fdc18a1d0c06aec7173ef2de3aabac.tar.gz emacs-59ca28de83fdc18a1d0c06aec7173ef2de3aabac.zip | |
Refactor code that determines row->start and row->end.
xdisp.c (find_row_end): New function, refactored from display_line.
(display_line): Use it.
| -rw-r--r-- | src/ChangeLog | 5 | ||||
| -rw-r--r-- | src/xdisp.c | 239 |
2 files changed, 129 insertions, 115 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index a6a89a4ea3b..13b2a29e74d 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,8 @@ | |||
| 1 | 2010-05-01 Eli Zaretskii <eliz@gnu.org> | ||
| 2 | |||
| 3 | * xdisp.c (find_row_end): New function, refactored from display_line. | ||
| 4 | (display_line): Use it. | ||
| 5 | |||
| 1 | 2010-04-27 Eli Zaretskii <eliz@gnu.org> | 6 | 2010-04-27 Eli Zaretskii <eliz@gnu.org> |
| 2 | 7 | ||
| 3 | * xdisp.c (set_cursor_from_row): Fix a crash when a display string | 8 | * xdisp.c (set_cursor_from_row): Fix a crash when a display string |
diff --git a/src/xdisp.c b/src/xdisp.c index 9e14f7879a2..017aa690023 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -17370,6 +17370,123 @@ unproduce_glyphs (it, n) | |||
| 17370 | glyph[-n] = *glyph; | 17370 | glyph[-n] = *glyph; |
| 17371 | } | 17371 | } |
| 17372 | 17372 | ||
| 17373 | /* Find the positions in a bidi-reordered ROW to serve as ROW->start | ||
| 17374 | and ROW->end. */ | ||
| 17375 | static struct display_pos | ||
| 17376 | find_row_end (it, row) | ||
| 17377 | struct it *it; | ||
| 17378 | struct glyph_row *row; | ||
| 17379 | { | ||
| 17380 | /* FIXME: Revisit this when glyph ``spilling'' in continuation | ||
| 17381 | lines' rows is implemented for bidi-reordered rows. */ | ||
| 17382 | EMACS_INT min_pos = ZV + 1, max_pos = 0; | ||
| 17383 | struct glyph *g; | ||
| 17384 | struct it save_it; | ||
| 17385 | struct text_pos tpos; | ||
| 17386 | struct display_pos row_end = it->current; | ||
| 17387 | |||
| 17388 | for (g = row->glyphs[TEXT_AREA]; | ||
| 17389 | g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]; | ||
| 17390 | g++) | ||
| 17391 | { | ||
| 17392 | if (BUFFERP (g->object)) | ||
| 17393 | { | ||
| 17394 | if (g->charpos > 0 && g->charpos < min_pos) | ||
| 17395 | min_pos = g->charpos; | ||
| 17396 | if (g->charpos > max_pos) | ||
| 17397 | max_pos = g->charpos; | ||
| 17398 | } | ||
| 17399 | } | ||
| 17400 | /* Empty lines have a valid buffer position at their first | ||
| 17401 | glyph, but that glyph's OBJECT is zero, as if it didn't come | ||
| 17402 | from a buffer. If we didn't find any valid buffer positions | ||
| 17403 | in this row, maybe we have such an empty line. */ | ||
| 17404 | if (max_pos == 0 && row->used[TEXT_AREA]) | ||
| 17405 | { | ||
| 17406 | for (g = row->glyphs[TEXT_AREA]; | ||
| 17407 | g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]; | ||
| 17408 | g++) | ||
| 17409 | { | ||
| 17410 | if (INTEGERP (g->object)) | ||
| 17411 | { | ||
| 17412 | if (g->charpos > 0 && g->charpos < min_pos) | ||
| 17413 | min_pos = g->charpos; | ||
| 17414 | if (g->charpos > max_pos) | ||
| 17415 | max_pos = g->charpos; | ||
| 17416 | } | ||
| 17417 | } | ||
| 17418 | } | ||
| 17419 | |||
| 17420 | /* ROW->start is the value of min_pos, the minimal buffer position | ||
| 17421 | we have in ROW. */ | ||
| 17422 | if (min_pos <= ZV) | ||
| 17423 | { | ||
| 17424 | /* Avoid calling the costly CHAR_TO_BYTE if possible. */ | ||
| 17425 | if (min_pos != row->start.pos.charpos) | ||
| 17426 | SET_TEXT_POS (row->start.pos, min_pos, CHAR_TO_BYTE (min_pos)); | ||
| 17427 | if (max_pos == 0) | ||
| 17428 | max_pos = min_pos; | ||
| 17429 | } | ||
| 17430 | |||
| 17431 | /* For ROW->end, we need the position that is _after_ max_pos, in | ||
| 17432 | the logical order, unless we are at ZV. */ | ||
| 17433 | if (row->ends_at_zv_p) | ||
| 17434 | { | ||
| 17435 | if (!row->used[TEXT_AREA]) | ||
| 17436 | row->start.pos = row_end.pos; | ||
| 17437 | } | ||
| 17438 | else if (row->used[TEXT_AREA] && max_pos) | ||
| 17439 | { | ||
| 17440 | int at_eol_p; | ||
| 17441 | |||
| 17442 | SET_TEXT_POS (tpos, max_pos, CHAR_TO_BYTE (max_pos)); | ||
| 17443 | save_it = *it; | ||
| 17444 | it->bidi_p = 0; | ||
| 17445 | reseat (it, tpos, 0); | ||
| 17446 | if (!get_next_display_element (it)) | ||
| 17447 | abort (); /* this row cannot be at ZV, see above */ | ||
| 17448 | at_eol_p = ITERATOR_AT_END_OF_LINE_P (it); | ||
| 17449 | set_iterator_to_next (it, 1); | ||
| 17450 | row_end = it->current; | ||
| 17451 | /* If the character at max_pos is not a newline and the | ||
| 17452 | characters at max_pos+1 is a newline, skip that newline as | ||
| 17453 | well. Note that this may skip some invisible text. */ | ||
| 17454 | if (!at_eol_p | ||
| 17455 | && get_next_display_element (it) | ||
| 17456 | && ITERATOR_AT_END_OF_LINE_P (it)) | ||
| 17457 | { | ||
| 17458 | set_iterator_to_next (it, 1); | ||
| 17459 | /* Record the position after the newline of a continued row. | ||
| 17460 | We will need that to set ROW->end of the last row | ||
| 17461 | produced for a continued line. */ | ||
| 17462 | if (row->continued_p) | ||
| 17463 | save_it.eol_pos = it->current.pos; | ||
| 17464 | else | ||
| 17465 | { | ||
| 17466 | row_end = it->current; | ||
| 17467 | save_it.eol_pos.charpos = save_it.eol_pos.bytepos = 0; | ||
| 17468 | } | ||
| 17469 | } | ||
| 17470 | else if (!row->continued_p | ||
| 17471 | && MATRIX_ROW_CONTINUATION_LINE_P (row) | ||
| 17472 | && it->eol_pos.charpos > 0) | ||
| 17473 | { | ||
| 17474 | /* Last row of a continued line. Use the position recorded | ||
| 17475 | in IT->eol_pos, to the effect that the newline belongs to | ||
| 17476 | this row, not to the row which displays the character | ||
| 17477 | with the largest buffer position before the newline. */ | ||
| 17478 | row_end.pos = it->eol_pos; | ||
| 17479 | it->eol_pos.charpos = it->eol_pos.bytepos = 0; | ||
| 17480 | } | ||
| 17481 | *it = save_it; | ||
| 17482 | /* The members of ROW->end that are not taken from buffer | ||
| 17483 | positions are copied from IT->current. */ | ||
| 17484 | row_end.string_pos = it->current.string_pos; | ||
| 17485 | row_end.overlay_string_index = it->current.overlay_string_index; | ||
| 17486 | row_end.dpvec_index = it->current.dpvec_index; | ||
| 17487 | } | ||
| 17488 | return row_end; | ||
| 17489 | } | ||
| 17373 | 17490 | ||
| 17374 | /* Construct the glyph row IT->glyph_row in the desired matrix of | 17491 | /* Construct the glyph row IT->glyph_row in the desired matrix of |
| 17375 | IT->w from text at the current position of IT. See dispextern.h | 17492 | IT->w from text at the current position of IT. See dispextern.h |
| @@ -17388,7 +17505,6 @@ display_line (it) | |||
| 17388 | int wrap_row_used = -1, wrap_row_ascent, wrap_row_height; | 17505 | int wrap_row_used = -1, wrap_row_ascent, wrap_row_height; |
| 17389 | int wrap_row_phys_ascent, wrap_row_phys_height; | 17506 | int wrap_row_phys_ascent, wrap_row_phys_height; |
| 17390 | int wrap_row_extra_line_spacing; | 17507 | int wrap_row_extra_line_spacing; |
| 17391 | struct display_pos row_end; | ||
| 17392 | int cvpos; | 17508 | int cvpos; |
| 17393 | 17509 | ||
| 17394 | /* We always start displaying at hpos zero even if hscrolled. */ | 17510 | /* We always start displaying at hpos zero even if hscrolled. */ |
| @@ -17912,120 +18028,13 @@ display_line (it) | |||
| 17912 | compute_line_metrics (it); | 18028 | compute_line_metrics (it); |
| 17913 | 18029 | ||
| 17914 | /* Remember the position at which this line ends. */ | 18030 | /* Remember the position at which this line ends. */ |
| 17915 | row->end = row_end = it->current; | 18031 | row->end = it->current; |
| 18032 | /* ROW->start and ROW->end must be the smallest and the largest | ||
| 18033 | buffer positions in ROW. But if ROW was bidi-reordered, these | ||
| 18034 | two positions can be anywhere in the row, so we must rescan all | ||
| 18035 | of the ROW's glyphs to find them. */ | ||
| 17916 | if (it->bidi_p) | 18036 | if (it->bidi_p) |
| 17917 | { | 18037 | row->end = find_row_end (it, row); |
| 17918 | /* ROW->start and ROW->end must be the smallest and largest | ||
| 17919 | buffer positions in ROW. But if ROW was bidi-reordered, | ||
| 17920 | these two positions can be anywhere in the row, so we must | ||
| 17921 | rescan all of the ROW's glyphs to find them. */ | ||
| 17922 | /* FIXME: Revisit this when glyph ``spilling'' in continuation | ||
| 17923 | lines' rows is implemented for bidi-reordered rows. */ | ||
| 17924 | EMACS_INT min_pos = ZV + 1, max_pos = 0; | ||
| 17925 | struct glyph *g; | ||
| 17926 | struct it save_it; | ||
| 17927 | struct text_pos tpos; | ||
| 17928 | |||
| 17929 | for (g = row->glyphs[TEXT_AREA]; | ||
| 17930 | g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]; | ||
| 17931 | g++) | ||
| 17932 | { | ||
| 17933 | if (BUFFERP (g->object)) | ||
| 17934 | { | ||
| 17935 | if (g->charpos > 0 && g->charpos < min_pos) | ||
| 17936 | min_pos = g->charpos; | ||
| 17937 | if (g->charpos > max_pos) | ||
| 17938 | max_pos = g->charpos; | ||
| 17939 | } | ||
| 17940 | } | ||
| 17941 | /* Empty lines have a valid buffer position at their first | ||
| 17942 | glyph, but that glyph's OBJECT is zero, as if it didn't come | ||
| 17943 | from a buffer. If we didn't find any valid buffer positions | ||
| 17944 | in this row, maybe we have such an empty line. */ | ||
| 17945 | if (min_pos == ZV + 1 && row->used[TEXT_AREA]) | ||
| 17946 | { | ||
| 17947 | for (g = row->glyphs[TEXT_AREA]; | ||
| 17948 | g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]; | ||
| 17949 | g++) | ||
| 17950 | { | ||
| 17951 | if (INTEGERP (g->object)) | ||
| 17952 | { | ||
| 17953 | if (g->charpos > 0 && g->charpos < min_pos) | ||
| 17954 | min_pos = g->charpos; | ||
| 17955 | if (g->charpos > max_pos) | ||
| 17956 | max_pos = g->charpos; | ||
| 17957 | } | ||
| 17958 | } | ||
| 17959 | } | ||
| 17960 | if (min_pos <= ZV) | ||
| 17961 | { | ||
| 17962 | if (min_pos != row->start.pos.charpos) | ||
| 17963 | { | ||
| 17964 | row->start.pos.charpos = min_pos; | ||
| 17965 | row->start.pos.bytepos = CHAR_TO_BYTE (min_pos); | ||
| 17966 | } | ||
| 17967 | if (max_pos == 0) | ||
| 17968 | max_pos = min_pos; | ||
| 17969 | } | ||
| 17970 | /* For ROW->end, we need the position that is _after_ max_pos, | ||
| 17971 | in the logical order, unless we are at ZV. */ | ||
| 17972 | if (row->ends_at_zv_p) | ||
| 17973 | { | ||
| 17974 | if (!row->used[TEXT_AREA]) | ||
| 17975 | { | ||
| 17976 | row->start.pos.charpos = row_end.pos.charpos; | ||
| 17977 | row->start.pos.bytepos = row_end.pos.bytepos; | ||
| 17978 | } | ||
| 17979 | } | ||
| 17980 | else if (row->used[TEXT_AREA] && max_pos) | ||
| 17981 | { | ||
| 17982 | SET_TEXT_POS (tpos, max_pos, CHAR_TO_BYTE (max_pos)); | ||
| 17983 | save_it = *it; | ||
| 17984 | it->bidi_p = 0; | ||
| 17985 | reseat (it, tpos, 0); | ||
| 17986 | if (!get_next_display_element (it)) | ||
| 17987 | abort (); /* row at ZV was already handled above */ | ||
| 17988 | set_iterator_to_next (it, 1); | ||
| 17989 | row_end = it->current; | ||
| 17990 | /* If the character at max_pos+1 is a newline, skip that as | ||
| 17991 | well. Note that this may skip some invisible text. */ | ||
| 17992 | if (get_next_display_element (it) | ||
| 17993 | && ITERATOR_AT_END_OF_LINE_P (it)) | ||
| 17994 | { | ||
| 17995 | set_iterator_to_next (it, 1); | ||
| 17996 | /* Record the position after the newline of a continued | ||
| 17997 | row. We will need that to set ROW->end of the last | ||
| 17998 | row produced for a continued line. */ | ||
| 17999 | if (row->continued_p) | ||
| 18000 | { | ||
| 18001 | save_it.eol_pos.charpos = IT_CHARPOS (*it); | ||
| 18002 | save_it.eol_pos.bytepos = IT_BYTEPOS (*it); | ||
| 18003 | } | ||
| 18004 | else | ||
| 18005 | { | ||
| 18006 | row_end = it->current; | ||
| 18007 | save_it.eol_pos.charpos = save_it.eol_pos.bytepos = 0; | ||
| 18008 | } | ||
| 18009 | } | ||
| 18010 | else if (!row->continued_p | ||
| 18011 | && MATRIX_ROW_CONTINUATION_LINE_P (row) | ||
| 18012 | && it->eol_pos.charpos > 0) | ||
| 18013 | { | ||
| 18014 | /* Last row of a continued line. Use the position | ||
| 18015 | recorded in ROW->eol_pos, to the effect that the | ||
| 18016 | newline belongs to this row, not to the row which | ||
| 18017 | displays the character with the largest buffer | ||
| 18018 | position. */ | ||
| 18019 | row_end.pos = it->eol_pos; | ||
| 18020 | it->eol_pos.charpos = it->eol_pos.bytepos = 0; | ||
| 18021 | } | ||
| 18022 | *it = save_it; | ||
| 18023 | row_end.string_pos = it->current.string_pos; | ||
| 18024 | row_end.overlay_string_index = it->current.overlay_string_index; | ||
| 18025 | row_end.dpvec_index = it->current.dpvec_index; | ||
| 18026 | row->end = row_end; | ||
| 18027 | } | ||
| 18028 | } | ||
| 18029 | 18038 | ||
| 18030 | /* Record whether this row ends inside an ellipsis. */ | 18039 | /* Record whether this row ends inside an ellipsis. */ |
| 18031 | row->ends_in_ellipsis_p | 18040 | row->ends_in_ellipsis_p |
| @@ -18079,7 +18088,7 @@ display_line (it) | |||
| 18079 | the flag accordingly. */ | 18088 | the flag accordingly. */ |
| 18080 | if (it->glyph_row < MATRIX_BOTTOM_TEXT_ROW (it->w->desired_matrix, it->w)) | 18089 | if (it->glyph_row < MATRIX_BOTTOM_TEXT_ROW (it->w->desired_matrix, it->w)) |
| 18081 | it->glyph_row->reversed_p = row->reversed_p; | 18090 | it->glyph_row->reversed_p = row->reversed_p; |
| 18082 | it->start = row_end; | 18091 | it->start = row->end; |
| 18083 | return row->displays_text_p; | 18092 | return row->displays_text_p; |
| 18084 | } | 18093 | } |
| 18085 | 18094 | ||