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;
|
||||
BS/CUB/HPB after wrap will move back to the previous line(s);
|
||||
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"
|
||||
@ -213,10 +214,11 @@ struct Cache
|
||||
|
||||
#define MAX_ARG 16 // max number of args in an escape sequence
|
||||
int state; // automata state
|
||||
TCHAR prefix; // escape sequence prefix ( '[', ']' or '(' );
|
||||
TCHAR prefix2; // secondary prefix ( '?' or '>' );
|
||||
TCHAR suffix; // escape sequence suffix
|
||||
TCHAR suffix2; // escape sequence secondary suffix
|
||||
TCHAR prefix; // escape sequence prefix ( '[' or ']' );
|
||||
TCHAR prefix2; // secondary prefix ( one of '<=>?' );
|
||||
TCHAR suffix; // escape sequence final byte
|
||||
TCHAR suffix2; // escape sequence intermediate byte
|
||||
int ibytes; // count of intermediate bytes
|
||||
int es_argc; // escape sequence args count
|
||||
int es_argv[MAX_ARG]; // escape sequence args
|
||||
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
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -981,7 +1033,7 @@ void InterpretEscSeq( void )
|
||||
|
||||
if (prefix == '[')
|
||||
{
|
||||
if (prefix2 == '?')
|
||||
if (prefix2 == '?' && (suffix2 == 0 || suffix2 == '+'))
|
||||
{
|
||||
if (suffix == 'h' || suffix == 'l')
|
||||
{
|
||||
@ -1093,7 +1145,7 @@ void InterpretEscSeq( void )
|
||||
top = TOP;
|
||||
bottom = BOTTOM;
|
||||
}
|
||||
switch (suffix)
|
||||
if (suffix2 == 0 || suffix2 == '+') switch (suffix)
|
||||
{
|
||||
case 'm': // SGR
|
||||
if (es_argc == 0) es_argc++; // ESC[m == ESC[0m
|
||||
@ -1580,82 +1632,78 @@ void InterpretEscSeq( void )
|
||||
}
|
||||
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++)
|
||||
if (suffix2 == '+')
|
||||
if (suffix2 == '+') switch (es_argv[i])
|
||||
{
|
||||
switch (es_argv[i])
|
||||
{
|
||||
case 1: // ACFM
|
||||
pState->fm = TRUE;
|
||||
break;
|
||||
}
|
||||
case 1: // ACFM
|
||||
pState->fm = state;
|
||||
break;
|
||||
}
|
||||
else switch (es_argv[i])
|
||||
{
|
||||
case 3: // CRM
|
||||
pState->crm = TRUE;
|
||||
pState->crm = state;
|
||||
break;
|
||||
|
||||
case 4: // IRM
|
||||
im = TRUE;
|
||||
im = state;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
if (suffix2 == '!') switch (suffix)
|
||||
{
|
||||
case 'p': // DECSTR - ESC[!p Soft reset
|
||||
if (es_argc != 0) return;
|
||||
Reset( FALSE );
|
||||
return;
|
||||
|
||||
case 'l': // RM - ESC[#l Reset Mode
|
||||
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;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
|
||||
case '~':
|
||||
if (suffix2 == ',') // DECPS - ESC[#;#;#...,~ Play Sound
|
||||
{
|
||||
// Frequencies of notes obtained from:
|
||||
// https://pages.mtu.edu/~suits/notefreqs.html
|
||||
// http://www.liutaiomottola.com/formulae/freqtab.htm
|
||||
// This is different to what the VT520 manual has, but since that
|
||||
// only specifies four frequencies, so be it. I've also rounded to
|
||||
// even numbers, as the Beep function seems to stutter on odd.
|
||||
static const DWORD snd_freq[] = { 0,
|
||||
}
|
||||
if (suffix2 == ',') switch (suffix)
|
||||
{
|
||||
case '~': // DECPS - ESC[#;#;#...,~ Play Sound
|
||||
{
|
||||
// Frequencies of notes obtained from:
|
||||
// https://pages.mtu.edu/~suits/notefreqs.html
|
||||
// http://www.liutaiomottola.com/formulae/freqtab.htm
|
||||
// This is different to what the VT520 manual has, but since that
|
||||
// only specifies four frequencies, so be it. I've also rounded to
|
||||
// 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
|
||||
/* 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,
|
||||
/* 7 */ 2094
|
||||
};
|
||||
DWORD dur;
|
||||
if (es_argc < 2) return;
|
||||
dur = es_argv[1];
|
||||
if (dur <= 48) // use 1/32 second
|
||||
dur = 1000 * dur / 32;
|
||||
else if (dur > 8000) // max out at 8 seconds
|
||||
dur = 8000;
|
||||
if (es_argc == 2) // no notes
|
||||
};
|
||||
DWORD dur;
|
||||
if (es_argc < 2) return;
|
||||
dur = es_argv[1];
|
||||
if (dur <= 48) // use 1/32 second
|
||||
dur = 1000 * dur / 32;
|
||||
else if (dur > 8000) // max out at 8 seconds
|
||||
dur = 8000;
|
||||
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 );
|
||||
else for (i = 2; i < es_argc; ++i)
|
||||
{
|
||||
if (es_argv[0] == 0) // zero volume
|
||||
Sleep( dur );
|
||||
else
|
||||
Beep( (es_argv[i] < lenof(snd_freq)) ? snd_freq[es_argv[i]]
|
||||
: es_argv[i], dur );
|
||||
}
|
||||
else
|
||||
Beep( (es_argv[i] < lenof(snd_freq)) ? snd_freq[es_argv[i]]
|
||||
: es_argv[i], dur );
|
||||
}
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
return;
|
||||
@ -1984,6 +2032,7 @@ ParseAndPrintString( HANDLE hDev,
|
||||
if (c == ESC)
|
||||
{
|
||||
suffix2 = 0;
|
||||
ibytes = 0;
|
||||
get_state();
|
||||
state = (pState->crm) ? 7 : 2;
|
||||
}
|
||||
@ -2025,10 +2074,14 @@ ParseAndPrintString( HANDLE hDev,
|
||||
state = 1;
|
||||
}
|
||||
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')
|
||||
shifted = G0_special = TRUE;
|
||||
@ -2091,6 +2144,10 @@ ParseAndPrintString( HANDLE hDev,
|
||||
}
|
||||
state = 1;
|
||||
}
|
||||
else if (c == 'c') // RIS Reset to Initial State
|
||||
{
|
||||
Reset( TRUE );
|
||||
}
|
||||
else if (c == '[' || // CSI Control Sequence Introducer
|
||||
c == ']') // OSC Operating System Command
|
||||
{
|
||||
@ -2134,15 +2191,16 @@ ParseAndPrintString( HANDLE hDev,
|
||||
{
|
||||
// ignore it
|
||||
}
|
||||
else if (c >= '\x3b' && c <= '\x3f')
|
||||
else if (c >= '\x3c' && c <= '\x3f')
|
||||
{
|
||||
prefix2 = c;
|
||||
}
|
||||
else if (c >= '\x20' && c <= '\x2f')
|
||||
{
|
||||
suffix2 = c;
|
||||
++ibytes;
|
||||
}
|
||||
else if (suffix2 != 0 && suffix2 != '+' && (suffix2 != ',' || c != '~'))
|
||||
else if (ibytes > 1)
|
||||
{
|
||||
state = 1;
|
||||
}
|
||||
@ -2175,8 +2233,9 @@ ParseAndPrintString( HANDLE hDev,
|
||||
else if (c >= '\x20' && c <= '\x2f')
|
||||
{
|
||||
suffix2 = c;
|
||||
++ibytes;
|
||||
}
|
||||
else if (suffix2 != 0 && suffix2 != '+' && (suffix2 != ',' || c != '~'))
|
||||
else if (ibytes > 1)
|
||||
{
|
||||
state = 1;
|
||||
}
|
||||
|
@ -91,7 +91,7 @@
|
||||
use -pu to unload from the parent.
|
||||
*/
|
||||
|
||||
#define PDATE L"22 December, 2017"
|
||||
#define PDATE L"23 December, 2017"
|
||||
|
||||
#include "ansicon.h"
|
||||
#include "version.h"
|
||||
|
@ -191,6 +191,7 @@ Sequences Recognised
|
||||
\e[?5W DECST8C Set Tab at Every 8 Columns
|
||||
\e[?5;#W DECST8C Set Tab at Every # Columns (ANSICON extension)
|
||||
\e[#;#r DECSTBM Set Top and Bottom Margins
|
||||
\e[!p DECSTR Soft Terminal Reset
|
||||
\e[?25h DECTCEM Text Cursor Enable Mode (show cursor)
|
||||
\e[?25l DECTCEM Text Cursor Enable Mode (hide cursor)
|
||||
\e[#M DL Delete Line
|
||||
@ -214,6 +215,7 @@ Sequences Recognised
|
||||
\eE NEL Next Line
|
||||
\e[#b REP Repeat
|
||||
\eM RI Reverse Index
|
||||
\ec RIS Reset to Initial State
|
||||
\e(0 SCS Select Character Set (DEC special graphics)
|
||||
\e(B SCS Select Character Set (ASCII)
|
||||
\e[#;#;#m SGR Select Graphic Rendition
|
||||
@ -322,7 +324,7 @@ Version History
|
||||
|
||||
Legend: + added, - bug-fixed, * changed.
|
||||
|
||||
1.80 - 22 December, 2017:
|
||||
1.80 - 23 December, 2017:
|
||||
- fix unloading;
|
||||
- fix -e et al when redirecting to CON;
|
||||
- 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 tab handling (HT, HTS, TBC & DECST8C);
|
||||
+ added IRM;
|
||||
+ added DECOM, DECSTBM, SD & SU.
|
||||
+ added DECOM, DECSTBM, SD & SU;
|
||||
+ added DECSTR & RIS.
|
||||
|
||||
1.72 - 24 December, 2015:
|
||||
- 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
|
||||
[?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)
|
||||
[0c as above
|
||||
[5n sends "\e[0n" to console input
|
||||
|
Loading…
x
Reference in New Issue
Block a user