From 997411b6357b90d9c01935091713fdd7884e1395 Mon Sep 17 00:00:00 2001 From: Jonathan de Boyne Pollard Date: Sun, 4 Jun 2017 21:18:44 +0100 Subject: 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. --- src/nvim/tui/tui.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src/nvim') diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index 54893014e9..55ada08663 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -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); } -- cgit