1 #ifndef lint 2 static char Notice[] = "Copyright (c) 1984, 1985 Adobe Systems Incorporated"; 3 static char *RCSID="$Header: psdit.c,v 2.1 85/11/24 11:50:41 shore Rel $"; 4 #endif 5 # define XMOD 6 /* psdit.c 7 * 8 * Copyright (c) 1984, 1985 Adobe Systems Incorporated 9 * 10 * ditroff intermediate file to PostScript translator 11 * 12 * Original Version: Barry Hayes spring/summer 1984 13 * Edit History: 14 * Andrew Shore: Sat Nov 23 20:05:26 1985 15 * End Edit History. 16 * 17 * RCSLOG: 18 * $Log: psdit.c,v $ 19 * Revision 2.1 85/11/24 11:50:41 shore 20 * Product Release 2.0 21 * 22 * Revision 1.8 85/11/23 20:09:44 shore 23 * test for termination of included PostScript was bad 24 * 25 * Revision 1.7 85/11/21 14:23:56 shore 26 * added envget check for PSLIBDIR 27 * 28 * Revision 1.6 85/11/20 00:43:43 shore 29 * support for included PostScript 30 * big rework on FlushShow, word "breaks" 31 * removed FlushFont and made them instant 32 * Still no Gremlin support yet 33 * 34 * Revision 1.5 85/10/03 10:48:09 shore 35 * added FlushShow to xf fix ! 36 * 37 * Revision 1.4 85/10/02 16:20:32 shore 38 * fixed xf bug 39 * mounting a font causes a font switch! 40 * 41 * Revision 1.3 85/07/09 13:10:20 shore 42 * added fclose on map file 43 * 44 * Revision 1.2 85/05/14 11:24:23 shore 45 * added flush to trailer 46 * fixed read bug when mounting fonts 47 * 48 * 49 */ 50 51 /* 52 output language from troff: 53 all numbers are character strings 54 55 sn size in points 56 fn font as number from 1-n 57 cx ascii character x 58 Cxyz funny char xyz. terminated by white space 59 Hn go to absolute horizontal position n 60 Vn go to absolute vertical position n (down is positive) 61 hn go n units horizontally (relative) 62 vn ditto vertically 63 nnc move right nn, then print c (exactly 2 digits!) 64 (this wart is an optimization that shrinks output file size 65 about 35% and run-time about 15% while preserving ascii-ness) 66 Dt ...\n draw operation 't': 67 Dl x y line from here by x,y 68 Dc d circle of diameter d with left side here 69 De x y ellipse of axes x,y with left side here 70 Da x y r arc counter-clockwise by x,y of radius r 71 D~ x y x y ... wiggly line by x,y then x,y ... 72 nb a end of line (information only -- no action needed) 73 a = space before line, a = after 74 w paddable word space -- no action needed 75 pn new page begins -- set v to 0 76 { push current environment (font info & location) 77 } pop a saved environment 78 txxxx print string xxxx using natural widths 79 #...\n comment 80 x ...\n device control functions: 81 x i[nit] init 82 x T s name of device is s 83 x r[es] n h v resolution is n/inch 84 h = min horizontal motion, v = min vert 85 x p[ause] pause (can restart) 86 x s[top] stop -- done for ever 87 x t[railer] generate trailer 88 x f[font] n s font position n contains font s 89 x H[eight] n set character height to n 90 x S[slant] n set slant to N 91 92 Adobe Extension for included PostScript: 93 % 94 (raw postscript...) 95 .\n 96 97 */ 98 99 #include <stdio.h> 100 #include <ctype.h> 101 #include <signal.h> 102 #include <pwd.h> 103 #ifdef SYSV 104 extern struct passwd *getpwuid(); 105 #endif 106 #include "transcript.h" 107 108 #include "dev.h" 109 110 char *malloc(); 111 112 #define NFONT 10 113 114 /* DIT state consists of: */ 115 private int hpos; /* current horizontal position */ 116 private int vpos; /* current vertical position */ 117 private int fontsize; /* current font size */ 118 private int fontheight; /* current character height */ 119 private int fontslant; /* current font slant */ 120 private int font; /* current font */ 121 private int resolution; /* device resolution */ 122 private int minhoriz; /* minimum horizontal motion */ 123 private int minvert; /* minimum vertical motion */ 124 125 private int onspecial; 126 private int specfont; 127 private int prevfont; 128 private int pfont; 129 130 /* {} push/pop stack */ 131 #define DSTACK 10 132 private struct ditstack { 133 int hpos, vpos, fontsize, fontheight, fontslant, font; 134 } ditstack[DSTACK]; 135 private int dlevel = 0; 136 137 #define ErrorTolerance 48 138 #define PSWID 0x00000FFF 139 #define ISPSPROC 0x000FF000 140 141 142 /* PSscale is equivalent to (x * PSmag / 72000) + 0.5 */ 143 #define PSmag 16 144 #define PSscale(x) (((x)+2250)/4500) 145 146 /* we maintain PS coords with PSmag times the precision */ 147 /* current PS state is: */ 148 149 private int PSx; /* current horizontal position */ 150 private int PSy; /* current vertical position */ 151 private int savex, savey; /* position of start of current show string */ 152 153 /* ps move types -- note that XMOVE|YMOVE == XYMOVE ! */ 154 #define NONE 0 155 #define XMOVE 1 156 #define YMOVE 2 157 #define XYMOVE 3 158 159 private int movepending = NONE; 160 161 /* buffer string for show -- save up adjacent chars */ 162 #define SHOWSIZE 400 163 private char showbuf[SHOWSIZE + 3]; /* extras are for quoting */ 164 private int showind = 0; /* index into string of next available byte */ 165 private int PSshowlen = 0; /* size in big units of buffered string */ 166 private int nshow = 0; /* actual number of show chars in showbuf */ 167 private int startx; /* troff starting pos of current string */ 168 private int thisw; 169 170 /* #define NONE 0 */ 171 #define HMOT 1 172 #define VMOT 2 173 #define CPUT 4 174 #define BRK 8 175 #define FNT 16 176 private int lastcmd; 177 178 private int output = 0; /* do we do output at all? */ 179 private int nolist = 0; /* output page list if > 0 */ 180 private int olist[20]; /* pairs of page numbers */ 181 private int spage = 9999; /* stop every spage pages */ 182 private int scount = 0; 183 private int stopped = 0; 184 private int pageno = 0; 185 private int firstpage = TRUE; 186 187 private struct dev dev; 188 private struct font *fontbase[NFONT+1]; 189 private short *pstab; 190 private int dres; /* resolution from DESC */ 191 private int nsizes; /* number of point sizes from DESC */ 192 private int nfonts; /* number of fonts from DESC */ 193 private int smnt; /* index of first special font */ 194 private int nchtab; 195 private char *chname; 196 private short *chtab; 197 private char *fitab[NFONT+1]; 198 private char *widthtab[NFONT+1]; /* widtab would be a better name */ 199 private char *codetab[NFONT+1]; /* device codes */ 200 201 private int *pswidths[NFONT+1]; /* ps width tables */ 202 private int fontdelta[NFONT+1]; /* nonzero if xf overwrites font i */ 203 204 /* font position info: */ 205 private struct { 206 char *name; 207 int number; 208 } fontname[NFONT+1]; 209 210 #define FATAL 1 211 #define BMASK 0377 212 213 #ifdef DEBUG 214 int dbg = 0; 215 int fdbg = 0; 216 #define debugp(xxx) {if(dbg != 0){dbg--; printf xxx ; VOIDC fflush(stdout);}} 217 #else 218 #define debugp(x) 219 #endif 220 221 private FILE *tf = stdout; /* output file */ 222 private char devname[20] = "psc"; 223 224 private char *infilename = "stdin"; /* input file name */ 225 private char *prologfile = PSDITPRO; 226 private char *ditdir = DitDir; 227 228 private char *prog; /* argv[0] - program name */ 229 230 main(argc, argv) 231 int argc; 232 char *argv[]; 233 { 234 FILE *fp; 235 VOID done(); 236 237 prog = argv[0]; 238 while (argc > 1 && argv[1][0] == '-') { 239 switch (argv[1][1]) { 240 case 'f': 241 case 'F': 242 if (argv[1][2]) 243 ditdir = &argv[1][2]; 244 else { 245 ditdir = argv[2]; 246 argv++; 247 argc--; 248 } 249 break; 250 case 'p': 251 if (argv[1][2]) 252 prologfile = &argv[1][2]; 253 break; 254 case 'o': 255 outlist (&argv[1][2]); 256 break; 257 case 'd': 258 #ifdef DEBUG 259 dbg = atoi (&argv[1][2]); 260 if (dbg == 0) 261 dbg = 1; 262 tf = stdout; 263 #endif DEBUG 264 break; 265 case 'b': /* ignore busy */ 266 break; 267 case 'w': /* ignore wait */ 268 break; 269 case 's': 270 spage = atoi (&argv[1][2]); 271 if (spage <= 0) 272 spage = 9999; 273 break; 274 } 275 argc--; 276 argv++; 277 } 278 279 if (signal (SIGINT, done) == SIG_IGN) { 280 signal (SIGINT, SIG_IGN); 281 signal (SIGQUIT, SIG_IGN); 282 signal (SIGHUP, SIG_IGN); 283 } 284 else { 285 signal (SIGQUIT, done); 286 signal (SIGHUP, done); 287 } 288 signal (SIGTERM, done); 289 290 preface (); 291 292 if (argc <= 1) 293 conv (stdin); 294 else 295 while (--argc > 0) { 296 if (strcmp (*++argv, "-") == 0) 297 fp = stdin; 298 else if ((fp = fopen (*argv, "r")) == NULL) { 299 fprintf (stderr, "%s: can't open %s\n", prog, *argv); 300 pexit(prog,2); 301 } 302 infilename = *argv; 303 conv (fp); 304 VOIDC fclose (fp); 305 } 306 done (); 307 } 308 309 private outlist(s) /* process list of page numbers to be printed */ 310 char *s; 311 { 312 int n1, n2, i; 313 314 nolist = 0; 315 while (*s) { 316 n1 = 0; 317 if (isdigit (*s)) { 318 do { 319 n1 = 10 * n1 + *s++ - '0'; 320 } 321 while (isdigit (*s)); 322 } 323 else { 324 n1 = -9999; 325 } 326 n2 = n1; 327 if (*s == '-') { 328 s++; 329 n2 = 0; 330 if (isdigit (*s)) { 331 do { 332 n2 = 10 * n2 + *s++ - '0'; 333 } 334 while (isdigit (*s)); 335 } 336 else { 337 n2 = 9999; 338 } 339 } 340 olist[nolist++] = n1; 341 olist[nolist++] = n2; 342 if (*s != '\0') { 343 s++; 344 } 345 } 346 olist[nolist] = 0; 347 #ifdef DEBUG 348 if (dbg) 349 for (i = 0; i < nolist; i += 2) 350 printf ("%3d %3d\n", olist[i], olist[i + 1]); 351 #endif 352 } 353 354 private conv(fp) /* convert a file */ 355 register FILE *fp; 356 { 357 register int c, k; 358 int m, n, n1, m1; 359 char str[100], buf[300]; 360 361 while ((c = getc(fp)) != EOF) { 362 switch (c) { 363 case '\n': case ' ': case '\0': 364 break; 365 case '{': /* push down current environment */ 366 t_push(); 367 break; 368 case '}': 369 t_pop(); 370 break; 371 case '0': case '1': case '2': case '3': case '4': 372 case '5': case '6': case '7': case '8': case '9': 373 /* two motion digits plus a character */ 374 hmot((c - '0') * 10 + getc (fp) - '0'); 375 lastcmd = HMOT; 376 put1(getc(fp), (char *) 0); 377 lastcmd = CPUT; 378 break; 379 case 'c': /* single ascii character */ 380 put1(getc(fp), (char *) 0); 381 lastcmd = CPUT; 382 break; 383 case 'C': 384 fscanf(fp, "%s", str); 385 put1s(str); 386 lastcmd = CPUT; 387 break; 388 case 't': /* straight text */ 389 fgets(buf, sizeof (buf), fp); 390 t_text (buf); 391 lastcmd = CPUT; 392 break; 393 case 'D': /* draw function */ 394 fgets(buf, sizeof (buf), fp); 395 switch (buf[0]) { 396 case 'l': /* draw a line */ 397 sscanf (buf + 1, "%d %d", &n, &m); 398 drawline (n, m); 399 break; 400 case 'c': /* circle */ 401 sscanf (buf + 1, "%d", &n); 402 drawcirc (n); 403 break; 404 case 'e': /* ellipse */ 405 sscanf (buf + 1, "%d %d", &m, &n); 406 drawellip (m, n); 407 break; 408 case 'a': /* arc */ 409 sscanf (buf + 1, "%d %d %d %d", &n, &m, &n1, &m1); 410 drawarc (n, m, n1, m1); 411 break; 412 case '~': /* wiggly line */ 413 drawwig (buf + 1); 414 break; 415 default: 416 fprintf(stderr,"%s: unknown drawing function %s\n", 417 prog,buf); 418 exit(2); 419 break; 420 } 421 break; 422 case 's': 423 fscanf (fp, "%d", &n); 424 t_size (n); 425 lastcmd = FNT; 426 break; 427 case 'f': 428 fscanf (fp, "%s", str); 429 setfont (t_font (str)); 430 lastcmd = FNT; 431 break; 432 case 'H': /* absolute horizontal motion */ 433 while ((c = getc (fp)) == ' '); 434 k = 0; 435 do { 436 k = 10 * k + c - '0'; 437 } while (isdigit (c = getc (fp))); 438 ungetc (c, fp); 439 hgoto (k); 440 lastcmd = HMOT; 441 break; 442 case 'h': /* relative horizontal motion */ 443 while ((c = getc (fp)) == ' '); 444 k = 0; 445 do { 446 k = 10 * k + c - '0'; 447 } while (isdigit (c = getc (fp))); 448 ungetc (c, fp); 449 hmot (k); 450 lastcmd = HMOT; 451 break; 452 case 'w': 453 FlushShow(1); 454 lastcmd = BRK; 455 break; 456 case 'V': 457 fscanf (fp, "%d", &n); 458 vgoto (n); 459 lastcmd = VMOT; 460 break; 461 case 'v': 462 fscanf (fp, "%d", &n); 463 vmot (n); 464 lastcmd = VMOT; 465 break; 466 case 'p': /* new page */ 467 fscanf (fp, "%d", &n); 468 t_page (n); 469 lastcmd = NONE; 470 break; 471 case 'n': /* end of line -- ignore */ 472 while (getc (fp) != '\n'); 473 FlushShow(1); 474 lastcmd = BRK; 475 break; 476 case '#': /* comment */ 477 /* maybe should pass through as a PS comment */ 478 while (getc (fp) != '\n'); 479 break; 480 case 'x': /* device control */ 481 devcntrl (fp); 482 break; 483 case '%': /* imbedded PostScript */ 484 /* copy everything up to but NOT including a line */ 485 /* with at single "." */ 486 FlushShow(0);MoveTo();DoMove(); 487 printf("\n%% included PostScript\n"); 488 while (fgets(buf, sizeof buf, fp) != NULL) { 489 if (strcmp(".\n",buf) == 0) break; 490 fputs(buf,stdout); 491 } 492 break; 493 default: 494 fprintf(stderr,"%s: bad input char \\%03o (%c)\n",prog,c,c); 495 exit(2); 496 done (); 497 } 498 } 499 } 500 501 502 /* put in PostScript prolog */ 503 private preface() 504 { 505 register FILE *prolog; 506 char hostname[256]; 507 char tempfile[512]; 508 struct passwd *pswd; 509 long clock; 510 char *libdir; 511 512 fprintf (tf, "%%!%s\n", COMMENTVERSION); 513 pswd = getpwuid (getuid ()); 514 VOIDC gethostname (hostname, sizeof hostname); 515 fprintf (tf, "%%%%Creator: %s:%s (%s)\n", hostname, 516 pswd->pw_name, pswd->pw_gecos); 517 fprintf (tf, "%%%%Title: %s (ditroff)\n", infilename); 518 fprintf (tf, "%%%%CreationDate: %s", 519 (time (&clock), ctime (&clock))); 520 fprintf (tf, "%%%%EndComments\n"); 521 522 if ((libdir = envget("PSLIBDIR")) == NULL) libdir = LibDir; 523 mstrcat(tempfile, libdir, prologfile, sizeof tempfile); 524 if ((copyfile(tempfile, stdout)) != 0) { 525 fprintf(stderr,"%s: can't copy prolog file %s\n",prog, tempfile); 526 exit(2); 527 } 528 printf ("ditstart\n"); 529 } 530 531 private devcntrl(fp) /* interpret device control functions */ 532 FILE *fp; 533 { 534 char str[20], str1[50], buf[50]; 535 int c, n, res, minh, minv; 536 537 fscanf (fp, "%s", str); 538 switch (str[0]) { /* crude for now */ 539 case 'i': /* initialize */ 540 fileinit (); 541 t_init (); 542 lastcmd = NONE; 543 break; 544 case 'T': /* device name */ 545 fscanf (fp, "%s", devname); 546 if (strcmp (devname, "psc")) { 547 fprintf(stderr,"%s: device not psc\n",prog); 548 exit(2); 549 } 550 printf ("(%s)xT\n", devname); 551 lastcmd = NONE; 552 break; 553 case 't': /* trailer */ 554 t_trailer (); 555 lastcmd = NONE; 556 break; 557 case 'p': /* pause -- can restart */ 558 t_reset ('p'); 559 lastcmd = NONE; 560 break; 561 case 's': /* stop */ 562 t_reset ('s'); 563 lastcmd = NONE; 564 break; 565 case 'r': /* resolution assumed when prepared */ 566 fscanf (fp, "%d %d %d", &res, &minh, &minv); 567 t_res (res, minh, minv); 568 lastcmd = NONE; 569 break; 570 case 'f': /* font used */ 571 fscanf (fp, "%d %s", &n, str); 572 fgets (buf, sizeof buf, fp);/* in case theres a filename */ 573 ungetc ('\n', fp); /* fgets goes too far */ 574 str1[0] = 0; /* in case there is nothing to come in */ 575 sscanf (buf, "%s", str1); 576 loadfont (n, str, str1); 577 lastcmd = FNT; 578 break; 579 case 'H': /* char height */ 580 fscanf (fp, "%d", &n); 581 t_charht (n); 582 lastcmd = FNT; 583 break; 584 case 'S': /* slant */ 585 fscanf (fp, "%d", &n); 586 t_slant (n); 587 lastcmd = FNT; 588 break; 589 #ifdef XMOD 590 case 'X': { /* \X command from ditroff */ 591 int last; 592 char largebuf[128]; 593 fscanf (fp, "%1s", str); 594 switch (str[0]) { 595 case 'p' : 596 FlushShow(0);MoveTo();DoMove(); 597 fgets(largebuf, sizeof(largebuf), fp); 598 last = strlen(largebuf) - 1; 599 if (last >= 0 && largebuf[last] == '\n') { 600 ungetc('\n', fp); 601 largebuf[last] = ' '; 602 } 603 fputs(largebuf, tf); 604 putc('\n', tf); 605 break; 606 case 'f' : 607 FlushShow(0);MoveTo();DoMove(); 608 if (fscanf(fp, "%s", largebuf) == 1) { 609 char *nl = (char *) index(largebuf, '\n'); 610 if (nl) *nl = '\0'; 611 includefile(largebuf); 612 } else 613 fprintf(stderr, "warning - include cmd w/o path.\n"); 614 break; 615 } 616 } 617 break; 618 #endif 619 } 620 /* skip rest of input line */ 621 while ((c = getc (fp)) != '\n') {if (c == EOF) break;}; 622 } 623 624 #ifdef XMOD 625 includefile(filenm) 626 char *filenm; { 627 628 FILE *inf; 629 int ch, c1, c2, firstch = 0; 630 631 if (!(inf = fopen(filenm, "r"))) { 632 fprintf(stderr, "psdit: fopen(%s): ", filenm); 633 perror(); 634 exit(1); 635 } 636 c1 = fgetc(inf); c2 = fgetc(inf); 637 if (c1 != '%' || c2 != '!') 638 fprintf(stderr, "psdit: %s not a postscript file.\n", filenm), 639 exit(1); 640 641 fputs("%!", tf); 642 while ((ch = fgetc(inf)) != EOF) { 643 fputc(ch, tf); 644 if (firstch && ch == '%') { 645 /* we have to double leading '%'s */ 646 fputc('%', tf); 647 } 648 firstch = (ch == '\n'); 649 } 650 fclose(inf); 651 } 652 #endif 653 private fileinit() /* read in font and code files, etc. */ 654 { 655 int i, fin, nw; 656 char *filebase, *p; 657 char temp[60]; 658 unsigned msize; 659 660 /* open table for device, 661 * read in resolution, size info, font info, etc. and set params */ 662 663 sprintf (temp, "%s/dev%s/DESC.out", ditdir, devname); 664 if ((fin = open (temp, 0)) < 0) { 665 fprintf (stderr, "%s: can't open %s - %s\n", prog, devname, temp); 666 pexit(prog,2); 667 } 668 if (read(fin,(char *)&dev, (int) sizeof(struct dev)) != sizeof(struct dev)) { 669 fprintf (stderr, "%s: can't read %s\n", prog, temp); 670 pexit(prog,2); 671 } 672 dres = dev.res; 673 nfonts = dev.nfonts; 674 nsizes = dev.nsizes; 675 nchtab = dev.nchtab; 676 /* enough room for whole file */ 677 filebase = malloc ((unsigned) dev.filesize); 678 if (read (fin, filebase, dev.filesize) != dev.filesize) { 679 fprintf (stderr, "%s: trouble reading %s\n", prog, temp); 680 pexit(prog,2); 681 } 682 pstab = (short *) filebase; /* point size table */ 683 chtab = pstab + nsizes + 1; /* char index table */ 684 chname = (char *) (chtab + dev.nchtab); /* char name table */ 685 p = chname + dev.lchname; /* end of char name table */ 686 /* parse the preloaded font tables */ 687 for (i = 1; i <= nfonts; i++) { 688 fontdelta[i] = 0; 689 fontbase[i] = (struct font *) p; 690 nw = *p & BMASK; /* number of width entries */ 691 if ((smnt == 0) && (fontbase[i]->specfont == 1)) 692 smnt = i; /* first special font */ 693 p += sizeof (struct font); /* skip header */ 694 widthtab[i] = p; /* width table */ 695 /* kern table is next */ 696 codetab[i] = p + 2 * nw; /* device codes */ 697 fitab[i] = p + 3 * nw; /* font index table */ 698 699 p += 3 * nw + dev.nchtab + (128 - 32); /* next font */ 700 t_fp (i, fontbase[i]->namefont, fontbase[i]->intname); 701 loadpswidths (i, fontbase[i]->namefont); 702 sayload (i, fontbase[i]->namefont, (char *) 0); 703 #ifdef DEBUG 704 if (fdbg > 1) 705 fontprint (i); 706 #endif 707 } 708 fontdelta[0] = 0; 709 msize = 3*255 + dev.nchtab + (128-32) + sizeof (struct font); 710 fontbase[0] = (struct font *) malloc(msize); 711 widthtab[0] = (char *) fontbase[0] + sizeof (struct font); 712 fontbase[0]->nwfont = 255; 713 close (fin); 714 } 715 716 private loadpswidths(i,name) 717 int i; 718 char *name; 719 { 720 char temp[60]; 721 register FILE *auxin; 722 register int j; 723 int cc, wid, funny; 724 725 sprintf(temp, "%s/dev%s/%s.aux", ditdir, devname, name); 726 auxin = fopen(temp, "r"); 727 /* allocate table */ 728 if (pswidths[i] == NULL) { 729 pswidths[i] = (int *) malloc(256 * (sizeof (int))); 730 } 731 /* initialize to not-there */ 732 for (j = 0; j <= 255; pswidths[i][j++] = -1); 733 /* read them in */ 734 while (fscanf(auxin, "%d %d %d", &cc, &wid, &funny) != EOF) { 735 pswidths[i][cc] = wid | (funny << 12); 736 } 737 VOIDC fclose(auxin); 738 } 739 740 #ifdef DEBUG 741 private fontprint(i) /* debugging print of font i (0,...) */ 742 int i; 743 { 744 int j, n; 745 char *p; 746 747 printf ("font %d:\n", i); 748 p = (char *) fontbase[i]; 749 n = fontbase[i]->nwfont & BMASK; 750 printf ("base=0%o, nchars=%d, spec=%d, name=%s, widtab=0%o, fitab=0%o\n", 751 p, n, fontbase[i]->specfont, 752 fontbase[i]->namefont, widthtab[i], fitab[i]); 753 printf ("widths:\n"); 754 for (j = 0; j <= n; j++) { 755 printf (" %2d", widthtab[i][j] & BMASK); 756 if (j % 20 == 19) 757 printf ("\n"); 758 } 759 printf ("\ncodetab:\n"); 760 for (j = 0; j <= n; j++) { 761 printf (" %2d", codetab[i][j] & BMASK); 762 if (j % 20 == 19) 763 printf ("\n"); 764 } 765 printf ("\nfitab:\n"); 766 for (j = 0; j <= dev.nchtab + 128 - 32; j++) { 767 printf (" %2d", fitab[i][j] & BMASK); 768 if (j % 20 == 19) 769 printf ("\n"); 770 } 771 printf ("\n"); 772 } 773 #endif 774 775 private loadfont(n, s, s1) /* load font info for font s on position n */ 776 int n; 777 char *s, *s1; 778 { 779 char temp[60]; 780 int fin, nw, norig; 781 int bcount; 782 783 if (n < 0 || n > NFONT) { 784 fprintf(stderr,"%s: illegal fp command %d %s\n", prog, n, s); 785 exit(2); 786 } 787 if (strcmp(s, fontbase[n]->namefont) == 0) return; 788 if (fontbase[n]->namefont != 0) { 789 fontdelta[n] = 1; 790 } 791 if (s1 == NULL || s1[0] == '\0') { 792 sprintf (temp, "%s/dev%s/%s.out", ditdir, devname, s); 793 } 794 else { 795 sprintf (temp, "%s/%s.out", s1, s); 796 } 797 if ((fin = open (temp, 0)) < 0) { 798 fprintf(stderr,"%s: can't open font table %s\n", prog, temp); 799 pexit(prog,2); 800 } 801 norig = fontbase[n]->nwfont & BMASK; 802 bcount = 3 * norig + nchtab + 128 - 32 + sizeof (struct font); 803 VOIDC read (fin, (char *)fontbase[n], bcount); 804 if ((fontbase[n]->nwfont & BMASK) > norig) { 805 fprintf(stderr,"%s: Font %s too big for position %d\n", prog, s, n); 806 exit(2); 807 } 808 close (fin); 809 nw = fontbase[n]->nwfont & BMASK; 810 widthtab[n] = (char *) fontbase[n] + sizeof (struct font); 811 codetab[n] = (char *) widthtab[n] + 2 * nw; 812 fitab[n] = (char *) widthtab[n] + 3 * nw; 813 t_fp (n, fontbase[n]->namefont, fontbase[n]->intname); 814 loadpswidths (n, fontbase[n]->namefont); 815 sayload (n, s, s1); 816 fontbase[n]->nwfont = norig; /* so can later use full original size */ 817 #ifdef DEBUG 818 if (fdbg > 1) 819 fontprint (n); 820 #endif 821 } 822 823 private sayload(n, s, s1) /* position n contains font s (internal s1) */ 824 int n; 825 char *s, *s1; 826 { 827 char pass[60]; 828 FILE *ptrfile; 829 char Adobefont[60]; 830 831 if (s1 == NULL || s1[0] == '\0') { 832 sprintf (pass, "%s/dev%s/%s.map", ditdir, devname, s); 833 } 834 else { 835 sprintf (pass, "%s/%s.map", s1, s); 836 } 837 838 if ((ptrfile = fopen (pass, "r")) == NULL) { 839 fprintf(stderr,"%s: can't open font map file %s\n", prog, pass); 840 pexit(prog,2); 841 } 842 843 fscanf (ptrfile, "%s", Adobefont); 844 FlushShow(0); 845 printf ("%d(%s)xf %d f\n", n, Adobefont, n); 846 font = n; 847 VOIDC fclose(ptrfile); 848 } 849 850 private VOID done() 851 { 852 if (tf == NULL) 853 exit (1); 854 t_reset ('s'); 855 exit (0); 856 } 857 858 private t_init() /* "x i" - initialize device */ 859 { 860 movepending = NONE; 861 savex = savey = 0; 862 863 t_size (10); /* start somewhere */ 864 t_slant (0); 865 setfont (1); /* set font */ 866 printf("xi\n"); 867 printf("%%%%EndProlog\n"); 868 } 869 870 private t_push() /* begin a new block */ 871 { 872 FlushShow(1);MoveTo();DoMove(); 873 if (dlevel == DSTACK) { 874 fprintf(stderr,"%s: ditroff push/pop overflow!\n",prog); 875 exit(2); 876 } 877 ditstack[dlevel].hpos = hpos; 878 ditstack[dlevel].vpos = vpos; 879 ditstack[dlevel].fontsize = fontsize; 880 ditstack[dlevel].fontheight = fontheight; 881 ditstack[dlevel].fontslant = fontslant; 882 ditstack[dlevel].font = font; 883 dlevel++; 884 printf ("\nditpush\n"); 885 } 886 887 private t_pop() /* pop to previous state */ 888 { 889 FlushShow(1);MoveTo();DoMove(); 890 if (dlevel == 0) { 891 fprintf(stderr,"%s: ditroff push/pop underflow!\n",prog); 892 exit(2); 893 } 894 dlevel--; 895 hpos = ditstack[dlevel].hpos; 896 vpos = ditstack[dlevel].vpos; 897 fontsize = ditstack[dlevel].fontsize; 898 fontheight = ditstack[dlevel].fontheight; 899 fontslant = ditstack[dlevel].fontslant; 900 font = ditstack[dlevel].font; 901 printf ("%d s %d xH %d xS %d f\n",fontsize,fontheight,fontslant,font); 902 startx = savex = hpos; 903 savey = vpos; 904 PSx = hpos * PSmag; 905 PSy = vpos * PSmag; 906 printf("%d %d MXY\n",savex,savey); 907 movepending = NONE; 908 printf("\nditpop\n"); 909 } 910 911 private t_page(n) /* do whatever new page functions */ 912 { 913 int i; 914 915 if (output) { 916 if (++scount >= spage) { 917 t_reset ('p'); 918 scount = 0; 919 } 920 } 921 output = 1; 922 FlushShow(0); 923 if (!firstpage) { 924 printf("\n%d p",n); 925 } 926 firstpage = FALSE; 927 printf ("\n%%%%Page: %d %d\n", n, ++pageno, n); 928 for (i = 0; i <= nfonts; i++) { 929 if (fontdelta[i] != 0) { 930 sayload (i, fontname[i].name, (char *) 0); 931 } 932 } 933 vpos = 0; 934 PSy = 0; 935 printf ("%d s %d xH %d xS %d f\n",fontsize,fontheight,fontslant,font); 936 if (nolist == 0) 937 return; 938 output = 0; 939 for (i = 0; i < nolist; i += 2) 940 if (n >= olist[i] && n <= olist[i + 1]) { 941 output = 1; 942 break; 943 } 944 } 945 946 private t_size(n) /* convert integer to internal size number*/ 947 int n; 948 { 949 FlushShow(1); 950 if (fontsize != n) { 951 fontsize = n; 952 #ifdef XMOD 953 fontheight = n; 954 #endif 955 printf("%d s\n",fontsize); 956 } 957 } 958 959 private t_charht(n) /* set character height to n */ 960 int n; 961 { 962 FlushShow(1); 963 if (fontheight != n) { 964 fontheight = n; 965 printf("%d xH\n",fontheight); 966 } 967 } 968 969 private t_slant(n) /* set slant to n */ 970 int n; 971 { 972 FlushShow(1); 973 if (fontslant != n) { 974 fontslant = n; 975 printf("%d xS\n",fontslant); 976 } 977 } 978 979 private t_font(s) /* convert string to internal font number */ 980 char *s; 981 { 982 int n; 983 984 n = atoi (s); 985 if (n < 0 || n > nfonts) n = 1; 986 return (n); 987 } 988 989 private t_text(s) /* print string s as text??? */ 990 char *s; 991 { 992 fprintf(stderr,"%s: ditroff t <%s> unimplemented!\n",prog,s); 993 } 994 995 private t_reset(c) 996 { 997 output = 1; /* by God */ 998 if (c == 'p') { 999 printf ("\nxp\n"); 1000 } 1001 else { 1002 if (!stopped) 1003 printf ("\nxs\n"); 1004 stopped = 1; 1005 } 1006 fflush (tf); 1007 } 1008 1009 private t_res(res, minh, minv) 1010 int res, minh, minv; 1011 { 1012 resolution = res; 1013 minhoriz = minh; 1014 minvert = minv; 1015 printf ("%d %d %d xr\n", res, minh, minv); 1016 } 1017 1018 private t_trailer() 1019 { 1020 FlushShow(0); 1021 printf("\n%d p",pageno); 1022 printf("\n%%%%Trailer\n"); 1023 printf("xt\n"); 1024 } 1025 1026 private put1s(s) /* s is a funny char name */ 1027 char *s; 1028 { 1029 int i; 1030 1031 if (!output) return; 1032 debugp(("%s ", s)); 1033 1034 /* search for s in the funny char name table */ 1035 for (i = 0; i < nchtab; i++) { 1036 if (strcmp(&chname[chtab[i]], s) == 0) break; 1037 } 1038 1039 if (i < nchtab) { 1040 put1(i + 128, s); 1041 } 1042 else { 1043 debugp(("not found ")); 1044 putnf (0, s); 1045 } 1046 } 1047 1048 #define needsescape(c) ((c=='\\') || (c=='(') || (c==')')) 1049 1050 private put1(c, s) /* output char c */ 1051 int c; 1052 char *s; 1053 { 1054 char *pw; 1055 register char *p; 1056 register int i, k; 1057 register int cc; 1058 int ofont, code; 1059 int psinfo, pswid, tw; 1060 1061 if (!output) return; 1062 if (c == 32) { 1063 thisw = 0; 1064 FlushShow(0); 1065 return; 1066 } 1067 if (c < 32) { 1068 debugp(("non-exist 0%o\n",c)); 1069 return; 1070 } 1071 1072 c -= 32; /* offset char code */ 1073 k = ofont = pfont = font; 1074 if (onspecial) pfont = prevfont; 1075 1076 if ((i = (fitab[pfont][c] & BMASK)) != 0) {/* char on this font */ 1077 p = codetab[pfont]; 1078 pw = widthtab[pfont]; 1079 if (onspecial) { 1080 setfont(prevfont); 1081 thisw = 0; 1082 onspecial = 0; 1083 } 1084 } 1085 else if (smnt > 0) { /* on special (we hope) */ 1086 for (k = smnt; k <= nfonts; k += 1) 1087 if ((i = (fitab[k][c] & BMASK)) != 0) { 1088 p = codetab[k]; 1089 pw = widthtab[k]; 1090 prevfont = pfont; 1091 if (onspecial && (k == specfont)) break; 1092 setfont (k); 1093 thisw = 0; 1094 onspecial = 1; 1095 specfont = k; 1096 break; 1097 } 1098 } 1099 if ((i == 0) || (k > nfonts) || ((code = p[i] & BMASK) == 0)) { 1100 debugp(("not found 0%o\n", c+32)); 1101 putnf (c + 32, s); 1102 return; 1103 } 1104 /* when we get here, 1105 * c == biased character code 1106 * k == font number 1107 * i == index into codetab and widthtab for this character 1108 * p == codetab for this font 1109 * pw == width tab for this font 1110 * code == character code for this char 1111 */ 1112 1113 cc = c + 32; 1114 debugp(((isascii(cc) && isprint(cc)) ? "%c %d\n":"%03o %d\n", 1115 cc, code)); 1116 psinfo = pswidths[font][code]; /* PS specific char info */ 1117 pswid = psinfo & PSWID; /* PS character width */ 1118 thisw = pw[i] & BMASK; /* troff char width */ 1119 tw = thisw = (thisw * fontsize + dev.unitwidth/2) / dev.unitwidth; 1120 1121 if ((psinfo & ISPSPROC) && (psinfo != -1)) { 1122 /* character is implemented by a PostScript proc */ 1123 showspecial(s, code, pswid); 1124 if (pswid > 0) { 1125 PSx += PSscale(pswid * fontsize * dres); 1126 } 1127 thisw = 0; 1128 } 1129 else { 1130 showchar(code); 1131 if (pswid > 0) { 1132 PSshowlen += PSscale(pswid * fontsize * dres); 1133 } 1134 } 1135 1136 /* 1137 if (font != ofont) { 1138 setfont(ofont); 1139 startx = hpos + tw; 1140 thisw = 0; 1141 lastcmd = FNT; 1142 } 1143 */ 1144 debugp(("...width (%d)\n", pw[i]&BMASK)); 1145 } 1146 1147 1148 private putnf(c, s) /* note that a character wasnt found */ 1149 int c; 1150 char *s; 1151 { 1152 1153 FlushShow(0); 1154 thisw = 0; 1155 if ((s == NULL) || (*s == '\0')) printf("(\%3o)cb\n", c); 1156 else if ((strcmp(s, "\\|") == 0) || (strcmp(s, "\\^") == 0) 1157 || (strcmp (s, "\\&") == 0)) 1158 return; 1159 else 1160 printf("(%s)cb\n", s); 1161 } 1162 1163 1164 private t_fp(n, s, si) /* font position n now contains font s, intname si */ 1165 int n; /* position */ 1166 char *s; /* font (ditname) */ 1167 char *si; /* font (intname = number) */ 1168 { 1169 fontname[n].name = s; 1170 fontname[n].number = atoi (si); 1171 } 1172 1173 private setfont(n) /* set font to n */ 1174 int n; 1175 { 1176 FlushShow(1); 1177 1178 if (n < 0 || n > NFONT) { 1179 fprintf(stderr,"%s: illegal font %d\n", prog,n); 1180 } 1181 if (font != n) { 1182 font = n; 1183 printf("%d f\n",font); 1184 } 1185 onspecial = 0; 1186 } 1187 1188 private drawline(dx, dy) /* draw line from here to dx, dy */ 1189 int dx, dy; 1190 { 1191 FlushShow(0); MoveTo(); DoMove(); 1192 printf("%d %d Dl\n", dx, dy); 1193 hpos += dx; 1194 PSx = hpos * PSmag; 1195 vpos += dy; 1196 PSy = vpos * PSmag; 1197 } 1198 1199 private drawwig(s) /* draw wiggly line */ 1200 char *s; 1201 { 1202 FlushShow(0); MoveTo(); DoMove(); 1203 printf("D~ %s D~~\n",s); 1204 } 1205 1206 private drawcirc(d) 1207 int d; 1208 { 1209 FlushShow(0); MoveTo(); DoMove(); 1210 printf("%d Dc\n",d); 1211 } 1212 1213 private drawarc(dx1, dy1, dx2, dy2) 1214 int dx1, dy1, dx2, dy2; 1215 { 1216 FlushShow(0); MoveTo(); DoMove(); 1217 printf("%d %d %d %d Da\n", dx1, dy1, dx2, dy2); 1218 hpos += dx1 + dx2; 1219 PSx = hpos * PSmag; 1220 vpos += dy1 + dy2; 1221 PSy = vpos * PSmag; 1222 } 1223 1224 private drawellip(a, b) 1225 int a, b; 1226 { 1227 FlushShow(0);MoveTo();DoMove(); 1228 printf("%d %d De\n",a,b); 1229 } 1230 1231 private hmot(a) /* relative horizontal motion */ 1232 int a; 1233 { 1234 register int aa; 1235 aa = abs(a); 1236 if ((aa < 8) || (aa > (10 * thisw)) || (a >= 100) 1237 || ((thisw != 0) && (abs(thisw - a) > 4))) { 1238 FlushShow(1); 1239 } 1240 hpos += a; 1241 if (lastcmd != CPUT) startx = hpos; 1242 } 1243 1244 private hgoto(a) /* absolute horizontal motion */ 1245 int a; 1246 { 1247 FlushShow(1); 1248 startx = hpos = a; 1249 thisw = 0; 1250 } 1251 1252 private vmot(a) /* relative vertical motion */ 1253 int a; 1254 { 1255 FlushShow(1); 1256 vpos += a; 1257 thisw = 0; 1258 } 1259 1260 private vgoto(a) /* absolute vertical motion */ 1261 int a; 1262 { 1263 FlushShow(1); 1264 vpos = a; 1265 thisw = 0; 1266 } 1267 1268 private showspecial(s,cc,wid) 1269 char *s; 1270 int cc; 1271 int wid; 1272 { 1273 char *sp; 1274 1275 FlushShow(0); 1276 MoveTo(); 1277 DoMove(); 1278 putchar('('); 1279 for (sp = s; *sp != '\0'; sp++) { 1280 if (needsescape(*sp)) { 1281 putchar('\\'); 1282 } 1283 putchar(*sp); 1284 } 1285 printf(")%d %d oc\n",cc,wid); 1286 } 1287 1288 private showchar(c) 1289 int c; 1290 { 1291 if (showind == 0) {MoveTo();} 1292 else if ((vpos * PSmag) != PSy) { 1293 FlushShow(0); 1294 MoveTo(); 1295 } 1296 if (showind >= SHOWSIZE) FlushShow(0); 1297 if (isascii(c) && isprint(c)) { 1298 switch (c) { 1299 case '\\': case '(': case ')': 1300 showbuf[showind++] = '\\'; 1301 /* fall through */ 1302 1303 default: 1304 showbuf[showind++] = c; 1305 } 1306 } 1307 else { 1308 showbuf[showind++] = '\\'; 1309 showbuf[showind++] = ((c>>6)&03) + '0'; 1310 showbuf[showind++] = ((c>>3)&07) + '0'; 1311 showbuf[showind++] = (c&07) + '0'; 1312 } 1313 showbuf[showind] = '\0'; 1314 nshow++; 1315 } 1316 1317 private MoveTo() { 1318 int x, y; 1319 x = hpos * PSmag; 1320 y = vpos * PSmag; 1321 1322 if (x != PSx) { 1323 startx = savex = hpos; 1324 PSx = x; 1325 movepending |= XMOVE; 1326 } 1327 if (y != PSy) { 1328 savey = vpos; 1329 PSy = y; 1330 movepending |= YMOVE; 1331 } 1332 } 1333 1334 private FlushMove() { 1335 switch (movepending) { 1336 case NONE: 1337 break; 1338 case XMOVE: 1339 printf("%d",savex); 1340 break; 1341 case YMOVE: 1342 printf("%d",savey); 1343 break; 1344 case XYMOVE: 1345 printf("%d %d",savex,savey); 1346 break; 1347 default: 1348 fprintf(stderr,"%s: invalid move code %d\n",prog, movepending); 1349 exit(2); 1350 } 1351 } 1352 1353 private char *movecmds[] = { 1354 "MX","MY","MXY" 1355 }; 1356 1357 private DoMove() { 1358 FlushMove(); 1359 if (movepending != NONE) { 1360 printf(" %s\n",movecmds[movepending-1]); 1361 movepending = NONE; 1362 } 1363 } 1364 1365 private char showops[] = "SXYN"; 1366 1367 private FlushShow(t) int t; { 1368 long err, tlen; 1369 float cerror; 1370 1371 if (showind == 0) {thisw = 0; return;} 1372 if (movepending != NONE) { 1373 FlushMove(); 1374 } 1375 tlen = hpos - startx; 1376 if (lastcmd == CPUT) tlen += thisw; 1377 err = tlen * PSmag - PSshowlen; 1378 if ((nshow != 1) && (abs(err) > ErrorTolerance)) { 1379 cerror = ((float) err) / ((nshow - 1) * PSmag); 1380 #ifdef DEBUG 1381 fprintf(stderr,"F%d lc %d thisw %d ",t,lastcmd,thisw); 1382 fprintf(stderr,"x %ld h %ld tn %ld %ld ", 1383 startx, hpos, tlen*PSmag,PSshowlen); 1384 fprintf(stderr,"error %d %.4f %s\n",nshow,cerror,showbuf); 1385 fflush(stderr); 1386 #endif 1387 printf(" %.4f(%s)A%c\n", cerror, showbuf, showops[movepending]); 1388 } 1389 else { 1390 printf("(%s)%c\n", showbuf, showops[movepending]); 1391 } 1392 1393 showind = 0; 1394 nshow = 0; 1395 showbuf[showind] = '\0'; 1396 PSx += PSshowlen; 1397 PSshowlen = 0; 1398 startx = hpos; 1399 if (lastcmd == CPUT) startx += thisw; 1400 thisw = 0; 1401 movepending = NONE; 1402 } 1403