[mod.amiga.sources] vt100 terminal emulator with kermit/xmodem

doc@pucc-j.UUCP (07/14/86)

Reply-To: ihnp4!decwrl!cookie.dec.com!wecker@ee.purdue.edu  (DAVE  TANSTAAFL  WECKER)

#	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
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	README
#	Makefile
#	make.scr
#	init.c
#	kermit.c
#	remote.c
#	vt100.c
#	window.c
#	xmodem.c
#	vt100.h
# This archive created: Mon Jul 14 15:31:46 1986
# By:	Craig Norborg (Purdue University Computing Center)
cat << \SHAR_EOF > README
This archive contains a vt100 emulator with KERMIT and XMODEM file transfer
protocols by Dave Wecker (Based on AmigaTerm). This is an EARLY release
(Version 860710 DBW).

The files in this archive may be extracted by the Bourne Shell "/bin/sh" or
by hand (each file is preceeded with a "sed" line and is terminated with a
"SHAR_EOF" line. In addition, you must remove the prefix character ("X") from
each text line).

The files are:

	README		- this file

	makefile	- a makefile made to be used with the "make" utility
			included on the AZTEC-C disk.  A script is also included
			that can be used in place of this makefile (make.scr)
			(Note: this makefile was created by Craig Norborg 
			mod.amiga.sources moderator)

	make.scr	- a script that can be handed to "execute" to create
			  the emulator (switches are for MANX AZTEC-C).

	vt100.h		- include file used by all other modules

	window.c	- manager for window and keyboard

	vt100.c		- main module, handles menus

	remote.c	- handle remote characters (vt100 emulation)

	kermit.c	- kermit protocol (to transfer text files on VMS
			  select the CRLF option on the transfer mode menu,
			  otherwise use image mode).

	init.c		- startup code

	xmodem.c	- xmodem protocol that understands AMIGA binary and
			  text file formats (automatically).

Please send bugs/comments/suggestions to:

	Dave Wecker at	ENET:	COOKIE::WECKER
			ARPA:	wecker%cookie.dec.com@decwrl.dec.com
			USENET:	decvax!decwrl!cookie.dec.com!wecker

SHAR_EOF
cat << \SHAR_EOF > Makefile
# *** Note ***  Compilation will go faster if you have the libraries in
# RamDisk.  This makefile lets the user decide if they wish to have it there
# or not
#
SRC = vt100.c init.c window.c xmodem.c remote.c kermit.c
OBJ = vt100.o init.o window.o xmodem.o remote.o kermit.o
HDR = vt100.h

all: vt100

vt100: $(OBJ)
	ln -v -w -o vt100 $(OBJ) -lc

vt100.syms: vt100.h
	echo

vt100.o: vt100.c vt100.h
	cc +Hvt100.syms vt100.c

init.o: init.c vt100.syms vt100.h
	cc +Ivt100.syms init.c

window.o: window.c vt100.syms vt100.h
	cc +Ivt100.syms window.c

xmodem.o: xmodem.c vt100.syms vt100.h
	cc +Ivt100.syms xmodem.c

remote.o: remote.c vt100.syms vt100.h
	cc +Ivt100.syms remote.c

kermit.o: kermit.c vt100.syms vt100.h
	cc +Ivt100.syms kermit.c
SHAR_EOF
cat << \SHAR_EOF > make.scr
. Script to build vt100 terminal emulator
.     v1.0  DBW   860710   Dave Wecker
.
. Type "execute makefile" to build the emulator
.
echo "cc +Hvt100.syms vt100.c"
cc +Hvt100.syms vt100.c
.
echo "cc +Ivt100.syms init.c"
cc +Ivt100.syms init.c
.
echo "cc +Ivt100.syms window.c"
cc +Ivt100.syms window.c
.
echo "cc +Ivt100.syms xmodem.c"
cc +Ivt100.syms xmodem.c
.
echo "cc +Ivt100.syms remote.c"
cc +Ivt100.syms remote.c
.
echo "cc +Ivt100.syms kermit.c"
cc +Ivt100.syms kermit.c
.
if not exists ram:c.lib
  echo "Copying c.lib to ram"
  copy df0:lib/c.lib ram:
  set CLIB=ram:
  endif
echo "Linking vt100"
ln -v -w -o vt100 vt100.o init.o window.o xmodem.o remote.o kermit.o -lc
.
echo "Done!"

SHAR_EOF
cat << \SHAR_EOF > init.c
/***************************************************************
 * vt100 - terminal emulator - initialization
 *    v1.0  DBW   860621   Dave Wecker
 ***************************************************************/

#define MODULE_INIT 1
#include "vt100.h"

InitDevs()
{
IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", INTUITION_REV);
if( IntuitionBase == NULL )
   {
   puts("can't open intuition\n");
   exit(TRUE);
   }

GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",GRAPHICS_REV);
if( GfxBase == NULL )
   {
   puts("can't open graphics library\n");
   exit(TRUE);
   }

if(( myscreen = (struct Screen *)OpenScreen(&NewScreen)) == NULL)
   {
   puts("can't open screen!!\n");
   exit(TRUE);
   }

NewWindow.Screen = myscreen;

if(( mywindow = (struct Window *)OpenWindow(&NewWindow) ) == NULL)
   {
   puts("cant open window\n");
   CloseScreen( myscreen );
   exit(TRUE);
   }

myviewport   = (struct ViewPort *)ViewPortAddress(mywindow);
mycolormap   = (struct ColorMap *)GetColorMap(2L);
mycolortable = (USHORT *)mycolormap->ColorTable;
mycolortable[0] = 0x200;
mycolortable[1] = 0xA00;
LoadRGB4(myviewport,mycolortable,2L);

Read_Request = (struct IOExtSer *)AllocMem((long)sizeof(*Read_Request),MEMF_PUBLIC|MEMF_CLEAR);
Read_Request->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
Read_Request->IOSer.io_Message.mn_ReplyPort = CreatePort("Read_RS",0);
if(OpenDevice(SERIALNAME,NULL,Read_Request,NULL))
   {
   puts("Cant open Read device\n");
   FreeColorMap( mycolormap );
   CloseWindow( mywindow );
   CloseScreen( myscreen );
   DeletePort(Read_Request->IOSer.io_Message.mn_ReplyPort);
   FreeMem(Read_Request,(long)sizeof(*Read_Request));
   exit(TRUE);
   }
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);
Write_Request->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
Write_Request->IOSer.io_Message.mn_ReplyPort = CreatePort("Write_RS",0);
if(OpenDevice(SERIALNAME,NULL,Write_Request,NULL))
   {
   puts("Cant open Write device\n");
   FreeColorMap( mycolormap );
   CloseWindow( mywindow );
   CloseScreen( myscreen );
   DeletePort(Write_Request->IOSer.io_Message.mn_ReplyPort);
   FreeMem(Write_Request,(long)sizeof(*Write_Request));
   DeletePort(Read_Request->IOSer.io_Message.mn_ReplyPort);
   FreeMem(Read_Request,(long)sizeof(*Read_Request));
   exit(TRUE);
   }
