diff --git a/ANSI.c b/ANSI.c index f4217df..1d4a836 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 3 December, 2017: + v1.80, 26 October to 9 December, 2017: fix unloading; revert back to (re)storing buffer cursor position; increase cache to five handles; @@ -166,7 +166,8 @@ ESC followed by a control character will display that character; added palette sequences; change the scan lines in the graphics set to their actual Unicode chars; - added IND, NEL & RI (using buffer, in keeping with LF). + added IND, NEL & RI (using buffer, in keeping with LF); + added DA, DECCOLM, DECNCSM, DECSC & DECRC. */ #include "ansicon.h" @@ -343,6 +344,9 @@ typedef struct BYTE crm; // showing control characters? COORD SavePos; // saved cursor position COLORREF palette[16]; + SHORT buf_width; // buffer width prior to setting 132 columns + SHORT win_width; // window width prior to setting 132 columns + BYTE noclear; // don't clear the screen on column mode change } STATE, *PSTATE; PSTATE pState; @@ -762,6 +766,61 @@ void InterpretEscSeq( void ) mode &= ~ENABLE_WRAP_AT_EOL_OUTPUT; SetConsoleMode( hConOut, mode ); return; + + case 95: + pState->noclear = (suffix == 'h'); + return; + + case 3: + { + COORD buf; + SMALL_RECT win; + buf.X = (suffix == 'l') ? pState->buf_width : 132; + if (buf.X == 0) + return; + GetConsoleScreenBufferInfo( hConOut, &Info ); + buf.Y = HEIGHT; + win.Left = 0; + win.Top = TOP; + win.Bottom = BOTTOM; + if (suffix == 'h') + { + pState->buf_width = WIDTH; + pState->win_width = WIN.Right - WIN.Left; + win.Right = 131; + } + else + { + win.Right = pState->win_width; + pState->buf_width = 0; + } + // The buffer cannot be smaller than the window; the window cannot + // be bigger than the buffer. + if (WIN.Right - WIN.Left > win.Right) + { + SetConsoleWindowInfo( hConOut, TRUE, &win ); + SetConsoleScreenBufferSize( hConOut, buf ); + } + else + { + SetConsoleScreenBufferSize( hConOut, buf ); + SetConsoleWindowInfo( hConOut, TRUE, &win ); + } + // Even if the screen is not cleared, scroll in a new window the + // first time this is used. + if (pState->noclear && + (suffix2 == '+' || (TOP == screen_top && CUR.Y != LAST))) + { + CUR.X = LEFT; + CUR.Y = (suffix2 == '+') ? 0 : TOP; + SetConsoleCursorPosition( hConOut, CUR ); + return; + } + prefix2 = 0; + es_argv[0] = 2; + suffix = 'J'; + break; + } } } // Ignore any other private sequences. @@ -1175,10 +1234,16 @@ 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 > LAST) Pos.Y = LAST; SetConsoleCursorPosition( hConOut, Pos ); return; + case 'c': // ESC[#c Device attributes + if (es_argc == 0) es_argv[es_argc++] = 0; // ESC[c == ESC[0c + if (es_argc != 1 || es_argv[0] != 0) return; + SendSequence( L"\33[?62;1c" ); // VT220 with 132 columns + return; + case 'n': // ESC[#n Device status report if (es_argc != 1) return; // ESC[n == ESC[0n -> ignored switch (es_argv[0]) @@ -1564,6 +1629,17 @@ ParseAndPrintString( HANDLE hDev, ScrollUp(); state = 1; } + else if (c == '7' || // DECSC Save Cursor + c == '8') // DECRC Restore Cursor + { + es_argc = 0; + prefix = '['; + prefix2 = 0; + suffix = (c == '7') ? 's' : 'u'; + FlushBuffer(); + InterpretEscSeq(); + state = 1; + } else if (c == '[' || // CSI Control Sequence Introducer c == ']') // OSC Operating System Command { diff --git a/ansicon.c b/ansicon.c index 4871428..fa74051 100644 --- a/ansicon.c +++ b/ansicon.c @@ -91,7 +91,7 @@ use -pu to unload from the parent. */ -#define PDATE L"3 December, 2017" +#define PDATE L"9 December, 2017" #include "ansicon.h" #include "version.h" diff --git a/readme.txt b/readme.txt index 6b061e0..26cf4bf 100644 --- a/readme.txt +++ b/readme.txt @@ -172,10 +172,17 @@ Sequences Recognised \e[#C CUF Cursor Right \e[#;#H CUP Cursor Position \e[#A CUU Cursor Up + \e[c DA Device Attributes \e[#P DCH Delete Character \e[?7h DECAWM DEC Autowrap Mode (autowrap) \e[?7l DECAWM DEC Autowrap Mode (no autowrap) + \e[?3h DECCOLM DEC Selecting 80 or 132 Columns per Page (132) + \e[?3l DECCOLM DEC Selecting 80 or 132 Columns per Page (prior) + \e[?3h DECNCSM DEC No Clearing Screen On Column Change Mode (keep) + \e[?3l DECNCSM DEC No Clearing Screen On Column Change Mode (clear) \e[#;#;#...,~ DECPS DEC Play Sound + \e8 DECRC DEC Restore Cursor + \e7 DECSC DEC Save Cursor \e[?25h DECTCEM DEC Text Cursor Enable Mode (show cursor) \e[?25l DECTCEM DEC Text Cursor Enable Mode (hide cursor) \e[#M DL Delete Line @@ -307,7 +314,7 @@ Version History Legend: + added, - bug-fixed, * changed. - 1.80 - 3 December, 2017: + 1.80 - 9 December, 2017: - fix unloading; - fix -e et al when redirecting to CON; - hook CreateFile and CreateConsoleScreenBuffer to force read/write access @@ -323,7 +330,7 @@ Version History + added '+' intermediate byte to use the buffer, rather than the window; + added palette sequences; + added -pu to unload from the parent; - + added IND, NEL and RI. + + added IND, NEL, RI, DA, DECCOLM, DECNCSM, DECSC & DECRC. 1.72 - 24 December, 2015: - handle STD_OUTPUT_HANDLE & STD_ERROR_HANDLE in WriteFile; @@ -552,4 +559,4 @@ Distribution ============================ -Jason Hood, 3 December, 2017. +Jason Hood, 9 December, 2017. diff --git a/sequences.txt b/sequences.txt index 4c94b72..b24dce4 100644 --- a/sequences.txt +++ b/sequences.txt @@ -120,16 +120,24 @@ M move cursor up one line (scroll if necessary; always uses buffer) [#;#f move cursor to line #, column # [s save cursor position +7 as above [u move cursor to saved position (or top-left, if nothing was saved) +8 as above [3h display control characters (LF is also performed) [3l perform control functions (the only such recognised during above) +[?3h set 132 columns +[?3l restore original columns [?7h wrap lines at screen edge [?7l don't wrap lines at screen edge [?25h show cursor [?25l hide cursor +[?95h don't clear screen when changing columns +[?95l clear screen when changing columns -[5n sends "\e[0n" to console input (where \e is escape) +[c sends "\e[?62;1c" to console input (where \e is escape) +[0c as above +[5n sends "\e[0n" to console input [6n sends "\e[#;#R" (line & column) to console input [21t sends "\e]lTitle\e\" (the console's window title) to console input ]0;TitleST