[net.sources] Tvi emulator for IBM PC

ctk@ecsvax.UUCP (04/14/84)

: Run this shell script with "sh" not "csh"
PATH=:/bin:/usr/bin:/usr/ucb
export PATH
all=FALSE
if [ $1x = -ax ]; then
	all=TRUE
fi
/bin/echo 'Extracting term.doc'
sed 's/^X//' <<'//go.sysin dd *' >term.doc
This file comtains a shell script that generates files to create a terminal
emulator to compile under CI-C86. The program does a 70% job of emulating
a tvi-920c. Features left out include block mode and remote control of tabs.
The emulation is good enough to work with vi using the tvi termcap entry.
	The program is based on an interrupt handler written by R.F.Starr
that was posted to net.sources a few months ago.
	The program has been designed to work with the systems that I
use. These include two unix vaxes and an IBM 4341 running VM/370 with
the SIMTERM full screen program. For those out there who use this on
the NCSU local system you'll be able to do most of your favorite things
by selecting the televideo 920 item on the simterm menu (#3).
	To create the program you must modify the $main program in the
CI library to allow the interrupt program to work. You must also compile the
the programs interinit and interserv in the CI library (I'm talking about
version 1.33d here. I was one of those who decided to wait for version
2.1 for my free update and am still waiting.) You must assemble the program
com_set.asm and (if you still have 1.33d) convert it to .o format with the
cvtobj program on your CI disks.
	The files the shell script will generate are
	1. term.doc -- What you're reading now.
	2. term.c
	3. komm.c  -- mostly the work of R.F. Starr (!shell!starr)
	4. k2.c
	5. k3.c
	6. k4.c
	7. funkey.c
	8. help.c   -- online help
	9. updn.c   -- upload and download of ascii files.Read the documentation
		       before using. It might also help to read and modify
		       the code to your own needs.
	10. com_set.asm
	11. commio.h
   There are not a lot of comments in the code since I don't have the time
for neatness. I had to do some hacking to get XON and XOFF to transmit
properly. The program sends break nicely.
	The program writes to screen memory for the insert character part
of the terminal emulation and for the little clock in the first screen.
Hence you must either have the ibm monochrome card of be willing to fix
this up. I use the DOS 2.0 Ansi.sys device driver and this must be insatlled.

 (IBM, 4341, VM/370, UNIX, DOS, SIMTERM, NCSU, and anything else I forgot
are trademarks of the obvious folks.)

			 How to use this program.
	When you type term the file term.exe executes and the opening screen
asks you to select between cms and unix. If you type anyting but the number 1
unix will be selected. Note that at this point the seconds will tick off on the
time line at the top of the screen; this is a silly feature but I like it.
If you selected unix the local echo will be off and the assumption is that
the editor prompt is ':' (for uploading). If you select cms the local echo is
on and the editor prompt is XON. The uploading feature only works with remote
echo off (stty -echo) and this must be done by you before uploading.
	Uploading is activated by pressing F4 or alt+u. In either case you
are asked on the status line (line 25) the name of the file on your machine.
You must be in input mode before you begin this. When EOF is reached the
bell will sound.
	Downloading is activated in two ways. Pressing F3 opens a file
on your c: drive (my ram disk, you may want to change this) named
buff.trm. Anything that comes on the screen is put in this file untill
a function key is pressed. Pressing alt+d allows you to give the name of
the target file. (Note by alt+d I mean press alt and d at the same time.)
	The other keys are described in the file help.c. The end key and
F1 both send break. I like to have both left and right handed break keys.
This program is intended for fairly knowledgable people. I left a lot of
user friendly features out (like dialing the phone for you).
	 Finally, the baud rate is set at only one place for 1200. The code
can be changed at this place only to get 300. I have not tried it at any speed
faster than 1200.
	I hearby place this in the public domain. If you add any features
to the program please mail me a copy of the code. I am presently adding
some utilities that I got from the netnews to the code and when I get my
compiler update I will add one of the execl() programs that have been
floating around.
				Enjoy,
				C.T. Kelley
				Dept. of Mathematics
				N.C. State University, box 8205
				Raleigh, N.C. 27695-8205
				!decvax!mcnc!ecsvax!ctk
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 term.doc
	/bin/echo -n '	'; /bin/ls -ld term.doc
fi
/bin/echo 'Extracting term.c'
sed 's/^X//' <<'//go.sysin dd *' >term.c
#include "commio.h"
char line[4097];
main()
{
	int c,i;
	menu();
start:
	if(xfread(line)) comprt(line);
	if((c=inkey())>=0) outchar(c,1);
	goto start;
}
int unix=0;
menu()
{
	int i,c;
	extern int cms,hafdup;
stt:	cls();
	prdate();
	xrtime(0,40);
	locate(3,20);
	printf("Terminal Types -- Choose Number");
	locate(10,30);
	printf("1.   cms");
	locate(11,30);
	printf("2.   unix");
	locate(12,0);
	cms=0;
	unix=0;
	i=menkey();
	if(i=='1') {
		cms=1;
		hafdup=1;
		printf("\n cms -- ");
	}
	if(i!='1') {
		printf("\n unix -- ");
		hafdup=0;
		unix=1;
	}
	printf("Make connection and press any key to start.\n");
	while((c=inkey()) == -2) xrtime(0,40);
	xopen("COM1:",1200,'e',7,1);
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 term.c
	/bin/echo -n '	'; /bin/ls -ld term.c
fi
/bin/echo 'Extracting komm.c'
sed 's/^X//' <<'//go.sysin dd *' >komm.c
X/* Most of this by R.F. Starr  */
#include "commio.h"
#define BLTG (bel ? BELL:DIE)
static int bel=1;
char c;
int kk;
struct regval
{
	unsigned int ax,bx,cx,dx,si,di,ds,es;
}
srv,rrv;
static int rs_vec = 0x14;  /* RS232_IO in BIOS */
unsigned char combuf[BUFSIZE];
int dummy;
static int cptr = 0;
static int head = 0;


X/* ***************************************************************** */
X/* ****       \rs232 communications interface to BIOS		**** */
X/* ***************************************************************** */


int_com()    /* Communications interrupt service routine */
{
	unsigned char inportb(),cbuf;
	unsigned int lsr_data;

	/* Check lsb of lsr... if 0, no data is available */
	lsr_data = inportb (0x3fd);
	if ( (lsr_data & 0x0001) == 0 )
	{
		outportb (0x3fc,0xb);  /* Reset MCR */
		outportb (0x20,0x20);  /* Send EOI to 8259 */
		return;
	}

	/* Data ready... get from com device */
	cbuf = inportb (0x3f8);  /* Read RBR for character */
	if (cptr >= BUFSIZE) cptr = 0;

	combuf[cptr++] = cbuf;

	outportb (0x3fc,0xb);	/* Reset MCR */
	outportb (0x20,0x20);	/* Send EOI to 8259 */
	return;
}


X/* Routine to set up the RS232 interface ( baud rate, #data bits, etc.) */
xopen (device,baud,parity,databits,stopbits)
char *device;
int baud;
char parity;  /* Must be 'e', 'o', or 'n' */
int databits,
stopbits;
{
	unsigned int rs232_param;
	unsigned int baud_bit,parity_bit,stop_bit,data_bit;
	char *stk_buf;
	/* extern xint(); */
	extern char *alloc();

	switch (baud)
	{
	case 110:
		baud_bit = 0 ;
		break;

	case 150:
		baud_bit = 1 ;
		break;

	case 300:
		baud_bit = 2 ;
		break;

	case 600:
		baud_bit = 3 ;
		break;

	case 1200:
		baud_bit = 4 ;
		break;

	case 2400:
		baud_bit = 5 ;
		break;

	case 4800:
		baud_bit = 6 ;
		break;

	case 9600:
		baud_bit = 7 ;
		break;
	}

	switch (parity)
	{
	case 'n':
		parity_bit = 0 ;
		break;

	case 'o':
		parity_bit = 1 ;
		break;

	case 'e':
		parity_bit = 3 ;
		break;
	}

	switch (stopbits)
	{
	case 1:
		stop_bit = 0 ;
		break;

	case 2:
		stop_bit = 1 ;
		break;
	}

	switch (databits)
	{
	case 7:
		data_bit = 2 ;
		break;

	case 8:
		data_bit = 3 ;
		break;
	}

	rs232_param = 0;
	rs232_param |= (baud_bit << 5);
	rs232_param |= (parity_bit << 3);
	rs232_param |= (stop_bit << 2);
	rs232_param |= data_bit;

	srv.ax = rs232_param;  /* Tell Int14 to initialize for rs232 */
	srv.dx = 0;	/* Select COM1: */
	sysint (rs_vec,&srv,&rrv);
	intrinit (int_com,3000,12);
	com_set ();	 /* Activate com interrupt rs_vec */
	outportb (0x3fc,0x9);

	return;
}

xread (string)	 /* Read a string from COM1: */
char *string;
{
	int i,nchar,j,k;
	int quit_flg;
	unsigned char cbuf;

	*(string) = '\0';  /* Just in case */
	quit_flg = OFF ;
	i = 0;
	k = cptr;  /* Latch onto last character pointer */
	if (k == head) return 0;
	if (k > head)
	{
		while (head < k)
		{
			cbuf = combuf[head++];
			if (cbuf == '\0') cbuf = ' ';
			*(string+i++) = cbuf;
		}
		*(string+i) = '\0';
		return i;
	}
	while (head < BUFSIZE)
	{
		cbuf = combuf[head++];
		if (cbuf == '\0') cbuf = ' ';
		*(string+i++) = cbuf;
	}
	head = 0;
	while (head < k)
	{
		cbuf = combuf[head++];
		if (cbuf == '\0') cbuf = ' ';
		*(string+i++) = cbuf;
	}
	*(string + i) = '\0';
	return i;  /* The number of characters read */
}

xfread (string)   /* Read a string from COM1: and filter it */
char *string;
{
	int i,nchar,j,k;
	int quit_flg;
	unsigned char cbuf;

	*(string) = '\0';  /* Just in case */
	quit_flg = OFF ;
	i = 0;
	k = cptr;  /* Latch onto last character pointer */
	if (k == head) return 0;
	if (k > head)
	{
		while (head < k)
		{
			cbuf = combuf[head++];
			if ( (cbuf == XON) || (cbuf == XOFF) || (cbuf == XTRA) || (cbuf == BLTG) ) continue;
			if (cbuf == '\0') cbuf = ' ';
			*(string+i++) = cbuf;
		}
		*(string+i) = '\0';
		return i;
	}
	while (head < BUFSIZE)
	{
		cbuf = combuf[head++];
		if ( (cbuf == XON) || (cbuf == XOFF) || (cbuf == XTRA) || (cbuf == BLTG) ) continue;
		if (cbuf == '\0') cbuf = ' ';
		*(string+i++) = cbuf;
	}
	head = 0;
	while (head < k)
	{
		cbuf = combuf[head++];
		if ( (cbuf == XON) || (cbuf == XOFF) || (cbuf == XTRA) || (cbuf == BLTG) ) continue;
		if (cbuf == '\0') cbuf = ' ';
		*(string+i++) = cbuf;
	}
	*(string + i) = '\0';
	return i;  /* The number of characters read */
}

X/* Write a string to COM1: */
#define hl2x(B) (0x100+(B&0xff))
xwrite (string)
char *string;
{
	int i;
	char cc;
	unsigned char inportb();
	unsigned char status;
	i = 0;
	while ( (cc=*(string+i++)) != '\0' )
	{
		srv.ax = hl2x(cc);
		srv.dx = 0;
		sysint (rs_vec,&srv,&rrv);
		outportb (0x3fc,0x0b);
wait:  /* Check for THRE */
		status = inportb (0x3fd); /* Read LSR */
		if ( (status & 0x20) == 0 ) goto wait;
	}
	return;
}

xclose()  /* Close the com device */
{
	unsigned char inportb();
	unsigned char cc;

	outportb (0x3fc,0x00);	/* Reset MCR */
	outportb (0x3f9,0x00);	/* Reset IER */
	cc = inportb (0x21);
	cc |= 0x10;
	outportb (0x21,cc);
	outportb (0x20,0x20);
	return;
}

brk()  /* Send break down com line */
{
	unsigned char inportb();
	unsigned char cc;
	int i;

	cc = inportb (0x3fb);	/* Read line control register */
	cc |= 0x40;  /* Set break high */
	outportb (0x3fb,cc);
	wait (300);  /* Delay ~300 msec */
	cc &= 0xbf;  /* Reset break bit low */
	outportb (0x3fb,cc);
	return;
}
getcx ()   /* Read a char from COM1: */
{
	int k;
	unsigned char cbuf;
	k = cptr;  /* Latch onto last character pointer */
	if (k == head) return 0;
	if (k > head)
	{
		cbuf = combuf[head++];
		if (cbuf == '\0') cbuf = ' ';
		return(cbuf);
	}
	if (head < BUFSIZE)
	{
		cbuf = combuf[head++];
		if (cbuf == '\0') cbuf = ' ';
		return(cbuf);
	}
	head = 0;
	if (head < k)
	{
		cbuf = combuf[head++];
		if (cbuf == '\0') cbuf = ' ';
		return(cbuf);
	}
	printf("error in getcx\n");
	xclose();
	exit();
}
wait(q)
int q;
{
	int t,s,time();
	t=time();
	q/=10;
	if(q > 99) abort("wait - interval must be < 1 sec");
	if((s=t+q) <100) {
		while((s>time()) && (time()>=t)) ;
	}
	else {
		s-=100;
		while((time()>=t) || (s>time())) ;
	}
}
time()
{
	int t1;
	struct regval treg;
	unsigned char num;
	num=0x21;
	treg.ax=0x2c00;
	sysint(num,&treg,&treg);
	t1=treg.dx&0xff;
	return(t1);
}
bellsw()
{
	bel=turn(bel);
}
X/* Write a char to COM1: */
xputc (cc)
char cc;
{
	int i;
	unsigned char inportb();
	unsigned char status;
		srv.ax = hl2x(cc);
		srv.dx = 0;
		sysint (rs_vec,&srv,&rrv);
		outportb (0x3fc,0x0b);
wait:  /* Check for THRE */
		status = inportb (0x3fd); /* Read LSR */
		if ( (status & 0x20) == 0 ) goto wait;
	return;
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 komm.c
	/bin/echo -n '	'; /bin/ls -ld komm.c
fi
/bin/echo 'Extracting k2.c'
sed 's/^X//' <<'//go.sysin dd *' >k2.c
#include "commio.h"
X/* k2.c small system dependent routines  */
int cms=0;
int hafdup=1;
turn(p)
int p;
{
	if(p == 0) return(1);
	return(0);
}
die()
{
	xclose();
	exit(0);
}
dupsw()
{
	hafdup=turn(hafdup);
}
getarg(fline)
char *fline;
{
	int c;
	char *base;
	base=fline;
	while((c=getkey())!=CR) {
		if(isprint(c) && ((fline-base)<14)) (*fline++)=c;
		if(c=='\b' && ((fline-base)>0)) fline--;
		putchar(c);
	}
	*(fline++)='\0';
}
hexdp()
{
	int c,ci;
	while((c=inkey()) !=DIE )
	{
		if(c==NULL) {
			getkey();
			return;
		}
		if((ci=getcx())!=NULL)
		{
			printf("< %5x %c >",ci,ci);
		}
		if(c>0) {
			outchar(c,1);
		}
	}
}
struct regval
{
	unsigned int ax,bx,cx,dx,si,di,ds,es;
}
ddt,sst,treg;
menkey()
{
	unsigned char intn;
	ddt.ax=0x1+0xc00;
	intn=0x21;
	sysint(intn,&ddt,&ddt);  /* flush keyboard buffer and get a char. */
	return(ddt.ax&0xff);
}
getkey()
{
	int x;
	x=(bdos(7)&0xff);
	if(x==EOZ) return(EOF);
	return(x);
}
inkey()
{
	if(!chrt()) return(bdos(7)&0xff);
	return(-2);
}
chrt()	/* returns 1 if no char available */
{
	unsigned char intn;    /* I have to use ROM BIOS rather than */
	int flag;		/* Dos calls in order to get XOFF to */
	sst.ax=0x100;		/* transmit properly when I hit CNTRL-S */
	intn=0x16;
	flag=sysint(intn,&sst,&sst);  /* read about it on A-33 of TRM */
	return(flag&0x40);
}
prtime()
{
	int tm[4];
	gtime(tm);
	printf("%02d:%02d:%02d",tm[1],tm[2],tm[3]);
}
prdate()
{
	unsigned int dt[4];
	gdate(dt);
	printf("%02d/%02d/%d",dt[2],dt[3],dt[1]);
}
gtime(t)
int t[];
{
	unsigned char num;
	num=0x21;
	treg.ax=0x2c00;
	sysint(num,&treg,&treg);
	t[1]=treg.cx&0xff00;
	t[1]>>=8;
	t[2]=treg.cx&0xff;
	t[3]=treg.dx&0xff00;
	t[3]>>=8;
}
gdate(d)
int d[];
{
	unsigned char num;
	num=0x21;
	treg.ax=0x2a00;
	sysint(num,&treg,&treg);
	d[1]=treg.cx;
	d[1]-=1900;
	d[2]=treg.dx&0xff00;
	d[2]>>=8;
	d[3]=treg.dx&0xff;
}
rowpos()	  /* get row # from bios  */
{
	int inum,ir,q;
	ddt.bx=0;
	ddt.ax=0x300;
	inum=0x10;
	sysint(inum,&ddt,&ddt);
	ir=ddt.dx&0xff00;
	ir>>=8;
	return(ir);
}
colpos()	  /* get col # from bios  */
{
	int inum,ir,q;
	ddt.bx=0;
	ddt.ax=0x300;
	inum=0x10;
	sysint(inum,&ddt,&ddt);
	ir=ddt.dx&0xff;
	return(ir);
}
scroll()
{
	int inum,ir,q;
	ddt.bx=0x700;
	ddt.ax=0x601;
	ddt.dx=0x174f;
	ddt.cx=0;
	inum=0x10;
	sysint(inum,&ddt,&ddt);
	printf("\r");
}
lindel()
{
	int inum,ir,q;
	q=0x100*rowpos();
	ddt.bx=0x700;
	ddt.ax=0x601;	 /* scroll up 1 line  */
	ddt.dx=0x174f;	 /* lower rgt corner of scroll at (23,79) */
	ddt.cx=q; /* upper lft corner of scroll at current line */
	inum=0x10;
	sysint(inum,&ddt,&ddt);
	printf("\r");
}
linins()
{
	int inum,ir,q;
	q=0x100*rowpos(); /* upper lft corner of scroll at current line */
	ddt.bx=0x700;
	ddt.ax=0x701;	 /* scroll down 1 line	*/
	ddt.dx=0x174f;	 /* lower rgt corner of scroll at (23,79) */
	ddt.cx=q;
	inum=0x10;
	sysint(inum,&ddt,&ddt);
	printf("\r");
}
locate(r,c)
int r,c;
{
	unsigned char intn;
	ddt.ax=0x200;
	ddt.bx=0;
	intn=0x10;
	if((r<0) || (r>24)) abort("locate error");
	if((c<0) || (c>79)) abort("locate error");
	ddt.dx=(r<<8)+c;
	sysint(intn,&ddt,&ddt);
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 k2.c
	/bin/echo -n '	'; /bin/ls -ld k2.c
fi
/bin/echo 'Extracting k3.c'
sed 's/^X//' <<'//go.sysin dd *' >k3.c
X/* k3.c  character handling. */
#include "commio.h"
outchar(c,q)
int c,q;
{
	static int escout=0,oc=2; /* oc=2 means ESC sent from terminal */
	extern int hafdup,cms;
	if(c==NULL) funkey();
	if(c*q>0) xputc(c);
	if(hafdup && c>0)
	{
		if((colpos() == 79) && (rowpos() == 23)) scroll();
		if(!escout && isprint(c)) putchar(c);
		if(escout) {
			esctr(c,&oc);
			escout=0;
		}
		if(iscntrl(c)){
			if(c== '\r')
			{
				if(!cms) {
					if((rowpos() == 23)) scroll();
					else printf("\n");
				}
			}
			else
				cntltr(c,&escout);
		}
	}
}
int eat;
comprt(xline)
char *xline;
{
	extern int cms,eat;
	static int escf=0;
	int c,scrf;
	while((c=*xline++) != '\0')
	{
		scrf=0;
		if((c==32) && eat ) continue;
		eat=0;
		if(escf) {
			esctr(c,&escf);
			continue;
		}
		if(isprint(c)){
			if((colpos()== 79) && (rowpos() == 23)) {
				scroll();
				scrf=1;
				locate(22,79);
			}
			putchar(c);
			if(scrf && cms) locate(22,0);
			continue;
		}
		if(iscntrl(c)) cntltr(c,&escf);

	}
}
X/* screen routines */
char CLS[] = {
	'\033', "[2J" }; /* cls */
char  SAVE[] = {
	'\033', "[s"}; /* store cursor pos  */
char  STTL[] = {
	'\033', "[25;1f"};   /* locate row 25 col 1  */
char  RCVR[] = {
	'\033', "[u"};  /* recover cursor  */
char  CLINE[] = {
	'\033' , "[K"};  /* erase to end of line */
char  HION[]  = {
	'\033' , "[7m"}; /* reverse video on  */
char  NORM[]  = {
	'\033' , "[0m"}; /* video back to normal */
char ULINE[] = {
	'\033' , "[4m"}; /* underline on */
char CRUP[]  = {
	'\033' , "[A"};  /* cursor up */
char CRFR[] = {
	'\033' , "[C"};
char CRDN[] = {
	'\033' , "[B"};
crup()
{
	printf("%s",CRUP);
}
crdn()
{
	printf("%s",CRDN);
}
crfr()
{
	printf("%s",CRFR);
}
cls()
{
	printf("%s",CLS);
}
pshcur()
{
	printf("%s",SAVE);
}
popcur()
{
	printf("%s",RCVR);
}
cline()
{
	printf("%s",CLINE);
}
uline()
{
	printf("%s",ULINE);
}
status(lmsg,p)
char *lmsg;
int p;
{
	pshcur();
	printf("%s",STTL);
	if(p==1) hion();
	printf("%s",lmsg);
	if(p==1) scnorm();
	popcur();
}
hion()
{
	printf("%s",HION);
}
scnorm()
{
	printf("%s",NORM);
}
clstat()
{
	status(CLINE,0);
}
X/* clock routine, does not move cursor	*/
xrtime(nr,ncl)
int nr,ncl;
{
	int soff,doff,sseg,dseg,i,j,k,time[4],itoa();
	char ctm[20],bff[7];
	struct{
		int cs,ss,ds,es;
	}
	rrv;
	segread(&rrv);
	sseg=rrv.ds;
	dseg=0xb000;
	doff=nr*160+ncl*2;
	soff=ctm;
	gtime(time);
	for(k=1;k<18;k++) *(ctm+k)=7;
	for(k=0;k<3;k++) {
		j=time[k+1]/10;
		*(ctm+6*k)='0'+j;
		time[k+1]-=j*10;
		*(ctm+(6*k)+2)='0'+time[k+1];
		*(ctm+(6*k)+4)=':';
	}
	movblock(soff,sseg,doff,dseg,16);
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 k3.c
	/bin/echo -n '	'; /bin/ls -ld k3.c
fi
/bin/echo 'Extracting k4.c'
sed 's/^X//' <<'//go.sysin dd *' >k4.c
X/* k4.c escape and cntrl char translation  */
#include "commio.h"
esctr(c,ip)
int c,*ip;
{
	int i,h;
	extern int eat;
	static int locf=0,rnum,cnum;
	if((*ip !=2) && locf){
		if(locf==2) rnum=c-32;
		if(locf==1) {
			cnum=c-32;
			locate(rnum,cnum);
			*ip=0;
		}
		locf--;
	}
	else {
		*ip=0;
		switch(c)
		{
		case 'T':
		case 't':
			cline();
			break;
		case 'Q':
			chins();
			break;
		case 'W':
			chdel();
			break;
		case 'E':
			linins();
			eat=1;
			break;
		case 'i':
			/*	printf("\t");   */
			break;
		case 'j':
			hion();
			break;
		case 'l':
			uline();
			break;
		case 'k':
		case 'm':
			scnorm();
			break;
		case 'R':
			lindel();
			eat=1;
			break;
		case 'y':
		case 'Y':
			cline();
			if((h=rowpos())<23){
				pshcur();
				for(i=h+1;i<24;i++)  {
					locate(i,0);
					cline();
				}
				popcur();
			}
			break;
		case '=':
			if(*ip !=2){
				locf=2;
				*ip=1;
			}
			break;
		case '?':
			xputc(rowpos()+32);
			xputc(colpos()+32);
			xputc('\r');
			break;
		case '+':
		case '*':
		case ':':
		case ';':
			cls();
			break;
		case '"':
		case '#':
			eat=1;
			break;
		default:
			break;
		}
	}
}
cntltr(cc,mp)
int cc,*mp;
{
	int pk;
	extern int cms;
	switch((cc)+64)
	{
	case 'K' :
		if(rowpos() !=0 ) crup();
		else locate(23,colpos());
		break;
	case 'H' :
		if((rowpos() ==0) && (colpos() == 0)) locate(23,79);
		if(colpos() != 0 ) printf("\b");
		else locate(rowpos()-1,79);
		break;
	case 'J' :      /* LF  */
		if(rowpos() != 23) {
			crdn();
			break;
		}
		pk=colpos();
		scroll();
		locate(23,pk);
		break;
	case 'M':       /* CR */
		printf("\r");
		break;
	case 'Z' :
		cls();
		break;
	case 'L' :
		if(colpos() != 79) crfr();
		else {
			if(rowpos() != 23) locate(rowpos()+1,0);
		}
		break;
	case '^' :
	case '~' :
		locate(0,0);
		break;
	case 91  :    /* set escape flag if ESC received  */
		*mp=1;
		break;
	case '_':
		if(rowpos() == 23) {
			scroll();
			break;
		}
		locate(rowpos()+1,0);
		break;
	default:
		putchar(cc);
		break;
	}
}
chins()
{
	int rn,cn;
	unsigned seg,soff,doff,cnt;
	seg=0xb000;
	soff=((rn=rowpos())*160)+(cn=colpos())*2;
	doff=soff+2;
	cnt=(79-cn)*2;
	movblock(soff,seg,doff,seg,cnt);
	printf(" \b");
}
chdel()
{
	int rn,cn;
	unsigned seg,soff,doff,cnt;
	seg=0xb000;
	doff=((rn=rowpos())*160)+(cn=colpos())*2;
	soff=doff+2;
	cnt=(79-cn)*2;
	movblock(soff,seg,doff,seg,cnt);
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 k4.c
	/bin/echo -n '	'; /bin/ls -ld k4.c
fi
/bin/echo 'Extracting funkey.c'
sed 's/^X//' <<'//go.sysin dd *' >funkey.c
X/* funtion keys */
#include "commio.h"
funkey()
{
	int i,j,k,c;
	extern int hafdup,cms;
	i=getkey();
	switch(i)
	{
	case 83:  /* Character insert and delete for Simterm */
		if(cms) {xputc(ESC); xputc('W'); chdel(); break;}
	case 81:
		if(cms) {xputc(SOH); xputc('G'); xputc(CR); break;}
	case 59: /* F1 and End send break */
	case 79:
		brk();
		break;
	case 73:  /* page up for cms  */
		if(cms) {xputc(SOH); xputc('F'); xputc(CR);}
		break;
	case 82: /* insert for cms */
		if(cms) {xputc(ESC); xputc('Q'); chins();}
		break;
	case 71:  /* for cms the home key is PA2 in simterm */
		if(cms) {xputc(SOH); xputc('2'); xputc(CR);}
		break;
	case 18:	  /* alt-e toggles halfdup */
		dupsw();
		break;
	case 22:
	case 62:	/* alt-u or F4 toggle upload */
		upl();
		break;
	case 60:	 /* F2 returns to menu */
		xclose();
		menu();
		break;
	case 61:	  /* F3 toggles download to c:buff.trm	*/
		dwnl(1);
		break;
	case 32:	 /* alt-d toggles download  */
		dwnl(0);  /* to named file*/
		break;
	case 35:	 /* alt-h calls help  */
		help();
		break;
	case 64:
		clstat();  /* F6 clears status line  */
		break;
	case 63:	 /* F5 toggles hex dump  */
		hexdp();
		break;
	case 46:	 /* alt-c cls  */
		cls();
		break;
	case 48:	 /* alt-b toggles bell */
		bellsw();
		break;
	case  72:    /* up arrow key  */
		if(hafdup) crup();
		c=11;
		xputc(c);
		break;
	case  75:
		if(hafdup) printf("\b");     /* back arrow key */
		c=8; xputc(c);
		break;
	case  77:
		if(hafdup) crfr();   /* forward arrow key */
		c=12; xputc(c);
		break;
	case  80:	     /* down arrow key */
		if(hafdup){
			   k=colpos();
			   if(rowpos() == 23) {scroll(); locate(23,k);}
				else {crdn();}
			  }
		c=10; xputc(c);
		break;
	case 84:	  /* shift-F1 toggles shifted tvi-funkeys */
		status("tvi shifted function keys. Press alt+key.",1);
		pshcur(); locate(24,60);
		k=menkey();
		if(k==0) {k=getkey();
		if((k>119) && (k<131)){k-=24;
		xputc(SOH); xputc(k); xputc(CR);}
		}
		popcur();
		clstat();
		break;
	case 103:	  /* cntrl-F10 exits */
		die();
		break;
	case 131:     /* alt-= toggles tvi FUNC key  */
		status("tvi FUNC ON. Press key.",1);
		pshcur(); locate(24,40);
		k=menkey();
		popcur();
		xputc(SOH); xputc(k); xputc(CR);
		clstat();
		break;
	case 120:     /* alt-1 thru alt-- are the tvi keys F1-F11  */
	case 121:
	case 122:
	case 123:
	case 124:
	case 125:
	case 126:
	case 127:
	case 128:
	case 129:
	case 130:
		if(cms) {
			xputc(SOH);
			xputc(i-56);
			xputc(CR);
			break;}
	default:
		status("function key undefined. cntrl-F10 exits.",1);
		break;
	}
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 funkey.c
	/bin/echo -n '	'; /bin/ls -ld funkey.c
fi
/bin/echo 'Extracting help.c'
sed 's/^X//' <<'//go.sysin dd *' >help.c
char *hline[] = {"Local commands." ,
"alt-key means press key while alt is held down.",
"alt - b  toggles bell, default is off.",
"alt -c  local clear screen.",
"alt -d  begins download to a given file. You will be asked for the file name.",
"alt -e  toggles local echo, on for cms.",
"alt -h prints this help file.",
"alt -u or function key F4 begin upload from given file. See manual.",
"alt -1 through - sends the tvi function keys F1 - F11.",
"alt -= is the tvi-FUNC key. You will be prompted for the key.",
"Function Keys.",
"F1 sends break.   F2 closes comm port and returns to menu.",
"The end key also sends break.",
"F3 begins download to a file c:buff.trm.    F4 toggles upload.",
"F5 toggles hex dump. See Manual.    F6 clears status line.",
"cntrl-F10 ends program.",
"In cms mode with simterm the pgup, pgdn ,del, and ins keys work.",
"In cms mode the home key sends FUNC-2.",
"Arrow keys work as on a tvi 920.",
"shift-F1 lets you send a shifted tvi function key",
"ESC and CNTRL codes work as on tvi-920."};
#define LINENUM 21
#include "commio.h"
help()
{int p,o;
extern int cms,unix;
cls();
for(p=0;p<LINENUM;p++){
locate(p,0);
printf(hline[p]);}
status("Press any key to return to term",1);
locate (24,40);
o=menkey();
if(o==NULL) o=getkey();
cls();
if(cms) xputc(26);
xputc(CR);
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 help.c
	/bin/echo -n '	'; /bin/ls -ld help.c
fi
/bin/echo 'Extracting updn.c'
sed 's/^X//' <<'//go.sysin dd *' >updn.c
#include "commio.h"
#define MXLEN 256
dwnl(dp)
int dp;
{
	FILE *outp;
	char  fname[16];
	extern char line[];
	int c;
	if(dp==1) {
		if((outp=fopen("c:buff.trm","ab"))==NULL)
		{
			status("open error for buff.trm.",1);
			pshcur();
			locate(24,40);
			printf("F6 clears status line.");
			popcur();
			return;
		}
		status("buff.trm open",0);
	}
	else{
		pshcur();
		locate(24,0);
		printf("Give name of target file for download.--  ");
		getarg(fname);
		popcur();
		if((outp=fopen(fname, "wb")) == NULL) {
			status("open error in download",1);
			pshcur();
			locate(24,40);
			printf("F6 clears status line.");
			popcur();
			return;
		}
		clstat();
		pshcur();
		locate(24,0);
		printf("Downloading to %s  ",fname);
		popcur();
	}
	pshcur();
	locate(24,34);
	printf("Press any function key to terminate download.");
	popcur();
	while((c=inkey()) !=DIE )
	{
		if(c==NULL) {
			fprintf(outp,"\r");
			fclose(outp);
			getkey();
			clstat();
			return;
		}
		if(xfread(line))
		{
			fprintf(outp,"%s",line);
			cmmprt(line);
		}
		if(c>0) {
			outchar(c,1);
		}
	}
}
upl()
{
	extern int cms,hafdup;
	int c,dc,edpmt;
	FILE *inpf;
	unsigned strlen();
	char  fname[16],inline[256];
	if(!hafdup) {
		     status("upload works only in half duplex mode.",1);
		     return;}
	edpmt=':';
	if(cms) edpmt=XON;
	pshcur();
	locate(24,0);
	printf(" Give name of file to be uploaded.--");
	getarg(fname);
	popcur();
	if(cms){
		if((inpf=fopen(fname, "rb")) == NULL) {
			status("open error-upl",1);
			pshcur();
			locate(24,40);
			printf("F6 clears status line.");
			popcur();
			return;
		}
	}
	if(!cms){
		if((inpf=fopen(fname, "r")) == NULL) {
			status("open error-upl",1);
			pshcur();
			locate(24,40);
			printf("F6 clears status line.");
			popcur();
			return;
		}
	}
	clstat();
	pshcur();
	locate(24,0);
	printf(" Uploading from %s  ",fname);
	printf("Press any function key to exit upload.");
	popcur();
	while(fgets(inline,MXLEN,inpf) != NULL)
	{
		if(*inline == EOZ ) break;
		xwrite(inline);
		cmmprt(inline);
		while((c=getcx()) != edpmt) {
			if((dc=inkey()) == NULL) {
				cmmprt("upload terminated\n");
				fclose(inpf);
				printf("\7");
				clstat();
				getkey();
				return;
			}
			if(isprint(c) && c!=0x20) outchar(c,0);
			if(c=='?') {
				clstat();
				status("upload error",0);
				fclose(inpf);
				printf("\7");
				return;
			}
		}
		if(isprint(c) && c!=0x20)outchar(c,0);
	}
	fclose(inpf);
	printf("\7");
	clstat();
}
cmmprt(xline)
char *xline;
{
	int c;
	while((c=*xline++) != '\0')
	{
		if((colpos()== 79) && (rowpos() == 23)) scroll();
		{
			switch(c)
			{
			case '\b':
				printf("\b \b");
				break;
			case '\n':
				if(rowpos() != 23) {
					putchar(c);
					break;
				}
				scroll();
				break;
			default:
				putchar(c);
				break;
			}
		}
	}
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 updn.c
	/bin/echo -n '	'; /bin/ls -ld updn.c
fi
/bin/echo 'Extracting com_set.asm'
sed 's/^X//' <<'//go.sysin dd *' >com_set.asm
;This by R.F.Starr

code	segment byte public
	assume	cs:code
;	assume	ds:data
	public	com_set 	; Entry to prep the com device & interrupt
				; controller

;
; Sets up the com device
; com_set ()
;
com_set proc	near
	push	bp
	mov	bp,sp

	cli			; Disable the interrupts for now
	mov	dx,3fch
	in	al,dx
	and	al,0f7h ; Set modem control register
	mov	al,0bh
	mov	dx,3fch ;
	out	dx,al	;

	mov	dx,3fbh  ;Set DLAB
	in	al,dx	 ;
	and	al,7fh	 ;
	out	dx,al	 ;

	mov	al,1	 ; Tell the modem to interrupt when a
	mov	dx,3f9h  ; Character is available
	out	dx,al	 ;

	mov	dx,21h	 ;Allow interrupts from com line
	in	al,dx	 ;
	and	al,0efh  ;
	out	dx,al	 ;

	sti
	nop

	pop	bp
	ret
com_set endp

code	ends
	end
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 com_set.asm
	/bin/echo -n '	'; /bin/ls -ld com_set.asm
fi
/bin/echo 'Extracting commio.h'
sed 's/^X//' <<'//go.sysin dd *' >commio.h

#include "stdio.h"
#define ON 1
#define OFF 2
#define SOH 1
#define BELL 7
#define LF 10
#define CR 13
#define XON 17
#define XOFF 19
#define EOZ 26
#define ESC 27
#define XTRA 127
#define DIE 129
#define IER 0x3f9
#define MCR 0x3fc
#define MSR 0x3fe
#define LSR 0x3fd
#define INTA00 0x20
#define EOI 0x20
#define BUFSIZE 4096   /* The buffer that the interrupt vector fills */
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 commio.h
	/bin/echo -n '	'; /bin/ls -ld commio.h
fi