changeset 107639:844012bdb5dd

Continue debugging continuation lines. .gdbinit (prowlims, pmtxrows): New commands. xdisp.c (display_line): Special-case the calculation of row->end in rows that end at ZV, to avoid abort in CHAR_TO_BYTE. Handle empty lines correctly when calculating row's max and min pos. Display cursor at the first glyph row that has its ends_at_zv_p flag set.
author Eli Zaretskii <eliz@gnu.org>
date Sat, 06 Mar 2010 11:06:24 -0500
parents 772da445ced7
children a744b1df50bd
files src/.gdbinit src/ChangeLog.bidi src/xdisp.c
diffstat 3 files changed, 106 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/src/.gdbinit	Sat Mar 06 05:16:27 2010 -0500
+++ b/src/.gdbinit	Sat Mar 06 11:06:24 2010 -0500
@@ -613,6 +613,28 @@
 Pretty print all glyphs in it->glyph_row.
 end
 
+define prowlims
+  printf "start=%d,end=%d,reversed=%d,cont=%d\n", $arg0->start.pos.charpos, $arg0->end.pos.charpos, $arg0->reversed_p, $arg0->continued_p
+end
+document prowlims
+Print important attributes of a glyph_row structure.
+Takes one argument, a pointer to a glyph_row structure.
+end
+
+define pmtxrows
+  set $mtx = $arg0
+  set $gl = $mtx->rows
+  set $glend = $mtx->rows + $mtx->nrows
+  while ($gl < $glend)
+    prowlims $gl
+    set $gl = $gl + 1
+  end
+end
+document pmtxrows
+Print data about glyph rows in a glyph matrix.
+Takes one argument, a pointer to a glyph_matrix structure.
+end
+
 define xtype
   xgettype $
   output $type
--- a/src/ChangeLog.bidi	Sat Mar 06 05:16:27 2010 -0500
+++ b/src/ChangeLog.bidi	Sat Mar 06 11:06:24 2010 -0500
@@ -1,3 +1,13 @@
+2010-03-06  Eli Zaretskii  <eliz@gnu.org>
+
+	* .gdbinit (prowlims, pmtxrows): New commands.
+
+	* xdisp.c (display_line): Special-case the calculation of row->end
+	in rows that end at ZV, to avoid abort in CHAR_TO_BYTE.  Handle
+	empty lines correctly when calculating row's max and min pos.
+	Display cursor at the first glyph row that has its ends_at_zv_p
+	flag set.
+
 2010-02-20  Eli Zaretskii  <eliz@gnu.org>
 
 	* xdisp.c (set_cursor_from_row): Compare candidate cursor
--- a/src/xdisp.c	Sat Mar 06 05:16:27 2010 -0500
+++ b/src/xdisp.c	Sat Mar 06 11:06:24 2010 -0500
@@ -17604,19 +17604,18 @@
   compute_line_metrics (it);
 
   /* Remember the position at which this line ends.  */
-  if (!it->bidi_p)
-    row->end = row_end = it->current;
-  else
-    {
-      EMACS_INT min_pos = row->start.pos.charpos, max_pos = 0;
-      struct glyph *g;
-      struct it save_it;
-      struct text_pos tpos;
-
+  row->end = row_end = it->current;
+  if (it->bidi_p)
+    {
       /* ROW->start and ROW->end must be the smallest and largest
 	 buffer positions in ROW.  But if ROW was bidi-reordered,
 	 these two positions can be anywhere in the row, so we must
 	 rescan all of the ROW's glyphs to find them.  */
+      EMACS_INT min_pos = ZV + 1, max_pos = 0;
+      struct glyph *g;
+      struct it save_it;
+      struct text_pos tpos;
+
       for (g = row->glyphs[TEXT_AREA];
 	   g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
 	   g++)
@@ -17629,34 +17628,68 @@
 		max_pos = g->charpos;
 	    }
 	}
