130195Sdenise #ifndef lint
2*30592Sdenise static char sccsid[] = "@(#)nvsort.c 1.4 (CWI) 87/03/05";
330195Sdenise #endif
430195Sdenise /*
530195Sdenise * from (Berkeley):
630195Sdenise * vsort.c 1.11 84/05/29
730194Sdenise *
830194Sdenise * Sorts and shuffles ditroff output for versatec wide printer. It
930194Sdenise * puts pages side-by-side on the output, and fits as many as it can
1030194Sdenise * on one horizontal span. The versatec driver sees only pages of
1130194Sdenise * full width, not the individual pages. Output is sorted vertically
1230194Sdenise * and bands are created NLINES pixels high. Any object that has
1330194Sdenise * ANY part of it in a band is put on that band.
1430194Sdenise *
1530194Sdenise * Jaap Akkerhuis
1630194Sdenise * de-Berkletized by #ifdef BERK
1730194Sdenise */
1830194Sdenise
1930194Sdenise
2030194Sdenise #include <stdio.h>
2130194Sdenise #include <ctype.h>
2230194Sdenise #include <math.h>
2330194Sdenise
2430194Sdenise
2530194Sdenise /* #define DEBUGABLE /* compile-time flag for debugging */
2630194Sdenise #define FATAL 1
2730194Sdenise #define NVLIST 3000 /* size of list of vertical spans */
2830194Sdenise #define OBUFSIZ 250000 /* size of character buffer before sorting */
2930194Sdenise #define SLOP 1000 /* extra bit of buffer to allow for passing OBUFSIZ */
3030194Sdenise #define MAXVECT 200 /* maximum number of points (vectors) in a polygon */
3130194Sdenise
3230194Sdenise #ifndef FONTDIR
3330194Sdenise #define FONTDIR "/usr/lib/font"
3430194Sdenise #endif FONTDIR
3530194Sdenise
3630194Sdenise #define POINT 72 /* number of points per inch */
3730194Sdenise
3830194Sdenise #ifndef VER80
3930194Sdenise #define WIDTH 7040 /* number of pixels across the page */
4030194Sdenise #else
4130194Sdenise #define WIDTH 2112 /* number of pixels across the page */
4230194Sdenise /*
4330194Sdenise * Note that this does not work unless the input really is
4430194Sdenise * designed for the versatec, i.e., res = 200. But that's
4530194Sdenise * OK, because it is only used for side-by-side pages, which
4630194Sdenise * we don't do anyway.
4730194Sdenise * DD
4830194Sdenise */
4930194Sdenise #endif VER80
5030194Sdenise
5130194Sdenise #define BAND 2.2 /* length of each band in inches */
5230194Sdenise #define NLINES (int)(BAND * inch) /* number of pixels in each band */
5330194Sdenise #define HALF (inch/2)
5430194Sdenise
5530194Sdenise #define hgoto(n) if((hpos = leftmarg + n) > maxh) maxh = hpos
5630194Sdenise #define hmot(n) if((hpos += n) > maxh) maxh = hpos
5730194Sdenise #define vmot(n) vpos += (n)
5830194Sdenise #define vgoto(n) vpos = (n)
5930194Sdenise
6030194Sdenise
6130194Sdenise int dbg = 0; /* debug flag != 0 means do debug output */
6230194Sdenise
6330194Sdenise int size = 10; /* current size (points) */
6430194Sdenise int up = 0; /* number of pixels that the current size pushes up */
6530194Sdenise int down = 0; /* # of pixels that the current size will hang down */
6630194Sdenise int font = 1; /* current font */
6730194Sdenise char * fontdir = FONTDIR; /* place to find DESC.out file */
6830194Sdenise int inch = 200; /* resolution of the device, in inches */
6930194Sdenise int thick = 3; /* line thickness */
7030194Sdenise
7130194Sdenise #ifdef BERK
7230194Sdenise int stip = 1; /* current stipple */
7330194Sdenise int style = -1; /* line style bit-mask */
7430194Sdenise #endif BERK
7530194Sdenise
7630194Sdenise
7730194Sdenise int hpos = 0; /* horizontal position to be at next (left = 0) */
7830194Sdenise int vpos = 0; /* current vertical position (down positive) */
7930194Sdenise
8030194Sdenise int maxh = 0; /* farthest right we've gone on the current span */
8130194Sdenise int leftmarg= 0; /* current page offset */
8230194Sdenise int spanno = 0; /* current span number for driver in 'p#' commands */
8330194Sdenise int pageno = 0; /* number of pages spread across a physical page */
8430194Sdenise
8530194Sdenise
8630194Sdenise struct vlist {
8730194Sdenise unsigned short v; /* vertical position of this spread */
8830194Sdenise unsigned short h; /* horizontal position */
8930194Sdenise unsigned short t; /* line thickness */
9030194Sdenise #ifdef BERK
9130194Sdenise short st; /* style mask */
9230194Sdenise unsigned char l; /* stipple number */
9330194Sdenise #endif BERK
9430194Sdenise unsigned short u; /* upper extent of height */
9530194Sdenise unsigned short d; /* depth of height */
9630194Sdenise unsigned short s; /* point size */
9730194Sdenise unsigned char f; /* font number */
9830216Sdenise unsigned short x; /* set if this span starts with `x' command */
9930194Sdenise char *p; /* text pointer to this spread */
10030194Sdenise };
10130194Sdenise
10230194Sdenise struct vlist vlist[NVLIST + 1];
10330194Sdenise struct vlist *vlp; /* current spread being added to */
10430194Sdenise int nvlist = 1; /* number of spreads in list */
10530194Sdenise int obufsiz = OBUFSIZ;
10630194Sdenise char obuf[OBUFSIZ + SLOP];
10730194Sdenise char *op = obuf; /* pointer to current spot in buffer */
10830194Sdenise
10930194Sdenise
11030194Sdenise
main(argc,argv)11130194Sdenise main(argc, argv)
11230194Sdenise int argc;
11330194Sdenise char *argv[];
11430194Sdenise {
11530194Sdenise FILE *fp;
11630194Sdenise double atof();
11730194Sdenise
11830194Sdenise
11930194Sdenise vlp = &vlist[0]; /* initialize spread pointer */
12030194Sdenise vlp->p = op;
12130194Sdenise vlp->v = vlp->d = vlp->u = vlp->h = 0;
12230194Sdenise vlp->s = size;
12330194Sdenise vlp->f = font;
12430194Sdenise #ifdef BERK
12530194Sdenise vlp->l = stip;
12630194Sdenise vlp->st = style;
12730194Sdenise #endif BERK
12830194Sdenise vlp->t = thick;
12930216Sdenise /* we don't need added HxxVxxfxsxx for first span */
13030216Sdenise vlp->x++;
13130194Sdenise
13230194Sdenise while (argc > 1 && **++argv == '-') {
13330194Sdenise switch ((*argv)[1]) {
13430194Sdenise case 'f':
13530194Sdenise fontdir = &(*argv)[2];
13630194Sdenise break;
13730194Sdenise #ifdef DEBUGABLE
13830194Sdenise case 'd':
13930194Sdenise dbg = atoi(&(*argv)[2]);
14030194Sdenise if (!dbg) dbg = 1;
14130194Sdenise break;
14230194Sdenise case 's':
14330194Sdenise if((obufsiz = atoi(&(*argv)[2])) > OBUFSIZ)
14430194Sdenise obufsiz = OBUFSIZ;
14530194Sdenise break;
14630194Sdenise #endif DEBUGABLE
14730194Sdenise }
14830194Sdenise argc--;
14930194Sdenise }
15030194Sdenise
15130194Sdenise if (argc <= 1)
15230194Sdenise conv(stdin);
15330194Sdenise else
15430194Sdenise while (--argc > 0) {
15530194Sdenise if ((fp = fopen(*argv, "r")) == NULL)
15630194Sdenise error(FATAL, "can't open %s", *argv);
15730194Sdenise conv(fp);
15830194Sdenise fclose(fp);
15930194Sdenise }
16030194Sdenise done();
16130194Sdenise }
16230194Sdenise
16330194Sdenise /* read number from input: copy to output */
16430194Sdenise int
getnumber(fp)16530194Sdenise getnumber (fp)
16630194Sdenise register FILE *fp;
16730194Sdenise {
16830194Sdenise register int k;
16930194Sdenise register char c;
17030194Sdenise
17130194Sdenise while (isspace(c = getc(fp)))
17230194Sdenise ;
17330194Sdenise k = 0;
17430194Sdenise if (c == '-') {
17530194Sdenise #ifndef BERK
17630194Sdenise *op++ = c; /* should be output as well!!! */
17730194Sdenise #endif BERK
17830194Sdenise c = getc(fp);
17930194Sdenise do {
18030194Sdenise k = 10 * k - ((*op++ = c) - '0');
18130194Sdenise } while (isdigit(c = getc(fp)));
18230194Sdenise } else {
18330194Sdenise do {
18430194Sdenise k = 10 * k + (*op++ = c) - '0';
18530194Sdenise } while (isdigit(c = getc(fp)));
18630194Sdenise }
18730194Sdenise ungetc(c, fp);
18830194Sdenise return (k);
18930194Sdenise }
19030194Sdenise
19130194Sdenise /* read number from input: do _N_O_T copy to output */
19230194Sdenise int
ngetnumber(fp)19330194Sdenise ngetnumber (fp)
19430194Sdenise register FILE *fp;
19530194Sdenise {
19630194Sdenise register int k;
19730194Sdenise register char c;
19830194Sdenise
19930194Sdenise while (isspace(c = getc(fp)))
20030194Sdenise ;
20130194Sdenise k = 0;
20230194Sdenise if (c == '-') {
20330194Sdenise c = getc(fp);
20430194Sdenise do {
20530194Sdenise k = 10 * k - (c - '0');
20630194Sdenise } while (isdigit(c = getc(fp)));
20730194Sdenise } else {
20830194Sdenise do {
20930194Sdenise k = 10 * k + c - '0';
21030194Sdenise } while (isdigit(c = getc(fp)));
21130194Sdenise }
21230194Sdenise ungetc(c, fp);
21330194Sdenise return (k);
21430194Sdenise }
21530194Sdenise
21630194Sdenise
conv(fp)21730194Sdenise conv(fp)
21830194Sdenise register FILE *fp;
21930194Sdenise {
22030194Sdenise register int c;
22130194Sdenise int m, n, m1, n1;
22230194Sdenise
22330194Sdenise while ((c = getc(fp)) != EOF) {
22430194Sdenise #ifdef DEBUGABLE
22530194Sdenise if (dbg > 2) fprintf(stderr, "conv: got:<%c>, op-obuf=%d V=%d\n", c, op-obuf, vpos);
22630194Sdenise #endif DEBUGABLE
22730194Sdenise if (op > obuf + obufsiz) {
22830194Sdenise error(!FATAL, "buffer overflow %d.", op - (obuf + obufsiz));
22930194Sdenise oflush();
23030194Sdenise }
23130194Sdenise switch (c) {
23230194Sdenise case '\0': /* filter out noise */
23330194Sdenise break;
23430194Sdenise case '\n': /* let text input through */
23530194Sdenise case '\t':
23630194Sdenise case ' ':
23730194Sdenise *op++ = c;
23830194Sdenise break;
23930194Sdenise case '{': /* push down current environment */
24030194Sdenise *op++ = c;
24130194Sdenise t_push();
24230194Sdenise break;
24330194Sdenise case '}': /* pop up last environment */
24430194Sdenise *op++ = c;
24530194Sdenise t_pop();
24630194Sdenise break;
24730194Sdenise case '0': case '1': case '2': case '3': case '4':
24830194Sdenise case '5': case '6': case '7': case '8': case '9':
24930194Sdenise /* two motion digits plus a character */
25030194Sdenise setlimit(vpos - up, vpos + down);
25130194Sdenise /*
25230194Sdenise *op++ = c;
25330194Sdenise hmot((c-'0') * 10 + (*op++ = getc(fp)) - '0');
25430194Sdenise *op++ = getc(fp);
25530194Sdenise */
25630194Sdenise n = ((c - '0') * 10 + ( m = getc(fp)) - '0');
25730194Sdenise hmot(n);
25830194Sdenise sprintf(op, "%02d", n);
25930194Sdenise op += strlen(op);
26030194Sdenise *op++ = getc(fp);
26130194Sdenise break;
26230194Sdenise case 'c': /* single ascii character */
26330194Sdenise setlimit(vpos - up, vpos + down);
26430194Sdenise *op++ = c;
26530194Sdenise *op++ = getc(fp);
26630194Sdenise break;
26730194Sdenise case 'C': /* white-space terminated funny character */
26830194Sdenise setlimit(vpos - up, vpos + down);
26930194Sdenise *op++ = c;
27030194Sdenise do
27130194Sdenise *op++ = c = getc(fp);
27230194Sdenise while (c != EOF && !isspace(c));
27330194Sdenise break;
27430194Sdenise case 't': /* straight text */
27530194Sdenise setlimit(vpos - up, vpos + down);
27630194Sdenise *op++ = c;
27730194Sdenise fgets(op, SLOP, fp);
27830194Sdenise op += strlen(op);
27930194Sdenise break;
28030194Sdenise case 'D': /* draw function */
28130194Sdenise switch (c = getc(fp)) {
28230194Sdenise int skip;
28330194Sdenise #ifdef BERK
28430194Sdenise case 's': /* "style" */
28530194Sdenise sprintf(op, "Ds ");
28630194Sdenise op += 3;
28730194Sdenise style = getnumber(fp);
28830194Sdenise break;
28930194Sdenise
29030194Sdenise case 't': /* thickness */
29130194Sdenise sprintf(op, "Dt ");
29230194Sdenise op += 3;
29330194Sdenise thick = getnumber(fp);
29430194Sdenise break;
29530194Sdenise #endif BERK
29630194Sdenise
29730194Sdenise case 'l': /* draw a line */
29830194Sdenise n1 = ngetnumber(fp);
29930194Sdenise m1 = ngetnumber(fp);
30030194Sdenise n = n1;
30130194Sdenise m = m1;
30230194Sdenise if (m < 0) {
30330194Sdenise setlimit(vpos+m-thick/2, vpos+thick/2);
30430194Sdenise } else {
30530194Sdenise setlimit(vpos-(1+thick/2),vpos+1+m+thick/2);
30630194Sdenise }
30730194Sdenise sprintf(op, "Dl %d %d", n, m);
30830194Sdenise op += strlen(op);
30930194Sdenise hmot(n1);
31030194Sdenise vmot(m1);
31130194Sdenise #ifndef BERK
31230194Sdenise /*
31330194Sdenise * note that this function is actually
31430194Sdenise * Dl n m .
31530194Sdenise * so we have to skip over the ".".
31630194Sdenise *
31730194Sdenise * Rhetoric question: Why doensn't Berkeley
31830194Sdenise * maintain compatability?
31930194Sdenise */
32030194Sdenise do{
32130194Sdenise skip = getc(fp);
32230194Sdenise if( skip == EOF)
32330194Sdenise error(FATAL,
32430194Sdenise "Cannot find . in Dl\n");
32530194Sdenise }while( skip != '.');
32630194Sdenise #endif BERK
32730194Sdenise break;
32830194Sdenise
32930194Sdenise case 'e': /* ellipse */
33030194Sdenise n = ngetnumber(fp);
33130194Sdenise m = ngetnumber(fp);
33230194Sdenise setlimit(vpos-(m+thick)/2, vpos+(m+thick)/2);
33330194Sdenise sprintf(op, "De %d %d", n, m);
33430194Sdenise op += strlen(op);
33530194Sdenise hmot(n);
33630194Sdenise break;
33730194Sdenise
33830194Sdenise case 'c': /* circle */
33930194Sdenise n = ngetnumber(fp);
34030194Sdenise setlimit(vpos-(n+thick)/2, vpos+(n+thick)/2);
34130194Sdenise sprintf(op, "Dc %d", n);
34230194Sdenise op += strlen(op);
34330194Sdenise hmot(n);
34430194Sdenise break;
34530194Sdenise
34630194Sdenise case 'a': /* arc */
34730194Sdenise #ifdef BERK
34830194Sdenise n = getnumber(fp);
34930194Sdenise m = getnumber(fp);
35030194Sdenise n1 = getnumber(fp);
35130194Sdenise m1 = getnumber(fp);
35230194Sdenise #else
35330194Sdenise n = ngetnumber(fp);
35430194Sdenise m = ngetnumber(fp);
35530194Sdenise n1 = ngetnumber(fp);
35630194Sdenise m1 = ngetnumber(fp);
35730194Sdenise #endif BERK
35830194Sdenise arcbounds(n, m, n1, m1);
35930194Sdenise sprintf(op, "Da %d %d %d %d", n, m, n1, m1);
36030194Sdenise op += strlen(op);
36130194Sdenise hmot(n + n1);
36230194Sdenise vmot(m + m1);
36330194Sdenise break;
36430194Sdenise
36530194Sdenise #ifdef BERK
36630194Sdenise case 'P':
36730194Sdenise case 'p':
36830194Sdenise {
36930194Sdenise register int nvect;
37030194Sdenise int member;
37130194Sdenise int border;
37230194Sdenise int x[MAXVECT];
37330194Sdenise int y[MAXVECT];
37430194Sdenise
37530194Sdenise
37630194Sdenise border = (c == 'p'); /* type of polygon */
37730194Sdenise member = ngetnumber(fp);/* and member number */
37830194Sdenise
37930194Sdenise nvect = 1; /* starting point for */
38030194Sdenise x[1] = hpos; /* points on polygon */
38130194Sdenise y[1] = vpos;
38230194Sdenise m = n = vpos; /* = max/min vertical */
38330194Sdenise /* position for curve */
38430194Sdenise {
38530194Sdenise register int h;
38630194Sdenise register int v;
38730194Sdenise
38830194Sdenise
38930194Sdenise h = hpos; /* calculate max and minimum */
39030194Sdenise v = vpos; /* vertical position */
39130194Sdenise /* and get points */
39230194Sdenise do {
39330194Sdenise h += ngetnumber(fp);
39430194Sdenise v += ngetnumber(fp);
39530194Sdenise
39630194Sdenise if (v < n) n = v;
39730194Sdenise else if (v > m) m = v;
39830194Sdenise
39930194Sdenise if (nvect < (MAXVECT-1))/* keep the */
40030194Sdenise nvect++; /* points in */
40130194Sdenise x[nvect] = h; /* bounds */
40230194Sdenise y[nvect] = v; /* of arrays */
40330194Sdenise c = getc(fp);
40430194Sdenise } while (c != '\n' && c != EOF);
40530194Sdenise }
40630194Sdenise if (border) { /* output border as a */
40730194Sdenise register int *x1; /* bunch of lines */
40830194Sdenise register int *x2; /* instead of having */
40930194Sdenise register int *y1; /* the filter do it */
41030194Sdenise register int *y2;
41130194Sdenise register int extra = thick/2;
41230194Sdenise
41330194Sdenise x1 = &(x[0]); /* x1, y1, x2, y2 are */
41430194Sdenise x2 = &(x[1]); /* for indexing along */
41530194Sdenise y1 = &(y[0]); /* coordinate arrays */
41630194Sdenise y2 = &(y[1]);
41730194Sdenise for (border = 0; ++border < nvect; ) {
41830194Sdenise if (*++y1 > *++y2) {
41930194Sdenise setlimit(*y2-extra, vpos+extra);
42030194Sdenise } else {
42130194Sdenise setlimit(vpos-(1+extra),*y2+1+extra);
42230194Sdenise /* the extra 1's are to force */
42330194Sdenise /* setlimit to know this is a */
42430194Sdenise /* real entry (making sure it */
42530194Sdenise /* doesn't get vpos as limit */
42630194Sdenise }
42730194Sdenise sprintf(op, "Dl %d %d\n",
42830194Sdenise c = *++x2 - *++x1, *y2 - *y1);
42930194Sdenise op += strlen(op);
43030194Sdenise hmot(c); /* update vpos for */
43130194Sdenise vgoto(*y2); /* the setlimit call */
43230194Sdenise }
43330194Sdenise } else {
43430194Sdenise register int *x1; /* x1, x2, are for */
43530194Sdenise register int *x2; /* indexing points */
43630194Sdenise register int i; /* random int */
43730194Sdenise
43830194Sdenise x1 = &(x[0]);
43930194Sdenise x2 = &(x[1]);
44030194Sdenise for (i = 0; ++i < nvect; ) {
44130194Sdenise hmot(*++x2 - *++x1);
44230194Sdenise }
44330194Sdenise vgoto(y[nvect]);
44430194Sdenise sprintf(op, "H%dV%d", hpos, vpos);
44530194Sdenise op += strlen(op);
44630194Sdenise }
44730194Sdenise if (member) {
44830194Sdenise polygon(member, nvect, x, y, m, n);
44930194Sdenise }
45030194Sdenise }
45130194Sdenise break;
45230194Sdenise #endif BERK
45330194Sdenise
45430194Sdenise case '~': /* wiggly line */
45530194Sdenise #ifdef BERK
45630194Sdenise case 'g': /* gremlin curve */
45730194Sdenise #endif BERK
45830194Sdenise startspan(vpos); /* always put curve */
45930194Sdenise sprintf(op, "D%c ", c); /* on its own span */
46030194Sdenise op += 3;
46130194Sdenise
46230194Sdenise m = n = vpos; /* = max/min vertical */
46330194Sdenise do { /* position for curve */
46430194Sdenise /*
46530194Sdenise hpos += getnumber(fp);
46630194Sdenise *op++ = ' ';
46730194Sdenise vpos += getnumber(fp);
46830194Sdenise *op++ = ' ';
46930194Sdenise */
47030194Sdenise n1 = ngetnumber(fp);
47130194Sdenise m1 = ngetnumber(fp);
47230194Sdenise
47330194Sdenise hmot(n1);
47430194Sdenise vmot(m1);
47530194Sdenise sprintf(op, "%d %d ", n1, m1);
47630194Sdenise op += strlen(op);
47730194Sdenise
47830194Sdenise if (vpos < n) n = vpos;
47930194Sdenise else if (vpos > m) m = vpos;
48030194Sdenise c = getc(fp);
48130194Sdenise } while (c != '\n' && c != EOF);
48230194Sdenise
48330194Sdenise vlp->u = n < 0 ? 0 : n;
48430194Sdenise vlp->d = m;
48530194Sdenise *op++ = '\n';
48630194Sdenise startspan(vpos);
48730194Sdenise break;
48830194Sdenise
48930194Sdenise default:
49030194Sdenise error(FATAL,"unknown drawing command %c", c);
49130194Sdenise break;
49230194Sdenise }
49330194Sdenise break;
49430194Sdenise case 's':
49530194Sdenise *op++ = c;
49630194Sdenise size = getnumber(fp);
49730194Sdenise up = ((size + 1)*inch) / POINT; /* ROUGH estimate */
49830194Sdenise down = up / 3; /* of max up/down */
49930194Sdenise break;
50030194Sdenise case 'f':
50130194Sdenise *op++ = c;
50230194Sdenise font = getnumber(fp);
50330194Sdenise break;
50430194Sdenise #ifdef BERK
50530194Sdenise case 'i':
50630194Sdenise *op++ = c;
50730194Sdenise stip = getnumber(fp);
50830194Sdenise break;
50930194Sdenise #endif BERK
51030194Sdenise case 'H': /* absolute horizontal motion */
51130194Sdenise hgoto(ngetnumber(fp));
51230194Sdenise sprintf(op, "H%d", hpos);
51330194Sdenise op += strlen(op); /* reposition by page offset */
51430194Sdenise break;
51530194Sdenise case 'h': /* relative horizontal motion */
51630194Sdenise /*
51730194Sdenise *op++ = c;
51830194Sdenise hmot(getnumber(fp));
51930194Sdenise */
52030194Sdenise n = ngetnumber(fp);
52130194Sdenise hmot(n);
52230194Sdenise sprintf(op, "h%d", n);
52330194Sdenise op += strlen(op);
52430194Sdenise break;
52530194Sdenise case 'w': /* useless */
52630194Sdenise *op++ = c; /* But put it out anyway */
52730194Sdenise break;
52830194Sdenise case 'V': /* absolute vertical motion */
52930194Sdenise /*
53030194Sdenise *op++ = c;
53130194Sdenise vgoto(getnumber(fp));
53230194Sdenise */
53330194Sdenise vgoto(ngetnumber(fp));
53430194Sdenise sprintf(op, "V%d", vpos);
53530194Sdenise op += strlen(op);
53630194Sdenise break;
53730194Sdenise case 'v':
53830194Sdenise /*
53930194Sdenise *op++ = c;
54030194Sdenise vmot(getnumber(fp));
54130194Sdenise */
54230194Sdenise n = ngetnumber(fp);
54330194Sdenise vmot(n);
54430194Sdenise sprintf(op, "v%d", n);
54530194Sdenise op += strlen(op);
54630194Sdenise break;
54730194Sdenise case 'p': /* new page */
54830195Sdenise startspan(vpos);
54930194Sdenise t_page(ngetnumber(fp));
55030194Sdenise vpos = 0;
55130194Sdenise break;
55230194Sdenise case 'n': /* end of line */
55330194Sdenise hpos = leftmarg;
55430194Sdenise /*
55530194Sdenise *op++ = c;
55630194Sdenise do
55730194Sdenise *op++ = c = getc(fp);
55830194Sdenise while (c != '\n' && c != EOF);
55930194Sdenise */
56030194Sdenise *op++ = c;
56130194Sdenise n = ngetnumber(fp);
56230194Sdenise m = ngetnumber(fp);
56330194Sdenise sprintf(op, "%d %d", n, m);
56430194Sdenise op += strlen(op);
56530194Sdenise break;
56630194Sdenise case '#': /* comment */
56730194Sdenise do
56830194Sdenise c = getc(fp);
56930194Sdenise while (c != '\n' && c != EOF);
57030194Sdenise break;
57130194Sdenise case 'x': /* device control */
57230194Sdenise devcntrl(fp);
57330194Sdenise break;
57430194Sdenise default:
57530194Sdenise error(!FATAL, "unknown input character %o %c", c, c);
57630194Sdenise done();
57730194Sdenise }
57830194Sdenise }
57930194Sdenise }
58030194Sdenise
devcntrl(fp)58130194Sdenise devcntrl(fp) /* interpret device control functions */
58230194Sdenise FILE *fp; /* returns -1 apon recieving "stop" command */
58330194Sdenise {
58430194Sdenise char str[20], str1[50], buf[50];
58530194Sdenise char *p;
58630194Sdenise int c, n, t1, t2;
58730194Sdenise
58830194Sdenise fscanf(fp, "%s", str);
58930216Sdenise switch (str[0]) {
59030194Sdenise case 'r': /* resolution assumed when prepared */
59130194Sdenise fscanf(fp, "%d %d %d", &inch, &t1, &t2);
59230194Sdenise sprintf(str1, "x res %d %d %d", inch, t1, t2);
59330194Sdenise break;
59430194Sdenise default: /* reconstruct the string */
59530194Sdenise fgets(buf, sizeof buf, fp);
59630194Sdenise sprintf(str1, "x %s%s", str, buf);
59730194Sdenise }
59830194Sdenise
59930194Sdenise startspan(vpos);
60030216Sdenise vlp->x++; /* yes, this is an x command */
60130194Sdenise p = str1;
60230194Sdenise while (*p)
60330194Sdenise *op++ = *p++;
60430194Sdenise }
60530194Sdenise
60630194Sdenise /*----------------------------------------------------------------------------*
60730194Sdenise | Routine: setlimit
60830194Sdenise |
60930194Sdenise | Results: using "newup" and "newdown" decide when to start a new span.
61030194Sdenise | maximum rise and/or fall of a vertical extent are saved.
61130194Sdenise |
61230194Sdenise | Side Efct: may start new span.
61330194Sdenise *----------------------------------------------------------------------------*/
61430194Sdenise
61530194Sdenise #define diffspan(x,y) ((x)/NLINES != (y)/NLINES)
61630194Sdenise
setlimit(newup,newdown)61730194Sdenise setlimit(newup, newdown)
61830194Sdenise register int newup;
61930194Sdenise register int newdown;
62030194Sdenise {
62130194Sdenise register int currup = vlp->u;
62230194Sdenise register int currdown = vlp->d;
62330194Sdenise
62430194Sdenise if (newup < 0) newup = 0; /* don't go back beyond start of page */
62530194Sdenise if (newdown < 0) newdown = 0;
62630194Sdenise
62730194Sdenise if (diffspan(currup, currdown)) { /* now spans > one band */
62830194Sdenise if (diffspan(newup, currup) || diffspan(newdown, currdown)) {
62930194Sdenise startspan (vpos);
63030194Sdenise vlp->u = newup;
63130194Sdenise vlp->d = newdown;
63230194Sdenise } else {
63330194Sdenise if (newup < currup) vlp->u = newup;
63430194Sdenise if (newdown > currdown) vlp->d = newdown;
63530194Sdenise }
63630194Sdenise } else {
63730194Sdenise if (newup < currup) { /* goes farther up than before */
63830194Sdenise if (currup == vlp->v) { /* is new span, just set "up" */
63930194Sdenise vlp->u = newup;
64030194Sdenise } else {
64130194Sdenise if (diffspan(newup, currup)) { /* goes up farther */
64230194Sdenise startspan(vpos); /* than previously */
64330194Sdenise vlp->u = newup; /* AND to a higher */
64430194Sdenise vlp->d = newdown; /* band. */
64530194Sdenise return;
64630194Sdenise } else {
64730194Sdenise vlp->u = newup;
64830194Sdenise }
64930194Sdenise }
65030194Sdenise }
65130194Sdenise if (newdown > currdown) {
65230194Sdenise if (currdown == vlp->v) {
65330194Sdenise vlp->d = newdown;
65430194Sdenise return;
65530194Sdenise } else {
65630194Sdenise if (diffspan(newdown, currdown)) {
65730194Sdenise startspan(vpos);
65830194Sdenise vlp->u = newup;
65930194Sdenise vlp->d = newdown;
66030194Sdenise return;
66130194Sdenise } else {
66230194Sdenise vlp->d = newdown;
66330194Sdenise }
66430194Sdenise }
66530194Sdenise }
66630194Sdenise }
66730194Sdenise }
66830194Sdenise
66930194Sdenise
67030194Sdenise /*----------------------------------------------------------------------------*
67130194Sdenise | Routine: arcbounds (h, v, h1, v1)
67230194Sdenise |
67330194Sdenise | Results: using the horizontal positions of the starting and ending
67430194Sdenise | points relative to the center and vertically relative to
67530194Sdenise | each other, arcbounds calculates the upper and lower extent
67630194Sdenise | of the arc which is one of: starting point, ending point
67730194Sdenise | or center + rad for bottom, and center - rad for top.
67830194Sdenise |
67930194Sdenise | Side Efct: calls setlimit(up, down) to save the extent information.
68030194Sdenise *----------------------------------------------------------------------------*/
68130194Sdenise
arcbounds(h,v,h1,v1)68230194Sdenise arcbounds(h, v, h1, v1)
68330194Sdenise int h, v, h1, v1;
68430194Sdenise {
68530194Sdenise register unsigned rad = (int)(sqrt((double)(h*h + v*v)) + 0.5);
68630194Sdenise register int i = ((h >= 0) << 2) | ((h1 < 0) << 1) | ((v + v1) < 0);
68730194Sdenise
68830194Sdenise /* i is a set of flags for the points being on the */
68930194Sdenise /* left of the center point, and which is higher */
69030194Sdenise
69130194Sdenise v1 += vpos + v; /* v1 is vertical position of ending point */
69230194Sdenise /* test relative positions for maximums */
69330194Sdenise setlimit( /* and set the up/down of the arc */
69430194Sdenise ((((i&3)==1) ? v1 : (((i&5)==4) ? vpos : vpos+v-rad)) - thick/2),
69530194Sdenise ((((i&3)==2) ? v1 : (((i&5)==1) ? vpos : vpos+v+rad)) + thick/2));
69630194Sdenise }
69730194Sdenise
69830194Sdenise
oflush()69930194Sdenise oflush() /* sort, then dump out contents of obuf */
70030194Sdenise {
70130194Sdenise register struct vlist *vp;
70230194Sdenise register int notdone;
70330194Sdenise register int topv;
70430194Sdenise register int botv;
70530194Sdenise register int i;
70630194Sdenise register char *p;
70730194Sdenise
70830194Sdenise #ifdef DEBUGABLE
70930194Sdenise if (dbg) fprintf(stderr, "GAG me with an into oflush, V=%d\n", vpos);
71030194Sdenise #endif DEBUGABLE
71130194Sdenise if (op == obuf)
71230194Sdenise return;
71330194Sdenise *op = 0;
71430194Sdenise
71530194Sdenise topv = 0;
71630194Sdenise botv = NLINES - 1;
71730194Sdenise do {
71830194Sdenise notdone = 0;
71930194Sdenise vp = vlist;
72030194Sdenise for (i = 0; i < nvlist; i++, vp++) {
72130194Sdenise #ifdef DEBUGABLE
72230194Sdenise if(dbg>1)fprintf(stderr,"oflush: u=%d, d=%d,%.60s\n",vp->u,vp->d,vp->p);
72330194Sdenise #endif DEBUGABLE
72430194Sdenise if (vp->u <= botv && vp->d >= topv) {
725*30592Sdenise if(vp->x) /* doesn't need font or size */
726*30592Sdenise printf("H%dV%d\n%s", vp->h,vp->v,vp->p);
72730216Sdenise else
72830216Sdenise printf("H%dV%ds%df%d\n%s",
72930216Sdenise vp->h,vp->v,vp->s,vp->f,vp->p);
73030194Sdenise }
73130194Sdenise notdone |= vp->d > botv; /* not done if there's still */
73230194Sdenise } /* something to put lower */
73330194Sdenise if (notdone) putchar('P'); /* mark the end of the spread */
73430194Sdenise topv += NLINES; /* unless it's the last one */
73530194Sdenise botv += NLINES;
73630194Sdenise } while (notdone);
73730194Sdenise
73830194Sdenise fflush(stdout);
73930194Sdenise vlp = vlist;
74030194Sdenise vlp->p = op = obuf;
74130194Sdenise vlp->h = hpos;
74230194Sdenise vlp->v = vpos;
74330194Sdenise vlp->u = vpos;
74430194Sdenise vlp->d = vpos;
74530194Sdenise vlp->s = size;
74630194Sdenise vlp->f = font;
74730194Sdenise #ifdef BERK
74830194Sdenise vlp->l = stip;
74930194Sdenise vlp->st = style;
75030194Sdenise #endif BERK
75130194Sdenise vlp->t = thick;
75230216Sdenise vlp->x = 0;
75330194Sdenise *op = 0;
75430194Sdenise nvlist = 1;
75530194Sdenise }
75630194Sdenise
75730194Sdenise
done()75830194Sdenise done()
75930194Sdenise {
76030194Sdenise oflush();
76130194Sdenise exit(0);
76230194Sdenise }
76330194Sdenise
error(f,s,a1,a2,a3,a4,a5,a6,a7)76430194Sdenise error(f, s, a1, a2, a3, a4, a5, a6, a7) {
76530194Sdenise fprintf(stderr, "vsort: ");
76630194Sdenise fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7);
76730194Sdenise fprintf(stderr, "\n");
76830194Sdenise if (f)
76930194Sdenise done();
77030194Sdenise }
77130194Sdenise
77230194Sdenise #define MAXSTATE 5
77330194Sdenise
77430194Sdenise struct state {
77530194Sdenise int ssize;
77630194Sdenise int sfont;
77730194Sdenise int shpos;
77830194Sdenise int svpos;
77930194Sdenise };
78030194Sdenise struct state state[MAXSTATE];
78130194Sdenise struct state *statep = state;
78230194Sdenise
t_push()78330194Sdenise t_push() /* begin a new block */
78430194Sdenise {
78530194Sdenise statep->ssize = size;
78630194Sdenise statep->sfont = font;
78730194Sdenise statep->shpos = hpos;
78830194Sdenise statep->svpos = vpos;
78930194Sdenise hpos = vpos = 0;
79030194Sdenise if (statep++ >= state+MAXSTATE)
79130194Sdenise error(FATAL, "{ nested too deep");
79230194Sdenise hpos = vpos = 0;
79330194Sdenise }
79430194Sdenise
t_pop()79530194Sdenise t_pop() /* pop to previous state */
79630194Sdenise {
79730194Sdenise if (--statep < state)
79830194Sdenise error(FATAL, "extra }");
79930194Sdenise size = statep->ssize;
80030194Sdenise font = statep->sfont;
80130194Sdenise hpos = statep->shpos;
80230194Sdenise vpos = statep->svpos;
80330194Sdenise }
80430194Sdenise
80530194Sdenise
80630194Sdenise /*----------------------------------------------------------------------------*
80730194Sdenise | Routine: t_page
80830194Sdenise |
80930194Sdenise | Results: new Margins are calculated for putting pages side-by-side.
81030194Sdenise | If no more pages can fit across the paper (WIDTH wide)
81130194Sdenise | a real page end is done and the currrent page is output.
81230194Sdenise |
81330194Sdenise | Side Efct: oflush is called on a REAL page boundary.
81430194Sdenise *----------------------------------------------------------------------------*/
81530194Sdenise
t_page(n)81630194Sdenise t_page(n)
81730194Sdenise int n;
81830194Sdenise {
81930194Sdenise #ifndef VER80
82030194Sdenise static int first = 1; /* flag to catch the 1st time through */
82130194Sdenise
82230195Sdenise /*
82330195Sdenise * if we're near the edge, or this is the first page
82430195Sdenise * we'll go over on this page.
82530195Sdenise */
82630195Sdenise if (leftmarg + 2*(pageno ? leftmarg/pageno : 0) > WIDTH
82730195Sdenise || maxh > WIDTH - inch || first) {
82830194Sdenise oflush();
82930194Sdenise printf("p%d\n", spanno++); /* make it a REAL page-break */
83030194Sdenise first = pageno = leftmarg = maxh = 0;
83130195Sdenise
83230195Sdenise } else {
83330195Sdenise /* x = last page's width (in half-inches) */
83430194Sdenise register int x = (maxh - leftmarg + (HALF - 1)) / HALF;
83530194Sdenise
83630194Sdenise if (x > 11 && x <= 17)
83730194Sdenise leftmarg += (8 * inch) + HALF; /* if close to 8.5" */
83830194Sdenise else /* then make it so */
83930194Sdenise leftmarg = ((maxh + HALF) / HALF) * HALF; /* else set it to the */
84030194Sdenise pageno++; /* nearest half-inch */
84130194Sdenise }
84230194Sdenise #else
84330194Sdenise oflush();
84430194Sdenise printf("p%d\n", n);
84530194Sdenise pageno = leftmarg = maxh = 0;
84630194Sdenise #endif VER80
84730194Sdenise }
84830194Sdenise
84930194Sdenise
startspan(n)85030194Sdenise startspan(n)
85130194Sdenise register int n;
85230194Sdenise {
85330194Sdenise *op++ = 0;
85430194Sdenise if (nvlist >= NVLIST) {
85530194Sdenise #ifdef DEBUGABLE
85630194Sdenise error(!FATAL, "(startspan) ran out of vlist");
85730194Sdenise #endif DEBUGABLE
85830194Sdenise oflush();
85930194Sdenise }
86030194Sdenise vlp++;
86130194Sdenise vlp->p = op;
86230194Sdenise vlp->v = n;
86330194Sdenise vlp->d = n;
86430194Sdenise vlp->u = n;
86530194Sdenise vlp->h = hpos;
86630194Sdenise vlp->s = size;
86730194Sdenise vlp->f = font;
86830194Sdenise #ifdef BERK
86930194Sdenise vlp->l = stip;
87030194Sdenise vlp->st = style;
87130194Sdenise #endif BERK
87230194Sdenise vlp->t = thick;
87330216Sdenise vlp->x = 0;
87430194Sdenise nvlist++;
87530194Sdenise }
87630194Sdenise
87730194Sdenise #ifdef BERK
87830194Sdenise
87930194Sdenise #define MAXX 0x7fff
88030194Sdenise #define MINX 0x8000
88130194Sdenise
88230194Sdenise typedef struct poly {
88330194Sdenise struct poly *next; /* doublely-linked lists of vectors */
88430194Sdenise struct poly *prev;
88530194Sdenise int param; /* bressenham line algorithm parameter */
88630194Sdenise short dx; /* delta-x for calculating line */
88730194Sdenise short dy; /* delta-y for calculating line */
88830194Sdenise short currx; /* current x in this vector */
88930194Sdenise short endy; /* where vector ends */
89030194Sdenise } polyvector;
89130194Sdenise
89230194Sdenise
89330194Sdenise /*----------------------------------------------------------------------------*
89430194Sdenise | Routine: polygon ( member, num_vectors, x_coor, y_coor, maxy, miny )
89530194Sdenise |
89630194Sdenise | Results: outputs commands to draw a polygon starting at (x[1], y[1])
89730194Sdenise | going through each of (x_coordinates, y_coordinates), and
89830194Sdenise | filled with "member" stipple pattern.
89930194Sdenise |
90030194Sdenise | A scan-line algorithm is simulated and pieces of the
90130194Sdenise | polygon are put out that fit on bands of the versatec
90230194Sdenise | output filter.
90330194Sdenise |
90430194Sdenise | The format of the polygons put out are:
90530194Sdenise | 'Dp member num miny maxy [p dx dy curx endy]'
90630194Sdenise | where "num" is the number of [..] entries in that
90730194Sdenise | section of the polygon.
90830194Sdenise *----------------------------------------------------------------------------*/
90930194Sdenise
polygon(member,nvect,x,y,maxy,miny)91030194Sdenise polygon(member, nvect, x, y, maxy, miny)
91130194Sdenise int member;
91230194Sdenise int nvect;
91330194Sdenise int x[];
91430194Sdenise int y[];
91530194Sdenise int maxy;
91630194Sdenise int miny;
91730194Sdenise {
91830194Sdenise int nexty; /* at what x value the next vector starts */
91930194Sdenise register int active; /* number of vectors in active list */
92030194Sdenise int firsttime; /* force out a polgon the first time through */
92130194Sdenise polyvector *activehead; /* doing fill, is active edge list */
92230194Sdenise polyvector *waitinghead; /* edges waiting to be active */
92330194Sdenise register polyvector *vectptr; /* random vector */
92430194Sdenise register int i; /* random register */
92530194Sdenise
92630194Sdenise
92730194Sdenise /* allocate space for raster-fill algorithm*/
92830194Sdenise vectptr = (polyvector *) malloc(sizeof(polyvector) * (nvect + 4));
92930194Sdenise if (vectptr == (polyvector *) NULL) {
93030194Sdenise error(!FATAL, "unable to allocate space for polygon");
93130194Sdenise return;
93230194Sdenise }
93330194Sdenise
93430194Sdenise waitinghead = vectptr;
93530194Sdenise vectptr->param = miny - 1;
93630194Sdenise (vectptr++)->prev = NULL; /* put dummy entry at start */
93730194Sdenise waitinghead->next = vectptr;
93830194Sdenise vectptr->prev = waitinghead;
93930194Sdenise i = 1; /* starting point of coords */
94030194Sdenise if (y[1] != y[nvect] || x[1] != x[nvect]) {
94130194Sdenise y[0] = y[nvect]; /* close polygon if it's not */
94230194Sdenise x[0] = x[nvect];
94330194Sdenise i = 0;
94430194Sdenise }
94530194Sdenise active = 0;
94630194Sdenise while (i < nvect) { /* set up the vectors */
94730194Sdenise register int j; /* indexes to work off of */
94830194Sdenise register int k;
94930194Sdenise
95030194Sdenise j = i; /* j "points" to the higher (lesser) point */
95130194Sdenise k = ++i;
95230194Sdenise if (y[j] == y[k]) /* ignore horizontal lines */
95330194Sdenise continue;
95430194Sdenise
95530194Sdenise if (y[j] > y[k]) {
95630194Sdenise j++;
95730194Sdenise k--;
95830194Sdenise }
95930194Sdenise active++;
96030194Sdenise vectptr->next = vectptr + 1;
96130194Sdenise vectptr->param = y[j]; /* starting point of vector */
96230194Sdenise vectptr->dx = x[k] - x[j]; /* line-calculating parameters */
96330194Sdenise vectptr->dy = y[k] - y[j];
96430194Sdenise vectptr->currx = x[j]; /* starting point */
96530194Sdenise (vectptr++)->endy = y[k]; /* ending point */
96630194Sdenise vectptr->prev = vectptr - 1;
96730194Sdenise }
96830194Sdenise /* if no useable vectors, quit */
96930194Sdenise if (active < 2)
97030194Sdenise goto leavepoly;
97130194Sdenise
97230194Sdenise vectptr->param = maxy + 1; /* dummy entry at end, too */
97330194Sdenise vectptr->next = NULL;
97430194Sdenise
97530194Sdenise activehead = ++vectptr; /* two dummy entries for active list */
97630194Sdenise vectptr->currx = MINX; /* head */
97730194Sdenise vectptr->endy = maxy + 1;
97830194Sdenise vectptr->param = vectptr->dx = vectptr->dy = 0;
97930194Sdenise activehead->next = ++vectptr;
98030194Sdenise activehead->prev = vectptr;
98130194Sdenise vectptr->prev = activehead; /* tail */
98230194Sdenise vectptr->next = activehead;
98330194Sdenise vectptr->currx = MAXX;
98430194Sdenise vectptr->endy = maxy + 1;
98530194Sdenise vectptr->param = vectptr->dx = vectptr->dy = 0;
98630194Sdenise
98730194Sdenise /* if there's no need to break the */
98830194Sdenise /* polygon into pieces, don't bother */
98930194Sdenise if (diffspan(miny, maxy)) {
99030194Sdenise active = 0; /* will keep track of # of vectors */
99130194Sdenise firsttime = 1;
99230194Sdenise } else { /* in the active list */
99330194Sdenise startspan(miny);
99430194Sdenise sprintf(op, "Dq %d %d %d %d", member, active, miny, maxy);
99530194Sdenise op += strlen(op);
99630194Sdenise for (vectptr = waitinghead->next; active--; vectptr++) {
99730194Sdenise sprintf(op, " %d %d %d %d %d",
99830194Sdenise vectptr->param, vectptr->dx, vectptr->dy,
99930194Sdenise vectptr->currx, vectptr->endy);
100030194Sdenise op += strlen(op);
100130194Sdenise }
100230194Sdenise *(op++) = '\n';
100330194Sdenise goto leavepoly;
100430194Sdenise }
100530194Sdenise /* main loop -- gets vectors off the waiting list, */
100630194Sdenise /* then displays spans while updating the vectors in */
100730194Sdenise /* the active list */
100830194Sdenise while (miny <= maxy) {
100930194Sdenise i = maxy + 1; /* this is the NEXT time to get a new vector */
101030194Sdenise for (vectptr = waitinghead->next; vectptr != NULL; ) {
101130194Sdenise if (miny == vectptr->param) {
101230194Sdenise /* the entry in waiting list (vectptr) is */
101330194Sdenise /* ready to go into active list. Need to */
101430194Sdenise /* convert some vector stuff and sort the */
101530194Sdenise /* entry into the list. */
101630194Sdenise register polyvector *p; /* random vector pointers */
101730194Sdenise register polyvector *v;
101830194Sdenise
101930194Sdenise /* convert this */
102030194Sdenise if (vectptr->dx < 0) /* entry to active */
102130194Sdenise vectptr->param = -((vectptr->dx >> 1) + (vectptr->dy >> 1));
102230194Sdenise else
102330194Sdenise vectptr->param = (vectptr->dx >> 1) - (vectptr->dy >> 1);
102430194Sdenise
102530194Sdenise p = vectptr; /* remove from the */
102630194Sdenise vectptr = vectptr->next; /* waiting list */
102730194Sdenise vectptr->prev = p->prev;
102830194Sdenise p->prev->next = vectptr;
102930194Sdenise /* find where it goes */
103030194Sdenise /* in the active list */
103130194Sdenise /* (sorted smallest first) */
103230194Sdenise for (v = activehead->next; v->currx < p->currx; v = v->next)
103330194Sdenise ;
103430194Sdenise p->next = v; /* insert into active list */
103530194Sdenise p->prev = v->prev; /* before the one it stopped on */
103630194Sdenise v->prev = p;
103730194Sdenise p->prev->next = p;
103830194Sdenise active++;
103930194Sdenise } else {
104030194Sdenise if (i > vectptr->param) {
104130194Sdenise i = vectptr->param;
104230194Sdenise }
104330194Sdenise vectptr = vectptr->next;
104430194Sdenise }
104530194Sdenise }
104630194Sdenise nexty = i;
104730194Sdenise
104830194Sdenise /* print the polygon while there */
104930194Sdenise /* are no more vectors to add */
105030194Sdenise while (miny < nexty) {
105130194Sdenise /* remove any finished vectors */
105230194Sdenise vectptr = activehead->next;
105330194Sdenise do {
105430194Sdenise if (vectptr->endy <= miny) {
105530194Sdenise vectptr->prev->next = vectptr->next;
105630194Sdenise vectptr->next->prev = vectptr->prev;
105730194Sdenise active--;
105830194Sdenise }
105930194Sdenise } while ((vectptr = vectptr->next) != activehead);
106030194Sdenise
106130194Sdenise /* output a polygon for this band */
106230194Sdenise if (firsttime || !(miny % NLINES)) {
106330194Sdenise register int numwait; /* number in the waiting list */
106430194Sdenise register int newmaxy; /* max for this band (bottom or maxy)*/
106530194Sdenise
106630194Sdenise
106730194Sdenise startspan(miny);
106830194Sdenise if ((newmaxy = (miny / NLINES) * NLINES + (NLINES - 1)) > maxy)
106930194Sdenise newmaxy = maxy;
107030194Sdenise
107130194Sdenise /* count up those vectors that WILL */
107230194Sdenise /* become active in this band */
107330194Sdenise for (numwait = 0, vectptr = waitinghead->next;
107430194Sdenise vectptr != NULL; vectptr = vectptr->next) {
107530194Sdenise if (vectptr->param <= newmaxy)
107630194Sdenise numwait++;
107730194Sdenise }
107830194Sdenise
107930194Sdenise sprintf(op,"Dq %d %d %d %d",member,active+numwait,miny,newmaxy);
108030194Sdenise op += strlen(op);
108130194Sdenise for (i = active, vectptr = activehead->next; i--;
108230194Sdenise vectptr = vectptr->next) {
108330194Sdenise sprintf(op, " %d %d %d %d %d",
108430194Sdenise vectptr->param, vectptr->dx, -vectptr->dy,
108530194Sdenise vectptr->currx, vectptr->endy);
108630194Sdenise op += strlen(op);
108730194Sdenise }
108830194Sdenise for (vectptr = waitinghead->next; vectptr != NULL;
108930194Sdenise vectptr = vectptr->next) {
109030194Sdenise if (vectptr->param <= newmaxy) {
109130194Sdenise sprintf(op, " %d %d %d %d %d",
109230194Sdenise vectptr->param, vectptr->dx, vectptr->dy,
109330194Sdenise vectptr->currx, vectptr->endy);
109430194Sdenise op += strlen(op);
109530194Sdenise }
109630194Sdenise }
109730194Sdenise *(op++) = '\n';
109830194Sdenise firsttime = 0;
109930194Sdenise }
110030194Sdenise
110130194Sdenise /* update the vectors */
110230194Sdenise vectptr = activehead->next;
110330194Sdenise do {
110430194Sdenise if (vectptr->dx > 0) {
110530194Sdenise while (vectptr->param >= 0) {
110630194Sdenise vectptr->param -= vectptr->dy;
110730194Sdenise vectptr->currx++;
110830194Sdenise }
110930194Sdenise vectptr->param += vectptr->dx;
111030194Sdenise } else if (vectptr->dx < 0) {
111130194Sdenise while (vectptr->param >= 0) {
111230194Sdenise vectptr->param -= vectptr->dy;
111330194Sdenise vectptr->currx--;
111430194Sdenise }
111530194Sdenise vectptr->param -= vectptr->dx;
111630194Sdenise }
111730194Sdenise /* must sort the vectors if updates */
111830194Sdenise /* caused them to cross */
111930194Sdenise /* also move to next vector here */
112030194Sdenise if (vectptr->currx < vectptr->prev->currx) {
112130194Sdenise register polyvector *v; /* vector to move */
112230194Sdenise register polyvector *p; /* vector to put it after */
112330194Sdenise
112430194Sdenise v = vectptr;
112530194Sdenise p = v->prev;
112630194Sdenise while (v->currx < p->currx) /* find the */
112730194Sdenise p = p->prev; /* right vector */
112830194Sdenise
112930194Sdenise vectptr = vectptr->next; /* remove from spot */
113030194Sdenise vectptr->prev = v->prev;
113130194Sdenise v->prev->next = vectptr;
113230194Sdenise
113330194Sdenise v->prev = p; /* put in new spot */
113430194Sdenise v->next = p->next;
113530194Sdenise p->next = v;
113630194Sdenise v->next->prev = v;
113730194Sdenise } else {
113830194Sdenise vectptr = vectptr->next;
113930194Sdenise }
114030194Sdenise } while (vectptr != activehead);
114130194Sdenise
114230194Sdenise ++miny;
114330194Sdenise } /* while (miny < nexty) */
114430194Sdenise } /* while (miny <= maxy) */
114530194Sdenise
114630194Sdenise leavepoly:
114730194Sdenise startspan(vpos); /* make sure stuff after polygon is at correct vpos */
114830194Sdenise free(waitinghead);
114930194Sdenise } /* polygon function */
115030194Sdenise #endif BERK
1151