/*	TERM.C		Terminal emulation on the ELZET80

	19 Feb 1988	A.Herrmann

	This program was originally based on program TERMINAL.C 
	that I received from ELEKTRONIKLADEN in October 1985.
	It has, however, undergone extensive changes ever since 
	I started really needing it for connecting up to the SB180.
	
	TERM emulates a terminal using the RS323 printer port on the
	ELZET CPU/IEC board as the terminal line.
	SIO input is interrupt driven to keep up with incoming chars
	at higher baud rates.
	Screen output is geared towards the VIDEO80 board;
	optionally, some of the (ANSI) functionality of a VT100 can 
	be emulated with TERM.

	The following communication parameters can be selected.
		Parameter:	Alternatives:			Default:
		Xon/Xoff	XON , ---			XON
		Input file	< filename			----------
		Output file	> filename			----------
		File format	ASC , BIN			BIN
		LF after CR	-- , LF				LF
		Local echo	-- , EC				--
		Control chars	IC (Interpret), DC (Display)	IC
		VT100 emul.	-- , VT				--
		Character set	C0 , C1				C0
		Printer log	-- , PR				--
		Protocol	--- , RTS , DTR , XON		RTS
		Baud rate	300,1200,2400,9600		9600
		Bits/char	5 , 6 , 7 , 8			8
		Stop bits	1 , 2	 			1
		Parity		-- (None), PE (Even), PO (Odd)	--

	The communication parameter alternatives are stored in structure
	items; current values are determined by index items.ind.

	To change the communication parameters switch from 
	terminal mode into setup mode by pressing Ctrl/^.
	The current settings appear in window #2 which temporarily
	overlays the ELZET status line window #1. Therefore,
	updating of the ELZET status line is disabled when
	TERM is using this screen area.
	In setup mode input and output file names can be
	entered directly but must be followed by a RETURN.
	Settings of the other parameters are toggled by 
	pressing the SPACE bar.
	You can go back and forth between parameters using 
	BACKSPACE and RETURN.
	Ctrl/C in setup mode exits the program;	
	Ctrl/^ or ESC switches back to terminal mode.

	Screen output in terminal mode goes to window #0 
	which has 24 lines of 80 columns.

Note:	After exiting TERM, in order to	be able to use the 
	RS232 as a printer port again you'll have to reboot
	the system.
*/


#include "stdio.h"
#include "term.h"


/*  Static variables, defined as external in file TERM.E */

FILE *input = NULL;	/* current input file			*/
FILE *output = NULL;	/* current output file			*/
int format;		/* current file format			*/
int mode;		/* current protocol			*/
int mask;		/* current character mask		*/
int cset;		/* current character set		*/
int bufclr;		/* TRUE iff enough space in input buffer*/
int hstppd = FALSE;	/* TRUE iff host is stopped		*/
int xonkey;		/* TRUE iff Xon/Xoff enabled		*/
int passlf;		/* TRUE iff LF after CR			*/
int echo;		/* TRUE iff local echo on		*/
int dspctl;		/* TRUE iff control chars to display	*/
int vtemul;		/* TRUE iff VT100 (ANSI) emulation	*/
int vtinit;		/* TRUE iff VT100 parser needs init	*/
int prtlog;		/* TRUE iff printer is on		*/

char pio_b0=0;		/* PIO output for Baudrate selection		*/

char sio_reg[] = {	/* SIO registers; sample settings:		*/
	0x18,		/* Channel reset				*/
	0x18,		/* Interrupt on all Rx chars			*/
	0xD0,		/* Interrupt vector low byte			*/
	0xC1,		/* 8 bit/Rx Char, Rx enable			*/
	0x44,		/* 16x clock (=9600 bd), 1 Stopbit, no parity	*/
	0x6A,		/* no DTR, 8 bit/Tx char, Tx enable, RTS	*/
	0x00,		/* not used in asynchronous mode		*/
	0x00		/* ditto.					*/
  };

/* External functions for selecting parameter alternatives */

