1 /* dver.c 1.2 83/05/19 2 * 3 * dver.c - Versatec driver for the new troff 4 * 5 * Authors: BWK(BELL), VCAT(berkley), and Richard L. Hyde 6 * Many parts where lifted from the above sources. 7 * Editor: Richard L. Hyde 8 * Dept. of Computer Sciences 9 * Purdue University 10 * Date: Thu Oct 28 1982 11 */ 12 13 14 /******************************************************************************* 15 16 output language from troff: 17 all numbers are character strings 18 19 sn size in points 20 fn font as number from 1-n 21 cx ascii character x 22 Cxyz funny char xyz. terminated by white space 23 Hn go to absolute horizontal position n 24 Vn go to absolute vertical position n (down is positive) 25 hn go n units horizontally (relative) 26 vn ditto vertically 27 nnc move right nn, then print c (exactly 2 digits!) 28 (this wart is an optimization that shrinks output file size 29 about 35% and run-time about 15% while preserving ascii-ness) 30 Dt ..\n draw operation 't': 31 Dl x y line from here by x,y 32 Dc d circle of diameter d with left side here 33 De x y ellipse of axes x,y with left side here 34 Da x y r arc counter-clockwise by x,y of radius r 35 D~ x y x y ... wiggly line by x,y then x,y ... 36 nb a end of line (information only -- no action needed) 37 w paddable word space -- no action needed 38 b = space before line, a = after 39 p new page begins -- set v to 0 40 #..\n comment 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 45 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 <signal.h> 61 #include "dev.h" 62 #include <errno.h> 63 #include <sys/param.h> 64 #include <sys/dir.h> 65 #include <sys/stat.h> 66 #include "modes.h" 67 68 69 /*#define ACCOUNT*/ 70 #define NFONT 25 71 #define OPENREAD 0 72 #define RESTART 1 73 #define ABORT 2 74 75 char SccsId[]= "dver.c 1.2 83/05/19"; 76 77 int output = 0; /* do we do output at all? */ 78 int nolist = 0; /* output page list if > 0 */ 79 int olist[20]; /* pairs of page numbers */ 80 int spage = 9999; /* stop every spage pages */ 81 int scount = 0; 82 int DX = 1; 83 int DY = 1; 84 struct dev dev; 85 struct font *fontbase[NFONT+1]; 86 short *pstab; 87 int nsizes; 88 int nfonts; 89 int smnt; /* index of first special font */ 90 int nchtab; 91 char *chname; 92 short *chtab; 93 char *fitab[NFONT+1]; 94 char *widthtab[NFONT+1]; /* widtab would be a better name */ 95 char *codetab[NFONT+1]; /* device codes */ 96 97 #define FATAL 1 98 #undef BMASK 99 #define BMASK 0377 100 int dbg = 0; 101 int res; /* input was computed according to this resolution */ 102 103 FILE *tf = NULL; /* output file */ 104 char *fontdir= "/usr/lib/font"; 105 extern char devname[]; 106 107 /* hpos == hpos */ 108 /* vpos != vpos vpos = vertical postion on the page xpos is rel buf0p */ 109 110 #define hmot(n) hpos += n 111 #define hgoto(n) hpos = n 112 #define vmot(n) vgoto(vpos + n) 113 int maxX; 114 int size = -1; /* this is invalid */ 115 int font = -1; /* current font */ 116 int hpos; /* horizontal position we are to be at next; left = 0 */ 117 int oldh; /* previous H position */ 118 int vpos; /* current vertical position (down positive) */ 119 int oldv; /* current pos in 1/4 point units */ 120 int horig; /* h origin of current block; hpos rel to this */ 121 int vorig; 122 int drawdot = '.'; /* draw with this character */ 123 int drawsize = 2; /* shrink by this factor when drawing */ 124 /* new 125 */ 126 127 #define DISPATCHSIZE 256 /* must be a power of two */ 128 #define CHARMASK (DISPATCHSIZE-1) 129 #define NFONTS 25 130 #define SPECIALFONT 3 131 #define DSIZ ((sizeof *dispatch)*DISPATCHSIZE) 132 #define MAXF (NFONT + 1) 133 #define OUTFILE 1 134 135 136 #define RASTER_LENGTH 1600 /* 100 characters, 16 bits / character */ 137 #define BYTES_PER_LINE (RASTER_LENGTH/8) 138 #define NLINES (11*200 + 10) 139 #define BUFFER_SIZE (NLINES*BYTES_PER_LINE) 140 141 char buffer[BUFFER_SIZE]; /* Big line buffers */ 142 char *buf0p = &buffer[0]; /* Zero origin in circular buffer */ 143 144 char *calloc(); 145 char *nalloc(); 146 char *allpanic(); 147 struct passwd *getpwuid(); 148 149 struct header{ 150 short magic; 151 unsigned short size; 152 short maxx; 153 short maxy; 154 short xtnd; 155 } header; 156 157 struct dispatch{ 158 unsigned short addr; 159 short nbytes; 160 char up; 161 char down; 162 char left; 163 char right; 164 short width; 165 }; 166 167 struct fontdes { 168 int fnum; 169 int psize; 170 struct dispatch *disp; 171 char *bits; 172 } fontdes[NFONTS] = { 173 -1, 174 -1 175 }; 176 177 struct dispatch *dispatch; 178 /* Accounting assumes roll paper */ 179 #define FFLINES 650 180 #define EOTLINES 1400 181 int cfnum = -1; 182 int cpsize = 10; 183 int cfont = 1; 184 char *bits; 185 int nfontnum = -1; 186 int fontwanted = 1; 187 int npsize = 10; 188 189 #ifdef ACCOUNT 190 int lines = 0; /* line counter */ 191 char *user; /* user name */ 192 #endif 193 194 /* 195 old 196 */ 197 198 main(argc, argv) 199 char *argv[]; 200 { 201 FILE *fp; 202 int done(); 203 204 tf = stdout; 205 while (argc > 1 && argv[1][0] == '-') { 206 switch (argv[1][1]) { 207 case 'f': 208 case 'F': 209 fontdir = argv[2]; 210 argv++; 211 argc--; 212 break; 213 case 'o': 214 outlist(&argv[1][2]); 215 break; 216 case 'd': 217 dbg = atoi(&argv[1][2]); 218 if (dbg == 0) dbg = 1; 219 tf = stdout; 220 break; 221 case 's': 222 spage = atoi(&argv[1][2]); 223 if (spage <= 0) 224 spage = 9999; 225 break; 226 case 'n': /* user's name */ 227 argc--; 228 #ifdef ACCOUNT 229 user = 230 #endif 231 *++argv; 232 break; 233 } 234 argc--; 235 argv++; 236 } 237 238 ioctl(OUTFILE, VSETSTATE, pltmode); 239 240 if (argc <= 1) 241 conv(stdin); 242 else 243 while (--argc > 0) { 244 if (strcmp(*++argv, "-") == 0) 245 fp = stdin; 246 else if ((fp = fopen(*argv, "r")) == NULL) 247 error(FATAL, "can't open %s", *argv); 248 conv(fp); 249 fclose(fp); 250 } 251 #ifdef ACCOUNT 252 accounting(); 253 #endif 254 waitchild(); 255 done(); 256 exit(0); 257 } 258 259 outlist(s) /* process list of page numbers to be printed */ 260 char *s; 261 { 262 int n1, n2, i; 263 264 nolist = 0; 265 while (*s) { 266 n1 = 0; 267 if (isdigit(*s)) 268 do 269 n1 = 10 * n1 + *s++ - '0'; 270 while (isdigit(*s)); 271 else 272 n1 = -9999; 273 n2 = n1; 274 if (*s == '-') { 275 s++; 276 n2 = 0; 277 if (isdigit(*s)) 278 do 279 n2 = 10 * n2 + *s++ - '0'; 280 while (isdigit(*s)); 281 else 282 n2 = 9999; 283 } 284 olist[nolist++] = n1; 285 olist[nolist++] = n2; 286 if (*s != '\0') 287 s++; 288 } 289 olist[nolist] = 0; 290 if (dbg) 291 for (i=0; i<nolist; i += 2) 292 fprintf(stderr,"%3d %3d\n", olist[i], olist[i+1]); 293 } 294 295 conv(fp) 296 register 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 */ 351 drawwig(buf+1); 352 break; 353 default: 354 error(FATAL, "unknown drawing function %s\n", buf); 355 break; 356 } 357 break; 358 case 's': 359 fscanf(fp, "%d", &n); /* ignore fractional sizes */ 360 setsize(t_size(n)); 361 break; 362 case 'f': 363 fscanf(fp, "%s", str); 364 setfont(t_font(str)); 365 break; 366 case 'H': /* absolute horizontal motion */ 367 /* fscanf(fp, "%d", &n); */ 368 while ((c = getc(fp)) == ' ') 369 ; 370 k = 0; 371 do { 372 k = 10 * k + c - '0'; 373 } while (isdigit(c = getc(fp))); 374 ungetc(c, fp); 375 hgoto(k); 376 break; 377 case 'h': /* relative horizontal motion */ 378 while ((c = getc(fp)) == ' ') 379 ; 380 k = 0; 381 do { 382 k = 10 * k + c - '0'; 383 } while (isdigit(c = getc(fp))); 384 ungetc(c, fp); 385 hmot(k); 386 break; 387 case 'w': /* word space */ 388 break; 389 case 'V': 390 fscanf(fp, "%d", &n); 391 vgoto(n); 392 break; 393 case 'v': 394 fscanf(fp, "%d", &n); 395 vmot(n); 396 break; 397 case 'p': /* new page */ 398 fscanf(fp, "%d", &n); 399 t_page(n); 400 break; 401 case 'n': /* end of line */ 402 while (getc(fp) != '\n') 403 ; 404 t_newline(); 405 break; 406 case '#': /* comment */ 407 while (getc(fp) != '\n') 408 ; 409 break; 410 case 'x': /* device control */ 411 devcntrl(fp); 412 break; 413 default: 414 error(!FATAL, "unknown input character %o %c\n", c, c); 415 done(); 416 } 417 } 418 } 419 420 devcntrl(fp) /* interpret device control functions */ 421 FILE *fp; 422 { 423 char str[20], str1[50], buf[50]; 424 int c, n; 425 426 fscanf(fp, "%s", str); 427 switch (str[0]) { /* crude for now */ 428 case 'i': /* initialize */ 429 fileinit(); 430 t_init(0); 431 break; 432 case 'T': /* device name */ 433 fscanf(fp, "%s", devname); 434 break; 435 case 't': /* trailer */ 436 t_trailer(); 437 break; 438 case 'p': /* pause -- can restart */ 439 t_reset('p'); 440 break; 441 case 's': /* stop */ 442 t_reset('s'); 443 break; 444 case 'r': /* resolution assumed when prepared */ 445 fscanf(fp, "%d", &res); 446 break; 447 case 'f': /* font used */ 448 fscanf(fp, "%d %s", &n, str); 449 fgets(buf, sizeof buf, fp); /* in case there's a filename */ 450 ungetc('\n', fp); /* fgets goes too far */ 451 str1[0] = 0; /* in case nothing comes in */ 452 sscanf(buf, "%s", str1); 453 loadfont(n, str, str1); 454 break; 455 /* these don't belong here... */ 456 case 'H': /* char height */ 457 fscanf(fp, "%d", &n); 458 t_charht(n); 459 break; 460 case 'S': /* slant */ 461 fscanf(fp, "%d", &n); 462 t_slant(n); 463 break; 464 } 465 while ((c = getc(fp)) != '\n') /* skip rest of input line */ 466 if (c == EOF) 467 break; 468 } 469 470 /* fileinit: read in font and code files, etc. 471 Must open table for device, read in resolution, 472 size info, font info, etc. and set params 473 */ 474 fileinit() 475 { 476 int i, fin, nw; 477 char *filebase, *p; 478 char temp[60]; 479 480 sprintf(temp, "%s/dev%s/DESC.out", fontdir, devname); 481 if ((fin = open(temp, 0)) < 0) 482 error(FATAL, "can't open tables for %s\n", temp); 483 read(fin, &dev, sizeof(struct dev)); 484 nfonts = dev.nfonts; 485 nsizes = dev.nsizes; 486 nchtab = dev.nchtab; 487 filebase = calloc(1,dev.filesize); /* enough room for whole file */ 488 read(fin, filebase, dev.filesize); /* all at once */ 489 pstab = (short *) filebase; 490 chtab = pstab + nsizes + 1; 491 chname = (char *) (chtab + dev.nchtab); 492 p = chname + dev.lchname; 493 for (i = 1; i <= nfonts; i++) { 494 fontbase[i] = (struct font *) p; 495 nw = *p & BMASK; /* 1st thing is width count */ 496 if (smnt == 0 && fontbase[i]->specfont == 1) 497 smnt = i; /* first special font */ 498 p += sizeof(struct font); /* that is on the beginning */ 499 widthtab[i] = p; 500 codetab[i] = p + 2 * nw; 501 fitab[i] = p + 3 * nw; 502 p += 3 * nw + dev.nchtab + 128 - 32; 503 t_fp(i, fontbase[i]->namefont, fontbase[i]->intname); 504 if(dbg > 1) fontprint(i); 505 } 506 fontbase[0] = (struct font *) 507 calloc(1,3*255 + dev.nchtab + (128-32) + sizeof (struct font)); 508 widthtab[0] = (char *) fontbase[0] + sizeof (struct font); 509 fontbase[0]->nwfont = 255; 510 close(fin); 511 } 512 513 fontprint(i) /* debugging print of font i (0,...) */ 514 { 515 int j, n; 516 char *p; 517 518 fprintf(stderr,"font %d:\n", i); 519 p = (char *) fontbase[i]; 520 n = fontbase[i]->nwfont & BMASK; 521 fprintf(stderr, 522 "base=0%o, nchars=%d, spec=%d, name=%s, widtab=0%o, fitab=0%o\n",p, 523 n,fontbase[i]->specfont,fontbase[i]->namefont,widthtab[i],fitab[i]); 524 fprintf(stderr,"widths:\n"); 525 for (j=0; j <= n; j++) { 526 fprintf(stderr," %2d", widthtab[i][j] & BMASK); 527 if (j % 20 == 19) fprintf(stderr,"\n"); 528 } 529 fprintf(stderr,"\ncodetab:\n"); 530 for (j=0; j <= n; j++) { 531 fprintf(stderr," %2d", codetab[i][j] & BMASK); 532 if (j % 20 == 19) fprintf(stderr,"\n"); 533 } 534 fprintf(stderr,"\nfitab:\n"); 535 for (j=0; j <= dev.nchtab + 128-32; j++) { 536 fprintf(stderr," %2d", fitab[i][j] & BMASK); 537 if (j % 20 == 19) fprintf(stderr,"\n"); 538 } 539 fprintf(stderr,"\n"); 540 } 541 542 loadfont(n, s, s1) /* load font info for font s on position n (0...) */ 543 int n; 544 char *s, *s1; 545 { 546 char temp[60]; 547 int fin, nw, norig; 548 549 if (n < 0 || n > NFONT) 550 error(FATAL, "illegal fp command %d %s", n, s); 551 if (strcmp(s, fontbase[n]->namefont) == 0) 552 return; 553 if (s1 == NULL || s1[0] == '\0') 554 sprintf(temp, "%s/dev%s/%s.out", fontdir, devname, s); 555 else 556 sprintf(temp, "%s/%s.out", s1, s); 557 if ((fin = open(temp, 0)) < 0) 558 error(FATAL, "can't open font table %s", temp); 559 norig = fontbase[n]->nwfont & BMASK; 560 read(fin, fontbase[n], 3*norig + nchtab+128-32 + sizeof(struct font)); 561 if ((fontbase[n]->nwfont & BMASK) > norig) 562 error(FATAL, "Font %s too big for position %d\n", s, n); 563 close(fin); 564 nw = fontbase[n]->nwfont & BMASK; 565 widthtab[n] = (char *) fontbase[n] + sizeof(struct font); 566 codetab[n] = (char *) widthtab[n] + 2 * nw; 567 fitab[n] = (char *) widthtab[n] + 3 * nw; 568 t_fp(n, fontbase[n]->namefont, fontbase[n]->intname); 569 fontbase[n]->nwfont = norig; /* to later use full original size */ 570 if (dbg > 1) fontprint(n); 571 } 572 573 done() 574 { 575 t_reset('s'); 576 exit(0); 577 } 578 /*VARARGS1*/ 579 error(f, s, a1, a2, a3, a4, a5, a6, a7) { 580 fprintf(stderr, "dver: "); 581 fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7); 582 fprintf(stderr, "\n"); 583 if (f) 584 done(); 585 } 586 587 588 /******************************************************************************* 589 590 Here beginneth all the stuff that really depends on the versatec (we hope). 591 592 *******************************************************************************/ 593 594 595 char devname[20] = "dver"; 596 597 #define RES 200 598 599 #define TRAILER (14 * res) 600 #define LMARGIN 0 /* left margin offset */ 601 #define HMAX (48 * (res/6)) /* maximum horizontal size = 48 picas */ 602 #define VMAX (12 * res) /* 15 inch page */ 603 604 int lastw; /* last character and width (maybe not used) */ 605 long paper; /* paper used */ 606 607 608 t_init(reinit) /* initialize device */ 609 int reinit; 610 { 611 int i; 612 613 hpos = vpos = oldv = oldh = 0; 614 615 /* the above are not true until the code below happens*/ 616 617 setsize(t_size(10)); /* start somewhere */ 618 setfont(1); 619 620 for (i = 0; i < nchtab; i++) /* find the line drawing char */ 621 if (strcmp(&chname[chtab[i]], "l.") == 0) 622 break; 623 if (i < nchtab) { 624 drawdot = i + 128; 625 drawsize = 1; 626 } else { 627 drawdot = '.'; 628 drawsize = 2; /* half size */ 629 } 630 } 631 632 #define MAXSTATE 6 633 634 struct state { 635 int ssize; 636 int sfont; 637 int shpos; 638 int svpos; 639 int shorig; 640 int svorig; 641 }; 642 struct state state[MAXSTATE]; 643 struct state *statep = state; 644 645 t_push() /* begin a new block */ 646 { 647 statep->ssize = size; 648 statep->sfont = font; 649 statep->shorig = horig; 650 statep->svorig = vorig; 651 statep->shpos = hpos; 652 statep->svpos = vpos; 653 horig = hpos; 654 vorig = vpos; 655 hpos = vpos = 0; 656 if (statep++ >= state+MAXSTATE) 657 error(FATAL, "{ nested too deep"); 658 hpos = vpos = 0; 659 } 660 661 t_pop() /* pop to previous state */ 662 { 663 if (--statep < state) 664 error(FATAL, "extra }"); 665 size = statep->ssize; 666 font = statep->sfont; 667 hpos = statep->shpos; 668 vpos = statep->svpos; 669 horig = statep->shorig; 670 vorig = statep->svorig; 671 } 672 673 t_page(n) /* do whatever new page functions */ 674 { 675 int i; 676 677 678 if (output) { 679 if (tf != stdout) 680 paper += vpos; 681 if (++scount >= spage) { 682 t_reset('p'); 683 scount = 0; 684 } 685 /******* 686 flush out the buffer. Do it in a child proc 687 this buffering was added by Bob Brown to stop the versatec 688 from smearing while waiting for the next page 689 *******/ 690 waitchild(); 691 if (fork() == 0) { 692 slop_lines(maxX); 693 ioctl(OUTFILE, VSETSTATE, prtmode); 694 if (write(OUTFILE, "\f", 2) != 2) 695 exit(RESTART); 696 ioctl(OUTFILE, VSETSTATE, pltmode); 697 exit(0); 698 } 699 #ifdef ACCOUNT 700 lines += maxX; 701 #endif 702 size = BYTES_PER_LINE * maxX; 703 vclear(buf0p, size); 704 buf0p = buffer; 705 } 706 707 maxX = 0; 708 709 vpos = 0; 710 oldv = 0; 711 output = 1; 712 if (nolist == 0) 713 return; /* no -o specified */ 714 output = 0; 715 for (i = 0; i < nolist; i += 2) 716 if (n >= olist[i] && n <= olist[i+1]) { 717 output = 1; 718 break; 719 } 720 } 721 waitchild() 722 { 723 int status; 724 while ( wait(&status) != -1 ) 725 if ( ((status>>8) & 0xff ) != 0 ) 726 exit((status>>8) & 0xff); 727 } 728 729 t_newline() /* do whatever for the end of a line */ 730 { 731 hpos = 0; /* because we're now back at the left margin */ 732 } 733 734 t_size(n) /* convert integer to internal size number*/ 735 int n; 736 { 737 int i; 738 739 if (n <= pstab[0]) 740 return(1); 741 else if (n >= pstab[nsizes-1]) 742 return(nsizes); 743 for (i = 0; n > pstab[i]; i++) 744 ; 745 return(i+1); 746 } 747 748 t_charht(n) /* set character height to n */ 749 int n; 750 { 751 if(dbg)fprintf(stderr,"can't set height on versatec yet\n"); 752 } 753 754 t_slant(n) /* set slant to n */ 755 int n; 756 { 757 if(dbg)fprintf(stderr,"can't set slant on versatec yet\n"); 758 } 759 760 t_font(s) /* convert string to internal font number */ 761 char *s; 762 { 763 int n; 764 765 n = atoi(s); 766 if (n < 0 || n > nfonts) 767 n = 1; 768 return(n); 769 } 770 771 t_text(s) /* print string s as text */ 772 char *s; 773 { 774 int c; 775 char str[100]; 776 777 if (!output) 778 return; 779 while (c = *s++) { 780 if (c == '\\') { 781 switch (c = *s++) { 782 case '\\': 783 case 'e': 784 put1('\\'); 785 break; 786 case '(': 787 str[0] = *s++; 788 str[1] = *s++; 789 str[2] = '\0'; 790 put1s(str); 791 break; 792 } 793 } else { 794 put1(c); 795 } 796 hmot(lastw); 797 if (dbg) fprintf(stderr,"width = %d\n", lastw); 798 } 799 } 800 801 t_reset(c) 802 { 803 804 805 if (output) 806 paper += vpos; 807 output = 1; 808 switch(c){ 809 case 'p': 810 waitchild(); 811 slop_lines(maxX); 812 maxX = 0; 813 buf0p = buffer; 814 break; 815 case 's': 816 waitchild(); 817 slop_lines(maxX); 818 t_done(); 819 break; /* no Return */ 820 } 821 } 822 823 t_done() /* clean up and get ready to die */ 824 { 825 waitchild(); 826 ioctl(OUTFILE, VSETSTATE, prtmode); 827 if (write(OUTFILE, "\f", 2) != 2) 828 exit(RESTART); 829 } 830 831 t_trailer() 832 { 833 vpos = oldv = 0; 834 vgoto(TRAILER); 835 vpos = oldv = 0; 836 } 837 838 vgoto(n) 839 { 840 if(n < 0){ 841 /* check to see if n would move use past buf0p */ 842 fprintf(stderr,"ERROR vgoto past the beginning"); 843 done(); /* no return */ 844 } 845 /* check for end of page */ 846 if(n > RES * 11) n -= RES * 11; /* wrap around on to the top */ 847 vpos = n; 848 849 } 850 851 put1s(s) /* s is a funny char name */ 852 char *s; 853 { 854 int i; 855 856 if (!output) 857 return; 858 if (dbg) fprintf(stderr,"%s ", s); 859 for (i = 0; i < nchtab; i++) 860 if (strcmp(&chname[chtab[i]], s) == 0) 861 break; 862 if (i < nchtab) 863 put1(i + 128); 864 } 865 866 put1(c) /* output char c */ 867 int c; 868 { 869 char *pw; 870 register char *p; 871 register int i, k; 872 int j, ofont, code; 873 874 if (!output) 875 return; 876 c -= 32; 877 if (c <= 0) { 878 if (dbg) fprintf(stderr,"non-exist 0%o\n", c + 32); 879 lastw = widthtab[font][0] * pstab[size-1] / dev.unitwidth; 880 return; 881 } 882 k = ofont = font; 883 i = fitab[font][c] & BMASK; 884 if (i != 0) { /* it's on this font */ 885 p = codetab[font]; /* get the printing value of ch */ 886 pw = widthtab[font]; /* get the width */ 887 } else if (smnt > 0) { /* on special (we hope) */ 888 for (k=smnt, j=0; j <= nfonts; j++, k = (k+1) % (nfonts+1)){ 889 if(fitab[k] == 0) 890 continue; 891 if ((i = fitab[k][c] & BMASK) != 0) { 892 p = codetab[k]; 893 pw = widthtab[k]; 894 setfont(k); 895 break; 896 } 897 } 898 } 899 if (i == 0 || (code = p[i] & BMASK) == 0 || k > nfonts) { 900 if (dbg) fprintf(stderr,"not found 0%o\n", c+32); 901 return; 902 } 903 if (dbg) { 904 if (isprint(c+32)) 905 fprintf(stderr,"%c %d\n", c+32, code); 906 else 907 fprintf(stderr,"%03o %d\n", c+32, code); 908 } else 909 outc(code); /* character is < 254 */ 910 if (font != ofont) 911 setfont(ofont); 912 lastw = pw[i] & 077; 913 lastw = (lastw * pstab[size-1] + dev.unitwidth/2) / dev.unitwidth; 914 } 915 916 /* font position info: */ 917 918 struct { 919 char *name; 920 int number; 921 } fontname[NFONT+1]; 922 923 924 setsize(n) /* set point size to n (internal) */ 925 int n; 926 { 927 928 if (n == size) 929 return; /* already there */ 930 if(vloadfont(font,pstab[n-1]) != -1) 931 size = n; 932 } 933 934 t_fp(n, s, si) /* font position n now contains font s, intname si */ 935 int n; 936 char *s, *si; 937 { 938 register i; 939 940 fontname[n].name = s; 941 fontname[n].number = atoi(si); 942 for(i = 0;i < NFONT;i++)/* free the bits of that font */ 943 if(fontdes[i].fnum == n){ 944 nfree(fontdes[i].bits); 945 fontdes[i].bits = 0; 946 fontdes[i].fnum = -1; 947 } 948 } 949 950 setfont(n) /* set font to n */ 951 int n; 952 { 953 if (n < 0 || n > NFONT) 954 error(FATAL, "illegal font %d\n", n); 955 if(vloadfont(n,pstab[size - 1]) != -1) 956 font = n; 957 } 958 959 vloadfont(fnum, fsize) 960 register int fnum; 961 register int fsize; 962 { 963 register int i; 964 965 fontwanted = 0; 966 if (fnum == cfnum && fsize == cpsize) 967 return(0); 968 for (i = 0; i < NFONTS; i++) { 969 if (fontdes[i].fnum == fnum && fontdes[i].psize == fsize) { 970 cfnum = fontdes[i].fnum; 971 cpsize = fontdes[i].psize; 972 dispatch = &fontdes[i].disp[0]; 973 bits = fontdes[i].bits; 974 cfont = i; 975 return (0); 976 } 977 } 978 /* this is a new font */ 979 if (fnum < 0 || fnum >= MAXF || fontname[fnum].name == 0) { 980 fprintf(stderr, 981 "Internal error: illegal font %d name %s size\n", 982 fontname[fnum].name,fnum,fsize); 983 return(-1); 984 } 985 /* Need to verify the existance of that font/size here*/ 986 nfontnum = fnum; 987 npsize = fsize; 988 fontwanted++; 989 return (0); 990 } 991 992 993 getfont() 994 { 995 register int fnum, fsize, fontd; 996 int d; 997 char cbuf[BUFSIZ]; 998 999 if (!fontwanted) 1000 return(0); 1001 fnum = nfontnum; 1002 fsize = npsize; 1003 sprintf(cbuf, "/usr/lib/vfont/%s.%d",fontname[fnum].name, fsize); 1004 fontd = open(cbuf, OPENREAD); 1005 if (fontd == -1) { 1006 perror(cbuf); 1007 error(0,"fnum = %d size = %d name = %s\n", 1008 fnum,fsize,fontname[fnum]); 1009 fontwanted = 0; 1010 return (-1); 1011 } 1012 if (read(fontd, &header, sizeof (header)) != sizeof (header) 1013 || header.magic != 0436) 1014 fprintf(stderr, "%s: Bad font file", cbuf); 1015 else { 1016 cfont = relfont(); 1017 if (((bits=nalloc(header.size+DSIZ+1,1))== NULL) 1018 && ((bits=allpanic(header.size+DSIZ+1))== NULL)) { 1019 fprintf(stderr,"%s: ran out of memory\n", cbuf); 1020 exit(ABORT); 1021 } else { 1022 /* 1023 * have allocated one chunk of mem for font, dispatch. 1024 * get the dispatch addr, align to word boundary. 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 } 1044 close(fontd); 1045 fontwanted = 0; 1046 return(-1); 1047 } 1048 1049 int lastloaded = -1; 1050 1051 relfont() 1052 { 1053 register int newfont; 1054 1055 newfont = lastloaded; 1056 1057 /* 1058 * optimization for special font. since we think that usually 1059 * there is only one character at a time from any special math 1060 * font, make it the candidate for removal. 1061 */ 1062 1063 if (fontdes[newfont].fnum != SPECIALFONT || fontdes[newfont].bits==0) 1064 if (++newfont>=NFONTS) 1065 newfont = 0; 1066 lastloaded = newfont; 1067 if (fontdes [newfont].bits != (char *) -1 1068 && fontdes [newfont].bits != (char *) 0) { 1069 nfree (fontdes [newfont].bits); 1070 fontdes [newfont].bits = (char *)0; 1071 /* fprintf(stderr, "freeing position %d\n", newfont); */ 1072 } /* else 1073 fprintf(stderr, "taking without freeing position %d\n", newfont); */ 1074 fontdes[newfont].bits = 0; 1075 return (newfont); 1076 } 1077 1078 char *allpanic (nbytes) 1079 int nbytes; 1080 { 1081 register int i; 1082 1083 for (i = 0; i <= NFONTS; i++) 1084 if (fontdes[i].bits != (char *)-1 && fontdes[i].bits != (char *)0) 1085 nfree(fontdes[i].bits); 1086 lastloaded = cfont; 1087 for (i = 0; i <= NFONTS; i++) { 1088 fontdes[i].fnum = fontdes[i].psize = -1; 1089 fontdes[i].bits = 0; 1090 cfnum = cpsize = -1; 1091 } 1092 return(nalloc(nbytes,1)); 1093 } 1094 1095 int M[] = { 0xffffffff, 0xfefefefe, 0xfcfcfcfc, 0xf8f8f8f8, 1096 0xf0f0f0f0, 0xe0e0e0e0, 0xc0c0c0c0, 0x80808080, 0x0 }; 1097 int N[] = { 0x00000000, 0x01010101, 0x03030303, 0x07070707, 1098 0x0f0f0f0f, 0x1f1f1f1f, 0x3f3f3f3f, 0x7f7f7f7f, 0xffffffff }; 1099 int strim[] = { 0xffffffff, 0xffffff00, 0xffff0000, 0xff000000, 0 }; 1100 1101 outc(code) 1102 int code; 1103 { 1104 char c; /* character to print */ 1105 register struct dispatch *d; /* ptr to character font record */ 1106 register char *addr; /* addr of font data */ 1107 int llen; /* length of each font line */ 1108 int nlines; /* number of font lines */ 1109 register char *scanp; /* ptr to output buffer */ 1110 int scanp_inc; /* increment to start of next buffer */ 1111 int offset; /* bit offset to start of font data */ 1112 int i; /* loop counter */ 1113 register int count; /* font data ptr */ 1114 register unsigned fontdata; /* font data temporary */ 1115 register int off8; /* offset + 8 */ 1116 1117 if (fontwanted) 1118 getfont(); 1119 c = code; 1120 d = dispatch+c; 1121 if (d->nbytes) { 1122 addr = bits+d->addr; 1123 llen = (d->left+d->right+7)/8; 1124 nlines = d->up+d->down; 1125 i = vpos + d->down; 1126 if( i > maxX ) maxX = i; /* for flush */ 1127 scanp= ((vpos-d->up-1)*BYTES_PER_LINE+(hpos-d->left)/8)+buf0p; 1128 if (scanp < &buffer[0]) 1129 scanp += sizeof buffer; 1130 scanp_inc = BYTES_PER_LINE-llen; 1131 offset = -((hpos-d->left)&07); 1132 off8 = offset+8; 1133 for (i = 0; i < nlines; i++) { 1134 if (scanp >= &buffer[BUFFER_SIZE]) 1135 scanp -= sizeof buffer; 1136 count = llen; 1137 if (scanp + count <= &buffer[BUFFER_SIZE]) 1138 do { 1139 fontdata = *(unsigned *)addr; 1140 addr += 4; 1141 if (count < 4) 1142 fontdata &= ~strim[count]; 1143 *(unsigned*)scanp |=(fontdata << offset) & ~M[off8]; 1144 scanp++; 1145 *(unsigned*)scanp |=(fontdata << off8) & ~N[off8]; 1146 scanp += 3; 1147 count -= 4; 1148 } while (count > 0); 1149 scanp += scanp_inc+count; 1150 addr += count; 1151 } 1152 return; 1153 } 1154 return; 1155 } 1156 1157 slop_lines(nlines) 1158 int nlines; 1159 1160 /* Output "nlines" lines from the buffer, and clear that section of the */ 1161 /* buffer. */ 1162 1163 { 1164 unsigned usize; 1165 1166 if(!nlines ); 1167 /* rlines = (&buffer[BUFFER_SIZE] - buf0p) / BYTES_PER_LINE; */ 1168 usize = BYTES_PER_LINE * nlines; 1169 writev(buf0p,usize); 1170 vclear(buf0p, usize); 1171 ioctl(OUTFILE, VSETSTATE, pltmode); 1172 } 1173 1174 writev(buf,usize) 1175 char *buf; 1176 unsigned usize; 1177 { 1178 register tsize = 0; 1179 while(usize){ 1180 buf += tsize; 1181 if(usize > (unsigned)(1024 * 1024)){ 1182 tsize = 1024 * 1024; 1183 }else tsize = usize; 1184 usize -= tsize; 1185 if(dbg)fprintf(stderr,"buf = %d size = %d\n",buf,tsize); 1186 1187 if (tsize != write(OUTFILE, buf, tsize)) { 1188 perror("dver: write failed"); 1189 exit(RESTART); 1190 } 1191 } 1192 } 1193 1194 vclear (ptr, nbytes) 1195 char *ptr; 1196 unsigned nbytes; 1197 { 1198 register tsize = 0; 1199 1200 while(nbytes){ 1201 if ((unsigned)(16*1024) < nbytes) { 1202 tsize = 16 * 1024; 1203 } else 1204 tsize = nbytes; 1205 nbytes -= tsize; 1206 if (dbg) fprintf(stderr,"clearing ptr = %d size = %d\n",ptr,tsize); 1207 clear(ptr,tsize); 1208 ptr += tsize; 1209 } 1210 } 1211 1212 /*ARGSUSED*/ 1213 clear(lp, nbytes) 1214 int *lp; 1215 int nbytes; 1216 { 1217 asm("movc5 $0,(sp),$0,8(ap),*4(ap)"); 1218 } 1219 1220 char * 1221 nalloc(i, j) 1222 int i, j; 1223 { 1224 register char *cp; 1225 1226 cp = calloc(i, j); 1227 if(dbg) fprintf(stderr, "allocated %d bytes at %x\n", i * j, cp); 1228 return(cp); 1229 } 1230 1231 nfree(cp) 1232 char *cp; 1233 { 1234 if(dbg) fprintf(stderr, "freeing at %x\n", cp);/* DEBUG */ 1235 free(cp); 1236 } 1237 1238 #ifdef ACCOUNT 1239 accounting(){} 1240 #endif 1241 1242 /******************************************************************************* 1243 1244 graphics routines go here 1245 1246 *******************************************************************************/ 1247 1248 drawline(){} 1249 drawcirc(){} 1250 drawellip(){} 1251 drawarc(){} 1252 drawwig(){} 1253 1254