Add palette sequences
Recognise the xterm ESC]4 & ESC]104 OSC commands to set/reset colors. Three color specs are recognised: `#RGB`, `#RRGGBB` and `R,G,B`; in addition, multiple specs can be given (separated by commas) to automatically increase the index. I also allow `*` to query this index and all subsequent ones. Reset will restore the colors from when the DLL was first loaded, not from the Console Properties.
This commit is contained in:
parent
9fbe42a583
commit
e2f9b4e417
248
ANSI.c
248
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 23 November, 2017:
|
||||
v1.80, 26 October to 29 November, 2017:
|
||||
fix unloading;
|
||||
revert back to (re)storing buffer cursor position;
|
||||
increase cache to five handles;
|
||||
@ -163,7 +163,8 @@
|
||||
use the system default sound for the bell;
|
||||
add DECPS Play Sound;
|
||||
use intermediate byte '+' to use buffer, not window;
|
||||
ESC followed by a control character will display that character.
|
||||
ESC followed by a control character will display that character;
|
||||
added palette sequences.
|
||||
*/
|
||||
|
||||
#include "ansicon.h"
|
||||
@ -287,8 +288,8 @@ const BYTE backgroundcolor[8] =
|
||||
BACKGROUND_WHITE, // white background
|
||||
};
|
||||
|
||||
const BYTE attr2ansi[8] = // map console attribute to ANSI number
|
||||
{
|
||||
const BYTE attr2ansi[16] = // map console attribute to ANSI number
|
||||
{ // or vice versa
|
||||
0, // black
|
||||
4, // blue
|
||||
2, // green
|
||||
@ -296,21 +297,50 @@ const BYTE attr2ansi[8] = // map console attribute to ANSI number
|
||||
1, // red
|
||||
5, // magenta
|
||||
3, // yellow
|
||||
7 // white
|
||||
7, // white
|
||||
8, // bright black
|
||||
12, // bright blue
|
||||
10, // bright green
|
||||
14, // bright cyan
|
||||
9, // bright red
|
||||
13, // bright magenta
|
||||
11, // bright yellow
|
||||
15, // bright white
|
||||
};
|
||||
|
||||
|
||||
typedef struct _CONSOLE_SCREEN_BUFFER_INFOX {
|
||||
ULONG cbSize;
|
||||
COORD dwSize;
|
||||
COORD dwCursorPosition;
|
||||
WORD wAttributes;
|
||||
SMALL_RECT srWindow;
|
||||
COORD dwMaximumWindowSize;
|
||||
WORD wPopupAttributes;
|
||||
BOOL bFullscreenSupported;
|
||||
COLORREF ColorTable[16];
|
||||
} CONSOLE_SCREEN_BUFFER_INFOX, *PCONSOLE_SCREEN_BUFFER_INFOX;
|
||||
|
||||
typedef BOOL (WINAPI *PHCSBIX)(
|
||||
HANDLE hConsoleOutput,
|
||||
PCONSOLE_SCREEN_BUFFER_INFOX lpConsoleScreenBufferInfoEx
|
||||
);
|
||||
|
||||
PHCSBIX GetConsoleScreenBufferInfoX, SetConsoleScreenBufferInfoX;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE foreground; // ANSI base color (0 to 7; add 30)
|
||||
BYTE background; // ANSI base color (0 to 7; add 40)
|
||||
BYTE bold; // console FOREGROUND_INTENSITY bit
|
||||
BYTE underline; // console BACKGROUND_INTENSITY bit
|
||||
BYTE rvideo; // swap foreground/bold & background/underline
|
||||
BYTE concealed; // set foreground/bold to background/underline
|
||||
BYTE reverse; // swap console foreground & background attributes
|
||||
BYTE crm; // showing control characters?
|
||||
COORD SavePos; // saved cursor position
|
||||
BYTE foreground; // ANSI base color (0 to 7; add 30)
|
||||
BYTE background; // ANSI base color (0 to 7; add 40)
|
||||
BYTE bold; // console FOREGROUND_INTENSITY bit
|
||||
BYTE underline; // console BACKGROUND_INTENSITY bit
|
||||
BYTE rvideo; // swap foreground/bold & background/underline
|
||||
BYTE concealed; // set foreground/bold to background/underline
|
||||
BYTE reverse; // swap console foreground & background attributes
|
||||
BYTE crm; // showing control characters?
|
||||
COORD SavePos; // saved cursor position
|
||||
COLORREF palette[16];
|
||||
} STATE, *PSTATE;
|
||||
|
||||
PSTATE pState;
|
||||
@ -325,7 +355,8 @@ void get_state( void )
|
||||
HWND hwnd;
|
||||
BOOL init;
|
||||
HANDLE hConOut;
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||
CONSOLE_SCREEN_BUFFER_INFOX csbix;
|
||||
static STATE state; // on the odd chance file mapping fails
|
||||
|
||||
if (pState != NULL)
|
||||
@ -362,7 +393,16 @@ void get_state( void )
|
||||
hConOut = CreateFile( L"CONOUT$", GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL, OPEN_EXISTING, 0, NULL );
|
||||
if (!GetConsoleScreenBufferInfo( hConOut, &csbi ))
|
||||
csbix.cbSize = sizeof(csbix);
|
||||
if (GetConsoleScreenBufferInfoX &&
|
||||
GetConsoleScreenBufferInfoX( hConOut, &csbix ))
|
||||
{
|
||||
csbi.dwSize = csbix.dwSize;
|
||||
csbi.wAttributes = csbix.wAttributes;
|
||||
csbi.srWindow = csbix.srWindow;
|
||||
memcpy( pState->palette, csbix.ColorTable, sizeof(csbix.ColorTable) );
|
||||
}
|
||||
else if (!GetConsoleScreenBufferInfo( hConOut, &csbi ))
|
||||
{
|
||||
DEBUGSTR( 1, "Failed to get screen buffer info (%u) - assuming defaults",
|
||||
GetLastError() );
|
||||
@ -641,6 +681,21 @@ void SendSequence( LPTSTR seq )
|
||||
HeapFree( hHeap, 0, in );
|
||||
}
|
||||
|
||||
void send_palette_sequence( COLORREF c )
|
||||
{
|
||||
BYTE r, g, b;
|
||||
TCHAR buf[16];
|
||||
|
||||
r = GetRValue( c );
|
||||
g = GetGValue( c );
|
||||
b = GetBValue( c );
|
||||
if ((c & 0x0F0F0F) == ((c & 0xF0F0F0) >> 4))
|
||||
wsprintf( buf, L"#%X%X%X", r & 0xF, g & 0xF, b & 0xF );
|
||||
else
|
||||
wsprintf( buf, L"#%02X%02X%02X", r, g, b );
|
||||
SendSequence( buf );
|
||||
}
|
||||
|
||||
// ========== Print functions
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -742,7 +797,7 @@ void InterpretEscSeq( void )
|
||||
// that's what we do. According to T.416 (ISO 8613-6), there is
|
||||
// only one parameter, which is divided into elements. So where
|
||||
// xterm does "38;2;R;G;B" it should really be "38;2:I:R:G:B" (I is
|
||||
// a colour space identifier).
|
||||
// a color space identifier).
|
||||
if (i+1 < es_argc)
|
||||
{
|
||||
if (es_argv[i+1] == 2) // rgb
|
||||
@ -1211,14 +1266,154 @@ void InterpretEscSeq( void )
|
||||
else // (prefix == ']')
|
||||
{
|
||||
// Ignore any "private" sequences.
|
||||
if (prefix2 != 0)
|
||||
if (prefix2 != 0 || es_argc != 1)
|
||||
return;
|
||||
|
||||
if (es_argc == 1 && (es_argv[0] == 0 || // ESC]0;titleST - icon (ignored) &
|
||||
es_argv[0] == 2)) // ESC]2;titleST - window
|
||||
if (es_argv[0] == 0 || // ESC]0;titleST - icon (ignored) &
|
||||
es_argv[0] == 2) // ESC]2;titleST - window
|
||||
{
|
||||
SetConsoleTitle( Pt_arg );
|
||||
}
|
||||
else if (es_argv[0] == 4 || // ESC]4;paletteST - set/get color(s)
|
||||
es_argv[0] == 104) // ESC]104;paletteST - reset color(s)
|
||||
{
|
||||
CONSOLE_SCREEN_BUFFER_INFOX csbix;
|
||||
csbix.cbSize = sizeof(csbix);
|
||||
if (!GetConsoleScreenBufferInfoX ||
|
||||
!GetConsoleScreenBufferInfoX( hConOut, &csbix ))
|
||||
return;
|
||||
if (es_argv[0] == 4)
|
||||
{
|
||||
BYTE r, g, b;
|
||||
DWORD c;
|
||||
LPTSTR beg, end;
|
||||
BOOL started = FALSE;
|
||||
for (beg = Pt_arg;; beg = end + 1)
|
||||
{
|
||||
i = (int)wcstoul( beg, &end, 10 );
|
||||
if (end == beg || (*end != ';' && *end != '\0') || i >= 16)
|
||||
break;
|
||||
if (end[2] == ';' || end[2] == '\0')
|
||||
{
|
||||
if (end[1] == '*')
|
||||
{
|
||||
SendSequence( L"\33]4;" );
|
||||
end[1] = '\0';
|
||||
SendSequence( beg );
|
||||
for (; i < 16; ++i)
|
||||
{
|
||||
send_palette_sequence( csbix.ColorTable[attr2ansi[i]] );
|
||||
SendSequence( (i == 15) ? L"\a" : L"," );
|
||||
}
|
||||
}
|
||||
else if (end[1] == '?')
|
||||
{
|
||||
if (!started)
|
||||
{
|
||||
SendSequence( L"\33]4" );
|
||||
started = TRUE;
|
||||
}
|
||||
SendSequence( L";" );
|
||||
end[1] = '\0';
|
||||
SendSequence( beg );
|
||||
send_palette_sequence( csbix.ColorTable[attr2ansi[i]] );
|
||||
}
|
||||
else
|
||||
break;
|
||||
end += (end[2] == '\0') ? 1 : 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (started)
|
||||
{
|
||||
started = FALSE;
|
||||
SendSequence( L"\a" );
|
||||
}
|
||||
for (beg = end + 1;; beg = end + 1)
|
||||
{
|
||||
BOOL valid;
|
||||
if (*beg == '#')
|
||||
{
|
||||
valid = TRUE;
|
||||
c = (DWORD)wcstoul( ++beg, &end, 16 );
|
||||
if (end - beg == 3)
|
||||
{
|
||||
r = (BYTE)(c >> 8);
|
||||
g = (BYTE)(c >> 4) & 0xF;
|
||||
b = (BYTE)c & 0xF;
|
||||
r |= r << 4;
|
||||
g |= g << 4;
|
||||
b |= b << 4;
|
||||
}
|
||||
else if (end - beg == 6)
|
||||
{
|
||||
r = (BYTE)(c >> 16);
|
||||
g = (BYTE)(c >> 8);
|
||||
b = (BYTE)c;
|
||||
}
|
||||
else
|
||||
valid = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
valid = FALSE;
|
||||
c = (DWORD)wcstoul( beg, &end, 10 );
|
||||
if (*end == ',' && c < 256)
|
||||
{
|
||||
r = (BYTE)c;
|
||||
c = (DWORD)wcstoul( end + 1, &end, 10 );
|
||||
if (*end == ',' && c < 256)
|
||||
{
|
||||
g = (BYTE)c;
|
||||
c = (DWORD)wcstoul( end + 1, &end, 10 );
|
||||
if ((*end == ',' || *end == ';' || *end == '\0') && c < 256)
|
||||
{
|
||||
b = (BYTE)c;
|
||||
valid = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (valid)
|
||||
csbix.ColorTable[attr2ansi[i++]] = RGB( r, g, b );
|
||||
if (*end != ',' || i == 16)
|
||||
{
|
||||
while (*end != ';' && *end != '\0')
|
||||
++end;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (*end != ';')
|
||||
break;
|
||||
}
|
||||
if (started)
|
||||
SendSequence( L"\a" );
|
||||
}
|
||||
else // (es_argv[0] == 104)
|
||||
{
|
||||
// Reset each index, or the entire palette.
|
||||
if (Pt_len == 0)
|
||||
memcpy( csbix.ColorTable, pState->palette, sizeof(csbix.ColorTable) );
|
||||
else
|
||||
{
|
||||
LPTSTR beg, end;
|
||||
for (beg = Pt_arg;; beg = end + 1)
|
||||
{
|
||||
i = (int)wcstoul( beg, &end, 10 );
|
||||
if (end == beg || (*end != ';' && *end != '\0') || i >= 16)
|
||||
break;
|
||||
i = attr2ansi[i];
|
||||
csbix.ColorTable[i] = pState->palette[i];
|
||||
if (*end == '\0')
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
++csbix.srWindow.Right;
|
||||
++csbix.srWindow.Bottom;
|
||||
SetConsoleScreenBufferInfoX( hConOut, &csbix );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1384,6 +1579,12 @@ ParseAndPrintString( HANDLE hDev,
|
||||
{
|
||||
state = 1;
|
||||
}
|
||||
else if (prefix == ']')
|
||||
{
|
||||
es_argc++;
|
||||
state = 5;
|
||||
goto state5;
|
||||
}
|
||||
else
|
||||
{
|
||||
es_argc++;
|
||||
@ -1394,6 +1595,7 @@ ParseAndPrintString( HANDLE hDev,
|
||||
}
|
||||
else if (state == 5)
|
||||
{
|
||||
state5:
|
||||
if (c == BEL)
|
||||
{
|
||||
Pt_arg[Pt_len] = '\0';
|
||||
@ -2647,6 +2849,11 @@ BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved )
|
||||
if (dwReason == DLL_PROCESS_ATTACH)
|
||||
{
|
||||
hHeap = HeapCreate( 0, 0, 128 * 1024 );
|
||||
hKernel = GetModuleHandleA( APIKernel );
|
||||
GetConsoleScreenBufferInfoX = (PHCSBIX)GetProcAddress(
|
||||
hKernel, "GetConsoleScreenBufferInfoEx" );
|
||||
SetConsoleScreenBufferInfoX = (PHCSBIX)GetProcAddress(
|
||||
hKernel, "SetConsoleScreenBufferInfoEx" );
|
||||
|
||||
*logstr = '\0';
|
||||
GetEnvironmentVariable( L"ANSICON_LOG", logstr, lenof(logstr) );
|
||||
@ -2662,7 +2869,6 @@ BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved )
|
||||
DEBUGSTR( 1, "hDllInstance = %p", hDllInstance );
|
||||
|
||||
// Get the entry points to the original functions.
|
||||
hKernel = GetModuleHandleA( APIKernel );
|
||||
for (hook = Hooks; hook->name; ++hook)
|
||||
hook->oldfunc = GetProcAddress( hKernel, hook->name );
|
||||
|
||||
|
@ -90,7 +90,7 @@
|
||||
write newline with _putws, not putwchar (fixes redirecting to CON).
|
||||
*/
|
||||
|
||||
#define PDATE L"24 November, 2017"
|
||||
#define PDATE L"29 November, 2017"
|
||||
|
||||
#include "ansicon.h"
|
||||
#include "version.h"
|
||||
|
10
readme.txt
10
readme.txt
@ -152,6 +152,8 @@ Sequences Recognised
|
||||
|
||||
\e]0;titleBEL xterm: Set window's title (and icon, ignored)
|
||||
\e]2;titleBEL xterm: Set window's title
|
||||
\e]4;...BEL xterm: Change color(s)
|
||||
\e]104;...BEL xterm: Reset color(s)
|
||||
\e[21t xterm: Report window's title
|
||||
\e[s ANSI.SYS: Save Cursor Position
|
||||
\e[u ANSI.SYS: Restore Cursor Position
|
||||
@ -283,6 +285,7 @@ Limitations
|
||||
|
||||
Tabs are fixed at eight columns.
|
||||
The saved position will not be restored correctly if the buffer scrolls.
|
||||
Palette sequences only work from Vista.
|
||||
|
||||
There may be a conflict with NVIDIA's drivers, requiring the setting of the
|
||||
Environment Variable:
|
||||
@ -298,7 +301,7 @@ Version History
|
||||
|
||||
Legend: + added, - bug-fixed, * changed.
|
||||
|
||||
1.80 - 24 November, 2017:
|
||||
1.80 - 29 November, 2017:
|
||||
- fix unloading;
|
||||
- fix -e et al when redirecting to CON;
|
||||
- hook CreateFile and CreateConsoleScreenBuffer to force read/write access
|
||||
@ -310,7 +313,8 @@ Version History
|
||||
* escape control characters;
|
||||
+ use the system default sound for the bell;
|
||||
+ added Play Sound DECPS;
|
||||
+ added '+' intermediate byte to use the buffer, rather than the window.
|
||||
+ added '+' intermediate byte to use the buffer, rather than the window;
|
||||
+ added palette sequences.
|
||||
|
||||
1.72 - 24 December, 2015:
|
||||
- handle STD_OUTPUT_HANDLE & STD_ERROR_HANDLE in WriteFile;
|
||||
@ -539,4 +543,4 @@ Distribution
|
||||
|
||||
|
||||
=============================
|
||||
Jason Hood, 24 November, 2017.
|
||||
Jason Hood, 29 November, 2017.
|
||||
|
@ -131,6 +131,18 @@ whilst "[2+J" will erase the buffer).
|
||||
]2;TitleST
|
||||
sets the console title to "Title"; ST (string terminator) is either
|
||||
character 7 (BEL) or escape and backslash
|
||||
]4;#;spec,spec...;#...ST
|
||||
set or query the palette:
|
||||
# is the ANSI index (0-7, or 8-15 for bold/underline)
|
||||
spec is:
|
||||
? send the current value to console input
|
||||
* send the current and all subsequent values
|
||||
#RGB set the color (hexadecimal)
|
||||
#RRGGBB set the color (hexadecimal)
|
||||
R,G,B set the color (decimal)
|
||||
]104ST restore the entire palette
|
||||
]104;#...ST
|
||||
restore the color of each index
|
||||
|
||||
[#;#;#...,~
|
||||
play sound (beep):
|
||||
|
Loading…
x
Reference in New Issue
Block a user