Newsgroups: comp.sys.ti
Path: utzoo!utgpu!jarvis.csri.toronto.edu!csri.toronto.edu!pkern
From: pkern@csri.toronto.edu (pkern)
Subject: a vt100 emulator in Turbo C  (2 of 3)
Message-ID: <8806071609.AA12844@bloor.csri.toronto.edu>
Organization: University of Toronto, CSRI
Date:	Tue, 7 Jun 88 10:49:58 EDT


#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	common.h
#	cterm.ini
#	defs.c
#	esc.c
#	main.c
#	misc.c
#	printer.c
#	setup.c
#	term.c
#	text.c
# This archive created: Tue Jun  7 11:27:25 1988
# By:	pkern ()
export PATH; PATH=/bin:$PATH
echo shar: extracting "'common.h'" '(1599 characters)'
if test -f 'common.h'
then
	echo shar: will not over-write existing file "'common.h'"
else
sed 's/^X//' << \SHAR_EOF > 'common.h'
X/*
X * common.h: main common definitions
X *
X * copyright (c) University of Toronto, 1988.
X */
X	/* ascii control char names */
X#define NUL	000	/* ^@ */
X#define SOH	001	/* ^A */
X#define STX	002	/* ^B */
X#define ETX	003	/* ^C */
X#define EOT	004	/* ^D */
X#define ENQ	005	/* ^E */
X#define ACK	006	/* ^F */
X#define BEL	007	/* ^G */
X#define BS	010	/* ^H */
X#define HT	011	/* ^I */
X#define LF	012	/* ^J */
X#define VT	013	/* ^K */
X#define FF	014	/* ^L */
X#define CR	015	/* ^M */
X#define SO	016	/* ^N */
X#define SI	017	/* ^O */
X#define DLE	020	/* ^P */
X#define DC1	021	/* ^Q */
X#define DC2	022	/* ^R */
X#define DC3	023	/* ^S */
X#define DC4	024	/* ^T */
X#define NAK	025	/* ^U */
X#define SYN	026	/* ^V */
X#define ETB	027	/* ^W */
X#define CAN	030	/* ^X */
X#define EM	031	/* ^Y */
X#define SUB	032	/* ^Z */
X#define ESC	033	/* ^[ */
X#define FS	034	/* ^\ */
X#define GS	035	/* ^] */
X#define RS	036	/* ^^ */
X#define US	037	/* ^_ */
X#define SP	040	/* ' ' */
X#define DEL	0177	/* ^? */
X
X#define XON	DC1	/* ^Q */
X#define XOFF	DC3	/* ^S */
X
X#ifndef FINIT
X#define FINIT	"cterm.ini"	/* setups init file */
X#endif
X
X#ifndef NARGS
X#define NARGS	32	/* max args allowed */
X#endif
X
X	/* attribute bits */
X#define AT_MASK		0x0f
X#define AT_REV		0x01
X#define AT_UL		0x02
X#define AT_BLINK	0x04
X#define AT_BOLD		0x08
X
X#define UP	0
X#define DOWN	1
X#define RIGHT	2
X#define LEFT	3
X
X#define VT52	0
X#define ANSI	1
X#define OFS52	0
X#define ANSOFS	0x40
X#define KEYNORM 0
X#define KEYAPPL	0x20
X
X#define BUFMAX	512
X
X
Xtypedef unsigned char uchar;
X
Xextern int (*xmit)(), (*recv)();
Xextern int (*o_xmit)(), (*o_recv)();
Xextern int (*burp)(), (*esc)();
X
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'cterm.ini'" '(265 characters)'
if test -f 'cterm.ini'
then
	echo shar: will not over-write existing file "'cterm.ini'"
else
sed 's/^X//' << \SHAR_EOF > 'cterm.ini'
X# -- cterm.ini setups --
X# setup A: tabs
XA: 1 9 17 25 33 41 49 57 65 73 89 97 105 113 121 129
X#
X# setup B: main terminal options
XB: 0 1 0 0  0 0 1 1  0 1 0 1  0 0 1 0   2 9600 9600
X#
X# setup C: printer & misc. options
XC: 0 0 0 0  0 0 1 0  0 0 0 0  0 0 0 0   4 1200
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'defs.c'" '(3313 characters)'
if test -f 'defs.c'
then
	echo shar: will not over-write existing file "'defs.c'"
else
sed 's/^X//' << \SHAR_EOF > 'defs.c'
X/*
X * defs.c: init file(s) read or write handling.
X *
X * copyright (c) University of Toronto, 1988.
X */
X#include 
X#include 
X#include 
X#include "common.h"
X
Xextern char tabs[];
X
Xextern uchar *sB[16], *sC[16];
Xextern int *sBi[3], *sCi[2];
X
Xextern int nbaud, pbaud, t_spd, pr_spd;
X
Xstatic char *svfl = FINIT;	/* saved setups filename */
Xstatic char fnbuf[80];
X
X/*
X * getdef -- retrieve setup configuration from a file.
X *	- reads from fnam instead of FINIT, if fnam not null.
X */
Xgetdefs(fnam)
Xchar *fnam;
X{
X	FILE *fp;
X	char *p, *bp, buf[128];
X	int n=0, na=0, nb=0, nc=0, nt=0;
X
X
X	nbaud = prtspd(t_spd);
X	pbaud = prtspd(pr_spd);
X
X	if (fnam && *fnam)	/* ... then use another setups file */
X		{ strcpy(fnbuf, fnam); svfl = fnbuf; }
X	if ((fp = fopen(svfl, "r")) == NULL)
X		return(-1);
X
X	/* read the saved setups and initialize */
X	while(bp = fgets(buf, 127, fp)) {
X		p = bp;	bp += strlen(bp);
X		switch(buf[0]) {
X		case 'A':	/* set some tabs */
X			nb = nc = 0;
X			do {
X				while (p 15)
X					*(sBi[nb-16]) = atoi(p);
X				else
X					*(sB[nb]) = atoi(p) % 2;
X				nb++;
X				while (p < bp && isdigit(*p)) p++;
X			}
X			break;
X		case 'C':	/* setup C */
X			na = nb = 0;
X			/*
X			 * get the 4 block of 4 1/0 flags and
X			 * the printer port number and speed
X			 */
X			while (p < bp && nc < 18) {
X				if (!isdigit(*p)) {
X					if (*p == '#') break;
X					p++; continue;
X				}
X				if (nc > 15)
X					*(sCi[nc-16]) = atoi(p);
X				else
X					*(sC[nc]) = atoi(p) % 2;
X				nc++;
X				while (p < bp && isdigit(*p)) p++;
X			}
X			break;
X		default:	/* notes, junk, ... etc. */
X			break;
X		}
X	}
X
X	fclose(fp);
X
X	/* set new tabs */
X	if (nt) for(na=0; na<132; na++) 
X		tabs[na] = (tabs[na] == 't') ? 'T' : SP;
X
X	/* adjustments */
X	*(sBi[0]) -= 1; *(sCi[0]) -= 1;	/* n_port--; p_port--; */
X
X#ifdef debug
Xcputs("B: ");
Xfor(n=0; n<16; n++)
X	cprintf(" %d%s", *sB[n], ((n+1)%4)?"":" ");
Xcprintf(" %d %d %d\r\n", *sBi[0], *sBi[1], *sBi[2]);
Xcputs("C: ");
Xfor(n=0; n<16; n++)
X	cprintf(" %d%s", *sC[n], ((n+1)%4)?"":" ");
Xcprintf(" %d %d\r\n", *sCi[0], *sCi[1]);
X
Xn = getch();
X#endif
X}
X
X/*
X * putdefs -- write current setup configuration to file svfl
X */
Xputdefs()
X{
X	FILE *fp;
X	int i, n;
X
X	if ((fp = fopen(svfl, "a")) == NULL)
X		return(-1);
X
X	/* save tabs */
X	fprintf(fp, "# -- terminal setups --\n# setup A: tabs\nA:");
X	for (i=n=0; i<132; i++) {
X		if (tabs[i] == 'T') {
X			fprintf(fp, " %d", i+1);
X			n += 2 + (i > 8) + (i > 98);
X		}
X		if (n > 72)
X			fprintf(fp, "\nA:");
X	}
X
X	fprintf(fp, "\n#\n# setup B: main terminal options\nB:");
X	for (i=0; i<16; i++)
X		fprintf(fp, " %d%s", *sB[i], ((i+1)%4)?"":" ");
X	/* n_port, t_spd, r_spd */
X	fprintf(fp, "  %d %d %d\n", *sBi[0]+1, *sBi[1], *sBi[2]);
X
X	fprintf(fp, "#\n# setup C: printer & misc. options\nC:");
X	for (i=0; i<16; i++)
X		fprintf(fp, " %d%s", *sC[i], ((i+1)%4)?"":" ");
X	/* p_port, pr_spd */
X	fprintf(fp, "  %d %d\n", *sCi[0]+1, *sCi[1]);
X	fclose(fp);
X}
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'esc.c'" '(11542 characters)'
if test -f 'esc.c'
then
	echo shar: will not over-write existing file "'esc.c'"
