[comp.sources.amiga] v02i037: VT100 R2.7

doc@s.cc.purdue.edu (Craig Norborg) (10/03/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  3 out of  3.
# This archive created: Sat Oct  3 01:36:26 1987
# By: Craig Norborg (Purdue University Computing Center)
#	Run the following text with /bin/sh to create:
#	script.c
#	vt100.c
#	vt100.h
#	xmodem.c
cat << \SHAR_EOF > script.c
/*************************************************************
 * vt100 terminal emulator - Script file support
 *
 *	v2.7 870825 ACS - Wait for the reply from AbortIO().
 *			  Use the *InfoMsg*() routines in window.c.  Provide
 *			  for multiple script files on command line
 *			  (companion to the changes in init.c).  Add the
 *			  ability to set shortcuts from init file.
 *	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 BAUD, PARITY and WORD commands & handling
 *	     860823 DBW - Integrated and rewrote lots of code
 *	     860815 Steve Drew: Initial version written of SCRIPT.C
 *	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"

struct COMMAND {
    void (*func)();
    char *cname;
};

struct LABEL  {
    struct LABEL *next;
    char *name;
    long pos;
};

extern long atol();

struct SHORT_CUTS {
    char *cname;
    char *pos;
};
    
/*   Following variables are set up in init.c's InitDefaults.  They tell
** us if there are any other script files listed on the command line so
** that we can execute them when a prior script is done.  */

extern int script_files_todo;
extern char **script_files;

/****************  globals  needed  ******************/

char		on_string[20];	     /* string to match on for on cmd	 */
char		wait_string[20];     /* string to match of for wait cmd  */
char		golabel[20];	     /* label we are looking for in goto */
char		on_cmd[20];	     /* command to execute when on matchs*/
int		onsize;		     /* size of on_string		 */
int		waitsize;	     /* size of wait_string		 */
int		onpos;		     /* position in on string for search */
int		waitpos;	     /* pos in wait_string for search	 */
int		on_match;	     /* flag set while doing on_cmd	 */
FILE		*sf;		     /* file pointer for script file	 */
struct LABEL	*lbase = NULL;	     /* will point to first label	 */
struct LABEL	*labels;	     /* current label pointer		 */

void cmd_short();

/********************** command tables *******************************/
static struct COMMAND inicmds[] = {	/* initialization commands */
    cmd_bkg,	"bac",		/* set background color     */
    cmd_bold,	"bol",		/* set bold color	    */
    cmd_buf,	"buf",		/* set buffer size	    */
    cmd_cursor, "cur",		/* set cursor color	    */
    cmd_depth,	"dep",		/* set screen depth	    */
    cmd_fore,	"for",		/* set foreground color     */
    cmd_inter,	"int",		/* interlace ON/OFF	    */
    cmd_lines,	"lin",		/* num lines		    */
    cmd_screen, "scr",		/* Screen WB/CUST	    */
    cmd_volume, "vol",		/* set volume		    */
    cmd_wb,	"wb",		/* use WB colors	    */
    cmd_short,	"sho",		/* Set shortcuts	    */
    cmd_null,	NULL		/* mark the end of the list */
};
static struct COMMAND scrcmds[] = {	/* script only commands */
    cmd_as,	"asc",		/* ascii send		    */
    cmd_beep,	"bee",		/* Beep			    */
    cmd_cap,	"cap",		/* ascii capture on/off     */
    cmd_cd,	"cd",		/* change directory	    */
    cmd_delay,	"del",		/* delay amount of seconds  */
    cmd_goto,	"got",		/* goto label		    */
    cmd_kb,	"kb",		/* kermit bye (for server)  */
    cmd_kg,	"kg",		/* kermit get file	    */
    cmd_kr,	"kr",		/* kermit receive file	    */
    cmd_ks,	"ks",		/* kermit send file	    */
    cmd_on,	"on",		/* on a 'string' do a cmd   */
    cmd_sb,	"sb",		/* Send a break		    */
    cmd_send,	"send",		/* send string to host	    */
    cmd_wait,	"wait",		/* wait for a host string   */
    cmd_xr,	"xr",		/* xmodem receive file	    */
    cmd_xs,	"xs",		/* xmodem send file	    */
    cmd_null,	NULL		/* mark the end of the list */
};
static struct COMMAND commands[]= {	/* generally available commands */
    cmd_appcur, "app",		/* turn app. cursor on/off  */
    cmd_baud,	"bau",		/* Set Baud Rate	    */
    cmd_bt,	"bre",		/* Set Break Time	    */
    cmd_conv,	"con",		/* convert fn to lowercase  */
    cmd_echo,	"ech",		/* turn echo on or off	    */
    cmd_exit,	"exi",		/* exit script file	    */
    cmd_fnc,	"f",		/* define function key	    */
    cmd_key,	"key",		/* keyscript character	    */
    cmd_mode,	"mod",		/* KERMIT transfer mode     */
    cmd_numkey, "numkey",	/* turn numeric kpad on/off */
    cmd_parity, "parity",	/* Set Parity		    */
    cmd_swap,	"swap",		/* Swap BS and DEL	    */
    cmd_wrap,	"wrap",		/* turn wrap on or off	    */
    cmd_null,	NULL		/* mark the end of the list */
};

/*   NB: The structures referenced in the structure may be found in
** init.c */
struct filecmd {
    char ac;	/* ASCII Capture	*/
    char as;	/* ASCII Send		*/
    char xs;	/* Xmodem Send		*/
    char xr;	/* Xmodem Receive	*/
    char kg;	/* Kermit Get		*/
    char kr;	/* Kermit Receive	*/
    char ks;	/* Kermit Send		*/
    char kb;	/* Kermit Bye		*/
    char nl;
} filecmd_chars;

struct baducmd {
    char b03;	/* 0300			*/
    char b12;	/* 1200			*/
    char b24;	/* 2400			*/
    char b48;	/* 4800			*/
    char b96;	/* 9600			*/
    char bnl;
} baudcmd_chars;

struct parcmd {
    char no;	/* NOne			*/
    char ma;	/* MArk			*/
    char sp;	/* SPace		*/
    char ev;	/* EVen			*/
    char od;	/* ODd			*/
    char nl;
} parcmd_chars;

struct modcmd {
    char im;	/* IMage		*/
    char tx;	/* TeXt			*/
    char cn;	/* CoNvert		*/
    char nl;
} modcmd_chars;

extern struct scrcmd {
    char em;	/* Execute Macro	*/
    char ab;	/* Abort Macro		*/
    char nl;
} scrcmd_chars;

extern struct {
    char sb;	/* Send Break	*/
    char hu;	/* Hang Up	*/
    char cd;	/* Change Dir	*/
    char cs;	/* Clear Screen	*/
    char ec;	/* ECho		*/
    char wr;	/* WRap		*/
    char nk;	/* Num Key	*/
    char ac;	/* App Cur	*/
    char bs;	/* BS<->DEL	*/
    char nl;
} utilcmd_chars;

static struct SHORT_CUTS shortkeys[] = {	/* Short-cut keys */
	/* File items:	*/
    "cap", &(filecmd_chars.ac),		/* ascii capture on/off     */
    "asc", &(filecmd_chars.as),		/* ascii send		    */
    "xr", &(filecmd_chars.xs),		/* xmodem receive file	    */
    "xs", &(filecmd_chars.xr),		/* xmodem send file	    */
    "kg", &(filecmd_chars.kg),		/* kermit get file	    */
    "kr", &(filecmd_chars.kr),		/* kermit receive file	    */
    "ks", &(filecmd_chars.ks),		/* kermit send file	    */
    "kb", &(filecmd_chars.kb),		/* kermit bye (for server)  */
	/* Comm items:	*/
    "300", &(baudcmd_chars.b03),	/* Set Baud Rate	    */
    "1200", &(baudcmd_chars.b12),	/* Set Baud Rate	    */
    "2400", &(baudcmd_chars.b24),	/* Set Baud Rate	    */
    "4800", &(baudcmd_chars.b48),	/* Set Baud Rate	    */
    "9600", &(baudcmd_chars.b96),	/* Set Baud Rate	    */
    "none", &(parcmd_chars.no),		/* Set Parity		    */
    "mark", &(parcmd_chars.ma),		/* Set Parity		    */
    "space", &(parcmd_chars.sp),	/* Set Parity		    */
    "even", &(parcmd_chars.ev),		/* Set Parity		    */
    "odd", &(parcmd_chars.od),		/* Set Parity		    */
    "image", &(modcmd_chars.im),	/* KERMIT transfer mode     */
    "text", &(modcmd_chars.tx),		/* KERMIT transfer mode     */
    "convert", &(modcmd_chars.cn),	/* KERMIT transfer mode     */
	/* Script items:	*/
    "execute", &(scrcmd_chars.em),	/* execute macro	    */
    "abort", &(scrcmd_chars.ab),	/* abort macro		    */
	/* Util items: */
    "sb", &(utilcmd_chars.sb),		/* send break		    */
    "hang", &(utilcmd_chars.hu),	/* hang up		    */
    "cd", &(utilcmd_chars.cd),		/* change directory	    */
    "clear", &(utilcmd_chars.cs),	/* clear screen		    */
    "ech", &(utilcmd_chars.ec),		/* turn echo on or off	    */
    "wrap", &(utilcmd_chars.wr),	/* turn wrap on or off	    */
    "numkey", &(utilcmd_chars.nk),	/* turn numeric kpad on/off */
    "app", &(utilcmd_chars.ac),		/* turn app. cursor on/off  */
    "con", &(utilcmd_chars.bs),		/* convert bs to del	    */
    "swap", &(utilcmd_chars.bs),	/* Swap BS and DEL	    */
    NULL, NULL
};

/********************************************************************/
/* checks char to see if match with on string or wait_string	    */
/* if on string match oncmd gets executed imediately,		    */
/* if wait_string match script_wait is set.			    */
/********************************************************************/

chk_script(c)
char c;
{
    if (on_string[0] != '\0') {
	if (on_string[onpos] == c) {
	    onpos++;
	    if (onpos == onsize) {
		on_match = TRUE;
		do_script_cmd(ONCOMMAND);
		on_match = FALSE;
		return(0);
	    }
	}
	else onpos = 0;
    }
    if (wait_string[0] != '\0') {
       if (wait_string[waitpos] != c) {
	    waitpos = 0;
	    return(0);
	}
	waitpos++;
	if (waitpos != waitsize) return(0);
	wait_string[0] = '\0';
	script_wait = FALSE;
    }
}

script_start(file)
char *file;
{
    char *sfile = NULL;

    if (strlen(file) == 0 || *file == '#') return(0);
    if ((sf = fopen(file, "r")) == NULL) {
	    sfile = AllocMem((LONG)(strlen(file)+3), MEMF_PUBLIC|MEMF_CLEAR);
	    strcpy(sfile, "S:");
	    strcat(sfile, file);
	    if((sf = fopen(sfile, "r")) == NULL) {
		InfoMsg2Line("Can't open script file",file);
		return(0);
	    }
    }
    script_on = TRUE;
    script_wait = FALSE;
    wait_string[0] = '\0';
    on_string[0] = '\0';
    on_match = FALSE;
    lbase = NULL;
    if(sfile)
	FreeMem(sfile, (LONG)strlen(file)+3);
}

/* return pointer to next word. set l to size of the word */

char *next_wrd(s,l)
char *s;
int *l;
{
    char *p;

    while(*s && (*s == ' ' || *s == '\t')) s++;
    p = s;
    while(*s && (*s != ' ' && *s != '\t')) s++;
    *l = s-p;
    return(p);
}

exe_cmd(p,l)
char *p;
int l;
{
    int i,l2;

    /* downcase the command */
    for (i=0; i<l; i++) p[i] |= ' ';

    /* now search for it (first in the init command list) */
    if (doing_init)
	for (i=0; inicmds[i].func != cmd_null; ++i) {
	    l2 = strlen(inicmds[i].cname);
	    if (l >= l2 && strncmp(p, inicmds[i].cname, l2) == 0) {
		(*inicmds[i].func)(next_wrd(p+l, &l));
		return(TRUE);
	    }
	}

    /* or the script command list */
    else
	for (i=0; scrcmds[i].func != cmd_null; ++i) {
	    l2 = strlen(scrcmds[i].cname);
	    if (l >= l2 && strncmp(p, scrcmds[i].cname, l2) == 0) {
		(*scrcmds[i].func)(next_wrd(p+l, &l));
		return(TRUE);
	    }
	}

    /* now search for it (in the standard command list) */
    for (i=0; commands[i].func != cmd_null; ++i) {
	l2 = strlen(commands[i].cname);
	if (l >= l2 && strncmp(p, commands[i].cname, l2) == 0) {
	    (*commands[i].func)(next_wrd(p+l, &l));
	    return(TRUE);
	}
    }
    if (doing_init) {
	puts("INIT - unknown command:");
	puts(p);
    }
    else InfoMsg2Line("Script - unknown command:",p);

    return(FALSE);
}

struct LABEL *find_label(lname)
char *lname;
{
    struct LABEL *label;

    label = lbase;
    while(label != NULL) {
	if (strcmp(label->name, lname) == 0) return (label);
	label = label->next;
    }
    return(NULL);
}

do_script_cmd(stat)
int stat;
{
    int len,l;
    char line[256];
    char *p;

    /* if ON command is matched and we were	*/
    /* doing a DELAY then abort the delay timer,*/
    /* except if on_cmd was just a SEND.	*/
    if (stat == ONCOMMAND) {
	strcpy(line,on_cmd);
	p = next_wrd(line,&l);
	if (*p != 's' && script_wait == WAIT_TIMER)  {
	    AbortIO((char *) &Script_Timer);
	    Wait (1L << Script_Timer_Port->mp_SigBit);
	    WaitIO(Script_Timer);

	    /* script will proceed after on command    */
	    script_wait = FALSE;
	}
	exe_cmd(p,l);
	return(0);
    }
    script_wait = FALSE;
    while(fgets(line,256,sf) != NULL) {
       len = strlen(line);
       line[--len] = '\0';
       p = next_wrd(&line[0], &l);
       if (*(p + l - 1) == ':') {		/* its a label */
	   *(p + l - 1) = '\0';
	   if (find_label(p) == NULL) {		/* it's a new label */
		if (lbase == NULL)  {		/* it's the first label */
		    labels = lbase = (struct LABEL *)
			malloc(sizeof (struct LABEL));
		}
		else {
		    labels->next = (struct LABEL *)
			malloc(sizeof (struct LABEL));
		    labels = labels->next;
		}
		labels->pos  = ftell(sf);
		labels->name = malloc(l);
		labels->next = NULL;
		strcpy(labels->name, p);
		if (stat == GOTOLABEL && strcmp(p, golabel) == 0)
		      stat = NEXTCOMMAND;
	    }
	    p = next_wrd(p+l+1, &l);
	}   /* end of it's a label */
	if (stat == GOTOLABEL || *p == '#') continue;
	if (*p) exe_cmd(p,l);
	return(0);
    }		    /* end of while */
    if (stat == GOTOLABEL) InfoMsg2Line("Script - label not found:",golabel);
    exit_script();
    if(script_files_todo > 0) {
	script_files_todo--;
	script_start(*(script_files++));
    }
}

exit_script()
{
    if (script_wait == WAIT_TIMER) {	/* timer not done yet */
       AbortIO((char *) &Script_Timer); /* so abort it */
       Wait (1L << Script_Timer_Port->mp_SigBit); /* Wait for the sig */
       WaitIO(Script_Timer); /* Get my reply back */
    }
    InfoMsg1Line("Script - terminated");
    script_on = FALSE;
    script_wait = TRUE;
    fclose(sf);
}

/* remove quotes terminate string & return pointer to start */

char *tostring(ptr)
char *ptr;
{
    char *s1,*s2;

    s1 = ptr;
    if (*ptr == '"') {
	while(*ptr++  && *ptr != '"') ;
	if (*ptr == '"') {
	    *ptr = '\0';
	    ptr = s2 = ++s1;
	    while(*s2) {
		if	(*s2 != '^')	 *s1++ = *s2;
		else if (*(s2+1) == '^') *s1++ = *s2++;
		else			 *s1++ = ((*++s2)|' ')-96;
		s2++;
	    }
	    *s1 = '\0';
	    return(ptr);
	}
    }
    if (*s1 == '^') {
	*s1 = (*(s1+1)|' ')-96;
	*(s1+1) = '\0';
	return(s1);
    }
    *(s1+1) = '\0';
    return(s1);
}

/***************************** SCRIPT COMMANDS ********************/

void cmd_goto(lname)
char *lname;
{
    struct LABEL *label;
			    /* if on_cmd was a goto kill wait state */
    if (on_match) { wait_string[0] = '\0'; script_wait = FALSE; }
    if ((label = find_label(lname)) == NULL) {	/* is it forward */
	strcpy(golabel,lname);
	do_script_cmd(GOTOLABEL);
    }
    else {
	fseek(sf,(long)(label->pos),0);
    }
}

void cmd_send(str)
char *str;
{
    sendstring(tostring(str));
}

void cmd_wait(str)
char *str;
{
    str = tostring(str);
    *(str+20) = '\0';	      /* 20 characters max */
    strcpy(wait_string, str);
    waitsize = strlen(str);
    script_wait = WAIT_STRING;
}

void cmd_on(str)
char *str;
{
   char *p;

    p = tostring(str);
    strcpy(on_string, p);
    onsize = strlen(p);
    *(p+onsize+2+20) = '\0';	    /* 20 characters max */
    strcpy(on_cmd,p+onsize+2);
}

void cmd_delay(seconds)
char *seconds;
{
    script_wait = WAIT_TIMER;
    Script_Timer.tr_time.tv_secs = atoi(seconds);
    Script_Timer.tr_time.tv_micro = 0;
    SendIO((char *) &Script_Timer.tr_node);
}

void cmd_exit(option)
char *option;
{
    char *p;
    int  l;

    if (doing_init) return;

    if (*option) {
	p = next_wrd(option,&l);
	*(p+l) = '\000';
	if  (strcmp(p,"vt100") == 0 || strcmp(p,"VT100") == 0)
	    cleanup("Exit vt100 from script",0);
	exit_script();
	script_start(p);
    }
    else {
	exit_script();
	if(script_files_todo > 0) {
	    script_files_todo--;
	    script_start(*(script_files++));
	}
    }
}

void cmd_ks(file)
char *file;
{
    multi_xfer(file, doksend, 1);
}

void cmd_kr(file)
char *file;
{
    multi_xfer(file, dokreceive, 0);
}

void cmd_kg(file)
char *file;
{
    server = TRUE;
    multi_xfer(file, dokreceive, 0);
}

void cmd_kb()
{
    saybye();
}

void cmd_xs(file)
char *file;
{
    multi_xfer(file, XMODEM_Send_File, 1);
}

void cmd_xr(file)
char *file;
{
    multi_xfer(file, XMODEM_Read_File, 1);
}

void cmd_cap(file)
char *file;
{
    do_capture(file);
}

void cmd_as(file)
char *file;
{
    do_send(file);
}

void cmd_cd(name)
char *name;
{
    set_dir(name);
}

void cmd_sb(str)
char *str;
{
    sendbreak();
}

void cmd_baud(rate)
char *rate;
{
    int i = atoi(rate);

    switch( i ) {
	case  300:
	case 1200:
	case 2400:
	case 4800:
	case 9600:
	if (doing_init) p_baud = i;
	else		setserbaud(i, TRUE);
	break;

	default:
	if (doing_init) {
	    puts("INIT - invalid baud rate:");
	    puts(rate);
	}
	else InfoMsg2Line("Script - invalid baud rate: ",rate);
	break;
    }
}

void cmd_parity(par)
char *par;
{
    int i;

    switch( *par|' ' ) {
	case 'n': i =  0; break;
	case 'm': i =  1; break;
	case 's': i =  2; break;
	case 'e': i =  3; break;
	case 'o': i =  4; break;

	default:
	if (doing_init) {
	    puts("INIT - invalid parity:");
	    puts(par);
	}
	else InfoMsg2Line("Script - invalid parity: ",par);
	return;
    }
    p_parity = i;
    if (doing_init) return;

    ClearMenuStrip( mywindow );		/* Remove old menu */
    InitCommItems();			/* Re-do comm menu   */
    SetMenuStrip(mywindow,&menu[0]);	/* Re-display the menu */
}

void cmd_bt(breaklength)
char *breaklength;
{
    p_break = atol(breaklength);
    if (doing_init) return;

    AbortIO(Read_Request);
    Wait(1L << Read_Request->IOSer.io_Message.mn_ReplyPort->mp_SigBit);
    WaitIO(Read_Request);
    Read_Request->io_BrkTime = Write_Request->io_BrkTime = p_break;
    setparams();
}

void cmd_mode(tmode)
char *tmode;
{
    switch (*tmode|' ') {
	case 'i':
	p_mode = 0;
	break;

	case 'c':
	p_mode = 1;
	break;

	default:
	if (doing_init) {
	    puts("INIT - invalid transfer mode: ");
	    puts(tmode);
	}
	else InfoMsg2Line("Script - invalid transfer mode: ",tmode);
	return;
    }
    if (doing_init) return;

    ClearMenuStrip(mywindow);
    InitCommItems();			/* Re-do comm menu   */
    SetMenuStrip(mywindow,&menu[0]);
}

void cmd_beep(dummy)
char	*dummy;
{
    if (p_volume == 0) DisplayBeep(NULL);
    else {
	BeginIO(&Audio_Request);
	WaitIO(&Audio_Request);
    }
}

void setvar(par,typ,var)
char	*par;
int	typ,*var;
{
    int i;

    switch (typ) {
	case 0: /* ON/OFF or YES/NO */
	case 1: /* not case */
	if ((par[1]|' ') == 'n' || (par[0]|' ') == 'y') *var = 1-typ;
	else						*var = typ;
	break;

	case 2: /* read hex number */
	if (sscanf(par,"%x",&i) == 1) *var = i;

	break;

	case 3: /* read decimal number */
	if (sscanf(par,"%d",&i) == 1) *var = i;
	break;
    }
}

void cmd_echo(par)
char	*par;
{
    setvar(par,0,&p_echo);
    if (doing_init == 0) redoutil();
}

void cmd_wrap(par)
char	*par;
{
    setvar(par,0,&p_wrap);
    if (doing_init == 0) redoutil();
}

void cmd_numkey(par)
char	*par;
{
    setvar(par,1,&p_keyapp);
    if (doing_init == 0) redoutil();
}

void cmd_appcur(par)
char	*par;
{
    setvar(par,0,&p_curapp);
    if (doing_init == 0) redoutil();
}

void cmd_swap(par)
char	*par;
{
    setvar(par,0,&p_bs_del);
    if (doing_init == 0) redoutil();
}

void cmd_bkg(par)
char	*par;
{
    setvar(par,2,&p_background);
}

void cmd_bold(par)
char	*par;
{
    setvar(par,2,&p_bold);
}

void cmd_buf(par)
char	*par;
{
    setvar(par,3,&p_buffer);
}

void cmd_cursor(par)
char	*par;
{
    setvar(par,2,&p_cursor);
}

void cmd_depth(par)
char	*par;
{
    setvar(par,3,&p_depth);
}

void cmd_fore(par)
char	*par;
{
    setvar(par,2,&p_foreground);
}

void cmd_inter(par)
char	*par;
{
    setvar(par,0,&p_interlace);
}

void cmd_lines(par)
char	*par;
{
    setvar(par,3,&p_lines);
}

void cmd_screen(par)
char	*par;
{
    if ((par[0]|' ') == 'w') p_screen = 0;
    else		     p_screen = 1;
}

void cmd_wb(par)
char	*par;
{
    setvar(par,0,&p_wbcolors);
}

void cmd_short(par)	/* Set keyboard shortcuts */
char	*par;
{
    int	i, l, l2;
    register char *p = par;
    
    /* downcase the next word */
    for (i=0; p[i] && (p[i] != ' '); i++) p[i] |= ' ';
    l = i;
    
    /*   Find the command name.  If found set the shortcut key to the
    ** user's value.  If no value then set the key to ' ' to indicate no
    ** shortcur available. */
    for(i = 0; shortkeys[i].cname != NULL; i++) {
	l2 = strlen(shortkeys[i].cname);
	if (l >= l2 && strncmp(p, shortkeys[i].cname, l2) == 0) {
	    for( ; p[l] && (p[l] == ' '); l++) ;
	    if(p[l])
		*(shortkeys[i].pos) = p[l];
	    else
		*(shortkeys[i].pos) = ' ';
	}
    }
}

void cmd_key(par)
char	*par;
{
    int i;

    if (sscanf(par,"%x",&i) == 1) p_keyscript = (char)(i & 0x7f);
}

void cmd_volume(par)
char	*par;
{
    setvar(par,3,&p_volume);
}

void cmd_conv(par)
char	*par;
{
    setvar(par,0,&p_convert);
    if (doing_init == 0) redoutil();
}

void cmd_fnc(par)
char	*par;
{
    char    *s;
    int     l;
    int     i = atoi(par);

    s = par;
    if (*s) s = next_wrd(s,&l);		/* skip key number */
    if (*s) s = next_wrd(s+l+1,&l);	/* point at desired string */
    if (*s) s = tostring(s);		/* convert the string */
    if (*s && i > 0 && i < 21) {
	if (i > 10) {
	    p_F[i-11] = malloc(strlen(s)+1);
	    strcpy(p_F[i-11],s);
	}
	else {
	    p_f[i-1] = malloc(strlen(s)+1);
	    strcpy(p_f[i-1],s);
	}
    }
}

void cmd_null(dummy)
char *dummy;
{ }

SHAR_EOF
cat << \SHAR_EOF > vt100.c
/********************************************************************
 *  vt100 terminal emulator with xmodem transfer capability
 *
 *	v2.7 870825 ACS - Provide handling of the msgs from the
 *			  info/status window.
 *	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
 *
 *  use <esc> to abort xmodem or kermit transfers
 *
 *  written by Michael Mounier
 *  new version by Dave Wecker
 *******************************************************************/

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

/**************************************************************/
/* here are all the global definitions that appear in vt100.h */
/**************************************************************/

char    bufr[BufSize];
int     fd, timeout = FALSE, ttime;
int	multi = FALSE, server;
long    bytes_xferred;
char	MyDir[60];
struct	FileLock *MyDirLock = NULL;
struct	FileLock *StartLock = NULL;
struct	IntuitionBase *IntuitionBase;
struct	GfxBase *GfxBase;

struct	TextAttr myattr = {
    (STRPTR) "topaz.font",
    8,
    0,
    0};
struct	TextFont *myfont = NULL;
struct NewScreen NewScreen = {
   0,0,640,200,1,		/* left, top, width, height, depth */
   0,1,HIRES,			/* DetailPen, BlockPen, ViewModes */
   CUSTOMSCREEN,&myattr,	/* Type, Font */
   (UBYTE *)"VT100",		/* Title */
   NULL,NULL };			/* Gadgets, Bitmap */
struct NewWindow NewWindow = {
   0,0,640,200,			/* left, top, width, height */
   0,1,				/* detailpen, blockpen */
   MENUPICK|CLOSEWINDOW|RAWKEY|ACTIVEWINDOW|INACTIVEWINDOW,
   SMART_REFRESH|ACTIVATE|BORDERLESS|WINDOWCLOSE|WINDOWDEPTH|WINDOWDRAG,
   NULL,NULL,			/* FirstGadget, CheckMark */
   (UBYTE *)NULL,
   NULL,			/* set screen after open screen */
   NULL,			/* bitmap */
   640, 200, 640, 200,		/* minw, minh, maxw, maxh */
   CUSTOMSCREEN			/* Type */
   };
struct NewWindow NewReqWindow = {
   10, 15, ((54*8)+4+18), ((4*8)+11+2), /* left, top, width, height */
   0, 1,			/* detailpen, blockpen */
	/* IDCMP Flags... */
   CLOSEWINDOW | ACTIVEWINDOW | REQCLEAR | REQSET | NEWSIZE,
	/* Flags... */
   SMART_REFRESH | NOCAREREFRESH | ACTIVATE | WINDOWSIZING | SIZEBRIGHT |
   WINDOWCLOSE | WINDOWDEPTH | WINDOWDRAG,

   NULL,			/* First gadget */
   NULL,			/* CheckMark */
   (UBYTE *)"VT100 Info & Xfer Status",	/* Title */
   NULL,			/* set screen after open screen */
   NULL,			/* bitmap */
   ((5*8)+4+18), ((1*8)+11+2), 640, 200,	/* minw, minh, maxw, maxh */
   CUSTOMSCREEN			/* Type */
   };
struct IntuiText MyTitle = {
    0,1,JAM2,26,0,		/* front pen, back pen, mode, left, top */
    &myattr,			/* font */
    (UBYTE *)VERSION,		/* title */
    NULL};			/* next text */

struct Screen *myscreen = NULL;		/* ptr to applications screen */
struct Window *mywindow = NULL;		/* ptr to applications window */
struct Window *reqwindow = NULL;	/* ptr to requester's window */
struct ViewPort *myviewport;
struct RastPort *myrastport;
struct IntuiMessage *NewMessage;	/* msg structure for GetMsg() */
struct Preferences  *Prefs;		/* preferences from GetPrefs() */

/**** String requester support ******/

char	InpBuf[80],UndoBuf[80],Prompt[80];
struct IntuiText donetxt = {
    1,0,JAM2,0,0,	/* front pen, back pen, mode, left, top */
    &myattr,		/* font */
    (UBYTE *)"DONE",	/* question to ask */
    NULL};		/* next text */
struct Gadget mydonegad = {
    &mystrgad,290,2,40,10,	/* next,left,top,width,height */
    GADGHCOMP|REQGADGET,	/* flags */
    RELVERIFY|ENDGADGET,	/* activation */
    BOOLGADGET,			/* gadget type */
    NULL,NULL,&donetxt,		/* gad render, sel render, gad text */
    0L,NULL,2,NULL};		/* mutual exclude, special, ID, user data */
struct	StringInfo mystrinfo = {
    (UBYTE *)InpBuf,
    (UBYTE *)UndoBuf,
    0,80,0,0,0,0,	/* initial, max, disp, undo, #chrs, dsp chrs */
    0,0,NULL,0L,NULL};	/* left,top,layer,longint,keymap */
struct Gadget mystrgad = {
    NULL,10,12,320,10,	/* next,left,top,width,height */
    GADGHCOMP|REQGADGET,/* flags */
    ENDGADGET,STRGADGET,/* activation, type */
    NULL,NULL,NULL,	/* gad render, sel render, gad text */
    0L,			/* mutual exclude */
    (APTR)&mystrinfo,	/* special info */
    1,NULL};		/* gadget ID, user data */
struct IntuiText mystrtxt = {
    0,1,JAM2,10,2,	/* front pen, back pen, mode, left, top */
    &myattr,		/* font */
    (UBYTE *)Prompt,	/* question to ask */
    NULL};		/* next text */
struct Requester myrequest = {
    NULL,0,10,340,22,	/* older requester, left, top, width, height */
    0,0,&mydonegad,	/* relleft reltop, gadgets */
    NULL,		/* border */
    &mystrtxt,		/* text */
    NULL,1,NULL,	/* flags, back fill pen, layer */
    {0,0,0,0,0,0,0,0,
     0,0,0,0,0,0,0,0,
     0,0,0,0,0,0,0,0,
     0,0,0,0,0,0,0,0},	/* pad1 */
    NULL,NULL,		/* image bit map, rquest window */
    {0,0,0,0,0,0,0,0,0,
     0,0,0,0,0,0,0,0,0,
     0,0,0,0,0,0,0,0,0,
     0,0,0,0,0,0,0,0,0} /* pad2 */
    };

int numreqs = 0;		/* number of outstanding requestors */
int reqwinup = 0;		/* Requester window is NOT displayed */
extern int reqmaxx, reqmaxy, reqmaxlen;	/* Defined in window.c */
extern void ReqNewSize();	/* New req window size -- window.c */
extern void KillReq();		/* Kill requester window in window.c */	

/***** menu structures *****/
struct MenuItem FileItem[FILEMAX];
struct IntuiText FileText[FILEMAX];
struct MenuItem CommItem[COMMAX];
struct IntuiText CommText[COMMAX];
struct MenuItem RSItem[RSMAX];
struct IntuiText RSText[RSMAX];
struct MenuItem ParItem[PARMAX];
struct IntuiText ParText[PARMAX];
struct MenuItem XFItem[XFMAX];
struct IntuiText XFText[XFMAX];
struct MenuItem ScriptItem[SCRIPTMAX];
struct IntuiText ScriptText[SCRIPTMAX];
struct MenuItem UtilItem[UTILMAX];
struct IntuiText UtilText[UTILMAX];
struct Menu menu[MAXMENU];
struct IOExtSer *Read_Request;
char *rs_in;
struct IOExtSer *Write_Request;
char rs_out[2];
struct timerequest Timer;
struct MsgPort *Timer_Port = NULL;
struct timerequest Script_Timer;
struct MsgPort *Script_Timer_Port = NULL;
struct IOAudio Audio_Request;
struct MsgPort *Audio_Port = NULL;
UBYTE  *BeepWave;
UBYTE  Audio_AllocMap[4] = { 1, 8, 2, 4 };
int x,y,curmode;
int MINX	= 0;
int MAXX	= 632;
int MINY	= 14;
int MAXY	= 198;
int top		= 14;
int bot		= 198;
int savx	= 0;
int savy	= 14;
int savmode	= 0;
int nlmode	= 0;
int alt		= 0;
int savalt	= 0;
int a[2]	= { 0, 0 };
int sa[2]	= { 0, 0 };
int  inesc	= -1;
int  inctrl	= -1;
int  private	= 0;
int  badseq	= 0;
int  maxcol	= 79;

/*************************** defaults *******************************/
int	p_baud	     = 1200;	    /* baud rate */
int	p_screen     = 0;	    /* 0 = WORKBENCH,	    1 = CUSTOM */
int	p_wbcolors   = 1;	    /* 0 = Custom, 1 = Workbench colors */
int	p_interlace  = 0;	    /* 0 = no interlace,    1 = interlace */
int	p_depth	     = 2;	    /* number of bit planes (1 or 2) */
int	p_foreground = 0x840;	    /* default foreground RGB color */
int	p_background = 0x000;	    /* default background RGB color */
int	p_bold	     = 0x000;	    /* default BOLD       RGB color */
int	p_cursor     = 0x00d;	    /* default Cursor	  RGB color */
int	p_lines	     = 24;	    /* number of lines on the screen */
int	p_mode	     = 0;	    /* 0 = image, 1 = CRLF (for kermit) */
int	p_buffer     = 512;	    /* read buffer size (>= 512 bytes) */
int     p_parity     = 0;	    /* 0=none,1=mark,2=space,3=even,4=odd */
long	p_break	     = 750000;	    /* break time (in micro seconds) */
int	p_volume     = 64;	    /* beep volume (0 = DisplayBeep) */
int	p_wrap	     = 1;	    /* 0 = truncate, 1 = wrap long lines */
int	p_keyapp     = 0;	    /* 0 = numeric, 1 = application keypad */
int	p_curapp     = 0;	    /* 0 = cursor, 1 = application cursor */
int	p_echo	     = 0;	    /* 0 = full duplex, 1 = half duplex */
int	p_bs_del     = 0;	    /* 0 = normal, 1 = swap bs and delete */
int	p_convert    = 0;	    /* 1 = convert filenames to lower case */
char	p_keyscript  = 0x7E;	    /* function key script introducer = ~ */
char	*p_f[10]     = {	    /* function key defaults */
    "\033OP","\033OQ","\033OR","\033OS",
    "f5","f6","f7","f8","f9","f10" };

char	*p_F[10]     = {	    /* shifted function key defaults */
    "F1","F2","F3","F4","F5",
    "F6","F7","F8","F9","F10"};

/* for script file */
int script_on;
int script_wait;
int doing_init = 0;

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

char lookahead[80];
FILE *tranr = NULL;
FILE *trans = NULL;
int capture,send;
char name[80];
struct MsgPort *mySerPort;

main(argc,argv)
int	argc;
char	**argv;
    {
    ULONG class, waitmask;
    unsigned int code, qual;
    int KeepGoing,i,la,dola,actual;
    char c,*ptr;

    ptr = InitDefaults(argc,argv);
    InitDevs();
    InitFileItems();
    InitCommItems();
    InitScriptItems();
    InitUtilItems();
    InitMenu();
    SetMenuStrip(mywindow,&menu[0]);
    PrintIText(mywindow->RPort,&MyTitle,0L,0L);

    MyDir[0]  =	    '\000';
    StartLock =	(struct FileLock *)((ULONG)((struct Process *)
		    (FindTask(NULL)))->pr_CurrentDir);
    MyDirLock = (struct FileLock *)DupLock(StartLock);
    KeepGoing =	    TRUE;
    capture   =	    FALSE;
    send      =	    FALSE;
    maxcol    =	    MAXX / 8;
    la	      =	    0;
    x	      =	    MINX ;
    y	      =	    MINY;
    curmode   =	    FS_NORMAL;
    script_on =     FALSE;
    script_wait=    TRUE;
    SetAPen(mywindow->RPort,1L);
    cursorflip();
    cursorflip();
    emit(12);
    mySerPort = Read_Request->IOSer.io_Message.mn_ReplyPort;
    SendIO(Read_Request);

    /* see if we had a startup script */
    if (ptr != NULL) script_start(ptr);

    reqwinup = 0;
    while( KeepGoing )
	    {
	    /* wait for window message or serial port message */
	    cursorflip();
	    if(reqwinup)
		waitmask = (1L << mySerPort->mp_SigBit) |
			   (1L << mywindow->UserPort->mp_SigBit) |
			   (1L << Script_Timer_Port->mp_SigBit) |
			   (1L << reqwindow->UserPort->mp_SigBit);
	    else
		waitmask = (1L << mySerPort->mp_SigBit) |
			   (1L << mywindow->UserPort->mp_SigBit) |
			   (1L << Script_Timer_Port->mp_SigBit);
	    if (script_wait)	/* if script ready dont wait here */
		Wait(waitmask);
	    cursorflip();

	    /* do ascii file send */
	    if (send)
		{
		if ((c=getc(trans)) != EOF) {
		    if (c == '\n') c = '\r';
		    sendchar(c);
		    }
		else {
		    fclose(trans);
		    InfoMsg1Line("File Sent");
		    send=FALSE;
		    }
		}

	    /* see if there are any characters from the host */
	    if (CheckIO(Read_Request)) {
		WaitIO(Read_Request);
		c = rs_in[0] & 0x7F;
		doremote(c);
		if (script_on) chk_script(c);
		if (capture && c != 10) {
		    if (c == 13) c = 10;
		    putc(c , tranr);
		    }
		Read_Request->IOSer.io_Command = SDCMD_QUERY;
		DoIO(Read_Request);
		Read_Request->IOSer.io_Command = CMD_READ;
		actual = (int)Read_Request->IOSer.io_Actual;
		if (actual > 0) {
		    if (inesc   <  0 &&
			inctrl  <  0 &&
			a[alt]  == 0 &&
			capture == FALSE) dola = 1;
		    else dola = 0;
		    Read_Request->IOSer.io_Length =
			Read_Request->IOSer.io_Actual;
		    DoIO(Read_Request);
		    Read_Request->IOSer.io_Length = 1;

		    for (i = 0; i < actual; i++) {
			c=rs_in[i] & 0x7f;
			if (script_on) chk_script(c);

			if (dola == 1) {
			    if (c >= ' ' && c <= '~' && la < 80)
				lookahead[la++] = c;
			    else {
				if (la > 0) {
				    emitbatch(la,lookahead);
				    la = 0;
				    }
				doremote(c);
				dola = 0;
				}
			    }
			else {
			    doremote(c);
			    if (inesc   <  0 &&
				inctrl  <  0 &&
				a[alt]  == 0 &&
				capture == FALSE) dola = 1;
			    if (capture && c != 10) {
				if (c == 13) c = 10;
				putc(c , tranr);
				}
			    }
			}

		    /* dump anything left in the lookahead buffer */
		    if (la > 0) {
			emitbatch(la,lookahead);
			la = 0;
			}
		    }
		SendIO(Read_Request);
		}

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

		    case RAWKEY:
		    c = toasc(code,qual,0);
		    if (p_echo) doremote(c);
		    break;

		    case NEWSIZE:
		    emit(12);
		    break;

		    case MENUPICK:
		    handle_menupick(class,code);
		    break;

		    default:
		    PrintIText(mywindow->RPort,&MyTitle,0L,0L);
		    break;
		    }   /* end of switch (class) */
		}   /* end of while ( newmessage )*/

	    if (!script_wait ||
		 (CheckIO(&Script_Timer) &&
		    script_wait == WAIT_TIMER))
		do_script_cmd(NEXTCOMMAND);

	    while( reqwinup &&  
		   ((NewMessage = (struct IntuiMessage *)
				  GetMsg(reqwindow->UserPort)) != FALSE)
		 ) {
		class = NewMessage->Class;
		ReplyMsg( NewMessage );
		switch( class ) {
		    case REQCLEAR:
		    numreqs = 0;
		    break;

		    case CLOSEWINDOW:
		    KillReq(); /* Kills requester window, set reqwinup = 0 */
		    break;

		    case NEWSIZE:
		    ReqNewSize(reqwindow->Height, reqwindow->Width);
		    break;
		}   /* end of switch (class) */
	    } /* end while */
    }  /* end while ( keepgoing ) */

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

    cleanup("",0);

} /* end of main */

