[comp.sources.amiga] v02i033: vt100 2.6 -w- tektronix support

ng@s.cc.purdue.edu.UUCP (10/02/87)

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# Xshar: Extended Shell Archiver.
# This is part  2 out of  3.
# This archive created: Fri Oct  2 13:14:34 1987
# By: Craig Norborg (Purdue University Computing Center)
#	Run the following text with /bin/sh to create:
#	init.c
#	kermit.c
#	remote.c
#	vt100.h
cat << \SHAR_EOF > init.c
/***************************************************************
 * vt100 - terminal emulator - initialization
 *
 *	v2.65		NG  - added tek4014 emulation
 *	v2.6 870227 DBW - bug fixes for all the stuff in v2.5
 *	v2.5 870214 DBW - more additions (see readme file)
 *	v2.4 861214 DBW - lots of fixes/additions (see readme file)
 *	v2.3 861101 DBW - minor bug fixes
 *	v2.2 861012 DBW - more of the same
 *	v2.1 860915 DBW - new features (see README)
 *	     860901 ACS	- Added Parity and Word Length and support code
 *	     860823 DBW - Integrated and rewrote lots of code
 *	v2.0 860809 DBW - Major rewrite
 *	v1.1 860720 DBW	- Switches, 80 cols, colors, bug fixes
 *	v1.0 860712 DBW	- First version released
 *
 ***************************************************************/

#include "vt100.h"

char line[256];
static char cmds[] = "<>GRSBLHX+-I7.DWKCZ";	/* changed a bit for tek	*/

char *InitDefaults(argc,argv)
int	argc;
char	**argv;
    {
    FILE    *fd;
    char    *p;
    int	    l;

    doing_init = 1;	/* make sure we only allow INIT script commands */
    if (((argc > 1) && (fd=fopen(argv[1],"r")) != 0) ||
	(fd=fopen("vt100.init","r")) != 0 ||
	(fd=fopen("s:vt100.init","r")) != 0) {
	while (fgets(line,256,fd) != 0) {
	    line[strlen(line)-1] = '\000';
	    p = next_wrd(&line[0],&l);
	    if (*p) {
		*p |= ' ';
		if (p[1]) p[1] |= ' ';
		if (*p == '#') continue;
		if (*p == 'e' && p[1] == 'x') break;
		exe_cmd(p,l);
		}
	    }
	fclose(fd);
	}
    doing_init = 0;

    /* Now set up all the screen info as necessary */
    if (p_interlace == 0) {
	if (p_lines > 24) p_lines = 24;
	MINY = 14;
	NewWindow.Height    = (long)((p_lines*8)+8);
	}
    else {
	if (p_lines > 48) p_lines = 48;
	MINY = 16;
	NewScreen.ViewModes |= LACE;
	NewWindow.Height    = (long)((p_lines*8)+10);
	}
    NewWindow.MinHeight = NewWindow.Height;
    NewWindow.MaxHeight = NewWindow.Height;
    NewWindow.TopEdge   = 0L;
    MAXY = ((p_lines-1)*8) + MINY;
    top  = MINY;
    bot	 = MAXY;
    savx = MINX;
    savy = MINY;
    if (p_screen == 1) {
	if (p_depth > 2) p_depth = 2;
	if (p_depth < 1) p_depth = 1;
	NewScreen.Depth	    = (long)p_depth;
	NewScreen.Height    = (long)((p_lines*8)+16);
	if (p_interlace == 1)
	    NewScreen.TopEdge   = (long)(400 - NewScreen.Height);
	else
	    NewScreen.TopEdge   = (long)(208 - NewScreen.Height);
	}
    else {
	p_depth			= 2L;
	NewWindow.TopEdge	= 0L;
	NewWindow.Screen	= NULL;
	NewWindow.Type		= WBENCHSCREEN;
	}
    /* see if we exit with a startup script */
    if (*p == 'e') {
	p = next_wrd(p+l+1,&l);
	if (*p) return(p);
	}
    return(NULL);
    }

void InitDevs()
{
USHORT	colors[4];
int	i;
BYTE	*b,*c;

IntuitionBase = (struct IntuitionBase *)
    OpenLibrary("intuition.library", INTUITION_REV);
if( IntuitionBase == NULL )
    cleanup("can't open intuition",1);

GfxBase = (struct GfxBase *)
    OpenLibrary("graphics.library",GRAPHICS_REV);
if( GfxBase == NULL )
    cleanup("can't open graphics library",2);

if (p_screen == 1) {
    if ((myscreen = (struct Screen *)OpenScreen(&NewScreen)) == NULL)
	cleanup("can't open screen",3);
    NewWindow.Screen = myscreen;
    }

if ((mywindow = (struct Window *)OpenWindow(&NewWindow)) == NULL)
    cleanup("can't open window",4);
if ((myfont = (struct TextFont *)OpenFont(&myattr)) == NULL)
    cleanup("can't open font",4);

myviewport   = (struct ViewPort *)ViewPortAddress(mywindow);
myrastport   = (struct RastPort *)mywindow->RPort;

SetFont(myrastport,myfont);

if (p_depth > 1) myrequest.BackFill = 2;
if (p_screen != 0 && p_wbcolors == 0) {
    colors[0] = p_background;
    colors[1] = p_foreground;
    colors[2] = p_bold;
    colors[3] = p_cursor;
    if (p_depth == 1)
	LoadRGB4(myviewport,(struct ColorMap *)colors,2L);
    else
    	LoadRGB4(myviewport,(struct ColorMap *)colors,4L);
    }

Read_Request = (struct IOExtSer *)
    AllocMem((long)sizeof(*Read_Request),MEMF_PUBLIC|MEMF_CLEAR);
Read_Request->io_SerFlags = 0L;
Read_Request->IOSer.io_Message.mn_ReplyPort = CreatePort(0L,0L);
if(OpenDevice(SERIALNAME,NULL,Read_Request,NULL))
    cleanup("Cant open Read device",5);
rs_in = malloc(p_buffer+1);
Read_Request->io_SerFlags = 0L;
Read_Request->io_Baud	  = p_baud;
Read_Request->io_ReadLen  = 8L;
Read_Request->io_WriteLen = 8L;
Read_Request->io_CtlChar  = 0x11130000L;
Read_Request->io_RBufLen  = p_buffer;
Read_Request->io_BrkTime  = p_break;
Read_Request->IOSer.io_Command = SDCMD_SETPARAMS;
DoIO(Read_Request);
Read_Request->IOSer.io_Command = CMD_READ;
Read_Request->IOSer.io_Length  = 1;
Read_Request->IOSer.io_Data    = (APTR) &rs_in[0];

Write_Request = (struct IOExtSer *)
    AllocMem((long)sizeof(*Write_Request),MEMF_PUBLIC|MEMF_CLEAR);
b = (BYTE *)Read_Request;
c = (BYTE *)Write_Request;
for (i=0;i<sizeof(struct IOExtSer);i++) *c++ = *b++;
Write_Request->IOSer.io_Message.mn_ReplyPort = CreatePort(0L,0L);
Write_Request->IOSer.io_Command = CMD_WRITE;
Write_Request->IOSer.io_Length  = 1;
Write_Request->IOSer.io_Data    = (APTR) &rs_out[0];

Timer_Port = CreatePort("Timer Port",0L);
Script_Timer_Port = CreatePort("Timer Port",0L);

if (OpenDevice(TIMERNAME, UNIT_VBLANK, (char *) &Timer, 0) ||
    OpenDevice(TIMERNAME, UNIT_VBLANK, (char *) &Script_Timer, 0)) 
	cleanup("can't open timer device",7);

Timer.tr_node.io_Message.mn_ReplyPort = Timer_Port;
Timer.tr_node.io_Command = TR_ADDREQUEST;
Timer.tr_node.io_Flags = 0;
Timer.tr_node.io_Error = 0;

Script_Timer.tr_node.io_Message.mn_ReplyPort = Script_Timer_Port;
Script_Timer.tr_node.io_Command = TR_ADDREQUEST;
Script_Timer.tr_node.io_Flags = 0;
Script_Timer.tr_node.io_Error = 0;

BeepWave   = (UBYTE *)AllocMem(BEEPSIZE,(long)(MEMF_CHIP|MEMF_CLEAR));
if (BeepWave != 0) BeepWave[0] = 100;

Audio_Port = CreatePort("Audio Port",0L);

Audio_Request.ioa_Request.io_Message.mn_ReplyPort   = Audio_Port;
Audio_Request.ioa_Request.io_Message.mn_Node.ln_Pri = 85;
Audio_Request.ioa_Data		    = Audio_AllocMap;
Audio_Request.ioa_Length	    = (ULONG) sizeof(Audio_AllocMap);

if (OpenDevice(AUDIONAME, NULL, (char *) &Audio_Request, NULL))
	cleanup("can't open audio device",8);

Audio_Request.ioa_Request.io_Command	= CMD_WRITE;
Audio_Request.ioa_Request.io_Flags	= ADIOF_PERVOL;
Audio_Request.ioa_Data		= BeepWave;
Audio_Request.ioa_Length	= BEEPSIZE;
Audio_Request.ioa_Period	= COLORCLOCK / (BEEPSIZE * BEEPFREQ);
Audio_Request.ioa_Volume	= p_volume;
Audio_Request.ioa_Cycles	= 100;
}

