#ifndef lint
static const char	RCSid[] = "$Id: devmain.c,v 2.5 2016/08/18 00:52:48 greg Exp $";
#endif
/*
 *  devmain.c - main for independent drivers.
 *
 *	Redefine your initialization routine to dinit.
 */

#include "copyright.h"

#include "standard.h"

#include "color.h"

#include "driver.h"

struct driver	*dev = NULL;			/* output device */

FILE	*devin, *devout;			/* communications channels */

char	*progname;				/* driver name */

int	r_clear(), r_paintr(), r_getcur(), r_comout(), r_comin(), r_flush();

int	(*dev_func[NREQUESTS])() = {		/* request handlers */
		r_clear, r_paintr,
		r_getcur, r_comout,
		r_comin, r_flush
	};


main(argc, argv)		/* set up communications and main loop */
int	argc;
char	*argv[];
{
	extern struct driver	*dinit();
	int  com;
						/* set up I/O */
	progname = argv[0];
	if (argc < 3) {
		eputs("arg count\n");
		quit(1);
	}
	devin = fdopen(atoi(argv[1]), "r");
	devout = fdopen(atoi(argv[2]), "w");
	if (devin == NULL || devout == NULL || getw(devin) != COM_SENDM) {
		eputs("connection failure\n");
		quit(1);
	}
						/* open device */
	if ((dev = dinit(argv[0], argv[3])) == NULL)
		quit(1);
	putw(COM_RECVM, devout);		/* verify initialization */
	sendstate();
	fflush(devout);
						/* loop on requests */
	while ((com = getc(devin)) != EOF) {
		if (com >= NREQUESTS || dev_func[com] == NULL) {
			eputs("invalid request\n");
			quit(1);
		}
		(*dev_func[com])();		/* process request */
	}
	quit(0);			/* all done, clean up and exit */
}


void
quit(code)				/* close device and exit */
int	code;
{
	if (dev != NULL)
		(*dev->close)();
	exit(code);
}


r_clear()				/* clear screen */
{
	int	xres, yres;

	xres = getw(devin);
	yres = getw(devin);
	(*dev->clear)(xres, yres);
}


r_paintr()				/* paint a rectangle */
{
	COLOR	col;
	int	xmin, ymin, xmax, ymax;

	getbinary((char *)col, sizeof(COLOR), 1, devin);
	xmin = getw(devin); ymin = getw(devin);
	xmax = getw(devin); ymax = getw(devin);
	(*dev->paintr)(col, xmin, ymin, xmax, ymax);
}


r_flush()				/* flush output */
{
	if (dev->flush != NULL)
		(*dev->flush)();
	putc(COM_FLUSH, devout);
	sendstate();
	fflush(devout);
}


r_getcur()				/* get and return cursor position */
{
	int	c;
	int	x, y;
					/* get it if we can */
	if (dev->getcur == NULL) {
		c = ABORT;
		x = y = 0;
	} else
		c = (*dev->getcur)(&x, &y);
					/* reply */
	putc(COM_GETCUR, devout);
	putc(c, devout);
	putw(x, devout);
	putw(y, devout);
	fflush(devout);
}


r_comout()				/* print string to command line */
{
	char	str[256];

	mygets(str, devin);
	(*dev->comout)(str);
}


r_comin()				/* read string from command line */
{
	char	buf[256], *prompt;
					/* get prompt */
	if (getc(devin)) {
		mygets(buf, devin);
		prompt = buf;
	} else
		prompt = NULL;
					/* get string */
	(*dev->comin)(buf, prompt);
					/* reply */
	putc(COM_COMIN, devout);
	myputs(buf, devout);
	sendstate();
	fflush(devout);
}


mygets(s, fp)				/* get string from file (with nul) */
register char	*s;
register FILE	*fp;
{
	register int	c;

	while ((c = getc(fp)) != EOF)
		if ((*s++ = c) == '\0')
			return;
	*s = '\0';
}


myputs(s, fp)				/* put string to file (with nul) */
register char	*s;
register FILE	*fp;
{
	do
		putc(*s, fp);
	while (*s++);
}


void
eputs(s)				/* put string to stderr */
register char  *s;
{
	static int  midline = 0;

	if (!*s)
		return;
	if (!midline++) {
		fputs(progname, stderr);
		fputs(": ", stderr);
	}
	fputs(s, stderr);
	if (s[strlen(s)-1] == '\n') {
		fflush(stderr);
		midline = 0;
	}
}


sendstate()				/* send driver state variables */
{
	putbinary(&dev->pixaspect, sizeof(dev->pixaspect), 1, devout);
	putw(dev->xsiz, devout);
	putw(dev->ysiz, devout);
	putw(dev->inpready, devout);
}
