1*b8908d5bSslatteng /* @(#)dterm.c	1.14	(Berkeley)	02/26/85"
2af45d5e6Sslatteng  *
3af45d5e6Sslatteng  *	Converts ditroff output to text on a terminal.  It is NOT meant to
4af45d5e6Sslatteng  *	produce readable output, but is to show one how one's paper is (in
5af45d5e6Sslatteng  *	general) formatted - what will go where on which page.
6af45d5e6Sslatteng  *
7af45d5e6Sslatteng  *	options:
8af45d5e6Sslatteng  *
9af45d5e6Sslatteng  *	  -hn	set horizontal resolution to n (in characters per inch;
10af45d5e6Sslatteng  *		default is 10.0).
11af45d5e6Sslatteng  *
12af45d5e6Sslatteng  *	  -vn	set vertical resolution (default is 6.0).
13af45d5e6Sslatteng  *
14af45d5e6Sslatteng  *	  -ln	set maximum output line-length to n (default is 79).
15af45d5e6Sslatteng  *
16af45d5e6Sslatteng  *	-olist	output page list - as in troff.
17af45d5e6Sslatteng  *
18af45d5e6Sslatteng  *	  -c	continue at end of page.  Default is to stop at the end
19af45d5e6Sslatteng  *		of each page, print "dterm:" and wait for a command.
20af45d5e6Sslatteng  *		Type ? to get a list of available commands.
21af45d5e6Sslatteng  *
22ce133b5eSslatteng  *	  -m	print margins.  Default action is to cut printing area down
23ce133b5eSslatteng  *		to only the part of the page with information on it.
24ce133b5eSslatteng  *
25083ff42bSslatteng  *	  -a	make the output readable - i.e. print like a "troff -a" with
26083ff42bSslatteng  *		no character overlap, and one space 'tween words
27083ff42bSslatteng  *
286e5cc3e6Sslatteng  *	  -L	put a form feed (^L) at the end of each page
296e5cc3e6Sslatteng  *
30ce133b5eSslatteng  *	  -w	sets h = 20, v = 12, l = 131, also sets -c, -m and -L to allow
316e5cc3e6Sslatteng  *		for extra-wide printouts on the printer.
3218573097Sslatteng  *
3318573097Sslatteng  *	-fxxx	get special character definition file "xxx".  Default is
34*b8908d5bSslatteng  *		FONTDIR/devter/specfile.
35af45d5e6Sslatteng  */
36af45d5e6Sslatteng 
37af45d5e6Sslatteng 
38af45d5e6Sslatteng #include	<stdio.h>
39af45d5e6Sslatteng #include	<ctype.h>
40af45d5e6Sslatteng #include	<math.h>
41af45d5e6Sslatteng 
42af45d5e6Sslatteng 
43af45d5e6Sslatteng #define	FATAL		1
44bb5743b1Sslatteng #define	PGWIDTH		266		/* WAY too big - for good measure */
45bb5743b1Sslatteng #define	PGHEIGHT	220
46af45d5e6Sslatteng #define LINELEN		78
47*b8908d5bSslatteng #define SPECFILE	"devter/specfile"
48*b8908d5bSslatteng #ifndef FONTDIR
49*b8908d5bSslatteng #define FONTDIR		"/usr/lib/font"
50*b8908d5bSslatteng #endif
51af45d5e6Sslatteng 
52af45d5e6Sslatteng #define hgoto(n)	hpos = n
53af45d5e6Sslatteng #define vgoto(n)	vpos = n
54af45d5e6Sslatteng #define hmot(n)		hpos += n
55af45d5e6Sslatteng #define vmot(n)		vpos += n
56af45d5e6Sslatteng 
57af45d5e6Sslatteng #define	sgn(n)		((n > 0) ? 1 : ((n < 0) ? -1 : 0))
58af45d5e6Sslatteng #define	abs(n)		((n) >= 0 ? (n) : -(n))
59af45d5e6Sslatteng #define	max(x,y)	((x) > (y) ? (x) : (y))
60af45d5e6Sslatteng #define	min(x,y)	((x) < (y) ? (x) : (y))
61af45d5e6Sslatteng #define sqr(x)		(long int)(x)*(x)
62af45d5e6Sslatteng 
63af45d5e6Sslatteng 
64*b8908d5bSslatteng char	SccsId [] = "@(#)dterm.c	1.14	(Berkeley)	02/26/85";
65af45d5e6Sslatteng 
6618573097Sslatteng char	**spectab;		/* here go the special characters */
67*b8908d5bSslatteng char	specfile[100] = FONTDIR;/* place to look up special characters */
6818573097Sslatteng char	*malloc();
696e5cc3e6Sslatteng char	*operand();
70af45d5e6Sslatteng 
71bb5743b1Sslatteng int 	keepon	= 0;	/* flags:  Don't stop at the end of each page? */
72bb5743b1Sslatteng int	clearsc = 0;		/* Put out form feed at each page? */
73bb5743b1Sslatteng int	output	= 0;		/* Do we do output at all? */
74bb5743b1Sslatteng int	nolist	= 0;		/* Output page list if > 0 */
75ce133b5eSslatteng int	margin	= 0;		/* Print blank margins? */
76083ff42bSslatteng int	ascii	= 0;		/* make the output "readable"? */
77af45d5e6Sslatteng int	olist[20];		/* pairs of page numbers */
78af45d5e6Sslatteng 
7918573097Sslatteng float	hscale	= 10.0;		/* characters and lines per inch for output */
8018573097Sslatteng float	vscale	= 6.0;		/*	device (defaults are for printer) */
81af45d5e6Sslatteng FILE	*fp = stdin;		/* input file pointer */
82af45d5e6Sslatteng 
83af45d5e6Sslatteng char	pagebuf[PGHEIGHT][PGWIDTH];
84af45d5e6Sslatteng int	minh	= PGWIDTH;
85af45d5e6Sslatteng int	maxh	= 0;
86af45d5e6Sslatteng int	minv	= PGHEIGHT;
87af45d5e6Sslatteng int	maxv	= 0;
88af45d5e6Sslatteng int	linelen = LINELEN;
89af45d5e6Sslatteng 
90af45d5e6Sslatteng int	hpos;		/* horizontal position to be next (left = 0) */
91af45d5e6Sslatteng int	vpos;		/* current vertical position (down positive) */
92af45d5e6Sslatteng 
93af45d5e6Sslatteng int	np;		/* number of pages seen */
94af45d5e6Sslatteng int	npmax;		/* high-water mark of np */
95af45d5e6Sslatteng int	pgnum[40];	/* their actual numbers */
96af45d5e6Sslatteng long	pgadr[40];	/* their seek addresses */
97af45d5e6Sslatteng 
9818573097Sslatteng int	DP;			/* step size for drawing */
99bb5743b1Sslatteng int	maxdots	= 3200;		/* maximum number of dots in an object */
100af45d5e6Sslatteng 
101af45d5e6Sslatteng 
102af45d5e6Sslatteng 
main(argc,argv)103af45d5e6Sslatteng main(argc, argv)
104af45d5e6Sslatteng int argc;
105af45d5e6Sslatteng char **argv;
106af45d5e6Sslatteng {
107*b8908d5bSslatteng 	strcat(specfile, "/");
108*b8908d5bSslatteng 	strcat(specfile, SPECFILE);
1096e5cc3e6Sslatteng 	while (--argc > 0 && **++argv == '-') {
1106e5cc3e6Sslatteng 	    switch ((*argv)[1]) {
11118573097Sslatteng 		case 'f':		/* special character filepath */
112*b8908d5bSslatteng 			strncpy(specfile, operand(&argc, &argv), 100);
11318573097Sslatteng 			break;
11418573097Sslatteng 		case 'l':		/* output line length */
1156e5cc3e6Sslatteng 			linelen = atoi(operand(&argc, &argv)) - 1;
116af45d5e6Sslatteng 			break;
11718573097Sslatteng 		case 'h':		/* horizontal scale (char/inch) */
1186e5cc3e6Sslatteng 			hscale = atof(operand(&argc, &argv));
119af45d5e6Sslatteng 			break;
12018573097Sslatteng 		case 'v':		/* vertical scale (char/inch) */
1216e5cc3e6Sslatteng 			vscale = atof(operand(&argc, &argv));
122af45d5e6Sslatteng 			break;
12318573097Sslatteng 		case 'o':		/* output list */
1246e5cc3e6Sslatteng 			outlist(operand(&argc, &argv));
125af45d5e6Sslatteng 			break;
126bb5743b1Sslatteng 		case 'c':		/* continue at endofpage */
1276e5cc3e6Sslatteng 			keepon = !keepon;
128af45d5e6Sslatteng 			break;
129ce133b5eSslatteng 		case 'm':		/* print margins */
130ce133b5eSslatteng 			margin = !margin;
131ce133b5eSslatteng 			break;
132083ff42bSslatteng 		case 'a':		/* readable mode */
133083ff42bSslatteng 			ascii = !ascii;
134083ff42bSslatteng 			break;
135bb5743b1Sslatteng 		case 'L':		/* form feed after each page */
1366e5cc3e6Sslatteng 			clearsc = !clearsc;
137bb5743b1Sslatteng 			break;
138bb5743b1Sslatteng  		case 'w':		/* "wide" printer format */
139b15ec68bSslatteng 			hscale = 16.0;
140b15ec68bSslatteng 			vscale = 9.6;
141af45d5e6Sslatteng 			linelen = 131;
142af45d5e6Sslatteng 			keepon = 1;
143bb5743b1Sslatteng 			clearsc = 1;
144af45d5e6Sslatteng 			break;
145af45d5e6Sslatteng 	    }
146af45d5e6Sslatteng 	}
147af45d5e6Sslatteng 
1486e5cc3e6Sslatteng 	if (argc < 1)
149af45d5e6Sslatteng 		conv(stdin);
150af45d5e6Sslatteng 	else
1516e5cc3e6Sslatteng 		while (argc--) {
152af45d5e6Sslatteng 			if (strcmp(*argv, "-") == 0)
153af45d5e6Sslatteng 				fp = stdin;
154af45d5e6Sslatteng 			else if ((fp = fopen(*argv, "r")) == NULL)
155af45d5e6Sslatteng 				error(FATAL, "can't open %s", *argv);
156af45d5e6Sslatteng 			conv(fp);
157af45d5e6Sslatteng 			fclose(fp);
158af45d5e6Sslatteng 			argv++;
159af45d5e6Sslatteng 		}
160af45d5e6Sslatteng 	done();
161af45d5e6Sslatteng }
162af45d5e6Sslatteng 
163af45d5e6Sslatteng 
1646e5cc3e6Sslatteng /*----------------------------------------------------------------------------*
1656e5cc3e6Sslatteng  | Routine:	char  * operand (& argc,  & argv)
1666e5cc3e6Sslatteng  |
1676e5cc3e6Sslatteng  | Results:	returns address of the operand given with a command-line
1686e5cc3e6Sslatteng  |		option.  It uses either "-Xoperand" or "-X operand", whichever
1696e5cc3e6Sslatteng  |		is present.  The program is terminated if no option is present.
1706e5cc3e6Sslatteng  |
1716e5cc3e6Sslatteng  | Side Efct:	argc and argv are updated as necessary.
1726e5cc3e6Sslatteng  *----------------------------------------------------------------------------*/
1736e5cc3e6Sslatteng 
operand(argcp,argvp)1746e5cc3e6Sslatteng char *operand(argcp, argvp)
1756e5cc3e6Sslatteng int * argcp;
1766e5cc3e6Sslatteng char ***argvp;
1776e5cc3e6Sslatteng {
1786e5cc3e6Sslatteng 	if ((**argvp)[2]) return(**argvp + 2); /* operand immediately follows */
1796e5cc3e6Sslatteng 	if ((--*argcp) <= 0) {			/* operand next word */
1806e5cc3e6Sslatteng 	    fprintf (stderr, "command-line option operand missing.\n");
1816e5cc3e6Sslatteng 	    exit(1);
1826e5cc3e6Sslatteng 	}
1836e5cc3e6Sslatteng 	return(*(++(*argvp)));			/* no operand */
1846e5cc3e6Sslatteng }
1856e5cc3e6Sslatteng 
1866e5cc3e6Sslatteng 
outlist(s)187af45d5e6Sslatteng outlist(s)	/* process list of page numbers to be printed */
188af45d5e6Sslatteng char *s;
189af45d5e6Sslatteng {
190af45d5e6Sslatteng 	int n1, n2, i;
191af45d5e6Sslatteng 
192af45d5e6Sslatteng 	nolist = 0;
193af45d5e6Sslatteng 	while (*s) {
194af45d5e6Sslatteng 		n1 = 0;
195af45d5e6Sslatteng 		if (isdigit(*s))
196af45d5e6Sslatteng 			do
197af45d5e6Sslatteng 				n1 = 10 * n1 + *s++ - '0';
198af45d5e6Sslatteng 			while (isdigit(*s));
199af45d5e6Sslatteng 		else
200af45d5e6Sslatteng 			n1 = -9999;
201af45d5e6Sslatteng 		n2 = n1;
202af45d5e6Sslatteng 		if (*s == '-') {
203af45d5e6Sslatteng 			s++;
204af45d5e6Sslatteng 			n2 = 0;
205af45d5e6Sslatteng 			if (isdigit(*s))
206af45d5e6Sslatteng 				do
207af45d5e6Sslatteng 					n2 = 10 * n2 + *s++ - '0';
208af45d5e6Sslatteng 				while (isdigit(*s));
209af45d5e6Sslatteng 			else
210af45d5e6Sslatteng 				n2 = 9999;
211af45d5e6Sslatteng 		}
212af45d5e6Sslatteng 		olist[nolist++] = n1;
213af45d5e6Sslatteng 		olist[nolist++] = n2;
214af45d5e6Sslatteng 		if (*s != '\0')
215af45d5e6Sslatteng 			s++;
216af45d5e6Sslatteng 	}
217af45d5e6Sslatteng 	olist[nolist] = 0;
218af45d5e6Sslatteng }
219af45d5e6Sslatteng 
220af45d5e6Sslatteng 
in_olist(n)221af45d5e6Sslatteng in_olist(n)	/* is n in olist? */
222af45d5e6Sslatteng int n;
223af45d5e6Sslatteng {
224af45d5e6Sslatteng 	int i;
225af45d5e6Sslatteng 
226af45d5e6Sslatteng 	if (nolist == 0)
227af45d5e6Sslatteng 		return(1);	/* everything is included */
228af45d5e6Sslatteng 	for (i = 0; i < nolist; i += 2)
229af45d5e6Sslatteng 		if (n >= olist[i] && n <= olist[i+1])
230af45d5e6Sslatteng 			return(1);
231af45d5e6Sslatteng 	return(0);
232af45d5e6Sslatteng }
233af45d5e6Sslatteng 
234af45d5e6Sslatteng 
conv(fp)235af45d5e6Sslatteng conv(fp)
236af45d5e6Sslatteng register FILE *fp;
237af45d5e6Sslatteng {
238af45d5e6Sslatteng 	register int c;
239af45d5e6Sslatteng 	int m, n, i, n1, m1;
240af45d5e6Sslatteng 	char str[100], buf[300];
241af45d5e6Sslatteng 
242af45d5e6Sslatteng 	while ((c = getc(fp)) != EOF) {
243af45d5e6Sslatteng 		switch (c) {
244af45d5e6Sslatteng 		case '\n':	/* when input is text */
245af45d5e6Sslatteng 		case '\t':
246af45d5e6Sslatteng 		case ' ':
247af45d5e6Sslatteng 		case 0:
248af45d5e6Sslatteng 			break;
249af45d5e6Sslatteng 
250af45d5e6Sslatteng 		case '0': case '1': case '2': case '3': case '4':
251af45d5e6Sslatteng 		case '5': case '6': case '7': case '8': case '9':
252af45d5e6Sslatteng 				/* two motion digits plus a character */
253083ff42bSslatteng 			if (ascii) {
254083ff42bSslatteng 			    hmot((int)hscale);
255083ff42bSslatteng 			    getc(fp);
256083ff42bSslatteng 			} else {
257af45d5e6Sslatteng 			    hmot((c-'0')*10 + getc(fp)-'0');
258083ff42bSslatteng 			}
259af45d5e6Sslatteng 			put1(getc(fp));
260af45d5e6Sslatteng 			break;
261af45d5e6Sslatteng 
262af45d5e6Sslatteng 		case 'c':	/* single ascii character */
263af45d5e6Sslatteng 			put1(getc(fp));
264af45d5e6Sslatteng 			break;
265af45d5e6Sslatteng 
266af45d5e6Sslatteng 		case 'C':	/* funny character */
267af45d5e6Sslatteng 			fscanf(fp, "%s", str);
268af45d5e6Sslatteng 			put1s(str);
269af45d5e6Sslatteng 			break;
270af45d5e6Sslatteng 
271af45d5e6Sslatteng 		case 't':	/* straight text */
272af45d5e6Sslatteng 			fgets(buf, sizeof(buf), fp);
273af45d5e6Sslatteng 			t_text(buf);
274af45d5e6Sslatteng 			break;
275af45d5e6Sslatteng 
276af45d5e6Sslatteng 		case 'D':	/* draw function */
277af45d5e6Sslatteng 			fgets(buf, sizeof(buf), fp);
278af45d5e6Sslatteng 			switch (buf[0]) {
279af45d5e6Sslatteng 			case 'l':	/* draw a line */
280af45d5e6Sslatteng 				sscanf(buf+1, "%d %d", &n, &m);
2815839e65eSslatteng 				drawline(n, m);
282af45d5e6Sslatteng 				break;
283af45d5e6Sslatteng 			case 'c':	/* circle */
284af45d5e6Sslatteng 				sscanf(buf+1, "%d", &n);
285af45d5e6Sslatteng 				drawcirc(n);
286af45d5e6Sslatteng 				break;
287af45d5e6Sslatteng 			case 'e':	/* ellipse */
288af45d5e6Sslatteng 				sscanf(buf+1, "%d %d", &m, &n);
289af45d5e6Sslatteng 				drawellip(m, n);
290af45d5e6Sslatteng 				break;
291af45d5e6Sslatteng 			case 'a':	/* arc */
292af45d5e6Sslatteng 				sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1);
293af45d5e6Sslatteng 				drawarc(n, m, n1, m1);
294af45d5e6Sslatteng 				break;
295007e314bSslatteng 			case 'q':	/* versatec polygon - ignore */
296007e314bSslatteng 				while (buf[strlen(buf) - 1] != '\n')
297007e314bSslatteng 				    if (fgets(buf, sizeof(buf), fp) == NULL)
298007e314bSslatteng 					error(FATAL,"unexpected end of input");
299007e314bSslatteng 				break;
300007e314bSslatteng 			case 'P':	/* unbordered */
3015839e65eSslatteng 			case 'p':	/* polygon */
3025839e65eSslatteng 				sscanf(buf+1, "%d", &n);
3035839e65eSslatteng 				n = 1;
3045839e65eSslatteng 				while(buf[n++] == ' ');
3055839e65eSslatteng 				while(isdigit(buf[n])) n++;
3065839e65eSslatteng 				drawwig(buf+n, 1);
3075839e65eSslatteng 				break;
308af45d5e6Sslatteng 			case 'g':	/* "gremlin" curve */
309af45d5e6Sslatteng 			case '~':	/* wiggly line */
3105839e65eSslatteng 				drawwig(buf+1, 0);
311af45d5e6Sslatteng 				break;
312af45d5e6Sslatteng 			case 't':	/* thickness - not important */
313af45d5e6Sslatteng 			case 's':	/* style - not important */
314af45d5e6Sslatteng 				break;
315af45d5e6Sslatteng 			default:
316af45d5e6Sslatteng 				error(FATAL,"unknown drawing command %s\n",buf);
317af45d5e6Sslatteng 				break;
318af45d5e6Sslatteng 			}
319af45d5e6Sslatteng 			break;
3205839e65eSslatteng 		case 'i':	/* stipple pattern request - ignored */
321af45d5e6Sslatteng 		case 's':	/* point size - ignored */
322af45d5e6Sslatteng 			fscanf(fp, "%d", &n);
323af45d5e6Sslatteng 			break;
324af45d5e6Sslatteng 
325af45d5e6Sslatteng 		case 'f':	/* font request - ignored */
326af45d5e6Sslatteng 			fscanf(fp, "%s", str);
327af45d5e6Sslatteng 			break;
328af45d5e6Sslatteng 
329af45d5e6Sslatteng 		case 'H':	/* absolute horizontal motion */
330af45d5e6Sslatteng 			fscanf(fp, "%d", &n);
331af45d5e6Sslatteng 			hgoto(n);
332af45d5e6Sslatteng 			break;
333af45d5e6Sslatteng 
334af45d5e6Sslatteng 		case 'h':	/* relative horizontal motion */
335af45d5e6Sslatteng 			fscanf(fp, "%d", &n);
336af45d5e6Sslatteng 			hmot(n);
337af45d5e6Sslatteng 			break;
338af45d5e6Sslatteng 
339af45d5e6Sslatteng 		case 'w':	/* word space */
340083ff42bSslatteng 			if (ascii) {
341083ff42bSslatteng 			    hmot((int)hscale);
342083ff42bSslatteng 			}
343af45d5e6Sslatteng 			break;
344af45d5e6Sslatteng 
345af45d5e6Sslatteng 		case 'V':	/* absolute vertical motion */
346af45d5e6Sslatteng 			fscanf(fp, "%d", &n);
347af45d5e6Sslatteng 			vgoto(n);
348af45d5e6Sslatteng 			break;
349af45d5e6Sslatteng 
350af45d5e6Sslatteng 		case 'v':	/* relative vertical motion */
351af45d5e6Sslatteng 			fscanf(fp, "%d", &n);
352af45d5e6Sslatteng 			vmot(n);
353af45d5e6Sslatteng 			break;
354af45d5e6Sslatteng 
355af45d5e6Sslatteng 		case 'p':	/* new page */
356af45d5e6Sslatteng 			fscanf(fp, "%d", &n);
357af45d5e6Sslatteng 			t_page(n);
358af45d5e6Sslatteng 			break;
359af45d5e6Sslatteng 
360ce133b5eSslatteng 		case 'P':	/* new span (ignored) */
361ce133b5eSslatteng 			fscanf(fp, "%d", &n);
362ce133b5eSslatteng 			break;
363ce133b5eSslatteng 
364af45d5e6Sslatteng 		case 'n':	/* end of line */
365af45d5e6Sslatteng 			hpos = 0;
366af45d5e6Sslatteng 		case '#':	/* comment */
367af45d5e6Sslatteng 			while (getc(fp) != '\n')
368af45d5e6Sslatteng 				;
369af45d5e6Sslatteng 			break;
370af45d5e6Sslatteng 
371af45d5e6Sslatteng 		case 'x':	/* device control */
372af45d5e6Sslatteng 			devcntrl(fp);
373af45d5e6Sslatteng 			break;
374af45d5e6Sslatteng 
375af45d5e6Sslatteng 		default:
376af45d5e6Sslatteng 			error(!FATAL, "unknown input character %o %c\n", c, c);
377af45d5e6Sslatteng 			done();
378af45d5e6Sslatteng 		}
379af45d5e6Sslatteng 	}
380af45d5e6Sslatteng }
381af45d5e6Sslatteng 
382af45d5e6Sslatteng 
devcntrl(fp)383af45d5e6Sslatteng devcntrl(fp)	/* interpret device control functions */
384af45d5e6Sslatteng FILE *fp;
385af45d5e6Sslatteng {
386af45d5e6Sslatteng 	int c, n;
387af45d5e6Sslatteng 	char str[20];
388af45d5e6Sslatteng 
389af45d5e6Sslatteng 	fscanf(fp, "%s", str);
390af45d5e6Sslatteng 	switch (str[0]) {	/* crude for now */
391af45d5e6Sslatteng 	case 'i':	/* initialize */
392af45d5e6Sslatteng 		t_init(0);
393af45d5e6Sslatteng 		break;
394af45d5e6Sslatteng 	case 'r':	/* resolution assumed when prepared */
395af45d5e6Sslatteng 		fscanf(fp, "%d", &n);
396af45d5e6Sslatteng 		hscale = (float) n / hscale;
397af45d5e6Sslatteng 		vscale = (float) n / vscale;
398bb5743b1Sslatteng 		DP = min (hscale, vscale);	/* guess the drawing */
399bb5743b1Sslatteng 		DP = max (DP, 1);		/* resolution */
400bb5743b1Sslatteng 		break;
401af45d5e6Sslatteng 	case 'f':	/* font used */
402af45d5e6Sslatteng 	case 'T':	/* device name */
403af45d5e6Sslatteng 	case 't':	/* trailer */
404af45d5e6Sslatteng 	case 'p':	/* pause -- can restart */
405af45d5e6Sslatteng 	case 's':	/* stop */
406af45d5e6Sslatteng 		break;
407af45d5e6Sslatteng 	}
408af45d5e6Sslatteng 	while (getc(fp) != '\n')	/* skip rest of input line */
409af45d5e6Sslatteng 		;
410af45d5e6Sslatteng }
411af45d5e6Sslatteng 
412af45d5e6Sslatteng 		/* error printing routine - first argument is a "fatal" flag */
error(f,s,a1,a2,a3,a4,a5,a6,a7)413af45d5e6Sslatteng error(f, s, a1, a2, a3, a4, a5, a6, a7) {
414af45d5e6Sslatteng     fprintf(stderr, "dterm: ");
415af45d5e6Sslatteng     fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7);
416af45d5e6Sslatteng     fprintf(stderr, "\n");
417af45d5e6Sslatteng     if (f) exit(1);
418af45d5e6Sslatteng }
419af45d5e6Sslatteng 
420af45d5e6Sslatteng 
t_init(reinit)421af45d5e6Sslatteng t_init(reinit)	/* initialize device */
422af45d5e6Sslatteng int reinit;
423af45d5e6Sslatteng {
42418573097Sslatteng 	register int i;
42518573097Sslatteng 	register int j;
42618573097Sslatteng 	register FILE *fp;	/* file to look up special characters */
42718573097Sslatteng 	register char *charptr;	/* string pointer to step through specials */
42818573097Sslatteng 	register char *tabptr;	/* string pointer for spectab setting */
42918573097Sslatteng 	char specials[5000];	/* intermediate input buffer (made bigger */
43018573097Sslatteng 				/*   than we'll EVER use... */
43118573097Sslatteng 
432af45d5e6Sslatteng 
433af45d5e6Sslatteng 	fflush(stdout);
434af45d5e6Sslatteng 	hpos = vpos = 0;
435af45d5e6Sslatteng 	for (i = 0; i < PGHEIGHT; i++)
436af45d5e6Sslatteng 		for (j = 0; j < PGWIDTH; j++)
437af45d5e6Sslatteng 			pagebuf[i][j] = ' ';
438af45d5e6Sslatteng 	minh = PGWIDTH;
439af45d5e6Sslatteng 	maxh = 0;
440af45d5e6Sslatteng 	minv = PGHEIGHT;
441af45d5e6Sslatteng 	maxv = 0;
44218573097Sslatteng 
44318573097Sslatteng 	if (reinit) return;		/* if this is the first time, read */
44418573097Sslatteng 					/* special character table file. */
44518573097Sslatteng 	if ((fp = fopen (specfile, "r")) != NULL) {
44618573097Sslatteng 	    charptr = &specials[0];
44726bd01f2Sslatteng 	    for (i = 2; fscanf(fp, "%s", charptr) != EOF; i++) {
44818573097Sslatteng 		charptr += strlen(charptr) + 1;
44918573097Sslatteng 	    }
45018573097Sslatteng 	    fclose(fp);
45118573097Sslatteng 	    *charptr++ = '\0';			/* ending strings */
45218573097Sslatteng 	    *charptr++ = '\0';
45318573097Sslatteng 						/* allocate table */
45418573097Sslatteng 	    spectab = (char **) malloc(i * sizeof(char*));
45518573097Sslatteng 	    spectab[0] = tabptr = malloc(j = (int) (charptr - &specials[0]));
45618573097Sslatteng 
45718573097Sslatteng 						/* copy whole table */
45818573097Sslatteng 	    for (charptr = &specials[0]; j--; *tabptr++ = *charptr++);
45918573097Sslatteng 
46026bd01f2Sslatteng 	    tabptr = spectab[0];		/* set up pointers to table */
46118573097Sslatteng 	    for (j = 0; i--; j++) {
46218573097Sslatteng 		spectab[j] = tabptr;
46318573097Sslatteng 		tabptr += strlen(tabptr) + 1;
46418573097Sslatteng 	    }
46518573097Sslatteng 
46618573097Sslatteng 	} else {	/* didn't find table - allocate a null one */
46718573097Sslatteng 
46818573097Sslatteng 	    error (!FATAL, "Can't open special character file: %s", specfile);
46918573097Sslatteng 	    spectab = (char **) malloc(2 * sizeof(char*));
47018573097Sslatteng 	    spectab[0] = malloc (2);
47118573097Sslatteng 	    spectab[1] = spectab[0] + 1;
47218573097Sslatteng 	    *spectab[0] = '\0';
47318573097Sslatteng 	    *spectab[1] = '\0';
47418573097Sslatteng 	}
475af45d5e6Sslatteng }
476af45d5e6Sslatteng 
477af45d5e6Sslatteng 
478af45d5e6Sslatteng 		/* just got "p#" command.  print the current page and */
t_page(n)479af45d5e6Sslatteng t_page(n)	/* do whatever new page functions */
480af45d5e6Sslatteng {
481af45d5e6Sslatteng 	long ftell();
482af45d5e6Sslatteng 	int c, m, i;
483af45d5e6Sslatteng 	char buf[100], *bp;
484af45d5e6Sslatteng 
485af45d5e6Sslatteng 	pgnum[np++] = n;
486af45d5e6Sslatteng 	pgadr[np] = ftell(fp);
487af45d5e6Sslatteng 	if (np > npmax)
488af45d5e6Sslatteng 		npmax = np;
489af45d5e6Sslatteng 	if (output == 0) {
490af45d5e6Sslatteng 		output = in_olist(n);
491af45d5e6Sslatteng 		t_init(1);
492af45d5e6Sslatteng 		return;
493af45d5e6Sslatteng 	}
494af45d5e6Sslatteng 
495af45d5e6Sslatteng 	putpage();
496af45d5e6Sslatteng 	fflush(stdout);
497af45d5e6Sslatteng 
498bb5743b1Sslatteng 	if (clearsc) putchar('');
499af45d5e6Sslatteng 	if (keepon) {
500af45d5e6Sslatteng 		t_init(1);
501af45d5e6Sslatteng 		return;
502af45d5e6Sslatteng 	}
503af45d5e6Sslatteng   next:
504af45d5e6Sslatteng 	for (bp = buf; (*bp = readch()); )
505af45d5e6Sslatteng 		if (*bp++ == '\n')
506af45d5e6Sslatteng 			break;
507af45d5e6Sslatteng 	*bp = 0;
508af45d5e6Sslatteng 	switch (buf[0]) {
509af45d5e6Sslatteng 	case 0:
510af45d5e6Sslatteng 		done();
511af45d5e6Sslatteng 		break;
512af45d5e6Sslatteng 	case '\n':
513af45d5e6Sslatteng 		output = in_olist(n);
514af45d5e6Sslatteng 		t_init(1);
515af45d5e6Sslatteng 		return;
516af45d5e6Sslatteng 	case '-':
517af45d5e6Sslatteng 	case 'p':
518af45d5e6Sslatteng 		m = atoi(&buf[1]) + 1;
519af45d5e6Sslatteng 		if (fp == stdin) {
520af45d5e6Sslatteng 			fputs("you can't; it's not a file\n", stderr);
521af45d5e6Sslatteng 			break;
522af45d5e6Sslatteng 		}
523af45d5e6Sslatteng 		if (np - m <= 0) {
524af45d5e6Sslatteng 			fputs("too far back\n", stderr);
525af45d5e6Sslatteng 			break;
526af45d5e6Sslatteng 		}
527af45d5e6Sslatteng 		np -= m;
528af45d5e6Sslatteng 		fseek(fp, pgadr[np], 0);
529af45d5e6Sslatteng 		output = 1;
530af45d5e6Sslatteng 		t_init(1);
531af45d5e6Sslatteng 		return;
532af45d5e6Sslatteng 	case '0': case '1': case '2': case '3': case '4':
533af45d5e6Sslatteng 	case '5': case '6': case '7': case '8': case '9':
534af45d5e6Sslatteng 		m = atoi(&buf[0]);
535af45d5e6Sslatteng 		for (i = 0; i < npmax; i++)
536af45d5e6Sslatteng 			if (m == pgnum[i])
537af45d5e6Sslatteng 				break;
538af45d5e6Sslatteng 		if (i >= npmax || fp == stdin) {
539af45d5e6Sslatteng 			fputs("you can't\n", stderr);
540af45d5e6Sslatteng 			break;
541af45d5e6Sslatteng 		}
542af45d5e6Sslatteng 		np = i + 1;
543af45d5e6Sslatteng 		fseek(fp, pgadr[np], 0);
544af45d5e6Sslatteng 		output = 1;
545af45d5e6Sslatteng 		t_init(1);
546af45d5e6Sslatteng 		return;
547af45d5e6Sslatteng 	case 'o':
548af45d5e6Sslatteng 		outlist(&buf[1]);
549af45d5e6Sslatteng 		output = 0;
550af45d5e6Sslatteng 		t_init(1);
551af45d5e6Sslatteng 		return;
552af45d5e6Sslatteng 	case '?':
553af45d5e6Sslatteng 		fputs("p	print this page again\n", stderr);
554af45d5e6Sslatteng 		fputs("-n	go back n pages\n", stderr);
555af45d5e6Sslatteng 		fputs("n	print page n (previously printed)\n", stderr);
556af45d5e6Sslatteng 		fputs("o...	set the -o output list to ...\n", stderr);
557af45d5e6Sslatteng 		break;
558af45d5e6Sslatteng 	default:
559af45d5e6Sslatteng 		fputs("?\n", stderr);
560af45d5e6Sslatteng 		break;
561af45d5e6Sslatteng 	}
562af45d5e6Sslatteng 	goto next;
563af45d5e6Sslatteng }
564af45d5e6Sslatteng 
565af45d5e6Sslatteng 			/* print the contents of the current page.  puts out */
putpage()566af45d5e6Sslatteng putpage()		/* only the part of the page that's been written on */
567ce133b5eSslatteng {			/* unless "margin" is set. */
568af45d5e6Sslatteng 	int i, j, k;
569af45d5e6Sslatteng 
570af45d5e6Sslatteng 	fflush(stdout);
571ce133b5eSslatteng 	if (margin) minv = minh = 0;
572af45d5e6Sslatteng 	for (i = minv; i <= maxv; i++) {
573af45d5e6Sslatteng 		for (k = maxh; pagebuf[i][k] == ' '; k--)
574af45d5e6Sslatteng 			;
575af45d5e6Sslatteng 		if (k > minh + linelen)
576af45d5e6Sslatteng 			k = minh + linelen;
577af45d5e6Sslatteng 		for (j = minh; j <= k; j++)
578af45d5e6Sslatteng 			putchar(pagebuf[i][j]);
579af45d5e6Sslatteng 		putchar('\n');
580af45d5e6Sslatteng 	}
581af45d5e6Sslatteng 	fflush(stdout);
582af45d5e6Sslatteng }
583af45d5e6Sslatteng 
584af45d5e6Sslatteng 
t_text(s)585af45d5e6Sslatteng t_text(s)		/* print string s as text */
586af45d5e6Sslatteng char *s;
587af45d5e6Sslatteng {
588af45d5e6Sslatteng 	int c;
589af45d5e6Sslatteng 	char str[100];
590af45d5e6Sslatteng 
591af45d5e6Sslatteng 	if (!output)
592af45d5e6Sslatteng 		return;
593af45d5e6Sslatteng 	while ((c = *s++) != '\n') {
594af45d5e6Sslatteng 		if (c == '\\') {
595af45d5e6Sslatteng 			switch (c = *s++) {
596af45d5e6Sslatteng 			case '\\':
597af45d5e6Sslatteng 			case 'e':
598af45d5e6Sslatteng 				put1('\\');
599af45d5e6Sslatteng 				break;
600af45d5e6Sslatteng 			case '(':
601af45d5e6Sslatteng 				str[0] = *s++;
602af45d5e6Sslatteng 				str[1] = *s++;
603af45d5e6Sslatteng 				str[2] = '\0';
604af45d5e6Sslatteng 				put1s(str);
605af45d5e6Sslatteng 				break;
606af45d5e6Sslatteng 			}
607af45d5e6Sslatteng 		} else {
608af45d5e6Sslatteng 			put1(c);
609af45d5e6Sslatteng 		}
610083ff42bSslatteng 		hmot((int)hscale);
611af45d5e6Sslatteng 	}
612af45d5e6Sslatteng }
613af45d5e6Sslatteng 
614af45d5e6Sslatteng 
put1s(s)615af45d5e6Sslatteng put1s(s)	/* s is a funny char name */
616af45d5e6Sslatteng char *s;
617af45d5e6Sslatteng {
618af45d5e6Sslatteng 	int i;
619af45d5e6Sslatteng 	char *p;
620af45d5e6Sslatteng 	static char prev[10] = "";
621af45d5e6Sslatteng 	static int previ;
622af45d5e6Sslatteng 
623af45d5e6Sslatteng 	if (!output)
624af45d5e6Sslatteng 		return;
625af45d5e6Sslatteng 	if (strcmp(s, prev) != 0) {
626af45d5e6Sslatteng 		previ = -1;
62718573097Sslatteng 		for (i = 0; *spectab[i] != '\0'; i += 2)
628af45d5e6Sslatteng 			if (strcmp(spectab[i], s) == 0) {
629af45d5e6Sslatteng 				strcpy(prev, s);
630af45d5e6Sslatteng 				previ = i;
631af45d5e6Sslatteng 				break;
632af45d5e6Sslatteng 			}
633af45d5e6Sslatteng 	}
634af45d5e6Sslatteng 	if (previ >= 0) {
635083ff42bSslatteng 		for (hmot((int)-hscale), p = spectab[previ+1]; *p; p++) {
636083ff42bSslatteng 			hmot((int)hscale);
637af45d5e6Sslatteng 			store(*p);
638083ff42bSslatteng 		}
639af45d5e6Sslatteng 	} else
64018573097Sslatteng 		prev[0] = '\0';
641af45d5e6Sslatteng }
642af45d5e6Sslatteng 
643af45d5e6Sslatteng 
put1(c)644af45d5e6Sslatteng put1(c)			/* output char c */
645af45d5e6Sslatteng int c;
646af45d5e6Sslatteng {
647af45d5e6Sslatteng 	if (!output)
648af45d5e6Sslatteng 		return;
649af45d5e6Sslatteng 	store(c);
650af45d5e6Sslatteng }
651af45d5e6Sslatteng 
652af45d5e6Sslatteng 
done()653af45d5e6Sslatteng done()
654af45d5e6Sslatteng {
655af45d5e6Sslatteng 	output = 1;
656af45d5e6Sslatteng 	putpage();
657af45d5e6Sslatteng 	fflush(stdout);
658af45d5e6Sslatteng 	exit(0);
659af45d5e6Sslatteng }
660af45d5e6Sslatteng 
661af45d5e6Sslatteng 
readch()662af45d5e6Sslatteng readch ()
663af45d5e6Sslatteng {
664af45d5e6Sslatteng 	int c;
665af45d5e6Sslatteng 	static FILE *rcf;
666af45d5e6Sslatteng 	static nbol;	/* 0 if at beginning of a line */
667af45d5e6Sslatteng 
668af45d5e6Sslatteng 	if (rcf == NULL) {
669af45d5e6Sslatteng 		rcf = fopen ("/dev/tty", "r");
670af45d5e6Sslatteng 		setbuf (rcf, NULL);
671af45d5e6Sslatteng 	}
672af45d5e6Sslatteng 
673af45d5e6Sslatteng 	if (!nbol)
674af45d5e6Sslatteng 		fprintf (stderr, "dterm: ");	/* issue prompt */
675af45d5e6Sslatteng 	if ((c = getc (rcf)) == EOF)
676af45d5e6Sslatteng 		return 0;
677af45d5e6Sslatteng 	nbol = (c != '\n');
678af45d5e6Sslatteng 	return c;
679af45d5e6Sslatteng }
680af45d5e6Sslatteng 
681af45d5e6Sslatteng 
store(c)682af45d5e6Sslatteng store(c)		/* put 'c' in the page at (hpos, vpos) */
683af45d5e6Sslatteng {
684af45d5e6Sslatteng 	register int i;
685af45d5e6Sslatteng 	register int j;
686af45d5e6Sslatteng 
687af45d5e6Sslatteng 
688af45d5e6Sslatteng 	i = hpos / hscale;	/* scale the position to page coordinates */
689af45d5e6Sslatteng 	j = vpos / vscale;
690af45d5e6Sslatteng 
691af45d5e6Sslatteng 	if (i >= PGWIDTH) i = PGWIDTH - 1;	/* don't go over the edge */
692af45d5e6Sslatteng 	else if (i < 0) i = 0;
693af45d5e6Sslatteng 	if (j >= PGHEIGHT) j = PGHEIGHT - 1;
694af45d5e6Sslatteng 	else if (j < 0) j = 0;
695af45d5e6Sslatteng 
696af45d5e6Sslatteng 	pagebuf[j][i] = c;		/* write the character */
697af45d5e6Sslatteng 
698af45d5e6Sslatteng 	if (i > maxh) maxh = i;		/* update the page bounds */
699af45d5e6Sslatteng 	if (i < minh) minh = i;
700af45d5e6Sslatteng 	if (j > maxv) maxv = j;
701af45d5e6Sslatteng 	if (j < minv) minv = j;
702af45d5e6Sslatteng }
703af45d5e6Sslatteng 
704af45d5e6Sslatteng 
drawline(dx,dy)7055839e65eSslatteng drawline(dx, dy)	/* draw line from here to dx, dy using s */
706af45d5e6Sslatteng int dx, dy;
707af45d5e6Sslatteng {
708af45d5e6Sslatteng 	register int xd;
709af45d5e6Sslatteng 	register int yd;
710af45d5e6Sslatteng 	register int i;
711af45d5e6Sslatteng 	register int numdots;
712af45d5e6Sslatteng 	int dirmot, perp;
713af45d5e6Sslatteng 	int motincr, perpincr;
714af45d5e6Sslatteng 	int ohpos, ovpos;
715af45d5e6Sslatteng 	float val, slope;
716af45d5e6Sslatteng 	float incrway;
717af45d5e6Sslatteng 
718af45d5e6Sslatteng 	ohpos = hpos;
719af45d5e6Sslatteng 	ovpos = vpos;
720af45d5e6Sslatteng 	xd = dx / DP;
721af45d5e6Sslatteng 	yd = dy / DP;
722af45d5e6Sslatteng 	if (xd == 0) {
723af45d5e6Sslatteng 		numdots = abs (yd);
724af45d5e6Sslatteng 		numdots = min(numdots, maxdots);
725af45d5e6Sslatteng 		motincr = DP * sgn (yd);
726eea66e16Sslatteng 		put1('|');
727af45d5e6Sslatteng 		for (i = 0; i < numdots; i++) {
728af45d5e6Sslatteng 			vmot(motincr);
729eea66e16Sslatteng 			put1('|');
730af45d5e6Sslatteng 		}
731af45d5e6Sslatteng 	} else
732af45d5e6Sslatteng 	if (yd == 0) {
733af45d5e6Sslatteng 		numdots = abs (xd);
734bb5743b1Sslatteng 		numdots = min(numdots, maxdots);
735af45d5e6Sslatteng 		motincr = DP * sgn (xd);
736eea66e16Sslatteng 		put1('-');
737af45d5e6Sslatteng 		for (i = 0; i < numdots; i++) {
738af45d5e6Sslatteng 			hmot(motincr);
739eea66e16Sslatteng 			put1('-');
740af45d5e6Sslatteng 		}
741af45d5e6Sslatteng 	} else {
742af45d5e6Sslatteng 	    if (abs (xd) > abs (yd)) {
743af45d5e6Sslatteng 		val = slope = (float) xd/yd;
744af45d5e6Sslatteng 		numdots = abs (xd);
745af45d5e6Sslatteng 		dirmot = 'h';
746af45d5e6Sslatteng 		perp = 'v';
747af45d5e6Sslatteng 		motincr = DP * sgn (xd);
748af45d5e6Sslatteng 		perpincr = DP * sgn (yd);
749af45d5e6Sslatteng 	    } else {
750af45d5e6Sslatteng 		val = slope = (float) yd/xd;
751af45d5e6Sslatteng 		numdots = abs (yd);
752af45d5e6Sslatteng 		dirmot = 'v';
753af45d5e6Sslatteng 		perp = 'h';
754af45d5e6Sslatteng 		motincr = DP * sgn (yd);
755af45d5e6Sslatteng 		perpincr = DP * sgn (xd);
756af45d5e6Sslatteng 	    }
75718573097Sslatteng 	    numdots = min(numdots, maxdots);
758af45d5e6Sslatteng 	    incrway = sgn ((int) slope);
759eea66e16Sslatteng 	    put1('*');
760af45d5e6Sslatteng 	    for (i = 0; i < numdots; i++) {
761af45d5e6Sslatteng 		val -= incrway;
762af45d5e6Sslatteng 		if (dirmot == 'h')
763af45d5e6Sslatteng 			hmot(motincr);
764af45d5e6Sslatteng 		else
765af45d5e6Sslatteng 			vmot(motincr);
766af45d5e6Sslatteng 		if (val * slope < 0) {
767af45d5e6Sslatteng 			if (perp == 'h')
768af45d5e6Sslatteng 				hmot(perpincr);
769af45d5e6Sslatteng 			else
770af45d5e6Sslatteng 				vmot(perpincr);
771af45d5e6Sslatteng 			val += slope;
772af45d5e6Sslatteng 		}
773eea66e16Sslatteng 		put1('*');
774af45d5e6Sslatteng 	    }
775af45d5e6Sslatteng 	}
776af45d5e6Sslatteng 	hgoto(ohpos + dx);
777af45d5e6Sslatteng 	vgoto(ovpos + dy);
778af45d5e6Sslatteng }
779af45d5e6Sslatteng 
780af45d5e6Sslatteng 
drawwig(s,poly)7815839e65eSslatteng drawwig(s, poly)	/* draw wiggly line or polygon, if "poly" set */
782af45d5e6Sslatteng char *s;
7835839e65eSslatteng int poly;
784af45d5e6Sslatteng {
785af45d5e6Sslatteng 	int x[50], y[50], xp, yp, pxp, pyp;
786af45d5e6Sslatteng 	float t1, t2, t3, w;
787af45d5e6Sslatteng 	int i, j, numdots, N;
788af45d5e6Sslatteng 	char temp[50], *p, *getstr();
789af45d5e6Sslatteng 
790af45d5e6Sslatteng 	p = s;
791af45d5e6Sslatteng 	for (N = 2; (p=getstr(p,temp)) != NULL && N < sizeof(x)/sizeof(x[0]);) {
792af45d5e6Sslatteng 		x[N] = atoi(temp);
793af45d5e6Sslatteng 		p = getstr(p, temp);
794af45d5e6Sslatteng 		y[N++] = atoi(temp);
795af45d5e6Sslatteng 	}
7965839e65eSslatteng 	if (poly) {
7975839e65eSslatteng 		for (i = 2; i < N; i++)
7985839e65eSslatteng 			drawline(x[i], y[i]);
7995839e65eSslatteng 		return;
8005839e65eSslatteng 	}
801af45d5e6Sslatteng 	x[0] = x[1] = hpos;
802af45d5e6Sslatteng 	y[0] = y[1] = vpos;
803af45d5e6Sslatteng 	for (i = 1; i < N; i++) {
804af45d5e6Sslatteng 		x[i+1] += x[i];
805af45d5e6Sslatteng 		y[i+1] += y[i];
806af45d5e6Sslatteng 	}
807af45d5e6Sslatteng 	x[N] = x[N-1];
808af45d5e6Sslatteng 	y[N] = y[N-1];
809af45d5e6Sslatteng 	pxp = pyp = -9999;
810af45d5e6Sslatteng 	for (i = 0; i < N-1; i++) {	/* interval */
811af45d5e6Sslatteng 		numdots = (dist(x[i], y[i], x[i+1], y[i+1])
812af45d5e6Sslatteng 			     + dist(x[i+1], y[i+1], x[i+2], y[i+2])) / 2;
813af45d5e6Sslatteng 		numdots /= DP;
814af45d5e6Sslatteng 		numdots = min(numdots, maxdots);
815af45d5e6Sslatteng 		for (j = 0; j < numdots; j++) {	/* points within */
816af45d5e6Sslatteng 			w = (float) j / numdots;
817af45d5e6Sslatteng 			t1 = 0.5 * w * w;
818af45d5e6Sslatteng 			w = w - 0.5;
819af45d5e6Sslatteng 			t2 = 0.75 - w * w;
820af45d5e6Sslatteng 			w = w - 0.5;
821af45d5e6Sslatteng 			t3 = 0.5 * w * w;
822af45d5e6Sslatteng 			xp = t1 * x[i+2] + t2 * x[i+1] + t3 * x[i] + 0.5;
823af45d5e6Sslatteng 			yp = t1 * y[i+2] + t2 * y[i+1] + t3 * y[i] + 0.5;
824af45d5e6Sslatteng 			if (xp != pxp || yp != pyp) {
825af45d5e6Sslatteng 				hgoto(xp);
826af45d5e6Sslatteng 				vgoto(yp);
827eea66e16Sslatteng 				put1('*');
828af45d5e6Sslatteng 				pxp = xp;
829af45d5e6Sslatteng 				pyp = yp;
830af45d5e6Sslatteng 			}
831af45d5e6Sslatteng 		}
832af45d5e6Sslatteng 	}
833af45d5e6Sslatteng }
834af45d5e6Sslatteng 
835af45d5e6Sslatteng 
836af45d5e6Sslatteng /* copy next non-blank string from p to temp, update p */
837af45d5e6Sslatteng 
getstr(p,temp)838af45d5e6Sslatteng char *getstr(p, temp)
839af45d5e6Sslatteng char *p, *temp;
840af45d5e6Sslatteng {
841af45d5e6Sslatteng 	while (*p == ' ' || *p == '\t' || *p == '\n')
842af45d5e6Sslatteng 		p++;
843af45d5e6Sslatteng 	if (*p == '\0') {
844af45d5e6Sslatteng 		temp[0] = 0;
845af45d5e6Sslatteng 		return(NULL);
846af45d5e6Sslatteng 	}
847af45d5e6Sslatteng 	while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
848af45d5e6Sslatteng 		*temp++ = *p++;
849af45d5e6Sslatteng 	*temp = '\0';
850af45d5e6Sslatteng 	return(p);
851af45d5e6Sslatteng }
852af45d5e6Sslatteng 
853af45d5e6Sslatteng 
drawcirc(d)854af45d5e6Sslatteng drawcirc(d)
855af45d5e6Sslatteng {
856af45d5e6Sslatteng 	int xc, yc;
857af45d5e6Sslatteng 
858af45d5e6Sslatteng 	xc = hpos;
859af45d5e6Sslatteng 	yc = vpos;
860af45d5e6Sslatteng 	conicarc(hpos + d/2, -vpos, hpos, -vpos, hpos, -vpos, d/2, d/2);
861af45d5e6Sslatteng 	hgoto(xc + d);	/* circle goes to right side */
862af45d5e6Sslatteng 	vgoto(yc);
863af45d5e6Sslatteng }
864af45d5e6Sslatteng 
865af45d5e6Sslatteng 
dist(x1,y1,x2,y2)866af45d5e6Sslatteng dist(x1, y1, x2, y2)	/* integer distance from x1,y1 to x2,y2 */
867af45d5e6Sslatteng {
868af45d5e6Sslatteng 	float dx, dy;
869af45d5e6Sslatteng 
870af45d5e6Sslatteng 	dx = x2 - x1;
871af45d5e6Sslatteng 	dy = y2 - y1;
872af45d5e6Sslatteng 	return sqrt(dx*dx + dy*dy) + 0.5;
873af45d5e6Sslatteng }
874af45d5e6Sslatteng 
875af45d5e6Sslatteng 
drawarc(dx1,dy1,dx2,dy2)876af45d5e6Sslatteng drawarc(dx1, dy1, dx2, dy2)
877af45d5e6Sslatteng {
878af45d5e6Sslatteng 	int x0, y0, x2, y2, r;
879af45d5e6Sslatteng 
880af45d5e6Sslatteng 	x0 = hpos + dx1;	/* center */
881af45d5e6Sslatteng 	y0 = vpos + dy1;
882af45d5e6Sslatteng 	x2 = x0 + dx2;	/* "to" */
883af45d5e6Sslatteng 	y2 = y0 + dy2;
884af45d5e6Sslatteng 	r = sqrt((float) dx1 * dx1 + (float) dy1 * dy1) + 0.5;
885af45d5e6Sslatteng 	conicarc(x0, -y0, hpos, -vpos, x2, -y2, r, r);
886af45d5e6Sslatteng }
887af45d5e6Sslatteng 
888af45d5e6Sslatteng 
drawellip(a,b)889af45d5e6Sslatteng drawellip(a, b)
890af45d5e6Sslatteng {
891af45d5e6Sslatteng 	int xc, yc;
892af45d5e6Sslatteng 
893af45d5e6Sslatteng 	xc = hpos;
894af45d5e6Sslatteng 	yc = vpos;
895af45d5e6Sslatteng 	conicarc(hpos + a/2, -vpos, hpos, -vpos, hpos, -vpos, a/2, b/2);
896af45d5e6Sslatteng 	hgoto(xc + a);
897af45d5e6Sslatteng 	vgoto(yc);
898af45d5e6Sslatteng }
899af45d5e6Sslatteng 
900af45d5e6Sslatteng 
conicarc(x,y,x0,y0,x1,y1,a,b)901af45d5e6Sslatteng conicarc(x, y, x0, y0, x1, y1, a, b)
902af45d5e6Sslatteng {
903af45d5e6Sslatteng 		/* based on Bresenham, CACM Feb 77, pp 102-3 by Chris Van Wyk */
904af45d5e6Sslatteng 		/* capitalized vars are an internal reference frame */
905af45d5e6Sslatteng 	long dotcount = 0;
906af45d5e6Sslatteng 	int	xs, ys, xt, yt, Xs, Ys, qs, Xt, Yt, qt,
907af45d5e6Sslatteng 		M1x, M1y, M2x, M2y, M3x, M3y,
908af45d5e6Sslatteng 		Q, move, Xc, Yc;
909af45d5e6Sslatteng 	int ox1, oy1;
910af45d5e6Sslatteng 	long	delta;
911af45d5e6Sslatteng 	float	xc, yc;
912af45d5e6Sslatteng 	float	radius, slope;
913af45d5e6Sslatteng 	float	xstep, ystep;
914af45d5e6Sslatteng 
915af45d5e6Sslatteng 	ox1 = x1;
916af45d5e6Sslatteng 	oy1 = y1;
917af45d5e6Sslatteng 	if (a != b)	/* an arc of an ellipse; internally, think of circle */
918af45d5e6Sslatteng 		if (a > b) {
919af45d5e6Sslatteng 			xstep = (float)a / b;
920af45d5e6Sslatteng 			ystep = 1;
921af45d5e6Sslatteng 			radius = b;
922af45d5e6Sslatteng 		} else {
923af45d5e6Sslatteng 			xstep = 1;
924af45d5e6Sslatteng 			ystep = (float)b / a;
925af45d5e6Sslatteng 			radius = a;
926af45d5e6Sslatteng 		}
927af45d5e6Sslatteng 	else {
928af45d5e6Sslatteng 	    /* a circular arc; radius computed from center and first point */
929af45d5e6Sslatteng 		xstep = ystep = 1;
930af45d5e6Sslatteng 		radius = sqrt((float)(sqr(x0 - x) + sqr(y0 - y)));
931af45d5e6Sslatteng 	}
932af45d5e6Sslatteng 
933af45d5e6Sslatteng 	xc = x0;
934af45d5e6Sslatteng 	yc = y0;
935af45d5e6Sslatteng 	/* now, use start and end point locations to figure out
936af45d5e6Sslatteng 	the angle at which start and end happen; use these
937af45d5e6Sslatteng 	angles with known radius to figure out where start
938af45d5e6Sslatteng 	and end should be
939af45d5e6Sslatteng 	*/
940af45d5e6Sslatteng 	slope = atan2((double)(y0 - y), (double)(x0 - x) );
941af45d5e6Sslatteng 	if (slope == 0.0 && x0 < x)
942af45d5e6Sslatteng 		slope = 3.14159265;
943af45d5e6Sslatteng 	x0 = x + radius * cos(slope) + 0.5;
944af45d5e6Sslatteng 	y0 = y + radius * sin(slope) + 0.5;
945af45d5e6Sslatteng 	slope = atan2((double)(y1 - y), (double)(x1 - x));
946af45d5e6Sslatteng 	if (slope == 0.0 && x1 < x)
947af45d5e6Sslatteng 		slope = 3.14159265;
948af45d5e6Sslatteng 	x1 = x + radius * cos(slope) + 0.5;
949af45d5e6Sslatteng 	y1 = y + radius * sin(slope) + 0.5;
950af45d5e6Sslatteng 	/* step 2: translate to zero-centered circle */
951af45d5e6Sslatteng 	xs = x0 - x;
952af45d5e6Sslatteng 	ys = y0 - y;
953af45d5e6Sslatteng 	xt = x1 - x;
954af45d5e6Sslatteng 	yt = y1 - y;
955af45d5e6Sslatteng 	/* step 3: normalize to first quadrant */
956af45d5e6Sslatteng 	if (xs < 0)
957af45d5e6Sslatteng 		if (ys < 0) {
958af45d5e6Sslatteng 			Xs = abs(ys);
959af45d5e6Sslatteng 			Ys = abs(xs);
960af45d5e6Sslatteng 			qs = 3;
961af45d5e6Sslatteng 			M1x = 0;
962af45d5e6Sslatteng 			M1y = -1;
963af45d5e6Sslatteng 			M2x = 1;
964af45d5e6Sslatteng 			M2y = -1;
965af45d5e6Sslatteng 			M3x = 1;
966af45d5e6Sslatteng 			M3y = 0;
967af45d5e6Sslatteng 		} else {
968af45d5e6Sslatteng 			Xs = abs(xs);
969af45d5e6Sslatteng 			Ys = abs(ys);
970af45d5e6Sslatteng 			qs = 2;
971af45d5e6Sslatteng 			M1x = -1;
972af45d5e6Sslatteng 			M1y = 0;
973af45d5e6Sslatteng 			M2x = -1;
974af45d5e6Sslatteng 			M2y = -1;
975af45d5e6Sslatteng 			M3x = 0;
976af45d5e6Sslatteng 			M3y = -1;
977af45d5e6Sslatteng 		}
978af45d5e6Sslatteng 	else if (ys < 0) {
979af45d5e6Sslatteng 		Xs = abs(xs);
980af45d5e6Sslatteng 		Ys = abs(ys);
981af45d5e6Sslatteng 		qs = 0;
982af45d5e6Sslatteng 		M1x = 1;
983af45d5e6Sslatteng 		M1y = 0;
984af45d5e6Sslatteng 		M2x = 1;
985af45d5e6Sslatteng 		M2y = 1;
986af45d5e6Sslatteng 		M3x = 0;
987af45d5e6Sslatteng 		M3y = 1;
988af45d5e6Sslatteng 	} else {
989af45d5e6Sslatteng 		Xs = abs(ys);
990af45d5e6Sslatteng 		Ys = abs(xs);
991af45d5e6Sslatteng 		qs = 1;
992af45d5e6Sslatteng 		M1x = 0;
993af45d5e6Sslatteng 		M1y = 1;
994af45d5e6Sslatteng 		M2x = -1;
995af45d5e6Sslatteng 		M2y = 1;
996af45d5e6Sslatteng 		M3x = -1;
997af45d5e6Sslatteng 		M3y = 0;
998af45d5e6Sslatteng 	}
999af45d5e6Sslatteng 
1000af45d5e6Sslatteng 	Xc = Xs;
1001af45d5e6Sslatteng 	Yc = Ys;
1002af45d5e6Sslatteng 	if (xt < 0)
1003af45d5e6Sslatteng 		if (yt < 0) {
1004af45d5e6Sslatteng 			Xt = abs(yt);
1005af45d5e6Sslatteng 			Yt = abs(xt);
1006af45d5e6Sslatteng 			qt = 3;
1007af45d5e6Sslatteng 		} else {
1008af45d5e6Sslatteng 			Xt = abs(xt);
1009af45d5e6Sslatteng 			Yt = abs(yt);
1010af45d5e6Sslatteng 			qt = 2;
1011af45d5e6Sslatteng 		}
1012af45d5e6Sslatteng 	else if (yt < 0) {
1013af45d5e6Sslatteng 		Xt = abs(xt);
1014af45d5e6Sslatteng 		Yt = abs(yt);
1015af45d5e6Sslatteng 		qt = 0;
1016af45d5e6Sslatteng 	} else {
1017af45d5e6Sslatteng 		Xt = abs(yt);
1018af45d5e6Sslatteng 		Yt = abs(xt);
1019af45d5e6Sslatteng 		qt = 1;
1020af45d5e6Sslatteng 	}
1021af45d5e6Sslatteng 
1022af45d5e6Sslatteng 		/* step 4: calculate number of quadrant crossings */
1023af45d5e6Sslatteng 	if (((4 + qt - qs) % 4 == 0) && (Xt <= Xs) && (Yt >= Ys))
1024af45d5e6Sslatteng 		Q = 3;
1025af45d5e6Sslatteng 	else
1026af45d5e6Sslatteng 		Q = (4 + qt - qs) % 4 - 1;
1027af45d5e6Sslatteng 		/* step 5: calculate initial decision difference */
1028af45d5e6Sslatteng 	delta = sqr(Xs + 1) + sqr(Ys - 1) - sqr(xs) - sqr(ys);
1029af45d5e6Sslatteng 				/* here begins the work of drawing. */
1030af45d5e6Sslatteng 	while ((Q >= 0) || ((Q > -2) && ((Xt > Xc) && (Yt < Yc)))) {
1031eea66e16Sslatteng 		if (dotcount++ % DP == 0) {
1032eea66e16Sslatteng 			hgoto((int)xc);
1033eea66e16Sslatteng 			vmot(-vpos-((int)yc));
1034eea66e16Sslatteng 			put1('*');
1035eea66e16Sslatteng 		}
1036af45d5e6Sslatteng 		if (Yc < 0.5) {
1037af45d5e6Sslatteng 			/* reinitialize */
1038af45d5e6Sslatteng 			Xs = Xc = 0;
1039af45d5e6Sslatteng 			Ys = Yc = sqrt((float)(sqr(xs) + sqr(ys)));
1040af45d5e6Sslatteng 			delta = sqr(Xs + 1) + sqr(Ys - 1) - sqr(xs) - sqr(ys);
1041af45d5e6Sslatteng 			Q--;
1042af45d5e6Sslatteng 			M1x = M3x;
1043af45d5e6Sslatteng 			M1y = M3y;
1044af45d5e6Sslatteng 			 {
1045af45d5e6Sslatteng 				int	T;
1046af45d5e6Sslatteng 				T = M2y;
1047af45d5e6Sslatteng 				M2y = M2x;
1048af45d5e6Sslatteng 				M2x = -T;
1049af45d5e6Sslatteng 				T = M3y;
1050af45d5e6Sslatteng 				M3y = M3x;
1051af45d5e6Sslatteng 				M3x = -T;
1052af45d5e6Sslatteng 			}
1053af45d5e6Sslatteng 		} else {
1054af45d5e6Sslatteng 			if (delta <= 0)
1055af45d5e6Sslatteng 				if (2 * delta + 2 * Yc - 1 <= 0)
1056af45d5e6Sslatteng 					move = 1;
1057af45d5e6Sslatteng 				else
1058af45d5e6Sslatteng 					move = 2;
1059af45d5e6Sslatteng 			else if (2 * delta - 2 * Xc - 1 <= 0)
1060af45d5e6Sslatteng 				move = 2;
1061af45d5e6Sslatteng 			else
1062af45d5e6Sslatteng 				move = 3;
1063af45d5e6Sslatteng 			switch (move) {
1064af45d5e6Sslatteng 			case 1:
1065af45d5e6Sslatteng 				Xc++;
1066af45d5e6Sslatteng 				delta += 2 * Xc + 1;
1067af45d5e6Sslatteng 				xc += M1x * xstep;
1068af45d5e6Sslatteng 				yc += M1y * ystep;
1069af45d5e6Sslatteng 				break;
1070af45d5e6Sslatteng 			case 2:
1071af45d5e6Sslatteng 				Xc++;
1072af45d5e6Sslatteng 				Yc--;
1073af45d5e6Sslatteng 				delta += 2 * Xc - 2 * Yc + 2;
1074af45d5e6Sslatteng 				xc += M2x * xstep;
1075af45d5e6Sslatteng 				yc += M2y * ystep;
1076af45d5e6Sslatteng 				break;
1077af45d5e6Sslatteng 			case 3:
1078af45d5e6Sslatteng 				Yc--;
1079af45d5e6Sslatteng 				delta -= 2 * Yc + 1;
1080af45d5e6Sslatteng 				xc += M3x * xstep;
1081af45d5e6Sslatteng 				yc += M3y * ystep;
1082af45d5e6Sslatteng 				break;
1083af45d5e6Sslatteng 			}
1084af45d5e6Sslatteng 		}
1085af45d5e6Sslatteng 	}
10865839e65eSslatteng 	drawline((int)xc-ox1,(int)yc-oy1);
1087af45d5e6Sslatteng }
1088