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