Write_Request->IOSer.io_Command = CMD_WRITE;
Write_Request->IOSer.io_Length = 1;
Write_Request->IOSer.io_Data = (APTR) &rs_out[0];

Read_Request->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
Read_Request->io_Baud = 2400;
Read_Request->io_ReadLen = 8;
Read_Request->io_WriteLen = 8;
Read_Request->io_CtlChar = 1L;
Read_Request->IOSer.io_Command = SDCMD_SETPARAMS;
DoIO(Read_Request);
Read_Request->IOSer.io_Command = CMD_READ;
}

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

/* initialize each menu item and IntuiText with loop */
for( n=0; n<FILEMAX; n++ )
   {
   FileItem[n].NextItem = &FileItem[n+1];
   FileItem[n].LeftEdge = 0;
   FileItem[n].TopEdge = 11 * n;
   FileItem[n].Width = 135;
   FileItem[n].Height = 11;
   FileItem[n].Flags = ITEMTEXT | ITEMENABLED | HIGHBOX;
   FileItem[n].MutualExclude = 0;
   FileItem[n].ItemFill = (APTR)&FileText[n];
   FileItem[n].SelectFill = NULL;
   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 Receive";
FileText[5].IText = (UBYTE *)"Kermit Send";
return( 0 );
}

/*****************************************************************/
/*    The following function initializes the structure arrays    */
/*   needed to provide the BaudRate menu topic.                  */
/*****************************************************************/
InitRSItems()
{
short n;

/* initialize each menu item and IntuiText with loop */
for( n=0; n<RSMAX; n++ )
   {
   RSItem[n].NextItem = &RSItem[n+1];
   RSItem[n].LeftEdge = 0;
   RSItem[n].TopEdge = 11 * n;
   RSItem[n].Width = 85;
   RSItem[n].Height = 11;
   RSItem[n].Flags = ITEMTEXT | ITEMENABLED | HIGHBOX | CHECKIT;
   RSItem[n].MutualExclude = (~(1 << n));
   RSItem[n].ItemFill = (APTR)&RSText[n];
   RSItem[n].SelectFill = NULL;
   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;
/* 2400 baud item chekced */
RSItem[2].Flags = ITEMTEXT | ITEMENABLED | HIGHBOX | CHECKIT | 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";

return( 0 );
}

/*****************************************************************/
/*    The following function initializes the structure arrays    */
/*    needed to provide the Transfer Mode menu topic.            */
/*****************************************************************/
InitXFItems()
{
short n;

/* initialize each menu item and IntuiText with loop */
for( n=0; n<XFMAX; n++ )
   {
   XFItem[n].NextItem = &XFItem[n+1];
   XFItem[n].LeftEdge = 0;
   XFItem[n].TopEdge = 11 * n;
   XFItem[n].Width = 85;
   XFItem[n].Height = 11;
   XFItem[n].Flags = ITEMTEXT | ITEMENABLED | HIGHBOX | CHECKIT;
   XFItem[n].MutualExclude = (~(1 << n));
   XFItem[n].ItemFill = (APTR)&XFText[n];
   XFItem[n].SelectFill = NULL;
   XFItem[n].Command = 0;
   XFItem[n].SubItem = NULL;
   XFItem[n].NextSelect = 0;

   XFText[n].FrontPen = 0;
   XFText[n].BackPen = 1;
   XFText[n].DrawMode = JAM2;     /* render in fore and background */
   XFText[n].LeftEdge = 0;
   XFText[n].TopEdge = 1;
   XFText[n].ITextFont = NULL;
   XFText[n].NextText = NULL;
   }
XFItem[XFMAX-1].NextItem = NULL;
/* IMAGE mode checked */
XFItem[1].Flags = ITEMTEXT | ITEMENABLED | HIGHBOX | CHECKIT | CHECKED;
imagemode = 1;

/* initialize text for specific menu items */
XFText[0].IText = (UBYTE *)"  CR LF";
XFText[1].IText = (UBYTE *)"  image";

return( 0 );
}

/**********************************************************************/
/*   The following function initializes the Menu structure array with */
/*  appropriate values for our simple menu strip.  Review the manual  */
/*  if you need to know what each value means.                        */
/**********************************************************************/
InitMenu()
{
menu[0].NextMenu = &menu[1];
menu[0].LeftEdge = 5;
menu[0].TopEdge = 0;
menu[0].Width = 50;
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 = 65;
menu[1].TopEdge = 0;
menu[1].Width = 85;
menu[1].Height = 10;
menu[1].Flags = MENUENABLED;
menu[1].MenuName = "BaudRate";        /* text for menu-bar display */
menu[1].FirstItem = &RSItem[0];    /* pointer to first item in list */

menu[2].NextMenu = NULL;
menu[2].LeftEdge = 160;
menu[2].TopEdge = 0;
menu[2].Width = 85;
menu[2].Height = 10;
menu[2].Flags = MENUENABLED;
menu[2].MenuName = "Xfer Mode";        /* text for menu-bar display */
menu[2].FirstItem = &XFItem[0];    /* pointer to first item in list */

return( 0 );
}

SHAR_EOF
cat << \SHAR_EOF > kermit.c
/*************************************************************
 * vt100 terminal emulator - KERMIT protocol support
 *    v1.0  DBW   860622   Dave Wecker
 *************************************************************/

#define MODULE_KERMIT 1
#include "vt100.h"

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

#define MAXTRY    10       /* Times to retry a msgpkt */
#define MYQUOTE  '#'       /* Quote character I will use */
#define MYRPTQ   '~'       /* Repeat quote character */
#define MYPAD      0       /* Number of padding characters I will need */
#define MYPCHAR    0       /* Padding character I need (NULL) */
#define MYEOL    '\n'      /* End-Of-Line character I need */
#define MYTIME    10       /* Seconds after which I should be timed out */
#define MAXTIM    60       /* Maximum timeout interval */
#define MINTIM     2       /* Minumum timeout interval */


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

/* Global Variables */

short
   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 */
   numtry,    /* Times this msgpkt retried */
   oldtry,    /* Times previous msgpkt retried */
   rptflg,    /* are we doing repeat quoting */
   first,     /* is this the first time in a file */
   rpt;       /* current repeat count */

char
   next,      /* what is the next character */
   t,         /* current character */
   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 */
   ackpkt[MAXPACKSIZ+10], /* ACK/NAK packet buffer */
   msgpkt[MAXPACKSIZ+10], /* Message Packet buffer */
   filnam[40];            /* remote file name */

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

doksend(file)
char *file;
   {
   short retval;

   if ((fp = fopen(file,"r")) == NULL) {
      emits("Cannot open send file\n");
      return FALSE;
      }
   emits("Remote file name [local name]: ");
   filename(filnam);
   if (filnam[0] == 0) strcpy(filnam,file);
   timeout = FALSE;
   emits("\nType <ESC> to abort transfer\n");
   retval  = sendsw();
   emits("\n");
   fclose(fp);
   return(retval);
   }

dokreceive(file)
char *file;
   {
   short retval;

   if ((fp = fopen(file,"w")) == NULL) {
      emits("Cannot open file\n");
      return FALSE;
      }
   emits("Remote file name [local name]: ");
   filename(filnam);
   if (filnam[0] == 0) strcpy(filnam,file);
   timeout = FALSE;
   emits("\nType <esc> to abort transfer\n");
   retval  = recsw();
   emits("\n");
   fclose(fp);
   return(retval);
   }

sendsw()
   {
   char sinit(), sfile(), sdata(), seof(), sbreak();

   state = 'S';
   n = 0;
   numtry = 0;
   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':   return(TRUE);
         case 'A':   return(FALSE);
         default:    return(FALSE);
         }
      }
   }

