/*	TERM5.C		Subroutines for TERM.C - Part 5
			Low level I/O
	14 Feb 1988	A.Herrmann
*/

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


void i_rs232()		/* initializes PIO port B0 and SIO registers	*/
{
	outp(PIOBC,PIOOUT); outp(PIOBD,pio_b0);	/* clock frequency	*/
	outsio(A_CONT,0);			/* Reset SIO		*/
	outsio(B_CONT,2);			/* Intrpt vector (Ch.B)	*/
	outsio(A_CONT,4);			/* Communication params	*/
	outsio(A_CONT,3);			/* Rx parameters	*/
	outsio(A_CONT,5);			/* Tx parameters	*/
	outsio(A_CONT,1);			/* Interrupt mode	*/
}


void outsio(port,reg)	/* sets SIO-port register reg with sio_reg[]	*/
int port,reg;
{
	outp(port,reg);
	outp(port,sio_reg[reg]);
}


#define WR5RTS	0x02
#define WR5DTR	0x80


void stophost()	/* signals host to stop transmission		*/
{
	if (hstppd) return;
	switch (mode) {
	case XONOFF:
		s_rs232(_XOFF);
		break;
	case DTR:
		sio_reg[5] &= ~WR5DTR;		/* clear bit 7 */
		outsio(A_CONT,5);
		break;
	case RTS:
		sio_reg[5] &= ~WR5RTS;		/* clear bit 1 */
		outsio(A_CONT,5);
		break;
	}
	hstppd = TRUE;
}


void wakehost()		/* signals host to resume transmission	*/
{
	if (!hstppd) return;
	switch (mode) {
	case XONOFF:
		s_rs232(_XON);
		break;
	case DTR:
		sio_reg[5] |= WR5DTR;		/* set bit 7 */
		outsio(A_CONT,5);
		break;
	case RTS:
		sio_reg[5] |= WR5RTS;		/* set bit 1 */
		outsio(A_CONT,5);
		break;
	}
	hstppd = FALSE;
}


void defwdw(w,xmin,ymin,xmax,ymax)	/* defines window w */
int w, xmin,ymin,xmax,ymax;
{
	to_wdw(w);			/* switch to window		*/
	pc(_ESC); pc('C');	 	/* set window dimensions	*/
	pc(_BLANK+xmin); pc(_BLANK+ymin);
	pc(_BLANK+xmax); pc(_BLANK+ymax);
	to_wdw(TERWDW); 		/* back to terminal window	*/
}


void to_wdw(w)	/* switches to window w	*/
int w;
{
	pc(_ESC); pc('B'); pc(_BLANK+w);
}


void dissta()	/* disable status line update	*/
{
	pc(_ESC); pc('X');	
}


void enasta()	/* enable status line update	*/
{
	pc(_ESC); pc('W');	
}


void ps(s)	/* outputs string s on console	*/
char *s;
{
	while (*s) pc(*s++);
}


void yx(y,x)	/* Cursor position	*/
short y,x;
{
	pc(_ESC); pc('F'); pc(_BLANK + y); pc(_BLANK + x);
}


gc()	/* returns character from console or NULL if none available;	*/
{
	return _abdos(6,0xFF);
}


void pc(ch)	/* outputs character ch directly on console */
char ch;
{
	_bdos(6,ch);
}


void pt(ch)	/* outputs character ch directly to printer */
char ch;
{
	_bdos(5,ch);
}


#define	FBDECR	1024			/* file buffer decrement	*/
#define FBSIZE	32*FBDECR		/* file buffer size		*/

static char *fbp;			/* file buffer pointers		*/
static char *fbbeg=NULL, *fbend;


int initfb()	/* initializes file buffer; Returns true buffer size	*/
		/* Note: Only one buffer can be open at a time!		*/
{
	static int fblen;
	char *alloc();

	if (fbbeg) return NULL;		/* Buffer already opened?	*/
	fblen = FBSIZE; 
	while ((fbbeg=fbp=alloc(fblen))==NULL && (fblen -=FBDECR) != 0) ;
	fbend = fbbeg + fblen - 1;
	return fblen;
}

	
FILE *iofopen(name,mode)	/* opens input/output file name in mode	*/
char *name, *mode;		/* Inits file buffer			*/
				/* Returns file pointer / NULL if error */
{
	if (initfb()) return fopen(name,mode);
	return NULL;
}


int iofclose(fp,item)		/* flushes IO file buffer and closes file fp */
FILE **fp;			/* Resets file pointer fp to NULL	     */
int item;			/* Returns EOF iff error		     */
{
	if ((item==IFITEM || flushfb()) && fclose(*fp)!=EOF) {
		free(fbbeg);
		return (fbbeg = *fp = NULL);
	}
	return EOF;
}


int gf()	/* gets next character ch from input file		*/
		/* Returns EOF on EOF or error, else ch			*/
		/* Note: LFs from input file are suppressed here	*/
{
	static int ch;

	do {
		if (fbp==fbbeg && !loadfb()) return EOF;
		ch = *fbp++;
		if (fbp>fbend) fbp = fbbeg;
	} while (ch==_LF && !passlf);
	return ch;
}


int loadfb()	/* loads buffer with next input file segment	*/
		/* beginning at fbbeg				*/
		/* Returns FALSE iff no input, else TRUE	*/
{
	static int c;
	static char *p;

	stophost();
	p=fbbeg;
	do {
		c=getc(input);		/* It's gotta be integer!	*/
		*p++=c;
	} while (p<=fbend && c!=EOF); 
	if (bufclr) wakehost();
	return (p!=fbbeg);
}


int pf(ch)	/* outputs character ch to output file	*/
char ch;	/* Returns EOF on error, else ch	*/
{
	*fbp++ = ch;
	if (fbp>fbend && !flushfb()) return EOF;
	return ch;
}


int flushfb()	/* flushes current IO file buffer to file	 */
		/* beginning at fbbeg up to, but NOT incl. fbp */
		/* Returns FALSE iff output error, else TRUE	 */
{
	static char *p;
	static int c;

	stophost();
	c = NULL;
	for (p=fbbeg; p<fbp && (c=putc(*p,output))!=EOF; p++) ;
	fbp = fbbeg;
	if (bufclr) wakehost();
	return (c!=EOF);
}
