home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d8xx
/
d832
/
term.lha
/
Term
/
term-3.1-Source.lha
/
termEmulation.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-02-18
|
43KB
|
2,477 lines
/*
** termEmulation.c
**
** Terminal emulation (parsing and processing) routines
**
** Copyright © 1990-1993 by Olaf `Olsen' Barthel & MXM
** All Rights Reserved
*/
#include "termGlobal.h"
/* One of the emulation callback routines. */
typedef VOID (* __regargs EPTR)(STRPTR Buffer);
/* This structure describes an ANSI control sequence. */
struct ControlCode
{
UBYTE FirstChar;
STRPTR Match;
UBYTE LastChar;
BYTE ExactSize;
EPTR Func;
};
/* How many characters we will keep in the scan buffer. */
#define MAX_SCAN_SIZE 256
/* Flag indicating whether the cursor has already been
* erased or not.
*/
STATIC BYTE CursorEnabled = FALSE;
/* Global string buffer and backup style. */
STATIC UBYTE GlobalBuffer[40],StyleType = FS_NORMAL;
/* Cursor backup data. */
STATIC struct CursorData CursorBackup;
/* A couple of internally referenced variables. */
STATIC BYTE CharsInBuffer = 0,
ScanStep = 0;
STATIC UBYTE SaveBuffer[MAX_SCAN_SIZE + 1];
/* Character access tables. */
STATIC UBYTE Table0[256] =
{
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
STATIC UBYTE Table1[256] =
{
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
STATIC UBYTE Table2[256] =
{
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
STATIC UBYTE Table3[256] =
{
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
STATIC UBYTE Table4[256] =
{
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,0,0,0,1,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
/* This follows the control code information. */
struct ControlCode ANSICode[] =
{
/* Single Character Sequences. */
'D', Table0, 0 , 1, (EPTR)CursorScrollDown,
'M', Table0, 0 , 1, (EPTR)CursorScrollUp,
'E', Table0, 0 , 1, (EPTR)NextLine,
'7', Table0, 0 , 1, (EPTR)SaveCursor,
'8', Table0, 0 , 1, (EPTR)LoadCursor,
'=', Table0, 0 , 1, (EPTR)NumericAppMode,
'>', Table0, 0 , 1, (EPTR)NumericAppMode,
'N', Table0, 0 , 1, (EPTR)Ignore,
'O', Table0, 0 , 1, (EPTR)Ignore,
'H', Table0, 0 , 1, (EPTR)SetTab,
'Z', Table0, 0 , 1, (EPTR)RequestTerminal,
'c', Table0, 0 , 1, (EPTR)Reset,
'<', Table0, 0 , 1, (EPTR)Ignore,
'~', Table0, 0 , 1, (EPTR)Ignore,
'n', Table0, 0 , 1, (EPTR)Ignore,
'}', Table0, 0 , 1, (EPTR)Ignore,
'o', Table0, 0 , 1, (EPTR)Ignore,
'|', Table0, 0 , 1, (EPTR)Ignore,
/* Double Character Sequences. */
'[', Table0, 's', 2, (EPTR)SaveCursor,
'[', Table0, 'u', 2, (EPTR)LoadCursor,
'(', Table0, 'A', 2, (EPTR)FontStuff,
'(', Table0, 'B', 2, (EPTR)FontStuff,
'(', Table0, '0', 2, (EPTR)FontStuff,
')', Table0, 'A', 2, (EPTR)FontStuff,
')', Table0, 'B', 2, (EPTR)FontStuff,
')', Table0, '0', 2, (EPTR)FontStuff,
'#', Table0, '3', 2, (EPTR)ScaleFont,
'#', Table0, '4', 2, (EPTR)ScaleFont,
'#', Table0, '5', 2, (EPTR)ScaleFont,
'#', Table0, '6', 2, (EPTR)ScaleFont,
'#', Table0, '8', 2, (EPTR)AlignmentTest,
' ', Table0, 'F', 2, (EPTR)Ignore,
' ', Table0, 'G', 2, (EPTR)Ignore,
/* Multiple Character Sequence. */
'[', Table3, 'i', 0, (EPTR)PrinterController,
'[', Table3, 'n', 0, (EPTR)RequestInformation,
'[', Table3, 'c', 0, (EPTR)RequestTerminal,
'[', Table3, 'h', 0, (EPTR)SetSomething,
'[', Table3, 'l', 0, (EPTR)SetSomething,
'[', Table4, 'h', 0, (EPTR)Ignore,
'[', Table1, 'A', 0, (EPTR)MoveCursor,
'[', Table1, 'B', 0, (EPTR)MoveCursor,
'[', Table1, 'C', 0, (EPTR)MoveCursor,
'[', Table1, 'D', 0, (EPTR)MoveCursor,
'[', Table1, 'K', 0, (EPTR)EraseLine,
'[', Table1, 'J', 0, (EPTR)EraseScreen,
'[', Table1, 'P', 0, (EPTR)EraseCharacters,
'[', Table1, '@', 0, (EPTR)InsertCharacters,
'[', Table1, 'L', 0, (EPTR)InsertLine,
'[', Table1, 'M', 0, (EPTR)ClearLine,
'[', Table1, 'g', 0, (EPTR)SetTabs,
'[', Table1, 'q', 0, (EPTR)Ignore,
'[', Table2, 'H', 0, (EPTR)SetAbsolutePosition,
'[', Table2, 'f', 0, (EPTR)SetAbsolutePosition,
'[', Table2, 'm', 0, (EPTR)SetAttributes,
'[', Table2, 'y', 0, (EPTR)Ignore,
'[', Table2, 'r', 0, (EPTR)SetRegion,
'[', Table1, 'S', 0, (EPTR)ScrollUp,
'[', Table1, 'T', 0, (EPTR)ScrollDown
};
STATIC WORD NumCodes = sizeof(ANSICode) / sizeof(struct ControlCode);
/* DoCancel():
*
* Cancel any currently scanned sequence.
*/
BYTE __regargs
DoCancel()
{
InSequence = FALSE;
CharsInBuffer = ScanStep = 0;
return(FALSE);
}
/* CSIFake():
*
* This routine was added to support 8-bit control
* sequences introduced by a CSI character.
*/
VOID
CSIFake()
{
/* Reset scanner */
DoCancel();
/* Perform as if ESC [ had been transmitted. */
InSequence = ParseCode('[');
}
/* ParseCode(UBYTE c):
*
* Input: A character to be passed through the ANSI code
* parser.
*
* Output: FALSE if input characters did form a valid ANSI
* control sequence or if input characters did not
* form an ANSI control sequence at all.
*
* TRUE if input characters did possibly introduce
* a valid ANSI control sequence.
*/
BYTE __regargs
ParseCode(UBYTE c)
{
/* ScanStep = 0: This is the first character
* to introduce a control sequence.
*/
if(!ScanStep)
{
register WORD i;
/* Scan all available codes and try to find
* a match.
*/
for(i = 0 ; i < NumCodes ; i++)
{
/* This character may introduce a
* control sequence.
*/
if(ANSICode[i] . FirstChar == c)
{
/* If this is a single
* character control sequence
* call the approriate function
* and exit immediately.
*/
if(ANSICode[i] . ExactSize == 1)
{
if(Config -> TerminalConfig -> EmulationMode != EMULATION_ATOMIC)
{
SaveBuffer[CharsInBuffer++] = c;
SaveBuffer[CharsInBuffer ] = 0;
(*ANSICode[i] . Func)(SaveBuffer);
}
CharsInBuffer = ScanStep = 0;
return(FALSE);
}
else
{
/* The length of this control
* sequence is greater than
* a single character. Save
* the input character and
* return.
*/
ScanStep = i;
SaveBuffer[CharsInBuffer++] = c;
return(TRUE);
}
}
}
}
else
{
if(CharsInBuffer < MAX_SCAN_SIZE)
{
register WORD i;
/* Scan the remaining codes for a match. */
for(i = ScanStep ; i < NumCodes ; i++)
{
/* This sequence begins with the
* same character the parser was
* initialized with, so let's take
* a look at it.
*/
if(ANSICode[i] . FirstChar == SaveBuffer[0])
{
/* This character is supposed to
* terminate the sequence, so exit.
*/
if(ANSICode[i] . LastChar == c)
{
if(Config -> TerminalConfig -> EmulationMode != EMULATION_ATOMIC)
{
SaveBuffer[CharsInBuffer++] = c;
SaveBuffer[CharsInBuffer ] = 0;
(*ANSICode[i] . Func)(SaveBuffer);
}
CharsInBuffer = ScanStep = 0;
return(FALSE);
}
else
{
/* If this character is part of
* a legal sequence store it
* and return.
*/
if(ANSICode[i] . Match[c])
{
ScanStep = i;
SaveBuffer[CharsInBuffer++] = c;
return(TRUE);
}
}
}
}
}
}
/* Return failure. */
CharsInBuffer = ScanStep = 0;
return(FALSE);
}
/* GetFontWidth():
*
* Get the font width of the current line.
*/
STATIC WORD
GetFontWidth(VOID)
{
if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
{
if(Config -> EmulationConfig -> FontScale == SCALE_HALF)
return((WORD)(TextFontWidth / 2));
else
return(TextFontWidth);
}
else
{
if(Config -> EmulationConfig -> FontScale == SCALE_HALF)
return(TextFontWidth);
else
return((WORD)(TextFontWidth * 2));
}
}
/* ColourValue(UWORD Colour):
*
* Calculate the value of a given colour (brightness).
*/
STATIC WORD __inline
ColourValue(UWORD Colour)
{
BYTE Red,Green,Blue;
WORD Sum;
Red = Colour >> 8;
Green = (Colour >> 4) & 0xF;
Blue = Colour & 0xF;
Sum = (Red + Green + Blue) / 3;
return(Sum);
}
/* ScrollRegion(WORD Direction):
*
* Scroll the current scroll region up or down.
*/
STATIC VOID __inline
ScrollRegion(WORD Direction)
{
WORD RegionTop,RegionBottom,RegionLines;
LONG Dir,MinY,MaxY;
if(Direction < 0)
Dir = -Direction;
else
Dir = Direction;
if(RegionSet)
{
MinY = MUL_Y(Top);
MaxY = MUL_Y(Bottom + 1) - 1;
RegionTop = Top;
RegionBottom = Bottom + 1;
RegionLines = Bottom - Top + 1;
}
else
{
MinY = 0;
MaxY = MUL_Y(LastLine + 1) - 1;
RegionTop = 0;
RegionBottom = LastLine + 1;
RegionLines = LastLine + 1;
}
BackupRender();
RasterScrollRegion(Direction,RegionTop,RegionBottom,RegionLines);
if(Config -> EmulationConfig -> ScrollMode == SCROLL_JUMP || (TextFontHeight & 1))
{
if(Dir > RegionLines)
ScrollLineRectFill(RPort,0,MinY,LastPixel,MaxY);
else
{
if(Direction > 0)
ScrollLineRaster(RPort,0,MUL_Y(Direction),0,MinY,LastPixel,MaxY,FALSE);
else
ScrollLineRaster(RPort,0,-MUL_Y(-Direction),0,MinY,LastPixel,MaxY,FALSE);
}
}
else
{
if(Direction > 0)
ScrollLineRaster(RPort,0,MUL_Y(Direction),0,MinY,LastPixel,MaxY,TRUE);
else
ScrollLineRaster(RPort,0,-MUL_Y(-Direction),0,MinY,LastPixel,MaxY,TRUE);
}
BackupRender();
}
/* LastChar(STRPTR Buffer):
*
* Return the last character in a string.
*/
STATIC UBYTE __inline
LastChar(STRPTR Buffer)
{
WORD Offset = 0;
while(Buffer[Offset])
Offset++;
return(Buffer[Offset - 1]);
}
/* ReadValue(STRPTR Buffer,BYTE *Value):
*
* Parse a buffer for numbers and return a pointer
* to the next buffer element to contain additional
* information.
*/
STATIC STRPTR __inline
ReadValue(STRPTR Buffer,WORD *Value)
{
while((*Buffer < '0' || *Buffer > '9') && (*Buffer != ';') && *Buffer)
Buffer++;
if(*Buffer)
{
*Value = 0;
while(*Buffer >= '0' && *Buffer <= '9')
*Value = (*Value * 10) + (*Buffer++ - '0');
}
else
*Value = -1;
if(*Buffer == ';' || *Buffer == ' ')
return(&Buffer[1]);
else
return(NULL);
}
/* ClipBlitCursor(UBYTE DoClip,UBYTE DoMove):
*
* Change the appearance of the cursor.
*/
VOID __regargs
ClipBlitCursor(UBYTE DoClip,UBYTE DoMove)
{
if(DoClip || DoMove)
{
STATIC WORD LastCursorX = -1,LastCursorY = -1;
STATIC LONG DestX,DestY,XSize,X,Y,Column;
if(CursorY != LastCursorY || CursorX != LastCursorX)
{
if(CursorY != LastCursorY)
{
if(CursorY > LastLine)
Y = LastLine;
else
{
if(CursorY < 0)
Y = 0;
else
Y = CursorY;
}
if(RasterAttr[Y] == SCALE_ATTR_NORMAL)
Column = LastColumn;
else
Column = ((LastColumn + 1) / 2) - 1;
DestY = MUL_Y(Y);
LastCursorY = CursorY;
}
LastCursorX = CursorX;
if(CursorX > Column)
X = Column;
else
{
if(CursorX < 0)
X = 0;
else
X = CursorX;
}
if(Config -> EmulationConfig -> FontScale == SCALE_NORMAL)
{
if(RasterAttr[Y] == SCALE_ATTR_NORMAL)
{
DestX = MUL_X(X);
XSize = TextFontWidth;
}
else
{
DestX = MUL_X(X) * 2;
XSize = TextFontWidth * 2;
if(X > ((LastColumn + 1) / 2) - 1)
X = ((LastColumn + 1) / 2) - 1;
}
}
else
{
if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
{
DestX = MUL_X(X) / 2;
XSize = TextFontWidth / 2;
}
else
{
DestX = MUL_X(X);
XSize = TextFontWidth;
if(X > ((LastColumn + 1) / 2) - 1)
X = ((LastColumn + 1) / 2) - 1;
}
}
}
if(DoMove)
Move(RPort,WindowLeft + DestX,WindowTop + DestY + TextFontBase);
if(DoClip)
{
if(UseMasking)
{
UBYTE Mask = RPort -> Mask;
SetWrMsk(RPort,DepthMask);
ClipBlit(RPort,0,0,RPort,WindowLeft + DestX,WindowTop + DestY,XSize,TextFontHeight,0x50);
SetWrMsk(RPort,Mask);
}
else
ClipBlit(RPort,0,0,RPort,WindowLeft + DestX,WindowTop + DestY,XSize,TextFontHeight,0x50);
}
}
}
/* ClearCursor():
*
* Clear the cursor image.
*/
VOID
ClearCursor()
{
if(CursorEnabled)
{
ClipBlitCursor(TRUE,FALSE);
CursorEnabled = FALSE;
}
}
/* DrawCursor():
*
* Explicitely (re-)draw the cursor image.
*/
VOID
DrawCursor()
{
if(!CursorEnabled)
{
ClipBlitCursor(TRUE,FALSE);
CursorEnabled = TRUE;
}
}
/* BackupRender():
*
* Save current draw modes, pen and position or restore
* the data.
*/
VOID
BackupRender()
{
STATIC BYTE Called = FALSE;
STATIC UBYTE DrMd,
FgPen,
BgPen;
STATIC UWORD OldX,OldY;
STATIC UBYTE Style;
if(!Called)
{
DrMd = ReadDrMd(RPort);
FgPen = ReadAPen(RPort);
BgPen = ReadBPen(RPort);
OldX = RPort -> cp_x - WindowLeft;
OldY = RPort -> cp_y - WindowTop;
Style = StyleType;
Called = TRUE;
}
else
{
if(ReadDrMd(RPort) != DrMd)
SetDrMd(RPort,DrMd);
if(ReadAPen(RPort) != FgPen)
SetAPen(RPort,FgPen);
if(ReadBPen(RPort) != BgPen)
SetBPen(RPort,BgPen);
Move(RPort,OldX + WindowLeft,OldY + WindowTop);
if(Style != StyleType)
{
SetSoftStyle(RPort,Style,0xFF);
StyleType = Style;
}
Called = FALSE;
}
}
/* ShiftChar(LONG Size):
*
* Simulate character insertion at the current cursor
* position by shifting the whole line Size times eight pixels
* to the right.
*/
VOID __regargs
ShiftChar(LONG Size)
{
LONG DeltaX,MinX,MinY;
MinY = MUL_Y(CursorY);
if(Config -> EmulationConfig -> FontScale == SCALE_NORMAL)
{
if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
{
DeltaX = MUL_X(Size);
MinX = MUL_X(CursorX);
}
else
{
DeltaX = MUL_X(Size) * 2;
MinX = MUL_X(CursorX) * 2;
}
}
else
{
if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
{
DeltaX = MUL_X(Size) / 2;
MinX = MUL_X(CursorX) / 2;
}
else
{
DeltaX = MUL_X(Size);
MinX = MUL_X(CursorX);
}
}
if(MinX < WindowWidth)
{
BackupRender();
ScrollLineRaster(RPort,-DeltaX,0,MinX,MinY,LastPixel,MinY + TextFontHeight - 1,FALSE);
BackupRender();
}
}
/* Ignore():
*
* Do nothing, return immediately.
*/
VOID
Ignore()
{
}
/* ScrollDown(STRPTR Buffer):
*
* Scroll the current region down.
*/
VOID __regargs
ScrollDown(STRPTR Buffer)
{
WORD Value;
ReadValue(Buffer,&Value);
if(Value < 1)
Value = 1;
ScrollRegion(-Value);
}
/* ScrollUp(STRPTR Buffer):
*
* Scroll the current region up.
*/
VOID __regargs
ScrollUp(STRPTR Buffer)
{
WORD Value;
ReadValue(Buffer,&Value);
if(Value < 1)
Value = 1;
ScrollRegion(Value);
}
/* CursorScrollDown():
*
* Move cursor down and scroll region if necessary.
*/
VOID
CursorScrollDown()
{
DownLine();
ClipBlitCursor(FALSE,TRUE);
}
VOID
DownLine()
{
UBYTE InRegion = TRUE;
WORD Hit = LastLine;
if(RegionSet)
{
if(CursorY <= Bottom)
Hit = Bottom;
else
InRegion = FALSE;
}
if(CursorY == Hit)
{
if(InRegion)
ScrollRegion(1);
}
else
{
CursorY++;
if(CursorY > LastLine)
CursorY = LastLine;
ConFontScaleUpdate();
}
}
/* CursorScrollUp():
*
* Move cursor up and scroll region if necessary.
*/
VOID
CursorScrollUp()
{
BYTE InRegion = TRUE;
WORD Hit = 0;
if(RegionSet)
{
if(CursorY >= Top)
Hit = Top;
else
InRegion = FALSE;
}
if(CursorY == Hit)
{
if(InRegion)
ScrollRegion(-1);
}
else
{
if(--CursorY < 0)
CursorY = 0;
ConFontScaleUpdate();
}
ClipBlitCursor(FALSE,TRUE);
}
/* NextLine():
*
* Do something like CR+LF.
*/
VOID
NextLine()
{
CursorX = 0;
DownLine();
ClipBlitCursor(FALSE,TRUE);
}
/* SaveCursor():
*
* Save cursor position and rendering attributes.
*/
VOID
SaveCursor()
{
CursorBackup . Charset = Charset;
CursorBackup . Attributes = Attributes;
CursorBackup . CursorX = CursorX;
CursorBackup . CursorY = CursorY;
CursorBackup . Style = StyleType;
CursorBackup . FgPen = GetPenIndex(ReadAPen(RPort));
CursorBackup . BgPen = GetPenIndex(ReadBPen(RPort));
CursorBackup . CurrentFont = CurrentFont;
CursorBackup . CharMode[0] = CharMode[0];
CursorBackup . CharMode[1] = CharMode[1];
}
/* FontStuff(STRPTR Buffer):
*
* Set the drawing font (standard characters/line).
*/
VOID __regargs
FontStuff(STRPTR Buffer)
{
BYTE Changed = FALSE;
if(Buffer[0] == '(')
{
switch(LastChar(Buffer))
{
case 'A':
case 'B':
if(CharMode[0] != TABLE_ASCII && !Charset)
Changed = TRUE;
CharMode[0] = TABLE_ASCII;
break;
case '0':
if(CharMode[0] != TABLE_GFX && !Charset)
Changed = TRUE;
CharMode[0] = TABLE_GFX;
break;
}
}
if(Buffer[0] == ')')
{
switch(LastChar(Buffer))
{
case 'A':
case 'B':
if(CharMode[1] != TABLE_ASCII && Charset == 1)
Changed = TRUE;
CharMode[1] = TABLE_ASCII;
break;
case '0':
if(CharMode[1] != TABLE_GFX && Charset == 1)
Changed = TRUE;
CharMode[1] = TABLE_GFX;
break;
}
}
if(Changed)
{
BackupRender();
if(Charset)
DoShiftIn();
else
DoShiftOut();
BackupRender();
}
}
/* LoadCursor():
*
* Load cursor position and rendering attributes.
*/
VOID
LoadCursor()
{
Charset = CursorBackup . Charset;
CharMode[0] = CursorBackup . CharMode[0];
CharMode[1] = CursorBackup . CharMode[1];
if(CurrentFont != CursorBackup . CurrentFont)
{
CurrentFont = CursorBackup . CurrentFont;
SetFont(RPort,CurrentFont);
ConOutputUpdate();
}
if(StyleType != CursorBackup . Style)
{
SetSoftStyle(RPort,CursorBackup . Style,0xFF);
StyleType = CursorBackup . Style;
}
if(ReadAPen(RPort) != MappedPens[0][CursorBackup . FgPen])
SetAPen(RPort,MappedPens[0][CursorBackup . FgPen]);
if(ReadBPen(RPort) != MappedPens[0][CursorBackup . BgPen])
SetBPen(RPort,MappedPens[0][CursorBackup . BgPen]);
Attributes = CursorBackup . Attributes;
CursorX = CursorBackup . CursorX;
CursorY = CursorBackup . CursorY;
ConFontScaleUpdate();
ClipBlitCursor(FALSE,TRUE);
}
/* ScaleFont(STRPTR Buffer):
*
* Select a new font scale.
*/
VOID __regargs
ScaleFont(STRPTR Buffer)
{
WORD NewScale,Scale;
Scale = RasterAttr[CursorY];
NewScale = Scale;
switch(LastChar(Buffer))
{
case '3':
NewScale = SCALE_ATTR_TOP2X;
break;
case '4':
NewScale = SCALE_ATTR_BOT2X;
break;
case '5':
NewScale = SCALE_NORMAL;
break;
case '6':
NewScale = SCALE_ATTR_2X;
break;
}
if(Scale != NewScale)
{
UBYTE *RasterPtr = &Raster[CursorY * RasterWidth];
WORD RightMargin = LastColumn + 1,
CursorXSave = CursorX;
if(NewScale != SCALE_ATTR_NORMAL)
RightMargin /= 2;
RasterAttr[CursorY] = NewScale;
ConFontScaleUpdate();
if(((Config -> EmulationConfig -> FontScale == SCALE_NORMAL) && (NewScale == SCALE_ATTR_NORMAL)) || ((Config -> EmulationConfig -> FontScale == SCALE_HALF) && (NewScale == SCALE_ATTR_2X)))
{
Move(RPort,WindowLeft,WindowTop + MUL_Y(CursorY) + TextFontBase);
Text(RPort,RasterPtr,RightMargin);
}
else
{
CursorX = 0;
PrintScaled(RasterPtr,RightMargin,NewScale);
}
if(CursorXSave >= RightMargin)
CursorX = RightMargin - 1;
else
CursorX = CursorXSave;
}
ClipBlitCursor(FALSE,TRUE);
}
/* AlignmentTest():
*
* Perform screen alignment test, fill the screen with `E's.
*/
VOID
AlignmentTest()
{
STRPTR Buffer;
if(Buffer = AllocVec(LastColumn + 1,MEMF_ANY))
{
WORD i;
memset(Buffer,'E',LastColumn + 1);
EraseScreen("2");
if(Config -> EmulationConfig -> FontScale == SCALE_HALF)
{
for(i = 0 ; i <= LastLine ; i++)
{
CursorX = 0;
CursorY = i;
RasterAttr[i] = SCALE_ATTR_NORMAL;
RasterPutString(Buffer,LastColumn + 1);
ScrollLinePutString(LastColumn + 1);
Move(RPort,WindowLeft,WindowTop + MUL_Y(i) + TextFontBase);
PrintScaled(Buffer,LastColumn + 1,SCALE_ATTR_NORMAL);
}
}
else
{
for(i = 0 ; i <= LastLine ; i++)
{
CursorX = 0;
CursorY = i;
RasterAttr[i] = SCALE_ATTR_NORMAL;
RasterPutString(Buffer,LastColumn + 1);
ScrollLinePutString(LastColumn + 1);
Move(RPort,WindowLeft,WindowTop + MUL_Y(i) + TextFontBase);
Text(RPort,Buffer,LastColumn + 1);
}
}
CursorX = CursorY = 0;
ClipBlitCursor(FALSE,TRUE);
FreeVec(Buffer);
ConFontScaleUpdate();
}
}
/* SetTab():
*
* Set a tabulator stop at the current position.
*/
VOID
SetTab()
{
if(CursorX < TabStopMax)
TabStops[CursorX] = TRUE;
}
/* RequestTerminal(STRPTR Buffer):
*
* Return the current terminal position.
*/
VOID __regargs
RequestTerminal(STRPTR Buffer)
{
switch(Buffer[0])
{
/* Make ourselves known as a VT200
* terminal.
*/
case '[':
if(Buffer[1] != '>')
SerWrite("\033[?62;1;2;6;7;8;9c",-1);
else
SerWrite("\033[>1;10;0c",-1);
break;
/* This is an old status request type,
* we will return the standard `I am a
* VT101' sequence.
*/
case 'Z':
SerWrite("\033[?1;0c",-1);
break;
}
}
/* SoftReset():
*
* Plain and simple: reset the text rendering colours, style and the
* font being used. This works similar to the Reset() call which
* also clears the screen.
*/
VOID
SoftReset()
{
/* Are we running on an external emulation? */
if(XEmulatorBase && Config -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL)
{
XEmulatorResetTextStyles(XEM_IO);
XEmulatorResetCharset(XEM_IO);
}
else
{
/* Reset the text rendering styles. */
SetAttributes("0m");
Config -> EmulationConfig -> FontScale = SCALE_NORMAL;
ConFontScaleUpdate();
/* Reset the text rendering colours. */
FgPen = GetPenIndex(SafeTextPen);
BgPen = 0;
if(ReadAPen(RPort) != MappedPens[0][FgPen])
SetAPen(RPort,MappedPens[0][FgPen]);
if(ReadBPen(RPort) != MappedPens[0][BgPen])
SetBPen(RPort,MappedPens[0][BgPen]);
SetWrMsk(RPort,DepthMask);
CurrentFont = TextFont;
SetFont(RPort,CurrentFont);
ConOutputUpdate();
}
}
/* Reset():
*
* Reset terminal to initial state.
*/
VOID
Reset()
{
LONG MaxColumns,MaxLines,
Columns,Lines,
i;
CursorEnabled = FALSE;
/* Determine window inner dimensions and top/left edge offsets. */
WindowLeft = Window -> BorderLeft;
WindowTop = Window -> BorderTop;
WindowWidth = Window -> Width - (Window -> BorderLeft + Window -> BorderRight);
WindowHeight = Window -> Height - (Window -> BorderTop + Window -> BorderBottom);
MaxColumns = WindowWidth / TextFontWidth;
MaxLines = WindowHeight / TextFontHeight;
/* Set up the new screen width. */
if(Config -> TerminalConfig -> NumColumns < 20)
Columns = MaxColumns;
else
Columns = Config -> TerminalConfig -> NumColumns;
/* Set up the new screen height. */
if(Config -> TerminalConfig -> NumLines < 20)
Lines = MaxLines;
else
Lines = Config -> TerminalConfig -> NumLines;
/* More columns than we will be able to display? */
if(Columns > MaxColumns)
Columns = MaxColumns;
/* More lines than we will be able to display? */
if(Lines > MaxLines)
Lines = MaxLines;
/* Set up the central data. */
LastColumn = Columns - 1;
LastLine = Lines - 1;
LastPixel = MUL_X(Columns) - 1;
memset(TabStops,FALSE,TabStopMax);
for(i = 8 ; i < TabStopMax ; i += 8)
TabStops[i] = TRUE;
CharMode[0] = TABLE_ASCII;
CharMode[1] = TABLE_GFX;
Charset = 0;
SetAPen(RPort,MappedPens[0][0]);
SetWrMsk(RPort,DepthMask);
RectFill(RPort,WindowLeft,WindowTop,WindowLeft + WindowWidth - 1,WindowTop + WindowHeight - 1);
ScrollLineEraseScreen(2);
RasterEraseScreen(2);
FgPen = GetPenIndex(SafeTextPen);
BgPen = 0;
if(ReadAPen(RPort) != MappedPens[0][FgPen])
SetAPen(RPort,MappedPens[0][FgPen]);
if(ReadBPen(RPort) != MappedPens[0][BgPen])
SetBPen(RPort,MappedPens[0][BgPen]);
if(StyleType != FS_NORMAL)
{
SetSoftStyle(RPort,FS_NORMAL,0xFF);
StyleType = FS_NORMAL;
}
CurrentFont = TextFont;
SetFont(RPort,CurrentFont);
ConOutputUpdate();
UseRegion = FALSE;
RegionSet = FALSE;
Config -> EmulationConfig -> CursorMode = KEYMODE_STANDARD;
Config -> EmulationConfig -> NumericMode = KEYMODE_STANDARD;
Config -> EmulationConfig -> NewLineMode = FALSE;
Config -> EmulationConfig -> InsertMode = FALSE;
Config -> EmulationConfig -> LineWrap = TRUE;
Config -> EmulationConfig -> CursorWrap = FALSE;
Config -> EmulationConfig -> FontScale = SCALE_NORMAL;
Config -> EmulationConfig -> ScrollMode = SCROLL_JUMP;
Attributes = 0;
Top = 0;
Bottom = LastLine;
CursorX = 0;
CursorY = 0;
CursorBackup . Charset = Charset;
CursorBackup . Attributes = Attributes;
CursorBackup . CursorX = CursorX;
CursorBackup . CursorY = CursorY;
CursorBackup . Style = StyleType;
CursorBackup . FgPen = FgPen;
CursorBackup . BgPen = BgPen;
CursorBackup . CurrentFont = CurrentFont;
CursorBackup . CharMode[0] = CharMode[0];
CursorBackup . CharMode[1] = CharMode[1];
ConFontScaleUpdate();
ClipBlitCursor(FALSE,TRUE);
}
/* PrinterController(STRPTR Buffer):
*
* Controls various screen dump and capture functions.
*/
VOID __regargs
PrinterController(STRPTR Buffer)
{
if(Config -> EmulationConfig -> PrinterEnabled)
{
switch(Buffer[1])
{
case 'i':
case '0':
if(RegionSet)
PrintRegion(Top,Bottom + 1);
else
PrintRegion(0,LastLine + 1);
break;
case '5':
OpenPrinterCapture(TRUE);
break;
case '4':
ClosePrinterCapture(FALSE);
break;
}
}
}
/* RequestInformation(STRPTR Buffer):
*
* Request miscellaneous information (state & cursor position).
*/
VOID __regargs
RequestInformation(STRPTR Buffer)
{
WORD Value;
ReadValue(Buffer,&Value);
switch(Value)
{
/* Terminal status report, return code
* for `no malfunction'.
*/
case 5:
SerWrite("\033[0n",-1);
break;
/* The origin is placed at 0/0 and the first
* cursor position is 1/1. We'll have to add
* 1 to our internal positions since our
* universe has been shifted one field to the
* left top corner.
*/
case 6:
SPrintf(GlobalBuffer,"\033[%ld;%ldR",CursorY + 1,CursorX + 1);
SerWrite(GlobalBuffer,-1);
break;
/* A VT200 command: request printer status.
* We will return `the printer is ready' in
* case the printer control commands are
* enabled, else return `no printer connected'.
*/
case 15:
if(Config -> EmulationConfig -> PrinterEnabled)
SerWrite("\033[?10n",-1);
else
SerWrite("\033[?11n",-1);
break;
/* VT200 command: request user defined
* key status. We will return `user
* defined keys are locked'.
*/
case 25:
SerWrite("\033[?21n",-1);
break;
/* Another VT200 command: request
* keyboard language. We will return
* `keyboard language unknown'.
*/
case 26:
SerWrite("\033[?27;0n",-1);
break;
}
}
/* SetSomething(STRPTR Buffer):
*
* Set a terminal option.
*/
VOID __regargs
SetSomething(STRPTR Buffer)
{
switch(Buffer[1])
{
case '?':
switch(Buffer[2])
{
/* Set cursor keys applications mode. */
case '1':
if(Buffer[3] == 'h')
Config -> EmulationConfig -> CursorMode = KEYMODE_APPLICATION;
else
Config -> EmulationConfig -> CursorMode = KEYMODE_STANDARD;
break;
/* Set line length (132 or 80). */
case '3':
if(Buffer[3] == 'h')
{
if(Config -> EmulationConfig -> FontScale != SCALE_HALF)
{
PrivateConfig = Config;
Config -> EmulationConfig -> FontScale = SCALE_HALF;
ScreenSizeStuff();
}
}
else
{
if(Config -> EmulationConfig -> FontScale != SCALE_NORMAL)
{
PrivateConfig = Config;
Config -> EmulationConfig -> FontScale = SCALE_NORMAL;
ScreenSizeStuff();
}
}
CursorX = CursorY = 0;
ClipBlitCursor(FALSE,TRUE);
EraseScreen("2");
break;
/* Set scroll mode (jump or smooth). */
case '4':
if(Buffer[3] == 'h')
Config -> EmulationConfig -> ScrollMode = SCROLL_SMOOTH;
else
Config -> EmulationConfig -> ScrollMode = SCROLL_JUMP;
break;
/* Turn region on or off. */
case '6':
if(Buffer[3] == 'h')
UseRegion = TRUE;
else
UseRegion = FALSE;
ResetCursor();
break;
/* Turn character wrapping on or off. */
case '7':
if(Buffer[3] == 'h')
Config -> EmulationConfig -> LineWrap = TRUE;
else
Config -> EmulationConfig -> LineWrap = FALSE;
break;
/* Set interlaced mode. */
case '9':
if(Buffer[3] == 'h')
{
if(!(Config -> ScreenConfig -> DisplayMode & LACE))
{
if(!ModeNotAvailable(Config -> ScreenConfig -> DisplayMode | LACE))
{
SaveConfig(Config,PrivateConfig);
Config -> ScreenConfig -> DisplayMode |= LACE;
ResetDisplay = TRUE;
}
}
}
else
{
if(Config -> ScreenConfig -> DisplayMode & LACE)
{
if(!ModeNotAvailable(Config -> ScreenConfig -> DisplayMode & ~LACE))
{
SaveConfig(Config,PrivateConfig);
Config -> ScreenConfig -> DisplayMode &= ~LACE;
ResetDisplay = TRUE;
}
}
}
break;
}
break;
case '2':
/* Set newline mode. */
if(Buffer[2] == '0')
{
if(Buffer[3] == 'h')
Config -> EmulationConfig -> NewLineMode = TRUE;
else
Config -> EmulationConfig -> NewLineMode = FALSE;
}
break;
case '4':
/* Set insert mode. */
if(Buffer[2] == 'h')
Config -> EmulationConfig -> InsertMode = TRUE;
else
Config -> EmulationConfig -> InsertMode = FALSE;
break;
case '1':
/* Print region or screen. */
if(Buffer[2] == '9')
{
if(Buffer[3] == 'l')
{
if(RegionSet)
PrintRegion(Top,Bottom + 1);
else
PrintRegion(0,LastLine + 1);
}
if(Buffer[3] == 'h')
PrintRegion(0,LastLine + 1);
}
break;
default:
break;
}
}
/* NumericAppMode(STRPTR Buffer):
*
* Set the numeric pad applications mode.
*/
VOID __regargs
NumericAppMode(STRPTR Buffer)
{
if(*Buffer == '=')
Config -> EmulationConfig -> NumericMode = TRUE;
else
{
if(*Buffer == '>')
Config -> EmulationConfig -> NumericMode = FALSE;
}
}
/* MoveCursor(STRPTR Buffer):
*
* Move the cursor in some direction and stop at
* top/bottom/margin if necessary.
*/
VOID __regargs
MoveCursor(STRPTR Buffer)
{
WORD Value,Hit,LastCharPosition;
BYTE InRegion = TRUE;
ReadValue(Buffer,&Value);
if(Value < 1)
Value = 1;
switch(LastChar(Buffer))
{
/* Move cursor Up value lines */
case 'A':
ScrollUp: Hit = 0;
if(RegionSet)
{
if(CursorY >= Top)
Hit = Top;
else
InRegion = FALSE;
}
CursorY -= Value;
if(CursorY < Hit)
{
Value = CursorY - Hit;
CursorY = Hit;
if(Config -> EmulationConfig -> CursorWrap && InRegion)
ScrollRegion(Value);
}
ConFontScaleUpdate();
break;
/* Move cursor Down value lines */
case 'B':
ScrollDown: Hit = LastLine;
if(RegionSet)
{
if(CursorY <= Bottom)
Hit = Bottom;
else
InRegion = FALSE;
}
CursorY += Value;
if(CursorY > Hit)
{
Value = CursorY - Hit;
CursorY = Hit;
if(Config -> EmulationConfig -> CursorWrap && InRegion)
ScrollRegion(Value);
}
ConFontScaleUpdate();
break;
/* Move cursor Right value columns */
case 'C':
CursorX += Value;
if(CursorX > LastColumn)
{
if(Config -> EmulationConfig -> CursorWrap)
{
Value = CursorX / (LastColumn + 1);
CursorX -= Value * (LastColumn + 1);
goto ScrollDown;
}
else
CursorX = LastColumn;
}
break;
/* Move cursor Left value columns */
case 'D':
CursorX -= Value;
if(CursorX < 0)
{
if(Config -> EmulationConfig -> CursorWrap)
{
Value = CursorX / (LastColumn + 1);
CursorX -= Value * (LastColumn + 1);
Value = -Value;
goto ScrollDown;
}
else
CursorX = 0;
}
break;
}
if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
LastCharPosition = LastColumn;
else
LastCharPosition = ((LastColumn + 1) / 2) - 1;
if(CursorX > LastCharPosition)
CursorX = LastCharPosition;
ClipBlitCursor(FALSE,TRUE);
}
/* EraseLine(STRPTR Buffer):
*
* Erase a line on the display.
*/
VOID __regargs
EraseLine(STRPTR Buffer)
{
WORD Value,Width = GetFontWidth();
ReadValue(Buffer,&Value);
BackupRender();
SetAPen(RPort,MappedPens[0][0]);
switch(Value)
{
case 1:
ScrollLineRectFill(RPort,0,MUL_Y(CursorY),((CursorX + 1) * Width) - 1,MUL_Y(CursorY + 1) - 1);
break;
case 2:
ScrollLineRectFill(RPort,0,MUL_Y(CursorY),LastPixel,MUL_Y(CursorY + 1) - 1);
break;
default:
ScrollLineRectFill(RPort,CursorX * Width,MUL_Y(CursorY),LastPixel,MUL_Y(CursorY + 1) - 1);
break;
}
ScrollLineEraseLine(Value);
RasterEraseLine(Value);
BackupRender();
}
/* EraseScreen(STRPTR Buffer):
*
* Erase parts of the screen.
*/
VOID __regargs
EraseScreen(STRPTR Buffer)
{
WORD Value,Width = GetFontWidth();
ReadValue(Buffer,&Value);
BackupRender();
SetAPen(RPort,MappedPens[0][0]);
switch(Value)
{
case 1:
if(CursorY)
ScrollLineRectFill(RPort,0,0,LastPixel,MUL_Y(CursorY) - 1);
ScrollLineRectFill(RPort,0,MUL_Y(TextFontHeight),((CursorX + 1) * Width) - 1,MUL_Y(CursorY + 1) - 1);
break;
case 2:
ScrollLineRectFill(RPort,0,0,LastPixel,MUL_Y(LastLine + 1) - 1);
break;
default:
ScrollLineRectFill(RPort,CursorX * Width,MUL_Y(CursorY),LastPixel,MUL_Y(CursorY + 1) - 1);
if(CursorY != LastLine)
ScrollLineRectFill(RPort,0,MUL_Y(CursorY + 1),LastPixel,MUL_Y(LastLine + 1) - 1);
break;
}
ScrollLineEraseScreen(Value);
RasterEraseScreen(Value);
BackupRender();
}
/* EraseCharacters(STRPTR Buffer):
*
* Erase a number of characters.
*/
VOID __regargs
EraseCharacters(STRPTR Buffer)
{
WORD Value,Width = GetFontWidth();
ReadValue(Buffer,&Value);
BackupRender();
if(Value < 1)
Value = 1;
RasterEraseCharacters(Value);
ScrollLineEraseCharacters(Value);
ScrollLineRaster(RPort,Value * Width,0,CursorX * Width,MUL_Y(CursorY),LastPixel,MUL_Y(CursorY + 1) - 1,FALSE);
BackupRender();
}
/* InsertCharacters(STRPTR Buffer):
*
* Insert a number of characters.
*/
VOID __regargs
InsertCharacters(STRPTR Buffer)
{
WORD Value,Width = GetFontWidth();
ReadValue(Buffer,&Value);
BackupRender();
if(Value < 1)
Value = 1;
RasterShiftChar(Value);
ScrollLineShiftChar(Value);
ScrollLineRaster(RPort,-Value * Width,0,CursorX * Width,MUL_Y(CursorY),LastPixel,MUL_Y(CursorY + 1) - 1,FALSE);
BackupRender();
}
/* InsertLine(STRPTR Buffer):
*
* Insert a number of lines and scroll the rest of the
* display down.
*/
VOID __regargs
InsertLine(STRPTR Buffer)
{
WORD Value,RegionBottom,RegionTop,TheTop = CursorY;
ReadValue(Buffer,&Value);
BackupRender();
SetAPen(RPort,MappedPens[0][0]);
if(Value < 1)
Value = 1;
if(RegionSet)
{
RegionTop = Top;
RegionBottom = Bottom + 1;
}
else
{
RegionTop = 0;
RegionBottom = LastLine + 1;
}
if(TheTop < RegionTop)
TheTop = RegionTop;
RasterInsertLine(Value,TheTop);
ScrollLineRaster(RPort,0,-MUL_Y(Value),0,MUL_Y(TheTop),LastPixel,MUL_Y(RegionBottom) - 1,FALSE);
BackupRender();
}
/* ClearLine(STRPTR Buffer):
*
* Clear a number of lines and scroll up the ones below it.
*/
VOID __regargs
ClearLine(STRPTR Buffer)
{
WORD Value,RegionBottom,RegionTop,TheTop = CursorY;
ReadValue(Buffer,&Value);
BackupRender();
SetAPen(RPort,MappedPens[0][0]);
if(Value < 1)
Value = 1;
if(RegionSet)
{
RegionTop = Top;
RegionBottom = Bottom + 1;
}
else
{
RegionTop = 0;
RegionBottom = LastLine + 1;
}
if(TheTop < RegionTop)
TheTop = RegionTop;
RasterClearLine(Value,TheTop);
ScrollLineRaster(RPort,0,MUL_Y(Value),0,MUL_Y(TheTop),LastPixel,MUL_Y(RegionBottom) - 1,FALSE);
BackupRender();
}
/* SetTabs(STRPTR Buffer):
*
* Set the current tab stops.
*/
VOID __regargs
SetTabs(STRPTR Buffer)
{
WORD Value;
ReadValue(Buffer,&Value);
if(Value < 1)
Value = 0;
switch(Value)
{
case 0:
if(CursorX < TabStopMax)
TabStops[CursorX] = FALSE;
break;
case 3:
memset(TabStops,FALSE,TabStopMax);
break;
default:
break;
}
}
/* SetAbsolutePosition(STRPTR Buffer):
*
* Move the cursor to a given location on the display,
* this routine ignores the current scroll region
* settings.
*/
VOID __regargs
SetAbsolutePosition(STRPTR Buffer)
{
WORD Value;
Buffer = ReadValue(Buffer,&Value);
if(UseRegion && RegionSet)
CursorY = Top;
else
CursorY = 0;
CursorX = 0;
if(Value != -1)
{
/* Our raster origin is 0/0 instead of 1/1. */
if(Value)
Value--;
if(UseRegion && RegionSet)
CursorY = Top + Value;
else
CursorY = Value;
if(Buffer)
{
ReadValue(Buffer,&Value);
if(Value > 0)
CursorX = Value - 1;
else
CursorX = 0;
}
/* Truncate illegal positions. */
if(CursorX > LastColumn)
CursorX = LastColumn;
if(CursorY > LastLine)
CursorY = LastLine;
}
ConFontScaleUpdate();
ClipBlitCursor(FALSE,TRUE);
}
/* SetAttributes(STRPTR Buffer):
*
* Set the current display rendering attributes.
*/
VOID __regargs
SetAttributes(STRPTR Buffer)
{
LONG TextFlags = FS_NORMAL;
WORD Value;
do
{
Buffer = ReadValue(Buffer,&Value);
if(Value == -1)
Value = 0;
switch(Value)
{
case 0:
FgPen = GetPenIndex(SafeTextPen);
BgPen = 0;
Attributes = 0;
break;
case 1:
Attributes |= ATTR_HIGHLIGHT;
break;
case 4:
Attributes |= ATTR_UNDERLINE;
break;
case 5:
Attributes |= ATTR_BLINK;
break;
case 7:
if(!(Attributes & ATTR_INVERSE))
{
BYTE Help;
Help = FgPen;
FgPen = BgPen;
BgPen = Help;
}
Attributes |= ATTR_INVERSE;
break;
default:
if(Value >= 30)
{
if(Value <= 37)
{
if(Attributes & ATTR_INVERSE)
BgPen = Value - 30;
else
FgPen = Value - 30;
}
else
{
if(Value >= 40 && Value <= 47)
{
if(Attributes & ATTR_INVERSE)
FgPen = Value - 40;
else
BgPen = Value - 40;
}
}
}
break;
}
}
while(Buffer);
/* Make sure that the text rendered will be
* visible by wrapping the colour if
* necessary.
*/
if(FgPen > DepthMask && !(FgPen & DepthMask))
FgPen = GetPenIndex(SafeTextPen);
if(BgPen > DepthMask && !(BgPen & DepthMask))
BgPen = GetPenIndex(SafeTextPen);
if(Attributes & ATTR_UNDERLINE)
TextFlags |= FSF_UNDERLINED;
if(Attributes & ATTR_HIGHLIGHT)
{
if(Config -> ScreenConfig -> ColourMode == COLOUR_SIXTEEN)
{
if(Attributes & ATTR_INVERSE)
BgPen |= 8;
else
FgPen |= 8;
}
else
TextFlags |= FSF_BOLD;
}
if(Attributes & ATTR_BLINK)
{
if(Config -> TerminalConfig -> EmulationMode == EMULATION_ANSIVT100)
{
switch(Config -> ScreenConfig -> ColourMode)
{
case COLOUR_AMIGA:
if(Attributes & ATTR_INVERSE)
BgPen = 3;
else
FgPen = 3;
break;
case COLOUR_EIGHT:
if(Attributes & ATTR_INVERSE)
BgPen |= 8;
else
FgPen |= 8;
break;
case COLOUR_MONO:
if(Attributes & ATTR_INVERSE)
BgPen = GetPenIndex(SafeTextPen);
else
FgPen = GetPenIndex(SafeTextPen);
break;
}
}
}
if(TextFlags != StyleType)
{
SetSoftStyle(RPort,TextFlags,0xFF);
StyleType = TextFlags;
}
if(Config -> ScreenConfig -> ColourMode == COLOUR_MONO)
{
if(ColourValue(MappedPens[0][FgPen]) < ColourValue(MappedPens[0][BgPen]))
{
if(Attributes & ATTR_INVERSE)
{
FgPen = GetPenIndex(SafeTextPen);
BgPen = 0;
}
else
{
FgPen = 0;
BgPen = GetPenIndex(SafeTextPen);
}
}
else
{
if(Attributes & ATTR_INVERSE)
{
FgPen = 0;
BgPen = GetPenIndex(SafeTextPen);
}
else
{
FgPen = GetPenIndex(SafeTextPen);
BgPen = 0;
}
}
}
if(MappedPens[0][FgPen] != ReadAPen(RPort))
SetAPen(RPort,MappedPens[0][FgPen]);
if(MappedPens[0][BgPen] != ReadBPen(RPort))
SetBPen(RPort,MappedPens[0][BgPen]);
ClipBlitCursor(FALSE,TRUE);
}
/* SetRegion(STRPTR Buffer):
*
* Set the current scroll region top and bottom.
*/
VOID __regargs
SetRegion(STRPTR Buffer)
{
WORD NewTop,Value,NewBottom = LastLine;
Buffer = ReadValue(Buffer,&Value);
if(!Value)
Value = 1;
if(Value > 0)
{
if(Buffer)
{
NewTop = Value - 1;
ReadValue(Buffer,&Value);
if(Value > 0)
NewBottom = Value - 1;
if(NewBottom > LastLine)
NewBottom = LastLine;
if(NewTop > LastLine)
NewTop = LastLine;
}
else
{
NewTop = 0;
NewBottom = LastLine;
}
}
else
{
NewTop = 0;
NewBottom = LastLine;
}
if(NewTop < NewBottom)
{
if(NewTop != 0 || NewBottom != LastLine)
{
Top = NewTop;
Bottom = NewBottom;
RegionSet = TRUE;
}
else
UseRegion = RegionSet = FALSE;
ResetCursor();
}
else
RegionSet = FALSE;
}
/* ResetCursor():
*
* Reset cursor to top of screen.
*/
VOID
ResetCursor()
{
CursorX = 0;
if(UseRegion && RegionSet)
CursorY = Top;
else
CursorY = 0;
ConFontScaleUpdate();
ClipBlitCursor(FALSE,TRUE);
}