extern ALTFCT xonsw;
extern ALTFCT infil;
extern ALTFCT outfil;
extern ALTFCT fform;
extern ALTFCT lfsw;
extern ALTFCT echosw;
extern ALTFCT ctlcsw;
extern ALTFCT emulsw;
extern ALTFCT csetsw;
extern ALTFCT prntsw;
extern ALTFCT proto;
extern ALTFCT baud;
extern ALTFCT bpch;
extern ALTFCT stop;
extern ALTFCT parity;

/* Table of communication parameter settings */

struct items {
	int pos;		/* position in status line		*/
	int len;		/* length of field in status line	*/ 
	ALTFCT fct;		/* function to select alternatives	*/
	int ind;		/* currently selected alternative	*/
	int nra;		/* number of alternatives		*/
	char *alt[MAXALT];	/* values of alternatives		*/
} par[] = {
	{  0, 3, xonsw,  1, 2, { "---","XON" } },	/* Xon/Xoff key	*/
	{  5,14, infil,  0, 1, { "--------------" } },	/* Input file	*/
	{ 22,14, outfil, 0, 1, { "--------------" } },	/* Output file	*/
	{ 38, 3, fform,  1, 2, { "ASC","BIN" } },	/* File format	*/
	{ 42, 2, lfsw,   1, 2, { "--","LF" } },		/* LF after CR	*/
	{ 45, 2, echosw, 0, 2, { "--","EC" } },		/* Echo off/on	*/
	{ 48, 2, ctlcsw, 0, 2, { "IC","DC" } },		/* Intp/Disp Ctl*/
	{ 51, 2, emulsw, 0, 2, { "--","VT" } },		/* VT100 emul.	*/
	{ 54, 2, csetsw, 0, 2, { "C0","C1" } },		/* Character set*/
	{ 57, 2, prntsw, 0, 2, { "--","PR" } },		/* Print on/off */
	{ 61, 3, proto,  1, 4, { "---","RTS",		/* Protocol	*/
				 "DTR","XON" } },
	{ 65, 4, baud,   3, 4, { " 300","1200",		/* Baud rate	*/
			 	 "2400","9600" } },
	{ 72, 1, bpch,   3, 4, { "5","6","7","8" } },	/* Bits per char*/
	{ 74, 1, stop,   0, 2, { "1","2" } },		/* Stop bits	*/
	{ 76, 2, parity, 0, 3, { "--","PE","PO" } }	/* Parity	*/
};
char ruler[] ="\
... <..............  >..............  ... .. .. .. .. .. ..  ... ....bd ./. ..";/*
^    ^                ^               ^   ^  ^  ^  ^  ^  ^   ^   ^      ^   ^
0    5                22              38  42 45 48 51 54 57  61  65     72  76
*/


main()	/* Program loops indefinitely until CTRLC is entered in setup mode */
	/* Program exits thru function finis() called in newpar()	   */
{
	static int no,ind;		/* communication par.number, index */
	extern void ioloop();

	defwdw(STAWDW,STCMIN,STLMIN,STCMAX,STLMAX);	/* def.setup window */
	for (no=0; no<MAXITEM; no++) {		/* init comm.parameters	*/
		ind = par[no].ind;		/* current alternative	*/
		cpitem(par[no].alt[ind],no);	/* copy into status line*/
		if (no!=IFITEM && no!=OFITEM)
			(*par[no].fct)(ind);	/* change settings	*/
	}
	install();				/* inst.SIO input buffer*/
	intrpt();				/* and SIO intrpt 	*/
	pc(_FF);				/* clear screen		*/
	ioloop();				/* do IO until ABORT	*/
}

void finis()		/* cleans up and exits to CP/M	*/
{
	if (input) closefile(&input,IFITEM);
	if (output) closefile(&output,OFITEM);
	enasta();			/* enable status line update	*/
	unintrpt();			/* undefine SIO interrupt	*/
	pc(_FF);
	exit();
}


void intrpt()		/* defines interrupt mode for the SIO	*/
{
	sio_reg[1] = 0x18;
	sio_reg[2] = 0xD0;
	sioswap();
}


void unintrpt()		/* undefines interrupt mode for the SIO	*/
{
	sio_reg[1] = sio_reg[2] = 0;
	sioswap();
}