/*****************************************************************/
/*    The following function initializes the structure arrays    */
/*   needed to provide the File menu topic.                      */
/*****************************************************************/
void InitFileItems()
    {
    int	    n,nplus1;

/* initialize each menu item and IntuiText with loop */
for( n=0; n<FILEMAX; n++ )
    {
    nplus1 = n + 1;
    FileItem[n].NextItem = &FileItem[nplus1];
    FileItem[n].LeftEdge = 0;
    FileItem[n].TopEdge = 10 * n;
    FileItem[n].Width = 120+40;
    FileItem[n].Height = 10;
    FileItem[n].Flags = ITEMTEXT | ITEMENABLED | HIGHCOMP;
    FileItem[n].MutualExclude = 0;
    FileItem[n].ItemFill = (APTR)&FileText[n];
    FileItem[n].SelectFill = NULL;
    if (n >= 2 && n <= 7) {
	FileItem[n].Command  = cmds[n-2];
	FileItem[n].Flags   |= COMMSEQ;
	}
    else FileItem[n].Command = 0;
    FileItem[n].SubItem = NULL;
    FileItem[n].NextSelect = 0;

    FileText[n].FrontPen = 0;
    FileText[n].BackPen = 1;
    FileText[n].DrawMode = JAM2;/* render in fore and background */
    FileText[n].LeftEdge = 0;
    FileText[n].TopEdge = 1;
    FileText[n].ITextFont = NULL;
    FileText[n].NextText = NULL;
    }
FileItem[FILEMAX-1].NextItem = NULL;

/* initialize text for specific menu items */

FileText[0].IText = (UBYTE *)"Ascii  Capture";
FileText[1].IText = (UBYTE *)"Ascii  Send";
FileText[2].IText = (UBYTE *)"Xmodem Receive";
FileText[3].IText = (UBYTE *)"Xmodem Send";
FileText[4].IText = (UBYTE *)"Kermit Get";
FileText[5].IText = (UBYTE *)"Kermit Receive";
FileText[6].IText = (UBYTE *)"Kermit Send";
FileText[7].IText = (UBYTE *)"Kermit BYE";
}

/******************************************************************
/*			Main Comm menu
/*		set up for Baud & Parity submenus
/******************************************************************/
void InitCommItems()
    {
    int	    n,nplus1;

/* initialize each menu item and IntuiText with loop */
for( n=0; n<COMMAX; n++ )
    {
    nplus1 = n + 1;
    CommItem[n].NextItem = &CommItem[nplus1];
    CommItem[n].LeftEdge = 0;
    CommItem[n].TopEdge = 10 * n;
    CommItem[n].Width = 88;
    CommItem[n].Height = 10;
    CommItem[n].Flags = ITEMTEXT | ITEMENABLED | HIGHCOMP ;
    CommItem[n].MutualExclude = 0;
    CommItem[n].ItemFill = (APTR)&CommText[n];
    CommItem[n].SelectFill = NULL;
    CommItem[n].Command = 0;
    CommItem[n].NextSelect = 0;

    CommText[n].FrontPen = 0;
    CommText[n].BackPen = 1;
    CommText[n].DrawMode = JAM2;    
    CommText[n].LeftEdge = 0;
    CommText[n].TopEdge = 1;
    CommText[n].ITextFont = NULL;
    CommText[n].NextText = NULL;
    }
CommItem[COMMAX-1].NextItem = NULL;

CommText[0].IText = (UBYTE *)"Baud Rate";
CommText[1].IText = (UBYTE *)"Parity   ";
CommText[2].IText = (UBYTE *)"Xfer Mode";
CommItem[0].SubItem = RSItem;
CommItem[1].SubItem = ParItem;
CommItem[2].SubItem = XFItem;

/*****************************************************************/
/*    The following initializes the structure arrays		 */
/*   needed to provide the BaudRate Submenu topic.               */
/*****************************************************************/

for( n=0; n<RSMAX; n++ )
    {
    nplus1 = n + 1;
    RSItem[n].NextItem = &RSItem[nplus1];
    RSItem[n].LeftEdge = 75;
    RSItem[n].TopEdge = 10 * n;
    RSItem[n].Width = 56+40;
    RSItem[n].Height = 10;
    RSItem[n].Flags = ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT;
    RSItem[n].MutualExclude = (~(1 << n));
    RSItem[n].ItemFill = (APTR)&RSText[n];
    RSItem[n].SelectFill = NULL;
    if (n >= 1 && n <= 2) {
	RSItem[n].Command    = cmds[n+5];
	RSItem[n].Flags	    |= COMMSEQ;
	}
    else RSItem[n].Command = 0;
    RSItem[n].SubItem = NULL;
    RSItem[n].NextSelect = 0;

    RSText[n].FrontPen = 0;
    RSText[n].BackPen = 1;
    RSText[n].DrawMode = JAM2;     /* render in fore and background */
    RSText[n].LeftEdge = 0;
    RSText[n].TopEdge = 1;
    RSText[n].ITextFont = NULL;
    RSText[n].NextText = NULL;
    }
RSItem[RSMAX-1].NextItem = NULL;

/* select baud item chekced */
switch (p_baud) {
    case 300:	n = 0; break;
    case 1200:	n = 1; break;
    case 2400:	n = 2; break;
    case 4800:	n = 3; break;
    case 9600:	n = 4; break;
    default:	n = 2; p_baud = 2400;
    }
RSItem[n].Flags |= CHECKED;

/* initialize text for specific menu items */
RSText[0].IText = (UBYTE *)"   300";
RSText[1].IText = (UBYTE *)"  1200";
RSText[2].IText = (UBYTE *)"  2400";
RSText[3].IText = (UBYTE *)"  4800";
RSText[4].IText = (UBYTE *)"  9600";

/*****************************************************************/
/*    The following initializes the structure arrays		 */
/*   needed to provide the Parity   Submenu topic.               */
/*****************************************************************/

for( n=0; n<PARMAX; n++ )
    {
    nplus1 = n + 1;
    ParItem[n].NextItem = &ParItem[nplus1];
    ParItem[n].LeftEdge = 75;
    ParItem[n].TopEdge = 10 * n;
    ParItem[n].Width = 56+40;
    ParItem[n].Height = 10;
    ParItem[n].Flags = ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT;
    ParItem[n].MutualExclude = (~(1 << n));
    ParItem[n].ItemFill = (APTR)&ParText[n];
    ParItem[n].SelectFill = NULL;
    if (n == 0 || n == 3 || n == 4) {
	ParItem[n].Command   = cmds[(n==0)?8:n+6];
	ParItem[n].Flags    |= COMMSEQ;
	}
    else ParItem[n].Command = 0;
    ParItem[n].SubItem = NULL;
    ParItem[n].NextSelect = 0;

    ParText[n].FrontPen = 0;
    ParText[n].BackPen = 1;
    ParText[n].DrawMode = JAM2;/* render in fore and background */
    ParText[n].LeftEdge = 0;
    ParText[n].TopEdge = 1;
    ParText[n].ITextFont = NULL;
    ParText[n].NextText = NULL;
    }
ParItem[PARMAX-1].NextItem = NULL;

/* select parity item chekced */
ParItem[p_parity].Flags |= CHECKED;

/* initialize text for specific menu items */
ParText[0].IText = (UBYTE *)"  None ";
ParText[1].IText = (UBYTE *)"  Mark ";
ParText[2].IText = (UBYTE *)"  Space";
ParText[3].IText = (UBYTE *)"  Even ";
ParText[4].IText = (UBYTE *)"  Odd  ";

/*****************************************************************/
/*    The following initializes the structure arrays		 */
/*    needed to provide the Transfer Mode menu topic.            */
/*****************************************************************/

/* initialize each menu item and IntuiText with loop */
for( n=0; n<XFMAX; n++ )
    {
    nplus1 = n + 1;
    XFItem[n].NextItem = &XFItem[nplus1];
    XFItem[n].LeftEdge = 75;
    XFItem[n].TopEdge = 10 * n;
    XFItem[n].Width = 80+40;
    XFItem[n].Height = 10;
    XFItem[n].Flags = ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT;
    if (n < 2)  XFItem[n].MutualExclude = 2 - n;
    else	XFItem[n].MutualExclude = 0;
    XFItem[n].ItemFill = (APTR)&XFText[n];
    XFItem[n].SelectFill = NULL;
    if (n < 2) {
	XFItem[n].Command    = cmds[n+11];
	XFItem[n].Flags	    |= COMMSEQ;
	}
    else XFItem[n].Command = 0;
    XFItem[n].SubItem = NULL;
    XFItem[n].NextSelect = 0;

    XFText[n].FrontPen = 0;
    XFText[n].BackPen = 1;
    XFText[n].DrawMode = JAM2;
    XFText[n].LeftEdge = 0;
    XFText[n].TopEdge = 1;
    XFText[n].ITextFont = NULL;
    XFText[n].NextText = NULL;
    }
XFItem[XFMAX-1].NextItem = NULL;
/* mode checked */
XFItem[p_mode].Flags |= CHECKED;
if (p_convert)	XFItem[2].Flags |= CHECKED;

/* initialize text for specific menu items */
XFText[0].IText = (UBYTE *)"  Image  ";
XFText[1].IText = (UBYTE *)"  Text   ";
XFText[2].IText = (UBYTE *)"  Convert";

} /* end of InitCommItems() */


