1*16548Sslatteng /* vsort.c	1.11	84/05/29
213918Sslatteng  *
314758Sslatteng  *	Sorts and shuffles ditroff output for versatec wide printer.  It
414758Sslatteng  *	puts pages side-by-side on the output, and fits as many as it can
514758Sslatteng  *	on one horizontal span.  The versatec driver sees only pages of
614758Sslatteng  *	full width, not the individual pages.  Output is sorted vertically
714758Sslatteng  *	and bands are created NLINES pixels high.  Any object that has
814758Sslatteng  *	ANY part of it in a band is put on that band.
913918Sslatteng  */
1013918Sslatteng 
1113918Sslatteng 
1213918Sslatteng #include	<stdio.h>
1313918Sslatteng #include	<ctype.h>
1414758Sslatteng #include	<math.h>
1513918Sslatteng 
1613918Sslatteng 
1715277Sslatteng /* #define DEBUGABLE	/* compile-time flag for debugging */
1813918Sslatteng #define	FATAL	1
1914758Sslatteng #define	NVLIST	3000	/* size of list of vertical spans */
2014758Sslatteng #define	OBUFSIZ	250000	/* size of character buffer before sorting */
2114297Sslatteng #define	SLOP	1000	/* extra bit of buffer to allow for passing OBUFSIZ */
22*16548Sslatteng #define MAXVECT	200	/* maximum number of points (vectors) in a polygon */
2313918Sslatteng 
2415946Sslatteng #ifndef FONTDIR
2514758Sslatteng #define FONTDIR "/usr/lib/font"
2615946Sslatteng #endif
2714758Sslatteng #define INCH	200	/* assumed resolution of the printer (dots/inch) */
2814758Sslatteng #define POINT	72	/* number of points per inch */
2914758Sslatteng #define WIDTH	7040	/* number of pixels across the page */
3014758Sslatteng #define HALF	(INCH/2)
3115059Sslatteng #ifndef DEBUGABLE
3215616Sslatteng #define BAND	1	/* length of each band (or defined below) */
3315059Sslatteng #endif
3414758Sslatteng #define NLINES	(int)(BAND * INCH)	/* number of pixels in each band */
3513918Sslatteng 
3614758Sslatteng #define hgoto(n)	if((hpos = leftmarg + n) > maxh) maxh = hpos
3714758Sslatteng #define hmot(n)		if((hpos += n) > maxh) maxh = hpos
38*16548Sslatteng #define vmot(n)		vpos += (n)
39*16548Sslatteng #define vgoto(n)	vpos = (n)
4013918Sslatteng 
4114758Sslatteng 
4214297Sslatteng #ifdef DEBUGABLE
4315059Sslatteng int	dbg = 0;	/* debug flag != 0 means do debug output */
4416183Sslatteng float	BAND = 1.0;
4514297Sslatteng #endif
4614758Sslatteng 
4715059Sslatteng 
4814758Sslatteng int	size	= 10;	/* current size (points) */
4914758Sslatteng int	up	= 0;	/* number of pixels that the current size pushes up */
5014758Sslatteng int	down	= 0;	/* # of pixels that the current size will hang down */
5113918Sslatteng int	font	= 1;	/* current font */
52*16548Sslatteng int	stip	= 1;	/* current stipple */
5314758Sslatteng char *	fontdir = FONTDIR;	/* place to find DESC.out file */
5414285Sslatteng int	thick	= 3;	/* line thickness */
5514758Sslatteng int	style	= -1;	/* line style bit-mask */
5613918Sslatteng int	hpos	= 0;	/* horizontal position to be at next (left = 0) */
5713918Sslatteng int	vpos	= 0;	/* current vertical position (down positive) */
5813918Sslatteng 
5914758Sslatteng int	maxh	= 0;	/* farthest right we've gone on the current span */
6014758Sslatteng int	leftmarg= 0;	/* current page offset */
6114758Sslatteng int	spanno	= 0;	/* current span number for driver in 'p#' commands */
6215277Sslatteng int	pageno	= 0;	/* number of pages spread across a physical page */
6314758Sslatteng 
6414758Sslatteng 
6513918Sslatteng struct vlist {
6615946Sslatteng 	unsigned short	v;	/* vertical position of this spread */
6715946Sslatteng 	unsigned short	h;	/* horizontal position */
6815946Sslatteng 	unsigned short	t;	/* line thickness */
69*16548Sslatteng 	short	st;		/* style mask */
7015946Sslatteng 	unsigned short	u;	/* upper extent of height */
7115946Sslatteng 	unsigned short	d;	/* depth of height */
72*16548Sslatteng 	unsigned short	s;	/* point size */
7315946Sslatteng 	unsigned char	f;	/* font number */
74*16548Sslatteng 	unsigned char	l;	/* stipple number */
75*16548Sslatteng 	char	*p;		/* text pointer to this spread */
7613918Sslatteng };
7713918Sslatteng 
7813918Sslatteng struct	vlist	vlist[NVLIST + 1];
7914758Sslatteng struct	vlist	*vlp;			/* current spread being added to */
8015946Sslatteng int	nvlist	= 1;			/* number of spreads in list */
8113918Sslatteng int	obufsiz	= OBUFSIZ;
8213918Sslatteng char	obuf[OBUFSIZ + SLOP];
8314758Sslatteng char	*op = obuf;			/* pointer to current spot in buffer */
8413918Sslatteng 
8513918Sslatteng 
main(argc,argv)8613918Sslatteng main(argc, argv)
8713918Sslatteng int argc;
8813918Sslatteng char *argv[];
8913918Sslatteng {
9013918Sslatteng 	FILE *fp;
9115059Sslatteng 	double atof();
9213918Sslatteng 
9313918Sslatteng 
9415946Sslatteng 	vlp = &vlist[0];		/* initialize spread pointer */
9515946Sslatteng 	vlp->p = op;
9615946Sslatteng 	vlp->v = vlp->d = vlp->u = vlp->h = 0;
9715946Sslatteng 	vlp->s = size;
9815946Sslatteng 	vlp->f = font;
99*16548Sslatteng 	vlp->l = stip;
10015946Sslatteng 	vlp->st = style;
10115946Sslatteng 	vlp->t = thick;
10215946Sslatteng 
10313918Sslatteng 	while (argc > 1 && **++argv == '-') {
10413918Sslatteng 	    switch ((*argv)[1]) {
10514758Sslatteng 		case 'f':
10614758Sslatteng 			fontdir = &(*argv)[2];
10714758Sslatteng 			break;
10814297Sslatteng #ifdef DEBUGABLE
10915059Sslatteng 		case 'B':
11015059Sslatteng 			BAND = atof(&(*argv)[2]);
11115059Sslatteng 			break;
11213918Sslatteng 		case 'd':
11313918Sslatteng 			dbg = atoi(&(*argv)[2]);
11414758Sslatteng 			if (!dbg) dbg = 1;
11513918Sslatteng 			break;
11614758Sslatteng 
11714758Sslatteng 		case 's':
11814758Sslatteng 			if((obufsiz = atoi(&(*argv)[2])) > OBUFSIZ)
11914758Sslatteng 			    obufsiz = OBUFSIZ;
12014758Sslatteng 			break;
12114297Sslatteng #endif
12213918Sslatteng 	    }
12313918Sslatteng 	    argc--;
12413918Sslatteng 	}
12514758Sslatteng 
12613918Sslatteng 	if (argc <= 1)
12713918Sslatteng 	    conv(stdin);
12813918Sslatteng 	else
12913918Sslatteng 	    while (--argc > 0) {
13013918Sslatteng 		if ((fp = fopen(*argv, "r")) == NULL)
13113918Sslatteng 		    error(FATAL, "can't open %s", *argv);
13213918Sslatteng 		conv(fp);
13313918Sslatteng 		fclose(fp);
13413918Sslatteng 	    }
13514758Sslatteng 	done();
13613918Sslatteng }
13713918Sslatteng 
13813918Sslatteng 			/* read number from input:  copy to output */
getnumber(fp)13913918Sslatteng int getnumber (fp)
14013918Sslatteng register FILE *fp;
14113918Sslatteng {
14214758Sslatteng 	register int k;
14314758Sslatteng 	register char c;
14413918Sslatteng 
145*16548Sslatteng 	while (isspace(c = getc(fp)))
14614758Sslatteng 	    ;
14714758Sslatteng 	k = 0;
148*16548Sslatteng 	if (c == '-') {
149*16548Sslatteng 	    c = getc(fp);
150*16548Sslatteng 	    do {
151*16548Sslatteng 		k = 10 * k - ((*op++ = c) - '0');
152*16548Sslatteng 	    } while (isdigit(c = getc(fp)));
153*16548Sslatteng 	} else {
154*16548Sslatteng 	    do {
155*16548Sslatteng 		k = 10 * k + (*op++ = c) - '0';
156*16548Sslatteng 	    } while (isdigit(c = getc(fp)));
157*16548Sslatteng 	}
15814758Sslatteng 	ungetc(c, fp);
15914758Sslatteng 	return (k);
16013918Sslatteng }
16113918Sslatteng 
16213918Sslatteng 			/* read number from input:  do _N_O_T copy to output */
ngetnumber(fp)16313918Sslatteng int ngetnumber (fp)
16413918Sslatteng register FILE *fp;
16513918Sslatteng {
16614758Sslatteng 	register int k;
16714758Sslatteng 	register char c;
16813918Sslatteng 
169*16548Sslatteng 	while (isspace(c = getc(fp)))
17014758Sslatteng 	    ;
17114758Sslatteng 	k = 0;
172*16548Sslatteng 	if (c == '-') {
173*16548Sslatteng 	    c = getc(fp);
174*16548Sslatteng 	    do {
175*16548Sslatteng 		k = 10 * k - (c - '0');
176*16548Sslatteng 	    } while (isdigit(c = getc(fp)));
177*16548Sslatteng 	} else {
178*16548Sslatteng 	    do {
179*16548Sslatteng 		k = 10 * k + c - '0';
180*16548Sslatteng 	    } while (isdigit(c = getc(fp)));
181*16548Sslatteng 	}
18214758Sslatteng 	ungetc(c, fp);
18314758Sslatteng 	return (k);
18413918Sslatteng }
18513918Sslatteng 
18613918Sslatteng 
conv(fp)18713918Sslatteng conv(fp)
18813918Sslatteng register FILE *fp;
18913918Sslatteng {
19013918Sslatteng 	register int c;
19113918Sslatteng 	int m, n, m1, n1;
19213918Sslatteng 
19313918Sslatteng 	while ((c = getc(fp)) != EOF) {
19414297Sslatteng #ifdef DEBUGABLE
19514758Sslatteng 	    if (dbg > 2) fprintf(stderr, "%c i=%d V=%d\n", c, op-obuf, vpos);
19614297Sslatteng #endif
19715277Sslatteng 	    if (op > obuf + obufsiz) {
19815277Sslatteng 		error(!FATAL, "buffer overflow %d.", op - (obuf + obufsiz));
19913918Sslatteng 		oflush();
20015277Sslatteng 	    }
20113918Sslatteng 	    switch (c) {
20216183Sslatteng 		case '\0':	/* filter out noise */
20316183Sslatteng 			break;
20413918Sslatteng 		case '\n':	/* let text input through */
20513918Sslatteng 		case '\t':
20613918Sslatteng 		case ' ':
20713918Sslatteng 			*op++ = c;
20813918Sslatteng 			break;
20913918Sslatteng 		case '{':	/* push down current environment */
21013918Sslatteng 			*op++ = c;
21113918Sslatteng 			t_push();
21213918Sslatteng 			break;
21313918Sslatteng 		case '}':	/* pop up last environment */
21413918Sslatteng 			*op++ = c;
21513918Sslatteng 			t_pop();
21613918Sslatteng 			break;
21713918Sslatteng 		case '0': case '1': case '2': case '3': case '4':
21813918Sslatteng 		case '5': case '6': case '7': case '8': case '9':
21913918Sslatteng 				/* two motion digits plus a character */
22015946Sslatteng 			setlimit(vpos - up, vpos + down);
22113918Sslatteng 			*op++ = c;
22213918Sslatteng 			hmot((c-'0') * 10 + (*op++ = getc(fp)) - '0');
22313918Sslatteng 			*op++ = getc(fp);
22413918Sslatteng 			break;
22513918Sslatteng 		case 'c':	/* single ascii character */
22615946Sslatteng 			setlimit(vpos - up, vpos + down);
22713918Sslatteng 			*op++ = c;
22813918Sslatteng 			*op++ = getc(fp);
22913918Sslatteng 			break;
23013918Sslatteng 		case 'C':	/* white-space terminated funny character */
23115946Sslatteng 			setlimit(vpos - up, vpos + down);
23213918Sslatteng 			*op++ = c;
23316183Sslatteng 			do
23416183Sslatteng 			    *op++ = c = getc(fp);
235*16548Sslatteng 			while (c != EOF && !isspace(c));
23613918Sslatteng 			break;
23713918Sslatteng 		case 't':	/* straight text */
23815946Sslatteng 			setlimit(vpos - up, vpos + down);
23913918Sslatteng 			*op++ = c;
24013918Sslatteng 			fgets(op, SLOP, fp);
24113918Sslatteng 			op += strlen(op);
24213918Sslatteng 			break;
24313918Sslatteng 		case 'D':	/* draw function */
244*16548Sslatteng 			switch (c = getc(fp)) {
24514285Sslatteng 			case 's':	/* "style" */
246*16548Sslatteng 				sprintf(op, "Ds ");
247*16548Sslatteng 				op += 3;
248*16548Sslatteng 				style = getnumber(fp);
24914285Sslatteng 				break;
250*16548Sslatteng 
25114285Sslatteng 			case 't':	/* thickness */
252*16548Sslatteng 				sprintf(op, "Dt ");
253*16548Sslatteng 				op += 3;
254*16548Sslatteng 				thick = getnumber(fp);
25514285Sslatteng 				break;
256*16548Sslatteng 
25713918Sslatteng 			case 'l':	/* draw a line */
258*16548Sslatteng 				n = ngetnumber(fp);
259*16548Sslatteng 				m = ngetnumber(fp);
26013918Sslatteng 				if (m < 0) {
26115946Sslatteng 				    setlimit(vpos+m-thick/2, vpos+thick/2);
26214758Sslatteng 				} else {
26316183Sslatteng 				    setlimit(vpos-(1+thick/2),vpos+1+m+thick/2);
26413918Sslatteng 				}
265*16548Sslatteng 				sprintf(op, "Dl %d %d", n, m);
26613918Sslatteng 				op += strlen(op);
26713918Sslatteng 				hmot(n);
26813918Sslatteng 				vmot(m);
26913918Sslatteng 				break;
270*16548Sslatteng 
271*16548Sslatteng 			case 'e':	/* ellipse */
272*16548Sslatteng 				n = ngetnumber(fp);
273*16548Sslatteng 				m = ngetnumber(fp);
274*16548Sslatteng 				setlimit(vpos-(m+thick)/2, vpos+(m+thick)/2);
275*16548Sslatteng 				sprintf(op, "De %d %d", n, m);
276*16548Sslatteng 				op += strlen(op);
277*16548Sslatteng 				hmot(n);
278*16548Sslatteng 				break;
279*16548Sslatteng 
28013918Sslatteng 			case 'c':	/* circle */
281*16548Sslatteng 				n = ngetnumber(fp);
28215946Sslatteng 				setlimit(vpos-(n+thick)/2, vpos+(n+thick)/2);
283*16548Sslatteng 				sprintf(op, "Dc %d", n);
28414758Sslatteng 				op += strlen(op);
28513918Sslatteng 				hmot(n);
28613918Sslatteng 				break;
287*16548Sslatteng 
28813918Sslatteng 			case 'a':	/* arc */
289*16548Sslatteng 				n = getnumber(fp);
290*16548Sslatteng 				m = getnumber(fp);
291*16548Sslatteng 				n1 = getnumber(fp);
292*16548Sslatteng 				m1 = getnumber(fp);
29314758Sslatteng 				arcbounds(n, m, n1, m1);
294*16548Sslatteng 				sprintf(op, "Da %d %d %d %d", n, m, n1, m1);
29513918Sslatteng 				op += strlen(op);
29614758Sslatteng 				hmot(n + n1);
29714758Sslatteng 				vmot(m + m1);
29813918Sslatteng 				break;
299*16548Sslatteng 
300*16548Sslatteng 			case 'P':
301*16548Sslatteng 			case 'p':
30213918Sslatteng 			    {
303*16548Sslatteng 				register int nvect;
304*16548Sslatteng 				int member;
305*16548Sslatteng 				int border;
306*16548Sslatteng 				int x[MAXVECT];
307*16548Sslatteng 				int y[MAXVECT];
30815946Sslatteng 
309*16548Sslatteng 
310*16548Sslatteng 				border = (c == 'p');	/* type of polygon */
311*16548Sslatteng 				member = ngetnumber(fp);/* and member number */
312*16548Sslatteng 
313*16548Sslatteng 				nvect = 1;		/* starting point for */
314*16548Sslatteng 				x[1] = hpos;		/* points on polygon */
315*16548Sslatteng 				y[1] = vpos;
31614758Sslatteng 				m = n = vpos;		/* = max/min vertical */
31713918Sslatteng 							/* position for curve */
318*16548Sslatteng 				{
319*16548Sslatteng 				    register int h;
320*16548Sslatteng 				    register int v;
32113918Sslatteng 
322*16548Sslatteng 
323*16548Sslatteng 				    h = hpos;	/* calculate max and minimum */
324*16548Sslatteng 				    v = vpos;		/* vertical position */
325*16548Sslatteng 							/*    and get points */
326*16548Sslatteng 				    do {
327*16548Sslatteng 					h += ngetnumber(fp);
328*16548Sslatteng 					v += ngetnumber(fp);
329*16548Sslatteng 
330*16548Sslatteng 					if (v < n) n = v;
331*16548Sslatteng 					else if (v > m) m = v;
332*16548Sslatteng 
333*16548Sslatteng 					if (nvect < (MAXVECT-1))/* keep the */
334*16548Sslatteng 					    nvect++;		/* points in */
335*16548Sslatteng 					x[nvect] = h;		/* bounds */
336*16548Sslatteng 					y[nvect] = v;		/* of arrays */
337*16548Sslatteng 					c = getc(fp);
338*16548Sslatteng 				    } while (c != '\n' && c != EOF);
339*16548Sslatteng 				}
340*16548Sslatteng 				if (border) {		/* output border as a */
341*16548Sslatteng 				    register int *x1;	/*  bunch of lines */
342*16548Sslatteng 				    register int *x2;	/*  instead of having */
343*16548Sslatteng 				    register int *y1;	/*  the filter do it */
344*16548Sslatteng 				    register int *y2;
345*16548Sslatteng 				    register int extra = thick/2;
346*16548Sslatteng 
347*16548Sslatteng 				    x1 = &(x[0]);	/* x1, y1, x2, y2 are */
348*16548Sslatteng 				    x2 = &(x[1]);	/* for indexing along */
349*16548Sslatteng 				    y1 = &(y[0]);	/* coordinate arrays */
350*16548Sslatteng 				    y2 = &(y[1]);
351*16548Sslatteng 				    for (border = 0; ++border < nvect; ) {
352*16548Sslatteng 					if (*++y1 > *++y2) {
353*16548Sslatteng 					   setlimit(*y2-extra, vpos+extra);
354*16548Sslatteng 					} else {
355*16548Sslatteng 					   setlimit(vpos-(1+extra),*y2+1+extra);
356*16548Sslatteng 						/* the extra 1's are to force */
357*16548Sslatteng 						/* setlimit to know this is a */
358*16548Sslatteng 						/* real entry (making sure it */
359*16548Sslatteng 						/* doesn't get vpos as limit */
360*16548Sslatteng 					}
361*16548Sslatteng 					sprintf(op, "Dl %d %d\n",
362*16548Sslatteng 						c = *++x2 - *++x1, *y2 - *y1);
363*16548Sslatteng 					op += strlen(op);
364*16548Sslatteng 					hmot(c);	/* update vpos for */
365*16548Sslatteng 					vgoto(*y2);	/* the setlimit call */
366*16548Sslatteng 				    }
367*16548Sslatteng 				} else {
368*16548Sslatteng 				    register int *x1;	/* x1, x2, are for */
369*16548Sslatteng 				    register int *x2;	/* indexing points */
370*16548Sslatteng 				    register int i;	/* random int */
371*16548Sslatteng 
372*16548Sslatteng 				    x1 = &(x[0]);
373*16548Sslatteng 				    x2 = &(x[1]);
374*16548Sslatteng 				    for (i = 0; ++i < nvect; ) {
375*16548Sslatteng 					hmot(*++x2 - *++x1);
376*16548Sslatteng 				    }
377*16548Sslatteng 				    vgoto(y[nvect]);
378*16548Sslatteng 				    sprintf(op, "H%dV%d", hpos, vpos);
379*16548Sslatteng 				    op += strlen(op);
380*16548Sslatteng 				}
381*16548Sslatteng 				if (member) {
382*16548Sslatteng 				    polygon(member, nvect, x, y, m, n);
383*16548Sslatteng 				}
38413918Sslatteng 			    }
38513918Sslatteng 			    break;
38613918Sslatteng 
387*16548Sslatteng 			case '~':	/* wiggly line */
388*16548Sslatteng 			case 'g':	/* gremlin curve */
389*16548Sslatteng 			    startspan(vpos);		/* always put curve */
390*16548Sslatteng 			    sprintf(op, "D%c ", c);	/* on its own span */
391*16548Sslatteng 			    op += 3;
392*16548Sslatteng 
393*16548Sslatteng 			    m = n = vpos;		/* = max/min vertical */
394*16548Sslatteng 			    do {			/* position for curve */
395*16548Sslatteng 				hpos += getnumber(fp);
396*16548Sslatteng 				*op++ = ' ';
397*16548Sslatteng 				vpos += getnumber(fp);
398*16548Sslatteng 				*op++ = ' ';
399*16548Sslatteng 
400*16548Sslatteng 				if (vpos < n) n = vpos;
401*16548Sslatteng 				else if (vpos > m) m = vpos;
402*16548Sslatteng 
403*16548Sslatteng 				c = getc(fp);
404*16548Sslatteng 			    } while (c != '\n' && c != EOF);
405*16548Sslatteng 
406*16548Sslatteng 			    vlp->u = n < 0 ? 0 : n;
407*16548Sslatteng 			    vlp->d = m;
408*16548Sslatteng 			    *op++ = '\n';
409*16548Sslatteng 			    startspan(vpos);
410*16548Sslatteng 			    break;
411*16548Sslatteng 
41213918Sslatteng 			default:
413*16548Sslatteng 				error(FATAL,"unknown drawing command %c", c);
41413918Sslatteng 				break;
41513918Sslatteng 			}
41613918Sslatteng 			break;
41713918Sslatteng 		case 's':
41813918Sslatteng 			*op++ = c;
41914758Sslatteng 			size = getnumber(fp);
42016183Sslatteng 			up = ((size + 1)*INCH) / POINT;	/* ROUGH estimate */
42115277Sslatteng 			down = up / 3;			/* of max up/down */
42213918Sslatteng 			break;
42313918Sslatteng 		case 'f':
42413918Sslatteng 			*op++ = c;
42514758Sslatteng 			font = getnumber(fp);
42613918Sslatteng 			break;
427*16548Sslatteng 		case 'i':
428*16548Sslatteng 			*op++ = c;
429*16548Sslatteng 			stip = getnumber(fp);
430*16548Sslatteng 			break;
43113918Sslatteng 		case 'H':	/* absolute horizontal motion */
43214758Sslatteng 			hgoto(ngetnumber(fp));
433*16548Sslatteng 			sprintf(op, "H%d", hpos);
43414758Sslatteng 			op += strlen(op);	/* reposition by page offset */
43513918Sslatteng 			break;
43613918Sslatteng 		case 'h':	/* relative horizontal motion */
43713918Sslatteng 			*op++ = c;
43814758Sslatteng 			hmot(getnumber(fp));
43913918Sslatteng 			break;
44013918Sslatteng 		case 'w':	/* useless */
44113918Sslatteng 			break;
44213918Sslatteng 		case 'V':	/* absolute vertical motion */
443*16548Sslatteng 			*op++ = c;
444*16548Sslatteng 			vgoto(getnumber(fp));
44513918Sslatteng 			break;
44613918Sslatteng 		case 'v':
447*16548Sslatteng 			*op++ = c;
448*16548Sslatteng 			vmot(getnumber(fp));
44913918Sslatteng 			break;
45013918Sslatteng 		case 'p':	/* new page */
45114758Sslatteng 			t_page(ngetnumber(fp));
45213918Sslatteng 			vpos = 0;
45313918Sslatteng 			break;
45413918Sslatteng 		case 'n':	/* end of line */
45514758Sslatteng 			hpos = leftmarg;
45616183Sslatteng 			*op++ = c;
45716183Sslatteng 			do
45816183Sslatteng 			    *op++ = c = getc(fp);
45916183Sslatteng 			while (c != '\n' && c != EOF);
46016183Sslatteng 			break;
46113918Sslatteng 		case '#':	/* comment */
46216183Sslatteng 			do
46316183Sslatteng 			    c = getc(fp);
46416183Sslatteng 			while (c != '\n' && c != EOF);
46516183Sslatteng 			break;
46614758Sslatteng 		case 'x':	/* device control */
46715946Sslatteng 			startspan(vpos);
46813918Sslatteng 			*op++ = c;
46916183Sslatteng 			do
47016183Sslatteng 			    *op++ = c = getc(fp);
47116183Sslatteng 			while (c != '\n' && c != EOF);
47213918Sslatteng 			break;
47313918Sslatteng 		default:
47416183Sslatteng 			error(!FATAL, "unknown input character %o %c", c, c);
47513918Sslatteng 			done();
47613918Sslatteng 	    }
47713918Sslatteng 	}
47813918Sslatteng }
47913918Sslatteng 
48015277Sslatteng 
48115277Sslatteng /*----------------------------------------------------------------------------*
48215277Sslatteng  | Routine:	setlimit
48315277Sslatteng  |
48415946Sslatteng  | Results:	using "newup" and "newdown" decide when to start a new span.
48515946Sslatteng  |		maximum rise and/or fall of a vertical extent are saved.
48615277Sslatteng  |
48715946Sslatteng  | Side Efct:	may start new span.
48815277Sslatteng  *----------------------------------------------------------------------------*/
48915277Sslatteng 
490*16548Sslatteng #define diffspan(x,y)	((x)/NLINES != (y)/NLINES)
49115946Sslatteng 
setlimit(newup,newdown)49215946Sslatteng setlimit(newup, newdown)
49315946Sslatteng register int newup;
49415946Sslatteng register int newdown;
49514758Sslatteng {
49615946Sslatteng 	register int currup = vlp->u;
49715946Sslatteng 	register int currdown = vlp->d;
49813918Sslatteng 
49915946Sslatteng 	if (newup < 0) newup = 0;	/* don't go back beyond start of page */
50015946Sslatteng 	if (newdown < 0) newdown = 0;
50115946Sslatteng 
50215946Sslatteng 	if (diffspan(currup, currdown)) {	/* now spans > one band */
50316183Sslatteng 	    if (diffspan(newup, currup) || diffspan(newdown, currdown)) {
50415946Sslatteng 		startspan (vpos);
50515946Sslatteng 		vlp->u = newup;
50615946Sslatteng 		vlp->d = newdown;
50716183Sslatteng 	    } else {
50816183Sslatteng 		if (newup < currup) vlp->u = newup;
50916183Sslatteng 		if (newdown > currdown) vlp->d = newdown;
51015946Sslatteng 	    }
51115946Sslatteng 	} else {
51215946Sslatteng 	    if (newup < currup) {	/* goes farther up than before */
51315946Sslatteng 		if (currup == vlp->v) {		/* is new span, just set "up" */
51415946Sslatteng 		    vlp->u = newup;
51515946Sslatteng 		} else {
51615946Sslatteng 		    if (diffspan(newup, currup)) {	/* goes up farther */
51715946Sslatteng 			startspan(vpos);		/* than previously */
51815946Sslatteng 			vlp->u = newup;			/* AND to a higher */
51915946Sslatteng 			vlp->d = newdown;		/* band.  */
52015946Sslatteng 			return;
52115946Sslatteng 		    } else {
52215946Sslatteng 			vlp->u = newup;
52315946Sslatteng 		    }
52415946Sslatteng 		}
52515946Sslatteng 	    }
52615946Sslatteng 	    if (newdown > currdown) {
52715946Sslatteng 		if (currdown == vlp->v) {
52815946Sslatteng 		    vlp->d = newdown;
52915946Sslatteng 		    return;
53015946Sslatteng 		} else {
53115946Sslatteng 		    if (diffspan(newdown, currdown)) {
53215946Sslatteng 			startspan(vpos);
53315946Sslatteng 			vlp->u = newup;
53415946Sslatteng 			vlp->d = newdown;
53515946Sslatteng 			return;
53615946Sslatteng 		    } else {
53715946Sslatteng 			vlp->d = newdown;
53815946Sslatteng 		    }
53915946Sslatteng 		}
54015946Sslatteng 	    }
54115946Sslatteng 	}
54214758Sslatteng }
54314758Sslatteng 
54414758Sslatteng 
54515277Sslatteng /*----------------------------------------------------------------------------*
54615277Sslatteng  | Routine:	arcbounds (h, v, h1, v1)
54715277Sslatteng  |
54815277Sslatteng  | Results:	using the horizontal positions of the starting and ending
54915277Sslatteng  |		points relative to the center and vertically relative to
55015277Sslatteng  |		each other, arcbounds calculates the upper and lower extent
55115277Sslatteng  |		of the arc which is one of:  starting point, ending point
55215277Sslatteng  |		or center + rad for bottom, and center - rad for top.
55315277Sslatteng  |
55415946Sslatteng  | Side Efct:	calls setlimit(up, down) to save the extent information.
55515277Sslatteng  *----------------------------------------------------------------------------*/
55615277Sslatteng 
arcbounds(h,v,h1,v1)55715277Sslatteng arcbounds(h, v, h1, v1)
55815277Sslatteng int h, v, h1, v1;
55914758Sslatteng {
56015616Sslatteng 	register unsigned rad = (int)(sqrt((double)(h*h + v*v)) + 0.5);
56115277Sslatteng 	register int i = ((h >= 0) << 2) | ((h1 < 0) << 1) | ((v + v1) < 0);
56215277Sslatteng 
56315277Sslatteng 			/* i is a set of flags for the points being on the */
56415277Sslatteng 			/* left of the center point, and which is higher */
56515277Sslatteng 
56615277Sslatteng 	v1 += vpos + v;		/* v1 is vertical position of ending point */
56715277Sslatteng 				/* test relative positions for maximums */
56815946Sslatteng 	setlimit(		/* and set the up/down of the arc */
56915946Sslatteng 	    ((((i&3)==1) ? v1 : (((i&5)==4) ? vpos : vpos+v-rad)) - thick/2),
57015946Sslatteng 	    ((((i&3)==2) ? v1 : (((i&5)==1) ? vpos : vpos+v+rad)) + thick/2));
57114758Sslatteng }
57214758Sslatteng 
57314758Sslatteng 
oflush()57413918Sslatteng oflush()	/* sort, then dump out contents of obuf */
57513918Sslatteng {
57613918Sslatteng 	register struct vlist *vp;
57714758Sslatteng 	register int notdone;
57814758Sslatteng 	register int topv;
57914758Sslatteng 	register int botv;
58014285Sslatteng 	register int i;
58114758Sslatteng 	register char *p;
58213918Sslatteng 
58314297Sslatteng #ifdef DEBUGABLE
58413918Sslatteng 	if (dbg) fprintf(stderr, "into oflush, V=%d\n", vpos);
58514297Sslatteng #endif
58613918Sslatteng 	if (op == obuf)
58713918Sslatteng 		return;
58816183Sslatteng 	*op = 0;
58913918Sslatteng 
59014758Sslatteng 	topv = 0;
59114758Sslatteng 	botv = NLINES - 1;
59214758Sslatteng 	do {
59314758Sslatteng 	    notdone = 0;
59414758Sslatteng 	    vp = vlist;
59514758Sslatteng #ifdef DEBUGABLE
59614758Sslatteng 	    if (dbg) fprintf(stderr, "topv=%d, botv=%d\n", topv, botv);
59714758Sslatteng #endif
59814758Sslatteng 	    for (i = 0; i < nvlist; i++, vp++) {
59914758Sslatteng #ifdef DEBUGABLE
60014758Sslatteng 		if(dbg>1)fprintf(stderr,"u=%d, d=%d,%.60s\n",vp->u,vp->d,vp->p);
60114758Sslatteng #endif
60214758Sslatteng 		if (vp->u <= botv && vp->d >= topv) {
603*16548Sslatteng 		    printf("H%dV%ds%df%d\ni%d\nDs%d\nDt%d\n%s",
604*16548Sslatteng 			 vp->h,vp->v,vp->s,vp->f,vp->l,vp->st,vp->t,vp->p);
60514758Sslatteng 		}
60614758Sslatteng 		notdone |= vp->d > botv;	/* not done if there's still */
60714758Sslatteng 	    }					/* something to put lower */
60814758Sslatteng 	    if (notdone) putchar('P');		/* mark the end of the spread */
60914758Sslatteng 	    topv += NLINES;			/* unless it's the last one */
61014758Sslatteng 	    botv += NLINES;
61114758Sslatteng 	} while (notdone);
61214758Sslatteng 
61313918Sslatteng 	fflush(stdout);
61413918Sslatteng 	vlp = vlist;
61513918Sslatteng 	vlp->p = op = obuf;
61613918Sslatteng 	vlp->h = hpos;
61713918Sslatteng 	vlp->v = vpos;
61814758Sslatteng 	vlp->u = vpos;
61914758Sslatteng 	vlp->d = vpos;
62013918Sslatteng 	vlp->s = size;
62113918Sslatteng 	vlp->f = font;
622*16548Sslatteng 	vlp->l = stip;
62314285Sslatteng 	vlp->st = style;
62414285Sslatteng 	vlp->t = thick;
62513918Sslatteng 	*op = 0;
62613918Sslatteng 	nvlist = 1;
62713918Sslatteng }
62813918Sslatteng 
62913918Sslatteng 
done()63013918Sslatteng done()
63113918Sslatteng {
63213918Sslatteng 	oflush();
63313918Sslatteng 	exit(0);
63413918Sslatteng }
63513918Sslatteng 
error(f,s,a1,a2,a3,a4,a5,a6,a7)63613918Sslatteng error(f, s, a1, a2, a3, a4, a5, a6, a7) {
63713918Sslatteng 	fprintf(stderr, "vsort: ");
63813918Sslatteng 	fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7);
63913918Sslatteng 	fprintf(stderr, "\n");
64013918Sslatteng 	if (f)
64113918Sslatteng 		done();
64213918Sslatteng }
64313918Sslatteng 
64413918Sslatteng #define	MAXSTATE	5
64513918Sslatteng 
64613918Sslatteng struct state {
64713918Sslatteng 	int	ssize;
64813918Sslatteng 	int	sfont;
64913918Sslatteng 	int	shpos;
65013918Sslatteng 	int	svpos;
65113918Sslatteng };
65213918Sslatteng struct	state	state[MAXSTATE];
65313918Sslatteng struct	state	*statep = state;
65413918Sslatteng 
t_push()65513918Sslatteng t_push()	/* begin a new block */
65613918Sslatteng {
65713918Sslatteng 	statep->ssize = size;
65813918Sslatteng 	statep->sfont = font;
65913918Sslatteng 	statep->shpos = hpos;
66013918Sslatteng 	statep->svpos = vpos;
66113918Sslatteng 	hpos = vpos = 0;
66213918Sslatteng 	if (statep++ >= state+MAXSTATE)
66313918Sslatteng 		error(FATAL, "{ nested too deep");
66413918Sslatteng 	hpos = vpos = 0;
66513918Sslatteng }
66613918Sslatteng 
t_pop()66713918Sslatteng t_pop()	/* pop to previous state */
66813918Sslatteng {
66913918Sslatteng 	if (--statep < state)
67013918Sslatteng 		error(FATAL, "extra }");
67113918Sslatteng 	size = statep->ssize;
67213918Sslatteng 	font = statep->sfont;
67313918Sslatteng 	hpos = statep->shpos;
67413918Sslatteng 	vpos = statep->svpos;
67513918Sslatteng }
67613918Sslatteng 
67713918Sslatteng 
67815946Sslatteng /*----------------------------------------------------------------------------*
67915946Sslatteng  | Routine:	t_page
68015946Sslatteng  |
68115946Sslatteng  | Results:	new Margins are calculated for putting pages side-by-side.
68215946Sslatteng  |		If no more pages can fit across the paper (WIDTH wide)
68315946Sslatteng  |		a real page end is done and the currrent page is output.
68415946Sslatteng  |
68515946Sslatteng  | Side Efct:	oflush is called on a REAL page boundary.
68615946Sslatteng  *----------------------------------------------------------------------------*/
68715946Sslatteng 
t_page(n)68814758Sslatteng t_page(n)
68914758Sslatteng int n;
69014758Sslatteng {
69115277Sslatteng     static int first = 1;		/* flag to catch the 1st time through */
69214758Sslatteng 
69315277Sslatteng     				/* if we're near the edge, we'll go over on */
69415277Sslatteng     if (leftmarg + 2*(pageno ? leftmarg/pageno : 0) > WIDTH	/* this page, */
69515277Sslatteng 	  || maxh > WIDTH - INCH || first) {	/* or this is the first page */
69615277Sslatteng 	oflush();
69716375Sslatteng 	printf("p%d\n", spanno++);		/* make it a REAL page-break */
69815277Sslatteng 	first = pageno = leftmarg = maxh = 0;
69915277Sslatteng     } else {			    /* x = last page's width (in half-inches) */
70015277Sslatteng 	register int x = (maxh - leftmarg + (HALF - 1)) / HALF;
70115277Sslatteng 
70215277Sslatteng 	if (x > 11 && x <= 17)
70314758Sslatteng 	    leftmarg += (8 * INCH) + HALF; 		/* if close to 8.5"  */
70414758Sslatteng 	else						/* then make it so   */
70514758Sslatteng 	    leftmarg = ((maxh + HALF) / HALF) * HALF;	/* else set it to the */
70615277Sslatteng 	pageno++;					/* nearest half-inch */
70715277Sslatteng     }
70814758Sslatteng }
70914758Sslatteng 
71014758Sslatteng 
startspan(n)71113918Sslatteng startspan(n)
71213918Sslatteng register int n;
71313918Sslatteng {
71413918Sslatteng 	*op++ = 0;
71513918Sslatteng 	if (nvlist >= NVLIST) {
71615946Sslatteng #ifdef DEBUGABLE
71715946Sslatteng 	    error(!FATAL, "ran out of vlist");
71815946Sslatteng #endif
71913918Sslatteng 	    oflush();
72013918Sslatteng 	}
72114758Sslatteng 	vlp++;
72213918Sslatteng 	vlp->p = op;
72313918Sslatteng 	vlp->v = n;
72414758Sslatteng 	vlp->d = n;
72514758Sslatteng 	vlp->u = n;
72613918Sslatteng 	vlp->h = hpos;
72713918Sslatteng 	vlp->s = size;
72813918Sslatteng 	vlp->f = font;
729*16548Sslatteng 	vlp->l = stip;
73014285Sslatteng 	vlp->st = style;
73114285Sslatteng 	vlp->t = thick;
73213918Sslatteng 	nvlist++;
73313918Sslatteng }
734*16548Sslatteng 
735*16548Sslatteng 
736*16548Sslatteng #define MAXX	0x7fff
737*16548Sslatteng #define MINX	0x8000
738*16548Sslatteng 
739*16548Sslatteng typedef struct poly {
740*16548Sslatteng 	struct poly *next;	/* doublely-linked lists of vectors */
741*16548Sslatteng 	struct poly *prev;
742*16548Sslatteng 	int param;	/* bressenham line algorithm parameter */
743*16548Sslatteng 	short dx;	/* delta-x for calculating line */
744*16548Sslatteng 	short dy;	/* delta-y for calculating line */
745*16548Sslatteng 	short currx;	/* current x in this vector */
746*16548Sslatteng 	short endy;	/* where vector ends */
747*16548Sslatteng } polyvector;
748*16548Sslatteng 
749*16548Sslatteng 
750*16548Sslatteng /*----------------------------------------------------------------------------*
751*16548Sslatteng  | Routine:	polygon ( member, num_vectors, x_coor, y_coor, maxy, miny )
752*16548Sslatteng  |
753*16548Sslatteng  | Results:	outputs commands to draw a polygon starting at (x[1], y[1])
754*16548Sslatteng  |		going through each of (x_coordinates, y_coordinates), and
755*16548Sslatteng  |		filled with "member" stipple pattern.
756*16548Sslatteng  |
757*16548Sslatteng  |		A scan-line algorithm is simulated and pieces of the
758*16548Sslatteng  |		polygon are put out that fit on bands of the versatec
759*16548Sslatteng  |		output filter.
760*16548Sslatteng  |
761*16548Sslatteng  |		The format of the polygons put out are:
762*16548Sslatteng  |			'Dp member num miny maxy [p dx dy curx endy]'
763*16548Sslatteng  |		where "num" is the number of [..] entries in that
764*16548Sslatteng  |		section of the polygon.
765*16548Sslatteng  *----------------------------------------------------------------------------*/
766*16548Sslatteng 
polygon(member,nvect,x,y,maxy,miny)767*16548Sslatteng polygon(member, nvect, x, y, maxy, miny)
768*16548Sslatteng int member;
769*16548Sslatteng int nvect;
770*16548Sslatteng int x[];
771*16548Sslatteng int y[];
772*16548Sslatteng int maxy;
773*16548Sslatteng int miny;
774*16548Sslatteng {
775*16548Sslatteng     int nexty;			/* at what x value the next vector starts */
776*16548Sslatteng     register int active;	/* number of vectors in active list */
777*16548Sslatteng     int firsttime;		/* force out a polgon the first time through */
778*16548Sslatteng     polyvector *activehead;		/* doing fill, is active edge list */
779*16548Sslatteng     polyvector *waitinghead;		/* edges waiting to be active */
780*16548Sslatteng     register polyvector *vectptr;	/* random vector */
781*16548Sslatteng     register int i;			/* random register */
782*16548Sslatteng 
783*16548Sslatteng 
784*16548Sslatteng 				/* allocate space for raster-fill algorithm*/
785*16548Sslatteng     vectptr = (polyvector *) malloc(sizeof(polyvector) * (nvect + 4));
786*16548Sslatteng     if (vectptr == (polyvector *) NULL) {
787*16548Sslatteng 	error(!FATAL, "unable to allocate space for polygon");
788*16548Sslatteng 	return;
789*16548Sslatteng     }
790*16548Sslatteng 
791*16548Sslatteng     waitinghead = vectptr;
792*16548Sslatteng     vectptr->param = miny - 1;
793*16548Sslatteng     (vectptr++)->prev = NULL;		/* put dummy entry at start */
794*16548Sslatteng     waitinghead->next = vectptr;
795*16548Sslatteng     vectptr->prev = waitinghead;
796*16548Sslatteng     i = 1;					/* starting point of coords */
797*16548Sslatteng     if (y[1] != y[nvect] || x[1] != x[nvect]) {
798*16548Sslatteng 	y[0] = y[nvect];			/* close polygon if it's not */
799*16548Sslatteng 	x[0] = x[nvect];
800*16548Sslatteng 	i = 0;
801*16548Sslatteng     }
802*16548Sslatteng     active = 0;
803*16548Sslatteng     while (i < nvect) {		/* set up the vectors */
804*16548Sslatteng 	register int j;			/* indexes to work off of */
805*16548Sslatteng 	register int k;
806*16548Sslatteng 
807*16548Sslatteng 	j = i;			/* j "points" to the higher (lesser) point */
808*16548Sslatteng 	k = ++i;
809*16548Sslatteng 	if (y[j] == y[k])		/* ignore horizontal lines */
810*16548Sslatteng 	    continue;
811*16548Sslatteng 
812*16548Sslatteng 	if (y[j] > y[k]) {
813*16548Sslatteng 	    j++;
814*16548Sslatteng 	    k--;
815*16548Sslatteng 	}
816*16548Sslatteng 	active++;
817*16548Sslatteng 	vectptr->next = vectptr + 1;
818*16548Sslatteng 	vectptr->param = y[j];		/* starting point of vector */
819*16548Sslatteng 	vectptr->dx = x[k] - x[j];	/* line-calculating parameters */
820*16548Sslatteng 	vectptr->dy = y[k] - y[j];
821*16548Sslatteng 	vectptr->currx = x[j];		/* starting point */
822*16548Sslatteng 	(vectptr++)->endy = y[k];	/* ending point */
823*16548Sslatteng 	vectptr->prev = vectptr - 1;
824*16548Sslatteng     }
825*16548Sslatteng 					/* if no useable vectors, quit */
826*16548Sslatteng     if (active < 2)
827*16548Sslatteng 	goto leavepoly;
828*16548Sslatteng 
829*16548Sslatteng     vectptr->param = maxy + 1;		/* dummy entry at end, too */
830*16548Sslatteng     vectptr->next = NULL;
831*16548Sslatteng 
832*16548Sslatteng     activehead = ++vectptr;		/* two dummy entries for active list */
833*16548Sslatteng     vectptr->currx = MINX;		/* head */
834*16548Sslatteng     vectptr->endy = maxy + 1;
835*16548Sslatteng     vectptr->param = vectptr->dx = vectptr->dy = 0;
836*16548Sslatteng     activehead->next = ++vectptr;
837*16548Sslatteng     activehead->prev = vectptr;
838*16548Sslatteng     vectptr->prev = activehead;		/* tail */
839*16548Sslatteng     vectptr->next = activehead;
840*16548Sslatteng     vectptr->currx = MAXX;
841*16548Sslatteng     vectptr->endy = maxy + 1;
842*16548Sslatteng     vectptr->param = vectptr->dx = vectptr->dy = 0;
843*16548Sslatteng 
844*16548Sslatteng 					/* if there's no need to break the */
845*16548Sslatteng 					/* polygon into pieces, don't bother */
846*16548Sslatteng     if (diffspan(miny, maxy)) {
847*16548Sslatteng 	active = 0;			/* will keep track of # of vectors */
848*16548Sslatteng 	firsttime = 1;
849*16548Sslatteng     } else {				/*   in the active list */
850*16548Sslatteng 	startspan(miny);
851*16548Sslatteng 	sprintf(op, "Dq %d %d %d %d", member, active, miny, maxy);
852*16548Sslatteng 	op += strlen(op);
853*16548Sslatteng 	for (vectptr = waitinghead->next; active--; vectptr++) {
854*16548Sslatteng 	    sprintf(op, " %d %d %d %d %d",
855*16548Sslatteng 		vectptr->param, vectptr->dx, vectptr->dy,
856*16548Sslatteng 		vectptr->currx, vectptr->endy);
857*16548Sslatteng 	    op += strlen(op);
858*16548Sslatteng 	}
859*16548Sslatteng 	*(op++) = '\n';
860*16548Sslatteng 	goto leavepoly;
861*16548Sslatteng     }
862*16548Sslatteng 			/* main loop -- gets vectors off the waiting list, */
863*16548Sslatteng 			/* then displays spans while updating the vectors in */
864*16548Sslatteng     			/* the active list */
865*16548Sslatteng     while (miny <= maxy) {
866*16548Sslatteng 	i = maxy + 1;		/* this is the NEXT time to get a new vector */
867*16548Sslatteng 	for (vectptr = waitinghead->next; vectptr != NULL; ) {
868*16548Sslatteng 	    if (miny == vectptr->param) {
869*16548Sslatteng 				/* the entry in waiting list (vectptr) is */
870*16548Sslatteng 				/*   ready to go into active list.  Need to */
871*16548Sslatteng 				/*   convert some vector stuff and sort the */
872*16548Sslatteng 				/*   entry into the list. */
873*16548Sslatteng 		register polyvector *p;	/* random vector pointers */
874*16548Sslatteng 		register polyvector *v;
875*16548Sslatteng 
876*16548Sslatteng 							/* convert this */
877*16548Sslatteng 		if (vectptr->dx < 0)			/* entry to active */
878*16548Sslatteng 		    vectptr->param = -((vectptr->dx >> 1) + (vectptr->dy >> 1));
879*16548Sslatteng 		else
880*16548Sslatteng 		    vectptr->param = (vectptr->dx >> 1) - (vectptr->dy >> 1);
881*16548Sslatteng 
882*16548Sslatteng 		p = vectptr;			/* remove from the */
883*16548Sslatteng 		vectptr = vectptr->next;	/* waiting list */
884*16548Sslatteng 		vectptr->prev = p->prev;
885*16548Sslatteng 		p->prev->next = vectptr;
886*16548Sslatteng 						/* find where it goes */
887*16548Sslatteng 						/* in the active list */
888*16548Sslatteng 						/* (sorted smallest first) */
889*16548Sslatteng 		for (v = activehead->next; v->currx < p->currx; v = v->next)
890*16548Sslatteng 		    ;
891*16548Sslatteng 		p->next = v;		/* insert into active list */
892*16548Sslatteng 		p->prev = v->prev;	/* before the one it stopped on */
893*16548Sslatteng 		v->prev = p;
894*16548Sslatteng 		p->prev->next = p;
895*16548Sslatteng 		active++;
896*16548Sslatteng 	    } else {
897*16548Sslatteng 		if (i > vectptr->param) {
898*16548Sslatteng 		    i = vectptr->param;
899*16548Sslatteng 		}
900*16548Sslatteng 		vectptr = vectptr->next;
901*16548Sslatteng 	    }
902*16548Sslatteng 	}
903*16548Sslatteng 	nexty = i;
904*16548Sslatteng 
905*16548Sslatteng 					/* print the polygon while there */
906*16548Sslatteng 					/* are no more vectors to add */
907*16548Sslatteng 	while (miny < nexty) {
908*16548Sslatteng 					/* remove any finished vectors */
909*16548Sslatteng 	    vectptr = activehead->next;
910*16548Sslatteng 	    do {
911*16548Sslatteng 		if (vectptr->endy <= miny) {
912*16548Sslatteng 		    vectptr->prev->next = vectptr->next;
913*16548Sslatteng 		    vectptr->next->prev = vectptr->prev;
914*16548Sslatteng 		    active--;
915*16548Sslatteng 		}
916*16548Sslatteng 	    } while ((vectptr = vectptr->next) != activehead);
917*16548Sslatteng 
918*16548Sslatteng 					/* output a polygon for this band */
919*16548Sslatteng 	    if (firsttime || !(miny % NLINES)) {
920*16548Sslatteng 		register int numwait;	/* number in the waiting list */
921*16548Sslatteng 		register int newmaxy;	/* max for this band (bottom or maxy)*/
922*16548Sslatteng 
923*16548Sslatteng 
924*16548Sslatteng 		startspan(miny);
925*16548Sslatteng 		if ((newmaxy = (miny / NLINES) * NLINES + (NLINES - 1)) > maxy)
926*16548Sslatteng 		    newmaxy = maxy;
927*16548Sslatteng 
928*16548Sslatteng 					/* count up those vectors that WILL */
929*16548Sslatteng 					/* become active in this band */
930*16548Sslatteng 		for (numwait = 0, vectptr = waitinghead->next;
931*16548Sslatteng 				vectptr != NULL; vectptr = vectptr->next) {
932*16548Sslatteng 		    if (vectptr->param <= newmaxy)
933*16548Sslatteng 			numwait++;
934*16548Sslatteng 		}
935*16548Sslatteng 
936*16548Sslatteng 		sprintf(op,"Dq %d %d %d %d",member,active+numwait,miny,newmaxy);
937*16548Sslatteng 		op += strlen(op);
938*16548Sslatteng 		for (i = active, vectptr = activehead->next; i--;
939*16548Sslatteng 						vectptr = vectptr->next) {
940*16548Sslatteng 		    sprintf(op, " %d %d %d %d %d",
941*16548Sslatteng 			    vectptr->param, vectptr->dx, -vectptr->dy,
942*16548Sslatteng 			    vectptr->currx, vectptr->endy);
943*16548Sslatteng 		    op += strlen(op);
944*16548Sslatteng 		}
945*16548Sslatteng 		for (vectptr = waitinghead->next; vectptr != NULL;
946*16548Sslatteng 						vectptr = vectptr->next) {
947*16548Sslatteng 		    if (vectptr->param <= newmaxy) {
948*16548Sslatteng 			sprintf(op, " %d %d %d %d %d",
949*16548Sslatteng 				vectptr->param, vectptr->dx, vectptr->dy,
950*16548Sslatteng 				vectptr->currx, vectptr->endy);
951*16548Sslatteng 			op += strlen(op);
952*16548Sslatteng 		    }
953*16548Sslatteng 		}
954*16548Sslatteng 		*(op++) = '\n';
955*16548Sslatteng 		firsttime = 0;
956*16548Sslatteng 	    }
957*16548Sslatteng 
958*16548Sslatteng 					/* update the vectors */
959*16548Sslatteng 	    vectptr = activehead->next;
960*16548Sslatteng 	    do {
961*16548Sslatteng 		if (vectptr->dx > 0) {
962*16548Sslatteng 		    while (vectptr->param >= 0) {
963*16548Sslatteng 			vectptr->param -= vectptr->dy;
964*16548Sslatteng 			vectptr->currx++;
965*16548Sslatteng 		    }
966*16548Sslatteng 		    vectptr->param += vectptr->dx;
967*16548Sslatteng 		} else if (vectptr->dx < 0) {
968*16548Sslatteng 		    while (vectptr->param >= 0) {
969*16548Sslatteng 			vectptr->param -= vectptr->dy;
970*16548Sslatteng 			vectptr->currx--;
971*16548Sslatteng 		    }
972*16548Sslatteng 		    vectptr->param -= vectptr->dx;
973*16548Sslatteng 		}
974*16548Sslatteng 					/* must sort the vectors if updates */
975*16548Sslatteng 					/* caused them to cross */
976*16548Sslatteng 					/* also move to next vector here */
977*16548Sslatteng 		if (vectptr->currx < vectptr->prev->currx) {
978*16548Sslatteng 		    register polyvector *v;		/* vector to move */
979*16548Sslatteng 		    register polyvector *p;	/* vector to put it after */
980*16548Sslatteng 
981*16548Sslatteng 		    v = vectptr;
982*16548Sslatteng 		    p = v->prev;
983*16548Sslatteng 		    while (v->currx < p->currx)	/* find the */
984*16548Sslatteng 			p = p->prev;		/* right vector */
985*16548Sslatteng 
986*16548Sslatteng 		    vectptr = vectptr->next;	/* remove from spot */
987*16548Sslatteng 		    vectptr->prev = v->prev;
988*16548Sslatteng 		    v->prev->next = vectptr;
989*16548Sslatteng 
990*16548Sslatteng 		    v->prev = p;		/* put in new spot */
991*16548Sslatteng 		    v->next = p->next;
992*16548Sslatteng 		    p->next = v;
993*16548Sslatteng 		    v->next->prev = v;
994*16548Sslatteng 		} else {
995*16548Sslatteng 		    vectptr = vectptr->next;
996*16548Sslatteng 		}
997*16548Sslatteng 	    } while (vectptr != activehead);
998*16548Sslatteng 
999*16548Sslatteng 	    ++miny;
1000*16548Sslatteng 	} /* while (miny < nexty) */
1001*16548Sslatteng     } /* while (miny <= maxy) */
1002*16548Sslatteng 
1003*16548Sslatteng leavepoly:
1004*16548Sslatteng     startspan(vpos);	/* make sure stuff after polygon is at correct vpos */
1005*16548Sslatteng     free(waitinghead);
1006*16548Sslatteng }  /* polygon function */
1007