/* cleanup code */

cleanup(reason, fault)
char *reason;
int fault;
    {
    switch(fault) {
	case 0:		/* quitting close everything */
	KillReq();	/* Kill the requester and its window */
	ClearMenuStrip( mywindow );
	CloseDevice(&Audio_Request);
	if (MyDirLock != NULL) UnLock(MyDirLock);

	case 8:		/* error opening audio */
	DeletePort(Audio_Port);
	FreeMem(BeepWave,BEEPSIZE);
	CloseDevice(&Timer);

	case 7:		/* error opening timer */
	DeletePort(Timer_Port);
	CloseDevice(&Script_Timer);
	DeletePort(Script_Timer_Port);

	case 6:		/* error opening write device */
	DeletePort(Write_Request->IOSer.io_Message.mn_ReplyPort);
	FreeMem(Write_Request,(long)sizeof(*Write_Request));
	CloseDevice(Read_Request);

	case 5:		/* error opening read device */
	DeletePort(Read_Request->IOSer.io_Message.mn_ReplyPort);
	FreeMem(Read_Request,(long)sizeof(*Read_Request));

	case 4:		/* error opening window */
	if (myfont   != NULL) CloseFont( myfont );
	if (mywindow != NULL) CloseWindow( mywindow );
	if (p_screen != 0) CloseScreen( myscreen );

	case 3:		/* error opening screen */
	case 2:		/* error opening graphics library */
	case 1:		/* error opening intuition */
	default:
	if (*reason) puts (reason);
	}
    exit(fault);
    }