else
sed 's/^X//' << \SHAR_EOF > 'esc.c'
X/*
X * esc.c:
X *	Escape sequence handling routines. The "guts" of vt100-ness.
X *
X * copyright (c) University of Toronto, 1988.
X */
X/*
X * layout based in part on connect.inc from Qkermit.
X */
X#include "common.h"
X
X	/* some xt100 modes (and their default) */
Xuchar m_ansi = ANSI;	/* ANSI/VT52 mode (ANSI) */
Xuchar m_newline = 0;	/* linefeed/newline (linefeed) */
Xuchar m_repeat = 1;	/* auto repeat (on) */
Xuchar m_wrap = 1;	/* wraparound (on) */
Xuchar m_smooth = 0;	/* scrolling mode (jump) */
Xuchar m_print = 0;	/* printer controller mode (exit) */
Xuchar m_autopr = 0;	/* auto print mode (exit) */
Xuchar m_prxtent = 1;	/* print extent (full page) */
Xuchar m_prterm = 0;	/* print termintation (none) */
Xuchar m_origin = 0;	/* origin mode (absolute) */
Xuchar m_reverse = 0;	/* screen mode (normal) */
Xuchar m_insert = 0;	/* insertion/replacement (replacement) */
Xuchar m_columns = 80;	/* column mode (80 cols) */
Xuchar m_crskey = KEYNORM;	/* cursor key mode (cursor) */
Xuchar m_keypad = KEYNORM;	/* keypad mode (numeric) */
X
Xuchar srgn_top=1, srgn_bot=24;	/* scroll region markers */
X
Xstatic int attrb, o_attr, o_x, o_y=0;	/* storage */
Xstatic char *o_cset;	/* more storage */
X	
Xextern uchar cx, cy;
Xextern char tabs[], led[];
Xextern char *cset, *g0, *g1;
Xextern char *ukascii, *usascii;
Xextern int nbaud;
Xextern uchar parity, bpc, m_prty;
Xextern int avofs;
Xextern char *vt100ids[];
Xextern uchar vtidnum;
X
X#define EBMAX	256
Xchar ebuf[EBMAX];	/* escape sequence buffer: place to collect */
X			/* chars for potential future post-mortems */
X
X/*
X * EGETC():
X *	- get next byte from input buffer.
X *	- return(0) if it's CAN or return(1) if it's ESC.
X *	- execute if it's a control char.
X */
X#define EGETC(a)	\
X	while((a=recv()) 1)
X			curs_xy(cx, --cy);
X		break;
X	case '7':	/* save cursor & attributes */
X		o_x = cx, o_y = cy, o_attr = attrb; o_cset = cset;
X		break;
X	case '8':	/* restore cursor & attributes */
X		if (!o_y) break;	/* nothing saved yet */
X		curs_xy(cx=o_x, cy=o_y);
X		attribs(o_attr);
X		cset = o_cset;
X		break;
X	case 'H':	/* set tab stop */
X		tabs[cx-1] = 'T';
X		break;
X	case '=': m_keypad = KEYAPPL; break;
X	case '>': m_keypad = KEYNORM; break;
X	case '@':	/* NB: this ain't ANSI ! */
X		/* an extension to access graphics screens for */
X		/* those too lazy to emulate Tektronix (ie. me) */
X		do {
X			EGETC(c)
X			ebuf[ebi++] = c;
X		} while ((c >= '0' && c <= '9') || c == ';');
X		ebuf[ebi] = NUL;
X		gfx(ebuf, ebi);
X		break;
X	case '[':	/* CSI (command sequence introducer) */
X		qmark = 0;
X		EGETC(c)
X		if (c == '?') {
X			qmark = 1;
X			EGETC(c)
X		}
X		while ((c >= '0' && c <= '9') || c == ';') {
X			ebuf[ebi++] = c;
X			EGETC(c)
X		}
X		ebuf[ebi++] = c;
X		/* get parameter numbers */
X		pn[0] = pn[1] = pn[2] = pn[3] = pn[4] = 0;
X		pn[5] = pn[6] = pn[7] = pn[8] = pn[9] = pn[10] = 0;
X		for (i=2, pnc=0; i=0 && n<=9)
X				pn[pnc] = pn[pnc] * 10 + n;
X			else	/* it's ';' or it's the final char */
X				pn[++pnc] = 0;
X		}
X		switch (c) {
X		case 'A':	/* cursor up */
X			if (!pn[0]) pn[0] = 1;
X			while (cy>1 && pn[0]-- && cy != srgn_top) cy--;
X			curs_xy(cx, cy);
X			break;
X		case 'B':	/* cursor down */
X			if (!pn[0]) pn[0] = 1;
X			while (cy<24 && pn[0]-- && cy != srgn_bot) cy++;
X			curs_xy(cx, cy);
X			break;
X		case 'C':	/* cursor right */
X			if (!pn[0]) pn[0] = 1;
X			if ((cx += pn[0]) > m_columns) cx = m_columns;
X			curs_xy(cx, cy);
X			break;
X		case 'D':	/* cursor left */
X			if (!pn[0]) pn[0] = 1;
X			cx = (cx > pn[0]) ? (cx - pn[0]) : 1;
X			curs_xy(cx, cy);
X			break;
X		case 'H': case 'f':	/* direct cursor address */
X			if (!(cx = pn[1])) cx = 1;
X			if (!(cy = pn[0])) cy = 1;
X			if (m_origin) {
X				cy += (srgn_top-1);
X				if (cy > srgn_bot) cy = srgn_bot;
X			}
X			if (cx > m_columns) cx = m_columns;
X			if (cy > 24) cy = 24;
X			curs_xy(cx, cy);
X			break;
X		case 'K':	/* line erase */
X			switch (pn[0]) {
X			case 0: eol_erase(cx, cy); break;
X			case 1: bol_erase(cx, cy); break;
X			case 2: line_erase(cx, cy); break;
X			}
X			break;
X		case 'J':	/* screen erase */
X			switch (pn[0]) {
X			case 0: eos_erase(cx, cy); break;
X			case 1: bos_erase(cx, cy); break;
X			case 2: all_erase(cx, cy); break;
X			}
X			break;
X		case 'L':	/* insert line */
X			if (cy < srgn_top || cy > srgn_bot) break;
X			if (!pn[0]) pn[0] = 1;
X			cx = 1;
X			line_ins(pn[0], cx, cy, srgn_bot);
X			break;
X		case 'M':	/* delete line */
X			if (cy < srgn_top || cy > srgn_bot) break;
X			if (!pn[0]) pn[0] = 1;
X			cx = 1;
X			line_del(pn[0], cx, cy, srgn_bot);
X			break;
X		case '@':	/* insert char */
X			if (!pn[0]) pn[0] = 1;
X			char_ins(pn[0], cx, cy); break;
X		case 'P':	/* delete char */
X			if (!pn[0]) pn[0] = 1;
X			char_del(pn[0], cx, cy); break;
X		case 'm':	/* attributes */
X			for (i=0; i1 && cy != srgn_top) curs_xy(cx, --cy); break;
X	case 'B': if (cy<24 && cy != srgn_bot) curs_xy(cx, ++cy); break;
X	case 'C': if (cx < 80) curs_xy(++cx, cy); break;
X	case 'D': if (cx > 1) curs_xy(--cx, cy); break;
X	case 'F':	/* UK ASCII */
X		cset = ukascii;
X		break;
X	case 'G':	/* US ASCII */
X		cset = usascii;
X		break;
X	case 'H': curs_xy(cx=1, cy=1); break;
X	case 'I':	/* reverse line feed */
X		if (cy == srgn_top)
X			scrl_down(1, srgn_top, srgn_bot, cx, cy);
X		else if (cy > 1)
X			curs_xy(cx, --cy);
X		break;
X	case 'J': eos_erase(cx, cy); break;
X	case 'K': eol_erase(cx, cy); break;
X	case 'Y':	/* cursor addressing */
X		EGETC(c)
X		ebuf[ebi++] = c;
X		EGETC(c)
X		ebuf[ebi++] = c;
X		/* ignore address if it's out of bounds */
X		if (ebuf[2] > '7' || ebuf[3] > 'o') break;
X		cy = ebuf[2] - SP;
X		cx = ebuf[3] - SP;
X		curs_xy(++cx, ++cy);
X		break;
X	case 'Z':	/* vt52 identify */
X		p = "\033/Z";
X		while (*p) xmit(*p++);
X		break;
X	case '=': m_keypad = KEYAPPL; break;
X	case '>': m_keypad = KEYNORM; break;
X	case '<':
X		m_ansi = ANSI; avofs = ANSOFS;
X		cset = usascii; esc = ansi;
X		break;
X	/* printer commands */
X	case 'W':	/* enter printer mode */
X	case 'X': 	/* exit printer mode */
X	case '^':	/* auto print mode on */
X	case '_':	/* auto print mode off */
X	case 'V':	/* print line */
X	case ']':	/* print page */
X		break;
X	}
X	ebuf[ebi] = '\0';
X	return(0);
X}
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'main.c'" '(2812 characters)'
if test -f 'main.c'
then
	echo shar: will not over-write existing file "'main.c'"
