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

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

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# Xshar: Extended Shell Archiver.
# This is part  1 out of  3.
# This archive created: Fri Oct  2 13:14:34 1987
# By: Craig Norborg (Purdue University Computing Center)
#	Run the following text with /bin/sh to create:
#	makefile
#	script.c
#	tek.doc
#	tek.h
#	vt100.init
#	xmodem.c
cat << \SHAR_EOF > makefile
OBJS	= tek.o vt100.o window.o remote.o xmodem.o kermit.o \
		  init.o script.o expand.o

tek	: $(OBJS)
	ln -v -o tek $(OBJS) -lm -lc

tek.o	: tek.c vt100.h tek.h
		cc tek.c

vt100.o	: vt100.c vt100.h tek.h
		cc vt100.c

window.o	: window.c vt100.h tek.h
			cc window.c

remote.o	: remote.c vt100.h tek.h
			cc remote.c

xmodem.o	: xmodem.c vt100.h tek.h
			cc xmodem.c

kermit.o	: kermit.c vt100.h tek.h
			cc kermit.c

script.o	: script.c vt100.h tek.h
			cc script.c

init.o		: init.c vt100.h tek.h
			cc init.c

expand.o	: expand.c vt100.h tek.h
			cc expand.c
SHAR_EOF
cat << \SHAR_EOF > script.c
/*************************************************************
 * vt100 terminal emulator - Script file support
 *
 *	v2.65       NG  - added tek4014 emulation
 *	v2.6 870227 DBW - bug fixes for all the stuff in v2.5
 *	v2.5 870214 DBW - more additions (see readme file)
 *	v2.4 861214 DBW - lots of fixes/additions (see readme file)
 *	v2.3 861101 DBW - minor bug fixes
 *	v2.2 861012 DBW - more of the same
 *	v2.1 860915 DBW - new features (see README)
 *	     860901 ACS - Added 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();

/****************  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		 */

/********************** 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_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 bs to del	    */
    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 */
    };

/********************************************************************/
/* 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;
    {
    if (strlen(file) == 0 || *file == '#') return(0);
    if ((sf = fopen(file, "r")) == NULL) {
        req("Can't open script file",file,0);
        return(0);
	}
    script_on = TRUE;
    script_wait = FALSE;
    wait_string[0] = '\0';
    on_string[0] = '\0';
    on_match = FALSE;
    lbase = NULL;
    }

/* 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);
	    }
	}

	/* now search in the tek command list		*/
	if(exe_t_cmd(p,l) == 1)
		return(TRUE);

    if (doing_init) {
	puts("INIT - unknown command:");
	puts(p);
	}
    else req("Script - unknown command:",p,0);

    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);

	    /* 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) req("Script - label not found: ",golabel,0);
    exit_script();
    }

exit_script()
    {
    if (script_wait == WAIT_TIMER)      /* timer not done yet */
       AbortIO((char *) &Script_Timer); /* so abort it */
    req("Script - terminated","",0);    
    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();
    }

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 req("Script - invalid baud rate: ",rate,0);
	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 req("Script - invalid parity: ",par,0);
	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);
    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 req("Script - invalid transfer mode: ",tmode,0);
	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_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_bs_del);
    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 > tek.doc
This is a terminal emulation/communications program which has been
put together by Nick Giordano (9-87).  It does vt100 and tek4014/4010 
emulation. The majority of the code is the vt100(v2.6) public domain program 
by Dave Wecker, and his documentation comes at the end of this file.
The tek emulation is based on the tek4010 program by T. Whelan which I
obtained from one of the Fish disks.  My
only contributions have been relatively minor.  Some the changes I have made
are the following.

(1) The original tek4010 program was built on top of vt100(v2.0).  This
    version is built on what is now the latest version of vt100.
	It is also now relatively easy to put the tek emulation on top
	of new versions of vt100.

(2) The original tek4010 program had most of the options (such as
    graphics screen depth) hard coded in.  These are now options which
	can be selected via menus, or set on startup from data in the
	vt100.init file in the same manner as other vt100 options.

(3) Various error conditions (such as insufficient memory for the
    tek screen) are now handled more gracefully, without visits 
	from the guru.

(4) The current version now compiles under Manx 3.4a (patch level 3)
    with 16 bit integers, and should also compile under Lattice 
	(but I have not tried this yet).

This program normally behaves exactly like vt100(v2.6) until you
open the tek screen.  This is a custom screen which can be opened either
on start-up, or via menu selection.  The depth and resolution of the
tek screen are user selectable.  When the tek screen is open it normally
sits behind the vt100 screen.  However, when a graphics command is
received, the tek screen is automatically brought to the front and the
graphics commands are executed.  When the command to go back to text mode
is received, the tek screen is then pushed to the back, but the graphics
are still there.  One can then, if one wants, bring the tek screen back
to the front via menu selection, etc.  The graphics stays on that screen
until it is explicitly cleared, which can be via menu selection or
a command from the host computer.  