/*****************************************************************/
/*    The following function initializes the structure arrays    */
/*   needed to provide the Script menu topic.                    */
/*****************************************************************/
void InitScriptItems()
{
int n,nplus1;

/* initialize each menu item and IntuiText with loop */
for( n=0; n<SCRIPTMAX; n++ )
    {
    nplus1 = n + 1;
    ScriptItem[n].NextItem = &ScriptItem[nplus1];
    ScriptItem[n].LeftEdge = 0;
    ScriptItem[n].TopEdge = 10 * n;
    ScriptItem[n].Width = 128;
    ScriptItem[n].Height = 10;
    ScriptItem[n].Flags = ITEMTEXT | ITEMENABLED | HIGHCOMP;
    ScriptItem[n].MutualExclude = 0;
    ScriptItem[n].ItemFill = (APTR)&ScriptText[n];
    ScriptItem[n].SelectFill = NULL;
    ScriptItem[n].Command = 0;
    ScriptItem[n].SubItem = NULL;
    ScriptItem[n].NextSelect = 0;

    ScriptText[n].FrontPen = 0;
    ScriptText[n].BackPen = 1;
    ScriptText[n].DrawMode = JAM2;/* render in fore and background */
    ScriptText[n].LeftEdge = 0;
    ScriptText[n].TopEdge = 1;
    ScriptText[n].ITextFont = NULL;
    ScriptText[n].NextText = NULL;
    }
ScriptItem[SCRIPTMAX-1].NextItem = NULL;

/* initialize text for specific menu items */
ScriptText[0].IText = (UBYTE *)"Execute file";
ScriptText[1].IText = (UBYTE *)"Abort Execution";
}

/*****************************************************************/
/*    The following function initializes the structure arrays    */
/*   needed to provide the Util menu topic.                    */
/*****************************************************************/
void InitUtilItems()
    {
    int	    n,nplus1;

/* initialize each menu item and IntuiText with loop */
for( n=0; n<UTILMAX; n++ )
    {
    nplus1 = n + 1;
    UtilItem[n].NextItem = &UtilItem[nplus1];
    UtilItem[n].LeftEdge = 0;
    UtilItem[n].TopEdge = 10 * n;
    UtilItem[n].Width = 88+40;
    UtilItem[n].Height = 10;
    UtilItem[n].Flags = ITEMTEXT | ITEMENABLED | HIGHCOMP;
    if (n > 3) UtilItem[n].Flags |= CHECKIT;
    UtilItem[n].MutualExclude = 0;
    UtilItem[n].ItemFill = (APTR)&UtilText[n];
    UtilItem[n].SelectFill = NULL;
    if (n == 0 || n == 2) {
	UtilItem[n].Command   = cmds[(n==0)?13:14];
	UtilItem[n].Flags    |= COMMSEQ;
	}
    else if (n >= 5) {
	UtilItem[n].Command   = cmds[n+10];
	UtilItem[n].Flags    |= COMMSEQ;
	}
    else UtilItem[n].Command = 0;
    UtilItem[n].SubItem = NULL;
    UtilItem[n].NextSelect = 0;

    UtilText[n].FrontPen = 0;
    UtilText[n].BackPen = 1;
    UtilText[n].DrawMode = JAM2;/* render in fore and background */
    UtilText[n].LeftEdge = 0;
    UtilText[n].TopEdge = 1;
    UtilText[n].ITextFont = NULL;
    UtilText[n].NextText = NULL;
    }
UtilItem[UTILMAX-1].NextItem = NULL;

if (p_echo)	    UtilItem[4].Flags |= CHECKED;
if (p_wrap)	    UtilItem[5].Flags |= CHECKED;
if (p_keyapp == 0)  UtilItem[6].Flags |= CHECKED;
if (p_curapp)	    UtilItem[7].Flags |= CHECKED;
if (p_bs_del)	    UtilItem[8].Flags |= CHECKED;

/* initialize text for specific menu items */
UtilText[0].IText = (UBYTE *)"Send Break";
UtilText[1].IText = (UBYTE *)"Hang Up";
UtilText[2].IText = (UBYTE *)"Change Dir";
UtilText[3].IText = (UBYTE *)"Clear Scrn";
UtilText[4].IText = (UBYTE *)"  Echo";
UtilText[5].IText = (UBYTE *)"  Wrap";
UtilText[6].IText = (UBYTE *)"  Num Key";
UtilText[7].IText = (UBYTE *)"  App Cur";
UtilText[8].IText = (UBYTE *)"  BS<->DEL";
}

/****************************************************************/
/*   The following function inits the Menu structure array with */
/*  appropriate values for our simple menu.  Review the manual  */
/*  if you need to know what each value means.                  */
/****************************************************************/
void InitMenu()
{
menu[0].NextMenu = &menu[1];
menu[0].LeftEdge = 5;
menu[0].TopEdge = 0;
menu[0].Width = 40;
menu[0].Height = 10;
menu[0].Flags = MENUENABLED;
menu[0].MenuName = "File";        /* text for menu-bar display */
menu[0].FirstItem = &FileItem[0]; /* pointer to first item in list */

menu[1].NextMenu = &menu[2];
menu[1].LeftEdge = 55;
menu[1].TopEdge = 0;
menu[1].Width = 88;
menu[1].Height = 10;
menu[1].Flags = MENUENABLED;
menu[1].MenuName = "Comm Setup";   /* text for menu-bar display */
menu[1].FirstItem = &CommItem[0];  /* pointer to first item in list */

menu[2].NextMenu = &menu[3];
menu[2].LeftEdge = 153;
menu[2].TopEdge = 0;
menu[2].Width = 56;
menu[2].Height = 10;
menu[2].Flags = MENUENABLED;
menu[2].MenuName = "Script";        /* text for menu-bar display */
menu[2].FirstItem = &ScriptItem[0]; /* pointer to first item in list*/

menu[3].NextMenu = &menu[4];		/* link to tek menu items	*/
menu[3].LeftEdge = 225;
menu[3].TopEdge = 0;
menu[3].Width = 64;
menu[3].Height = 10;
menu[3].Flags = MENUENABLED;
menu[3].MenuName = "Utility";      /* text for menu-bar display */
menu[3].FirstItem = &UtilItem[0];  /* pointer to first item in list*/
}
SHAR_EOF
cat << \SHAR_EOF > kermit.c
/*************************************************************
 * vt100 terminal emulator - KERMIT protocol support
 *
 *	v2.6 870227 DBW - bug fixes for all the stuff in v2.5
 *	v2.5 870214 DBW - more additions (see readme file)
 *	v2.4 861214 DBW - lots of fixes/additions (see readme file)
 *	v2.3 861101 DBW - minor bug fixes
 *	v2.2 861012 DBW - more of the same
 *	v2.1 860915 DBW - new features (see README)
 *	     860901 ACS - Added eight bit quoting
 *           860830 Steve Drew Wild card support, err recovry,bugs.
 *	     860823 DBW - Integrated and rewrote lots of code
 *           860811 Steve Drew multi filexfer, bugs, status line ect..
 *	v2.0 860809 DBW - Major rewrite
 *	v1.1 860720 DBW	- Switches, 80 cols, colors, bug fixes
 *	v1.0 860712 DBW	- First version released
 *
 *************************************************************/

#include "vt100.h"

#define MAXPACKSIZ 94       /* Maximum msgpkt size */
#define CR         13       /* ASCII Carriage Return */
#define LF         10       /* ASCII line feed */
#define SP         32       /* ASCII space */
#define DEL       127       /* Delete (rubout) */

#define MAXTRY    5        /* Times to retry a msgpkt */
#define MYQUOTE  '#'       /* Quote character I will use */
#define MYRPTQ   '~'       /* Repeat quote character */
#define MYEBQ	 '&'	   /* 8th bit prefix character */
#define MYPAD      0       /* Number of padding charss I will need */
#define MYPCHAR    0       /* Padding character I need (NULL) */
#define MYEOL    '\n'      /* End-Of-Line character I need */

#define tochar(ch)  ((ch) + ' ')
#define unchar(ch)  ((ch) - ' ')
#define ctl(ch)     ((ch) ^ 64 )

/* Global Variables */