else
sed 's/^X//' << \SHAR_EOF > 'main.c'
X/*
X * main.c:
X *	main() and some misc. routines
X *
X * copyright (c) University of Toronto, 1988.
X */
X#include 
X#include 
X#include 
X#include 
X#include 
X
X#include "common.h"
X#include "tipro.h"
X
Xstatic uchar iflag=0;
X
X/*
X * initialize the world and run the terminal ...
X * ... then reset the world and exit.
X */
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	char *s;
X	int n, boom();
X
X	while (--argc) {
X		argv++;
X		if (argv[0][0] == '-')
X			switch (argv[0][1]) {
X			case 'i':
X				if (getdefs(argv[1]) < 0) {
X					perror(argv[1]);
X					exit(1);
X				}
X				argv++;
X				iflag++;
X				break;
X			default:
X				break;
X			}
X	}
X
X	if (!iflag)
X		getdefs(FINIT);
X	ctrlbrk(boom);	/* for safety sake */
X	init_kbd();
X	init_scr();
X	curs_xy(1, 1); eos_erase(1, 1);
X	init_prt();
X	term();
X	boom(1);
X}
X
Xboom(sw)
Xint sw;
X{
X	reset_prt();
X	reset_kbd();
X	reset_scr();
X	if (sw) cputs("**ZAP**");
X	return(0);
X}
X
X
X/*
X * some misc. routines
X */
X
X
X/*
X * counter(), cntdn, timer_int():
X *	attempt to simulate time-outs (eg. signals on UNIX)
X */
Xunsigned int cntdn=0;
X
Xvoid interrupt (*o_timer)();
X
Xvoid interrupt
Xtimer_int()
X{
X	if (cntdn) cntdn--;
X}
X
X/*
X * install or reset timer_int ISR
X *	allows cntdn to be used as a count-down clock.
X *	(see tipro.h for difference between TIMER and TICKER)
X *	(see kermit.c or xmodem.c for counter/cntdn usage examples)
X */
Xcounter(sw)
Xint sw;
X{
X	if (sw) {	/* install timer_int ISR */
X		o_timer = getvect(TIMER);
X		disable();
X		setvect(TIMER, timer_int);
X		enable();
X	}
X	else {		/* restore old ISR */
X		disable();
X		setvect(TIMER, o_timer);
X		enable();
X	}
X}
X
X
X/* run cmd in dos */
X/*
X * please excuse the tortured code but both system() and
X * spawnl() refused to exit properly (version 1.0 Turbo C)
X */
Xdocmd(cmd)
Xchar *cmd;
X{
X	int i;
X	union REGS r;
X	char *av[] = { "", "", (char *)0 };
X	char buf[128], cpath[128];
X
X	strcpy(cpath, getenv("COMSPEC"));
X	for(i=strlen(cpath)-1; i>0; i--)
X		if (cpath[i]=='\\' || cpath[i]=='/' || cpath[i]==':')
X			{ i++; break; }
X	strcpy(buf, &cpath[i]);
X	av[0] = buf; av[1] = buf + strlen(buf);
X	r.x.ax = 0x3700; intdos(&r, &r);	/* get switchar */
X	sprintf(av[1], "%cC %s", r.h.dl, cmd);
X
X	/* phew! ok, now do it */
X	if (spawnv(P_WAIT, cpath, av) < 0)
X		perror(cmd);
X}
X
X/* doxpnd: expand name if it contains glob chars */
X/* (lazy version ... uses Turbo C's findfirst/findnext routines) */
Xstatic char *ap, abuf[NARGS*16];
X
Xdoxpnd(ac, av)
Xint ac;
Xchar *av[];
X{
X	struct ffblk ff;
X
X	if (ac < 2) ap = abuf;
X#ifdef debug
Xcprintf("%d: %s\r\n", ac, av[ac]);
X#endif
X	if (findfirst(av[ac], &ff, ~FA_LABEL) < 0) return(ac);
X	do {
X		strcpy(ap, ff.ff_name);
X		av[ac] = ap;
X		ap += strlen(ap); *ap++ = NUL;
X#ifdef debug
Xcprintf("%d: %s\r\n", ac, av[ac]);
X#endif
X	} while (!findnext(&ff) && ac++ < NARGS);
X	return(ac);	/* return new arg count */
X}		
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'misc.c'" '(4202 characters)'
if test -f 'misc.c'
then
	echo shar: will not over-write existing file "'misc.c'"