do_capture(file)
char *file;
    {
    if (capture == TRUE)
	{
	capture=FALSE;
	fclose(tranr);
	InfoMsg1Line("End File Capture");
	}
    else
	{
	if (file == NULL) {
	    name[0] = '\000';
	    req("Ascii Capture:",name,1);
	    }
	else strcpy(name, file);
	if ((tranr=fopen(name,"w")) == 0) {
	    capture=FALSE;
	    InfoMsg1Line("Error Opening File");
	    return(FALSE);
	    }
	capture=TRUE;
	}
    }

do_send(file)
char *file;
    {
    if (send == TRUE)
	{
	send=FALSE;
	fclose(trans);
	InfoMsg1Line("File Send Cancelled");
	}
    else
	{
	if (file == NULL) {
	    name[0] = '\000';
	    req("Ascii Send:",name,1);
	    }
	else strcpy(name, file);
	if ((trans=fopen(name,"r")) == 0) {
	    send=FALSE;
	    InfoMsg1Line("Error Opening File");
	    return(FALSE);
	    }
	send=TRUE;
	}
    }

void setparams()
    {
    Read_Request->IOSer.io_Command =
	Write_Request->IOSer.io_Command =
	    SDCMD_SETPARAMS;
    DoIO(Read_Request); DoIO(Write_Request);
    Read_Request->IOSer.io_Command = CMD_READ;
    SendIO(Read_Request);
    Write_Request->IOSer.io_Command = CMD_WRITE;
    }