According to T. Whelan, the tek emulation should also do color
graphics, but I am not able to test this mode.  I have not made any
changes in the way colors are handled, so this part should work as
well as it did in the original tek4010 program.

As in T. Whelan's version, this emulator is also compatible with the
Selanar command codes, to mimic the behavior of a Selanar Hi-Rez 100
terminal.

I usually don't open the tek screen unless I plan to use the graphics mode,
since this screen eats up some memory.  I have found that the program
works reliably, ALTHOUGH IT IS INCOMPATIBLE WITH THE CLOCK PROGRAM
of M. Meyer.  I haven't tracked this bug down yet, but plan to work on
it in the near future.  In any case, this may indicate incompatibilities
with other programs of that type, so user beware.  The problem may be with
having a high priority running in the backround, but the tek program does
coexist with popcliII without any problems.  

I had not planned on releasing this program so soon, so a good bit of
debugging code and unnecessary code are still present.  I apologize for
the code, but it works for me and I make no guarantees.  However I would
greatly appreciate hearing about any bugs which you discover, and I will try
to fix them when I can.

Finally, let me say again that I have, in the spirit of public domain
programming, written relatively little of this code.  The credit should
really go to D. Wecker and T. Whelan.

This version has several tek options which can be set from the
initialization file (vt100.init).  These are listed below.

int	t_scale = 0; /* 0->1024x780	1->640x400 resolution	*/
int	t_on    = 0; /* 0 = no  1 = yes  come up with tek screen on */
int	t_depth = 1; /* depth of tek screen					*/
int	t_interlace = 1; /* interlace tek screen  0=no  1=yes	*/

KNOWN BUGS:

1) Does not work when M. Meyers clock program is running in the backround.
   In this case, some graphics commands are lost, resulting in garbage.

2) Any problems in vt100(v2.6) will also be found here.  I have not made
   any of the patches which have been suggested.

CHANGES in VT100(v2.6):

1) I have changed some of the menu selection keys 
   (i.e., right Amiga - something).  These are noted in the vt100
   documentation below.

2) There is now a quit menu selection (right Amiga - Q) which will terminate
   the program.

PLANS FOR THE FUTURE:

1) Add a new smaller font so as to be more compatible with the fonts found
   on the 4014.

2) Make the colors user selectable.

3) Fix any bugs which are reported.

I would greatly appreciate any suggestions for changes/improvements, as
well as bug reports.  

Nick Giordano
Physics Department
Purdue University
West Lafayette, IN 47907
(9-1-87)

***********************************************************************
***********************************************************************
The following are comments from T. Whelan's original version.
***********************************************************************
***********************************************************************
/* This module is a minimum extenal hooks tek 4010 emulation, the
 * function InitTek() must be called before any of the others, it
 * assumes that gfx, intuition are open. Tek() returns true if it
 * uses the input stream else false. It must be called before any 
 * character parsing or you could get into trouble. CloseTek() Frees
 * up all resources used by this module */

/* I had to invent a few commands for area fill reset screen, and
 * color setting. Any one who knows the correct commands please let me
 * know  the line drawing and color index selection are standard commands.
 * I have vax software to drive the 640x400 mode, and it works really well.
 * the 1024x780 mode is not quite as clear, but works ok.
 * The author of this software can be contacted as:
 * T.Whelan
 * Dept. of Physics & Astronomy
 * University of Iowa
 * Iowa City
 * IA 52244
 * and on span at IOWA::WHELAN

 * on the "to do" list, are graphic input mode and run time selection
 * of the screen resolution. */


**********************************************************************
**********************************************************************
The following is D. Wecker's original documentation.
**********************************************************************
**********************************************************************
This is the documentation file for the VT100 terminal emulator by Dave
Wecker (V2.6 DBW 870227). Comments/suggestions/bugs/problems/praise
should be sent to:

	Dave Wecker at	ENET:	COOKIE::WECKER
			ARPA:	wecker%cookie.dec.com@decwrl.dec.com
			USENET:	{decvax|decwrl}!cookie.dec.com!wecker
			SNAIL:	Dave Wecker
				115 Palm Springs Drive
				Colorado Springs, CO  80908

MANY pieces of code/suggestions have been sent in..

	thanks to all!

Program startup:
----------------
	1> vt100 [initfile]

		- At startup, the program will search for an initialization
		  file to execute. It will first look for the specified
		  "initfile", then VT100.INIT (in the current directory)
		  and finally S:VT100.INIT. The format for the init file
		  is described later in this document.

		- The init file controls the setting of initial defaults
		  and screen and macro definitions.

		- If none of the files (listed above) are found, the
		  built-in defaults (defined in VT100.C as variables,
		  beginning with "p_") are used.

		- All commands are either menu or script based. Scripts
		  are described below.

