tui: Do not optimize left motion at the right margin.

From observation, there are several different possible behaviours:

1. Deferred wrap like a real DEC VT.  The cursor stays visible in the last
   column, and CUB is calculated relative to that column.
   Examples: xterm, Unicode rxvt, PuTTY, nosh console-terminal-emulator,
   FreeBSD kernel's built-in emulator, Linux's built-in emulator
2. Deferred wrap like a real DEC VT.  CUB is calculated relative to the last
   column.  But the cursor is invisible.
   Examples: emulators using newer libvte
3. Non-deferred wrap.  The cursor has already wrapped to the next line and CUB
   does not wrap back.
   Examples: cygwin, Interix
4. Non-deferred wrap that acts like deferred wrap.  The cursor has already
   visibly wrapped to the next line, but CUB can wrap back around the left
   margin.
   Examples: Konsole
5. Deferred wrap with visibly out of bounds cursor.  The cursor visibly moves
   outwith the screen boundaries.  CUB is calculated relative to a cursor
   column that has overflowed the end of the screen grid array.
   Examples: iTerm2
6. Deferred wrap with invisibly out of bounds cursor.  CUB is calculated
   relative to a cursor column that has overflowed the end of the screen grid
   array.  And the cursor is invisible.
   Examples: emulators using older libvte

In many cases, nvim does not have enough information to know which behaviour
the terminal will exhibit, and thus the correct amount of CUB to issue.
This commit is contained in:
Jonathan de Boyne Pollard 2017-06-04 21:18:44 +01:00
parent 15500dbd8f
commit 997411b635

View File

@ -517,16 +517,19 @@ static void cursor_goto(UI *ui, int row, int col)
}
}
if (row == grid->row) {
if (col < grid->col) {
if (col < grid->col
// Deferred right margin wrap terminals have inconsistent ideas about
// where the cursor actually is during a deferred wrap. Relative
// motion calculations have OBOEs that cannot be compensated for,
// because two terminals that claim to be the same will implement
// different cursor positioning rules.
&& (data->immediate_wrap_after_last_column || grid->col < ui->width)) {
int n = grid->col - col;
if (n <= 4) { // This might be just BS, so it is considered really cheap.
while (n--) {
unibi_out(ui, unibi_cursor_left);
}
} else {
if (!data->immediate_wrap_after_last_column && grid->col >= ui->width) {
n--; // We have calculated one too many columns because of delayed wrap.
}
data->params[0].i = n;
unibi_out(ui, unibi_parm_left_cursor);
}