else
sed 's/^X//' << \SHAR_EOF > 'misc.c'
X/*
X * misc.c:
X *	misc. strings including keypadv[] and vt100ids[]
X *
X * copyright (c) University of Toronto, 1988.
X */
X#include "common.h"
X
Xchar ansback[33];		/* answerback message */
X
Xchar *keypadv[0x80] = {		/* cursor key & keypad strings */
X/* vt52 */
X		/* normal mode */
X	/* cursor keys */
X	"\033A", "\033B", "\033C", "\033D", "", "", "", "",
X	/* keypad */
X	"0", "1", "2", "3", "4", "5", "6", "7",
X	"8", "9", "-", ",", ".", "\r", "\033P", "\033Q",
X	"\033R", "\033S", "\200", "\b", "\003", "\r\n", ansback, "",
X	
X		/* application mode */
X	/* cursor keys */
X	"\033A", "\033B", "\033C", "\033D", "", "", "", "",
X	/* keypad */
X	"\033?p", "\033?q", "\033?r", "\033?s",
X	"\033?t", "\033?u", "\033?v", "\033?w",
X	"\033?x", "\033?y", "\033?m", "\033?l",
X	"\033?n", "\033?M", "\033P", "\033Q",
X	"\033R", "\033S", "\200", "\b",
X	"\003", "\033?M", ansback, "",
X
X/* ansi */
X		/* normal mode */
X	/* cursor keys */
X	"\033[A", "\033[B", "\033[C", "\033[D", "", "", "", "",
X	/* keypad */
X	"0", "1", "2", "3", "4", "5", "6", "7",
X	"8", "9", "-", ",", ".", "\r", "\033OP", "\033OQ",
X	"\033OR", "\033OS", "\200", "\b", "\003", "\r\n", ansback, "",
X
X		/* application mode */
X	/* cursor keys */
X	"\033OA", "\033OB", "\033OC", "\033OD", "", "", "", "",
X	/* keypad */
X	"\033Op", "\033Oq", "\033Or", "\033Os",
X	"\033Ot", "\033Ou", "\033Ov", "\033Ow",
X	"\033Ox", "\033Oy", "\033Om", "\033Ol",
X	"\033On", "\033OM", "\033OP", "\033OQ",
X	"\033OR", "\033OS", "\200", "\b",
X	"\003", "\033OM", ansback, ""
X};
X
X
Xuchar vtidnum = 9;	/* vt100ids index (see below) */
X
Xchar *vt100ids[] = {	/* device report terminal ID strings */
X		/*
X		 * strings lifted from vttest's main.c
X		 *   STP = processor option
X		 *   PP  = printer port
X		 *   AVO = advanced video option
X		 *   GPO = graphics processor option
X		 */
X	"\033[?1;0c",	/* No options (vanilla VT100)		*/
X/*	"\033[?1;1c",	/* VT100 with STP			*/
X	"\033[?1;2c",	/* VT100 with AVO (could be a VT102)	*/
X/*	"\033[?1;3c",	/* VT100 with STP and AVO		*/
X/*	"\033[?1;4c",	/* VT100 with GPO			*/
X/*	"\033[?1;5c",	/* VT100 with STP and GPO		*/
X/*	"\033[?1;6c",	/* VT100 with AVO and GPO		*/
X/*	"\033[?1;7c",	/* VT100 with STP, AVO and GPO		*/
X	"\033[?1;11c",	/* VT100 with PP and AVO		*/
X	"\033[?1;15c",	/* VT100 with PP, GPO and AVO		*/
X/*	"\033[?4;2c",	/* VT132 with AVO			*/
X/*	"\033[?4;3c",	/* VT132 with AVO and STP		*/
X/*	"\033[?4;6c",	/* VT132 with GPO and AVO		*/
X/*	"\033[?4;7c",	/* VT132 with GPO, AVO, and STP		*/
X/*	"\033[?4;11c",	/* VT132 with PP and AVO		*/
X/*	"\033[?4;15c",	/* VT132 with PP, GPO and AVO		*/
X/*	"\033[?7c",	/* VT131				*/
X/*	"\033[?12;5c",	/* VT125				*/
X/*	"\033[?12;7c",	/* VT125 with AVO			*/
X/*	"\033[?5;0c",	/* VK100 (GIGI)				*/
X/*	"\033[?5c",	/* VK100 (GIGI)				*/
X	""
X};
X
Xchar led[4] = { SP, SP, SP, SP};	/* simulated LEDs */
X
Xchar *cset, *g0, *g1;		/* character set pointers */
X	/* simulated US ASCII char set */
Xchar *usascii = "\
X\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\
X\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037\
X !\"#$%&'()*+,-./0123456789:;<=>\
X?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^\
X_`abcdefghijklmnopqrstuvwxyz{|}~\177";
X
X	/* simulated UK ASCII set */
Xchar *ukascii = "\
X\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\
X\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037\
X !\"#$%&'()*+,-./0123456789:;<=>\
X?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^\
X\040\004\261....\370\361..\331\277\332\300\305\304\
X\304\304\304_\303\264\301\302\263\363\362\343\330\234\371\177";
X
X/* tab string */
Xchar tabs[133] = {
X	'T',SP,SP,SP,SP,SP,SP,SP,'T',SP,SP,SP,SP,SP,SP,SP,
X	'T',SP,SP,SP,SP,SP,SP,SP,'T',SP,SP,SP,SP,SP,SP,SP,
X	'T',SP,SP,SP,SP,SP,SP,SP,'T',SP,SP,SP,SP,SP,SP,SP,
X	'T',SP,SP,SP,SP,SP,SP,SP,'T',SP,SP,SP,SP,SP,SP,SP,
X	'T',SP,SP,SP,SP,SP,SP,SP,'T',SP,SP,SP,SP,SP,SP,SP,
X	'T',SP,SP,SP,SP,SP,SP,SP,'T',SP,SP,SP,SP,SP,SP,SP,
X	'T',SP,SP,SP,SP,SP,SP,SP,'T',SP,SP,SP,SP,SP,SP,SP,
X	'T',SP,SP,SP,SP,SP,SP,SP,'T',SP,SP,SP,SP,SP,SP,SP,
X	'T',SP,SP,SP,NUL};
X
Xextern uchar m_columns;
X
X/*
X * tab -- return next tab-stop column position (x == current column).
X */
Xtab(x)
Xint x;
X{
X	register int i;
X
X	i = x-1;
X	if (tabs[i] != SP) i++;
X	while (i+1 < m_columns && tabs[i] == SP) ++i;
X	return(i+1);
X}
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'printer.c'" '(414 characters)'
if test -f 'printer.c'
then
	echo shar: will not over-write existing file "'printer.c'"
else
sed 's/^X//' << \SHAR_EOF > 'printer.c'
X/*
X * printer.c:
X *	printer related (dummy) functions.
X *
X * copyright (c) University of Toronto, 1988.
X */
X#include "common.h"
X
X/* send current page to printer */
Xpr_page() { }
X
X/* send curent line to printer */
Xpr_line() { }
X
X/*
X * send printer status to host
X *  possible responses:
X *	 1 = printer ready
X *	 0 = printer not ready
X *	-1 = no printer
X */
Xpr_stat() { return(-1); }
X
Xpr_init() { }
X
Xpr_reset() { }
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'setup.c'" '(14100 characters)'
if test -f 'setup.c'
then
	echo shar: will not over-write existing file "'setup.c'"