Menus (Commands in parenthesis are keyboard bindings: Right-Amiga-chr):
-----------------------------------------------------------------------
File 	  			- file transfers
	Ascii Capture		- Begin/end a script of the current session
	Ascii Send		- Type a file to the host
	Xmodem Receive	(A-V)	- Receive a file using XMODEM protocol
	(this is now A-<   N.G.)
	Xmodem Send	(A-^)	- Send    a file using XMODEM protocol
	(this is now A->   N.G.)
	Kermit Get	(A-G)	- Receive files from a host KERMIT SERVER
	Kermit Receive	(A-R)	- Receive files from a host KERMIT
	Kermit Send	(A-S)	- Send    files to   a host KERMIT [SERVER]
	Kermit Bye	(A-B)	- Terminate a host KERMIT SERVER
Comm Setup			- Setup communications
	Baud Rate		- Set the terminal baud rate
		300, 
		1200,	(A-L)
		2400,	(A-H)
		4800,
		9600
	Parity			- Type of parity
		NONE, 	(A-X)
		MARK,
		SPACE,
		EVEN,	(A-E)   (this is now A-+   N.G.)
		ODD	(A-O)       (this is now A--   N.G.)
	Xfer Mode
		Image	(A-I)	- Send files verbatim (for UNIX hosts or
				  binary files)
		Text	(A-T)	- Send CR LF as line terminator and strip
				  CR on received files (VMS text).
		(this is now A-7   N.G.)
		Convert		- Should KERMIT convert fnames to lower case
Script 	  			- Script commands
	Execute file		- Start up an asynchronous script file
	Abort Execution		- Terminate a script file
Utility   			- Utility commands
	Send Break	(A-.)	- send a break to the host
	Hang Up			- close line (not implemented yet)
	Change Dir	(A-D)	- change the local directory (for transfers)
	Clear Scrn		- clear the screen (initial state)
	Echo			- turn on/off half duplex mode
	Wrap		(A-W)	- turn on/off long line wrapping mode
	Num Key		(A-K)	- turn on/off numeric keypad mode
	App Cur		(A-C)	- turn on/off application cursor mode
	BS<->DEL	(A-Z)	- swap backspace and delete keys

Keypad mapping (in application keypad mode):
--------------------------------------------

		AMIGA		VT100		comments
		-------		-------		---------------------------
		0-9	==	0-9
		.	==	.
		ENTER	==	ENTER		(basically, flip the bottom
		-	==	,		 2 keys up to get a VT100)
		HELP	==	-		(only free key around)
		f1-f4	==	PF1-PF4		(or any rebinding you do)
		arrows	==	arrows

Note:	Right AMIGA key in conjunction with a period (".")
	will send a break to the host.

	CTRL in conjunction with an at-sign ("@") a two ("2") or a
	space (" ") will send a NULL to the host.

	CTRL in conjunction with a six  ("6") will send a CTRL-^
	CTRL in conjunction with a dash ("-") or question mark ("?")
		will send a CTRL-_ to the host.

Multi file Xfers:
-----------------
The VT100 emulator supports multiple file transfers. This is
specified by using a comma (",") between file names when using XMODEM
or KERMIT. (NOTE: host XMODEM's normally CANNOT support multiple file
transfers).

When specifying a file name to recieve by default the directory path
is stripped off of the filename when sent to the host but is kept for the
local file spec. eg:

        receive file: ram:file.txt,df1:newfile.bin,$

will ask the server for file.txt and put it in ram:, and get
newfile.bin and put it on df1: (see explanation of "$" below). If you
do a single file transfer you will get another prompt for the remote
name e.g.:

        receive file: ram:file.txt
        remote file name [file.txt]:  userdisk1:wantfile.txt

The same rules apply to sending multiple files therefore if you are
doing multi file transfers make sure the host server is connected to
the desired directory.

In addition KERMIT supports wildcards:
    * = any number of characters
    ? = any single character
Examples:
	send:	*.c,*.h,*.doc
	get:	*.c,*.h,$

KERMIT receive is now smart enough to use the host filename so no
filename needs to be specified on the AMIGA's side (see the CONVERT option).

Initialization and Script file operation:
-----------------------------------------
An initialization file (as described in the "Program Startup" section)
may contain any of the commands shown below that have the word INIT in
their description below. Commands that are available from scripts have
the word SCRIPT in the descriptions below. All commands may be abbreviated
to 3 letters and are case insensitive.

The script file can be invoked by selecting 'execute file' from the
script menu. At any time you can abort the script file by selecting
'Abort Execution'. You may also invoke a script from a function key if
the first character of the function key definition is the KEYSCRIPT
character (e.g., define F5 as "~df1:foo.script").

During the time script file is running the terminal emulation is still
active and you may type simulataneous to the script file. This may be
desired if your script file is WAITing for a string or is DELAYing for
a period of time etc.

Initialization and Script file Commands:
----------------------------------------
#	Commented line					(INIT,SCRIPT)
   Format:
	# This line is a comment
------------------------------------------------------------
APPCUR	Set the application cursor mode			(INIT,SCRIPT)
   Format:
	APPCUR	ON/OFF or YES/NO
