1 /* dver.c 1.17 85/08/05
2 *
3 * VAX Versatec driver for the new troff
4 *
5 * Authors: BWK(BELL)
6 * VCAT(berkley)
7 * Richard L. Hyde, Perdue University
8 * and David Slattengren, U.C. Berkeley
9 */
10
11
12 /*******************************************************************************
13
14 output language from troff:
15 all numbers are character strings
16
17 #..\n comment
18 sn size in points
19 fn font as number from 1 to n
20 in stipple as number from 1 to n
21 cx ascii character x
22 Cxyz funny char \(xyz. terminated by white space
23 Hn go to absolute horizontal position n
24 Vn go to absolute vertical position n (down is positive)
25 hn go n units horizontally (relative)
26 vn ditto vertically
27 nnc move right nn, then print c (exactly 2 digits!)
28 (this wart is an optimization that shrinks output file size
29 about 35% and run-time about 15% while preserving ascii-ness)
30 pn new page begins (number n) -- set v to 0
31 P spread ends -- output it.
32 nb a end of line (information only -- no action needed)
33 b = space before line, a = after
34 w paddable word space -- no action needed
35
36 Dt ..\n draw operation 't':
37 Dt d set line thickness to d pixels
38 Ds d set line style mask to d
39 Dl x y line from here by x,y
40 Dc d circle of diameter d with left side here
41 De x y ellipse of axes x,y with left side here
42 Da x y r arc counter-clockwise by x,y of radius r
43 D~ x y x y ... B-spline curve by x,y then x,y ...
44 Dg x y x y ... gremlin spline curve by x,y then x,y ...
45 Dq d n miny maxy [p dx dy curx endy] polygon filled with d, has n
46 vectors, with extents from miny to maxy (no border)
47
48 x ..\n device control functions:
49 x i init
50 x T s name of device is s
51 x r n h v resolution is n/inch h = min horizontal motion, v = min vert
52 x p pause (can restart)
53 x s stop -- done for ever
54 x t generate trailer
55 x f n s font position n contains font s
56 x H n set character height to n
57 x S n set slant to N
58
59 Subcommands like "i" are often spelled out like "init".
60
61 *******************************************************************************/
62
63
64 #include <stdio.h>
65 #include <ctype.h>
66 #include <sys/vcmd.h>
67 #include "dev.h"
68
69
70 /* #define DEBUGABLE /* No, not debugable... */
71 #define DRIVER /* Yes, we're driving directly */
72 #define NFONTS 65 /* total number of fonts useable */
73 #define MAXSTATE 6 /* number of environments rememberable */
74 #define OPENREAD 0 /* mode for openning files */
75 #define RESTART 1 /* upon exit, return either RESTART */
76 #define ABORT 2 /* or ABORT */
77 #define FATAL 1 /* type of error */
78 #define BMASK 0377 /* byte grabber */
79 #ifndef FONTDIR
80 #define FONTDIR "/usr/lib/font" /* default place to find font descriptions */
81 #endif
82 #ifndef BITDIR
83 #define BITDIR "/usr/lib/vfont" /* default place to look for font rasters */
84 #endif
85 #define MAXWRIT 4096 /* max characters allowed to write at once */
86
87 #define hmot(n) hpos += n
88 #define hgoto(n) hpos = n
89 #define vmot(n) vgoto(vpos + (n))
90
91
92 char SccsId[]= "dver.c 1.17 85/08/05";
93
94 int output = 0; /* do we do output at all? */
95 int nolist = 0; /* output page list if > 0 */
96 int olist[20]; /* pairs of page numbers */
97 struct dev dev;
98 struct font *fontbase[NFONTS+1];
99 short * pstab; /* point size table pointer */
100 int nsizes; /* number of sizes device is capable of printing */
101 int nfonts = 1; /* number of fonts device is capable of printing */
102 int nstips = 1; /* number of stipple fonts device can print */
103 int nchtab;
104 char * chname;
105 short * chtab;
106 char * fitab[NFONTS+1]; /* font inclusion table - maps ascii to ch # */
107 char * widtab[NFONTS+1]; /* width table for each font */
108 char * codetab[NFONTS+1]; /* device codes */
109 char * fontdir = FONTDIR; /* place to find devxxx directories */
110 char * bitdir = BITDIR; /* place to find raster fonts and fontmap */
111 char * fontname[NFONTS+1]; /* list of what font is on what position */
112 struct { /* table of what font */
113 char fname[3]; /* name maps to what */
114 char *ffile; /* filename in bitdirectory */
115 } fontmap[NFONTS+1];
116
117 #ifdef DEBUGABLE
118 int dbg = 0;
119 #endif
120 int size = 1; /* current point size (internal pstable index) */
121 int font = 1; /* current font - assume reasonable starting font */
122 int stip = -1; /* current stipple font - none to start with */
123 int stipmem = 0; /* current member from stipple font to use */
124 int hpos; /* horizontal position we are to be at next; left = 0 */
125 int vpos; /* current vertical position (down positive) */
126 int maxv; /* farthest down the page we've been */
127 extern linethickness; /* thickness (in pixels) of any drawn object */
128 extern linmod; /* line style (a bit mask - dotted, etc.) of objects */
129 int lastw; /* width of last character printed */
130
131
132 #define DISPATCHSIZE 256 /* must be a power of two */
133 #define CHARMASK (DISPATCHSIZE-1)
134 #define DSIZ ((sizeof *dispatch)*DISPATCHSIZE)
135 #define OUTFILE fileno (stdout)
136
137 #define RES 200 /* resolution of the device (dots/in) */
138 #define RASTER_LENGTH 7040 /* device line length */
139 #define BYTES_PER_LINE (RASTER_LENGTH/8)
140 #define BAND 1 /* length of a band in inches */
141 #define NLINES (int)(BAND * RES) /* BAND" long bands */
142 #define BUFFER_SIZE (NLINES*BYTES_PER_LINE) /* number of chars in picture */
143
144 #define BUFTOP (&buffer[0])
145 #define BUFBOTTOM (&buffer[BUFFER_SIZE] - 1)
146 #define buf0p BUFTOP /* vorigin in circular buffer */
147 #define PAGEEND 1 /* flags to "outband" to tell */
148 #define OVERBAND 0 /* whether to fill out a page */
149
150
151 int pltmode[] = { VPLOT };
152 int prtmode[] = { VPRINT };
153 char buffer[BUFFER_SIZE]; /* versatec-wide NLINES buffer */
154 int vorigin = 0; /* where on the page startbuf maps to */
155 int pagelen = 0; /* how long the current "page" has printed */
156
157 char * calloc();
158 char * nalloc();
159 char * allpanic();
160 char * operand();
161
162 struct header {
163 short magic;
164 unsigned short size;
165 short maxx;
166 short maxy;
167 short xtnd;
168 } header;
169
170 struct dispatch{
171 unsigned short addr;
172 short nbytes;
173 char up;
174 char down;
175 char left;
176 char right;
177 short width;
178 };
179
180 struct fontdes {
181 int fnum; /* if == -1, this position unused */
182 int psize;
183 struct dispatch *disp;
184 char *bits;
185 } fontdes[NFONTS+1]; /* is initialized at start of main */
186
187 struct dispatch *dispatch;
188 struct dispatch *stip_disp;
189 int cfnum = -1;
190 int cpsize = 10;
191 int cfont = 1;
192 char *bits;
193 char *stip_bits;
194 int fontwanted = 1; /* flag: "has a new font been requested?" */
195 int nfontnum = -1;
196 int npsize = 10;
197
198
199
main(argc,argv)200 main(argc, argv)
201 char *argv[];
202 {
203 register FILE *fp;
204 register int i;
205
206 for (i = 0; i <= NFONTS; fontdes[i++].fnum = -1);
207 while (--argc > 0 && **++argv == '-') {
208 switch ((*argv)[1]) {
209 case 'F':
210 bitdir = operand(&argc, &argv);
211 break;
212 case 'f':
213 fontdir = operand(&argc, &argv);
214 break;
215 case 'o':
216 outlist(operand(&argc, &argv));
217 break;
218 #ifdef DEBUGABLE
219 case 'd':
220 dbg = atoi(operand(&argc, &argv));
221 if (dbg == 0) dbg = 1;
222 break;
223 #endif
224 }
225 }
226 #ifdef DRIVER
227 ioctl(OUTFILE, VSETSTATE, pltmode);
228 #endif
229
230 if (argc < 1)
231 conv(stdin);
232 else
233 while (argc-- > 0) {
234 if (strcmp(*argv, "-") == 0)
235 fp = stdin;
236 else if ((fp = fopen(*argv, "r")) == NULL)
237 error(FATAL, "can't open %s", *argv);
238 conv(fp);
239 fclose(fp);
240 argv++;
241 }
242 exit(0);
243 }
244
245
246 /*----------------------------------------------------------------------------*
247 | Routine: char * operand (& argc, & argv)
248 |
249 | Results: returns address of the operand given with a command-line
250 | option. It uses either "-Xoperand" or "-X operand", whichever
251 | is present. The program is terminated if no option is present.
252 |
253 | Side Efct: argc and argv are updated as necessary.
254 *----------------------------------------------------------------------------*/
255
operand(argcp,argvp)256 char *operand(argcp, argvp)
257 int * argcp;
258 char ***argvp;
259 {
260 if ((**argvp)[2]) return(**argvp + 2); /* operand immediately follows */
261 if ((--*argcp) <= 0) { /* no operand */
262 error (FATAL, "command-line option operand missing.");
263 }
264 return(*(++(*argvp))); /* operand next word */
265 }
266
267
outlist(s)268 outlist(s) /* process list of page numbers to be printed */
269 char *s;
270 {
271 int n1, n2;
272 #ifdef DEBUGABLE
273 int i;
274 #endif
275
276 nolist = 0;
277 while (*s) {
278 n1 = 0;
279 if (isdigit(*s))
280 do
281 n1 = 10 * n1 + *s++ - '0';
282 while (isdigit(*s));
283 else
284 n1 = -9999;
285 n2 = n1;
286 if (*s == '-') {
287 s++;
288 n2 = 0;
289 if (isdigit(*s))
290 do
291 n2 = 10 * n2 + *s++ - '0';
292 while (isdigit(*s));
293 else
294 n2 = 9999;
295 }
296 olist[nolist++] = n1;
297 olist[nolist++] = n2;
298 if (*s != '\0')
299 s++;
300 }
301 olist[nolist] = 0;
302 #ifdef DEBUGABLE
303 if (dbg)
304 for (i=0; i<nolist; i += 2)
305 fprintf(stderr,"%3d %3d\n", olist[i], olist[i+1]);
306 #endif
307 }
308
conv(fp)309 conv(fp)
310 register FILE *fp;
311 {
312 register int c, k;
313 int m, n, n1, m1;
314 char str[100], buf[300];
315
316 while ((c = getc(fp)) != EOF) {
317 switch (c) {
318 case '\n': /* when input is text */
319 case 0: /* occasional noise creeps in */
320 case '\t':
321 case ' ':
322 break;
323 case '{': /* push down current environment */
324 t_push();
325 break;
326 case '}':
327 t_pop();
328 break;
329 case '0': case '1': case '2': case '3': case '4':
330 case '5': case '6': case '7': case '8': case '9':
331 /* two motion digits plus a character */
332 hmot((c-'0')*10 + getc(fp)-'0');
333 put1(getc(fp));
334 break;
335 case 'c': /* single ascii character */
336 put1(getc(fp));
337 break;
338 case 'C':
339 fscanf(fp, "%s", str);
340 put1s(str);
341 break;
342 case 't': /* straight text */
343 if (fgets(buf, sizeof(buf), fp) == NULL)
344 error(FATAL, "unexpected end of input");
345 t_text(buf);
346 break;
347 case 'D': /* draw function */
348 if (fgets(buf, sizeof(buf), fp) == NULL)
349 error(FATAL, "unexpected end of input");
350 switch (buf[0]) {
351 case 'l': /* draw a line */
352 sscanf(buf+1, "%d %d", &n, &m);
353 drawline(n, m);
354 break;
355 case 'c': /* circle */
356 sscanf(buf+1, "%d", &n);
357 drawcirc(n);
358 break;
359 case 'e': /* ellipse */
360 sscanf(buf+1, "%d %d", &m, &n);
361 drawellip(m, n);
362 break;
363 case 'a': /* arc */
364 sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1);
365 drawarc(n, m, n1, m1);
366 break;
367 case 'q': /* polygon */
368 n = 1; /* get stipple */
369 while (isspace(buf[++n])); /* number first */
370 setfill(atoi(&(buf[n]))); /* set up stipple */
371 while (isdigit(buf[++n]));
372 polygon(&(buf[n]), fp); /* draw polygon */
373 break;
374 case '~': /* wiggly line */
375 case 'g': /* gremlin spline */
376 drawwig(buf+1, fp, buf[0] == '~');
377 break;
378 case 't': /* line thickness */
379 sscanf(buf+1, "%d", &n);
380 drawthick(n);
381 break;
382 case 's': /* line style */
383 sscanf(buf+1, "%d", &n);
384 drawstyle(n);
385 break;
386 default:
387 error(FATAL, "unknown drawing function %s", buf);
388 break;
389 }
390 break;
391 case 's':
392 fscanf(fp, "%d", &n);
393 setsize(t_size(n));
394 break;
395 case 'i':
396 fscanf(fp, "%d", &n);
397 setstip(n);
398 break;
399 case 'f':
400 fscanf(fp, "%s", str);
401 setfont(t_font(str));
402 break;
403 case 'H': /* absolute horizontal motion */
404 while ((c = getc(fp)) == ' ')
405 ;
406 k = 0;
407 do {
408 k = 10 * k + c - '0';
409 } while (isdigit(c = getc(fp)));
410 ungetc(c, fp);
411 hgoto(k);
412 break;
413 case 'h': /* relative horizontal motion */
414 while ((c = getc(fp)) == ' ')
415 ;
416 k = 0;
417 do {
418 k = 10 * k + c - '0';
419 } while (isdigit(c = getc(fp)));
420 ungetc(c, fp);
421 hmot(k);
422 break;
423 case 'w': /* word space */
424 break;
425 case 'V':
426 fscanf(fp, "%d", &n);
427 vgoto(n);
428 break;
429 case 'v':
430 fscanf(fp, "%d", &n);
431 vmot(n);
432 break;
433 case 'P': /* new spread */
434 if (output) outband(OVERBAND);
435 break;
436 case 'p': /* new page */
437 fscanf(fp, "%d", &n);
438 t_page(n);
439 break;
440 case 'n': /* end of line */
441 t_newline();
442
443 case '#': /* comment */
444 do
445 c = getc(fp);
446 while (c != '\n' && c != EOF);
447 break;
448 case 'x': /* device control */
449 if (devcntrl(fp)) return;
450 break;
451 default:
452 error(FATAL, "unknown input character %o %c", c, c);
453 }
454 }
455 }
456
devcntrl(fp)457 int devcntrl(fp) /* interpret device control functions */
458 FILE *fp; /* returns -1 apon recieving "stop" command */
459 {
460 char str[20], str1[50], buf[50];
461 int c, n;
462
463 fscanf(fp, "%s", str);
464 switch (str[0]) { /* crude for now */
465 case 'i': /* initialize */
466 fileinit();
467 t_init();
468 break;
469 case 't': /* trailer */
470 break;
471 case 'p': /* pause -- can restart */
472 t_reset('p');
473 break;
474 case 's': /* stop */
475 t_reset('s');
476 return -1;
477 case 'r': /* resolution assumed when prepared */
478 fscanf(fp, "%d", &n);
479 if (n!=RES) error(FATAL,"Input computed for wrong printer");
480 break;
481 case 'f': /* font used */
482 fscanf(fp, "%d %s", &n, str);
483 (void) fgets(buf, sizeof buf, fp); /* in case of filename */
484 ungetc('\n', fp); /* fgets goes too far */
485 str1[0] = 0; /* in case nothing comes in */
486 sscanf(buf, "%s", str1);
487 loadfont(n, str, str1);
488 break;
489 /* these don't belong here... */
490 case 'H': /* char height */
491 fscanf(fp, "%d", &n);
492 t_charht(n);
493 break;
494 case 'S': /* slant */
495 fscanf(fp, "%d", &n);
496 t_slant(n);
497 break;
498 }
499 while ((c = getc(fp)) != '\n') /* skip rest of input line */
500 if (c == EOF)
501 return -1;
502 return 0;
503 }
504
505 /* fileinit: read in font and code files, etc.
506 Must open table for device, read in resolution,
507 size info, font info, etc. and set params.
508 Also read in font name mapping.
509 */
fileinit()510 fileinit()
511 {
512 register int i;
513 register int fin;
514 register int nw;
515 register char *filebase;
516 register char *p;
517 register FILE *fp;
518 char temp[100];
519
520
521 /* first, read in font map file. The file must be of Format:
522 XX FILENAME (XX = troff font name)
523 with one entry per text line of the file.
524 Extra stuff after FILENAME is ignored */
525
526 sprintf(temp, "%s/fontmap", bitdir);
527 if ((fp = fopen(temp, "r")) == NULL)
528 error(FATAL, "Can't open %s", temp);
529 for (i = 0; i <= NFONTS && fgets(temp, 100, fp) != NULL; i++) {
530 sscanf(temp, "%2s", fontmap[i].fname);
531 p = &temp[0];
532 while (*p != ' ' && *p != ' ') p++;
533 while (*p == ' ' || *p == ' ') p++;
534 filebase = p;
535 for (nw = 1; *p != '\n' && *p != ' ' && *p != '\t'; p++) nw++;
536 fontmap[i].ffile = nalloc(1, nw);
537 sscanf(filebase, "%s", fontmap[i].ffile);
538 }
539 fontmap[++i].fname[0] = '0'; /* finish off with zeros */
540 fontmap[i].ffile = (char *) 0;
541 fclose(fp);
542 #ifdef DEBUGABLE
543 if(dbg) {
544 fprintf(stderr, "font map:\n");
545 for (i = 0; fontmap[i].ffile; i++)
546 fprintf(stderr,"%s = %s\n", fontmap[i].fname, fontmap[i].ffile);
547 }
548 #endif
549
550
551 sprintf(temp, "%s/devvp/DESC.out", fontdir);
552 if ((fin = open(temp, 0)) < 0)
553 error(FATAL, "can't open tables for %s", temp);
554 if (read(fin, &dev, sizeof(struct dev)) != sizeof(struct dev))
555 error(FATAL, "can't read header for %s", temp);
556 nfonts = dev.nfonts;
557 nsizes = dev.nsizes;
558 nstips = dev.nstips;
559 nchtab = dev.nchtab;
560 filebase = calloc(1, dev.filesize); /* enough room for whole file */
561 if (read(fin, filebase, dev.filesize) != dev.filesize) /* at once */
562 error(FATAL, "can't read width table for %s", temp);
563 pstab = (short *) filebase;
564 chtab = pstab + nsizes + 1;
565 chname = (char *) (chtab + dev.nchtab);
566 p = chname + dev.lchname;
567 for (i = 1; i <= nfonts; i++) {
568 fontbase[i] = (struct font *) p;
569 nw = *p & BMASK; /* 1st thing is width count */
570 p += sizeof(struct font);
571 widtab[i] = p;
572 codetab[i] = p + 2 * nw;
573 fitab[i] = p + 3 * nw;
574 p += 3 * nw + dev.nchtab + 128 - 32;
575 t_fp(i, fontbase[i]->namefont, fontbase[i]->intname);
576 #ifdef DEBUGABLE
577 if (dbg > 1) fontprint(i);
578 #endif
579 }
580 for (i = 1; i <= nstips; i++) { /* add in stipple "filenames" */
581 if (nfonts + i <= NFONTS)
582 t_fp(nfonts + i, p, (char *)0);
583 p += strlen(p) + 1;
584 }
585 fontbase[0] = (struct font *)
586 calloc(1,3*255 + dev.nchtab + (128-32) + sizeof (struct font));
587 widtab[0] = (char *) fontbase[0] + sizeof (struct font);
588 fontbase[0]->nwfont = 255;
589 close(fin);
590 }
591
592 #ifdef DEBUGABLE
fontprint(i)593 fontprint(i) /* debugging print of font i (0,...) */
594 {
595 int j, n;
596 char *p;
597
598 fprintf(stderr,"font %d:\n", i);
599 p = (char *) fontbase[i];
600 n = fontbase[i]->nwfont & BMASK;
601 fprintf(stderr,
602 "base=0%o, nchars=%d, spec=%d, name=%s, widtab=0%o, fitab=0%o\n",p,
603 n,fontbase[i]->specfont,fontbase[i]->namefont,widtab[i],fitab[i]);
604 fprintf(stderr,"widths:\n");
605 for (j=0; j <= n; j++) {
606 fprintf(stderr," %2d", widtab[i][j] & BMASK);
607 if (j % 20 == 19) fprintf(stderr,"\n");
608 }
609 fprintf(stderr,"\ncodetab:\n");
610 for (j=0; j <= n; j++) {
611 fprintf(stderr," %2d", codetab[i][j] & BMASK);
612 if (j % 20 == 19) fprintf(stderr,"\n");
613 }
614 fprintf(stderr,"\nfitab:\n");
615 for (j=0; j <= dev.nchtab + 128-32; j++) {
616 fprintf(stderr," %2d", fitab[i][j] & BMASK);
617 if (j % 20 == 19) fprintf(stderr,"\n");
618 }
619 fprintf(stderr,"\n");
620 }
621 #endif
622
623
loadfont(n,s,s1)624 loadfont(n, s, s1) /* load font info for font s on position n (0...) */
625 int n;
626 char *s, *s1;
627 {
628 char temp[60];
629 register int fin;
630 register int nw;
631 register int norig;
632
633 if (n < 0 || n > NFONTS)
634 error(FATAL, "illegal fp command %d %s", n, s);
635 if (strcmp(s, fontbase[n]->namefont) == 0)
636 return;
637
638 for (fin = 1; fin <= NFONTS; fin++) /* first check to see if the */
639 if (strcmp(s, fontbase[fin]->namefont) == 0) { /* font is loaded */
640 register char *c; /* somewhere else */
641
642 #define ptrswap(x, y) { c = (char*) (x); x = y; y = c; }
643 #define ptrfswap(x, y) { c = (char*) (x); x = y; y = (struct font *)c; }
644
645 ptrfswap(fontbase[n], fontbase[fin]);
646 ptrswap(codetab[n], codetab[fin]);
647 ptrswap(widtab[n], widtab[fin]);
648 ptrswap(fitab[n], fitab[fin]);
649 t_fp(n, fontbase[n]->namefont, fontbase[n]->intname);
650 t_fp(fin, fontbase[fin]->namefont, fontbase[fin]->intname);
651 return;
652 }
653
654 if (s1 == NULL || s1[0] == '\0')
655 sprintf(temp, "%s/devvp/%s.out", fontdir, s);
656 else
657 sprintf(temp, "%s/%s.out", s1, s);
658 if ((fin = open(temp, 0)) < 0)
659 error(FATAL, "can't open font table %s", temp);
660 norig = fontbase[n]->nwfont & BMASK;
661 if (read(fin,fontbase[n],3*norig+nchtab+128-32+sizeof(struct font)) < 0)
662 error(FATAL, "Can't read in font %s on position %d", s, n);
663 if ((fontbase[n]->nwfont & BMASK) > norig)
664 error(FATAL, "Font %s too big for position %d", s, n);
665 close(fin);
666 nw = fontbase[n]->nwfont & BMASK;
667 widtab[n] = (char *) fontbase[n] + sizeof(struct font);
668 codetab[n] = (char *) widtab[n] + 2 * nw;
669 fitab[n] = (char *) widtab[n] + 3 * nw;
670 t_fp(n, fontbase[n]->namefont, fontbase[n]->intname);
671 fontbase[n]->nwfont = norig; /* to later use full original size */
672 #ifdef DEBUGABLE
673 if (dbg > 1) fontprint(n);
674 #endif
675 }
676
677
678 /*VARARGS1*/
error(f,s,a1,a2,a3,a4,a5,a6,a7)679 error(f, s, a1, a2, a3, a4, a5, a6, a7) {
680 fprintf(stderr, "dver: ");
681 fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7);
682 fprintf(stderr, "\n");
683 if (f) exit(ABORT);
684 }
685
686
t_init()687 t_init() /* initialize device */
688 {
689 vorigin = pagelen = maxv = hpos = vpos = 0;
690
691 output = 0; /* don't output anything yet */
692 setsize(t_size(10)); /* start somewhere */
693 setfont(1);
694 }
695
696
697 struct state {
698 int ssize;
699 int sfont;
700 int shpos;
701 int svpos;
702 int sstyle;
703 int sthick;
704 };
705 struct state state[MAXSTATE];
706 struct state *statep = state;
707
t_push()708 t_push() /* begin a new block */
709 {
710 statep->ssize = size;
711 statep->sfont = font;
712 statep->sstyle = linmod;
713 statep->sthick = linethickness;
714 statep->shpos = hpos;
715 statep->svpos = vpos;
716 if (statep++ >= state+MAXSTATE)
717 error(FATAL, "{ nested too deep");
718 }
719
t_pop()720 t_pop() /* pop to previous state */
721 {
722 if (--statep < state)
723 error(FATAL, "extra }");
724 size = statep->ssize;
725 font = statep->sfont;
726 hpos = statep->shpos;
727 vpos = statep->svpos;
728 linmod = statep->sstyle;
729 linethickness = statep->sthick;
730 }
731
732
t_page(n)733 t_page(n) /* do whatever new page functions */
734 {
735 int i;
736
737
738 if (output) outband(PAGEEND);
739
740 maxv = vpos = 0;
741
742 output = 1;
743 if (nolist == 0)
744 return; /* no -o specified */
745 output = 0;
746 for (i = 0; i < nolist; i += 2)
747 if (n >= olist[i] && n <= olist[i+1]) {
748 output = 1;
749 break;
750 }
751 }
752
753
outband(page)754 outband(page)
755 int page;
756 {
757 register int outsize;
758
759 if (page == PAGEEND) { /* set outsize to inch boundary */
760 outsize = (maxv + (RES - 2) - pagelen) / RES;
761 vorigin = pagelen = 0; /* reset for new page */
762 if (outsize < 1) return; /* if outsize <= zero, forget it */
763
764 outsize *= RES * BYTES_PER_LINE;
765 vwrite(buf0p, outsize > BUFFER_SIZE ? BUFFER_SIZE : outsize);
766 vclear(buf0p, BUFFER_SIZE);
767 while ((outsize -= BUFFER_SIZE) > 0)
768 vwrite(buf0p, outsize > BUFFER_SIZE ? BUFFER_SIZE : outsize);
769 } else {
770 vorigin += NLINES;
771 pagelen += NLINES;
772 vwrite(buf0p, BUFFER_SIZE);
773 vclear(buf0p, BUFFER_SIZE);
774 }
775 }
776
777
t_newline()778 t_newline() /* do whatever for the end of a line */
779 {
780 hpos = 0; /* because we're now back at the left margin */
781 }
782
t_size(n)783 t_size(n) /* convert integer to internal size number*/
784 int n;
785 {
786 int i;
787
788 if (n <= pstab[0])
789 return(0);
790 else if (n >= pstab[nsizes - 1])
791 return(nsizes - 1);
792 for (i = 0; n > pstab[i]; i++)
793 ;
794 return(i);
795 }
796
797 /*ARGSUSED*/
t_charht(n)798 t_charht(n) /* set character height to n */
799 int n;
800 {
801 #ifdef DEBUGABLE
802 if (dbg) error(!FATAL, "can't set height on versatec");
803 #endif
804 }
805
806 /*ARGSUSED*/
t_slant(n)807 t_slant(n) /* set slant to n */
808 int n;
809 {
810 #ifdef DEBUGABLE
811 if (dbg) error(!FATAL, "can't set slant on versatec");
812 #endif
813 }
814
t_font(s)815 t_font(s) /* convert string to internal font number */
816 char *s;
817 {
818 int n;
819
820 n = atoi(s);
821 if (n < 0 || n > nfonts)
822 n = 1;
823 return(n);
824 }
825
t_text(s)826 t_text(s) /* print string s as text */
827 char *s;
828 {
829 int c;
830 char str[100];
831
832 if (!output)
833 return;
834 while (c = *s++) {
835 if (c == '\\') {
836 switch (c = *s++) {
837 case '\\':
838 case 'e':
839 put1('\\');
840 break;
841 case '(':
842 str[0] = *s++;
843 str[1] = *s++;
844 str[2] = '\0';
845 put1s(str);
846 break;
847 }
848 } else {
849 put1(c);
850 }
851 hmot(lastw);
852 #ifdef DEBUGABLE
853 if (dbg) fprintf(stderr,"width = %d\n", lastw);
854 #endif
855 }
856 }
857
858
t_reset(c)859 t_reset(c)
860 {
861 switch(c){
862 case 's':
863 t_page(0);
864 #ifdef DRIVER
865 ioctl(OUTFILE, VSETSTATE, prtmode);
866 #endif
867 break;
868 }
869 }
870
871
vgoto(n)872 vgoto (n)
873 int n;
874 {
875 vpos = n;
876 }
877
878
put1s(s)879 put1s(s) /* s is a funny char name */
880 char *s;
881 {
882 int i;
883
884 if (!output)
885 return;
886 #ifdef DEBUGABLE
887 if (dbg) fprintf(stderr,"%s ", s);
888 #endif
889 for (i = 0; i < nchtab; i++)
890 if (strcmp(&chname[chtab[i]], s) == 0)
891 break;
892 if (i < nchtab)
893 put1(i + 128);
894 }
895
put1(c)896 put1(c) /* output char c */
897 int c;
898 {
899 char *pw;
900 register char *p;
901 register int i, k;
902 int j, ofont, code;
903
904 if (!output)
905 return;
906 c -= 32;
907 if (c <= 0) {
908 #ifdef DEBUGABLE
909 if (dbg) fprintf(stderr,"non-exist 0%o\n", c + 32);
910 #endif
911 lastw = (widtab[font][0] * pstab[size] + dev.unitwidth/2)
912 / dev.unitwidth;
913 return;
914 }
915 k = ofont = font;
916 i = fitab[font][c] & BMASK;
917 if (i != 0) { /* it's on this font */
918 p = codetab[font]; /* get the printing value of ch */
919 pw = widtab[font]; /* get the width */
920 } else /* on another font (we hope) */
921 for (j=0; j <= nfonts; j++, k = (k+1) % (nfonts+1)){
922 if (fitab[k] == 0)
923 continue;
924 if ((i = fitab[k][c] & BMASK) != 0) {
925 p = codetab[k];
926 pw = widtab[k];
927 setfont(k);
928 break;
929 }
930 }
931
932 if (i == 0) {
933 #ifdef DEBUGABLE
934 if (dbg) fprintf(stderr,"not found 0%o\n", c+32);
935 #endif
936 return;
937 }
938 code = p[i] & BMASK;
939 #ifdef DEBUGABLE
940 if (dbg) {
941 if (isprint(c+32))
942 fprintf(stderr,"%c %d\n", c+32, code);
943 else
944 fprintf(stderr,"%03o %d\n", c+32, code);
945 }
946 #endif
947 outc(code); /* character is < 254 */
948 if (font != ofont)
949 setfont(ofont);
950 lastw = ((pw[i]&077) * pstab[size] + dev.unitwidth/2) / dev.unitwidth;
951 }
952
953
954
setsize(n)955 setsize(n) /* set point size to n (internal) */
956 int n;
957 {
958
959 if (n == size)
960 return; /* already there */
961 if (vloadfont(font, pstab[n]) != -1)
962 size = n;
963 }
964
965 /*ARGSUSED*/
t_fp(n,s,si)966 t_fp(n, s, si) /* font position n now contains font s, intname si */
967 int n; /* internal name is ignored */
968 char *s, *si;
969 {
970 register int i;
971
972 /* first convert s to filename if possible */
973 for (i = 0; fontmap[i].ffile != (char *) 0; i++) {
974 #ifdef DEBUGABLE
975 if(dbg>1)fprintf(stderr,"testing :%s:%s:\n",s,fontmap[i].fname);
976 #endif
977 if (strcmp(s, fontmap[i].fname) == 0) {
978 s = fontmap[i].ffile;
979 #ifdef DEBUGABLE
980 if(dbg)fprintf(stderr, "found :%s:\n",fontmap[i].ffile);
981 #endif
982 break;
983 }
984 }
985
986 fontname[n] = s;
987 for(i = 0;i <= NFONTS;i++) /* free the bits of that font */
988 if (fontdes[i].fnum == n){
989 nfree(fontdes[i].bits);
990 fontdes[i].fnum = -1;
991 }
992 }
993
setfont(n)994 setfont(n) /* set font to n */
995 int n;
996 {
997 if (n < 0 || n > nfonts)
998 error(FATAL, "illegal font %d", n);
999 if (vloadfont(n,pstab[size]) != -1)
1000 font = n;
1001 }
1002
setstip(n)1003 setstip(n) /* set stipple font to n */
1004 int n;
1005 {
1006 if (n < 1 || n > nstips)
1007 error(FATAL, "illegal stipple %d", n);
1008 stip = n;
1009 }
1010
1011
1012 /*----------------------------------------------------------------------------*
1013 | Routine: setfill(stipple_number)
1014 |
1015 | Results: sets the fill-pattern pointers (stip_disp and
1016 | stip_bits) for a particular stipple. Takes stipple
1017 | font from current "stip" number.
1018 *----------------------------------------------------------------------------*/
1019
setfill(number)1020 setfill(number)
1021 int number;
1022 {
1023 int curfont; /* places to save current text font */
1024 int cursize;
1025
1026 /* set global stipmem for polygon */
1027 if (number < 0 || number >= DISPATCHSIZE)
1028 stipmem = 0;
1029 else
1030 stipmem = number;
1031
1032 curfont = cfnum; /* get pointers to */
1033 cursize = cpsize; /* the inuse font */
1034 if (vloadfont(nfonts + stip, 0)) {
1035 stip_disp = (struct dispatch *) NULL; /* stipple not here */
1036 } else {
1037 if (fontwanted) {
1038 if (getfont()) {
1039 stip_disp = (struct dispatch *) NULL;
1040 } else {
1041 stip_disp = dispatch; /* save for polygon routine */
1042 stip_bits = bits;
1043 }
1044 } else {
1045 stip_disp = dispatch; /* save for polygon routine */
1046 stip_bits = bits;
1047 }
1048 }
1049 vloadfont(curfont, cursize);
1050 }
1051
1052
vloadfont(fnum,fsize)1053 vloadfont(fnum, fsize)
1054 register int fnum;
1055 register int fsize;
1056 {
1057 register int i;
1058
1059 fontwanted = 0;
1060 if (fnum == cfnum && fsize == cpsize)
1061 return(0);
1062 for (i = 0; i <= NFONTS; i++) {
1063 if (fontdes[i].fnum == fnum && fontdes[i].psize == fsize) {
1064 cfnum = fontdes[i].fnum;
1065 cpsize = fontdes[i].psize;
1066 dispatch = &fontdes[i].disp[0];
1067 bits = fontdes[i].bits;
1068 cfont = i;
1069 return (0);
1070 }
1071 }
1072 /* this is a new font */
1073 if (fnum < 0 || fnum > NFONTS || fontname[fnum] == 0) {
1074 #ifdef DEBUGABLE
1075 if (dbg) error(!FATAL, "illegal font %d size %d", fnum, fsize);
1076 #endif
1077 return(-1);
1078 }
1079 /* Need to verify the existance of that font/size here*/
1080 nfontnum = fnum;
1081 npsize = fsize;
1082 fontwanted++;
1083 return (0);
1084 }
1085
1086
getfont()1087 getfont()
1088 {
1089 register int fnum;
1090 register int fsize;
1091 register int fontd;
1092 register int d;
1093 register int sizehunt = size;
1094 char cbuf[BUFSIZ];
1095
1096
1097 fnum = nfontnum;
1098 fsize = npsize;
1099 /* try to open font file - if unsuccessful, hunt for */
1100 /* a file of same style, different size to substitute */
1101 d = -1; /* direction to look in pstab (smaller first) */
1102 do {
1103 sprintf(cbuf, "%s/%s.%d", bitdir, fontname[fnum], fsize);
1104 fontd = open(cbuf, OPENREAD);
1105 if (fontd == -1) { /* File wasn't found. Try another ps */
1106 sizehunt += d;
1107 if (sizehunt < 0) { /* past beginning - look higher */
1108 d = 1;
1109 sizehunt = size + 1;
1110 }
1111 if (sizehunt > nsizes) { /* past top - forget it */
1112 d = 0;
1113 } else {
1114 fsize = pstab[sizehunt];
1115 }
1116 }
1117 } while (fontd == -1 && d != 0);
1118
1119 if (fontd == -1) { /* completely unsuccessful */
1120 perror(cbuf);
1121 error(!FATAL,"fnum = %d, psize = %d, name = %s",
1122 fnum, npsize, fontname[fnum]);
1123 fontwanted = 0;
1124 return (-1);
1125 }
1126 if (read(fontd, &header, sizeof (header)) != sizeof (header)
1127 || header.magic != 0436)
1128 fprintf(stderr, "%s: Bad font file", cbuf);
1129 else {
1130 cfont = relfont();
1131 if ((bits=nalloc(header.size+DSIZ+1,1))== NULL)
1132 if ((bits=allpanic(header.size+DSIZ+1))== NULL) {
1133 error(FATAL, "%s: ran out of memory", cbuf);
1134 }
1135
1136 /*
1137 * have allocated one chunk of mem for font, dispatch.
1138 * get the dispatch addr, align to word boundary.
1139 */
1140
1141 d = (int) bits+header.size;
1142 d += 1;
1143 d &= ~1;
1144 if (read (fontd, d, DSIZ) != DSIZ
1145 || read (fontd, bits, header.size) != header.size)
1146 fprintf(stderr, "bad font header");
1147 else {
1148 close(fontd);
1149 cfnum = fontdes[cfont].fnum = fnum;
1150 cpsize = fontdes[cfont].psize = fsize;
1151 fontdes [cfont].bits = bits;
1152 fontdes [cfont].disp = (struct dispatch *) d;
1153 dispatch = &fontdes[cfont].disp[0];
1154 fontwanted = 0;
1155 return (0);
1156 }
1157 }
1158 close(fontd);
1159 fontwanted = 0;
1160 return(-1);
1161 }
1162
1163 /*
1164 * "release" a font position - find an empty one, if possible
1165 */
1166
relfont()1167 relfont()
1168 {
1169 register int newfont;
1170
1171 for (newfont = 0; newfont < NFONTS; newfont++)
1172 if (fontdes [newfont].fnum == -1)
1173 break;
1174 if (fontdes [newfont].fnum != -1) {
1175 nfree (fontdes [newfont].bits);
1176 #ifdef DEBUGABLE
1177 if (dbg) fprintf (stderr, "freeing position %d\n", newfont);
1178 } else {
1179 if (dbg)
1180 fprintf (stderr, "taking, not freeing, position %d\n", newfont);
1181 #endif
1182 }
1183 fontdes[newfont].fnum = -1;
1184 return (newfont);
1185 }
1186
allpanic(nbytes)1187 char *allpanic (nbytes)
1188 int nbytes;
1189 {
1190 register int i;
1191
1192 for (i = 0; i <= NFONTS; i++) {
1193 if (fontdes[i].fnum != -1) nfree(fontdes[i].bits);
1194 fontdes[i].fnum = fontdes[i].psize = -1;
1195 cfnum = cpsize = -1;
1196 }
1197 return(nalloc(nbytes,1));
1198 }
1199
1200 int M[] = { 0xffffffff, 0xfefefefe, 0xfcfcfcfc, 0xf8f8f8f8,
1201 0xf0f0f0f0, 0xe0e0e0e0, 0xc0c0c0c0, 0x80808080, 0x0 };
1202 int N[] = { 0x00000000, 0x01010101, 0x03030303, 0x07070707,
1203 0x0f0f0f0f, 0x1f1f1f1f, 0x3f3f3f3f, 0x7f7f7f7f, 0xffffffff };
1204 int strim[] = { 0xffffffff, 0xffffff00, 0xffff0000, 0xff000000, 0 };
1205
outc(code)1206 outc(code)
1207 int code; /* character to print */
1208 {
1209 register struct dispatch *dis; /* ptr to character font record */
1210 register char *addr; /* addr of font data */
1211 int llen; /* length of each font line */
1212 int nlines; /* number of font lines */
1213 register char *scanp; /* ptr to output buffer */
1214 int scanp_inc; /* increment to start of next buffer */
1215 int offset; /* bit offset to start of font data */
1216 register int i; /* loop counter */
1217 register int count; /* font data ptr */
1218 register unsigned fontdata; /* font data temporary */
1219 register int off8; /* reverse of offset */
1220
1221 if (fontwanted)
1222 if (getfont()) return;
1223 dis = dispatch + code;
1224 if (dis->nbytes) {
1225 #ifdef DEBUGABLE
1226 if (dbg) fprintf(stderr, "char %d at (%d,%d)", code, hpos, vpos);
1227 #endif
1228 addr = bits + dis->addr;
1229 llen = (dis->left + dis->right + 7) / 8;
1230 nlines = dis->up + dis->down;
1231 if ((i = vpos + dis->down) > maxv) maxv = i;
1232 scanp = buf0p + (vpos - (vorigin + dis->up)) * BYTES_PER_LINE
1233 + (hpos - dis->left) / 8;
1234 scanp_inc = BYTES_PER_LINE - llen;
1235 offset = (hpos - dis->left) &07;
1236 off8 = 8 - offset;
1237 for (i = 0; i < nlines; i++) {
1238 if (scanp + (count = llen) > BUFBOTTOM) {
1239 #ifdef DEBUGABLE
1240 if (dbg) fprintf(stderr, " scrapped\n");
1241 #endif
1242 return;
1243 }
1244 #ifdef DEBUGABLE
1245 if (dbg) fprintf(stderr, "-");
1246 #endif
1247 if (scanp >= BUFTOP) {
1248 do {
1249 fontdata = *(unsigned *)addr;
1250 addr += 4;
1251 if (count < 4)
1252 fontdata &= ~strim[count];
1253 *(unsigned*)scanp |=(fontdata >> offset) & ~M[off8];
1254 scanp++;
1255 *(unsigned*)scanp |=(fontdata << off8) & ~N[off8];
1256 scanp += 3;
1257 count -= 4;
1258 } while (count > 0);
1259 }
1260 scanp += scanp_inc+count;
1261 addr += count;
1262 }
1263 #ifdef DEBUGABLE
1264 if (dbg) fprintf(stderr, "\n");
1265 #endif
1266 }
1267 }
1268
1269
vwrite(buf,usize)1270 vwrite(buf,usize)
1271 char *buf;
1272 int usize;
1273 {
1274 register int tsize = 0;
1275
1276 while (usize) {
1277 buf += tsize;
1278 tsize = usize > MAXWRIT ? MAXWRIT : usize;
1279 #ifdef DEBUGABLE
1280 if (dbg)fprintf(stderr,"buf = %d size = %d\n",buf,tsize);
1281 if (!dbg)
1282 #endif
1283 if ((tsize = write(OUTFILE, buf, tsize)) < 0) {
1284 perror("dver: write failed");
1285 exit(RESTART);
1286 }
1287 usize -= tsize;
1288 }
1289 }
1290
vclear(ptr,nbytes)1291 vclear (ptr, nbytes)
1292 char *ptr;
1293 int nbytes;
1294 {
1295 register tsize = 0;
1296
1297 while (nbytes){
1298 if ((unsigned)(16*1024) < nbytes) {
1299 tsize = 16 * 1024;
1300 } else
1301 tsize = nbytes;
1302 nbytes -= tsize;
1303 #ifdef DEBUGABLE
1304 if (dbg) fprintf(stderr,"clearing ptr = %d size = %d\n",ptr,tsize);
1305 #endif
1306 clear(ptr,tsize);
1307 ptr += tsize;
1308 }
1309 }
1310
1311 /*ARGSUSED*/
clear(lp,nbytes)1312 clear(lp, nbytes)
1313 char *lp;
1314 int nbytes;
1315 {
1316 #ifdef vax
1317 asm("movc5 $0,(sp),$0,8(ap),*4(ap)");
1318 #else
1319 register int i = nbytes;
1320 register char *cp = lp;
1321
1322 while(i-- > 0)
1323 *(cp++) = 0;
1324 #endif
1325 }
1326
1327 char *
nalloc(i,j)1328 nalloc(i, j)
1329 int i, j;
1330 {
1331 register char *cp;
1332
1333 cp = calloc(i, j);
1334 #ifdef DEBUGABLE
1335 if (dbg) fprintf(stderr, "allocated %d bytes at %x\n", i * j, cp);
1336 #endif
1337 return(cp);
1338 }
1339
nfree(cp)1340 nfree(cp)
1341 char *cp;
1342 {
1343 #ifdef DEBUGABLE
1344 if (dbg) fprintf(stderr, "freeing at %x\n", cp);
1345 #endif
1346 free(cp);
1347 }
1348
1349
1350 /*
1351 * Plot a dot at (x, y). Points should be in the range 0 <= x < RASTER_LENGTH,
1352 * vorigin <= y < vorigin + NLINES. If the point will not fit on the buffer,
1353 * it is left out. Things outside the x boundary are wrapped around the end.
1354 */
point(x,y)1355 point(x, y)
1356 register int x;
1357 register int y;
1358 {
1359 register char *ptr = buf0p + (y - vorigin) * BYTES_PER_LINE + (x >> 3);
1360
1361 if (ptr > BUFBOTTOM || ptr < BUFTOP) /* ignore if it's off buffer */
1362 return;
1363
1364 *ptr |= 1 << (7 - (x & 07));
1365 if (y > maxv) maxv = y;
1366 }
1367
1368
1369 #define MAXX 0x7fff /* largest positive int */
1370 #define MINX 0x8000 /* smallest negative int */
1371 #define MAXVECT 75
1372
1373 typedef struct poly {
1374 struct poly *next; /* doublely-linked lists of vectors */
1375 struct poly *prev;
1376 int param; /* bressenham line algorithm parameter */
1377 short dy; /* delta-y for calculating line */
1378 short dx; /* delta-x for calculating line */
1379 short currx; /* current x in this vector */
1380 short endy; /* where vector ends */
1381 } polyvector;
1382
1383 int rp_len; /* length of the string in "buf" */
1384 char * rp_ptr; /* "walking" pointer into buf */
1385
1386
1387 /*----------------------------------------------------------------------------*
1388 | Routine: read_poly (input_buffer, file_pointer)
1389 |
1390 | Results: gets an integer from buffer pointed to by rp_ptr,
1391 | and advances in the file. If there is nothing left,
1392 | more can be read in from the file. rp_ptr and rp_len
1393 | are set in "polygon".
1394 *----------------------------------------------------------------------------*/
1395
read_poly(buf,fp)1396 read_poly(buf, fp)
1397 char *buf;
1398 FILE *fp;
1399 {
1400 register int i;
1401
1402
1403 if (*rp_ptr == '\n')
1404 return 0;
1405
1406 while (isspace(*++rp_ptr)); /* skip any leading spaces */
1407 i = atoi(rp_ptr); /* convert motion to curve points */
1408 while (isdigit(*++rp_ptr)); /* skip number*/
1409 /* if the amount we read wasn't the */
1410 /* whole thing, read some more in */
1411 if (rp_len - (rp_ptr - buf) < 10 && *(buf + rp_len - 1) != '\n') {
1412 register char *cop = buf;
1413
1414 while (*(cop++) = *(rp_ptr++)); /* what's left to beginning */
1415 if (fgets ((cop - 1), rp_len - (cop - buf), fp) == NULL)
1416 error(FATAL, "unexpected end of input");
1417 rp_ptr = buf;
1418 }
1419
1420 return i;
1421 }
1422
1423
1424 /*----------------------------------------------------------------------------*
1425 | Routine: polygon ( string, file )
1426 |
1427 | Results: draws a polygon specified by the parameters encoded into the
1428 | string (and from the file, if necessary). The parameters are
1429 | broken up into separate vectors. The vectors are encoded as
1430 | follows: (p dx dy curx endy); endy is the bottom of vector,
1431 | curx is where x starts; dx, dy are the deltas for the line;
1432 | if dy is negative, p is the Bresenham line algorithm parameter,
1433 | otherwise p is the starting y. All the active vectors must be
1434 | put first.
1435 |
1436 | The polygon is filled with a stipple pattern from stip_disp
1437 | and stip_bits, which point to the stipple font. The pattern
1438 | is defined by "stip" and "stipmem".
1439 |
1440 | The scan-line algorithm implemented scans from top to
1441 | bottom (low y to high y). It also scans, within a line,
1442 | from left to right (low x to high x).
1443 |
1444 | Bugs: stipple pattern MUST be a power of two bytes "wide" and
1445 | square. The square restriction comes from the fact that
1446 | the varian and versatec are respectively rotated.
1447 *----------------------------------------------------------------------------*/
1448
polygon(buf,fp)1449 polygon(buf, fp)
1450 char *buf;
1451 FILE *fp;
1452 {
1453 int nexty; /* at what y value the next vector starts */
1454 int maxy, miny; /* finds bounds of polygon */
1455 polyvector *activehead; /* doing fill, is active edge list */
1456 polyvector *waitinghead; /* edges waiting to be active */
1457 register polyvector *vectptr; /* random vector */
1458 register int i; /* random register */
1459
1460 char *topstipple; /* points to beginning of stipple glyph */
1461 char *leftstipple; /* points to beginning of line of stipple */
1462 char *leftpage; /* points to the edge of a raster line */
1463 int bytewidth; /* glyph width in bytes */
1464 int mask; /* mask to pick off pixel index into stipple */
1465 int bytemask; /* mask to pick off byte index into stipple */
1466
1467
1468 rp_len = strlen(buf); /* length of the string in "buf" */
1469 rp_ptr = buf; /* "walking" pointer into buf */
1470 /* if no stipple, don't fill */
1471 if (stip_disp == (struct dispatch *) NULL || stip_bits == (char *) NULL)
1472 goto leavepoly;
1473
1474 stip_disp += stipmem; /* set up parameters for */
1475 if (!stip_disp->nbytes) { /* tiling with the stipple */
1476 #ifdef DEBUGABLE
1477 error(!FATAL, "member not found: member %d, stipple %d", stipmem, stip);
1478 #endif
1479 goto leavepoly;
1480 }
1481 topstipple = stip_bits + stip_disp->addr;
1482 bytewidth = stip_disp->up + stip_disp->down;
1483 for (i = 1 << 30; i && i != bytewidth; i = i >> 1)
1484 ;
1485 if (i==0 || bytewidth<8 || bytewidth != stip_disp->right+stip_disp->left) {
1486 error(!FATAL, "invalid stipple: number %d, member %d", stip, stipmem);
1487 goto leavepoly;
1488 }
1489 mask = bytewidth - 1;
1490 bytewidth = bytewidth >> 3;
1491 bytemask = bytewidth - 1;
1492
1493 if ((i = read_poly(buf, fp)) < 2) /* # of vects command holds */
1494 goto leavepoly;
1495 miny = read_poly(buf, fp); /* get limits from command */
1496 maxy = read_poly(buf, fp);
1497
1498 leftstipple = topstipple + (miny & mask) * bytewidth;
1499 leftpage = buf0p + (miny - vorigin) * BYTES_PER_LINE;
1500
1501 /* allocate space for raster-fill algorithm*/
1502 vectptr = (polyvector *) nalloc(sizeof(polyvector), i + 4);
1503 if (vectptr == (polyvector *) NULL) {
1504 error(!FATAL, "unable to allocate space for polygon");
1505 return;
1506 }
1507
1508 waitinghead = vectptr;
1509 vectptr->param = miny - 1; /* put dummy entry at start */
1510 (vectptr++)->prev = NULL;
1511 waitinghead->next = vectptr;
1512 vectptr->prev = waitinghead;
1513
1514 while (i--) {
1515 vectptr->next = vectptr + 1;
1516 vectptr->param = read_poly(buf, fp);
1517 vectptr->dx = read_poly(buf,fp);
1518 vectptr->dy = read_poly(buf,fp);
1519 vectptr->currx = read_poly(buf,fp);
1520 (vectptr++)->endy = read_poly(buf,fp);
1521 vectptr->prev = vectptr - 1;
1522 }
1523
1524 vectptr->param = maxy + 1; /* dummy entry at end, too */
1525 vectptr->currx = vectptr->dx = vectptr->dy = 0;
1526 vectptr->next = NULL;
1527
1528 activehead = ++vectptr; /* two dummy entries for active list */
1529 vectptr->currx = MINX; /* head */
1530 vectptr->endy = maxy + 1;
1531 vectptr->param = vectptr->dx = vectptr->dy = 0;
1532 activehead->next = ++vectptr;
1533 activehead->prev = vectptr;
1534 vectptr->prev = activehead; /* tail */
1535 vectptr->next = activehead;
1536 vectptr->currx = MAXX;
1537 vectptr->endy = maxy + 1;
1538 vectptr->param = vectptr->dx = vectptr->dy = 0;
1539
1540 vectptr = waitinghead->next; /* if anything is active already */
1541 if (vectptr->dy < 0) { /* put them into the active list */
1542 register polyvector *p; /* random useful register pointer */
1543
1544 p = vectptr;
1545 do {
1546 vectptr->dy = -vectptr->dy;
1547 } while ((++vectptr)->dy < 0);
1548
1549 waitinghead->next = vectptr; /* first, remove list from waiting */
1550 (vectptr--)->prev = waitinghead;
1551
1552 activehead->next->prev = vectptr; /* link in end */
1553 vectptr->next = activehead->next;
1554 activehead->next = p; /* link in start */
1555 p->prev = activehead;
1556 }
1557
1558 /* main loop -- gets vectors off the waiting list, */
1559 /* then displays spans while updating the vectors in */
1560 /* the active list */
1561 while (miny <= maxy) {
1562 i = maxy + 1; /* this is the NEXT time to get a new vector */
1563 for (vectptr = waitinghead->next; vectptr != NULL; ) {
1564 if (miny == vectptr->param) {
1565 /* the entry in waiting list (vectptr) is */
1566 /* ready to go into active list. Need to */
1567 /* convert some vector stuff and sort the */
1568 /* entry into the list. */
1569 register polyvector *p; /* random vector pointers */
1570 register polyvector *v;
1571
1572 /* convert this */
1573 if (vectptr->dx < 0) /* entry to active */
1574 vectptr->param = -((vectptr->dx >> 1) + (vectptr->dy >> 1));
1575 else
1576 vectptr->param = (vectptr->dx >> 1) - (vectptr->dy >> 1);
1577
1578 p = vectptr; /* remove from the */
1579 vectptr = vectptr->next; /* waiting list */
1580 vectptr->prev = p->prev;
1581 p->prev->next = vectptr;
1582 /* find where it goes */
1583 /* in the active list */
1584 /* (sorted smallest first) */
1585 for (v = activehead->next; v->currx < p->currx; v = v->next)
1586 ;
1587 p->next = v; /* insert into active list */
1588 p->prev = v->prev; /* before the one it stopped on */
1589 v->prev = p;
1590 p->prev->next = p;
1591 } else {
1592 if (i > vectptr->param) {
1593 i = vectptr->param;
1594 }
1595 vectptr = vectptr->next;
1596 }
1597 }
1598 nexty = i;
1599
1600 /* print the polygon while there */
1601 /* are no more vectors to add */
1602 while (miny < nexty) {
1603 /* remove any finished vectors */
1604 vectptr = activehead->next;
1605 do {
1606 if (vectptr->endy <= miny) {
1607 vectptr->prev->next = vectptr->next;
1608 vectptr->next->prev = vectptr->prev;
1609 }
1610 } while ((vectptr = vectptr->next) != activehead);
1611
1612 /* draw the span */
1613 vectptr = activehead->next;
1614 while (vectptr->next != activehead) {
1615 register int start; /* get the beginning */
1616 register int length; /* and the end of span */
1617 register char *glyph;
1618 register char *raster;
1619
1620 start = vectptr->currx;
1621 vectptr = vectptr->next;
1622 length = vectptr->currx + 1;
1623 vectptr = vectptr->next;
1624
1625 /* bound the polygon to the page */
1626 if (start >= RASTER_LENGTH)
1627 break;
1628 if (start < 0) start = 0;
1629 if (length > RASTER_LENGTH) length = RASTER_LENGTH;
1630 length -= start; /* length is in pixels */
1631
1632 i = start & 7;
1633 start = start >> 3; /* start is in bytes */
1634 raster = leftpage + start;
1635 glyph = leftstipple + (start & bytemask);
1636
1637 if (i) { /* do any piece of byte */
1638 register char data; /* that hangs on the front */
1639
1640 data = (*(glyph++)) & (0x7f >> --i);
1641 length -= 7 - i;
1642 if (length < 0) { /* less than one byte wide? */
1643 data &= 0xff << -length;
1644 length = 0; /* force clean stoppage */
1645 }
1646 *(raster++) |= data;
1647 /* update glyph ptr after first byte */
1648 if (!(++start & bytemask))
1649 glyph = leftstipple;
1650 }
1651 /* fill the line of raster */
1652 while ((length -= 8) >= 0) {
1653 *(raster++) |= *(glyph++);
1654 if (!(++start & bytemask))
1655 glyph = leftstipple;
1656 }
1657 if (length & 7) { /* add any part hanging off the end */
1658 *raster |= (*glyph) & (0xff << -length);
1659 }
1660 }
1661
1662 #ifdef DEBUGABLE
1663 if (dbg) {
1664 vectptr = activehead;
1665 do {
1666 fprintf (stderr, "%d ", vectptr->currx);
1667 vectptr = vectptr->next;
1668 } while (vectptr != activehead);
1669 }
1670 #endif
1671 /* update the vectors */
1672 vectptr = activehead->next;
1673 do {
1674 if (vectptr->dx > 0) {
1675 while (vectptr->param >= 0) {
1676 vectptr->param -= vectptr->dy;
1677 vectptr->currx++;
1678 }
1679 vectptr->param += vectptr->dx;
1680 } else if (vectptr->dx < 0) {
1681 while (vectptr->param >= 0) {
1682 vectptr->param -= vectptr->dy;
1683 vectptr->currx--;
1684 }
1685 vectptr->param -= vectptr->dx;
1686 }
1687 /* must sort the vectors if updates */
1688 /* caused them to cross */
1689 /* also move to next vector here */
1690 if (vectptr->currx < vectptr->prev->currx) {
1691 register polyvector *v; /* vector to move */
1692 register polyvector *p; /* vector to put it after */
1693
1694 v = vectptr;
1695 p = v->prev;
1696 while (v->currx < p->currx) /* find the */
1697 p = p->prev; /* right vector */
1698
1699 vectptr = vectptr->next; /* remove from spot */
1700 vectptr->prev = v->prev;
1701 v->prev->next = vectptr;
1702
1703 v->prev = p; /* put in new spot */
1704 v->next = p->next;
1705 p->next = v;
1706 v->next->prev = v;
1707 } else {
1708 vectptr = vectptr->next;
1709 }
1710 } while (vectptr != activehead);
1711 #ifdef DEBUGABLE
1712 if (dbg) fprintf(stderr, "line done\n");
1713 #endif
1714
1715 if (++miny & mask) {
1716 leftstipple += bytewidth;
1717 } else {
1718 leftstipple = topstipple;
1719 }
1720 leftpage += BYTES_PER_LINE;
1721 } /* while (miny < nexty) */
1722 } /* while (miny <= maxy) */
1723
1724 nfree(waitinghead); /* dump the space allocated for polygon */
1725
1726 leavepoly:
1727 while (*rp_ptr != '\n')
1728 i = read_poly(buf, fp);
1729 } /* polygon function */
1730