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