else
sed 's/^X//' << \SHAR_EOF > 'setup.c'
X/*
X * setup.c:
X *	setups(): simulate XT100+ setup screens.
X *	(beware! code in setups() is not pretty)
X *	genstat(): put general status bar on line 25.
X *
X * copyright (c) University of Toronto, 1988.
X */
X#include "common.h"
X#include "tipro.h"
X	
X#define TOGGLE(a)	a=((a)+1)%2	/* toggle between 0 and 1 */
X#define SWAP(a,b,x)	x=a;a=b;b=x;
X
Xextern int keyhit;
Xextern char tabs[], ansback[];
Xextern uchar m_ansi, m_wrap, m_newline;
Xextern uchar m_smooth, m_repeat, m_reverse;
X
Xextern char *bauds[];
X
X/* main port parameters */
Xint n_port=1, nbaud=B9600, t_spd=9600, r_spd=9600;
Xuchar bpc=1, parity=0, stopbits=0, m_prty=0;
X
X/* printer port parameters */
Xint p_port=3, pbaud=B1200, pr_spd=1200;
Xuchar p_bpc=1, p_prty=0, p_sbits=0, pm_pty=0;
X
Xuchar cursor=1;	/* block or underline cursor (block) */
Xuchar echo=0;	/* local echo (none) */
Xuchar transparent=0;	/* control chars (interpret) */
Xuchar local=0;	/* connect (on line) */
Xuchar flowctl=1, xoff=0;	/* auto xon/xoff, ready to receive */
Xuchar interlace=0;	/* graphics display */
Xuchar ignrflow=0;	/* don't ignore remote xon/xoff */
Xuchar rxoff=0;		/* no remote XOFF yet */
Xuchar devrep=1;	/* device report */
X
Xextern char *ukascii;
Xuchar pt, zilch=0;
X
Xuchar *sB[16] = { /* setup B related variables */
X	&m_smooth,	/* scroll mode */
X	&m_repeat,	/* autorepeat */
X	&m_reverse,	/* screen mode */
X	&cursor,	/* cursor type */
X	&zilch,	/* margin bell (NA) (off) */
X	&zilch,	/* keyclick (NA) (off) */
X	&m_ansi,	/* ansi/vt52 */
X	&flowctl,	/* auto xon/xoff */
X	&zilch,	/* #/pound sign (NA) (#) */
X	&m_wrap,	/* wraparound */
X	&m_newline,	/* newline */
X	&interlace,	/* interlace */
X	&parity,	/* parity sense */
X	&m_prty,	/* parity */
X	&bpc,		/* bits per char */
X/*	&zilch;	/* power (NA) (60 Hz) */
X	&stopbits	/* stop bits */
X};
X
Xuchar *sC[16] = {
X	&zilch,	/* printer => host */
X	&zilch,	/* printer test */
X	&zilch,	/* print termination */
X	&zilch,	/* print extent */
X	&p_prty,	/* printer parity sense */
X	&pm_pty,	/* printer parity */
X	&p_bpc,		/* printer bits per char */
X	&echo,	/* local echo */
X	&zilch,	/* screen saver */
X	&zilch,	/* diagnostic mode */
X	&zilch,	/* two page operation */
X	&zilch,	/* smooth scroll speed */
X	&transparent,	/* transparency mode */
X	&ignrflow,	/* discard xon/xoff from host */
X	&zilch,	/* character rate to host */
X	&devrep	/* identification */
X};
X
Xint *sBi[3] = {
X	&n_port,	/* comm port number */
X	&t_spd,		/* Tx speed */
X	&r_spd		/* Rx speed */
X};
X
Xint *sCi[2] = {
X	&p_port,	/* printer port */
X	&pr_spd		/* printer speed */
X};
X
Xstatic char *sBs[48] = {	/* setup B label strings */
X	"SCROLL: ",	"jump",	"smooth",
X	"AUTOREPEAT: ",	"off",	"on",
X	"SCREEN BACKGROUND: ",	"dark",	"light",
X	"CURSOR: ",	"underline",	"block",
X	"MARGIN BELL: ",	"off",	"on",
X	"KEYCLICK: ",	"off",	"on",
X	"ANSI/VT52: ",	"vt52",	"ansi",
X	"AUTO XON XOFF: ",	"off",	"on",
X	"SHIFTED \"3\": ",	"#",	"\234",
X	"WRAP AROUND: ",	"off",	"on",
X	"NEW LINE: ",	"off",	"on",
X	"INTERLACE: ",	"off",	"on",
X	"PARITY SENSE: ",	"odd",	"even",
X	"PARITY: ",	"disabled",	"enabled",
X	"BITS PER CHAR: ",	"7",	"8",
X/*	"POWER (HZ): ",	"60",	"50",	*/
X	"STOPBITS: ",	"1",	"2",
X};
X
Xstatic char *sCs[48] = {	/* setup C label strings */
X	"PRINTER => HOST: ",	"disabled",	"enabled",
X	"PRINTER TEST: ",	"disabled",	"enabled",
X	"PRINT TERMINATION: ",	"none",	"form feed",
X	"PRINT EXTENT: ",	"scroll window",	"all",
X	"PARITY SENSE: ",	"odd",	"even",
X	"PARITY: ",	"disabled",	"enabled",
X	"BITS PER CHAR: ",	"7",	"8",
X	"LOCAL ECHO: ",	"disabled",	"enabled",
X	"SCREEN SAVER: ",	"disabled",	"enabled",
X	"DIAGNOSTIC MODE: ",	"disabled",	"enabled",
X	"TWO PAGE OPERATION (80 COL): ", "disabled",	"enabled",
X	"SMOOTH SCROLL SPEED: ",	"slow",	"fast",
X	"TRANSPARENCY MODE: ",	"disabled",	"enabled",
X	"DO NOT PROCESS \"XOFF/XON\": ", "disabled",	"enabled",
X	"CHARACTER RATE TO HOST: ", "unlimited", "limited to 60 cps",
X	"DEVICE REPORT: ",	"Esc[?1;11c",	"Esc[?1;2c",
X};
X
X/* display setup screens, set modes/parameters */
Xsetups()
X{
X	int ac;
X	char *av[NARGS];
X	int (*proto)(), kermit(), xmodem(), text();
X
X	char b, pb, nbuf[256], *p, *s;
X	int c, i, n, n0, x, ox, togl, pnum, ppn;
X
X	/* restore kb interrupts */
X	reset_kbd();
X	/* save screen image */
X	save_scr();
X		
X	pt = *(ukascii+'l');
X	pnum = n_port;	ppn = p_port;
X	b = nbaud; pb = pbaud;
X	togl = 0;
X	av[0] = (char *)0;
X
Xset_up:		/* re-entry ... refreshes info screen */
X	curs_xy(1, 1);
X	eos_erase(1, 1);
X	genstat(1, 1);
X	burps("SET-UP", 2, 2, AT_BLINK);
X	burps("TO EXIT PRESS \"SETUP\"", 2, 4, AT_UL);
X	burps("\
X  F1      F2      F3       F4     \
X              F9      F10     F11     F12     \
X SETUP  (SETUP)  Break   Backspace\
X              Up      Down    Left   Right    ", 1, 8, 0);
X	burps("\
X clear/    clear    line/   setups\
X  toggle  transmit  receive    80/132  reset  \
Xset tabs  all tabs   local   a/b/c\
X   1/0     speed     speed     (port)         \
X   2@        3#       4$      5%  \
X    6^       7&        8*        9(      0)   ", 1, 14, 0);
X
Xset_a:
X	burps("A", 9, 2, AT_BLINK);
X	for (i=0; i<80; i+=20) {
X		burps("1234567890", i+1, 24, 0);
X		burps("1234567890", i+11, 24, AT_REV);
X	}
X	tabs[80] = NUL;
X	burps(tabs, 1, 23, 0);
X	for(x=1;;) switch(c=kbdget()) {
X		case K_SETUP:
X		case K_F2:	goto done;
X
X		case '0':
Xfresh:		/* reset terminal configuration */
X			getdefs("");
X			devset();
X			pnum = n_port;	ppn = p_port;
X			b = nbaud; pb = pbaud;
X			goto set_up; break;
X
X		case SP:
X		case K_F12:
X		case K_RIGHT:	x=(x<80)?x+1:80; curs_xy(x, 23); break;
X
X		case BS:
X		case K_F11:
X		case K_LEFT:	x=(x>1)?x-1:1; curs_xy(x, 23); break;
X
X		case CR:	curs_xy(x=1, 23); break;
X
X		case HT:	curs_xy(x=tab(x), 23); break;
X
X		case '5':
X		case K_DOWN:	goto set_b; break;
X
X		case K_UP:	goto set_c; break;
X
X		case '4':		/* toggle connect mode */
X			TOGGLE(local);
X			genstat(x, 23);
X			break;
X
X		case '2':		/* toggle tab */
X			if (tabs[x-1] == 'T')
X				tabs[x-1] = SP;
X			else
X				tabs[x-1] = 'T';
X			burpc(tabs[x-1]); burpc(BS);
X			break;
X
X		case K_INS:		/* set tab */
X			tabs[x-1] = 'T';
X			burpc(tabs[x-1]); burpc(BS);
X			break;
X
X		case K_DEL:		/* erase tab */
X			tabs[x-1] = SP;
X			burpc(tabs[x-1]); burpc(BS);
X			break;
X
X		case 'T':	/* set default tabs */
X			curs_xy(1, 23);
X			for(i=0; i<80; i++) {
X				tabs[i] = SP;
X				if (i && !(i%8)) tabs[i] = 'T';
X				burpc(tabs[i]);
X			}
X			curs_xy(x, 23);
X			break;
X
X		case '3':		/* clear all tabs */
X			for(i=0; i<80; i++) tabs[i] = SP;
X			burps(tabs, x=1, 23, 0);
X			break;
X
X		case 'S':	/* save setup */
Xdumpit:
X			all_erase();
X			burps("  PLEASE   WAIT  ", 31, 6, AT_REV | AT_BLINK);
X			curs_xy(48,6);
X			t_spd = r_spd = atoi(bauds[b]);
X			pr_spd = atoi(bauds[pb]);
X			sBi[0] = &pnum; sCi[0] = &ppn;
X
X			sleep(3);	/* pretend churning :-) */
X			putdefs();
X
X			sBi[0] = &n_port; sCi[0] = &p_port;
X			goto set_up;
X			break;
X
X		case '!':	/* execute a command in dos */
Xcmd:
X			burps("! ", 1, 21, 0); curs_xy(3,21);
X			nbuf[0] = 80; s = cgets(nbuf);
X			if (nbuf[1]) {
X				reset_scr();
X				clr_home();
X				docmd(s);
X				kbflush();
X				burps(s, 1, 25, AT_REV);
X				curs_xy(nbuf[1]+1, 25);
X				c = kbdget();
X				init_scr();
X				goto set_up;
X			}
X			curs_xy(1, 21); eol_erase(1, 21);
X			curs_xy(x, 23);
X			break;
X
X		/*
X		 * file transfer:
X		 *	k - kermit
X		 *	x - xmodem
X		 *	c - text ("cat")
X		 */
X		case 'k':
X			av[0] = "kermit";
X			proto = kermit;
X		case 'c':
X			if (!av[0]) {
X				av[0] = "cat";
X				proto = text;
X			}
X		case 'x':
X			if (!av[0]) {
X				av[0] = "xmodem";
X				proto = xmodem;
X			}
X			burps("$ ", 1, 21, 0);
X			burps(av[0], 3, 21, 0);
X			curs_xy(4+strlen(av[0]),21);
X			nbuf[0] = 80; s = cgets(nbuf);
X			reset_scr();
X			clr_home();
X			for(ac=1, n=*s; *s && n && ac1)?x-1:1; break;
X
X		case K_UP:	goto set_a; break;
X
X		case '4':		/* toggle connect mode */
X			TOGGLE(local);
X			genstat(x, 23);
X			break;
X
X		case '5':
X		case K_DOWN:	goto set_c; break;
X
X		case CR: x = 1; break;
X
X		case HT: x = tab(x); break;
X
X		case '6':	togl++; break;
X
X		case 'A':	/* answer back message */
X			burps("A = ", 1, 21, 0); curs_xy(5, 21);
X			i = 0;
X			c = (n0 = kbdget()) & 0xff;
X			if (c 27 || i & 4) continue;
X		i = (i & 3) | ((i & 24) >> 1);
X		n = i * 3;
X		if (togl) switch (i) {
X		/* block 1 */
X		case 1:
X			TOGGLE(m_repeat);
X			kbautorep(m_repeat);
X			break;
X		case 3:
X			TOGGLE(cursor);
X			curs_type(cursor);
X			break;
X
X/*
X *		case 6: case 7: case 9: case 10:
X *		case 12: case 13: case 14: case 15:
X *			TOGGLE(*sB[i]); break;
X */
X		/* block 2 */
X		case 6: TOGGLE(m_ansi);		break;
X		case 7: TOGGLE(flowctl);	break;
X
X		/* block 3 */
X		case 9: TOGGLE(m_wrap);		break;
X		case 10: TOGGLE(m_newline);	break;
X		case 11:
X			TOGGLE(interlace);
X			init_gfx();
X			break;
X
X		/* block 4 */
X		case 12: TOGGLE(parity);	break;
X		case 13: TOGGLE(m_prty);	break;
X		case 14: TOGGLE(bpc); 		break;
X		case 15: TOGGLE(stopbits);	break;
X
X		default:
X			break;
X		}
X		sdisp(x, *sB[i], sBs[n], sBs[n+1], sBs[n+2]);
X	}
X	goto done;
X
Xset_c:		/* mostly printer-related */
X	curs_xy(1, 23); eos_erase(1, 23);
X	burps("C", 9, 2, AT_BLINK);
X	for (i=0; i<16; i++)
X		nbuf[i] = (*sC[i]) + '0';
X
X	burps("1 ....  2 ....  3 ....  4 ....", 1, 24, 0);
X	for(i=16, n=27; i; i-=4, n-=8) {
X		nbuf[i] = NUL;
X		burps(nbuf+i-4, n, 24, AT_REV);
X	}
X
X	burps("PRINTER PORT  .", 49, 24, 0);
X	s = "0"; *s = '1'+ppn; burps(s, 63, 24, 0);
X	burps("SPEED .....   ", 66, 24, 0);
X	burps(bauds[pb], 72, 24, 0);
X	curs_xy(1, 23);
X
X	for(ox=x=1, togl=0;; togl=0) {
X		switch(c=kbdget()) {
X		case K_SETUP:
X		case K_F2:	goto done;
X
X		case '0':	goto fresh; break;
X
X		case SP:
X		case K_F12:
X		case K_LEFT:	x=(x>1)?x-1:1; break;
X
X		case BS:
X		case K_F11:
X		case K_RIGHT:	x=(x<80)?x+1:80; break;
X
X		case K_UP:	goto set_b; break;
X
X		case '4':		/* toggle connect mode */
X			TOGGLE(local);
X			genstat(x, 23);
X			break;
X
X		case '5':
X		case K_DOWN:	goto set_a; break;
X
X		case CR: x = 1; break;
X
X		case HT: x = tab(x); break;
X
X		case '6':	togl++; break;
X
X		case '7': case '8':	/* printer speed */
X			pb = (pb+1) % (EXTB+1);
X			burps(bauds[pb], 72, 24, 0);
X			curs_xy(x, 23);
X			break;
X
X		case '9':	/* was 80/132 toggle */
X		case 'p': case 'P':	/* printer port */
X			ppn = (ppn+1) % NPORTS;
X			s = "0"; *s = '1'+ppn; burps(s, 63, 24, 0);
X			curs_xy(x, 23);
X			break;
X
X		case 'S':	/* save setups */
X			goto dumpit;
X			break;
X
X		case '!':	/* dos command */
X			goto cmd;
X			break;
X
X		default:
X			break;
X		}
X
X		if (x != ox)
X			{ eol_erase(ox, 23); curs_xy(x, 23); }
X
X
X		ox = x;
X		i = x-3;
X		if (i > 27 || i & 4) continue;
X		i = (i & 3) | ((i & 24) >> 1);
X		n = i * 3;
X		if (togl) switch (i) {
X/*
X *		case 4: case 5: case 6: case 7: case 12:
X *			TOGGLE(*sC[i]); break;
X */
X		case 4:	TOGGLE(p_prty);	break;
X		case 5:	TOGGLE(pm_pty);	break;
X		case 6:	TOGGLE(p_bpc);	break;
X		case 7: TOGGLE(echo);	break;
X
X		/* block 4 */
X		case 12: TOGGLE(transparent);	break;
X		case 13: TOGGLE(ignrflow);	break;
X		case 15: TOGGLE(devrep);	break;
X
X		default:
X			break;
X		}
X		sdisp(x, *sC[i], sCs[n], sCs[n+1], sCs[n+2]);
X	}
Xdone:
X	pbaud = pb;
X	pr_reset();
X	p_port = ppn;
X	pr_init();
X
X	nbaud = b;
X	if (pnum != n_port) {
X		reset_prt();
X		n_port = pnum;
X		init_prt();
X	}
X	restore_scr();
X	init_kbd();
X	set_prt();
X	devset();
X}
X
X/* display a setup option, underline current selection */
X
Xsdisp(x, sw, label, off, on)
Xint x, sw;
Xchar *label, *off, *on;
X{
X	char *p;
X	int l, n, f;
X
X	l = strlen(label); n = strlen(on);
X	f = x+2+l+n; n = x+1+l;
X	p = "0"; *p = '0' + (sw>0);
X	burps(p, x, 24, AT_REV);
X	burps(label, x+1, 23, 0);
X	burps(on, n, 23, (sw)? AT_UL : 0);
X	*p = '/'; burps(p, f-1, 23, 0);
X	burps(off, f, 23, (sw)? 0 : AT_UL);
X	*p = pt; burps(p, x, 23, 0);
X}
X
Xchar stbuf[81];		/* status line buffer */
Xextern char led[];
X
X/* general status line */
Xgenstat(x, y)
Xuchar x, y;
X{
X	/* comm information */
X	sprintf(stbuf, "port:%d data:%d%c%d speed:%5s        ",
X		n_port+1, bpc+7,
X		((m_prty) ? ((parity) ? 'E' : 'O') : 'N'),
X		stopbits+1, bauds[nbaud]);
X	/* connect mode "leds" */
X	sprintf(&stbuf+35, "on line %c  local %c       ",
X		(local) ? SP : '*', (local) ? '*' : SP);
X	/* programmable "leds" */
X	sprintf(&stbuf+60, "1 %c  2 %c  3 %c  4 %c  ",
X		led[0], led[1], led[2], led[3]);
X	sturp(stbuf, x, y);
X}
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'term.c'" '(7801 characters)'
if test -f 'term.c'
then
	echo shar: will not over-write existing file "'term.c'"
