839 lines
23 KiB
C
839 lines
23 KiB
C
#define WIN32_ONLY
|
|
#include <posix/sys/types.h>
|
|
#include <posix/termios.h>
|
|
#include "psxses.h"
|
|
#include "ansiio.h"
|
|
#include <io.h>
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
|
|
extern DWORD OutputModeFlags; /* Console Output Mode */
|
|
extern DWORD InputModeFlags;
|
|
extern unsigned char AnsiNewMode;
|
|
extern struct termios SavedTermios;
|
|
|
|
/* DFC: New globals (from trans.h) */
|
|
WORD ansi_attr; /* attribute of TTY */
|
|
WORD ansi_attr1; /* MSKK : leave space for 3 attr */
|
|
WORD ansi_attr2; /* MSKK : leave space for 3 attr */
|
|
SHORT ScreenColNum; /* col number */
|
|
SHORT ScreenRowNum; /* row number */
|
|
BYTE CarriageReturn;
|
|
|
|
COORD TrackedCoord,
|
|
CurrentCoord;
|
|
|
|
DWORD TTYConBeep(void);
|
|
|
|
static BYTE ColorTable[8] = { 0, /* Black */
|
|
4, /* Red */
|
|
2, /* Green */
|
|
6, /* Yellow */
|
|
1, /* Blue */
|
|
5, /* Magenta */
|
|
3, /* Cyan */
|
|
7}; /* White */
|
|
|
|
DWORD
|
|
TermioInit(void)
|
|
{
|
|
CONSOLE_SCREEN_BUFFER_INFO ScreenInfo1;
|
|
BOOL Success;
|
|
|
|
ansi_state = NOCMD; /* state of machine */
|
|
ignore_next_char = 0;
|
|
#if 0
|
|
ansi_base = ansi_attr = 0x07; /* white on black */
|
|
#endif
|
|
ansi_reverse = 0;
|
|
|
|
InputModeFlags = (ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
|
|
OutputModeFlags ^= ENABLE_WRAP_AT_EOL_OUTPUT;
|
|
AnsiNewMode = FALSE;
|
|
|
|
if (!SetConsoleMode(hConsoleInput, InputModeFlags)) {
|
|
KdPrint(("posix - can't set console mode: 0x%x\n", GetLastError()));
|
|
}
|
|
|
|
/* Set default termio parameters */
|
|
SavedTermios.c_iflag = BRKINT|ICRNL;
|
|
SavedTermios.c_oflag = OPOST|ONLCR;
|
|
SavedTermios.c_cflag = CREAD|CS8;
|
|
SavedTermios.c_lflag = ICANON|ECHO|ECHOE|ECHOK|ISIG;
|
|
|
|
SavedTermios.c_cc[VEOF] = CTRL('Z');
|
|
SavedTermios.c_cc[VEOL] = 0; // _POSIX_VDISABLE
|
|
SavedTermios.c_cc[VERASE] = CTRL('H');
|
|
SavedTermios.c_cc[VINTR] = CTRL('C');
|
|
SavedTermios.c_cc[VKILL] = CTRL('X');
|
|
SavedTermios.c_cc[VQUIT] = CTRL('\\');
|
|
SavedTermios.c_cc[VSUSP] = CTRL('Y');
|
|
SavedTermios.c_cc[VSTOP] = CTRL('S');
|
|
SavedTermios.c_cc[VSTART] = CTRL('Q');
|
|
|
|
SavedTermios.c_ospeed = B9600;
|
|
SavedTermios.c_ispeed = B9600;
|
|
|
|
Success = GetConsoleScreenBufferInfo(hConsoleOutput, &ScreenInfo1);
|
|
if (!Success) {
|
|
return Success;
|
|
}
|
|
|
|
ansi_base = ansi_attr = ScreenInfo1.wAttributes;
|
|
ansi_attr1 = ansi_attr2 = 0;
|
|
|
|
ScreenRowNum = ScreenInfo1.dwSize.Y;
|
|
ScreenColNum = ScreenInfo1.dwSize.X;
|
|
|
|
CurrentCoord.Y = TrackedCoord.Y = ScreenInfo1.dwCursorPosition.Y + 1;
|
|
CurrentCoord.X = TrackedCoord.X = ScreenInfo1.dwCursorPosition.X + 1;
|
|
|
|
return (DWORD) 0;
|
|
}
|
|
|
|
/*
|
|
** TermOutput(SourStr, cnt) - pass characters to the finite state machine
|
|
** SourStr points to the array of characters
|
|
** cnt indicates how many characters are being passed.
|
|
*/
|
|
|
|
DWORD
|
|
TermOutput(
|
|
IN HANDLE cs,
|
|
IN LPSTR SourStr,
|
|
IN DWORD cnt)
|
|
{
|
|
register CHAR c;
|
|
USHORT NewCoord, ToFlash;
|
|
DWORD Rc = 0, orig_cnt = cnt;
|
|
BOOL SetModeOn, OldWrap, NewWrap;
|
|
CONSOLE_SCREEN_BUFFER_INFO ScreenInfo1;
|
|
|
|
//
|
|
// Kludge because we don't know how many carriage returns we received
|
|
// as input, thereby impeding TermOutput()'s ability to track the
|
|
// cursor coordinate accurately
|
|
//
|
|
|
|
GetConsoleScreenBufferInfo(cs, &ScreenInfo1);
|
|
CurrentCoord.Y = TrackedCoord.Y = ScreenInfo1.dwCursorPosition.Y + 1;
|
|
CurrentCoord.X = TrackedCoord.X = ScreenInfo1.dwCursorPosition.X + 1;
|
|
|
|
NewCoord = 0;
|
|
CarriageReturn = 0;
|
|
TTYOldCtrlCharInStr = TRUE;
|
|
TTYCtrlCharInStr = FALSE;
|
|
TTYcs = cs;
|
|
TTYTextPtr = SourStr;
|
|
TTYNumBytes = 0;
|
|
|
|
//
|
|
// Stop output, if VSTOP has been encountered
|
|
//
|
|
|
|
if (bStop) {
|
|
RtlEnterCriticalSection(&StopMutex);
|
|
if (bStop) {
|
|
RtlLeaveCriticalSection(&StopMutex);
|
|
WaitForSingleObject(hStopEvent, INFINITE);
|
|
} else {
|
|
RtlLeaveCriticalSection(&StopMutex);
|
|
}
|
|
}
|
|
|
|
SetModeOn = FALSE;
|
|
while (cnt--) {
|
|
c = *SourStr++;
|
|
|
|
switch (ansi_state) {
|
|
case NOCMD:
|
|
if (c == ANSI_ESC) {
|
|
//
|
|
// Make sure buffer is flushed and cursor position is
|
|
// up-to-date before processing next esc-seq
|
|
//
|
|
if ( (Rc = TTYFlushStr(&NewCoord, "1")) != 0 ) {
|
|
KdPrint(("PSXSES(trans-TTY): failed on "
|
|
"TTYFlushStr #1\n"));
|
|
return (DWORD) -1;
|
|
}
|
|
ansi_state = ESCED;
|
|
break;
|
|
} else {
|
|
if (isprint(c)) { /* Printable char found */
|
|
|
|
TTYNumBytes++;
|
|
TrackedCoord.X++;
|
|
|
|
} else {
|
|
/* Non-printable char found */
|
|
|
|
ToFlash = TRUE;
|
|
switch ( c ) {
|
|
case '\n':
|
|
new_line:
|
|
if (SavedTermios.c_oflag & OPOST) {
|
|
if (c == '\n' &&
|
|
(SavedTermios.c_oflag & ONLCR)) {
|
|
TrackedCoord.Y++;
|
|
goto carriage_return;
|
|
}
|
|
if (SavedTermios.c_oflag & ONLRET) {
|
|
#if 0
|
|
TrackedCoord.X = 1;
|
|
#endif
|
|
CarriageReturn = 1;
|
|
}
|
|
}
|
|
TrackedCoord.Y++;
|
|
NewCoord = 1;
|
|
break;
|
|
|
|
case '\r':
|
|
carriage_return:
|
|
if ( SavedTermios.c_oflag & OPOST ) {
|
|
if ( c == '\r' &&
|
|
(SavedTermios.c_oflag & OCRNL) ) {
|
|
goto new_line;
|
|
} else if ( ! (SavedTermios.c_oflag & ONOCR) ||
|
|
TrackedCoord.X != 1 ) {
|
|
#if 0
|
|
TrackedCoord.X = 1;
|
|
#endif
|
|
NewCoord = 1;
|
|
CarriageReturn = 1;
|
|
}
|
|
} else {
|
|
if ( TrackedCoord.X > 1 ) {
|
|
TrackedCoord.X = 1;
|
|
NewCoord = 1;
|
|
CarriageReturn = 1;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case '\b':
|
|
if ( TrackedCoord.X > 1 ) {
|
|
TrackedCoord.X--;
|
|
NewCoord = 1;
|
|
}
|
|
break;
|
|
|
|
case '\t':
|
|
TrackedCoord.X += (8 - ((TrackedCoord.X - 1) % 8));
|
|
|
|
// Handle wrap after tab
|
|
|
|
if (TrackedCoord.X > ScreenColNum) {
|
|
if (OutputModeFlags & ENABLE_WRAP_AT_EOL_OUTPUT) {
|
|
TrackedCoord.Y += ((TrackedCoord.X) / ScreenColNum);
|
|
TrackedCoord.X = (TrackedCoord.X % ScreenColNum);
|
|
} else {
|
|
TrackedCoord.X = ScreenColNum;
|
|
}
|
|
}
|
|
NewCoord = 1;
|
|
break;
|
|
|
|
case '\a':
|
|
if ( (Rc = TTYConBeep()) != 0 ) {
|
|
KdPrint(("PSXSES(trans-TTY): failed on "
|
|
"BEEP\n"));
|
|
return (DWORD) -1;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
TTYCtrlCharInStr = TRUE;
|
|
ToFlash = FALSE;
|
|
#if 0
|
|
TTYNumBytes++;
|
|
TrackedCoord.X++;
|
|
#endif
|
|
break;
|
|
} /* switch */
|
|
|
|
if ( ToFlash ) { /* Flush */
|
|
//
|
|
// Flush carriage control chars to update cursor
|
|
// position
|
|
//
|
|
if ((Rc = TTYFlushStr(&NewCoord, "2")) != 0) {
|
|
return (DWORD)-1;
|
|
}
|
|
|
|
TTYTextPtr = SourStr;
|
|
}
|
|
} /* isprint */
|
|
} /* ANSI_ESC */
|
|
break;
|
|
|
|
case ESCED:
|
|
switch ( c ) {
|
|
case '[':
|
|
ansi_state = PARAMS;
|
|
SetModeOn = TRUE;
|
|
clrparam();
|
|
break;
|
|
|
|
default:
|
|
ansi_state = NOCMD;
|
|
TTYTextPtr = SourStr - 1;
|
|
cnt++ ;
|
|
SourStr--;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case PARAMS:
|
|
if ( isdigit(c) ) {
|
|
ansi_param[ansi_pnum] *= 10;
|
|
ansi_param[ansi_pnum] += (c - '0');
|
|
SetModeOn = FALSE;
|
|
} else if ( c == ';' ) {
|
|
if ( ansi_pnum < (NPARMS - 1) )
|
|
++ansi_pnum;
|
|
else {
|
|
ansi_state = NOCMD;
|
|
TTYTextPtr = SourStr;
|
|
}
|
|
} else if ( (c == '=') && SetModeOn ) { /* maybe set/reset mode */
|
|
ansi_state = MODCMD;
|
|
} else {
|
|
ansi_state = NOCMD;
|
|
if ( (Rc = ansicmd(cs, c)) != 0 ) {
|
|
return (DWORD) -1;
|
|
}
|
|
TTYTextPtr = SourStr;
|
|
NewCoord = 1;
|
|
if ( (Rc = TTYFlushStr(&NewCoord, "3")) != 0 ) {
|
|
#if 0
|
|
return (DWORD) -1;
|
|
#endif
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MODCMD:
|
|
if ( ansi_pnum == 1 ) {
|
|
|
|
if ( c == 'h' || c == 'l' ) {
|
|
|
|
if ( ansi_param[0] == 7 ) {
|
|
|
|
OldWrap = ((OutputModeFlags &
|
|
ENABLE_WRAP_AT_EOL_OUTPUT) != 0);
|
|
NewWrap = (c == 'h');
|
|
|
|
if ( OldWrap != NewWrap ) {
|
|
|
|
if ( (Rc = !SetConsoleMode(cs,
|
|
OutputModeFlags^ENABLE_WRAP_AT_EOL_OUTPUT))
|
|
!= 0 ) {
|
|
return (DWORD) -1;
|
|
}
|
|
|
|
OutputModeFlags ^= ENABLE_WRAP_AT_EOL_OUTPUT;
|
|
#if 0
|
|
} else {
|
|
OutputModeFlags ~= ENABLE_WRAP_AT_EOL_OUTPUT;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
TTYTextPtr = SourStr;
|
|
|
|
} else {
|
|
TTYTextPtr = SourStr - 5;
|
|
TTYNumBytes = 5;
|
|
}
|
|
|
|
} else if ( c >= '0' && c <= '7' ) {
|
|
ansi_param[0] = (USHORT) (c - '0');
|
|
ansi_pnum = 1;
|
|
break;
|
|
} else {
|
|
TTYTextPtr = SourStr - 4;
|
|
TTYNumBytes = 4;
|
|
}
|
|
ansi_state = NOCMD;
|
|
break;
|
|
|
|
case MODDBCS:
|
|
TTYNumBytes++;
|
|
TrackedCoord.X++;
|
|
ansi_state = NOCMD;
|
|
break;
|
|
|
|
} /* switch ansi_state */
|
|
|
|
} /* while cnt */
|
|
|
|
/* Flush */
|
|
if ( (Rc = TTYFlushStr(&NewCoord, "4")) != 0 ) {
|
|
return (DWORD) -1;
|
|
}
|
|
|
|
return(orig_cnt);
|
|
}
|
|
|
|
/*
|
|
** clrparam(lp) - clear the parameters for a screen
|
|
** lp points to the screen's crt struct
|
|
*/
|
|
|
|
VOID
|
|
clrparam(void)
|
|
{
|
|
register int i;
|
|
|
|
for ( i = 0; i < NPARMS; i += 1 )
|
|
ansi_param[i] = 0;
|
|
ansi_pnum = 0;
|
|
}
|
|
|
|
//
|
|
// lscroll - scroll the sceen
|
|
//
|
|
void
|
|
lscroll(
|
|
HANDLE h, // handle on the console buffer to scroll
|
|
int lines // number of lines to scroll (negative means
|
|
// scroll text down)
|
|
)
|
|
{
|
|
COORD coordDest;
|
|
SMALL_RECT ScrollRect;
|
|
CHAR_INFO ScrollChar;
|
|
BOOLEAN Success;
|
|
|
|
if (0 == lines) {
|
|
// already done
|
|
return;
|
|
}
|
|
|
|
if (lines < 0) {
|
|
// scroll text down
|
|
ScrollRect.Top = 0;
|
|
ScrollRect.Bottom = ScreenRowNum + lines;
|
|
coordDest.X = 0;
|
|
coordDest.Y = 0 - lines;
|
|
} else {
|
|
// scroll text up
|
|
ScrollRect.Top = (SHORT)lines;
|
|
ScrollRect.Bottom = ScreenRowNum;
|
|
coordDest.X = 0;
|
|
coordDest.Y = 0;
|
|
}
|
|
|
|
ScrollRect.Left = 0;
|
|
ScrollRect.Right = ScreenColNum;
|
|
|
|
ScrollChar.Attributes = (ansi_attr);
|
|
ScrollChar.Char.AsciiChar = ' ';
|
|
|
|
Success = ScrollConsoleScreenBufferA(h, &ScrollRect, NULL,
|
|
coordDest, &ScrollChar) ? TRUE : FALSE;
|
|
if (!Success) {
|
|
KdPrint(("POSIX: ScrollConsole: 0x%x\n", GetLastError()));
|
|
}
|
|
return;
|
|
}
|
|
|
|
//
|
|
// ansicmd - perform some ANSI 3.64 function, using the parameters
|
|
// we've just gathered.
|
|
//
|
|
// c is the character that indicates the function to be performed
|
|
//
|
|
|
|
DWORD
|
|
ansicmd(
|
|
IN HANDLE cs,
|
|
IN CHAR c
|
|
)
|
|
{
|
|
DWORD NumFilled, Rc = 0;
|
|
USHORT j;
|
|
COORD Coord;
|
|
|
|
switch (c) {
|
|
case ANSI_CUB: /* cursor backward */
|
|
TrackedCoord.X -= (short) range(ansi_param[0], 1, 1, TrackedCoord.X - 1);
|
|
break;
|
|
|
|
case ANSI_CUF: /* cursor forward */
|
|
TrackedCoord.X += (short) range(ansi_param[0], 1, 1,
|
|
ScreenColNum - TrackedCoord.X );
|
|
break;
|
|
|
|
case ANSI_CUU: /* cursor up */
|
|
TrackedCoord.Y -= (short) range(ansi_param[0], 1, 1, TrackedCoord.Y - 1);
|
|
break;
|
|
|
|
case ANSI_CUD: /* cursor down */
|
|
TrackedCoord.Y += (short) range(ansi_param[0], 1, 1,
|
|
ScreenRowNum - TrackedCoord.Y);
|
|
break;
|
|
|
|
case ANSI_CUP: /* cursor position */
|
|
case ANSI_CUP1:
|
|
TrackedCoord.Y = (USHORT) range(ansi_param[0], 1, 1, ScreenRowNum);
|
|
TrackedCoord.X = (USHORT) range(ansi_param[1], 1, 1, ScreenColNum);
|
|
break;
|
|
|
|
case ANSI_ED: /* erase display */
|
|
switch ( ansi_param[0] ) {
|
|
case 2:
|
|
TrackedCoord.Y = TrackedCoord.X = 1;
|
|
Coord.X = (SHORT) (TrackedCoord.X - 1);
|
|
Coord.Y = (SHORT) (TrackedCoord.Y - 1);
|
|
if ( (Rc = (!FillConsoleOutputCharacterA(cs, ' ',
|
|
(DWORD) ScreenRowNum * ScreenColNum, Coord, &NumFilled)))
|
|
!= 0 ) {
|
|
return (Rc);
|
|
}
|
|
|
|
if ( (Rc = (!FillConsoleOutputAttribute(cs, (ansi_attr),
|
|
NumFilled, Coord, &NumFilled))) != 0 ) {
|
|
|
|
return (Rc);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case ANSI_EL:
|
|
Coord.X = (SHORT)(TrackedCoord.X - 1);
|
|
Coord.Y = (SHORT)(TrackedCoord.Y - 1);
|
|
|
|
switch ( ansi_param[0] ) {
|
|
case 0: /* up to end */
|
|
if ( (Rc = (!FillConsoleOutputCharacterA(cs, ' ',
|
|
(DWORD) (ScreenColNum - Coord.X), Coord, &NumFilled))) != 0 ) {
|
|
return (Rc);
|
|
}
|
|
|
|
if ( (Rc = (!FillConsoleOutputAttribute(cs, (ansi_attr),
|
|
NumFilled, Coord, &NumFilled))) != 0 ) {
|
|
|
|
return (Rc);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case ANSI_SGR:
|
|
// SGR = Select Graphic Rendition
|
|
|
|
for ( j = 0; (SHORT) j <= (SHORT) ansi_pnum; j++ ) {
|
|
SetTTYAttr(cs, ansi_param[j]);
|
|
}
|
|
break;
|
|
|
|
#if 0
|
|
case ANSI_SCP:
|
|
ansi_scp = TrackedCoord;
|
|
break;
|
|
|
|
case ANSI_RCP:
|
|
TrackedCoord = ansi_scp;
|
|
break;
|
|
case ANSI_CPL: /* cursor to previous line */
|
|
TrackedCoord.Y -= range(ansi_param[0], 1, 1, ScreenRowNum);
|
|
TrackedCoord.X = 1;
|
|
break;
|
|
|
|
case ANSI_CNL: /* cursor to next line */
|
|
TrackedCoord.Y += range(ansi_param[0], 1, 1, ScreenRowNum);
|
|
TrackedCoord.X = 1;
|
|
break;
|
|
|
|
case ANSI_CBT: /* tab backwards */
|
|
col = TrackedCoord.X - 1;
|
|
i = range(ansi_param[0], 1, 1, (col + 7) >> 3);
|
|
if ( col & 7 ) {
|
|
TrackedCoord.X = (col & ~7) + 1;
|
|
--i;
|
|
}
|
|
TrackedCoord.X -= (i << 3);
|
|
break;
|
|
|
|
case ANSI_DCH: /* delete character */
|
|
ansi_param[0] = range(ansi_param[0], 1, 1,
|
|
(ScreenColNum - TrackedCoord.X) + 1);
|
|
if ( TrackedCoord.X + ansi_param[0] <= ScreenColNum ) {
|
|
lcopy(cs, lp, TrackedCoord.X+ansi_param[0]-1, TrackedCoord.Y-1,
|
|
TrackedCoord.X-1, TrackedCoord.Y-1,
|
|
ScreenColNum-(TrackedCoord.X+ansi_param[0]-1));
|
|
}
|
|
lclear(cs, lp, ScreenColNum-ansi_param[0], TrackedCoord.Y-1,
|
|
ansi_param[0], SA_BONW);
|
|
break;
|
|
|
|
case ANSI_DL: /* delete line */
|
|
ansi_param[0] = range(ansi_param[0], 1, 1,
|
|
(ScreenRowNum - TrackedCoord.Y) + 1);
|
|
/* copy lines up */
|
|
if ( TrackedCoord.Y + ansi_param[0] <= ScreenRowNum ) {
|
|
lcopy(cs, lp, 0, TrackedCoord.Y+ansi_param[0]-1, 0,
|
|
TrackedCoord.Y-1,
|
|
ScreenColNum*(ScreenRowNum-(TrackedCoord.Y+ansi_param[0]-1)));
|
|
}
|
|
/* clear new stuff */
|
|
lclear(cs, lp, 0, ScreenRowNum-ansi_param[0],
|
|
ScreenColNum*ansi_param[0], SA_BONW);
|
|
break;
|
|
|
|
case ANSI_ECH: /* erase character */
|
|
ansi_param[0] = range( ansi_param[0], 1, 1,
|
|
(ScreenColNum - TrackedCoord.X) + 1);
|
|
lclear(cs, lp, TrackedCoord.X-1, TrackedCoord.Y-1, ansi_param[0],
|
|
SA_BONW);
|
|
break;
|
|
|
|
case ANSI_ICH: /* insert character */
|
|
ansi_param[0] = range( ansi_param[0], 1, 1,
|
|
(ScreenColNum - TrackedCoord.X) + 1);
|
|
if ( TrackedCoord.X + ansi_param[0] <= ScreenColNum ) {
|
|
lcopy(cs, lp, TrackedCoord.X-1, TrackedCoord.Y-1,
|
|
TrackedCoord.X+ansi_param[0]-1, TrackedCoord.Y-1,
|
|
ScreenColNum-(TrackedCoord.X+ansi_param[0]-1));
|
|
}
|
|
lclear(cs, lp, TrackedCoord.X-1, TrackedCoord.Y-1, ansi_param[0],
|
|
SA_BONW);
|
|
break;
|
|
|
|
case ANSI_IL: /* insert line */
|
|
ansi_param[0] = range(ansi_param[0], 1, 1,
|
|
(ScreenRowNum - TrackedCoord.Y) + 1);
|
|
/* copy lines down */
|
|
if ( TrackedCoord.Y + ansi_param[0] <= ScreenRowNum ) {
|
|
lcopy(cs, lp, 0, TrackedCoord.Y-1, 0,
|
|
TrackedCoord.Y+ansi_param[0]-1,
|
|
ScreenColNum*(ScreenRowNum-(TrackedCoord.Y+ansi_param[0]-1)));
|
|
}
|
|
/* clear new stuff */
|
|
lclear(cs, lp, 0, TrackedCoord.Y-1, ScreenColNum * ansi_param[0],
|
|
SA_BONW);
|
|
break;
|
|
#endif
|
|
|
|
case ANSI_SU: /* scroll up */
|
|
ansi_param[0] = (short) range(ansi_param[0], 1, 1, ScreenRowNum);
|
|
lscroll(cs, ansi_param[0]);
|
|
break;
|
|
|
|
case ANSI_SD: /* scroll down */
|
|
{
|
|
int i = -range(ansi_param[0], 1, 1, ScreenRowNum);
|
|
lscroll(cs, i);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return (DWORD) 0;
|
|
}
|
|
return (Rc);
|
|
}
|
|
|
|
/*
|
|
** range(val, default, min, max) - restrict a value to a range, or supply a
|
|
** default
|
|
** val is the value to be restricted.
|
|
** default is the value to be returned if val is zero
|
|
** min is the minimum value
|
|
** max is the maximum value
|
|
*/
|
|
|
|
int
|
|
range(int val, int def, int min, int max)
|
|
{
|
|
if ( val == 0 )
|
|
return def;
|
|
if ( val < min )
|
|
return min;
|
|
if ( val > max )
|
|
return max;
|
|
return val;
|
|
}
|
|
|
|
DWORD
|
|
SetTTYAttr(IN HANDLE cs, IN USHORT AnsiParm)
|
|
{
|
|
WORD NewAttr, LastAttr = ansi_attr; /* attribute of TTY */
|
|
BOOL Rc;
|
|
|
|
if ( AnsiParm == 0 ) { // BUGBUG ? or the default is according to Win
|
|
ansi_base = 0x07; /* white on black */
|
|
ansi_reverse = 0x00;
|
|
} else if ( AnsiParm == 7 ) {
|
|
ansi_reverse = 1;
|
|
} else if ( ((AnsiParm >= 30) && (AnsiParm <= 37)) ||
|
|
((AnsiParm >= 40) && (AnsiParm <= 47)) ) {
|
|
if ( AnsiParm >= 40 )
|
|
ansi_base = (BYTE) ((ansi_base & 0x0F) | ( 4 << ColorTable[AnsiParm%10]));
|
|
else
|
|
ansi_base = (BYTE) ((ansi_base & 0xF0) | ColorTable[AnsiParm%10]);
|
|
} else if ( AnsiParm == 8 ) {
|
|
#if 0
|
|
ansi_cancel = 1;
|
|
#endif
|
|
} else if ( AnsiParm == 1 ) {
|
|
#if 0
|
|
ansi_intensity = 1;
|
|
#endif
|
|
} else if ( AnsiParm == 4 ) {
|
|
#if 0
|
|
ansi_bold = 1;
|
|
#endif
|
|
} else if ( AnsiParm == 5 ) {
|
|
#if 0
|
|
ansi_underscore = 1;
|
|
#endif
|
|
}
|
|
|
|
if ( ansi_reverse )
|
|
NewAttr = (BYTE) (((ansi_base & 0x0F) << 4 ) |
|
|
((ansi_base & 0xF0) >> 4 ));
|
|
else
|
|
NewAttr = ansi_base;
|
|
|
|
if ( LastAttr != NewAttr ) {
|
|
/* new attribute */
|
|
if ( (Rc = !SetConsoleTextAttribute(cs, (NewAttr))) != 0 ) {
|
|
return (Rc);
|
|
} else {
|
|
ansi_attr = NewAttr;
|
|
}
|
|
}
|
|
return (NO_ERROR);
|
|
}
|
|
|
|
DWORD
|
|
TTYConBeep(void)
|
|
{
|
|
DWORD NumWritten, Rc;
|
|
CHAR BeepChar = '\a';
|
|
|
|
Rc = !WriteConsoleA(TTYcs, &BeepChar, 1, &NumWritten, NULL);
|
|
|
|
return(Rc);
|
|
}
|
|
|
|
|
|
DWORD
|
|
TTYFlushStr(USHORT *newcoord, const char *call)
|
|
{
|
|
DWORD NumWritten;
|
|
BOOL Success;
|
|
COORD coordDest, coord;
|
|
SMALL_RECT ScrollRect;
|
|
CHAR_INFO ScrollChar;
|
|
|
|
if (TTYNumBytes) {
|
|
if (TrackedCoord.X > ScreenColNum) {
|
|
|
|
// Handle cursor tracking of text wrap-around
|
|
|
|
if (OutputModeFlags & ENABLE_WRAP_AT_EOL_OUTPUT) {
|
|
#if 0
|
|
TrackedCoord.Y += ((CurrentCoord.X + TrackedCoord.X)
|
|
/ ScreenColNum);
|
|
#else
|
|
TrackedCoord.Y += ((TrackedCoord.X) / ScreenColNum);
|
|
#endif
|
|
TrackedCoord.X = (TrackedCoord.X % ScreenColNum);
|
|
} else {
|
|
TrackedCoord.X = ScreenColNum;
|
|
}
|
|
*newcoord = 1;
|
|
} else if (TrackedCoord.X < 1) {
|
|
TrackedCoord.X = 1;
|
|
#if 0
|
|
*newcoord = 1;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
//
|
|
// Handle scrolling when printing beyond bottom of screen
|
|
//
|
|
|
|
if (TrackedCoord.Y > ScreenRowNum) {
|
|
#if 0
|
|
ScrollRect.Top = TrackedCoord.Y - ScreenRowNum;
|
|
ScrollRect.Bottom = (SHORT)ScreenRowNum;
|
|
ScrollRect.Left = 0;
|
|
ScrollRect.Right = (SHORT)ScreenColNum;
|
|
coordDest.X = 0;
|
|
coordDest.Y = 0;
|
|
ScrollChar.Attributes = (ansi_attr);
|
|
ScrollChar.Char.AsciiChar = ' ';
|
|
|
|
Success = ScrollConsoleScreenBufferA(TTYcs, &ScrollRect, NULL,
|
|
coordDest, &ScrollChar);
|
|
if (!Success) {
|
|
KdPrint(("POSIX: ScrollConsole: 0x%x\n", GetLastError()));
|
|
return Success;
|
|
}
|
|
#else
|
|
lscroll(TTYcs, TrackedCoord.Y - ScreenRowNum);
|
|
#endif
|
|
|
|
if (TTYNumBytes) {
|
|
coord.X = CurrentCoord.X - 1;
|
|
coord.Y = ScreenRowNum - (TrackedCoord.Y - ScreenRowNum) - 1;
|
|
|
|
Success = WriteConsoleOutputCharacterA(TTYcs, (LPSTR)TTYTextPtr,
|
|
TTYNumBytes, coord, &NumWritten);
|
|
if (!Success) {
|
|
KdPrint(("POSIX: WriteConsoleOutputChar: 0x%x\n", GetLastError()));
|
|
return Success;
|
|
}
|
|
|
|
TTYNumBytes = 0;
|
|
}
|
|
TrackedCoord.Y = ScreenRowNum;
|
|
#if 0
|
|
*newcoord = 1;
|
|
#endif
|
|
} else if (TTYNumBytes) {
|
|
|
|
// Not printing beyond bottom of screen.
|
|
|
|
Success = WriteConsoleA(TTYcs, (LPSTR) TTYTextPtr, TTYNumBytes,
|
|
&NumWritten, NULL);
|
|
if (!Success) {
|
|
return Success;
|
|
}
|
|
TTYNumBytes = 0;
|
|
}
|
|
|
|
if (*newcoord) {
|
|
if (CarriageReturn) {
|
|
CarriageReturn = 0;
|
|
TrackedCoord.X = 1;
|
|
}
|
|
|
|
coord.X = TrackedCoord.X - 1;
|
|
coord.Y = TrackedCoord.Y - 1;
|
|
|
|
Success = SetConsoleCursorPosition(TTYcs, coord);
|
|
if (!Success) {
|
|
return Success;
|
|
}
|
|
*newcoord = 0;
|
|
}
|
|
|
|
CurrentCoord = TrackedCoord;
|
|
|
|
return (DWORD)0;
|
|
}
|