int
   size,      /* Size of present data */
   osize,     /* Size of last data entry */
   rpsiz,     /* Maximum receive msgpkt size */
   spsiz,     /* Maximum send msgpkt size */
   timint,    /* Time interval to wait */
   pad,       /* How much padding to send */
   n,         /* Packet number */
   tp,        /* total packets */
   numtry,    /* Times this msgpkt retried */
   retry,     /* total retries */
   oldtry,    /* Times previous msgpkt retried */
   sendabort, /* flag for aborting send file  */
   rptflg,    /* are we doing repeat quoting */
   ebqflg,    /* are we doing 8th bit quoting */
   notfirst,  /* is this the first file received */
   first,     /* is this the first time in a file */
   rpt,       /* current repeat count */
   next,      /* what is the next character */
   t;         /* current character */
long
   totbytes;  /* total bytes xfered on this file */

char 
   state,     /* Present state of the automaton */
   padchar,   /* Padding character to send */
   eol,       /* End-Of-Line character to send */
   quote,     /* Quote character in incoming data */
   rptq,      /* Quote character for repeats */
   ebq,	      /* Quote character for 8th bit quoting */
   ackpkt[MAXPACKSIZ+20], /* ACK/NAK packet buffer */
   msgpkt[MAXPACKSIZ+20], /* Message Packet buffer */
   filnam[40],            /* remote file name */
   snum[10],
   sl1[] = "FILE            PKT NUM RETR BYTES",
   sl2[] = "%-15s  %c %4d  %2d %6ld %5s",
   sl3[50],
   mainmode[10];

FILE *fp;     /* file for send/receive */

char *
getfname(name)   /* returns ptr to start of file name from spec */
char *name;
    {
    int l;

    l = strlen(name);
    while(l && name[l] != '/' && name[l] != ':') l--;
    if (name[l] == '/' || name[l] == ':') l++;
    return(name += l);
    }
    
doksend(file,more)
char *file;
int more;
   {
   int amount, c, wild;
   char *p, **list = NULL;

   if (!strcmp(file,"$")) { saybye(); return(2); }
   p = file;
   while(*p && *p != '*' && *p != '?') p++;
   if (*p) { 
       wild = TRUE;
       list = expand(file, &amount);
       if (list == NULL)  req("KERMIT","No wild card match",0);
       }
   else {
       wild = FALSE;
       amount = 1;
       }
   for (c = 0; c < amount; c++) {
       if (wild == TRUE) p = list[c];
         else  p = file;
       strcpy(filnam,getfname(p));
       ttime = TTIME_KERMIT;
       tp = retry = n = numtry = 0; totbytes = 0L;
       if ((fp = fopen(p,"r")) == NULL) {
           req("KERMIT: can't open send file:",p,0);
           continue;
           }
       strcpy(mainmode,"SEND");
       ClearBuffer();
       if (sendsw()) dostats(' ',"DONE");
       fclose(fp);
       } 
   free_expand(list);
   return TRUE;
   }
 
dokreceive(file,more)
char *file;
int more;
   {
   int retval;
   
   ttime = TTIME_KERMIT;
   if (!strcmp(file,"$")) { saybye(); return(2); }
   strcpy(filnam, file);   
   if (server) strcpy(mainmode,"GET");
   else	       strcpy(mainmode,"RECV");
   tp =  retry = n =  numtry = notfirst = 0; totbytes = 0L;
   ClearBuffer();
   retval  = recsw();
   return(retval);
   }

sendsw()
   {
   char sinit(), sfile(), sdata(), seof(), sbreak();
   sendabort = 0;
   state = 'S';
   while(TRUE) {
      switch(state) {
         case 'S':   state = sinit();  break;
         case 'F':   state = sfile();  break;
         case 'D':   state = sdata();  break;
         case 'Z':   state = seof();   break;
         case 'B':   state = sbreak(); break;
         case 'C':   if (sendabort) return FALSE;
                     else return TRUE;
         case 'E':   dostats('E',"ERROR");  /* so print the err and abort */
                     print_host_err(ackpkt);
                     return(FALSE);
         case 'A':   if (timeout == USERABORT) {
			 timeout = GOODREAD;
                         n = (n+1)%64;			 
                     	 sendabort = 1;
                     	 dostats('A',"ABORT");
                     	 strcpy(msgpkt, "D");
                     	 state = 'Z'; 
                     	 break;
                     	 }
                     if (timeout == TIMEOUT)  dostats('A',"TMOUT");
                     else { /* protocol error dectected by us */
			 dostats('A',"ERROR");
			 print_our_err();
			 }
                     return(FALSE);
         default:    return(FALSE);
         }
      }
   }

char sinit()
   {
   int num, len;
   
   retry++;
   if (numtry++ > MAXTRY) return('A');
   spar(msgpkt);

   spack('S',n,9,msgpkt);
   switch(rpack(&len,&num,ackpkt)) {
      case 'N':  return(state);
      case 'Y':  if (n != num) return(state);
                 rpar(ackpkt);
                 if (eol == 0) eol = '\n';
                 if (quote == 0) quote = MYQUOTE;
                 numtry = 0;
                 retry--;
                 n = (n+1)%64;
                 return('F');
      case 'E':  return('E');
      case FALSE:if (timeout == USERABORT) state = 'A';
                 return(state);
      default:   return('A');
      }
    }

char sfile()
   {
   int num, len;

   retry++;
   if (numtry++ > MAXTRY) return('A');

   spack('F',n,strlen(filnam),filnam);
   switch(rpack(&len,&num,ackpkt)) {
      case 'N':
         num = (--num<0 ? 63:num);
         if (n != num) return(state);
      case 'Y':
         if (n != num) return(state);
         numtry = 0;
         retry--;
         n = (n+1)%64;
         first = 1;
         size = getpkt();
         return('D');
      case 'E':
         return('E');
      case FALSE: if (timeout == USERABORT) state = 'A';
                  return(state);
      default:
         return('A');
      }
   }

char sdata()
   {
   int num, len;
   
   retry++;
   if (numtry++ > MAXTRY) return('A');

   spack('D',n,size,msgpkt);
   switch(rpack(&len,&num,ackpkt)) {
      case 'N':
         num = (--num<0 ? 63:num);
         if (n != num) return(state);
      case 'Y':
         if (n != num) return(state);
         numtry = 0;
         retry--;
         n = (n+1)%64;
         if ((size = getpkt()) == 0) return('Z');
         return('D');
      case 'E':
         return('E');
      case FALSE: if (timeout == USERABORT) state = 'A';
                  return(state);
      default:    
         return('A');
      }
   }

char seof()
   {
   int num, len;
   retry++;
   if (numtry++ > MAXTRY) return('A');

/*   if (timeout == USERABORT) {*/	/* tell host to discard file */
/*      timeout = GOODREAD;	*/
/*        spack('Z',n,1,"D");	*/
/*        }			*/
/*   else			*/
	spack('Z',n,sendabort,msgpkt);
   switch(rpack(&len,&num,ackpkt)) {
      case 'N':
         num = (--num<0 ? 63:num);
         if (n != num) return(state);
      case 'Y':
         if (n != num) return(state);
         numtry = 0;
         retry--;
         n = (n+1)%64;
         return('B');
      case 'E':
         return('E');
      case FALSE: return(state);
      default:
         return('A');
      }
   }

char sbreak()
   {
   int num, len;
   retry++;
   if (numtry++ > MAXTRY) return('A');

   spack('B',n,0,msgpkt);
   switch (rpack(&len,&num,ackpkt)) {
      case 'N':
         num = (--num<0 ? 63:num);
         if (n != num) return(state);
      case 'Y':
         if (n != num) return(state);
         numtry = 0;
	 retry--;
         n = (n+1)%64;
         return('C');
      case 'E':
         return('E');
      case FALSE: return(state);
      default:    return ('A');
      }
   }

/* timeout equals USERABORT so lets end the file and quit  */
/* when host receives 'Z' packet with "D" in data field he */
/* should discard the file.                                */
/*
sabort()
   {
   dostats(' ',"ABORT");
   n = (n+1)%64;
   retry--;
   state = 'Z';
   while (state == 'Z') state = seof();
   while (state == 'B') state = sbreak();
   return(FALSE);
   }
*/ 


recsw()
   {
   char rinit(), rfile(), rdata();

   state = 'R';
   
   while(TRUE) {
      switch(state) {
         case 'R':   state = rinit(); break;
         case 'Z':
         case 'F':   state = rfile(); break;
         case 'D':   state = rdata(); break;
         case 'C':   return(TRUE);
         case 'E':
         case 'A':   /* easy way to cleanly abort
			should really send and ACK
			with "X" in data field and 
			wait for host to abort but
			not all kermits support
			this feature.           */
		    if (timeout == USERABORT){
			/* send an error packet back   */
                         dostats('A',"ABORT");
                         spack('E',n,12,"User aborted"); 
                     }
                     else if (timeout == TIMEOUT) {
			    /* we timed out waiting */
    			    /* will we need to spack here ?*/
			 dostats('A',"TMOUT");
			 }
			    /* must be 'E' from host or we
			     detected a protocol error */
                         else dostats('A',"ERROR");

		     if (state == 'E') print_host_err(msgpkt);

		     else if (timeout == GOODREAD) /* tell host why */
			print_our_err();
			   /* will this kill all files ?*/
                     do  {
                         ttime = 2;        
                         readchar();
                         }  while (timeout == GOODREAD);
                     fclose(fp);
                     sendstring("\r");
                     return(FALSE);
	 default:    return(FALSE);	
         }
      }
   }



