1*24165Sslatteng /* dvar.c 1.15 85/08/05
213858Sslatteng *
313858Sslatteng * Varian driver for the new troff
413858Sslatteng *
513858Sslatteng * Authors: BWK(BELL)
613858Sslatteng * VCAT(berkley)
713858Sslatteng * Richard L. Hyde, Perdue University
814582Sslatteng * and David Slattengren, U.C. Berkeley
913858Sslatteng */
1013858Sslatteng
1113858Sslatteng
1213858Sslatteng /*******************************************************************************
1313858Sslatteng
1413858Sslatteng output language from troff:
1513858Sslatteng all numbers are character strings
1613858Sslatteng
1713858Sslatteng #..\n comment
1813858Sslatteng sn size in points
1913858Sslatteng fn font as number from 1 to n
2016539Sslatteng in stipple `font' as number from 1 to n
2113858Sslatteng cx ascii character x
2213858Sslatteng Cxyz funny char \(xyz. terminated by white space
2313858Sslatteng Hn go to absolute horizontal position n
2413858Sslatteng Vn go to absolute vertical position n (down is positive)
2513858Sslatteng hn go n units horizontally (relative)
2613858Sslatteng vn ditto vertically
2713858Sslatteng nnc move right nn, then print c (exactly 2 digits!)
2813858Sslatteng (this wart is an optimization that shrinks output file size
2913858Sslatteng about 35% and run-time about 15% while preserving ascii-ness)
3013858Sslatteng p new page begins -- set v to 0
3113858Sslatteng nb a end of line (information only -- no action needed)
3213858Sslatteng b = space before line, a = after
3313858Sslatteng w paddable word space -- no action needed
3413858Sslatteng
3513858Sslatteng Dt ..\n draw operation 't':
3616539Sslatteng Dt d set line thickness to d
3716539Sslatteng Ds d set line style (mask) to d
3813858Sslatteng Dl x y line from here by x,y
3913858Sslatteng Dc d circle of diameter d with left side here
4013858Sslatteng De x y ellipse of axes x,y with left side here
4113858Sslatteng Da x y r arc counter-clockwise by x,y of radius r
4213858Sslatteng D~ x y x y ... B-spline curve by x,y then x,y ...
4316539Sslatteng Dg x y x y ... gremlin spline curve by x,y then x,y ...
4416539Sslatteng Dp s x y ... polygon by x,y then ... filled with stipple s
4513858Sslatteng
4613858Sslatteng x ..\n device control functions:
4713858Sslatteng x i init
4813858Sslatteng x T s name of device is s
4913858Sslatteng x r n h v resolution is n/inch h = min horizontal motion, v = min vert
5013858Sslatteng x p pause (can restart)
5113858Sslatteng x s stop -- done for ever
5213858Sslatteng x t generate trailer
5313858Sslatteng x f n s font position n contains font s
5413858Sslatteng x H n set character height to n
5513858Sslatteng x S n set slant to N
5613858Sslatteng
5713858Sslatteng Subcommands like "i" are often spelled out like "init".
5813858Sslatteng
5913858Sslatteng *******************************************************************************/
6013858Sslatteng
6113858Sslatteng
6213858Sslatteng #include <stdio.h>
6313858Sslatteng #include <ctype.h>
6413858Sslatteng #include <sys/vcmd.h>
6513858Sslatteng #include "dev.h"
6613858Sslatteng
6713858Sslatteng
6815176Sslatteng /* #define DEBUGABLE /* No, not debugable... */
6915176Sslatteng #define DRIVER /* Yes, we're driving directly */
7015176Sslatteng /* #define FULLPAGE /* No, don't output full pages */
7116539Sslatteng #define NFONTS 65 /* total number of fonts useable */
7213858Sslatteng #define MAXSTATE 6 /* number of environments rememberable */
7313858Sslatteng #define OPENREAD 0 /* mode for openning files */
7413858Sslatteng #define RESTART 1 /* upon exit, return either RESTART */
7513858Sslatteng #define ABORT 2 /* or ABORT */
7613858Sslatteng #define FATAL 1 /* type of error */
7713858Sslatteng #define BMASK 0377 /* byte grabber */
7815734Sslatteng #ifndef FONTDIR
7914582Sslatteng #define FONTDIR "/usr/lib/font" /* default place to find font descriptions */
8015734Sslatteng #endif
8119066Sslatteng #ifndef BITDIR
8214582Sslatteng #define BITDIR "/usr/lib/vfont" /* default place to look for font rasters */
8319066Sslatteng #endif
8413858Sslatteng #define MAXWRIT 4096 /* max characters allowed to write at once */
8513858Sslatteng
8614284Sslatteng #define hmot(n) hgoto(hpos + n)
8713858Sslatteng #define vmot(n) vgoto(vpos + n)
8813858Sslatteng
8913858Sslatteng
90*24165Sslatteng char SccsId[]= "dvar.c 1.15 85/08/05";
9113858Sslatteng
9213858Sslatteng int output = 0; /* do we do output at all? */
9313858Sslatteng int nolist = 0; /* output page list if > 0 */
9413858Sslatteng int olist[20]; /* pairs of page numbers */
9513858Sslatteng int spage = 9999; /* stop every spage pages */
9613858Sslatteng int scount = 0;
9713858Sslatteng struct dev dev;
9813858Sslatteng struct font *fontbase[NFONTS+1];
9914582Sslatteng short * pstab; /* point size table pointer */
10013858Sslatteng int nsizes; /* number of sizes device is capable of printing */
10113858Sslatteng int nfonts; /* number of fonts device is capable of printing */
10216539Sslatteng int nstips; /* number of stipple fonts device can print */
10313858Sslatteng int nchtab;
10414582Sslatteng char * chname;
10514582Sslatteng short * chtab;
10614582Sslatteng char * fitab[NFONTS+1]; /* font inclusion table - maps ascii to ch # */
10714582Sslatteng char * widtab[NFONTS+1]; /* width table for each font */
10814582Sslatteng char * codetab[NFONTS+1]; /* device codes */
10914582Sslatteng char * fontdir = FONTDIR; /* place to find devxxx directories */
11014582Sslatteng char * bitdir = BITDIR; /* place to find raster fonts and fontmap */
11115176Sslatteng char * fontname[NFONTS+1]; /* table of what font is on what position */
11213858Sslatteng struct { /* table of what font */
11314582Sslatteng char fname[3]; /* name maps to what */
11414582Sslatteng char *ffile; /* filename in bitdirectory */
11514582Sslatteng } fontmap[NFONTS+1];
11613858Sslatteng
11714582Sslatteng
11813858Sslatteng #ifdef DEBUGABLE
11913858Sslatteng int dbg = 0;
12013858Sslatteng #endif
12114582Sslatteng int size = -1; /* current point size (internal pstable index) */
12213858Sslatteng int font = -1; /* current font - not using any to start with */
12316539Sslatteng int stip = -1; /* current stipple font - not using any to start with */
12416539Sslatteng int stipmem = 0; /* current member to use from stipple font */
12513858Sslatteng int hpos; /* horizontal position we are to be at next; left = 0 */
12613858Sslatteng int vpos; /* current vertical position (down positive) */
12714582Sslatteng extern linethickness; /* thickness (in pixels) of any drawn object */
12814284Sslatteng extern linmod; /* line style (a bit mask - dotted, etc.) of objects */
12913858Sslatteng int lastw; /* width of last character printed */
13013858Sslatteng
13113858Sslatteng
13213858Sslatteng #define DISPATCHSIZE 256 /* must be a power of two */
13313858Sslatteng #define CHARMASK (DISPATCHSIZE-1)
13413858Sslatteng #define DSIZ ((sizeof *dispatch)*DISPATCHSIZE)
13513858Sslatteng #define OUTFILE fileno (stdout)
13614582Sslatteng #define RES 200 /* resolution of the device (dots/in) */
13713858Sslatteng
13813890Sslatteng #define RASTER_LENGTH 2112 /* device line length */
13913858Sslatteng #define BYTES_PER_LINE (RASTER_LENGTH/8)
14015176Sslatteng #ifndef FULLPAGE
14115176Sslatteng # define NLINES 1600 /* page width, 8 inches */
14215176Sslatteng #endif
14315176Sslatteng #ifdef FULLPAGE
14415176Sslatteng # define NLINES 1700 /* page width, 8.5 inches */
14515176Sslatteng #endif
14613858Sslatteng #define BUFFER_SIZE (NLINES*BYTES_PER_LINE) /* number of chars in picture */
14713858Sslatteng
14813858Sslatteng
14913858Sslatteng int pltmode[] = { VPLOT };
15013858Sslatteng int prtmode[] = { VPRINT };
15115283Sslatteng char buffer1[BUFFER_SIZE]; /* Big line buffers */
15215283Sslatteng char buffer2[BUFFER_SIZE];
15315283Sslatteng char * fill = &buffer1[0]; /* Zero origin in filling buffer */
15415283Sslatteng char * empty = &buffer2[0]; /* Zero origin in emptying buffer */
15515283Sslatteng char * elevel = &buffer2[0]; /* current position in emptying buffer */
15615283Sslatteng int emptypos = NLINES; /* amount of emptying done (initially "done") */
15713858Sslatteng
15815283Sslatteng
15914582Sslatteng char * calloc();
16014582Sslatteng char * nalloc();
16114582Sslatteng char * allpanic();
16214823Sslatteng char * operand();
16313858Sslatteng
16413858Sslatteng struct header {
16513858Sslatteng short magic;
16613858Sslatteng unsigned short size;
16713858Sslatteng short maxx;
16813858Sslatteng short maxy;
16913858Sslatteng short xtnd;
17013858Sslatteng } header;
17113858Sslatteng
17213858Sslatteng struct dispatch{
17313858Sslatteng unsigned short addr;
17413858Sslatteng short nbytes;
17513858Sslatteng char up;
17613858Sslatteng char down;
17713858Sslatteng char left;
17813858Sslatteng char right;
17913858Sslatteng short width;
18013858Sslatteng };
18113858Sslatteng
18213858Sslatteng struct fontdes {
18315283Sslatteng int fnum; /* if == -1, then this position is empty */
18413858Sslatteng int psize;
18513858Sslatteng struct dispatch *disp;
18613858Sslatteng char *bits;
18715283Sslatteng } fontdes[NFONTS+1]; /* initialized at program start */
18813858Sslatteng
18913858Sslatteng struct dispatch *dispatch;
19016539Sslatteng struct dispatch *stip_disp;
19113858Sslatteng int cfnum = -1;
19213858Sslatteng int cpsize = 10;
19313858Sslatteng int cfont = 1;
19413858Sslatteng char *bits;
19516539Sslatteng char *stip_bits;
19616539Sslatteng int bordered = 1; /* flag: "do polygons get bordered?" */
19713858Sslatteng int fontwanted = 1; /* flag: "has a new font been requested?" */
19813858Sslatteng int nfontnum = -1;
19913858Sslatteng int npsize = 10;
20013858Sslatteng
20113858Sslatteng
20213858Sslatteng
main(argc,argv)20313858Sslatteng main(argc, argv)
20413858Sslatteng char *argv[];
20513858Sslatteng {
20615283Sslatteng register FILE *fp;
20715283Sslatteng register int i;
20813858Sslatteng
20915283Sslatteng for (i = 0; i <= NFONTS; fontdes[i++].fnum = -1);
21014823Sslatteng while (--argc > 0 && **++argv == '-') {
21114823Sslatteng switch ((*argv)[1]) {
21214582Sslatteng case 'F':
21315176Sslatteng bitdir = operand(&argc, &argv);
21414582Sslatteng break;
21513858Sslatteng case 'f':
21615176Sslatteng fontdir = operand(&argc, &argv);
21713858Sslatteng break;
21813858Sslatteng case 'o':
21914823Sslatteng outlist(operand(&argc, &argv));
22013858Sslatteng break;
22113858Sslatteng #ifdef DEBUGABLE
22213858Sslatteng case 'd':
22314823Sslatteng dbg = atoi(operand(&argc, &argv));
22413858Sslatteng if (dbg == 0) dbg = 1;
22513858Sslatteng break;
22613858Sslatteng #endif
22713858Sslatteng case 's':
22814823Sslatteng spage = atoi(operand(&argc, &argv));
22913858Sslatteng if (spage <= 0)
23013858Sslatteng spage = 9999;
23113858Sslatteng break;
23213858Sslatteng }
23313858Sslatteng }
23413858Sslatteng
23515176Sslatteng #ifdef DRIVER
23613858Sslatteng ioctl(OUTFILE, VSETSTATE, pltmode);
23715176Sslatteng #endif
23813858Sslatteng
23914823Sslatteng if (argc < 1)
24013858Sslatteng conv(stdin);
24113858Sslatteng else
24214823Sslatteng while (argc--) {
24314823Sslatteng if (strcmp(*argv, "-") == 0)
24413858Sslatteng fp = stdin;
24513858Sslatteng else if ((fp = fopen(*argv, "r")) == NULL)
24613858Sslatteng error(FATAL, "can't open %s", *argv);
24713858Sslatteng conv(fp);
24813858Sslatteng fclose(fp);
24914823Sslatteng argv++;
25013858Sslatteng }
25113858Sslatteng exit(0);
25213858Sslatteng }
25313858Sslatteng
25414823Sslatteng
25514823Sslatteng /*----------------------------------------------------------------------------*
25614823Sslatteng | Routine: char * operand (& argc, & argv)
25714823Sslatteng |
25814823Sslatteng | Results: returns address of the operand given with a command-line
25914823Sslatteng | option. It uses either "-Xoperand" or "-X operand", whichever
26014823Sslatteng | is present. The program is terminated if no option is present.
26114823Sslatteng |
26214823Sslatteng | Side Efct: argc and argv are updated as necessary.
26314823Sslatteng *----------------------------------------------------------------------------*/
26414823Sslatteng
operand(argcp,argvp)26514823Sslatteng char *operand(argcp, argvp)
26614823Sslatteng int * argcp;
26714823Sslatteng char ***argvp;
26814823Sslatteng {
26914823Sslatteng if ((**argvp)[2]) return(**argvp + 2); /* operand immediately follows */
27014823Sslatteng if ((--*argcp) <= 0) /* no operand */
27114823Sslatteng error (FATAL, "command-line option operand missing.\n");
27214823Sslatteng return(*(++(*argvp))); /* operand next word */
27314823Sslatteng }
27414823Sslatteng
27514823Sslatteng
outlist(s)27613858Sslatteng outlist(s) /* process list of page numbers to be printed */
27713858Sslatteng char *s;
27813858Sslatteng {
27913858Sslatteng int n1, n2, i;
28013858Sslatteng
28113858Sslatteng nolist = 0;
28213858Sslatteng while (*s) {
28313858Sslatteng n1 = 0;
28413858Sslatteng if (isdigit(*s))
28513858Sslatteng do
28613858Sslatteng n1 = 10 * n1 + *s++ - '0';
28713858Sslatteng while (isdigit(*s));
28813858Sslatteng else
28913858Sslatteng n1 = -9999;
29013858Sslatteng n2 = n1;
29113858Sslatteng if (*s == '-') {
29213858Sslatteng s++;
29313858Sslatteng n2 = 0;
29413858Sslatteng if (isdigit(*s))
29513858Sslatteng do
29613858Sslatteng n2 = 10 * n2 + *s++ - '0';
29713858Sslatteng while (isdigit(*s));
29813858Sslatteng else
29913858Sslatteng n2 = 9999;
30013858Sslatteng }
30113858Sslatteng olist[nolist++] = n1;
30213858Sslatteng olist[nolist++] = n2;
30313858Sslatteng if (*s != '\0')
30413858Sslatteng s++;
30513858Sslatteng }
30613858Sslatteng olist[nolist] = 0;
30713858Sslatteng #ifdef DEBUGABLE
30813858Sslatteng if (dbg)
30913858Sslatteng for (i=0; i<nolist; i += 2)
31013858Sslatteng fprintf(stderr,"%3d %3d\n", olist[i], olist[i+1]);
31113858Sslatteng #endif
31213858Sslatteng }
31313858Sslatteng
conv(fp)31413858Sslatteng conv(fp)
31513858Sslatteng register FILE *fp;
31613858Sslatteng {
31713858Sslatteng register int c, k;
31813858Sslatteng int m, n, n1, m1;
31913858Sslatteng char str[100], buf[300];
32013858Sslatteng
32113858Sslatteng while ((c = getc(fp)) != EOF) {
32213858Sslatteng switch (c) {
32313858Sslatteng case '\n': /* when input is text */
32413858Sslatteng case ' ':
32513858Sslatteng case 0: /* occasional noise creeps in */
32613858Sslatteng break;
32713858Sslatteng case '{': /* push down current environment */
32813858Sslatteng t_push();
32913858Sslatteng break;
33013858Sslatteng case '}':
33113858Sslatteng t_pop();
33213858Sslatteng break;
33313858Sslatteng case '0': case '1': case '2': case '3': case '4':
33413858Sslatteng case '5': case '6': case '7': case '8': case '9':
33513858Sslatteng /* two motion digits plus a character */
33613858Sslatteng hmot((c-'0')*10 + getc(fp)-'0');
33713858Sslatteng put1(getc(fp));
33813858Sslatteng break;
33913858Sslatteng case 'c': /* single ascii character */
34013858Sslatteng put1(getc(fp));
34113858Sslatteng break;
34213858Sslatteng case 'C':
34313858Sslatteng fscanf(fp, "%s", str);
34413858Sslatteng put1s(str);
34513858Sslatteng break;
34613858Sslatteng case 't': /* straight text */
34713858Sslatteng fgets(buf, sizeof(buf), fp);
34813858Sslatteng t_text(buf);
34913858Sslatteng break;
35013858Sslatteng case 'D': /* draw function */
35116186Sslatteng if (fgets(buf, sizeof(buf), fp) == NULL)
35216186Sslatteng error(FATAL, "unexpected end of input");;
35313858Sslatteng switch (buf[0]) {
35413858Sslatteng case 'l': /* draw a line */
35513858Sslatteng sscanf(buf+1, "%d %d", &n, &m);
35613858Sslatteng drawline(n, m);
35713858Sslatteng break;
35813858Sslatteng case 'c': /* circle */
35913858Sslatteng sscanf(buf+1, "%d", &n);
36013858Sslatteng drawcirc(n);
36113858Sslatteng break;
36213858Sslatteng case 'e': /* ellipse */
36313858Sslatteng sscanf(buf+1, "%d %d", &m, &n);
36413858Sslatteng drawellip(m, n);
36513858Sslatteng break;
36613858Sslatteng case 'a': /* arc */
36713858Sslatteng sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1);
36813858Sslatteng drawarc(n, m, n1, m1);
36913858Sslatteng break;
37016539Sslatteng case 'P': /* unbordered polygon */
37116539Sslatteng bordered = 0; /* unset border flag */
37216539Sslatteng case 'p': /* polygon */
37316539Sslatteng sscanf(buf+1, "%d", &m); /* get stipple */
37416539Sslatteng n = 1; /* number first */
37516539Sslatteng while (buf[++n] == ' ');
37616539Sslatteng while (isdigit(buf[++n]));
37716539Sslatteng setfill(m); /* set up stipple */
37816539Sslatteng drawwig(buf+n, fp, -1); /* draw polygon */
37916539Sslatteng bordered = 1; /* ALWAYS set after */
38016539Sslatteng break;
38113858Sslatteng case '~': /* wiggly line */
38216539Sslatteng drawwig(buf+1, fp, 1);
38316539Sslatteng break;
38413890Sslatteng case 'g': /* gremlin spline */
38516539Sslatteng drawwig(buf+1, fp, 0);
38613858Sslatteng break;
38713890Sslatteng case 't': /* line thickness */
38813890Sslatteng sscanf(buf+1, "%d", &n);
38913890Sslatteng drawthick(n);
39013890Sslatteng break;
39113890Sslatteng case 's': /* line style */
39213890Sslatteng sscanf(buf+1, "%d", &n);
39313890Sslatteng drawstyle(n);
39413890Sslatteng break;
39513858Sslatteng default:
39614284Sslatteng error(FATAL, "unknown drawing function %s", buf);
39713858Sslatteng break;
39813858Sslatteng }
39913858Sslatteng break;
40013858Sslatteng case 's':
40113858Sslatteng fscanf(fp, "%d", &n); /* ignore fractional sizes */
40213858Sslatteng setsize(t_size(n));
40313858Sslatteng break;
40413858Sslatteng case 'f':
40513858Sslatteng fscanf(fp, "%s", str);
40613858Sslatteng setfont(t_font(str));
40713858Sslatteng break;
40816539Sslatteng case 'i':
40916539Sslatteng fscanf(fp, "%d", &n);
41016539Sslatteng setstip(n);
41116539Sslatteng break;
41213858Sslatteng case 'H': /* absolute horizontal motion */
41313858Sslatteng /* fscanf(fp, "%d", &n); */
41413858Sslatteng while ((c = getc(fp)) == ' ')
41513858Sslatteng ;
41613858Sslatteng k = 0;
41713858Sslatteng do {
41813858Sslatteng k = 10 * k + c - '0';
41913858Sslatteng } while (isdigit(c = getc(fp)));
42013858Sslatteng ungetc(c, fp);
42113858Sslatteng hgoto(k);
42213858Sslatteng break;
42313858Sslatteng case 'h': /* relative horizontal motion */
42413858Sslatteng while ((c = getc(fp)) == ' ')
42513858Sslatteng ;
42613858Sslatteng k = 0;
42713858Sslatteng do {
42813858Sslatteng k = 10 * k + c - '0';
42913858Sslatteng } while (isdigit(c = getc(fp)));
43013858Sslatteng ungetc(c, fp);
43113858Sslatteng hmot(k);
43213858Sslatteng break;
43313858Sslatteng case 'w': /* word space */
43413858Sslatteng break;
43513858Sslatteng case 'V':
43613858Sslatteng fscanf(fp, "%d", &n);
43713858Sslatteng vgoto(n);
43813858Sslatteng break;
43913858Sslatteng case 'v':
44013858Sslatteng fscanf(fp, "%d", &n);
44113858Sslatteng vmot(n);
44213858Sslatteng break;
44313858Sslatteng case 'p': /* new page */
44413858Sslatteng fscanf(fp, "%d", &n);
44513858Sslatteng t_page(n);
44613858Sslatteng break;
44713858Sslatteng case 'n': /* end of line */
44813858Sslatteng t_newline();
44916186Sslatteng
45013858Sslatteng case '#': /* comment */
45116186Sslatteng do
45216186Sslatteng c = getc(fp);
45316186Sslatteng while (c != '\n' && c != EOF);
45413858Sslatteng break;
45513858Sslatteng case 'x': /* device control */
45615618Sslatteng if (devcntrl(fp)) return;
45713858Sslatteng break;
45813858Sslatteng default:
45914284Sslatteng error(FATAL, "unknown input character %o %c", c, c);
46013858Sslatteng }
46115283Sslatteng if (emptypos < NLINES) { /* for each input operation */
46215283Sslatteng slop_lines(1); /* put out an output line */
46315283Sslatteng #ifdef DRIVER
46415283Sslatteng if (emptypos == NLINES) {
46515283Sslatteng ioctl(OUTFILE, VSETSTATE, prtmode);
46615283Sslatteng if (write(OUTFILE, "\f", 2) != 2)
46715283Sslatteng exit(RESTART);
46815283Sslatteng ioctl(OUTFILE, VSETSTATE, pltmode);
46915283Sslatteng }
47015283Sslatteng #endif
47115283Sslatteng }
47213858Sslatteng }
47313858Sslatteng }
47413858Sslatteng
devcntrl(fp)47515618Sslatteng int devcntrl(fp) /* interpret device control functions */
47615618Sslatteng FILE *fp; /* returns -1 upon "stop" command */
47713858Sslatteng {
47813858Sslatteng char str[20], str1[50], buf[50];
47913858Sslatteng int c, n;
48013858Sslatteng
48113858Sslatteng fscanf(fp, "%s", str);
48213858Sslatteng switch (str[0]) { /* crude for now */
48313858Sslatteng case 'i': /* initialize */
48413858Sslatteng fileinit();
48513858Sslatteng t_init();
48613858Sslatteng break;
48713858Sslatteng case 't': /* trailer */
48813858Sslatteng break;
48913858Sslatteng case 'p': /* pause -- can restart */
49013858Sslatteng t_reset('p');
49113858Sslatteng break;
49213858Sslatteng case 's': /* stop */
49313858Sslatteng t_reset('s');
49415618Sslatteng return -1;
49513858Sslatteng case 'r': /* resolution assumed when prepared */
49614582Sslatteng fscanf(fp, "%d", &n);
49716539Sslatteng if (n!=RES) error(FATAL,"Input computed for wrong printer");
49813858Sslatteng break;
49913858Sslatteng case 'f': /* font used */
50013858Sslatteng fscanf(fp, "%d %s", &n, str);
50113858Sslatteng fgets(buf, sizeof buf, fp); /* in case there's a filename */
50213858Sslatteng ungetc('\n', fp); /* fgets goes too far */
50313858Sslatteng str1[0] = 0; /* in case nothing comes in */
50413858Sslatteng sscanf(buf, "%s", str1);
50513858Sslatteng loadfont(n, str, str1);
50613858Sslatteng break;
50713858Sslatteng /* these don't belong here... */
50813858Sslatteng case 'H': /* char height */
50913858Sslatteng fscanf(fp, "%d", &n);
51013858Sslatteng t_charht(n);
51113858Sslatteng break;
51213858Sslatteng case 'S': /* slant */
51313858Sslatteng fscanf(fp, "%d", &n);
51413858Sslatteng t_slant(n);
51513858Sslatteng break;
51613858Sslatteng }
51713858Sslatteng while ((c = getc(fp)) != '\n') /* skip rest of input line */
51813858Sslatteng if (c == EOF)
51915618Sslatteng return -1;
52015618Sslatteng return 0;
52113858Sslatteng }
52213858Sslatteng
52313858Sslatteng /* fileinit: read in font and code files, etc.
52413858Sslatteng Must open table for device, read in resolution,
52514582Sslatteng size info, font info, etc. and set params.
52614582Sslatteng Also read in font name mapping.
52713858Sslatteng */
52814582Sslatteng
fileinit()52913858Sslatteng fileinit()
53013858Sslatteng {
53114582Sslatteng register int i;
53214582Sslatteng register int fin;
53314582Sslatteng register int nw;
53414582Sslatteng register char *filebase;
53514582Sslatteng register char *p;
53614582Sslatteng register FILE *fp;
53714582Sslatteng char temp[100];
53813858Sslatteng
53914582Sslatteng /* first, read in font map file. The file must be of Format:
54014582Sslatteng XX FILENAME (XX = troff font name)
54114582Sslatteng with one entry per text line of the file.
54214582Sslatteng Extra stuff after FILENAME is ignored */
54314582Sslatteng
54414582Sslatteng sprintf(temp, "%s/fontmap", bitdir);
54514582Sslatteng if ((fp = fopen(temp, "r")) == NULL)
54614582Sslatteng error(FATAL, "Can't open %s", temp);
54714582Sslatteng for (i = 0; i <= NFONTS && fgets(temp, 100, fp) != NULL; i++) {
54814582Sslatteng sscanf(temp, "%2s", fontmap[i].fname);
54914582Sslatteng p = &temp[0];
55014582Sslatteng while (*p != ' ' && *p != ' ') p++;
55114582Sslatteng while (*p == ' ' || *p == ' ') p++;
55214582Sslatteng filebase = p;
55314582Sslatteng for (nw = 1; *p != '\n' && *p != ' ' && *p != '\t'; p++) nw++;
55414582Sslatteng fontmap[i].ffile = nalloc(1, nw);
55514582Sslatteng sscanf(filebase, "%s", fontmap[i].ffile);
55614582Sslatteng }
55714582Sslatteng fontmap[++i].fname[0] = '0'; /* finish off with zeros */
55814582Sslatteng fontmap[i].ffile = (char *) 0;
55914582Sslatteng fclose(fp);
56014582Sslatteng #ifdef DEBUGABLE
56114582Sslatteng if(dbg) {
56214582Sslatteng fprintf(stderr, "font map:\n");
56314582Sslatteng for (i = 0; fontmap[i].ffile; i++)
56414582Sslatteng fprintf(stderr,"%s = %s\n", fontmap[i].fname, fontmap[i].ffile);
56514582Sslatteng }
56614582Sslatteng #endif
56714582Sslatteng
56815283Sslatteng sprintf(temp, "%s/devva/DESC.out", fontdir);
56913858Sslatteng if ((fin = open(temp, 0)) < 0)
57014284Sslatteng error(FATAL, "can't open tables for %s", temp);
57113858Sslatteng read(fin, &dev, sizeof(struct dev));
57213858Sslatteng nfonts = dev.nfonts;
57316539Sslatteng nstips = dev.nstips;
57413858Sslatteng nsizes = dev.nsizes;
57513858Sslatteng nchtab = dev.nchtab;
57614582Sslatteng filebase = calloc(1, dev.filesize); /* enough room for whole file */
57713858Sslatteng read(fin, filebase, dev.filesize); /* all at once */
57813858Sslatteng pstab = (short *) filebase;
57913858Sslatteng chtab = pstab + nsizes + 1;
58013858Sslatteng chname = (char *) (chtab + dev.nchtab);
58113858Sslatteng p = chname + dev.lchname;
58213858Sslatteng for (i = 1; i <= nfonts; i++) {
58313858Sslatteng fontbase[i] = (struct font *) p;
58413858Sslatteng nw = *p & BMASK; /* 1st thing is width count */
58515176Sslatteng p += sizeof(struct font);
58613858Sslatteng widtab[i] = p;
58713858Sslatteng codetab[i] = p + 2 * nw;
58813858Sslatteng fitab[i] = p + 3 * nw;
58913858Sslatteng p += 3 * nw + dev.nchtab + 128 - 32;
59013858Sslatteng t_fp(i, fontbase[i]->namefont, fontbase[i]->intname);
59113858Sslatteng #ifdef DEBUGABLE
59213858Sslatteng if (dbg > 1) fontprint(i);
59313858Sslatteng #endif
59413858Sslatteng }
59516539Sslatteng for (i = 1; i <= nstips; i++) { /* add in stipple "filenames" */
59616539Sslatteng if (nfonts + i <= NFONTS)
59716539Sslatteng t_fp(nfonts + i, p, (char *)0);
59816539Sslatteng p += strlen(p) + 1;
59916539Sslatteng }
60013858Sslatteng fontbase[0] = (struct font *)
60113858Sslatteng calloc(1,3*255 + dev.nchtab + (128-32) + sizeof (struct font));
60213858Sslatteng widtab[0] = (char *) fontbase[0] + sizeof (struct font);
60313858Sslatteng fontbase[0]->nwfont = 255;
60413858Sslatteng close(fin);
60514582Sslatteng
60613858Sslatteng }
60713858Sslatteng
60814582Sslatteng
60916098Sslatteng #ifdef DEBUGABLE
fontprint(i)61013858Sslatteng fontprint(i) /* debugging print of font i (0,...) */
61113858Sslatteng {
61213858Sslatteng int j, n;
61313858Sslatteng char *p;
61413858Sslatteng
61513858Sslatteng fprintf(stderr,"font %d:\n", i);
61613858Sslatteng p = (char *) fontbase[i];
61713858Sslatteng n = fontbase[i]->nwfont & BMASK;
61813858Sslatteng fprintf(stderr,
61913858Sslatteng "base=0%o, nchars=%d, spec=%d, name=%s, widtab=0%o, fitab=0%o\n",p,
62013858Sslatteng n,fontbase[i]->specfont,fontbase[i]->namefont,widtab[i],fitab[i]);
62113858Sslatteng fprintf(stderr,"widths:\n");
62213858Sslatteng for (j=0; j <= n; j++) {
62313858Sslatteng fprintf(stderr," %2d", widtab[i][j] & BMASK);
62413858Sslatteng if (j % 20 == 19) fprintf(stderr,"\n");
62513858Sslatteng }
62613858Sslatteng fprintf(stderr,"\ncodetab:\n");
62713858Sslatteng for (j=0; j <= n; j++) {
62813858Sslatteng fprintf(stderr," %2d", codetab[i][j] & BMASK);
62913858Sslatteng if (j % 20 == 19) fprintf(stderr,"\n");
63013858Sslatteng }
63113858Sslatteng fprintf(stderr,"\nfitab:\n");
63213858Sslatteng for (j=0; j <= dev.nchtab + 128-32; j++) {
63313858Sslatteng fprintf(stderr," %2d", fitab[i][j] & BMASK);
63413858Sslatteng if (j % 20 == 19) fprintf(stderr,"\n");
63513858Sslatteng }
63613858Sslatteng fprintf(stderr,"\n");
63713858Sslatteng }
63816098Sslatteng #endif
63913858Sslatteng
64015618Sslatteng
loadfont(n,s,s1)64113858Sslatteng loadfont(n, s, s1) /* load font info for font s on position n (0...) */
64213858Sslatteng int n;
64313858Sslatteng char *s, *s1;
64413858Sslatteng {
64513858Sslatteng char temp[60];
64615618Sslatteng register int fin;
64715618Sslatteng register int nw;
64815618Sslatteng register int norig;
64913858Sslatteng
65013858Sslatteng if (n < 0 || n > NFONTS)
65113858Sslatteng error(FATAL, "illegal fp command %d %s", n, s);
65213858Sslatteng if (strcmp(s, fontbase[n]->namefont) == 0)
65313858Sslatteng return;
65415618Sslatteng
65515618Sslatteng for (fin = 1; fin <= NFONTS; fin++) /* first check to see if the */
65615618Sslatteng if (strcmp(s, fontbase[fin]->namefont) == 0) { /* font is loaded */
65715618Sslatteng register char *c; /* somewhere else */
65815618Sslatteng
65915618Sslatteng #define ptrswap(x, y) { c = (char*) (x); x = y; y = c; }
66016098Sslatteng #define ptrfswap(x, y) { c = (char*) (x); x = y; y = (struct font *) c; }
66115618Sslatteng
66216098Sslatteng ptrfswap(fontbase[n], fontbase[fin]);
66315618Sslatteng ptrswap(codetab[n], codetab[fin]);
66415618Sslatteng ptrswap(widtab[n], widtab[fin]);
66515618Sslatteng ptrswap(fitab[n], fitab[fin]);
66615618Sslatteng t_fp(n, fontbase[n]->namefont, fontbase[n]->intname);
66715618Sslatteng t_fp(fin, fontbase[fin]->namefont, fontbase[fin]->intname);
66815618Sslatteng return;
66915618Sslatteng }
67015618Sslatteng
67113858Sslatteng if (s1 == NULL || s1[0] == '\0')
67215283Sslatteng sprintf(temp, "%s/devva/%s.out", fontdir, s);
67313858Sslatteng else
67413858Sslatteng sprintf(temp, "%s/%s.out", s1, s);
67513858Sslatteng if ((fin = open(temp, 0)) < 0)
67613858Sslatteng error(FATAL, "can't open font table %s", temp);
67713858Sslatteng norig = fontbase[n]->nwfont & BMASK;
67813858Sslatteng read(fin, fontbase[n], 3*norig + nchtab+128-32 + sizeof(struct font));
67913858Sslatteng if ((fontbase[n]->nwfont & BMASK) > norig)
68014284Sslatteng error(FATAL, "Font %s too big for position %d", s, n);
68113858Sslatteng close(fin);
68213858Sslatteng nw = fontbase[n]->nwfont & BMASK;
68313858Sslatteng widtab[n] = (char *) fontbase[n] + sizeof(struct font);
68413858Sslatteng codetab[n] = (char *) widtab[n] + 2 * nw;
68513858Sslatteng fitab[n] = (char *) widtab[n] + 3 * nw;
68613858Sslatteng t_fp(n, fontbase[n]->namefont, fontbase[n]->intname);
68713858Sslatteng fontbase[n]->nwfont = norig; /* to later use full original size */
68813858Sslatteng #ifdef DEBUGABLE
68913858Sslatteng if (dbg > 1) fontprint(n);
69013858Sslatteng #endif
69113858Sslatteng }
69213858Sslatteng
69314284Sslatteng
69413858Sslatteng /*VARARGS1*/
error(f,s,a1,a2,a3,a4,a5,a6,a7)69513858Sslatteng error(f, s, a1, a2, a3, a4, a5, a6, a7) {
69614284Sslatteng fprintf(stderr, "dvar: ");
69713858Sslatteng fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7);
69813858Sslatteng fprintf(stderr, "\n");
69915176Sslatteng if (f) exit(ABORT);
70013858Sslatteng }
70113858Sslatteng
70213858Sslatteng
t_init()70313858Sslatteng t_init() /* initialize device */
70413858Sslatteng {
70513858Sslatteng int i;
70613858Sslatteng
70713858Sslatteng hpos = vpos = 0;
70813858Sslatteng
70913858Sslatteng setsize(t_size(10)); /* start somewhere */
71013858Sslatteng setfont(1);
71113858Sslatteng }
71213858Sslatteng
71313858Sslatteng
71413858Sslatteng struct state {
71513858Sslatteng int ssize;
71613858Sslatteng int sfont;
71713858Sslatteng int shpos;
71813858Sslatteng int svpos;
71914284Sslatteng int sstyle;
72014284Sslatteng int sthick;
72113858Sslatteng };
72213858Sslatteng struct state state[MAXSTATE];
72313858Sslatteng struct state *statep = state;
72413858Sslatteng
t_push()72513858Sslatteng t_push() /* begin a new block */
72613858Sslatteng {
72713858Sslatteng statep->ssize = size;
72813858Sslatteng statep->sfont = font;
72914284Sslatteng statep->sstyle = linmod;
73014284Sslatteng statep->sthick = linethickness;
73113858Sslatteng statep->shpos = hpos;
73213858Sslatteng statep->svpos = vpos;
73313858Sslatteng if (statep++ >= state+MAXSTATE)
73413858Sslatteng error(FATAL, "{ nested too deep");
73513858Sslatteng }
73613858Sslatteng
t_pop()73713858Sslatteng t_pop() /* pop to previous state */
73813858Sslatteng {
73913858Sslatteng if (--statep < state)
74013858Sslatteng error(FATAL, "extra }");
74113858Sslatteng size = statep->ssize;
74213858Sslatteng font = statep->sfont;
74313858Sslatteng hpos = statep->shpos;
74413858Sslatteng vpos = statep->svpos;
74514284Sslatteng linmod = statep->sstyle;
74614284Sslatteng linethickness = statep->sthick;
74713858Sslatteng }
74813858Sslatteng
t_page(n)74913858Sslatteng t_page(n) /* do whatever new page functions */
75013858Sslatteng {
75113858Sslatteng int i;
75213858Sslatteng
75313858Sslatteng
75415283Sslatteng if (emptypos < NLINES) { /* finish off last page, if */
75515283Sslatteng slop_lines(NLINES - emptypos); /* it's not done yet */
75615176Sslatteng #ifdef DRIVER
75713858Sslatteng ioctl(OUTFILE, VSETSTATE, prtmode);
75813858Sslatteng if (write(OUTFILE, "\f", 2) != 2)
75913858Sslatteng exit(RESTART);
76013858Sslatteng ioctl(OUTFILE, VSETSTATE, pltmode);
76115176Sslatteng #endif
76213858Sslatteng }
76315283Sslatteng if (output) {
76415283Sslatteng emptypos = 0; /* set emptying to be started */
76515283Sslatteng elevel = fill; /* swap buffer pointers */
76615283Sslatteng fill = empty;
76715283Sslatteng empty = elevel;
76815283Sslatteng }
76913858Sslatteng
77013858Sslatteng vpos = 0;
77113858Sslatteng output = 1;
77213858Sslatteng if (nolist == 0)
77314582Sslatteng return; /* no -o specified */
77413858Sslatteng output = 0;
77513858Sslatteng for (i = 0; i < nolist; i += 2)
77613858Sslatteng if (n >= olist[i] && n <= olist[i+1]) {
77713858Sslatteng output = 1;
77813858Sslatteng break;
77913858Sslatteng }
78013858Sslatteng }
78113858Sslatteng
t_newline()78213858Sslatteng t_newline() /* do whatever for the end of a line */
78313858Sslatteng {
78413858Sslatteng hpos = 0; /* because we're now back at the left margin */
78513858Sslatteng }
78613858Sslatteng
t_size(n)78713858Sslatteng t_size(n) /* convert integer to internal size number*/
78813858Sslatteng int n;
78913858Sslatteng {
79013858Sslatteng int i;
79113858Sslatteng
79213858Sslatteng if (n <= pstab[0])
79314582Sslatteng return(0);
79414582Sslatteng else if (n >= pstab[nsizes - 1])
79514582Sslatteng return(nsizes - 1);
79613858Sslatteng for (i = 0; n > pstab[i]; i++)
79713858Sslatteng ;
79814582Sslatteng return(i);
79913858Sslatteng }
80013858Sslatteng
t_charht(n)80113858Sslatteng t_charht(n) /* set character height to n */
80213858Sslatteng int n;
80313858Sslatteng {
80413858Sslatteng #ifdef DEBUGABLE
80514582Sslatteng if (dbg) error(!FATAL, "can't set height on varian");
80613858Sslatteng #endif
80713858Sslatteng }
80813858Sslatteng
t_slant(n)80913858Sslatteng t_slant(n) /* set slant to n */
81013858Sslatteng int n;
81113858Sslatteng {
81213858Sslatteng #ifdef DEBUGABLE
81314582Sslatteng if (dbg) error(!FATAL, "can't set slant on varian");
81413858Sslatteng #endif
81513858Sslatteng }
81613858Sslatteng
t_font(s)81713858Sslatteng t_font(s) /* convert string to internal font number */
81813858Sslatteng char *s;
81913858Sslatteng {
82013858Sslatteng int n;
82113858Sslatteng
82213858Sslatteng n = atoi(s);
82313858Sslatteng if (n < 0 || n > nfonts)
82413858Sslatteng n = 1;
82513858Sslatteng return(n);
82613858Sslatteng }
82713858Sslatteng
t_text(s)82813858Sslatteng t_text(s) /* print string s as text */
82913858Sslatteng char *s;
83013858Sslatteng {
83113858Sslatteng int c;
83213858Sslatteng char str[100];
83313858Sslatteng
83413858Sslatteng if (!output)
83513858Sslatteng return;
83613858Sslatteng while (c = *s++) {
83713858Sslatteng if (c == '\\') {
83813858Sslatteng switch (c = *s++) {
83913858Sslatteng case '\\':
84013858Sslatteng case 'e':
84113858Sslatteng put1('\\');
84213858Sslatteng break;
84313858Sslatteng case '(':
84413858Sslatteng str[0] = *s++;
84513858Sslatteng str[1] = *s++;
84613858Sslatteng str[2] = '\0';
84713858Sslatteng put1s(str);
84813858Sslatteng break;
84913858Sslatteng }
85013858Sslatteng } else {
85113858Sslatteng put1(c);
85213858Sslatteng }
85313858Sslatteng hmot(lastw);
85413858Sslatteng #ifdef DEBUGABLE
85513858Sslatteng if (dbg) fprintf(stderr,"width = %d\n", lastw);
85613858Sslatteng #endif
85713858Sslatteng }
85813858Sslatteng }
85913858Sslatteng
86015283Sslatteng
t_reset(c)86113858Sslatteng t_reset(c)
86213858Sslatteng {
86315283Sslatteng if (c == 's') {
86415283Sslatteng t_page();
86515283Sslatteng output = 0;
86615283Sslatteng t_page();
86715176Sslatteng #ifdef DRIVER
86814582Sslatteng ioctl(OUTFILE, VSETSTATE, prtmode);
86914582Sslatteng if (write(OUTFILE, "\f", 2) != 2)
87014582Sslatteng exit(RESTART);
87115176Sslatteng #endif
87213858Sslatteng }
87313858Sslatteng }
87413858Sslatteng
87513858Sslatteng
87614284Sslatteng /*----------------------------------------------------------------------------*
87714284Sslatteng | Routine: hgoto (horizontal_spot)
87814284Sslatteng |
87914284Sslatteng | Results: hpos is set to n. If n overlaps in either direction, it wraps
88014284Sslatteng | around to the other end of the page.
88114284Sslatteng *----------------------------------------------------------------------------*/
88214284Sslatteng
hgoto(n)88314284Sslatteng hgoto(n)
88414284Sslatteng int n;
88514284Sslatteng {
88614284Sslatteng if (n < 0)
88714284Sslatteng n += NLINES;
88814284Sslatteng else if (n >= NLINES)
88914284Sslatteng n -= NLINES;
89014284Sslatteng hpos = n;
89114284Sslatteng }
89214284Sslatteng
89314284Sslatteng
89414284Sslatteng /*----------------------------------------------------------------------------*
89514284Sslatteng | Routine: vgoto (vertical_spot)
89614284Sslatteng |
89714284Sslatteng | Results: vpos is set to n. If n overlaps in either direction, it wraps
89814284Sslatteng | around to the other end of the page.
89914284Sslatteng *----------------------------------------------------------------------------*/
90014284Sslatteng
vgoto(n)90113858Sslatteng vgoto(n)
90214284Sslatteng int n;
90313858Sslatteng {
90414284Sslatteng if (n < 0)
90514284Sslatteng n += RASTER_LENGTH;
90614284Sslatteng else if (n > RASTER_LENGTH)
90714284Sslatteng n -= RASTER_LENGTH;
90813858Sslatteng vpos = n;
90913858Sslatteng }
91013858Sslatteng
put1s(s)91113858Sslatteng put1s(s) /* s is a funny char name */
91213858Sslatteng char *s;
91313858Sslatteng {
91413858Sslatteng int i;
91513858Sslatteng
91613858Sslatteng if (!output)
91713858Sslatteng return;
91813858Sslatteng #ifdef DEBUGABLE
91913858Sslatteng if (dbg) fprintf(stderr,"%s ", s);
92013858Sslatteng #endif
92113858Sslatteng for (i = 0; i < nchtab; i++)
92213858Sslatteng if (strcmp(&chname[chtab[i]], s) == 0)
92313858Sslatteng break;
92413858Sslatteng if (i < nchtab)
92513858Sslatteng put1(i + 128);
92613858Sslatteng }
92713858Sslatteng
put1(c)92813858Sslatteng put1(c) /* output char c */
92913858Sslatteng int c;
93013858Sslatteng {
93113858Sslatteng char *pw;
93213858Sslatteng register char *p;
93313858Sslatteng register int i, k;
93413858Sslatteng int j, ofont, code;
93513858Sslatteng
93613858Sslatteng if (!output)
93713858Sslatteng return;
93813858Sslatteng c -= 32;
93913858Sslatteng if (c <= 0) {
94013858Sslatteng #ifdef DEBUGABLE
94113858Sslatteng if (dbg) fprintf(stderr,"non-exist 0%o\n", c + 32);
94213858Sslatteng #endif
94314582Sslatteng lastw = (widtab[font][0] * pstab[size] + dev.unitwidth/2)
94413858Sslatteng / dev.unitwidth;
94513858Sslatteng return;
94613858Sslatteng }
94713858Sslatteng k = ofont = font;
94813858Sslatteng i = fitab[font][c] & BMASK;
94913858Sslatteng if (i != 0) { /* it's on this font */
95013858Sslatteng p = codetab[font]; /* get the printing value of ch */
95113858Sslatteng pw = widtab[font]; /* get the width */
95216098Sslatteng } else { /* on another font - run down the font list */
95316098Sslatteng for (j=0; j++ <= nfonts; k = (k+1) % (nfonts+1)) {
95413858Sslatteng if (fitab[k] == 0)
95513858Sslatteng continue;
95616098Sslatteng if ((i=fitab[k][c] & BMASK) != 0) {
95713858Sslatteng p = codetab[k];
95813858Sslatteng pw = widtab[k];
95913858Sslatteng setfont(k);
96013858Sslatteng break;
96113858Sslatteng }
96213858Sslatteng }
96316098Sslatteng }
96415176Sslatteng
96516098Sslatteng if (i == 0) {
96613858Sslatteng #ifdef DEBUGABLE
96713858Sslatteng if (dbg) fprintf(stderr,"not found 0%o\n", c+32);
96813858Sslatteng #endif
96913858Sslatteng return;
97013858Sslatteng }
97116098Sslatteng code = p[i] & BMASK;
97213858Sslatteng #ifdef DEBUGABLE
97313858Sslatteng if (dbg) {
97413858Sslatteng if (isprint(c+32))
97513858Sslatteng fprintf(stderr,"%c %d\n", c+32, code);
97613858Sslatteng else
97713858Sslatteng fprintf(stderr,"%03o %d\n", c+32, code);
97813858Sslatteng }
97913858Sslatteng #endif
98013858Sslatteng outc(code); /* character is < 254 */
98113858Sslatteng if (font != ofont)
98213858Sslatteng setfont(ofont);
98314582Sslatteng lastw = ((pw[i]&077) * pstab[size] + dev.unitwidth/2) / dev.unitwidth;
98413858Sslatteng }
98513858Sslatteng
98613858Sslatteng
98713858Sslatteng
setsize(n)98813858Sslatteng setsize(n) /* set point size to n (internal) */
98913858Sslatteng int n;
99013858Sslatteng {
99113858Sslatteng
99213858Sslatteng if (n == size)
99313858Sslatteng return; /* already there */
99414582Sslatteng if (vloadfont(font, pstab[n]) != -1)
99513858Sslatteng size = n;
99613858Sslatteng }
99713858Sslatteng
t_fp(n,s,si)99813858Sslatteng t_fp(n, s, si) /* font position n now contains font s, intname si */
99915176Sslatteng int n; /* internal name is ignored */
100013858Sslatteng char *s, *si;
100113858Sslatteng {
100214582Sslatteng register int i;
100313858Sslatteng
100414582Sslatteng
100514582Sslatteng /* first convert s to filename if possible */
100614582Sslatteng for (i = 0; fontmap[i].ffile != (char *) 0; i++) {
100714582Sslatteng #ifdef DEBUGABLE
100814582Sslatteng if(dbg>1)fprintf(stderr,"testing :%s:%s:\n",s,fontmap[i].fname);
100914582Sslatteng #endif
101014582Sslatteng if (strcmp(s, fontmap[i].fname) == 0) {
101114582Sslatteng s = fontmap[i].ffile;
101214582Sslatteng #ifdef DEBUGABLE
101314582Sslatteng if(dbg)fprintf(stderr, "found :%s:\n",fontmap[i].ffile);
101414582Sslatteng #endif
101514582Sslatteng break;
101614582Sslatteng }
101714582Sslatteng }
101815176Sslatteng fontname[n] = s;
101915283Sslatteng for(i = 0;i <= NFONTS;i++) /* free the bits of that font */
102013858Sslatteng if (fontdes[i].fnum == n){
102113858Sslatteng nfree(fontdes[i].bits);
102213858Sslatteng fontdes[i].fnum = -1;
102313858Sslatteng }
102413858Sslatteng }
102513858Sslatteng
102614582Sslatteng
setfont(n)102713858Sslatteng setfont(n) /* set font to n */
102813858Sslatteng int n;
102913858Sslatteng {
103016539Sslatteng if (n < 0 || n > nfonts)
103114284Sslatteng error(FATAL, "illegal font %d", n);
103214582Sslatteng if (vloadfont(n,pstab[size]) != -1)
103313858Sslatteng font = n;
103413858Sslatteng }
103513858Sslatteng
103616539Sslatteng
setstip(n)103716539Sslatteng setstip(n) /* set stipple font to n */
103816539Sslatteng int n;
103916539Sslatteng {
104016539Sslatteng if (n < 1 || n > nstips)
104116539Sslatteng error(FATAL, "illegal stipple %d", n);
104216539Sslatteng stip = n;
104316539Sslatteng }
104416539Sslatteng
104516539Sslatteng
vloadfont(fnum,fsize)104613858Sslatteng vloadfont(fnum, fsize)
104713858Sslatteng register int fnum;
104813858Sslatteng register int fsize;
104913858Sslatteng {
105013858Sslatteng register int i;
105113858Sslatteng
105213858Sslatteng fontwanted = 0;
105313858Sslatteng if (fnum == cfnum && fsize == cpsize)
105413858Sslatteng return(0);
105513858Sslatteng for (i = 0; i < NFONTS; i++) {
105613858Sslatteng if (fontdes[i].fnum == fnum && fontdes[i].psize == fsize) {
105713858Sslatteng cfnum = fontdes[i].fnum;
105813858Sslatteng cpsize = fontdes[i].psize;
105913858Sslatteng dispatch = &fontdes[i].disp[0];
106013858Sslatteng bits = fontdes[i].bits;
106113858Sslatteng cfont = i;
106213858Sslatteng return (0);
106313858Sslatteng }
106413858Sslatteng }
106513858Sslatteng /* this is a new font */
106615176Sslatteng if (fnum < 0 || fnum > NFONTS || fontname[fnum] == 0) {
106717226Sslatteng error(!FATAL,"error: illegal font %d, size %d\n", fnum, fsize);
106813858Sslatteng return(-1);
106913858Sslatteng }
107013858Sslatteng /* Need to verify the existance of that font/size here*/
107113858Sslatteng nfontnum = fnum;
107213858Sslatteng npsize = fsize;
107313858Sslatteng fontwanted++;
107413858Sslatteng return (0);
107513858Sslatteng }
107613858Sslatteng
107713858Sslatteng
getfont()107813858Sslatteng getfont()
107913858Sslatteng {
108014582Sslatteng register int fnum;
108114582Sslatteng register int fsize;
108214582Sslatteng register int fontd;
108314582Sslatteng register int d;
108415176Sslatteng register int sizehunt = size;
108513858Sslatteng char cbuf[BUFSIZ];
108613858Sslatteng
108713858Sslatteng fnum = nfontnum;
108813858Sslatteng fsize = npsize;
108914582Sslatteng /* try to open font file - if unsuccessful, hunt for */
109014582Sslatteng /* a file of same style, different size to substitute */
109115176Sslatteng d = -1; /* direction to look in pstab (smaller first) */
109214582Sslatteng do {
109315176Sslatteng sprintf(cbuf, "%s/%s.%dr", bitdir, fontname[fnum], fsize);
109414582Sslatteng fontd = open(cbuf, OPENREAD);
109514582Sslatteng if (fontd == -1) { /* File wasn't found. Try another ps */
109615176Sslatteng sizehunt += d;
109715176Sslatteng if (sizehunt < 0) { /* past beginning - look higher */
109814582Sslatteng d = 1;
109915176Sslatteng sizehunt = size + 1;
110014582Sslatteng }
110115176Sslatteng if (sizehunt > nsizes) { /* past top - forget it */
110214582Sslatteng d = 0;
110314582Sslatteng } else {
110415176Sslatteng fsize = pstab[sizehunt];
110514582Sslatteng }
110614582Sslatteng }
110714582Sslatteng } while (fontd == -1 && d != 0);
110814582Sslatteng
110914582Sslatteng if (fontd == -1) { /* completely unsuccessful */
111014582Sslatteng perror(cbuf);
111114582Sslatteng error(!FATAL,"fnum = %d, psize = %d, name = %s",
111215176Sslatteng fnum, npsize, fontname[fnum]);
111314582Sslatteng fontwanted = 0;
111414582Sslatteng return (-1);
111513858Sslatteng }
111613858Sslatteng if (read(fontd, &header, sizeof (header)) != sizeof (header)
111713858Sslatteng || header.magic != 0436)
111813858Sslatteng fprintf(stderr, "%s: Bad font file", cbuf);
111913858Sslatteng else {
112013858Sslatteng cfont = relfont();
112113858Sslatteng if ((bits=nalloc(header.size+DSIZ+1,1))== NULL)
112213858Sslatteng if ((bits=allpanic(header.size+DSIZ+1))== NULL) {
112315176Sslatteng error(FATAL,"%s: ran out of memory", cbuf);
112413858Sslatteng }
112513858Sslatteng
112613858Sslatteng /*
112713858Sslatteng * have allocated one chunk of mem for font, dispatch.
112813858Sslatteng * get the dispatch addr, align to word boundary.
112913858Sslatteng */
113013858Sslatteng
113113858Sslatteng d = (int) bits+header.size;
113213858Sslatteng d += 1;
113313858Sslatteng d &= ~1;
113413858Sslatteng if (read (fontd, d, DSIZ) != DSIZ
113513858Sslatteng || read (fontd, bits, header.size) != header.size)
113613858Sslatteng fprintf(stderr, "bad font header");
113713858Sslatteng else {
113813858Sslatteng close(fontd);
113913858Sslatteng cfnum = fontdes[cfont].fnum = fnum;
114013858Sslatteng cpsize = fontdes[cfont].psize = fsize;
114113858Sslatteng fontdes [cfont].bits = bits;
114213858Sslatteng fontdes [cfont].disp = (struct dispatch *) d;
114313858Sslatteng dispatch = &fontdes[cfont].disp[0];
114413858Sslatteng fontwanted = 0;
114513858Sslatteng return (0);
114613858Sslatteng }
114713858Sslatteng }
114813858Sslatteng close(fontd);
114913858Sslatteng fontwanted = 0;
115013858Sslatteng return(-1);
115113858Sslatteng }
115213858Sslatteng
115313858Sslatteng /*
115413858Sslatteng * "release" a font position - find an empty one, if possible
115513858Sslatteng */
115613858Sslatteng
relfont()115713858Sslatteng relfont()
115813858Sslatteng {
115913858Sslatteng register int newfont;
116013858Sslatteng
116113858Sslatteng for (newfont = 0; newfont < NFONTS; newfont++)
116215283Sslatteng if (fontdes [newfont].fnum == -1)
116313858Sslatteng break;
116415283Sslatteng if (fontdes [newfont].fnum != -1) {
116513858Sslatteng nfree (fontdes [newfont].bits);
116613858Sslatteng #ifdef DEBUGABLE
116713858Sslatteng if (dbg) fprintf (stderr, "freeing position %d\n", newfont);
116813858Sslatteng } else {
116913858Sslatteng if (dbg)
117013858Sslatteng fprintf (stderr, "taking, not freeing, position %d\n", newfont);
117113858Sslatteng #endif
117213858Sslatteng }
117315283Sslatteng fontdes[newfont].fnum = -1;
117413858Sslatteng return (newfont);
117513858Sslatteng }
117613858Sslatteng
allpanic(nbytes)117713858Sslatteng char *allpanic (nbytes)
117813858Sslatteng int nbytes;
117913858Sslatteng {
118013858Sslatteng register int i;
118113858Sslatteng
118213858Sslatteng for (i = 0; i <= NFONTS; i++) {
118315283Sslatteng if (fontdes[i].fnum != -1) nfree(fontdes[i].bits);
118415283Sslatteng fontdes[i].fnum = -1;
118513858Sslatteng cfnum = cpsize = -1;
118613858Sslatteng }
118713858Sslatteng return(nalloc(nbytes,1));
118813858Sslatteng }
118913858Sslatteng
119013858Sslatteng int M[] = { 0xffffffff, 0xfefefefe, 0xfcfcfcfc, 0xf8f8f8f8,
119113858Sslatteng 0xf0f0f0f0, 0xe0e0e0e0, 0xc0c0c0c0, 0x80808080, 0x0 };
119213858Sslatteng int N[] = { 0x00000000, 0x01010101, 0x03030303, 0x07070707,
119313858Sslatteng 0x0f0f0f0f, 0x1f1f1f1f, 0x3f3f3f3f, 0x7f7f7f7f, 0xffffffff };
119413858Sslatteng int strim[] = { 0xffffffff, 0xffffff00, 0xffff0000, 0xff000000, 0 };
119513858Sslatteng
outc(code)119613858Sslatteng outc(code)
119713858Sslatteng int code; /* character to print */
119813858Sslatteng {
119913858Sslatteng register struct dispatch *dis; /* ptr to character font record */
120013858Sslatteng register char *addr; /* addr of font data */
120113858Sslatteng int llen; /* length of each font line */
120213858Sslatteng int nlines; /* number of font lines */
120313858Sslatteng register char *scanp; /* ptr to output buffer */
120413858Sslatteng int scanp_inc; /* increment to start of next buffer */
120513858Sslatteng int offset; /* bit offset to start of font data */
120614582Sslatteng register int i; /* loop counter */
120713858Sslatteng register int count; /* font data ptr */
120813858Sslatteng register unsigned fontdata; /* font data temporary */
120913858Sslatteng register int off8; /* offset + 8 */
121013858Sslatteng
121113858Sslatteng if (fontwanted)
121213858Sslatteng getfont();
121313858Sslatteng dis = dispatch + code;
121413858Sslatteng if (dis->nbytes) {
121513858Sslatteng addr = bits + dis->addr;
121613890Sslatteng llen = (dis->up + dis->down + 7) >> 3;
121713890Sslatteng nlines = dis->right + dis->left;
121815283Sslatteng scanp = fill + (hpos + 1 - dis->left) * BYTES_PER_LINE
121915283Sslatteng - (1 + ((dis->down + vpos - 1) >> 3));
122015283Sslatteng if (scanp < fill)
122115283Sslatteng scanp += BUFFER_SIZE;
122213858Sslatteng scanp_inc = BYTES_PER_LINE - llen;
122315283Sslatteng off8 = ((dis->down + vpos - 1) &07);
122413890Sslatteng offset = off8 - 8;
122513858Sslatteng for (i = 0; i < nlines; i++) {
122615283Sslatteng if (scanp >= fill + BUFFER_SIZE)
122715176Sslatteng scanp -= BUFFER_SIZE;
122813858Sslatteng count = llen;
122915283Sslatteng if (scanp + count < fill + BUFFER_SIZE) {
123013858Sslatteng do {
123113858Sslatteng fontdata = *(unsigned *)addr;
123213858Sslatteng addr += 4;
123313858Sslatteng if (count < 4)
123413858Sslatteng fontdata &= ~strim[count];
123513858Sslatteng *(unsigned*)scanp |=(fontdata << offset) & ~M[off8];
123613858Sslatteng scanp++;
123713858Sslatteng *(unsigned*)scanp |=(fontdata << off8) & ~N[off8];
123813858Sslatteng scanp += 3;
123913858Sslatteng count -= 4;
124013858Sslatteng } while (count > 0);
124113858Sslatteng }
124213858Sslatteng scanp += scanp_inc+count;
124313858Sslatteng addr += count;
124413858Sslatteng }
124513858Sslatteng return;
124613858Sslatteng }
124713858Sslatteng return;
124813858Sslatteng }
124913858Sslatteng
125016539Sslatteng
125116539Sslatteng /*----------------------------------------------------------------------------*
125216539Sslatteng | Routine: setfill(stipple_number)
125316539Sslatteng |
125416539Sslatteng | Results: sets the fill-pattern pointers (stip_disp and
125516539Sslatteng | stip_bits) for a particular stipple. Takes stipple
125616539Sslatteng | font from current "stip" number.
125716539Sslatteng *----------------------------------------------------------------------------*/
125816539Sslatteng
setfill(number)125916539Sslatteng setfill(number)
126016539Sslatteng int number;
126116539Sslatteng {
126216539Sslatteng int curfont; /* places to save current text font */
126316539Sslatteng int cursize;
126416539Sslatteng
126516539Sslatteng /* set global stipmem for polygon */
126616539Sslatteng if (number < 0 || number >= DISPATCHSIZE)
126716539Sslatteng stipmem = 0;
126816539Sslatteng else
126916539Sslatteng stipmem = number;
127016539Sslatteng
127116539Sslatteng curfont = cfnum; /* get pointers to */
127216539Sslatteng cursize = cpsize; /* the inuse font */
127316539Sslatteng if (vloadfont(nfonts + stip, 0)) {
127416539Sslatteng stip_disp = (struct dispatch *) NULL; /* stipple not here */
127516539Sslatteng } else {
127616539Sslatteng if (fontwanted) {
127716539Sslatteng if (getfont()) {
127816539Sslatteng stip_disp = (struct dispatch *) NULL;
127916539Sslatteng } else {
128016539Sslatteng stip_disp = dispatch; /* save for polygon routine */
128116539Sslatteng stip_bits = bits;
128216539Sslatteng }
128316539Sslatteng } else {
128416539Sslatteng stip_disp = dispatch; /* save for polygon routine */
128516539Sslatteng stip_bits = bits;
128616539Sslatteng }
128716539Sslatteng }
128817226Sslatteng if (curfont >= 0) vloadfont(curfont, cursize);
128916539Sslatteng }
129016539Sslatteng
129116539Sslatteng
slop_lines(nlines)129213858Sslatteng slop_lines(nlines)
129313858Sslatteng int nlines;
129413858Sslatteng
129513858Sslatteng /* Output "nlines" lines from the buffer, and clear that section of the */
129615283Sslatteng /* buffer. Also updates the pointers to the emptying buffer */
129713858Sslatteng
129813858Sslatteng {
129913858Sslatteng unsigned usize;
130013858Sslatteng
130113858Sslatteng usize = BYTES_PER_LINE * nlines;
130215283Sslatteng vwrite(elevel, usize);
130315283Sslatteng vclear(elevel, usize);
130415283Sslatteng elevel += usize;
130515283Sslatteng emptypos += nlines;
130613858Sslatteng }
130713858Sslatteng
vwrite(buf,usize)130814582Sslatteng vwrite(buf,usize)
130913858Sslatteng char *buf;
131013858Sslatteng unsigned usize;
131113858Sslatteng {
131213858Sslatteng register int tsize = 0;
131313858Sslatteng
131413858Sslatteng while (usize){
131513858Sslatteng buf += tsize;
131613858Sslatteng tsize = usize > MAXWRIT ? MAXWRIT : usize;
131713858Sslatteng #ifdef DEBUGABLE
131813858Sslatteng if (dbg)fprintf(stderr,"buf = %d size = %d\n",buf,tsize);
131913858Sslatteng #endif
132013858Sslatteng if ((tsize = write(OUTFILE, buf, tsize)) < 0) {
132114284Sslatteng perror("dvar: write failed");
132213858Sslatteng exit(RESTART);
132313858Sslatteng }
132413858Sslatteng usize -= tsize;
132513858Sslatteng }
132613858Sslatteng }
132713858Sslatteng
vclear(ptr,nbytes)132813858Sslatteng vclear (ptr, nbytes)
132913858Sslatteng char *ptr;
133013858Sslatteng unsigned nbytes;
133113858Sslatteng {
133213858Sslatteng register tsize = 0;
133313858Sslatteng
133413858Sslatteng while (nbytes){
133513858Sslatteng if ((unsigned)(16*1024) < nbytes) {
133613858Sslatteng tsize = 16 * 1024;
133713858Sslatteng } else
133813858Sslatteng tsize = nbytes;
133913858Sslatteng nbytes -= tsize;
134013858Sslatteng #ifdef DEBUGABLE
134113858Sslatteng if (dbg) fprintf(stderr,"clearing ptr = %d size = %d\n",ptr,tsize);
134213858Sslatteng #endif
134313858Sslatteng clear(ptr,tsize);
134413858Sslatteng ptr += tsize;
134513858Sslatteng }
134613858Sslatteng }
134713858Sslatteng
134813858Sslatteng /*ARGSUSED*/
clear(lp,nbytes)134913858Sslatteng clear(lp, nbytes)
135013858Sslatteng int *lp;
135113858Sslatteng int nbytes;
135213858Sslatteng {
1353*24165Sslatteng #ifdef vax
135413858Sslatteng asm("movc5 $0,(sp),$0,8(ap),*4(ap)");
1355*24165Sslatteng #else
1356*24165Sslatteng register int i = nbytes;
1357*24165Sslatteng register int *cp = lp;
1358*24165Sslatteng
1359*24165Sslatteng while (i-- > 0)
1360*24165Sslatteng *(cp++) = 0;
1361*24165Sslatteng #endif
136213858Sslatteng }
136313858Sslatteng
136413858Sslatteng char *
nalloc(i,j)136513858Sslatteng nalloc(i, j)
136613858Sslatteng int i, j;
136713858Sslatteng {
136813858Sslatteng register char *cp;
136913858Sslatteng
137013858Sslatteng cp = calloc(i, j);
137113858Sslatteng #ifdef DEBUGABLE
137213858Sslatteng if (dbg) fprintf(stderr, "allocated %d bytes at %x\n", i * j, cp);
137313858Sslatteng #endif
137413858Sslatteng return(cp);
137513858Sslatteng }
137613858Sslatteng
nfree(cp)137713858Sslatteng nfree(cp)
137813858Sslatteng char *cp;
137913858Sslatteng {
138013858Sslatteng #ifdef DEBUGABLE
138113858Sslatteng if (dbg) fprintf(stderr, "freeing at %x\n", cp);
138213858Sslatteng #endif
138313858Sslatteng free(cp);
138413858Sslatteng }
138513858Sslatteng
138613858Sslatteng
138713858Sslatteng /*
138813858Sslatteng * Points should be in the range 0 <= x < RASTER_LENGTH, 0 <= y < NLINES.
138913858Sslatteng * The origin is the top left-hand corner with increasing x towards the
139014582Sslatteng * right and increasing y going down. X and Y should be sent as (0,0) being
139114582Sslatteng * at the bottom left. The output array is NLINES x BYTES_PER_LINE pixels.
139213858Sslatteng */
point(x,y)139313858Sslatteng point(x, y)
139413890Sslatteng register int x;
139513890Sslatteng register int y;
139613858Sslatteng {
139716539Sslatteng if ((unsigned)(y=(RASTER_LENGTH-1)-y)<RASTER_LENGTH && (unsigned)x<NLINES) {
139815283Sslatteng *(fill + x * BYTES_PER_LINE + (y >> 3)) |= 1 << (7 - (y & 07));
139913858Sslatteng }
140013858Sslatteng }
140116539Sslatteng
140216539Sslatteng
140316539Sslatteng #define pv(x) ((polyvector *)x)
140416539Sslatteng
140516539Sslatteng typedef struct poly {
140616539Sslatteng struct poly *next; /* doublely-linked lists of vectors */
140716539Sslatteng struct poly *prev;
140816539Sslatteng int param; /* bressenham line algorithm parameter */
140916539Sslatteng short dy; /* delta-y for calculating line */
141016539Sslatteng short dx; /* delta-x for calculating line */
141116539Sslatteng short curry; /* current y in this vector */
141216539Sslatteng short endx; /* where vector ends */
141316539Sslatteng } polyvector;
141416539Sslatteng
141516539Sslatteng
141616539Sslatteng /*----------------------------------------------------------------------------*
141716539Sslatteng | Routine: polygon ( x_coordinates, y_coordinates, num_of_points )
141816539Sslatteng |
141916539Sslatteng | Results: draws a polygon starting at (x[1], y[1]) going through
142016539Sslatteng | each of (x_coordinates, y_coordinates), and fills it
142116539Sslatteng | with a stipple pattern from stip_disp and stip_bits,
142216539Sslatteng | which point to the stipple font. The pattern is defined
142316539Sslatteng | by "stip" and "stipmem".
142416539Sslatteng |
142516539Sslatteng | The scan-line algorithm implemented scans from left to
142616539Sslatteng | right (low x to high x). It also scans, within a line,
142716539Sslatteng | from bottom to top (high y to low y).
142816539Sslatteng |
142916539Sslatteng | polygons are clipped to page boundary.
143016539Sslatteng |
143116539Sslatteng | Bugs: stipple pattern MUST be a power of two bytes "wide" and
143216539Sslatteng | square. The square restriction comes from the fact that
143316539Sslatteng | the varian and versatec are respectively rotated.
143416539Sslatteng *----------------------------------------------------------------------------*/
143516539Sslatteng
polygon(x,y,npts)143616539Sslatteng polygon(x, y, npts)
143716539Sslatteng int x[];
143816539Sslatteng int y[];
143916539Sslatteng int npts;
144016539Sslatteng {
144116539Sslatteng int nextx; /* at what x value the next vector starts */
144216539Sslatteng int maxx, minx, maxy, miny; /* finds bounds of polygon */
144316539Sslatteng polyvector *activehead; /* doing fill, is active edge list */
144416539Sslatteng polyvector *waitinghead; /* edges waiting to be active */
144516539Sslatteng register polyvector *vectptr; /* random vector */
144616539Sslatteng register int i; /* random register */
144716539Sslatteng
144816539Sslatteng char *topstipple; /* points to beginning of stipple glyph */
144916539Sslatteng char *leftstipple; /* points to beginning of line of stipple */
145016539Sslatteng char *bottompage; /* points to the edge of a raster line */
145116539Sslatteng int bytewidth; /* glyph width in bytes */
145216539Sslatteng int mask; /* mask to pick off pixel index into stipple */
145316539Sslatteng int bytemask; /* mask to pick off byte index into stipple */
145416539Sslatteng
145516539Sslatteng
145616539Sslatteng if (bordered) {
145716539Sslatteng for (i = 1; i < npts; i++) /* first draw outlines */
145816539Sslatteng HGtline(x[i], y[i], x[i+1], y[i+1]);
145916539Sslatteng }
146016539Sslatteng
146116539Sslatteng /* if no stipple, don't fill */
146216539Sslatteng if (stip_disp == (struct dispatch *) NULL || stip_bits == (char *) NULL)
146316539Sslatteng return;
146416539Sslatteng
146516539Sslatteng stip_disp += stipmem; /* set up parameters for */
146616539Sslatteng if (!stip_disp->nbytes) { /* tiling with the stipple */
146716539Sslatteng #ifdef DEBUGABLE
146816539Sslatteng error(!FATAL, "member not found: member %d, stipple %d", stipmem, stip);
146916539Sslatteng #endif
147016539Sslatteng return;
147116539Sslatteng }
147216539Sslatteng topstipple = stip_bits + stip_disp->addr;
147316539Sslatteng bytewidth = stip_disp->up + stip_disp->down;
147416539Sslatteng for (i = 1 << 30; i && i != bytewidth; i = i >> 1)
147516539Sslatteng ;
147616539Sslatteng if (i==0 || bytewidth<8 || bytewidth != stip_disp->right+stip_disp->left) {
147716539Sslatteng error(!FATAL, "invalid stipple: number %d, member %d", stip, stipmem);
147816539Sslatteng return;
147916539Sslatteng }
148016539Sslatteng mask = bytewidth - 1;
148116539Sslatteng bytewidth = bytewidth >> 3;
148216539Sslatteng bytemask = bytewidth - 1;
148316539Sslatteng
148416539Sslatteng /* allocate space for raster-fill algorithm*/
148516539Sslatteng if ((vectptr = pv( nalloc(sizeof(polyvector), npts + 6) )) == NULL) {
148616539Sslatteng error(!FATAL, "unable to allocate space for polygon");
148716539Sslatteng return;
148816539Sslatteng }
148916539Sslatteng #ifdef DEBUGABLE
149016539Sslatteng if (dbg) fprintf(stderr, "polygon, %d points\n", npts);
149116539Sslatteng #endif
149216539Sslatteng
149316539Sslatteng waitinghead = vectptr;
149416539Sslatteng minx = maxx = x[1];
149516539Sslatteng miny = maxy = y[1];
149616539Sslatteng (vectptr++)->prev = pv( NULL ); /* put dummy entry at start */
149716539Sslatteng waitinghead->next = vectptr;
149816539Sslatteng vectptr->prev = waitinghead;
149916539Sslatteng i = 1; /* starting point of coords */
150016539Sslatteng if (y[1] != y[npts] || x[1] != x[npts]) {
150116539Sslatteng y[0] = y[npts]; /* close polygon if it's not */
150216539Sslatteng x[0] = x[npts];
150316539Sslatteng i = 0;
150416539Sslatteng }
150516539Sslatteng while (i < npts) { /* set up the vectors */
150616539Sslatteng register int j; /* indexes to work off of */
150716539Sslatteng register int k;
150816539Sslatteng
150916539Sslatteng if (miny > y[i]) miny = y[i]; /* remember limits */
151016539Sslatteng else if (maxy < y[i]) maxy = y[i];
151116539Sslatteng if (maxx < x[i]) maxx = x[i];
151216539Sslatteng else if (minx > x[i]) minx = x[i];
151316539Sslatteng
151416539Sslatteng j = i; /* j "points" to the higher (lesser) point */
151516539Sslatteng k = ++i;
151616539Sslatteng if (x[j] == x[k]) /* ignore vertical lines */
151716539Sslatteng continue;
151816539Sslatteng
151916539Sslatteng if (x[j] > x[k]) {
152016539Sslatteng j++;
152116539Sslatteng k--;
152216539Sslatteng }
152316539Sslatteng vectptr->next = vectptr + 1;
152416539Sslatteng vectptr->param = x[j]; /* starting point of vector */
152516539Sslatteng vectptr->dy = y[k] - y[j]; /* line-calculating parameters */
152616539Sslatteng vectptr->dx = x[k] - x[j];
152716539Sslatteng vectptr->curry = y[j]; /* starting point */
152816539Sslatteng (vectptr++)->endx = x[k]; /* ending point */
152916539Sslatteng vectptr->prev = vectptr - 1;
153016539Sslatteng }
153116539Sslatteng /* set now because we didn't know minx before */
153216539Sslatteng leftstipple = topstipple + (minx & mask) * bytewidth;
153316539Sslatteng bottompage = fill + minx * BYTES_PER_LINE;
153416539Sslatteng waitinghead->param = minx - 1;
153516539Sslatteng /* if no useable vectors, quit */
153616539Sslatteng if (vectptr == waitinghead + 1)
153716539Sslatteng goto leavepoly;
153816539Sslatteng
153916539Sslatteng vectptr->param = maxx + 1; /* dummy entry at end, too */
154016539Sslatteng vectptr->next = pv( NULL );
154116539Sslatteng
154216539Sslatteng activehead = ++vectptr; /* two dummy entries for active list */
154316539Sslatteng vectptr->curry = maxy + 1; /* head */
154416539Sslatteng vectptr->endx = maxx + 1;
154516539Sslatteng vectptr->param = vectptr->dx = vectptr->dy = 0;
154616539Sslatteng activehead->next = ++vectptr;
154716539Sslatteng activehead->prev = vectptr;
154816539Sslatteng
154916539Sslatteng vectptr->prev = activehead; /* tail */
155016539Sslatteng vectptr->next = activehead;
155116539Sslatteng vectptr->curry = miny - 1;
155216539Sslatteng vectptr->endx = maxx + 1;
155316539Sslatteng vectptr->param = vectptr->dx = vectptr->dy = 0;
155416539Sslatteng
155516539Sslatteng
155616539Sslatteng /* main loop -- gets vectors off the waiting list, */
155716539Sslatteng /* then displays spans while updating the vectors in */
155816539Sslatteng /* the active list */
155916539Sslatteng while (minx <= maxx) {
156016539Sslatteng i = maxx + 1; /* this is the NEXT time to get a new vector */
156116539Sslatteng for (vectptr = waitinghead->next; vectptr != pv( NULL ); ) {
156216539Sslatteng if (minx == vectptr->param) {
156316539Sslatteng /* the entry in waiting list (vectptr) is */
156416539Sslatteng /* ready to go into active list. Need to */
156516539Sslatteng /* convert some vector stuff and sort the */
156616539Sslatteng /* entry into the list. */
156716539Sslatteng register polyvector *p; /* random vector pointers */
156816539Sslatteng register polyvector *v;
156916539Sslatteng
157016539Sslatteng /* convert this */
157116539Sslatteng if (vectptr->dy < 0) /* entry to active */
157216539Sslatteng vectptr->param = (vectptr->dy >> 1) - (vectptr->dx >> 1);
157316539Sslatteng else
157416539Sslatteng vectptr->param = -((vectptr->dx >> 1) + (vectptr->dy >> 1));
157516539Sslatteng
157616539Sslatteng p = vectptr; /* remove from the */
157716539Sslatteng vectptr = vectptr->next; /* waiting list */
157816539Sslatteng vectptr->prev = p->prev;
157916539Sslatteng p->prev->next = vectptr;
158016539Sslatteng /* find where it goes */
158116539Sslatteng /* in the active list */
158216539Sslatteng /* (sorted greatest first) */
158316539Sslatteng for (v = activehead->next; v->curry > p->curry; v = v->next)
158416539Sslatteng ;
158516539Sslatteng p->next = v; /* insert into active list */
158616539Sslatteng p->prev = v->prev; /* before the one it stopped on */
158716539Sslatteng v->prev = p;
158816539Sslatteng p->prev->next = p;
158916539Sslatteng } else {
159016539Sslatteng if (i > vectptr->param) {
159116539Sslatteng i = vectptr->param;
159216539Sslatteng }
159316539Sslatteng vectptr = vectptr->next;
159416539Sslatteng }
159516539Sslatteng }
159616539Sslatteng nextx = i;
159716539Sslatteng
159816539Sslatteng /* print the polygon while there */
159916539Sslatteng /* are no more vectors to add */
160016539Sslatteng while (minx < nextx) {
160116539Sslatteng /* remove any finished vectors */
160216539Sslatteng vectptr = activehead->next;
160316539Sslatteng do {
160416539Sslatteng if (vectptr->endx <= minx) {
160516539Sslatteng vectptr->prev->next = vectptr->next;
160616539Sslatteng vectptr->next->prev = vectptr->prev;
160716539Sslatteng }
160816539Sslatteng } while ((vectptr = vectptr->next) != activehead);
160916539Sslatteng
161016539Sslatteng /* draw the span */
161116539Sslatteng if (((unsigned) minx) < NLINES) {
161216539Sslatteng vectptr = activehead->next;
161316539Sslatteng while (vectptr->next != activehead) {
161416539Sslatteng register int start; /* get the beginning */
161516539Sslatteng register int length; /* and the end of span */
161616539Sslatteng register char *glyph;
161716539Sslatteng register char *raster;
161816539Sslatteng
161916539Sslatteng start = (RASTER_LENGTH - 1) - vectptr->curry;
162016539Sslatteng vectptr = vectptr->next;
162116539Sslatteng length = RASTER_LENGTH - vectptr->curry;
162216539Sslatteng vectptr = vectptr->next;
162316539Sslatteng
162416539Sslatteng /* bound the polygon to the page */
162516539Sslatteng if (start >= RASTER_LENGTH)
162616539Sslatteng break;
162716539Sslatteng if (start < 0) start = 0;
162816539Sslatteng if (length > RASTER_LENGTH) length = RASTER_LENGTH;
162916539Sslatteng length -= start; /* length is in pixels */
163016539Sslatteng
163116539Sslatteng i = start & 7;
163216539Sslatteng start = start >> 3; /* start is in bytes */
163316539Sslatteng raster = bottompage + start;
163416539Sslatteng glyph = leftstipple + (start & bytemask);
163516539Sslatteng
163616539Sslatteng if (i) { /* do any piece of byte */
163716539Sslatteng register char data; /* that hangs on the front */
163816539Sslatteng
163916539Sslatteng data = (*(glyph++)) & (0x7f >> --i);
164016539Sslatteng length -= 7 - i;
164116539Sslatteng if (length < 0) { /* less than one byte wide? */
164216539Sslatteng data &= 0xff << -length;
164316539Sslatteng length = 0; /* force clean stoppage */
164416539Sslatteng }
164516539Sslatteng *(raster++) |= data;
164616539Sslatteng /* update glyph ptr after first byte */
164716539Sslatteng if (!(++start & bytemask))
164816539Sslatteng glyph = leftstipple;
164916539Sslatteng }
165016539Sslatteng /* fill the line of raster */
165116539Sslatteng while ((length -= 8) >= 0) {
165216539Sslatteng *(raster++) |= *(glyph++);
165316539Sslatteng if (!(++start & bytemask))
165416539Sslatteng glyph = leftstipple;
165516539Sslatteng }
165616539Sslatteng if (length & 7) { /* add any part hanging off the end */
165716539Sslatteng *raster |= (*glyph) & (0xff << -length);
165816539Sslatteng }
165916539Sslatteng }
166016539Sslatteng }
166116539Sslatteng
166216539Sslatteng #ifdef DEBUGABLE
166316539Sslatteng if (dbg) {
166416539Sslatteng vectptr = activehead;
166516539Sslatteng do {
166616539Sslatteng fprintf (stderr, "%d ", vectptr->curry);
166716539Sslatteng vectptr = vectptr->next;
166816539Sslatteng } while (vectptr != activehead);
166916539Sslatteng }
167016539Sslatteng #endif
167116539Sslatteng /* update the vectors */
167216539Sslatteng vectptr = activehead->next;
167316539Sslatteng do {
167416539Sslatteng if (vectptr->dy > 0) {
167516539Sslatteng while (vectptr->param >= 0) {
167616539Sslatteng vectptr->param -= vectptr->dx;
167716539Sslatteng vectptr->curry++;
167816539Sslatteng }
167916539Sslatteng vectptr->param += vectptr->dy;
168016539Sslatteng } else if (vectptr->dy < 0) {
168116539Sslatteng while (vectptr->param >= 0) {
168216539Sslatteng vectptr->param -= vectptr->dx;
168316539Sslatteng vectptr->curry--;
168416539Sslatteng }
168516539Sslatteng vectptr->param -= vectptr->dy;
168616539Sslatteng }
168716539Sslatteng /* must sort the vectors if updates */
168816539Sslatteng /* caused them to cross */
168916539Sslatteng /* also move to next vector here */
169016539Sslatteng if (vectptr->curry > vectptr->prev->curry) {
169116539Sslatteng register polyvector *v; /* vector to move */
169216539Sslatteng register polyvector *p; /* vector to put it after */
169316539Sslatteng
169416539Sslatteng v = vectptr;
169516539Sslatteng p = v->prev;
169616539Sslatteng while (v->curry > p->curry) /* find the */
169716539Sslatteng p = p->prev; /* right vector */
169816539Sslatteng
169916539Sslatteng vectptr = vectptr->next; /* remove from spot */
170016539Sslatteng vectptr->prev = v->prev;
170116539Sslatteng v->prev->next = vectptr;
170216539Sslatteng
170316539Sslatteng v->prev = p; /* put in new spot */
170416539Sslatteng v->next = p->next;
170516539Sslatteng p->next = v;
170616539Sslatteng v->next->prev = v;
170716539Sslatteng } else {
170816539Sslatteng vectptr = vectptr->next;
170916539Sslatteng }
171016539Sslatteng } while (vectptr != activehead);
171116539Sslatteng #ifdef DEBUGABLE
171216539Sslatteng if (dbg) fprintf(stderr, "line done\n");
171316539Sslatteng #endif
171416539Sslatteng
171516539Sslatteng if (++minx & mask) {
171616539Sslatteng leftstipple += bytewidth;
171716539Sslatteng } else {
171816539Sslatteng leftstipple = topstipple;
171916539Sslatteng }
172016539Sslatteng bottompage += BYTES_PER_LINE;
172116539Sslatteng } /* while (minx < nextx) */
172216539Sslatteng } /* while (minx <= maxx) */
172316539Sslatteng
172416539Sslatteng leavepoly:
172516539Sslatteng nfree(waitinghead);
172616539Sslatteng } /* polygon function */
1727