------------------------------------------------------------
ASCII_SEND Send an ascii file to the host.		(SCRIPT)
   Format:
	(same format as CAPTURE)
------------------------------------------------------------
BACKGROUND Define a background color			(INIT)
   Format:
	BACKGROUND hex		three digit hex number
   Example:
	BACKGROUND F00		bright red background
------------------------------------------------------------
BAUD 	Set baud rate					(INIT,SCRIPT)
   Format:
	BAUD rate		Sets the baud rate for send/receive
   Example:
	BAUD 2400		Sets the baud rate at 2400 baud
------------------------------------------------------------
BEEP	Beep at the console				(SCRIPT)
   Format:
	BEEP
------------------------------------------------------------
BOLD 	Define a color for bold				(INIT)
   Format:
	(same as BACKGROUND)
------------------------------------------------------------
BREAK	Set the break time (for an SB command)		(INIT,SCRIPT)
   Format:
	BREAK value		Value is in micro-seconds
   Example:
	BREAK 750000
------------------------------------------------------------
BUFFER 	Set transmission buffer size			(INIT)
   Format:
	BUFFER n		Number of bytes to buffer
   Example:
	BUFFER 512
------------------------------------------------------------
CAPTURE	To start/stop ascii file capture.		(SCRIPT)
   Format:
	CAPTURE	file		Start ascii capturing
	CAPTURE			End ascii capturing
------------------------------------------------------------
CD 	To change the local directory			(SCRIPT)
   Format:
	CD	newdir		set a new directory for file transfers
   Example:
	CD	DF1:foo/bar	set the directory as specified
------------------------------------------------------------
CONVERT	Tell KERMIT whether or not to convert filenames	(INIT,SCRIPT)
   Format:
	CONVERT	ON/OFF or YES/NO
   Example:
	CONVERT	ON		Filenames will be down cased
------------------------------------------------------------
CURSOR 	Define a color for the cursor			(INIT)
   Format:
	(same as BACKGROUND)
------------------------------------------------------------
DELAY 	Suspends script file for a specified time	(SCRIPT)
   Format:        
        DELAY 	n		Suspends execution for n seconds
   Example:
	DELAY	2		Suspends for 2 seconds
------------------------------------------------------------
DEPTH 	Define the depth of the window/screen		(INIT)
   Format:
	DEPTH n		Number of planes in window/screen
   Example:
	DEPTH 1		Minimum depth
	DEPTH 2		Same as Workbench
------------------------------------------------------------
ECHO	Turn on/off local echo				(INIT,SCRIPT)
   Format:
	ECHO	ON/OFF or YES/NO
   Example:
	ECHO	ON		Half duplex mode
------------------------------------------------------------
EXIT	Ends execution of the current script file.	(INIT,SCRIPT)
   Format:
	EXIT			Exit the current script/init file
	EXIT VT100		Exit vt100 program (from SCRIPT only)
	EXIT newscript		Exit this file and start up newscript
   Example:
	EXIT DF1:FOO.BAR	Exit the current file and start FOO.BAR
------------------------------------------------------------
F	Define a function key				(INIT,SCRIPT)
   Format:
	F n string		Define Function key n to be string
   Example:				(see SEND for string format)
	F 1 "dir^M"		Define F1 is the string dir<cr>
	F 11 "help"		Define Shifted F1 as the string help
	F 20 ^C			Define Shifted F10 as a control-C
------------------------------------------------------------
FOREGROUND Define a color for the foreground		(INIT)
   Format:
	(same as BACKGROUND)
------------------------------------------------------------
GOTO	Jumps to a different part of the script file.	(SCRIPT)
   Format:
	GOTO label		Jumps to a line beginning with label:
				Jumps may be forward or backward.
   Example:
	FOO:			Sets up a label
	...
	GOTO FOO		Jumps to FOO
------------------------------------------------------------
INTERLACE Turn on/off interlace				(INIT)
   Format:
	INTERLACE ON/OFF or YES/NO
   Example:
	INTERLACE ON		Use interlacing
------------------------------------------------------------
KB  	Send a BYE packet to a host KERMIT server.	(SCRIPT)
   Format:
	KB 			Shut down server.
------------------------------------------------------------
KEYSCRIPT Define a new keyscript character		(INIT,SCRIPT)
   Format:
	KEYSCRIPT hex		New character in hex
   Example:
	KEYSCRIPT 7E		Use "~" as the new character
------------------------------------------------------------
KG  	Gets files from host.				(SCRIPT)
   Format:
	(same format as KS)	 Get from server
------------------------------------------------------------
KR  	Receives a file from kermit host.		(SCRIPT)
   Format:
	(same format as KS)	 Not from a server
------------------------------------------------------------
KS  	Sends files via kermit to the host.		(SCRIPT)
   Format:
	KS file			Send one file
	KS file1,file2,...	Send multiple files
	KS file1,file2,...,$	Send multiple files and shut down server
   Example:
	KS foo.bar		sends foo.bar (note no quoting is used)
	KS foo1,foo2,foo3	sends three files
	KS foo1,foo2,foo3,$	sends three files and shuts down server
