#ifndef lint
static char sccsid[] = "@(#)dbbc1.c	1.9 (mg@ukc) 11/8/88";
#endif
/*
 *	dbbc
 *	Ditroff driver for BBC micro with UKC terminal emulator ROM
 *	Martin Guy. UKC. December 1984
 *	"Adapted" from dsan.c
 *
 *	-d flags:
 *	1	List bbc commands as called (in bbcplot.c)
 */

#include	<stdio.h>
#include	<ctype.h>
#include	"dev.h"		/* for struct dev in fileinit() */
#include	"bbcplot.h"
#include	"dbbc.h"

int	nolist	= 0;	/* output page list if > 0 */
int	olist[20];	/* pairs of page numbers */

int	paperwidth;
int	paperlength;
int	byteorder;	/* byte-ordering in a two-char character constant */

char	*fontdir	= "/usr/lib/font";
char	devname[20];

char stdoutbuf[1024];	/* To get round stdios inefficient line buffering */

#ifdef DEBUG
int	debug = 0;
#endif

main(argc, argv)
char *argv[];
{
	register int fromfile = 0;
	register FILE *ifp; /* input file pointer */

	setbuffer(stdout, stdoutbuf, sizeof(stdoutbuf));
	switch ('AB') {
	case ('A'*256 + 'B'):
		byteorder = BO_HL;
		break;
	case ('A' + 'B'*256):
		byteorder = BO_LH;
		break;
	default:
		fputs("dbbc: Can't figure out byte ordering. Take me to mg!\n", stderr);
		exit(1);
	}
	--argc; ++argv;
	while (argc > 0 ) {
		if (argv[0][0] == '-') {
			switch (argv[0][1]) {
			case 'o':
				outlist(&argv[0][2]);
				break;
#ifdef DEBUG
			case 'd':
				debug = atoi(&argv[0][2]);
				if (debug==0) debug = ~0;	/* everything */
				break;
#endif
			case '\0':
				fromfile = 1;
				conv(stdin);
				break;
			default:
usage:			      error("Usage: dbbc [-olist] [file] ...");
			}
		} else {
			fromfile = 1;
			ifp = fopen(*argv,"r");
			if (ifp == NULL) {
				char str[32];
				(void) sprintf(str,"dbbc: Cannot open %s",*argv);
				error(str);
			} else {
				conv(ifp);
				(void) fclose(ifp);
			}
		}
		argc--;
		argv++;
	}

	if (!fromfile) {
		/* If they really want to, they can use "dbbc -" */
		if (isatty(0)) goto usage;
		conv(stdin);
	}
	done();
}

/*
 *	Process list of page numbers to be printed
 */
outlist(s)
char *s;
{
	register int n1, n2;

	nolist = 0;
	while (*s) {
		n1 = 0;
		if (isdigit(*s))
			do
				n1 = 10 * n1 + *s++ - '0';
			while (isdigit(*s));
		else
			n1 = -9999;
		n2 = n1;
		if (*s == '-') {
			s++;
			n2 = 0;
			if (isdigit(*s))
				do
					n2 = 10 * n2 + *s++ - '0';
				while (isdigit(*s));
			else
				n2 = 9999;
		}
		olist[nolist++] = n1;
		olist[nolist++] = n2;
		if (*s != '\0')
			s++;
	}
	olist[nolist] = 0;
}

in_olist(n)
int n;
{
	int i;

	if (nolist == 0)
		return(1);	/* everything is included */
	for (i = 0; i < nolist; i += 2)
		if (n >= olist[i] && n <= olist[i+1])
			return(1);
	return(0);
}

