home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d5xx
/
d534
/
term.lha
/
Term
/
Source.LZH
/
Console.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-07-17
|
18KB
|
1,184 lines
/* $Revision Header * Header built automatically - do not edit! *************
*
* (C) Copyright 1990 by Olaf 'Olsen' Barthel & MXM
*
* Name .....: Console.c
* Created ..: Monday 21-Jan-91 20:12
* Revision .: 1
*
* Date Author Comment
* ========= ======== ====================
* 14-Apr-91 Olsen Rewrote double-dead-key support.
* 05-Feb-91 Olsen Added double-dead-key support.
* 21-Jan-91 Olsen Created this file!
*
* $Revision Header ********************************************************/
#include "TermGlobal.h"
/* Capture(APTR Buffer,LONG Size):
*
* Send the buffer contents to the display/disk capture.
*/
VOID
Capture(APTR Buffer,LONG Size)
{
struct MenuItem *SomeItem;
/* We are parsing a control sequence, don't buffer it! */
if(!InSequence)
StoreBuffer(Buffer,Size);
/* Write to capture file. */
if(FileCapture)
{
if(!FWrite(FileCapture,Buffer,Size,1))
{
BlockWindows();
/* We had an error writing to the file. */
switch(MyEasyRequest(NULL,"Error writing to capture\nfile %s!","Ignore Error|Close & Discard File|Close File",CaptureName))
{
case 0: break;
case 1: Close(FileCapture);
DeleteFile(CaptureName);
if(SomeItem = FindThisItem(MEN_CAPTUREDISK))
SomeItem -> Flags &= ~CHECKED;
FileCapture = NULL;
break;
case 2: Close(FileCapture);
if(SomeItem = FindThisItem(MEN_CAPTUREDISK))
SomeItem -> Flags &= ~CHECKED;
FileCapture = NULL;
if(!GetFileSize(CaptureName))
DeleteFile(CaptureName);
break;
}
ReleaseWindows();
}
}
/* Send the buffer to the printer (ignore ANSI control
* sequences).
*/
if(PrinterCapture)
{
if(*((UBYTE *)Buffer) != '\033' && !InSequence)
{
if(!FWrite(FileCapture,Buffer,Size,1))
{
BlockWindows();
if(!MyEasyRequest(NULL,"Error writing to printer!","Ignore Error|Close Printer"))
{
Close(PrinterCapture);
if(SomeItem = FindThisItem(MEN_CAPTUREPRINTER))
SomeItem -> Flags &= ~CHECKED;
PrinterCapture = NULL;
}
ReleaseWindows();
}
}
}
}
/* HandleCursor(UBYTE Char):
*
* This routine handles the somewhat strange behaviour of
* an assorted set of keys in VT100 applications mode.
*/
BYTE
HandleCursor(UBYTE Char)
{
STATIC struct
{
UBYTE Char;
UBYTE *VanillaString;
UBYTE *ApplicationString;
} Table[18] =
{
CUP, "\033[A", "\033OA",
CDN, "\033[B", "\033OB",
CFW, "\033[C", "\033OC",
CBK, "\033[D", "\033OD",
'0', "0", "\033Op",
'1', "1", "\033Oq",
'2', "2", "\033Or",
'3', "3", "\033Os",
'4', "4", "\033Ot",
'5', "5", "\033Ou",
'6', "6", "\033Ov",
'7', "7", "\033Ow",
'8', "8", "\033Ox",
'9', "9", "\033Oy",
'-', "-", "\033Om",
'*', "*", "\033Ol",
'.', ".", "\033On",
'\r', "\r", "\033OM"
};
BYTE i;
/* Look for the cursor keys first. */
for(i = 0 ; i < 4 ; i++)
{
if(Table[i] . Char == Char)
{
if(Config . CursorApp)
SerWrite(Table[i] . ApplicationString,strlen(Table[i] . ApplicationString));
else
SerWrite(Table[i] . VanillaString,strlen(Table[i] . VanillaString));
return(TRUE);
}
}
/* Then take a look at the numeric pad. */
for(i = 4 ; i < 18 ; i++)
{
if(Table[i] . Char == Char)
{
if(Config . NumApp)
SerWrite(Table[i] . ApplicationString,strlen(Table[i] . ApplicationString));
else
{
if(i == 17)
{
switch(Config . SendCR)
{
case CR_IGNORE: break;
case CR_ASCR: SerWrite("\r",1);
break;
case CR_ASCRLF: SerWrite("\r\n",2);
break;
}
}
else
SerWrite(Table[i] . VanillaString,strlen(Table[i] . VanillaString));
}
return(TRUE);
}
}
return(FALSE);
}
/* DoBackspace():
*
* Special function: perform backspace.
*/
VOID
DoBackspace()
{
Capture("\b",1);
if(CursorX)
{
ClearCursor();
CursorX--;
/* If destructive, shift the remaining line
* one character to the right.
*/
if(Config . DestructiveBackspace)
{
BackupRender();
SetBPen(RPort,0);
RasterEraseCharacters(1);
ScrollRaster(RPort,8,0,CursorX * 8,CursorY * 8,Window -> Width - 1,(CursorY + 1) * 8 - 1);
BackupRender();
}
SetCursor();
}
}
/* Raise(UWORD Colour):
*
* Make an RGB value brighter.
*/
STATIC UWORD
Raise(UWORD Colour)
{
SHORT r,g,b;
r = ((Colour >> 8) & 0xF) + 4;
g = ((Colour >> 4) & 0xF) + 4;
b = ((Colour ) & 0xF) + 4;
if(r > 15)
r = 15;
if(g > 15)
g = 15;
if(b > 15)
b = 15;
return(r << 8 | g << 4 | b);
}
/* VisualBeep():
*
* `Beep' the screen visually.
*/
STATIC BYTE
VisualBeep()
{
struct UCopList *UserCopperList;
/* Create a user copper list. */
if(UserCopperList = (struct UCopList *)AllocMem(sizeof(struct UCopList),MEMF_PUBLIC|MEMF_CLEAR))
{
SHORT i;
/* Initialize for 35 commands. */
CINIT(UserCopperList,2 + 16 + 16 + 1);
/* Wait until first line of window. */
CWAIT(UserCopperList,Window -> TopEdge,0);
/* Set the light colours. */
for(i = 0 ; i < 16 ; i++)
CMOVE(UserCopperList,custom . color[i],Raise(GetRGB4(Screen -> ViewPort . ColorMap,i)));
/* Wait until bottom of window. */
CWAIT(UserCopperList,Window -> TopEdge + Window -> Height - 1,0);
/* Set the standard colours. */
for(i = 0 ; i < 16 ; i++)
CMOVE(UserCopperList,custom . color[i],GetRGB4(Screen -> ViewPort . ColorMap,i));
/* Finish list. */
CEND(UserCopperList);
/* Lock the screen. */
LockLayers(&Screen -> LayerInfo);
/* Install user copper list... */
Screen -> ViewPort . UCopIns = UserCopperList;
/* ...and display it. */
RethinkDisplay();
return(TRUE);
}
}
/* DoSomeBeep():
*
* Special function: beep the terminal.
*/
VOID
DoSomeBeep()
{
/* Handle the visual part. */
if(Config . VisibleBell)
{
if(VisualBeep())
{
if(Config . AudibleBell)
Beep();
Delay(25);
/* Remove the copper list. */
FreeVPortCopLists(&Screen -> ViewPort);
/* Really remove it. */
RemakeDisplay();
/* Unlock screen layers. */
UnlockLayers(&Screen -> LayerInfo);
}
else
{
if(Config . AudibleBell)
Beep();
}
}
else
{
/* Let it beep. */
if(Config . AudibleBell)
Beep();
Delay(25);
}
if(!Config . CaptureFilter)
Capture("\a",1);
}
/* DoLF():
*
* Special function: perform line feed.
*/
VOID
DoLF()
{
ClearCursor();
if(UseRegion)
{
if(CursorY == Bottom)
ScrollRegion(8);
else
{
CursorY++;
SetCursor();
}
}
else
{
if(CursorY == LastLine)
ScrollRegion(8);
else
{
CursorY++;
SetCursor();
}
}
}
/* DoIgnore():
*
* Special function: don't do anything.
*/
VOID
DoIgnore()
{
}
/* DoCR_LF():
*
* Special function: perform carriage return and line feed.
*/
VOID
DoCR_LF()
{
ClearCursor();
CursorX = 0;
if(UseRegion)
{
if(CursorY == Bottom)
ScrollRegion(8);
else
{
CursorY++;
SetCursor();
}
}
else
{
if(CursorY == LastLine)
ScrollRegion(8);
else
{
CursorY++;
SetCursor();
}
}
if(Config . CaptureFilter)
Capture("\n",1);
else
Capture("\r\n",2);
}
/* DoFF():
*
* Special function: perform form feed.
*/
VOID
DoFF()
{
ClearCursor();
if(Config . NewLine)
{
CursorX = 0;
if(UseRegion)
{
if(CursorY == Bottom)
ScrollRegion(8);
else
{
CursorY++;
SetCursor();
}
}
else
{
if(CursorY == LastLine)
ScrollRegion(8);
else
{
CursorY++;
SetCursor();
}
}
if(Config . CaptureFilter)
Capture("\n",1);
else
Capture("\r\n",2);
}
else
{
EraseScreen("2");
CursorX = CursorY = 0;
SetCursor();
if(Config . CaptureFilter)
Capture("\n",1);
else
Capture("\f",1);
}
}
/* DoLF_FF_VT():
*
* Special function: handle line feed, form feed and vertical
* tab.
*/
VOID
DoLF_FF_VT()
{
if(Config . NewLine)
DoCR_LF();
else
DoLF();
}
/* DoCR():
*
* Special function: handle carriage return.
*/
VOID
DoCR()
{
if(Config . NewLine)
DoCR_LF();
else
{
ClearCursor();
CursorX = 0;
SetCursor();
if(Config . CaptureFilter)
Capture("\n",1);
else
Capture("\r",1);
}
}
/* DoTab():
*
* Special function: handle tab, move cursor to next
* tab stop.
*/
VOID
DoTab()
{
ClearCursor();
if(CursorX < LastColumn)
{
SHORT i;
for(i = CursorX + 1 ; i <= LastColumn ; i++)
{
if(TabStops[i])
{
CursorX = i;
SetCursor();
Capture("\t",1);
return;
}
}
}
Capture("\t",1);
CursorX = 0;
if(UseRegion)
{
if(CursorY == Bottom)
ScrollRegion(8);
else
{
CursorY++;
SetCursor();
}
}
else
{
if(CursorY == LastLine)
ScrollRegion(8);
else
{
CursorY++;
SetCursor();
}
}
}
/* SpillTheBeans(UBYTE *Buffer,LONG Size):
*
* Output a buffer of given size to the terminal
* window.
*/
VOID
SpillTheBeans(UBYTE *Buffer,LONG Size)
{
/* The slow method: insert characters at of the
* initial cursor position and shift the remaining
* screen characters to the right.
*/
if(Config . InsertChar)
{
/* Do we still have a character in the
* magnificient buffer?
*/
while(Size--)
{
/* Shift the character(s) over. */
if(CursorX != LastColumn)
{
RasterShiftChar();
ShiftChar();
}
/* The cursor hasn't hit the right
* margin, has it? So let's print a
* single character.
*/
ClearCursor();
if(CursorX++ <= LastColumn)
{
/* Real-time font scaling
* enabled?
*/
if(Config . FontScale)
{
if(CursorX != LastColumn)
{
RasterShiftChar();
ShiftChar();
}
CursorX--;
PrintScaled(*Buffer++);
}
else
{
RasterPutString(Buffer,1);
Text(RPort,Buffer,1);
Buffer++;
}
}
else
{
/* Cursor is positioned at
* the right hand side of the
* display. If auto-wrap is
* enabled, perform some
* kind of CR/LF, else leave
* the cursor where it is.
*/
if(Config . AutoWrap)
{
if(UseRegion)
{
if(CursorY == Bottom)
ScrollRegion(8);
else
CursorY++;
Capture("\n",1);
}
else
{
if(CursorY == LastLine)
ScrollRegion(8);
else
CursorY++;
Capture("\n",1);
}
CursorX = 0;
}
else
CursorX = LastColumn;
}
SetCursor();
}
}
else
{
/* Do we still have a character in the
* magnificient buffer?
*/
while(Size > 0)
{
/* Cursor is positioned at
* the right hand side of the
* display. If auto-wrap is
* enabled, perform some
* kind of CR/LF, else leave
* the cursor where it is and
* quit the show.
*/
ClearCursor();
if(CursorX > LastColumn)
{
if(Config . AutoWrap)
{
CursorX = 0;
if(UseRegion)
{
if(CursorY == Bottom)
ScrollRegion(8);
else
{
CursorY++;
SetCursor();
}
Capture("\n",1);
}
else
{
if(CursorY == LastLine)
ScrollRegion(8);
else
{
CursorY++;
SetCursor();
}
Capture("\n",1);
}
}
else
{
CursorX = LastColumn;
SetCursor();
return;
}
}
else
{
/* Real-time font scaling
* enabled?
*/
if(Config . FontScale)
{
while(CursorX <= LastColumn && Size)
{
PrintScaled(*Buffer++);
Size--;
}
SetCursor();
}
else
{
SHORT Offset;
/* We won't have to take
* care of characters to shift.
* We'll collect as many
* characters in the buffer as will
* fit into the current line
* and print them.
*/
if((Offset = LastColumn + 1 - CursorX) > Size)
Offset = Size;
RasterPutString(Buffer,Offset);
Text(RPort,Buffer,Offset);
Size -= Offset;
CursorX += Offset;
SetCursor();
}
}
}
}
}
/* ConWrite(APTR Buffer,LONG Size):
*
* Write a string to the console window.
*/
VOID
ConWrite(APTR Buffer,LONG Size)
{
STATIC UBYTE StringBuffer[200],BufSize = 0;
UBYTE *Char = Buffer;
/* Run down the buffer. */
while(Size--)
{
/* Are we parsing a control sequence? */
if(InSequence)
{
if(*Char == ESC)
{
DoCancel();
InSequence = TRUE;
if(!Config . CaptureFilter)
Capture("\033",1);
}
else
{
if(!Config . CaptureFilter)
Capture(Char,1);
/* See if we are already done. */
InSequence = ParseCode(*Char++);
}
}
else
{
/* This looks like a control sequence
* introducing character.
*/
if(*Char == ESC || *Char == CSI)
{
if(BufSize)
{
Capture(&StringBuffer[0],BufSize);
SpillTheBeans(&StringBuffer[0],BufSize);
BufSize = 0;
}
/* So we're in TTY mode,
* escape the `escape' character
* and continue.
*/
if(Config . Emulation == EMULATION_TTY)
{
if(*Char == ESC)
{
StringBuffer[BufSize++] = '^';
StringBuffer[BufSize++] = '[';
if(!Config . CaptureFilter)
Capture("\033",1);
}
else
{
/* Fake a CSI. */
StringBuffer[BufSize++] = '^';
StringBuffer[BufSize++] = '[';
if(!Config . CaptureFilter)
Capture("\033[",2);
}
}
else
{
if(*Char == ESC)
{
InSequence = TRUE;
if(!Config . CaptureFilter)
Capture("\033",1);
}
else
CSIFake();
}
Char++;
}
else
{
/* Stuff the character into
* the buffer.
*/
StringBuffer[BufSize++] = *Char++;
/* If buffer is full, spill it. */
if(BufSize == 200)
{
Capture(&StringBuffer[0],BufSize);
SpillTheBeans(&StringBuffer[0],BufSize);
BufSize = 0;
}
}
}
}
/* Any characters in the buffer we didn't process yet? */
if(!InSequence && BufSize)
{
Capture(&StringBuffer[0],BufSize);
SpillTheBeans(&StringBuffer[0],BufSize);
BufSize = 0;
}
}
/* ConProcess(UBYTE *String,LONG Size):
*
* Process the contents of a string to be sent to the
* console window.
*/
VOID
ConProcess(UBYTE *String,LONG Size)
{
LONG i,j;
/* In quiet mode no characters are echoed to the
* console window, they are just passed through
* the data flow filter. This mode is enabled
* by the dial panel.
*/
if(Quiet)
{
for(i = 0 ; i < Size ; i++)
FlowFilter(String[i]);
}
else
{
/* If the current font is Topaz, some bytes
* will need to be filtered since they are not
* defined as valid ASCII characters.
*/
if(Config . Font == FONT_TOPAZ)
{
for(i = 0, j = 0 ; i < Size ; i++)
{
FlowFilter(String[i]);
if(IsPrintable(String[i]))
{
/* This character is
* associated with a
* special function
* (bell, xon, xoff, etc.).
*/
if(SpecialMap[String[i]] != -1)
{
if(j)
{
ConWrite(SharedBuffer,j);
j = 0;
}
SpecialKeys[SpecialMap[String[i]]] . Routine();
}
else
{
/* Put the character
* into the buffer
* and empty it if
* necessary.
*/
SharedBuffer[j] = String[i];
if(j++ == 512)
{
ConWrite(SharedBuffer,j);
j = 0;
}
}
}
}
}
else
{
/* In IBM font mode, any character gives
* a sensible result.
*/
for(i = 0, j = 0 ; i < Size ; i++)
{
FlowFilter(String[i]);
if(SpecialMap[String[i]] != -1)
{
if(j)
{
ConWrite(SharedBuffer,j);
j = 0;
}
SpecialKeys[SpecialMap[String[i]]] . Routine();
}
else
{
SharedBuffer[j] = String[i];
if(j++ == 512)
{
ConWrite(SharedBuffer,j);
j = 0;
}
}
}
}
if(j)
ConWrite(SharedBuffer,j);
}
}
/* ConWrites(UBYTE *String,...):
*
* Output a string to the console.
*/
VOID __stdargs
ConWrites(UBYTE *String,...)
{
va_list VarArgs;
va_start(VarArgs,String);
VSPrintf(SharedBuffer,String,VarArgs);
va_end(VarArgs);
ConProcess(SharedBuffer,strlen(SharedBuffer));
}
/* KeyConvert(struct IntuiMessage *Massage,UBYTE *Buffer):
*
* Convert a raw key information according to the
* current keymap settings.
*/
UBYTE
KeyConvert(struct IntuiMessage *Massage,UBYTE *Buffer)
{
if(Buffer)
Buffer[0] = 0;
if(Massage -> Class == IDCMP_RAWKEY)
{
/* These are the sequences mapped to special
* control keys (cursor keys, function keys,
* the help key).
*/
STATIC struct
{
UBYTE *RawCode;
UBYTE Result;
} ConversionTable[16] =
{
(UBYTE *)"A", CUP,
(UBYTE *)"B", CDN,
(UBYTE *)"C", CFW,
(UBYTE *)"D", CBK,
(UBYTE *)"?~", HLP,
(UBYTE *)"0~", FN1,
(UBYTE *)"1~", FN2,
(UBYTE *)"2~", FN3,
(UBYTE *)"3~", FN4,
(UBYTE *)"4~", FN5,
(UBYTE *)"5~", FN6,
(UBYTE *)"6~", FN7,
(UBYTE *)"7~", FN8,
(UBYTE *)"8~", FN9,
(UBYTE *)"9~", F10
};
/* Key was pressed, not released. */
if(!(Massage -> Code & IECODE_UP_PREFIX))
{
UBYTE ConvertBuffer[257],i;
ULONG Qualifier = Massage -> Qualifier;
/* If it's a function key clear the qualifier. */
if(Massage -> Code >= 80 && Massage -> Code <= 89)
Qualifier = 0;
/* Clear the buffer. */
memset(&ConvertBuffer[0],0,257);
/* Convert the key. */
FakeInputEvent -> ie_Code = Massage -> Code;
FakeInputEvent -> ie_Qualifier = Qualifier;
FakeInputEvent -> ie_position . ie_addr = *((APTR *)Massage -> IAddress);
if(RawKeyConvert(FakeInputEvent,(UBYTE *)ConvertBuffer,257,NULL) > 0)
{
if(ConvertBuffer[0])
{
if(Buffer)
strcpy(Buffer,ConvertBuffer);
/* Translated sequence starts
* with a CSI, let's have a look
* at the associated control
* key.
*/
if(ConvertBuffer[0] == CSI)
{
for(i = 0 ; i < 16 ; i++)
{
if(!StrCmp(&ConvertBuffer[1],ConversionTable[i] . RawCode))
{
ConvertBuffer[0] = ConversionTable[i] . Result;
if(Buffer)
{
Buffer[0] = ConversionTable[i] . Result;
Buffer[1] = 0;
}
break;
}
}
}
return(ConvertBuffer[0]);
}
}
}
}
return(0);
}