------------------------------------------------------------
LINES	Define number of lines in the window		(INIT)
   Format:
	LINES n
   Example:
	LINES 24		Maximum for non-interlace
	LINES 48		Maximum for interlaced
------------------------------------------------------------
MODE	Set a transfer mode for KERMIT to use		(INIT,SCRIPT)
   Format:
	MODE type		type of transfers to perform
   Example:
	MODE IMAGE		image mode transfers
	MODE CRLF		<CR><LF> text transfers (VMS Kermit).
------------------------------------------------------------
NUMKEY	Numeric keypad mode				(INIT,SCRIPT)
   Format:
	NUMKEY	ON/OFF or YES/NO
   Example:
	NUMKEY	ON		Keypad is pure numbers
------------------------------------------------------------
ON	Peforms a command every time string is received	(SCRIPT)
   Format:
        ON      "string"  cmd	Execute cmd when string is received.
				Only one ON string may be installed at a
				time.

  				If cmd is a GOTO and we were previously
				WAITing for a string the WAIT is aborted and
				execution resumes at the new label.

              			If cmd is not SEND and we were previously
				DELAYing, then the DELAY is aborted and the
				cmd is executed, followed by the next command
				after the DELAY.

				If cmd is a SEND and we were previously
				DELAYing, then the DELAY is continued.
   Example:
        ON  "LOSS CARRIER" GOTO RESTART
				If modem drops carrier, try to redial
        ON  "--more--" SEND " "
				Send a space every time --more-- is received
------------------------------------------------------------
PARITY	Sets the parity					(INIT,SCRIPT)
   Format:
	PARITY	type		Set the parity type
   Example:
	PARITY	NONE		no parity
	PARITY	MARK		mark parity
	PARITY	SPACE		space parity
	PARITY	ODD		odd parity
	PARITY	EVEN		even parity
------------------------------------------------------------
SB	Sends a break character to the host		(SCRIPT)
   Format:			Note that any pending character to send
	SB				is aborted by this call
------------------------------------------------------------
SCREEN	Define the screen type				(INIT)
   Format:
	SCREEN type		type of screen to use
   Example:
	SCREEN WORKBENCH	use the workbench screen
	SCREEN CUSTOM		use a custom screen