conv(fp)
register FILE *fp;
{
	register int c, k;
	int m, n, m1, n1;
	char str[100], buf[300];

	/* Check for DIL: is first line "x T ???"? */
	c = getc(fp);
	(void) fscanf(fp, "%s", buf);
	if (c != 'x' || buf[0] != 'T') {
		error("Input is not Ditroff intermediate");
	}
	(void) fscanf(fp, "%s", devname);
	fileinit();

	while ((c = getc(fp)) != '\n')	/* skip rest of input line */
		if (c == EOF)
			break;

	while ((c = getc(fp)) != EOF) {
		switch (c) {
		case '\n':	/* when input is text */
		case ' ':
			break;
		case '0': case '1': case '2': case '3': case '4':
		case '5': case '6': case '7': case '8': case '9':
			/* two motion digits plus a character */
			hmot((c-'0')*10 + getc(fp)-'0');
			put1(getc(fp));
			break;
		case 'c':	/* single ascii character */
			put1(getc(fp));
			break;
		case 'C':
			(void) fscanf(fp, "%s", str);
			put1s(str);
			break;
		case 'D':	/* draw function */
			(void) fgets(buf, sizeof(buf), fp);
			switch (buf[0]) {
			case 'l':	/* draw a line */
				(void) sscanf(buf+1, "%d %d", &n, &m);
				t_line(n, m);
				break;
			case 'c':	/* circle */
				(void) sscanf(buf+1, "%d", &n);
				drawcirc(n);
				break;
			case 'e':	/* ellipse */
				(void) sscanf(buf+1, "%d %d", &m, &n);
				drawellip(m, n);
				break;
			case 'a':	/* arc */
				(void) sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1);
				drawarc(n, m, n1, m1);
				break;
			case '~':	/* wiggly line */
				drawwig(buf+1);
				break;
			}
			break;
		case 's':
			(void) fscanf(fp, "%d", &n);	/* ignore fractional sizes */
			break;
		case 'f':
			(void) fscanf(fp, "%s", str);
			break;
		case 'H':	/* absolute horizontal motion */
			/* (void) fscanf(fp, "%d", &n); */
			while ((c = getc(fp)) == ' ')
				;
			k = 0;
			do {
				k = 10 * k + c - '0';
			} while (isdigit(c = getc(fp)));
			(void) ungetc(c, fp);
			hgoto(k);
			break;
		case 'h':	/* relative horizontal motion */
			/* (void) fscanf(fp, "%d", &n); */
			while ((c = getc(fp)) == ' ')
				;
			k = 0;
			do {
				k = 10 * k + c - '0';
			} while (isdigit(c = getc(fp)));
			(void) ungetc(c, fp);
			hmot(k);
			break;
		case 'w':	/* word space */
			break;
		case 'V':
			(void) fscanf(fp, "%d", &n);
			vgoto(n);
			break;
		case 'v':
			(void) fscanf(fp, "%d", &n);
			vmot(n);
			break;
		case 'p':	/* new page */
			(void) fscanf(fp, "%d", &n);
			t_page(n,fp);
			break;
		case 'n':	/* end of line */
		case 'x':	/* device control */
			devctrl(fp);
		case '#':	/* comment */
			while ((c=getc(fp)) != '\n')
				if (c == EOF) break;
			break;
		default:
			(void) sprintf(str, "unknown input character %o %c", c, c);
			error(str);
		}
	}
}

devctrl(fp)
FILE *fp;
{
	(void) getc(fp);	/* Dump the space */
	switch (getc(fp)) {
	case 's':	/* x stop */
		/* Included for tail +0f file.i | dbbc */
		fflush(stdout);
		break;
	}
	/* Caller must gobble rest of line */
}

/*
 *	Read in font and code files etc.
 */
fileinit()
{
	int fin;
	char temp[60];
	struct dev dev;

	/* open table for device, and set params */
	(void) sprintf(temp, "%s/dev%s/DESC.out", fontdir, devname);
	if ((fin = open(temp, 0)) < 0) {
		char str[64];
		(void) sprintf(str, "can't open tables for %s", temp);
		error(str);
	}
	(void) read(fin, (char *)&dev, sizeof(struct dev));
	paperwidth = dev.paperwidth;
	paperlength = dev.paperlength;
	if (paperwidth==0 || paperlength==0) {
		char str[64];
		(void) sprintf(str, "size of paper not specified in DESC file for %s (please report)", devname);
		error(str);
	}
	(void) close(fin);
}