else
sed 's/^X//' << \SHAR_EOF > 'term.c'
X/*
X * term.c:
X *	term(): the terminal.
X *	rloop(), xloop(): local mode recv & xmit routines
X *	devset(): assigns xmit & recv and
X *		  handles other setings and "devices."
X * note: some code gets repeated here and there.
X *	 this may not be pretty but it keeps the
X *	 main loops from getting bogged down.
X *
X * copyright (c) University of Toronto, 1988.
X */
X#include "common.h"
X
Xuchar cx=1, cy=1;	/* current cursor position */
Xuchar tx=0, ty=0;	/* cursor "memory" (for wrap, scroll, etc.) */
X
Xextern char ansback[];
Xextern char *cset, *g0, *g1;
Xextern char *usascii, *ukascii;
Xextern char *keypadv[];
X
Xextern uchar keyboom, keyhit;
Xextern uchar m_insert, m_repeat;
Xextern uchar m_ansi, m_crskey, m_keypad;
Xextern uchar m_columns, m_wrap, m_newline;
Xextern uchar srgn_bot, srgn_top;
Xextern uchar local, transparent, echo, xoff, cursor;
Xextern uchar ignrflow, rxoff, devrep, vtidnum, txtxfr;
X
Xextern int xmit_chr(), recv_chr(), trns_chr();
Xextern int burpc(), insurpc(), ansi(), vt52();
Xextern int kbdget();
X
Xint avofs = ANSOFS;	/* ansi/vt52 keypadv "offset" bits */
Xint (*xmit)(), (*recv)();	/* xmit = output to "comm port" */
Xint (*o_xmit)(), (*o_recv)();	/* recv = input from "comm port" */
Xint (*burp)();			/* output to "screen" */
Xint (*keyg)(), (*o_keyg)();	/* input from "keyboard" */
X
X/*
X * term -- the main loop, the guts, "where the action is"
X *	"key" input has priority. Only after the "key type-ahead"
X *	buffer is emptied does it check the input buffer.
X *	(except when rxoff is high (ie. a remote XOFF request))
X */
Xterm()
X{
X	char *p;
X	int zip();
X	register int c;
X
X	cset = g0 = g1 = usascii;
X
X	devset();
X
X	while (!keyboom) {
X		while (keyhit) {	/* drain key buffer(s) */
X			if ((c = keyg()) & 0xff) {	/* ascii keys */
X				xmit(c);
X				if (c < SP) switch (c) {
X					case CR:
X						if (m_newline) xmit(LF);
X						break;
X					case XOFF:
X						xoff++; recv=zip;
X						break;
X					case XON:
X						xoff=0; recv=o_recv;
X						break;
X					default:
X						break;
X				}
X			}
X			else if ((c = kbdfn(c)) & 0x80)	/* setup keys */
X				setups();
X			else if (c & 0x40) {	/* send BREAK or NUL */
X				if (c & 1) xmit(NUL);
X				else send_brk(local);
X			}
X			else {			/* function "keys" */
X				c |= (c & 0x18) ? m_keypad : m_crskey;
X				p = keypadv[c | avofs];
X				while (*p) xmit(*p++ & 0x7f);
X				if (rxoff) break;
X			}
X		}
X
X		/* check incoming buffer(s) */
X		if ((c = recv()) < 0) continue;
X
X		if (c & 0x60) {		/* visible ascii */
Xsplat:
X			/*
X			 * wraparound handling: tx indicates a visible
X			 * char was last placed in the final column.
X			 * if our line position (cy) hasn't changed
X			 * and if m_wrap then if we're at the end of a
X			 * scroll region, scroll else move down 1 line.
X			 */
X			if (tx && ty == cy && m_wrap) {
X				tx = ty = 0;
X				curs_xy(cx=1, cy);	/* CR */
X				if (cy == srgn_bot)	/* scroll it */
X				/*	scrl_up(1, srgn_top, srgn_bot, cx, cy);	 */
X					/*
X					 * seems TI bios scrolls faster
X					 * when burping LF than with
X					 * scrl_up(1,1,24), so let's try
X					 * to take advantage of that.
X					 */
X					if (srgn_top-1 || cy < 24)
X						scrl_up(1, srgn_top, srgn_bot, cx, cy);
X					else
X						burpc(LF, cx, cy);
X				else if (cy < 24)
X					curs_xy(cx, ++cy);
X			}
X
X			burp(*(cset+c), cx++, cy);	/* screen it */
X
X			if (cx > m_columns) {	/* at last column? */
X				/* next char might wraparound */
X				ty = cy;
X				curs_xy(cx=tx=m_columns, cy);
X			}
X			continue;
X		}
X
X		switch (c) {		/* control chars */
X		case CR: tx = 0; curs_xy(cx=1, cy); break;
X		case LF: case VT: case FF:
X			tx = 0;
X			if (cy == srgn_bot)	/* scroll it */
X				if (cy < 24 || srgn_top-1)
X					scrl_up(1, srgn_top, srgn_bot, cx, cy);
X				else
X					burpc(LF, cx, cy);
X			else if (cy < 24)
X				curs_xy(cx, ++cy);
X			break;
X		case ESC:
X			while (esc()) ;
X			if (tx && !(ty == cy && tx == cx)) tx = 0;
X			break;
X		case HT: tx = 0; curs_xy(cx=tab(cx), cy); break;
X		case BS:
X			tx = 0;
X			if (cx > 1) curs_xy(--cx, cy);
X			break;
X		case SO: cset = g1; break;
X		case SI: cset = g0; break;
X/*		case DC1: kbunlck(); break; 	/* XON */
X/*		case DC3: kblock(); break;	/* XOFF */
X		case DC1: rxoff = 0; break;
X		case DC3: if (!ignrflow) rxoff++; break;
X		case BEL:
X			/* might want to have another BEL.
X			 * in the meantime let bios handle it */
X			burpc(c, cx, cy); break;
X		case ENQ: p = ansback; while (*p) xmit(*p++); break;
X		case NUL: break;
X		default:	/* not a special ctrl char? */
X				/* ok burp it, lessee what happens */
X			goto splat;
X			break;	/* not reached */
X		}
X	}
X}
X
X/* handle ctrl chars (from EGETC in esc.c) */
Xdoctrl(c)
Xregister int c;
X{
X	char *p;
X
X	switch (c) {
X	case CR: tx = 0; curs_xy(cx=1, cy); break;
X	case LF: case VT: case FF:
X		tx = 0;
X		if (cy == srgn_bot)
X			if (cy < 24 || srgn_top-1)
X				scrl_up(1, srgn_top, srgn_bot, cx, cy);
X			else
X				burpc(LF, cx, cy);
X		else if (cy < 24)
X			curs_xy(cx, ++cy);
X		break;
X/* NB:	case ESC:  	... not handled here. */
X	case ENQ: p = ansback; while (*p) xmit(*p++); break;
X	case BS:
X		tx = 0;
X		if (cx > 1) curs_xy(--cx, cy);
X		break;
X	case HT: tx = 0; curs_xy(cx=tab(cx), cy); break;
X	case SO: cset = g1; break;
X	case SI: cset = g0; break;
X/*	case DC1: kbunlck(); break; 	/* XON */
X/*	case DC3: kblock(); break;	/* XOFF */
X	case DC1: rxoff = 0; break;
X	case DC3: if (!ignrflow) rxoff++; break;
X	case BEL: /* see BEL comment in term() */
X		burpc(c, cx, cy); break;
X	default:
X		break;
X	}
X}
X
X/*
X * local mode:
X *	"key" output is placed into local input buffer
X *	where it's received and read as "comm" input.
X *	(see devset() for xmit/recv assignments)
X */
X
X/* get more chars into lbuf buffer (called from rloop()) */
Xxtract()
X{
X	int c;
X	char *p;
X
X	while (keyhit) {
X		if ((c = keyg()) & 0xff) {	/* ascii keys */
X			xmit(c);
X			if (m_newline && c == CR)	xmit(LF);
X		}
X		else if ((c = kbdfn(c)) & 0x80) {	/* setup key */
X			setups();
X			if (!local) return(-2);
X		}
X		else if (c & 0x40) {	/* send BREAK or NUL */
X			if (c & 1) xmit(NUL);
X			else send_brk(local);
X		}
X		else {			/* "function" keys */
X			c |= (c & 0x18) ? m_keypad : m_crskey;
X			p = keypadv[c | avofs];
X			while (*p) xmit(*p++);
X			if (rxoff) break;
X		}
X	}
X	return(-1);
X}
X
X/* local mode buffer + buffer indices */
Xint lin, lout;
Xchar lbuf[BUFMAX];
X#define BUFC(a,b)	((a BUFMAX-8) {	/* buffer almost full */
X		rxoff++;		/* probably due to stxt() */
X		lbuf[lin++] = DC1;
X		lin %= BUFMAX;
X	}
X
X	if (transparent && c < SP) {
X		lbuf[lin++] = '^';
X		lin %= BUFMAX;
X		c |= '@';
X	}
X	lbuf[lin++] = c & 0x7f;
X	lin %= BUFMAX;
X}
X
X/* local mode "recv" -- get chars from local input buffer */
Xrloop()
X{
X	int c;
X
X	if (BUFC(lin,lout) > 0) {
X		c = lbuf[lout++];
X		lout %= BUFMAX;
X		return(c);
X	}
X	/* buffer empty so check for more key input */
X	return(xtract());
X}
X
X/* echo mode "xmit" (not used when "local") */
Xxsplit(c)
X{
X	loop_chr(c);	/* insert char into incoming data buffer */
X	xmit_chr(c);	/* send char to host */
X}
X
X
X/*
X * choose devices(ie. procedures) according to current options.
X */
Xdevset()
X{
X	xypos(&cx, &cy);
X	curs_type(cursor);
X	kbautorep(m_repeat);
X	nlmod(m_newline);
X	genstat(cx, cy);
X	init_gfx();
X	if (ignrflow) rxoff = 0;
X	vtidnum = (devrep) ? 1 : 2;	/* see misc.c */
X
X	xmit = (echo) ? xsplit : xmit_chr;
X	recv = (transparent) ? trns_chr : recv_chr;
X
X	if (local) {
X		recv = rloop;
X		xmit = xloop;
X	}
X
X	burp = (m_insert) ? insurpc : burpc;
X	esc = (m_ansi) ? ansi : vt52;
X	keyg = kbdget;
X
X	avofs = (m_ansi) ? ANSOFS : OFS52;
X
X	o_xmit = xmit;
X	o_recv = recv;
X	o_keyg = keyg;
X
X	if (txtxfr)	/* ... then reassign keyg() */
X		txtset();
X}
X
X/*
X * zip -- dummy comm port input function
X * used when XOFF hit (or PAUS (see keybrd.c)) to "freeze" the screen.
X * (depends on flow control to take care of incoming comm data)
X */
Xzip()
X{
X	return(-1);
X}
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'text.c'" '(3105 characters)'
if test -f 'text.c'
then
	echo shar: will not over-write existing file "'text.c'"
