Use window height, not buffer.

Clear screen (\e[2J) will scroll in a new window the first time it's used,
or the window has scrolled, or the cursor is on the last line of the buffer.

Restore Cursor Position (\e[u) will recognise screen size changes and limit
itself to the new boundaries.
This commit is contained in:
Jason Hood 2014-02-20 18:06:28 +10:00
parent 9fa86512f3
commit 7539473550
3 changed files with 135 additions and 117 deletions

224
ANSI.c
View File

@ -111,7 +111,7 @@
v1.66, 20 & 21 September, 2013: v1.66, 20 & 21 September, 2013:
fix 32-bit process trying to detect 64-bit process. fix 32-bit process trying to detect 64-bit process.
v1.70, 25 January to 18 February, 2014: v1.70, 25 January to 20 February, 2014:
don't hook ourself from LoadLibrary or LoadLibraryEx; don't hook ourself from LoadLibrary or LoadLibraryEx;
update the LoadLibraryEx flags that should not cause hooking; update the LoadLibraryEx flags that should not cause hooking;
inject by manipulating the import directory table; for 64-bit AnyCPU use inject by manipulating the import directory table; for 64-bit AnyCPU use
@ -126,7 +126,8 @@
don't hook a module that's already hooked us; don't hook a module that's already hooked us;
better parsing of escape & CSI sequences; better parsing of escape & CSI sequences;
ignore xterm 38 & 48 SGR values; ignore xterm 38 & 48 SGR values;
change G1 blank from space to U+00A0 - No-Break Space. change G1 blank from space to U+00A0 - No-Break Space;
use window height, not buffer.
*/ */
#include "ansicon.h" #include "ansicon.h"
@ -156,6 +157,7 @@ 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
int Pt_len; int Pt_len;
BOOL shifted; BOOL shifted;
int screen_top = -1; // initial window top when cleared
// DEC Special Graphics Character Set from // DEC Special Graphics Character Set from
@ -473,6 +475,17 @@ void InterpretEscSeq( void )
SMALL_RECT Rect; SMALL_RECT Rect;
CHAR_INFO CharInfo; CHAR_INFO CharInfo;
#define WIDTH Info.dwSize.X
#define CUR Info.dwCursorPosition
#define WIN Info.srWindow
#define TOP WIN.Top
#define BOTTOM WIN.Bottom
#define FillBlank( len, Pos ) \
FillConsoleOutputCharacter( hConOut, ' ', len, Pos, &NumberOfCharsWritten );\
FillConsoleOutputAttribute( hConOut, Info.wAttributes, len, Pos, \
&NumberOfCharsWritten )
if (prefix == '[') if (prefix == '[')
{ {
if (prefix2 == '?' && (suffix == 'h' || suffix == 'l')) if (prefix2 == '?' && (suffix == 'h' || suffix == 'l'))
@ -613,35 +626,50 @@ void InterpretEscSeq( void )
switch (es_argv[0]) switch (es_argv[0])
{ {
case 0: // ESC[0J erase from cursor to end of display case 0: // ESC[0J erase from cursor to end of display
len = (Info.dwSize.Y - Info.dwCursorPosition.Y - 1) * Info.dwSize.X len = (BOTTOM - CUR.Y) * WIDTH + WIDTH - CUR.X;
+ Info.dwSize.X - Info.dwCursorPosition.X - 1; FillBlank( len, CUR );
FillConsoleOutputCharacter( hConOut, ' ', len,
Info.dwCursorPosition,
&NumberOfCharsWritten );
FillConsoleOutputAttribute( hConOut, Info.wAttributes, len,
Info.dwCursorPosition,
&NumberOfCharsWritten );
return; return;
case 1: // ESC[1J erase from start to cursor. case 1: // ESC[1J erase from start to cursor.
Pos.X = 0; Pos.X = 0;
Pos.Y = 0; Pos.Y = TOP;
len = Info.dwCursorPosition.Y * Info.dwSize.X len = (CUR.Y - TOP) * WIDTH + CUR.X + 1;
+ Info.dwCursorPosition.X + 1; FillBlank( len, Pos );
FillConsoleOutputCharacter( hConOut, ' ', len, Pos, return;
&NumberOfCharsWritten );
FillConsoleOutputAttribute( hConOut, Info.wAttributes, len, Pos,
&NumberOfCharsWritten );
return;
case 2: // ESC[2J Clear screen and home cursor case 2: // ESC[2J Clear screen and home cursor
if (TOP != screen_top || BOTTOM == Info.dwSize.Y - 1)
{
// Rather than clearing the existing window, make the current
// line the new top of the window (assuming this is the first
// thing a program does).
int range = BOTTOM - TOP;
if (CUR.Y + range < Info.dwSize.Y)
{
TOP = CUR.Y;
BOTTOM = TOP + range;
}
else
{
BOTTOM = Info.dwSize.Y - 1;
TOP = BOTTOM - range;
Rect.Left = 0;
Rect.Right = WIDTH - 1;
Rect.Top = CUR.Y - TOP;
Rect.Bottom = CUR.Y - 1;
Pos.X = Pos.Y = 0;
CharInfo.Char.UnicodeChar = ' ';
CharInfo.Attributes = Info.wAttributes;
ScrollConsoleScreenBuffer(hConOut, &Rect, NULL, Pos, &CharInfo);
}
SetConsoleWindowInfo( hConOut, TRUE, &WIN );
screen_top = TOP;
}
Pos.X = 0; Pos.X = 0;
Pos.Y = 0; Pos.Y = TOP;
len = Info.dwSize.X * Info.dwSize.Y; len = (BOTTOM - TOP + 1) * WIDTH;
FillConsoleOutputCharacter( hConOut, ' ', len, Pos, FillBlank( len, Pos );
&NumberOfCharsWritten ); // Not technically correct, but perhaps expected.
FillConsoleOutputAttribute( hConOut, Info.wAttributes, len, Pos,
&NumberOfCharsWritten );
SetConsoleCursorPosition( hConOut, Pos ); SetConsoleCursorPosition( hConOut, Pos );
return; return;
@ -655,34 +683,20 @@ void InterpretEscSeq( void )
switch (es_argv[0]) switch (es_argv[0])
{ {
case 0: // ESC[0K Clear to end of line case 0: // ESC[0K Clear to end of line
len = Info.dwSize.X - Info.dwCursorPosition.X + 1; len = WIDTH - CUR.X + 1;
FillConsoleOutputCharacter( hConOut, ' ', len, FillBlank( len, CUR );
Info.dwCursorPosition,
&NumberOfCharsWritten );
FillConsoleOutputAttribute( hConOut, Info.wAttributes, len,
Info.dwCursorPosition,
&NumberOfCharsWritten );
return; return;
case 1: // ESC[1K Clear from start of line to cursor case 1: // ESC[1K Clear from start of line to cursor
Pos.X = 0; Pos.X = 0;
Pos.Y = Info.dwCursorPosition.Y; Pos.Y = CUR.Y;
FillConsoleOutputCharacter( hConOut, ' ', FillBlank( CUR.X + 1, Pos );
Info.dwCursorPosition.X + 1, Pos,
&NumberOfCharsWritten );
FillConsoleOutputAttribute( hConOut, Info.wAttributes,
Info.dwCursorPosition.X + 1, Pos,
&NumberOfCharsWritten );
return; return;
case 2: // ESC[2K Clear whole line. case 2: // ESC[2K Clear whole line.
Pos.X = 0; Pos.X = 0;
Pos.Y = Info.dwCursorPosition.Y; Pos.Y = CUR.Y;
FillConsoleOutputCharacter( hConOut, ' ', Info.dwSize.X, Pos, FillBlank( WIDTH, Pos );
&NumberOfCharsWritten );
FillConsoleOutputAttribute( hConOut, Info.wAttributes,
Info.dwSize.X, Pos,
&NumberOfCharsWritten );
return; return;
default: default:
@ -692,82 +706,74 @@ void InterpretEscSeq( void )
case 'X': // ESC[#X Erase # characters. case 'X': // ESC[#X Erase # characters.
if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[X == ESC[1X if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[X == ESC[1X
if (es_argc != 1) return; if (es_argc != 1) return;
FillConsoleOutputCharacter( hConOut, ' ', es_argv[0], FillBlank( es_argv[0], CUR );
Info.dwCursorPosition,
&NumberOfCharsWritten );
FillConsoleOutputAttribute( hConOut, Info.wAttributes, es_argv[0],
Info.dwCursorPosition,
&NumberOfCharsWritten );
return; return;
case 'L': // ESC[#L Insert # blank lines. case 'L': // ESC[#L Insert # blank lines.
if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[L == ESC[1L if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[L == ESC[1L
if (es_argc != 1) return; if (es_argc != 1) return;
Rect.Left = 0; Rect.Left = WIN.Left = 0;
Rect.Top = Info.dwCursorPosition.Y; Rect.Right = WIN.Right = WIDTH - 1;
Rect.Right = Info.dwSize.X - 1; Rect.Top = CUR.Y;
Rect.Bottom = Info.dwSize.Y - 1; Rect.Bottom = BOTTOM;
Pos.X = 0; Pos.X = 0;
Pos.Y = Info.dwCursorPosition.Y + es_argv[0]; Pos.Y = CUR.Y + es_argv[0];
CharInfo.Char.UnicodeChar = ' '; CharInfo.Char.UnicodeChar = ' ';
CharInfo.Attributes = Info.wAttributes; CharInfo.Attributes = Info.wAttributes;
ScrollConsoleScreenBuffer( hConOut, &Rect, NULL, Pos, &CharInfo ); ScrollConsoleScreenBuffer( hConOut, &Rect, &WIN, Pos, &CharInfo );
// Technically should home the cursor, but perhaps not expected.
return; return;
case 'M': // ESC[#M Delete # lines. case 'M': // ESC[#M Delete # lines.
if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[M == ESC[1M if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[M == ESC[1M
if (es_argc != 1) return; if (es_argc != 1) return;
if (es_argv[0] > Info.dwSize.Y - Info.dwCursorPosition.Y) Rect.Left = WIN.Left = 0;
es_argv[0] = Info.dwSize.Y - Info.dwCursorPosition.Y; Rect.Right = WIN.Right = WIDTH - 1;
Rect.Left = 0; Rect.Bottom = BOTTOM;
Rect.Top = Info.dwCursorPosition.Y + es_argv[0]; Rect.Top = CUR.Y - es_argv[0];
Rect.Right = Info.dwSize.X - 1;
Rect.Bottom = Info.dwSize.Y - 1;
Pos.X = 0; Pos.X = 0;
Pos.Y = Info.dwCursorPosition.Y; Pos.Y = TOP = CUR.Y;
CharInfo.Char.UnicodeChar = ' '; CharInfo.Char.UnicodeChar = ' ';
CharInfo.Attributes = Info.wAttributes; CharInfo.Attributes = Info.wAttributes;
ScrollConsoleScreenBuffer( hConOut, &Rect, NULL, Pos, &CharInfo ); ScrollConsoleScreenBuffer( hConOut, &Rect, &WIN, Pos, &CharInfo );
// Technically should home the cursor, but perhaps not expected.
return; return;
case 'P': // ESC[#P Delete # characters. case 'P': // ESC[#P Delete # characters.
if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[P == ESC[1P if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[P == ESC[1P
if (es_argc != 1) return; if (es_argc != 1) return;
if (Info.dwCursorPosition.X + es_argv[0] > Info.dwSize.X - 1) Rect.Left = WIN.Left = CUR.X;
es_argv[0] = Info.dwSize.X - Info.dwCursorPosition.X; Rect.Right = WIN.Right = WIDTH - 1;
Rect.Left = Info.dwCursorPosition.X + es_argv[0]; Pos.X = CUR.X - es_argv[0];
Rect.Top = Info.dwCursorPosition.Y; Pos.Y =
Rect.Right = Info.dwSize.X - 1; Rect.Top =
Rect.Bottom = Info.dwCursorPosition.Y; Rect.Bottom = CUR.Y;
CharInfo.Char.UnicodeChar = ' '; CharInfo.Char.UnicodeChar = ' ';
CharInfo.Attributes = Info.wAttributes; CharInfo.Attributes = Info.wAttributes;
ScrollConsoleScreenBuffer( hConOut, &Rect, NULL, Info.dwCursorPosition, ScrollConsoleScreenBuffer( hConOut, &Rect, &WIN, Pos, &CharInfo );
&CharInfo );
return; return;
case '@': // ESC[#@ Insert # blank characters. case '@': // ESC[#@ Insert # blank characters.
if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[@ == ESC[1@ if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[@ == ESC[1@
if (es_argc != 1) return; if (es_argc != 1) return;
if (Info.dwCursorPosition.X + es_argv[0] > Info.dwSize.X - 1) Rect.Left = WIN.Left = CUR.X;
es_argv[0] = Info.dwSize.X - Info.dwCursorPosition.X; Rect.Right = WIN.Right = WIDTH - 1;
Rect.Left = Info.dwCursorPosition.X; Pos.X = CUR.X + es_argv[0];
Rect.Top = Info.dwCursorPosition.Y; Pos.Y =
Rect.Right = Info.dwSize.X - 1 - es_argv[0]; Rect.Top =
Rect.Bottom = Info.dwCursorPosition.Y; Rect.Bottom = CUR.Y;
Pos.X = Info.dwCursorPosition.X + es_argv[0];
Pos.Y = Info.dwCursorPosition.Y;
CharInfo.Char.UnicodeChar = ' '; CharInfo.Char.UnicodeChar = ' ';
CharInfo.Attributes = Info.wAttributes; CharInfo.Attributes = Info.wAttributes;
ScrollConsoleScreenBuffer( hConOut, &Rect, NULL, Pos, &CharInfo ); ScrollConsoleScreenBuffer( hConOut, &Rect, &WIN, Pos, &CharInfo );
return; return;
case 'k': // ESC[#k case 'k': // ESC[#k
case 'A': // ESC[#A Moves cursor up # lines case 'A': // ESC[#A Moves cursor up # lines
if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[A == ESC[1A if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[A == ESC[1A
if (es_argc != 1) return; if (es_argc != 1) return;
Pos.Y = Info.dwCursorPosition.Y - es_argv[0]; Pos.Y = CUR.Y - es_argv[0];
if (Pos.Y < 0) Pos.Y = 0; if (Pos.Y < TOP) Pos.Y = TOP;
Pos.X = Info.dwCursorPosition.X; Pos.X = CUR.X;
SetConsoleCursorPosition( hConOut, Pos ); SetConsoleCursorPosition( hConOut, Pos );
return; return;
@ -775,9 +781,9 @@ void InterpretEscSeq( void )
case 'B': // ESC[#B Moves cursor down # lines case 'B': // ESC[#B Moves cursor down # lines
if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[B == ESC[1B if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[B == ESC[1B
if (es_argc != 1) return; if (es_argc != 1) return;
Pos.Y = Info.dwCursorPosition.Y + es_argv[0]; Pos.Y = CUR.Y + es_argv[0];
if (Pos.Y >= Info.dwSize.Y) Pos.Y = Info.dwSize.Y - 1; if (Pos.Y > BOTTOM) Pos.Y = BOTTOM;
Pos.X = Info.dwCursorPosition.X; Pos.X = CUR.X;
SetConsoleCursorPosition( hConOut, Pos ); SetConsoleCursorPosition( hConOut, Pos );
return; return;
@ -785,9 +791,9 @@ void InterpretEscSeq( void )
case 'C': // ESC[#C Moves cursor forward # spaces case 'C': // ESC[#C Moves cursor forward # spaces
if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[C == ESC[1C if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[C == ESC[1C
if (es_argc != 1) return; if (es_argc != 1) return;
Pos.X = Info.dwCursorPosition.X + es_argv[0]; Pos.X = CUR.X + es_argv[0];
if (Pos.X >= Info.dwSize.X) Pos.X = Info.dwSize.X - 1; if (Pos.X >= WIDTH) Pos.X = WIDTH - 1;
Pos.Y = Info.dwCursorPosition.Y; Pos.Y = CUR.Y;
SetConsoleCursorPosition( hConOut, Pos ); SetConsoleCursorPosition( hConOut, Pos );
return; return;
@ -795,17 +801,17 @@ void InterpretEscSeq( void )
case 'D': // ESC[#D Moves cursor back # spaces case 'D': // ESC[#D Moves cursor back # spaces
if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[D == ESC[1D if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[D == ESC[1D
if (es_argc != 1) return; if (es_argc != 1) return;
Pos.X = Info.dwCursorPosition.X - es_argv[0]; Pos.X = CUR.X - es_argv[0];
if (Pos.X < 0) Pos.X = 0; if (Pos.X < 0) Pos.X = 0;
Pos.Y = Info.dwCursorPosition.Y; Pos.Y = CUR.Y;
SetConsoleCursorPosition( hConOut, Pos ); SetConsoleCursorPosition( hConOut, Pos );
return; return;
case 'E': // ESC[#E Moves cursor down # lines, column 1. case 'E': // ESC[#E Moves cursor down # lines, column 1.
if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[E == ESC[1E if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[E == ESC[1E
if (es_argc != 1) return; if (es_argc != 1) return;
Pos.Y = Info.dwCursorPosition.Y + es_argv[0]; Pos.Y = CUR.Y + es_argv[0];
if (Pos.Y >= Info.dwSize.Y) Pos.Y = Info.dwSize.Y - 1; if (Pos.Y > BOTTOM) Pos.Y = BOTTOM;
Pos.X = 0; Pos.X = 0;
SetConsoleCursorPosition( hConOut, Pos ); SetConsoleCursorPosition( hConOut, Pos );
return; return;
@ -813,8 +819,8 @@ void InterpretEscSeq( void )
case 'F': // ESC[#F Moves cursor up # lines, column 1. case 'F': // ESC[#F Moves cursor up # lines, column 1.
if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[F == ESC[1F if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[F == ESC[1F
if (es_argc != 1) return; if (es_argc != 1) return;
Pos.Y = Info.dwCursorPosition.Y - es_argv[0]; Pos.Y = CUR.Y - es_argv[0];
if (Pos.Y < 0) Pos.Y = 0; if (Pos.Y < TOP) Pos.Y = TOP;
Pos.X = 0; Pos.X = 0;
SetConsoleCursorPosition( hConOut, Pos ); SetConsoleCursorPosition( hConOut, Pos );
return; return;
@ -824,9 +830,9 @@ void InterpretEscSeq( void )
if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[G == ESC[1G if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[G == ESC[1G
if (es_argc != 1) return; if (es_argc != 1) return;
Pos.X = es_argv[0] - 1; Pos.X = es_argv[0] - 1;
if (Pos.X >= Info.dwSize.X) Pos.X = Info.dwSize.X - 1; if (Pos.X >= WIDTH) Pos.X = WIDTH - 1;
if (Pos.X < 0) Pos.X = 0; if (Pos.X < 0) Pos.X = 0;
Pos.Y = Info.dwCursorPosition.Y; Pos.Y = CUR.Y;
SetConsoleCursorPosition( hConOut, Pos ); SetConsoleCursorPosition( hConOut, Pos );
return; return;
@ -834,8 +840,8 @@ void InterpretEscSeq( void )
if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[d == ESC[1d if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[d == ESC[1d
if (es_argc != 1) return; if (es_argc != 1) return;
Pos.Y = es_argv[0] - 1; Pos.Y = es_argv[0] - 1;
if (Pos.Y < 0) Pos.Y = 0; if (Pos.Y < TOP) Pos.Y = TOP;
if (Pos.Y >= Info.dwSize.Y) Pos.Y = Info.dwSize.Y - 1; if (Pos.Y > BOTTOM) Pos.Y = BOTTOM;
SetConsoleCursorPosition( hConOut, Pos ); SetConsoleCursorPosition( hConOut, Pos );
return; return;
@ -848,23 +854,28 @@ void InterpretEscSeq( void )
if (es_argc > 2) return; if (es_argc > 2) return;
Pos.X = es_argv[1] - 1; Pos.X = es_argv[1] - 1;
if (Pos.X < 0) Pos.X = 0; if (Pos.X < 0) Pos.X = 0;
if (Pos.X >= Info.dwSize.X) Pos.X = Info.dwSize.X - 1; if (Pos.X >= WIDTH) Pos.X = WIDTH - 1;
Pos.Y = es_argv[0] - 1; Pos.Y = es_argv[0] - 1;
if (Pos.Y < 0) Pos.Y = 0; if (Pos.Y < TOP) Pos.Y = TOP;
if (Pos.Y >= Info.dwSize.Y) Pos.Y = Info.dwSize.Y - 1; if (Pos.Y > BOTTOM) Pos.Y = BOTTOM;
SetConsoleCursorPosition( hConOut, Pos ); SetConsoleCursorPosition( hConOut, Pos );
return; return;
case 's': // ESC[s Saves cursor position for recall later case 's': // ESC[s Saves cursor position for recall later
if (es_argc != 0) return; if (es_argc != 0) return;
get_state(); get_state();
pState->SavePos = Info.dwCursorPosition; pState->SavePos.X = CUR.X;
pState->SavePos.Y = CUR.Y - TOP;
return; return;
case 'u': // ESC[u Return to saved cursor position case 'u': // ESC[u Return to saved cursor position
if (es_argc != 0) return; if (es_argc != 0) return;
get_state(); get_state();
SetConsoleCursorPosition( hConOut, pState->SavePos ); Pos.X = pState->SavePos.X;
Pos.Y = pState->SavePos.Y + TOP;
if (Pos.X >= WIDTH) Pos.X = WIDTH - 1;
if (Pos.Y > BOTTOM) Pos.Y = BOTTOM;
SetConsoleCursorPosition( hConOut, Pos );
return; return;
case 'n': // ESC[#n Device status report case 'n': // ESC[#n Device status report
@ -878,8 +889,7 @@ void InterpretEscSeq( void )
case 6: // ESC[6n Report cursor position case 6: // ESC[6n Report cursor position
{ {
TCHAR buf[32]; TCHAR buf[32];
wsprintf( buf, L"\33[%d;%dR", Info.dwCursorPosition.Y + 1, wsprintf( buf, L"\33[%d;%dR", CUR.Y - TOP + 1, CUR.X + 1 );
Info.dwCursorPosition.X + 1 );
SendSequence( buf ); SendSequence( buf );
} }
return; return;

View File

@ -87,7 +87,7 @@
add error codes to some message. add error codes to some message.
*/ */
#define PDATE L"18 February, 2014" #define PDATE L"20 February, 2014"
#include "ansicon.h" #include "ansicon.h"
#include "version.h" #include "version.h"

View File

@ -147,11 +147,11 @@ Sequences Recognised
The following escape sequences are recognised. The following escape sequences are recognised.
\e]0;titleBEL Set (xterm) window's title (and icon, ignored) \e]0;titleBEL xterm: Set window's title (and icon, ignored)
\e]2;titleBEL Set (xterm) window's title \e]2;titleBEL xterm: Set window's title
\e[21t Report (xterm) window's title \e[21t xterm: Report window's title
\e[s Save Cursor \e[s ANSI.SYS: Save Cursor Position
\e[u Restore Cursor \e[u ANSI.SYS: Restore Cursor Position
\e[#G CHA Cursor Character Absolute \e[#G CHA Cursor Character Absolute
\e[#E CNL Cursor Next Line \e[#E CNL Cursor Next Line
\e[#F CPL Cursor Preceding Line \e[#F CPL Cursor Preceding Line
@ -194,6 +194,12 @@ Sequences Recognised
iable ANSICON_DEF can be used to change the default colors (same value as iable ANSICON_DEF can be used to change the default colors (same value as
'-m'; setting the variable does not change the current colors). '-m'; setting the variable does not change the current colors).
The first time a program clears the screen ('\e[2J') will actually scroll
in a new window (assuming the buffer is bigger than the window, of course).
Subsequent clears will then blank the window. However, if the window has
scrolled, or the cursor is on the last line of the buffer, it will again
scroll in a new window.
Sequences Ignored Sequences Ignored
================= =================
@ -261,7 +267,7 @@ DEC Special Graphics Character Set
Limitations Limitations
=========== ===========
The entire console buffer is used, not just the visible window. Line sequences use the window; column sequences use the buffer.
There's a conflict with NVIDIA's drivers, requiring the setting of the There's a conflict with NVIDIA's drivers, requiring the setting of the
Environment Variable: Environment Variable:
@ -277,7 +283,7 @@ Version History
Legend: + added, - bug-fixed, * changed. Legend: + added, - bug-fixed, * changed.
1.70 - 18 February, 2014: 1.70 - 20 February, 2014:
- don't hook again if using LoadLibrary or LoadLibraryEx; - don't hook again if using LoadLibrary or LoadLibraryEx;
- update the LoadLibraryEx flags that shouldn't hook; - update the LoadLibraryEx flags that shouldn't hook;
- restore original attributes on detach (for LoadLibrary/FreeLibrary usage); - restore original attributes on detach (for LoadLibrary/FreeLibrary usage);
@ -285,12 +291,14 @@ Version History
- an installed ansicon.exe will restore current (not default) attributes; - an installed ansicon.exe will restore current (not default) attributes;
- attributes and saved position are local to each console window; - attributes and saved position are local to each console window;
- improved recognition of unsupported sequences; - improved recognition of unsupported sequences;
- restore cursor to bounds, if size reduced;
* inject into a created process by modifying the import descriptor table * inject into a created process by modifying the import descriptor table
(-p will use CreateRemoteThread); (-p will use CreateRemoteThread);
* log: remove the quotes around the CreateProcess command line; * log: remove the quotes around the CreateProcess command line;
add an underscore in 64-bit addresses to distinguish 8-digit groups; add an underscore in 64-bit addresses to distinguish 8-digit groups;
* ANSICON_EXC can exclude entire programs; * ANSICON_EXC can exclude entire programs;
* switch G1 blank from space (U+0020) to No-Break Space (U+00A0). * switch G1 blank from space (U+0020) to No-Break Space (U+00A0);
* use window height, not buffer.
1.66 - 20 September, 2013: 1.66 - 20 September, 2013:
- fix 32-bit process trying to detect 64-bit process. - fix 32-bit process trying to detect 64-bit process.
@ -478,4 +486,4 @@ Distribution
============================== ==============================
Jason Hood, 18 February, 2014. Jason Hood, 20 February, 2014.