fix point size search bug, remove special font number and search
[unix-history] / usr / src / local / ditroff / ditroff.old.okeeffe / driver / dvar.c
CommitLineData
25d31bd7 1/* dvar.c 1.6 83/10/06
aa26c251
DS
2 *
3 * Varian driver for the new troff
4 *
5 * Authors: BWK(BELL)
6 * VCAT(berkley)
7 * Richard L. Hyde, Perdue University
a95209fa 8 * and David Slattengren, U.C. Berkeley
aa26c251
DS
9 */
10
11
12/*******************************************************************************
13
14 output language from troff:
15 all numbers are character strings
16
17#..\n comment
18sn size in points
19fn font as number from 1 to n
20cx ascii character x
21Cxyz funny char \(xyz. terminated by white space
22Hn go to absolute horizontal position n
23Vn go to absolute vertical position n (down is positive)
24hn go n units horizontally (relative)
25vn ditto vertically
26nnc move right nn, then print c (exactly 2 digits!)
27 (this wart is an optimization that shrinks output file size
28 about 35% and run-time about 15% while preserving ascii-ness)
29p new page begins -- set v to 0
30nb a end of line (information only -- no action needed)
31 b = space before line, a = after
32w paddable word space -- no action needed
33
34Dt ..\n draw operation 't':
35 Dl x y line from here by x,y
36 Dc d circle of diameter d with left side here
37 De x y ellipse of axes x,y with left side here
38 Da x y r arc counter-clockwise by x,y of radius r
39 D~ x y x y ... B-spline curve by x,y then x,y ...
40
41x ..\n device control functions:
42 x i init
43 x T s name of device is s
44 x r n h v resolution is n/inch h = min horizontal motion, v = min vert
45 x p pause (can restart)
46 x s stop -- done for ever
47 x t generate trailer
48 x f n s font position n contains font s
49 x H n set character height to n
50 x S n set slant to N
51
52 Subcommands like "i" are often spelled out like "init".
53
54*******************************************************************************/
55
56
57#include <stdio.h>
58#include <ctype.h>
59#include <sys/vcmd.h>
60#include "dev.h"
61
62
25d31bd7
DS
63/* #define DEBUGABLE /* No, not debugable... */
64#define DRIVER /* Yes, we're driving directly */
65/* #define FULLPAGE /* No, don't output full pages */
a95209fa 66#define NFONTS 60 /* total number of fonts useable */
aa26c251
DS
67#define MAXSTATE 6 /* number of environments rememberable */
68#define OPENREAD 0 /* mode for openning files */
69#define RESTART 1 /* upon exit, return either RESTART */
70#define ABORT 2 /* or ABORT */
71#define FATAL 1 /* type of error */
72#define BMASK 0377 /* byte grabber */
a95209fa
DS
73#define FONTDIR "/usr/lib/font" /* default place to find font descriptions */
74#define BITDIR "/usr/lib/vfont" /* default place to look for font rasters */
aa26c251
DS
75#define MAXWRIT 4096 /* max characters allowed to write at once */
76
fcf4cc1d 77#define hmot(n) hgoto(hpos + n)
aa26c251
DS
78#define vmot(n) vgoto(vpos + n)
79
80
25d31bd7 81char SccsId[]= "dvar.c 1.6 83/10/06";
aa26c251
DS
82
83int output = 0; /* do we do output at all? */
84int nolist = 0; /* output page list if > 0 */
85int olist[20]; /* pairs of page numbers */
86int spage = 9999; /* stop every spage pages */
87int scount = 0;
88struct dev dev;
89struct font *fontbase[NFONTS+1];
a95209fa 90short * pstab; /* point size table pointer */
aa26c251
DS
91int nsizes; /* number of sizes device is capable of printing */
92int nfonts; /* number of fonts device is capable of printing */
aa26c251 93int nchtab;
a95209fa
DS
94char * chname;
95short * chtab;
96char * fitab[NFONTS+1]; /* font inclusion table - maps ascii to ch # */
97char * widtab[NFONTS+1]; /* width table for each font */
98char * codetab[NFONTS+1]; /* device codes */
99char * fontdir = FONTDIR; /* place to find devxxx directories */
100char * bitdir = BITDIR; /* place to find raster fonts and fontmap */
25d31bd7 101char * fontname[NFONTS+1]; /* table of what font is on what position */
a95209fa
DS
102struct { /* table of what font */
103 char fname[3]; /* name maps to what */
104 char *ffile; /* filename in bitdirectory */
105} fontmap[NFONTS+1];
106
aa26c251
DS
107
108#ifdef DEBUGABLE
109int dbg = 0;
110#endif
a95209fa 111int size = -1; /* current point size (internal pstable index) */
aa26c251
DS
112int font = -1; /* current font - not using any to start with */
113int hpos; /* horizontal position we are to be at next; left = 0 */
114int vpos; /* current vertical position (down positive) */
a95209fa 115extern linethickness; /* thickness (in pixels) of any drawn object */
fcf4cc1d 116extern linmod; /* line style (a bit mask - dotted, etc.) of objects */
aa26c251
DS
117int lastw; /* width of last character printed */
118
119
120#define DISPATCHSIZE 256 /* must be a power of two */
121#define CHARMASK (DISPATCHSIZE-1)
122#define DSIZ ((sizeof *dispatch)*DISPATCHSIZE)
123#define OUTFILE fileno (stdout)
a95209fa 124#define RES 200 /* resolution of the device (dots/in) */
aa26c251 125
deb3e887 126#define RASTER_LENGTH 2112 /* device line length */
aa26c251 127#define BYTES_PER_LINE (RASTER_LENGTH/8)
25d31bd7
DS
128#ifndef FULLPAGE
129# define NLINES 1600 /* page width, 8 inches */
130#endif
131#ifdef FULLPAGE
132# define NLINES 1700 /* page width, 8.5 inches */
133#endif
aa26c251
DS
134#define BUFFER_SIZE (NLINES*BYTES_PER_LINE) /* number of chars in picture */
135
136
137int pltmode[] = { VPLOT };
138int prtmode[] = { VPRINT };
139char buffer[BUFFER_SIZE]; /* Big line buffers */
a95209fa 140char * buf0p = &buffer[0]; /* Zero origin in circular buffer */
aa26c251 141
a95209fa
DS
142char * calloc();
143char * nalloc();
144char * allpanic();
93f390a8 145char * operand();
aa26c251
DS
146
147struct header {
148 short magic;
149 unsigned short size;
150 short maxx;
151 short maxy;
152 short xtnd;
153} header;
154
155struct dispatch{
156 unsigned short addr;
157 short nbytes;
158 char up;
159 char down;
160 char left;
161 char right;
162 short width;
163};
164
165struct fontdes {
166 int fnum;
167 int psize;
168 struct dispatch *disp;
169 char *bits;
170} fontdes[NFONTS] = {
171 -1,
172 -1
173};
174
175struct dispatch *dispatch;
176int cfnum = -1;
177int cpsize = 10;
178int cfont = 1;
179char *bits;
180int fontwanted = 1; /* flag: "has a new font been requested?" */
181int nfontnum = -1;
182int npsize = 10;
183
184
185
186main(argc, argv)
187char *argv[];
188{
189 FILE *fp;
aa26c251 190
93f390a8
DS
191 while (--argc > 0 && **++argv == '-') {
192 switch ((*argv)[1]) {
aa26c251 193 case 'F':
25d31bd7 194 bitdir = operand(&argc, &argv);
a95209fa
DS
195 break;
196 case 'f':
25d31bd7 197 fontdir = operand(&argc, &argv);
aa26c251
DS
198 break;
199 case 'o':
93f390a8 200 outlist(operand(&argc, &argv));
aa26c251
DS
201 break;
202#ifdef DEBUGABLE
203 case 'd':
93f390a8 204 dbg = atoi(operand(&argc, &argv));
aa26c251
DS
205 if (dbg == 0) dbg = 1;
206 break;
207#endif
208 case 's':
93f390a8 209 spage = atoi(operand(&argc, &argv));
aa26c251
DS
210 if (spage <= 0)
211 spage = 9999;
212 break;
213 }
aa26c251
DS
214 }
215
25d31bd7 216#ifdef DRIVER
aa26c251 217 ioctl(OUTFILE, VSETSTATE, pltmode);
25d31bd7 218#endif
aa26c251 219
93f390a8 220 if (argc < 1)
aa26c251
DS
221 conv(stdin);
222 else
93f390a8
DS
223 while (argc--) {
224 if (strcmp(*argv, "-") == 0)
aa26c251
DS
225 fp = stdin;
226 else if ((fp = fopen(*argv, "r")) == NULL)
227 error(FATAL, "can't open %s", *argv);
228 conv(fp);
229 fclose(fp);
93f390a8 230 argv++;
aa26c251 231 }
aa26c251
DS
232 exit(0);
233}
234
93f390a8
DS
235
236/*----------------------------------------------------------------------------*
237 | Routine: char * operand (& argc, & argv)
238 |
239 | Results: returns address of the operand given with a command-line
240 | option. It uses either "-Xoperand" or "-X operand", whichever
241 | is present. The program is terminated if no option is present.
242 |
243 | Side Efct: argc and argv are updated as necessary.
244 *----------------------------------------------------------------------------*/
245
246char *operand(argcp, argvp)
247int * argcp;
248char ***argvp;
249{
250 if ((**argvp)[2]) return(**argvp + 2); /* operand immediately follows */
251 if ((--*argcp) <= 0) /* no operand */
252 error (FATAL, "command-line option operand missing.\n");
253 return(*(++(*argvp))); /* operand next word */
254}
255
256
aa26c251
DS
257outlist(s) /* process list of page numbers to be printed */
258char *s;
259{
260 int n1, n2, i;
261
262 nolist = 0;
263 while (*s) {
264 n1 = 0;
265 if (isdigit(*s))
266 do
267 n1 = 10 * n1 + *s++ - '0';
268 while (isdigit(*s));
269 else
270 n1 = -9999;
271 n2 = n1;
272 if (*s == '-') {
273 s++;
274 n2 = 0;
275 if (isdigit(*s))
276 do
277 n2 = 10 * n2 + *s++ - '0';
278 while (isdigit(*s));
279 else
280 n2 = 9999;
281 }
282 olist[nolist++] = n1;
283 olist[nolist++] = n2;
284 if (*s != '\0')
285 s++;
286 }
287 olist[nolist] = 0;
288#ifdef DEBUGABLE
289 if (dbg)
290 for (i=0; i<nolist; i += 2)
291 fprintf(stderr,"%3d %3d\n", olist[i], olist[i+1]);
292#endif
293}
294
295conv(fp)
296register FILE *fp;
297{
298 register int c, k;
299 int m, n, n1, m1;
300 char str[100], buf[300];
301
302 while ((c = getc(fp)) != EOF) {
303 switch (c) {
304 case '\n': /* when input is text */
305 case ' ':
306 case 0: /* occasional noise creeps in */
307 break;
308 case '{': /* push down current environment */
309 t_push();
310 break;
311 case '}':
312 t_pop();
313 break;
314 case '0': case '1': case '2': case '3': case '4':
315 case '5': case '6': case '7': case '8': case '9':
316 /* two motion digits plus a character */
317 hmot((c-'0')*10 + getc(fp)-'0');
318 put1(getc(fp));
319 break;
320 case 'c': /* single ascii character */
321 put1(getc(fp));
322 break;
323 case 'C':
324 fscanf(fp, "%s", str);
325 put1s(str);
326 break;
327 case 't': /* straight text */
328 fgets(buf, sizeof(buf), fp);
329 t_text(buf);
330 break;
331 case 'D': /* draw function */
332 fgets(buf, sizeof(buf), fp);
333 switch (buf[0]) {
334 case 'l': /* draw a line */
335 sscanf(buf+1, "%d %d", &n, &m);
336 drawline(n, m);
337 break;
338 case 'c': /* circle */
339 sscanf(buf+1, "%d", &n);
340 drawcirc(n);
341 break;
342 case 'e': /* ellipse */
343 sscanf(buf+1, "%d %d", &m, &n);
344 drawellip(m, n);
345 break;
346 case 'a': /* arc */
347 sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1);
348 drawarc(n, m, n1, m1);
349 break;
350 case '~': /* wiggly line */
deb3e887
DS
351 case 'g': /* gremlin spline */
352 drawwig(buf+1, fp, buf[0] == '~');
353 break;
354 case 't': /* line thickness */
355 sscanf(buf+1, "%d", &n);
356 drawthick(n);
357 break;
358 case 's': /* line style */
359 sscanf(buf+1, "%d", &n);
360 drawstyle(n);
aa26c251
DS
361 break;
362 default:
fcf4cc1d 363 error(FATAL, "unknown drawing function %s", buf);
aa26c251
DS
364 break;
365 }
366 break;
367 case 's':
368 fscanf(fp, "%d", &n); /* ignore fractional sizes */
369 setsize(t_size(n));
370 break;
371 case 'f':
372 fscanf(fp, "%s", str);
373 setfont(t_font(str));
374 break;
375 case 'H': /* absolute horizontal motion */
376 /* fscanf(fp, "%d", &n); */
377 while ((c = getc(fp)) == ' ')
378 ;
379 k = 0;
380 do {
381 k = 10 * k + c - '0';
382 } while (isdigit(c = getc(fp)));
383 ungetc(c, fp);
384 hgoto(k);
385 break;
386 case 'h': /* relative horizontal motion */
387 while ((c = getc(fp)) == ' ')
388 ;
389 k = 0;
390 do {
391 k = 10 * k + c - '0';
392 } while (isdigit(c = getc(fp)));
393 ungetc(c, fp);
394 hmot(k);
395 break;
396 case 'w': /* word space */
397 break;
398 case 'V':
399 fscanf(fp, "%d", &n);
400 vgoto(n);
401 break;
402 case 'v':
403 fscanf(fp, "%d", &n);
404 vmot(n);
405 break;
406 case 'p': /* new page */
407 fscanf(fp, "%d", &n);
408 t_page(n);
409 break;
410 case 'n': /* end of line */
411 while (getc(fp) != '\n')
412 ;
413 t_newline();
414 break;
415 case '#': /* comment */
416 while (getc(fp) != '\n')
417 ;
418 break;
419 case 'x': /* device control */
420 devcntrl(fp);
421 break;
422 default:
fcf4cc1d 423 error(FATAL, "unknown input character %o %c", c, c);
aa26c251
DS
424 }
425 }
426}
427
428devcntrl(fp) /* interpret device control functions */
429FILE *fp;
430{
431 char str[20], str1[50], buf[50];
432 int c, n;
433
434 fscanf(fp, "%s", str);
435 switch (str[0]) { /* crude for now */
436 case 'i': /* initialize */
437 fileinit();
438 t_init();
439 break;
440 case 't': /* trailer */
aa26c251
DS
441 break;
442 case 'p': /* pause -- can restart */
443 t_reset('p');
444 break;
445 case 's': /* stop */
446 t_reset('s');
447 break;
448 case 'r': /* resolution assumed when prepared */
a95209fa
DS
449 fscanf(fp, "%d", &n);
450 if (n!=RES) error(FATAL,"Input computed with wrong resolution");
aa26c251
DS
451 break;
452 case 'f': /* font used */
453 fscanf(fp, "%d %s", &n, str);
454 fgets(buf, sizeof buf, fp); /* in case there's a filename */
455 ungetc('\n', fp); /* fgets goes too far */
456 str1[0] = 0; /* in case nothing comes in */
457 sscanf(buf, "%s", str1);
458 loadfont(n, str, str1);
459 break;
460 /* these don't belong here... */
461 case 'H': /* char height */
462 fscanf(fp, "%d", &n);
463 t_charht(n);
464 break;
465 case 'S': /* slant */
466 fscanf(fp, "%d", &n);
467 t_slant(n);
468 break;
469 }
470 while ((c = getc(fp)) != '\n') /* skip rest of input line */
471 if (c == EOF)
472 break;
473}
474
475/* fileinit: read in font and code files, etc.
476 Must open table for device, read in resolution,
a95209fa
DS
477 size info, font info, etc. and set params.
478 Also read in font name mapping.
aa26c251 479*/
a95209fa 480
aa26c251
DS
481fileinit()
482{
a95209fa
DS
483 register int i;
484 register int fin;
485 register int nw;
486 register char *filebase;
487 register char *p;
488 register FILE *fp;
489 char temp[100];
490
491 /* first, read in font map file. The file must be of Format:
492 XX FILENAME (XX = troff font name)
493 with one entry per text line of the file.
494 Extra stuff after FILENAME is ignored */
495
496 sprintf(temp, "%s/fontmap", bitdir);
497 if ((fp = fopen(temp, "r")) == NULL)
498 error(FATAL, "Can't open %s", temp);
499 for (i = 0; i <= NFONTS && fgets(temp, 100, fp) != NULL; i++) {
500 sscanf(temp, "%2s", fontmap[i].fname);
501 p = &temp[0];
502 while (*p != ' ' && *p != ' ') p++;
503 while (*p == ' ' || *p == ' ') p++;
504 filebase = p;
505 for (nw = 1; *p != '\n' && *p != ' ' && *p != '\t'; p++) nw++;
506 fontmap[i].ffile = nalloc(1, nw);
507 sscanf(filebase, "%s", fontmap[i].ffile);
508 }
509 fontmap[++i].fname[0] = '0'; /* finish off with zeros */
510 fontmap[i].ffile = (char *) 0;
511 fclose(fp);
512#ifdef DEBUGABLE
513 if(dbg) {
514 fprintf(stderr, "font map:\n");
515 for (i = 0; fontmap[i].ffile; i++)
516 fprintf(stderr,"%s = %s\n", fontmap[i].fname, fontmap[i].ffile);
517 }
518#endif
aa26c251 519
fcf4cc1d 520 sprintf(temp, "%s/devvar/DESC.out", fontdir);
aa26c251 521 if ((fin = open(temp, 0)) < 0)
fcf4cc1d 522 error(FATAL, "can't open tables for %s", temp);
aa26c251
DS
523 read(fin, &dev, sizeof(struct dev));
524 nfonts = dev.nfonts;
525 nsizes = dev.nsizes;
526 nchtab = dev.nchtab;
a95209fa 527 filebase = calloc(1, dev.filesize); /* enough room for whole file */
aa26c251
DS
528 read(fin, filebase, dev.filesize); /* all at once */
529 pstab = (short *) filebase;
530 chtab = pstab + nsizes + 1;
531 chname = (char *) (chtab + dev.nchtab);
532 p = chname + dev.lchname;
533 for (i = 1; i <= nfonts; i++) {
534 fontbase[i] = (struct font *) p;
535 nw = *p & BMASK; /* 1st thing is width count */
25d31bd7 536 p += sizeof(struct font);
aa26c251
DS
537 widtab[i] = p;
538 codetab[i] = p + 2 * nw;
539 fitab[i] = p + 3 * nw;
540 p += 3 * nw + dev.nchtab + 128 - 32;
541 t_fp(i, fontbase[i]->namefont, fontbase[i]->intname);
542#ifdef DEBUGABLE
543 if (dbg > 1) fontprint(i);
544#endif
545 }
546 fontbase[0] = (struct font *)
547 calloc(1,3*255 + dev.nchtab + (128-32) + sizeof (struct font));
548 widtab[0] = (char *) fontbase[0] + sizeof (struct font);
549 fontbase[0]->nwfont = 255;
550 close(fin);
a95209fa 551
aa26c251
DS
552}
553
a95209fa 554
aa26c251
DS
555fontprint(i) /* debugging print of font i (0,...) */
556{
557 int j, n;
558 char *p;
559
560 fprintf(stderr,"font %d:\n", i);
561 p = (char *) fontbase[i];
562 n = fontbase[i]->nwfont & BMASK;
563 fprintf(stderr,
564 "base=0%o, nchars=%d, spec=%d, name=%s, widtab=0%o, fitab=0%o\n",p,
565 n,fontbase[i]->specfont,fontbase[i]->namefont,widtab[i],fitab[i]);
566 fprintf(stderr,"widths:\n");
567 for (j=0; j <= n; j++) {
568 fprintf(stderr," %2d", widtab[i][j] & BMASK);
569 if (j % 20 == 19) fprintf(stderr,"\n");
570 }
571 fprintf(stderr,"\ncodetab:\n");
572 for (j=0; j <= n; j++) {
573 fprintf(stderr," %2d", codetab[i][j] & BMASK);
574 if (j % 20 == 19) fprintf(stderr,"\n");
575 }
576 fprintf(stderr,"\nfitab:\n");
577 for (j=0; j <= dev.nchtab + 128-32; j++) {
578 fprintf(stderr," %2d", fitab[i][j] & BMASK);
579 if (j % 20 == 19) fprintf(stderr,"\n");
580 }
581 fprintf(stderr,"\n");
582}
583
584loadfont(n, s, s1) /* load font info for font s on position n (0...) */
585int n;
586char *s, *s1;
587{
588 char temp[60];
589 int fin, nw, norig;
590
a95209fa 591
aa26c251
DS
592 if (n < 0 || n > NFONTS)
593 error(FATAL, "illegal fp command %d %s", n, s);
594 if (strcmp(s, fontbase[n]->namefont) == 0)
595 return;
596 if (s1 == NULL || s1[0] == '\0')
fcf4cc1d 597 sprintf(temp, "%s/devvar/%s.out", fontdir, s);
aa26c251
DS
598 else
599 sprintf(temp, "%s/%s.out", s1, s);
600 if ((fin = open(temp, 0)) < 0)
601 error(FATAL, "can't open font table %s", temp);
602 norig = fontbase[n]->nwfont & BMASK;
603 read(fin, fontbase[n], 3*norig + nchtab+128-32 + sizeof(struct font));
604 if ((fontbase[n]->nwfont & BMASK) > norig)
fcf4cc1d 605 error(FATAL, "Font %s too big for position %d", s, n);
aa26c251
DS
606 close(fin);
607 nw = fontbase[n]->nwfont & BMASK;
608 widtab[n] = (char *) fontbase[n] + sizeof(struct font);
609 codetab[n] = (char *) widtab[n] + 2 * nw;
610 fitab[n] = (char *) widtab[n] + 3 * nw;
611 t_fp(n, fontbase[n]->namefont, fontbase[n]->intname);
612 fontbase[n]->nwfont = norig; /* to later use full original size */
613#ifdef DEBUGABLE
614 if (dbg > 1) fontprint(n);
615#endif
616}
617
fcf4cc1d 618
aa26c251
DS
619/*VARARGS1*/
620error(f, s, a1, a2, a3, a4, a5, a6, a7) {
fcf4cc1d 621 fprintf(stderr, "dvar: ");
aa26c251
DS
622 fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7);
623 fprintf(stderr, "\n");
25d31bd7 624 if (f) exit(ABORT);
aa26c251
DS
625}
626
627
aa26c251
DS
628t_init() /* initialize device */
629{
630 int i;
631
632 hpos = vpos = 0;
633
634 setsize(t_size(10)); /* start somewhere */
635 setfont(1);
636}
637
638
639struct state {
640 int ssize;
641 int sfont;
642 int shpos;
643 int svpos;
fcf4cc1d
DS
644 int sstyle;
645 int sthick;
aa26c251
DS
646};
647struct state state[MAXSTATE];
648struct state *statep = state;
649
650t_push() /* begin a new block */
651{
652 statep->ssize = size;
653 statep->sfont = font;
fcf4cc1d
DS
654 statep->sstyle = linmod;
655 statep->sthick = linethickness;
aa26c251
DS
656 statep->shpos = hpos;
657 statep->svpos = vpos;
aa26c251
DS
658 if (statep++ >= state+MAXSTATE)
659 error(FATAL, "{ nested too deep");
aa26c251
DS
660}
661
662t_pop() /* pop to previous state */
663{
664 if (--statep < state)
665 error(FATAL, "extra }");
666 size = statep->ssize;
667 font = statep->sfont;
668 hpos = statep->shpos;
669 vpos = statep->svpos;
fcf4cc1d
DS
670 linmod = statep->sstyle;
671 linethickness = statep->sthick;
aa26c251
DS
672}
673
674t_page(n) /* do whatever new page functions */
675{
676 int i;
677
678
679 if (output) {
680 if (++scount >= spage) {
681 t_reset('p');
682 scount = 0;
683 }
fcf4cc1d 684 slop_lines(NLINES);
25d31bd7 685#ifdef DRIVER
aa26c251
DS
686 ioctl(OUTFILE, VSETSTATE, prtmode);
687 if (write(OUTFILE, "\f", 2) != 2)
688 exit(RESTART);
689 ioctl(OUTFILE, VSETSTATE, pltmode);
25d31bd7 690#endif
aa26c251
DS
691 }
692
aa26c251
DS
693 vpos = 0;
694 output = 1;
695 if (nolist == 0)
a95209fa 696 return; /* no -o specified */
aa26c251
DS
697 output = 0;
698 for (i = 0; i < nolist; i += 2)
699 if (n >= olist[i] && n <= olist[i+1]) {
700 output = 1;
701 break;
702 }
703}
704
705t_newline() /* do whatever for the end of a line */
706{
707 hpos = 0; /* because we're now back at the left margin */
708}
709
710t_size(n) /* convert integer to internal size number*/
711int n;
712{
713 int i;
714
715 if (n <= pstab[0])
a95209fa
DS
716 return(0);
717 else if (n >= pstab[nsizes - 1])
718 return(nsizes - 1);
aa26c251
DS
719 for (i = 0; n > pstab[i]; i++)
720 ;
a95209fa 721 return(i);
aa26c251
DS
722}
723
724t_charht(n) /* set character height to n */
725int n;
726{
727#ifdef DEBUGABLE
a95209fa 728 if (dbg) error(!FATAL, "can't set height on varian");
aa26c251
DS
729#endif
730}
731
732t_slant(n) /* set slant to n */
733int n;
734{
735#ifdef DEBUGABLE
a95209fa 736 if (dbg) error(!FATAL, "can't set slant on varian");
aa26c251
DS
737#endif
738}
739
740t_font(s) /* convert string to internal font number */
741char *s;
742{
743 int n;
744
745 n = atoi(s);
746 if (n < 0 || n > nfonts)
747 n = 1;
748 return(n);
749}
750
751t_text(s) /* print string s as text */
752char *s;
753{
754 int c;
755 char str[100];
756
757 if (!output)
758 return;
759 while (c = *s++) {
760 if (c == '\\') {
761 switch (c = *s++) {
762 case '\\':
763 case 'e':
764 put1('\\');
765 break;
766 case '(':
767 str[0] = *s++;
768 str[1] = *s++;
769 str[2] = '\0';
770 put1s(str);
771 break;
772 }
773 } else {
774 put1(c);
775 }
776 hmot(lastw);
777#ifdef DEBUGABLE
778 if (dbg) fprintf(stderr,"width = %d\n", lastw);
779#endif
780 }
781}
782
783t_reset(c)
784{
aa26c251
DS
785 output = 1;
786 switch(c){
787 case 'p':
fcf4cc1d 788 slop_lines(NLINES);
aa26c251
DS
789 break;
790 case 's':
fcf4cc1d 791 slop_lines(NLINES);
25d31bd7 792#ifdef DRIVER
a95209fa
DS
793 ioctl(OUTFILE, VSETSTATE, prtmode);
794 if (write(OUTFILE, "\f", 2) != 2)
795 exit(RESTART);
25d31bd7 796#endif
a95209fa
DS
797 break; /* no Return */
798 }
aa26c251
DS
799}
800
fcf4cc1d
DS
801
802/*----------------------------------------------------------------------------*
803 | Routine: hgoto (horizontal_spot)
804 |
805 | Results: hpos is set to n. If n overlaps in either direction, it wraps
806 | around to the other end of the page.
807 *----------------------------------------------------------------------------*/
808
809hgoto(n)
810int n;
811{
812 if (n < 0)
813 n += NLINES;
814 else if (n >= NLINES)
815 n -= NLINES;
816 hpos = n;
817}
818
819
820/*----------------------------------------------------------------------------*
821 | Routine: vgoto (vertical_spot)
822 |
823 | Results: vpos is set to n. If n overlaps in either direction, it wraps
824 | around to the other end of the page.
825 *----------------------------------------------------------------------------*/
826
aa26c251 827vgoto(n)
fcf4cc1d 828int n;
aa26c251 829{
fcf4cc1d
DS
830 if (n < 0)
831 n += RASTER_LENGTH;
832 else if (n > RASTER_LENGTH)
833 n -= RASTER_LENGTH;
aa26c251
DS
834 vpos = n;
835}
836
837put1s(s) /* s is a funny char name */
838char *s;
839{
840 int i;
841
842 if (!output)
843 return;
844#ifdef DEBUGABLE
845 if (dbg) fprintf(stderr,"%s ", s);
846#endif
847 for (i = 0; i < nchtab; i++)
848 if (strcmp(&chname[chtab[i]], s) == 0)
849 break;
850 if (i < nchtab)
851 put1(i + 128);
852}
853
854put1(c) /* output char c */
855int c;
856{
857 char *pw;
858 register char *p;
859 register int i, k;
860 int j, ofont, code;
861
862 if (!output)
863 return;
864 c -= 32;
865 if (c <= 0) {
866#ifdef DEBUGABLE
867 if (dbg) fprintf(stderr,"non-exist 0%o\n", c + 32);
868#endif
a95209fa 869 lastw = (widtab[font][0] * pstab[size] + dev.unitwidth/2)
aa26c251
DS
870 / dev.unitwidth;
871 return;
872 }
873 k = ofont = font;
874 i = fitab[font][c] & BMASK;
875 if (i != 0) { /* it's on this font */
876 p = codetab[font]; /* get the printing value of ch */
877 pw = widtab[font]; /* get the width */
25d31bd7
DS
878 } else /* on another font (we hope) */
879 for (k=font, j=0; j <= nfonts; j++, k = (k+1) % (nfonts+1)){
aa26c251
DS
880 if (fitab[k] == 0)
881 continue;
882 if ((i = fitab[k][c] & BMASK) != 0) {
883 p = codetab[k];
884 pw = widtab[k];
885 setfont(k);
886 break;
887 }
888 }
25d31bd7 889
aa26c251
DS
890 if (i == 0 || (code = p[i] & BMASK) == 0 || k > nfonts) {
891#ifdef DEBUGABLE
892 if (dbg) fprintf(stderr,"not found 0%o\n", c+32);
893#endif
894 return;
895 }
896#ifdef DEBUGABLE
897 if (dbg) {
898 if (isprint(c+32))
899 fprintf(stderr,"%c %d\n", c+32, code);
900 else
901 fprintf(stderr,"%03o %d\n", c+32, code);
902 }
903#endif
904 outc(code); /* character is < 254 */
905 if (font != ofont)
906 setfont(ofont);
a95209fa 907 lastw = ((pw[i]&077) * pstab[size] + dev.unitwidth/2) / dev.unitwidth;
aa26c251
DS
908}
909
910
911
912setsize(n) /* set point size to n (internal) */
913int n;
914{
915
916 if (n == size)
917 return; /* already there */
a95209fa 918 if (vloadfont(font, pstab[n]) != -1)
aa26c251
DS
919 size = n;
920}
921
922t_fp(n, s, si) /* font position n now contains font s, intname si */
25d31bd7 923int n; /* internal name is ignored */
aa26c251
DS
924char *s, *si;
925{
a95209fa 926 register int i;
aa26c251 927
a95209fa
DS
928
929 /* first convert s to filename if possible */
930 for (i = 0; fontmap[i].ffile != (char *) 0; i++) {
931#ifdef DEBUGABLE
932 if(dbg>1)fprintf(stderr,"testing :%s:%s:\n",s,fontmap[i].fname);
933#endif
934 if (strcmp(s, fontmap[i].fname) == 0) {
935 s = fontmap[i].ffile;
936#ifdef DEBUGABLE
937 if(dbg)fprintf(stderr, "found :%s:\n",fontmap[i].ffile);
938#endif
939 break;
940 }
941 }
25d31bd7 942 fontname[n] = s;
a95209fa 943 for(i = 0;i < NFONTS;i++) /* free the bits of that font */
aa26c251
DS
944 if (fontdes[i].fnum == n){
945 nfree(fontdes[i].bits);
946 fontdes[i].bits = 0;
947 fontdes[i].fnum = -1;
948 }
949}
950
a95209fa 951
aa26c251
DS
952setfont(n) /* set font to n */
953int n;
954{
955 if (n < 0 || n > NFONTS)
fcf4cc1d 956 error(FATAL, "illegal font %d", n);
a95209fa 957 if (vloadfont(n,pstab[size]) != -1)
aa26c251
DS
958 font = n;
959}
960
961vloadfont(fnum, fsize)
962register int fnum;
963register int fsize;
964{
965 register int i;
966
967 fontwanted = 0;
968 if (fnum == cfnum && fsize == cpsize)
969 return(0);
970 for (i = 0; i < NFONTS; i++) {
971 if (fontdes[i].fnum == fnum && fontdes[i].psize == fsize) {
972 cfnum = fontdes[i].fnum;
973 cpsize = fontdes[i].psize;
974 dispatch = &fontdes[i].disp[0];
975 bits = fontdes[i].bits;
976 cfont = i;
977 return (0);
978 }
979 }
980 /* this is a new font */
25d31bd7 981 if (fnum < 0 || fnum > NFONTS || fontname[fnum] == 0) {
aa26c251 982 fprintf(stderr, "Internal error: illegal font %d name %s size\n",
25d31bd7 983 fontname[fnum], fnum, fsize);
aa26c251
DS
984 return(-1);
985 }
986 /* Need to verify the existance of that font/size here*/
987 nfontnum = fnum;
988 npsize = fsize;
989 fontwanted++;
990 return (0);
991}
992
993
994getfont()
995{
a95209fa
DS
996 register int fnum;
997 register int fsize;
998 register int fontd;
999 register int d;
25d31bd7 1000 register int sizehunt = size;
aa26c251
DS
1001 char cbuf[BUFSIZ];
1002
1003 fnum = nfontnum;
1004 fsize = npsize;
a95209fa
DS
1005 /* try to open font file - if unsuccessful, hunt for */
1006 /* a file of same style, different size to substitute */
25d31bd7 1007 d = -1; /* direction to look in pstab (smaller first) */
a95209fa 1008 do {
25d31bd7 1009 sprintf(cbuf, "%s/%s.%dr", bitdir, fontname[fnum], fsize);
a95209fa
DS
1010 fontd = open(cbuf, OPENREAD);
1011 if (fontd == -1) { /* File wasn't found. Try another ps */
25d31bd7
DS
1012 sizehunt += d;
1013 if (sizehunt < 0) { /* past beginning - look higher */
a95209fa 1014 d = 1;
25d31bd7 1015 sizehunt = size + 1;
a95209fa 1016 }
25d31bd7 1017 if (sizehunt > nsizes) { /* past top - forget it */
a95209fa
DS
1018 d = 0;
1019 } else {
25d31bd7 1020 fsize = pstab[sizehunt];
a95209fa
DS
1021 }
1022 }
1023 } while (fontd == -1 && d != 0);
1024
1025 if (fontd == -1) { /* completely unsuccessful */
1026 perror(cbuf);
1027 error(!FATAL,"fnum = %d, psize = %d, name = %s",
25d31bd7 1028 fnum, npsize, fontname[fnum]);
a95209fa
DS
1029 fontwanted = 0;
1030 return (-1);
aa26c251
DS
1031 }
1032 if (read(fontd, &header, sizeof (header)) != sizeof (header)
1033 || header.magic != 0436)
1034 fprintf(stderr, "%s: Bad font file", cbuf);
1035 else {
1036 cfont = relfont();
1037 if ((bits=nalloc(header.size+DSIZ+1,1))== NULL)
1038 if ((bits=allpanic(header.size+DSIZ+1))== NULL) {
25d31bd7 1039 error(FATAL,"%s: ran out of memory", cbuf);
aa26c251
DS
1040 }
1041
1042 /*
1043 * have allocated one chunk of mem for font, dispatch.
1044 * get the dispatch addr, align to word boundary.
1045 */
1046
1047 d = (int) bits+header.size;
1048 d += 1;
1049 d &= ~1;
1050 if (read (fontd, d, DSIZ) != DSIZ
1051 || read (fontd, bits, header.size) != header.size)
1052 fprintf(stderr, "bad font header");
1053 else {
1054 close(fontd);
1055 cfnum = fontdes[cfont].fnum = fnum;
1056 cpsize = fontdes[cfont].psize = fsize;
1057 fontdes [cfont].bits = bits;
1058 fontdes [cfont].disp = (struct dispatch *) d;
1059 dispatch = &fontdes[cfont].disp[0];
1060 fontwanted = 0;
1061 return (0);
1062 }
1063 }
1064 close(fontd);
1065 fontwanted = 0;
1066 return(-1);
1067}
1068
1069/*
1070 * "release" a font position - find an empty one, if possible
1071 */
1072
1073relfont()
1074{
1075 register int newfont;
1076
1077 for (newfont = 0; newfont < NFONTS; newfont++)
1078 if (fontdes [newfont].bits == (char *) -1 || !fontdes [newfont].bits)
1079 break;
1080 if (fontdes [newfont].bits != (char *) -1 && fontdes [newfont].bits) {
1081 nfree (fontdes [newfont].bits);
1082 fontdes [newfont].bits = (char *)0;
1083#ifdef DEBUGABLE
1084 if (dbg) fprintf (stderr, "freeing position %d\n", newfont);
1085 } else {
1086 if (dbg)
1087 fprintf (stderr, "taking, not freeing, position %d\n", newfont);
1088#endif
1089 }
1090 fontdes[newfont].bits = 0;
1091 return (newfont);
1092}
1093
1094char *allpanic (nbytes)
1095int nbytes;
1096{
1097 register int i;
1098
1099 for (i = 0; i <= NFONTS; i++)
1100 if (fontdes[i].bits != (char *)-1 && fontdes[i].bits != (char *)0)
1101 nfree(fontdes[i].bits);
1102 for (i = 0; i <= NFONTS; i++) {
1103 fontdes[i].fnum = fontdes[i].psize = -1;
1104 fontdes[i].bits = 0;
1105 cfnum = cpsize = -1;
1106 }
1107 return(nalloc(nbytes,1));
1108}
1109
1110int M[] = { 0xffffffff, 0xfefefefe, 0xfcfcfcfc, 0xf8f8f8f8,
1111 0xf0f0f0f0, 0xe0e0e0e0, 0xc0c0c0c0, 0x80808080, 0x0 };
1112int N[] = { 0x00000000, 0x01010101, 0x03030303, 0x07070707,
1113 0x0f0f0f0f, 0x1f1f1f1f, 0x3f3f3f3f, 0x7f7f7f7f, 0xffffffff };
1114int strim[] = { 0xffffffff, 0xffffff00, 0xffff0000, 0xff000000, 0 };
1115
1116outc(code)
1117int code; /* character to print */
1118{
1119 register struct dispatch *dis; /* ptr to character font record */
1120 register char *addr; /* addr of font data */
1121 int llen; /* length of each font line */
1122 int nlines; /* number of font lines */
1123 register char *scanp; /* ptr to output buffer */
1124 int scanp_inc; /* increment to start of next buffer */
1125 int offset; /* bit offset to start of font data */
a95209fa 1126 register int i; /* loop counter */
aa26c251
DS
1127 register int count; /* font data ptr */
1128 register unsigned fontdata; /* font data temporary */
1129 register int off8; /* offset + 8 */
1130
1131 if (fontwanted)
1132 getfont();
1133 dis = dispatch + code;
1134 if (dis->nbytes) {
1135 addr = bits + dis->addr;
deb3e887
DS
1136 llen = (dis->up + dis->down + 7) >> 3;
1137 nlines = dis->right + dis->left;
deb3e887
DS
1138 scanp = buf0p + (hpos - dis->left) * BYTES_PER_LINE
1139 - (1 + ((dis->down + vpos) >> 3));
aa26c251
DS
1140 if (scanp < &buffer[0])
1141 scanp += sizeof buffer;
1142 scanp_inc = BYTES_PER_LINE - llen;
deb3e887
DS
1143 off8 = ((dis->down + vpos) &07);
1144 offset = off8 - 8;
aa26c251
DS
1145 for (i = 0; i < nlines; i++) {
1146 if (scanp >= &buffer[BUFFER_SIZE])
25d31bd7 1147 scanp -= BUFFER_SIZE;
aa26c251 1148 count = llen;
25d31bd7 1149 if (scanp + count < &buffer[BUFFER_SIZE]) {
aa26c251
DS
1150 do {
1151 fontdata = *(unsigned *)addr;
1152 addr += 4;
1153 if (count < 4)
1154 fontdata &= ~strim[count];
1155 *(unsigned*)scanp |=(fontdata << offset) & ~M[off8];
1156 scanp++;
1157 *(unsigned*)scanp |=(fontdata << off8) & ~N[off8];
1158 scanp += 3;
1159 count -= 4;
1160 } while (count > 0);
1161 }
1162 scanp += scanp_inc+count;
1163 addr += count;
1164 }
1165 return;
1166 }
1167 return;
1168}
1169
1170slop_lines(nlines)
1171int nlines;
1172
1173/* Output "nlines" lines from the buffer, and clear that section of the */
1174/* buffer. */
1175
1176{
1177 unsigned usize;
1178
1179 usize = BYTES_PER_LINE * nlines;
a95209fa 1180 vwrite(buf0p, usize);
aa26c251 1181 vclear(buf0p, usize);
25d31bd7 1182#ifdef DRIVER
aa26c251 1183 ioctl(OUTFILE, VSETSTATE, pltmode);
25d31bd7 1184#endif
aa26c251
DS
1185}
1186
a95209fa 1187vwrite(buf,usize)
aa26c251
DS
1188char *buf;
1189unsigned usize;
1190{
1191 register int tsize = 0;
1192
1193 while (usize){
1194 buf += tsize;
1195 tsize = usize > MAXWRIT ? MAXWRIT : usize;
1196#ifdef DEBUGABLE
1197 if (dbg)fprintf(stderr,"buf = %d size = %d\n",buf,tsize);
1198#endif
1199 if ((tsize = write(OUTFILE, buf, tsize)) < 0) {
fcf4cc1d 1200 perror("dvar: write failed");
aa26c251
DS
1201 exit(RESTART);
1202 }
1203 usize -= tsize;
1204 }
1205}
1206
1207vclear (ptr, nbytes)
1208char *ptr;
1209unsigned nbytes;
1210{
1211 register tsize = 0;
1212
1213 while (nbytes){
1214 if ((unsigned)(16*1024) < nbytes) {
1215 tsize = 16 * 1024;
1216 } else
1217 tsize = nbytes;
1218 nbytes -= tsize;
1219#ifdef DEBUGABLE
1220 if (dbg) fprintf(stderr,"clearing ptr = %d size = %d\n",ptr,tsize);
1221#endif
1222 clear(ptr,tsize);
1223 ptr += tsize;
1224 }
1225}
1226
1227/*ARGSUSED*/
1228clear(lp, nbytes)
1229int *lp;
1230int nbytes;
1231{
1232 asm("movc5 $0,(sp),$0,8(ap),*4(ap)");
1233}
1234
1235char *
1236nalloc(i, j)
1237int i, j;
1238{
1239 register char *cp;
1240
1241 cp = calloc(i, j);
1242#ifdef DEBUGABLE
1243 if (dbg) fprintf(stderr, "allocated %d bytes at %x\n", i * j, cp);
1244#endif
1245 return(cp);
1246}
1247
1248nfree(cp)
1249char *cp;
1250{
1251#ifdef DEBUGABLE
1252 if (dbg) fprintf(stderr, "freeing at %x\n", cp);
1253#endif
1254 free(cp);
1255}
1256
1257
1258/*
1259 * Points should be in the range 0 <= x < RASTER_LENGTH, 0 <= y < NLINES.
1260 * The origin is the top left-hand corner with increasing x towards the
a95209fa
DS
1261 * right and increasing y going down. X and Y should be sent as (0,0) being
1262 * at the bottom left. The output array is NLINES x BYTES_PER_LINE pixels.
aa26c251
DS
1263 */
1264point(x, y)
deb3e887
DS
1265register int x;
1266register int y;
aa26c251 1267{
deb3e887
DS
1268 if ((unsigned)(y=RASTER_LENGTH-y) < RASTER_LENGTH && (unsigned)x < NLINES) {
1269 buffer [x * BYTES_PER_LINE + (y >> 3)] |= 1 << (7 - (y & 07));
aa26c251
DS
1270 }
1271}