char rinit()
   {
   int len, num;
   retry++;
   if (numtry++ > MAXTRY) return('A');

   if (server) spack('R',n,strlen(filnam),filnam);
   else  spack('N',n,0,0);
   switch(rpack(&len,&num,msgpkt)) {
      case 'S':
         rpar(msgpkt);
         spar(msgpkt);
         spack('Y',n,9,msgpkt);
         oldtry = numtry;
         numtry = 0;
         retry--;
         n = (n+1)%64;
         return('F');
      case 'E':
         return('E');
      case FALSE:
         if (timeout == USERABORT) return('A');
         spack('N',n,0,0);
         return(state);
      default:
         return('A');
      }
   }

char rfile()
   {
   int num, len;
   retry++;
   if (numtry++ > MAXTRY) return('A');

   switch(rpack(&len,&num,msgpkt)) {
      case 'S':
         if (oldtry++ > MAXTRY) return('A');
         if (num == ((n==0) ? 63:n-1)) {
            spar(msgpkt);
            spack('Y',num,9,msgpkt);
            numtry = 0;
            return(state);
            }
         else return('A');
      case 'Z':
         if (oldtry++ > MAXTRY) return('A');
         if (num == ((n==0) ? 63:n-1)) {
            spack('Y',num,0,0);
            numtry = 0;
            return(state);
            }
         else return('A');
      case 'F':
         if (num != n) return('A');
	 strcpy(filnam,msgpkt);
         if (p_convert) {
             char *p;
	     p = &filnam[0];
             while (*p) { *p = tolower(*p); p++; }
             }
	 if (notfirst) { 
             totbytes = 0L;
             dostats('F',"RECV");
             }
	 /* is the first file so emit actual file name from host */
         else {
	     notfirst++;
	     }
         if ((fp = fopen(filnam,"w")) == NULL) {
	     req("KERMIT: Unable to create file:",filnam,0);
	     strcpy(msgpkt,"VT100 - Kermit - cannot create file: ");
	     strcat(msgpkt,filnam);
	     spack('E',n,strlen(msgpkt),msgpkt); /* let host know */
             dostats('E',"ERROR");
             return ('\0');       /* abort everything */
             }
         spack('Y',n,0,0);
         oldtry = numtry;
         numtry = 0;
         retry--;
         n = (n+1)%64;
         return('D');

      /* totaly done server sending no more */
      case 'B':
         if (num != n) return ('A');
         spack('Y',n,0,0);
         retry--;
         return('C');
      case 'E':
         return('E');
      case FALSE:
         if (timeout == USERABORT) return('A');
         spack('N',n,0,0);
         return(state);
      default:
         return ('A');
      }
   }

char rdata()
   {
   int num, len;
   retry++;
   if (numtry++ > MAXTRY) return('A');

   switch(rpack(&len,&num,msgpkt)) {
      case 'D':
         if (num != n) {
            if (oldtry++ > MAXTRY) return('A');
            if (num == ((n==0) ? 63:n-1)) {
               spack('Y',num,6,msgpkt); 
               numtry = 0;
               return(state);
               }
            else return('A');
            }
         decode();
         spack('Y',n,0,0);
         oldtry = numtry;
         numtry = 0;
         retry--;
         n = (n+1)%64;
         return('D');
      case 'Z':
         if (num != n) return('A');
         spack('Y',n,0,0);
         n = (n+1)%64;
         retry--;
         dostats('Z',"DONE");
	 fclose(fp);
         return('Z');
      case 'F':
         if (oldtry++ > MAXTRY) return('A');
         if (num == ((n==0) ? 63:n-1)) {
	     spack('Y',num,0,0);
	     numtry = 0;
	     return(state);
             }
      case 'E':
         return('E');
      case FALSE:
         if (timeout == USERABORT) return('A');
         spack('N',n,0,0);
         return(state);
      default:
        return('A');
      }
   }


spack(type,num,len,data)
char type, *data;
int num, len;
   {
   int i;
   char chksum, buffer[100];
   register char *bufp;
   
   dostats(type,mainmode);
   bufp = buffer;
   ClearBuffer();
   for (i=1; i<=pad; i++) sendchar(padchar);

   *bufp++ = SOH;
   *bufp++ = tochar(len+3);
   chksum  = tochar(len+3);
   *bufp++ = tochar(num);
   chksum += tochar(num);
   *bufp++ = type;
   chksum += type;

   for (i=0; i<len; i++) {
      *bufp++ = data[i];
      chksum += data[i];
      }
   chksum = (((chksum&0300) >> 6)+chksum)&077;
   *bufp++ = tochar(chksum);
   *bufp++ = '\r';
   *bufp++ = '\n';
   *bufp   = 0;
   sendstring(buffer);
   }

rpack(len,num,data)
int *len, *num;
char *data;
   {
   int i, done;
   char type, cchksum, rchksum;
   char t = '\0';

    do {
       t = readchar();
       if (timeout != GOODREAD) return(FALSE);
       } while (t != SOH);

    done = FALSE;
    while (!done) {
       t = readchar();
       if (timeout != GOODREAD) return(FALSE);
       if (t == SOH) continue;
       cchksum = t;
       *len = unchar(t)-3;
       t = readchar();
       if (timeout != GOODREAD) return(FALSE);
       if (t == SOH) continue;
       cchksum = cchksum + t;
       *num = unchar(t);
       t = readchar();
       if (timeout != GOODREAD) return(FALSE);
       if (t == SOH) continue;
       cchksum = cchksum + t;
       type = t;
       for (i=0; i<*len; i++) {
          t = readchar();
          if (timeout != GOODREAD) return(FALSE);
          if (t == SOH) continue;
          cchksum = cchksum + t;
          data[i] = t;
          }
       data[*len] = 0;
       t = readchar();
       if (timeout != GOODREAD) return(FALSE);
       rchksum = unchar(t);
       t = readchar();
       if (timeout != GOODREAD) return(FALSE);
       if (t == SOH) continue;
       done = TRUE;
       }
   dostats(type,mainmode);
   cchksum = (((cchksum&0300) >> 6)+cchksum)&077;
   if (cchksum != rchksum) return(FALSE);
   return((int)type);
   }

getpkt() {
   int i,eof;

   static char leftover[10] = { '\0', '\0', '\0', '\0', '\0',
			        '\0', '\0', '\0', '\0', '\0' };

   if (first == 1) {
      first = 0;
      *leftover = '\0';
      t = getc(fp);
      if (t == EOF) {
         first = 1;
         return(size = 0);
         }
      totbytes++;
      }
   else if (first == -1) {
      first = 1;
      return(size = 0);
      }
   for (size = 0; (msgpkt[size] = leftover[size]) != '\0'; size++) ;
   *leftover = '\0';
   rpt = 0;
   eof = 0;
   while (!eof) {
      next = getc(fp);
      if (next == EOF) {
         first = -1;
         eof   =  1;
         }
      else totbytes++;
      osize = size;
      encode(t);
      t = next;
      if (size == spsiz-3) return(size);
      if (size > spsiz-3) {
         for (i = 0; (leftover[i] = msgpkt[osize+i]) != '\0'; i++) ;
         size = osize;
         msgpkt[size] = '\0';
         return(size);
         }
      }
   return(size);
   }

void encode(a)
char a;
   {
   int a7,b8;

   if (p_mode == 1 && a == '\n') {
      rpt = 0;
      msgpkt[size++] = quote;
      msgpkt[size++] = ctl('\r');
      if (size <= spsiz-3) osize = size;
      msgpkt[size++] = quote;
      msgpkt[size++] = ctl('\n');
      msgpkt[size]   = '\0';
      return;
      }
   if (rptflg) {
      if (a == next && (first == 0)) {
         if (++rpt < 94) return;
         else if (rpt == 94) {
            msgpkt[size++] = rptq;
            msgpkt[size++] = tochar(rpt);
            rpt = 0;
            }
         }
      else if (rpt == 1) {
         rpt = 0;
         encode(a);
         if (size <= spsiz-3) osize = size; 
         rpt = 0;
         encode(a);
         return;
         }
      else if (rpt > 1) {
         msgpkt[size++] = rptq;
         msgpkt[size++] = tochar(++rpt);
         rpt = 0;
         }
      }
   a7 = a & 0177;
   b8 = a & 0200;

   if (ebqflg && b8) {			/* Do 8th bit prefix if necessary. */
	msgpkt[size++] = ebq;
	a = a7;
	}
   
   if ((a7 < SP) || (a7==DEL)) {
      msgpkt[size++] = quote;
      a = ctl(a);
      }
   if (a7 == quote) msgpkt[size++] = quote;
   if ((rptflg) && (a7 == rptq)) msgpkt[size++] = quote;

   if ((ebqflg) && (a7 == ebq))	/* Prefix the 8th bit prefix */
       msgpkt[size++] = quote;  /* if doing 8th-bit prefixes */

   msgpkt[size++] = a;
   msgpkt[size] = '\0';
   }

