Add tab handling
Support setting (HTS & DECST8C) and clearing (TBC) tabs, overriding the console's own tab processing. I've extended TBC with `\e[8g` to restore console processing and added an extra parameter to DECST8C to set a particular tab size.
This commit is contained in:
parent
645f57e59c
commit
d20ab7471f
90
ANSI.c
90
ANSI.c
@ -169,7 +169,8 @@
|
|||||||
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;
|
added DA, DECCOLM, DECNCSM, DECSC & DECRC;
|
||||||
an explicit zero parameter should still default to one;
|
an explicit zero parameter should still default to one;
|
||||||
restrict parameters to a maximum value of 32767.
|
restrict parameters to a maximum value of 32767;
|
||||||
|
added tab handling.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ansicon.h"
|
#include "ansicon.h"
|
||||||
@ -199,7 +200,8 @@ struct Cache
|
|||||||
} cache[CACHE];
|
} cache[CACHE];
|
||||||
|
|
||||||
#define ESC '\x1B' // ESCape character
|
#define ESC '\x1B' // ESCape character
|
||||||
#define BEL '\x07'
|
#define BEL '\x07' // BELl
|
||||||
|
#define HT '\x09' // Horizontal Tabulation
|
||||||
#define SO '\x0E' // Shift Out
|
#define SO '\x0E' // Shift Out
|
||||||
#define SI '\x0F' // Shift In
|
#define SI '\x0F' // Shift In
|
||||||
|
|
||||||
@ -334,6 +336,8 @@ typedef BOOL (WINAPI *PHCSBIX)(
|
|||||||
PHCSBIX GetConsoleScreenBufferInfoX, SetConsoleScreenBufferInfoX;
|
PHCSBIX GetConsoleScreenBufferInfoX, SetConsoleScreenBufferInfoX;
|
||||||
|
|
||||||
|
|
||||||
|
#define MAX_TABS 2048
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
BYTE foreground; // ANSI base color (0 to 7; add 30)
|
BYTE foreground; // ANSI base color (0 to 7; add 30)
|
||||||
@ -349,6 +353,8 @@ typedef struct
|
|||||||
SHORT buf_width; // buffer width prior to setting 132 columns
|
SHORT buf_width; // buffer width prior to setting 132 columns
|
||||||
SHORT win_width; // window 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
|
BYTE noclear; // don't clear the screen on column mode change
|
||||||
|
BYTE tabs; // handle tabs directly
|
||||||
|
BYTE tab_stop[MAX_TABS];
|
||||||
} STATE, *PSTATE;
|
} STATE, *PSTATE;
|
||||||
|
|
||||||
PSTATE pState;
|
PSTATE pState;
|
||||||
@ -704,6 +710,19 @@ void send_palette_sequence( COLORREF c )
|
|||||||
SendSequence( buf );
|
SendSequence( buf );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Clear existing tabs and set tab stops at every size columns.
|
||||||
|
void init_tabs( int size )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
memset( pState->tab_stop, FALSE, MAX_TABS );
|
||||||
|
for (i = 0; i < MAX_TABS; i += size)
|
||||||
|
pState->tab_stop[i] = TRUE;
|
||||||
|
pState->tabs = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ========== Print functions
|
// ========== Print functions
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -751,8 +770,11 @@ void InterpretEscSeq( void )
|
|||||||
|
|
||||||
if (prefix == '[')
|
if (prefix == '[')
|
||||||
{
|
{
|
||||||
if (prefix2 == '?' && (suffix == 'h' || suffix == 'l') && es_argc == 1)
|
if (prefix2 == '?')
|
||||||
{
|
{
|
||||||
|
if (suffix == 'h' || suffix == 'l')
|
||||||
|
{
|
||||||
|
if (es_argc != 1) return;
|
||||||
switch (es_argv[0])
|
switch (es_argv[0])
|
||||||
{
|
{
|
||||||
case 25:
|
case 25:
|
||||||
@ -826,6 +848,14 @@ void InterpretEscSeq( void )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (suffix == 'W')
|
||||||
|
{
|
||||||
|
if (es_argv[0] != 5 || es_argc > 2) return;
|
||||||
|
if (es_argc == 1) es_argv[1] = 8;
|
||||||
|
init_tabs( es_argv[1] );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
// Ignore any other private sequences.
|
// Ignore any other private sequences.
|
||||||
if (prefix2 != 0)
|
if (prefix2 != 0)
|
||||||
return;
|
return;
|
||||||
@ -1185,9 +1215,37 @@ void InterpretEscSeq( void )
|
|||||||
SetConsoleCursorPosition( hConOut, Pos );
|
SetConsoleCursorPosition( hConOut, Pos );
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case 'g':
|
||||||
|
if (es_argc > 1) return; // ESC[g == ESC[0g
|
||||||
|
switch (es_argv[0])
|
||||||
|
{
|
||||||
|
case 0: // ESC[0g Clear tab at cursor
|
||||||
|
if (!pState->tabs) init_tabs( 8 );
|
||||||
|
if (CUR.X < MAX_TABS) pState->tab_stop[CUR.X] = FALSE;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 3: // ESC[3g Clear all tabs
|
||||||
|
memset( pState->tab_stop, FALSE, MAX_TABS );
|
||||||
|
pState->tabs = TRUE;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 8: // ESC[8g Let console handle tabs
|
||||||
|
pState->tabs = FALSE;
|
||||||
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
case 'I': // ESC[#I Moves cursor forward # tabs
|
case 'I': // ESC[#I Moves cursor forward # tabs
|
||||||
if (es_argc > 1) return; // ESC[I == ESC[1I
|
if (es_argc > 1) return; // ESC[I == ESC[1I
|
||||||
Pos.Y = CUR.Y;
|
Pos.Y = CUR.Y;
|
||||||
|
if (pState->tabs)
|
||||||
|
{
|
||||||
|
Pos.X = CUR.X;
|
||||||
|
while (++Pos.X < MAX_TABS && (!pState->tab_stop[Pos.X] || --p1 > 0)) ;
|
||||||
|
}
|
||||||
|
else
|
||||||
Pos.X = (CUR.X & -8) + p1 * 8;
|
Pos.X = (CUR.X & -8) + p1 * 8;
|
||||||
if (Pos.X > RIGHT) Pos.X = RIGHT;
|
if (Pos.X > RIGHT) Pos.X = RIGHT;
|
||||||
SetConsoleCursorPosition( hConOut, Pos );
|
SetConsoleCursorPosition( hConOut, Pos );
|
||||||
@ -1196,10 +1254,18 @@ void InterpretEscSeq( void )
|
|||||||
case 'Z': // ESC[#Z Moves cursor back # tabs
|
case 'Z': // ESC[#Z Moves cursor back # tabs
|
||||||
if (es_argc > 1) return; // ESC[Z == ESC[1Z
|
if (es_argc > 1) return; // ESC[Z == ESC[1Z
|
||||||
Pos.Y = CUR.Y;
|
Pos.Y = CUR.Y;
|
||||||
|
if (pState->tabs)
|
||||||
|
{
|
||||||
|
Pos.X = (CUR.X < MAX_TABS) ? CUR.X : MAX_TABS;
|
||||||
|
while (--Pos.X > 0 && (!pState->tab_stop[Pos.X] || --p1 > 0)) ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if ((CUR.X & 7) == 0)
|
if ((CUR.X & 7) == 0)
|
||||||
Pos.X = CUR.X - p1 * 8;
|
Pos.X = CUR.X - p1 * 8;
|
||||||
else
|
else
|
||||||
Pos.X = (CUR.X & -8) - (p1 - 1) * 8;
|
Pos.X = (CUR.X & -8) - (p1 - 1) * 8;
|
||||||
|
}
|
||||||
if (Pos.X < LEFT) Pos.X = LEFT;
|
if (Pos.X < LEFT) Pos.X = LEFT;
|
||||||
SetConsoleCursorPosition( hConOut, Pos );
|
SetConsoleCursorPosition( hConOut, Pos );
|
||||||
return;
|
return;
|
||||||
@ -1579,6 +1645,15 @@ ParseAndPrintString( HANDLE hDev,
|
|||||||
}
|
}
|
||||||
else if (c == SO) shifted = TRUE;
|
else if (c == SO) shifted = TRUE;
|
||||||
else if (c == SI) shifted = G0_special;
|
else if (c == SI) shifted = G0_special;
|
||||||
|
else if (c == HT && pState != NULL && pState->tabs)
|
||||||
|
{
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO Info;
|
||||||
|
FlushBuffer();
|
||||||
|
GetConsoleScreenBufferInfo( hConOut, &Info );
|
||||||
|
while (++CUR.X < MAX_TABS && !pState->tab_stop[CUR.X]) ;
|
||||||
|
if (CUR.X > RIGHT) CUR.X = RIGHT;
|
||||||
|
SetConsoleCursorPosition( hConOut, CUR );
|
||||||
|
}
|
||||||
else PushBuffer( (WCHAR)c );
|
else PushBuffer( (WCHAR)c );
|
||||||
}
|
}
|
||||||
else if (state == 2)
|
else if (state == 2)
|
||||||
@ -1622,6 +1697,15 @@ ParseAndPrintString( HANDLE hDev,
|
|||||||
ScrollUp();
|
ScrollUp();
|
||||||
state = 1;
|
state = 1;
|
||||||
}
|
}
|
||||||
|
else if (c == 'H') // HTS Character Tabulation Set
|
||||||
|
{
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO Info;
|
||||||
|
if (!pState->tabs) init_tabs( 8 );
|
||||||
|
FlushBuffer();
|
||||||
|
GetConsoleScreenBufferInfo( hConOut, &Info );
|
||||||
|
if (CUR.X < MAX_TABS) pState->tab_stop[CUR.X] = TRUE;
|
||||||
|
state = 1;
|
||||||
|
}
|
||||||
else if (c == '7' || // DECSC Save Cursor
|
else if (c == '7' || // DECSC Save Cursor
|
||||||
c == '8') // DECRC Restore Cursor
|
c == '8') // DECRC Restore Cursor
|
||||||
{
|
{
|
||||||
|
@ -91,7 +91,7 @@
|
|||||||
use -pu to unload from the parent.
|
use -pu to unload from the parent.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PDATE L"9 December, 2017"
|
#define PDATE L"10 December, 2017"
|
||||||
|
|
||||||
#include "ansicon.h"
|
#include "ansicon.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
23
readme.txt
23
readme.txt
@ -150,7 +150,8 @@ Usage
|
|||||||
Sequences Recognised
|
Sequences Recognised
|
||||||
====================
|
====================
|
||||||
|
|
||||||
The following escape sequences are recognised.
|
The following escape sequences are recognised (see "sequences.txt" for a
|
||||||
|
more complete description).
|
||||||
|
|
||||||
\e]0;titleBEL xterm: Set window's title (and icon, ignored)
|
\e]0;titleBEL xterm: Set window's title (and icon, ignored)
|
||||||
\e]2;titleBEL xterm: Set window's title
|
\e]2;titleBEL xterm: Set window's title
|
||||||
@ -183,6 +184,8 @@ Sequences Recognised
|
|||||||
\e[#;#;#...,~ DECPS DEC Play Sound
|
\e[#;#;#...,~ DECPS DEC Play Sound
|
||||||
\e8 DECRC DEC Restore Cursor
|
\e8 DECRC DEC Restore Cursor
|
||||||
\e7 DECSC DEC Save Cursor
|
\e7 DECSC DEC Save Cursor
|
||||||
|
\e[?5W DECST8C DEC Set Tab at Every 8 Columns
|
||||||
|
\e[?5;#W DECST8C DEC Set Tab at Every # Columns (ANSICON extension)
|
||||||
\e[?25h DECTCEM DEC Text Cursor Enable Mode (show cursor)
|
\e[?25h DECTCEM DEC Text Cursor Enable Mode (show cursor)
|
||||||
\e[?25l DECTCEM DEC Text Cursor Enable Mode (hide cursor)
|
\e[?25l DECTCEM DEC Text Cursor Enable Mode (hide cursor)
|
||||||
\e[#M DL Delete Line
|
\e[#M DL Delete Line
|
||||||
@ -193,6 +196,8 @@ Sequences Recognised
|
|||||||
\e[#` HPA Character Position Absolute
|
\e[#` HPA Character Position Absolute
|
||||||
\e[#j HPB Character Position Backward
|
\e[#j HPB Character Position Backward
|
||||||
\e[#a HPR Character Position Forward
|
\e[#a HPR Character Position Forward
|
||||||
|
HT HT Character Tabulation
|
||||||
|
\eH HTS Character Tabulation Set
|
||||||
\e[#;#f HVP Character And Line Position
|
\e[#;#f HVP Character And Line Position
|
||||||
\e[#@ ICH Insert Character
|
\e[#@ ICH Insert Character
|
||||||
\e[#L IL Insert Line
|
\e[#L IL Insert Line
|
||||||
@ -205,13 +210,14 @@ Sequences Recognised
|
|||||||
\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
|
||||||
|
\e[#g TBC Tabulation Clear
|
||||||
\e[#d VPA Line Position Absolute
|
\e[#d VPA Line Position Absolute
|
||||||
\e[#k VPB Line Position Backward
|
\e[#k VPB Line Position Backward
|
||||||
\e[#e VPR Line Position Forward
|
\e[#e VPR Line Position Forward
|
||||||
|
|
||||||
'\e' represents the escape character (ASCII 27); '#' represents a decimal
|
'\e' represents the escape character (ASCII 27); '#' represents a decimal
|
||||||
number (optional, in most cases defaulting to 1); BEL, SO and SI are ASCII
|
number (optional, in most cases defaulting to 1); BEL, HT, SO and SI are
|
||||||
7, 14 and 15. See "sequences.txt" for a more complete description.
|
ASCII 7, 9, 14 and 15.
|
||||||
|
|
||||||
Escape followed by a control character will display that character, not
|
Escape followed by a control character will display that character, not
|
||||||
perform its function; an unrecognised character will preserve the escape.
|
perform its function; an unrecognised character will preserve the escape.
|
||||||
@ -286,7 +292,7 @@ DEC Special Graphics Character Set
|
|||||||
Limitations
|
Limitations
|
||||||
===========
|
===========
|
||||||
|
|
||||||
Tabs are fixed at eight columns.
|
Tabs can only be set up to column 2048.
|
||||||
The saved position will not be restored correctly if the buffer scrolls.
|
The saved position will not be restored correctly if the buffer scrolls.
|
||||||
Palette sequences only work from Vista.
|
Palette sequences only work from Vista.
|
||||||
|
|
||||||
@ -304,7 +310,7 @@ Version History
|
|||||||
|
|
||||||
Legend: + added, - bug-fixed, * changed.
|
Legend: + added, - bug-fixed, * changed.
|
||||||
|
|
||||||
1.80 - 9 December, 2017:
|
1.80 - 10 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
|
||||||
@ -323,7 +329,8 @@ Version History
|
|||||||
+ added palette sequences;
|
+ added palette sequences;
|
||||||
+ added -pu to unload from the parent;
|
+ added -pu to unload from the parent;
|
||||||
+ added IND, NEL, RI, DA, DECCOLM, DECNCSM, DECSC & DECRC;
|
+ added IND, NEL, RI, DA, DECCOLM, DECNCSM, DECSC & DECRC;
|
||||||
+ 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).
|
||||||
|
|
||||||
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;
|
||||||
@ -551,5 +558,5 @@ Distribution
|
|||||||
in LICENSE.txt.
|
in LICENSE.txt.
|
||||||
|
|
||||||
|
|
||||||
============================
|
==============================
|
||||||
Jason Hood, 9 December, 2017.
|
Jason Hood, 10 December, 2017.
|
||||||
|
@ -83,6 +83,14 @@ M move cursor up one line (scroll if necessary; always uses buffer)
|
|||||||
[#C move cursor right # characters
|
[#C move cursor right # characters
|
||||||
[D move cursor left one character
|
[D move cursor left one character
|
||||||
[#D move cursor left # characters
|
[#D move cursor left # characters
|
||||||
|
|
||||||
|
H set tab stop
|
||||||
|
[g remove tab stop at cursor
|
||||||
|
[0g as above
|
||||||
|
[3g remove all tab stops
|
||||||
|
[8g restore console tab handling (ANSICON extension)
|
||||||
|
[?5W set tab stops every 8 columns
|
||||||
|
[?5;#W set tab stops every # columns (ANSICON extension)
|
||||||
[I move cursor forward one tab
|
[I move cursor forward one tab
|
||||||
[#I move cursor forward # tabs
|
[#I move cursor forward # tabs
|
||||||
[Z move cursor back one tab
|
[Z move cursor back one tab
|
||||||
|
Loading…
x
Reference in New Issue
Block a user