Subject: unwanted scrolling of the terminal
From: Oliver Kiddle <[email-masked]>
To: Zsh workers <[email-masked]>
Date: Thu, 23 Jun 2016 13:58:51 +0200
List-Id: Zsh Workers List <zsh-workers.zsh.org>

I think there may be a bug somewhere in the zle_refresh code which is
resulting in the terminal scrolling up when it shouldn't. This occurs
with urxvt but I think the key thing in that is that $termcap[ic] is
available rather than urxvt itself.

To reproduce it from zsh -f with urxvt, the following setup is needed.
You also need to make sure that the prompt is at the bottom of the
terminal.
zle-keymap-select() {
  zle reset-prompt
}
zle -N zle-keymap-select
zle_highlight=( 'default:fg=black' )
bindkey -v

Then enter: [escape]ox[escape]>k

That will indent the x but it also scrolls giving the impression that an
additional line has been added at the bottom. I would suspect that there
are other ways to trigger the same set of conditions that cause this
and there isn't much that is special about the particular widgets used
here. It is hard to verify with old versions of zsh because vi-indent
was broken before. Note that there is no right prompt and no real need
for zsh to be putting anything near the end of the line.

Looking at the output in a script log for an 84 char width terminal, I get:
  x
  \e[39m  - colour
  \e[K    - clear to eol
  \r
  \e[8@   - insert 8 characters
  \e[34m
  eight spaces
  \e[75C  - cursor right 75 chars
  \e[39m
  two spaces
  \r

So why the two spaces? The second of those is what caused the scrolling.
The first one is printed from line 1958 in zle_refresh.c
The second is from line 2175 in the moveto function

At this point, I'm fairly stuck on how this might be fixed. It isn't at
all clear to me what moveto is doing printing stuff anyway unless it is
to intentionally cause scrolling. zle_refresh.c is mostly fairly good on
comments but that part lacks any. The main substance of that code seems
to have been around as long as the version control but it has also been
changed so maybe someone knows what it is supposed to be doing? Is vcs
zero or one-based indexing of the cursor position. Given the former,
vcs == winw would mean it has already printed something in the final
column.

Oliver