void hangup ()
    {
    AbortIO(Read_Request);
    CloseDevice (Read_Request);
    Timer.tr_time.tv_secs=0L;
    Timer.tr_time.tv_micro=750000L;
    DoIO((char *) &Timer.tr_node);
    OpenDevice (SERIALNAME,NULL,Read_Request,NULL);
    setparams();
    }

void redocomm() {
    ClearMenuStrip( mywindow );         /* Remove old menu */
    InitCommItems();                    /* Re-do comm menu   */
    SetMenuStrip(mywindow,&menu[0]);    /* Re-display the menu */
    }

void setserbaud(baud, redomenu)
int baud;
LONG redomenu;
    {
    AbortIO(Read_Request);
    Write_Request->io_Baud = Read_Request->io_Baud = baud;
    setparams();
    p_baud = baud;
    if (redomenu) redocomm();
    }

void redoutil() {
    ClearMenuStrip(mywindow);
    InitUtilItems();
    SetMenuStrip(mywindow,&menu[0]);
    }

void handle_menupick(class, code)
ULONG class;
unsigned int code;
    {
    unsigned int menunum, itemnum, subnum;

    if (code == MENUNULL) return;

    menunum = MENUNUM( code );
    itemnum = ITEMNUM( code );
    subnum  = SUBNUM( code );
    switch( menunum ) {
	case 0:
	switch( itemnum ) {
	    case 0:
	    do_capture(NULL);
	    break;

	    case 1:
	    do_send(NULL);
	    break;

	    case 2:
	    if (p_parity > 0) {
		InfoMsg1Line("Parity setting prevents this");
		break;
		}
	    name[0] = '\000';
	    req("Xmodem Receive:",name,1);
	    multi_xfer(name,XMODEM_Read_File,0);
	    break;

	    case 3:
	    if (p_parity > 0) {
		InfoMsg1Line("Parity setting prevents this");
		break;
		}
	    name[0] = '\000';
	    req("Xmodem Send:",name,1);
	    multi_xfer(name,XMODEM_Send_File,1);
	    break;

	    case 4:
	    server = TRUE;
	    name[0] = '\000';
	    req("Kermit GET remote file(s):",name,1);
	    multi_xfer(name,dokreceive,0);
	    break;

	    case 5:
	    multi_xfer("",dokreceive,0);
	    break;

	    case 6:
	    server = TRUE;
	    name[0] = '\000';
	    req("Kermit Send local name:",name,1);
	    multi_xfer(name,doksend,1);
	    break;

	    case 7:
	    saybye();
	    break;
	    }
	break;

	case 1:
	switch( itemnum ) {
	    case 0:
	    switch( subnum ) {
		case 0:
		setserbaud(300, FALSE);
		break;

		case 1:
		setserbaud(1200, FALSE);
		break;

		case 2:
		setserbaud(2400, FALSE);
		break;

		case 3:
		setserbaud(4800, FALSE);
		break;

		case 4:
		setserbaud(9600, FALSE);
		break;
		}
	    break;

	    case 1:
	    /* Set  Parity */
	    p_parity = subnum;
	    break;

	    case 2:
	    /* set transfer mode */
	    if (subnum < 2) p_mode = subnum;
	    else {
		if (p_convert)	p_convert = 0;
		else		p_convert = 1;
		redocomm();
		}
	    break;
	    }
	break;

	case 2:
	if (!itemnum && !script_on) {
	    name[0] = '\000';
	    req("Script file name:",name,1);
	    script_start(name);
	    }
	if (itemnum && script_on) exit_script();
	break;

	case 3:
	switch( itemnum ) {
	    case 0:
	    sendbreak();
	    break;

	    case 1:
	    hangup();
	    break;

	    case 2:
	    strcpy(name,MyDir);
	    req("Directory:",name,1);
	    set_dir(name);
	    break;

	    case 3:
	    top = MINY; bot = MAXY; savx = MINX; savy = MINY;
	    curmode = FS_NORMAL; inesc = -1;
	    a[0] = 0; a[1] = 0; sa[0] = 0; sa[1] = 0;
	    redoutil();
	    emit(12);
	    break;

	    case 4:
	    if (p_echo) p_echo = 0;
	    else	p_echo = 1;
	    redoutil();
	    break;

	    case 5:
	    if (p_wrap) p_wrap = 0;
	    else        p_wrap = 1;
	    redoutil();
	    break;

	    case 6:
	    if (p_keyapp) p_keyapp = 0;
	    else          p_keyapp = 1;
	    redoutil();
	    break;

	    case 7:
	    if (p_curapp) p_curapp = 0;
	    else          p_curapp = 1;
	    redoutil();
	    break;

	    case 8:
	    swap_bs_del();
	    redoutil();
	    break;
	    }

	break;
	} /* end of switch ( menunum ) */
    }

