aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2010-05-01 11:50:01 +0300
committerEli Zaretskii2010-05-01 11:50:01 +0300
commit59ca28de83fdc18a1d0c06aec7173ef2de3aabac (patch)
tree32c1874ba8f99d0c34cd8c9323acef518eaf5739 /src
parent4fc85283057936715d48842ec8f89ae146b1e8d7 (diff)
downloademacs-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.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog5
-rw-r--r--src/xdisp.c239
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 @@
12010-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
12010-04-27 Eli Zaretskii <eliz@gnu.org> 62010-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. */
17375static struct display_pos
17376find_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