1*24162Sslatteng /* dver.c 1.17 85/08/05
212593Sslatteng *
316099Sslatteng * VAX Versatec driver for the new troff
412587Sslatteng *
513857Sslatteng * Authors: BWK(BELL)
613857Sslatteng * VCAT(berkley)
713857Sslatteng * Richard L. Hyde, Perdue University
814759Sslatteng * and David Slattengren, U.C. Berkeley
912587Sslatteng */
1012587Sslatteng
1112587Sslatteng
1212593Sslatteng /*******************************************************************************
1312587Sslatteng
1412593Sslatteng output language from troff:
1512593Sslatteng all numbers are character strings
1612593Sslatteng
1713275Sslatteng #..\n comment
1812587Sslatteng sn size in points
1913275Sslatteng fn font as number from 1 to n
2016538Sslatteng in stipple as number from 1 to n
2112587Sslatteng cx ascii character x
2213275Sslatteng Cxyz funny char \(xyz. terminated by white space
2312587Sslatteng Hn go to absolute horizontal position n
2412587Sslatteng Vn go to absolute vertical position n (down is positive)
2512587Sslatteng hn go n units horizontally (relative)
2612587Sslatteng vn ditto vertically
2712587Sslatteng nnc move right nn, then print c (exactly 2 digits!)
2812587Sslatteng (this wart is an optimization that shrinks output file size
2912587Sslatteng about 35% and run-time about 15% while preserving ascii-ness)
3014759Sslatteng pn new page begins (number n) -- set v to 0
3114759Sslatteng P spread ends -- output it.
3213275Sslatteng nb a end of line (information only -- no action needed)
3313275Sslatteng b = space before line, a = after
3413275Sslatteng w paddable word space -- no action needed
3513275Sslatteng
3612593Sslatteng Dt ..\n draw operation 't':
3716538Sslatteng Dt d set line thickness to d pixels
3816538Sslatteng Ds d set line style mask to d
3912587Sslatteng Dl x y line from here by x,y
4012587Sslatteng Dc d circle of diameter d with left side here
4112587Sslatteng De x y ellipse of axes x,y with left side here
4212587Sslatteng Da x y r arc counter-clockwise by x,y of radius r
4313275Sslatteng D~ x y x y ... B-spline curve by x,y then x,y ...
4416538Sslatteng Dg x y x y ... gremlin spline curve by x,y then x,y ...
4516538Sslatteng Dq d n miny maxy [p dx dy curx endy] polygon filled with d, has n
4616538Sslatteng vectors, with extents from miny to maxy (no border)
4713275Sslatteng
4812593Sslatteng x ..\n device control functions:
4913275Sslatteng x i init
5013275Sslatteng x T s name of device is s
5113275Sslatteng x r n h v resolution is n/inch h = min horizontal motion, v = min vert
5213275Sslatteng x p pause (can restart)
5313275Sslatteng x s stop -- done for ever
5413275Sslatteng x t generate trailer
5513275Sslatteng x f n s font position n contains font s
5613275Sslatteng x H n set character height to n
5713275Sslatteng x S n set slant to N
5812587Sslatteng
5912587Sslatteng Subcommands like "i" are often spelled out like "init".
6012587Sslatteng
6112593Sslatteng *******************************************************************************/
6212593Sslatteng
6312593Sslatteng
6412593Sslatteng #include <stdio.h>
6512593Sslatteng #include <ctype.h>
6613275Sslatteng #include <sys/vcmd.h>
6712587Sslatteng #include "dev.h"
6812587Sslatteng
6912587Sslatteng
7015282Sslatteng /* #define DEBUGABLE /* No, not debugable... */
7115282Sslatteng #define DRIVER /* Yes, we're driving directly */
7216538Sslatteng #define NFONTS 65 /* total number of fonts useable */
7313787Sslatteng #define MAXSTATE 6 /* number of environments rememberable */
7413275Sslatteng #define OPENREAD 0 /* mode for openning files */
7513275Sslatteng #define RESTART 1 /* upon exit, return either RESTART */
7613275Sslatteng #define ABORT 2 /* or ABORT */
7713275Sslatteng #define FATAL 1 /* type of error */
7813275Sslatteng #define BMASK 0377 /* byte grabber */
7915735Sslatteng #ifndef FONTDIR
8014759Sslatteng #define FONTDIR "/usr/lib/font" /* default place to find font descriptions */
8115735Sslatteng #endif
8219068Sslatteng #ifndef BITDIR
8314759Sslatteng #define BITDIR "/usr/lib/vfont" /* default place to look for font rasters */
8419068Sslatteng #endif
8513787Sslatteng #define MAXWRIT 4096 /* max characters allowed to write at once */
8612587Sslatteng
8713275Sslatteng #define hmot(n) hpos += n
8813275Sslatteng #define hgoto(n) hpos = n
8914759Sslatteng #define vmot(n) vgoto(vpos + (n))
9012593Sslatteng
9113275Sslatteng
92*24162Sslatteng char SccsId[]= "dver.c 1.17 85/08/05";
9313275Sslatteng
9412587Sslatteng int output = 0; /* do we do output at all? */
9512587Sslatteng int nolist = 0; /* output page list if > 0 */
9612587Sslatteng int olist[20]; /* pairs of page numbers */
9712587Sslatteng struct dev dev;
9813275Sslatteng struct font *fontbase[NFONTS+1];
9914759Sslatteng short * pstab; /* point size table pointer */
10013787Sslatteng int nsizes; /* number of sizes device is capable of printing */
10116538Sslatteng int nfonts = 1; /* number of fonts device is capable of printing */
10216538Sslatteng int nstips = 1; /* number of stipple fonts device can print */
10312587Sslatteng int nchtab;
10414759Sslatteng char * chname;
10514759Sslatteng short * chtab;
10614759Sslatteng char * fitab[NFONTS+1]; /* font inclusion table - maps ascii to ch # */
10714759Sslatteng char * widtab[NFONTS+1]; /* width table for each font */
10814759Sslatteng char * codetab[NFONTS+1]; /* device codes */
10914759Sslatteng char * fontdir = FONTDIR; /* place to find devxxx directories */
11014759Sslatteng char * bitdir = BITDIR; /* place to find raster fonts and fontmap */
11115282Sslatteng char * fontname[NFONTS+1]; /* list of what font is on what position */
11213787Sslatteng struct { /* table of what font */
11314759Sslatteng char fname[3]; /* name maps to what */
11414759Sslatteng char *ffile; /* filename in bitdirectory */
11514759Sslatteng } fontmap[NFONTS+1];
11612587Sslatteng
11713275Sslatteng #ifdef DEBUGABLE
11812587Sslatteng int dbg = 0;
11913275Sslatteng #endif
12014759Sslatteng int size = 1; /* current point size (internal pstable index) */
12114759Sslatteng int font = 1; /* current font - assume reasonable starting font */
12216538Sslatteng int stip = -1; /* current stipple font - none to start with */
12316538Sslatteng int stipmem = 0; /* current member from stipple font to use */
12412593Sslatteng int hpos; /* horizontal position we are to be at next; left = 0 */
12512587Sslatteng int vpos; /* current vertical position (down positive) */
12614759Sslatteng int maxv; /* farthest down the page we've been */
12714759Sslatteng extern linethickness; /* thickness (in pixels) of any drawn object */
12814283Sslatteng extern linmod; /* line style (a bit mask - dotted, etc.) of objects */
12913787Sslatteng int lastw; /* width of last character printed */
13012587Sslatteng
13112587Sslatteng
13213275Sslatteng #define DISPATCHSIZE 256 /* must be a power of two */
13313275Sslatteng #define CHARMASK (DISPATCHSIZE-1)
13413275Sslatteng #define DSIZ ((sizeof *dispatch)*DISPATCHSIZE)
13513275Sslatteng #define OUTFILE fileno (stdout)
13612587Sslatteng
13714759Sslatteng #define RES 200 /* resolution of the device (dots/in) */
13814759Sslatteng #define RASTER_LENGTH 7040 /* device line length */
13913275Sslatteng #define BYTES_PER_LINE (RASTER_LENGTH/8)
14015619Sslatteng #define BAND 1 /* length of a band in inches */
14115282Sslatteng #define NLINES (int)(BAND * RES) /* BAND" long bands */
14213787Sslatteng #define BUFFER_SIZE (NLINES*BYTES_PER_LINE) /* number of chars in picture */
14312587Sslatteng
14414759Sslatteng #define BUFTOP (&buffer[0])
14514759Sslatteng #define BUFBOTTOM (&buffer[BUFFER_SIZE] - 1)
14615282Sslatteng #define buf0p BUFTOP /* vorigin in circular buffer */
14714759Sslatteng #define PAGEEND 1 /* flags to "outband" to tell */
14814759Sslatteng #define OVERBAND 0 /* whether to fill out a page */
14913275Sslatteng
15014759Sslatteng
15113275Sslatteng int pltmode[] = { VPLOT };
15213275Sslatteng int prtmode[] = { VPRINT };
15314759Sslatteng char buffer[BUFFER_SIZE]; /* versatec-wide NLINES buffer */
15414759Sslatteng int vorigin = 0; /* where on the page startbuf maps to */
15514759Sslatteng int pagelen = 0; /* how long the current "page" has printed */
15612587Sslatteng
15714759Sslatteng char * calloc();
15814759Sslatteng char * nalloc();
15914759Sslatteng char * allpanic();
16015282Sslatteng char * operand();
16112587Sslatteng
16213275Sslatteng struct header {
16312587Sslatteng short magic;
16412587Sslatteng unsigned short size;
16512587Sslatteng short maxx;
16612587Sslatteng short maxy;
16712587Sslatteng short xtnd;
16812587Sslatteng } header;
16912587Sslatteng
17012587Sslatteng struct dispatch{
17112587Sslatteng unsigned short addr;
17212587Sslatteng short nbytes;
17312587Sslatteng char up;
17412587Sslatteng char down;
17512587Sslatteng char left;
17612587Sslatteng char right;
17712587Sslatteng short width;
17812587Sslatteng };
17912587Sslatteng
18012587Sslatteng struct fontdes {
18115282Sslatteng int fnum; /* if == -1, this position unused */
18212587Sslatteng int psize;
18312587Sslatteng struct dispatch *disp;
18412587Sslatteng char *bits;
18515282Sslatteng } fontdes[NFONTS+1]; /* is initialized at start of main */
18612587Sslatteng
18712587Sslatteng struct dispatch *dispatch;
18816538Sslatteng struct dispatch *stip_disp;
18912587Sslatteng int cfnum = -1;
19012587Sslatteng int cpsize = 10;
19112587Sslatteng int cfont = 1;
19212587Sslatteng char *bits;
19316538Sslatteng char *stip_bits;
19413275Sslatteng int fontwanted = 1; /* flag: "has a new font been requested?" */
19512587Sslatteng int nfontnum = -1;
19612587Sslatteng int npsize = 10;
19712587Sslatteng
19813275Sslatteng
19912587Sslatteng
main(argc,argv)20012587Sslatteng main(argc, argv)
20112587Sslatteng char *argv[];
20212587Sslatteng {
20315282Sslatteng register FILE *fp;
20415282Sslatteng register int i;
20512587Sslatteng
20615282Sslatteng for (i = 0; i <= NFONTS; fontdes[i++].fnum = -1);
20715282Sslatteng while (--argc > 0 && **++argv == '-') {
20815282Sslatteng switch ((*argv)[1]) {
20912587Sslatteng case 'F':
21015282Sslatteng bitdir = operand(&argc, &argv);
21112587Sslatteng break;
21214759Sslatteng case 'f':
21315282Sslatteng fontdir = operand(&argc, &argv);
21414759Sslatteng break;
21512587Sslatteng case 'o':
21615282Sslatteng outlist(operand(&argc, &argv));
21712587Sslatteng break;
21813275Sslatteng #ifdef DEBUGABLE
21912587Sslatteng case 'd':
22015282Sslatteng dbg = atoi(operand(&argc, &argv));
22112587Sslatteng if (dbg == 0) dbg = 1;
22212587Sslatteng break;
22313275Sslatteng #endif
22412587Sslatteng }
22512587Sslatteng }
22615282Sslatteng #ifdef DRIVER
22715282Sslatteng ioctl(OUTFILE, VSETSTATE, pltmode);
22815282Sslatteng #endif
22912587Sslatteng
23015282Sslatteng if (argc < 1)
23112587Sslatteng conv(stdin);
23212587Sslatteng else
23315282Sslatteng while (argc-- > 0) {
23415282Sslatteng if (strcmp(*argv, "-") == 0)
23512587Sslatteng fp = stdin;
23612587Sslatteng else if ((fp = fopen(*argv, "r")) == NULL)
23712587Sslatteng error(FATAL, "can't open %s", *argv);
23812587Sslatteng conv(fp);
23912587Sslatteng fclose(fp);
24015282Sslatteng argv++;
24112587Sslatteng }
24212587Sslatteng exit(0);
24312587Sslatteng }
24412587Sslatteng
24515282Sslatteng
24615282Sslatteng /*----------------------------------------------------------------------------*
24715282Sslatteng | Routine: char * operand (& argc, & argv)
24815282Sslatteng |
24915282Sslatteng | Results: returns address of the operand given with a command-line
25015282Sslatteng | option. It uses either "-Xoperand" or "-X operand", whichever
25115282Sslatteng | is present. The program is terminated if no option is present.
25215282Sslatteng |
25315282Sslatteng | Side Efct: argc and argv are updated as necessary.
25415282Sslatteng *----------------------------------------------------------------------------*/
25515282Sslatteng
operand(argcp,argvp)25615282Sslatteng char *operand(argcp, argvp)
25715282Sslatteng int * argcp;
25815282Sslatteng char ***argvp;
25915282Sslatteng {
26015282Sslatteng if ((**argvp)[2]) return(**argvp + 2); /* operand immediately follows */
26115282Sslatteng if ((--*argcp) <= 0) { /* no operand */
26215282Sslatteng error (FATAL, "command-line option operand missing.");
26315282Sslatteng }
26415282Sslatteng return(*(++(*argvp))); /* operand next word */
26515282Sslatteng }
26615282Sslatteng
26715282Sslatteng
outlist(s)26812587Sslatteng outlist(s) /* process list of page numbers to be printed */
26912587Sslatteng char *s;
27012587Sslatteng {
27115282Sslatteng int n1, n2;
27215282Sslatteng #ifdef DEBUGABLE
27315282Sslatteng int i;
27415282Sslatteng #endif
27512587Sslatteng
27612587Sslatteng nolist = 0;
27712587Sslatteng while (*s) {
27812587Sslatteng n1 = 0;
27912587Sslatteng if (isdigit(*s))
28012587Sslatteng do
28112587Sslatteng n1 = 10 * n1 + *s++ - '0';
28212587Sslatteng while (isdigit(*s));
28312587Sslatteng else
28412587Sslatteng n1 = -9999;
28512587Sslatteng n2 = n1;
28612587Sslatteng if (*s == '-') {
28712587Sslatteng s++;
28812587Sslatteng n2 = 0;
28912587Sslatteng if (isdigit(*s))
29012587Sslatteng do
29112587Sslatteng n2 = 10 * n2 + *s++ - '0';
29212587Sslatteng while (isdigit(*s));
29312587Sslatteng else
29412587Sslatteng n2 = 9999;
29512587Sslatteng }
29612587Sslatteng olist[nolist++] = n1;
29712587Sslatteng olist[nolist++] = n2;
29812587Sslatteng if (*s != '\0')
29912587Sslatteng s++;
30012587Sslatteng }
30112587Sslatteng olist[nolist] = 0;
30213275Sslatteng #ifdef DEBUGABLE
30312587Sslatteng if (dbg)
30412587Sslatteng for (i=0; i<nolist; i += 2)
30512587Sslatteng fprintf(stderr,"%3d %3d\n", olist[i], olist[i+1]);
30613275Sslatteng #endif
30712587Sslatteng }
30812587Sslatteng
conv(fp)30912587Sslatteng conv(fp)
31012587Sslatteng register FILE *fp;
31112587Sslatteng {
31212587Sslatteng register int c, k;
31312587Sslatteng int m, n, n1, m1;
31412587Sslatteng char str[100], buf[300];
31512587Sslatteng
31612587Sslatteng while ((c = getc(fp)) != EOF) {
31712587Sslatteng switch (c) {
31812587Sslatteng case '\n': /* when input is text */
31916196Sslatteng case 0: /* occasional noise creeps in */
32016196Sslatteng case '\t':
32112587Sslatteng case ' ':
32212587Sslatteng break;
32312587Sslatteng case '{': /* push down current environment */
32412587Sslatteng t_push();
32512587Sslatteng break;
32612587Sslatteng case '}':
32712587Sslatteng t_pop();
32812587Sslatteng break;
32912587Sslatteng case '0': case '1': case '2': case '3': case '4':
33012587Sslatteng case '5': case '6': case '7': case '8': case '9':
33112587Sslatteng /* two motion digits plus a character */
33212587Sslatteng hmot((c-'0')*10 + getc(fp)-'0');
33312587Sslatteng put1(getc(fp));
33412587Sslatteng break;
33512587Sslatteng case 'c': /* single ascii character */
33612587Sslatteng put1(getc(fp));
33712587Sslatteng break;
33812587Sslatteng case 'C':
33912587Sslatteng fscanf(fp, "%s", str);
34012587Sslatteng put1s(str);
34112587Sslatteng break;
34212587Sslatteng case 't': /* straight text */
34316196Sslatteng if (fgets(buf, sizeof(buf), fp) == NULL)
34416196Sslatteng error(FATAL, "unexpected end of input");
34512587Sslatteng t_text(buf);
34612587Sslatteng break;
34712587Sslatteng case 'D': /* draw function */
34816196Sslatteng if (fgets(buf, sizeof(buf), fp) == NULL)
34916196Sslatteng error(FATAL, "unexpected end of input");
35012587Sslatteng switch (buf[0]) {
35112587Sslatteng case 'l': /* draw a line */
35212593Sslatteng sscanf(buf+1, "%d %d", &n, &m);
35313787Sslatteng drawline(n, m);
35412593Sslatteng break;
35512587Sslatteng case 'c': /* circle */
35612593Sslatteng sscanf(buf+1, "%d", &n);
35712593Sslatteng drawcirc(n);
35812593Sslatteng break;
35912587Sslatteng case 'e': /* ellipse */
36012593Sslatteng sscanf(buf+1, "%d %d", &m, &n);
36112593Sslatteng drawellip(m, n);
36212593Sslatteng break;
36312587Sslatteng case 'a': /* arc */
36412593Sslatteng sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1);
36512593Sslatteng drawarc(n, m, n1, m1);
36612593Sslatteng break;
36716538Sslatteng case 'q': /* polygon */
36816538Sslatteng n = 1; /* get stipple */
36916538Sslatteng while (isspace(buf[++n])); /* number first */
37016538Sslatteng setfill(atoi(&(buf[n]))); /* set up stipple */
37116538Sslatteng while (isdigit(buf[++n]));
37216538Sslatteng polygon(&(buf[n]), fp); /* draw polygon */
37316538Sslatteng break;
37412587Sslatteng case '~': /* wiggly line */
37513889Sslatteng case 'g': /* gremlin spline */
37613889Sslatteng drawwig(buf+1, fp, buf[0] == '~');
37712593Sslatteng break;
37813889Sslatteng case 't': /* line thickness */
37913889Sslatteng sscanf(buf+1, "%d", &n);
38013889Sslatteng drawthick(n);
38113889Sslatteng break;
38213889Sslatteng case 's': /* line style */
38313889Sslatteng sscanf(buf+1, "%d", &n);
38413889Sslatteng drawstyle(n);
38513889Sslatteng break;
38612587Sslatteng default:
38714759Sslatteng error(FATAL, "unknown drawing function %s", buf);
38812593Sslatteng break;
38912587Sslatteng }
39012587Sslatteng break;
39112587Sslatteng case 's':
39216196Sslatteng fscanf(fp, "%d", &n);
39312587Sslatteng setsize(t_size(n));
39412587Sslatteng break;
39516538Sslatteng case 'i':
39616538Sslatteng fscanf(fp, "%d", &n);
39716538Sslatteng setstip(n);
39816538Sslatteng break;
39912587Sslatteng case 'f':
40012587Sslatteng fscanf(fp, "%s", str);
40112587Sslatteng setfont(t_font(str));
40212587Sslatteng break;
40312587Sslatteng case 'H': /* absolute horizontal motion */
40412587Sslatteng while ((c = getc(fp)) == ' ')
40512587Sslatteng ;
40612587Sslatteng k = 0;
40712587Sslatteng do {
40812587Sslatteng k = 10 * k + c - '0';
40912587Sslatteng } while (isdigit(c = getc(fp)));
41012587Sslatteng ungetc(c, fp);
41112587Sslatteng hgoto(k);
41212587Sslatteng break;
41312587Sslatteng case 'h': /* relative horizontal motion */
41412587Sslatteng while ((c = getc(fp)) == ' ')
41512587Sslatteng ;
41612587Sslatteng k = 0;
41712587Sslatteng do {
41812587Sslatteng k = 10 * k + c - '0';
41912587Sslatteng } while (isdigit(c = getc(fp)));
42012587Sslatteng ungetc(c, fp);
42112587Sslatteng hmot(k);
42212587Sslatteng break;
42312587Sslatteng case 'w': /* word space */
42412587Sslatteng break;
42512587Sslatteng case 'V':
42612587Sslatteng fscanf(fp, "%d", &n);
42712587Sslatteng vgoto(n);
42812587Sslatteng break;
42912587Sslatteng case 'v':
43012587Sslatteng fscanf(fp, "%d", &n);
43112587Sslatteng vmot(n);
43212587Sslatteng break;
43314759Sslatteng case 'P': /* new spread */
43415282Sslatteng if (output) outband(OVERBAND);
43514759Sslatteng break;
43612587Sslatteng case 'p': /* new page */
43712587Sslatteng fscanf(fp, "%d", &n);
43812587Sslatteng t_page(n);
43912587Sslatteng break;
44012587Sslatteng case 'n': /* end of line */
44112587Sslatteng t_newline();
44216196Sslatteng
44312587Sslatteng case '#': /* comment */
44416196Sslatteng do
44516196Sslatteng c = getc(fp);
44616196Sslatteng while (c != '\n' && c != EOF);
44712587Sslatteng break;
44812587Sslatteng case 'x': /* device control */
44915619Sslatteng if (devcntrl(fp)) return;
45012587Sslatteng break;
45112587Sslatteng default:
45214759Sslatteng error(FATAL, "unknown input character %o %c", c, c);
45312587Sslatteng }
45412587Sslatteng }
45512587Sslatteng }
45612587Sslatteng
devcntrl(fp)45715619Sslatteng int devcntrl(fp) /* interpret device control functions */
45815619Sslatteng FILE *fp; /* returns -1 apon recieving "stop" command */
45912587Sslatteng {
46012587Sslatteng char str[20], str1[50], buf[50];
46112587Sslatteng int c, n;
46212587Sslatteng
46312587Sslatteng fscanf(fp, "%s", str);
46412587Sslatteng switch (str[0]) { /* crude for now */
46512587Sslatteng case 'i': /* initialize */
46612587Sslatteng fileinit();
46713787Sslatteng t_init();
46812587Sslatteng break;
46912587Sslatteng case 't': /* trailer */
47012587Sslatteng break;
47112587Sslatteng case 'p': /* pause -- can restart */
47212587Sslatteng t_reset('p');
47312587Sslatteng break;
47412587Sslatteng case 's': /* stop */
47512587Sslatteng t_reset('s');
47615619Sslatteng return -1;
47712587Sslatteng case 'r': /* resolution assumed when prepared */
47814759Sslatteng fscanf(fp, "%d", &n);
47916538Sslatteng if (n!=RES) error(FATAL,"Input computed for wrong printer");
48012587Sslatteng break;
48112587Sslatteng case 'f': /* font used */
48212587Sslatteng fscanf(fp, "%d %s", &n, str);
48315282Sslatteng (void) fgets(buf, sizeof buf, fp); /* in case of filename */
48412593Sslatteng ungetc('\n', fp); /* fgets goes too far */
48512593Sslatteng str1[0] = 0; /* in case nothing comes in */
48612587Sslatteng sscanf(buf, "%s", str1);
48712587Sslatteng loadfont(n, str, str1);
48812587Sslatteng break;
48912593Sslatteng /* these don't belong here... */
49012587Sslatteng case 'H': /* char height */
49112587Sslatteng fscanf(fp, "%d", &n);
49212587Sslatteng t_charht(n);
49312587Sslatteng break;
49412587Sslatteng case 'S': /* slant */
49512587Sslatteng fscanf(fp, "%d", &n);
49612587Sslatteng t_slant(n);
49712587Sslatteng break;
49812587Sslatteng }
49912587Sslatteng while ((c = getc(fp)) != '\n') /* skip rest of input line */
50012587Sslatteng if (c == EOF)
50115619Sslatteng return -1;
50215619Sslatteng return 0;
50312587Sslatteng }
50412587Sslatteng
50512593Sslatteng /* fileinit: read in font and code files, etc.
50612593Sslatteng Must open table for device, read in resolution,
50714759Sslatteng size info, font info, etc. and set params.
50814759Sslatteng Also read in font name mapping.
50912593Sslatteng */
fileinit()51012593Sslatteng fileinit()
51112587Sslatteng {
51214759Sslatteng register int i;
51314759Sslatteng register int fin;
51414759Sslatteng register int nw;
51514759Sslatteng register char *filebase;
51614759Sslatteng register char *p;
51714759Sslatteng register FILE *fp;
51814759Sslatteng char temp[100];
51912587Sslatteng
52014759Sslatteng
52114759Sslatteng /* first, read in font map file. The file must be of Format:
52214759Sslatteng XX FILENAME (XX = troff font name)
52314759Sslatteng with one entry per text line of the file.
52414759Sslatteng Extra stuff after FILENAME is ignored */
52514759Sslatteng
52614759Sslatteng sprintf(temp, "%s/fontmap", bitdir);
52714759Sslatteng if ((fp = fopen(temp, "r")) == NULL)
52814759Sslatteng error(FATAL, "Can't open %s", temp);
52914759Sslatteng for (i = 0; i <= NFONTS && fgets(temp, 100, fp) != NULL; i++) {
53014759Sslatteng sscanf(temp, "%2s", fontmap[i].fname);
53114759Sslatteng p = &temp[0];
53214759Sslatteng while (*p != ' ' && *p != ' ') p++;
53314759Sslatteng while (*p == ' ' || *p == ' ') p++;
53414759Sslatteng filebase = p;
53514759Sslatteng for (nw = 1; *p != '\n' && *p != ' ' && *p != '\t'; p++) nw++;
53614759Sslatteng fontmap[i].ffile = nalloc(1, nw);
53714759Sslatteng sscanf(filebase, "%s", fontmap[i].ffile);
53814759Sslatteng }
53914759Sslatteng fontmap[++i].fname[0] = '0'; /* finish off with zeros */
54014759Sslatteng fontmap[i].ffile = (char *) 0;
54114759Sslatteng fclose(fp);
54214759Sslatteng #ifdef DEBUGABLE
54314759Sslatteng if(dbg) {
54414759Sslatteng fprintf(stderr, "font map:\n");
54514759Sslatteng for (i = 0; fontmap[i].ffile; i++)
54614759Sslatteng fprintf(stderr,"%s = %s\n", fontmap[i].fname, fontmap[i].ffile);
54714759Sslatteng }
54814759Sslatteng #endif
54914759Sslatteng
55014759Sslatteng
55115282Sslatteng sprintf(temp, "%s/devvp/DESC.out", fontdir);
55212587Sslatteng if ((fin = open(temp, 0)) < 0)
55314759Sslatteng error(FATAL, "can't open tables for %s", temp);
55415282Sslatteng if (read(fin, &dev, sizeof(struct dev)) != sizeof(struct dev))
55515282Sslatteng error(FATAL, "can't read header for %s", temp);
55612587Sslatteng nfonts = dev.nfonts;
55712587Sslatteng nsizes = dev.nsizes;
55816538Sslatteng nstips = dev.nstips;
55912587Sslatteng nchtab = dev.nchtab;
56014759Sslatteng filebase = calloc(1, dev.filesize); /* enough room for whole file */
56115282Sslatteng if (read(fin, filebase, dev.filesize) != dev.filesize) /* at once */
56215282Sslatteng error(FATAL, "can't read width table for %s", temp);
56312587Sslatteng pstab = (short *) filebase;
56412587Sslatteng chtab = pstab + nsizes + 1;
56512587Sslatteng chname = (char *) (chtab + dev.nchtab);
56612587Sslatteng p = chname + dev.lchname;
56712587Sslatteng for (i = 1; i <= nfonts; i++) {
56812587Sslatteng fontbase[i] = (struct font *) p;
56912593Sslatteng nw = *p & BMASK; /* 1st thing is width count */
57015282Sslatteng p += sizeof(struct font);
57113275Sslatteng widtab[i] = p;
57212587Sslatteng codetab[i] = p + 2 * nw;
57312587Sslatteng fitab[i] = p + 3 * nw;
57412587Sslatteng p += 3 * nw + dev.nchtab + 128 - 32;
57512587Sslatteng t_fp(i, fontbase[i]->namefont, fontbase[i]->intname);
57613275Sslatteng #ifdef DEBUGABLE
57713275Sslatteng if (dbg > 1) fontprint(i);
57813275Sslatteng #endif
57912587Sslatteng }
58016538Sslatteng for (i = 1; i <= nstips; i++) { /* add in stipple "filenames" */
58116538Sslatteng if (nfonts + i <= NFONTS)
58216538Sslatteng t_fp(nfonts + i, p, (char *)0);
58316538Sslatteng p += strlen(p) + 1;
58416538Sslatteng }
58512593Sslatteng fontbase[0] = (struct font *)
58612593Sslatteng calloc(1,3*255 + dev.nchtab + (128-32) + sizeof (struct font));
58713275Sslatteng widtab[0] = (char *) fontbase[0] + sizeof (struct font);
58812587Sslatteng fontbase[0]->nwfont = 255;
58912587Sslatteng close(fin);
59012587Sslatteng }
59112587Sslatteng
59215282Sslatteng #ifdef DEBUGABLE
fontprint(i)59312587Sslatteng fontprint(i) /* debugging print of font i (0,...) */
59412587Sslatteng {
59512587Sslatteng int j, n;
59612587Sslatteng char *p;
59712587Sslatteng
59812587Sslatteng fprintf(stderr,"font %d:\n", i);
59912587Sslatteng p = (char *) fontbase[i];
60012587Sslatteng n = fontbase[i]->nwfont & BMASK;
60112593Sslatteng fprintf(stderr,
60212593Sslatteng "base=0%o, nchars=%d, spec=%d, name=%s, widtab=0%o, fitab=0%o\n",p,
60313275Sslatteng n,fontbase[i]->specfont,fontbase[i]->namefont,widtab[i],fitab[i]);
60412587Sslatteng fprintf(stderr,"widths:\n");
60512587Sslatteng for (j=0; j <= n; j++) {
60613275Sslatteng fprintf(stderr," %2d", widtab[i][j] & BMASK);
60712587Sslatteng if (j % 20 == 19) fprintf(stderr,"\n");
60812587Sslatteng }
60912587Sslatteng fprintf(stderr,"\ncodetab:\n");
61012587Sslatteng for (j=0; j <= n; j++) {
61112587Sslatteng fprintf(stderr," %2d", codetab[i][j] & BMASK);
61212587Sslatteng if (j % 20 == 19) fprintf(stderr,"\n");
61312587Sslatteng }
61412587Sslatteng fprintf(stderr,"\nfitab:\n");
61512587Sslatteng for (j=0; j <= dev.nchtab + 128-32; j++) {
61612587Sslatteng fprintf(stderr," %2d", fitab[i][j] & BMASK);
61712587Sslatteng if (j % 20 == 19) fprintf(stderr,"\n");
61812587Sslatteng }
61912587Sslatteng fprintf(stderr,"\n");
62012587Sslatteng }
62115282Sslatteng #endif
62212587Sslatteng
62314759Sslatteng
loadfont(n,s,s1)62412587Sslatteng loadfont(n, s, s1) /* load font info for font s on position n (0...) */
62512587Sslatteng int n;
62612587Sslatteng char *s, *s1;
62712587Sslatteng {
62812587Sslatteng char temp[60];
62915619Sslatteng register int fin;
63015619Sslatteng register int nw;
63115619Sslatteng register int norig;
63212587Sslatteng
63313275Sslatteng if (n < 0 || n > NFONTS)
63412587Sslatteng error(FATAL, "illegal fp command %d %s", n, s);
63512587Sslatteng if (strcmp(s, fontbase[n]->namefont) == 0)
63612587Sslatteng return;
63715619Sslatteng
63815619Sslatteng for (fin = 1; fin <= NFONTS; fin++) /* first check to see if the */
63915619Sslatteng if (strcmp(s, fontbase[fin]->namefont) == 0) { /* font is loaded */
64015619Sslatteng register char *c; /* somewhere else */
64115619Sslatteng
64215619Sslatteng #define ptrswap(x, y) { c = (char*) (x); x = y; y = c; }
64316099Sslatteng #define ptrfswap(x, y) { c = (char*) (x); x = y; y = (struct font *)c; }
64415619Sslatteng
64516099Sslatteng ptrfswap(fontbase[n], fontbase[fin]);
64615619Sslatteng ptrswap(codetab[n], codetab[fin]);
64715619Sslatteng ptrswap(widtab[n], widtab[fin]);
64815619Sslatteng ptrswap(fitab[n], fitab[fin]);
64915619Sslatteng t_fp(n, fontbase[n]->namefont, fontbase[n]->intname);
65015619Sslatteng t_fp(fin, fontbase[fin]->namefont, fontbase[fin]->intname);
65115619Sslatteng return;
65215619Sslatteng }
65315619Sslatteng
65412587Sslatteng if (s1 == NULL || s1[0] == '\0')
65515282Sslatteng sprintf(temp, "%s/devvp/%s.out", fontdir, s);
65612587Sslatteng else
65712587Sslatteng sprintf(temp, "%s/%s.out", s1, s);
65812587Sslatteng if ((fin = open(temp, 0)) < 0)
65912587Sslatteng error(FATAL, "can't open font table %s", temp);
66012587Sslatteng norig = fontbase[n]->nwfont & BMASK;
66115282Sslatteng if (read(fin,fontbase[n],3*norig+nchtab+128-32+sizeof(struct font)) < 0)
66215282Sslatteng error(FATAL, "Can't read in font %s on position %d", s, n);
66312587Sslatteng if ((fontbase[n]->nwfont & BMASK) > norig)
66414759Sslatteng error(FATAL, "Font %s too big for position %d", s, n);
66512587Sslatteng close(fin);
66612587Sslatteng nw = fontbase[n]->nwfont & BMASK;
66713275Sslatteng widtab[n] = (char *) fontbase[n] + sizeof(struct font);
66813275Sslatteng codetab[n] = (char *) widtab[n] + 2 * nw;
66913275Sslatteng fitab[n] = (char *) widtab[n] + 3 * nw;
67012587Sslatteng t_fp(n, fontbase[n]->namefont, fontbase[n]->intname);
67112593Sslatteng fontbase[n]->nwfont = norig; /* to later use full original size */
67213275Sslatteng #ifdef DEBUGABLE
67312587Sslatteng if (dbg > 1) fontprint(n);
67413275Sslatteng #endif
67512587Sslatteng }
67612587Sslatteng
67714759Sslatteng
67812587Sslatteng /*VARARGS1*/
error(f,s,a1,a2,a3,a4,a5,a6,a7)67912587Sslatteng error(f, s, a1, a2, a3, a4, a5, a6, a7) {
68012587Sslatteng fprintf(stderr, "dver: ");
68112587Sslatteng fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7);
68212587Sslatteng fprintf(stderr, "\n");
68315282Sslatteng if (f) exit(ABORT);
68412587Sslatteng }
68512587Sslatteng
68612587Sslatteng
t_init()68713787Sslatteng t_init() /* initialize device */
68812587Sslatteng {
68915282Sslatteng vorigin = pagelen = maxv = hpos = vpos = 0;
69012587Sslatteng
69115282Sslatteng output = 0; /* don't output anything yet */
69212587Sslatteng setsize(t_size(10)); /* start somewhere */
69312587Sslatteng setfont(1);
69412587Sslatteng }
69512587Sslatteng
69612587Sslatteng
69712587Sslatteng struct state {
69812587Sslatteng int ssize;
69912587Sslatteng int sfont;
70012587Sslatteng int shpos;
70112587Sslatteng int svpos;
70214283Sslatteng int sstyle;
70314283Sslatteng int sthick;
70412587Sslatteng };
70512587Sslatteng struct state state[MAXSTATE];
70612587Sslatteng struct state *statep = state;
70712587Sslatteng
t_push()70812587Sslatteng t_push() /* begin a new block */
70912587Sslatteng {
71012587Sslatteng statep->ssize = size;
71112587Sslatteng statep->sfont = font;
71214283Sslatteng statep->sstyle = linmod;
71314283Sslatteng statep->sthick = linethickness;
71412587Sslatteng statep->shpos = hpos;
71512587Sslatteng statep->svpos = vpos;
71612587Sslatteng if (statep++ >= state+MAXSTATE)
71712587Sslatteng error(FATAL, "{ nested too deep");
71812587Sslatteng }
71912587Sslatteng
t_pop()72012587Sslatteng t_pop() /* pop to previous state */
72112587Sslatteng {
72212587Sslatteng if (--statep < state)
72312587Sslatteng error(FATAL, "extra }");
72412587Sslatteng size = statep->ssize;
72512587Sslatteng font = statep->sfont;
72612587Sslatteng hpos = statep->shpos;
72712587Sslatteng vpos = statep->svpos;
72814283Sslatteng linmod = statep->sstyle;
72914283Sslatteng linethickness = statep->sthick;
73012587Sslatteng }
73112587Sslatteng
73214759Sslatteng
t_page(n)73312587Sslatteng t_page(n) /* do whatever new page functions */
73412587Sslatteng {
73512587Sslatteng int i;
73612587Sslatteng
73712587Sslatteng
73815282Sslatteng if (output) outband(PAGEEND);
73915282Sslatteng
74014759Sslatteng maxv = vpos = 0;
74112587Sslatteng
74212587Sslatteng output = 1;
74312587Sslatteng if (nolist == 0)
74414759Sslatteng return; /* no -o specified */
74512587Sslatteng output = 0;
74612587Sslatteng for (i = 0; i < nolist; i += 2)
74712587Sslatteng if (n >= olist[i] && n <= olist[i+1]) {
74812587Sslatteng output = 1;
74912587Sslatteng break;
75012587Sslatteng }
75112587Sslatteng }
75212587Sslatteng
75314759Sslatteng
outband(page)75414759Sslatteng outband(page)
75514759Sslatteng int page;
75614759Sslatteng {
75714759Sslatteng register int outsize;
75814759Sslatteng
75915282Sslatteng if (page == PAGEEND) { /* set outsize to inch boundary */
76016196Sslatteng outsize = (maxv + (RES - 2) - pagelen) / RES;
76115619Sslatteng vorigin = pagelen = 0; /* reset for new page */
76215282Sslatteng if (outsize < 1) return; /* if outsize <= zero, forget it */
76315282Sslatteng
76416196Sslatteng outsize *= RES * BYTES_PER_LINE;
76516196Sslatteng vwrite(buf0p, outsize > BUFFER_SIZE ? BUFFER_SIZE : outsize);
76616196Sslatteng vclear(buf0p, BUFFER_SIZE);
76716196Sslatteng while ((outsize -= BUFFER_SIZE) > 0)
76816196Sslatteng vwrite(buf0p, outsize > BUFFER_SIZE ? BUFFER_SIZE : outsize);
76916196Sslatteng } else {
77014759Sslatteng vorigin += NLINES;
77114759Sslatteng pagelen += NLINES;
77214759Sslatteng vwrite(buf0p, BUFFER_SIZE);
77314759Sslatteng vclear(buf0p, BUFFER_SIZE);
77414759Sslatteng }
77514759Sslatteng }
77614759Sslatteng
77714759Sslatteng
t_newline()77812587Sslatteng t_newline() /* do whatever for the end of a line */
77912587Sslatteng {
78012587Sslatteng hpos = 0; /* because we're now back at the left margin */
78112587Sslatteng }
78212587Sslatteng
t_size(n)78312587Sslatteng t_size(n) /* convert integer to internal size number*/
78412587Sslatteng int n;
78512587Sslatteng {
78612587Sslatteng int i;
78712587Sslatteng
78812587Sslatteng if (n <= pstab[0])
78914759Sslatteng return(0);
79014759Sslatteng else if (n >= pstab[nsizes - 1])
79114759Sslatteng return(nsizes - 1);
79212587Sslatteng for (i = 0; n > pstab[i]; i++)
79312587Sslatteng ;
79414759Sslatteng return(i);
79512587Sslatteng }
79612587Sslatteng
79715282Sslatteng /*ARGSUSED*/
t_charht(n)79812587Sslatteng t_charht(n) /* set character height to n */
79912587Sslatteng int n;
80012587Sslatteng {
80113275Sslatteng #ifdef DEBUGABLE
80214759Sslatteng if (dbg) error(!FATAL, "can't set height on versatec");
80313275Sslatteng #endif
80412587Sslatteng }
80512587Sslatteng
80615282Sslatteng /*ARGSUSED*/
t_slant(n)80712587Sslatteng t_slant(n) /* set slant to n */
80812587Sslatteng int n;
80912587Sslatteng {
81013275Sslatteng #ifdef DEBUGABLE
81114759Sslatteng if (dbg) error(!FATAL, "can't set slant on versatec");
81213275Sslatteng #endif
81312587Sslatteng }
81412587Sslatteng
t_font(s)81512587Sslatteng t_font(s) /* convert string to internal font number */
81612587Sslatteng char *s;
81712587Sslatteng {
81812587Sslatteng int n;
81912587Sslatteng
82012587Sslatteng n = atoi(s);
82112587Sslatteng if (n < 0 || n > nfonts)
82212587Sslatteng n = 1;
82312587Sslatteng return(n);
82412587Sslatteng }
82512587Sslatteng
t_text(s)82612587Sslatteng t_text(s) /* print string s as text */
82712587Sslatteng char *s;
82812587Sslatteng {
82912587Sslatteng int c;
83012587Sslatteng char str[100];
83112587Sslatteng
83212587Sslatteng if (!output)
83312587Sslatteng return;
83412587Sslatteng while (c = *s++) {
83512587Sslatteng if (c == '\\') {
83612587Sslatteng switch (c = *s++) {
83712587Sslatteng case '\\':
83812587Sslatteng case 'e':
83912587Sslatteng put1('\\');
84012587Sslatteng break;
84112587Sslatteng case '(':
84212587Sslatteng str[0] = *s++;
84312587Sslatteng str[1] = *s++;
84412587Sslatteng str[2] = '\0';
84512587Sslatteng put1s(str);
84612587Sslatteng break;
84712587Sslatteng }
84812587Sslatteng } else {
84912587Sslatteng put1(c);
85012587Sslatteng }
85112587Sslatteng hmot(lastw);
85213275Sslatteng #ifdef DEBUGABLE
85312587Sslatteng if (dbg) fprintf(stderr,"width = %d\n", lastw);
85413275Sslatteng #endif
85512587Sslatteng }
85612587Sslatteng }
85712587Sslatteng
85814759Sslatteng
t_reset(c)85912587Sslatteng t_reset(c)
86012587Sslatteng {
86112587Sslatteng switch(c){
86212587Sslatteng case 's':
86315282Sslatteng t_page(0);
86415282Sslatteng #ifdef DRIVER
86515282Sslatteng ioctl(OUTFILE, VSETSTATE, prtmode);
86615282Sslatteng #endif
86714759Sslatteng break;
86812587Sslatteng }
86912587Sslatteng }
87012587Sslatteng
87112587Sslatteng
vgoto(n)87214759Sslatteng vgoto (n)
87314759Sslatteng int n;
87412587Sslatteng {
87514759Sslatteng vpos = n;
87612587Sslatteng }
87712587Sslatteng
87812587Sslatteng
put1s(s)87912587Sslatteng put1s(s) /* s is a funny char name */
88012587Sslatteng char *s;
88112587Sslatteng {
88212587Sslatteng int i;
88312587Sslatteng
88412587Sslatteng if (!output)
88512587Sslatteng return;
88613275Sslatteng #ifdef DEBUGABLE
88712587Sslatteng if (dbg) fprintf(stderr,"%s ", s);
88813275Sslatteng #endif
88912587Sslatteng for (i = 0; i < nchtab; i++)
89012587Sslatteng if (strcmp(&chname[chtab[i]], s) == 0)
89112587Sslatteng break;
89212587Sslatteng if (i < nchtab)
89312587Sslatteng put1(i + 128);
89412587Sslatteng }
89512587Sslatteng
put1(c)89612587Sslatteng put1(c) /* output char c */
89712587Sslatteng int c;
89812587Sslatteng {
89912587Sslatteng char *pw;
90012587Sslatteng register char *p;
90112587Sslatteng register int i, k;
90212587Sslatteng int j, ofont, code;
90312587Sslatteng
90412587Sslatteng if (!output)
90512587Sslatteng return;
90612587Sslatteng c -= 32;
90712587Sslatteng if (c <= 0) {
90813275Sslatteng #ifdef DEBUGABLE
90912587Sslatteng if (dbg) fprintf(stderr,"non-exist 0%o\n", c + 32);
91013275Sslatteng #endif
91114759Sslatteng lastw = (widtab[font][0] * pstab[size] + dev.unitwidth/2)
91213787Sslatteng / dev.unitwidth;
91312587Sslatteng return;
91412587Sslatteng }
91512587Sslatteng k = ofont = font;
91612587Sslatteng i = fitab[font][c] & BMASK;
91713787Sslatteng if (i != 0) { /* it's on this font */
91813787Sslatteng p = codetab[font]; /* get the printing value of ch */
91913787Sslatteng pw = widtab[font]; /* get the width */
92015282Sslatteng } else /* on another font (we hope) */
92116099Sslatteng for (j=0; j <= nfonts; j++, k = (k+1) % (nfonts+1)){
92213275Sslatteng if (fitab[k] == 0)
92312587Sslatteng continue;
92412587Sslatteng if ((i = fitab[k][c] & BMASK) != 0) {
92512587Sslatteng p = codetab[k];
92613275Sslatteng pw = widtab[k];
92712587Sslatteng setfont(k);
92812587Sslatteng break;
92912587Sslatteng }
93012587Sslatteng }
93115282Sslatteng
93216099Sslatteng if (i == 0) {
93313275Sslatteng #ifdef DEBUGABLE
93412587Sslatteng if (dbg) fprintf(stderr,"not found 0%o\n", c+32);
93513275Sslatteng #endif
93612587Sslatteng return;
93712587Sslatteng }
93816099Sslatteng code = p[i] & BMASK;
93913275Sslatteng #ifdef DEBUGABLE
94012587Sslatteng if (dbg) {
94112587Sslatteng if (isprint(c+32))
94212587Sslatteng fprintf(stderr,"%c %d\n", c+32, code);
94312587Sslatteng else
94412587Sslatteng fprintf(stderr,"%03o %d\n", c+32, code);
94513275Sslatteng }
94613275Sslatteng #endif
94713275Sslatteng outc(code); /* character is < 254 */
94812587Sslatteng if (font != ofont)
94912587Sslatteng setfont(ofont);
95014759Sslatteng lastw = ((pw[i]&077) * pstab[size] + dev.unitwidth/2) / dev.unitwidth;
95112587Sslatteng }
95212587Sslatteng
95312587Sslatteng
95412587Sslatteng
setsize(n)95512587Sslatteng setsize(n) /* set point size to n (internal) */
95612587Sslatteng int n;
95712587Sslatteng {
95812587Sslatteng
95912587Sslatteng if (n == size)
96012587Sslatteng return; /* already there */
96114759Sslatteng if (vloadfont(font, pstab[n]) != -1)
96212587Sslatteng size = n;
96312587Sslatteng }
96412587Sslatteng
96515282Sslatteng /*ARGSUSED*/
t_fp(n,s,si)96612587Sslatteng t_fp(n, s, si) /* font position n now contains font s, intname si */
96715282Sslatteng int n; /* internal name is ignored */
96812587Sslatteng char *s, *si;
96912587Sslatteng {
97014759Sslatteng register int i;
97112587Sslatteng
97214759Sslatteng /* first convert s to filename if possible */
97314759Sslatteng for (i = 0; fontmap[i].ffile != (char *) 0; i++) {
97414759Sslatteng #ifdef DEBUGABLE
97514759Sslatteng if(dbg>1)fprintf(stderr,"testing :%s:%s:\n",s,fontmap[i].fname);
97614759Sslatteng #endif
97714759Sslatteng if (strcmp(s, fontmap[i].fname) == 0) {
97814759Sslatteng s = fontmap[i].ffile;
97914759Sslatteng #ifdef DEBUGABLE
98014759Sslatteng if(dbg)fprintf(stderr, "found :%s:\n",fontmap[i].ffile);
98114759Sslatteng #endif
98214759Sslatteng break;
98314759Sslatteng }
98414759Sslatteng }
98514759Sslatteng
98615282Sslatteng fontname[n] = s;
98715282Sslatteng for(i = 0;i <= NFONTS;i++) /* free the bits of that font */
98813275Sslatteng if (fontdes[i].fnum == n){
98912587Sslatteng nfree(fontdes[i].bits);
99012587Sslatteng fontdes[i].fnum = -1;
99112587Sslatteng }
99212587Sslatteng }
99312587Sslatteng
setfont(n)99412587Sslatteng setfont(n) /* set font to n */
99512587Sslatteng int n;
99612587Sslatteng {
99716538Sslatteng if (n < 0 || n > nfonts)
99814759Sslatteng error(FATAL, "illegal font %d", n);
99914759Sslatteng if (vloadfont(n,pstab[size]) != -1)
100012587Sslatteng font = n;
100112587Sslatteng }
100212587Sslatteng
setstip(n)100316538Sslatteng setstip(n) /* set stipple font to n */
100416538Sslatteng int n;
100516538Sslatteng {
100616538Sslatteng if (n < 1 || n > nstips)
100716538Sslatteng error(FATAL, "illegal stipple %d", n);
100816538Sslatteng stip = n;
100916538Sslatteng }
101016538Sslatteng
101116538Sslatteng
101216538Sslatteng /*----------------------------------------------------------------------------*
101316538Sslatteng | Routine: setfill(stipple_number)
101416538Sslatteng |
101516538Sslatteng | Results: sets the fill-pattern pointers (stip_disp and
101616538Sslatteng | stip_bits) for a particular stipple. Takes stipple
101716538Sslatteng | font from current "stip" number.
101816538Sslatteng *----------------------------------------------------------------------------*/
101916538Sslatteng
setfill(number)102016538Sslatteng setfill(number)
102116538Sslatteng int number;
102216538Sslatteng {
102316538Sslatteng int curfont; /* places to save current text font */
102416538Sslatteng int cursize;
102516538Sslatteng
102616538Sslatteng /* set global stipmem for polygon */
102716538Sslatteng if (number < 0 || number >= DISPATCHSIZE)
102816538Sslatteng stipmem = 0;
102916538Sslatteng else
103016538Sslatteng stipmem = number;
103116538Sslatteng
103216538Sslatteng curfont = cfnum; /* get pointers to */
103316538Sslatteng cursize = cpsize; /* the inuse font */
103416538Sslatteng if (vloadfont(nfonts + stip, 0)) {
103516538Sslatteng stip_disp = (struct dispatch *) NULL; /* stipple not here */
103616538Sslatteng } else {
103716538Sslatteng if (fontwanted) {
103816538Sslatteng if (getfont()) {
103916538Sslatteng stip_disp = (struct dispatch *) NULL;
104016538Sslatteng } else {
104116538Sslatteng stip_disp = dispatch; /* save for polygon routine */
104216538Sslatteng stip_bits = bits;
104316538Sslatteng }
104416538Sslatteng } else {
104516538Sslatteng stip_disp = dispatch; /* save for polygon routine */
104616538Sslatteng stip_bits = bits;
104716538Sslatteng }
104816538Sslatteng }
104916538Sslatteng vloadfont(curfont, cursize);
105016538Sslatteng }
105116538Sslatteng
105216538Sslatteng
vloadfont(fnum,fsize)105312587Sslatteng vloadfont(fnum, fsize)
105412587Sslatteng register int fnum;
105512587Sslatteng register int fsize;
105612587Sslatteng {
105712587Sslatteng register int i;
105812587Sslatteng
105912587Sslatteng fontwanted = 0;
106012587Sslatteng if (fnum == cfnum && fsize == cpsize)
106112587Sslatteng return(0);
106215282Sslatteng for (i = 0; i <= NFONTS; i++) {
106312587Sslatteng if (fontdes[i].fnum == fnum && fontdes[i].psize == fsize) {
106412587Sslatteng cfnum = fontdes[i].fnum;
106512587Sslatteng cpsize = fontdes[i].psize;
106612587Sslatteng dispatch = &fontdes[i].disp[0];
106712587Sslatteng bits = fontdes[i].bits;
106812587Sslatteng cfont = i;
106912587Sslatteng return (0);
107012587Sslatteng }
107112593Sslatteng }
107212587Sslatteng /* this is a new font */
107315282Sslatteng if (fnum < 0 || fnum > NFONTS || fontname[fnum] == 0) {
107414759Sslatteng #ifdef DEBUGABLE
107514759Sslatteng if (dbg) error(!FATAL, "illegal font %d size %d", fnum, fsize);
107614759Sslatteng #endif
107713275Sslatteng return(-1);
107812587Sslatteng }
107912593Sslatteng /* Need to verify the existance of that font/size here*/
108012587Sslatteng nfontnum = fnum;
108112587Sslatteng npsize = fsize;
108212587Sslatteng fontwanted++;
108312587Sslatteng return (0);
108412587Sslatteng }
108512587Sslatteng
108612587Sslatteng
getfont()108712587Sslatteng getfont()
108812587Sslatteng {
108914759Sslatteng register int fnum;
109014759Sslatteng register int fsize;
109114759Sslatteng register int fontd;
109214759Sslatteng register int d;
109315282Sslatteng register int sizehunt = size;
109412587Sslatteng char cbuf[BUFSIZ];
109512587Sslatteng
109614759Sslatteng
109712587Sslatteng fnum = nfontnum;
109812587Sslatteng fsize = npsize;
109914759Sslatteng /* try to open font file - if unsuccessful, hunt for */
110014759Sslatteng /* a file of same style, different size to substitute */
110114759Sslatteng d = -1; /* direction to look in pstab (smaller first) */
110214759Sslatteng do {
110315282Sslatteng sprintf(cbuf, "%s/%s.%d", bitdir, fontname[fnum], fsize);
110414759Sslatteng fontd = open(cbuf, OPENREAD);
110514759Sslatteng if (fontd == -1) { /* File wasn't found. Try another ps */
110615282Sslatteng sizehunt += d;
110715282Sslatteng if (sizehunt < 0) { /* past beginning - look higher */
110814759Sslatteng d = 1;
110915282Sslatteng sizehunt = size + 1;
111014759Sslatteng }
111115282Sslatteng if (sizehunt > nsizes) { /* past top - forget it */
111214759Sslatteng d = 0;
111314759Sslatteng } else {
111415282Sslatteng fsize = pstab[sizehunt];
111514759Sslatteng }
111614759Sslatteng }
111714759Sslatteng } while (fontd == -1 && d != 0);
111814759Sslatteng
111914759Sslatteng if (fontd == -1) { /* completely unsuccessful */
112014759Sslatteng perror(cbuf);
112114759Sslatteng error(!FATAL,"fnum = %d, psize = %d, name = %s",
112215282Sslatteng fnum, npsize, fontname[fnum]);
112314759Sslatteng fontwanted = 0;
112414759Sslatteng return (-1);
112512587Sslatteng }
112612593Sslatteng if (read(fontd, &header, sizeof (header)) != sizeof (header)
112712593Sslatteng || header.magic != 0436)
112812587Sslatteng fprintf(stderr, "%s: Bad font file", cbuf);
112912587Sslatteng else {
113012587Sslatteng cfont = relfont();
113113275Sslatteng if ((bits=nalloc(header.size+DSIZ+1,1))== NULL)
113213275Sslatteng if ((bits=allpanic(header.size+DSIZ+1))== NULL) {
113315282Sslatteng error(FATAL, "%s: ran out of memory", cbuf);
113413275Sslatteng }
113513275Sslatteng
113612587Sslatteng /*
113712587Sslatteng * have allocated one chunk of mem for font, dispatch.
113812587Sslatteng * get the dispatch addr, align to word boundary.
113912587Sslatteng */
114013275Sslatteng
114113275Sslatteng d = (int) bits+header.size;
114213275Sslatteng d += 1;
114313275Sslatteng d &= ~1;
114413275Sslatteng if (read (fontd, d, DSIZ) != DSIZ
114513275Sslatteng || read (fontd, bits, header.size) != header.size)
114613275Sslatteng fprintf(stderr, "bad font header");
114713275Sslatteng else {
114813275Sslatteng close(fontd);
114913275Sslatteng cfnum = fontdes[cfont].fnum = fnum;
115013275Sslatteng cpsize = fontdes[cfont].psize = fsize;
115113275Sslatteng fontdes [cfont].bits = bits;
115213275Sslatteng fontdes [cfont].disp = (struct dispatch *) d;
115313275Sslatteng dispatch = &fontdes[cfont].disp[0];
115413275Sslatteng fontwanted = 0;
115513275Sslatteng return (0);
115612587Sslatteng }
115712587Sslatteng }
115812587Sslatteng close(fontd);
115912587Sslatteng fontwanted = 0;
116012587Sslatteng return(-1);
116112587Sslatteng }
116212587Sslatteng
116313275Sslatteng /*
116413275Sslatteng * "release" a font position - find an empty one, if possible
116513275Sslatteng */
116612587Sslatteng
relfont()116712587Sslatteng relfont()
116812587Sslatteng {
116913275Sslatteng register int newfont;
117012587Sslatteng
117113275Sslatteng for (newfont = 0; newfont < NFONTS; newfont++)
117215282Sslatteng if (fontdes [newfont].fnum == -1)
117313275Sslatteng break;
117415282Sslatteng if (fontdes [newfont].fnum != -1) {
117513275Sslatteng nfree (fontdes [newfont].bits);
117613275Sslatteng #ifdef DEBUGABLE
117713275Sslatteng if (dbg) fprintf (stderr, "freeing position %d\n", newfont);
117813275Sslatteng } else {
117913275Sslatteng if (dbg)
118013275Sslatteng fprintf (stderr, "taking, not freeing, position %d\n", newfont);
118113275Sslatteng #endif
118213275Sslatteng }
118315282Sslatteng fontdes[newfont].fnum = -1;
118413275Sslatteng return (newfont);
118512587Sslatteng }
118612587Sslatteng
allpanic(nbytes)118712593Sslatteng char *allpanic (nbytes)
118812593Sslatteng int nbytes;
118912587Sslatteng {
119012587Sslatteng register int i;
119112587Sslatteng
119212587Sslatteng for (i = 0; i <= NFONTS; i++) {
119315282Sslatteng if (fontdes[i].fnum != -1) nfree(fontdes[i].bits);
119412587Sslatteng fontdes[i].fnum = fontdes[i].psize = -1;
119512587Sslatteng cfnum = cpsize = -1;
119612587Sslatteng }
119712587Sslatteng return(nalloc(nbytes,1));
119812587Sslatteng }
119912587Sslatteng
120012587Sslatteng int M[] = { 0xffffffff, 0xfefefefe, 0xfcfcfcfc, 0xf8f8f8f8,
120112587Sslatteng 0xf0f0f0f0, 0xe0e0e0e0, 0xc0c0c0c0, 0x80808080, 0x0 };
120212587Sslatteng int N[] = { 0x00000000, 0x01010101, 0x03030303, 0x07070707,
120312587Sslatteng 0x0f0f0f0f, 0x1f1f1f1f, 0x3f3f3f3f, 0x7f7f7f7f, 0xffffffff };
120412587Sslatteng int strim[] = { 0xffffffff, 0xffffff00, 0xffff0000, 0xff000000, 0 };
120512587Sslatteng
outc(code)120612587Sslatteng outc(code)
120713787Sslatteng int code; /* character to print */
120812587Sslatteng {
120913787Sslatteng register struct dispatch *dis; /* ptr to character font record */
121013787Sslatteng register char *addr; /* addr of font data */
121113787Sslatteng int llen; /* length of each font line */
121213787Sslatteng int nlines; /* number of font lines */
121313787Sslatteng register char *scanp; /* ptr to output buffer */
121413787Sslatteng int scanp_inc; /* increment to start of next buffer */
121513787Sslatteng int offset; /* bit offset to start of font data */
121614759Sslatteng register int i; /* loop counter */
121713787Sslatteng register int count; /* font data ptr */
121813787Sslatteng register unsigned fontdata; /* font data temporary */
121916196Sslatteng register int off8; /* reverse of offset */
122012587Sslatteng
122113787Sslatteng if (fontwanted)
122215282Sslatteng if (getfont()) return;
122313787Sslatteng dis = dispatch + code;
122413787Sslatteng if (dis->nbytes) {
122516214Sslatteng #ifdef DEBUGABLE
122616214Sslatteng if (dbg) fprintf(stderr, "char %d at (%d,%d)", code, hpos, vpos);
122716214Sslatteng #endif
122813787Sslatteng addr = bits + dis->addr;
122913787Sslatteng llen = (dis->left + dis->right + 7) / 8;
123013787Sslatteng nlines = dis->up + dis->down;
123114759Sslatteng if ((i = vpos + dis->down) > maxv) maxv = i;
123215282Sslatteng scanp = buf0p + (vpos - (vorigin + dis->up)) * BYTES_PER_LINE
123314759Sslatteng + (hpos - dis->left) / 8;
123413787Sslatteng scanp_inc = BYTES_PER_LINE - llen;
123516196Sslatteng offset = (hpos - dis->left) &07;
123616196Sslatteng off8 = 8 - offset;
123713787Sslatteng for (i = 0; i < nlines; i++) {
123816214Sslatteng if (scanp + (count = llen) > BUFBOTTOM) {
123916214Sslatteng #ifdef DEBUGABLE
124016214Sslatteng if (dbg) fprintf(stderr, " scrapped\n");
124116214Sslatteng #endif
124215282Sslatteng return;
124316214Sslatteng }
124416214Sslatteng #ifdef DEBUGABLE
124516214Sslatteng if (dbg) fprintf(stderr, "-");
124616214Sslatteng #endif
124714759Sslatteng if (scanp >= BUFTOP) {
124813787Sslatteng do {
124913787Sslatteng fontdata = *(unsigned *)addr;
125013787Sslatteng addr += 4;
125113787Sslatteng if (count < 4)
125213787Sslatteng fontdata &= ~strim[count];
125316196Sslatteng *(unsigned*)scanp |=(fontdata >> offset) & ~M[off8];
125413787Sslatteng scanp++;
125513787Sslatteng *(unsigned*)scanp |=(fontdata << off8) & ~N[off8];
125613787Sslatteng scanp += 3;
125713787Sslatteng count -= 4;
125813787Sslatteng } while (count > 0);
125913787Sslatteng }
126013787Sslatteng scanp += scanp_inc+count;
126113787Sslatteng addr += count;
126212587Sslatteng }
126316214Sslatteng #ifdef DEBUGABLE
126416214Sslatteng if (dbg) fprintf(stderr, "\n");
126516214Sslatteng #endif
126613787Sslatteng }
126712587Sslatteng }
126812587Sslatteng
126912587Sslatteng
vwrite(buf,usize)127014759Sslatteng vwrite(buf,usize)
127112587Sslatteng char *buf;
127215282Sslatteng int usize;
127312587Sslatteng {
127413275Sslatteng register int tsize = 0;
127513275Sslatteng
127615282Sslatteng while (usize) {
127712587Sslatteng buf += tsize;
127813787Sslatteng tsize = usize > MAXWRIT ? MAXWRIT : usize;
127913275Sslatteng #ifdef DEBUGABLE
128013275Sslatteng if (dbg)fprintf(stderr,"buf = %d size = %d\n",buf,tsize);
128116214Sslatteng if (!dbg)
128213275Sslatteng #endif
128313275Sslatteng if ((tsize = write(OUTFILE, buf, tsize)) < 0) {
128412587Sslatteng perror("dver: write failed");
128512587Sslatteng exit(RESTART);
128612587Sslatteng }
128713275Sslatteng usize -= tsize;
128812587Sslatteng }
128912587Sslatteng }
129012587Sslatteng
vclear(ptr,nbytes)129112593Sslatteng vclear (ptr, nbytes)
129212587Sslatteng char *ptr;
129315282Sslatteng int nbytes;
129412587Sslatteng {
129512593Sslatteng register tsize = 0;
129612593Sslatteng
129713275Sslatteng while (nbytes){
129812593Sslatteng if ((unsigned)(16*1024) < nbytes) {
129912593Sslatteng tsize = 16 * 1024;
130012593Sslatteng } else
130112593Sslatteng tsize = nbytes;
130212593Sslatteng nbytes -= tsize;
130313275Sslatteng #ifdef DEBUGABLE
130412593Sslatteng if (dbg) fprintf(stderr,"clearing ptr = %d size = %d\n",ptr,tsize);
130513275Sslatteng #endif
130612593Sslatteng clear(ptr,tsize);
130712593Sslatteng ptr += tsize;
130812593Sslatteng }
130912587Sslatteng }
131012587Sslatteng
131112587Sslatteng /*ARGSUSED*/
clear(lp,nbytes)131212587Sslatteng clear(lp, nbytes)
131315282Sslatteng char *lp;
131412593Sslatteng int nbytes;
131512587Sslatteng {
1316*24162Sslatteng #ifdef vax
131712587Sslatteng asm("movc5 $0,(sp),$0,8(ap),*4(ap)");
1318*24162Sslatteng #else
1319*24162Sslatteng register int i = nbytes;
1320*24162Sslatteng register char *cp = lp;
1321*24162Sslatteng
1322*24162Sslatteng while(i-- > 0)
1323*24162Sslatteng *(cp++) = 0;
1324*24162Sslatteng #endif
132512587Sslatteng }
132612587Sslatteng
132712587Sslatteng char *
nalloc(i,j)132812587Sslatteng nalloc(i, j)
132912593Sslatteng int i, j;
133012587Sslatteng {
133112587Sslatteng register char *cp;
133212587Sslatteng
133312587Sslatteng cp = calloc(i, j);
133413275Sslatteng #ifdef DEBUGABLE
133513275Sslatteng if (dbg) fprintf(stderr, "allocated %d bytes at %x\n", i * j, cp);
133613275Sslatteng #endif
133712587Sslatteng return(cp);
133812587Sslatteng }
133912587Sslatteng
nfree(cp)134012587Sslatteng nfree(cp)
134112593Sslatteng char *cp;
134212587Sslatteng {
134313275Sslatteng #ifdef DEBUGABLE
134413275Sslatteng if (dbg) fprintf(stderr, "freeing at %x\n", cp);
134513275Sslatteng #endif
134612587Sslatteng free(cp);
134712587Sslatteng }
134812593Sslatteng
134912593Sslatteng
135013787Sslatteng /*
135114759Sslatteng * Plot a dot at (x, y). Points should be in the range 0 <= x < RASTER_LENGTH,
135214759Sslatteng * vorigin <= y < vorigin + NLINES. If the point will not fit on the buffer,
135314759Sslatteng * it is left out. Things outside the x boundary are wrapped around the end.
135413787Sslatteng */
point(x,y)135513787Sslatteng point(x, y)
135616196Sslatteng register int x;
135716196Sslatteng register int y;
135813787Sslatteng {
135914759Sslatteng register char *ptr = buf0p + (y - vorigin) * BYTES_PER_LINE + (x >> 3);
136014759Sslatteng
136116196Sslatteng if (ptr > BUFBOTTOM || ptr < BUFTOP) /* ignore if it's off buffer */
136216196Sslatteng return;
136316196Sslatteng
136416196Sslatteng *ptr |= 1 << (7 - (x & 07));
136516196Sslatteng if (y > maxv) maxv = y;
136613787Sslatteng }
136716538Sslatteng
136816538Sslatteng
136916538Sslatteng #define MAXX 0x7fff /* largest positive int */
137016538Sslatteng #define MINX 0x8000 /* smallest negative int */
137116538Sslatteng #define MAXVECT 75
137216538Sslatteng
137316538Sslatteng typedef struct poly {
137416538Sslatteng struct poly *next; /* doublely-linked lists of vectors */
137516538Sslatteng struct poly *prev;
137616538Sslatteng int param; /* bressenham line algorithm parameter */
137716538Sslatteng short dy; /* delta-y for calculating line */
137816538Sslatteng short dx; /* delta-x for calculating line */
137916538Sslatteng short currx; /* current x in this vector */
138016538Sslatteng short endy; /* where vector ends */
138116538Sslatteng } polyvector;
138216538Sslatteng
138316538Sslatteng int rp_len; /* length of the string in "buf" */
138416538Sslatteng char * rp_ptr; /* "walking" pointer into buf */
138516538Sslatteng
138616538Sslatteng
138716538Sslatteng /*----------------------------------------------------------------------------*
138816538Sslatteng | Routine: read_poly (input_buffer, file_pointer)
138916538Sslatteng |
139016538Sslatteng | Results: gets an integer from buffer pointed to by rp_ptr,
139116538Sslatteng | and advances in the file. If there is nothing left,
139216538Sslatteng | more can be read in from the file. rp_ptr and rp_len
139316538Sslatteng | are set in "polygon".
139416538Sslatteng *----------------------------------------------------------------------------*/
139516538Sslatteng
read_poly(buf,fp)139616538Sslatteng read_poly(buf, fp)
139716538Sslatteng char *buf;
139816538Sslatteng FILE *fp;
139916538Sslatteng {
140016538Sslatteng register int i;
140116538Sslatteng
140216538Sslatteng
140316538Sslatteng if (*rp_ptr == '\n')
140416538Sslatteng return 0;
140516538Sslatteng
140616538Sslatteng while (isspace(*++rp_ptr)); /* skip any leading spaces */
140716538Sslatteng i = atoi(rp_ptr); /* convert motion to curve points */
140816538Sslatteng while (isdigit(*++rp_ptr)); /* skip number*/
140916538Sslatteng /* if the amount we read wasn't the */
141016538Sslatteng /* whole thing, read some more in */
141116538Sslatteng if (rp_len - (rp_ptr - buf) < 10 && *(buf + rp_len - 1) != '\n') {
141216538Sslatteng register char *cop = buf;
141316538Sslatteng
141416538Sslatteng while (*(cop++) = *(rp_ptr++)); /* what's left to beginning */
141516538Sslatteng if (fgets ((cop - 1), rp_len - (cop - buf), fp) == NULL)
141616538Sslatteng error(FATAL, "unexpected end of input");
141716538Sslatteng rp_ptr = buf;
141816538Sslatteng }
141916538Sslatteng
142016538Sslatteng return i;
142116538Sslatteng }
142216538Sslatteng
142316538Sslatteng
142416538Sslatteng /*----------------------------------------------------------------------------*
142516538Sslatteng | Routine: polygon ( string, file )
142616538Sslatteng |
142716538Sslatteng | Results: draws a polygon specified by the parameters encoded into the
142816538Sslatteng | string (and from the file, if necessary). The parameters are
142916538Sslatteng | broken up into separate vectors. The vectors are encoded as
143016538Sslatteng | follows: (p dx dy curx endy); endy is the bottom of vector,
143116538Sslatteng | curx is where x starts; dx, dy are the deltas for the line;
143216538Sslatteng | if dy is negative, p is the Bresenham line algorithm parameter,
143316538Sslatteng | otherwise p is the starting y. All the active vectors must be
143416538Sslatteng | put first.
143516538Sslatteng |
143616538Sslatteng | The polygon is filled with a stipple pattern from stip_disp
143716538Sslatteng | and stip_bits, which point to the stipple font. The pattern
143816538Sslatteng | is defined by "stip" and "stipmem".
143916538Sslatteng |
144016538Sslatteng | The scan-line algorithm implemented scans from top to
144116538Sslatteng | bottom (low y to high y). It also scans, within a line,
144216538Sslatteng | from left to right (low x to high x).
144316538Sslatteng |
144416538Sslatteng | Bugs: stipple pattern MUST be a power of two bytes "wide" and
144516538Sslatteng | square. The square restriction comes from the fact that
144616538Sslatteng | the varian and versatec are respectively rotated.
144716538Sslatteng *----------------------------------------------------------------------------*/
144816538Sslatteng
polygon(buf,fp)144916538Sslatteng polygon(buf, fp)
145016538Sslatteng char *buf;
145116538Sslatteng FILE *fp;
145216538Sslatteng {
145316538Sslatteng int nexty; /* at what y value the next vector starts */
145416538Sslatteng int maxy, miny; /* finds bounds of polygon */
145516538Sslatteng polyvector *activehead; /* doing fill, is active edge list */
145616538Sslatteng polyvector *waitinghead; /* edges waiting to be active */
145716538Sslatteng register polyvector *vectptr; /* random vector */
145816538Sslatteng register int i; /* random register */
145916538Sslatteng
146016538Sslatteng char *topstipple; /* points to beginning of stipple glyph */
146116538Sslatteng char *leftstipple; /* points to beginning of line of stipple */
146216538Sslatteng char *leftpage; /* points to the edge of a raster line */
146316538Sslatteng int bytewidth; /* glyph width in bytes */
146416538Sslatteng int mask; /* mask to pick off pixel index into stipple */
146516538Sslatteng int bytemask; /* mask to pick off byte index into stipple */
146616538Sslatteng
146716538Sslatteng
146816538Sslatteng rp_len = strlen(buf); /* length of the string in "buf" */
146916538Sslatteng rp_ptr = buf; /* "walking" pointer into buf */
147016538Sslatteng /* if no stipple, don't fill */
147116538Sslatteng if (stip_disp == (struct dispatch *) NULL || stip_bits == (char *) NULL)
147216538Sslatteng goto leavepoly;
147316538Sslatteng
147416538Sslatteng stip_disp += stipmem; /* set up parameters for */
147516538Sslatteng if (!stip_disp->nbytes) { /* tiling with the stipple */
147616538Sslatteng #ifdef DEBUGABLE
147716538Sslatteng error(!FATAL, "member not found: member %d, stipple %d", stipmem, stip);
147816538Sslatteng #endif
147916538Sslatteng goto leavepoly;
148016538Sslatteng }
148116538Sslatteng topstipple = stip_bits + stip_disp->addr;
148216538Sslatteng bytewidth = stip_disp->up + stip_disp->down;
148316538Sslatteng for (i = 1 << 30; i && i != bytewidth; i = i >> 1)
148416538Sslatteng ;
148516538Sslatteng if (i==0 || bytewidth<8 || bytewidth != stip_disp->right+stip_disp->left) {
148616538Sslatteng error(!FATAL, "invalid stipple: number %d, member %d", stip, stipmem);
148716538Sslatteng goto leavepoly;
148816538Sslatteng }
148916538Sslatteng mask = bytewidth - 1;
149016538Sslatteng bytewidth = bytewidth >> 3;
149116538Sslatteng bytemask = bytewidth - 1;
149216538Sslatteng
149316538Sslatteng if ((i = read_poly(buf, fp)) < 2) /* # of vects command holds */
149416538Sslatteng goto leavepoly;
149516538Sslatteng miny = read_poly(buf, fp); /* get limits from command */
149616538Sslatteng maxy = read_poly(buf, fp);
149716538Sslatteng
149816538Sslatteng leftstipple = topstipple + (miny & mask) * bytewidth;
149916538Sslatteng leftpage = buf0p + (miny - vorigin) * BYTES_PER_LINE;
150016538Sslatteng
150116538Sslatteng /* allocate space for raster-fill algorithm*/
150216538Sslatteng vectptr = (polyvector *) nalloc(sizeof(polyvector), i + 4);
150316538Sslatteng if (vectptr == (polyvector *) NULL) {
150416538Sslatteng error(!FATAL, "unable to allocate space for polygon");
150516538Sslatteng return;
150616538Sslatteng }
150716538Sslatteng
150816538Sslatteng waitinghead = vectptr;
150916538Sslatteng vectptr->param = miny - 1; /* put dummy entry at start */
151016538Sslatteng (vectptr++)->prev = NULL;
151116538Sslatteng waitinghead->next = vectptr;
151216538Sslatteng vectptr->prev = waitinghead;
151316538Sslatteng
151416538Sslatteng while (i--) {
151516538Sslatteng vectptr->next = vectptr + 1;
151616538Sslatteng vectptr->param = read_poly(buf, fp);
151716538Sslatteng vectptr->dx = read_poly(buf,fp);
151816538Sslatteng vectptr->dy = read_poly(buf,fp);
151916538Sslatteng vectptr->currx = read_poly(buf,fp);
152016538Sslatteng (vectptr++)->endy = read_poly(buf,fp);
152116538Sslatteng vectptr->prev = vectptr - 1;
152216538Sslatteng }
152316538Sslatteng
152416538Sslatteng vectptr->param = maxy + 1; /* dummy entry at end, too */
152516538Sslatteng vectptr->currx = vectptr->dx = vectptr->dy = 0;
152616538Sslatteng vectptr->next = NULL;
152716538Sslatteng
152816538Sslatteng activehead = ++vectptr; /* two dummy entries for active list */
152916538Sslatteng vectptr->currx = MINX; /* head */
153016538Sslatteng vectptr->endy = maxy + 1;
153116538Sslatteng vectptr->param = vectptr->dx = vectptr->dy = 0;
153216538Sslatteng activehead->next = ++vectptr;
153316538Sslatteng activehead->prev = vectptr;
153416538Sslatteng vectptr->prev = activehead; /* tail */
153516538Sslatteng vectptr->next = activehead;
153616538Sslatteng vectptr->currx = MAXX;
153716538Sslatteng vectptr->endy = maxy + 1;
153816538Sslatteng vectptr->param = vectptr->dx = vectptr->dy = 0;
153916538Sslatteng
154016538Sslatteng vectptr = waitinghead->next; /* if anything is active already */
154116538Sslatteng if (vectptr->dy < 0) { /* put them into the active list */
154216538Sslatteng register polyvector *p; /* random useful register pointer */
154316538Sslatteng
154416538Sslatteng p = vectptr;
154516538Sslatteng do {
154616538Sslatteng vectptr->dy = -vectptr->dy;
154716538Sslatteng } while ((++vectptr)->dy < 0);
154816538Sslatteng
154916538Sslatteng waitinghead->next = vectptr; /* first, remove list from waiting */
155016538Sslatteng (vectptr--)->prev = waitinghead;
155116538Sslatteng
155216538Sslatteng activehead->next->prev = vectptr; /* link in end */
155316538Sslatteng vectptr->next = activehead->next;
155416538Sslatteng activehead->next = p; /* link in start */
155516538Sslatteng p->prev = activehead;
155616538Sslatteng }
155716538Sslatteng
155816538Sslatteng /* main loop -- gets vectors off the waiting list, */
155916538Sslatteng /* then displays spans while updating the vectors in */
156016538Sslatteng /* the active list */
156116538Sslatteng while (miny <= maxy) {
156216538Sslatteng i = maxy + 1; /* this is the NEXT time to get a new vector */
156316538Sslatteng for (vectptr = waitinghead->next; vectptr != NULL; ) {
156416538Sslatteng if (miny == vectptr->param) {
156516538Sslatteng /* the entry in waiting list (vectptr) is */
156616538Sslatteng /* ready to go into active list. Need to */
156716538Sslatteng /* convert some vector stuff and sort the */
156816538Sslatteng /* entry into the list. */
156916538Sslatteng register polyvector *p; /* random vector pointers */
157016538Sslatteng register polyvector *v;
157116538Sslatteng
157216538Sslatteng /* convert this */
157316538Sslatteng if (vectptr->dx < 0) /* entry to active */
157416538Sslatteng vectptr->param = -((vectptr->dx >> 1) + (vectptr->dy >> 1));
157516538Sslatteng else
157616538Sslatteng vectptr->param = (vectptr->dx >> 1) - (vectptr->dy >> 1);
157716538Sslatteng
157816538Sslatteng p = vectptr; /* remove from the */
157916538Sslatteng vectptr = vectptr->next; /* waiting list */
158016538Sslatteng vectptr->prev = p->prev;
158116538Sslatteng p->prev->next = vectptr;
158216538Sslatteng /* find where it goes */
158316538Sslatteng /* in the active list */
158416538Sslatteng /* (sorted smallest first) */
158516538Sslatteng for (v = activehead->next; v->currx < p->currx; v = v->next)
158616538Sslatteng ;
158716538Sslatteng p->next = v; /* insert into active list */
158816538Sslatteng p->prev = v->prev; /* before the one it stopped on */
158916538Sslatteng v->prev = p;
159016538Sslatteng p->prev->next = p;
159116538Sslatteng } else {
159216538Sslatteng if (i > vectptr->param) {
159316538Sslatteng i = vectptr->param;
159416538Sslatteng }
159516538Sslatteng vectptr = vectptr->next;
159616538Sslatteng }
159716538Sslatteng }
159816538Sslatteng nexty = i;
159916538Sslatteng
160016538Sslatteng /* print the polygon while there */
160116538Sslatteng /* are no more vectors to add */
160216538Sslatteng while (miny < nexty) {
160316538Sslatteng /* remove any finished vectors */
160416538Sslatteng vectptr = activehead->next;
160516538Sslatteng do {
160616538Sslatteng if (vectptr->endy <= miny) {
160716538Sslatteng vectptr->prev->next = vectptr->next;
160816538Sslatteng vectptr->next->prev = vectptr->prev;
160916538Sslatteng }
161016538Sslatteng } while ((vectptr = vectptr->next) != activehead);
161116538Sslatteng
161216538Sslatteng /* draw the span */
161316538Sslatteng vectptr = activehead->next;
161416538Sslatteng while (vectptr->next != activehead) {
161516538Sslatteng register int start; /* get the beginning */
161616538Sslatteng register int length; /* and the end of span */
161716538Sslatteng register char *glyph;
161816538Sslatteng register char *raster;
161916538Sslatteng
162016538Sslatteng start = vectptr->currx;
162116538Sslatteng vectptr = vectptr->next;
162216538Sslatteng length = vectptr->currx + 1;
162316538Sslatteng vectptr = vectptr->next;
162416538Sslatteng
162516538Sslatteng /* bound the polygon to the page */
162616538Sslatteng if (start >= RASTER_LENGTH)
162716538Sslatteng break;
162816538Sslatteng if (start < 0) start = 0;
162916538Sslatteng if (length > RASTER_LENGTH) length = RASTER_LENGTH;
163016538Sslatteng length -= start; /* length is in pixels */
163116538Sslatteng
163216538Sslatteng i = start & 7;
163316538Sslatteng start = start >> 3; /* start is in bytes */
163416538Sslatteng raster = leftpage + start;
163516538Sslatteng glyph = leftstipple + (start & bytemask);
163616538Sslatteng
163716538Sslatteng if (i) { /* do any piece of byte */
163816538Sslatteng register char data; /* that hangs on the front */
163916538Sslatteng
164016538Sslatteng data = (*(glyph++)) & (0x7f >> --i);
164116538Sslatteng length -= 7 - i;
164216538Sslatteng if (length < 0) { /* less than one byte wide? */
164316538Sslatteng data &= 0xff << -length;
164416538Sslatteng length = 0; /* force clean stoppage */
164516538Sslatteng }
164616538Sslatteng *(raster++) |= data;
164716538Sslatteng /* update glyph ptr after first byte */
164816538Sslatteng if (!(++start & bytemask))
164916538Sslatteng glyph = leftstipple;
165016538Sslatteng }
165116538Sslatteng /* fill the line of raster */
165216538Sslatteng while ((length -= 8) >= 0) {
165316538Sslatteng *(raster++) |= *(glyph++);
165416538Sslatteng if (!(++start & bytemask))
165516538Sslatteng glyph = leftstipple;
165616538Sslatteng }
165716538Sslatteng if (length & 7) { /* add any part hanging off the end */
165816538Sslatteng *raster |= (*glyph) & (0xff << -length);
165916538Sslatteng }
166016538Sslatteng }
166116538Sslatteng
166216538Sslatteng #ifdef DEBUGABLE
166316538Sslatteng if (dbg) {
166416538Sslatteng vectptr = activehead;
166516538Sslatteng do {
166616538Sslatteng fprintf (stderr, "%d ", vectptr->currx);
166716538Sslatteng vectptr = vectptr->next;
166816538Sslatteng } while (vectptr != activehead);
166916538Sslatteng }
167016538Sslatteng #endif
167116538Sslatteng /* update the vectors */
167216538Sslatteng vectptr = activehead->next;
167316538Sslatteng do {
167416538Sslatteng if (vectptr->dx > 0) {
167516538Sslatteng while (vectptr->param >= 0) {
167616538Sslatteng vectptr->param -= vectptr->dy;
167716538Sslatteng vectptr->currx++;
167816538Sslatteng }
167916538Sslatteng vectptr->param += vectptr->dx;
168016538Sslatteng } else if (vectptr->dx < 0) {
168116538Sslatteng while (vectptr->param >= 0) {
168216538Sslatteng vectptr->param -= vectptr->dy;
168316538Sslatteng vectptr->currx--;
168416538Sslatteng }
168516538Sslatteng vectptr->param -= vectptr->dx;
168616538Sslatteng }
168716538Sslatteng /* must sort the vectors if updates */
168816538Sslatteng /* caused them to cross */
168916538Sslatteng /* also move to next vector here */
169016538Sslatteng if (vectptr->currx < vectptr->prev->currx) {
169116538Sslatteng register polyvector *v; /* vector to move */
169216538Sslatteng register polyvector *p; /* vector to put it after */
169316538Sslatteng
169416538Sslatteng v = vectptr;
169516538Sslatteng p = v->prev;
169616538Sslatteng while (v->currx < p->currx) /* find the */
169716538Sslatteng p = p->prev; /* right vector */
169816538Sslatteng
169916538Sslatteng vectptr = vectptr->next; /* remove from spot */
170016538Sslatteng vectptr->prev = v->prev;
170116538Sslatteng v->prev->next = vectptr;
170216538Sslatteng
170316538Sslatteng v->prev = p; /* put in new spot */
170416538Sslatteng v->next = p->next;
170516538Sslatteng p->next = v;
170616538Sslatteng v->next->prev = v;
170716538Sslatteng } else {
170816538Sslatteng vectptr = vectptr->next;
170916538Sslatteng }
171016538Sslatteng } while (vectptr != activehead);
171116538Sslatteng #ifdef DEBUGABLE
171216538Sslatteng if (dbg) fprintf(stderr, "line done\n");
171316538Sslatteng #endif
171416538Sslatteng
171516538Sslatteng if (++miny & mask) {
171616538Sslatteng leftstipple += bytewidth;
171716538Sslatteng } else {
171816538Sslatteng leftstipple = topstipple;
171916538Sslatteng }
172016538Sslatteng leftpage += BYTES_PER_LINE;
172116538Sslatteng } /* while (miny < nexty) */
172216538Sslatteng } /* while (miny <= maxy) */
172316538Sslatteng
172416538Sslatteng nfree(waitinghead); /* dump the space allocated for polygon */
172516538Sslatteng
172616538Sslatteng leavepoly:
172716538Sslatteng while (*rp_ptr != '\n')
172816538Sslatteng i = read_poly(buf, fp);
172916538Sslatteng } /* polygon function */
1730