-      if (min_pos < row->start.pos.charpos)
-	{
-	  row->start.pos.charpos = min_pos;
-	  row->start.pos.bytepos = CHAR_TO_BYTE (min_pos);
-	}
-      if (max_pos == 0)
-	max_pos = min_pos;
+      /* Empty lines have a valid buffer position at their first
+	 glyph, but that glyph's OBJECT is zero, as if it didn't come
+	 from a buffer.  If we didn't find any valid buffer positions
+	 in this row, maybe we have such an empty line.  */
+      if (min_pos == ZV + 1 && row->used[TEXT_AREA])
+	{
+	  for (g = row->glyphs[TEXT_AREA];
+	       g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
+	       g++)
+	    {
+	      if (INTEGERP (g->object))
+		{
+		  if (g->charpos && g->charpos < min_pos)
+		    min_pos = g->charpos;
+		  if (g->charpos > max_pos)
+		    max_pos = g->charpos;
+		}
+	    }
+	}
+      if (min_pos <= ZV)
+	{
+	  if (min_pos != row->start.pos.charpos)
+	    {
+	      row->start.pos.charpos = min_pos;
+	      row->start.pos.bytepos = CHAR_TO_BYTE (min_pos);
+	    }
+	  if (max_pos == 0)
+	    max_pos = min_pos;
+	}
       /* For ROW->end, we need the position that is _after_ max_pos,
-	 in the logical order.  */
-      SET_TEXT_POS (tpos, max_pos + 1, CHAR_TO_BYTE (max_pos + 1));
-      /* If the character at max_pos+1 is a newline, skip that as
-	 well.  Note that this may skip some invisible text.  */
-      if (FETCH_CHAR (tpos.bytepos) == '\n'
-	  || (FETCH_CHAR (tpos.bytepos) == '\r' && it->selective))
-	{
-	  save_it = *it;
-	  it->bidi_p = 0;
-	  reseat_1 (it, tpos, 0);
-	  set_iterator_to_next (it, 1);
-	  row_end = it->current;
-	  *it = save_it;
-	}
-      else
-	{
-	  row_end = it->current;
-	  row_end.pos = tpos;
-	}
-      row->end = row_end;
+	 in the logical order, unless we are at ZV.  */
+      if (row->ends_at_zv_p)
+	{
+	  row_end = row->end = it->current;
+	  if (!row->used[TEXT_AREA])
+	    {
+	      row->start.pos.charpos = row_end.pos.charpos;
+	      row->start.pos.bytepos = row_end.pos.bytepos;
+	    }
+	}
+      else if (row->used[TEXT_AREA] && max_pos)
+	{
+	  SET_TEXT_POS (tpos, max_pos + 1, CHAR_TO_BYTE (max_pos + 1));
+	  /* If the character at max_pos+1 is a newline, skip that as
+	     well.  Note that this may skip some invisible text.  */
+	  if (FETCH_CHAR (tpos.bytepos) == '\n'
+	      || (FETCH_CHAR (tpos.bytepos) == '\r' && it->selective))
+	    {
+	      save_it = *it;
+	      it->bidi_p = 0;
+	      reseat_1 (it, tpos, 0);
+	      set_iterator_to_next (it, 1);
+	      row_end = it->current;
+	      *it = save_it;
+	    }
+	  else
+	    {
+	      row_end = it->current;
+	      row_end.pos = tpos;
+	    }
+	  row->end = row_end;
+	}
     }
 
   /* Record whether this row ends inside an ellipsis.  */
@@ -17680,8 +17713,11 @@
        /* In bidi-reordered rows, keep checking for proper cursor
 	  position even if one has been found already, because buffer
 	  positions in such rows change non-linearly with ROW->VPOS,
-	  when a line is continued.  */
-       || it->bidi_p)
+	  when a line is continued.  One exception: when we are at ZV,
+	  display cursor on the first suitable glyph row, since all
+	  the empty rows after that also have their ends_at_zv_p flag
+	  set.  */
+       || (it->bidi_p && !row->ends_at_zv_p))
       && PT >= MATRIX_ROW_START_CHARPOS (row)
       && PT <= MATRIX_ROW_END_CHARPOS (row)
       && cursor_row_p (it->w, row))