Subject: bug#14582: 24.3.50.1; Strange overlay behavior, when window-start is inside an overlay.

From: Eli Zaretskii <[email-masked]>
Date: Tue, 01 Feb 2022 20:18:06 +0200

> From: Michael Heerdegen <[email-masked]>
> Cc: [email-masked],  [email-masked],  [email-masked]
> Date: Tue, 01 Feb 2022 04:03:04 +0100
> 
> I think I mean the same.  I guess the original recipe only explicitly
> sets window-start to ensure the recipe reliably works regardless of the
> number of display lines and such things.
> 
> Anyway, this here works for me:
> 
> Open emacs -Q (I'm in X), and evaluate (with M-:) the follow piece of code:
> 
> #+begin_src emacs-lisp
> (progn
>   (dotimes (_ 33) (insert "\
> \(defun foo ()
>   1
>   2)\n"))
>   (goto-char (point-max))
>   (sit-for 1)
>   (scroll-down)
>   (sit-for 1)
>   (hs-minor-mode)
>   (hs-hide-all))
> #+end_src
> 
> That gives me a display of *scratch* where the first visible window line
> displays "...)" instead of expected "(defun xyz nil...)".

Yes, it's basically the same issue.

So please tell me: why do you expect Emacs to move the window-start so
that the window displays starting at "(defun ...)" in the above case?
What would be the trigger for making that change in the window-start
position?

It's a good-faith question.  The display engine doesn't know anything
about the semantics and the intended effect of hiding the bodies of
the functions by putting the invisible property there; in fact, the
display engine doesn't even know what a function's body is, nor where
it begins and ends.  The original window-start position was inside a
function's body, and the call to hs-hide-all causes that position to
be displayed as the ellipsis, that's all.  There's nothing here to
cause the display engine to move window-start.  So it doesn't, because
it, by design, tries not to move the window-start fixed as much as
possible.

Perhaps your mental model of redisplay is that it determines the
window-start position _after_ it applies the various text properties
and overlays, which affect what will be visible on display.  In which
case it would have noticed that after hiding the function bodies the
visual line will start at "(defun ...", and would therefore start the
window's display there.  But that's not how redisplay works: it in
fact first determines where to put window-start, and only after that
redisplays the window using that window-start position.  And if that
causes the window-start position to be covered by some display or
invisible property or some overlay, it's all fine from the POV of the
display engine -- precisely _because_ it isn't any of its business to
understand what those properties and overlays mean and what effect
they want to produce.

hs-minor-mode _does_ know what effect it wants to produce, so it's
hs-minor-mode that needs to adjust window-start if it happens to wind
up in the part of text that is about to be hidden on display.