void decode()
   {
   USHORT  a, a7, b8;
   char *buf;

   buf = msgpkt;
   rpt = 0;
   
   while ((a = *buf++) != '\0') {
      if (rptflg) {
         if (a == rptq) {
            rpt = unchar(*buf++);
            a = *buf++;
            }
         }
      b8 = 0;
      if (ebqflg) {                  /* 8th-bit prefixing? */
	  if (a == ebq) {            /* Yes, got an 8th-bit prefix? */
	      b8 = 0200;             /* Yes, remember this, */
	      a = *buf++;            /* and get the prefixed character. */
	  }
      }
      if (a == quote) {
         a  = *buf++;
         a7 = a & 0177;
         if ((a7 >= 0100 && a7 <= 0137) || a7 == '?') a = ctl(a);
         }
      a |= b8;
      if (rpt == 0) rpt = 1;
      if (p_mode == 1 && a == '\r') continue;
      totbytes += rpt;
      for (; rpt > 0; rpt--) putc(a, fp);
      }
   return;
   }

void spar(data)
char data[];
   {
   data[0] = tochar(MAXPACKSIZ);
   data[1] = tochar(TTIME_KERMIT);
   data[2] = tochar(MYPAD);
   data[3] = ctl(MYPCHAR);
   data[4] = tochar(MYEOL);
   data[5] = MYQUOTE;
   if ((p_parity > 0) || ebqflg) {         /* 8-bit quoting... */
	data[6] = MYEBQ;          /* If parity or flag on, send &. */
	if ((ebq > 0040 && ebq < 0100) || /* If flag off, then turn it on  */
	   (ebq > 0140 && ebq < 0177) || /* if other side has asked us to */
	   (ebq == 'Y')) ebqflg = 1;
	}
    else				    /* Normally, */
       data[6] = 'Y';			    /* just say we're willing. */
    data[7] = '1';
    data[8] = MYRPTQ;
    data[9] = '\0';
    }

void rpar(data)
char data[];
    {
    spsiz   = unchar(data[0]);
    ttime   = unchar(data[1]);
    pad     = unchar(data[2]);
    padchar = ctl(data[3]);
    eol     = unchar(data[4]);
    quote   = data[5];
    rptflg  = 0;
    ebqflg  = 0;
    if (data[6] == 0) return;
    ebq = data[6];
    if ((ebq > 040 && ebq < 0100) || 
	(ebq > 0140 && ebq < 0177)) ebqflg = 1;
    else if (((p_parity > 0) || ebqflg) && (ebq == 'Y')) {
	ebqflg = 1;
	ebq = '&';
	}
    else ebqflg = 0;
    if (data[7] == 0) return;
    if (data[8] == 0) return;
    rptq    = data[8];
    rptflg  = ((rptq > 040 && rptq < 0100) || 
	(rptq > 0140 && rptq < 0177));
    }

saybye()
  {
  int len,num;
  spack('G',n,1,"F");  /* shut down server no more files */
  rpack(&len,&num,ackpkt);
  }

print_our_err()
    {
    if (retry > MAXTRY || oldtry > MAXTRY) {
	req("KERMIT:","Too may retries for packet",0);
	strcpy(msgpkt,"VT100 KERMIT: Too many retries for packet");
	}
    else {
	req("KERMIT:","Protocol Error",0);
	strcpy(msgpkt,"VT100 KERMIT: Protocol Error");
	}
    spack('E',n,strlen(msgpkt));
    }

print_host_err(msg)
  char *msg;
  {
  req("KERMIT Host Error:",msg,0);
  }

dostats(type,stat)
char type,*stat;
    {
    if (type == 'Y' || type == 'N' || type == 'G') return;
    sprintf(sl3,sl2,filnam,type,n+(tp*64),retry-1,(long)totbytes,stat);
    if (n==63) tp++;
    req(sl1,sl3,0);
    }

ClearBuffer()
    {
    AbortIO(Read_Request);
    Read_Request->IOSer.io_Command = CMD_CLEAR;
    DoIO(Read_Request);
    Read_Request->IOSer.io_Command = CMD_READ;
    SendIO(Read_Request);
    }

SHAR_EOF
cat << \SHAR_EOF > remote.c
/****************************************************
 * vt100 emulator - remote character interpretation
 *
 *	v2.65       NG  - added tek4014 emulation
 *	v2.6 870227 DBW - bug fixes for all the stuff in v2.5
 *	v2.5 870214 DBW - more additions (see readme file)
 *	v2.4 861214 DBW - lots of fixes/additions (see readme file)
 *	v2.3 861101 DBW - minor bug fixes
 *	v2.2 861012 DBW - more of the same
 *	v2.1 860915 DBW - new features (see README)
 *	     860823 DBW - Integrated and rewrote lots of code
 *	v2.0 860803 DRB - Rewrote the control sequence parser
 *	v1.1 860720 DBW	- Switches, 80 cols, colors, bug fixes
 *	v1.0 860712 DBW	- First version released
 *
 ****************************************************/

#include "vt100.h"

static int    p[10];
static int    numpar;
static char   escseq[40];

/************************************************
*  function to handle remote characters
*************************************************/
void doremote(c)
char c;
    {
	if (Tek(c))		/* added for tek emulation	*/
		return;

    if (c == 24) { inesc = 0; inctrl = 0; return; }
    if (c == 27 || (inesc >= 0 && c >= ' ')) { doesc(c); return; }
    if (inctrl >= 0 && c >= ' ') { doctrl(c); return; }
    if (c == 10 || c == 11 || c == 12) {
	if (nlmode) doindex('E'); else doindex('D');
	return;
	}
    if (c == 13) {
	if (!nlmode) emit(c);
	return;
	}
    if (c == 15) { alt = 0; return; }
    if (c == 14) { alt = 1; return; }
    if (a[alt] && c > 94 && c < 127) { doalt(c); return; }
    emit(c);
    }

void doesc(c)
char c;
{
    if (inesc < 0) { inesc = 0; return; }
    if (c == 27 || c == 24) { inesc = -1; return; }
    if (c < ' ' || c == 127) return;	  /* Ignore control chars */

    /* Collect intermediates */
    if (c < '0') {escseq[inesc++] = c; return; }

    /* by process of elimination, we have a final character.
       Put it in the buffer, and dispatch on the first character
       in the buffer */

    escseq[inesc] = c;
    inesc = -1;				/* No longer collecting a sequence */
    switch (escseq[0])			/* Dispatch on the first received */
    {
      case '[':				/* Control sequence introducer */
	numpar = 0;			/* No parameters yet */
	private = 0;			/* Not a private sequence (yet?) */
	badseq = 0;			/* Good until proven bad */
	p[0] = p[1] = 0;		/* But default the first parameter */
	inctrl = 0;			/* We are in a control sequence */
	return;				/* All done for now ... */

      case 'D': case 'E': case 'M':	/* Some kind of index */
	doindex (c);			/* Do the index */
	return;				/* Return */

      case '7':				/* Save cursor position */
	savx = x; savy = y; savmode = curmode; savalt = alt;
	sa[0] = a[0]; sa[1] = a[1];
	return;

      case '8':				/* Restore cursor position */
	x = savx; y = savy; alt = savalt; curmode = savmode;
	a[0] = sa[0]; a[1] = sa[1];
	return;

      case 'c':				/* Reset */
	top = MINY; bot = MAXY; savx = MINX; savy = MINY;
	curmode = FS_NORMAL; p_keyapp = 0; p_curapp = 0;
	inesc = -1;
	a[0] = 0; a[1] = 0; sa[0] = 0; sa[1] = 0;
	redoutil();
	emit(12);
	return;

      case '(':				/* Change character set */
	if (c == '0' || c == '2') a[0] = 1; else a[0] = 0;
	return;

      case ')':				/* Change the other character set */
	if (c == '0' || c == '2') a[1] = 1; else a[1] = 0;
	return;

      case '=':				/* set keypad application mode */
        p_keyapp = 1;
	redoutil();
        return;
        
      case '>':				/* reset application mode */
        p_keyapp = 0;
	redoutil();
        return;
        
      case 'Z':
	sendchar(27); sendstring("[?1;7c"); return;

      /* If we didn't match anything, we can just return, happy in the
	 knowledge that we've at least eaten the whole sequence */

    }					/* End of switch */
    return;
}