else
sed 's/^X//' << \SHAR_EOF > 'text.c'
X/*
X * text.c:
X *	raw ascii text transfer functions
X *
X * copyright (c) University of Toronto, 1988.
X */
X#include 
X
Xstatic int xfd=0;
X
Xunsigned char txtxfr=0;
X
X#define LSZ	255
X	
X#ifdef debug
Xstatic int dfd;
Xstatic char *dp, dbuf[LSZ];
X#endif
X
Xstatic int ln = 0;
Xstatic char *lp, lbuf[LSZ];
Xstatic char prog[16], *opt, fnam[16];
Xstatic int oparms;
Xstatic int sflag, rflag, fdone, bflag, tflag, errflg;
X
X/*
X * text -- text transfer "interface" called from setups()
X *	sets local flags needed by txtset().
X *	checks argument options and the filename.
X */
Xtext(ac, av)
Xint ac;
Xchar *av[];
X{
X	char *p;
X
X	strcpy(prog, av[0]);
X	sflag = rflag = fdone = bflag = tflag = errflg = 0;
X
X	if (ac < 2 || ac > 3)
X		goto usage;
X
X	opt = av[1];
X
X	for (p = opt; *p; p++)
X		switch (*p) {
X		case '$': fdone++; break;
X		case 's': sflag++; break;
X		case 'r': rflag++; break;
X		case 't': tflag++; break;
X		case 'b': bflag++; break;
X		default: errflg++; break;
X		}
X
X	if (errflg || (sflag+rflag) != 1 || (bflag+tflag+fdone) != 1) {
Xusage:
X		cprintf("\
XUsage: %s {st|sb|s$|rt|rb|r$} filename\r\n", prog);
X		cputs("\
X\tst - send text\r\n\
X\tsb - send binary\r\n\
X\ts$ - terminate send (close file)\r\n\
X\trt - receive text\r\n\
X\trb - receive binary\r\n\
X\tr$ - terminate receive\r\n");
X		return(-1);
X	}
X
X	if (fdone) {	/* shutdown rtxt() or stxt() */
X		if (xfd > 0) {
X			if (rflag && ln > 0)
X				write(xfd, lbuf, ln);
X			close(xfd);
X		}
X		txtxfr = xfd = 0;
X		return(0);
X	}
X
X	if (sflag)
X		oparms = O_RDONLY | ((bflag) ? O_BINARY : 0);
X	else
X		oparms = O_WRONLY|O_BINARY|O_CREAT;
X
X	strcpy(fnam, av[2]);
X	if (xfd > 0) close(xfd);
X	if ((xfd = open(fnam, oparms, 0664)) < 0) {
X		perror(fnam);
X		txtxfr = xfd = 0;
X		return(-1);
X	}
X	close(xfd);	/* only wanted to test fnam */
X	cprintf("\r\n%s transfer of %s will begin on exit from setups.\r\n",
X		(tflag) ? "Ascii text" : "Raw data", fnam);
X	txtxfr++;
X	return(0);
X}
X
Xextern unsigned char keyhit, rxoff;
Xextern int (*recv)(), (*o_recv)();
Xextern int (*keyg)(), (*xmit)();
X
X/* prepare files and routines for text transfer */
Xtxtset()
X{
X	int stxt();
X	int rtxt();
X	extern int recv_byt();
X	extern unsigned char local, transparent;
X
X	lp = lbuf; ln = 0;
X
X	if (sflag) {
X		xfd = open(fnam, oparms);
X		ln = read(xfd, lp, LSZ);
X		if (ln < 1 || keyhit) {
X			txtxfr = 0;
X			return;
X		}
X		keyg = stxt;
X		keyhit = ln;
X	}
X	else if (rflag) {
X		recv = rtxt;
X		xfd = open(fnam, oparms, 0664);
X		if (bflag && !(local || transparent))
X			o_recv = recv_byt;	/* was recv_chr */
X	}
X
X	txtxfr = 0;
X}
X
X/* send text */
Xstxt()
X{
X	int n;
X
X	if (rxoff)	/* remote XOFF? ok, take a break */
X		return(0);	
X
X	n = *lp++;
X	if (n == '\n' && tflag) n = '\r';
X
X	if (keyhit != ln) {	/* user hit a key? */
X		close(xfd);
X		xfd = keyhit = 0;
X		devset();
X		return(n);
X	}
X
X	ln--;
X	if (keyhit) keyhit--;
X
X	if (ln < 1) {
X		lp = lbuf;
X		keyhit = ln = read(xfd, lp, LSZ);
X		if (ln < 1) {
X			close(xfd);
X			xfd = keyhit = 0;
X			devset();
X		}
X	}
X	return(n);
X}
X
X/* receive text */
Xrtxt()
X{
X	int n;
X	char c;
X
X	if ((n = o_recv()) < 0)
X		return(n);
X	lbuf[ln] = n; ln++;
X	if (ln >= LSZ) {
X		write(xfd, lbuf, ln);
X		ln = 0;
X	}
X	return(n);
X}
SHAR_EOF
fi # end of overwriting check
#	End of shell archive
exit 0