Subject: Re: bug#11063: Window-start in the middle of a line with nhexl-mode

From: Eli Zaretskii <[email-masked]>
Date: Sat, 31 Mar 2012 20:22:55 +0300

> From: Stefan Monnier <[email-masked]>
> Date: Wed, 21 Mar 2012 23:23:05 -0400
> 
> % src/emacs -Q -l .../elpa/packages/nhexl-mode/nhexl-mode.el README
> M-x nhexl-mode RET
> <page-down>
> 
> You'll see at the top of the screen that the window-start is in the
> middle of one of the (display) lines, even though none of the display
> lines are particularly long.

The following one-liner fixes this.  Whether to install this now is up
to you; after all, nhexl-mode is not part of Emacs, and quite a corner
case at that.  OTOH, the current code is obviously wrong.

Note that there are still display problems after this change: except
when you are at BOB, the first screen line below the liner is almost
always empty (buffer contents is displayed starting from the second
line).  Also, there seem to be a miscalculation of the line width when
some character is displayed using a display table, e.g. where there
are ^L characters in README.  All these were there before the patch,
and I didn't investigate further what causes them.

=== modified file 'src/xdisp.c'
--- a/src/xdisp.c	2012-03-31 17:18:00 +0000
+++ b/src/xdisp.c	2012-03-31 17:18:26 +0000
@@ -8973,7 +8973,20 @@
     {
       move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS);
       if (!IT_POS_VALID_AFTER_MOVE_P (it))
-	move_it_to (it, IT_CHARPOS (*it) + 1, -1, -1, -1, MOVE_TO_POS);
+	{
+	  /* Only move to the next buffer position if we ended up in a
+	     string from display property, not in an overlay string
+	     (before-string or after-string).  That is because the
+	     latter don't conceal the underlying buffer position, so
+	     we can ask to move the iterator to the exact position we
+	     are interested in.  Note that, even if we are already at
+	     IT_CHARPOS (*it), the call below is not a no-op, as it
+	     will detect that we are at the end of the string, pop the
+	     iterator, and compute it->current_x and it->hpos
+	     correctly.  */
+	  move_it_to (it, IT_CHARPOS (*it) + it->string_from_display_prop_p,
+		      -1, -1, -1, MOVE_TO_POS);
+	}
     }
   else
     {