From e44cbb848fca6988240d472f38f9a1884db79c64 Mon Sep 17 00:00:00 2001 From: Jason Hood Date: Thu, 23 Nov 2017 12:06:33 +1000 Subject: [PATCH] Add `+` to use the buffer Normally the display uses the window height; adding an intermediate character of `+` will use the buffer height. Report cursor position will also output `+R` when used with `+n`. --- ANSI.c | 72 ++++++++++++++++++++++++++++++++------------------- ansicon.c | 2 +- readme.txt | 8 +++--- sequences.txt | 5 +++- 4 files changed, 54 insertions(+), 33 deletions(-) diff --git a/ANSI.c b/ANSI.c index 5b04cb6..3b08d5d 100644 --- a/ANSI.c +++ b/ANSI.c @@ -152,7 +152,7 @@ remove wcstok, avoiding potential interference with the host; similarly, use a private heap instead of malloc. - v1.80, 26 October to 19 November, 2017: + v1.80, 26 October to 23 November, 2017: fix unloading; revert back to (re)storing buffer cursor position; increase cache to five handles; @@ -161,7 +161,8 @@ preserve escape that isn't part of a sequence; fix escape followed by CRM in control mode; use the system default sound for the bell; - add DECPS Play Sound. + add DECPS Play Sound; + use intermediate byte '+' to use buffer, not window. */ #include "ansicon.h" @@ -668,12 +669,15 @@ void InterpretEscSeq( void ) SMALL_RECT Rect; CHAR_INFO CharInfo; DWORD mode; + SHORT top, bottom; #define WIDTH Info.dwSize.X +#define HEIGHT Info.dwSize.Y #define CUR Info.dwCursorPosition #define WIN Info.srWindow #define TOP WIN.Top #define BOTTOM WIN.Bottom +#define LAST (HEIGHT - 1) #define LEFT 0 #define RIGHT (WIDTH - 1) @@ -707,6 +711,16 @@ void InterpretEscSeq( void ) return; GetConsoleScreenBufferInfo( hConOut, &Info ); + if (suffix2 == '+') + { + top = 0; + bottom = LAST; + } + else + { + top = TOP; + bottom = BOTTOM; + } switch (suffix) { case 'm': @@ -829,32 +843,32 @@ void InterpretEscSeq( void ) switch (es_argv[0]) { case 0: // ESC[0J erase from cursor to end of display - len = (BOTTOM - CUR.Y) * WIDTH + WIDTH - CUR.X; + len = (bottom - CUR.Y) * WIDTH + WIDTH - CUR.X; FillBlank( len, CUR ); return; case 1: // ESC[1J erase from start to cursor. - Pos.X = 0; - Pos.Y = TOP; - len = (CUR.Y - TOP) * WIDTH + CUR.X + 1; + Pos.X = LEFT; + Pos.Y = top; + len = (CUR.Y - top) * WIDTH + CUR.X + 1; FillBlank( len, Pos ); return; case 2: // ESC[2J Clear screen and home cursor - if (TOP != screen_top || BOTTOM == Info.dwSize.Y - 1) + if (suffix2 != '+' && (TOP != screen_top || CUR.Y == LAST)) { // Rather than clearing the existing window, make the current // line the new top of the window (assuming this is the first // thing a program does). int range = BOTTOM - TOP; - if (CUR.Y + range < Info.dwSize.Y) + if (CUR.Y + range < HEIGHT) { TOP = CUR.Y; BOTTOM = TOP + range; } else { - BOTTOM = Info.dwSize.Y - 1; + BOTTOM = LAST; TOP = BOTTOM - range; Rect.Left = LEFT; Rect.Right = RIGHT; @@ -867,10 +881,12 @@ void InterpretEscSeq( void ) } SetConsoleWindowInfo( hConOut, TRUE, &WIN ); screen_top = TOP; + top = TOP; + bottom = BOTTOM; } Pos.X = LEFT; - Pos.Y = TOP; - len = (BOTTOM - TOP + 1) * WIDTH; + Pos.Y = top; + len = (bottom - top + 1) * WIDTH; FillBlank( len, Pos ); // Not technically correct, but perhaps expected. SetConsoleCursorPosition( hConOut, Pos ); @@ -918,7 +934,7 @@ void InterpretEscSeq( void ) Rect.Left = WIN.Left = LEFT; Rect.Right = WIN.Right = RIGHT; Rect.Top = CUR.Y; - Rect.Bottom = BOTTOM; + Rect.Bottom = bottom; Pos.X = LEFT; Pos.Y = CUR.Y + es_argv[0]; CharInfo.Char.UnicodeChar = ' '; @@ -932,7 +948,7 @@ void InterpretEscSeq( void ) if (es_argc != 1) return; Rect.Left = WIN.Left = LEFT; Rect.Right = WIN.Right = RIGHT; - Rect.Bottom = BOTTOM; + Rect.Bottom = bottom; Rect.Top = CUR.Y - es_argv[0]; Pos.X = LEFT; Pos.Y = TOP = CUR.Y; @@ -975,7 +991,7 @@ void InterpretEscSeq( void ) if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[A == ESC[1A if (es_argc != 1) return; Pos.Y = CUR.Y - es_argv[0]; - if (Pos.Y < TOP) Pos.Y = TOP; + if (Pos.Y < top) Pos.Y = top; Pos.X = CUR.X; SetConsoleCursorPosition( hConOut, Pos ); return; @@ -985,7 +1001,7 @@ void InterpretEscSeq( void ) if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[B == ESC[1B if (es_argc != 1) return; Pos.Y = CUR.Y + es_argv[0]; - if (Pos.Y > BOTTOM) Pos.Y = BOTTOM; + if (Pos.Y > bottom) Pos.Y = bottom; Pos.X = CUR.X; SetConsoleCursorPosition( hConOut, Pos ); return; @@ -1014,7 +1030,7 @@ void InterpretEscSeq( void ) if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[E == ESC[1E if (es_argc != 1) return; Pos.Y = CUR.Y + es_argv[0]; - if (Pos.Y > BOTTOM) Pos.Y = BOTTOM; + if (Pos.Y > bottom) Pos.Y = bottom; Pos.X = LEFT; SetConsoleCursorPosition( hConOut, Pos ); return; @@ -1023,7 +1039,7 @@ void InterpretEscSeq( void ) if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[F == ESC[1F if (es_argc != 1) return; Pos.Y = CUR.Y - es_argv[0]; - if (Pos.Y < TOP) Pos.Y = TOP; + if (Pos.Y < top) Pos.Y = top; Pos.X = LEFT; SetConsoleCursorPosition( hConOut, Pos ); return; @@ -1042,9 +1058,9 @@ void InterpretEscSeq( void ) case 'd': // ESC[#d Moves cursor row #, current column. if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[d == ESC[1d if (es_argc != 1) return; - Pos.Y = es_argv[0] - 1; - if (Pos.Y < TOP) Pos.Y = TOP; - if (Pos.Y > BOTTOM) Pos.Y = BOTTOM; + Pos.Y = top + es_argv[0] - 1; + if (Pos.Y < top) Pos.Y = top; + if (Pos.Y > bottom) Pos.Y = bottom; SetConsoleCursorPosition( hConOut, Pos ); return; @@ -1058,9 +1074,9 @@ void InterpretEscSeq( void ) Pos.X = es_argv[1] - 1; if (Pos.X < LEFT) Pos.X = LEFT; if (Pos.X > RIGHT) Pos.X = RIGHT; - Pos.Y = es_argv[0] - 1; - if (Pos.Y < TOP) Pos.Y = TOP; - if (Pos.Y > BOTTOM) Pos.Y = BOTTOM; + Pos.Y = top + es_argv[0] - 1; + if (Pos.Y < top) Pos.Y = top; + if (Pos.Y > bottom) Pos.Y = bottom; SetConsoleCursorPosition( hConOut, Pos ); return; @@ -1101,7 +1117,7 @@ void InterpretEscSeq( void ) if (es_argc != 0) return; Pos = pState->SavePos; if (Pos.X > RIGHT) Pos.X = RIGHT; - if (Pos.Y > BOTTOM) Pos.Y = BOTTOM; + if (Pos.Y > bottom) Pos.Y = bottom; SetConsoleCursorPosition( hConOut, Pos ); return; @@ -1116,7 +1132,9 @@ void InterpretEscSeq( void ) case 6: // ESC[6n Report cursor position { TCHAR buf[32]; - wsprintf( buf, L"\33[%d;%dR", CUR.Y - TOP + 1, CUR.X + 1 ); + wsprintf( buf, L"\33[%d;%d%sR", + CUR.Y - top + 1, CUR.X + 1, + (suffix2 == '+') ? L"+" : L"" ); SendSequence( buf ); } return; @@ -1320,7 +1338,7 @@ ParseAndPrintString( HANDLE hDev, { suffix2 = c; } - else if (suffix2 != 0 && suffix2 != ',') + else if (suffix2 != 0 && suffix2 != ',' && suffix2 != '+') { state = 1; } @@ -1353,7 +1371,7 @@ ParseAndPrintString( HANDLE hDev, { suffix2 = c; } - else if (suffix2 != 0 && suffix2 != ',') + else if (suffix2 != 0 && suffix2 != ',' && suffix2 != '+') { state = 1; } diff --git a/ansicon.c b/ansicon.c index a34725c..ff2b1ac 100644 --- a/ansicon.c +++ b/ansicon.c @@ -90,7 +90,7 @@ write newline with _putws, not putwchar (fixes redirecting to CON). */ -#define PDATE L"19 November, 2017" +#define PDATE L"23 November, 2017" #include "ansicon.h" #include "version.h" diff --git a/readme.txt b/readme.txt index a1a82f8..00b4741 100644 --- a/readme.txt +++ b/readme.txt @@ -278,7 +278,6 @@ DEC Special Graphics Character Set Limitations =========== - Line sequences use the window; column sequences use the buffer. Tabs are fixed at eight columns. The saved position will not be restored correctly if the buffer scrolls. @@ -296,7 +295,7 @@ Version History Legend: + added, - bug-fixed, * changed. - 1.80 - 17 November, 2017: + 1.80 - 23 November, 2017: - fix unloading; - fix -e et al when redirecting to CON; - hook CreateFile and CreateConsoleScreenBuffer to force read/write access @@ -306,7 +305,8 @@ Version History * go back to saving the buffer cursor position; * preserve escape that isn't part of a sequence; + use the system default sound for the bell; - + added Play Sound DECPS. + + added Play Sound DECPS; + + added '+' intermediate byte to use the buffer, rather than the window. 1.72 - 24 December, 2015: - handle STD_OUTPUT_HANDLE & STD_ERROR_HANDLE in WriteFile; @@ -535,4 +535,4 @@ Distribution ============================= -Jason Hood, 19 November, 2017. +Jason Hood, 23 November, 2017. diff --git a/sequences.txt b/sequences.txt index 04e5a7e..66b53d4 100644 --- a/sequences.txt +++ b/sequences.txt @@ -3,7 +3,10 @@ Version 1.80 This is a complete list of the ANSI escape sequences recognised by ANSICON, -roughly ordered by function. The initial escape character is assumed. +roughly ordered by function. The initial escape character is assumed. The +display consists of the buffer width and window height; add '+' before the +final character to use the buffer height (e.g. "[2J" will erase the window, +whilst "[2+J" will erase the buffer). [m restore default color (and intensity)