SHAR_EOF
cat << \SHAR_EOF > vt100.h
/*********************************************************************
 *  a terminal program that has ascii and xmodem transfer capability
 *
 *	v2.7 870825 ACS - See README.
 *	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 (V2.7 ACS 870825) Terminal Window"

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

/*  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 4    /* total number of menu entries */

#define MAXGADSTR 80	/* Max size of prompts and inputs */

#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	NewWindow NewReqWindow;
extern struct	Screen *myscreen;
extern struct	Window *mywindow;
extern struct	Window *reqwindow;
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 int	reqwinup;
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();
extern void	ScrollInfoMsg(), InfoMsgNoScroll(), InfoMsg1Line(),
		InfoMsg2Line();

/* 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
cat << \SHAR_EOF > xmodem.c
/*************************************************************
 * vt100 terminal emulator - XMODEM protocol support
 *
 *	v2.7 870825 ACS - Make multi_xfer() non-recursive; on non-ESC in
 *			  readchar() re-do the main window's title. 
 *	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
 *	     860815 Steve Drew: readchar inproved with real timeouts
 *	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"

int enablexon = TRUE;

extern struct IntuiText MyTitle;

static unsigned long parity_settings[4] = {
    0x96696996,
    0x69969669,
    0x69969669,
    0x96696996 };

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

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

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

/**************************************************************/
/* send char and read char functions for the xmodem function */
/************************************************************/
void sendchar(ch)
int ch;
    {
    int doxon,i,j,k;

    doxon = enablexon;
    if (doxon) No_XON();
    switch (p_parity) {
	case 0:	/* no parity */
	rs_out[0] = ch & 0xFF;
	break;

	case 1: /* mark */
	rs_out[0] = (ch & 0x7F) | 0x80;
	break;

	case 2: /* space */
	rs_out[0] = ch & 0x7F;
	break;

	case 3:	/* even */
	case 4: /* odd  */
	i     = (ch >> 5) & 0x3;
	j     = ch & 0x1F;
	k     = ((parity_settings[i] >> j) & 0x1) << 7;
	if (p_parity == 3)			/* even parity */
	    rs_out[0] = (ch & 0x7F) | k;
	else					/* odd parity */
	    rs_out[0] = (ch & 0x7F) | (k ^ 0x80);
	}
    do {
	DoIO(Write_Request);
    } while(Write_Request->IOSer.io_Error != 0);
    if (doxon) Do_XON();
    }