void doctrl(c)
char c;
{
    int	    i;

    if (c == 27 || c == 24) { inctrl = -1; return; }
    if (c < ' ' || c == 127) return;		  /* Ignore control chars */

    /* First, look for some parameter characters.  If the very first
	parameter character isn't a digit, then we have a 
	private sequence */

    if (c >= '0' && c < '@')
    {
	/* can't have parameters after intermediates */
	if (inctrl > 0) {badseq++ ; return; }
	switch (c)
	{
	  case '0': case '1': case '2': case '3': case '4':
	  case '5': case '6': case '7': case '8': case '9':
	    p[numpar] = p[numpar] * 10 + (c - '0');
	    return;

	  case ';':
	    p[++numpar] = 0;		/* Start a new parameter */
	    return;

	  case '<': case '=': case '>': case '?': /* Can only mean private */

	    /* Only allowed BEFORE parameters */
    	    if (inctrl == 0) private = c;
	    return;

	/* if we come here, it's a bad sequence */
	}
	badseq++;			/* Flag the bad sequence */
    }

    if (c < '0')			/* Intermediate character */
    {
	escseq[inctrl++] = c;		/* Save the intermediate character */
	return;
    }

    /* if we get here, we have the final character.  Put it in the 
       escape sequence buffer, then dispatch the control sequence */

    numpar++;				/* Reflect the real number of parameters */
    escseq[inctrl++] = c;		/* Store the final character */
    escseq[inctrl] = '\000';		/* Tie off the buffer */
    inctrl = -1;			/* End of the control sequence scan */

    /* Don't know how to do most private sequences right now,
	so just punt them */

    if ((private != 0 && private != '?') || badseq != 0) return;
    if (private == '?' && escseq[0] != 'h' &&
	escseq[0] != 'l') return;

    switch (escseq[0])			/* Dispatch on first intermediate or final */
    {
      case 'A': if (p[0]<=0) p[0] = 1;
		y -= 8*p[0]; if (y<top)  y = top;  return;
      case 'B': if (p[0]<=0) p[0] = 1;
		y += 8*p[0]; if (y>bot)  y = bot;  return;
      case 'C': if (p[0]<=0) p[0] = 1;
		x += 8*p[0]; if (x>MAXX) x = MAXX; return;
      case 'D': if (p[0]<=0) p[0] = 1;  
		x -= 8*p[0]; if (x<MINX) x = MINX; return;

      case 'H': case 'f':		/* Cursor position */
	if (p[0] <= 0) p[0] = 1;
	if (p[1] <= 0) p[1] = 1;
	y = (--p[0]*8)+MINY; x = (--p[1]*8)+MINX;
	if (y > MAXY) y = MAXY;
	if (x > MAXX) x = MAXX;
	if (y < MINY) y = MINY;
	if (x < MINX) x = MINX;
	return;

      case 'L':				/* ANSI insert line */
      case 'M':				/* ANSI delete line */
	if (p[0] <= 0) p[0] = 1;
	ScrollRaster(mywindow->RPort,0L,
	    (long)((escseq[0] == 'M' ? 8L : -8L) * p[0]),
	    (long)MINX,(long)y-6,(long)(MAXX+7),(long)bot+1);
	return;

      case 'r':				/* Set scroll region */
	if (p[0] <= 0) p[0] = 1;
	if (p[1] <= 0) p[1] = p_lines;
	top = (--p[0]*8)+MINY; bot = (--p[1]*8)+MINY;
	if (top < MINY) top = MINY;
	if (bot > MAXY) bot = MAXY;
	if (top > bot) { top = MINY; bot = MAXY; }
	x = MINX; y = MINY;
	return;

      case 'm':				/* Set graphic rendition */
	for (i=0;i<numpar;i++) {
	    if (p[i] < 0) p[i] = 0;
	    switch (p[i]) {
		case 0:
		curmode  = FS_NORMAL;
		break;

		case 1:
		curmode |= FSF_BOLD;
		break;

		case 4:
		curmode |= FSF_UNDERLINED;
		break;

		case 5:
		curmode |= FSF_ITALIC;
		break;

		default:
		curmode |= FSF_REVERSE;
		break;
		}
	    }
	return;

      case 'K':				/* Erase in line */
	doerase();
	return;

      case 'J':				/* Erase in display */
	if (p[0] < 0) p[0] = 0;
	SetAPen(mywindow->RPort,0L);
	if (p[0] == 0) {
	    if (y < MAXY) RectFill(mywindow->RPort,
		(long)MINX,(long)(y+2),(long)(MAXX+7),(long)(MAXY+1));
	    }
	else if (p[0] == 1) {
	    if (y > MINY) RectFill(mywindow->RPort,
		(long)MINX,(long)(MINY-6),(long)(MAXX+7),(long)(y-7));
	    }
	else RectFill(mywindow->RPort,
	    (long)MINX,(long)(MINY-6),(long)(MAXX+7),(long)(MAXY+1));
	SetAPen(mywindow->RPort,1L);
	doerase(); return;

      case 'h':				/* Set parameter */
	if (private == 0 && p[0] == 20)		nlmode = 1;
	else if (private == '?') {
	    if      (p[0] == 7)	p_wrap   = 1;
	    else if (p[0] == 1)	p_curapp = 1;
	    redoutil();
	    }
	return;

      case 'l':				/* Reset parameter */
	if (private == 0 && p[0] == 20)		nlmode = 0;
	else if (private == '?') {
	    if      (p[0] == 7)	p_wrap   = 0;
	    else if (p[0] == 1) p_curapp = 0;
	    redoutil();
	    }
	return;

      case 'x':
	sendchar(27); sendstring("[3;1;8;64;64;1;0x"); return;

      case 'n':
	if (p[0] == 6) {
	    sendchar(27);
	    sprintf(escseq,"[%d;%dR",((y-MINY)/8)+1,((x-MINX)/8)+1);
	    sendstring(escseq); return;
	    }
	sendchar(27); sendstring("[0n"); return;

      case 'c':
	sendchar(27); sendstring("[?1;7c"); return;
    }

    /* Don't know how to do this one, so punt it */
}

void doindex(c)
char c;
    {
    if (c != 'M') {
	if (c == 'E') x = MINX;
	if (y > bot) if (y < MAXY) y += 8;
	if (y == bot)
	    ScrollRaster(mywindow->RPort,0L,8L,(long)MINX,(long)(top-6),
		(long)(MAXX+7),(long)(bot+1));
	if (y < bot) y += 8;
	}
    else {
	if (y < top) if (y > MINY) y -= 8;
	if (y == top)
	    ScrollRaster(mywindow->RPort,0L,-8L,(long)MINX,(long)(top-6),
		(long)(MAXX+7),(long)(bot+1));
	if (y > top) y -= 8;
	}
    return;
    }

doalt(c)
char c;
    {
    int oldx,newx;
    inesc = -1;
    oldx = x; emit(' '); newx = x;
    x = oldx;
    SetAPen(mywindow->RPort,1L);
    switch (c) {
	case 'a':
	doline(0,-6,8,1);
	break;

	case 'j':
	case 'm':
	case 'v':   doline(4,-6,4,-2);
	if      (c=='j')  doline(0,-2,4,-2);
	else if (c=='m')  doline(4,-2,8,-2);
	else              doline(0,-2,8,-2);
	break;

	case 'k':
	case 'l':
	case 'w': doline(4,-2,4,1);
	if      (c=='k')  doline(0,-2,4,-2);
	else if (c=='l')  doline(4,-2,8,-2);
	else              doline(0,-2,8,-2);
	break;

	case 'n':
	case 'q': doline(0,-2,8,-2);
	if      (c=='n')  doline(4,-6,4,2);
	break;

	case 't':
	case 'u':
	case 'x':   doline(4,-6,4,1);
	if      (c=='t')  doline(4,-2,8,-2);
	else if (c=='u')  doline(0,-2,4,-2);
	break;
	}
    x = newx;
    }

doline(x1,y1,x2,y2) {
    RectFill(mywindow->RPort,(long)(x+x1),(long)(y+y1),
	(long)(x+x2),(long)(y+y2));
    }

void doerase()
    {
    if (p[0] < 0) p[0] = 0;
    SetAPen(mywindow->RPort,0L);
    if (p[0] == 0) RectFill(mywindow->RPort,(long)x,(long)(y-6),
	(long)(MAXX+7),(long)(y+1));
    else if (p[0] == 1) RectFill(mywindow->RPort,
	(long)MINX,(long)(y-6),(long)(x+7),(long)(y+1));
    else RectFill(mywindow->RPort,
	(long)MINX,(long)(y-6),(long)(MAXX+7),(long)(y+1));
    SetAPen(mywindow->RPort,1L);
    return;
    }