char sinit()
   {
   int num, len;

   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 = '#';
                 numtry = 0;
                 n = (n+1)%64;
                 return('F');
      case 'E':  return('A');
      case FALSE:return(state);
      default:   return('A');
      }
    }

char sfile()
   {
   int num, len;

   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;
         n = (n+1)%64;
         first = 1;
         size = getpkt();
         return('D');
      case 'E':
         return('A');
      case FALSE: return(state);
      default:    return('A');
      }
   }

char sdata()
   {
   int num, len;

   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;
         n = (n+1)%64;
         if ((size = getpkt()) == 0) return('Z');
         return('D');
      case 'E':
         return('A');
      case FALSE: return(state);
      default:    return('A');
      }
   }

char seof()
   {
   int num, len;

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

   spack('Z',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;
         n = (n+1)%64;
         return('B');
      case 'E':
         return('A');
      case FALSE: return(state);
      default:    return('A');
      }
   }

char sbreak()
   {
   int num, len;
   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;
         n = (n+1)%64;
         return('C');
      case 'E':
         return('A');
      case FALSE: return(state);
      default:    return ('A');
      }
   }

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

   state = 'R';
   n = 0;
   numtry = 0;

   while(TRUE) {
      switch(state) {
         case 'R':   state = rinit(); break;
         case 'F':   state = rfile(); break;
         case 'D':   state = rdata(); break;
         case 'C':   return(TRUE);
         case 'A':   return(FALSE);
         }
      }
   }

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

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

char rfile()
   {
   int num, len;
   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');
         spack('Y',n,0,0);
         oldtry = numtry;
         numtry = 0;
         n = (n+1)%64;
         return('D');
      case 'B':
         if (num != n) return ('A');
         spack('Y',n,0,0);
         return('C');
      case 'E':
         return('A');
      case FALSE:
         spack('N',n,0,0);
         return(state);
      default:
         return ('A');
      }
   }

char rdata()
   {
   int num, len;
   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;
         n = (n+1)%64;
         return('D');
      case 'F':
         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 'Z':
         if (num != n) return('A');
         spack('Y',n,0,0);
         n = (n+1)%64;
         return('C');
      case 'E':
         return('A');
      case FALSE:
         spack('N',n,0,0);
         return(state);
      default:
        return('A');
      }
   }

spack(type,num,len,data)
char type, *data;
short num, len;
   {
   short i;
   char chksum, buffer[100];
   register char *bufp;

   if (type != 'Y' && type != 'N') {
      if (num == 0) emits("\n");
      emit(type);
      }
   bufp = buffer;
   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)
short *len, *num;
char *data;
   {
   short i, done;
   char t, type, cchksum, rchksum;

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

    done = FALSE;
    while (!done) {
       t = readchar();
       if (timeout) return(FALSE);
       if (t == SOH) continue;
       cchksum = t;
       *len = unchar(t)-3;
       t = readchar();
       if (timeout) return(FALSE);
       if (t == SOH) continue;
       cchksum = cchksum + t;
       *num = unchar(t);
       t = readchar();
       if (timeout) return(FALSE);
       if (t == SOH) continue;
       cchksum = cchksum + t;
       type = t;
       for (i=0; i<*len; i++) {
          t = readchar();
          if (timeout) return(FALSE);
          if (t == SOH) continue;
          cchksum = cchksum + t;
          data[i] = t;
          }
       data[*len] = 0;
       t = readchar();
       if (timeout) return(FALSE);
       rchksum = unchar(t);
       t = readchar();
       if (timeout) return(FALSE);
       if (t == SOH) continue;
       done = TRUE;
       }
   if (type != 'Y' && type != 'N') {
      if (*num == 0) emits("\n");
      emit(type);
      }
   cchksum = (((cchksum&0300) >> 6)+cchksum)&077;
   if (cchksum != rchksum) return(FALSE);
   return(type);
   }

getpkt() {
   short i,eof;

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

   if (first == 1) {
      first = 0;
      *leftover = '\0';
      t = getc(fp);
      if (t == EOF) {
         first = 1;
         return(size = 0);
         }
      }
   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;
         }
      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);
   }

encode(a)
char a;
   {
   short a7,b8;

   if ((!imagemode) && a == '\n') {
      rpt = 0;
      msgpkt[size++] = quote;
      msgpkt[size++] = ctl('\r');
      if (size <= spsiz-3) osize = size;
      msgpkt[size++] = quote;
      msgpkt[size++] = ctl('\n');
      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 ((a7 < SP) || (a7==DEL)) {
      msgpkt[size++] = quote;
      a = ctl(a);
      }
   if (a7 == quote) msgpkt[size++] = quote;
   if ((rptflg) && (a7 == rptq)) msgpkt[size++] = quote;
   msgpkt[size++] = a;
   msgpkt[size] = '\0';
   }

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++;
            }
         }
      if (a == quote) {
         a  = *buf++;
         a7 = a & 0177;
         if ((a7 >= 0100 && a7 <= 0137) || a7 == '?') a = ctl(a);
         }
      if (rpt == 0) rpt = 1;
      if ((!imagemode) && a == '\r') continue;
      for (; rpt > 0; rpt--) putc(a, fp);
      }
   return(0);
   }

spar(data)
char data[];
   {
   data[0] = tochar(MAXPACKSIZ);
   data[1] = tochar(MYTIME);
   data[2] = tochar(MYPAD);
   data[3] = ctl(MYPCHAR);
   data[4] = tochar(MYEOL);
   data[5] = MYQUOTE;
   data[6] = 'N';
   data[7] = '1';
   data[8] = MYRPTQ;
   data[9] = '\0';
   }

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

SHAR_EOF
cat << \SHAR_EOF > remote.c
/****************************************************
* vt100 emulator - remote character interpretation
*    v1.0  DBW   860621   Dave Wecker
****************************************************/

#define MODULE_REMOTE 1
#include "vt100.h"

