Add DECSTR and RIS
Implement soft and hard resets (handling intermediate bytes a little better in the process).
This commit is contained in:
parent
c28b3597dd
commit
a37657ac52
197
ANSI.c
197
ANSI.c
@ -176,7 +176,8 @@
|
|||||||
added insert mode;
|
added insert mode;
|
||||||
BS/CUB/HPB after wrap will move back to the previous line(s);
|
BS/CUB/HPB after wrap will move back to the previous line(s);
|
||||||
added DECOM, DECSTBM, SD & SU;
|
added DECOM, DECSTBM, SD & SU;
|
||||||
only flush before accessing the console, adding a mode to flush immediately.
|
only flush before accessing the console, adding a mode to flush immediately;
|
||||||
|
added DECSTR & RIS.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ansicon.h"
|
#include "ansicon.h"
|
||||||
@ -213,10 +214,11 @@ struct Cache
|
|||||||
|
|
||||||
#define MAX_ARG 16 // max number of args in an escape sequence
|
#define MAX_ARG 16 // max number of args in an escape sequence
|
||||||
int state; // automata state
|
int state; // automata state
|
||||||
TCHAR prefix; // escape sequence prefix ( '[', ']' or '(' );
|
TCHAR prefix; // escape sequence prefix ( '[' or ']' );
|
||||||
TCHAR prefix2; // secondary prefix ( '?' or '>' );
|
TCHAR prefix2; // secondary prefix ( one of '<=>?' );
|
||||||
TCHAR suffix; // escape sequence suffix
|
TCHAR suffix; // escape sequence final byte
|
||||||
TCHAR suffix2; // escape sequence secondary suffix
|
TCHAR suffix2; // escape sequence intermediate byte
|
||||||
|
int ibytes; // count of intermediate bytes
|
||||||
int es_argc; // escape sequence args count
|
int es_argc; // escape sequence args count
|
||||||
int es_argv[MAX_ARG]; // escape sequence args
|
int es_argv[MAX_ARG]; // escape sequence args
|
||||||
TCHAR Pt_arg[MAX_PATH*2]; // text parameter for Operating System Command
|
TCHAR Pt_arg[MAX_PATH*2]; // text parameter for Operating System Command
|
||||||
@ -945,6 +947,56 @@ void init_tabs( int size )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ========== Reset
|
||||||
|
|
||||||
|
void InterpretEscSeq( void );
|
||||||
|
|
||||||
|
void Reset( BOOL hard )
|
||||||
|
{
|
||||||
|
CONSOLE_CURSOR_INFO CursInfo;
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFOX csbix;
|
||||||
|
|
||||||
|
GetConsoleCursorInfo( hConOut, &CursInfo );
|
||||||
|
CursInfo.bVisible = TRUE;
|
||||||
|
SetConsoleCursorInfo( hConOut, &CursInfo );
|
||||||
|
im =
|
||||||
|
om =
|
||||||
|
tb_margins =
|
||||||
|
pState->crm = FALSE;
|
||||||
|
awm = TRUE;
|
||||||
|
SetConsoleMode( hConOut, cache[0].mode | ENABLE_WRAP_AT_EOL_OUTPUT );
|
||||||
|
shifted = G0_special = SaveG0 = FALSE;
|
||||||
|
pState->SavePos.X = pState->SavePos.Y = 0;
|
||||||
|
pState->SaveAttr = 0;
|
||||||
|
es_argv[0] = es_argc = 0;
|
||||||
|
prefix = '[';
|
||||||
|
prefix2 = suffix2 = 0;
|
||||||
|
suffix = 'm';
|
||||||
|
InterpretEscSeq();
|
||||||
|
|
||||||
|
if (hard)
|
||||||
|
{
|
||||||
|
pState->tabs =
|
||||||
|
pState->noclear = FALSE;
|
||||||
|
prefix2 = '?';
|
||||||
|
es_argv[0] = 3; es_argc = 1;
|
||||||
|
suffix2 = '+';
|
||||||
|
suffix = 'l';
|
||||||
|
InterpretEscSeq();
|
||||||
|
screen_top = -1;
|
||||||
|
csbix.cbSize = sizeof(csbix);
|
||||||
|
if (GetConsoleScreenBufferInfoX &&
|
||||||
|
GetConsoleScreenBufferInfoX( hConOut, &csbix ))
|
||||||
|
{
|
||||||
|
memcpy( csbix.ColorTable, pState->palette, sizeof(csbix.ColorTable) );
|
||||||
|
++csbix.srWindow.Right;
|
||||||
|
++csbix.srWindow.Bottom;
|
||||||
|
SetConsoleScreenBufferInfoX( hConOut, &csbix );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ========== Print functions
|
// ========== Print functions
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -981,7 +1033,7 @@ void InterpretEscSeq( void )
|
|||||||
|
|
||||||
if (prefix == '[')
|
if (prefix == '[')
|
||||||
{
|
{
|
||||||
if (prefix2 == '?')
|
if (prefix2 == '?' && (suffix2 == 0 || suffix2 == '+'))
|
||||||
{
|
{
|
||||||
if (suffix == 'h' || suffix == 'l')
|
if (suffix == 'h' || suffix == 'l')
|
||||||
{
|
{
|
||||||
@ -1093,7 +1145,7 @@ void InterpretEscSeq( void )
|
|||||||
top = TOP;
|
top = TOP;
|
||||||
bottom = BOTTOM;
|
bottom = BOTTOM;
|
||||||
}
|
}
|
||||||
switch (suffix)
|
if (suffix2 == 0 || suffix2 == '+') switch (suffix)
|
||||||
{
|
{
|
||||||
case 'm': // SGR
|
case 'm': // SGR
|
||||||
if (es_argc == 0) es_argc++; // ESC[m == ESC[0m
|
if (es_argc == 0) es_argc++; // ESC[m == ESC[0m
|
||||||
@ -1580,82 +1632,78 @@ void InterpretEscSeq( void )
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 'h': // SM - ESC[#h Set Mode
|
case 'h': // SM - ESC[#...h Set Mode
|
||||||
|
case 'l': // RM - ESC[#...l Reset Mode
|
||||||
|
{
|
||||||
|
BOOL state = (suffix == 'h');
|
||||||
for (i = 0; i < es_argc; i++)
|
for (i = 0; i < es_argc; i++)
|
||||||
if (suffix2 == '+')
|
if (suffix2 == '+') switch (es_argv[i])
|
||||||
{
|
{
|
||||||
switch (es_argv[i])
|
case 1: // ACFM
|
||||||
{
|
pState->fm = state;
|
||||||
case 1: // ACFM
|
break;
|
||||||
pState->fm = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else switch (es_argv[i])
|
else switch (es_argv[i])
|
||||||
{
|
{
|
||||||
case 3: // CRM
|
case 3: // CRM
|
||||||
pState->crm = TRUE;
|
pState->crm = state;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4: // IRM
|
case 4: // IRM
|
||||||
im = TRUE;
|
im = state;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (suffix2 == '!') switch (suffix)
|
||||||
|
{
|
||||||
|
case 'p': // DECSTR - ESC[!p Soft reset
|
||||||
|
if (es_argc != 0) return;
|
||||||
|
Reset( FALSE );
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 'l': // RM - ESC[#l Reset Mode
|
default:
|
||||||
for (i = 0; i < es_argc; i++)
|
|
||||||
if (suffix2 == '+')
|
|
||||||
{
|
|
||||||
switch (es_argv[i])
|
|
||||||
{
|
|
||||||
case 1: // ACFM
|
|
||||||
pState->fm = FALSE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else switch (es_argv[i]) // CRM - ESC[3l is handled during parsing
|
|
||||||
{
|
|
||||||
case 4: // IRM
|
|
||||||
im = FALSE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
case '~':
|
if (suffix2 == ',') switch (suffix)
|
||||||
if (suffix2 == ',') // DECPS - ESC[#;#;#...,~ Play Sound
|
{
|
||||||
{
|
case '~': // DECPS - ESC[#;#;#...,~ Play Sound
|
||||||
// Frequencies of notes obtained from:
|
{
|
||||||
// https://pages.mtu.edu/~suits/notefreqs.html
|
// Frequencies of notes obtained from:
|
||||||
// http://www.liutaiomottola.com/formulae/freqtab.htm
|
// https://pages.mtu.edu/~suits/notefreqs.html
|
||||||
// This is different to what the VT520 manual has, but since that
|
// http://www.liutaiomottola.com/formulae/freqtab.htm
|
||||||
// only specifies four frequencies, so be it. I've also rounded to
|
// This is different to what the VT520 manual has, but since that
|
||||||
// even numbers, as the Beep function seems to stutter on odd.
|
// only specifies four frequencies, so be it. I've also rounded to
|
||||||
static const DWORD snd_freq[] = { 0,
|
// even numbers, as the Beep function seems to stutter on odd.
|
||||||
|
static const DWORD snd_freq[] = { 0,
|
||||||
// C C#/Db D D#/Eb E F F#/Gb G G#/Ab A A#/Bb B
|
// C C#/Db D D#/Eb E F F#/Gb G G#/Ab A A#/Bb B
|
||||||
/* 5 */ 524, 554, 588, 622, 660, 698, 740, 784, 830, 880, 932, 988,
|
/* 5 */ 524, 554, 588, 622, 660, 698, 740, 784, 830, 880, 932, 988,
|
||||||
/* 6 */ 1046, 1108, 1174, 1244, 1318, 1396, 1480, 1568, 1662, 1760, 1864, 1976,
|
/* 6 */ 1046, 1108, 1174, 1244, 1318, 1396, 1480, 1568, 1662, 1760, 1864, 1976,
|
||||||
/* 7 */ 2094
|
/* 7 */ 2094
|
||||||
};
|
};
|
||||||
DWORD dur;
|
DWORD dur;
|
||||||
if (es_argc < 2) return;
|
if (es_argc < 2) return;
|
||||||
dur = es_argv[1];
|
dur = es_argv[1];
|
||||||
if (dur <= 48) // use 1/32 second
|
if (dur <= 48) // use 1/32 second
|
||||||
dur = 1000 * dur / 32;
|
dur = 1000 * dur / 32;
|
||||||
else if (dur > 8000) // max out at 8 seconds
|
else if (dur > 8000) // max out at 8 seconds
|
||||||
dur = 8000;
|
dur = 8000;
|
||||||
if (es_argc == 2) // no notes
|
if (es_argc == 2) // no notes
|
||||||
|
Sleep( dur );
|
||||||
|
else for (i = 2; i < es_argc; ++i)
|
||||||
|
{
|
||||||
|
if (es_argv[0] == 0) // zero volume
|
||||||
Sleep( dur );
|
Sleep( dur );
|
||||||
else for (i = 2; i < es_argc; ++i)
|
else
|
||||||
{
|
Beep( (es_argv[i] < lenof(snd_freq)) ? snd_freq[es_argv[i]]
|
||||||
if (es_argv[0] == 0) // zero volume
|
: es_argv[i], dur );
|
||||||
Sleep( dur );
|
|
||||||
else
|
|
||||||
Beep( (es_argv[i] < lenof(snd_freq)) ? snd_freq[es_argv[i]]
|
|
||||||
: es_argv[i], dur );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
@ -1984,6 +2032,7 @@ ParseAndPrintString( HANDLE hDev,
|
|||||||
if (c == ESC)
|
if (c == ESC)
|
||||||
{
|
{
|
||||||
suffix2 = 0;
|
suffix2 = 0;
|
||||||
|
ibytes = 0;
|
||||||
get_state();
|
get_state();
|
||||||
state = (pState->crm) ? 7 : 2;
|
state = (pState->crm) ? 7 : 2;
|
||||||
}
|
}
|
||||||
@ -2025,10 +2074,14 @@ ParseAndPrintString( HANDLE hDev,
|
|||||||
state = 1;
|
state = 1;
|
||||||
}
|
}
|
||||||
else if (c >= '\x20' && c <= '\x2f')
|
else if (c >= '\x20' && c <= '\x2f')
|
||||||
suffix2 = c;
|
|
||||||
else if (suffix2 != 0)
|
|
||||||
{
|
{
|
||||||
if (suffix2 == '(') // SCS - Designate G0 character set
|
suffix2 = c;
|
||||||
|
++ibytes;
|
||||||
|
}
|
||||||
|
else if (ibytes != 0)
|
||||||
|
{
|
||||||
|
if (ibytes == 1 &&
|
||||||
|
suffix2 == '(') // SCS - Designate G0 character set
|
||||||
{
|
{
|
||||||
if (c == '0')
|
if (c == '0')
|
||||||
shifted = G0_special = TRUE;
|
shifted = G0_special = TRUE;
|
||||||
@ -2091,6 +2144,10 @@ ParseAndPrintString( HANDLE hDev,
|
|||||||
}
|
}
|
||||||
state = 1;
|
state = 1;
|
||||||
}
|
}
|
||||||
|
else if (c == 'c') // RIS Reset to Initial State
|
||||||
|
{
|
||||||
|
Reset( TRUE );
|
||||||
|
}
|
||||||
else if (c == '[' || // CSI Control Sequence Introducer
|
else if (c == '[' || // CSI Control Sequence Introducer
|
||||||
c == ']') // OSC Operating System Command
|
c == ']') // OSC Operating System Command
|
||||||
{
|
{
|
||||||
@ -2134,15 +2191,16 @@ ParseAndPrintString( HANDLE hDev,
|
|||||||
{
|
{
|
||||||
// ignore it
|
// ignore it
|
||||||
}
|
}
|
||||||
else if (c >= '\x3b' && c <= '\x3f')
|
else if (c >= '\x3c' && c <= '\x3f')
|
||||||
{
|
{
|
||||||
prefix2 = c;
|
prefix2 = c;
|
||||||
}
|
}
|
||||||
else if (c >= '\x20' && c <= '\x2f')
|
else if (c >= '\x20' && c <= '\x2f')
|
||||||
{
|
{
|
||||||
suffix2 = c;
|
suffix2 = c;
|
||||||
|
++ibytes;
|
||||||
}
|
}
|
||||||
else if (suffix2 != 0 && suffix2 != '+' && (suffix2 != ',' || c != '~'))
|
else if (ibytes > 1)
|
||||||
{
|
{
|
||||||
state = 1;
|
state = 1;
|
||||||
}
|
}
|
||||||
@ -2175,8 +2233,9 @@ ParseAndPrintString( HANDLE hDev,
|
|||||||
else if (c >= '\x20' && c <= '\x2f')
|
else if (c >= '\x20' && c <= '\x2f')
|
||||||
{
|
{
|
||||||
suffix2 = c;
|
suffix2 = c;
|
||||||
|
++ibytes;
|
||||||
}
|
}
|
||||||
else if (suffix2 != 0 && suffix2 != '+' && (suffix2 != ',' || c != '~'))
|
else if (ibytes > 1)
|
||||||
{
|
{
|
||||||
state = 1;
|
state = 1;
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@
|
|||||||
use -pu to unload from the parent.
|
use -pu to unload from the parent.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PDATE L"22 December, 2017"
|
#define PDATE L"23 December, 2017"
|
||||||
|
|
||||||
#include "ansicon.h"
|
#include "ansicon.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
@ -191,6 +191,7 @@ Sequences Recognised
|
|||||||
\e[?5W DECST8C Set Tab at Every 8 Columns
|
\e[?5W DECST8C Set Tab at Every 8 Columns
|
||||||
\e[?5;#W DECST8C Set Tab at Every # Columns (ANSICON extension)
|
\e[?5;#W DECST8C Set Tab at Every # Columns (ANSICON extension)
|
||||||
\e[#;#r DECSTBM Set Top and Bottom Margins
|
\e[#;#r DECSTBM Set Top and Bottom Margins
|
||||||
|
\e[!p DECSTR Soft Terminal Reset
|
||||||
\e[?25h DECTCEM Text Cursor Enable Mode (show cursor)
|
\e[?25h DECTCEM Text Cursor Enable Mode (show cursor)
|
||||||
\e[?25l DECTCEM Text Cursor Enable Mode (hide cursor)
|
\e[?25l DECTCEM Text Cursor Enable Mode (hide cursor)
|
||||||
\e[#M DL Delete Line
|
\e[#M DL Delete Line
|
||||||
@ -214,6 +215,7 @@ Sequences Recognised
|
|||||||
\eE NEL Next Line
|
\eE NEL Next Line
|
||||||
\e[#b REP Repeat
|
\e[#b REP Repeat
|
||||||
\eM RI Reverse Index
|
\eM RI Reverse Index
|
||||||
|
\ec RIS Reset to Initial State
|
||||||
\e(0 SCS Select Character Set (DEC special graphics)
|
\e(0 SCS Select Character Set (DEC special graphics)
|
||||||
\e(B SCS Select Character Set (ASCII)
|
\e(B SCS Select Character Set (ASCII)
|
||||||
\e[#;#;#m SGR Select Graphic Rendition
|
\e[#;#;#m SGR Select Graphic Rendition
|
||||||
@ -322,7 +324,7 @@ Version History
|
|||||||
|
|
||||||
Legend: + added, - bug-fixed, * changed.
|
Legend: + added, - bug-fixed, * changed.
|
||||||
|
|
||||||
1.80 - 22 December, 2017:
|
1.80 - 23 December, 2017:
|
||||||
- fix unloading;
|
- fix unloading;
|
||||||
- fix -e et al when redirecting to CON;
|
- fix -e et al when redirecting to CON;
|
||||||
- hook CreateFile and CreateConsoleScreenBuffer to force read/write access
|
- hook CreateFile and CreateConsoleScreenBuffer to force read/write access
|
||||||
@ -349,7 +351,8 @@ Version History
|
|||||||
+ added SCS, but only for special/ASCII (same as Win10);
|
+ added SCS, but only for special/ASCII (same as Win10);
|
||||||
+ added tab handling (HT, HTS, TBC & DECST8C);
|
+ added tab handling (HT, HTS, TBC & DECST8C);
|
||||||
+ added IRM;
|
+ added IRM;
|
||||||
+ added DECOM, DECSTBM, SD & SU.
|
+ added DECOM, DECSTBM, SD & SU;
|
||||||
|
+ added DECSTR & RIS.
|
||||||
|
|
||||||
1.72 - 24 December, 2015:
|
1.72 - 24 December, 2015:
|
||||||
- handle STD_OUTPUT_HANDLE & STD_ERROR_HANDLE in WriteFile;
|
- handle STD_OUTPUT_HANDLE & STD_ERROR_HANDLE in WriteFile;
|
||||||
@ -578,4 +581,4 @@ Distribution
|
|||||||
|
|
||||||
|
|
||||||
==============================
|
==============================
|
||||||
Jason Hood, 22 December, 2017.
|
Jason Hood, 23 December, 2017.
|
||||||
|
@ -182,6 +182,25 @@ H set tab stop
|
|||||||
[?95h don't clear screen when changing columns
|
[?95h don't clear screen when changing columns
|
||||||
[?95l clear screen when changing columns
|
[?95l clear screen when changing columns
|
||||||
|
|
||||||
|
[!p soft reset:
|
||||||
|
show cursor
|
||||||
|
perform control functions
|
||||||
|
replace characters
|
||||||
|
set origin to top line
|
||||||
|
wrap lines at screen edge
|
||||||
|
select ASCII
|
||||||
|
remove margins
|
||||||
|
default SGR
|
||||||
|
set the saved cursor to the top-left
|
||||||
|
c hard reset:
|
||||||
|
as above
|
||||||
|
restore console tab handling
|
||||||
|
restore the entire palette
|
||||||
|
restore original columns
|
||||||
|
clear screen when changing columns
|
||||||
|
clear the buffer
|
||||||
|
home the cursor
|
||||||
|
|
||||||
[c sends "\e[?62;1c" to console input (where \e is escape)
|
[c sends "\e[?62;1c" to console input (where \e is escape)
|
||||||
[0c as above
|
[0c as above
|
||||||
[5n sends "\e[0n" to console input
|
[5n sends "\e[0n" to console input
|
||||||
|
Loading…
x
Reference in New Issue
Block a user