1 /* psdit.c 1.1 87/03/08 */ 2 #ifndef lint 3 static char Notice[] = "Copyright (c) 1984, 1985 Adobe Systems Incorporated"; 4 static char *RCSID="$Header: psdit.c,v 2.1 85/11/24 11:50:41 shore Rel $"; 5 #endif 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 } 590 /* skip rest of input line */ 591 while ((c = getc (fp)) != '\n') {if (c == EOF) break;}; 592 } 593 594 private fileinit() /* read in font and code files, etc. */ 595 { 596 int i, fin, nw; 597 char *filebase, *p; 598 char temp[60]; 599 unsigned msize; 600 601 /* open table for device, 602 * read in resolution, size info, font info, etc. and set params */ 603 604 sprintf (temp, "%s/dev%s/DESC.out", ditdir, devname); 605 if ((fin = open (temp, 0)) < 0) { 606 fprintf (stderr, "%s: can't open %s - %s\n", prog, devname, temp); 607 pexit(prog,2); 608 } 609 if (read(fin,(char *)&dev, (int) sizeof(struct dev)) != sizeof(struct dev)) { 610 fprintf (stderr, "%s: can't read %s\n", prog, temp); 611 pexit(prog,2); 612 } 613 dres = dev.res; 614 nfonts = dev.nfonts; 615 nsizes = dev.nsizes; 616 nchtab = dev.nchtab; 617 /* enough room for whole file */ 618 filebase = malloc ((unsigned) dev.filesize); 619 if (read (fin, filebase, dev.filesize) != dev.filesize) { 620 fprintf (stderr, "%s: trouble reading %s\n", prog, temp); 621 pexit(prog,2); 622 } 623 pstab = (short *) filebase; /* point size table */ 624 chtab = pstab + nsizes + 1; /* char index table */ 625 chname = (char *) (chtab + dev.nchtab); /* char name table */ 626 p = chname + dev.lchname; /* end of char name table */ 627 /* parse the preloaded font tables */ 628 for (i = 1; i <= nfonts; i++) { 629 fontdelta[i] = 0; 630 fontbase[i] = (struct font *) p; 631 nw = *p & BMASK; /* number of width entries */ 632 if ((smnt == 0) && (fontbase[i]->specfont == 1)) 633 smnt = i; /* first special font */ 634 p += sizeof (struct font); /* skip header */ 635 widthtab[i] = p; /* width table */ 636 /* kern table is next */ 637 codetab[i] = p + 2 * nw; /* device codes */ 638 fitab[i] = p + 3 * nw; /* font index table */ 639 640 p += 3 * nw + dev.nchtab + (128 - 32); /* next font */ 641 t_fp (i, fontbase[i]->namefont, fontbase[i]->intname); 642 loadpswidths (i, fontbase[i]->namefont); 643 sayload (i, fontbase[i]->namefont, (char *) 0); 644 #ifdef DEBUG 645 if (fdbg > 1) 646 fontprint (i); 647 #endif 648 } 649 fontdelta[0] = 0; 650 msize = 3*255 + dev.nchtab + (128-32) + sizeof (struct font); 651 fontbase[0] = (struct font *) malloc(msize); 652 widthtab[0] = (char *) fontbase[0] + sizeof (struct font); 653 fontbase[0]->nwfont = 255; 654 close (fin); 655 } 656 657 private loadpswidths(i,name) 658 int i; 659 char *name; 660 { 661 char temp[60]; 662 register FILE *auxin; 663 register int j; 664 int cc, wid, funny; 665 666 sprintf(temp, "%s/dev%s/%s.aux", ditdir, devname, name); 667 auxin = fopen(temp, "r"); 668 /* allocate table */ 669 if (pswidths[i] == NULL) { 670 pswidths[i] = (int *) malloc(256 * (sizeof (int))); 671 } 672 /* initialize to not-there */ 673 for (j = 0; j <= 255; pswidths[i][j++] = -1); 674 /* read them in */ 675 while (fscanf(auxin, "%d %d %d", &cc, &wid, &funny) != EOF) { 676 pswidths[i][cc] = wid | (funny << 12); 677 } 678 VOIDC fclose(auxin); 679 } 680 681 #ifdef DEBUG 682 private fontprint(i) /* debugging print of font i (0,...) */ 683 int i; 684 { 685 int j, n; 686 char *p; 687 688 printf ("font %d:\n", i); 689 p = (char *) fontbase[i]; 690 n = fontbase[i]->nwfont & BMASK; 691 printf ("base=0%o, nchars=%d, spec=%d, name=%s, widtab=0%o, fitab=0%o\n", 692 p, n, fontbase[i]->specfont, 693 fontbase[i]->namefont, widthtab[i], fitab[i]); 694 printf ("widths:\n"); 695 for (j = 0; j <= n; j++) { 696 printf (" %2d", widthtab[i][j] & BMASK); 697 if (j % 20 == 19) 698 printf ("\n"); 699 } 700 printf ("\ncodetab:\n"); 701 for (j = 0; j <= n; j++) { 702 printf (" %2d", codetab[i][j] & BMASK); 703 if (j % 20 == 19) 704 printf ("\n"); 705 } 706 printf ("\nfitab:\n"); 707 for (j = 0; j <= dev.nchtab + 128 - 32; j++) { 708 printf (" %2d", fitab[i][j] & BMASK); 709 if (j % 20 == 19) 710 printf ("\n"); 711 } 712 printf ("\n"); 713 } 714 #endif 715 716 private loadfont(n, s, s1) /* load font info for font s on position n */ 717 int n; 718 char *s, *s1; 719 { 720 char temp[60]; 721 int fin, nw, norig; 722 int bcount; 723 724 if (n < 0 || n > NFONT) { 725 fprintf(stderr,"%s: illegal fp command %d %s\n", prog, n, s); 726 exit(2); 727 } 728 if (strcmp(s, fontbase[n]->namefont) == 0) return; 729 if (fontbase[n]->namefont != 0) { 730 fontdelta[n] = 1; 731 } 732 if (s1 == NULL || s1[0] == '\0') { 733 sprintf (temp, "%s/dev%s/%s.out", ditdir, devname, s); 734 } 735 else { 736 sprintf (temp, "%s/%s.out", s1, s); 737 } 738 if ((fin = open (temp, 0)) < 0) { 739 fprintf(stderr,"%s: can't open font table %s\n", prog, temp); 740 pexit(prog,2); 741 } 742 norig = fontbase[n]->nwfont & BMASK; 743 bcount = 3 * norig + nchtab + 128 - 32 + sizeof (struct font); 744 VOIDC read (fin, (char *)fontbase[n], bcount); 745 if ((fontbase[n]->nwfont & BMASK) > norig) { 746 fprintf(stderr,"%s: Font %s too big for position %d\n", prog, s, n); 747 exit(2); 748 } 749 close (fin); 750 nw = fontbase[n]->nwfont & BMASK; 751 widthtab[n] = (char *) fontbase[n] + sizeof (struct font); 752 codetab[n] = (char *) widthtab[n] + 2 * nw; 753 fitab[n] = (char *) widthtab[n] + 3 * nw; 754 t_fp (n, fontbase[n]->namefont, fontbase[n]->intname); 755 loadpswidths (n, fontbase[n]->namefont); 756 sayload (n, s, s1); 757 fontbase[n]->nwfont = norig; /* so can later use full original size */ 758 #ifdef DEBUG 759 if (fdbg > 1) 760 fontprint (n); 761 #endif 762 } 763 764 private sayload(n, s, s1) /* position n contains font s (internal s1) */ 765 int n; 766 char *s, *s1; 767 { 768 char pass[60]; 769 FILE *ptrfile; 770 char Adobefont[60]; 771 772 if (s1 == NULL || s1[0] == '\0') { 773 sprintf (pass, "%s/dev%s/%s.map", ditdir, devname, s); 774 } 775 else { 776 sprintf (pass, "%s/%s.map", s1, s); 777 } 778 779 if ((ptrfile = fopen (pass, "r")) == NULL) { 780 fprintf(stderr,"%s: can't open font map file %s\n", prog, pass); 781 pexit(prog,2); 782 } 783 784 fscanf (ptrfile, "%s", Adobefont); 785 FlushShow(0); 786 printf ("%d(%s)xf %d f\n", n, Adobefont, n); 787 font = n; 788 VOIDC fclose(ptrfile); 789 } 790 791 private VOID done() 792 { 793 if (tf == NULL) 794 exit (1); 795 t_reset ('s'); 796 exit (0); 797 } 798 799 private t_init() /* "x i" - initialize device */ 800 { 801 movepending = NONE; 802 savex = savey = 0; 803 804 t_size (10); /* start somewhere */ 805 t_slant (0); 806 setfont (1); /* set font */ 807 printf("xi\n"); 808 printf("%%%%EndProlog\n"); 809 } 810 811 private t_push() /* begin a new block */ 812 { 813 FlushShow(1);MoveTo();DoMove(); 814 if (dlevel == DSTACK) { 815 fprintf(stderr,"%s: ditroff push/pop overflow!\n",prog); 816 exit(2); 817 } 818 ditstack[dlevel].hpos = hpos; 819 ditstack[dlevel].vpos = vpos; 820 ditstack[dlevel].fontsize = fontsize; 821 ditstack[dlevel].fontheight = fontheight; 822 ditstack[dlevel].fontslant = fontslant; 823 ditstack[dlevel].font = font; 824 dlevel++; 825 printf ("\nditpush\n"); 826 } 827 828 private t_pop() /* pop to previous state */ 829 { 830 FlushShow(1);MoveTo();DoMove(); 831 if (dlevel == 0) { 832 fprintf(stderr,"%s: ditroff push/pop underflow!\n",prog); 833 exit(2); 834 } 835 dlevel--; 836 hpos = ditstack[dlevel].hpos; 837 vpos = ditstack[dlevel].vpos; 838 fontsize = ditstack[dlevel].fontsize; 839 fontheight = ditstack[dlevel].fontheight; 840 fontslant = ditstack[dlevel].fontslant; 841 font = ditstack[dlevel].font; 842 printf ("%d s %d xH %d xS %d f\n",fontsize,fontheight,fontslant,font); 843 startx = savex = hpos; 844 savey = vpos; 845 PSx = hpos * PSmag; 846 PSy = vpos * PSmag; 847 printf("%d %d MXY\n",savex,savey); 848 movepending = NONE; 849 printf("\nditpop\n"); 850 } 851 852 private t_page(n) /* do whatever new page functions */ 853 { 854 int i; 855 856 if (output) { 857 if (++scount >= spage) { 858 t_reset ('p'); 859 scount = 0; 860 } 861 } 862 output = 1; 863 FlushShow(0); 864 if (!firstpage) { 865 printf("\n%d p",n); 866 } 867 firstpage = FALSE; 868 printf ("\n%%%%Page: %d %d\n", n, ++pageno, n); 869 for (i = 0; i <= nfonts; i++) { 870 if (fontdelta[i] != 0) { 871 sayload (i, fontname[i].name, (char *) 0); 872 } 873 } 874 vpos = 0; 875 PSy = 0; 876 printf ("%d s %d xH %d xS %d f\n",fontsize,fontheight,fontslant,font); 877 if (nolist == 0) 878 return; 879 output = 0; 880 for (i = 0; i < nolist; i += 2) 881 if (n >= olist[i] && n <= olist[i + 1]) { 882 output = 1; 883 break; 884 } 885 } 886 887 private t_size(n) /* convert integer to internal size number*/ 888 int n; 889 { 890 FlushShow(1); 891 if (fontsize != n) { 892 fontsize = n; 893 printf("%d s\n",fontsize); 894 } 895 } 896 897 private t_charht(n) /* set character height to n */ 898 int n; 899 { 900 FlushShow(1); 901 if (fontheight != n) { 902 fontheight = n; 903 printf("%d xH\n",fontheight); 904 } 905 } 906 907 private t_slant(n) /* set slant to n */ 908 int n; 909 { 910 FlushShow(1); 911 if (fontslant != n) { 912 fontslant = n; 913 printf("%d xS\n",fontslant); 914 } 915 } 916 917 private t_font(s) /* convert string to internal font number */ 918 char *s; 919 { 920 int n; 921 922 n = atoi (s); 923 if (n < 0 || n > nfonts) n = 1; 924 return (n); 925 } 926 927 private t_text(s) /* print string s as text??? */ 928 char *s; 929 { 930 fprintf(stderr,"%s: ditroff t <%s> unimplemented!\n",prog,s); 931 } 932 933 private t_reset(c) 934 { 935 output = 1; /* by God */ 936 if (c == 'p') { 937 printf ("\nxp\n"); 938 } 939 else { 940 if (!stopped) 941 printf ("\nxs\n"); 942 stopped = 1; 943 } 944 fflush (tf); 945 } 946 947 private t_res(res, minh, minv) 948 int res, minh, minv; 949 { 950 resolution = res; 951 minhoriz = minh; 952 minvert = minv; 953 printf ("%d %d %d xr\n", res, minh, minv); 954 } 955 956 private t_trailer() 957 { 958 FlushShow(0); 959 printf("\n%d p",pageno); 960 printf("\n%%%%Trailer\n"); 961 printf("xt\n"); 962 } 963 964 private put1s(s) /* s is a funny char name */ 965 char *s; 966 { 967 int i; 968 969 if (!output) return; 970 debugp(("%s ", s)); 971 972 /* search for s in the funny char name table */ 973 for (i = 0; i < nchtab; i++) { 974 if (strcmp(&chname[chtab[i]], s) == 0) break; 975 } 976 977 if (i < nchtab) { 978 put1(i + 128, s); 979 } 980 else { 981 debugp(("not found ")); 982 putnf (0, s); 983 } 984 } 985 986 #define needsescape(c) ((c=='\\') || (c=='(') || (c==')')) 987 988 private put1(c, s) /* output char c */ 989 int c; 990 char *s; 991 { 992 char *pw; 993 register char *p; 994 register int i, k; 995 register int cc; 996 int ofont, code; 997 int psinfo, pswid, tw; 998 999 if (!output) return; 1000 if (c == 32) { 1001 thisw = 0; 1002 FlushShow(0); 1003 return; 1004 } 1005 if (c < 32) { 1006 debugp(("non-exist 0%o\n",c)); 1007 return; 1008 } 1009 1010 c -= 32; /* offset char code */ 1011 k = ofont = pfont = font; 1012 if (onspecial) pfont = prevfont; 1013 1014 if ((i = (fitab[pfont][c] & BMASK)) != 0) {/* char on this font */ 1015 p = codetab[pfont]; 1016 pw = widthtab[pfont]; 1017 if (onspecial) { 1018 setfont(prevfont); 1019 thisw = 0; 1020 onspecial = 0; 1021 } 1022 } 1023 else if (smnt > 0) { /* on special (we hope) */ 1024 for (k = smnt; k <= nfonts; k += 1) 1025 if ((i = (fitab[k][c] & BMASK)) != 0) { 1026 p = codetab[k]; 1027 pw = widthtab[k]; 1028 prevfont = pfont; 1029 if (onspecial && (k == specfont)) break; 1030 setfont (k); 1031 thisw = 0; 1032 onspecial = 1; 1033 specfont = k; 1034 break; 1035 } 1036 } 1037 if ((i == 0) || (k > nfonts) || ((code = p[i] & BMASK) == 0)) { 1038 debugp(("not found 0%o\n", c+32)); 1039 putnf (c + 32, s); 1040 return; 1041 } 1042 /* when we get here, 1043 * c == biased character code 1044 * k == font number 1045 * i == index into codetab and widthtab for this character 1046 * p == codetab for this font 1047 * pw == width tab for this font 1048 * code == character code for this char 1049 */ 1050 1051 cc = c + 32; 1052 debugp(((isascii(cc) && isprint(cc)) ? "%c %d\n":"%03o %d\n", 1053 cc, code)); 1054 psinfo = pswidths[font][code]; /* PS specific char info */ 1055 pswid = psinfo & PSWID; /* PS character width */ 1056 thisw = pw[i] & BMASK; /* troff char width */ 1057 tw = thisw = (thisw * fontsize + dev.unitwidth/2) / dev.unitwidth; 1058 1059 if ((psinfo & ISPSPROC) && (psinfo != -1)) { 1060 /* character is implemented by a PostScript proc */ 1061 showspecial(s, code, pswid); 1062 if (pswid > 0) { 1063 PSx += PSscale(pswid * fontsize * dres); 1064 } 1065 thisw = 0; 1066 } 1067 else { 1068 showchar(code); 1069 if (pswid > 0) { 1070 PSshowlen += PSscale(pswid * fontsize * dres); 1071 } 1072 } 1073 1074 /* 1075 if (font != ofont) { 1076 setfont(ofont); 1077 startx = hpos + tw; 1078 thisw = 0; 1079 lastcmd = FNT; 1080 } 1081 */ 1082 debugp(("...width (%d)\n", pw[i]&BMASK)); 1083 } 1084 1085 1086 private putnf(c, s) /* note that a character wasnt found */ 1087 int c; 1088 char *s; 1089 { 1090 1091 FlushShow(0); 1092 thisw = 0; 1093 if ((s == NULL) || (*s == '\0')) printf("(\%3o)cb\n", c); 1094 else if ((strcmp(s, "\\|") == 0) || (strcmp(s, "\\^") == 0) 1095 || (strcmp (s, "\\&") == 0)) 1096 return; 1097 else 1098 printf("(%s)cb\n", s); 1099 } 1100 1101 1102 private t_fp(n, s, si) /* font position n now contains font s, intname si */ 1103 int n; /* position */ 1104 char *s; /* font (ditname) */ 1105 char *si; /* font (intname = number) */ 1106 { 1107 fontname[n].name = s; 1108 fontname[n].number = atoi (si); 1109 } 1110 1111 private setfont(n) /* set font to n */ 1112 int n; 1113 { 1114 FlushShow(1); 1115 1116 if (n < 0 || n > NFONT) { 1117 fprintf(stderr,"%s: illegal font %d\n", prog,n); 1118 } 1119 if (font != n) { 1120 font = n; 1121 printf("%d f\n",font); 1122 } 1123 onspecial = 0; 1124 } 1125 1126 private drawline(dx, dy) /* draw line from here to dx, dy */ 1127 int dx, dy; 1128 { 1129 FlushShow(0); MoveTo(); DoMove(); 1130 printf("%d %d Dl\n", dx, dy); 1131 hpos += dx; 1132 PSx = hpos * PSmag; 1133 vpos += dy; 1134 PSy = vpos * PSmag; 1135 } 1136 1137 private drawwig(s) /* draw wiggly line */ 1138 char *s; 1139 { 1140 FlushShow(0); MoveTo(); DoMove(); 1141 printf("D~ %s D~~\n",s); 1142 } 1143 1144 private drawcirc(d) 1145 int d; 1146 { 1147 FlushShow(0); MoveTo(); DoMove(); 1148 printf("%d Dc\n",d); 1149 } 1150 1151 private drawarc(dx1, dy1, dx2, dy2) 1152 int dx1, dy1, dx2, dy2; 1153 { 1154 FlushShow(0); MoveTo(); DoMove(); 1155 printf("%d %d %d %d Da\n", dx1, dy1, dx2, dy2); 1156 hpos += dx1 + dx2; 1157 PSx = hpos * PSmag; 1158 vpos += dy1 + dy2; 1159 PSy = vpos * PSmag; 1160 } 1161 1162 private drawellip(a, b) 1163 int a, b; 1164 { 1165 FlushShow(0);MoveTo();DoMove(); 1166 printf("%d %d De\n",a,b); 1167 } 1168 1169 private hmot(a) /* relative horizontal motion */ 1170 int a; 1171 { 1172 register int aa; 1173 aa = abs(a); 1174 if ((aa < 8) || (aa > (10 * thisw)) || (a >= 100) 1175 || ((thisw != 0) && (abs(thisw - a) > 4))) { 1176 FlushShow(1); 1177 } 1178 hpos += a; 1179 if (lastcmd != CPUT) startx = hpos; 1180 } 1181 1182 private hgoto(a) /* absolute horizontal motion */ 1183 int a; 1184 { 1185 FlushShow(1); 1186 startx = hpos = a; 1187 thisw = 0; 1188 } 1189 1190 private vmot(a) /* relative vertical motion */ 1191 int a; 1192 { 1193 FlushShow(1); 1194 vpos += a; 1195 thisw = 0; 1196 } 1197 1198 private vgoto(a) /* absolute vertical motion */ 1199 int a; 1200 { 1201 FlushShow(1); 1202 vpos = a; 1203 thisw = 0; 1204 } 1205 1206 private showspecial(s,cc,wid) 1207 char *s; 1208 int cc; 1209 int wid; 1210 { 1211 char *sp; 1212 1213 FlushShow(0); 1214 MoveTo(); 1215 DoMove(); 1216 putchar('('); 1217 for (sp = s; *sp != '\0'; sp++) { 1218 if (needsescape(*sp)) { 1219 putchar('\\'); 1220 } 1221 putchar(*sp); 1222 } 1223 printf(")%d %d oc\n",cc,wid); 1224 } 1225 1226 private showchar(c) 1227 int c; 1228 { 1229 if (showind == 0) {MoveTo();} 1230 else if ((vpos * PSmag) != PSy) { 1231 FlushShow(0); 1232 MoveTo(); 1233 } 1234 if (showind >= SHOWSIZE) FlushShow(0); 1235 if (isascii(c) && isprint(c)) { 1236 switch (c) { 1237 case '\\': case '(': case ')': 1238 showbuf[showind++] = '\\'; 1239 /* fall through */ 1240 1241 default: 1242 showbuf[showind++] = c; 1243 } 1244 } 1245 else { 1246 showbuf[showind++] = '\\'; 1247 showbuf[showind++] = ((c>>6)&03) + '0'; 1248 showbuf[showind++] = ((c>>3)&07) + '0'; 1249 showbuf[showind++] = (c&07) + '0'; 1250 } 1251 showbuf[showind] = '\0'; 1252 nshow++; 1253 } 1254 1255 private MoveTo() { 1256 int x, y; 1257 x = hpos * PSmag; 1258 y = vpos * PSmag; 1259 1260 if (x != PSx) { 1261 startx = savex = hpos; 1262 PSx = x; 1263 movepending |= XMOVE; 1264 } 1265 if (y != PSy) { 1266 savey = vpos; 1267 PSy = y; 1268 movepending |= YMOVE; 1269 } 1270 } 1271 1272 private FlushMove() { 1273 switch (movepending) { 1274 case NONE: 1275 break; 1276 case XMOVE: 1277 printf("%d",savex); 1278 break; 1279 case YMOVE: 1280 printf("%d",savey); 1281 break; 1282 case XYMOVE: 1283 printf("%d %d",savex,savey); 1284 break; 1285 default: 1286 fprintf(stderr,"%s: invalid move code %d\n",prog, movepending); 1287 exit(2); 1288 } 1289 } 1290 1291 private char *movecmds[] = { 1292 "MX","MY","MXY" 1293 }; 1294 1295 private DoMove() { 1296 FlushMove(); 1297 if (movepending != NONE) { 1298 printf(" %s\n",movecmds[movepending-1]); 1299 movepending = NONE; 1300 } 1301 } 1302 1303 private char showops[] = "SXYN"; 1304 1305 private FlushShow(t) int t; { 1306 long err, tlen; 1307 float cerror; 1308 1309 if (showind == 0) {thisw = 0; return;} 1310 if (movepending != NONE) { 1311 FlushMove(); 1312 } 1313 tlen = hpos - startx; 1314 if (lastcmd == CPUT) tlen += thisw; 1315 err = tlen * PSmag - PSshowlen; 1316 if ((nshow != 1) && (abs(err) > ErrorTolerance)) { 1317 cerror = ((float) err) / ((nshow - 1) * PSmag); 1318 #ifdef DEBUG 1319 fprintf(stderr,"F%d lc %d thisw %d ",t,lastcmd,thisw); 1320 fprintf(stderr,"x %ld h %ld tn %ld %ld ", 1321 startx, hpos, tlen*PSmag,PSshowlen); 1322 fprintf(stderr,"error %d %.4f %s\n",nshow,cerror,showbuf); 1323 fflush(stderr); 1324 #endif 1325 printf(" %.4f(%s)A%c\n", cerror, showbuf, showops[movepending]); 1326 } 1327 else { 1328 printf("(%s)%c\n", showbuf, showops[movepending]); 1329 } 1330 1331 showind = 0; 1332 nshow = 0; 1333 showbuf[showind] = '\0'; 1334 PSx += PSshowlen; 1335 PSshowlen = 0; 1336 startx = hpos; 1337 if (lastcmd == CPUT) startx += thisw; 1338 thisw = 0; 1339 movepending = NONE; 1340 } 1341