static USHORT top       = MINY;
static USHORT bot       = MAXY;
static USHORT savx      = MINX;
static USHORT savy      = MINY;
static USHORT savmode   = 0;
static USHORT nlmode    = 0;
static USHORT alt       = 0;
static USHORT savalt    = 0;
static USHORT a[2]      = { 0, 0 };
static USHORT sa[2]     = { 0, 0 };
static short  inesc     = -1;

static short  p1,p2,numpar;
static char   escseq[40];

/************************************************
*  function to handle remote characters
*************************************************/
doremote(c)
char c;
    {
    if (c == 27 || inesc >= 0) { doesc(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);
    }

doesc(c)
char c;
    {
    if (inesc < 0) { inesc = 0; return; }
    if (c == 27 || c == 24) { inesc = -1; return; }
    if (inesc == 0) {
	if (c == '[' || c == '#' || c == '(' || c == ')') {
	    numpar = 0;
	    escseq[inesc++] = c;
	    return;
	    }
	if (c == 'D' || c == 'E' || c == 'M') {
	    inesc = -1;
	    doindex(c);
	    return;
	    }
	if (c == '7') {
	    inesc = -1;
	    savx = x; savy = y; savmode = curmode; savalt = alt;
	    sa[0] = a[0]; sa[1] = a[1];
	    return;
	    }
	if (c == '8') {
	    inesc = -1;
	    x = savx; y = savy; alt = savalt; curmode = savmode;
	    a[0] = sa[0]; a[1] = sa[1];
	    return;
	    }
	if (c == 'c') {
	    inesc = -1;
	    top = MINY; bot = MAXY; savx = MINX; savy = MINY;
	    a[0] = 0; a[1] = 0; sa[0] = 0; sa[1] = 0;
	    emit(12); return;
	    }
	inesc = -1;
	return;
	}
    if (inesc == 1 && escseq[0] == '#') { inesc = -1; return; }
    if (inesc == 1 && escseq[0] == '(') {
	inesc = -1;
	if (c == '0' || c == '2') a[0] = 1; else a[0] = 0;
	return;
	}
    if (inesc == 1 && escseq[0] == ')') {
	inesc = -1;
	if (c == '0' || c == '2') a[1] = 1; else a[1] = 0;
	return;
	}
    if ((c >= '0' && c <= '9') || c == ';' || c == '?') {
	if (inesc == 1) numpar = 1;
	if (c == ';') numpar++;
	escseq[inesc++] = c;
	return;
	}
    escseq[inesc] = '\000';
    inesc = -1; p1 = -1; p2 = -1;
    if (escseq[1] == '?') return;
    switch (numpar) {
	case 1: sscanf(escseq,"[%d",         &p1);             break;
	case 2: sscanf(escseq,"[%d;%d",      &p1,&p2);         break;
	case 3: sscanf(escseq,"[%d;%d;%d",   &p1,&p2,&p2);     break;
	case 4: sscanf(escseq,"[%d;%d;%d;%d",&p1,&p2,&p2,&p2); break;
	}
    if (c >= 'A' && c <= 'D') {
	if (p1 <= 0) p1 = 1;
	switch (c) {
	    case 'A':   y -= 8*p1; if (y<top)  y = top;  break;
	    case 'B':   y += 8*p1; if (y>bot)  y = bot;  break;
	    case 'C':   x += 8*p1; if (x>MAXX) x = MAXX; break;
	    case 'D':   x -= 8*p1; if (x<MINX) x = MINX; break;
	    }
	return;
	}
    if (c == 'H' || c == 'f') {
	if (p1 <= 0) p1 = 1;
	if (p2 <= 0) p2 = 1;
	y = (--p1*8)+MINY; x = (--p2*8)+MINX;
	if (y > MAXY) y = MAXY;
	if (x > MAXX) x = MAXX;
	if (y < MINY) y = MINY;
	if (x < MINX) x = MINX;
	return;
	}
    if (c == 'r') {
	if (p1 <= 0) p1 = 1;
	if (p2 <= 0) p2 = 24;
	top = (--p1*8)+MINY; bot = (--p2*8)+MINY;
	if (top < MINY) top = MINY;
	if (bot > MAXY) bot = MAXY;
	if (top > bot) { top = MINY; bot = MAXY; }
	return;
	}
    if (c == 'm') {
	if (p2 >= 0) p1 = p2;
	if (p1 <= 0) curmode = 0; else curmode = 1;
	return;
	}
    if (c == 'K') {
	doerase();
	return;
	}
    if (c == 'J') {
	if (p1 < 0) p1 = 0;
	SetAPen(mywindow->RPort,0L);
	if (p1 == 0) RectFill(mywindow->RPort,
	    (long)MINX,(long)(y+2),(long)(MAXX+7),(long)(bot+2));
	else if (p1 == 1) RectFill(mywindow->RPort,
	    (long)MINX,(long)(top-7),(long)(MAXX+7),(long)(y-7));
	else RectFill(mywindow->RPort,
	    (long)MINX,(long)(top-7),(long)(MAXX+7),(long)(bot+2));
	SetAPen(mywindow->RPort,1L);
	doerase(); return;
	}
    if (c == 'h') {
	if (p1 == 20) nlmode = 1;
	return;
	}
    if (c == 'l') {
	if (p1 == 20) nlmode = 0;
	return;
	}
    if (c == 'x') {
	sendchar(27); sendstring("[3;1;8;64;64;1;0x"); return;
	}
    if (c == 'n') {
	if (p1 == 6) {
	    sendchar(27);
	    sprintf(escseq,"[%d;%dR",((y-MINY)/8)+1,((x-MINX)/8)+1);
	    sendstring(escseq); return;
	    }
	sendchar(27); sendstring("[0n"); return;
	}
    if (c == 'c') {
	sendchar(27); sendstring("[?1;0c"); return;
	}
    }

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

doalt(c)
char c;
    {
    short oldx,newx;
    inesc = -1;
    oldx = x; emit(' '); newx = x;
    x = oldx;
    SetAPen(mywindow->RPort,1L);
    switch (c) {
	case 'j':
	case 'm':
	case 'v':   doline(4,-8,4,-4);
	if      (c=='j')  doline(0,-4,4,-4);
	else if (c=='m')  doline(4,-4,8,-4);
	else              doline(0,-4,8,-4);
	break;

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

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

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

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

doerase()
    {
    inesc = -1;
    if (p1 < 0) p1 = 0;
    SetAPen(mywindow->RPort,0L);
    if (p1 == 0) RectFill(mywindow->RPort,(long)x,(long)(y-6),
	(long)(MAXX+7),(long)(y+1));
    else if (p1 == 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.c
/************************************************************************
*  vt100 terminal emulator with xmodem transfer capability
*
*     v1.0  DBW   860710   Dave Wecker - major rewrite of AmigaTerm
*
*  use <esc> to abort xmodem or kermit transfers
*
*  written by Michael Mounier
*  new version by Dave Wecker
************************************************************************/

/*  all includes defines and globals */
#define MODULE_MAIN 1
#include "vt100.h"

/******************************************************/
/*                   Main Program                     */
/*                                                    */
/*      This is the main body of the program.         */
/******************************************************/

main()
    {
    ULONG class;
    USHORT code,menunum,itemnum;
    int KeepGoing,capture,send,maxwait;
    char c,name[32];
    FILE *tranr,*trans;

    InitDevs();
    InitFileItems();
    InitRSItems();
    InitXFItems();
    InitMenu();
    SetMenuStrip(mywindow,&menu[0]);

    KeepGoing = TRUE;
    capture=FALSE;
    send=FALSE;
    x = MINX ; y = MINY; curmode = 0;
    SetAPen(mywindow->RPort,1L);
    cursoron();
    cursoroff();
    emit(12);
    BeginIO(Read_Request);

    while( KeepGoing )
	    {
	    /* wait for window message or serial port message */
	    cursoron();
	    Wait((1L << Read_Request->IOSer.io_Message.mn_ReplyPort->mp_SigBit) |
		(1L << mywindow->UserPort->mp_SigBit));
	    cursoroff();

	    if (send)
		{
		if ((c=getc(trans)) != EOF)
		    {
		    if (c == '\n') c = '\r';
		    sendchar(c);
		    }
		else
		    {
		    fclose(trans);
		    emits("\nFile Sent\n");
		    send=FALSE;
		    }
		}
	    maxwait = 0;
	    while (CheckIO(Read_Request) && maxwait++ < 20)
		{
		WaitIO(Read_Request);
		c=rs_in[0] & 0x7f;
		BeginIO(Read_Request);
		doremote(c);
		if (capture && c != 10) {
		    if (c == 13) c = 10;
		    putc(c , tranr);
		    }
		}

	    while( NewMessage=(struct IntuiMessage *)GetMsg(mywindow->UserPort) )
		{
		class = NewMessage->Class;
		code = NewMessage->Code;
		ReplyMsg( NewMessage );
		switch( class )
		    {
		    case CLOSEWINDOW:
		    KeepGoing = FALSE;
		    break;

		    case RAWKEY:
		    c = toasc(code);
		    break;

		    case NEWSIZE:
		    emit(12);
		    break;

		    case MENUPICK:
		    if ( code != MENUNULL )
			{
			menunum = MENUNUM( code );
			itemnum = ITEMNUM( code );
			switch( menunum )
			    {
			    case 0:
			    switch( itemnum )
				{
				case 0:
				if (capture == TRUE)
				    {
				    capture=FALSE;
				    fclose(tranr);
				    emits("\nEnd File Capture\n");
				    }
				else
				    {
				    emits("\nAscii Capture:");
				    filename(name);
				    if ((tranr=fopen(name,"w")) == 0)
					{
					capture=FALSE;
					emits("\nError Opening File\n");
					break;
					}
				    capture=TRUE;
				    }
				break;

				case 1:
				if (send == TRUE)
				{ 
				    send=FALSE;
				    fclose(trans);
				    emits("\nFile Send Cancelled\n");
				    }
				else
				    {
				    emits("\nAscii Send:");
				    filename(name);
				    if ((trans=fopen(name,"r")) == 0)
					{
					send=FALSE;
					emits("\nError Opening File\n");
					break;
					}
				    send=TRUE;
				    }
				break;

				case 2:
				emits("\nXmodem Receive:");
				filename(name);
				if (XMODEM_Read_File(name))
				    {
				    emits("\nRecieved File\n");
				    emit(8);
				    }
				else
				    {
				    close(fd);
				    emits("Xmodem Receive Failed\n");
				    emit(8);
				    }
				break;

				case 3:
				emits("\nXmodem Send:");
				filename(name);
				if (XMODEM_Send_File(name))
				    {
				    emits("\nSent File\n");
				    emit(8);
				    }
				else
				    {
				    close(fd);
				    emits("\nXmodem Send Failed\n");
				    emit(8);
				    }
				break;

				case 4:
				emits("\nKermit Receive local name:");
				filename(name);
				if (dokreceive(name))
				    {
				    emits("\nRecieved File\n");
				    emit(8);
				    }
				else
				    {
				    close(fd);
				    emits("Kermit Receive Failed\n");
				    emit(8);
				    }
				break;

				case 5:
				emits("\nKermit Send local name:");
				filename(name);
				if (doksend(name))
				    {
				    emits("\nSent File\n");
				    emit(8);
				    }
				else
				    {
				    close(fd);
				    emits("\nKermit Send Failed\n");
				    emit(8);
				    }
				break;
				}
			    break;

			    case 1:
			    AbortIO(Read_Request);
			    switch( itemnum )
				{
				case 0:
				Read_Request->io_Baud = 300;
				break;
				case 1:
				Read_Request->io_Baud = 1200;
				break;
				case 2:
				Read_Request->io_Baud = 2400;
				break;
				case 3:
				Read_Request->io_Baud = 4800;
				break;
				case 4:
				Read_Request->io_Baud = 9600;
				break;
				}
			    Read_Request->IOSer.io_Command = SDCMD_SETPARAMS;
			    DoIO(Read_Request);
			    Read_Request->IOSer.io_Command = CMD_READ;
			    BeginIO(Read_Request);
			    break;

			    case 2:
			    switch( itemnum )
				{
				case 0:
				imagemode = 0;
				break;

				case 1:
				imagemode = 1;
				break;
				}
			    break;
			    } /* end of switch ( menunum ) */
			}    /*  end of if ( not null ) */
		    }   /* end of switch (class) */
		}   /* end of while ( newmessage )*/
	    }  /* end while ( keepgoing ) */

    /*   It must be time to quit, so we have to clean
    *   up and exit.
    */

    CloseDevice(Read_Request);
    DeletePort(Read_Request->IOSer.io_Message.mn_ReplyPort);
    FreeMem(Read_Request,(long)sizeof(*Read_Request));
    CloseDevice(Write_Request);
    DeletePort(Write_Request->IOSer.io_Message.mn_ReplyPort);
    FreeMem(Write_Request,(long)sizeof(*Write_Request));
    ClearMenuStrip( mywindow );
    FreeColorMap( mycolormap );
    CloseWindow( mywindow );
    CloseScreen( myscreen );
    exit(FALSE);
    } /* end of main */
SHAR_EOF
cat << \SHAR_EOF > window.c
/****************************************************
* vt100 emulator - window/keyboard support
*    v1.0  DBW   860621   Dave Wecker
****************************************************/

#define MODULE_WINDOW 1
#include "vt100.h"

/*************************************************
*  function to get file name
*************************************************/
filename(name)
char name[];
    {
    char c;
    ULONG class;
    USHORT code;
    int keepgoing,i;
    keepgoing = TRUE;
    i=0;
    while (keepgoing) {
	while( NewMessage=(struct IntuiMessage *)GetMsg(mywindow->UserPort) )
	    {
	    class = NewMessage->Class;
	    code = NewMessage->Code;
	    ReplyMsg( NewMessage );
	    if (class=RAWKEY)
		{
		c = toasc(code);
		name[i]=c;
		if (name[i] != 0)
		    {
		    if (name[i] == 13)
			{
			name[i]=0;
			keepgoing = FALSE;
			}
		    else
			{
			if (name[i] == 8)
			    {
			    i -=2;
			    if (i < -1)
			    i = -1;
			    else
				{
				emit(8);
				emit(32);
				emit(8);
				}
			    }
			else
			emit(c);
			}
		    i += 1;
		    }
		}
	    } /* end of new message loop */
	}   /* end of god knows what */
    emit(13);
    emit(10);
    } /* end of function */


/*************************************************
*  function to print a string
*************************************************/
emits(string)
char string[];
    {
    int i;
    char c;

    i=0;
    while (string[i] != 0)
	{
	c=string[i];
	if (c == 10) emit(13);
	emit(c);
	i += 1;
	}
    }

/*************************************************
*  function to output ascii chars to window
*************************************************/
emit(c)
char c;
    {
    Move(mywindow->RPort,(long)x,(long)y);

    c &= 0x7F;
    switch( c )
	{
	case '\t':
	x += 64 - ((x-MINX) % 64);
	break;

	case 10:  /* lf */
	y += 8;
	break;

	case 13:  /* cr */
	x = MINX;
	break;

	case 8:   /* backspace */
	x -= 8;
	if (x < MINX) x = MINX;
	break;

	case 12:     /* page */
	x = MINX;
	y = MINY;
	SetAPen(mywindow->RPort,0L);
	RectFill(mywindow->RPort,(long)MINX,
	    (long)(MINY-7),(long)(MAXX+7),(long)(MAXY+1));
	SetAPen(mywindow->RPort,1L);
	break;

	case 7:     /* bell */
	ClipBlit(mywindow->RPort,0L,0L,mywindow->RPort,0L,0L,
	    MAXX,MAXY,0x50L);
	ClipBlit(mywindow->RPort,0L,0L,mywindow->RPort,0L,0L,
	    MAXX,MAXY,0x50L);
	break;

	default:
	if (c < ' ' || c > '~') break;
	if (curmode) {
	    Text(mywindow->RPort," ",1L);
	    Move(mywindow->RPort,(long)x,(long)y);
	    SetDrMd(mywindow->RPort,(long)INVERSVID);
	    Text(mywindow->RPort,&c,1L);
	    SetDrMd(mywindow->RPort,(long)JAM2);
	    }
	else Text(mywindow->RPort,&c,1L);
	x += 8;
	} /* end of switch */

    while (x > MAXX) x -= 8;
    while (y > MAXY) {
	y -= 8;
	x  = MINX;
	ScrollRaster(mywindow->RPort,0L,8L,(long)MINX,
	    (long)(MINY-7),(long)(MAXX+7),(long)(MAXY+1));
	}
    }

/******************************
* Manipulate cursor
******************************/
cursoroff()
    {
    SetDrMd(mywindow->RPort,COMPLEMENT);
    SetAPen(mywindow->RPort,3L);
    RectFill(mywindow->RPort,
	(long)(x-1),(long)(y-8),(long)(x+8),(long)(y+2));
    SetAPen(mywindow->RPort,1L);
    SetDrMd(mywindow->RPort,(long)JAM2);
    }

cursoron()
    {
    SetDrMd(mywindow->RPort,COMPLEMENT);
    SetAPen(mywindow->RPort,3L);
    RectFill(mywindow->RPort,
	(long)(x-1),(long)(y-8),(long)(x+8),(long)(y+2));
    SetAPen(mywindow->RPort,1L);
    SetDrMd(mywindow->RPort,(long)JAM2);
    }

/************************************************
*  function to take raw key data and convert it 
*  into ascii chars
**************************************************/
toasc(code)
USHORT code;
    {
    static int ctrl = FALSE;
    static int shift = FALSE;
    static int capsl = FALSE;
    char c;
    static char keys[75] = {
	'`' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , '0' , '-' ,
	'=' , '\\' , 0 , '0' , 'q' , 'w' , 'e' , 'r' , 't' , 'y' , 'u' , 'i' , 'o' ,
	'p' , '[' , ']' , 0 , '1' , '2' , '3' , 'a' , 's' , 'd' , 'f' , 'g' , 'h' ,
	'j' , 'k' , 'l' , ';' , '\'' , 0 , 0 , '4' , '5' , '6' , 0 , 'z' , 'x' , 'c' , 'v' ,
	'b' , 'n' , 'm' , 44 , '.' , '/' , 0 , '.' , '7' , '8' , '9' , ' ' , 8 ,
	'\t' , 13 , 13 , 27 , 127 , 0 , 0 , 0 , '-' } ;

    switch ( code )
	{
	case 98:   capsl = TRUE; c = 0;break;
	case 226:  capsl = FALSE;c = 0;break;
	case 99:   ctrl = TRUE;  c = 0;break;
	case 227:  ctrl = FALSE; c = 0;break;
	case 96:
	case 97:   shift = TRUE; c = 0;break;
	case 224:
	case 225:  shift = FALSE;c = 0;break;
	case 0x50: c=0; sendchar(27); sendstring("OP"); break;
	case 0x51: c=0; sendchar(27); sendstring("OQ"); break;
	case 0x52: c=0; sendchar(27); sendstring("OR"); break;
	case 0x53: c=0; sendchar(27); sendstring("OS"); break;
	case 0x0f: c=0; sendchar(27); sendstring("Op"); break;
	case 0x1d: c=0; sendchar(27); sendstring("Oq"); break;
	case 0x1e: c=0; sendchar(27); sendstring("Or"); break;
	case 0x1f: c=0; sendchar(27); sendstring("Os"); break;
	case 0x2d: c=0; sendchar(27); sendstring("Ot"); break;
	case 0x2e: c=0; sendchar(27); sendstring("Ou"); break;
	case 0x2f: c=0; sendchar(27); sendstring("Ov"); break;
	case 0x3d: c=0; sendchar(27); sendstring("Ow"); break;
	case 0x3e: c=0; sendchar(27); sendstring("Ox"); break;
	case 0x3f: c=0; sendchar(27); sendstring("Oy"); break;
	case 0x43: c=0; sendchar(27); sendstring("OM"); break;
	case 0x4a: c=0; sendchar(27); sendstring("Ol"); break;
	case 0x5f: c=0; sendchar(27); sendstring("Om"); break;
	case 0x3c: c=0; sendchar(27); sendstring("On"); break;
	case 0x4c: c = 0; sendchar(27); sendstring("[A"); break;
	case 0x4d: c = 0; sendchar(27); sendstring("[B"); break;
	case 0x4e: c = 0; sendchar(27); sendstring("[C"); break;
	case 0x4f: c = 0; sendchar(27); sendstring("[D"); break;
	default:
	if (code < 75) c = keys[code];
	else c = 0;
	}

    /* add modifiers to the keys */

    if (c != 0) {
	if (shift) {
	    if ((c <= 'z') && (c >= 'a')) c -= 32;
	    else
	    switch( c ) {
		case '[':  c = '{'; break;
		case ']':  c = '}'; break;
		case '\\': c = '|'; break;
		case '\'': c = '"'; break;
		case ';':  c = ':'; break;
		case '/':  c = '?'; break;
		case '.':  c = '>'; break;
		case ',':  c = '<'; break;
		case '`':  c = '~'; break;
		case '=':  c = '+'; break;
		case '-':  c = '_'; break;
		case '1':  c = '!'; break;
		case '2':  c = '@'; break;
		case '3':  c = '#'; break;
		case '4':  c = '$'; break;
		case '5':  c = '%'; break;
		case '6':  c = '^'; break;
		case '7':  c = '&'; break;
		case '8':  c = '*'; break;
		case '9':  c = '('; break;
		case '0':  c = ')'; break;
		default:            break;
		}
	    }
	else if (capsl && (c <= 'z') && (c >= 'a')) c -= 32;
	}
    if (ctrl) {
	if (c >= '`' && c <= 127) c -= 96;
	else if (c >= '@' && c <= '_') c -= 64;
	}
    if (c != 0) sendchar(c);
    return(c);
    }

SHAR_EOF
cat << \SHAR_EOF > xmodem.c
/*************************************************************
* vt100 terminal emulator - XMODEM protocol support
*    v1.0  DBW   860621   Dave Wecker
*************************************************************/

#define MODULE_XMODEM 1
#include "vt100.h"

/************************************************************
* Send a string (using sendchar below)
************************************************************/

sendstring(s)
char *s;
    {
    char c;

    while ((c = *s++) != '\000') sendchar(c);
    }

/**************************************************************/
/* send char and read char functions for the xmodem function */
/************************************************************/
sendchar(ch)
int ch;
    {
    rs_out[0] = ch;
    DoIO(Write_Request);
    }

readchar()
    {
    unsigned char c;
    int rd,ch;

    rd = FALSE;

    while (rd == FALSE)
	{
	Wait((1L << Read_Request->IOSer.io_Message.mn_ReplyPort->mp_SigBit) | ( 1L << mywindow->UserPort->mp_SigBit));
	if(CheckIO(Read_Request))
	    {
	    WaitIO(Read_Request);
	    ch=rs_in[0];
	    rd = TRUE;
	    BeginIO(Read_Request);
	    }
	if (NewMessage=(struct IntuiMessage *)GetMsg(mywindow->UserPort))
	if ((NewMessage->Class) == RAWKEY)
	if ((NewMessage->Code) == 69)
	    {
	    emits("\nUser Cancelled Transfer");
	    break;
	    }
	}
    if (rd == FALSE)
	{
	timeout = TRUE;
	emits("\nTimeout Waiting For Character\n");
	}
    c = ch;
    return(c);
    }

/**************************************/
/* xmodem send and recieve functions */
/************************************/

XMODEM_Read_File(file)
char *file;
    {
    int firstchar, sectnum, sectcurr, sectcomp, errors, errorflag,
	findtype, exe;
    unsigned int checksum, j, bufptr,i;
    char numb[10];
    bytes_xferred = 0L;

    if ((fd = creat(file, 0)) < 0)
	{
	emits("Cannot Open File\n");
	return FALSE;
	}
    else
    emits("Receiving File\n\nType <ESC> to abort transfer\n");

    timeout=FALSE;
    sectnum = errors = bufptr = 0;
    findtype = TRUE; exe = FALSE;
    sendchar(NAK);
    firstchar = 0;
    while (firstchar != EOT && errors != ERRORMAX)
	{
	errorflag = FALSE;

	do                                    /* get sync char */
	    {
	    firstchar = readchar();
	    if (timeout == TRUE)
	    return FALSE;
	    }
	while (firstchar != SOH && firstchar != EOT);

	if  (firstchar == SOH)
	    {
	    emits("Getting Block ");
	    sprintf(numb, "%d", sectnum);
	    emits(numb);
	    emits("...");
	    sectcurr = readchar();
	    if (timeout == TRUE)
	    return FALSE;
	    sectcomp = readchar();
	    if (timeout == TRUE)
	    return FALSE;
	    if ((sectcurr + sectcomp) == 255)
		{
		if (sectcurr == (sectnum + 1 & 0xff))
		    {
		    checksum = 0;
		    for (j = bufptr; j < (bufptr + SECSIZ); j++)
			{
			bufr[j] = readchar();
			if (findtype && sectcurr == 1 && j == 3) {
			    findtype = FALSE;
			    if (bufr[0] == 0x00 && bufr[1] == 0x00 &&
			        bufr[2] == 0x03 && bufr[3] == 0xF3)
				    exe = TRUE;
			    }
			if (timeout == TRUE)
			return FALSE;
			checksum = (checksum + bufr[j]) & 0xff;
			}
		    if (checksum == readchar())
			{
			errors = 0;
			sectnum++;
			bufptr += SECSIZ;
			bytes_xferred += SECSIZ;
			emits("verified\n");
			if (bufptr == BufSize)
			    {
			    if (write(fd, bufr, BufSize-128) == EOF)
				{
				emits("\nError Writing File\n");
				return FALSE;
				}
			    bufptr = 128;
			    for (j = 0; j < 128; j++)
				bufr[j] = bufr[(BufSize-128)+j];
			    }
			sendchar(ACK);
			}
		    else
			{
			errorflag = TRUE;
			if (timeout == TRUE)
			return FALSE;
			}
		    }
		else
		    {
		    if (sectcurr == (sectnum & 0xff))
			{
			emits("\nReceived Duplicate Sector\n");
			sendchar(ACK);
			}
		    else
		    errorflag = TRUE;
		    }
		}
	    else
	    errorflag = TRUE;
	    }
	if (errorflag == TRUE)
	    {
	    errors++;
	    emits("\nError\n");
	    sendchar(NAK);
	    }
	}        /* end while */
    if ((firstchar == EOT) && (errors < ERRORMAX))
	{
	sendchar(ACK);
	if (exe) while (bufr[--bufptr] != 0xF2) ;
	else     while (bufr[--bufptr] == 0) ;
	write(fd, bufr, ++bufptr);
	close(fd);
	return TRUE;
	}
    return FALSE;
    }

XMODEM_Send_File(file)
char *file;
    {
    int sectnum, bytes_to_send, size, attempts, c, i;
    unsigned checksum, j, bufptr;
    char numb[10];
    timeout=FALSE;
    bytes_xferred = 0;
    if ((fd = open(file, 0)) < 0) {
	emits("Cannot Open Send File\n");
	return FALSE;
	}
    else
    emits("Sending File\n\nType <ESC> to abort transfer\n");
    attempts = 0;
    sectnum = 1;
    /* wait for sync char */
    j=1;
    while (((c = readchar()) != NAK) && (j++ < ERRORMAX));
    if (j >= (ERRORMAX))
	{
	emits("\nReceiver not sending NAKs\n");
	return FALSE;
	}

    while ((bytes_to_send = read(fd, bufr, BufSize)) && attempts != RETRYMAX)
	{
	if (bytes_to_send == EOF)
	    {
	    emits("\nError Reading File\n");
	    return FALSE;
	    }

	bufptr = 0;
	while (bytes_to_send > 0 && attempts != RETRYMAX)
	    {
	    attempts = 0;
	    do
		{
		sendchar(SOH);
		sendchar(sectnum);
		sendchar(~sectnum);
		checksum = 0;
		size = SECSIZ <= bytes_to_send ? SECSIZ : bytes_to_send;
		bytes_to_send -= size;
		for (j = bufptr; j < (bufptr + SECSIZ); j++)
		if (j < (bufptr + size))
		    {
		    sendchar(bufr[j]);
		    checksum += bufr[j];
		    }
		else
		    {
		    sendchar(0);
		    }
		sendchar(checksum & 0xff);
		attempts++;
		c = readchar();
		if (timeout == TRUE)
		return FALSE;
		}
	    while ((c != ACK) && (attempts != RETRYMAX));
	    bufptr += size;
	    bytes_xferred += size;
	    emits("Block ");
	    sprintf(numb, "%d", sectnum);
	    emits(numb);
	    emits(" sent\n");
	    sectnum++;
	    }
	}
    close(fd);
    if (attempts == RETRYMAX)
	{
	emits("\nNo Acknowledgment Of Sector, Aborting\n");
	return FALSE;
	}
    else
	{
	attempts = 0;
	do
	    {
	    sendchar(EOT);
	    attempts++;
	    }
	while ((readchar() != ACK) && (attempts != RETRYMAX) && (timeout == FALSE));
	if (attempts == RETRYMAX)
	emits("\nNo Acknowledgment Of End Of File\n");
	}
    return TRUE;
    }


SHAR_EOF
cat << \SHAR_EOF > vt100.h
/*********************************************************************
*  a terminal program that has ascii and xmodem transfer capability
*
*  use esc to abort xmodem transfer
*
*  written by Michael Mounier
*  new version by Dave Wecker 860621
************************************************************************/

/*  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 <hardware/blit.h>
#include <stdio.h>
#include <ctype.h>
#include <libraries/dos.h>
#include <functions.h>

#undef NULL
#define   NULL   ((void *)0)

#define INTUITION_REV 1L
#define GRAPHICS_REV  1L

/* things for xmodem send and recieve */
#define SECSIZ   0x80
#define TTIME    10          /* number of seconds for timeout */
#define BufSize  0x1000      /* Text buffer */
#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 6    /* number of file menu items */
#define RSMAX 5      /* speed menu items */
#define XFMAX 2      /* transfer mode items */
#define MAXMENU 3    /* total number of menu entries */

#define MINX    3L
#define MAXX    627L
#define MINY    18L
#define MAXY    202L

extern struct MsgPort *CreatePort();

#ifdef MODULE_MAIN
char    bufr[BufSize];
int     fd, timeout = FALSE;
long    bytes_xferred;
int     imagemode = TRUE;
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;

struct NewScreen NewScreen = {
   0,0,640,400,1,       /* left, top, width, height, depth */
   0,1,(HIRES|LACE),    /* DetailPen, BlockPen, ViewModes */
   CUSTOMSCREEN,NULL,   /* Type, Font */
   (UBYTE *)"VT100 Terminal Screen", /* Title */
   NULL,NULL };         /* Gadgets, Bitmap */

struct NewWindow NewWindow = {
   0,100,640,212,     /* left, top, width, height */
   0,1,              /* detailpen, blockpen */
   CLOSEWINDOW | RAWKEY | MENUPICK | NEWSIZE,
   WINDOWCLOSE | SMART_REFRESH | ACTIVATE | WINDOWDRAG
   | WINDOWDEPTH | WINDOWSIZING | REPORTMOUSE, /* Flags */
   NULL,NULL,        /* FirstGadget, CheckMark */
   (UBYTE *)
   "VT100 Terminal Window                                                  ",
   NULL,             /* set screen after open screen */
   NULL,             /* bitmap */
   640, 212, 640, 212,/* minw, minh, maxw, maxh */
   CUSTOMSCREEN      /* Type */
};

struct Screen *myscreen;            /* ptr to applications screen */
struct Window *mywindow;            /* ptr to applications window */
struct ViewPort *myviewport;
struct ColorMap *mycolormap;
USHORT *mycolortable;
struct IntuiMessage *NewMessage;    /* msg structure for GetMsg() */

struct MenuItem FileItem[FILEMAX];
struct IntuiText FileText[FILEMAX];
struct MenuItem RSItem[RSMAX];
struct IntuiText RSText[RSMAX];
struct MenuItem XFItem[XFMAX];
struct IntuiText XFText[XFMAX];
struct Menu menu[MAXMENU];
struct IOExtSer *Read_Request;
char rs_in[2];
struct IOExtSer *Write_Request;
char rs_out[2];
short x,y,curmode;

#else /* not MODULE_MAIN */
extern char    bufr[BufSize];
extern int     fd, timeout;
extern long    bytes_xferred;
extern int     imagemode;

extern struct IntuitionBase *IntuitionBase;
extern struct GfxBase *GfxBase;

extern struct NewScreen NewScreen;
extern struct NewWindow NewWindow;
extern struct Screen *myscreen;
extern struct Window *mywindow;
extern struct ViewPort *myviewport;
extern struct ColorMap *mycolormap;
extern USHORT *mycolortable;
extern struct IntuiMessage *NewMessage;
extern struct MenuItem FileItem[FILEMAX];
extern struct IntuiText FileText[FILEMAX];
extern struct MenuItem RSItem[RSMAX];
extern struct IntuiText RSText[RSMAX];
extern struct MenuItem XFItem[XFMAX];
extern struct IntuiText XFText[XFMAX];
extern struct Menu menu[MAXMENU];
extern struct IOExtSer *Read_Request;
extern char rs_in[2];
extern struct IOExtSer *Write_Request;
extern char rs_out[2];
extern short x,y,curmode;
#endif /* not MODULE_MAIN */

#ifndef MODULE_INIT
extern InitDevs(),InitFileItems(),InitRSItems(),InitXFItems(),InitMenu();
#endif

#ifndef MODULE_WINDOW
extern filename(),emits(),emit(),cursoroff(),cursoron(),toasc();
#endif

#ifndef MODULE_XMODEM
extern sendchar(), sendstring(), readchar(),
       XMODEM_Read_File(), XMODEM_Send_File();
#endif

#ifndef MODULE_REMOTE
extern doremote();
#endif

#ifndef MODULE_KERMIT
extern doksend(),dokreceive();
#endif

SHAR_EOF
#	End of shell archive
exit 0