------------------------------------------------------------
SEND 	Sends a string or character to the host.	(SCRIPT)
   Format:
	SEND    "string"	Sends a string to the host. Beginning and
				ending double quotes (") are required. A
				carat (^) may be used to send control chars.
				Two carats transmits a carat character.
        SEND    chr           	Sends a single character.
        SEND    ^chr   	    	Sends a single control character. The chr
				is NOT case sensitve
   Example:
	SEND	"mail"		Send the string mail
	SEND    "dir^M"		Send the string dir followed by a <CR>
	SEND	a		Send the letter a
	SEND	^C		Send a control C
	SEND	"abc^^def"	Send the string abc^def
	SEND	^^		Send a control-uparrow
	SEND	"		Send the '"' character
------------------------------------------------------------
SWAP 	Swap the meanings of backspace and delete keys	(INIT,SCRIPT)
   Format:
	SWAP ON/OFF or YES/NO
   Example:
	SWAP NO		Use standard definitions
------------------------------------------------------------
VOLUME	Set the BELL volume				(INIT)
   Format:
	VOLUME n
   Example:
	VOLUME 0		Use a visual bell
	VOLUME 64		Use a loud audible bell
------------------------------------------------------------
WAIT 	Suspends until a certain string is received.	(SCRIPT)
   Format:
	WAIT	"string"	Same rules for string as SEND
	WAIT			Enter an endless wait. Usually used after
				some "ON" commands have been set up. Can
				still be aborted via the script menu.
   Example:
        WAIT    "User:"    	Waits for the string User:
------------------------------------------------------------
WBCOLORS Force usage of workbench colors		(INIT)
   Format:
	WBCOLORS ON/OFF or YES/NO
   Example:
	WBCOLORS YES		Workbebch colors will be used for all
------------------------------------------------------------
WRAP	Set long line wrapping				(INIT,SCRIPT)
   Format:
	WRAP	ON/OFF or YES/NO
   Example:
	WRAP	ON		Long lines will wrap
------------------------------------------------------------
XR  	Receives a file via XMODEM.			(SCRIPT)
   Format:
	(same format as KS)
------------------------------------------------------------
XS  	Sends a file via XMODEM.			(SCRIPT)
   Format:
	(same format as KS)
------------------------------------------------------------


----------------------------
Initialization file example:
----------------------------

#####################################################################
#
#	VT100 sample initialization file
#	v2.6 870222 DBW	- Dave Wecker standard defaults
#
# Hash mark at the beginning of a line denotes a comment.
# White space (space(s) or tab(s)) delimit fields.
# Case ignored except for function key bindings.
#
# All items in this file overide variables of the same name in VT100.C
# (all variables in vt100.c have a "p_" prepended to them)
#
#####################################################################
#
APPCUR		ON		# Application keypad mode is being used
BACKGROUND	000		# Colors are in hex RGB from 000 to FFF
BAUD		2400		# Anything after required fields is ignored
BOLD		a00		# Color for bold highlighting (in custom)
BREAK		750000		# Break time in micro-seconds
BUFFER		512		# 512 <= Input buffer size <= 2048
CONVERT		ON		# KERMIT should downcase host names
CURSOR		00a		# Color for cursor (in custom screen)
DEPTH		1		# number of bit planes to use (1 or 2)
ECHO		OFF		# Full duplex mode in use
FOREGROUND	950		# Colors are only used on the custom screen
INTERLACE	ON		# ON for CUSTOM or interlaced workbench
KEYSCRIPT	7E		# Hex value for script introducer
LINES		48		# normal <= 24 interlaced <= 48
MODE		CRLF		# IMAGE or CRLF (for KERMIT transfers)
NUMKEY		ON		# The keypad should be numeric
PARITY		NONE		# NONE (= 8 bit), MARK, SPACE, ODD or EVEN
SCREEN		CUSTOM		# may be CUSTOM or WORKBENCH
SWAP		OFF		# Don't Swap the Back-space and Delete keys
VOLUME		64		# Beep Volume (0 = Visual Beep)
WBCOLORS	YES		# ignore custom colors and use defaults
WRAP		OFF		# Auto wrap ON or OFF
#
# Function bindings (strings to type when any of F1 - F10 are pressed)
#	f <num>		= function key
#	f <num>+10	= shifted function key
#
# The string specified must be the same format as the SEND command:
#	^	= control next character
#	^^	= up arrow
#
# Sample control characters:
#	^[	= escape	^M	= carriage return
#	^J	= line feed	^L	= form feed
#
# If the first character of the string is a script introducer
# (KEYSCRIPT) then the string is interpreted as a script filename
# to be executed when the key is pressed.
#
# Examples of bindings:
#
f 1	"^[OP"			# f1-f4 = PF1 - PF4 on a VT100
f 2	"^[OQ"
f 3	"^[OR"
f 4	"^[OS"
#
# f5,6,7 = scripts to execute (assuming that KEYSCRIPT = '~' = 0x7E)
#
f 5	"~df1:vt100_source/dialwork.script"
f 6	"~df1:vt100_source/sendvt100.script"
f 7	"~df1:vt100_source/getpics.script"
#
f 8	"MAIL^M"		# Reads my mail (note embedded <CR>)
f 9	"NOTE^M"		# Reads conferences
f 11	"$2400!"		# dials the phone to work
f 12	"$bbs1!"		# dials the phone to billboard 1
f 13	"$bbs2!"		# dials the phone to billboard 2
f 14	"$bbs3!"		# dials the phone to billboard 3
#
# all done with init, now execute script as startup sequence
#
exit df1:vt100_source/dialwork.script

--------------------
Script file example:
--------------------

###################################################################
# Script to dial work (dialwork.script)
#	v2.6	870222	DBW
###################################################################
#
# Make sure that we have all the parameters we want
#
	DELAY	2
	BAUD	2400
	PARITY	NONE
	MODE	CRLF
	BREAK	750000
	SB
#
# First get the modem's attention:
#
Start:
	DELAY 1
	ON "Ready" GOTO Dial
	SEND ^B
	DELAY 2
	GOTO Start
#
# Now dial the 2400 baud line to work:
#
Dial:
	ON "Attached" GOTO Login
	SEND "$2400!"
	DELAY 30
	GOTO Start
#
# We got attached, so keep hitting return until the Gandalf terminal
# handler wakes up:
#
Login:
	ON "enter" GOTO Gandalf
	DELAY 1
	SEND ^M
	GOTO Login
#
# Now connect from the Gandalf to the terminal server (ts2):
# (when it asks for a password I need to type the password 
# manually here)
#
Gandalf:
	DELAY 2
	SEND "ts2^M"
	WAIT "class start"
#
# Keep sending <CR>'s until the LAT prompts for a username:
#
WaitLat:
	DELAY 2
	ON "username>" GOTO Lat
	SEND ^M
	GOTO WaitLat
#
# Tell the LAT that it's me, and connect to the "cookie cluster"
# (my host systems). Tell the cluster my user name.
# (when it asks for a password I need to type the password
# manually here)
#
Lat:
	SEND "wecker^M"
	DELAY 1
	SEND "connect cookie^M"
	WAIT "Username:"
	SEND "WECKER^M"
	WAIT "at home"
	SEND "^M^Mn^M"
#
# Got through all the LOGIN garbage, so let's do some work.
#
	WAIT "$ "
#
# All done so stop:
#
	EXIT

SHAR_EOF
cat << \SHAR_EOF > tek.h
/*********************************************************************
 *  a terminal program that has ascii and xmodem transfer capability
 *
 *	v2.65		NG  - tek4014 emulation added
 *	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
 ********************************************************************/

/*********************** tek defaults *******************************/
extern int t_scale; /* 0->1024x780	1->640x400 resolution		*/
extern int t_on; /* 0 = no  1 = yes  come up with tek screen on */
extern int t_depth; /* depth of tek screen						*/
extern int t_interlace; /* interlace tek screen  0=no  1=yes		*/

extern int Tek_screen_open;
extern int TekMode;
extern int Tek();
extern int OpenTek();
extern int CloseTek();
extern int InitTekDev();
extern struct Window *TekWindow;
extern void InitTekItems();
extern void InitTekMenu();
extern void t_cmd_scale();
extern void t_cmd_depth();
extern void t_cmd_on();
extern void t_cmd_interlace();
extern int exe_t_cmd();

#define TekParamsMax 3
#define TekScaleMax 2
#define TekDepthMax 4
#define TekInterlaceMax 2
#define TekScreenMax 5
#define TekSelectMax 2
SHAR_EOF
cat << \SHAR_EOF > vt100.init

#####################################################################
#
#	VT100 sample initialization file
#	v2.3 861101 DBW	- Dave Wecker standard defaults
#	compatible with v2.6
#
#   also includes tek initializations
#   tek version 2.65 - Nick Giordano (9-87)
#
# Hash mark at the beginning of a line denotes a comment.
# White space (space(s) or tab(s)) delimit fields.
# Case ignored except for function key bindings.
#
# All items in this file overide variables of the same name in VT100.H
# (all variables in vt100.h have a "p_" prepended to them)
#
# (tek variables have a "t_" prepended)
#
#####################################################################
#
BAUD		1200		# Anything after required fields is ignored
SCREEN		WORKBENCH		# may be CUSTOM or WORKBENCH
INTERLACE	OFF		# ON for CUSTOM or interlaced workbench
DEPTH		1		# number of bit planes to use (1 or 2)
WBCOLORS	YES		# ignore custom colors and use defaults
FOREGROUND	950		# Colors are only used on the custom screen
BACKGROUND	000		# Colors are in hex RGB from 000 to FFF
BOLD		a00		# Color for bold highlighting (in custom)
CURSOR		00a		# Color for cursor (in custom screen)
LINES		24		# normal <= 24 interlaced <= 48
MODE		CRLF		# IMAGE or CRLF (for KERMIT transfers)
BUFFER		512		# 512 <= Input buffer size <= 2048
PARITY		NONE		# NONE (= 8 bit), MARK, SPACE, ODD or EVEN
BREAK		750000		# Length for break key in microseconds
VOLUME		64		# Beep Volume (0 = Visual Beep)
WRAP		OFF		# Auto wrap ON or OFF
KEYSCRIPT	7E		# Hex value for script introducer
TSCREEN     1       # tek screen resolution  0=1024x780 (default)   1=640x400
TON     	0		# 0=tek_screen off (default)  1=on
TINT		1		# 0=tek screen interlace no   1=yes (default)
TDEPTH		1		# tek screen depth (default)
#
# Function bindings (strings to type when any of F1 - F10 are pressed)
#	f<num>	= function key
#	F<num>	= shifted function key
#
# The string specified must be delimited and uses one special char:
#	^	= control next character
#	^^	= up arrow
#
# Sample control characters:
#	^[	= escape	^M	= carriage return
#	^J	= line feed	^L	= form feed
#
# If the first character of the string is a script introducer
# (KEYSCRIPT) then the string is interpreted as a script filename
# to be executed when the key is pressed.
#
# Examples of bindings:
#
#	f1	"^[OP"			# f1-f4 = PF1 - PF4 on a VT100
#	f2	"^[OQ"
#	f3	"^[OR"
#	f4	"^[OS"
#
# f5,6,7 = scripts to execute (assuming that KEYSCRIPT = '~' = 0x7E)
#
#	f5	"~df1:vt100_source/dialwork.script"
#	f6	"~df1:vt100_source/sendvt100.script"
#	f7	"~df1:vt100_source/getpics.script"
#
#	f8	"MAIL^M"		# Reads my mail (note embedded <CR>)
#	f9	"NOTE^M"		# Reads conferences
#	F1	"$2400!"		# dials the phone to work
#	F2	"$bbs1!"		# dials the phone to billboard 1
#	F3	"$bbs2!"		# dials the phone to billboard 2
#	F4	"$bbs3!"		# dials the phone to billboard 3
#
# all done with init, now execute script as startup sequence
#
SHAR_EOF
cat << \SHAR_EOF > xmodem.c
/*************************************************************
 * vt100 terminal emulator - XMODEM protocol support
 *
 *	v2.6 870227 DBW - bug fixes for all the stuff in v2.5
 *	v2.5 870214 DBW - more additions (see readme file)
 *	v2.4 861214 DBW - lots of fixes/additions (see readme file)
 *	v2.3 861101 DBW - minor bug fixes
 *	v2.2 861012 DBW - more of the same
 *	v2.1 860915 DBW - new features (see README)
 *	     860901 ACS - Added 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;

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);
	}
    DoIO(Write_Request);
    if (doxon) Do_XON();
    }

/* send a break to the host */
void sendbreak() {
    AbortIO(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;

    Timer.tr_time.tv_secs = ttime;
    Timer.tr_time.tv_micro = 0;
    SendIO((char *) &Timer.tr_node);
    
    rd = FALSE;
    while (rd == FALSE)  
        {	
	Wait((1L << Read_Request->IOSer.io_Message.mn_ReplyPort->mp_SigBit) |
            ( 1L << mywindow->UserPort->mp_SigBit) |
            ( 1L << Timer_Port->mp_SigBit));
	if (CheckIO(Read_Request))
            {
	    WaitIO(Read_Request);
	    ch=rs_in[0];
	    rd = TRUE;
	    SendIO(Read_Request);
	    }
	if (NewMessage=(struct IntuiMessage *)GetMsg(mywindow->UserPort)) {
	   if ((NewMessage->Class == RAWKEY) && (NewMessage->Code == 69))
	         {
                 AbortIO((char *) &Timer);
                 Wait (1L << Timer_Port->mp_SigBit);
	         req("ERROR:","User aborted transfer",0);
	         timeout = USERABORT;
                 return('\0');
	         }
            continue;
            }
        if (rd == FALSE && CheckIO(&Timer)) {
            req("ERROR","Timeout waiting for character",0);
            timeout = TIMEOUT;
            return('\0');
            }
	}     /* end while */
    AbortIO((char *) &Timer);
    Wait (1L << Timer_Port->mp_SigBit);
    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 scrstr[40],scrstr2[40];
    bytes_xferred = 0L;
    ttime = TTIME_SHORT;

    if ((fd = creat(file, 0)) < 0)
	{
	req("XMODEM Can't Open File:",file,0);
	return FALSE;
	}
    else
    strcpy(scrstr,"XMODEM Receive, <esc> to abort");
    req(scrstr,"",0);

    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);
	    req(scrstr,scrstr2,0);
	    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;
			req(scrstr,scrstr2,0);
			if (bufptr == BufSize)
			    {
			    if (write(fd, bufr, BufSize-128) == EOF)
				{
				req(scrstr,"Error Writing File",0);
				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;
			    }
			req(scrstr,"Received Duplicate Sector",0);
			sendchar(ACK);
			}
		    else errorflag = TRUE;
    		    }
		}
	    else errorflag = TRUE;
	    }
	if (errorflag == TRUE)
	    {
	    errors++;
	    req(scrstr,"Error",0);
	    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();
	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 scrstr[40],scrstr2[40];
    bytes_xferred = 0;
    ttime = TTIME_LONG;

    if ((fd = open(file, 0)) < 0) {
	req("XMODEM","Cannot Open Send File",0);
	return FALSE;
	}
    else
    strcpy(scrstr,"XMODEM Send, <esc> to abort");
    req(scrstr,"",0);
    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))
	{
	req(scrstr,"Receiver not sending NAKs",0);
	Do_XON();
	return FALSE;
	}

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

	bufptr = 0;
	while (bytes_to_send > 0 && attempts != RETRYMAX)
	    {
	    attempts = 0;
	    sprintf(scrstr2,"Sending block %4d",sectnum);
	    do {
		req(scrstr,scrstr2,0);
		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) {
		    req(scrstr,"ABORTED",0);
		    Do_XON();
		    return FALSE;
		    }
		} while ((c != ACK) && (attempts != RETRYMAX));
	    bufptr += size;
	    bytes_xferred += size;
	    sprintf(scrstr2,"Sent block %4d",sectnum);
	    req(scrstr,scrstr2,0);
	    sectnum++;
	    }
	}
    close(fd);
    if (attempts == RETRYMAX)
	{
	req(scrstr,"No Acknowledgment, ABORTING",0);
	Do_XON();
	return FALSE;
	}
    else
	{
	attempts = 0;
	do {
	    sendchar(EOT);
	    attempts++;
	    } while ((readchar() != ACK) &&
		     (attempts != RETRYMAX) &&
		     (timeout != USERABORT)) ;
	if (attempts == RETRYMAX)
	    req(scrstr,"NO END OF FILE",0);
	}
    Do_XON();
    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;
    
    if (name[0] == '$' && name[1] == '\0') {
	saybye();
	return;
	}
    p = name;
    while(*p == ' ') p++;
    while(*p && *p != ',' && *p != ' ') p++;
    if (*p == '\0')   done = TRUE;
    else	      multi = 1;
    *p = '\0';

    status = ((*mode)(name, multi));
    if (status == FALSE) close(fd);
    if (!done && timeout != USERABORT) multi_xfer(++p, mode, do_send);
    else emit('\n');
    server = 0;
    multi = 0;
    }

SHAR_EOF