Subject: Re: bug#11484: 23.4; Scrolling leaves traces of old text behind

From: Eli Zaretskii <[email-masked]>
Date: Mon, 22 Oct 2012 19:29:30 +0200

> From: Jan Djärv <[email-masked]>
> Date: Mon, 22 Oct 2012 07:07:33 +0200
> Cc: [email-masked]
> 
> In the file helix.pqr, there are columns of A:s followed by space.  When scrolling fast (or sometimes just going to the end of the buffer), the A:s are replaced with Y:s.  But the spacees following the A:s are not redrawn.  I assume the display engine correctly assumes that from a character view they have not changed and need not be redrawn.  But that extra pixel in A:s lower right corner is in the box for the space.  Redrawing the whole line in this case would also redraw the space.
> 
> That isn't a very good solution now that I think about it, as it would require a redraw of the whole line just to draw the cursor.  A more efficient way would be to include the previous unchanged character and the following unchanged character when redrawing a block of changed characters.

You may wish taking a look at dispnew.c:update_text_area.  This
function is called for every glyph row (= screen line) we may need to
redraw, and it tries to minimize the parts of the line that are
actually redrawn.  I would first try disabling this optimization,
forcing the function to always redraw each line, as it normally does
under the following conditions:

  /* If rows are at different X or Y, or rows have different height,
     or the current row is marked invalid, write the entire line.  */
  if (!current_row->enabled_p
      || desired_row->y != current_row->y
      || desired_row->ascent != current_row->ascent
      || desired_row->phys_ascent != current_row->phys_ascent
      || desired_row->phys_height != current_row->phys_height
      || desired_row->visible_height != current_row->visible_height
      || current_row->overlapped_p
      /* This next line is necessary for correctly redrawing
	 mouse-face areas after scrolling and other operations.
	 However, it causes excessive flickering when mouse is moved
	 across the mode line.  Luckily, turning it off for the mode
	 line doesn't seem to hurt anything. -- cyd.
         But it is still needed for the header line. -- kfs.  */
      || (current_row->mouse_face_p
	  && !(current_row->mode_line_p && vpos > 0))
      || current_row->x != desired_row->x)
    {
      rif->cursor_to (vpos, 0, desired_row->y, desired_row->x);

      if (desired_row->used[TEXT_AREA])
	rif->write_glyphs (desired_row->glyphs[TEXT_AREA],
			   desired_row->used[TEXT_AREA]);

If this indeed shows you are on the right track, try changing the
'else' branch of this 'if' so that it redraws a larger part of the
line, as needed in this case.  There's already some logic there
towards this end, which has to do with glyph overlaps, so maybe just a
small change to that will fix this case.

Or maybe NS needs some change in xdisp.c:x_get_glyph_overhangs, which
is what update_text_area calls to determine whether a glyph overlaps
its neighbor.

HTH