/* send a break to the host */
void sendbreak() {
    AbortIO(Read_Request);
    Wait(1L << Read_Request->IOSer.io_Message.mn_ReplyPort->mp_SigBit);
    WaitIO(Read_Request);
    Read_Request->IOSer.io_Command = SDCMD_BREAK;
    DoIO(Read_Request);
    Read_Request->IOSer.io_Command = CMD_READ;
    SendIO(Read_Request);
    }

int readchar()
    {
    int rd,ch;
    ULONG class, waitmask;
    USHORT code;

    Timer.tr_time.tv_secs = ttime;
    Timer.tr_time.tv_micro = 0;
    SendIO((char *) &Timer.tr_node);

    rd = FALSE;
    waitmask = ((1L << Read_Request->IOSer.io_Message.mn_ReplyPort->mp_SigBit) |
		( 1L << mywindow->UserPort->mp_SigBit) |
		( 1L << Timer_Port->mp_SigBit));
    if(reqwinup)
	waitmask |= (1L << reqwindow->UserPort->mp_SigBit);
    while (rd == FALSE) {
	Wait(waitmask);
	if (CheckIO(Read_Request)) {
	    WaitIO(Read_Request);
	    ch=rs_in[0];
	    rd = TRUE;
	    SendIO(Read_Request);
	}
	if(reqwinup &&
	  (NewMessage=(struct IntuiMessage *)GetMsg(reqwindow->UserPort))) {
	    class = NewMessage->Class;
	    ReplyMsg(NewMessage);
	    if(class == NEWSIZE)
		ReqNewSize(reqwindow->Height, reqwindow->Width);
	}
	if (NewMessage=(struct IntuiMessage *)GetMsg(mywindow->UserPort)) {
	   class = NewMessage->Class;
	   code = NewMessage->Code;
	   ReplyMsg(NewMessage);
	   if ((class == RAWKEY) && (code == 69)) {
		 AbortIO((char *) &Timer);
		 Wait (1L << Timer_Port->mp_SigBit);
		 WaitIO((char *) &Timer.tr_node);
		 InfoMsg1Line("ERROR: User aborted transfer");
		 timeout = USERABORT;
		 return('\0');
	   }
	   PrintIText(mywindow->RPort, &MyTitle, 0L, 0L);
	   continue;
	}

	if (rd == FALSE && CheckIO(&Timer)) {
	    InfoMsg1Line("ERROR: Timeout waiting for character");
	    timeout = TIMEOUT;
	    return('\0');
	}
    } /* end while */
    AbortIO((char *) &Timer);
    Wait (1L << Timer_Port->mp_SigBit);
    WaitIO((char *) &Timer.tr_node);
    timeout = GOODREAD;
    return(ch & (p_parity == 0 ? 0xFF : 0x7F));
    }

