From 9260451684f7e9d3954cb8d8128f22d5acf8131f Mon Sep 17 00:00:00 2001 From: Jason Hood Date: Tue, 8 May 2018 22:52:52 +1000 Subject: [PATCH] Scroll in new lines using the default attribute When the window or buffer scrolls use the default attribute for the resulting new lines, not the current. Fixes #64. --- ANSI.c | 64 +++++++++++++++++++++++++++++++++++++++++------------- ansicon.c | 2 +- readme.txt | 7 +++--- 3 files changed, 54 insertions(+), 19 deletions(-) diff --git a/ANSI.c b/ANSI.c index 4e54c01..91c5c92 100644 --- a/ANSI.c +++ b/ANSI.c @@ -197,7 +197,7 @@ v1.83, 16 February, 2018: create the flush thread on first use. - v1.84-wip, 17 February, 26 April to 7 May, 2018: + v1.84-wip, 17 February, 26 April to 8 May, 2018: close the flush handles on detach; dynamically load WINMM.DLL; use sprintf/_snprintf/_snwprintf instead of wsprintf, avoiding USER32.DLL; @@ -207,7 +207,8 @@ use remote load on Win8+ when the process has no IAT; remove dependency on the CRT; increase heap to 256KiB to fix logging of really long command lines; - default to 7 or -7 if ANSICON_DEF could not be parsed. + default to 7 or -7 if ANSICON_DEF could not be parsed; + scrolling will use the default attribute for new lines. */ #include "ansicon.h" @@ -670,6 +671,25 @@ void set_pos( int x, int y ) } +// Get the default attribute, as-is if !ATTR (i.e. preserve negative), else for +// the console (swap foreground/background if negative). +int get_default_attr( BOOL attr ) +{ + TCHAR def[4]; + int a; + + *def = '7'; def[1] = '\0'; + GetEnvironmentVariable( L"ANSICON_DEF", def, lenof(def) ); + a = ac_wcstol( def, NULL, 16 ); + if (a == 0) + a = (*def == '-') ? -7 : 7; + if (a > 0 || !attr) + return a; + a = -a; + return ((a >> 4) & 15) | ((a & 15) << 4); +} + + //----------------------------------------------------------------------------- // FlushBuffer() // Writes the buffer to the console and empties it. @@ -835,7 +855,7 @@ void FlushBuffer( void ) CHAR_INFO ci; ci.Char.UnicodeChar = ' '; - ci.Attributes = ATTR; + ci.Attributes = get_default_attr( TRUE ); c.X = sr.Left = LEFT; sr.Right = RIGHT; @@ -860,6 +880,26 @@ void FlushBuffer( void ) cr.Left = CUR.X = wi.CURPOS.X; ScrollConsoleScreenBuffer( hConOut, &sr, &cr, CUR, &ci ); } + else if (nWrapped && CUR.Y + nWrapped > LAST) + { + // The buffer is going to scroll; do it manually in order to use the + // default attribute, not current. + SMALL_RECT sr; + COORD c; + CHAR_INFO ci; + + ci.Char.UnicodeChar = ' '; + ci.Attributes = get_default_attr( TRUE ); + c.X = + sr.Left = LEFT; + sr.Right = RIGHT; + sr.Top = 0; + sr.Bottom = LAST; + c.Y = -wi.CURPOS.Y; + ScrollConsoleScreenBuffer( hConOut, &sr, &sr, c, &ci ); + CUR.Y -= wi.CURPOS.Y; + SetConsoleCursorPos( hConOut, CUR ); + } if (pState->crm) { SetConsoleMode( hConOut, cache[0].mode & ~ENABLE_PROCESSED_OUTPUT ); @@ -1368,13 +1408,7 @@ void InterpretEscSeq( void ) case 39: case 49: { - TCHAR def[4]; - int a; - *def = '7'; def[1] = '\0'; - GetEnvironmentVariable( L"ANSICON_DEF", def, lenof(def) ); - a = ac_wcstol( def, NULL, 16 ); - if (a == 0) - a = (*def == '-') ? -7 : 7; + int a = get_default_attr( FALSE ); pState->sgr.reverse = FALSE; if (a < 0) { @@ -1572,7 +1606,7 @@ void InterpretEscSeq( void ) } Pos.Y = Rect.Top + (suffix == 'T' ? p1 : -p1); CharInfo.Char.UnicodeChar = ' '; - CharInfo.Attributes = ATTR; + CharInfo.Attributes = get_default_attr( TRUE ); ScrollConsoleScreenBuffer( hConOut, &Rect, &Rect, Pos, &CharInfo ); return; @@ -2098,7 +2132,7 @@ void MoveDown( BOOL home ) Pos.X = LEFT; Pos.Y = TOP + pState->top_margin; CharInfo.Char.UnicodeChar = ' '; - CharInfo.Attributes = ATTR; + CharInfo.Attributes = get_default_attr( TRUE ); ScrollConsoleScreenBuffer( hConOut, &Rect, NULL, Pos, &CharInfo ); if (home) { @@ -2122,7 +2156,7 @@ void MoveDown( BOOL home ) Rect.Bottom = LAST; Pos.X = Pos.Y = 0; CharInfo.Char.UnicodeChar = ' '; - CharInfo.Attributes = ATTR; + CharInfo.Attributes = get_default_attr( TRUE ); ScrollConsoleScreenBuffer( hConOut, &Rect, NULL, Pos, &CharInfo ); if (home) { @@ -2155,7 +2189,7 @@ void MoveUp( void ) Pos.X = LEFT; Pos.Y = TOP + pState->top_margin + 1; CharInfo.Char.UnicodeChar = ' '; - CharInfo.Attributes = ATTR; + CharInfo.Attributes = get_default_attr( TRUE ); ScrollConsoleScreenBuffer( hConOut, &Rect, NULL, Pos, &CharInfo ); } else if (pState->tb_margins && CUR.Y == TOP) @@ -2171,7 +2205,7 @@ void MoveUp( void ) Pos.X = LEFT; Pos.Y = 1; CharInfo.Char.UnicodeChar = ' '; - CharInfo.Attributes = ATTR; + CharInfo.Attributes = get_default_attr( TRUE ); ScrollConsoleScreenBuffer( hConOut, &Rect, NULL, Pos, &CharInfo ); } else diff --git a/ansicon.c b/ansicon.c index 03f950d..ba541bb 100644 --- a/ansicon.c +++ b/ansicon.c @@ -94,7 +94,7 @@ import the DLL. */ -#define PDATE L"7 May, 2018" +#define PDATE L"8 May, 2018" #include "ansicon.h" #include "version.h" diff --git a/readme.txt b/readme.txt index bed6158..52f9380 100644 --- a/readme.txt +++ b/readme.txt @@ -339,7 +339,7 @@ Version History Legend: + added, - bug-fixed, * changed. - 1.84-wip - 7 May, 2018: + 1.84-wip - 8 May, 2018: - close the flush handles on detach; - WriteFile wasn't properly testing if its handle was for a console; - use remote load on Win8+ if the process has no IAT; @@ -348,7 +348,8 @@ Version History * remove dependency on CRT & USER32, dynamically load WINMM; * exit process if the primary thread is detached (for processes on Win10 that return, rather than call ExitProcess); - * ansicon.exe statically loads the DLL. + * ansicon.exe statically loads the DLL; + * scrolling will use the default attribute for new lines. 1.83 - 16 February, 2018: - create the flush thread on first use. @@ -624,4 +625,4 @@ Distribution ======================== -Jason Hood, 7 May, 2018. +Jason Hood, 8 May, 2018.