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
/
termConsole.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-02-19
|
41KB
|
2,339 lines
/*
** termConsole.c
**
** High-level terminal console routines
**
** Copyright © 1990-1993 by Olaf `Olsen' Barthel & MXM
** All Rights Reserved
*/
#include "termGlobal.h"
/* Character set modes. */
enum { MODE_STANDARD,MODE_GFX };
/* Hints for the data flow scanner. */
STATIC WORD ScanStart,
ScanEnd;
STATIC WORD AttentionCount[SCAN_COUNT],
AttentionLength[SCAN_COUNT],
FlowCount;
/* Temporary console working buffer. */
STATIC UBYTE ConTempBuffer[512];
/* Text output data. */
STATIC UBYTE CurrentFontScale,FontScalingRequired;
STATIC WORD LastPrintableColumn;
/* ConTranslateSetup():
*
* Set up for buffer translation.
*/
STATIC VOID __inline
ConTranslateSetup(struct TranslationHandle *Handle,STRPTR SourceBuffer,LONG SourceLen,STRPTR DestinationBuffer,LONG DestinationLen,struct TranslationEntry **Table)
{
Handle -> LocalBuffer = NULL;
Handle -> LocalLen = 0;
Handle -> SourceBuffer = SourceBuffer;
Handle -> SourceLen = SourceLen;
Handle -> DestinationBuffer = DestinationBuffer;
Handle -> DestinationLen = DestinationLen;
Handle -> Table = Table;
}
/* ConTranslateBuffer(struct TranslationHandle *Handle):
*
* Translate buffer contents according to
* translation table contents.
*/
STATIC LONG __inline
ConTranslateBuffer(struct TranslationHandle *Handle)
{
register STRPTR Data = Handle -> DestinationBuffer;
register LONG BytesWritten = 0;
register struct TranslationEntry *Entry;
/* Are we to return any translated data? */
while(Handle -> LocalLen && BytesWritten < Handle -> DestinationLen)
{
/* Decrement number of bytes in buffer. */
Handle -> LocalLen--;
/* Return next character. */
*Data++ = *Handle -> LocalBuffer++;
/* Add another byte. */
BytesWritten++;
}
/* Loop until done. */
while(Handle -> SourceLen && BytesWritten < Handle -> DestinationLen)
{
/* Another byte eaten. */
Handle -> SourceLen--;
/* Get table entry. */
if(Entry = Handle -> Table[*Handle -> SourceBuffer++])
{
/* Copy to local data area. */
Handle -> LocalBuffer = Entry -> String;
Handle -> LocalLen = Entry -> Len;
/* Translate the data. */
while(Handle -> LocalLen && BytesWritten < Handle -> DestinationLen)
{
/* Decrement number of bytes in buffer. */
Handle -> LocalLen--;
/* Return next character. */
*Data++ = *Handle -> LocalBuffer++;
/* Add another byte. */
BytesWritten++;
}
}
}
return(BytesWritten);
}
/* FlowFilter(register STRPTR Data,register LONG Size,UBYTE Mask):
*
* Data flow filter.
*/
STATIC VOID __regargs
FlowFilter(register STRPTR Data,register LONG Size,register UBYTE Mask)
{
register UBYTE c;
/* Run until done. */
do
{
if(c = (*Data++ & Mask))
{
/* We already got a `CONNECT' and the
* `connect auto-baud' feature is enabled.
* Continue scanning the serial output
* data for the actual baud rate.
*/
if(BaudPending)
{
if(c < ' ')
{
if(BaudCount)
BaudCount--;
while(BaudCount > 0 && BaudBuffer[BaudCount] == ' ')
BaudCount--;
BaudBuffer[BaudCount + 1] = 0;
FlowInfo . Connect = TRUE;
FlowInfo . Changed = TRUE;
BaudPending = FALSE;
DTERate = GetBaudRate(BaudBuffer);
}
else
{
if(c != ' ' || BaudCount)
{
BaudBuffer[BaudCount++] = c;
if(BaudCount == 79)
{
BaudCount--;
while(BaudCount > 0 && BaudBuffer[BaudCount] == ' ')
BaudCount--;
BaudBuffer[BaudCount + 1] = 0;
FlowInfo . Connect = TRUE;
FlowInfo . Changed = TRUE;
BaudPending = FALSE;
DTERate = GetBaudRate(BaudBuffer);
}
}
}
}
else
{
register BYTE MatchMade;
register WORD i;
do
{
MatchMade = FALSE;
/* Scan all ID strings for matches. */
for(i = ScanStart ; i <= ScanEnd ; i++)
{
/* This sequence is a likely
* match.
*/
if(AttentionCount[i] == FlowCount)
{
/* Does the character
* fit into the sequence?
*/
if(c == AttentionBuffers[i][FlowCount])
{
MatchMade = TRUE;
/* Did we hit the
* last character
* in the sequence?
*/
if(++AttentionCount[i] == AttentionLength[i])
{
/* We've got a valid
* sequence, now look
* which flags to change.
*/
switch(i)
{
/* We got a `no carrier' message. */
case SCAN_NOCARRIER:
if(Config -> SerialConfig -> CheckCarrier)
{
WriteRequest -> IOSer . io_Command = SDCMD_QUERY;
DoIO(WriteRequest);
/* Is the carrier still present? */
if(!(WriteRequest -> io_Status & CIAF_COMCD))
break;
}
if(!FlowInfo . NoCarrier)
{
FlowInfo . NoCarrier = TRUE;
FlowInfo . Changed = TRUE;
}
WasOnline = Online;
Online = FALSE;
/* Clear the password. */
Password[0] = 0;
UserName[0] = 0;
CurrentBBSName[0] = 0;
CurrentBBSComment[0] = 0;
CurrentBBSNumber[0] = 0;
if(WasOnline)
{
StopCall(FALSE);
if(CurrentPay && ChosenEntry)
LogAction(LocaleString(MSG_TERMAUX_CARRIER_LOST_COST_TXT),CreateSum(CurrentPay,TRUE));
else
LogAction(LocaleString(MSG_TERMAUX_CARRIER_LOST_TXT));
Say(LocaleString(MSG_TERMAUX_CARRIER_LOST_TXT));
SetDialMenu(TRUE);
}
break;
/* Got another call. */
case SCAN_RING:
if(!FlowInfo . Ring)
{
FlowInfo . Ring = TRUE;
FlowInfo . Changed = TRUE;
}
break;
/* Got a voice call. */
case SCAN_VOICE:
if(!FlowInfo . Voice)
{
FlowInfo . Voice = TRUE;
FlowInfo . Changed = TRUE;
}
break;
/* Got a connect message. */
case SCAN_CONNECT:
/* Are we to check the carrier signal? */
if(Config -> SerialConfig -> CheckCarrier)
{
WriteRequest -> IOSer . io_Command = SDCMD_QUERY;
DoIO(WriteRequest);
/* Is the carrier signal present, i.e.
* was the `CONNECT' message valid?
*/
if(WriteRequest -> io_Status & CIAF_COMCD)
break;
}
WasOnline = Online;
if(!Online)
{
BaudBuffer[0] = 0;
BaudPending = TRUE;
BaudCount = 0;
}
break;
/* Got the ZModem inquiry sequence. */
case SCAN_ZMODEM:
if(!FlowInfo . ZModemUpload)
{
FlowInfo . ZModemUpload = TRUE;
FlowInfo . Changed = TRUE;
}
break;
/* Line is busy. */
case SCAN_BUSY:
if(!FlowInfo . Busy)
{
FlowInfo . Busy = TRUE;
FlowInfo . Changed = TRUE;
}
break;
case SCAN_NODIALTONE:
if(!FlowInfo . NoDialTone)
{
FlowInfo . NoDialTone = TRUE;
FlowInfo . Changed = TRUE;
}
break;
}
}
}
}
}
if(MatchMade)
FlowCount++;
else
{
if(FlowCount)
{
FlowCount = 0;
memset(AttentionCount,0,sizeof(AttentionCount));
}
else
break;
}
}
while(!FlowCount);
}
}
}
while(--Size);
}
/* StripSequence():
*
* Strips a string from ESC and CSI introduced control
* sequences.
*/
STATIC LONG __regargs
StripSequence(STRPTR Src,STRPTR Dst,LONG Length)
{
STATIC BYTE HasESC = FALSE,
HasCSI = FALSE;
LONG Size = 0;
while(Length--)
{
if(HasESC)
{
if(*Src == '[')
{
HasESC = FALSE;
HasCSI = TRUE;
}
else
{
if(*Src >= '0')
HasESC = FALSE;
}
Src++;
continue;
}
if(HasCSI)
{
if(*Src >= '@')
HasCSI = FALSE;
Src++;
continue;
}
switch(*Src)
{
case CAN:
case SUB:
HasESC = HasCSI = FALSE;
break;
case '\r':
break;
case ESC:
HasESC = TRUE;
break;
case CSI:
HasCSI = TRUE;
break;
default:
if(IsPrintable[*Src])
{
*Dst++ = *Src;
Size++;
}
break;
}
Src++;
}
return(Size);
}
/* ConOutputPrinter(STRPTR Buffer,LONG Size):
*
* Raw text output routine, printer capture flavour.
*/
STATIC VOID __regargs
ConOutputPrinter(STRPTR Buffer,LONG Size)
{
if(FWrite(PrinterCapture,Buffer,Size,1) != 1)
{
BlockWindows();
if(!MyEasyRequest(NULL,LocaleString(MSG_CONSOLE_ERROR_WRITING_TO_PRINTER_TXT),LocaleString(MSG_CONSOLE_IGNORE_CLOSE_PRINTER_TXT)))
ClosePrinterCapture(TRUE);
ReleaseWindows();
}
}
/* ConOutputCaptureGFX(STRPTR Buffer,LONG Size):
*
* Raw text output routine, GFX text & capture flavour.
*/
STATIC VOID __regargs
ConOutputCaptureGFX(STRPTR Buffer,LONG Size)
{
register WORD Offset;
/* Do we still have a character in the
* magnificient buffer?
*/
while(Size)
{
/* 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.
*/
if(CursorX > LastPrintableColumn)
{
/* Wrap cursor. */
if(Config -> EmulationConfig -> LineWrap)
{
/* Move to beginning of next line. */
CursorX = 0;
DownLine();
Capture("\n",1);
CurrentFontScale = SCALE_ATTR_NORMAL;
FontScalingRequired = (Config -> EmulationConfig -> FontScale != SCALE_NORMAL);
LastPrintableColumn = LastColumn;
/* Reposition cursor, don't redraw it. */
ClipBlitCursor(FALSE,TRUE);
}
else
{
/* Stop the cursor. */
CursorX = LastPrintableColumn;
Capture(Buffer,Size);
/* Make it reappear. */
ClipBlitCursor(FALSE,TRUE);
return;
}
}
if((Offset = LastPrintableColumn + 1 - CursorX) > Size)
Offset = Size;
if(Config -> EmulationConfig -> InsertMode)
{
RasterShiftChar(Offset);
ScrollLineShiftChar(Offset);
ShiftChar(Offset);
}
RasterPutString(Buffer,Offset);
ScrollLinePutString(Offset);
if(FontScalingRequired)
PrintScaled(Buffer,Offset,CurrentFontScale);
else
GfxText(RPort,Buffer,Offset);
Capture(Buffer,Offset);
Buffer += Offset;
Size -= Offset;
CursorX += Offset;
}
ClipBlitCursor(FALSE,TRUE);
}
/* ConOutputCaptureNormal(STRPTR Buffer,LONG Size):
*
* Raw text output routine, normal text & capture flavour.
*/
STATIC VOID __regargs
ConOutputCaptureNormal(STRPTR Buffer,LONG Size)
{
register WORD Offset;
while(Size)
{
if(CursorX > LastPrintableColumn)
{
if(Config -> EmulationConfig -> LineWrap)
{
CursorX = 0;
DownLine();
Capture("\n",1);
CurrentFontScale = SCALE_ATTR_NORMAL;
FontScalingRequired = (Config -> EmulationConfig -> FontScale != SCALE_NORMAL);
LastPrintableColumn = LastColumn;
ClipBlitCursor(FALSE,TRUE);
}
else
{
CursorX = LastPrintableColumn;
Capture(Buffer,Size);
ClipBlitCursor(FALSE,TRUE);
return;
}
}
if((Offset = LastPrintableColumn + 1 - CursorX) > Size)
Offset = Size;
if(Config -> EmulationConfig -> InsertMode)
{
RasterShiftChar(Offset);
ScrollLineShiftChar(Offset);
ShiftChar(Offset);
}
RasterPutString(Buffer,Offset);
ScrollLinePutString(Offset);
if(FontScalingRequired)
PrintScaled(Buffer,Offset,CurrentFontScale);
else
Text(RPort,Buffer,Offset);
Capture(Buffer,Offset);
Buffer += Offset;
Size -= Offset;
CursorX += Offset;
}
ClipBlitCursor(FALSE,TRUE);
}
/* ConOutputGFX(STRPTR Buffer,LONG Size):
*
* Raw text output routine, GFX text flavour.
*/
STATIC VOID __regargs
ConOutputGFX(STRPTR Buffer,LONG Size)
{
register WORD Offset;
/* Do we still have a character in the
* magnificient buffer?
*/
while(Size)
{
/* 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.
*/
if(CursorX > LastPrintableColumn)
{
/* Wrap cursor. */
if(Config -> EmulationConfig -> LineWrap)
{
/* Move to beginning of next line. */
CursorX = 0;
DownLine();
CurrentFontScale = SCALE_ATTR_NORMAL;
FontScalingRequired = (Config -> EmulationConfig -> FontScale != SCALE_NORMAL);
LastPrintableColumn = LastColumn;
/* Reposition cursor, don't redraw it. */
ClipBlitCursor(FALSE,TRUE);
}
else
{
/* Stop the cursor. */
CursorX = LastPrintableColumn;
/* Make it reappear. */
ClipBlitCursor(FALSE,TRUE);
return;
}
}
if((Offset = LastPrintableColumn + 1 - CursorX) > Size)
Offset = Size;
if(Config -> EmulationConfig -> InsertMode)
{
RasterShiftChar(Offset);
ScrollLineShiftChar(Offset);
ShiftChar(Offset);
}
RasterPutString(Buffer,Offset);
ScrollLinePutString(Offset);
if(FontScalingRequired)
PrintScaled(Buffer,Offset,CurrentFontScale);
else
GfxText(RPort,Buffer,Offset);
Buffer += Offset;
Size -= Offset;
CursorX += Offset;
}
ClipBlitCursor(FALSE,TRUE);
}
/* ConOutputNormal(STRPTR Buffer,LONG Size):
*
* Raw text output routine, normal text flavour.
*/
STATIC VOID __regargs
ConOutputNormal(STRPTR Buffer,LONG Size)
{
register WORD Offset;
while(Size)
{
if(CursorX > LastPrintableColumn)
{
if(Config -> EmulationConfig -> LineWrap)
{
CursorX = 0;
DownLine();
CurrentFontScale = SCALE_ATTR_NORMAL;
FontScalingRequired = (Config -> EmulationConfig -> FontScale != SCALE_NORMAL);
LastPrintableColumn = LastColumn;
ClipBlitCursor(FALSE,TRUE);
}
else
{
CursorX = LastPrintableColumn;
ClipBlitCursor(FALSE,TRUE);
return;
}
}
if((Offset = LastPrintableColumn + 1 - CursorX) > Size)
Offset = Size;
if(Config -> EmulationConfig -> InsertMode)
{
RasterShiftChar(Offset);
ScrollLineShiftChar(Offset);
ShiftChar(Offset);
}
RasterPutString(Buffer,Offset);
ScrollLinePutString(Offset);
if(FontScalingRequired)
PrintScaled(Buffer,Offset,CurrentFontScale);
else
Text(RPort,Buffer,Offset);
Buffer += Offset;
Size -= Offset;
CursorX += Offset;
}
ClipBlitCursor(FALSE,TRUE);
}
/* ConOutputUpdate():
*
* Choose the right raw text output routine for the job.
*/
VOID
ConOutputUpdate()
{
if(ControllerActive)
ConOutput = ConOutputPrinter;
else
{
if((Config -> CaptureConfig -> CaptureFilterMode && FileCapture) || PrinterCapture)
{
if(CurrentFont == GFX)
ConOutput = ConOutputCaptureGFX;
else
ConOutput = ConOutputCaptureNormal;
}
else
{
if(BufferFrozen)
{
if(CurrentFont == GFX)
ConOutput = ConOutputGFX;
else
ConOutput = ConOutputNormal;
}
else
{
if(CurrentFont == GFX)
ConOutput = ConOutputCaptureGFX;
else
ConOutput = ConOutputCaptureNormal;
}
}
}
if(ReceiveTable)
ConDump = ConTransWrite;
else
ConDump = ConOutput;
}
/* ConFontScaleUpdate():
*
* Choose the right font scale for the job.
*/
VOID
ConFontScaleUpdate()
{
CurrentFontScale = RasterAttr[CursorY];
if(Config -> EmulationConfig -> FontScale == SCALE_HALF)
{
FontScalingRequired = (CurrentFontScale != SCALE_ATTR_2X);
LastPrintableColumn = LastColumn;
}
else
{
if(FontScalingRequired = (CurrentFontScale != SCALE_ATTR_NORMAL))
LastPrintableColumn = ((LastColumn + 1) / 2) - 1;
else
LastPrintableColumn = LastColumn;
}
}
/* ConTransWrite(STRPTR Buffer,LONG Size):
*
* Frontend for ConWrite(), including character translation.
*/
VOID __regargs
ConTransWrite(STRPTR Buffer,LONG Size)
{
struct TranslationHandle Handle;
UBYTE LocalBuffer[256];
/* Set up for translation. */
ConTranslateSetup(&Handle,Buffer,Size,LocalBuffer,256,ReceiveTable);
/* Process and output the data. */
while(Size = ConTranslateBuffer(&Handle))
(* ConOutput)(LocalBuffer,Size);
}
/* ConProcessDataTransExternal(register STRPTR String,register LONG Size):
*
* Process data, external emulation including translation flavour.
*/
VOID __regargs
ConProcessDataTransExternal(register STRPTR String,register LONG Size)
{
struct TranslationHandle Handle;
/* Set up for translation. */
ConTranslateSetup(&Handle,String,Size,ConTempBuffer,256,ReceiveTable);
if(StripBuffer)
{
register LONG Len;
/* Process and output the data. */
while(Size = ConTranslateBuffer(&Handle))
{
XEmulatorWrite(XEM_IO,ConTempBuffer,Size);
XEM_HostData . Source = ConTempBuffer;
XEM_HostData . Destination = StripBuffer;
if(Len = XEmulatorHostMon(XEM_IO,&XEM_HostData,Size))
Capture(StripBuffer,Len);
}
}
else
{
/* Process and output the data. */
while(Size = ConTranslateBuffer(&Handle))
XEmulatorWrite(XEM_IO,ConTempBuffer,Size);
}
}
/* ConProcessDataExternal(register STRPTR String,register LONG Size):
*
* Process data, external emulation flavour.
*/
VOID __regargs
ConProcessDataExternal(register STRPTR String,register LONG Size)
{
XEmulatorWrite(XEM_IO,String,Size);
/* Build another string to contain
* the pure ASCII contents, i.e.
* not including any ESC control
* sequences.
*/
if(StripBuffer)
{
register LONG Len;
XEM_HostData . Source = String;
XEM_HostData . Destination = StripBuffer;
if(Len = XEmulatorHostMon(XEM_IO,&XEM_HostData,Size))
Capture(StripBuffer,Len);
}
}
/* ConProcessData7(register STRPTR String,register LONG Size):
*
* Process data, 7 bit flavour.
*/
VOID __regargs
ConProcessData7(register STRPTR String,register LONG Size)
{
register LONG Len = 0;
register UBYTE c;
/* If still parsing a sequence,
* continue with it.
*/
if(InSequence)
{
while(Size--)
{
c = *String++ & 0x7F;
if(!(*AbortTable[c])(c))
{
InSequence = FALSE;
break;
}
}
}
/* Check which font we are in, if other than Topaz
* the only invalid char is a Null (0) which will
* display as a space if let to continue.
*/
if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
{
while(Size-- > 0)
{
if(IsPrintable[c = *String++ & 0x7F])
{
/* This character is associated with a
* special function (bell, xon, xoff, etc.).
*/
if(SpecialTable[c])
{
if(Len)
{
(*ConDump)(ConTempBuffer,Len);
Len = 0;
}
/* Does this character start
* a control sequence?
*/
if(InSequence = (*SpecialTable[c])(c))
{
while(Size-- > 0)
{
c = *String++ & 0x7F;
if(!(*AbortTable[c])(c))
{
InSequence = FALSE;
break;
}
}
}
}
else
{
/* Put the character into the buffer
* and flush it if necessary.
*/
ConTempBuffer[Len] = c;
if(Len++ == 512)
{
(*ConDump)(ConTempBuffer,Len);
Len = 0;
}
}
}
}
}
else
{
while(Size-- > 0)
{
if(c = (*String++ & 0x7F))
{
/* This character is associated with a
* special function (bell, xon, xoff, etc.).
*/
if(SpecialTable[c])
{
if(Len)
{
(*ConDump)(ConTempBuffer,Len);
Len = 0;
}
if(InSequence = (*SpecialTable[c])(c))
{
while(Size-- > 0)
{
c = *String++ & 0x7F;
if(!(*AbortTable[c])(c))
{
InSequence = FALSE;
break;
}
}
}
}
else
{
/* Put the character into the buffer
* and flush it if necessary.
*/
ConTempBuffer[Len] = c;
if(Len++ == 512)
{
(*ConDump)(ConTempBuffer,Len);
Len = 0;
}
}
}
}
}
if(Len)
(*ConDump)(ConTempBuffer,Len);
}
/* ConProcessData8(register STRPTR String,register LONG Size):
*
* Process data, 8 bit flavour.
*/
VOID __regargs
ConProcessData8(register STRPTR String,register LONG Size)
{
register LONG Len = 0;
register UBYTE c;
if(InSequence)
{
while(Size--)
{
c = *String++;
if(!(*AbortTable[c])(c))
{
InSequence = FALSE;
break;
}
}
}
if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
{
while(Size-- > 0)
{
if(IsPrintable[c = *String++])
{
if(SpecialTable[c])
{
if(Len)
{
(*ConDump)(ConTempBuffer,Len);
Len = 0;
}
if(InSequence = (*SpecialTable[c])(c))
{
while(Size-- > 0)
{
c = *String++;
if(!(*AbortTable[c])(c))
{
InSequence = FALSE;
break;
}
}
}
}
else
{
ConTempBuffer[Len] = c;
if(Len++ == 512)
{
(*ConDump)(ConTempBuffer,Len);
Len = 0;
}
}
}
}
}
else
{
while(Size-- > 0)
{
if(c = *String++)
{
if(SpecialTable[c])
{
if(Len)
{
(*ConDump)(ConTempBuffer,Len);
Len = 0;
}
if(InSequence = (*SpecialTable[c])(c))
{
while(Size-- > 0)
{
c = *String++;
if(!(*AbortTable[c])(c))
{
InSequence = FALSE;
break;
}
}
}
}
else
{
ConTempBuffer[Len] = c;
if(Len++ == 512)
{
(*ConDump)(ConTempBuffer,Len);
Len = 0;
}
}
}
}
}
if(Len)
(*ConDump)(ConTempBuffer,Len);
}
/* ConTransferHost(STRPTR Buffer,LONG Len):
*
* Process data read from the serial line,
* special XPR flavour.
*/
VOID __regargs
ConTransferHost(STRPTR Buffer,LONG Len)
{
Len = XProtocolHostMon(XprIO,Buffer,Len,Config -> SerialConfig -> SerialBufferSize);
if(TransferWindow)
TransferCleanup();
if(Len)
ConProcess(Buffer,Len);
}
/* ConProcess(STRPTR String,LONG Size):
*
* Process the contents of a string to be sent to the
* console window.
*/
VOID __regargs
ConProcess(register STRPTR String,register LONG Size)
{
/* If the capture filter happens to be disabled, write the
* raw data.
*/
if(!Config -> CaptureConfig -> CaptureFilterMode)
CaptureToFile(String,Size);
/* Feed the flow filter. */
if(UseFlow)
{
if(Config -> SerialConfig -> StripBit8)
FlowFilter(String,Size,0x7F);
else
FlowFilter(String,Size,0xFF);
}
/* In quiet mode no characters are echoed to the
* console window, they are just passed through
* the data flow filter. Usually, this mode is
* enabled by the dial panel.
*/
if(!Quiet)
(*ConProcessData)(String,Size);
}
/* ConWrites(STRPTR String,...):
*
* Output a string to the console.
*/
VOID __stdargs
ConWrites(STRPTR String,...)
{
va_list VarArgs;
if(Marking)
DropMarker();
ClearCursor();
va_start(VarArgs,String);
VSPrintf(SharedBuffer,String,VarArgs);
va_end(VarArgs);
ConProcess(SharedBuffer,strlen(SharedBuffer));
DrawCursor();
}
/* FlowInit():
*
* Set up the data flow parser. The parser scans the serial
* output data for more or less interesting modem output
* (carrier lost, connect, etc.).
*/
VOID
FlowInit(BYTE FullReset)
{
WORD i;
/* Set up `NO CARRIER' message. */
if(Config -> ModemConfig -> NoCarrier[0])
SPrintf(AttentionBuffers[SCAN_NOCARRIER],"%s\r",Config -> ModemConfig -> NoCarrier);
else
AttentionBuffers[SCAN_NOCARRIER][0] = 0;
/* Set up ZRQINIT message. */
strcpy(AttentionBuffers[SCAN_ZMODEM],"*\030B01");
/* Set up `CONNECT' message. */
strcpy(AttentionBuffers[SCAN_CONNECT],Config -> ModemConfig -> Connect);
/* Set up `VOICE' message. */
if(Config -> ModemConfig -> Voice[0])
SPrintf(AttentionBuffers[SCAN_VOICE],"%s\r",Config -> ModemConfig -> Voice);
else
AttentionBuffers[SCAN_VOICE][0] = 0;
/* Set up `RING' message. */
if(Config -> ModemConfig -> Ring[0])
SPrintf(AttentionBuffers[SCAN_RING],"%s\r",Config -> ModemConfig -> Ring);
else
AttentionBuffers[SCAN_RING][0] = 0;
/* Set up `BUSY' message. */
if(Config -> ModemConfig -> Busy[0])
SPrintf(AttentionBuffers[SCAN_BUSY],"%s\r",Config -> ModemConfig -> Busy);
else
AttentionBuffers[SCAN_BUSY][0] = 0;
/* Set up `NO DIALTONE' message. */
if(Config -> ModemConfig -> NoDialTone[0])
SPrintf(AttentionBuffers[SCAN_NODIALTONE],"%s\r",Config -> ModemConfig -> NoDialTone);
else
AttentionBuffers[SCAN_NODIALTONE][0] = 0;
/* Reset match counter. */
FlowCount = 0;
/* Reset indices. */
memset(AttentionCount,0,sizeof(AttentionCount));
/* Determine lengths. */
for(i = 0 ; i < SCAN_COUNT ; i++)
AttentionLength[i] = strlen(AttentionBuffers[i]);
if(FullReset)
{
/* No, we are not yet looking for a baud rate. */
BaudPending = FALSE;
/* Reset the flags. */
FlowInfo . Changed = FlowInfo . NoCarrier = FlowInfo . ZModemUpload = FlowInfo . Connect = FlowInfo . Voice = FlowInfo . Ring = FlowInfo . Busy = FlowInfo . NoDialTone = FALSE;
}
/* Is it safe to disable the flow filter? */
if(!FullCheck && Online && Config -> SerialConfig -> CheckCarrier && !Config -> MiscConfig -> AutoUpload)
UseFlow = FALSE;
else
UseFlow = TRUE;
/* Full data check is a lot slower than looking for
* just a single sequence (such as the `CONNECT'
* below). This mode is reserved for the dial panel.
*/
if(FullCheck)
{
ScanStart = SCAN_NOCARRIER;
ScanEnd = SCAN_NODIALTONE;
}
else
{
if(Online)
{
ScanStart = SCAN_NOCARRIER;
if(UsesZModem)
ScanEnd = SCAN_ZMODEM;
else
ScanEnd = SCAN_NOCARRIER;
}
else
{
if(UsesZModem)
ScanStart = SCAN_ZMODEM;
else
ScanStart = SCAN_CONNECT;
ScanEnd = SCAN_RING;
}
}
}
/* HandleCursor(UBYTE Char,ULONG Qualifier):
*
* This routine handles the somewhat strange behaviour of
* an assorted set of keys in VT100 applications mode.
*/
BYTE __regargs
HandleCursor(UBYTE Char,ULONG Qualifier)
{
STATIC struct { UBYTE Char; STRPTR VanillaString,ApplicationString; } Table[24] =
{
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", /* This should really be a comma */
'.', ".", "\033On",
'[', "[", "\033OP",
'{', "{", "\033OP",
']', "]", "\033OQ",
'}', "}", "\033OQ",
'/', "/", "\033OR",
'*', "*", "\033OS",
'\r', "\r", "\033OM"
};
BYTE i;
/* Look for the cursor keys first. */
for(i = 0 ; i < 4 ; i++)
{
/* Is this the key we want? */
if(Table[i] . Char == Char)
{
/* If in cursor key applications mode,
* send the corresponding string.
*/
if(Config -> EmulationConfig -> CursorMode == KEYMODE_APPLICATION)
SerWrite(Table[i] . ApplicationString,strlen(Table[i] . ApplicationString));
else
{
WORD QualType = 0;
/* Find the approriate qualifier. */
if(Qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
QualType = 1;
else
{
if(Qualifier & (IEQUALIFIER_LALT|IEQUALIFIER_RALT))
QualType = 2;
else
{
if(Qualifier & IEQUALIFIER_CONTROL)
QualType = 3;
}
}
/* Send the corresponding string. */
SerialCommand(CursorKeys -> Keys[QualType][i]);
}
return(TRUE);
}
}
/* Then take a look at the numeric pad. */
for(i = 4 ; i < 24 ; i++)
{
/* Is this the character we want? */
if(Table[i] . Char == Char)
{
/* If in numeric keypad applications mode,
* send the corresponding string.
*/
if(Config -> EmulationConfig -> NumericMode == KEYMODE_APPLICATION)
SerWrite(Table[i] . ApplicationString,strlen(Table[i] . ApplicationString));
else
{
/* Is this the return key? */
if(i == 23)
{
switch(Config -> TerminalConfig -> SendCR)
{
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);
}
/* ConvertKey():
*
* The actual key conversion routine.
*/
STATIC LONG __inline
ConvertKey(ULONG Qualifier,UWORD Code,APTR IAddress,STRPTR Buffer,LONG Len)
{
LONG Actual;
/* Fill in the defaults. */
FakeInputEvent -> ie_Code = Code;
FakeInputEvent -> ie_Qualifier = Qualifier;
FakeInputEvent -> ie_position . ie_addr = *((APTR *)IAddress);
/* Clear the buffer (sortof). */
Buffer[0] = 0;
/* Convert the codes. */
if((Actual = RawKeyConvert(FakeInputEvent,Buffer,Len,KeyMap)) > 0)
return(Actual);
else
return(0);
}
/* KeyConvert(struct IntuiMessage *Massage,STRPTR Buffer):
*
* Convert a raw key information according to the
* current keymap settings.
*/
UBYTE __regargs
KeyConvert(struct IntuiMessage *Massage,STRPTR Buffer,LONG *Len)
{
if(Buffer)
Buffer[0] = 0;
if(Len)
*Len = 0;
/* Key was pressed, not released. */
if(Massage -> Class == IDCMP_RAWKEY && !(Massage -> Code & IECODE_UP_PREFIX))
{
/* These are the sequences mapped to special
* control keys (cursor keys, function keys,
* the help key).
*/
STATIC struct { STRPTR RawCode; UBYTE Result; } ConversionTable[15] =
{
(STRPTR)"A", CUP,
(STRPTR)"B", CDN,
(STRPTR)"C", CFW,
(STRPTR)"D", CBK,
(STRPTR)"?~", HLP,
(STRPTR)"0~", FN1,
(STRPTR)"1~", FN2,
(STRPTR)"2~", FN3,
(STRPTR)"3~", FN4,
(STRPTR)"4~", FN5,
(STRPTR)"5~", FN6,
(STRPTR)"6~", FN7,
(STRPTR)"7~", FN8,
(STRPTR)"8~", FN9,
(STRPTR)"9~", F10
};
STATIC UBYTE SeqLens[15] = { 1,1,1,1,2,2,2,2,2,2,2,2,2,2,2 };
UBYTE ConvertBuffer[257];
ULONG Qualifier;
LONG Actual;
/* If it's a function or cursor key, clear the qualifier. */
if(Massage -> Code >= CURSOR_UP_CODE && Massage -> Code <= F10_CODE)
Qualifier = NULL;
else
{
Qualifier = Massage -> Qualifier;
/* Does it have a numeric keypad qualifier set? */
if((Qualifier & (IEQUALIFIER_NUMERICPAD | IEQUALIFIER_CONTROL)) == (IEQUALIFIER_NUMERICPAD | IEQUALIFIER_CONTROL))
{
/* Look at the vanilla result. */
if(ConvertKey(Qualifier & ~(IEQUALIFIER_CONTROL | IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT | IEQUALIFIER_LALT | IEQUALIFIER_RALT),Massage -> Code,Massage -> IAddress,ConvertBuffer,1))
{
STRPTR String;
/* Take a look at the results. */
switch(ConvertBuffer[0])
{
case '[':
String = "\033OP";
break;
case ']':
String = "\033OQ";
break;
case '/':
String = "\033OR";
break;
case '*':
String = "\033OS";
break;
default:
String = NULL;
break;
}
/* Return the PFx key code. */
if(String)
{
if(Buffer)
memcpy(Buffer,String,3);
if(Len)
*Len = 3;
return('\033');
}
}
}
/* Does it have a shift qualifier set? */
if(Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
{
/* Do the conversion... */
if(ConvertKey(Qualifier & ~(IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT),Massage -> Code,Massage -> IAddress,ConvertBuffer,1))
{
/* Did it produce a tab key? If so, transfer
* Esc tab instead.
*/
if(ConvertBuffer[0] == '\t')
{
if(Len)
*Len = 2;
if(Buffer)
memcpy(Buffer,"\033\t",2);
return('\033');
}
}
}
/* Does it have the control qualifier set? */
if(Qualifier & IEQUALIFIER_CONTROL)
{
/* Do the conversion... */
if(ConvertKey(Qualifier & ~IEQUALIFIER_CONTROL,Massage -> Code,Massage -> IAddress,ConvertBuffer,1))
{
/* Did it produce a space or an `at' sign? */
if(ConvertBuffer[0] == ' ' || ConvertBuffer[0] == '@')
{
/* If so, produce a nul instead. */
if(Len)
*Len = 1;
if(Buffer)
Buffer[0] = 0;
return(0);
}
}
}
}
/* Do the final conversion... */
if(Actual = ConvertKey(Qualifier,Massage -> Code,Massage -> IAddress,ConvertBuffer,256))
{
/* Did we get anything in return? */
if(ConvertBuffer[0])
{
/* Are we to swap the backspace and
* delete keys?
*/
if(Config -> EmulationConfig -> SwapBSDelete)
{
register WORD i;
for(i = 0 ; i < Actual ; i++)
{
if(ConvertBuffer[i] == BKS)
ConvertBuffer[i] = DEL;
else
{
if(ConvertBuffer[i] == DEL)
ConvertBuffer[i] = BKS;
}
}
}
/* Translated sequence starts
* with a CSI, let's have a look
* at the associated control
* key.
*/
if(ConvertBuffer[0] == CSI)
{
register WORD i;
for(i = 0 ; i < sizeof(SeqLens) ; i++)
{
/* Does it match? */
if(!memcmp(&ConvertBuffer[1],ConversionTable[i] . RawCode,SeqLens[i]))
{
/* Store the length. */
if(Len)
*Len = 1;
/* Store the result. */
if(Buffer)
{
Buffer[0] = ConversionTable[i] . Result;
Buffer[1] = 0;
}
return(ConversionTable[i] . Result);
}
}
}
/* Store the number of characters converted. */
if(Len)
*Len = Actual;
/* Store the converted characters. */
if(Buffer)
memcpy(Buffer,ConvertBuffer,Actual);
return(ConvertBuffer[0]);
}
}
}
return(0);
}
/* GfxText(struct RastPort *RPort,STRPTR Buffer,LONG Length):
*
* Text output, if necessary switching from gfx font
* to current default font.
*/
VOID __regargs
GfxText(struct RastPort *RPort,STRPTR Buffer,LONG Length)
{
BYTE TextMode;
LONG SameMode;
/* Determine current text rendering mode. */
if(GfxTable[Buffer[0]] == MODE_GFX)
TextMode = MODE_GFX;
else
{
TextMode = MODE_STANDARD;
SetFont(RPort,TextFont);
}
/* Reset number of characters in common mode. */
SameMode = 0;
/* Scan until all input is processed. */
FOREVER
{
/* Scan for characters in the current mode. */
while(GfxTable[Buffer[SameMode]] == TextMode && SameMode < Length)
SameMode++;
/* Output the text found. */
Text(RPort,Buffer,SameMode);
/* Decrement number of remaining bytes. */
Length -= SameMode;
/* Anything left? */
if(Length)
{
/* Skip to next character. */
Buffer += SameMode;
SameMode = 0;
/* Change text output mode. */
if(TextMode == MODE_GFX)
{
SetFont(RPort,TextFont);
TextMode = MODE_STANDARD;
}
else
{
SetFont(RPort,GFX);
TextMode = MODE_GFX;
}
}
else
break;
}
/* Reset font type. */
if(TextMode == MODE_STANDARD)
SetFont(RPort,GFX);
}
/* DoBackspace():
*
* Special function: perform backspace.
*/
BYTE __regargs
DoBackspace()
{
Capture("\b",1);
if(CursorX)
{
CursorX--;
/* If destructive, shift the remaining line
* one character to the right.
*/
if(Config -> EmulationConfig -> DestructiveBackspace)
{
WORD DeltaX,MinX;
BackupRender();
RasterEraseCharacters(1);
if(Config -> EmulationConfig -> FontScale == SCALE_NORMAL)
{
if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
{
DeltaX = TextFontWidth;
MinX = MUL_X(CursorX);
}
else
{
DeltaX = TextFontWidth / 2;
MinX = MUL_X(CursorX) / 2;
}
}
else
{
if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
{
DeltaX = TextFontWidth / 2;
MinX = MUL_X(CursorX) / 2;
}
else
{
DeltaX = TextFontWidth;
MinX = MUL_X(CursorX);
}
}
ScrollLineEraseCharacters(1);
ScrollLineRaster(RPort,DeltaX,0,MinX,MUL_Y(CursorY),LastPixel,MUL_Y(CursorY + 1) - 1,FALSE);
BackupRender();
}
ClipBlitCursor(FALSE,TRUE);
}
return(FALSE);
}
/* DoBeep():
*
* The real interface to the beep routine.
*/
BYTE __regargs
DoBeep()
{
/* Handle the visual part. */
if(Config -> TerminalConfig -> BellMode != BELL_AUDIBLE)
{
if(StatusProcess)
Signal(StatusProcess,SIG_BELL);
}
/* Let it beep. */
if(Config -> TerminalConfig -> BellMode == BELL_AUDIBLE || Config -> TerminalConfig -> BellMode == BELL_BOTH)
Beep();
/* Capture the bell. */
if(Config -> CaptureConfig -> CaptureFilterMode == FILTER_NONE)
Capture("\a",1);
return(FALSE);
}
/* DoxON():
*
* Perform XON (stop data flow).
*/
BYTE __regargs
DoxON()
{
if(Config -> SerialConfig -> xONxOFF)
Status = STATUS_HOLDING;
return(FALSE);
}
/* DoLF():
*
* Special function: perform line feed.
*/
BYTE __regargs
DoLF()
{
if(Config -> TerminalConfig -> ReceiveLF == LF_ASLFCR)
{
CursorX = 0;
DownLine();
ClipBlitCursor(FALSE,TRUE);
Capture("\n",1);
}
else
{
if(Config -> TerminalConfig -> ReceiveLF == LF_ASLF)
{
DownLine();
ClipBlitCursor(FALSE,TRUE);
}
}
return(FALSE);
}
/* DoShiftIn():
*
* Special function: Shift into graphics mode
*/
BYTE __regargs
DoShiftIn()
{
if(CharMode[1] == TABLE_GFX && GFX)
CurrentFont = GFX;
if(CharMode[1] == TABLE_ASCII)
CurrentFont = TextFont;
SetFont(RPort,CurrentFont);
ConOutputUpdate();
Charset = 1;
return(FALSE);
}
/* DoShiftOut():
*
* Special function: Shift out of graphics mode
*/
BYTE __regargs
DoShiftOut()
{
if(CharMode[0] == TABLE_GFX && GFX)
CurrentFont = GFX;
if(CharMode[0] == TABLE_ASCII)
CurrentFont = TextFont;
SetFont(RPort,CurrentFont);
ConOutputUpdate();
Charset = 0;
return(FALSE);
}
/* DoCR_LF():
*
* Special function: perform carriage return and line feed.
*/
BYTE __regargs
DoCR_LF()
{
CursorX = 0;
DownLine();
ClipBlitCursor(FALSE,TRUE);
Capture("\n",1);
return(FALSE);
}
/* DoFF():
*
* Special function: perform form feed.
*/
BYTE __regargs
DoFF()
{
if(Config -> EmulationConfig -> NewLineMode)
{
CursorX = 0;
DoCR_LF();
}
else
{
EraseScreen("2");
CursorX = CursorY = 0;
ClipBlitCursor(FALSE,TRUE);
ConFontScaleUpdate();
Capture("\n",1);
}
return(FALSE);
}
/* DoLF_FF_VT():
*
* Special function: handle line feed, form feed and vertical
* tab.
*/
BYTE __regargs
DoLF_FF_VT()
{
if(Config -> EmulationConfig -> NewLineMode)
DoCR_LF();
else
DoLF();
return(FALSE);
}
/* DoCR():
*
* Special function: handle carriage return.
*/
BYTE __regargs
DoCR()
{
if(Config -> EmulationConfig -> NewLineMode || Config -> TerminalConfig -> ReceiveCR == CR_ASCRLF)
DoCR_LF();
else
{
if(Config -> TerminalConfig -> ReceiveCR == CR_ASCR)
{
CursorX = 0;
ClipBlitCursor(FALSE,TRUE);
Capture("\n",1);
}
}
return(FALSE);
}
/* DoTab():
*
* Special function: handle tab, move cursor to next
* tab stop.
*/
BYTE __regargs
DoTab()
{
WORD Column;
if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
Column = LastColumn;
else
Column = ((LastColumn + 1) / 2) - 1;
if(Config -> EmulationConfig -> LineWrap)
{
if(CursorX >= LastColumn)
{
CursorX = 0;
DownLine();
}
else
{
while(CursorX < Column)
{
CursorX++;
if(TabStops[CursorX])
break;
}
}
}
else
{
while(CursorX < Column)
{
CursorX++;
if(TabStops[CursorX])
break;
}
}
ClipBlitCursor(FALSE,TRUE);
Capture("\t",1);
return(FALSE);
}
/* DoEnq():
*
* Special function: send answerback message.
*/
BYTE __regargs
DoEnq()
{
if(Config -> EmulationConfig -> AnswerBack[0])
SerialCommand(Config -> EmulationConfig -> AnswerBack);
return(FALSE);
}
/* DoEsc():
*
* Start new control sequence.
*/
BYTE __regargs
DoEsc()
{
if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
(* ConDump)("^",1);
return(TRUE);
}
/* DoCsi():
*
* Start new control sequence.
*/
BYTE __regargs
DoCsi()
{
if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
(* ConDump)("^[",2);
ParseCode('[');
return(TRUE);
}
/* DoNewEsc(UBYTE Char):
*
* Start new control sequence.
*/
BYTE __regargs
DoNewEsc(UBYTE Char)
{
if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
(* ConDump)("^",1);
DoCancel();
return(TRUE);
}
/* DoNewCsi(UBYTE Char):
*
* Start new control sequence.
*/
BYTE __regargs
DoNewCsi(UBYTE Char)
{
if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
(* ConDump)("^[",2);
DoCancel();
return(ParseCode('['));
}