void No_XON() {

    /* turn off XON/XOFF processing */
    enablexon = FALSE;
    Write_Request->io_SerFlags |= SERF_XDISABLED;
    Write_Request->IOSer.io_Command = SDCMD_SETPARAMS;
    DoIO(Write_Request);
    Write_Request->IOSer.io_Command = CMD_WRITE;
    }

void Do_XON() {
    /* turn on XON/XOFF processing */
    enablexon = TRUE;
    Write_Request->io_SerFlags &= ~SERF_XDISABLED;
    Write_Request->IOSer.io_Command = SDCMD_SETPARAMS;
    DoIO(Write_Request);
    Write_Request->IOSer.io_Command = CMD_WRITE;
    }

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

int XMODEM_Read_File(file)
char *file;
    {
    int firstchar, sectnum, sectcurr, sectcomp, errors, errorflag;
    unsigned int checksum, j, bufptr;
    char scrstr2[40];
    bytes_xferred = 0L;
    ttime = TTIME_SHORT;

    if ((fd = creat(file, 0)) < 0)
	{
	InfoMsg2Line("XMODEM Can't Open File:",file);
	return FALSE;
	}
    else
    InfoMsg1Line("XMODEM Receive, <esc> in VT100 window to abort");

    sectnum = errors = bufptr = 0;
    sendchar(NAK);
    firstchar = 0;
    No_XON();
    while (firstchar != EOT && errors != ERRORMAX)
	{
	errorflag = FALSE;

	do {                                    /* get sync char */
	    firstchar = readchar();
	    if (timeout != GOODREAD) {
		if (timeout == USERABORT || errors++ == ERRORMAX)
		    Do_XON();
		    return FALSE;
		}
	    } while (firstchar != SOH && firstchar != EOT);

	if  (firstchar == SOH)
	    {
	    sprintf(scrstr2,"Getting Block %4d...",sectnum);
	    InfoMsgNoScroll(scrstr2);
	    sectcurr = readchar();
	    if (timeout != GOODREAD) { Do_XON(); return FALSE; }
	    sectcomp = readchar();
	    if (timeout != GOODREAD) { Do_XON(); return FALSE; }
	    if ((sectcurr + sectcomp) == 255)
		{
		if (sectcurr == ((sectnum + 1) & 0xff))
		    {
		    checksum = 0;
		    for (j = bufptr; j < (bufptr + SECSIZ); j++)
			{
			bufr[j] = readchar();
			if (timeout != GOODREAD) { Do_XON(); return FALSE; }
			checksum = (checksum + bufr[j]) & 0xff;
			}
		    if (checksum == readchar() && timeout == GOODREAD)
			{
			errors = 0;
			sprintf(scrstr2,"Block %4d verified",sectnum);
			sectnum++;
			bufptr += SECSIZ;
			bytes_xferred += SECSIZ;
			InfoMsgNoScroll(scrstr2);
			if (bufptr == BufSize)
			    {
			    if (write(fd, bufr, BufSize-128) == EOF)
				{
				InfoMsg1Line("XMODEM: Error Writing File");
				Do_XON();
				return FALSE;
				}
			    bufptr = 128;
			    for (j = 0; j < 128; j++)
				bufr[j] = bufr[(BufSize-128)+j];
			    }
			sendchar(ACK);
			}
		    else
			{
			errorflag = TRUE;
			if (timeout == USERABORT) { Do_XON(); return FALSE; }
			}
		    }
		else
		    {
		    /* got a duplicate sector */
		    if (sectcurr == (sectnum & 0xff))
			{
			/* wait until we time out for 5secs */
			do {
			    readchar();
			    } while (timeout == GOODREAD);
			if (timeout == USERABORT) {
			    Do_XON();
			    return FALSE;
			    }
			InfoMsg1Line("XMODEM: Received Duplicate Sector");
			sendchar(ACK);
			}
		    else errorflag = TRUE;
		    }
		}
	    else errorflag = TRUE;
	    }
	if (errorflag == TRUE)
	    {
	    errors++;
	    InfoMsg1Line("XMODEM: Error");
	    sendchar(NAK);
	    }
	}        /* end while */
    if ((firstchar == EOT) && (errors < ERRORMAX))
	{
	sendchar(ACK);
	while (bufptr > 0 && (bufr[--bufptr] == 0x00 ||
			      bufr[bufptr]   == 0x1A)) ;
	write(fd, bufr, ++bufptr);
	close(fd);
	Do_XON();
	ScrollInfoMsg(1);
	return TRUE;
	}
    Do_XON();
    return FALSE;
    }

