From 36a2d00fb384709383c786b9380cabc92a2584de Mon Sep 17 00:00:00 2001 From: nick black Date: Wed, 5 May 2021 04:49:02 -0400 Subject: [PATCH] ncdirect: move down with raw-mode newlines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The cud capability to move the cursor down doesn't scroll (and shouldn't be used on the last row). We have no reliable knowledge of whether we're on the last row or not, so instead switch to raw mode, emit the newlines, and switch back to whatever mode we were in. This method is due to @dnkl aka Daniel Eklöf, a gentleman and scholar who absolutely knows his shit. Closes #1625. --- src/lib/direct.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/lib/direct.c b/src/lib/direct.c index 08c2cc6ae..f67aca344 100644 --- a/src/lib/direct.c +++ b/src/lib/direct.c @@ -139,7 +139,10 @@ int ncdirect_cursor_right(ncdirect* nc, int num){ return term_emit(tiparm(nc->tcache.cuf, num), nc->ttyfp, false); } -// if we're on the last line, we need some scrolling action. +// if we're on the last line, we need some scrolling action. rather than +// merely using cud, we emit newlines in raw mode. this combination has +// the peculiar property of scrolling when necessary and not performing +// a carriage return -- a pure line feed. int ncdirect_cursor_down(ncdirect* nc, int num){ if(num < 0){ @@ -148,10 +151,26 @@ int ncdirect_cursor_down(ncdirect* nc, int num){ if(num == 0){ return 0; } - if(!nc->tcache.cud){ + struct termios term, raw; + if(tcgetattr(nc->ctermfd, &term)){ return -1; } - return term_emit(tiparm(nc->tcache.cud, num), nc->ttyfp, false); + memcpy(&raw, &term, sizeof(raw)); + cfmakeraw(&raw); + if(tcsetattr(nc->ctermfd, TCSADRAIN, &raw)){ + return -1; + } + int ret = 0; + while(num--){ + if(ncfputc('\n', nc->ttyfp) == EOF){ + ret = -1; + break; + } + } + if(tcsetattr(nc->ctermfd, TCSADRAIN, &term)){ + return -1; + } + return ret; } int ncdirect_clear(ncdirect* nc){