SHAR_EOF
cat << \SHAR_EOF > vt100.h
/*********************************************************************
 *  a terminal program that has ascii and xmodem transfer capability
 *
 *	v2.65		NG  - added tek4014 emulation
 *	v2.6 870227 DBW - bug fixes for all the stuff in v2.5
 *	v2.5 870214 DBW - more additions (see readme file)
 *	v2.4 861214 DBW - lots of fixes/additions (see readme file)
 *	v2.3 861101 DBW - minor bug fixes
 *	v2.2 861012 DBW - more of the same
 *	v2.1 860915 DBW - new features (see README)
 *	     860823 DBW - Integrated and rewrote lots of code
 *	v2.0 860809 DBW	- Major release.. LOTS of changes
 *	v1.1 860720 DBW	- Switches, 80 cols, colors, bug fixes
 *	v1.0 860712 DBW	- First version released
 *
 *  use esc to abort xmodem transfer
 *
 *  written by Michael Mounier
 *  new version by Dave Wecker 860621
 ********************************************************************/

/********* major version (used for title of terminal window) *********/
#define	VERSION	"VT100/TEK4014 (V2.65)"

/*********** ########  define the compiler type here ######## ********/
#define	LATTICE	0
#define MANX	1

#include "tek.h"		/* 	added for tek emulation		*/

/*  compiler directives to fetch the necessary header files */
#include <exec/types.h>
#include <exec/exec.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <graphics/gfxbase.h>
#include <graphics/gfx.h>
#include <graphics/text.h>
#include <graphics/regions.h>
#include <graphics/copper.h>
#include <graphics/gels.h>
#include <devices/serial.h>
#include <devices/keymap.h>
#include <devices/inputevent.h>
#include <devices/audio.h>
#include <hardware/blit.h>

			/* for Lattice you may have to change these with: */
#include <stdio.h>	/* #include <lattice/stdio.h> and */
#include <ctype.h>	/* #include <lattice/ctype.h>	 */

#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <devices/timer.h>

#if MANX
#include <functions.h>
#undef NULL
#define   NULL   ((void *)0)
#endif

#define INTUITION_REV 1L
#define GRAPHICS_REV  1L

/* things for xmodem send and recieve */
#define GOODREAD    0
#define TIMEOUT	    1
#define USERABORT   2
#define SECSIZ   0x80
#define TTIME_SHORT 5        /* number of seconds for short timeout */
#define TTIME_LONG  50	     /* number of seconds for long  timeout */
#define TTIME_KERMIT 10	     /* number of seconds for KERMIT timeout*/
#define BufSize  0x200       /* Text buffer for XMODEM */
#define ERRORMAX 10          /* Max errors before abort */
#define RETRYMAX 10          /* Maximum retrys before abort */
#define SOH      1           /* Start of sector char */
#define EOT      4           /* end of transmission char */
#define ACK      6           /* acknowledge sector transmission */
#define NAK      21          /* error in transmission detected */

#define FILEMAX 8    /* number of file menu items */
#define COMMAX 3     /* number of communication sub menus */
#define RSMAX 5      /* speed menu items */
#define PARMAX 5     /* parity items */
#define XFMAX 3      /* transfer mode items */
#define SCRIPTMAX 2  /* script menu items */
#define UTILMAX 9    /* utility menu */
#define MAXMENU 6    /* total number of menu entries */
					 /* change to 6 (add two more entries for tek)	*/

#define FSF_REVERSE 256	/* fake font style to flag INVERSVID mode */

/* things for script support */

#define GOTOLABEL   1
#define	NEXTCOMMAND 0
#define ONCOMMAND   2

#define	WAIT_TIMER  2
#define WAIT_STRING 1

/* things for 'beep' support */
#define BEEPSIZE    10L
#define BEEPFREQ    1000L
#define COLORCLOCK  3579545L

extern struct	MsgPort *CreatePort();
extern char	*malloc(),*strcpy(),*fgets();
extern long	ftell();

extern int	multi;		    /* flags multi file transfers */
extern int	server;
extern char	bufr[BufSize];
extern int	fd, timeout, ttime;
extern long	bytes_xferred;
extern char	MyDir[60];
extern struct	FileLock *MyDirLock;
extern struct	FileLock *StartLock;
extern struct	IntuitionBase *IntuitionBase;
extern struct	GfxBase *GfxBase;
extern struct	TextAttr myattr;
extern struct	TextFont *myfont;
extern struct	NewScreen NewScreen;
extern struct	NewWindow NewWindow;
extern struct	Screen *myscreen;
extern struct	Window *mywindow;
extern struct	ViewPort *myviewport;
extern struct	RastPort *myrastport;
extern struct	IntuiMessage *NewMessage;
extern struct	Preferences  *Prefs;
extern char	InpBuf[80],UndoBuf[80],Prompt[80];
extern struct	StringInfo mystrinfo;
extern struct	Gadget     mystrgad;
extern struct	IntuiText  donetxt;
extern struct	Gadget	   mydonegad;
extern struct	IntuiText  mystrtxt;
extern struct	Requester  myrequest;
extern int	numreqs;
extern struct	MenuItem FileItem[FILEMAX];
extern struct	IntuiText FileText[FILEMAX];
extern struct	MenuItem CommItem[COMMAX];
extern struct	IntuiText CommText[COMMAX];
extern struct	MenuItem RSItem[RSMAX];
extern struct	IntuiText RSText[RSMAX];
extern struct	MenuItem ParItem[PARMAX];
extern struct	IntuiText ParText[PARMAX];
extern struct	MenuItem XFItem[XFMAX];
extern struct	IntuiText XFText[XFMAX];
extern struct	MenuItem ScriptItem[SCRIPTMAX];
extern struct	IntuiText ScriptText[SCRIPTMAX];
extern struct	MenuItem UtilItem[UTILMAX];
extern struct	IntuiText UtilText[UTILMAX];
extern struct	Menu menu[MAXMENU];
extern struct	timerequest Timer, Script_Timer;
extern struct	MsgPort *Timer_Port, *Script_Timer_Port;
extern struct	IOExtSer *Read_Request;
extern char	*rs_in;
extern struct	IOExtSer *Write_Request;
extern char	rs_out[2];
extern int	x,y,curmode;
extern int	MINX,MAXX,MINY,MAXY,top,bot,savx,savy;
extern int	savmode,nlmode,alt,savalt,a[2],sa[2];
extern int	inesc,inctrl,private,badseq,maxcol;
extern struct	IOAudio Audio_Request;
extern struct	MsgPort *Audio_Port;
extern UBYTE	*BeepWave;
extern UBYTE	Audio_AllocMap[4];
extern int	p_baud,p_screen,p_interlace,p_depth,p_buffer,p_wbcolors;
extern int	p_foreground,p_background,p_bold,p_cursor,p_lines,p_mode;
extern int	p_parity,p_volume,p_wrap,p_echo,p_keyapp,p_curapp,p_bs_del;
extern int	p_convert;
extern char	p_keyscript;
extern long	p_break;
extern char	*p_f[10],*p_F[10];
extern int	script_on;
extern int	script_wait;
extern int	doing_init;

/* vt100.c */
extern int  do_send(),do_capture(),cleanup();
extern void setserpar(), setserbaud(), setparams(), redoutil(), redocomm(),
	    handle_menupick();

/* init.c */
extern void InitDevs(),InitFileItems(),InitCommItems(),
	 InitScriptItems(),InitUtilItems(),InitMenu();
extern char *InitDefaults();

/* window.c */
extern	void swap_bs_del(),req(),emits(),emit(),emitbatch(),cursorflip();
extern	int  toasc();

/* xmodem.c */
extern	void sendchar(),sendstring(),sendbreak(),multi_xfer(),
        No_XON(),Do_XON();
extern	int  readchar(),XMODEM_Read_File(),XMODEM_Send_File();

/* remote.c */
extern	void doremote(),doindex(),doctrl(),doesc(),doerase();

/* kermit.c */
extern	int	doksend(), dokreceive(), saybye();
extern	void	encode(), decode(), rpar(), spar();

/* script.c */
extern int	script_start(), chk_script(), exit_script(),
		do_script_cmd();
extern char	*next_wrd(), *tostring();

		/* init commands */
extern void	cmd_bkg(), cmd_bold(), cmd_buf(), cmd_cursor(), cmd_depth(),
		cmd_fore(), cmd_inter(), cmd_lines(), cmd_screen(),
		cmd_volume(), cmd_wb(), cmd_null(),

		/* script commands */
		cmd_as(), cmd_beep(), cmd_cap(), cmd_cd(), cmd_delay(),
		cmd_goto(), cmd_goto(), cmd_kb(), cmd_kg(), cmd_kr(),
		cmd_ks(), cmd_on(), cmd_sb(), cmd_send(), cmd_wait(),
		cmd_xr(), cmd_xs(),

		/* init and script commands */
		cmd_appcur(), cmd_baud(), cmd_bt(), cmd_conv(), cmd_echo(),
		cmd_exit(), cmd_fnc(), cmd_key(), cmd_mode(), cmd_numkey(),
		cmd_parity(), cmd_swap(), cmd_wrap();

/* expand.c */
extern char **expand();
extern int  set_dir(), free_expand();

SHAR_EOF