int XMODEM_Send_File(file)
char *file;
    {
    int sectnum, bytes_to_send, size, attempts, c;
    unsigned checksum, j, bufptr;
    char scrstr2[40];
    bytes_xferred = 0;
    ttime = TTIME_LONG;

    if ((fd = open(file, 0)) < 0) {
	InfoMsg1Line("XMODEM: Cannot Open Send File");
	return FALSE;
	}
    else
    InfoMsg1Line("XMODEM Send, <esc> from VT100 window to abort");
    attempts = 0;
    sectnum = 1;
    No_XON();
    /* wait for sync char */
    j=1;
    while (((c = readchar()) != NAK) && (j++ < ERRORMAX))
	if (timeout == USERABORT) { Do_XON(); return(FALSE); }
    if (j >= (ERRORMAX))
	{
	InfoMsg1Line("XMODEM: Receiver not sending NAKs");
	Do_XON();
	return FALSE;
	}

    while ((bytes_to_send = read(fd, bufr, BufSize)) &&
	    attempts != RETRYMAX)
	{
	if (bytes_to_send == EOF)
	    {
	    InfoMsg1Line("XMODEM: Error Reading File");
	    Do_XON();
	    return FALSE;
	    }

	bufptr = 0;
	while (bytes_to_send > 0 && attempts != RETRYMAX)
	    {
	    attempts = 0;
	    sprintf(scrstr2,"Sending block %4d",sectnum);
	    do {
		InfoMsgNoScroll(scrstr2);
		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);
		attempts++;
		c = readchar();
		if (timeout == USERABORT) {
		    InfoMsg1Line("XMODEM: ABORTED");
		    Do_XON();
		    return FALSE;
		    }
		} while ((c != ACK) && (attempts != RETRYMAX));
	    bufptr += size;
	    bytes_xferred += size;
	    sprintf(scrstr2,"Sent    block %4d",sectnum);
	    InfoMsgNoScroll(scrstr2);
	    sectnum++;
	    }
	}
    close(fd);
    if (attempts == RETRYMAX)
	{
	InfoMsg1Line("XMODEM: No Acknowledgment, ABORTING");
	Do_XON();
	return FALSE;
	}
    else
	{
	attempts = 0;
	do {
	    sendchar(EOT);
	    attempts++;
	    } while ((readchar() != ACK) &&
		     (attempts != RETRYMAX) &&
		     (timeout != USERABORT)) ;
	if (attempts == RETRYMAX)
	    InfoMsg1Line("XMODEM: No end of file");
	}
    Do_XON();
    ScrollInfoMsg(1);
    return TRUE;
    }

/* allow for multi file xfers separated by commas under
    kermit and XMODEM */

void multi_xfer(name,mode,do_send)
char *name;
int (*mode)();
int do_send;
    {
    int done = 0;
    int status;
    char *p, *name_start;

    timeout = USERABORT - 1;
    for(p=name_start=name; !done && timeout != USERABORT; name_start=++p)
	{
	if (*(name_start) == '$' && *(name_start+1) == '\0') {
	    saybye();
	    return;
	    }
	while(*p == ' ') p++;
	while(*p && *p != ',' && *p != ' ') p++;
	if (*p == '\0') {
	    done = TRUE;
	    multi = 0;
	}
	else
	    multi = 1;
	*p = '\0';

	status = ((*mode)(name_start, multi));
	if (status == FALSE) close(fd);
	}
    server = 0;
    multi = 0;
    }

SHAR_EOF